log.c

説明を見る。
00001 /* -*- c-file-style: "linux"; -*-
00002 
00003    Copyright (C) 1998-2001 by Andrew Tridgell <tridge@samba.org>
00004    Copyright (C) 2000-2001 by Martin Pool <mbp@samba.org>
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 2 of the License, or
00009    (at your option) any later version.
00010 
00011    This program is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014    GNU General Public License for more details.
00015 
00016    You should have received a copy of the GNU General Public License
00017    along with this program; if not, write to the Free Software
00018    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019 */
00020 
00021 /*
00022   Logging and utility functions.
00023   tridge, May 1998
00024 
00025   Mapping to human-readable messages added by Martin Pool
00026   <mbp@samba.org>, Oct 2000.
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  * Map from rsync error code to name, or return NULL.
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                 /* Rsync falls back to using syslog on failure. */
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         /* this looks pointless, but it is needed in order for the
00169          * C library on some systems to fetch the timezone info
00170          * before the chroot */
00171         t = time(NULL);
00172         localtime(&t);
00173 
00174         /* optionally use a log file instead of syslog */
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 /* this is the underlying (unformatted) rsync debugging function. Call
00222  * it with FINFO, FERROR or FLOG.  Note: recursion can happen with
00223  * certain fatal conditions. */
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                 /* Pass the message to our sibling. */
00237                 send_msg((enum msgcode)code, buf, len);
00238                 return;
00239         }
00240 
00241         if (code == FSOCKERR) /* This gets simplified for a non-sibling. */
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                 /* Pass the message to the non-server side. */
00267                 if (io_multiplex_write((enum msgcode)code, buf, len))
00268                         return;
00269                 if (am_daemon) {
00270                         /* TODO: can we send the error to the user somehow? */
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 /* This is the rsync debugging function. Call it with FINFO, FERROR or
00331  * FLOG. */
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         /* Deal with buffer overruns.  Instead of panicking, just
00343          * truncate the resulting string.  (Note that configure ensures
00344          * that we have a vsnprintf() that doesn't ever return -1.) */
00345         if (len > sizeof buf - 1) {
00346                 static const char ellipsis[] = "[...]";
00347 
00348                 /* Reset length, and zero-terminate the end of our buffer */
00349                 len = sizeof buf - 1;
00350                 buf[len] = '\0';
00351 
00352                 /* Copy the ellipsis to the end of the string, but give
00353                  * us one extra character:
00354                  *
00355                  *                  v--- null byte at buf[sizeof buf - 1]
00356                  *        abcdefghij0
00357                  *     -> abcd[...]00  <-- now two null bytes at end
00358                  *
00359                  * If the input format string has a trailing newline,
00360                  * we copy it into that extra null; if it doesn't, well,
00361                  * all we lose is one byte.  */
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 /* This is like rprintf, but it also tries to print some
00372  * representation of the error code.  Normally errcode = errno.
00373  *
00374  * Unlike rprintf, this always adds a newline and there should not be
00375  * one in the format string.
00376  *
00377  * Note that since strerror might involve dynamically loading a
00378  * message catalog we need to call it once before chroot-ing. */
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 /* a generic logging routine for send/recv, with parameter
00430  * substitiution */
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         /* We expand % codes one by one in place in buf.  We don't
00443          * copy in the terminating null of the inserted strings, but
00444          * rather keep going until we reach the null of the format. */
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); /* skip the type char */
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                 /* "n" is the string to be inserted in place of this % code. */
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                 /* Subtract the length of the escape from the string's size. */
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                 /* Shuffle the rest of the string along to make space for n */
00655                 if (len != (size_t)(p - s + 1))
00656                         memmove(s + len, p + 1, total - (s - buf) + 1);
00657                 total += len;
00658 
00659                 /* Insert the contents of string "n", but NOT its null. */
00660                 if (len)
00661                         memcpy(s, n, len);
00662 
00663                 /* Skip over inserted string; continue looking */
00664                 p = s + len;
00665         }
00666 
00667         rwrite(code, buf, total);
00668 }
00669 
00670 /* Return 1 if the format escape is in the log-format string (e.g. look for
00671  * the 'b' in the "%9b" format escape). */
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 /* log the transfer of a file */
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++; /* directories include trailing null */
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  * Called when the transfer is interrupted for some reason.
00752  *
00753  * Code is one of the RERR_* codes from errcode.h, or terminating
00754  * successfully.
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                 /* VANISHED is not an error, only a warning */
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 }

rsyncに対してSat Dec 5 19:45:41 2009に生成されました。  doxygen 1.4.7