From: lauras AT softhome DOT net Message-ID: <20010916143811.19992.qmail@softhome.net> To: djgpp-workers AT delorie DOT com Subject: Patch: skipping paths in djtar (3rd try) Date: Sun, 16 Sep 2001 14:38:11 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 I've dug up my old patch, if somebody remembers that; cleared up all issues raised by Eli back in February, and here is what I believe is the final form ready for CVS: Laurynas Index: djgpp/src/docs/kb/wc204.txi =================================================================== RCS file: /cvs/djgpp/djgpp/src/docs/kb/wc204.txi,v retrieving revision 1.96 diff -u -p -r1.96 wc204.txi --- djgpp/src/docs/kb/wc204.txi 2001/08/26 10:41:18 1.96 +++ djgpp/src/docs/kb/wc204.txi 2001/09/16 15:10:32 @@ -613,3 +613,10 @@ correct read/write permissions in @code{ in @code{st_dev} members of @code{struct stat}. This was known to fail functions like @code{link} and programs like GNU @code{cp} which tested files for being on the same filesystem by calling @code{fstat}. + +@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: djgpp/src/utils/utils.tex =================================================================== RCS file: /cvs/djgpp/djgpp/src/utils/utils.tex,v retrieving revision 1.17 diff -u -p -r1.17 utils.tex --- djgpp/src/utils/utils.tex 2001/07/03 17:15:37 1.17 +++ djgpp/src/utils/utils.tex 2001/09/16 15:10:49 @@ -127,9 +127,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 @@ -262,11 +263,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. +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. If there is no ``new'' directory +specified, the ``old'' one and all its siblings will be not extracted. @item -d @@ -297,6 +300,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}. @@ -305,7 +315,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 +several different directories and files. @item -i @@ -515,10 +526,10 @@ hours:minutes:seconds. @end table -Options are processed in the order they are encountered. Thus, "-o foo --eo" means "redirect output to foo, then redirect errors there also", -whereas "-eo -o foo" means "send errors to where output was going, then -move output to foo". +Options are processed in the order they are encountered. Thus, ``-o foo +-eo'' means ``redirect output to foo, then redirect errors there also'', +whereas ``-eo -o foo'' means ``send errors to where output was going, then +move output to foo''. Examples: Index: djgpp/src/utils/djtar/djtar.c =================================================================== RCS file: /cvs/djgpp/djgpp/src/utils/djtar/djtar.c,v retrieving revision 1.8 diff -u -p -r1.8 djtar.c --- djgpp/src/utils/djtar/djtar.c 2001/03/21 17:01:58 1.8 +++ djgpp/src/utils/djtar/djtar.c 2001/09/16 15:10:51 @@ -24,6 +24,15 @@ Fatal(const char *msg) exit(1); } +static char * +xstrdup(const char * source) +{ + char * ptr = strdup(source); + 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,11 +76,9 @@ 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->from = strdup(from); - ce->to = strdup(to); + CE *ce = (CE *)xmalloc(sizeof(CE)); + ce->from = xstrdup(from); + ce->to = xstrdup(to); ce->next = htab[h]; htab[h] = ce; } @@ -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 = xmalloc(sizeof(struct skip_dir_list)); + new_entry->skip_dir = xstrdup(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,12 +206,10 @@ 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 *)xmalloc(sizeof(CHANGE)); ch->next = change_root; change_root = ch; - ch->old = strdup(fname); + ch->old = xstrdup(fname); pos = strrchr(fname, '/'); if (pos && (strchr(new, '/') == 0)) { @@ -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 *)xmalloc(strlen(new) + (pos-fname) + 2); *pos = 0; sprintf(ch->new, "%s/%s", fname, new); } @@ -201,7 +225,7 @@ change(char *fname, const char *problem, else if (new[0] == 0) ch->new = skipped_str; else - ch->new = strdup(new); + ch->new = xstrdup(new); ch->isdir = isadir; strcpy(fname, ch->new); if (new[0] == 0) @@ -294,14 +318,45 @@ 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))) + { + char * following_char = name_to_change + strlen(name_to_change); + if ((*following_char == '\0') || (*following_char == '/') || + (*following_char == '\\')) + 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)) { @@ -498,12 +553,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])); + progname = strlwr(xstrdup(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); } @@ -515,6 +572,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]) @@ -544,8 +602,17 @@ main(int argc, char **argv) if (argv[i][2] == '.') dot_switch = 0; break; + case 'e': + skip_entry = xmalloc(sizeof(struct skip_dir_list)); + skip_entry->skip_dir = xstrdup(argv[++i]); + skip_entry->next = skip_dirs; + skip_dirs = skip_entry; + break; case 'o': - only_dir = strdup(argv[++i]); + only_entry = xmalloc(sizeof(struct only_dir_list)); + only_entry->only_dir = xstrdup(argv[++i]); + only_entry->next = only_dirs; + only_dirs = only_entry; break; case 'p': to_stdout = 1;