~ubuntu-branches/ubuntu/precise/sup/precise

« back to all changes in this revision

Viewing changes to scan.c

  • Committer: Bazaar Package Importer
  • Author(s): Matt Zimmerman
  • Date: 2004-06-03 10:52:06 UTC
  • Revision ID: james.westby@ubuntu.com-20040603105206-gs0ru9r7st4s4ldm
Tags: upstream-1.8
ImportĀ upstreamĀ versionĀ 1.8

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 1992 Carnegie Mellon University
 
3
 * All Rights Reserved.
 
4
 * 
 
5
 * Permission to use, copy, modify and distribute this software and its
 
6
 * documentation is hereby granted, provided that both the copyright
 
7
 * notice and this permission notice appear in all copies of the
 
8
 * software, derivative works or modified versions, and any portions
 
9
 * thereof, and that both notices appear in supporting documentation.
 
10
 *
 
11
 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
 
12
 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
 
13
 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
 
14
 *
 
15
 * Carnegie Mellon requests users of this software to return to
 
16
 *
 
17
 *  Software Distribution Coordinator  or  Software_Distribution@CS.CMU.EDU
 
18
 *  School of Computer Science
 
19
 *  Carnegie Mellon University
 
20
 *  Pittsburgh PA 15213-3890
 
21
 *
 
22
 * any improvements or extensions that they make and grant Carnegie Mellon
 
23
 * the rights to redistribute these changes.
 
24
 */
 
25
/*
 
26
 * scan.c - sup list file scanner
 
27
 *
 
28
 **********************************************************************
 
29
 * HISTORY
 
30
 * $Log: scan.c,v $
 
31
 * Revision 1.1.1.1  1993/08/21  00:46:33  jkh
 
32
 * Current sup with compression support.
 
33
 *
 
34
 * Revision 1.1.1.1  1993/05/21  14:52:17  cgd
 
35
 * initial import of CMU's SUP to NetBSD
 
36
 *
 
37
 * Revision 1.8  92/08/11  12:04:28  mrt
 
38
 *      Brad's changes: delinted, added forward declarations of static
 
39
 *      functions.Added Copyright.
 
40
 *      [92/07/24            mrt]
 
41
 * 
 
42
 * 18-Mar-88  Glenn Marcy (gm0w) at Carnegie-Mellon University
 
43
 *      Added host=<hostfile> support to releases file.
 
44
 *
 
45
 * 11-Mar-88  Glenn Marcy (gm0w) at Carnegie-Mellon University
 
46
 *      Added "rsymlink" recursive symbolic link quoting directive.
 
47
 *
 
48
 * 28-Jun-87  Glenn Marcy (gm0w) at Carnegie-Mellon University
 
49
 *      Added code for "release" support.
 
50
 *
 
51
 * 26-May-87  Doug Philips (dwp) at Carnegie-Mellon University
 
52
 *      Lets see if we'll be able to write the scan file BEFORE
 
53
 *      we collect the data for it.  Include sys/file.h and use
 
54
 *      new definitions for access check codes.
 
55
 *
 
56
 * 20-May-87  Glenn Marcy (gm0w) at Carnegie-Mellon University
 
57
 *      Added type casting information for lint.
 
58
 *
 
59
 * 21-Jan-86  Glenn Marcy (gm0w) at Carnegie-Mellon University
 
60
 *      Added check for newonly upgrade when lasttime is the same as
 
61
 *      scantime.  This will save us the trouble of parsing the scanfile
 
62
 *      when the client has successfully received everything in the
 
63
 *      scanfile already.
 
64
 *
 
65
 * 16-Jan-86  Glenn Marcy (gm0w) at Carnegie-Mellon University
 
66
 *      Clear Texec pointers in execT so that Tfree of execT will not
 
67
 *      free command trees associated with files in listT.
 
68
 *
 
69
 * 06-Jan-86  Glenn Marcy (gm0w) at Carnegie-Mellon University
 
70
 *      Added code to omit scanned files from list if we want new files
 
71
 *      only and they are old.
 
72
 *
 
73
 * 29-Dec-85  Glenn Marcy (gm0w) at Carnegie-Mellon University
 
74
 *      Major rewrite for protocol version 4.  Added version numbers to
 
75
 *      scan file.  Also added mode of file in addition to flags.
 
76
 *      Execute commands are now immediately after file information.
 
77
 *
 
78
 * 13-Dec-85  Glenn Marcy (gm0w) at Carnegie-Mellon University
 
79
 *      Added comments to list file format.
 
80
 *
 
81
 * 08-Dec-85  Glenn Marcy (gm0w) at Carnegie-Mellon University
 
82
 *      Added code to implement omitany.  Currently doesn't know about
 
83
 *      {a,b,c} patterns.
 
84
 *
 
85
 * 07-Oct-85  Glenn Marcy (gm0w) at Carnegie-Mellon University
 
86
 *      Created.
 
87
 *
 
88
 **********************************************************************
 
89
 */
 
