home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume11 / id / part03 / paths.c < prev    next >
C/C++ Source or Header  |  1987-09-25  |  4KB  |  194 lines

  1. /* Copyright (c) 1986, Greg McGary */
  2. static char sccsid[] = "@(#)paths.c    1.1 86/10/09";
  3.  
  4. #include    <bool.h>
  5. #include    <stdio.h>
  6. #include    <string.h>
  7.  
  8. bool canCrunch();
  9. char *getDirToName();
  10. char *rootName();
  11. char *skipJunk();
  12. char *spanPath();
  13. char *suffName();
  14.  
  15. char *
  16. spanPath(dir, arg)
  17.     char        *dir;
  18.     char        *arg;
  19. {
  20.     static char    pathBuf[BUFSIZ];
  21.     char        *path;
  22.     char        *argTail;
  23.     char        *dirTail;
  24.     int        argLength;
  25.     int        dirLength;
  26.  
  27.     for (dirTail = &dir[strlen(dir)-1]; *dirTail == '/'; dirTail--)
  28.         *dirTail = '\0';
  29.     for (;;) {
  30.         dir = skipJunk(dir);
  31.         if ((dirTail = strchr(dir, '/')) == NULL)
  32.             dirTail = &dir[strlen(dir)];
  33.         dirLength = dirTail - dir;
  34.  
  35.         arg = skipJunk(arg);
  36.         if ((argTail = strchr(arg, '/')) == NULL)
  37.             break;
  38.         argLength = argTail - arg;
  39.  
  40.         if (argLength != dirLength)
  41.             break;
  42.         if (!strnequ(arg, dir, argLength))
  43.             break;
  44.         arg = argTail;
  45.         dir = dirTail;
  46.     }
  47.  
  48.     (path = pathBuf)[0] = '\0';
  49.     for (; dir && *dir; dir = skipJunk(strchr(dir, '/'))) {
  50.         strcpy(path, "../");
  51.         path += 3;
  52.     }
  53.     strcat(path, arg);
  54.     return pathBuf;
  55. }
  56.  
  57. char *
  58. skipJunk(path)
  59.     char        *path;
  60. {
  61.     if (path == NULL)
  62.         return NULL;
  63.     while (*path == '/')
  64.         path++;
  65.     while (path[0] == '.' && path[1] == '/') {
  66.         path += 2;
  67.         while (*path == '/')
  68.             path++;
  69.     }
  70.     if (strequ(path, "."))
  71.         path++;
  72.     
  73.     return path;
  74. }
  75.  
  76. char *
  77. rootName(path)
  78.     char        *path;
  79. {
  80.     static char    pathBuf[BUFSIZ];
  81.     char        *root;
  82.     char        *dot;
  83.  
  84.     if ((root = strrchr(path, '/')) == NULL)
  85.         root = path;
  86.     else
  87.         root++;
  88.     
  89.     if ((dot = strrchr(root, '.')) == NULL)
  90.         strcpy(pathBuf, root);
  91.     else {
  92.         strncpy(pathBuf, root, dot - root);
  93.         pathBuf[dot - root] = '\0';
  94.     }
  95.     return pathBuf;
  96. }
  97.  
  98. char *
  99. suffName(path)
  100.     char        *path;
  101. {
  102.     char        *dot;
  103.  
  104.     if ((dot = strrchr(path, '.')) == NULL)
  105.         return "";
  106.     return dot;
  107. }
  108.  
  109. bool
  110. canCrunch(path1, path2)
  111.     char        *path1;
  112.     char        *path2;
  113. {
  114.     char        *slash1;
  115.     char        *slash2;
  116.  
  117.     slash1 = strrchr(path1, '/');
  118.     slash2 = strrchr(path2, '/');
  119.  
  120.     if (slash1 == NULL && slash2 == NULL)
  121.         return strequ(suffName(path1), suffName(path2));
  122.     if ((slash1 - path1) != (slash2 - path2))
  123.         return FALSE;
  124.     if (!strnequ(path1, path2, slash1 - path1))
  125.         return FALSE;
  126.     return strequ(suffName(slash1), suffName(slash2));
  127. }
  128. #include    <sys/types.h>
  129. #include    <sys/stat.h>
  130. #ifdef NDIR
  131. #include    <ndir.h>
  132. #else
  133. #include    <sys/dir.h>
  134. #endif
  135.  
  136. static char    dot[]     = ".";
  137. static char    dotdot[] = "..";
  138.  
  139. /*
  140.     Return our directory name relative to the first parent dir
  141.     that contains a file with a name that matches `topName'.
  142.     Fail if we hit the root, or if any dir in our way is unreadable.
  143. */
  144. char *
  145. getDirToName(topName)
  146.     char        *topName;
  147. {
  148.     register struct direct    *dirp;
  149.     register DIR    *dirdp;
  150.     static char    nameBuf[BUFSIZ];
  151.     char        *name;
  152.     struct    stat    dStat;
  153.     struct    stat    ddStat;
  154.  
  155.     name = &nameBuf[sizeof(nameBuf)-1];
  156.     *name = '\0';
  157.     for (;;) {
  158.         if (stat(topName, &dStat) == 0) {
  159.             if (!*name)
  160.                 name = dot;
  161.             else
  162.                 chdir(name);
  163.             return name;
  164.         } if (stat(dot, &dStat) < 0)
  165.             return NULL;
  166.         if ((dirdp = opendir(dotdot)) == NULL)
  167.             return NULL;
  168.         if (fstat(dirdp->dd_fd, &ddStat) < 0)
  169.             return NULL;
  170.         if (chdir(dotdot) < 0)
  171.             return NULL;
  172.         if (dStat.st_dev == ddStat.st_dev) {
  173.             if (dStat.st_ino == ddStat.st_ino)
  174.                 return NULL;
  175.             do {
  176.                 if ((dirp = readdir(dirdp)) == NULL)
  177.                     return NULL;
  178.             } while (dirp->d_ino != dStat.st_ino);
  179.         } else {
  180.             do {
  181.                 if ((dirp = readdir(dirdp)) == NULL)
  182.                     return NULL;
  183.                 stat(dirp->d_name, &ddStat);
  184.             } while (ddStat.st_ino != dStat.st_ino || ddStat.st_dev != dStat.st_dev);
  185.         }
  186.         closedir(dirdp);
  187.     
  188.         if (*name != '\0')
  189.             *--name = '/';
  190.         name -= dirp->d_namlen;
  191.         strncpy(name, dirp->d_name, dirp->d_namlen);
  192.     }
  193. }
  194.