Compare commits

..

4 Commits

Author SHA1 Message Date
Wayne Davison
c02f4b232a Preparing for release of 2.6.6 2005-07-28 19:31:55 +00:00
Wayne Davison
d8edb8c614 Mentioned the final changes. 2005-07-28 19:24:22 +00:00
Wayne Davison
29050a2565 Incorporate the improvements made to the daemon/remote-shell sections. 2005-07-28 19:19:47 +00:00
Wayne Davison
04a13dd408 A fix for the itemized output to prevent superfluous 'p' flags. 2005-07-28 19:06:03 +00:00
106 changed files with 4506 additions and 8699 deletions

19
.ignore Normal file
View File

@@ -0,0 +1,19 @@
.#*
*.log
Makefile
config.h
*.o
CVS
.ignore
.cvsignore
*~
rsync
config.status
config.cache
TAGS
config.log
test
*.gz
rsync-*
*.dvi
*.aux

View File

@@ -2,7 +2,7 @@
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
@@ -313,7 +313,7 @@ Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.

23
INSTALL
View File

@@ -1,4 +1,4 @@
To build and install rsync:
To build and install rsync
$ ./configure
$ make
@@ -9,15 +9,8 @@ to ./configure. To see them, use:
$ ./configure --help
Configure tries to figure out if the local system uses group "nobody" or
"nogroup" by looking in the /etc/group file. (This is only used for the
default group of an rsync daemon, which attempts to run with "nobody"
user and group permissions.) You can change the default user and group
for the daemon by editing the NOBODY_USER and NOBODY_GROUP defines in
config.h, or just override them in your /etc/rsyncd.conf file.
As of 2.4.7, rsync uses Eric Troan's popt option-parsing library. A
cut-down copy of release 1.6.4 is included in the rsync distribution,
cut-down copy of release 1.5 is included in the rsync distribution,
and will be used if there is no popt library on your build host, or if
the --with-included-popt option is passed to ./configure.
@@ -25,6 +18,7 @@ If you configure using --enable-maintainer-mode, then rsync will try
to pop up an xterm on DISPLAY=:0 if it crashes. You might find this
useful, but it should be turned off for production builds.
RPM NOTES
---------
@@ -43,15 +37,16 @@ fails:
Install gcc or HP's "ANSI/C Compiler".
MAC OSX NOTES
-------------
Some versions of Mac OS X (Darwin) seem to have an IPv6 stack, but do
not completely implement the "New Sockets" API.
Mac OS X (Darwin) seems to have an IPv6 stack, but it does not
completely implement the "New Sockets" API.
<http://www.ipv6.org/impl/mac.html> says that Apple started to support
IPv6 in 10.2 (Jaguar). If your build fails, try again after running
configure with --disable-ipv6.
<http://www.ipv6.org/impl/mac.html> says that Apple do not support
IPv6 yet. If your build fails, try again with --disable-ipv6.
IBM AIX NOTES
-------------

View File

@@ -2,7 +2,6 @@
# Makefile
prefix=@prefix@
datarootdir=@datarootdir@
exec_prefix=@exec_prefix@
bindir=@bindir@
mandir=@mandir@
@@ -34,7 +33,7 @@ ZLIBOBJ=zlib/deflate.o zlib/inffast.o zlib/inflate.o zlib/inftrees.o \
OBJS1=rsync.o generator.o receiver.o cleanup.o sender.o exclude.o util.o \
main.o checksum.o match.o syscall.o log.o backup.o
OBJS2=options.o flist.o io.o compat.o hlink.o token.o uidlist.o socket.o \
fileio.o batch.o clientname.o chmod.o
fileio.o batch.o clientname.o
OBJS3=progress.o pipe.o
DAEMON_OBJ = params.o loadparm.o clientserver.o access.o connection.o authenticate.o
popt_OBJS=popt/findme.o popt/popt.o popt/poptconfig.o \
@@ -91,14 +90,29 @@ T_UNSAFE_OBJ = t_unsafe.o syscall.o util.o t_stub.o lib/compat.o lib/snprintf.o
t_unsafe$(EXEEXT): $(T_UNSAFE_OBJ)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(T_UNSAFE_OBJ) $(LIBS)
gen:
cd $(srcdir) && $(MAKE) -f prepare-source.mak gen
gen: $(srcdir)/configure $(srcdir)/config.h.in proto man
man:
cd $(srcdir) && $(MAKE) -f prepare-source.mak man
man: $(srcdir)/rsync.1 $(srcdir)/rsyncd.conf.5
$(srcdir)/configure: $(srcdir)/configure.in $(srcdir)/aclocal.m4
cd $(srcdir); autoconf
$(srcdir)/config.h.in: $(srcdir)/configure.in $(srcdir)/aclocal.m4
cd $(srcdir); autoheader
$(srcdir)/rsync.1: $(srcdir)/rsync.yo
yodl2man -o $(srcdir)/rsync.1 $(srcdir)/rsync.yo
$(srcdir)/rsyncd.conf.5: $(srcdir)/rsyncd.conf.yo
yodl2man -o $(srcdir)/rsyncd.conf.5 $(srcdir)/rsyncd.conf.yo
proto:
cd $(srcdir) && $(MAKE) -f prepare-source.mak proto.h
cat $(srcdir)/*.c $(srcdir)/lib/compat.c | awk -f $(srcdir)/mkproto.awk >$(srcdir)/proto.h.new
if diff $(srcdir)/proto.h $(srcdir)/proto.h.new >/dev/null; then \
rm $(srcdir)/proto.h.new; \
else \
mv $(srcdir)/proto.h.new $(srcdir)/proto.h; \
fi
clean: cleantests
rm -f *~ $(OBJS) $(TLS_OBJ) $(CHECK_PROGS) $(CHECK_OBJS)
@@ -143,11 +157,11 @@ test: check
# might lose in the future where POSIX diverges from old sh.
check: all $(CHECK_PROGS)
rsync_bin=`pwd`/rsync$(EXEEXT) $(srcdir)/runtests.sh
POSIXLY_CORRECT=1 TOOLDIR=`pwd` rsync_bin=`pwd`/rsync$(EXEEXT) srcdir="$(srcdir)" $(srcdir)/runtests.sh
wildtest.o: wildtest.c lib/wildmatch.c rsync.h
wildtest$(EXEEXT): wildtest.o lib/compat.o
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ wildtest.o lib/compat.o @BUILD_POPT@ $(LIBS)
wildtest$(EXEEXT): wildtest.o
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ wildtest.o @BUILD_POPT@ $(LIBS)
# This does *not* depend on building or installing: you can use it to
# check a version installed from a binary or some other source tree,

185
NEWS
View File

@@ -1,158 +1,65 @@
NEWS for rsync 2.6.9 (6 Nov 2006)
NEWS for rsync 2.6.6 (28 Jul 2005)
Protocol: 29 (unchanged)
Changes since 2.6.8:
Changes since 2.6.5:
SECURITY FIXES:
- The zlib code was upgraded to version 1.2.3 in order to make it more
secure. While the widely-publicized security problem in zlib 1.2.2 did
not affect rsync, another security problem surfaced that affects rsync's
zlib 1.1.4.
BUG FIXES:
- If rsync is interrupted via a handled signal (such as SIGINT), it will
once again clean-up its temp file from the destination dir.
- The setting of flist->high in clean_flist() was wrong for an empty list.
This could cause flist_find() to crash in certain rare circumstances
(e.g. if just the right directory setup was around when --fuzzy was
combined with --link-dest).
- Fixed an overzealous sanitizing bug in the handling of the --link-dest,
--copy-dest, and --compare-dest options to a daemon without chroot: if
the copy's destination dir is deeper than the top of the module's path,
these options now accept a safe number of parent-dir (../) references
(since these options are relative to the destination dir). The old code
incorrectly chopped off all "../" prefixes for these options, no matter
how deep the destination directory was in the module's hierarchy.
- The outputting of hard-linked files when verbosity was > 1 was not right:
without -i it would output the name of each hard-linked file as though
it had been changed (it now outputs a "is hard linked" message for the
file); with -i it would output all dots for the unchanged attributes of
a hard-link (it now changes those dots to spaces, as is done for other
totally unchanged items).
- Fixed a bug where a deferred info/error/log message could get sent
directly to the sender instead of being handled by rwrite() in the
generator. This fixes an "unexpected tag 3" fatal error, and should
also fix a potential problem where a deferred info/error message from
the receiver might bypass the log file and get sent only to the client
process. (These problems could only affect an rsync daemon that was
receiving files.)
- When backing up a changed symlink or device, get rid of any old backup
item so that we don't get an "already exists" error.
- Fixed a bug when --inplace was combined with a --*-dest option and we
update a file's data using an alternate basis file. The code now
notices that it needs to copy the matching data from the basis file
instead of (wrongly) assuming that it was already present in the file.
- A couple places that were comparing a local and a remote modification-
time were not honoring the --modify-window option.
- Fixed a bug where using --dry-run with a --*-dest option with a path
relative to a directory that does not yet exist: the affected option
gets its proper path value so that the output of the dry-run is right.
- Fixed a bug where the 'p' (permissions) itemized-changes flag might get
set too often (if some non-significant mode bits differed).
- Fixed a bug in the %f logfile escape when receiving files: the
destination path is now included in the output (e.g. you can now tell
when a user specifies a subdir inside a module).
- If the receiving side fails to create a directory, it will now skip
trying to update everything that is inside that directory.
- If --link-dest is specified with --checksum but without --times, rsync
will now allow a hard-link to be created to a matching link-dest file
even when the file's modify-time doesn't match the server's file.
- The daemon now calls more timezone-using functions prior to doing a
chroot. This should help some C libraries to generate proper timestamps
from inside a chrooted daemon (and to not try to access /etc/timezone
over and over again).
- Fixed a bug in the handling of an absolute --partial-dir=ABS_PATH option:
it now deletes an alternate basis file from the partial-dir that was used
to successfully update a destination file.
- Fixed a bug in the handling of --delete-excluded when using a per-dir
merge file: the merge file is now honored on the receiving side, and
only its unqualified include/exclude commands are ignored (just as is
done for global include/excludes).
- Fixed a recent bug where --delete was not working when transferring from
the root (/) of the filesystem with --relative enabled.
- Fixed a recent bug where an --exclude='*' could affect the root (/) of
the filesystem with --relative enabled.
- When --inplace creates a file, it is now created with owner read/write
permissions (0600) instead of no permissions at all. This avoids a
problem continuing a transfer that was interrupted (since --inplace
will not update a file that has no write permissions).
- If either --remove-source-files or --remove-sent-files is enabled and we
are unable to remove the source file, rsync now outputs an error.
- Fixed a bug in the daemon's "incoming chmod" rule: newly-created
directories no longer get the 'F' (file) rules applied to them.
- Fixed an infinite loop bug when a filter rule was rejected due to being
overly long.
- When the server receives a --partial-dir option from the client, it no
longer runs the client-side code that adds an assumed filter rule (since
the client will be sending us the rules in the usual manner, and they
may have chosen to override the auto-added rule).
- Fixed a really old, minor bug that could cause rsync to warn about being
unable to mkdir() a path that ends in "/." because it just created the
directory (required --relative, --no-implied-dirs, a source path that
ended in either a trailing slash or a trailing "/.", and a non-existing
destination dir to tickle the bug in a recent version).
ENHANCEMENTS:
- Added the --log-file=FILE and --log-file-format=FORMAT options. These
can be used to tell any rsync to output what it is doing to a log file.
They work with a client rsync, a non-daemon server rsync (see the man
page for instructions), and also allows the overriding of rsyncd.conf
settings when starting a daemon.
- Made the "max verbosity" setting in the rsyncd.conf file settable on a
per-module basis (which now matches the documentation).
- The --log-format option was renamed to be --out-format to avoid confusing
it with affecting the log-file output. (The old option remains as an
alias for the new to preserve backward compatibility.)
- The support/rrsync script has been upgraded to verify the args of options
that take args (instead of rejecting any such options). The script was
also changed to try to be more secure and to fix a problem in the parsing
of a pull operation that has multiple sources.
- Made "log file" and "syslog facility" settable on a per-module basis in
the daemon's config file.
- Improved the documentation that explains the difference between a
normal daemon transfer and a daemon-over remote-shell transfer.
- Added the --remove-source-files option as a replacement for the (now
deprecated) --remove-sent-files option. This new option removes all
non-dirs from the source directories, even if the file was already
up-to-date. This fixes a problem where interrupting an rsync that
was using --remove-sent-files and restarting it could leave behind
a file that the earlier rsync synchronized, but didn't get to remove.
(The deprecated --remove-sent-files is still understood for now, and
still behaves in the same way as before.)
- Some of the diffs supplied in the patches dir were fixed and/or
improved.
- Added the option --no-motd to suppress the message-of-the-day output
from a daemon when doing a copy. (See the manpage for a caveat.)
BUILD CHANGES:
- Added a new environment variable to the pre-/post-xfer exec commands (in
the daemon's config file): RSYNC_PID. This value will be the same in
both the pre- and post-xfer commands, so it can be used if the pre-xfer
command wants to cache some arg/request info for the post-xfer command.
- Made configure define NOBODY_USER (currently hard-wired to "nobody") and
NOBODY_GROUP (set to either "nobody" or "nogroup" depending on what we
find in the /etc/group file).
INTERNAL:
- Added a test to the test suite, itemized.test, that tests the output of
-i (log-format w/%i) and some double-verbose messages.
- Did a code audit using IBM's code-checker program and made several
changes, including: replacing most of the strcpy() and sprintf()
calls with strlcpy(), snprintf(), and memcpy(), adding a 0-value to
an enum that had been intermingling a literal 0 with the defined enum
values, silencing some uninitialized memory checks, marking some
functions with a "noreturn" attribute, and changing an "if" that
could never succeed on some platforms into a pre-processor directive
that conditionally compiles the code.
- Fixed a potential bug in f_name_cmp() when both the args are a
top-level "." dir (which doesn't happen in normal operations).
- Changed exit_cleanup() so that it can never return instead of exit.
The old code might return if it found the exit_cleanup() function
was being called recursively. The new code is segmented so that
any recursive calls move on to the next step of the exit-processing.
- The macro WIFEXITED(stat) will now be defined if the OS didn't already
define it.
DEVELOPER RELATED:
- The acls.diff and xattrs.diff patches have received a bunch of work to
make them much closer to being acceptable in the main distribution.
The xattrs patch also has some preliminary Mac OS X compatibility code
that allows Macs and non-macs to exchange extended attributes.
- A new diff in the patches dir, fake-root.diff, allows rsync to
maintain a backup hierarchy with full owner, group, and device info
without actually running as root. It does this using a special
extended attribute, so it depends on xattrs.diff (which depends on
acls.diff).
- The rsync.yo and rsyncd.conf.yo files have been updated to work
better with the latest yodl 2.x releases.
- Updated config.guess and config.sub to their 2006-02-23 version.
- Updated various files to include the latest FSF address and to have
consistent opening comments.

479
OLDNEWS
View File

@@ -1,459 +1,3 @@
NEWS for rsync 2.6.8 (22 Apr 2006)
Protocol: 29 (unchanged)
Changes since 2.6.7:
BUG FIXES:
- Fixed a bug in the exclude code where an anchored exclude without any
wildcards fails to match an absolute source arg, but only when --relative
is in effect.
- Improved the I/O code for the generator to fix a potential hang when the
receiver gets an EOF on the socket but the generator's select() call
never indicates that the socket is writable for it to be notified about
the EOF. (This can happen when using stunnel).
- Fixed a problem with the file-reading code where a failed read (such as
that caused by a bad sector) would not advance the file's read-position
beyond the failed read's data.
- Fixed a logging bug where the "log file" directive was not being honored
in a single-use daemon (one spawned by a remote-shell connection or by
init).
- If rsync cannot honor the --delete option, we output an error and exit
instead of silently ignoring the option.
- Fixed a bug in the --link-dest code that prevented special files (such as
fifos) from being linked.
- The ability to hard-link symlinks and special files is now determined at
configure time instead of at runtime. This fixes a bug with --link-dest
creating a hard-link to a symlink's referent on a BSD system.
ENHANCEMENTS:
- In daemon mode, if rsync fails to bind to the requested port, the
error(s) returned by socket() and/or bind() are now logged.
- When we output a fatal error, we now output the version of rsync in the
message.
- Improved the documentation for the --owner and --group options.
- The rsyncstats script in "support" has an improved line-parsing regex
that is easier to read and also makes it to parse syslog-generated lines.
- A new script in "support": file-attr-restore, can be used to restore the
attributes of a file-set (the permissions, ownership, and group info)
taken from the cached output of a "find ARG... -ls" command.
DEVELOPER RELATED:
- Removed the unused function write_int_named(), the unused variable
io_read_phase, and the rarely used variable io_write_phase. This also
elides the confusing 'phase "unknown"' part of one error message.
- Removed two unused configure checks and two related (also unused)
compatibility functions.
- The xattrs.diff patch received a security fix that prevents a potential
buffer overflow in the receive_xattr() code.
- The acls.diff patch has been improved quite a bit, with more to come.
- A new patch was added: log-file.diff. This contains an early version of
a future option, --log-file=FILE, that will allow any rsync to log its
actions to a file (something that only a daemon supports at present).
NEWS for rsync 2.6.7 (11 Mar 2006)
Protocol: 29 (unchanged)
Changes since 2.6.6:
OUTPUT CHANGES:
- The letter 'D' in the itemized output was being used for both devices
(character or block) as well as other special files (such as fifos and
named sockets). This has changed to separate non-device special files
under the 'S' designation (e.g. "cS+++++++ path/fifo"). See also the
"--specials" option, below.
- The way rsync escapes unreadable characters has changed. First, rsync
now has support for recognizing valid multibyte character sequences in
your current locale, allowing it to escape fewer characters than before
for a locale such as UTF-8. Second, it now uses an escape idiom of
"\#123", which is the literal string "\#" followed by exactly 3 octal
digits. Rsync no longer doubles a backslash character in a filename
(e.g. it used to output "foo\\bar" when copying "foo\bar") -- now it only
escapes a backslash that is followed by a hash-sign and 3 digits (0-9)
(e.g. it will output "foo\#134#789" when copying "foo\#789"). See also
the --8-bit-output (-8) option, mentioned below.
Script writers: the local rsync is the one that outputs escaped names,
so if you need to support unescaping of filenames for older rsyncs, I'd
suggest that you parse the output of "rsync --version" and only use the
old unescaping rules for 2.6.5 and 2.6.6.
BUG FIXES:
- Fixed a really old bug that caused --checksum (-c) to checksum all the
files encountered during the delete scan (ouch).
- Fixed a potential hang in a remote generator: when the receiver gets a
read-error on the socket, it now signals the generator about this so that
the generator does not try to send any of the terminating error messages
to the client (avoiding a potential hang in some setups).
- Made hard-links work with symlinks and devices again.
- If the sender gets an early EOF reading a source file, we propagate this
error to the receiver so that it can discard the file and try requesting
it again (which is the existing behavior for other kinds of read errors).
- If a device-file/special-file changes permissions, rsync now updates the
permissions without recreating the file.
- If the user specifies a remote-host for both the source and destination,
we now output a syntax error rather than trying to open the destination
hostspec as a filename.
- When --inplace creates a new destination file, rsync now creates it with
permissions 0600 instead of 0000 -- this makes restarting possible when
the transfer gets interrupted in the middle of sending a new file.
- Reject the combination of --inplace and --sparse since the sparse-output
algorithm doesn't work when overwriting existing data.
- Fixed the directory name in the error that is output when pop_dir()
fails.
- Really fixed the parsing of a "!" entry in .cvsignore files this time.
- If the generator gets a stat() error on a file, output it (this used to
require at least -vv for the error to be seen).
- If waitpid() fails or the child rsync didn't exit cleanly, we now handle
the exit status properly and generate a better error.
- Fixed some glitches in the double-verbose output when using --copy-dest,
--link-dest, or --compare-dest. Also improved how the verbose output
handles hard-links (within the transfer) that had an up-to-date alternate
"dest" file, and copied files (via --copy-dest).
- Fixed the matching of the dont-compress items (e.g. *.gz) against files
that have a path component containing a slash.
- If code reading a filter/exclude file an EINTR error, rsync now clears
the error flag on the file handle so it can keep on reading.
- If --relative is active, the sending side cleans up trailing "/" or "/."
suffixes to avoid triggering a bug in older rsync versions. Also, we now
reject a ".." dir if it would be sent as a relative dir.
- If a non-directory is in the way of a directory and rsync is run with
--dry-run and --delete, rsync no longer complains about not being able
to opendir() the not-yet present directory.
- When --list-only is used and a non-existent local destination dir was
also specified as a destination, rsync no longer generates a warning
about being unable to create the missing directory.
- Fixed some problems with --relative --no-implied-dirs when the
destination directory did not yet exist: we can now create a symlink or
device when it is the first thing in the missing dir, and --fuzzy no
longer complains about being unable to open the missing dir.
- Fixed a bug where the --copy-links option would not affect implied
directories without --copy-unsafe-links (see --relative).
- Got rid of the need for --force to be used in some circumstances with
--delete-after (making it consistent with --delete-before/-during).
- Rsync now ignores the SIGXFSZ signal, just in case your OS sends this
when a file is too large (rsync handles the write error).
- Fixed a bug in the Proxy-Authorization header's base64-encoded value: it
was not properly padded with trailing '=' chars. This only affects a
user that need to use a password-authenticated proxy for an outgoing
daemon-rsync connection.
- If we're transferring an empty directory to a new name, rsync no longer
forces S_IWUSR if it wasn't already set, nor does it accidentally leave
it set.
- Fixed a bug in the debug output (-vvvvv) that could mention the wrong
checksum for the current file offset.
- Rsync no longer allows a single directory to be copied over a non-
directory destination arg.
ENHANCEMENTS:
- Added the --append option that makes rsync append data onto files that
are longer on the source than the destination (this includes new files).
- Added the --min-size=SIZE option to exclude small files from the
transfer.
- Added the --compress-level option to allow you to set how aggressive
rsync's compression should be (this option implies --compress).
- Enhanced the parsing of the SIZE value for --min-size and --max-size to
allow easy entry of multiples of 1000 (instead of just multiples of 1024)
and off-by-one values too (e.g. --max-size=8mb-1).
- Added the --8-bit-output (-8) option, which tells rsync to avoid escaping
high-bit characters that it thinks are unreadable in the current locale.
- The new option --human-readable (-h) changes the output of --progress,
--stats, and the end-of-run summary to be easier to read. If repeated,
the units become powers of 1024 instead of powers of 1000. (The old
meaning of -h, as a shorthand for --help, still works as long as you
just use it on its own, as in "rsync -h".)
- If lutimes() and/or lchmod() are around, use them to allow the
preservation of attributes on symlinks.
- The --link-dest option now affects symlinks and devices (when possible).
- Added two config items to the rsyncd.conf parsing: "pre-xfer exec" and
"post-xfer exec". These allow a command to be specified on a per-module
basis that will be run before and/or after a daemon-mode transfer. (See
the man page for a list of the environment variables that are set with
information about the transfer.)
- When using the --relative option, you can now insert a dot dir in
the source path to indicate where the replication of the source dirs
should start. For example, if you specify a source path of
rsync://host/module/foo/bar/./baz/dir with -R, rsync will now only
replicate the "baz/dir" part of the source path (note: a trailing
dot dir is unaffected unless it also has a trailing slash).
- Added some new --no-FOO options that make it easier to override unwanted
implied or default options. For example, "-a --no-o" (aka "--archive
--no-owner") can be used to turn off the preservation of file ownership
that is implied by -a.
- Added the --chmod=MODE option that allows the destination permissions to
be changed from the source permissions. E.g. --chmod=g+w,o-rwx
- Added the "incoming chmod" and "outgoing chmod" daemon options that allow
a module to specify what permissions changes should be applied to all
files copied to and from the daemon.
- Allow the --temp-dir option to be specified when starting a daemon, which
sets the default temporary directory for incoming files.
- If --delete is combined with --dirs without --recursive, rsync will now
delete in any directory whose content is being synchronized.
- If --backup is combined with --delete without --backup-dir (and without
--delete-excluded), we add a "protect" filter-rule to ensure that files
with the backup suffix are not deleted.
- The file-count stats that are output by --progress were improved to
better indicate what the numbers mean. For instance, the output:
"(xfer#5, to-check=8383/9999)" indicates that this was the fifth file
to be transferred, and we still need to check 8383 more files out of
a total of 9999.
- The include/exclude code now allows a dir/*** directive (with 3 trailing
stars) to match both the dir itself as well as all the content below the
dir (dir/** would not match the dir).
- Added the --prune-empty-dirs (-m) option that makes the receiving rsync
discard empty chains of directories from the file-list. This makes it
easier to selectively copy files from a source hierarchy and end up with
just the directories needed to hold the resulting files.
- If the --itemize-changes (-i) option is repeated, rsync now includes
unchanged files in the itemized output (similar to -vv, but without all
the other verbose messages that can get in the way). Of course, the
client must be version 2.6.7 for this to work, but the remote rsync only
needs to be 2.6.7 if you're pushing files.
- Added the --specials option to tell rsync to copy non-device special
files (which rsync now attempts even as a normal user). The --devices
option now requests the copying of just devices (character and block).
The -D option still requests both (e.g. --devices and --specials), -a
still implies -D, and non-root users still get a silent downgrade that
omits device copying.
- Added the --super option to make the receiver always attempt super-user
activities. This is useful for systems that allow things such as devices
to be created or ownership to be set without being UID 0, and is also
useful for someone who wants to ensure that errors will be output if the
receiving rsync isn't being run as root.
- Added the --sockopts option for those few who want to customize the TCP
options used to contact a daemon rsync.
- Added a way for the --temp-dir option to be combined with a partial-dir
setting that lets rsync avoid non-atomic updates (for those times when
--temp-dir is not being used because space is tight).
- A new support script, files-to-excludes, will transform a list of files
into a set of include/exclude directives that will copy those files.
- A new option, --executability (-E) can be used to preserve just the
execute bit on files, for those times when using the --perms option is
not desired.
- The daemon now logs each connection and also each module-list request
that it receives.
- New log-format options: %M (modtime), %U (uid), %G (gid), and %B
(permission bits, e.g. "rwxr-xrwt").
- The --dry-run option no longer forces the enabling of --verbose.
- The --remove-sent-files option now does a better job of incrementally
removing the sent files on the sending side (older versions tended to
clump up all the removals at the end).
- A daemon now supersedes its minimal SIGCHLD handler with the standard
PID-remembering version after forking. This ensures that the generator
can get the child-exit status from the receiver.
- Use of the --bwlimit option no longer interferes with the remote rsync
sending error messages about invalid/refused options.
- Rsync no longer returns a usage error when used with one local source arg
and no destination: this now implies the --list-only option, just like
the comparable situation with a remote source arg.
- Added the --copy-dirlinks option, a more limited version of --copy-links.
- Various documentation improvements, including: a better synopsis, some
improved examples, a better discussion of the presence and absence of
--perms (including how it interacts with the new --executability and
--chmod options), an extended discussion of --temp-dir, an improved
discussion of --partial-dir, a better description of rsync's pattern
matching characters, an improved --no-implied-dirs section, and the
documenting of what the --stats option outputs.
- Various new and updated diffs in the patches dir, including: acls.diff,
xattrs.diff, atimes.diff, detect-renamed.diff, and slp.diff.
INTERNAL:
- We now use sigaction() and sigprocmask() if possible, and fall back on
signal() if not. Using sigprocmask() ensures that rsync enables all the
signals that it needs, just in case it was started in a masked state.
- Some buffer sizes were expanded a bit, particularly on systems where
MAXPATHLEN is overly small (e.g. cygwin).
- If io_printf() tries to format more data than fits in the buffer, exit
with an error instead of transmitting a truncated buffer.
- If a va_copy macro is defined, lib/snprintf.c will use it when defining
the VA_COPY macro.
- Reduced the amount of stack memory needed for each level of directory
recursion by nearly MAXPATHLEN bytes.
- The wildmatch function was extended to allow an array of strings to be
supplied as the string to match. This allows the exclude code to do less
string copying.
- Got rid of the safe_fname() function (and all the myriad calls) and
replaced it with a new function in the log.c code that filters all the
output going to the terminal.
- Unified the f_name() and the f_name_to() functions.
- Improved the hash-table code the sender uses to handle checksums to make
it use slightly less memory and run just a little faster.
DEVELOPER RELATED:
- The diffs in the patches dir now require "patch -p1 <DIFF" instead of
the previous -p0. Also, the version included in the release tar now
affect generated files (e.g. configure, rsync.1, proto.h, etc.), so
it is no longer necessary to run autoconf and/or yodl unless you're
applying a patch that was checked out from CVS.
- Several diffs in the patches dir now use the proper --enable-FOO
configure option instead of --with-FOO to turn on the inclusion of
the newly patched feature.
- There is a new script, "prepare-source" than can be used to update the
various generated files (proto.h, configure, etc.) even before configure
has created the Makefile (this is mainly useful when patching the source
with a patch that doesn't affect generated files).
- The testsuite now sets HOME so that it won't be affected by a file such
as ~/.popt.
NEWS for rsync 2.6.6 (28 Jul 2005)
Protocol: 29 (unchanged)
Changes since 2.6.5:
SECURITY FIXES:
- The zlib code was upgraded to version 1.2.3 in order to make it more
secure. While the widely-publicized security problem in zlib 1.2.2 did
not affect rsync, another security problem surfaced that affects rsync's
zlib 1.1.4.
BUG FIXES:
- The setting of flist->high in clean_flist() was wrong for an empty list.
This could cause flist_find() to crash in certain rare circumstances
(e.g. if just the right directory setup was around when --fuzzy was
combined with --link-dest).
- The outputting of hard-linked files when verbosity was > 1 was not right:
(1) Without -i it would output the name of each hard-linked file as
though it had been changed; it now outputs a "is hard linked" message for
the file. (2) With -i it would output all dots for the unchanged
attributes of a hard-link; it now changes those dots to spaces, as is
done for other totally unchanged items.
- When backing up a changed symlink or device, get rid of any old backup
item so that we don't get an "already exists" error.
- A couple places that were comparing a local and a remote modification-
time were not honoring the --modify-window option.
- Fixed a bug where the 'p' (permissions) itemized-changes flag might get
set too often (if some non-significant mode bits differed).
- Fixed a really old, minor bug that could cause rsync to warn about being
unable to mkdir() a path that ends in "/." because it just created the
directory (required --relative, --no-implied-dirs, a source path that
ended in either a trailing slash or a trailing "/.", and a non-existing
destination dir to tickle the bug in a recent version).
ENHANCEMENTS:
- Made the "max verbosity" setting in the rsyncd.conf file settable on a
per-module basis (which now matches the documentation).
- The support/rrsync script has been upgraded to verify the args of options
that take args (instead of rejecting any such options). The script was
also changed to try to be more secure and to fix a problem in the parsing
of a pull operation that has multiple sources.
- Improved the documentation that explains the difference between a
normal daemon transfer and a daemon-over remote-shell transfer.
- Some of the diffs supplied in the patches dir were fixed and/or
improved.
BUILD CHANGES:
- Made configure define NOBODY_USER (currently hard-wired to "nobody") and
NOBODY_GROUP (set to either "nobody" or "nogroup" depending on what we
find in the /etc/group file).
- Added a test to the test suite, itemized.test, that tests the output of
-i (log-format w/%i) and some double-verbose messages.
NEWS for rsync 2.6.5 (1 Jun 2005)
Protocol: 29 (unchanged)
Changes since 2.6.4:
@@ -684,7 +228,7 @@ Changes since 2.6.3:
- An OS that has a binary mode for its files (such as cygwin) needed
setmode(fd, O_BINARY) called on the temp-file we opened with
mkstemp(). (Fix derived from cygwin's 2.6.3 rsync package.)
mkstemp(). (Fix derived from the cygwin's 2.6.3 rsync package.)
- Fixed a potential hang when verbosity is high, the client side is
the sender, and the file-list is large.
@@ -749,11 +293,9 @@ Changes since 2.6.3:
(since the forked process already has a copy of the exclude list,
there's no need to send them a set of duplicates).
- The output of the items that are being updated by the generator (dirs,
symlinks, devices) is now intermingled in the proper order with the
output from the items that the receiver is updating (regular files)
when pulling. This misordering was particularly bad when --progress
was specified. (Requires protocol 29.)
- When --progress is specified, the output of items that the generator
is creating (e.g. dirs, symlinks) is now integrated into the progress
output without overlapping it. (Requires protocol 29.)
- When --timeout is specified, lulls that occur in the transfer while
the generator is doing work that does not generate socket traffic
@@ -1160,8 +702,6 @@ Changes since 2.6.2:
user chose to combine the output of rsync's stdout and stderr (e.g.
using the "2>&1").
- Fixed an option-parsing bug when --files-from got passed to a daemon.
ENHANCEMENTS:
- Added the --partial-dir=DIR option that lets you specify where to
@@ -1375,7 +915,7 @@ Changes since 2.6.0:
- We now reset the "new data has been sent" flag at the start of
each file we send. This makes sure that an interrupted transfer
with the --partial option set doesn't keep a shorter temp file
than the current basis file when no new data has been transferred
than the current basis file when no new data has been transfered
over the wire for that file.
- Fixed a byte-order problem in --batch-mode on big-endian machines.
@@ -1428,9 +968,6 @@ Changes since 2.6.0:
- Fixed the ability to request an empty backup --suffix when sending
files to an rsync daemon.
- Fixed an option-parsing bug when --files-from was sent to a server
sender.
INTERNAL:
- Most of the I/O is now buffered, which results in a pretty large
@@ -1690,7 +1227,7 @@ Changes since 2.5.5:
* The --suffix option can now be used with --backup-dir. (Michael
Zimmerman)
* Combining "::" syntax with the --rsh/-e option now uses the
* Combining "::" syntax with the -rsh/-e option now uses the
specified remote-shell as a transport to talk to a (newly-spawned)
server-daemon. This allows someone to use daemon features, such
as modules, over a secure protocol, such as ssh. (JD Paul)
@@ -2082,10 +1619,6 @@ Changes since 2.4.6:
Partial Protocol History
RELEASE DATE VER. DATE OF COMMIT* PROTOCOL
06 Nov 2006 2.6.9 29
22 Apr 2006 2.6.8 29
11 Mar 2006 2.6.7 29
28 Jul 2005 2.6.6 29
01 Jun 2005 2.6.5 29
30 Mar 2005 2.6.4 17 Jan 2005 29
30 Sep 2004 2.6.3 28

120
TODO
View File

@@ -1,17 +1,22 @@
-*- indented-text -*-
BUGS ---------------------------------------------------------------
Do not rely on having a group called "nobody"
FEATURES ------------------------------------------------------------
Use chroot only if supported
Allow supplementary groups in rsyncd.conf 2002/04/09
Handling IPv6 on old machines
Other IPv6 stuff
Other IPv6 stuff:
Add ACL support 2001/12/02
Lazy directory creation
proxy authentication 2002/01/23
SOCKS 2002/01/23
FAT support
Allow forcing arbitrary permissions 2002/03/12
--diff david.e.sewell 2002/03/15
Add daemon --no-fork option
Create more granular verbosity 2003/05/15
Create more granular verbosity jw 2003/05/15
DOCUMENTATION --------------------------------------------------------
Keep list of open issues and todos on the web site
@@ -20,19 +25,22 @@ Perhaps redo manual as SGML
LOGGING --------------------------------------------------------------
Memory accounting
Improve error messages
Better statistics Rasmus 2002/03/08
Better statistics: Rasmus 2002/03/08
Perhaps flush stdout like syslog
Log deamon sessions that just list modules
Log child death on signal
Log errors with function that reports process of origin
verbose output David Stein 2001/12/20
internationalization
DEVELOPMENT --------------------------------------------------------
Handling duplicate names
Use generic zlib 2002/02/25
TDB 2002/03/12
TDB: 2002/03/12
Splint 2002/03/12
PERFORMANCE ----------------------------------------------------------
File list structure in memory
Traverse just one directory at a time
Allow skipping MD4 file_sum 2002/04/08
Accelerate MD4
@@ -44,6 +52,8 @@ Test on kernel source
Test large files
Create mutator program for testing
Create configure option to enable dangerous tests
If tests are skipped, say why.
Test daemon feature to disallow particular options.
Create pipe program for testing
Create test makefile target for some tests
@@ -56,6 +66,17 @@ reverse rsync over HTTP Range
BUGS ---------------------------------------------------------------
Do not rely on having a group called "nobody"
http://www.linuxbase.org/spec/refspecs/LSB_1.1.0/gLSB/usernames.html
On Debian it's "nogroup"
-- --
FEATURES ------------------------------------------------------------
@@ -112,7 +133,7 @@ Handling IPv6 on old machines
-- --
Other IPv6 stuff
Other IPv6 stuff:
Implement suggestions from http://www.kame.net/newsletter/19980604/
and ftp://ftp.iij.ad.jp/pub/RFC/rfc2553.txt
@@ -138,6 +159,15 @@ Add ACL support 2001/12/02
-- --
Lazy directory creation
With the current common --include '*/' --exclude '*' pattern, people
can end up with many empty directories. We might avoid this by
lazily creating such directories.
-- --
proxy authentication 2002/01/23
Allow RSYNC_PROXY to be http://user:pass@proxy.foo:3128/, and do
@@ -169,6 +199,35 @@ FAT support
-- --
Allow forcing arbitrary permissions 2002/03/12
On 12 Mar 2002, Dave Dykstra <dwd@bell-labs.com> wrote:
> If we would add an option to do that functionality, I
> would vote for one that was more general which could mask
> off any set of permission bits and possibly add any set of
> bits. Perhaps a chmod-like syntax if it could be
> implemented simply.
I think that would be good too. For example, people uploading files
to a web server might like to say
rsync -avzP --chmod a+rX ./ sourcefrog.net:/home/www/sourcefrog/
Ideally the patch would implement as many of the gnu chmod semantics
as possible. I think the mode parser should be a separate function
that passes back something like (mask,set) description to the rest
of the program. For bonus points there would be a test case for the
parser.
Possibly also --chown
(Debian #23628)
NOTE: there is a patch that implements this in the "patches" subdir.
-- --
--diff david.e.sewell 2002/03/15
Allow people to specify the diff command. (Might want to use wdiff,
@@ -193,7 +252,7 @@ Add daemon --no-fork option
-- --
Create more granular verbosity 2003/05/15
Create more granular verbosity jw 2003/05/15
Control output with the --report option.
@@ -263,10 +322,14 @@ Improve error messages
our load? (Debian #28416) Probably fixed now, but a test case would
be good.
When running as a daemon, some errors should both be returned to the
user and logged. This will make interacting with a daemon less
cryptic.
-- --
Better statistics Rasmus 2002/03/08
Better statistics: Rasmus 2002/03/08
<Rasmus>
hey, how about an rsync option that just gives you the
@@ -292,6 +355,14 @@ Perhaps flush stdout like syslog
-- --
Log deamon sessions that just list modules
At the connections that just get a list of modules are not logged,
but they should be.
-- --
Log child death on signal
If a child of the rsync daemon dies with a signal, we should notice
@@ -300,6 +371,15 @@ Log child death on signal
-- --
Log errors with function that reports process of origin
Use a separate function for reporting errors; prefix it with
"rsync:" or "rsync(remote)", or perhaps even "rsync(local
generator): ".
-- --
verbose output David Stein 2001/12/20
At end of transfer, show how many files were or were not transferred
@@ -365,7 +445,7 @@ Use generic zlib 2002/02/25
-- --
TDB 2002/03/12
TDB: 2002/03/12
Rather than storing the file list in memory, store it in a TDB.
@@ -392,6 +472,20 @@ Splint 2002/03/12
PERFORMANCE ----------------------------------------------------------
File list structure in memory
Rather than one big array, perhaps have a tree in memory mirroring
the directory tree.
This might make sorting much faster! (I'm not sure it's a big CPU
problem, mind you.)
It might also reduce memory use in storing repeated directory names
-- again I'm not sure this is a problem.
-- --
Traverse just one directory at a time
Traverse just one directory at a time. Tridge says it's possible.
@@ -492,6 +586,16 @@ Create configure option to enable dangerous tests
-- --
If tests are skipped, say why.
-- --
Test daemon feature to disallow particular options.
-- --
Create pipe program for testing
Create pipe program that makes slow/jerky connections for

View File

@@ -1,26 +1,29 @@
/*
Copyright (C) Andrew Tridgell 1998
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* Routines to authenticate access to a daemon (hosts allow/deny).
*
* Copyright (C) 1998 Andrew Tridgell
* Copyright (C) 2004, 2005 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
hosts allow/deny code for rsync
*/
#include "rsync.h"
static int match_hostname(char *host, char *tok)
{
if (!host || !*host)
@@ -205,7 +208,7 @@ static int match_address(char *addr, char *tok)
ret = match_binary(a, t, mask, addrlen);
out:
out:
freeaddrinfo(resa);
freeaddrinfo(rest);
return ret;

View File

@@ -1,39 +1,41 @@
/*
* Support rsync daemon authentication.
*
* Copyright (C) 1998-2000 Andrew Tridgell
* Copyright (C) 2002, 2004, 2005, 2006 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
/* -*- c-file-style: "linux"; -*-
Copyright (C) 1998-2000 by Andrew Tridgell
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* support rsync authentication */
#include "rsync.h"
extern char *password_file;
extern int am_root;
/***************************************************************************
encode a buffer using base64 - simple and slow algorithm. null terminates
the result.
***************************************************************************/
void base64_encode(char *buf, int len, char *out, int pad)
void base64_encode(char *buf, int len, char *out)
{
char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
int bit_offset, byte_offset, idx, i;
unsigned char *d = (unsigned char *)buf;
int bytes = (len*8 + 5)/6;
memset(out, 0, bytes+1);
for (i = 0; i < bytes; i++) {
byte_offset = (i*6)/8;
bit_offset = (i*6)%8;
@@ -47,11 +49,6 @@ void base64_encode(char *buf, int len, char *out, int pad)
}
out[i] = b64[idx];
}
while (pad && (i % 4))
out[i++] = '=';
out[i] = '\0';
}
/* Generate a challenge buffer and return it base64-encoded. */
@@ -73,7 +70,7 @@ static void gen_challenge(char *addr, char *challenge)
sum_update(input, sizeof input);
sum_end(md4_out);
base64_encode(md4_out, MD4_SUM_LENGTH, challenge, 0);
base64_encode(md4_out, MD4_SUM_LENGTH, challenge);
}
@@ -93,13 +90,13 @@ static int get_secret(int module, char *user, char *secret, int len)
return 0;
if (do_stat(fname, &st) == -1) {
rsyserr(FLOG, errno, "stat(%s)", fname);
rsyserr(FLOG, errno, "stat(%s)", safe_fname(fname));
ok = 0;
} else if (lp_strict_modes(module)) {
if ((st.st_mode & 06) != 0) {
rprintf(FLOG, "secrets file must not be other-accessible (see strict modes option)\n");
ok = 0;
} else if (MY_UID() == 0 && st.st_uid != 0) {
} else if (am_root && (st.st_uid != 0)) {
rprintf(FLOG, "secrets file must be owned by root when running as root (see strict modes)\n");
ok = 0;
}
@@ -163,19 +160,19 @@ static char *getpassf(char *filename)
if ((fd = open(filename,O_RDONLY)) < 0) {
rsyserr(FERROR, errno, "could not open password file \"%s\"",
filename);
safe_fname(filename));
if (envpw)
rprintf(FERROR, "falling back to RSYNC_PASSWORD environment variable.\n");
return NULL;
}
if (do_stat(filename, &st) == -1) {
rsyserr(FERROR, errno, "stat(%s)", filename);
rsyserr(FERROR, errno, "stat(%s)", safe_fname(filename));
ok = 0;
} else if ((st.st_mode & 06) != 0) {
rprintf(FERROR,"password file must not be other-accessible\n");
ok = 0;
} else if (MY_UID() == 0 && st.st_uid != 0) {
} else if (am_root && st.st_uid != 0) {
rprintf(FERROR,"password file must be owned by root when running as root\n");
ok = 0;
}
@@ -212,7 +209,7 @@ static void generate_hash(char *in, char *challenge, char *out)
sum_update(challenge, strlen(challenge));
sum_end(buf);
base64_encode(buf, MD4_SUM_LENGTH, out, 0);
base64_encode(buf, MD4_SUM_LENGTH, out);
}
/* Possibly negotiate authentication with the client. Use "leader" to
@@ -226,7 +223,7 @@ char *auth_server(int f_in, int f_out, int module, char *host, char *addr,
{
char *users = lp_auth_users(module);
char challenge[MD4_SUM_LENGTH*2];
char line[BIGPATHBUFLEN];
char line[MAXPATHLEN];
char secret[512];
char pass2[MD4_SUM_LENGTH*2];
char *tok, *pass;

View File

@@ -1,27 +1,27 @@
/*
* Backup handling code.
*
* Copyright (C) 1999 Andrew Tridgell
* Copyright (C) 2003, 2004, 2005, 2006 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
Copyright (C) Andrew Tridgell 1999
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* backup handling code */
#include "rsync.h"
extern int verbose;
extern int backup_suffix_len;
extern int backup_dir_len;
extern unsigned int backup_dir_remainder;
extern char backup_dir_buf[MAXPATHLEN];
@@ -30,8 +30,9 @@ extern char *backup_dir;
extern int am_root;
extern int preserve_devices;
extern int preserve_specials;
extern int preserve_links;
extern int preserve_hard_links;
extern int orig_umask;
extern int safe_symlinks;
/* make a complete pathname for backup file */
@@ -64,7 +65,8 @@ static int make_simple_backup(char *fname)
if (do_rename(fname, fnamebak) == 0) {
if (verbose > 1) {
rprintf(FINFO, "backed up %s to %s\n",
fname, fnamebak);
safe_fname(fname),
safe_fname(fnamebak));
}
break;
}
@@ -79,7 +81,7 @@ static int make_simple_backup(char *fname)
continue;
rsyserr(FERROR, rename_errno, "rename %s to backup %s",
fname, fnamebak);
safe_fname(fname), safe_fname(fnamebak));
errno = rename_errno;
return 0;
}
@@ -110,7 +112,7 @@ static int make_bak_dir(char *fullpath)
}
if (*p == '/') {
*p = '\0';
if (mkdir_defmode(fullpath) == 0)
if (do_mkdir(fullpath, 0777 & ~orig_umask) == 0)
break;
if (errno != ENOENT) {
rsyserr(FERROR, errno,
@@ -139,7 +141,7 @@ static int make_bak_dir(char *fullpath)
p += strlen(p);
if (p == end)
break;
if (mkdir_defmode(fullpath) < 0) {
if (do_mkdir(fullpath, 0777 & ~orig_umask) < 0) {
rsyserr(FERROR, errno, "make_bak_dir mkdir %s failed",
full_fname(fullpath));
goto failure;
@@ -147,7 +149,7 @@ static int make_bak_dir(char *fullpath)
}
return 0;
failure:
failure:
while (p != end) {
*p = '/';
p += strlen(p);
@@ -158,9 +160,8 @@ static int make_bak_dir(char *fullpath)
/* robustly move a file, creating new directory structures if necessary */
static int robust_move(char *src, char *dst)
{
if (robust_rename(src, dst, NULL, 0755) < 0
&& (errno != ENOENT || make_bak_dir(dst) < 0
|| robust_rename(src, dst, NULL, 0755) < 0))
if (robust_rename(src, dst, 0755) < 0 && (errno != ENOENT
|| make_bak_dir(dst) < 0 || robust_rename(src, dst, 0755) < 0))
return -1;
return 0;
}
@@ -180,15 +181,14 @@ static int keep_backup(char *fname)
if (do_lstat(fname, &st) < 0)
return 1;
if (!(file = make_file(fname, NULL, NULL, 0, NO_FILTERS)))
if (!(file = make_file(fname, NULL, NO_FILTERS)))
return 1; /* the file could have disappeared */
if (!(buf = get_backup_name(fname)))
return 0;
/* Check to see if this is a device file, or link */
if ((am_root && preserve_devices && IS_DEVICE(file->mode))
|| (preserve_specials && IS_SPECIAL(file->mode))) {
if (IS_DEVICE(file->mode) && am_root && preserve_devices) {
do_unlink(buf);
if (do_mknod(buf, file->mode, file->u.rdev) < 0
&& (errno != ENOENT || make_bak_dir(buf) < 0
@@ -197,7 +197,7 @@ static int keep_backup(char *fname)
full_fname(buf));
} else if (verbose > 2) {
rprintf(FINFO, "make_backup: DEVICE %s successful.\n",
fname);
safe_fname(fname));
}
kept = 1;
do_unlink(fname);
@@ -235,7 +235,7 @@ static int keep_backup(char *fname)
|| do_symlink(file->u.link, buf) < 0)) {
rsyserr(FERROR, errno, "link %s -> \"%s\"",
full_fname(buf),
file->u.link);
safe_fname(file->u.link));
}
do_unlink(fname);
kept = 1;
@@ -245,7 +245,7 @@ static int keep_backup(char *fname)
if (!kept && !S_ISREG(file->mode)) {
rprintf(FINFO, "make_bak: skipping non-regular file %s\n",
fname);
safe_fname(fname));
return 1;
}
@@ -253,19 +253,19 @@ static int keep_backup(char *fname)
if (!kept) {
if (robust_move(fname, buf) != 0) {
rsyserr(FERROR, errno, "keep_backup failed: %s -> \"%s\"",
full_fname(fname), buf);
full_fname(fname), safe_fname(buf));
} else if (st.st_nlink > 1) {
/* If someone has hard-linked the file into the backup
* dir, rename() might return success but do nothing! */
robust_unlink(fname); /* Just in case... */
}
}
set_file_attrs(buf, file, NULL, 0);
set_perms(buf, file, NULL, 0);
free(file);
if (verbose > 1) {
rprintf(FINFO, "backed up %s to %s\n",
fname, buf);
safe_fname(fname), safe_fname(buf));
}
return 1;
}

86
batch.c
View File

@@ -1,29 +1,14 @@
/*
* Support for the batch-file options.
*
* Copyright (C) 1999 Weiss
* Copyright (C) 2004 Chris Shoemaker
* Copyright (C) 2004, 2005, 2006 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
/* -*- c-file-style: "linux" -*-
Weiss 1/1999
Batch utilities for rsync.
*/
#include "rsync.h"
#include "zlib/zlib.h"
#include <time.h>
extern int am_sender;
extern int eol_nulls;
extern int recurse;
extern int xfer_dirs;
@@ -34,14 +19,11 @@ extern int preserve_uid;
extern int preserve_gid;
extern int always_checksum;
extern int do_compression;
extern int def_compress_level;
extern int protocol_version;
extern char *batch_name;
extern struct filter_list_struct filter_list;
static int tweaked_compress_level;
static int *flag_ptr[] = {
&recurse, /* 0 */
&preserve_uid, /* 1 */
@@ -51,7 +33,7 @@ static int *flag_ptr[] = {
&preserve_hard_links, /* 5 */
&always_checksum, /* 6 */
&xfer_dirs, /* 7 (protocol 29) */
&tweaked_compress_level,/* 8 (protocol 29) */
&do_compression, /* 8 (protocol 29) */
NULL
};
@@ -72,12 +54,6 @@ void write_stream_flags(int fd)
{
int i, flags;
#if Z_DEFAULT_COMPRESSION == -1
tweaked_compress_level = do_compression ? def_compress_level + 2 : 0;
#else
#error internal logic error! Fix def_compress_level logic above and below too!
#endif
/* Start the batch file with a bitmap of data-stream-affecting
* flags. */
if (protocol_version < 29)
@@ -112,13 +88,6 @@ void read_stream_flags(int fd)
else if (xfer_dirs < 2)
xfer_dirs = 0;
}
if (tweaked_compress_level == 0 || tweaked_compress_level == 2)
do_compression = 0;
else {
do_compression = 1;
def_compress_level = tweaked_compress_level - 2;
}
}
static void write_arg(int fd, char *arg)
@@ -179,7 +148,7 @@ void write_batch_shell_file(int argc, char *argv[], int file_arg_cnt)
S_IRUSR | S_IWUSR | S_IEXEC);
if (fd < 0) {
rsyserr(FERROR, errno, "Batch file %s open error",
filename);
safe_fname(filename));
exit_cleanup(1);
}
@@ -225,7 +194,42 @@ void write_batch_shell_file(int argc, char *argv[], int file_arg_cnt)
write_filter_rules(fd);
if (write(fd, "\n", 1) != 1 || close(fd) < 0) {
rsyserr(FERROR, errno, "Batch file %s write error",
filename);
safe_fname(filename));
exit_cleanup(1);
}
}
void show_flist(int index, struct file_struct **fptr)
{
/* for debugging show_flist(flist->count, flist->files * */
int i;
for (i = 0; i < index; i++) {
rprintf(FINFO, "flist->flags=%#x\n", fptr[i]->flags);
rprintf(FINFO, "flist->modtime=%#lx\n",
(long unsigned) fptr[i]->modtime);
rprintf(FINFO, "flist->length=%.0f\n",
(double) fptr[i]->length);
rprintf(FINFO, "flist->mode=%#o\n", (int) fptr[i]->mode);
rprintf(FINFO, "flist->basename=%s\n",
safe_fname(fptr[i]->basename));
if (fptr[i]->dirname) {
rprintf(FINFO, "flist->dirname=%s\n",
safe_fname(fptr[i]->dirname));
}
if (am_sender && fptr[i]->dir.root) {
rprintf(FINFO, "flist->dir.root=%s\n",
safe_fname(fptr[i]->dir.root));
}
}
}
/* for debugging */
void show_argvs(int argc, char *argv[])
{
int i;
rprintf(FINFO, "BATCH.C:show_argvs,argc=%d\n", argc);
for (i = 0; i < argc; i++)
rprintf(FINFO, "i=%d,argv[i]=%s\n", i, safe_fname(argv[i]));
}

View File

@@ -1,26 +1,25 @@
/*
* Simple byteorder handling.
*
* Copyright (C) 1992-1995 Andrew Tridgell
*
* 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
/*
simple byteorder handling
Copyright (C) Andrew Tridgell 1992-1995
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#undef CAREFUL_ALIGNMENT
/* we know that the x86 can handle misalignment and has the "right"
/* we know that the x86 can handle misalignment and has the "right"
byteorder */
#ifdef __i386__
#define CAREFUL_ALIGNMENT 0

View File

@@ -1,80 +0,0 @@
/*
* End-of-run cleanup helper code used by cleanup.c.
*
* Copyright (C) 2006 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
/* This is included by cleanup.c multiple times, once for every segement in
* the _exit_cleanup() code. This produces the next "case N:" statement in
* sequence and increments the cleanup_step variable by 1. This ensures that
* our case statements never get out of whack due to added/removed steps. */
#if !defined EXIT_CLEANUP_CASE_0
#define EXIT_CLEANUP_CASE_0
case 0:
#elif !defined EXIT_CLEANUP_CASE_1
#define EXIT_CLEANUP_CASE_1
case 1:
#elif !defined EXIT_CLEANUP_CASE_2
#define EXIT_CLEANUP_CASE_2
case 2:
#elif !defined EXIT_CLEANUP_CASE_3
#define EXIT_CLEANUP_CASE_3
case 3:
#elif !defined EXIT_CLEANUP_CASE_4
#define EXIT_CLEANUP_CASE_4
case 4:
#elif !defined EXIT_CLEANUP_CASE_5
#define EXIT_CLEANUP_CASE_5
case 5:
#elif !defined EXIT_CLEANUP_CASE_6
#define EXIT_CLEANUP_CASE_6
case 6:
#elif !defined EXIT_CLEANUP_CASE_7
#define EXIT_CLEANUP_CASE_7
case 7:
#elif !defined EXIT_CLEANUP_CASE_8
#define EXIT_CLEANUP_CASE_8
case 8:
#elif !defined EXIT_CLEANUP_CASE_9
#define EXIT_CLEANUP_CASE_9
case 9:
#elif !defined EXIT_CLEANUP_CASE_10
#define EXIT_CLEANUP_CASE_10
case 10:
#elif !defined EXIT_CLEANUP_CASE_11
#define EXIT_CLEANUP_CASE_11
case 11:
#elif !defined EXIT_CLEANUP_CASE_12
#define EXIT_CLEANUP_CASE_12
case 12:
#elif !defined EXIT_CLEANUP_CASE_13
#define EXIT_CLEANUP_CASE_13
case 13:
#elif !defined EXIT_CLEANUP_CASE_14
#define EXIT_CLEANUP_CASE_14
case 14:
#elif !defined EXIT_CLEANUP_CASE_15
#define EXIT_CLEANUP_CASE_15
case 15:
#elif !defined EXIT_CLEANUP_CASE_16
#define EXIT_CLEANUP_CASE_16
case 16:
#else
#error Need to add more case statements!
#endif
cleanup_step++;

View File

@@ -1,24 +1,21 @@
/*
* Routines to support checksumming of bytes.
*
* Copyright (C) 1996 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2004, 2005 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
Copyright (C) Andrew Tridgell 1996
Copyright (C) Paul Mackerras 1996
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "rsync.h"

226
chmod.c
View File

@@ -1,226 +0,0 @@
/*
* Implement the core of the --chmod option.
*
* Copyright (C) 2002 Scott Howard
* Copyright (C) 2005, 2006 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "rsync.h"
extern mode_t orig_umask;
#define FLAG_X_KEEP (1<<0)
#define FLAG_DIRS_ONLY (1<<1)
#define FLAG_FILES_ONLY (1<<2)
struct chmod_mode_struct {
struct chmod_mode_struct *next;
int ModeAND, ModeOR;
char flags;
};
#define CHMOD_ADD 1
#define CHMOD_SUB 2
#define CHMOD_EQ 3
#define STATE_ERROR 0
#define STATE_1ST_HALF 1
#define STATE_2ND_HALF 2
/* Parse a chmod-style argument, and break it down into one or more AND/OR
* pairs in a linked list. We return a pointer to new items on succcess
* (appending the items to the specified list), or NULL on error. */
struct chmod_mode_struct *parse_chmod(const char *modestr,
struct chmod_mode_struct **root_mode_ptr)
{
int state = STATE_1ST_HALF;
int where = 0, what = 0, op = 0, topbits = 0, topoct = 0, flags = 0;
struct chmod_mode_struct *first_mode = NULL, *curr_mode = NULL,
*prev_mode = NULL;
while (state != STATE_ERROR) {
if (!*modestr || *modestr == ',') {
int bits;
if (!op) {
state = STATE_ERROR;
break;
}
prev_mode = curr_mode;
curr_mode = new_array(struct chmod_mode_struct, 1);
if (prev_mode)
prev_mode->next = curr_mode;
else
first_mode = curr_mode;
curr_mode->next = NULL;
if (where)
bits = where * what;
else {
where = 0111;
bits = (where * what) & ~orig_umask;
}
switch (op) {
case CHMOD_ADD:
curr_mode->ModeAND = CHMOD_BITS;
curr_mode->ModeOR = bits + topoct;
break;
case CHMOD_SUB:
curr_mode->ModeAND = CHMOD_BITS - bits - topoct;
curr_mode->ModeOR = 0;
break;
case CHMOD_EQ:
curr_mode->ModeAND = CHMOD_BITS - (where * 7) - (topoct ? topbits : 0);
curr_mode->ModeOR = bits + topoct;
break;
}
curr_mode->flags = flags;
if (!*modestr)
break;
modestr++;
state = STATE_1ST_HALF;
where = what = op = topoct = topbits = flags = 0;
}
if (state != STATE_2ND_HALF) {
switch (*modestr) {
case 'D':
if (flags & FLAG_FILES_ONLY)
state = STATE_ERROR;
flags |= FLAG_DIRS_ONLY;
break;
case 'F':
if (flags & FLAG_DIRS_ONLY)
state = STATE_ERROR;
flags |= FLAG_FILES_ONLY;
break;
case 'u':
where |= 0100;
topbits |= 04000;
break;
case 'g':
where |= 0010;
topbits |= 02000;
break;
case 'o':
where |= 0001;
break;
case 'a':
where |= 0111;
break;
case '+':
op = CHMOD_ADD;
state = STATE_2ND_HALF;
break;
case '-':
op = CHMOD_SUB;
state = STATE_2ND_HALF;
break;
case '=':
op = CHMOD_EQ;
state = STATE_2ND_HALF;
break;
default:
state = STATE_ERROR;
break;
}
} else {
switch (*modestr) {
case 'r':
what |= 4;
break;
case 'w':
what |= 2;
break;
case 'X':
flags |= FLAG_X_KEEP;
/* FALL THROUGH */
case 'x':
what |= 1;
break;
case 's':
if (topbits)
topoct |= topbits;
else
topoct = 04000;
break;
case 't':
topoct |= 01000;
break;
default:
state = STATE_ERROR;
break;
}
}
modestr++;
}
if (state == STATE_ERROR) {
free_chmod_mode(first_mode);
return NULL;
}
if (!(curr_mode = *root_mode_ptr))
*root_mode_ptr = first_mode;
else {
while (curr_mode->next)
curr_mode = curr_mode->next;
curr_mode->next = first_mode;
}
return first_mode;
}
/* Takes an existing file permission and a list of AND/OR changes, and
* create a new permissions. */
int tweak_mode(int mode, struct chmod_mode_struct *chmod_modes)
{
int IsX = mode & 0111;
int NonPerm = mode & ~CHMOD_BITS;
for ( ; chmod_modes; chmod_modes = chmod_modes->next) {
if ((chmod_modes->flags & FLAG_DIRS_ONLY) && !S_ISDIR(NonPerm))
continue;
if ((chmod_modes->flags & FLAG_FILES_ONLY) && S_ISDIR(NonPerm))
continue;
mode &= chmod_modes->ModeAND;
if ((chmod_modes->flags & FLAG_X_KEEP) && !IsX && !S_ISDIR(NonPerm))
mode |= chmod_modes->ModeOR & ~0111;
else
mode |= chmod_modes->ModeOR;
}
return mode | NonPerm;
}
/* Free the linked list created by parse_chmod. */
int free_chmod_mode(struct chmod_mode_struct *chmod_modes)
{
struct chmod_mode_struct *next;
while (chmod_modes) {
next = chmod_modes->next;
free(chmod_modes);
chmod_modes = next;
}
return 0;
}

216
cleanup.c
View File

@@ -1,39 +1,30 @@
/*
* End-of-run cleanup routines.
*
* Copyright (C) 1996-2000 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2002 Martin Pool
* Copyright (C) 2003, 2004, 2005, 2006 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
/* -*- c-file-style: "linux" -*-
Copyright (C) 1996-2000 by Andrew Tridgell
Copyright (C) Paul Mackerras 1996
Copyright (C) 2002 by Martin Pool
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "rsync.h"
extern int am_server;
extern int am_daemon;
extern int io_error;
extern int keep_partial;
extern int log_got_error;
extern char *partial_dir;
extern char *logfile_name;
#ifdef HAVE_SIGACTION
static struct sigaction sigact;
#endif
/**
* Close all open sockets and files, allowing a (somewhat) graceful
@@ -92,117 +83,82 @@ pid_t cleanup_child_pid = -1;
*
* @param code one of the RERR_* codes from errcode.h.
**/
NORETURN void _exit_cleanup(int code, const char *file, int line)
void _exit_cleanup(int code, const char *file, int line)
{
static int cleanup_step = 0;
static int exit_code = 0;
static int unmodified_code = 0;
int ocode = code;
static int inside_cleanup = 0;
SIGACTION(SIGUSR1, SIG_IGN);
SIGACTION(SIGUSR2, SIG_IGN);
if (inside_cleanup > 10) {
/* prevent the occasional infinite recursion */
return;
}
inside_cleanup++;
if (exit_code) /* Preserve first error code when recursing. */
code = exit_code;
signal(SIGUSR1, SIG_IGN);
signal(SIGUSR2, SIG_IGN);
/* Some of our actions might cause a recursive call back here, so we
* keep track of where we are in the cleanup and never repeat a step. */
switch (cleanup_step) {
#include "case_N.h" /* case 0: cleanup_step++; */
exit_code = unmodified_code = code;
if (verbose > 3) {
rprintf(FINFO,
"_exit_cleanup(code=%d, file=%s, line=%d): entered\n",
code, file, line);
}
/* FALLTHROUGH */
#include "case_N.h"
if (cleanup_child_pid != -1) {
int status;
int pid = wait_process(cleanup_child_pid, &status, WNOHANG);
if (pid == cleanup_child_pid) {
status = WEXITSTATUS(status);
if (status > code)
code = exit_code = status;
}
}
/* FALLTHROUGH */
#include "case_N.h"
if (cleanup_got_literal && cleanup_fname && cleanup_new_fname
&& keep_partial && handle_partial_dir(cleanup_new_fname, PDIR_CREATE)) {
char *fname = cleanup_fname;
cleanup_fname = NULL;
if (cleanup_fd_r != -1)
close(cleanup_fd_r);
if (cleanup_fd_w != -1) {
flush_write_file(cleanup_fd_w);
close(cleanup_fd_w);
}
finish_transfer(cleanup_new_fname, fname, NULL,
cleanup_file, 0, !partial_dir);
}
/* FALLTHROUGH */
#include "case_N.h"
io_flush(FULL_FLUSH);
/* FALLTHROUGH */
#include "case_N.h"
if (cleanup_fname)
do_unlink(cleanup_fname);
if (code)
kill_all(SIGUSR1);
if (cleanup_pid && cleanup_pid == getpid()) {
char *pidf = lp_pid_file();
if (pidf && *pidf)
unlink(lp_pid_file());
}
if (code == 0) {
if (io_error & IOERR_DEL_LIMIT)
code = exit_code = RERR_DEL_LIMIT;
if (io_error & IOERR_VANISHED)
code = exit_code = RERR_VANISHED;
if (io_error & IOERR_GENERAL || log_got_error)
code = exit_code = RERR_PARTIAL;
}
if (code || am_daemon || (logfile_name && (am_server || !verbose)))
log_exit(code, file, line);
/* FALLTHROUGH */
#include "case_N.h"
if (verbose > 2) {
rprintf(FINFO,
"_exit_cleanup(code=%d, file=%s, line=%d): "
"about to call exit(%d)\n",
unmodified_code, file, line, code);
}
/* FALLTHROUGH */
#include "case_N.h"
close_all();
/* FALLTHROUGH */
default:
break;
if (verbose > 3) {
rprintf(FINFO,"_exit_cleanup(code=%d, file=%s, line=%d): entered\n",
code, safe_fname(file), line);
}
if (cleanup_child_pid != -1) {
int status;
if (waitpid(cleanup_child_pid, &status, WNOHANG) == cleanup_child_pid) {
status = WEXITSTATUS(status);
if (status > code)
code = status;
}
}
if (cleanup_got_literal && cleanup_fname && keep_partial
&& handle_partial_dir(cleanup_new_fname, PDIR_CREATE)) {
char *fname = cleanup_fname;
cleanup_fname = NULL;
if (cleanup_fd_r != -1)
close(cleanup_fd_r);
if (cleanup_fd_w != -1) {
flush_write_file(cleanup_fd_w);
close(cleanup_fd_w);
}
finish_transfer(cleanup_new_fname, fname, cleanup_file, 0,
!partial_dir);
}
io_flush(FULL_FLUSH);
if (cleanup_fname)
do_unlink(cleanup_fname);
if (code)
kill_all(SIGUSR1);
if (cleanup_pid && cleanup_pid == getpid()) {
char *pidf = lp_pid_file();
if (pidf && *pidf)
unlink(lp_pid_file());
}
if (code == 0) {
if (io_error & IOERR_DEL_LIMIT)
code = RERR_DEL_LIMIT;
if (io_error & IOERR_VANISHED)
code = RERR_VANISHED;
if (io_error & IOERR_GENERAL || log_got_error)
code = RERR_PARTIAL;
}
if (code)
log_exit(code, file, line);
if (verbose > 2) {
rprintf(FINFO,"_exit_cleanup(code=%d, file=%s, line=%d): about to call exit(%d)\n",
ocode, safe_fname(file), line, code);
}
close_all();
exit(code);
}
void cleanup_disable(void)
{
cleanup_fname = cleanup_new_fname = NULL;
cleanup_fname = NULL;
cleanup_got_literal = 0;
}
@@ -211,7 +167,7 @@ void cleanup_set(char *fnametmp, char *fname, struct file_struct *file,
int fd_r, int fd_w)
{
cleanup_fname = fnametmp;
cleanup_new_fname = fname; /* can be NULL on a partial-dir failure */
cleanup_new_fname = fname;
cleanup_file = file;
cleanup_fd_r = fd_r;
cleanup_fd_w = fd_w;

View File

@@ -1,35 +1,40 @@
/*
/* -*- c-file-style: "linux" -*-
rsync -- fast file replication program
Copyright (C) 1992-2001 by Andrew Tridgell <tridge@samba.org>
Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/**
* @file clientname.c
*
* Functions for looking up the remote name or addr of a socket.
*
* Copyright (C) 1992-2001 Andrew Tridgell <tridge@samba.org>
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
* Copyright (C) 2002, 2003, 2004 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
/*
* This file is now converted to use the new-style getaddrinfo()
* interface, which supports IPv6 but is also supported on recent
* IPv4-only machines. On systems that don't have that interface, we
* emulate it using the KAME implementation.
*/
**/
#include "rsync.h"
static const char default_name[] = "UNKNOWN";
extern int am_daemon;
extern int am_server;
@@ -50,7 +55,7 @@ char *client_addr(int fd)
initialised = 1;
if (am_server) { /* daemon over --rsh mode */
strlcpy(addr_buf, "0.0.0.0", sizeof addr_buf);
strcpy(addr_buf, "0.0.0.0");
if ((ssh_info = getenv("SSH_CONNECTION")) != NULL
|| (ssh_info = getenv("SSH_CLIENT")) != NULL
|| (ssh_info = getenv("SSH2_CLIENT")) != NULL) {
@@ -99,7 +104,7 @@ char *client_name(int fd)
if (initialised)
return name_buf;
strlcpy(name_buf, default_name, sizeof name_buf);
strcpy(name_buf, default_name);
initialised = 1;
memset(&ss, 0, sizeof ss);
@@ -133,8 +138,6 @@ char *client_name(int fd)
memcpy(&ss, answer->ai_addr, ss_len);
break;
#endif
default:
exit_cleanup(RERR_SOCKETIO);
}
freeaddrinfo(answer);
} else {
@@ -144,7 +147,7 @@ char *client_name(int fd)
if (lookup_name(fd, &ss, ss_len, name_buf, sizeof name_buf,
port_buf, sizeof port_buf) == 0)
check_name(fd, &ss, name_buf, sizeof name_buf);
check_name(fd, &ss, name_buf);
return name_buf;
}
@@ -208,18 +211,18 @@ void client_sockaddr(int fd,
**/
int lookup_name(int fd, const struct sockaddr_storage *ss,
socklen_t ss_len,
char *name_buf, size_t name_buf_size,
char *port_buf, size_t port_buf_size)
char *name_buf, size_t name_buf_len,
char *port_buf, size_t port_buf_len)
{
int name_err;
/* reverse lookup */
name_err = getnameinfo((struct sockaddr *) ss, ss_len,
name_buf, name_buf_size,
port_buf, port_buf_size,
name_buf, name_buf_len,
port_buf, port_buf_len,
NI_NAMEREQD | NI_NUMERICSERV);
if (name_err != 0) {
strlcpy(name_buf, default_name, name_buf_size);
strcpy(name_buf, default_name);
rprintf(FLOG, "name lookup failed for %s: %s\n",
client_addr(fd), gai_strerror(name_err));
return name_err;
@@ -300,7 +303,7 @@ int compare_addrinfo_sockaddr(const struct addrinfo *ai,
**/
int check_name(int fd,
const struct sockaddr_storage *ss,
char *name_buf, size_t name_buf_size)
char *name_buf)
{
struct addrinfo hints, *res, *res0;
int error;
@@ -314,10 +317,11 @@ int check_name(int fd,
if (error) {
rprintf(FLOG, "forward name lookup for %s failed: %s\n",
name_buf, gai_strerror(error));
strlcpy(name_buf, default_name, name_buf_size);
strcpy(name_buf, default_name);
return error;
}
/* Given all these results, we expect that one of them will be
* the same as ss. The comparison is a bit complicated. */
for (res = res0; res; res = res->ai_next) {
@@ -330,13 +334,13 @@ int check_name(int fd,
* address that was the same as ss. */
rprintf(FLOG, "no known address for \"%s\": "
"spoofed address?\n", name_buf);
strlcpy(name_buf, default_name, name_buf_size);
strcpy(name_buf, default_name);
} else if (res == NULL) {
/* We hit the end of the list without finding an
* address that was the same as ss. */
rprintf(FLOG, "%s is not a known address for \"%s\": "
"spoofed address?\n", client_addr(fd), name_buf);
strlcpy(name_buf, default_name, name_buf_size);
strcpy(name_buf, default_name);
}
freeaddrinfo(res0);

View File

@@ -1,9 +1,7 @@
/*
* The socket based protocol for setting up a connection with rsyncd.
/* -*- c-file-style: "linux"; -*-
*
* Copyright (C) 1998-2001 Andrew Tridgell <tridge@samba.org>
* Copyright (C) 2001-2002 Martin Pool <mbp@samba.org>
* Copyright (C) 2002, 2003, 2004, 2005, 2006 Wayne Davison
* Copyright (C) 1998-2001 by Andrew Tridgell <tridge@samba.org>
* Copyright (C) 2001-2002 by Martin Pool <mbp@samba.org>
*
* 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
@@ -15,16 +13,21 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/**
* @file
*
* The socket based protocol for setting up a connection with
* rsyncd.
**/
#include "rsync.h"
extern int verbose;
extern int quiet;
extern int output_motd;
extern int list_only;
extern int am_sender;
extern int am_server;
@@ -38,32 +41,23 @@ extern int filesfrom_fd;
extern int remote_protocol;
extern int protocol_version;
extern int io_timeout;
extern int orig_umask;
extern int no_detach;
extern int default_af_hint;
extern int logfile_format_has_i;
extern int logfile_format_has_o_or_i;
extern mode_t orig_umask;
extern char *bind_address;
extern char *sockopts;
extern char *config_file;
extern char *logfile_format;
extern char *files_from;
extern char *tmpdir;
extern struct chmod_mode_struct *chmod_modes;
extern struct filter_list_struct server_filter_list;
extern char *config_file;
extern char *files_from;
char *auth_user;
int read_only = 0;
int daemon_log_format_has_i = 0;
int daemon_log_format_has_o_or_i = 0;
int module_id = -1;
struct chmod_mode_struct *daemon_chmod_modes;
/* Length of lp_path() string when in daemon mode & not chrooted, else 0. */
unsigned int module_dirlen = 0;
#ifdef HAVE_SIGACTION
static struct sigaction sigact;
#endif
/**
* Run a client connected to an rsyncd. The alternative to this
* function for remote-shell connections is do_cmd().
@@ -103,20 +97,18 @@ int start_socket_client(char *host, char *path, int argc, char *argv[])
if (fd == -1)
exit_cleanup(RERR_SOCKETIO);
set_socket_options(fd, sockopts);
ret = start_inband_exchange(user, path, fd, fd, argc);
return ret ? ret : client_run(fd, fd, -1, argc, argv);
}
int start_inband_exchange(char *user, char *path, int f_in, int f_out,
int start_inband_exchange(char *user, char *path, int f_in, int f_out,
int argc)
{
int i;
char *sargs[MAX_ARGS];
int sargc = 0;
char line[BIGPATHBUFLEN];
char line[MAXPATHLEN];
char *p;
if (argc == 0 && !am_sender)
@@ -206,10 +198,7 @@ int start_inband_exchange(char *user, char *path, int f_in, int f_out,
return -1;
}
/* This might be a MOTD line or a module listing, but there is
* no way to differentiate it. The manpage mentions this. */
if (output_motd)
rprintf(FINFO, "%s\n", line);
rprintf(FINFO, "%s\n", line);
}
kluge_around_eof = 0;
@@ -226,62 +215,27 @@ int start_inband_exchange(char *user, char *path, int f_in, int f_out,
return 0;
}
static char *finish_pre_exec(pid_t pid, int fd, char *request,
int argc, char *argv[])
{
int j, status = -1;
if (request) {
write_buf(fd, request, strlen(request)+1);
for (j = 0; j < argc; j++)
write_buf(fd, argv[j], strlen(argv[j])+1);
}
write_byte(fd, 0);
close(fd);
if (wait_process(pid, &status, 0) < 0
|| !WIFEXITED(status) || WEXITSTATUS(status) != 0) {
char *e;
if (asprintf(&e, "pre-xfer exec returned failure (%d)\n", status) < 0)
out_of_memory("finish_pre_exec");
return e;
}
return NULL;
}
static int read_arg_from_pipe(int fd, char *buf, int limit)
{
char *bp = buf, *eob = buf + limit - 1;
while (1) {
if (read(fd, bp, 1) != 1)
return -1;
if (*bp == '\0')
break;
if (bp < eob)
bp++;
}
*bp = '\0';
return bp - buf;
}
static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
static int rsync_module(int f_in, int f_out, int i)
{
int argc = 0;
int maxargs;
char **argv;
char line[BIGPATHBUFLEN];
char **argp;
char line[MAXPATHLEN];
uid_t uid = (uid_t)-2; /* canonically "nobody" */
gid_t gid = (gid_t)-2;
char *p, *err_msg = NULL;
char *p;
#ifdef HAVE_PUTENV
char *s;
#endif
char *addr = client_addr(f_in);
char *host = client_name(f_in);
char *name = lp_name(i);
int use_chroot = lp_use_chroot(i);
int start_glob = 0;
int ret, pre_exec_fd = -1;
pid_t pre_exec_pid = 0;
int ret;
char *request = NULL;
if (!allow_access(addr, host, lp_hosts_allow(i), lp_hosts_deny(i))) {
@@ -305,7 +259,7 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
if (!claim_connection(lp_lock_file(i), lp_max_connections(i))) {
if (errno) {
rsyserr(FLOG, errno, "failed to open lock file %s",
lp_lock_file(i));
safe_fname(lp_lock_file(i)));
io_printf(f_out, "@ERROR: failed to open lock file\n");
} else {
rprintf(FLOG, "max connections (%d) reached\n",
@@ -328,12 +282,13 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
if (lp_read_only(i))
read_only = 1;
if (lp_transfer_logging(i) && !logfile_format)
logfile_format = lp_log_format(i);
if (log_format_has(logfile_format, 'i'))
logfile_format_has_i = 1;
if (logfile_format_has_i || log_format_has(logfile_format, 'o'))
logfile_format_has_o_or_i = 1;
if (lp_transfer_logging(i)) {
if (log_format_has(lp_log_format(i), 'i'))
daemon_log_format_has_i = 1;
if (daemon_log_format_has_i
|| log_format_has(lp_log_format(i), 'o'))
daemon_log_format_has_o_or_i = 1;
}
am_root = (MY_UID() == 0);
@@ -374,29 +329,31 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
p = lp_filter(i);
parse_rule(&server_filter_list, p, MATCHFLG_WORD_SPLIT,
XFLG_ABS_IF_SLASH);
XFLG_ANCHORED2ABS);
p = lp_include_from(i);
parse_filter_file(&server_filter_list, p, MATCHFLG_INCLUDE,
XFLG_ABS_IF_SLASH | XFLG_OLD_PREFIXES | XFLG_FATAL_ERRORS);
XFLG_ANCHORED2ABS | XFLG_OLD_PREFIXES | XFLG_FATAL_ERRORS);
p = lp_include(i);
parse_rule(&server_filter_list, p,
MATCHFLG_INCLUDE | MATCHFLG_WORD_SPLIT,
XFLG_ABS_IF_SLASH | XFLG_OLD_PREFIXES);
XFLG_ANCHORED2ABS | XFLG_OLD_PREFIXES);
p = lp_exclude_from(i);
parse_filter_file(&server_filter_list, p, 0,
XFLG_ABS_IF_SLASH | XFLG_OLD_PREFIXES | XFLG_FATAL_ERRORS);
XFLG_ANCHORED2ABS | XFLG_OLD_PREFIXES | XFLG_FATAL_ERRORS);
p = lp_exclude(i);
parse_rule(&server_filter_list, p, MATCHFLG_WORD_SPLIT,
XFLG_ABS_IF_SLASH | XFLG_OLD_PREFIXES);
XFLG_ANCHORED2ABS | XFLG_OLD_PREFIXES);
log_init(1);
log_init();
#ifdef HAVE_PUTENV
if (*lp_prexfer_exec(i) || *lp_postxfer_exec(i)) {
s = lp_prexfer_exec(i);
p = lp_postxfer_exec(i);
if ((s && *s) || (p && *p)) {
char *modname, *modpath, *hostaddr, *hostname, *username;
int status;
if (asprintf(&modname, "RSYNC_MODULE_NAME=%s", name) < 0
@@ -411,10 +368,15 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
putenv(hostname);
putenv(username);
umask(orig_umask);
/* For post-xfer exec, fork a new process to run the rsync
* daemon while this process waits for the exit status and
* runs the indicated command at that point. */
if (*lp_postxfer_exec(i)) {
if (s && *s) {
status = system(s);
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
rprintf(FLOG, "prexfer-exec failed\n");
io_printf(f_out, "@ERROR: prexfer-exec failed\n");
return -1;
}
}
if (p && *p) {
pid_t pid = fork();
if (pid < 0) {
rsyserr(FLOG, errno, "fork failed");
@@ -422,67 +384,20 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
return -1;
}
if (pid) {
if (asprintf(&p, "RSYNC_PID=%ld", (long)pid) > 0)
putenv(p);
if (wait_process(pid, &status, 0) < 0)
status = -1;
if (asprintf(&p, "RSYNC_RAW_STATUS=%d", status) > 0)
putenv(p);
char *ret1, *ret2;
waitpid(pid, &status, 0);
if (asprintf(&ret1, "RSYNC_RAW_STATUS=%d", status) > 0)
putenv(ret1);
if (WIFEXITED(status))
status = WEXITSTATUS(status);
else
status = -1;
if (asprintf(&p, "RSYNC_EXIT_STATUS=%d", status) > 0)
putenv(p);
system(lp_postxfer_exec(i));
if (asprintf(&ret2, "RSYNC_EXIT_STATUS=%d", status) > 0)
putenv(ret2);
system(p);
_exit(status);
}
}
/* For pre-xfer exec, fork a child process to run the indicated
* command, though it first waits for the parent process to
* send us the user's request via a pipe. */
if (*lp_prexfer_exec(i)) {
int fds[2];
if (asprintf(&p, "RSYNC_PID=%ld", (long)getpid()) > 0)
putenv(p);
if (pipe(fds) < 0 || (pre_exec_pid = fork()) < 0) {
rsyserr(FLOG, errno, "pre-xfer exec preparation failed");
io_printf(f_out, "@ERROR: pre-xfer exec preparation failed\n");
return -1;
}
if (pre_exec_pid == 0) {
char buf[BIGPATHBUFLEN];
int j, len;
close(fds[1]);
set_blocking(fds[0]);
len = read_arg_from_pipe(fds[0], buf, BIGPATHBUFLEN);
if (len <= 0)
_exit(1);
if (asprintf(&p, "RSYNC_REQUEST=%s", buf) > 0)
putenv(p);
for (j = 0; ; j++) {
len = read_arg_from_pipe(fds[0], buf,
BIGPATHBUFLEN);
if (len <= 0) {
if (!len)
break;
_exit(1);
}
if (asprintf(&p, "RSYNC_ARG%d=%s", j, buf) > 0)
putenv(p);
}
close(fds[0]);
close(STDIN_FILENO);
close(STDOUT_FILENO);
status = system(lp_prexfer_exec(i));
if (!WIFEXITED(status))
_exit(1);
_exit(WEXITSTATUS(status));
}
close(fds[0]);
set_blocking(fds[1]);
pre_exec_fd = fds[1];
}
umask(0);
}
#endif
@@ -502,22 +417,22 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
*/
if (chroot(lp_path(i))) {
rsyserr(FLOG, errno, "chroot %s failed",
lp_path(i));
safe_fname(lp_path(i)));
io_printf(f_out, "@ERROR: chroot failed\n");
return -1;
}
if (!push_dir("/", 0)) {
if (!push_dir("/")) {
rsyserr(FLOG, errno, "chdir %s failed\n",
lp_path(i));
safe_fname(lp_path(i)));
io_printf(f_out, "@ERROR: chdir failed\n");
return -1;
}
} else {
if (!push_dir(lp_path(i), 0)) {
if (!push_dir(lp_path(i))) {
rsyserr(FLOG, errno, "chdir %s failed\n",
lp_path(i));
safe_fname(lp_path(i)));
io_printf(f_out, "@ERROR: chdir failed\n");
return -1;
}
@@ -559,16 +474,6 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
am_root = (MY_UID() == 0);
}
if (lp_temp_dir(i) && *lp_temp_dir(i)) {
tmpdir = lp_temp_dir(i);
if (strlen(tmpdir) >= MAXPATHLEN - 10) {
rprintf(FLOG,
"the 'temp dir' value for %s is WAY too long -- ignoring.\n",
name);
tmpdir = NULL;
}
}
io_printf(f_out, "@RSYNCD: OK\n");
maxargs = MAX_ARGS;
@@ -593,37 +498,22 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
if (!(argv[argc] = strdup(p)))
out_of_memory("rsync_module");
switch (start_glob) {
case 0:
argc++;
if (strcmp(line, ".") == 0)
start_glob = 1;
break;
case 1:
if (pre_exec_pid) {
err_msg = finish_pre_exec(pre_exec_pid,
pre_exec_fd, p,
argc, argv);
pre_exec_pid = 0;
if (start_glob) {
if (start_glob == 1) {
request = strdup(p);
start_glob++;
}
request = strdup(p);
start_glob = 2;
/* FALL THROUGH */
default:
if (!err_msg)
glob_expand(name, &argv, &argc, &maxargs);
break;
}
}
glob_expand(name, &argv, &argc, &maxargs);
} else
argc++;
if (pre_exec_pid) {
err_msg = finish_pre_exec(pre_exec_pid, pre_exec_fd, request,
argc, argv);
if (strcmp(line, ".") == 0)
start_glob = 1;
}
verbose = 0; /* future verbosity is controlled by client options */
ret = parse_arguments(&argc, (const char ***) &argv, 0);
quiet = 0; /* Don't let someone try to be tricky. */
argp = argv;
ret = parse_arguments(&argc, (const char ***) &argp, 0);
if (filesfrom_fd == 0)
filesfrom_fd = f_in;
@@ -650,7 +540,7 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
if (protocol_version < 23
&& (protocol_version == 22 || am_sender))
io_start_multiplex_out();
else if (!ret || err_msg) {
else if (!ret) {
/* We have to get I/O multiplexing started so that we can
* get the error back to the client. This means getting
* the protocol setup finished first in later versions. */
@@ -676,11 +566,8 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
io_start_multiplex_out();
}
if (!ret || err_msg) {
if (err_msg)
rprintf(FERROR, err_msg);
else
option_error();
if (!ret) {
option_error();
msleep(400);
exit_cleanup(RERR_UNSUPPORTED);
}
@@ -688,20 +575,7 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
if (lp_timeout(i) && lp_timeout(i) > io_timeout)
set_io_timeout(lp_timeout(i));
/* If we have some incoming/outgoing chmod changes, append them to
* any user-specified changes (making our changes have priority).
* We also get a pointer to just our changes so that a receiver
* process can use them separately if --perms wasn't specified. */
if (am_sender)
p = lp_outgoing_chmod(i);
else
p = lp_incoming_chmod(i);
if (*p && !(daemon_chmod_modes = parse_chmod(p, &chmod_modes))) {
rprintf(FLOG, "Invalid \"%sing chmod\" directive: %s\n",
am_sender ? "outgo" : "incom", p);
}
start_server(f_in, f_out, argc, argv);
start_server(f_in, f_out, argc, argp);
return 0;
}
@@ -727,29 +601,20 @@ static void send_listing(int fd)
here */
int start_daemon(int f_in, int f_out)
{
char line[1024];
char *motd, *addr, *host;
char line[200];
char *motd;
int i;
io_set_sock_fds(f_in, f_out);
/* We must load the config file before calling any function that
* might cause log-file output to occur. This ensures that the
* "log file" param gets honored for the 2 non-forked use-cases
* (when rsync is run by init and run by a remote shell). */
if (!lp_load(config_file, 0))
exit_cleanup(RERR_SYNTAX);
addr = client_addr(f_in);
host = client_name(f_in);
rprintf(FLOG, "connect from %s (%s)\n", host, addr);
log_init();
if (!am_server) {
set_socket_options(f_in, "SO_KEEPALIVE");
if (sockopts)
set_socket_options(f_in, sockopts);
else
set_socket_options(f_in, lp_socket_options());
set_socket_options(f_in, lp_socket_options());
set_nonblocking(f_in);
}
@@ -785,8 +650,6 @@ int start_daemon(int f_in, int f_out)
return -1;
if (!*line || strcmp(line, "#list") == 0) {
rprintf(FLOG, "module-list request from %s (%s)\n",
host, addr);
send_listing(f_out);
return -1;
}
@@ -798,20 +661,18 @@ int start_daemon(int f_in, int f_out)
}
if ((i = lp_number(line)) < 0) {
char *addr = client_addr(f_in);
char *host = client_name(f_in);
rprintf(FLOG, "unknown module '%s' tried from %s (%s)\n",
line, host, addr);
io_printf(f_out, "@ERROR: Unknown module '%s'\n", line);
return -1;
}
#ifdef HAVE_SIGACTION
sigact.sa_flags = SA_NOCLDSTOP;
#endif
SIGACTION(SIGCHLD, remember_children);
return rsync_module(f_in, f_out, i, addr, host);
return rsync_module(f_in, f_out, i);
}
int daemon_main(void)
{
char *pid_file;
@@ -841,7 +702,7 @@ int daemon_main(void)
if (bind_address == NULL && *lp_bind_address())
bind_address = lp_bind_address();
log_init(0);
log_init();
rprintf(FLOG, "rsyncd version %s starting, listening on port %d\n",
RSYNC_VERSION, rsync_port);
@@ -858,7 +719,7 @@ int daemon_main(void)
0666 & ~orig_umask)) == -1) {
cleanup_set_pid(0);
rsyserr(FLOG, errno, "failed to create pid file %s",
pid_file);
safe_fname(pid_file));
exit_cleanup(RERR_FILEIO);
}
snprintf(pidbuf, sizeof pidbuf, "%ld\n", (long)pid);

View File

@@ -1,24 +1,27 @@
/*
/*
Copyright (C) Andrew Tridgell 1996
Copyright (C) Paul Mackerras 1996
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/**
* @file compat.c
*
* Compatibility routines for older rsync protocol versions.
*
* Copyright (C) Andrew Tridgell 1996
* Copyright (C) Paul Mackerras 1996
* Copyright (C) 2004, 2005, 2006 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
**/
#include "rsync.h"
@@ -26,12 +29,12 @@ int remote_protocol = 0;
extern int verbose;
extern int am_server;
extern int am_sender;
extern int inplace;
extern int fuzzy_basis;
extern int read_batch;
extern int checksum_seed;
extern int basis_dir_cnt;
extern int prune_empty_dirs;
extern int protocol_version;
extern char *dest_option;
@@ -75,38 +78,25 @@ void setup_protocol(int f_out,int f_in)
exit_cleanup(RERR_PROTOCOL);
}
if (protocol_version < 29) {
if (fuzzy_basis) {
rprintf(FERROR,
"--fuzzy requires protocol 29 or higher"
" (negotiated %d).\n",
protocol_version);
exit_cleanup(RERR_PROTOCOL);
}
if (fuzzy_basis && protocol_version < 29) {
rprintf(FERROR,
"--fuzzy requires protocol 29 or higher (negotiated %d).\n",
protocol_version);
exit_cleanup(RERR_PROTOCOL);
}
if (basis_dir_cnt && inplace) {
rprintf(FERROR,
"%s with --inplace requires protocol 29 or higher"
" (negotiated %d).\n",
dest_option, protocol_version);
exit_cleanup(RERR_PROTOCOL);
}
if (basis_dir_cnt && inplace && protocol_version < 29) {
rprintf(FERROR,
"%s with --inplace requires protocol 29 or higher (negotiated %d).\n",
dest_option, protocol_version);
exit_cleanup(RERR_PROTOCOL);
}
if (basis_dir_cnt > 1) {
rprintf(FERROR,
"Using more than one %s option requires protocol"
" 29 or higher (negotiated %d).\n",
dest_option, protocol_version);
exit_cleanup(RERR_PROTOCOL);
}
if (prune_empty_dirs) {
rprintf(FERROR,
"--prune-empty-dirs requires protocol 29 or higher"
" (negotiated %d).\n",
protocol_version);
exit_cleanup(RERR_PROTOCOL);
}
if (basis_dir_cnt > 1 && protocol_version < 29) {
rprintf(FERROR,
"Multiple %s options requires protocol 29 or higher (negotiated %d).\n",
dest_option, protocol_version);
exit_cleanup(RERR_PROTOCOL);
}
if (am_server) {

650
config.guess vendored
View File

File diff suppressed because it is too large Load Diff

206
config.sub vendored
View File

@@ -1,10 +1,9 @@
#! /bin/sh
# Configuration validation subroutine script.
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
# Inc.
# 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
timestamp='2006-07-02'
timestamp='2003-08-18'
# This file is (in principle) common to ALL GNU software.
# The presence of a machine in this file suggests that SOME GNU software
@@ -22,15 +21,14 @@ timestamp='2006-07-02'
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
# 02110-1301, USA.
#
# Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# Please send patches to <config-patches@gnu.org>. Submit a context
# diff and a properly formatted ChangeLog entry.
#
@@ -72,7 +70,7 @@ Report bugs and patches to <config-patches@gnu.org>."
version="\
GNU config.sub ($timestamp)
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
@@ -85,11 +83,11 @@ Try \`$me --help' for more information."
while test $# -gt 0 ; do
case $1 in
--time-stamp | --time* | -t )
echo "$timestamp" ; exit ;;
echo "$timestamp" ; exit 0 ;;
--version | -v )
echo "$version" ; exit ;;
echo "$version" ; exit 0 ;;
--help | --h* | -h )
echo "$usage"; exit ;;
echo "$usage"; exit 0 ;;
-- ) # Stop option processing
shift; break ;;
- ) # Use stdin as input.
@@ -101,7 +99,7 @@ while test $# -gt 0 ; do
*local*)
# First pass through any local machine types.
echo $1
exit ;;
exit 0;;
* )
break ;;
@@ -120,9 +118,7 @@ esac
# Here we must recognize all the valid KERNEL-OS combinations.
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
case $maybe_os in
nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
storm-chaos* | os2-emx* | rtmk-nova*)
nto-qnx* | linux-gnu* | linux-dietlibc | kfreebsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*)
os=-$maybe_os
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
;;
@@ -148,7 +144,7 @@ case $os in
-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
-apple | -axis | -knuth | -cray)
-apple | -axis)
os=
basic_machine=$1
;;
@@ -173,10 +169,6 @@ case $os in
-hiux*)
os=-hiuxwe2
;;
-sco6)
os=-sco5v6
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-sco5)
os=-sco3.2v5
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
@@ -193,10 +185,6 @@ case $os in
# Don't forget version if it is 3.2v4 or newer.
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-sco5v6*)
# Don't forget version if it is 3.2v4 or newer.
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-sco*)
os=-sco3.2v2
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
@@ -241,16 +229,14 @@ case $basic_machine in
| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
| am33_2.0 \
| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
| bfin \
| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
| c4x | clipper \
| d10v | d30v | dlx | dsp16xx \
| fr30 | frv \
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
| i370 | i860 | i960 | ia64 \
| ip2k | iq2000 \
| m32c | m32r | m32rle | m68000 | m68k | m88k \
| maxq | mb | microblaze | mcore \
| m32r | m68000 | m68k | m88k | mcore \
| mips | mipsbe | mipseb | mipsel | mipsle \
| mips16 \
| mips64 | mips64el \
@@ -259,7 +245,6 @@ case $basic_machine in
| mips64vr4100 | mips64vr4100el \
| mips64vr4300 | mips64vr4300el \
| mips64vr5000 | mips64vr5000el \
| mips64vr5900 | mips64vr5900el \
| mipsisa32 | mipsisa32el \
| mipsisa32r2 | mipsisa32r2el \
| mipsisa64 | mipsisa64el \
@@ -268,23 +253,20 @@ case $basic_machine in
| mipsisa64sr71k | mipsisa64sr71kel \
| mipstx39 | mipstx39el \
| mn10200 | mn10300 \
| mt \
| msp430 \
| nios | nios2 \
| ns16k | ns32k \
| or32 \
| openrisc | or32 \
| pdp10 | pdp11 | pj | pjl \
| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
| pyramid \
| sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
| sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
| sh64 | sh64le \
| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
| spu | strongarm \
| sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \
| strongarm \
| tahoe | thumb | tic4x | tic80 | tron \
| v850 | v850e \
| we32k \
| x86 | xscale | xscalee[bl] | xstormy16 | xtensa \
| x86 | xscale | xstormy16 | xtensa \
| z8k)
basic_machine=$basic_machine-unknown
;;
@@ -295,9 +277,6 @@ case $basic_machine in
;;
m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
;;
ms1)
basic_machine=mt-unknown
;;
# We use `pc' rather than `unknown'
# because (1) that's what they normally are, and
@@ -317,10 +296,10 @@ case $basic_machine in
| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
| arm-* | armbe-* | armle-* | armeb-* | armv*-* \
| avr-* | avr32-* \
| bfin-* | bs2000-* \
| avr-* \
| bs2000-* \
| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
| clipper-* | craynv-* | cydra-* \
| clipper-* | cydra-* \
| d10v-* | d30v-* | dlx-* \
| elxsi-* \
| f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
@@ -328,9 +307,9 @@ case $basic_machine in
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
| i*86-* | i860-* | i960-* | ia64-* \
| ip2k-* | iq2000-* \
| m32c-* | m32r-* | m32rle-* \
| m32r-* \
| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
| m88110-* | m88k-* | maxq-* | mcore-* \
| m88110-* | m88k-* | mcore-* \
| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
| mips16-* \
| mips64-* | mips64el-* \
@@ -339,7 +318,6 @@ case $basic_machine in
| mips64vr4100-* | mips64vr4100el-* \
| mips64vr4300-* | mips64vr4300el-* \
| mips64vr5000-* | mips64vr5000el-* \
| mips64vr5900-* | mips64vr5900el-* \
| mipsisa32-* | mipsisa32el-* \
| mipsisa32r2-* | mipsisa32r2el-* \
| mipsisa64-* | mipsisa64el-* \
@@ -347,28 +325,24 @@ case $basic_machine in
| mipsisa64sb1-* | mipsisa64sb1el-* \
| mipsisa64sr71k-* | mipsisa64sr71kel-* \
| mipstx39-* | mipstx39el-* \
| mmix-* \
| mt-* \
| msp430-* \
| nios-* | nios2-* \
| none-* | np1-* | ns16k-* | ns32k-* \
| none-* | np1-* | nv1-* | ns16k-* | ns32k-* \
| orion-* \
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
| pyramid-* \
| romp-* | rs6000-* \
| sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
| sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \
| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
| sparclite-* \
| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
| sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \
| sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
| tahoe-* | thumb-* \
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
| tron-* \
| v850-* | v850e-* | vax-* \
| we32k-* \
| x86-* | x86_64-* | xps100-* | xscale-* | xscalee[bl]-* \
| xstormy16-* | xtensa-* \
| x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \
| xtensa-* \
| ymp-* \
| z8k-*)
;;
@@ -388,9 +362,6 @@ case $basic_machine in
basic_machine=a29k-amd
os=-udi
;;
abacus)
basic_machine=abacus-unknown
;;
adobe68k)
basic_machine=m68010-adobe
os=-scout
@@ -408,9 +379,6 @@ case $basic_machine in
amd64)
basic_machine=x86_64-pc
;;
amd64-*)
basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
amdahl)
basic_machine=580-amdahl
os=-sysv
@@ -470,27 +438,12 @@ case $basic_machine in
basic_machine=j90-cray
os=-unicos
;;
craynv)
basic_machine=craynv-cray
os=-unicosmp
;;
cr16c)
basic_machine=cr16c-unknown
os=-elf
;;
crds | unos)
basic_machine=m68k-crds
;;
crisv32 | crisv32-* | etraxfs*)
basic_machine=crisv32-axis
;;
cris | cris-* | etrax*)
basic_machine=cris-axis
;;
crx)
basic_machine=crx-unknown
os=-elf
;;
da30 | da30-*)
basic_machine=m68k-da30
;;
@@ -513,10 +466,6 @@ case $basic_machine in
basic_machine=m88k-motorola
os=-sysv3
;;
djgpp)
basic_machine=i586-pc
os=-msdosdjgpp
;;
dpx20 | dpx20-*)
basic_machine=rs6000-bull
os=-bosx
@@ -695,6 +644,10 @@ case $basic_machine in
mips3*)
basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
;;
mmix*)
basic_machine=mmix-knuth
os=-mmixware
;;
monitor)
basic_machine=m68k-rom68k
os=-coff
@@ -707,9 +660,6 @@ case $basic_machine in
basic_machine=i386-pc
os=-msdos
;;
ms1-*)
basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
;;
mvs)
basic_machine=i370-ibm
os=-mvs
@@ -778,6 +728,10 @@ case $basic_machine in
np1)
basic_machine=np1-gould
;;
nv1)
basic_machine=nv1-cray
os=-unicosmp
;;
nsr-tandem)
basic_machine=nsr-tandem
;;
@@ -785,12 +739,9 @@ case $basic_machine in
basic_machine=hppa1.1-oki
os=-proelf
;;
openrisc | openrisc-*)
or32 | or32-*)
basic_machine=or32-unknown
;;
os400)
basic_machine=powerpc-ibm
os=-os400
os=-coff
;;
OSE68000 | ose68000)
basic_machine=m68000-ericsson
@@ -817,12 +768,6 @@ case $basic_machine in
pc532 | pc532-*)
basic_machine=ns32k-pc532
;;
pc98)
basic_machine=i386-pc
;;
pc98-*)
basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
pentium | p5 | k5 | k6 | nexgen | viac3)
basic_machine=i586-pc
;;
@@ -879,10 +824,6 @@ case $basic_machine in
basic_machine=i586-unknown
os=-pw32
;;
rdos)
basic_machine=i386-pc
os=-rdos
;;
rom68k)
basic_machine=m68k-rom68k
os=-coff
@@ -1022,10 +963,6 @@ case $basic_machine in
tower | tower-32)
basic_machine=m68k-ncr
;;
tpf)
basic_machine=s390x-ibm
os=-tpf
;;
udi29k)
basic_machine=a29k-amd
os=-udi
@@ -1069,10 +1006,6 @@ case $basic_machine in
basic_machine=hppa1.1-winbond
os=-proelf
;;
xbox)
basic_machine=i686-pc
os=-mingw32
;;
xps | xps100)
basic_machine=xps100-honeywell
;;
@@ -1103,9 +1036,6 @@ case $basic_machine in
romp)
basic_machine=romp-ibm
;;
mmix)
basic_machine=mmix-knuth
;;
rs6000)
basic_machine=rs6000-ibm
;;
@@ -1122,10 +1052,13 @@ case $basic_machine in
we32k)
basic_machine=we32k-att
;;
sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele)
sh3 | sh4 | sh[34]eb | sh[1234]le | sh[23]ele)
basic_machine=sh-unknown
;;
sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
sh64)
basic_machine=sh64-unknown
;;
sparc | sparcv9 | sparcv9b)
basic_machine=sparc-sun
;;
cydra)
@@ -1198,23 +1131,19 @@ case $os in
| -aos* \
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
| -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
| -openbsd* | -solidbsd* \
| -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
| -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
| -hiux* | -386bsd* | -netbsd* | -openbsd* | -kfreebsd* | -freebsd* | -riscix* \
| -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
| -chorusos* | -chorusrdb* \
| -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
| -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
| -uxpv* | -beos* | -mpeix* | -udk* \
| -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \
| -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
| -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
| -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
| -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
| -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
| -skyos* | -haiku* | -rdos* | -toppers*)
| -powermax* | -dnix* | -nx6 | -nx7 | -sei*)
# Remember, each alternative MUST END IN *, to match a version number.
;;
-qnx*)
@@ -1232,7 +1161,7 @@ case $os in
os=`echo $os | sed -e 's|nto|nto-qnx|'`
;;
-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
| -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
| -windows* | -osx | -abug | -netware* | -os9* | -beos* \
| -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
;;
-mac*)
@@ -1253,9 +1182,6 @@ case $os in
-opened*)
os=-openedition
;;
-os400*)
os=-os400
;;
-wince*)
os=-wince
;;
@@ -1277,9 +1203,6 @@ case $os in
-atheos*)
os=-atheos
;;
-syllable*)
os=-syllable
;;
-386bsd)
os=-bsd
;;
@@ -1302,9 +1225,6 @@ case $os in
-sinix*)
os=-sysv4
;;
-tpf*)
os=-tpf
;;
-triton*)
os=-sysv3
;;
@@ -1341,9 +1261,6 @@ case $os in
-kaos*)
os=-kaos
;;
-zvmoe)
os=-zvmoe
;;
-none)
;;
*)
@@ -1366,9 +1283,6 @@ else
# system, and we'll never get to this point.
case $basic_machine in
spu-*)
os=-elf
;;
*-acorn)
os=-riscix1.2
;;
@@ -1378,9 +1292,9 @@ case $basic_machine in
arm*-semi)
os=-aout
;;
c4x-* | tic4x-*)
os=-coff
;;
c4x-* | tic4x-*)
os=-coff
;;
# This must come before the *-dec entry.
pdp10-*)
os=-tops20
@@ -1424,15 +1338,9 @@ case $basic_machine in
*-be)
os=-beos
;;
*-haiku)
os=-haiku
;;
*-ibm)
os=-aix
;;
*-knuth)
os=-mmixware
;;
*-wec)
os=-proelf
;;
@@ -1565,15 +1473,9 @@ case $basic_machine in
-mvs* | -opened*)
vendor=ibm
;;
-os400*)
vendor=ibm
;;
-ptx*)
vendor=sequent
;;
-tpf*)
vendor=ibm
;;
-vxsim* | -vxworks* | -windiss*)
vendor=wrs
;;
@@ -1598,7 +1500,7 @@ case $basic_machine in
esac
echo $basic_machine$os
exit
exit 0
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)

View File

@@ -5,7 +5,7 @@ AC_CONFIG_SRCDIR([byteorder.h])
AC_CONFIG_HEADER(config.h)
AC_PREREQ(2.59)
RSYNC_VERSION=2.6.9
RSYNC_VERSION=2.6.6
AC_SUBST(RSYNC_VERSION)
AC_MSG_NOTICE([Configuring rsync $RSYNC_VERSION])
@@ -26,7 +26,8 @@ AC_SUBST(SHELL)
AC_DEFINE([_GNU_SOURCE], 1,
[Define _GNU_SOURCE so that we get all necessary prototypes])
if test x"$ac_cv_prog_cc_stdc" = x"no"; then
if test "x$ac_cv_prog_cc_stdc" = xno
then
AC_MSG_WARN([rsync requires an ANSI C compiler and you don't seem to have one])
fi
@@ -37,10 +38,12 @@ fi
AC_MSG_CHECKING([whether to include debugging symbols])
AC_ARG_ENABLE(debug,
AC_HELP_STRING([--disable-debug],
[turn off debugging symbols and features]))
AC_HELP_STRING([--enable-debug],
[including debugging symbols and features (default yes)]),
[], [])
if test x"$enable_debug" = x"no"; then
if test x"$enable_debug" = x"no"
then
AC_MSG_RESULT(no)
CFLAGS=${CFLAGS-"-O"}
else
@@ -53,8 +56,10 @@ fi
AC_ARG_ENABLE(profile,
AC_HELP_STRING([--enable-profile],
[turn on CPU profiling]))
if test x"$enable_profile" = x"yes"; then
[turn on CPU profiling (default no)],
[], []))
if test x"$enable_profile" = xyes
then
CFLAGS="$CFLAGS -pg"
fi
@@ -62,8 +67,10 @@ fi
# Specifically, this turns on panic_action handling.
AC_ARG_ENABLE(maintainer-mode,
AC_HELP_STRING([--enable-maintainer-mode],
[turn on extra debug features]))
if test x"$enable_maintainer_mode" = x"yes"; then
[turn on extra debug features],
[], []))
if test x"$enable_maintainer_mode" = xyes
then
CFLAGS="$CFLAGS -DMAINTAINER_MODE"
fi
@@ -73,15 +80,16 @@ fi
CFLAGS="$CFLAGS -DHAVE_CONFIG_H"
# If GCC, turn on warnings.
if test x"$GCC" = x"yes"; then
if test x"$GCC" = x"yes"
then
CFLAGS="$CFLAGS -Wall -W"
fi
AC_ARG_WITH(included-popt,
AC_HELP_STRING([--with-included-popt], [use bundled popt library, not from system]))
[ --with-included-popt use bundled popt library, not from system])
AC_ARG_WITH(rsync-path,
AC_HELP_STRING([--with-rsync-path=PATH], [set default --rsync-path to PATH (default: rsync)]),
[ --with-rsync-path=PATH set default --rsync-path to PATH (default: rsync)],
[ RSYNC_PATH="$with_rsync_path" ],
[ RSYNC_PATH="rsync" ])
@@ -116,34 +124,27 @@ if test x$HAVE_REMSH = x1; then
AC_DEFINE(HAVE_REMSH, 1, [Define to 1 if remote shell is remsh, not rsh])
fi
if test x"$with_rsh" != x; then
if test x"$with_rsh" != x
then
RSYNC_RSH="$with_rsh"
else
RSYNC_RSH="ssh"
fi
AC_DEFINE_UNQUOTED(RSYNC_RSH, "$RSYNC_RSH", [default -e command])
AC_ARG_WITH(nobody-group,
AC_HELP_STRING([--with-nobody-group=GROUP],
[set the default unprivileged group (default nobody or nogroup)]),
[ NOBODY_GROUP="$with_nobody_group" ])
if test x"$with_nobody_group" = x; then
AC_MSG_CHECKING([the group for user "nobody"])
if grep '^nobody:' /etc/group >/dev/null 2>&1; then
NOBODY_GROUP=nobody
elif grep '^nogroup:' /etc/group >/dev/null 2>&1; then
NOBODY_GROUP=nogroup
else
NOBODY_GROUP=nobody # test for others?
fi
AC_MSG_RESULT($NOBODY_GROUP)
AC_MSG_CHECKING([the group for user "nobody"])
if grep '^nobody:' /etc/group >/dev/null 2>&1; then
NOBODY_GROUP=nobody
elif grep '^nogroup:' /etc/group >/dev/null 2>&1; then
NOBODY_GROUP=nogroup
else
NOBODY_GROUP=nobody # test for others?
fi
AC_MSG_RESULT($NOBODY_GROUP)
AC_DEFINE_UNQUOTED(NOBODY_USER, "nobody", [unprivileged user--e.g. nobody])
AC_DEFINE_UNQUOTED(NOBODY_GROUP, "$NOBODY_GROUP", [unprivileged group for unprivileged user])
# arrgh. libc in some old debian version screwed up the largefile
# arrgh. libc in the current debian stable screws up the largefile
# stuff, getting byte range locking wrong
AC_CACHE_CHECK([for broken largefile support],rsync_cv_HAVE_BROKEN_LARGEFILE,[
AC_TRY_RUN([
@@ -189,9 +190,21 @@ ipv6lib=none
ipv6trylibc=yes
AC_ARG_ENABLE(ipv6,
AC_HELP_STRING([--disable-ipv6],
[don't even try to use IPv6]))
if test x"$enable_ipv6" != x"no"; then
AC_HELP_STRING([--disable-ipv6], [don't even try to use IPv6]))
dnl Do you want to disable use of locale functions
AH_TEMPLATE([CONFIG_LOCALE],
[Undefine if you don't want locale features. By default this is defined.])
AC_ARG_ENABLE([locale],
AC_HELP_STRING([--disable-locale], [turn off locale features]),
[if test x$enableval = xyes; then
AC_DEFINE(CONFIG_LOCALE)
fi],
AC_DEFINE(CONFIG_LOCALE)
)
if test "x$enable_ipv6" != xno
then
AC_MSG_CHECKING([ipv6 stack type])
for i in inria kame linux-glibc linux-inet6 toshiba v6d zeta; do
case $i in
@@ -280,16 +293,6 @@ yes
AC_SEARCH_LIBS(getaddrinfo, inet6)
fi
dnl Do you want to disable use of locale functions
AC_ARG_ENABLE([locale],
AC_HELP_STRING([--disable-locale],
[turn off locale features]))
AH_TEMPLATE([CONFIG_LOCALE],
[Undefine if you don't want locale features. By default this is defined.])
if test x"$enable_locale" != x"no"; then
AC_DEFINE(CONFIG_LOCALE)
fi
AC_MSG_CHECKING([whether to call shutdown on all sockets])
case $host_os in
*cygwin* ) AC_MSG_RESULT(yes)
@@ -307,34 +310,9 @@ AC_CHECK_HEADERS(sys/fcntl.h sys/select.h fcntl.h sys/time.h sys/unistd.h \
unistd.h utime.h grp.h compat.h sys/param.h ctype.h sys/wait.h \
sys/ioctl.h sys/filio.h string.h stdlib.h sys/socket.h sys/mode.h \
sys/un.h glob.h mcheck.h arpa/inet.h arpa/nameser.h locale.h \
netdb.h malloc.h float.h limits.h iconv.h libcharset.h langinfo.h)
netdb.h malloc.h float.h)
AC_HEADER_MAJOR
AC_CACHE_CHECK([if makedev takes 3 args],rsync_cv_MAKEDEV_TAKES_3_ARGS,[
AC_TRY_RUN([
#include <sys/types.h>
#ifdef MAJOR_IN_MKDEV
#include <sys/mkdev.h>
# if !defined makedev && (defined mkdev || defined _WIN32 || defined __WIN32__)
# define makedev mkdev
# endif
#elif defined MAJOR_IN_SYSMACROS
#include <sys/sysmacros.h>
#endif
int main(void)
{
dev_t dev = makedev(0, 5, 7);
if (major(dev) != 5 || minor(dev) != 7)
exit(1);
return 0;
}
],
rsync_cv_MAKEDEV_TAKES_3_ARGS=yes,rsync_cv_MAKEDEV_TAKES_3_ARGS=no,rsync_cv_MAKEDEV_TAKES_3_ARGS=no)])
if test x"$rsync_cv_MAKEDEV_TAKES_3_ARGS" = x"yes"; then
AC_DEFINE(MAKEDEV_TAKES_3_ARGS, 1, [Define to 1 if makedev() takes 3 args])
fi
AC_CHECK_SIZEOF(int)
AC_CHECK_SIZEOF(long)
AC_CHECK_SIZEOF(long long)
@@ -399,11 +377,7 @@ if test x"$ac_cv_func_connect" = x"no"; then
fi
fi
AC_SEARCH_LIBS(inet_ntop, resolv)
# Solaris and HP-UX weirdness:
# Search for libiconv_open (not iconv_open) to discover if -liconv is needed!
AC_SEARCH_LIBS(libiconv_open, iconv)
AC_CHECK_LIB(resolv, inet_ntop)
dnl AC_MSG_NOTICE([Looking in libraries: $LIBS])
@@ -522,20 +496,19 @@ dnl AC_FUNC_MEMCMP
AC_FUNC_UTIME_NULL
AC_FUNC_ALLOCA
AC_CHECK_FUNCS(waitpid wait4 getcwd strdup chown chmod lchmod mknod mkfifo \
fchmod fstat ftruncate strchr readlink link utime utimes lutimes strftime \
AC_CHECK_FUNCS(waitpid wait4 getcwd strdup strerror chown chmod mknod mkfifo \
fchmod fstat strchr readlink link utime utimes strftime mtrace ftruncate \
memmove lchown vsnprintf snprintf vasprintf asprintf setsid glob strpbrk \
strlcat strlcpy strtol mallinfo getgroups setgroups geteuid getegid \
setlocale setmode open64 lseek64 mkstemp64 mtrace va_copy __va_copy \
strerror putenv iconv_open locale_charset nl_langinfo \
sigaction sigprocmask)
setlocale setmode open64 lseek64 mkstemp64 va_copy __va_copy)
AC_CHECK_FUNCS(getpgrp tcgetpgrp)
if test $ac_cv_func_getpgrp = yes; then
AC_FUNC_GETPGRP
fi
AC_CACHE_CHECK([whether chown() modifies symlinks],rsync_cv_chown_modifies_symlink,[
# Determine whether chown follows symlinks (it should).
AC_CACHE_CHECK([whether chown() dereferences symlinks],rsync_cv_chown_follows_symlink,[
AC_TRY_RUN([
#if HAVE_UNISTD_H
# include <unistd.h>
@@ -546,52 +519,14 @@ AC_CACHE_CHECK([whether chown() modifies symlinks],rsync_cv_chown_modifies_symli
char const *dangling_symlink = "conftest.dangle";
unlink(dangling_symlink);
if (symlink("conftest.no-such", dangling_symlink) < 0) abort();
if (chown(dangling_symlink, getuid(), getgid()) < 0 && errno == ENOENT) exit(1);
exit(0);
if (chown(dangling_symlink, getuid(), getgid()) < 0 && errno == ENOENT) exit(0);
exit(1);
}],
rsync_cv_chown_modifies_symlink=yes,rsync_cv_chown_modifies_symlink=no,rsync_cv_chown_modifies_symlink=no)])
if test $rsync_cv_chown_modifies_symlink = yes; then
rsync_cv_chown_follows_symlink=yes,rsync_cv_chown_follows_symlink=no,rsync_cv_chown_follows_symlink=yes)])
if test $rsync_cv_chown_follows_symlink = no; then
AC_DEFINE(CHOWN_MODIFIES_SYMLINK, 1, [Define to 1 if chown modifies symlinks.])
fi
AC_CACHE_CHECK([whether link() can hard-link symlinks],rsync_cv_can_hardlink_symlink,[
AC_TRY_RUN([
#if HAVE_UNISTD_H
# include <unistd.h>
#endif
#include <stdlib.h>
#include <errno.h>
#define FILENAME "conftest.dangle"
main() {
unlink(FILENAME);
if (symlink("conftest.no-such", FILENAME) < 0) abort();
if (link(FILENAME, FILENAME "2") < 0) exit(1);
exit(0);
}],
rsync_cv_can_hardlink_symlink=yes,rsync_cv_can_hardlink_symlink=no,rsync_cv_can_hardlink_symlink=no)])
if test $rsync_cv_can_hardlink_symlink = yes; then
AC_DEFINE(CAN_HARDLINK_SYMLINK, 1, [Define to 1 if link() can hard-link symlinks.])
fi
AC_CACHE_CHECK([whether link() can hard-link special files],rsync_cv_can_hardlink_special,[
AC_TRY_RUN([
#if HAVE_UNISTD_H
# include <unistd.h>
#endif
#include <stdlib.h>
#include <errno.h>
#define FILENAME "conftest.fifi"
main() {
unlink(FILENAME);
if (mkfifo(FILENAME, 0777) < 0) abort();
if (link(FILENAME, FILENAME "2") < 0) exit(1);
exit(0);
}],
rsync_cv_can_hardlink_special=yes,rsync_cv_can_hardlink_special=no,rsync_cv_can_hardlink_special=no)])
if test $rsync_cv_can_hardlink_special = yes; then
AC_DEFINE(CAN_HARDLINK_SPECIAL, 1, [Define to 1 if link() can hard-link special files.])
fi
AC_CACHE_CHECK([for working socketpair],rsync_cv_HAVE_SOCKETPAIR,[
AC_TRY_RUN([
#include <sys/types.h>
@@ -606,12 +541,14 @@ if test x"$rsync_cv_HAVE_SOCKETPAIR" = x"yes"; then
AC_DEFINE(HAVE_SOCKETPAIR, 1, [Define to 1 if you have the "socketpair" function])
fi
if test x"$with_included_popt" != x"yes"; then
if test x"$with_included_popt" != x"yes"
then
AC_CHECK_LIB(popt, poptGetContext, , [with_included_popt=yes])
fi
AC_MSG_CHECKING([whether to use included libpopt])
if test x"$with_included_popt" = x"yes"; then
if test x"$with_included_popt" = x"yes"
then
AC_MSG_RESULT($srcdir/popt)
BUILD_POPT='$(popt_OBJS)'
CFLAGS="$CFLAGS -I$srcdir/popt"
@@ -720,6 +657,35 @@ if test x"$rsync_cv_HAVE_SECURE_MKSTEMP" = x"yes"; then
fi
AC_CACHE_CHECK([for broken inet_ntoa],rsync_cv_REPLACE_INET_NTOA,[
AC_TRY_RUN([
#include <stdio.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
main() { struct in_addr ip; ip.s_addr = 0x12345678;
if (strcmp(inet_ntoa(ip),"18.52.86.120") &&
strcmp(inet_ntoa(ip),"120.86.52.18")) { exit(1); }
exit(0);}],
rsync_cv_REPLACE_INET_NTOA=no,rsync_cv_REPLACE_INET_NTOA=yes,rsync_cv_REPLACE_INET_NTOA=cross)])
if test x"$rsync_cv_REPLACE_INET_NTOA" = x"yes"; then
AC_DEFINE(REPLACE_INET_NTOA, 1, [Define to 1 if inet_ntoa() needs to be replaced])
fi
AC_CACHE_CHECK([for broken inet_aton],rsync_cv_REPLACE_INET_ATON,[
AC_TRY_RUN([
#include <stdio.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
main() { struct in_addr ip;
if (inet_aton("example", &ip) == 0) exit(0); exit(1);}],
rsync_cv_REPLACE_INET_ATON=no,rsync_cv_REPLACE_INET_ATON=yes,rsync_cv_REPLACE_INET_ATON=cross)])
if test x"$rsync_cv_REPLACE_INET_ATON" = x"yes"; then
AC_DEFINE(REPLACE_INET_ATON, 1, [Define to 1 if inet_aton() needs to be replaced])
fi
AC_CACHE_CHECK([if mknod creates FIFOs],rsync_cv_MKNOD_CREATES_FIFOS,[
AC_TRY_RUN([
#include <stdio.h>
@@ -727,7 +693,7 @@ AC_TRY_RUN([
#include <errno.h>
main() { int rc, ec; char *fn = "fifo-test";
unlink(fn); rc = mknod(fn,S_IFIFO,0600); ec = errno; unlink(fn);
if (rc) {printf("(%d %d) ",rc,ec); return ec;}
if (rc) {printf("%d %d\n",rc,ec); return ec;}
return 0;}],
rsync_cv_MKNOD_CREATES_FIFOS=yes,rsync_cv_MKNOD_CREATES_FIFOS=no,rsync_cv_MKNOD_CREATES_FIFOS=cross)])
if test x"$rsync_cv_MKNOD_CREATES_FIFOS" = x"yes"; then
@@ -741,7 +707,7 @@ AC_TRY_RUN([
#include <errno.h>
main() { int rc, ec; char *fn = "sock-test";
unlink(fn); rc = mknod(fn,S_IFSOCK,0600); ec = errno; unlink(fn);
if (rc) {printf("(%d %d) ",rc,ec); return ec;}
if (rc) {printf("%d %d\n",rc,ec); return ec;}
return 0;}],
rsync_cv_MKNOD_CREATES_SOCKETS=yes,rsync_cv_MKNOD_CREATES_SOCKETS=no,rsync_cv_MKNOD_CREATES_SOCKETS=cross)])
if test x"$rsync_cv_MKNOD_CREATES_SOCKETS" = x"yes"; then

View File

@@ -1,25 +1,25 @@
/*
* Support the max connections option.
*
* Copyright (C) 1998 Andrew Tridgell
*
* 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
/*
Copyright (C) Andrew Tridgell 1998
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* support the max connections option */
#include "rsync.h"
/****************************************************************************
simple routine to do connection counting
****************************************************************************/
@@ -39,7 +39,7 @@ int claim_connection(char *fname,int max_connections)
/* find a free spot */
for (i=0;i<max_connections;i++) {
if (lock_range(fd, i*4, 4)) return 1;
}
}
/* only interested in open failures */
errno = 0;

View File

@@ -1,26 +1,26 @@
/*
* Error codes returned by rsync.
*
* Copyright (C) 1998-2000 Andrew Tridgell
* Copyright (C) 2003, 2005 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
/* -*- c-file-style: "linux"; -*-
Copyright (C) 1998-2000 by Andrew Tridgell
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* If you change these, please also update the string mappings in log.c and
* the EXIT VALUES in rsync.yo. */
/*
* error codes returned by rsync. If you change these, please also update the
* string mappings in log.c and the EXIT VALUES in rsync.yo
*/
#define RERR_OK 0
#define RERR_SYNTAX 1 /* syntax or usage error */
@@ -34,11 +34,8 @@
#define RERR_STREAMIO 12 /* error in rsync protocol data stream */
#define RERR_MESSAGEIO 13 /* errors with program diagnostics */
#define RERR_IPC 14 /* error in IPC code */
#define RERR_CRASHED 15 /* sibling crashed */
#define RERR_TERMINATED 16 /* sibling terminated abnormally */
#define RERR_SIGNAL1 19 /* status returned when sent SIGUSR1 */
#define RERR_SIGNAL 20 /* status returned when sent SIGINT, SIGTERM, SIGHUP */
#define RERR_SIGNAL 20 /* status returned when sent SIGUSR1, SIGINT */
#define RERR_WAITCHILD 21 /* some error returned by waitpid() */
#define RERR_MALLOC 22 /* error allocating core memory buffers */
#define RERR_PARTIAL 23 /* partial transfer */

244
exclude.c
View File

@@ -1,10 +1,8 @@
/*
* The filter include/exclude routines.
/* -*- c-file-style: "linux" -*-
*
* Copyright (C) 1996-2001 Andrew Tridgell <tridge@samba.org>
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2002 Martin Pool
* Copyright (C) 2003, 2004, 2005, 2006 Wayne Davison
* Copyright (C) 1996-2001 by Andrew Tridgell <tridge@samba.org>
* Copyright (C) 1996 by Paul Mackerras
* Copyright (C) 2002 by Martin Pool
*
* 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
@@ -16,11 +14,16 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* a lot of this stuff was originally derived from GNU tar, although
it has now changed so much that it is hard to tell :) */
/* include/exclude cluestick added by Martin Pool <mbp@samba.org> */
#include "rsync.h"
extern int verbose;
@@ -31,7 +34,6 @@ extern int list_only;
extern int recurse;
extern int io_error;
extern int local_server;
extern int prune_empty_dirs;
extern int delete_mode;
extern int delete_excluded;
extern int cvs_exclude;
@@ -44,8 +46,8 @@ extern unsigned int curr_dir_len;
extern unsigned int module_dirlen;
struct filter_list_struct filter_list = { 0, 0, "" };
struct filter_list_struct cvs_filter_list = { 0, 0, " [global CVS]" };
struct filter_list_struct server_filter_list = { 0, 0, " [daemon]" };
struct filter_list_struct cvs_filter_list = { 0, 0, " [cvsignore]" };
struct filter_list_struct server_filter_list = { 0, 0, " [server]" };
/* Need room enough for ":MODS " prefix plus some room to grow. */
#define MAX_RULE_PREFIX (16)
@@ -131,9 +133,9 @@ static void add_rule(struct filter_list_struct *listp, const char *pat,
listp->debug_type);
}
/* These flags also indicate that we're reading a list that
/* This flag also indicates that we're reading a list that
* needs to be filtered now, not post-filtered later. */
if (xflags & (XFLG_ANCHORED2ABS|XFLG_ABS_IF_SLASH)) {
if (xflags & XFLG_ANCHORED2ABS) {
uint32 mf = mflags & (MATCHFLG_RECEIVER_SIDE|MATCHFLG_SENDER_SIDE);
if (am_sender) {
if (mf == MATCHFLG_RECEIVER_SIDE)
@@ -148,14 +150,10 @@ static void add_rule(struct filter_list_struct *listp, const char *pat,
out_of_memory("add_rule");
memset(ret, 0, sizeof ret[0]);
if (!(mflags & (MATCHFLG_ABS_PATH | MATCHFLG_MERGE_FILE))
&& ((xflags & (XFLG_ANCHORED2ABS|XFLG_ABS_IF_SLASH) && *pat == '/')
|| (xflags & XFLG_ABS_IF_SLASH && strchr(pat, '/') != NULL))) {
if (xflags & XFLG_ANCHORED2ABS && *pat == '/'
&& !(mflags & (MATCHFLG_ABS_PATH | MATCHFLG_MERGE_FILE))) {
mflags |= MATCHFLG_ABS_PATH;
if (*pat == '/')
ex_len = dirbuf_len - module_dirlen - 1;
else
ex_len = 0;
ex_len = dirbuf_len - module_dirlen - 1;
} else
ex_len = 0;
if (!(ret->pattern = new_array(char, ex_len + pat_len + 1)))
@@ -172,12 +170,6 @@ static void add_rule(struct filter_list_struct *listp, const char *pat,
/* If the pattern starts with **, note that. */
if (cp == ret->pattern)
mflags |= MATCHFLG_WILD2_PREFIX;
/* If the pattern ends with ***, note that. */
if (pat_len >= 3
&& ret->pattern[pat_len-3] == '*'
&& ret->pattern[pat_len-2] == '*'
&& ret->pattern[pat_len-1] == '*')
mflags |= MATCHFLG_WILD3_SUFFIX;
}
}
@@ -298,28 +290,30 @@ static char *parse_merge_name(const char *merge_file, unsigned int *len_ptr,
strlcpy(to, merge_file, *len_ptr + 1);
merge_file = to;
}
if (!sanitize_path(fn, merge_file, r, dirbuf_depth, NULL)) {
if (!sanitize_path(fn, merge_file, r, dirbuf_depth)) {
rprintf(FERROR, "merge-file name overflows: %s\n",
merge_file);
safe_fname(merge_file));
return NULL;
}
fn_len = strlen(fn);
} else {
strlcpy(fn, merge_file, len_ptr ? *len_ptr + 1 : MAXPATHLEN);
fn_len = clean_fname(fn, 1);
clean_fname(fn, 1);
}
fn_len = strlen(fn);
if (fn == buf)
goto done;
/* If the name isn't in buf yet, it's wasn't absolute. */
if (fn != buf) {
if (dirbuf_len + fn_len >= MAXPATHLEN) {
rprintf(FERROR, "merge-file name overflows: %s\n", fn);
return NULL;
}
memcpy(buf, dirbuf + prefix_skip, dirbuf_len - prefix_skip);
memcpy(buf + dirbuf_len - prefix_skip, fn, fn_len + 1);
fn_len = clean_fname(buf, 1);
if (dirbuf_len + fn_len >= MAXPATHLEN) {
rprintf(FERROR, "merge-file name overflows: %s\n",
safe_fname(fn));
return NULL;
}
memcpy(buf, dirbuf + prefix_skip, dirbuf_len - prefix_skip);
memcpy(buf + dirbuf_len - prefix_skip, fn, fn_len + 1);
fn_len = clean_fname(buf, 1);
done:
if (len_ptr)
*len_ptr = fn_len;
return buf;
@@ -494,69 +488,71 @@ void pop_local_filters(void *mem)
static int rule_matches(char *name, struct filter_struct *ex, int name_is_dir)
{
int slash_handling, str_cnt = 0, anchored_match = 0;
char *p, full_name[MAXPATHLEN];
int match_start = 0;
int ret_match = ex->match_flags & MATCHFLG_NEGATE ? 0 : 1;
char *p, *pattern = ex->pattern;
const char *strings[16]; /* more than enough */
char *pattern = ex->pattern;
if (*name == '/')
name++;
if (!*name)
return 0;
/* If the pattern does not have any slashes AND it does not have
* a "**" (which could match a slash), then we just match the
* name portion of the path. */
if (!ex->u.slash_cnt && !(ex->match_flags & MATCHFLG_WILD2)) {
/* If the pattern does not have any slashes AND it does
* not have a "**" (which could match a slash), then we
* just match the name portion of the path. */
if ((p = strrchr(name,'/')) != NULL)
name = p+1;
} else if (ex->match_flags & MATCHFLG_ABS_PATH && *name != '/'
&& curr_dir_len > module_dirlen + 1) {
/* If we're matching against an absolute-path pattern,
* we need to prepend our full path info. */
strings[str_cnt++] = curr_dir + module_dirlen + 1;
strings[str_cnt++] = "/";
} else if (ex->match_flags & MATCHFLG_WILD2_PREFIX && *name != '/') {
/* Allow "**"+"/" to match at the start of the string. */
strings[str_cnt++] = "/";
}
strings[str_cnt++] = name;
if (name_is_dir) {
/* Allow a trailing "/"+"***" to match the directory. */
if (ex->match_flags & MATCHFLG_WILD3_SUFFIX)
strings[str_cnt++] = "/";
} else if (ex->match_flags & MATCHFLG_DIRECTORY)
else if (ex->match_flags & MATCHFLG_ABS_PATH && *name != '/'
&& curr_dir_len > module_dirlen + 1) {
pathjoin(full_name, sizeof full_name,
curr_dir + module_dirlen + 1, name);
name = full_name;
}
if (ex->match_flags & MATCHFLG_DIRECTORY && !name_is_dir)
return !ret_match;
strings[str_cnt] = NULL;
if (*pattern == '/') {
anchored_match = 1;
match_start = 1;
pattern++;
}
if (!anchored_match && ex->u.slash_cnt
&& !(ex->match_flags & MATCHFLG_WILD2)) {
/* A non-anchored match with an infix slash and no "**"
* needs to match the last slash_cnt+1 name elements. */
slash_handling = ex->u.slash_cnt + 1;
} else if (!anchored_match && !(ex->match_flags & MATCHFLG_WILD2_PREFIX)
&& ex->match_flags & MATCHFLG_WILD2) {
/* A non-anchored match with an infix or trailing "**" (but not
* a prefixed "**") needs to try matching after every slash. */
slash_handling = -1;
} else {
/* The pattern matches only at the start of the path or name. */
slash_handling = 0;
if (*name == '/')
name++;
}
if (ex->match_flags & MATCHFLG_WILD) {
if (wildmatch_array(pattern, strings, slash_handling))
/* A non-anchored match with an infix slash and no "**"
* needs to match the last slash_cnt+1 name elements. */
if (!match_start && ex->u.slash_cnt
&& !(ex->match_flags & MATCHFLG_WILD2)) {
int cnt = ex->u.slash_cnt + 1;
for (p = name + strlen(name) - 1; p >= name; p--) {
if (*p == '/' && !--cnt)
break;
}
name = p+1;
}
if (wildmatch(pattern, name))
return ret_match;
} else if (str_cnt > 1) {
if (litmatch_array(pattern, strings, slash_handling))
return ret_match;
} else if (anchored_match) {
if (strcmp(name, pattern) == 0)
if (ex->match_flags & MATCHFLG_WILD2_PREFIX) {
/* If the **-prefixed pattern has a '/' as the next
* character, then try to match the rest of the
* pattern at the root. */
if (pattern[2] == '/' && wildmatch(pattern+3, name))
return ret_match;
}
else if (!match_start && ex->match_flags & MATCHFLG_WILD2) {
/* A non-anchored match with an infix or trailing "**"
* (but not a prefixed "**") needs to try matching
* after every slash. */
while ((name = strchr(name, '/')) != NULL) {
name++;
if (wildmatch(pattern, name))
return ret_match;
}
}
} else if (match_start) {
if (strcmp(name,pattern) == 0)
return ret_match;
} else {
int l1 = strlen(name);
@@ -581,13 +577,11 @@ static void report_filter_result(char const *name,
* case we add it back in here. */
if (verbose >= 2) {
static char *actions[2][2]
= { {"show", "hid"}, {"risk", "protect"} };
const char *w = who_am_i();
rprintf(FINFO, "[%s] %sing %s %s because of pattern %s%s%s\n",
w, actions[*w!='s'][!(ent->match_flags&MATCHFLG_INCLUDE)],
name_is_dir ? "directory" : "file", name, ent->pattern,
ent->match_flags & MATCHFLG_DIRECTORY ? "/" : "", type);
rprintf(FINFO, "[%s] %scluding %s %s because of pattern %s%s%s\n",
who_am_i(),
ent->match_flags & MATCHFLG_INCLUDE ? "in" : "ex",
name_is_dir ? "directory" : "file", name, ent->pattern,
ent->match_flags & MATCHFLG_DIRECTORY ? "/" : "", type);
}
}
@@ -833,8 +827,7 @@ static const char *parse_rule_tok(const char *p, uint32 mflags, int xflags,
len = strlen((char*)s);
if (new_mflags & MATCHFLG_CLEAR_LIST) {
if (!(mflags & MATCHFLG_NO_PREFIXES)
&& !(xflags & XFLG_OLD_PREFIXES) && len) {
if (!(xflags & XFLG_OLD_PREFIXES) && len) {
rprintf(FERROR,
"'!' rule has trailing characters: %s\n", p);
exit_cleanup(RERR_SYNTAX);
@@ -846,22 +839,13 @@ static const char *parse_rule_tok(const char *p, uint32 mflags, int xflags,
exit_cleanup(RERR_SYNTAX);
}
/* --delete-excluded turns an un-modified include/exclude into a
* sender-side rule. We also affect per-dir merge files that take
* no prefixes as a simple optimization. */
if (delete_excluded
&& !(new_mflags & (MATCHFLG_RECEIVER_SIDE|MATCHFLG_SENDER_SIDE))
&& (!(new_mflags & MATCHFLG_PERDIR_MERGE)
|| new_mflags & MATCHFLG_NO_PREFIXES))
new_mflags |= MATCHFLG_SENDER_SIDE;
*len_ptr = len;
*mflags_ptr = new_mflags;
return (const char *)s;
}
static char default_cvsignore[] =
static char default_cvsignore[] =
/* These default ignored items come from the CVS manual. */
"RCS SCCS CVS CVS.adm RCSLOG cvslog.* tags TAGS"
" .make.state .nse_depinfo *~ #* .#* ,* _$* *$"
@@ -869,7 +853,7 @@ static char default_cvsignore[] =
" *.a *.olb *.o *.obj *.so *.exe"
" *.Z *.elc *.ln core"
/* The rest we added to suit ourself. */
" .svn/ .bzr/";
" .svn/";
static void get_cvs_excludes(uint32 mflags)
{
@@ -906,14 +890,12 @@ void parse_rule(struct filter_list_struct *listp, const char *pattern,
&pat_len, &new_mflags);
if (!cp)
break;
pattern = cp + pat_len;
if (pat_len >= MAXPATHLEN) {
rprintf(FERROR, "discarding over-long filter: %.*s\n",
(int)pat_len, cp);
rprintf(FERROR, "discarding over-long filter: %s\n",
cp);
continue;
}
pattern = cp + pat_len;
if (new_mflags & MATCHFLG_CLEAR_LIST) {
if (verbose > 2) {
@@ -933,9 +915,11 @@ void parse_rule(struct filter_list_struct *listp, const char *pattern,
}
len = pat_len;
if (new_mflags & MATCHFLG_EXCLUDE_SELF) {
const char *name = cp + len;
while (name > cp && name[-1] != '/') name--;
len -= name - cp;
const char *name = strrchr(cp, '/');
if (name)
len -= ++name - cp;
else
name = cp;
add_rule(listp, name, len, 0, 0);
new_mflags &= ~MATCHFLG_EXCLUDE_SELF;
len = pat_len;
@@ -970,7 +954,7 @@ void parse_filter_file(struct filter_list_struct *listp, const char *fname,
uint32 mflags, int xflags)
{
FILE *fp;
char line[BIGPATHBUFLEN];
char line[MAXPATHLEN+MAX_RULE_PREFIX+1]; /* +1 for trailing slash. */
char *eob = line + sizeof line - 1;
int word_split = mflags & MATCHFLG_WORD_SPLIT;
@@ -992,7 +976,7 @@ void parse_filter_file(struct filter_list_struct *listp, const char *fname,
if (verbose > 2) {
rprintf(FINFO, "[%s] parse_filter_file(%s,%x,%x)%s\n",
who_am_i(), fname, mflags, xflags,
who_am_i(), safe_fname(fname), mflags, xflags,
fp ? "" : " [not found]");
}
@@ -1001,7 +985,7 @@ void parse_filter_file(struct filter_list_struct *listp, const char *fname,
rsyserr(FERROR, errno,
"failed to open %sclude file %s",
mflags & MATCHFLG_INCLUDE ? "in" : "ex",
fname);
safe_fname(fname));
exit_cleanup(RERR_FILEIO);
}
return;
@@ -1013,10 +997,8 @@ void parse_filter_file(struct filter_list_struct *listp, const char *fname,
int ch, overflow = 0;
while (1) {
if ((ch = getc(fp)) == EOF) {
if (ferror(fp) && errno == EINTR) {
clearerr(fp);
if (ferror(fp) && errno == EINTR)
continue;
}
break;
}
if (word_split && isspace(ch))
@@ -1106,20 +1088,11 @@ static void send_rules(int f_out, struct filter_list_struct *flp)
int elide = 0;
char *p;
/* Note we need to check delete_excluded here in addition to
* the code in parse_rule_tok() because some rules may have
* been added before we found the --delete-excluded option.
* We must also elide any CVS merge-file rules to avoid a
* backward compatibility problem, and we elide any no-prefix
* merge files as an optimization (since they can only have
* include/exclude rules). */
if (ent->match_flags & MATCHFLG_SENDER_SIDE)
elide = am_sender ? 1 : -1;
if (ent->match_flags & MATCHFLG_RECEIVER_SIDE)
elide = elide ? 0 : am_sender ? -1 : 1;
else if (delete_excluded && !elide
&& (!(ent->match_flags & MATCHFLG_PERDIR_MERGE)
|| ent->match_flags & MATCHFLG_NO_PREFIXES))
else if (delete_excluded && !elide)
elide = am_sender ? 1 : -1;
if (elide < 0) {
if (prev)
@@ -1162,8 +1135,8 @@ static void send_rules(int f_out, struct filter_list_struct *flp)
/* This is only called by the client. */
void send_filter_list(int f_out)
{
int receiver_wants_list = prune_empty_dirs
|| (delete_mode && (!delete_excluded || protocol_version >= 29));
int receiver_wants_list = delete_mode
&& (!delete_excluded || protocol_version >= 29);
if (local_server || (am_sender && !receiver_wants_list))
f_out = -1;
@@ -1194,11 +1167,10 @@ void send_filter_list(int f_out)
/* This is only called by the server. */
void recv_filter_list(int f_in)
{
char line[BIGPATHBUFLEN];
char line[MAXPATHLEN+MAX_RULE_PREFIX+1]; /* +1 for trailing slash. */
int xflags = protocol_version >= 29 ? 0 : XFLG_OLD_PREFIXES;
int receiver_wants_list = prune_empty_dirs
|| (delete_mode
&& (!delete_excluded || protocol_version >= 29));
int receiver_wants_list = delete_mode
&& (!delete_excluded || protocol_version >= 29);
unsigned int len;
if (!local_server && (am_sender || receiver_wants_list)) {

View File

@@ -1,31 +1,27 @@
/*
* File IO utilities used in rsync.
*
* Copyright (C) 1998 Andrew Tridgell
* Copyright (C) 2002 Martin Pool
* Copyright (C) 2004, 2005, 2006 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
Copyright (C) Andrew Tridgell 1998
Copyright (C) 2002 by Martin Pool
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
File IO utilities used in rsync
*/
#include "rsync.h"
#ifndef ENODATA
#define ENODATA EAGAIN
#endif
extern int sparse_files;
static char last_byte;
@@ -221,35 +217,34 @@ char *map_ptr(struct map_struct *map, OFF_T offset, int32 len)
rprintf(FERROR, "invalid read_size of %ld in map_ptr\n",
(long)read_size);
exit_cleanup(RERR_FILEIO);
}
if (map->p_fd_offset != read_start) {
OFF_T ret = do_lseek(map->fd, read_start, SEEK_SET);
if (ret != read_start) {
rsyserr(FERROR, errno, "lseek returned %.0f, not %.0f",
(double)ret, (double)read_start);
exit_cleanup(RERR_FILEIO);
} else {
if (map->p_fd_offset != read_start) {
OFF_T ret = do_lseek(map->fd, read_start, SEEK_SET);
if (ret != read_start) {
rsyserr(FERROR, errno,
"lseek returned %.0f, not %.0f",
(double)ret, (double)read_start);
exit_cleanup(RERR_FILEIO);
}
map->p_fd_offset = read_start;
}
map->p_fd_offset = read_start;
}
map->p_offset = window_start;
map->p_len = window_size;
while (read_size > 0) {
nread = read(map->fd, map->p + read_offset, read_size);
if (nread <= 0) {
if (!map->status)
map->status = nread ? errno : ENODATA;
/* The best we can do is zero the buffer -- the file
* has changed mid transfer! */
memset(map->p + read_offset, 0, read_size);
break;
if ((nread=read(map->fd,map->p + read_offset,read_size)) != read_size) {
if (nread < 0) {
nread = 0;
if (!map->status)
map->status = errno;
}
/* the best we can do is zero the buffer - the file
has changed mid transfer! */
memset(map->p+read_offset+nread, 0, read_size - nread);
}
map->p_fd_offset += nread;
read_offset += nread;
read_size -= nread;
}
map->p_offset = window_start;
map->p_len = window_size;
return map->p;
}

745
flist.c
View File

File diff suppressed because it is too large Load Diff

View File

File diff suppressed because it is too large Load Diff

View File

@@ -1,25 +1,29 @@
/*
* Print out the gids of all groups for the current user. This is like
* `id -G` on Linux, but it's too hard to find a portable equivalent.
*
* Copyright (C) 2002 Martin Pool
* Copyright (C) 2003, 2004 Wayne Davison
*
* Copyright (C) 2002 by Martin Pool
*
* 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/**
* @file getgroups.c
*
* Print out the gids of all groups for the current user. This is
* like `id -G` on Linux, but it's too hard to find a portable
* equivalent.
**/
#include "rsync.h"
int
@@ -59,6 +63,6 @@ main(UNUSED(int argc), UNUSED(char *argv[]))
if (!gid_in_list)
printf("%lu", (unsigned long)gid);
printf("\n");
return 0;
}

123
hlink.c
View File

@@ -1,35 +1,29 @@
/*
* Routines to support hard-linking.
*
* Copyright (C) 1996 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2002 Martin Pool <mbp@samba.org>
* Copyright (C) 2004, 2005, 2006 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
Copyright (C) Andrew Tridgell 1996
Copyright (C) Paul Mackerras 1996
Copyright (C) 2002 by Martin Pool <mbp@samba.org>
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "rsync.h"
extern int dry_run;
extern int verbose;
extern int do_xfers;
extern int link_dest;
extern int make_backups;
extern int remove_source_files;
extern int stdout_format_has_i;
extern char *basis_dir[];
extern int log_format_has_i;
extern struct file_list *the_file_list;
#ifdef SUPPORT_HARD_LINKS
@@ -55,14 +49,14 @@ static int hlink_compare(int *int1, int *int2)
return f_name_cmp(f1, f2);
}
static int32 *hlink_list;
static int32 hlink_count;
static int *hlink_list;
static int hlink_count;
/* Analyze the data in the hlink_list[], remove items that aren't multiply
* linked, and replace the dev+inode data with the hlindex+next linked list. */
static void link_idev_data(void)
{
int32 cur, from, to, start;
int cur, from, to, start;
alloc_pool_t hlink_pool;
alloc_pool_t idev_pool = the_file_list->hlink_pool;
@@ -83,7 +77,6 @@ static void link_idev_data(void)
FPTR(cur)->F_HLINDEX = to;
FPTR(cur)->F_NEXT = hlink_list[++from];
FPTR(cur)->link_u.links->link_dest_used = 0;
}
pool_free(idev_pool, 0, FPTR(cur)->link_u.idev);
if (from > start) {
@@ -95,7 +88,6 @@ static void link_idev_data(void)
FPTR(cur)->F_HLINDEX = to;
FPTR(cur)->F_NEXT = head;
FPTR(cur)->flags |= FLAG_HLINK_EOL;
FPTR(cur)->link_u.links->link_dest_used = 0;
hlink_list[to++] = head;
} else
FPTR(cur)->link_u.links = NULL;
@@ -108,7 +100,7 @@ static void link_idev_data(void)
hlink_pool = NULL;
} else {
hlink_count = to;
hlink_list = realloc_array(hlink_list, int32, hlink_count);
hlink_list = realloc_array(hlink_list, int, hlink_count);
if (!hlink_list)
out_of_memory("init_hard_links");
}
@@ -125,7 +117,7 @@ void init_hard_links(void)
if (hlink_list)
free(hlink_list);
if (!(hlink_list = new_array(int32, the_file_list->count)))
if (!(hlink_list = new_array(int, the_file_list->count)))
out_of_memory("init_hard_links");
hlink_count = 0;
@@ -181,64 +173,28 @@ int hard_link_check(struct file_struct *file, int ndx, char *fname,
{
#ifdef SUPPORT_HARD_LINKS
int head;
if (!file->link_u.links)
return 0;
if (skip && !(file->flags & FLAG_HLINK_EOL))
head = hlink_list[file->F_HLINDEX] = file->F_NEXT;
else
head = hlink_list[file->F_HLINDEX];
if (ndx != head) {
struct file_struct *head_file = FPTR(head);
if (!stdout_format_has_i && verbose > 1) {
if (!log_format_has_i && verbose > 1) {
rprintf(FINFO, "\"%s\" is a hard link\n",
f_name(file, NULL));
safe_fname(f_name(file)));
}
if (head_file->F_HLINDEX == FINISHED_LINK) {
STRUCT_STAT st2, st3;
char toname[MAXPATHLEN];
int ldu = head_file->link_u.links->link_dest_used;
if (ldu) {
pathjoin(toname, MAXPATHLEN, basis_dir[ldu-1],
f_name(head_file, NULL));
} else
f_name(head_file, toname);
STRUCT_STAT st2;
char *toname = f_name(head_file);
if (link_stat(toname, &st2, 0) < 0) {
rsyserr(FERROR, errno, "stat %s failed",
full_fname(toname));
return -1;
}
if (statret < 0 && basis_dir[0] != NULL) {
char cmpbuf[MAXPATHLEN];
int j = 0;
do {
pathjoin(cmpbuf, MAXPATHLEN, basis_dir[j], fname);
if (link_stat(cmpbuf, &st3, 0) < 0)
continue;
if (link_dest) {
if (st2.st_dev != st3.st_dev
|| st2.st_ino != st3.st_ino)
continue;
statret = 1;
st = &st3;
if (verbose < 2 || !stdout_format_has_i) {
itemizing = 0;
code = FNONE;
}
break;
}
if (!unchanged_file(cmpbuf, file, &st3))
continue;
statret = 1;
st = &st3;
if (unchanged_attrs(file, &st3))
break;
} while (basis_dir[++j] != NULL);
}
maybe_hard_link(file, ndx, fname, statret, st,
toname, &st2, itemizing, code);
if (remove_source_files == 1 && do_xfers) {
char numbuf[4];
SIVAL(numbuf, 0, ndx);
send_msg(MSG_SUCCESS, numbuf, 4);
}
file->F_HLINDEX = FINISHED_LINK;
} else
file->F_HLINDEX = SKIPPED_LINK;
@@ -261,7 +217,7 @@ int hard_link_one(struct file_struct *file, int ndx, char *fname,
} else
code = FERROR;
rsyserr(code, errno, "link %s => %s failed",
full_fname(fname), toname);
full_fname(fname), safe_fname(toname));
return -1;
}
@@ -270,8 +226,10 @@ int hard_link_one(struct file_struct *file, int ndx, char *fname,
ITEM_LOCAL_CHANGE | ITEM_XNAME_FOLLOWS, 0,
terse ? "" : toname);
}
if (code != FNONE && verbose && !terse)
rprintf(code, "%s => %s\n", fname, toname);
if (code && verbose && !terse) {
rprintf(code, "%s => %s\n",
safe_fname(fname), safe_fname(toname));
}
return 0;
}
#endif
@@ -287,7 +245,7 @@ void hard_link_cluster(struct file_struct *file, int master, int itemizing,
int statret, ndx = master;
file->F_HLINDEX = FINISHED_LINK;
if (link_stat(f_name(file, hlink1), &st1, 0) < 0)
if (link_stat(f_name_to(file, hlink1), &st1, 0) < 0)
return;
if (!(file->flags & FLAG_HLINK_TOL)) {
while (!(file->flags & FLAG_HLINK_EOL)) {
@@ -300,15 +258,10 @@ void hard_link_cluster(struct file_struct *file, int master, int itemizing,
file = FPTR(ndx);
if (file->F_HLINDEX != SKIPPED_LINK)
continue;
hlink2 = f_name(file, NULL);
hlink2 = f_name(file);
statret = link_stat(hlink2, &st2, 0);
maybe_hard_link(file, ndx, hlink2, statret, &st2,
hlink1, &st1, itemizing, code);
if (remove_source_files == 1 && do_xfers) {
char numbuf[4];
SIVAL(numbuf, 0, ndx);
send_msg(MSG_SUCCESS, numbuf, 4);
}
file->F_HLINDEX = FINISHED_LINK;
} while (!(file->flags & FLAG_HLINK_EOL));
#endif

390
io.c
View File

@@ -1,10 +1,8 @@
/*
* Socket and pipe I/O utilities used in rsync.
/* -*- c-file-style: "linux" -*-
*
* Copyright (C) 1996-2001 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
* Copyright (C) 2003, 2004, 2005, 2006 Wayne Davison
* Copyright (C) 1996-2001 by Andrew Tridgell
* Copyright (C) Paul Mackerras 1996
* Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
*
* 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
@@ -16,17 +14,25 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* Rsync provides its own multiplexing system, which is used to send
* stderr and stdout over a single socket.
/**
* @file io.c
*
* Socket and pipe I/O utilities used in rsync.
*
* rsync provides its own multiplexing system, which is used to send
* stderr and stdout over a single socket. We need this because
* stdout normally carries the binary data stream, and stderr all our
* error messages.
*
* For historical reasons this is off during the start of the
* connection, but it's switched on quite early using
* io_start_multiplex_out() and io_start_multiplex_in(). */
* io_start_multiplex_out() and io_start_multiplex_in().
**/
#include "rsync.h"
@@ -35,6 +41,7 @@
extern int bwlimit;
extern size_t bwlimit_writemax;
extern int verbose;
extern int io_timeout;
extern int allowed_lull;
extern int am_server;
@@ -46,7 +53,7 @@ extern int read_batch;
extern int csum_length;
extern int checksum_seed;
extern int protocol_version;
extern int remove_source_files;
extern int remove_sent_files;
extern int preserve_hard_links;
extern char *filesfrom_host;
extern struct stats stats;
@@ -57,6 +64,22 @@ int ignore_timeout = 0;
int batch_fd = -1;
int batch_gen_fd = -1;
/**
* The connection might be dropped at some point; perhaps because the
* remote instance crashed. Just giving the offset on the stream is
* not very helpful. So instead we try to make io_phase_name point to
* something useful.
*
* For buffered/multiplexed I/O these names will be somewhat
* approximate; perhaps for ease of support we would rather make the
* buffer always flush when a single application-level I/O finishes.
*
* @todo Perhaps we want some simple stack functionality, but there's
* no need to overdo it.
**/
const char *io_write_phase = phase_unknown;
const char *io_read_phase = phase_unknown;
/* Ignore an EOF error if non-zero. See whine_about_eof(). */
int kluge_around_eof = 0;
@@ -80,10 +103,8 @@ static char io_filesfrom_buf[2048];
static char *io_filesfrom_bp;
static char io_filesfrom_lastchar;
static int io_filesfrom_buflen;
static int defer_forwarding_messages = 0;
static size_t contiguous_write_len = 0;
static int select_timeout = SELECT_TIMEOUT;
static int active_filecnt = 0;
static OFF_T active_bytecnt = 0;
static void read_loop(int fd, char *buf, size_t len);
@@ -98,17 +119,14 @@ struct flist_ndx_list {
static struct flist_ndx_list redo_list, hlink_list;
struct msg_list_item {
struct msg_list_item *next;
int len;
char buf[1];
};
struct msg_list {
struct msg_list_item *head, *tail;
struct msg_list *next;
char *buf;
int len;
};
static struct msg_list msg2genr, msg2sndr;
static struct msg_list *msg_list_head;
static struct msg_list *msg_list_tail;
static void flist_ndx_push(struct flist_ndx_list *lp, int ndx)
{
@@ -204,22 +222,33 @@ void set_msg_fd_out(int fd)
}
/* Add a message to the pending MSG_* list. */
static void msg_list_add(struct msg_list *lst, int code, char *buf, int len)
static void msg_list_add(int code, char *buf, int len)
{
struct msg_list_item *m;
int sz = len + 4 + sizeof m[0] - 1;
struct msg_list *ml;
if (!(m = (struct msg_list_item *)new_array(char, sz)))
if (!(ml = new(struct msg_list)))
out_of_memory("msg_list_add");
m->next = NULL;
m->len = len + 4;
SIVAL(m->buf, 0, ((code+MPLEX_BASE)<<24) | len);
memcpy(m->buf + 4, buf, len);
if (lst->tail)
lst->tail->next = m;
ml->next = NULL;
if (!(ml->buf = new_array(char, len+4)))
out_of_memory("msg_list_add");
SIVAL(ml->buf, 0, ((code+MPLEX_BASE)<<24) | len);
memcpy(ml->buf+4, buf, len);
ml->len = len+4;
if (msg_list_tail)
msg_list_tail->next = ml;
else
lst->head = m;
lst->tail = m;
msg_list_head = ml;
msg_list_tail = ml;
}
void send_msg(enum msgcode code, char *buf, int len)
{
if (msg_fd_out < 0) {
io_multiplex_write(code, buf, len);
return;
}
msg_list_add(code, buf, len);
msg_list_push(NORMAL_FLUSH);
}
/* Read a message from the MSG_* fd and handle it. This is called either
@@ -257,8 +286,6 @@ static void read_msg_fd(void)
exit_cleanup(RERR_STREAMIO);
}
read_loop(fd, buf, 4);
if (remove_source_files)
decrement_active_files(IVAL(buf,0));
flist_ndx_push(&redo_list, IVAL(buf,0));
break;
case MSG_DELETED:
@@ -267,7 +294,7 @@ static void read_msg_fd(void)
exit_cleanup(RERR_STREAMIO);
}
read_loop(fd, buf, len);
send_msg(MSG_DELETED, buf, len);
io_multiplex_write(MSG_DELETED, buf, len);
break;
case MSG_SUCCESS:
if (len != 4 || !am_generator) {
@@ -275,20 +302,11 @@ static void read_msg_fd(void)
exit_cleanup(RERR_STREAMIO);
}
read_loop(fd, buf, len);
if (remove_source_files) {
decrement_active_files(IVAL(buf,0));
send_msg(MSG_SUCCESS, buf, len);
}
if (remove_sent_files)
io_multiplex_write(MSG_SUCCESS, buf, len);
if (preserve_hard_links)
flist_ndx_push(&hlink_list, IVAL(buf,0));
break;
case MSG_SOCKERR:
if (!am_generator) {
rprintf(FERROR, "invalid message %d:%d\n", tag, len);
exit_cleanup(RERR_STREAMIO);
}
close_multiplexing_out();
/* FALL THROUGH */
case MSG_INFO:
case MSG_ERROR:
case MSG_LOG:
@@ -297,45 +315,22 @@ static void read_msg_fd(void)
if (n >= sizeof buf)
n = sizeof buf - 1;
read_loop(fd, buf, n);
rwrite(tag, buf, n);
rwrite((enum logcode)tag, buf, n);
len -= n;
}
break;
default:
rprintf(FERROR, "unknown message %d:%d [%s]\n",
tag, len, who_am_i());
rprintf(FERROR, "unknown message %d:%d\n", tag, len);
exit_cleanup(RERR_STREAMIO);
}
msg_fd_in = fd;
}
/* This is used by the generator to limit how many file transfers can
* be active at once when --remove-source-files is specified. Without
* this, sender-side deletions were mostly happening at the end. */
void increment_active_files(int ndx, int itemizing, enum logcode code)
{
/* TODO: tune these limits? */
while (active_filecnt >= (active_bytecnt >= 128*1024 ? 10 : 50)) {
if (hlink_list.head)
check_for_finished_hlinks(itemizing, code);
read_msg_fd();
}
active_filecnt++;
active_bytecnt += the_file_list->files[ndx]->length;
}
void decrement_active_files(int ndx)
{
active_filecnt--;
active_bytecnt -= the_file_list->files[ndx]->length;
}
/* Try to push messages off the list onto the wire. If we leave with more
* to do, return 0. On error, return -1. If everything flushed, return 1.
* This is only active in the receiver. */
static int msg2genr_flush(int flush_it_all)
int msg_list_push(int flush_it_all)
{
static int written = 0;
struct timeval tv;
@@ -344,9 +339,9 @@ static int msg2genr_flush(int flush_it_all)
if (msg_fd_out < 0)
return -1;
while (msg2genr.head) {
struct msg_list_item *m = msg2genr.head;
int n = write(msg_fd_out, m->buf + written, m->len - written);
while (msg_list_head) {
struct msg_list *ml = msg_list_head;
int n = write(msg_fd_out, ml->buf + written, ml->len - written);
if (n < 0) {
if (errno == EINTR)
continue;
@@ -360,32 +355,18 @@ static int msg2genr_flush(int flush_it_all)
tv.tv_usec = 0;
if (!select(msg_fd_out+1, NULL, &fds, NULL, &tv))
check_timeout();
} else if ((written += n) == m->len) {
msg2genr.head = m->next;
if (!msg2genr.head)
msg2genr.tail = NULL;
free(m);
} else if ((written += n) == ml->len) {
free(ml->buf);
msg_list_head = ml->next;
if (!msg_list_head)
msg_list_tail = NULL;
free(ml);
written = 0;
}
}
return 1;
}
int send_msg(enum msgcode code, char *buf, int len)
{
if (msg_fd_out < 0) {
if (!defer_forwarding_messages)
return io_multiplex_write(code, buf, len);
if (!io_multiplexing_out)
return 0;
msg_list_add(&msg2sndr, code, buf, len);
return 1;
}
msg_list_add(&msg2genr, code, buf, len);
msg2genr_flush(NORMAL_FLUSH);
return 1;
}
int get_redo_num(int itemizing, enum logcode code)
{
while (1) {
@@ -453,6 +434,7 @@ static void whine_about_eof(int fd)
exit_cleanup(RERR_STREAMIO);
}
/**
* Read from a socket with I/O timeout. return the number of bytes
* read. If no bytes can be read then exit, never return a number <= 0.
@@ -466,11 +448,11 @@ static void whine_about_eof(int fd)
*/
static int read_timeout(int fd, char *buf, size_t len)
{
int n, cnt = 0;
int n, ret = 0;
io_flush(NORMAL_FLUSH);
while (cnt == 0) {
while (ret == 0) {
/* until we manage to read *something* */
fd_set r_fds, w_fds;
struct timeval tv;
@@ -480,7 +462,7 @@ static int read_timeout(int fd, char *buf, size_t len)
FD_ZERO(&r_fds);
FD_ZERO(&w_fds);
FD_SET(fd, &r_fds);
if (msg2genr.head) {
if (msg_list_head) {
FD_SET(msg_fd_out, &w_fds);
if (msg_fd_out > maxfd)
maxfd = msg_fd_out;
@@ -517,8 +499,8 @@ static int read_timeout(int fd, char *buf, size_t len)
continue;
}
if (msg2genr.head && FD_ISSET(msg_fd_out, &w_fds))
msg2genr_flush(NORMAL_FLUSH);
if (msg_list_head && FD_ISSET(msg_fd_out, &w_fds))
msg_list_push(NORMAL_FLUSH);
if (io_filesfrom_f_out >= 0) {
if (io_filesfrom_buflen) {
@@ -596,23 +578,21 @@ static int read_timeout(int fd, char *buf, size_t len)
continue;
/* Don't write errors on a dead socket. */
if (fd == sock_f_in) {
if (fd == sock_f_in)
close_multiplexing_out();
rsyserr(FSOCKERR, errno, "read error");
} else
rsyserr(FERROR, errno, "read error");
rsyserr(FERROR, errno, "read error");
exit_cleanup(RERR_STREAMIO);
}
buf += n;
len -= n;
cnt += n;
ret += n;
if (fd == sock_f_in && io_timeout)
last_io_in = time(NULL);
}
return cnt;
return ret;
}
/**
@@ -633,19 +613,13 @@ int read_filesfrom_line(int fd, char *fname)
if (cnt < 0 && (errno == EWOULDBLOCK
|| errno == EINTR || errno == EAGAIN)) {
struct timeval tv;
fd_set r_fds, e_fds;
FD_ZERO(&r_fds);
FD_SET(fd, &r_fds);
FD_ZERO(&e_fds);
FD_SET(fd, &e_fds);
fd_set fds;
FD_ZERO(&fds);
FD_SET(fd, &fds);
tv.tv_sec = select_timeout;
tv.tv_usec = 0;
if (!select(fd+1, &r_fds, NULL, &e_fds, &tv))
if (!select(fd+1, &fds, NULL, NULL, &tv))
check_timeout();
if (FD_ISSET(fd, &e_fds)) {
rsyserr(FINFO, errno,
"select exception on fd %d", fd);
}
continue;
}
if (cnt != 1)
@@ -668,6 +642,7 @@ int read_filesfrom_line(int fd, char *fname)
return s - fname;
}
static char *iobuf_out;
static int iobuf_out_cnt;
@@ -680,6 +655,7 @@ void io_start_buffering_out(void)
iobuf_out_cnt = 0;
}
static char *iobuf_in;
static size_t iobuf_in_siz;
@@ -692,6 +668,7 @@ void io_start_buffering_in(void)
out_of_memory("io_start_buffering_in");
}
void io_end_buffering(void)
{
io_flush(NORMAL_FLUSH);
@@ -701,12 +678,14 @@ void io_end_buffering(void)
}
}
void maybe_flush_socket(void)
{
if (iobuf_out && iobuf_out_cnt && time(NULL) - last_io_out >= 5)
io_flush(NORMAL_FLUSH);
}
void maybe_send_keepalive(void)
{
if (time(NULL) - last_io_out >= allowed_lull) {
@@ -721,6 +700,7 @@ void maybe_send_keepalive(void)
}
}
/**
* Continue trying to read len bytes - don't return until len has been
* read.
@@ -735,6 +715,7 @@ static void read_loop(int fd, char *buf, size_t len)
}
}
/**
* Read from the file descriptor handling multiplexing - return number
* of bytes read.
@@ -746,8 +727,12 @@ static int readfd_unbuffered(int fd, char *buf, size_t len)
static size_t remaining;
static size_t iobuf_in_ndx;
size_t msg_bytes;
int tag, cnt = 0;
char line[BIGPATHBUFLEN];
int tag, ret = 0;
#if MAXPATHLEN < 4096
char line[4096+1024];
#else
char line[MAXPATHLEN+1024];
#endif
if (!iobuf_in || fd != sock_f_in)
return read_timeout(fd, buf, len);
@@ -757,13 +742,13 @@ static int readfd_unbuffered(int fd, char *buf, size_t len)
iobuf_in_ndx = 0;
}
while (cnt == 0) {
while (ret == 0) {
if (remaining) {
len = MIN(len, remaining);
memcpy(buf, iobuf_in + iobuf_in_ndx, len);
iobuf_in_ndx += len;
remaining -= len;
cnt = len;
ret = len;
break;
}
@@ -789,13 +774,12 @@ static int readfd_unbuffered(int fd, char *buf, size_t len)
if (msg_bytes >= sizeof line)
goto overflow;
read_loop(fd, line, msg_bytes);
line[msg_bytes] = '\0';
/* A directory name was sent with the trailing null */
if (msg_bytes > 0 && !line[msg_bytes-1])
log_delete(line, S_IFDIR);
else {
line[msg_bytes] = '\0';
else
log_delete(line, S_IFREG);
}
break;
case MSG_SUCCESS:
if (msg_bytes != 4) {
@@ -828,9 +812,11 @@ static int readfd_unbuffered(int fd, char *buf, size_t len)
if (remaining == 0)
io_flush(NORMAL_FLUSH);
return cnt;
return ret;
}
/**
* Do a buffered read from @p fd. Don't return until all @p n bytes
* have been read. If all @p n can't be read then exit with an
@@ -838,12 +824,12 @@ static int readfd_unbuffered(int fd, char *buf, size_t len)
**/
static void readfd(int fd, char *buffer, size_t N)
{
int cnt;
int ret;
size_t total = 0;
while (total < N) {
cnt = readfd_unbuffered(fd, buffer + total, N-total);
total += cnt;
ret = readfd_unbuffered(fd, buffer + total, N-total);
total += ret;
}
if (fd == write_batch_monitor_in) {
@@ -855,6 +841,7 @@ static void readfd(int fd, char *buffer, size_t N)
stats.total_read += total;
}
int read_shortint(int f)
{
uchar b[2];
@@ -862,36 +849,37 @@ int read_shortint(int f)
return (b[1] << 8) + b[0];
}
int32 read_int(int f)
{
char b[4];
int32 num;
int32 ret;
readfd(f,b,4);
num = IVAL(b,0);
if (num == (int32)0xffffffff)
ret = IVAL(b,0);
if (ret == (int32)0xffffffff)
return -1;
return num;
return ret;
}
int64 read_longint(int f)
{
int64 num;
int64 ret;
char b[8];
num = read_int(f);
ret = read_int(f);
if ((int32)num != (int32)0xffffffff)
return num;
if ((int32)ret != (int32)0xffffffff)
return ret;
#if SIZEOF_INT64 < 8
rprintf(FERROR, "Integer overflow: attempted 64-bit offset\n");
exit_cleanup(RERR_UNSUPPORTED);
#else
readfd(f,b,8);
num = IVAL(b,0) | (((int64)IVAL(b,4))<<32);
ret = IVAL(b,0) | (((int64)IVAL(b,4))<<32);
#endif
return num;
return ret;
}
void read_buf(int f,char *buf,size_t len)
@@ -936,11 +924,6 @@ int read_vstring(int f, char *buf, int bufsize)
void read_sum_head(int f, struct sum_struct *sum)
{
sum->count = read_int(f);
if (sum->count < 0) {
rprintf(FERROR, "Invalid checksum count %ld [%s]\n",
(long)sum->count, who_am_i());
exit_cleanup(RERR_PROTOCOL);
}
sum->blength = read_int(f);
if (sum->blength < 0 || sum->blength > MAX_BLOCK_SIZE) {
rprintf(FERROR, "Invalid block length %ld [%s]\n",
@@ -978,6 +961,7 @@ void write_sum_head(int f, struct sum_struct *sum)
write_int(f, sum->remainder);
}
/**
* Sleep after writing to limit I/O bandwidth usage.
*
@@ -997,16 +981,16 @@ void write_sum_head(int f, struct sum_struct *sum)
static void sleep_for_bwlimit(int bytes_written)
{
static struct timeval prior_tv;
static long total_written = 0;
static long total_written = 0;
struct timeval tv, start_tv;
long elapsed_usec, sleep_usec;
#define ONE_SEC 1000000L /* # of microseconds in a second */
if (!bwlimit_writemax)
if (!bwlimit)
return;
total_written += bytes_written;
total_written += bytes_written;
gettimeofday(&start_tv, NULL);
if (prior_tv.tv_sec) {
@@ -1033,8 +1017,9 @@ static void sleep_for_bwlimit(int bytes_written)
total_written = (sleep_usec - elapsed_usec) * bwlimit / (ONE_SEC/1024);
}
/* Write len bytes to the file descriptor fd, looping as necessary to get
* the job done and also (in certain circumstances) reading any data on
* the job done and also (in certain circumstnces) reading any data on
* msg_fd_in to avoid deadlock.
*
* This function underlies the multiplexing system. The body of the
@@ -1042,23 +1027,20 @@ static void sleep_for_bwlimit(int bytes_written)
static void writefd_unbuffered(int fd,char *buf,size_t len)
{
size_t n, total = 0;
fd_set w_fds, r_fds, e_fds;
int maxfd, count, cnt, using_r_fds;
int defer_save = defer_forwarding_messages;
fd_set w_fds, r_fds;
int maxfd, count, ret, using_r_fds;
struct timeval tv;
no_flush++;
while (total < len) {
FD_ZERO(&w_fds);
FD_SET(fd, &w_fds);
FD_ZERO(&e_fds);
FD_SET(fd, &e_fds);
FD_SET(fd,&w_fds);
maxfd = fd;
if (msg_fd_in >= 0) {
if (msg_fd_in >= 0 && len-total >= contiguous_write_len) {
FD_ZERO(&r_fds);
FD_SET(msg_fd_in, &r_fds);
FD_SET(msg_fd_in,&r_fds);
if (msg_fd_in > maxfd)
maxfd = msg_fd_in;
using_r_fds = 1;
@@ -1070,7 +1052,7 @@ static void writefd_unbuffered(int fd,char *buf,size_t len)
errno = 0;
count = select(maxfd + 1, using_r_fds ? &r_fds : NULL,
&w_fds, &e_fds, &tv);
&w_fds, NULL, &tv);
if (count <= 0) {
if (count < 0 && errno == EBADF)
@@ -1079,11 +1061,6 @@ static void writefd_unbuffered(int fd,char *buf,size_t len)
continue;
}
if (FD_ISSET(fd, &e_fds)) {
rsyserr(FINFO, errno,
"select exception on fd %d", fd);
}
if (using_r_fds && FD_ISSET(msg_fd_in, &r_fds))
read_msg_fd();
@@ -1091,12 +1068,12 @@ static void writefd_unbuffered(int fd,char *buf,size_t len)
continue;
n = len - total;
if (bwlimit_writemax && n > bwlimit_writemax)
if (bwlimit && n > bwlimit_writemax)
n = bwlimit_writemax;
cnt = write(fd, buf + total, n);
ret = write(fd, buf + total, n);
if (cnt <= 0) {
if (cnt < 0) {
if (ret <= 0) {
if (ret < 0) {
if (errno == EINTR)
continue;
if (errno == EWOULDBLOCK || errno == EAGAIN) {
@@ -1109,8 +1086,8 @@ static void writefd_unbuffered(int fd,char *buf,size_t len)
if (fd == sock_f_out)
close_multiplexing_out();
rsyserr(FERROR, errno,
"writefd_unbuffered failed to write %ld bytes [%s]",
(long)len, who_am_i());
"writefd_unbuffered failed to write %ld bytes: phase \"%s\" [%s]",
(long)len, io_write_phase, who_am_i());
/* If the other side is sending us error messages, try
* to grab any messages they sent before they died. */
while (fd == sock_f_out && io_multiplexing_in) {
@@ -1122,36 +1099,18 @@ static void writefd_unbuffered(int fd,char *buf,size_t len)
exit_cleanup(RERR_STREAMIO);
}
total += cnt;
defer_forwarding_messages = 1;
total += ret;
if (fd == sock_f_out) {
if (io_timeout || am_generator)
last_io_out = time(NULL);
sleep_for_bwlimit(cnt);
sleep_for_bwlimit(ret);
}
}
defer_forwarding_messages = defer_save;
no_flush--;
}
static void msg2sndr_flush(void)
{
if (defer_forwarding_messages)
return;
while (msg2sndr.head && io_multiplexing_out) {
struct msg_list_item *m = msg2sndr.head;
if (!(msg2sndr.head = m->next))
msg2sndr.tail = NULL;
stats.total_written += m->len;
defer_forwarding_messages = 1;
writefd_unbuffered(sock_f_out, m->buf, m->len);
defer_forwarding_messages = 0;
free(m);
}
}
/**
* Write an message to a multiplexed stream. If this fails then rsync
@@ -1159,33 +1118,38 @@ static void msg2sndr_flush(void)
**/
static void mplex_write(enum msgcode code, char *buf, size_t len)
{
char buffer[1024];
char buffer[4096];
size_t n = len;
SIVAL(buffer, 0, ((MPLEX_BASE + (int)code)<<24) + len);
if (n > sizeof buffer - 4)
n = 0;
else
memcpy(buffer + 4, buf, n);
/* When the generator reads messages from the msg_fd_in pipe, it can
* cause output to occur down the socket. Setting contiguous_write_len
* prevents the reading of msg_fd_in once we actually start to write
* this sequence of data (though we might read it before the start). */
if (am_generator && msg_fd_in >= 0)
contiguous_write_len = len + 4;
if (n > sizeof buffer - 4)
n = sizeof buffer - 4;
memcpy(&buffer[4], buf, n);
writefd_unbuffered(sock_f_out, buffer, n+4);
len -= n;
buf += n;
if (len) {
defer_forwarding_messages = 1;
if (len)
writefd_unbuffered(sock_f_out, buf, len);
defer_forwarding_messages = 0;
msg2sndr_flush();
}
if (am_generator && msg_fd_in >= 0)
contiguous_write_len = 0;
}
void io_flush(int flush_it_all)
{
msg2genr_flush(flush_it_all);
msg2sndr_flush();
msg_list_push(flush_it_all);
if (!iobuf_out_cnt || no_flush)
return;
@@ -1197,6 +1161,7 @@ void io_flush(int flush_it_all)
iobuf_out_cnt = 0;
}
static void writefd(int fd,char *buf,size_t len)
{
if (fd == msg_fd_out) {
@@ -1231,6 +1196,7 @@ static void writefd(int fd,char *buf,size_t len)
}
}
void write_shortint(int f, int x)
{
uchar b[2];
@@ -1239,6 +1205,7 @@ void write_shortint(int f, int x)
writefd(f, (char *)b, 2);
}
void write_int(int f,int32 x)
{
char b[4];
@@ -1246,6 +1213,15 @@ void write_int(int f,int32 x)
writefd(f,b,4);
}
void write_int_named(int f, int32 x, const char *phase)
{
io_write_phase = phase;
write_int(f, x);
io_write_phase = phase_unknown;
}
/*
* Note: int64 may actually be a 32-bit type if ./configure couldn't find any
* 64-bit types on this platform.
@@ -1307,6 +1283,7 @@ void write_vstring(int f, char *str, int len)
writefd(f, str, len);
}
/**
* Read a line of up to @p maxlen characters into @p buf (not counting
* the trailing null). Strips the (required) trailing newline and all
@@ -1332,10 +1309,11 @@ int read_line(int f, char *buf, size_t maxlen)
return maxlen > 0;
}
void io_printf(int fd, const char *format, ...)
{
va_list ap;
char buf[BIGPATHBUFLEN];
char buf[1024];
int len;
va_start(ap, format);
@@ -1345,14 +1323,10 @@ void io_printf(int fd, const char *format, ...)
if (len < 0)
exit_cleanup(RERR_STREAMIO);
if (len > (int)sizeof buf) {
rprintf(FERROR, "io_printf() was too long for the buffer.\n");
exit_cleanup(RERR_STREAMIO);
}
write_sbuf(fd, buf);
}
/** Setup for multiplexing a MSG_* stream with the data stream. */
void io_start_multiplex_out(void)
{

View File

@@ -1,35 +1,42 @@
/*
* Reimplementations of standard functions for platforms that don't have them.
/*
Copyright (C) Andrew Tridgell 1998
Copyright (C) 2002 by Martin Pool
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/**
* @file compat.c
*
* Copyright (C) 1998 Andrew Tridgell
* Copyright (C) 2002 Martin Pool
* Copyright (C) 2004, 2005, 2006 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
* Reimplementations of standard functions for platforms that don't
* have them.
**/
#include "rsync.h"
#ifndef HAVE_STRDUP
char *strdup(char *s)
{
int len = strlen(s) + 1;
char *ret = (char *)malloc(len);
if (ret)
memcpy(ret, s, len);
return ret;
int l = strlen(s) + 1;
char *ret = (char *)malloc(l);
if (ret)
strcpy(ret,s);
return ret;
}
#endif
@@ -79,7 +86,7 @@
/**
* Find the first ocurrence in @p s of any character in @p accept.
*
* Derived from glibc
* Derived from glibc
**/
char *strpbrk(const char *s, const char *accept)
{
@@ -98,7 +105,7 @@
#ifndef HAVE_STRLCPY
/**
* Like strncpy but does not 0 fill the buffer and always null
* Like strncpy but does not 0 fill the buffer and always null
* terminates.
*
* @param bufsize is the size of the destination buffer.
@@ -121,7 +128,7 @@
#ifndef HAVE_STRLCAT
/**
* Like strncat() but does not 0 fill the buffer and always null
* Like strncat() but does not 0 fill the buffer and always null
* terminates.
*
* @param bufsize length of the buffer, which should be one more than
@@ -143,6 +150,49 @@
}
#endif
#ifdef REPLACE_INET_NTOA
char *rep_inet_ntoa(struct in_addr ip)
{
unsigned char *p = (unsigned char *)&ip.s_addr;
static char buf[18];
#ifdef WORDS_BIGENDIAN
snprintf(buf, 18, "%d.%d.%d.%d",
(int)p[0], (int)p[1], (int)p[2], (int)p[3]);
#else
snprintf(buf, 18, "%d.%d.%d.%d",
(int)p[3], (int)p[2], (int)p[1], (int)p[0]);
#endif
return buf;
}
#endif
#ifdef REPLACE_INET_ATON
int inet_aton(const char *cp, struct in_addr *inp)
{
unsigned int a1, a2, a3, a4;
unsigned long ret;
if (strcmp(cp, "255.255.255.255") == 0) {
inp->s_addr = (unsigned) -1;
return 0;
}
if (sscanf(cp, "%u.%u.%u.%u", &a1, &a2, &a3, &a4) != 4 ||
a1 > 255 || a2 > 255 || a3 > 255 || a4 > 255) {
return 0;
}
ret = (a1 << 24) | (a2 << 16) | (a3 << 8) | a4;
inp->s_addr = htonl(ret);
if (inp->s_addr == (unsigned) -1) {
return 0;
}
return 1;
}
#endif
/* some systems don't take the 2nd argument */
int sys_gettimeofday(struct timeval *tv)
{

View File

@@ -75,14 +75,13 @@ inet_ntop4(const unsigned char *src, char *dst, size_t size)
{
static const char *fmt = "%u.%u.%u.%u";
char tmp[sizeof "255.255.255.255"];
size_t len;
len = snprintf(tmp, sizeof tmp, fmt, src[0], src[1], src[2], src[3]);
if (len >= size) {
if ((size_t)sprintf(tmp, fmt, src[0], src[1], src[2], src[3]) >= size)
{
errno = ENOSPC;
return (NULL);
}
memcpy(dst, tmp, len + 1);
strcpy(dst, tmp);
return (dst);
}
@@ -107,7 +106,7 @@ inet_ntop6(const unsigned char *src, char *dst, size_t size)
char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
struct { int base, len; } best, cur;
unsigned int words[NS_IN6ADDRSZ / NS_INT16SZ];
int i, inc;
int i;
/*
* Preprocess:
@@ -158,14 +157,13 @@ inet_ntop6(const unsigned char *src, char *dst, size_t size)
/* Is this address an encapsulated IPv4? */
if (i == 6 && best.base == 0 &&
(best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp)))
if (!inet_ntop4(src+12, tp,
sizeof tmp - (tp - tmp)))
return (NULL);
tp += strlen(tp);
break;
}
inc = snprintf(tp, 5, "%x", words[i]);
assert(inc < 5);
tp += inc;
tp += sprintf(tp, "%x", words[i]);
}
/* Was it a trailing run of 0x00's? */
if (best.base != -1 && (best.base + best.len) ==
@@ -180,7 +178,7 @@ inet_ntop6(const unsigned char *src, char *dst, size_t size)
errno = ENOSPC;
return (NULL);
}
memcpy(dst, tmp, tp - tmp);
strcpy(dst, tmp);
return (dst);
}
#endif /* AF_INET6 */

View File

@@ -1,31 +1,30 @@
/*
* Unix SMB/Netbios implementation.
* Version 1.9.
* An implementation of MD4 designed for use in the SMB authentication protocol.
*
* Copyright (C) 1997-1998 Andrew Tridgell
* Copyright (C) 2005 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
Unix SMB/Netbios implementation.
Version 1.9.
a implementation of MD4 designed for use in the SMB authentication protocol
Copyright (C) Andrew Tridgell 1997-1998.
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "rsync.h"
/* NOTE: This code makes no attempt to be fast!
*
* It assumes that a int is at least 32 bits long. */
It assumes that a int is at least 32 bits long
*/
static struct mdfour *m;

View File

@@ -1,24 +1,23 @@
/*
* Unix SMB/Netbios implementation.
* Version 1.9.
* An implementation of MD4 designed for use in the SMB authentication protocol.
*
* Copyright (C) 1997-1998 Andrew Tridgell
*
* 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
Unix SMB/Netbios implementation.
Version 1.9.
a implementation of MD4 designed for use in the SMB authentication protocol
Copyright (C) Andrew Tridgell 1997-1998.
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
struct mdfour {
uint32 A, B, C, D;
@@ -30,3 +29,7 @@ void mdfour_begin(struct mdfour *md);
void mdfour_update(struct mdfour *md, unsigned char *in, uint32 n);
void mdfour_result(struct mdfour *md, unsigned char *out);
void mdfour(unsigned char *out, unsigned char *in, int n);

View File

@@ -1,40 +1,41 @@
/*
* A single utility routine.
*
* Copyright (C) 1996 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2001 Martin Pool <mbp@samba.org>
* Copyright (C) 2003, 2006 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
/*
Copyright (C) Andrew Tridgell 1996
Copyright (C) Paul Mackerras 1996
Copyright (C) 2001 by Martin Pool <mbp@samba.org>
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "rsync.h"
/* Produce a string representation of Unix mode bits like that used by ls(1).
* The "buf" buffer must be at least 11 characters. */
void permstring(char *perms, mode_t mode)
/**
* Produce a string representation of Unix mode bits like that used by
* ls(1).
*
* @param buf buffer of at least 11 characters
**/
void permstring(char *perms,
int mode)
{
static const char *perm_map = "rwxrwxrwx";
int i;
strlcpy(perms, "----------", 11);
for (i = 0; i < 9; i++) {
if (mode & (1 << i))
perms[9-i] = perm_map[8-i];
strcpy(perms, "----------");
for (i=0;i<9;i++) {
if (mode & (1<<i)) perms[9-i] = perm_map[8-i];
}
/* Handle setuid/sticky bits. You might think the indices are
@@ -45,22 +46,18 @@ void permstring(char *perms, mode_t mode)
if (mode & S_ISGID)
perms[6] = (mode & S_IXGRP) ? 's' : 'S';
#ifdef S_ISVTX
if (mode & S_ISVTX)
perms[9] = (mode & S_IXOTH) ? 't' : 'T';
#endif
if (S_ISDIR(mode))
perms[0] = 'd';
else if (S_ISLNK(mode))
perms[0] = 'l';
else if (S_ISBLK(mode))
perms[0] = 'b';
else if (S_ISCHR(mode))
perms[0] = 'c';
else if (S_ISSOCK(mode))
perms[0] = 's';
else if (S_ISFIFO(mode))
perms[0] = 'p';
if (S_ISLNK(mode)) perms[0] = 'l';
if (S_ISDIR(mode)) perms[0] = 'd';
if (S_ISBLK(mode)) perms[0] = 'b';
if (S_ISCHR(mode)) perms[0] = 'c';
if (S_ISSOCK(mode)) perms[0] = 's';
if (S_ISFIFO(mode)) perms[0] = 'p';
}

View File

@@ -1,3 +1,3 @@
#define PERMSTRING_SIZE 11
void permstring(char *perms, mode_t mode);
void permstring(char *perms, int mode);

View File

@@ -56,7 +56,8 @@ pool_create(size_t size, size_t quantum,
pool->size = size /* round extent size to min alignment reqs */
? (size + MINALIGN - 1) & ~(MINALIGN - 1)
: POOL_DEF_EXTENT;
if (pool->flags & POOL_INTERN) {
if (pool->flags & POOL_INTERN)
{
pool->size -= sizeof (struct pool_extent);
flags |= POOL_APPEND;
}
@@ -76,13 +77,15 @@ pool_destroy(alloc_pool_t p)
if (!pool)
return;
if (pool->live) {
if (pool->live)
{
cur = pool->live;
free(cur->start);
if (!(pool->flags & POOL_APPEND))
free(cur);
}
for (cur = pool->free; cur; cur = next) {
for (cur = pool->free; cur; cur = next)
{
next = cur->next;
free(cur->start);
if (!(pool->flags & POOL_APPEND))
@@ -106,14 +109,16 @@ pool_alloc(alloc_pool_t p, size_t len, char *bomb)
if (len > pool->size)
goto bomb;
if (!pool->live || len > pool->live->free) {
if (!pool->live || len > pool->live->free)
{
void *start;
size_t free;
size_t bound;
size_t sqew;
size_t asize;
if (pool->live) {
if (pool->live)
{
pool->live->next = pool->free;
pool->free = pool->live;
}
@@ -132,11 +137,16 @@ pool_alloc(alloc_pool_t p, size_t len, char *bomb)
memset(start, 0, pool->size);
if (pool->flags & POOL_APPEND)
{
pool->live = PTR_ADD(start, free);
}
else if (!(pool->live = (struct pool_extent *) malloc(sizeof (struct pool_extent))))
{
goto bomb;
}
if (pool->flags & POOL_QALIGN && pool->quantum > 1
&& (sqew = (size_t)PTR_ADD(start, free) % pool->quantum)) {
&& (sqew = (size_t)PTR_ADD(start, free) % pool->quantum))
{
bound += sqew;
free -= sqew;
}
@@ -176,7 +186,8 @@ pool_free(alloc_pool_t p, size_t len, void *addr)
else if (pool->quantum > 1 && len % pool->quantum)
len += pool->quantum - len % pool->quantum;
if (!addr && pool->live) {
if (!addr && pool->live)
{
pool->live->next = pool->free;
pool->free = pool->live;
pool->live = NULL;
@@ -186,28 +197,35 @@ pool_free(alloc_pool_t p, size_t len, void *addr)
pool->b_freed += len;
cur = pool->live;
if (cur && addr >= cur->start
&& addr < PTR_ADD(cur->start, pool->size)) {
if (addr == PTR_ADD(cur->start, cur->free)) {
if (cur
&& addr >= cur->start
&& addr < PTR_ADD(cur->start, pool->size))
{
if (addr == PTR_ADD(cur->start, cur->free))
{
if (pool->flags & POOL_CLEAR)
memset(addr, 0, len);
pool->b_freed += len;
} else
} else {
cur->bound += len;
if (cur->free + cur->bound >= pool->size) {
}
if (cur->free + cur->bound >= pool->size)
{
size_t sqew;
cur->free = pool->size;
cur->bound = 0;
if (pool->flags & POOL_QALIGN && pool->quantum > 1
&& (sqew = (size_t)PTR_ADD(cur->start, cur->free) % pool->quantum)) {
&& (sqew = (size_t)PTR_ADD(cur->start, cur->free) % pool->quantum))
{
cur->bound += sqew;
cur->free -= sqew;
}
}
return;
}
for (prev = NULL, cur = pool->free; cur; prev = cur, cur = cur->next) {
for (prev = NULL, cur = pool->free; cur; prev = cur, cur = cur->next)
{
if (addr >= cur->start
&& addr < PTR_ADD(cur->start, pool->size))
break;
@@ -215,14 +233,16 @@ pool_free(alloc_pool_t p, size_t len, void *addr)
if (!cur)
return;
if (prev) {
if (prev)
{
prev->next = cur->next;
cur->next = pool->free;
pool->free = cur;
}
cur->bound += len;
if (cur->free + cur->bound >= pool->size) {
if (cur->free + cur->bound >= pool->size)
{
pool->free = cur->next;
free(cur->start);
@@ -234,11 +254,11 @@ pool_free(alloc_pool_t p, size_t len, void *addr)
}
#define FDPRINT(label, value) \
snprintf(buf, sizeof buf, label, value), \
write(fd, buf, strlen(buf))
snprintf(buf, BUFSIZ, label, value), \
write(fd, buf, strlen(buf));
#define FDEXTSTAT(ext) \
snprintf(buf, sizeof buf, " %12ld %5ld\n", \
snprintf(buf, BUFSIZ, " %12ld %5ld\n", \
(long) ext->free, \
(long) ext->bound), \
write(fd, buf, strlen(buf))
@@ -271,10 +291,14 @@ pool_stats(alloc_pool_t p, int fd, int summarize)
write(fd, "\n", 1);
if (pool->live)
{
FDEXTSTAT(pool->live);
strlcpy(buf, " FREE BOUND\n", sizeof buf);
}
strcpy(buf, " FREE BOUND\n");
write(fd, buf, strlen(buf));
for (cur = pool->free; cur; cur = cur->next)
{
FDEXTSTAT(cur);
}
}

View File

@@ -146,7 +146,7 @@
#endif
#ifndef VA_COPY
#if defined HAVE_VA_COPY || defined va_copy
#ifdef HAVE_VA_COPY
#define VA_COPY(dest, src) va_copy(dest, src)
#else
#ifdef HAVE___VA_COPY

View File

@@ -57,312 +57,173 @@
int wildmatch_iteration_count;
#endif
static int force_lower_case = 0;
/* Match pattern "p" against the a virtually-joined string consisting
* of "text" and any strings in array "a". */
static int dowild(const uchar *p, const uchar *text, const uchar*const *a)
static int domatch(const uchar *p, const uchar *text)
{
uchar p_ch;
int matched, special;
uchar ch, prev;
#ifdef WILD_TEST_ITERATIONS
wildmatch_iteration_count++;
#endif
for ( ; (p_ch = *p) != '\0'; text++, p++) {
int matched, special;
uchar t_ch, prev_ch;
while ((t_ch = *text) == '\0') {
if (*a == NULL) {
if (p_ch != '*')
return ABORT_ALL;
break;
}
text = *a++;
}
if (force_lower_case && ISUPPER(t_ch))
t_ch = tolower(t_ch);
switch (p_ch) {
for ( ; (ch = *p) != '\0'; text++, p++) {
if (*text == '\0' && ch != '*')
return FALSE;
switch (ch) {
case '\\':
/* Literal match with following character. Note that the test
* in "default" handles the p[1] == '\0' failure case. */
p_ch = *++p;
ch = *++p;
/* FALLTHROUGH */
default:
if (t_ch != p_ch)
if (*text != ch)
return FALSE;
continue;
case '?':
/* Match anything but '/'. */
if (t_ch == '/')
if (*text == '/')
return FALSE;
continue;
case '*':
if (*++p == '*') {
while (*++p == '*') {}
special = TRUE;
} else
}
else
special = FALSE;
if (*p == '\0') {
/* Trailing "**" matches everything. Trailing "*" matches
* only if there are no more slash characters. */
if (!special) {
do {
if (strchr((char*)text, '/') != NULL)
return FALSE;
} while ((text = *a++) != NULL);
}
return TRUE;
return special? TRUE : strchr((char*)text, '/') == NULL;
}
while (1) {
if (t_ch == '\0') {
if ((text = *a++) == NULL)
break;
t_ch = *text;
continue;
}
if ((matched = dowild(p, text, a)) != FALSE) {
for ( ; *text; text++) {
if ((matched = domatch(p, text)) != FALSE) {
if (!special || matched != ABORT_TO_STARSTAR)
return matched;
} else if (!special && t_ch == '/')
}
else if (!special && *text == '/')
return ABORT_TO_STARSTAR;
t_ch = *++text;
}
return ABORT_ALL;
case '[':
p_ch = *++p;
ch = *++p;
#ifdef NEGATE_CLASS2
if (p_ch == NEGATE_CLASS2)
p_ch = NEGATE_CLASS;
if (ch == NEGATE_CLASS2)
ch = NEGATE_CLASS;
#endif
/* Assign literal TRUE/FALSE because of "matched" comparison. */
special = p_ch == NEGATE_CLASS? TRUE : FALSE;
special = ch == NEGATE_CLASS? TRUE : FALSE;
if (special) {
/* Inverted character class. */
p_ch = *++p;
ch = *++p;
}
prev_ch = 0;
prev = 0;
matched = FALSE;
do {
if (!p_ch)
if (!ch)
return ABORT_ALL;
if (p_ch == '\\') {
p_ch = *++p;
if (!p_ch)
if (ch == '\\') {
ch = *++p;
if (!ch)
return ABORT_ALL;
if (t_ch == p_ch)
if (*text == ch)
matched = TRUE;
} else if (p_ch == '-' && prev_ch && p[1] && p[1] != ']') {
p_ch = *++p;
if (p_ch == '\\') {
p_ch = *++p;
if (!p_ch)
}
else if (ch == '-' && prev && p[1] && p[1] != ']') {
ch = *++p;
if (ch == '\\') {
ch = *++p;
if (!ch)
return ABORT_ALL;
}
if (t_ch <= p_ch && t_ch >= prev_ch)
if (*text <= ch && *text >= prev)
matched = TRUE;
p_ch = 0; /* This makes "prev_ch" get set to 0. */
} else if (p_ch == '[' && p[1] == ':') {
ch = 0; /* This makes "prev" get set to 0. */
}
else if (ch == '[' && p[1] == ':') {
const uchar *s;
int i;
for (s = p += 2; (p_ch = *p) && p_ch != ']'; p++) {}
if (!p_ch)
for (s = p += 2; (ch = *p) && ch != ']'; p++) {}
if (!ch)
return ABORT_ALL;
i = p - s - 1;
if (i < 0 || p[-1] != ':') {
/* Didn't find ":]", so treat like a normal set. */
p = s - 2;
p_ch = '[';
if (t_ch == p_ch)
ch = '[';
if (*text == ch)
matched = TRUE;
continue;
}
if (CC_EQ(s,i, "alnum")) {
if (ISALNUM(t_ch))
if (ISALNUM(*text))
matched = TRUE;
} else if (CC_EQ(s,i, "alpha")) {
if (ISALPHA(t_ch))
}
else if (CC_EQ(s,i, "alpha")) {
if (ISALPHA(*text))
matched = TRUE;
} else if (CC_EQ(s,i, "blank")) {
if (ISBLANK(t_ch))
}
else if (CC_EQ(s,i, "blank")) {
if (ISBLANK(*text))
matched = TRUE;
} else if (CC_EQ(s,i, "cntrl")) {
if (ISCNTRL(t_ch))
}
else if (CC_EQ(s,i, "cntrl")) {
if (ISCNTRL(*text))
matched = TRUE;
} else if (CC_EQ(s,i, "digit")) {
if (ISDIGIT(t_ch))
}
else if (CC_EQ(s,i, "digit")) {
if (ISDIGIT(*text))
matched = TRUE;
} else if (CC_EQ(s,i, "graph")) {
if (ISGRAPH(t_ch))
}
else if (CC_EQ(s,i, "graph")) {
if (ISGRAPH(*text))
matched = TRUE;
} else if (CC_EQ(s,i, "lower")) {
if (ISLOWER(t_ch))
}
else if (CC_EQ(s,i, "lower")) {
if (ISLOWER(*text))
matched = TRUE;
} else if (CC_EQ(s,i, "print")) {
if (ISPRINT(t_ch))
}
else if (CC_EQ(s,i, "print")) {
if (ISPRINT(*text))
matched = TRUE;
} else if (CC_EQ(s,i, "punct")) {
if (ISPUNCT(t_ch))
}
else if (CC_EQ(s,i, "punct")) {
if (ISPUNCT(*text))
matched = TRUE;
} else if (CC_EQ(s,i, "space")) {
if (ISSPACE(t_ch))
}
else if (CC_EQ(s,i, "space")) {
if (ISSPACE(*text))
matched = TRUE;
} else if (CC_EQ(s,i, "upper")) {
if (ISUPPER(t_ch))
}
else if (CC_EQ(s,i, "upper")) {
if (ISUPPER(*text))
matched = TRUE;
} else if (CC_EQ(s,i, "xdigit")) {
if (ISXDIGIT(t_ch))
}
else if (CC_EQ(s,i, "xdigit")) {
if (ISXDIGIT(*text))
matched = TRUE;
} else /* malformed [:class:] string */
}
else /* malformed [:class:] string */
return ABORT_ALL;
p_ch = 0; /* This makes "prev_ch" get set to 0. */
} else if (t_ch == p_ch)
ch = 0; /* This makes "prev" get set to 0. */
}
else if (*text == ch)
matched = TRUE;
} while (prev_ch = p_ch, (p_ch = *++p) != ']');
if (matched == special || t_ch == '/')
} while (prev = ch, (ch = *++p) != ']');
if (matched == special || *text == '/')
return FALSE;
continue;
}
}
do {
if (*text)
return FALSE;
} while ((text = *a++) != NULL);
return TRUE;
return *text == '\0';
}
/* Match literal string "s" against the a virtually-joined string consisting
* of "text" and any strings in array "a". */
static int doliteral(const uchar *s, const uchar *text, const uchar*const *a)
/* Find the pattern (p) in the text string (t). */
int wildmatch(const char *p, const char *t)
{
for ( ; *s != '\0'; text++, s++) {
while (*text == '\0') {
if ((text = *a++) == NULL)
return FALSE;
}
if (*text != *s)
return FALSE;
}
do {
if (*text)
return FALSE;
} while ((text = *a++) != NULL);
return TRUE;
}
/* Return the last "count" path elements from the concatenated string.
* We return a string pointer to the start of the string, and update the
* array pointer-pointer to point to any remaining string elements. */
static const uchar *trailing_N_elements(const uchar*const **a_ptr, int count)
{
const uchar*const *a = *a_ptr;
const uchar*const *first_a = a;
while (*a)
a++;
while (a != first_a) {
const uchar *s = *--a;
s += strlen((char*)s);
while (--s >= *a) {
if (*s == '/' && !--count) {
*a_ptr = a+1;
return s+1;
}
}
}
if (count == 1) {
*a_ptr = a+1;
return *a;
}
return NULL;
}
/* Match the "pattern" against the "text" string. */
int wildmatch(const char *pattern, const char *text)
{
static const uchar *nomore[1]; /* A NULL pointer. */
#ifdef WILD_TEST_ITERATIONS
wildmatch_iteration_count = 0;
#endif
return dowild((const uchar*)pattern, (const uchar*)text, nomore) == TRUE;
}
/* Match the "pattern" against the forced-to-lower-case "text" string. */
int iwildmatch(const char *pattern, const char *text)
{
static const uchar *nomore[1]; /* A NULL pointer. */
int ret;
#ifdef WILD_TEST_ITERATIONS
wildmatch_iteration_count = 0;
#endif
force_lower_case = 1;
ret = dowild((const uchar*)pattern, (const uchar*)text, nomore) == TRUE;
force_lower_case = 0;
return ret;
}
/* Match pattern "p" against the a virtually-joined string consisting
* of all the pointers in array "texts" (which has a NULL pointer at the
* end). The int "where" can be 0 (normal matching), > 0 (match only
* the trailing N slash-separated filename components of "texts"), or < 0
* (match the "pattern" at the start or after any slash in "texts"). */
int wildmatch_array(const char *pattern, const char*const *texts, int where)
{
const uchar *p = (const uchar*)pattern;
const uchar*const *a = (const uchar*const*)texts;
const uchar *text;
int matched;
#ifdef WILD_TEST_ITERATIONS
wildmatch_iteration_count = 0;
#endif
if (where > 0)
text = trailing_N_elements(&a, where);
else
text = *a++;
if (!text)
return FALSE;
if ((matched = dowild(p, text, a)) != TRUE && where < 0
&& matched != ABORT_ALL) {
while (1) {
if (*text == '\0') {
if ((text = (uchar*)*a++) == NULL)
return FALSE;
continue;
}
if (*text++ == '/' && (matched = dowild(p, text, a)) != FALSE
&& matched != ABORT_TO_STARSTAR)
break;
}
}
return matched == TRUE;
}
/* Match literal string "s" against the a virtually-joined string consisting
* of all the pointers in array "texts" (which has a NULL pointer at the
* end). The int "where" can be 0 (normal matching), or > 0 (match
* only the trailing N slash-separated filename components of "texts"). */
int litmatch_array(const char *string, const char*const *texts, int where)
{
const uchar *s = (const uchar*)string;
const uchar*const *a = (const uchar* const*)texts;
const uchar *text;
if (where > 0)
text = trailing_N_elements(&a, where);
else
text = *a++;
if (!text)
return FALSE;
return doliteral(s, text, a) == TRUE;
return domatch((const uchar*)p, (const uchar*)t) == TRUE;
}

View File

@@ -1,6 +1,3 @@
/* wildmatch.h */
int wildmatch(const char *pattern, const char *text);
int iwildmatch(const char *pattern, const char *text);
int wildmatch_array(const char *pattern, const char*const *texts, int where);
int litmatch_array(const char *string, const char*const *texts, int where);
int wildmatch(const char *p, const char *text);

View File

@@ -1,27 +1,27 @@
/* This is based on loadparm.c from Samba, written by Andrew Tridgell
and Karl Auer */
/*
* 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
/* some fixes
*
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
* Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
*/
/*
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* Load parameters.
*
@@ -57,10 +57,6 @@
typedef char pstring[1024];
#define pstrcpy(a,b) strlcpy(a,b,sizeof(pstring))
#ifndef LOG_DAEMON
#define LOG_DAEMON 0
#endif
/* the following are used by loadparm for option lists */
typedef enum
{
@@ -102,11 +98,12 @@ struct parm_struct
*/
typedef struct
{
char *bind_address;
char *motd_file;
char *log_file;
char *pid_file;
char *socket_options;
char *bind_address;
int syslog_facility;
int rsync_port;
} global;
@@ -114,97 +111,78 @@ static global Globals;
/*
* This structure describes a single service. Their order must match the
* initializers below, which you can accomplish by keeping each sub-section
* sorted. (e.g. in vim, just visually select each subsection and use !sort.)
* This structure describes a single service.
*/
typedef struct
{
char *auth_users;
char *name;
char *path;
char *comment;
char *dont_compress;
char *exclude;
char *exclude_from;
char *filter;
char *lock_file;
BOOL read_only;
BOOL write_only;
BOOL list;
BOOL use_chroot;
BOOL transfer_logging;
BOOL ignore_errors;
char *uid;
char *gid;
char *hosts_allow;
char *hosts_deny;
char *auth_users;
char *secrets_file;
BOOL strict_modes;
char *filter;
char *exclude;
char *exclude_from;
char *include;
char *include_from;
char *incoming_chmod;
char *lock_file;
char *log_file;
char *log_format;
char *name;
char *outgoing_chmod;
char *path;
char *postxfer_exec;
char *prexfer_exec;
char *refuse_options;
char *secrets_file;
char *temp_dir;
char *uid;
char *dont_compress;
char *prexfer_exec;
char *postxfer_exec;
int timeout;
int max_connections;
int max_verbosity;
int syslog_facility;
int timeout;
BOOL ignore_errors;
BOOL ignore_nonreadable;
BOOL list;
BOOL read_only;
BOOL strict_modes;
BOOL transfer_logging;
BOOL use_chroot;
BOOL write_only;
} service;
/* This is a default service used to prime a services structure. In order
* to make these easy to keep sorted in the same way as the variables
* above, use the variable name in the leading comment, including a
* trailing ';' (to avoid a sorting problem with trailing digits). */
/* This is a default service used to prime a services structure */
static service sDefault =
{
/* auth_users; */ NULL,
/* comment; */ NULL,
/* dont_compress; */ "*.gz *.tgz *.zip *.z *.rpm *.deb *.iso *.bz2 *.tbz",
/* exclude; */ NULL,
/* exclude_from; */ NULL,
/* filter; */ NULL,
/* gid; */ NOBODY_GROUP,
/* hosts_allow; */ NULL,
/* hosts_deny; */ NULL,
/* include; */ NULL,
/* include_from; */ NULL,
/* incoming_chmod; */ NULL,
/* lock_file; */ DEFAULT_LOCK_FILE,
/* log_file; */ NULL,
/* log_format; */ "%o %h [%a] %m (%u) %f %l",
/* name; */ NULL,
/* outgoing_chmod; */ NULL,
/* path; */ NULL,
/* postxfer_exec; */ NULL,
/* prexfer_exec; */ NULL,
/* refuse_options; */ NULL,
/* secrets_file; */ NULL,
/* temp_dir; */ NULL,
/* uid; */ NOBODY_USER,
/* max_connections; */ 0,
/* max_verbosity; */ 1,
/* syslog_facility; */ LOG_DAEMON,
/* timeout; */ 0,
/* ignore_errors; */ False,
/* ignore_nonreadable; */ False,
/* list; */ True,
/* read_only; */ True,
/* strict_modes; */ True,
/* transfer_logging; */ False,
/* use_chroot; */ True,
/* write_only; */ False,
NULL, /* name */
NULL, /* path */
NULL, /* comment */
DEFAULT_LOCK_FILE, /* lock file */
True, /* read only */
False, /* write only */
True, /* list */
True, /* use chroot */
False, /* transfer logging */
False, /* ignore errors */
NOBODY_USER,/* uid */
NOBODY_GROUP,/* gid */
NULL, /* hosts allow */
NULL, /* hosts deny */
NULL, /* auth users */
NULL, /* secrets file */
True, /* strict modes */
NULL, /* filter */
NULL, /* exclude */
NULL, /* exclude from */
NULL, /* include */
NULL, /* include from */
"%o %h [%a] %m (%u) %f %l", /* log format */
NULL, /* refuse options */
"*.gz *.tgz *.zip *.z *.rpm *.deb *.iso *.bz2 *.tbz", /* dont compress */
NULL, /* prexfer_exec */
NULL, /* postxfer_exec */
0, /* timeout */
0, /* max connections */
1, /* max verbosity */
False /* ignore nonreadable */
};
@@ -287,64 +265,64 @@ static struct enum_list enum_facilities[] = {
/* note that we do not initialise the defaults union - it is not allowed in ANSI C */
static struct parm_struct parm_table[] =
{
{"address", P_STRING, P_GLOBAL,&Globals.bind_address, NULL,0},
{"motd file", P_STRING, P_GLOBAL,&Globals.motd_file, NULL,0},
{"pid file", P_STRING, P_GLOBAL,&Globals.pid_file, NULL,0},
{"port", P_INTEGER,P_GLOBAL,&Globals.rsync_port, NULL,0},
{"socket options", P_STRING, P_GLOBAL,&Globals.socket_options, NULL,0},
{"motd file", P_STRING, P_GLOBAL, &Globals.motd_file, NULL, 0},
{"syslog facility", P_ENUM, P_GLOBAL, &Globals.syslog_facility, enum_facilities,0},
{"socket options", P_STRING, P_GLOBAL, &Globals.socket_options,NULL, 0},
{"log file", P_STRING, P_GLOBAL, &Globals.log_file, NULL, 0},
{"pid file", P_STRING, P_GLOBAL, &Globals.pid_file, NULL, 0},
{"port", P_INTEGER, P_GLOBAL, &Globals.rsync_port, NULL, 0},
{"address", P_STRING, P_GLOBAL, &Globals.bind_address, NULL, 0},
{"auth users", P_STRING, P_LOCAL, &sDefault.auth_users, NULL,0},
{"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL,0},
{"dont compress", P_STRING, P_LOCAL, &sDefault.dont_compress, NULL,0},
{"exclude from", P_STRING, P_LOCAL, &sDefault.exclude_from, NULL,0},
{"exclude", P_STRING, P_LOCAL, &sDefault.exclude, NULL,0},
{"filter", P_STRING, P_LOCAL, &sDefault.filter, NULL,0},
{"gid", P_STRING, P_LOCAL, &sDefault.gid, NULL,0},
{"hosts allow", P_STRING, P_LOCAL, &sDefault.hosts_allow, NULL,0},
{"hosts deny", P_STRING, P_LOCAL, &sDefault.hosts_deny, NULL,0},
{"ignore errors", P_BOOL, P_LOCAL, &sDefault.ignore_errors, NULL,0},
{"ignore nonreadable",P_BOOL, P_LOCAL, &sDefault.ignore_nonreadable,NULL,0},
{"include from", P_STRING, P_LOCAL, &sDefault.include_from, NULL,0},
{"include", P_STRING, P_LOCAL, &sDefault.include, NULL,0},
{"incoming chmod", P_STRING, P_LOCAL, &sDefault.incoming_chmod, NULL,0},
{"list", P_BOOL, P_LOCAL, &sDefault.list, NULL,0},
{"lock file", P_STRING, P_LOCAL, &sDefault.lock_file, NULL,0},
{"log file", P_STRING, P_LOCAL, &sDefault.log_file, NULL,0},
{"log format", P_STRING, P_LOCAL, &sDefault.log_format, NULL,0},
{"max connections", P_INTEGER,P_LOCAL, &sDefault.max_connections, NULL,0},
{"max verbosity", P_INTEGER,P_LOCAL, &sDefault.max_verbosity, NULL,0},
{"name", P_STRING, P_LOCAL, &sDefault.name, NULL,0},
{"outgoing chmod", P_STRING, P_LOCAL, &sDefault.outgoing_chmod, NULL,0},
{"path", P_PATH, P_LOCAL, &sDefault.path, NULL,0},
{"timeout", P_INTEGER, P_LOCAL, &sDefault.timeout, NULL, 0},
{"max connections", P_INTEGER, P_LOCAL, &sDefault.max_connections,NULL, 0},
{"max verbosity", P_INTEGER, P_LOCAL, &sDefault.max_verbosity,NULL, 0},
{"name", P_STRING, P_LOCAL, &sDefault.name, NULL, 0},
{"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL, 0},
{"lock file", P_STRING, P_LOCAL, &sDefault.lock_file, NULL, 0},
{"path", P_PATH, P_LOCAL, &sDefault.path, NULL, 0},
{"read only", P_BOOL, P_LOCAL, &sDefault.read_only, NULL, 0},
{"write only", P_BOOL, P_LOCAL, &sDefault.write_only, NULL, 0},
{"list", P_BOOL, P_LOCAL, &sDefault.list, NULL, 0},
{"use chroot", P_BOOL, P_LOCAL, &sDefault.use_chroot, NULL, 0},
{"ignore nonreadable",P_BOOL, P_LOCAL, &sDefault.ignore_nonreadable, NULL, 0},
{"uid", P_STRING, P_LOCAL, &sDefault.uid, NULL, 0},
{"gid", P_STRING, P_LOCAL, &sDefault.gid, NULL, 0},
{"hosts allow", P_STRING, P_LOCAL, &sDefault.hosts_allow, NULL, 0},
{"hosts deny", P_STRING, P_LOCAL, &sDefault.hosts_deny, NULL, 0},
{"auth users", P_STRING, P_LOCAL, &sDefault.auth_users, NULL, 0},
{"secrets file", P_STRING, P_LOCAL, &sDefault.secrets_file,NULL, 0},
{"strict modes", P_BOOL, P_LOCAL, &sDefault.strict_modes,NULL, 0},
{"filter", P_STRING, P_LOCAL, &sDefault.filter, NULL, 0},
{"exclude", P_STRING, P_LOCAL, &sDefault.exclude, NULL, 0},
{"exclude from", P_STRING, P_LOCAL, &sDefault.exclude_from,NULL, 0},
{"include", P_STRING, P_LOCAL, &sDefault.include, NULL, 0},
{"include from", P_STRING, P_LOCAL, &sDefault.include_from,NULL, 0},
{"transfer logging", P_BOOL, P_LOCAL, &sDefault.transfer_logging,NULL,0},
{"ignore errors", P_BOOL, P_LOCAL, &sDefault.ignore_errors,NULL,0},
{"log format", P_STRING, P_LOCAL, &sDefault.log_format, NULL, 0},
{"refuse options", P_STRING, P_LOCAL, &sDefault.refuse_options,NULL, 0},
{"dont compress", P_STRING, P_LOCAL, &sDefault.dont_compress,NULL, 0},
#ifdef HAVE_PUTENV
{"post-xfer exec", P_STRING, P_LOCAL, &sDefault.postxfer_exec, NULL,0},
{"pre-xfer exec", P_STRING, P_LOCAL, &sDefault.prexfer_exec, NULL,0},
{"pre-xfer exec", P_STRING, P_LOCAL, &sDefault.prexfer_exec, NULL, 0},
{"post-xfer exec", P_STRING, P_LOCAL, &sDefault.postxfer_exec,NULL, 0},
#endif
{"read only", P_BOOL, P_LOCAL, &sDefault.read_only, NULL,0},
{"refuse options", P_STRING, P_LOCAL, &sDefault.refuse_options, NULL,0},
{"secrets file", P_STRING, P_LOCAL, &sDefault.secrets_file, NULL,0},
{"strict modes", P_BOOL, P_LOCAL, &sDefault.strict_modes, NULL,0},
{"syslog facility", P_ENUM, P_LOCAL, &sDefault.syslog_facility,enum_facilities,0},
{"temp dir", P_PATH, P_LOCAL, &sDefault.temp_dir, NULL,0},
{"timeout", P_INTEGER,P_LOCAL, &sDefault.timeout, NULL,0},
{"transfer logging", P_BOOL, P_LOCAL, &sDefault.transfer_logging, NULL,0},
{"uid", P_STRING, P_LOCAL, &sDefault.uid, NULL,0},
{"use chroot", P_BOOL, P_LOCAL, &sDefault.use_chroot, NULL,0},
{"write only", P_BOOL, P_LOCAL, &sDefault.write_only, NULL,0},
{NULL, P_BOOL, P_NONE, NULL, NULL,0}
{NULL, P_BOOL, P_NONE, NULL, NULL, 0}
};
/***************************************************************************
* Initialise the global parameter structure.
Initialise the global parameter structure.
***************************************************************************/
static void init_globals(void)
{
memset(&Globals, 0, sizeof Globals);
#ifdef LOG_DAEMON
Globals.syslog_facility = LOG_DAEMON;
#endif
}
/***************************************************************************
* Initialise the sDefault parameter structure.
Initialise the sDefault parameter structure.
***************************************************************************/
static void init_locals(void)
{
@@ -375,51 +353,45 @@ static void init_locals(void)
int fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);}
FN_GLOBAL_STRING(lp_bind_address, &Globals.bind_address)
FN_GLOBAL_STRING(lp_motd_file, &Globals.motd_file)
FN_GLOBAL_STRING(lp_log_file, &Globals.log_file)
FN_GLOBAL_STRING(lp_pid_file, &Globals.pid_file)
FN_GLOBAL_STRING(lp_socket_options, &Globals.socket_options)
FN_GLOBAL_INTEGER(lp_syslog_facility, &Globals.syslog_facility)
FN_GLOBAL_INTEGER(lp_rsync_port, &Globals.rsync_port)
FN_GLOBAL_STRING(lp_bind_address, &Globals.bind_address)
FN_LOCAL_STRING(lp_auth_users, auth_users)
FN_LOCAL_STRING(lp_name, name)
FN_LOCAL_STRING(lp_comment, comment)
FN_LOCAL_STRING(lp_dont_compress, dont_compress)
FN_LOCAL_STRING(lp_exclude, exclude)
FN_LOCAL_STRING(lp_exclude_from, exclude_from)
FN_LOCAL_STRING(lp_filter, filter)
FN_LOCAL_STRING(lp_path, path)
FN_LOCAL_STRING(lp_lock_file, lock_file)
FN_LOCAL_BOOL(lp_read_only, read_only)
FN_LOCAL_BOOL(lp_write_only, write_only)
FN_LOCAL_BOOL(lp_list, list)
FN_LOCAL_BOOL(lp_use_chroot, use_chroot)
FN_LOCAL_BOOL(lp_transfer_logging, transfer_logging)
FN_LOCAL_BOOL(lp_ignore_errors, ignore_errors)
FN_LOCAL_BOOL(lp_ignore_nonreadable, ignore_nonreadable)
FN_LOCAL_STRING(lp_uid, uid)
FN_LOCAL_STRING(lp_gid, gid)
FN_LOCAL_STRING(lp_hosts_allow, hosts_allow)
FN_LOCAL_STRING(lp_hosts_deny, hosts_deny)
FN_LOCAL_STRING(lp_auth_users, auth_users)
FN_LOCAL_STRING(lp_secrets_file, secrets_file)
FN_LOCAL_BOOL(lp_strict_modes, strict_modes)
FN_LOCAL_STRING(lp_filter, filter)
FN_LOCAL_STRING(lp_exclude, exclude)
FN_LOCAL_STRING(lp_exclude_from, exclude_from)
FN_LOCAL_STRING(lp_include, include)
FN_LOCAL_STRING(lp_include_from, include_from)
FN_LOCAL_STRING(lp_incoming_chmod, incoming_chmod)
FN_LOCAL_STRING(lp_lock_file, lock_file)
FN_LOCAL_STRING(lp_log_file, log_file)
FN_LOCAL_STRING(lp_log_format, log_format)
FN_LOCAL_STRING(lp_name, name)
FN_LOCAL_STRING(lp_outgoing_chmod, outgoing_chmod)
FN_LOCAL_STRING(lp_path, path)
FN_LOCAL_STRING(lp_postxfer_exec, postxfer_exec)
FN_LOCAL_STRING(lp_prexfer_exec, prexfer_exec)
FN_LOCAL_STRING(lp_refuse_options, refuse_options)
FN_LOCAL_STRING(lp_secrets_file, secrets_file)
FN_LOCAL_INTEGER(lp_syslog_facility, syslog_facility)
FN_LOCAL_STRING(lp_temp_dir, temp_dir)
FN_LOCAL_STRING(lp_uid, uid)
FN_LOCAL_STRING(lp_dont_compress, dont_compress)
FN_LOCAL_STRING(lp_prexfer_exec, prexfer_exec)
FN_LOCAL_STRING(lp_postxfer_exec, postxfer_exec)
FN_LOCAL_INTEGER(lp_timeout, timeout)
FN_LOCAL_INTEGER(lp_max_connections, max_connections)
FN_LOCAL_INTEGER(lp_max_verbosity, max_verbosity)
FN_LOCAL_INTEGER(lp_timeout, timeout)
FN_LOCAL_BOOL(lp_ignore_errors, ignore_errors)
FN_LOCAL_BOOL(lp_ignore_nonreadable, ignore_nonreadable)
FN_LOCAL_BOOL(lp_list, list)
FN_LOCAL_BOOL(lp_read_only, read_only)
FN_LOCAL_BOOL(lp_strict_modes, strict_modes)
FN_LOCAL_BOOL(lp_transfer_logging, transfer_logging)
FN_LOCAL_BOOL(lp_use_chroot, use_chroot)
FN_LOCAL_BOOL(lp_write_only, write_only)
/* local prototypes */
static int strwicmp(char *psz1, char *psz2);
@@ -432,7 +404,7 @@ static BOOL do_section(char *sectionname);
/***************************************************************************
* initialise a service to the defaults
initialise a service to the defaults
***************************************************************************/
static void init_service(service *pservice)
{
@@ -466,8 +438,8 @@ static void string_set(char **s, const char *v)
/***************************************************************************
* add a new service to the services array initialising it with the given
* service
add a new service to the services array initialising it with the given
service
***************************************************************************/
static int add_a_service(service *pservice, char *name)
{
@@ -506,7 +478,7 @@ static int add_a_service(service *pservice, char *name)
}
/***************************************************************************
* Do a case-insensitive, whitespace-ignoring string compare.
Do a case-insensitive, whitespace-ignoring string compare.
***************************************************************************/
static int strwicmp(char *psz1, char *psz2)
{
@@ -538,8 +510,8 @@ static int strwicmp(char *psz1, char *psz2)
}
/***************************************************************************
* Map a parameter's string representation to something we can use.
* Returns False if the parameter string is not recognised, else TRUE.
Map a parameter's string representation to something we can use.
Returns False if the parameter string is not recognised, else TRUE.
***************************************************************************/
static int map_parameter(char *parmname)
{
@@ -558,9 +530,9 @@ static int map_parameter(char *parmname)
/***************************************************************************
* Set a boolean variable from the text value stored in the passed string.
* Returns True in success, False if the passed string does not correctly
* represent a boolean.
Set a boolean variable from the text value stored in the passed string.
Returns True in success, False if the passed string does not correctly
represent a boolean.
***************************************************************************/
static BOOL set_boolean(BOOL *pb, char *parmvalue)
{
@@ -586,7 +558,7 @@ static BOOL set_boolean(BOOL *pb, char *parmvalue)
}
/***************************************************************************
* Find a service by name. Otherwise works like get_service.
Find a service by name. Otherwise works like get_service.
***************************************************************************/
static int getservicebyname(char *name, service *pserviceDest)
{
@@ -606,7 +578,8 @@ static int getservicebyname(char *name, service *pserviceDest)
/***************************************************************************
* Copy a service structure to another
Copy a service structure to another
***************************************************************************/
static void copy_service(service *pserviceDest,
service *pserviceSource)
@@ -651,8 +624,8 @@ static void copy_service(service *pserviceDest,
/***************************************************************************
* Process a parameter for a particular service number. If snum < 0
* then assume we are in the globals
Process a parameter for a particular service number. If snum < 0
then assume we are in the globals
***************************************************************************/
static BOOL lp_do_parameter(int snum, char *parmname, char *parmvalue)
{
@@ -743,7 +716,7 @@ static BOOL lp_do_parameter(int snum, char *parmname, char *parmvalue)
}
/***************************************************************************
* Process a parameter.
Process a parameter.
***************************************************************************/
static BOOL do_parameter(char *parmname, char *parmvalue)
{
@@ -751,9 +724,9 @@ static BOOL do_parameter(char *parmname, char *parmvalue)
}
/***************************************************************************
* Process a new section (service). At this stage all sections are services.
* Later we'll have special sections that permit server parameters to be set.
* Returns True on success, False on failure.
Process a new section (service). At this stage all sections are services.
Later we'll have special sections that permit server parameters to be set.
Returns True on success, False on failure.
***************************************************************************/
static BOOL do_section(char *sectionname)
{
@@ -798,12 +771,13 @@ static BOOL do_section(char *sectionname)
/***************************************************************************
* Load the services array from the services file. Return True on success,
* False on failure.
Load the services array from the services file. Return True on success,
False on failure.
***************************************************************************/
BOOL lp_load(char *pszFname, int globals_only)
{
extern int am_server;
extern int am_daemon;
extern int am_root;
pstring n2;
BOOL bRetval;
@@ -816,7 +790,7 @@ BOOL lp_load(char *pszFname, int globals_only)
if (pszFname)
pstrcpy(n2,pszFname);
else if (am_server && !am_root)
else if (am_server && am_daemon && !am_root)
pstrcpy(n2,RSYNCD_USERCONF);
else
pstrcpy(n2,RSYNCD_SYSCONF);
@@ -830,7 +804,7 @@ BOOL lp_load(char *pszFname, int globals_only)
/***************************************************************************
* return the max number of services
return the max number of services
***************************************************************************/
int lp_numservices(void)
{
@@ -838,10 +812,10 @@ int lp_numservices(void)
}
/***************************************************************************
* Return the number of the service with the given name, or -1 if it doesn't
* exist. Note that this is a DIFFERENT ANIMAL from the internal function
* getservicebyname()! This works ONLY if all services have been loaded, and
* does not copy the found service.
Return the number of the service with the given name, or -1 if it doesn't
exist. Note that this is a DIFFERENT ANIMAL from the internal function
getservicebyname()! This works ONLY if all services have been loaded, and
does not copy the found service.
***************************************************************************/
int lp_number(char *name)
{

430
log.c
View File

@@ -1,29 +1,31 @@
/*
* Logging and utility functions.
*
* Copyright (C) 1998-2001 Andrew Tridgell <tridge@samba.org>
* Copyright (C) 2000-2001 Martin Pool <mbp@samba.org>
* Copyright (C) 2003, 2004, 2005, 2006 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
/* -*- c-file-style: "linux"; -*-
Copyright (C) 1998-2001 by Andrew Tridgell <tridge@samba.org>
Copyright (C) 2000-2001 by Martin Pool <mbp@samba.org>
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
Logging and utility functions.
tridge, May 1998
Mapping to human-readable messages added by Martin Pool
<mbp@samba.org>, Oct 2000.
*/
#include "rsync.h"
#if defined HAVE_ICONV_OPEN && defined HAVE_ICONV_H
#include <iconv.h>
#endif
extern int verbose;
extern int dry_run;
@@ -34,27 +36,17 @@ extern int local_server;
extern int quiet;
extern int module_id;
extern int msg_fd_out;
extern int allow_8bit_chars;
extern int protocol_version;
extern int preserve_times;
extern int stdout_format_has_i;
extern int stdout_format_has_o_or_i;
extern int logfile_format_has_i;
extern int logfile_format_has_o_or_i;
extern mode_t orig_umask;
extern int log_format_has_o_or_i;
extern int daemon_log_format_has_o_or_i;
extern char *auth_user;
extern char *stdout_format;
extern char *logfile_format;
extern char *logfile_name;
#if defined HAVE_ICONV_OPEN && defined HAVE_ICONV_H
extern iconv_t ic_chck;
#endif
extern char curr_dir[];
extern unsigned int module_dirlen;
extern char *log_format;
static int log_initialised;
static int logfile_was_closed;
static FILE *logfile_fp;
static char *logfname;
static FILE *logfile;
struct stats stats;
int log_got_error = 0;
@@ -73,11 +65,8 @@ struct {
{ RERR_STREAMIO , "error in rsync protocol data stream" },
{ RERR_MESSAGEIO , "errors with program diagnostics" },
{ RERR_IPC , "error in IPC code" },
{ RERR_CRASHED , "sibling process crashed" },
{ RERR_TERMINATED , "sibling process terminated abnormally" },
{ RERR_SIGNAL1 , "received SIGUSR1" },
{ RERR_SIGNAL , "received SIGINT, SIGTERM, or SIGHUP" },
{ RERR_WAITCHILD , "waitpid() failed" },
{ RERR_SIGNAL , "received SIGUSR1 or SIGINT" },
{ RERR_WAITCHILD , "some error returned by waitpid()" },
{ RERR_MALLOC , "error allocating core memory buffers" },
{ RERR_PARTIAL , "some files could not be transferred" },
{ RERR_VANISHED , "some files vanished before they could be transferred" },
@@ -90,6 +79,8 @@ struct {
{ 0, NULL }
};
/*
* Map from rsync error code to name, or return NULL.
*/
@@ -103,14 +94,15 @@ static char const *rerr_name(int code)
return NULL;
}
static void logit(int priority, char *buf)
{
if (logfile_was_closed)
logfile_reopen();
if (logfile_fp) {
fprintf(logfile_fp, "%s [%d] %s",
if (logfile) {
fprintf(logfile,"%s [%d] %s",
timestring(time(NULL)), (int)getpid(), buf);
fflush(logfile_fp);
fflush(logfile);
} else {
syslog(priority, "%s", buf);
}
@@ -130,7 +122,7 @@ static void syslog_init()
#endif
#ifdef LOG_DAEMON
openlog("rsyncd", options, lp_syslog_facility(module_id));
openlog("rsyncd", options, lp_syslog_facility());
#else
openlog("rsyncd", options);
#endif
@@ -142,50 +134,37 @@ static void syslog_init()
static void logfile_open(void)
{
mode_t old_umask = umask(022 | orig_umask);
logfile_fp = fopen(logfile_name, "a");
extern int orig_umask;
int old_umask = umask(022 | orig_umask);
logfile = fopen(logfname, "a");
umask(old_umask);
if (!logfile_fp) {
if (!logfile) {
int fopen_errno = errno;
/* Rsync falls back to using syslog on failure. */
syslog_init();
rsyserr(FERROR, fopen_errno,
"failed to open log-file %s", logfile_name);
"failed to open log-file %s", logfname);
rprintf(FINFO, "Ignoring \"log file\" setting.\n");
}
}
void log_init(int restart)
void log_init(void)
{
if (log_initialised) {
if (!restart)
return;
if (strcmp(logfile_name, lp_log_file(module_id)) != 0) {
if (logfile_fp) {
fclose(logfile_fp);
logfile_fp = NULL;
} else
closelog();
logfile_name = NULL;
} else if (*logfile_name)
return; /* unchanged, non-empty "log file" names */
else if (lp_syslog_facility(-1) != lp_syslog_facility(module_id))
closelog();
else
return; /* unchanged syslog settings */
} else
log_initialised = 1;
time_t t;
/* This looks pointless, but it is needed in order for the
if (log_initialised)
return;
log_initialised = 1;
/* this looks pointless, but it is needed in order for the
* C library on some systems to fetch the timezone info
* before the chroot. */
timestring(time(NULL));
* before the chroot */
t = time(NULL);
localtime(&t);
/* Optionally use a log file instead of syslog. (Non-daemon
* rsyncs will have already set logfile_name, as needed.) */
if (am_daemon && !logfile_name)
logfile_name = lp_log_file(module_id);
if (logfile_name && *logfile_name)
/* optionally use a log file instead of syslog */
logfname = lp_log_file();
if (logfname && *logfname)
logfile_open();
else
syslog_init();
@@ -193,10 +172,10 @@ void log_init(int restart)
void logfile_close(void)
{
if (logfile_fp) {
if (logfile) {
logfile_was_closed = 1;
fclose(logfile_fp);
logfile_fp = NULL;
fclose(logfile);
logfile = NULL;
}
}
@@ -208,51 +187,30 @@ void logfile_reopen(void)
}
}
static void filtered_fwrite(FILE *f, const char *buf, int len, int use_isprint)
{
const char *s, *end = buf + len;
for (s = buf; s < end; s++) {
if ((s < end - 4
&& *s == '\\' && s[1] == '#'
&& isdigit(*(uchar*)(s+2))
&& isdigit(*(uchar*)(s+3))
&& isdigit(*(uchar*)(s+4)))
|| (*s != '\t'
&& ((use_isprint && !isprint(*(uchar*)s))
|| *(uchar*)s < ' '))) {
if (s != buf && fwrite(buf, s - buf, 1, f) != 1)
exit_cleanup(RERR_MESSAGEIO);
fprintf(f, "\\#%03o", *(uchar*)s);
buf = s + 1;
}
}
if (buf != end && fwrite(buf, end - buf, 1, f) != 1)
exit_cleanup(RERR_MESSAGEIO);
}
/* this is the underlying (unformatted) rsync debugging function. Call
* it with FINFO, FERROR or FLOG. Note: recursion can happen with
* certain fatal conditions. */
* it with FINFO, FERROR or FLOG */
void rwrite(enum logcode code, char *buf, int len)
{
int trailing_CR_or_NL;
FILE *f = NULL;
/* recursion can happen with certain fatal conditions */
if (quiet && code == FINFO)
return;
if (len < 0)
exit_cleanup(RERR_MESSAGEIO);
buf[len] = 0;
if (am_server && msg_fd_out >= 0) {
/* Pass the message to our sibling. */
send_msg((enum msgcode)code, buf, len);
return;
}
if (code == FSOCKERR) /* This gets simplified for a non-sibling. */
code = FERROR;
if (code == FCLIENT)
code = FINFO;
else if (am_daemon || logfile_name) {
else if (am_daemon) {
static int in_block;
char msg[2048];
int priority = code == FERROR ? LOG_WARNING : LOG_INFO;
@@ -261,22 +219,19 @@ void rwrite(enum logcode code, char *buf, int len)
return;
in_block = 1;
if (!log_initialised)
log_init(0);
log_init();
strlcpy(msg, buf, MIN((int)sizeof msg, len + 1));
logit(priority, msg);
in_block = 0;
if (code == FLOG || (am_daemon && !am_server))
if (code == FLOG || !am_server)
return;
} else if (code == FLOG)
return;
if (quiet && code != FERROR)
return;
if (am_server) {
/* Pass the message to the non-server side. */
if (send_msg((enum msgcode)code, buf, len))
if (io_multiplex_write((enum msgcode)code, buf, len))
return;
if (am_daemon) {
/* TODO: can we send the error to the user somehow? */
@@ -284,58 +239,31 @@ void rwrite(enum logcode code, char *buf, int len)
}
}
switch (code) {
case FERROR:
if (code == FERROR) {
log_got_error = 1;
f = stderr;
break;
case FINFO:
}
if (code == FINFO)
f = am_server ? stderr : stdout;
break;
default:
if (!f)
exit_cleanup(RERR_MESSAGEIO);
}
trailing_CR_or_NL = len && (buf[len-1] == '\n' || buf[len-1] == '\r')
? buf[--len] : 0;
if (fwrite(buf, len, 1, f) != 1)
exit_cleanup(RERR_MESSAGEIO);
#if defined HAVE_ICONV_OPEN && defined HAVE_ICONV_H
if (ic_chck != (iconv_t)-1) {
char convbuf[1024];
char *in_buf = buf, *out_buf = convbuf;
size_t in_cnt = len, out_cnt = sizeof convbuf - 1;
iconv(ic_chck, NULL, 0, NULL, 0);
while (iconv(ic_chck, &in_buf,&in_cnt,
&out_buf,&out_cnt) == (size_t)-1) {
if (out_buf != convbuf) {
filtered_fwrite(f, convbuf, out_buf - convbuf, 0);
out_buf = convbuf;
out_cnt = sizeof convbuf - 1;
}
if (errno == E2BIG)
continue;
fprintf(f, "\\#%03o", *(uchar*)in_buf++);
in_cnt--;
}
if (out_buf != convbuf)
filtered_fwrite(f, convbuf, out_buf - convbuf, 0);
} else
#endif
filtered_fwrite(f, buf, len, !allow_8bit_chars);
if (trailing_CR_or_NL) {
fputc(trailing_CR_or_NL, f);
if (buf[len-1] == '\r' || buf[len-1] == '\n')
fflush(f);
}
}
/* This is the rsync debugging function. Call it with FINFO, FERROR or
* FLOG. */
void rprintf(enum logcode code, const char *format, ...)
{
va_list ap;
char buf[BIGPATHBUFLEN];
char buf[MAXPATHLEN+512];
size_t len;
va_start(ap, format);
@@ -346,7 +274,7 @@ void rprintf(enum logcode code, const char *format, ...)
* truncate the resulting string. (Note that configure ensures
* that we have a vsnprintf() that doesn't ever return -1.) */
if (len > sizeof buf - 1) {
static const char ellipsis[] = "[...]";
const char ellipsis[] = "[...]";
/* Reset length, and zero-terminate the end of our buffer */
len = sizeof buf - 1;
@@ -362,7 +290,7 @@ void rprintf(enum logcode code, const char *format, ...)
* If the input format string has a trailing newline,
* we copy it into that extra null; if it doesn't, well,
* all we lose is one byte. */
memcpy(buf+len-sizeof ellipsis, ellipsis, sizeof ellipsis);
strncpy(buf+len-sizeof ellipsis, ellipsis, sizeof ellipsis);
if (format[strlen(format)-1] == '\n') {
buf[len-1] = '\n';
}
@@ -371,6 +299,7 @@ void rprintf(enum logcode code, const char *format, ...)
rwrite(code, buf, len);
}
/* This is like rprintf, but it also tries to print some
* representation of the error code. Normally errcode = errno.
*
@@ -382,10 +311,10 @@ void rprintf(enum logcode code, const char *format, ...)
void rsyserr(enum logcode code, int errcode, const char *format, ...)
{
va_list ap;
char buf[BIGPATHBUFLEN];
char buf[MAXPATHLEN+512];
size_t len;
strlcpy(buf, RSYNC_NAME ": ", sizeof buf);
strcpy(buf, RSYNC_NAME ": ");
len = (sizeof RSYNC_NAME ": ") - 1;
va_start(ap, format);
@@ -402,22 +331,39 @@ void rsyserr(enum logcode code, int errcode, const char *format, ...)
rwrite(code, buf, len);
}
void rflush(enum logcode code)
{
FILE *f = NULL;
if (am_daemon || code == FLOG)
if (am_daemon) {
return;
}
if (code == FERROR || am_server)
if (code == FLOG) {
return;
}
if (code == FERROR) {
f = stderr;
else
f = stdout;
}
if (code == FINFO) {
if (am_server)
f = stderr;
else
f = stdout;
}
if (!f) exit_cleanup(RERR_MESSAGEIO);
fflush(f);
}
/* A generic logging routine for send/recv, with parameter substitiution. */
/* a generic logging routine for send/recv, with parameter
* substitiution */
static void log_formatted(enum logcode code, char *format, char *op,
struct file_struct *file, struct stats *initial_stats,
int iflags, char *hlink)
@@ -453,114 +399,66 @@ static void log_formatted(enum logcode code, char *format, char *op,
n = NULL;
switch (*p) {
case 'h':
if (am_daemon)
n = client_name(0);
break;
case 'a':
if (am_daemon)
n = client_addr(0);
break;
case 'h': if (am_daemon) n = client_name(0); break;
case 'a': if (am_daemon) n = client_addr(0); break;
case 'l':
strlcat(fmt, ".0f", sizeof fmt);
snprintf(buf2, sizeof buf2, fmt,
(double)file->length);
n = buf2;
break;
case 'U':
strlcat(fmt, "ld", sizeof fmt);
snprintf(buf2, sizeof buf2, fmt,
(long)file->uid);
n = buf2;
break;
case 'G':
if (file->gid == GID_NONE)
n = "DEFAULT";
else {
strlcat(fmt, "ld", sizeof fmt);
snprintf(buf2, sizeof buf2, fmt,
(long)file->gid);
n = buf2;
}
break;
case 'p':
strlcat(fmt, "ld", sizeof fmt);
snprintf(buf2, sizeof buf2, fmt,
(long)getpid());
n = buf2;
break;
case 'M':
n = timestring(file->modtime);
{
char *cp = n;
while ((cp = strchr(cp, ' ')) != NULL)
*cp = '-';
}
break;
case 'B':
n = buf2 + MAXPATHLEN - PERMSTRING_SIZE;
permstring(n - 1, file->mode); /* skip the type char */
break;
case 'o':
n = op;
break;
case 'o': n = op; break;
case 'f':
n = f_name(file, NULL);
n = safe_fname(f_name(file));
if (am_sender && file->dir.root) {
pathjoin(buf2, sizeof buf2,
file->dir.root, n);
clean_fname(buf2, 0);
/* The buffer from safe_fname() has more
* room than MAXPATHLEN, so this is safe. */
if (fmt[1])
strlcpy(n, buf2, MAXPATHLEN);
strcpy(n, buf2);
else
n = buf2;
} else if (*n != '/') {
pathjoin(buf2, sizeof buf2,
curr_dir + module_dirlen, n);
clean_fname(buf2, 0);
if (fmt[1])
strlcpy(n, buf2, MAXPATHLEN);
else
n = buf2;
} else
clean_fname(n, 0);
}
clean_fname(n, 0);
if (*n == '/')
n++;
break;
case 'n':
n = f_name(file, NULL);
if (S_ISDIR(file->mode))
strlcat(n, "/", MAXPATHLEN);
n = safe_fname(f_name(file));
if (S_ISDIR(file->mode)) {
/* The buffer from safe_fname() has more
* room than MAXPATHLEN, so this is safe. */
strcat(n, "/");
}
break;
case 'L':
if (hlink && *hlink) {
n = hlink;
strlcpy(buf2, " => ", sizeof buf2);
n = safe_fname(hlink);
strcpy(buf2, " => ");
} else if (S_ISLNK(file->mode) && file->u.link) {
n = file->u.link;
strlcpy(buf2, " -> ", sizeof buf2);
n = safe_fname(file->u.link);
strcpy(buf2, " -> ");
} else {
n = "";
if (!fmt[1])
break;
strlcpy(buf2, " ", sizeof buf2);
strcpy(buf2, " ");
}
strlcat(fmt, "s", sizeof fmt);
snprintf(buf2 + 4, sizeof buf2 - 4, fmt, n);
n = buf2;
break;
case 'm':
n = lp_name(module_id);
break;
case 't':
n = timestring(time(NULL));
break;
case 'P':
n = lp_path(module_id);
break;
case 'u':
n = auth_user;
break;
case 'm': n = lp_name(module_id); break;
case 't': n = timestring(time(NULL)); break;
case 'P': n = lp_path(module_id); break;
case 'u': n = auth_user; break;
case 'b':
if (am_sender) {
b = stats.total_written -
@@ -596,17 +494,17 @@ static void log_formatted(enum logcode code, char *format, char *op,
: !(iflags & ITEM_TRANSFER) ? '.'
: !local_server && *op == 's' ? '<' : '>';
n[1] = S_ISDIR(file->mode) ? 'd'
: IS_SPECIAL(file->mode) ? 'S'
: IS_DEVICE(file->mode) ? 'D'
: S_ISLNK(file->mode) ? 'L' : 'f';
n[2] = !(iflags & ITEM_REPORT_CHECKSUM) ? '.' : 'c';
n[3] = !(iflags & ITEM_REPORT_SIZE) ? '.' : 's';
n[4] = !(iflags & ITEM_REPORT_TIME) ? '.'
: !preserve_times || S_ISLNK(file->mode) ? 'T' : 't';
: !preserve_times || IS_DEVICE(file->mode)
|| S_ISLNK(file->mode) ? 'T' : 't';
n[5] = !(iflags & ITEM_REPORT_PERMS) ? '.' : 'p';
n[6] = !(iflags & ITEM_REPORT_OWNER) ? '.' : 'o';
n[7] = !(iflags & ITEM_REPORT_GROUP) ? '.' : 'g';
n[8] = '.';
n[8] = !(iflags & ITEM_REPORT_XATTRS) ? '.' : 'a';
n[9] = '\0';
if (iflags & (ITEM_IS_NEW|ITEM_MISSING_DATA)) {
@@ -614,8 +512,7 @@ static void log_formatted(enum logcode code, char *format, char *op,
int i;
for (i = 2; n[i]; i++)
n[i] = ch;
} else if (n[0] == '.' || n[0] == 'h'
|| (n[0] == 'c' && n[1] == 'f')) {
} else if (n[0] == '.' || n[0] == 'h') {
int i;
for (i = 2; n[i]; i++) {
if (n[i] != '.')
@@ -687,20 +584,17 @@ int log_format_has(const char *format, char esc)
return 0;
}
/* Log the transfer of a file. If the code is FCLIENT, the output just goes
* to stdout. If it is FLOG, it just goes to the log file. Otherwise we
* output to both. */
void log_item(enum logcode code, struct file_struct *file,
struct stats *initial_stats, int iflags, char *hlink)
/* log the transfer of a file */
void log_item(struct file_struct *file, struct stats *initial_stats,
int iflags, char *hlink)
{
char *s_or_r = am_sender ? "send" : "recv";
if (code != FLOG && stdout_format && !am_server) {
log_formatted(FCLIENT, stdout_format, s_or_r,
if (lp_transfer_logging(module_id)) {
log_formatted(FLOG, lp_log_format(module_id), s_or_r,
file, initial_stats, iflags, hlink);
}
if (code != FCLIENT && logfile_format && *logfile_format) {
log_formatted(FLOG, logfile_format, s_or_r,
} else if (log_format && !am_server) {
log_formatted(FINFO, log_format, s_or_r,
file, initial_stats, iflags, hlink);
}
}
@@ -709,18 +603,15 @@ void maybe_log_item(struct file_struct *file, int iflags, int itemizing,
char *buf)
{
int significant_flags = iflags & SIGNIFICANT_ITEM_FLAGS;
int see_item = itemizing && (significant_flags || *buf
|| stdout_format_has_i > 1 || (verbose > 1 && stdout_format_has_i));
int local_change = iflags & ITEM_LOCAL_CHANGE && significant_flags;
int see_item = itemizing && (significant_flags || *buf || verbose > 1);
int local_change = iflags & ITEM_LOCAL_CHANGE
&& (!(iflags & ITEM_XNAME_FOLLOWS) || significant_flags);
if (am_server) {
if (logfile_name && !dry_run && see_item
&& (significant_flags || logfile_format_has_i))
log_item(FLOG, file, &stats, iflags, buf);
if (am_daemon && !dry_run && see_item)
log_item(file, &stats, iflags, buf);
} else if (see_item || local_change || *buf
|| (S_ISDIR(file->mode) && significant_flags)) {
enum logcode code = significant_flags || logfile_format_has_i ? FINFO : FCLIENT;
log_item(code, file, &stats, iflags, buf);
}
|| (S_ISDIR(file->mode) && significant_flags))
log_item(file, &stats, iflags, buf);
}
void log_delete(char *fname, int mode)
@@ -732,25 +623,26 @@ void log_delete(char *fname, int mode)
file.mode = mode;
file.basename = fname;
if (!verbose && !stdout_format)
if (!verbose && !log_format)
;
else if (am_server && protocol_version >= 29 && len < MAXPATHLEN) {
if (S_ISDIR(mode))
len++; /* directories include trailing null */
send_msg(MSG_DELETED, fname, len);
} else {
fmt = stdout_format_has_o_or_i ? stdout_format : "deleting %n";
fmt = log_format_has_o_or_i ? log_format : "deleting %n";
log_formatted(FCLIENT, fmt, "del.", &file, &stats,
ITEM_DELETED, NULL);
}
if (!logfile_name || dry_run || !logfile_format)
if (!am_daemon || dry_run || !lp_transfer_logging(module_id))
return;
fmt = logfile_format_has_o_or_i ? logfile_format : "deleting %n";
fmt = daemon_log_format_has_o_or_i ? lp_log_format(module_id) : "deleting %n";
log_formatted(FLOG, fmt, "del.", &file, &stats, ITEM_DELETED, NULL);
}
/*
* Called when the transfer is interrupted for some reason.
*
@@ -773,11 +665,11 @@ void log_exit(int code, const char *file, int line)
/* VANISHED is not an error, only a warning */
if (code == RERR_VANISHED) {
rprintf(FINFO, "rsync warning: %s (code %d) at %s(%d) [%s=%s]\n",
name, code, file, line, who_am_i(), RSYNC_VERSION);
rprintf(FINFO, "rsync warning: %s (code %d) at %s(%d)\n",
name, code, file, line);
} else {
rprintf(FERROR, "rsync error: %s (code %d) at %s(%d) [%s=%s]\n",
name, code, file, line, who_am_i(), RSYNC_VERSION);
rprintf(FERROR, "rsync error: %s (code %d) at %s(%d)\n",
name, code, file, line);
}
}
}

552
main.c
View File

@@ -1,25 +1,23 @@
/*
* The startup routines, including main(), for rsync.
*
* Copyright (C) 1996-2001 Andrew Tridgell <tridge@samba.org>
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
* Copyright (C) 2003, 2004, 2005, 2006 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
/* -*- c-file-style: "linux" -*-
Copyright (C) 1996-2001 by Andrew Tridgell <tridge@samba.org>
Copyright (C) Paul Mackerras 1996
Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "rsync.h"
#if defined CONFIG_LOCALE && defined HAVE_LOCALE_H
@@ -35,24 +33,20 @@ extern int am_sender;
extern int am_generator;
extern int am_daemon;
extern int blocking_io;
extern int remove_source_files;
extern int remove_sent_files;
extern int daemon_over_rsh;
extern int need_messages_from_generator;
extern int kluge_around_eof;
extern int do_stats;
extern int log_got_error;
extern int module_id;
extern int orig_umask;
extern int copy_links;
extern int copy_dirlinks;
extern int keep_dirlinks;
extern int preserve_hard_links;
extern int protocol_version;
extern int recurse;
extern int relative_paths;
extern int sanitize_paths;
extern int curr_dir_depth;
extern int curr_dir_len;
extern int module_id;
extern int rsync_port;
extern int whole_file;
extern int read_batch;
@@ -63,35 +57,20 @@ extern int filesfrom_fd;
extern pid_t cleanup_child_pid;
extern struct stats stats;
extern char *filesfrom_host;
extern char *partial_dir;
extern char *basis_dir[];
extern char *rsync_path;
extern char *shell_cmd;
extern char *batch_name;
extern char curr_dir[MAXPATHLEN];
extern struct filter_list_struct server_filter_list;
int local_server = 0;
int new_root_dir = 0;
mode_t orig_umask = 0;
struct file_list *the_file_list;
/* There's probably never more than at most 2 outstanding child processes,
* but set it higher, just in case. */
#define MAXCHILDPROCS 7
#ifdef HAVE_SIGACTION
# ifdef HAVE_SIGPROCMASK
# define SIGACTMASK(n,h) SIGACTION(n,h), sigaddset(&sigmask,(n))
# else
# define SIGACTMASK(n,h) SIGACTION(n,h)
# endif
static struct sigaction sigact;
#endif
#define MAXCHILDPROCS 5
struct pid_status {
pid_t pid;
int status;
int status;
} pid_stat_table[MAXCHILDPROCS];
static time_t starttime, endtime;
@@ -99,58 +78,38 @@ static int64 total_read, total_written;
static void show_malloc_stats(void);
/* Works like waitpid(), but if we already harvested the child pid in our
* remember_children(), we succeed instead of returning an error. */
pid_t wait_process(pid_t pid, int *status_ptr, int flags)
{
pid_t waited_pid = waitpid(pid, status_ptr, flags);
if (waited_pid == -1 && errno == ECHILD) {
/* Status of requested child no longer available: check to
* see if it was processed by remember_children(). */
int cnt;
for (cnt = 0; cnt < MAXCHILDPROCS; cnt++) {
if (pid == pid_stat_table[cnt].pid) {
*status_ptr = pid_stat_table[cnt].status;
pid_stat_table[cnt].pid = 0;
return pid;
}
}
}
return waited_pid;
}
/* Wait for a process to exit, calling io_flush while waiting. */
static void wait_process_with_flush(pid_t pid, int *exit_code_ptr)
/****************************************************************************
wait for a process to exit, calling io_flush while waiting
****************************************************************************/
void wait_process(pid_t pid, int *status)
{
pid_t waited_pid;
int status;
int cnt;
while ((waited_pid = wait_process(pid, &status, WNOHANG)) == 0) {
while ((waited_pid = waitpid(pid, status, WNOHANG)) == 0) {
msleep(20);
io_flush(FULL_FLUSH);
}
if (waited_pid == -1 && errno == ECHILD) {
/* status of requested child no longer available.
* check to see if it was processed by the sigchld_handler.
*/
for (cnt = 0; cnt < MAXCHILDPROCS; cnt++) {
if (pid == pid_stat_table[cnt].pid) {
*status = pid_stat_table[cnt].status;
pid_stat_table[cnt].pid = 0;
break;
}
}
}
/* TODO: If the child exited on a signal, then log an
* appropriate error message. Perhaps we should also accept a
* message describing the purpose of the child. Also indicate
* this to the caller so that they know something went wrong. */
if (waited_pid < 0) {
rsyserr(FERROR, errno, "waitpid");
*exit_code_ptr = RERR_WAITCHILD;
} else if (!WIFEXITED(status)) {
#ifdef WCOREDUMP
if (WCOREDUMP(status))
*exit_code_ptr = RERR_CRASHED;
else
#endif
if (WIFSIGNALED(status))
*exit_code_ptr = RERR_TERMINATED;
else
*exit_code_ptr = RERR_WAITCHILD;
} else
*exit_code_ptr = WEXITSTATUS(status);
* this to the caller so that thhey know something went
* wrong. */
*status = WEXITSTATUS(*status);
}
/* This function gets called from all 3 processes. We want the client side
@@ -179,6 +138,7 @@ static void handle_stats(int f)
return;
if (am_daemon) {
log_exit(0, __FILE__, __LINE__);
if (f == -1 || !am_sender)
return;
}
@@ -199,7 +159,7 @@ static void handle_stats(int f)
/* this is the client */
if (f < 0 && !am_sender) /* e.g. when we got an empty file list. */
;
;
else if (!am_sender) {
/* Read the first two in opposite order because the meaning of
* read/write swaps when switching from sender to receiver. */
@@ -226,18 +186,17 @@ static void handle_stats(int f)
static void output_summary(void)
{
if (do_stats) {
rprintf(FCLIENT, "\n");
rprintf(FINFO,"Number of files: %d\n", stats.num_files);
rprintf(FINFO,"\nNumber of files: %d\n", stats.num_files);
rprintf(FINFO,"Number of files transferred: %d\n",
stats.num_transferred_files);
rprintf(FINFO,"Total file size: %s bytes\n",
human_num(stats.total_size));
rprintf(FINFO,"Total transferred file size: %s bytes\n",
human_num(stats.total_transferred_size));
rprintf(FINFO,"Literal data: %s bytes\n",
human_num(stats.literal_data));
rprintf(FINFO,"Matched data: %s bytes\n",
human_num(stats.matched_data));
rprintf(FINFO,"Total file size: %.0f bytes\n",
(double)stats.total_size);
rprintf(FINFO,"Total transferred file size: %.0f bytes\n",
(double)stats.total_transferred_size);
rprintf(FINFO,"Literal data: %.0f bytes\n",
(double)stats.literal_data);
rprintf(FINFO,"Matched data: %.0f bytes\n",
(double)stats.matched_data);
rprintf(FINFO,"File list size: %d\n", stats.flist_size);
if (stats.flist_buildtime) {
rprintf(FINFO,
@@ -247,20 +206,19 @@ static void output_summary(void)
"File list transfer time: %.3f seconds\n",
(double)stats.flist_xfertime / 1000);
}
rprintf(FINFO,"Total bytes sent: %s\n",
human_num(total_written));
rprintf(FINFO,"Total bytes received: %s\n",
human_num(total_read));
rprintf(FINFO,"Total bytes sent: %.0f\n",
(double)total_written);
rprintf(FINFO,"Total bytes received: %.0f\n",
(double)total_read);
}
if (verbose || do_stats) {
rprintf(FCLIENT, "\n");
rprintf(FINFO,
"sent %s bytes received %s bytes %s bytes/sec\n",
human_num(total_written), human_num(total_read),
human_dnum((total_written + total_read)/(0.5 + (endtime - starttime)), 2));
rprintf(FINFO, "total size is %s speedup is %.2f\n",
human_num(stats.total_size),
"\nsent %.0f bytes received %.0f bytes %.2f bytes/sec\n",
(double)total_written, (double)total_read,
(total_written + total_read)/(0.5 + (endtime - starttime)));
rprintf(FINFO, "total size is %.0f speedup is %.2f\n",
(double)stats.total_size,
(double)stats.total_size / (total_written+total_read));
}
@@ -279,8 +237,7 @@ static void show_malloc_stats(void)
mi = mallinfo();
rprintf(FCLIENT, "\n");
rprintf(FINFO, RSYNC_NAME "[%d] (%s%s%s) heap statistics:\n",
rprintf(FINFO, "\n" RSYNC_NAME "[%d] (%s%s%s) heap statistics:\n",
getpid(), am_server ? "server " : "",
am_daemon ? "daemon " : "", who_am_i());
rprintf(FINFO, " arena: %10ld (bytes from sbrk)\n",
@@ -316,11 +273,10 @@ static pid_t do_cmd(char *cmd, char *machine, char *user, char *path,
int i, argc = 0;
char *args[MAX_ARGS];
pid_t ret;
char *dir = NULL;
char *tok, *dir = NULL;
int dash_l_set = 0;
if (!read_batch && !local_server) {
char *t, *f, in_quote = '\0';
char *rsh_env = getenv(RSYNC_RSH_ENV);
if (!cmd)
cmd = rsh_env;
@@ -330,39 +286,13 @@ static pid_t do_cmd(char *cmd, char *machine, char *user, char *path,
if (!cmd)
goto oom;
for (t = f = cmd; *f; f++) {
if (*f == ' ')
continue;
for (tok = strtok(cmd, " "); tok; tok = strtok(NULL, " ")) {
/* Comparison leaves rooms for server_options(). */
if (argc >= MAX_ARGS - MAX_SERVER_ARGS) {
rprintf(FERROR, "internal: args[] overflowed in do_cmd()\n");
exit_cleanup(RERR_SYNTAX);
}
args[argc++] = t;
while (*f != ' ' || in_quote) {
if (!*f) {
if (in_quote) {
rprintf(FERROR,
"Missing trailing-%c in remote-shell command.\n",
in_quote);
exit_cleanup(RERR_SYNTAX);
}
f--;
break;
}
if (*f == '\'' || *f == '"') {
if (!in_quote) {
in_quote = *f++;
continue;
}
if (*f == in_quote && *++f != in_quote) {
in_quote = '\0';
continue;
}
}
*t++ = *f++;
}
*t++ = '\0';
args[argc++] = tok;
}
/* check to see if we've already been given '-l user' in
@@ -415,9 +345,10 @@ static pid_t do_cmd(char *cmd, char *machine, char *user, char *path,
args[argc] = NULL;
if (verbose > 3) {
rprintf(FINFO,"cmd=");
for (i = 0; i < argc; i++)
rprintf(FCLIENT, "cmd[%d]=%s ", i, args[i]);
rprintf(FCLIENT, "\n");
rprintf(FINFO, "%s ", safe_fname(args[i]));
rprintf(FINFO,"\n");
}
if (read_batch) {
@@ -444,163 +375,64 @@ static pid_t do_cmd(char *cmd, char *machine, char *user, char *path,
return ret;
oom:
oom:
out_of_memory("do_cmd");
return 0; /* not reached */
}
/* The receiving side operates in one of two modes:
*
* 1. it receives any number of files into a destination directory,
* placing them according to their names in the file-list.
*
* 2. it receives a single file and saves it using the name in the
* destination path instead of its file-list name. This requires a
* "local name" for writing out the destination file.
*
* So, our task is to figure out what mode/local-name we need.
* For mode 1, we change into the destination directory and return NULL.
* For mode 2, we change into the directory containing the destination
* file (if we aren't already there) and return the local-name. */
static char *get_local_name(struct file_list *flist, char *dest_path)
static char *get_local_name(struct file_list *flist,char *name)
{
STRUCT_STAT st;
int statret;
char *cp;
int e;
if (verbose > 2) {
rprintf(FINFO, "get_local_name count=%d %s\n",
flist->count, NS(dest_path));
}
if (verbose > 2)
rprintf(FINFO,"get_local_name count=%d %s\n",
flist->count, NS(name));
if (!dest_path || list_only)
if (!name)
return NULL;
/* See what currently exists at the destination. */
if ((statret = do_stat(dest_path, &st)) == 0) {
/* If the destination is a dir, enter it and use mode 1. */
if (do_stat(name,&st) == 0) {
if (S_ISDIR(st.st_mode)) {
if (!push_dir(dest_path, 0)) {
if (!push_dir(name)) {
rsyserr(FERROR, errno, "push_dir#1 %s failed",
full_fname(dest_path));
full_fname(name));
exit_cleanup(RERR_FILESELECT);
}
return NULL;
}
if (flist->count > 1) {
rprintf(FERROR,
"ERROR: destination must be a directory when"
" copying more than 1 file\n");
rprintf(FERROR,"ERROR: destination must be a directory when copying more than 1 file\n");
exit_cleanup(RERR_FILESELECT);
}
/* Caution: flist->count could be 0! */
if (flist->count == 1 && S_ISDIR(flist->files[0]->mode)) {
rprintf(FERROR,
"ERROR: cannot overwrite non-directory"
" with a directory\n");
exit_cleanup(RERR_FILESELECT);
}
} else if (errno != ENOENT) {
/* If we don't know what's at the destination, fail. */
rsyserr(FERROR, errno, "ERROR: cannot stat destination %s",
full_fname(dest_path));
exit_cleanup(RERR_FILESELECT);
return name;
}
cp = strrchr(dest_path, '/');
if (flist->count <= 1 && ((e = strlen(name)) <= 1 || name[e-1] != '/'))
return name;
/* If we need a destination directory because the transfer is not
* of a single non-directory or the user has requested one via a
* destination path ending in a slash, create one and use mode 1. */
if (flist->count > 1 || (cp && !cp[1])) {
/* Lop off the final slash (if any). */
if (cp && !cp[1])
*cp = '\0';
if (statret == 0) {
rprintf(FERROR,
"ERROR: destination path is not a directory\n");
exit_cleanup(RERR_SYNTAX);
}
if (mkdir_defmode(dest_path) != 0) {
rsyserr(FERROR, errno, "mkdir %s failed",
full_fname(dest_path));
exit_cleanup(RERR_FILEIO);
}
new_root_dir = 1;
if (verbose)
rprintf(FINFO, "created directory %s\n", dest_path);
if (dry_run) {
/* Indicate that dest dir doesn't really exist. */
dry_run++;
}
if (!push_dir(dest_path, dry_run > 1)) {
rsyserr(FERROR, errno, "push_dir#2 %s failed",
full_fname(dest_path));
exit_cleanup(RERR_FILESELECT);
}
if (do_mkdir(name,0777 & ~orig_umask) != 0) {
rsyserr(FERROR, errno, "mkdir %s failed", full_fname(name));
exit_cleanup(RERR_FILEIO);
}
if (verbose > 0)
rprintf(FINFO, "created directory %s\n", safe_fname(name));
if (dry_run) {
dry_run++;
return NULL;
}
/* Otherwise, we are writing a single file, possibly on top of an
* existing non-directory. Change to the item's parent directory
* (if it has a path component), return the basename of the
* destination file as the local name, and use mode 2. */
if (!cp)
return dest_path;
if (cp == dest_path)
dest_path = "/";
*cp = '\0';
if (!push_dir(dest_path, 0)) {
rsyserr(FERROR, errno, "push_dir#3 %s failed",
full_fname(dest_path));
if (!push_dir(name)) {
rsyserr(FERROR, errno, "push_dir#2 %s failed",
full_fname(name));
exit_cleanup(RERR_FILESELECT);
}
*cp = '/';
return cp + 1;
return NULL;
}
/* Call this if the destination dir (which is assumed to be in curr_dir)
* does not yet exist and we can't create it due to being in dry-run
* mode. We'll fix dirs that can be relative to the non-existent dir. */
static void fix_basis_dirs(void)
{
char **dir, *new, *slash;
int len;
if (dry_run <= 1)
return;
slash = strrchr(curr_dir, '/');
for (dir = basis_dir; *dir; dir++) {
if (**dir == '/')
continue;
len = curr_dir_len + 1 + strlen(*dir) + 1;
if (!(new = new_array(char, len)))
out_of_memory("fix_basis_dirs");
if (slash && strncmp(*dir, "../", 3) == 0) {
/* We want to remove only one leading "../" prefix for
* the directory we couldn't create in dry-run mode:
* this ensures that any other ".." references get
* evaluated the same as they would for a live copy. */
*slash = '\0';
pathjoin(new, len, curr_dir, *dir + 3);
*slash = '/';
} else
pathjoin(new, len, curr_dir, *dir);
*dir = new;
}
}
/* This is only called by the sender. */
static void read_final_goodbye(int f_in, int f_out)
@@ -626,8 +458,9 @@ static void read_final_goodbye(int f_in, int f_out)
}
static void do_server_sender(int f_in, int f_out, int argc, char *argv[])
static void do_server_sender(int f_in, int f_out, int argc,char *argv[])
{
int i;
struct file_list *flist;
char *dir = argv[0];
@@ -641,24 +474,29 @@ static void do_server_sender(int f_in, int f_out, int argc, char *argv[])
exit_cleanup(RERR_SYNTAX);
return;
}
if (am_daemon && lp_read_only(module_id) && remove_source_files) {
if (am_daemon && lp_read_only(module_id) && remove_sent_files) {
rprintf(FERROR,
"ERROR: --remove-%s-files cannot be used with a read-only module\n",
remove_source_files == 1 ? "source" : "sent");
"ERROR: --remove-sent-files cannot be used with a read-only module\n");
exit_cleanup(RERR_SYNTAX);
return;
}
if (!relative_paths) {
if (!push_dir(dir, 0)) {
rsyserr(FERROR, errno, "push_dir#3 %s failed",
full_fname(dir));
exit_cleanup(RERR_FILESELECT);
}
if (!relative_paths && !push_dir(dir)) {
rsyserr(FERROR, errno, "push_dir#3 %s failed",
full_fname(dir));
exit_cleanup(RERR_FILESELECT);
}
argc--;
argv++;
if (strcmp(dir,".")) {
int l = strlen(dir);
if (strcmp(dir,"/") == 0)
l = 0;
for (i = 0; i < argc; i++)
argv[i] += l+1;
}
if (argc == 0 && (recurse || list_only)) {
argc = 1;
argv--;
@@ -687,12 +525,12 @@ static void do_server_sender(int f_in, int f_out, int argc, char *argv[])
static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
{
int pid;
int exit_code = 0;
int status = 0;
int error_pipe[2];
/* The receiving side mustn't obey this, or an existing symlink that
* points to an identical file won't be replaced by the referent. */
copy_links = copy_dirlinks = 0;
copy_links = 0;
if (preserve_hard_links)
init_hard_links();
@@ -773,14 +611,14 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
set_msg_fd_in(-1);
kill(pid, SIGUSR2);
wait_process_with_flush(pid, &exit_code);
return exit_code;
wait_process(pid, &status);
return status;
}
static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
{
int exit_code;
int status;
struct file_list *flist;
char *local_name = NULL;
char *dir = NULL;
@@ -803,11 +641,12 @@ static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
return;
}
if (argc > 0) {
dir = argv[0];
argc--;
argv++;
if (!am_daemon && !push_dir(dir, 0)) {
if (!am_daemon && !push_dir(dir)) {
rsyserr(FERROR, errno, "push_dir#4 %s failed",
full_fname(dir));
exit_cleanup(RERR_FILESELECT);
@@ -835,41 +674,17 @@ static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
}
the_file_list = flist;
if (argc > 0)
if (argc > 0) {
if (strcmp(dir,".")) {
argv[0] += strlen(dir);
if (argv[0][0] == '/')
argv[0]++;
}
local_name = get_local_name(flist,argv[0]);
/* Now that we know what our destination directory turned out to be,
* we can sanitize the --link-/copy-/compare-dest args correctly. */
if (sanitize_paths) {
char **dir;
for (dir = basis_dir; *dir; dir++) {
*dir = sanitize_path(NULL, *dir, NULL, curr_dir_depth, NULL);
}
if (partial_dir) {
partial_dir = sanitize_path(NULL, partial_dir, NULL, curr_dir_depth, NULL);
}
}
fix_basis_dirs();
if (server_filter_list.head) {
char **dir;
struct filter_list_struct *elp = &server_filter_list;
for (dir = basis_dir; *dir; dir++) {
if (check_filter(elp, *dir, 1) < 0)
goto options_rejected;
}
if (partial_dir && *partial_dir == '/'
&& check_filter(elp, partial_dir, 1) < 0) {
options_rejected:
rprintf(FERROR,
"Your options have been rejected by the server.\n");
exit_cleanup(RERR_SYNTAX);
}
}
exit_code = do_recv(f_in,f_out,flist,local_name);
exit_cleanup(exit_code);
status = do_recv(f_in,f_out,flist,local_name);
exit_cleanup(status);
}
@@ -887,9 +702,6 @@ void start_server(int f_in, int f_out, int argc, char *argv[])
io_set_sock_fds(f_in, f_out);
setup_protocol(f_out, f_in);
#if defined HAVE_ICONV_OPEN && defined HAVE_ICONV_H
setup_iconv();
#endif
if (protocol_version >= 23)
io_start_multiplex_out();
@@ -915,7 +727,7 @@ void start_server(int f_in, int f_out, int argc, char *argv[])
int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
{
struct file_list *flist = NULL;
int exit_code = 0, exit_code2 = 0;
int status = 0, status2 = 0;
char *local_name = NULL;
cleanup_child_pid = pid;
@@ -926,9 +738,6 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
io_set_sock_fds(f_in, f_out);
setup_protocol(f_out,f_in);
#if defined HAVE_ICONV_OPEN && defined HAVE_ICONV_H
setup_iconv();
#endif
if (protocol_version >= 23 && !read_batch)
io_start_multiplex_in();
@@ -970,11 +779,11 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
if (verbose > 3)
rprintf(FINFO,"client_run waiting on %d\n", (int) pid);
io_flush(FULL_FLUSH);
wait_process_with_flush(pid, &exit_code);
wait_process(pid, &status);
}
output_summary();
io_flush(FULL_FLUSH);
exit_cleanup(exit_code);
exit_cleanup(status);
}
if (need_messages_from_generator && !read_batch)
@@ -998,9 +807,7 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
if (flist && flist->count > 0) {
local_name = get_local_name(flist, argv[0]);
fix_basis_dirs();
exit_code2 = do_recv(f_in, f_out, flist, local_name);
status2 = do_recv(f_in, f_out, flist, local_name);
} else {
handle_stats(-1);
output_summary();
@@ -1010,10 +817,10 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
if (verbose > 3)
rprintf(FINFO,"client_run2 waiting on %d\n", (int) pid);
io_flush(FULL_FLUSH);
wait_process_with_flush(pid, &exit_code);
wait_process(pid, &status);
}
return MAX(exit_code, exit_code2);
return MAX(status, status2);
}
static int copy_argv (char *argv[])
@@ -1057,12 +864,12 @@ static int start_client(int argc, char *argv[])
return rc;
if (!read_batch) { /* for read_batch, NO source is specified */
argc--;
shell_path = check_for_hostspec(argv[0], &shell_machine, &rsync_port);
if (shell_path) { /* source is remote */
char *dummy1;
int dummy2;
if (--argc
&& check_for_hostspec(argv[argc], &dummy1, &dummy2)) {
if (argc && check_for_hostspec(argv[argc], &dummy1, &dummy2)) {
rprintf(FERROR,
"The source and destination cannot both be remote.\n");
exit_cleanup(RERR_SYNTAX);
@@ -1087,14 +894,12 @@ static int start_client(int argc, char *argv[])
} else { /* source is local, check dest arg */
am_sender = 1;
if (argc > 1)
p = argv[--argc];
else {
p = ".";
list_only = 1;
if (argc < 1) { /* destination required */
usage(FERROR);
exit_cleanup(RERR_SYNTAX);
}
shell_path = check_for_hostspec(p, &shell_machine, &rsync_port);
shell_path = check_for_hostspec(argv[argc], &shell_machine, &rsync_port);
if (shell_path && filesfrom_host && *filesfrom_host
&& strcmp(filesfrom_host, shell_machine) != 0) {
rprintf(FERROR,
@@ -1109,7 +914,7 @@ static int start_client(int argc, char *argv[])
exit_cleanup(RERR_SYNTAX);
}
shell_machine = NULL;
shell_path = p;
shell_path = argv[argc];
} else if (rsync_port) {
if (!shell_cmd) {
return start_socket_client(shell_machine,
@@ -1139,10 +944,10 @@ static int start_client(int argc, char *argv[])
if (verbose > 3) {
rprintf(FINFO,"cmd=%s machine=%s user=%s path=%s\n",
shell_cmd ? shell_cmd : "",
shell_machine ? shell_machine : "",
shell_user ? shell_user : "",
shell_path ? shell_path : "");
shell_cmd ? safe_fname(shell_cmd) : "",
shell_machine ? safe_fname(shell_machine) : "",
shell_user ? safe_fname(shell_user) : "",
shell_path ? safe_fname(shell_path) : "");
}
/* for remote source, only single dest arg can remain ... */
@@ -1179,7 +984,7 @@ static int start_client(int argc, char *argv[])
static RETSIGTYPE sigusr1_handler(UNUSED(int val))
{
exit_cleanup(RERR_SIGNAL1);
exit_cleanup(RERR_SIGNAL);
}
static RETSIGTYPE sigusr2_handler(UNUSED(int val))
@@ -1192,7 +997,7 @@ static RETSIGTYPE sigusr2_handler(UNUSED(int val))
_exit(0);
}
RETSIGTYPE remember_children(UNUSED(int val))
static RETSIGTYPE sigchld_handler(UNUSED(int val))
{
#ifdef WNOHANG
int cnt, status;
@@ -1201,7 +1006,8 @@ RETSIGTYPE remember_children(UNUSED(int val))
* get him to explain why he put it in, so rather than taking it
* out we're instead saving the child exit statuses for later use.
* The waitpid() loop presumably eliminates all possibility of leaving
* zombie children, maybe that's why he did it. */
* zombie children, maybe that's why he did it.
*/
while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
/* save the child's exit status */
for (cnt = 0; cnt < MAXCHILDPROCS; cnt++) {
@@ -1213,9 +1019,6 @@ RETSIGTYPE remember_children(UNUSED(int val))
}
}
#endif
#ifndef HAVE_SIGACTION
signal(SIGCHLD, remember_children);
#endif
}
@@ -1258,8 +1061,8 @@ static RETSIGTYPE rsync_panic_handler(UNUSED(int whatsig))
char cmd_buf[300];
int ret;
snprintf(cmd_buf, sizeof cmd_buf, get_panic_action(),
getpid(), getpid());
sprintf(cmd_buf, get_panic_action(),
getpid(), getpid());
/* Unless we failed to execute gdb, we allow the process to
* continue. I'm not sure if that's right. */
@@ -1275,23 +1078,16 @@ int main(int argc,char *argv[])
int ret;
int orig_argc = argc;
char **orig_argv = argv;
#ifdef HAVE_SIGACTION
# ifdef HAVE_SIGPROCMASK
sigset_t sigmask;
sigemptyset(&sigmask);
# endif
sigact.sa_flags = SA_NOCLDSTOP;
#endif
SIGACTMASK(SIGUSR1, sigusr1_handler);
SIGACTMASK(SIGUSR2, sigusr2_handler);
SIGACTMASK(SIGCHLD, remember_children);
signal(SIGUSR1, sigusr1_handler);
signal(SIGUSR2, sigusr2_handler);
signal(SIGCHLD, sigchld_handler);
#ifdef MAINTAINER_MODE
SIGACTMASK(SIGSEGV, rsync_panic_handler);
SIGACTMASK(SIGFPE, rsync_panic_handler);
SIGACTMASK(SIGABRT, rsync_panic_handler);
SIGACTMASK(SIGBUS, rsync_panic_handler);
#endif
signal(SIGSEGV, rsync_panic_handler);
signal(SIGFPE, rsync_panic_handler);
signal(SIGABRT, rsync_panic_handler);
signal(SIGBUS, rsync_panic_handler);
#endif /* def MAINTAINER_MODE */
starttime = time(NULL);
am_root = (MY_UID() == 0);
@@ -1305,11 +1101,7 @@ int main(int argc,char *argv[])
/* we set a 0 umask so that correct file permissions can be
* carried across */
orig_umask = umask(0);
#if defined CONFIG_LOCALE && defined HAVE_SETLOCALE
setlocale(LC_CTYPE, "");
#endif
orig_umask = (int)umask(0);
if (!parse_arguments(&argc, (const char ***) &argv, 1)) {
/* FIXME: We ought to call the same error-handling
@@ -1318,25 +1110,23 @@ int main(int argc,char *argv[])
exit_cleanup(RERR_SYNTAX);
}
SIGACTMASK(SIGINT, sig_int);
SIGACTMASK(SIGHUP, sig_int);
SIGACTMASK(SIGTERM, sig_int);
#if defined HAVE_SIGACTION && HAVE_SIGPROCMASK
sigprocmask(SIG_UNBLOCK, &sigmask, NULL);
#endif
signal(SIGINT,SIGNAL_CAST sig_int);
signal(SIGHUP,SIGNAL_CAST sig_int);
signal(SIGTERM,SIGNAL_CAST sig_int);
/* Ignore SIGPIPE; we consistently check error codes and will
* see the EPIPE. */
SIGACTION(SIGPIPE, SIG_IGN);
#ifdef SIGXFSZ
SIGACTION(SIGXFSZ, SIG_IGN);
signal(SIGPIPE, SIG_IGN);
#if defined CONFIG_LOCALE && defined HAVE_SETLOCALE
setlocale(LC_CTYPE, "");
#endif
/* Initialize push_dir here because on some old systems getcwd
* (implemented by forking "pwd" and reading its output) doesn't
* work when there are other child processes. Also, on all systems
* that implement getcwd that way "pwd" can't be found after chroot. */
push_dir(NULL, 0);
push_dir(NULL);
init_flist();

151
match.c
View File

@@ -1,69 +1,89 @@
/*
* Block matching used by the file-transfer code.
*
* Copyright (C) 1996 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2003, 2004, 2005, 2006 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
Copyright (C) Andrew Tridgell 1996
Copyright (C) Paul Mackerras 1996
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "rsync.h"
extern int verbose;
extern int am_server;
extern int do_progress;
extern int checksum_seed;
extern int append_mode;
int updating_basis_file;
typedef unsigned short tag;
#define TABLESIZE (1<<16)
#define NULL_TAG (-1)
static int false_alarms;
static int hash_hits;
static int tag_hits;
static int matches;
static int64 data_transfer;
static int total_false_alarms;
static int total_hash_hits;
static int total_tag_hits;
static int total_matches;
extern struct stats stats;
#define TABLESIZE (1<<16)
struct target {
tag t;
int32 i;
};
static int32 *hash_table;
static struct target *targets;
static int32 *tag_table;
#define gettag2(s1,s2) (((s1) + (s2)) & 0xFFFF)
#define gettag(sum) gettag2((sum)&0xFFFF,(sum)>>16)
static int compare_targets(struct target *t1,struct target *t2)
{
return (int)t1->t - (int)t2->t;
}
#define SUM2HASH2(s1,s2) (((s1) + (s2)) & 0xFFFF)
#define SUM2HASH(sum) SUM2HASH2((sum)&0xFFFF,(sum)>>16)
static void build_hash_table(struct sum_struct *s)
{
int32 i;
if (!hash_table) {
hash_table = new_array(int32, TABLESIZE);
if (!hash_table)
out_of_memory("build_hash_table");
}
if (!tag_table)
tag_table = new_array(int32, TABLESIZE);
memset(hash_table, 0xFF, TABLESIZE * sizeof hash_table[0]);
targets = new_array(struct target, s->count);
if (!tag_table || !targets)
out_of_memory("build_hash_table");
for (i = 0; i < s->count; i++) {
uint32 t = SUM2HASH(s->sums[i].sum1);
s->sums[i].chain = hash_table[t];
hash_table[t] = i;
targets[i].i = i;
targets[i].t = gettag(s->sums[i].sum1);
}
qsort(targets,s->count,sizeof(targets[0]),(int (*)())compare_targets);
for (i = 0; i < TABLESIZE; i++)
tag_table[i] = NULL_TAG;
for (i = s->count; i-- > 0; )
tag_table[targets[i].t] = i;
}
@@ -108,6 +128,7 @@ static void matched(int f, struct sum_struct *s, struct map_struct *buf,
sum_update(map_ptr(buf, last_match + j, n1), n1);
}
if (i >= 0)
last_match = offset + s->sums[i].len;
else
@@ -157,22 +178,20 @@ static void hash_search(int f,struct sum_struct *s,
}
do {
tag t = gettag2(s1,s2);
int done_csum2 = 0;
int32 i;
int32 j = tag_table[t];
if (verbose > 4) {
rprintf(FINFO, "offset=%.0f sum=%04x%04x\n",
(double)offset, s2 & 0xFFFF, s1 & 0xFFFF);
}
if (verbose > 4)
rprintf(FINFO,"offset=%.0f sum=%08x\n",(double)offset,sum);
i = hash_table[SUM2HASH2(s1,s2)];
if (i < 0)
goto null_hash;
if (j == NULL_TAG)
goto null_tag;
sum = (s1 & 0xffff) | (s2 << 16);
hash_hits++;
tag_hits++;
do {
int32 l;
int32 l, i = targets[j].i;
if (sum != s->sums[i].sum1)
continue;
@@ -188,11 +207,9 @@ static void hash_search(int f,struct sum_struct *s,
&& !(s->sums[i].flags & SUMFLG_SAME_OFFSET))
continue;
if (verbose > 3) {
rprintf(FINFO,
"potential match at %.0f i=%ld sum=%08x\n",
(double)offset, (long)i, sum);
}
if (verbose > 3)
rprintf(FINFO,"potential match at %.0f target=%.0f %.0f sum=%08x\n",
(double)offset,(double)j,(double)i,sum);
if (!done_csum2) {
map = (schar *)map_ptr(buf,offset,l);
@@ -209,8 +226,8 @@ static void hash_search(int f,struct sum_struct *s,
* one with an identical offset, so we prefer that over
* the following want_i optimization. */
if (updating_basis_file) {
int32 i2;
for (i2 = i; i2 >= 0; i2 = s->sums[i2].chain) {
do {
int32 i2 = targets[j].i;
if (s->sums[i2].offset != offset)
continue;
if (i2 != i) {
@@ -225,7 +242,7 @@ static void hash_search(int f,struct sum_struct *s,
* both the sender and the receiver. */
s->sums[i].flags |= SUMFLG_SAME_OFFSET;
goto set_want_i;
}
} while (++j < s->count && targets[j].t == t);
}
/* we've found a match, but now check to see
@@ -251,9 +268,9 @@ static void hash_search(int f,struct sum_struct *s,
s2 = sum >> 16;
matches++;
break;
} while ((i = s->sums[i].chain) >= 0);
} while (++j < s->count && targets[j].t == t);
null_hash:
null_tag:
backup = offset - last_match;
/* We sometimes read 1 byte prior to last_match... */
if (backup < 0)
@@ -308,7 +325,7 @@ void match_sums(int f, struct sum_struct *s, struct map_struct *buf, OFF_T len)
last_match = 0;
false_alarms = 0;
hash_hits = 0;
tag_hits = 0;
matches = 0;
data_transfer = 0;
@@ -317,16 +334,12 @@ void match_sums(int f, struct sum_struct *s, struct map_struct *buf, OFF_T len)
if (append_mode) {
OFF_T j = 0;
for (j = CHUNK_SIZE; j < s->flength; j += CHUNK_SIZE) {
if (buf && do_progress)
show_progress(last_match, buf->file_size);
sum_update(map_ptr(buf, last_match, CHUNK_SIZE),
CHUNK_SIZE);
last_match = j;
}
if (last_match < s->flength) {
int32 len = s->flength - last_match;
if (buf && do_progress)
show_progress(last_match, buf->file_size);
sum_update(map_ptr(buf, last_match, len), len);
last_match = s->flength;
}
@@ -360,11 +373,16 @@ void match_sums(int f, struct sum_struct *s, struct map_struct *buf, OFF_T len)
rprintf(FINFO,"sending file_sum\n");
write_buf(f,file_sum,MD4_SUM_LENGTH);
if (verbose > 2)
rprintf(FINFO, "false_alarms=%d hash_hits=%d matches=%d\n",
false_alarms, hash_hits, matches);
if (targets) {
free(targets);
targets=NULL;
}
total_hash_hits += hash_hits;
if (verbose > 2)
rprintf(FINFO, "false_alarms=%d tag_hits=%d matches=%d\n",
false_alarms, tag_hits, matches);
total_tag_hits += tag_hits;
total_false_alarms += false_alarms;
total_matches += matches;
stats.literal_data += data_transfer;
@@ -376,7 +394,8 @@ void match_report(void)
return;
rprintf(FINFO,
"total: matches=%d hash_hits=%d false_alarms=%d data=%.0f\n",
total_matches, total_hash_hits, total_false_alarms,
"total: matches=%d tag_hits=%d false_alarms=%d data=%.0f\n",
total_matches,total_tag_hits,
total_false_alarms,
(double)stats.literal_data);
}

View File

@@ -54,14 +54,15 @@ BEGIN {
printf "int %s(void);\n", a[2]
}
/^static|^extern/ || /[;]/ {
/^static|^extern/ || !/^[a-zA-Z]/ || /[;]/ {
next;
}
!/^[A-Za-z][A-Za-z0-9_]* / {
!/^OFF_T|^size_t|^off_t|^pid_t|^unsigned|^mode_t|^DIR|^user|^int|^char|^uint|^uchar|^short|^struct|^BOOL|^void|^time|^const/ {
next;
}
/[(].*[)][ \t]*$/ {
printf "%s;\n",$0;
next;
@@ -72,3 +73,4 @@ BEGIN {
printf "%s\n",$0;
next;
}

766
options.c
View File

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
Summary: A program for synchronizing files over a network.
Name: rsync
Version: 2.6.9
Version: 2.6.6
Release: 1
Group: Applications/Internet
Source: ftp://rsync.samba.org/pub/rsync/rsync-%{version}.tar.gz

View File

@@ -1,122 +0,0 @@
#!/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. 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).
#
# 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
# HTML man pages in the nightly dir, and then rsync the changes to the
# samba.org server.
use Getopt::Long;
use Date::Format;
# Choose any dir where a pristine rsync has been checked out of CVS.
our $unpacked = $ENV{HOME} . '/release/nightly';
# Where the local copy of /home/ftp/pub/rsync/nightly should be updated.
our $nightly = $ENV{HOME} . '/samba-rsync-ftp/nightly';
our $nightly_symlink = "$nightly/rsync-HEAD.tar.gz";
our($cvs_update, $make_tar, $upload, $help_opt);
&Getopt::Long::Configure('bundling');
&usage if !&GetOptions(
'cvs-update|c' => \$cvs_update,
'make-tar|t' => \$make_tar,
'upload|u' => \$upload,
'help|h' => \$help_opt,
) || $help_opt;
our $name = time2str('rsync-HEAD-%Y%m%d-%H%M%Z', time, 'GMT');
our $ztoday = time2str('%d %b %Y', time);
our $today = $ztoday;
chdir($unpacked) or die $!;
if ($cvs_update) {
print "Updating from cvs...\n";
system 'cvs -q up' and die $!;
}
if ($make_tar) {
print "Generating list of active CVS files...\n";
my($dir, @files);
open(CVS, '-|', 'cvs status 2>&1') or die $!;
while (<CVS>) {
if (/^cvs status: Examining (.*)/) {
if ($1 eq '.') {
$dir = '';
} else {
push(@files, $1);
$dir = $1 . '/';
}
} elsif (/^File: (.*?)\s+Status: (.*)/ && $1 ne '.cvsignore') {
push(@files, $dir . $1);
if ($2 ne 'Up-to-date') {
print "*** Not up-to-date: $dir$1\n";
}
}
}
close CVS;
print "Creating $unpacked/$name.tar.gz\n";
chdir('..') or die $!;
rename($unpacked, $name) or die $!;
open(TAR, '|-', "fakeroot tar --files-from=- --no-recursion --mode=g-w -czf $nightly/$name.tar.gz $name") or die $!;
foreach (@files) {
print TAR "$name/$_\n";
}
close TAR;
rename($name, $unpacked) or die $!;
unlink($nightly_symlink);
symlink("$name.tar.gz", $nightly_symlink);
}
chdir($nightly) or die $!;
foreach my $fn (qw( rsync.yo rsyncd.conf.yo )) {
my $html_fn = $fn;
$html_fn =~ s/\.yo/.html/;
open(IN, '<', "$unpacked/$fn") or die $!;
undef $/; $_ = <IN>; $/ = "\n";
close IN;
s/^(manpage\([^)]+\)\(\d+\)\()[^)]+(\).*)/$1$today$2/m;
#s/^(This man ?page is current for version) \S+ (of rsync)/$1 $version $2/m;
open(OUT, '>', $fn) or die $!;
print OUT $_;
close OUT;
system "yodl2html -o $html_fn $fn";
unlink($fn);
}
system "find . -name 'rsync-HEAD-*' -daystart -mtime +14 | xargs rm -f";
system 'ls -ltr';
if ($upload) {
my $opt = '';
if (defined $ENV{RSYNC_PARTIAL_DIR}) {
$opt = " -f 'R $ENV{RSYNC_PARTIAL_DIR}'";
}
system "rsync$opt -aviHP --delete-after . samba.org:/home/ftp/pub/rsync/nightly";
}
exit;
sub usage
{
die <<EOT;
Usage: nightly-rsync [OPTIONS]
-c, --cvs-update update $unpacked via CVS.
-t, --make-tar create a new tar file in $nightly
-u, --upload upload the revised nightly dir to samba.org
-h, --help display this help
EOT
}

View File

@@ -1,319 +0,0 @@
#!/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. If it is run
# in test mode, it instead expects a dir named ~/tmp/samba-rsync-ftp
# (e.g. copy ~/samba-rsync-ftp into ~/tmp and you can do a trial-run of
# a release without affecting the files in the ~/samba-rsync-ftp dir).
#
# Run this as "release-rsync live" to affect ~/samba-rsync-ftp instead
# of ~/tmp/samba-rsync-ftp.
use Date::Format;
my $dest = $ENV{HOME} . '/samba-rsync-ftp';
my $releasedir = $ENV{HOME} . '/release';
my $cvsroot = $ENV{CVSROOT} = 'samba.org:/data/cvs';
my $ztoday = time2str('%d %b %Y', time);
my $today = $ztoday;
$today =~ s/^0//;
my $break = <<EOT;
==========================================================================
EOT
my $note = <<EOT;
== Note: type "-a u,n" if you want to auto-accept the U,N suggestions. ==
EOT
my $live = shift;
my $skipping = '';
print $break;
if ($live) {
print <<EOT;
== This will release a new version of rsync onto an unsuspecting world. ==
EOT
} else {
print <<EOT;
== **** TESTMODE **** (Add "live" arg to avoid this.) ==
EOT
$dest =~ s#([^/]+$)#tmp/$1#;
$skipping = ' ** SKIPPING **';
}
die "$dest does not exist\n" unless -d $dest;
print $break, "\nChecking out the latest rsync into $releasedir ...\n";
mkdir($releasedir, 0755) or die $! unless -d $releasedir;
chdir($releasedir) or die $!;
system 'rm -rf rsync';
my(%dirs, @files);
open(CVS, '-|', 'cvs checkout -P rsync') or die $!;
while (<CVS>) {
print $_;
next if /\.(cvs)?ignore$/;
if (m#^[UP] rsync/(.*)#) {
my $fn = $1;
my($dir) = $fn =~ m#^(.+)/#;
push(@files, $dir) if defined($dir) && !$dirs{$1}++;
push(@files, $fn);
}
}
chdir('rsync') or die $!;
my($version, $lastversion);
open(IN, 'configure.in') or die $!;
while (<IN>) {
if (/^RSYNC_VERSION=(.*)/) {
$version = $lastversion = $1;
last;
}
}
close IN;
$lastversion =~ s/(\d+)cvs$/ $1 - 1 /e;
$version =~ s/cvs/pre1/ || $version =~ s/pre(\d+)/ 'pre' . ($1 + 1) /e;
print $break, "\nPlease enter the version number of this release: [$version] ";
chomp($_ = <STDIN>);
if ($_ eq '.') {
$version =~ s/pre\d+//;
} elsif ($_ ne '') {
$version = $_;
}
$version =~ s/[-.]*pre[-.]*/pre/;
$lastversion =~ s/(\d+)pre\d+$/ $1 - 1 /e unless $version =~ /pre/;
my $cvstag = "release-$version";
$cvstag =~ s/[.]/-/g;
$cvstag =~ s/pre/-pre/;
print "Enter the previous version to produce a patch against: [$lastversion] ";
chomp($_ = <STDIN>);
$lastversion = $_ if $_ ne '';
$lastversion =~ s/[-.]*pre[-.]*/pre/;
my $release = 1;
print "Please enter the RPM release number of this release: [$release] ";
chomp($_ = <STDIN>);
$release = $_ if $_ ne '';
my $diffdir;
my $skipping2;
if ($lastversion =~ /pre/) {
if ($version !~ /pre/) {
die "You should not diff a release version against a pre-release version.\n";
}
$diffdir = "$dest/old-previews";
$skipping2 = ' ** SKIPPING **';
} elsif ($version =~ /pre/) {
$diffdir = $dest;
$skipping2 = ' ** SKIPPING **';
} else {
$diffdir = "$dest/old-versions";
$skipping2 = '';
}
print "\n", $break, <<EOT;
\$version is "$version"
\$lastversion is "$lastversion"
\$cvstag is "$cvstag"
\$dest is "$dest"
\$releasedir is "$releasedir"
\$diffdir is "$diffdir"
\$release is "$release"
About to:
- make sure that configure, config.h.in, and proto.h are updated
- tweak the version in configure.in, configure, and the spec files
- tweak NEWS and OLDNEWS to update the release date$skipping2
- tweak the date in the *.yo files and re-generate the man pages
- make sure that the patches dir has been updated
- page through the "cvs diff" output
EOT
print "<Press Enter to continue> ";
$_ = <STDIN>;
my $f_opt = /f/ ? ' -f' : '';
print $break;
system "./prepare-source && touch proto.h";
my @tweak_files = ( glob('packaging/*.spec'), glob('packaging/*/*.spec'),
glob('*.yo'), qw( configure.in configure ) );
if ($version !~ /pre/) {
push(@tweak_files, qw( NEWS OLDNEWS ));
}
foreach my $fn (@tweak_files) {
open(IN, '<', $fn) or die $!;
undef $/; $_ = <IN>; $/ = "\n";
close IN;
if ($fn =~ /configure/) {
s/^RSYNC_VERSION=.*/RSYNC_VERSION=$version/m;
} elsif ($fn =~ /\.spec/) {
s/^(Version:) .*/$1 $version/m;
s/^(Release:) .*/$1 $release/m;
} elsif ($fn =~ /\.yo/) {
s/^(manpage\([^)]+\)\(\d+\)\()[^)]+(\).*)/$1$today$2/m;
s/^(This man ?page is current for version) \S+ (of rsync)/$1 $version $2/m;
} elsif ($fn eq 'NEWS') {
s/^(NEWS for rsync \Q$version\E) \(UNRELEASED\)\s*\n/$1 ($today)\n/mi
or die "Couldn't update NEWS file with release date!\n";
} elsif ($fn eq 'OLDNEWS') {
s/^\t\S\S\s\S\S\S\s\d\d\d\d(\t\Q$version\E)/\t$ztoday$1/m
or die "Couldn't update OLDNEWS file with release date!\n";
} else {
die "Unrecognized file in \@tweak_files: $fn\n";
}
open(OUT, '>', $fn) or die $!;
print OUT $_;
close OUT;
}
system "yodl2man -o rsync.1 rsync.yo; ./tweak_manpage_dashes rsync.1";
system "yodl2man -o rsyncd.conf.5 rsyncd.conf.yo; ./tweak_manpage_dashes rsyncd.conf.5";
mkdir('patches/tmp') or die $!;
system "rsync -a --exclude=patches/ --exclude-from=.cvsignore . patches/tmp/cvsdir/";
print "\n", $break, $note, $break;
system "patches/verify-patches -n -an$f_opt";
print $break;
system "cvs -q diff | egrep -v '^(===============|RCS file: |retrieving revision |Index: )' | less -p '^diff .*'";
print $break, <<EOT;
About to:
- "cvs commit" all changes$skipping
- "cvs tag" this release as $cvstag$skipping
- change the diffs in the patches dir to include generated files
EOT
print "<Press Enter to continue> ";
$_ = <STDIN>;
if ($live) {
system "cvs commit -m 'Preparing for release of $version'";
system "cvs tag -F $cvstag .";
}
if (!/skip/i) {
print "\n", $break, $note, $break;
system "patches/verify-patches -pun -an";
}
my $tar_name = "rsync-$version.tar.gz";
my $diff_name = "rsync-$lastversion-$version.diffs.gz";
my $tar_file = "$dest/$tar_name";
my $diff_file = "$dest/$diff_name";
print $break, <<EOT;
About to do the following in the samba-rsync-ftp dir:
- move the old tar/diff files into the appropriate old-* dirs
- hard-link the moved tar/diff files on samba.org$skipping
- create release tar, "$tar_name"
- create release diffs, "$diff_name"
- update README, *NEWS, TODO, and cvs.log
- update rsync*.html man pages
- gpg-sign the release files$skipping
EOT
print "<Press Enter to continue> ";
$_ = <STDIN>;
chdir($releasedir) or die $!;
print $break;
system "rm -rf rsync-$version";
rename('rsync', "rsync-$version") or die $!;
# When creating a pre-release after a normal release, there's nothing to move.
if ($diffdir ne $dest) {
chdir($dest) or die $!;
print "Shuffling old files ...\n";
# We need to run this regardless of $lastversion's "pre"ness.
my @moved_files;
foreach my $fn (glob('rsync*pre*.tar.gz*'), glob('rsync*pre*-NEWS')) {
link($fn, "old-previews/$fn") or die $!;
push(@moved_files, $fn);
}
if ($version !~ /pre/) {
foreach my $fn (glob('rsync*.tar.gz*'), glob('rsync*-NEWS')) {
next if $fn =~ /^rsync.*pre/;
link($fn, "old-versions/$fn") or die $!;
push(@moved_files, $fn);
}
foreach my $fn (glob('rsync*pre*.diffs.gz*')) {
unlink($fn);
}
foreach my $fn (glob('rsync*.diffs.gz*')) {
link($fn, "old-patches/$fn") or die $!;
push(@moved_files, $fn);
}
}
# Optimize our future upload (in the absence of --detect-renamed) by
# using rsync to hard-link the above files on samba.org.
if ($live) {
system "rsync -avHOC --include='rsync*.gz*' --include='old-*/' --exclude='*' . samba.org:/home/ftp/pub/rsync";
}
foreach (@moved_files) {
unlink($_);
}
chdir($releasedir) or die $!;
}
print "Creating $tar_file ...\n";
system "fakeroot tar czf $tar_file rsync-$version";
open(TAR, '|-', "fakeroot tar --files-from=- --no-recursion --mode=g+w -czf $tar_file rsync-$version") or die $!;
foreach (@files) {
print TAR "rsync-$version/$_\n";
}
close TAR;
print "Creating $diff_file ...\n";
system "rm -rf rsync-$version rsync-$lastversion";
system "tar xzf $tar_file; tar xzf $diffdir/rsync-$lastversion.tar.gz";
## TWEAK THE VERSIONS AS DESIRED HERE ##
#mkdir("rsync-$lastversion/support", 0755) or die $!;
#rename("rsync-$lastversion/rsyncstats", "rsync-$lastversion/support/rsyncstats");
#unlink("rsync-$lastversion/.ignore");
## END ##
system "diff -urN --exclude=patches rsync-$lastversion rsync-$version| gzip -9 >$diff_file";
print "Updating the other files in $dest ...\n";
system "rsync -a rsync-$version/{README,NEWS,OLDNEWS,TODO} $dest";
unlink("$dest/rsync-$version-NEWS");
link("$dest/NEWS", "$dest/rsync-$version-NEWS");
system "rsync -a $cvsroot/CVSROOT/rsync.updates $dest/cvs.log";
system "yodl2html -o $dest/rsync.html rsync-$version/rsync.yo";
system "yodl2html -o $dest/rsyncd.conf.html rsync-$version/rsyncd.conf.yo";
system "rm -rf rsync-*";
if ($live) {
chdir($dest) or die $!;
system "gpg -ba $tar_name; gpg -ba $diff_name";
print $break, <<EOT;
All done. Remember to announce the release on *BOTH*
rsync-announce\@lists.samba.org and rsync\@lists.samba.org!
EOT
} else {
print $break, "All done.\n";
}

View File

@@ -1,7 +1,7 @@
/* This modules is based on the params.c module from Samba, written by Karl Auer
and much modifed by Christopher Hertel. */
/*
This modules is based on the params.c module from Samba, written by Karl Auer
and much modifed by Christopher Hertel.
* 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
* the Free Software Foundation; either version 2 of the License, or
@@ -12,12 +12,11 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
/* -------------------------------------------------------------------------- **
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* -------------------------------------------------------------------------- **
*
* Module name: params
*
@@ -492,8 +491,8 @@ static FILE *OpenConfFile( char *FileName )
OpenedFile = fopen( FileName, "r" );
if( NULL == OpenedFile )
{
rsyserr(FERROR, errno, "unable to open configuration file \"%s\"",
FileName);
rsyserr(FERROR, errno, "rsync: unable to open configuration file \"%s\"",
safe_fname(FileName));
}
return( OpenedFile );

42
pipe.c
View File

@@ -1,10 +1,8 @@
/*
* Routines used to setup various kinds of inter-process pipes.
/* -*- c-file-style: "linux" -*-
*
* Copyright (C) 1996-2000 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
* Copyright (C) 2004, 2005, 2006 Wayne Davison
* Copyright (C) 1996-2000 by Andrew Tridgell
* Copyright (C) Paul Mackerras 1996
* Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
*
* 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
@@ -16,9 +14,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "rsync.h"
@@ -26,13 +24,11 @@
extern int am_sender;
extern int am_server;
extern int blocking_io;
extern int orig_umask;
extern int filesfrom_fd;
extern mode_t orig_umask;
extern char *logfile_name;
extern struct chmod_mode_struct *chmod_modes;
/**
* Create a child connected to us via its stdin/stdout.
* Create a child connected to use on stdin/stdout.
*
* This is derived from CVS code
*
@@ -82,7 +78,8 @@ pid_t piped_child(char **command, int *f_in, int *f_out)
if (blocking_io > 0)
set_blocking(STDOUT_FILENO);
execvp(command[0], command);
rsyserr(FERROR, errno, "Failed to exec %s", command[0]);
rsyserr(FERROR, errno, "Failed to exec %s",
safe_fname(command[0]));
exit_cleanup(RERR_IPC);
}
@@ -114,9 +111,6 @@ pid_t local_child(int argc, char **argv, int *f_in, int *f_out,
int to_child_pipe[2];
int from_child_pipe[2];
/* The parent process is always the sender for a local rsync. */
assert(am_sender);
if (fd_pair(to_child_pipe) < 0 ||
fd_pair(from_child_pipe) < 0) {
rsyserr(FERROR, errno, "pipe");
@@ -130,10 +124,11 @@ pid_t local_child(int argc, char **argv, int *f_in, int *f_out,
}
if (pid == 0) {
am_sender = 0;
am_sender = !am_sender;
am_server = 1;
filesfrom_fd = -1;
chmod_modes = NULL; /* Let the sending side handle this. */
if (!am_sender)
filesfrom_fd = -1;
if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 ||
close(to_child_pipe[1]) < 0 ||
@@ -149,11 +144,8 @@ pid_t local_child(int argc, char **argv, int *f_in, int *f_out,
child_main(argc, argv);
}
/* Let the client side handle this. */
if (logfile_name) {
logfile_name = NULL;
logfile_close();
}
if (!am_sender)
filesfrom_fd = -1;
if (close(from_child_pipe[1]) < 0 ||
close(to_child_pipe[0]) < 0) {

View File

@@ -1,12 +0,0 @@
#!/bin/sh
# Use autoconf, autoheader, yodl, etc. to ready the generated files in the
# release. This is typically used after applying a diff from the "patches"
# directory in a CVS-checked-out version.
#
# NOTE: if you use a diff from the "patches" directory of a *release tar*
# (as opposed to from CVS), this is not needed (but doesn't hurt anything).
dir=`dirname $0`
if test x"$dir" != x -a x"$dir" != x.; then
cd "$dir"
fi
make -f prepare-source.mak

View File

@@ -1,25 +0,0 @@
gen: configure config.h.in proto.h man
configure: configure.in aclocal.m4
autoconf
config.h.in: configure.in aclocal.m4
autoheader && touch config.h.in
proto.h: *.c lib/compat.c
cat *.c lib/compat.c | awk -f mkproto.awk >proto.h.new
if diff proto.h proto.h.new >/dev/null; then \
rm proto.h.new; \
else \
mv proto.h.new proto.h; \
fi
man: rsync.1 rsyncd.conf.5
rsync.1: rsync.yo
yodl2man -o rsync.1 rsync.yo
-./tweak_manpage_dashes rsync.1
rsyncd.conf.5: rsyncd.conf.yo
yodl2man -o rsyncd.conf.5 rsyncd.conf.yo
-./tweak_manpage_dashes rsyncd.conf.5

View File

@@ -1,10 +1,8 @@
/*
* Routines to output progress information during a file transfer.
/* -*- c-file-style: "linux" -*-
*
* Copyright (C) 1996-2000 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
* Copyright (C) 2003, 2004, 2005, 2006 Wayne Davison
* Copyright (C) 1996-2000 by Andrew Tridgell
* Copyright (C) Paul Mackerras 1996
* Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
*
* 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
@@ -16,9 +14,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "rsync.h"
@@ -99,14 +97,15 @@ static void rprint_progress(OFF_T ofs, OFF_T size, struct timeval *now,
remain_h = (int) (remain / 3600.0);
if (is_last) {
snprintf(eol, sizeof eol, " (xfer#%d, to-check=%d/%d)\n",
snprintf(eol, sizeof eol, " (%d, %.1f%% of %d)\n",
stats.num_transferred_files,
stats.num_files - stats.current_file_index - 1,
(float)((stats.current_file_index+1) * 100)
/ stats.num_files,
stats.num_files);
} else
strlcpy(eol, "\r", sizeof eol);
rprintf(FCLIENT, "%12s %3d%% %7.2f%s %4d:%02d:%02d%s",
human_num(ofs), pct, rate, units,
strcpy(eol, "\r");
rprintf(FINFO, "%12.0f %3d%% %7.2f%s %4d:%02d:%02d%s",
(double) ofs, pct, rate, units,
remain_h, remain_m, remain_s, eol);
}

View File

@@ -1,64 +1,126 @@
/*
* Routines only used by the receiving process.
*
* Copyright (C) 1996-2000 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2003, 2004, 2005, 2006 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
/* -*- c-file-style: "linux" -*-
Copyright (C) 1996-2000 by Andrew Tridgell
Copyright (C) Paul Mackerras 1996
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "rsync.h"
extern int verbose;
extern int do_xfers;
extern int am_daemon;
extern int am_server;
extern int do_progress;
extern int log_before_transfer;
extern int stdout_format_has_i;
extern int logfile_format_has_i;
extern int log_format_has_i;
extern int daemon_log_format_has_i;
extern int csum_length;
extern int read_batch;
extern int write_batch;
extern int batch_gen_fd;
extern int protocol_version;
extern int relative_paths;
extern int keep_dirlinks;
extern int preserve_hard_links;
extern int preserve_perms;
extern int io_error;
extern int basis_dir_cnt;
extern int make_backups;
extern int cleanup_got_literal;
extern int remove_source_files;
extern int remove_sent_files;
extern int module_id;
extern int ignore_errors;
extern int orig_umask;
extern int append_mode;
extern int sparse_files;
extern int keep_partial;
extern int checksum_seed;
extern int inplace;
extern int delay_updates;
extern struct stats stats;
extern char *stdout_format;
extern char *log_format;
extern char *tmpdir;
extern char *partial_dir;
extern char *basis_dir[];
extern struct file_list *the_file_list;
extern struct filter_list_struct server_filter_list;
static struct bitbag *delayed_bits = NULL;
#define SLOT_SIZE (16*1024) /* Desired size in bytes */
#define PER_SLOT_BITS (SLOT_SIZE * 8) /* Number of bits per slot */
#define PER_SLOT_INTS (SLOT_SIZE / 4) /* Number of int32s per slot */
static uint32 **delayed_bits = NULL;
static int delayed_slot_cnt = 0;
static int phase = 0;
/* We're either updating the basis file or an identical copy: */
static int updating_basis;
static void init_delayed_bits(int max_ndx)
{
delayed_slot_cnt = (max_ndx + PER_SLOT_BITS - 1) / PER_SLOT_BITS;
if (!(delayed_bits = (uint32**)calloc(delayed_slot_cnt, sizeof (uint32*))))
out_of_memory("set_delayed_bit");
}
static void set_delayed_bit(int ndx)
{
int slot = ndx / PER_SLOT_BITS;
ndx %= PER_SLOT_BITS;
if (!delayed_bits[slot]) {
if (!(delayed_bits[slot] = (uint32*)calloc(PER_SLOT_INTS, 4)))
out_of_memory("set_delayed_bit");
}
delayed_bits[slot][ndx/32] |= 1u << (ndx % 32);
}
/* Call this with -1 to start checking from 0. Returns -1 at the end. */
static int next_delayed_bit(int after)
{
uint32 bits, mask;
int i, ndx = after + 1;
int slot = ndx / PER_SLOT_BITS;
ndx %= PER_SLOT_BITS;
mask = (1u << (ndx % 32)) - 1;
for (i = ndx / 32; slot < delayed_slot_cnt; slot++, i = mask = 0) {
if (!delayed_bits[slot])
continue;
for ( ; i < PER_SLOT_INTS; i++, mask = 0) {
if (!(bits = delayed_bits[slot][i] & ~mask))
continue;
/* The xor magic figures out the lowest enabled bit in
* bits, and the switch quickly computes log2(bit). */
switch (bits ^ (bits & (bits-1))) {
#define LOG2(n) case 1u << n: return slot*PER_SLOT_BITS + i*32 + n
LOG2(0); LOG2(1); LOG2(2); LOG2(3);
LOG2(4); LOG2(5); LOG2(6); LOG2(7);
LOG2(8); LOG2(9); LOG2(10); LOG2(11);
LOG2(12); LOG2(13); LOG2(14); LOG2(15);
LOG2(16); LOG2(17); LOG2(18); LOG2(19);
LOG2(20); LOG2(21); LOG2(22); LOG2(23);
LOG2(24); LOG2(25); LOG2(26); LOG2(27);
LOG2(28); LOG2(29); LOG2(30); LOG2(31);
}
return -1; /* impossible... */
}
}
return -1;
}
/*
@@ -84,13 +146,15 @@ static int updating_basis;
static int get_tmpname(char *fnametmp, char *fname)
{
int maxname, added, length = 0;
char *f;
int length = 0;
int maxname;
if (tmpdir) {
/* Note: this can't overflow, so the return value is safe */
length = strlcpy(fnametmp, tmpdir, MAXPATHLEN - 2);
fnametmp[length++] = '/';
fnametmp[length] = '\0'; /* always NULL terminated */
}
if ((f = strrchr(fname, '/')) != NULL) {
@@ -103,21 +167,19 @@ static int get_tmpname(char *fnametmp, char *fname)
} else
f = fname;
fnametmp[length++] = '.';
fnametmp[length] = '\0'; /* always NULL terminated */
/* The maxname value is bufsize, and includes space for the '\0'.
* (Note that NAME_MAX get -8 for the leading '.' above.) */
maxname = MIN(MAXPATHLEN - 7 - length, NAME_MAX - 8);
if (maxname < 1) {
rprintf(FERROR, "temporary filename too long: %s\n", fname);
rprintf(FERROR, "temporary filename too long: %s\n",
safe_fname(fname));
fnametmp[0] = '\0';
return 0;
}
added = strlcpy(fnametmp + length, f, maxname);
if (added >= maxname)
added = maxname - 1;
memcpy(fnametmp + length + added, ".XXXXXX", 8);
strlcpy(fnametmp + length, f, maxname);
strcat(fnametmp + length, ".XXXXXX");
return 1;
}
@@ -144,7 +206,7 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
mapbuf = map_file(fd_r, size_r, read_size, sum.blength);
if (verbose > 2) {
rprintf(FINFO, "recv mapped %s of size %.0f\n",
fname_r, (double)size_r);
safe_fname(fname_r), (double)size_r);
}
} else
mapbuf = NULL;
@@ -157,22 +219,18 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
if (sum.remainder)
sum.flength -= sum.blength - sum.remainder;
for (j = CHUNK_SIZE; j < sum.flength; j += CHUNK_SIZE) {
if (do_progress)
show_progress(offset, total_size);
sum_update(map_ptr(mapbuf, offset, CHUNK_SIZE),
CHUNK_SIZE);
offset = j;
}
if (offset < sum.flength) {
int32 len = sum.flength - offset;
if (do_progress)
show_progress(offset, total_size);
sum_update(map_ptr(mapbuf, offset, len), len);
offset = sum.flength;
}
if (fd != -1 && (j = do_lseek(fd, offset, SEEK_SET)) != offset) {
rsyserr(FERROR, errno, "lseek of %s returned %.0f, not %.0f",
full_fname(fname), (double)j, (double)offset);
if (fd != -1 && do_lseek(fd, offset, SEEK_SET) != offset) {
rsyserr(FERROR, errno, "lseek failed on %s",
full_fname(fname));
exit_cleanup(RERR_FILEIO);
}
}
@@ -219,17 +277,15 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
sum_update(map, len);
}
if (updating_basis) {
if (inplace) {
if (offset == offset2 && fd != -1) {
OFF_T pos;
if (flush_write_file(fd) < 0)
goto report_write_error;
offset += len;
if ((pos = do_lseek(fd, len, SEEK_CUR)) != offset) {
if (do_lseek(fd, len, SEEK_CUR) != offset) {
rsyserr(FERROR, errno,
"lseek of %s returned %.0f, not %.0f",
full_fname(fname),
(double)pos, (double)offset);
"lseek failed on %s",
full_fname(fname));
exit_cleanup(RERR_FILEIO);
}
continue;
@@ -282,30 +338,31 @@ static void handle_delayed_updates(struct file_list *flist, char *local_name)
char *fname, *partialptr, numbuf[4];
int i;
for (i = -1; (i = bitbag_next_bit(delayed_bits, i)) >= 0; ) {
for (i = -1; (i = next_delayed_bit(i)) >= 0; ) {
struct file_struct *file = flist->files[i];
fname = local_name ? local_name : f_name(file, NULL);
fname = local_name ? local_name : f_name(file);
if ((partialptr = partial_dir_fname(fname)) != NULL) {
if (make_backups && !make_backup(fname))
continue;
if (verbose > 2) {
rprintf(FINFO, "renaming %s to %s\n",
partialptr, fname);
safe_fname(partialptr),
safe_fname(fname));
}
/* We don't use robust_rename() here because the
* partial-dir must be on the same drive. */
if (do_rename(partialptr, fname) < 0) {
rsyserr(FERROR, errno,
"rename failed for %s (from %s)",
full_fname(fname), partialptr);
full_fname(fname),
safe_fname(partialptr));
} else {
if (remove_source_files
if (remove_sent_files
|| (preserve_hard_links
&& file->link_u.links)) {
SIVAL(numbuf, 0, i);
send_msg(MSG_SUCCESS,numbuf,4);
}
handle_partial_dir(partialptr, PDIR_DELETE);
handle_partial_dir(partialptr,
PDIR_DELETE);
}
}
}
@@ -318,7 +375,7 @@ static int get_next_gen_i(int batch_gen_fd, int next_gen_i, int desired_i)
rprintf(FINFO,
"(No batched update for%s \"%s\")\n",
phase ? " resend of" : "",
f_name(the_file_list->files[next_gen_i], NULL));
safe_fname(f_name(the_file_list->files[next_gen_i])));
}
next_gen_i = read_int(batch_gen_fd);
if (next_gen_i == -1)
@@ -347,8 +404,8 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
struct file_struct *file;
struct stats initial_stats;
int save_make_backups = make_backups;
int itemizing = am_server ? logfile_format_has_i : stdout_format_has_i;
enum logcode log_code = log_before_transfer ? FLOG : FINFO;
int itemizing = am_daemon ? daemon_log_format_has_i
: !am_server && log_format_has_i;
int max_phase = protocol_version >= 29 ? 2 : 1;
int i, recv_ok;
@@ -361,9 +418,7 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
}
if (delay_updates)
delayed_bits = bitbag_create(flist->count);
updating_basis = inplace;
init_delayed_bits(flist->count);
while (1) {
cleanup_disable();
@@ -385,10 +440,7 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
send_msg(MSG_DONE, "", 0);
if (keep_partial && !partial_dir)
make_backups = 0; /* prevents double backup */
if (append_mode) {
append_mode = 0;
sparse_files = 0;
}
append_mode = 0;
continue;
}
@@ -398,10 +450,10 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
continue;
file = flist->files[i];
fname = local_name ? local_name : f_name(file, fbuf);
fname = local_name ? local_name : f_name_to(file, fbuf);
if (verbose > 2)
rprintf(FINFO, "recv_files(%s)\n", fname);
rprintf(FINFO, "recv_files(%s)\n", safe_fname(fname));
if (!(iflags & ITEM_TRANSFER)) {
maybe_log_item(file, iflags, itemizing, xname);
@@ -426,13 +478,14 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
}
if (!do_xfers) { /* log the transfer */
log_item(FCLIENT, file, &stats, iflags, NULL);
if (!am_server && log_format)
log_item(file, &stats, iflags, NULL);
if (read_batch)
discard_receive_data(f_in, file->length);
continue;
}
if (write_batch < 0) {
log_item(FINFO, file, &stats, iflags, NULL);
log_item(file, &stats, iflags, NULL);
if (!am_server)
discard_receive_data(f_in, file->length);
continue;
@@ -441,9 +494,8 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
if (read_batch) {
next_gen_i = get_next_gen_i(batch_gen_fd, next_gen_i, i);
if (i < next_gen_i) {
rprintf(FINFO,
"(Skipping batched update for \"%s\")\n",
fname);
rprintf(FINFO, "(Skipping batched update for \"%s\")\n",
safe_fname(fname));
discard_receive_data(f_in, file->length);
continue;
}
@@ -464,7 +516,6 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
fnamecmp = get_backup_name(fname);
break;
case FNAMECMP_FUZZY:
updating_basis = 0;
if (file->dirname) {
pathjoin(fnamecmpbuf, MAXPATHLEN,
file->dirname, xname);
@@ -473,7 +524,6 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
fnamecmp = xname;
break;
default:
updating_basis = 0;
if (fnamecmp_type >= basis_dir_cnt) {
rprintf(FERROR,
"invalid basis_dir index: %d.\n",
@@ -520,10 +570,7 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
}
}
if (fd1 == -1) {
st.st_mode = 0;
st.st_size = 0;
} else if (do_fstat(fd1,&st) != 0) {
if (fd1 != -1 && do_fstat(fd1,&st) != 0) {
rsyserr(FERROR, errno, "fstat %s failed",
full_fname(fnamecmp));
discard_receive_data(f_in, file->length);
@@ -549,16 +596,16 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
fd1 = -1;
}
/* If we're not preserving permissions, change the file-list's
* mode based on the local permissions and some heuristics. */
if (!preserve_perms) {
int exists = fd1 != -1;
file->mode = dest_mode(file->mode, st.st_mode, exists);
if (fd1 != -1 && !preserve_perms) {
/* if the file exists already and we aren't preserving
* permissions then act as though the remote end sent
* us the file permissions we already have */
file->mode = st.st_mode;
}
/* We now check to see if we are writing the file "inplace" */
/* We now check to see if we are writing file "inplace" */
if (inplace) {
fd2 = do_open(fname, O_WRONLY|O_CREAT, 0600);
fd2 = do_open(fname, O_WRONLY|O_CREAT, 0);
if (fd2 == -1) {
rsyserr(FERROR, errno, "open %s failed",
full_fname(fname));
@@ -587,7 +634,7 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
* because their information should have been previously
* transferred, but that may not be the case with -R */
if (fd2 == -1 && relative_paths && errno == ENOENT
&& create_directory_path(fnametmp) == 0) {
&& create_directory_path(fnametmp, orig_umask) == 0) {
/* Get back to name with XXXXXX in it. */
get_tmpname(fnametmp, fname);
fd2 = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS);
@@ -601,20 +648,22 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
continue;
}
cleanup_set(fnametmp, partialptr, file, fd1, fd2);
if (partialptr)
cleanup_set(fnametmp, partialptr, file, fd1, fd2);
}
/* log the transfer */
if (log_before_transfer)
log_item(FCLIENT, file, &initial_stats, iflags, NULL);
log_item(file, &initial_stats, iflags, NULL);
else if (!am_server && verbose && do_progress)
rprintf(FINFO, "%s\n", fname);
rprintf(FINFO, "%s\n", safe_fname(fname));
/* recv file data */
recv_ok = receive_data(f_in, fnamecmp, fd1, st.st_size,
fname, fd2, file->length);
log_item(log_code, file, &initial_stats, iflags, NULL);
if (!log_before_transfer)
log_item(file, &initial_stats, iflags, NULL);
if (fd1 != -1)
close(fd1);
@@ -625,25 +674,17 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
}
if ((recv_ok && (!delay_updates || !partialptr)) || inplace) {
char *temp_copy_name;
if (partialptr == fname)
partialptr = temp_copy_name = NULL;
else if (*partial_dir == '/')
temp_copy_name = NULL;
else
temp_copy_name = partialptr;
finish_transfer(fname, fnametmp, temp_copy_name,
file, recv_ok, 1);
if (fnamecmp == partialptr) {
finish_transfer(fname, fnametmp, file, recv_ok, 1);
if (partialptr != fname && fnamecmp == partialptr) {
do_unlink(partialptr);
handle_partial_dir(partialptr, PDIR_DELETE);
}
} else if (keep_partial && partialptr
&& handle_partial_dir(partialptr, PDIR_CREATE)) {
finish_transfer(partialptr, fnametmp, NULL,
file, recv_ok, !partial_dir);
finish_transfer(partialptr, fnametmp, file, recv_ok,
!partial_dir);
if (delay_updates && recv_ok) {
bitbag_set_bit(delayed_bits, i);
set_delayed_bit(i);
recv_ok = -1;
}
} else {
@@ -654,7 +695,7 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
cleanup_disable();
if (recv_ok > 0) {
if (remove_source_files
if (remove_sent_files
|| (preserve_hard_links && file->link_u.links)) {
SIVAL(numbuf, 0, i);
send_msg(MSG_SUCCESS, numbuf, 4);
@@ -678,7 +719,8 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
}
rprintf(msgtype,
"%s: %s failed verification -- update %s%s.\n",
errstr, fname, keptstr, redostr);
errstr, safe_fname(fname),
keptstr, redostr);
}
if (!phase) {
SIVAL(numbuf, 0, i);

203
rsync.c
View File

@@ -1,39 +1,30 @@
/*
* Routines common to more than one of the rsync processes.
*
* Copyright (C) 1996 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2003, 2004, 2005, 2006 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
Copyright (C) Andrew Tridgell 1996
Copyright (C) Paul Mackerras 1996
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* this file contains code used by more than one part of the rsync
process */
#include "rsync.h"
#if defined HAVE_ICONV_OPEN && defined HAVE_ICONV_H
#include <iconv.h>
#endif
#if defined HAVE_LIBCHARSET_H && defined HAVE_LOCALE_CHARSET
#include <libcharset.h>
#elif defined HAVE_LANGINFO_H && defined HAVE_NL_LANGINFO
#include <langinfo.h>
#endif
extern int verbose;
extern int dry_run;
extern int preserve_perms;
extern int preserve_executability;
extern int daemon_log_format_has_i;
extern int preserve_times;
extern int omit_dir_times;
extern int am_root;
@@ -41,53 +32,13 @@ extern int am_server;
extern int am_sender;
extern int am_generator;
extern int am_starting_up;
extern int allow_8bit_chars;
extern int preserve_uid;
extern int preserve_gid;
extern int inplace;
extern int keep_dirlinks;
extern int make_backups;
extern mode_t orig_umask;
extern struct stats stats;
extern struct chmod_mode_struct *daemon_chmod_modes;
#if defined HAVE_ICONV_OPEN && defined HAVE_ICONV_H
iconv_t ic_chck = (iconv_t)-1;
static const char *default_charset(void)
{
#if defined HAVE_LIBCHARSET_H && defined HAVE_LOCALE_CHARSET
return locale_charset();
#elif defined HAVE_LANGINFO_H && defined HAVE_NL_LANGINFO
return nl_langinfo(CODESET);
#else
return ""; /* Works with (at the very least) gnu iconv... */
#endif
}
void setup_iconv()
{
if (!am_server && !allow_8bit_chars) {
const char *defset = default_charset();
/* It's OK if this fails... */
ic_chck = iconv_open(defset, defset);
if (verbose > 3) {
if (ic_chck == (iconv_t)-1) {
rprintf(FINFO,
"note: iconv_open(\"%s\", \"%s\") failed (%d)"
" -- using isprint() instead of iconv().\n",
defset, defset, errno);
} else {
rprintf(FINFO,
"note: iconv_open(\"%s\", \"%s\") succeeded.\n",
defset, defset);
}
}
}
}
#endif
/*
free a sums struct
@@ -98,38 +49,13 @@ void free_sums(struct sum_struct *s)
free(s);
}
/* This is only called when we aren't preserving permissions. Figure out what
* the permissions should be and return them merged back into the mode. */
mode_t dest_mode(mode_t flist_mode, mode_t stat_mode, int exists)
{
int new_mode;
/* If the file already exists, we'll return the local permissions,
* possibly tweaked by the --executability option. */
if (exists) {
new_mode = (flist_mode & ~CHMOD_BITS) | (stat_mode & CHMOD_BITS);
if (preserve_executability && S_ISREG(flist_mode)) {
/* If the source file is executable, grant execute
* rights to everyone who can read, but ONLY if the
* file isn't already executable. */
if (!(flist_mode & 0111))
new_mode &= ~0111;
else if (!(stat_mode & 0111))
new_mode |= (new_mode & 0444) >> 2;
}
} else {
/* Apply the umask and turn off special permissions. */
new_mode = flist_mode & (~CHMOD_BITS | (ACCESSPERMS & ~orig_umask));
}
return new_mode;
}
int set_file_attrs(char *fname, struct file_struct *file, STRUCT_STAT *st,
int flags)
int set_perms(char *fname,struct file_struct *file,STRUCT_STAT *st,
int flags)
{
int updated = 0;
STRUCT_STAT st2;
int change_uid, change_gid;
mode_t new_mode = file->mode;
if (!st) {
if (dry_run)
@@ -140,18 +66,12 @@ int set_file_attrs(char *fname, struct file_struct *file, STRUCT_STAT *st,
return 0;
}
st = &st2;
if (!preserve_perms && S_ISDIR(new_mode)
&& st->st_mode & S_ISGID) {
/* We just created this directory and its setgid
* bit is on, so make sure it stays on. */
new_mode |= S_ISGID;
}
}
if (!preserve_times || (S_ISDIR(st->st_mode) && omit_dir_times))
flags |= ATTRS_SKIP_MTIME;
if (!(flags & ATTRS_SKIP_MTIME)
&& cmp_time(st->st_mtime, file->modtime) != 0) {
flags |= PERMS_SKIP_MTIME;
if (!(flags & PERMS_SKIP_MTIME)
&& cmp_modtime(st->st_mtime, file->modtime) != 0) {
int ret = set_modtime(fname, file->modtime, st->st_mode);
if (ret < 0) {
rsyserr(FERROR, errno, "failed to set times on %s",
@@ -175,13 +95,13 @@ int set_file_attrs(char *fname, struct file_struct *file, STRUCT_STAT *st,
if (change_uid) {
rprintf(FINFO,
"set uid of %s from %ld to %ld\n",
fname,
safe_fname(fname),
(long)st->st_uid, (long)file->uid);
}
if (change_gid) {
rprintf(FINFO,
"set gid of %s from %ld to %ld\n",
fname,
safe_fname(fname),
(long)st->st_gid, (long)file->gid);
}
}
@@ -205,11 +125,9 @@ int set_file_attrs(char *fname, struct file_struct *file, STRUCT_STAT *st,
updated = 1;
}
if (daemon_chmod_modes && !S_ISLNK(new_mode))
new_mode = tweak_mode(new_mode, daemon_chmod_modes);
#ifdef HAVE_CHMOD
if ((st->st_mode & CHMOD_BITS) != (new_mode & CHMOD_BITS)) {
int ret = do_chmod(fname, new_mode);
if ((st->st_mode & CHMOD_BITS) != (file->mode & CHMOD_BITS)) {
int ret = do_chmod(fname, file->mode);
if (ret < 0) {
rsyserr(FERROR, errno,
"failed to set permissions on %s",
@@ -221,16 +139,19 @@ int set_file_attrs(char *fname, struct file_struct *file, STRUCT_STAT *st,
}
#endif
if (verbose > 1 && flags & ATTRS_REPORT) {
if (verbose > 1 && flags & PERMS_REPORT) {
enum logcode code = daemon_log_format_has_i || dry_run
? FCLIENT : FINFO;
if (updated)
rprintf(FCLIENT, "%s\n", fname);
rprintf(code, "%s\n", safe_fname(fname));
else
rprintf(FCLIENT, "%s is uptodate\n", fname);
rprintf(code, "%s is uptodate\n", safe_fname(fname));
}
return updated;
}
RETSIGTYPE sig_int(UNUSED(int val))
void sig_int(void)
{
/* KLUGE: if the user hits Ctrl-C while ssh is prompting
* for a password, then our cleanup's sending of a SIGUSR1
@@ -244,39 +165,36 @@ RETSIGTYPE sig_int(UNUSED(int val))
exit_cleanup(RERR_SIGNAL);
}
/* Finish off a file transfer: renaming the file and setting the file's
* attributes (e.g. permissions, ownership, etc.). If partialptr is not
* NULL and the robust_rename() call is forced to copy the temp file, we
* stage the file into the partial-dir and then rename it into place. */
void finish_transfer(char *fname, char *fnametmp, char *partialptr,
struct file_struct *file, int ok_to_set_time,
int overwriting_basis)
/* finish off a file transfer, renaming the file and setting the permissions
and ownership */
void finish_transfer(char *fname, char *fnametmp, struct file_struct *file,
int ok_to_set_time, int overwriting_basis)
{
int ret;
if (inplace) {
if (verbose > 2)
rprintf(FINFO, "finishing %s\n", fname);
fnametmp = fname;
goto do_set_file_attrs;
rprintf(FINFO, "finishing %s\n", safe_fname(fname));
goto do_set_perms;
}
if (make_backups && overwriting_basis && !make_backup(fname))
return;
/* Change permissions before putting the file into place. */
set_file_attrs(fnametmp, file, NULL,
ok_to_set_time ? 0 : ATTRS_SKIP_MTIME);
set_perms(fnametmp, file, NULL, ok_to_set_time ? 0 : PERMS_SKIP_MTIME);
/* move tmp file over real file */
if (verbose > 2)
rprintf(FINFO, "renaming %s to %s\n", fnametmp, fname);
ret = robust_rename(fnametmp, fname, partialptr,
file->mode & INITACCESSPERMS);
if (verbose > 2) {
rprintf(FINFO, "renaming %s to %s\n",
safe_fname(fnametmp), safe_fname(fname));
}
ret = robust_rename(fnametmp, fname, file->mode & INITACCESSPERMS);
if (ret < 0) {
rsyserr(FERROR, errno, "%s %s -> \"%s\"",
ret == -2 ? "copy" : "rename",
full_fname(fnametmp), fname);
ret == -2 ? "copy" : "rename",
full_fname(fnametmp), safe_fname(fname));
do_unlink(fnametmp);
return;
}
@@ -284,21 +202,8 @@ void finish_transfer(char *fname, char *fnametmp, char *partialptr,
/* The file was moved into place (not copied), so it's done. */
return;
}
/* The file was copied, so tweak the perms of the copied file. If it
* was copied to partialptr, move it into its final destination. */
fnametmp = partialptr ? partialptr : fname;
do_set_file_attrs:
set_file_attrs(fnametmp, file, NULL,
ok_to_set_time ? 0 : ATTRS_SKIP_MTIME);
if (partialptr) {
if (do_rename(fnametmp, fname) < 0) {
rsyserr(FERROR, errno, "rename %s -> \"%s\"",
full_fname(fnametmp), fname);
} else
handle_partial_dir(partialptr, PDIR_DELETE);
}
do_set_perms:
set_perms(fname, file, NULL, ok_to_set_time ? 0 : PERMS_SKIP_MTIME);
}
const char *who_am_i(void)

154
rsync.h
View File

@@ -1,23 +1,23 @@
/*
* Copyright (C) 1996, 2000 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
* Copyright (C) 2003, 2004, 2005, 2006 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
Copyright (C) by Andrew Tridgell 1996, 2000
Copyright (C) Paul Mackerras 1996
Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#define False 0
#define True 1
@@ -58,13 +58,12 @@
/* These flags are used in the live flist data. */
#define FLAG_TOP_DIR (1<<0)
#define FLAG_SENT (1<<1) /* sender */
#define FLAG_HLINK_EOL (1<<1) /* receiver/generator */
#define FLAG_MOUNT_POINT (1<<2) /* sender/generator */
#define FLAG_MOUNT_POINT (1<<2) /* sender */
#define FLAG_NO_FUZZY (1<<2) /* generator */
#define FLAG_DEL_HERE (1<<3) /* receiver/generator */
#define FLAG_SENT (1<<3) /* sender */
#define FLAG_HLINK_TOL (1<<4) /* receiver/generator */
#define FLAG_NO_FUZZY (1<<5) /* generator */
#define FLAG_MISSING (1<<6) /* generator */
/* update this if you make incompatible changes */
#define PROTOCOL_VERSION 29
@@ -116,10 +115,9 @@
#define XFLG_FATAL_ERRORS (1<<0)
#define XFLG_OLD_PREFIXES (1<<1)
#define XFLG_ANCHORED2ABS (1<<2)
#define XFLG_ABS_IF_SLASH (1<<3)
#define ATTRS_REPORT (1<<0)
#define ATTRS_SKIP_MTIME (1<<1)
#define PERMS_REPORT (1<<0)
#define PERMS_SKIP_MTIME (1<<1)
#define FULL_FLUSH 1
#define NORMAL_FLUSH 0
@@ -135,22 +133,26 @@
#define FNAMECMP_BACKUP 0x82
#define FNAMECMP_FUZZY 0x83
/* For calling delete_file() */
#define DEL_NO_RECURSE (1<<1)
#define DEL_FORCE_RECURSE (1<<2) /* recurse even w/o --force */
#define DEL_TERSE (1<<3)
/* For use by the itemize_changes code */
#define ITEM_REPORT_ATIME (1<<0)
#define ITEM_REPORT_CHECKSUM (1<<1)
#define ITEM_REPORT_SIZE (1<<2)
#define ITEM_REPORT_TIME (1<<3)
#define ITEM_REPORT_PERMS (1<<4)
#define ITEM_REPORT_OWNER (1<<5)
#define ITEM_REPORT_GROUP (1<<6)
#define ITEM_REPORT_ACL (1<<7)
#define ITEM_REPORT_XATTR (1<<8)
#define ITEM_REPORT_XATTRS (1<<7)
#define ITEM_BASIS_TYPE_FOLLOWS (1<<11)
#define ITEM_XNAME_FOLLOWS (1<<12)
#define ITEM_IS_NEW (1<<13)
#define ITEM_LOCAL_CHANGE (1<<14)
#define ITEM_TRANSFER (1<<15)
/* These are outside the range of the transmitted flags. */
#define ITEM_NO_DEST_AND_NO_UPDATE (1<<16) /* used by itemize() */
#define ITEM_MISSING_DATA (1<<16) /* used by log_formatted() */
#define ITEM_DELETED (1<<17) /* used by log_formatted() */
@@ -158,17 +160,16 @@
ITEM_BASIS_TYPE_FOLLOWS | ITEM_XNAME_FOLLOWS | ITEM_LOCAL_CHANGE))
/* Log-message categories. Only FERROR and FINFO get sent over the socket,
* but FLOG and FSOCKERR can be sent over the receiver -> generator pipe.
* FLOG only goes to the log file, not the client; FCLIENT is the opposite. */
enum logcode { FNONE=0, FERROR=1, FINFO=2, FLOG=3, FCLIENT=4, FSOCKERR=5 };
/* Log-message categories. FLOG and FCLIENT are only used on the daemon
* side for custom logging -- they don't get sent over the socket. */
enum logcode { FERROR=1, FINFO=2, FLOG=3, FCLIENT=4 };
/* Messages types that are sent over the message channel. The logcode
* values must all be present here with identical numbers. */
enum msgcode {
MSG_DATA=0, /* raw data on the multiplexed stream */
MSG_ERROR=FERROR, MSG_INFO=FINFO, /* remote logging */
MSG_LOG=FLOG, MSG_SOCKERR=FSOCKERR, /* sibling logging */
MSG_LOG=FLOG, MSG_FCLIENT=FCLIENT, /* sibling logging */
MSG_REDO=9, /* reprocess indicated flist index */
MSG_SUCCESS=100,/* successfully updated indicated flist index */
MSG_DELETED=101,/* successfully deleted a file on receiving side */
@@ -314,20 +315,10 @@ enum msgcode {
#include <sys/sysmacros.h>
#endif
#ifdef MAKEDEV_TAKES_3_ARGS
#define MAKEDEV(devmajor,devminor) makedev(0,devmajor,devminor)
#else
#define MAKEDEV(devmajor,devminor) makedev(devmajor,devminor)
#endif
#ifdef HAVE_COMPAT_H
#include <compat.h>
#endif
#ifdef HAVE_LIMITS_H
# include <limits.h>
#endif
#include <assert.h>
#include "lib/pool_alloc.h"
@@ -389,7 +380,10 @@ enum msgcode {
* to ensure that any code that really requires a 64-bit integer has
* it (e.g. the checksum code uses two 32-bit integers for its 64-bit
* counter). */
#if SIZEOF_LONG == 8
#if SIZEOF_OFF64_T == 8
# define int64 off64_t
# define SIZEOF_INT64 8
#elif SIZEOF_LONG == 8
# define int64 long
# define SIZEOF_INT64 8
#elif SIZEOF_INT == 8
@@ -398,9 +392,6 @@ enum msgcode {
#elif SIZEOF_LONG_LONG == 8
# define int64 long long
# define SIZEOF_INT64 8
#elif SIZEOF_OFF64_T == 8
# define int64 off64_t
# define SIZEOF_INT64 8
#elif SIZEOF_OFF_T == 8
# define int64 off_t
# define SIZEOF_INT64 8
@@ -472,14 +463,6 @@ struct idev {
#define MAXPATHLEN 1024
#endif
/* We want a roomy line buffer that can hold more than MAXPATHLEN,
* and significantly more than an overly short MAXPATHLEN. */
#if MAXPATHLEN < 4096
#define BIGPATHBUFLEN (4096+1024)
#else
#define BIGPATHBUFLEN (MAXPATHLEN+1024)
#endif
#ifndef NAME_MAX
#define NAME_MAX 255
#endif
@@ -498,9 +481,8 @@ struct idev {
#define HL_SKIP 1
struct hlink {
int32 next;
int32 hlindex;
unsigned short link_dest_used;
int next;
int hlindex;
};
#define F_DEV link_u.idev->dev
@@ -570,7 +552,6 @@ struct sum_buf {
OFF_T offset; /**< offset in file of this chunk */
int32 len; /**< length of chunk of file */
uint32 sum1; /**< simple checksum */
int32 chain; /**< next hash-table collision */
short flags; /**< flag bits */
char sum2[SUM_LENGTH]; /**< checksum */
};
@@ -598,11 +579,11 @@ struct map_struct {
#define MATCHFLG_WILD (1<<0) /* pattern has '*', '[', and/or '?' */
#define MATCHFLG_WILD2 (1<<1) /* pattern has '**' */
#define MATCHFLG_WILD2_PREFIX (1<<2) /* pattern starts with "**" */
#define MATCHFLG_WILD3_SUFFIX (1<<3) /* pattern ends with "***" */
#define MATCHFLG_ABS_PATH (1<<4) /* path-match on absolute path */
#define MATCHFLG_INCLUDE (1<<5) /* this is an include, not an exclude */
#define MATCHFLG_DIRECTORY (1<<6) /* this matches only directories */
#define MATCHFLG_WILD2_PREFIX (1<<2) /* pattern starts with '**' */
#define MATCHFLG_ABS_PATH (1<<3) /* path-match on absolute path */
#define MATCHFLG_INCLUDE (1<<4) /* this is an include, not an exclude */
#define MATCHFLG_DIRECTORY (1<<5) /* this matches only directories */
#define MATCHFLG_CLEAR_LIST (1<<6) /* this item is the "!" token */
#define MATCHFLG_WORD_SPLIT (1<<7) /* split rules on whitespace */
#define MATCHFLG_NO_INHERIT (1<<8) /* don't inherit these rules */
#define MATCHFLG_NO_PREFIXES (1<<9) /* parse no prefixes from patterns */
@@ -614,7 +595,6 @@ struct map_struct {
#define MATCHFLG_CVS_IGNORE (1<<15)/* rule was -C or :C */
#define MATCHFLG_SENDER_SIDE (1<<16)/* rule applies to the sending side */
#define MATCHFLG_RECEIVER_SIDE (1<<17)/* rule applies to the receiving side */
#define MATCHFLG_CLEAR_LIST (1<<18)/* this item is the "!" token */
#define MATCHFLGS_FROM_CONTAINER (MATCHFLG_ABS_PATH | MATCHFLG_INCLUDE \
| MATCHFLG_DIRECTORY | MATCHFLG_SENDER_SIDE \
@@ -651,7 +631,6 @@ struct stats {
int current_file_index;
};
struct chmod_mode_struct;
#include "byteorder.h"
#include "lib/mdfour.h"
@@ -659,16 +638,6 @@ struct chmod_mode_struct;
#include "lib/permstring.h"
#include "lib/addrinfo.h"
#if !defined __GNUC__ || defined __APPLE__
/* Apparently the OS X port of gcc gags on __attribute__.
*
* <http://www.opensource.apple.com/bugs/X/gcc/2512150.html> */
#define __attribute__(x)
#endif
#define UNUSED(x) x __attribute__((__unused__))
#define NORETURN __attribute__((__noreturn__))
#include "proto.h"
/* We have replacement versions of these if they're missing. */
@@ -712,12 +681,7 @@ extern int errno;
#define SUPPORT_HARD_LINKS 1
#endif
#ifdef HAVE_SIGACTION
#define SIGACTION(n,h) sigact.sa_handler=(h), sigaction((n),&sigact,NULL)
#define signal(n,h) we_need_to_call_SIGACTION_not_signal(n,h)
#else
#define SIGACTION(n,h) signal(n,h)
#endif
#define SIGNAL_CAST (RETSIGTYPE (*)())
#ifndef EWOULDBLOCK
#define EWOULDBLOCK EAGAIN
@@ -814,8 +778,7 @@ extern int errno;
#define INADDR_NONE 0xffffffff
#endif
#define IS_SPECIAL(mode) (S_ISSOCK(mode) || S_ISFIFO(mode))
#define IS_DEVICE(mode) (S_ISCHR(mode) || S_ISBLK(mode))
#define IS_DEVICE(mode) (S_ISCHR(mode) || S_ISBLK(mode) || S_ISSOCK(mode) || S_ISFIFO(mode))
/* Initial mask on permissions given to temporary files. Mask off setuid
bits and group access because of potential race-condition security
@@ -823,7 +786,15 @@ extern int errno;
#define INITACCESSPERMS 0700
/* handler for null strings in printf format */
#define NS(s) ((s)?(s):"<NULL>")
#define NS(s) ((s)?safe_fname(s):"<NULL>")
#if !defined __GNUC__ || defined __APPLE__
/* Apparently the OS X port of gcc gags on __attribute__.
*
* <http://www.opensource.apple.com/bugs/X/gcc/2512150.html> */
#define __attribute__(x)
#endif
/* Convenient wrappers for malloc and realloc. Use them. */
#define new(type) ((type *)malloc(sizeof(type)))
@@ -841,6 +812,10 @@ void rsyserr(enum logcode, int, const char *, ...)
__attribute__((format (printf, 3, 4)))
;
#ifdef REPLACE_INET_NTOA
#define inet_ntoa rep_inet_ntoa
#endif
/* Make sure that the O_BINARY flag is defined. */
#ifndef O_BINARY
#define O_BINARY 0
@@ -857,9 +832,6 @@ size_t strlcat(char *d, const char *s, size_t bufsize);
#ifndef WEXITSTATUS
#define WEXITSTATUS(stat) ((int)(((stat)>>8)&0xFF))
#endif
#ifndef WIFEXITED
#define WIFEXITED(stat) ((int)((stat)&0xFF) == 0)
#endif
#define exit_cleanup(code) _exit_cleanup(code, __FILE__, __LINE__)
@@ -888,3 +860,7 @@ int inet_pton(int af, const char *src, void *dst);
#ifdef MAINTAINER_MODE
const char *get_panic_action(void);
#endif
#define UNUSED(x) x __attribute__((__unused__))
extern const char *io_write_phase, *io_read_phase;

1004
rsync.yo
View File

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
mailto(rsync-bugs@samba.org)
manpage(rsyncd.conf)(5)(6 Nov 2006)()()
manpage(rsyncd.conf)(5)(28 Jul 2005)()()
manpagename(rsyncd.conf)(configuration file for rsync in daemon mode)
manpagesynopsis()
@@ -8,27 +8,27 @@ rsyncd.conf
manpagedescription()
The rsyncd.conf file is the runtime configuration file for rsync when
run as an rsync daemon.
run as an rsync daemon.
The rsyncd.conf file controls authentication, access, logging and
available modules.
manpagesection(FILE FORMAT)
The file consists of modules and parameters. A module begins with the
The file consists of modules and parameters. A module begins with the
name of the module in square brackets and continues until the next
module begins. Modules contain parameters of the form 'name = value'.
The file is line-based -- that is, each newline-terminated line represents
either a comment, a module name or a parameter.
Only the first equals sign in a parameter is significant. Whitespace before
Only the first equals sign in a parameter is significant. Whitespace before
or after the first equals sign is discarded. Leading, trailing and internal
whitespace in module and parameter names is irrelevant. Leading and
trailing whitespace in a parameter value is discarded. Internal whitespace
within a parameter value is retained verbatim.
Any line beginning with a hash (#) is ignored, as are lines containing
Any line beginning with a hash (#) is ignored, as are lines containing
only whitespace.
Any line ending in a \ is "continued" on the next line in the
@@ -37,12 +37,12 @@ customary UNIX fashion.
The values following the equals sign in parameters are all either a string
(no quotes needed) or a boolean, which may be given as yes/no, 0/1 or
true/false. Case is not significant in boolean values, but is preserved
in string values.
in string values.
manpagesection(LAUNCHING THE RSYNC DAEMON)
The rsync daemon is launched by specifying the bf(--daemon) option to
rsync.
rsync.
The daemon must run with root privileges if you wish to use chroot, to
bind to a port numbered under 1024 (as is the default 873), or to set
@@ -58,7 +58,7 @@ When run via inetd you should add a line like this to /etc/services:
verb( rsync 873/tcp)
and a single line something like this to /etc/inetd.conf:
verb( rsync stream tcp nowait root /usr/bin/rsync rsyncd --daemon)
Replace "/usr/bin/rsync" with the path to where you have rsync installed on
@@ -67,12 +67,12 @@ reread its config file.
Note that you should bf(not) send the rsync daemon a HUP signal to force
it to reread the tt(rsyncd.conf) file. The file is re-read on each client
connection.
connection.
manpagesection(GLOBAL OPTIONS)
The first parameters in the file (before a [module] header) are the
global parameters.
global parameters.
You may also include any module parameters in the global part of the
config file in which case the supplied value will override the
@@ -84,9 +84,25 @@ dit(bf(motd file)) The "motd file" option allows you to specify a
usually contains site information and any legal notices. The default
is no motd file.
dit(bf(log file)) The "log file" option tells the rsync daemon to log
messages to that file rather than using syslog. This is particularly
useful on systems (such as AIX) where syslog() doesn't work for
chrooted programs. If the daemon fails to open to specified file, it
will fall back to using syslog and output an error about the failure.
(Note that a failure to open the specified log file used to be a fatal
error.)
dit(bf(pid file)) The "pid file" option tells the rsync daemon to write
its process ID to that file.
dit(bf(syslog facility)) The "syslog facility" option allows you to
specify the syslog facility name to use when logging messages from the
rsync daemon. You may use any standard syslog facility name which is
defined on your system. Common names are auth, authpriv, cron, daemon,
ftp, kern, lpr, mail, news, security, syslog, user, uucp, local0,
local1, local2, local3, local4, local5, local6 and local7. The default
is daemon.
dit(bf(port)) You can override the default port the daemon will listen on
by specifying this value (defaults to 873). This is ignored if the daemon
is being run by inetd, and is superseded by the bf(--port) command-line option.
@@ -98,10 +114,9 @@ being run by inetd, and is superseded by the bf(--address) command-line option.
dit(bf(socket options)) This option can provide endless fun for people
who like to tune their systems to the utmost degree. You can set all
sorts of socket options which may make transfers faster (or
slower!). Read the man page for the code(setsockopt()) system call for
slower!). Read the man page for the setsockopt() system call for
details on some of the options you may be able to set. By default no
special socket options are set. These settings are superseded by the
bf(--sockopts) command-line option.
special socket options are set.
enddit()
@@ -126,7 +141,7 @@ for each module in tt(rsyncd.conf).
dit(bf(use chroot)) If "use chroot" is true, the rsync daemon will chroot
to the "path" before starting the file transfer with the client. This has
the advantage of extra protection against possible implementation security
holes, but it has the disadvantages of requiring super-user privileges,
holes, but it has the disadvantages of requiring super-user privileges,
of not being able to follow symbolic links that are either absolute or outside
of the new root path, and of complicating the preservation of usernames and groups
(see below). When "use chroot" is false, for security reasons,
@@ -138,7 +153,7 @@ The default for "use chroot" is true.
In order to preserve usernames and groupnames, rsync needs to be able to
use the standard library functions for looking up names and IDs (i.e.
code(getpwuid()), code(getgrgid()), code(getpwname()), and code(getgrnam())). This means a
getpwuid(), getgrgid(), getpwname(), and getgrnam()). This means a
process in the chroot namespace will need to have access to the resources
used by these library functions (traditionally /etc/passwd and
/etc/group). If these resources are not available, rsync will only be
@@ -148,7 +163,7 @@ specified.
Note that you are free to setup user/group information in the chroot area
differently from your normal system. For example, you could abbreviate
the list of users and groups. Also, you can protect this information from
being downloaded/uploaded by adding an exclude rule to the rsyncd.conf file
being downloaded/uploaded by adding an exclude rule to the rsync.conf file
(e.g. "exclude = /etc/**"). Note that having the exclusion affect uploads
is a relatively new feature in rsync, so make sure your daemon is
at least 2.6.3 to effect this. Also note that it is safest to exclude a
@@ -164,29 +179,6 @@ Any clients connecting when the maximum has been reached will receive a
message telling them to try later. The default is 0 which means no limit.
See also the "lock file" option.
dit(bf(log file)) When the "log file" option is set to a non-empty
string, the rsync daemon will log messages to the indicated file rather
than using syslog. This is particularly useful on systems (such as AIX)
where code(syslog()) doesn't work for chrooted programs. The file is
opened before code(chroot()) is called, allowing it to be placed outside
the transfer. If this value is set on a per-module basis instead of
globally, the global log will still contain any authorization failures
or config-file error messages.
If the daemon fails to open to specified file, it will fall back to
using syslog and output an error about the failure. (Note that the
failure to open the specified log file used to be a fatal error.)
dit(bf(syslog facility)) The "syslog facility" option allows you to
specify the syslog facility name to use when logging messages from the
rsync daemon. You may use any standard syslog facility name which is
defined on your system. Common names are auth, authpriv, cron, daemon,
ftp, kern, lpr, mail, news, security, syslog, user, uucp, local0,
local1, local2, local3, local4, local5, local6 and local7. The default
is daemon. This setting has no effect if the "log file" setting is a
non-empty string (either set in the per-modules settings, or inherited
from the global settings).
dit(bf(max verbosity)) The "max verbosity" option allows you to control
the maximum amount of verbose information that you'll allow the daemon to
generate (since the information goes into the log file). The default is 1,
@@ -195,7 +187,7 @@ which allows the client to request one level of verbosity.
dit(bf(lock file)) The "lock file" option specifies the file to use to
support the "max connections" option. The rsync daemon uses record
locking on this file to ensure that the max connections limit is not
exceeded for the modules sharing the lock file.
exceeded for the modules sharing the lock file.
The default is tt(/var/run/rsyncd.lock).
dit(bf(read only)) The "read only" option determines whether clients
@@ -247,7 +239,7 @@ Because this exclude list is not passed to the client it only applies on
the daemon: that is, it excludes files received by a client when receiving
from a daemon and files deleted on a daemon when sending to a daemon, but
it doesn't exclude files from being deleted on a client when receiving
from a daemon.
from a daemon.
dit(bf(exclude from)) The "exclude from" option specifies a filename
on the daemon that contains exclude patterns, one per line.
@@ -270,25 +262,6 @@ only superficially equivalent to the client specifying the
bf(--include-from) option with a equivalent file.
See the "exclude" option above.
dit(bf(incoming chmod)) This option allows you to specify a set of
comma-separated chmod strings that will affect the permissions of all
incoming files (files that are being received by the daemon). These
changes happen after all other permission calculations, and this will
even override destination-default and/or existing permissions when the
client does not specify bf(--perms).
See the description of the bf(--chmod) rsync option and the bf(chmod)(1)
manpage for information on the format of this string.
dit(bf(outgoing chmod)) This option allows you to specify a set of
comma-separated chmod strings that will affect the permissions of all
outgoing files (files that are being sent out from the daemon). These
changes happen first, making the sent permissions appear to be different
than those stored in the filesystem itself. For instance, you could
disable group write permissions on the server while having it appear to
be on to the clients.
See the description of the bf(--chmod) rsync option and the bf(chmod)(1)
manpage for information on the format of this string.
dit(bf(auth users)) The "auth users" option specifies a comma and
space-separated list of usernames that will be allowed to connect to
this module. The usernames do not need to exist on the local
@@ -296,12 +269,12 @@ system. The usernames may also contain shell wildcard characters. If
"auth users" is set then the client will be challenged to supply a
username and password to connect to the module. A challenge response
authentication protocol is used for this exchange. The plain text
usernames and passwords are stored in the file specified by the
usernames are passwords are stored in the file specified by the
"secrets file" option. The default is for all users to be able to
connect without a password (this is called "anonymous rsync").
See also the "CONNECTING TO AN RSYNC DAEMON OVER A REMOTE SHELL
PROGRAM" section in bf(rsync)(1) for information on how handle an
PROGRAM" section in rsync(1) for information on how handle an
rsyncd.conf-level username that differs from the remote-shell-level
username when using a remote shell to connect to an rsync daemon.
@@ -313,13 +286,13 @@ username:password pairs separated by a single colon. Any line starting
with a hash (#) is considered a comment and is skipped. The passwords
can contain any characters but be warned that many operating systems
limit the length of passwords that can be typed at the client end, so
you may find that passwords longer than 8 characters don't work.
you may find that passwords longer than 8 characters don't work.
There is no default for the "secrets file" option, you must choose a name
(such as tt(/etc/rsyncd.secrets)). The file must normally not be readable
by "other"; see "strict modes".
dit(bf(strict modes)) The "strict modes" option determines whether or not
dit(bf(strict modes)) The "strict modes" option determines whether or not
the permissions on the secrets file will be checked. If "strict modes" is
true, then the secrets file must not be readable by any user ID other
than the one that the rsync daemon is running under. If "strict modes" is
@@ -333,7 +306,7 @@ connection is rejected.
Each pattern can be in one of five forms:
quote(itemization(
quote(itemize(
it() a dotted decimal IPv4 address of the form a.b.c.d, or an IPv6 address
of the form a:b:c::d:e:f. In this case the incoming machine's IP address
must match exactly.
@@ -364,7 +337,7 @@ You can also combine "hosts allow" with a separate "hosts deny"
option. If both options are specified then the "hosts allow" option s
checked first and a match results in the client being able to
connect. The "hosts deny" option is then checked and a match means
that the host is rejected. If the host does not match either the
that the host is rejected. If the host does not match either the
"hosts allow" or the "hosts deny" patterns then it is allowed to
connect.
@@ -383,14 +356,14 @@ phase of the transfer. Normally rsync skips the bf(--delete) step if any
I/O errors have occurred in order to prevent disastrous deletion due
to a temporary resource shortage or other I/O error. In some cases this
test is counter productive so you can use this option to turn off this
behavior.
behavior.
dit(bf(ignore nonreadable)) This tells the rsync daemon to completely
ignore files that are not readable by the user. This is useful for
public archives that may have some non-readable files among the
directories, and the sysadmin doesn't want those files to be seen at all.
dit(bf(transfer logging)) The "transfer logging" option enables per-file
dit(bf(transfer logging)) The "transfer logging" option enables per-file
logging of downloads and uploads in a format somewhat similar to that
used by ftp daemons. The daemon always logs the transfer at the end, so
if a transfer is aborted, no mention will be made in the log file.
@@ -412,26 +385,25 @@ rsyncstats.)
The single-character escapes that are understood are as follows:
quote(itemization(
it() %a the remote IP address
it() %b the number of bytes actually transferred
it() %B the permission bits of the file (e.g. rwxrwxrwt)
it() %c the checksum bytes received for this file (only when sending)
it() %f the filename (long form on sender; no trailing "/")
it() %G the gid of the file (decimal) or "DEFAULT"
it() %h the remote host name
quote(itemize(
it() %h for the remote host name
it() %a for the remote IP address
it() %l for the length of the file in bytes
it() %p for the process ID of this rsync session
it() %o for the operation, which is "send", "recv", or "del."
(the latter includes the trailing period)
it() %f for the filename (long form on sender; no trailing "/")
it() %n for the filename (short form; trailing "/" on dir)
it() %L either the string " -> SYMLINK", or " => HARDLINK" or an
empty string (where bf(SYMLINK) or bf(HARDLINK) is a filename)
it() %P for the module path
it() %m for the module name
it() %t for the current date time
it() %u for the authenticated username (or the null string)
it() %b for the number of bytes actually transferred
it() %c when sending files this gives the number of checksum bytes
received for this file
it() %i an itemized list of what is being updated
it() %l the length of the file in bytes
it() %L the string " -> SYMLINK", " => HARDLINK", or "" (where bf(SYMLINK) or bf(HARDLINK) is a filename)
it() %m the module name
it() %M the last-modified time of the file
it() %n the filename (short form; trailing "/" on dir)
it() %o the operation, which is "send", "recv", or "del." (the latter includes the trailing period)
it() %p the process ID of this rsync session
it() %P the module path
it() %t the current date time
it() %u the authenticated username or an empty string
it() %U the uid of the file (decimal)
))
For a list of what the characters mean that are output by "%i", see the
@@ -466,18 +438,15 @@ without the former, instead refuse "delete-*" -- that refuses all the
delete modes without affecting bf(--remove-sent-files).
When an option is refused, the daemon prints an error message and exits.
To prevent all compression when serving files,
you can use "dont compress = *" (see below)
To prevent all compression, you can use "dont compress = *" (see below)
instead of "refuse options = compress" to avoid returning an error to a
client that requests compression.
dit(bf(dont compress)) The "dont compress" option allows you to select
filenames based on wildcard patterns that should not be compressed
when pulling files from the daemon (no analogous option exists to
govern the pushing of files to a daemon).
Compression is expensive in terms of CPU usage, so it
during transfer. Compression is expensive in terms of CPU usage so it
is usually good to not try to compress files that won't compress well,
such as already compressed files.
such as already compressed files.
The "dont compress" option takes a space-separated list of
case-insensitive wildcard patterns. Any source filename matching one
@@ -485,48 +454,16 @@ of the patterns will not be compressed during transfer.
The default setting is tt(*.gz *.tgz *.zip *.z *.rpm *.deb *.iso *.bz2 *.tbz)
dit(bf(pre-xfer exec), bf(post-xfer exec)) You may specify a command to be run
before and/or after the transfer. If the bf(pre-xfer exec) command fails, the
transfer is aborted before it begins.
The following environment variables will be set, though some are
specific to the pre-xfer or the post-xfer environment:
quote(itemization(
it() bf(RSYNC_MODULE_NAME): The name of the module being accessed.
it() bf(RSYNC_MODULE_PATH): The path configured for the module.
it() bf(RSYNC_HOST_ADDR): The accessing host's IP address.
it() bf(RSYNC_HOST_NAME): The accessing host's name.
it() bf(RSYNC_USER_NAME): The accessing user's name (empty if no user).
it() bf(RSYNC_PID): A unique number for this transfer.
it() bf(RSYNC_REQUEST): (pre-xfer only) The module/path info specified
by the user (note that the user can specify multiple source files,
so the request can be something like "mod/path1 mod/path2", etc.).
it() bf(RSYNC_ARG#): (pre-xfer only) The pre-request arguments are set
in these numbered values. RSYNC_ARG0 is always "rsyncd", and the last
value contains a single period.
it() bf(RSYNC_EXIT_STATUS): (post-xfer only) the server side's exit value.
This will be 0 for a successful run, a positive value for an error that the
server generated, or a -1 if rsync failed to exit properly. Note that an
error that occurs on the client side does not currently get sent to the
server side, so this is not the final exit status for the whole transfer.
it() bf(RSYNC_RAW_STATUS): (post-xfer only) the raw exit value from code(waitpid()).
))
Even though the commands can be associated with a particular module, they
are run using the permissions of the user that started the daemon (not the
module's uid/gid setting) without any chroot restrictions.
enddit()
manpagesection(AUTHENTICATION STRENGTH)
The authentication protocol used in rsync is a 128 bit MD4 based
challenge response system. This is fairly weak protection, though (with
at least one brute-force hash-finding algorithm publicly available), so
if you want really top-quality security, then I recommend that you run
rsync over ssh. (Yes, a future version of rsync will switch over to a
stronger hashing method.)
challenge response system. Although I believe that no one has ever
demonstrated a brute-force break of this sort of system you should
realize that this is not a "military strength" authentication system.
It should be good enough for most purposes but if you want really top
quality security then I recommend that you run rsync over ssh.
Also note that the rsync daemon protocol does not currently provide any
encryption of the data that is transferred over the connection. Only
@@ -568,7 +505,7 @@ pid file = /var/run/rsyncd.pid
[rsyncftp]
path = /var/ftp/pub/rsync
comment = rsync ftp area (approx 6 MB)
[sambawww]
path = /public_html/samba
comment = Samba WWW pages (approx 240 MB)
@@ -593,7 +530,7 @@ manpagefiles()
manpageseealso()
bf(rsync)(1)
rsync(1)
manpagediagnostics()
@@ -604,7 +541,7 @@ url(http://rsync.samba.org/)(http://rsync.samba.org/)
manpagesection(VERSION)
This man page is current for version 2.6.9 of rsync.
This man page is current for version 2.6.6 of rsync.
manpagesection(CREDITS)
@@ -626,7 +563,7 @@ manpagesection(THANKS)
Thanks to Warren Stanley for his original idea and patch for the rsync
daemon. Thanks to Karsten Thygesen for his many suggestions and
documentation!
documentation!
manpageauthor()
@@ -634,4 +571,4 @@ rsync was written by Andrew Tridgell and Paul Mackerras.
Many people have later contributed to it.
Mailing lists for support and development are available at
url(http://lists.samba.org)(lists.samba.org)
url(http://lists.samba.org)(lists.samba.org)

View File

@@ -1,7 +1,6 @@
#! /bin/sh
# Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
# Copyright (C) 2003, 2004, 2005, 2006 Wayne Davison
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version
@@ -14,7 +13,8 @@
#
# You should have received a copy of the GNU Lesser General Public
# License along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
# rsync top-level test script -- this invokes all the other more
# detailed tests in order. This script can either be called by `make
@@ -85,7 +85,7 @@
# they're explicitly given on the command line.
# Also, we can't count on 'cp -a' or 'mkdir -p', although they're
# pretty handy (see function makepath for the latter).
# pretty handy.
# I think some of the GNU documentation suggests that we shouldn't
# rely on shell functions. However, the Bash manual seems to say that
@@ -100,8 +100,6 @@
# You cannot do "export VAR=VALUE" all on one line; the export must be
# separate from the assignment. (SCO SysV)
# Don't rely on grep -q, as that doesn't work everywhere -- just redirect
# stdout to /dev/null to keep it quiet.
# STILL TO DO:
@@ -126,7 +124,6 @@ set -e
. "./shconfig"
RUNSHFLAGS='-e'
export RUNSHFLAGS
# for Solaris
[ -d /usr/xpg4/bin ] && PATH="/usr/xpg4/bin/:$PATH"
@@ -138,27 +135,9 @@ if [ "x$loglevel" != x ] && [ "$loglevel" -gt 8 ]; then
fi
fi
POSIXLY_CORRECT=1
if test x"$TOOLDIR" = x; then
TOOLDIR=`pwd`
fi
srcdir=`dirname $0`
if test x"$srcdir" = x -o x"$srcdir" = x.; then
srcdir="$TOOLDIR"
fi
if test x"$rsync_bin" = x; then
rsync_bin="$TOOLDIR/rsync"
fi
# This allows the user to specify extra rsync options -- use carefully!
RSYNC="$rsync_bin $*"
#RSYNC="valgrind $rsync_bin $*"
export POSIXLY_CORRECT TOOLDIR srcdir RSYNC
echo "============================================================"
echo "$0 running in $TOOLDIR"
echo " rsync_bin=$RSYNC"
echo "$0 running in `pwd`"
echo " rsync_bin=$rsync_bin"
echo " srcdir=$srcdir"
if [ -f /usr/bin/whoami ]; then
@@ -181,16 +160,6 @@ else
echo " preserve_scratch=no"
fi
# Check if setfacl is around and if it supports the -k or -s option.
if setfacl --help 2>&1 | grep ' -k,\|\[-[a-z]*k' >/dev/null; then
setfacl_nodef='setfacl -k'
elif setfacl -s u::7,g::5,o:5 testsuite 2>/dev/null; then
setfacl_nodef='setfacl -s u::7,g::5,o:5'
else
setfacl_nodef=true
fi
export setfacl_nodef
if [ ! -f "$rsync_bin" ]; then
echo "rsync_bin $rsync_bin is not a file" >&2
@@ -202,6 +171,11 @@ if [ ! -d "$srcdir" ]; then
exit 2
fi
RSYNC="$rsync_bin"
#RSYNC="valgrind --tool=addrcheck $rsync_bin"
export rsync_bin RSYNC
skipped=0
missing=0
passed=0
@@ -210,7 +184,7 @@ failed=0
# Prefix for scratch directory. We create separate directories for
# each test case, so that they can be left behind in case of failure
# to aid investigation.
scratchbase="$TOOLDIR"/testtmp
scratchbase="`pwd`"/testtmp
echo " scratchbase=$scratchbase"
suitedir="$srcdir/testsuite"
@@ -220,9 +194,6 @@ export scratchdir suitedir
prep_scratch() {
[ -d "$scratchdir" ] && rm -rf "$scratchdir"
mkdir "$scratchdir"
# Get rid of default ACLs and dir-setgid to avoid confusing some tests.
$setfacl_nodef "$scratchdir" || true
chmod g-s "$scratchdir"
return 0
}

View File

@@ -1,24 +1,21 @@
/*
* Routines only used by the sending process.
*
* Copyright (C) 1996 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2003, 2004, 2005, 2006 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
Copyright (C) Andrew Tridgell 1996
Copyright (C) Paul Mackerras 1996
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "rsync.h"
@@ -27,14 +24,14 @@ extern int do_xfers;
extern int am_server;
extern int am_daemon;
extern int log_before_transfer;
extern int stdout_format_has_i;
extern int logfile_format_has_i;
extern int log_format_has_i;
extern int daemon_log_format_has_i;
extern int csum_length;
extern int append_mode;
extern int io_error;
extern int allowed_lull;
extern int protocol_version;
extern int remove_source_files;
extern int remove_sent_files;
extern int updating_basis_file;
extern int make_backups;
extern int do_progress;
@@ -43,7 +40,7 @@ extern int batch_fd;
extern int write_batch;
extern struct stats stats;
extern struct file_list *the_file_list;
extern char *stdout_format;
extern char *log_format;
/**
@@ -128,18 +125,18 @@ void successful_send(int ndx)
return;
file = the_file_list->files[ndx];
/* The generator might tell us about symlinks we didn't send. */
if (!(file->flags & FLAG_SENT) && !S_ISLNK(file->mode))
return;
if (file->dir.root) {
offset = stringjoin(fname, sizeof fname,
file->dir.root, "/", NULL);
} else
offset = 0;
f_name(file, fname + offset);
if (remove_source_files) {
if (do_unlink(fname) == 0) {
if (verbose > 1)
rprintf(FINFO, "sender removed %s\n", fname + offset);
} else
rsyserr(FERROR, errno, "sender failed to remove %s", fname + offset);
f_name_to(file, fname + offset);
if (remove_sent_files && do_unlink(fname) == 0 && verbose > 1) {
rprintf(FINFO, "sender removed %s\n",
safe_fname(fname + offset));
}
}
@@ -220,8 +217,8 @@ void send_files(struct file_list *flist, int f_out, int f_in)
int phase = 0, max_phase = protocol_version >= 29 ? 2 : 1;
struct stats initial_stats;
int save_make_backups = make_backups;
int itemizing = am_server ? logfile_format_has_i : stdout_format_has_i;
enum logcode log_code = log_before_transfer ? FLOG : FINFO;
int itemizing = am_daemon ? daemon_log_format_has_i
: !am_server && log_format_has_i;
int f_xfer = write_batch < 0 ? batch_fd : f_out;
int i, j;
@@ -259,7 +256,7 @@ void send_files(struct file_list *flist, int f_out, int f_in)
fname[offset++] = '/';
} else
offset = 0;
fname2 = f_name(file, fname + offset);
fname2 = f_name_to(file, fname + offset);
if (verbose > 2)
rprintf(FINFO, "send_files(%d, %s)\n", i, fname);
@@ -283,7 +280,8 @@ void send_files(struct file_list *flist, int f_out, int f_in)
stats.total_transferred_size += file->length;
if (!do_xfers) { /* log the transfer */
log_item(FCLIENT, file, &stats, iflags, NULL);
if (!am_server && log_format)
log_item(file, &stats, iflags, NULL);
write_ndx_and_attrs(f_out, i, iflags, fnamecmp_type,
xname, xlen);
continue;
@@ -333,20 +331,22 @@ void send_files(struct file_list *flist, int f_out, int f_in)
if (verbose > 2) {
rprintf(FINFO, "send_files mapped %s of size %.0f\n",
fname, (double)st.st_size);
safe_fname(fname), (double)st.st_size);
}
write_ndx_and_attrs(f_out, i, iflags, fnamecmp_type,
xname, xlen);
write_sum_head(f_xfer, s);
if (verbose > 2)
rprintf(FINFO, "calling match_sums %s\n", fname);
if (verbose > 2) {
rprintf(FINFO, "calling match_sums %s\n",
safe_fname(fname));
}
if (log_before_transfer)
log_item(FCLIENT, file, &initial_stats, iflags, NULL);
log_item(file, &initial_stats, iflags, NULL);
else if (!am_server && verbose && do_progress)
rprintf(FCLIENT, "%s\n", fname2);
rprintf(FINFO, "%s\n", safe_fname(fname2));
set_compression(fname);
@@ -354,7 +354,8 @@ void send_files(struct file_list *flist, int f_out, int f_in)
if (do_progress)
end_progress(st.st_size);
log_item(log_code, file, &initial_stats, iflags, NULL);
if (!log_before_transfer)
log_item(file, &initial_stats, iflags, NULL);
if (mbuf) {
j = unmap_file(mbuf);
@@ -369,8 +370,10 @@ void send_files(struct file_list *flist, int f_out, int f_in)
free_sums(s);
if (verbose > 2)
rprintf(FINFO, "sender finished %s\n", fname);
if (verbose > 2) {
rprintf(FINFO, "sender finished %s\n",
safe_fname(fname));
}
/* Flag that we actually sent this entry. */
file->flags |= FLAG_SENT;

100
socket.c
View File

@@ -1,42 +1,41 @@
/*
/* -*- c-file-style: "linux" -*-
rsync -- fast file replication program
Copyright (C) 1992-2001 by Andrew Tridgell <tridge@samba.org>
Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/**
* @file socket.c
*
* Socket functions used in rsync.
*
* Copyright (C) 1992-2001 Andrew Tridgell <tridge@samba.org>
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
* Copyright (C) 2003, 2004, 2005, 2006 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
/* This file is now converted to use the new-style getaddrinfo()
* This file is now converted to use the new-style getaddrinfo()
* interface, which supports IPv6 but is also supported on recent
* IPv4-only machines. On systems that don't have that interface, we
* emulate it using the KAME implementation. */
* emulate it using the KAME implementation.
**/
#include "rsync.h"
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
extern char *bind_address;
extern int default_af_hint;
#ifdef HAVE_SIGACTION
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,
@@ -55,13 +54,13 @@ static int establish_proxy_connection(int fd, char *host, int port,
proxy_user, ":", proxy_pass, NULL);
len = strlen(buffer);
if ((len*8 + 5) / 6 >= (int)sizeof authbuf - 3) {
if ((len*8 + 5) / 6 >= (int)sizeof authbuf) {
rprintf(FERROR,
"authentication information is too long\n");
return -1;
}
base64_encode(buffer, len, authbuf, 1);
base64_encode(buffer, len, authbuf);
authhdr = "\r\nProxy-Authorization: Basic ";
} else {
*authbuf = '\0';
@@ -330,9 +329,9 @@ static int *open_socket_in(int type, int port, const char *bind_addr,
int af_hint)
{
int one = 1;
int s, *socks, maxs, i, ecnt;
int s, *socks, maxs, i;
struct addrinfo hints, *all_ai, *resp;
char portbuf[10], **errmsgs;
char portbuf[10];
int error;
memset(&hints, 0, sizeof hints);
@@ -350,25 +349,17 @@ static int *open_socket_in(int type, int port, const char *bind_addr,
/* Count max number of sockets we might open. */
for (maxs = 0, resp = all_ai; resp; resp = resp->ai_next, maxs++) {}
socks = new_array(int, maxs + 1);
errmsgs = new_array(char *, maxs);
if (!socks || !errmsgs)
if (!(socks = new_array(int, maxs + 1)))
out_of_memory("open_socket_in");
/* We may not be able to create the socket, if for example the
* machine knows about IPv6 in the C library, but not in the
* kernel. */
for (resp = all_ai, i = ecnt = 0; resp; resp = resp->ai_next) {
for (resp = all_ai, i = 0; resp; resp = resp->ai_next) {
s = socket(resp->ai_family, resp->ai_socktype,
resp->ai_protocol);
if (s == -1) {
int r = asprintf(&errmsgs[ecnt++],
"socket(%d,%d,%d) failed: %s\n",
(int)resp->ai_family, (int)resp->ai_socktype,
(int)resp->ai_protocol, strerror(errno));
if (r < 0)
out_of_memory("open_socket_in");
/* See if there's another address that will work... */
continue;
}
@@ -390,11 +381,6 @@ static int *open_socket_in(int type, int port, const char *bind_addr,
/* Now we've got a socket - we need to bind it. */
if (bind(s, resp->ai_addr, resp->ai_addrlen) < 0) {
/* Nope, try another */
int r = asprintf(&errmsgs[ecnt++],
"bind() failed: %s (address-family %d)\n",
strerror(errno), (int)resp->ai_family);
if (r < 0)
out_of_memory("open_socket_in");
close(s);
continue;
}
@@ -406,15 +392,6 @@ static int *open_socket_in(int type, int port, const char *bind_addr,
if (all_ai)
freeaddrinfo(all_ai);
/* Only output the socket()/bind() messages if we were totally
* unsuccessful, or if the daemon is being run with -vv. */
for (s = 0; s < ecnt; s++) {
if (!i || verbose > 1)
rwrite(FLOG, errmsgs[s], strlen(errmsgs[s]));
free(errmsgs[s]);
}
free(errmsgs);
if (!i) {
rprintf(FERROR,
"unable to bind any inbound sockets on port %d\n",
@@ -456,9 +433,7 @@ static RETSIGTYPE sigchld_handler(UNUSED(int val))
#ifdef WNOHANG
while (waitpid(-1, NULL, WNOHANG) > 0) {}
#endif
#ifndef HAVE_SIGACTION
signal(SIGCHLD, sigchld_handler);
#endif
}
@@ -467,10 +442,6 @@ void start_accept_loop(int port, int (*fn)(int, int))
fd_set deffds;
int *sp, maxfd, i;
#ifdef HAVE_SIGACTION
sigact.sa_flags = SA_NOCLDSTOP;
#endif
/* open an incoming socket */
sp = open_socket_in(SOCK_STREAM, port, bind_address, default_af_hint);
if (sp == NULL)
@@ -494,6 +465,7 @@ void start_accept_loop(int port, int (*fn)(int, int))
maxfd = sp[i];
}
/* now accept incoming connections - forking a new process
* for each incoming connection */
while (1) {
@@ -528,7 +500,7 @@ void start_accept_loop(int port, int (*fn)(int, int))
if (fd < 0)
continue;
SIGACTION(SIGCHLD, sigchld_handler);
signal(SIGCHLD, sigchld_handler);
if ((pid = fork()) == 0) {
int ret;

View File

@@ -55,7 +55,7 @@ EOT
foreach my $opt (sort keys %long_opt) {
my $val = $long_opt{$opt};
$val = 1 if $opt =~ /^(max-|min-)/;
$val = 1 if $opt =~ /^max-/;
$val = 3 if $opt eq 'files-from';
$val = '$ro ? -1 : ' . $val if $opt =~ /^remove-/;
print " '$opt' => $val,\n";

View File

@@ -1,173 +0,0 @@
#!/usr/bin/perl
# This script will parse the output of "find ARG [ARG...] -ls" and
# apply (at your discretion) the permissions, owner, and group info
# it reads onto any existing files and dirs (it doesn't try to affect
# symlinks). Run this with --help (-h) for a usage summary.
use strict;
use Getopt::Long;
our($p_opt, $o_opt, $g_opt, $map_file, $dry_run, $verbosity, $help_opt);
&Getopt::Long::Configure('bundling');
&usage if !&GetOptions(
'all|a' => sub { $p_opt = $o_opt = $g_opt = 1 },
'perms|p' => \$p_opt,
'owner|o' => \$o_opt,
'groups|g' => \$g_opt,
'map|m=s' => \$map_file,
'dry-run|n' => \$dry_run,
'help|h' => \$help_opt,
'verbose|v+' => \$verbosity,
) || $help_opt;
our(%uid_hash, %gid_hash);
$" = ', '; # How to join arrays referenced in double-quotes.
&parse_map_file($map_file) if defined $map_file;
my $detail_line = qr{
^ \s* \d+ \s+ # ignore inode
\d+ \s+ # ignore size
([-bcdlps]) # 1. File type
( [-r][-w][-xsS] # 2. user-permissions
[-r][-w][-xsS] # 3. group-permissions
[-r][-w][-xtT] ) \s+ # 4. other-permissions
\d+ \s+ # ignore number of links
(\S+) \s+ # 5. owner
(\S+) \s+ # 6. group
(?: \d+ \s+ )? # ignore size (when present)
\w+ \s+ \d+ \s+ # ignore month and date
\d+ (?: : \d+ )? \s+ # ignore time or year
([^\r\n]+) $ # 7. name
}x;
while (<>) {
my($type, $perms, $owner, $group, $name) = /$detail_line/;
die "Invalid input line $.:\n$_" unless defined $name;
die "A filename is not properly escaped:\n$_" unless $name =~ /^[^"\\]*(\\(\d\d\d|\D)[^"\\]*)*$/;
my $fn = $name;
$fn =~ s/\\(\d+|.)/ eval "\"\\$1\"" /eg;
if ($type eq '-') {
undef $type unless -f $fn;
} elsif ($type eq 'd') {
undef $type unless -d $fn;
} elsif ($type eq 'b') {
undef $type unless -b $fn;
} elsif ($type eq 'c') {
undef $type unless -c $fn;
} elsif ($type eq 'p') {
undef $type unless -p $fn;
} elsif ($type eq 's') {
undef $type unless -S $fn;
} else {
if ($verbosity) {
if ($type eq 'l') {
$name =~ s/ -> .*//;
$type = 'symlink';
} else {
$type = "type '$type'";
}
print "Skipping $name ($type ignored)\n";
}
next;
}
if (!defined $type) {
my $reason = -e _ ? "types don't match" : 'missing';
print "Skipping $name ($reason)\n";
next;
}
my($cur_mode, $cur_uid, $cur_gid) = (stat(_))[2,4,5];
$cur_mode &= 07777;
my $highs = join('', $perms =~ /..(.)..(.)..(.)/);
$highs =~ tr/-rwxSTst/00001111/;
$perms =~ tr/-STrwxst/00011111/;
my $mode = $p_opt ? oct('0b' . $highs . $perms) : $cur_mode;
my $uid = $o_opt ? $uid_hash{$owner} : $cur_uid;
if (!defined $uid) {
if ($owner =~ /^\d+$/) {
$uid = $owner;
} else {
$uid = getpwnam($owner);
}
$uid_hash{$owner} = $uid;
}
my $gid = $g_opt ? $gid_hash{$group} : $cur_gid;
if (!defined $gid) {
if ($group =~ /^\d+$/) {
$gid = $group;
} else {
$gid = getgrnam($group);
}
$gid_hash{$group} = $gid;
}
my @changes;
if ($mode != $cur_mode) {
push(@changes, 'permissions');
if (!$dry_run && !chmod($mode, $fn)) {
warn "chmod($mode, \"$name\") failed: $!\n";
}
}
if ($uid != $cur_uid || $gid != $cur_gid) {
push(@changes, 'owner') if $uid != $cur_uid;
push(@changes, 'group') if $gid != $cur_gid;
if (!$dry_run) {
if (!chown($uid, $gid, $fn)) {
warn "chown($uid, $gid, \"$name\") failed: $!\n";
}
if (($mode & 06000) && !chmod($mode, $fn)) {
warn "post-chown chmod($mode, \"$name\") failed: $!\n";
}
}
}
if (@changes) {
print "$name: changed @changes\n";
} elsif ($verbosity) {
print "$name: OK\n";
}
}
exit;
sub parse_map_file
{
my($fn) = @_;
open(IN, $fn) or die "Unable to open $fn: $!\n";
while (<IN>) {
if (/^user\s+(\S+)\s+(\S+)/) {
$uid_hash{$1} = $2;
} elsif (/^group\s+(\S+)\s+(\S+)/) {
$gid_hash{$1} = $2;
} else {
die "Invalid line #$. in mapfile `$fn':\n$_";
}
}
close IN;
}
sub usage
{
die <<EOT;
Usage: file-attr-restore [OPTIONS] FILE [FILE...]
-a, --all Restore all the attributes (-pog)
-p, --perms Restore the permissions
-o, --owner Restore the ownership
-g, --groups Restore the group
-m, --map=FILE Read user/group mappings from FILE
-n, --dry-run Don't actually make the changes
-v, --verbose Increase verbosity
-h, --help Show this help text
The FILE arg(s) should have been created by running the "find"
program with "-ls" as the output specifier.
The input file for the --map option must be in this format:
user FROM TO
group FROM TO
The "FROM" should be an user/group mentioned in the input, and the TO
should be either a uid/gid number, or a local user/group name.
EOT
}

View File

@@ -1,27 +0,0 @@
#!/usr/bin/perl
# This script takes an input of filenames and outputs a set of
# include/exclude directives that can be used by rsync to copy
# just the indicated files using an --exclude-from=FILE option.
use strict;
my %hash;
while (<>) {
chomp;
s#^/+##;
my $path = '/';
while (m#([^/]+/)/*#g) {
$path .= $1;
print "+ $path\n" unless $hash{$path}++;
}
if (m#([^/]+)$#) {
print "+ $path$1\n";
} else {
delete $hash{$path};
}
}
foreach (sort keys %hash) {
print "- $_*\n";
}
print "- /*\n";

View File

@@ -1,34 +0,0 @@
#!/usr/bin/perl
# Filter the rsync daemon log messages by module name. The log file can be
# in either syslog format or rsync's own log-file format. Note that the
# MODULE_NAME parameter is used in a regular-expression match in order to
# allow regex wildcards to be used. You can also limit the output by
# directory hierarchy in a module. Examples:
#
# logfilter foo /var/log/rsyncd.log # output lines for module foo
# logfilter foo/dir /var/log/syslog # limit lines to those in dir of foo
use strict;
my $match = shift;
die "Usage: logfilter MODULE_NAME [LOGFILE ...]\n" unless defined $match;
my $syslog_prefix = '\w\w\w +\d+ \d\d:\d\d:\d\d \S+ rsyncd';
my $rsyncd_prefix = '\d\d\d\d/\d\d/\d\d \d\d:\d\d:\d\d ';
my %pids;
while (<>) {
my($pid,$msg) = /^(?:$syslog_prefix|$rsyncd_prefix)\[(\d+)\]:? (.*)/o;
next unless defined $pid;
my($mod_spec) = $msg =~ /^rsync (?:on|to) (\S+) from /;
if (defined $mod_spec) {
if ($mod_spec =~ /^$match(\/\S*)?$/o) {
$pids{$pid} = 1;
} else {
delete $pids{$pid};
}
}
next unless $pids{$pid};
print $_;
}

View File

@@ -50,19 +50,17 @@ die "$0 -ro: sending to read-only server not allowed\n" if $ro && !$am_sender;
# To disable a short-named option, add its letter to this string:
our $short_disabled = '';
our $short_no_arg = 'CDEHIKLORSWbcdgklmnoprtuvxz'; # DO NOT REMOVE ANY
our $short_no_arg = 'CDHIKLORSWbcdglnoprtuvxz'; # DO NOT REMOVE ANY
our $short_with_num = 'B'; # DO NOT REMOVE ANY
# To disable a long-named option, change its value to a -1. The values mean:
# 0 = the option has no arg; 1 = the arg doesn't need any checking; 2 = only
# check the arg when receiving; and 3 = always check the arg.
our %long_opt = (
'append' => 0,
'backup-dir' => 2,
'bwlimit' => 1,
'checksum-seed' => 1,
'compare-dest' => 2,
'compress-level' => 1,
'copy-dest' => 2,
'copy-unsafe-links' => 0,
'daemon' => 0,
@@ -85,25 +83,19 @@ our %long_opt = (
'log-format' => 1,
'max-delete' => 1,
'max-size' => 1,
'min-size' => 1,
'modify-window' => 1,
'no-implied-dirs' => 0,
'no-r' => 0,
'no-relative' => 0,
'no-specials' => 0,
'numeric-ids' => 0,
'only-write-batch' => 1,
'partial' => 0,
'partial-dir' => 2,
'remove-sent-files' => $ro ? -1 : 0,
'remove-source-files' => $ro ? -1 : 0,
'safe-links' => 0,
'sender' => 0,
'server' => 0,
'size-only' => 0,
'specials' => 0,
'suffix' => 1,
'super' => 0,
'temp-dir' => 2,
'timeout' => 1,
);

View File

@@ -12,7 +12,7 @@
use Getopt::Long;
# You may wish to edit the next line to customize for your default log file.
$usage_file = "/var/log/rsyncd.log";
$usage_file = "/var/adm/rsyncd.log";
# Edit the following lines for default report settings.
# Entries defined here will be over-ridden by the command line.
@@ -52,22 +52,9 @@ if ($only_section) {
line: while (<LOG>) {
my $syslog_prefix = '\w\w\w +\d+ \d\d:\d\d:\d\d \S+ rsyncd';
my $rsyncd_prefix = '\d\d\d\d/\d\d/\d\d \d\d:\d\d:\d\d ';
next unless ($day,$time,$op,$host,$module,$file,$bytes)
= m{^
( \w\w\w\s+\d+ | \d+/\d\d/\d\d ) \s+ # day
(\d\d:\d\d:\d\d) \s+ # time
[^[]* \[\d+\]:? \s+ # pid (ignored)
(send|recv|[<>]f\S+) \s+ # op (%o or %i)
(\S+) \s+ # host
\[\d+\.\d+\.\d+\.\d+\] \s+ # IP (ignored)
(\S+) \s+ # module
\(\S*\) \s+ # user (ignored)
(.*) \s+ # file name
(\d+) # file length in bytes
$ }x;
= m#^ (\d+/\d\d/\d\d)\s+(\d\d:\d\d:\d\d)\s+\[\d+\]\s+(send|recv|[<>]f\S+)\s+
(\S+)\s+\[\d+\.\d+\.\d+\.\d+\]\s+(\S+)\s+\(\S*\)\s+(.*)\s+(\d+) $ #x;
# TODO actually divide the data by into send/recv categories
if ($op =~ /^>/) {

View File

@@ -7,13 +7,20 @@
* -o Save the output coming from PROGRAM to the OUTPUT_FILE
*
* If you want to capture the flow of data for an rsync command, use one of
* the following commands (the resulting files should be identical):
* the following commands (the first two are push commands, the last two are
* pull commands):
*
* rsync -av --rsh="savetransfer -i /tmp/to.server ssh"
* --rsync-path="savetransfer -i /tmp/from.client rsync" SOURCE DEST
* rsync -av --rsh="savetransfer -i /tmp/from.sender ssh"
* --rsync-path="savetransfer -i /tmp/to.receiver rsync" FILES HOST:DEST
*
* rsync -av --rsh="savetransfer -o /tmp/from.server ssh"
* --rsync-path="savetransfer -o /tmp/to.client rsync" SOURCE DEST
* rsync -av --rsh="savetransfer -o /tmp/to.sender ssh"
* --rsync-path="savetransfer -o /tmp/from.generator rsync" FILES HOST:DEST
*
* rsync -av --rsh="savetransfer -i /tmp/from.generator ssh"
* --rsync-path="savetransfer -i /tmp/to.sender rsync" HOST:FILES DEST
*
* rsync -av --rsh="savetransfer -o /tmp/to.receiver ssh"
* --rsync-path="savetransfer -o /tmp/from.sender rsync" HOST:FILES DEST
*
* Note that this program aborts after 30 seconds of inactivity, so you'll need
* to change it if that is not enough dead time for your transfer. Also, some

View File

@@ -1,25 +1,28 @@
/*
/*
Copyright (C) Andrew Tridgell 1998
Copyright (C) 2002 by Martin Pool
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/**
* @file syscall.c
*
* Syscall wrappers to ensure that nothing gets done in dry_run mode
* and to handle system peculiarities.
*
* Copyright (C) 1998 Andrew Tridgell
* Copyright (C) 2002 Martin Pool
* Copyright (C) 2003, 2004, 2005, 2006 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
**/
#include "rsync.h"
@@ -42,14 +45,14 @@ extern int preserve_perms;
#define RETURN_ERROR_IF_RO_OR_LO RETURN_ERROR_IF(read_only || list_only, EROFS)
int do_unlink(const char *fname)
int do_unlink(char *fname)
{
if (dry_run) return 0;
RETURN_ERROR_IF_RO_OR_LO;
return unlink(fname);
}
int do_symlink(const char *fname1, const char *fname2)
int do_symlink(char *fname1, char *fname2)
{
if (dry_run) return 0;
RETURN_ERROR_IF_RO_OR_LO;
@@ -57,7 +60,7 @@ int do_symlink(const char *fname1, const char *fname2)
}
#ifdef HAVE_LINK
int do_link(const char *fname1, const char *fname2)
int do_link(char *fname1, char *fname2)
{
if (dry_run) return 0;
RETURN_ERROR_IF_RO_OR_LO;
@@ -115,14 +118,14 @@ int do_mknod(char *pathname, mode_t mode, dev_t dev)
#endif
}
int do_rmdir(const char *pathname)
int do_rmdir(char *pathname)
{
if (dry_run) return 0;
RETURN_ERROR_IF_RO_OR_LO;
return rmdir(pathname);
}
int do_open(const char *pathname, int flags, mode_t mode)
int do_open(char *pathname, int flags, mode_t mode)
{
if (flags != O_RDONLY) {
RETURN_ERROR_IF(dry_run, 0);
@@ -152,23 +155,24 @@ int do_chmod(const char *path, mode_t mode)
}
#endif
int do_rename(const char *fname1, const char *fname2)
int do_rename(char *fname1, char *fname2)
{
if (dry_run) return 0;
RETURN_ERROR_IF_RO_OR_LO;
return rename(fname1, fname2);
}
void trim_trailing_slashes(char *name)
{
int l;
/* Some BSD systems cannot make a directory if the name
* contains a trailing slash.
* <http://www.opensource.apple.com/bugs/X/BSD%20Kernel/2734739.html> */
/* Don't change empty string; and also we can't improve on
* "/" */
l = strlen(name);
while (l > 1) {
if (name[--l] != '/')
@@ -177,14 +181,16 @@ void trim_trailing_slashes(char *name)
}
}
int do_mkdir(char *fname, mode_t mode)
{
if (dry_run) return 0;
RETURN_ERROR_IF_RO_OR_LO;
trim_trailing_slashes(fname);
trim_trailing_slashes(fname);
return mkdir(fname, mode);
}
/* like mkstemp but forces permissions */
int do_mkstemp(char *template, mode_t perms)
{
@@ -249,11 +255,7 @@ int do_fstat(int fd, STRUCT_STAT *st)
OFF_T do_lseek(int fd, OFF_T offset, int whence)
{
#ifdef HAVE_LSEEK64
#if !SIZEOF_OFF64_T
OFF_T lseek64();
#else
off64_t lseek64();
#endif
return lseek64(fd, offset, whence);
#else
return lseek(fd, offset, whence);

View File

@@ -1,33 +1,33 @@
/*
* This file contains really simple implementations for rsync global
* functions, so that module test harnesses can run standalone.
*
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
* Copyright (C) 2003, 2004, 2005, 2006 Wayne Davison
/* -*- c-file-style: "linux" -*-
*
* Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
*
* 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "rsync.h"
/**
* @file t_stub.c
*
* This file contains really simple implementations for rsync global
* functions, so that module test harnesses can run standalone.
**/
int modify_window = 0;
int module_id = -1;
int relative_paths = 0;
int human_readable = 0;
int module_dirlen = 0;
mode_t orig_umask = 002;
char *partial_dir;
struct filter_list_struct server_filter_list;
@@ -66,20 +66,16 @@ struct filter_list_struct server_filter_list;
char *lp_name(UNUSED(int mod))
{
return NULL;
return NULL;
}
BOOL lp_use_chroot(UNUSED(int mod))
{
return 0;
return 0;
}
char *lp_path(UNUSED(int mod))
{
return NULL;
return NULL;
}
const char *who_am_i(void)
{
return "tester";
}

View File

@@ -1,32 +1,36 @@
/*
* Test harness for unsafe_symlink(). Not linked into rsync itself.
*
* Copyright (C) 2002 Martin Pool
* Copyright (C) 2003 Wayne Davison
*
* Copyright (C) 2002 by Martin Pool
*
* 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* Prints either "safe" or "unsafe" depending on the two arguments.
* Always returns 0 unless something extraordinary happens. */
/**
* @file
*
* Test harness for unsafe_symlink(). Not linked into @c rsync itself.
*
* Prints either "safe" or "unsafe" depending on the two arguments.
* Always returns 0 unless something extraordinary happens.
**/
#include "rsync.h"
int dry_run, read_only, list_only, verbose;
int preserve_perms = 0;
int
main(int argc, char **argv)
{
@@ -37,6 +41,6 @@ main(int argc, char **argv)
printf("%s\n",
unsafe_symlink(argv[1], argv[2]) ? "unsafe" : "safe");
return 0;
}

View File

@@ -9,6 +9,8 @@
. "$suitedir/rsync.fns"
set -x
hands_setup
cd "$tmpdir"

View File

@@ -11,6 +11,8 @@
. "$suitedir/rsync.fns"
set -x
# Build some hardlinks
mygrps="`rsync_getgroups`" || fail "Can't get groups"

View File

@@ -1,72 +0,0 @@
#! /bin/sh
# Copyright (C) 2002 by Martin Pool <mbp@samba.org>
# This program is distributable under the terms of the GNU GPL (see
# COPYING).
# Test that the --chmod option functions correctly.
. $srcdir/testsuite/rsync.fns
# Build some files
fromdir="$scratchdir/from"
todir="$scratchdir/to"
checkdir="$scratchdir/check"
mkdir "$fromdir"
name1="$fromdir/name1"
name2="$fromdir/name2"
dir1="$fromdir/dir1"
dir2="$fromdir/dir2"
echo "This is the file" > "$name1"
echo "This is the other file" > "$name2"
mkdir "$dir1" "$dir2"
chmod 4700 "$name1" || test_skipped "Can't chmod"
chmod 700 "$dir1"
chmod 770 "$dir2"
# Copy the files we've created over to another directory
checkit "$RSYNC -avv \"$fromdir/\" \"$checkdir/\"" "$fromdir" "$checkdir"
# And then manually make the changes which should occur
umask 002
chmod ug-s,a+rX "$checkdir"/*
chmod +w "$checkdir" "$checkdir"/dir*
checkit "$RSYNC -avv --chmod ug-s,a+rX,D+w \"$fromdir/\" \"$todir/\"" "$checkdir" "$todir"
rm -r "$fromdir" "$checkdir" "$todir"
makepath "$todir"
makepath "$fromdir/foo"
touch "$fromdir/bar"
checkit "$RSYNC -avv \"$fromdir/\" \"$checkdir/\"" "$fromdir" "$checkdir"
chmod o+x "$fromdir"/bar
checkit "$RSYNC -avv --chmod=Fo-x \"$fromdir/\" \"$todir/\"" "$checkdir" "$todir"
# Tickle a bug in rsync 2.6.8: if you push a new directory with --perms off to
# a daemon with an incoming chmod, the daemon pretends the directory is a file
# for the purposes of the second application of the incoming chmod.
build_rsyncd_conf
cat >>"$scratchdir/test-rsyncd.conf" <<EOF
[test-incoming-chmod]
path = $todir
read only = no
incoming chmod = Fo-x
EOF
RSYNC_CONNECT_PROG="$RSYNC --config=$conf --daemon"
export RSYNC_CONNECT_PROG
rm -r "$todir"
makepath "$todir"
checkit "$RSYNC -rtvv \"$fromdir/\" localhost::test-incoming-chmod/" "$checkdir" "$todir"
# The script would have aborted on error, so getting here means we've won.
exit 0

View File

@@ -2,7 +2,7 @@
# Copyright (C) 2004 by Wayne Davison <wayned@samba.org>
# This program is distributable under the terms of the GNU GPL (see
# This program is distributable under the terms of the GNU GPL see
# COPYING).
# Test that various read-only and set[ug]id permissions work properly,
@@ -11,6 +11,8 @@
. "$suitedir/rsync.fns"
set -x
hands_setup
tmpdir2=/tmp

View File

@@ -2,7 +2,7 @@
# Copyright (C) 2004 by Wayne Davison <wayned@samba.org>
# This program is distributable under the terms of the GNU GPL (see
# This program is distributable under the terms of the GNU GPL see
# COPYING).
# Test that various read-only and set[ug]id permissions work properly,
@@ -11,6 +11,8 @@
. "$suitedir/rsync.fns"
set -x
hands_setup
chmod 440 "$fromdir/text"

View File

@@ -13,6 +13,8 @@
. "$suitedir/rsync.fns"
set -x
case `id -u` in
'') ;; # If "id" failed, try to continue...
0) ;;

View File

@@ -2,7 +2,7 @@
# Copyright (C) 2004 by Wayne Davison <wayned@samba.org>
# This program is distributable under the terms of the GNU GPL (see
# This program is distributable under the terms of the GNU GPL see
# COPYING).
# Test rsync handling of the --compare-dest option.
@@ -14,6 +14,8 @@ alt2dir="$tmpdir/alt2"
# Build some files/dirs/links to copy
set -x
hands_setup
# Setup the alt and chk dirs

View File

@@ -26,6 +26,8 @@ build_rsyncd_conf
RSYNC_CONNECT_PROG="$RSYNC --config=$conf --daemon"
export RSYNC_CONNECT_PROG
set -x
hands_setup
# Build chkdir with a normal rsync and an --exclude.

View File

@@ -20,6 +20,8 @@ build_rsyncd_conf
RSYNC_CONNECT_PROG="$RSYNC --config=$conf --daemon"
export RSYNC_CONNECT_PROG
set -x
hands_setup
# Build chkdir with a normal rsync and an --exclude.

View File

@@ -2,13 +2,15 @@
# Copyright (C) 2005 by Wayne Davison <wayned@samba.org>
# This program is distributable under the terms of the GNU GPL (see
# This program is distributable under the terms of the GNU GPL see
# COPYING).
# Test rsync handling of various delete directives.
. "$suitedir/rsync.fns"
set -x
hands_setup
makepath "$chkdir"
@@ -23,19 +25,5 @@ checkit "$RSYNC -avv --remove-sent-files \
diff -r "$chkdir/empty" "$fromdir"
# Make sure that "P" but not "-" per-dir merge-file filters take effect with
# --delete-excluded.
cat >"$todir/filters" <<EOF
P foo
- bar
EOF
touch "$todir/foo" "$todir/bar" "$todir/baz"
$RSYNC -r --exclude=baz --filter=': filters' --delete-excluded "$fromdir/" "$todir/"
test -f "$todir/foo" || test_fail "rsync deleted $todir/foo"
test -f "$todir/bar" && test_fail "rsync did not delete $todir/bar"
test -f "$todir/baz" && test_fail "rsync did not delete $todir/baz"
# The script would have aborted on error, so getting here means we've won.
exit 0

View File

@@ -9,9 +9,6 @@
. "$suitedir/rsync.fns"
chkfile="$scratchdir/rsync.chk"
outfile="$scratchdir/rsync.out"
# Build some hardlinks
case `id -u` in
@@ -19,7 +16,7 @@ case `id -u` in
0) ;;
*) if [ -f /usr/bin/fakeroot ]; then
echo "Let's try re-running the script under fakeroot..."
exec /usr/bin/fakeroot /bin/sh $RUNSHFLAGS "$0"
exec /usr/bin/fakeroot /bin/sh "$0"
fi
test_skipped "Rsync won't copy devices unless we're root"
;;
@@ -28,66 +25,15 @@ esac
# TODO: Need to test whether hardlinks are possible on this OS/filesystem
mkdir "$fromdir"
mkdir "$todir"
mknod "$fromdir/char" c 41 67 || test_skipped "Can't create char device node unless root"
mknod "$fromdir/char2" c 42 68 || test_skipped "Can't create char device node unless root"
mknod "$fromdir/char3" c 42 69 || test_skipped "Can't create char device node unless root"
mknod "$fromdir/block" b 42 69 || test_skipped "Can't create block device node unless root"
mknod "$fromdir/block2" b 42 73 || test_skipped "Can't create block device node unless root"
mknod "$fromdir/block3" b 105 73 || test_skipped "Can't create block device node unless root"
ln "$fromdir/block3" "$fromdir/block2.5" || echo "Skipping hard-linked device test..."
mkfifo "$fromdir/fifo" || test_skipped "Can't run mkfifo"
touch -r "$fromdir/block" "$fromdir/block2"
$RSYNC -ai "$fromdir/block" "$todir/block2" \
| tee "$outfile"
cat <<EOT >"$chkfile"
cD+++++++ block
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 1 failed"
$RSYNC -ai "$fromdir/block2" "$todir/block" \
| tee "$outfile"
cat <<EOT >"$chkfile"
cD+++++++ block2
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 2 failed"
sleep 1
$RSYNC -Di "$fromdir/block3" "$todir/block" \
| tee "$outfile"
cat <<EOT >"$chkfile"
cD..T.... block3
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 3 failed"
$RSYNC -aiHvv "$fromdir/" "$todir/" \
| tee "$outfile"
filter_outfile
cat <<EOT >"$chkfile"
.d..t.... ./
cD..t.... block
cD....... block2
cD+++++++ block3
hD+++++++ block2.5 => block3
cD+++++++ char
cD+++++++ char2
cD+++++++ char3
cS+++++++ fifo
EOT
if test ! -b "$fromdir/block2.5"; then
sed -e '/block2\.5/d' \
<"$chkfile" >"$chkfile.new"
mv "$chkfile.new" "$chkfile"
fi
diff $diffopt "$chkfile" "$outfile" || test_fail "test 4 failed"
echo "check how the directory listings compare with diff:"
echo ""
( cd "$fromdir" && rsync_ls_lR . ) > "$tmpdir/ls-from"
( cd "$todir" && rsync_ls_lR . ) > "$tmpdir/ls-to"
diff $diffopt "$tmpdir/ls-from" "$tmpdir/ls-to"
checkit "$RSYNC -aHvv \"$fromdir/\" \"$todir/\"" "$fromdir" "$todir" skip_file_diff
# The script would have aborted on error, so getting here means we've won.
exit 0

View File

@@ -1,41 +0,0 @@
#! /bin/sh
# This program is distributable under the terms of the GNU GPL (see
# COPYING).
# Test that rsync obeys directory setgid. -- Matt McCutchen
. $srcdir/testsuite/rsync.fns
umask 077
# Call as: testit <dirname> <dirperms> <file-expected> <program-expected> <dir-expected>
testit() {
todir="$scratchdir/$1"
mkdir "$todir"
chmod $2 "$todir"
# Make sure we obey directory setgid when creating a directory to hold multiple transferred files,
# even though the directory itself is outside the transfer
$RSYNC -rvv "$scratchdir/dir" "$scratchdir/file" "$scratchdir/program" "$todir/to/"
check_perms "$todir/to" $5 "Target $1"
check_perms "$todir/to/dir" $5 "Target $1"
check_perms "$todir/to/file" $3 "Target $1"
check_perms "$todir/to/program" $4 "Target $1"
}
echo "File!" >"$scratchdir/file"
echo "#!/bin/sh" >"$scratchdir/program"
mkdir "$scratchdir/dir"
chmod 2764 "$scratchdir/dir" || test_skipped "Can't chmod"
chmod 664 "$scratchdir/file"
chmod 775 "$scratchdir/program"
[ -g "$scratchdir/dir" ] || test_skipped "The directory setgid bit vanished!"
mkdir "$scratchdir/dir/blah"
[ -g "$scratchdir/dir/blah" ] || test_skipped "Your filesystem doesn't use directory setgid; maybe it's BSD."
# Test some target directories
testit setgid-off 700 rw------- rwx------ rwx------
testit setgid-on 2700 rw------- rwx------ rwx--S---
# Hooray
exit 0

View File

@@ -2,7 +2,7 @@
# Copyright (C) 2002 by Martin Pool <mbp@samba.org>
# This program is distributable under the terms of the GNU GPL (see
# This program is distributable under the terms of the GNU GPL see
# COPYING).
# Test rsync handling of duplicate filenames.
@@ -21,6 +21,8 @@
. "$suitedir/rsync.fns"
set -x
# Build some hardlinks
mkdir "$fromdir"

View File

@@ -2,7 +2,7 @@
# Copyright (C) 2003, 2004, 2005 by Wayne Davison <wayned@samba.org>
# This program is distributable under the terms of the GNU GPL (see
# This program is distributable under the terms of the GNU GPL see
# COPYING).
# Test rsync handling of exclude/include directives.
@@ -12,18 +12,18 @@
. "$suitedir/rsync.fns"
HOME="$scratchdir"
CVSIGNORE='*.junk'
export CVSIGNORE
export HOME CVSIGNORE
set -x
# Build some files/dirs/links to copy
makepath "$fromdir/foo/down/to/you"
makepath "$fromdir/foo/sub"
makepath "$fromdir/bar/down/to/foo/too"
makepath "$fromdir/bar/down/to/bar/baz"
makepath "$fromdir/mid/for/foo/and/that/is/who"
makepath "$fromdir/new/keep/this"
makepath "$fromdir/new/lose/this"
cat >"$fromdir/.filt" <<EOF
exclude down
: .filt-temp
@@ -32,14 +32,13 @@ clear
- *.bak
- *.old
EOF
echo filtered-1 >"$fromdir/foo/file1"
echo kept >"$fromdir/foo/file1"
echo removed >"$fromdir/foo/file2"
echo cvsout >"$fromdir/foo/file2.old"
cat >"$fromdir/foo/.filt" <<EOF
include .filt
- /file1
- file1
EOF
echo not-filtered-1 >"$fromdir/foo/sub/file1"
cat >"$fromdir/bar/.filt" <<EOF
- home-cvs-exclude
dir-merge .filt2
@@ -88,12 +87,8 @@ cat >"$excl" <<EOF
- /bar
# This should match against the whole path, not just the name.
+ foo**too
# These should float at the end of the path.
+ foo/s?b/
# This should float at the end of the path.
- foo/*/
# Test how /** differs from /***
- new/keep/**
- new/lose/***
# Test some normal excludes. Competing lines are paired.
+ t[o]/
- to
@@ -114,8 +109,6 @@ sleep 1 # Ensures that the rm commands will tweak the directory times.
rm -r "$chkdir"/foo/down
rm -r "$chkdir"/mid/for/foo/and
rm -r "$chkdir"/new/keep/this
rm -r "$chkdir"/new/lose
rm "$chkdir"/foo/file[235-9]
rm "$chkdir"/bar/down/to/foo/to "$chkdir"/bar/down/to/foo/file[235-9]
rm "$chkdir"/mid/for/foo/extra
@@ -203,13 +196,5 @@ $RSYNC -av --delete-excluded --exclude='*' "$fromdir/" "$todir/"
checkit "$RSYNC -avv -f dir-merge,-_.excl \
\"$fromdir/\" \"$todir/\"" "$chkdir" "$todir"
relative_opts='--relative --chmod=Du+w --copy-unsafe-links'
$RSYNC -av $relative_opts "$fromdir/foo" "$chkdir/"
rm -rf "$chkdir$fromdir/foo/down"
$RSYNC -av $relative_opts --existing --filter='-! */' "$fromdir/foo" "$chkdir/"
checkit "$RSYNC -avv $relative_opts --exclude=\"$fromdir/foo/down\" \
\"$fromdir/foo\" \"$todir\"" "$chkdir$fromdir/foo" "$todir$fromdir/foo"
# The script would have aborted on error, so getting here means we've won.
exit 0

View File

@@ -1,47 +0,0 @@
#! /bin/sh
# This program is distributable under the terms of the GNU GPL (see
# COPYING).
# Test the --executability or -E option. -- Matt McCutchen
. $srcdir/testsuite/rsync.fns
# Put some files in the From directory
mkdir "$fromdir"
cat <<EOF >"$fromdir/1"
#!/bin/sh
echo 'Program One!'
EOF
cat <<EOF >"$fromdir/2"
#!/bin/sh
echo 'Program Two!'
EOF
chmod 1700 "$fromdir/1" || test_skipped "Can't chmod"
chmod 600 "$fromdir/2"
$RSYNC -rvv "$fromdir/" "$todir/"
check_perms "$todir/1" rwx------ 1
check_perms "$todir/2" rw------- 1
# Mix up the permissions a bit
chmod 600 "$fromdir/1"
chmod 601 "$fromdir/2"
chmod 604 "$todir/2"
$RSYNC -rvv "$fromdir/" "$todir/"
# No -E, so nothing should have changed
check_perms "$todir/1" rwx------ 2
check_perms "$todir/2" rw----r-- 2
$RSYNC -rvvE "$fromdir/" "$todir/"
# Now things should have happened!
check_perms "$todir/1" rw------- 3
check_perms "$todir/2" rwx---r-x 3
# Hooray
exit 0

View File

@@ -2,13 +2,15 @@
# Copyright (C) 2005 by Wayne Davison <wayned@samba.org>
# This program is distributable under the terms of the GNU GPL (see
# This program is distributable under the terms of the GNU GPL see
# COPYING).
# Test rsync handling of the --fuzzy option.
. "$suitedir/rsync.fns"
set -x
mkdir "$fromdir"
mkdir "$todir"

View File

@@ -12,6 +12,8 @@
. "$suitedir/rsync.fns"
set -x
# Build some hardlinks
fromdir="$scratchdir/from"

View File

@@ -2,7 +2,7 @@
# Copyright (C) 2005 by Wayne Davison <wayned@samba.org>
# This program is distributable under the terms of the GNU GPL (see
# This program is distributable under the terms of the GNU GPL see
# COPYING).
# Test the output of various copy commands to ensure itemized output
@@ -10,11 +10,26 @@
. "$suitedir/rsync.fns"
set -x
lddir="$tmpdir/ld"
chkfile="$scratchdir/rsync.chk"
outfile="$scratchdir/rsync.out"
# This is only called if rsync was run with -v or -vv (not -i alone).
# Higher levels of -v would require more filtering.
filter_outfile() {
sed -e '/^building file list /d' \
-e '/^created directory /d' \
-e '/^done$/d' \
-e '/ --whole-file$/d' \
-e '/^total: /d' \
-e '/^$/,$d' \
<"$outfile" >"$outfile.new"
mv "$outfile.new" "$outfile"
}
makepath "$fromdir/foo"
makepath "$fromdir/bar/baz"
cp -p "$srcdir/configure.in" "$fromdir/foo/config1"
@@ -29,7 +44,6 @@ ln "$fromdir/foo/config1" "$fromdir/foo/extra"
$RSYNC -iplr "$fromdir/" "$todir/" \
| tee "$outfile"
cat <<EOT >"$chkfile"
cd+++++++ ./
cd+++++++ bar/
cd+++++++ bar/baz/
>f+++++++ bar/baz/rsync
@@ -131,153 +145,34 @@ EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 7 failed"
mv "$todir" "$lddir"
$RSYNC -ivvplrtH --copy-dest=../ld "$fromdir/" "$todir/" \
$RSYNC -ivvplrtH --copy-dest="$lddir" "$fromdir/" "$todir/" \
| tee "$outfile"
filter_outfile
cat <<EOT >"$chkfile"
cd+++++++ ./
.d..t.... ./
cd+++++++ bar/
cd+++++++ bar/baz/
cf bar/baz/rsync
cf....... bar/baz/rsync
cd+++++++ foo/
cf foo/config1
cf foo/config2
hf foo/extra => foo/config1
cL..T.... foo/sym -> ../bar/baz/rsync
cf....... foo/config1
cf....... foo/config2
hf+++++++ foo/extra => foo/config1
cL+++++++ foo/sym -> ../bar/baz/rsync
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 8 failed"
rm -rf "$todir"
$RSYNC -iplrtH --copy-dest=../ld "$fromdir/" "$todir/" \
$RSYNC -iplrtH --link-dest="$lddir" "$fromdir/" "$todir/" \
| tee "$outfile"
cat <<EOT >"$chkfile"
cd+++++++ ./
.d..t.... ./
cd+++++++ bar/
cd+++++++ bar/baz/
cd+++++++ foo/
hf foo/extra => foo/config1
hf+++++++ foo/extra => foo/config1
cL+++++++ foo/sym -> ../bar/baz/rsync
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 9 failed"
rm -rf "$todir"
$RSYNC -vvplrtH --copy-dest="$lddir" "$fromdir/" "$todir/" \
| tee "$outfile"
filter_outfile
cat <<EOT >"$chkfile"
./
bar/
bar/baz/
bar/baz/rsync is uptodate
foo/
foo/config1 is uptodate
foo/config2 is uptodate
"foo/extra" is a hard link
foo/extra => foo/config1
foo/sym is uptodate
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 10 failed"
rm -rf "$todir"
$RSYNC -ivvplrtH --link-dest="$lddir" "$fromdir/" "$todir/" \
| tee "$outfile"
filter_outfile
cat <<EOT >"$chkfile"
cd+++++++ ./
cd+++++++ bar/
cd+++++++ bar/baz/
hf bar/baz/rsync
cd+++++++ foo/
hf foo/config1
hf foo/config2
hf foo/extra => foo/config1
hL foo/sym -> ../bar/baz/rsync
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 11 failed"
rm -rf "$todir"
$RSYNC -iplrtH --dry-run --link-dest=../ld "$fromdir/" "$todir/" \
| tee "$outfile"
cat <<EOT >"$chkfile"
cd+++++++ ./
cd+++++++ bar/
cd+++++++ bar/baz/
cd+++++++ foo/
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 12 failed"
rm -rf "$todir"
$RSYNC -iplrtH --link-dest=../ld "$fromdir/" "$todir/" \
| tee "$outfile"
cat <<EOT >"$chkfile"
cd+++++++ ./
cd+++++++ bar/
cd+++++++ bar/baz/
cd+++++++ foo/
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 13 failed"
rm -rf "$todir"
$RSYNC -vvplrtH --link-dest="$lddir" "$fromdir/" "$todir/" \
| tee "$outfile"
filter_outfile
cat <<EOT >"$chkfile"
./
bar/
bar/baz/
bar/baz/rsync is uptodate
foo/
foo/config1 is uptodate
foo/config2 is uptodate
"foo/extra" is a hard link
foo/sym is uptodate
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 14 failed"
rm -rf "$todir"
$RSYNC -ivvplrtH --compare-dest="$lddir" "$fromdir/" "$todir/" \
| tee "$outfile"
filter_outfile
# TODO fix really-old problem when combining -H with --compare-dest:
# missing output for foo/extra hard-link (and it might not be updated)!
cat <<EOT >"$chkfile"
cd+++++++ ./
cd+++++++ bar/
cd+++++++ bar/baz/
.f bar/baz/rsync
cd+++++++ foo/
.f foo/config1
.f foo/config2
.L foo/sym -> ../bar/baz/rsync
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 15 failed"
rm -rf "$todir"
$RSYNC -iplrtH --compare-dest="$lddir" "$fromdir/" "$todir/" \
| tee "$outfile"
cat <<EOT >"$chkfile"
cd+++++++ ./
cd+++++++ bar/
cd+++++++ bar/baz/
cd+++++++ foo/
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 16 failed"
rm -rf "$todir"
$RSYNC -vvplrtH --compare-dest="$lddir" "$fromdir/" "$todir/" \
| tee "$outfile"
filter_outfile
cat <<EOT >"$chkfile"
./
bar/
bar/baz/
bar/baz/rsync is uptodate
foo/
foo/config1 is uptodate
foo/config2 is uptodate
"foo/extra" is a hard link
foo/sym is uptodate
EOT
diff $diffopt "$chkfile" "$outfile" || test_fail "test 17 failed"
# The script would have aborted on error, so getting here means we've won.
exit 0

View File

@@ -7,6 +7,8 @@
. "$suitedir/rsync.fns"
set -x
hands_setup
longname=This-is-a-directory-with-a-stupidly-long-name-created-in-an-attempt-to-provoke-an-error-found-in-2.0.11-that-should-hopefully-never-appear-again-if-this-test-does-its-job

View File

@@ -9,6 +9,8 @@
. "$suitedir/rsync.fns"
set -x
# Build some files/dirs/links to copy
from1dir="${fromdir}1"

View File

@@ -32,9 +32,6 @@ else
diffopt="-c"
fi
HOME="$scratchdir"
export HOME
runtest() {
echo $ECHO_N "Test $1: $ECHO_C"
if eval "$2"
@@ -47,38 +44,15 @@ runtest() {
fi
}
# Call this if you want to filter out verbose messages (-v or -vv) from
# the output of an rsync run (whittling the output down to just the file
# messages). This isn't needed if you use -i without -v.
filter_outfile() {
sed -e '/^building file list /d' \
-e '/^created directory /d' \
-e '/^done$/d' \
-e '/ --whole-file$/d' \
-e '/^total: /d' \
-e '/^$/,$d' \
<"$outfile" >"$outfile.new"
mv "$outfile.new" "$outfile"
}
printmsg() {
echo "$1"
}
rsync_ls_lR() {
find "$@" -print | sort | sed 's/ /\\ /g' | xargs "$TOOLDIR/tls"
}
check_perms() {
perms=`"$TOOLDIR/tls" "$1" | sed 's/^[-d]\(.........\).*/\1/'`
if test $perms = $2; then
return 0
fi
echo "permissions: $perms on $1"
echo "should be: $2"
test_fail "failed test $3"
}
rsync_getgroups() {
"$TOOLDIR/getgroups"
}
@@ -144,7 +118,7 @@ hands_setup() {
####################
# Many machines do not have "mkdir -p", so we have to build up long paths.
# How boring.
makepath() {
makepath () {
echo " makepath $1"
p="$1"
(
@@ -224,19 +198,17 @@ build_rsyncd_conf() {
port=2612
pidfile="$scratchdir/rsyncd.pid"
logfile="$scratchdir/rsyncd.log"
hostname=`uname -n`
cat >"$conf" <<EOF
# rsyncd configuration file autogenerated by $0
pid file = $pidfile
use chroot = no
hosts allow = localhost 127.0.0.1 $hostname
hosts allow = localhost, 127.0.0.1
log file = $logfile
log format = %i %h [%a] %m (%u) %l %f%L
transfer logging = yes
exclude = foobar.baz
max verbosity = 9
uid = 0
gid = 0
@@ -247,10 +219,6 @@ gid = 0
[test-to]
path = $todir
read only = no
[test-scratch]
path = $scratchdir
read only = no
EOF
}

View File

@@ -10,6 +10,8 @@
. "$suitedir/rsync.fns"
set -x
build_symlinks || test_fail "failed to build symlinks"
# Copy recursively, but without -l or -L or -a, and all the symlinks

View File

@@ -9,6 +9,8 @@
. "$suitedir/rsync.fns"
set -x
"$TOOLDIR/trimslash" "/usr/local/bin" "/usr/local/bin/" "/usr/local/bin///" \
"//a//" "////" \
"/Users/Wierd Macintosh Name/// Ooh, translucent plastic/" \

View File

@@ -32,6 +32,8 @@ ln -s ../files/file1 "from/safe/links/"
ln -s ../files/file2 "from/safe/links/"
ln -s ../../unsafe/unsafefile "from/safe/links/"
set -x
echo "rsync with relative path and just -a";
$RSYNC -avv from/safe/ to
test_symlink to/links/file1

View File

@@ -9,15 +9,12 @@
. "$suitedir/rsync.fns"
# This test exercises the wildmatch() function (with no options) and the
# wildmatch_join() function (using -x and/or -e).
for opts in "" -x1 "-x1 -e1" "-x1 -e1se" -x2 "-x2 -ese" -x3 "-x3 -e1" -x4 "-x4 -e2e" -x5 "-x5 -es"; do
echo Running wildtest with "$opts"
"$TOOLDIR/wildtest" $opts "$srcdir/wildtest.txt" >"$scratchdir/wild.out"
diff $diffopt "$scratchdir/wild.out" - <<EOF
set -x
"$TOOLDIR/wildtest" "$srcdir/wildtest.txt" >"$scratchdir/wild.out"
diff $diffopt "$scratchdir/wild.out" - <<EOF
No wildmatch errors found.
EOF
done
# The script would have aborted on error, so getting here means we've won.
exit 0

49
tls.c
View File

@@ -1,8 +1,6 @@
/*
* Trivial ls for comparing two directories after running an rsync.
/* -*- c-file-style: "linux" -*-
*
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
* Copyright (C) 2003, 2004, 2005 Wayne Davison
* Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version
@@ -13,12 +11,17 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* The problem with using the system's own ls is that some features
/**
* @file tls.c
*
* Trivial @c ls for comparing two directories after running an rsync.
*
* The problem with using the system's own ls is that some features
* have little quirks that make directories look different when for
* our purposes they're the same -- for example, the BSD braindamage
* about setting the mode on symlinks based on your current umask.
@@ -31,7 +34,9 @@
*
* A key requirement for this program is that the output be "very
* reproducible." So we mask away information that can accidentally
* change. */
* change.
**/
#include "rsync.h"
@@ -43,6 +48,7 @@ int read_only = 1;
int list_only = 0;
int preserve_perms = 0;
static void failed(char const *what, char const *where)
{
fprintf(stderr, PROGRAM ": %s %s: %s\n",
@@ -50,6 +56,8 @@ static void failed(char const *what, char const *where)
exit(1);
}
static void list_file(const char *fname)
{
STRUCT_STAT buf;
@@ -74,7 +82,7 @@ static void list_file(const char *fname)
buf.st_mode &= ~0777;
buf.st_mtime = (time_t)0;
buf.st_uid = buf.st_gid = 0;
strlcpy(linkbuf, " -> ", sizeof linkbuf);
strcpy(linkbuf, " -> ");
/* const-cast required for silly UNICOS headers */
len = readlink((char *) fname, linkbuf+4, sizeof(linkbuf) - 4);
if (len == -1)
@@ -91,16 +99,16 @@ static void list_file(const char *fname)
if (buf.st_mtime) {
mt = gmtime(&buf.st_mtime);
snprintf(datebuf, sizeof datebuf,
"%04d-%02d-%02d %02d:%02d:%02d",
(int)mt->tm_year + 1900,
(int)mt->tm_mon + 1,
(int)mt->tm_mday,
(int)mt->tm_hour,
(int)mt->tm_min,
(int)mt->tm_sec);
} else
strlcpy(datebuf, " ", sizeof datebuf);
sprintf(datebuf, "%04d-%02d-%02d %02d:%02d:%02d",
mt->tm_year + 1900,
mt->tm_mon + 1,
mt->tm_mday,
mt->tm_hour,
mt->tm_min,
mt->tm_sec);
} else {
strcpy(datebuf, " ");
}
/* TODO: Perhaps escape special characters in fname? */
@@ -116,6 +124,7 @@ static void list_file(const char *fname)
datebuf, fname, linkbuf);
}
int
main(int argc, char *argv[])
{

103
token.c
View File

@@ -1,84 +1,67 @@
/*
* Routines used by the file-transfer code.
*
* Copyright (C) 1996 Andrew Tridgell
* Copyright (C) 1996 Paul Mackerras
* Copyright (C) 2003, 2004, 2005 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
Copyright (C) Andrew Tridgell 1996
Copyright (C) Paul Mackerras 1996
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "rsync.h"
#include "zlib/zlib.h"
extern int do_compression;
extern int module_id;
extern int def_compress_level;
static int compression_level, per_file_default_level;
static int compression_level = Z_DEFAULT_COMPRESSION;
/* determine the compression level based on a wildcard filename list */
void set_compression(char *fname)
{
static char *match_list;
char *s;
char *dont;
char *tok;
if (!do_compression)
return;
if (!match_list) {
char *t, *f = lp_dont_compress(module_id);
int len = strlen(f);
if (!(match_list = t = new_array(char, len + 2)))
out_of_memory("set_compression");
while (*f) {
if (*f == ' ') {
f++;
continue;
}
do {
if (isupper(*(unsigned char *)f))
*t++ = tolower(*(unsigned char *)f);
else
*t++ = *f;
} while (*++f != ' ' && *f);
*t++ = '\0';
}
/* Optimize a match-string of "*". */
if (t - match_list == 2 && match_list[0] == '*') {
t = match_list;
per_file_default_level = 0;
} else
per_file_default_level = def_compress_level;
*t++ = '\0';
}
compression_level = Z_DEFAULT_COMPRESSION;
dont = lp_dont_compress(module_id);
compression_level = per_file_default_level;
if (!*match_list)
if (!dont || !*dont)
return;
if ((s = strrchr(fname, '/')) != NULL)
fname = s + 1;
if (dont[0] == '*' && !dont[1]) {
/* an optimization to skip the rest of this routine */
compression_level = 0;
return;
}
for (s = match_list; *s; s += strlen(s) + 1) {
if (iwildmatch(s, fname)) {
dont = strdup(dont);
fname = strdup(fname);
if (!dont || !fname)
return;
strlower(dont);
strlower(fname);
for (tok = strtok(dont, " "); tok; tok = strtok(NULL, " ")) {
if (wildmatch(tok, fname)) {
compression_level = 0;
break;
}
}
free(dont);
free(fname);
}
/* non-compressing recv token */
@@ -108,6 +91,7 @@ static int32 simple_recv_token(int f, char **data)
return n;
}
/* non-compressing send token */
static void simple_send_token(int f, int32 token, struct map_struct *buf,
OFF_T offset, int32 n)
@@ -126,6 +110,7 @@ static void simple_send_token(int f, int32 token, struct map_struct *buf,
write_int(f, -(token+1));
}
/* Flag bytes in compressed stream are encoded as follows: */
#define END_FLAG 0 /* that's all folks */
#define TOKEN_LONG 0x20 /* followed by 32-bit token number */
@@ -189,8 +174,10 @@ send_deflated_token(int f, int32 token, struct map_struct *buf, OFF_T offset,
last_run_end = 0;
run_start = token;
flush_pending = 0;
} else if (last_token == -2) {
run_start = token;
} else if (nb != 0 || token != last_token + 1
|| token >= run_start + 65536) {
/* output previous run */
@@ -294,6 +281,7 @@ send_deflated_token(int f, int32 token, struct map_struct *buf, OFF_T offset,
}
}
/* tells us what the receiver is in the middle of doing */
static enum { r_init, r_idle, r_running, r_inflating, r_inflated } recv_state;
@@ -492,6 +480,7 @@ void send_token(int f, int32 token, struct map_struct *buf, OFF_T offset,
send_deflated_token(f, token, buf, offset, n, toklen);
}
/*
* receive a token or buffer from the other end. If the reurn value is >0 then
* it is a data buffer of that length, and *data will point at the data.

Some files were not shown because too many files have changed in this diff Show More