90
 
 
91
#include <libc.h>
 
92
#include <c.h>
 
93
#include <sys/types.h>
 
94
#include <sys/time.h>
 
95
#include <sys/stat.h>
 
96
#include <sys/dir.h>
 
97
#include <sys/file.h>
 
98
#include "sup.h"
 
99
 
 
100
/*************************
 
101
 ***    M A C R O S    ***
 
102
 *************************/
 
103
 
 
104
#define SPECNUMBER 1000
 
105
        /* number of filenames produced by a single spec in the list file */
 
106
 
 
107
/*******************************************
 
108
 ***    D A T A   S T R U C T U R E S    ***
 
109
 *******************************************/
 
110
 
 
111
typedef enum {                  /* release options */
 
112
        ONEXT,          OPREFIX,        OLIST,          OSCAN,
 
113
        OHOST
 
114
} OPTION;
 
115
 
 
116
static char *options[] = {
 
117
        "next",         "prefix",       "list",         "scan",
 
118
        "host",
 
119
        0
 
120
};
 
121
 
 
122
typedef enum {                  /* <collection>/list file lines */
 
123
        LUPGRADE,       LOMIT,          LBACKUP,        LEXECUTE,
 
124
        LINCLUDE,       LNOACCT,        LOMITANY,       LALWAYS,
 
125
        LSYMLINK,       LRSYMLINK
 
126
} LISTTYPE;
 
127
 
 
128
static char *ltname[] = {
 
129
        "upgrade",      "omit",         "backup",       "execute",
 
130
        "include",      "noaccount",    "omitany",      "always",
 
131
        "symlink",      "rsymlink",
 
132
        0
 
133
};
 
134
 
 
135
#define FALWAYS         FUPDATE
 
136
 
 
137
/* list file lines */
 
138
static TREE *upgT;                      /* files to upgrade */
 
139
static TREE *flagsT;                    /* special flags: BACKUP NOACCT */
 
140
static TREE *omitT;                     /* recursize file omition list */
 
141
static TREE *omanyT;                    /* non-recursize file omition list */
 
142
static TREE *symT;                      /* symbolic links to quote */
 
143
static TREE *rsymT;                     /* recursive symbolic links to quote */
 
144
static TREE *execT;                     /* execute command list */
 
145
 
 
146
/*************************
 
147
 ***    E X T E R N    ***
 
148
 *************************/
 
149
 
 
150
#ifdef  lint
 
151
static char _argbreak;
 
152
#else
 
153
extern char _argbreak;                  /* break character from nxtarg */
 
154
#endif
 
155
 
 
156
extern TREELIST *listTL;                /* list of trees for scanning */
 
157
extern TREE *listT;                     /* final list of files in collection */
 
158
extern TREE *refuseT;                   /* files refused by client */
 
159
 
 
160
extern char *collname;                  /* collection name */
 
161
extern char *basedir;                   /* base directory name */
 
162
extern char *prefix;                    /* collection pathname prefix */
 
163
extern long lasttime;                   /* time of last upgrade */
 
164
extern long scantime;                   /* time of this scan */
 
165
extern int trace;                       /* trace directories */
 
166
extern int newonly;                     /* new files only */
 
167
 
 
168
extern long time();
 
169
 
 
170
/*************************************************
 
171
 ***   STATIC   R O U T I N E S    ***
 
172
 *************************************************/
 
173
 
 
174
static makescan();
 
175
static getscan();
 
176
static doscan();
 
177
static readlistfile();
 
178
static expTinsert();
 
179
static listone();
 
180
static listentry();
 
181
static listname();
 
182
static listdir();
 
183
static omitanyone();
 
184
static anyglob();
 
185
static int getscanfile();
 
186
static chkscanfile();
 
187
static makescanfile();
 
188
static recordone();
 
189
static recordexec();
 
190
 
 
191
/*************************************************
 
192
 ***    L I S T   S C A N   R O U T I N E S    ***
 
193
 *************************************************/
 
194
 
 
195
static
 
196
passdelim (ptr,delim)           /* skip over delimiter */
 
197
char **ptr,delim;
 
198
{
 
199
        *ptr = skipover (*ptr, " \t");
 
200
        if (_argbreak != delim && **ptr == delim) {
 
201
                (*ptr)++;
 
202
                *ptr = skipover (*ptr, " \t");
 
203
        }
 
204
}
 
205
 
 
206
static
 
207
char *parserelease(tlp,relname,args)
 
208
TREELIST **tlp;
 
209
char *relname,*args;
 
