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.
This commit is contained in:
Sergey Poznyakoff
2018-12-21 13:24:29 +02:00
parent 916fe62ae9
commit 983a82a376
4 changed files with 55 additions and 10 deletions

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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: