|
|
1.1 root 1: /* $Source: /src386/usr/bin/pax/namelist.c,v $
2: *
3: * $Revision: 1.1 $
4: *
5: * namelist.c - track filenames given as arguments to tar/cpio/pax
6: *
7: * DESCRIPTION
8: *
9: * Arguments may be regular expressions, therefore all agurments will
10: * be treated as if they were regular expressions, even if they are
11: * not.
12: *
13: * AUTHOR
14: *
15: * Mark H. Colburn, NAPS International ([email protected])
16: *
17: * Sponsored by The USENIX Association for public distribution.
18: *
19: * Copyright (c) 1989 Mark H. Colburn.
20: * All rights reserved.
21: *
22: * Redistribution and use in source and binary forms are permitted
23: * provided that the above copyright notice is duplicated in all such
24: * forms and that any documentation, advertising materials, and other
25: * materials related to such distribution and use acknowledge that the
26: * software was developed by Mark H. Colburn and sponsored by The
27: * USENIX Association.
28: *
29: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
30: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
31: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
32: *
33: * $Log: namelist.c,v $
34: * Revision 1.1 92/08/28 08:02:19 bin
35: * Initial revision
36: *
37: * Revision 1.1 89/02/14 16:48:02 jep
38: * Initial revision
39: *
40: * Revision 1.1 88/12/23 18:02:17 mark
41: * Initial revision
42: *
43: */
44:
45: #ifndef lint
46: static char *ident = "$Id: namelist.c,v 1.1 92/08/28 08:02:19 bin Exp Locker: bin $";
47: static char *copyright = "Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.\n";
48: #endif /* ! lint */
49:
50:
51: /* Headers */
52: #include "pax.h"
53:
54:
55: /* Type Definitions */
56:
57: /*
58: * Structure for keeping track of filenames and lists thereof.
59: */
60: struct nm_list {
61: struct nm_list *next;
62: short length; /* cached strlen(name) */
63: char found; /* A matching file has been found */
64: char firstch; /* First char is literally matched */
65: char regexp; /* regexp pattern for item */
66: char name[1]; /* name of file or rexexp */
67: };
68:
69: struct dirinfo {
70: char dirname[PATH_MAX + 1]; /* name of directory */
71: OFFSET where; /* current location in directory */
72: struct dirinfo *next;
73: };
74:
75:
76: /* Static Variables */
77:
78: static struct dirinfo *stack_head = (struct dirinfo *)NULL;
79:
80:
81: /* Function Prototypes */
82:
83: #ifndef __STDC__
84:
85: static void pushdir();
86: static struct dirinfo *popdir();
87:
88: #else
89:
90: static void pushdir(struct dirinfo *info);
91: static struct dirinfo *popdir(void);
92:
93: #endif
94:
95:
96: /* Internal Identifiers */
97:
98: static struct nm_list *namelast; /* Points to last name in list */
99: static struct nm_list *namelist; /* Points to first name in list */
100:
101:
102: /* addname - add a name to the namelist.
103: *
104: * DESCRIPTION
105: *
106: * Addname adds the name given to the name list. Memory for the
107: * namelist structure is dynamically allocated. If the space for
108: * the structure cannot be allocated, then the program will exit
109: * the an out of memory error message and a non-zero return code
110: * will be returned to the caller.
111: *
112: * PARAMETERS
113: *
114: * char *name - A pointer to the name to add to the list
115: */
116:
117: #if __STDC__
118:
119: void add_name(char *name)
120:
121: #else
122:
123: void add_name(name)
124: char *name; /* pointer to name */
125:
126: #endif
127: {
128: int i; /* Length of string */
129: struct nm_list *p; /* Current struct pointer */
130:
131: i = strlen(name);
132: p = (struct nm_list *) malloc((unsigned) (i + sizeof(struct nm_list)));
133: if (!p) {
134: fatal("cannot allocate memory for namelist entry\n");
135: }
136: p->next = (struct nm_list *)NULL;
137: p->length = i;
138: strncpy(p->name, name, i);
139: p->name[i] = '\0'; /* Null term */
140: p->found = 0;
141: p->firstch = isalpha(name[0]);
142: if (strchr(name, '*') || strchr(name, '[') || strchr(name, '?')) {
143: p->regexp = 1;
144: }
145: if (namelast) {
146: namelast->next = p;
147: }
148: namelast = p;
149: if (!namelist) {
150: namelist = p;
151: }
152: }
153:
154:
155: /* name_match - match a name from an archive with a name from the namelist
156: *
157: * DESCRIPTION
158: *
159: * Name_match attempts to find a name pointed at by p in the namelist.
160: * If no namelist is available, then all filenames passed in are
161: * assumed to match the filename criteria. Name_match knows how to
162: * match names with regular expressions, etc.
163: *
164: * PARAMETERS
165: *
166: * char *p - the name to match
167: *
168: * RETURNS
169: *
170: * Returns 1 if the name is in the namelist, or no name list is
171: * available, otherwise returns 0
172: *
173: */
174:
175: #if __STDC__
176:
177: int name_match(char *p)
178:
179: #else
180:
181: int name_match(p)
182: char *p;
183:
184: #endif
185: {
186: struct nm_list *nlp;
187: int len;
188:
189: if ((nlp = namelist) == 0) {/* Empty namelist is easy */
190: return (1);
191: }
192: len = strlen(p);
193: for (; nlp != 0; nlp = nlp->next) {
194: /* If first chars don't match, quick skip */
195: if (nlp->firstch && nlp->name[0] != p[0]) {
196: continue;
197: }
198: /* Regular expressions */
199: if (nlp->regexp) {
200: if (wildmat(nlp->name, p)) {
201: nlp->found = 1; /* Remember it matched */
202: return (1); /* We got a match */
203: }
204: continue;
205: }
206: /* Plain Old Strings */
207: if (nlp->length <= len /* Archive len >= specified */
208: && (p[nlp->length] == '\0' || p[nlp->length] == '/')
209: && strncmp(p, nlp->name, nlp->length) == 0) {
210: /* Name compare */
211: nlp->found = 1; /* Remember it matched */
212: return (1); /* We got a match */
213: }
214: }
215: return (0);
216: }
217:
218:
219: /* names_notfound - print names of files in namelist that were not found
220: *
221: * DESCRIPTION
222: *
223: * Names_notfound scans through the namelist for any files which were
224: * named, but for which a matching file was not processed by the
225: * archive. Each of the files is listed on the standard error.
226: *
227: */
228:
229: #if __STDC__
230:
231: void names_notfound(void)
232:
233: #else
234:
235: void names_notfound()
236:
237: #endif
238: {
239: struct nm_list *nlp;
240:
241: for (nlp = namelist; nlp != 0; nlp = nlp->next) {
242: if (!nlp->found) {
243: fprintf(stderr, "%s: %s not found in archive\n",
244: myname, nlp->name);
245: }
246: free(nlp);
247: }
248: namelist = (struct nm_list *)NULL;
249: namelast = (struct nm_list *)NULL;
250: }
251:
252:
253: /* name_init - set up to gather file names
254: *
255: * DESCRIPTION
256: *
257: * Name_init sets up the namelist pointers so that we may access the
258: * command line arguments. At least the first item of the command
259: * line (argv[0]) is assumed to be stripped off, prior to the
260: * name_init call.
261: *
262: * PARAMETERS
263: *
264: * int argc - number of items in argc
265: * char **argv - pointer to the command line arguments
266: */
267:
268: #if __STDC__
269:
270: void name_init(int argc, char **argv)
271:
272: #else
273:
274: void name_init(argc, argv)
275: int argc;
276: char **argv;
277:
278: #endif
279: {
280: /* Get file names from argv, after options. */
281: n_argc = argc;
282: n_argv = argv;
283: }
284:
285:
286: /* name_next - get the next name from argv or the name file.
287: *
288: * DESCRIPTION
289: *
290: * Name next finds the next name which is to be processed in the
291: * archive. If the named file is a directory, then the directory
292: * is recursively traversed for additional file names. Directory
293: * names and locations within the directory are kept track of by
294: * using a directory stack. See the pushdir/popdir function for
295: * more details.
296: *
297: * The names come from argv, after options or from the standard input.
298: *
299: * PARAMETERS
300: *
301: * name - a pointer to a buffer of at least MAX_PATH + 1 bytes long;
302: * statbuf - a pointer to a stat structure
303: *
304: * RETURNS
305: *
306: * Returns -1 if there are no names left, (e.g. EOF), otherwise returns
307: * 0
308: */
309:
310: #if __STDC__
311:
312: int name_next(char *name, Stat *statbuf)
313:
314: #else
315:
316: int name_next(name, statbuf)
317: char *name;
318: Stat *statbuf;
319:
320: #endif
321: {
322: int err = -1;
323: static int in_subdir = 0;
324: int len;
325: struct dirent *d;
326: static struct dirinfo *curr_dir;
327: static DIR *dirp;
328:
329: do {
330: if (names_from_stdin) {
331: if (lineget(stdin, name) < 0) {
332: return (-1);
333: }
334: if (nameopt(name) < 0) {
335: continue;
336: }
337: } else {
338: if (in_subdir) {
339: if ((d = readdir(dirp)) != (struct dirent *)NULL) {
340: /* Skip . and .. */
341: if (strcmp(d->d_name, ".") == 0 ||
342: strcmp(d->d_name, "..") == 0) {
343: continue;
344: }
345: if (strlen(d->d_name) +
346: strlen(curr_dir->dirname) >= PATH_MAX) {
347: warn("name too long", d->d_name);
348: continue;
349: }
350: strcpy(name, curr_dir->dirname);
351: strcat(name, d->d_name);
352: } else {
353: closedir(dirp);
354: in_subdir--;
355: curr_dir = popdir();
356: if (in_subdir) {
357: errno = 0;
358: if ((dirp=opendir(curr_dir->dirname)) == (DIR *)NULL) {
359: warn(curr_dir->dirname, "error opening directory (1)");
360: in_subdir--;
361: }
362: seekdir(dirp, curr_dir->where);
363: }
364: continue;
365: }
366: } else if (optind >= n_argc) {
367: return (-1);
368: } else {
369: strcpy(name, n_argv[optind++]);
370: }
371: }
372: if ((err = LSTAT(name, statbuf)) < 0) {
373: warn(name, strerror());
374: continue;
375: }
376: if (!names_from_stdin && (statbuf->sb_mode & S_IFMT) == S_IFDIR) {
377: if (in_subdir) {
378: curr_dir->where = telldir(dirp);
379: pushdir(curr_dir);
380: closedir(dirp);
381: }
382: in_subdir++;
383:
384: /* Build new prototype name */
385: if ((curr_dir = (struct dirinfo *) mem_get(sizeof(struct dirinfo)))
386: == (struct dirinfo *)NULL) {
387: exit(2);
388: }
389: strcpy(curr_dir->dirname, name);
390: len = strlen(curr_dir->dirname);
391: while (len >= 1 && curr_dir->dirname[len - 1] == '/') {
392: len--; /* Delete trailing slashes */
393: }
394: curr_dir->dirname[len++] = '/'; /* Now add exactly one back */
395: curr_dir->dirname[len] = '\0';/* Make sure null-terminated */
396: curr_dir->where = 0;
397:
398: errno = 0;
399: do {
400: if ((dirp = opendir(curr_dir->dirname)) == (DIR *)NULL) {
401: warn(curr_dir->dirname, "error opening directory (2)");
402: if (in_subdir > 1) {
403: curr_dir = popdir();
404: }
405: in_subdir--;
406: err = -1;
407: continue;
408: } else {
409: seekdir(dirp, curr_dir->where);
410: }
411: } while (in_subdir && (! dirp));
412: }
413: } while (err < 0);
414: return (0);
415: }
416:
417:
418: /* name_gather - gather names in a list for scanning.
419: *
420: * DESCRIPTION
421: *
422: * Name_gather takes names from the command line and adds them to
423: * the name list.
424: *
425: * FIXME
426: *
427: * We could hash the names if we really care about speed here.
428: */
429:
430: #if __STDC__
431:
432: void name_gather(void)
433:
434: #else
435:
436: void name_gather()
437:
438: #endif
439: {
440: while (optind < n_argc) {
441: add_name(n_argv[optind++]);
442: }
443: }
444:
445:
446: /* pushdir - pushes a directory name on the directory stack
447: *
448: * DESCRIPTION
449: *
450: * The pushdir function puses the directory structure which is pointed
451: * to by "info" onto a stack for later processing. The information
452: * may be retrieved later with a call to popdir().
453: *
454: * PARAMETERS
455: *
456: * dirinfo *info - pointer to directory structure to save
457: */
458:
459: #if __STDC__
460:
461: static void pushdir(struct dirinfo *info)
462:
463: #else
464:
465: static void pushdir(info)
466: struct dirinfo *info;
467:
468: #endif
469: {
470: if (stack_head == (struct dirinfo *)NULL) {
471: stack_head = info;
472: stack_head->next = (struct dirinfo *)NULL;
473: } else {
474: info->next = stack_head;
475: stack_head = info;
476: }
477: }
478:
479:
480: /* popdir - pop a directory structure off the directory stack.
481: *
482: * DESCRIPTION
483: *
484: * The popdir function pops the most recently pushed directory
485: * structure off of the directory stack and returns it to the calling
486: * function.
487: *
488: * RETURNS
489: *
490: * Returns a pointer to the most recently pushed directory structure
491: * or NULL if the stack is empty.
492: */
493:
494: #if __STDC__
495:
496: static struct dirinfo *popdir(void)
497:
498: #else
499:
500: static struct dirinfo *popdir()
501:
502: #endif
503: {
504: struct dirinfo *tmp;
505:
506: if (stack_head == (struct dirinfo *)NULL) {
507: return((struct dirinfo *)NULL);
508: } else {
509: tmp = stack_head;
510: stack_head = stack_head->next;
511: }
512: return(tmp);
513: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.