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