From: Sergey Poznyakoff Date: Sun, 29 Nov 2015 18:51:08 +0000 (+0200) Subject: Fix extraction from concatenated incremental archives with renamed directories. X-Git-Tag: release_1_29~36 X-Git-Url: https://git.gag.com/?a=commitdiff_plain;h=d02c81df15e3ac3764c654f1e3bf24b5f45b3ed7;p=debian%2Ftar Fix extraction from concatenated incremental archives with renamed directories. Complements 15c02c2b. * src/extract.c (delayed_set_stat): Change type of file_name. (delay_set_stat): Allocate file_name member. (free_delayed_set_stat): Free file_name. (fixup_delayed_set_stat): New function. (rename_directory): Call fixup_delayed_set_stat on success. * tests/incr11.at: New testcase. * tests/incr10.at: Improve description. * tests/Makefile.am: Add incr11.at * tests/testsuite.at: Add incr11.at --- diff --git a/src/extract.c b/src/extract.c index 5aaeb1bf..2dcfd282 100644 --- a/src/extract.c +++ b/src/extract.c @@ -109,7 +109,7 @@ struct delayed_set_stat struct xattr_array *xattr_map; /* Length and contents of name. */ size_t file_name_len; - char file_name[1]; + char *file_name; }; static struct delayed_set_stat *delayed_set_stat_head; @@ -441,9 +441,7 @@ delay_set_stat (char const *file_name, struct tar_stat_info const *st, mode_t mode, int atflag) { size_t file_name_len = strlen (file_name); - struct delayed_set_stat *data = - xmalloc (offsetof (struct delayed_set_stat, file_name) - + file_name_len + 1); + struct delayed_set_stat *data = xmalloc (sizeof (*data)); data->next = delayed_set_stat_head; data->mode = mode; if (st) @@ -456,6 +454,7 @@ delay_set_stat (char const *file_name, struct tar_stat_info const *st, data->mtime = st->mtime; } data->file_name_len = file_name_len; + data->file_name = xstrdup (file_name); data->current_mode = current_mode; data->current_mode_mask = current_mode_mask; data->interdir = ! st; @@ -540,6 +539,7 @@ repair_delayed_set_stat (char const *dir, static void free_delayed_set_stat (struct delayed_set_stat *data) { + free (data->file_name); xheader_xattr_free (data->xattr_map, data->xattr_map_size); free (data->cntx_name); free (data->acls_a_ptr); @@ -569,6 +569,23 @@ remove_delayed_set_stat (const char *fname) } } +static void +fixup_delayed_set_stat (char const *src, char const *dst) +{ + struct delayed_set_stat *data; + for (data = delayed_set_stat_head; data; data = data->next) + { + if (chdir_current == data->change_dir + && strcmp (data->file_name, src) == 0) + { + free (data->file_name); + data->file_name = xstrdup (dst); + data->file_name_len = strlen (dst); + return; + } + } +} + /* After a file/link/directory creation has failed, see if it's because some required directory was not present, and if so, create all required directories. Return zero if all the required @@ -1769,7 +1786,9 @@ extract_finish (void) bool rename_directory (char *src, char *dst) { - if (renameat (chdir_fd, src, chdir_fd, dst) != 0) + if (renameat (chdir_fd, src, chdir_fd, dst) == 0) + fixup_delayed_set_stat (src, dst); + else { int e = errno; bool interdir_made; diff --git a/tests/Makefile.am b/tests/Makefile.am index 06722c3d..d9a52b3e 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -118,6 +118,7 @@ TESTSUITE_AT = \ incr08.at\ incr09.at\ incr10.at\ + incr11.at\ indexfile.at\ ignfail.at\ iotty.at\ diff --git a/tests/incr10.at b/tests/incr10.at index 3b519265..4eec51f4 100644 --- a/tests/incr10.at +++ b/tests/incr10.at @@ -15,7 +15,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -AT_SETUP([concatenated incremental archives]) +AT_SETUP([concatenated incremental archives (deletes)]) AT_KEYWORDS([incremental concat cat incr10]) # Description: Extraction from concatenated incremental archives diff --git a/tests/incr11.at b/tests/incr11.at new file mode 100644 index 00000000..1d052e21 --- /dev/null +++ b/tests/incr11.at @@ -0,0 +1,75 @@ +# Process this file with autom4te to create testsuite. -*- Autotest -*- +# Test suite for GNU tar. +# Copyright 2015 Free Software Foundation, Inc. +# +# GNU tar is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# GNU tar is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Description: Extraction from concatenated incremental archives +# produced spurious error messages when trying to set file ownership +# and permissions on renamed directories +# Reported by: Alex Efros +# References: <20151129094003.GD18347@home.power> +# http://lists.gnu.org/archive/html/bug-tar/2015-11/msg00033.html + +AT_SETUP([concatenated incremental archives (renames)]) +AT_KEYWORDS([incremental concat cat incr11]) + +AT_TAR_CHECK([ +AT_SORT_PREREQ +AT_TAR_MKHIER([data/dir],[file]) +decho Level 0 +tar -cvf full.tar -g snap -C data . +decho Level 1 +mv data/dir data/dir2 +tar -cvf incr.tar -g snap -C data . +decho Concat +cp full.tar full2.tar +tar -A -f full2.tar incr.tar +decho Extract +mkdir out +tar -xvf full2.tar -g /dev/null -C out +decho List +find out | sort +], +[0], +[Level 0 +./ +./dir/ +./dir/file +Level 1 +./ +./dir2/ +Concat +Extract +./ +./dir/ +./dir/file +./ +./dir2/ +List +out +out/dir2 +out/dir2/file +], +[Level 0 +tar: .: Directory is new +tar: ./dir: Directory is new +Level 1 +tar: ./dir2: Directory has been renamed from './dir' +Concat +Extract +List +],[],[],[gnu]) + +AT_CLEANUP diff --git a/tests/testsuite.at b/tests/testsuite.at index 46e42d34..085011c6 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -305,6 +305,7 @@ m4_include([incr07.at]) m4_include([incr08.at]) m4_include([incr09.at]) m4_include([incr10.at]) +m4_include([incr11.at]) AT_BANNER([Files removed while archiving]) m4_include([filerem01.at])