static struct exclude_struct **exclude_list;
+/*
+ * Optimization for special case when all included files are explicitly
+ * listed without wildcards in the "exclude" list followed by a "- *"
+ * to exclude the rest.
+ * Contributed by Dave Dykstra <dwd@bell-labs.com>
+ */
+static int only_included_files = 1;
+static struct exclude_struct *exclude_the_rest;
+
+int send_included_file_names(int f,struct file_list *flist)
+{
+ struct exclude_struct *ex, **ex_list;
+ int n;
+ char *p;
+
+ if (!only_included_files || (exclude_the_rest == NULL))
+ return 0;
+
+ if (verbose > 1) {
+ rprintf(FINFO,"(using include-only optimization) ");
+ }
+
+ /* set exclude_list to NULL temporarily so check_exclude */
+ /* will always return true */
+ ex_list = exclude_list;
+ exclude_list = NULL;
+ for (n=0; (ex = ex_list[n]) != NULL; n++) {
+ if (ex == exclude_the_rest)
+ break;
+ p = ex->pattern;
+ while (*p == '/') {
+ /* skip the allowed beginning slashes */
+ p++;
+ }
+ send_file_name(f,flist,p,0,0);
+ }
+ exclude_list = ex_list;
+
+ return 1;
+}
+
/* build an exclude structure given a exclude pattern */
static struct exclude_struct *make_exclude(char *pattern, int include)
{
if (!ret->orig || !ret->pattern) out_of_memory("make_exclude");
- if (strpbrk(pattern, "*[?")) ret->regular_exp = 1;
+ if (strpbrk(pattern, "*[?")) {
+ if (!ret->include && (*pattern == '*') && (*(pattern+1) == '\0')) {
+ exclude_the_rest = ret;
+ } else {
+ only_included_files = 0;
+ }
+ ret->regular_exp = 1;
+ } else if (!ret->include) {
+ only_included_files = 0;
+ }
if (strlen(pattern) > 1 && pattern[strlen(pattern)-1] == '/') {
ret->pattern[strlen(pattern)-1] = 0;
}
free((*list));
*list = NULL;
+ only_included_files = 1;
+ exclude_the_rest = NULL;
return;
}
-static void send_file_name(int f,struct file_list *flist,char *fname,
+void send_file_name(int f,struct file_list *flist,char *fname,
int recursive, unsigned base_flags)
{
struct file_struct *file;
{
int i,l;
STRUCT_STAT st;
- char *p,*dir;
+ char *p,*dir,*olddir;
char lastpath[MAXPATHLEN]="";
struct file_list *flist;
int64 start_write;
}
dir = NULL;
+ olddir = NULL;
if (!relative_paths) {
p = strrchr(fname,'/');
fname = ".";
if (dir && *dir) {
- char *olddir = push_dir(dir, 1);
+ olddir = push_dir(dir, 1);
if (!olddir) {
io_error=1;
}
flist_dir = dir;
- if (one_file_system)
- set_filesystem(fname);
+ }
+
+ if (one_file_system)
+ set_filesystem(fname);
+
+ if (!recurse || !send_included_file_names(f,flist))
send_file_name(f,flist,fname,recurse,FLAG_DELETE);
+
+ if (olddir != NULL) {
flist_dir = NULL;
if (pop_dir(olddir) != 0) {
rprintf(FERROR,"pop_dir %s : %s\n",
dir,strerror(errno));
exit_cleanup(1);
}
- continue;
}
-
- if (one_file_system)
- set_filesystem(fname);
- send_file_name(f,flist,fname,recurse,FLAG_DELETE);
}
if (f != -1) {