version 1.19, 2019/04/02 11:05:55 |
version 1.20, 2019/05/08 20:00:25 |
|
|
unit = "KB"; |
unit = "KB"; |
} |
} |
|
|
LOG1(sess, "%s (%.*f %s, %.1f%% downloaded)", |
LOG1("%s (%.*f %s, %.1f%% downloaded)", |
f->path, prec, tot, unit, frac); |
f->path, prec, tot, unit, frac); |
} |
} |
|
|
|
|
struct download *p; |
struct download *p; |
|
|
if ((p = malloc(sizeof(struct download))) == NULL) { |
if ((p = malloc(sizeof(struct download))) == NULL) { |
ERR(sess, "malloc"); |
ERR("malloc"); |
return NULL; |
return NULL; |
} |
} |
|
|
|
|
p->obuf = NULL; |
p->obuf = NULL; |
p->obufmax = OBUF_SIZE; |
p->obufmax = OBUF_SIZE; |
if (p->obufmax && (p->obuf = malloc(p->obufmax)) == NULL) { |
if (p->obufmax && (p->obuf = malloc(p->obufmax)) == NULL) { |
ERR(sess, "malloc"); |
ERR("malloc"); |
free(p); |
free(p); |
return NULL; |
return NULL; |
} |
} |
|
|
assert(p->obufsz <= p->obufmax); |
assert(p->obufsz <= p->obufmax); |
assert(p->obuf != NULL); |
assert(p->obuf != NULL); |
if ((ssz = write(p->fd, p->obuf, p->obufsz)) < 0) { |
if ((ssz = write(p->fd, p->obuf, p->obufsz)) < 0) { |
ERR(sess, "%s: write", p->fname); |
ERR("%s: write", p->fname); |
return 0; |
return 0; |
} else if ((size_t)ssz != p->obufsz) { |
} else if ((size_t)ssz != p->obufsz) { |
ERRX(sess, "%s: short write", p->fname); |
ERRX("%s: short write", p->fname); |
return 0; |
return 0; |
} |
} |
p->obufsz = 0; |
p->obufsz = 0; |
|
|
|
|
if (sz) { |
if (sz) { |
if ((ssz = write(p->fd, buf, sz)) < 0) { |
if ((ssz = write(p->fd, buf, sz)) < 0) { |
ERR(sess, "%s: write", p->fname); |
ERR("%s: write", p->fname); |
return 0; |
return 0; |
} else if ((size_t)ssz != sz) { |
} else if ((size_t)ssz != sz) { |
ERRX(sess, "%s: short write", p->fname); |
ERRX("%s: short write", p->fname); |
return 0; |
return 0; |
} |
} |
} |
} |
|
|
|
|
if (p->state == DOWNLOAD_READ_NEXT) { |
if (p->state == DOWNLOAD_READ_NEXT) { |
if (!io_read_int(sess, p->fdin, &idx)) { |
if (!io_read_int(sess, p->fdin, &idx)) { |
ERRX1(sess, "io_read_int"); |
ERRX1("io_read_int"); |
return -1; |
return -1; |
} else if (idx >= 0 && (size_t)idx >= p->flsz) { |
} else if (idx >= 0 && (size_t)idx >= p->flsz) { |
ERRX(sess, "index out of bounds"); |
ERRX("index out of bounds"); |
return -1; |
return -1; |
} else if (idx < 0) { |
} else if (idx < 0) { |
LOG3(sess, "downloader: phase complete"); |
LOG3("downloader: phase complete"); |
return 0; |
return 0; |
} |
} |
|
|
|
|
|
|
download_reinit(sess, p, idx); |
download_reinit(sess, p, idx); |
if (!blk_send_ack(sess, p->fdin, &p->blk)) { |
if (!blk_send_ack(sess, p->fdin, &p->blk)) { |
ERRX1(sess, "blk_send_ack"); |
ERRX1("blk_send_ack"); |
goto out; |
goto out; |
} |
} |
|
|
|
|
p->ofd = openat(p->rootfd, f->path, O_RDONLY | O_NONBLOCK, 0); |
p->ofd = openat(p->rootfd, f->path, O_RDONLY | O_NONBLOCK, 0); |
|
|
if (p->ofd == -1 && errno != ENOENT) { |
if (p->ofd == -1 && errno != ENOENT) { |
ERR(sess, "%s: openat", f->path); |
ERR("%s: openat", f->path); |
goto out; |
goto out; |
} else if (p->ofd != -1) { |
} else if (p->ofd != -1) { |
*ofd = p->ofd; |
*ofd = p->ofd; |
|
|
|
|
if (p->ofd != -1 && |
if (p->ofd != -1 && |
fstat(p->ofd, &st) == -1) { |
fstat(p->ofd, &st) == -1) { |
ERR(sess, "%s: fstat", f->path); |
ERR("%s: fstat", f->path); |
goto out; |
goto out; |
} else if (p->ofd != -1 && !S_ISREG(st.st_mode)) { |
} else if (p->ofd != -1 && !S_ISREG(st.st_mode)) { |
WARNX(sess, "%s: not regular", f->path); |
WARNX("%s: not regular", f->path); |
goto out; |
goto out; |
} |
} |
|
|
|
|
p->map = mmap(NULL, p->mapsz, |
p->map = mmap(NULL, p->mapsz, |
PROT_READ, MAP_SHARED, p->ofd, 0); |
PROT_READ, MAP_SHARED, p->ofd, 0); |
if (p->map == MAP_FAILED) { |
if (p->map == MAP_FAILED) { |
ERR(sess, "%s: mmap", f->path); |
ERR("%s: mmap", f->path); |
goto out; |
goto out; |
} |
} |
} |
} |
|
|
|
|
if (mktemplate(sess, &p->fname, |
if (mktemplate(sess, &p->fname, |
f->path, sess->opts->recursive) == -1) { |
f->path, sess->opts->recursive) == -1) { |
ERRX1(sess, "mktemplate"); |
ERRX1("mktemplate"); |
goto out; |
goto out; |
} |
} |
|
|
if ((p->fd = mkstempat(p->rootfd, p->fname)) == -1) { |
if ((p->fd = mkstempat(p->rootfd, p->fname)) == -1) { |
ERR(sess, "mkstempat"); |
ERR("mkstempat"); |
goto out; |
goto out; |
} |
} |
|
|
|
|
* memory beforehand. |
* memory beforehand. |
*/ |
*/ |
|
|
LOG3(sess, "%s: temporary: %s", f->path, p->fname); |
LOG3("%s: temporary: %s", f->path, p->fname); |
p->state = DOWNLOAD_READ_REMOTE; |
p->state = DOWNLOAD_READ_REMOTE; |
return 1; |
return 1; |
} |
} |
|
|
assert(p->fdin != -1); |
assert(p->fdin != -1); |
|
|
if (!io_read_int(sess, p->fdin, &rawtok)) { |
if (!io_read_int(sess, p->fdin, &rawtok)) { |
ERRX1(sess, "io_read_int"); |
ERRX1("io_read_int"); |
goto out; |
goto out; |
} |
} |
|
|
if (rawtok > 0) { |
if (rawtok > 0) { |
sz = rawtok; |
sz = rawtok; |
if ((buf = malloc(sz)) == NULL) { |
if ((buf = malloc(sz)) == NULL) { |
ERR(sess, "realloc"); |
ERR("realloc"); |
goto out; |
goto out; |
} |
} |
if (!io_read_buf(sess, p->fdin, buf, sz)) { |
if (!io_read_buf(sess, p->fdin, buf, sz)) { |
ERRX1(sess, "io_read_int"); |
ERRX1("io_read_int"); |
goto out; |
goto out; |
} else if (!buf_copy(sess, buf, sz, p)) { |
} else if (!buf_copy(sess, buf, sz, p)) { |
ERRX1(sess, "buf_copy"); |
ERRX1("buf_copy"); |
goto out; |
goto out; |
} |
} |
p->total += sz; |
p->total += sz; |
p->downloaded += sz; |
p->downloaded += sz; |
LOG4(sess, "%s: received %zu B block", p->fname, sz); |
LOG4("%s: received %zu B block", p->fname, sz); |
MD4_Update(&p->ctx, buf, sz); |
MD4_Update(&p->ctx, buf, sz); |
free(buf); |
free(buf); |
|
|
/* Fast-track more reads as they arrive. */ |
/* Fast-track more reads as they arrive. */ |
|
|
if ((c = io_read_check(sess, p->fdin)) < 0) { |
if ((c = io_read_check(sess, p->fdin)) < 0) { |
ERRX1(sess, "io_read_check"); |
ERRX1("io_read_check"); |
goto out; |
goto out; |
} else if (c > 0) |
} else if (c > 0) |
goto again; |
goto again; |
|
|
} else if (rawtok < 0) { |
} else if (rawtok < 0) { |
tok = -rawtok - 1; |
tok = -rawtok - 1; |
if (tok >= p->blk.blksz) { |
if (tok >= p->blk.blksz) { |
ERRX(sess, |
ERRX("%s: token not in block set: %zu (have %zu blocks)", |
"%s: token not in block set: %zu (have %zu blocks)", |
|
p->fname, tok, p->blk.blksz); |
p->fname, tok, p->blk.blksz); |
goto out; |
goto out; |
} |
} |
|
|
|
|
assert(p->map != MAP_FAILED); |
assert(p->map != MAP_FAILED); |
if (!buf_copy(sess, buf, sz, p)) { |
if (!buf_copy(sess, buf, sz, p)) { |
ERRX1(sess, "buf_copy"); |
ERRX1("buf_copy"); |
goto out; |
goto out; |
} |
} |
p->total += sz; |
p->total += sz; |
LOG4(sess, "%s: copied %zu B", p->fname, sz); |
LOG4("%s: copied %zu B", p->fname, sz); |
MD4_Update(&p->ctx, buf, sz); |
MD4_Update(&p->ctx, buf, sz); |
|
|
/* Fast-track more reads as they arrive. */ |
/* Fast-track more reads as they arrive. */ |
|
|
if ((c = io_read_check(sess, p->fdin)) < 0) { |
if ((c = io_read_check(sess, p->fdin)) < 0) { |
ERRX1(sess, "io_read_check"); |
ERRX1("io_read_check"); |
goto out; |
goto out; |
} else if (c > 0) |
} else if (c > 0) |
goto again; |
goto again; |
|
|
} |
} |
|
|
if (!buf_copy(sess, NULL, 0, p)) { |
if (!buf_copy(sess, NULL, 0, p)) { |
ERRX1(sess, "buf_copy"); |
ERRX1("buf_copy"); |
goto out; |
goto out; |
} |
} |
|
|
|
|
MD4_Final(ourmd, &p->ctx); |
MD4_Final(ourmd, &p->ctx); |
|
|
if (!io_read_buf(sess, p->fdin, md, MD4_DIGEST_LENGTH)) { |
if (!io_read_buf(sess, p->fdin, md, MD4_DIGEST_LENGTH)) { |
ERRX1(sess, "io_read_buf"); |
ERRX1("io_read_buf"); |
goto out; |
goto out; |
} else if (memcmp(md, ourmd, MD4_DIGEST_LENGTH)) { |
} else if (memcmp(md, ourmd, MD4_DIGEST_LENGTH)) { |
ERRX(sess, "%s: hash does not match", p->fname); |
ERRX("%s: hash does not match", p->fname); |
goto out; |
goto out; |
} |
} |
|
|
/* Adjust our file metadata (uid, mode, etc.). */ |
/* Adjust our file metadata (uid, mode, etc.). */ |
|
|
if (!rsync_set_metadata(sess, 1, p->fd, f, p->fname)) { |
if (!rsync_set_metadata(sess, 1, p->fd, f, p->fname)) { |
ERRX1(sess, "rsync_set_metadata"); |
ERRX1("rsync_set_metadata"); |
goto out; |
goto out; |
} |
} |
|
|
/* Finally, rename the temporary to the real file. */ |
/* Finally, rename the temporary to the real file. */ |
|
|
if (renameat(p->rootfd, p->fname, p->rootfd, f->path) == -1) { |
if (renameat(p->rootfd, p->fname, p->rootfd, f->path) == -1) { |
ERR(sess, "%s: renameat: %s", p->fname, f->path); |
ERR("%s: renameat: %s", p->fname, f->path); |
goto out; |
goto out; |
} |
} |
|
|