1
0
mirror of git://git.sv.gnu.org/coreutils.git synced 2026-02-14 03:12:10 +02:00

cp: port better to old limited hosts

Port better ancient platforms where OFF_T_MAX is only 2**31 - 1,
but some devices have more than that many bytes.
* src/copy-file-data.c (copy_file_data): Byte count is now
count_t, not off_t.  All callers changed.  Since we need to check
for overflow anyway, also check for too-small calls to fadvise.
This commit is contained in:
Paul Eggert
2025-08-05 15:45:35 -07:00
parent 06a6758d03
commit 5b5dcb7056
3 changed files with 14 additions and 5 deletions

View File

@@ -493,13 +493,13 @@ infer_scantype (int fd, struct stat const *sb, off_t pos,
/* Copy data from input file (descriptor IFD, status IST, initial file
offset IPOS, and name INAME) to output file (OFD, OST, OPOS, ONAME).
Copy until IBYTES have been copied or until end of file;
if IBYTES is OFF_T_MAX that suffices to copy to end of file.
if IBYTES is COUNT_MAX that suffices to copy to end of file.
Respect copy options X's sparse_mode and reflink_mode settings.
Read and update *DEBUG as needed. */
bool
copy_file_data (int ifd, struct stat const *ist, off_t ipos, char const *iname,
int ofd, struct stat const *ost, off_t opos, char const *oname,
off_t ibytes, struct cp_options const *x, struct copy_debug *debug)
count_t ibytes, struct cp_options const *x, struct copy_debug *debug)
{
/* Choose a suitable buffer size; it may be adjusted later. */
size_t buf_size = io_blksize (ost);
@@ -518,7 +518,11 @@ copy_file_data (int ifd, struct stat const *ist, off_t ipos, char const *iname,
|| (x->sparse_mode == SPARSE_AUTO
&& scantype != PLAIN_SCANTYPE)));
fdadvise (ifd, ipos, ibytes, FADVISE_SEQUENTIAL);
/* Don't bother calling fadvise for small copies, as it is not
likely to help performance and might even hurt it. */
if (IO_BUFSIZE < ibytes)
fdadvise (ifd, ipos, ibytes <= OFF_T_MAX - ipos ? ibytes : 0,
FADVISE_SEQUENTIAL);
/* If not making a sparse file, try to use a more-efficient
buffer size. */

View File

@@ -1048,7 +1048,7 @@ copy_reg (char const *src_name, char const *dst_name,
{
return_val = copy_file_data (source_desc, &src_open_sb, 0, src_name,
dest_desc, &sb, 0, dst_name,
OFF_T_MAX, x, &copy_debug);
COUNT_MAX, x, &copy_debug);
if (!return_val)
goto close_src_and_dst_desc;
}

View File

@@ -321,6 +321,11 @@ struct copy_debug
enum copy_debug_val sparse_detection;
};
/* The type of a large counter. Although it is always nonnegative,
it is signed to help signed overflow checking catch any bugs. */
typedef intmax_t count_t;
#define COUNT_MAX INTMAX_MAX
bool copy (char const *src_name, char const *dst_name,
int dst_dirfd, char const *dst_relname,
int nonexistent_dst, const struct cp_options *options,
@@ -331,7 +336,7 @@ bool copy_file_data (int ifd, struct stat const *ist, off_t ipos,
char const *iname,
int ofd, struct stat const *ost, off_t opos,
char const *oname,
off_t ibytes, struct cp_options const *x,
count_t ibytes, struct cp_options const *x,
struct copy_debug *copy_debug)
_GL_ATTRIBUTE_NONNULL ((2, 4, 6, 8, 10, 11));