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