mirror of
https://git.savannah.gnu.org/git/tar.git
synced 2026-08-22 01:06:03 +00:00
Draft patch for openat2 changes vs --one-top-level
The patch leverages the existing -C code. In order to do that, every entry in the wd[] table gets another companion entry in the table that represents the --one-top-level directory. There is one additional field in each entry that allows skipping the companion entries if they are not desired. The actual directory is created lazily by chdir_do() if needed, as you requested, to avoid empty "a/foo" after --one-top-level=foo -C a -C b. The patch "by the way" fixes also extraction of hardlinks with --one-top-level which currently is broken in the typical case (the transform is not applied to the target, so the hardlink is wrong). The patch does not yet handle the --show-transformed case with --one-top-level that you discussed in another subthread. As a result, two tests now fail (onetop02.at and onetop04.at). I suppose that this would be quite easy to fix. Another issue that I am aware of is that I am not sure whether to call repair_delayed_set_stat and/or delay_set_stat on the newly created directories like extract_dir() does (the whole delay_set code is abit mysterious to me). Use of --create together with --one-top-level should probably be forbidden, as unlink.c uses wd[] in a way that will likely break in the presence of companion entries (the chdir_do call in flush_deferred_unlinks). Show the one-top-level arg as a transformation
This commit is contained in:
committed by
Paul Eggert
parent
e407e6e7dd
commit
1b91f5f66f
+32
-12
@@ -136,16 +136,28 @@ enforce_one_top_level (char **pfile_name)
|
||||
idx_t pos = strlen (one_top_level_dir);
|
||||
if (strncmp (p, one_top_level_dir, pos) == 0)
|
||||
{
|
||||
if (ISSLASH (p[pos]) || p[pos] == 0)
|
||||
return;
|
||||
/* Remove the one_top_level_dir prefix if it ends at
|
||||
component boundary. */
|
||||
if (ISSLASH (p[pos]))
|
||||
{
|
||||
*pfile_name = xstrdup (p[pos+1] ? &p[pos+1] : ".");
|
||||
free (file_name);
|
||||
return;
|
||||
}
|
||||
else if (p[pos] == 0)
|
||||
{
|
||||
*pfile_name = xstrdup (".");
|
||||
free (file_name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
*pfile_name = make_file_name (one_top_level_dir, file_name);
|
||||
normalize_filename_x (*pfile_name);
|
||||
/* If the prefix does not match, do nothing. */
|
||||
}
|
||||
else
|
||||
*pfile_name = xstrdup (one_top_level_dir);
|
||||
free (file_name);
|
||||
{
|
||||
*pfile_name = xstrdup (".");
|
||||
free (file_name);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -171,7 +183,14 @@ transform_stat_info (char typeflag, struct tar_stat_info *stat_info)
|
||||
}
|
||||
|
||||
if (one_top_level_dir)
|
||||
enforce_one_top_level (&stat_info->file_name);
|
||||
{
|
||||
enforce_one_top_level (&stat_info->file_name);
|
||||
/* Hard links are interpreted relative to cwd, and --one-top-level
|
||||
works by means of a hidden change of cwd to the requested directory.
|
||||
Adjust hard link targets as well. */
|
||||
if (typeflag == LNKTYPE)
|
||||
enforce_one_top_level (&stat_info->link_name);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1129,10 +1148,10 @@ static void
|
||||
simple_print_header (struct tar_stat_info *st, union block *blk,
|
||||
off_t block_ordinal)
|
||||
{
|
||||
char *temp_name
|
||||
= (show_transformed_names_option
|
||||
? (st->file_name ? st->file_name : st->orig_file_name)
|
||||
: (st->orig_file_name ? st->orig_file_name : st->file_name));
|
||||
char *temp_name =
|
||||
(show_transformed_names_option
|
||||
? transform_top_level (st->file_name ? st->file_name : st->orig_file_name)
|
||||
: xstrdup (st->orig_file_name ? st->orig_file_name : st->file_name));
|
||||
|
||||
if (block_number_option)
|
||||
{
|
||||
@@ -1331,6 +1350,7 @@ simple_print_header (struct tar_stat_info *st, union block *blk,
|
||||
}
|
||||
fflush (stdlis);
|
||||
xattrs_print (st);
|
||||
free (temp_name);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user