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