210
{
 
211
        register TREELIST *tl;
 
212
        register char *arg;
 
213
        register OPTION option;
 
214
        int opno;
 
215
        char *nextrel;
 
216
 
 
217
        tl = (TREELIST *) malloc (sizeof(TREELIST));
 
218
        if ((*tlp = tl) == NULL)
 
219
                goaway ("Couldn't allocate TREELIST");
 
220
        tl->TLnext = NULL;
 
221
        tl->TLname = salloc (relname);
 
222
        tl->TLprefix = NULL;
 
223
        tl->TLlist = NULL;
 
224
        tl->TLscan = NULL;
 
225
        tl->TLhost = NULL;
 
226
        nextrel = NULL;
 
227
        args = skipover (args," \t");
 
228
        while (*(arg=nxtarg(&args," \t="))) {
 
229
                for (opno = 0; options[opno] != NULL; opno++)
 
230
                        if (strcmp (arg,options[opno]) == 0)
 
231
                                break;
 
232
                if (options[opno] == NULL)
 
233
                        goaway ("Invalid release option %s for release %s",
 
234
                                arg,relname);
 
235
                option = (OPTION) opno;
 
236
                switch (option) {
 
237
                case ONEXT:
 
238
                        passdelim (&args,'=');
 
239
                        arg = nxtarg (&args," \t");
 
240
                        nextrel = salloc (arg);
 
241
                        break;
 
242
                case OPREFIX:
 
243
                        passdelim (&args,'=');
 
244
                        arg = nxtarg (&args," \t");
 
245
                        tl->TLprefix = salloc (arg);
 
246
                        break;
 
247
                case OLIST:
 
248
                        passdelim (&args,'=');
 
249
                        arg = nxtarg (&args," \t");
 
250
                        tl->TLlist = salloc (arg);
 
251
                        break;
 
252
                case OSCAN:
 
253
                        passdelim (&args,'=');
 
254
                        arg = nxtarg (&args," \t");
 
255
                        tl->TLscan = salloc (arg);
 
256
                        break;
 
257
                case OHOST:
 
258
                        passdelim (&args,'=');
 
259
                        arg = nxtarg (&args," \t");
 
260
                        tl->TLhost = salloc (arg);
 
261
                        break;
 
262
                }
 
263
        }
 
264
        return (nextrel);
 
265
}
 
266
 
 
267
getrelease (release)
 
268
char *release;
 
269
{
 
270
        TREELIST *tl;
 
271
        char buf[STRINGLENGTH];
 
272
        char *p,*q;
 
273
        int rewound;
 
274
        FILE *f;
 
275
 
 
276
        if (release == NULL)
 
277
                release = salloc (DEFRELEASE);
 
278
        listTL = NULL;
 
279
 
 
280
        (void) sprintf (buf,FILERELEASES,collname);
 
281
        f = fopen (buf,"r");
 
282
        if (f != NULL) {
 
283
                rewound = TRUE;
 
284
                for (;;) {
 
285
                        p = fgets (buf,STRINGLENGTH,f);
 
286
                        if (p == NULL) {
 
287
                                if (rewound)
 
288
                                        break;
 
289
                                rewind (f);
 
290
                                rewound = TRUE;
 
291
                                continue;
 
292
                        }
 
293
                        q = index (p,'\n');
 
294
                        if (q)  *q = 0;
 
295
                        if (index ("#;:",*p))  continue;
 
296
                        q = nxtarg (&p," \t");
 
297
                        if (strcmp (q,release) != 0)
 
298
                                continue;
 
299
                        release = parserelease (&tl,release,p);
 
300
                        if (tl->TLprefix == NULL)
 
301
                                tl->TLprefix = prefix;
 
302
                        else if (chdir (tl->TLprefix) < 0)
 
303
                                return (FALSE);
 
304
                        else
 
305
                                (void) chdir (basedir);
 
306
                        tl->TLnext = listTL;
 
307
                        listTL = tl;
 
308
                        if (release == NULL)
 
309
                                break;
 
310
                        rewound = FALSE;
 
311
                }
 
312
                (void) fclose (f);
 
313
        }
 
314
        if (release == NULL)
 
315
                return (TRUE);
 
316
        if (strcmp (release,DEFRELEASE) != 0)
 
317
                return (FALSE);
 
318
        (void) parserelease (&tl,release,"");
 
319
        tl->TLprefix = prefix;
 
320
        tl->TLnext = listTL;
 
321
        listTL = tl;
 
322
        return (TRUE);
 
323
}
 
324
 
 
325
makescanlists ()
 
326
{
 
327
        TREELIST *tl;
 
328
        char buf[STRINGLENGTH];
 
329
        char *p,*q;
 
330
        FILE *f;
 
331
        char *saveprefix = prefix;
 
332
        int count = 0;
 
333
 
 
334
        (void) sprintf (buf,FILERELEASES,collname);
 
335
        f = fopen (buf,"r");
 
336
        if (f != NULL) {
 
337
                while (p = fgets (buf,STRINGLENGTH,f)) {
 
338
                        q = index (p,'\n');
 
339
                        if (q)  *q = 0;
 
340
                        if (index ("#;:",*p))  continue;
 
341
                        q = nxtarg (&p," \t");
 
342
                        (void) parserelease (&tl,q,p);
 
343
                        if ((prefix = tl->TLprefix) == NULL)
 
344
                                prefix = saveprefix;
 
345
                        if (prefix != NULL) {
 
346
                                if (chdir (prefix) < 0)
 
347
                                        goaway ("Can't chdir to %s",prefix);
 
348
                                (void) chdir (basedir);
 
349
                        }
 
350
                        makescan (tl->TLlist,tl->TLscan);
 
351
                        free ((char *)tl);
 
352
                        count++;
 
353
                }
 
354
                (void) fclose (f);
 
355
        }
 
356
        if (count == 0)
 
357
                makescan ((char *)NULL,(char *)NULL);
 
358
}
 
