File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / rsync / sender.c
Revision 1.1: download - view: text, annotated - select for diffs - revision graph
Fri Feb 17 15:09:30 2012 UTC (12 years, 4 months ago) by misho
CVS tags: MAIN, HEAD
Initial revision

    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-2009 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: 
   24: extern int verbose;
   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 csum_length;
   33: extern int append_mode;
   34: extern int io_error;
   35: extern int allowed_lull;
   36: extern int preserve_xattrs;
   37: extern int protocol_version;
   38: extern int remove_source_files;
   39: extern int updating_basis_file;
   40: extern int make_backups;
   41: extern int do_progress;
   42: extern int inplace;
   43: extern int batch_fd;
   44: extern int write_batch;
   45: extern struct stats stats;
   46: extern struct file_list *cur_flist, *first_flist, *dir_flist;
   47: 
   48: /**
   49:  * @file
   50:  *
   51:  * The sender gets checksums from the generator, calculates deltas,
   52:  * and transmits them to the receiver.  The sender process runs on the
   53:  * machine holding the source files.
   54:  **/
   55: 
   56: /**
   57:  * Receive the checksums for a buffer
   58:  **/
   59: static struct sum_struct *receive_sums(int f)
   60: {
   61: 	struct sum_struct *s;
   62: 	int32 i;
   63: 	int lull_mod = allowed_lull * 5;
   64: 	OFF_T offset = 0;
   65: 
   66: 	if (!(s = new(struct sum_struct)))
   67: 		out_of_memory("receive_sums");
   68: 
   69: 	read_sum_head(f, s);
   70: 
   71: 	s->sums = NULL;
   72: 
   73: 	if (verbose > 3) {
   74: 		rprintf(FINFO, "count=%.0f n=%ld rem=%ld\n",
   75: 			(double)s->count, (long)s->blength, (long)s->remainder);
   76: 	}
   77: 
   78: 	if (append_mode > 0) {
   79: 		s->flength = (OFF_T)s->count * s->blength;
   80: 		if (s->remainder)
   81: 			s->flength -= s->blength - s->remainder;
   82: 		return s;
   83: 	}
   84: 
   85: 	if (s->count == 0)
   86: 		return(s);
   87: 
   88: 	if (!(s->sums = new_array(struct sum_buf, s->count)))
   89: 		out_of_memory("receive_sums");
   90: 
   91: 	for (i = 0; i < s->count; i++) {
   92: 		s->sums[i].sum1 = read_int(f);
   93: 		read_buf(f, s->sums[i].sum2, s->s2length);
   94: 
   95: 		s->sums[i].offset = offset;
   96: 		s->sums[i].flags = 0;
   97: 
   98: 		if (i == s->count-1 && s->remainder != 0)
   99: 			s->sums[i].len = s->remainder;
  100: 		else
  101: 			s->sums[i].len = s->blength;
  102: 		offset += s->sums[i].len;
  103: 
  104: 		if (allowed_lull && !(i % lull_mod))
  105: 			maybe_send_keepalive();
  106: 
  107: 		if (verbose > 3) {
  108: 			rprintf(FINFO,
  109: 				"chunk[%d] len=%d offset=%.0f sum1=%08x\n",
  110: 				i, s->sums[i].len, (double)s->sums[i].offset,
  111: 				s->sums[i].sum1);
  112: 		}
  113: 	}
  114: 
  115: 	s->flength = offset;
  116: 
  117: 	return s;
  118: }
  119: 
  120: void successful_send(int ndx)
  121: {
  122: 	char fname[MAXPATHLEN];
  123: 	struct file_struct *file;
  124: 	struct file_list *flist;
  125: 
  126: 	if (!remove_source_files)
  127: 		return;
  128: 
  129: 	flist = flist_for_ndx(ndx, "successful_send");
  130: 	file = flist->files[ndx - flist->ndx_start];
  131: 	if (!change_pathname(file, NULL, 0))
  132: 		return;
  133: 	f_name(file, fname);
  134: 
  135: 	if (do_unlink(fname) == 0) {
  136: 		if (verbose > 1)
  137: 			rprintf(FINFO, "sender removed %s\n", fname);
  138: 	} else
  139: 		rsyserr(FERROR, errno, "sender failed to remove %s", fname);
  140: }
  141: 
  142: static void write_ndx_and_attrs(int f_out, int ndx, int iflags,
  143: 				const char *fname, struct file_struct *file,
  144: 				uchar fnamecmp_type, char *buf, int len)
  145: {
  146: 	write_ndx(f_out, ndx);
  147: 	if (protocol_version < 29)
  148: 		return;
  149: 	write_shortint(f_out, iflags);
  150: 	if (iflags & ITEM_BASIS_TYPE_FOLLOWS)
  151: 		write_byte(f_out, fnamecmp_type);
  152: 	if (iflags & ITEM_XNAME_FOLLOWS)
  153: 		write_vstring(f_out, buf, len);
  154: #ifdef SUPPORT_XATTRS
  155: 	if (preserve_xattrs && iflags & ITEM_REPORT_XATTR && do_xfers)
  156: 		send_xattr_request(fname, file, f_out);
  157: #endif
  158: }
  159: 
  160: void send_files(int f_in, int f_out)
  161: {
  162: 	int fd = -1;
  163: 	struct sum_struct *s;
  164: 	struct map_struct *mbuf = NULL;
  165: 	STRUCT_STAT st;
  166: 	char fname[MAXPATHLEN], xname[MAXPATHLEN];
  167: 	const char *path, *slash;
  168: 	uchar fnamecmp_type;
  169: 	int iflags, xlen;
  170: 	struct file_struct *file;
  171: 	int phase = 0, max_phase = protocol_version >= 29 ? 2 : 1;
  172: 	struct stats initial_stats;
  173: 	int itemizing = am_server ? logfile_format_has_i : stdout_format_has_i;
  174: 	enum logcode log_code = log_before_transfer ? FLOG : FINFO;
  175: 	int f_xfer = write_batch < 0 ? batch_fd : f_out;
  176: 	int save_io_error = io_error;
  177: 	int ndx, j;
  178: 
  179: 	if (verbose > 2)
  180: 		rprintf(FINFO, "send_files starting\n");
  181: 
  182: 	while (1) {
  183: 		if (inc_recurse)
  184: 			send_extra_file_list(f_out, FILECNT_LOOKAHEAD);
  185: 
  186: 		/* This call also sets cur_flist. */
  187: 		ndx = read_ndx_and_attrs(f_in, &iflags, &fnamecmp_type,
  188: 					 xname, &xlen);
  189: 		if (ndx == NDX_DONE) {
  190: 			if (inc_recurse && first_flist) {
  191: 				flist_free(first_flist);
  192: 				if (first_flist) {
  193: 					write_ndx(f_out, NDX_DONE);
  194: 					continue;
  195: 				}
  196: 			}
  197: 			if (++phase > max_phase)
  198: 				break;
  199: 			if (verbose > 2)
  200: 				rprintf(FINFO, "send_files phase=%d\n", phase);
  201: 			write_ndx(f_out, NDX_DONE);
  202: 			continue;
  203: 		}
  204: 
  205: 		if (inc_recurse)
  206: 			send_extra_file_list(f_out, FILECNT_LOOKAHEAD);
  207: 
  208: 		if (ndx - cur_flist->ndx_start >= 0)
  209: 			file = cur_flist->files[ndx - cur_flist->ndx_start];
  210: 		else
  211: 			file = dir_flist->files[cur_flist->parent_ndx];
  212: 		if (F_PATHNAME(file)) {
  213: 			path = F_PATHNAME(file);
  214: 			slash = "/";
  215: 		} else {
  216: 			path = slash = "";
  217: 		}
  218: 		if (!change_pathname(file, NULL, 0))
  219: 			continue;
  220: 		f_name(file, fname);
  221: 
  222: 		if (verbose > 2)
  223: 			rprintf(FINFO, "send_files(%d, %s%s%s)\n", ndx, path,slash,fname);
  224: 
  225: #ifdef SUPPORT_XATTRS
  226: 		if (preserve_xattrs && iflags & ITEM_REPORT_XATTR && do_xfers)
  227: 			recv_xattr_request(file, f_in);
  228: #endif
  229: 
  230: 		if (!(iflags & ITEM_TRANSFER)) {
  231: 			maybe_log_item(file, iflags, itemizing, xname);
  232: 			write_ndx_and_attrs(f_out, ndx, iflags, fname, file,
  233: 					    fnamecmp_type, xname, xlen);
  234: 			continue;
  235: 		}
  236: 		if (phase == 2) {
  237: 			rprintf(FERROR,
  238: 				"got transfer request in phase 2 [%s]\n",
  239: 				who_am_i());
  240: 			exit_cleanup(RERR_PROTOCOL);
  241: 		}
  242: 
  243: 		if (file->flags & FLAG_FILE_SENT) {
  244: 			if (csum_length == SHORT_SUM_LENGTH) {
  245: 				/* For inplace: redo phase turns off the backup
  246: 				 * flag so that we do a regular inplace send. */
  247: 				make_backups = -make_backups;
  248: 				append_mode = -append_mode;
  249: 				csum_length = SUM_LENGTH;
  250: 			}
  251: 		} else {
  252: 			if (csum_length != SHORT_SUM_LENGTH) {
  253: 				make_backups = -make_backups;
  254: 				append_mode = -append_mode;
  255: 				csum_length = SHORT_SUM_LENGTH;
  256: 			}
  257: 		}
  258: 
  259: 		updating_basis_file = inplace && (protocol_version >= 29
  260: 			? fnamecmp_type == FNAMECMP_FNAME : make_backups <= 0);
  261: 
  262: 		if (!am_server && do_progress)
  263: 			set_current_file_index(file, ndx);
  264: 		stats.num_transferred_files++;
  265: 		stats.total_transferred_size += F_LENGTH(file);
  266: 
  267: 		if (!do_xfers) { /* log the transfer */
  268: 			log_item(FCLIENT, file, &stats, iflags, NULL);
  269: 			write_ndx_and_attrs(f_out, ndx, iflags, fname, file,
  270: 					    fnamecmp_type, xname, xlen);
  271: 			continue;
  272: 		}
  273: 
  274: 		initial_stats = stats;
  275: 
  276: 		if (!(s = receive_sums(f_in))) {
  277: 			io_error |= IOERR_GENERAL;
  278: 			rprintf(FERROR_XFER, "receive_sums failed\n");
  279: 			exit_cleanup(RERR_PROTOCOL);
  280: 		}
  281: 
  282: 		fd = do_open(fname, O_RDONLY, 0);
  283: 		if (fd == -1) {
  284: 			if (errno == ENOENT) {
  285: 				enum logcode c = am_daemon
  286: 				    && protocol_version < 28 ? FERROR
  287: 							     : FWARNING;
  288: 				io_error |= IOERR_VANISHED;
  289: 				rprintf(c, "file has vanished: %s\n",
  290: 					full_fname(fname));
  291: 			} else {
  292: 				io_error |= IOERR_GENERAL;
  293: 				rsyserr(FERROR_XFER, errno,
  294: 					"send_files failed to open %s",
  295: 					full_fname(fname));
  296: 			}
  297: 			free_sums(s);
  298: 			if (protocol_version >= 30)
  299: 				send_msg_int(MSG_NO_SEND, ndx);
  300: 			continue;
  301: 		}
  302: 
  303: 		/* map the local file */
  304: 		if (do_fstat(fd, &st) != 0) {
  305: 			io_error |= IOERR_GENERAL;
  306: 			rsyserr(FERROR_XFER, errno, "fstat failed");
  307: 			free_sums(s);
  308: 			close(fd);
  309: 			exit_cleanup(RERR_PROTOCOL);
  310: 		}
  311: 
  312: 		if (st.st_size) {
  313: 			int32 read_size = MAX(s->blength * 3, MAX_MAP_SIZE);
  314: 			mbuf = map_file(fd, st.st_size, read_size, s->blength);
  315: 		} else
  316: 			mbuf = NULL;
  317: 
  318: 		if (verbose > 2) {
  319: 			rprintf(FINFO, "send_files mapped %s%s%s of size %.0f\n",
  320: 				path,slash,fname, (double)st.st_size);
  321: 		}
  322: 
  323: 		write_ndx_and_attrs(f_out, ndx, iflags, fname, file,
  324: 				    fnamecmp_type, xname, xlen);
  325: 		write_sum_head(f_xfer, s);
  326: 
  327: 		if (verbose > 2)
  328: 			rprintf(FINFO, "calling match_sums %s%s%s\n", path,slash,fname);
  329: 
  330: 		if (log_before_transfer)
  331: 			log_item(FCLIENT, file, &initial_stats, iflags, NULL);
  332: 		else if (!am_server && verbose && do_progress)
  333: 			rprintf(FCLIENT, "%s\n", fname);
  334: 
  335: 		set_compression(fname);
  336: 
  337: 		match_sums(f_xfer, s, mbuf, st.st_size);
  338: 		if (do_progress)
  339: 			end_progress(st.st_size);
  340: 
  341: 		log_item(log_code, file, &initial_stats, iflags, NULL);
  342: 
  343: 		if (mbuf) {
  344: 			j = unmap_file(mbuf);
  345: 			if (j) {
  346: 				io_error |= IOERR_GENERAL;
  347: 				rsyserr(FERROR_XFER, j,
  348: 					"read errors mapping %s",
  349: 					full_fname(fname));
  350: 			}
  351: 		}
  352: 		close(fd);
  353: 
  354: 		free_sums(s);
  355: 
  356: 		if (verbose > 2)
  357: 			rprintf(FINFO, "sender finished %s%s%s\n", path,slash,fname);
  358: 
  359: 		/* Flag that we actually sent this entry. */
  360: 		file->flags |= FLAG_FILE_SENT;
  361: 	}
  362: 	if (make_backups < 0)
  363: 		make_backups = -make_backups;
  364: 
  365: 	if (io_error != save_io_error && protocol_version >= 30)
  366: 		send_msg_int(MSG_IO_ERROR, io_error);
  367: 
  368: 	if (verbose > 2)
  369: 		rprintf(FINFO, "send files finished\n");
  370: 
  371: 	match_report();
  372: 
  373: 	write_ndx(f_out, NDX_DONE);
  374: }

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