]> Dogcows Code - chaz/tar/commitdiff
(tar_checksum): New function
authorSergey Poznyakoff <gray@gnu.org.ua>
Fri, 26 Nov 2004 19:09:26 +0000 (19:09 +0000)
committerSergey Poznyakoff <gray@gnu.org.ua>
Fri, 26 Nov 2004 19:09:26 +0000 (19:09 +0000)
src/list.c

index b592c8beb0ffe52cc736984d299ae77043ef1034..0d96e8bb67eaef9d9e4ab05552e57c771838b1da 100644 (file)
@@ -266,6 +266,61 @@ list_archive (void)
     assign_string (&save_name, 0);
 }
 
+/* Check header checksum */
+/* The standard BSD tar sources create the checksum by adding up the
+   bytes in the header as type char.  I think the type char was unsigned
+   on the PDP-11, but it's signed on the Next and Sun.  It looks like the
+   sources to BSD tar were never changed to compute the checksum
+   correctly, so both the Sun and Next add the bytes of the header as
+   signed chars.  This doesn't cause a problem until you get a file with
+   a name containing characters with the high bit set.  So tar_checksum
+   computes two checksums -- signed and unsigned.  */
+
+enum read_header
+tar_checksum (union block *header)
+{
+  size_t i;
+  int unsigned_sum = 0;                /* the POSIX one :-) */
+  int signed_sum = 0;          /* the Sun one :-( */
+  int recorded_sum;
+  uintmax_t parsed_sum;
+  char *p;
+  
+  p = header->buffer;
+  for (i = sizeof *header; i-- != 0;)
+    {
+      unsigned_sum += (unsigned char) *p;
+      signed_sum += (signed char) (*p++);
+    }
+
+  if (unsigned_sum == 0)
+    return HEADER_ZERO_BLOCK;
+
+  /* Adjust checksum to count the "chksum" field as blanks.  */
+
+  for (i = sizeof header->header.chksum; i-- != 0;)
+    {
+      unsigned_sum -= (unsigned char) header->header.chksum[i];
+      signed_sum -= (signed char) (header->header.chksum[i]);
+    }
+  unsigned_sum += ' ' * sizeof header->header.chksum;
+  signed_sum += ' ' * sizeof header->header.chksum;
+
+  parsed_sum = from_header (header->header.chksum,
+                           sizeof header->header.chksum, 0,
+                           (uintmax_t) 0,
+                           (uintmax_t) TYPE_MAXIMUM (int));
+  if (parsed_sum == (uintmax_t) -1)
+    return HEADER_FAILURE;
+
+  recorded_sum = parsed_sum;
+  
+  if (unsigned_sum != recorded_sum && signed_sum != recorded_sum)
+    return HEADER_FAILURE;
+
+  return HEADER_SUCCESS;
+}
+
 /* Read a block that's supposed to be a header block.  Return its
    address in "current_header", and if it is good, the file's size in
    current_stat_info.stat.st_size.
@@ -279,23 +334,9 @@ list_archive (void)
    You must always set_next_block_after(current_header) to skip past
    the header which this routine reads.  */
 
-/* The standard BSD tar sources create the checksum by adding up the
-   bytes in the header as type char.  I think the type char was unsigned
-   on the PDP-11, but it's signed on the Next and Sun.  It looks like the
-   sources to BSD tar were never changed to compute the checksum
-   correctly, so both the Sun and Next add the bytes of the header as
-   signed chars.  This doesn't cause a problem until you get a file with
-   a name containing characters with the high bit set.  So read_header
-   computes two checksums -- signed and unsigned.  */
-
 enum read_header
 read_header (bool raw_extended_headers)
 {
-  size_t i;
-  int unsigned_sum;            /* the POSIX one :-) */
-  int signed_sum;              /* the Sun one :-( */
-  int recorded_sum;
-  uintmax_t parsed_sum;
   char *p;
   union block *header;
   union block *header_copy;
@@ -309,44 +350,15 @@ read_header (bool raw_extended_headers)
 
   while (1)
     {
+      enum read_header status;
+      
       header = find_next_block ();
       current_header = header;
       if (!header)
        return HEADER_END_OF_FILE;
 
-      unsigned_sum = 0;
-      signed_sum = 0;
-      p = header->buffer;
-      for (i = sizeof *header; i-- != 0;)
-       {
-         unsigned_sum += (unsigned char) *p;
-         signed_sum += (signed char) (*p++);
-       }
-
-      if (unsigned_sum == 0)
-       return HEADER_ZERO_BLOCK;
-
-      /* Adjust checksum to count the "chksum" field as blanks.  */
-
-      for (i = sizeof header->header.chksum; i-- != 0;)
-       {
-         unsigned_sum -= (unsigned char) header->header.chksum[i];
-         signed_sum -= (signed char) (header->header.chksum[i]);
-       }
-      unsigned_sum += ' ' * sizeof header->header.chksum;
-      signed_sum += ' ' * sizeof header->header.chksum;
-
-      parsed_sum = from_header (header->header.chksum,
-                               sizeof header->header.chksum, 0,
-                               (uintmax_t) 0,
-                               (uintmax_t) TYPE_MAXIMUM (int));
-      if (parsed_sum == (uintmax_t) -1)
-       return HEADER_FAILURE;
-
-      recorded_sum = parsed_sum;
-
-      if (unsigned_sum != recorded_sum && signed_sum != recorded_sum)
-       return HEADER_FAILURE;
+      if ((status = tar_checksum (header)) != HEADER_SUCCESS)
+       return status;
 
       /* Good block.  Decode file size and return.  */
 
This page took 0.026217 seconds and 4 git commands to generate.