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