tar: handle tarfiles with (broken) checksums a-la Sun.
authorDenis Vlasenko <vda.linux@googlemail.com>
Sat, 3 Mar 2007 20:06:59 +0000 (20:06 -0000)
committerDenis Vlasenko <vda.linux@googlemail.com>
Sat, 3 Mar 2007 20:06:59 +0000 (20:06 -0000)
archival/libunarchive/get_header_tar.c
archival/tar.c

index 622f09fa5ba71e682b58c9fac9da3e3b0bac92f2..a9659181ebf56e410ba18f3c7b5250c0eef018a5 100644 (file)
@@ -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");
        }
 
index 1cdae296dfaf83d0b862104aa9346a991357af76..992128ef45eaa72c024453d675aa6b7fa964d3eb 100644 (file)
@@ -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;