From: Wayne Davison Date: Sun, 27 Mar 2022 19:26:39 +0000 (-0700) Subject: Some `--write-device` fixes. X-Git-Tag: v3.2.4pre4~2 X-Git-Url: http://git.samba.org/?p=rsync.git;a=commitdiff_plain;h=8977815f5d70d1b6747837b41e7e0b5bd672ef01 Some `--write-device` fixes. --- diff --git a/NEWS.md b/NEWS.md index f95c6867..6dfed8d0 100644 --- a/NEWS.md +++ b/NEWS.md @@ -87,6 +87,12 @@ per-file compression skipping has apparently never worked, so it is now documented as being ineffective. + - Fixed a truncate error when a `--write-devices` copy wrote a file onto a + device that was shorter than the device. + + - Made `--write-devices` support both `--checksum` and `--no-whole-file` when + copying to a device. + - Improved how the [`--stop-at`](rsync.1#opt), [`--stop-after`](rsync.1#opt), and (the deprecated) [`--time-limit`](rsync.1#opt) options check to see if the allowed time is over, which should make rsync exit more consistently. diff --git a/generator.c b/generator.c index 454fd19f..278e2a6f 100644 --- a/generator.c +++ b/generator.c @@ -35,11 +35,11 @@ extern int inc_recurse; extern int relative_paths; extern int implied_dirs; extern int keep_dirlinks; +extern int write_devices; extern int preserve_acls; extern int preserve_xattrs; extern int preserve_links; extern int preserve_devices; -extern int write_devices; extern int preserve_specials; extern int preserve_hard_links; extern int preserve_executability; @@ -1793,6 +1793,12 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, goto cleanup; } + if (write_devices && IS_DEVICE(sx.st.st_mode) && sx.st.st_size == 0) { + /* This early open into fd skips the regular open below. */ + if ((fd = do_open(fnamecmp, O_RDONLY, 0)) >= 0) + real_sx.st.st_size = sx.st.st_size = get_device_size(fd, fnamecmp); + } + if (fnamecmp_type <= FNAMECMP_BASIS_DIR_HIGH) ; else if (fnamecmp_type >= FNAMECMP_FUZZY) @@ -1858,7 +1864,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, } /* open the file */ - if ((fd = do_open(fnamecmp, O_RDONLY, 0)) < 0) { + if (fd < 0 && (fd = do_open(fnamecmp, O_RDONLY, 0)) < 0) { rsyserr(FERROR, errno, "failed to open %s, continuing", full_fname(fnamecmp)); pretend_missing: @@ -1875,11 +1881,9 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, if (inplace && make_backups > 0 && fnamecmp_type == FNAMECMP_FNAME) { if (!(backupptr = get_backup_name(fname))) { - close(fd); goto cleanup; } if (!(back_file = make_file(fname, NULL, NULL, 0, NO_FILTERS))) { - close(fd); goto pretend_missing; } if (robust_unlink(backupptr) && errno != ENOENT) { @@ -1887,14 +1891,12 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, full_fname(backupptr)); unmake_file(back_file); back_file = NULL; - close(fd); goto cleanup; } if ((f_copy = do_open(backupptr, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0600)) < 0) { rsyserr(FERROR_XFER, errno, "open %s", full_fname(backupptr)); unmake_file(back_file); back_file = NULL; - close(fd); goto cleanup; } fnamecmp_type = FNAMECMP_BACKUP; @@ -1945,7 +1947,6 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, write_sum_head(f_out, NULL); else if (sx.st.st_size <= 0) { write_sum_head(f_out, NULL); - close(fd); } else { if (generate_and_send_sums(fd, sx.st.st_size, f_out, f_copy) < 0) { rprintf(FWARNING, @@ -1953,10 +1954,11 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, fnamecmp); write_sum_head(f_out, NULL); } - close(fd); } cleanup: + if (fd >= 0) + close(fd); if (back_file) { int save_preserve_xattrs = preserve_xattrs; if (f_copy >= 0) diff --git a/receiver.c b/receiver.c index 90e1685b..b3a69da0 100644 --- a/receiver.c +++ b/receiver.c @@ -808,14 +808,16 @@ int recv_files(int f_in, int f_out, char *local_name) continue; } - if (fd1 != -1 && !(S_ISREG(st.st_mode) || (write_devices && IS_DEVICE(st.st_mode)))) { + if (write_devices && IS_DEVICE(st.st_mode)) { + if (fd1 != -1 && st.st_size == 0) + st.st_size = get_device_size(fd1, fname); + /* Mark the file entry as a device so that we don't try to truncate it later on. */ + file->mode = S_IFBLK | (file->mode & ACCESSPERMS); + } else if (fd1 != -1 && !(S_ISREG(st.st_mode))) { close(fd1); fd1 = -1; } - if (fd1 != -1 && IS_DEVICE(st.st_mode) && st.st_size == 0) - st.st_size = get_device_size(fd1, fname); - /* If we're not preserving permissions, change the file-list's * mode based on the local permissions and some heuristics. */ if (!preserve_perms) { diff --git a/rsync.1.md b/rsync.1.md index 06024916..ca0ed7f7 100644 --- a/rsync.1.md +++ b/rsync.1.md @@ -1481,9 +1481,9 @@ your home directory (remove the '=' for that). This option implies the [`--inplace`](#opt) option. Be careful using this, as you should know what devices are present on the - receiving side of the transfer, especially if running rsync as root. + receiving side of the transfer, especially when running rsync as root. - This option is refused by an rsync daemon. + This option is refused by default by an rsync daemon. 0. `--times`, `-t`