version 1.20, 2019/04/02 11:05:55 |
version 1.21, 2019/05/08 20:00:25 |
|
|
return; |
return; |
sz = strlen(f->path); |
sz = strlen(f->path); |
assert(sz > 0); |
assert(sz > 0); |
LOG1(sess, "%s%s", f->path, (f->path[sz - 1] == '/') ? "" : "/"); |
LOG1("%s%s", f->path, (f->path[sz - 1] == '/') ? "" : "/"); |
} |
} |
|
|
/* |
/* |
|
|
{ |
{ |
|
|
if (!sess->opts->server) |
if (!sess->opts->server) |
LOG1(sess, "%s -> %s", f->path, f->link); |
LOG1("%s -> %s", f->path, f->link); |
} |
} |
|
|
/* |
/* |
|
|
{ |
{ |
|
|
if (!sess->opts->server) |
if (!sess->opts->server) |
LOG1(sess, "%s", f->path); |
LOG1("%s", f->path); |
} |
} |
|
|
/* |
/* |
|
|
assert(S_ISLNK(f->st.mode)); |
assert(S_ISLNK(f->st.mode)); |
|
|
if (!sess->opts->preserve_links) { |
if (!sess->opts->preserve_links) { |
WARNX(sess, "%s: ignoring symlink", f->path); |
WARNX("%s: ignoring symlink", f->path); |
return 0; |
return 0; |
} else if (sess->opts->dry_run) { |
} else if (sess->opts->dry_run) { |
log_link(sess, f); |
log_link(sess, f); |
|
|
if (rc != -1 && !S_ISLNK(st.st_mode)) { |
if (rc != -1 && !S_ISLNK(st.st_mode)) { |
if (S_ISDIR(st.st_mode) && |
if (S_ISDIR(st.st_mode) && |
unlinkat(p->rootfd, f->path, AT_REMOVEDIR) == -1) { |
unlinkat(p->rootfd, f->path, AT_REMOVEDIR) == -1) { |
ERR(sess, "%s: unlinkat", f->path); |
ERR("%s: unlinkat", f->path); |
return -1; |
return -1; |
} |
} |
rc = -1; |
rc = -1; |
} else if (rc == -1 && errno != ENOENT) { |
} else if (rc == -1 && errno != ENOENT) { |
ERR(sess, "%s: fstatat", f->path); |
ERR("%s: fstatat", f->path); |
return -1; |
return -1; |
} |
} |
|
|
|
|
if (rc != -1) { |
if (rc != -1) { |
b = symlinkat_read(sess, p->rootfd, f->path); |
b = symlinkat_read(sess, p->rootfd, f->path); |
if (b == NULL) { |
if (b == NULL) { |
ERRX1(sess, "symlinkat_read"); |
ERRX1("symlinkat_read"); |
return -1; |
return -1; |
} |
} |
if (strcmp(f->link, b)) { |
if (strcmp(f->link, b)) { |
free(b); |
free(b); |
b = NULL; |
b = NULL; |
LOG3(sess, "%s: updating symlink: %s", f->path, f->link); |
LOG3("%s: updating symlink: %s", f->path, f->link); |
updatelink = 1; |
updatelink = 1; |
} |
} |
free(b); |
free(b); |
|
|
*/ |
*/ |
|
|
if (rc == -1 || updatelink) { |
if (rc == -1 || updatelink) { |
LOG3(sess, "%s: creating symlink: %s", f->path, f->link); |
LOG3("%s: creating symlink: %s", f->path, f->link); |
if (mktemplate(sess, &temp, |
if (mktemplate(sess, &temp, |
f->path, sess->opts->recursive) == -1) { |
f->path, sess->opts->recursive) == -1) { |
ERRX1(sess, "mktemplate"); |
ERRX1("mktemplate"); |
return -1; |
return -1; |
} |
} |
if (mkstemplinkat(f->link, p->rootfd, temp) == NULL) { |
if (mkstemplinkat(f->link, p->rootfd, temp) == NULL) { |
ERR(sess, "mkstemplinkat"); |
ERR("mkstemplinkat"); |
free(temp); |
free(temp); |
return -1; |
return -1; |
} |
} |
|
|
|
|
if (newlink) { |
if (newlink) { |
if (renameat(p->rootfd, temp, p->rootfd, f->path) == -1) { |
if (renameat(p->rootfd, temp, p->rootfd, f->path) == -1) { |
ERR(sess, "%s: renameat %s", temp, f->path); |
ERR("%s: renameat %s", temp, f->path); |
(void)unlinkat(p->rootfd, temp, 0); |
(void)unlinkat(p->rootfd, temp, 0); |
free(temp); |
free(temp); |
return -1; |
return -1; |
|
|
assert(S_ISBLK(f->st.mode) || S_ISCHR(f->st.mode)); |
assert(S_ISBLK(f->st.mode) || S_ISCHR(f->st.mode)); |
|
|
if (!sess->opts->devices || getuid() != 0) { |
if (!sess->opts->devices || getuid() != 0) { |
WARNX(sess, "skipping non-regular file %s", f->path); |
WARNX("skipping non-regular file %s", f->path); |
return 0; |
return 0; |
} else if (sess->opts->dry_run) { |
} else if (sess->opts->dry_run) { |
log_file(sess, f); |
log_file(sess, f); |
|
|
if (rc != -1 && !(S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode))) { |
if (rc != -1 && !(S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode))) { |
if (S_ISDIR(st.st_mode) && |
if (S_ISDIR(st.st_mode) && |
unlinkat(p->rootfd, f->path, AT_REMOVEDIR) == -1) { |
unlinkat(p->rootfd, f->path, AT_REMOVEDIR) == -1) { |
ERR(sess, "%s: unlinkat", f->path); |
ERR("%s: unlinkat", f->path); |
return -1; |
return -1; |
} |
} |
rc = -1; |
rc = -1; |
} else if (rc == -1 && errno != ENOENT) { |
} else if (rc == -1 && errno != ENOENT) { |
ERR(sess, "%s: fstatat", f->path); |
ERR("%s: fstatat", f->path); |
return -1; |
return -1; |
} |
} |
|
|
|
|
if ((f->st.mode & (S_IFCHR|S_IFBLK)) != |
if ((f->st.mode & (S_IFCHR|S_IFBLK)) != |
(st.st_mode & (S_IFCHR|S_IFBLK)) || |
(st.st_mode & (S_IFCHR|S_IFBLK)) || |
f->st.rdev != st.st_rdev) { |
f->st.rdev != st.st_rdev) { |
LOG3(sess, "%s: updating device", f->path); |
LOG3("%s: updating device", f->path); |
updatedev = 1; |
updatedev = 1; |
} |
} |
} |
} |
|
|
newdev = 1; |
newdev = 1; |
if (mktemplate(sess, &temp, f->path, |
if (mktemplate(sess, &temp, f->path, |
sess->opts->recursive) == -1) { |
sess->opts->recursive) == -1) { |
ERRX1(sess, "mktemplate"); |
ERRX1("mktemplate"); |
return -1; |
return -1; |
} |
} |
if (mkstempnodat(p->rootfd, temp, |
if (mkstempnodat(p->rootfd, temp, |
f->st.mode & (S_IFCHR|S_IFBLK), f->st.rdev) == NULL) { |
f->st.mode & (S_IFCHR|S_IFBLK), f->st.rdev) == NULL) { |
ERR(sess, "mkstempnodat"); |
ERR("mkstempnodat"); |
free(temp); |
free(temp); |
return -1; |
return -1; |
} |
} |
|
|
|
|
if (newdev) { |
if (newdev) { |
if (renameat(p->rootfd, temp, p->rootfd, f->path) == -1) { |
if (renameat(p->rootfd, temp, p->rootfd, f->path) == -1) { |
ERR(sess, "%s: renameat %s", temp, f->path); |
ERR("%s: renameat %s", temp, f->path); |
(void)unlinkat(p->rootfd, temp, 0); |
(void)unlinkat(p->rootfd, temp, 0); |
free(temp); |
free(temp); |
return -1; |
return -1; |
|
|
assert(S_ISFIFO(f->st.mode)); |
assert(S_ISFIFO(f->st.mode)); |
|
|
if (!sess->opts->specials) { |
if (!sess->opts->specials) { |
WARNX(sess, "skipping non-regular file %s", f->path); |
WARNX("skipping non-regular file %s", f->path); |
return 0; |
return 0; |
} else if (sess->opts->dry_run) { |
} else if (sess->opts->dry_run) { |
log_file(sess, f); |
log_file(sess, f); |
|
|
if (rc != -1 && !S_ISFIFO(st.st_mode)) { |
if (rc != -1 && !S_ISFIFO(st.st_mode)) { |
if (S_ISDIR(st.st_mode) && |
if (S_ISDIR(st.st_mode) && |
unlinkat(p->rootfd, f->path, AT_REMOVEDIR) == -1) { |
unlinkat(p->rootfd, f->path, AT_REMOVEDIR) == -1) { |
ERR(sess, "%s: unlinkat", f->path); |
ERR("%s: unlinkat", f->path); |
return -1; |
return -1; |
} |
} |
rc = -1; |
rc = -1; |
} else if (rc == -1 && errno != ENOENT) { |
} else if (rc == -1 && errno != ENOENT) { |
ERR(sess, "%s: fstatat", f->path); |
ERR("%s: fstatat", f->path); |
return -1; |
return -1; |
} |
} |
|
|
|
|
newfifo = 1; |
newfifo = 1; |
if (mktemplate(sess, &temp, f->path, |
if (mktemplate(sess, &temp, f->path, |
sess->opts->recursive) == -1) { |
sess->opts->recursive) == -1) { |
ERRX1(sess, "mktemplate"); |
ERRX1("mktemplate"); |
return -1; |
return -1; |
} |
} |
if (mkstempfifoat(p->rootfd, temp) == NULL) { |
if (mkstempfifoat(p->rootfd, temp) == NULL) { |
ERR(sess, "mkstempfifoat"); |
ERR("mkstempfifoat"); |
free(temp); |
free(temp); |
return -1; |
return -1; |
} |
} |
|
|
|
|
if (newfifo) { |
if (newfifo) { |
if (renameat(p->rootfd, temp, p->rootfd, f->path) == -1) { |
if (renameat(p->rootfd, temp, p->rootfd, f->path) == -1) { |
ERR(sess, "%s: renameat %s", temp, f->path); |
ERR("%s: renameat %s", temp, f->path); |
(void)unlinkat(p->rootfd, temp, 0); |
(void)unlinkat(p->rootfd, temp, 0); |
free(temp); |
free(temp); |
return -1; |
return -1; |
|
|
assert(S_ISSOCK(f->st.mode)); |
assert(S_ISSOCK(f->st.mode)); |
|
|
if (!sess->opts->specials) { |
if (!sess->opts->specials) { |
WARNX(sess, "skipping non-regular file %s", f->path); |
WARNX("skipping non-regular file %s", f->path); |
return 0; |
return 0; |
} else if (sess->opts->dry_run) { |
} else if (sess->opts->dry_run) { |
log_file(sess, f); |
log_file(sess, f); |
|
|
if (rc != -1 && !S_ISSOCK(st.st_mode)) { |
if (rc != -1 && !S_ISSOCK(st.st_mode)) { |
if (S_ISDIR(st.st_mode) && |
if (S_ISDIR(st.st_mode) && |
unlinkat(p->rootfd, f->path, AT_REMOVEDIR) == -1) { |
unlinkat(p->rootfd, f->path, AT_REMOVEDIR) == -1) { |
ERR(sess, "%s: unlinkat", f->path); |
ERR("%s: unlinkat", f->path); |
return -1; |
return -1; |
} |
} |
rc = -1; |
rc = -1; |
} else if (rc == -1 && errno != ENOENT) { |
} else if (rc == -1 && errno != ENOENT) { |
ERR(sess, "%s: fstatat", f->path); |
ERR("%s: fstatat", f->path); |
return -1; |
return -1; |
} |
} |
|
|
|
|
newsock = 1; |
newsock = 1; |
if (mktemplate(sess, &temp, f->path, |
if (mktemplate(sess, &temp, f->path, |
sess->opts->recursive) == -1) { |
sess->opts->recursive) == -1) { |
ERRX1(sess, "mktemplate"); |
ERRX1("mktemplate"); |
return -1; |
return -1; |
} |
} |
if (mkstempsock(p->root, temp) == NULL) { |
if (mkstempsock(p->root, temp) == NULL) { |
ERR(sess, "mkstempsock"); |
ERR("mkstempsock"); |
free(temp); |
free(temp); |
return -1; |
return -1; |
} |
} |
|
|
|
|
if (newsock) { |
if (newsock) { |
if (renameat(p->rootfd, temp, p->rootfd, f->path) == -1) { |
if (renameat(p->rootfd, temp, p->rootfd, f->path) == -1) { |
ERR(sess, "%s: renameat %s", temp, f->path); |
ERR("%s: renameat %s", temp, f->path); |
(void)unlinkat(p->rootfd, temp, 0); |
(void)unlinkat(p->rootfd, temp, 0); |
free(temp); |
free(temp); |
return -1; |
return -1; |
|
|
assert(S_ISDIR(f->st.mode)); |
assert(S_ISDIR(f->st.mode)); |
|
|
if (!sess->opts->recursive) { |
if (!sess->opts->recursive) { |
WARNX(sess, "%s: ignoring directory", f->path); |
WARNX("%s: ignoring directory", f->path); |
return 0; |
return 0; |
} else if (sess->opts->dry_run) { |
} else if (sess->opts->dry_run) { |
log_dir(sess, f); |
log_dir(sess, f); |
|
|
rc = fstatat(p->rootfd, f->path, &st, AT_SYMLINK_NOFOLLOW); |
rc = fstatat(p->rootfd, f->path, &st, AT_SYMLINK_NOFOLLOW); |
|
|
if (rc == -1 && errno != ENOENT) { |
if (rc == -1 && errno != ENOENT) { |
ERR(sess, "%s: fstatat", f->path); |
ERR("%s: fstatat", f->path); |
return -1; |
return -1; |
} else if (rc != -1 && !S_ISDIR(st.st_mode)) { |
} else if (rc != -1 && !S_ISDIR(st.st_mode)) { |
ERRX(sess, "%s: not a directory", f->path); |
ERRX("%s: not a directory", f->path); |
return -1; |
return -1; |
} else if (rc != -1) { |
} else if (rc != -1) { |
/* |
/* |
|
|
* as we may locally have shut down writing into the |
* as we may locally have shut down writing into the |
* directory and that doesn't work. |
* directory and that doesn't work. |
*/ |
*/ |
LOG3(sess, "%s: updating directory", f->path); |
LOG3("%s: updating directory", f->path); |
return 0; |
return 0; |
} |
} |
|
|
|
|
* case it's u-w or something. |
* case it's u-w or something. |
*/ |
*/ |
|
|
LOG3(sess, "%s: creating directory", f->path); |
LOG3("%s: creating directory", f->path); |
if (mkdirat(p->rootfd, f->path, 0777 & ~p->oumask) == -1) { |
if (mkdirat(p->rootfd, f->path, 0777 & ~p->oumask) == -1) { |
ERR(sess, "%s: mkdirat", f->path); |
ERR("%s: mkdirat", f->path); |
return -1; |
return -1; |
} |
} |
|
|
|
|
return 1; |
return 1; |
|
|
if (fstatat(u->rootfd, f->path, &st, AT_SYMLINK_NOFOLLOW) == -1) { |
if (fstatat(u->rootfd, f->path, &st, AT_SYMLINK_NOFOLLOW) == -1) { |
ERR(sess, "%s: fstatat", f->path); |
ERR("%s: fstatat", f->path); |
return 0; |
return 0; |
} else if (!S_ISDIR(st.st_mode)) { |
} else if (!S_ISDIR(st.st_mode)) { |
WARNX(sess, "%s: not a directory", f->path); |
WARNX("%s: not a directory", f->path); |
return 0; |
return 0; |
} |
} |
|
|
|
|
tv[1].tv_nsec = 0; |
tv[1].tv_nsec = 0; |
rc = utimensat(u->rootfd, f->path, tv, 0); |
rc = utimensat(u->rootfd, f->path, tv, 0); |
if (rc == -1) { |
if (rc == -1) { |
ERR(sess, "%s: utimensat", f->path); |
ERR("%s: utimensat", f->path); |
return 0; |
return 0; |
} |
} |
LOG4(sess, "%s: updated date", f->path); |
LOG4("%s: updated date", f->path); |
} |
} |
|
|
/* |
/* |
|
|
(sess->opts->preserve_perms && st.st_mode != f->st.mode)) { |
(sess->opts->preserve_perms && st.st_mode != f->st.mode)) { |
rc = fchmodat(u->rootfd, f->path, f->st.mode, 0); |
rc = fchmodat(u->rootfd, f->path, f->st.mode, 0); |
if (rc == -1) { |
if (rc == -1) { |
ERR(sess, "%s: fchmodat", f->path); |
ERR("%s: fchmodat", f->path); |
return 0; |
return 0; |
} |
} |
LOG4(sess, "%s: updated mode", f->path); |
LOG4("%s: updated mode", f->path); |
} |
} |
|
|
return 1; |
return 1; |
|
|
if (sess->opts->dry_run) { |
if (sess->opts->dry_run) { |
log_file(sess, f); |
log_file(sess, f); |
if (!io_write_int(sess, p->fdout, p->idx)) { |
if (!io_write_int(sess, p->fdout, p->idx)) { |
ERRX1(sess, "io_write_int"); |
ERRX1("io_write_int"); |
return -1; |
return -1; |
} |
} |
return 0; |
return 0; |
|
|
O_RDONLY | O_NOFOLLOW | O_NONBLOCK, 0); |
O_RDONLY | O_NOFOLLOW | O_NONBLOCK, 0); |
if (*filefd != -1 || errno == ENOENT) |
if (*filefd != -1 || errno == ENOENT) |
return 1; |
return 1; |
ERR(sess, "%s: openat", f->path); |
ERR("%s: openat", f->path); |
return -1; |
return -1; |
} |
} |
|
|
|
|
struct upload *p; |
struct upload *p; |
|
|
if ((p = calloc(1, sizeof(struct upload))) == NULL) { |
if ((p = calloc(1, sizeof(struct upload))) == NULL) { |
ERR(sess, "calloc"); |
ERR("calloc"); |
return NULL; |
return NULL; |
} |
} |
|
|
|
|
p->oumask = msk; |
p->oumask = msk; |
p->root = strdup(root); |
p->root = strdup(root); |
if (p->root == NULL) { |
if (p->root == NULL) { |
ERR(sess, "strdup"); |
ERR("strdup"); |
free(p); |
free(p); |
return NULL; |
return NULL; |
} |
} |
|
|
p->flsz = flsz; |
p->flsz = flsz; |
p->newdir = calloc(flsz, sizeof(int)); |
p->newdir = calloc(flsz, sizeof(int)); |
if (p->newdir == NULL) { |
if (p->newdir == NULL) { |
ERR(sess, "calloc"); |
ERR("calloc"); |
free(p->root); |
free(p->root); |
free(p); |
free(p); |
return NULL; |
return NULL; |
|
|
c = io_write_buf(sess, u->fdout, |
c = io_write_buf(sess, u->fdout, |
u->buf + u->bufpos, sz); |
u->buf + u->bufpos, sz); |
if (c == 0) { |
if (c == 0) { |
ERRX1(sess, "io_write_nonblocking"); |
ERRX1("io_write_nonblocking"); |
return -1; |
return -1; |
} |
} |
u->bufpos += sz; |
u->bufpos += sz; |
|
|
if (u->idx == u->flsz) { |
if (u->idx == u->flsz) { |
assert(*fileinfd == -1); |
assert(*fileinfd == -1); |
if (!io_write_int(sess, u->fdout, -1)) { |
if (!io_write_int(sess, u->fdout, -1)) { |
ERRX1(sess, "io_write_int"); |
ERRX1("io_write_int"); |
return -1; |
return -1; |
} |
} |
u->state = UPLOAD_FINISHED; |
u->state = UPLOAD_FINISHED; |
LOG4(sess, "uploader: finished"); |
LOG4("uploader: finished"); |
return 0; |
return 0; |
} |
} |
|
|
|
|
f = &u->fl[u->idx]; |
f = &u->fl[u->idx]; |
|
|
if (fstat(*fileinfd, &st) == -1) { |
if (fstat(*fileinfd, &st) == -1) { |
ERR(sess, "%s: fstat", f->path); |
ERR("%s: fstat", f->path); |
close(*fileinfd); |
close(*fileinfd); |
*fileinfd = -1; |
*fileinfd = -1; |
return -1; |
return -1; |
} else if (!S_ISREG(st.st_mode)) { |
} else if (!S_ISREG(st.st_mode)) { |
ERRX(sess, "%s: not regular", f->path); |
ERRX("%s: not regular", f->path); |
close(*fileinfd); |
close(*fileinfd); |
*fileinfd = -1; |
*fileinfd = -1; |
return -1; |
return -1; |
|
|
|
|
if (st.st_size == f->st.size && |
if (st.st_size == f->st.size && |
st.st_mtime == f->st.mtime) { |
st.st_mtime == f->st.mtime) { |
LOG3(sess, "%s: skipping: up to date", f->path); |
LOG3("%s: skipping: up to date", f->path); |
if (!rsync_set_metadata |
if (!rsync_set_metadata |
(sess, 0, *fileinfd, f, f->path)) { |
(sess, 0, *fileinfd, f, f->path)) { |
ERRX1(sess, "rsync_set_metadata"); |
ERRX1("rsync_set_metadata"); |
close(*fileinfd); |
close(*fileinfd); |
*fileinfd = -1; |
*fileinfd = -1; |
return -1; |
return -1; |
|
|
mapsz = st.st_size; |
mapsz = st.st_size; |
map = mmap(NULL, mapsz, PROT_READ, MAP_SHARED, *fileinfd, 0); |
map = mmap(NULL, mapsz, PROT_READ, MAP_SHARED, *fileinfd, 0); |
if (map == MAP_FAILED) { |
if (map == MAP_FAILED) { |
ERR(sess, "%s: mmap", u->fl[u->idx].path); |
ERR("%s: mmap", u->fl[u->idx].path); |
close(*fileinfd); |
close(*fileinfd); |
*fileinfd = -1; |
*fileinfd = -1; |
return -1; |
return -1; |
|
|
|
|
blk.blks = calloc(blk.blksz, sizeof(struct blk)); |
blk.blks = calloc(blk.blksz, sizeof(struct blk)); |
if (blk.blks == NULL) { |
if (blk.blks == NULL) { |
ERR(sess, "calloc"); |
ERR("calloc"); |
munmap(map, mapsz); |
munmap(map, mapsz); |
close(*fileinfd); |
close(*fileinfd); |
*fileinfd = -1; |
*fileinfd = -1; |
|
|
munmap(map, mapsz); |
munmap(map, mapsz); |
close(*fileinfd); |
close(*fileinfd); |
*fileinfd = -1; |
*fileinfd = -1; |
LOG3(sess, "%s: mapped %jd B with %zu blocks", |
LOG3("%s: mapped %jd B with %zu blocks", |
u->fl[u->idx].path, (intmax_t)blk.size, |
u->fl[u->idx].path, (intmax_t)blk.size, |
blk.blksz); |
blk.blksz); |
} else { |
} else { |
|
|
*fileinfd = -1; |
*fileinfd = -1; |
} |
} |
blk.len = MAX_CHUNK; /* Doesn't matter. */ |
blk.len = MAX_CHUNK; /* Doesn't matter. */ |
LOG3(sess, "%s: not mapped", u->fl[u->idx].path); |
LOG3("%s: not mapped", u->fl[u->idx].path); |
} |
} |
|
|
assert(*fileinfd == -1); |
assert(*fileinfd == -1); |
|
|
|
|
if (u->bufsz > u->bufmax) { |
if (u->bufsz > u->bufmax) { |
if ((bufp = realloc(u->buf, u->bufsz)) == NULL) { |
if ((bufp = realloc(u->buf, u->bufsz)) == NULL) { |
ERR(sess, "realloc"); |
ERR("realloc"); |
return -1; |
return -1; |
} |
} |
u->buf = bufp; |
u->buf = bufp; |
|
|
!sess->opts->preserve_perms) |
!sess->opts->preserve_perms) |
return 1; |
return 1; |
|
|
LOG2(sess, "fixing up directory times and permissions"); |
LOG2("fixing up directory times and permissions"); |
|
|
for (i = 0; i < u->flsz; i++) |
for (i = 0; i < u->flsz; i++) |
if (S_ISDIR(u->fl[i].st.mode)) |
if (S_ISDIR(u->fl[i].st.mode)) |