extern struct stats stats;
extern int verbose;
-extern int do_progress;
+extern int dry_run;
+extern int list_only;
extern int am_root;
extern int am_server;
extern int am_daemon;
extern int am_sender;
+extern int do_progress;
extern int always_checksum;
extern int module_id;
extern int ignore_errors;
extern int copy_unsafe_links;
extern int protocol_version;
extern int sanitize_paths;
-extern int deletion_count;
-extern int max_delete;
extern int orig_umask;
-extern int list_only;
-extern unsigned int curr_dir_len;
-extern char *log_format;
extern char curr_dir[MAXPATHLEN];
extern struct filter_list_struct server_filter_list;
int io_error;
+dev_t filesystem_dev; /* used to implement -x */
static char empty_sum[MD4_SUM_LENGTH];
static unsigned int file_struct_len;
static struct file_list *received_flist, *sorting_flist;
-static dev_t filesystem_dev; /* used to implement -x */
static void clean_flist(struct file_list *flist, int strip_root, int no_dups);
-static void output_flist(struct file_list *flist, const char *whose_list);
+static void output_flist(struct file_list *flist);
void init_flist(void)
{
static void send_directory(int f, struct file_list *flist,
- char *fbuf, unsigned int offset);
+ char *fbuf, int len);
static char *flist_dir;
static int flist_dir_len;
file->mode = save_mode;
}
- if (!S_ISDIR(st.st_mode))
+ if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode))
stats.total_size += st.st_size;
return file;
}
-/* 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() calls this with f set to -2, which indicates that local
- * filter rules should be ignored. */
+/* 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. */
static void send_directory(int f, struct file_list *flist,
- char *fbuf, unsigned int len)
+ char *fbuf, int len)
{
struct dirent *di;
+ unsigned remainder;
char *p;
DIR *d;
if (len != 1 || *fbuf != '/')
*p++ = '/';
*p = '\0';
+ remainder = MAXPATHLEN - (p - fbuf);
for (errno = 0, di = readdir(d); di; errno = 0, di = readdir(d)) {
char *dname = d_name(di);
if (dname[0] == '.' && (dname[1] == '\0'
|| (dname[1] == '.' && dname[2] == '\0')))
continue;
- if (strlcpy(p, dname, MAXPATHLEN - len) < MAXPATHLEN - len) {
+ if (strlcpy(p, dname, remainder) < remainder) {
int do_subdirs = recurse >= 1 ? recurse-- : recurse;
send_file_name(f, flist, fbuf, do_subdirs, 0);
} else {
full_fname(fbuf));
}
}
+
+ fbuf[len] = '\0';
+
if (errno) {
io_error |= IOERR_GENERAL;
- *p = '\0';
rsyserr(FERROR, errno, "readdir(%s)", full_fname(fbuf));
}
stats.num_files = flist->count;
if (verbose > 3)
- output_flist(flist, who_am_i());
+ output_flist(flist);
if (verbose > 2)
rprintf(FINFO, "send_file_list done\n");
}
if (verbose > 3)
- output_flist(flist, who_am_i());
+ output_flist(flist);
if (list_only) {
int i;
}
}
-static void output_flist(struct file_list *flist, const char *whose_list)
+
+static void output_flist(struct file_list *flist)
{
char uidbuf[16], gidbuf[16], depthbuf[16];
struct file_struct *file;
+ const char *who = who_am_i();
int i;
for (i = 0; i < flist->count; i++) {
if (!am_sender)
sprintf(depthbuf, "%d", file->dir.depth);
rprintf(FINFO, "[%s] i=%d %s %s%s%s%s mode=0%o len=%.0f%s%s flags=%x\n",
- whose_list, i, am_sender ? NS(file->dir.root) : depthbuf,
+ who, i, am_sender ? NS(file->dir.root) : depthbuf,
file->dirname ? safe_fname(file->dirname) : "",
file->dirname ? "/" : "", NS(file->basename),
S_ISDIR(file->mode) ? "/" : "", (int)file->mode,
}
-struct file_list *get_dirlist(const char *dirname, int ignore_filter_rules)
+/* Do a non-recursive scan of the named directory, possibly ignoring all
+ * exclude rules except for the daemon's. If "dlen" is >=0, it is the length
+ * of the dirname string, and also indicates that "dirname" is a MAXPATHLEN
+ * buffer (the functions we call will append names onto the end, but the old
+ * dir value will be restored on exit). */
+struct file_list *get_dirlist(char *dirname, int dlen,
+ int ignore_filter_rules)
{
struct file_list *dirlist;
char dirbuf[MAXPATHLEN];
- int dlen;
int save_recurse = recurse;
- dlen = strlcpy(dirbuf, dirname, MAXPATHLEN);
- if (dlen >= MAXPATHLEN)
- return NULL;
+ if (dlen < 0) {
+ dlen = strlcpy(dirbuf, dirname, MAXPATHLEN);
+ if (dlen >= MAXPATHLEN)
+ return NULL;
+ dirname = dirbuf;
+ }
dirlist = flist_new(WITHOUT_HLINK, "get_dirlist");
+
recurse = 0;
- send_directory(ignore_filter_rules ? -2 : -1, dirlist, dirbuf, dlen);
+ send_directory(ignore_filter_rules ? -2 : -1, dirlist, dirname, dlen);
recurse = save_recurse;
- return dirlist;
-}
-
-
-/* This function is used to implement per-directory deletion, and
- * is used by all the --delete-WHEN options. Note that the fbuf
- * pointer must point to a MAXPATHLEN buffer with the name of the
- * directory in it (the functions we call will append names onto
- * the end, but the old dir value will be restored on exit). */
-void delete_in_dir(struct file_list *flist, char *fbuf,
- struct file_struct *file)
-{
- static int min_depth = MAXPATHLEN, cur_depth = -1;
- static void *filt_array[MAXPATHLEN/2+1];
- struct file_list *dir_list;
- STRUCT_STAT st;
- int dlen;
-
- if (!flist) {
- while (cur_depth >= min_depth)
- pop_local_filters(filt_array[cur_depth--]);
- min_depth = MAXPATHLEN;
- cur_depth = -1;
- return;
- }
- if (file->dir.depth >= MAXPATHLEN/2+1)
- return; /* Impossible... */
-
- if (max_delete && deletion_count >= max_delete)
- return;
-
- if (io_error && !(lp_ignore_errors(module_id) || ignore_errors)) {
- rprintf(FINFO,
- "IO error encountered -- skipping file deletion\n");
- max_delete = -1; /* avoid duplicating the above warning */
- return;
- }
-
- while (cur_depth >= file->dir.depth && cur_depth >= min_depth)
- pop_local_filters(filt_array[cur_depth--]);
- cur_depth = file->dir.depth;
- if (min_depth > cur_depth)
- min_depth = cur_depth;
- dlen = strlen(fbuf);
- filt_array[cur_depth] = push_local_filters(fbuf, dlen);
-
- if (link_stat(fbuf, &st, keep_dirlinks) < 0)
- return;
-
- if (one_file_system && file->flags & FLAG_TOP_DIR)
- filesystem_dev = st.st_dev;
-
- dir_list = flist_new(WITHOUT_HLINK, "delete_in_dir");
-
- recurse = 0;
- send_directory(-1, dir_list, fbuf, dlen);
- recurse = -1;
- fbuf[dlen] = '\0';
+ clean_flist(dirlist, 0, 0);
if (verbose > 3)
- output_flist(dir_list, "delete");
-
- delete_missing(flist, dir_list, fbuf);
-
- flist_free(dir_list);
-}
-
+ output_flist(dirlist);
-/* If an item in dir_list is not found in full_list, delete it from the
- * filesystem. */
-void delete_missing(struct file_list *full_list, struct file_list *dir_list,
- const char *dirname)
-{
- char fbuf[MAXPATHLEN];
- int i;
-
- if (max_delete && deletion_count >= max_delete)
- return;
-
- if (verbose > 2)
- rprintf(FINFO, "delete_missing(%s)\n", safe_fname(dirname));
-
- for (i = dir_list->count; i--; ) {
- if (!dir_list->files[i]->basename)
- continue;
- if (flist_find(full_list, dir_list->files[i]) < 0) {
- char *fn = f_name_to(dir_list->files[i], fbuf);
- int mode = dir_list->files[i]->mode;
- int dflag = S_ISDIR(mode) ? DEL_FORCE_RECURSE : 0;
- if (delete_file(fn, mode, dflag) < 0)
- break;
- }
- }
+ return dirlist;
}