From: Wayne Davison Date: Wed, 21 Oct 2009 05:05:38 +0000 (-0700) Subject: Added write-devices.diff patch from Darryl Dixon. X-Git-Url: https://mattmccutchen.net/rsync/rsync-patches.git/commitdiff_plain/8763cc5d2a566cfa3de2624addf37ffe3888f2a9 Added write-devices.diff patch from Darryl Dixon. --- diff --git a/write-devices.diff b/write-devices.diff new file mode 100644 index 0000000..42d9c80 --- /dev/null +++ b/write-devices.diff @@ -0,0 +1,147 @@ +This patch adds the --write-devices option, which will try to write +data into a device when used as a destination. + +To use this patch, run these commands for a successful build: + + patch -p1 MAX_SERVER_ARGS) { /* Not possible... */ + rprintf(FERROR, "argc overflow in server_options().\n"); + exit_cleanup(RERR_MALLOC); +diff --git a/receiver.c b/receiver.c +--- a/receiver.c ++++ b/receiver.c +@@ -37,6 +37,7 @@ extern int protocol_version; + extern int relative_paths; + extern int preserve_hard_links; + extern int preserve_perms; ++extern int write_devices; + extern int preserve_xattrs; + extern int basis_dir_cnt; + extern int make_backups; +@@ -198,6 +199,7 @@ int open_tmpfile(char *fnametmp, const char *fname, struct file_struct *file) + static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r, + const char *fname, int fd, OFF_T total_size) + { ++ STRUCT_STAT st; + static char file_sum1[MAX_DIGEST_LEN]; + struct map_struct *mapbuf; + struct sum_struct sum; +@@ -317,10 +319,14 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r, + goto report_write_error; + + #ifdef HAVE_FTRUNCATE +- if (inplace && fd != -1 +- && ftruncate(fd, offset) < 0) { +- rsyserr(FERROR_XFER, errno, "ftruncate failed on %s", +- full_fname(fname)); ++ (void)do_fstat(fd,&st); ++ /* Makes no sense to attempt to ftruncate() a block device: */ ++ if (!(IS_DEVICE(st.st_mode))) { ++ if (inplace && fd != -1 ++ && ftruncate(fd, offset) < 0) { ++ rsyserr(FERROR_XFER, errno, "ftruncate failed on %s", ++ full_fname(fname)); ++ } + } + #endif + +@@ -728,11 +734,25 @@ int recv_files(int f_in, int f_out, char *local_name) + continue; + } + +- if (fd1 != -1 && !S_ISREG(st.st_mode)) { ++ if (fd1 != -1 && !(S_ISREG(st.st_mode) || (write_devices && IS_DEVICE(st.st_mode)))) { + close(fd1); + fd1 = -1; + } + ++ /* On Linux systems (at least), st_size is typically 0 for devices. ++ * If so, try to determine the actual device size. */ ++ if (fd1 != -1 && IS_DEVICE(st.st_mode) && st.st_size == 0) { ++ OFF_T off = lseek(fd1, 0, SEEK_END); ++ if (off == (OFF_T) -1) ++ rsyserr(FERROR, errno, "failed to seek to end of %s to determine size", fname); ++ else { ++ st.st_size = off; ++ off = lseek(fd1, 0, SEEK_SET); ++ if (off != 0) ++ rsyserr(FERROR, errno, "failed to seek back to beginning of %s to read it", fname); ++ } ++ } ++ + /* If we're not preserving permissions, change the file-list's + * mode based on the local permissions and some heuristics. */ + if (!preserve_perms) {