diff options
Diffstat (limited to 'usr.sbin/sup/lib/scan.c')
-rw-r--r-- | usr.sbin/sup/lib/scan.c | 969 |
1 files changed, 969 insertions, 0 deletions
diff --git a/usr.sbin/sup/lib/scan.c b/usr.sbin/sup/lib/scan.c new file mode 100644 index 0000000..e68bcdd --- /dev/null +++ b/usr.sbin/sup/lib/scan.c @@ -0,0 +1,969 @@ +/* + * Copyright (c) 1992 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. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software_Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ +/* + * scan.c - sup list file scanner + * + ********************************************************************** + * HISTORY + * $Log: scan.c,v $ + * Revision 1.1.1.1 1993/08/21 00:46:33 jkh + * Current sup with compression support. + * + * Revision 1.1.1.1 1993/05/21 14:52:17 cgd + * initial import of CMU's SUP to NetBSD + * + * Revision 1.8 92/08/11 12:04:28 mrt + * Brad's changes: delinted, added forward declarations of static + * functions.Added Copyright. + * [92/07/24 mrt] + * + * 18-Mar-88 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added host=<hostfile> support to releases file. + * + * 11-Mar-88 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added "rsymlink" recursive symbolic link quoting directive. + * + * 28-Jun-87 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added code for "release" support. + * + * 26-May-87 Doug Philips (dwp) at Carnegie-Mellon University + * Lets see if we'll be able to write the scan file BEFORE + * we collect the data for it. Include sys/file.h and use + * new definitions for access check codes. + * + * 20-May-87 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added type casting information for lint. + * + * 21-Jan-86 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added check for newonly upgrade when lasttime is the same as + * scantime. This will save us the trouble of parsing the scanfile + * when the client has successfully received everything in the + * scanfile already. + * + * 16-Jan-86 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Clear Texec pointers in execT so that Tfree of execT will not + * free command trees associated with files in listT. + * + * 06-Jan-86 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added code to omit scanned files from list if we want new files + * only and they are old. + * + * 29-Dec-85 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Major rewrite for protocol version 4. Added version numbers to + * scan file. Also added mode of file in addition to flags. + * Execute commands are now immediately after file information. + * + * 13-Dec-85 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added comments to list file format. + * + * 08-Dec-85 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Added code to implement omitany. Currently doesn't know about + * {a,b,c} patterns. + * + * 07-Oct-85 Glenn Marcy (gm0w) at Carnegie-Mellon University + * Created. + * + ********************************************************************** + */ + +#include <libc.h> +#include <c.h> +#include <sys/types.h> +#include <sys/time.h> +#include <sys/stat.h> +#include <sys/dir.h> +#include <sys/file.h> +#include "sup.h" + +/************************* + *** M A C R O S *** + *************************/ + +#define SPECNUMBER 1000 + /* number of filenames produced by a single spec in the list file */ + +/******************************************* + *** D A T A S T R U C T U R E S *** + *******************************************/ + +typedef enum { /* release options */ + ONEXT, OPREFIX, OLIST, OSCAN, + OHOST +} OPTION; + +static char *options[] = { + "next", "prefix", "list", "scan", + "host", + 0 +}; + +typedef enum { /* <collection>/list file lines */ + LUPGRADE, LOMIT, LBACKUP, LEXECUTE, + LINCLUDE, LNOACCT, LOMITANY, LALWAYS, + LSYMLINK, LRSYMLINK +} LISTTYPE; + +static char *ltname[] = { + "upgrade", "omit", "backup", "execute", + "include", "noaccount", "omitany", "always", + "symlink", "rsymlink", + 0 +}; + +#define FALWAYS FUPDATE + +/* list file lines */ +static TREE *upgT; /* files to upgrade */ +static TREE *flagsT; /* special flags: BACKUP NOACCT */ +static TREE *omitT; /* recursize file omition list */ +static TREE *omanyT; /* non-recursize file omition list */ +static TREE *symT; /* symbolic links to quote */ +static TREE *rsymT; /* recursive symbolic links to quote */ +static TREE *execT; /* execute command list */ + +/************************* + *** E X T E R N *** + *************************/ + +#ifdef lint +static char _argbreak; +#else +extern char _argbreak; /* break character from nxtarg */ +#endif + +extern TREELIST *listTL; /* list of trees for scanning */ +extern TREE *listT; /* final list of files in collection */ +extern TREE *refuseT; /* files refused by client */ + +extern char *collname; /* collection name */ +extern char *basedir; /* base directory name */ +extern char *prefix; /* collection pathname prefix */ +extern long lasttime; /* time of last upgrade */ +extern long scantime; /* time of this scan */ +extern int trace; /* trace directories */ +extern int newonly; /* new files only */ + +extern long time(); + +/************************************************* + *** STATIC R O U T I N E S *** + *************************************************/ + +static makescan(); +static getscan(); +static doscan(); +static readlistfile(); +static expTinsert(); +static listone(); +static listentry(); +static listname(); +static listdir(); +static omitanyone(); +static anyglob(); +static int getscanfile(); +static chkscanfile(); +static makescanfile(); +static recordone(); +static recordexec(); + +/************************************************* + *** L I S T S C A N R O U T I N E S *** + *************************************************/ + +static +passdelim (ptr,delim) /* skip over delimiter */ +char **ptr,delim; +{ + *ptr = skipover (*ptr, " \t"); + if (_argbreak != delim && **ptr == delim) { + (*ptr)++; + *ptr = skipover (*ptr, " \t"); + } +} + +static +char *parserelease(tlp,relname,args) +TREELIST **tlp; +char *relname,*args; +{ + register TREELIST *tl; + register char *arg; + register OPTION option; + int opno; + char *nextrel; + + tl = (TREELIST *) malloc (sizeof(TREELIST)); + if ((*tlp = tl) == NULL) + goaway ("Couldn't allocate TREELIST"); + tl->TLnext = NULL; + tl->TLname = salloc (relname); + tl->TLprefix = NULL; + tl->TLlist = NULL; + tl->TLscan = NULL; + tl->TLhost = NULL; + nextrel = NULL; + args = skipover (args," \t"); + while (*(arg=nxtarg(&args," \t="))) { + for (opno = 0; options[opno] != NULL; opno++) + if (strcmp (arg,options[opno]) == 0) + break; + if (options[opno] == NULL) + goaway ("Invalid release option %s for release %s", + arg,relname); + option = (OPTION) opno; + switch (option) { + case ONEXT: + passdelim (&args,'='); + arg = nxtarg (&args," \t"); + nextrel = salloc (arg); + break; + case OPREFIX: + passdelim (&args,'='); + arg = nxtarg (&args," \t"); + tl->TLprefix = salloc (arg); + break; + case OLIST: + passdelim (&args,'='); + arg = nxtarg (&args," \t"); + tl->TLlist = salloc (arg); + break; + case OSCAN: + passdelim (&args,'='); + arg = nxtarg (&args," \t"); + tl->TLscan = salloc (arg); + break; + case OHOST: + passdelim (&args,'='); + arg = nxtarg (&args," \t"); + tl->TLhost = salloc (arg); + break; + } + } + return (nextrel); +} + +getrelease (release) +char *release; +{ + TREELIST *tl; + char buf[STRINGLENGTH]; + char *p,*q; + int rewound; + FILE *f; + + if (release == NULL) + release = salloc (DEFRELEASE); + listTL = NULL; + + (void) sprintf (buf,FILERELEASES,collname); + f = fopen (buf,"r"); + if (f != NULL) { + rewound = TRUE; + for (;;) { + p = fgets (buf,STRINGLENGTH,f); + if (p == NULL) { + if (rewound) + break; + rewind (f); + rewound = TRUE; + continue; + } + q = index (p,'\n'); + if (q) *q = 0; + if (index ("#;:",*p)) continue; + q = nxtarg (&p," \t"); + if (strcmp (q,release) != 0) + continue; + release = parserelease (&tl,release,p); + if (tl->TLprefix == NULL) + tl->TLprefix = prefix; + else if (chdir (tl->TLprefix) < 0) + return (FALSE); + else + (void) chdir (basedir); + tl->TLnext = listTL; + listTL = tl; + if (release == NULL) + break; + rewound = FALSE; + } + (void) fclose (f); + } + if (release == NULL) + return (TRUE); + if (strcmp (release,DEFRELEASE) != 0) + return (FALSE); + (void) parserelease (&tl,release,""); + tl->TLprefix = prefix; + tl->TLnext = listTL; + listTL = tl; + return (TRUE); +} + +makescanlists () +{ + TREELIST *tl; + char buf[STRINGLENGTH]; + char *p,*q; + FILE *f; + char *saveprefix = prefix; + int count = 0; + + (void) sprintf (buf,FILERELEASES,collname); + f = fopen (buf,"r"); + if (f != NULL) { + while (p = fgets (buf,STRINGLENGTH,f)) { + q = index (p,'\n'); + if (q) *q = 0; + if (index ("#;:",*p)) continue; + q = nxtarg (&p," \t"); + (void) parserelease (&tl,q,p); + if ((prefix = tl->TLprefix) == NULL) + prefix = saveprefix; + if (prefix != NULL) { + if (chdir (prefix) < 0) + goaway ("Can't chdir to %s",prefix); + (void) chdir (basedir); + } + makescan (tl->TLlist,tl->TLscan); + free ((char *)tl); + count++; + } + (void) fclose (f); + } + if (count == 0) + makescan ((char *)NULL,(char *)NULL); +} + +static +scanone (t) +register TREE *t; +{ + register TREE *newt; + + if (newonly && (t->Tflags&FNEW) == 0) + return (SCMOK); + newt = Tinsert (&listT,t->Tname,FALSE); + if (newt == NULL) + return (SCMOK); + newt->Tmode = t->Tmode; + newt->Tflags = t->Tflags; + newt->Tmtime = t->Tmtime; + return (SCMOK); +} + +getscanlists () +{ + TREELIST *tl,*stl; + + stl = listTL; + listTL = NULL; + while ((tl = stl) != NULL) { + prefix = tl->TLprefix; + getscan (tl->TLlist,tl->TLscan); + tl->TLtree = listT; + stl = tl->TLnext; + tl->TLnext = listTL; + listTL = tl; + } + listT = NULL; + for (tl = listTL; tl != NULL; tl = tl->TLnext) + (void) Tprocess (tl->TLtree,scanone); +} + +static +makescan (listfile,scanfile) +char *listfile,*scanfile; +{ + listT = NULL; + chkscanfile (scanfile); /* can we can write a scan file? */ + doscan (listfile); /* read list file and scan disk */ + makescanfile (scanfile); /* record names in scan file */ + Tfree (&listT); /* free file list tree */ +} + +static +getscan (listfile,scanfile) +char *listfile,*scanfile; +{ + listT = NULL; + if (!getscanfile(scanfile)) { /* check for pre-scanned file list */ + scantime = time ((long *)NULL); + doscan (listfile); /* read list file and scan disk */ + } +} + +static +doscan (listfile) + char *listfile; +{ + char buf[STRINGLENGTH]; + int listone (); + + upgT = NULL; + flagsT = NULL; + omitT = NULL; + omanyT = NULL; + execT = NULL; + symT = NULL; + rsymT = NULL; + if (listfile == NULL) + listfile = FILELISTDEF; + (void) sprintf (buf,FILELIST,collname,listfile); + readlistfile (buf); /* get contents of list file */ + (void) Tprocess (upgT,listone); /* build list of files specified */ + cdprefix ((char *)NULL); + Tfree (&upgT); + Tfree (&flagsT); + Tfree (&omitT); + Tfree (&omanyT); + Tfree (&execT); + Tfree (&symT); + Tfree (&rsymT); +} + +static +readlistfile (fname) +char *fname; +{ + char buf[STRINGLENGTH],*p; + register char *q,*r; + register FILE *f; + register int ltn,n,i,flags; + register TREE **t; + register LISTTYPE lt; + char *speclist[SPECNUMBER]; + + f = fopen (fname,"r"); + if (f == NULL) goaway ("Can't read list file %s",fname); + cdprefix (prefix); + while (p = fgets (buf,STRINGLENGTH,f)) { + if (q = index (p,'\n')) *q = '\0'; + if (index ("#;:",*p)) continue; + q = nxtarg (&p," \t"); + if (*q == '\0') continue; + for (ltn = 0; ltname[ltn] && strcmp(q,ltname[ltn]) != 0; ltn++); + if (ltname[ltn] == NULL) + goaway ("Invalid list file keyword %s",q); + lt = (LISTTYPE) ltn; + flags = 0; + switch (lt) { + case LUPGRADE: + t = &upgT; + break; + case LBACKUP: + t = &flagsT; + flags = FBACKUP; + break; + case LNOACCT: + t = &flagsT; + flags = FNOACCT; + break; + case LSYMLINK: + t = &symT; + break; + case LRSYMLINK: + t = &rsymT; + break; + case LOMIT: + t = &omitT; + break; + case LOMITANY: + t = &omanyT; + break; + case LALWAYS: + t = &upgT; + flags = FALWAYS; + break; + case LINCLUDE: + while (*(q=nxtarg(&p," \t"))) { + cdprefix ((char *)NULL); + n = expand (q,speclist,SPECNUMBER); + for (i = 0; i < n && i < SPECNUMBER; i++) { + readlistfile (speclist[i]); + cdprefix ((char *)NULL); + free (speclist[i]); + } + cdprefix (prefix); + } + continue; + case LEXECUTE: + r = p = q = skipover (p," \t"); + do { + q = p = skipto (p," \t("); + p = skipover (p," \t"); + } while (*p != '(' && *p != '\0'); + if (*p++ == '(') { + *q = '\0'; + do { + q = nxtarg (&p," \t)"); + if (*q == 0) + _argbreak = ')'; + else + expTinsert (q,&execT,0,r); + } while (_argbreak != ')'); + continue; + } + /* fall through */ + default: + goaway ("Error in handling list file keyword %d",ltn); + } + while (*(q=nxtarg(&p," \t"))) { + if (lt == LOMITANY) + (void) Tinsert (t,q,FALSE); + else + expTinsert (q,t,flags,(char *)NULL); + } + } + (void) fclose (f); +} + +static +expTinsert (p,t,flags,exec) +char *p; +TREE **t; +int flags; +char *exec; +{ + register int n, i; + register TREE *newt; + char *speclist[SPECNUMBER]; + char buf[STRINGLENGTH]; + + n = expand (p,speclist,SPECNUMBER); + for (i = 0; i < n && i < SPECNUMBER; i++) { + newt = Tinsert (t,speclist[i],TRUE); + newt->Tflags |= flags; + if (exec) { + (void) sprintf (buf,exec,speclist[i]); + (void) Tinsert (&newt->Texec,buf,FALSE); + } + free (speclist[i]); + } +} + +static +listone (t) /* expand and add one name from upgrade list */ +TREE *t; +{ + listentry(t->Tname,t->Tname,(char *)NULL,(t->Tflags&FALWAYS) != 0); + return (SCMOK); +} + +static +listentry(name,fullname,updir,always) +register char *name, *fullname, *updir; +int always; +{ + struct stat statbuf; + int link = 0; + int omitanyone (); + + if (Tlookup (refuseT,fullname)) return; + if (!always) { + if (Tsearch (omitT,fullname)) return; + if (Tprocess (omanyT,omitanyone,fullname) != SCMOK) + return; + } + if (lstat(name,&statbuf) < 0) + return; + if ((statbuf.st_mode&S_IFMT) == S_IFLNK) { + if (Tsearch (symT,fullname)) { + listname (fullname,&statbuf); + return; + } + if (Tlookup (rsymT,fullname)) { + listname (fullname,&statbuf); + return; + } + if (updir) link++; + if (stat(name,&statbuf) < 0) return; + } + if ((statbuf.st_mode&S_IFMT) == S_IFDIR) { + if (access(name,R_OK|X_OK) < 0) return; + if (chdir(name) < 0) return; + listname (fullname,&statbuf); + if (trace) { + printf ("Scanning directory %s\n",fullname); + (void) fflush (stdout); + } + listdir (fullname,always); + if (updir == 0 || link) { + (void) chdir (basedir); + if (prefix) (void) chdir (prefix); + if (updir && *updir) (void) chdir (updir); + } else + (void) chdir (".."); + return; + } + if (access(name,R_OK) < 0) return; + listname (fullname,&statbuf); +} + +static +listname (name,st) +register char *name; +register struct stat *st; +{ + register TREE *t,*ts; + register int new; + register TREELIST *tl; + + new = st->st_ctime > lasttime; + if (newonly && !new) { + for (tl = listTL; tl != NULL; tl = tl->TLnext) + if (ts = Tsearch (tl->TLtree,name)) + ts->Tflags &= ~FNEW; + return; + } + t = Tinsert (&listT,name,FALSE); + if (t == NULL) return; + t->Tmode = st->st_mode; + t->Tctime = st->st_ctime; + t->Tmtime = st->st_mtime; + if (new) t->Tflags |= FNEW; + if (ts = Tsearch (flagsT,name)) + t->Tflags |= ts->Tflags; + if (ts = Tsearch (execT,name)) { + t->Texec = ts->Texec; + ts->Texec = NULL; + } +} + +static +listdir (name,always) /* expand directory */ +char *name; +int always; +{ + struct direct *dentry; + register DIR *dirp; + char ename[STRINGLENGTH],newname[STRINGLENGTH],filename[STRINGLENGTH]; + register char *p,*newp; + register int i; + + dirp = opendir ("."); + if (dirp == 0) return; /* unreadable: probably protected */ + + p = name; /* punt leading ./ and trailing / */ + newp = newname; + if (p[0] == '.' && p[1] == '/') { + p += 2; + while (*p == '/') p++; + } + while (*newp++ = *p++) ; /* copy string */ + --newp; /* trailing null */ + while (newp > newname && newp[-1] == '/') --newp; /* trailing / */ + *newp = 0; + if (strcmp (newname,".") == 0) newname[0] = 0; /* "." ==> "" */ + + while (dentry=readdir(dirp)) { + if (dentry->d_ino == 0) continue; + if (strcmp(dentry->d_name,".") == 0) continue; + if (strcmp(dentry->d_name,"..") == 0) continue; + for (i=0; i<=MAXNAMLEN && dentry->d_name[i]; i++) + ename[i] = dentry->d_name[i]; + ename[i] = 0; + if (*newname) + (void) sprintf (filename,"%s/%s",newname,ename); + else + (void) strcpy (filename,ename); + listentry(ename,filename,newname,always); + } + closedir (dirp); +} + +static +omitanyone (t,filename) +TREE *t; +char **filename; +{ + if (anyglob (t->Tname,*filename)) + return (SCMERR); + return (SCMOK); +} + +static +anyglob (pattern,match) +char *pattern,*match; +{ + register char *p,*m; + register char *pb,*pe; + + p = pattern; + m = match; + while (*m && *p == *m ) { + p++; + m++; + } + if (*p == '\0' && *m == '\0') + return (TRUE); + switch (*p++) { + case '*': + for (;;) { + if (*p == '\0') + return (TRUE); + if (*m == '\0') + return (*p == '\0'); + if (anyglob (p,++m)) + return (TRUE); + } + case '?': + return (anyglob (p,++m)); + case '[': + pb = p; + while (*(++p) != ']') + if (*p == '\0') + return (FALSE); + pe = p; + for (p = pb + 1; p != pe; p++) { + switch (*p) { + case '-': + if (p == pb && *m == '-') { + p = pe + 1; + return (anyglob (p,++m)); + } + if (p == pb) + continue; + if ((p + 1) == pe) + return (FALSE); + if (*m > *(p - 1) && + *m <= *(p + 1)) { + p = pe + 1; + return (anyglob (p,++m)); + } + continue; + default: + if (*m == *p) { + p = pe + 1; + return (anyglob (p,++m)); + } + } + } + return (FALSE); + default: + return (FALSE); + } +} + +/***************************************** + *** R E A D S C A N F I L E *** + *****************************************/ + +static +int getscanfile (scanfile) +char *scanfile; +{ + char buf[STRINGLENGTH]; + struct stat sbuf; + register FILE *f; + TREE ts; + register char *p,*q; + register TREE *tmp, *t = NULL; + register notwanted; + register TREELIST *tl; + + if (scanfile == NULL) + scanfile = FILESCANDEF; + (void) sprintf (buf,FILESCAN,collname,scanfile); + if (stat(buf,&sbuf) < 0) + return (FALSE); + if ((f = fopen (buf,"r")) == NULL) + return (FALSE); + if ((p = fgets (buf,STRINGLENGTH,f)) == NULL) { + (void) fclose (f); + return (FALSE); + } + if (q = index (p,'\n')) *q = '\0'; + if (*p++ != 'V') { + (void) fclose (f); + return (FALSE); + } + if (atoi (p) != SCANVERSION) { + (void) fclose (f); + return (FALSE); + } + scantime = sbuf.st_mtime; /* upgrade time is time of supscan, + * i.e. time of creation of scanfile */ + if (newonly && scantime == lasttime) { + (void) fclose (f); + return (TRUE); + } + notwanted = FALSE; + while (p = fgets (buf,STRINGLENGTH,f)) { + q = index (p,'\n'); + if (q) *q = 0; + ts.Tflags = 0; + if (*p == 'X') { + if (notwanted) continue; + if (t == NULL) + goaway ("scanfile format inconsistant"); + (void) Tinsert (&t->Texec,++p,FALSE); + continue; + } + notwanted = FALSE; + if (*p == 'B') { + p++; + ts.Tflags |= FBACKUP; + } + if (*p == 'N') { + p++; + ts.Tflags |= FNOACCT; + } + if ((q = index (p,' ')) == NULL) + goaway ("scanfile format inconsistant"); + *q++ = '\0'; + ts.Tmode = atoo (p); + p = q; + if ((q = index (p,' ')) == NULL) + goaway ("scanfile format inconsistant"); + *q++ = '\0'; + ts.Tctime = atoi (p); + p = q; + if ((q = index (p,' ')) == NULL) + goaway ("scanfile format inconsistant"); + *q++ = 0; + ts.Tmtime = atoi (p); + if (ts.Tctime > lasttime) + ts.Tflags |= FNEW; + else if (newonly) { + for (tl = listTL; tl != NULL; tl = tl->TLnext) + if (tmp = Tsearch (tl->TLtree,q)) + tmp->Tflags &= ~FNEW; + notwanted = TRUE; + continue; + } + if (Tlookup (refuseT,q)) { + notwanted = TRUE; + continue; + } + t = Tinsert (&listT,q,TRUE); + t->Tmode = ts.Tmode; + t->Tflags = ts.Tflags; + t->Tctime = ts.Tctime; + t->Tmtime = ts.Tmtime; + } + (void) fclose (f); + return (TRUE); +} + +/******************************************* + *** W R I T E S C A N F I L E *** + *******************************************/ + +static chkscanfile (scanfile) +char *scanfile; +{ + char tname[STRINGLENGTH], fname[STRINGLENGTH]; + FILE *f; + + if (scanfile == NULL) + scanfile = FILESCANDEF; + (void) sprintf (fname,FILESCAN,collname,scanfile); + (void) sprintf (tname,"%s.temp",fname); + if (NULL == (f = fopen (tname, "w"))) + goaway ("Can't test scan file temp %s for %s",tname,collname); + else { + (void) unlink (tname); + (void) fclose (f); + } +} + +static makescanfile (scanfile) +char *scanfile; +{ + char tname[STRINGLENGTH],fname[STRINGLENGTH]; + struct timeval tbuf[2]; + FILE *scanF; /* output file for scanned file list */ + int recordone (); + + if (scanfile == NULL) + scanfile = FILESCANDEF; + (void) sprintf (fname,FILESCAN,collname,scanfile); + (void) sprintf (tname,"%s.temp",fname); + scanF = fopen (tname,"w"); + if (scanF == NULL) + goaway ("Can't write scan file temp %s for %s",tname,collname); + fprintf (scanF,"V%d\n",SCANVERSION); + (void) Tprocess (listT,recordone,scanF); + (void) fclose (scanF); + if (rename (tname,fname) < 0) + goaway ("Can't change %s to %s",tname,fname); + (void) unlink (tname); + tbuf[0].tv_sec = time((long *)NULL); tbuf[0].tv_usec = 0; + tbuf[1].tv_sec = scantime; tbuf[1].tv_usec = 0; + (void) utimes (fname,tbuf); +} + +static +recordone (t,scanF) +TREE *t; +FILE **scanF; +{ + int recordexec (); + + if (t->Tflags&FBACKUP) fprintf (*scanF,"B"); + if (t->Tflags&FNOACCT) fprintf (*scanF,"N"); + fprintf (*scanF,"%o %d %d %s\n", + t->Tmode,t->Tctime,t->Tmtime,t->Tname); + (void) Tprocess (t->Texec,recordexec,*scanF); + return (SCMOK); +} + +static +recordexec (t,scanF) +TREE *t; +FILE **scanF; +{ + fprintf(*scanF,"X%s\n",t->Tname); + return (SCMOK); +} + +cdprefix (prefix) +char *prefix; +{ + static char *curprefix = NULL; + + if (curprefix == NULL) { + if (prefix == NULL) + return; + (void) chdir (prefix); + curprefix = prefix; + return; + } + if (prefix == NULL) { + (void) chdir (basedir); + curprefix = NULL; + return; + } + if (prefix == curprefix) + return; + if (strcmp (prefix, curprefix) == 0) { + curprefix = prefix; + return; + } + (void) chdir (basedir); + (void) chdir (prefix); + curprefix = prefix; +} |