home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume24 / mkid2 / part02 / unsymlink.c < prev   
C/C++ Source or Header  |  1991-10-09  |  3KB  |  86 lines

  1. #include <string.h>
  2. #include <sys/param.h>
  3. #include <sys/stat.h>
  4.  
  5. extern void cannoname();
  6.  
  7. /* unsymlink is a routine that resolves all symbolic links in
  8.  * a file name, transforming a name to the "actual" file name
  9.  * instead of the name in terms of symbolic links.
  10.  *
  11.  * If it can resolve all links and discover an actual file
  12.  * it returns a pointer to its argument string and transforms
  13.  * the argument in place to the actual name.
  14.  *
  15.  * If no such actual file exists, or for some reason the links
  16.  * cannot be resolved, it returns a NULL pointer and leaves the
  17.  * name alone.
  18.  */
  19. char *
  20. unsymlink(n)
  21.    char *    n;
  22. {
  23.    char          newname[MAXPATHLEN];
  24.    char          partname[MAXPATHLEN];
  25.    char          linkname[MAXPATHLEN];
  26.    char *        s;
  27.    char *        d;
  28.    char *        lastcomp;
  29.    int           linksize;
  30.    struct stat   statb;
  31.  
  32.    /* Just stat the file to automagically do all the symbolic
  33.     * link verification checks and make sure we have access to
  34.     * directories, etc.
  35.     */
  36.    if (stat(n, &statb) != 0) return(NULL) ;
  37.    strcpy(newname, n);
  38.    /* Now loop, lstating each component to see if it is a symbolic
  39.     * link. For symbolic link components, use readlink() to get
  40.     * the real name, put the read link name in place of the
  41.     * last component, and start again.
  42.     */
  43.    cannoname(newname) ;
  44.    s = &newname[0] ;
  45.    d = &partname[0] ;
  46.    if (*s == '/') {
  47.       *d++ = *s++ ;
  48.    }
  49.    lastcomp = d ;
  50.    for ( ; ; ) {
  51.       if ((*s == '/') || (*s == '\0')) {
  52.          /* we have a complete component name in partname, check it out */
  53.          *d = '\0' ;
  54.          if (lstat(partname, &statb) != 0) return(NULL) ;
  55.          if ((statb.st_mode & S_IFMT) == S_IFLNK) {
  56.             /* This much of name is a symbolic link, do a readlink
  57.              * and tack the bits and pieces together
  58.              */
  59.             linksize = readlink(partname, linkname, MAXPATHLEN) ;
  60.             if (linksize < 0) return(NULL) ;
  61.             linkname[linksize] = '\0' ;
  62.             strcpy(lastcomp, linkname) ;
  63.             lastcomp += linksize ;
  64.             strcpy(lastcomp, s) ;
  65.             strcpy(newname, partname) ;
  66.             cannoname(newname) ;
  67.             s = &newname[0] ;
  68.             d = &partname[0] ;
  69.             if (*s == '/') {
  70.                *d++ = *s++ ;
  71.             }
  72.             lastcomp = d ;
  73.          } else {
  74.             /* Not a symlink, just keep scanning to next component */
  75.             if (*s == '\0') break ;
  76.             *d++ = *s++ ;
  77.             lastcomp = d ;
  78.          }
  79.       } else {
  80.          *d++ = *s++ ;
  81.       }
  82.    }
  83.    strcpy(n, newname) ;
  84.    return(n) ;
  85. }
  86.