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
00030 static char *logfname;
00031 static FILE *logfile;
00032 static int log_error_fd = -1;
00033 struct stats stats;
00034
00035 int log_got_error=0;
00036
00037 struct {
00038 int code;
00039 char const *name;
00040 } const rerr_names[] = {
00041 { RERR_SYNTAX , "syntax or usage error" },
00042 { RERR_PROTOCOL , "protocol incompatibility" },
00043 { RERR_FILESELECT , "errors selecting input/output files, dirs" },
00044 { RERR_UNSUPPORTED, "requested action not supported" },
00045 { RERR_STARTCLIENT, "error starting client-server protocol" },
00046 { RERR_SOCKETIO , "error in socket IO" },
00047 { RERR_FILEIO , "error in file IO" },
00048 { RERR_STREAMIO , "error in rsync protocol data stream" },
00049 { RERR_MESSAGEIO , "errors with program diagnostics" },
00050 { RERR_IPC , "error in IPC code" },
00051 { RERR_SIGNAL , "received SIGUSR1 or SIGINT" },
00052 { RERR_WAITCHILD , "some error returned by waitpid()" },
00053 { RERR_MALLOC , "error allocating core memory buffers" },
00054 { RERR_PARTIAL , "some files could not be transferred" },
00055 { RERR_TIMEOUT , "timeout in data send/receive" },
00056 { RERR_CMD_FAILED , "remote shell failed" },
00057 { RERR_CMD_KILLED , "remote shell killed" },
00058 { RERR_CMD_RUN, "remote command could not be run" },
00059 { RERR_CMD_NOTFOUND, "remote command not found" },
00060 { 0, NULL }
00061 };
00062
00063
00064
00065
00066
00067
00068 static char const *rerr_name(int code)
00069 {
00070 int i;
00071 for (i = 0; rerr_names[i].name; i++) {
00072 if (rerr_names[i].code == code)
00073 return rerr_names[i].name;
00074 }
00075 return NULL;
00076 }
00077
00078 struct err_list {
00079 struct err_list *next;
00080 char *buf;
00081 int len;
00082 int written;
00083 };
00084
00085 static struct err_list *err_list_head;
00086 static struct err_list *err_list_tail;
00087
00088
00089 static void err_list_add(int code, char *buf, int len)
00090 {
00091 struct err_list *el;
00092 el = (struct err_list *)malloc(sizeof(*el));
00093 if (!el) exit_cleanup(RERR_MALLOC);
00094 el->next = NULL;
00095 el->buf = malloc(len+4);
00096 if (!el->buf) exit_cleanup(RERR_MALLOC);
00097 memcpy(el->buf+4, buf, len);
00098 SIVAL(el->buf, 0, ((code+MPLEX_BASE)<<24) | len);
00099 el->len = len+4;
00100 el->written = 0;
00101 if (err_list_tail) {
00102 err_list_tail->next = el;
00103 } else {
00104 err_list_head = el;
00105 }
00106 err_list_tail = el;
00107 }
00108
00109
00110
00111 void err_list_push(void)
00112 {
00113 if (log_error_fd == -1) return;
00114
00115 while (err_list_head) {
00116 struct err_list *el = err_list_head;
00117 int n = write(log_error_fd, el->buf+el->written, el->len - el->written);
00118
00119
00120 if (n == -1) break;
00121 if (n > 0) {
00122 el->written += n;
00123 }
00124 if (el->written == el->len) {
00125 free(el->buf);
00126 err_list_head = el->next;
00127 if (!err_list_head) err_list_tail = NULL;
00128 free(el);
00129 }
00130 }
00131 }
00132
00133
00134 static void logit(int priority, char *buf)
00135 {
00136 if (logfname) {
00137 if (!logfile)
00138 log_open();
00139 fprintf(logfile,"%s [%d] %s",
00140 timestring(time(NULL)), (int)getpid(), buf);
00141 fflush(logfile);
00142 } else {
00143 syslog(priority, "%s", buf);
00144 }
00145 }
00146
00147 void log_init(void)
00148 {
00149 static int initialised;
00150 int options = LOG_PID;
00151 time_t t;
00152
00153 if (initialised) return;
00154 initialised = 1;
00155
00156
00157
00158
00159 t = time(NULL);
00160 localtime(&t);
00161
00162
00163 logfname = lp_log_file();
00164 if (logfname) {
00165 if (*logfname) {
00166 log_open();
00167 return;
00168 }
00169 logfname = NULL;
00170 }
00171
00172 #ifdef LOG_NDELAY
00173 options |= LOG_NDELAY;
00174 #endif
00175
00176 #ifdef LOG_DAEMON
00177 openlog("rsyncd", options, lp_syslog_facility());
00178 #else
00179 openlog("rsyncd", options);
00180 #endif
00181
00182 #ifndef LOG_NDELAY
00183 logit(LOG_INFO,"rsyncd started\n");
00184 #endif
00185 }
00186
00187 void log_open()
00188 {
00189 if (logfname && !logfile) {
00190 extern int orig_umask;
00191 int old_umask = umask(022 | orig_umask);
00192 logfile = fopen(logfname, "a");
00193 umask(old_umask);
00194 }
00195 }
00196
00197 void log_close()
00198 {
00199 if (logfile) {
00200 fclose(logfile);
00201 logfile = NULL;
00202 }
00203 }
00204
00205
00206
00207 void set_error_fd(int fd)
00208 {
00209 log_error_fd = fd;
00210 set_nonblocking(log_error_fd);
00211 }
00212
00213
00214
00215 void rwrite(enum logcode code, char *buf, int len)
00216 {
00217 FILE *f=NULL;
00218 extern int am_daemon;
00219 extern int am_server;
00220 extern int quiet;
00221
00222
00223 if (quiet && code == FINFO) return;
00224
00225 if (len < 0) exit_cleanup(RERR_MESSAGEIO);
00226
00227 buf[len] = 0;
00228
00229 if (code == FLOG) {
00230 if (am_daemon) logit(LOG_INFO, buf);
00231 return;
00232 }
00233
00234
00235 if (am_server && log_error_fd != -1) {
00236 err_list_add(code, buf, len);
00237 err_list_push();
00238 return;
00239 }
00240
00241
00242
00243
00244
00245
00246 if (am_server && io_multiplex_write(code, buf, len)) {
00247 return;
00248 }
00249
00250 if (am_daemon) {
00251 static int depth;
00252 int priority = LOG_INFO;
00253 if (code == FERROR) priority = LOG_WARNING;
00254
00255 if (depth) return;
00256
00257 depth++;
00258
00259 log_init();
00260 logit(priority, buf);
00261
00262 depth--;
00263 return;
00264 }
00265
00266 if (code == FERROR) {
00267 log_got_error = 1;
00268 f = stderr;
00269 }
00270
00271 if (code == FINFO) {
00272 if (am_server)
00273 f = stderr;
00274 else
00275 f = stdout;
00276 }
00277
00278 if (!f) exit_cleanup(RERR_MESSAGEIO);
00279
00280 if (fwrite(buf, len, 1, f) != 1) exit_cleanup(RERR_MESSAGEIO);
00281
00282 if (buf[len-1] == '\r' || buf[len-1] == '\n') fflush(f);
00283 }
00284
00285
00286
00287
00288 void rprintf(enum logcode code, const char *format, ...)
00289 {
00290 va_list ap;
00291 char buf[1024];
00292 int len;
00293
00294 va_start(ap, format);
00295
00296 len = vsnprintf(buf, sizeof(buf), format, ap);
00297 va_end(ap);
00298
00299
00300
00301
00302 if ((size_t) len > sizeof(buf)-1 || len < 0) {
00303 const char ellipsis[] = "[...]";
00304
00305
00306 len = sizeof(buf)-1;
00307 buf[len] = '\0';
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319 strncpy(buf+len-sizeof(ellipsis), ellipsis, sizeof(ellipsis));
00320 if (format[strlen(format)-1] == '\n') {
00321 buf[len-1] = '\n';
00322 }
00323 }
00324
00325 rwrite(code, buf, len);
00326 }
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337 void rsyserr(enum logcode code, int errcode, const char *format, ...)
00338 {
00339 va_list ap;
00340 char buf[1024];
00341 int len;
00342 size_t sys_len;
00343 char *sysmsg;
00344
00345 va_start(ap, format);
00346
00347 len = vsnprintf(buf, sizeof(buf), format, ap);
00348 va_end(ap);
00349
00350
00351
00352 if ((size_t) len > sizeof(buf)-1)
00353 exit_cleanup(RERR_MESSAGEIO);
00354
00355 sysmsg = strerror(errcode);
00356 sys_len = strlen(sysmsg);
00357 if ((size_t) len + 3 + sys_len > sizeof(buf) - 1)
00358 exit_cleanup(RERR_MESSAGEIO);
00359
00360 strcpy(buf + len, ": ");
00361 len += 2;
00362 strcpy(buf + len, sysmsg);
00363 len += sys_len;
00364 strcpy(buf + len, "\n");
00365 len++;
00366
00367 rwrite(code, buf, len);
00368 }
00369
00370
00371
00372 void rflush(enum logcode code)
00373 {
00374 FILE *f = NULL;
00375 extern int am_daemon;
00376
00377 if (am_daemon) {
00378 return;
00379 }
00380
00381 if (code == FLOG) {
00382 return;
00383 }
00384
00385 if (code == FERROR) {
00386 f = stderr;
00387 }
00388
00389 if (code == FINFO) {
00390 extern int am_server;
00391 if (am_server)
00392 f = stderr;
00393 else
00394 f = stdout;
00395 }
00396
00397 if (!f) exit_cleanup(RERR_MESSAGEIO);
00398 fflush(f);
00399 }
00400
00401
00402
00403
00404
00405 static void log_formatted(enum logcode code,
00406 char *format, char *op, struct file_struct *file,
00407 struct stats *initial_stats)
00408 {
00409 extern int module_id;
00410 extern char *auth_user;
00411 char buf[1024];
00412 char buf2[1024];
00413 char *p, *s, *n;
00414 size_t l;
00415 extern struct stats stats;
00416 extern int am_sender;
00417 extern int am_daemon;
00418 int64 b;
00419
00420
00421
00422
00423
00424
00425 memset(buf, 0, sizeof buf);
00426 strlcpy(buf, format, sizeof(buf));
00427
00428 for (s=&buf[0];
00429 s && (p=strchr(s,'%')); ) {
00430 n = NULL;
00431 s = p + 1;
00432
00433 switch (p[1]) {
00434 case 'h': if (am_daemon) n = client_name(0); break;
00435 case 'a': if (am_daemon) n = client_addr(0); break;
00436 case 'l':
00437 snprintf(buf2,sizeof(buf2),"%.0f",
00438 (double)file->length);
00439 n = buf2;
00440 break;
00441 case 'p':
00442 snprintf(buf2,sizeof(buf2),"%d",
00443 (int)getpid());
00444 n = buf2;
00445 break;
00446 case 'o': n = op; break;
00447 case 'f':
00448 snprintf(buf2, sizeof(buf2), "%s/%s",
00449 file->basedir?file->basedir:"",
00450 f_name(file));
00451 clean_fname(buf2);
00452 n = buf2;
00453 if (*n == '/') n++;
00454 break;
00455 case 'm': n = lp_name(module_id); break;
00456 case 't': n = timestring(time(NULL)); break;
00457 case 'P': n = lp_path(module_id); break;
00458 case 'u': n = auth_user; break;
00459 case 'b':
00460 if (am_sender) {
00461 b = stats.total_written -
00462 initial_stats->total_written;
00463 } else {
00464 b = stats.total_read -
00465 initial_stats->total_read;
00466 }
00467 snprintf(buf2,sizeof(buf2),"%.0f", (double)b);
00468 n = buf2;
00469 break;
00470 case 'c':
00471 if (!am_sender) {
00472 b = stats.total_written -
00473 initial_stats->total_written;
00474 } else {
00475 b = stats.total_read -
00476 initial_stats->total_read;
00477 }
00478 snprintf(buf2,sizeof(buf2),"%.0f", (double)b);
00479 n = buf2;
00480 break;
00481 }
00482
00483
00484
00485
00486 if (!n)
00487 continue;
00488
00489 l = strlen(n);
00490
00491 if (l + ((int)(s - &buf[0])) >= sizeof(buf)) {
00492 rprintf(FERROR,"buffer overflow expanding %%%c - exiting\n",
00493 p[0]);
00494 exit_cleanup(RERR_MESSAGEIO);
00495 }
00496
00497
00498 if (l != 2) {
00499 memmove(s+(l-1), s+1, strlen(s+1)+1);
00500 }
00501
00502
00503
00504 memcpy(p, n, l);
00505
00506
00507 s = p+l;
00508 }
00509
00510 rprintf(code,"%s\n", buf);
00511 }
00512
00513
00514 void log_send(struct file_struct *file, struct stats *initial_stats)
00515 {
00516 extern int module_id;
00517 extern int am_server;
00518 extern char *log_format;
00519
00520 if (lp_transfer_logging(module_id)) {
00521 log_formatted(FLOG, lp_log_format(module_id), "send", file, initial_stats);
00522 } else if (log_format && !am_server) {
00523 log_formatted(FINFO, log_format, "send", file, initial_stats);
00524 }
00525 }
00526
00527
00528 void log_recv(struct file_struct *file, struct stats *initial_stats)
00529 {
00530 extern int module_id;
00531 extern int am_server;
00532 extern char *log_format;
00533
00534 if (lp_transfer_logging(module_id)) {
00535 log_formatted(FLOG, lp_log_format(module_id), "recv", file, initial_stats);
00536 } else if (log_format && !am_server) {
00537 log_formatted(FINFO, log_format, "recv", file, initial_stats);
00538 }
00539 }
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550 void log_exit(int code, const char *file, int line)
00551 {
00552 if (code == 0) {
00553 extern struct stats stats;
00554 rprintf(FLOG,"wrote %.0f bytes read %.0f bytes total size %.0f\n",
00555 (double)stats.total_written,
00556 (double)stats.total_read,
00557 (double)stats.total_size);
00558 } else {
00559 const char *name;
00560
00561 name = rerr_name(code);
00562 if (!name)
00563 name = "unexplained error";
00564
00565 rprintf(FERROR,"rsync error: %s (code %d) at %s(%d)\n",
00566 name, code, file, line);
00567 }
00568 }
00569
00570
00571
00572
00573
00574
00575 void log_transfer(struct file_struct *file, const char *fname)
00576 {
00577 extern int verbose;
00578
00579 if (!verbose) return;
00580
00581 rprintf(FINFO, "%s\n", fname);
00582 }