Annotation of embedaddon/rsync/sender.c, revision 1.1.1.1
1.1 misho 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>