dev_t filesystem_dev; /* used to implement -x */
static char empty_sum[MD4_SUM_LENGTH];
+static int flist_count_offset;
static unsigned int file_struct_len;
static struct file_list *sorting_flist;
}
-static void emit_filelist_progress(const struct file_list *flist)
+static void emit_filelist_progress(int count)
{
- rprintf(FINFO, " %d files...\r", flist->count);
+ rprintf(FINFO, " %d files...\r", count);
}
-static void maybe_emit_filelist_progress(const struct file_list *flist)
+static void maybe_emit_filelist_progress(int count)
{
- if (do_progress && show_filelist_p() && (flist->count % 100) == 0)
- emit_filelist_progress(flist);
+ if (do_progress && show_filelist_p() && (count % 100) == 0)
+ emit_filelist_progress(count);
}
if (flags & XMIT_TOP_DIR) {
in_del_hier = 1;
del_hier_name_len = file->dir.depth == 0 ? 0 : l1 + l2;
+ if (relative_paths && del_hier_name_len > 2
+ && basename_len == 1+1 && *basename == '.')
+ del_hier_name_len -= 2;
file->flags |= FLAG_TOP_DIR | FLAG_DEL_HERE;
} else if (in_del_hier) {
if (!relative_paths || !del_hier_name_len
}
-void send_file_name(int f, struct file_list *flist, char *fname,
- int recursive, unsigned short base_flags)
+static struct file_struct *send_file_name(int f, struct file_list *flist,
+ char *fname, unsigned short base_flags)
{
struct file_struct *file;
- char fbuf[MAXPATHLEN];
file = make_file(fname, flist, f == -2 ? SERVER_FILTERS : ALL_FILTERS);
if (!file)
- return;
+ return NULL;
- maybe_emit_filelist_progress(flist);
+ maybe_emit_filelist_progress(flist->count + flist_count_offset);
flist_expand(flist);
flist->files[flist->count++] = file;
send_file_entry(file, f, base_flags);
}
+ return file;
+}
+
+static void send_if_directory(int f, struct file_list *flist,
+ struct file_struct *file)
+{
+ char fbuf[MAXPATHLEN];
- if (recursive && S_ISDIR(file->mode)
+ if (S_ISDIR(file->mode)
&& !(file->flags & FLAG_MOUNT_POINT) && f_name_to(file, fbuf)) {
void *save_filters;
unsigned int len = strlen(fbuf);
}
-/* Note that the "recurse" value either contains -1, for infinite recursion, or
- * a number >= 0 indicating how many levels of recursion we will allow. This
- * function is normally called by the sender, but the receiving side also calls
- * it from delete_in_dir() with f set to -1 so that we just construct the file
- * list in memory without sending it over the wire. Also, get_dirlist() might
- * call this with f set to -2, which indicates that local filter rules should
- * be ignored. */
+/* This function is normally called by the sender, but the receiving side also
+ * calls it from get_dirlist() with f set to -1 so that we just construct the
+ * file list in memory without sending it over the wire. Also, get_dirlist()
+ * might call this with f set to -2, which also indicates that local filter
+ * rules should be ignored. */
static void send_directory(int f, struct file_list *flist,
char *fbuf, int len)
{
unsigned remainder;
char *p;
DIR *d;
+ int start = flist->count;
if (!(d = opendir(fbuf))) {
io_error |= IOERR_GENERAL;
if (dname[0] == '.' && (dname[1] == '\0'
|| (dname[1] == '.' && dname[2] == '\0')))
continue;
- if (strlcpy(p, dname, remainder) < remainder) {
- int do_subdirs = recurse >= 1 ? recurse-- : recurse;
- send_file_name(f, flist, fbuf, do_subdirs, 0);
- } else {
+ if (strlcpy(p, dname, remainder) < remainder)
+ send_file_name(f, flist, fbuf, 0);
+ else {
io_error |= IOERR_GENERAL;
rprintf(FINFO,
"cannot send long-named file %s\n",
}
closedir(d);
+
+ if (recurse) {
+ int i, end = flist->count - 1;
+ for (i = start; i <= end; i++)
+ send_if_directory(f, flist, flist->files[i]);
+ }
}
}
while (1) {
+ struct file_struct *file;
char fname2[MAXPATHLEN];
char *fname = fname2;
- int do_subdirs;
+ int is_dot_dir;
if (use_ff_fd) {
if (read_filesfrom_line(filesfrom_fd, fname) == 0)
fname[l++] = '.';
fname[l] = '\0';
}
+ is_dot_dir = 1;
+ } else {
+ is_dot_dir = fname[l-1] == '.'
+ && (l == 1 || fname[l-2] == '/');
}
- if (fname[l-1] == '.' && (l == 1 || fname[l-2] == '/')) {
- if (!recurse && xfer_dirs)
- recurse = 1; /* allow one level */
- } else if (recurse > 0)
- recurse = 0;
if (link_stat(fname, &st, keep_dirlinks) != 0) {
io_error |= IOERR_GENERAL;
xfer_dirs = 1;
while ((slash = strchr(slash+1, '/')) != 0) {
*slash = 0;
- send_file_name(f, flist, fname, 0, 0);
+ send_file_name(f, flist, fname, 0);
*slash = '/';
}
copy_links = save_copy_links;
if (one_file_system)
filesystem_dev = st.st_dev;
- do_subdirs = recurse >= 1 ? recurse-- : recurse;
- send_file_name(f, flist, fname, do_subdirs, XMIT_TOP_DIR);
+ if ((file = send_file_name(f, flist, fname, XMIT_TOP_DIR))) {
+ if (recurse || (xfer_dirs && is_dot_dir))
+ send_if_directory(f, flist, file);
+ }
if (olddir[0]) {
flist_dir = NULL;
flist->files[flist->count++] = file;
- maybe_emit_filelist_progress(flist);
+ maybe_emit_filelist_progress(flist->count);
if (verbose > 2) {
rprintf(FINFO, "recv_file_name(%s)\n",
if (!*c2) {
switch (state2) {
case s_DIR:
- if (state1 == s_SLASH && sorting_flist) {
- int j;
- /* Optimize for future comparisons. */
- for (j = 0;
- j < sorting_flist->count;
- j++) {
- struct file_struct *fp
- = sorting_flist->files[j];
- if (fp->dirname == f2->dirname)
- fp->dirname = f1->dirname;
- }
- }
state2 = s_SLASH;
c2 = (uchar*)"/";
break;
recurse = 0;
send_directory(ignore_filter_rules ? -2 : -1, dirlist, dirname, dlen);
recurse = save_recurse;
+ if (do_progress)
+ flist_count_offset += dirlist->count;
clean_flist(dirlist, 0, 0);