[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.19

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