tar: improve OLDGNU compat, make old SUN compat configurable

This commit is contained in:
Denis Vlasenko 2007-06-21 12:41:59 +00:00
parent 9a33780152
commit a80b4a0fa7
3 changed files with 37 additions and 8 deletions

View File

@ -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

View File

@ -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;

View File

@ -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
}
/* This field does not need special treatment (getOctal) */
sum = xstrtoul(tar.chksum, 8);
if (sum_u != sum && sum_s != sum) {
#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 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';