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