-# endif
-# ifdef CONFIG_FEATURE_TAR_GNU_EXTENSIONS
- case 'L': {
- longname = xmalloc(file_header->size + 1);
- archive_xread_all(archive_handle, longname, file_header->size);
- longname[file_header->size] = '\0';
- archive_handle->offset += file_header->size;
-
- return(get_header_tar(archive_handle));
- }
- case 'K': {
- linkname = xmalloc(file_header->size + 1);
- archive_xread_all(archive_handle, linkname, file_header->size);
- linkname[file_header->size] = '\0';
- archive_handle->offset += file_header->size;
-
- file_header->name = linkname;
- return(get_header_tar(archive_handle));
- }
- case 'D':
- case 'M':
- case 'N':
- case 'S':
- case 'V':
- bb_error_msg("Ignoring GNU extension type %c", tar.formated.typeflag);
-# endif
+#if ENABLE_FEATURE_TAR_GNU_EXTENSIONS
+ case 'L':
+ /* free: paranoia: tar with several consecutive longnames */
+ free(longname);
+ /* For paranoia reasons we allocate extra NUL char */
+ longname = xzalloc(file_header->size + 1);
+ /* We read ASCIZ string, including NUL */
+ xread(archive_handle->src_fd, longname, file_header->size);
+ archive_handle->offset += file_header->size;
+ /* return get_header_tar(archive_handle); */
+ /* gcc 4.1.1 didn't optimize it into jump */
+ /* so we will do it ourself, this also saves stack */
+ goto again;
+ case 'K':
+ free(linkname);
+ linkname = xzalloc(file_header->size + 1);
+ xread(archive_handle->src_fd, linkname, file_header->size);
+ archive_handle->offset += file_header->size;
+ /* return get_header_tar(archive_handle); */
+ goto again;
+ case 'D': /* GNU dump dir */
+ case 'M': /* Continuation of multi volume archive */
+ case 'N': /* Old GNU for names > 100 characters */
+ case 'S': /* Sparse file */
+ case 'V': /* Volume header */
+#endif
+ case 'g': /* pax global header */
+ case 'x': { /* pax extended header */
+ off_t sz;
+ bb_error_msg("warning: skipping header '%c'", tar.typeflag);
+ sz = (file_header->size + 511) & ~(off_t)511;
+ archive_handle->offset += sz;
+ sz >>= 9; /* sz /= 512 but w/o contortions for signed div */
+ while (sz--)
+ xread(archive_handle->src_fd, &tar, 512);
+ /* return get_header_tar(archive_handle); */
+ goto again_after_align;
+ }
+ default:
+ bb_error_msg_and_die("unknown typeflag: 0x%x", tar.typeflag);
+ }
+
+#if ENABLE_FEATURE_TAR_GNU_EXTENSIONS
+ if (longname) {
+ file_header->name = longname;
+ longname = NULL;
+ }
+ if (linkname) {
+ file_header->link_name = linkname;
+ linkname = NULL;