home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Tools / mkid / paths.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-03  |  3.9 KB  |  213 lines

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