extern struct chmod_mode_struct *chmod_modes;
extern struct filter_list_struct filter_list;
-extern struct filter_list_struct server_filter_list;
+extern struct filter_list_struct daemon_filter_list;
#ifdef ICONV_OPTION
extern int filesfrom_convert;
#endif
}
+static inline int is_daemon_excluded(const char *fname, int is_dir)
+{
+ if (daemon_filter_list.head
+ && check_filter(&daemon_filter_list, FLOG, fname, is_dir) < 0) {
+ errno = ENOENT;
+ return 1;
+ }
+ 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, FLOG, path, 1);
+ *slash = '/';
+ if (ret < 0) {
+ errno = ENOENT;
+ return 1;
+ }
+ }
+
+ if (!ignore_filename
+ && check_filter(&daemon_filter_list, FLOG, 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. */
-static int is_excluded(char *fname, int is_dir, int filter_level)
+static int is_excluded(const char *fname, int is_dir, int filter_level)
{
#if 0 /* This currently never happens, so avoid a useless compare. */
if (filter_level == NO_FILTERS)
return 0;
}
}
- if (server_filter_list.head
- && check_filter(&server_filter_list, fname, is_dir) < 0)
+ if (is_daemon_excluded(fname, is_dir))
return 1;
if (filter_level != ALL_FILTERS)
return 0;
if (filter_list.head
- && check_filter(&filter_list, fname, is_dir) < 0)
+ && check_filter(&filter_list, FINFO, fname, is_dir) < 0)
return 1;
return 0;
}
return 1;
}
-static void send_file_entry(int f, struct file_struct *file, int ndx, int first_ndx)
+static void send_file_entry(int f, const char *fname, struct file_struct *file, int ndx, int first_ndx)
{
static time_t modtime;
static mode_t mode;
static gid_t gid;
static const char *user_name, *group_name;
static char lastname[MAXPATHLEN];
- char fname[MAXPATHLEN];
int first_hlink_ndx = -1;
int l1, l2;
int xflags;
-#ifdef ICONV_OPTION
- if (ic_send != (iconv_t)-1) {
- xbuf outbuf, inbuf;
-
- INIT_CONST_XBUF(outbuf, fname);
-
- if (file->dirname) {
- INIT_XBUF_STRLEN(inbuf, (char*)file->dirname);
- outbuf.size -= 2; /* Reserve room for '/' & 1 more char. */
- if (iconvbufs(ic_send, &inbuf, &outbuf, 0) < 0)
- goto convert_error;
- outbuf.size += 2;
- outbuf.buf[outbuf.len++] = '/';
- }
-
- INIT_XBUF_STRLEN(inbuf, (char*)file->basename);
- if (iconvbufs(ic_send, &inbuf, &outbuf, 0) < 0) {
- convert_error:
- io_error |= IOERR_GENERAL;
- rprintf(FINFO,
- "[%s] cannot convert filename: %s (%s)\n",
- who_am_i(), f_name(file, fname), strerror(errno));
- return;
- }
- outbuf.buf[outbuf.len] = '\0';
- } else
-#endif
- f_name(file, fname);
-
/* Initialize starting value of xflags. */
if (protocol_version >= 30 && S_ISDIR(file->mode)) {
dir_count++;
}
#endif
- clean_fname(thisname, 0);
+ if (*thisname)
+ clean_fname(thisname, 0);
if (sanitize_paths)
- sanitize_path(thisname, thisname, "", 0);
+ sanitize_path(thisname, thisname, "", 0, SP_DEFAULT);
if ((basename = strrchr(thisname, '/')) != NULL) {
int len = basename++ - thisname;
bp += FILE_STRUCT_LEN;
memcpy(bp, basename, basename_len);
- bp += basename_len;
#ifdef SUPPORT_HARD_LINKS
if (xflags & XMIT_HLINKED)
#ifdef SUPPORT_LINKS
if (linkname_len) {
+ bp += basename_len;
if (first_hlink_ndx >= flist->ndx_start) {
struct file_struct *first = flist->files[first_hlink_ndx - flist->ndx_start];
memcpy(bp, F_SYMLINK(first), linkname_len);
} else {
read_sbuf(f, bp, linkname_len - 1);
if (sanitize_paths)
- sanitize_path(bp, bp, "", lastdir_depth);
+ sanitize_path(bp, bp, "", lastdir_depth, SP_DEFAULT);
}
}
#endif
}
clean_fname(thisname, 0);
if (sanitize_paths)
- sanitize_path(thisname, thisname, "", 0);
+ sanitize_path(thisname, thisname, "", 0, SP_DEFAULT);
if (stp && S_ISDIR(stp->st_mode)) {
st = *stp; /* Needed for "symlink/." with --relative. */
bp += FILE_STRUCT_LEN;
memcpy(bp, basename, basename_len);
- bp += basename_len;
#ifdef SUPPORT_HARD_LINKS
if (preserve_hard_links && flist && flist->prev) {
#ifdef SUPPORT_LINKS
if (linkname_len)
- memcpy(bp, linkname, linkname_len);
+ memcpy(bp + basename_len, linkname, linkname_len);
#endif
if (always_checksum && am_sender && S_ISREG(st.st_mode))
}
static struct file_struct *send_file_name(int f, struct file_list *flist,
- char *fname, STRUCT_STAT *stp,
+ const char *fname, STRUCT_STAT *stp,
int flags, int filter_level)
{
struct file_struct *file;
-#if defined SUPPORT_ACLS || defined SUPPORT_XATTRS
- stat_x sx;
-#endif
file = make_file(fname, flist, stp, flags, filter_level);
if (!file)
if (chmod_modes && !S_ISLNK(file->mode))
file->mode = tweak_mode(file->mode, chmod_modes);
+ if (f >= 0) {
+ char fbuf[MAXPATHLEN];
+#if defined SUPPORT_ACLS || defined SUPPORT_XATTRS
+ stat_x sx;
+#endif
+
+#ifdef ICONV_OPTION
+ if (ic_send != (iconv_t)-1) {
+ xbuf outbuf, inbuf;
+
+ INIT_CONST_XBUF(outbuf, fbuf);
+
+ if (file->dirname) {
+ INIT_XBUF_STRLEN(inbuf, (char*)file->dirname);
+ outbuf.size -= 2; /* Reserve room for '/' & 1 more char. */
+ if (iconvbufs(ic_send, &inbuf, &outbuf, 0) < 0)
+ goto convert_error;
+ outbuf.size += 2;
+ outbuf.buf[outbuf.len++] = '/';
+ }
+
+ INIT_XBUF_STRLEN(inbuf, (char*)file->basename);
+ if (iconvbufs(ic_send, &inbuf, &outbuf, 0) < 0) {
+ convert_error:
+ io_error |= IOERR_GENERAL;
+ rprintf(FINFO,
+ "[%s] cannot convert filename: %s (%s)\n",
+ who_am_i(), f_name(file, fbuf), strerror(errno));
+ return NULL;
+ }
+ outbuf.buf[outbuf.len] = '\0';
+ } else
+#endif
+ f_name(file, fbuf);
+
#ifdef SUPPORT_ACLS
- if (preserve_acls && !S_ISLNK(file->mode) && f >= 0) {
- sx.st.st_mode = file->mode;
- sx.acc_acl = sx.def_acl = NULL;
- if (get_acl(fname, &sx) < 0)
- return NULL;
- }
+ if (preserve_acls && !S_ISLNK(file->mode)) {
+ sx.st.st_mode = file->mode;
+ sx.acc_acl = sx.def_acl = NULL;
+ if (get_acl(fname, &sx) < 0)
+ return NULL;
+ }
#endif
#ifdef SUPPORT_XATTRS
- if (preserve_xattrs && f >= 0) {
- sx.xattr = NULL;
- if (get_xattr(fname, &sx) < 0)
- return NULL;
- }
+ if (preserve_xattrs) {
+ sx.xattr = NULL;
+ if (get_xattr(fname, &sx) < 0)
+ return NULL;
+ }
#endif
- maybe_emit_filelist_progress(flist->used + flist_count_offset);
+ send_file_entry(f, fbuf, file, flist->used, flist->ndx_start);
- flist_expand(flist, 1);
- flist->files[flist->used++] = file;
- if (f >= 0) {
- send_file_entry(f, file, flist->used - 1, flist->ndx_start);
#ifdef SUPPORT_ACLS
if (preserve_acls && !S_ISLNK(file->mode)) {
send_acl(&sx, f);
}
#endif
}
+
+ maybe_emit_filelist_progress(flist->used + flist_count_offset);
+
+ flist_expand(flist, 1);
+ flist->files[flist->used++] = file;
+
return file;
}
| (filesfrom_convert ? RL_CONVERT : 0)
#endif
| (eol_nulls || reading_remotely ? RL_EOL_NULLS : 0);
+ int implied_dot_dir = 0;
rprintf(FLOG, "building file list\n");
if (show_filelist_p())
if (use_ff_fd) {
if (read_line(filesfrom_fd, fbuf, sizeof fbuf, rl_flags) == 0)
break;
- sanitize_path(fbuf, fbuf, "", 0);
+ sanitize_path(fbuf, fbuf, "", 0, SP_KEEP_DOT_DIRS);
} else {
if (argc-- == 0)
break;
strlcpy(fbuf, *argv++, MAXPATHLEN);
if (sanitize_paths)
- sanitize_path(fbuf, fbuf, "", 0);
+ sanitize_path(fbuf, fbuf, "", 0, SP_KEEP_DOT_DIRS);
}
len = strlen(fbuf);
*p = '\0';
if (p == fbuf)
dir = "/";
- else
+ else {
dir = fbuf;
+ clean_fname(dir, 0);
+ }
fn = p + 3;
while (*fn == '/')
fn++;
*--fn = '\0'; /* ensure room for '.' */
} else
fn = fbuf;
- len = clean_fname(fn, CFN_KEEP_LEADING_DOT_DIR
- | CFN_KEEP_TRAILING_SLASH
+ /* A leading ./ can be used in relative mode to affect
+ * the dest dir without its name being in the path. */
+ if (*fn == '.' && fn[1] == '/' && !implied_dot_dir) {
+ send_file_name(f, flist, ".", NULL,
+ (flags | FLAG_IMPLIED_DIR) & ~FLAG_CONTENT_DIR,
+ ALL_FILTERS);
+ implied_dot_dir = 1;
+ }
+ len = clean_fname(fn, CFN_KEEP_TRAILING_SLASH
| CFN_DROP_TRAILING_DOT_DIR);
if (len == 1) {
if (fn[0] == '/') {
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;
if (fn != fbuf)
memmove(fbuf, fn, len + 1);
- if (link_stat(fbuf, &st, copy_dirlinks || name_type != NORMAL_NAME) != 0) {
+ if (link_stat(fbuf, &st, copy_dirlinks || name_type != NORMAL_NAME) != 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));
int top_flags = FLAG_TOP_DIR | FLAG_CONTENT_DIR | flags;
file = send_file_name(f, flist, fbuf, &st,
top_flags, ALL_FILTERS);
+ if (!file)
+ continue;
if (inc_recurse) {
- if (name_type == DOT_NAME && file) {
+ if (name_type == DOT_NAME) {
if (send_dir_depth < 0) {
send_dir_depth = 0;
change_local_filter_dir(fbuf, len, send_dir_depth);
}
send_directory(f, flist, fbuf, len, flags);
}
- } else if (file)
+ } else
send_if_directory(f, flist, file, fbuf, len, flags);
} else
send_file_name(f, flist, fbuf, &st, flags, ALL_FILTERS);