Moved the generic list-growing function into util.c so that the
[rsync/rsync-patches.git] / log-file.diff
CommitLineData
ac81cbf8 1This patch allows a non-daemon server and/or a client rsync to log what they
9d32714e
WD
2are doing, similar to how a daemon logs its actions.
3
4--- old/cleanup.c
5+++ new/cleanup.c
21c15524 6@@ -21,10 +21,13 @@
9d32714e
WD
7
8 #include "rsync.h"
9
10+extern int am_server;
21c15524 11+extern int am_daemon;
9d32714e
WD
12 extern int io_error;
13 extern int keep_partial;
14 extern int log_got_error;
ac81cbf8
WD
15 extern char *partial_dir;
16+extern char *logfile_name;
17
18 #ifdef HAVE_SIGACTION
19 static struct sigaction sigact;
21c15524 20@@ -149,7 +152,7 @@ void _exit_cleanup(int code, const char
9d32714e
WD
21 code = RERR_PARTIAL;
22 }
23
24- if (code)
ac81cbf8 25+ if (code || am_daemon || (am_server && logfile_name))
9d32714e
WD
26 log_exit(code, file, line);
27
28 if (verbose > 2) {
29--- old/clientserver.c
30+++ new/clientserver.c
6596b2bd 31@@ -44,10 +44,14 @@ extern int protocol_version;
9d32714e
WD
32 extern int io_timeout;
33 extern int no_detach;
34 extern int default_af_hint;
35+extern int logfile_format_has_i;
36+extern int logfile_format_has_o_or_i;
37 extern mode_t orig_umask;
38 extern char *bind_address;
39 extern char *sockopts;
40 extern char *config_file;
41+extern char *logfile_format;
42+extern char *logfile_name;
43 extern char *files_from;
44 extern char *tmpdir;
45 extern struct chmod_mode_struct *chmod_modes;
6596b2bd 46@@ -55,8 +59,6 @@ extern struct filter_list_struct server_
9d32714e
WD
47
48 char *auth_user;
49 int read_only = 0;
50-int daemon_log_format_has_i = 0;
51-int daemon_log_format_has_o_or_i = 0;
52 int module_id = -1;
53 struct chmod_mode_struct *daemon_chmod_modes;
54
6596b2bd 55@@ -329,11 +331,12 @@ static int rsync_module(int f_in, int f_
9d32714e
WD
56 read_only = 1;
57
9d32714e
WD
58 if (lp_transfer_logging(i)) {
59- if (log_format_has(lp_log_format(i), 'i'))
60- daemon_log_format_has_i = 1;
61- if (daemon_log_format_has_i
62- || log_format_has(lp_log_format(i), 'o'))
63- daemon_log_format_has_o_or_i = 1;
64+ logfile_format = lp_log_format(i);
65+ if (log_format_has(logfile_format, 'i'))
66+ logfile_format_has_i = 1;
67+ if (logfile_format_has_i
68+ || log_format_has(logfile_format, 'o'))
69+ logfile_format_has_o_or_i = 1;
70 }
71
72 am_root = (MY_UID() == 0);
73--- old/flist.c
74+++ new/flist.c
75@@ -95,15 +95,15 @@ static int show_filelist_p(void)
76
77 static void start_filelist_progress(char *kind)
78 {
79- rprintf(FINFO, "%s ... ", kind);
80+ rprintf(FCLIENT, "%s ... ", kind);
81 if (verbose > 1 || do_progress)
82- rprintf(FINFO, "\n");
83+ rprintf(FCLIENT, "\n");
84 rflush(FINFO);
85 }
86
87 static void emit_filelist_progress(int count)
88 {
89- rprintf(FINFO, " %d files...\r", count);
90+ rprintf(FCLIENT, " %d files...\r", count);
91 }
92
93 static void maybe_emit_filelist_progress(int count)
94@@ -295,7 +295,7 @@ void flist_expand(struct file_list *flis
95 flist->malloced);
96
97 if (verbose >= 2 && flist->malloced != FLIST_START) {
98- rprintf(FINFO, "[%s] expand file_list to %.0f bytes, did%s move\n",
99+ rprintf(FCLIENT, "[%s] expand file_list to %.0f bytes, did%s move\n",
100 who_am_i(),
101 (double)sizeof flist->files[0] * flist->malloced,
102 (new_ptr == flist->files) ? " not" : "");
103@@ -1077,6 +1077,7 @@ struct file_list *send_file_list(int f,
104 int64 start_write;
105 int use_ff_fd = 0;
106
107+ rprintf(FLOG, "building file list\n");
108 if (show_filelist_p())
109 start_filelist_progress("building file list");
110
111@@ -1343,6 +1344,7 @@ struct file_list *recv_file_list(int f)
112 unsigned short flags;
113 int64 start_read;
114
115+ rprintf(FLOG, "receiving file list\n");
116 if (show_filelist_p())
117 start_filelist_progress("receiving file list");
118
119--- old/generator.c
120+++ new/generator.c
121@@ -27,7 +27,7 @@ extern int verbose;
122 extern int dry_run;
123 extern int do_xfers;
124 extern int log_format_has_i;
125-extern int daemon_log_format_has_i;
126+extern int logfile_format_has_i;
127 extern int am_root;
128 extern int am_server;
129 extern int am_daemon;
ac81cbf8 130@@ -661,7 +661,7 @@ static int try_dests_reg(struct file_str
9d32714e
WD
131 } else if (itemizing)
132 itemize(file, ndx, 0, stp, 0, 0, NULL);
133 if (verbose > 1 && maybe_ATTRS_REPORT) {
134- code = daemon_log_format_has_i || dry_run
135+ code = logfile_format_has_i || dry_run
136 ? FCLIENT : FINFO;
137 rprintf(code, "%s is uptodate\n", fname);
138 }
ac81cbf8 139@@ -684,7 +684,7 @@ static int try_dests_reg(struct file_str
9d32714e
WD
140 if (maybe_ATTRS_REPORT
141 && ((!itemizing && verbose && match_level == 2)
142 || (verbose > 1 && match_level == 3))) {
143- code = daemon_log_format_has_i || dry_run
144+ code = logfile_format_has_i || dry_run
145 ? FCLIENT : FINFO;
146 rprintf(code, "%s%s\n", fname,
147 match_level == 3 ? " is uptodate" : "");
21c15524 148@@ -758,7 +758,7 @@ static int try_dests_non(struct file_str
9d32714e
WD
149 itemize(file, ndx, 0, &st, changes, 0, lp);
150 }
151 if (verbose > 1 && maybe_ATTRS_REPORT) {
152- code = daemon_log_format_has_i || dry_run
153+ code = logfile_format_has_i || dry_run
154 ? FCLIENT : FINFO;
155 rprintf(code, "%s is uptodate\n", fname);
156 }
21c15524 157@@ -1327,9 +1327,9 @@ void generate_files(int f_out, struct fi
9d32714e
WD
158 if (protocol_version >= 29) {
159 itemizing = 1;
160 maybe_ATTRS_REPORT = log_format_has_i ? 0 : ATTRS_REPORT;
161- code = daemon_log_format_has_i ? 0 : FLOG;
162+ code = logfile_format_has_i ? 0 : FLOG;
163 } else if (am_daemon) {
164- itemizing = daemon_log_format_has_i && do_xfers;
165+ itemizing = logfile_format_has_i && do_xfers;
166 maybe_ATTRS_REPORT = ATTRS_REPORT;
167 code = itemizing || !do_xfers ? FCLIENT : FINFO;
168 } else if (!am_server) {
169--- old/log.c
170+++ new/log.c
6596b2bd 171@@ -44,18 +44,19 @@ extern int protocol_version;
9d32714e
WD
172 extern int preserve_times;
173 extern int log_format_has_i;
174 extern int log_format_has_o_or_i;
175-extern int daemon_log_format_has_o_or_i;
176+extern int logfile_format_has_o_or_i;
177 extern mode_t orig_umask;
178 extern char *auth_user;
179 extern char *log_format;
180+extern char *logfile_format;
181+extern char *logfile_name;
182 #if defined HAVE_ICONV_OPEN && defined HAVE_ICONV_H
183 extern iconv_t ic_chck;
184 #endif
185
6596b2bd 186 static int log_initialised;
9d32714e
WD
187 static int logfile_was_closed;
188-static char *logfname;
31ce435c
WD
189-static FILE *logfile;
190+static FILE *logfile_fp;
9d32714e
WD
191 struct stats stats;
192
31ce435c
WD
193 int log_got_error = 0;
194@@ -109,10 +110,10 @@ static void logit(int priority, char *bu
195 {
196 if (logfile_was_closed)
197 logfile_reopen();
198- if (logfile) {
199- fprintf(logfile,"%s [%d] %s",
200+ if (logfile_fp) {
201+ fprintf(logfile_fp, "%s [%d] %s",
202 timestring(time(NULL)), (int)getpid(), buf);
203- fflush(logfile);
204+ fflush(logfile_fp);
205 } else {
206 syslog(priority, "%s", buf);
207 }
9d32714e
WD
208@@ -145,14 +146,14 @@ static void syslog_init()
209 static void logfile_open(void)
210 {
211 mode_t old_umask = umask(022 | orig_umask);
212- logfile = fopen(logfname, "a");
31ce435c 213+ logfile_fp = fopen(logfile_name, "a");
9d32714e 214 umask(old_umask);
31ce435c
WD
215- if (!logfile) {
216+ if (!logfile_fp) {
9d32714e
WD
217 int fopen_errno = errno;
218 /* Rsync falls back to using syslog on failure. */
219 syslog_init();
220 rsyserr(FERROR, fopen_errno,
221- "failed to open log-file %s", logfname);
222+ "failed to open log-file %s", logfile_name);
223 rprintf(FINFO, "Ignoring \"log file\" setting.\n");
224 }
225 }
6596b2bd
WD
226@@ -171,9 +172,11 @@ void log_init(void)
227 t = time(NULL);
9d32714e
WD
228 localtime(&t);
229
6596b2bd 230- /* optionally use a log file instead of syslog */
9d32714e
WD
231- logfname = lp_log_file();
232- if (logfname && *logfname)
6596b2bd
WD
233+ /* Optionally use a log file instead of syslog. (Non-daemon
234+ * rsyncs will have already set logfile_name, as needed.) */
235+ if (am_daemon)
236+ logfile_name = lp_log_file();
9d32714e
WD
237+ if (logfile_name && *logfile_name)
238 logfile_open();
239 else
240 syslog_init();
6596b2bd 241@@ -181,10 +184,10 @@ void log_init(void)
31ce435c
WD
242
243 void logfile_close(void)
244 {
245- if (logfile) {
246+ if (logfile_fp) {
247 logfile_was_closed = 1;
248- fclose(logfile);
249- logfile = NULL;
250+ fclose(logfile_fp);
251+ logfile_fp = NULL;
252 }
253 }
254
6596b2bd 255@@ -243,9 +246,9 @@ void rwrite(enum logcode code, char *buf
9d32714e
WD
256
257 if (code == FCLIENT)
258 code = FINFO;
259- else if (am_daemon) {
6596b2bd 260+ else if (am_daemon || logfile_name) {
9d32714e
WD
261 static int in_block;
262- char msg[2048];
263+ char msg[2048], *s;
264 int priority = code == FERROR ? LOG_WARNING : LOG_INFO;
265
266 if (in_block)
6596b2bd 267@@ -254,10 +257,11 @@ void rwrite(enum logcode code, char *buf
9d32714e
WD
268 if (!log_initialised)
269 log_init();
270 strlcpy(msg, buf, MIN((int)sizeof msg, len + 1));
271- logit(priority, msg);
272+ for (s = msg; *s == '\n' && s[1]; s++) {}
273+ logit(priority, s);
274 in_block = 0;
275
276- if (code == FLOG || !am_server)
277+ if (code == FLOG || (am_daemon && !am_server))
278 return;
279 } else if (code == FLOG)
280 return;
6596b2bd 281@@ -403,26 +407,14 @@ void rflush(enum logcode code)
9d32714e
WD
282 {
283 FILE *f = NULL;
284
285- if (am_daemon) {
286+ if (am_daemon || code == FLOG)
287 return;
288- }
289
290- if (code == FLOG) {
291- return;
292- }
293-
294- if (code == FERROR) {
295+ if (code == FERROR || am_server)
296 f = stderr;
297- }
298-
299- if (code == FINFO) {
300- if (am_server)
301- f = stderr;
302- else
303- f = stdout;
304- }
305+ else
306+ f = stdout;
307
308- if (!f) exit_cleanup(RERR_MESSAGEIO);
309 fflush(f);
310 }
311
6596b2bd 312@@ -695,12 +687,12 @@ void log_item(struct file_struct *file,
9d32714e
WD
313 {
314 char *s_or_r = am_sender ? "send" : "recv";
315
316- if (lp_transfer_logging(module_id)) {
317- log_formatted(FLOG, lp_log_format(module_id), s_or_r,
318- file, initial_stats, iflags, hlink);
319- } else if (log_format && !am_server) {
320+ if (log_format && !am_server) {
321 log_formatted(FNAME, log_format, s_or_r,
322 file, initial_stats, iflags, hlink);
323+ } else if (logfile_format) {
324+ log_formatted(FLOG, logfile_format, s_or_r,
325+ file, initial_stats, iflags, hlink);
326 }
327 }
328
6596b2bd 329@@ -712,7 +704,7 @@ void maybe_log_item(struct file_struct *
9d32714e
WD
330 || log_format_has_i > 1 || (verbose > 1 && log_format_has_i));
331 int local_change = iflags & ITEM_LOCAL_CHANGE && significant_flags;
332 if (am_server) {
333- if (am_daemon && !dry_run && see_item)
334+ if (logfile_name && !dry_run && see_item)
335 log_item(file, &stats, iflags, buf);
336 } else if (see_item || local_change || *buf
337 || (S_ISDIR(file->mode) && significant_flags))
6596b2bd 338@@ -740,10 +732,10 @@ void log_delete(char *fname, int mode)
9d32714e
WD
339 ITEM_DELETED, NULL);
340 }
341
342- if (!am_daemon || dry_run || !lp_transfer_logging(module_id))
343+ if (!logfile_name || dry_run || !logfile_format)
344 return;
345
346- fmt = daemon_log_format_has_o_or_i ? lp_log_format(module_id) : "deleting %n";
347+ fmt = logfile_format_has_o_or_i ? logfile_format : "deleting %n";
348 log_formatted(FLOG, fmt, "del.", &file, &stats, ITEM_DELETED, NULL);
349 }
350
351--- old/main.c
352+++ new/main.c
353@@ -168,7 +168,6 @@ static void handle_stats(int f)
354 return;
355
356 if (am_daemon) {
357- log_exit(0, __FILE__, __LINE__);
358 if (f == -1 || !am_sender)
359 return;
360 }
361--- old/options.c
362+++ new/options.c
a56690e2 363@@ -146,6 +146,8 @@ char *basis_dir[MAX_BASIS_DIRS+1];
9d32714e
WD
364 char *config_file = NULL;
365 char *shell_cmd = NULL;
366 char *log_format = NULL;
367+char *logfile_name = NULL;
368+char *logfile_format = NULL;
369 char *password_file = NULL;
370 char *rsync_path = RSYNC_PATH;
371 char *backup_dir = NULL;
a56690e2 372@@ -162,7 +164,9 @@ int verbose = 0;
9d32714e
WD
373 int quiet = 0;
374 int log_before_transfer = 0;
375 int log_format_has_i = 0;
376+int logfile_format_has_i = 0;
377 int log_format_has_o_or_i = 0;
378+int logfile_format_has_o_or_i = 0;
379 int always_checksum = 0;
380 int list_only = 0;
381
a56690e2 382@@ -359,6 +363,7 @@ void usage(enum logcode F)
9d32714e
WD
383 rprintf(F," --progress show progress during transfer\n");
384 rprintf(F," -P same as --partial --progress\n");
385 rprintf(F," -i, --itemize-changes output a change-summary for all updates\n");
386+ rprintf(F," --log-file=FILE output what we're doing to a log file\n");
387 rprintf(F," --log-format=FORMAT output filenames using the specified format\n");
388 rprintf(F," --password-file=FILE read password from FILE\n");
389 rprintf(F," --list-only list the files instead of copying them\n");
a56690e2 390@@ -492,6 +497,7 @@ static struct poptOption long_options[]
9d32714e
WD
391 {"partial-dir", 0, POPT_ARG_STRING, &partial_dir, 0, 0, 0 },
392 {"delay-updates", 0, POPT_ARG_NONE, &delay_updates, 0, 0, 0 },
393 {"prune-empty-dirs",'m', POPT_ARG_NONE, &prune_empty_dirs, 0, 0, 0 },
394+ {"log-file", 0, POPT_ARG_STRING, &logfile_name, 0, 0, 0 },
395 {"log-format", 0, POPT_ARG_STRING, &log_format, 0, 0, 0 },
396 {"itemize-changes", 'i', POPT_ARG_NONE, 0, 'i', 0, 0 },
397 {"bwlimit", 0, POPT_ARG_INT, &bwlimit, 0, 0, 0 },
a56690e2 398@@ -1311,6 +1317,21 @@ int parse_arguments(int *argc, const cha
9d32714e
WD
399 if (log_format_has_i || log_format_has(log_format, 'o'))
400 log_format_has_o_or_i = 1;
401
402+ if (am_daemon)
403+ logfile_name = NULL;
404+ else if (logfile_name) {
405+ if (am_server) {
406+ logfile_format = "%i %n%L";
407+ logfile_format_has_i = logfile_format_has_o_or_i = 1;
408+ } else if (log_format) {
409+ logfile_format = log_format;
410+ logfile_format_has_i = log_format_has_i;
411+ logfile_format_has_o_or_i = log_format_has_o_or_i;
412+ }
413+ log_before_transfer = !am_server;
414+ log_init();
415+ }
416+
417 if (daemon_bwlimit && (!bwlimit || bwlimit > daemon_bwlimit))
418 bwlimit = daemon_bwlimit;
419 if (bwlimit) {
420--- old/progress.c
421+++ new/progress.c
422@@ -103,7 +103,7 @@ static void rprint_progress(OFF_T ofs, O
423 stats.num_files);
424 } else
425 strcpy(eol, "\r");
426- rprintf(FINFO, "%12s %3d%% %7.2f%s %4d:%02d:%02d%s",
427+ rprintf(FCLIENT, "%12s %3d%% %7.2f%s %4d:%02d:%02d%s",
428 human_num(ofs), pct, rate, units,
429 remain_h, remain_m, remain_s, eol);
430 }
431--- old/receiver.c
432+++ new/receiver.c
433@@ -27,7 +27,7 @@ extern int am_server;
434 extern int do_progress;
435 extern int log_before_transfer;
436 extern int log_format_has_i;
437-extern int daemon_log_format_has_i;
438+extern int logfile_format_has_i;
439 extern int csum_length;
440 extern int read_batch;
441 extern int write_batch;
442@@ -341,8 +341,7 @@ int recv_files(int f_in, struct file_lis
443 struct file_struct *file;
444 struct stats initial_stats;
445 int save_make_backups = make_backups;
446- int itemizing = am_daemon ? daemon_log_format_has_i
447- : !am_server && log_format_has_i;
448+ int itemizing = am_server ? logfile_format_has_i : log_format_has_i;
449 int max_phase = protocol_version >= 29 ? 2 : 1;
450 int i, recv_ok;
451
452--- old/rsync.c
453+++ new/rsync.c
454@@ -32,7 +32,7 @@
455
456 extern int verbose;
457 extern int dry_run;
458-extern int daemon_log_format_has_i;
459+extern int logfile_format_has_i;
460 extern int preserve_perms;
461 extern int preserve_executability;
462 extern int preserve_times;
463@@ -218,7 +218,7 @@ int set_file_attrs(char *fname, struct f
464 #endif
465
466 if (verbose > 1 && flags & ATTRS_REPORT) {
467- enum logcode code = daemon_log_format_has_i || dry_run
468+ enum logcode code = logfile_format_has_i || dry_run
469 ? FCLIENT : FINFO;
470 if (updated)
471 rprintf(code, "%s\n", fname);
472--- old/rsync.h
473+++ new/rsync.h
a56690e2 474@@ -158,8 +158,8 @@
9d32714e
WD
475
476
477 /* Log-message categories. Only FERROR and FINFO get sent over the socket.
478- * FLOG and FCLIENT are only used on the daemon side for custom logging,
479- * while FNAME is only used on the client side. */
480+ * FLOG only goes to the log file, not to the client; FCLIENT is the opposite.
481+ * FNAME is a client-side message when outputting a filename on its own. */
482 enum logcode { FERROR=1, FINFO=2, FLOG=3, FCLIENT=4, FNAME=5, FSOCKERR=6 };
483
484 /* Messages types that are sent over the message channel. The logcode
485--- old/rsync.yo
486+++ new/rsync.yo
487@@ -387,6 +387,7 @@ to the detailed description below for a
488 --progress show progress during transfer
489 -P same as --partial --progress
490 -i, --itemize-changes output a change-summary for all updates
491+ --log-file=FILE output what we're doing to a log file
492 --log-format=FORMAT output filenames using the specified format
493 --password-file=FILE read password from FILE
494 --list-only list the files instead of copying them
21c15524 495@@ -1430,6 +1431,23 @@ the string "*deleting" for each item tha
9d32714e
WD
496 you are talking to a recent enough rsync that it logs deletions instead of
497 outputting them as a verbose message).
498
499+dit(bf(--log-file=FILE)) This option causes rsync to log what it is doing
500+to a file. This is similar to the logging that a daemon does, but can be
501+requested for the client side and/or the server side of a non-daemon
502+transfer. If specified as a client option, transfer logging will in effect
503+if the bf(--log-format) option was either specified or implied (e.g.
504+bf(--verbose) implies a basic log format). If explicitly sent to a server
505+via the bf(--rsync-path) option, transfer logging will always occur using
506+the default bf(--itemize-changes) format.
507+
508+Here's a example command that requests the remote side to log what is
509+happening:
510+
511+verb( rsync -av --rsync-path="path --log-file=/tmp/rlog" src/ dest/)
512+
513+This is very useful if you need to debug why a connection is closing
514+unexpectedly.
515+
516 dit(bf(--log-format=FORMAT)) This allows you to specify exactly what the
517 rsync client outputs to the user on a per-file basis. The format is a text
518 string containing embedded single-character escape sequences prefixed with
519--- old/sender.c
520+++ new/sender.c
521@@ -25,7 +25,7 @@ extern int am_server;
522 extern int am_daemon;
523 extern int log_before_transfer;
524 extern int log_format_has_i;
525-extern int daemon_log_format_has_i;
526+extern int logfile_format_has_i;
527 extern int csum_length;
528 extern int append_mode;
529 extern int io_error;
530@@ -215,8 +215,7 @@ void send_files(struct file_list *flist,
531 int phase = 0, max_phase = protocol_version >= 29 ? 2 : 1;
532 struct stats initial_stats;
533 int save_make_backups = make_backups;
534- int itemizing = am_daemon ? daemon_log_format_has_i
535- : !am_server && log_format_has_i;
536+ int itemizing = am_server ? logfile_format_has_i : log_format_has_i;
537 int f_xfer = write_batch < 0 ? batch_fd : f_out;
538 int i, j;
539