diff options
-rw-r--r-- | usr.bin/rsync/downloader.c | 39 | ||||
-rw-r--r-- | usr.bin/rsync/extern.h | 4 | ||||
-rw-r--r-- | usr.bin/rsync/receiver.c | 49 | ||||
-rw-r--r-- | usr.bin/rsync/uploader.c | 37 |
4 files changed, 80 insertions, 49 deletions
diff --git a/usr.bin/rsync/downloader.c b/usr.bin/rsync/downloader.c index 2b545f00c3e..62914437607 100644 --- a/usr.bin/rsync/downloader.c +++ b/usr.bin/rsync/downloader.c @@ -1,4 +1,4 @@ -/* $Id: downloader.c,v 1.8 2019/02/13 05:41:35 tb Exp $ */ +/* $Id: downloader.c,v 1.9 2019/02/14 18:29:08 florian Exp $ */ /* * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv> * @@ -306,7 +306,6 @@ rsync_downloader(struct download *p, struct sess *sess, int *ofd) char *buf = NULL; unsigned char ourmd[MD4_DIGEST_LENGTH], md[MD4_DIGEST_LENGTH]; - struct timespec tv[2]; /* * If we don't have a download already in session, then the next @@ -569,39 +568,11 @@ rsync_downloader(struct download *p, struct sess *sess, int *ofd) goto out; } - /* - * Conditionally adjust group id. - * FIXME: remember the original file's group id and don't - * reassign it if it's the same. - * If we have an EPERM, report it but continue on: this just - * means that we're mapping into an unknown (or disallowed) - * group identifier. - */ - - if (sess->opts->preserve_gids) { - if (fchown(p->fd, -1, f->st.gid) == -1) { - if (errno != EPERM) { - ERR(sess, "%s: fchown", p->fname); - goto out; - } - WARNX(sess, "%s: gid unknown or not available " - "to user: %u", f->path, f->st.gid); - } else - LOG4(sess, "%s: updated gid", f->path); - } - - /* Conditionally adjust file modification time. */ + /* Adjust our file metadata (uid, mode, etc.). */ - if (sess->opts->preserve_times) { - tv[0].tv_sec = time(NULL); - tv[0].tv_nsec = 0; - tv[1].tv_sec = f->st.mtime; - tv[1].tv_nsec = 0; - if (futimens(p->fd, tv) == -1) { - ERR(sess, "%s: futimens", p->fname); - goto out; - } - LOG4(sess, "%s: updated date", f->path); + if (!rsync_set_metadata(sess, 1, p->fd, f, p->fname)) { + ERRX1(sess, "rsync_set_metadata"); + goto out; } /* Finally, rename the temporary to the real file. */ diff --git a/usr.bin/rsync/extern.h b/usr.bin/rsync/extern.h index 25dbc6420cd..da9bbac9fda 100644 --- a/usr.bin/rsync/extern.h +++ b/usr.bin/rsync/extern.h @@ -1,4 +1,4 @@ -/* $Id: extern.h,v 1.9 2019/02/14 18:26:52 florian Exp $ */ +/* $Id: extern.h,v 1.10 2019/02/14 18:29:08 florian Exp $ */ /* * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv> * @@ -264,6 +264,8 @@ int rsync_client(const struct opts *, int, const struct fargs *); int rsync_socket(const struct opts *, const struct fargs *); int rsync_server(const struct opts *, size_t, char *[]); int rsync_downloader(struct download *, struct sess *, int *); +int rsync_set_metadata(struct sess *, int, int, + const struct flist *, const char *); int rsync_uploader(struct upload *, int *, struct sess *, int *); int rsync_uploader_tail(struct upload *, struct sess *); diff --git a/usr.bin/rsync/receiver.c b/usr.bin/rsync/receiver.c index 5b1446265d5..b5fb79c538a 100644 --- a/usr.bin/rsync/receiver.c +++ b/usr.bin/rsync/receiver.c @@ -1,4 +1,4 @@ -/* $Id: receiver.c,v 1.6 2019/02/12 17:58:35 benno Exp $ */ +/* $Id: receiver.c,v 1.7 2019/02/14 18:29:08 florian Exp $ */ /* * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv> @@ -40,6 +40,53 @@ enum pfdt { PFD__MAX }; +int +rsync_set_metadata(struct sess *sess, int newfile, + int fd, const struct flist *f, const char *path) +{ + uid_t uid; + gid_t gid; + struct timespec tv[2]; + + /* + * Conditionally adjust identifiers. + * If we have an EPERM, report it but continue on: this just + * means that we're mapping into an unknown (or disallowed) + * group identifier. + */ + + if (sess->opts->preserve_gids || + sess->opts->preserve_uids) { + uid = sess->opts->preserve_uids ? f->st.uid : -1; + gid = sess->opts->preserve_gids ? f->st.gid : -1; + if (fchown(fd, uid, gid) == -1) { + if (errno != EPERM) { + ERR(sess, "%s: fchown", path); + return 0; + } + WARNX(sess, "%s: identity unknown or not available " + "to user.group: %u.%u", f->path, uid, gid); + } else + LOG4(sess, "%s: updated uid and/or gid", f->path); + } + + /* Conditionally adjust file modification time. */ + + if (sess->opts->preserve_times) { + tv[0].tv_sec = time(NULL); + tv[0].tv_nsec = 0; + tv[1].tv_sec = f->st.mtime; + tv[1].tv_nsec = 0; + if (futimens(fd, tv) == -1) { + ERR(sess, "%s: futimens", path); + return 0; + } + LOG4(sess, "%s: updated date", f->path); + } + + return 1; +} + /* * Pledges: unveil, rpath, cpath, wpath, stdio, fattr. * Pledges (dry-run): -cpath, -wpath, -fattr. diff --git a/usr.bin/rsync/uploader.c b/usr.bin/rsync/uploader.c index ad4320aad82..efa2439c3c9 100644 --- a/usr.bin/rsync/uploader.c +++ b/usr.bin/rsync/uploader.c @@ -1,4 +1,4 @@ -/* $Id: uploader.c,v 1.4 2019/02/11 21:41:22 deraadt Exp $ */ +/* $Id: uploader.c,v 1.5 2019/02/14 18:29:08 florian Exp $ */ /* * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv> * @@ -499,12 +499,13 @@ int rsync_uploader(struct upload *u, int *fileinfd, struct sess *sess, int *fileoutfd) { - struct blkset blk; - struct stat st; - void *map, *bufp; - size_t i, mapsz, pos, sz; - off_t offs; - int c; + struct blkset blk; + struct stat st; + void *map, *bufp; + size_t i, mapsz, pos, sz; + off_t offs; + int c; + const struct flist *f; /* This should never get called. */ @@ -617,23 +618,33 @@ rsync_uploader(struct upload *u, int *fileinfd, if (u->state == UPLOAD_READ_LOCAL) { assert(*fileinfd != -1); assert(*fileoutfd == -1); + f = &u->fl[u->idx]; if (fstat(*fileinfd, &st) == -1) { - WARN(sess, "%s: fstat", u->fl[u->idx].path); + ERR(sess, "%s: fstat", f->path); close(*fileinfd); *fileinfd = -1; return -1; } else if (!S_ISREG(st.st_mode)) { - WARNX(sess, "%s: not regular", u->fl[u->idx].path); + ERRX(sess, "%s: not regular", f->path); close(*fileinfd); *fileinfd = -1; return -1; } - if (st.st_size == u->fl[u->idx].st.size && - st.st_mtime == u->fl[u->idx].st.mtime) { - LOG3(sess, "%s: skipping: " - "up to date", u->fl[u->idx].path); + if (st.st_size == f->st.size && + st.st_mtime == f->st.mtime) { + LOG3(sess, "%s: skipping: up to date", f->path); +#if 0 + /* Not yet: investigate behaviour. */ + if (!rsync_set_metadata + (sess, 0, *fileinfd, f, f->path)) { + ERRX1(sess, "rsync_set_metadata"); + close(*fileinfd); + *fileinfd = -1; + return -1; + } +#endif close(*fileinfd); *fileinfd = -1; *fileoutfd = u->fdout; |