Use new sparse file interface.

This commit is contained in:
Sergey Poznyakoff
2003-11-17 07:37:03 +00:00
parent 3cdbeffe30
commit 87fa28ed2a

View File

@@ -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,7 +570,7 @@ extract_archive (void)
/* Print the block from current_header and current_stat. */
if (verbose_option)
print_header (-1);
print_header (&current_stat_info, -1);
file_name = safer_name_suffix (current_stat_info.file_name, 0);
if (strip_path_elements)
@@ -746,9 +604,6 @@ extract_archive (void)
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 +678,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, &current_stat_info, &size);
}
else
for (size = current_stat_info.stat.st_size; size > 0; )