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

📄 receiver.c

📁 Rsync 3.0.5 source code
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Routines only used by the receiving process. * * Copyright (C) 1996-2000 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"extern int verbose;extern int dry_run;extern int do_xfers;extern int am_server;extern int do_progress;extern int inc_recurse;extern int log_before_transfer;extern int stdout_format_has_i;extern int logfile_format_has_i;extern int csum_length;extern int read_batch;extern int write_batch;extern int batch_gen_fd;extern int protocol_version;extern int relative_paths;extern int preserve_hard_links;extern int preserve_perms;extern int preserve_xattrs;extern int basis_dir_cnt;extern int make_backups;extern int cleanup_got_literal;extern int remove_source_files;extern int append_mode;extern int sparse_files;extern int keep_partial;extern int checksum_seed;extern int inplace;extern int delay_updates;extern mode_t orig_umask;extern struct stats stats;extern char *tmpdir;extern char *partial_dir;extern char *basis_dir[];extern struct file_list *cur_flist, *first_flist, *dir_flist;extern struct filter_list_struct daemon_filter_list;static struct bitbag *delayed_bits = NULL;static int phase = 0, redoing = 0;static flist_ndx_list batch_redo_list;/* We're either updating the basis file or an identical copy: */static int updating_basis_or_equiv;/* * get_tmpname() - create a tmp filename for a given filename * *   If a tmpdir is defined, use that as the directory to *   put it in.  Otherwise, the tmp filename is in the same *   directory as the given name.  Note that there may be no *   directory at all in the given name! * *   The tmp filename is basically the given filename with a *   dot prepended, and .XXXXXX appended (for mkstemp() to *   put its unique gunk in).  Take care to not exceed *   either the MAXPATHLEN or NAME_MAX, esp. the last, as *   the basename basically becomes 8 chars longer. In that *   case, the original name is shortened sufficiently to *   make it all fit. * *   Of course, there's no real reason for the tmp name to *   look like the original, except to satisfy us humans. *   As long as it's unique, rsync will work. */int get_tmpname(char *fnametmp, const char *fname){	int maxname, added, length = 0;	const char *f;	if (tmpdir) {		/* Note: this can't overflow, so the return value is safe */		length = strlcpy(fnametmp, tmpdir, MAXPATHLEN - 2);		fnametmp[length++] = '/';	}	if ((f = strrchr(fname, '/')) != NULL) {		++f;		if (!tmpdir) {			length = f - fname;			/* copy up to and including the slash */			strlcpy(fnametmp, fname, length + 1);		}	} else		f = fname;	fnametmp[length++] = '.';	/* The maxname value is bufsize, and includes space for the '\0'.	 * (Note that NAME_MAX get -8 for the leading '.' above.) */	maxname = MIN(MAXPATHLEN - 7 - length, NAME_MAX - 8);	if (maxname < 1) {		rprintf(FERROR_XFER, "temporary filename too long: %s\n", fname);		fnametmp[0] = '\0';		return 0;	}	added = strlcpy(fnametmp + length, f, maxname);	if (added >= maxname)		added = maxname - 1;	memcpy(fnametmp + length + added, ".XXXXXX", 8);	return 1;}/* Opens a temporary file for writing. * Success: Writes name into fnametmp, returns fd. * Failure: Clobbers fnametmp, returns -1. * Calling cleanup_set() is the caller's job. */int open_tmpfile(char *fnametmp, const char *fname, struct file_struct *file){	int fd;	if (!get_tmpname(fnametmp, fname))		return -1;	/* We initially set the perms without the setuid/setgid bits or group	 * access to ensure that there is no race condition.  They will be	 * correctly updated after the right owner and group info is set.	 * (Thanks to snabb@epipe.fi for pointing this out.) */	fd = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS);#if 0	/* In most cases parent directories will already exist because their	 * information should have been previously transferred, but that may	 * not be the case with -R */	if (fd == -1 && relative_paths && errno == ENOENT	    && create_directory_path(fnametmp) == 0) {		/* Get back to name with XXXXXX in it. */		get_tmpname(fnametmp, fname);		fd = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS);	}#endif	if (fd == -1) {		rsyserr(FERROR_XFER, errno, "mkstemp %s failed",			full_fname(fnametmp));		return -1;	}	return fd;}static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,			const char *fname, int fd, OFF_T total_size){	static char file_sum1[MAX_DIGEST_LEN];	static char file_sum2[MAX_DIGEST_LEN];	struct map_struct *mapbuf;	struct sum_struct sum;	int32 len, sum_len;	OFF_T offset = 0;	OFF_T offset2;	char *data;	int32 i;	char *map = NULL;	read_sum_head(f_in, &sum);	if (fd_r >= 0 && size_r > 0) {		int32 read_size = MAX(sum.blength * 2, 16*1024);		mapbuf = map_file(fd_r, size_r, read_size, sum.blength);		if (verbose > 2) {			rprintf(FINFO, "recv mapped %s of size %.0f\n",				fname_r, (double)size_r);		}	} else		mapbuf = NULL;	sum_init(checksum_seed);	if (append_mode > 0) {		OFF_T j;		sum.flength = (OFF_T)sum.count * sum.blength;		if (sum.remainder)			sum.flength -= sum.blength - sum.remainder;		if (append_mode == 2) {			for (j = CHUNK_SIZE; j < sum.flength; j += CHUNK_SIZE) {				if (do_progress)					show_progress(offset, total_size);				sum_update(map_ptr(mapbuf, offset, CHUNK_SIZE),					   CHUNK_SIZE);				offset = j;			}			if (offset < sum.flength) {				int32 len = (int32)(sum.flength - offset);				if (do_progress)					show_progress(offset, total_size);				sum_update(map_ptr(mapbuf, offset, len), len);			}		}		offset = sum.flength;		if (fd != -1 && (j = do_lseek(fd, offset, SEEK_SET)) != offset) {			rsyserr(FERROR_XFER, errno, "lseek of %s returned %.0f, not %.0f",				full_fname(fname), (double)j, (double)offset);			exit_cleanup(RERR_FILEIO);		}	}	while ((i = recv_token(f_in, &data)) != 0) {		if (do_progress)			show_progress(offset, total_size);		if (i > 0) {			if (verbose > 3) {				rprintf(FINFO,"data recv %d at %.0f\n",					i,(double)offset);			}			stats.literal_data += i;			cleanup_got_literal = 1;			sum_update(data, i);			if (fd != -1 && write_file(fd,data,i) != i)				goto report_write_error;			offset += i;			continue;		}		i = -(i+1);		offset2 = i * (OFF_T)sum.blength;		len = sum.blength;		if (i == (int)sum.count-1 && sum.remainder != 0)			len = sum.remainder;		stats.matched_data += len;		if (verbose > 3) {			rprintf(FINFO,				"chunk[%d] of size %ld at %.0f offset=%.0f\n",				i, (long)len, (double)offset2, (double)offset);		}		if (mapbuf) {			map = map_ptr(mapbuf,offset2,len);			see_token(map, len);			sum_update(map, len);		}		if (updating_basis_or_equiv) {			if (offset == offset2 && fd != -1) {				OFF_T pos;				if (flush_write_file(fd) < 0)					goto report_write_error;				offset += len;				if ((pos = do_lseek(fd, len, SEEK_CUR)) != offset) {					rsyserr(FERROR_XFER, errno,						"lseek of %s returned %.0f, not %.0f",						full_fname(fname),						(double)pos, (double)offset);					exit_cleanup(RERR_FILEIO);				}				continue;			}		}		if (fd != -1 && map && write_file(fd, map, len) != (int)len)			goto report_write_error;		offset += len;	}	if (flush_write_file(fd) < 0)		goto report_write_error;#ifdef HAVE_FTRUNCATE	if (inplace && fd != -1	 && ftruncate(fd, offset) < 0) {		rsyserr(FERROR_XFER, errno, "ftruncate failed on %s",			full_fname(fname));	}#endif	if (do_progress)		end_progress(total_size);	if (fd != -1 && offset > 0 && sparse_end(fd) != 0) {	    report_write_error:		rsyserr(FERROR_XFER, errno, "write failed on %s",			full_fname(fname));		exit_cleanup(RERR_FILEIO);	}	sum_len = sum_end(file_sum1);	if (mapbuf)		unmap_file(mapbuf);	read_buf(f_in, file_sum2, sum_len);	if (verbose > 2)		rprintf(FINFO,"got file_sum\n");	if (fd != -1 && memcmp(file_sum1, file_sum2, sum_len) != 0)		return 0;	return 1;}static void discard_receive_data(int f_in, OFF_T length){	receive_data(f_in, NULL, -1, 0, NULL, -1, length);}static void handle_delayed_updates(char *local_name){	char *fname, *partialptr;	int ndx;	for (ndx = -1; (ndx = bitbag_next_bit(delayed_bits, ndx)) >= 0; ) {		struct file_struct *file = cur_flist->files[ndx];		fname = local_name ? local_name : f_name(file, NULL);		if ((partialptr = partial_dir_fname(fname)) != NULL) {			if (make_backups > 0 && !make_backup(fname))				continue;			if (verbose > 2) {				rprintf(FINFO, "renaming %s to %s\n",					partialptr, fname);			}			/* We don't use robust_rename() here because the			 * partial-dir must be on the same drive. */			if (do_rename(partialptr, fname) < 0) {				rsyserr(FERROR_XFER, errno,					"rename failed for %s (from %s)",					full_fname(fname), partialptr);			} else {				if (remove_source_files				 || (preserve_hard_links && F_IS_HLINKED(file)))					send_msg_int(MSG_SUCCESS, ndx);				handle_partial_dir(partialptr, PDIR_DELETE);			}		}	}}static void no_batched_update(int ndx, BOOL is_redo){	struct file_list *flist = flist_for_ndx(ndx, "no_batched_update");	struct file_struct *file = flist->files[ndx - flist->ndx_start];	rprintf(FERROR_XFER, "(No batched update for%s \"%s\")\n",		is_redo ? " resend of" : "", f_name(file, NULL));	if (inc_recurse)		send_msg_int(MSG_NO_SEND, ndx);}static int we_want_redo(int desired_ndx){	static int redo_ndx = -1;	while (redo_ndx < desired_ndx) {		if (redo_ndx >= 0)			no_batched_update(redo_ndx, True);		if ((redo_ndx = flist_ndx_pop(&batch_redo_list)) < 0)			return 0;	}	if (redo_ndx == desired_ndx) {		redo_ndx = -1;		return 1;	}	return 0;}static int gen_wants_ndx(int desired_ndx){	static int next_ndx = -1;	static BOOL got_eof = 0;	if (got_eof)		return 0;	while (next_ndx < desired_ndx) {		if (next_ndx >= 0)			no_batched_update(next_ndx, False);		if ((next_ndx = read_int(batch_gen_fd)) < 0) {			got_eof = True;			return 0;		}	}	if (next_ndx == desired_ndx) {		next_ndx = -1;		return 1;	}

⌨️ 快捷键说明

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