359
 
 
360
static
 
361
scanone (t)
 
362
register TREE *t;
 
363
{
 
364
        register TREE *newt;
 
365
 
 
366
        if (newonly && (t->Tflags&FNEW) == 0)
 
367
                return (SCMOK);
 
368
        newt = Tinsert (&listT,t->Tname,FALSE);
 
369
        if (newt == NULL)
 
370
                return (SCMOK);
 
371
        newt->Tmode = t->Tmode;
 
372
        newt->Tflags = t->Tflags;
 
373
        newt->Tmtime = t->Tmtime;
 
374
        return (SCMOK);
 
375
}
 
376
 
 
377
getscanlists ()
 
378
{
 
379
        TREELIST *tl,*stl;
 
380
 
 
381
        stl = listTL;
 
382
        listTL = NULL;
 
383
        while ((tl = stl) != NULL) {
 
384
                prefix = tl->TLprefix;
 
385
                getscan (tl->TLlist,tl->TLscan);
 
386
                tl->TLtree = listT;
 
387
                stl = tl->TLnext;
 
388
                tl->TLnext = listTL;
 
389
                listTL = tl;
 
390
        }
 
391
        listT = NULL;
 
392
        for (tl = listTL; tl != NULL; tl = tl->TLnext)
 
393
                (void) Tprocess (tl->TLtree,scanone);
 
394
}
 
395
 
 
396
static
 
397
makescan (listfile,scanfile)
 
398
char *listfile,*scanfile;
 
399
{
 
400
        listT = NULL;
 
401
        chkscanfile (scanfile);         /* can we can write a scan file? */
 
402
        doscan (listfile);              /* read list file and scan disk */
 
403
        makescanfile (scanfile);        /* record names in scan file */
 
404
        Tfree (&listT);                 /* free file list tree */
 
405
}
 
406
 
 
407
static
 
408
getscan (listfile,scanfile)
 
409
char *listfile,*scanfile;
 
410
{
 
411
        listT = NULL;
 
412
        if (!getscanfile(scanfile)) {   /* check for pre-scanned file list */
 
413
                scantime = time ((long *)NULL);
 
414
                doscan (listfile);      /* read list file and scan disk */
 
415
        }
 
416
}
 
417
 
 
418
static
 
419
doscan (listfile)
 
420
        char *listfile;
 
421
{
 
422
        char buf[STRINGLENGTH];
 
423
        int listone ();
 
424
 
 
425
        upgT = NULL;
 
426
        flagsT = NULL;
 
427
        omitT = NULL;
 
428
        omanyT = NULL;
 
429
        execT = NULL;
 
430
        symT = NULL;
 
431
        rsymT = NULL;
 
432
        if (listfile == NULL)
 
433
                listfile = FILELISTDEF;
 
434
        (void) sprintf (buf,FILELIST,collname,listfile);
 
435
        readlistfile (buf);             /* get contents of list file */
 
436
        (void) Tprocess (upgT,listone); /* build list of files specified */
 
437
        cdprefix ((char *)NULL);
 
438
        Tfree (&upgT);
 
439
        Tfree (&flagsT);
 
440
        Tfree (&omitT);
 
441
        Tfree (&omanyT);
 
442
        Tfree (&execT);
 
443
        Tfree (&symT);
 
444
        Tfree (&rsymT);
 
445
}
 
446
 
 
447
static
 
448
readlistfile (fname)
 
449
char *fname;
 
