version 1.23, 2019/03/31 09:26:05 |
version 1.24, 2019/04/04 04:19:54 |
|
|
size_t *max) |
size_t *max) |
{ |
{ |
char *cargv[2], *cp; |
char *cargv[2], *cp; |
int rc = 0; |
int rc = 0, nxdev = 0, flag, i; |
FTS *fts; |
FTS *fts; |
FTSENT *ent; |
FTSENT *ent; |
struct flist *f; |
struct flist *f; |
size_t flsz = 0, stripdir; |
size_t flsz = 0, stripdir; |
|
dev_t *xdev; |
struct stat st; |
struct stat st; |
|
|
cargv[0] = root; |
cargv[0] = root; |
|
|
continue; |
continue; |
} |
} |
|
|
|
/* |
|
* If rsync is told to avoid crossing a filesystem |
|
* boundary when recursing, then replace all mount point |
|
* directories with empty directories. The latter is |
|
* prevented by telling rsync multiple times to avoid |
|
* crossing a filesystem boundary when recursing. |
|
* Replacing mount point directories is tricky. We need |
|
* to sort out which directories to include. As such, |
|
* keep track of unique device inodes, and use these for |
|
* comparison. |
|
*/ |
|
|
|
if (sess->opts->one_file_system && |
|
ent->fts_statp->st_dev != st.st_dev) { |
|
if (sess->opts->one_file_system > 1 || |
|
!S_ISDIR(ent->fts_statp->st_mode)) |
|
continue; |
|
|
|
if ((xdev = malloc(sizeof(dev_t))) == NULL) { |
|
ERRX1(sess, "malloc"); |
|
goto out; |
|
} |
|
|
|
flag = 0; |
|
for (i = 0; i < nxdev; i++) |
|
if (xdev[i] == ent->fts_statp->st_dev) { |
|
flag = 1; |
|
break; |
|
} |
|
if (flag) |
|
continue; |
|
|
|
if (nxdev) |
|
if ((xdev = realloc(xdev, sizeof(dev_t))) == |
|
NULL) { |
|
ERRX1(sess, "realloc"); |
|
goto out; |
|
} |
|
xdev[nxdev] = ent->fts_statp->st_dev; |
|
nxdev++; |
|
} |
|
|
/* Allocate a new file entry. */ |
/* Allocate a new file entry. */ |
|
|
if (!flist_realloc(sess, fl, sz, max)) { |
if (!flist_realloc(sess, fl, sz, max)) { |
|
|
rc = 1; |
rc = 1; |
out: |
out: |
fts_close(fts); |
fts_close(fts); |
|
if (sess->opts->one_file_system) |
|
free(xdev); |
return rc; |
return rc; |
} |
} |
|
|
|
|
size_t *sz, const struct flist *wfl, size_t wflsz) |
size_t *sz, const struct flist *wfl, size_t wflsz) |
{ |
{ |
char **cargv = NULL; |
char **cargv = NULL; |
int rc = 0, c; |
int rc = 0, c, flag; |
FTS *fts = NULL; |
FTS *fts = NULL; |
FTSENT *ent; |
FTSENT *ent; |
struct flist *f; |
struct flist *f; |
|
struct stat st; |
size_t cargvs = 0, i, j, max = 0, stripdir; |
size_t cargvs = 0, i, j, max = 0, stripdir; |
ENTRY hent; |
ENTRY hent; |
ENTRY *hentp; |
ENTRY *hentp; |
|
|
} else if (stripdir >= ent->fts_pathlen) |
} else if (stripdir >= ent->fts_pathlen) |
continue; |
continue; |
|
|
|
assert(ent->fts_statp != NULL); |
|
|
|
/* |
|
* If rsync is told to avoid crossing a filesystem |
|
* boundary when recursing, then exclude all entries |
|
* from the list with a device inode, which does not |
|
* match that of one of the top-level directories. |
|
*/ |
|
|
|
if (sess->opts->one_file_system) { |
|
flag = 0; |
|
for (i = 0; i < wflsz; i++) { |
|
if (stat(wfl[i].path, &st) == -1) { |
|
ERR(sess, "%s: stat", wfl[i].path); |
|
goto out; |
|
} |
|
if (ent->fts_statp->st_dev == st.st_dev) { |
|
flag = 1; |
|
break; |
|
} |
|
} |
|
if (!flag) |
|
continue; |
|
} |
|
|
/* Look up in hashtable. */ |
/* Look up in hashtable. */ |
|
|
memset(&hent, 0, sizeof(ENTRY)); |
memset(&hent, 0, sizeof(ENTRY)); |
|
|
goto out; |
goto out; |
} |
} |
f->wpath = f->path + stripdir; |
f->wpath = f->path + stripdir; |
assert(ent->fts_statp != NULL); |
|
flist_copy_stat(f, ent->fts_statp); |
flist_copy_stat(f, ent->fts_statp); |
errno = 0; |
errno = 0; |
} |
} |