|
|
1.1 ! root 1: /* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */ ! 2: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */ ! 3: /* The copyright notice does not imply actual or intended publication. */ ! 4: /* AUTHORS: */ ! 5: /* H. S. Baird - ATT-BL MH - first versions */ ! 6: /* Path.c - Path functions */ ! 7: ! 8: #include <errno.h> ! 9: #include <stdio.h> ! 10: #include <string.h> ! 11: #define FILE_TREE_INCL 1 ! 12: #include "CPU.h" ! 13: #include "Path.h" ! 14: ! 15: #define dbg_FTW (0) ! 16: ! 17: /* Return full path string in Path *pp, starting at level `sl'; ! 18: if the level is too deep or the name at level `sl' is null, return null string. ! 19: */ ! 20: char *path_toa(pp,sl) ! 21: Path *pp; ! 22: int sl; /* starting level: 0 is first */ ! 23: { int len,lvl; ! 24: static char s[MAX_PATH_DEPTH*(32)]; ! 25: s[0] = '\0'; ! 26: if( sl<=pp->level && pp->name[sl]!=NULL && pp->name[sl][0]!='\0' ) { ! 27: for(lvl=sl; lvl<=pp->level; lvl++) { ! 28: strcat(s,pp->name[lvl]); ! 29: strcat(s,"/"); ! 30: }; ! 31: }; ! 32: if((len=strlen(s))>0) s[len-1] = '\0'; ! 33: return(s); ! 34: } ! 35: ! 36: /* no. slashes in a name */ ! 37: int slashes(n) ! 38: char *n; ! 39: { register int res; ! 40: register char *c; ! 41: res=0; ! 42: c=n; ! 43: while(*c!='\0') { ! 44: if(*c=='/') res++; ! 45: c++; ! 46: }; ! 47: return(res); ! 48: } ! 49: ! 50: /* basename */ ! 51: char *bname(n) ! 52: char *n; ! 53: { register char *res,*c; ! 54: res=n-1; ! 55: c=n; ! 56: while(*c!='\0') { ! 57: if(*c=='/') res=c; ! 58: c++; ! 59: }; ! 60: return(res+1); ! 61: } ! 62: ! 63: #if CPU==VAX || CPU==CRAY ! 64: ! 65: int process_file_tree_node(n,s,code,S) ! 66: char *n; ! 67: struct stat *s; ! 68: int code; ! 69: struct FTW *S; ! 70: /* Uses global `path_process' structure */ ! 71: { char *out_n; ! 72: int persist; ! 73: struct stat sbuf; ! 74: switch(code) { ! 75: case FTW_F: if(dbg_FTW)err("visit file %s %s %d",n,n+(S->base),S->level); ! 76: if(S->level>0) { ! 77: if(path_process.path.name[S->level]!=NULL) ! 78: free(path_process.path.name[S->level]); ! 79: path_process.path.name[S->level]=strdup(n+(S->base)); ! 80: }; ! 81: path_process.path.level = S->level; ! 82: out_n = strdup(path_toa(&path_process.path,0)); ! 83: if(dbg_FTW)err("file: %s ==> %s",n,out_n); ! 84: (*path_process.process)(n,out_n,path_process.arg); ! 85: if(out_n!=NULL) free(out_n); ! 86: break; ! 87: case FTW_SL: if(dbg_FTW)err("visit link %s %s %d",n,n+(S->base),S->level); ! 88: S->quit = FTW_FOLLOW; /* follow symbolic link */ ! 89: break; ! 90: case FTW_D: /* pre-visit of directory */ ! 91: if(dbg_FTW)err("visit dir %s %s %d",n,n+(S->base),S->level); ! 92: if(S->level>0) { ! 93: if(path_process.path.name[S->level]!=NULL) ! 94: free(path_process.path.name[S->level]); ! 95: path_process.path.name[S->level]=strdup(n+(S->base)); ! 96: }; ! 97: path_process.path.level = S->level; ! 98: out_n = path_toa(&path_process.path,0); ! 99: if(dbg_FTW)err("dir: %s --> %s",n,out_n); ! 100: if(out_n[0]=='\0') /* no output name */ break; ! 101: /* ensure directory named out_n exists */ ! 102: if(stat(out_n,&sbuf)==0) { ! 103: /* file exists */ ! 104: if(!(sbuf.st_mode&S_IFDIR)) { ! 105: /* not a directory - try to remove */ ! 106: if(unlink(out_n)==0) { ! 107: if(mkdir(out_n,0777)!=0) { ! 108: /* irrecoverable mkdir */ ! 109: abort("can't mkdir %s", ! 110: out_n); ! 111: }; ! 112: } ! 113: else { /* irrecoverable unlink */ ! 114: abort("can't unlink %s",out_n); ! 115: }; ! 116: }; ! 117: } ! 118: else if(errno==ENOENT) { ! 119: /* file doesn't exist */ ! 120: if(mkdir(out_n,0777)!=0) { ! 121: /* irrecoverable mkdir */ ! 122: abort("can't mkdir %s",out_n); ! 123: }; ! 124: } ! 125: else { /* irrecoverable stat */ ! 126: abort("can't stat %s",out_n); ! 127: }; ! 128: break; ! 129: case FTW_DP: /* post-visit of directory: ignore it*/ ! 130: break; ! 131: case FTW_DNR: ! 132: err("can't read dir %s (FTW_DNR) - ignore it",n); ! 133: break; ! 134: case FTW_NS: ! 135: err("can't stat %s (FTW_NS) - ignore it",n); ! 136: break; ! 137: case FTW_NSL: ! 138: if(0) /* happens if file is missing */ ! 139: err("can't stat symbolic link %s (FTW_NSL) - ignore it",n); ! 140: break; ! 141: default: ! 142: err("unexpected FTW code %d - ignore it",code); ! 143: break; ! 144: }; ! 145: return(0); ! 146: } ! 147: ! 148: #else ! 149: #if CPU==MIPS ! 150: int process_file_tree_node(n,s,code) ! 151: char *n; /* name of the object */ ! 152: struct stat *s; /* info. about object */ ! 153: int code; ! 154: /* Uses global `path_process' structure */ ! 155: #define lvl path_process.path.level ! 156: { char *out_n; ! 157: int persist; ! 158: struct stat sbuf; ! 159: char *bn; ! 160: lvl = slashes(n) - path_process.sl0; ! 161: bn = bname(n); ! 162: switch(code) { ! 163: case FTW_F: if(dbg_FTW) err("visit file %s, bn %s, lvl %d",n,bn,lvl); ! 164: if(lvl>0) { ! 165: if(path_process.path.name[lvl]!=NULL) ! 166: free(path_process.path.name[lvl]); ! 167: path_process.path.name[lvl]=strdup(bn); ! 168: }; ! 169: out_n = strdup(path_toa(&path_process.path,0)); ! 170: if(dbg_FTW)err("file: %s ==> %s",n,out_n); ! 171: (*path_process.process)(n,out_n,path_process.arg); ! 172: if(out_n!=NULL) free(out_n); ! 173: break; ! 174: case FTW_D: /* pre-visit of directory */ ! 175: if(dbg_FTW) err("visit dir %s, bn %s, lvl %d",n,bn,lvl); ! 176: if(lvl>0) { ! 177: if(path_process.path.name[lvl]!=NULL) ! 178: free(path_process.path.name[lvl]); ! 179: path_process.path.name[lvl]=strdup(bn); ! 180: }; ! 181: out_n = path_toa(&path_process.path,0); ! 182: if(dbg_FTW)err("dir: %s --> %s",n,out_n); ! 183: if(out_n[0]=='\0') /* no output name */ break; ! 184: /* ensure directory named out_n exists */ ! 185: if(stat(out_n,&sbuf)==0) { ! 186: /* file exists */ ! 187: if(!(sbuf.st_mode&S_IFDIR)) { ! 188: /* not a directory - try to remove */ ! 189: if(unlink(out_n)==0) { ! 190: if(mkdir(out_n,0777)!=0) { ! 191: /* irrecoverable mkdir */ ! 192: abort("can't mkdir %s", ! 193: out_n); ! 194: }; ! 195: } ! 196: else { /* irrecoverable unlink */ ! 197: abort("can't unlink %s",out_n); ! 198: }; ! 199: }; ! 200: } ! 201: else if(errno==ENOENT) { ! 202: /* file doesn't exist */ ! 203: if(mkdir(out_n,0777)!=0) { ! 204: /* irrecoverable mkdir */ ! 205: abort("can't mkdir %s",out_n); ! 206: }; ! 207: } ! 208: else { /* irrecoverable stat */ ! 209: abort("can't stat %s",out_n); ! 210: }; ! 211: break; ! 212: case FTW_DNR: ! 213: err("can't read dir %s (FTW_DNR) - ignore it",n); ! 214: break; ! 215: case FTW_NS: ! 216: err("can't stat %s (FTW_NS) - ignore it",n); ! 217: break; ! 218: default: ! 219: err("unexpected FTW code %d - ignore it",code); ! 220: break; ! 221: }; ! 222: return(0); ! 223: } ! 224: ! 225: #endif ! 226: #endif ! 227: ! 228: /* Process every leaf file (non-directory) in the file-tree rooted at `in_ftn'. ! 229: If `in_ftn' is itself a leaf, then only it is processed. If it is a directory, ! 230: then a corresponding file-tree is built, rooted at `out_ftn', and paths ! 231: to its leaves created by `mkdir's as required; for each pair of corresponding ! 232: leaf filenames, `process' is called. The filenames have not yet been opened. ! 233: If `out_ftn' is the empty string, then no output file-tree will be generated ! 234: and the corresponding output filenames will all be null. If `in_ftn' is the ! 235: empty string, then `process' is called only once, with the input filename ! 236: empty. Pass 'arg' to 'process' as third argument. */ ! 237: process_file_trees(process,in_ftn,out_ftn,arg) ! 238: VOID (*process)(); ! 239: char *in_ftn; /* may be empty */ ! 240: char *out_ftn; /* may be empty */ ! 241: VOID *arg; /* passed to '(*process)()' as 3rd argument */ ! 242: /* Uses global `path_process' structure */ ! 243: { int level; ! 244: if(in_ftn[0]=='\0') (*process)(in_ftn,out_ftn,arg); ! 245: else { if(dbg_FTW) err("process_file_trees(%s,%s)",in_ftn,out_ftn); ! 246: path_process.path.level = 0; ! 247: path_process.path.name[0] = out_ftn; ! 248: path_process.sl0 = slashes(in_ftn); ! 249: for(level=1; level<MAX_PATH_DEPTH; level++) ! 250: path_process.path.name[level] = NULL; ! 251: path_process.process = process; ! 252: path_process.arg = arg; ! 253: if(ftw(in_ftn,process_file_tree_node,MAX_PATH_DEPTH)<0) ! 254: err("ftw error: errno %d",errno); ! 255: }; ! 256: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.