version 1.25.2.1, 2021/11/09 13:41:24 |
version 1.26, 2021/05/06 07:29:59 |
|
|
#include <sys/stat.h> |
#include <sys/stat.h> |
|
|
#include <assert.h> |
#include <assert.h> |
#include <err.h> |
|
#include <errno.h> |
#include <errno.h> |
#include <fcntl.h> |
#include <fcntl.h> |
#include <inttypes.h> |
#include <inttypes.h> |
|
|
rsync_receiver(struct sess *sess, int fdin, int fdout, const char *root) |
rsync_receiver(struct sess *sess, int fdin, int fdout, const char *root) |
{ |
{ |
struct flist *fl = NULL, *dfl = NULL; |
struct flist *fl = NULL, *dfl = NULL; |
size_t i, flsz = 0, dflsz = 0; |
size_t i, flsz = 0, dflsz = 0, excl; |
char *tofree; |
char *tofree; |
int rc = 0, dfd = -1, phase = 0, c; |
int rc = 0, dfd = -1, phase = 0, c; |
int32_t ioerror; |
int32_t ioerror; |
|
|
struct upload *ul = NULL; |
struct upload *ul = NULL; |
mode_t oumask; |
mode_t oumask; |
|
|
if (pledge("stdio unix rpath wpath cpath dpath fattr chown getpw unveil", NULL) == -1) |
if (pledge("stdio unix rpath wpath cpath dpath fattr chown getpw unveil", NULL) == -1) { |
err(ERR_IPC, "pledge"); |
ERR("pledge"); |
|
goto out; |
|
} |
|
|
/* |
/* Client sends zero-length exclusions. */ |
* Create the path for our destination directory, if we're not |
|
* in dry-run mode (which would otherwise crash w/the pledge). |
|
* This uses our current umask: we might set the permissions on |
|
* this directory in post_dir(). |
|
*/ |
|
|
|
if (!sess->opts->dry_run) { |
if (!sess->opts->server && |
if ((tofree = strdup(root)) == NULL) |
!io_write_int(sess, fdout, 0)) { |
err(ERR_NOMEM, NULL); |
ERRX1("io_write_int"); |
if (mkpath(tofree) < 0) |
goto out; |
err(ERR_FILE_IO, "%s: mkpath", tofree); |
|
free(tofree); |
|
} |
} |
|
|
/* |
if (sess->opts->server && sess->opts->del) { |
* Make our entire view of the file-system be limited to what's |
if (!io_read_size(sess, fdin, &excl)) { |
* in the root directory. |
ERRX1("io_read_size"); |
* This prevents us from accidentally (or "under the influence") |
goto out; |
* writing into other parts of the file-system. |
} else if (excl != 0) { |
*/ |
ERRX("exclusion list is non-empty"); |
if (sess->opts->basedir[0]) { |
goto out; |
/* |
} |
* XXX just unveil everything for read |
|
* Could unveil each basedir or maybe a common path |
|
* also the fact that relative path are relative to the |
|
* root does not help. |
|
*/ |
|
if (unveil("/", "r") == -1) |
|
err(ERR_IPC, "%s: unveil", root); |
|
} |
} |
|
|
if (unveil(root, "rwc") == -1) |
|
err(ERR_IPC, "%s: unveil", root); |
|
|
|
if (unveil(NULL, NULL) == -1) |
|
err(ERR_IPC, "unveil"); |
|
|
|
/* Client sends exclusions. */ |
|
if (!sess->opts->server) |
|
send_rules(sess, fdout); |
|
|
|
/* Server receives exclusions if delete is on. */ |
|
if (sess->opts->server && sess->opts->del) |
|
recv_rules(sess, fdin); |
|
|
|
/* |
/* |
* Start by receiving the file list and our mystery number. |
* Start by receiving the file list and our mystery number. |
* These we're going to be touching on our local system. |
* These we're going to be touching on our local system. |
|
|
LOG2("%s: receiver destination", root); |
LOG2("%s: receiver destination", root); |
|
|
/* |
/* |
|
* Create the path for our destination directory, if we're not |
|
* in dry-run mode (which would otherwise crash w/the pledge). |
|
* This uses our current umask: we might set the permissions on |
|
* this directory in post_dir(). |
|
*/ |
|
|
|
if (!sess->opts->dry_run) { |
|
if ((tofree = strdup(root)) == NULL) { |
|
ERR("strdup"); |
|
goto out; |
|
} else if (mkpath(tofree) < 0) { |
|
ERRX1("%s: mkpath", root); |
|
free(tofree); |
|
goto out; |
|
} |
|
free(tofree); |
|
} |
|
|
|
/* |
* Disable umask() so we can set permissions fully. |
* Disable umask() so we can set permissions fully. |
* Then open the directory iff we're not in dry_run. |
* Then open the directory iff we're not in dry_run. |
*/ |
*/ |
|
|
oumask = umask(0); |
oumask = umask(0); |
|
|
if (!sess->opts->dry_run) { |
if (!sess->opts->dry_run) { |
dfd = open(root, O_RDONLY | O_DIRECTORY); |
dfd = open(root, O_RDONLY | O_DIRECTORY, 0); |
if (dfd == -1) |
if (dfd == -1) { |
err(ERR_FILE_IO, "%s: open", root); |
ERR("%s: open", root); |
|
goto out; |
|
} |
} |
} |
|
|
/* |
/* |
|
|
sess->opts->recursive && |
sess->opts->recursive && |
!flist_gen_dels(sess, root, &dfl, &dflsz, fl, flsz)) { |
!flist_gen_dels(sess, root, &dfl, &dflsz, fl, flsz)) { |
ERRX1("flist_gen_local"); |
ERRX1("flist_gen_local"); |
|
goto out; |
|
} |
|
|
|
/* |
|
* Make our entire view of the file-system be limited to what's |
|
* in the root directory. |
|
* This prevents us from accidentally (or "under the influence") |
|
* writing into other parts of the file-system. |
|
*/ |
|
|
|
if (unveil(root, "rwc") == -1) { |
|
ERR("%s: unveil", root); |
|
goto out; |
|
} else if (unveil(NULL, NULL) == -1) { |
|
ERR("%s: unveil", root); |
goto out; |
goto out; |
} |
} |
|
|