/* Copyright (c) 1986, Greg McGary */ static char sccsid[] = "@(#)paths.c 1.1 86/10/09"; #include "bool.h" #include #include "string.h" bool canCrunch(); char *getDirToName(); char *rootName(); char *skipJunk(); char *spanPath(); char *suffName(); char * spanPath(dir, arg) char *dir; char *arg; { static char pathBuf[BUFSIZ]; char *path; char *argTail; char *dirTail; int argLength; int dirLength; for (dirTail = &dir[strlen(dir)-1]; *dirTail == '/'; dirTail--) *dirTail = '\0'; (path = pathBuf)[0] = '\0'; /* was lower REJ */ /* while dir and arg are the same loop REJ */ #ifdef AMIGA /* two complete path names, find minimal traverse, using ///... */ /* first, the volume names must match */ dirTail = strchr(dir,':'); argTail = strchr(arg,':'); if (dirTail && argTail) /* should always be true, but paranoia */ { dirLength = dirTail - dir; argLength = argTail - arg; if (argLength == dirLength) { if (!strnicmp(arg, dir, argLength)) { arg = argTail; dir = dirTail; #endif for (;;) { dir = skipJunk(dir); if ((dirTail = strchr(dir, '/')) == NULL) dirTail = &dir[strlen(dir)]; dirLength = dirTail - dir; arg = skipJunk(arg); if ((argTail = strchr(arg, '/')) == NULL) break; argLength = argTail - arg; if (argLength != dirLength) break; if (!strnequ(arg, dir, argLength)) break; arg = argTail; dir = dirTail; } for (; dir && *dir; dir = skipJunk(strchr(dir, '/'))) { #ifdef UNIX strcpy(path, "../"); path += 3; #endif #ifdef AMIGA *path++ = '/'; *path = '\0'; #endif } #ifdef AMIGA } } } #endif strcat(path, arg); return pathBuf; } char * skipJunk(path) char *path; { if (path == NULL) return NULL; #ifdef AMIGA if (*path == ':' || *path == '/') path++; #endif #ifdef UNIX while (*path == '/') path++; while (path[0] == '.' && path[1] == '/') { path += 2; while (*path == '/') path++; } if (strequ(path, ".")) path++; #endif return path; } char * rootName(path) char *path; { static char pathBuf[BUFSIZ]; char *root; char *dot; if ((root = strrchr(path, '/')) == NULL) #ifdef AMIGA if ((root = strrchr(path, ':')) == NULL) root = path; else root++; #endif #ifdef UNIX root = path; #endif else root++; if ((dot = strrchr(root, '.')) == NULL) strcpy(pathBuf, root); else { strncpy(pathBuf, root, dot - root); pathBuf[dot - root] = '\0'; } return pathBuf; } 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, '/'); #ifdef AMIGA if (slash1 == NULL) slash1 = strrchr(path1,':'); if (slash2 == NULL) slash2 = strrchr(path2,':'); #endif 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)); } #ifdef UNIX #include #include #ifdef NDIR #include #else #include #endif #endif UNIX static char dot[] = "."; static char dotdot[] = ".."; /* Return our directory name relative to the first parent dir that contains a file with a name that matches `topName'. Fail if we hit the root, or if any dir in our way is unreadable. */ char * getDirToName(topName) char *topName; { static char nameBuf[BUFSIZ]; char *name; #ifdef UNIX register struct direct *dirp; register DIR *dirdp; struct stat dStat; struct stat ddStat; #endif #ifdef AMIGA char path[64]; char *temp; #endif name = &nameBuf[sizeof(nameBuf)-1]; *name = '\0'; for (;;) { #ifdef UNIX if (stat(topName, &dStat) == 0) { if (!*name) name = dot; else chdir(name); return name; } if (stat(dot, &dStat) < 0) return NULL; if ((dirdp = opendir(dotdot)) == NULL) return NULL; if (fstat(dirdp->dd_fd, &ddStat) < 0) return NULL; if (chdir(dotdot) < 0) return NULL; if (dStat.st_dev == ddStat.st_dev) { if (dStat.st_ino == ddStat.st_ino) return NULL; do { if ((dirp = readdir(dirdp)) == NULL) return NULL; } while (dirp->d_ino != dStat.st_ino); } else { do { if ((dirp = readdir(dirdp)) == NULL) return NULL; stat(dirp->d_name, &ddStat); } while (ddStat.st_ino != dStat.st_ino || ddStat.st_dev != dStat.st_dev); } closedir(dirdp); if (*name != '\0') *--name = '/'; name -= dirp->d_namlen; strncpy(name, dirp->d_name, dirp->d_namlen); #endif UNIX #ifdef AMIGA if (access(topName,0) == 0) { /* got it */ if (!*name) name = ""; else if (chdir(name) == -1) return NULL; return name; } if (getcd(0,path) == -1 || path[strlen(path)-1] == ':') return NULL; /* add current dir to list */ if (*name != '\0') *--name = '/'; /* assumes xxx:yyy[{/zzz}...] */ if ((temp = strrchr(path,'/')) == NULL) temp = strchr(path,':'); /* root - take volume */ else temp++; /* point past '/' */ name -= strlen(temp); strncpy(name, temp, strlen(temp)); chdir("/"); #endif } }