This fixed a glitch in the daemon-exclusion code that allowed
an exclude rule such as ".*" or "*/" to affect a '.' dir.
#define NORMAL_NAME 0
#define SLASH_ENDING_NAME 1
#define NORMAL_NAME 0
#define SLASH_ENDING_NAME 1
/* Starting from protocol version 26, we always use 64-bit ino_t and dev_t
* internally, even if this platform does not allow files to have 64-bit inums.
/* Starting from protocol version 26, we always use 64-bit ino_t and dev_t
* internally, even if this platform does not allow files to have 64-bit inums.
if (filter_level == NO_FILTERS)
return 0;
#endif
if (filter_level == NO_FILTERS)
return 0;
#endif
- if (fname) {
- /* never exclude '.', even if somebody does --exclude '*' */
- if (fname[0] == '.' && !fname[1])
- return 0;
- /* Handle the -R version of the '.' dir. */
- if (fname[0] == '/') {
- int len = strlen(fname);
- if (fname[len-1] == '.' && fname[len-2] == '/')
- return 0;
- }
- }
if (is_daemon_excluded(fname, is_dir))
return 1;
if (filter_level != ALL_FILTERS)
if (is_daemon_excluded(fname, is_dir))
return 1;
if (filter_level != ALL_FILTERS)
const char *basename;
alloc_pool_t *pool;
STRUCT_STAT st;
const char *basename;
alloc_pool_t *pool;
STRUCT_STAT st;
char *bp;
if (strlcpy(thisname, fname, sizeof thisname) >= sizeof thisname) {
char *bp;
if (strlcpy(thisname, fname, sizeof thisname) >= sizeof thisname) {
} else
flags &= ~FLAG_CONTENT_DIR;
} else
flags &= ~FLAG_CONTENT_DIR;
- if (is_excluded(thisname, S_ISDIR(st.st_mode) != 0, filter_level)) {
+ if (S_ISDIR(st.st_mode)) {
+ if (flags & FLAG_DOTDIR_NAME) {
+ /* A "." fname (or "/." fname in relative mode) is
+ * never excluded. No other trailing-dotdir names
+ * are possible. */
+ excl_ret = 0;
+ } else
+ excl_ret = is_excluded(thisname, 1, filter_level);
+ } else
+ excl_ret = is_excluded(thisname, 0, filter_level);
+ if (excl_ret) {
if (ignore_perishable)
non_perishable_cnt++;
return NULL;
if (ignore_perishable)
non_perishable_cnt++;
return NULL;
int64 start_write;
int use_ff_fd = 0;
int disable_buffering;
int64 start_write;
int use_ff_fd = 0;
int disable_buffering;
- int flags = recurse ? FLAG_CONTENT_DIR : 0;
+ int arg_flags, flags = recurse ? FLAG_CONTENT_DIR : 0;
int reading_remotely = filesfrom_host != NULL;
int rl_flags = (reading_remotely ? 0 : RL_DUMP_COMMENTS)
#ifdef ICONV_OPTION
int reading_remotely = filesfrom_host != NULL;
int rl_flags = (reading_remotely ? 0 : RL_DUMP_COMMENTS)
#ifdef ICONV_OPTION
fbuf[len++] = '.';
fbuf[len] = '\0';
}
fbuf[len++] = '.';
fbuf[len] = '\0';
}
+ name_type = DOTDIR_NAME;
} else if (len > 1 && fbuf[len-1] == '.' && fbuf[len-2] == '.'
&& (len == 2 || fbuf[len-3] == '/')) {
if (len + 2 >= MAXPATHLEN)
} else if (len > 1 && fbuf[len-1] == '.' && fbuf[len-2] == '.'
&& (len == 2 || fbuf[len-3] == '/')) {
if (len + 2 >= MAXPATHLEN)
fbuf[len++] = '/';
fbuf[len++] = '.';
fbuf[len] = '\0';
fbuf[len++] = '/';
fbuf[len++] = '.';
fbuf[len] = '\0';
+ name_type = DOTDIR_NAME;
} else if (fbuf[len-1] == '.' && (len == 1 || fbuf[len-2] == '/'))
} else if (fbuf[len-1] == '.' && (len == 1 || fbuf[len-2] == '/'))
+ name_type = DOTDIR_NAME;
else
name_type = NORMAL_NAME;
else
name_type = NORMAL_NAME;
if (fn[0] == '/') {
fn = "/.";
len = 2;
if (fn[0] == '/') {
fn = "/.";
len = 2;
+ name_type = DOTDIR_NAME;
+ name_type = DOTDIR_NAME;
} else if (fn[len-1] == '/') {
fn[--len] = '\0';
if (len == 1 && *fn == '.')
} else if (fn[len-1] == '/') {
fn[--len] = '\0';
if (len == 1 && *fn == '.')
+ name_type = DOTDIR_NAME;
else
name_type = SLASH_ENDING_NAME;
}
else
name_type = SLASH_ENDING_NAME;
}
if (!*fn) {
len = 1;
fn = ".";
if (!*fn) {
len = 1;
fn = ".";
+ name_type = DOTDIR_NAME;
}
dirlen = dir ? strlen(dir) : 0;
}
dirlen = dir ? strlen(dir) : 0;
memmove(fbuf, fn, len + 1);
if (link_stat(fbuf, &st, copy_dirlinks || name_type != NORMAL_NAME) != 0
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)
+ || (name_type != DOTDIR_NAME && is_daemon_excluded(fbuf, S_ISDIR(st.st_mode)))
|| (relative_paths && path_is_daemon_excluded(fbuf, 1))) {
io_error |= IOERR_GENERAL;
rsyserr(FERROR_XFER, errno, "link_stat %s failed",
|| (relative_paths && path_is_daemon_excluded(fbuf, 1))) {
io_error |= IOERR_GENERAL;
rsyserr(FERROR_XFER, errno, "link_stat %s failed",
if (one_file_system)
filesystem_dev = st.st_dev;
if (one_file_system)
filesystem_dev = st.st_dev;
+ arg_flags = name_type == DOTDIR_NAME ? FLAG_DOTDIR_NAME : 0;
+
if (recurse || (xfer_dirs && name_type != NORMAL_NAME)) {
struct file_struct *file;
if (recurse || (xfer_dirs && name_type != NORMAL_NAME)) {
struct file_struct *file;
- int top_flags = FLAG_TOP_DIR | FLAG_CONTENT_DIR | flags;
+ arg_flags |= FLAG_TOP_DIR | FLAG_CONTENT_DIR;
file = send_file_name(f, flist, fbuf, &st,
file = send_file_name(f, flist, fbuf, &st,
- top_flags, ALL_FILTERS);
+ arg_flags | flags, ALL_FILTERS);
if (!file)
continue;
if (inc_recurse) {
if (!file)
continue;
if (inc_recurse) {
- if (name_type == DOT_NAME) {
+ if (name_type == DOTDIR_NAME) {
if (send_dir_depth < 0) {
send_dir_depth = 0;
change_local_filter_dir(fbuf, len, send_dir_depth);
if (send_dir_depth < 0) {
send_dir_depth = 0;
change_local_filter_dir(fbuf, len, send_dir_depth);
} else
send_if_directory(f, flist, file, fbuf, len, flags);
} else
} else
send_if_directory(f, flist, file, fbuf, len, flags);
} else
- send_file_name(f, flist, fbuf, &st, flags, ALL_FILTERS);
+ send_file_name(f, flist, fbuf, &st, arg_flags | flags, ALL_FILTERS);
}
gettimeofday(&end_tv, NULL);
}
gettimeofday(&end_tv, NULL);
/* These flags are passed to functions but not stored. */
#define FLAG_DIVERT_DIRS (1<<16)/* sender */
/* These flags are passed to functions but not stored. */
#define FLAG_DIVERT_DIRS (1<<16)/* sender */
+#define FLAG_DOTDIR_NAME (1<<17)/* sender */
#define BITS_SET(val,bits) (((val) & (bits)) == (bits))
#define BITS_SETnUNSET(val,onbits,offbits) (((val) & ((onbits)|(offbits))) == (onbits))
#define BITS_SET(val,bits) (((val) & (bits)) == (bits))
#define BITS_SETnUNSET(val,onbits,offbits) (((val) & ((onbits)|(offbits))) == (onbits))