Improve --clone-dest.
[rsync-patches.git] / copy-devices.diff
1 This patch adds the --copy-devices option, which will try to copy
2 the data inside a device instead of duplicating the device node.
3
4 To use this patch, run these commands for a successful build:
5
6     patch -p1 <patches/copy-devices.diff
7     ./prepare-source
8     ./configure                      (optional if already run)
9     make
10
11 based-on: d2a97a7ab492e0d0548708251309e077e6aa8c8b
12 diff --git a/generator.c b/generator.c
13 --- a/generator.c
14 +++ b/generator.c
15 @@ -39,6 +39,7 @@ extern int preserve_acls;
16  extern int preserve_xattrs;
17  extern int preserve_links;
18  extern int preserve_devices;
19 +extern int copy_devices;
20  extern int write_devices;
21  extern int preserve_specials;
22  extern int preserve_hard_links;
23 @@ -1673,7 +1674,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
24                 goto cleanup;
25         }
26  
27 -       if (ftype != FT_REG) {
28 +       if (ftype != FT_REG && (!copy_devices || ftype != FT_DEVICE)) {
29                 if (solo_file)
30                         fname = f_name(file, NULL);
31                 rprintf(FINFO, "skipping non-regular file \"%s\"\n", fname);
32 @@ -1894,6 +1895,9 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
33                 fnamecmp_type = FNAMECMP_BACKUP;
34         }
35  
36 +       if (IS_DEVICE(sx.st.st_mode) && sx.st.st_size == 0)
37 +               sx.st.st_size = get_device_size(fd, fnamecmp);
38 +
39         if (DEBUG_GTE(DELTASUM, 3)) {
40                 rprintf(FINFO, "gen mapped %s of size %s\n",
41                         fnamecmp, big_num(sx.st.st_size));
42 diff --git a/options.c b/options.c
43 --- a/options.c
44 +++ b/options.c
45 @@ -47,6 +47,7 @@ int append_mode = 0;
46  int keep_dirlinks = 0;
47  int copy_dirlinks = 0;
48  int copy_links = 0;
49 +int copy_devices = 0;
50  int write_devices = 0;
51  int preserve_links = 0;
52  int preserve_hard_links = 0;
53 @@ -652,6 +653,7 @@ static struct poptOption long_options[] = {
54    {"no-D",             0,  POPT_ARG_NONE,   0, OPT_NO_D, 0, 0 },
55    {"devices",          0,  POPT_ARG_VAL,    &preserve_devices, 1, 0, 0 },
56    {"no-devices",       0,  POPT_ARG_VAL,    &preserve_devices, 0, 0, 0 },
57 +  {"copy-devices",     0,  POPT_ARG_NONE,   &copy_devices, 0, 0, 0 },
58    {"write-devices",    0,  POPT_ARG_VAL,    &write_devices, 1, 0, 0 },
59    {"no-write-devices", 0,  POPT_ARG_VAL,    &write_devices, 0, 0, 0 },
60    {"specials",         0,  POPT_ARG_VAL,    &preserve_specials, 1, 0, 0 },
61 @@ -942,6 +944,7 @@ static void set_refuse_options(void)
62                  || strcmp("iconv", longName) == 0
63                  || strcmp("no-iconv", longName) == 0
64                  || strcmp("checksum-seed", longName) == 0
65 +                || strcmp("copy-devices", longName) == 0 /* disable wild-match (it gets refused below) */
66                  || strcmp("write-devices", longName) == 0 /* disable wild-match (it gets refused below) */
67                  || strcmp("log-format", longName) == 0 /* aka out-format (NOT log-file-format) */
68                  || strcmp("sender", longName) == 0
69 @@ -953,6 +956,7 @@ static void set_refuse_options(void)
70         assert(list_end != NULL);
71  
72         if (am_daemon) { /* Refused by default, but can be accepted via a negated exact match. */
73 +               parse_one_refuse_match(0, "copy-devices", list_end);
74                 parse_one_refuse_match(0, "write-devices", list_end);
75         }
76  
77 @@ -2856,6 +2860,9 @@ void server_options(char **args, int *argc_p)
78         else if (remove_source_files)
79                 args[ac++] = "--remove-sent-files";
80  
81 +       if (copy_devices)
82 +               args[ac++] = "--copy-devices";
83 +
84         if (preallocate_files && am_sender)
85                 args[ac++] = "--preallocate";
86  
87 diff --git a/rsync.1.md b/rsync.1.md
88 --- a/rsync.1.md
89 +++ b/rsync.1.md
90 @@ -368,6 +368,7 @@ detailed description below for a complete description.
91  --owner, -o              preserve owner (super-user only)
92  --group, -g              preserve group
93  --devices                preserve device files (super-user only)
94 +--copy-devices           copy device contents as regular file
95  --specials               preserve special files
96  -D                       same as --devices --specials
97  --times, -t              preserve modification times
98 diff --git a/rsync.c b/rsync.c
99 --- a/rsync.c
100 +++ b/rsync.c
101 @@ -33,6 +33,7 @@ extern int preserve_xattrs;
102  extern int preserve_perms;
103  extern int preserve_executability;
104  extern int preserve_times;
105 +extern int copy_devices;
106  extern int am_root;
107  extern int am_server;
108  extern int am_daemon;
109 @@ -419,7 +420,8 @@ int read_ndx_and_attrs(int f_in, int f_out, int *iflag_ptr, uchar *type_ptr, cha
110  
111         if (iflags & ITEM_TRANSFER) {
112                 int i = ndx - cur_flist->ndx_start;
113 -               if (i < 0 || !S_ISREG(cur_flist->files[i]->mode)) {
114 +               struct file_struct *file = cur_flist->files[i];
115 +               if (i < 0 || !(S_ISREG(file->mode) || (copy_devices && IS_DEVICE(file->mode)))) {
116                         rprintf(FERROR,
117                                 "received request to transfer non-regular file: %d [%s]\n",
118                                 ndx, who_am_i());
119 diff --git a/rsyncd.conf.5.md b/rsyncd.conf.5.md
120 --- a/rsyncd.conf.5.md
121 +++ b/rsyncd.conf.5.md
122 @@ -930,9 +930,10 @@ the values of parameters.  See the GLOBAL PARAMETERS section for more details.
123      If you are un-refusing the compress option, you probably want to match
124      "`!compress*`" so that you also accept the `--compress-level` option.
125  
126 -    Note that the "write-devices" option is refused by default, but can be
127 -    explicitly accepted with "`!write-devices`".  The options "log-file" and
128 -    "log-file-format" are forcibly refused and cannot be accepted.
129 +    Note that the "copy-devices" & "write-devices" options are refused by
130 +    default, but they can be explicitly accepted with "`!copy-devices`" and/or
131 +    "`!write-devices`".  The options "log-file" and "log-file-format" are
132 +    forcibly refused and cannot be accepted.
133  
134      Here are all the options that are not matched by wild-cards:
135  
136 diff --git a/sender.c b/sender.c
137 --- a/sender.c
138 +++ b/sender.c
139 @@ -362,6 +362,9 @@ void send_files(int f_in, int f_out)
140                         exit_cleanup(RERR_FILEIO);
141                 }
142  
143 +               if (IS_DEVICE(st.st_mode) && st.st_size == 0)
144 +                       st.st_size = get_device_size(fd, fname);
145 +
146                 if (append_mode > 0 && st.st_size < F_LENGTH(file)) {
147                         rprintf(FWARNING, "skipped diminished file: %s\n",
148                                 full_fname(fname));