This is makepath.c in view mode; [Download] [Up]
/* * Copyright (c) 1990 Carnegie Mellon University * All Rights Reserved. * * Permission to use, copy, modify and distribute this software and its * documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. * * THE SOFTWARE IS PROVIDED "AS IS" AND CARNEGIE MELLON UNIVERSITY * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT * SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * Users of this software agree to return to Carnegie Mellon any * improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. * * Export of this software is permitted only after complying with the * regulations of the U.S. Deptartment of Commerce relating to the * Export of Technical Data. */ /* * makepath - create intermediate directories along a path * * makepath(path, refpath, trace, showerrs) * char *path, *refpath; * int trace, showerrs; * * Create any directories missing in path. If refpath is non-null, * then it must have a non-null trailing subpath that is common to * path. The entire path will be created if refpath is given and * refpath is the path of a directory, otherwise only the components * preceding the final component will be created for path. If trace * is non-zero, diagnostics will be printed to stderr. If showerrs * is non-zero error messages will be printed to stderr. * ********************************************************************** * HISTORY * $Log: makepath.c,v $ * Revision 2.3 90/12/11 17:56:54 mja * Add copyright/disclaimer for distribution. * * Revision 2.2 88/12/13 13:51:54 gm0w * Created from makepath program. * [88/12/13 gm0w] * ********************************************************************** */ #include <sys/param.h> #include <sys/stat.h> #include <sys/time.h> #include <stdio.h> #include <libc.h> #include <c.h> static char *fixpath(path, buf) register char *path; char *buf; { register char *ls = NULL; register char *p = buf; *p = *path; while (*path != '\0') { path++; while (*p == '/' && *path == '/') path++; *++p = *path; if (*p == '/') ls = p; } return(ls); } makepath(path, refpath, trace, showerrs) char *path, *refpath; int trace, showerrs; { char pathbuf[MAXPATHLEN], refpathbuf[MAXPATHLEN]; char linkbuf[MAXPATHLEN], linkbuf2[MAXPATHLEN]; char *base, *refbase; char *slash, *refslash; struct stat statb, refstatb; int ch, cc, cc2; extern uid_t getuid(); uid_t uid = getuid(); if (path == NULL) { if (showerrs) fprintf(stderr, "makepath: NULL path argument\n"); return(1); } base = fixpath(path, pathbuf); if (refpath == NULL) { if (base == NULL || base == pathbuf) { if (showerrs) fprintf(stderr, "makepath: %s must have an imbedded '/' character\n", pathbuf); return(1); } *base = '\0'; base = pathbuf; if (*base == '/') base++; if (*base == '\0') { if (showerrs) fprintf(stderr, "makepath: illegal pathname %s\n", pathbuf); return(1); } for (;;) { /* find end of this component */ while (*base != '\0' && *base != '/') base++; /* create path so far, if necessary */ ch = *base; *base = '\0'; if (stat(pathbuf, &statb) < 0) { if (mkdir(pathbuf, 0755) < 0) { if (showerrs) fprintf(stderr, "makepath: unable to create directory %s: %s\n", pathbuf, errmsg(-1)); return(1); } if (stat(pathbuf, &statb) < 0) { if (showerrs) fprintf(stderr, "%s: unable to stat directory %s: %s\n", pathbuf, errmsg(-1)); return(1); } if (trace) fprintf(stderr, "%s: created directory\n", pathbuf); } else if ((statb.st_mode&S_IFMT) != S_IFDIR) { if (showerrs) fprintf(stderr, "makepath: %s is not a directory (mode %#o)\n", pathbuf, (statb.st_mode&S_IFMT)); return(1); } if (ch == '\0') break; *base++ = ch; } return(0); } refbase = fixpath(refpath, refpathbuf); /* if not a directory path, strip final component */ if (stat(refpathbuf, &refstatb) < 0 || (refstatb.st_mode&S_IFMT) != S_IFDIR) { if (base == NULL || base == pathbuf) { if (showerrs) fprintf(stderr, "makepath: %s must have an imbedded '/' character\n", pathbuf); return(1); } if (refbase == NULL || refbase == refpathbuf) { if (showerrs) fprintf(stderr, "makepath: %s must have an imbedded '/' character\n", refpathbuf); return(1); } if (strcmp(base, refbase) != 0) { if (showerrs) fprintf(stderr, "makepath: %s and %s do not have common trailing components\n", base, refbase); return(1); } *base = *refbase = '\0'; if (stat(refpathbuf, &refstatb) < 0) { if (showerrs) fprintf(stderr, "%s: unable to stat reference directory %s: %s\n", refpathbuf, errmsg(-1)); return(1); } if ((refstatb.st_mode&S_IFMT) != S_IFDIR) { if (showerrs) fprintf(stderr, "makepath: %s is not a directory (mode %#o)\n", refpathbuf, (refstatb.st_mode&S_IFMT)); return(1); } } /* find beginning of common part of path names */ base = pathbuf + strlen(pathbuf); refbase = refpathbuf + strlen(refpathbuf); while (*base == *refbase) { if (base == pathbuf || refbase == refpathbuf) break; base--; refbase--; } if (*base == *refbase && *base != '/') { if (base == pathbuf && *(refbase-1) == '/') { base = pathbuf + strlen(pathbuf) + 2; do { *base = *(base - 2); } while (base-- > pathbuf + 2); *(base-1) = '.'; *base = '/'; refbase--; } if (refbase == refpathbuf && *(base-1) == '/') { refbase = refpathbuf + strlen(refpathbuf) + 2; do { *refbase = *(refbase - 2); } while (refbase-- > refpathbuf + 2); *(refbase-1) = '.'; *refbase = '/'; base--; } } while (*base != '\0' && *base != '/') { base++; refbase++; } slash = base++; refslash = refbase++; ch = *slash; *slash = '\0'; if (stat(pathbuf, &statb) < 0) { if (showerrs) fprintf(stderr, "makepath: unable to stat target directory %s: %s\n", pathbuf, errmsg(-1)); return(1); } if ((statb.st_mode&S_IFMT) != S_IFDIR) { if (showerrs) fprintf(stderr, "makepath: %s: invalid mode %#o\n", pathbuf, (statb.st_mode&S_IFMT)); return(1); } *slash = ch; /* check each component along common path and make them the same */ while (ch != '\0') { /* find end of this component */ while (*base != '\0' && *base != '/') { base++; refbase++; } /* get stat information for source path */ ch = *refbase; *refbase = '\0'; *base = '\0'; if (stat(refpathbuf, &refstatb) < 0) { if (showerrs) fprintf(stderr, "makepath: stat %s: %s\n", refpathbuf, errmsg(-1)); return(1); } if ((refstatb.st_mode&S_IFMT) != S_IFDIR) { if (showerrs) fprintf(stderr, "makepath: %s: invalid mode %#o\n", refpathbuf, (refstatb.st_mode&S_IFMT)); return(1); } if (lstat(refpathbuf, &refstatb) < 0) { if (showerrs) fprintf(stderr, "makepath: lstat %s: %s\n", refpathbuf, errmsg(-1)); return(1); } if ((refstatb.st_mode&S_IFMT) == S_IFLNK) { if ((cc = readlink(refpathbuf, linkbuf, sizeof(linkbuf)-1)) < 0) { if (showerrs) fprintf(stderr, "makepath: readlink %s: %s\n", refpathbuf, errmsg(-1)); return(1); } if (cc > 0 && *linkbuf != '/') { *refbase = ch; linkbuf[cc] = '\0'; if (lstat(pathbuf, &statb) < 0) { if (symlink(linkbuf, pathbuf) < 0) { if (showerrs) fprintf(stderr, "makepath: symlink %s: %s\n", pathbuf, errmsg(-1)); return(1); } if (trace) fprintf(stderr, "%s: created symlink to %s\n", pathbuf, linkbuf); } else { if ((statb.st_mode&S_IFMT) != S_IFLNK) { if (showerrs) fprintf(stderr, "makepath: %s: invalid mode %#o\n", pathbuf, (statb.st_mode&S_IFMT)); return(1); } cc2 = readlink(pathbuf, linkbuf2, sizeof(linkbuf2)-1); if (cc2 < 0) { if (showerrs) fprintf(stderr, "makepath: readlink %s: %s\n", pathbuf, errmsg(-1)); return(1); } if (cc != cc2 || bcmp(linkbuf, linkbuf2, cc) != 0) { if (showerrs) fprintf(stderr, "makepath: symlinks %s and %s differ\n", refpathbuf, pathbuf, errmsg(-1)); return(1); } } (void) strcpy(linkbuf+cc, refbase); (void) strcpy(refslash+1, linkbuf); (void) strcpy(slash+1, linkbuf); (void) fixpath(refslash, refslash); (void) fixpath(slash, slash); refbase = refslash+1; base = slash+1; ch = *refslash; continue; } } /* create path so far, if necessary */ if (lstat(pathbuf, &statb) < 0) { if (mkdir(pathbuf, (int)(refstatb.st_mode&07777)) < 0) { if (showerrs) fprintf(stderr, "makepath: mkdir %s: %s\n", pathbuf, errmsg(-1)); return(1); } if (stat(pathbuf, &statb) < 0) { if (showerrs) fprintf(stderr, "makepath: stat %s: %s\n", pathbuf, errmsg(-1)); return(1); } if (trace) fprintf(stderr, "%s: created directory\n", pathbuf); } else if ((statb.st_mode&S_IFMT) != S_IFDIR) { if (showerrs) fprintf(stderr, "makepath: %s: invalid mode %#o\n", pathbuf, (statb.st_mode&S_IFMT)); return(1); } if (uid == 0 && (statb.st_uid != refstatb.st_uid || statb.st_gid != refstatb.st_gid)) { (void) chown(pathbuf, (int)refstatb.st_uid, (int)refstatb.st_gid); if (trace) fprintf(stderr, "%s: owner %d, group %d\n", pathbuf, refstatb.st_uid, refstatb.st_gid); } if ((statb.st_mode&07777) != (refstatb.st_mode&07777)) { (void) chmod(pathbuf, (int)(refstatb.st_mode&07777)); if (trace) fprintf(stderr, "%s: mode %#o\n", pathbuf, refstatb.st_mode&07777); } refslash = refbase; *refbase++ = ch; slash = base; *base++ = ch; } return(0); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.