tar: handle tarfiles with (broken) checksums a-la Sun.
No binary (build failed)
—
(log yok)
| @@ -69,7 +69,7 @@ char get_header_tar(archive_handle_t *archive_handle) | |
| char padding[12]; /* 500-512 */ | |
| } tar; | |
| char *cp; | |
| - | int sum, i; |
| + | int i, sum_u, sum_s, sum; |
| int parse_names; | |
| if (sizeof(tar) != 512) | |
| @@ -110,16 +110,23 @@ char get_header_tar(archive_handle_t *archive_handle) | |
| #endif | |
| bb_error_msg_and_die("invalid tar magic"); | |
| } | |
| - | /* Do checksum on headers */ |
| - | sum = ' ' * sizeof(tar.chksum); |
| + | |
| + | /* Do checksum on headers. |
| + | * POSIX says that checksum is done on unsigned bytes, but |
| + | * Sun and HP-UX fucked it up... more details in |
| + | * GNU tar source. */ |
| + | sum_s = sum_u = ' ' * sizeof(tar.chksum); |
| for (i = 0; i < 148 ; i++) { | |
| - | sum += ((char*)&tar)[i]; |
| + | sum_u += ((unsigned char*)&tar)[i]; |
| + | sum_s += ((signed char*)&tar)[i]; |
| } | |
| for (i = 156; i < 512 ; i++) { | |
| - | sum += ((char*)&tar)[i]; |
| + | sum_u += ((unsigned char*)&tar)[i]; |
| + | sum_s += ((signed char*)&tar)[i]; |
| } | |
| /* This field does not need special treatment (getOctal) */ | |
| - | if (sum != xstrtoul(tar.chksum, 8)) { |
| + | sum = xstrtoul(tar.chksum, 8); |
| + | if (sum_u != sum && sum_s != sum) { |
| bb_error_msg_and_die("invalid tar header checksum"); | |
| } | |
| @@ -173,6 +173,9 @@ static void putOctal(char *cp, int len, off_t value) | |
| static void chksum_and_xwrite(int fd, struct TarHeader* hp) | |
| { | |
| + | /* POSIX says that checksum is done on unsigned bytes |
| + | * (Sun and HP-UX fucked it up... more details in |
| + | * GNU tar source) */ |
| const unsigned char *cp; | |
| int chksum, size; | |