00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "rsync.h"
00029 #if defined HAVE_ICONV_OPEN && defined HAVE_ICONV_H
00030 #include <iconv.h>
00031 #endif
00032
00033 extern int verbose;
00034 extern int dry_run;
00035 extern int am_daemon;
00036 extern int am_server;
00037 extern int am_sender;
00038 extern int local_server;
00039 extern int quiet;
00040 extern int module_id;
00041 extern int msg_fd_out;
00042 extern int allow_8bit_chars;
00043 extern int protocol_version;
00044 extern int preserve_times;
00045 extern int log_format_has_i;
00046 extern int log_format_has_o_or_i;
00047 extern int daemon_log_format_has_o_or_i;
00048 extern mode_t orig_umask;
00049 extern char *auth_user;
00050 extern char *log_format;
00051 #if defined HAVE_ICONV_OPEN && defined HAVE_ICONV_H
00052 extern iconv_t ic_chck;
00053 #endif
00054
00055 static int log_initialised;
00056 static int logfile_was_closed;
00057 static char *logfname;
00058 static FILE *logfile;
00059 struct stats stats;
00060
00061 int log_got_error = 0;
00062
00063 struct {
00064 int code;
00065 char const *name;
00066 } const rerr_names[] = {
00067 { RERR_SYNTAX , "syntax or usage error" },
00068 { RERR_PROTOCOL , "protocol incompatibility" },
00069 { RERR_FILESELECT , "errors selecting input/output files, dirs" },
00070 { RERR_UNSUPPORTED, "requested action not supported" },
00071 { RERR_STARTCLIENT, "error starting client-server protocol" },
00072 { RERR_SOCKETIO , "error in socket IO" },
00073 { RERR_FILEIO , "error in file IO" },
00074 { RERR_STREAMIO , "error in rsync protocol data stream" },
00075 { RERR_MESSAGEIO , "errors with program diagnostics" },
00076 { RERR_IPC , "error in IPC code" },
00077 { RERR_CRASHED , "sibling process crashed" },
00078 { RERR_TERMINATED , "sibling process terminated abnormally" },
00079 { RERR_SIGNAL1 , "received SIGUSR1" },
00080 { RERR_SIGNAL , "received SIGINT, SIGTERM, or SIGHUP" },
00081 { RERR_WAITCHILD , "waitpid() failed" },
00082 { RERR_MALLOC , "error allocating core memory buffers" },
00083 { RERR_PARTIAL , "some files could not be transferred" },
00084 { RERR_VANISHED , "some files vanished before they could be transferred" },
00085 { RERR_TIMEOUT , "timeout in data send/receive" },
00086 { RERR_CMD_FAILED , "remote shell failed" },
00087 { RERR_CMD_KILLED , "remote shell killed" },
00088 { RERR_CMD_RUN , "remote command could not be run" },
00089 { RERR_CMD_NOTFOUND,"remote command not found" },
00090 { RERR_DEL_LIMIT , "the --max-delete limit stopped deletions" },
00091 { 0, NULL }
00092 };
00093
00094
00095
00096
00097
00098 static char const *rerr_name(int code)
00099 {
00100 int i;
00101 for (i = 0; rerr_names[i].name; i++) {
00102 if (rerr_names[i].code == code)
00103 return rerr_names[i].name;
00104 }
00105 return NULL;
00106 }
00107
00108 static void logit(int priority, char *buf)
00109 {
00110 if (logfile_was_closed)
00111 logfile_reopen();
00112 if (logfile) {
00113 fprintf(logfile,"%s [%d] %s",
00114 timestring(time(NULL)), (int)getpid(), buf);
00115 fflush(logfile);
00116 } else {
00117 syslog(priority, "%s", buf);
00118 }
00119 }
00120
00121 static void syslog_init()
00122 {
00123 static int been_here = 0;
00124 int options = LOG_PID;
00125
00126 if (been_here)
00127 return;
00128 been_here = 1;
00129
00130 #ifdef LOG_NDELAY
00131 options |= LOG_NDELAY;
00132 #endif
00133
00134 #ifdef LOG_DAEMON
00135 openlog("rsyncd", options, lp_syslog_facility());
00136 #else
00137 openlog("rsyncd", options);
00138 #endif
00139
00140 #ifndef LOG_NDELAY
00141 logit(LOG_INFO, "rsyncd started\n");
00142 #endif
00143 }
00144
00145 static void logfile_open(void)
00146 {
00147 mode_t old_umask = umask(022 | orig_umask);
00148 logfile = fopen(logfname, "a");
00149 umask(old_umask);
00150 if (!logfile) {
00151 int fopen_errno = errno;
00152
00153 syslog_init();
00154 rsyserr(FERROR, fopen_errno,
00155 "failed to open log-file %s", logfname);
00156 rprintf(FINFO, "Ignoring \"log file\" setting.\n");
00157 }
00158 }
00159
00160 void log_init(void)
00161 {
00162 time_t t;
00163
00164 if (log_initialised)
00165 return;
00166 log_initialised = 1;
00167
00168
00169
00170
00171 t = time(NULL);
00172 localtime(&t);
00173
00174
00175 logfname = lp_log_file();
00176 if (logfname && *logfname)
00177 logfile_open();
00178 else
00179 syslog_init();
00180 }
00181
00182 void logfile_close(void)
00183 {
00184 if (logfile) {
00185 logfile_was_closed = 1;
00186 fclose(logfile);
00187 logfile = NULL;
00188 }
00189 }
00190
00191 void logfile_reopen(void)
00192 {
00193 if (logfile_was_closed) {
00194 logfile_was_closed = 0;
00195 logfile_open();
00196 }
00197 }
00198
00199 static void filtered_fwrite(FILE *f, const char *buf, int len, int use_isprint)
00200 {
00201 const char *s, *end = buf + len;
00202 for (s = buf; s < end; s++) {
00203 if ((s < end - 4
00204 && *s == '\\' && s[1] == '#'
00205 && isdigit(*(uchar*)(s+2))
00206 && isdigit(*(uchar*)(s+3))
00207 && isdigit(*(uchar*)(s+4)))
00208 || (*s != '\t'
00209 && ((use_isprint && !isprint(*(uchar*)s))
00210 || *(uchar*)s < ' '))) {
00211 if (s != buf && fwrite(buf, s - buf, 1, f) != 1)
00212 exit_cleanup(RERR_MESSAGEIO);
00213 fprintf(f, "\\#%03o", *(uchar*)s);
00214 buf = s + 1;
00215 }
00216 }
00217 if (buf != end && fwrite(buf, end - buf, 1, f) != 1)
00218 exit_cleanup(RERR_MESSAGEIO);
00219 }
00220
00221
00222
00223
00224 void rwrite(enum logcode code, char *buf, int len)
00225 {
00226 int trailing_CR_or_NL;
00227 FILE *f = NULL;
00228
00229 if (len < 0)
00230 exit_cleanup(RERR_MESSAGEIO);
00231
00232 if (quiet && code == FINFO)
00233 return;
00234
00235 if (am_server && msg_fd_out >= 0) {
00236
00237 send_msg((enum msgcode)code, buf, len);
00238 return;
00239 }
00240
00241 if (code == FSOCKERR)
00242 code = FERROR;
00243
00244 if (code == FCLIENT)
00245 code = FINFO;
00246 else if (am_daemon) {
00247 static int in_block;
00248 char msg[2048];
00249 int priority = code == FERROR ? LOG_WARNING : LOG_INFO;
00250
00251 if (in_block)
00252 return;
00253 in_block = 1;
00254 if (!log_initialised)
00255 log_init();
00256 strlcpy(msg, buf, MIN((int)sizeof msg, len + 1));
00257 logit(priority, msg);
00258 in_block = 0;
00259
00260 if (code == FLOG || !am_server)
00261 return;
00262 } else if (code == FLOG)
00263 return;
00264
00265 if (am_server) {
00266
00267 if (io_multiplex_write((enum msgcode)code, buf, len))
00268 return;
00269 if (am_daemon) {
00270
00271 return;
00272 }
00273 }
00274
00275 switch (code) {
00276 case FERROR:
00277 log_got_error = 1;
00278 f = stderr;
00279 goto pre_scan;
00280 case FINFO:
00281 f = am_server ? stderr : stdout;
00282 pre_scan:
00283 while (len > 1 && *buf == '\n') {
00284 fputc(*buf, f);
00285 buf++;
00286 len--;
00287 }
00288 break;
00289 case FNAME:
00290 f = am_server ? stderr : stdout;
00291 break;
00292 default:
00293 exit_cleanup(RERR_MESSAGEIO);
00294 }
00295
00296 trailing_CR_or_NL = len && (buf[len-1] == '\n' || buf[len-1] == '\r')
00297 ? buf[--len] : 0;
00298
00299 #if defined HAVE_ICONV_OPEN && defined HAVE_ICONV_H
00300 if (ic_chck != (iconv_t)-1) {
00301 char convbuf[1024];
00302 char *in_buf = buf, *out_buf = convbuf;
00303 size_t in_cnt = len, out_cnt = sizeof convbuf - 1;
00304
00305 iconv(ic_chck, NULL, 0, NULL, 0);
00306 while (iconv(ic_chck, &in_buf,&in_cnt,
00307 &out_buf,&out_cnt) == (size_t)-1) {
00308 if (out_buf != convbuf) {
00309 filtered_fwrite(f, convbuf, out_buf - convbuf, 0);
00310 out_buf = convbuf;
00311 out_cnt = sizeof convbuf - 1;
00312 }
00313 if (errno == E2BIG)
00314 continue;
00315 fprintf(f, "\\#%03o", *(uchar*)in_buf++);
00316 in_cnt--;
00317 }
00318 if (out_buf != convbuf)
00319 filtered_fwrite(f, convbuf, out_buf - convbuf, 0);
00320 } else
00321 #endif
00322 filtered_fwrite(f, buf, len, !allow_8bit_chars);
00323
00324 if (trailing_CR_or_NL) {
00325 fputc(trailing_CR_or_NL, f);
00326 fflush(f);
00327 }
00328 }
00329
00330
00331
00332 void rprintf(enum logcode code, const char *format, ...)
00333 {
00334 va_list ap;
00335 char buf[BIGPATHBUFLEN];
00336 size_t len;
00337
00338 va_start(ap, format);
00339 len = vsnprintf(buf, sizeof buf, format, ap);
00340 va_end(ap);
00341
00342
00343
00344
00345 if (len > sizeof buf - 1) {
00346 static const char ellipsis[] = "[...]";
00347
00348
00349 len = sizeof buf - 1;
00350 buf[len] = '\0';
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362 memcpy(buf+len-sizeof ellipsis, ellipsis, sizeof ellipsis);
00363 if (format[strlen(format)-1] == '\n') {
00364 buf[len-1] = '\n';
00365 }
00366 }
00367
00368 rwrite(code, buf, len);
00369 }
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379 void rsyserr(enum logcode code, int errcode, const char *format, ...)
00380 {
00381 va_list ap;
00382 char buf[BIGPATHBUFLEN];
00383 size_t len;
00384
00385 strcpy(buf, RSYNC_NAME ": ");
00386 len = (sizeof RSYNC_NAME ": ") - 1;
00387
00388 va_start(ap, format);
00389 len += vsnprintf(buf + len, sizeof buf - len, format, ap);
00390 va_end(ap);
00391
00392 if (len < sizeof buf) {
00393 len += snprintf(buf + len, sizeof buf - len,
00394 ": %s (%d)\n", strerror(errcode), errcode);
00395 }
00396 if (len >= sizeof buf)
00397 exit_cleanup(RERR_MESSAGEIO);
00398
00399 rwrite(code, buf, len);
00400 }
00401
00402 void rflush(enum logcode code)
00403 {
00404 FILE *f = NULL;
00405
00406 if (am_daemon) {
00407 return;
00408 }
00409
00410 if (code == FLOG) {
00411 return;
00412 }
00413
00414 if (code == FERROR) {
00415 f = stderr;
00416 }
00417
00418 if (code == FINFO) {
00419 if (am_server)
00420 f = stderr;
00421 else
00422 f = stdout;
00423 }
00424
00425 if (!f) exit_cleanup(RERR_MESSAGEIO);
00426 fflush(f);
00427 }
00428
00429
00430
00431 static void log_formatted(enum logcode code, char *format, char *op,
00432 struct file_struct *file, struct stats *initial_stats,
00433 int iflags, char *hlink)
00434 {
00435 char buf[MAXPATHLEN+1024], buf2[MAXPATHLEN], fmt[32];
00436 char *p, *s, *n;
00437 size_t len, total;
00438 int64 b;
00439
00440 *fmt = '%';
00441
00442
00443
00444
00445 total = strlcpy(buf, format, sizeof buf);
00446 if (total > MAXPATHLEN) {
00447 rprintf(FERROR, "log-format string is WAY too long!\n");
00448 exit_cleanup(RERR_MESSAGEIO);
00449 }
00450 buf[total++] = '\n';
00451 buf[total] = '\0';
00452
00453 for (p = buf; (p = strchr(p, '%')) != NULL; ) {
00454 s = p++;
00455 n = fmt + 1;
00456 if (*p == '-')
00457 *n++ = *p++;
00458 while (isdigit(*(uchar*)p) && n - fmt < (int)(sizeof fmt) - 8)
00459 *n++ = *p++;
00460 if (!*p)
00461 break;
00462 *n = '\0';
00463 n = NULL;
00464
00465 switch (*p) {
00466 case 'h':
00467 if (am_daemon)
00468 n = client_name(0);
00469 break;
00470 case 'a':
00471 if (am_daemon)
00472 n = client_addr(0);
00473 break;
00474 case 'l':
00475 strlcat(fmt, ".0f", sizeof fmt);
00476 snprintf(buf2, sizeof buf2, fmt,
00477 (double)file->length);
00478 n = buf2;
00479 break;
00480 case 'U':
00481 strlcat(fmt, "ld", sizeof fmt);
00482 snprintf(buf2, sizeof buf2, fmt,
00483 (long)file->uid);
00484 n = buf2;
00485 break;
00486 case 'G':
00487 if (file->gid == GID_NONE)
00488 n = "DEFAULT";
00489 else {
00490 strlcat(fmt, "ld", sizeof fmt);
00491 snprintf(buf2, sizeof buf2, fmt,
00492 (long)file->gid);
00493 n = buf2;
00494 }
00495 break;
00496 case 'p':
00497 strlcat(fmt, "ld", sizeof fmt);
00498 snprintf(buf2, sizeof buf2, fmt,
00499 (long)getpid());
00500 n = buf2;
00501 break;
00502 case 'M':
00503 n = timestring(file->modtime);
00504 {
00505 char *cp = n;
00506 while ((cp = strchr(cp, ' ')) != NULL)
00507 *cp = '-';
00508 }
00509 break;
00510 case 'B':
00511 n = buf2 + MAXPATHLEN - PERMSTRING_SIZE;
00512 permstring(n - 1, file->mode);
00513 break;
00514 case 'o':
00515 n = op;
00516 break;
00517 case 'f':
00518 n = f_name(file, NULL);
00519 if (am_sender && file->dir.root) {
00520 pathjoin(buf2, sizeof buf2,
00521 file->dir.root, n);
00522 clean_fname(buf2, 0);
00523 if (fmt[1])
00524 strlcpy(n, buf2, MAXPATHLEN);
00525 else
00526 n = buf2;
00527 } else
00528 clean_fname(n, 0);
00529 if (*n == '/')
00530 n++;
00531 break;
00532 case 'n':
00533 n = f_name(file, NULL);
00534 if (S_ISDIR(file->mode))
00535 strlcat(n, "/", MAXPATHLEN);
00536 break;
00537 case 'L':
00538 if (hlink && *hlink) {
00539 n = hlink;
00540 strcpy(buf2, " => ");
00541 } else if (S_ISLNK(file->mode) && file->u.link) {
00542 n = file->u.link;
00543 strcpy(buf2, " -> ");
00544 } else {
00545 n = "";
00546 if (!fmt[1])
00547 break;
00548 strcpy(buf2, " ");
00549 }
00550 strlcat(fmt, "s", sizeof fmt);
00551 snprintf(buf2 + 4, sizeof buf2 - 4, fmt, n);
00552 n = buf2;
00553 break;
00554 case 'm':
00555 n = lp_name(module_id);
00556 break;
00557 case 't':
00558 n = timestring(time(NULL));
00559 break;
00560 case 'P':
00561 n = lp_path(module_id);
00562 break;
00563 case 'u':
00564 n = auth_user;
00565 break;
00566 case 'b':
00567 if (am_sender) {
00568 b = stats.total_written -
00569 initial_stats->total_written;
00570 } else {
00571 b = stats.total_read -
00572 initial_stats->total_read;
00573 }
00574 strlcat(fmt, ".0f", sizeof fmt);
00575 snprintf(buf2, sizeof buf2, fmt, (double)b);
00576 n = buf2;
00577 break;
00578 case 'c':
00579 if (!am_sender) {
00580 b = stats.total_written -
00581 initial_stats->total_written;
00582 } else {
00583 b = stats.total_read -
00584 initial_stats->total_read;
00585 }
00586 strlcat(fmt, ".0f", sizeof fmt);
00587 snprintf(buf2, sizeof buf2, fmt, (double)b);
00588 n = buf2;
00589 break;
00590 case 'i':
00591 if (iflags & ITEM_DELETED) {
00592 n = "*deleting";
00593 break;
00594 }
00595 n = buf2 + MAXPATHLEN - 32;
00596 n[0] = iflags & ITEM_LOCAL_CHANGE
00597 ? iflags & ITEM_XNAME_FOLLOWS ? 'h' : 'c'
00598 : !(iflags & ITEM_TRANSFER) ? '.'
00599 : !local_server && *op == 's' ? '<' : '>';
00600 n[1] = S_ISDIR(file->mode) ? 'd'
00601 : IS_SPECIAL(file->mode) ? 'S'
00602 : IS_DEVICE(file->mode) ? 'D'
00603 : S_ISLNK(file->mode) ? 'L' : 'f';
00604 n[2] = !(iflags & ITEM_REPORT_CHECKSUM) ? '.' : 'c';
00605 n[3] = !(iflags & ITEM_REPORT_SIZE) ? '.' : 's';
00606 n[4] = !(iflags & ITEM_REPORT_TIME) ? '.'
00607 : !preserve_times || S_ISLNK(file->mode) ? 'T' : 't';
00608 n[5] = !(iflags & ITEM_REPORT_PERMS) ? '.' : 'p';
00609 n[6] = !(iflags & ITEM_REPORT_OWNER) ? '.' : 'o';
00610 n[7] = !(iflags & ITEM_REPORT_GROUP) ? '.' : 'g';
00611 n[8] = '.';
00612 n[9] = '\0';
00613
00614 if (iflags & (ITEM_IS_NEW|ITEM_MISSING_DATA)) {
00615 char ch = iflags & ITEM_IS_NEW ? '+' : '?';
00616 int i;
00617 for (i = 2; n[i]; i++)
00618 n[i] = ch;
00619 } else if (n[0] == '.' || n[0] == 'h'
00620 || (n[0] == 'c' && n[1] == 'f')) {
00621 int i;
00622 for (i = 2; n[i]; i++) {
00623 if (n[i] != '.')
00624 break;
00625 }
00626 if (!n[i]) {
00627 for (i = 2; n[i]; i++)
00628 n[i] = ' ';
00629 }
00630 }
00631 break;
00632 }
00633
00634
00635 if (!n)
00636 continue;
00637 if (n != buf2 && fmt[1]) {
00638 strlcat(fmt, "s", sizeof fmt);
00639 snprintf(buf2, sizeof buf2, fmt, n);
00640 n = buf2;
00641 }
00642 len = strlen(n);
00643
00644
00645 total -= p - s + 1;
00646
00647 if (len + total >= (size_t)sizeof buf) {
00648 rprintf(FERROR,
00649 "buffer overflow expanding %%%c -- exiting\n",
00650 p[0]);
00651 exit_cleanup(RERR_MESSAGEIO);
00652 }
00653
00654
00655 if (len != (size_t)(p - s + 1))
00656 memmove(s + len, p + 1, total - (s - buf) + 1);
00657 total += len;
00658
00659
00660 if (len)
00661 memcpy(s, n, len);
00662
00663
00664 p = s + len;
00665 }
00666
00667 rwrite(code, buf, total);
00668 }
00669
00670
00671
00672 int log_format_has(const char *format, char esc)
00673 {
00674 const char *p;
00675
00676 if (!format)
00677 return 0;
00678
00679 for (p = format; (p = strchr(p, '%')) != NULL; ) {
00680 if (*++p == '-')
00681 p++;
00682 while (isdigit(*(uchar*)p))
00683 p++;
00684 if (!*p)
00685 break;
00686 if (*p == esc)
00687 return 1;
00688 }
00689 return 0;
00690 }
00691
00692
00693 void log_item(struct file_struct *file, struct stats *initial_stats,
00694 int iflags, char *hlink)
00695 {
00696 char *s_or_r = am_sender ? "send" : "recv";
00697
00698 if (lp_transfer_logging(module_id)) {
00699 log_formatted(FLOG, lp_log_format(module_id), s_or_r,
00700 file, initial_stats, iflags, hlink);
00701 } else if (log_format && !am_server) {
00702 log_formatted(FNAME, log_format, s_or_r,
00703 file, initial_stats, iflags, hlink);
00704 }
00705 }
00706
00707 void maybe_log_item(struct file_struct *file, int iflags, int itemizing,
00708 char *buf)
00709 {
00710 int significant_flags = iflags & SIGNIFICANT_ITEM_FLAGS;
00711 int see_item = itemizing && (significant_flags || *buf
00712 || log_format_has_i > 1 || (verbose > 1 && log_format_has_i));
00713 int local_change = iflags & ITEM_LOCAL_CHANGE && significant_flags;
00714 if (am_server) {
00715 if (am_daemon && !dry_run && see_item)
00716 log_item(file, &stats, iflags, buf);
00717 } else if (see_item || local_change || *buf
00718 || (S_ISDIR(file->mode) && significant_flags))
00719 log_item(file, &stats, iflags, buf);
00720 }
00721
00722 void log_delete(char *fname, int mode)
00723 {
00724 static struct file_struct file;
00725 int len = strlen(fname);
00726 char *fmt;
00727
00728 file.mode = mode;
00729 file.basename = fname;
00730
00731 if (!verbose && !log_format)
00732 ;
00733 else if (am_server && protocol_version >= 29 && len < MAXPATHLEN) {
00734 if (S_ISDIR(mode))
00735 len++;
00736 send_msg(MSG_DELETED, fname, len);
00737 } else {
00738 fmt = log_format_has_o_or_i ? log_format : "deleting %n";
00739 log_formatted(FCLIENT, fmt, "del.", &file, &stats,
00740 ITEM_DELETED, NULL);
00741 }
00742
00743 if (!am_daemon || dry_run || !lp_transfer_logging(module_id))
00744 return;
00745
00746 fmt = daemon_log_format_has_o_or_i ? lp_log_format(module_id) : "deleting %n";
00747 log_formatted(FLOG, fmt, "del.", &file, &stats, ITEM_DELETED, NULL);
00748 }
00749
00750
00751
00752
00753
00754
00755
00756 void log_exit(int code, const char *file, int line)
00757 {
00758 if (code == 0) {
00759 rprintf(FLOG,"sent %.0f bytes received %.0f bytes total size %.0f\n",
00760 (double)stats.total_written,
00761 (double)stats.total_read,
00762 (double)stats.total_size);
00763 } else {
00764 const char *name;
00765
00766 name = rerr_name(code);
00767 if (!name)
00768 name = "unexplained error";
00769
00770
00771 if (code == RERR_VANISHED) {
00772 rprintf(FINFO, "rsync warning: %s (code %d) at %s(%d) [%s=%s]\n",
00773 name, code, file, line, who_am_i(), RSYNC_VERSION);
00774 } else {
00775 rprintf(FERROR, "rsync error: %s (code %d) at %s(%d) [%s=%s]\n",
00776 name, code, file, line, who_am_i(), RSYNC_VERSION);
00777 }
00778 }
00779 }