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