From: Wayne Davison Date: Sat, 22 Mar 2008 22:29:34 +0000 (-0700) Subject: Made the filename arg-parsing code skip args that have excluded path X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/commitdiff_plain/b5daf5300fe83e2be5a9c0f3f981d52069189bfa Made the filename arg-parsing code skip args that have excluded path components, returning the same errors that would occur if the path elements didn't actually exist. The glob_match() code was also changed to no longer truncate an arg with an excluded path element (it just omits excluded items from glob matching). --- diff --git a/flist.c b/flist.c index dce55c7b..0a8ace99 100644 --- a/flist.c +++ b/flist.c @@ -242,6 +242,32 @@ static inline int is_daemon_excluded(const char *fname, int is_dir) return 0; } +static inline int path_is_daemon_excluded(char *path, int ignore_filename) +{ + if (daemon_filter_list.head && path) { + char *slash = path; + + while ((slash = strchr(slash+1, '/')) != NULL) { + int ret; + *slash = '\0'; + ret = check_filter(&daemon_filter_list, path, 1); + *slash = '/'; + if (ret < 0) { + errno = ENOENT; + return 1; + } + } + + if (!ignore_filename + && check_filter(&daemon_filter_list, path, 1) < 0) { + errno = ENOENT; + return 1; + } + } + + return 0; +} + /* This function is used to check if a file should be included/excluded * from the list of files based on its name and type etc. The value of * filter_level is set to either SERVER_FILTERS or ALL_FILTERS. */ @@ -1948,6 +1974,12 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) dirlen = dir ? strlen(dir) : 0; if (dirlen != lastdir_len || memcmp(lastdir, dir, dirlen) != 0) { + if (path_is_daemon_excluded(dir, 0)) { + io_error |= IOERR_GENERAL; + rsyserr(FERROR, errno, "push_dir %s failed in %s", + full_fname(dir), curr_dir); + continue; + } if (!push_pathname(dir ? strdup(dir) : NULL, dirlen)) continue; lastdir = pathname; @@ -1959,7 +1991,8 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) memmove(fbuf, fn, len + 1); if (link_stat(fbuf, &st, copy_dirlinks || name_type != NORMAL_NAME) != 0 - || is_daemon_excluded(fbuf, S_ISDIR(st.st_mode) != 0)) { + || is_daemon_excluded(fbuf, S_ISDIR(st.st_mode) != 0) + || (relative_paths && path_is_daemon_excluded(fbuf, 1))) { io_error |= IOERR_GENERAL; rsyserr(FERROR_XFER, errno, "link_stat %s failed", full_fname(fbuf)); diff --git a/util.c b/util.c index a4a08e7c..6f5bfc55 100644 --- a/util.c +++ b/util.c @@ -586,22 +586,15 @@ static inline void call_glob_match(const char *name, int len, int from_glob, STRUCT_STAT st; int is_dir; - if (do_stat(glob.arg_buf, &st) != 0) { - if (from_glob) - return; - is_dir = 0; - } else { - is_dir = S_ISDIR(st.st_mode) != 0; - if (arg && !is_dir) - return; - } + if (do_stat(glob.arg_buf, &st) != 0) + return; + is_dir = S_ISDIR(st.st_mode) != 0; + if (arg && !is_dir) + return; if (daemon_filter_list.head - && check_filter(&daemon_filter_list, use_buf, is_dir) < 0) { - if (from_glob) - return; - arg = NULL; - } + && check_filter(&daemon_filter_list, use_buf, is_dir) < 0) + return; } if (arg) {