version 1.21, 2019/04/02 11:05:55 |
version 1.22, 2019/05/08 20:00:25 |
|
|
sz = MINIMUM(MAX_CHUNK, |
sz = MINIMUM(MAX_CHUNK, |
up->stat.curlen - up->stat.curpos); |
up->stat.curlen - up->stat.curpos); |
if (!io_lowbuffer_alloc(sess, wb, wbsz, wbmax, isz)) { |
if (!io_lowbuffer_alloc(sess, wb, wbsz, wbmax, isz)) { |
ERRX1(sess, "io_lowbuffer_alloc"); |
ERRX1("io_lowbuffer_alloc"); |
return 0; |
return 0; |
} |
} |
io_lowbuffer_int(sess, *wb, &pos, *wbsz, sz); |
io_lowbuffer_int(sess, *wb, &pos, *wbsz, sz); |
if (!io_lowbuffer_alloc(sess, wb, wbsz, wbmax, sz)) { |
if (!io_lowbuffer_alloc(sess, wb, wbsz, wbmax, sz)) { |
ERRX1(sess, "io_lowbuffer_alloc"); |
ERRX1("io_lowbuffer_alloc"); |
return 0; |
return 0; |
} |
} |
io_lowbuffer_buf(sess, *wb, &pos, *wbsz, |
io_lowbuffer_buf(sess, *wb, &pos, *wbsz, |
|
|
*/ |
*/ |
|
|
if (!io_lowbuffer_alloc(sess, wb, wbsz, wbmax, isz)) { |
if (!io_lowbuffer_alloc(sess, wb, wbsz, wbmax, isz)) { |
ERRX1(sess, "io_lowbuffer_alloc"); |
ERRX1("io_lowbuffer_alloc"); |
return 0; |
return 0; |
} |
} |
io_lowbuffer_int(sess, *wb, |
io_lowbuffer_int(sess, *wb, |
|
|
|
|
hash_file(up->stat.map, up->stat.mapsz, fmd, sess); |
hash_file(up->stat.map, up->stat.mapsz, fmd, sess); |
if (!io_lowbuffer_alloc(sess, wb, wbsz, wbmax, dsz)) { |
if (!io_lowbuffer_alloc(sess, wb, wbsz, wbmax, dsz)) { |
ERRX1(sess, "io_lowbuffer_alloc"); |
ERRX1("io_lowbuffer_alloc"); |
return 0; |
return 0; |
} |
} |
io_lowbuffer_buf(sess, *wb, &pos, *wbsz, fmd, dsz); |
io_lowbuffer_buf(sess, *wb, &pos, *wbsz, fmd, dsz); |
|
|
*/ |
*/ |
|
|
if (!sess->opts->dry_run) |
if (!sess->opts->dry_run) |
LOG3(sess, "%s: flushed %jd KB total, %.2f%% uploaded", |
LOG3("%s: flushed %jd KB total, %.2f%% uploaded", |
fl[up->cur->idx].path, |
fl[up->cur->idx].path, |
(intmax_t)up->stat.total / 1024, |
(intmax_t)up->stat.total / 1024, |
100.0 * up->stat.dirty / up->stat.total); |
100.0 * up->stat.dirty / up->stat.total); |
|
|
|
|
if (up->cur->idx < 0) { |
if (up->cur->idx < 0) { |
if (!io_lowbuffer_alloc(sess, wb, wbsz, wbmax, isz)) { |
if (!io_lowbuffer_alloc(sess, wb, wbsz, wbmax, isz)) { |
ERRX1(sess, "io_lowbuffer_alloc"); |
ERRX1("io_lowbuffer_alloc"); |
return 0; |
return 0; |
} |
} |
io_lowbuffer_int(sess, *wb, &pos, *wbsz, -1); |
io_lowbuffer_int(sess, *wb, &pos, *wbsz, -1); |
|
|
if (sess->opts->server && sess->rver > 27) { |
if (sess->opts->server && sess->rver > 27) { |
if (!io_lowbuffer_alloc(sess, |
if (!io_lowbuffer_alloc(sess, |
wb, wbsz, wbmax, isz)) { |
wb, wbsz, wbmax, isz)) { |
ERRX1(sess, "io_lowbuffer_alloc"); |
ERRX1("io_lowbuffer_alloc"); |
return 0; |
return 0; |
} |
} |
io_lowbuffer_int(sess, *wb, &pos, *wbsz, -1); |
io_lowbuffer_int(sess, *wb, &pos, *wbsz, -1); |
|
|
up->stat.curst = BLKSTAT_PHASE; |
up->stat.curst = BLKSTAT_PHASE; |
} else if (sess->opts->dry_run) { |
} else if (sess->opts->dry_run) { |
if (!sess->opts->server) |
if (!sess->opts->server) |
LOG1(sess, "%s", fl[up->cur->idx].wpath); |
LOG1("%s", fl[up->cur->idx].wpath); |
|
|
if (!io_lowbuffer_alloc(sess, wb, wbsz, wbmax, isz)) { |
if (!io_lowbuffer_alloc(sess, wb, wbsz, wbmax, isz)) { |
ERRX1(sess, "io_lowbuffer_alloc"); |
ERRX1("io_lowbuffer_alloc"); |
return 0; |
return 0; |
} |
} |
io_lowbuffer_int(sess, *wb, &pos, *wbsz, up->cur->idx); |
io_lowbuffer_int(sess, *wb, &pos, *wbsz, up->cur->idx); |
|
|
*/ |
*/ |
|
|
if (!sess->opts->server) |
if (!sess->opts->server) |
LOG1(sess, "%s", fl[up->cur->idx].wpath); |
LOG1("%s", fl[up->cur->idx].wpath); |
|
|
if (!io_lowbuffer_alloc(sess, wb, wbsz, wbmax, 20)) { |
if (!io_lowbuffer_alloc(sess, wb, wbsz, wbmax, 20)) { |
ERRX1(sess, "io_lowbuffer_alloc"); |
ERRX1("io_lowbuffer_alloc"); |
return 0; |
return 0; |
} |
} |
assert(sizeof(buf) == 20); |
assert(sizeof(buf) == 20); |
blk_recv_ack(sess, buf, up->cur->blks, up->cur->idx); |
blk_recv_ack(sess, buf, up->cur->blks, up->cur->idx); |
io_lowbuffer_buf(sess, *wb, &pos, *wbsz, buf, 20); |
io_lowbuffer_buf(sess, *wb, &pos, *wbsz, buf, 20); |
|
|
LOG3(sess, "%s: primed for %jd B total", |
LOG3("%s: primed for %jd B total", |
fl[up->cur->idx].path, (intmax_t)up->cur->blks->size); |
fl[up->cur->idx].path, (intmax_t)up->cur->blks->size); |
up->stat.curst = BLKSTAT_NEXT; |
up->stat.curst = BLKSTAT_NEXT; |
} |
} |
|
|
|
|
if (idx == -1) { |
if (idx == -1) { |
if ((s = calloc(1, sizeof(struct send_dl))) == NULL) { |
if ((s = calloc(1, sizeof(struct send_dl))) == NULL) { |
ERR(sess, "calloc"); |
ERR("calloc"); |
return 0; |
return 0; |
} |
} |
s->idx = -1; |
s->idx = -1; |
|
|
/* Validate the index. */ |
/* Validate the index. */ |
|
|
if (idx < 0 || (uint32_t)idx >= flsz) { |
if (idx < 0 || (uint32_t)idx >= flsz) { |
ERRX(sess, "file index out of bounds: invalid %d out of %zu", |
ERRX("file index out of bounds: invalid %d out of %zu", |
idx, flsz); |
idx, flsz); |
return 0; |
return 0; |
} else if (S_ISDIR(fl[idx].st.mode)) { |
} else if (S_ISDIR(fl[idx].st.mode)) { |
ERRX(sess, "blocks requested for " |
ERRX("blocks requested for " |
"directory: %s", fl[idx].path); |
"directory: %s", fl[idx].path); |
return 0; |
return 0; |
} else if (S_ISLNK(fl[idx].st.mode)) { |
} else if (S_ISLNK(fl[idx].st.mode)) { |
ERRX(sess, "blocks requested for " |
ERRX("blocks requested for " |
"symlink: %s", fl[idx].path); |
"symlink: %s", fl[idx].path); |
return 0; |
return 0; |
} else if (!S_ISREG(fl[idx].st.mode)) { |
} else if (!S_ISREG(fl[idx].st.mode)) { |
ERRX(sess, "blocks requested for " |
ERRX("blocks requested for " |
"special: %s", fl[idx].path); |
"special: %s", fl[idx].path); |
return 0; |
return 0; |
} |
} |
|
|
if ((s = calloc(1, sizeof(struct send_dl))) == NULL) { |
if ((s = calloc(1, sizeof(struct send_dl))) == NULL) { |
ERR(sess, "callloc"); |
ERR("callloc"); |
return 0; |
return 0; |
} |
} |
s->idx = idx; |
s->idx = idx; |
|
|
if (!sess->opts->dry_run) { |
if (!sess->opts->dry_run) { |
s->blks = blk_recv(sess, fd, fl[idx].path); |
s->blks = blk_recv(sess, fd, fl[idx].path); |
if (s->blks == NULL) { |
if (s->blks == NULL) { |
ERRX1(sess, "blk_recv"); |
ERRX1("blk_recv"); |
return 0; |
return 0; |
} |
} |
} |
} |
|
|
ssize_t ssz; |
ssize_t ssz; |
|
|
if (pledge("stdio getpw rpath unveil", NULL) == -1) { |
if (pledge("stdio getpw rpath unveil", NULL) == -1) { |
ERR(sess, "pledge"); |
ERR("pledge"); |
return 0; |
return 0; |
} |
} |
|
|
|
|
*/ |
*/ |
|
|
if (!flist_gen(sess, argc, argv, &fl, &flsz)) { |
if (!flist_gen(sess, argc, argv, &fl, &flsz)) { |
ERRX1(sess, "flist_gen"); |
ERRX1("flist_gen"); |
goto out; |
goto out; |
} |
} |
|
|
|
|
|
|
if (!sess->opts->server && sess->opts->del && |
if (!sess->opts->server && sess->opts->del && |
!io_write_int(sess, fdout, 0)) { |
!io_write_int(sess, fdout, 0)) { |
ERRX1(sess, "io_write_int"); |
ERRX1("io_write_int"); |
goto out; |
goto out; |
} |
} |
|
|
|
|
*/ |
*/ |
|
|
if (!flist_send(sess, fdin, fdout, fl, flsz)) { |
if (!flist_send(sess, fdin, fdout, fl, flsz)) { |
ERRX1(sess, "flist_send"); |
ERRX1("flist_send"); |
goto out; |
goto out; |
} else if (!io_write_int(sess, fdout, 0)) { |
} else if (!io_write_int(sess, fdout, 0)) { |
ERRX1(sess, "io_write_int"); |
ERRX1("io_write_int"); |
goto out; |
goto out; |
} |
} |
|
|
/* Exit if we're the server with zero files. */ |
/* Exit if we're the server with zero files. */ |
|
|
if (flsz == 0 && sess->opts->server) { |
if (flsz == 0 && sess->opts->server) { |
WARNX(sess, "sender has empty file list: exiting"); |
WARNX("sender has empty file list: exiting"); |
rc = 1; |
rc = 1; |
goto out; |
goto out; |
} else if (!sess->opts->server) |
} else if (!sess->opts->server) |
LOG1(sess, "Transfer starting: %zu files", flsz); |
LOG1("Transfer starting: %zu files", flsz); |
|
|
/* |
/* |
* If we're the server, read our exclusion list. |
* If we're the server, read our exclusion list. |
|
|
|
|
if (sess->opts->server) { |
if (sess->opts->server) { |
if (!io_read_size(sess, fdin, &excl)) { |
if (!io_read_size(sess, fdin, &excl)) { |
ERRX1(sess, "io_read_size"); |
ERRX1("io_read_size"); |
goto out; |
goto out; |
} else if (excl != 0) { |
} else if (excl != 0) { |
ERRX1(sess, "exclusion list is non-empty"); |
ERRX1("exclusion list is non-empty"); |
goto out; |
goto out; |
} |
} |
} |
} |
|
|
for (;;) { |
for (;;) { |
assert(pfd[0].fd != -1); |
assert(pfd[0].fd != -1); |
if ((c = poll(pfd, 3, POLL_TIMEOUT)) == -1) { |
if ((c = poll(pfd, 3, POLL_TIMEOUT)) == -1) { |
ERR(sess, "poll"); |
ERR("poll"); |
goto out; |
goto out; |
} else if (c == 0) { |
} else if (c == 0) { |
ERRX(sess, "poll: timeout"); |
ERRX("poll: timeout"); |
goto out; |
goto out; |
} |
} |
for (i = 0; i < 3; i++) |
for (i = 0; i < 3; i++) |
if (pfd[i].revents & (POLLERR|POLLNVAL)) { |
if (pfd[i].revents & (POLLERR|POLLNVAL)) { |
ERRX(sess, "poll: bad fd"); |
ERRX("poll: bad fd"); |
goto out; |
goto out; |
} else if (pfd[i].revents & POLLHUP) { |
} else if (pfd[i].revents & POLLHUP) { |
ERRX(sess, "poll: hangup"); |
ERRX("poll: hangup"); |
goto out; |
goto out; |
} |
} |
|
|
|
|
|
|
if (sess->mplex_reads && (pfd[0].revents & POLLIN)) { |
if (sess->mplex_reads && (pfd[0].revents & POLLIN)) { |
if (!io_read_flush(sess, fdin)) { |
if (!io_read_flush(sess, fdin)) { |
ERRX1(sess, "io_read_flush"); |
ERRX1("io_read_flush"); |
goto out; |
goto out; |
} else if (sess->mplex_read_remain == 0) { |
} else if (sess->mplex_read_remain == 0) { |
c = io_read_check(sess, fdin); |
c = io_read_check(sess, fdin); |
if (c < 0) { |
if (c < 0) { |
ERRX1(sess, "io_read_check"); |
ERRX1("io_read_check"); |
goto out; |
goto out; |
} else if (c > 0) |
} else if (c > 0) |
continue; |
continue; |
|
|
|
|
if (pfd[0].revents & POLLIN) { |
if (pfd[0].revents & POLLIN) { |
if (!io_read_int(sess, fdin, &idx)) { |
if (!io_read_int(sess, fdin, &idx)) { |
ERRX1(sess, "io_read_int"); |
ERRX1("io_read_int"); |
goto out; |
goto out; |
} |
} |
if (!send_dl_enqueue(sess, |
if (!send_dl_enqueue(sess, |
&sdlq, idx, fl, flsz, fdin)) { |
&sdlq, idx, fl, flsz, fdin)) { |
ERRX1(sess, "send_dl_enqueue"); |
ERRX1("send_dl_enqueue"); |
goto out; |
goto out; |
} |
} |
c = io_read_check(sess, fdin); |
c = io_read_check(sess, fdin); |
if (c < 0) { |
if (c < 0) { |
ERRX1(sess, "io_read_check"); |
ERRX1("io_read_check"); |
goto out; |
goto out; |
} else if (c > 0) |
} else if (c > 0) |
continue; |
continue; |
|
|
f = &fl[up.cur->idx]; |
f = &fl[up.cur->idx]; |
|
|
if (fstat(up.stat.fd, &st) == -1) { |
if (fstat(up.stat.fd, &st) == -1) { |
ERR(sess, "%s: fstat", f->path); |
ERR("%s: fstat", f->path); |
goto out; |
goto out; |
} |
} |
|
|
|
|
up.stat.mapsz, PROT_READ, |
up.stat.mapsz, PROT_READ, |
MAP_SHARED, up.stat.fd, 0); |
MAP_SHARED, up.stat.fd, 0); |
if (up.stat.map == MAP_FAILED) { |
if (up.stat.map == MAP_FAILED) { |
ERR(sess, "%s: mmap", f->path); |
ERR("%s: mmap", f->path); |
goto out; |
goto out; |
} |
} |
} |
} |
|
|
ssz = write(fdout, |
ssz = write(fdout, |
wbuf + wbufpos, wbufsz - wbufpos); |
wbuf + wbufpos, wbufsz - wbufpos); |
if (ssz < 0) { |
if (ssz < 0) { |
ERR(sess, "write"); |
ERR("write"); |
goto out; |
goto out; |
} |
} |
wbufpos += ssz; |
wbufpos += ssz; |
|
|
assert(wbufpos == 0 && wbufsz == 0); |
assert(wbufpos == 0 && wbufsz == 0); |
if (!send_up_fsm(sess, &phase, |
if (!send_up_fsm(sess, &phase, |
&up, &wbuf, &wbufsz, &wbufmax, fl)) { |
&up, &wbuf, &wbufsz, &wbufmax, fl)) { |
ERRX1(sess, "send_up_fsm"); |
ERRX1("send_up_fsm"); |
goto out; |
goto out; |
} else if (phase > 1) |
} else if (phase > 1) |
break; |
break; |
|
|
up.stat.fd = open(fl[up.cur->idx].path, |
up.stat.fd = open(fl[up.cur->idx].path, |
O_RDONLY|O_NONBLOCK, 0); |
O_RDONLY|O_NONBLOCK, 0); |
if (up.stat.fd == -1) { |
if (up.stat.fd == -1) { |
ERR(sess, "%s: open", fl[up.cur->idx].path); |
ERR("%s: open", fl[up.cur->idx].path); |
goto out; |
goto out; |
} |
} |
pfd[2].fd = up.stat.fd; |
pfd[2].fd = up.stat.fd; |
|
|
} |
} |
|
|
if (!TAILQ_EMPTY(&sdlq)) { |
if (!TAILQ_EMPTY(&sdlq)) { |
ERRX(sess, "phases complete with files still queued"); |
ERRX("phases complete with files still queued"); |
goto out; |
goto out; |
} |
} |
|
|
if (!sess_stats_send(sess, fdout)) { |
if (!sess_stats_send(sess, fdout)) { |
ERRX1(sess, "sess_stats_end"); |
ERRX1("sess_stats_end"); |
goto out; |
goto out; |
} |
} |
|
|
/* Final "goodbye" message. */ |
/* Final "goodbye" message. */ |
|
|
if (!io_read_int(sess, fdin, &idx)) { |
if (!io_read_int(sess, fdin, &idx)) { |
ERRX1(sess, "io_read_int"); |
ERRX1("io_read_int"); |
goto out; |
goto out; |
} else if (idx != -1) { |
} else if (idx != -1) { |
ERRX(sess, "read incorrect update complete ack"); |
ERRX("read incorrect update complete ack"); |
goto out; |
goto out; |
} |
} |
|
|
LOG2(sess, "sender finished updating"); |
LOG2("sender finished updating"); |
rc = 1; |
rc = 1; |
out: |
out: |
send_up_reset(&up); |
send_up_reset(&up); |