450
{
 
451
        char buf[STRINGLENGTH],*p;
 
452
        register char *q,*r;
 
453
        register FILE *f;
 
454
        register int ltn,n,i,flags;
 
455
        register TREE **t;
 
456
        register LISTTYPE lt;
 
457
        char *speclist[SPECNUMBER];
 
458
 
 
459
        f = fopen (fname,"r");
 
460
        if (f == NULL)  goaway ("Can't read list file %s",fname);
 
461
        cdprefix (prefix);
 
462
        while (p = fgets (buf,STRINGLENGTH,f)) {
 
463
                if (q = index (p,'\n'))  *q = '\0';
 
464
                if (index ("#;:",*p))  continue;
 
465
                q = nxtarg (&p," \t");
 
466
                if (*q == '\0') continue;
 
467
                for (ltn = 0; ltname[ltn] && strcmp(q,ltname[ltn]) != 0; ltn++);
 
468
                if (ltname[ltn] == NULL)
 
469
                        goaway ("Invalid list file keyword %s",q);
 
470
                lt = (LISTTYPE) ltn;
 
471
                flags = 0;
 
472
                switch (lt) {
 
473
                case LUPGRADE:
 
474
                        t = &upgT;
 
475
                        break;
 
476
                case LBACKUP:
 
477
                        t = &flagsT;
 
478
                        flags = FBACKUP;
 
479
                        break;
 
480
                case LNOACCT:
 
481
                        t = &flagsT;
 
482
                        flags = FNOACCT;
 
483
                        break;
 
484
                case LSYMLINK:
 
485
                        t = &symT;
 
486
                        break;
 
487
                case LRSYMLINK:
 
488
                        t = &rsymT;
 
489
                        break;
 
490
                case LOMIT:
 
491
                        t = &omitT;
 
492
                        break;
 
493
                case LOMITANY:
 
494
                        t = &omanyT;
 
495
                        break;
 
496
                case LALWAYS:
 
497
                        t = &upgT;
 
498
                        flags = FALWAYS;
 
499
                        break;
 
500
                case LINCLUDE:
 
501
                        while (*(q=nxtarg(&p," \t"))) {
 
502
                                cdprefix ((char *)NULL);
 
503
                                n = expand (q,speclist,SPECNUMBER);
 
504
                                for (i = 0; i < n && i < SPECNUMBER; i++) {
 
505
                                        readlistfile (speclist[i]);
 
506
                                        cdprefix ((char *)NULL);
 
507
                                        free (speclist[i]);
 
508
                                }
 
509
                                cdprefix (prefix);
 
510
                        }
 
511
                        continue;
 
512
                case LEXECUTE:
 
513
                        r = p = q = skipover (p," \t");
 
514
                        do {
 
515
                                q = p = skipto (p," \t(");
 
516
                                p = skipover (p," \t");
 
517
                        } while (*p != '(' && *p != '\0');
 
518
                        if (*p++ == '(') {
 
519
                                *q = '\0';
 
520
                                do {
 
521
                                        q = nxtarg (&p," \t)");
 
522
                                        if (*q == 0)
 
523
                                                _argbreak = ')';
 
524
                                        else
 
525
                                                expTinsert (q,&execT,0,r);
 
526
                                } while (_argbreak != ')');
 
527
                                continue;
 
528
                        }
 
529
                        /* fall through */
 
530
                default:
 
531
                        goaway ("Error in handling list file keyword %d",ltn);
 
532
                }
 
533
                while (*(q=nxtarg(&p," \t"))) {
 
534
                        if (lt == LOMITANY)
 
535
                                (void) Tinsert (t,q,FALSE);
 
536
                        else
 
537
                                expTinsert (q,t,flags,(char *)NULL);
 
538
                }
 
539
        }
 
540
        (void) fclose (f);
 
541
}
 
542
 
 
543
static
 
544
expTinsert (p,t,flags,exec)
 
545
char *p;
 
546
TREE **t;
 
547
int flags;
 
548
char *exec;
 
549
{
 
550
        register int n, i;
 
551
        register TREE *newt;
 
552
        char *speclist[SPECNUMBER];
 
553
        char buf[STRINGLENGTH];
 
554
 
 
555
        n = expand (p,speclist,SPECNUMBER);
 
556
        for (i = 0; i < n && i < SPECNUMBER; i++) {
 
557
                newt = Tinsert (t,speclist[i],TRUE);
 
558
                newt->Tflags |= flags;
 
559
                if (exec) {
 
560
                        (void) sprintf (buf,exec,speclist[i]);
 
561
                        (void) Tinsert (&newt->Texec,buf,FALSE);
 
562
                }
 
563
                free (speclist[i]);
 
564
        }
 
565
}
 
566
 
 
567
static
 
568
listone (t)             /* expand and add one name from upgrade list */
 
569
TREE *t;
 
570
{
 
571
        listentry(t->Tname,t->Tname,(char *)NULL,(t->Tflags&FALWAYS) != 0);
 
572
        return (SCMOK);
 
573
}
 
574
 
 
575
static
 
576
listentry(name,fullname,updir,always)
 
577
register char *name, *fullname, *updir;
 
578
int always;
 
