1 After applying this patch and running configure, you MUST run this
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;
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));
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-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));
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 @@ -677,6 +685,16 @@ static int readfd_unbuffered(int fd, cha
47 read_loop(fd, iobuf_in, remaining);
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-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;
74 extern int log_got_error;
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);
84 + if (am_daemon && lp_read_only(module_id) && remove_sent_files) {
86 + "ERROR: --remove-sent-files cannot be used with a read-only module\n");
87 + exit_cleanup(RERR_SYNTAX);
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
96 keep_dirlinks = 0; /* Must be disabled on the sender. */
97 + if (need_messages_from_generator)
98 + io_start_multiplex_in();
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);
106 + if (need_messages_from_generator && !read_batch)
107 + io_start_multiplex_out();
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;
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
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"
154 + if (refused_delete && am_sender) {
155 + create_refuse_error(refused_delete);
158 + need_messages_from_generator = 1;
161 *argv = poptGetArgs(pc);
162 *argc = count_args(*argv);
164 @@ -1411,6 +1426,9 @@ void server_options(char **args,int *arg
165 if (fuzzy_basis && am_sender)
166 args[ac++] = "--fuzzy";
168 + if (remove_sent_files)
169 + args[ac++] = "--remove-sent-files";
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
199 + if (remove_sent_files) {
200 + SIVAL(numbuf, 0, i);
201 + send_msg(MSG_SUCCESS, numbuf, 4);
204 int msgtype = csum_length == SUM_LENGTH || read_batch ?
206 if (msgtype == FERROR || verbose) {
207 @@ -612,9 +618,8 @@ int recv_files(int f_in, struct file_lis
210 if (csum_length != SUM_LENGTH) {
213 - send_msg(MSG_REDO, buf, 4);
214 + SIVAL(numbuf, 0, i);
215 + send_msg(MSG_REDO, numbuf, 4);
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
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.
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))
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).
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;
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
268 +static struct file_list *the_flist;
270 +void successful_send(int i)
272 + char fname[MAXPATHLEN];
273 + struct file_struct *file;
274 + unsigned int offset;
276 + if (!the_flist || i < 0 || i >= the_flist->count)
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))
283 + if (file->dir.root) {
284 + offset = stringjoin(fname, sizeof fname,
285 + file->dir.root, "/", NULL);
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));
295 void send_files(struct file_list *flist, int f_out, int f_in)
297 @@ -117,6 +143,8 @@ void send_files(struct file_list *flist,
299 rprintf(FINFO, "send_files starting\n");
306 @@ -281,6 +309,9 @@ void send_files(struct file_list *flist,
307 rprintf(FINFO, "sender finished %s\n",
311 + /* Flag that we actually sent this entry. */
312 + file->flags |= FLAG_SENT;
314 make_backups = save_make_backups;