home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / gnustuff / tos / gnulib / libsrc98.zoo / symlink.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-11-05  |  2.8 KB  |  141 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <errno.h>
  4. #include <string.h>
  5. #include <types.h>
  6. #include <stat.h>
  7. #include <assert.h>
  8. #include <unistd.h>
  9. #include "symdir.h"
  10.  
  11. /*
  12.  * make a symbolic link named 'new' to the file named 'old'
  13.  */
  14.  
  15. int
  16. symlink(old, new)
  17.     const char *old, *new;
  18. {
  19.     char linkpath[FILENAME_MAX];
  20.     char *name;
  21.     SYMDIR *dir;
  22.     SYMENTRY *d;
  23.     char *s;
  24.     int r, save_errno;
  25.  
  26. /* Problem: to TOS, "Makefile", "Makefile", and "makefilefoo" are all
  27.  * identical. Fortunately, _unx2dos can distinguish them, and
  28.  * returns _NM_CHANGE for names that are not "canonical" (_NM_OK
  29.  * means a normal file, _NM_LINK means an existing symbolic link).
  30.  * So if _unx2dos returns _NM_OK, and access finds the file, then
  31.  * it already exists; if _unx2dos returns _NM_LINK, the file already
  32.  * exists as a symbolic link (access would work in this case, but
  33.  * is redundant).
  34.  */
  35.  
  36.         save_errno = errno;
  37.     r = _unx2dos(new, linkpath);
  38.     if ((r == _NM_LINK) || (r == _NM_OK) && !access(new, 0)) {
  39.         errno = EEXIST;
  40.         return -1;
  41.     }
  42.     errno = save_errno;
  43.  
  44. /*
  45.  * find the name (from the original path in "new"), and the canonical form
  46.  * of the path to it (from what _unx2dos just gave us)
  47.  */
  48.  
  49.     name = new;
  50.     for (s = new; *s; s++) {
  51.         if (*s == '\\' || (_tSLASH && *s == '/'))
  52.             name = s+1;
  53.     }
  54.     if ((s = strrchr(linkpath, '\\'))) {
  55.         *s = 0;
  56.     }
  57. /*
  58.  * now get the directory information
  59.  */
  60.     dir = _read_symdir(linkpath);
  61.     if (!dir) {
  62.         /* errno was already set */
  63.         return -1;
  64.     }
  65.  
  66.     d = (SYMENTRY *)
  67.         malloc(sizeof(SYMENTRY)+strlen(old)+strlen(name)+2);
  68.     if (d == 0) {
  69.         errno = ENOMEM;
  70.         return -1;
  71.         _free_symdir(dir);
  72.     }
  73.     strcpy(d->linkname, name);
  74.     for (s = d->linkname; *s; s++)
  75.         ;
  76.     d->flags = 0;
  77.     d->cflags = s;    /* an empty string */
  78.     ++s;
  79.     d->linkto = s;
  80.     strcpy(s, old);
  81.     d->next = dir->s_dir;
  82.     dir->s_dir = d;
  83.     r = _write_symdir(linkpath, dir);
  84.     _free_symdir(dir);
  85.     if (r) {
  86.         errno = -r;
  87.         return -1;
  88.     }
  89.     return 0;
  90. }
  91.  
  92. /*
  93.  * read a symbolic link
  94.  */
  95.  
  96. int
  97. readlink(filename, linkto, siz)
  98.     char *filename, *linkto;
  99.     int siz;
  100. {
  101.     char tmp[FILENAME_MAX], linkpath[FILENAME_MAX], *s, *lastslash = 0;
  102.     SYMDIR *dir;
  103.     SYMENTRY *ent;
  104.         size_t len;
  105.  
  106.     strcpy(tmp, filename);
  107.     for (s = tmp; *s; s++) {
  108.         if (*s == '\\' || (_tSLASH && (*s == '/')))
  109.             lastslash = s;
  110.     }
  111.         if (lastslash==tmp) {
  112.             lastslash++;
  113.             _unx2dos("/",linkpath);
  114.         } else if (lastslash) {
  115.         *lastslash++ = 0;
  116.         _unx2dos(tmp, linkpath);
  117.     }
  118.     else {
  119.         lastslash = tmp;
  120.         _unx2dos(".", linkpath);
  121.     }
  122.     if (!(dir = _read_symdir(linkpath))) {
  123.         errno = EPATH;
  124.         return -1;
  125.     }
  126.     if (!(ent = _symdir_lookup(dir, lastslash))) {
  127.         _free_symdir(dir);
  128.         errno = ENOENT;
  129.         return -1;
  130.     }
  131.     strncpy(linkto, ent->linkto, siz);
  132.  
  133.         /* must get length right */
  134.         len=strlen(ent->linkto);
  135.         if (len>siz) {
  136.            len=siz;
  137.         }
  138.     _free_symdir(dir);
  139.     return len;
  140. }
  141.