+ for (size = current_stat_info.stat.st_size; size > 0; size -= written)
+ {
+ if (multi_volume_option)
+ save_sizeleft = size;
+ data_block = find_next_block ();
+ if (!data_block)
+ {
+ ERROR ((0, 0, _("Unexpected EOF in archive")));
+ break; /* FIXME: What happens, then? */
+ }
+ written = available_space_after (data_block);
+ if (written > size)
+ written = size;
+ errno = 0;
+ check = fwrite (data_block->buffer, sizeof (char), written, stdlis);
+ set_next_block_after ((union block *)
+ (data_block->buffer + written - 1));
+ if (check != written)
+ {
+ write_error_details (current_stat_info.file_name, check, written);
+ skip_file (size - written);
+ break;
+ }
+ }
+ if (multi_volume_option)
+ assign_string (&save_name, 0);
+ fputc ('\n', stdlis);
+ fflush (stdlis);
+ return;
+
+ }
+
+ if (multi_volume_option)
+ assign_string (&save_name, current_stat_info.file_name);
+
+ skip_member ();
+
+ if (multi_volume_option)
+ 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, bool silent)
+{
+ 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), true, silent);
+ 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.
+
+ Return 1 for success, 0 if the checksum is bad, EOF on eof, 2 for a
+ block full of zeros (EOF marker).
+
+ If RAW_EXTENDED_HEADERS is nonzero, do not automagically fold the
+ GNU long name and link headers into later headers.