Annotation of src/usr.bin/rsync/uploader.c, Revision 1.19
1.19 ! deraadt 1: /* $Id: uploader.c,v 1.18 2019/03/18 15:33:21 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.1 benno 627: (sess->opts->preserve_perms &&
628: st.st_mode != f->st.mode)) {
629: rc = fchmodat(u->rootfd, f->path, f->st.mode, 0);
1.4 deraadt 630: if (rc == -1) {
1.1 benno 631: ERR(sess, "%s: fchmodat", f->path);
632: return 0;
633: }
634: LOG4(sess, "%s: updated mode", f->path);
635: }
636:
637: return 1;
638: }
639:
640: /*
641: * Try to open the file at the current index.
642: * If the file does not exist, returns with success.
643: * Return <0 on failure, 0 on success w/nothing to be done, >0 on
644: * success and the file needs attention.
645: */
646: static int
647: pre_file(const struct upload *p, int *filefd, struct sess *sess)
648: {
649: const struct flist *f;
650:
651: f = &p->fl[p->idx];
652: assert(S_ISREG(f->st.mode));
653:
654: if (sess->opts->dry_run) {
655: log_file(sess, f);
1.3 deraadt 656: if (!io_write_int(sess, p->fdout, p->idx)) {
1.1 benno 657: ERRX1(sess, "io_write_int");
658: return -1;
659: }
660: return 0;
661: }
662:
663: /*
664: * For non dry-run cases, we'll write the acknowledgement later
665: * in the rsync_uploader() function because we need to wait for
666: * the open() call to complete.
667: * If the call to openat() fails with ENOENT, there's a
668: * fast-path between here and the write function, so we won't do
669: * any blocking between now and then.
670: */
671:
672: *filefd = openat(p->rootfd, f->path,
673: O_RDONLY | O_NOFOLLOW | O_NONBLOCK, 0);
1.4 deraadt 674: if (*filefd != -1 || errno == ENOENT)
1.1 benno 675: return 1;
676: ERR(sess, "%s: openat", f->path);
677: return -1;
678: }
679:
680: /*
681: * Allocate an uploader object in the correct state to start.
682: * Returns NULL on failure or the pointer otherwise.
683: * On success, upload_free() must be called with the allocated pointer.
684: */
685: struct upload *
1.11 florian 686: upload_alloc(struct sess *sess, const char *root, int rootfd, int fdout,
1.1 benno 687: size_t clen, const struct flist *fl, size_t flsz, mode_t msk)
688: {
689: struct upload *p;
690:
1.4 deraadt 691: if ((p = calloc(1, sizeof(struct upload))) == NULL) {
1.1 benno 692: ERR(sess, "calloc");
693: return NULL;
694: }
695:
696: p->state = UPLOAD_FIND_NEXT;
697: p->oumask = msk;
1.11 florian 698: p->root = strdup(root);
699: if (p->root == NULL) {
700: ERR(sess, "strdup");
701: free(p);
702: return NULL;
703: }
1.1 benno 704: p->rootfd = rootfd;
705: p->csumlen = clen;
706: p->fdout = fdout;
707: p->fl = fl;
708: p->flsz = flsz;
709: p->newdir = calloc(flsz, sizeof(int));
1.4 deraadt 710: if (p->newdir == NULL) {
1.1 benno 711: ERR(sess, "calloc");
1.11 florian 712: free(p->root);
1.1 benno 713: free(p);
714: return NULL;
715: }
716: return p;
717: }
718:
719: /*
720: * Perform all cleanups and free.
721: * Passing a NULL to this function is ok.
722: */
723: void
724: upload_free(struct upload *p)
725: {
726:
1.4 deraadt 727: if (p == NULL)
1.1 benno 728: return;
1.11 florian 729: free(p->root);
1.1 benno 730: free(p->newdir);
731: free(p->buf);
732: free(p);
733: }
734:
735: /*
736: * Iterates through all available files and conditionally gets the file
737: * ready for processing to check whether it's up to date.
738: * If not up to date or empty, sends file information to the sender.
739: * If returns 0, we've processed all files there are to process.
740: * If returns >0, we're waiting for POLLIN or POLLOUT data.
741: * Otherwise returns <0, which is an error.
742: */
743: int
1.2 benno 744: rsync_uploader(struct upload *u, int *fileinfd,
1.1 benno 745: struct sess *sess, int *fileoutfd)
746: {
1.5 florian 747: struct blkset blk;
748: struct stat st;
749: void *map, *bufp;
750: size_t i, mapsz, pos, sz;
751: off_t offs;
752: int c;
753: const struct flist *f;
1.1 benno 754:
755: /* This should never get called. */
756:
1.4 deraadt 757: assert(u->state != UPLOAD_FINISHED);
1.1 benno 758:
759: /*
760: * If we have an upload in progress, then keep writing until the
761: * buffer has been fully written.
762: * We must only have the output file descriptor working and also
763: * have a valid buffer to write.
764: */
765:
1.4 deraadt 766: if (u->state == UPLOAD_WRITE_LOCAL) {
1.14 deraadt 767: assert(u->buf != NULL);
1.4 deraadt 768: assert(*fileoutfd != -1);
769: assert(*fileinfd == -1);
1.1 benno 770:
771: /*
772: * Unfortunately, we need to chunk these: if we're
773: * the server side of things, then we're multiplexing
774: * output and need to wrap this in chunks.
775: * This is a major deficiency of rsync.
776: * FIXME: add a "fast-path" mode that simply dumps out
777: * the buffer non-blocking if we're not mplexing.
778: */
779:
780: if (u->bufpos < u->bufsz) {
781: sz = MAX_CHUNK < (u->bufsz - u->bufpos) ?
782: MAX_CHUNK : (u->bufsz - u->bufpos);
1.2 benno 783: c = io_write_buf(sess, u->fdout,
1.1 benno 784: u->buf + u->bufpos, sz);
1.4 deraadt 785: if (c == 0) {
1.1 benno 786: ERRX1(sess, "io_write_nonblocking");
787: return -1;
788: }
789: u->bufpos += sz;
790: if (u->bufpos < u->bufsz)
791: return 1;
792: }
793:
1.2 benno 794: /*
1.1 benno 795: * Let the UPLOAD_FIND_NEXT state handle things if we
796: * finish, as we'll need to write a POLLOUT message and
797: * not have a writable descriptor yet.
798: */
799:
800: u->state = UPLOAD_FIND_NEXT;
801: u->idx++;
802: return 1;
803: }
804:
805: /*
806: * If we invoke the uploader without a file currently open, then
807: * we iterate through til the next available regular file and
808: * start the opening process.
809: * This means we must have the output file descriptor working.
810: */
811:
1.4 deraadt 812: if (u->state == UPLOAD_FIND_NEXT) {
813: assert(*fileinfd == -1);
814: assert(*fileoutfd != -1);
1.1 benno 815:
816: for ( ; u->idx < u->flsz; u->idx++) {
817: if (S_ISDIR(u->fl[u->idx].st.mode))
818: c = pre_dir(u, sess);
819: else if (S_ISLNK(u->fl[u->idx].st.mode))
820: c = pre_link(u, sess);
821: else if (S_ISREG(u->fl[u->idx].st.mode))
822: c = pre_file(u, fileinfd, sess);
1.11 florian 823: else if (S_ISBLK(u->fl[u->idx].st.mode) ||
824: S_ISCHR(u->fl[u->idx].st.mode))
825: c = pre_dev(u, sess);
826: else if (S_ISFIFO(u->fl[u->idx].st.mode))
827: c = pre_fifo(u, sess);
828: else if (S_ISSOCK(u->fl[u->idx].st.mode))
829: c = pre_sock(u, sess);
1.1 benno 830: else
831: c = 0;
832:
833: if (c < 0)
834: return -1;
835: else if (c > 0)
836: break;
837: }
838:
1.2 benno 839: /*
1.1 benno 840: * Whether we've finished writing files or not, we
841: * disable polling on the output channel.
842: */
843:
844: *fileoutfd = -1;
845: if (u->idx == u->flsz) {
1.4 deraadt 846: assert(*fileinfd == -1);
1.3 deraadt 847: if (!io_write_int(sess, u->fdout, -1)) {
1.1 benno 848: ERRX1(sess, "io_write_int");
849: return -1;
850: }
851: u->state = UPLOAD_FINISHED;
852: LOG4(sess, "uploader: finished");
853: return 0;
854: }
855:
856: /* Go back to the event loop, if necessary. */
857:
1.14 deraadt 858: u->state = (*fileinfd == -1) ?
1.17 benno 859: UPLOAD_WRITE_LOCAL : UPLOAD_READ_LOCAL;
1.4 deraadt 860: if (u->state == UPLOAD_READ_LOCAL)
1.1 benno 861: return 1;
862: }
863:
1.2 benno 864: /*
1.1 benno 865: * If an input file is open, stat it and see if it's already up
866: * to date, in which case close it and go to the next one.
867: * Either way, we don't have a write channel open.
868: */
869:
1.4 deraadt 870: if (u->state == UPLOAD_READ_LOCAL) {
871: assert(*fileinfd != -1);
872: assert(*fileoutfd == -1);
1.5 florian 873: f = &u->fl[u->idx];
1.1 benno 874:
1.4 deraadt 875: if (fstat(*fileinfd, &st) == -1) {
1.5 florian 876: ERR(sess, "%s: fstat", f->path);
1.1 benno 877: close(*fileinfd);
878: *fileinfd = -1;
879: return -1;
1.3 deraadt 880: } else if (!S_ISREG(st.st_mode)) {
1.5 florian 881: ERRX(sess, "%s: not regular", f->path);
1.1 benno 882: close(*fileinfd);
883: *fileinfd = -1;
884: return -1;
885: }
886:
1.5 florian 887: if (st.st_size == f->st.size &&
888: st.st_mtime == f->st.mtime) {
889: LOG3(sess, "%s: skipping: up to date", f->path);
890: if (!rsync_set_metadata
891: (sess, 0, *fileinfd, f, f->path)) {
892: ERRX1(sess, "rsync_set_metadata");
893: close(*fileinfd);
894: *fileinfd = -1;
895: return -1;
896: }
1.1 benno 897: close(*fileinfd);
898: *fileinfd = -1;
899: *fileoutfd = u->fdout;
900: u->state = UPLOAD_FIND_NEXT;
901: u->idx++;
902: return 1;
903: }
904:
905: /* Fallthrough... */
906:
907: u->state = UPLOAD_WRITE_LOCAL;
908: }
909:
910: /* Initialies our blocks. */
911:
1.4 deraadt 912: assert(u->state == UPLOAD_WRITE_LOCAL);
1.1 benno 913: memset(&blk, 0, sizeof(struct blkset));
914: blk.csum = u->csumlen;
915:
1.4 deraadt 916: if (*fileinfd != -1 && st.st_size > 0) {
1.1 benno 917: mapsz = st.st_size;
1.7 deraadt 918: map = mmap(NULL, mapsz, PROT_READ, MAP_SHARED, *fileinfd, 0);
1.4 deraadt 919: if (map == MAP_FAILED) {
1.17 benno 920: ERR(sess, "%s: mmap", u->fl[u->idx].path);
1.1 benno 921: close(*fileinfd);
922: *fileinfd = -1;
923: return -1;
924: }
925:
926: init_blkset(&blk, st.st_size);
927: assert(blk.blksz);
928:
929: blk.blks = calloc(blk.blksz, sizeof(struct blk));
1.4 deraadt 930: if (blk.blks == NULL) {
1.1 benno 931: ERR(sess, "calloc");
932: munmap(map, mapsz);
933: close(*fileinfd);
934: *fileinfd = -1;
935: return -1;
936: }
937:
938: offs = 0;
939: for (i = 0; i < blk.blksz; i++) {
1.2 benno 940: init_blk(&blk.blks[i],
1.1 benno 941: &blk, offs, i, map, sess);
942: offs += blk.len;
943: }
944:
945: munmap(map, mapsz);
946: close(*fileinfd);
947: *fileinfd = -1;
948: LOG3(sess, "%s: mapped %jd B with %zu blocks",
1.19 ! deraadt 949: u->fl[u->idx].path, (intmax_t)blk.size,
! 950: blk.blksz);
1.1 benno 951: } else {
1.4 deraadt 952: if (*fileinfd != -1) {
1.1 benno 953: close(*fileinfd);
954: *fileinfd = -1;
955: }
956: blk.len = MAX_CHUNK; /* Doesn't matter. */
957: LOG3(sess, "%s: not mapped", u->fl[u->idx].path);
958: }
959:
1.4 deraadt 960: assert(*fileinfd == -1);
1.1 benno 961:
962: /* Make sure the block metadata buffer is big enough. */
963:
1.2 benno 964: u->bufsz =
1.1 benno 965: sizeof(int32_t) + /* identifier */
966: sizeof(int32_t) + /* block count */
967: sizeof(int32_t) + /* block length */
968: sizeof(int32_t) + /* checksum length */
969: sizeof(int32_t) + /* block remainder */
1.2 benno 970: blk.blksz *
1.1 benno 971: (sizeof(int32_t) + /* short checksum */
972: blk.csum); /* long checksum */
973:
974: if (u->bufsz > u->bufmax) {
1.4 deraadt 975: if ((bufp = realloc(u->buf, u->bufsz)) == NULL) {
1.1 benno 976: ERR(sess, "realloc");
977: return -1;
978: }
979: u->buf = bufp;
980: u->bufmax = u->bufsz;
981: }
982:
983: u->bufpos = pos = 0;
984: io_buffer_int(sess, u->buf, &pos, u->bufsz, u->idx);
985: io_buffer_int(sess, u->buf, &pos, u->bufsz, blk.blksz);
986: io_buffer_int(sess, u->buf, &pos, u->bufsz, blk.len);
987: io_buffer_int(sess, u->buf, &pos, u->bufsz, blk.csum);
988: io_buffer_int(sess, u->buf, &pos, u->bufsz, blk.rem);
989: for (i = 0; i < blk.blksz; i++) {
1.2 benno 990: io_buffer_int(sess, u->buf, &pos, u->bufsz,
1.1 benno 991: blk.blks[i].chksum_short);
1.2 benno 992: io_buffer_buf(sess, u->buf, &pos, u->bufsz,
1.1 benno 993: blk.blks[i].chksum_long, blk.csum);
994: }
995: assert(pos == u->bufsz);
996:
997: /* Reenable the output poller and clean up. */
998:
999: *fileoutfd = u->fdout;
1000: free(blk.blks);
1001: return 1;
1002: }
1003:
1004: /*
1005: * Fix up the directory permissions and times post-order.
1006: * We can't fix up directory permissions in place because the server may
1007: * want us to have overly-tight permissions---say, those that don't
1008: * allow writing into the directory.
1009: * We also need to do our directory times post-order because making
1010: * files within the directory will change modification times.
1011: * Returns zero on failure, non-zero on success.
1012: */
1013: int
1014: rsync_uploader_tail(struct upload *u, struct sess *sess)
1015: {
1016: size_t i;
1017:
1018:
1.3 deraadt 1019: if (!sess->opts->preserve_times &&
1020: !sess->opts->preserve_perms)
1.1 benno 1021: return 1;
1022:
1023: LOG2(sess, "fixing up directory times and permissions");
1024:
1025: for (i = 0; i < u->flsz; i++)
1026: if (S_ISDIR(u->fl[i].st.mode))
1.3 deraadt 1027: if (!post_dir(sess, u, i))
1.1 benno 1028: return 0;
1029:
1030: return 1;
1031: }