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

📄 rsync.c

📁 Rsync 3.0.5 source code
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Routines common to more than one of the rsync processes. * * Copyright (C) 1996 Andrew Tridgell * Copyright (C) 1996 Paul Mackerras * 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"#if defined HAVE_LIBCHARSET_H && defined HAVE_LOCALE_CHARSET#include <libcharset.h>#elif defined HAVE_LANGINFO_H && defined HAVE_NL_LANGINFO#include <langinfo.h>#endifextern int verbose;extern int dry_run;extern int preserve_acls;extern int preserve_xattrs;extern int preserve_perms;extern int preserve_executability;extern int preserve_times;extern int am_root;extern int am_server;extern int am_sender;extern int am_generator;extern int am_starting_up;extern int allow_8bit_chars;extern int protocol_version;extern int uid_ndx;extern int gid_ndx;extern int inc_recurse;extern int inplace;extern int flist_eof;extern int keep_dirlinks;extern int make_backups;extern struct file_list *cur_flist, *first_flist, *dir_flist;extern struct chmod_mode_struct *daemon_chmod_modes;#ifdef ICONV_OPTIONextern char *iconv_opt;#endif#ifdef ICONV_CONSTiconv_t ic_chck = (iconv_t)-1;# ifdef ICONV_OPTIONiconv_t ic_send = (iconv_t)-1, ic_recv = (iconv_t)-1;# endifstatic const char *default_charset(void){# if defined HAVE_LIBCHARSET_H && defined HAVE_LOCALE_CHARSET	return locale_charset();# elif defined HAVE_LANGINFO_H && defined HAVE_NL_LANGINFO	return nl_langinfo(CODESET);# else	return ""; /* Works with (at the very least) gnu iconv... */# endif}void setup_iconv(void){	const char *defset = default_charset();# ifdef ICONV_OPTION	const char *charset;	char *cp;# endif	if (!am_server && !allow_8bit_chars) {		/* It's OK if this fails... */		ic_chck = iconv_open(defset, defset);		if (verbose > 3) {			if (ic_chck == (iconv_t)-1) {				rprintf(FINFO,					"note: iconv_open(\"%s\", \"%s\") failed (%d)"					" -- using isprint() instead of iconv().\n",					defset, defset, errno);			} else {				rprintf(FINFO,					"note: iconv_open(\"%s\", \"%s\") succeeded.\n",					defset, defset);			}		}	}# ifdef ICONV_OPTION	if (!iconv_opt)		return;	if ((cp = strchr(iconv_opt, ',')) != NULL) {		if (am_server) /* A local transfer needs this. */			iconv_opt = cp + 1;		else			*cp = '\0';	}	if (!*iconv_opt || (*iconv_opt == '.' && iconv_opt[1] == '\0'))		charset = defset;	else		charset = iconv_opt;	if ((ic_send = iconv_open(UTF8_CHARSET, charset)) == (iconv_t)-1) {		rprintf(FERROR, "iconv_open(\"%s\", \"%s\") failed\n",			UTF8_CHARSET, charset);		exit_cleanup(RERR_UNSUPPORTED);	}	if ((ic_recv = iconv_open(charset, UTF8_CHARSET)) == (iconv_t)-1) {		rprintf(FERROR, "iconv_open(\"%s\", \"%s\") failed\n",			charset, UTF8_CHARSET);		exit_cleanup(RERR_UNSUPPORTED);	}	if (verbose > 1) {		rprintf(FINFO, "%s charset: %s\n",			am_server ? "server" : "client",			*charset ? charset : "[LOCALE]");	}# endif}/* This function converts the characters in the "in" xbuf into characters * in the "out" xbuf.  The "len" of the "in" xbuf is used starting from its * "pos".  The "size" of the "out" xbuf restricts how many characters can be * stored, starting at its "pos+len" position.  Note that the last byte of * the buffer is never used, which reserves space for a terminating '\0'. * We return a 0 on success or a -1 on error.  An error also sets errno to * E2BIG, EILSEQ, or EINVAL (see below); otherwise errno will be set to 0. * The "in" xbuf is altered to update "pos" and "len".  The "out" xbuf has * data appended, and its "len" incremented.   If ICB_EXPAND_OUT is set in * "flags", the "out" xbuf will also be allocated if empty, and expanded if * too small (so E2BIG will not be returned).  If ICB_INCLUDE_BAD is set in * "flags", any badly-encoded chars are included verbatim in the "out" xbuf, * so EILSEQ will not be returned.  Likewise for ICB_INCLUDE_INCOMPLETE with * respect to an incomplete multi-byte char at the end, which ensures that * EINVAL is not returned.  Anytime "in.pos" is 0 we will reset the iconv() * state prior to processing the characters. */int iconvbufs(iconv_t ic, xbuf *in, xbuf *out, int flags){	ICONV_CONST char *ibuf;	size_t icnt, ocnt;	char *obuf;	if (!out->size && flags & ICB_EXPAND_OUT)		alloc_xbuf(out, 1024);	if (!in->pos)		iconv(ic, NULL, 0, NULL, 0);	ibuf = in->buf + in->pos;	icnt = in->len;	obuf = out->buf + (out->pos + out->len);	ocnt = out->size - (out->pos + out->len) - 1;	while (icnt) {		while (iconv(ic, &ibuf, &icnt, &obuf, &ocnt) == (size_t)-1) {			if (errno == EINTR)				continue;			if (errno == EINVAL) {				if (!(flags & ICB_INCLUDE_INCOMPLETE))					goto finish;			} else if (errno == EILSEQ) {				if (!(flags & ICB_INCLUDE_BAD))					goto finish;			} else {				size_t opos = obuf - out->buf;				if (!(flags & ICB_EXPAND_OUT)) {					errno = E2BIG;					goto finish;				}				realloc_xbuf(out, out->size + 1024);				obuf = out->buf + opos;				ocnt += 1024;				continue;			}			*obuf++ = *ibuf++;			ocnt--, icnt--;		}	}	errno = 0;  finish:	in->len = icnt;	in->pos = ibuf - in->buf;	out->len = obuf - out->buf - out->pos;	return errno ? -1 : 0;}#endifvoid send_protected_args(int fd, char *args[]){	int i;#ifdef ICONV_OPTION	int convert = ic_send != (iconv_t)-1;	xbuf outbuf, inbuf;	if (convert)		alloc_xbuf(&outbuf, 1024);#endif	for (i = 0; args[i]; i++) {} /* find first NULL */	args[i] = "rsync"; /* set a new arg0 */	if (verbose > 1)		print_child_argv("protected args:", args + i + 1);	do {		if (!args[i][0])			write_buf(fd, ".", 2);#ifdef ICONV_OPTION		else if (convert) {			INIT_XBUF_STRLEN(inbuf, args[i]);			iconvbufs(ic_send, &inbuf, &outbuf,				  ICB_EXPAND_OUT | ICB_INCLUDE_BAD | ICB_INCLUDE_INCOMPLETE);			outbuf.buf[outbuf.len] = '\0';			write_buf(fd, outbuf.buf, outbuf.len + 1);			outbuf.len = 0;		}#endif		else			write_buf(fd, args[i], strlen(args[i]) + 1);	} while (args[++i]);	write_byte(fd, 0);#ifdef ICONV_OPTION	if (convert)		free(outbuf.buf);#endif}int read_ndx_and_attrs(int f_in, int *iflag_ptr, uchar *type_ptr,		       char *buf, int *len_ptr){	int len, iflags = 0;	struct file_list *flist;	uchar fnamecmp_type = FNAMECMP_FNAME;	int ndx, save_verbose = verbose;  read_loop:	while (1) {		ndx = read_ndx(f_in);		if (ndx >= 0)			break;		if (ndx == NDX_DONE)			return ndx;		if (!inc_recurse || am_sender) {			int last;			if (first_flist)				last = first_flist->prev->ndx_start + first_flist->prev->used - 1;			else				last = -1;			rprintf(FERROR,				"Invalid file index: %d (%d - %d) [%s]\n",				ndx, NDX_DONE, last, who_am_i());			exit_cleanup(RERR_PROTOCOL);		}		if (ndx == NDX_FLIST_EOF) {			flist_eof = 1;			send_msg(MSG_FLIST_EOF, "", 0, 0);			continue;		}		ndx = NDX_FLIST_OFFSET - ndx;		if (ndx < 0 || ndx >= dir_flist->used) {			ndx = NDX_FLIST_OFFSET - ndx;			rprintf(FERROR,				"Invalid dir index: %d (%d - %d) [%s]\n",				ndx, NDX_FLIST_OFFSET,				NDX_FLIST_OFFSET - dir_flist->used + 1,				who_am_i());			exit_cleanup(RERR_PROTOCOL);		}		/* Send everything read from f_in to msg_fd_out. */		if (verbose > 3) {			rprintf(FINFO, "[%s] receiving flist for dir %d\n",				who_am_i(), ndx);		}		verbose = 0;		send_msg_int(MSG_FLIST, ndx);		start_flist_forward(f_in);		flist = recv_file_list(f_in);		flist->parent_ndx = ndx;		stop_flist_forward();		verbose = save_verbose;	}	iflags = protocol_version >= 29 ? read_shortint(f_in)		   : ITEM_TRANSFER | ITEM_MISSING_DATA;	/* Honor the old-style keep-alive indicator. */	if (protocol_version < 30	 && ndx == cur_flist->used && iflags == ITEM_IS_NEW) {		if (am_sender)			maybe_send_keepalive();		goto read_loop;	}	cur_flist = flist_for_ndx(ndx, "read_ndx_and_attrs");	if (iflags & ITEM_BASIS_TYPE_FOLLOWS)		fnamecmp_type = read_byte(f_in);	*type_ptr = fnamecmp_type;	if (iflags & ITEM_XNAME_FOLLOWS) {		if ((len = read_vstring(f_in, buf, MAXPATHLEN)) < 0)			exit_cleanup(RERR_PROTOCOL);	} else {		*buf = '\0';		len = -1;	}	*len_ptr = len;

⌨️ 快捷键说明

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