V10/cmd/bcp/Path.c

Compare this file to the similar file:
Show the results in this format:

/* 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);
		};
	}