From: Paul Eggert Date: Tue, 5 Aug 2025 22:45:35 +0000 (-0700) Subject: cp: port better to old limited hosts X-Git-Tag: v9.8~49 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=5b5dcb70566f9622573d54eb2cc32184e953d9cc;p=thirdparty%2Fcoreutils.git 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. --- diff --git a/src/copy-file-data.c b/src/copy-file-data.c index 3a139689de..2b72492c09 100644 --- a/src/copy-file-data.c +++ b/src/copy-file-data.c @@ -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. */ diff --git a/src/copy.c b/src/copy.c index e9bfff9420..9d9a0079e6 100644 --- a/src/copy.c +++ b/src/copy.c @@ -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, ©_debug); + COUNT_MAX, x, ©_debug); if (!return_val) goto close_src_and_dst_desc; } diff --git a/src/copy.h b/src/copy.h index ccb00d8073..5b7af32f76 100644 --- a/src/copy.h +++ b/src/copy.h @@ -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));