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