rsync-exclude.patch.
John Bowman
bowman at math.ualberta.ca
Sun Feb 16 11:16:46 EST 2003
> I like the idea of your rsync-exclude.patch and have thought
> about hacking it in myself. However as you already have done the work
> may I make a small suggestion...... can the name of the exclude file
> (your .rsync) be specified in the flags.... e.g.
>
> rsync --rsync-exclude=.snapshot -axvH /here /there
>
> In this way different invocations (e.g. system and personal) can exclude
> different files.
>
> Anthony R Iano-Fletcher Anthony.Iano-Fletcher at nih.gov
> http://cbel.cit.nih.gov/~arif
> CBEL, CIT, NIH, Bethesda, MD, USA.
A good idea. I have implemented this as
http://www.math.ualberta.ca/imaging/rlbackup/rsync-exclude-file.patch
Unfortunately, backwards compatibility with the previous syntax
rsync --rsync-exclude -axvH /here /there
does not appear to be possible, because of deficiencies in the popt
option routines relative to getopt_long: popt doesn't really handle
optional arguments correctly, even with POPT_ARGFLAG_OPTIONAL.
Anyway, below is the new version of the --rsync-exclude patch.
This is a useful and general enough feature that I hope it will be added
to the next release of rsync.
-- John Bowman
University of Alberta
This is a patch to add an --rsync-exclude=FILE option to rsync-2.5.6.
Patterns in FILE are used to recursively exclude/include files in a
directory and all of its subdirectories. For example,
rsync --rsync-exclude=.rsync -vaxH /here /there
will copy all files from /here to /there, excluding any files listed in
a file .rsync from the directory containing this file and all of its
subdirectories. As usual, prefixing a pattern with "+ " forces inclusion
rather than exclusion.
This has advantages over --cvs-exclude for backing up large file systems
since the .cvsignore files only apply to the current directory:
unless the .cvsignore restrictions apply to the entire tree they must be
duplicated in each subdirectory. In any case, the --cvs-exclude option
isn't intended for general system backups (for example, unless the default
list is cleared with "!", it automatically excludes *.a and *.so libraries).
diff -ru rsync-2.5.6/exclude.c rsync-2.5.6J/exclude.c
--- rsync-2.5.6/exclude.c Sun Jan 26 13:10:23 2003
+++ rsync-2.5.6J/exclude.c Wed Jan 29 17:16:39 2003
@@ -127,6 +127,7 @@
static void report_exclude_result(char const *name,
struct exclude_struct const *ent,
+ char const *type,
STRUCT_STAT const *st)
{
/* If a trailing slash is present to match only directories,
@@ -134,10 +135,10 @@
* case we add it back in here. */
if (verbose >= 2)
- rprintf(FINFO, "%s %s %s because of pattern %s%s\n",
+ rprintf(FINFO, "%s %s %s because of %s pattern %s%s\n",
ent->include ? "including" : "excluding",
S_ISDIR(st->st_mode) ? "directory" : "file",
- name, ent->pattern,
+ name, type, ent->pattern,
ent->directory ? "/" : "");
}
@@ -147,6 +148,7 @@
* LOCAL_EXCLUDE_LIST or the globals EXCLUDE_LIST.
*/
int check_exclude(char *name, struct exclude_struct **local_exclude_list,
+ struct exclude_struct **recur_local_exclude_list,
STRUCT_STAT *st)
{
int n;
@@ -156,21 +158,37 @@
/* never exclude '.', even if somebody does --exclude '*' */
return 0;
- if (exclude_list) {
- for (n=0; exclude_list[n]; n++) {
- ent = exclude_list[n];
+ /* Precedence: use the most local and most recent matching pattern,
+ in this order: FILE, .cvsignore, --exclude */
+
+ if (recur_local_exclude_list) {
+ for (n=0; recur_local_exclude_list[n]; n++) ;
+ for (n--; n >= 0; n--) {
+ ent = recur_local_exclude_list[n];
if (check_one_exclude(name, ent, st)) {
- report_exclude_result(name, ent, st);
+ report_exclude_result(name, ent, "rsync", st);
return !ent->include;
}
}
}
if (local_exclude_list) {
- for (n=0; local_exclude_list[n]; n++) {
+ for (n=0; local_exclude_list[n]; n++) ;
+ for (n--; n >= 0; n--) {
ent = local_exclude_list[n];
if (check_one_exclude(name, ent, st)) {
- report_exclude_result(name, ent, st);
+ report_exclude_result(name, ent, "cvsignore", st);
+ return !ent->include;
+ }
+ }
+ }
+
+ if (exclude_list) {
+ for (n=0; exclude_list[n]; n++) ;
+ for (n--; n >= 0; n--) {
+ ent = exclude_list[n];
+ if (check_one_exclude(name, ent, st)) {
+ report_exclude_result(name, ent, "global", st);
return !ent->include;
}
}
diff -ru rsync-2.5.6/flist.c rsync-2.5.6J/flist.c
--- rsync-2.5.6/flist.c Sat Jan 18 11:00:23 2003
+++ rsync-2.5.6J/flist.c Thu Feb 13 09:59:40 2003
@@ -39,6 +39,7 @@
extern int always_checksum;
extern int cvs_exclude;
+extern const char *rsync_exclude;
extern int recurse;
@@ -62,6 +63,7 @@
extern int write_batch;
static struct exclude_struct **local_exclude_list;
+static struct exclude_struct **recur_local_exclude_list;
static struct file_struct null_file;
@@ -258,7 +260,8 @@
if ((f == -1) && delete_excluded) {
return 0;
}
- if (check_exclude(fname, local_exclude_list, st)) {
+ if (check_exclude(fname, local_exclude_list,
+ recur_local_exclude_list, st)) {
return 1;
}
return 0;
@@ -773,7 +776,32 @@
return file;
}
+static struct exclude_struct **copy_exclude_list(struct exclude_struct **from) {
+ struct exclude_struct **to;
+ int i;
+ int len=0;
+ int size;
+
+ if (!from) return NULL;
+
+ for (; from[len]; len++) ;
+ size=sizeof(struct exclude_struct *)*(len+1);
+ to = (struct exclude_struct **) malloc(size);
+ if (!to) out_of_memory("copy_exclude_list");
+
+ size=sizeof(struct exclude_struct);
+ for (i=0; i < len; i++) {
+ struct exclude_struct *p;
+ p=to[i]=(struct exclude_struct *) malloc(size);
+ if (!p) out_of_memory("copy_exclude_list");
+ *p=*from[i];
+ p->pattern=strdup(from[i]->pattern);
+ if (!p->pattern) out_of_memory("copy_exclude_list");
+ }
+ to[len]=NULL;
+ return to;
+}
void send_file_name(int f, struct file_list *flist, char *fname,
int recursive, unsigned base_flags)
@@ -800,8 +828,11 @@
if (S_ISDIR(file->mode) && recursive) {
struct exclude_struct **last_exclude_list =
local_exclude_list;
+ struct exclude_struct **recur_last_exclude_list =
+ recur_local_exclude_list;
send_directory(f, flist, f_name(file));
local_exclude_list = last_exclude_list;
+ recur_local_exclude_list = recur_last_exclude_list;
return;
}
}
@@ -840,6 +871,7 @@
p = fname + strlen(fname);
local_exclude_list = NULL;
+ recur_local_exclude_list = copy_exclude_list(recur_local_exclude_list);
if (cvs_exclude) {
if (strlen(fname) + strlen(".cvsignore") <= MAXPATHLEN - 1) {
@@ -854,6 +886,19 @@
}
}
+ if (rsync_exclude) {
+ if (strlen(fname) + strlen(rsync_exclude) <= MAXPATHLEN - 1) {
+ strcpy(p, rsync_exclude);
+ recur_local_exclude_list =
+ make_exclude_list(fname, recur_local_exclude_list, 0, 0);
+ } else {
+ io_error = 1;
+ rprintf(FINFO,
+ "cannot cvs-exclude in long-named directory %s\n",
+ fname);
+ }
+ }
+
for (di = readdir(d); di; di = readdir(d)) {
char *dname = d_name(di);
if (strcmp(dname, ".") == 0 || strcmp(dname, "..") == 0)
@@ -866,6 +911,10 @@
add_exclude_list("!", &local_exclude_list, 0);
}
+ if (recur_local_exclude_list) {
+ add_exclude_list("!", &recur_local_exclude_list, 0);
+ }
+
closedir(d);
}
@@ -887,6 +936,8 @@
if (show_filelist_p() && f != -1)
start_filelist_progress("building file list");
+ recur_local_exclude_list = NULL;
+
start_write = stats.total_written;
flist = flist_new();
diff -ru rsync-2.5.6/options.c rsync-2.5.6J/options.c
--- rsync-2.5.6/options.c Mon Jan 27 20:11:57 2003
+++ rsync-2.5.6J/options.c Thu Feb 13 11:13:01 2003
@@ -45,6 +45,7 @@
int preserve_times = 0;
int update_only = 0;
int cvs_exclude = 0;
+const char *rsync_exclude = NULL;
int dry_run=0;
int local_server=0;
int ignore_times=0;
@@ -84,7 +85,6 @@
int modify_window=0;
int blocking_io=-1;
-
/** Network address family. **/
#ifdef INET6
int default_af_hint = 0; /* Any protocol */
@@ -233,6 +233,7 @@
rprintf(F," -e, --rsh=COMMAND specify the remote shell\n");
rprintf(F," --rsync-path=PATH specify path to rsync on the remote machine\n");
rprintf(F," -C, --cvs-exclude auto ignore files in the same way CVS does\n");
+ rprintf(F," --rsync-exclude=FILE recursively exclude files listed in FILE\n");
rprintf(F," --existing only update files that already exist\n");
rprintf(F," --ignore-existing ignore files that already exist on the receiving side\n");
rprintf(F," --delete delete files that don't exist on the sending side\n");
@@ -320,6 +321,7 @@
{"dry-run", 'n', POPT_ARG_NONE, &dry_run , 0, 0, 0 },
{"sparse", 'S', POPT_ARG_NONE, &sparse_files , 0, 0, 0 },
{"cvs-exclude", 'C', POPT_ARG_NONE, &cvs_exclude , 0, 0, 0 },
+ {"rsync-exclude", 0, POPT_ARG_STRING, &rsync_exclude , 0, 0, 0 },
{"update", 'u', POPT_ARG_NONE, &update_only , 0, 0, 0 },
{"links", 'l', POPT_ARG_NONE, &preserve_links , 0, 0, 0 },
{"copy-links", 'L', POPT_ARG_NONE, ©_links , 0, 0, 0 },
diff -ru rsync-2.5.6/proto.h rsync-2.5.6J/proto.h
--- rsync-2.5.6/proto.h Sun Jan 26 20:35:09 2003
+++ rsync-2.5.6J/proto.h Wed Jan 29 17:16:39 2003
@@ -58,6 +58,7 @@
void setup_protocol(int f_out,int f_in);
int claim_connection(char *fname,int max_connections);
int check_exclude(char *name, struct exclude_struct **local_exclude_list,
+ struct exclude_struct **recur_local_exclude_list,
STRUCT_STAT *st);
void add_exclude_list(const char *pattern, struct exclude_struct ***list, int include);
void add_exclude(const char *pattern, int include);
diff -ru rsync-2.5.6/rsync.yo rsync-2.5.6J/rsync.yo
--- rsync-2.5.6/rsync.yo Mon Jan 27 20:11:57 2003
+++ rsync-2.5.6J/rsync.yo Thu Feb 13 11:57:07 2003
@@ -311,6 +311,7 @@
-e, --rsh=COMMAND specify the remote shell to use
--rsync-path=PATH specify path to rsync on the remote machine
-C, --cvs-exclude auto ignore files in the same way CVS does
+ --rsync-exclude=FILE recursively exclude files listed in FILE
--existing only update files that already exist
--ignore-existing ignore files that already exist on the receiving side
--delete delete files that don't exist on the sending side
@@ -654,6 +655,12 @@
.cvsignore file and matches one of the patterns listed therein. See
the bf(cvs(1)) manual for more information.
+dit(bf(--rsync-exclude=FILE)) Patterns in FILE are excluded from the file
+lists associated with the current directory and all of its subdirectories.
+Prefixing the file name with "+ " will force inclusion of the file.
+If there are multiplying matching patterns, the most local and most recent
+matching pattern will be used, in this order: FILE, .cvsignore, --exclude.
+
dit(bf(--csum-length=LENGTH)) By default the primary checksum used in
rsync is a very strong 16 byte MD4 checksum. In most cases you will
find that a truncated version of this checksum is quite efficient, and
More information about the rsync
mailing list