+
+ if (header->header.typeflag == LNKTYPE)
+ current_stat_info.stat.st_size = 0; /* links 0 size on tape */
+ else
+ current_stat_info.stat.st_size = OFF_FROM_HEADER (header->header.size);
+
+ if (header->header.typeflag == GNUTYPE_LONGNAME
+ || header->header.typeflag == GNUTYPE_LONGLINK)
+ {
+ if (raw_extended_headers)
+ return HEADER_SUCCESS_EXTENDED;
+ else
+ {
+ size_t name_size = current_stat_info.stat.st_size;
+ size = name_size - name_size % BLOCKSIZE + 2 * BLOCKSIZE;
+ if (name_size != current_stat_info.stat.st_size || size < name_size)
+ xalloc_die ();
+ }
+
+ header_copy = xmalloc (size + 1);
+
+ if (header->header.typeflag == GNUTYPE_LONGNAME)
+ {
+ if (next_long_name)
+ free (next_long_name);
+ next_long_name = header_copy;
+ next_long_name_blocks = size / BLOCKSIZE;
+ }
+ else
+ {
+ if (next_long_link)
+ free (next_long_link);
+ next_long_link = header_copy;
+ next_long_link_blocks = size / BLOCKSIZE;
+ }
+
+ set_next_block_after (header);
+ *header_copy = *header;
+ bp = header_copy->buffer + BLOCKSIZE;
+
+ for (size -= BLOCKSIZE; size > 0; size -= written)
+ {
+ data_block = find_next_block ();
+ if (! data_block)
+ {
+ ERROR ((0, 0, _("Unexpected EOF in archive")));
+ break;
+ }
+ written = available_space_after (data_block);
+ if (written > size)
+ written = size;
+
+ memcpy (bp, data_block->buffer, written);
+ bp += written;
+ set_next_block_after ((union block *)
+ (data_block->buffer + written - 1));
+ }
+
+ *bp = '\0';
+
+ /* Loop! */
+
+ }
+ else
+ {
+ char const *name;
+ struct posix_header const *h = ¤t_header->header;
+ char namebuf[sizeof h->prefix + 1 + NAME_FIELD_SIZE + 1];
+
+ if (recent_long_name)
+ free (recent_long_name);
+
+ if (next_long_name)
+ {
+ name = next_long_name->buffer + BLOCKSIZE;
+ recent_long_name = next_long_name;
+ recent_long_name_blocks = next_long_name_blocks;
+ }
+ else
+ {
+ /* Accept file names as specified by POSIX.1-1996
+ section 10.1.1. */
+ char *np = namebuf;
+
+ if (h->prefix[0] && strcmp (h->magic, TMAGIC) == 0)
+ {
+ memcpy (np, h->prefix, sizeof h->prefix);
+ np[sizeof h->prefix] = '\0';
+ np += strlen (np);
+ *np++ = '/';
+
+ /* Prevent later references to current_header from
+ mistakenly treating this as an old GNU header.
+ This assignment invalidates h->prefix. */
+ current_header->oldgnu_header.isextended = 0;
+ }
+ memcpy (np, h->name, sizeof h->name);
+ np[sizeof h->name] = '\0';
+ name = namebuf;
+ recent_long_name = 0;
+ recent_long_name_blocks = 0;
+ }
+ assign_string (¤t_stat_info.orig_file_name, name);
+ assign_string (¤t_stat_info.file_name, name);
+ current_stat_info.had_trailing_slash = strip_trailing_slashes (current_stat_info.file_name);
+
+ if (recent_long_link)
+ free (recent_long_link);
+
+ if (next_long_link)
+ {
+ name = next_long_link->buffer + BLOCKSIZE;
+ recent_long_link = next_long_link;
+ recent_long_link_blocks = next_long_link_blocks;
+ }
+ else
+ {
+ memcpy (namebuf, h->linkname, sizeof h->linkname);
+ namebuf[sizeof h->linkname] = '\0';
+ name = namebuf;
+ recent_long_link = 0;
+ recent_long_link_blocks = 0;
+ }
+ assign_string (¤t_stat_info.link_name, name);