tar: improve OLDGNU compat, make old SUN compat configurable
This commit is contained 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
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
 
 | 
			
		||||
@@ -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';
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user