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