Fixed patch fuzz.
[rsync/rsync-patches.git] / remove-sent-files.diff
1 After applying this patch and running configure, you MUST run this
2 command before "make":
3
4     make proto
5
6
7 --- orig/generator.c    2005-02-20 00:02:23
8 +++ generator.c 2005-02-15 21:33:51
9 @@ -42,6 +42,7 @@ extern int preserve_gid;
10  extern int preserve_times;
11  extern int omit_dir_times;
12  extern int delete_during;
13 +extern int remove_sent_files;
14  extern int update_only;
15  extern int opt_ignore_existing;
16  extern int inplace;
17 @@ -559,6 +560,11 @@ static void recv_generator(char *fname, 
18                                 rprintf(code, "%s -> %s\n", safe_fname(fname),
19                                         safe_fname(file->u.link));
20                         }
21 +                       if (remove_sent_files && !dry_run) {
22 +                               char numbuf[4];
23 +                               SIVAL(numbuf, 0, ndx);
24 +                               io_multiplex_write(MSG_SUCCESS, numbuf, 4);
25 +                       }
26                 }
27  #endif
28                 return;
29 --- orig/io.c   2005-02-19 09:27:48
30 +++ io.c        2005-02-15 21:33:51
31 @@ -256,6 +256,14 @@ static void read_msg_fd(void)
32                 read_loop(fd, buf, len);
33                 io_multiplex_write(MSG_DELETED, buf, len);
34                 break;
35 +       case MSG_SUCCESS:
36 +               if (len != 4 || !am_generator) {
37 +                       rprintf(FERROR, "invalid message %d:%d\n", tag, len);
38 +                       exit_cleanup(RERR_STREAMIO);
39 +               }
40 +               read_loop(fd, buf, len);
41 +               io_multiplex_write(MSG_SUCCESS, buf, len);
42 +               break;
43         case MSG_INFO:
44         case MSG_ERROR:
45         case MSG_LOG:
46 @@ -704,6 +712,16 @@ static int readfd_unbuffered(int fd, cha
47                                 log_delete(line, S_IFREG);
48                         remaining = 0;
49                         break;
50 +               case MSG_SUCCESS:
51 +                       if (remaining != 4) {
52 +                               rprintf(FERROR, "invalid multi-message %d:%ld\n",
53 +                                       tag, (long)remaining);
54 +                               exit_cleanup(RERR_STREAMIO);
55 +                       }
56 +                       read_loop(fd, line, remaining);
57 +                       successful_send(IVAL(line, 0));
58 +                       remaining = 0;
59 +                       break;
60                 case MSG_INFO:
61                 case MSG_ERROR:
62                         if (remaining >= sizeof line) {
63 --- orig/main.c 2005-02-20 00:02:23
64 +++ main.c      2005-02-20 00:09:59
65 @@ -33,7 +33,9 @@ extern int am_generator;
66  extern int am_daemon;
67  extern int blocking_io;
68  extern int delete_before;
69 +extern int remove_sent_files;
70  extern int daemon_over_rsh;
71 +extern int need_messages_from_generator;
72  extern int do_stats;
73  extern int log_got_error;
74  extern int module_id;
75 @@ -441,6 +443,12 @@ static void do_server_sender(int f_in, i
76                 exit_cleanup(RERR_SYNTAX);
77                 return;
78         }
79 +       if (am_daemon && lp_read_only(module_id) && remove_sent_files) {
80 +               rprintf(FERROR,
81 +                   "ERROR: --remove-sent-files cannot be used with a read-only module\n");
82 +               exit_cleanup(RERR_SYNTAX);
83 +               return;
84 +       }
85  
86         if (!relative_paths && !push_dir(dir)) {
87                 rsyserr(FERROR, errno, "push_dir#3 %s failed",
88 @@ -672,6 +680,8 @@ void start_server(int f_in, int f_out, i
89  
90         if (am_sender) {
91                 keep_dirlinks = 0; /* Must be disabled on the sender. */
92 +               if (need_messages_from_generator)
93 +                       io_start_multiplex_in();
94  
95                 recv_filter_list(f_in);
96                 do_server_sender(f_in, f_out, argc, argv);
97 @@ -749,6 +759,9 @@ int client_run(int f_in, int f_out, pid_
98                 exit_cleanup(status);
99         }
100  
101 +       if (need_messages_from_generator && !read_batch)
102 +               io_start_multiplex_out();
103 +
104         if (argc == 0)
105                 list_only |= 1;
106  
107 --- orig/options.c      2005-02-20 00:02:23
108 +++ options.c   2005-02-15 21:33:52
109 @@ -59,6 +59,7 @@ int delete_during = 0;
110  int delete_before = 0;
111  int delete_after = 0;
112  int delete_excluded = 0;
113 +int remove_sent_files = 0;
114  int one_file_system = 0;
115  int protocol_version = PROTOCOL_VERSION;
116  int sparse_files = 0;
117 @@ -93,6 +94,7 @@ int fuzzy_basis = 0;
118  size_t bwlimit_writemax = 0;
119  int only_existing = 0;
120  int opt_ignore_existing = 0;
121 +int need_messages_from_generator = 0;
122  int max_delete = 0;
123  OFF_T max_size = 0;
124  int ignore_errors = 0;
125 @@ -288,6 +290,7 @@ void usage(enum logcode F)
126    rprintf(F,"     --rsync-path=PATH       specify path to rsync on the remote machine\n");
127    rprintf(F,"     --existing              only update files that already exist on receiver\n");
128    rprintf(F,"     --ignore-existing       ignore files that already exist on receiving side\n");
129 +  rprintf(F,"     --remove-sent-files     sent files/symlinks are removed from sending side\n");
130    rprintf(F,"     --del                   an alias for --delete-during\n");
131    rprintf(F,"     --delete                delete files that don't exist on the sending side\n");
132    rprintf(F,"     --delete-before         receiver deletes before transfer (default)\n");
133 @@ -371,6 +374,7 @@ static struct poptOption long_options[] 
134    {"delete-during",    0,  POPT_ARG_NONE,   &delete_during, 0, 0, 0 },
135    {"delete-after",     0,  POPT_ARG_NONE,   &delete_after, 0, 0, 0 },
136    {"delete-excluded",  0,  POPT_ARG_NONE,   &delete_excluded, 0, 0, 0 },
137 +  {"remove-sent-files",0,  POPT_ARG_NONE,   &remove_sent_files, 0, 0, 0 },
138    {"force",            0,  POPT_ARG_NONE,   &force_delete, 0, 0, 0 },
139    {"numeric-ids",      0,  POPT_ARG_NONE,   &numeric_ids, 0, 0, 0 },
140    {"filter",          'f', POPT_ARG_STRING, 0, OPT_FILTER, 0, 0 },
141 @@ -978,6 +982,17 @@ int parse_arguments(int *argc, const cha
142                 return 0;
143         }
144  
145 +       if (remove_sent_files) {
146 +               /* We only want to infer this refusal of --remove-sent-files
147 +                * via the refusal of "delete", not any of the "delete-FOO"
148 +                * options. */
149 +               if (refused_delete && am_sender) {
150 +                       create_refuse_error(refused_delete);
151 +                       return 0;
152 +               }
153 +               need_messages_from_generator = 1;
154 +       }
155 +
156         *argv = poptGetArgs(pc);
157         *argc = count_args(*argv);
158  
159 @@ -1435,6 +1450,9 @@ void server_options(char **args,int *arg
160         if (fuzzy_basis && am_sender)
161                 args[ac++] = "--fuzzy";
162  
163 +       if (remove_sent_files)
164 +               args[ac++] = "--remove-sent-files";
165 +
166         *argc = ac;
167         return;
168  
169 --- orig/receiver.c     2005-02-20 00:16:35
170 +++ receiver.c  2005-02-15 21:33:52
171 @@ -41,6 +41,7 @@ extern int io_error;
172  extern int basis_dir_cnt;
173  extern int make_backups;
174  extern int cleanup_got_literal;
175 +extern int remove_sent_files;
176  extern int module_id;
177  extern int ignore_errors;
178  extern int orig_umask;
179 @@ -312,7 +313,7 @@ int recv_files(int f_in, struct file_lis
180         char *fname, fbuf[MAXPATHLEN];
181         char template[MAXPATHLEN];
182         char fnametmp[MAXPATHLEN];
183 -       char *fnamecmp, *partialptr;
184 +       char *fnamecmp, *partialptr, numbuf[4];
185         char fnamecmpbuf[MAXPATHLEN];
186         uchar *delayed_bits = NULL;
187         struct file_struct *file;
188 @@ -595,7 +596,12 @@ int recv_files(int f_in, struct file_lis
189  
190                 cleanup_disable();
191  
192 -               if (!recv_ok) {
193 +               if (recv_ok) {
194 +                       if (remove_sent_files) {
195 +                               SIVAL(numbuf, 0, i);
196 +                               send_msg(MSG_SUCCESS, numbuf, 4);
197 +                       }
198 +               } else {
199                         int msgtype = csum_length == SUM_LENGTH || read_batch ?
200                                 FERROR : FINFO;
201                         if (msgtype == FERROR || verbose) {
202 @@ -619,9 +625,8 @@ int recv_files(int f_in, struct file_lis
203                                         keptstr, redostr);
204                         }
205                         if (csum_length != SUM_LENGTH) {
206 -                               char buf[4];
207 -                               SIVAL(buf, 0, i);
208 -                               send_msg(MSG_REDO, buf, 4);
209 +                               SIVAL(numbuf, 0, i);
210 +                               send_msg(MSG_REDO, numbuf, 4);
211                         }
212                 }
213         }
214 --- orig/rsync.yo       2005-02-19 09:27:49
215 +++ rsync.yo    2005-02-15 21:33:55
216 @@ -332,6 +332,7 @@ to the detailed description below for a 
217       --rsync-path=PATH       specify path to rsync on the remote machine
218       --existing              only update files that already exist
219       --ignore-existing       ignore files that already exist on receiver
220 +     --remove-sent-files     sent files/symlinks are removed from sender
221       --del                   an alias for --delete-during
222       --delete                delete files that don't exist on sender
223       --delete-before         receiver deletes before transfer (default)
224 @@ -674,6 +675,11 @@ dit(bf(--ignore-existing))
225  This tells rsync not to update files that already exist on
226  the destination.
227  
228 +dit(bf(--remove-sent-files)) This tells rsync to remove from the sending
229 +side the files and/or symlinks that are newly created or whose content is
230 +updated on the receiving side.  Directories and devices are not removed,
231 +nor are files/symlinks whose attributes are merely changed.
232 +
233  dit(bf(--delete)) This tells rsync to delete extraneous files from the
234  receiving side (ones that aren't on the sending side), but only for the
235  directories that are being synchronized.  You must have asked rsync to
236 --- orig/rsyncd.conf.yo 2005-02-20 00:02:23
237 +++ rsyncd.conf.yo      2005-02-15 21:33:55
238 @@ -459,6 +459,10 @@ quote(tt(    refuse options = c delete))
239  
240  The reason the above refuses all delete options is that the options imply
241  bf(--delete), and implied options are refused just like explicit options.
242 +As an additional safety feature, the refusal of "delete" also refuses
243 +bf(remove-sent-files) when the daemon is the sender; if you want the latter
244 +without the former, instead refuse "delete-*" -- that refuses all the
245 +delete modes without affecting bf(--remove-sent-files).
246  
247  When an option is refused, the server prints an error message and exits.
248  To prevent all compression, you can use "dont compress = *" (see below)
249 --- orig/sender.c       2005-02-20 00:16:35
250 +++ sender.c    2005-02-20 00:10:24
251 @@ -29,6 +29,7 @@ extern int daemon_log_format_has_i;
252  extern int csum_length;
253  extern int io_error;
254  extern int protocol_version;
255 +extern int remove_sent_files;
256  extern int updating_basis_file;
257  extern int make_backups;
258  extern int do_progress;
259 @@ -98,7 +99,32 @@ static struct sum_struct *receive_sums(i
260         return s;
261  }
262  
263 +static struct file_list *the_flist;
264  
265 +void successful_send(int i)
266 +{
267 +       char fname[MAXPATHLEN];
268 +       struct file_struct *file;
269 +       unsigned int offset;
270 +
271 +       if (!the_flist || i < 0 || i >= the_flist->count)
272 +               return;
273 +
274 +       file = the_flist->files[i];
275 +       /* The generator might tell us about symlinks we didn't send. */
276 +       if (!(file->flags & FLAG_SENT) && !S_ISLNK(file->mode))
277 +               return;
278 +       if (file->dir.root) {
279 +               offset = stringjoin(fname, sizeof fname,
280 +                                   file->dir.root, "/", NULL);
281 +       } else
282 +               offset = 0;
283 +       f_name_to(file, fname + offset);
284 +       if (remove_sent_files && do_unlink(fname) == 0 && verbose) {
285 +               rprintf(FINFO, "sender removed %s\n",
286 +                       safe_fname(fname + offset));
287 +       }
288 +}
289  
290  void send_files(struct file_list *flist, int f_out, int f_in)
291  {
292 @@ -119,6 +145,8 @@ void send_files(struct file_list *flist,
293         if (verbose > 2)
294                 rprintf(FINFO, "send_files starting\n");
295  
296 +       the_flist = flist;
297 +
298         while (1) {
299                 unsigned int offset;
300  
301 @@ -285,6 +313,9 @@ void send_files(struct file_list *flist,
302                         rprintf(FINFO, "sender finished %s\n",
303                                 safe_fname(fname));
304                 }
305 +
306 +               /* Flag that we actually sent this entry. */
307 +               file->flags |= FLAG_SENT;
308         }
309         make_backups = save_make_backups;
310