File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / rsync / sender.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Nov 1 09:54:32 2016 UTC (7 years, 7 months ago) by misho
Branches: rsync, MAIN
CVS tags: v3_1_2p5, HEAD
rsync 3.1.2

    1: /*
    2:  * Routines only used by the sending process.
    3:  *
    4:  * Copyright (C) 1996 Andrew Tridgell
    5:  * Copyright (C) 1996 Paul Mackerras
    6:  * Copyright (C) 2003-2015 Wayne Davison
    7:  *
    8:  * This program is free software; you can redistribute it and/or modify
    9:  * it under the terms of the GNU General Public License as published by
   10:  * the Free Software Foundation; either version 3 of the License, or
   11:  * (at your option) any later version.
   12:  *
   13:  * This program is distributed in the hope that it will be useful,
   14:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   15:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   16:  * GNU General Public License for more details.
   17:  *
   18:  * You should have received a copy of the GNU General Public License along
   19:  * with this program; if not, visit the http://fsf.org website.
   20:  */
   21: 
   22: #include "rsync.h"
   23: #include "inums.h"
   24: 
   25: extern int do_xfers;
   26: extern int am_server;
   27: extern int am_daemon;
   28: extern int inc_recurse;
   29: extern int log_before_transfer;
   30: extern int stdout_format_has_i;
   31: extern int logfile_format_has_i;
   32: extern int want_xattr_optim;
   33: extern int csum_length;
   34: extern int append_mode;
   35: extern int io_error;
   36: extern int flist_eof;
   37: extern int allowed_lull;
   38: extern int preserve_xattrs;
   39: extern int protocol_version;
   40: extern int remove_source_files;
   41: extern int updating_basis_file;
   42: extern int make_backups;
   43: extern int inplace;
   44: extern int batch_fd;
   45: extern int write_batch;
   46: extern int file_old_total;
   47: extern struct stats stats;
   48: extern struct file_list *cur_flist, *first_flist, *dir_flist;
   49: 
   50: BOOL extra_flist_sending_enabled;
   51: 
   52: /**
   53:  * @file
   54:  *
   55:  * The sender gets checksums from the generator, calculates deltas,
   56:  * and transmits them to the receiver.  The sender process runs on the
   57:  * machine holding the source files.
   58:  **/
   59: 
   60: /**
   61:  * Receive the checksums for a buffer
   62:  **/
   63: static struct sum_struct *receive_sums(int f)
   64: {
   65: 	struct sum_struct *s;
   66: 	int32 i;
   67: 	int lull_mod = protocol_version >= 31 ? 0 : allowed_lull * 5;
   68: 	OFF_T offset = 0;
   69: 
   70: 	if (!(s = new(struct sum_struct)))
   71: 		out_of_memory("receive_sums");
   72: 
   73: 	read_sum_head(f, s);
   74: 
   75: 	s->sums = NULL;
   76: 
   77: 	if (DEBUG_GTE(DELTASUM, 3)) {
   78: 		rprintf(FINFO, "count=%s n=%ld rem=%ld\n",
   79: 			big_num(s->count), (long)s->blength, (long)s->remainder);
   80: 	}
   81: 
   82: 	if (append_mode > 0) {
   83: 		s->flength = (OFF_T)s->count * s->blength;
   84: 		if (s->remainder)
   85: 			s->flength -= s->blength - s->remainder;
   86: 		return s;
   87: 	}
   88: 
   89: 	if (s->count == 0)
   90: 		return(s);
   91: 
   92: 	if (!(s->sums = new_array(struct sum_buf, s->count)))
   93: 		out_of_memory("receive_sums");
   94: 
   95: 	for (i = 0; i < s->count; i++) {
   96: 		s->sums[i].sum1 = read_int(f);
   97: 		read_buf(f, s->sums[i].sum2, s->s2length);
   98: 
   99: 		s->sums[i].offset = offset;
  100: 		s->sums[i].flags = 0;
  101: 
  102: 		if (i == s->count-1 && s->remainder != 0)
  103: 			s->sums[i].len = s->remainder;
  104: 		else
  105: 			s->sums[i].len = s->blength;
  106: 		offset += s->sums[i].len;
  107: 
  108: 		if (lull_mod && !(i % lull_mod))
  109: 			maybe_send_keepalive(time(NULL), True);
  110: 
  111: 		if (DEBUG_GTE(DELTASUM, 3)) {
  112: 			rprintf(FINFO,
  113: 				"chunk[%d] len=%d offset=%s sum1=%08x\n",
  114: 				i, s->sums[i].len, big_num(s->sums[i].offset),
  115: 				s->sums[i].sum1);
  116: 		}
  117: 	}
  118: 
  119: 	s->flength = offset;
  120: 
  121: 	return s;
  122: }
  123: 
  124: void successful_send(int ndx)
  125: {
  126: 	char fname[MAXPATHLEN];
  127: 	char *failed_op;
  128: 	struct file_struct *file;
  129: 	struct file_list *flist;
  130: 	STRUCT_STAT st;
  131: 
  132: 	if (!remove_source_files)
  133: 		return;
  134: 
  135: 	flist = flist_for_ndx(ndx, "successful_send");
  136: 	file = flist->files[ndx - flist->ndx_start];
  137: 	if (!change_pathname(file, NULL, 0))
  138: 		return;
  139: 	f_name(file, fname);
  140: 
  141: 	if (do_lstat(fname, &st) < 0) {
  142: 		failed_op = "re-lstat";
  143: 		goto failed;
  144: 	}
  145: 
  146: 	if (S_ISREG(file->mode) /* Symlinks & devices don't need this check: */
  147: 	 && (st.st_size != F_LENGTH(file) || st.st_mtime != file->modtime
  148: #ifdef ST_MTIME_NSEC
  149: 	 || (NSEC_BUMP(file) && (uint32)st.ST_MTIME_NSEC != F_MOD_NSEC(file))
  150: #endif
  151: 	)) {
  152: 		rprintf(FERROR_XFER, "ERROR: Skipping sender remove for changed file: %s\n", fname);
  153: 		return;
  154: 	}
  155: 
  156: 	if (do_unlink(fname) < 0) {
  157: 		failed_op = "remove";
  158: 	  failed:
  159: 		if (errno == ENOENT)
  160: 			rprintf(FINFO, "sender file already removed: %s\n", fname);
  161: 		else
  162: 			rsyserr(FERROR_XFER, errno, "sender failed to %s %s", failed_op, fname);
  163: 	} else {
  164: 		if (INFO_GTE(REMOVE, 1))
  165: 			rprintf(FINFO, "sender removed %s\n", fname);
  166: 	}
  167: }
  168: 
  169: static void write_ndx_and_attrs(int f_out, int ndx, int iflags,
  170: 				const char *fname, struct file_struct *file,
  171: 				uchar fnamecmp_type, char *buf, int len)
  172: {
  173: 	write_ndx(f_out, ndx);
  174: 	if (protocol_version < 29)
  175: 		return;
  176: 	write_shortint(f_out, iflags);
  177: 	if (iflags & ITEM_BASIS_TYPE_FOLLOWS)
  178: 		write_byte(f_out, fnamecmp_type);
  179: 	if (iflags & ITEM_XNAME_FOLLOWS)
  180: 		write_vstring(f_out, buf, len);
  181: #ifdef SUPPORT_XATTRS
  182: 	if (preserve_xattrs && iflags & ITEM_REPORT_XATTR && do_xfers
  183: 	 && !(want_xattr_optim && BITS_SET(iflags, ITEM_XNAME_FOLLOWS|ITEM_LOCAL_CHANGE)))
  184: 		send_xattr_request(fname, file, f_out);
  185: #endif
  186: }
  187: 
  188: void send_files(int f_in, int f_out)
  189: {
  190: 	int fd = -1;
  191: 	struct sum_struct *s;
  192: 	struct map_struct *mbuf = NULL;
  193: 	STRUCT_STAT st;
  194: 	char fname[MAXPATHLEN], xname[MAXPATHLEN];
  195: 	const char *path, *slash;
  196: 	uchar fnamecmp_type;
  197: 	int iflags, xlen;
  198: 	struct file_struct *file;
  199: 	int phase = 0, max_phase = protocol_version >= 29 ? 2 : 1;
  200: 	int itemizing = am_server ? logfile_format_has_i : stdout_format_has_i;
  201: 	enum logcode log_code = log_before_transfer ? FLOG : FINFO;
  202: 	int f_xfer = write_batch < 0 ? batch_fd : f_out;
  203: 	int save_io_error = io_error;
  204: 	int ndx, j;
  205: 
  206: 	if (DEBUG_GTE(SEND, 1))
  207: 		rprintf(FINFO, "send_files starting\n");
  208: 
  209: 	while (1) {
  210: 		if (inc_recurse) {
  211: 			send_extra_file_list(f_out, MIN_FILECNT_LOOKAHEAD);
  212: 			extra_flist_sending_enabled = !flist_eof;
  213: 		}
  214: 
  215: 		/* This call also sets cur_flist. */
  216: 		ndx = read_ndx_and_attrs(f_in, f_out, &iflags, &fnamecmp_type,
  217: 					 xname, &xlen);
  218: 		extra_flist_sending_enabled = False;
  219: 
  220: 		if (ndx == NDX_DONE) {
  221: 			if (!am_server && INFO_GTE(PROGRESS, 2) && cur_flist) {
  222: 				set_current_file_index(NULL, 0);
  223: 				end_progress(0);
  224: 			}
  225: 			if (inc_recurse && first_flist) {
  226: 				file_old_total -= first_flist->used;
  227: 				flist_free(first_flist);
  228: 				if (first_flist) {
  229: 					if (first_flist == cur_flist)
  230: 						file_old_total = cur_flist->used;
  231: 					write_ndx(f_out, NDX_DONE);
  232: 					continue;
  233: 				}
  234: 			}
  235: 			if (++phase > max_phase)
  236: 				break;
  237: 			if (DEBUG_GTE(SEND, 1))
  238: 				rprintf(FINFO, "send_files phase=%d\n", phase);
  239: 			write_ndx(f_out, NDX_DONE);
  240: 			continue;
  241: 		}
  242: 
  243: 		if (inc_recurse)
  244: 			send_extra_file_list(f_out, MIN_FILECNT_LOOKAHEAD);
  245: 
  246: 		if (ndx - cur_flist->ndx_start >= 0)
  247: 			file = cur_flist->files[ndx - cur_flist->ndx_start];
  248: 		else
  249: 			file = dir_flist->files[cur_flist->parent_ndx];
  250: 		if (F_PATHNAME(file)) {
  251: 			path = F_PATHNAME(file);
  252: 			slash = "/";
  253: 		} else {
  254: 			path = slash = "";
  255: 		}
  256: 		if (!change_pathname(file, NULL, 0))
  257: 			continue;
  258: 		f_name(file, fname);
  259: 
  260: 		if (DEBUG_GTE(SEND, 1))
  261: 			rprintf(FINFO, "send_files(%d, %s%s%s)\n", ndx, path,slash,fname);
  262: 
  263: #ifdef SUPPORT_XATTRS
  264: 		if (preserve_xattrs && iflags & ITEM_REPORT_XATTR && do_xfers
  265: 		 && !(want_xattr_optim && BITS_SET(iflags, ITEM_XNAME_FOLLOWS|ITEM_LOCAL_CHANGE)))
  266: 			recv_xattr_request(file, f_in);
  267: #endif
  268: 
  269: 		if (!(iflags & ITEM_TRANSFER)) {
  270: 			maybe_log_item(file, iflags, itemizing, xname);
  271: 			write_ndx_and_attrs(f_out, ndx, iflags, fname, file,
  272: 					    fnamecmp_type, xname, xlen);
  273: 			if (iflags & ITEM_IS_NEW) {
  274: 				stats.created_files++;
  275: 				if (S_ISREG(file->mode)) {
  276: 					/* Nothing further to count. */
  277: 				} else if (S_ISDIR(file->mode))
  278: 					stats.created_dirs++;
  279: #ifdef SUPPORT_LINKS
  280: 				else if (S_ISLNK(file->mode))
  281: 					stats.created_symlinks++;
  282: #endif
  283: 				else if (IS_DEVICE(file->mode))
  284: 					stats.created_devices++;
  285: 				else
  286: 					stats.created_specials++;
  287: 			}
  288: 			continue;
  289: 		}
  290: 		if (phase == 2) {
  291: 			rprintf(FERROR,
  292: 				"got transfer request in phase 2 [%s]\n",
  293: 				who_am_i());
  294: 			exit_cleanup(RERR_PROTOCOL);
  295: 		}
  296: 
  297: 		if (file->flags & FLAG_FILE_SENT) {
  298: 			if (csum_length == SHORT_SUM_LENGTH) {
  299: 				/* For inplace: redo phase turns off the backup
  300: 				 * flag so that we do a regular inplace send. */
  301: 				make_backups = -make_backups;
  302: 				append_mode = -append_mode;
  303: 				csum_length = SUM_LENGTH;
  304: 			}
  305: 		} else {
  306: 			if (csum_length != SHORT_SUM_LENGTH) {
  307: 				make_backups = -make_backups;
  308: 				append_mode = -append_mode;
  309: 				csum_length = SHORT_SUM_LENGTH;
  310: 			}
  311: 			if (iflags & ITEM_IS_NEW)
  312: 				stats.created_files++;
  313: 		}
  314: 
  315: 		updating_basis_file = inplace && (protocol_version >= 29
  316: 			? fnamecmp_type == FNAMECMP_FNAME : make_backups <= 0);
  317: 
  318: 		if (!am_server && INFO_GTE(PROGRESS, 1))
  319: 			set_current_file_index(file, ndx);
  320: 		stats.xferred_files++;
  321: 		stats.total_transferred_size += F_LENGTH(file);
  322: 
  323: 		remember_initial_stats();
  324: 
  325: 		if (!do_xfers) { /* log the transfer */
  326: 			log_item(FCLIENT, file, iflags, NULL);
  327: 			write_ndx_and_attrs(f_out, ndx, iflags, fname, file,
  328: 					    fnamecmp_type, xname, xlen);
  329: 			continue;
  330: 		}
  331: 
  332: 		if (!(s = receive_sums(f_in))) {
  333: 			io_error |= IOERR_GENERAL;
  334: 			rprintf(FERROR_XFER, "receive_sums failed\n");
  335: 			exit_cleanup(RERR_PROTOCOL);
  336: 		}
  337: 
  338: 		fd = do_open(fname, O_RDONLY, 0);
  339: 		if (fd == -1) {
  340: 			if (errno == ENOENT) {
  341: 				enum logcode c = am_daemon
  342: 				    && protocol_version < 28 ? FERROR
  343: 							     : FWARNING;
  344: 				io_error |= IOERR_VANISHED;
  345: 				rprintf(c, "file has vanished: %s\n",
  346: 					full_fname(fname));
  347: 			} else {
  348: 				io_error |= IOERR_GENERAL;
  349: 				rsyserr(FERROR_XFER, errno,
  350: 					"send_files failed to open %s",
  351: 					full_fname(fname));
  352: 			}
  353: 			free_sums(s);
  354: 			if (protocol_version >= 30)
  355: 				send_msg_int(MSG_NO_SEND, ndx);
  356: 			continue;
  357: 		}
  358: 
  359: 		/* map the local file */
  360: 		if (do_fstat(fd, &st) != 0) {
  361: 			io_error |= IOERR_GENERAL;
  362: 			rsyserr(FERROR_XFER, errno, "fstat failed");
  363: 			free_sums(s);
  364: 			close(fd);
  365: 			exit_cleanup(RERR_FILEIO);
  366: 		}
  367: 
  368: 		if (st.st_size) {
  369: 			int32 read_size = MAX(s->blength * 3, MAX_MAP_SIZE);
  370: 			mbuf = map_file(fd, st.st_size, read_size, s->blength);
  371: 		} else
  372: 			mbuf = NULL;
  373: 
  374: 		if (DEBUG_GTE(DELTASUM, 2)) {
  375: 			rprintf(FINFO, "send_files mapped %s%s%s of size %s\n",
  376: 				path,slash,fname, big_num(st.st_size));
  377: 		}
  378: 
  379: 		write_ndx_and_attrs(f_out, ndx, iflags, fname, file,
  380: 				    fnamecmp_type, xname, xlen);
  381: 		write_sum_head(f_xfer, s);
  382: 
  383: 		if (DEBUG_GTE(DELTASUM, 2))
  384: 			rprintf(FINFO, "calling match_sums %s%s%s\n", path,slash,fname);
  385: 
  386: 		if (log_before_transfer)
  387: 			log_item(FCLIENT, file, iflags, NULL);
  388: 		else if (!am_server && INFO_GTE(NAME, 1) && INFO_EQ(PROGRESS, 1))
  389: 			rprintf(FCLIENT, "%s\n", fname);
  390: 
  391: 		set_compression(fname);
  392: 
  393: 		match_sums(f_xfer, s, mbuf, st.st_size);
  394: 		if (INFO_GTE(PROGRESS, 1))
  395: 			end_progress(st.st_size);
  396: 
  397: 		log_item(log_code, file, iflags, NULL);
  398: 
  399: 		if (mbuf) {
  400: 			j = unmap_file(mbuf);
  401: 			if (j) {
  402: 				io_error |= IOERR_GENERAL;
  403: 				rsyserr(FERROR_XFER, j,
  404: 					"read errors mapping %s",
  405: 					full_fname(fname));
  406: 			}
  407: 		}
  408: 		close(fd);
  409: 
  410: 		free_sums(s);
  411: 
  412: 		if (DEBUG_GTE(SEND, 1))
  413: 			rprintf(FINFO, "sender finished %s%s%s\n", path,slash,fname);
  414: 
  415: 		/* Flag that we actually sent this entry. */
  416: 		file->flags |= FLAG_FILE_SENT;
  417: 	}
  418: 	if (make_backups < 0)
  419: 		make_backups = -make_backups;
  420: 
  421: 	if (io_error != save_io_error && protocol_version >= 30)
  422: 		send_msg_int(MSG_IO_ERROR, io_error);
  423: 
  424: 	if (DEBUG_GTE(SEND, 1))
  425: 		rprintf(FINFO, "send files finished\n");
  426: 
  427: 	match_report();
  428: 
  429: 	write_ndx(f_out, NDX_DONE);
  430: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>