diff options
| author | Dylan Simon <dylan@dylex.net> | 2010-07-18 15:43:00 -0400 |
|---|---|---|
| committer | Dylan Simon <dylan@dylex.net> | 2010-07-18 15:43:00 -0400 |
| commit | 2f4cc732146ecf781b875d8f46f61802506d9be3 (patch) | |
| tree | 241d1d14ee80adf8baf59cbe0ff52bdc00d20f8c | |
| parent | 2ee87bd118ff706c5a6db93b6ff6d0dcc0f7cb54 (diff) | |
| parent | f8cd1c4730f8a7ea4934c6986223d6a50a3ab00c (diff) | |
| download | android_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.in | 2 | ||||
| -rw-r--r-- | NEWS | 75 | ||||
| -rw-r--r-- | OLDNEWS | 67 | ||||
| -rw-r--r-- | backup.c | 4 | ||||
| -rw-r--r-- | checksum.c | 2 | ||||
| -rw-r--r-- | clientserver.c | 5 | ||||
| -rw-r--r-- | configure.ac (renamed from configure.in) | 2 | ||||
| -rw-r--r-- | exclude.c | 2 | ||||
| -rw-r--r-- | generator.c | 11 | ||||
| -rw-r--r-- | hlink.c | 2 | ||||
| -rw-r--r-- | io.c | 5 | ||||
| -rw-r--r-- | log.c | 4 | ||||
| -rw-r--r-- | main.c | 6 | ||||
| -rw-r--r-- | options.c | 5 | ||||
| -rwxr-xr-x | packaging/cull_options | 4 | ||||
| -rwxr-xr-x | packaging/extern-squish | 18 | ||||
| -rw-r--r-- | packaging/git-status.pl | 48 | ||||
| -rwxr-xr-x | packaging/nightly-rsync | 56 | ||||
| -rwxr-xr-x | packaging/patch-update | 69 | ||||
| -rwxr-xr-x | packaging/release-rsync | 120 | ||||
| -rwxr-xr-x | packaging/var-checker | 83 | ||||
| -rw-r--r-- | popt/popt.c | 19 | ||||
| -rw-r--r-- | popt/popt.h | 1 | ||||
| -rw-r--r-- | prepare-source.mak | 4 | ||||
| -rw-r--r-- | receiver.c | 2 | ||||
| -rw-r--r-- | rsync.yo | 80 | ||||
| -rw-r--r-- | rsync3.txt | 30 | ||||
| -rw-r--r-- | rsyncd.conf.yo | 2 | ||||
| -rw-r--r-- | socket.c | 110 | ||||
| -rw-r--r-- | support/rrsync | 16 | ||||
| -rw-r--r-- | syscall.c | 12 | ||||
| -rw-r--r-- | testsuite/itemize.test | 6 | ||||
| -rw-r--r-- | token.c | 2 | ||||
| -rw-r--r-- | xattrs.c | 4 |
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 @@ -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. @@ -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 @@ -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 { @@ -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]) @@ -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; } @@ -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 @@ -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; @@ -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; @@ -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'))) @@ -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 @@ -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; @@ -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 @@ -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§ion=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. @@ -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; } @@ -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/" \ @@ -192,6 +192,8 @@ void set_compression(const char *fname) return; while (1) { + if (isUpper(<r)) + ltr = toLower(<r); while (node->letter != ltr) { if (node->letter > ltr) return; @@ -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; |
