home *** CD-ROM | disk | FTP | other *** search
- /* $Source: /u/mark/src/pax/RCS/namelist.c,v $
- *
- * $Revision: 1.6 $
- *
- * namelist.c - track filenames given as arguments to tar/cpio/pax
- *
- * DESCRIPTION
- *
- * Arguments may be regular expressions, therefore all agurments will
- * be treated as if they were regular expressions, even if they are
- * not.
- *
- * AUTHOR
- *
- * Mark H. Colburn, NAPS International (mark@jhereg.mn.org)
- *
- * Sponsored by The USENIX Association for public distribution.
- *
- * Copyright (c) 1989 Mark H. Colburn.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice is duplicated in all such
- * forms and that any documentation, advertising materials, and other
- * materials related to such distribution and use acknowledge that the
- * software was developed by Mark H. Colburn and sponsored by The
- * USENIX Association.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * $Log: namelist.c,v $
- * Revision 1.6 89/02/13 09:14:48 mark
- * Fixed problem with directory errors
- *
- * Revision 1.5 89/02/12 12:14:00 mark
- * Fixed misspellings
- *
- * Revision 1.4 89/02/12 11:25:19 mark
- * Modifications to compile and link cleanly under USG
- *
- * Revision 1.3 89/02/12 10:40:23 mark
- * Fixed casting problems
- *
- * Revision 1.2 89/02/12 10:04:57 mark
- * 1.2 release fixes
- *
- * Revision 1.1 88/12/23 18:02:17 mark
- * Initial revision
- *
- */
-
- #ifndef lint
- static char *ident = "$Id: namelist.c,v 1.6 89/02/13 09:14:48 mark Exp $";
- static char *copyright = "Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.\n";
- #endif /* ! lint */
-
-
- /* Headers */
-
- #include "pax.h"
-
-
- /* Type Definitions */
-
- /*
- * Structure for keeping track of filenames and lists thereof.
- */
- struct nm_list {
- struct nm_list *next;
- short length; /* cached strlen(name) */
- char found; /* A matching file has been found */
- char firstch; /* First char is literally matched */
- char regexp; /* regexp pattern for item */
- char name[1]; /* name of file or rexexp */
- };
-
- struct dirinfo {
- char dirname[PATH_MAX + 1]; /* name of directory */
- OFFSET where; /* current location in directory */
- struct dirinfo *next;
- };
-
-
- /* Static Variables */
-
- static struct dirinfo *stack_head = (struct dirinfo *)NULL;
-
-
- /* Function Prototypes */
-
- #ifndef __STDC__
-
- static void pushdir();
- static struct dirinfo *popdir();
-
- #else
-
- static void pushdir(struct dirinfo *info);
- static struct dirinfo *popdir(void);
-
- #endif
-
-
- /* Internal Identifiers */
-
- static struct nm_list *namelast = NULL; /* Points to last name in list */ /* Xn */
- static struct nm_list *namelist = NULL; /* Points to first name in list */ /* Xn */
-
-
- /* addname - add a name to the namelist.
- *
- * DESCRIPTION
- *
- * Addname adds the name given to the name list. Memory for the
- * namelist structure is dynamically allocated. If the space for
- * the structure cannot be allocated, then the program will exit
- * the an out of memory error message and a non-zero return code
- * will be returned to the caller.
- *
- * PARAMETERS
- *
- * char *name - A pointer to the name to add to the list
- */
-
- #ifdef __STDC__
-
- void add_name(char *name)
-
- #else
-
- void add_name(name)
- char *name; /* pointer to name */
-
- #endif
- {
- int i; /* Length of string */
- struct nm_list *p; /* Current struct pointer */
-
- #ifdef DF_TRACE_DEBUG
- printf("DF_TRACE_DEBUG: void add_name() in namelist.c\n");
- #endif
- i = strlen(name);
- p = (struct nm_list *) malloc((unsigned) (i + sizeof(struct nm_list)));
- if (!p) {
- fatal("cannot allocate memory for namelist entry\n");
- }
- p->next = (struct nm_list *)NULL;
- p->length = (short)i; /* Xn */
- strncpy(p->name, name, i);
- p->name[i] = '\0'; /* Null term */
- p->found = 0;
- p->firstch = (char)isalpha(name[0]); /* Xn */
- if (strchr(name, '*') || strchr(name, '[') || strchr(name, '?')) {
- p->regexp = 1;
- }
- if (namelast) {
- namelast->next = p;
- }
- namelast = p;
- if (!namelist) {
- namelist = p;
- }
- }
-
-
- /* name_match - match a name from an archive with a name from the namelist
- *
- * DESCRIPTION
- *
- * Name_match attempts to find a name pointed at by p in the namelist.
- * If no namelist is available, then all filenames passed in are
- * assumed to match the filename criteria. Name_match knows how to
- * match names with regular expressions, etc.
- *
- * PARAMETERS
- *
- * char *p - the name to match
- *
- * RETURNS
- *
- * Returns 1 if the name is in the namelist, or no name list is
- * available, otherwise returns 0
- *
- */
-
- #ifdef __STDC__
-
- int name_match(char *p)
-
- #else
-
- int name_match(p)
- char *p;
-
- #endif
- {
- struct nm_list *nlp;
- int len;
-
- #ifdef DF_TRACE_DEBUG
- printf("DF_TRACE_DEBUG: int name_match() in namelist.c\n");
- #endif
- if ((nlp = namelist) == 0) {/* Empty namelist is easy */
- return (1);
- }
- len = strlen(p);
- for (; nlp != 0; nlp = nlp->next) {
- /* If first chars don't match, quick skip */
- if (nlp->firstch && nlp->name[0] != p[0]) {
- continue;
- }
- /* Regular expressions */
- if (nlp->regexp) {
- if (wildmat(nlp->name, p)) {
- nlp->found = 1; /* Remember it matched */
- return (1); /* We got a match */
- }
- continue;
- }
- /* Plain Old Strings */
- if (nlp->length <= len /* Archive len >= specified */
- && (p[nlp->length] == '\0' || p[nlp->length] == '/')
- && strncmp(p, nlp->name, nlp->length) == 0) {
- /* Name compare */
- nlp->found = 1; /* Remember it matched */
- return (1); /* We got a match */
- }
- }
- return (0);
- }
-
-
- /* names_notfound - print names of files in namelist that were not found
- *
- * DESCRIPTION
- *
- * Names_notfound scans through the namelist for any files which were
- * named, but for which a matching file was not processed by the
- * archive. Each of the files is listed on the standard error.
- *
- */
-
- #ifdef __STDC__
-
- void names_notfound(void)
-
- #else
-
- void names_notfound()
-
- #endif
- {
- struct nm_list *nlp;
-
- #ifdef DF_TRACE_DEBUG
- printf("DF_TRACE_DEBUG: void names_notfound() in namelist.c\n");
- #endif
- for (nlp = namelist; nlp != 0; nlp = nlp->next) {
- if (!nlp->found) {
- fprintf(stderr, "%s: %s not found in archive\n",
- myname, nlp->name);
- }
- free(nlp);
- }
- namelist = (struct nm_list *)NULL;
- namelast = (struct nm_list *)NULL;
- }
-
-
- /* name_init - set up to gather file names
- *
- * DESCRIPTION
- *
- * Name_init sets up the namelist pointers so that we may access the
- * command line arguments. At least the first item of the command
- * line (argv[0]) is assumed to be stripped off, prior to the
- * name_init call.
- *
- * PARAMETERS
- *
- * int argc - number of items in argc
- * char **argv - pointer to the command line arguments
- */
-
- #ifdef __STDC__
-
- void name_init(int argc, char **argv)
-
- #else
-
- void name_init(argc, argv)
- int argc;
- char **argv;
-
- #endif
- {
- /* Get file names from argv, after options. */
- #ifdef DF_TRACE_DEBUG
- printf("DF_TRACE_DEBUG: void name_init() in namelist.c\n");
- #endif
- n_argc = argc;
- n_argv = argv;
- }
-
-
- /* name_next - get the next name from argv or the name file.
- *
- * DESCRIPTION
- *
- * Name next finds the next name which is to be processed in the
- * archive. If the named file is a directory, then the directory
- * is recursively traversed for additional file names. Directory
- * names and locations within the directory are kept track of by
- * using a directory stack. See the pushdir/popdir function for
- * more details.
- *
- * The names come from argv, after options or from the standard input.
- *
- * PARAMETERS
- *
- * name - a pointer to a buffer of at least MAX_PATH + 1 bytes long;
- * statbuf - a pointer to a stat structure
- *
- * RETURNS
- *
- * Returns -1 if there are no names left, (e.g. EOF), otherwise returns
- * 0
- */
-
- #ifdef __STDC__
-
- int name_next(char *name, Stat *statbuf)
-
- #else
-
- int name_next(name, statbuf)
- char *name;
- Stat *statbuf;
-
- #endif
- {
- int err = -1; /* Xn */
- static int in_subdir = 0; /* Xn */
- static DIR *dirp = NULL; /* Xn */
- struct dirent *d; /* Xn */
- static struct dirinfo *curr_dir = NULL; /* Xn */
- int len; /* Xn */
-
- do {
- #ifdef DF_TRACE_DEBUG
- printf("DF_TRACE_DEBUG: int name_next() in namelist.c\n");
- #endif
- if (names_from_stdin) {
- if (lineget(stdin, name) < 0) {
- return (-1);
- }
- if (nameopt(name) < 0) {
- continue;
- }
- } else {
- if (in_subdir) {
- if ((d = readdir(dirp)) != (struct dirent *)NULL) {
- /* Skip . and .. */
- if (strcmp(d->d_name, ".") == 0 ||
- strcmp(d->d_name, "..") == 0) {
- continue;
- }
- #ifdef DF_TRACE_DEBUG
- printf("DF_TRACE_DEBUG: strcmp() in namelist.c\n");
- #endif
- if (strlen(d->d_name) +
- strlen(curr_dir->dirname) >= PATH_MAX) {
- #ifdef DF_TRACE_DEBUG
- printf("DF_TRACE_DEBUG: strlen() in namelist.c\n");
- #endif
- warn("name too long", d->d_name);
- continue;
- }
- strcpy(name, curr_dir->dirname);
- strcat(name, d->d_name);
- } else {
- closedir(dirp);
- in_subdir--;
- curr_dir = popdir();
- if (in_subdir) {
- errno = 0;
- if ((dirp=opendir(curr_dir->dirname)) == (DIR *)NULL) {
- warn(curr_dir->dirname, "error opening directory (1)");
- in_subdir--;
- }
- seekdir(dirp, curr_dir->where);
- }
- continue;
- }
- } else if (optind >= n_argc) {
- return (-1);
- } else {
- strcpy(name, n_argv[optind++]);
- }
- }
- if ((err = LSTAT(name, statbuf)) < 0) {
- warn(name, strerror(errno)); /* Xn */
- continue;
- }
- #if 0
- (void) fprintf(stderr, "namelist.c/name_next - name: \"%s\"; statbuf->sb_stat.st_uid: %lu; statbuf->sb_stat.st_gid: %lu\n",
- name, (unsigned long) statbuf->sb_stat.st_uid, (unsigned long) statbuf->sb_stat.st_gid);
- (void) fflush(stderr);
- #endif /* Xn 1993-06-23 */
- if (!names_from_stdin && (statbuf->sb_mode & S_IFMT) == S_IFDIR) {
- if (in_subdir) {
- curr_dir->where = telldir(dirp);
- pushdir(curr_dir);
- closedir(dirp);
- }
- in_subdir++;
-
- /* Build new prototype name */
- if ((curr_dir = (struct dirinfo *) mem_get(sizeof(struct dirinfo)))
- == (struct dirinfo *)NULL) {
- #if 1 && WIN_NT
- if (ppid == (pid_t) 1 && globulation == 0)
- deglobulate();
- #endif
- exit(2);
- }
- strcpy(curr_dir->dirname, name);
- len = strlen(curr_dir->dirname);
- while (len >= 1 && curr_dir->dirname[len - 1] == '/') {
- len--; /* Delete trailing slashes */
- }
- curr_dir->dirname[len++] = '/'; /* Now add exactly one back */
- curr_dir->dirname[len] = '\0';/* Make sure null-terminated */
- curr_dir->where = 0;
-
- errno = 0;
- do {
- if ((dirp = opendir(curr_dir->dirname)) == (DIR *)NULL) {
- warn(curr_dir->dirname, "error opening directory (2)");
- if (in_subdir > 1) {
- curr_dir = popdir();
- }
- in_subdir--;
- err = -1;
- continue;
- } else {
- seekdir(dirp, curr_dir->where);
- }
- } while (in_subdir && (! dirp));
- }
- } while (err < 0);
- return (0);
- }
-
-
- /* name_gather - gather names in a list for scanning.
- *
- * DESCRIPTION
- *
- * Name_gather takes names from the command line and adds them to
- * the name list.
- *
- * FIXME
- *
- * We could hash the names if we really care about speed here.
- */
-
- #ifdef __STDC__
-
- void name_gather(void)
-
- #else
-
- void name_gather()
-
- #endif
- {
- #ifdef DF_TRACE_DEBUG
- printf("DF_TRACE_DEBUG: void name_gather() in namelist.c\n");
- #endif
- while (optind < n_argc) {
- add_name(n_argv[optind++]);
- }
- }
-
-
- /* pushdir - pushes a directory name on the directory stack
- *
- * DESCRIPTION
- *
- * The pushdir function puses the directory structure which is pointed
- * to by "info" onto a stack for later processing. The information
- * may be retrieved later with a call to popdir().
- *
- * PARAMETERS
- *
- * dirinfo *info - pointer to directory structure to save
- */
-
- #ifdef __STDC__
-
- static void pushdir(struct dirinfo *info)
-
- #else
-
- static void pushdir(info)
- struct dirinfo *info;
-
- #endif
- {
- #ifdef DF_TRACE_DEBUG
- printf("DF_TRACE_DEBUG: static void pushdir() in namelist.c\n");
- #endif
- if (stack_head == (struct dirinfo *)NULL) {
- stack_head = info;
- stack_head->next = (struct dirinfo *)NULL;
- } else {
- info->next = stack_head;
- stack_head = info;
- }
- }
-
-
- /* popdir - pop a directory structure off the directory stack.
- *
- * DESCRIPTION
- *
- * The popdir function pops the most recently pushed directory
- * structure off of the directory stack and returns it to the calling
- * function.
- *
- * RETURNS
- *
- * Returns a pointer to the most recently pushed directory structure
- * or NULL if the stack is empty.
- */
-
- #ifdef __STDC__
-
- static struct dirinfo *popdir(void)
-
- #else
-
- static struct dirinfo *popdir()
-
- #endif
- {
- struct dirinfo *tmp;
-
- #ifdef DF_TRACE_DEBUG
- printf("DF_TRACE_DEBUG: static struct dirinfo *popdir() in namelist.c\n");
- #endif
- if (stack_head == (struct dirinfo *)NULL) {
- return((struct dirinfo *)NULL);
- } else {
- tmp = stack_head;
- stack_head = stack_head->next;
- }
- return(tmp);
- }
-