/* 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);
|| (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. */
{
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;
}
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,
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));