mirror of
https://github.com/RsyncProject/rsync.git
synced 2026-10-22 22:04:15 -04:00
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.
This commit is contained in:
1 parent
b32aa4797d
commit
9e9d33a2db
4 files changed
+57
-14
No files matched your search
+2
-1
@@ -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;
|
||||
|
||||
@@ -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 devices as files (implies --inplace)\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)
|
||||
|
||||
+28
-13
@@ -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);
|
||||
|
||||
|
||||
@@ -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 devices as files (implies --inplace)
|
||||
-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,16 @@ 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 on the receiving
|
||||
side as a regular file, allowing the writing of file data into a device.
|
||||
|
||||
This option implies the bf(--inplace) 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.
|
||||
|
||||
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
|
||||
|
||||
Reference in new issue
Block a user