Annotation of src/usr.bin/rsync/sender.c, Revision 1.28.2.1
1.28.2.1! benno 1: /* $Id: sender.c,v 1.28 2021/04/05 18:17:37 deraadt Exp $ */
1.1 benno 2: /*
3: * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
4: *
5: * Permission to use, copy, modify, and distribute this software for any
6: * purpose with or without fee is hereby granted, provided that the above
7: * copyright notice and this permission notice appear in all copies.
8: *
9: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16: */
1.8 florian 17: #include <sys/mman.h>
18: #include <sys/queue.h>
1.1 benno 19: #include <sys/stat.h>
20:
21: #include <assert.h>
1.8 florian 22: #include <fcntl.h>
1.1 benno 23: #include <inttypes.h>
1.8 florian 24: #include <poll.h>
1.1 benno 25: #include <stdlib.h>
26: #include <string.h>
27: #include <unistd.h>
28:
1.9 florian 29: #include <openssl/md4.h>
30:
1.1 benno 31: #include "extern.h"
32:
33: /*
1.8 florian 34: * A request from the receiver to download updated file data.
35: */
36: struct send_dl {
1.21 deraadt 37: int32_t idx; /* index in our file list */
38: struct blkset *blks; /* the sender's block information */
39: TAILQ_ENTRY(send_dl) entries;
1.8 florian 40: };
41:
42: /*
43: * The current file being "updated": sent from sender to receiver.
44: * If there is no file being uploaded, "cur" is NULL.
45: */
46: struct send_up {
47: struct send_dl *cur; /* file being updated or NULL */
48: struct blkstat stat; /* status of file being updated */
49: };
50:
51: TAILQ_HEAD(send_dlq, send_dl);
52:
53: /*
54: * We have finished updating the receiver's file with sender data.
55: * Deallocate and wipe clean all resources required for that.
56: */
57: static void
58: send_up_reset(struct send_up *p)
59: {
60:
1.13 deraadt 61: assert(p != NULL);
1.8 florian 62:
63: /* Free the download request, if applicable. */
64:
65: if (p->cur != NULL) {
66: free(p->cur->blks);
67: free(p->cur);
68: p->cur = NULL;
69: }
70:
71: /* If we mapped a file for scanning, unmap it and close. */
72:
73: if (p->stat.map != MAP_FAILED)
74: munmap(p->stat.map, p->stat.mapsz);
75:
76: p->stat.map = MAP_FAILED;
77: p->stat.mapsz = 0;
78:
79: if (p->stat.fd != -1)
80: close(p->stat.fd);
81:
82: p->stat.fd = -1;
83:
84: /* Now clear the in-transfer information. */
85:
86: p->stat.offs = 0;
87: p->stat.hint = 0;
1.9 florian 88: p->stat.curst = BLKSTAT_NONE;
1.16 benno 89: }
90:
91: /*
92: * This is the bulk of the sender work.
93: * Here we tend to an output buffer that responds to receiver requests
94: * for data.
95: * This does not act upon the output descriptor itself so as to avoid
96: * blocking, which otherwise would deadlock the protocol.
97: * Returns zero on failure, non-zero on success.
98: */
99: static int
100: send_up_fsm(struct sess *sess, size_t *phase,
101: struct send_up *up, void **wb, size_t *wbsz, size_t *wbmax,
102: const struct flist *fl)
103: {
104: size_t pos = 0, isz = sizeof(int32_t),
105: dsz = MD4_DIGEST_LENGTH;
106: unsigned char fmd[MD4_DIGEST_LENGTH];
107: off_t sz;
108: char buf[20];
109:
110: switch (up->stat.curst) {
111: case BLKSTAT_DATA:
112: /*
113: * A data segment to be written: buffer both the length
114: * and the data.
115: * If we've finished the transfer, move on to the token;
116: * otherwise, keep sending data.
117: */
118:
119: sz = MINIMUM(MAX_CHUNK,
120: up->stat.curlen - up->stat.curpos);
121: if (!io_lowbuffer_alloc(sess, wb, wbsz, wbmax, isz)) {
1.22 benno 122: ERRX1("io_lowbuffer_alloc");
1.16 benno 123: return 0;
124: }
125: io_lowbuffer_int(sess, *wb, &pos, *wbsz, sz);
126: if (!io_lowbuffer_alloc(sess, wb, wbsz, wbmax, sz)) {
1.22 benno 127: ERRX1("io_lowbuffer_alloc");
1.16 benno 128: return 0;
129: }
130: io_lowbuffer_buf(sess, *wb, &pos, *wbsz,
131: up->stat.map + up->stat.curpos, sz);
132:
133: up->stat.curpos += sz;
134: if (up->stat.curpos == up->stat.curlen)
135: up->stat.curst = BLKSTAT_TOK;
136: return 1;
137: case BLKSTAT_TOK:
138: /*
139: * The data token following (maybe) a data segment.
140: * These can also come standalone if, say, the file's
141: * being fully written.
142: * It's followed by a hash or another data segment,
143: * depending on the token.
144: */
145:
146: if (!io_lowbuffer_alloc(sess, wb, wbsz, wbmax, isz)) {
1.22 benno 147: ERRX1("io_lowbuffer_alloc");
1.16 benno 148: return 0;
149: }
150: io_lowbuffer_int(sess, *wb,
151: &pos, *wbsz, up->stat.curtok);
152: up->stat.curst = up->stat.curtok ?
153: BLKSTAT_NEXT : BLKSTAT_HASH;
154: return 1;
155: case BLKSTAT_HASH:
156: /*
157: * The hash following transmission of all file contents.
158: * This is always followed by the state that we're
159: * finished with the file.
160: */
161:
162: hash_file(up->stat.map, up->stat.mapsz, fmd, sess);
163: if (!io_lowbuffer_alloc(sess, wb, wbsz, wbmax, dsz)) {
1.22 benno 164: ERRX1("io_lowbuffer_alloc");
1.16 benno 165: return 0;
166: }
167: io_lowbuffer_buf(sess, *wb, &pos, *wbsz, fmd, dsz);
168: up->stat.curst = BLKSTAT_DONE;
169: return 1;
170: case BLKSTAT_DONE:
171: /*
172: * The data has been written.
173: * Clear our current send file and allow the block below
174: * to find another.
175: */
176:
1.17 benno 177: if (!sess->opts->dry_run)
1.22 benno 178: LOG3("%s: flushed %jd KB total, %.2f%% uploaded",
1.20 deraadt 179: fl[up->cur->idx].path,
180: (intmax_t)up->stat.total / 1024,
181: 100.0 * up->stat.dirty / up->stat.total);
1.16 benno 182: send_up_reset(up);
183: return 1;
184: case BLKSTAT_PHASE:
185: /*
186: * This is where we actually stop the algorithm: we're
187: * already at the second phase.
188: */
189:
190: send_up_reset(up);
191: (*phase)++;
192: return 1;
193: case BLKSTAT_NEXT:
194: /*
195: * Our last case: we need to find the
196: * next block (and token) to transmit to
197: * the receiver.
198: * These will drive the finite state
199: * machine in the first few conditional
200: * blocks of this set.
201: */
202:
203: assert(up->stat.fd != -1);
204: blk_match(sess, up->cur->blks,
205: fl[up->cur->idx].path, &up->stat);
206: return 1;
207: case BLKSTAT_NONE:
208: break;
209: }
210:
211: assert(BLKSTAT_NONE == up->stat.curst);
212:
213: /*
214: * We've either hit the phase change following the last file (or
215: * start, or prior phase change), or we need to prime the next
216: * file for transmission.
217: * We special-case dry-run mode.
218: */
219:
220: if (up->cur->idx < 0) {
221: if (!io_lowbuffer_alloc(sess, wb, wbsz, wbmax, isz)) {
1.22 benno 222: ERRX1("io_lowbuffer_alloc");
1.16 benno 223: return 0;
224: }
225: io_lowbuffer_int(sess, *wb, &pos, *wbsz, -1);
226:
227: if (sess->opts->server && sess->rver > 27) {
228: if (!io_lowbuffer_alloc(sess,
229: wb, wbsz, wbmax, isz)) {
1.22 benno 230: ERRX1("io_lowbuffer_alloc");
1.16 benno 231: return 0;
232: }
233: io_lowbuffer_int(sess, *wb, &pos, *wbsz, -1);
234: }
235: up->stat.curst = BLKSTAT_PHASE;
236: } else if (sess->opts->dry_run) {
237: if (!sess->opts->server)
1.22 benno 238: LOG1("%s", fl[up->cur->idx].wpath);
1.16 benno 239:
240: if (!io_lowbuffer_alloc(sess, wb, wbsz, wbmax, isz)) {
1.22 benno 241: ERRX1("io_lowbuffer_alloc");
1.16 benno 242: return 0;
243: }
244: io_lowbuffer_int(sess, *wb, &pos, *wbsz, up->cur->idx);
1.17 benno 245: up->stat.curst = BLKSTAT_DONE;
1.16 benno 246: } else {
247: assert(up->stat.fd != -1);
248:
249: /*
250: * FIXME: use the nice output of log_file() and so on in
251: * downloader.c, which means moving this into
252: * BLKSTAT_DONE instead of having it be here.
253: */
254:
255: if (!sess->opts->server)
1.22 benno 256: LOG1("%s", fl[up->cur->idx].wpath);
1.16 benno 257:
258: if (!io_lowbuffer_alloc(sess, wb, wbsz, wbmax, 20)) {
1.22 benno 259: ERRX1("io_lowbuffer_alloc");
1.16 benno 260: return 0;
261: }
262: assert(sizeof(buf) == 20);
1.23 benno 263: blk_recv_ack(buf, up->cur->blks, up->cur->idx);
1.16 benno 264: io_lowbuffer_buf(sess, *wb, &pos, *wbsz, buf, 20);
265:
1.22 benno 266: LOG3("%s: primed for %jd B total",
1.20 deraadt 267: fl[up->cur->idx].path, (intmax_t)up->cur->blks->size);
1.16 benno 268: up->stat.curst = BLKSTAT_NEXT;
269: }
270:
271: return 1;
1.8 florian 272: }
273:
274: /*
275: * Enqueue a download request, getting it off the read channel as
276: * quickly a possible.
277: * This frees up the read channel for further incoming requests.
278: * We'll handle each element in turn, up to and including the last
279: * request (phase change), which is always a -1 idx.
280: * Returns zero on failure, non-zero on success.
281: */
282: static int
283: send_dl_enqueue(struct sess *sess, struct send_dlq *q,
284: int32_t idx, const struct flist *fl, size_t flsz, int fd)
285: {
286: struct send_dl *s;
1.15 benno 287:
1.8 florian 288: /* End-of-phase marker. */
289:
290: if (idx == -1) {
291: if ((s = calloc(1, sizeof(struct send_dl))) == NULL) {
1.22 benno 292: ERR("calloc");
1.8 florian 293: return 0;
294: }
295: s->idx = -1;
296: s->blks = NULL;
297: TAILQ_INSERT_TAIL(q, s, entries);
298: return 1;
299: }
300:
301: /* Validate the index. */
1.15 benno 302:
1.8 florian 303: if (idx < 0 || (uint32_t)idx >= flsz) {
1.22 benno 304: ERRX("file index out of bounds: invalid %d out of %zu",
1.20 deraadt 305: idx, flsz);
1.8 florian 306: return 0;
307: } else if (S_ISDIR(fl[idx].st.mode)) {
1.22 benno 308: ERRX("blocks requested for "
1.8 florian 309: "directory: %s", fl[idx].path);
310: return 0;
311: } else if (S_ISLNK(fl[idx].st.mode)) {
1.22 benno 312: ERRX("blocks requested for "
1.8 florian 313: "symlink: %s", fl[idx].path);
314: return 0;
315: } else if (!S_ISREG(fl[idx].st.mode)) {
1.22 benno 316: ERRX("blocks requested for "
1.8 florian 317: "special: %s", fl[idx].path);
318: return 0;
319: }
320:
321: if ((s = calloc(1, sizeof(struct send_dl))) == NULL) {
1.22 benno 322: ERR("callloc");
1.8 florian 323: return 0;
324: }
325: s->idx = idx;
326: s->blks = NULL;
327: TAILQ_INSERT_TAIL(q, s, entries);
328:
1.10 florian 329: /*
1.8 florian 330: * This blocks til the full blockset has been read.
331: * That's ok, because the most important thing is getting data
332: * off the wire.
333: */
334:
335: if (!sess->opts->dry_run) {
336: s->blks = blk_recv(sess, fd, fl[idx].path);
337: if (s->blks == NULL) {
1.22 benno 338: ERRX1("blk_recv");
1.8 florian 339: return 0;
340: }
341: }
342: return 1;
343: }
344:
345: /*
1.1 benno 346: * A client sender manages the read-only source files and sends data to
347: * the receiver as requested.
348: * First it sends its list of files, then it waits for the server to
349: * request updates to individual files.
1.8 florian 350: * It queues requests for updates as soon as it receives them.
1.1 benno 351: * Returns zero on failure, non-zero on success.
352: *
1.27 claudio 353: * Pledges: stdio, getpw, rpath.
1.1 benno 354: */
355: int
356: rsync_sender(struct sess *sess, int fdin,
357: int fdout, size_t argc, char **argv)
358: {
1.9 florian 359: struct flist *fl = NULL;
360: const struct flist *f;
1.28.2.1! benno 361: size_t i, flsz = 0, phase = 0;
1.9 florian 362: int rc = 0, c;
363: int32_t idx;
364: struct pollfd pfd[3];
365: struct send_dlq sdlq;
366: struct send_dl *dl;
367: struct send_up up;
368: struct stat st;
369: void *wbuf = NULL;
1.16 benno 370: size_t wbufpos = 0, wbufsz = 0, wbufmax = 0;
1.9 florian 371: ssize_t ssz;
1.1 benno 372:
1.27 claudio 373: if (pledge("stdio getpw rpath", NULL) == -1) {
1.22 benno 374: ERR("pledge");
1.1 benno 375: return 0;
376: }
377:
1.8 florian 378: memset(&up, 0, sizeof(struct send_up));
379: TAILQ_INIT(&sdlq);
380: up.stat.fd = -1;
381: up.stat.map = MAP_FAILED;
1.24 florian 382: up.stat.blktab = blkhash_alloc();
1.8 florian 383:
1.1 benno 384: /*
385: * Generate the list of files we want to send from our
386: * command-line input.
387: * This will also remove all invalid files.
388: */
389:
1.4 deraadt 390: if (!flist_gen(sess, argc, argv, &fl, &flsz)) {
1.22 benno 391: ERRX1("flist_gen");
1.1 benno 392: goto out;
393: }
394:
395: /* Client sends zero-length exclusions if deleting. */
1.28.2.1! benno 396: if (!sess->opts->server && sess->opts->del)
! 397: send_rules(sess, fdout);
1.1 benno 398:
1.2 benno 399: /*
1.1 benno 400: * Then the file list in any mode.
401: * Finally, the IO error (always zero for us).
402: */
1.2 benno 403:
1.4 deraadt 404: if (!flist_send(sess, fdin, fdout, fl, flsz)) {
1.22 benno 405: ERRX1("flist_send");
1.1 benno 406: goto out;
1.4 deraadt 407: } else if (!io_write_int(sess, fdout, 0)) {
1.22 benno 408: ERRX1("io_write_int");
1.1 benno 409: goto out;
1.2 benno 410: }
1.1 benno 411:
412: /* Exit if we're the server with zero files. */
413:
1.5 deraadt 414: if (flsz == 0 && sess->opts->server) {
1.22 benno 415: WARNX("sender has empty file list: exiting");
1.1 benno 416: rc = 1;
417: goto out;
1.4 deraadt 418: } else if (!sess->opts->server)
1.22 benno 419: LOG1("Transfer starting: %zu files", flsz);
1.1 benno 420:
421: /*
422: * If we're the server, read our exclusion list.
423: * This is always 0 for now.
424: */
425:
1.28.2.1! benno 426: if (sess->opts->server)
! 427: recv_rules(sess, fdin);
1.1 benno 428:
1.10 florian 429: /*
1.8 florian 430: * Set up our poll events.
431: * We start by polling only in receiver requests, enabling other
432: * poll events on demand.
1.1 benno 433: */
434:
1.8 florian 435: pfd[0].fd = fdin; /* from receiver */
436: pfd[0].events = POLLIN;
437: pfd[1].fd = -1; /* to receiver */
438: pfd[1].events = POLLOUT;
439: pfd[2].fd = -1; /* from local file */
440: pfd[2].events = POLLIN;
441:
1.1 benno 442: for (;;) {
1.8 florian 443: assert(pfd[0].fd != -1);
1.26 claudio 444: if ((c = poll(pfd, 3, poll_timeout)) == -1) {
1.22 benno 445: ERR("poll");
1.8 florian 446: goto out;
447: } else if (c == 0) {
1.22 benno 448: ERRX("poll: timeout");
1.1 benno 449: goto out;
450: }
1.8 florian 451: for (i = 0; i < 3; i++)
452: if (pfd[i].revents & (POLLERR|POLLNVAL)) {
1.22 benno 453: ERRX("poll: bad fd");
1.8 florian 454: goto out;
455: } else if (pfd[i].revents & POLLHUP) {
1.22 benno 456: ERRX("poll: hangup");
1.8 florian 457: goto out;
458: }
459:
1.1 benno 460: /*
1.8 florian 461: * If we have a request coming down off the wire, pull
462: * it in as quickly as possible into our buffer.
1.18 benno 463: * Start by seeing if we have a log message.
464: * If we do, pop it off, then see if we have anything
465: * left and hit it again if so (read priority).
1.1 benno 466: */
467:
1.19 benno 468: if (sess->mplex_reads && (pfd[0].revents & POLLIN)) {
1.18 benno 469: if (!io_read_flush(sess, fdin)) {
1.22 benno 470: ERRX1("io_read_flush");
1.18 benno 471: goto out;
472: } else if (sess->mplex_read_remain == 0) {
1.23 benno 473: c = io_read_check(fdin);
1.8 florian 474: if (c < 0) {
1.22 benno 475: ERRX1("io_read_check");
1.8 florian 476: goto out;
1.18 benno 477: } else if (c > 0)
478: continue;
479: pfd[0].revents &= ~POLLIN;
480: }
481: }
482:
483: /*
484: * Now that we've handled the log messages, we're left
485: * here if we have any actual data coming down.
486: * Enqueue message requests, then loop again if we see
487: * more data (read priority).
488: */
489:
490: if (pfd[0].revents & POLLIN) {
491: if (!io_read_int(sess, fdin, &idx)) {
1.22 benno 492: ERRX1("io_read_int");
1.18 benno 493: goto out;
1.8 florian 494: }
1.18 benno 495: if (!send_dl_enqueue(sess,
496: &sdlq, idx, fl, flsz, fdin)) {
1.22 benno 497: ERRX1("send_dl_enqueue");
1.18 benno 498: goto out;
499: }
1.23 benno 500: c = io_read_check(fdin);
1.18 benno 501: if (c < 0) {
1.22 benno 502: ERRX1("io_read_check");
1.18 benno 503: goto out;
504: } else if (c > 0)
505: continue;
506: }
1.8 florian 507:
508: /*
1.9 florian 509: * One of our local files has been opened in response
510: * to a receiver request and now we can map it.
1.8 florian 511: * We'll respond to the event by looking at the map when
512: * the writer is available.
513: * Here we also enable the poll event for output.
514: */
515:
516: if (pfd[2].revents & POLLIN) {
517: assert(up.cur != NULL);
518: assert(up.stat.fd != -1);
519: assert(up.stat.map == MAP_FAILED);
520: assert(up.stat.mapsz == 0);
1.9 florian 521: f = &fl[up.cur->idx];
1.8 florian 522:
523: if (fstat(up.stat.fd, &st) == -1) {
1.22 benno 524: ERR("%s: fstat", f->path);
1.1 benno 525: goto out;
526: }
527:
1.8 florian 528: /*
529: * If the file is zero-length, the map will
530: * fail, but either way we want to unset that
1.9 florian 531: * we're waiting for the file to open and set
532: * that we're ready for the output channel.
1.8 florian 533: */
534:
535: if ((up.stat.mapsz = st.st_size) > 0) {
1.9 florian 536: up.stat.map = mmap(NULL,
537: up.stat.mapsz, PROT_READ,
538: MAP_SHARED, up.stat.fd, 0);
1.8 florian 539: if (up.stat.map == MAP_FAILED) {
1.22 benno 540: ERR("%s: mmap", f->path);
1.8 florian 541: goto out;
542: }
1.9 florian 543: }
544:
1.8 florian 545: pfd[2].fd = -1;
546: pfd[1].fd = fdout;
547: }
548:
549: /*
1.9 florian 550: * If we have buffers waiting to write, write them out
551: * as soon as we can in a non-blocking fashion.
552: * We must not be waiting for any local files.
553: * ALL WRITES MUST HAPPEN HERE.
554: * This keeps the sender deadlock-free.
1.8 florian 555: */
1.1 benno 556:
1.9 florian 557: if ((pfd[1].revents & POLLOUT) && wbufsz > 0) {
558: assert(pfd[2].fd == -1);
559: assert(wbufsz - wbufpos);
1.28 deraadt 560: ssz = write(fdout, wbuf + wbufpos, wbufsz - wbufpos);
1.25 deraadt 561: if (ssz == -1) {
1.22 benno 562: ERR("write");
1.9 florian 563: goto out;
564: }
565: wbufpos += ssz;
566: if (wbufpos == wbufsz)
567: wbufpos = wbufsz = 0;
568: pfd[1].revents &= ~POLLOUT;
569:
570: /* This is usually in io.c... */
571:
572: sess->total_write += ssz;
573: }
574:
1.16 benno 575: /*
576: * Engage the FSM for the current transfer.
577: * If our phase changes, stop processing.
578: */
579:
580: if (pfd[1].revents & POLLOUT && up.cur != NULL) {
1.8 florian 581: assert(pfd[2].fd == -1);
1.13 deraadt 582: assert(wbufpos == 0 && wbufsz == 0);
1.16 benno 583: if (!send_up_fsm(sess, &phase,
584: &up, &wbuf, &wbufsz, &wbufmax, fl)) {
1.22 benno 585: ERRX1("send_up_fsm");
1.16 benno 586: goto out;
587: } else if (phase > 1)
588: break;
1.1 benno 589: }
590:
591: /*
1.8 florian 592: * Incoming queue management.
593: * If we have no queue component that we're waiting on,
594: * then pull off the receiver-request queue and start
595: * processing the request.
1.1 benno 596: */
597:
1.8 florian 598: if (up.cur == NULL) {
599: assert(pfd[2].fd == -1);
600: assert(up.stat.fd == -1);
601: assert(up.stat.map == MAP_FAILED);
602: assert(up.stat.mapsz == 0);
1.9 florian 603: assert(wbufsz == 0 && wbufpos == 0);
604: pfd[1].fd = -1;
605:
606: /*
607: * If there's nothing in the queue, then keep
608: * the output channel disabled and wait for
609: * whatever comes next from the reader.
610: */
1.8 florian 611:
612: if ((up.cur = TAILQ_FIRST(&sdlq)) == NULL)
613: continue;
1.24 florian 614: TAILQ_REMOVE(&sdlq, up.cur, entries);
615:
616: /* Hash our blocks. */
1.9 florian 617:
1.24 florian 618: blkhash_set(up.stat.blktab, up.cur->blks);
1.8 florian 619:
1.10 florian 620: /*
1.9 florian 621: * End of phase: enable channel to receiver.
622: * We'll need our output buffer enabled in order
623: * to process this event.
624: */
1.8 florian 625:
626: if (up.cur->idx == -1) {
627: pfd[1].fd = fdout;
628: continue;
629: }
1.15 benno 630:
1.10 florian 631: /*
1.9 florian 632: * Non-blocking open of file.
633: * This will be picked up in the state machine
634: * block of not being primed.
635: */
1.1 benno 636:
1.9 florian 637: up.stat.fd = open(fl[up.cur->idx].path,
1.8 florian 638: O_RDONLY|O_NONBLOCK, 0);
639: if (up.stat.fd == -1) {
1.22 benno 640: ERR("%s: open", fl[up.cur->idx].path);
1.8 florian 641: goto out;
642: }
643: pfd[2].fd = up.stat.fd;
1.1 benno 644: }
645: }
646:
1.9 florian 647: if (!TAILQ_EMPTY(&sdlq)) {
1.22 benno 648: ERRX("phases complete with files still queued");
1.9 florian 649: goto out;
650: }
651:
1.4 deraadt 652: if (!sess_stats_send(sess, fdout)) {
1.22 benno 653: ERRX1("sess_stats_end");
1.1 benno 654: goto out;
655: }
656:
657: /* Final "goodbye" message. */
658:
1.4 deraadt 659: if (!io_read_int(sess, fdin, &idx)) {
1.22 benno 660: ERRX1("io_read_int");
1.1 benno 661: goto out;
1.5 deraadt 662: } else if (idx != -1) {
1.22 benno 663: ERRX("read incorrect update complete ack");
1.1 benno 664: goto out;
665: }
666:
1.22 benno 667: LOG2("sender finished updating");
1.1 benno 668: rc = 1;
669: out:
1.9 florian 670: send_up_reset(&up);
671: while ((dl = TAILQ_FIRST(&sdlq)) != NULL) {
1.16 benno 672: TAILQ_REMOVE(&sdlq, dl, entries);
1.9 florian 673: free(dl->blks);
674: free(dl);
675: }
1.1 benno 676: flist_free(fl, flsz);
1.9 florian 677: free(wbuf);
1.24 florian 678: blkhash_free(up.stat.blktab);
1.1 benno 679: return rc;
680: }