[BACK]Return to uploader.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / rsync

Annotation of src/usr.bin/rsync/uploader.c, Revision 1.12

1.12    ! florian     1: /*     $Id: uploader.c,v 1.11 2019/02/16 10:48:05 florian Exp $ */
1.1       benno       2: /*
                      3:  * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
1.12    ! florian     4:  * Copyright (c) 2019 Florian Obser <florian@openbsd.org>
1.1       benno       5:  *
                      6:  * Permission to use, copy, modify, and distribute this software for any
                      7:  * purpose with or without fee is hereby granted, provided that the above
                      8:  * copyright notice and this permission notice appear in all copies.
                      9:  *
                     10:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     11:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     12:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     13:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     14:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     15:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     16:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     17:  */
                     18: #include <sys/mman.h>
                     19: #include <sys/stat.h>
                     20:
                     21: #include <assert.h>
                     22: #include <errno.h>
                     23: #include <fcntl.h>
                     24: #include <inttypes.h>
                     25: #include <math.h>
                     26: #include <poll.h>
                     27: #include <stdio.h>
                     28: #include <stdlib.h>
                     29: #include <string.h>
                     30: #include <time.h>
                     31: #include <unistd.h>
                     32:
                     33: #include "extern.h"
                     34:
                     35: enum   uploadst {
                     36:        UPLOAD_FIND_NEXT = 0, /* find next to upload to sender */
                     37:        UPLOAD_WRITE_LOCAL, /* wait to write to sender */
                     38:        UPLOAD_READ_LOCAL, /* wait to read from local file */
                     39:        UPLOAD_FINISHED /* nothing more to do in phase */
                     40: };
                     41:
                     42: /*
                     43:  * Used to keep track of data flowing from the receiver to the sender.
                     44:  * This is managed by the receiver process.
                     45:  */
                     46: struct upload {
                     47:        enum uploadst       state;
                     48:        char               *buf; /* if not NULL, pending upload */
                     49:        size_t              bufsz; /* size of buf */
                     50:        size_t              bufmax; /* maximum size of buf */
                     51:        size_t              bufpos; /* position in buf */
                     52:        size_t              idx; /* current transfer index */
                     53:        mode_t              oumask; /* umask for creating files */
1.11      florian    54:        char               *root; /* destination directory path */
1.1       benno      55:        int                 rootfd; /* destination directory */
                     56:        size_t              csumlen; /* checksum length */
                     57:        int                 fdout; /* write descriptor to sender */
                     58:        const struct flist *fl; /* file list */
                     59:        size_t              flsz; /* size of file list */
                     60:        int                *newdir; /* non-zero if mkdir'd */
                     61: };
                     62:
                     63: /*
                     64:  * Log a directory by emitting the file and a trailing slash, just to
                     65:  * show the operator that we're a directory.
                     66:  */
                     67: static void
                     68: log_dir(struct sess *sess, const struct flist *f)
                     69: {
                     70:        size_t   sz;
                     71:
                     72:        if (sess->opts->server)
                     73:                return;
                     74:        sz = strlen(f->path);
                     75:        assert(sz > 0);
1.7       deraadt    76:        LOG1(sess, "%s%s", f->path, ('/' == f->path[sz - 1]) ? "" : "/");
1.1       benno      77: }
                     78:
                     79: /*
                     80:  * Log a link by emitting the file and the target, just to show the
                     81:  * operator that we're a link.
                     82:  */
                     83: static void
                     84: log_link(struct sess *sess, const struct flist *f)
                     85: {
                     86:
1.3       deraadt    87:        if (!sess->opts->server)
1.1       benno      88:                LOG1(sess, "%s -> %s", f->path, f->link);
                     89: }
                     90:
                     91: /*
                     92:  * Simply log the filename.
                     93:  */
                     94: static void
                     95: log_file(struct sess *sess, const struct flist *f)
                     96: {
                     97:
1.3       deraadt    98:        if (!sess->opts->server)
1.1       benno      99:                LOG1(sess, "%s", f->path);
                    100: }
                    101:
                    102: /*
                    103:  * Prepare the overall block set's metadata.
                    104:  * We always have at least one block.
                    105:  * The block size is an important part of the algorithm.
                    106:  * I use the same heuristic as the reference rsync, but implemented in a
                    107:  * bit more of a straightforward way.
                    108:  * In general, the individual block length is the rounded square root of
                    109:  * the total file size.
                    110:  * The minimum block length is 700.
                    111:  */
                    112: static void
                    113: init_blkset(struct blkset *p, off_t sz)
                    114: {
                    115:        double   v;
                    116:
                    117:        if (sz >= (BLOCK_SIZE_MIN * BLOCK_SIZE_MIN)) {
                    118:                /* Simple rounded-up integer square root. */
                    119:
                    120:                v = sqrt(sz);
                    121:                p->len = ceil(v);
                    122:
1.2       benno     123:                /*
1.1       benno     124:                 * Always be a multiple of eight.
                    125:                 * There's no reason to do this, but rsync does.
                    126:                 */
                    127:
                    128:                if ((p->len % 8) > 0)
                    129:                        p->len += 8 - (p->len % 8);
                    130:        } else
                    131:                p->len = BLOCK_SIZE_MIN;
                    132:
                    133:        p->size = sz;
1.4       deraadt   134:        if ((p->blksz = sz / p->len) == 0)
1.1       benno     135:                p->rem = sz;
                    136:        else
                    137:                p->rem = sz % p->len;
                    138:
                    139:        /* If we have a remainder, then we need an extra block. */
                    140:
                    141:        if (p->rem)
                    142:                p->blksz++;
                    143: }
                    144:
                    145: /*
                    146:  * For each block, prepare the block's metadata.
                    147:  * We use the mapped "map" file to set our checksums.
                    148:  */
                    149: static void
                    150: init_blk(struct blk *p, const struct blkset *set, off_t offs,
                    151:        size_t idx, const void *map, const struct sess *sess)
                    152: {
                    153:
1.4       deraadt   154:        assert(map != MAP_FAILED);
1.1       benno     155:
                    156:        /* Block length inherits for all but the last. */
                    157:
                    158:        p->idx = idx;
                    159:        p->len = idx < set->blksz - 1 ? set->len : set->rem;
                    160:        p->offs = offs;
                    161:
                    162:        p->chksum_short = hash_fast(map + offs, p->len);
                    163:        hash_slow(map + offs, p->len, p->chksum_long, sess);
                    164: }
                    165:
                    166: /*
                    167:  * Return <0 on failure 0 on success.
                    168:  */
                    169: static int
                    170: pre_link(struct upload *p, struct sess *sess)
                    171: {
1.9       florian   172:        struct stat              st;
                    173:        const struct flist      *f;
                    174:        int                      rc, newlink = 0, updatelink = 0;
1.11      florian   175:        char                    *b, *temp = NULL;
1.1       benno     176:
                    177:        f = &p->fl[p->idx];
                    178:        assert(S_ISLNK(f->st.mode));
                    179:
1.3       deraadt   180:        if (!sess->opts->preserve_links) {
1.1       benno     181:                WARNX(sess, "%s: ignoring symlink", f->path);
                    182:                return 0;
                    183:        } else if (sess->opts->dry_run) {
                    184:                log_link(sess, f);
                    185:                return 0;
                    186:        }
                    187:
                    188:        /* See if the symlink already exists. */
                    189:
1.4       deraadt   190:        assert(p->rootfd != -1);
1.1       benno     191:        rc = fstatat(p->rootfd, f->path, &st, AT_SYMLINK_NOFOLLOW);
1.4       deraadt   192:        if (rc != -1 && !S_ISLNK(st.st_mode)) {
1.9       florian   193:                if (S_ISDIR(st.st_mode)) {
                    194:                        if (unlinkat(p->rootfd, f->path, AT_REMOVEDIR) == -1) {
                    195:                                WARN(sess, "%s", f->path);
                    196:                                return -1;
                    197:                        }
                    198:                }
                    199:                rc = -1; /* overwrite object with symlink */
1.4       deraadt   200:        } else if (rc == -1 && errno != ENOENT) {
1.1       benno     201:                WARN(sess, "%s: fstatat", f->path);
                    202:                return -1;
                    203:        }
                    204:
                    205:        /*
                    206:         * If the symbolic link already exists, then make sure that it
                    207:         * points to the correct place.
                    208:         */
                    209:
1.9       florian   210:        if (rc != -1) {
1.1       benno     211:                b = symlinkat_read(sess, p->rootfd, f->path);
1.4       deraadt   212:                if (b == NULL) {
1.1       benno     213:                        ERRX1(sess, "%s: symlinkat_read", f->path);
                    214:                        return -1;
                    215:                }
                    216:                if (strcmp(f->link, b)) {
                    217:                        free(b);
                    218:                        b = NULL;
                    219:                        LOG3(sess, "%s: updating "
                    220:                                "symlink: %s", f->path, f->link);
1.9       florian   221:                        updatelink = 1;
1.2       benno     222:                }
1.1       benno     223:                free(b);
1.9       florian   224:                b = NULL;
                    225:        }
                    226:
                    227:        if (rc == -1 || updatelink) {
                    228:                LOG3(sess, "%s: creating "
                    229:                        "symlink: %s", f->path, f->link);
                    230:
1.11      florian   231:                if (mktemplate(&temp, f->path, sess->opts->recursive) == -1) {
1.9       florian   232:                        ERR(sess, "asprintf");
                    233:                        return -1;
                    234:                }
1.11      florian   235:                if (mkstemplinkat(f->link, p->rootfd, temp) == NULL) {
                    236:                        WARN(sess, "%s: symlinkat", temp);
                    237:                        free(temp);
1.9       florian   238:                        return -1;
                    239:                }
                    240:                newlink = 1;
1.1       benno     241:        }
                    242:
1.11      florian   243:        rsync_set_metadata_at(sess, newlink, p->rootfd, f,
                    244:            newlink ? temp : f->path);
                    245:
                    246:        if (newlink) {
                    247:                if (renameat(p->rootfd, temp, p->rootfd, f->path) == -1) {
                    248:                        ERR(sess, "%s: renameat %s", temp, f->path);
                    249:                        (void)unlinkat(p->rootfd, temp, 0);
                    250:                        free(temp);
                    251:                        return -1;
                    252:                }
                    253:                free(temp);
                    254:        }
                    255:
                    256:        log_link(sess, f);
                    257:        return 0;
                    258: }
                    259:
                    260: /*
                    261:  * Return <0 on failure 0 on success.
                    262:  */
                    263: static int
                    264: pre_dev(struct upload *p, struct sess *sess)
                    265: {
                    266:        struct stat              st;
                    267:        const struct flist      *f;
                    268:        int                      rc, newdev = 0, updatedev = 0;
                    269:        char                    *temp = NULL;
                    270:
                    271:        f = &p->fl[p->idx];
                    272:        assert(S_ISBLK(f->st.mode) || S_ISCHR(f->st.mode));
                    273:
                    274:        if (!sess->opts->devices || getuid() != 0) {
                    275:                WARNX(sess, "skipping non-regular file %s", f->path);
                    276:                return 0;
                    277:        } else if (sess->opts->dry_run) {
                    278:                log_file(sess, f);
                    279:                return 0;
                    280:        }
                    281:
                    282:        /* See if the dev already exists */
                    283:        assert(p->rootfd != -1);
                    284:
                    285:        rc = fstatat(p->rootfd, f->path, &st, AT_SYMLINK_NOFOLLOW);
                    286:
                    287:        if (rc != -1 && !(S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode))) {
                    288:                if (S_ISDIR(st.st_mode)) {
                    289:                        if (unlinkat(p->rootfd, f->path, AT_REMOVEDIR) == -1) {
                    290:                                WARN(sess, "%s", f->path);
                    291:                                return -1;
                    292:                        }
                    293:                }
                    294:                rc = -1; /* overwrite object with dev */
                    295:        } else if (rc == -1 && errno != ENOENT) {
                    296:                WARN(sess, "%s: fstatat", f->path);
                    297:                return -1;
                    298:        }
                    299:
                    300:        /*
                    301:         * If the device already exists make sure it is of the correct type.
1.6       florian   302:         */
1.1       benno     303:
1.11      florian   304:        if (rc != -1) {
                    305:                if ((f->st.mode & (S_IFCHR|S_IFBLK)) !=
                    306:                    (st.st_mode & (S_IFCHR|S_IFBLK)) || f->st.rdev !=
                    307:                    st.st_rdev) {
                    308:                        LOG3(sess, "%s: updating dev", f->path);
                    309:                        updatedev = 1;
                    310:                }
                    311:        }
                    312:
                    313:        if (rc == -1 || updatedev) {
                    314:                newdev = 1;
                    315:                if (mktemplate(&temp, f->path, sess->opts->recursive) == -1) {
                    316:                        ERR(sess, "asprintf");
                    317:                        return -1;
                    318:                }
                    319:                if (mkstempnodat(p->rootfd, temp, f->st.mode &
                    320:                    (S_IFCHR|S_IFBLK), f->st.rdev) == NULL) {
                    321:                        WARN(sess, "%s: mknodat", temp);
                    322:                        free(temp);
                    323:                        return -1;
                    324:                }
                    325:        }
                    326:
                    327:        rsync_set_metadata_at(sess, newdev, p->rootfd, f,
                    328:            newdev ? temp : f->path);
                    329:
                    330:        if (newdev) {
                    331:                if (renameat(p->rootfd, temp, p->rootfd, f->path) == -1) {
                    332:                        ERR(sess, "%s: renameat %s", temp, f->path);
                    333:                        (void)unlinkat(p->rootfd, temp, 0);
                    334:                        free(temp);
                    335:                        return -1;
                    336:                }
                    337:                free(temp);
                    338:        }
                    339:        log_file(sess, f);
                    340:        return 0;
                    341: }
                    342:
                    343: /*
                    344:  * Return <0 on failure 0 on success.
                    345:  */
                    346: static int
                    347: pre_fifo(struct upload *p, struct sess *sess)
                    348: {
                    349:        struct stat              st;
                    350:        const struct flist      *f;
                    351:        int                      rc, newfifo = 0;
                    352:        char                    *temp = NULL;
                    353:
                    354:        f = &p->fl[p->idx];
                    355:        assert(S_ISFIFO(f->st.mode));
                    356:
                    357:        if (!sess->opts->specials) {
                    358:                WARNX(sess, "skipping non-regular file %s", f->path);
                    359:                return 0;
                    360:        } else if (sess->opts->dry_run) {
                    361:                log_file(sess, f);
                    362:                return 0;
                    363:        }
                    364:
                    365:        /* See if the fifo already exists */
                    366:        assert(p->rootfd != -1);
                    367:
                    368:        rc = fstatat(p->rootfd, f->path, &st, AT_SYMLINK_NOFOLLOW);
1.8       deraadt   369:
1.11      florian   370:        if (rc != -1 && !S_ISFIFO(st.st_mode)) {
                    371:                if (S_ISDIR(st.st_mode)) {
                    372:                        if (unlinkat(p->rootfd, f->path, AT_REMOVEDIR) == -1) {
                    373:                                WARN(sess, "%s", f->path);
                    374:                                return -1;
1.9       florian   375:                        }
1.11      florian   376:                }
                    377:                rc = -1; /* overwrite object with fifo */
                    378:        } else if (rc == -1 && errno != ENOENT) {
                    379:                WARN(sess, "%s: fstatat", f->path);
                    380:                return -1;
                    381:        }
                    382:
                    383:        if (rc == -1) {
                    384:                newfifo = 1;
                    385:                if (mktemplate(&temp, f->path, sess->opts->recursive) == -1) {
                    386:                        ERR(sess, "asprintf");
                    387:                        return -1;
                    388:                }
                    389:                if (mkstempfifoat(p->rootfd, temp) == NULL) {
                    390:                        WARN(sess, "%s: mkfifoat", temp);
                    391:                        free(temp);
1.1       benno     392:                        return -1;
                    393:                }
                    394:        }
1.2       benno     395:
1.11      florian   396:        rsync_set_metadata_at(sess, newfifo, p->rootfd, f,
                    397:            newfifo ? temp : f->path);
                    398:
                    399:        if (newfifo) {
                    400:                if (renameat(p->rootfd, temp, p->rootfd, f->path) == -1) {
                    401:                        ERR(sess, "%s: renameat %s", temp, f->path);
                    402:                        (void)unlinkat(p->rootfd, temp, 0);
                    403:                        free(temp);
                    404:                        return -1;
                    405:                }
                    406:                free(temp);
                    407:        }
                    408:        log_file(sess, f);
                    409:        return 0;
                    410: }
