tar/tar-1.15.1-lseek.patch
Peter Vrabec cd8b09bcba - extract sparse files even if the output fd is not seekable.(#154882)
- (sparse_scan_file): Bugfix. offset had incorrect type.
2005-04-15 09:18:16 +00:00

163 lines
4.3 KiB
Diff
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

--- tar-1.15.1/src/sparse.c.lseek 2004-09-06 13:30:57.000000000 +0200
+++ tar-1.15.1/src/sparse.c 2005-04-15 10:33:17.990735744 +0200
@@ -46,6 +46,9 @@
struct tar_sparse_file
{
int fd; /* File descriptor */
+ bool seekable; /* Is fd seekable? */
+ size_t offset; /* Current offset in fd if seekable==false.
+ Otherwise unused */
size_t dumped_size; /* Number of bytes actually written
to the archive */
struct tar_stat_info *stat_info; /* Information about the file */
@@ -54,6 +57,39 @@
reqiure */
};
+/* Dump zeros to file->fd until offset is reached. It is used instead of
+ lseek if the output file is not seekable */
+static long
+dump_zeros (struct tar_sparse_file *file, off_t offset)
+{
+ char buf[BLOCKSIZE];
+
+ if (offset - file->offset < 0)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ memset (buf, 0, sizeof buf);
+ while (file->offset < offset)
+ {
+ size_t size = offset - file->offset;
+ size_t wrbytes;
+
+ if (size > sizeof buf)
+ size = sizeof buf;
+ wrbytes = write (file->fd, buf, size);
+ if (wrbytes <= 0)
+ {
+ if (wrbytes == 0)
+ errno = EINVAL;
+ return -1;
+ }
+ file->offset += wrbytes;
+ }
+ return file->offset;
+}
+
static bool
tar_sparse_member_p (struct tar_sparse_file *file)
{
@@ -130,9 +166,16 @@
static bool
-lseek_or_error (struct tar_sparse_file *file, off_t offset, int whence)
+lseek_or_error (struct tar_sparse_file *file, off_t offset)
{
- if (lseek (file->fd, offset, whence) < 0)
+ off_t off;
+
+ if (file->seekable)
+ off = lseek (file->fd, offset, SEEK_SET);
+ else
+ off = dump_zeros (file, offset);
+
+ if (off < 0)
{
seek_diag_details (file->stat_info->orig_file_name, offset);
return false;
@@ -182,10 +225,10 @@
{
static char buffer[BLOCKSIZE];
size_t count;
- size_t offset = 0;
+ off_t offset = 0;
struct sp_array sp = {0, 0};
- if (!lseek_or_error (file, 0, SEEK_SET))
+ if (!lseek_or_error (file, 0))
return false;
clear_block (buffer);
@@ -269,8 +312,7 @@
union block *blk;
off_t bytes_left = file->stat_info->sparse_map[i].numbytes;
- if (!lseek_or_error (file, file->stat_info->sparse_map[i].offset,
- SEEK_SET))
+ if (!lseek_or_error (file, file->stat_info->sparse_map[i].offset))
return false;
while (bytes_left > 0)
@@ -304,8 +346,7 @@
{
size_t write_size;
- if (!lseek_or_error (file, file->stat_info->sparse_map[i].offset,
- SEEK_SET))
+ if (!lseek_or_error (file, file->stat_info->sparse_map[i].offset))
return false;
write_size = file->stat_info->sparse_map[i].numbytes;
@@ -313,7 +354,7 @@
if (write_size == 0)
{
/* Last block of the file is a hole */
- if (sys_truncate (file->fd))
+ if (file->seekable && sys_truncate (file->fd))
truncate_warn (file->stat_info->orig_file_name);
}
else while (write_size > 0)
@@ -330,6 +371,7 @@
count = full_write (file->fd, blk->buffer, wrbytes);
write_size -= count;
file->dumped_size += count;
+ file->offset += count;
if (count != wrbytes)
{
write_error_details (file->stat_info->orig_file_name,
@@ -351,7 +393,9 @@
file.stat_info = st;
file.fd = fd;
-
+ file.seekable = true; /* File *must* be seekable for dump to work */
+ file.offset = 0;
+
if (!sparse_select_optab (&file)
|| !tar_sparse_init (&file))
return dump_status_not_implemented;
@@ -414,7 +458,9 @@
file.stat_info = st;
file.fd = fd;
-
+ file.seekable = lseek (fd, 0, SEEK_SET) == 0;
+ file.offset = 0;
+
if (!sparse_select_optab (&file)
|| !tar_sparse_init (&file))
return dump_status_not_implemented;
@@ -450,7 +496,7 @@
static bool
check_sparse_region (struct tar_sparse_file *file, off_t beg, off_t end)
{
- if (!lseek_or_error (file, beg, SEEK_SET))
+ if (!lseek_or_error (file, beg))
return false;
while (beg < end)
@@ -486,8 +532,7 @@
{
size_t size_left;
- if (!lseek_or_error (file, file->stat_info->sparse_map[i].offset,
- SEEK_SET))
+ if (!lseek_or_error (file, file->stat_info->sparse_map[i].offset))
return false;
size_left = file->stat_info->sparse_map[i].numbytes;
while (size_left > 0)