Index: trunk/src/VBox/Runtime/common/zip/tar.cpp
===================================================================
--- trunk/src/VBox/Runtime/common/zip/tar.cpp	(revision 50086)
+++ trunk/src/VBox/Runtime/common/zip/tar.cpp	(revision 50139)
@@ -41,4 +41,5 @@
 
 #include "internal/magics.h"
+#include "tar.h"
 
 
@@ -269,27 +270,57 @@
 }
 
-DECLINLINE(int) rtTarCalcChkSum(PRTTARRECORD pRecord, uint32_t *pChkSum)
-{
-    uint32_t check = 0;
-    uint32_t zero = 0;
-    for (size_t i = 0; i < sizeof(RTTARRECORD); ++i)
-    {
-        /* Calculate the sum of every byte from the header. The checksum field
-         * itself is counted as all blanks. */
-        if (   i <  RT_UOFFSETOF(RTTARRECORD, h.chksum)
-            || i >= RT_UOFFSETOF(RTTARRECORD, h.linkflag))
-            check += pRecord->d[i];
-        else
-            check += ' ';
-        /* Additional check if all fields are zero, which indicate EOF. */
-        zero += pRecord->d[i];
-    }
-
-    /* EOF? */
-    if (!zero)
-        return VERR_TAR_END_OF_FILE;
-
-    *pChkSum = check;
-    return VINF_SUCCESS;
+/**
+ * Calculates the TAR header checksums and detects if it's all zeros.
+ *
+ * @returns true if all zeros, false if not.
+ * @param   pHdr                The header to checksum.
+ * @param   pi32Unsigned        Where to store the checksum calculated using
+ *                              unsigned chars.   This is the one POSIX
+ *                              specifies.
+ * @param   pi32Signed          Where to store the checksum calculated using
+ *                              signed chars.
+ *
+ * @remarks The reason why we calculate the checksum as both signed and unsigned
+ *          has to do with various the char C type being signed on some hosts
+ *          and unsigned on others.
+ *
+ * @remarks Borrowed from tarvfs.cpp.
+ */
+static bool rtZipTarCalcChkSum(PCRTZIPTARHDR pHdr, int32_t *pi32Unsigned, int32_t *pi32Signed)
+{
+    int32_t i32Unsigned = 0;
+    int32_t i32Signed   = 0;
+
+    /*
+     * Sum up the entire header.
+     */
+    const char *pch    = (const char *)pHdr;
+    const char *pchEnd = pch + sizeof(*pHdr);
+    do
+    {
+        i32Unsigned += *(unsigned char *)pch;
+        i32Signed   += *(signed   char *)pch;
+    } while (++pch != pchEnd);
+
+    /*
+     * Check if it's all zeros and replace the chksum field with spaces.
+     */
+    bool const fZeroHdr = i32Unsigned == 0;
+
+    pch    = pHdr->Common.chksum;
+    pchEnd = pch + sizeof(pHdr->Common.chksum);
+    do
+    {
+        i32Unsigned -= *(unsigned char *)pch;
+        i32Signed   -= *(signed   char *)pch;
+    } while (++pch != pchEnd);
+
+    i32Unsigned += (unsigned char)' ' * sizeof(pHdr->Common.chksum);
+    i32Signed   += (signed   char)' ' * sizeof(pHdr->Common.chksum);
+
+    *pi32Unsigned = i32Unsigned;
+    if (pi32Signed)
+        *pi32Signed = i32Signed;
+    return fZeroHdr;
 }
 
@@ -306,14 +337,14 @@
 
     /* Check for data integrity & an EOF record */
-    uint32_t check = 0;
-    rc = rtTarCalcChkSum(pRecord, &check);
-    /* EOF? */
-    if (RT_FAILURE(rc))
-        return rc;
+    int32_t iUnsignedChksum, iSignedChksum;
+    if (rtZipTarCalcChkSum((PCRTZIPTARHDR)pRecord, &iUnsignedChksum, &iSignedChksum))
+        return VERR_TAR_END_OF_FILE;
 
     /* Verify the checksum */
     uint32_t sum;
     rc = RTStrToUInt32Full(pRecord->h.chksum, 8, &sum);
-    if (RT_SUCCESS(rc) && sum == check)
+    if (   RT_SUCCESS(rc)
+        && (   sum == (uint32_t)iSignedChksum
+            || sum == (uint32_t)iUnsignedChksum) )
     {
         /* Make sure the strings are zero terminated. */
@@ -351,10 +382,10 @@
 
     /* Create the checksum out of the new header */
-    uint32_t uChkSum = 0;
-    int rc = rtTarCalcChkSum(pRecord, &uChkSum);
-    if (RT_FAILURE(rc))
-        return rc;
+    int32_t iUnsignedChksum, iSignedChksum;
+    if (rtZipTarCalcChkSum((PCRTZIPTARHDR)pRecord, &iUnsignedChksum, &iSignedChksum))
+        return VERR_TAR_END_OF_FILE;
+
     /* Format the checksum */
-    RTStrPrintf(pRecord->h.chksum, sizeof(pRecord->h.chksum), "%0.7o", uChkSum);
+    RTStrPrintf(pRecord->h.chksum, sizeof(pRecord->h.chksum), "%0.7o", iUnsignedChksum);
 
     return VINF_SUCCESS;
