+ /* Skip past the header in the archive, and past any extended headers. */
+
+ set_next_block_after (current_header);
+ if (current_header->oldgnu_header.isextended)
+ skip_extended_headers ();
+
+ if (multi_volume_option)
+ assign_string (&save_name, current_file_name);
+
+ /* Skip to the next header on the archive. */
+
+ skip_file (current_stat.st_size);
+
+ if (multi_volume_option)
+ assign_string (&save_name, 0);
+}
+
+/*-----------------------------------------------------------------------.
+| 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.st_size. |
+| |
+| Return 1 for success, 0 if the checksum is bad, EOF on eof, 2 for a |
+| block full of zeros (EOF marker). |
+| |
+| 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 (void)
+{
+ 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;
+ char **longp;
+ char *bp;
+ union block *data_block;
+ size_t size, written;
+ static char *next_long_name, *next_long_link;
+
+ while (1)
+ {
+ 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;
+
+ /* Good block. Decode file size and return. */
+
+ if (header->header.typeflag == LNKTYPE)
+ current_stat.st_size = 0; /* links 0 size on tape */
+ else
+ current_stat.st_size = OFF_FROM_HEADER (header->header.size);
+
+ if (header->header.typeflag == GNUTYPE_LONGNAME
+ || header->header.typeflag == GNUTYPE_LONGLINK)
+ {
+ longp = ((header->header.typeflag == GNUTYPE_LONGNAME)
+ ? &next_long_name
+ : &next_long_link);
+
+ set_next_block_after (header);
+ if (*longp)
+ free (*longp);
+ size = current_stat.st_size;
+ if (size != current_stat.st_size)
+ FATAL_ERROR ((0, 0, _("Memory exhausted")));
+ bp = *longp = xmalloc (size);
+
+ for (; size > 0; size -= written)
+ {
+ data_block = find_next_block ();
+ if (! data_block)
+ {
+ ERROR ((0, 0, _("Unexpected EOF on archive file")));
+ break;