#include "rsync.h"
-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 numeric_ids;
-
extern int recurse;
extern int xfer_dirs;
-extern char curr_dir[MAXPATHLEN];
-extern unsigned int curr_dir_len;
-extern char *backup_dir;
-extern char *backup_suffix;
extern int filesfrom_fd;
-
extern int one_file_system;
extern int keep_dirlinks;
extern int preserve_links;
extern int preserve_gid;
extern int relative_paths;
extern int implied_dirs;
-extern int make_backups;
-extern int backup_suffix_len;
extern int copy_links;
extern int copy_unsafe_links;
extern int protocol_version;
extern int sanitize_paths;
-extern int max_delete;
extern int orig_umask;
-extern int list_only;
+extern struct stats stats;
+extern struct file_list *the_file_list;
+
+extern char curr_dir[MAXPATHLEN];
extern struct filter_list_struct filter_list;
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 int deletion_count = 0; /* used to implement --max-delete */
+static struct file_list *sorting_flist;
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;
char fname[MAXPATHLEN];
int l1, l2;
- if (f == -1)
+ if (f < 0)
return;
if (!file) {
STRUCT_STAT st2;
int save_mode = file->mode;
file->mode = S_IFDIR; /* find a directory w/our name */
- if (flist_find(received_flist, file) >= 0
+ if (flist_find(the_file_list, file) >= 0
&& do_stat(thisname, &st2) == 0 && S_ISDIR(st2.st_mode)) {
file->modtime = st2.st_mtime;
file->length = st2.st_size;
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;
struct file_struct *file;
char fbuf[MAXPATHLEN];
- if (!(file = make_file(fname, flist, ALL_FILTERS)))
+ file = make_file(fname, flist, f == -2 ? SERVER_FILTERS : ALL_FILTERS);
+ if (!file)
return;
maybe_emit_filelist_progress(flist);
}
-/* 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. */
+/* 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");
start_read = stats.total_read;
flist = flist_new(WITH_HLINK, "recv_file_list");
- received_flist = flist;
flist->count = 0;
flist->malloced = 1000;
clean_flist(flist, relative_paths, 1);
- if (f != -1) {
+ if (f >= 0) {
/* Now send the uid/gid list. This was introduced in
* protocol version 15 */
recv_uid_list(f, flist);
}
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,
}
-static int is_backup_file(char *fn)
-{
- int k = strlen(fn) - backup_suffix_len;
- return k > 0 && strcmp(fn+k, backup_suffix) == 0;
-}
-
-
-/* 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)
+/* 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)
{
- 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... */
+ struct file_list *dirlist;
+ char dirbuf[MAXPATHLEN];
+ int save_recurse = recurse;
- 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;
+ if (dlen < 0) {
+ dlen = strlcpy(dirbuf, dirname, MAXPATHLEN);
+ if (dlen >= MAXPATHLEN)
+ return NULL;
+ dirname = dirbuf;
}
- 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");
+ dirlist = flist_new(WITHOUT_HLINK, "get_dirlist");
recurse = 0;
- send_directory(-1, dir_list, fbuf, dlen);
- recurse = -1;
- fbuf[dlen] = '\0';
-
- if (verbose > 3)
- output_flist(dir_list, "delete");
-
- delete_missing(flist, dir_list, fbuf);
-
- flist_free(dir_list);
-}
+ send_directory(ignore_filter_rules ? -2 : -1, dirlist, dirname, dlen);
+ recurse = save_recurse;
+ clean_flist(dirlist, 0, 0);
-/* 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)
-{
- int i, mode;
-
- if (max_delete && deletion_count >= max_delete)
- return;
-
- if (verbose > 2)
- rprintf(FINFO, "delete_missing(%s)\n", safe_fname(dirname));
+ if (verbose > 3)
+ output_flist(dirlist);
- for (i = dir_list->count; i--; ) {
- if (!dir_list->files[i]->basename)
- continue;
- mode = dir_list->files[i]->mode;
- if (flist_find(full_list, dir_list->files[i]) < 0) {
- char *f = f_name(dir_list->files[i]);
- if (make_backups && (backup_dir || !is_backup_file(f))
- && !S_ISDIR(mode)) {
- make_backup(f);
- if (verbose) {
- rprintf(FINFO, "deleting %s\n",
- safe_fname(f));
- }
- } else if (S_ISDIR(mode))
- delete_file(f, DEL_DIR | DEL_FORCE_RECURSE);
- else
- delete_file(f, 0);
- deletion_count++;
- if (max_delete && deletion_count >= max_delete)
- break;
- }
- }
+ return dirlist;
}