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

📄 generator.c

📁 Rsync 3.0.5 source code
💻 C
📖 第 1 页 / 共 5 页
字号:
		fd_w = -1;		copy_to = dest;	} else {		fd_w = open_tmpfile(buf, dest, file);		if (fd_w < 0)			return -1;		copy_to = buf;	}	cleanup_set(copy_to, NULL, NULL, -1, -1);	if (copy_file(src, copy_to, fd_w, file->mode, 0) < 0) {		if (verbose) {			rsyserr(FINFO, errno, "copy_file %s => %s",				full_fname(src), copy_to);		}		/* Try to clean up. */		unlink(copy_to);		cleanup_disable();		return -1;	}	partialptr = partial_dir ? partial_dir_fname(dest) : NULL;	preserve_xattrs = 0; /* xattrs were copied with file */	ok = finish_transfer(dest, copy_to, src, partialptr, file, 1, 0);	preserve_xattrs = save_preserve_xattrs;	cleanup_disable();	return ok ? 0 : -1;}/* This is only called for regular files.  We return -2 if we've finished * handling the file, -1 if no dest-linking occurred, or a non-negative * value if we found an alternate basis file. */static int try_dests_reg(struct file_struct *file, char *fname, int ndx,			 char *cmpbuf, stat_x *sxp, int itemizing,			 enum logcode code){	int best_match = -1;	int match_level = 0;	int j = 0;	do {		pathjoin(cmpbuf, MAXPATHLEN, basis_dir[j], fname);		if (link_stat(cmpbuf, &sxp->st, 0) < 0 || !S_ISREG(sxp->st.st_mode))			continue;		switch (match_level) {		case 0:			best_match = j;			match_level = 1;			/* FALL THROUGH */		case 1:			if (!unchanged_file(cmpbuf, file, &sxp->st))				continue;			best_match = j;			match_level = 2;			/* FALL THROUGH */		case 2:			if (!unchanged_attrs(cmpbuf, file, sxp))				continue;			best_match = j;			match_level = 3;			break;		}		break;	} while (basis_dir[++j] != NULL);	if (!match_level)		return -1;	if (j != best_match) {		j = best_match;		pathjoin(cmpbuf, MAXPATHLEN, basis_dir[j], fname);		if (link_stat(cmpbuf, &sxp->st, 0) < 0)			return -1;	}	if (match_level == 3 && !copy_dest) {#ifdef SUPPORT_HARD_LINKS		if (link_dest) {			if (!hard_link_one(file, fname, cmpbuf, 1))				goto try_a_copy;			if (preserve_hard_links && F_IS_HLINKED(file))				finish_hard_link(file, fname, ndx, &sxp->st, itemizing, code, j);			if (!maybe_ATTRS_REPORT && (verbose > 1 || stdout_format_has_i > 1)) {				itemize(cmpbuf, file, ndx, 1, sxp,					ITEM_LOCAL_CHANGE | ITEM_XNAME_FOLLOWS,					0, "");			}		} else#endif		if (itemizing)			itemize(cmpbuf, file, ndx, 0, sxp, 0, 0, NULL);		if (verbose > 1 && maybe_ATTRS_REPORT)			rprintf(FCLIENT, "%s is uptodate\n", fname);		return -2;	}	if (match_level >= 2) {#ifdef SUPPORT_HARD_LINKS	  try_a_copy: /* Copy the file locally. */#endif		if (!dry_run && copy_altdest_file(cmpbuf, fname, file) < 0)			return -1;		if (itemizing)			itemize(cmpbuf, file, ndx, 0, sxp, ITEM_LOCAL_CHANGE, 0, NULL);		if (maybe_ATTRS_REPORT		 && ((!itemizing && verbose && match_level == 2)		  || (verbose > 1 && match_level == 3))) {			code = match_level == 3 ? FCLIENT : FINFO;			rprintf(code, "%s%s\n", fname,				match_level == 3 ? " is uptodate" : "");		}#ifdef SUPPORT_HARD_LINKS		if (preserve_hard_links && F_IS_HLINKED(file))			finish_hard_link(file, fname, ndx, &sxp->st, itemizing, code, -1);#endif		return -2;	}	return FNAMECMP_BASIS_DIR_LOW + j;}/* This is only called for non-regular files.  We return -2 if we've finished * handling the file, or -1 if no dest-linking occurred, or a non-negative * value if we found an alternate basis file. */static int try_dests_non(struct file_struct *file, char *fname, int ndx,			 char *cmpbuf, stat_x *sxp, int itemizing,			 enum logcode code){	char lnk[MAXPATHLEN];	int best_match = -1;	int match_level = 0;	enum nonregtype type;	uint32 *devp;	int len, j = 0;#ifndef SUPPORT_LINKS	if (S_ISLNK(file->mode))		return -1;#endif	if (S_ISDIR(file->mode)) {		type = TYPE_DIR;	} else if (IS_SPECIAL(file->mode))		type = TYPE_SPECIAL;	else if (IS_DEVICE(file->mode))		type = TYPE_DEVICE;#ifdef SUPPORT_LINKS	else if (S_ISLNK(file->mode))		type = TYPE_SYMLINK;#endif	else {		rprintf(FERROR,			"internal: try_dests_non() called with invalid mode (%o)\n",			(int)file->mode);		exit_cleanup(RERR_UNSUPPORTED);	}	do {		pathjoin(cmpbuf, MAXPATHLEN, basis_dir[j], fname);		if (link_stat(cmpbuf, &sxp->st, 0) < 0)			continue;		switch (type) {		case TYPE_DIR:			if (!S_ISDIR(sxp->st.st_mode))				continue;			break;		case TYPE_SPECIAL:			if (!IS_SPECIAL(sxp->st.st_mode))				continue;			break;		case TYPE_DEVICE:			if (!IS_DEVICE(sxp->st.st_mode))				continue;			break;#ifdef SUPPORT_LINKS		case TYPE_SYMLINK:			if (!S_ISLNK(sxp->st.st_mode))				continue;			break;#endif		}		if (match_level < 1) {			match_level = 1;			best_match = j;		}		switch (type) {		case TYPE_DIR:			break;		case TYPE_SPECIAL:		case TYPE_DEVICE:			devp = F_RDEV_P(file);			if (sxp->st.st_rdev != MAKEDEV(DEV_MAJOR(devp), DEV_MINOR(devp)))				continue;			break;#ifdef SUPPORT_LINKS		case TYPE_SYMLINK:			if ((len = readlink(cmpbuf, lnk, MAXPATHLEN-1)) <= 0)				continue;			lnk[len] = '\0';			if (strcmp(lnk, F_SYMLINK(file)) != 0)				continue;			break;#endif		}		if (match_level < 2) {			match_level = 2;			best_match = j;		}		if (unchanged_attrs(cmpbuf, file, sxp)) {			match_level = 3;			best_match = j;			break;		}	} while (basis_dir[++j] != NULL);	if (!match_level)		return -1;	if (j != best_match) {		j = best_match;		pathjoin(cmpbuf, MAXPATHLEN, basis_dir[j], fname);		if (link_stat(cmpbuf, &sxp->st, 0) < 0)			return -1;	}	if (match_level == 3) {#ifdef SUPPORT_HARD_LINKS		if (link_dest#ifndef CAN_HARDLINK_SYMLINK		 && !S_ISLNK(file->mode)#endif#ifndef CAN_HARDLINK_SPECIAL		 && !IS_SPECIAL(file->mode) && !IS_DEVICE(file->mode)#endif		 && !S_ISDIR(file->mode)) {			if (do_link(cmpbuf, fname) < 0) {				rsyserr(FERROR_XFER, errno,					"failed to hard-link %s with %s",					cmpbuf, fname);				return j;			}			if (preserve_hard_links && F_IS_HLINKED(file))				finish_hard_link(file, fname, ndx, NULL, itemizing, code, -1);		} else#endif			match_level = 2;		if (itemizing && stdout_format_has_i		 && (verbose > 1 || stdout_format_has_i > 1)) {			int chg = compare_dest && type != TYPE_DIR ? 0			    : ITEM_LOCAL_CHANGE + (match_level == 3 ? ITEM_XNAME_FOLLOWS : 0);			char *lp = match_level == 3 ? "" : NULL;			itemize(cmpbuf, file, ndx, 0, sxp, chg + ITEM_MATCHED, 0, lp);		}		if (verbose > 1 && maybe_ATTRS_REPORT) {			rprintf(FCLIENT, "%s%s is uptodate\n",				fname, type == TYPE_DIR ? "/" : "");		}		return -2;	}	return j;}static void list_file_entry(struct file_struct *f){	char permbuf[PERMSTRING_SIZE];	double len;	if (!F_IS_ACTIVE(f)) {		/* this can happen if duplicate names were removed */		return;	}	permstring(permbuf, f->mode);	len = F_LENGTH(f);	/* TODO: indicate '+' if the entry has an ACL. */#ifdef SUPPORT_LINKS	if (preserve_links && S_ISLNK(f->mode)) {		rprintf(FINFO, "%s %11.0f %s %s -> %s\n",			permbuf, len, timestring(f->modtime),			f_name(f, NULL), F_SYMLINK(f));	} else#endif	{		rprintf(FINFO, "%s %11.0f %s %s\n",			permbuf, len, timestring(f->modtime),			f_name(f, NULL));	}}static int phase = 0;static int dflt_perms;static int implied_dirs_are_missing;/* Helper for recv_generator's skip_dir and dry_missing_dir tests. */static BOOL is_below(struct file_struct *file, struct file_struct *subtree){	return F_DEPTH(file) > F_DEPTH(subtree)		&& (!implied_dirs_are_missing || f_name_has_prefix(file, subtree));}/* Acts on the indicated item in cur_flist whose name is fname.  If a dir, * make sure it exists, and has the right permissions/timestamp info.  For * all other non-regular files (symlinks, etc.) we create them here.  For * regular files that have changed, we try to find a basis file and then * start sending checksums.  The ndx is the file's unique index value. * * The fname parameter must point to a MAXPATHLEN buffer!  (e.g it gets * passed to delete_item(), which can use it during a recursive delete.) * * Note that f_out is set to -1 when doing final directory-permission and * modification-time repair. */static void recv_generator(char *fname, struct file_struct *file, int ndx,			   int itemizing, enum logcode code, int f_out){	static const char *parent_dirname = "";	/* Missing dir not created due to --dry-run; will still be scanned. */	static struct file_struct *dry_missing_dir = NULL;	/* Missing dir whose contents are skipped altogether due to	 * --ignore-non-existing, daemon exclude, or mkdir failure. */	static struct file_struct *skip_dir = NULL;	static struct file_list *fuzzy_dirlist = NULL;	static int need_fuzzy_dirlist = 0;	struct file_struct *fuzzy_file = NULL;	int fd = -1, f_copy = -1;	stat_x sx, real_sx;	STRUCT_STAT partial_st;	struct file_struct *back_file = NULL;	int statret, real_ret, stat_errno;	char *fnamecmp, *partialptr, *backupptr = NULL;	char fnamecmpbuf[MAXPATHLEN];	uchar fnamecmp_type;	int del_opts = delete_mode || force_delete ? DEL_RECURSE : 0;	int is_dir = !S_ISDIR(file->mode) ? 0		   : inc_recurse && ndx != cur_flist->ndx_start - 1 ? -1		   : 1;	if (verbose > 2)		rprintf(FINFO, "recv_generator(%s,%d)\n", fname, ndx);	if (list_only) {		if (is_dir < 0		 || (is_dir && !implied_dirs && file->flags & FLAG_IMPLIED_DIR))			return;		list_file_entry(file);		return;	}	if (skip_dir) {		if (is_below(file, skip_dir)) {			if (is_dir)				file->flags |= FLAG_MISSING_DIR;#ifdef SUPPORT_HARD_LINKS			else if (F_IS_HLINKED(file))				handle_skipped_hlink(file, itemizing, code, f_out);#endif			return;		}		skip_dir = NULL;	}	if (daemon_filter_list.head && (*fname != '.' || fname[1])) {		if (check_filter(&daemon_filter_list, FLOG, fname, is_dir) < 0) {			if (is_dir < 0)				return;#ifdef SUPPORT_HARD_LINKS			if (F_IS_HLINKED(file))				handle_skipped_hlink(file, itemizing, code, f_out);#endif			rprintf(FERROR_XFER,				"skipping daemon-excluded %s \"%s\"\n",				is_dir ? "directory" : "file", fname);			if (is_dir)				goto skipping_dir_contents;			return;		}	}#ifdef SUPPORT_ACLS	sx.acc_acl = sx.def_acl = NULL;#endif#ifdef SUPPORT_XATTRS	sx.xattr = NULL;#endif	if (dry_run > 1 || (dry_missing_dir && is_below(file, dry_missing_dir))) {	  parent_is_dry_missing:		if (fuzzy_dirlist) {			flist_free(fuzzy_dirlist);			fuzzy_dirlist = NULL;		}		parent_dirname = "";		statret = -1;		stat_errno = ENOENT;	} else {		const char *dn = file->dirname ? file->dirname : ".";		dry_missing_dir = NULL;		if (parent_dirname != dn && strcmp(parent_dirname, dn) != 0) {			if (relative_paths && !implied_dirs			 && do_stat(dn, &sx.st) < 0) {				if (dry_run)					goto parent_is_dry_missing;				if (create_directory_path(fname) < 0) {					rsyserr(FERROR_XFER, errno,						"recv_generator: mkdir %s failed",						full_fname(dn));				}			}			if (fuzzy_dirlist) {				flist_free(fuzzy_dirlist);				fuzzy_dirlist = NULL;			}			if (fuzzy_basis)				need_fuzzy_dirlist = 1;#ifdef SUPPORT_ACLS			if (!preserve_perms)				dflt_perms = default_perms_for_dir(dn);#endif		}		parent_dirname = dn;		if (need_fuzzy_dirlist && S_ISREG(file->mode)) {			strlcpy(fnamecmpbuf, dn, sizeof fnamecmpbuf);			fuzzy_dirlist = get_dirlist(fnamecmpbuf, -1, 1);			need_fuzzy_dirlist = 0;		}		statret = link_stat(fname, &sx.st, keep_dirlinks && is_dir);		stat_errno = errno;	}	if (ignore_non_existing > 0 && statret == -1 && stat_errno == ENOENT) {		if (is_dir) {			if (is_dir < 0)				return;			skip_dir = file;			file->flags |= FLAG_MISSING_DIR;		}#ifdef SUPPORT_HARD_LINKS		else if (F_IS_HLINKED(file))			handle_skipped_hlink(file, itemizing, code, f_out);#endif		if (verbose > 1) {			rprintf(FINFO, "not creating new %s \"%s\"\n",				is_dir ? "directory" : "file", fname);		}		return;	}	if (statret == 0 && !(sx.st.st_mode & S_IWUSR)	 && !am_root && sx.st.st_uid == our_uid)		del_opts |= DEL_NO_UID_WRITE;	if (ignore_existing > 0 && statret == 0	 && (!is_dir || !S_ISDIR(sx.st.st_mode))) {		if (verbose > 1 && is_dir >= 0)			rprintf(FINFO, "%s exists\n", fname);#ifdef SUPPORT_HARD_LINKS		if (F_IS_HLINKED(file))			handle_skipped_hlink(file, itemizing, code, f_out);#endif		goto cleanup;	}	if (is_dir) {		if (!implied_dirs && file->flags & FLAG_IMPLIED_DIR)			goto cleanup;		if (is_dir < 0) {			/* In inc_recurse mode we want to make sure any missing			 * directories get created while we're still processing			 * the parent dir (which allows us to touch the parent			 * dir's mtime right away).  We will handle the dir in			 * full later (right before we handle its contents). */

⌨️ 快捷键说明

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