1.1       benno     411:
1.11      florian   412: /*
                    413:  * Return <0 on failure 0 on success.
                    414:  */
                    415: static int
                    416: pre_sock(struct upload *p, struct sess *sess)
                    417: {
                    418:        struct stat              st;
                    419:        const struct flist      *f;
                    420:        int                      rc, newsock = 0;
                    421:        char                    *temp = NULL;
                    422:
                    423:        f = &p->fl[p->idx];
                    424:        assert(S_ISSOCK(f->st.mode));
                    425:
                    426:        if (!sess->opts->specials) {
                    427:                WARNX(sess, "skipping non-regular file %s", f->path);
                    428:                return 0;
                    429:        } else if (sess->opts->dry_run) {
                    430:                log_file(sess, f);
                    431:                return 0;
                    432:        }
                    433:
                    434:        rc = fstatat(p->rootfd, f->path, &st, AT_SYMLINK_NOFOLLOW);
                    435:
                    436:        if (rc != -1 && !S_ISSOCK(st.st_mode)) {
                    437:                if (S_ISDIR(st.st_mode)) {
                    438:                        if (unlinkat(p->rootfd, f->path, AT_REMOVEDIR) == -1) {
                    439:                                WARN(sess, "%s", f->path);
                    440:                                return -1;
1.9       florian   441:                        }
1.11      florian   442:                }
                    443:                rc = -1; /* overwrite object with sock */
                    444:        } else if (rc == -1 && errno != ENOENT) {
                    445:                WARN(sess, "%s: fstatat", f->path);
                    446:                return -1;
                    447:        }
                    448:
                    449:        if (rc == -1) {
                    450:                newsock = 1;
                    451:
                    452:                if (mktemplate(&temp, f->path, sess->opts->recursive) == -1) {
                    453:                        ERR(sess, "asprintf");
                    454:                        return -1;
                    455:                }
                    456:
                    457:                if (mkstempsock(p->root, temp) == NULL) {
                    458:                        WARN(sess, "%s: mksockat", temp);
                    459:                        free(temp);
1.1       benno     460:                        return -1;
                    461:                }
1.9       florian   462:        }
                    463:
1.11      florian   464:        rsync_set_metadata_at(sess, newsock, p->rootfd, f,
                    465:            newsock ? temp : f->path);
                    466:
                    467:        if (newsock) {
                    468:                if (renameat(p->rootfd, temp, p->rootfd, f->path) == -1) {
                    469:                        ERR(sess, "%s: renameat %s", temp, f->path);
                    470:                        (void)unlinkat(p->rootfd, temp, 0);
                    471:                        free(temp);
1.9       florian   472:                        return -1;
                    473:                }
1.11      florian   474:                free(temp);
1.1       benno     475:        }
1.11      florian   476:        log_file(sess, f);
1.1       benno     477:        return 0;
                    478: }
                    479:
                    480: /*
                    481:  * If not found, create the destination directory in prefix order.
                    482:  * Create directories using the existing umask.
                    483:  * Return <0 on failure 0 on success.
                    484:  */
                    485: static int
                    486: pre_dir(const struct upload *p, struct sess *sess)
                    487: {
                    488:        struct stat      st;
1.2       benno     489:        int              rc;
1.1       benno     490:        const struct flist *f;
                    491:
                    492:        f = &p->fl[p->idx];
                    493:        assert(S_ISDIR(f->st.mode));
                    494:
1.3       deraadt   495:        if (!sess->opts->recursive) {
1.1       benno     496:                WARNX(sess, "%s: ignoring directory", f->path);
                    497:                return 0;
                    498:        } else if (sess->opts->dry_run) {
                    499:                log_dir(sess, f);
                    500:                return 0;
                    501:        }
                    502:
1.4       deraadt   503:        assert(p->rootfd != -1);
1.1       benno     504:        rc = fstatat(p->rootfd, f->path, &st, AT_SYMLINK_NOFOLLOW);
1.4       deraadt   505:        if (rc == -1 && errno != ENOENT) {
1.1       benno     506:                WARN(sess, "%s: fstatat", f->path);
                    507:                return -1;
1.4       deraadt   508:        } else if (rc != -1 && !S_ISDIR(st.st_mode)) {
1.1       benno     509:                WARNX(sess, "%s: not a directory", f->path);
                    510:                return -1;
1.4       deraadt   511:        } else if (rc != -1) {
1.2       benno     512:                /*
1.1       benno     513:                 * FIXME: we should fchmod the permissions here as well,
                    514:                 * as we may locally have shut down writing into the
                    515:                 * directory and that doesn't work.
                    516:                 */
                    517:                LOG3(sess, "%s: updating directory", f->path);
                    518:                return 0;
                    519:        }
                    520:
                    521:        /*
                    522:         * We want to make the directory with default permissions (using
                    523:         * our old umask, which we've since unset), then adjust
                    524:         * permissions (assuming preserve_perms or new) afterward in
                    525:         * case it's u-w or something.
                    526:         */
                    527:
                    528:        LOG3(sess, "%s: creating directory", f->path);
1.4       deraadt   529:        if (mkdirat(p->rootfd, f->path, 0777 & ~p->oumask) == -1) {
1.1       benno     530:                WARN(sess, "%s: mkdirat", f->path);
                    531:                return -1;
                    532:        }
                    533:
                    534:        p->newdir[p->idx] = 1;
                    535:        log_dir(sess, f);
                    536:        return 0;
                    537: }
                    538:
                    539: /*
                    540:  * Process the directory time and mode for "idx" in the file list.
                    541:  * Returns zero on failure, non-zero on success.
                    542:  */
                    543: static int
                    544: post_dir(struct sess *sess, const struct upload *u, size_t idx)
                    545: {
                    546:        struct timespec  tv[2];
                    547:        int              rc;
                    548:        struct stat      st;
                    549:        const struct flist *f;
                    550:
                    551:        f = &u->fl[idx];
                    552:        assert(S_ISDIR(f->st.mode));
                    553:
                    554:        /* We already warned about the directory in pre_process_dir(). */
                    555:
1.3       deraadt   556:        if (!sess->opts->recursive)
1.1       benno     557:                return 1;
                    558:        else if (sess->opts->dry_run)
                    559:                return 1;
                    560:
1.4       deraadt   561:        if (fstatat(u->rootfd, f->path, &st, AT_SYMLINK_NOFOLLOW) == -1) {
1.1       benno     562:                ERR(sess, "%s: fstatat", f->path);
                    563:                return 0;
1.3       deraadt   564:        } else if (!S_ISDIR(st.st_mode)) {
1.1       benno     565:                WARNX(sess, "%s: not a directory", f->path);
                    566:                return 0;
                    567:        }
                    568:
1.2       benno     569:        /*
1.1       benno     570:         * Update the modification time if we're a new directory *or* if
                    571:         * we're preserving times and the time has changed.
1.6       florian   572:         * FIXME: run rsync_set_metadata()?
1.1       benno     573:         */
                    574:
1.2       benno     575:        if (u->newdir[idx] ||
                    576:            (sess->opts->preserve_times &&
1.1       benno     577:             st.st_mtime != f->st.mtime)) {
                    578:                tv[0].tv_sec = time(NULL);
                    579:                tv[0].tv_nsec = 0;
                    580:                tv[1].tv_sec = f->st.mtime;
                    581:                tv[1].tv_nsec = 0;
                    582:                rc = utimensat(u->rootfd, f->path, tv, 0);
1.4       deraadt   583:                if (rc == -1) {
1.1       benno     584:                        ERR(sess, "%s: utimensat", f->path);
                    585:                        return 0;
                    586:                }
                    587:                LOG4(sess, "%s: updated date", f->path);
                    588:        }
                    589:
                    590:        /*
                    591:         * Update the mode if we're a new directory *or* if we're
                    592:         * preserving modes and it has changed.
                    593:         */
                    594:
1.2       benno     595:        if (u->newdir[idx] ||
1.1       benno     596:            (sess->opts->preserve_perms &&
                    597:             st.st_mode != f->st.mode)) {
                    598:                rc = fchmodat(u->rootfd, f->path, f->st.mode, 0);
1.4       deraadt   599:                if (rc == -1) {
1.1       benno     600:                        ERR(sess, "%s: fchmodat", f->path);
                    601:                        return 0;
                    602:                }
                    603:                LOG4(sess, "%s: updated mode", f->path);
                    604:        }
                    605:
                    606:        return 1;
                    607: }
                    608:
                    609: /*
                    610:  * Try to open the file at the current index.
                    611:  * If the file does not exist, returns with success.
                    612:  * Return <0 on failure, 0 on success w/nothing to be done, >0 on
                    613:  * success and the file needs attention.
                    614:  */
                    615: static int
                    616: pre_file(const struct upload *p, int *filefd, struct sess *sess)
                    617: {
                    618:        const struct flist *f;
                    619:
                    620:        f = &p->fl[p->idx];
                    621:        assert(S_ISREG(f->st.mode));
                    622:
                    623:        if (sess->opts->dry_run) {
                    624:                log_file(sess, f);
1.3       deraadt   625:                if (!io_write_int(sess, p->fdout, p->idx)) {
1.1       benno     626:                        ERRX1(sess, "io_write_int");
                    627:                        return -1;
                    628:                }
                    629:                return 0;
                    630:        }
                    631:
                    632:        /*
                    633:         * For non dry-run cases, we'll write the acknowledgement later
                    634:         * in the rsync_uploader() function because we need to wait for
                    635:         * the open() call to complete.
                    636:         * If the call to openat() fails with ENOENT, there's a
                    637:         * fast-path between here and the write function, so we won't do
                    638:         * any blocking between now and then.
                    639:         */
                    640:
                    641:        *filefd = openat(p->rootfd, f->path,
                    642:                O_RDONLY | O_NOFOLLOW | O_NONBLOCK, 0);
1.4       deraadt   643:        if (*filefd != -1 || errno == ENOENT)
1.1       benno     644:                return 1;
                    645:        ERR(sess, "%s: openat", f->path);
                    646:        return -1;
                    647: }
                    648:
                    649: /*
                    650:  * Allocate an uploader object in the correct state to start.
                    651:  * Returns NULL on failure or the pointer otherwise.
                    652:  * On success, upload_free() must be called with the allocated pointer.
                    653:  */
                    654: struct upload *
