home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include <stdlib.h>
- #include <errno.h>
- #include <string.h>
- #include <types.h>
- #include <stat.h>
- #include <assert.h>
- #include <unistd.h>
- #include "symdir.h"
-
- /*
- * make a symbolic link named 'new' to the file named 'old'
- */
-
- int
- symlink(old, new)
- const char *old, *new;
- {
- char linkpath[FILENAME_MAX];
- char *name;
- SYMDIR *dir;
- SYMENTRY *d;
- char *s;
- int r, save_errno;
-
- /* Problem: to TOS, "Makefile", "Makefile", and "makefilefoo" are all
- * identical. Fortunately, _unx2dos can distinguish them, and
- * returns _NM_CHANGE for names that are not "canonical" (_NM_OK
- * means a normal file, _NM_LINK means an existing symbolic link).
- * So if _unx2dos returns _NM_OK, and access finds the file, then
- * it already exists; if _unx2dos returns _NM_LINK, the file already
- * exists as a symbolic link (access would work in this case, but
- * is redundant).
- */
-
- save_errno = errno;
- r = _unx2dos(new, linkpath);
- if ((r == _NM_LINK) || (r == _NM_OK) && !access(new, 0)) {
- errno = EEXIST;
- return -1;
- }
- errno = save_errno;
-
- /*
- * find the name (from the original path in "new"), and the canonical form
- * of the path to it (from what _unx2dos just gave us)
- */
-
- name = new;
- for (s = new; *s; s++) {
- if (*s == '\\' || (_tSLASH && *s == '/'))
- name = s+1;
- }
- if ((s = strrchr(linkpath, '\\'))) {
- *s = 0;
- }
- /*
- * now get the directory information
- */
- dir = _read_symdir(linkpath);
- if (!dir) {
- /* errno was already set */
- return -1;
- }
-
- d = (SYMENTRY *)
- malloc(sizeof(SYMENTRY)+strlen(old)+strlen(name)+2);
- if (d == 0) {
- errno = ENOMEM;
- return -1;
- _free_symdir(dir);
- }
- strcpy(d->linkname, name);
- for (s = d->linkname; *s; s++)
- ;
- d->flags = 0;
- d->cflags = s; /* an empty string */
- ++s;
- d->linkto = s;
- strcpy(s, old);
- d->next = dir->s_dir;
- dir->s_dir = d;
- r = _write_symdir(linkpath, dir);
- _free_symdir(dir);
- if (r) {
- errno = -r;
- return -1;
- }
- return 0;
- }
-
- /*
- * read a symbolic link
- */
-
- int
- readlink(filename, linkto, siz)
- char *filename, *linkto;
- int siz;
- {
- char tmp[FILENAME_MAX], linkpath[FILENAME_MAX], *s, *lastslash = 0;
- SYMDIR *dir;
- SYMENTRY *ent;
- size_t len;
-
- strcpy(tmp, filename);
- for (s = tmp; *s; s++) {
- if (*s == '\\' || (_tSLASH && (*s == '/')))
- lastslash = s;
- }
- if (lastslash==tmp) {
- lastslash++;
- _unx2dos("/",linkpath);
- } else if (lastslash) {
- *lastslash++ = 0;
- _unx2dos(tmp, linkpath);
- }
- else {
- lastslash = tmp;
- _unx2dos(".", linkpath);
- }
- if (!(dir = _read_symdir(linkpath))) {
- errno = EPATH;
- return -1;
- }
- if (!(ent = _symdir_lookup(dir, lastslash))) {
- _free_symdir(dir);
- errno = ENOENT;
- return -1;
- }
- strncpy(linkto, ent->linkto, siz);
-
- /* must get length right */
- len=strlen(ent->linkto);
- if (len>siz) {
- len=siz;
- }
- _free_symdir(dir);
- return len;
- }
-