#include <string.h>
#include <unistd.h>
#include <errno.h>
+#include <sys/types.h>
+#ifdef HAVE_SENDFILE
+#include <sys/sendfile.h>
+#endif
#include "c.h"
return c;
}
+static inline ssize_t sendfile_all(int out, int in, off_t *off, size_t count)
+{
+#ifdef HAVE_SENDFILE
+ ssize_t ret;
+ ssize_t c = 0;
+ int tries = 0;
+ while (count) {
+ ret = sendfile(out, in, off, count);
+ if (ret < 0) {
+ if ((errno == EAGAIN || errno == EINTR) && (tries++ < 5)) {
+ xusleep(250000);
+ continue;
+ }
+ return c ? c : -1;
+ }
+ if (ret == 0)
+ return c;
+ tries = 0;
+ count -= ret;
+ c += ret;
+ }
+ return c;
+#else
+ errno = ENOSYS;
+ return -1;
+#endif
+}
+
#endif /* UTIL_LINUX_ALL_IO_H */
#include <unistd.h>
#include <sys/time.h>
#include <sys/resource.h>
-#ifdef HAVE_SENDFILE
-#include <sys/sendfile.h>
-#endif
#include <string.h>
#include "c.h"
#ifdef HAVE_SENDFILE
struct stat st;
ssize_t nw;
- off_t left;
if (fstat(from, &st) == -1)
return -1;
if (!S_ISREG(st.st_mode))
return copy_file_simple(from, to);
- for (left = st.st_size; left != 0; left -= nw) {
- if ((nw = sendfile(to, from, NULL, left)) < 0)
- return copy_file_simple(from, to);
- if (!nw)
- return 0;
- }
- /* For extra robustness, treat st_size as advisory and ensure that we
- * actually get EOF. */
- while ((nw = sendfile(to, from, NULL, 1024*1024)) != 0)
+ if (sendfile_all(to, from, NULL, st.st_size) < 0)
+ return copy_file_simple(from, to);
+ /* ensure we either get an EOF or an error */
+ while ((nw = sendfile_all(to, from, NULL, 16*1024*1024)) != 0)
if (nw < 0)
return copy_file_simple(from, to);
return 0;