mirror of
https://github.com/RsyncProject/rsync.git
synced 2026-05-07 22:45:44 -04:00
Add parent-dir validation for --no-inc-recurse too.
This commit is contained in:
32
flist.c
32
flist.c
@@ -2502,8 +2502,8 @@ struct file_list *recv_file_list(int f, int dir_ndx)
|
||||
const char *d = dir_ndx >= 0 ? f_name(dir_flist->files[dir_ndx], NULL) : empty_dir;
|
||||
if (strcmp(cur_dir, d) != 0) {
|
||||
rprintf(FERROR,
|
||||
"ABORTING due to invalid dir prefix from sender: %s (should be: %s)\n",
|
||||
cur_dir, d);
|
||||
"ABORTING due to invalid path from sender: %s/%s\n",
|
||||
cur_dir, file->basename);
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
}
|
||||
good_dirname = cur_dir;
|
||||
@@ -2689,6 +2689,34 @@ int flist_find(struct file_list *flist, struct file_struct *f)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Search for a name in the file list. You must specify want_dir_match as:
|
||||
* 1=match directories, 0=match non-directories, or -1=match either. */
|
||||
int flist_find_name(struct file_list *flist, const char *fname, int want_dir_match)
|
||||
{
|
||||
struct { /* We have to create a temporary file_struct for the search. */
|
||||
struct file_struct f;
|
||||
char name_space[MAXPATHLEN];
|
||||
} t;
|
||||
char fbuf[MAXPATHLEN];
|
||||
const char *slash = strrchr(fname, '/');
|
||||
const char *basename = slash ? slash+1 : fname;
|
||||
|
||||
memset(&t.f, 0, FILE_STRUCT_LEN);
|
||||
memcpy((void *)t.f.basename, basename, strlen(basename)+1);
|
||||
|
||||
if (slash) {
|
||||
strlcpy(fbuf, fname, slash - fname + 1);
|
||||
t.f.dirname = fbuf;
|
||||
} else
|
||||
t.f.dirname = NULL;
|
||||
|
||||
t.f.mode = want_dir_match > 0 ? S_IFDIR : S_IFREG;
|
||||
|
||||
if (want_dir_match < 0)
|
||||
return flist_find_ignore_dirness(flist, &t.f);
|
||||
return flist_find(flist, &t.f);
|
||||
}
|
||||
|
||||
/* Search for an identically-named item in the file list. Differs from
|
||||
* flist_find in that an item that agrees with "f" in directory-ness is
|
||||
* preferred but one that does not is still found. */
|
||||
|
||||
14
generator.c
14
generator.c
@@ -1177,6 +1177,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
int itemizing, enum logcode code, int f_out)
|
||||
{
|
||||
static const char *parent_dirname = "";
|
||||
static struct file_struct *prior_dir_file = NULL;
|
||||
/* Missing dir not created due to --dry-run; will still be scanned. */
|
||||
static struct file_struct *dry_missing_dir = NULL;
|
||||
/* Missing dir whose contents are skipped altogether due to
|
||||
@@ -1256,6 +1257,18 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
const char *dn = file->dirname ? file->dirname : ".";
|
||||
dry_missing_dir = NULL;
|
||||
if (parent_dirname != dn && strcmp(parent_dirname, dn) != 0) {
|
||||
/* Each parent dir must be in the file list or the flist data is bad.
|
||||
* Optimization: most of the time the parent dir will be the last dir
|
||||
* this function was asked to process in the file list. */
|
||||
if (!inc_recurse
|
||||
&& (*dn != '.' || dn[1]) /* Avoid an issue with --relative and the "." dir. */
|
||||
&& (prior_dir_file && strcmp(dn, f_name(prior_dir_file, NULL)) != 0)
|
||||
&& flist_find_name(cur_flist, dn, 1) < 0) {
|
||||
rprintf(FERROR,
|
||||
"ABORTING due to invalid path from sender: %s/%s\n",
|
||||
dn, file->basename);
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
}
|
||||
if (relative_paths && !implied_dirs
|
||||
&& do_stat(dn, &sx.st) < 0) {
|
||||
if (dry_run)
|
||||
@@ -1467,6 +1480,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
else
|
||||
change_local_filter_dir(fname, strlen(fname), F_DEPTH(file));
|
||||
}
|
||||
prior_dir_file = file;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user