chiark / gitweb /
[1/5] Apply missing fixes from upstream
[elogind.git] / src / basic / copy.c
index 163bbf7c7a7ee24cb66fb325f2ee5e0df0d2bd6d..3c02fd41ea22710e27788a9fcc37b689cb020dc8 100644 (file)
@@ -29,7 +29,7 @@
 
 #define COPY_BUFFER_SIZE (16*1024)
 
-int copy_bytes(int fdf, int fdt, off_t max_bytes, bool try_reflink) {
+int copy_bytes(int fdf, int fdt, uint64_t max_bytes, bool try_reflink) {
         bool try_sendfile = true, try_splice = true;
         int r;
 
@@ -37,22 +37,26 @@ int copy_bytes(int fdf, int fdt, off_t max_bytes, bool try_reflink) {
         assert(fdt >= 0);
 #if 0
         /* Try btrfs reflinks first. */
-        if (try_reflink && max_bytes == (off_t) -1) {
+        if (try_reflink &&
+            max_bytes == (uint64_t) -1 &&
+            lseek(fdf, 0, SEEK_CUR) == 0 &&
+            lseek(fdt, 0, SEEK_CUR) == 0) {
+
                 r = btrfs_reflink(fdf, fdt);
                 if (r >= 0)
-                        return r;
+                        return 0; /* we copied the whole thing, hence hit EOF, return 0 */
         }
 #endif // 0
         for (;;) {
                 size_t m = COPY_BUFFER_SIZE;
                 ssize_t n;
 
-                if (max_bytes != (off_t) -1) {
+                if (max_bytes != (uint64_t) -1) {
 
                         if (max_bytes <= 0)
                                 return -EFBIG;
 
-                        if ((off_t) m > max_bytes)
+                        if ((uint64_t) m > max_bytes)
                                 m = (size_t) max_bytes;
                 }
 
@@ -91,7 +95,7 @@ int copy_bytes(int fdf, int fdt, off_t max_bytes, bool try_reflink) {
 
                 /* As a fallback just copy bits by hand */
                 {
-                        char buf[m];
+                        uint8_t buf[m];
 
                         n = read(fdf, buf, m);
                         if (n < 0)
@@ -105,13 +109,13 @@ int copy_bytes(int fdf, int fdt, off_t max_bytes, bool try_reflink) {
                 }
 
         next:
-                if (max_bytes != (off_t) -1) {
-                        assert(max_bytes >= n);
+                if (max_bytes != (uint64_t) -1) {
+                        assert(max_bytes >= (uint64_t) n);
                         max_bytes -= n;
                 }
         }
 
-        return 0;
+        return 0; /* return 0 if we hit EOF earlier than the size limit */
 }
 
 // UNNEEDED by elogind
@@ -154,7 +158,7 @@ static int fd_copy_regular(int df, const char *from, const struct stat *st, int
         if (fdt < 0)
                 return -errno;
 
-        r = copy_bytes(fdf, fdt, (off_t) -1, true);
+        r = copy_bytes(fdf, fdt, (uint64_t) -1, true);
         if (r < 0) {
                 unlinkat(dt, to, 0);
                 return r;
@@ -373,7 +377,7 @@ int copy_file_fd(const char *from, int fdt, bool try_reflink) {
         if (fdf < 0)
                 return -errno;
 
-        r = copy_bytes(fdf, fdt, (off_t) -1, try_reflink);
+        r = copy_bytes(fdf, fdt, (uint64_t) -1, try_reflink);
 
         (void) copy_times(fdf, fdt);
         (void) copy_xattr(fdf, fdt);