mirror of
https://github.com/RsyncProject/rsync.git
synced 2026-05-25 07:15:35 -04:00
Compare commits
170 Commits
v2.6.4pre4
...
v2.6.5
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2dfe1c37ad | ||
|
|
b9949780f4 | ||
|
|
5fe857d4be | ||
|
|
3d86c6b18f | ||
|
|
0f0b2e66b8 | ||
|
|
5d24ee71ad | ||
|
|
3a05c5d3ce | ||
|
|
89ec535af5 | ||
|
|
e96d7972c4 | ||
|
|
962a3f0b6e | ||
|
|
cbb5fa4f07 | ||
|
|
b57907efb2 | ||
|
|
26beb7861f | ||
|
|
6e8b9f1341 | ||
|
|
6efe94167f | ||
|
|
51cc96e469 | ||
|
|
bdedced84b | ||
|
|
f497ad722d | ||
|
|
339eb8943e | ||
|
|
c36864e40e | ||
|
|
af6155bb0e | ||
|
|
605fed4b46 | ||
|
|
ac40b74788 | ||
|
|
3e6ddb3738 | ||
|
|
9ac756c6ea | ||
|
|
3b0a30eba8 | ||
|
|
bac7259081 | ||
|
|
4d474ad513 | ||
|
|
e50e82ab40 | ||
|
|
4922175589 | ||
|
|
a289f89fbe | ||
|
|
ba64001df8 | ||
|
|
b225b089b8 | ||
|
|
557a35f55b | ||
|
|
1848fd6fa1 | ||
|
|
f2a4853c93 | ||
|
|
e65154085c | ||
|
|
e4676bb59b | ||
|
|
3b968014c9 | ||
|
|
21b9b93377 | ||
|
|
c4d1b2983d | ||
|
|
7d7a34aeb2 | ||
|
|
65c84700fc | ||
|
|
5a727522f0 | ||
|
|
1599754727 | ||
|
|
d90338cec6 | ||
|
|
d0e94abb40 | ||
|
|
d8c4d6de10 | ||
|
|
74ba98a51b | ||
|
|
c296031d9f | ||
|
|
81c453b16a | ||
|
|
4a34c6f176 | ||
|
|
9b3150bd2e | ||
|
|
6f2245c8fa | ||
|
|
0f9941dc5a | ||
|
|
060f31500b | ||
|
|
7c2a83c635 | ||
|
|
97e3c50cd9 | ||
|
|
b2360dabf6 | ||
|
|
723160280f | ||
|
|
fa92818af3 | ||
|
|
289a32167c | ||
|
|
95e107db96 | ||
|
|
513fd04d21 | ||
|
|
7a16e12207 | ||
|
|
de8252f67f | ||
|
|
98e4741463 | ||
|
|
028245a57b | ||
|
|
2765f2e4a7 | ||
|
|
79db59d1a7 | ||
|
|
c48cff9fbe | ||
|
|
f4b8e829e9 | ||
|
|
468d766819 | ||
|
|
f3ab64d3a8 | ||
|
|
a234bca4ef | ||
|
|
42e9c7eb56 | ||
|
|
9d19f8a5fe | ||
|
|
24e61cffe3 | ||
|
|
3556fe5d86 | ||
|
|
ee887d98f6 | ||
|
|
5c7b1feb4c | ||
|
|
3cd5301f40 | ||
|
|
d8169e6f6b | ||
|
|
c4833b024e | ||
|
|
2a5d5a8cc4 | ||
|
|
f7112154e9 | ||
|
|
f83051b2e3 | ||
|
|
2e42adb302 | ||
|
|
c09ebb8c04 | ||
|
|
042dc7360e | ||
|
|
7a6e294f7b | ||
|
|
97e786c331 | ||
|
|
8ee6adefe3 | ||
|
|
64c37826e4 | ||
|
|
2e8015e0da | ||
|
|
5b6281afcf | ||
|
|
e732fb0c4f | ||
|
|
b10917a426 | ||
|
|
7ae64260e0 | ||
|
|
f97f6bcd3a | ||
|
|
e86d98cbaa | ||
|
|
6afb90778b | ||
|
|
32c7f91a14 | ||
|
|
b28a27e9e9 | ||
|
|
15164c0aa9 | ||
|
|
bf011fedfc | ||
|
|
d7d11b7ebd | ||
|
|
9a929c8f68 | ||
|
|
298d8c0a9b | ||
|
|
a054570942 | ||
|
|
a0009fc30d | ||
|
|
beb51aa09e | ||
|
|
e8a96e275e | ||
|
|
11e758a430 | ||
|
|
d630f53e0d | ||
|
|
5918daf8a4 | ||
|
|
326bb56e40 | ||
|
|
f96154f44c | ||
|
|
45c5b903eb | ||
|
|
5037cf3adf | ||
|
|
180443af42 | ||
|
|
4f3f97fbde | ||
|
|
664cf3278a | ||
|
|
cd36049cd1 | ||
|
|
c2523a0541 | ||
|
|
92739a0aa7 | ||
|
|
cd908ef4ff | ||
|
|
ebd33e0cea | ||
|
|
5f2c5bf110 | ||
|
|
417099fa20 | ||
|
|
626bec8e84 | ||
|
|
a06e2b7cab | ||
|
|
3ae5367ff2 | ||
|
|
b4ef0bca47 | ||
|
|
4313d6f9c0 | ||
|
|
2a0dd9bd70 | ||
|
|
3eeac9bc7e | ||
|
|
67de72bd9b | ||
|
|
552a218468 | ||
|
|
d940151496 | ||
|
|
f5c7f4abe7 | ||
|
|
3ae6c1875d | ||
|
|
1ad6a7f611 | ||
|
|
89d26123ff | ||
|
|
46bffd98cb | ||
|
|
41b84ce012 | ||
|
|
de392f1e5c | ||
|
|
0455cd933d | ||
|
|
d9c0051fae | ||
|
|
126e7affb7 | ||
|
|
624d6be2a5 | ||
|
|
16f960feb5 | ||
|
|
e145d51ba6 | ||
|
|
dcbae65444 | ||
|
|
b4bf2b5a7e | ||
|
|
9baed7609c | ||
|
|
1c2efa1706 | ||
|
|
80a24d52d4 | ||
|
|
af9f56a09d | ||
|
|
ddd74b67be | ||
|
|
7b558d7f8b | ||
|
|
c87ae64a82 | ||
|
|
b9f0ca7274 | ||
|
|
c1759b9fa2 | ||
|
|
9c63d83d3d | ||
|
|
1ed91a04fe | ||
|
|
154cdaaa40 | ||
|
|
33c4b445ef | ||
|
|
53135fe89a | ||
|
|
083acd496d |
11
COPYING
11
COPYING
@@ -2,7 +2,7 @@
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
675 Mass Ave, Cambridge, MA 02139, 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.
|
||||
|
||||
@@ -279,7 +279,7 @@ POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
Appendix: How to Apply These Terms to Your New Programs
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
@@ -291,7 +291,7 @@ convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) 19yy <name of author>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
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
|
||||
@@ -305,14 +305,15 @@ the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
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.
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
|
||||
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) 19yy 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.
|
||||
|
||||
466
NEWS
466
NEWS
@@ -1,381 +1,181 @@
|
||||
NEWS for rsync 2.6.4 (30 March 2005)
|
||||
Protocol: 29 (changed)
|
||||
Changes since 2.6.3:
|
||||
NEWS for rsync 2.6.5 (1 Jun 2005)
|
||||
Protocol: 29 (unchanged)
|
||||
Changes since 2.6.4:
|
||||
|
||||
OUTPUT CHANGES:
|
||||
|
||||
- When rsync deletes a directory and outputs a verbose message about
|
||||
it, it now appends a trailing slash to the name instead of (only
|
||||
sometimes) outputting a preceding "directory " string.
|
||||
- Non-printable chars in filenames are now output using backslash-
|
||||
escaped characters rather than '?'s. Any non-printable character is
|
||||
output using 3 digits of octal (e.g. "\n" -> "\012"), and a backslash
|
||||
is now output as "\\". Rsync also uses your locale setting, which
|
||||
can make it treat fewer high-bit characters as non-printable.
|
||||
|
||||
- The --stats output will contain file-list time-statistics if both
|
||||
sides are 2.6.4, or if the local side is 2.6.4 and the files are
|
||||
being pushed (since the stats come from the sending side).
|
||||
(Requires protocol 29 for a pull.)
|
||||
- If rsync received an empty file-list when pulling files, it would
|
||||
output a "nothing to do" message and exit with a 0 (success) exit
|
||||
status, even if the remote rsync returned an error (it did not do
|
||||
this under the same conditions when pushing files). This was changed
|
||||
to make the pulling behavior the same as the pushing behavior: we
|
||||
now do the normal end-of-run outputting (depending on options) and
|
||||
exit with the appropriate exit status.
|
||||
|
||||
- The "%o" (operation) log-format escape now has a third value (besides
|
||||
"send" and "recv"): "del." (with trailing dot to make it 4 chars).
|
||||
This changes the way deletions are logged in the daemon's log file.
|
||||
|
||||
- When the --log-format option is combined with --verbose, rsync now
|
||||
avoids outputting the name of the file twice in most circumstances.
|
||||
As long as the --log-format item does not refer to any post-transfer
|
||||
items (such as %b or %c), the --log-format message is output prior to
|
||||
the transfer, so --verbose is now the equivalent of a --log-format of
|
||||
'%n%L' (which outputs the name and any link info). If the log output
|
||||
must occur after the transfer to be complete, the only time the name
|
||||
is also output prior to the transfer is when --progress was specified
|
||||
(so that the name will precede the progress stats, and the full
|
||||
--log-format output will come after).
|
||||
|
||||
BUG FIXES:
|
||||
|
||||
- Restore the list-clearing behavior of "!" in a .cvsignore file (2.6.3
|
||||
was only treating it as a special token in an rsync include/exclude
|
||||
file).
|
||||
- A crash bug was fixed when a daemon had its "path" set to "/", did
|
||||
not have chroot enabled, and used some anchored excludes in the
|
||||
rsyncd.conf file.
|
||||
|
||||
- The combination of --verbose and --dry-run now mentions the full list
|
||||
of changes that would be output without --dry-run.
|
||||
- Fixed a bug in the transfer of a single file when -H is specified
|
||||
(rsync would either infinite loop or perhaps crash).
|
||||
|
||||
- Avoid a mkdir warning when removing a directory in the destination
|
||||
that already exists in the --backup-dir.
|
||||
- Fixed a case where the generator might try (and fail) to tweak the
|
||||
write-permissions of a read-only directory in list-only mode (this
|
||||
only caused an annoying warning message).
|
||||
|
||||
- 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 the cygwin's 2.6.3 rsync package.)
|
||||
- If --compare-dest or --link-dest uses a locally-copied file as the
|
||||
basis for an updated version, log this better when --verbose or -i
|
||||
is in effect.
|
||||
|
||||
- Fixed a potential hang when verbosity is high, the client side is
|
||||
the sender, and the file-list is large.
|
||||
- Fixed the accidental disabling of --backup during the --delete-after
|
||||
processing.
|
||||
|
||||
- Fixed a potential protocol-corrupting bug where the generator could
|
||||
merge a message from the receiver into the middle of a multiplexed
|
||||
packet of data if only part of that data had been written out to the
|
||||
socket when the message from the generator arrived.
|
||||
- Restored the ability to use the --address option in client mode (in
|
||||
addition to its use in daemon mode).
|
||||
|
||||
- We now check if the OS doesn't support using mknod() for creating
|
||||
FIFOs and sockets, and compile-in some compatibility code using
|
||||
mkfifo() and socket() when necessary.
|
||||
- Make sure that some temporary progress information from the delete
|
||||
processing does not get left on the screen when it is followed by a
|
||||
newline.
|
||||
|
||||
- Fixed an off-by-one error in the handling of --max-delete=N. Also,
|
||||
if the --max-delete limit is exceeded during a run, we now output a
|
||||
warning about this at the end of the run and exit with a new error
|
||||
code (25).
|
||||
- When --existing skips a directory with extra verbosity, refer to it
|
||||
as a "directory", not a "file".
|
||||
|
||||
- One place in the code wasn't checking if fork() failed.
|
||||
- When transferring a single file to a different-named file, any
|
||||
generator messages that are source-file related no longer refer to
|
||||
the file by the destination filename.
|
||||
|
||||
- The "ignore nonreadable" daemon parameter used to erroneously affect
|
||||
readable symlinks that pointed to a non-existent file.
|
||||
- Fixed a bug where hard-linking a group of files might fail if the
|
||||
generator hasn't created a needed destination directory yet.
|
||||
|
||||
- If the OS does not have lchown() and a chown() of a symlink will
|
||||
affect the referent of a symlink (as it should), we no longer try
|
||||
to set the user and group of a symlink.
|
||||
- Fixed a bug where a hard-linked group of files that is newly-linked
|
||||
to a file in a --link-dest dir doesn't link the files from the rest
|
||||
of the cluster.
|
||||
|
||||
- The generator now properly runs the hard-link loop and the dir-time
|
||||
rewriting loop after we're sure that the redo phase is complete.
|
||||
- When deleting files with the --one-file-system (-x) option set, rsync
|
||||
no longer tries to remove files from inside a mount-point on the
|
||||
receiving side. Also, we don't complain about being unable to remove
|
||||
the mount-point dir.
|
||||
|
||||
- When --backup was specified with --partial-dir=DIR, where DIR is a
|
||||
relative path, the backup code was erroneously trying to backup a
|
||||
file that was put into the partial-dir.
|
||||
- Fixed a compatibility problem when using --cvs-ignore (-C) and
|
||||
sending files to an older rsync without using --delete.
|
||||
|
||||
- If a file gets resent in a single transfer and the --backup option is
|
||||
enabled along with --inplace, rsync no longer performs a duplicate
|
||||
backup (it used to overwrite the first backup with the failed file).
|
||||
- Make sure that a "- !" or "+ !" include/exclude pattern does not
|
||||
trigger the list-clearing action that is reserved for "!".
|
||||
|
||||
- One call to flush_write_file() was not being checked for an error.
|
||||
- Avoid a timeout in the generator when the sender/receiver aren't
|
||||
handling the generator's checksum output quickly enough.
|
||||
|
||||
- The --no-relative option was not being sent from the client to a
|
||||
server sender.
|
||||
- Fixed the omission of some directories in the delete processing when
|
||||
--relative (-R) was combined with a source path that had a trailing
|
||||
slash.
|
||||
|
||||
- If an rsync daemon specified "dont compress = ..." for a file and the
|
||||
client tried to specify --compress, the libz code was not handling a
|
||||
compression level of 0 properly. This could cause a transfer failure
|
||||
if the block-size for a file was large enough (e.g. rsync might have
|
||||
exited with an error for large files).
|
||||
- Fixed a case where rsync would erroneously delete some files and then
|
||||
re-transfer them when the options --relative (-R) and --recursive
|
||||
(-r) were both enabled (along with --delete) and a source path had a
|
||||
trailing slash.
|
||||
|
||||
- Fixed a bug that would sometimes surface when using --compress and
|
||||
sending a file with a block-size larger than 64K (either manually
|
||||
specified, or computed due to the file being really large). Prior
|
||||
versions of rsync would sometimes fail to decompress the data
|
||||
properly, and thus the transferred file would fail its verification.
|
||||
- Make sure that --max-size doesn't affect a device or a symlink.
|
||||
|
||||
- If a daemon can't open the specified log file (i.e. syslog is not
|
||||
being used), die without crashing. We also output an error about
|
||||
the failure on stderr (which will only be seen if --no-detach was
|
||||
specified) and exit with a new error code (6).
|
||||
- Make sure that a system with a really small MAXPATHLEN does not cause
|
||||
the buffers in readfd_unbuffered() to be too small to receive normal
|
||||
messages. (This mainly affected Cygwin.)
|
||||
|
||||
- A local transfer no longer duplicates all its include/exclude options
|
||||
(since the forked process already has a copy of the exclude list,
|
||||
there's no need to send them a set of duplicates).
|
||||
- If a source pathname ends with a filename of "..", treat it as if
|
||||
"../" had been specified (so that we don't copy files to the parent
|
||||
dir of the destination).
|
||||
|
||||
- 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.)
|
||||
- If --delete is combined with a file-listing rsync command (i.e. no
|
||||
transfer is happening), avoid outputting a warning that we couldn't
|
||||
delete anything.
|
||||
|
||||
- When --timeout is specified, lulls that occur in the transfer while
|
||||
the generator is doing work that does not generate socket traffic
|
||||
(looking for changed files, deleting files, doing directory-time
|
||||
touch-ups, etc.) will cause a new keep-alive packet to be sent that
|
||||
should keep the transfer going as long as the generator continues to
|
||||
make progress. (Requires protocol 29.)
|
||||
- If --stats is specified with --delete-after, ensure that all the
|
||||
"deleting" messages are output before the statistics.
|
||||
|
||||
- The stat size of a device is not added to the total file size of the
|
||||
items in the transfer (the size might be undefined on some OSes).
|
||||
|
||||
- Fixed a problem with refused-option messages sometimes not making it
|
||||
back to the client side when a remote --files-from was in effect and
|
||||
the daemon was the receiver.
|
||||
|
||||
- The --compare-dest option was not updating a file that differred in
|
||||
(the preserved) attributes from the version in the compare-dest DIR.
|
||||
|
||||
- When rsync is copying files into a write-protected directory, fixed
|
||||
the change-report output for the directory so that we don't report
|
||||
an identical directory as changed.
|
||||
- Improved one "if" in the deletion code that was only checking errno
|
||||
for ENOTEMPTY when it should have also been checking for EEXIST (for
|
||||
compatibility with OS variations).
|
||||
|
||||
ENHANCEMENTS:
|
||||
|
||||
- Rsync now supports popt's option aliases, which means that you can
|
||||
use /etc/popt and/or ~/.popt to create your own option aliases.
|
||||
- Added the --only-write-batch=FILE option that may be used (instead
|
||||
of --write-batch=FILE) to create a batch file without doing any
|
||||
actual updating of the destination. This allows you to divert all
|
||||
the file-updating data away from a slow data link (as long as you
|
||||
are pushing the data to the remote server when creating the batch).
|
||||
|
||||
- Added the --delete-during (--del) option which will delete files
|
||||
from the receiving side incrementally as each directory in the
|
||||
transfer is being processed. This makes it more efficient than the
|
||||
default, before-the-transfer behavior, which is now also available as
|
||||
--delete-before (and is still the default --delete-WHEN option that
|
||||
will be chosen if --delete or --delete-excluded is specified without
|
||||
a --delete-WHEN choice). All the --del* options infer --delete, so
|
||||
an rsync daemon that refuses "delete" will still refuse to allow any
|
||||
file-deleting options (including the new --remove-sent-files option).
|
||||
- When the generator is taking a long time to fill up its output buffer
|
||||
(e.g. if the transferred files are few, small, or missing), it now
|
||||
periodically flushes the output buffer so that the sender/receiver
|
||||
can get started on the files sooner rather than later.
|
||||
|
||||
- All the --delete-WHEN options are now more memory efficient:
|
||||
Previously an duplicate set of file-list objects was created on the
|
||||
receiving side for the entire destination hierarchy. The new
|
||||
algorithm only creates one directory of objects at a time (for files
|
||||
inside the transfer).
|
||||
- Improved the keep-alive code to handle a long silence between the
|
||||
sender and the receiver that can occur when the sender is receiving
|
||||
the checksum data for a large file.
|
||||
|
||||
- Added the --copy-dest option, which works like --link-dest except
|
||||
that it locally copies identical files instead of hard-linking them.
|
||||
- Improved the auth-errors that are logged by the daemon to include
|
||||
some information on why the authorization failed: wrong user,
|
||||
password mismatch, etc. (The client-visible message is unchanged!)
|
||||
|
||||
- Added support for specifying multiple --compare-dest, --copy-dest, or
|
||||
--link-dest options, but only of a single type. (Promoted from the
|
||||
patches dir and enhanced.) (Requires protocol 29.)
|
||||
- Improved the client's handling of an "@ERROR" from a daemon so that
|
||||
it does not complain about an unexpectedly closed socket (since we
|
||||
really did expect the socket to close).
|
||||
|
||||
- Added the --max-size option. (Promoted from the patches dir.)
|
||||
- If the daemon can't open the log-file specified in rsyncd.conf, fall
|
||||
back to using syslog and log an appropriate warning. This is better
|
||||
than what was typically a totally silent (and fatal) failure (since a
|
||||
daemon is not usually run with the --no-detach option that was
|
||||
necessary to see the error on stderr).
|
||||
|
||||
- The daemon-mode options are now separated from the normal rsync
|
||||
options so that they can't be mixed together. This makes it
|
||||
impossible to start a daemon that has improper default option values
|
||||
(which could cause problems when a client connects, such as hanging
|
||||
or crashing).
|
||||
- The man pages now consistently refer to an rsync daemon as a "daemon"
|
||||
instead of a "server" (to distinguish it from the server process in a
|
||||
non-daemon transfer).
|
||||
|
||||
- The --bwlimit option may now be used in combination with --daemon
|
||||
to specify both a default value for the daemon side and a value
|
||||
that cannot be exceeded by a user-specified --bwlimit option.
|
||||
|
||||
- Added the "port" parameter to the rsyncd.conf file. (Promoted from
|
||||
the patches dir.) Also added "address". The command-line options
|
||||
take precedence over a config-file option, as expected.
|
||||
|
||||
- In _exit_cleanup(): when we are exiting with a partially-received
|
||||
file, we now flush any data in the write-cache before closing the
|
||||
partial file.
|
||||
|
||||
- The --inplace support was enhanced to work with --compare-dest,
|
||||
--link-dest, and (the new) --copy-dest options. (Requires protocol
|
||||
29.)
|
||||
|
||||
- Added the --dirs (-d) option for an easier way to copy directories
|
||||
without recursion.
|
||||
|
||||
- Added the --list-only option, which is mainly a way for the client to
|
||||
put the server into listing mode without needing to resort to any
|
||||
internal option kluges (e.g. the age-old use of "-r --exclude="/*/*"
|
||||
for a non-recursive listing). This option is used automatically
|
||||
(behind the scenes) when a modern rsync speaks to a modern daemon,
|
||||
but may also be specified manually if you want to force the use of
|
||||
the --list-only option over a remote-shell connection.
|
||||
|
||||
- Added the --omit-dir-times (-O) option, which will avoid updating
|
||||
the modified time for directories when --times was specified. This
|
||||
option will avoid an extra pass through the file-list at the end of
|
||||
the transfer (to tweak all the directory times), which may provide
|
||||
an appreciable speedup for a really large transfer. (Promoted from
|
||||
the patches dir.)
|
||||
|
||||
- Added the --filter (-f) option and its helper option, -F. Filter
|
||||
rules are an extension to the existing include/exclude handling
|
||||
that also supports nested filter files as well as per-directory
|
||||
filter files (like .cvsignore, but with full filter-rule parsing).
|
||||
This new option was chosen in order to ensure that all existing
|
||||
include/exclude processing remained 100% compatible with older
|
||||
versions. Protocol 29 is needed for full filter-rule support, but
|
||||
backward-compatible rules work with earlier protocol versions.
|
||||
(Promoted from the patches dir and enhanced.)
|
||||
|
||||
- Added the --delay-updates option that puts all updated files into
|
||||
a temporary directory (by default ".~tmp~", but settable via the
|
||||
--partial-dir=DIR option) until the end of the transfer. This
|
||||
makes the updates a little more atomic for a large transfer.
|
||||
|
||||
- If rsync is put into the background, any output from --progress is
|
||||
reduced.
|
||||
|
||||
- Documented the "max verbosity" setting for rsyncd.conf. (This
|
||||
setting was added a couple releases ago, but left undocumented.)
|
||||
|
||||
- The sender and the generator now double-check the file-list index
|
||||
they are given, and refuse to try to do a file transfer on a
|
||||
non-file index (since that would indicate that something had gone
|
||||
very wrong).
|
||||
|
||||
- Added the --itemize-changes (-i) option, which is a way to output a
|
||||
more detailed list of what files changed and in what way. The effect
|
||||
is the same as specifying a --log-format of "%i %n%L" (see both the
|
||||
rsync and rsyncd.conf manpages). Works with --dry-run too.
|
||||
|
||||
- Added the --fuzzy (-y) option, which attempts to find a basis file
|
||||
for a file that is being created from scratch. The current algorithm
|
||||
only looks in the destination directory for the created file, but it
|
||||
does attempt to find a match based on size/mod-time (in case the file
|
||||
was renamed with no other changes) as well as based on a fuzzy
|
||||
name-matching algorithm. This option requires protocol 29 because it
|
||||
needs the new file-sorting order. (Promoted from patches dir and
|
||||
enhanced.) (Requires protocol 29.)
|
||||
|
||||
- Added the --remove-sent-files option, which lets you move files
|
||||
between systems.
|
||||
|
||||
- The hostname in HOST:PATH or HOST::PATH may now be an IPv6 literal
|
||||
enclosed in '[' and ']' (e.g. "[::1]"). (We already allowed IPv6
|
||||
literals in the rsync://HOST:PORT/PATH format.)
|
||||
|
||||
- When rsync recurses to build the file list, it no longer keeps open
|
||||
one or more directory handles from the dir's parent dirs.
|
||||
|
||||
- When building under windows, the default for --daemon is now to
|
||||
avoid detaching, requiring the new --detach option to force rsync
|
||||
to detach.
|
||||
|
||||
- The --dry-run option can now be combined with either --write-batch or
|
||||
--read-batch, allowing you to run a do-nothing test command to see
|
||||
what would happen without --dry-run.
|
||||
|
||||
- The daemon's "read only" config item now sets an internal read_only
|
||||
variable that makes extra sure that no write/delete calls on the
|
||||
read-only side can succeed.
|
||||
|
||||
- Improved the option descriptions in the --help text.
|
||||
|
||||
SUPPORT FILES:
|
||||
|
||||
- Added atomic-rsync to the support dir: a perl script that will
|
||||
transfer some files using rsync, and then move the updated files into
|
||||
place all at once at the end of the transfer. Only works when
|
||||
pulling, and uses --link-dest and a parallel hierarchy of files to
|
||||
effect its update.
|
||||
|
||||
- Added mnt-excl to the support dir: a perl script that takes the
|
||||
/proc/mounts file and translates it into a set of excludes that will
|
||||
exclude all mount points (even mapped mounts to the same disk). The
|
||||
excludes are made relative to the specified source dir and properly
|
||||
anchored.
|
||||
|
||||
- Added savetransfer.c to the support dir: a C program that can make
|
||||
a copy of all the data that flows over the wire. This lets you test
|
||||
for data corruption (by saving the data on both the sending side and
|
||||
the receiving side) and provides one way to debug a protocol error.
|
||||
|
||||
- Added rrsync to the support dir: this is an updated version of Joe
|
||||
Smith's restricted rsync perl script. This helps to ensure that only
|
||||
certain rsync commands can be run by an ssh invocation.
|
||||
- Made a small change to the rrsync script (restricted rsync -- in the
|
||||
support dir) to make a read-only server reject all --remove-* options
|
||||
when sending files (to future-proof it against the possibility of
|
||||
other similar options being added at some point).
|
||||
|
||||
INTERNAL:
|
||||
|
||||
- Added better checking of the checksum-header values that come over
|
||||
the socket.
|
||||
- Rsync now calls setlocale(LC_CTYPE, ""). This enables isprint() to
|
||||
better discern which filename characters need to be escaped in
|
||||
messages (which should result in fewer escaped characters in some
|
||||
locales).
|
||||
|
||||
- Merged a variety of file-deleting functions into a single function so
|
||||
that it is easier to maintain.
|
||||
- Improved the naming of the log-file open/reopen/close functions.
|
||||
|
||||
- Improved the type of some variables (particularly blocksize vars) for
|
||||
consistency and proper size.
|
||||
|
||||
- Got rid of the uint64 type (which we didn't need).
|
||||
|
||||
- Use a slightly more compatible set of core #include directives.
|
||||
|
||||
- Defined int32 in a way that ensures that the build dies if we can't
|
||||
find a variable with at least 32 bits.
|
||||
|
||||
PROTOCOL DIFFERENCES FOR VERSION 29:
|
||||
|
||||
- A 16-bit flag-word is transmitted after every file-list index. This
|
||||
indicates what is changing between the sender and the receiver. The
|
||||
generator now transmits an index and a flag-word to indicate when
|
||||
dirs and symlinks have changed (instead of producing a message),
|
||||
which makes the outputting of the information more consistent and
|
||||
less prone to screen corruption (because the local receiver/sender is
|
||||
now outputting all the file-change info messages).
|
||||
|
||||
- If a file is being hard-linked, the ITEM_XNAME_FOLLOWS bit is enabled
|
||||
in the flag-word and the name of the file that was linked immediately
|
||||
follows in vstring format (see below).
|
||||
|
||||
- If a file is being transferred with an alternate-basis file, the
|
||||
ITEM_BASIS_TYPE_FOLLOWS bit is enabled in the flag-word and a single
|
||||
byte follows, indicating what type of basis file was chosen. If that
|
||||
indicates that a fuzzy-match was selected, the ITEM_XNAME_FOLLOWS bit
|
||||
is set in the flag-word and the name of the match in vstring format
|
||||
follows the basis byte. A vstring is a variable length string that
|
||||
has its size written prior to the string, and no terminating null.
|
||||
If the string is from 1-127 bytes, the length is a single byte. If
|
||||
it is from 128-32767 bytes, the length is written as ((len >> 8) |
|
||||
0x80) followed by (len % 0x100).
|
||||
|
||||
- The sending of exclude names is done using filter-rule syntax. This
|
||||
means that all names have a prefixed rule indicator, even excludes
|
||||
(which used to be sent as a bare pattern, when possible). The -C
|
||||
option will include the per-dir .cvsignore merge file in the list of
|
||||
filter rules so it is positioned correctly (unlike in some older
|
||||
transfer scenarios).
|
||||
|
||||
- Rsync sorts the filename list in a different way: it sorts the subdir
|
||||
names after the non-subdir names for each dir's contents, and it
|
||||
always puts a dir's contents immediately after the dir's name in the
|
||||
list. (Previously an item named "foo.txt" would sort in between
|
||||
directory "foo/" and "foo/bar".)
|
||||
|
||||
- When talking to a protocol 29 rsync daemon, a list-only request
|
||||
is able to note this before the options are sent over the wire and
|
||||
the new --list-only option is included in the options.
|
||||
|
||||
- When the --stats bytes are sent over the wire (or stored in a batch),
|
||||
they now include two elapsed-time values: one for how long it took to
|
||||
build the file-list, and one for how long it took to send it over the
|
||||
wire (each expressed in thousandths of a second).
|
||||
|
||||
- When --delete-excluded is specified with some filter rules (AKA
|
||||
excludes), a client sender will now initiate a send of the rules to
|
||||
the receiver (older protocols used to omit the sending of excludes in
|
||||
this situation since there were no receiver-specific rules that
|
||||
survived --delete-excluded back then). Note that, as with all the
|
||||
filter-list sending, only items that are significant to the other
|
||||
side will actually be sent over the wire, so the filter-rule list
|
||||
that is sent in this scenario is often empty.
|
||||
|
||||
- An index equal to the file-list count is sent as a keep-alive packet
|
||||
from the generator to the sender, which then forwards it on to the
|
||||
receiver. This normally invalid index is only a valid keep-alive
|
||||
packet if the 16-bit flag-word that follows it contains a single bit
|
||||
(ITEM_IS_NEW, which is normally an illegal flag to appear alone).
|
||||
|
||||
- A protocol-29 batch file includes a bit for the setting of the --dirs
|
||||
option and for the setting of the --compress option. Also, the shell
|
||||
script created by --write-batch will use the --filter option instead
|
||||
of --exclude-from to capture any filter rules.
|
||||
- Removed some protocol-compatibility code that was only needed to help
|
||||
someone running a pre-release of 2.6.4.
|
||||
|
||||
BUILD CHANGES:
|
||||
|
||||
- Handle an operating system that use mkdev() in place of makedev().
|
||||
- Added configure option "--disable-locale" to disable any use of
|
||||
setlocale() in the binary.
|
||||
|
||||
- Improved configure to better handle cross-compiling.
|
||||
- Fixed a bug in the SUPPORT{,_HARD}_LINKS #defines which prevented
|
||||
rsync from being built without symlink or hard-link support.
|
||||
|
||||
- Only #define HAVE_REMSH if it is going to be set to 1.
|
||||
|
||||
- Configure now disables the use of mkstemp() under HP-UX (since they
|
||||
refuse to fix its broken handling of large files).
|
||||
|
||||
- Configure now explicitly checks for the lseek64() function so that
|
||||
the code can use HAVE_LSEEK64 instead of inferring lseek64()'s
|
||||
presence based on the presence of the off64_t type.
|
||||
|
||||
- Configure no longer mentions the change in the default remote-shell
|
||||
(from rsh to ssh) that occurred for the 2.6.0 release.
|
||||
|
||||
- Some minor enhancements to the test scripts.
|
||||
|
||||
- Added a few new *.diff files to the patches dir, including a patch
|
||||
that enables the optional copying of extended attributes.
|
||||
|
||||
392
OLDNEWS
392
OLDNEWS
@@ -1,3 +1,394 @@
|
||||
NEWS for rsync 2.6.4 (30 March 2005)
|
||||
Protocol: 29 (changed)
|
||||
Changes since 2.6.3:
|
||||
|
||||
OUTPUT CHANGES:
|
||||
|
||||
- When rsync deletes a directory and outputs a verbose message about
|
||||
it, it now appends a trailing slash to the name instead of (only
|
||||
sometimes) outputting a preceding "directory " string.
|
||||
|
||||
- The --stats output will contain file-list time-statistics if both
|
||||
sides are 2.6.4, or if the local side is 2.6.4 and the files are
|
||||
being pushed (since the stats come from the sending side).
|
||||
(Requires protocol 29 for a pull.)
|
||||
|
||||
- The "%o" (operation) log-format escape now has a third value (besides
|
||||
"send" and "recv"): "del." (with trailing dot to make it 4 chars).
|
||||
This changes the way deletions are logged in the daemon's log file.
|
||||
|
||||
- When the --log-format option is combined with --verbose, rsync now
|
||||
avoids outputting the name of the file twice in most circumstances.
|
||||
As long as the --log-format item does not refer to any post-transfer
|
||||
items (such as %b or %c), the --log-format message is output prior to
|
||||
the transfer, so --verbose is now the equivalent of a --log-format of
|
||||
'%n%L' (which outputs the name and any link info). If the log output
|
||||
must occur after the transfer to be complete, the only time the name
|
||||
is also output prior to the transfer is when --progress was specified
|
||||
(so that the name will precede the progress stats, and the full
|
||||
--log-format output will come after).
|
||||
|
||||
- Non-printable characters in filenames are replaced with a '?' to
|
||||
avoid corrupting the screen or generating empty lines in the output.
|
||||
|
||||
BUG FIXES:
|
||||
|
||||
- Restore the list-clearing behavior of "!" in a .cvsignore file (2.6.3
|
||||
was only treating it as a special token in an rsync include/exclude
|
||||
file).
|
||||
|
||||
- The combination of --verbose and --dry-run now mentions the full list
|
||||
of changes that would be output without --dry-run.
|
||||
|
||||
- Avoid a mkdir warning when removing a directory in the destination
|
||||
that already exists in the --backup-dir.
|
||||
|
||||
- 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 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.
|
||||
|
||||
- Fixed a potential protocol-corrupting bug where the generator could
|
||||
merge a message from the receiver into the middle of a multiplexed
|
||||
packet of data if only part of that data had been written out to the
|
||||
socket when the message from the generator arrived.
|
||||
|
||||
- We now check if the OS doesn't support using mknod() for creating
|
||||
FIFOs and sockets, and compile-in some compatibility code using
|
||||
mkfifo() and socket() when necessary.
|
||||
|
||||
- Fixed an off-by-one error in the handling of --max-delete=N. Also,
|
||||
if the --max-delete limit is exceeded during a run, we now output a
|
||||
warning about this at the end of the run and exit with a new error
|
||||
code (25).
|
||||
|
||||
- One place in the code wasn't checking if fork() failed.
|
||||
|
||||
- The "ignore nonreadable" daemon parameter used to erroneously affect
|
||||
readable symlinks that pointed to a non-existent file.
|
||||
|
||||
- If the OS does not have lchown() and a chown() of a symlink will
|
||||
affect the referent of a symlink (as it should), we no longer try
|
||||
to set the user and group of a symlink.
|
||||
|
||||
- The generator now properly runs the hard-link loop and the dir-time
|
||||
rewriting loop after we're sure that the redo phase is complete.
|
||||
|
||||
- When --backup was specified with --partial-dir=DIR, where DIR is a
|
||||
relative path, the backup code was erroneously trying to backup a
|
||||
file that was put into the partial-dir.
|
||||
|
||||
- If a file gets resent in a single transfer and the --backup option is
|
||||
enabled along with --inplace, rsync no longer performs a duplicate
|
||||
backup (it used to overwrite the first backup with the failed file).
|
||||
|
||||
- One call to flush_write_file() was not being checked for an error.
|
||||
|
||||
- The --no-relative option was not being sent from the client to a
|
||||
server sender.
|
||||
|
||||
- If an rsync daemon specified "dont compress = ..." for a file and the
|
||||
client tried to specify --compress, the libz code was not handling a
|
||||
compression level of 0 properly. This could cause a transfer failure
|
||||
if the block-size for a file was large enough (e.g. rsync might have
|
||||
exited with an error for large files).
|
||||
|
||||
- Fixed a bug that would sometimes surface when using --compress and
|
||||
sending a file with a block-size larger than 64K (either manually
|
||||
specified, or computed due to the file being really large). Prior
|
||||
versions of rsync would sometimes fail to decompress the data
|
||||
properly, and thus the transferred file would fail its verification.
|
||||
|
||||
- If a daemon can't open the specified log file (i.e. syslog is not
|
||||
being used), die without crashing. We also output an error about
|
||||
the failure on stderr (which will only be seen if --no-detach was
|
||||
specified) and exit with a new error code (6).
|
||||
|
||||
- A local transfer no longer duplicates all its include/exclude options
|
||||
(since the forked process already has a copy of the exclude list,
|
||||
there's no need to send them a set of duplicates).
|
||||
|
||||
- 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
|
||||
(looking for changed files, deleting files, doing directory-time
|
||||
touch-ups, etc.) will cause a new keep-alive packet to be sent that
|
||||
should keep the transfer going as long as the generator continues to
|
||||
make progress. (Requires protocol 29.)
|
||||
|
||||
- The stat size of a device is not added to the total file size of the
|
||||
items in the transfer (the size might be undefined on some OSes).
|
||||
|
||||
- Fixed a problem with refused-option messages sometimes not making it
|
||||
back to the client side when a remote --files-from was in effect and
|
||||
the daemon was the receiver.
|
||||
|
||||
- The --compare-dest option was not updating a file that differed in
|
||||
(the preserved) attributes from the version in the compare-dest DIR.
|
||||
|
||||
- When rsync is copying files into a write-protected directory, fixed
|
||||
the change-report output for the directory so that we don't report
|
||||
an identical directory as changed.
|
||||
|
||||
ENHANCEMENTS:
|
||||
|
||||
- Rsync now supports popt's option aliases, which means that you can
|
||||
use /etc/popt and/or ~/.popt to create your own option aliases.
|
||||
|
||||
- Added the --delete-during (--del) option which will delete files
|
||||
from the receiving side incrementally as each directory in the
|
||||
transfer is being processed. This makes it more efficient than the
|
||||
default, before-the-transfer behavior, which is now also available as
|
||||
--delete-before (and is still the default --delete-WHEN option that
|
||||
will be chosen if --delete or --delete-excluded is specified without
|
||||
a --delete-WHEN choice). All the --del* options infer --delete, so
|
||||
an rsync daemon that refuses "delete" will still refuse to allow any
|
||||
file-deleting options (including the new --remove-sent-files option).
|
||||
|
||||
- All the --delete-WHEN options are now more memory efficient:
|
||||
Previously an duplicate set of file-list objects was created on the
|
||||
receiving side for the entire destination hierarchy. The new
|
||||
algorithm only creates one directory of objects at a time (for files
|
||||
inside the transfer).
|
||||
|
||||
- Added the --copy-dest option, which works like --link-dest except
|
||||
that it locally copies identical files instead of hard-linking them.
|
||||
|
||||
- Added support for specifying multiple --compare-dest, --copy-dest, or
|
||||
--link-dest options, but only of a single type. (Promoted from the
|
||||
patches dir and enhanced.) (Requires protocol 29.)
|
||||
|
||||
- Added the --max-size option. (Promoted from the patches dir.)
|
||||
|
||||
- The daemon-mode options are now separated from the normal rsync
|
||||
options so that they can't be mixed together. This makes it
|
||||
impossible to start a daemon that has improper default option values
|
||||
(which could cause problems when a client connects, such as hanging
|
||||
or crashing).
|
||||
|
||||
- The --bwlimit option may now be used in combination with --daemon
|
||||
to specify both a default value for the daemon side and a value
|
||||
that cannot be exceeded by a user-specified --bwlimit option.
|
||||
|
||||
- Added the "port" parameter to the rsyncd.conf file. (Promoted from
|
||||
the patches dir.) Also added "address". The command-line options
|
||||
take precedence over a config-file option, as expected.
|
||||
|
||||
- In _exit_cleanup(): when we are exiting with a partially-received
|
||||
file, we now flush any data in the write-cache before closing the
|
||||
partial file.
|
||||
|
||||
- The --inplace support was enhanced to work with --compare-dest,
|
||||
--link-dest, and (the new) --copy-dest options. (Requires protocol
|
||||
29.)
|
||||
|
||||
- Added the --dirs (-d) option for an easier way to copy directories
|
||||
without recursion. Any directories that are encountered are created
|
||||
on the destination. Specifying a directory with a trailing slash
|
||||
copies its immediate contents to the destination.
|
||||
|
||||
- The --files-from option now implies --dirs (-d).
|
||||
|
||||
- Added the --list-only option, which is mainly a way for the client to
|
||||
put the server into listing mode without needing to resort to any
|
||||
internal option kluges (e.g. the age-old use of "-r --exclude="/*/*"
|
||||
for a non-recursive listing). This option is used automatically
|
||||
(behind the scenes) when a modern rsync speaks to a modern daemon,
|
||||
but may also be specified manually if you want to force the use of
|
||||
the --list-only option over a remote-shell connection.
|
||||
|
||||
- Added the --omit-dir-times (-O) option, which will avoid updating
|
||||
the modified time for directories when --times was specified. This
|
||||
option will avoid an extra pass through the file-list at the end of
|
||||
the transfer (to tweak all the directory times), which may provide
|
||||
an appreciable speedup for a really large transfer. (Promoted from
|
||||
the patches dir.)
|
||||
|
||||
- Added the --filter (-f) option and its helper option, -F. Filter
|
||||
rules are an extension to the existing include/exclude handling
|
||||
that also supports nested filter files as well as per-directory
|
||||
filter files (like .cvsignore, but with full filter-rule parsing).
|
||||
This new option was chosen in order to ensure that all existing
|
||||
include/exclude processing remained 100% compatible with older
|
||||
versions. Protocol 29 is needed for full filter-rule support, but
|
||||
backward-compatible rules work with earlier protocol versions.
|
||||
(Promoted from the patches dir and enhanced.)
|
||||
|
||||
- Added the --delay-updates option that puts all updated files into
|
||||
a temporary directory (by default ".~tmp~", but settable via the
|
||||
--partial-dir=DIR option) until the end of the transfer. This
|
||||
makes the updates a little more atomic for a large transfer.
|
||||
|
||||
- If rsync is put into the background, any output from --progress is
|
||||
reduced.
|
||||
|
||||
- Documented the "max verbosity" setting for rsyncd.conf. (This
|
||||
setting was added a couple releases ago, but left undocumented.)
|
||||
|
||||
- The sender and the generator now double-check the file-list index
|
||||
they are given, and refuse to try to do a file transfer on a
|
||||
non-file index (since that would indicate that something had gone
|
||||
very wrong).
|
||||
|
||||
- Added the --itemize-changes (-i) option, which is a way to output a
|
||||
more detailed list of what files changed and in what way. The effect
|
||||
is the same as specifying a --log-format of "%i %n%L" (see both the
|
||||
rsync and rsyncd.conf manpages). Works with --dry-run too.
|
||||
|
||||
- Added the --fuzzy (-y) option, which attempts to find a basis file
|
||||
for a file that is being created from scratch. The current algorithm
|
||||
only looks in the destination directory for the created file, but it
|
||||
does attempt to find a match based on size/mod-time (in case the file
|
||||
was renamed with no other changes) as well as based on a fuzzy
|
||||
name-matching algorithm. This option requires protocol 29 because it
|
||||
needs the new file-sorting order. (Promoted from patches dir and
|
||||
enhanced.) (Requires protocol 29.)
|
||||
|
||||
- Added the --remove-sent-files option, which lets you move files
|
||||
between systems.
|
||||
|
||||
- The hostname in HOST:PATH or HOST::PATH may now be an IPv6 literal
|
||||
enclosed in '[' and ']' (e.g. "[::1]"). (We already allowed IPv6
|
||||
literals in the rsync://HOST:PORT/PATH format.)
|
||||
|
||||
- When rsync recurses to build the file list, it no longer keeps open
|
||||
one or more directory handles from the dir's parent dirs.
|
||||
|
||||
- When building under windows, the default for --daemon is now to
|
||||
avoid detaching, requiring the new --detach option to force rsync
|
||||
to detach.
|
||||
|
||||
- The --dry-run option can now be combined with either --write-batch or
|
||||
--read-batch, allowing you to run a do-nothing test command to see
|
||||
what would happen without --dry-run.
|
||||
|
||||
- The daemon's "read only" config item now sets an internal read_only
|
||||
variable that makes extra sure that no write/delete calls on the
|
||||
read-only side can succeed.
|
||||
|
||||
- The log-format % escapes can now have a numeric field width in
|
||||
between the % and the escape letter (e.g. "%-40n %08p").
|
||||
|
||||
- Improved the option descriptions in the --help text.
|
||||
|
||||
SUPPORT FILES:
|
||||
|
||||
- Added atomic-rsync to the support dir: a perl script that will
|
||||
transfer some files using rsync, and then move the updated files into
|
||||
place all at once at the end of the transfer. Only works when
|
||||
pulling, and uses --link-dest and a parallel hierarchy of files to
|
||||
effect its update.
|
||||
|
||||
- Added mnt-excl to the support dir: a perl script that takes the
|
||||
/proc/mounts file and translates it into a set of excludes that will
|
||||
exclude all mount points (even mapped mounts to the same disk). The
|
||||
excludes are made relative to the specified source dir and properly
|
||||
anchored.
|
||||
|
||||
- Added savetransfer.c to the support dir: a C program that can make
|
||||
a copy of all the data that flows over the wire. This lets you test
|
||||
for data corruption (by saving the data on both the sending side and
|
||||
the receiving side) and provides one way to debug a protocol error.
|
||||
|
||||
- Added rrsync to the support dir: this is an updated version of Joe
|
||||
Smith's restricted rsync perl script. This helps to ensure that only
|
||||
certain rsync commands can be run by an ssh invocation.
|
||||
|
||||
INTERNAL:
|
||||
|
||||
- Added better checking of the checksum-header values that come over
|
||||
the socket.
|
||||
|
||||
- Merged a variety of file-deleting functions into a single function so
|
||||
that it is easier to maintain.
|
||||
|
||||
- Improved the type of some variables (particularly blocksize vars) for
|
||||
consistency and proper size.
|
||||
|
||||
- Got rid of the uint64 type (which we didn't need).
|
||||
|
||||
- Use a slightly more compatible set of core #include directives.
|
||||
|
||||
- Defined int32 in a way that ensures that the build dies if we can't
|
||||
find a variable with at least 32 bits.
|
||||
|
||||
PROTOCOL DIFFERENCES FOR VERSION 29:
|
||||
|
||||
- A 16-bit flag-word is transmitted after every file-list index. This
|
||||
indicates what is changing between the sender and the receiver. The
|
||||
generator now transmits an index and a flag-word to indicate when
|
||||
dirs and symlinks have changed (instead of producing a message),
|
||||
which makes the outputting of the information more consistent and
|
||||
less prone to screen corruption (because the local receiver/sender is
|
||||
now outputting all the file-change info messages).
|
||||
|
||||
- If a file is being hard-linked, the ITEM_XNAME_FOLLOWS bit is enabled
|
||||
in the flag-word and the name of the file that was linked immediately
|
||||
follows in vstring format (see below).
|
||||
|
||||
- If a file is being transferred with an alternate-basis file, the
|
||||
ITEM_BASIS_TYPE_FOLLOWS bit is enabled in the flag-word and a single
|
||||
byte follows, indicating what type of basis file was chosen. If that
|
||||
indicates that a fuzzy-match was selected, the ITEM_XNAME_FOLLOWS bit
|
||||
is set in the flag-word and the name of the match in vstring format
|
||||
follows the basis byte. A vstring is a variable length string that
|
||||
has its size written prior to the string, and no terminating null.
|
||||
If the string is from 1-127 bytes, the length is a single byte. If
|
||||
it is from 128-32767 bytes, the length is written as ((len >> 8) |
|
||||
0x80) followed by (len % 0x100).
|
||||
|
||||
- The sending of exclude names is done using filter-rule syntax. This
|
||||
means that all names have a prefixed rule indicator, even excludes
|
||||
(which used to be sent as a bare pattern, when possible). The -C
|
||||
option will include the per-dir .cvsignore merge file in the list of
|
||||
filter rules so it is positioned correctly (unlike in some older
|
||||
transfer scenarios).
|
||||
|
||||
- Rsync sorts the filename list in a different way: it sorts the subdir
|
||||
names after the non-subdir names for each dir's contents, and it
|
||||
always puts a dir's contents immediately after the dir's name in the
|
||||
list. (Previously an item named "foo.txt" would sort in between
|
||||
directory "foo/" and "foo/bar".)
|
||||
|
||||
- When talking to a protocol 29 rsync daemon, a list-only request
|
||||
is able to note this before the options are sent over the wire and
|
||||
the new --list-only option is included in the options.
|
||||
|
||||
- When the --stats bytes are sent over the wire (or stored in a batch),
|
||||
they now include two elapsed-time values: one for how long it took to
|
||||
build the file-list, and one for how long it took to send it over the
|
||||
wire (each expressed in thousandths of a second).
|
||||
|
||||
- When --delete-excluded is specified with some filter rules (AKA
|
||||
excludes), a client sender will now initiate a send of the rules to
|
||||
the receiver (older protocols used to omit the sending of excludes in
|
||||
this situation since there were no receiver-specific rules that
|
||||
survived --delete-excluded back then). Note that, as with all the
|
||||
filter-list sending, only items that are significant to the other
|
||||
side will actually be sent over the wire, so the filter-rule list
|
||||
that is sent in this scenario is often empty.
|
||||
|
||||
- An index equal to the file-list count is sent as a keep-alive packet
|
||||
from the generator to the sender, which then forwards it on to the
|
||||
receiver. This normally invalid index is only a valid keep-alive
|
||||
packet if the 16-bit flag-word that follows it contains a single bit
|
||||
(ITEM_IS_NEW, which is normally an illegal flag to appear alone).
|
||||
|
||||
- A protocol-29 batch file includes a bit for the setting of the --dirs
|
||||
option and for the setting of the --compress option. Also, the shell
|
||||
script created by --write-batch will use the --filter option instead
|
||||
of --exclude-from to capture any filter rules.
|
||||
|
||||
BUILD CHANGES:
|
||||
|
||||
- Handle an operating system that use mkdev() in place of makedev().
|
||||
|
||||
- Improved configure to better handle cross-compiling.
|
||||
NEWS for rsync 2.6.3 (30 Sep 2004)
|
||||
Protocol: 28 (unchanged)
|
||||
Changes since 2.6.2:
|
||||
@@ -1043,6 +1434,7 @@ Changes since 2.4.6:
|
||||
|
||||
Partial Protocol History
|
||||
RELEASE DATE VER. DATE OF COMMIT* PROTOCOL
|
||||
01 Jun 2005 2.6.5 29
|
||||
30 Mar 2005 2.6.4 17 Jan 2005 29
|
||||
30 Sep 2004 2.6.3 28
|
||||
30 Apr 2004 2.6.2 28
|
||||
|
||||
3
README
3
README
@@ -89,6 +89,9 @@ mailing list archives at
|
||||
To send a bug report, follow the instructions on the bug-tracking
|
||||
page of the web site.
|
||||
|
||||
If you don't have web access, email your bug report to
|
||||
rsync@lists.samba.org.
|
||||
|
||||
|
||||
CVS TREE
|
||||
--------
|
||||
|
||||
@@ -51,10 +51,11 @@ void base64_encode(char *buf, int len, char *out)
|
||||
}
|
||||
}
|
||||
|
||||
/* create a 16 byte challenge buffer */
|
||||
/* Generate a challenge buffer and return it base64-encoded. */
|
||||
static void gen_challenge(char *addr, char *challenge)
|
||||
{
|
||||
char input[32];
|
||||
char md4_out[MD4_SUM_LENGTH];
|
||||
struct timeval tv;
|
||||
|
||||
memset(input, 0, sizeof input);
|
||||
@@ -67,7 +68,9 @@ static void gen_challenge(char *addr, char *challenge)
|
||||
|
||||
sum_init(0);
|
||||
sum_update(input, sizeof input);
|
||||
sum_end(challenge);
|
||||
sum_end(md4_out);
|
||||
|
||||
base64_encode(md4_out, MD4_SUM_LENGTH, challenge);
|
||||
}
|
||||
|
||||
|
||||
@@ -195,17 +198,18 @@ static char *getpassf(char *filename)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* generate a 16 byte hash from a password and challenge */
|
||||
/* Generate an MD4 hash created from the combination of the password
|
||||
* and the challenge string and return it base64-encoded. */
|
||||
static void generate_hash(char *in, char *challenge, char *out)
|
||||
{
|
||||
char buf[16];
|
||||
char buf[MD4_SUM_LENGTH];
|
||||
|
||||
sum_init(0);
|
||||
sum_update(in, strlen(in));
|
||||
sum_update(challenge, strlen(challenge));
|
||||
sum_end(buf);
|
||||
|
||||
base64_encode(buf, 16, out);
|
||||
base64_encode(buf, MD4_SUM_LENGTH, out);
|
||||
}
|
||||
|
||||
/* Possibly negotiate authentication with the client. Use "leader" to
|
||||
@@ -214,17 +218,15 @@ static void generate_hash(char *in, char *challenge, char *out)
|
||||
* Return NULL if authentication failed. Return "" if anonymous access.
|
||||
* Otherwise return username.
|
||||
*/
|
||||
char *auth_server(int f_in, int f_out, int module, char *addr, char *leader)
|
||||
char *auth_server(int f_in, int f_out, int module, char *host, char *addr,
|
||||
char *leader)
|
||||
{
|
||||
char *users = lp_auth_users(module);
|
||||
char challenge[16];
|
||||
char b64_challenge[30];
|
||||
char challenge[MD4_SUM_LENGTH*2];
|
||||
char line[MAXPATHLEN];
|
||||
static char user[100];
|
||||
char secret[100];
|
||||
char pass[30];
|
||||
char pass2[30];
|
||||
char *tok;
|
||||
char secret[512];
|
||||
char pass2[MD4_SUM_LENGTH*2];
|
||||
char *tok, *pass;
|
||||
|
||||
/* if no auth list then allow anyone in! */
|
||||
if (!users || !*users)
|
||||
@@ -232,52 +234,60 @@ char *auth_server(int f_in, int f_out, int module, char *addr, char *leader)
|
||||
|
||||
gen_challenge(addr, challenge);
|
||||
|
||||
base64_encode(challenge, 16, b64_challenge);
|
||||
io_printf(f_out, "%s%s\n", leader, challenge);
|
||||
|
||||
io_printf(f_out, "%s%s\n", leader, b64_challenge);
|
||||
|
||||
if (!read_line(f_in, line, sizeof line - 1))
|
||||
if (!read_line(f_in, line, sizeof line - 1)
|
||||
|| (pass = strchr(line, ' ')) == NULL) {
|
||||
rprintf(FLOG, "auth failed on module %s from %s (%s): "
|
||||
"invalid challenge response\n",
|
||||
lp_name(module), host, addr);
|
||||
return NULL;
|
||||
}
|
||||
*pass++ = '\0';
|
||||
|
||||
memset(user, 0, sizeof user);
|
||||
memset(pass, 0, sizeof pass);
|
||||
if (!(users = strdup(users)))
|
||||
out_of_memory("auth_server");
|
||||
|
||||
if (sscanf(line,"%99s %29s", user, pass) != 2)
|
||||
return NULL;
|
||||
|
||||
users = strdup(users);
|
||||
if (!users)
|
||||
return NULL;
|
||||
|
||||
for (tok=strtok(users," ,\t"); tok; tok = strtok(NULL," ,\t")) {
|
||||
if (wildmatch(tok, user))
|
||||
for (tok = strtok(users, " ,\t"); tok; tok = strtok(NULL, " ,\t")) {
|
||||
if (wildmatch(tok, line))
|
||||
break;
|
||||
}
|
||||
free(users);
|
||||
|
||||
if (!tok)
|
||||
return NULL;
|
||||
|
||||
memset(secret, 0, sizeof secret);
|
||||
if (!get_secret(module, user, secret, sizeof secret - 1)) {
|
||||
memset(secret, 0, sizeof secret);
|
||||
if (!tok) {
|
||||
rprintf(FLOG, "auth failed on module %s from %s (%s): "
|
||||
"unauthorized user\n",
|
||||
lp_name(module), host, addr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
generate_hash(secret, b64_challenge, pass2);
|
||||
memset(secret, 0, sizeof secret);
|
||||
if (!get_secret(module, line, secret, sizeof secret - 1)) {
|
||||
memset(secret, 0, sizeof secret);
|
||||
rprintf(FLOG, "auth failed on module %s from %s (%s): "
|
||||
"missing secret for user \"%s\"\n",
|
||||
lp_name(module), host, addr, line);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
generate_hash(secret, challenge, pass2);
|
||||
memset(secret, 0, sizeof secret);
|
||||
|
||||
if (strcmp(pass, pass2) == 0)
|
||||
return user;
|
||||
if (strcmp(pass, pass2) != 0) {
|
||||
rprintf(FLOG, "auth failed on module %s from %s (%s): "
|
||||
"password mismatch\n",
|
||||
lp_name(module), host, addr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return strdup(line);
|
||||
}
|
||||
|
||||
|
||||
void auth_client(int fd, char *user, char *challenge)
|
||||
{
|
||||
char *pass;
|
||||
char pass2[30];
|
||||
char pass2[MD4_SUM_LENGTH*2];
|
||||
|
||||
if (!user || !*user)
|
||||
user = "nobody";
|
||||
@@ -302,5 +312,3 @@ void auth_client(int fd, char *user, char *challenge)
|
||||
generate_hash(pass, challenge, pass2);
|
||||
io_printf(fd, "%s %s\n", user, pass2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
9
batch.c
9
batch.c
@@ -139,7 +139,7 @@ static void write_filter_rules(int fd)
|
||||
* (hopefully) work. */
|
||||
void write_batch_shell_file(int argc, char *argv[], int file_arg_cnt)
|
||||
{
|
||||
int fd, i;
|
||||
int fd, i, len;
|
||||
char *p, filename[MAXPATHLEN];
|
||||
|
||||
stringjoin(filename, sizeof filename,
|
||||
@@ -175,11 +175,12 @@ void write_batch_shell_file(int argc, char *argv[], int file_arg_cnt)
|
||||
continue;
|
||||
}
|
||||
write(fd, " ", 1);
|
||||
if (strncmp(p, "--write-batch", 13) == 0) {
|
||||
if (strncmp(p, "--write-batch", len = 13) == 0
|
||||
|| strncmp(p, "--only-write-batch", len = 18) == 0) {
|
||||
write(fd, "--read-batch", 12);
|
||||
if (p[13] == '=') {
|
||||
if (p[len] == '=') {
|
||||
write(fd, "=", 1);
|
||||
write_arg(fd, p + 14);
|
||||
write_arg(fd, p + len + 1);
|
||||
}
|
||||
} else
|
||||
write_arg(fd, p);
|
||||
|
||||
@@ -41,7 +41,6 @@ extern int filesfrom_fd;
|
||||
extern int remote_protocol;
|
||||
extern int protocol_version;
|
||||
extern int io_timeout;
|
||||
extern int select_timeout;
|
||||
extern int orig_umask;
|
||||
extern int no_detach;
|
||||
extern int default_af_hint;
|
||||
@@ -100,7 +99,7 @@ int start_socket_client(char *host, char *path, int argc, char *argv[])
|
||||
|
||||
ret = start_inband_exchange(user, path, fd, fd, argc);
|
||||
|
||||
return ret < 0? ret : client_run(fd, fd, -1, argc, argv);
|
||||
return ret ? ret : client_run(fd, fd, -1, argc, argv);
|
||||
}
|
||||
|
||||
int start_inband_exchange(char *user, char *path, int f_in, int f_out,
|
||||
@@ -196,10 +195,10 @@ int start_inband_exchange(char *user, char *path, int f_in, int f_out,
|
||||
rprintf(FERROR, "%s\n", line);
|
||||
/* This is always fatal; the server will now
|
||||
* close the socket. */
|
||||
return RERR_STARTCLIENT;
|
||||
} else {
|
||||
rprintf(FINFO,"%s\n", line);
|
||||
return -1;
|
||||
}
|
||||
|
||||
rprintf(FINFO, "%s\n", line);
|
||||
}
|
||||
kluge_around_eof = 0;
|
||||
|
||||
@@ -268,11 +267,9 @@ static int rsync_module(int f_in, int f_out, int i)
|
||||
return -1;
|
||||
}
|
||||
|
||||
auth_user = auth_server(f_in, f_out, i, addr, "@RSYNCD: AUTHREQD ");
|
||||
auth_user = auth_server(f_in, f_out, i, host, addr, "@RSYNCD: AUTHREQD ");
|
||||
|
||||
if (!auth_user) {
|
||||
rprintf(FLOG, "auth failed on module %s from %s (%s)\n",
|
||||
name, host, addr);
|
||||
io_printf(f_out, "@ERROR: auth failed on module %s\n", name);
|
||||
return -1;
|
||||
}
|
||||
@@ -283,10 +280,10 @@ static int rsync_module(int f_in, int f_out, int i)
|
||||
read_only = 1;
|
||||
|
||||
if (lp_transfer_logging(i)) {
|
||||
if (strstr(lp_log_format(i), "%i") != NULL)
|
||||
if (log_format_has(lp_log_format(i), 'i'))
|
||||
daemon_log_format_has_i = 1;
|
||||
if (daemon_log_format_has_i
|
||||
|| strstr(lp_log_format(i), "%o") != NULL)
|
||||
|| log_format_has(lp_log_format(i), 'o'))
|
||||
daemon_log_format_has_o_or_i = 1;
|
||||
}
|
||||
|
||||
@@ -321,13 +318,11 @@ static int rsync_module(int f_in, int f_out, int i)
|
||||
/* TODO: Perhaps take a list of gids, and make them into the
|
||||
* supplementary groups. */
|
||||
|
||||
if (use_chroot) {
|
||||
if (use_chroot || (module_dirlen = strlen(lp_path(i))) == 1) {
|
||||
module_dirlen = 0;
|
||||
set_filter_dir("/", 1);
|
||||
} else {
|
||||
module_dirlen = strlen(lp_path(i));
|
||||
} else
|
||||
set_filter_dir(lp_path(i), module_dirlen);
|
||||
}
|
||||
|
||||
p = lp_filter(i);
|
||||
parse_rule(&server_filter_list, p, MATCHFLG_WORD_SPLIT,
|
||||
@@ -522,11 +517,8 @@ static int rsync_module(int f_in, int f_out, int i)
|
||||
exit_cleanup(RERR_UNSUPPORTED);
|
||||
}
|
||||
|
||||
if (lp_timeout(i)) {
|
||||
io_timeout = lp_timeout(i);
|
||||
if (io_timeout < select_timeout)
|
||||
select_timeout = io_timeout;
|
||||
}
|
||||
if (lp_timeout(i) && lp_timeout(i) > io_timeout)
|
||||
set_io_timeout(lp_timeout(i));
|
||||
|
||||
start_server(f_in, f_out, argc, argp);
|
||||
|
||||
|
||||
48
configure.in
48
configure.in
@@ -5,7 +5,7 @@ AC_CONFIG_SRCDIR([byteorder.h])
|
||||
AC_CONFIG_HEADER(config.h)
|
||||
AC_PREREQ(2.59)
|
||||
|
||||
RSYNC_VERSION=2.6.4pre4
|
||||
RSYNC_VERSION=2.6.5
|
||||
AC_SUBST(RSYNC_VERSION)
|
||||
AC_MSG_NOTICE([Configuring rsync $RSYNC_VERSION])
|
||||
|
||||
@@ -122,7 +122,9 @@ AC_ARG_WITH(rsh,
|
||||
AC_HELP_STRING([--with-rsh=CMD], [set remote shell command to CMD (default: ssh)]))
|
||||
|
||||
AC_CHECK_PROG(HAVE_REMSH, remsh, 1, 0)
|
||||
AC_DEFINE_UNQUOTED(HAVE_REMSH, $HAVE_REMSH, [remote shell is remsh not rsh])
|
||||
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
|
||||
@@ -181,6 +183,17 @@ ipv6trylibc=yes
|
||||
AC_ARG_ENABLE(ipv6,
|
||||
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])
|
||||
@@ -287,7 +300,7 @@ AC_HEADER_SYS_WAIT
|
||||
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 \
|
||||
sys/un.h glob.h mcheck.h arpa/inet.h arpa/nameser.h locale.h \
|
||||
netdb.h malloc.h float.h)
|
||||
AC_HEADER_MAJOR
|
||||
|
||||
@@ -478,7 +491,7 @@ 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 \
|
||||
setmode open64 mkstemp64 va_copy __va_copy)
|
||||
setlocale setmode open64 lseek64 mkstemp64 va_copy __va_copy)
|
||||
|
||||
AC_CHECK_FUNCS(getpgrp tcgetpgrp)
|
||||
if test $ac_cv_func_getpgrp = yes; then
|
||||
@@ -621,7 +634,17 @@ rsync_cv_HAVE_SECURE_MKSTEMP=yes,
|
||||
rsync_cv_HAVE_SECURE_MKSTEMP=no,
|
||||
rsync_cv_HAVE_SECURE_MKSTEMP=cross)])
|
||||
if test x"$rsync_cv_HAVE_SECURE_MKSTEMP" = x"yes"; then
|
||||
AC_DEFINE(HAVE_SECURE_MKSTEMP, 1, [Define to 1 if mkstemp() is available and works right])
|
||||
case $target_os in
|
||||
hpux*)
|
||||
dnl HP-UX has a broken mkstemp() implementation they refuse to fix,
|
||||
dnl so we noisily skip using it. See HP change request JAGaf34426
|
||||
dnl for details. (sbonds)
|
||||
AC_MSG_WARN(Skipping broken HP-UX mkstemp() -- using mktemp() instead)
|
||||
;;
|
||||
*)
|
||||
AC_DEFINE(HAVE_SECURE_MKSTEMP, 1, [Define to 1 if mkstemp() is available and works right])
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
|
||||
@@ -716,21 +739,6 @@ AC_SUBST(BUILD_POPT)
|
||||
AC_CONFIG_FILES([Makefile lib/dummy zlib/dummy popt/dummy shconfig])
|
||||
AC_OUTPUT
|
||||
|
||||
if test x"$with_rsh" = x; then
|
||||
if test x"$HAVE_REMSH" = x1; then
|
||||
rmsh1='remsh:'
|
||||
rmsh2='=remsh'
|
||||
else
|
||||
rmsh1='rsh: '
|
||||
rmsh2='=rsh '
|
||||
fi
|
||||
AC_MSG_RESULT()
|
||||
AC_MSG_RESULT([ **********************************************************************])
|
||||
AC_MSG_RESULT([ * As of v2.6.0, the default remote shell is ssh instead of rsh!! *])
|
||||
AC_MSG_RESULT([ * To use previous default of $rmsh1 ./configure --with-rsh$rmsh2 *])
|
||||
AC_MSG_RESULT([ **********************************************************************])
|
||||
fi
|
||||
|
||||
AC_MSG_RESULT()
|
||||
AC_MSG_RESULT([ rsync ${RSYNC_VERSION} configuration successful])
|
||||
AC_MSG_RESULT()
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
#define RERR_FILESELECT 3 /* errors selecting input/output files, dirs */
|
||||
#define RERR_UNSUPPORTED 4 /* requested action not supported */
|
||||
#define RERR_STARTCLIENT 5 /* error starting client-server protocol */
|
||||
#define RERR_LOG_FAILURE 6 /* daemon unable to append to log-file */
|
||||
|
||||
#define RERR_SOCKETIO 10 /* error in socket IO */
|
||||
#define RERR_FILEIO 11 /* error in file IO */
|
||||
|
||||
@@ -674,8 +674,7 @@ static const char *parse_rule_tok(const char *p, uint32 mflags, int xflags,
|
||||
} else if (*s == '+' && s[1] == ' ') {
|
||||
new_mflags |= MATCHFLG_INCLUDE;
|
||||
s += 2;
|
||||
}
|
||||
if (*s == '!')
|
||||
} else if (*s == '!')
|
||||
new_mflags |= MATCHFLG_CLEAR_LIST; /* Tentative! */
|
||||
} else {
|
||||
char ch = 0, *mods = "";
|
||||
@@ -716,7 +715,6 @@ static const char *parse_rule_tok(const char *p, uint32 mflags, int xflags,
|
||||
if ((s = RULE_STRCMP(s, "show")) != NULL)
|
||||
ch = 'S';
|
||||
break;
|
||||
|
||||
default:
|
||||
ch = *s;
|
||||
if (s[1] == ',')
|
||||
@@ -1107,9 +1105,9 @@ static void send_rules(int f_out, struct filter_list_struct *flp)
|
||||
continue;
|
||||
if (ent->match_flags & MATCHFLG_CVS_IGNORE
|
||||
&& !(ent->match_flags & MATCHFLG_MERGE_FILE)) {
|
||||
int f = am_sender || protocol_version < 29 ? f_out : -1;
|
||||
int f = am_sender || protocol_version < 29 ? f_out : -2;
|
||||
send_rules(f, &cvs_filter_list);
|
||||
if (f >= 0)
|
||||
if (f == f_out)
|
||||
continue;
|
||||
}
|
||||
p = get_rule_prefix(ent->match_flags, ent->pattern, 1, &plen);
|
||||
|
||||
52
flist.c
52
flist.c
@@ -69,6 +69,7 @@ int io_error;
|
||||
dev_t filesystem_dev; /* used to implement -x */
|
||||
|
||||
static char empty_sum[MD4_SUM_LENGTH];
|
||||
static int flist_count_offset;
|
||||
static unsigned int file_struct_len;
|
||||
static struct file_list *sorting_flist;
|
||||
|
||||
@@ -98,16 +99,16 @@ static void start_filelist_progress(char *kind)
|
||||
}
|
||||
|
||||
|
||||
static void emit_filelist_progress(const struct file_list *flist)
|
||||
static void emit_filelist_progress(int count)
|
||||
{
|
||||
rprintf(FINFO, " %d files...\r", flist->count);
|
||||
rprintf(FINFO, " %d files...\r", count);
|
||||
}
|
||||
|
||||
|
||||
static void maybe_emit_filelist_progress(const struct file_list *flist)
|
||||
static void maybe_emit_filelist_progress(int count)
|
||||
{
|
||||
if (do_progress && show_filelist_p() && (flist->count % 100) == 0)
|
||||
emit_filelist_progress(flist);
|
||||
if (do_progress && show_filelist_p() && (count % 100) == 0)
|
||||
emit_filelist_progress(count);
|
||||
}
|
||||
|
||||
|
||||
@@ -654,6 +655,9 @@ static struct file_struct *receive_file_entry(struct file_list *flist,
|
||||
if (flags & XMIT_TOP_DIR) {
|
||||
in_del_hier = 1;
|
||||
del_hier_name_len = file->dir.depth == 0 ? 0 : l1 + l2;
|
||||
if (relative_paths && del_hier_name_len > 2
|
||||
&& basename_len == 1+1 && *basename == '.')
|
||||
del_hier_name_len -= 2;
|
||||
file->flags |= FLAG_TOP_DIR | FLAG_DEL_HERE;
|
||||
} else if (in_del_hier) {
|
||||
if (!relative_paths || !del_hier_name_len
|
||||
@@ -971,7 +975,7 @@ static struct file_struct *send_file_name(int f, struct file_list *flist,
|
||||
if (!file)
|
||||
return NULL;
|
||||
|
||||
maybe_emit_filelist_progress(flist);
|
||||
maybe_emit_filelist_progress(flist->count + flist_count_offset);
|
||||
|
||||
flist_expand(flist);
|
||||
|
||||
@@ -1007,7 +1011,7 @@ static void send_if_directory(int f, struct file_list *flist,
|
||||
|
||||
|
||||
/* This function is normally called by the sender, but the receiving side also
|
||||
* calls it from delete_in_dir() with f set to -1 so that we just construct the
|
||||
* calls it from get_dirlist() with f set to -1 so that we just construct the
|
||||
* file list in memory without sending it over the wire. Also, get_dirlist()
|
||||
* might call this with f set to -2, which also indicates that local filter
|
||||
* rules should be ignored. */
|
||||
@@ -1116,11 +1120,21 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
|
||||
if (l == 2 && fname[0] == '.') {
|
||||
/* Turn "./" into just "." rather than "./." */
|
||||
fname[1] = '\0';
|
||||
} else if (l < MAXPATHLEN) {
|
||||
} else {
|
||||
if (l + 1 >= MAXPATHLEN)
|
||||
overflow("send_file_list");
|
||||
fname[l++] = '.';
|
||||
fname[l] = '\0';
|
||||
}
|
||||
is_dot_dir = 1;
|
||||
} else if (l > 1 && fname[l-1] == '.' && fname[l-2] == '.'
|
||||
&& (l == 2 || fname[l-3] == '/')) {
|
||||
if (l + 2 >= MAXPATHLEN)
|
||||
overflow("send_file_list");
|
||||
fname[l++] = '/';
|
||||
fname[l++] = '.';
|
||||
fname[l] = '\0';
|
||||
is_dot_dir = 1;
|
||||
} else {
|
||||
is_dot_dir = fname[l-1] == '.'
|
||||
&& (l == 1 || fname[l-2] == '/');
|
||||
@@ -1309,7 +1323,7 @@ struct file_list *recv_file_list(int f)
|
||||
|
||||
flist->files[flist->count++] = file;
|
||||
|
||||
maybe_emit_filelist_progress(flist);
|
||||
maybe_emit_filelist_progress(flist->count);
|
||||
|
||||
if (verbose > 2) {
|
||||
rprintf(FINFO, "recv_file_name(%s)\n",
|
||||
@@ -1510,8 +1524,8 @@ static void clean_flist(struct file_list *flist, int strip_root, int no_dups)
|
||||
}
|
||||
/* Make sure that if we unduplicate '.', that we don't
|
||||
* lose track of a user-specified top directory. */
|
||||
if (flist->files[drop]->flags & FLAG_TOP_DIR)
|
||||
flist->files[keep]->flags |= FLAG_TOP_DIR;
|
||||
flist->files[keep]->flags |= flist->files[drop]->flags
|
||||
& (FLAG_TOP_DIR|FLAG_DEL_HERE);
|
||||
|
||||
clear_file(drop, flist);
|
||||
|
||||
@@ -1666,8 +1680,13 @@ int f_name_cmp(struct file_struct *f1, struct file_struct *f2)
|
||||
break;
|
||||
case s_SLASH:
|
||||
type1 = S_ISDIR(f1->mode) ? t_path : t_ITEM;
|
||||
state1 = s_BASE;
|
||||
c1 = (uchar*)f1->basename;
|
||||
if (type1 == t_PATH && *c1 == '.' && !c1[1]) {
|
||||
type1 = t_ITEM;
|
||||
state1 = s_TRAILING;
|
||||
c1 = (uchar*)"";
|
||||
} else
|
||||
state1 = s_BASE;
|
||||
break;
|
||||
case s_BASE:
|
||||
state1 = s_TRAILING;
|
||||
@@ -1691,8 +1710,13 @@ int f_name_cmp(struct file_struct *f1, struct file_struct *f2)
|
||||
break;
|
||||
case s_SLASH:
|
||||
type2 = S_ISDIR(f2->mode) ? t_path : t_ITEM;
|
||||
state2 = s_BASE;
|
||||
c2 = (uchar*)f2->basename;
|
||||
if (type2 == t_PATH && *c2 == '.' && !c2[1]) {
|
||||
type2 = t_ITEM;
|
||||
state2 = s_TRAILING;
|
||||
c2 = (uchar*)"";
|
||||
} else
|
||||
state2 = s_BASE;
|
||||
break;
|
||||
case s_BASE:
|
||||
state2 = s_TRAILING;
|
||||
@@ -1772,6 +1796,8 @@ struct file_list *get_dirlist(char *dirname, int dlen,
|
||||
recurse = 0;
|
||||
send_directory(ignore_filter_rules ? -2 : -1, dirlist, dirname, dlen);
|
||||
recurse = save_recurse;
|
||||
if (do_progress)
|
||||
flist_count_offset += dirlist->count;
|
||||
|
||||
clean_flist(dirlist, 0, 0);
|
||||
|
||||
|
||||
150
generator.c
150
generator.c
@@ -25,12 +25,14 @@
|
||||
|
||||
extern int verbose;
|
||||
extern int dry_run;
|
||||
extern int do_xfers;
|
||||
extern int log_format_has_i;
|
||||
extern int log_format_has_o_or_i;
|
||||
extern int daemon_log_format_has_i;
|
||||
extern int am_root;
|
||||
extern int am_server;
|
||||
extern int am_daemon;
|
||||
extern int do_progress;
|
||||
extern int recurse;
|
||||
extern int relative_paths;
|
||||
extern int keep_dirlinks;
|
||||
@@ -57,8 +59,8 @@ extern int csum_length;
|
||||
extern int ignore_times;
|
||||
extern int size_only;
|
||||
extern OFF_T max_size;
|
||||
extern int io_timeout;
|
||||
extern int io_error;
|
||||
extern int allowed_lull;
|
||||
extern int sock_f_out;
|
||||
extern int ignore_timeout;
|
||||
extern int protocol_version;
|
||||
@@ -70,7 +72,6 @@ extern int compare_dest;
|
||||
extern int copy_dest;
|
||||
extern int link_dest;
|
||||
extern int whole_file;
|
||||
extern int local_server;
|
||||
extern int list_only;
|
||||
extern int read_batch;
|
||||
extern int only_existing;
|
||||
@@ -88,8 +89,6 @@ extern int backup_suffix_len;
|
||||
extern struct file_list *the_file_list;
|
||||
extern struct filter_list_struct server_filter_list;
|
||||
|
||||
int allowed_lull = 0;
|
||||
|
||||
static int deletion_count = 0; /* used to implement --max-delete */
|
||||
|
||||
|
||||
@@ -151,7 +150,7 @@ static int delete_item(char *fname, int mode, int flags)
|
||||
deletion_count--;
|
||||
return 0;
|
||||
}
|
||||
if (!zap_dir || (errno != ENOTEMPTY && errno != EEXIST)) {
|
||||
if (!zap_dir) {
|
||||
rsyserr(FERROR, errno, "delete_file: rmdir %s failed",
|
||||
full_fname(fname));
|
||||
return -1;
|
||||
@@ -170,10 +169,7 @@ static int delete_item(char *fname, int mode, int flags)
|
||||
continue;
|
||||
|
||||
f_name_to(fp, buf);
|
||||
if (delete_item(buf, fp->mode, flags & ~DEL_TERSE) != 0) {
|
||||
flist_free(dirlist);
|
||||
return -1;
|
||||
}
|
||||
delete_item(buf, fp->mode, flags & ~DEL_TERSE);
|
||||
}
|
||||
flist_free(dirlist);
|
||||
|
||||
@@ -185,7 +181,7 @@ static int delete_item(char *fname, int mode, int flags)
|
||||
if (do_rmdir(fname) == 0) {
|
||||
if (!(flags & DEL_TERSE))
|
||||
log_delete(fname, mode);
|
||||
} else if (errno != ENOTEMPTY && errno != ENOENT) {
|
||||
} else if (errno != ENOTEMPTY && errno != EEXIST && errno != ENOENT) {
|
||||
rsyserr(FERROR, errno, "delete_file: rmdir %s failed",
|
||||
full_fname(fname));
|
||||
return -1;
|
||||
@@ -248,21 +244,25 @@ static void delete_in_dir(struct file_list *flist, char *fbuf,
|
||||
if (link_stat(fbuf, &st, keep_dirlinks) < 0)
|
||||
return;
|
||||
|
||||
if (one_file_system && file->flags & FLAG_TOP_DIR)
|
||||
filesystem_dev = st.st_dev;
|
||||
if (one_file_system) {
|
||||
if (file->flags & FLAG_TOP_DIR)
|
||||
filesystem_dev = st.st_dev;
|
||||
else if (filesystem_dev != st.st_dev)
|
||||
return;
|
||||
}
|
||||
|
||||
dirlist = get_dirlist(fbuf, dlen, 0);
|
||||
|
||||
/* If an item in dirlist is not found in flist, delete it
|
||||
* from the filesystem. */
|
||||
for (i = dirlist->count; i--; ) {
|
||||
if (!dirlist->files[i]->basename)
|
||||
struct file_struct *fp = dirlist->files[i];
|
||||
if (!fp->basename || fp->flags & FLAG_MOUNT_POINT)
|
||||
continue;
|
||||
if (flist_find(flist, dirlist->files[i]) < 0) {
|
||||
int mode = dirlist->files[i]->mode;
|
||||
f_name_to(dirlist->files[i], delbuf);
|
||||
if (delete_item(delbuf, mode, DEL_FORCE_RECURSE) < 0)
|
||||
break;
|
||||
if (flist_find(flist, fp) < 0) {
|
||||
int mode = fp->mode;
|
||||
f_name_to(fp, delbuf);
|
||||
delete_item(delbuf, mode, DEL_FORCE_RECURSE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -276,7 +276,8 @@ static void do_delete_pass(struct file_list *flist)
|
||||
char fbuf[MAXPATHLEN];
|
||||
int j;
|
||||
|
||||
if (dry_run > 1) /* destination doesn't exist yet */
|
||||
if (dry_run > 1 /* destination doesn't exist yet */
|
||||
|| list_only)
|
||||
return;
|
||||
|
||||
for (j = 0; j < flist->count; j++) {
|
||||
@@ -291,6 +292,8 @@ static void do_delete_pass(struct file_list *flist)
|
||||
|
||||
delete_in_dir(flist, fbuf, file);
|
||||
}
|
||||
if (do_progress && !am_server)
|
||||
rprintf(FINFO, " \r");
|
||||
}
|
||||
|
||||
static int unchanged_attrs(struct file_struct *file, STRUCT_STAT *st)
|
||||
@@ -665,7 +668,8 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
if (only_existing && statret == -1 && stat_errno == ENOENT) {
|
||||
/* we only want to update existing files */
|
||||
if (verbose > 1) {
|
||||
rprintf(FINFO, "not creating new file \"%s\"\n",
|
||||
rprintf(FINFO, "not creating new %s \"%s\"\n",
|
||||
S_ISDIR(file->mode) ? "directory" : "file",
|
||||
safe_fname(fname));
|
||||
}
|
||||
return;
|
||||
@@ -717,18 +721,12 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
return;
|
||||
}
|
||||
|
||||
if (max_size && file->length > max_size) {
|
||||
if (verbose > 1) {
|
||||
rprintf(FINFO, "%s is over max-size\n",
|
||||
safe_fname(fname));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (preserve_links && S_ISLNK(file->mode)) {
|
||||
#ifdef SUPPORT_LINKS
|
||||
if (safe_symlinks && unsafe_symlink(file->u.link, fname)) {
|
||||
if (verbose) {
|
||||
if (the_file_list->count == 1)
|
||||
fname = f_name(file);
|
||||
rprintf(FINFO,
|
||||
"ignoring unsafe symlink %s -> \"%s\"\n",
|
||||
full_fname(fname),
|
||||
@@ -821,15 +819,29 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
return;
|
||||
}
|
||||
|
||||
if (preserve_hard_links && hard_link_check(file, ndx, HL_CHECK_MASTER))
|
||||
if (preserve_hard_links
|
||||
&& hard_link_check(file, ndx, fname, statret, &st,
|
||||
itemizing, code, HL_CHECK_MASTER))
|
||||
return;
|
||||
|
||||
if (!S_ISREG(file->mode)) {
|
||||
if (the_file_list->count == 1)
|
||||
fname = f_name(file);
|
||||
rprintf(FINFO, "skipping non-regular file \"%s\"\n",
|
||||
safe_fname(fname));
|
||||
return;
|
||||
}
|
||||
|
||||
if (max_size && file->length > max_size) {
|
||||
if (verbose > 1) {
|
||||
if (the_file_list->count == 1)
|
||||
fname = f_name(file);
|
||||
rprintf(FINFO, "%s is over max-size\n",
|
||||
safe_fname(fname));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (opt_ignore_existing && statret == 0) {
|
||||
if (verbose > 1)
|
||||
rprintf(FINFO, "%s exists\n", safe_fname(fname));
|
||||
@@ -902,12 +914,14 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
if (hard_link_one(file, ndx, fname, -1, &st,
|
||||
fnamecmpbuf, 1,
|
||||
itemizing && verbose > 1,
|
||||
code) == 0)
|
||||
code) == 0) {
|
||||
if (preserve_hard_links
|
||||
&& file->link_u.links) {
|
||||
hard_link_cluster(file, ndx,
|
||||
itemizing,
|
||||
code);
|
||||
}
|
||||
return;
|
||||
if (verbose) {
|
||||
rsyserr(FINFO, errno, "link %s => %s",
|
||||
full_fname(fnamecmpbuf),
|
||||
safe_fname(fname));
|
||||
}
|
||||
match_level = 2;
|
||||
}
|
||||
@@ -923,8 +937,25 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
}
|
||||
match_level = 0;
|
||||
statret = -1;
|
||||
} else
|
||||
set_perms(fname, file, NULL, 0);
|
||||
} else {
|
||||
if (itemizing) {
|
||||
itemize(file, ndx, 0, &st,
|
||||
ITEM_LOCAL_CHANGE, 0,
|
||||
NULL);
|
||||
} else if (verbose && code) {
|
||||
rprintf(code, "%s\n",
|
||||
safe_fname(fname));
|
||||
}
|
||||
set_perms(fname, file, NULL,
|
||||
maybe_PERMS_REPORT);
|
||||
if (preserve_hard_links
|
||||
&& file->link_u.links) {
|
||||
hard_link_cluster(file, ndx,
|
||||
itemizing,
|
||||
code);
|
||||
}
|
||||
return;
|
||||
}
|
||||
} else if (compare_dest || match_level == 1) {
|
||||
fnamecmp = fnamecmpbuf;
|
||||
fnamecmp_type = i;
|
||||
@@ -960,7 +991,9 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
|
||||
}
|
||||
|
||||
if (statret != 0) {
|
||||
if (preserve_hard_links && hard_link_check(file, ndx, HL_SKIP))
|
||||
if (preserve_hard_links
|
||||
&& hard_link_check(file, ndx, fname, statret, &st,
|
||||
itemizing, code, HL_SKIP))
|
||||
return;
|
||||
if (stat_errno == ENOENT)
|
||||
goto notify_others;
|
||||
@@ -1001,7 +1034,7 @@ prepare_to_open:
|
||||
statret = 0;
|
||||
}
|
||||
|
||||
if (dry_run || read_batch || whole_file)
|
||||
if (!do_xfers || read_batch || whole_file)
|
||||
goto notify_others;
|
||||
|
||||
if (fuzzy_basis) {
|
||||
@@ -1018,7 +1051,9 @@ prepare_to_open:
|
||||
full_fname(fnamecmp));
|
||||
pretend_missing:
|
||||
/* pretend the file didn't exist */
|
||||
if (preserve_hard_links && hard_link_check(file, ndx, HL_SKIP))
|
||||
if (preserve_hard_links
|
||||
&& hard_link_check(file, ndx, fname, statret, &st,
|
||||
itemizing, code, HL_SKIP))
|
||||
return;
|
||||
statret = real_ret = -1;
|
||||
goto notify_others;
|
||||
@@ -1073,7 +1108,7 @@ notify_others:
|
||||
fuzzy_file ? fuzzy_file->basename : NULL);
|
||||
}
|
||||
|
||||
if (dry_run) {
|
||||
if (!do_xfers) {
|
||||
if (preserve_hard_links && file->link_u.links)
|
||||
hard_link_cluster(file, ndx, itemizing, code);
|
||||
return;
|
||||
@@ -1104,26 +1139,26 @@ notify_others:
|
||||
|
||||
void generate_files(int f_out, struct file_list *flist, char *local_name)
|
||||
{
|
||||
int i, lull_mod;
|
||||
int i;
|
||||
char fbuf[MAXPATHLEN];
|
||||
int itemizing, maybe_PERMS_REPORT;
|
||||
enum logcode code;
|
||||
int lull_mod = allowed_lull * 5;
|
||||
int need_retouch_dir_times = preserve_times && !omit_dir_times;
|
||||
int need_retouch_dir_perms = 0;
|
||||
int save_only_existing = only_existing;
|
||||
int save_opt_ignore_existing = opt_ignore_existing;
|
||||
|
||||
allowed_lull = read_batch ? 0 : (io_timeout + 1) / 2;
|
||||
lull_mod = allowed_lull * 5;
|
||||
int save_do_progress = do_progress;
|
||||
int save_make_backups = make_backups;
|
||||
|
||||
if (protocol_version >= 29) {
|
||||
itemizing = 1;
|
||||
maybe_PERMS_REPORT = log_format_has_i ? 0 : PERMS_REPORT;
|
||||
code = daemon_log_format_has_i ? 0 : FLOG;
|
||||
} else if (am_daemon) {
|
||||
itemizing = daemon_log_format_has_i && !dry_run;
|
||||
itemizing = daemon_log_format_has_i && do_xfers;
|
||||
maybe_PERMS_REPORT = PERMS_REPORT;
|
||||
code = itemizing || dry_run ? FCLIENT : FINFO;
|
||||
code = itemizing || !do_xfers ? FCLIENT : FINFO;
|
||||
} else if (!am_server) {
|
||||
itemizing = log_format_has_i;
|
||||
maybe_PERMS_REPORT = log_format_has_i ? 0 : PERMS_REPORT;
|
||||
@@ -1141,6 +1176,7 @@ void generate_files(int f_out, struct file_list *flist, char *local_name)
|
||||
|
||||
if (delete_before && !local_name && flist->count > 0)
|
||||
do_delete_pass(flist);
|
||||
do_progress = 0;
|
||||
|
||||
if (whole_file < 0)
|
||||
whole_file = 0;
|
||||
@@ -1151,8 +1187,11 @@ void generate_files(int f_out, struct file_list *flist, char *local_name)
|
||||
: "enabled");
|
||||
}
|
||||
|
||||
if (protocol_version < 29)
|
||||
ignore_timeout = 1;
|
||||
/* Since we often fill up the outgoing socket and then just sit around
|
||||
* waiting for the other 2 processes to do their thing, we don't want
|
||||
* to exit on a timeout. If the data stops flowing, the receiver will
|
||||
* notice that and let us know via the redo pipe (or its closing). */
|
||||
ignore_timeout = 1;
|
||||
|
||||
for (i = 0; i < flist->count; i++) {
|
||||
struct file_struct *file = flist->files[i];
|
||||
@@ -1167,7 +1206,8 @@ void generate_files(int f_out, struct file_list *flist, char *local_name)
|
||||
/* We need to ensure that any dirs we create have writeable
|
||||
* permissions during the time we are putting files within
|
||||
* them. This is then fixed after the transfer is done. */
|
||||
if (!am_root && S_ISDIR(file->mode) && !(file->mode & S_IWUSR)) {
|
||||
if (!am_root && S_ISDIR(file->mode) && !(file->mode & S_IWUSR)
|
||||
&& !list_only) {
|
||||
int mode = file->mode | S_IWUSR; /* user write */
|
||||
char *fname = local_name ? local_name : fbuf;
|
||||
if (do_chmod(fname, mode & CHMOD_BITS) < 0) {
|
||||
@@ -1183,6 +1223,8 @@ void generate_files(int f_out, struct file_list *flist, char *local_name)
|
||||
|
||||
if (allowed_lull && !(i % lull_mod))
|
||||
maybe_send_keepalive();
|
||||
else if (!(i % 200))
|
||||
maybe_flush_socket();
|
||||
}
|
||||
recv_generator(NULL, NULL, 0, 0, 0, code, -1);
|
||||
if (delete_during)
|
||||
@@ -1195,10 +1237,6 @@ void generate_files(int f_out, struct file_list *flist, char *local_name)
|
||||
ignore_times = 1;
|
||||
make_backups = 0; /* avoid a duplicate backup for inplace processing */
|
||||
|
||||
/* We expect to just sit around now, so don't exit on a timeout.
|
||||
* If we really get a timeout then the other process should exit. */
|
||||
ignore_timeout = 1;
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"generate_files phase=%d\n",phase);
|
||||
|
||||
@@ -1216,6 +1254,7 @@ void generate_files(int f_out, struct file_list *flist, char *local_name)
|
||||
phase++;
|
||||
only_existing = save_only_existing;
|
||||
opt_ignore_existing = save_opt_ignore_existing;
|
||||
make_backups = save_make_backups;
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"generate_files phase=%d\n",phase);
|
||||
@@ -1238,6 +1277,7 @@ void generate_files(int f_out, struct file_list *flist, char *local_name)
|
||||
get_redo_num(itemizing, code);
|
||||
}
|
||||
|
||||
do_progress = save_do_progress;
|
||||
if (delete_after && !local_name && flist->count > 0)
|
||||
do_delete_pass(flist);
|
||||
|
||||
@@ -1255,8 +1295,10 @@ void generate_files(int f_out, struct file_list *flist, char *local_name)
|
||||
continue;
|
||||
recv_generator(f_name(file), file, i, itemizing,
|
||||
maybe_PERMS_REPORT, code, -1);
|
||||
if (allowed_lull && !(j++ % lull_mod))
|
||||
if (allowed_lull && !(++j % lull_mod))
|
||||
maybe_send_keepalive();
|
||||
else if (!(j % 200))
|
||||
maybe_flush_socket();
|
||||
}
|
||||
}
|
||||
recv_generator(NULL, NULL, 0, 0, 0, code, -1);
|
||||
|
||||
142
hlink.c
142
hlink.c
@@ -27,6 +27,9 @@ extern struct file_list *the_file_list;
|
||||
|
||||
#ifdef SUPPORT_HARD_LINKS
|
||||
|
||||
#define SKIPPED_LINK (-1)
|
||||
#define FINISHED_LINK (-2)
|
||||
|
||||
#define FPTR(i) (the_file_list->files[i])
|
||||
#define LINKED(p1,p2) (FPTR(p1)->F_DEV == FPTR(p2)->F_DEV \
|
||||
&& FPTR(p1)->F_INODE == FPTR(p2)->F_INODE)
|
||||
@@ -52,7 +55,7 @@ static int hlink_count;
|
||||
* linked, and replace the dev+inode data with the hlindex+next linked list. */
|
||||
static void link_idev_data(void)
|
||||
{
|
||||
int head, from, to, start;
|
||||
int cur, from, to, start;
|
||||
|
||||
alloc_pool_t hlink_pool;
|
||||
alloc_pool_t idev_pool = the_file_list->hlink_pool;
|
||||
@@ -62,31 +65,31 @@ static void link_idev_data(void)
|
||||
|
||||
for (from = to = 0; from < hlink_count; from++) {
|
||||
start = from;
|
||||
head = hlink_list[start];
|
||||
while (from < hlink_count-1
|
||||
&& LINKED(hlink_list[from], hlink_list[from+1])) {
|
||||
pool_free(idev_pool, 0, FPTR(hlink_list[from])->link_u.idev);
|
||||
FPTR(hlink_list[from])->link_u.links = pool_talloc(hlink_pool,
|
||||
while (1) {
|
||||
cur = hlink_list[from];
|
||||
if (from == hlink_count-1
|
||||
|| !LINKED(cur, hlink_list[from+1]))
|
||||
break;
|
||||
pool_free(idev_pool, 0, FPTR(cur)->link_u.idev);
|
||||
FPTR(cur)->link_u.links = pool_talloc(hlink_pool,
|
||||
struct hlink, 1, "hlink_list");
|
||||
|
||||
FPTR(hlink_list[from])->F_HLINDEX = to;
|
||||
FPTR(hlink_list[from])->F_NEXT = hlink_list[from+1];
|
||||
from++;
|
||||
FPTR(cur)->F_HLINDEX = to;
|
||||
FPTR(cur)->F_NEXT = hlink_list[++from];
|
||||
}
|
||||
pool_free(idev_pool, 0, FPTR(cur)->link_u.idev);
|
||||
if (from > start) {
|
||||
pool_free(idev_pool, 0, FPTR(hlink_list[from])->link_u.idev);
|
||||
FPTR(hlink_list[from])->link_u.links = pool_talloc(hlink_pool,
|
||||
int head = hlink_list[start];
|
||||
FPTR(cur)->link_u.links = pool_talloc(hlink_pool,
|
||||
struct hlink, 1, "hlink_list");
|
||||
|
||||
FPTR(head)->flags |= FLAG_HLINK_TOL;
|
||||
FPTR(hlink_list[from])->F_HLINDEX = to;
|
||||
FPTR(hlink_list[from])->F_NEXT = head;
|
||||
FPTR(hlink_list[from])->flags |= FLAG_HLINK_EOL;
|
||||
FPTR(cur)->F_HLINDEX = to;
|
||||
FPTR(cur)->F_NEXT = head;
|
||||
FPTR(cur)->flags |= FLAG_HLINK_EOL;
|
||||
hlink_list[to++] = head;
|
||||
} else {
|
||||
pool_free(idev_pool, 0, FPTR(head)->link_u.idev);
|
||||
FPTR(head)->link_u.idev = NULL;
|
||||
}
|
||||
} else
|
||||
FPTR(cur)->link_u.links = NULL;
|
||||
}
|
||||
|
||||
if (!to) {
|
||||
@@ -110,9 +113,6 @@ void init_hard_links(void)
|
||||
#ifdef SUPPORT_HARD_LINKS
|
||||
int i;
|
||||
|
||||
if (the_file_list->count < 2)
|
||||
return;
|
||||
|
||||
if (hlink_list)
|
||||
free(hlink_list);
|
||||
|
||||
@@ -136,18 +136,67 @@ void init_hard_links(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
int hard_link_check(struct file_struct *file, int ndx, int skip)
|
||||
#ifdef SUPPORT_HARD_LINKS
|
||||
static int maybe_hard_link(struct file_struct *file, int ndx,
|
||||
char *fname, int statret, STRUCT_STAT *st,
|
||||
char *toname, STRUCT_STAT *to_st,
|
||||
int itemizing, enum logcode code)
|
||||
{
|
||||
if (statret == 0) {
|
||||
if (st->st_dev == to_st->st_dev
|
||||
&& st->st_ino == to_st->st_ino) {
|
||||
if (itemizing) {
|
||||
itemize(file, ndx, statret, st,
|
||||
ITEM_LOCAL_CHANGE | ITEM_XNAME_FOLLOWS,
|
||||
0, "");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (make_backups) {
|
||||
if (!make_backup(fname))
|
||||
return -1;
|
||||
} else if (robust_unlink(fname)) {
|
||||
rsyserr(FERROR, errno, "unlink %s failed",
|
||||
full_fname(fname));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return hard_link_one(file, ndx, fname, statret, st, toname,
|
||||
0, itemizing, code);
|
||||
}
|
||||
#endif
|
||||
|
||||
int hard_link_check(struct file_struct *file, int ndx, char *fname,
|
||||
int statret, STRUCT_STAT *st, int itemizing,
|
||||
enum logcode code, int skip)
|
||||
{
|
||||
#ifdef SUPPORT_HARD_LINKS
|
||||
if (!hlink_list || !file->link_u.links)
|
||||
int head;
|
||||
if (!file->link_u.links)
|
||||
return 0;
|
||||
if (skip && !(file->flags & FLAG_HLINK_EOL))
|
||||
hlink_list[file->F_HLINDEX] = file->F_NEXT;
|
||||
if (hlink_list[file->F_HLINDEX] != ndx) {
|
||||
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 (verbose > 2) {
|
||||
rprintf(FINFO, "\"%s\" is a hard link\n",
|
||||
safe_fname(f_name(file)));
|
||||
}
|
||||
if (head_file->F_HLINDEX == FINISHED_LINK) {
|
||||
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;
|
||||
}
|
||||
maybe_hard_link(file, ndx, fname, statret, st,
|
||||
toname, &st2, itemizing, code);
|
||||
file->F_HLINDEX = FINISHED_LINK;
|
||||
} else
|
||||
file->F_HLINDEX = SKIPPED_LINK;
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
@@ -160,10 +209,14 @@ int hard_link_one(struct file_struct *file, int ndx, char *fname,
|
||||
int itemizing, enum logcode code)
|
||||
{
|
||||
if (do_link(toname, fname)) {
|
||||
if (verbose) {
|
||||
rsyserr(FERROR, errno, "link %s => %s failed",
|
||||
full_fname(fname), safe_fname(toname));
|
||||
}
|
||||
if (terse) {
|
||||
if (!verbose)
|
||||
return -1;
|
||||
code = FINFO;
|
||||
} else
|
||||
code = FERROR;
|
||||
rsyserr(code, errno, "link %s => %s failed",
|
||||
full_fname(fname), safe_fname(toname));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -190,6 +243,7 @@ void hard_link_cluster(struct file_struct *file, int master, int itemizing,
|
||||
STRUCT_STAT st1, st2;
|
||||
int statret, ndx = master;
|
||||
|
||||
file->F_HLINDEX = FINISHED_LINK;
|
||||
if (link_stat(f_name_to(file, hlink1), &st1, 0) < 0)
|
||||
return;
|
||||
if (!(file->flags & FLAG_HLINK_TOL)) {
|
||||
@@ -201,33 +255,13 @@ void hard_link_cluster(struct file_struct *file, int master, int itemizing,
|
||||
do {
|
||||
ndx = file->F_NEXT;
|
||||
file = FPTR(ndx);
|
||||
if (ndx == master)
|
||||
if (file->F_HLINDEX != SKIPPED_LINK)
|
||||
continue;
|
||||
hlink2 = f_name(file);
|
||||
if ((statret = link_stat(hlink2, &st2, 0)) == 0) {
|
||||
if (st2.st_dev == st1.st_dev
|
||||
&& st2.st_ino == st1.st_ino) {
|
||||
if (itemizing) {
|
||||
itemize(file, ndx, statret, &st2,
|
||||
ITEM_LOCAL_CHANGE | ITEM_XNAME_FOLLOWS,
|
||||
0, "");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (make_backups) {
|
||||
if (!make_backup(hlink2))
|
||||
continue;
|
||||
} else if (robust_unlink(hlink2)) {
|
||||
if (verbose > 0) {
|
||||
rsyserr(FINFO, errno,
|
||||
"unlink %s failed",
|
||||
full_fname(hlink2));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
hard_link_one(file, ndx, hlink2, statret,
|
||||
&st2, hlink1, 0, itemizing, code);
|
||||
statret = link_stat(hlink2, &st2, 0);
|
||||
maybe_hard_link(file, ndx, hlink2, statret, &st2,
|
||||
hlink1, &st1, itemizing, code);
|
||||
file->F_HLINDEX = FINISHED_LINK;
|
||||
} while (!(file->flags & FLAG_HLINK_EOL));
|
||||
#endif
|
||||
}
|
||||
|
||||
109
io.c
109
io.c
@@ -49,6 +49,7 @@ extern int am_daemon;
|
||||
extern int am_sender;
|
||||
extern int am_generator;
|
||||
extern int eol_nulls;
|
||||
extern int read_batch;
|
||||
extern int csum_length;
|
||||
extern int checksum_seed;
|
||||
extern int protocol_version;
|
||||
@@ -59,7 +60,6 @@ extern struct stats stats;
|
||||
extern struct file_list *the_file_list;
|
||||
|
||||
const char phase_unknown[] = "unknown";
|
||||
int select_timeout = SELECT_TIMEOUT;
|
||||
int ignore_timeout = 0;
|
||||
int batch_fd = -1;
|
||||
int batch_gen_fd = -1;
|
||||
@@ -90,7 +90,8 @@ int sock_f_out = -1;
|
||||
|
||||
static int io_multiplexing_out;
|
||||
static int io_multiplexing_in;
|
||||
static time_t last_io;
|
||||
static time_t last_io_in;
|
||||
static time_t last_io_out;
|
||||
static int no_flush;
|
||||
|
||||
static int write_batch_monitor_in = -1;
|
||||
@@ -103,6 +104,7 @@ static char *io_filesfrom_bp;
|
||||
static char io_filesfrom_lastchar;
|
||||
static int io_filesfrom_buflen;
|
||||
static size_t contiguous_write_len = 0;
|
||||
static int select_timeout = SELECT_TIMEOUT;
|
||||
|
||||
static void read_loop(int fd, char *buf, size_t len);
|
||||
|
||||
@@ -166,17 +168,17 @@ static void check_timeout(void)
|
||||
if (!io_timeout || ignore_timeout)
|
||||
return;
|
||||
|
||||
if (!last_io) {
|
||||
last_io = time(NULL);
|
||||
if (!last_io_in) {
|
||||
last_io_in = time(NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
t = time(NULL);
|
||||
|
||||
if (t - last_io >= io_timeout) {
|
||||
if (t - last_io_in >= io_timeout) {
|
||||
if (!am_server && !am_daemon) {
|
||||
rprintf(FERROR, "io timeout after %d seconds -- exiting\n",
|
||||
(int)(t-last_io));
|
||||
(int)(t-last_io_in));
|
||||
}
|
||||
exit_cleanup(RERR_TIMEOUT);
|
||||
}
|
||||
@@ -190,6 +192,18 @@ void io_set_sock_fds(int f_in, int f_out)
|
||||
sock_f_out = f_out;
|
||||
}
|
||||
|
||||
void set_io_timeout(int secs)
|
||||
{
|
||||
io_timeout = secs;
|
||||
|
||||
if (!io_timeout || io_timeout > SELECT_TIMEOUT)
|
||||
select_timeout = SELECT_TIMEOUT;
|
||||
else
|
||||
select_timeout = io_timeout;
|
||||
|
||||
allowed_lull = read_batch ? 0 : (io_timeout + 1) / 2;
|
||||
}
|
||||
|
||||
/* Setup the fd used to receive MSG_* messages. Only needed during the
|
||||
* early stages of being a local sender (up through the sending of the
|
||||
* file list) or when we're the generator (to fetch the messages from
|
||||
@@ -574,8 +588,8 @@ static int read_timeout(int fd, char *buf, size_t len)
|
||||
len -= n;
|
||||
ret += n;
|
||||
|
||||
if (io_timeout && fd == sock_f_in)
|
||||
last_io = time(NULL);
|
||||
if (fd == sock_f_in && io_timeout)
|
||||
last_io_in = time(NULL);
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -665,9 +679,16 @@ 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 >= allowed_lull) {
|
||||
if (time(NULL) - last_io_out >= allowed_lull) {
|
||||
if (!iobuf_out || !iobuf_out_cnt) {
|
||||
if (protocol_version < 29)
|
||||
return; /* there's nothing we can do */
|
||||
@@ -705,8 +726,13 @@ 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, ret = 0;
|
||||
char line[MAXPATHLEN+1];
|
||||
#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);
|
||||
@@ -729,56 +755,52 @@ static int readfd_unbuffered(int fd, char *buf, size_t len)
|
||||
read_loop(fd, line, 4);
|
||||
tag = IVAL(line, 0);
|
||||
|
||||
remaining = tag & 0xFFFFFF;
|
||||
msg_bytes = tag & 0xFFFFFF;
|
||||
tag = (tag >> 24) - MPLEX_BASE;
|
||||
|
||||
switch (tag) {
|
||||
case MSG_DATA:
|
||||
if (remaining > iobuf_in_siz) {
|
||||
if (msg_bytes > iobuf_in_siz) {
|
||||
if (!(iobuf_in = realloc_array(iobuf_in, char,
|
||||
remaining)))
|
||||
msg_bytes)))
|
||||
out_of_memory("readfd_unbuffered");
|
||||
iobuf_in_siz = remaining;
|
||||
iobuf_in_siz = msg_bytes;
|
||||
}
|
||||
read_loop(fd, iobuf_in, remaining);
|
||||
read_loop(fd, iobuf_in, msg_bytes);
|
||||
remaining = msg_bytes;
|
||||
iobuf_in_ndx = 0;
|
||||
break;
|
||||
case MSG_DELETED:
|
||||
if (remaining >= sizeof line) {
|
||||
rprintf(FERROR, "invalid multi-message %d:%ld\n",
|
||||
tag, (long)remaining);
|
||||
exit_cleanup(RERR_STREAMIO);
|
||||
}
|
||||
read_loop(fd, line, remaining);
|
||||
line[remaining] = '\0';
|
||||
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 (remaining > 0 && !line[remaining-1])
|
||||
if (msg_bytes > 0 && !line[msg_bytes-1])
|
||||
log_delete(line, S_IFDIR);
|
||||
else
|
||||
log_delete(line, S_IFREG);
|
||||
remaining = 0;
|
||||
break;
|
||||
case MSG_SUCCESS:
|
||||
if (remaining != 4) {
|
||||
if (msg_bytes != 4) {
|
||||
rprintf(FERROR, "invalid multi-message %d:%ld [%s]\n",
|
||||
tag, (long)remaining, who_am_i());
|
||||
tag, (long)msg_bytes, who_am_i());
|
||||
exit_cleanup(RERR_STREAMIO);
|
||||
}
|
||||
read_loop(fd, line, remaining);
|
||||
read_loop(fd, line, msg_bytes);
|
||||
successful_send(IVAL(line, 0));
|
||||
remaining = 0;
|
||||
break;
|
||||
case MSG_INFO:
|
||||
case MSG_ERROR:
|
||||
if (remaining >= sizeof line) {
|
||||
if (msg_bytes >= sizeof line) {
|
||||
overflow:
|
||||
rprintf(FERROR,
|
||||
"multiplexing overflow %d:%ld [%s]\n",
|
||||
tag, (long)remaining, who_am_i());
|
||||
tag, (long)msg_bytes, who_am_i());
|
||||
exit_cleanup(RERR_STREAMIO);
|
||||
}
|
||||
read_loop(fd, line, remaining);
|
||||
rwrite((enum logcode)tag, line, remaining);
|
||||
remaining = 0;
|
||||
read_loop(fd, line, msg_bytes);
|
||||
rwrite((enum logcode)tag, line, msg_bytes);
|
||||
break;
|
||||
default:
|
||||
rprintf(FERROR, "unexpected tag %d [%s]\n",
|
||||
@@ -1006,7 +1028,7 @@ static void writefd_unbuffered(int fd,char *buf,size_t len)
|
||||
{
|
||||
size_t n, total = 0;
|
||||
fd_set w_fds, r_fds;
|
||||
int maxfd, count, ret;
|
||||
int maxfd, count, ret, using_r_fds;
|
||||
struct timeval tv;
|
||||
|
||||
no_flush++;
|
||||
@@ -1021,18 +1043,15 @@ static void writefd_unbuffered(int fd,char *buf,size_t len)
|
||||
FD_SET(msg_fd_in,&r_fds);
|
||||
if (msg_fd_in > maxfd)
|
||||
maxfd = msg_fd_in;
|
||||
}
|
||||
if (fd != sock_f_out && iobuf_out_cnt && no_flush == 1) {
|
||||
FD_SET(sock_f_out, &w_fds);
|
||||
if (sock_f_out > maxfd)
|
||||
maxfd = sock_f_out;
|
||||
}
|
||||
using_r_fds = 1;
|
||||
} else
|
||||
using_r_fds = 0;
|
||||
|
||||
tv.tv_sec = select_timeout;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
errno = 0;
|
||||
count = select(maxfd + 1, msg_fd_in >= 0 ? &r_fds : NULL,
|
||||
count = select(maxfd + 1, using_r_fds ? &r_fds : NULL,
|
||||
&w_fds, NULL, &tv);
|
||||
|
||||
if (count <= 0) {
|
||||
@@ -1042,7 +1061,7 @@ static void writefd_unbuffered(int fd,char *buf,size_t len)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (msg_fd_in >= 0 && FD_ISSET(msg_fd_in, &r_fds))
|
||||
if (using_r_fds && FD_ISSET(msg_fd_in, &r_fds))
|
||||
read_msg_fd();
|
||||
|
||||
if (!FD_ISSET(fd, &w_fds))
|
||||
@@ -1072,7 +1091,7 @@ static void writefd_unbuffered(int fd,char *buf,size_t len)
|
||||
/* 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) {
|
||||
io_timeout = select_timeout = 30;
|
||||
set_io_timeout(30);
|
||||
ignore_timeout = 0;
|
||||
readfd_unbuffered(sock_f_in, io_filesfrom_buf,
|
||||
sizeof io_filesfrom_buf);
|
||||
@@ -1083,8 +1102,8 @@ static void writefd_unbuffered(int fd,char *buf,size_t len)
|
||||
total += ret;
|
||||
|
||||
if (fd == sock_f_out) {
|
||||
if (io_timeout)
|
||||
last_io = time(NULL);
|
||||
if (io_timeout || am_generator)
|
||||
last_io_out = time(NULL);
|
||||
sleep_for_bwlimit(ret);
|
||||
}
|
||||
}
|
||||
|
||||
249
log.c
249
log.c
@@ -32,6 +32,7 @@ extern int dry_run;
|
||||
extern int am_daemon;
|
||||
extern int am_server;
|
||||
extern int am_sender;
|
||||
extern int local_server;
|
||||
extern int quiet;
|
||||
extern int module_id;
|
||||
extern int msg_fd_out;
|
||||
@@ -43,6 +44,7 @@ extern char *auth_user;
|
||||
extern char *log_format;
|
||||
|
||||
static int log_initialised;
|
||||
static int logfile_was_closed;
|
||||
static char *logfname;
|
||||
static FILE *logfile;
|
||||
struct stats stats;
|
||||
@@ -58,7 +60,6 @@ struct {
|
||||
{ RERR_FILESELECT , "errors selecting input/output files, dirs" },
|
||||
{ RERR_UNSUPPORTED, "requested action not supported" },
|
||||
{ RERR_STARTCLIENT, "error starting client-server protocol" },
|
||||
{ RERR_LOG_FAILURE, "daemon unable to append to log-file" },
|
||||
{ RERR_SOCKETIO , "error in socket IO" },
|
||||
{ RERR_FILEIO , "error in file IO" },
|
||||
{ RERR_STREAMIO , "error in rsync protocol data stream" },
|
||||
@@ -96,9 +97,9 @@ static char const *rerr_name(int code)
|
||||
|
||||
static void logit(int priority, char *buf)
|
||||
{
|
||||
if (logfname) {
|
||||
if (!logfile)
|
||||
log_open();
|
||||
if (logfile_was_closed)
|
||||
logfile_reopen();
|
||||
if (logfile) {
|
||||
fprintf(logfile,"%s [%d] %s",
|
||||
timestring(time(NULL)), (int)getpid(), buf);
|
||||
fflush(logfile);
|
||||
@@ -107,9 +108,48 @@ static void logit(int priority, char *buf)
|
||||
}
|
||||
}
|
||||
|
||||
static void syslog_init()
|
||||
{
|
||||
static int been_here = 0;
|
||||
int options = LOG_PID;
|
||||
|
||||
if (been_here)
|
||||
return;
|
||||
been_here = 1;
|
||||
|
||||
#ifdef LOG_NDELAY
|
||||
options |= LOG_NDELAY;
|
||||
#endif
|
||||
|
||||
#ifdef LOG_DAEMON
|
||||
openlog("rsyncd", options, lp_syslog_facility());
|
||||
#else
|
||||
openlog("rsyncd", options);
|
||||
#endif
|
||||
|
||||
#ifndef LOG_NDELAY
|
||||
logit(LOG_INFO, "rsyncd started\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void logfile_open(void)
|
||||
{
|
||||
extern int orig_umask;
|
||||
int old_umask = umask(022 | orig_umask);
|
||||
logfile = fopen(logfname, "a");
|
||||
umask(old_umask);
|
||||
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", logfname);
|
||||
rprintf(FINFO, "Ignoring \"log file\" setting.\n");
|
||||
}
|
||||
}
|
||||
|
||||
void log_init(void)
|
||||
{
|
||||
int options = LOG_PID;
|
||||
time_t t;
|
||||
|
||||
if (log_initialised)
|
||||
@@ -124,52 +164,29 @@ void log_init(void)
|
||||
|
||||
/* optionally use a log file instead of syslog */
|
||||
logfname = lp_log_file();
|
||||
if (logfname) {
|
||||
if (*logfname) {
|
||||
log_open();
|
||||
return;
|
||||
}
|
||||
logfname = NULL;
|
||||
}
|
||||
|
||||
#ifdef LOG_NDELAY
|
||||
options |= LOG_NDELAY;
|
||||
#endif
|
||||
|
||||
#ifdef LOG_DAEMON
|
||||
openlog("rsyncd", options, lp_syslog_facility());
|
||||
#else
|
||||
openlog("rsyncd", options);
|
||||
#endif
|
||||
|
||||
#ifndef LOG_NDELAY
|
||||
logit(LOG_INFO,"rsyncd started\n");
|
||||
#endif
|
||||
if (logfname && *logfname)
|
||||
logfile_open();
|
||||
else
|
||||
syslog_init();
|
||||
}
|
||||
|
||||
void log_open(void)
|
||||
{
|
||||
if (logfname && !logfile) {
|
||||
extern int orig_umask;
|
||||
int old_umask = umask(022 | orig_umask);
|
||||
logfile = fopen(logfname, "a");
|
||||
umask(old_umask);
|
||||
if (!logfile) {
|
||||
am_daemon = 0; /* avoid trying to log again */
|
||||
rsyserr(FERROR, errno, "fopen() of log-file failed");
|
||||
exit_cleanup(RERR_LOG_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void log_close(void)
|
||||
void logfile_close(void)
|
||||
{
|
||||
if (logfile) {
|
||||
logfile_was_closed = 1;
|
||||
fclose(logfile);
|
||||
logfile = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void logfile_reopen(void)
|
||||
{
|
||||
if (logfile_was_closed) {
|
||||
logfile_was_closed = 0;
|
||||
logfile_open();
|
||||
}
|
||||
}
|
||||
|
||||
/* this is the underlying (unformatted) rsync debugging function. Call
|
||||
* it with FINFO, FERROR or FLOG */
|
||||
void rwrite(enum logcode code, char *buf, int len)
|
||||
@@ -239,7 +256,7 @@ void rwrite(enum logcode code, char *buf, int len)
|
||||
if (buf[len-1] == '\r' || buf[len-1] == '\n')
|
||||
fflush(f);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* This is the rsync debugging function. Call it with FINFO, FERROR or
|
||||
* FLOG. */
|
||||
@@ -319,7 +336,7 @@ void rsyserr(enum logcode code, int errcode, const char *format, ...)
|
||||
void rflush(enum logcode code)
|
||||
{
|
||||
FILE *f = NULL;
|
||||
|
||||
|
||||
if (am_daemon) {
|
||||
return;
|
||||
}
|
||||
@@ -351,44 +368,70 @@ static void log_formatted(enum logcode code, char *format, char *op,
|
||||
struct file_struct *file, struct stats *initial_stats,
|
||||
int iflags, char *hlink)
|
||||
{
|
||||
char buf[MAXPATHLEN+1024];
|
||||
char buf2[MAXPATHLEN];
|
||||
char *p, *n;
|
||||
char buf[MAXPATHLEN+1024], buf2[MAXPATHLEN], fmt[32];
|
||||
char *p, *s, *n;
|
||||
size_t len, total;
|
||||
int64 b;
|
||||
|
||||
*fmt = '%';
|
||||
|
||||
/* We expand % codes one by one in place in buf. We don't
|
||||
* copy in the terminating nul of the inserted strings, but
|
||||
* rather keep going until we reach the nul of the format. */
|
||||
* copy in the terminating null of the inserted strings, but
|
||||
* rather keep going until we reach the null of the format. */
|
||||
total = strlcpy(buf, format, sizeof buf);
|
||||
|
||||
for (p = buf; (p = strchr(p, '%')) != NULL && p[1]; ) {
|
||||
if (total > MAXPATHLEN) {
|
||||
rprintf(FERROR, "log-format string is WAY too long!\n");
|
||||
exit_cleanup(RERR_MESSAGEIO);
|
||||
}
|
||||
buf[total++] = '\n';
|
||||
buf[total] = '\0';
|
||||
|
||||
for (p = buf; (p = strchr(p, '%')) != NULL; ) {
|
||||
s = p++;
|
||||
n = fmt + 1;
|
||||
if (*p == '-')
|
||||
*n++ = *p++;
|
||||
while (isdigit(*(uchar*)p) && n - fmt < (int)(sizeof fmt) - 8)
|
||||
*n++ = *p++;
|
||||
if (!*p)
|
||||
break;
|
||||
*n = '\0';
|
||||
n = NULL;
|
||||
|
||||
switch (p[1]) {
|
||||
switch (*p) {
|
||||
case 'h': if (am_daemon) n = client_name(0); break;
|
||||
case 'a': if (am_daemon) n = client_addr(0); break;
|
||||
case 'l':
|
||||
snprintf(buf2, sizeof buf2, "%.0f",
|
||||
strlcat(fmt, ".0f", sizeof fmt);
|
||||
snprintf(buf2, sizeof buf2, fmt,
|
||||
(double)file->length);
|
||||
n = buf2;
|
||||
break;
|
||||
case 'p':
|
||||
snprintf(buf2, sizeof buf2, "%d",
|
||||
(int)getpid());
|
||||
strlcat(fmt, "ld", sizeof fmt);
|
||||
snprintf(buf2, sizeof buf2, fmt,
|
||||
(long)getpid());
|
||||
n = buf2;
|
||||
break;
|
||||
case 'o': n = op; break;
|
||||
case 'f':
|
||||
pathjoin(buf2, sizeof buf2,
|
||||
am_sender && file->dir.root ? file->dir.root : "",
|
||||
safe_fname(f_name(file)));
|
||||
clean_fname(buf2, 0);
|
||||
n = buf2;
|
||||
if (*n == '/') n++;
|
||||
n = safe_fname(f_name(file));
|
||||
if (am_sender && file->dir.root) {
|
||||
pathjoin(buf2, sizeof buf2,
|
||||
file->dir.root, n);
|
||||
/* The buffer from safe_fname() has more
|
||||
* room than MAXPATHLEN, so this is safe. */
|
||||
if (fmt[1])
|
||||
strcpy(n, buf2);
|
||||
else
|
||||
n = buf2;
|
||||
}
|
||||
clean_fname(n, 0);
|
||||
if (*n == '/')
|
||||
n++;
|
||||
break;
|
||||
case 'n':
|
||||
n = (char*)safe_fname(f_name(file));
|
||||
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. */
|
||||
@@ -397,15 +440,20 @@ static void log_formatted(enum logcode code, char *format, char *op,
|
||||
break;
|
||||
case 'L':
|
||||
if (hlink && *hlink) {
|
||||
snprintf(buf2, sizeof buf2, " => %s",
|
||||
safe_fname(hlink));
|
||||
n = buf2;
|
||||
n = safe_fname(hlink);
|
||||
strcpy(buf2, " => ");
|
||||
} else if (S_ISLNK(file->mode) && file->u.link) {
|
||||
snprintf(buf2, sizeof buf2, " -> %s",
|
||||
safe_fname(file->u.link));
|
||||
n = buf2;
|
||||
} else
|
||||
n = safe_fname(file->u.link);
|
||||
strcpy(buf2, " -> ");
|
||||
} else {
|
||||
n = "";
|
||||
if (!fmt[1])
|
||||
break;
|
||||
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;
|
||||
@@ -419,7 +467,8 @@ static void log_formatted(enum logcode code, char *format, char *op,
|
||||
b = stats.total_read -
|
||||
initial_stats->total_read;
|
||||
}
|
||||
snprintf(buf2, sizeof buf2, "%.0f", (double)b);
|
||||
strlcat(fmt, ".0f", sizeof fmt);
|
||||
snprintf(buf2, sizeof buf2, fmt, (double)b);
|
||||
n = buf2;
|
||||
break;
|
||||
case 'c':
|
||||
@@ -430,7 +479,8 @@ static void log_formatted(enum logcode code, char *format, char *op,
|
||||
b = stats.total_read -
|
||||
initial_stats->total_read;
|
||||
}
|
||||
snprintf(buf2, sizeof buf2, "%.0f", (double)b);
|
||||
strlcat(fmt, ".0f", sizeof fmt);
|
||||
snprintf(buf2, sizeof buf2, fmt, (double)b);
|
||||
n = buf2;
|
||||
break;
|
||||
case 'i':
|
||||
@@ -438,11 +488,11 @@ static void log_formatted(enum logcode code, char *format, char *op,
|
||||
n = "*deleting";
|
||||
break;
|
||||
}
|
||||
n = buf2;
|
||||
n = buf2 + MAXPATHLEN - 32;
|
||||
n[0] = iflags & ITEM_LOCAL_CHANGE
|
||||
? iflags & ITEM_XNAME_FOLLOWS ? 'h' : 'c'
|
||||
: !(iflags & ITEM_TRANSFER) ? '.'
|
||||
: *op == 's' ? '<' : '>';
|
||||
: !local_server && *op == 's' ? '<' : '>';
|
||||
n[1] = S_ISDIR(file->mode) ? 'd'
|
||||
: IS_DEVICE(file->mode) ? 'D'
|
||||
: S_ISLNK(file->mode) ? 'L' : 'f';
|
||||
@@ -476,17 +526,20 @@ static void log_formatted(enum logcode code, char *format, char *op,
|
||||
break;
|
||||
}
|
||||
|
||||
/* n is the string to be inserted in place of this %
|
||||
* code; len is its length not including the trailing
|
||||
* NUL */
|
||||
if (!n) {
|
||||
p += 2;
|
||||
/* "n" is the string to be inserted in place of this % code. */
|
||||
if (!n)
|
||||
continue;
|
||||
if (n != buf2 && fmt[1]) {
|
||||
strlcat(fmt, "s", sizeof fmt);
|
||||
snprintf(buf2, sizeof buf2, fmt, n);
|
||||
n = buf2;
|
||||
}
|
||||
|
||||
len = strlen(n);
|
||||
|
||||
if (len + total - 2 >= sizeof buf) {
|
||||
/* Subtract the length of the escape from the string's size. */
|
||||
total -= p - s + 1;
|
||||
|
||||
if (len + total >= (size_t)sizeof buf) {
|
||||
rprintf(FERROR,
|
||||
"buffer overflow expanding %%%c -- exiting\n",
|
||||
p[0]);
|
||||
@@ -494,19 +547,41 @@ static void log_formatted(enum logcode code, char *format, char *op,
|
||||
}
|
||||
|
||||
/* Shuffle the rest of the string along to make space for n */
|
||||
if (len != 2)
|
||||
memmove(p + len, p + 2, total - (p + 2 - buf) + 1);
|
||||
total += len - 2;
|
||||
if (len != (size_t)(p - s + 1))
|
||||
memmove(s + len, p + 1, total - (s - buf) + 1);
|
||||
total += len;
|
||||
|
||||
/* Insert the contents of string "n", but NOT its nul. */
|
||||
/* Insert the contents of string "n", but NOT its null. */
|
||||
if (len)
|
||||
memcpy(p, n, len);
|
||||
memcpy(s, n, len);
|
||||
|
||||
/* Skip over inserted string; continue looking */
|
||||
p += len;
|
||||
p = s + len;
|
||||
}
|
||||
|
||||
rprintf(code, "%s\n", buf);
|
||||
rwrite(code, buf, total);
|
||||
}
|
||||
|
||||
/* Return 1 if the format escape is in the log-format string (e.g. look for
|
||||
* the 'b' in the "%9b" format escape). */
|
||||
int log_format_has(const char *format, char esc)
|
||||
{
|
||||
const char *p;
|
||||
|
||||
if (!format)
|
||||
return 0;
|
||||
|
||||
for (p = format; (p = strchr(p, '%')) != NULL; ) {
|
||||
if (*++p == '-')
|
||||
p++;
|
||||
while (isdigit(*(uchar*)p))
|
||||
p++;
|
||||
if (!*p)
|
||||
break;
|
||||
if (*p == esc)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* log the transfer of a file */
|
||||
|
||||
71
main.c
71
main.c
@@ -20,8 +20,9 @@
|
||||
*/
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
time_t starttime = 0;
|
||||
#if defined CONFIG_LOCALE && defined HAVE_LOCALE_H
|
||||
#include <locale.h>
|
||||
#endif
|
||||
|
||||
extern int verbose;
|
||||
extern int dry_run;
|
||||
@@ -77,6 +78,9 @@ struct pid_status {
|
||||
int status;
|
||||
} pid_stat_table[MAXCHILDPROCS];
|
||||
|
||||
static time_t starttime, endtime;
|
||||
static int64 total_read, total_written;
|
||||
|
||||
static void show_malloc_stats(void);
|
||||
|
||||
/****************************************************************************
|
||||
@@ -121,12 +125,13 @@ void wait_process(pid_t pid, int *status)
|
||||
* the report. All processes might also generate a set of debug stats, if
|
||||
* the verbose level is high enough (this is the only thing that the
|
||||
* generator process and the server receiver ever do here). */
|
||||
static void report(int f)
|
||||
static void handle_stats(int f)
|
||||
{
|
||||
endtime = time(NULL);
|
||||
|
||||
/* Cache two stats because the read/write code can change it. */
|
||||
int64 total_read = stats.total_read;
|
||||
int64 total_written = stats.total_written;
|
||||
time_t t = time(NULL);
|
||||
total_read = stats.total_read;
|
||||
total_written = stats.total_written;
|
||||
|
||||
if (do_stats && verbose > 1) {
|
||||
/* These come out from every process */
|
||||
@@ -158,7 +163,9 @@ static void report(int f)
|
||||
|
||||
/* this is the client */
|
||||
|
||||
if (!am_sender) {
|
||||
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. */
|
||||
total_written = read_longint(f);
|
||||
@@ -179,7 +186,10 @@ static void report(int f)
|
||||
write_longint(batch_fd, stats.flist_xfertime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void output_summary(void)
|
||||
{
|
||||
if (do_stats) {
|
||||
rprintf(FINFO,"\nNumber of files: %d\n", stats.num_files);
|
||||
rprintf(FINFO,"Number of files transferred: %d\n",
|
||||
@@ -211,7 +221,7 @@ static void report(int f)
|
||||
rprintf(FINFO,
|
||||
"\nsent %.0f bytes received %.0f bytes %.2f bytes/sec\n",
|
||||
(double)total_written, (double)total_read,
|
||||
(total_written + total_read)/(0.5 + (t - starttime)));
|
||||
(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));
|
||||
@@ -283,7 +293,7 @@ static pid_t do_cmd(char *cmd, char *machine, char *user, char *path,
|
||||
|
||||
for (tok = strtok(cmd, " "); tok; tok = strtok(NULL, " ")) {
|
||||
/* Comparison leaves rooms for server_options(). */
|
||||
if (argc >= MAX_ARGS - 100) {
|
||||
if (argc >= MAX_ARGS - MAX_SERVER_ARGS) {
|
||||
rprintf(FERROR, "internal: args[] overflowed in do_cmd()\n");
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
}
|
||||
@@ -509,7 +519,7 @@ static void do_server_sender(int f_in, int f_out, int argc,char *argv[])
|
||||
|
||||
send_files(flist,f_out,f_in);
|
||||
io_flush(FULL_FLUSH);
|
||||
report(f_out);
|
||||
handle_stats(f_out);
|
||||
if (protocol_version >= 24)
|
||||
read_final_goodbye(f_in, f_out);
|
||||
io_flush(FULL_FLUSH);
|
||||
@@ -555,7 +565,7 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
|
||||
|
||||
recv_files(f_in, flist, local_name);
|
||||
io_flush(FULL_FLUSH);
|
||||
report(f_in);
|
||||
handle_stats(f_in);
|
||||
|
||||
send_msg(MSG_DONE, "", 0);
|
||||
io_flush(FULL_FLUSH);
|
||||
@@ -583,7 +593,7 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
|
||||
|
||||
am_generator = 1;
|
||||
close_multiplexing_in();
|
||||
if (write_batch)
|
||||
if (write_batch && !am_server)
|
||||
stop_write_batch();
|
||||
|
||||
close(error_pipe[1]);
|
||||
@@ -596,7 +606,7 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
|
||||
|
||||
generate_files(f_out, flist, local_name);
|
||||
|
||||
report(-1);
|
||||
handle_stats(-1);
|
||||
io_flush(FULL_FLUSH);
|
||||
if (protocol_version >= 24) {
|
||||
/* send a final goodbye message */
|
||||
@@ -756,7 +766,7 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
|
||||
if (filesfrom_host)
|
||||
filesfrom_fd = f_in;
|
||||
|
||||
if (write_batch)
|
||||
if (write_batch && !am_server)
|
||||
start_write_batch(f_out);
|
||||
flist = send_file_list(f_out, argc, argv);
|
||||
set_msg_fd_in(-1);
|
||||
@@ -767,6 +777,7 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
|
||||
io_flush(NORMAL_FLUSH);
|
||||
send_files(flist,f_out,f_in);
|
||||
io_flush(FULL_FLUSH);
|
||||
handle_stats(-1);
|
||||
if (protocol_version >= 24)
|
||||
read_final_goodbye(f_in, f_out);
|
||||
if (pid != -1) {
|
||||
@@ -775,7 +786,7 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
|
||||
io_flush(FULL_FLUSH);
|
||||
wait_process(pid, &status);
|
||||
}
|
||||
report(-1);
|
||||
output_summary();
|
||||
io_flush(FULL_FLUSH);
|
||||
exit_cleanup(status);
|
||||
}
|
||||
@@ -793,20 +804,19 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
|
||||
filesfrom_fd = -1;
|
||||
}
|
||||
|
||||
if (write_batch)
|
||||
if (write_batch && !am_server)
|
||||
start_write_batch(f_in);
|
||||
flist = recv_file_list(f_in);
|
||||
if (!flist || flist->count == 0) {
|
||||
rprintf(FINFO, "client: nothing to do: "
|
||||
"perhaps you need to specify some filenames or "
|
||||
"the --recursive option?\n");
|
||||
exit_cleanup(0);
|
||||
}
|
||||
the_file_list = flist;
|
||||
|
||||
local_name = get_local_name(flist,argv[0]);
|
||||
if (flist && flist->count > 0) {
|
||||
local_name = get_local_name(flist, argv[0]);
|
||||
|
||||
status2 = 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();
|
||||
}
|
||||
|
||||
if (pid != -1) {
|
||||
if (verbose > 3)
|
||||
@@ -977,8 +987,11 @@ static RETSIGTYPE sigusr1_handler(UNUSED(int val))
|
||||
|
||||
static RETSIGTYPE sigusr2_handler(UNUSED(int val))
|
||||
{
|
||||
if (!am_server)
|
||||
output_summary();
|
||||
close_all();
|
||||
if (log_got_error) _exit(RERR_PARTIAL);
|
||||
if (log_got_error)
|
||||
_exit(RERR_PARTIAL);
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
@@ -1103,6 +1116,10 @@ int main(int argc,char *argv[])
|
||||
* see the EPIPE. */
|
||||
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
|
||||
@@ -1111,7 +1128,7 @@ int main(int argc,char *argv[])
|
||||
|
||||
init_flist();
|
||||
|
||||
if (write_batch || read_batch) {
|
||||
if ((write_batch || read_batch) && !am_server) {
|
||||
if (write_batch)
|
||||
write_batch_shell_file(orig_argc, orig_argv, argc);
|
||||
|
||||
@@ -1130,6 +1147,8 @@ int main(int argc,char *argv[])
|
||||
if (read_batch)
|
||||
read_stream_flags(batch_fd);
|
||||
}
|
||||
if (write_batch < 0)
|
||||
dry_run = 1;
|
||||
|
||||
if (am_daemon && !am_server)
|
||||
return daemon_main();
|
||||
|
||||
105
options.c
105
options.c
@@ -23,7 +23,6 @@
|
||||
|
||||
extern int module_id;
|
||||
extern int sanitize_paths;
|
||||
extern int select_timeout;
|
||||
extern struct filter_list_struct filter_list;
|
||||
extern struct filter_list_struct server_filter_list;
|
||||
|
||||
@@ -53,6 +52,7 @@ int omit_dir_times = 0;
|
||||
int update_only = 0;
|
||||
int cvs_exclude = 0;
|
||||
int dry_run = 0;
|
||||
int do_xfers = 1;
|
||||
int ignore_times = 0;
|
||||
int delete_mode = 0;
|
||||
int delete_during = 0;
|
||||
@@ -75,6 +75,7 @@ int implied_dirs = 1;
|
||||
int numeric_ids = 0;
|
||||
int force_delete = 0;
|
||||
int io_timeout = 0;
|
||||
int allowed_lull = 0;
|
||||
char *files_from = NULL;
|
||||
int filesfrom_fd = -1;
|
||||
char *filesfrom_host = NULL;
|
||||
@@ -150,7 +151,6 @@ char *dest_option = NULL;
|
||||
|
||||
int verbose = 0;
|
||||
int quiet = 0;
|
||||
int itemize_changes = 0;
|
||||
int log_before_transfer = 0;
|
||||
int log_format_has_i = 0;
|
||||
int log_format_has_o_or_i = 0;
|
||||
@@ -163,6 +163,7 @@ char *batch_name = NULL;
|
||||
static int daemon_opt; /* sets am_daemon after option error-reporting */
|
||||
static int F_option_cnt = 0;
|
||||
static int modify_window_set;
|
||||
static int itemize_changes = 0;
|
||||
static int refused_delete, refused_archive_part;
|
||||
static int refused_partial, refused_progress, refused_delete_before;
|
||||
static char *max_size_arg;
|
||||
@@ -250,7 +251,7 @@ void usage(enum logcode F)
|
||||
rprintf(F,"\nrsync is a file transfer program capable of efficient remote update\nvia a fast differencing algorithm.\n\n");
|
||||
|
||||
rprintf(F,"Usage: rsync [OPTION]... SRC [SRC]... [USER@]HOST:DEST\n");
|
||||
rprintf(F," or rsync [OPTION]... [USER@]HOST:SRC DEST\n");
|
||||
rprintf(F," or rsync [OPTION]... [USER@]HOST:SRC [DEST]\n");
|
||||
rprintf(F," or rsync [OPTION]... SRC [SRC]... DEST\n");
|
||||
rprintf(F," or rsync [OPTION]... [USER@]HOST::SRC [DEST]\n");
|
||||
rprintf(F," or rsync [OPTION]... SRC [SRC]... [USER@]HOST::DEST\n");
|
||||
@@ -330,8 +331,8 @@ void usage(enum logcode F)
|
||||
rprintf(F," --include=PATTERN don't exclude files matching PATTERN\n");
|
||||
rprintf(F," --include-from=FILE read include patterns from FILE\n");
|
||||
rprintf(F," --files-from=FILE read list of source-file names from FILE\n");
|
||||
rprintf(F," -0, --from0 all *-from file lists are delimited by nulls\n");
|
||||
rprintf(F," --version print version number\n");
|
||||
rprintf(F," -0, --from0 all *-from/filter files are delimited by 0s\n");
|
||||
rprintf(F," --address=ADDRESS bind address for outgoing socket to daemon\n");
|
||||
rprintf(F," --port=PORT specify double-colon alternate port number\n");
|
||||
rprintf(F," --blocking-io use blocking I/O for the remote shell\n");
|
||||
rprintf(F," --no-blocking-io turn off blocking I/O when it is the default\n");
|
||||
@@ -339,17 +340,19 @@ void usage(enum logcode F)
|
||||
rprintf(F," --progress show progress during transfer\n");
|
||||
rprintf(F," -P same as --partial --progress\n");
|
||||
rprintf(F," -i, --itemize-changes output a change-summary for all updates\n");
|
||||
rprintf(F," --log-format=FORMAT log file-transfers using specified format\n");
|
||||
rprintf(F," --log-format=FORMAT output filenames using the specified format\n");
|
||||
rprintf(F," --password-file=FILE read password from FILE\n");
|
||||
rprintf(F," --list-only list the files instead of copying them\n");
|
||||
rprintf(F," --bwlimit=KBPS limit I/O bandwidth; KBytes per second\n");
|
||||
rprintf(F," --write-batch=FILE write a batched update to FILE\n");
|
||||
rprintf(F," --only-write-batch=FILE like --write-batch but w/o updating destination\n");
|
||||
rprintf(F," --read-batch=FILE read a batched update from FILE\n");
|
||||
rprintf(F," --protocol=NUM force an older protocol version to be used\n");
|
||||
#ifdef INET6
|
||||
rprintf(F," -4, --ipv4 prefer IPv4\n");
|
||||
rprintf(F," -6, --ipv6 prefer IPv6\n");
|
||||
#endif
|
||||
rprintf(F," --version print version number\n");
|
||||
rprintf(F," -h, --help show this help screen\n");
|
||||
|
||||
rprintf(F,"\nUse \"rsync --daemon --help\" to see the daemon-mode command-line options.\n");
|
||||
@@ -360,7 +363,7 @@ void usage(enum logcode F)
|
||||
enum {OPT_VERSION = 1000, OPT_DAEMON, OPT_SENDER, OPT_EXCLUDE, OPT_EXCLUDE_FROM,
|
||||
OPT_FILTER, OPT_COMPARE_DEST, OPT_COPY_DEST, OPT_LINK_DEST,
|
||||
OPT_INCLUDE, OPT_INCLUDE_FROM, OPT_MODIFY_WINDOW,
|
||||
OPT_READ_BATCH, OPT_WRITE_BATCH, OPT_TIMEOUT, OPT_MAX_SIZE,
|
||||
OPT_READ_BATCH, OPT_WRITE_BATCH, OPT_ONLY_WRITE_BATCH, OPT_MAX_SIZE,
|
||||
OPT_REFUSED_BASE = 9000};
|
||||
|
||||
static struct poptOption long_options[] = {
|
||||
@@ -424,7 +427,7 @@ static struct poptOption long_options[] = {
|
||||
{"block-size", 'B', POPT_ARG_LONG, &block_size, 0, 0, 0 },
|
||||
{"max-delete", 0, POPT_ARG_INT, &max_delete, 0, 0, 0 },
|
||||
{"max-size", 0, POPT_ARG_STRING, &max_size_arg, OPT_MAX_SIZE, 0, 0 },
|
||||
{"timeout", 0, POPT_ARG_INT, &io_timeout, OPT_TIMEOUT, 0, 0 },
|
||||
{"timeout", 0, POPT_ARG_INT, &io_timeout, 0, 0, 0 },
|
||||
{"temp-dir", 'T', POPT_ARG_STRING, &tmpdir, 0, 0, 0 },
|
||||
{"compare-dest", 0, POPT_ARG_STRING, 0, OPT_COMPARE_DEST, 0, 0 },
|
||||
{"copy-dest", 0, POPT_ARG_STRING, 0, OPT_COPY_DEST, 0, 0 },
|
||||
@@ -442,6 +445,7 @@ static struct poptOption long_options[] = {
|
||||
{"no-blocking-io", 0, POPT_ARG_VAL, &blocking_io, 0, 0, 0 },
|
||||
{0, 'F', POPT_ARG_NONE, 0, 'F', 0, 0 },
|
||||
{0, 'P', POPT_ARG_NONE, 0, 'P', 0, 0 },
|
||||
{"address", 0, POPT_ARG_STRING, &bind_address, 0, 0, 0 },
|
||||
{"port", 0, POPT_ARG_INT, &rsync_port, 0, 0, 0 },
|
||||
{"log-format", 0, POPT_ARG_STRING, &log_format, 0, 0, 0 },
|
||||
{"itemize-changes", 'i', POPT_ARG_NONE, &itemize_changes, 0, 0, 0 },
|
||||
@@ -450,6 +454,7 @@ static struct poptOption long_options[] = {
|
||||
{"hard-links", 'H', POPT_ARG_NONE, &preserve_hard_links, 0, 0, 0 },
|
||||
{"read-batch", 0, POPT_ARG_STRING, &batch_name, OPT_READ_BATCH, 0, 0 },
|
||||
{"write-batch", 0, POPT_ARG_STRING, &batch_name, OPT_WRITE_BATCH, 0, 0 },
|
||||
{"only-write-batch", 0, POPT_ARG_STRING, &batch_name, OPT_ONLY_WRITE_BATCH, 0, 0 },
|
||||
{"files-from", 0, POPT_ARG_STRING, &files_from, 0, 0, 0 },
|
||||
{"from0", '0', POPT_ARG_NONE, &eol_nulls, 0, 0, 0},
|
||||
{"no-implied-dirs", 0, POPT_ARG_VAL, &implied_dirs, 0, 0, 0 },
|
||||
@@ -460,7 +465,6 @@ static struct poptOption long_options[] = {
|
||||
{"ipv6", '6', POPT_ARG_VAL, &default_af_hint, AF_INET6, 0, 0 },
|
||||
#endif
|
||||
/* All these options switch us into daemon-mode option-parsing. */
|
||||
{"address", 0, POPT_ARG_STRING, 0, OPT_DAEMON, 0, 0 },
|
||||
{"config", 0, POPT_ARG_STRING, 0, OPT_DAEMON, 0, 0 },
|
||||
{"daemon", 0, POPT_ARG_NONE, 0, OPT_DAEMON, 0, 0 },
|
||||
{"detach", 0, POPT_ARG_NONE, 0, OPT_DAEMON, 0, 0 },
|
||||
@@ -617,6 +621,35 @@ static int count_args(const char **argv)
|
||||
}
|
||||
|
||||
|
||||
static OFF_T parse_size_arg(const char *size_arg)
|
||||
{
|
||||
const char *arg;
|
||||
OFF_T size;
|
||||
|
||||
for (arg = size_arg; isdigit(*(uchar*)arg); arg++) {}
|
||||
if (*arg == '.')
|
||||
for (arg++; isdigit(*(uchar*)arg); arg++) {}
|
||||
switch (*arg) {
|
||||
case 'k': case 'K':
|
||||
size = atof(size_arg) * 1024;
|
||||
break;
|
||||
case 'm': case 'M':
|
||||
size = atof(size_arg) * 1024*1024;
|
||||
break;
|
||||
case 'g': case 'G':
|
||||
size = atof(size_arg) * 1024*1024*1024;
|
||||
break;
|
||||
case '\0':
|
||||
size = atof(size_arg);
|
||||
break;
|
||||
default:
|
||||
size = 0;
|
||||
break;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
static void create_refuse_error(int which)
|
||||
{
|
||||
/* The "which" value is the index + OPT_REFUSED_BASE. */
|
||||
@@ -791,33 +824,18 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
|
||||
write_batch = 1;
|
||||
break;
|
||||
|
||||
case OPT_ONLY_WRITE_BATCH:
|
||||
/* batch_name is already set */
|
||||
write_batch = -1;
|
||||
break;
|
||||
|
||||
case OPT_READ_BATCH:
|
||||
/* batch_name is already set */
|
||||
read_batch = 1;
|
||||
break;
|
||||
|
||||
case OPT_MAX_SIZE:
|
||||
for (arg = max_size_arg; isdigit(*(uchar*)arg); arg++) {}
|
||||
if (*arg == '.')
|
||||
for (arg++; isdigit(*(uchar*)arg); arg++) {}
|
||||
switch (*arg) {
|
||||
case 'k': case 'K':
|
||||
max_size = atof(max_size_arg) * 1024;
|
||||
break;
|
||||
case 'm': case 'M':
|
||||
max_size = atof(max_size_arg) * 1024*1024;
|
||||
break;
|
||||
case 'g': case 'G':
|
||||
max_size = atof(max_size_arg) * 1024*1024*1024;
|
||||
break;
|
||||
case '\0':
|
||||
max_size = atof(max_size_arg);
|
||||
break;
|
||||
default:
|
||||
max_size = 0;
|
||||
break;
|
||||
}
|
||||
if (max_size <= 0) {
|
||||
if ((max_size = parse_size_arg(max_size_arg)) <= 0) {
|
||||
snprintf(err_buf, sizeof err_buf,
|
||||
"--max-size value is invalid: %s\n",
|
||||
max_size_arg);
|
||||
@@ -825,11 +843,6 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
|
||||
}
|
||||
break;
|
||||
|
||||
case OPT_TIMEOUT:
|
||||
if (io_timeout && io_timeout < select_timeout)
|
||||
select_timeout = io_timeout;
|
||||
break;
|
||||
|
||||
case OPT_LINK_DEST:
|
||||
#ifdef HAVE_LINK
|
||||
link_dest = 1;
|
||||
@@ -901,7 +914,7 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
|
||||
"--write-batch and --read-batch can not be used together\n");
|
||||
return 0;
|
||||
}
|
||||
if (write_batch || read_batch) {
|
||||
if (write_batch > 0 || read_batch) {
|
||||
if (am_server) {
|
||||
rprintf(FINFO,
|
||||
"ignoring --%s-batch option sent to server\n",
|
||||
@@ -1078,10 +1091,10 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
|
||||
omit_dir_times = 1;
|
||||
|
||||
if (log_format) {
|
||||
if (strstr(log_format, "%i") != NULL)
|
||||
if (log_format_has(log_format, 'i'))
|
||||
log_format_has_i = 1;
|
||||
if (strstr(log_format, "%b") == NULL
|
||||
&& strstr(log_format, "%c") == NULL)
|
||||
if (!log_format_has(log_format, 'b')
|
||||
&& !log_format_has(log_format, 'c'))
|
||||
log_before_transfer = !am_server;
|
||||
} else if (itemize_changes) {
|
||||
log_format = "%i %n%L";
|
||||
@@ -1093,12 +1106,16 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
|
||||
&& !am_server)
|
||||
verbose = 1;
|
||||
|
||||
if (dry_run)
|
||||
do_xfers = 0;
|
||||
|
||||
set_io_timeout(io_timeout);
|
||||
|
||||
if (verbose && !log_format) {
|
||||
log_format = "%n%L";
|
||||
log_before_transfer = !am_server;
|
||||
}
|
||||
if (log_format_has_i
|
||||
|| (log_format && strstr(log_format, "%o") != NULL))
|
||||
if (log_format_has_i || log_format_has(log_format, 'o'))
|
||||
log_format_has_o_or_i = 1;
|
||||
|
||||
if (daemon_bwlimit && (!bwlimit || bwlimit > daemon_bwlimit))
|
||||
@@ -1215,7 +1232,7 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
|
||||
**/
|
||||
void server_options(char **args,int *argc)
|
||||
{
|
||||
static char argstr[50+MAX_BASIS_DIRS*2];
|
||||
static char argstr[64];
|
||||
int ac = *argc;
|
||||
char *arg;
|
||||
|
||||
@@ -1246,7 +1263,7 @@ void server_options(char **args,int *argc)
|
||||
argstr[x++] = 'b';
|
||||
if (update_only)
|
||||
argstr[x++] = 'u';
|
||||
if (dry_run)
|
||||
if (!do_xfers) /* NOT "dry_run"! */
|
||||
argstr[x++] = 'n';
|
||||
if (preserve_links)
|
||||
argstr[x++] = 'l';
|
||||
@@ -1374,6 +1391,8 @@ void server_options(char **args,int *argc)
|
||||
args[ac++] = "--delete-after";
|
||||
if (force_delete)
|
||||
args[ac++] = "--force";
|
||||
if (write_batch < 0)
|
||||
args[ac++] = "--only-write-batch=X";
|
||||
}
|
||||
|
||||
if (size_only)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Summary: A program for synchronizing files over a network.
|
||||
Name: rsync
|
||||
Version: 2.6.4pre4
|
||||
Version: 2.6.5
|
||||
Release: 1
|
||||
Group: Applications/Internet
|
||||
Source: ftp://rsync.samba.org/pub/rsync/rsync-%{version}.tar.gz
|
||||
|
||||
5
pipe.c
5
pipe.c
@@ -25,7 +25,6 @@ extern int am_sender;
|
||||
extern int am_server;
|
||||
extern int blocking_io;
|
||||
extern int orig_umask;
|
||||
extern int write_batch;
|
||||
extern int filesfrom_fd;
|
||||
|
||||
/**
|
||||
@@ -128,10 +127,6 @@ pid_t local_child(int argc, char **argv, int *f_in, int *f_out,
|
||||
am_sender = !am_sender;
|
||||
am_server = 1;
|
||||
|
||||
/* The server side never writes the batch, even if it
|
||||
* is local (it makes the logic easier elsewhere). */
|
||||
write_batch = 0;
|
||||
|
||||
if (!am_sender)
|
||||
filesfrom_fd = -1;
|
||||
|
||||
|
||||
46
receiver.c
46
receiver.c
@@ -21,7 +21,7 @@
|
||||
#include "rsync.h"
|
||||
|
||||
extern int verbose;
|
||||
extern int dry_run;
|
||||
extern int do_xfers;
|
||||
extern int am_daemon;
|
||||
extern int am_server;
|
||||
extern int do_progress;
|
||||
@@ -30,6 +30,7 @@ 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;
|
||||
@@ -53,7 +54,7 @@ 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;
|
||||
|
||||
#define SLOT_SIZE (16*1024) /* Desired size in bytes */
|
||||
@@ -62,6 +63,7 @@ extern struct filter_list_struct server_filter_list;
|
||||
|
||||
static uint32 **delayed_bits = NULL;
|
||||
static int delayed_slot_cnt = 0;
|
||||
static int phase = 0;
|
||||
|
||||
static void init_delayed_bits(int max_ndx)
|
||||
{
|
||||
@@ -266,7 +268,7 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (fd != -1 && write_file(fd, map, len) != (int)len)
|
||||
if (fd != -1 && map && write_file(fd, map, len) != (int)len)
|
||||
goto report_write_error;
|
||||
offset += len;
|
||||
}
|
||||
@@ -343,6 +345,22 @@ static void handle_delayed_updates(struct file_list *flist, char *local_name)
|
||||
}
|
||||
}
|
||||
|
||||
static int get_next_gen_i(int batch_gen_fd, int next_gen_i, int desired_i)
|
||||
{
|
||||
while (next_gen_i < desired_i) {
|
||||
if (next_gen_i >= 0) {
|
||||
rprintf(FINFO,
|
||||
"(No batched update for%s \"%s\")\n",
|
||||
phase ? " resend of" : "",
|
||||
safe_fname(f_name(the_file_list->files[next_gen_i])));
|
||||
}
|
||||
next_gen_i = read_int(batch_gen_fd);
|
||||
if (next_gen_i == -1)
|
||||
next_gen_i = the_file_list->count;
|
||||
}
|
||||
return next_gen_i;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* main routine for receiver process.
|
||||
@@ -365,7 +383,7 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
|
||||
int save_make_backups = make_backups;
|
||||
int itemizing = am_daemon ? daemon_log_format_has_i
|
||||
: !am_server && log_format_has_i;
|
||||
int phase = 0, max_phase = protocol_version >= 29 ? 2 : 1;
|
||||
int max_phase = protocol_version >= 29 ? 2 : 1;
|
||||
int i, recv_ok;
|
||||
|
||||
if (verbose > 2)
|
||||
@@ -385,8 +403,8 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
|
||||
i = read_int(f_in);
|
||||
if (i == -1) {
|
||||
if (read_batch) {
|
||||
if (next_gen_i != flist->count)
|
||||
while (read_int(batch_gen_fd) != -1) {}
|
||||
get_next_gen_i(batch_gen_fd, next_gen_i,
|
||||
flist->count);
|
||||
next_gen_i = -1;
|
||||
}
|
||||
if (++phase > max_phase)
|
||||
@@ -435,22 +453,24 @@ int recv_files(int f_in, struct file_list *flist, char *local_name)
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
}
|
||||
|
||||
if (dry_run) { /* log the transfer */
|
||||
if (!do_xfers) { /* log the transfer */
|
||||
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(file, &stats, iflags, NULL);
|
||||
if (!am_server)
|
||||
discard_receive_data(f_in, file->length);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (read_batch) {
|
||||
while (i > next_gen_i) {
|
||||
next_gen_i = read_int(batch_gen_fd);
|
||||
if (next_gen_i == -1)
|
||||
next_gen_i = flist->count;
|
||||
}
|
||||
next_gen_i = get_next_gen_i(batch_gen_fd, next_gen_i, i);
|
||||
if (i < next_gen_i) {
|
||||
rprintf(FINFO, "skipping update for \"%s\"\n",
|
||||
rprintf(FINFO, "(Skipping batched update for \"%s\")\n",
|
||||
safe_fname(fname));
|
||||
discard_receive_data(f_in, file->length);
|
||||
continue;
|
||||
|
||||
11
rsync.h
11
rsync.h
@@ -103,8 +103,8 @@
|
||||
#define IOERR_DEL_LIMIT (1<<2)
|
||||
|
||||
#define MAX_ARGS 1000
|
||||
|
||||
#define MAX_BASIS_DIRS 20
|
||||
#define MAX_SERVER_ARGS (MAX_BASIS_DIRS*2 + 100)
|
||||
|
||||
#define MPLEX_BASE 7
|
||||
|
||||
@@ -139,7 +139,6 @@
|
||||
#define DEL_TERSE (1<<3)
|
||||
|
||||
/* For use by the itemize_changes code */
|
||||
#define ITEM_DUMMY_BIT (1<<0)
|
||||
#define ITEM_REPORT_CHECKSUM (1<<1)
|
||||
#define ITEM_REPORT_SIZE (1<<2)
|
||||
#define ITEM_REPORT_TIME (1<<3)
|
||||
@@ -675,8 +674,12 @@ extern char *sys_errlist[];
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
#define SUPPORT_LINKS HAVE_READLINK
|
||||
#define SUPPORT_HARD_LINKS HAVE_LINK
|
||||
#ifdef HAVE_READLINK
|
||||
#define SUPPORT_LINKS 1
|
||||
#endif
|
||||
#ifdef HAVE_LINK
|
||||
#define SUPPORT_HARD_LINKS 1
|
||||
#endif
|
||||
|
||||
#define SIGNAL_CAST (RETSIGTYPE (*)())
|
||||
|
||||
|
||||
257
rsync.yo
257
rsync.yo
@@ -1,11 +1,11 @@
|
||||
mailto(rsync-bugs@samba.org)
|
||||
manpage(rsync)(1)(28 Mar 2005)()()
|
||||
manpage(rsync)(1)(1 Jun 2005)()()
|
||||
manpagename(rsync)(faster, flexible replacement for rcp)
|
||||
manpagesynopsis()
|
||||
|
||||
rsync [OPTION]... SRC [SRC]... [USER@]HOST:DEST
|
||||
|
||||
rsync [OPTION]... [USER@]HOST:SRC DEST
|
||||
rsync [OPTION]... [USER@]HOST:SRC [DEST]
|
||||
|
||||
rsync [OPTION]... SRC [SRC]... DEST
|
||||
|
||||
@@ -38,47 +38,39 @@ itemize(
|
||||
it() can use any transparent remote shell, including ssh or rsh
|
||||
it() does not require root privileges
|
||||
it() pipelining of file transfers to minimize latency costs
|
||||
it() support for anonymous or authenticated rsync servers (ideal for
|
||||
it() support for anonymous or authenticated rsync daemons (ideal for
|
||||
mirroring)
|
||||
)
|
||||
|
||||
manpagesection(GENERAL)
|
||||
|
||||
There are eight different ways of using rsync. They are:
|
||||
Rsync copies files either to or from a remote host, or locally on the
|
||||
current host (it does not support copying files between two remote hosts).
|
||||
|
||||
itemize(
|
||||
it() for copying local files. This is invoked when neither
|
||||
source nor destination path contains a : separator
|
||||
it() for copying from the local machine to a remote machine using
|
||||
a remote shell program as the transport (such as ssh or
|
||||
rsh). This is invoked when the destination path contains a
|
||||
single : separator.
|
||||
it() for copying from a remote machine to the local machine
|
||||
using a remote shell program. This is invoked when the source
|
||||
contains a : separator.
|
||||
it() for copying from a remote rsync server to the local
|
||||
machine. This is invoked when the source path contains a ::
|
||||
separator or an rsync:// URL.
|
||||
it() for copying from the local machine to a remote rsync
|
||||
server. This is invoked when the destination path contains a ::
|
||||
separator or an rsync:// URL.
|
||||
it() for copying from a remote machine using a remote shell
|
||||
program as the transport, using rsync server on the remote
|
||||
machine. This is invoked when the source path contains a ::
|
||||
separator and the bf(--rsh=COMMAND) (aka "bf(-e COMMAND)") option is
|
||||
also provided.
|
||||
it() for copying from the local machine to a remote machine
|
||||
using a remote shell program as the transport, using rsync
|
||||
server on the remote machine. This is invoked when the
|
||||
destination path contains a :: separator and the
|
||||
bf(--rsh=COMMAND) option is also provided.
|
||||
it() for listing files on a remote machine. This is done the
|
||||
same way as rsync transfers except that you leave off the
|
||||
local destination.
|
||||
)
|
||||
There are two different ways for rsync to contact a remote system: using a
|
||||
remote-shell program as the transport (such as ssh or rsh) or contacting an
|
||||
rsync daemon directly via TCP. The remote-shell transport is used whenever
|
||||
the source or destination path contains a single colon (:) separator after
|
||||
a host specification. Contacting an rsync daemon directly happens when the
|
||||
source or destination path contains a double colon (::) separator after a
|
||||
host specification, OR when an rsync:// URL is specified.
|
||||
|
||||
Note that in all cases (other than listing) at least one of the source
|
||||
and destination paths must be local.
|
||||
As a special case, if a remote source is specified without a destination,
|
||||
the remote files are listed in an output format similar to "ls -l".
|
||||
|
||||
As expected, if neither the source or destination path specify a remote
|
||||
host, the copy occurs locally (see also the bf(--list-only) option).
|
||||
|
||||
Finally, it is possible to use a remote-shell transport to contact a remote
|
||||
host and then to spawn a single-use rsync daemon. This allows the use of
|
||||
some of the daemon features (such as named modules) without having to run a
|
||||
daemon as a service. To achieve this, invoke rsync with an explicit
|
||||
bf(--rsh=COMMAND) (aka "bf(-e COMMAND)") option combined with either the
|
||||
source or destination path specified as an rsync daemon (i.e. either a ::
|
||||
separator or an rsync:// URL). In this case, rsync contacts the remote
|
||||
host specified using the specified remote shell, and then starts a
|
||||
single-use rsync daemon to deal with that copy request. See the section
|
||||
"CONNECTING TO AN RSYNC DAEMON OVER A REMOTE SHELL PROGRAM" below.
|
||||
|
||||
manpagesection(SETUP)
|
||||
|
||||
@@ -139,6 +131,15 @@ tt(rsync -av /src/foo /dest)nl()
|
||||
tt(rsync -av /src/foo/ /dest/foo)nl()
|
||||
)
|
||||
|
||||
Note also that host and module references don't require a trailing slash to
|
||||
copy the contents of the default directory. For example, both of these
|
||||
copy the remote directory's contents into "/dest":
|
||||
|
||||
quote(
|
||||
tt(rsync -av host: /dest)nl()
|
||||
tt(rsync -av host::module /dest)nl()
|
||||
)
|
||||
|
||||
You can also use rsync in local-only mode, where both the source and
|
||||
destination don't have a ':' in the name. In this case it behaves like
|
||||
an improved copy command.
|
||||
@@ -178,10 +179,10 @@ tt(rsync -av host:file?name?with?spaces /dest)nl()
|
||||
This latter example assumes that your shell passes through unmatched
|
||||
wildcards. If it complains about "no match", put the name in quotes.
|
||||
|
||||
manpagesection(CONNECTING TO AN RSYNC SERVER)
|
||||
manpagesection(CONNECTING TO AN RSYNC DAEMON)
|
||||
|
||||
It is also possible to use rsync without a remote shell as the
|
||||
transport. In this case you will connect to a remote rsync server
|
||||
transport. In this case you will connect to a remote rsync daemon
|
||||
running on TCP port 873.
|
||||
|
||||
You may establish the connection via a web proxy by setting the
|
||||
@@ -195,15 +196,15 @@ that:
|
||||
itemize(
|
||||
it() you either use a double colon :: instead of a single colon to
|
||||
separate the hostname from the path, or you use an rsync:// URL.
|
||||
it() the remote server may print a message of the day when you
|
||||
it() the remote daemon may print a message of the day when you
|
||||
connect.
|
||||
it() if you specify no path name on the remote server then the
|
||||
list of accessible paths on the server will be shown.
|
||||
it() if you specify no path name on the remote daemon then the
|
||||
list of accessible paths on the daemon will be shown.
|
||||
it() if you specify no local destination then a listing of the
|
||||
specified files on the remote server is provided.
|
||||
specified files on the remote daemon is provided.
|
||||
)
|
||||
|
||||
Some paths on the remote server may require authentication. If so then
|
||||
Some paths on the remote daemon may require authentication. If so then
|
||||
you will receive a password prompt when you connect. You can avoid the
|
||||
password prompt by setting the environment variable RSYNC_PASSWORD to
|
||||
the password you want to use or using the bf(--password-file) option. This
|
||||
@@ -212,24 +213,24 @@ may be useful when scripting rsync.
|
||||
WARNING: On some systems environment variables are visible to all
|
||||
users. On those systems using bf(--password-file) is recommended.
|
||||
|
||||
manpagesection(CONNECTING TO AN RSYNC SERVER OVER A REMOTE SHELL PROGRAM)
|
||||
manpagesection(CONNECTING TO AN RSYNC DAEMON OVER A REMOTE SHELL PROGRAM)
|
||||
|
||||
It is sometimes useful to be able to set up file transfers using rsync
|
||||
server capabilities on the remote machine, while still using ssh or
|
||||
daemon capabilities on the remote machine, while still using ssh or
|
||||
rsh for transport. This is especially useful when you want to connect
|
||||
to a remote machine via ssh (for encryption or to get through a
|
||||
firewall), but you still want to have access to the rsync server
|
||||
features (see RUNNING AN RSYNC SERVER OVER A REMOTE SHELL PROGRAM,
|
||||
firewall), but you still want to have access to the rsync daemon
|
||||
features (see RUNNING AN RSYNC DAEMON OVER A REMOTE SHELL PROGRAM,
|
||||
below).
|
||||
|
||||
From the user's perspective, using rsync in this way is the same as
|
||||
using it to connect to an rsync server, except that you must
|
||||
using it to connect to an rsync daemon, except that you must
|
||||
explicitly set the remote shell program on the command line with
|
||||
bf(--rsh=COMMAND). (Setting RSYNC_RSH in the environment will not turn on
|
||||
this functionality.)
|
||||
|
||||
In order to distinguish between the remote-shell user and the rsync
|
||||
server user, you can use '-l user' on your remote-shell command:
|
||||
daemon user, you can use '-l user' on your remote-shell command:
|
||||
|
||||
verb( rsync -av --rsh="ssh -l ssh-user" \
|
||||
rsync-user@host::module[/path] local-path)
|
||||
@@ -237,26 +238,26 @@ verb( rsync -av --rsh="ssh -l ssh-user" \
|
||||
The "ssh-user" will be used at the ssh level; the "rsync-user" will be
|
||||
used to check against the rsyncd.conf on the remote host.
|
||||
|
||||
manpagesection(RUNNING AN RSYNC SERVER)
|
||||
manpagesection(RUNNING AN RSYNC DAEMON)
|
||||
|
||||
An rsync server is configured using a configuration file. Please see the
|
||||
An rsync daemon is configured using a configuration file. Please see the
|
||||
rsyncd.conf(5) man page for more information. By default the configuration
|
||||
file is called /etc/rsyncd.conf, unless rsync is running over a remote
|
||||
shell program and is not running as root; in that case, the default name
|
||||
is rsyncd.conf in the current directory on the remote computer
|
||||
(typically $HOME).
|
||||
|
||||
manpagesection(RUNNING AN RSYNC SERVER OVER A REMOTE SHELL PROGRAM)
|
||||
manpagesection(RUNNING AN RSYNC DAEMON OVER A REMOTE SHELL PROGRAM)
|
||||
|
||||
See the rsyncd.conf(5) man page for full information on the rsync
|
||||
server configuration file.
|
||||
daemon configuration file.
|
||||
|
||||
Several configuration options will not be available unless the remote
|
||||
user is root (e.g. chroot, setuid/setgid, etc.). There is no need to
|
||||
configure inetd or the services map to include the rsync server port
|
||||
if you run an rsync server only via a remote shell program.
|
||||
configure inetd or the services map to include the rsync daemon port
|
||||
if you run an rsync daemon only via a remote shell program.
|
||||
|
||||
To run an rsync server out of a single-use ssh key, see this section
|
||||
To run an rsync daemon out of a single-use ssh key, see this section
|
||||
in the rsyncd.conf(5) man page.
|
||||
|
||||
manpagesection(EXAMPLES)
|
||||
@@ -365,8 +366,8 @@ to the detailed description below for a complete description. verb(
|
||||
--include=PATTERN don't exclude files matching PATTERN
|
||||
--include-from=FILE read include patterns from FILE
|
||||
--files-from=FILE read list of source-file names from FILE
|
||||
-0, --from0 all *from file lists are delimited by nulls
|
||||
--version print version number
|
||||
-0, --from0 all *from/filter files are delimited by 0s
|
||||
--address=ADDRESS bind address for outgoing socket to daemon
|
||||
--port=PORT specify double-colon alternate port number
|
||||
--blocking-io use blocking I/O for the remote shell
|
||||
--no-blocking-io turn off blocking I/O when it is default
|
||||
@@ -374,16 +375,18 @@ to the detailed description below for a complete description. verb(
|
||||
--progress show progress during transfer
|
||||
-P same as --partial --progress
|
||||
-i, --itemize-changes output a change-summary for all updates
|
||||
--log-format=FORMAT log file-transfers using specified format
|
||||
--log-format=FORMAT output filenames using the specified format
|
||||
--password-file=FILE read password from FILE
|
||||
--list-only list the files instead of copying them
|
||||
--bwlimit=KBPS limit I/O bandwidth; KBytes per second
|
||||
--write-batch=FILE write a batched update to FILE
|
||||
--only-write-batch=FILE like --write-batch but w/o updating dest
|
||||
--read-batch=FILE read a batched update from FILE
|
||||
--protocol=NUM force an older protocol version to be used
|
||||
--checksum-seed=NUM set block/file checksum seed (advanced)
|
||||
-4, --ipv4 prefer IPv4
|
||||
-6, --ipv6 prefer IPv6
|
||||
--version print version number
|
||||
-h, --help show this help screen)
|
||||
|
||||
Rsync can also be run as a daemon, in which case the following options are
|
||||
@@ -423,7 +426,7 @@ you are debugging rsync.
|
||||
|
||||
Note that the names of the transferred files that are output are done using
|
||||
a default bf(--log-format) of "%n%L", which tells you just the name of the
|
||||
file and, if the item is a symlink, where it points. At the single bf(-v)
|
||||
file and, if the item is a link, where it points. At the single bf(-v)
|
||||
level of verbosity, this does not mention when a file gets its attributes
|
||||
changed. If you ask for an itemized list of changed attributes (either
|
||||
bf(--itemize-changes) or adding "%i" to the bf(--log-format) setting), the
|
||||
@@ -620,9 +623,10 @@ default.
|
||||
dit(bf(-p, --perms)) This option causes rsync to set the destination
|
||||
permissions to be the same as the source permissions.
|
||||
|
||||
Without this option, each new file gets its permissions set based on the
|
||||
source file's permissions and the umask at the receiving end, while all
|
||||
other files (including updated files) retain their existing permissions
|
||||
Without this option, all existing files (including updated files) retain
|
||||
their existing permissions, while each new file gets its permissions set
|
||||
based on the source file's permissions, but masked by the receiving end's
|
||||
umask setting
|
||||
(which is the same behavior as other file-copy utilities, such as cp).
|
||||
|
||||
dit(bf(-o, --owner)) This option causes rsync to set the owner of the
|
||||
@@ -769,11 +773,11 @@ remote copies of rsync. Typically, rsync is configured to use ssh by
|
||||
default, but you may prefer to use rsh on a local network.
|
||||
|
||||
If this option is used with bf([user@]host::module/path), then the
|
||||
remote shell em(COMMAND) will be used to run an rsync server on the
|
||||
remote shell em(COMMAND) will be used to run an rsync daemon on the
|
||||
remote host, and all data will be transmitted through that remote
|
||||
shell connection, rather than through a direct socket connection to a
|
||||
running rsync server on the remote host. See the section "CONNECTING
|
||||
TO AN RSYNC SERVER OVER A REMOTE SHELL PROGRAM" above.
|
||||
running rsync daemon on the remote host. See the section "CONNECTING
|
||||
TO AN RSYNC DAEMON OVER A REMOTE SHELL PROGRAM" above.
|
||||
|
||||
Command-line arguments are permitted in COMMAND provided that COMMAND is
|
||||
presented to rsync as a single argument. For example:
|
||||
@@ -905,9 +909,14 @@ command:
|
||||
quote(tt( rsync -a --files-from=/tmp/foo /usr remote:/backup))
|
||||
|
||||
If /tmp/foo contains the string "bin" (or even "/bin"), the /usr/bin
|
||||
directory will be created as /backup/bin on the remote host (but the
|
||||
contents of the /usr/bin dir would not be sent unless you specified bf(-r)
|
||||
or the names were explicitly listed in /tmp/foo). Also keep in mind
|
||||
directory will be created as /backup/bin on the remote host. If it
|
||||
contains "bin/" (note the trailing slash), the immediate contents of
|
||||
the directory would also be sent (without needing to be explicitly
|
||||
mentioned in the file -- this began in version 2.6.4). In both cases,
|
||||
if the bf(-r) option was enabled, that dir's entire hierarchy would
|
||||
also be transferred (keep in mind that bf(-r) needs to be specified
|
||||
explicitly with bf(--files-from), since it is not implied by bf(-a)).
|
||||
Also note
|
||||
that the effect of the (enabled by default) bf(--relative) option is to
|
||||
duplicate only the path info that is read from the file -- it does not
|
||||
force the duplication of the source-spec path (/usr in this case).
|
||||
@@ -923,7 +932,7 @@ quote(tt( rsync -a --files-from=:/path/file-list src:/ /tmp/copy))
|
||||
This would copy all the files specified in the /path/file-list file that
|
||||
was located on the remote "src" host.
|
||||
|
||||
dit(bf(-0, --from0)) This tells rsync that the filenames it reads from a
|
||||
dit(bf(-0, --from0)) This tells rsync that the rules/filenames it reads from a
|
||||
file are terminated by a null ('\0') character, not a NL, CR, or CR+LF.
|
||||
This affects bf(--exclude-from), bf(--include-from), bf(--files-from), and any
|
||||
merged files specified in a bf(--filter) rule.
|
||||
@@ -1032,6 +1041,11 @@ dit(bf(--timeout=TIMEOUT)) This option allows you to set a maximum I/O
|
||||
timeout in seconds. If no data is transferred for the specified time
|
||||
then rsync will exit. The default is 0, which means no timeout.
|
||||
|
||||
dit(bf(--address)) By default rsync will bind to the wildcard address when
|
||||
connecting to an rsync daemon. The bf(--address) option allows you to
|
||||
specify a specific IP address (or hostname) to bind to. See also this
|
||||
option in the bf(--daemon) mode section.
|
||||
|
||||
dit(bf(--port=PORT)) This specifies an alternate TCP port number to use
|
||||
rather than the default of 873. This is only needed if you are using the
|
||||
double-colon (::) syntax to connect with an rsync daemon (since the URL
|
||||
@@ -1064,7 +1078,7 @@ quote(itemize(
|
||||
(sent).
|
||||
it() A bf(>) means that a file is being transferred to the local host
|
||||
(received).
|
||||
it() A bf(c) means that a local change/creation is occuring for the item
|
||||
it() A bf(c) means that a local change/creation is occurring for the item
|
||||
(such as the creation of a directory or the changing of a symlink, etc.).
|
||||
it() A bf(h) means that the item is a hard-link to another item (requires
|
||||
bf(--hard-links)).
|
||||
@@ -1073,33 +1087,33 @@ quote(itemize(
|
||||
))
|
||||
|
||||
The file-types that replace the bf(X) are: bf(f) for a file, a bf(d) for a
|
||||
dir, an bf(L) for a symlink, and a bf(D) for a device.
|
||||
directory, an bf(L) for a symlink, and a bf(D) for a device.
|
||||
|
||||
The other letters in the string above are the actual letters that
|
||||
will be output if the associated attribute for the item is being updated or
|
||||
a "." for no change. Three exceptions to this are: (1) a newly created
|
||||
item replaces each letter with a "+", (2) an identical item replaces each
|
||||
letter with a space, and (3) an unknown attribute replaces each letter with
|
||||
a "?" (this happens when talking to an older rsync).
|
||||
item replaces each letter with a "+", (2) an identical item replaces the
|
||||
dots with spaces, and (3) an unknown attribute replaces each letter with
|
||||
a "?" (this can happen when talking to an older rsync).
|
||||
|
||||
The attribute that is associated with each letter is as follows:
|
||||
|
||||
quote(itemize(
|
||||
it() A bf(c) means the checksum of the file is different and will be
|
||||
updated by the file transfer (requries bf(--checksum)).
|
||||
updated by the file transfer (requires bf(--checksum)).
|
||||
it() A bf(s) means the size of the file is different and will be updated
|
||||
by the file transfer.
|
||||
it() A bf(t) means the modification time is different and is being updated
|
||||
to the server's value (requires bf(--times)). An alternate value of bf(T)
|
||||
to the sender's value (requires bf(--times)). An alternate value of bf(T)
|
||||
means that the time will be set to the transfer time, which happens
|
||||
anytime a symlink is transferred, or when a file or device is transferred
|
||||
without bf(--times).
|
||||
it() A bf(p) means the permissions are different and are being updated to
|
||||
the server's value (requires bf(--perms)).
|
||||
the sender's value (requires bf(--perms)).
|
||||
it() An bf(o) means the owner is different and is being updated to the
|
||||
server's value (requires bf(--owner) and root privileges).
|
||||
sender's value (requires bf(--owner) and root privileges).
|
||||
it() A bf(g) means the group is different and is being updated to the
|
||||
server's value (requires bf(--group) and the authority to set the group).
|
||||
sender's value (requires bf(--group) and the authority to set the group).
|
||||
it() The bf(a) is reserved for a future enhanced version that supports
|
||||
extended file attributes, such as ACLs.
|
||||
))
|
||||
@@ -1120,7 +1134,7 @@ Specifying this option will mention each file, dir, etc. that gets updated
|
||||
in a significant way (a transferred file, a recreated symlink/device, or a
|
||||
touched directory) unless the itemized-changes escape (%i) is included in
|
||||
the string, in which case the logging of names increases to mention any
|
||||
item that is updated in any way (as long as the receiving side is version
|
||||
item that is changed in any way (as long as the receiving side is at least
|
||||
2.6.4). See the bf(--itemized-changes) option for a description of the
|
||||
output of "%i".
|
||||
|
||||
@@ -1188,7 +1202,7 @@ option does not look for this environment value is (1) when bf(--inplace) was
|
||||
specified (since bf(--inplace) conflicts with bf(--partial-dir)), or (2) when
|
||||
bf(--delay-updates) was specified (see below).
|
||||
|
||||
For the purposes of the server-config's "refuse options" setting,
|
||||
For the purposes of the daemon-config's "refuse options" setting,
|
||||
bf(--partial-dir) does em(not) imply bf(--partial). This is so that a
|
||||
refusal of the bf(--partial) option can be used to disallow the overwriting
|
||||
of destination files with a partial transfer, while still allowing the
|
||||
@@ -1202,7 +1216,7 @@ atomic. By default the files are placed into a directory named ".~tmp~" in
|
||||
each file's destination directory, but you can override this by specifying
|
||||
the bf(--partial-dir) option. (Note that RSYNC_PARTIAL_DIR has no effect
|
||||
on this value, nor is bf(--partial-dir) considered to be implied for the
|
||||
purposes of the server-config's "refuse options" setting.)
|
||||
purposes of the daemon-config's "refuse options" setting.)
|
||||
Conflicts with bf(--inplace).
|
||||
|
||||
This option uses more memory on the receiving side (one bit per file
|
||||
@@ -1246,8 +1260,8 @@ purpose is to make it much easier to specify these two options for a long
|
||||
transfer that may be interrupted.
|
||||
|
||||
dit(bf(--password-file)) This option allows you to provide a password
|
||||
in a file for accessing a remote rsync server. Note that this option
|
||||
is only useful when accessing an rsync server using the built in
|
||||
in a file for accessing a remote rsync daemon. Note that this option
|
||||
is only useful when accessing an rsync daemon using the built in
|
||||
transport, not when using a remote shell as the transport. The file
|
||||
must not be world readable. It should contain just the password as a
|
||||
single line.
|
||||
@@ -1255,9 +1269,11 @@ single line.
|
||||
dit(bf(--list-only)) This option will cause the source files to be listed
|
||||
instead of transferred. This option is inferred if there is no destination
|
||||
specified, so you don't usually need to use it explicitly. However, it can
|
||||
come in handy for a power user that wants to avoid the "bf(-r --exclude='/*/*')"
|
||||
come in handy for a user that wants to avoid the "bf(-r --exclude='/*/*')"
|
||||
options that rsync might use as a compatibility kluge when generating a
|
||||
non-recursive listing.
|
||||
non-recursive listing, or to list the files that are involved in a local
|
||||
copy (since the destination path is not optional for a local copy, you
|
||||
must specify this option explicitly and still include a destination).
|
||||
|
||||
dit(bf(--bwlimit=KBPS)) This option allows you to specify a maximum
|
||||
transfer rate in kilobytes per second. This option is most effective when
|
||||
@@ -1269,7 +1285,24 @@ of zero specifies no limit.
|
||||
|
||||
dit(bf(--write-batch=FILE)) Record a file that can later be applied to
|
||||
another identical destination with bf(--read-batch). See the "BATCH MODE"
|
||||
section for details.
|
||||
section for details, and also the bf(--only-write-batch) option.
|
||||
|
||||
dit(bf(--only-write-batch=FILE)) Works like bf(--write-batch), except that
|
||||
no updates are made on the destination system when creating the batch.
|
||||
This lets you transport the changes to the destination system via some
|
||||
other means and then apply the changes via bf(--read-batch).
|
||||
|
||||
Note that you can feel free to write the batch directly to some portable
|
||||
media: if this media fills to capacity before the end of the transfer, you
|
||||
can just apply that partial transfer to the destination and repeat the
|
||||
whole process to get the rest of the changes (as long as you don't mind a
|
||||
partially updated destination system while the multi-update cycle is
|
||||
happening).
|
||||
|
||||
Also note that you only save bandwidth when pushing changes to a remote
|
||||
system because this allows the batched data to be diverted from the sender
|
||||
into the batch file without having to flow over the wire to the receiver
|
||||
(when pulling, the sender is remote, and thus can't write the batch).
|
||||
|
||||
dit(bf(--read-batch=FILE)) Apply all of the changes stored in FILE, a
|
||||
file previously generated by bf(--write-batch).
|
||||
@@ -1280,9 +1313,9 @@ dit(bf(--protocol=NUM)) Force an older protocol version to be used. This
|
||||
is useful for creating a batch file that is compatible with an older
|
||||
version of rsync. For instance, if rsync 2.6.4 is being used with the
|
||||
bf(--write-batch) option, but rsync 2.6.3 is what will be used to run the
|
||||
bf(--read-batch) option, you should use "--protocol=28" (when creating the
|
||||
batch file) to force the older protocol version to be used in the batch
|
||||
file (assuming you can't upgrade the rsync on the reading system to 2.6.4).
|
||||
bf(--read-batch) option, you should use "--protocol=28" when creating the
|
||||
batch file to force the older protocol version to be used in the batch
|
||||
file (assuming you can't upgrade the rsync on the reading system).
|
||||
|
||||
dit(bf(-4, --ipv4) or bf(-6, --ipv6)) Tells rsync to prefer IPv4/IPv6
|
||||
when creating sockets. This only affects sockets that rsync has direct
|
||||
@@ -1316,12 +1349,11 @@ become a background daemon. The daemon will read the config file
|
||||
requests accordingly. See the rsyncd.conf(5) man page for more
|
||||
details.
|
||||
|
||||
dit(bf(--address)) By default rsync will bind to the wildcard address
|
||||
when run as a daemon with the bf(--daemon) option or when connecting to a
|
||||
rsync server. The bf(--address) option allows you to specify a specific IP
|
||||
address (or hostname) to bind to. This makes virtual hosting possible
|
||||
in conjunction with the bf(--config) option. See also the "address" global
|
||||
option in the rsyncd.conf manpage.
|
||||
dit(bf(--address)) By default rsync will bind to the wildcard address when
|
||||
run as a daemon with the bf(--daemon) option. The bf(--address) option
|
||||
allows you to specify a specific IP address (or hostname) to bind to. This
|
||||
makes virtual hosting possible in conjunction with the bf(--config) option.
|
||||
See also the "address" global option in the rsyncd.conf manpage.
|
||||
|
||||
dit(bf(--bwlimit=KBPS)) This option allows you to specify a maximum
|
||||
transfer rate in kilobytes per second for the data the daemon sends.
|
||||
@@ -1567,7 +1599,7 @@ itemize(
|
||||
default to having that modifier set. For instance, "merge,-/ .excl" would
|
||||
treat the contents of .excl as absolute-path excludes,
|
||||
while "dir-merge,s .filt" and ":sC" would each make all their
|
||||
per-directory rules apply only on the server side.
|
||||
per-directory rules apply only on the sending side.
|
||||
)
|
||||
|
||||
The following modifiers are accepted after a "+" or "-":
|
||||
@@ -1588,7 +1620,7 @@ itemize(
|
||||
being transferred. The default is for a rule to affect both sides
|
||||
unless bf(--delete-excluded) was specified, in which case default rules
|
||||
become sender-side only. See also the hide (H) and show (S) rules,
|
||||
which are an alternate way to specify server-side includes/excludes.
|
||||
which are an alternate way to specify sending-side includes/excludes.
|
||||
it() An bf(r) is used to indicate that the rule applies to the receiving
|
||||
side. When a rule affects the receiving side, it prevents files from
|
||||
being deleted. See the bf(s) modifier for more info. See also the
|
||||
@@ -1922,12 +1954,31 @@ ensure the rsync module they copy does not include symbolic links to
|
||||
bf(/etc/passwd) in the public section of the site. Using
|
||||
bf(--copy-unsafe-links) will cause any links to be copied as the file
|
||||
they point to on the destination. Using bf(--safe-links) will cause
|
||||
unsafe links to be omitted altogether.
|
||||
unsafe links to be omitted altogether. (Note that you must specify
|
||||
bf(--links) for bf(--safe-links) to have any effect.)
|
||||
|
||||
Symbolic links are considered unsafe if they are absolute symlinks
|
||||
(start with bf(/)), empty, or if they contain enough bf("..")
|
||||
components to ascend from the directory being copied.
|
||||
|
||||
Here's a summary of how the symlink options are interpreted. The list is
|
||||
in order of precedence, so if your combination of options isn't mentioned,
|
||||
use the first line that is a complete subset of your options:
|
||||
|
||||
dit(bf(--copy-links)) Turn all symlinks into normal files (leaving no
|
||||
symlinks for any other options to affect).
|
||||
|
||||
dit(bf(--links --copy-unsafe-links)) Turn all unsafe symlinks into files
|
||||
and duplicate all safe symlinks.
|
||||
|
||||
dit(bf(--copy-unsafe-links)) Turn all unsafe symlinks into files, noisily
|
||||
skip all safe symlinks.
|
||||
|
||||
dit(bf(--links --safe-links)) Duplicate safe symlinks and skip unsafe
|
||||
ones.
|
||||
|
||||
dit(bf(--links)) Duplicate all symlinks.
|
||||
|
||||
manpagediagnostics()
|
||||
|
||||
rsync occasionally produces error messages that may seem a little
|
||||
@@ -1997,7 +2048,7 @@ password allows you to run authenticated rsync connections to an rsync
|
||||
daemon without user intervention. Note that this does not supply a
|
||||
password to a shell transport such as ssh.
|
||||
dit(bf(USER) or bf(LOGNAME)) The USER or LOGNAME environment variables
|
||||
are used to determine the default username sent to an rsync server.
|
||||
are used to determine the default username sent to an rsync daemon.
|
||||
If neither is set, the username defaults to "nobody".
|
||||
dit(bf(HOME)) The HOME environment variable is used to find the user's
|
||||
default .cvsignore file.
|
||||
@@ -2027,6 +2078,10 @@ see also the comments on the bf(--delete) option
|
||||
Please report bugs! See the website at
|
||||
url(http://rsync.samba.org/)(http://rsync.samba.org/)
|
||||
|
||||
manpagesection(VERSION)
|
||||
|
||||
This man page is current for version 2.6.5 of rsync.
|
||||
|
||||
manpagesection(CREDITS)
|
||||
|
||||
rsync is distributed under the GNU public license. See the file
|
||||
|
||||
106
rsyncd.conf.yo
106
rsyncd.conf.yo
@@ -1,6 +1,6 @@
|
||||
mailto(rsync-bugs@samba.org)
|
||||
manpage(rsyncd.conf)(5)(28 Mar 2005)()()
|
||||
manpagename(rsyncd.conf)(configuration file for rsync server)
|
||||
manpage(rsyncd.conf)(5)(1 Jun 2005)()()
|
||||
manpagename(rsyncd.conf)(configuration file for rsync in daemon mode)
|
||||
manpagesynopsis()
|
||||
|
||||
rsyncd.conf
|
||||
@@ -8,7 +8,7 @@ rsyncd.conf
|
||||
manpagedescription()
|
||||
|
||||
The rsyncd.conf file is the runtime configuration file for rsync when
|
||||
run as an rsync server.
|
||||
run as an rsync daemon.
|
||||
|
||||
The rsyncd.conf file controls authentication, access, logging and
|
||||
available modules.
|
||||
@@ -53,7 +53,7 @@ You can launch it either via inetd, as a stand-alone daemon, or from
|
||||
an rsync client via a remote shell. If run as a stand-alone daemon then
|
||||
just run the command "bf(rsync --daemon)" from a suitable startup script.
|
||||
If run from an rsync client via a remote shell (by specifying both the
|
||||
bf(--rsh) (bf(-e)) option and server mode with "::" or "rsync://"), the bf(--daemon)
|
||||
bf(--rsh) (bf(-e)) option and daemon mode with "::" or "rsync://"), the bf(--daemon)
|
||||
option is automatically passed to the remote side.
|
||||
|
||||
When run via inetd you should add a line like this to /etc/services:
|
||||
@@ -68,7 +68,7 @@ Replace "/usr/bin/rsync" with the path to where you have rsync installed on
|
||||
your system. You will then need to send inetd a HUP signal to tell it to
|
||||
reread its config file.
|
||||
|
||||
Note that you should not send the rsync server a HUP signal to force
|
||||
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.
|
||||
|
||||
@@ -90,19 +90,30 @@ 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.
|
||||
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 server. You may use any standard syslog facility name which is
|
||||
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.
|
||||
|
||||
dit(bf(address)) You can override the default IP address the daemon
|
||||
will listen on by specifying this value. This is ignored if the daemon is
|
||||
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
|
||||
@@ -126,11 +137,11 @@ dit(bf(comment)) The "comment" option specifies a description string
|
||||
that is displayed next to the module name when clients obtain a list
|
||||
of available modules. The default is no comment.
|
||||
|
||||
dit(bf(path)) The "path" option specifies the directory in the servers
|
||||
dit(bf(path)) The "path" option specifies the directory in the daemon's
|
||||
filesystem to make available in this module. You must specify this option
|
||||
for each module in tt(rsyncd.conf).
|
||||
|
||||
dit(bf(use chroot)) If "use chroot" is true, the rsync server will chroot
|
||||
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,
|
||||
@@ -157,7 +168,7 @@ 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 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 server is running
|
||||
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
|
||||
directory and all its contents combining the rule "/some/dir/" with the
|
||||
rule "/some/dir/**" just to be sure that rsync will not allow deeper
|
||||
@@ -165,14 +176,6 @@ access to some of the excluded files inside the directory (rsync tries to
|
||||
do this automatically, but you might as well specify both to be extra
|
||||
sure).
|
||||
|
||||
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.
|
||||
|
||||
dit(bf(address)) You can override the default IP address the daemon
|
||||
will listen on by specifying this value. This is ignored if the daemon is
|
||||
being run by inetd, and is superseded by the bf(--address) command-line option.
|
||||
|
||||
dit(bf(max connections)) The "max connections" option allows you to
|
||||
specify the maximum number of simultaneous connections you will allow.
|
||||
Any clients connecting when the maximum has been reached will receive a
|
||||
@@ -185,7 +188,7 @@ generate (since the information goes into the log file). The default is 1,
|
||||
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 server uses record
|
||||
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.
|
||||
The default is tt(/var/run/rsyncd.lock).
|
||||
@@ -193,13 +196,13 @@ The default is tt(/var/run/rsyncd.lock).
|
||||
dit(bf(read only)) The "read only" option determines whether clients
|
||||
will be able to upload files or not. If "read only" is true then any
|
||||
attempted uploads will fail. If "read only" is false then uploads will
|
||||
be possible if file permissions on the server allow them. The default
|
||||
be possible if file permissions on the daemon side allow them. The default
|
||||
is for all modules to be read only.
|
||||
|
||||
dit(bf(write only)) The "write only" option determines whether clients
|
||||
will be able to download files or not. If "write only" is true then any
|
||||
attempted downloads will fail. If "write only" is false then downloads
|
||||
will be possible if file permissions on the server allow them. The
|
||||
will be possible if file permissions on the daemon side allow them. The
|
||||
default is for this option to be disabled.
|
||||
|
||||
dit(bf(list)) The "list" option determines if this module should be
|
||||
@@ -219,30 +222,30 @@ was run as root. This complements the "uid" option. The default is gid -2,
|
||||
which is normally the group "nobody".
|
||||
|
||||
dit(bf(filter)) The "filter" option allows you to specify a space-separated
|
||||
list of filter rules that the server will not allow to be read or written.
|
||||
list of filter rules that the daemon will not allow to be read or written.
|
||||
This is only superficially equivalent to the client specifying these
|
||||
patterns with the bf(--filter) option. Only one "filter" option may be
|
||||
specified, but it may contain as many rules as you like, including
|
||||
merge-file rules. Note that per-directory merge-file rules do not provide
|
||||
as much protection as global rules, but they can be used to make bf(--delete)
|
||||
work better when a client downloads the server's files (if the per-dir
|
||||
work better when a client downloads the daemon's files (if the per-dir
|
||||
merge files are included in the transfer).
|
||||
|
||||
dit(bf(exclude)) The "exclude" option allows you to specify a
|
||||
space-separated list of patterns that the server will not allow to be read
|
||||
space-separated list of patterns that the daemon will not allow to be read
|
||||
or written. This is only superficially equivalent to the client
|
||||
specifying these patterns with the bf(--exclude) option. Only one "exclude"
|
||||
option may be specified, but you can use "-" and "+" before patterns to
|
||||
specify exclude/include.
|
||||
|
||||
Because this exclude list is not passed to the client it only applies on
|
||||
the server: that is, it excludes files received by a client when receiving
|
||||
from a server and files deleted on a server when sending to a server, but
|
||||
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 server.
|
||||
from a daemon.
|
||||
|
||||
dit(bf(exclude from)) The "exclude from" option specifies a filename
|
||||
on the server that contains exclude patterns, one per line.
|
||||
on the daemon that contains exclude patterns, one per line.
|
||||
This is only superficially equivalent
|
||||
to the client specifying the bf(--exclude-from) option with an equivalent file.
|
||||
See the "exclude" option above.
|
||||
@@ -250,14 +253,14 @@ See the "exclude" option above.
|
||||
dit(bf(include)) The "include" option allows you to specify a
|
||||
space-separated list of patterns which rsync should not exclude. This is
|
||||
only superficially equivalent to the client specifying these patterns with
|
||||
the bf(--include) option because it applies only on the server. This is
|
||||
the bf(--include) option because it applies only on the daemon. This is
|
||||
useful as it allows you to build up quite complex exclude/include rules.
|
||||
Only one "include" option may be specified, but you can use "+" and "-"
|
||||
before patterns to switch include/exclude. See the "exclude" option
|
||||
above.
|
||||
|
||||
dit(bf(include from)) The "include from" option specifies a filename
|
||||
on the server that contains include patterns, one per line. This is
|
||||
on the daemon that contains include patterns, one per line. This is
|
||||
only superficially equivalent to the client specifying the
|
||||
bf(--include-from) option with a equivalent file.
|
||||
See the "exclude" option above.
|
||||
@@ -273,10 +276,10 @@ 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 bf(CONNECTING TO AN RSYNC SERVER OVER A REMOTE SHELL
|
||||
PROGRAM) section in rsync(1) for information on how handle an
|
||||
See also the "CONNECTING TO AN RSYNC DAEMON OVER A REMOTE SHELL
|
||||
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 server.
|
||||
username when using a remote shell to connect to an rsync daemon.
|
||||
|
||||
dit(bf(secrets file)) The "secrets file" option specifies the name of
|
||||
a file that contains the username:password pairs used for
|
||||
@@ -351,21 +354,21 @@ rejected. See the "hosts allow" option for more information.
|
||||
The default is no "hosts deny" option, which means all hosts can connect.
|
||||
|
||||
dit(bf(ignore errors)) The "ignore errors" option tells rsyncd to
|
||||
ignore I/O errors on the server when deciding whether to run the delete
|
||||
ignore I/O errors on the daemon when deciding whether to run the delete
|
||||
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.
|
||||
|
||||
dit(bf(ignore nonreadable)) This tells the rsync server to completely
|
||||
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
|
||||
logging of downloads and uploads in a format somewhat similar to that
|
||||
used by ftp daemons. The server always logs the transfer at the end, so
|
||||
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.
|
||||
|
||||
If you want to customize the log lines, see the "log format" option.
|
||||
@@ -373,7 +376,9 @@ If you want to customize the log lines, see the "log format" option.
|
||||
dit(bf(log format)) The "log format" option allows you to specify the
|
||||
format used for logging file transfers when transfer logging is enabled.
|
||||
The format is a text string containing embedded single-character escape
|
||||
sequences prefixed with a percent (%) character.
|
||||
sequences prefixed with a percent (%) character. An optional numeric
|
||||
field width may also be specified between the percent and the escape
|
||||
letter (e.g. "%-50n %8l %07p").
|
||||
|
||||
The default log format is "%o %h [%a] %m (%u) %f %l", and a "%t [%p] "
|
||||
is always prefixed when using the "log file" option.
|
||||
@@ -408,19 +413,19 @@ For a list of what the characters mean that are output by "%i", see the
|
||||
bf(--itemize-changes) option in the rsync manpage.
|
||||
|
||||
Note that some of the logged output changes when talking with older
|
||||
rsync versions. For instance, deleted files were only logged as verbose
|
||||
rsync versions. For instance, deleted files were only output as verbose
|
||||
messages prior to rsync 2.6.4.
|
||||
|
||||
dit(bf(timeout)) The "timeout" option allows you to override the
|
||||
clients choice for I/O timeout for this module. Using this option you
|
||||
can ensure that rsync won't wait on a dead client forever. The timeout
|
||||
is specified in seconds. A value of zero means no timeout and is the
|
||||
default. A good choice for anonymous rsync servers may be 600 (giving
|
||||
default. A good choice for anonymous rsync daemons may be 600 (giving
|
||||
a 10 minute timeout).
|
||||
|
||||
dit(bf(refuse options)) The "refuse options" option allows you to
|
||||
specify a space-separated list of rsync command line options that will
|
||||
be refused by your rsync server.
|
||||
be refused by your rsync daemon.
|
||||
You may specify the full option name, its one-letter abbreviation, or a
|
||||
wild-card string that matches multiple options.
|
||||
For example, this would refuse bf(--checksum) (bf(-c)) and all the various
|
||||
@@ -435,7 +440,7 @@ bf(remove-sent-files) when the daemon is the sender; if you want the latter
|
||||
without the former, instead refuse "delete-*" -- that refuses all the
|
||||
delete modes without affecting bf(--remove-sent-files).
|
||||
|
||||
When an option is refused, the server prints an error message and exits.
|
||||
When an option is refused, the daemon prints an error message and exits.
|
||||
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.
|
||||
@@ -463,7 +468,7 @@ 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 server protocol does not currently provide any
|
||||
Also note that the rsync daemon protocol does not currently provide any
|
||||
encryption of the data that is transferred over the connection. Only
|
||||
authentication is provided. Use ssh as the transport if you want
|
||||
encryption.
|
||||
@@ -471,16 +476,16 @@ encryption.
|
||||
Future versions of rsync may support SSL for better authentication and
|
||||
encryption, but that is still being investigated.
|
||||
|
||||
manpagesection(RUNNING AN RSYNC SERVER OVER A REMOTE SHELL PROGRAM)
|
||||
manpagesection(RUNNING AN RSYNC DAEMON OVER A REMOTE SHELL PROGRAM)
|
||||
|
||||
If rsync is run with both the bf(--daemon) and bf(--rsh) (bf(-e)) options, it will
|
||||
spawn an rsync daemon using a remote shell connection. Several
|
||||
configuration options will not be available unless the remote user is
|
||||
root (e.g. chroot, setuid/setgid, etc.). There is no need to configure
|
||||
inetd or the services map to include the rsync server port if you run an
|
||||
rsync server only via a remote shell program.
|
||||
inetd or the services map to include the rsync daemon port if you run an
|
||||
rsync daemon only via a remote shell program.
|
||||
|
||||
ADVANCED: To run an rsync server out of a single-use ssh key, use the
|
||||
ADVANCED: To run an rsync daemon out of a single-use ssh key, use the
|
||||
"command=em(COMMAND)" syntax in the remote user's authorized_keys entry,
|
||||
where command would be
|
||||
|
||||
@@ -560,15 +565,12 @@ manpagediagnostics()
|
||||
|
||||
manpagebugs()
|
||||
|
||||
The rsync server does not send all types of error messages to the
|
||||
client. this means a client may be mystified as to why a transfer
|
||||
failed. The error will have been logged by syslog on the server.
|
||||
|
||||
Please report bugs! The rsync bug tracking system is online at
|
||||
url(http://rsync.samba.org/)(http://rsync.samba.org/)
|
||||
|
||||
manpagesection(VERSION)
|
||||
This man page is current for version 2.x of rsync.
|
||||
|
||||
This man page is current for version 2.6.5 of rsync.
|
||||
|
||||
manpagesection(CREDITS)
|
||||
|
||||
@@ -589,7 +591,7 @@ Gailly and Mark Adler.
|
||||
manpagesection(THANKS)
|
||||
|
||||
Thanks to Warren Stanley for his original idea and patch for the rsync
|
||||
server. Thanks to Karsten Thygesen for his many suggestions and
|
||||
daemon. Thanks to Karsten Thygesen for his many suggestions and
|
||||
documentation!
|
||||
|
||||
manpageauthor()
|
||||
|
||||
20
sender.c
20
sender.c
@@ -20,7 +20,7 @@
|
||||
#include "rsync.h"
|
||||
|
||||
extern int verbose;
|
||||
extern int dry_run;
|
||||
extern int do_xfers;
|
||||
extern int am_server;
|
||||
extern int am_daemon;
|
||||
extern int log_before_transfer;
|
||||
@@ -28,12 +28,15 @@ extern int log_format_has_i;
|
||||
extern int daemon_log_format_has_i;
|
||||
extern int csum_length;
|
||||
extern int io_error;
|
||||
extern int allowed_lull;
|
||||
extern int protocol_version;
|
||||
extern int remove_sent_files;
|
||||
extern int updating_basis_file;
|
||||
extern int make_backups;
|
||||
extern int do_progress;
|
||||
extern int inplace;
|
||||
extern int batch_fd;
|
||||
extern int write_batch;
|
||||
extern struct stats stats;
|
||||
extern struct file_list *the_file_list;
|
||||
extern char *log_format;
|
||||
@@ -54,6 +57,7 @@ static struct sum_struct *receive_sums(int f)
|
||||
{
|
||||
struct sum_struct *s;
|
||||
int32 i;
|
||||
int lull_mod = allowed_lull * 5;
|
||||
OFF_T offset = 0;
|
||||
|
||||
if (!(s = new(struct sum_struct)))
|
||||
@@ -87,6 +91,9 @@ static struct sum_struct *receive_sums(int f)
|
||||
s->sums[i].len = s->blength;
|
||||
offset += s->sums[i].len;
|
||||
|
||||
if (allowed_lull && !(i % lull_mod))
|
||||
maybe_send_keepalive();
|
||||
|
||||
if (verbose > 3) {
|
||||
rprintf(FINFO,
|
||||
"chunk[%d] len=%d offset=%.0f sum1=%08x\n",
|
||||
@@ -173,10 +180,6 @@ int read_item_attrs(int f_in, int f_out, int ndx, uchar *type_ptr,
|
||||
}
|
||||
*len_ptr = len;
|
||||
|
||||
/* Temporary handling of 2.6.4pre3 */
|
||||
if (iflags & ITEM_DUMMY_BIT && iflags & (ITEM_LOCAL_CHANGE|ITEM_TRANSFER))
|
||||
iflags &= ~ITEM_DUMMY_BIT;
|
||||
|
||||
if (iflags & ITEM_TRANSFER) {
|
||||
if (!S_ISREG(the_file_list->files[ndx]->mode)) {
|
||||
rprintf(FERROR,
|
||||
@@ -208,6 +211,7 @@ void send_files(struct file_list *flist, int f_out, int f_in)
|
||||
int save_make_backups = make_backups;
|
||||
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;
|
||||
|
||||
if (verbose > 2)
|
||||
@@ -266,7 +270,7 @@ void send_files(struct file_list *flist, int f_out, int f_in)
|
||||
stats.num_transferred_files++;
|
||||
stats.total_transferred_size += file->length;
|
||||
|
||||
if (dry_run) { /* log the transfer */
|
||||
if (!do_xfers) { /* log the transfer */
|
||||
if (!am_server && log_format)
|
||||
log_item(file, &stats, iflags, NULL);
|
||||
write_ndx_and_attrs(f_out, i, iflags, fnamecmp_type,
|
||||
@@ -323,7 +327,7 @@ void send_files(struct file_list *flist, int f_out, int f_in)
|
||||
|
||||
write_ndx_and_attrs(f_out, i, iflags, fnamecmp_type,
|
||||
xname, xlen);
|
||||
write_sum_head(f_out, s);
|
||||
write_sum_head(f_xfer, s);
|
||||
|
||||
if (verbose > 2) {
|
||||
rprintf(FINFO, "calling match_sums %s\n",
|
||||
@@ -337,7 +341,7 @@ void send_files(struct file_list *flist, int f_out, int f_in)
|
||||
|
||||
set_compression(fname);
|
||||
|
||||
match_sums(f_out, s, mbuf, st.st_size);
|
||||
match_sums(f_xfer, s, mbuf, st.st_size);
|
||||
if (do_progress)
|
||||
end_progress(st.st_size);
|
||||
|
||||
|
||||
34
socket.c
34
socket.c
@@ -127,7 +127,7 @@ static int establish_proxy_connection(int fd, char *host, int port,
|
||||
* if this fails.
|
||||
**/
|
||||
int try_bind_local(int s, int ai_family, int ai_socktype,
|
||||
const char *bind_address)
|
||||
const char *bind_addr)
|
||||
{
|
||||
int error;
|
||||
struct addrinfo bhints, *bres_all, *r;
|
||||
@@ -136,9 +136,9 @@ int try_bind_local(int s, int ai_family, int ai_socktype,
|
||||
bhints.ai_family = ai_family;
|
||||
bhints.ai_socktype = ai_socktype;
|
||||
bhints.ai_flags = AI_PASSIVE;
|
||||
if ((error = getaddrinfo(bind_address, NULL, &bhints, &bres_all))) {
|
||||
if ((error = getaddrinfo(bind_addr, NULL, &bhints, &bres_all))) {
|
||||
rprintf(FERROR, RSYNC_NAME ": getaddrinfo %s: %s\n",
|
||||
bind_address, gai_strerror(error));
|
||||
bind_addr, gai_strerror(error));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -172,12 +172,12 @@ int try_bind_local(int s, int ai_family, int ai_socktype,
|
||||
* reachable, perhaps because we can't e.g. route ipv6 to that network
|
||||
* but we can get ip4 packets through.
|
||||
*
|
||||
* @param bind_address Local address to use. Normally NULL to bind
|
||||
* @param bind_addr Local address to use. Normally NULL to bind
|
||||
* the wildcard address.
|
||||
*
|
||||
* @param af_hint Address family, e.g. AF_INET or AF_INET6.
|
||||
**/
|
||||
int open_socket_out(char *host, int port, const char *bind_address,
|
||||
int open_socket_out(char *host, int port, const char *bind_addr,
|
||||
int af_hint)
|
||||
{
|
||||
int type = SOCK_STREAM;
|
||||
@@ -253,9 +253,9 @@ int open_socket_out(char *host, int port, const char *bind_address,
|
||||
if (s < 0)
|
||||
continue;
|
||||
|
||||
if (bind_address
|
||||
if (bind_addr
|
||||
&& try_bind_local(s, res->ai_family, type,
|
||||
bind_address) == -1) {
|
||||
bind_addr) == -1) {
|
||||
close(s);
|
||||
s = -1;
|
||||
continue;
|
||||
@@ -293,9 +293,9 @@ int open_socket_out(char *host, int port, const char *bind_address,
|
||||
*
|
||||
* This is based on the Samba LIBSMB_PROG feature.
|
||||
*
|
||||
* @param bind_address Local address to use. Normally NULL to get the stack default.
|
||||
* @param bind_addr Local address to use. Normally NULL to get the stack default.
|
||||
**/
|
||||
int open_socket_out_wrapped(char *host, int port, const char *bind_address,
|
||||
int open_socket_out_wrapped(char *host, int port, const char *bind_addr,
|
||||
int af_hint)
|
||||
{
|
||||
char *prog = getenv("RSYNC_CONNECT_PROG");
|
||||
@@ -307,7 +307,7 @@ int open_socket_out_wrapped(char *host, int port, const char *bind_address,
|
||||
}
|
||||
if (prog)
|
||||
return sock_exec(prog);
|
||||
return open_socket_out(host, port, bind_address, af_hint);
|
||||
return open_socket_out(host, port, bind_addr, af_hint);
|
||||
}
|
||||
|
||||
|
||||
@@ -322,10 +322,10 @@ int open_socket_out_wrapped(char *host, int port, const char *bind_address,
|
||||
* We return an array of file-descriptors to the sockets, with a trailing
|
||||
* -1 value to indicate the end of the list.
|
||||
*
|
||||
* @param bind_address Local address to bind, or NULL to allow it to
|
||||
* @param bind_addr Local address to bind, or NULL to allow it to
|
||||
* default.
|
||||
**/
|
||||
static int *open_socket_in(int type, int port, const char *bind_address,
|
||||
static int *open_socket_in(int type, int port, const char *bind_addr,
|
||||
int af_hint)
|
||||
{
|
||||
int one = 1;
|
||||
@@ -339,10 +339,10 @@ static int *open_socket_in(int type, int port, const char *bind_address,
|
||||
hints.ai_socktype = type;
|
||||
hints.ai_flags = AI_PASSIVE;
|
||||
snprintf(portbuf, sizeof portbuf, "%d", port);
|
||||
error = getaddrinfo(bind_address, portbuf, &hints, &all_ai);
|
||||
error = getaddrinfo(bind_addr, portbuf, &hints, &all_ai);
|
||||
if (error) {
|
||||
rprintf(FERROR, RSYNC_NAME ": getaddrinfo: bind address %s: %s\n",
|
||||
bind_address, gai_strerror(error));
|
||||
bind_addr, gai_strerror(error));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -478,7 +478,7 @@ void start_accept_loop(int port, int (*fn)(int, int))
|
||||
/* close log file before the potentially very long select so
|
||||
* file can be trimmed by another process instead of growing
|
||||
* forever */
|
||||
log_close();
|
||||
logfile_close();
|
||||
|
||||
#ifdef FD_COPY
|
||||
FD_COPY(&deffds, &fds);
|
||||
@@ -507,8 +507,8 @@ void start_accept_loop(int port, int (*fn)(int, int))
|
||||
for (i = 0; sp[i] >= 0; i++)
|
||||
close(sp[i]);
|
||||
/* Re-open log file in child before possibly giving
|
||||
* up privileges (see log_close() above). */
|
||||
log_open();
|
||||
* up privileges (see logfile_close() above). */
|
||||
logfile_reopen();
|
||||
ret = fn(fd, fd);
|
||||
close_all();
|
||||
_exit(ret);
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#!/usr/bin/perl
|
||||
#
|
||||
# This script lets you update a hierarchy of files in an atomic way by
|
||||
# first creating a new hierarchy using --link-dest to rsync, and then
|
||||
# swapping the hierarchy into place. See the usage message for more
|
||||
# details and some important caveats!
|
||||
# first creating a new hierarchy using rsync's --link-dest option, and
|
||||
# then swapping the hierarchy into place. **See the usage message for
|
||||
# more details and some important caveats!**
|
||||
|
||||
use strict;
|
||||
use Cwd 'abs_path';
|
||||
|
||||
42
support/cvs2includes
Executable file
42
support/cvs2includes
Executable file
@@ -0,0 +1,42 @@
|
||||
#!/usr/bin/perl
|
||||
#
|
||||
# This script finds all CVS/Entries files in the current directory and below
|
||||
# and creates a local .cvsinclude file with non-inherited rules including each
|
||||
# checked-in file. Then, use this option whenever using --cvs-exclude (-C):
|
||||
#
|
||||
# -f ': .cvsinclude'
|
||||
#
|
||||
# That ensures that all checked-in files/dirs are included in the transfer.
|
||||
# (You could alternately put ": .cvsinclude" into an .rsync-filter file and
|
||||
# use the -F option, which is easier to type.)
|
||||
#
|
||||
# The downside is that you need to remember to re-run cvs2includes whenever
|
||||
# You add a new file to the project.
|
||||
use strict;
|
||||
|
||||
open(FIND, 'find . -name CVS -type d |') or die $!;
|
||||
while (<FIND>) {
|
||||
chomp;
|
||||
s#^\./##;
|
||||
|
||||
my $entries = "$_/Entries";
|
||||
s/CVS$/.cvsinclude/;
|
||||
my $filter = $_;
|
||||
|
||||
open(ENTRIES, $entries) or die "Unable to open $entries: $!\n";
|
||||
my @includes;
|
||||
while (<ENTRIES>) {
|
||||
push(@includes, $1) if m#/(.+?)/#;
|
||||
}
|
||||
close ENTRIES;
|
||||
if (@includes) {
|
||||
open(FILTER, ">$filter") or die "Unable to write $filter: $!\n";
|
||||
print FILTER '+ /', join("\n+ /", @includes), "\n";
|
||||
close FILTER;
|
||||
print "Updated $filter\n";
|
||||
} elsif (-f $filter) {
|
||||
unlink($filter);
|
||||
print "Removed $filter\n";
|
||||
}
|
||||
}
|
||||
close FIND;
|
||||
@@ -20,7 +20,7 @@
|
||||
# ADDENDUM: The addition of the --filter option (which has support for
|
||||
# absolute-anchored excludes) has made this script less useful than it
|
||||
# was. Beginning with 2.6.4, you can achieve the effect of this script
|
||||
# though this command:
|
||||
# through this command:
|
||||
#
|
||||
# awk '{print $2}' /proc/mounts | rsync -f 'merge,/- -' host:/dir /dest/
|
||||
|
||||
|
||||
@@ -31,8 +31,8 @@ die "Not invoked via sshd\n$Usage" unless defined $command;
|
||||
die "SSH_ORIGINAL_COMMAND='$command' is not rsync\n" unless $command =~ /^rsync\s/;
|
||||
die "$0 -ro: sending to read-only server not allowed\n"
|
||||
if $ro and $command !~ /^rsync --server --sender /;
|
||||
die "$0 -ro: use of --remove-sent-files with read-only server not allowed\n"
|
||||
if $ro and $command =~ /\s--remove-sent-files/;
|
||||
die "$0 -ro: use of $1 with read-only server not allowed\n"
|
||||
if $ro and $command =~ /\s(--remove-\S+)/;
|
||||
|
||||
my ($cmd,$dir) = $command =~ /^(rsync\s+(?:-[-a-zA-Z]+\s+)+\.) ?("[^"]*"|[^\s"]*)$/;
|
||||
die "$0: invalid rsync-command syntax or options\n" if !defined $cmd;
|
||||
|
||||
@@ -243,7 +243,7 @@ int do_fstat(int fd, STRUCT_STAT *st)
|
||||
|
||||
OFF_T do_lseek(int fd, OFF_T offset, int whence)
|
||||
{
|
||||
#if SIZEOF_OFF64_T
|
||||
#ifdef HAVE_LSEEK64
|
||||
off64_t lseek64();
|
||||
return lseek64(fd, offset, whence);
|
||||
#else
|
||||
|
||||
@@ -35,15 +35,20 @@ for fn in name1 name2; do
|
||||
mv "$todir/$fn~" "$todir/$fn"
|
||||
done
|
||||
|
||||
checkit "$RSYNC -avv --no-whole-file --backup --backup-dir=\"$bakdir\" \"$fromdir/\" \"$todir/\"" "$fromdir" "$todir" \
|
||||
echo deleted-file >"$todir/dname"
|
||||
cp -p "$todir/dname" "$chkdir"
|
||||
|
||||
checkit "$RSYNC -avv --no-whole-file --delete-after \
|
||||
--backup --backup-dir=\"$bakdir\" \"$fromdir/\" \"$todir/\"" "$fromdir" "$todir" \
|
||||
| tee "$outfile"
|
||||
|
||||
for fn in name1 name2; do
|
||||
grep "backed up $fn to .*/$fn$" "$outfile" >/dev/null || test_fail "no backup message output for $fn"
|
||||
done
|
||||
diff -r $diffopt "$chkdir" "$bakdir" || test_fail "backup dir contents are bogus"
|
||||
rm "$bakdir/dname"
|
||||
|
||||
checkit "$RSYNC -avv \"$fromdir/\" \"$chkdir/\"" "$fromdir" "$chkdir"
|
||||
checkit "$RSYNC -avv --del \"$fromdir/\" \"$chkdir/\"" "$fromdir" "$chkdir"
|
||||
cat $srcdir/[efgr]*.[ch] > "$name1"
|
||||
cat $srcdir/[ew]*.[ch] > "$name2"
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ rm "$todir/text"
|
||||
runtest "one file" 'checkit "$RSYNC -avH \"$fromdir/\" \"$todir\"" "$fromdir/" "$todir"'
|
||||
|
||||
echo "extra line" >> "$todir/text"
|
||||
runtest "extra data" 'checkit "$RSYNC -avH \"$fromdir/\" \"$todir\"" "$fromdir/" "$todir"'
|
||||
runtest "extra data" 'checkit "$RSYNC -avH --no-whole-file \"$fromdir/\" \"$todir\"" "$fromdir/" "$todir"'
|
||||
|
||||
cp "$fromdir/text" "$todir/ThisShouldGo"
|
||||
runtest " --delete" 'checkit "$RSYNC --delete -avH \"$fromdir/\" \"$todir\"" "$fromdir/" "$todir"'
|
||||
|
||||
@@ -30,8 +30,34 @@ echo "This is the file" > "$name1"
|
||||
ln "$name1" "$name2" || fail "Can't create hardlink"
|
||||
ln "$name2" "$name3" || fail "Can't create hardlink"
|
||||
cp "$name2" "$name4" || fail "Can't copy file"
|
||||
cat $srcdir/*.c >"$fromdir/text"
|
||||
|
||||
checkit "$RSYNC -aHivv \"$fromdir/\" \"$todir/\"" "$fromdir" "$todir"
|
||||
|
||||
echo "extra extra" >>"$todir/name1"
|
||||
|
||||
checkit "$RSYNC -aHivv --no-whole-file \"$fromdir/\" \"$todir/\"" "$fromdir" "$todir"
|
||||
|
||||
# Add a new link in a new subdirectory to test that we don't try to link
|
||||
# the files before the directory gets created.
|
||||
mkdir "$fromdir/subdir"
|
||||
ln "$name1" "$fromdir/subdir/new-file"
|
||||
rm "$todir/text"
|
||||
|
||||
checkit "$RSYNC -aHivv \"$fromdir/\" \"$todir/\"" "$fromdir" "$todir"
|
||||
|
||||
# Do some duplicate copies using --link-dest and --copy-dest to test that
|
||||
# we hard-link all locally-inherited items.
|
||||
checkit "$RSYNC -aHivv --link-dest=\"$todir\" \"$fromdir/\" \"$chkdir/\"" "$todir" "$chkdir"
|
||||
|
||||
rm -rf "$chkdir"
|
||||
checkit "$RSYNC -aHivv --copy-dest=\"$todir\" \"$fromdir/\" \"$chkdir/\"" "$fromdir" "$chkdir"
|
||||
|
||||
# Make sure there's nothing wrong with sending a single file with -H
|
||||
# enabled (this has broken twice so far, so we need this test).
|
||||
rm -rf "$todir"
|
||||
$RSYNC -aHivv "$name1" "$todir/"
|
||||
diff $diffopt "$name1" "$todir" || test_fail "solo copy of name1 failed"
|
||||
|
||||
# The script would have aborted on error, so getting here means we've won.
|
||||
exit 0
|
||||
|
||||
39
testsuite/relative.test
Normal file
39
testsuite/relative.test
Normal file
@@ -0,0 +1,39 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Copyright (C) 2005 by Wayne Davison <wayned@samba.org>
|
||||
#
|
||||
# This program is distributable under the terms of the GNU GPL (see COPYING)
|
||||
|
||||
. "$suitedir/rsync.fns"
|
||||
|
||||
deepstr='down/3/deep'
|
||||
deepdir="$fromdir/$deepstr"
|
||||
mkdir -p "$deepdir"
|
||||
fromdir="$deepdir"
|
||||
hands_setup
|
||||
fromdir="$tmpdir/from"
|
||||
|
||||
outfile="$scratchdir/rsync.out"
|
||||
|
||||
cd "$fromdir"
|
||||
|
||||
# Main script starts here
|
||||
|
||||
echo "$fromdir"
|
||||
runtest "basic relative" 'checkit "$RSYNC -avR ./$deepstr \"$todir\"" "$fromdir/" "$todir"'
|
||||
|
||||
ln "$deepdir/filelist" "$deepdir/dir"
|
||||
runtest "hard links" 'checkit "$RSYNC -avHR ./$deepstr/ \"$todir\"" "$fromdir/" "$todir"'
|
||||
|
||||
cp "$deepdir/text" "$todir/$deepstr/ThisShouldGo"
|
||||
cp "$deepdir/text" "$todir/$deepstr/dir/ThisShouldGoToo"
|
||||
runtest "deletion" 'checkit "$RSYNC -avHR --delete ./$deepstr/ \"$todir\"" "$fromdir/" "$todir"'
|
||||
|
||||
runtest "non-deletion" 'checkit "$RSYNC -aiHR --delete ./$deepstr/ \"$todir\"" "$fromdir/" "$todir"' \
|
||||
| tee "$outfile"
|
||||
|
||||
# Make sure no files were deleted
|
||||
grep 'deleting ' "$outfile" && test_fail "Erroneous deletions occurred!"
|
||||
|
||||
# The script would have aborted on error, so getting here means we've won.
|
||||
exit 0
|
||||
32
util.c
32
util.c
@@ -877,12 +877,13 @@ int pop_dir(char *dir)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Return the filename, turning any non-printable characters into '?'s.
|
||||
* This ensures that outputting it on a line of its own cannot generate an
|
||||
* empty line. This function can return only MAX_SAFE_NAMES values at a
|
||||
* time! The returned value can be longer than MAXPATHLEN (because we
|
||||
* may be trying to output an error about a too-long filename)! */
|
||||
const char *safe_fname(const char *fname)
|
||||
/* Return the filename, turning any non-printable characters into escaped
|
||||
* characters (e.g. \n -> \012, \ -> \\). This ensures that outputting it
|
||||
* cannot generate an empty line nor corrupt the screen. This function can
|
||||
* return only MAX_SAFE_NAMES values at a time! The returned value can be
|
||||
* longer than MAXPATHLEN (because we may be trying to output an error about
|
||||
* a too-long filename)! */
|
||||
char *safe_fname(const char *fname)
|
||||
{
|
||||
#define MAX_SAFE_NAMES 4
|
||||
static char fbuf[MAX_SAFE_NAMES][MAXPATHLEN*2];
|
||||
@@ -892,12 +893,21 @@ const char *safe_fname(const char *fname)
|
||||
|
||||
ndx = (ndx + 1) % MAX_SAFE_NAMES;
|
||||
for (t = fbuf[ndx]; *fname; fname++) {
|
||||
if (!isprint(*(uchar*)fname))
|
||||
*t++ = '?';
|
||||
else
|
||||
if (*fname == '\\') {
|
||||
if ((limit -= 2) < 0)
|
||||
break;
|
||||
*t++ = '\\';
|
||||
*t++ = '\\';
|
||||
} else if (!isprint(*(uchar*)fname)) {
|
||||
if ((limit -= 4) < 0)
|
||||
break;
|
||||
sprintf(t, "\\%03o", *(uchar*)fname);
|
||||
t += 4;
|
||||
} else {
|
||||
if (--limit < 0)
|
||||
break;
|
||||
*t++ = *fname;
|
||||
if (--limit == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
*t = '\0';
|
||||
|
||||
|
||||
Reference in New Issue
Block a user