- Make sure that logfile_name is set properly for all possible
[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,16 +44,17 @@ 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  struct stats stats;
213  
214 @@ -145,14 +146,14 @@ static void syslog_init()
215  static void logfile_open(void)
216  {
217         mode_t old_umask = umask(022 | orig_umask);
218 -       logfile = fopen(logfname, "a");
219 +       logfile = fopen(logfile_name, "a");
220         umask(old_umask);
221         if (!logfile) {
222                 int fopen_errno = errno;
223                 /* Rsync falls back to using syslog on failure. */
224                 syslog_init();
225                 rsyserr(FERROR, fopen_errno,
226 -                       "failed to open log-file %s", logfname);
227 +                       "failed to open log-file %s", logfile_name);
228                 rprintf(FINFO, "Ignoring \"log file\" setting.\n");
229         }
230  }
231 @@ -171,9 +172,7 @@ void log_init(void)
232         t = time(NULL);
233         localtime(&t);
234  
235 -       /* optionally use a log file instead of syslog */
236 -       logfname = lp_log_file();
237 -       if (logfname && *logfname)
238 +       if (logfile_name && *logfile_name)
239                 logfile_open();
240         else
241                 syslog_init();
242 @@ -243,9 +242,9 @@ void rwrite(enum logcode code, char *buf
243  
244         if (code == FCLIENT)
245                 code = FINFO;
246 -       else if (am_daemon) {
247 +       else if (logfile_name) { /* always non-NULL in the daemon */
248                 static int in_block;
249 -               char msg[2048];
250 +               char msg[2048], *s;
251                 int priority = code == FERROR ? LOG_WARNING : LOG_INFO;
252  
253                 if (in_block)
254 @@ -254,10 +253,11 @@ void rwrite(enum logcode code, char *buf
255                 if (!log_initialised)
256                         log_init();
257                 strlcpy(msg, buf, MIN((int)sizeof msg, len + 1));
258 -               logit(priority, msg);
259 +               for (s = msg; *s == '\n' && s[1]; s++) {}
260 +               logit(priority, s);
261                 in_block = 0;
262  
263 -               if (code == FLOG || !am_server)
264 +               if (code == FLOG || (am_daemon && !am_server))
265                         return;
266         } else if (code == FLOG)
267                 return;
268 @@ -403,26 +403,14 @@ void rflush(enum logcode code)
269  {
270         FILE *f = NULL;
271  
272 -       if (am_daemon) {
273 +       if (am_daemon || code == FLOG)
274                 return;
275 -       }
276  
277 -       if (code == FLOG) {
278 -               return;
279 -       }
280 -
281 -       if (code == FERROR) {
282 +       if (code == FERROR || am_server)
283                 f = stderr;
284 -       }
285 -
286 -       if (code == FINFO) {
287 -               if (am_server)
288 -                       f = stderr;
289 -               else
290 -                       f = stdout;
291 -       }
292 +       else
293 +               f = stdout;
294  
295 -       if (!f) exit_cleanup(RERR_MESSAGEIO);
296         fflush(f);
297  }
298  
299 @@ -695,12 +683,12 @@ void log_item(struct file_struct *file, 
300  {
301         char *s_or_r = am_sender ? "send" : "recv";
302  
303 -       if (lp_transfer_logging(module_id)) {
304 -               log_formatted(FLOG, lp_log_format(module_id), s_or_r,
305 -                             file, initial_stats, iflags, hlink);
306 -       } else if (log_format && !am_server) {
307 +       if (log_format && !am_server) {
308                 log_formatted(FNAME, log_format, s_or_r,
309                               file, initial_stats, iflags, hlink);
310 +       } else if (logfile_format) {
311 +               log_formatted(FLOG, logfile_format, s_or_r,
312 +                             file, initial_stats, iflags, hlink);
313         }
314  }
315  
316 @@ -712,7 +700,7 @@ void maybe_log_item(struct file_struct *
317                 || log_format_has_i > 1 || (verbose > 1 && log_format_has_i));
318         int local_change = iflags & ITEM_LOCAL_CHANGE && significant_flags;
319         if (am_server) {
320 -               if (am_daemon && !dry_run && see_item)
321 +               if (logfile_name && !dry_run && see_item)
322                         log_item(file, &stats, iflags, buf);
323         } else if (see_item || local_change || *buf
324             || (S_ISDIR(file->mode) && significant_flags))
325 @@ -740,10 +728,10 @@ void log_delete(char *fname, int mode)
326                               ITEM_DELETED, NULL);
327         }
328  
329 -       if (!am_daemon || dry_run || !lp_transfer_logging(module_id))
330 +       if (!logfile_name || dry_run || !logfile_format)
331                 return;
332  
333 -       fmt = daemon_log_format_has_o_or_i ? lp_log_format(module_id) : "deleting %n";
334 +       fmt = logfile_format_has_o_or_i ? logfile_format : "deleting %n";
335         log_formatted(FLOG, fmt, "del.", &file, &stats, ITEM_DELETED, NULL);
336  }
337  
338 --- old/main.c
339 +++ new/main.c
340 @@ -168,7 +168,6 @@ static void handle_stats(int f)
341                 return;
342  
343         if (am_daemon) {
344 -               log_exit(0, __FILE__, __LINE__);
345                 if (f == -1 || !am_sender)
346                         return;
347         }
348 --- old/options.c
349 +++ new/options.c
350 @@ -146,6 +146,8 @@ char *basis_dir[MAX_BASIS_DIRS+1];
351  char *config_file = NULL;
352  char *shell_cmd = NULL;
353  char *log_format = NULL;
354 +char *logfile_name = NULL;
355 +char *logfile_format = NULL;
356  char *password_file = NULL;
357  char *rsync_path = RSYNC_PATH;
358  char *backup_dir = NULL;
359 @@ -162,7 +164,9 @@ int verbose = 0;
360  int quiet = 0;
361  int log_before_transfer = 0;
362  int log_format_has_i = 0;
363 +int logfile_format_has_i = 0;
364  int log_format_has_o_or_i = 0;
365 +int logfile_format_has_o_or_i = 0;
366  int always_checksum = 0;
367  int list_only = 0;
368  
369 @@ -359,6 +363,7 @@ void usage(enum logcode F)
370    rprintf(F,"     --progress              show progress during transfer\n");
371    rprintf(F," -P                          same as --partial --progress\n");
372    rprintf(F," -i, --itemize-changes       output a change-summary for all updates\n");
373 +  rprintf(F,"     --log-file=FILE         output what we're doing to a log file\n");
374    rprintf(F,"     --log-format=FORMAT     output filenames using the specified format\n");
375    rprintf(F,"     --password-file=FILE    read password from FILE\n");
376    rprintf(F,"     --list-only             list the files instead of copying them\n");
377 @@ -492,6 +497,7 @@ static struct poptOption long_options[] 
378    {"partial-dir",      0,  POPT_ARG_STRING, &partial_dir, 0, 0, 0 },
379    {"delay-updates",    0,  POPT_ARG_NONE,   &delay_updates, 0, 0, 0 },
380    {"prune-empty-dirs",'m', POPT_ARG_NONE,   &prune_empty_dirs, 0, 0, 0 },
381 +  {"log-file",         0,  POPT_ARG_STRING, &logfile_name, 0, 0, 0 },
382    {"log-format",       0,  POPT_ARG_STRING, &log_format, 0, 0, 0 },
383    {"itemize-changes", 'i', POPT_ARG_NONE,   0, 'i', 0, 0 },
384    {"bwlimit",          0,  POPT_ARG_INT,    &bwlimit, 0, 0, 0 },
385 @@ -1311,6 +1317,21 @@ int parse_arguments(int *argc, const cha
386         if (log_format_has_i || log_format_has(log_format, 'o'))
387                 log_format_has_o_or_i = 1;
388  
389 +       if (am_daemon)
390 +               logfile_name = NULL;
391 +       else if (logfile_name) {
392 +               if (am_server) {
393 +                       logfile_format = "%i %n%L";
394 +                       logfile_format_has_i = logfile_format_has_o_or_i = 1;
395 +               } else if (log_format) {
396 +                       logfile_format = log_format;
397 +                       logfile_format_has_i = log_format_has_i;
398 +                       logfile_format_has_o_or_i = log_format_has_o_or_i;
399 +               }
400 +               log_before_transfer = !am_server;
401 +               log_init();
402 +       }
403 +
404         if (daemon_bwlimit && (!bwlimit || bwlimit > daemon_bwlimit))
405                 bwlimit = daemon_bwlimit;
406         if (bwlimit) {
407 --- old/progress.c
408 +++ new/progress.c
409 @@ -103,7 +103,7 @@ static void rprint_progress(OFF_T ofs, O
410                         stats.num_files);
411         } else
412                 strcpy(eol, "\r");
413 -       rprintf(FINFO, "%12s %3d%% %7.2f%s %4d:%02d:%02d%s",
414 +       rprintf(FCLIENT, "%12s %3d%% %7.2f%s %4d:%02d:%02d%s",
415                 human_num(ofs), pct, rate, units,
416                 remain_h, remain_m, remain_s, eol);
417  }
418 --- old/receiver.c
419 +++ new/receiver.c
420 @@ -27,7 +27,7 @@ extern int am_server;
421  extern int do_progress;
422  extern int log_before_transfer;
423  extern int log_format_has_i;
424 -extern int daemon_log_format_has_i;
425 +extern int logfile_format_has_i;
426  extern int csum_length;
427  extern int read_batch;
428  extern int write_batch;
429 @@ -341,8 +341,7 @@ int recv_files(int f_in, struct file_lis
430         struct file_struct *file;
431         struct stats initial_stats;
432         int save_make_backups = make_backups;
433 -       int itemizing = am_daemon ? daemon_log_format_has_i
434 -                     : !am_server && log_format_has_i;
435 +       int itemizing = am_server ? logfile_format_has_i : log_format_has_i;
436         int max_phase = protocol_version >= 29 ? 2 : 1;
437         int i, recv_ok;
438  
439 --- old/rsync.c
440 +++ new/rsync.c
441 @@ -32,7 +32,7 @@
442  
443  extern int verbose;
444  extern int dry_run;
445 -extern int daemon_log_format_has_i;
446 +extern int logfile_format_has_i;
447  extern int preserve_perms;
448  extern int preserve_executability;
449  extern int preserve_times;
450 @@ -218,7 +218,7 @@ int set_file_attrs(char *fname, struct f
451  #endif
452  
453         if (verbose > 1 && flags & ATTRS_REPORT) {
454 -               enum logcode code = daemon_log_format_has_i || dry_run
455 +               enum logcode code = logfile_format_has_i || dry_run
456                                   ? FCLIENT : FINFO;
457                 if (updated)
458                         rprintf(code, "%s\n", fname);
459 --- old/rsync.h
460 +++ new/rsync.h
461 @@ -158,8 +158,8 @@
462  
463  
464  /* Log-message categories.  Only FERROR and FINFO get sent over the socket.
465 - * FLOG and FCLIENT are only used on the daemon side for custom logging,
466 - * while FNAME is only used on the client side. */
467 + * FLOG only goes to the log file, not to the client; FCLIENT is the opposite.
468 + * FNAME is a client-side message when outputting a filename on its own. */
469  enum logcode { FERROR=1, FINFO=2, FLOG=3, FCLIENT=4, FNAME=5, FSOCKERR=6 };
470  
471  /* Messages types that are sent over the message channel.  The logcode
472 --- old/rsync.yo
473 +++ new/rsync.yo
474 @@ -387,6 +387,7 @@ to the detailed description below for a 
475       --progress              show progress during transfer
476   -P                          same as --partial --progress
477   -i, --itemize-changes       output a change-summary for all updates
478 +     --log-file=FILE         output what we're doing to a log file
479       --log-format=FORMAT     output filenames using the specified format
480       --password-file=FILE    read password from FILE
481       --list-only             list the files instead of copying them
482 @@ -1423,6 +1424,23 @@ the string "*deleting" for each item tha
483  you are talking to a recent enough rsync that it logs deletions instead of
484  outputting them as a verbose message).
485  
486 +dit(bf(--log-file=FILE)) This option causes rsync to log what it is doing
487 +to a file.  This is similar to the logging that a daemon does, but can be
488 +requested for the client side and/or the server side of a non-daemon
489 +transfer.  If specified as a client option, transfer logging will in effect
490 +if the bf(--log-format) option was either specified or implied (e.g.
491 +bf(--verbose) implies a basic log format).  If explicitly sent to a server
492 +via the bf(--rsync-path) option, transfer logging will always occur using
493 +the default bf(--itemize-changes) format.
494 +
495 +Here's a example command that requests the remote side to log what is
496 +happening:
497 +
498 +verb(  rsync -av --rsync-path="path --log-file=/tmp/rlog" src/ dest/)
499 +
500 +This is very useful if you need to debug why a connection is closing
501 +unexpectedly.
502 +
503  dit(bf(--log-format=FORMAT)) This allows you to specify exactly what the
504  rsync client outputs to the user on a per-file basis.  The format is a text
505  string containing embedded single-character escape sequences prefixed with
506 --- old/sender.c
507 +++ new/sender.c
508 @@ -25,7 +25,7 @@ extern int am_server;
509  extern int am_daemon;
510  extern int log_before_transfer;
511  extern int log_format_has_i;
512 -extern int daemon_log_format_has_i;
513 +extern int logfile_format_has_i;
514  extern int csum_length;
515  extern int append_mode;
516  extern int io_error;
517 @@ -215,8 +215,7 @@ void send_files(struct file_list *flist,
518         int phase = 0, max_phase = protocol_version >= 29 ? 2 : 1;
519         struct stats initial_stats;
520         int save_make_backups = make_backups;
521 -       int itemizing = am_daemon ? daemon_log_format_has_i
522 -                     : !am_server && log_format_has_i;
523 +       int itemizing = am_server ? logfile_format_has_i : log_format_has_i;
524         int f_xfer = write_batch < 0 ? batch_fd : f_out;
525         int i, j;
526