diff options
-rw-r--r-- | archival/Config.in | 9 | ||||
-rw-r--r-- | archival/libunarchive/get_header_cpio.c | 3 | ||||
-rw-r--r-- | archival/libunarchive/get_header_tar.c | 29 |
3 files changed, 35 insertions, 6 deletions
diff --git a/archival/Config.in b/archival/Config.in index 661c71ccf..49070da06 100644 --- a/archival/Config.in +++ b/archival/Config.in @@ -205,6 +205,15 @@ config FEATURE_TAR_OLDGNU_COMPATIBILITY the old GNU format; help to kill this old format by repacking your ancient archives with the new format. +config FEATURE_TAR_OLDSUN_COMPATIBILITY + bool "Enable untarring of tarballs with checksums produced by buggy Sun tar" + default N + depends on TAR + help + This option is required to unpack archives created by some old + version of Sun's tar (it was calculating checksum using signed arithmetic). + It is said to be fixed in newer Sun tar, but "old" tarballs still exist. + config FEATURE_TAR_GNU_EXTENSIONS bool "Enable support for some GNU tar extensions" default y diff --git a/archival/libunarchive/get_header_cpio.c b/archival/libunarchive/get_header_cpio.c index 724368be2..3f5135512 100644 --- a/archival/libunarchive/get_header_cpio.c +++ b/archival/libunarchive/get_header_cpio.c @@ -16,8 +16,9 @@ typedef struct hardlinks_s { char get_header_cpio(archive_handle_t *archive_handle) { static hardlinks_t *saved_hardlinks = NULL; - static unsigned short pending_hardlinks = 0; + static unsigned pending_hardlinks = 0; static int inode; + file_header_t *file_header = archive_handle->file_header; char cpio_header[110]; int namesize; diff --git a/archival/libunarchive/get_header_tar.c b/archival/libunarchive/get_header_tar.c index d42f4c276..1a7a687cf 100644 --- a/archival/libunarchive/get_header_tar.c +++ b/archival/libunarchive/get_header_tar.c @@ -36,7 +36,7 @@ static unsigned long long getOctal(char *str, int len) */ str[len] = '\0'; v = strtoull(str, &str, 8); - if (*str) + if (*str && (!ENABLE_FEATURE_TAR_OLDGNU_COMPATIBILITY || *str != ' ')) bb_error_msg_and_die("corrupted octal value in tar header"); return v; } @@ -45,7 +45,7 @@ static unsigned long long getOctal(char *str, int len) void BUG_tar_header_size(void); char get_header_tar(archive_handle_t *archive_handle) { - static int end; + static smallint end; file_header_t *file_header = archive_handle->file_header; struct { @@ -69,7 +69,10 @@ char get_header_tar(archive_handle_t *archive_handle) char padding[12]; /* 500-512 */ } tar; char *cp; - int i, sum_u, sum_s, sum; + int i, sum_u, sum; +#if ENABLE_FEATURE_TAR_OLDSUN_COMPATIBILITY + int sum_s; +#endif int parse_names; if (sizeof(tar) != 512) @@ -115,20 +118,36 @@ char get_header_tar(archive_handle_t *archive_handle) * POSIX says that checksum is done on unsigned bytes, but * Sun and HP-UX gets it wrong... more details in * GNU tar source. */ - sum_s = sum_u = ' ' * sizeof(tar.chksum); +#if ENABLE_FEATURE_TAR_OLDSUN_COMPATIBILITY + sum_s = ' ' * sizeof(tar.chksum); +#endif + sum_u = ' ' * sizeof(tar.chksum); for (i = 0; i < 148 ; i++) { sum_u += ((unsigned char*)&tar)[i]; +#if ENABLE_FEATURE_TAR_OLDSUN_COMPATIBILITY sum_s += ((signed char*)&tar)[i]; +#endif } for (i = 156; i < 512 ; i++) { sum_u += ((unsigned char*)&tar)[i]; +#if ENABLE_FEATURE_TAR_OLDSUN_COMPATIBILITY sum_s += ((signed char*)&tar)[i]; +#endif + } +#if ENABLE_FEATURE_TAR_OLDGNU_COMPATIBILITY + sum = strtoul(tar.chksum, &cp, 8); + if ((*cp && *cp != ' ') + || (sum_u != sum USE_FEATURE_TAR_OLDSUN_COMPATIBILITY(&& sum_s != sum)) + ) { + bb_error_msg_and_die("invalid tar header checksum"); } +#else /* This field does not need special treatment (getOctal) */ sum = xstrtoul(tar.chksum, 8); - if (sum_u != sum && sum_s != sum) { + if (sum_u != sum USE_FEATURE_TAR_OLDSUN_COMPATIBILITY(&& sum_s != sum)) { bb_error_msg_and_die("invalid tar header checksum"); } +#endif /* 0 is reserved for high perf file, treat as normal file */ if (!tar.typeflag) tar.typeflag = '0'; |