Annotation of embedaddon/rsync/sender.c, revision 1.1.1.3

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
1.1.1.3 ! misho       6:  * Copyright (C) 2003-2015 Wayne Davison
1.1       misho       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"
1.1.1.2   misho      23: #include "inums.h"
1.1       misho      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;
1.1.1.3 ! misho      32: extern int want_xattr_optim;
1.1       misho      33: extern int csum_length;
                     34: extern int append_mode;
                     35: extern int io_error;
1.1.1.2   misho      36: extern int flist_eof;
1.1       misho      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;
1.1.1.2   misho      46: extern int file_old_total;
1.1       misho      47: extern struct stats stats;
                     48: extern struct file_list *cur_flist, *first_flist, *dir_flist;
                     49: 
1.1.1.2   misho      50: BOOL extra_flist_sending_enabled;
                     51: 
1.1       misho      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;
1.1.1.2   misho      67:        int lull_mod = protocol_version >= 31 ? 0 : allowed_lull * 5;
1.1       misho      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: 
1.1.1.2   misho      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);
1.1       misho      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: 
1.1.1.2   misho     108:                if (lull_mod && !(i % lull_mod))
                    109:                        maybe_send_keepalive(time(NULL), True);
1.1       misho     110: 
1.1.1.2   misho     111:                if (DEBUG_GTE(DELTASUM, 3)) {
1.1       misho     112:                        rprintf(FINFO,
1.1.1.2   misho     113:                                "chunk[%d] len=%d offset=%s sum1=%08x\n",
                    114:                                i, s->sums[i].len, big_num(s->sums[i].offset),
1.1       misho     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];
1.1.1.2   misho     127:        char *failed_op;
1.1       misho     128:        struct file_struct *file;
                    129:        struct file_list *flist;
1.1.1.2   misho     130:        STRUCT_STAT st;
1.1       misho     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: 
1.1.1.2   misho     141:        if (do_lstat(fname, &st) < 0) {
                    142:                failed_op = "re-lstat";
                    143:                goto failed;
                    144:        }
                    145: 
1.1.1.3 ! misho     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
1.1.1.2   misho     148: #ifdef ST_MTIME_NSEC
                    149:         || (NSEC_BUMP(file) && (uint32)st.ST_MTIME_NSEC != F_MOD_NSEC(file))
                    150: #endif
1.1.1.3 ! misho     151:        )) {
        !           152:                rprintf(FERROR_XFER, "ERROR: Skipping sender remove for changed file: %s\n", fname);
1.1.1.2   misho     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
1.1.1.3 ! misho     162:                        rsyserr(FERROR_XFER, errno, "sender failed to %s %s", failed_op, fname);
1.1.1.2   misho     163:        } else {
                    164:                if (INFO_GTE(REMOVE, 1))
1.1       misho     165:                        rprintf(FINFO, "sender removed %s\n", fname);
1.1.1.2   misho     166:        }
1.1       misho     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
1.1.1.2   misho     182:        if (preserve_xattrs && iflags & ITEM_REPORT_XATTR && do_xfers
1.1.1.3 ! misho     183:         && !(want_xattr_optim && BITS_SET(iflags, ITEM_XNAME_FOLLOWS|ITEM_LOCAL_CHANGE)))
1.1       misho     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: 
1.1.1.2   misho     206:        if (DEBUG_GTE(SEND, 1))
1.1       misho     207:                rprintf(FINFO, "send_files starting\n");
                    208: 
                    209:        while (1) {
1.1.1.2   misho     210:                if (inc_recurse) {
                    211:                        send_extra_file_list(f_out, MIN_FILECNT_LOOKAHEAD);
                    212:                        extra_flist_sending_enabled = !flist_eof;
                    213:                }
1.1       misho     214: 
                    215:                /* This call also sets cur_flist. */
1.1.1.2   misho     216:                ndx = read_ndx_and_attrs(f_in, f_out, &iflags, &fnamecmp_type,
1.1       misho     217:                                         xname, &xlen);
1.1.1.2   misho     218:                extra_flist_sending_enabled = False;
                    219: 
1.1       misho     220:                if (ndx == NDX_DONE) {
1.1.1.2   misho     221:                        if (!am_server && INFO_GTE(PROGRESS, 2) && cur_flist) {
                    222:                                set_current_file_index(NULL, 0);
                    223:                                end_progress(0);
                    224:                        }
1.1       misho     225:                        if (inc_recurse && first_flist) {
1.1.1.2   misho     226:                                file_old_total -= first_flist->used;
1.1       misho     227:                                flist_free(first_flist);
                    228:                                if (first_flist) {
1.1.1.2   misho     229:                                        if (first_flist == cur_flist)
                    230:                                                file_old_total = cur_flist->used;
1.1       misho     231:                                        write_ndx(f_out, NDX_DONE);
                    232:                                        continue;
                    233:                                }
                    234:                        }
                    235:                        if (++phase > max_phase)
                    236:                                break;
1.1.1.2   misho     237:                        if (DEBUG_GTE(SEND, 1))
1.1       misho     238:                                rprintf(FINFO, "send_files phase=%d\n", phase);
                    239:                        write_ndx(f_out, NDX_DONE);
                    240:                        continue;
                    241:                }
                    242: 
                    243:                if (inc_recurse)
1.1.1.2   misho     244:                        send_extra_file_list(f_out, MIN_FILECNT_LOOKAHEAD);
1.1       misho     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: 
1.1.1.2   misho     260:                if (DEBUG_GTE(SEND, 1))
1.1       misho     261:                        rprintf(FINFO, "send_files(%d, %s%s%s)\n", ndx, path,slash,fname);
                    262: 
                    263: #ifdef SUPPORT_XATTRS
1.1.1.2   misho     264:                if (preserve_xattrs && iflags & ITEM_REPORT_XATTR && do_xfers
1.1.1.3 ! misho     265:                 && !(want_xattr_optim && BITS_SET(iflags, ITEM_XNAME_FOLLOWS|ITEM_LOCAL_CHANGE)))
1.1       misho     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);
1.1.1.2   misho     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:                        }
1.1       misho     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:                        }
1.1.1.2   misho     311:                        if (iflags & ITEM_IS_NEW)
                    312:                                stats.created_files++;
