From 1130454b1c29f21206a4c41e18c59e3d228965c5 Mon Sep 17 00:00:00 2001 From: itojun Date: Wed, 9 Oct 2002 19:28:14 +0000 Subject: [PATCH] bring in --fast-read code from freebsd. --- gnu/dist/tar/src/common.h | 6 ++++++ gnu/dist/tar/src/list.c | 4 ++++ gnu/dist/tar/src/names.c | 33 +++++++++++++++++++++++++++++++++ gnu/dist/tar/src/tar.c | 8 +++++--- 4 files changed, 48 insertions(+), 3 deletions(-) diff --git a/gnu/dist/tar/src/common.h b/gnu/dist/tar/src/common.h index 4ea6a5269aa0..b0366b74e0c5 100644 --- a/gnu/dist/tar/src/common.h +++ b/gnu/dist/tar/src/common.h @@ -152,6 +152,9 @@ GLOBAL int dereference_option; /* Patterns that match file names to be excluded. */ GLOBAL struct exclude *excluded; +/* Boolean value. */ +GLOBAL int fast_read_option; + /* Specified file containing names to work on. */ GLOBAL const char *files_from_option; @@ -196,6 +199,9 @@ GLOBAL struct mode_change *mode_option; /* Boolean value. */ GLOBAL int multi_volume_option; +/* Boolean value. */ +GLOBAL int namelist_freed; + /* The same variable hold the time, whether mtime or ctime. Just fake a non-existing option, for making the code clearer, elsewhere. */ #define newer_ctime_option newer_mtime_option diff --git a/gnu/dist/tar/src/list.c b/gnu/dist/tar/src/list.c index e88d53b711f6..08a84d09a69b 100644 --- a/gnu/dist/tar/src/list.c +++ b/gnu/dist/tar/src/list.c @@ -78,6 +78,10 @@ read_and (void (*do_something) ()) { prev_status = status; status = read_header (0); + /* check if the namelist got emptied during the course of reading */ + /* the tape, if so stop by setting status to EOF */ + if (namelist_freed) + status = HEADER_END_OF_FILE; switch (status) { case HEADER_STILL_UNREAD: diff --git a/gnu/dist/tar/src/names.c b/gnu/dist/tar/src/names.c index eb1763696526..fe3763614dd9 100644 --- a/gnu/dist/tar/src/names.c +++ b/gnu/dist/tar/src/names.c @@ -549,6 +549,7 @@ name_match (const char *path) while (1) { struct name *cursor = namelist; + struct name *tmpnlp; if (!cursor) return ! files_from_option; @@ -572,6 +573,38 @@ name_match (const char *path) nametail = &namelist; } chdir_do (cursor->change_dir); + if (fast_read_option) + { + /* remove the current entry, since we found a match */ + if (namelist->next == NULL) + { + /* the list contains one element */ + free(namelist); + namelist = 0; + nametail = &namelist; + /* set a boolean to decide wether we started with a */ + /* non-empty namelist, that was emptied */ + namelist_freed = 1; + } + else + { + if (cursor == namelist) + { + /* the first element is the one */ + tmpnlp = namelist->next; + free(namelist); + namelist = tmpnlp; + } + else + { + tmpnlp = namelist; + while (tmpnlp->next != cursor) + tmpnlp = tmpnlp->next; + tmpnlp->next = cursor->next; + free(cursor); + } + } + } /* We got a match. */ return 1; diff --git a/gnu/dist/tar/src/tar.c b/gnu/dist/tar/src/tar.c index b22abcd9ee40..06a65d4508c4 100644 --- a/gnu/dist/tar/src/tar.c +++ b/gnu/dist/tar/src/tar.c @@ -200,7 +200,7 @@ static struct option long_options[] = {"exclude", required_argument, 0, EXCLUDE_OPTION}, {"exclude-from", required_argument, 0, 'X'}, {"extract", no_argument, 0, 'x'}, - {"fast-read", no_argument, 0, 0}, + {"fast-read", no_argument, &fast_read_option, 1}, {"file", required_argument, 0, 'f'}, {"files-from", required_argument, 0, 'T'}, {"force-local", no_argument, &force_local_option, 1}, @@ -337,8 +337,9 @@ Operation modifiers:\n\ -G, --incremental handle old GNU-format incremental backup\n\ -g, --listed-incremental=FILE\n\ handle new GNU-format incremental backup\n\ - --ignore-failed-read do not exit with nonzero on unreadable files\n"), - stdout); + --ignore-failed-read do not exit with nonzero on unreadable files\n\ + --fast-read stop after desired names in archive have been found\n"), + stdout); fputs (_("\ \n\ Handling of file attributes:\n\ @@ -512,6 +513,7 @@ decode_options (int argc, char **argv) excluded = new_exclude (); newer_mtime_option = TYPE_MINIMUM (time_t); recursion_option = FNM_LEADING_DIR; + namelist_freed = 0; owner_option = -1; group_option = -1;