From: lauras AT softhome DOT net Message-ID: <20010216102653.32267.qmail@softhome.net> To: djgpp-workers AT delorie DOT com Subject: djtar: skipping directories Date: Fri, 16 Feb 2001 10:26:53 GMT Mime-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit X-Sender: lauras AT softhome DOT net Reply-To: djgpp-workers AT delorie DOT com Here is an updated patch, which does: 1) All entries in file name mapping file without destination will be skipped 2) Multiple -o options allowed 3) New -x option 4) Minor cleanup: consolidate all malloc() error checking into djtmalloc(). This is still implemented with linked lists and not struct CHANGE. I still maintain the point it's the better way. Criticism is welcome, as always :) Index: docs/kb/wc204.txi =================================================================== RCS file: /cvs/djgpp/djgpp/src/docs/kb/wc204.txi,v retrieving revision 1.53 diff -p -u -r1.53 wc204.txi --- wc204.txi 2001/02/09 12:38:40 1.53 +++ wc204.txi 2001/02/16 10:24:30 @@ -317,3 +317,10 @@ namespace. @findex setjmp AT r{, also a macro} @code{setjmp} is now a macro as well as a function. This is required by the C AT t{++} standard, and also recommended by the C standard. + +@pindex djtar AT r{, new option -e} +@pindex djtar AT r{, multiple -o and -e options} +New option @samp{-e} has been added to @code{djtar} to skip specified files +and directories when extracting. Also @code{djtar} can accept multiple +@samp{-o} and @samp{-e} options in a single command line. Finally, the file +name change file format allows skipping files and directories. Index: utils/utils.tex =================================================================== RCS file: /cvs/djgpp/djgpp/src/utils/utils.tex,v retrieving revision 1.13 diff -p -u -r1.13 utils.tex --- utils.tex 2001/01/20 09:20:39 1.13 +++ utils.tex 2001/02/16 10:24:48 @@ -125,9 +125,10 @@ package is built. @node djtar, dtou, djecho, Top @chapter djtar -Usage: @code{djtar} [@code{-n} @file{changeFile}] [@code{-o} @file{dir}] -[@code{-t}|@code{-x}] [@code{-i}] [@code{-v}] [@code{-p}] -[@code{-.}|@code{-!.}] [@code{-d}|@code{-u}|@code{-b}] @file{tarfile} +Usage: @code{djtar} [@code{-n} @file{changeFile}] [@code{-e} @file{dir}] +[@code{-o} @file{dir}] [@code{-t}|@code{-x}] [@code{-i}] [@code{-v}] +[@code{-p}] [@code{-.}|@code{-!.}] [@code{-d}|@code{-u}|@code{-b}] +@file{tarfile} @code{djtar} is a program that is designed to ease the problems related to extracting Unix tar files on a DOS machine. The long file names and @@ -253,11 +254,13 @@ The format of the @file{changeFile} file @example dir/dir/dir/old.name.here dir/dir/dir/newname.hre dir/dir/dir/old2.name.here dir/dir/dir/newname2.hre +dir/dir/dir.to.skip.here @end example The directories must be complete, not relative. The "old" directories must match the complete path in the tar file, and the "new" directories -indicate where the file goes on the DOS disk. +indicate where the file goes on the DOS disk. If there is no "new" directory +specified, the "old" one and all its siblings will be not extracted. @item -d @@ -288,6 +291,13 @@ written in text mode, so this option doe with @samp{-p}, unless the output of @code{djtar} is redirected to a file or a pipe. +@item -e @var{string} + +Only extract files whose full path names do @strong{not} begin with @var{string}. +This option can be used to skip portions of archive. If both this +and @samp{-o} options are specified, then this option has precendence. In +other ways @samp{-e} is similar to @samp{-o} option. + @item -o @var{string} Only extract files whose full path names begin with @var{string}. @@ -296,7 +306,8 @@ extracted will still be shown, but with appended to their names. When given the @samp{-o} option, @code{djtar} actually checks if @var{string} is the initial substring of each filename, so you can specify incomplete file names, thus using @samp{-o} as a poor man's -wildcard facility. +wildcard facility. You may specify multiple @samp{-o} options to extract +few different directories and files. @item -i Index: utils/djtar/djtar.c =================================================================== RCS file: /cvs/djgpp/djgpp/src/utils/djtar/djtar.c,v retrieving revision 1.7 diff -p -u -r1.7 djtar.c --- djtar.c 1999/11/14 14:19:17 1.7 +++ djtar.c 2001/02/16 10:24:50 @@ -24,6 +24,15 @@ Fatal(const char *msg) exit(1); } +static void * +djtmalloc(const size_t size) +{ + void * ptr = malloc(size); + if (!ptr) + Fatal("Out of memory"); + return ptr; +} + /*------------------------------------------------------------------------*/ typedef struct CE { @@ -32,6 +41,21 @@ typedef struct CE { char *to; } CE; +/* Do not extract files and directories starting with prefixes in this list. */ +/* It has precendence over only_dir below. */ +struct skip_dir_list +{ + char *skip_dir; + struct skip_dir_list * next; +} * skip_dirs; + +/* Extract only files and directories starting with prefixes in this list. */ +struct only_dir_list +{ + char *only_dir; + struct only_dir_list * next; +} * only_dirs; + #define HASHSIZE 2048 #define HASHMASK 2047 #define HASHBITS 11 @@ -52,9 +76,7 @@ static void store_entry(char *from, char *to) { unsigned long h = hash(from); - CE *ce = (CE *)malloc(sizeof(CE)); - if (ce == 0) - Fatal("Out of memory"); + CE *ce = (CE *)djtmalloc(sizeof(CE)); ce->from = strdup(from); ce->to = strdup(to); ce->next = htab[h]; @@ -76,6 +98,7 @@ get_entry(char *from) static void DoNameChanges(char *fname) { + struct skip_dir_list * new_entry; FILE *f = fopen(fname, "r"); char from[PATH_MAX], to[PATH_MAX]; char line[PATH_MAX*2 + 10]; @@ -93,6 +116,13 @@ DoNameChanges(char *fname) sscanf(line, "%s %s", from, to); if (to[0]) store_entry(from, to); + else + { + new_entry = djtmalloc(sizeof(struct skip_dir_list)); + new_entry->skip_dir = strdup(from); + new_entry->next = skip_dirs; + skip_dirs = new_entry; + } } fclose(f); } @@ -112,8 +142,6 @@ int ignore_csum = 0; int list_only = 1; char skipped_str[] = "[skipped]"; -char *only_dir; - /*------------------------------------------------------------------------*/ typedef struct CHANGE { @@ -178,9 +206,7 @@ change(char *fname, const char *problem, if ((strcmp(new, "") == 0) && (isadir == 2)) return 0; if (isadir) isadir=1; - ch = (CHANGE *)malloc(sizeof(CHANGE)); - if (ch == 0) - Fatal("Out of memory"); + ch = (CHANGE *)djtmalloc(sizeof(CHANGE)); ch->next = change_root; change_root = ch; ch->old = strdup(fname); @@ -191,9 +217,7 @@ change(char *fname, const char *problem, ch->new = skipped_str; else { - ch->new = (char *)malloc(strlen(new) + (pos-fname) + 2); - if (ch->new == 0) - Fatal("Out of memory"); + ch->new = (char *)djtmalloc(strlen(new) + (pos-fname) + 2); *pos = 0; sprintf(ch->new, "%s/%s", fname, new); } @@ -294,13 +318,39 @@ char * get_new_name(char *name_to_change, int *should_be_written) { char *changed_name; + struct skip_dir_list * skip_dir_entry; + struct only_dir_list * only_dir_entry; /* ONLY_DIR says to extract only files which are siblings of that directory. */ *should_be_written = list_only == 0; - if (*should_be_written && - only_dir && strncmp(only_dir, name_to_change, strlen(only_dir))) - *should_be_written = 0; + + if (*should_be_written) + { + skip_dir_entry = skip_dirs; + while (skip_dir_entry) + { + if (!strncmp(skip_dir_entry->skip_dir, name_to_change, + strlen(skip_dir_entry->skip_dir))) + break; + skip_dir_entry = skip_dir_entry->next; + } + if (skip_dir_entry) + *should_be_written = 0; + else if (only_dirs) + { + only_dir_entry = only_dirs; + while (only_dir_entry) + { + if (!strncmp(only_dir_entry->only_dir, name_to_change, + strlen(only_dir_entry->only_dir))) + break; + only_dir_entry = only_dir_entry->next; + } + if (!only_dir_entry) + *should_be_written = 0; + } + } changed_name = get_entry(name_to_change); if (*should_be_written && !to_stdout && NO_LFN(changed_name)) @@ -478,12 +528,14 @@ main(int argc, char **argv) int i = 1; char *tp; char *xp; + struct skip_dir_list * skip_entry; + struct only_dir_list * only_entry; progname = strlwr(strdup(argv[0])); if (argc < 2) { - fprintf(stderr, "Usage: %s [-n changeFile] [-p] [-i] [-t|x] [-o dir] [-v] [-u|d|b] [-[!].] tarfile...\n", progname); + fprintf(stderr, "Usage: %s [-n changeFile] [-p] [-i] [-t|x] [-e dir] [-o dir] [-v] [-u|d|b] [-[!].] tarfile...\n", progname); exit(1); } @@ -495,6 +547,7 @@ main(int argc, char **argv) list_only = 1; else if (xp && (xp[sizeof(djtarx)-1] == '\0' || xp[sizeof(djtarx)-5] == '\0')) list_only = 0; + while ((argc > i) && (argv[i][0] == '-') && argv[i][1]) { switch (argv[i][1]) @@ -524,8 +577,17 @@ main(int argc, char **argv) if (argv[i][2] == '.') dot_switch = 0; break; + case 'e': + skip_entry = djtmalloc(sizeof(struct skip_dir_list)); + skip_entry->skip_dir = strdup(argv[++i]); + skip_entry->next = skip_dirs; + skip_dirs = skip_entry; + break; case 'o': - only_dir = strdup(argv[++i]); + only_entry = djtmalloc(sizeof(struct only_dir_list)); + only_entry->only_dir = strdup(argv[++i]); + only_entry->next = only_dirs; + only_dirs = only_entry; break; case 'p': to_stdout = 1;