home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (c) 1986, Greg McGary */
- static char sccsid[] = "@(#)paths.c 1.1 86/10/09";
-
- #include <bool.h>
- #include <stdio.h>
- #include <string.h>
-
- bool canCrunch();
- char *rootName();
- char *spanPath();
- char *suffName();
- void cannoname();
-
- /* relPath takes two arguments:
- * 1) an absolute path name for a directory.
- * (This name MUST have a trailing /).
- * 2) an absolute path name for a file.
- *
- * It looks for common components at the front of the file and
- * directory names and generates a relative path name for the file
- * (relative to the specified directory).
- *
- * This may result in a huge number of ../s if the names
- * have no components in common.
- *
- * The output from this concatenated with the input directory name
- * and run through spanPath should result in the original input
- * absolute path name of the file.
- *
- * Examples:
- * dir arg return value
- * /x/y/z/ /x/y/q/file -> ../q/file
- * /x/y/z/ /q/t/p/file -> ../../../q/t/p/file
- * /x/y/z/ /x/y/z/file -> file
- */
- char *
- relPath(dir, arg)
- char *dir;
- char *arg;
- {
- char * a;
- char * d;
- char * lasta;
- char * lastd;
- static char pathBuf[BUFSIZ];
-
- lasta = a = arg;
- lastd = d = dir;
- while (*a == *d) {
- if (*a == '/') {
- lasta = a;
- lastd = d;
- }
- ++a;
- ++d;
- }
- /* lasta and lastd now point to the last / in each
- * file name where the leading file components were
- * identical.
- */
- ++lasta;
- ++lastd;
- /* copy a ../ into the buffer for each component of
- * the directory that remains.
- */
- d = pathBuf;
- while (*lastd != '\0') {
- if (*lastd == '/') {
- strcpy(d, "../");
- d += 3;
- }
- ++lastd;
- }
- /* now tack on remainder of arg */
- strcpy(d, lasta);
- return(pathBuf);
- }
-
- /* spanPath accepts a directory name and a file name and returns
- * a cannonical form of the full file name within that directory.
- * It gets rid of ./ and things like that.
- *
- * If the file is an absolute name then the directory is ignored.
- */
- char *
- spanPath(dir, arg)
- char *dir;
- char *arg;
- {
- char * argptr;
- static char pathBuf[BUFSIZ];
-
- /* reduce directory to cannonical form */
- strcpy(pathBuf, dir);
- cannoname(pathBuf);
- /* tack the obilgatory / on the end */
- strcat(pathBuf, "/");
- /* stick file name in buffer after directory */
- argptr = pathBuf + strlen(pathBuf);
- strcpy(argptr, arg);
- /* and reduce it to cannonical form also */
- cannoname(argptr);
- /* If it is an absolute name, just return it */
- if (*argptr == '/') return(argptr);
- /* otherwise, combine the names to cannonical form */
- cannoname(pathBuf);
- return(pathBuf);
- }
-
- /* rootName returns the base name of the file with any leading
- * directory information or trailing suffix stripped off. Examples:
- *
- * /usr/include/stdio.h -> stdio
- * fred -> fred
- * barney.c -> barney
- * bill/bob -> bob
- * / -> < null string >
- */
- char *
- rootName(path)
- char *path;
- {
- static char pathBuf[BUFSIZ];
- char *root;
- char *dot;
-
- if ((root = strrchr(path, '/')) == NULL)
- root = path;
- else
- root++;
-
- if ((dot = strrchr(root, '.')) == NULL)
- strcpy(pathBuf, root);
- else {
- strncpy(pathBuf, root, dot - root);
- pathBuf[dot - root] = '\0';
- }
- return pathBuf;
- }
-
- /* suffName returns the suffix (including the dot) or a null string
- * if there is no suffix. Examples:
- *
- * /usr/include/stdio.h -> .h
- * fred -> < null string >
- * barney.c -> .c
- * bill/bob -> < null string >
- * / -> < null string >
- */
- char *
- suffName(path)
- char *path;
- {
- char *dot;
-
- if ((dot = strrchr(path, '.')) == NULL)
- return "";
- return dot;
- }
-
- bool
- canCrunch(path1, path2)
- char *path1;
- char *path2;
- {
- char *slash1;
- char *slash2;
-
- slash1 = strrchr(path1, '/');
- slash2 = strrchr(path2, '/');
-
- if (slash1 == NULL && slash2 == NULL)
- return strequ(suffName(path1), suffName(path2));
- if ((slash1 - path1) != (slash2 - path2))
- return FALSE;
- if (!strnequ(path1, path2, slash1 - path1))
- return FALSE;
- return strequ(suffName(slash1), suffName(slash2));
- }
- #include <sys/types.h>
- #include <sys/stat.h>
-
- /* LookUp adds ../s to the beginning of a file name until it finds
- * the one that really exists. Returns NULL if it gets all the way
- * to / and never finds it.
- *
- * If the file name starts with /, just return it as is.
- *
- * This routine is used to locate the ID database file.
- */
- char *
- LookUp(arg)
- char * arg;
- {
- char * p;
- static char pathBuf[BUFSIZ];
- struct stat rootb;
- struct stat statb;
-
- /* if we got absolute name, just use it. */
- if (arg[0] == '/') return(arg);
- /* if the name we were give exists, don't bother searching */
- if (stat(arg, &statb) == 0) return(arg);
- /* search up the tree until we find a directory where this
- * relative file name is visible.
- * (or we run out of tree to search by hitting root).
- */
- p = pathBuf;
- if (stat("/", &rootb) != 0) return(NULL);
- do {
- strcpy(p, "../");
- p += 3;
- strcpy(p, arg);
- if (stat(pathBuf, &statb) == 0) return(pathBuf);
- *p = '\0';
- if (stat(pathBuf, &statb) != 0) return(NULL);
- } while (! ((statb.st_ino == rootb.st_ino) ||
- (statb.st_dev == rootb.st_dev)));
- return(NULL);
- }
-