aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDylan Simon <dylan@dylex.net>2010-07-18 15:43:00 -0400
committerDylan Simon <dylan@dylex.net>2010-07-18 15:43:00 -0400
commit2f4cc732146ecf781b875d8f46f61802506d9be3 (patch)
tree241d1d14ee80adf8baf59cbe0ff52bdc00d20f8c
parent2ee87bd118ff706c5a6db93b6ff6d0dcc0f7cb54 (diff)
parentf8cd1c4730f8a7ea4934c6986223d6a50a3ab00c (diff)
downloadandroid_external_rsync-2f4cc732146ecf781b875d8f46f61802506d9be3.tar.gz
android_external_rsync-2f4cc732146ecf781b875d8f46f61802506d9be3.tar.bz2
android_external_rsync-2f4cc732146ecf781b875d8f46f61802506d9be3.zip
Merge remote branch 'rsync/b3.0.x'
-rw-r--r--Makefile.in2
-rw-r--r--NEWS75
-rw-r--r--OLDNEWS67
-rw-r--r--backup.c4
-rw-r--r--checksum.c2
-rw-r--r--clientserver.c5
-rw-r--r--configure.ac (renamed from configure.in)2
-rw-r--r--exclude.c2
-rw-r--r--generator.c11
-rw-r--r--hlink.c2
-rw-r--r--io.c5
-rw-r--r--log.c4
-rw-r--r--main.c6
-rw-r--r--options.c5
-rwxr-xr-xpackaging/cull_options4
-rwxr-xr-xpackaging/extern-squish18
-rw-r--r--packaging/git-status.pl48
-rwxr-xr-xpackaging/nightly-rsync56
-rwxr-xr-xpackaging/patch-update69
-rwxr-xr-xpackaging/release-rsync120
-rwxr-xr-xpackaging/var-checker83
-rw-r--r--popt/popt.c19
-rw-r--r--popt/popt.h1
-rw-r--r--prepare-source.mak4
-rw-r--r--receiver.c2
-rw-r--r--rsync.yo80
-rw-r--r--rsync3.txt30
-rw-r--r--rsyncd.conf.yo2
-rw-r--r--socket.c110
-rw-r--r--support/rrsync16
-rw-r--r--syscall.c12
-rw-r--r--testsuite/itemize.test6
-rw-r--r--token.c2
-rw-r--r--xattrs.c4
34 files changed, 591 insertions, 287 deletions
diff --git a/Makefile.in b/Makefile.in
index 7d18a4ac..38986da7 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -123,7 +123,7 @@ gensend: gen
conf:
cd $(srcdir) && $(MAKE) -f prepare-source.mak conf
-configure.sh config.h.in: configure.in aclocal.m4
+configure.sh config.h.in: configure.ac aclocal.m4
@if test -f configure.sh; then cp -p configure.sh configure.sh.old; else touch configure.sh.old; fi
@if test -f config.h.in; then cp -p config.h.in config.h.in.old; else touch config.h.in.old; fi
autoconf -o configure.sh
diff --git a/NEWS b/NEWS
index 4e97c085..f53d70d5 100644
--- a/NEWS
+++ b/NEWS
@@ -1,64 +1,49 @@
-NEWS for rsync 3.0.7 (31 Dec 2009)
+NEWS for rsync 3.0.8 (UNRELEASED)
Protocol: 30 (unchanged)
-Changes since 3.0.6:
+Changes since 3.0.7:
BUG FIXES:
- - Fixed a bogus free when using --xattrs with --backup.
+ - Fixed a buffer-overflow issue where a directory path that is exactly
+ MAXPATHLEN was not handled correctly.
- - Avoid an error when --dry-run was trying to stat a prior hard-link file
- that hasn't really been created.
+ - Fixed a potential crash when an rsync daemon has a filter/exclude list
+ and the transfer is using ACLs or extended attributes.
- - Fixed a problem with --compress (-z) where the receiving side could
- return the error "inflate (token) returned -5".
+ - Fixed a bug in the comparing of upper-case letters in file suffixes for
+ --skip-compress.
- - Fixed a bug where --delete-during could delete in a directory before it
- noticed that the sending side sent an I/O error for that directory (both
- sides of the transfer must be at least 3.0.7).
+ - If an rsync daemon has a module configured without a path setting, rsync
+ will now disallow access to that module.
- - Improved --skip-compress's error handling of bad character-sets and got
- rid of a lingering debug fprintf().
+ - If the destination arg is an empty string, it will be treated as a
+ reference to the current directory (as 2.x used to do).
- - Fixed the daemon's conveyance of io_error value from the sender.
+ - Fixed a batch-file writing bug that would not write out the full set of
+ compatibility flags that the transfer was using. This fixes a potential
+ protocol problem for a batch file that contains a sender-side I/O error:
+ it would have been sent in a way that the batch-reader wasn't expecting.
- - An rsync daemon use seteuid() (when available) if it used setuid().
+ - Some improvements to the hard-linking code to ensure that device-number
+ hashing is working right, and to supply more information if the hard-link
+ code fails.
- - Get the permissions right on a --fake-super transferred directory that
- needs more owner permissions to emulate root behavior.
+ - Improved the unsafe-symlink errors messages.
- - An absolute-path filter rule (i.e. with a '/' modifier) no longer loses
- its modifier when sending the filter rules to the remote rsync.
+ - Fix the popt arg parsing so that an option that doesn't take an arg will
+ reject an attempt to supply and arg.
- - Improved the "--delete does not work without -r or -d" message.
+ - A couple minor option tweaks to support/rrsync script, and also some
+ regex changes that make vim highlighting happier.
- - Improved rsync's handling of --timeout to avoid a weird timeout case
- where the sender could timeout even though it has recently written data
- to the socket (but hasn't read data recently, due to the writing).
-
- - Some misc manpage improvements.
-
- - Fixed the chmod-temp-dir testsuite on a system without /var/tmp.
-
- - Make sure that a timeout specified in the daemon's config is used as a
- maximum timeout value when the user also specifies a timeout.
-
- - Improved the error-exit reporting when rsync gets an error trying to
- cleanup after an error: the initial error is reported.
-
- - Improved configure's detection of IPv6 for solaris and cygwin.
-
- - The AIX sysacls routines will now return ENOSYS if ENOTSUP is missing.
-
- - Made our (only used if missing) getaddrinfo() routine use inet_pton()
- (which we also provide) instead of inet_aton().
-
- - The exit-related debug messages now mention the program's role so it is
- clear who output what message.
+ - A few manpage improvements.
DEVELOPER RELATED:
- - Got rid of type-punned compiler warnings output by newer gcc versions.
+ - Use lchmod() whenever it is available (not just on symlinks).
+
+ - A couple fixes to the socketpair_tcp() routine.
- - The Makefile now ensures that proto.h will be rebuilt if config.h changes.
+ - Updated the helper scripts in the packaging subdirectory.
- - The testsuite no longer uses "id -u", so it works better on solaris.
+ - Renamed configure.in to configure.ac.
diff --git a/OLDNEWS b/OLDNEWS
index 06a53c7a..2f17ac1c 100644
--- a/OLDNEWS
+++ b/OLDNEWS
@@ -1,3 +1,69 @@
+NEWS for rsync 3.0.7 (31 Dec 2009)
+Protocol: 30 (unchanged)
+Changes since 3.0.6:
+
+ BUG FIXES:
+
+ - Fixed a bogus free when using --xattrs with --backup.
+
+ - Avoid an error when --dry-run was trying to stat a prior hard-link file
+ that hasn't really been created.
+
+ - Fixed a problem with --compress (-z) where the receiving side could
+ return the error "inflate (token) returned -5".
+
+ - Fixed a bug where --delete-during could delete in a directory before it
+ noticed that the sending side sent an I/O error for that directory (both
+ sides of the transfer must be at least 3.0.7).
+
+ - Improved --skip-compress's error handling of bad character-sets and got
+ rid of a lingering debug fprintf().
+
+ - Fixed the daemon's conveyance of io_error value from the sender.
+
+ - An rsync daemon use seteuid() (when available) if it used setuid().
+
+ - Get the permissions right on a --fake-super transferred directory that
+ needs more owner permissions to emulate root behavior.
+
+ - An absolute-path filter rule (i.e. with a '/' modifier) no longer loses
+ its modifier when sending the filter rules to the remote rsync.
+
+ - Improved the "--delete does not work without -r or -d" message.
+
+ - Improved rsync's handling of --timeout to avoid a weird timeout case
+ where the sender could timeout even though it has recently written data
+ to the socket (but hasn't read data recently, due to the writing).
+
+ - Some misc manpage improvements.
+
+ - Fixed the chmod-temp-dir testsuite on a system without /var/tmp.
+
+ - Make sure that a timeout specified in the daemon's config is used as a
+ maximum timeout value when the user also specifies a timeout.
+
+ - Improved the error-exit reporting when rsync gets an error trying to
+ cleanup after an error: the initial error is reported.
+
+ - Improved configure's detection of IPv6 for solaris and cygwin.
+
+ - The AIX sysacls routines will now return ENOSYS if ENOTSUP is missing.
+
+ - Made our (only used if missing) getaddrinfo() routine use inet_pton()
+ (which we also provide) instead of inet_aton().
+
+ - The exit-related debug messages now mention the program's role so it is
+ clear who output what message.
+
+ DEVELOPER RELATED:
+
+ - Got rid of type-punned compiler warnings output by newer gcc versions.
+
+ - The Makefile now ensures that proto.h will be rebuilt if config.h changes.
+
+ - The testsuite no longer uses "id -u", so it works better on solaris.
+
+
NEWS for rsync 3.0.6 (8 May 2009)
Protocol: 30 (unchanged)
Changes since 3.0.5:
@@ -3028,6 +3094,7 @@ Changes since 2.4.6:
Partial Protocol History
RELEASE DATE VER. DATE OF COMMIT* PROTOCOL
+ ?? ??? 2010 3.0.8 30
31 Dec 2009 3.0.7 30
08 May 2009 3.0.6 30
28 Dec 2008 3.0.5 30
diff --git a/backup.c b/backup.c
index 7512d921..d9181465 100644
--- a/backup.c
+++ b/backup.c
@@ -309,8 +309,8 @@ static int keep_backup(const char *fname)
const char *sl = F_SYMLINK(file);
if (safe_symlinks && unsafe_symlink(sl, fname)) {
if (verbose) {
- rprintf(FINFO, "ignoring unsafe symlink %s -> %s\n",
- full_fname(buf), sl);
+ rprintf(FINFO, "not backing up unsafe symlink \"%s\" -> \"%s\"\n",
+ fname, sl);
}
kept = 1;
} else {
diff --git a/checksum.c b/checksum.c
index 4aaeb954..90d6ee3a 100644
--- a/checksum.c
+++ b/checksum.c
@@ -24,8 +24,6 @@
extern int checksum_seed;
extern int protocol_version;
-int csum_length = SHORT_SUM_LENGTH; /* initial value */
-
/*
a simple 32 bit checksum that can be upadted from either end
(inspired by Mark Adler's Adler-32 checksum)
diff --git a/clientserver.c b/clientserver.c
index 806a6e3c..0d476887 100644
--- a/clientserver.c
+++ b/clientserver.c
@@ -509,6 +509,11 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
* supplementary groups. */
module_dir = lp_path(i);
+ if (*module_dir == '\0') {
+ rprintf(FLOG, "No path specified for module %s\n", name);
+ io_printf(f_out, "@ERROR: no path setting.\n");
+ return -1;
+ }
if (use_chroot) {
if ((p = strstr(module_dir, "/./")) != NULL) {
*p = '\0'; /* Temporary... */
diff --git a/configure.in b/configure.ac
index 685970bf..22cf7106 100644
--- a/configure.in
+++ b/configure.ac
@@ -5,7 +5,7 @@ AC_CONFIG_SRCDIR([byteorder.h])
AC_CONFIG_HEADER(config.h)
AC_PREREQ(2.59)
-RSYNC_VERSION=3.0.7
+RSYNC_VERSION=3.0.8dev
AC_SUBST(RSYNC_VERSION)
AC_MSG_NOTICE([Configuring rsync $RSYNC_VERSION])
diff --git a/exclude.c b/exclude.c
index 70fa8c8a..e6490b09 100644
--- a/exclude.c
+++ b/exclude.c
@@ -37,7 +37,7 @@ extern int sanitize_paths;
extern int protocol_version;
extern int module_id;
-extern char curr_dir[];
+extern char curr_dir[MAXPATHLEN];
extern unsigned int curr_dir_len;
extern unsigned int module_dirlen;
diff --git a/generator.c b/generator.c
index 82b695e2..5846d85f 100644
--- a/generator.c
+++ b/generator.c
@@ -76,7 +76,7 @@ extern int fuzzy_basis;
extern int always_checksum;
extern int checksum_len;
extern char *partial_dir;
-extern char *basis_dir[];
+extern char *basis_dir[MAX_BASIS_DIRS+1];
extern int compare_dest;
extern int copy_dest;
extern int link_dest;
@@ -1532,11 +1532,14 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
const char *sl = F_SYMLINK(file);
if (safe_symlinks && unsafe_symlink(sl, fname)) {
if (verbose) {
- if (solo_file)
+ if (solo_file) {
+ /* fname contains the destination path, but we
+ * want to report the source path. */
fname = f_name(file, NULL);
+ }
rprintf(FINFO,
- "ignoring unsafe symlink %s -> \"%s\"\n",
- full_fname(fname), sl);
+ "ignoring unsafe symlink \"%s\" -> \"%s\"\n",
+ fname, sl);
}
return;
}
diff --git a/hlink.c b/hlink.c
index cfa1065e..fb090a9f 100644
--- a/hlink.c
+++ b/hlink.c
@@ -37,7 +37,7 @@ extern int remove_source_files;
extern int stdout_format_has_i;
extern int maybe_ATTRS_REPORT;
extern int unsort_ndx;
-extern char *basis_dir[];
+extern char *basis_dir[MAX_BASIS_DIRS+1];
extern struct file_list *cur_flist;
#ifdef SUPPORT_HARD_LINKS
diff --git a/io.c b/io.c
index 6599e5a9..00410003 100644
--- a/io.c
+++ b/io.c
@@ -36,7 +36,6 @@
extern int bwlimit;
extern size_t bwlimit_writemax;
extern int io_timeout;
-extern int allowed_lull;
extern int am_server;
extern int am_daemon;
extern int am_sender;
@@ -47,7 +46,6 @@ extern int eol_nulls;
extern int flist_eof;
extern int list_only;
extern int read_batch;
-extern int csum_length;
extern int compat_flags;
extern int protect_args;
extern int checksum_seed;
@@ -61,7 +59,8 @@ extern int filesfrom_convert;
extern iconv_t ic_send, ic_recv;
#endif
-const char phase_unknown[] = "unknown";
+int csum_length = SHORT_SUM_LENGTH; /* initial value */
+int allowed_lull = 0;
int ignore_timeout = 0;
int batch_fd = -1;
int msgdone_cnt = 0;
diff --git a/log.c b/log.c
index 05de68a2..02ac4ea1 100644
--- a/log.c
+++ b/log.c
@@ -52,9 +52,9 @@ extern char *logfile_name;
extern iconv_t ic_chck;
#endif
#ifdef ICONV_OPTION
-extern iconv_t ic_send, ic_recv;
+extern iconv_t ic_recv;
#endif
-extern char curr_dir[];
+extern char curr_dir[MAXPATHLEN];
extern char *full_module_path;
extern unsigned int module_dirlen;
diff --git a/main.c b/main.c
index f0ad96a0..55915398 100644
--- a/main.c
+++ b/main.c
@@ -70,7 +70,7 @@ extern struct stats stats;
extern char *filesfrom_host;
extern char *partial_dir;
extern char *dest_option;
-extern char *basis_dir[];
+extern char *basis_dir[MAX_BASIS_DIRS+1];
extern char *rsync_path;
extern char *shell_cmd;
extern char *batch_name;
@@ -508,6 +508,10 @@ static char *get_local_name(struct file_list *flist, char *dest_path)
if (!dest_path || list_only)
return NULL;
+ /* Treat an empty string as a copy into the current directory. */
+ if (!*dest_path)
+ dest_path = ".";
+
if (daemon_filter_list.head) {
char *slash = strrchr(dest_path, '/');
if (slash && (slash[1] == '\0' || (slash[1] == '.' && slash[2] == '\0')))
diff --git a/options.c b/options.c
index 6db09cf1..1f392844 100644
--- a/options.c
+++ b/options.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 1998-2001 Andrew Tridgell <tridge@samba.org>
* Copyright (C) 2000, 2001, 2002 Martin Pool <mbp@samba.org>
- * Copyright (C) 2002-2009 Wayne Davison
+ * Copyright (C) 2002-2010 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -85,7 +85,6 @@ int numeric_ids = 0;
int allow_8bit_chars = 0;
int force_delete = 0;
int io_timeout = 0;
-int allowed_lull = 0;
int prune_empty_dirs = 0;
int use_qsort = 0;
char *files_from = NULL;
@@ -260,7 +259,7 @@ static void print_rsync_version(enum logcode f)
rprintf(f, "%s version %s protocol version %d%s\n",
RSYNC_NAME, RSYNC_VERSION, PROTOCOL_VERSION, subprotocol);
- rprintf(f, "Copyright (C) 1996-2009 by Andrew Tridgell, Wayne Davison, and others.\n");
+ rprintf(f, "Copyright (C) 1996-2010 by Andrew Tridgell, Wayne Davison, and others.\n");
rprintf(f, "Web site: http://rsync.samba.org/\n");
rprintf(f, "Android port by Dylan Simon: http://github.com/dylex/android_external_rsync\n");
rprintf(f, "Capabilities:\n");
diff --git a/packaging/cull_options b/packaging/cull_options
index 3ef470df..add2b988 100755
--- a/packaging/cull_options
+++ b/packaging/cull_options
@@ -7,7 +7,7 @@ use strict;
our %short_no_arg;
our %short_with_num;
our %long_opt = (
- 'no-i-r' => 0,
+ 'daemon' => -1,
'fake-super' => 0,
'log-file' => 3,
);
@@ -24,7 +24,7 @@ while (<IN>) {
undef $last_long_opt;
} elsif (/\Qargs[ac++]\E = "--([^"=]+)"/) {
$last_long_opt = $1;
- $long_opt{$1} = 0;
+ $long_opt{$1} = 0 unless exists $long_opt{$1};
} elsif (defined($last_long_opt)
&& /\Qargs[ac++]\E = ([^["\s]+);/ && $1 ne 'dest_option') {
$long_opt{$last_long_opt} = 2;
diff --git a/packaging/extern-squish b/packaging/extern-squish
deleted file mode 100755
index eb8b32e1..00000000
--- a/packaging/extern-squish
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/usr/bin/perl
-# This script finds extraneous "extern" variables in the *.c files.
-# Run it from inside the main rsync directory.
-
-use strict;
-
-my @files = glob('*.c');
-
-foreach my $fn (@files) {
- open(IN, '<', $fn) or die;
- undef $/; $_ = <IN>; $/ = "\n";
- close IN;
- my @externs = /^extern .*?([^[\s(*;&.]+)(?:\[.*?\])?;/mg;
- foreach my $find (@externs) {
- my @matches = /(?<!\sstruct )\b(\Q$find\E)\b/g;
- print $fn, ': ', $find, "\n" if @matches == 1;
- }
-}
diff --git a/packaging/git-status.pl b/packaging/git-status.pl
new file mode 100644
index 00000000..295018c9
--- /dev/null
+++ b/packaging/git-status.pl
@@ -0,0 +1,48 @@
+# Do some git-status checking for the current dir and (optionally)
+# the patches dir.
+
+sub check_git_state
+{
+ my($master_branch, $fatal_unless_clean, $check_patches_dir) = @_;
+
+ my($cur_branch) = check_git_status($fatal_unless_clean);
+ if ($cur_branch ne $master_branch) {
+ print "The checkout is not on the $master_branch branch.\n";
+ exit 1 if $master_branch ne 'master';
+ print "Do you want me to continue with --branch=$cur_branch? [n] ";
+ $_ = <STDIN>;
+ exit 1 unless /^y/i;
+ $_[0] = $master_branch = $cur_branch; # Updates caller's $master_branch too.
+ }
+
+ if ($check_patches_dir && -d 'patches/.git') {
+ ($cur_branch) = check_git_status($fatal_unless_clean, 'patches');
+ if ($cur_branch ne $master_branch) {
+ print "The *patches* checkout is on branch $cur_branch, not branch $master_branch.\n";
+ print "Do you want to change it to branch $master_branch? [n] ";
+ $_ = <STDIN>;
+ exit 1 unless /^y/i;
+ system "cd patches && git checkout '$master_branch'";
+ }
+ }
+}
+
+sub check_git_status
+{
+ my($fatal_unless_clean, $subdir) = @_;
+ $subdir = '.' unless defined $subdir;
+ my $status = `cd '$subdir' && git status`;
+ my $is_clean = $status =~ /\nnothing to commit \(working directory clean\)/;
+ my($cur_branch) = $status =~ /^# On branch (.+)\n/;
+ if ($fatal_unless_clean && !$is_clean) {
+ if ($subdir eq '.') {
+ $subdir = '';
+ } else {
+ $subdir = " *$subdir*";
+ }
+ die "The$subdir checkout is not clean:\n", $status;
+ }
+ ($cur_branch, $is_clean, $status);
+}
+
+1;
diff --git a/packaging/nightly-rsync b/packaging/nightly-rsync
index af9f53a3..3aaabcb2 100755
--- a/packaging/nightly-rsync
+++ b/packaging/nightly-rsync
@@ -3,8 +3,8 @@ use strict;
# This script expects the directory ~/samba-rsync-ftp to exist and to be a
# copy of the /home/ftp/pub/rsync dir on samba.org. It also requires a
-# pristine CVS checkout of rsync (don't use your normal rsync build dir
-# unless you're 100% sure that there are not unchecked-in changes).
+# git checkout of rsync (feel free to use your normal rsync build dir as
+# long as it doesn't have any uncommitted changes).
#
# If this is run with -ctu, it will make an updated "nightly" tar file in
# the nightly dir. It will also remove any old tar files, regenerate the
@@ -56,6 +56,58 @@ if ($make_tar) {
}
close IN;
+ my $confversion;
+ open(IN, '<', 'configure.ac') or die "Unable to open configure.ac: $!\n";
+ while (<IN>) {
+ if (/^RSYNC_VERSION=(.*)/) {
+ $confversion = $1;
+ last;
+ }
+ }
+ close IN;
+ die "Unable to find RSYNC_VERSION in configure.ac\n" unless defined $confversion;
+
+ open(IN, '<', 'OLDNEWS') or die "Unable to open OLDNEWS: $!\n";
+ $_ = <IN>;
+ my($lastversion) = /(\d+\.\d+\.\d+)/;
+ my $last_protocol_version;
+ while (<IN>) {
+ if (my($ver,$pdate,$pver) = /^\s+\S\S\s\S\S\S\s\d\d\d\d\s+(\d+\.\d+\.\d+)\s+(\d\d \w\w\w \d\d\d\d\s+)?(\d+)$/) {
+ $last_protocol_version = $pver if $ver eq $lastversion;
+ }
+ }
+ close IN;
+ die "Unable to determine protocol_version for $lastversion.\n" unless defined $last_protocol_version;
+
+ my($protocol_version,$subprotocol_version);
+ open(IN, '<', 'rsync.h') or die "Unable to open rsync.h: $!\n";
+ while (<IN>) {
+ if (/^#define\s+PROTOCOL_VERSION\s+(\d+)/) {
+ $protocol_version = $1;
+ } elsif (/^#define\s+SUBPROTOCOL_VERSION\s+(\d+)/) {
+ $subprotocol_version = $1;
+ }
+ }
+ close IN;
+ die "Unable to determine the current PROTOCOL_VERSION.\n" unless defined $protocol_version;
+ die "Unable to determine the current SUBPROTOCOL_VERSION.\n" unless defined $subprotocol_version;
+
+ if ($confversion =~ /dev|pre/) {
+ if ($last_protocol_version ne $protocol_version) {
+ if ($subprotocol_version == 0) {
+ die "SUBPROTOCOL_VERSION must not be 0 for a non-final release with a changed PROTOCOL_VERSION.\n";
+ }
+ } else {
+ if ($subprotocol_version != 0) {
+ die "SUBPROTOCOL_VERSION must be 0 when the PROTOCOL_VERSION hasn't changed from the last release.\n";
+ }
+ }
+ } else {
+ if ($subprotocol_version != 0) {
+ die "SUBPROTOCOL_VERSION must be 0 for a final release.\n";
+ }
+ }
+
print "Creating $name.tar.gz\n";
system "rsync -a @extra_files $name/";
system "git archive --format=tar --prefix=$name/ HEAD | tar xf -";
diff --git a/packaging/patch-update b/packaging/patch-update
index 15d1b6c3..dba8e472 100755
--- a/packaging/patch-update
+++ b/packaging/patch-update
@@ -1,11 +1,12 @@
-#!/usr/bin/perl -w
-# This script is used to turn one or more of the "patch/*" branches
+#!/usr/bin/perl
+# This script is used to turn one or more of the "patch/BASE/*" branches
# into one or more diffs in the "patches" directory. Pass the option
# --gen if you want generated files in the diffs. Pass the name of
# one or more diffs if you want to just update a subset of all the
# diffs.
use strict;
+use warnings;
use Getopt::Long;
my $patches_dir = 'patches';
@@ -30,10 +31,19 @@ if (defined $incl_generated_files) {
die "No '$patches_dir' directory was found.\n" unless -d $patches_dir;
die "No '.git' directory present in the current dir.\n" unless -d '.git';
-my($status, $is_clean, $starting_branch) = &check_git_status;
-if (!$skip_branch_check && !$is_clean) {
- die "The checkout is not clean:\n", $status;
+require 'packaging/git-status.pl';
+check_git_state($master_branch, !$skip_branch_check, 1);
+
+my $master_commit;
+open PIPE, '-|', "git log -1 --no-color $master_branch" or die $!;
+while (<PIPE>) {
+ if (/^commit (\S+)/) {
+ $master_commit = $1;
+ last;
+ }
}
+close PIPE;
+die "Unable to determine commit hash for master branch: $master_branch\n" unless defined $master_commit;
my @extra_files;
open(IN, '<', 'Makefile.in') or die "Couldn't open Makefile.in: $!\n";
@@ -60,7 +70,7 @@ my %patches;
# Start by finding all patches so that we can load all possible parents.
open(PIPE, '-|', 'git', 'branch', '-l') or die $!;
while (<PIPE>) {
- if (m# patch/(.*)#) {
+ if (m# patch/\Q$master_branch\E/(.*)#o) {
$patches{$1} = 1;
}
}
@@ -70,7 +80,7 @@ my @patches = sort keys %patches;
my(%parent, %description);
foreach my $patch (@patches) {
- my $branch = "patch/$patch";
+ my $branch = "patch/$master_branch/$patch";
my $desc = '';
open(PIPE, '-|', 'git', 'diff', '-U1000', "$master_branch...$branch", '--', "PATCH.$patch") or die $!;
while (<PIPE>) {
@@ -114,7 +124,7 @@ if ($incl_generated_files) {
}
sleep 1 while $last_touch >= time;
-system "git checkout $starting_branch" and exit 1;
+system "git checkout $master_branch" and exit 1;
exit;
@@ -124,24 +134,27 @@ sub update_patch
my($patch) = @_;
my $parent = $parent{$patch};
+ my $based_on;
if (defined $parent) {
unless ($completed{$parent}++) {
update_patch($parent);
}
- $parent = "patch/$parent";
+ $based_on = $parent = "patch/$master_branch/$parent";
} else {
$parent = $master_branch;
+ $based_on = $master_commit;
}
print "======== $patch ========\n";
sleep 1 while $incl_generated_files && $last_touch >= time;
- system "git checkout patch/$patch" and return 0;
+ system "git checkout patch/$master_branch/$patch" and return 0;
- my $ok = system("git merge $parent") == 0;
+ my $ok = system("git merge $based_on") == 0;
if (!$ok || $launch_shell) {
- print qq|"git merge $parent" incomplete -- please fix.\n| if !$ok;
- $ENV{PS1} = "[$parent] patch/$patch: ";
+ my($parent_dir) = $parent =~ m{([^/]+)$};
+ print qq|"git merge $based_on" incomplete -- please fix.\n| if !$ok;
+ $ENV{PS1} = "[$parent_dir] $patch: ";
while (1) {
if (system($ENV{SHELL}) != 0) {
print "Abort? [n/y] ";
@@ -149,21 +162,21 @@ sub update_patch
next unless /^y/i;
return 0;
}
- ($status, $is_clean) = &check_git_status;
+ my($cur_branch, $is_clean, $status) = check_git_status(0);
last if $is_clean;
print $status;
}
}
open(OUT, '>', "$patches_dir/$patch.diff") or die $!;
- print OUT $description{$patch}, "\n";
+ print OUT $description{$patch}, "\nbased-on: $based_on\n";
if ($incl_generated_files) {
system "$make_gen_cmd && rsync -a @extra_files $tmp_dir/$patch/" and exit 1;
}
$last_touch = time;
- open(PIPE, '-|', 'git', 'diff', $parent) or die $!;
+ open(PIPE, '-|', 'git', 'diff', $based_on) or die $!;
DIFF: while (<PIPE>) {
while (m{^diff --git a/PATCH}) {
while (<PIPE>) {
@@ -200,22 +213,18 @@ sub update_patch
exit;
-sub check_git_status
-{
- open(IN, '-|', 'git status') or die $!;
- my $status = join('', <IN>);
- close IN;
- my $is_clean = $status =~ /\nnothing to commit \(working directory clean\)/;
- my($starting_branch) = $status =~ /^# On branch (.+)\n/;
- ($status, $is_clean, $starting_branch);
-}
-
sub usage
{
die <<EOT;
-Usage: patch-update [OPTIONS]
-
---gen[=DIR] Include generated files. Optional dest DIR overrides "patches".
---skip-check Skip the check that ensures starting with a clean branch.
+Usage: patch-update [OPTIONS] [patches/DIFF...]
+
+Options:
+-b, --branch=BRANCH The master branch to merge into the patch/BASE/* branches.
+ --gen[=DIR] Include generated files. Optional destination DIR
+ arg overrides the default of using the "patches" dir.
+ --skip-check Skip the check that ensures starting with a clean branch.
+-s, --shell Launch a shell for every patch/BASE/* branch updated, not
+ just when a conflict occurs.
+-h, --help Output this help message.
EOT
}
diff --git a/packaging/release-rsync b/packaging/release-rsync
index 6fa42137..0b906c43 100755
--- a/packaging/release-rsync
+++ b/packaging/release-rsync
@@ -1,11 +1,11 @@
#!/usr/bin/perl
-use strict;
-
# This script expects the directory ~/samba-rsync-ftp to exist and to be a
# copy of the /home/ftp/pub/rsync dir on samba.org. When the script is done,
# the git repository in the current directory will be updated, and the local
# ~/samba-rsync-ftp dir will be ready to be rsynced to samba.org.
+use strict;
+use warnings;
use Cwd;
use Getopt::Long;
use Term::ReadKey;
@@ -14,6 +14,7 @@ use Date::Format;
my $dest = $ENV{HOME} . '/samba-rsync-ftp';
my $passfile = $ENV{HOME} . '/.rsyncpass';
my $path = $ENV{PATH};
+my $make_gen_cmd = 'make -f prepare-source.mak conf && ./config.status && make gen';
&Getopt::Long::Configure('bundling');
&usage if !&GetOptions(
@@ -60,14 +61,11 @@ die "There is no .git dir in the current directory.\n" unless -d '.git';
die "'a' must not exist in the current directory.\n" if -e 'a';
die "'b' must not exist in the current directory.\n" if -e 'b';
-open(IN, '-|', 'git status') or die $!;
-my $status = join('', <IN>);
-close IN;
-die "The checkout is not clean:\n", $status unless $status =~ /\nnothing to commit \(working directory clean\)/;
-die "The checkout is not on the $master_branch branch.\n" unless $status =~ /^# On branch $master_branch\n/;
+require 'packaging/git-status.pl';
+check_git_state($master_branch, 1, 1);
my $confversion;
-open(IN, '<', 'configure.in') or die $!;
+open(IN, '<', 'configure.ac') or die $!;
while (<IN>) {
if (/^RSYNC_VERSION=(.*)/) {
$confversion = $1;
@@ -75,12 +73,31 @@ while (<IN>) {
}
}
close IN;
-die "Unable to find RSYNC_VERSION in configure.in\n" unless defined $confversion;
+die "Unable to find RSYNC_VERSION in configure.ac\n" unless defined $confversion;
open(IN, '<', 'OLDNEWS') or die $!;
$_ = <IN>;
-close IN;
my($lastversion) = /(\d+\.\d+\.\d+)/;
+my($last_protocol_version, %pdate);
+while (<IN>) {
+ if (my($ver,$pdate,$pver) = /^\s+\S\S\s\S\S\S\s\d\d\d\d\s+(\d+\.\d+\.\d+)\s+(\d\d \w\w\w \d\d\d\d\s+)?(\d+)$/) {
+ $pdate{$ver} = $pdate if defined $pdate;
+ $last_protocol_version = $pver if $ver eq $lastversion;
+ }
+}
+close IN;
+die "Unable to determine protocol_version for $lastversion.\n" unless defined $last_protocol_version;
+
+my $protocol_version;
+open(IN, '<', 'rsync.h') or die $!;
+while (<IN>) {
+ if (/^#define\s+PROTOCOL_VERSION\s+(\d+)/) {
+ $protocol_version = $1;
+ last;
+ }
+}
+close IN;
+die "Unable to determine the current PROTOCOL_VERSION.\n" unless defined $protocol_version;
my $version = $confversion;
$version =~ s/dev/pre1/ || $version =~ s/pre(\d+)/ 'pre' . ($1 + 1) /e;
@@ -118,6 +135,23 @@ chomp($_ = <STDIN>);
$release = $_ if $_ ne '';
$release .= ".$pre" if $pre;
+(my $finalversion = $version) =~ s/pre\d+//;
+my($proto_changed,$proto_change_date);
+if ($protocol_version eq $last_protocol_version) {
+ $proto_changed = 'unchanged';
+ $proto_change_date = "\t\t";
+} else {
+ $proto_changed = 'changed';
+ if (!defined($proto_change_date = $pdate{$finalversion})) {
+ while (1) {
+ print "On what date did the protocol change to $protocol_version get checked in? (dd Mmm yyyy) ";
+ chomp($_ = <STDIN>);
+ last if /^\d\d \w\w\w \d\d\d\d$/;
+ }
+ $proto_change_date = "$_\t";
+ }
+}
+
my($srcdir,$srcdiffdir,$lastsrcdir,$skipping);
if ($lastversion =~ /pre/) {
if (!$pre) {
@@ -146,9 +180,9 @@ print "\n", $break, <<EOT;
\$release is "$release"
About to:
- - make sure that SUBPROTOCOL_VERSION is 0$skipping
- - tweak the version in configure.in and the spec files
- - tweak NEWS and OLDNEWS to update the release date$skipping
+ - tweak SUBPROTOCOL_VERSION in rsync.h, if needed
+ - tweak the version in configure.ac and the spec files
+ - tweak NEWS and OLDNEWS to ensure header values are correct
- tweak the date in the *.yo files and generate the manpages
- generate configure.sh, config.h.in, and proto.h
- page through the differences
@@ -157,12 +191,11 @@ EOT
print "<Press Enter to continue> ";
$_ = <STDIN>;
-(my $finalversion = $version) =~ s/pre\d+//;
my %specvars = ( 'Version:' => $finalversion, 'Release:' => $release,
'%define fullversion' => "\%{version}$pre", 'Released' => "$version.",
'%define srcdir' => $srcdir );
my @tweak_files = ( glob('packaging/*.spec'), glob('packaging/*/*.spec'), glob('*.yo'),
- qw( configure.in rsync.h NEWS OLDNEWS options.c ) );
+ qw( configure.ac rsync.h NEWS OLDNEWS options.c ) );
foreach my $fn (@tweak_files) {
open(IN, '<', $fn) or die $!;
@@ -184,18 +217,19 @@ foreach my $fn (@tweak_files) {
s/^(This man ?page is current for version) \S+ (of rsync)/$1 $version $2/m
or die "Unable to update current version info in $fn\n";
} elsif ($fn eq 'rsync.h') {
- s/(#define\s+SUBPROTOCOL_VERSION)\s+\d+/$1 0/
+ s{(#define\s+SUBPROTOCOL_VERSION)\s+(\d+)}
+ { $1 . ' ' . get_subprotocol_version($2) }e
or die "Unable to find SUBPROTOCOL_VERSION define in $fn\n";
- next if $pre;
} elsif ($fn eq 'NEWS') {
- s/^(NEWS for rsync \Q$finalversion\E) \(UNRELEASED\)\s*\n/$1 ($today)\n/mi
- or die "The first line of $fn is not in the right format. It must be:\n"
- . "NEWS for rsync $finalversion (UNRELEASED)\n";
- next if $pre;
+ s{^(NEWS for rsync \Q$finalversion\E )(\(UNRELEASED\))\s*(\nProtocol: )(\d+) (\([^)]+\))\n}
+ { $1 . ($pre ? $2 : "($today)") . "$3$protocol_version ($proto_changed)\n" }ei
+ or die "The first 2 lines of $fn are not in the right format. They must be:\n"
+ . "NEWS for rsync $finalversion (UNRELEASED)\n"
+ . "Protocol: $protocol_version ($proto_changed)\n";
} elsif ($fn eq 'OLDNEWS') {
- s/^\t\S\S\s\S\S\S\s\d\d\d\d(\t\Q$finalversion\E)/\t$ztoday$1/m
+ s{^(\t\S\S\s\S\S\S\s\d\d\d\d)(\t\Q$finalversion\E\t).*}
+ { ($pre ? $1 : "\t$ztoday") . $2 . $proto_change_date . $protocol_version }em
or die "Unable to find \"?? ??? $year\t$finalversion\" line in $fn\n";
- next if $pre;
} elsif ($fn eq 'options.c') {
if (s/(Copyright \(C\) 2002-)(\d+)( Wayne Davison)/$1$year$3/
&& $2 ne $year) {
@@ -229,7 +263,7 @@ print $break, <<EOT;
About to:
- commit all version changes
- - merge the $master_branch branch into the patch/* branches
+ - merge the $master_branch branch into the patch/$master_branch/* branches
- update the files in the "patches" dir and OPTIONALLY
(if you type 'y') to launch a shell for each patch
@@ -243,10 +277,14 @@ print "Updating files in \"patches\" dir ...\n";
system "packaging/patch-update --branch=$master_branch";
if ($ans =~ /^y/i) {
- print "\nVisiting all \"patch/*\" branches ...\n";
+ print "\nVisiting all \"patch/$master_branch/*\" branches ...\n";
system "packaging/patch-update --branch=$master_branch --shell";
}
+if (-d 'patches/.git') {
+ system "cd patches && git commit -a -m 'The patches for $version.'" and exit 1;
+}
+
print $break, <<EOT;
About to:
@@ -264,6 +302,9 @@ EOT
print "<Press Enter to continue> ";
$_ = <STDIN>;
+# We want to use our passphrase-providing "gpg" script, so modify the PATH.
+$ENV{PATH} = "$curdir/packaging/bin:$path";
+
my $passphrase;
while (1) {
ReadMode('noecho');
@@ -281,17 +322,23 @@ while (1) {
umask $oldmask;
$ENV{'GPG_PASSFILE'} = $passfile;
- # We want to use our passphrase-providing "gpg" script, so modify the PATH.
- $ENV{PATH} = "packaging/bin:$path";
$_ = `git tag -s -m 'Version $version.' v$version 2>&1`;
- $ENV{PATH} = $path;
- unlink($passfile);
print $_;
next if /bad passphrase/;
- last unless /failed/;
- exit 1;
+ exit 1 if /failed/;
+
+ if (-d 'patches/.git') {
+ $_ = `cd patches && git tag -s -m 'Version $version.' v$version 2>&1`;
+ print $_;
+ exit 1 if /bad passphrase|failed/;
+ }
+
+ unlink($passfile);
+ last;
}
+$ENV{PATH} = $path;
+
# Extract the generated files from the old tar.
@_ = @extra_files;
map { s#^#rsync-$lastversion/# } @_;
@@ -299,7 +346,7 @@ system "tar xzf $lasttar_file @_";
rename("rsync-$lastversion", 'a');
print "Creating $diff_file ...\n";
-system "./config.status Makefile; make gen; rsync -a @extra_files b/";
+system "$make_gen_cmd && rsync -a @extra_files b/" and exit 1;
my $sed_script = 's:^((---|\+\+\+) [ab]/[^\t]+)\t.*:\1:';
system "(git diff v$lastversion v$version; diff -upN a b | sed -r '$sed_script') | gzip -9 >$diff_file";
system "rm -rf a";
@@ -354,6 +401,15 @@ EOT
exit;
+sub get_subprotocol_version
+{
+ my($subver) = @_;
+ if ($pre && $proto_changed eq 'changed') {
+ return $subver == 0 ? 1 : $subver;
+ }
+ 0;
+}
+
sub usage
{
die <<EOT;
diff --git a/packaging/var-checker b/packaging/var-checker
new file mode 100755
index 00000000..7c017252
--- /dev/null
+++ b/packaging/var-checker
@@ -0,0 +1,83 @@
+#!/usr/bin/perl
+# This script checks the *.c files for extraneous "extern" variables,
+# for vars that are defined but not used, and for inconsistent array
+# sizes. Run it from inside the main rsync directory.
+
+use strict;
+use warnings;
+
+my %add_syscall_c = map { $_ => 1 } qw( t_stub.c t_unsafe.c tls.c trimslash.c );
+my %add_compat_c = map { $_ => 1 } qw( t_stub.c tls.c trimslash.c wildtest.c );
+my %add_util_c = map { $_ => 1 } qw( t_stub.c t_unsafe.c );
+my %sizes;
+
+open(IN, '<', 'syscall.c') or die $!;
+undef $/; my $syscall_c = <IN>; $/ = "\n";
+close IN;
+$syscall_c =~ s/^extern\s.*//mg;
+
+open(IN, '<', 'lib/compat.c') or die $!;
+undef $/; my $compat_c = <IN>; $/ = "\n";
+close IN;
+$compat_c =~ s/^extern\s.*//mg;
+
+open(IN, '<', 'util.c') or die $!;
+undef $/; my $util_c = <IN>; $/ = "\n";
+close IN;
+$util_c =~ s/^extern\s.*//mg;
+
+my @files = glob('*.c');
+
+foreach my $fn (@files) {
+ open(IN, '<', $fn) or die $!;
+ undef $/; $_ = <IN>; $/ = "\n";
+ close IN;
+
+ my @vars = /^(?!(?:extern|enum)\s)([a-zA-Z]\S*\s+.*);/mg;
+ my @externs = /^extern\s+(.*);/mg;
+
+ $_ .= $syscall_c if $add_syscall_c{$fn};
+ $_ .= $compat_c if $add_compat_c{$fn};
+ $_ .= $util_c if $add_util_c{$fn};
+ s/INFO_GTE/info_levels/g;
+ s/DEBUG_GTE/debug_levels/g;
+
+ check_vars($fn, 'var', @vars);
+ check_vars($fn, 'extern', @externs);
+}
+
+exit;
+
+# The file's contents are in $_.
+sub check_vars
+{
+ my $fn = shift;
+ my $type = shift;
+
+ foreach my $line (@_) {
+ $line =~ s/\s*\{.*\}//;
+ $line =~ s/\s*\(.*\)//;
+ foreach my $item (split(/\s*,\s*/, $line)) {
+ $item =~ s/\s*=.*//;
+ my $sz = $item =~ s/(\[.*?\])// ? $1 : '';
+ my($var) = $item =~ /([^*\s]+)$/;
+ if (!defined $var) {
+ print "Bogus match? ($item)\n";
+ next;
+ }
+ if ($sz) {
+ if (defined $sizes{$var}) {
+ if ($sizes{$var} ne $sz) {
+ print $fn, ' has inconsistent size for "', $var,
+ "\": $sizes{$var} vs $sz\n";
+ }
+ } else {
+ $sizes{$var} = $sz;
+ }
+ }
+ my @matches = /(?<!\sstruct )\b(\Q$var\E)(?!\w)/g;
+ push(@matches, /(\QSIGACTION(\E)/g) if $var eq 'sigact';
+ print $fn, " has extraneous $type: \"", $var, "\"\n" if @matches == 1;
+ }
+ }
+}
diff --git a/popt/popt.c b/popt/popt.c
index a01b6b96..ec6f3bd8 100644
--- a/popt/popt.c
+++ b/popt/popt.c
@@ -860,20 +860,21 @@ int poptGetNextOpt(poptContext con)
origOptString++;
if (*origOptString != '\0')
- con->os->nextCharArg = origOptString + (*origOptString == '=');
+ con->os->nextCharArg = origOptString;
}
/*@=branchstate@*/
if (opt == NULL) return POPT_ERROR_BADOPT; /* XXX can't happen */
- if (opt->arg && (opt->argInfo & POPT_ARG_MASK) == POPT_ARG_NONE) {
- if (poptSaveInt((int *)opt->arg, opt->argInfo, 1L))
- return POPT_ERROR_BADOPERATION;
- } else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_VAL) {
+ if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_NONE
+ || (opt->argInfo & POPT_ARG_MASK) == POPT_ARG_VAL) {
+ if (longArg || (con->os->nextCharArg && con->os->nextCharArg[0] == '='))
+ return POPT_ERROR_UNWANTEDARG;
if (opt->arg) {
- if (poptSaveInt((int *)opt->arg, opt->argInfo, (long)opt->val))
+ long val = (opt->argInfo & POPT_ARG_MASK) == POPT_ARG_VAL ? opt->val : 1;
+ if (poptSaveInt((int *)opt->arg, opt->argInfo, val))
return POPT_ERROR_BADOPERATION;
}
- } else if ((opt->argInfo & POPT_ARG_MASK) != POPT_ARG_NONE) {
+ } else {
con->os->nextArg = _free(con->os->nextArg);
/*@-usedef@*/ /* FIX: W2DO? */
if (longArg) {
@@ -881,7 +882,7 @@ int poptGetNextOpt(poptContext con)
longArg = expandNextArg(con, longArg);
con->os->nextArg = longArg;
} else if (con->os->nextCharArg) {
- longArg = expandNextArg(con, con->os->nextCharArg);
+ longArg = expandNextArg(con, con->os->nextCharArg + (con->os->nextCharArg[0] == '='));
con->os->nextArg = longArg;
con->os->nextCharArg = NULL;
} else {
@@ -1202,6 +1203,8 @@ const char * poptStrerror(const int error)
switch (error) {
case POPT_ERROR_NOARG:
return POPT_("missing argument");
+ case POPT_ERROR_UNWANTEDARG:
+ return POPT_("option does not take an argument");
case POPT_ERROR_BADOPT:
return POPT_("unknown option");
case POPT_ERROR_BADOPERATION:
diff --git a/popt/popt.h b/popt/popt.h
index 4f85d9e3..8d85f731 100644
--- a/popt/popt.h
+++ b/popt/popt.h
@@ -82,6 +82,7 @@
/*@{*/
#define POPT_ERROR_NOARG -10 /*!< missing argument */
#define POPT_ERROR_BADOPT -11 /*!< unknown option */
+#define POPT_ERROR_UNWANTEDARG -12 /*!< option does not take an argument */
#define POPT_ERROR_OPTSTOODEEP -13 /*!< aliases nested too deeply */
#define POPT_ERROR_BADQUOTE -15 /*!< error in paramter quoting */
#define POPT_ERROR_ERRNO -16 /*!< errno set, use strerror(errno) */
diff --git a/prepare-source.mak b/prepare-source.mak
index 277dd6f2..054bab70 100644
--- a/prepare-source.mak
+++ b/prepare-source.mak
@@ -1,7 +1,7 @@
conf: configure.sh config.h.in
-configure.sh: configure.in aclocal.m4
+configure.sh: configure.ac aclocal.m4
autoconf -o configure.sh
-config.h.in: configure.in aclocal.m4
+config.h.in: configure.ac aclocal.m4
autoheader && touch config.h.in
diff --git a/receiver.c b/receiver.c
index 39c5e490..ea11ed53 100644
--- a/receiver.c
+++ b/receiver.c
@@ -53,7 +53,7 @@ extern mode_t orig_umask;
extern struct stats stats;
extern char *tmpdir;
extern char *partial_dir;
-extern char *basis_dir[];
+extern char *basis_dir[MAX_BASIS_DIRS+1];
extern struct file_list *cur_flist, *first_flist, *dir_flist;
extern struct filter_list_struct daemon_filter_list;
diff --git a/rsync.yo b/rsync.yo
index 41f90436..031e9825 100644
--- a/rsync.yo
+++ b/rsync.yo
@@ -688,6 +688,12 @@ specify a backup suffix using the bf(--suffix) option
(otherwise the files backed up in the specified directory
will keep their original filenames).
+Note that if you specify a relative path, the backup directory will be
+relative to the destination directory, so you probably want to specify
+either an absolute path or a path that starts with "../". If an rsync
+daemon is the receiver, the backup dir cannot go outside the module's path
+hierarchy, so take extra care not to delete it or copy into it.
+
dit(bf(--suffix=SUFFIX)) This option allows you to override the default
backup suffix used with the bf(--backup) (bf(-b)) option. The default suffix is a ~
if no -bf(-backup-dir) was specified, otherwise it is an empty string.
@@ -713,17 +719,26 @@ its data needs to be updated: instead of the default method of creating
a new copy of the file and moving it into place when it is complete, rsync
instead writes the updated data directly to the destination file.
-This has several effects: (1) in-use binaries cannot be updated (either the
-OS will prevent this from happening, or binaries that attempt to swap-in
-their data will misbehave or crash), (2) the file's data will be in an
-inconsistent state during the transfer, (3) a file's data may be left in an
-inconsistent state after the transfer if the transfer is interrupted or if
-an update fails, (4) a file that does not have write permissions can not be
-updated, and (5) the efficiency of rsync's delta-transfer algorithm may be
-reduced if some data in the destination file is overwritten before it can
-be copied to a position later in the file (one exception to this is if you
-combine this option with bf(--backup), since rsync is smart enough to use
-the backup file as the basis file for the transfer).
+This has several effects:
+
+quote(itemization(
+ it() Hard links are not broken. This means the new data will be visible
+ through other hard links to the destination file. Moreover, attempts to
+ copy differing source files onto a multiply-linked destination file will
+ result in a "tug of war" with the destination data changing back and forth.
+ it() In-use binaries cannot be updated (either the OS will prevent this from
+ happening, or binaries that attempt to swap-in their data will misbehave or
+ crash).
+ it() The file's data will be in an inconsistent state during the transfer
+ and will be left that way if the transfer is interrupted or if an update
+ fails.
+ it() A file that does not have write permissions cannot be updated.
+ it() The efficiency of rsync's delta-transfer algorithm may be reduced if
+ some data in the destination file is overwritten before it can be copied to
+ a position later in the file. This does not apply if you use bf(--backup),
+ since rsync is smart enough to use the backup file as the basis file for the
+ transfer.
+))
WARNING: you should not use this option to update files that are being
accessed by others, so be careful when choosing to use this for a copy.
@@ -814,6 +829,17 @@ bf(--force) or bf(--delete) is in effect).
See also bf(--keep-dirlinks) for an analogous option for the receiving
side.
+bf(--copy-dirlinks) applies to all symlinks to directories in the source. If
+you want to follow only a few specified symlinks, a trick you can use is to
+pass them as additional source args with a trailing slash, using bf(--relative)
+to make the paths match up right. For example:
+
+quote(tt(rsync -r --relative src/./ src/./follow-me/ dest/))
+
+This works because rsync calls bf(lstat)(2) on the source arg as given, and the
+trailing slash makes bf(lstat)(2) follow the symlink, giving rise to a directory
+in the file-list which overrides the symlink found during the scan of "src/./".
+
dit(bf(-K, --keep-dirlinks)) This option causes the receiving side to treat
a symlink to a directory as though it were a real directory, but only if it
matches a real directory from the sender. Without this option, the
@@ -837,17 +863,23 @@ to modify your receiving hierarchy.
See also bf(--copy-dirlinks) for an analogous option for the sending side.
dit(bf(-H, --hard-links)) This tells rsync to look for hard-linked files in
-the transfer and link together the corresponding files on the receiving
-side. Without this option, hard-linked files in the transfer are treated
+the source and link together the corresponding files on the destination.
+Without this option, hard-linked files in the source are treated
as though they were separate files.
-When you are updating a non-empty destination, this option only ensures
-that files that are hard-linked together on the source are hard-linked
-together on the destination. It does NOT currently endeavor to break
-already existing hard links on the destination that do not exist between
-the source files. Note, however, that if one or more extra-linked files
-have content changes, they will become unlinked when updated (assuming you
-are not using the bf(--inplace) option).
+This option does NOT necessarily ensure that the pattern of hard links on the
+destination exactly matches that on the source. Cases in which the
+destination may end up with extra hard links include the following:
+
+quote(itemization(
+ it() If the destination already contains hard links, rsync will not break
+ them explicitly. However, if one or more of the paths have content
+ differences, the normal file-update process will break those links, unless
+ you are using the bf(--inplace) option.
+ it() If you specify a bf(--link-dest) directory that contains hard links,
+ rsync may use the same bf(--link-dest) file multiple times via several of
+ its paths.
+))
Note that rsync can only detect hard links between files that are inside
the transfer set. If rsync updates a file that has extra hard-link
@@ -938,14 +970,18 @@ The source and destination systems must have compatible ACL entries for this
option to work properly. See the bf(--fake-super) option for a way to backup
and restore ACLs that are not compatible.
-dit(bf(-X, --xattrs)) This option causes rsync to update the remote
-extended attributes to be the same as the local ones.
+dit(bf(-X, --xattrs)) This option causes rsync to update the destination
+extended attributes to be the same as the source ones.
For systems that support extended-attribute namespaces, a copy being done by a
super-user copies all namespaces except system.*. A normal user only copies
the user.* namespace. To be able to backup and restore non-user namespaces as
a normal user, see the bf(--fake-super) option.
+Note that this option does not copy rsyncs special xattr values (e.g. those
+used by bf(--fake-super)) unless you repeat the option (e.g. -XX). This
+"copy all xattrs" mode cannot be used with bf(--fake-super).
+
dit(bf(--chmod)) This option tells rsync to apply one or more
comma-separated "chmod" strings to the permission of the files in the
transfer. The resulting value is treated as though it were the permissions
diff --git a/rsync3.txt b/rsync3.txt
index 42d77dca..967aa4b5 100644
--- a/rsync3.txt
+++ b/rsync3.txt
@@ -1,6 +1,6 @@
-*- indented-text -*-
-Notes towards a new version of rsync
+Notes towards a new version of rsync
Martin Pool <mbp@samba.org>, September 2001.
@@ -13,7 +13,7 @@ Good things about the current implementation:
- Fairly reliable.
- - The choice of runnning over a plain TCP socket or tunneling over
+ - The choice of running over a plain TCP socket or tunneling over
ssh.
- rsync operations are idempotent: you can always run the same
@@ -51,7 +51,7 @@ Bad things about the current implementation:
hard to modify/extend
- Both the program and the protocol assume a single non-interactive
- one-way transfer
+ one-way transfer
- A list of all files are held in memory for the entire transfer,
which cripples scalability to large file trees
@@ -88,7 +88,7 @@ Protocol philosophy:
Questionable features:
- These are neat, but not necessarily clean or worth preserving.
+ These are neat, but not necessarily clean or worth preserving.
- The remote rsync can be wrapped by some other program, such as in
tridge's rsync-mail scripts. The general feature of sending and
@@ -100,7 +100,7 @@ Desirable features:
These don't really require architectural changes; they're just
something to keep in mind.
-
+
- Synchronize ACLs and extended attributes
- Anonymous servers should be efficient
@@ -122,7 +122,7 @@ Desirable features:
Alternatively, as long as transfers are idempotent, we can just
restart the whole thing. [NFSv4]
- - Scripting support.
+ - Scripting support.
- Propagate atimes and do not modify them. This is very ugly on
Unix. It might be better to try to add O_NOATIME to kernels, and
@@ -224,7 +224,7 @@ Scripting hooks:
- What basis file to use
- Logging
-
+
- Whether to allow transfers (for public servers)
- Authentication
@@ -275,7 +275,7 @@ Pie-in-the-sky features:
These might have a severe impact on the protocol, and are not
clearly in our core requirements. It looks like in many of them
- having scripting hooks will allow us
+ having scripting hooks will allow us
- Transport over UDP multicast. The hard part is handling multiple
destinations which have different basis files. We can look at
@@ -344,7 +344,7 @@ In favour of using a new protocol:
- If we start from scratch, it can be documented as we go, and we
can avoid design decisions that make the protocol complex or
- implementation-bound.
+ implementation-bound.
Error handling:
@@ -365,7 +365,7 @@ Concurrency:
- We can do nonblocking network IO, but not so for disk.
- It makes sense to on the destination be generating signatures and
- applying patches at the same time.
+ applying patches at the same time.
- Can structure this with nonblocking, threads, separate processes,
etc.
@@ -381,7 +381,7 @@ Uses:
http://www.ietf.org/proceedings/00jul/00july-133.htm#P24510_1276764
- Sync with PDA
-
+
- Network backup systems
- CVS filemover
@@ -419,7 +419,7 @@ Filesystem migration:
Atomic updates:
The NFSv4 working group wants atomic migration. Most of the
- responsibility for this lies on the NFS server or OS.
+ responsibility for this lies on the NFS server or OS.
If migrating a whole tree, then we could do a nearly-atomic rename
at the end. This ties in to having separate basis and destination
@@ -427,11 +427,11 @@ Atomic updates:
There's no way in Unix to replace a whole set of files atomically.
However, if we get them all onto the destination machine and then do
- the updates quickly it would greatly reduce the window.
+ the updates quickly it would greatly reduce the window.
Scalability:
-
+
We should aim to work well on machines in use in a year or two.
That probably means transfers of many millions of files in one
batch, and gigabytes or terabytes of data.
@@ -466,4 +466,4 @@ Related work:
- http://freshmeat.net/search/?site=Freshmeat&q=mirror&section=projects
- BitTorrent -- p2p mirroring
- http://bitconjurer.org/BitTorrent/ \ No newline at end of file
+ http://bitconjurer.org/BitTorrent/
diff --git a/rsyncd.conf.yo b/rsyncd.conf.yo
index 8c9bf8ea..19e44b32 100644
--- a/rsyncd.conf.yo
+++ b/rsyncd.conf.yo
@@ -310,7 +310,7 @@ was run as root. This complements the "uid" parameter. The default is gid -2,
which is normally the group "nobody".
dit(bf(fake super)) Setting "fake super = yes" for a module causes the
-daemon side to behave as if the bf(--fake-user) command-line option had
+daemon side to behave as if the bf(--fake-super) command-line option had
been specified. This allows the full attributes of a file to be stored
without having to have the daemon actually running as root.
diff --git a/socket.c b/socket.c
index 3e70af2c..e496755f 100644
--- a/socket.c
+++ b/socket.c
@@ -39,12 +39,11 @@ extern int connect_timeout;
static struct sigaction sigact;
#endif
-/**
- * Establish a proxy connection on an open socket to a web proxy by
- * using the CONNECT method. If proxy_user and proxy_pass are not NULL,
- * they are used to authenticate to the proxy using the "Basic"
- * proxy-authorization protocol
- **/
+static int sock_exec(const char *prog);
+
+/* Establish a proxy connection on an open socket to a web proxy by using the
+ * CONNECT method. If proxy_user and proxy_pass are not NULL, they are used to
+ * authenticate to the proxy using the "Basic" proxy-authorization protocol. */
static int establish_proxy_connection(int fd, char *host, int port,
char *proxy_user, char *proxy_pass)
{
@@ -125,10 +124,8 @@ static int establish_proxy_connection(int fd, char *host, int port,
}
-/**
- * Try to set the local address for a newly-created socket. Return -1
- * if this fails.
- **/
+/* Try to set the local address for a newly-created socket.
+ * Return -1 if this fails. */
int try_bind_local(int s, int ai_family, int ai_socktype,
const char *bind_addr)
{
@@ -165,26 +162,22 @@ static RETSIGTYPE contimeout_handler(UNUSED(int val))
connect_timeout = -1;
}
-/**
- * Open a socket to a tcp remote host with the specified port .
+/* Open a socket to a tcp remote host with the specified port.
*
* Based on code from Warren. Proxy support by Stephen Rothwell.
* getaddrinfo() rewrite contributed by KAME.net.
*
- * Now that we support IPv6 we need to look up the remote machine's
- * address first, using @p af_hint to set a preference for the type
- * of address. Then depending on whether it has v4 or v6 addresses we
- * try to open a connection.
+ * Now that we support IPv6 we need to look up the remote machine's address
+ * first, using af_hint to set a preference for the type of address. Then
+ * depending on whether it has v4 or v6 addresses we try to open a connection.
*
- * The loop allows for machines with some addresses which may not be
- * reachable, perhaps because we can't e.g. route ipv6 to that network
- * but we can get ip4 packets through.
+ * The loop allows for machines with some addresses which may not be reachable,
+ * perhaps because we can't e.g. route ipv6 to that network but we can get ip4
+ * packets through.
*
- * @param bind_addr Local address to use. Normally NULL to bind
- * the wildcard address.
+ * bind_addr: local address to use. Normally NULL to bind the wildcard address.
*
- * @param af_hint Address family, e.g. AF_INET or AF_INET6.
- **/
+ * af_hint: address family, e.g. AF_INET or AF_INET6. */
int open_socket_out(char *host, int port, const char *bind_addr,
int af_hint)
{
@@ -308,8 +301,7 @@ int open_socket_out(char *host, int port, const char *bind_addr,
}
-/**
- * Open an outgoing socket, but allow for it to be intercepted by
+/* Open an outgoing socket, but allow for it to be intercepted by
* $RSYNC_CONNECT_PROG, which will execute a program across a TCP
* socketpair rather than really opening a socket.
*
@@ -318,8 +310,7 @@ int open_socket_out(char *host, int port, const char *bind_addr,
*
* This is based on the Samba LIBSMB_PROG feature.
*
- * @param bind_addr Local address to use. Normally NULL to get the stack default.
- **/
+ * bind_addr: local address to use. Normally NULL to get the stack default. */
int open_socket_out_wrapped(char *host, int port, const char *bind_addr,
int af_hint)
{
@@ -372,9 +363,7 @@ int open_socket_out_wrapped(char *host, int port, const char *bind_addr,
}
-
-/**
- * Open one or more sockets for incoming data using the specified type,
+/* Open one or more sockets for incoming data using the specified type,
* port, and address.
*
* The getaddrinfo() call may return several address results, e.g. for
@@ -383,9 +372,7 @@ int open_socket_out_wrapped(char *host, int port, const char *bind_addr,
* We return an array of file-descriptors to the sockets, with a trailing
* -1 value to indicate the end of the list.
*
- * @param bind_addr Local address to bind, or NULL to allow it to
- * default.
- **/
+ * bind_addr: local address to bind, or NULL to allow it to default. */
static int *open_socket_in(int type, int port, const char *bind_addr,
int af_hint)
{
@@ -490,9 +477,7 @@ static int *open_socket_in(int type, int port, const char *bind_addr,
}
-/*
- * Determine if a file descriptor is in fact a socket
- */
+/* Determine if a file descriptor is in fact a socket. */
int is_a_socket(int fd)
{
int v;
@@ -660,13 +645,11 @@ struct
#ifdef SO_RCVTIMEO
{"SO_RCVTIMEO", SOL_SOCKET, SO_RCVTIMEO, 0, OPT_INT},
#endif
- {NULL,0,0,0,0}};
-
+ {NULL,0,0,0,0}
+};
-/**
- * Set user socket options
- **/
+/* Set user socket options. */
void set_socket_options(int fd, char *options)
{
char *tok;
@@ -732,15 +715,10 @@ void set_socket_options(int fd, char *options)
}
-/**
- * This is like socketpair but uses tcp. It is used by the Samba
- * regression test code.
- *
- * The function guarantees that nobody else can attach to the socket,
- * or if they do that this function fails and the socket gets closed
- * returns 0 on success, -1 on failure the resulting file descriptors
- * are symmetrical.
- **/
+/* This is like socketpair but uses tcp. The function guarantees that nobody
+ * else can attach to the socket, or if they do that this function fails and
+ * the socket gets closed. Returns 0 on success, -1 on failure. The resulting
+ * file descriptors are symmetrical. Currently only for RSYNC_CONNECT_PROG. */
static int socketpair_tcp(int fd[2])
{
int listener;
@@ -761,16 +739,12 @@ static int socketpair_tcp(int fd[2])
sock2.sin_len = sizeof sock2;
#endif
sock2.sin_family = PF_INET;
+ sock2.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
- bind(listener, (struct sockaddr *)&sock2, sizeof sock2);
-
- if (listen(listener, 1) != 0)
- goto failed;
-
- if (getsockname(listener, (struct sockaddr *)&sock, &socklen) != 0)
- goto failed;
-
- if ((fd[1] = socket(PF_INET, SOCK_STREAM, 0)) == -1)
+ if (bind(listener, (struct sockaddr *)&sock2, sizeof sock2) != 0
+ || listen(listener, 1) != 0
+ || getsockname(listener, (struct sockaddr *)&sock, &socklen) != 0
+ || (fd[1] = socket(PF_INET, SOCK_STREAM, 0)) == -1)
goto failed;
set_nonblocking(fd[1]);
@@ -783,7 +757,7 @@ static int socketpair_tcp(int fd[2])
} else
connect_done = 1;
- if ((fd[0] = accept(listener, (struct sockaddr *)&sock, &socklen)) == -1)
+ if ((fd[0] = accept(listener, (struct sockaddr *)&sock2, &socklen)) == -1)
goto failed;
close(listener);
@@ -811,17 +785,13 @@ static int socketpair_tcp(int fd[2])
}
-
-/**
- * Run a program on a local tcp socket, so that we can talk to it's
- * stdin and stdout. This is used to fake a connection to a daemon
- * for testing -- not for the normal case of running SSH.
+/* Run a program on a local tcp socket, so that we can talk to it's stdin and
+ * stdout. This is used to fake a connection to a daemon for testing -- not
+ * for the normal case of running SSH.
*
- * @return a socket which is attached to a subprocess running
- * "prog". stdin and stdout are attached. stderr is left attached to
- * the original stderr
- **/
-int sock_exec(const char *prog)
+ * Retruns a socket which is attached to a subprocess running "prog". stdin and
+ * stdout are attached. stderr is left attached to the original stderr. */
+static int sock_exec(const char *prog)
{
pid_t pid;
int fd[2];
diff --git a/support/rrsync b/support/rrsync
index 0d138f17..216521db 100644
--- a/support/rrsync
+++ b/support/rrsync
@@ -92,7 +92,6 @@ our %long_opt = (
'max-size' => 1,
'min-size' => 1,
'modify-window' => 1,
- 'no-i-r' => 0,
'no-implied-dirs' => 0,
'no-r' => 0,
'no-relative' => 0,
@@ -109,6 +108,7 @@ our %long_opt = (
'size-only' => 0,
'skip-compress' => 1,
'specials' => 0,
+ 'stats' => 0,
'suffix' => 1,
'super' => 0,
'temp-dir' => 2,
@@ -175,10 +175,10 @@ while ($command =~ /((?:[^\s\\]+|\\.[^\s\\]*)+)/g) {
} else {
if ($subdir ne '/') {
# Validate args to ensure they don't try to leave our restricted dir.
- s#//+#/#g;
- s#^/##;
- s#^$#.#;
- die "Do not use .. in any path!\n" if m#(^|/)\\?\.\\?\.(\\?/|$)#;
+ s{//+}{/}g;
+ s{^/}{};
+ s{^$}{.};
+ die "$0: do not use .. in any path!\n" if m{(^|/)\\?\.\\?\.(\\?/|$)};
}
push(@args, bsd_glob($_, GLOB_LIMIT|GLOB_NOCHECK|GLOB_BRACE|GLOB_QUOTE));
}
@@ -205,10 +205,10 @@ sub check_arg
my($opt, $arg, $type) = @_;
$arg =~ s/\\(.)/$1/g;
if ($subdir ne '/' && ($type == 3 || ($type == 2 && !$am_sender))) {
- $arg =~ s#//#/#g;
+ $arg =~ s{//}{/}g;
die "Do not use .. in --$opt; anchor the path at the root of your restricted dir.\n"
- if $arg =~ m#(^|/)\.\.(/|$)#;
- $arg =~ s#^/#$subdir/#;
+ if $arg =~ m{(^|/)\.\.(/|$)};
+ $arg =~ s{^/}{$subdir/};
}
$arg;
}
diff --git a/syscall.c b/syscall.c
index 0d272591..4493d33d 100644
--- a/syscall.c
+++ b/syscall.c
@@ -152,10 +152,11 @@ int do_chmod(const char *path, mode_t mode)
int code;
if (dry_run) return 0;
RETURN_ERROR_IF_RO_OR_LO;
- if (S_ISLNK(mode)) {
#ifdef HAVE_LCHMOD
- code = lchmod(path, mode & CHMOD_BITS);
-#elif defined HAVE_SETATTRLIST
+ code = lchmod(path, mode & CHMOD_BITS);
+#else
+ if (S_ISLNK(mode)) {
+# if defined HAVE_SETATTRLIST
struct attrlist attrList;
uint32_t m = mode & CHMOD_BITS; /* manpage is wrong: not mode_t! */
@@ -163,11 +164,12 @@ int do_chmod(const char *path, mode_t mode)
attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
attrList.commonattr = ATTR_CMN_ACCESSMASK;
code = setattrlist(path, &attrList, &m, sizeof m, FSOPT_NOFOLLOW);
-#else
+# else
code = 1;
-#endif
+# endif
} else
code = chmod(path, mode & CHMOD_BITS); /* DISCOURAGED FUNCTION */
+#endif /* !HAVE_LCHMOD */
if (code != 0 && (preserve_perms || preserve_executability))
return code;
return 0;
diff --git a/testsuite/itemize.test b/testsuite/itemize.test
index bdb08c2f..0dbb5a4b 100644
--- a/testsuite/itemize.test
+++ b/testsuite/itemize.test
@@ -17,7 +17,7 @@ outfile="$scratchdir/rsync.out"
makepath "$fromdir/foo"
makepath "$fromdir/bar/baz"
-cp -p "$srcdir/configure.in" "$fromdir/foo/config1"
+cp -p "$srcdir/configure.ac" "$fromdir/foo/config1"
cp -p "$srcdir/config.h.in" "$fromdir/foo/config2"
cp -p "$srcdir/rsync.h" "$fromdir/bar/baz/rsync"
chmod 600 "$fromdir"/foo/config? "$fromdir/bar/baz/rsync"
@@ -66,7 +66,7 @@ diff $diffopt "$chkfile" "$outfile" || test_fail "test 1 failed"
# Ensure there are no accidental directory-time problems.
$RSYNC -a -f '-! */' "$fromdir/" "$todir"
-cp -p "$srcdir/configure.in" "$fromdir/foo/config2"
+cp -p "$srcdir/configure.ac" "$fromdir/foo/config2"
chmod 601 "$fromdir/foo/config2"
$RSYNC -iplrH "$fromdir/" "$todir/" \
| tee "$outfile"
@@ -99,7 +99,7 @@ cLc$T.$dots foo/sym -> ../bar/baz/rsync
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 3 failed"
-cp -p "$srcdir/configure.in" "$fromdir/foo/config2"
+cp -p "$srcdir/configure.ac" "$fromdir/foo/config2"
chmod 600 "$fromdir/foo/config2"
# Lack of -t is for unchanged hard-link stress-test!
$RSYNC -vvplrH "$fromdir/" "$todir/" \
diff --git a/token.c b/token.c
index 3e068a97..843055f7 100644
--- a/token.c
+++ b/token.c
@@ -192,6 +192,8 @@ void set_compression(const char *fname)
return;
while (1) {
+ if (isUpper(&ltr))
+ ltr = toLower(&ltr);
while (node->letter != ltr) {
if (node->letter > ltr)
return;
diff --git a/xattrs.c b/xattrs.c
index 23337bc7..b818f7e9 100644
--- a/xattrs.c
+++ b/xattrs.c
@@ -321,7 +321,7 @@ int copy_xattrs(const char *source, const char *dest)
if (sys_lsetxattr(dest, name, ptr, datum_len) < 0) {
int save_errno = errno ? errno : EINVAL;
rsyserr(FERROR_XFER, errno,
- "rsync_xal_set: lsetxattr(\"%s\",\"%s\") failed",
+ "copy_xattrs: lsetxattr(\"%s\",\"%s\") failed",
dest, name);
errno = save_errno;
return -1;
@@ -646,7 +646,7 @@ void receive_xattr(struct file_struct *file, int f)
F_XATTR(file) = ndx - 1;
return;
}
-
+
if ((count = read_varint(f)) != 0) {
(void)EXPAND_ITEM_LIST(&temp_xattr, rsync_xa, count);
temp_xattr.count = 0;