Use full-read instead of safe-read
This helps handle archiving on certain filesystems where read() returns less bytes than requested when reading from a regular file. References: https://savannah.gnu.org/bugs/index.php?64426 https://lists.gnu.org/archive/html/bug-tar/2021-07/msg00001.html * gnulib.modules: Add full-read. * src/common.h: Include full-read.h * src/misc.c: Use full_read. * src/sparse.c: Likewise. * src/update.c: Likewise.
This commit is contained in:
@@ -79,7 +79,7 @@ readlinkat
|
|||||||
renameat
|
renameat
|
||||||
root-uid
|
root-uid
|
||||||
rpmatch
|
rpmatch
|
||||||
safe-read
|
full-read
|
||||||
savedir
|
savedir
|
||||||
selinux-at
|
selinux-at
|
||||||
setenv
|
setenv
|
||||||
|
|||||||
@@ -58,6 +58,7 @@
|
|||||||
#include <modechange.h>
|
#include <modechange.h>
|
||||||
#include <quote.h>
|
#include <quote.h>
|
||||||
#include <safe-read.h>
|
#include <safe-read.h>
|
||||||
|
#include <full-read.h>
|
||||||
#include <stat-time.h>
|
#include <stat-time.h>
|
||||||
#include <timespec.h>
|
#include <timespec.h>
|
||||||
#define obstack_chunk_alloc xmalloc
|
#define obstack_chunk_alloc xmalloc
|
||||||
|
|||||||
@@ -821,7 +821,7 @@ deref_stat (char const *name, struct stat *buf)
|
|||||||
size_t
|
size_t
|
||||||
blocking_read (int fd, void *buf, size_t count)
|
blocking_read (int fd, void *buf, size_t count)
|
||||||
{
|
{
|
||||||
size_t bytes = safe_read (fd, buf, count);
|
size_t bytes = full_read (fd, buf, count);
|
||||||
|
|
||||||
#if defined F_SETFL && O_NONBLOCK
|
#if defined F_SETFL && O_NONBLOCK
|
||||||
if (bytes == SAFE_READ_ERROR && errno == EAGAIN)
|
if (bytes == SAFE_READ_ERROR && errno == EAGAIN)
|
||||||
@@ -829,10 +829,12 @@ blocking_read (int fd, void *buf, size_t count)
|
|||||||
int flags = fcntl (fd, F_GETFL);
|
int flags = fcntl (fd, F_GETFL);
|
||||||
if (0 <= flags && flags & O_NONBLOCK
|
if (0 <= flags && flags & O_NONBLOCK
|
||||||
&& fcntl (fd, F_SETFL, flags & ~O_NONBLOCK) != -1)
|
&& fcntl (fd, F_SETFL, flags & ~O_NONBLOCK) != -1)
|
||||||
bytes = safe_read (fd, buf, count);
|
bytes = full_read (fd, buf, count);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (bytes == 0 && errno != 0)
|
||||||
|
bytes = SAFE_READ_ERROR;
|
||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
72
src/sparse.c
72
src/sparse.c
@@ -415,7 +415,7 @@ sparse_dump_region (struct tar_sparse_file *file, size_t i)
|
|||||||
size_t bytes_read;
|
size_t bytes_read;
|
||||||
|
|
||||||
blk = find_next_block ();
|
blk = find_next_block ();
|
||||||
bytes_read = safe_read (file->fd, blk->buffer, bufsize);
|
bytes_read = full_read (file->fd, blk->buffer, bufsize);
|
||||||
if (bytes_read == SAFE_READ_ERROR)
|
if (bytes_read == SAFE_READ_ERROR)
|
||||||
{
|
{
|
||||||
read_diag_details (file->stat_info->orig_file_name,
|
read_diag_details (file->stat_info->orig_file_name,
|
||||||
@@ -427,27 +427,39 @@ sparse_dump_region (struct tar_sparse_file *file, size_t i)
|
|||||||
}
|
}
|
||||||
else if (bytes_read == 0)
|
else if (bytes_read == 0)
|
||||||
{
|
{
|
||||||
char buf[UINTMAX_STRSIZE_BOUND];
|
if (errno != 0)
|
||||||
struct stat st;
|
{
|
||||||
size_t n;
|
read_diag_details (file->stat_info->orig_file_name,
|
||||||
if (fstat (file->fd, &st) == 0)
|
(file->stat_info->sparse_map[i].offset
|
||||||
n = file->stat_info->stat.st_size - st.st_size;
|
+ file->stat_info->sparse_map[i].numbytes
|
||||||
|
- bytes_left),
|
||||||
|
bufsize);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
n = file->stat_info->stat.st_size
|
{
|
||||||
- (file->stat_info->sparse_map[i].offset
|
char buf[UINTMAX_STRSIZE_BOUND];
|
||||||
+ file->stat_info->sparse_map[i].numbytes
|
struct stat st;
|
||||||
- bytes_left);
|
size_t n;
|
||||||
|
if (fstat (file->fd, &st) == 0)
|
||||||
|
n = file->stat_info->stat.st_size - st.st_size;
|
||||||
|
else
|
||||||
|
n = file->stat_info->stat.st_size
|
||||||
|
- (file->stat_info->sparse_map[i].offset
|
||||||
|
+ file->stat_info->sparse_map[i].numbytes
|
||||||
|
- bytes_left);
|
||||||
|
|
||||||
WARNOPT (WARN_FILE_SHRANK,
|
WARNOPT (WARN_FILE_SHRANK,
|
||||||
(0, 0,
|
(0, 0,
|
||||||
ngettext ("%s: File shrank by %s byte; padding with zeros",
|
ngettext ("%s: File shrank by %s byte; padding with zeros",
|
||||||
"%s: File shrank by %s bytes; padding with zeros",
|
"%s: File shrank by %s bytes; padding with zeros",
|
||||||
n),
|
n),
|
||||||
quotearg_colon (file->stat_info->orig_file_name),
|
quotearg_colon (file->stat_info->orig_file_name),
|
||||||
STRINGIFY_BIGINT (n, buf)));
|
STRINGIFY_BIGINT (n, buf)));
|
||||||
if (! ignore_failed_read_option)
|
if (! ignore_failed_read_option)
|
||||||
set_exit_status (TAREXIT_DIFFERS);
|
set_exit_status (TAREXIT_DIFFERS);
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
memset (blk->buffer + bytes_read, 0, BLOCKSIZE - bytes_read);
|
memset (blk->buffer + bytes_read, 0, BLOCKSIZE - bytes_read);
|
||||||
@@ -615,7 +627,7 @@ check_sparse_region (struct tar_sparse_file *file, off_t beg, off_t end)
|
|||||||
size_t rdsize = BLOCKSIZE < end - beg ? BLOCKSIZE : end - beg;
|
size_t rdsize = BLOCKSIZE < end - beg ? BLOCKSIZE : end - beg;
|
||||||
char diff_buffer[BLOCKSIZE];
|
char diff_buffer[BLOCKSIZE];
|
||||||
|
|
||||||
bytes_read = safe_read (file->fd, diff_buffer, rdsize);
|
bytes_read = full_read (file->fd, diff_buffer, rdsize);
|
||||||
if (bytes_read == SAFE_READ_ERROR)
|
if (bytes_read == SAFE_READ_ERROR)
|
||||||
{
|
{
|
||||||
read_diag_details (file->stat_info->orig_file_name,
|
read_diag_details (file->stat_info->orig_file_name,
|
||||||
@@ -625,7 +637,12 @@ check_sparse_region (struct tar_sparse_file *file, off_t beg, off_t end)
|
|||||||
}
|
}
|
||||||
else if (bytes_read == 0)
|
else if (bytes_read == 0)
|
||||||
{
|
{
|
||||||
report_difference (file->stat_info, _("Size differs"));
|
if (errno != 0)
|
||||||
|
read_diag_details (file->stat_info->orig_file_name,
|
||||||
|
beg,
|
||||||
|
rdsize);
|
||||||
|
else
|
||||||
|
report_difference (file->stat_info, _("Size differs"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -668,7 +685,7 @@ check_data_region (struct tar_sparse_file *file, size_t i)
|
|||||||
}
|
}
|
||||||
set_next_block_after (blk);
|
set_next_block_after (blk);
|
||||||
file->dumped_size += BLOCKSIZE;
|
file->dumped_size += BLOCKSIZE;
|
||||||
bytes_read = safe_read (file->fd, diff_buffer, rdsize);
|
bytes_read = full_read (file->fd, diff_buffer, rdsize);
|
||||||
if (bytes_read == SAFE_READ_ERROR)
|
if (bytes_read == SAFE_READ_ERROR)
|
||||||
{
|
{
|
||||||
read_diag_details (file->stat_info->orig_file_name,
|
read_diag_details (file->stat_info->orig_file_name,
|
||||||
@@ -680,7 +697,14 @@ check_data_region (struct tar_sparse_file *file, size_t i)
|
|||||||
}
|
}
|
||||||
else if (bytes_read == 0)
|
else if (bytes_read == 0)
|
||||||
{
|
{
|
||||||
report_difference (¤t_stat_info, _("Size differs"));
|
if (errno != 0)
|
||||||
|
read_diag_details (file->stat_info->orig_file_name,
|
||||||
|
(file->stat_info->sparse_map[i].offset
|
||||||
|
+ file->stat_info->sparse_map[i].numbytes
|
||||||
|
- size_left),
|
||||||
|
rdsize);
|
||||||
|
else
|
||||||
|
report_difference (¤t_stat_info, _("Size differs"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
size_left -= bytes_read;
|
size_left -= bytes_read;
|
||||||
|
|||||||
@@ -60,10 +60,14 @@ append_file (char *file_name)
|
|||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
union block *start = find_next_block ();
|
union block *start = find_next_block ();
|
||||||
size_t status = safe_read (handle, start->buffer,
|
size_t status = full_read (handle, start->buffer,
|
||||||
available_space_after (start));
|
available_space_after (start));
|
||||||
if (status == 0)
|
if (status == 0)
|
||||||
break;
|
{
|
||||||
|
if (errno == 0)
|
||||||
|
break;
|
||||||
|
read_fatal (file_name);
|
||||||
|
}
|
||||||
if (status == SAFE_READ_ERROR)
|
if (status == SAFE_READ_ERROR)
|
||||||
read_fatal (file_name);
|
read_fatal (file_name);
|
||||||
if (status % BLOCKSIZE)
|
if (status % BLOCKSIZE)
|
||||||
|
|||||||
Reference in New Issue
Block a user