579
{
 
580
        struct stat statbuf;
 
581
        int link = 0;
 
582
        int omitanyone ();
 
583
 
 
584
        if (Tlookup (refuseT,fullname))  return;
 
585
        if (!always) {
 
586
                if (Tsearch (omitT,fullname))  return;
 
587
                if (Tprocess (omanyT,omitanyone,fullname) != SCMOK)
 
588
                        return;
 
589
        }
 
590
        if (lstat(name,&statbuf) < 0)
 
591
                return;
 
592
        if ((statbuf.st_mode&S_IFMT) == S_IFLNK) {
 
593
                if (Tsearch (symT,fullname)) {
 
594
                        listname (fullname,&statbuf);
 
595
                        return;
 
596
                }
 
597
                if (Tlookup (rsymT,fullname)) {
 
598
                        listname (fullname,&statbuf);
 
599
                        return;
 
600
                }
 
601
                if (updir) link++;
 
602
                if (stat(name,&statbuf) < 0) return;
 
603
        }
 
604
        if ((statbuf.st_mode&S_IFMT) == S_IFDIR) {
 
605
                if (access(name,R_OK|X_OK) < 0) return;
 
606
                if (chdir(name) < 0) return;
 
607
                listname (fullname,&statbuf);
 
608
                if (trace) {
 
609
                        printf ("Scanning directory %s\n",fullname);
 
610
                        (void) fflush (stdout);
 
611
                }
 
612
                listdir (fullname,always);
 
613
                if (updir == 0 || link) {
 
614
                        (void) chdir (basedir);
 
615
                        if (prefix) (void) chdir (prefix);
 
616
                        if (updir && *updir) (void) chdir (updir);
 
617
                } else
 
618
                        (void) chdir ("..");
 
619
                return;
 
620
        }
 
621
        if (access(name,R_OK) < 0) return;
 
622
        listname (fullname,&statbuf);
 
623
}
 
624
 
 
625
static
 
626
listname (name,st)
 
627
register char *name;
 
628
register struct stat *st;
 
629
{
 
630
        register TREE *t,*ts;
 
631
        register int new;
 
632
        register TREELIST *tl;
 
633
 
 
634
        new = st->st_ctime > lasttime;
 
635
        if (newonly && !new) {
 
636
                for (tl = listTL; tl != NULL; tl = tl->TLnext)
 
637
                        if (ts = Tsearch (tl->TLtree,name))
 
638
                                ts->Tflags &= ~FNEW;
 
639
                return;
 
640
        }
 
641
        t = Tinsert (&listT,name,FALSE);
 
642
        if (t == NULL)  return;
 
643
        t->Tmode = st->st_mode;
 
644
        t->Tctime = st->st_ctime;
 
645
        t->Tmtime = st->st_mtime;
 
646
        if (new)  t->Tflags |= FNEW;
 
647
        if (ts = Tsearch (flagsT,name))
 
648
                t->Tflags |= ts->Tflags;
 
649
        if (ts = Tsearch (execT,name)) {
 
650
                t->Texec = ts->Texec;
 
651
                ts->Texec = NULL;
 
652
        }
 
653
}
 
654
 
 
655
static
 
656
listdir (name,always)           /* expand directory */
 
657
char *name;
 
658
int always;
 
659
{
 
660
        struct direct *dentry;
 
661
        register DIR *dirp;
 
662
        char ename[STRINGLENGTH],newname[STRINGLENGTH],filename[STRINGLENGTH];
 
663
        register char *p,*newp;
 
664
        register int i;
 
665
 
 
666
        dirp = opendir (".");
 
667
        if (dirp == 0) return;  /* unreadable: probably protected */
 
668
 
 
669
        p = name;               /* punt leading ./ and trailing / */
 
670
        newp = newname;
 
671
        if (p[0] == '.' && p[1] == '/') {
 
672
                p += 2;
 
673
                while (*p == '/') p++;
 
674
        }
 
675
        while (*newp++ = *p++) ;        /* copy string */
 
676
        --newp;                         /* trailing null */
 
677
        while (newp > newname && newp[-1] == '/') --newp; /* trailing / */
 
678
        *newp = 0;
 
679
        if (strcmp (newname,".") == 0) newname[0] = 0;  /* "." ==> "" */
 
680
 
 
681
        while (dentry=readdir(dirp)) {
 
682
                if (dentry->d_ino == 0) continue;
 
683
                if (strcmp(dentry->d_name,".") == 0) continue;
 
684
                if (strcmp(dentry->d_name,"..") == 0) continue;
 
685
                for (i=0; i<=MAXNAMLEN && dentry->d_name[i]; i++)
 
686
                        ename[i] = dentry->d_name[i];
 
687
                ename[i] = 0;
 
688
                if (*newname)
 
689
                        (void) sprintf (filename,"%s/%s",newname,ename);
 
690
                else
 
691
                        (void) strcpy (filename,ename);
 
692
                listentry(ename,filename,newname,always);
 
693
        }
 
694
        closedir (dirp);
 
695
}
 
696
 
 
697
static
 
698
omitanyone (t,filename)
 
699
TREE *t;
 
700
char **filename;
 
701
{
 
702
        if (anyglob (t->Tname,*filename))
 
703
                return (SCMERR);
 
704
        return (SCMOK);
 
705
}
 
706
 
 
707
static
 
708
anyglob (pattern,match)
 
709
char *pattern,*match;
 