1.1       misho     313:                }
                    314: 
                    315:                updating_basis_file = inplace && (protocol_version >= 29
                    316:                        ? fnamecmp_type == FNAMECMP_FNAME : make_backups <= 0);
                    317: 
1.1.1.2   misho     318:                if (!am_server && INFO_GTE(PROGRESS, 1))
1.1       misho     319:                        set_current_file_index(file, ndx);
1.1.1.2   misho     320:                stats.xferred_files++;
1.1       misho     321:                stats.total_transferred_size += F_LENGTH(file);
                    322: 
1.1.1.3 ! misho     323:                remember_initial_stats();
1.1.1.2   misho     324: 
1.1       misho     325:                if (!do_xfers) { /* log the transfer */
1.1.1.2   misho     326:                        log_item(FCLIENT, file, iflags, NULL);
1.1       misho     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);
1.1.1.2   misho     365:                        exit_cleanup(RERR_FILEIO);
1.1       misho     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: 
1.1.1.2   misho     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));
1.1       misho     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: 
1.1.1.2   misho     383:                if (DEBUG_GTE(DELTASUM, 2))
1.1       misho     384:                        rprintf(FINFO, "calling match_sums %s%s%s\n", path,slash,fname);
                    385: 
                    386:                if (log_before_transfer)
1.1.1.2   misho     387:                        log_item(FCLIENT, file, iflags, NULL);
                    388:                else if (!am_server && INFO_GTE(NAME, 1) && INFO_EQ(PROGRESS, 1))
1.1       misho     389:                        rprintf(FCLIENT, "%s\n", fname);
                    390: 
                    391:                set_compression(fname);
                    392: 
                    393:                match_sums(f_xfer, s, mbuf, st.st_size);
1.1.1.2   misho     394:                if (INFO_GTE(PROGRESS, 1))
1.1       misho     395:                        end_progress(st.st_size);
                    396: 
1.1.1.2   misho     397:                log_item(log_code, file, iflags, NULL);
1.1       misho     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: 
1.1.1.2   misho     412:                if (DEBUG_GTE(SEND, 1))
1.1       misho     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: 
1.1.1.2   misho     424:        if (DEBUG_GTE(SEND, 1))
1.1       misho     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>