|
|
researchv10 Norman
/* Copyright (c) 1989, 1990 AT&T --- All Rights Reserved. */
/* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T. */
/* The copyright notice does not imply actual or intended publication. */
/* AUTHORS: */
/* H. S. Baird - ATT-BL MH - first versions */
/* Path.c - Path functions */
#include <errno.h>
#include <stdio.h>
#include <string.h>
#define FILE_TREE_INCL 1
#include "CPU.h"
#include "Path.h"
#define dbg_FTW (0)
/* Return full path string in Path *pp, starting at level `sl';
if the level is too deep or the name at level `sl' is null, return null string.
*/
char *path_toa(pp,sl)
Path *pp;
int sl; /* starting level: 0 is first */
{ int len,lvl;
static char s[MAX_PATH_DEPTH*(32)];
s[0] = '\0';
if( sl<=pp->level && pp->name[sl]!=NULL && pp->name[sl][0]!='\0' ) {
for(lvl=sl; lvl<=pp->level; lvl++) {
strcat(s,pp->name[lvl]);
strcat(s,"/");
};
};
if((len=strlen(s))>0) s[len-1] = '\0';
return(s);
}
/* no. slashes in a name */
int slashes(n)
char *n;
{ register int res;
register char *c;
res=0;
c=n;
while(*c!='\0') {
if(*c=='/') res++;
c++;
};
return(res);
}
/* basename */
char *bname(n)
char *n;
{ register char *res,*c;
res=n-1;
c=n;
while(*c!='\0') {
if(*c=='/') res=c;
c++;
};
return(res+1);
}
#if CPU==VAX || CPU==CRAY
int process_file_tree_node(n,s,code,S)
char *n;
struct stat *s;
int code;
struct FTW *S;
/* Uses global `path_process' structure */
{ char *out_n;
int persist;
struct stat sbuf;
switch(code) {
case FTW_F: if(dbg_FTW)err("visit file %s %s %d",n,n+(S->base),S->level);
if(S->level>0) {
if(path_process.path.name[S->level]!=NULL)
free(path_process.path.name[S->level]);
path_process.path.name[S->level]=strdup(n+(S->base));
};
path_process.path.level = S->level;
out_n = strdup(path_toa(&path_process.path,0));
if(dbg_FTW)err("file: %s ==> %s",n,out_n);
(*path_process.process)(n,out_n,path_process.arg);
if(out_n!=NULL) free(out_n);
break;
case FTW_SL: if(dbg_FTW)err("visit link %s %s %d",n,n+(S->base),S->level);
S->quit = FTW_FOLLOW; /* follow symbolic link */
break;
case FTW_D: /* pre-visit of directory */
if(dbg_FTW)err("visit dir %s %s %d",n,n+(S->base),S->level);
if(S->level>0) {
if(path_process.path.name[S->level]!=NULL)
free(path_process.path.name[S->level]);
path_process.path.name[S->level]=strdup(n+(S->base));
};
path_process.path.level = S->level;
out_n = path_toa(&path_process.path,0);
if(dbg_FTW)err("dir: %s --> %s",n,out_n);
if(out_n[0]=='\0') /* no output name */ break;
/* ensure directory named out_n exists */
if(stat(out_n,&sbuf)==0) {
/* file exists */
if(!(sbuf.st_mode&S_IFDIR)) {
/* not a directory - try to remove */
if(unlink(out_n)==0) {
if(mkdir(out_n,0777)!=0) {
/* irrecoverable mkdir */
abort("can't mkdir %s",
out_n);
};
}
else { /* irrecoverable unlink */
abort("can't unlink %s",out_n);
};
};
}
else if(errno==ENOENT) {
/* file doesn't exist */
if(mkdir(out_n,0777)!=0) {
/* irrecoverable mkdir */
abort("can't mkdir %s",out_n);
};
}
else { /* irrecoverable stat */
abort("can't stat %s",out_n);
};
break;
case FTW_DP: /* post-visit of directory: ignore it*/
break;
case FTW_DNR:
err("can't read dir %s (FTW_DNR) - ignore it",n);
break;
case FTW_NS:
err("can't stat %s (FTW_NS) - ignore it",n);
break;
case FTW_NSL:
if(0) /* happens if file is missing */
err("can't stat symbolic link %s (FTW_NSL) - ignore it",n);
break;
default:
err("unexpected FTW code %d - ignore it",code);
break;
};
return(0);
}
#else
#if CPU==MIPS
int process_file_tree_node(n,s,code)
char *n; /* name of the object */
struct stat *s; /* info. about object */
int code;
/* Uses global `path_process' structure */
#define lvl path_process.path.level
{ char *out_n;
int persist;
struct stat sbuf;
char *bn;
lvl = slashes(n) - path_process.sl0;
bn = bname(n);
switch(code) {
case FTW_F: if(dbg_FTW) err("visit file %s, bn %s, lvl %d",n,bn,lvl);
if(lvl>0) {
if(path_process.path.name[lvl]!=NULL)
free(path_process.path.name[lvl]);
path_process.path.name[lvl]=strdup(bn);
};
out_n = strdup(path_toa(&path_process.path,0));
if(dbg_FTW)err("file: %s ==> %s",n,out_n);
(*path_process.process)(n,out_n,path_process.arg);
if(out_n!=NULL) free(out_n);
break;
case FTW_D: /* pre-visit of directory */
if(dbg_FTW) err("visit dir %s, bn %s, lvl %d",n,bn,lvl);
if(lvl>0) {
if(path_process.path.name[lvl]!=NULL)
free(path_process.path.name[lvl]);
path_process.path.name[lvl]=strdup(bn);
};
out_n = path_toa(&path_process.path,0);
if(dbg_FTW)err("dir: %s --> %s",n,out_n);
if(out_n[0]=='\0') /* no output name */ break;
/* ensure directory named out_n exists */
if(stat(out_n,&sbuf)==0) {
/* file exists */
if(!(sbuf.st_mode&S_IFDIR)) {
/* not a directory - try to remove */
if(unlink(out_n)==0) {
if(mkdir(out_n,0777)!=0) {
/* irrecoverable mkdir */
abort("can't mkdir %s",
out_n);
};
}
else { /* irrecoverable unlink */
abort("can't unlink %s",out_n);
};
};
}
else if(errno==ENOENT) {
/* file doesn't exist */
if(mkdir(out_n,0777)!=0) {
/* irrecoverable mkdir */
abort("can't mkdir %s",out_n);
};
}
else { /* irrecoverable stat */
abort("can't stat %s",out_n);
};
break;
case FTW_DNR:
err("can't read dir %s (FTW_DNR) - ignore it",n);
break;
case FTW_NS:
err("can't stat %s (FTW_NS) - ignore it",n);
break;
default:
err("unexpected FTW code %d - ignore it",code);
break;
};
return(0);
}
#endif
#endif
/* Process every leaf file (non-directory) in the file-tree rooted at `in_ftn'.
If `in_ftn' is itself a leaf, then only it is processed. If it is a directory,
then a corresponding file-tree is built, rooted at `out_ftn', and paths
to its leaves created by `mkdir's as required; for each pair of corresponding
leaf filenames, `process' is called. The filenames have not yet been opened.
If `out_ftn' is the empty string, then no output file-tree will be generated
and the corresponding output filenames will all be null. If `in_ftn' is the
empty string, then `process' is called only once, with the input filename
empty. Pass 'arg' to 'process' as third argument. */
process_file_trees(process,in_ftn,out_ftn,arg)
VOID (*process)();
char *in_ftn; /* may be empty */
char *out_ftn; /* may be empty */
VOID *arg; /* passed to '(*process)()' as 3rd argument */
/* Uses global `path_process' structure */
{ int level;
if(in_ftn[0]=='\0') (*process)(in_ftn,out_ftn,arg);
else { if(dbg_FTW) err("process_file_trees(%s,%s)",in_ftn,out_ftn);
path_process.path.level = 0;
path_process.path.name[0] = out_ftn;
path_process.sl0 = slashes(in_ftn);
for(level=1; level<MAX_PATH_DEPTH; level++)
path_process.path.name[level] = NULL;
path_process.process = process;
path_process.arg = arg;
if(ftw(in_ftn,process_file_tree_node,MAX_PATH_DEPTH)<0)
err("ftw error: errno %d",errno);
};
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.