diff --git a/gnu/usr.bin/tar/list.c b/gnu/usr.bin/tar/list.c index 4158a45dac65..d40c01472867 100644 --- a/gnu/usr.bin/tar/list.c +++ b/gnu/usr.bin/tar/list.c @@ -95,6 +95,11 @@ read_and (do_something) { prev_status = status; status = read_header (); + /* check if the namelist got emptied during the course of reading */ + /* the tape, if so stop by setting status to EOF */ + if ((namelist == NULL) && nlpsfreed) { + status = EOF; + } switch (status) { diff --git a/gnu/usr.bin/tar/tar.1 b/gnu/usr.bin/tar/tar.1 index 3beef0b55db9..e97edc5c153c 100644 --- a/gnu/usr.bin/tar/tar.1 +++ b/gnu/usr.bin/tar/tar.1 @@ -3,7 +3,7 @@ .\" .\" Written by John F. Woods .\" -.\" $Id: tar.1,v 1.1 1995/01/26 00:14:11 jkh Exp $ +.\" $Id: tar.1,v 1.2 1995/01/31 04:36:48 jkh Exp $ .\" .Dd 6 August 1994 .Os FreeBSD @@ -158,6 +158,9 @@ on a remote machine. .It Fl -new-volume-script Ar file Run a script at the end of each archive volume (implies .Fl M ) . +.It Fl -fast-read +Stop after all non-wildcard extraction targets have been found +in the archive. .It Fl G .It Fl -incremental Create/list/extract old GNU-format incremental backup. diff --git a/gnu/usr.bin/tar/tar.c b/gnu/usr.bin/tar/tar.c index 6a7f8a2b4808..a51ff2bcb5ae 100644 --- a/gnu/usr.bin/tar/tar.c +++ b/gnu/usr.bin/tar/tar.c @@ -84,6 +84,7 @@ void name_add (); void name_init (); void options (); char *un_quote_string (); +int nlpsfreed = 0; #ifndef S_ISLNK #define lstat stat @@ -182,6 +183,7 @@ struct option long_options[] = {"atime-preserve", 0, &f_atime_preserve, 1}, {"unlink", 0, &f_unlink, 1}, + {"fast-read", 0, &f_fast_read, 1}, {0, 0, 0, 0} }; @@ -199,7 +201,7 @@ main (argc, argv) tar = argv[0]; /* JF: was "tar" Set program name */ filename_terminator = '\n'; errors = 0; - + options (argc, argv); if (!n_argv) @@ -760,6 +762,7 @@ Other options:\n\ --block-compress block the output of compression program for tapes\n\ -[0-7][lmh] specify drive and density\n\ --unlink unlink files before creating them\n\ +--fast-read stop after desired names in archive have been found\n\ ", stdout); } @@ -1123,6 +1126,7 @@ name_match (p) register char *p; { register struct name *nlp; + struct name *tmpnlp; register int len; again: @@ -1174,7 +1178,36 @@ name_match (p) } if (nlp->change_dir && chdir (nlp->change_dir)) msg_perror ("Can't change to directory %s", nlp->change_dir); + if (f_fast_read) { + if (strcmp(p, nlp->name) == 0) { + /* remove the current entry, since we found a match */ + /* use brute force, this code is a mess anyway */ + if (namelist->next == NULL) { + /* the list contains one element */ + free(namelist); + namelist = NULL; + } else { + if (nlp == namelist) { + /* the first element is the one */ + tmpnlp = namelist->next; + free(namelist); + namelist = tmpnlp; + } else { + tmpnlp = namelist; + while (tmpnlp->next != nlp) { + tmpnlp = tmpnlp->next; + } + tmpnlp->next = nlp->next; + free(nlp); + } + } + /* set a boolean to decide wether we started with a */ + /* non-empty namelist, that was emptied */ + nlpsfreed = 1; + } + } return 1; /* We got a match */ + } } diff --git a/gnu/usr.bin/tar/tar.h b/gnu/usr.bin/tar/tar.h index 46d29d81dd0e..21c5d52e1850 100644 --- a/gnu/usr.bin/tar/tar.h +++ b/gnu/usr.bin/tar/tar.h @@ -232,6 +232,7 @@ TAR_EXTERN int f_force_local; /* --force-local */ TAR_EXTERN int f_atime_preserve;/* --atime-preserve */ TAR_EXTERN int f_compress_block; /* --compress-block */ TAR_EXTERN int f_unlink; /* --unlink */ +TAR_EXTERN int f_fast_read; /* --fast-read */ /* * We default to Unix Standard format rather than 4.2BSD tar format. @@ -274,6 +275,10 @@ TAR_EXTERN char *gnu_dumpfile; */ TAR_EXTERN char read_error_flag; +/* + * global boolean, see name_match in tar.c + */ +extern int nlpsfreed; /* * Declarations of functions available to the world.