diff --git a/app-arch/tar/patches/tar-1.27.1.patchset b/app-arch/tar/patches/tar-1.27.1.patchset new file mode 100644 index 000000000..12d248294 --- /dev/null +++ b/app-arch/tar/patches/tar-1.27.1.patchset @@ -0,0 +1,125 @@ +From 5601acb5afe236cc83a2577a5fb36ef478944bab Mon Sep 17 00:00:00 2001 +From: Jonathan Schleifer +Date: Thu, 20 Mar 2014 14:52:58 +0100 +Subject: [PATCH] Patches from tar-1.26 + +--- + src/common.h | 2 ++ + src/extract.c | 41 +++++++++++++++++++++++++++++++++++++++++ + src/tar.c | 7 +++++++ + 3 files changed, 50 insertions(+) + +diff --git a/src/common.h b/src/common.h +index 42fd539..633ca19 100644 +--- a/src/common.h ++++ b/src/common.h +@@ -192,6 +192,8 @@ GLOBAL enum old_files old_files_option; + + GLOBAL bool keep_directory_symlink_option; + ++GLOBAL bool simulate_hardlinks_option; ++ + /* Specified file name for incremental list. */ + GLOBAL const char *listed_incremental_option; + /* Incremental dump level */ +diff --git a/src/extract.c b/src/extract.c +index 9b6b7f9..26b027f 100644 +--- a/src/extract.c ++++ b/src/extract.c +@@ -33,6 +33,8 @@ static bool we_are_root; /* true if our effective uid == 0 */ + static mode_t newdir_umask; /* umask when creating new directories */ + static mode_t current_umask; /* current umask (which is set to 0 if -p) */ + ++static int extract_symlink (char *, int); ++ + #define ALL_MODE_BITS ((mode_t) ~ (mode_t) 0) + + #if ! HAVE_FCHMOD && ! defined fchmod +@@ -1268,6 +1270,38 @@ extract_link (char *file_name, int typeflag) + char const *link_name; + int rc; + ++ if (simulate_hardlinks_option) ++ { ++ /* symlinks have to be normalized */ ++ const char* f = file_name; ++ const char* l = current_stat_info.link_name; ++ int sep_pos = 0; ++ int p_count = 0; ++ char *link_name = (char*) xmalloc(strlen(current_stat_info.link_name) * 2); ++ ++ for (; *f && *l; f++, l++) ++ { ++ if (*f != *l) ++ break; ++ if (*f == DIRECTORY_SEPARATOR) ++ sep_pos = f - file_name; ++ } ++ ++ for (p_count = 0; *f; f++) ++ if (*f == DIRECTORY_SEPARATOR) ++ p_count++; ++ ++ link_name[0] = '\0'; ++ while (p_count--) ++ strcat(link_name, "../"); ++ ++ strcat(link_name, ¤t_stat_info.link_name[sep_pos + 1]); ++ free(current_stat_info.link_name); ++ current_stat_info.link_name = link_name; ++ ++ return extract_symlink(file_name, typeflag); ++ } ++ + link_name = current_stat_info.link_name; + + if (! absolute_names_option && contains_dot_dot (link_name)) +@@ -1357,6 +1391,13 @@ extract_symlink (char *file_name, int typeflag) + #else + static int warned_once; + ++ /* recursion is not welcomed here */ ++ if (simulate_hardlinks_option && typeflag == LINKTYPE) ++ { ++ link_error (current_stat_info.link_name, file_name); ++ return -1; ++ } ++ + if (!warned_once) + { + warned_once = 1; +diff --git a/src/tar.c b/src/tar.c +index 4f5017d..2dd5200 100644 +--- a/src/tar.c ++++ b/src/tar.c +@@ -457,6 +457,8 @@ static struct argp_option options[] = { + {"check-device", CHECK_DEVICE_OPTION, NULL, 0, + N_("check device numbers when creating incremental archives (default)"), + GRID+1 }, ++ {"replace-hardlinks", 'Q', 0, 0, ++ N_("replace hardlinks with corresponding symlink when extracting"), GRID+1 }, + #undef GRID + + #define GRID 30 +@@ -1756,6 +1758,10 @@ parse_opt (int key, char *arg, struct argp_state *state) + set_archive_format (arg); + break; + ++ case 'Q': ++ simulate_hardlinks_option = true; ++ break; ++ + case INDEX_FILE_OPTION: + index_file_name = arg; + break; +@@ -2253,6 +2259,7 @@ decode_options (int argc, char **argv) + unquote_option = true; + tar_sparse_major = 1; + tar_sparse_minor = 0; ++ simulate_hardlinks_option = false; + + owner_option = -1; owner_name_option = NULL; + group_option = -1; group_name_option = NULL; +-- +Jonathan +