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>