diff options
| author | Denys Vlasenko <vda.linux@googlemail.com> | 2015-10-22 13:30:34 +0200 |
|---|---|---|
| committer | Denys Vlasenko <vda.linux@googlemail.com> | 2015-10-22 13:30:34 +0200 |
| commit | f167e4503d08561054e75deb2ff123be2b30afa5 (patch) | |
| tree | 9b5d8c110cdf4438d59df874f70204da8c55003b | |
| parent | 62ae323df0856546754ecfe226fc9bf0dc16bcb8 (diff) | |
| download | busybox-w32-f167e4503d08561054e75deb2ff123be2b30afa5.tar.gz busybox-w32-f167e4503d08561054e75deb2ff123be2b30afa5.tar.bz2 busybox-w32-f167e4503d08561054e75deb2ff123be2b30afa5.zip | |
tar: shrink hardlink name handling code
function old new delta
data_extract_all 1069 1040 -29
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
| -rw-r--r-- | archival/libarchive/data_extract_all.c | 43 |
1 files changed, 17 insertions, 26 deletions
diff --git a/archival/libarchive/data_extract_all.c b/archival/libarchive/data_extract_all.c index bd51d2ad3..cf821c9de 100644 --- a/archival/libarchive/data_extract_all.c +++ b/archival/libarchive/data_extract_all.c | |||
| @@ -12,12 +12,11 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle) | |||
| 12 | file_header_t *file_header = archive_handle->file_header; | 12 | file_header_t *file_header = archive_handle->file_header; |
| 13 | int dst_fd; | 13 | int dst_fd; |
| 14 | int res; | 14 | int res; |
| 15 | char *hard_link; | ||
| 15 | #if ENABLE_FEATURE_TAR_LONG_OPTIONS | 16 | #if ENABLE_FEATURE_TAR_LONG_OPTIONS |
| 16 | char *dst_name; | 17 | char *dst_name; |
| 17 | char *dst_link; | ||
| 18 | #else | 18 | #else |
| 19 | # define dst_name (file_header->name) | 19 | # define dst_name (file_header->name) |
| 20 | # define dst_link (file_header->link_target) | ||
| 21 | #endif | 20 | #endif |
| 22 | 21 | ||
| 23 | #if ENABLE_FEATURE_TAR_SELINUX | 22 | #if ENABLE_FEATURE_TAR_SELINUX |
| @@ -31,9 +30,14 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle) | |||
| 31 | } | 30 | } |
| 32 | #endif | 31 | #endif |
| 33 | 32 | ||
| 33 | /* Hard links are encoded as regular files of size 0 | ||
| 34 | * with a nonempty link field */ | ||
| 35 | hard_link = NULL; | ||
| 36 | if (S_ISREG(file_header->mode) && file_header->size == 0) | ||
| 37 | hard_link = file_header->link_target; | ||
| 38 | |||
| 34 | #if ENABLE_FEATURE_TAR_LONG_OPTIONS | 39 | #if ENABLE_FEATURE_TAR_LONG_OPTIONS |
| 35 | dst_name = file_header->name; | 40 | dst_name = file_header->name; |
| 36 | dst_link = file_header->link_target; | ||
| 37 | if (archive_handle->tar__strip_components) { | 41 | if (archive_handle->tar__strip_components) { |
| 38 | unsigned n = archive_handle->tar__strip_components; | 42 | unsigned n = archive_handle->tar__strip_components; |
| 39 | do { | 43 | do { |
| @@ -47,21 +51,18 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle) | |||
| 47 | * Link target is shortened only for hardlinks: | 51 | * Link target is shortened only for hardlinks: |
| 48 | * softlinks restored unchanged. | 52 | * softlinks restored unchanged. |
| 49 | */ | 53 | */ |
| 50 | if (S_ISREG(file_header->mode) | 54 | if (hard_link) { |
| 51 | && file_header->size == 0 | ||
| 52 | && dst_link | ||
| 53 | ) { | ||
| 54 | // GNU tar 1.26 does not check that we reached end of link name: | 55 | // GNU tar 1.26 does not check that we reached end of link name: |
| 55 | // if "dir/hardlink" is hardlinked to "file", | 56 | // if "dir/hardlink" is hardlinked to "file", |
| 56 | // tar xvf a.tar --strip-components=1 says: | 57 | // tar xvf a.tar --strip-components=1 says: |
| 57 | // tar: hardlink: Cannot hard link to '': No such file or directory | 58 | // tar: hardlink: Cannot hard link to '': No such file or directory |
| 58 | // and continues processing. We silently skip such entries. | 59 | // and continues processing. We silently skip such entries. |
| 59 | dst_link = strchr(dst_link, '/'); | 60 | hard_link = strchr(hard_link, '/'); |
| 60 | if (!dst_link || dst_link[1] == '\0') { | 61 | if (!hard_link || hard_link[1] == '\0') { |
| 61 | data_skip(archive_handle); | 62 | data_skip(archive_handle); |
| 62 | return; | 63 | return; |
| 63 | } | 64 | } |
| 64 | dst_link++; | 65 | hard_link++; |
| 65 | } | 66 | } |
| 66 | } while (--n != 0); | 67 | } while (--n != 0); |
| 67 | } | 68 | } |
| @@ -79,12 +80,7 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle) | |||
| 79 | if (archive_handle->ah_flags & ARCHIVE_UNLINK_OLD) { | 80 | if (archive_handle->ah_flags & ARCHIVE_UNLINK_OLD) { |
| 80 | /* Remove the entry if it exists */ | 81 | /* Remove the entry if it exists */ |
| 81 | if (!S_ISDIR(file_header->mode)) { | 82 | if (!S_ISDIR(file_header->mode)) { |
| 82 | /* Is it hardlink? | 83 | if (hard_link) { |
| 83 | * We encode hard links as regular files of size 0 with a symlink */ | ||
| 84 | if (S_ISREG(file_header->mode) | ||
| 85 | && file_header->size == 0 | ||
| 86 | && dst_link | ||
| 87 | ) { | ||
| 88 | /* Ugly special case: | 84 | /* Ugly special case: |
| 89 | * tar cf t.tar hardlink1 hardlink2 hardlink1 | 85 | * tar cf t.tar hardlink1 hardlink2 hardlink1 |
| 90 | * results in this tarball structure: | 86 | * results in this tarball structure: |
| @@ -92,7 +88,7 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle) | |||
| 92 | * hardlink2 -> hardlink1 | 88 | * hardlink2 -> hardlink1 |
| 93 | * hardlink1 -> hardlink1 <== !!! | 89 | * hardlink1 -> hardlink1 <== !!! |
| 94 | */ | 90 | */ |
| 95 | if (strcmp(dst_link, dst_name) == 0) | 91 | if (strcmp(hard_link, dst_name) == 0) |
| 96 | goto ret; | 92 | goto ret; |
| 97 | } | 93 | } |
| 98 | /* Proceed with deleting */ | 94 | /* Proceed with deleting */ |
| @@ -128,19 +124,14 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle) | |||
| 128 | } | 124 | } |
| 129 | } | 125 | } |
| 130 | 126 | ||
| 131 | /* Handle hard links separately | 127 | /* Handle hard links separately */ |
| 132 | * We encode hard links as regular files of size 0 with a symlink */ | 128 | if (hard_link) { |
| 133 | if (S_ISREG(file_header->mode) | 129 | res = link(hard_link, dst_name); |
| 134 | && file_header->size == 0 | ||
| 135 | && dst_link | ||
| 136 | ) { | ||
| 137 | /* Hard link */ | ||
| 138 | res = link(dst_link, dst_name); | ||
| 139 | if (res != 0 && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)) { | 130 | if (res != 0 && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)) { |
| 140 | bb_perror_msg("can't create %slink " | 131 | bb_perror_msg("can't create %slink " |
| 141 | "from %s to %s", "hard", | 132 | "from %s to %s", "hard", |
| 142 | dst_name, | 133 | dst_name, |
| 143 | dst_link); | 134 | hard_link); |
| 144 | } | 135 | } |
| 145 | /* Hardlinks have no separate mode/ownership, skip chown/chmod */ | 136 | /* Hardlinks have no separate mode/ownership, skip chown/chmod */ |
| 146 | goto ret; | 137 | goto ret; |