710
{
 
711
        register char *p,*m;
 
712
        register char *pb,*pe;
 
713
 
 
714
        p = pattern; 
 
715
        m = match;
 
716
        while (*m && *p == *m ) { 
 
717
                p++; 
 
718
                m++; 
 
719
        }
 
720
        if (*p == '\0' && *m == '\0')
 
721
                return (TRUE);
 
722
        switch (*p++) {
 
723
        case '*':
 
724
                for (;;) {
 
725
                        if (*p == '\0')
 
726
                                return (TRUE);
 
727
                        if (*m == '\0')
 
728
                                return (*p == '\0');
 
729
                        if (anyglob (p,++m))
 
730
                                return (TRUE);
 
731
                }
 
732
        case '?':
 
733
                return (anyglob (p,++m));
 
734
        case '[':
 
735
                pb = p;
 
736
                while (*(++p) != ']')
 
737
                        if (*p == '\0')
 
738
                                return (FALSE);
 
739
                pe = p;
 
740
                for (p = pb + 1; p != pe; p++) {
 
741
                        switch (*p) {
 
742
                        case '-':
 
743
                                if (p == pb && *m == '-') {
 
744
                                        p = pe + 1;
 
745
                                        return (anyglob (p,++m));
 
746
                                }
 
747
                                if (p == pb)
 
748
                                        continue;
 
749
                                if ((p + 1) == pe)
 
750
                                        return (FALSE);
 
751
                                if (*m > *(p - 1) &&
 
752
                                    *m <= *(p + 1)) {
 
753
                                        p = pe + 1;
 
754
                                        return (anyglob (p,++m));
 
755
                                }
 
756
                                continue;
 
757
                        default:
 
758
                                if (*m == *p) {
 
759
                                        p = pe + 1;
 
760
                                        return (anyglob (p,++m));
 
761
                                }
 
762
                        }
 
763
                }
 
764
                return (FALSE);
 
765
        default:
 
766
                return (FALSE);
 
767
        }
 
768
}
 
769
 
 
770
/*****************************************
 
771
 ***    R E A D   S C A N   F I L E    ***
 
772
 *****************************************/
 
773
 
 
774
static
 
775
int getscanfile (scanfile)
 
776
char *scanfile;
 
777
{
 
778
        char buf[STRINGLENGTH];
 
779
        struct stat sbuf;
 
780
        register FILE *f;
 
781
        TREE ts;
 
782
        register char *p,*q;
 
783
        register TREE *tmp, *t = NULL;
 
784
        register notwanted;
 
785
        register TREELIST *tl;
 
786
 
 
787
        if (scanfile == NULL)
 
788
                scanfile = FILESCANDEF;
 
789
        (void) sprintf (buf,FILESCAN,collname,scanfile);
 
790
        if (stat(buf,&sbuf) < 0)
 
791
                return (FALSE);
 
792
        if ((f = fopen (buf,"r")) == NULL)
 
793
                return (FALSE);
 
794
        if ((p = fgets (buf,STRINGLENGTH,f)) == NULL) {
 
795
                (void) fclose (f);
 
796
                return (FALSE);
 
797
        }
 
798
        if (q = index (p,'\n'))  *q = '\0';
 
799
        if (*p++ != 'V') {
 
800
                (void) fclose (f);
 
801
                return (FALSE);
 
802
        }
 
803
        if (atoi (p) != SCANVERSION) {
 
804
                (void) fclose (f);
 
805
                return (FALSE);
 
806
        }
 
807
        scantime = sbuf.st_mtime;       /* upgrade time is time of supscan,
 
808
                                         * i.e. time of creation of scanfile */
 
809
        if (newonly && scantime == lasttime) {
 
810
                (void) fclose (f);
 
811
                return (TRUE);
 
812
        }
 
813
        notwanted = FALSE;
 
814
        while (p = fgets (buf,STRINGLENGTH,f)) {
 
815
                q = index (p,'\n');
 
816
                if (q)  *q = 0;
 
817
                ts.Tflags = 0;
 
818
                if (*p == 'X') {
 
819
                        if (notwanted)  continue;
 
820
                        if (t == NULL)
 
821
                                goaway ("scanfile format inconsistant");
 
822
                        (void) Tinsert (&t->Texec,++p,FALSE);
 
823
                        continue;
 
824
                }
 
825
                notwanted = FALSE;
 
826
                if (*p == 'B') {
 
827
                        p++;
 
828
                        ts.Tflags |= FBACKUP;
 
829
                }
 
830
                if (*p == 'N') {
 
831
                        p++;
 
832
                        ts.Tflags |= FNOACCT;
 
833
                }
 
834
                if ((q = index (p,' ')) == NULL)
 
835
                        goaway ("scanfile format inconsistant");
 
836
                *q++ = '\0';
 
837
                ts.Tmode = atoo (p);
 
838
                p = q;
 
839
                if ((q = index (p,' ')) == NULL)
 
840
                        goaway ("scanfile format inconsistant");
 
841
                *q++ = '\0';
 
842
                ts.Tctime = atoi (p);
 
843
                p = q;
 
844
                if ((q = index (p,' ')) == NULL)
 
845
                        goaway ("scanfile format inconsistant");
 
846
                *q++ = 0;
 
847
                ts.Tmtime = atoi (p);
 
848
                if (ts.Tctime > lasttime)
 
849
                        ts.Tflags |= FNEW;
 
850
                else if (newonly) {
 
851
                        for (tl = listTL; tl != NULL; tl = tl->TLnext)
 
852
                                if (tmp = Tsearch (tl->TLtree,q))
 
853
                                        tmp->Tflags &= ~FNEW;
 
854
                        notwanted = TRUE;
 
855
                        continue;
 
856
                }
 
857
                if (Tlookup (refuseT,q)) {
 
858
                        notwanted = TRUE;
 
859
                        continue;
 
860
                }
 
861
                t = Tinsert (&listT,q,TRUE);
 
862
                t->Tmode = ts.Tmode;
 
863
                t->Tflags = ts.Tflags;
 
864
                t->Tctime = ts.Tctime;
 
865
                t->Tmtime = ts.Tmtime;
 
866
        }
 
867
        (void) fclose (f);
 
868
        return (TRUE);
 
869
}
 
