mirror of
https://git.savannah.gnu.org/git/tar.git
synced 2026-08-18 15:26:05 +00:00
tar: --dereference consistency
This closes another race condition, that occurs when overwriting a symlink with a regular file. * NEWS (--dereference consistency): New section. * doc/tar.texi (Option Summary): Describe new --deference behavior. (dereference): Likewise. Remove discussion that I didn't follow, even before --dereference was changed. * src/common.h (deref_stat, set_file_atime): Adjust signatures. * src/compare.c (diff_file, diff_multivol): Respect open_read_flags instead of rolling our own flags. This implements the new behavior for --dereference. (diff_file, diff_dumpdir): Likewise, for fstatat_flags. * src/create.c: Adjust to set_file_atime signature change. * src/extract.c (mark_after_links, file_newer_p, extract_dir): Likewise. * src/incremen.c (try_purge_directory): Likewise. * src/misc.c (maybe_backup_file): Likewise. * src/extract.c (file_newer_p): New arg STP. All callers changed. (maybe_recoverable): New arg REGULAR. All callers changed. Handle the case of overwriting a symlink with a regular file, when --overwrite is specified but --dereference is not. (open_output_file): Add O_CLOEXEC, O_NOCTTY, O_NONBLOCK for consistency with file creation. Add O_NOFOLLOW if overwriting_old_files && ! dereference_option. * src/incremen.c (update_parent_directory): Use fstat, not fstatat; there's less to go wrong. * src/misc.c (deref_stat): Remove DEREF arg. All callers changed. Instead, use fstatat_flags. (set_file_atime): Remove ATFLAG arg. All callers changed. Instead, use fstatat_flags. * src/names.c, src/update.c: Adjust to deref_stat signature change. * src/tar.c (get_date_or_file): Use stat, not deref_stat, as this is not a file to be archived. * tests/Makefile.am (TESTSUITE_AT): Add extrac13.at. * tests/extrac13.at: New file. * tests/testsuite.at: Include it.
This commit is contained in:
+5
-19
@@ -151,7 +151,7 @@ read_and_process (struct tar_stat_info *st, int (*processor) (size_t, char *))
|
||||
static int
|
||||
get_stat_data (char const *file_name, struct stat *stat_data)
|
||||
{
|
||||
int status = deref_stat (dereference_option, file_name, stat_data);
|
||||
int status = deref_stat (file_name, stat_data);
|
||||
|
||||
if (status != 0)
|
||||
{
|
||||
@@ -217,14 +217,7 @@ diff_file (void)
|
||||
}
|
||||
else
|
||||
{
|
||||
int atime_flag =
|
||||
(atime_preserve_option == system_atime_preserve
|
||||
? O_NOATIME
|
||||
: 0);
|
||||
|
||||
diff_handle = openat (chdir_fd, file_name,
|
||||
(O_RDONLY | O_BINARY | O_CLOEXEC | O_NOCTTY
|
||||
| O_NONBLOCK | atime_flag));
|
||||
diff_handle = openat (chdir_fd, file_name, open_read_flags);
|
||||
|
||||
if (diff_handle < 0)
|
||||
{
|
||||
@@ -244,8 +237,7 @@ diff_file (void)
|
||||
if (atime_preserve_option == replace_atime_preserve)
|
||||
{
|
||||
struct timespec atime = get_stat_atime (&stat_data);
|
||||
if (set_file_atime (diff_handle, chdir_fd, file_name,
|
||||
atime, 0)
|
||||
if (set_file_atime (diff_handle, chdir_fd, file_name, atime)
|
||||
!= 0)
|
||||
utime_error (file_name);
|
||||
}
|
||||
@@ -372,7 +364,7 @@ diff_dumpdir (void)
|
||||
dev_t dev = 0;
|
||||
struct stat stat_data;
|
||||
|
||||
if (deref_stat (true, current_stat_info.file_name, &stat_data))
|
||||
if (deref_stat (current_stat_info.file_name, &stat_data) != 0)
|
||||
{
|
||||
if (errno == ENOENT)
|
||||
stat_warn (current_stat_info.file_name);
|
||||
@@ -399,10 +391,6 @@ diff_multivol (void)
|
||||
struct stat stat_data;
|
||||
int fd, status;
|
||||
off_t offset;
|
||||
int atime_flag =
|
||||
(atime_preserve_option == system_atime_preserve
|
||||
? O_NOATIME
|
||||
: 0);
|
||||
|
||||
if (current_stat_info.had_trailing_slash)
|
||||
{
|
||||
@@ -429,9 +417,7 @@ diff_multivol (void)
|
||||
}
|
||||
|
||||
|
||||
fd = openat (chdir_fd, current_stat_info.file_name,
|
||||
(O_RDONLY | O_BINARY | O_CLOEXEC | O_NOCTTY | O_NONBLOCK
|
||||
| atime_flag));
|
||||
fd = openat (chdir_fd, current_stat_info.file_name, open_read_flags);
|
||||
|
||||
if (fd < 0)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user