home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Source Code 1992 March
/
Source_Code_CD-ROM_Walnut_Creek_March_1992.iso
/
usenet
/
altsrcs
/
2
/
2276
/
paths.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-12-28
|
5KB
|
221 lines
/* 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);
}