870
 
 
871
/*******************************************
 
872
 ***    W R I T E   S C A N   F I L E    ***
 
873
 *******************************************/
 
874
 
 
875
static chkscanfile (scanfile)
 
876
char *scanfile;
 
877
{
 
878
        char tname[STRINGLENGTH], fname[STRINGLENGTH];
 
879
        FILE *f;
 
880
 
 
881
        if (scanfile == NULL)
 
882
                scanfile = FILESCANDEF;
 
883
        (void) sprintf (fname,FILESCAN,collname,scanfile);
 
884
        (void) sprintf (tname,"%s.temp",fname);
 
885
        if (NULL == (f = fopen (tname, "w")))
 
886
                goaway ("Can't test scan file temp %s for %s",tname,collname);
 
887
        else {
 
888
                (void) unlink (tname);
 
889
                (void) fclose (f);
 
890
        }
 
891
}
 
892
 
 
893
static makescanfile (scanfile)
 
894
char *scanfile;
 
895
{
 
896
        char tname[STRINGLENGTH],fname[STRINGLENGTH];
 
897
        struct timeval tbuf[2];
 
898
        FILE *scanF;                    /* output file for scanned file list */
 
899
        int recordone ();
 
900
 
 
901
        if (scanfile == NULL)
 
902
                scanfile = FILESCANDEF;
 
903
        (void) sprintf (fname,FILESCAN,collname,scanfile);
 
904
        (void) sprintf (tname,"%s.temp",fname);
 
905
        scanF = fopen (tname,"w");
 
906
        if (scanF == NULL)
 
907
                goaway ("Can't write scan file temp %s for %s",tname,collname);
 
908
        fprintf (scanF,"V%d\n",SCANVERSION);
 
909
        (void) Tprocess (listT,recordone,scanF);
 
910
        (void) fclose (scanF);
 
911
        if (rename (tname,fname) < 0)
 
912
                goaway ("Can't change %s to %s",tname,fname);
 
913
        (void) unlink (tname);
 
914
        tbuf[0].tv_sec = time((long *)NULL);  tbuf[0].tv_usec = 0;
 
915
        tbuf[1].tv_sec = scantime;  tbuf[1].tv_usec = 0;
 
916
        (void) utimes (fname,tbuf);
 
917
}
 
918
 
 
919
static
 
920
recordone (t,scanF)
 
921
TREE *t;
 
922
FILE **scanF;
 
923
{
 
924
        int recordexec ();
 
925
 
 
926
        if (t->Tflags&FBACKUP)  fprintf (*scanF,"B");
 
927
        if (t->Tflags&FNOACCT)  fprintf (*scanF,"N");
 
928
        fprintf (*scanF,"%o %d %d %s\n",
 
929
                t->Tmode,t->Tctime,t->Tmtime,t->Tname);
 
930
        (void) Tprocess (t->Texec,recordexec,*scanF);
 
931
        return (SCMOK);
 
932
}
 
933
 
 
934
static
 
935
recordexec (t,scanF)
 
936
TREE *t;
 
937
FILE **scanF;
 
938
{
 
939
        fprintf(*scanF,"X%s\n",t->Tname);
 
940
        return (SCMOK);
 
941
}
 
942
 
 
943
cdprefix (prefix)
 
944
char *prefix;
 
945
{
 
946
        static char *curprefix = NULL;
 
947
 
 
948
        if (curprefix == NULL) {
 
949
                if (prefix == NULL)
 
950
                        return;
 
951
                (void) chdir (prefix);
 
952
                curprefix = prefix;
 
953
                return;
 
954
        }
 
955
        if (prefix == NULL) {
 
956
                (void) chdir (basedir);
 
957
                curprefix = NULL;
 
958
                return;
 
959
        }
 
960
        if (prefix == curprefix)
 
961
                return;
 
962
        if (strcmp (prefix, curprefix) == 0) {
 
963
                curprefix = prefix;
 
964
                return;
 
965
        }
 
966
        (void) chdir (basedir);
 
967
        (void) chdir (prefix);
 
968
        curprefix = prefix;
 
969
}