⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 log.c

📁 Rsync 3.0.5 source code
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Logging and utility functions. * * Copyright (C) 1998-2001 Andrew Tridgell <tridge@samba.org> * Copyright (C) 2000-2001 Martin Pool <mbp@samba.org> * Copyright (C) 2003-2008 Wayne Davison * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, visit the http://fsf.org website. */#include "rsync.h"#include "ifuncs.h"extern int verbose;extern int dry_run;extern int am_daemon;extern int am_server;extern int am_sender;extern int am_generator;extern int local_server;extern int quiet;extern int module_id;extern int msg_fd_out;extern int allow_8bit_chars;extern int protocol_version;extern int preserve_times;extern int uid_ndx;extern int gid_ndx;extern int progress_is_active;extern int stdout_format_has_i;extern int stdout_format_has_o_or_i;extern int logfile_format_has_i;extern int logfile_format_has_o_or_i;extern int receiver_symlink_times;extern mode_t orig_umask;extern char *auth_user;extern char *stdout_format;extern char *logfile_format;extern char *logfile_name;#ifdef ICONV_CONSTextern iconv_t ic_chck;#endif#ifdef ICONV_OPTIONextern iconv_t ic_send, ic_recv;#endifextern char curr_dir[];extern char *full_module_path;extern unsigned int module_dirlen;static int log_initialised;static int logfile_was_closed;static FILE *logfile_fp;struct stats stats;int got_xfer_error = 0;struct {        int code;        char const *name;} const rerr_names[] = {	{ RERR_SYNTAX     , "syntax or usage error" },	{ RERR_PROTOCOL   , "protocol incompatibility" },	{ RERR_FILESELECT , "errors selecting input/output files, dirs" },	{ RERR_UNSUPPORTED, "requested action not supported" },	{ RERR_STARTCLIENT, "error starting client-server protocol" },	{ RERR_SOCKETIO   , "error in socket IO" },	{ RERR_FILEIO     , "error in file IO" },	{ RERR_STREAMIO   , "error in rsync protocol data stream" },	{ RERR_MESSAGEIO  , "errors with program diagnostics" },	{ RERR_IPC        , "error in IPC code" },	{ RERR_CRASHED    , "sibling process crashed" },	{ RERR_TERMINATED , "sibling process terminated abnormally" },	{ RERR_SIGNAL1    , "received SIGUSR1" },	{ RERR_SIGNAL     , "received SIGINT, SIGTERM, or SIGHUP" },	{ RERR_WAITCHILD  , "waitpid() failed" },	{ RERR_MALLOC     , "error allocating core memory buffers" },	{ RERR_PARTIAL    , "some files/attrs were not transferred (see previous errors)" },	{ RERR_VANISHED   , "some files vanished before they could be transferred" },	{ RERR_TIMEOUT    , "timeout in data send/receive" },	{ RERR_CONTIMEOUT , "timeout waiting for daemon connection" },	{ RERR_CMD_FAILED , "remote shell failed" },	{ RERR_CMD_KILLED , "remote shell killed" },	{ RERR_CMD_RUN    , "remote command could not be run" },	{ RERR_CMD_NOTFOUND,"remote command not found" },	{ RERR_DEL_LIMIT  , "the --max-delete limit stopped deletions" },	{ 0, NULL }};/* * Map from rsync error code to name, or return NULL. */static char const *rerr_name(int code){	int i;	for (i = 0; rerr_names[i].name; i++) {		if (rerr_names[i].code == code)			return rerr_names[i].name;	}	return NULL;}static void logit(int priority, const char *buf){	if (logfile_was_closed)		logfile_reopen();	if (logfile_fp) {		fprintf(logfile_fp, "%s [%d] %s",			timestring(time(NULL)), (int)getpid(), buf);		fflush(logfile_fp);	} else {		syslog(priority, "%s", buf);	}}static void syslog_init(){	static int been_here = 0;	int options = LOG_PID;	if (been_here)		return;	been_here = 1;#ifdef LOG_NDELAY	options |= LOG_NDELAY;#endif#ifdef LOG_DAEMON	openlog("rsyncd", options, lp_syslog_facility(module_id));#else	openlog("rsyncd", options);#endif#ifndef LOG_NDELAY	logit(LOG_INFO, "rsyncd started\n");#endif}static void logfile_open(void){	mode_t old_umask = umask(022 | orig_umask);	logfile_fp = fopen(logfile_name, "a");	umask(old_umask);	if (!logfile_fp) {		int fopen_errno = errno;		/* Rsync falls back to using syslog on failure. */		syslog_init();		rsyserr(FERROR, fopen_errno,			"failed to open log-file %s", logfile_name);		rprintf(FINFO, "Ignoring \"log file\" setting.\n");	}}void log_init(int restart){	if (log_initialised) {		if (!restart)			return;		if (strcmp(logfile_name, lp_log_file(module_id)) != 0) {			if (logfile_fp) {				fclose(logfile_fp);				logfile_fp = NULL;			} else				closelog();			logfile_name = NULL;		} else if (*logfile_name)			return; /* unchanged, non-empty "log file" names */		else if (lp_syslog_facility(-1) != lp_syslog_facility(module_id))			closelog();		else			return; /* unchanged syslog settings */	} else		log_initialised = 1;	/* This looks pointless, but it is needed in order for the	 * C library on some systems to fetch the timezone info	 * before the chroot. */	timestring(time(NULL));	/* Optionally use a log file instead of syslog.  (Non-daemon	 * rsyncs will have already set logfile_name, as needed.) */	if (am_daemon && !logfile_name)		logfile_name = lp_log_file(module_id);	if (logfile_name && *logfile_name)		logfile_open();	else		syslog_init();}void logfile_close(void){	if (logfile_fp) {		logfile_was_closed = 1;		fclose(logfile_fp);		logfile_fp = NULL;	}}void logfile_reopen(void){	if (logfile_was_closed) {		logfile_was_closed = 0;		logfile_open();	}}static void filtered_fwrite(FILE *f, const char *buf, int len, int use_isprint){	const char *s, *end = buf + len;	for (s = buf; s < end; s++) {		if ((s < end - 4		  && *s == '\\' && s[1] == '#'		  && isDigit(s + 2)		  && isDigit(s + 3)		  && isDigit(s + 4))		 || (*s != '\t'		  && ((use_isprint && !isPrint(s))		   || *(uchar*)s < ' '))) {			if (s != buf && fwrite(buf, s - buf, 1, f) != 1)				exit_cleanup(RERR_MESSAGEIO);			fprintf(f, "\\#%03o", *(uchar*)s);			buf = s + 1;		}	}	if (buf != end && fwrite(buf, end - buf, 1, f) != 1)		exit_cleanup(RERR_MESSAGEIO);}/* this is the underlying (unformatted) rsync debugging function. Call * it with FINFO, FERROR_*, FWARNING, FLOG, or FCLIENT.  Note: recursion * can happen with certain fatal conditions. */void rwrite(enum logcode code, const char *buf, int len, int is_utf8){	int trailing_CR_or_NL;	FILE *f = NULL;#ifdef ICONV_OPTION	iconv_t ic = is_utf8 && ic_recv != (iconv_t)-1 ? ic_recv : ic_chck;#else#ifdef ICONV_CONST	iconv_t ic = ic_chck;#endif#endif	if (len < 0)		exit_cleanup(RERR_MESSAGEIO);	if (am_server && msg_fd_out >= 0) {		assert(!is_utf8);		/* Pass the message to our sibling in native charset. */		send_msg((enum msgcode)code, buf, len, 0);		return;	}	if (code == FERROR_SOCKET) /* This gets simplified for a non-sibling. */		code = FERROR;	else if (code == FERROR_UTF8) {		is_utf8 = 1;		code = FERROR;	}	if (code == FCLIENT)		code = FINFO;	else if (am_daemon || logfile_name) {		static int in_block;		char msg[2048];		int priority = code == FINFO || code == FLOG ? LOG_INFO :  LOG_WARNING;		if (in_block)			return;		in_block = 1;		if (!log_initialised)			log_init(0);		strlcpy(msg, buf, MIN((int)sizeof msg, len + 1));		logit(priority, msg);		in_block = 0;		if (code == FLOG || (am_daemon && !am_server))			return;	} else if (code == FLOG)		return;	if (quiet && code == FINFO)		return;	if (am_server) {		enum msgcode msg = (enum msgcode)code;		if (protocol_version < 30) {			if (msg == MSG_ERROR)				msg = MSG_ERROR_XFER;			else if (msg == MSG_WARNING)				msg = MSG_INFO;		}		/* Pass the message to the non-server side. */		if (send_msg(msg, buf, len, !is_utf8))			return;		if (am_daemon) {			/* TODO: can we send the error to the user somehow? */			return;		}	}	switch (code) {	case FERROR_XFER:		got_xfer_error = 1;		/* FALL THROUGH */	case FERROR:	case FWARNING:		f = stderr;		break;	case FINFO:		f = am_server ? stderr : stdout;		break;	default:		exit_cleanup(RERR_MESSAGEIO);	}	if (progress_is_active && !am_server) {		fputc('\n', f);		progress_is_active = 0;	}	trailing_CR_or_NL = len && (buf[len-1] == '\n' || buf[len-1] == '\r')			  ? buf[--len] : 0;#ifdef ICONV_CONST	if (ic != (iconv_t)-1) {		xbuf outbuf, inbuf;		char convbuf[1024];		int ierrno;		INIT_CONST_XBUF(outbuf, convbuf);		INIT_XBUF(inbuf, (char*)buf, len, -1);		while (inbuf.len) {			iconvbufs(ic, &inbuf, &outbuf, 0);			ierrno = errno;			if (outbuf.len) {				filtered_fwrite(f, convbuf, outbuf.len, 0);				outbuf.len = 0;			}			if (!ierrno || ierrno == E2BIG)				continue;			fprintf(f, "\\#%03o", CVAL(inbuf.buf, inbuf.pos++));			inbuf.len--;		}	} else#endif		filtered_fwrite(f, buf, len, !allow_8bit_chars);	if (trailing_CR_or_NL) {		fputc(trailing_CR_or_NL, f);		fflush(f);	}}/* This is the rsync debugging function. Call it with FINFO, FERROR_*, * FWARNING, FLOG, or FCLIENT. */void rprintf(enum logcode code, const char *format, ...){	va_list ap;	char buf[BIGPATHBUFLEN];	size_t len;	va_start(ap, format);	len = vsnprintf(buf, sizeof buf, format, ap);	va_end(ap);	/* Deal with buffer overruns.  Instead of panicking, just	 * truncate the resulting string.  (Note that configure ensures	 * that we have a vsnprintf() that doesn't ever return -1.) */	if (len > sizeof buf - 1) {		static const char ellipsis[] = "[...]";		/* Reset length, and zero-terminate the end of our buffer */		len = sizeof buf - 1;		buf[len] = '\0';		/* Copy the ellipsis to the end of the string, but give		 * us one extra character:		 *		 *                  v--- null byte at buf[sizeof buf - 1]		 *        abcdefghij0		 *     -> abcd[...]00  <-- now two null bytes at end		 *		 * If the input format string has a trailing newline,		 * we copy it into that extra null; if it doesn't, well,		 * all we lose is one byte.  */		memcpy(buf+len-sizeof ellipsis, ellipsis, sizeof ellipsis);		if (format[strlen(format)-1] == '\n') {			buf[len-1] = '\n';		}	}	rwrite(code, buf, len, 0);}/* This is like rprintf, but it also tries to print some * representation of the error code.  Normally errcode = errno. * * Unlike rprintf, this always adds a newline and there should not be * one in the format string. * * Note that since strerror might involve dynamically loading a * message catalog we need to call it once before chroot-ing. */void rsyserr(enum logcode code, int errcode, const char *format, ...){	va_list ap;	char buf[BIGPATHBUFLEN];	size_t len;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -