X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2Fextract.c;h=e62671e985fb32076623a5c7a06f6c273c4d9e0a;hb=d46025b23c5bbe31902ba4e902312ce8fe05ed63;hp=9d00c80bf3877f21574d7ef8c9ec06f9e0290a49;hpb=89d2ad35e60c1d72102eb3504f2b20b4977b3e7f;p=chaz%2Ftar diff --git a/src/extract.c b/src/extract.c index 9d00c80..e62671e 100644 --- a/src/extract.c +++ b/src/extract.c @@ -486,148 +486,6 @@ maybe_recoverable (char *file_name, int *interdir_made) } } -/* Translate the sparse information on the header, and in any - subsequent extended headers, into an array of structures with true - numbers, as opposed to character strings. Return nonzero if - successful. - - This function invalidates current_header. */ - -bool -fill_in_sparse_array (void) -{ - off_t sparse_data_size = current_stat_info.stat.st_size; - off_t file_size = OFF_FROM_HEADER (current_header->oldgnu_header.realsize); - int sparses; - int counter; - union block *h = current_header; - - init_sparsearray (); - - for (sparses = 0; sparses < SPARSES_IN_OLDGNU_HEADER; sparses++) - { - struct sparse const *s = &h->oldgnu_header.sp[sparses]; - off_t offset; - size_t numbytes; - if (s->numbytes[0] == '\0') - break; - sparsearray[sparses].offset = offset = OFF_FROM_HEADER (s->offset); - sparsearray[sparses].numbytes = numbytes = - SIZE_FROM_HEADER (s->numbytes); - sparse_data_size -= numbytes; - if (offset < 0 || file_size < offset + numbytes || sparse_data_size < 0) - goto invalid_member; - } - - if (h->oldgnu_header.isextended) - do - { - h = find_next_block (); - if (! h) - { - ERROR ((0, 0, _("Unexpected EOF in archive"))); - return 0; - } - - for (counter = 0; counter < SPARSES_IN_SPARSE_HEADER; counter++) - { - struct sparse const *s = &h->sparse_header.sp[counter]; - off_t offset; - size_t numbytes; - if (s->numbytes[0] == '\0') - break; - - if (sparses == sp_array_size) - { - sp_array_size *= 2; - sparsearray = - xrealloc (sparsearray, - sp_array_size * sizeof *sparsearray); - } - - sparsearray[sparses].offset = offset = - OFF_FROM_HEADER (s->offset); - sparsearray[sparses].numbytes = numbytes = - SIZE_FROM_HEADER (s->numbytes); - sparse_data_size -= numbytes; - if (offset < 0 || file_size < offset + numbytes - || sparse_data_size < 0) - goto invalid_member; - sparses++; - } - - set_next_block_after (h); - - } while (h->sparse_header.isextended); - - return 1; - - invalid_member: - ERROR ((0, 0, _("%s: invalid sparse archive member"), - current_stat_info.file_name)); - return 0; -} - - -static off_t -extract_sparse_file (int fd, char const *name, - off_t sizeleft, off_t file_size) -{ - int sparse_ind = 0; - - while (sizeleft != 0) - { - size_t written; - size_t count; - union block *data_block = find_next_block (); - if (! data_block) - { - ERROR ((0, 0, _("Unexpected EOF in archive"))); - return sizeleft; - } - if (lseek (fd, sparsearray[sparse_ind].offset, SEEK_SET) < 0) - { - seek_error_details (name, sparsearray[sparse_ind].offset); - return sizeleft; - } - written = sparsearray[sparse_ind++].numbytes; - while (written > BLOCKSIZE) - { - count = full_write (fd, data_block->buffer, BLOCKSIZE); - written -= count; - sizeleft -= count; - if (count != BLOCKSIZE) - { - write_error_details (name, count, BLOCKSIZE); - return sizeleft; - } - set_next_block_after (data_block); - data_block = find_next_block (); - if (! data_block) - { - ERROR ((0, 0, _("Unexpected EOF in archive"))); - return sizeleft; - } - } - - count = full_write (fd, data_block->buffer, written); - sizeleft -= count; - - if (count != written) - { - write_error_details (name, count, written); - return sizeleft; - } - - set_next_block_after (data_block); - } - - if (ftruncate (fd, file_size) != 0) - truncate_error (name); - - return 0; -} - /* Fix the statuses of all directories whose statuses need fixing, and which are not ancestors of FILE_NAME. If AFTER_SYMLINKS is nonzero, do this for all such directories; otherwise, stop at the @@ -712,9 +570,9 @@ extract_archive (void) /* Print the block from current_header and current_stat. */ if (verbose_option) - print_header (-1); + print_header (¤t_stat_info, -1); - file_name = safer_name_suffix (current_stat_info.file_name, 0); + file_name = safer_name_suffix (current_stat_info.file_name, false); if (strip_path_elements) { size_t prefix_len = stripped_prefix_len (file_name, strip_path_elements); @@ -743,12 +601,14 @@ extract_archive (void) /* Extract the archive entry according to its type. */ typeflag = current_header->header.typeflag; + /*KLUDGE */ + if (current_format == POSIX_FORMAT + && current_stat_info.archive_file_size != current_stat_info.stat.st_size) + typeflag = GNUTYPE_SPARSE; + switch (typeflag) { case GNUTYPE_SPARSE: - file_size = OFF_FROM_HEADER (current_header->oldgnu_header.realsize); - if (! fill_in_sparse_array ()) - return; /* Fall through. */ case AREGTYPE: @@ -823,21 +683,7 @@ extract_archive (void) extract_file: if (typeflag == GNUTYPE_SPARSE) { - char *name; - size_t name_length_bis; - - /* Kludge alert. NAME is assigned to header.name because - during the extraction, the space that contains the header - will get scribbled on, and the name will get munged, so any - error messages that happen to contain the filename will look - REAL interesting unless we do this. */ - - name_length_bis = strlen (file_name) + 1; - name = xmalloc (name_length_bis); - memcpy (name, file_name, name_length_bis); - size = extract_sparse_file (fd, name, - current_stat_info.stat.st_size, file_size); - free (sparsearray); + sparse_extract_file (fd, ¤t_stat_info, &size); } else for (size = current_stat_info.stat.st_size; size > 0; ) @@ -1015,7 +861,8 @@ extract_archive (void) again_link: { - char const *link_name = safer_name_suffix (current_stat_info.link_name, 1); + char const *link_name = safer_name_suffix (current_stat_info.link_name, + true); struct stat st1, st2; int e;