We make sure that the rsync_acl objects never have a forced
[rsync/rsync-patches.git] / log-file.diff
1 This patch allows a non-daemon server and/or 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,10 +21,13 @@
7  
8  #include "rsync.h"
9  
10 +extern int am_server;
11 +extern int am_daemon;
12  extern int io_error;
13  extern int keep_partial;
14  extern int log_got_error;
15  extern char *partial_dir;
16 +extern char *logfile_name;
17  
18  #ifdef HAVE_SIGACTION
19  static struct sigaction sigact;
20 @@ -149,7 +152,7 @@ void _exit_cleanup(int code, const char 
21                         code = RERR_PARTIAL;
22         }
23  
24 -       if (code)
25 +       if (code || am_daemon || (am_server && logfile_name))
26                 log_exit(code, file, line);
27  
28         if (verbose > 2) {
29 --- old/clientserver.c
30 +++ new/clientserver.c
31 @@ -44,10 +44,14 @@ extern int protocol_version;
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;
46 @@ -55,8 +59,6 @@ extern struct filter_list_struct server_
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  
55 @@ -329,11 +331,12 @@ static int rsync_module(int f_in, int f_
56                 read_only = 1;
57  
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;
130 @@ -661,7 +661,7 @@ static int try_dests_reg(struct file_str
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                 }
139 @@ -684,7 +684,7 @@ static int try_dests_reg(struct file_str
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" : "");
148 @@ -758,7 +758,7 @@ static int try_dests_non(struct file_str
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                 }
157 @@ -1327,9 +1327,9 @@ void generate_files(int f_out, struct fi
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
171 @@ -44,18 +44,19 @@ extern int protocol_version;
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  
186  static int log_initialised;
187  static int logfile_was_closed;
188 -static char *logfname;
189 -static FILE *logfile;
190 +static FILE *logfile_fp;
191  struct stats stats;
192  
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         }
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");
213 +       logfile_fp = fopen(logfile_name, "a");
214         umask(old_umask);
215 -       if (!logfile) {
216 +       if (!logfile_fp) {
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  }
226 @@ -171,9 +172,11 @@ void log_init(void)
227         t = time(NULL);
228         localtime(&t);
229  
230 -       /* optionally use a log file instead of syslog */
231 -       logfname = lp_log_file();
232 -       if (logfname && *logfname)
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();
237 +       if (logfile_name && *logfile_name)
238                 logfile_open();
239         else
240                 syslog_init();
241 @@ -181,10 +184,10 @@ void log_init(void)
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  
255 @@ -243,9 +246,9 @@ void rwrite(enum logcode code, char *buf
256  
257         if (code == FCLIENT)
258                 code = FINFO;
259 -       else if (am_daemon) {
260 +       else if (am_daemon || logfile_name) {
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)
267 @@ -254,10 +257,11 @@ void rwrite(enum logcode code, char *buf
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;
281 @@ -403,26 +407,14 @@ void rflush(enum logcode code)
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  
312 @@ -695,12 +687,12 @@ void log_item(struct file_struct *file, 
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  
329 @@ -712,7 +704,7 @@ void maybe_log_item(struct file_struct *
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))
338 @@ -740,10 +732,10 @@ void log_delete(char *fname, int mode)
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
363 @@ -146,6 +146,8 @@ char *basis_dir[MAX_BASIS_DIRS+1];
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;
372 @@ -162,7 +164,9 @@ int verbose = 0;
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  
382 @@ -359,6 +363,7 @@ void usage(enum logcode F)
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");
390 @@ -492,6 +497,7 @@ static struct poptOption long_options[] 
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 },
398 @@ -1311,6 +1317,21 @@ int parse_arguments(int *argc, const cha
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
474 @@ -158,8 +158,8 @@
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
495 @@ -1430,6 +1431,23 @@ the string "*deleting" for each item tha
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