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