131 lines
3.7 KiB
Diff
131 lines
3.7 KiB
Diff
|
|
From 983a82a3767da04cb3ca15eefe2e4b21154c335f Mon Sep 17 00:00:00 2001
|
||
|
|
From: Sergey Poznyakoff <gray@gnu.org>
|
||
|
|
Date: Fri, 21 Dec 2018 13:24:29 +0200
|
||
|
|
Subject: [PATCH 36/58] 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.
|
||
|
|
---
|
||
|
|
NEWS | 12 +++++++++++-
|
||
|
|
src/common.h | 5 +++++
|
||
|
|
src/names.c | 45 ++++++++++++++++++++++++++++++++++++++-------
|
||
|
|
src/tar.c | 3 +--
|
||
|
|
4 files changed, 55 insertions(+), 10 deletions(-)
|
||
|
|
|
||
|
|
diff --git a/src/common.h b/src/common.h
|
||
|
|
index 2877975..32e6f8b 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 f4dc978..d3728d8 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);
|
||
|
|
}
|
||
|
|
diff --git a/src/tar.c b/src/tar.c
|
||
|
|
index 1993887..9919e87 100644
|
||
|
|
--- a/src/tar.c
|
||
|
|
+++ b/src/tar.c
|
||
|
|
@@ -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:
|
||
|
|
--
|
||
|
|
2.19.1
|
||
|
|
|