1 After applying this patch and running configure, you MUST run this
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;
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));
21 + if (remove_sent_files && !dry_run) {
23 + SIVAL(numbuf, 0, ndx);
24 + io_multiplex_write(MSG_SUCCESS, numbuf, 4);
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);
36 + if (len != 4 || !am_generator) {
37 + rprintf(FERROR, "invalid message %d:%d\n", tag, len);
38 + exit_cleanup(RERR_STREAMIO);
40 + read_loop(fd, buf, len);
41 + io_multiplex_write(MSG_SUCCESS, buf, len);
46 @@ -704,6 +712,16 @@ static int readfd_unbuffered(int fd, cha
47 log_delete(line, S_IFREG);
51 + if (remaining != 4) {
52 + rprintf(FERROR, "invalid multi-message %d:%ld\n",
53 + tag, (long)remaining);
54 + exit_cleanup(RERR_STREAMIO);
56 + read_loop(fd, line, remaining);
57 + successful_send(IVAL(line, 0));
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;
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;
73 extern int log_got_error;
75 @@ -441,6 +443,12 @@ static void do_server_sender(int f_in, i
76 exit_cleanup(RERR_SYNTAX);
79 + if (am_daemon && lp_read_only(module_id) && remove_sent_files) {
81 + "ERROR: --remove-sent-files cannot be used with a read-only module\n");
82 + exit_cleanup(RERR_SYNTAX);
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
91 keep_dirlinks = 0; /* Must be disabled on the sender. */
92 + if (need_messages_from_generator)
93 + io_start_multiplex_in();
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_
101 + if (need_messages_from_generator && !read_batch)
102 + io_start_multiplex_out();
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;
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
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"
149 + if (refused_delete && am_sender) {
150 + create_refuse_error(refused_delete);
153 + need_messages_from_generator = 1;
156 *argv = poptGetArgs(pc);
157 *argc = count_args(*argv);
159 @@ -1435,6 +1450,9 @@ void server_options(char **args,int *arg
160 if (fuzzy_basis && am_sender)
161 args[ac++] = "--fuzzy";
163 + if (remove_sent_files)
164 + args[ac++] = "--remove-sent-files";
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
194 + if (remove_sent_files) {
195 + SIVAL(numbuf, 0, i);
196 + send_msg(MSG_SUCCESS, numbuf, 4);
199 int msgtype = csum_length == SUM_LENGTH || read_batch ?
201 if (msgtype == FERROR || verbose) {
202 @@ -619,9 +625,8 @@ int recv_files(int f_in, struct file_lis
205 if (csum_length != SUM_LENGTH) {
208 - send_msg(MSG_REDO, buf, 4);
209 + SIVAL(numbuf, 0, i);
210 + send_msg(MSG_REDO, numbuf, 4);
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
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.
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))
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).
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;
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
263 +static struct file_list *the_flist;
265 +void successful_send(int i)
267 + char fname[MAXPATHLEN];
268 + struct file_struct *file;
269 + unsigned int offset;
271 + if (!the_flist || i < 0 || i >= the_flist->count)
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))
278 + if (file->dir.root) {
279 + offset = stringjoin(fname, sizeof fname,
280 + file->dir.root, "/", NULL);
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));
290 void send_files(struct file_list *flist, int f_out, int f_in)
292 @@ -119,6 +145,8 @@ void send_files(struct file_list *flist,
294 rprintf(FINFO, "send_files starting\n");
301 @@ -285,6 +313,9 @@ void send_files(struct file_list *flist,
302 rprintf(FINFO, "sender finished %s\n",
306 + /* Flag that we actually sent this entry. */
307 + file->flags |= FLAG_SENT;
309 make_backups = save_make_backups;