mark_after_links (data);
}
+/* If DIR is an intermediate directory created earlier, update its
+ metadata from the current_stat_info and clear, its intermediate
+ status and return true. Return false otherwise.
+ */
+static bool
+update_interdir_set_stat (char const *dir)
+{
+ if (delayed_set_stat_table)
+ {
+ struct delayed_set_stat key, *data;
+
+ key.file_name = (char *) dir;
+ data = hash_lookup (delayed_set_stat_table, &key);
+ if (data && data->interdir)
+ {
+ data->dev = current_stat_info.stat.st_dev;
+ data->ino = current_stat_info.stat.st_ino;
+ data->mode = current_stat_info.stat.st_mode;
+ data->uid = current_stat_info.stat.st_uid;
+ data->gid = current_stat_info.stat.st_gid;
+ data->atime = current_stat_info.atime;
+ data->mtime = current_stat_info.mtime;
+ data->interdir = false;
+ return true;
+ }
+ }
+ return false;
+}
+
/* Update the delayed_set_stat info for an intermediate directory
created within the file name of DIR. The intermediate directory turned
out to be the same as this directory, e.g. due to ".." or symbolic
}
}
}
+ else if (update_interdir_set_stat (file_name))
+ return true;
else if (old_files_option == UNLINK_FIRST_OLD_FILES)
{
status = 0;
extrac25.at\
extrac26.at\
extrac27.at\
+ extrac28.at\
filerem01.at\
filerem02.at\
grow.at\
--- /dev/null
+# Test suite for GNU tar. -*- autotest -*-
+# Copyright 2025 Free Software Foundation, Inc.
+#
+# This file is part of GNU tar.
+#
+# 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 <http://www.gnu.org/licenses/>.
+
+# Description: When invoked with --skip-old-files, tar 1.35 failed
+# to restore mode of a directory member, if the directory was previously
+# created as an intermediate (i.e. member ordering in the archive was
+# inverted).
+# References: https://savannah.gnu.org/bugs/index.php?66774
+
+AT_SETUP([extract intermediates with --skip-old-files])
+AT_KEYWORDS([extract extrac28])
+AT_TAR_CHECK([
+mkdir dir
+chmod 700 dir
+touch dir/one dir/two
+tar cf archive.tar dir/one
+tar rf archive.tar --exclude dir/one dir
+tar tf archive.tar
+rm -rf dir
+tar xf archive.tar --skip-old-files --delay-directory-restore
+genfile --stat=mode.777 dir
+],
+[0],
+[dir/one
+dir/
+dir/two
+700
+])
+AT_CLEANUP
+
+
# Test idea:
# 1. Create a listed-incremental archive of a directory containing
-# a cetrain number of zero-length files.
+# a certain number of zero-length files.
# 2. Using the same snapshot file, create a *multivolume* listed-incremental
# archive. Number of files created in the directory and volume size should
# be selected so that the first volume ends in the midst of the directory
m4_include([extrac25.at])
m4_include([extrac26.at])
m4_include([extrac27.at])
+m4_include([extrac28.at])
m4_include([backup01.at])