tar: improve OLDGNU compat, make old SUN compat configurable

1_7_stable
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 the old GNU format; help to kill this old format by
repacking your ancient archives with the new format. 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 config FEATURE_TAR_GNU_EXTENSIONS
bool "Enable support for some GNU tar extensions" bool "Enable support for some GNU tar extensions"
default y default y

View File

@ -16,8 +16,9 @@ typedef struct hardlinks_s {
char get_header_cpio(archive_handle_t *archive_handle) char get_header_cpio(archive_handle_t *archive_handle)
{ {
static hardlinks_t *saved_hardlinks = NULL; static hardlinks_t *saved_hardlinks = NULL;
static unsigned short pending_hardlinks = 0; static unsigned pending_hardlinks = 0;
static int inode; static int inode;
file_header_t *file_header = archive_handle->file_header; file_header_t *file_header = archive_handle->file_header;
char cpio_header[110]; char cpio_header[110];
int namesize; int namesize;

View File

@ -36,7 +36,7 @@ static unsigned long long getOctal(char *str, int len)
*/ */
str[len] = '\0'; str[len] = '\0';
v = strtoull(str, &str, 8); 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"); bb_error_msg_and_die("corrupted octal value in tar header");
return v; return v;
} }
@ -45,7 +45,7 @@ static unsigned long long getOctal(char *str, int len)
void BUG_tar_header_size(void); void BUG_tar_header_size(void);
char get_header_tar(archive_handle_t *archive_handle) char get_header_tar(archive_handle_t *archive_handle)
{ {
static int end; static smallint end;
file_header_t *file_header = archive_handle->file_header; file_header_t *file_header = archive_handle->file_header;
struct { struct {
@ -69,7 +69,10 @@ char get_header_tar(archive_handle_t *archive_handle)
char padding[12]; /* 500-512 */ char padding[12]; /* 500-512 */
} tar; } tar;
char *cp; 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; int parse_names;
if (sizeof(tar) != 512) 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 * POSIX says that checksum is done on unsigned bytes, but
* Sun and HP-UX gets it wrong... more details in * Sun and HP-UX gets it wrong... more details in
* GNU tar source. */ * 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++) { for (i = 0; i < 148 ; i++) {
sum_u += ((unsigned char*)&tar)[i]; sum_u += ((unsigned char*)&tar)[i];
#if ENABLE_FEATURE_TAR_OLDSUN_COMPATIBILITY
sum_s += ((signed char*)&tar)[i]; sum_s += ((signed char*)&tar)[i];
#endif
} }
for (i = 156; i < 512 ; i++) { for (i = 156; i < 512 ; i++) {
sum_u += ((unsigned char*)&tar)[i]; sum_u += ((unsigned char*)&tar)[i];
#if ENABLE_FEATURE_TAR_OLDSUN_COMPATIBILITY
sum_s += ((signed char*)&tar)[i]; sum_s += ((signed char*)&tar)[i];
#endif
} }
/* This field does not need special treatment (getOctal) */ #if ENABLE_FEATURE_TAR_OLDGNU_COMPATIBILITY
sum = xstrtoul(tar.chksum, 8); sum = strtoul(tar.chksum, &cp, 8);
if (sum_u != sum && sum_s != sum) { if ((*cp && *cp != ' ')
|| (sum_u != sum USE_FEATURE_TAR_OLDSUN_COMPATIBILITY(&& sum_s != sum))
) {
bb_error_msg_and_die("invalid tar header checksum"); 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 */ /* 0 is reserved for high perf file, treat as normal file */
if (!tar.typeflag) tar.typeflag = '0'; if (!tar.typeflag) tar.typeflag = '0';