[SCM] The rsync repository. - branch master updated

Rsync CVS commit messages rsync-cvs at lists.samba.org
Sun Apr 5 18:45:00 UTC 2020


The branch, master has been updated
       via  4cc3b983 Added the --write-devices option.
      from  b32aa479 Make exit_cleanup() use _exit() if called from a signal handler. Fixes bug #13982.

https://git.samba.org/?p=rsync.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 4cc3b9830134316c8c249e471126424c64fa2fc1
Author: Wayne Davison <wayned at samba.org>
Date:   Sun Apr 5 11:21:02 2020 -0700

    Added the --write-devices option.
    
    This is a fleshed out version of the old one in the patches repo with
    documentation & proper handling of the implied --inplace option for a
    daemon's option-rufusing considerations. I ommitted the -w short option
    as I would hate for someone to turn this on accidentally.

-----------------------------------------------------------------------

Summary of changes:
 generator.c |  3 ++-
 options.c   | 16 ++++++++++++++++
 receiver.c  | 41 ++++++++++++++++++++++++++++-------------
 rsync.yo    | 15 +++++++++++++++
 4 files changed, 61 insertions(+), 14 deletions(-)


Changeset truncated at 500 lines:

diff --git a/generator.c b/generator.c
index 5538a92d..0ceab185 100644
--- a/generator.c
+++ b/generator.c
@@ -39,6 +39,7 @@ 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;
@@ -1688,7 +1689,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
 
 	fnamecmp_type = FNAMECMP_FNAME;
 
-	if (statret == 0 && !S_ISREG(sx.st.st_mode)) {
+	if (statret == 0 && !(S_ISREG(sx.st.st_mode) || (write_devices && IS_DEVICE(sx.st.st_mode)))) {
 		if (delete_item(fname, sx.st.st_mode, del_opts | DEL_FOR_FILE) != 0)
 			goto cleanup;
 		statret = -1;
diff --git a/options.c b/options.c
index 3464f9dd..11dbe96d 100644
--- a/options.c
+++ b/options.c
@@ -50,6 +50,7 @@ int append_mode = 0;
 int keep_dirlinks = 0;
 int copy_dirlinks = 0;
 int copy_links = 0;
+int write_devices = 0;
 int preserve_links = 0;
 int preserve_hard_links = 0;
 int preserve_acls = 0;
@@ -721,6 +722,7 @@ void usage(enum logcode F)
 #else
   rprintf(F,"     --preallocate           pre-allocate dest files on remote receiver\n");
 #endif
+  rprintf(F,"     --write-devices         write to (and read from) devices as files\n");
   rprintf(F," -n, --dry-run               perform a trial run with no changes made\n");
   rprintf(F," -W, --whole-file            copy files whole (without delta-xfer algorithm)\n");
   rprintf(F,"     --checksum-choice=STR   choose the checksum algorithms\n");
@@ -889,6 +891,8 @@ static struct poptOption long_options[] = {
   {"no-D",             0,  POPT_ARG_NONE,   0, OPT_NO_D, 0, 0 },
   {"devices",          0,  POPT_ARG_VAL,    &preserve_devices, 1, 0, 0 },
   {"no-devices",       0,  POPT_ARG_VAL,    &preserve_devices, 0, 0, 0 },
+  {"write-devices",    0,  POPT_ARG_VAL,    &write_devices, 1, 0, 0 },
+  {"no-write-devices", 0,  POPT_ARG_VAL,    &write_devices, 0, 0, 0 },
   {"specials",         0,  POPT_ARG_VAL,    &preserve_specials, 1, 0, 0 },
   {"no-specials",      0,  POPT_ARG_VAL,    &preserve_specials, 0, 0, 0 },
   {"links",           'l', POPT_ARG_VAL,    &preserve_links, 1, 0, 0 },
@@ -1330,6 +1334,7 @@ int parse_arguments(int *argc_p, const char ***argv_p)
 		if (!*lp_charset(module_id))
 			set_refuse_options("iconv");
 #endif
+		set_refuse_options("write-devices");
 	}
 
 #ifdef ICONV_OPTION
@@ -2288,6 +2293,14 @@ int parse_arguments(int *argc_p, const char ***argv_p)
 		inplace = 1;
 	}
 
+	if (write_devices) {
+		if (refused_inplace) {
+			create_refuse_error(refused_inplace);
+			return 0;
+		}
+		inplace = 1;
+	}
+
 	if (delay_updates && !partial_dir)
 		partial_dir = tmp_partialdir;
 
@@ -2806,6 +2819,9 @@ void server_options(char **args, int *argc_p)
 	if (relative_paths && !implied_dirs && (!am_sender || protocol_version >= 30))
 		args[ac++] = "--no-implied-dirs";
 
+	if (write_devices)
+		args[ac++] = "--write-devices";
+
 	if (remove_source_files == 1)
 		args[ac++] = "--remove-source-files";
 	else if (remove_source_files)
diff --git a/receiver.c b/receiver.c
index 799c3d64..e7441f4d 100644
--- a/receiver.c
+++ b/receiver.c
@@ -39,6 +39,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;
@@ -231,13 +232,14 @@ 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)
+			const char *fname, int fd, struct file_struct *file)
 {
 	static char file_sum1[MAX_DIGEST_LEN];
 	struct map_struct *mapbuf;
 	struct sum_struct sum;
 	int sum_len;
 	int32 len;
+	OFF_T total_size = F_LENGTH(file);
 	OFF_T offset = 0;
 	OFF_T offset2;
 	char *data;
@@ -379,7 +381,7 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
 	/* inplace: New data could be shorter than old data.
 	 * preallocate_files: total_size could have been an overestimate.
 	 *     Cut off any extra preallocated zeros from dest file. */
-	if ((inplace || preallocated_len > offset) && fd != -1 && do_ftruncate(fd, offset) < 0) {
+	if ((inplace || preallocated_len > offset) && fd != -1 && !IS_DEVICE(file->mode) && do_ftruncate(fd, offset) < 0) {
 		rsyserr(FERROR_XFER, errno, "ftruncate failed on %s",
 			full_fname(fname));
 	}
@@ -402,9 +404,9 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
 }
 
 
-static void discard_receive_data(int f_in, OFF_T length)
+static void discard_receive_data(int f_in, struct file_struct *file)
 {
-	receive_data(f_in, NULL, -1, 0, NULL, -1, length);
+	receive_data(f_in, NULL, -1, 0, NULL, -1, file);
 }
 
 static void handle_delayed_updates(char *local_name)
@@ -660,7 +662,7 @@ int recv_files(int f_in, int f_out, char *local_name)
 					"(Skipping batched update for%s \"%s\")\n",
 					redoing ? " resend of" : "",
 					fname);
