|
|
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.