1.11      florian   655: upload_alloc(struct sess *sess, const char *root, int rootfd, int fdout,
1.1       benno     656:        size_t clen, const struct flist *fl, size_t flsz, mode_t msk)
                    657: {
                    658:        struct upload   *p;
                    659:
1.4       deraadt   660:        if ((p = calloc(1, sizeof(struct upload))) == NULL) {
1.1       benno     661:                ERR(sess, "calloc");
                    662:                return NULL;
                    663:        }
                    664:
                    665:        p->state = UPLOAD_FIND_NEXT;
                    666:        p->oumask = msk;
1.11      florian   667:        p->root = strdup(root);
                    668:        if (p->root == NULL) {
                    669:                ERR(sess, "strdup");
                    670:                free(p);
                    671:                return NULL;
                    672:        }
1.1       benno     673:        p->rootfd = rootfd;
                    674:        p->csumlen = clen;
                    675:        p->fdout = fdout;
                    676:        p->fl = fl;
                    677:        p->flsz = flsz;
                    678:        p->newdir = calloc(flsz, sizeof(int));
1.4       deraadt   679:        if (p->newdir == NULL) {
1.1       benno     680:                ERR(sess, "calloc");
1.11      florian   681:                free(p->root);
1.1       benno     682:                free(p);
                    683:                return NULL;
                    684:        }
                    685:        return p;
                    686: }
                    687:
                    688: /*
                    689:  * Perform all cleanups and free.
                    690:  * Passing a NULL to this function is ok.
                    691:  */
                    692: void
                    693: upload_free(struct upload *p)
                    694: {
                    695:
1.4       deraadt   696:        if (p == NULL)
1.1       benno     697:                return;
1.11      florian   698:        free(p->root);
1.1       benno     699:        free(p->newdir);
                    700:        free(p->buf);
                    701:        free(p);
                    702: }
                    703:
                    704: /*
                    705:  * Iterates through all available files and conditionally gets the file
                    706:  * ready for processing to check whether it's up to date.
                    707:  * If not up to date or empty, sends file information to the sender.
                    708:  * If returns 0, we've processed all files there are to process.
                    709:  * If returns >0, we're waiting for POLLIN or POLLOUT data.
                    710:  * Otherwise returns <0, which is an error.
                    711:  */
                    712: int
