SHA256
3
0
forked from pool/tar
tar/bsc1200657.patch
Dirk Mueller 1335d7f7b4 - bsc1200657.patch was previously incomplete leading to deadlocks
* bsc#1202436
  * bsc1200657.patch updated

- Fix race condition while creating intermediate subdirectories,
  bsc#1200657
  * bsc1200657.patch

OBS-URL: https://build.opensuse.org/package/show/Base:System/tar?expand=0&rev=111
2022-08-20 06:22:41 +00:00

150 lines
4.4 KiB
Diff
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

From 49b9f54ff66d126c4c0d58ccfbc2b85f96f845fc Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Thu, 31 Mar 2022 18:26:03 -0700
Subject: [PATCH] Retry file creation more aggressively
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* src/extract.c (maybe_recoverable): When deciding whether to
retry file creation, dont insist on our making intermediate
subdirectories; its OK if some other process made them.
Problem reported by James Abbatiello in:
https://lists.gnu.org/r/bug-tar/2022-03/msg00000.html
---
src/extract.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
Index: tar-1.34/src/extract.c
===================================================================
--- tar-1.34.orig/src/extract.c
+++ tar-1.34/src/extract.c
@@ -645,9 +645,9 @@ fixup_delayed_set_stat (char const *src,
it's because some required directory was not present, and if so,
create all required directories. Return zero if all the required
directories were created, nonzero (issuing a diagnostic) otherwise.
- Set *INTERDIR_MADE if at least one directory was created. */
+ */
static int
-make_directories (char *file_name, bool *interdir_made)
+make_directories (char *file_name)
{
char *cursor0 = file_name + FILE_SYSTEM_PREFIX_LEN (file_name);
char *cursor; /* points into the file name */
@@ -689,7 +689,6 @@ make_directories (char *file_name, bool
desired_mode, AT_SYMLINK_NOFOLLOW);
print_for_mkdir (file_name, cursor - file_name, desired_mode);
- *interdir_made = true;
}
else if (errno == EEXIST)
status = 0;
@@ -829,8 +828,11 @@ maybe_recoverable (char *file_name, bool
case ENOENT:
/* Attempt creating missing intermediate directories. */
- if (make_directories (file_name, interdir_made) == 0 && *interdir_made)
- return RECOVER_OK;
+ if (make_directories (file_name) == 0)
+ {
+ *interdir_made = true;
+ return RECOVER_OK;
+ }
break;
default:
@@ -1329,7 +1331,7 @@ extract_file (char *file_name, int typef
first. If it doesn't exist, there is no matching entry in the list.
Otherwise, look for the entry in list which has the matching dev
and ino numbers.
-
+
This approach avoids scanning the singly-linked list in obvious cases
and does not rely on comparing file names, which may differ for
various reasons (e.g. relative vs. absolute file names).
@@ -1342,14 +1344,14 @@ find_delayed_link_source (char const *na
if (!delayed_link_head)
return NULL;
-
+
if (fstatat (chdir_fd, name, &st, AT_SYMLINK_NOFOLLOW))
{
if (errno != ENOENT)
stat_error (name);
return NULL;
}
-
+
for (dl = delayed_link_head; dl; dl = dl->next)
{
if (dl->dev == st.st_dev && dl->ino == st.st_ino)
@@ -1357,7 +1359,7 @@ find_delayed_link_source (char const *na
}
return dl;
}
-
+
/* Create a placeholder file with name FILE_NAME, which will be
replaced after other extraction is done by a symbolic link if
IS_SYMLINK is true, and by a hard link otherwise. Set
@@ -1385,7 +1387,7 @@ create_placeholder_file (char *file_name
*/
return 0;
}
-
+
switch (maybe_recoverable (file_name, false, interdir_made))
{
case RECOVER_OK:
@@ -1467,7 +1469,7 @@ extract_link (char *file_name, int typef
char const *link_name;
int rc;
struct delayed_link *dl;
-
+
link_name = current_stat_info.link_name;
if (! absolute_names_option && contains_dot_dot (link_name))
@@ -1475,7 +1477,7 @@ extract_link (char *file_name, int typef
dl = find_delayed_link_source (link_name);
if (dl)
return create_placeholder_file (file_name, false, &interdir_made, dl);
-
+
do
{
struct stat st1, st2;
@@ -1697,7 +1699,7 @@ prepare_to_extract (char const *file_nam
case GNUTYPE_VOLHDR:
return false;
-
+
case GNUTYPE_MULTIVOL:
ERROR ((0, 0,
_("%s: Cannot extract -- file is continued from another volume"),
@@ -1753,7 +1755,7 @@ prepare_to_extract (char const *file_nam
}
}
*fun = extractor;
-
+
return true;
}
@@ -1934,12 +1936,11 @@ rename_directory (char *src, char *dst)
else
{
int e = errno;
- bool interdir_made;
switch (e)
{
case ENOENT:
- if (make_directories (dst, &interdir_made) == 0)
+ if (make_directories (dst) == 0)
{
if (renameat (chdir_fd, src, chdir_fd, dst) == 0)
return true;