Updated to work with latest io.c changes.
[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,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