1.2       benno     713: rsync_uploader(struct upload *u, int *fileinfd,
1.1       benno     714:        struct sess *sess, int *fileoutfd)
                    715: {
1.5       florian   716:        struct blkset       blk;
                    717:        struct stat         st;
                    718:        void               *map, *bufp;
                    719:        size_t              i, mapsz, pos, sz;
                    720:        off_t               offs;
                    721:        int                 c;
                    722:        const struct flist *f;
1.1       benno     723:
                    724:        /* This should never get called. */
                    725:
1.4       deraadt   726:        assert(u->state != UPLOAD_FINISHED);
1.1       benno     727:
                    728:        /*
                    729:         * If we have an upload in progress, then keep writing until the
                    730:         * buffer has been fully written.
                    731:         * We must only have the output file descriptor working and also
                    732:         * have a valid buffer to write.
                    733:         */
                    734:
1.4       deraadt   735:        if (u->state == UPLOAD_WRITE_LOCAL) {
1.1       benno     736:                assert(NULL != u->buf);
1.4       deraadt   737:                assert(*fileoutfd != -1);
                    738:                assert(*fileinfd == -1);
1.1       benno     739:
                    740:                /*
                    741:                 * Unfortunately, we need to chunk these: if we're
                    742:                 * the server side of things, then we're multiplexing
                    743:                 * output and need to wrap this in chunks.
                    744:                 * This is a major deficiency of rsync.
                    745:                 * FIXME: add a "fast-path" mode that simply dumps out
                    746:                 * the buffer non-blocking if we're not mplexing.
                    747:                 */
                    748:
                    749:                if (u->bufpos < u->bufsz) {
                    750:                        sz = MAX_CHUNK < (u->bufsz - u->bufpos) ?
                    751:                                MAX_CHUNK : (u->bufsz - u->bufpos);
1.2       benno     752:                        c = io_write_buf(sess, u->fdout,
1.1       benno     753:                                u->buf + u->bufpos, sz);
1.4       deraadt   754:                        if (c == 0) {
1.1       benno     755:                                ERRX1(sess, "io_write_nonblocking");
                    756:                                return -1;
                    757:                        }
                    758:                        u->bufpos += sz;
                    759:                        if (u->bufpos < u->bufsz)
                    760:                                return 1;
                    761:                }
                    762:
1.2       benno     763:                /*
1.1       benno     764:                 * Let the UPLOAD_FIND_NEXT state handle things if we
                    765:                 * finish, as we'll need to write a POLLOUT message and
                    766:                 * not have a writable descriptor yet.
                    767:                 */
                    768:
                    769:                u->state = UPLOAD_FIND_NEXT;
                    770:                u->idx++;
                    771:                return 1;
                    772:        }
                    773:
                    774:        /*
                    775:         * If we invoke the uploader without a file currently open, then
                    776:         * we iterate through til the next available regular file and
                    777:         * start the opening process.
                    778:         * This means we must have the output file descriptor working.
                    779:         */
                    780:
1.4       deraadt   781:        if (u->state == UPLOAD_FIND_NEXT) {
                    782:                assert(*fileinfd == -1);
                    783:                assert(*fileoutfd != -1);
1.1       benno     784:
                    785:                for ( ; u->idx < u->flsz; u->idx++) {
                    786:                        if (S_ISDIR(u->fl[u->idx].st.mode))
                    787:                                c = pre_dir(u, sess);
                    788:                        else if (S_ISLNK(u->fl[u->idx].st.mode))
                    789:                                c = pre_link(u, sess);
                    790:                        else if (S_ISREG(u->fl[u->idx].st.mode))
                    791:                                c = pre_file(u, fileinfd, sess);
1.11      florian   792:                        else if (S_ISBLK(u->fl[u->idx].st.mode) ||
                    793:                            S_ISCHR(u->fl[u->idx].st.mode))
                    794:                                c = pre_dev(u, sess);
                    795:                        else if (S_ISFIFO(u->fl[u->idx].st.mode))
                    796:                                c = pre_fifo(u, sess);
                    797:                        else if (S_ISSOCK(u->fl[u->idx].st.mode))
                    798:                                c = pre_sock(u, sess);
1.1       benno     799:                        else
                    800:                                c = 0;
                    801:
                    802:                        if (c < 0)
                    803:                                return -1;
                    804:                        else if (c > 0)
                    805:                                break;
                    806:                }
                    807:
1.2       benno     808:                /*
1.1       benno     809:                 * Whether we've finished writing files or not, we
                    810:                 * disable polling on the output channel.
                    811:                 */
                    812:
                    813:                *fileoutfd = -1;
                    814:                if (u->idx == u->flsz) {
1.4       deraadt   815:                        assert(*fileinfd == -1);
1.3       deraadt   816:                        if (!io_write_int(sess, u->fdout, -1)) {
1.1       benno     817:                                ERRX1(sess, "io_write_int");
                    818:                                return -1;
                    819:                        }
                    820:                        u->state = UPLOAD_FINISHED;
                    821:                        LOG4(sess, "uploader: finished");
                    822:                        return 0;
                    823:                }
                    824:
                    825:                /* Go back to the event loop, if necessary. */
                    826:
                    827:                u->state = -1 == *fileinfd ?
                    828:                        UPLOAD_WRITE_LOCAL : UPLOAD_READ_LOCAL;
1.4       deraadt   829:                if (u->state == UPLOAD_READ_LOCAL)
1.1       benno     830:                        return 1;
                    831:        }
                    832:
1.2       benno     833:        /*
1.1       benno     834:         * If an input file is open, stat it and see if it's already up
                    835:         * to date, in which case close it and go to the next one.
                    836:         * Either way, we don't have a write channel open.
                    837:         */
                    838:
1.4       deraadt   839:        if (u->state == UPLOAD_READ_LOCAL) {
                    840:                assert(*fileinfd != -1);
                    841:                assert(*fileoutfd == -1);
1.5       florian   842:                f = &u->fl[u->idx];
1.1       benno     843:
1.4       deraadt   844:                if (fstat(*fileinfd, &st) == -1) {
1.5       florian   845:                        ERR(sess, "%s: fstat", f->path);
1.1       benno     846:                        close(*fileinfd);
                    847:                        *fileinfd = -1;
                    848:                        return -1;
1.3       deraadt   849:                } else if (!S_ISREG(st.st_mode)) {
1.5       florian   850:                        ERRX(sess, "%s: not regular", f->path);
1.1       benno     851:                        close(*fileinfd);
                    852:                        *fileinfd = -1;
                    853:                        return -1;
                    854:                }
                    855:
1.5       florian   856:                if (st.st_size == f->st.size &&
                    857:                    st.st_mtime == f->st.mtime) {
                    858:                        LOG3(sess, "%s: skipping: up to date", f->path);
                    859:                        if (!rsync_set_metadata
                    860:                            (sess, 0, *fileinfd, f, f->path)) {
                    861:                                ERRX1(sess, "rsync_set_metadata");
                    862:                                close(*fileinfd);
                    863:                                *fileinfd = -1;
                    864:                                return -1;
                    865:                        }
1.1       benno     866:                        close(*fileinfd);
                    867:                        *fileinfd = -1;
                    868:                        *fileoutfd = u->fdout;
                    869:                        u->state = UPLOAD_FIND_NEXT;
                    870:                        u->idx++;
                    871:                        return 1;
                    872:                }
                    873:
                    874:                /* Fallthrough... */
                    875:
                    876:                u->state = UPLOAD_WRITE_LOCAL;
                    877:        }
                    878:
                    879:        /* Initialies our blocks. */
                    880:
1.4       deraadt   881:        assert(u->state == UPLOAD_WRITE_LOCAL);
1.1       benno     882:        memset(&blk, 0, sizeof(struct blkset));
                    883:        blk.csum = u->csumlen;
                    884:
1.4       deraadt   885:        if (*fileinfd != -1 && st.st_size > 0) {
1.1       benno     886:                mapsz = st.st_size;
1.7       deraadt   887:                map = mmap(NULL, mapsz, PROT_READ, MAP_SHARED, *fileinfd, 0);
1.4       deraadt   888:                if (map == MAP_FAILED) {
1.1       benno     889:                        WARN(sess, "%s: mmap", u->fl[u->idx].path);
                    890:                        close(*fileinfd);
                    891:                        *fileinfd = -1;
                    892:                        return -1;
                    893:                }
                    894:
                    895:                init_blkset(&blk, st.st_size);
                    896:                assert(blk.blksz);
                    897:
                    898:                blk.blks = calloc(blk.blksz, sizeof(struct blk));
1.4       deraadt   899:                if (blk.blks == NULL) {
1.1       benno     900:                        ERR(sess, "calloc");
                    901:                        munmap(map, mapsz);
                    902:                        close(*fileinfd);
                    903:                        *fileinfd = -1;
                    904:                        return -1;
                    905:                }
                    906:
                    907:                offs = 0;
                    908:                for (i = 0; i < blk.blksz; i++) {
1.2       benno     909:                        init_blk(&blk.blks[i],
1.1       benno     910:                                &blk, offs, i, map, sess);
                    911:                        offs += blk.len;
                    912:                }
                    913:
                    914:                munmap(map, mapsz);
                    915:                close(*fileinfd);
                    916:                *fileinfd = -1;
                    917:                LOG3(sess, "%s: mapped %jd B with %zu blocks",
1.2       benno     918:                        u->fl[u->idx].path, (intmax_t)blk.size,
1.1       benno     919:                        blk.blksz);
                    920:        } else {
1.4       deraadt   921:                if (*fileinfd != -1) {
1.1       benno     922:                        close(*fileinfd);
                    923:                        *fileinfd = -1;
                    924:                }
                    925:                blk.len = MAX_CHUNK; /* Doesn't matter. */
                    926:                LOG3(sess, "%s: not mapped", u->fl[u->idx].path);
                    927:        }
                    928:
1.4       deraadt   929:        assert(*fileinfd == -1);
1.1       benno     930:
                    931:        /* Make sure the block metadata buffer is big enough. */
                    932:
1.2       benno     933:        u->bufsz =
1.1       benno     934:             sizeof(int32_t) + /* identifier */
                    935:             sizeof(int32_t) + /* block count */
                    936:             sizeof(int32_t) + /* block length */
                    937:             sizeof(int32_t) + /* checksum length */
                    938:             sizeof(int32_t) + /* block remainder */
1.2       benno     939:             blk.blksz *
1.1       benno     940:             (sizeof(int32_t) + /* short checksum */
                    941:              blk.csum); /* long checksum */
                    942:
                    943:        if (u->bufsz > u->bufmax) {
1.4       deraadt   944:                if ((bufp = realloc(u->buf, u->bufsz)) == NULL) {
1.1       benno     945:                        ERR(sess, "realloc");
                    946:                        return -1;
                    947:                }
                    948:                u->buf = bufp;
                    949:                u->bufmax = u->bufsz;
                    950:        }
                    951:
                    952:        u->bufpos = pos = 0;
                    953:        io_buffer_int(sess, u->buf, &pos, u->bufsz, u->idx);
                    954:        io_buffer_int(sess, u->buf, &pos, u->bufsz, blk.blksz);
                    955:        io_buffer_int(sess, u->buf, &pos, u->bufsz, blk.len);
                    956:        io_buffer_int(sess, u->buf, &pos, u->bufsz, blk.csum);
                    957:        io_buffer_int(sess, u->buf, &pos, u->bufsz, blk.rem);
                    958:        for (i = 0; i < blk.blksz; i++) {
1.2       benno     959:                io_buffer_int(sess, u->buf, &pos, u->bufsz,
1.1       benno     960:                        blk.blks[i].chksum_short);
1.2       benno     961:                io_buffer_buf(sess, u->buf, &pos, u->bufsz,
1.1       benno     962:                        blk.blks[i].chksum_long, blk.csum);
                    963:        }
                    964:        assert(pos == u->bufsz);
                    965:
                    966:        /* Reenable the output poller and clean up. */
                    967:
                    968:        *fileoutfd = u->fdout;
                    969:        free(blk.blks);
                    970:        return 1;
                    971: }
                    972:
                    973: /*
                    974:  * Fix up the directory permissions and times post-order.
                    975:  * We can't fix up directory permissions in place because the server may
                    976:  * want us to have overly-tight permissions---say, those that don't
                    977:  * allow writing into the directory.
                    978:  * We also need to do our directory times post-order because making
                    979:  * files within the directory will change modification times.
                    980:  * Returns zero on failure, non-zero on success.
                    981:  */
                    982: int
                    983: rsync_uploader_tail(struct upload *u, struct sess *sess)
                    984: {
                    985:        size_t   i;
                    986:
                    987:
1.3       deraadt   988:        if (!sess->opts->preserve_times &&
                    989:             !sess->opts->preserve_perms)
1.1       benno     990:                return 1;
                    991:
                    992:        LOG2(sess, "fixing up directory times and permissions");
                    993:
                    994:        for (i = 0; i < u->flsz; i++)
                    995:                if (S_ISDIR(u->fl[i].st.mode))
1.3       deraadt   996:                        if (!post_dir(sess, u, i))
1.1       benno     997:                                return 0;
                    998:
                    999:        return 1;
                   1000: }