diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2018-12-21 13:24:29 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2018-12-21 13:54:11 +0200 |
commit | 983a82a3767da04cb3ca15eefe2e4b21154c335f (patch) | |
tree | e105be1624b3a58bcfd2e6e3f575caf507d3f92a | |
parent | 916fe62ae9b91a5d71cfa752f7cad89a558d7672 (diff) | |
download | tar-983a82a3767da04cb3ca15eefe2e4b21154c335f.tar.gz |
Fix semantics of -K used together with explicit member names.
This also fixes the bug reported in
http://lists.gnu.org/archive/html/bug-tar/2018-12/msg00012.html
* src/common.h (starting_file_option): Describe the variable.
* src/names.c (add_starting_file): New function.
(name_match): Ignore everything before the member indicated by the
--starting-file option
* src/tar.c: Use add_starting_file to handle the -K option.
-rw-r--r-- | NEWS | 12 | ||||
-rw-r--r-- | src/common.h | 5 | ||||
-rw-r--r-- | src/names.c | 45 | ||||
-rw-r--r-- | src/tar.c | 3 |
4 files changed, 55 insertions, 10 deletions
@@ -1,4 +1,4 @@ -GNU tar NEWS - User visible changes. 2018-04-07 +GNU tar NEWS - User visible changes. 2018-12-21 Please send GNU tar bug reports to <bug-tar@gnu.org> @@ -15,6 +15,16 @@ recognized automatically. When '-a' option is in effect, zstd compression is selected if the destination archive name ends in '.zst' or '.tzst'. +* The -K option interacts properly with member names given in the command line + +Names of members to extract can be specified along with the "-K NAME" +option. In this case, tar will extract NAME and those of named members +that appear in the archive after it, which is consistent with the +semantics of the option. + +Previous versions of tar extracted NAME, those of named members that +appeared before it, and everything after it. + version 1.30 - Sergey Poznyakoff, 2017-12-17 diff --git a/src/common.h b/src/common.h index 28779751..32e6f8bd 100644 --- a/src/common.h +++ b/src/common.h @@ -302,6 +302,10 @@ enum hole_detection_method GLOBAL enum hole_detection_method hole_detection; +/* The first entry in names.c:namelist specifies the member name to + start extracting from. Set by add_starting_file() upon seeing the + -K option. +*/ GLOBAL bool starting_file_option; /* Specified maximum byte length of each tape volume (multiple of 1024). */ @@ -752,6 +756,7 @@ const char *name_next (int change_dirs); void name_gather (void); struct name *addname (char const *string, int change_dir, bool cmdline, struct name *parent); +void add_starting_file (char const *file_name); void remname (struct name *name); bool name_match (const char *name); void names_notfound (void); diff --git a/src/names.c b/src/names.c index f4dc978c..d3728d84 100644 --- a/src/names.c +++ b/src/names.c @@ -1227,6 +1227,34 @@ addname (char const *string, int change_dir, bool cmdline, struct name *parent) return name; } +void +add_starting_file (char const *file_name) +{ + struct name *name = make_name (file_name); + + if (starting_file_option) + { + struct name *head = namelist; + remname (head); + free_name (head); + } + + name->prev = NULL; + name->next = namelist; + namelist = name; + if (!nametail) + nametail = namelist; + + name->found_count = 0; + name->matching_flags = INCLUDE_OPTIONS; + name->change_dir = 0; + name->directory = NULL; + name->parent = NULL; + name->cmdline = true; + + starting_file_option = true; +} + /* Find a match for FILE_NAME (whose string length is LENGTH) in the name list. */ static struct name * @@ -1283,19 +1311,22 @@ name_match (const char *file_name) } cursor = namelist_match (file_name, length); + if (starting_file_option) + { + /* If starting_file_option is set, the head of the list is the name + of the member to start extraction from. Skip the match unless it + is head. */ + if (cursor == namelist) + starting_file_option = false; + else + cursor = NULL; + } if (cursor) { if (!(ISSLASH (file_name[cursor->length]) && recursion_option) || cursor->found_count == 0) cursor->found_count++; /* remember it matched */ - if (starting_file_option) - { - free (namelist); - namelist = NULL; - nametail = NULL; - } chdir_do (cursor->change_dir); - /* We got a match. */ return ISFOUND (cursor); } @@ -1443,8 +1443,7 @@ parse_opt (int key, char *arg, struct argp_state *state) case 'K': optloc_save (OC_STARTING_FILE, args->loc); - starting_file_option = true; - addname (arg, 0, true, NULL); + add_starting_file (arg); break; case ONE_FILE_SYSTEM_OPTION: |