* might be left at the end of the file. (Resetting before rather than after a copy attempt is safer
* because a previous attempt might have failed half-way, leaving the file offset at some undefined
* place.) */
- if (lseek(source_fd, 0, SEEK_SET) < 0)
- return log_error_errno(errno, "Failed to seek in \"%s\": %m", source_path);
-
- r = copy_bytes(source_fd, write_fd, UINT64_MAX, COPY_REFLINK);
+ r = copy_bytes(source_fd, write_fd, UINT64_MAX, COPY_REFLINK|COPY_SEEK0_SOURCE);
if (r < 0)
return log_error_errno(r, "Failed to copy data from \"%s\" to \"%s\": %m", source_path, dest_path);
if (lseek(whole_fd, p->offset, SEEK_SET) < 0)
return log_error_errno(errno, "Failed to seek to partition offset: %m");
- if (lseek(t->fd, 0, SEEK_SET) < 0)
- return log_error_errno(errno, "Failed to seek to start of temporary file: %m");
-
if (fstat(t->fd, &st) < 0)
return log_error_errno(errno, "Failed to stat temporary file: %m");
"Partition %" PRIu64 "'s contents (%s) don't fit in the partition (%s).",
p->partno, FORMAT_BYTES(st.st_size), FORMAT_BYTES(p->new_size));
- r = copy_bytes(t->fd, whole_fd, UINT64_MAX, COPY_REFLINK|COPY_HOLES|COPY_FSYNC);
+ r = copy_bytes(t->fd, whole_fd, UINT64_MAX, COPY_REFLINK|COPY_HOLES|COPY_FSYNC|COPY_SEEK0_SOURCE);
if (r < 0)
return log_error_errno(r, "Failed to copy bytes to partition: %m");
} else {
if (fdt < 0)
return fdt;
+ if (FLAGS_SET(copy_flags, COPY_SEEK0_SOURCE) &&
+ lseek(fdf, 0, SEEK_SET) < 0)
+ return -errno;
+
+ if (FLAGS_SET(copy_flags, COPY_SEEK0_TARGET) &&
+ lseek(fdt, 0, SEEK_SET) < 0)
+ return -errno;
+
/* Try btrfs reflinks first. This only works on regular, seekable files, hence let's check the file offsets of
* source and destination first. */
if ((copy_flags & COPY_REFLINK)) {
off_t foffset;
- foffset = lseek(fdf, 0, SEEK_CUR);
+ /* In reflink mode we need to know where the current file offset is, but if we just seeked to
+ * 0 anyway, we can suppress that. */
+ foffset = FLAGS_SET(copy_flags, COPY_SEEK0_SOURCE) ? 0 : lseek(fdf, 0, SEEK_CUR);
if (foffset >= 0) {
off_t toffset;
- toffset = lseek(fdt, 0, SEEK_CUR);
+ toffset = FLAGS_SET(copy_flags, COPY_SEEK0_TARGET) ? 0 : lseek(fdt, 0, SEEK_CUR);
if (toffset >= 0) {
if (foffset == 0 && toffset == 0 && max_bytes == UINT64_MAX)
/* Make sure the file is now higher than max_bytes */
assert_se(ftruncate(fd2, max_bytes + 1) == 0);
- assert_se(lseek(fd2, 0, SEEK_SET) == 0);
-
- r = copy_bytes(fd2, fd3, max_bytes, try_reflink ? COPY_REFLINK : 0);
+ r = copy_bytes(fd2, fd3, max_bytes, COPY_SEEK0_SOURCE | (try_reflink ? COPY_REFLINK : 0));
if (max_bytes == UINT64_MAX)
assert_se(r == 0);
else
assert_se(lseek(fd, 0, SEEK_END) == 2 * blksz);
/* Only ftruncate() can create holes at the end of a file. */
assert_se(ftruncate(fd, 3 * blksz) >= 0);
- assert_se(lseek(fd, 0, SEEK_SET) >= 0);
- assert_se(copy_bytes(fd, fd_copy, UINT64_MAX, COPY_HOLES) >= 0);
+ assert_se(copy_bytes(fd, fd_copy, UINT64_MAX, COPY_SEEK0_SOURCE|COPY_HOLES) >= 0);
/* Test that the hole starts at the beginning of the file. */
assert_se(lseek(fd_copy, 0, SEEK_HOLE) == 0);
assert_se(st.st_size == 3 * blksz);
/* Copy to the middle of the second hole */
- assert_se(lseek(fd, 0, SEEK_SET) >= 0);
- assert_se(lseek(fd_copy, 0, SEEK_SET) >= 0);
assert_se(ftruncate(fd_copy, 0) >= 0);
- assert_se(copy_bytes(fd, fd_copy, 4 * blksz, COPY_HOLES) >= 0);
+ assert_se(copy_bytes(fd, fd_copy, 4 * blksz, COPY_SEEK0_SOURCE|COPY_SEEK0_TARGET|COPY_HOLES) >= 0);
ASSERT_OK_ERRNO(fstat(fd_copy, &st));
assert_se(st.st_size == 4 * blksz);
/* Copy to the end of the second hole */
- assert_se(lseek(fd, 0, SEEK_SET) >= 0);
- assert_se(lseek(fd_copy, 0, SEEK_SET) >= 0);
assert_se(ftruncate(fd_copy, 0) >= 0);
- assert_se(copy_bytes(fd, fd_copy, 5 * blksz, COPY_HOLES) >= 0);
+ assert_se(copy_bytes(fd, fd_copy, 5 * blksz, COPY_SEEK0_SOURCE|COPY_SEEK0_TARGET|COPY_HOLES) >= 0);
ASSERT_OK_ERRNO(fstat(fd_copy, &st));
assert_se(st.st_size == 5 * blksz);
/* Copy everything */
- assert_se(lseek(fd, 0, SEEK_SET) >= 0);
- assert_se(lseek(fd_copy, 0, SEEK_SET) >= 0);
assert_se(ftruncate(fd_copy, 0) >= 0);
- assert_se(copy_bytes(fd, fd_copy, UINT64_MAX, COPY_HOLES) >= 0);
+ assert_se(copy_bytes(fd, fd_copy, UINT64_MAX, COPY_SEEK0_SOURCE|COPY_SEEK0_TARGET|COPY_HOLES) >= 0);
ASSERT_OK_ERRNO(fstat(fd_copy, &st));
assert_se(st.st_size == 6 * blksz);