问题
I need to use sendfile64 to copy about 16GB of files. What I have achieved so far is
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/sendfile.h>
#include <sys/stat.h>
int main (int argc, char** argv)
{
long long src;
long long dest;
struct stat64 stat_buf;
off64_t offset = 0LL;
long long rc;
if (argc != 3) {
fprintf(stderr, "usage: %s <source> <destination>\n", argv[0]);
exit(1);
}
src = open64(argv[1], O_RDONLY);
if (src == -1) {
fprintf(stderr, "unable to open '%s': %s\n", argv[1], strerror(errno));
exit(1);
}
fstat64(src, &stat_buf);
dest = open64(argv[2], O_WRONLY|O_CREAT, stat_buf.st_mode);
if (dest == -1) {
fprintf(stderr, "unable to open '%s': %s\n", argv[2], strerror(errno));
exit(1);
}
/* copy file using sendfile */
rc = sendfile64 (dest, src, &offset, stat_buf.st_size);
if (rc == -1) {
fprintf(stderr, "error from sendfile: %s\n", strerror(errno));
exit(1);
}
if (rc != stat_buf.st_size) {
fprintf(stderr, "incomplete transfer from sendfile: %lld of %lld bytes\n",
rc,
(long long)stat_buf.st_size);
exit(1);
}
/* clean up and exit */
close(dest);
close(src);
return 0;
}
I have compiled using
g++ BigCopy2.cpp -o BigCopy2 -D_FILE_OFFSET_BITS=64 -DLARGEFILE64_SOURCE
The problem is I still can't copy more than 2GB of file.
Can someone point me where is my mistake?
回答1:
You should use a loop to copy it all, sendfile() might, for various reasons, not copy all the data with one call. As janneb points out, the return value of sendfile64 is a ssize_t, so we should not pass in more than SSIZE_MAX to sendfile, moreover the last argument to sendfile is a size_t which would be 32 bit on 32 bit platforms.
/* copy file using sendfile */
while (offset < stat_buf.st_size) {
size_t count;
off64_t remaining = stat_buf.st_size- offset;
if (remaining > SSIZE_MAX)
count = SSIZE_MAX;
else
count = remaining;
rc = sendfile64 (dest, src, &offset, count);
if (rc == 0) {
break;
}
if (rc == -1) {
fprintf(stderr, "error from sendfile: %s\n", strerror(errno));
exit(1);
}
}
if (offset != stat_buf.st_size) {
fprintf(stderr, "incomplete transfer from sendfile: %lld of %lld bytes\n",
rc,
(long long)stat_buf.st_size);
exit(1);
}
Note that you can replace all your 64 bit variants, off64_t, stat64, sendfile64, with off_t, stat, sendfile. As long as you have the -D_FILE_OFFSET_BITS=64
flag, that define will do the right thing and transform off_t to off64_t, sendfile to sendfile64 and so on if those types and functions are not already 64 bits (such as on 32 bit architectures).
来源:https://stackoverflow.com/questions/22373528/sendfile64-only-copy-about-2gb