summaryrefslogtreecommitdiff
path: root/sys/src/ape/cmd/pax/namelist.c
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/ape/cmd/pax/namelist.c
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/ape/cmd/pax/namelist.c')
-rwxr-xr-xsys/src/ape/cmd/pax/namelist.c523
1 files changed, 523 insertions, 0 deletions
diff --git a/sys/src/ape/cmd/pax/namelist.c b/sys/src/ape/cmd/pax/namelist.c
new file mode 100755
index 000000000..9c539d706
--- /dev/null
+++ b/sys/src/ape/cmd/pax/namelist.c
@@ -0,0 +1,523 @@
+/* $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 re; /* 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; /* Points to last name in list */
+static struct nm_list *namelist; /* Points to first name in list */
+
+
+/* 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 */
+
+ 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 = i;
+ strncpy(p->name, name, i);
+ p->name[i] = '\0'; /* Null term */
+ p->found = 0;
+ p->firstch = isalpha(name[0]);
+ if (strchr(name, '*') || strchr(name, '[') || strchr(name, '?')) {
+ p->re = 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;
+
+ 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->re) {
+ 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;
+
+ 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. */
+ 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;
+ static int in_subdir = 0;
+ static DIR *dirp;
+ struct dirent *d;
+ static struct dirinfo *curr_dir;
+ int len;
+
+ do {
+ 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;
+ }
+ if (strlen(d->d_name) +
+ strlen(curr_dir->dirname) >= PATH_MAX) {
+ 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());
+ continue;
+ }
+ 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) {
+ 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
+{
+ 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
+{
+ 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;
+
+ if (stack_head == (struct dirinfo *)NULL) {
+ return((struct dirinfo *)NULL);
+ } else {
+ tmp = stack_head;
+ stack_head = stack_head->next;
+ }
+ return(tmp);
+}