diff options
author | James Abbatiello <abbeyj@gmail.com> | 2022-06-10 18:25:13 -0700 |
---|---|---|
committer | Paul Eggert <eggert@cs.ucla.edu> | 2022-06-10 18:26:37 -0700 |
commit | 79d1ac38c19faad64f0e993180bf1ad27f217072 (patch) | |
tree | 147acd8eba9f040a2c4ecd818dde2e4d53cb3094 | |
parent | 79a442d7b0e92622794bfa41dee18a28e450a0dc (diff) | |
download | tar-79d1ac38c19faad64f0e993180bf1ad27f217072.tar.gz |
tar: fix race condition
Problem reported in:
https://lists.gnu.org/r/bug-tar/2022-03/msg00000.html
* src/extract.c (make_directories): Retry the file creation as
long as the directory exists, regardless of whether tar itself
created the directory.
Copyright-paperwork-exempt: Yes
-rw-r--r-- | src/extract.c | 16 |
1 files changed, 8 insertions, 8 deletions
diff --git a/src/extract.c b/src/extract.c index 0753decf..fda4617d 100644 --- a/src/extract.c +++ b/src/extract.c @@ -638,10 +638,9 @@ fixup_delayed_set_stat (char const *src, char const *dst) /* After a file/link/directory creation has failed due to ENOENT, 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. */ + directories were created, nonzero (issuing a diagnostic) otherwise. */ 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 */ @@ -685,7 +684,6 @@ make_directories (char *file_name, bool *interdir_made) desired_mode, AT_SYMLINK_NOFOLLOW); print_for_mkdir (file_name, cursor - file_name, desired_mode); - *interdir_made = true; parent_end = NULL; } else @@ -841,8 +839,11 @@ maybe_recoverable (char *file_name, bool regular, bool *interdir_made) case ENOENT: /* Attempt creating missing intermediate directories. */ - if (make_directories (file_name, interdir_made) == 0) - return RECOVER_OK; + if (make_directories (file_name) == 0) + { + *interdir_made = true; + return RECOVER_OK; + } break; default: @@ -1944,12 +1945,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; |