home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume24 / mkid2 / part02 / paths.c < prev    next >
C/C++ Source or Header  |  1991-10-09  |  5KB  |  221 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 *rootName();
  10. char *spanPath();
  11. char *suffName();
  12. void cannoname();
  13.  
  14. /* relPath takes two arguments:
  15.  * 1) an absolute path name for a directory.
  16.  *    (This name MUST have a trailing /).
  17.  * 2) an absolute path name for a file.
  18.  *
  19.  * It looks for common components at the front of the file and
  20.  * directory names and generates a relative path name for the file
  21.  * (relative to the specified directory).
  22.  *
  23.  * This may result in a huge number of ../s if the names
  24.  * have no components in common.
  25.  *
  26.  * The output from this concatenated with the input directory name
  27.  * and run through spanPath should result in the original input
  28.  * absolute path name of the file.
  29.  *
  30.  * Examples:
  31.  *  dir      arg                  return value
  32.  *  /x/y/z/  /x/y/q/file      ->  ../q/file
  33.  *  /x/y/z/  /q/t/p/file      ->  ../../../q/t/p/file
  34.  *  /x/y/z/  /x/y/z/file      ->  file
  35.  */
  36. char *
  37. relPath(dir, arg)
  38.     char        *dir;
  39.     char        *arg;
  40. {
  41.     char *        a;
  42.     char *        d;
  43.     char *        lasta;
  44.     char *        lastd;
  45.     static char    pathBuf[BUFSIZ];
  46.  
  47.     lasta = a = arg;
  48.     lastd = d = dir;
  49.     while (*a == *d) {
  50.        if (*a == '/') {
  51.           lasta = a;
  52.           lastd = d;
  53.        }
  54.        ++a;
  55.        ++d;
  56.     }
  57.     /* lasta and lastd now point to the last / in each
  58.      * file name where the leading file components were
  59.      * identical.
  60.      */
  61.     ++lasta;
  62.     ++lastd;
  63.     /* copy a ../ into the buffer for each component of
  64.      * the directory that remains.
  65.      */
  66.     d = pathBuf;
  67.     while (*lastd != '\0') {
  68.         if (*lastd == '/') {
  69.             strcpy(d, "../");
  70.             d += 3;
  71.         }
  72.         ++lastd;
  73.     }
  74.     /* now tack on remainder of arg */
  75.     strcpy(d, lasta);
  76.     return(pathBuf);
  77. }
  78.  
  79. /* spanPath accepts a directory name and a file name and returns
  80.  * a cannonical form of the full file name within that directory.
  81.  * It gets rid of ./ and things like that.
  82.  *
  83.  * If the file is an absolute name then the directory is ignored.
  84.  */
  85. char *
  86. spanPath(dir, arg)
  87.     char        *dir;
  88.     char        *arg;
  89. {
  90.     char *          argptr;
  91.     static char    pathBuf[BUFSIZ];
  92.  
  93.     /* reduce directory to cannonical form */
  94.     strcpy(pathBuf, dir);
  95.     cannoname(pathBuf);
  96.     /* tack the obilgatory / on the end */
  97.     strcat(pathBuf, "/");
  98.     /* stick file name in buffer after directory */
  99.     argptr = pathBuf + strlen(pathBuf);
  100.     strcpy(argptr, arg);
  101.     /* and reduce it to cannonical form also */
  102.     cannoname(argptr);
  103.     /* If it is an absolute name, just return it */
  104.     if (*argptr == '/') return(argptr);
  105.     /* otherwise, combine the names to cannonical form */
  106.     cannoname(pathBuf);
  107.     return(pathBuf);
  108. }
  109.  
  110. /* rootName returns the base name of the file with any leading
  111.  * directory information or trailing suffix stripped off. Examples:
  112.  *
  113.  *   /usr/include/stdio.h   ->   stdio
  114.  *   fred                   ->   fred
  115.  *   barney.c               ->   barney
  116.  *   bill/bob               ->   bob
  117.  *   /                      ->   < null string >
  118.  */
  119. char *
  120. rootName(path)
  121.     char        *path;
  122. {
  123.     static char    pathBuf[BUFSIZ];
  124.     char        *root;
  125.     char        *dot;
  126.  
  127.     if ((root = strrchr(path, '/')) == NULL)
  128.         root = path;
  129.     else
  130.         root++;
  131.     
  132.     if ((dot = strrchr(root, '.')) == NULL)
  133.         strcpy(pathBuf, root);
  134.     else {
  135.         strncpy(pathBuf, root, dot - root);
  136.         pathBuf[dot - root] = '\0';
  137.     }
  138.     return pathBuf;
  139. }
  140.  
  141. /* suffName returns the suffix (including the dot) or a null string
  142.  * if there is no suffix. Examples:
  143.  *
  144.  *   /usr/include/stdio.h   ->   .h
  145.  *   fred                   ->   < null string >
  146.  *   barney.c               ->   .c
  147.  *   bill/bob               ->   < null string >
  148.  *   /                      ->   < null string >
  149.  */
  150. char *
  151. suffName(path)
  152.     char        *path;
  153. {
  154.     char        *dot;
  155.  
  156.     if ((dot = strrchr(path, '.')) == NULL)
  157.         return "";
  158.     return dot;
  159. }
  160.  
  161. bool
  162. canCrunch(path1, path2)
  163.     char        *path1;
  164.     char        *path2;
  165. {
  166.     char        *slash1;
  167.     char        *slash2;
  168.  
  169.     slash1 = strrchr(path1, '/');
  170.     slash2 = strrchr(path2, '/');
  171.  
  172.     if (slash1 == NULL && slash2 == NULL)
  173.         return strequ(suffName(path1), suffName(path2));
  174.     if ((slash1 - path1) != (slash2 - path2))
  175.         return FALSE;
  176.     if (!strnequ(path1, path2, slash1 - path1))
  177.         return FALSE;
  178.     return strequ(suffName(slash1), suffName(slash2));
  179. }
  180. #include    <sys/types.h>
  181. #include    <sys/stat.h>
  182.  
  183. /* LookUp adds ../s to the beginning of a file name until it finds
  184.  * the one that really exists. Returns NULL if it gets all the way
  185.  * to / and never finds it.
  186.  *
  187.  * If the file name starts with /, just return it as is.
  188.  *
  189.  * This routine is used to locate the ID database file.
  190.  */
  191. char *
  192. LookUp(arg)
  193.     char *        arg;
  194. {
  195.     char *        p;
  196.     static char    pathBuf[BUFSIZ];
  197.     struct stat    rootb;
  198.     struct stat    statb;
  199.  
  200.     /* if we got absolute name, just use it. */
  201.     if (arg[0] == '/') return(arg);
  202.     /* if the name we were give exists, don't bother searching */
  203.     if (stat(arg, &statb) == 0) return(arg);
  204.     /* search up the tree until we find a directory where this
  205.      * relative file name is visible.
  206.      * (or we run out of tree to search by hitting root).
  207.      */
  208.     p = pathBuf;
  209.     if (stat("/", &rootb) != 0) return(NULL);
  210.     do {
  211.         strcpy(p, "../");
  212.         p += 3;
  213.         strcpy(p, arg);
  214.         if (stat(pathBuf, &statb) == 0) return(pathBuf);
  215.         *p = '\0';
  216.         if (stat(pathBuf, &statb) != 0) return(NULL);
  217.     } while (! ((statb.st_ino == rootb.st_ino) ||
  218.                     (statb.st_dev == rootb.st_dev)));
  219.     return(NULL);
  220. }
  221.