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

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

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