summaryrefslogtreecommitdiff
path: root/archival
diff options
context:
space:
mode:
Diffstat (limited to 'archival')
-rw-r--r--archival/Config.in9
-rw-r--r--archival/libunarchive/get_header_cpio.c3
-rw-r--r--archival/libunarchive/get_header_tar.c29
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
205 the old GNU format; help to kill this old format by 205 the old GNU format; help to kill this old format by
206 repacking your ancient archives with the new format. 206 repacking your ancient archives with the new format.
207 207
208config FEATURE_TAR_OLDSUN_COMPATIBILITY
209 bool "Enable untarring of tarballs with checksums produced by buggy Sun tar"
210 default N
211 depends on TAR
212 help
213 This option is required to unpack archives created by some old
214 version of Sun's tar (it was calculating checksum using signed arithmetic).
215 It is said to be fixed in newer Sun tar, but "old" tarballs still exist.
216
208config FEATURE_TAR_GNU_EXTENSIONS 217config FEATURE_TAR_GNU_EXTENSIONS
209 bool "Enable support for some GNU tar extensions" 218 bool "Enable support for some GNU tar extensions"
210 default y 219 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 {
16char get_header_cpio(archive_handle_t *archive_handle) 16char get_header_cpio(archive_handle_t *archive_handle)
17{ 17{
18 static hardlinks_t *saved_hardlinks = NULL; 18 static hardlinks_t *saved_hardlinks = NULL;
19 static unsigned short pending_hardlinks = 0; 19 static unsigned pending_hardlinks = 0;
20 static int inode; 20 static int inode;
21
21 file_header_t *file_header = archive_handle->file_header; 22 file_header_t *file_header = archive_handle->file_header;
22 char cpio_header[110]; 23 char cpio_header[110];
23 int namesize; 24 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)
36 */ 36 */
37 str[len] = '\0'; 37 str[len] = '\0';
38 v = strtoull(str, &str, 8); 38 v = strtoull(str, &str, 8);
39 if (*str) 39 if (*str && (!ENABLE_FEATURE_TAR_OLDGNU_COMPATIBILITY || *str != ' '))
40 bb_error_msg_and_die("corrupted octal value in tar header"); 40 bb_error_msg_and_die("corrupted octal value in tar header");
41 return v; 41 return v;
42} 42}
@@ -45,7 +45,7 @@ static unsigned long long getOctal(char *str, int len)
45void BUG_tar_header_size(void); 45void BUG_tar_header_size(void);
46char get_header_tar(archive_handle_t *archive_handle) 46char get_header_tar(archive_handle_t *archive_handle)
47{ 47{
48 static int end; 48 static smallint end;
49 49
50 file_header_t *file_header = archive_handle->file_header; 50 file_header_t *file_header = archive_handle->file_header;
51 struct { 51 struct {
@@ -69,7 +69,10 @@ char get_header_tar(archive_handle_t *archive_handle)
69 char padding[12]; /* 500-512 */ 69 char padding[12]; /* 500-512 */
70 } tar; 70 } tar;
71 char *cp; 71 char *cp;
72 int i, sum_u, sum_s, sum; 72 int i, sum_u, sum;
73#if ENABLE_FEATURE_TAR_OLDSUN_COMPATIBILITY
74 int sum_s;
75#endif
73 int parse_names; 76 int parse_names;
74 77
75 if (sizeof(tar) != 512) 78 if (sizeof(tar) != 512)
@@ -115,20 +118,36 @@ char get_header_tar(archive_handle_t *archive_handle)
115 * POSIX says that checksum is done on unsigned bytes, but 118 * POSIX says that checksum is done on unsigned bytes, but
116 * Sun and HP-UX gets it wrong... more details in 119 * Sun and HP-UX gets it wrong... more details in
117 * GNU tar source. */ 120 * GNU tar source. */
118 sum_s = sum_u = ' ' * sizeof(tar.chksum); 121#if ENABLE_FEATURE_TAR_OLDSUN_COMPATIBILITY
122 sum_s = ' ' * sizeof(tar.chksum);
123#endif
124 sum_u = ' ' * sizeof(tar.chksum);
119 for (i = 0; i < 148 ; i++) { 125 for (i = 0; i < 148 ; i++) {
120 sum_u += ((unsigned char*)&tar)[i]; 126 sum_u += ((unsigned char*)&tar)[i];
127#if ENABLE_FEATURE_TAR_OLDSUN_COMPATIBILITY
121 sum_s += ((signed char*)&tar)[i]; 128 sum_s += ((signed char*)&tar)[i];
129#endif
122 } 130 }
123 for (i = 156; i < 512 ; i++) { 131 for (i = 156; i < 512 ; i++) {
124 sum_u += ((unsigned char*)&tar)[i]; 132 sum_u += ((unsigned char*)&tar)[i];
133#if ENABLE_FEATURE_TAR_OLDSUN_COMPATIBILITY
125 sum_s += ((signed char*)&tar)[i]; 134 sum_s += ((signed char*)&tar)[i];
135#endif
136 }
137#if ENABLE_FEATURE_TAR_OLDGNU_COMPATIBILITY
138 sum = strtoul(tar.chksum, &cp, 8);
139 if ((*cp && *cp != ' ')
140 || (sum_u != sum USE_FEATURE_TAR_OLDSUN_COMPATIBILITY(&& sum_s != sum))
141 ) {
142 bb_error_msg_and_die("invalid tar header checksum");
126 } 143 }
144#else
127 /* This field does not need special treatment (getOctal) */ 145 /* This field does not need special treatment (getOctal) */
128 sum = xstrtoul(tar.chksum, 8); 146 sum = xstrtoul(tar.chksum, 8);
129 if (sum_u != sum && sum_s != sum) { 147 if (sum_u != sum USE_FEATURE_TAR_OLDSUN_COMPATIBILITY(&& sum_s != sum)) {
130 bb_error_msg_and_die("invalid tar header checksum"); 148 bb_error_msg_and_die("invalid tar header checksum");
131 } 149 }
150#endif
132 151
133 /* 0 is reserved for high perf file, treat as normal file */ 152 /* 0 is reserved for high perf file, treat as normal file */
134 if (!tar.typeflag) tar.typeflag = '0'; 153 if (!tar.typeflag) tar.typeflag = '0';