-				discard_receive_data(f_in, F_LENGTH(file));
+				discard_receive_data(f_in, file);
 				file->flags |= FLAG_FILE_SENT;
 				continue;
 			}
@@ -671,13 +673,13 @@ int recv_files(int f_in, int f_out, char *local_name)
 		if (!do_xfers) { /* log the transfer */
 			log_item(FCLIENT, file, iflags, NULL);
 			if (read_batch)
-				discard_receive_data(f_in, F_LENGTH(file));
+				discard_receive_data(f_in, file);
 			continue;
 		}
 		if (write_batch < 0) {
 			log_item(FCLIENT, file, iflags, NULL);
 			if (!am_server)
-				discard_receive_data(f_in, F_LENGTH(file));
+				discard_receive_data(f_in, file);
 			if (inc_recurse)
 				send_msg_int(MSG_SUCCESS, ndx);
 			continue;
@@ -767,7 +769,7 @@ int recv_files(int f_in, int f_out, char *local_name)
 		} else if (do_fstat(fd1,&st) != 0) {
 			rsyserr(FERROR_XFER, errno, "fstat %s failed",
 				full_fname(fnamecmp));
-			discard_receive_data(f_in, F_LENGTH(file));
+			discard_receive_data(f_in, file);
 			close(fd1);
 			if (inc_recurse)
 				send_msg_int(MSG_NO_SEND, ndx);
@@ -782,18 +784,32 @@ int recv_files(int f_in, int f_out, char *local_name)
 			 */
 			rprintf(FERROR_XFER, "recv_files: %s is a directory\n",
 				full_fname(fnamecmp));
-			discard_receive_data(f_in, F_LENGTH(file));
+			discard_receive_data(f_in, file);
 			close(fd1);
 			if (inc_recurse)
 				send_msg_int(MSG_NO_SEND, ndx);
 			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) {
@@ -825,7 +841,7 @@ int recv_files(int f_in, int f_out, char *local_name)
 		}
 
 		if (fd2 == -1) {
-			discard_receive_data(f_in, F_LENGTH(file));
+			discard_receive_data(f_in, file);
 			if (fd1 != -1)
 				close(fd1);
 			if (inc_recurse)
@@ -840,8 +856,7 @@ int recv_files(int f_in, int f_out, char *local_name)
 			rprintf(FINFO, "%s\n", fname);
 
 		/* recv file data */
-		recv_ok = receive_data(f_in, fnamecmp, fd1, st.st_size,
-				       fname, fd2, F_LENGTH(file));
+		recv_ok = receive_data(f_in, fnamecmp, fd1, st.st_size, fname, fd2, file);
 
 		log_item(log_code, file, iflags, NULL);
 
diff --git a/rsync.yo b/rsync.yo
index fdaf3d27..1da5afc6 100644
--- a/rsync.yo
+++ b/rsync.yo
@@ -384,6 +384,7 @@ to the detailed description below for a complete description.  verb(
      --fake-super            store/recover privileged attrs using xattrs
  -S, --sparse                turn sequences of nulls into sparse blocks
      --preallocate           allocate dest files before writing
+     --write-devices         write to (and read from) devices as files
  -n, --dry-run               perform a trial run with no changes made
  -W, --whole-file            copy files whole (w/o delta-xfer algorithm)
      --checksum-choice=STR   choose the checksum algorithms
@@ -1221,6 +1222,20 @@ such as named sockets and fifos.
 
 dit(bf(-D)) The bf(-D) option is equivalent to bf(--devices) bf(--specials).
 
+dit(bf(--write-devices)) This tells rsync to treat a device as though it were
+a regular file, allowing both the writing of file data into a device on the
+receiving side and the reading of the device's data on the sending side. It
+does not require that both sides have the same device status, so a file's
+data can be transferred into a device and a device's data can be extracted
+into a file.
+
+This option implies the bf(--inplace) option.
+
+Be careful using this, as you should know what devices are present on both
+sides of the transfer, especially if running rsync as root.
+
+This option is refused by an rsync daemon.
+
 dit(bf(-t, --times)) This tells rsync to transfer modification times along
 with the files and update them on the remote system.  Note that if this
 option is not used, the optimization that excludes files that have not been


-- 
The rsync repository.



More information about the rsync-cvs mailing list