mirror of
https://github.com/RsyncProject/rsync.git
synced 2026-05-25 07:15:35 -04:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
594fe5e1cc | ||
|
|
9fb21d2882 |
@@ -1,6 +1,6 @@
|
||||
ID
|
||||
Makefile
|
||||
autom4te*.cache
|
||||
autom4te.cache
|
||||
confdefs.h
|
||||
config.cache
|
||||
config.h
|
||||
@@ -21,3 +21,4 @@ tls
|
||||
trimslash
|
||||
t_unsafe
|
||||
wildtest
|
||||
zlib/dummy
|
||||
|
||||
4
INSTALL
4
INSTALL
@@ -48,6 +48,10 @@ completely implement the "New Sockets" API.
|
||||
<http://www.ipv6.org/impl/mac.html> says that Apple do not support
|
||||
IPv6 yet. If your build fails, try again with --disable-ipv6.
|
||||
|
||||
There is an unresolved problem with the OSX implimentation
|
||||
of setgroups causing rsyncd to fail. The workaround is to
|
||||
#undef HAVE_SETGROUPS in config.h
|
||||
|
||||
IBM AIX NOTES
|
||||
-------------
|
||||
|
||||
|
||||
@@ -25,9 +25,9 @@ VERSION=@VERSION@
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .c .o
|
||||
|
||||
HEADERS=byteorder.h config.h errcode.h proto.h rsync.h lib/pool_alloc.h
|
||||
HEADERS=byteorder.h config.h errcode.h proto.h rsync.h
|
||||
LIBOBJ=lib/wildmatch.o lib/compat.o lib/snprintf.o lib/mdfour.o \
|
||||
lib/permstring.o lib/pool_alloc.o @LIBOBJS@
|
||||
lib/permstring.o @LIBOBJS@
|
||||
ZLIBOBJ=zlib/deflate.o zlib/infblock.o zlib/infcodes.o zlib/inffast.o \
|
||||
zlib/inflate.o zlib/inftrees.o zlib/infutil.o zlib/trees.o \
|
||||
zlib/zutil.o zlib/adler32.o
|
||||
|
||||
229
NEWS
229
NEWS
@@ -1,190 +1,99 @@
|
||||
NEWS for rsync 2.6.1 (26 Apr 2004)
|
||||
Protocol: 28 (changed)
|
||||
Changes since 2.6.0:
|
||||
NEWS for rsync version 2.5.7:
|
||||
|
||||
SECURITY FIXES:
|
||||
SECURITY:
|
||||
|
||||
- Paths sent to an rsync daemon are more thoroughly sanitized when
|
||||
chroot is not used. If you're running a non-read-only rsync
|
||||
daemon with chroot disabled, *please upgrade*, ESPECIALLY if the
|
||||
user privs you run rsync under is anything above "nobody".
|
||||
* Fix buffer handling bugs. (Andrew Tridgell, Martin Pool, Paul
|
||||
Russell, Andrea Barisani)
|
||||
|
||||
|
||||
NEWS for rsync version 2.5.6, aka the dwd-between-jobs release
|
||||
Changes since version 2.5.5:
|
||||
|
||||
ENHANCEMENTS:
|
||||
|
||||
- Lower memory use, more optimal transfer of data over the socket,
|
||||
and lower CPU usage (see the INTERNAL section for details).
|
||||
* The --delete-after option now implies --delete. (Wayne Davison)
|
||||
|
||||
- The RSYNC_PROXY environment variable can now contain a
|
||||
"USER:PASS@" prefix before the "HOST:PORT" information.
|
||||
(Bardur Arantsson)
|
||||
* The --suffix option can now be used with --backup-dir. (Michael
|
||||
Zimmerman)
|
||||
|
||||
- The --progress output now mentions how far along in the transfer
|
||||
we are, including both a count of files transferred and a
|
||||
percentage of the total file-count that we've processed. It also
|
||||
shows better current-rate-of-transfer and remaining-transfer-time
|
||||
values.
|
||||
* Combining "::" syntax with the -rsh/-e option now uses the
|
||||
specified remote-shell as a transport to talk to a (newly-spawned)
|
||||
server-daemon. This allows someone to use daemon features, such
|
||||
as modules, over a secure protocol, such as ssh. (JD Paul)
|
||||
|
||||
- The configure script now accepts --with-rsyncd-conf=PATH to
|
||||
override the default value of the /etc/rsyncd.conf file.
|
||||
* The rsync:// syntax for daemon connections is now accepted in the
|
||||
destination field.
|
||||
|
||||
- Added a couple extra diffs in the "patches" dir, removed the ones
|
||||
that got applied, and rebuilt the rest.
|
||||
* If the file name given to --include-from or --exclude-from is "-",
|
||||
rsync will read from standard input. (J.W. Schultz)
|
||||
|
||||
- Documentation changes now attempt to describe some often mis-
|
||||
understood features more clearly.
|
||||
* New option --link-dest which is like --compare-dest except that
|
||||
unchanged files are hard-linked in to the destination directory.
|
||||
(J.W. Schultz)
|
||||
|
||||
* Don't report an error if an excluded file disappears during an
|
||||
rsync run. (Eugene Chupriyanov and Bo Kersey)
|
||||
|
||||
* Added .svn to --cvs-exclude list to support subversion. (Jon
|
||||
Middleton)
|
||||
|
||||
* Properly support IPv6 addresses in the rsyncd.conf "hosts allow"
|
||||
and "hosts deny" fields. (Hideaki Yoshifuji)
|
||||
|
||||
* Changed exclude file handling to permit DOS or MAC style line
|
||||
terminations. (J.W. Schultz)
|
||||
|
||||
* Ignore errors from chmod when -p/-a/--preserve-perms is not set.
|
||||
(Dave Dykstra)
|
||||
|
||||
BUG FIXES:
|
||||
|
||||
* Fix "forward name lookup failed" errors on AIX 4.3.3. (John
|
||||
L. Allen, Martin Pool)
|
||||
|
||||
- When -x (--one-file-system) is combined with -L (--copy-links) or
|
||||
--copy-unsafe-links, no symlinked files are skipped, even if the
|
||||
referent file is on a different filesystem.
|
||||
* Generate each file's rolling-checksum data as we send it, not
|
||||
in a separate (memory-eating) pass before hand. This prevents
|
||||
timeout errors on really large files. (Stefan Nehlsen)
|
||||
|
||||
- The --link-dest code now works properly for a non-root user when
|
||||
(1) the UIDs of the source and destination differ and -o was
|
||||
specified, or (2) when the group of the source can't be used on
|
||||
the destination and -g was specified.
|
||||
* Fix compilation on Tru64. (Albert Chin, Zoong Pham)
|
||||
|
||||
- Fixed a bug in the handling of -H (hard-links) that might cause
|
||||
the expanded PATH/NAME value of the current item to get
|
||||
overwritten (due to an expanded-name caching bug).
|
||||
|
||||
- We now reset the "new data has been sent" flag at the start of
|
||||
each file we send. This makes sure that an interrupted transfer
|
||||
with the --partial option set doesn't keep a shorter temp file
|
||||
than the current basis file when no new data has been transfered
|
||||
over the wire for that file.
|
||||
* Better handling of some client-server errors. (Martin Pool)
|
||||
|
||||
- Fixed a byte-order problem in --batch-mode on big-endian machines.
|
||||
(Jay Fenlason)
|
||||
* Fixed a crash that would occur when sending a list of files that
|
||||
contains a duplicate name (if it sorts to the end of the file
|
||||
list) and using --delete. (Wayne Davison)
|
||||
|
||||
- Fixed configure bug when running "./configure --disable-ipv6".
|
||||
* Fixed the file-name duplicate-removal code when dealing with multiple
|
||||
dups in a row. (Wayne Davison)
|
||||
|
||||
- Fixed "make test" bug when build dir is not the source dir.
|
||||
* Fixed a bug that caused rsync to lose the exit status of its child
|
||||
processes and sometimes return an exit code of 0 instead of showing
|
||||
an error. (David R. Staples, Dave Dykstra)
|
||||
|
||||
- When using --cvs-exclude, the exclude items we get from a
|
||||
per-directory's .cvsignore file once again only affect that one
|
||||
directory (not all following directories too). The items are also
|
||||
now properly word-split and parsed without any +/- prefix parsing.
|
||||
* Fixed bug in --copy-unsafe-links that caused it to be completely
|
||||
broken. (Dave Dykstra)
|
||||
|
||||
- When specifying the USER@HOST: prefix for a file, the USER part
|
||||
can now contain an '@', if needed (i.e. the last '@' is used to
|
||||
find the HOST, not the first).
|
||||
* Prevent infinite recursion in cleanup code under certain circumstances.
|
||||
(Sviatoslav Sviridov and Marc Espie)
|
||||
|
||||
- Fixed some bugs in the handling of group IDs for non-root users:
|
||||
(1) It properly handles a group that the sender didn't have a name
|
||||
for (it would previously skip changing the group on any files in
|
||||
that group). (2) If --numeric-ids is used, rsync no longer
|
||||
attempts to set groups that the user doesn't have the permission
|
||||
to set.
|
||||
* Fixed a bug that prevented rsync from creating intervening directories
|
||||
when --relative-paths/-R is set. (Craig Barratt)
|
||||
|
||||
- Fixed the "refuse options" setting in the rsyncd.conf file.
|
||||
|
||||
- Improved the -x (--one-file-system) flag's handling of any mount-
|
||||
point directories we encounter. It is both more optimal (in that
|
||||
it no longer does a useless scan of the contents of the mount-
|
||||
point dirs) and also fixes a bug where a remapped mount of the
|
||||
original filesystem could get discovered in a subdir we should be
|
||||
ignoring.
|
||||
|
||||
- Rsync no longer discards a double-slash at the start of a filename
|
||||
when trying to open the file. It also no longer constructs names
|
||||
that start with a double slash (unless the user supplied them).
|
||||
|
||||
- Path-specifying options to a daemon should now work the same with
|
||||
or without chroot turned on. Previously, such a option (such as
|
||||
--link-dest) would get its absolute path munged into a relative
|
||||
one if chroot was not on, making that setting fairly useless.
|
||||
Rsync now transforms the path into one that is based on the
|
||||
module's base dir when chroot is not enabled.
|
||||
|
||||
- Fixed compilation problem on Tru64 Unix (having to do with
|
||||
sockaddr.sa_len and sockaddr.sin_len).
|
||||
|
||||
- Fixed a compatibility problem interacting with older rsync
|
||||
versions that might send us an empty --suffix value without
|
||||
telling us that --backup-dir was specified.
|
||||
|
||||
- The "hosts allow" option for a daemon-over-remote-shell process
|
||||
now has improved support for IPv6 addresses and a fix for systems
|
||||
that have a length field in their socket structs.
|
||||
|
||||
- Fixed the ability to request an empty backup --suffix when sending
|
||||
files to an rsync daemon.
|
||||
* Prevent "Connection reset by peer" messages from Cygwin. (Randy O'Meara)
|
||||
|
||||
INTERNAL:
|
||||
|
||||
- Most of the I/O is now buffered, which results in a pretty large
|
||||
speedup when running under MS Windows. (Craig Barratt)
|
||||
* Many code cleanups and improved internal documentation. (Martin
|
||||
Pool, Nelson Beebe)
|
||||
|
||||
- Optimizations to the name-handling/comparing code have made some
|
||||
significant reductions in user-CPU time for large file sets.
|
||||
* Portability fixes. (Dave Dykstra and Wayne Davison)
|
||||
|
||||
- Some cleanup of the variable types make the code more consistent.
|
||||
* More test cases. (Martin Pool)
|
||||
|
||||
- Reduced memory requirements of hard link preservation.
|
||||
(J.W. Schultz)
|
||||
* Some test-case fixes. (Brian Poole, Wayne Davison)
|
||||
|
||||
- Implemented a new algorithm for hard-link handling that speeds up
|
||||
the code significantly. (J.W. Schultz and Wayne Davison)
|
||||
* Updated included popt to the latest vendor drop, version 1.6.4.
|
||||
(Jos Backus)
|
||||
|
||||
- The --hard-link option now uses the first existing file in the
|
||||
group of linked files as the basis for the transfer. This
|
||||
prevents the sub-optimal transfer of a file's data when a new
|
||||
hardlink is added on the sending side and it sorts alphabetically
|
||||
earlier in the list than the files that are already present on the
|
||||
receiving side.
|
||||
|
||||
- Dropped support for protocol versions less than 20 (2.3.0 released
|
||||
15 Mar 1999) and activated warnings for protocols less than 25
|
||||
(2.5.0 released 23 Aug 2001). (Wayne Davison and J.W. Schultz,
|
||||
severally)
|
||||
|
||||
- More optimal data transmission for --hard-links (protocol 28).
|
||||
|
||||
- More optimal data transmission for --checksum (protocol 28).
|
||||
|
||||
- Less memory is used when --checksum is specified.
|
||||
|
||||
- Less memory is used in the file list (a per-file savings).
|
||||
|
||||
- The generator is now better about not modifying the file list
|
||||
during the transfer in order to avoid a copy-on-write memory
|
||||
bifurcation (on systems where fork() uses shared memory).
|
||||
Previously, rsync's shared memory would slowly become unshared,
|
||||
resulting in real memory usage nearly doubling on the receiving
|
||||
side by the end of the transfer. Now, as long as permissions
|
||||
are being preserved, the shared memory should remain that way
|
||||
for the entire transfer.
|
||||
|
||||
- Changed hardlink info and file_struct + strings to use allocation
|
||||
pools. This reduces memory use for large file-sets and permits
|
||||
freeing memory to the OS. (J.W. Schultz)
|
||||
|
||||
- The 2 pipes used between the receiver and generator processes
|
||||
(which are forked on the same machine) were reduced to 1 pipe and
|
||||
the protocol improved so that (1) it is now impossible to have the
|
||||
"redo" pipe fill up and hang rsync, and (2) trailing messages from
|
||||
the receiver don't get lost on their way through the generator
|
||||
over to the sender (which mainly affected hard-link messages and
|
||||
verbose --stats output).
|
||||
|
||||
- Improved the internal uid/gid code to be more portable and a
|
||||
little more optimized.
|
||||
|
||||
- The device numbers sent when using --devices are now sent as
|
||||
separate major/minor values with 32-bit accuracy (protocol 28).
|
||||
Previously, the copied devices were sent as a single 32-bit
|
||||
number. This will make inter-operation of 64-bit binaries more
|
||||
compatible with their 32-bit brethren (with both ends of the
|
||||
connection are using protocol 28). Note that optimizations in the
|
||||
binary protocol for sending the device numbers often results in
|
||||
fewer bytes being used than before, even though more precision is
|
||||
now available.
|
||||
|
||||
- Some cleanup of the exclude/include structures and its code made
|
||||
things clearer (internally), simpler, and more efficient.
|
||||
|
||||
- The reading & writing of the file-list in batch-mode is now
|
||||
handled by the same code that sends & receives the list over the
|
||||
wire. This makes it much easier to maintain. (Note that the
|
||||
batch code is still considered to be experimental.)
|
||||
* Updated config.guess and config.sub to latest versions; this
|
||||
means rsync should build on more platforms. (Paul Green)
|
||||
|
||||
389
OLDNEWS
389
OLDNEWS
@@ -1,252 +1,5 @@
|
||||
NEWS for rsync 2.6.0 (1 Jan 2004)
|
||||
Protocol: 27 (changed)
|
||||
Changes since 2.5.7:
|
||||
|
||||
ENHANCEMENTS:
|
||||
|
||||
* "ssh" is now the default remote shell for rsync. If you want to
|
||||
change this, configure like this: "./configure --with-rsh=rsh".
|
||||
|
||||
* Added --files-from, --no-relative, --no-implied-dirs, and --from0.
|
||||
Note that --from0 affects the line-ending character for all the
|
||||
files read by the --*-from options. (Wayne Davison)
|
||||
|
||||
* Length of csum2 is now per-file starting with protocol version
|
||||
27. (J.W. Schultz)
|
||||
|
||||
* Per-file dynamic block size is now sqrt(file length). The
|
||||
per-file checksum size is determined according to an algorithm
|
||||
provided by Donovan Baarda which reduces the probability of rsync
|
||||
algorithm corrupting data and falling back using the whole md4
|
||||
checksums. (J.W. Schultz, Donovan Baarda)
|
||||
|
||||
* The --stats option no longer includes the (debug) malloc summary
|
||||
unless the verbose option was specified at least twice.
|
||||
|
||||
* Added a new error/warning code for when files vanish from the
|
||||
sending side. Made vanished source files not interfere with the
|
||||
file-deletion pass when --delete-after was specified.
|
||||
|
||||
* Various trailing-info sections are now preceded by a newline.
|
||||
|
||||
BUG FIXES:
|
||||
|
||||
* Fixed several exclude/include matching bugs when using wild-cards.
|
||||
This has a several user-visible effects, all of which make the
|
||||
matching more consistent and intuitive. This should hopefully not
|
||||
cause anyone problems since it makes the matching work more like
|
||||
what people are expecting. (Wayne Davison)
|
||||
|
||||
- A pattern with a "**" no longer causes a "*" to match slashes.
|
||||
For example, with "/*/foo/**", "foo" must be 2 levels deep.
|
||||
[If your string has BOTH "*" and "**" wildcards, changing the
|
||||
"*" wildcards to "**" will provide the old behavior in all
|
||||
versions.]
|
||||
|
||||
- "**/foo" now matches at the base of the transfer (like /foo
|
||||
does). [Use "/**/foo" to get the old behavior in all versions.]
|
||||
|
||||
- A non-anchored wildcard term floats to match beyond the base of
|
||||
the transfer. E.g. "CVS/R*" matches at the end of the path,
|
||||
just like the non-wildcard term "CVS/Root" does. [Use "/CVS/R*"
|
||||
to get the old behavior in all versions.]
|
||||
|
||||
- Including a "**" in the match term causes it to be matched
|
||||
against the entire path, not just the name portion, even if
|
||||
there aren't any interior slashes in the term. E.g. "foo**bar"
|
||||
would exclude "/path/foo-bar" (just like before) as well as
|
||||
"/foo-path/baz-bar" (unlike before). [Use "foo*bar" to get the
|
||||
old behavior in all versions.]
|
||||
|
||||
* The exclude list specified in the daemon's config file is now
|
||||
properly applied to the pulled items no matter how deep the
|
||||
user's file-args are in the source tree. (Wayne Davison)
|
||||
|
||||
* For protocol version >= 27, mdfour_tail() is called when the
|
||||
block size (including checksum_seed) is a multiple of 64.
|
||||
Previously it was not called, giving the wrong MD4 checksum.
|
||||
(Craig Barratt)
|
||||
|
||||
* For protocol version >= 27, a 64 bit bit counter is used in
|
||||
mdfour.c as required by the RFC. Previously only a 32 bit bit
|
||||
counter was used, causing incorrect MD4 file checksums for
|
||||
file sizes >= 512MB - 4. (Craig Barratt)
|
||||
|
||||
* Fixed a crash bug when interacting with older rsync versions and
|
||||
multiple files of the same name are destined for the same dir.
|
||||
(Wayne Davison)
|
||||
|
||||
* Keep tmp names from overflowing MAXPATHLEN.
|
||||
|
||||
* Make --link-dest honor the absence of -p, -o, and -g.
|
||||
|
||||
* Made rsync treat a trailing slash in the destination in a more
|
||||
consistent manner.
|
||||
|
||||
* Fixed file I/O error detection. (John Van Essen)
|
||||
|
||||
* Fixed bogus "malformed address {hostname}" message in rsyncd log
|
||||
when checking IP address against hostnames from "hosts allow"
|
||||
and "hosts deny" parameters in config file.
|
||||
|
||||
* Print heap statistics when verbose >= 2 instead of when >= 1.
|
||||
|
||||
* Fixed a compression (-z) bug when syncing a mostly-matching file
|
||||
that contains already-compressed data. (Yasuoka Masahiko and
|
||||
Wayne Davison)
|
||||
|
||||
* Fixed a bug in the --backup code that could cause deleted files
|
||||
to not get backed up.
|
||||
|
||||
* When the backup code makes new directories, create them with mode
|
||||
0700 instead of 0755 (since the directory permissions in the
|
||||
backup tree are not yet copied from the main tree).
|
||||
|
||||
* Call setgroups() in a more portable manner.
|
||||
|
||||
* Improved file-related error messages to better indicate exactly
|
||||
what pathname failed. (Wayne Davison)
|
||||
|
||||
* Fixed some bugs in the handling of --delete and --exclude when
|
||||
using the --relative (-R) option. (Wayne Davison)
|
||||
|
||||
* Fixed bug that prevented regular files from replacing
|
||||
special files and caused a directory in --link-dest or
|
||||
--compare-dest to block the creation of a file with the
|
||||
same path. A directory still cannot be replaced by a
|
||||
regular file unless --delete specified. (J.W. Schultz)
|
||||
|
||||
* Detect and report when open or opendir succeed but read and
|
||||
readdir fail caused by network filesystem issues and truncated
|
||||
files. (David Norwood, Michael Brown, J.W. Schultz)
|
||||
|
||||
* Added a fix that should give ssh time to restore the tty settings
|
||||
if the user presses Ctrl-C at an ssh password prompt.
|
||||
|
||||
INTERNAL:
|
||||
|
||||
* Eliminated vestigial support for old versions that we stopped
|
||||
supporting. (J.W. Schultz)
|
||||
|
||||
* Simplified some of the option-parsing code. (Wayne Davison)
|
||||
|
||||
* Some cleanup made to the exclude code, as well as some new
|
||||
defines added to enhance readability. (Wayne Davison)
|
||||
|
||||
* Changed the protocol-version code so that it can interact at a
|
||||
lower protocol level than the maximum supported by both sides.
|
||||
Added an undocumented option, --protocol=N, to force the value
|
||||
we advertise to the other side (primarily for testing purposes).
|
||||
(Wayne Davison)
|
||||
|
||||
|
||||
NEWS for rsync 2.5.7 (4 Dec 2003)
|
||||
Protocol: 26 (unchanged)
|
||||
Changes since 2.5.6:
|
||||
|
||||
SECURITY FIXES:
|
||||
|
||||
* Fix buffer handling bugs. (Andrew Tridgell, Martin Pool, Paul
|
||||
Russell, Andrea Barisani)
|
||||
|
||||
|
||||
NEWS for rsync 2.5.6, aka "the dwd-between-jobs release" (26 Jan 2003)
|
||||
Protocol: 26 (unchanged)
|
||||
Changes since 2.5.5:
|
||||
|
||||
ENHANCEMENTS:
|
||||
|
||||
* The --delete-after option now implies --delete. (Wayne Davison)
|
||||
|
||||
* The --suffix option can now be used with --backup-dir. (Michael
|
||||
Zimmerman)
|
||||
|
||||
* Combining "::" syntax with the -rsh/-e option now uses the
|
||||
specified remote-shell as a transport to talk to a (newly-spawned)
|
||||
server-daemon. This allows someone to use daemon features, such
|
||||
as modules, over a secure protocol, such as ssh. (JD Paul)
|
||||
|
||||
* The rsync:// syntax for daemon connections is now accepted in the
|
||||
destination field.
|
||||
|
||||
* If the file name given to --include-from or --exclude-from is "-",
|
||||
rsync will read from standard input. (J.W. Schultz)
|
||||
|
||||
* New option --link-dest which is like --compare-dest except that
|
||||
unchanged files are hard-linked in to the destination directory.
|
||||
(J.W. Schultz)
|
||||
|
||||
* Don't report an error if an excluded file disappears during an
|
||||
rsync run. (Eugene Chupriyanov and Bo Kersey)
|
||||
|
||||
* Added .svn to --cvs-exclude list to support subversion. (Jon
|
||||
Middleton)
|
||||
|
||||
* Properly support IPv6 addresses in the rsyncd.conf "hosts allow"
|
||||
and "hosts deny" fields. (Hideaki Yoshifuji)
|
||||
|
||||
* Changed exclude file handling to permit DOS or MAC style line
|
||||
terminations. (J.W. Schultz)
|
||||
|
||||
* Ignore errors from chmod when -p/-a/--preserve-perms is not set.
|
||||
(Dave Dykstra)
|
||||
|
||||
BUG FIXES:
|
||||
|
||||
* Fix "forward name lookup failed" errors on AIX 4.3.3. (John
|
||||
L. Allen, Martin Pool)
|
||||
|
||||
* Generate each file's rolling-checksum data as we send it, not
|
||||
in a separate (memory-eating) pass before hand. This prevents
|
||||
timeout errors on really large files. (Stefan Nehlsen)
|
||||
|
||||
* Fix compilation on Tru64. (Albert Chin, Zoong Pham)
|
||||
|
||||
* Better handling of some client-server errors. (Martin Pool)
|
||||
|
||||
* Fixed a crash that would occur when sending a list of files that
|
||||
contains a duplicate name (if it sorts to the end of the file
|
||||
list) and using --delete. (Wayne Davison)
|
||||
|
||||
* Fixed the file-name duplicate-removal code when dealing with multiple
|
||||
dups in a row. (Wayne Davison)
|
||||
|
||||
* Fixed a bug that caused rsync to lose the exit status of its child
|
||||
processes and sometimes return an exit code of 0 instead of showing
|
||||
an error. (David R. Staples, Dave Dykstra)
|
||||
|
||||
* Fixed bug in --copy-unsafe-links that caused it to be completely
|
||||
broken. (Dave Dykstra)
|
||||
|
||||
* Prevent infinite recursion in cleanup code under certain circumstances.
|
||||
(Sviatoslav Sviridov and Marc Espie)
|
||||
|
||||
* Fixed a bug that prevented rsync from creating intervening directories
|
||||
when --relative-paths/-R is set. (Craig Barratt)
|
||||
|
||||
* Prevent "Connection reset by peer" messages from Cygwin. (Randy O'Meara)
|
||||
|
||||
INTERNAL:
|
||||
|
||||
* Many code cleanups and improved internal documentation. (Martin
|
||||
Pool, Nelson Beebe)
|
||||
|
||||
* Portability fixes. (Dave Dykstra and Wayne Davison)
|
||||
|
||||
* More test cases. (Martin Pool)
|
||||
|
||||
* Some test-case fixes. (Brian Poole, Wayne Davison)
|
||||
|
||||
* Updated included popt to the latest vendor drop, version 1.6.4.
|
||||
(Jos Backus)
|
||||
|
||||
* Updated config.guess and config.sub to latest versions; this
|
||||
means rsync should build on more platforms. (Paul Green)
|
||||
|
||||
|
||||
NEWS for rsync 2.5.5, aka Snowy River (2 Apr 2002)
|
||||
Protocol: 26 (unchanged)
|
||||
Changes since 2.5.4:
|
||||
rsync 2.5.5 "Snowy River" (2 April 2002)
|
||||
protocol: 26 (unchanged)
|
||||
|
||||
ENHANCEMENTS:
|
||||
|
||||
@@ -285,15 +38,16 @@ Changes since 2.5.4:
|
||||
* Improved network error handling. (Greg A. Woods)
|
||||
|
||||
|
||||
NEWS for rsync 2.5.4, aka "Imitation lizard skin" (13 Mar 2002)
|
||||
Protocol: 26 (unchanged)
|
||||
Changes since 2.5.3:
|
||||
rsync 2.5.4 (13 March 2002)
|
||||
protocol: 26 (unchanged)
|
||||
|
||||
"Imitation lizard skin"
|
||||
|
||||
BUG FIXES:
|
||||
|
||||
* Additional fix for zlib double-free bug. (Martin Pool, Andrew
|
||||
Tridgell) (CVE CAN-2002-0059)
|
||||
|
||||
|
||||
ENHANCEMENTS:
|
||||
|
||||
* Merge in changes from zlib 1.1.3 to zlib 1.1.4. (Jos Backus)
|
||||
@@ -303,9 +57,10 @@ Changes since 2.5.3:
|
||||
* Additional test cases for --compress. (Martin Pool)
|
||||
|
||||
|
||||
NEWS for rsync 2.5.3, aka "Happy 26" (11 Mar 2002)
|
||||
Protocol: 26 (unchanged)
|
||||
Changes since 2.5.2:
|
||||
rsync 2.5.3 (11 March 2002)
|
||||
protocol: 26 (unchanged)
|
||||
|
||||
"Happy 26"
|
||||
|
||||
SECURITY FIXES:
|
||||
|
||||
@@ -318,7 +73,7 @@ Changes since 2.5.2:
|
||||
* Fix zlib double-free bug. (Owen Taylor, Mark J Cox) (CVE
|
||||
CAN-2002-0059)
|
||||
|
||||
* Fixed problem that in many cases caused the error message
|
||||
* Fixed problem that in many cases caused the error message
|
||||
unexpected read size of 0 in map_ptr
|
||||
and resulted in the wrong data being copied.
|
||||
|
||||
@@ -339,7 +94,7 @@ Changes since 2.5.2:
|
||||
* Merge in changes from zlib 1.1.2 to zlib 1.1.3. (Note that
|
||||
rsync still uses a custom version of zlib; you can not just link
|
||||
against a system library. See zlib/README.rsync)
|
||||
|
||||
|
||||
* Command to initiate connections is only shown with -vv, rather
|
||||
than -v as in 2.5.2. Output from plain -v is more similar to
|
||||
what was historically used so as not to break scripts that try
|
||||
@@ -353,10 +108,8 @@ Changes since 2.5.2:
|
||||
* If the daemon is unable to fork a child to accept a connection,
|
||||
print an error message. (Colin Walters)
|
||||
|
||||
|
||||
NEWS for rsync 2.5.2 (26 Jan 2002)
|
||||
Protocol: 26 (changed)
|
||||
Changes since 2.5.1:
|
||||
rsync 2.5.2 (26 Jan 2002)
|
||||
protocol: 26 (changed)
|
||||
|
||||
SECURITY FIXES:
|
||||
|
||||
@@ -383,7 +136,7 @@ Changes since 2.5.1:
|
||||
connection.
|
||||
|
||||
* --statistics now shows memory heap usage on platforms that
|
||||
support mallinfo().
|
||||
support mallinfo().
|
||||
|
||||
* "The Ted T'so school of program optimization": make progress
|
||||
visible and people will think it's faster. (With --progress,
|
||||
@@ -392,17 +145,15 @@ Changes since 2.5.1:
|
||||
|
||||
* Improvements to batch mode support. This is still experimental
|
||||
but testing would be welcome. (Jos Backus)
|
||||
|
||||
|
||||
* New --ignore-existing option, patch previously distributed with
|
||||
Vipul's Razor. (Debian #124286)
|
||||
|
||||
|
||||
NEWS for rsync 2.5.1 (3 Jan 2002)
|
||||
Protocol: 25 (unchanged)
|
||||
Changes since 2.5.0:
|
||||
|
||||
BUG FIXES:
|
||||
rsync 2.5.1 (2002-01-03)
|
||||
protocol: 25 (unchanged)
|
||||
|
||||
BUG FIXES:
|
||||
|
||||
* Fix for segfault in --daemon mode configuration parser. (Paul
|
||||
Mackerras)
|
||||
|
||||
@@ -424,19 +175,18 @@ Changes since 2.5.0:
|
||||
ENHANCEMENTS:
|
||||
|
||||
* --progress and -P now show estimated data transfer rate (in a
|
||||
multiple of bytes/s) and estimated time to completion. (Rik
|
||||
Faith)
|
||||
|
||||
multiple of bytes/s) and estimated time to completion. (Rik
|
||||
Faith)
|
||||
|
||||
* --no-detach option, required to run as a W32 service and also
|
||||
useful when running on Unix under daemontools, AIX's SRC, or a
|
||||
debugger. (Max Bowsher, Jos Backus)
|
||||
useful when running on Unix under daemontools, AIX's SRC, or a
|
||||
debugger. (Max Bowsher, Jos Backus)
|
||||
|
||||
* Clearer error messages for some conditions.
|
||||
|
||||
|
||||
NEWS for rsync 2.5.0 (30 Nov 2001)
|
||||
Protocol: 25 (changed)
|
||||
Changes since 2.4.6:
|
||||
rsync 2.5.0 (2001-11-30)
|
||||
protocol: 25 (changed)
|
||||
|
||||
ANNOUNCEMENTS
|
||||
|
||||
@@ -498,7 +248,7 @@ Changes since 2.4.6:
|
||||
* Attempt to fix error handling lockup bug.
|
||||
|
||||
* Give a non-0 exit code if *any* of the files we have been asked
|
||||
to transfer fail to transfer.
|
||||
to transfer fail to transfer
|
||||
|
||||
* For log messages containing ridiculously long strings that might
|
||||
overflow a buffer rsync no longer aborts, but rather prints an
|
||||
@@ -509,7 +259,7 @@ Changes since 2.4.6:
|
||||
* Improved support for UNICOS (tested on Cray T3E and Cray SV1)
|
||||
|
||||
* autoconf2.52 (or later) is now required to rebuild the autoconf
|
||||
scripts. It is not required to simply build rsync.
|
||||
scripts. It is not required to simply build rsync.
|
||||
|
||||
* Platforms thought to work in this release:
|
||||
|
||||
@@ -552,46 +302,41 @@ Changes since 2.4.6:
|
||||
build farm.
|
||||
|
||||
Partial Protocol History
|
||||
RELEASE DATE VER. DATE OF COMMIT PROTOCOL
|
||||
01 Jan 2004 2.6.0 10 Apr 2003 27 (MAX=40)
|
||||
04 Dec 2003 2.5.7 26
|
||||
26 Jan 2003 2.5.6 26
|
||||
02 Apr 2002 2.5.5 26
|
||||
13 Mar 2002 2.5.4 26
|
||||
11 Mar 2002 2.5.3 26
|
||||
26 Jan 2002 2.5.2 11 Jan 2002 26
|
||||
03 Jan 2002 2.5.1 25
|
||||
30 Nov 2001 2.5.0 23 Aug 2001 25
|
||||
06 Sep 2000 2.4.6 24
|
||||
19 Aug 2000 2.4.5 24
|
||||
29 Jul 2000 2.4.4 24
|
||||
09 Apr 2000 2.4.3 24
|
||||
30 Mar 2000 2.4.2 24
|
||||
30 Jan 2000 2.4.1 29 Jan 2000 24
|
||||
29 Jan 2000 2.4.0 28 Jan 2000 23
|
||||
25 Jan 2000 2.3.3 23 Jan 2000 22
|
||||
08 Nov 1999 2.3.2 26 Jun 1999 21
|
||||
06 Apr 1999 2.3.1 20
|
||||
15 Mar 1999 2.3.0 15 Mar 1999 20
|
||||
25 Nov 1998 2.2.1 19
|
||||
03 Nov 1998 2.2.0 19
|
||||
09 Sep 1998 2.1.1 19
|
||||
20 Jul 1998 2.1.0 19
|
||||
17 Jul 1998 2.0.19 19
|
||||
18 Jun 1998 2.0.17 19
|
||||
01 Jun 1998 2.0.16 19
|
||||
27 May 1998 2.0.13 27 May 1998 19
|
||||
26 May 1998 2.0.12 18
|
||||
22 May 1998 2.0.11 18
|
||||
18 May 1998 2.0.9 18 May 1998 18
|
||||
17 May 1998 2.0.8 17
|
||||
15 May 1998 2.0.1 17
|
||||
14 May 1998 2.0.0 17
|
||||
17 Apr 1998 1.7.4 17
|
||||
13 Apr 1998 1.7.3 17
|
||||
05 Apr 1998 1.7.2 17
|
||||
26 Mar 1998 1.7.1 17
|
||||
26 Mar 1998 1.7.0 26 Mar 1998 17 (MAX=30)
|
||||
13 Jan 1998 1.6.9 13 Jan 1998 15 (MAX=20)
|
||||
DATE RELEASE PROTOCOL
|
||||
2003/01/26 20:11:16 release-2-5-6 26
|
||||
2002/02/23 00:17:50 release-2-5-3 26
|
||||
2002/01/25 23:00:21 release-2-5-2 26
|
||||
2001/12/18 06:47:40 release-2-5-1 25
|
||||
release-2-4-6 24
|
||||
2000/08/16 08:34:18 release-2-4-5 24
|
||||
2000/07/29 04:52:05 release-2-4-4 24
|
||||
2000/03/30 14:15:00 release-2-4-2 24
|
||||
2000/01/29 23:49:36 release-2-4-1 24
|
||||
2000/01/29 02:56:37 release-2-4-0 23
|
||||
release-2-3-3 21
|
||||
1999/06/26 01:06:38 release-2-3-2 21
|
||||
release-2-3-1 20
|
||||
1999/03/15 21:17:59 release-2-3-0 20
|
||||
1998/11/15 01:21:42 release-2-2-1 19
|
||||
1998/11/03 07:08:28 release-2-2-0 19
|
||||
1998/09/09 06:31:14 release-2-1-1 19
|
||||
1998/07/17 14:43:05 release-2-0-19 19
|
||||
1998/06/18 12:17:24 release-2-0-18 19
|
||||
1998/06/18 09:51:56 release-2-0-17 19
|
||||
1998/06/01 03:42:22 release-2-0-16 19
|
||||
1998/05/27 13:47:34 release-2-0-13 19
|
||||
1998/05/26 14:19:00 release-2-0-12 18
|
||||
1998/05/21 05:55:33 release-2-0-11 18
|
||||
1998/05/18 08:20:34 release-2-0-9 18
|
||||
1998/05/17 05:56:33 release-2-0-8 17
|
||||
1998/05/15 07:34:21 release-2-0-2 17
|
||||
1998/05/13 15:44:11 release-2-0-0 17
|
||||
1998/04/17 06:07:26 release-1-7-4 17
|
||||
1998/04/05 06:43:55 release-1-7-2 17
|
||||
1998/03/26 04:18:57 release-1-7-0 17 MAX=30
|
||||
1998/01/13 15:57:32 release-1-6-9 15 MAX=20
|
||||
1997/12/17 11:07:30 release-1-6-7 14
|
||||
1997/12/15 18:36:21 release-1-6-4 14
|
||||
|
||||
* DATE OF COMMIT is the date the protocol change was committed to CVS.
|
||||
* DATE OF COMMIT is the date the protocl change was committed
|
||||
to cvs, not the release date.
|
||||
|
||||
11
acconfig.h
Normal file
11
acconfig.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#undef ino_t
|
||||
#undef HAVE_CONNECT
|
||||
#undef HAVE_SHORT_INO_T
|
||||
#undef HAVE_GETOPT_LONG
|
||||
#undef REPLACE_INET_NTOA
|
||||
#undef REPLACE_INET_ATON
|
||||
#undef HAVE_GETTIMEOFDAY_TZ
|
||||
#undef ENABLE_IPV6
|
||||
#undef HAVE_SOCKADDR_LEN
|
||||
#undef HAVE_SOCKADDR_IN6_SCOPE_ID
|
||||
#undef HAVE_SOCKETPAIR
|
||||
@@ -24,7 +24,7 @@
|
||||
encode a buffer using base64 - simple and slow algorithm. null terminates
|
||||
the result.
|
||||
***************************************************************************/
|
||||
void base64_encode(char *buf, int len, char *out)
|
||||
static void base64_encode(char *buf, int len, char *out)
|
||||
{
|
||||
char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
int bit_offset, byte_offset, idx, i;
|
||||
@@ -33,7 +33,7 @@ void base64_encode(char *buf, int len, char *out)
|
||||
|
||||
memset(out, 0, bytes+1);
|
||||
|
||||
for (i = 0; i < bytes; i++) {
|
||||
for (i=0;i<bytes;i++) {
|
||||
byte_offset = (i*6)/8;
|
||||
bit_offset = (i*6)%8;
|
||||
if (bit_offset < 3) {
|
||||
@@ -269,8 +269,7 @@ void auth_client(int fd, char *user, char *challenge)
|
||||
char pass2[30];
|
||||
extern char *password_file;
|
||||
|
||||
if (!user || !*user)
|
||||
user = "nobody";
|
||||
if (!user || !*user) return;
|
||||
|
||||
if (!(pass=getpassf(password_file)) && !(pass=getenv("RSYNC_PASSWORD"))) {
|
||||
/* XXX: cyeoh says that getpass is deprecated, because
|
||||
|
||||
262
backup.c
262
backup.c
@@ -1,16 +1,16 @@
|
||||
/*
|
||||
/*
|
||||
Copyright (C) Andrew Tridgell 1999
|
||||
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
@@ -23,8 +23,6 @@
|
||||
extern int verbose;
|
||||
extern int backup_suffix_len;
|
||||
extern int backup_dir_len;
|
||||
extern unsigned int backup_dir_remainder;
|
||||
extern char backup_dir_buf[MAXPATHLEN];
|
||||
extern char *backup_suffix;
|
||||
extern char *backup_dir;
|
||||
|
||||
@@ -32,19 +30,17 @@ extern int am_root;
|
||||
extern int preserve_devices;
|
||||
extern int preserve_links;
|
||||
extern int preserve_hard_links;
|
||||
extern int orig_umask;
|
||||
|
||||
/* simple backup creates a backup with a suffix in the same directory */
|
||||
static int make_simple_backup(char *fname)
|
||||
{
|
||||
char fnamebak[MAXPATHLEN];
|
||||
|
||||
if (stringjoin(fnamebak, sizeof fnamebak, fname, backup_suffix, NULL)
|
||||
>= sizeof fnamebak) {
|
||||
if (strlen(fname) + backup_suffix_len > MAXPATHLEN-1) {
|
||||
rprintf(FERROR, "backup filename too long\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
snprintf(fnamebak, sizeof(fnamebak), "%s%s", fname, backup_suffix);
|
||||
if (do_rename(fname, fnamebak) != 0) {
|
||||
/* cygwin (at least version b19) reports EINVAL */
|
||||
if (errno != ENOENT && errno != EINVAL) {
|
||||
@@ -58,99 +54,151 @@ static int make_simple_backup(char *fname)
|
||||
}
|
||||
|
||||
|
||||
/* recursively make a directory path */
|
||||
static int make_dir(char *name, int mask)
|
||||
{
|
||||
char newdir [MAXPATHLEN];
|
||||
char *p, *d;
|
||||
|
||||
/* copy pathname over, look for last '/' */
|
||||
for (p = d = newdir; *name; *d++ = *name++)
|
||||
if (*name == '/')
|
||||
p = d;
|
||||
if (p == newdir)
|
||||
return 0;
|
||||
*p = 0;
|
||||
|
||||
/* make the new directory, if that fails then make its parent */
|
||||
while (do_mkdir (newdir, mask) != 0)
|
||||
if ((errno != ENOENT) || !make_dir (newdir, mask))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
} /* make_dir */
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
Create a directory given an absolute path, perms based upon another directory
|
||||
path
|
||||
****************************************************************************/
|
||||
static int make_bak_dir(char *fullpath)
|
||||
static int make_bak_dir(char *fname, char *bak_path)
|
||||
{
|
||||
STRUCT_STAT st;
|
||||
char *rel = fullpath + backup_dir_len;
|
||||
char *end = rel + strlen(rel);
|
||||
char *p = end;
|
||||
STRUCT_STAT *st2;
|
||||
char fullpath[MAXPATHLEN];
|
||||
extern int orig_umask;
|
||||
char *p;
|
||||
char *q;
|
||||
|
||||
while (strncmp(fullpath, "./", 2) == 0)
|
||||
fullpath += 2;
|
||||
while(strncmp(bak_path, "./", 2) == 0) bak_path += 2;
|
||||
|
||||
/* Try to find an existing dir, starting from the deepest dir. */
|
||||
while (1) {
|
||||
if (--p == fullpath) {
|
||||
p += strlen(p);
|
||||
goto failure;
|
||||
}
|
||||
if (*p == '/') {
|
||||
*p = '\0';
|
||||
if (do_mkdir(fullpath, 0777 & ~orig_umask) == 0)
|
||||
break;
|
||||
if (errno != ENOENT) {
|
||||
rprintf(FERROR,
|
||||
"make_bak_dir mkdir %s failed: %s\n",
|
||||
full_fname(fullpath), strerror(errno));
|
||||
goto failure;
|
||||
}
|
||||
}
|
||||
if(bak_path[strlen(bak_path)-1] != '/') {
|
||||
snprintf(fullpath, sizeof(fullpath), "%s/", bak_path);
|
||||
} else {
|
||||
snprintf(fullpath, sizeof(fullpath), "%s", bak_path);
|
||||
}
|
||||
p = fullpath;
|
||||
q = &fullpath[strlen(fullpath)]; /* End of bak_path string */
|
||||
strcat(fullpath, fname);
|
||||
|
||||
/* Make all the dirs that we didn't find on the way here. */
|
||||
while (1) {
|
||||
if (p >= rel) {
|
||||
/* Try to transfer the directory settings of the
|
||||
* actual dir that the files are coming from. */
|
||||
if (do_lstat(rel, &st) != 0) {
|
||||
rprintf(FERROR,
|
||||
"make_bak_dir stat %s failed: %s\n",
|
||||
full_fname(rel), strerror(errno));
|
||||
} else {
|
||||
set_modtime(fullpath, st.st_mtime);
|
||||
do_lchown(fullpath, st.st_uid, st.st_gid);
|
||||
do_chmod(fullpath, st.st_mode);
|
||||
/* Make the directories */
|
||||
while ((p = strchr(p, '/'))) {
|
||||
*p = 0;
|
||||
if(do_lstat(fullpath, &st) != 0) {
|
||||
do_mkdir(fullpath, 0777 & ~orig_umask);
|
||||
if(p>q) {
|
||||
if(do_lstat(q, &st) != 0) {
|
||||
rprintf(FERROR, "make_bak_dir stat %s failed: %s\n",
|
||||
full_fname(fullpath), strerror(errno));
|
||||
} else {
|
||||
st2 = &st;
|
||||
set_modtime(fullpath, st2->st_mtime);
|
||||
if(do_lchown(fullpath, st2->st_uid, st2->st_gid) != 0) {
|
||||
rprintf(FERROR, "make_bak_dir chown %s failed: %s\n",
|
||||
full_fname(fullpath), strerror(errno));
|
||||
}
|
||||
if(do_chmod(fullpath, st2->st_mode) != 0) {
|
||||
rprintf(FERROR, "make_bak_dir failed to set permissions on %s: %s\n",
|
||||
full_fname(fullpath), strerror(errno));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*p = '/';
|
||||
p += strlen(p);
|
||||
if (p == end)
|
||||
break;
|
||||
if (do_mkdir(fullpath, 0777 & ~orig_umask) < 0) {
|
||||
rprintf(FERROR,
|
||||
"make_bak_dir mkdir %s failed: %s\n",
|
||||
full_fname(fullpath), strerror(errno));
|
||||
goto failure;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
return 0;
|
||||
|
||||
failure:
|
||||
while (p != end) {
|
||||
*p = '/';
|
||||
p += strlen(p);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* robustly move a file, creating new directory structures if necessary */
|
||||
static int robust_move(char *src, char *dst)
|
||||
{
|
||||
if (robust_rename(src, dst, 0755) < 0 && (errno != ENOENT
|
||||
|| make_bak_dir(dst) < 0 || robust_rename(src, dst, 0755) < 0))
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
int keep_trying = 4;
|
||||
int keep_path_extfs = 0;
|
||||
int failed;
|
||||
|
||||
while (keep_trying) {
|
||||
if (keep_path_extfs) {
|
||||
failed = copy_file(src, dst, 0755);
|
||||
if (!failed) {
|
||||
do_unlink(src);
|
||||
}
|
||||
} else {
|
||||
failed = robust_rename (src, dst);
|
||||
}
|
||||
|
||||
if (failed) {
|
||||
if (verbose > 2)
|
||||
rprintf (FERROR, "robust_move failed: %s(%d)\n",
|
||||
strerror (errno), errno);
|
||||
switch (errno) {
|
||||
/* external filesystem */
|
||||
case EXDEV:
|
||||
keep_path_extfs = 1;
|
||||
keep_trying--;
|
||||
break;
|
||||
/* no directory to write to */
|
||||
case ENOENT:
|
||||
make_dir(dst, 0700);
|
||||
keep_trying--;
|
||||
break;
|
||||
default:
|
||||
keep_trying = 0;
|
||||
} /* switch */
|
||||
} else
|
||||
keep_trying = 0;
|
||||
} /* while */
|
||||
return (!failed);
|
||||
} /* robust_move */
|
||||
|
||||
|
||||
/* If we have a --backup-dir, then we get here from make_backup().
|
||||
* We will move the file to be deleted into a parallel directory tree. */
|
||||
/* if we have a backup_dir, then we get here from make_backup().
|
||||
We will move the file to be deleted into a parallel directory tree */
|
||||
static int keep_backup(char *fname)
|
||||
{
|
||||
|
||||
static int initialised;
|
||||
|
||||
char keep_name [MAXPATHLEN];
|
||||
STRUCT_STAT st;
|
||||
struct file_struct *file;
|
||||
|
||||
int kept = 0;
|
||||
int ret_code;
|
||||
|
||||
if (!initialised) {
|
||||
if (backup_dir_len && backup_dir[backup_dir_len - 1] == '/')
|
||||
backup_dir[--backup_dir_len] = '\0';
|
||||
if (verbose > 0)
|
||||
rprintf (FINFO, "backup_dir is %s\n", backup_dir);
|
||||
initialised = 1;
|
||||
}
|
||||
|
||||
/* return if no file to keep */
|
||||
#if SUPPORT_LINKS
|
||||
if (do_lstat(fname, &st)) return 1;
|
||||
if (do_lstat (fname, &st)) return 1;
|
||||
#else
|
||||
if (do_stat(fname, &st)) return 1;
|
||||
if (do_stat (fname, &st)) return 1;
|
||||
#endif
|
||||
|
||||
file = make_file(fname, NULL, NO_EXCLUDES);
|
||||
@@ -159,24 +207,24 @@ static int keep_backup(char *fname)
|
||||
if (!file) return 1;
|
||||
|
||||
/* make a complete pathname for backup file */
|
||||
if (stringjoin(backup_dir_buf + backup_dir_len, backup_dir_remainder,
|
||||
fname, backup_suffix, NULL) >= backup_dir_remainder) {
|
||||
rprintf(FERROR, "keep_backup filename too long\n");
|
||||
if (backup_dir_len+strlen(fname)+backup_suffix_len > MAXPATHLEN-1) {
|
||||
rprintf (FERROR, "keep_backup filename too long\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
snprintf(keep_name, sizeof (keep_name), "%s/%s%s",
|
||||
backup_dir, fname, backup_suffix);
|
||||
|
||||
#ifdef HAVE_MKNOD
|
||||
/* Check to see if this is a device file, or link */
|
||||
if (IS_DEVICE(file->mode)) {
|
||||
if (am_root && preserve_devices) {
|
||||
make_bak_dir(backup_dir_buf);
|
||||
if (do_mknod(backup_dir_buf, file->mode, file->u.rdev) != 0) {
|
||||
if(IS_DEVICE(file->mode)) {
|
||||
if(am_root && preserve_devices) {
|
||||
make_bak_dir(fname, backup_dir);
|
||||
if(do_mknod(keep_name, file->mode, file->rdev) != 0) {
|
||||
rprintf(FERROR, "mknod %s failed: %s\n",
|
||||
full_fname(backup_dir_buf), strerror(errno));
|
||||
} else if (verbose > 2) {
|
||||
rprintf(FINFO,
|
||||
"make_backup: DEVICE %s successful.\n",
|
||||
fname);
|
||||
full_fname(keep_name), strerror(errno));
|
||||
} else if(verbose>2) {
|
||||
rprintf(FINFO, "make_backup: DEVICE %s successful.\n", fname);
|
||||
}
|
||||
}
|
||||
kept = 1;
|
||||
@@ -184,13 +232,13 @@ static int keep_backup(char *fname)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!kept && S_ISDIR(file->mode)) {
|
||||
if(!kept && S_ISDIR(file->mode)) {
|
||||
/* make an empty directory */
|
||||
make_bak_dir(backup_dir_buf);
|
||||
do_mkdir(backup_dir_buf, file->mode);
|
||||
make_bak_dir(fname, backup_dir);
|
||||
do_mkdir(keep_name, file->mode);
|
||||
ret_code = do_rmdir(fname);
|
||||
|
||||
if (verbose > 2) {
|
||||
if(verbose>2) {
|
||||
rprintf(FINFO, "make_backup: RMDIR %s returns %i\n",
|
||||
full_fname(fname), ret_code);
|
||||
}
|
||||
@@ -198,50 +246,56 @@ static int keep_backup(char *fname)
|
||||
}
|
||||
|
||||
#if SUPPORT_LINKS
|
||||
if (!kept && preserve_links && S_ISLNK(file->mode)) {
|
||||
if(!kept && preserve_links && S_ISLNK(file->mode)) {
|
||||
extern int safe_symlinks;
|
||||
if (safe_symlinks && unsafe_symlink(file->u.link, backup_dir_buf)) {
|
||||
if (safe_symlinks && unsafe_symlink(file->link, keep_name)) {
|
||||
if (verbose) {
|
||||
rprintf(FINFO, "ignoring unsafe symlink %s -> %s\n",
|
||||
full_fname(backup_dir_buf), file->u.link);
|
||||
full_fname(keep_name), file->link);
|
||||
}
|
||||
kept = 1;
|
||||
}
|
||||
make_bak_dir(backup_dir_buf);
|
||||
if (do_symlink(file->u.link, backup_dir_buf) != 0) {
|
||||
make_bak_dir(fname, backup_dir);
|
||||
if(do_symlink(file->link, keep_name) != 0) {
|
||||
rprintf(FERROR, "link %s -> %s : %s\n",
|
||||
full_fname(backup_dir_buf), file->u.link, strerror(errno));
|
||||
full_fname(keep_name), file->link, strerror(errno));
|
||||
}
|
||||
do_unlink(fname);
|
||||
kept = 1;
|
||||
}
|
||||
#endif
|
||||
if(!kept && preserve_hard_links && check_hard_link(file)) {
|
||||
if(verbose > 1)
|
||||
rprintf(FINFO, "%s is a hard link\n", f_name(file));
|
||||
}
|
||||
|
||||
if (!kept && !S_ISREG(file->mode)) {
|
||||
if(!kept && !S_ISREG(file->mode)) {
|
||||
rprintf(FINFO, "make_bak: skipping non-regular file %s\n",
|
||||
fname);
|
||||
fname);
|
||||
}
|
||||
|
||||
/* move to keep tree if a file */
|
||||
if (!kept) {
|
||||
if (robust_move(fname, backup_dir_buf) != 0) {
|
||||
if(!kept) {
|
||||
if (!robust_move (fname, keep_name)) {
|
||||
rprintf(FERROR, "keep_backup failed: %s -> \"%s\": %s\n",
|
||||
full_fname(fname), backup_dir_buf, strerror(errno));
|
||||
full_fname(fname), keep_name, strerror(errno));
|
||||
}
|
||||
}
|
||||
set_perms(backup_dir_buf, file, NULL, 0);
|
||||
free(file);
|
||||
set_perms (keep_name, file, NULL, 0);
|
||||
free_file (file);
|
||||
free (file);
|
||||
|
||||
if (verbose > 1)
|
||||
rprintf(FINFO, "keep_backup %s -> %s\n", fname, backup_dir_buf);
|
||||
rprintf (FINFO, "keep_backup %s -> %s\n", fname, keep_name);
|
||||
return 1;
|
||||
}
|
||||
} /* keep_backup */
|
||||
|
||||
|
||||
/* main backup switch routine */
|
||||
int make_backup(char *fname)
|
||||
{
|
||||
if (backup_dir)
|
||||
return keep_backup(fname);
|
||||
return make_simple_backup(fname);
|
||||
return (keep_backup(fname));
|
||||
else
|
||||
return (make_simple_backup(fname));
|
||||
}
|
||||
|
||||
530
batch.c
530
batch.c
@@ -1,5 +1,5 @@
|
||||
/* -*- c-file-style: "linux" -*-
|
||||
|
||||
|
||||
Weiss 1/1999
|
||||
Batch utilities for rsync.
|
||||
|
||||
@@ -9,9 +9,6 @@
|
||||
#include <time.h>
|
||||
|
||||
extern char *batch_prefix;
|
||||
extern int csum_length;
|
||||
extern int protocol_version;
|
||||
extern struct stats stats;
|
||||
|
||||
struct file_list *batch_flist;
|
||||
|
||||
@@ -20,60 +17,122 @@ static char rsync_csums_file[] = ".rsync_csums";
|
||||
static char rsync_delta_file[] = ".rsync_delta";
|
||||
static char rsync_argvs_file[] = ".rsync_argvs";
|
||||
|
||||
static int f_csums = -1;
|
||||
static int f_delta = -1;
|
||||
static int fdb;
|
||||
static int fdb_delta;
|
||||
static int fdb_open;
|
||||
static int fdb_close;
|
||||
|
||||
void write_batch_flist_info(int flist_count, struct file_struct **files)
|
||||
void write_batch_flist_file(char *buff, int bytes_to_write)
|
||||
{
|
||||
char filename[MAXPATHLEN];
|
||||
int i, f, save_pv;
|
||||
int64 save_written;
|
||||
|
||||
stringjoin(filename, sizeof filename,
|
||||
batch_prefix, rsync_flist_file, NULL);
|
||||
if (fdb_open) {
|
||||
/* Set up file extension */
|
||||
strlcpy(filename, batch_prefix, sizeof(filename));
|
||||
strlcat(filename, rsync_flist_file, sizeof(filename));
|
||||
|
||||
f = do_open(filename, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
|
||||
if (f < 0) {
|
||||
rprintf(FERROR, "Batch file %s open error: %s\n",
|
||||
filename, strerror(errno));
|
||||
/*
|
||||
* Open batch flist file for writing;
|
||||
* create it if it doesn't exist
|
||||
*/
|
||||
fdb = do_open(filename, O_WRONLY | O_CREAT | O_TRUNC,
|
||||
S_IREAD | S_IWRITE);
|
||||
if (fdb == -1) {
|
||||
rprintf(FERROR, "Batch file %s open error: %s\n",
|
||||
filename, strerror(errno));
|
||||
close(fdb);
|
||||
exit_cleanup(1);
|
||||
}
|
||||
fdb_open = 0;
|
||||
}
|
||||
|
||||
/* Write buffer to batch flist file */
|
||||
|
||||
if (write(fdb, buff, bytes_to_write) == -1) {
|
||||
rprintf(FERROR, "Batch file %s write error: %s\n",
|
||||
filename, strerror(errno));
|
||||
close(fdb);
|
||||
exit_cleanup(1);
|
||||
}
|
||||
|
||||
save_written = stats.total_written;
|
||||
save_pv = protocol_version;
|
||||
protocol_version = PROTOCOL_VERSION;
|
||||
write_int(f, protocol_version);
|
||||
write_int(f, flist_count);
|
||||
|
||||
for (i = 0; i < flist_count; i++) {
|
||||
send_file_entry(files[i], f,
|
||||
files[i]->flags & FLAG_TOP_DIR ? XMIT_TOP_DIR : 0);
|
||||
if (fdb_close) {
|
||||
close(fdb);
|
||||
}
|
||||
send_file_entry(NULL, f, 0);
|
||||
|
||||
protocol_version = save_pv;
|
||||
stats.total_written = save_written;
|
||||
|
||||
close(f);
|
||||
}
|
||||
|
||||
void write_batch_flist_info(int flist_count, struct file_struct **fptr)
|
||||
{
|
||||
int i;
|
||||
int bytes_to_write;
|
||||
|
||||
/* Write flist info to batch file */
|
||||
|
||||
bytes_to_write =
|
||||
sizeof(unsigned) +
|
||||
sizeof(time_t) +
|
||||
sizeof(OFF_T) +
|
||||
sizeof(mode_t) +
|
||||
sizeof(INO64_T) +
|
||||
sizeof(DEV64_T) +
|
||||
sizeof(DEV64_T) +
|
||||
sizeof(uid_t) +
|
||||
sizeof(gid_t);
|
||||
|
||||
fdb_open = 1;
|
||||
fdb_close = 0;
|
||||
|
||||
for (i = 0; i < flist_count; i++) {
|
||||
write_batch_flist_file((char *) fptr[i], bytes_to_write);
|
||||
write_char_bufs(fptr[i]->basename);
|
||||
write_char_bufs(fptr[i]->dirname);
|
||||
write_char_bufs(fptr[i]->basedir);
|
||||
write_char_bufs(fptr[i]->link);
|
||||
if (i == flist_count - 1) {
|
||||
fdb_close = 1;
|
||||
}
|
||||
write_char_bufs(fptr[i]->sum);
|
||||
}
|
||||
}
|
||||
|
||||
void write_char_bufs(char *buf)
|
||||
{
|
||||
/* Write the size of the string which will follow */
|
||||
|
||||
char b[4];
|
||||
|
||||
SIVAL(b, 0, buf != NULL ? strlen(buf) : 0);
|
||||
|
||||
write_batch_flist_file(b, sizeof(int));
|
||||
|
||||
/* Write the string if there is one */
|
||||
|
||||
if (buf != NULL) {
|
||||
write_batch_flist_file(buf, strlen(buf));
|
||||
}
|
||||
}
|
||||
|
||||
void write_batch_argvs_file(int argc, char *argv[])
|
||||
{
|
||||
int f;
|
||||
int fdb;
|
||||
int i;
|
||||
char buff[256]; /* XXX */
|
||||
char buff2[MAXPATHLEN + 6];
|
||||
char filename[MAXPATHLEN];
|
||||
|
||||
stringjoin(filename, sizeof filename,
|
||||
batch_prefix, rsync_argvs_file, NULL);
|
||||
/* Set up file extension */
|
||||
strlcpy(filename, batch_prefix, sizeof(filename));
|
||||
strlcat(filename, rsync_argvs_file, sizeof(filename));
|
||||
|
||||
f = do_open(filename, O_WRONLY | O_CREAT | O_TRUNC,
|
||||
S_IRUSR | S_IWUSR | S_IEXEC);
|
||||
if (f < 0) {
|
||||
/*
|
||||
* Open batch argvs file for writing;
|
||||
* create it if it doesn't exist
|
||||
*/
|
||||
fdb = do_open(filename, O_WRONLY | O_CREAT | O_TRUNC,
|
||||
S_IREAD | S_IWRITE | S_IEXEC);
|
||||
if (fdb == -1) {
|
||||
rprintf(FERROR, "Batch file %s open error: %s\n",
|
||||
filename, strerror(errno));
|
||||
filename, strerror(errno));
|
||||
close(fdb);
|
||||
exit_cleanup(1);
|
||||
}
|
||||
buff[0] = '\0';
|
||||
@@ -82,135 +141,281 @@ void write_batch_argvs_file(int argc, char *argv[])
|
||||
|
||||
for (i = 0; i < argc; ++i) {
|
||||
if (i == argc - 2) /* Skip source directory on cmdline */
|
||||
continue;
|
||||
continue;
|
||||
/*
|
||||
* FIXME:
|
||||
* I think directly manipulating argv[] is probably bogus
|
||||
*/
|
||||
if (!strncmp(argv[i], "--write-batch",
|
||||
strlen("--write-batch"))) {
|
||||
strlen("--write-batch"))) {
|
||||
/* Safer to change it here than script */
|
||||
/*
|
||||
* Change to --read-batch=prefix
|
||||
* to get ready for remote
|
||||
*/
|
||||
strlcat(buff, "--read-batch=", sizeof buff);
|
||||
strlcat(buff, batch_prefix, sizeof buff);
|
||||
strlcat(buff, "--read-batch=", sizeof(buff));
|
||||
strlcat(buff, batch_prefix, sizeof(buff));
|
||||
} else
|
||||
if (i == argc - 1) {
|
||||
snprintf(buff2, sizeof buff2, "${1:-%s}", argv[i]);
|
||||
strlcat(buff, buff2, sizeof buff);
|
||||
snprintf(buff2, sizeof(buff2), "${1:-%s}", argv[i]);
|
||||
strlcat(buff, buff2, sizeof(buff));
|
||||
}
|
||||
else {
|
||||
strlcat(buff, argv[i], sizeof buff);
|
||||
strlcat(buff, argv[i], sizeof(buff));
|
||||
}
|
||||
|
||||
if (i < (argc - 1)) {
|
||||
strlcat(buff, " ", sizeof buff);
|
||||
strlcat(buff, " ", sizeof(buff));
|
||||
}
|
||||
}
|
||||
strlcat(buff, "\n", sizeof buff);
|
||||
if (!write(f, buff, strlen(buff))) {
|
||||
strlcat(buff, "\n", sizeof(buff));
|
||||
if (!write(fdb, buff, strlen(buff))) {
|
||||
rprintf(FERROR, "Batch file %s write error: %s\n",
|
||||
filename, strerror(errno));
|
||||
close(f);
|
||||
filename, strerror(errno));
|
||||
close(fdb);
|
||||
exit_cleanup(1);
|
||||
}
|
||||
close(f);
|
||||
close(fdb);
|
||||
}
|
||||
|
||||
struct file_list *create_flist_from_batch(void)
|
||||
{
|
||||
char filename[MAXPATHLEN];
|
||||
unsigned short flags;
|
||||
int i, f, save_pv;
|
||||
int64 save_read;
|
||||
unsigned char flags;
|
||||
|
||||
stringjoin(filename, sizeof filename,
|
||||
batch_prefix, rsync_flist_file, NULL);
|
||||
fdb_open = 1;
|
||||
fdb_close = 0;
|
||||
|
||||
f = do_open(filename, O_RDONLY, 0);
|
||||
if (f < 0) {
|
||||
rprintf(FERROR, "Batch file %s open error: %s\n",
|
||||
filename, strerror(errno));
|
||||
exit_cleanup(1);
|
||||
batch_flist = new(struct file_list);
|
||||
if (!batch_flist) {
|
||||
out_of_memory("create_flist_from_batch");
|
||||
}
|
||||
batch_flist->count = 0;
|
||||
batch_flist->malloced = 1000;
|
||||
batch_flist->files = new_array(struct file_struct *,
|
||||
batch_flist->malloced);
|
||||
if (!batch_flist->files) {
|
||||
out_of_memory("create_flist_from_batch");
|
||||
}
|
||||
|
||||
batch_flist = flist_new(WITH_HLINK, "create_flist_from_batch");
|
||||
for (flags = read_batch_flags(); flags; flags = read_batch_flags()) {
|
||||
|
||||
save_read = stats.total_read;
|
||||
save_pv = protocol_version;
|
||||
protocol_version = read_int(f);
|
||||
int i = batch_flist->count;
|
||||
|
||||
batch_flist->count = read_int(f);
|
||||
flist_expand(batch_flist);
|
||||
if (i >= batch_flist->malloced) {
|
||||
if (batch_flist->malloced < 1000)
|
||||
batch_flist->malloced += 1000;
|
||||
else
|
||||
batch_flist->malloced *= 2;
|
||||
batch_flist->files
|
||||
= realloc_array(batch_flist->files,
|
||||
struct file_struct *,
|
||||
batch_flist->malloced);
|
||||
if (!batch_flist->files)
|
||||
out_of_memory("create_flist_from_batch");
|
||||
}
|
||||
read_batch_flist_info(&batch_flist->files[i]);
|
||||
batch_flist->files[i]->flags = flags;
|
||||
|
||||
for (i = 0; (flags = read_byte(f)) != 0; i++) {
|
||||
if (protocol_version >= 28 && (flags & XMIT_EXTENDED_FLAGS))
|
||||
flags |= read_byte(f) << 8;
|
||||
receive_file_entry(&batch_flist->files[i], flags, batch_flist, f);
|
||||
batch_flist->count++;
|
||||
}
|
||||
receive_file_entry(NULL, 0, NULL, 0); /* Signal that we're done. */
|
||||
|
||||
protocol_version = save_pv;
|
||||
stats.total_read = save_read;
|
||||
|
||||
return batch_flist;
|
||||
}
|
||||
|
||||
int read_batch_flist_file(char *buff, int len)
|
||||
{
|
||||
int bytes_read;
|
||||
char filename[MAXPATHLEN];
|
||||
|
||||
if (fdb_open) {
|
||||
/* Set up file extension */
|
||||
strlcpy(filename, batch_prefix, sizeof(filename));
|
||||
strlcat(filename, rsync_flist_file, sizeof(filename));
|
||||
|
||||
/* Open batch flist file for reading */
|
||||
fdb = do_open(filename, O_RDONLY, 0);
|
||||
if (fdb == -1) {
|
||||
rprintf(FERROR, "Batch file %s open error: %s\n",
|
||||
filename, strerror(errno));
|
||||
close(fdb);
|
||||
exit_cleanup(1);
|
||||
}
|
||||
fdb_open = 0;
|
||||
}
|
||||
|
||||
/* Read flist batch file */
|
||||
|
||||
switch (bytes_read = read(fdb, buff, len)) {
|
||||
case -1:
|
||||
rprintf(FERROR, "Batch file %s read error: %s\n",
|
||||
filename, strerror(errno));
|
||||
close(fdb);
|
||||
exit_cleanup(1);
|
||||
break;
|
||||
case 0: /* EOF */
|
||||
close(fdb);
|
||||
}
|
||||
|
||||
return bytes_read;
|
||||
}
|
||||
|
||||
unsigned char read_batch_flags(void)
|
||||
{
|
||||
int flags;
|
||||
|
||||
if (read_batch_flist_file((char *) &flags, 4)) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void read_batch_flist_info(struct file_struct **fptr)
|
||||
{
|
||||
int int_str_len;
|
||||
char char_str_len[4];
|
||||
char buff[256];
|
||||
struct file_struct *file;
|
||||
|
||||
file = new(struct file_struct);
|
||||
if (!file)
|
||||
out_of_memory("read_batch_flist_info");
|
||||
memset((char *) file, 0, sizeof(*file));
|
||||
|
||||
*fptr = file;
|
||||
|
||||
/*
|
||||
* Keep these in sync with bytes_to_write assignment
|
||||
* in write_batch_flist_info()
|
||||
*/
|
||||
read_batch_flist_file((char *) &file->modtime, sizeof(time_t));
|
||||
read_batch_flist_file((char *) &file->length, sizeof(OFF_T));
|
||||
read_batch_flist_file((char *) &file->mode, sizeof(mode_t));
|
||||
read_batch_flist_file((char *) &file->inode, sizeof(INO64_T));
|
||||
read_batch_flist_file((char *) &file->dev, sizeof(DEV64_T));
|
||||
read_batch_flist_file((char *) &file->rdev, sizeof(DEV64_T));
|
||||
read_batch_flist_file((char *) &file->uid, sizeof(uid_t));
|
||||
read_batch_flist_file((char *) &file->gid, sizeof(gid_t));
|
||||
read_batch_flist_file(char_str_len, sizeof(char_str_len));
|
||||
int_str_len = IVAL(char_str_len, 0);
|
||||
if (int_str_len > 0) {
|
||||
read_batch_flist_file(buff, int_str_len);
|
||||
buff[int_str_len] = '\0';
|
||||
file->basename = strdup(buff);
|
||||
} else {
|
||||
file->basename = NULL;
|
||||
}
|
||||
|
||||
read_batch_flist_file(char_str_len, sizeof(char_str_len));
|
||||
int_str_len = IVAL(char_str_len, 0);
|
||||
if (int_str_len > 0) {
|
||||
read_batch_flist_file(buff, int_str_len);
|
||||
buff[int_str_len] = '\0';
|
||||
file[0].dirname = strdup(buff);
|
||||
} else {
|
||||
file[0].dirname = NULL;
|
||||
}
|
||||
|
||||
read_batch_flist_file(char_str_len, sizeof(char_str_len));
|
||||
int_str_len = IVAL(char_str_len, 0);
|
||||
if (int_str_len > 0) {
|
||||
read_batch_flist_file(buff, int_str_len);
|
||||
buff[int_str_len] = '\0';
|
||||
file[0].basedir = strdup(buff);
|
||||
} else {
|
||||
file[0].basedir = NULL;
|
||||
}
|
||||
|
||||
read_batch_flist_file(char_str_len, sizeof(char_str_len));
|
||||
int_str_len = IVAL(char_str_len, 0);
|
||||
if (int_str_len > 0) {
|
||||
read_batch_flist_file(buff, int_str_len);
|
||||
buff[int_str_len] = '\0';
|
||||
file[0].link = strdup(buff);
|
||||
} else {
|
||||
file[0].link = NULL;
|
||||
}
|
||||
|
||||
read_batch_flist_file(char_str_len, sizeof(char_str_len));
|
||||
int_str_len = IVAL(char_str_len, 0);
|
||||
if (int_str_len > 0) {
|
||||
read_batch_flist_file(buff, int_str_len);
|
||||
buff[int_str_len] = '\0';
|
||||
file[0].sum = strdup(buff);
|
||||
} else {
|
||||
file[0].sum = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void write_batch_csums_file(void *buff, int bytes_to_write)
|
||||
{
|
||||
if (write(f_csums, buff, bytes_to_write) < 0) {
|
||||
rprintf(FERROR, "Batch file write error: %s\n",
|
||||
strerror(errno));
|
||||
close(f_csums);
|
||||
static int fdb_open = 1;
|
||||
char filename[MAXPATHLEN];
|
||||
|
||||
if (fdb_open) {
|
||||
/* Set up file extension */
|
||||
strlcpy(filename, batch_prefix, sizeof(filename));
|
||||
strlcat(filename, rsync_csums_file, sizeof(filename));
|
||||
|
||||
/*
|
||||
* Open batch csums file for writing;
|
||||
* create it if it doesn't exist
|
||||
*/
|
||||
fdb = do_open(filename, O_WRONLY | O_CREAT | O_TRUNC,
|
||||
S_IREAD | S_IWRITE);
|
||||
if (fdb == -1) {
|
||||
rprintf(FERROR, "Batch file %s open error: %s\n",
|
||||
filename, strerror(errno));
|
||||
close(fdb);
|
||||
exit_cleanup(1);
|
||||
}
|
||||
fdb_open = 0;
|
||||
}
|
||||
|
||||
/* Write buffer to batch csums file */
|
||||
|
||||
if (write(fdb, buff, bytes_to_write) == -1) {
|
||||
rprintf(FERROR, "Batch file %s write error: %s\n",
|
||||
filename, strerror(errno));
|
||||
close(fdb);
|
||||
exit_cleanup(1);
|
||||
}
|
||||
}
|
||||
|
||||
void close_batch_csums_file(void)
|
||||
{
|
||||
close(f_csums);
|
||||
f_csums = -1;
|
||||
close(fdb);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Write csum info to batch file
|
||||
* Write csum info to batch file
|
||||
*
|
||||
* @todo This will break if s->count is ever larger than maxint. The
|
||||
* batch code should probably be changed to consistently use the
|
||||
* variable-length integer routines, which is probably a compatible
|
||||
* change.
|
||||
**/
|
||||
void write_batch_csum_info(int *flist_entry, struct sum_struct *s)
|
||||
void write_batch_csum_info(int *flist_entry, int flist_count,
|
||||
struct sum_struct *s)
|
||||
{
|
||||
size_t i;
|
||||
int int_count;
|
||||
char filename[MAXPATHLEN];
|
||||
extern int csum_length;
|
||||
|
||||
if (f_csums < 0) {
|
||||
stringjoin(filename, sizeof filename,
|
||||
batch_prefix, rsync_csums_file, NULL);
|
||||
fdb_open = 1;
|
||||
|
||||
f_csums = do_open(filename, O_WRONLY | O_CREAT | O_TRUNC,
|
||||
S_IRUSR | S_IWUSR);
|
||||
if (f_csums < 0) {
|
||||
rprintf(FERROR, "Batch file %s open error: %s\n",
|
||||
filename, strerror(errno));
|
||||
close(f_csums);
|
||||
exit_cleanup(1);
|
||||
}
|
||||
}
|
||||
|
||||
write_batch_csums_file(flist_entry, sizeof (int));
|
||||
write_batch_csums_file(flist_entry, sizeof(int));
|
||||
int_count = s ? (int) s->count : 0;
|
||||
write_batch_csums_file(&int_count, sizeof int_count);
|
||||
|
||||
|
||||
if (s) {
|
||||
for (i = 0; i < s->count; i++) {
|
||||
write_batch_csums_file(&s->sums[i].sum1,
|
||||
sizeof (uint32));
|
||||
write_batch_csums_file(&s->sums[i].sum1, sizeof(uint32));
|
||||
if ((*flist_entry == flist_count - 1)
|
||||
&& (i == s->count - 1)) {
|
||||
fdb_close = 1;
|
||||
}
|
||||
write_batch_csums_file(s->sums[i].sum2, csum_length);
|
||||
}
|
||||
}
|
||||
@@ -218,13 +423,37 @@ void write_batch_csum_info(int *flist_entry, struct sum_struct *s)
|
||||
|
||||
int read_batch_csums_file(char *buff, int len)
|
||||
{
|
||||
static int fdb_open = 1;
|
||||
int bytes_read;
|
||||
char filename[MAXPATHLEN];
|
||||
|
||||
if ((bytes_read = read(f_csums, buff, len)) < 0) {
|
||||
rprintf(FERROR, "Batch file read error: %s\n", strerror(errno));
|
||||
close(f_csums);
|
||||
if (fdb_open) {
|
||||
/* Set up file extension */
|
||||
strlcpy(filename, batch_prefix, sizeof(filename));
|
||||
strlcat(filename, rsync_csums_file, sizeof(filename));
|
||||
|
||||
/* Open batch flist file for reading */
|
||||
fdb = do_open(filename, O_RDONLY, 0);
|
||||
if (fdb == -1) {
|
||||
rprintf(FERROR, "Batch file %s open error: %s\n",
|
||||
filename, strerror(errno));
|
||||
close(fdb);
|
||||
exit_cleanup(1);
|
||||
}
|
||||
fdb_open = 0;
|
||||
}
|
||||
|
||||
/* Read csums batch file */
|
||||
|
||||
bytes_read = read(fdb, buff, len);
|
||||
|
||||
if (bytes_read == -1) {
|
||||
rprintf(FERROR, "Batch file %s read error: %s\n",
|
||||
filename, strerror(errno));
|
||||
close(fdb);
|
||||
exit_cleanup(1);
|
||||
}
|
||||
|
||||
return bytes_read;
|
||||
}
|
||||
|
||||
@@ -236,97 +465,104 @@ void read_batch_csum_info(int flist_entry, struct sum_struct *s,
|
||||
int file_chunk_ct;
|
||||
uint32 file_sum1;
|
||||
char file_sum2[SUM_LENGTH];
|
||||
char filename[MAXPATHLEN];
|
||||
extern int csum_length;
|
||||
|
||||
if (f_csums < 0) {
|
||||
stringjoin(filename, sizeof filename,
|
||||
batch_prefix, rsync_csums_file, NULL);
|
||||
|
||||
f_csums = do_open(filename, O_RDONLY, 0);
|
||||
if (f_csums < 0) {
|
||||
rprintf(FERROR, "Batch file %s open error: %s\n",
|
||||
filename, strerror(errno));
|
||||
close(f_csums);
|
||||
exit_cleanup(1);
|
||||
}
|
||||
}
|
||||
|
||||
read_batch_csums_file((char *) &file_flist_entry, sizeof (int));
|
||||
read_batch_csums_file((char *) &file_flist_entry, sizeof(int));
|
||||
if (file_flist_entry != flist_entry) {
|
||||
rprintf(FINFO, "file_flist_entry (%d) != flist_entry (%d)\n",
|
||||
file_flist_entry, flist_entry);
|
||||
close(f_csums);
|
||||
file_flist_entry, flist_entry);
|
||||
close(fdb);
|
||||
exit_cleanup(1);
|
||||
|
||||
} else {
|
||||
read_batch_csums_file((char *) &file_chunk_ct, sizeof (int));
|
||||
read_batch_csums_file((char *) &file_chunk_ct,
|
||||
sizeof(int));
|
||||
*checksums_match = 1;
|
||||
for (i = 0; i < file_chunk_ct; i++) {
|
||||
|
||||
read_batch_csums_file((char *) &file_sum1,
|
||||
sizeof (uint32));
|
||||
sizeof(uint32));
|
||||
read_batch_csums_file(file_sum2, csum_length);
|
||||
|
||||
if ((s->sums[i].sum1 != file_sum1)
|
||||
|| memcmp(s->sums[i].sum2, file_sum2, csum_length))
|
||||
if ((s->sums[i].sum1 != file_sum1) ||
|
||||
(memcmp(s->sums[i].sum2, file_sum2, csum_length)
|
||||
!= 0)) {
|
||||
*checksums_match = 0;
|
||||
}
|
||||
} /* end for */
|
||||
}
|
||||
}
|
||||
|
||||
void write_batch_delta_file(char *buff, int bytes_to_write)
|
||||
{
|
||||
static int fdb_delta_open = 1;
|
||||
char filename[MAXPATHLEN];
|
||||
|
||||
if (f_delta < 0) {
|
||||
stringjoin(filename, sizeof filename,
|
||||
batch_prefix, rsync_delta_file, NULL);
|
||||
if (fdb_delta_open) {
|
||||
/* Set up file extension */
|
||||
strlcpy(filename, batch_prefix, sizeof(filename));
|
||||
strlcat(filename, rsync_delta_file, sizeof(filename));
|
||||
|
||||
f_delta = do_open(filename, O_WRONLY | O_CREAT | O_TRUNC,
|
||||
S_IRUSR | S_IWUSR);
|
||||
if (f_delta < 0) {
|
||||
/*
|
||||
* Open batch delta file for writing;
|
||||
* create it if it doesn't exist
|
||||
*/
|
||||
fdb_delta = do_open(filename, O_WRONLY | O_CREAT | O_TRUNC,
|
||||
S_IREAD | S_IWRITE);
|
||||
if (fdb_delta == -1) {
|
||||
rprintf(FERROR, "Batch file %s open error: %s\n",
|
||||
filename, strerror(errno));
|
||||
close(fdb_delta);
|
||||
exit_cleanup(1);
|
||||
}
|
||||
fdb_delta_open = 0;
|
||||
}
|
||||
|
||||
if (write(f_delta, buff, bytes_to_write) < 0) {
|
||||
/* Write buffer to batch delta file */
|
||||
|
||||
if (write(fdb_delta, buff, bytes_to_write) == -1) {
|
||||
rprintf(FERROR, "Batch file %s write error: %s\n",
|
||||
filename, strerror(errno));
|
||||
close(f_delta);
|
||||
filename, strerror(errno));
|
||||
close(fdb_delta);
|
||||
exit_cleanup(1);
|
||||
}
|
||||
}
|
||||
|
||||
void close_batch_delta_file(void)
|
||||
{
|
||||
close(f_delta);
|
||||
f_delta = -1;
|
||||
close(fdb_delta);
|
||||
}
|
||||
|
||||
int read_batch_delta_file(char *buff, int len)
|
||||
{
|
||||
static int fdb_delta_open = 1;
|
||||
int bytes_read;
|
||||
char filename[MAXPATHLEN];
|
||||
|
||||
if (f_delta < 0) {
|
||||
stringjoin(filename, sizeof filename,
|
||||
batch_prefix, rsync_delta_file, NULL);
|
||||
if (fdb_delta_open) {
|
||||
/* Set up file extension */
|
||||
strlcpy(filename, batch_prefix, sizeof(filename));
|
||||
strlcat(filename, rsync_delta_file, sizeof(filename));
|
||||
|
||||
f_delta = do_open(filename, O_RDONLY, 0);
|
||||
if (f_delta < 0) {
|
||||
/* Open batch flist file for reading */
|
||||
fdb_delta = do_open(filename, O_RDONLY, 0);
|
||||
if (fdb_delta == -1) {
|
||||
rprintf(FERROR, "Batch file %s open error: %s\n",
|
||||
filename, strerror(errno));
|
||||
close(f_delta);
|
||||
filename, strerror(errno));
|
||||
close(fdb_delta);
|
||||
exit_cleanup(1);
|
||||
}
|
||||
fdb_delta_open = 0;
|
||||
}
|
||||
|
||||
bytes_read = read(f_delta, buff, len);
|
||||
if (bytes_read < 0) {
|
||||
/* Read delta batch file */
|
||||
|
||||
bytes_read = read(fdb_delta, buff, len);
|
||||
|
||||
if (bytes_read == -1) {
|
||||
rprintf(FERROR, "Batch file %s read error: %s\n",
|
||||
filename, strerror(errno));
|
||||
close(f_delta);
|
||||
filename, strerror(errno));
|
||||
close(fdb_delta);
|
||||
exit_cleanup(1);
|
||||
}
|
||||
|
||||
|
||||
32
checksum.c
32
checksum.c
@@ -23,8 +23,8 @@ int csum_length=2; /* initial value */
|
||||
|
||||
#define CSUM_CHUNK 64
|
||||
|
||||
extern int checksum_seed;
|
||||
extern int protocol_version;
|
||||
int checksum_seed = 0;
|
||||
extern int remote_version;
|
||||
|
||||
/*
|
||||
a simple 32 bit checksum that can be upadted from either end
|
||||
@@ -74,13 +74,7 @@ void get_checksum2(char *buf,int len,char *sum)
|
||||
for(i = 0; i + CSUM_CHUNK <= len; i += CSUM_CHUNK) {
|
||||
mdfour_update(&m, (uchar *)(buf1+i), CSUM_CHUNK);
|
||||
}
|
||||
/*
|
||||
* Prior to version 27 an incorrect MD4 checksum was computed
|
||||
* by failing to call mdfour_tail() for block sizes that
|
||||
* are multiples of 64. This is fixed by calling mdfour_update()
|
||||
* even when there are no more bytes.
|
||||
*/
|
||||
if (len - i > 0 || protocol_version >= 27) {
|
||||
if (len - i > 0) {
|
||||
mdfour_update(&m, (uchar *)(buf1+i), (len-i));
|
||||
}
|
||||
|
||||
@@ -111,16 +105,8 @@ void file_checksum(char *fname,char *sum,OFF_T size)
|
||||
mdfour_update(&m, (uchar *)tmpchunk, CSUM_CHUNK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Prior to version 27 an incorrect MD4 checksum was computed
|
||||
* by failing to call mdfour_tail() for block sizes that
|
||||
* are multiples of 64. This is fixed by calling mdfour_update()
|
||||
* even when there are no more bytes.
|
||||
*/
|
||||
if (len - i > 0) {
|
||||
memcpy(tmpchunk, map_ptr(buf,i,len-i), len-i);
|
||||
}
|
||||
if (len - i > 0 || protocol_version >= 27) {
|
||||
mdfour_update(&m, (uchar *)tmpchunk, (len-i));
|
||||
}
|
||||
|
||||
@@ -131,6 +117,16 @@ void file_checksum(char *fname,char *sum,OFF_T size)
|
||||
}
|
||||
|
||||
|
||||
void checksum_init(void)
|
||||
{
|
||||
if (remote_version >= 14)
|
||||
csum_length = 2; /* adaptive */
|
||||
else
|
||||
csum_length = SUM_LENGTH;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int sumresidue;
|
||||
static char sumrbuf[CSUM_CHUNK];
|
||||
static struct mdfour md;
|
||||
@@ -184,7 +180,7 @@ void sum_update(char *p, int len)
|
||||
|
||||
void sum_end(char *sum)
|
||||
{
|
||||
if (sumresidue || protocol_version >= 27) {
|
||||
if (sumresidue) {
|
||||
mdfour_update(&md, (uchar *)sumrbuf, sumresidue);
|
||||
}
|
||||
|
||||
|
||||
15
cleanup.c
15
cleanup.c
@@ -72,7 +72,7 @@ static char *cleanup_new_fname;
|
||||
static struct file_struct *cleanup_file;
|
||||
static int cleanup_fd1, cleanup_fd2;
|
||||
static struct map_struct *cleanup_buf;
|
||||
static pid_t cleanup_pid = 0;
|
||||
static int cleanup_pid = 0;
|
||||
extern int io_error;
|
||||
|
||||
pid_t cleanup_child_pid = -1;
|
||||
@@ -118,24 +118,21 @@ void _exit_cleanup(int code, const char *file, int line)
|
||||
if (cleanup_fd2 != -1) close(cleanup_fd2);
|
||||
finish_transfer(cleanup_new_fname, fname, cleanup_file);
|
||||
}
|
||||
io_flush(FULL_FLUSH);
|
||||
io_flush();
|
||||
if (cleanup_fname)
|
||||
do_unlink(cleanup_fname);
|
||||
if (code) {
|
||||
kill_all(SIGUSR1);
|
||||
}
|
||||
if (cleanup_pid && cleanup_pid == getpid()) {
|
||||
if ((cleanup_pid != 0) && (cleanup_pid == (int) getpid())) {
|
||||
char *pidf = lp_pid_file();
|
||||
if (pidf && *pidf) {
|
||||
unlink(lp_pid_file());
|
||||
}
|
||||
}
|
||||
|
||||
if (code == 0) {
|
||||
if ((io_error & ~IOERR_VANISHED) || log_got_error)
|
||||
code = RERR_PARTIAL;
|
||||
else if (io_error)
|
||||
code = RERR_VANISHED;
|
||||
if (code == 0 && (io_error || log_got_error)) {
|
||||
code = RERR_PARTIAL;
|
||||
}
|
||||
|
||||
if (code) log_exit(code, file, line);
|
||||
@@ -166,7 +163,7 @@ void cleanup_set(char *fnametmp, char *fname, struct file_struct *file,
|
||||
cleanup_fd2 = fd2;
|
||||
}
|
||||
|
||||
void cleanup_set_pid(pid_t pid)
|
||||
void cleanup_set_pid(int pid)
|
||||
{
|
||||
cleanup_pid = pid;
|
||||
}
|
||||
|
||||
131
clientname.c
131
clientname.c
@@ -1,20 +1,20 @@
|
||||
/* -*- c-file-style: "linux" -*-
|
||||
|
||||
|
||||
rsync -- fast file replication program
|
||||
|
||||
|
||||
Copyright (C) 1992-2001 by Andrew Tridgell <tridge@samba.org>
|
||||
Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
|
||||
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
/**
|
||||
* @file clientname.c
|
||||
*
|
||||
*
|
||||
* Functions for looking up the remote name or addr of a socket.
|
||||
*
|
||||
* This file is now converted to use the new-style getaddrinfo()
|
||||
@@ -39,7 +39,7 @@ extern int am_server;
|
||||
|
||||
|
||||
/**
|
||||
* Return the IP addr of the client as a string
|
||||
* Return the IP addr of the client as a string
|
||||
**/
|
||||
char *client_addr(int fd)
|
||||
{
|
||||
@@ -50,18 +50,19 @@ char *client_addr(int fd)
|
||||
static char addr_buf[100];
|
||||
static int initialised;
|
||||
|
||||
if (initialised)
|
||||
return addr_buf;
|
||||
if (initialised) return addr_buf;
|
||||
|
||||
initialised = 1;
|
||||
|
||||
if (am_server) { /* daemon over --rsh mode */
|
||||
if (am_server) {
|
||||
/* daemon over --rsh mode */
|
||||
strcpy(addr_buf, "0.0.0.0");
|
||||
if ((ssh_client = getenv("SSH_CLIENT")) != NULL) {
|
||||
/* truncate SSH_CLIENT to just IP address */
|
||||
if ((p = strchr(ssh_client, ' ')) != NULL) {
|
||||
len = MIN((unsigned int) (p - ssh_client),
|
||||
sizeof addr_buf - 1);
|
||||
p = strchr(ssh_client, ' ');
|
||||
if (p) {
|
||||
len = MIN((unsigned int) (p - ssh_client),
|
||||
sizeof(addr_buf) - 1);
|
||||
strncpy(addr_buf, ssh_client, len);
|
||||
*(addr_buf + len) = '\0';
|
||||
}
|
||||
@@ -100,54 +101,58 @@ char *client_name(int fd)
|
||||
static char name_buf[100];
|
||||
static char port_buf[100];
|
||||
static int initialised;
|
||||
struct sockaddr_storage ss;
|
||||
struct sockaddr_storage ss, *ssp;
|
||||
struct sockaddr_in sin;
|
||||
#ifdef INET6
|
||||
struct sockaddr_in6 sin6;
|
||||
#endif
|
||||
socklen_t ss_len;
|
||||
|
||||
if (initialised)
|
||||
return name_buf;
|
||||
if (initialised) return name_buf;
|
||||
|
||||
strcpy(name_buf, default_name);
|
||||
initialised = 1;
|
||||
|
||||
memset(&ss, 0, sizeof ss);
|
||||
if (am_server) {
|
||||
/* daemon over --rsh mode */
|
||||
|
||||
if (am_server) { /* daemon over --rsh mode */
|
||||
char *addr = client_addr(fd);
|
||||
struct addrinfo hint, *answer;
|
||||
int err;
|
||||
|
||||
memset(&hint, 0, sizeof hint);
|
||||
|
||||
hint.ai_flags = AI_NUMERICHOST;
|
||||
hint.ai_socktype = SOCK_STREAM;
|
||||
|
||||
if ((err = getaddrinfo(addr, NULL, &hint, &answer)) != 0) {
|
||||
rprintf(FERROR, RSYNC_NAME ": malformed address %s: %s\n",
|
||||
addr, gai_strerror(err));
|
||||
return name_buf;
|
||||
}
|
||||
|
||||
switch (answer->ai_family) {
|
||||
case AF_INET:
|
||||
ss_len = sizeof (struct sockaddr_in);
|
||||
memcpy(&ss, answer->ai_addr, ss_len);
|
||||
break;
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
ss_len = sizeof (struct sockaddr_in6);
|
||||
memcpy(&ss, answer->ai_addr, ss_len);
|
||||
break;
|
||||
#endif
|
||||
int dots = 0;
|
||||
char *p;
|
||||
|
||||
for (p = addr; *p && (dots <= 3); p++) {
|
||||
if (*p == '.')
|
||||
dots++;
|
||||
}
|
||||
freeaddrinfo(answer);
|
||||
if (dots > 3) {
|
||||
/* more than 4 parts to IP address, must be ipv6 */
|
||||
ssp = (struct sockaddr_storage *) &sin6;
|
||||
ss_len = sizeof sin6;
|
||||
memset(ssp, 0, ss_len);
|
||||
inet_pton(AF_INET6, addr, &sin6.sin6_addr);
|
||||
sin6.sin6_family = AF_INET6;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
ssp = (struct sockaddr_storage *) &sin;
|
||||
ss_len = sizeof sin;
|
||||
memset(ssp, 0, ss_len);
|
||||
inet_pton(AF_INET, addr, &sin.sin_addr);
|
||||
sin.sin_family = AF_INET;
|
||||
}
|
||||
|
||||
} else {
|
||||
ss_len = sizeof ss;
|
||||
ssp = &ss;
|
||||
|
||||
client_sockaddr(fd, &ss, &ss_len);
|
||||
|
||||
}
|
||||
|
||||
if (!lookup_name(fd, &ss, ss_len, name_buf, sizeof name_buf,
|
||||
if (!lookup_name(fd, ssp, ss_len, name_buf, sizeof name_buf,
|
||||
port_buf, sizeof port_buf))
|
||||
check_name(fd, &ss, name_buf);
|
||||
check_name(fd, ssp, name_buf);
|
||||
|
||||
return name_buf;
|
||||
}
|
||||
@@ -164,7 +169,7 @@ void client_sockaddr(int fd,
|
||||
struct sockaddr_storage *ss,
|
||||
socklen_t *ss_len)
|
||||
{
|
||||
memset(ss, 0, sizeof *ss);
|
||||
memset(ss, 0, sizeof(*ss));
|
||||
|
||||
if (getpeername(fd, (struct sockaddr *) ss, ss_len)) {
|
||||
/* FIXME: Can we really not continue? */
|
||||
@@ -174,7 +179,7 @@ void client_sockaddr(int fd,
|
||||
}
|
||||
|
||||
#ifdef INET6
|
||||
if (get_sockaddr_family(ss) == AF_INET6 &&
|
||||
if (get_sockaddr_family(ss) == AF_INET6 &&
|
||||
IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)ss)->sin6_addr)) {
|
||||
/* OK, so ss is in the IPv6 family, but it is really
|
||||
* an IPv4 address: something like
|
||||
@@ -185,12 +190,12 @@ void client_sockaddr(int fd,
|
||||
struct sockaddr_in6 sin6;
|
||||
struct sockaddr_in *sin;
|
||||
|
||||
memcpy(&sin6, ss, sizeof sin6);
|
||||
memcpy(&sin6, ss, sizeof(sin6));
|
||||
sin = (struct sockaddr_in *)ss;
|
||||
memset(sin, 0, sizeof *sin);
|
||||
memset(sin, 0, sizeof(*sin));
|
||||
sin->sin_family = AF_INET;
|
||||
*ss_len = sizeof (struct sockaddr_in);
|
||||
#if HAVE_SOCKADDR_IN_LEN
|
||||
*ss_len = sizeof(struct sockaddr_in);
|
||||
#ifdef HAVE_SOCKADDR_LEN
|
||||
sin->sin_len = *ss_len;
|
||||
#endif
|
||||
sin->sin_port = sin6.sin6_port;
|
||||
@@ -199,8 +204,8 @@ void client_sockaddr(int fd,
|
||||
* (IN6_V4MAPPED_TO_SINADDR ?), but it does not seem
|
||||
* to be present in the Linux headers. */
|
||||
memcpy(&sin->sin_addr, &sin6.sin6_addr.s6_addr[12],
|
||||
sizeof sin->sin_addr);
|
||||
}
|
||||
sizeof(sin->sin_addr));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -216,7 +221,7 @@ int lookup_name(int fd, const struct sockaddr_storage *ss,
|
||||
char *port_buf, size_t port_buf_len)
|
||||
{
|
||||
int name_err;
|
||||
|
||||
|
||||
/* reverse lookup */
|
||||
name_err = getnameinfo((struct sockaddr *) ss, ss_len,
|
||||
name_buf, name_buf_len,
|
||||
@@ -245,7 +250,7 @@ int compare_addrinfo_sockaddr(const struct addrinfo *ai,
|
||||
{
|
||||
int ss_family = get_sockaddr_family(ss);
|
||||
const char fn[] = "compare_addrinfo_sockaddr";
|
||||
|
||||
|
||||
if (ai->ai_family != ss_family) {
|
||||
rprintf(FERROR,
|
||||
"%s: response family %d != %d\n",
|
||||
@@ -259,19 +264,18 @@ int compare_addrinfo_sockaddr(const struct addrinfo *ai,
|
||||
|
||||
sin1 = (const struct sockaddr_in *) ss;
|
||||
sin2 = (const struct sockaddr_in *) ai->ai_addr;
|
||||
|
||||
|
||||
return memcmp(&sin1->sin_addr, &sin2->sin_addr,
|
||||
sizeof sin1->sin_addr);
|
||||
}
|
||||
|
||||
#ifdef INET6
|
||||
if (ss_family == AF_INET6) {
|
||||
else if (ss_family == AF_INET6) {
|
||||
const struct sockaddr_in6 *sin1, *sin2;
|
||||
|
||||
sin1 = (const struct sockaddr_in6 *) ss;
|
||||
sin2 = (const struct sockaddr_in6 *) ai->ai_addr;
|
||||
|
||||
if (ai->ai_addrlen < sizeof (struct sockaddr_in6)) {
|
||||
if (ai->ai_addrlen < sizeof(struct sockaddr_in6)) {
|
||||
rprintf(FERROR,
|
||||
"%s: too short sockaddr_in6; length=%d\n",
|
||||
fn, ai->ai_addrlen);
|
||||
@@ -289,9 +293,10 @@ int compare_addrinfo_sockaddr(const struct addrinfo *ai,
|
||||
return 0;
|
||||
}
|
||||
#endif /* INET6 */
|
||||
|
||||
/* don't know */
|
||||
return 1;
|
||||
else {
|
||||
/* don't know */
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -313,7 +318,7 @@ int check_name(int fd,
|
||||
int error;
|
||||
int ss_family = get_sockaddr_family(ss);
|
||||
|
||||
memset(&hints, 0, sizeof hints);
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = ss_family;
|
||||
hints.ai_flags = AI_CANONNAME;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
|
||||
@@ -27,31 +27,17 @@
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
extern int am_sender;
|
||||
extern int am_server;
|
||||
extern int am_daemon;
|
||||
extern int am_root;
|
||||
extern int module_id;
|
||||
extern int read_only;
|
||||
extern int verbose;
|
||||
extern int rsync_port;
|
||||
extern int kludge_around_eof;
|
||||
extern int daemon_over_rsh;
|
||||
extern int list_only;
|
||||
char *auth_user;
|
||||
extern int sanitize_paths;
|
||||
extern int filesfrom_fd;
|
||||
extern int remote_protocol;
|
||||
extern int protocol_version;
|
||||
extern int io_timeout;
|
||||
extern int orig_umask;
|
||||
extern int no_detach;
|
||||
extern int default_af_hint;
|
||||
extern char *bind_address;
|
||||
extern struct exclude_list_struct server_exclude_list;
|
||||
extern struct exclude_struct **server_exclude_list;
|
||||
extern char *exclude_path_prefix;
|
||||
extern char *config_file;
|
||||
|
||||
char *auth_user;
|
||||
|
||||
/**
|
||||
* Run a client connected to an rsyncd. The alternative to this
|
||||
@@ -71,6 +57,8 @@ int start_socket_client(char *host, char *path, int argc, char *argv[])
|
||||
{
|
||||
int fd, ret;
|
||||
char *p, *user=NULL;
|
||||
extern char *bind_address;
|
||||
extern int default_af_hint;
|
||||
|
||||
/* this is redundant with code in start_inband_exchange(), but
|
||||
* this short-circuits a problem before we open a socket, and
|
||||
@@ -87,10 +75,18 @@ int start_socket_client(char *host, char *path, int argc, char *argv[])
|
||||
*p = 0;
|
||||
}
|
||||
|
||||
if (verbose >= 2) {
|
||||
/* FIXME: If we're going to use a socket program for
|
||||
* testing, then this message is wrong. We need to
|
||||
* say something like "(except really using %s)" */
|
||||
rprintf(FINFO, "opening tcp connection to %s port %d\n",
|
||||
host, rsync_port);
|
||||
}
|
||||
fd = open_socket_out_wrapped(host, rsync_port, bind_address,
|
||||
default_af_hint);
|
||||
if (fd == -1)
|
||||
if (fd == -1) {
|
||||
exit_cleanup(RERR_SOCKETIO);
|
||||
}
|
||||
|
||||
ret = start_inband_exchange(user, path, fd, fd, argc);
|
||||
|
||||
@@ -104,6 +100,10 @@ int start_inband_exchange(char *user, char *path, int f_in, int f_out, int argc)
|
||||
int sargc = 0;
|
||||
char line[MAXPATHLEN];
|
||||
char *p;
|
||||
extern int kludge_around_eof;
|
||||
extern int am_sender;
|
||||
extern int daemon_over_rsh;
|
||||
extern int list_only;
|
||||
|
||||
if (argc == 0 && !am_sender)
|
||||
list_only = 1;
|
||||
@@ -129,7 +129,7 @@ int start_inband_exchange(char *user, char *path, int f_in, int f_out, int argc)
|
||||
|
||||
sargs[sargc] = NULL;
|
||||
|
||||
io_printf(f_out, "@RSYNCD: %d\n", protocol_version);
|
||||
io_printf(f_out, "@RSYNCD: %d\n", PROTOCOL_VERSION);
|
||||
|
||||
if (!read_line(f_in, line, sizeof(line)-1)) {
|
||||
rprintf(FERROR, "rsync: did not see server greeting\n");
|
||||
@@ -192,7 +192,7 @@ int start_inband_exchange(char *user, char *path, int f_in, int f_out, int argc)
|
||||
io_printf(f_out, "\n");
|
||||
|
||||
if (protocol_version < 23) {
|
||||
if (protocol_version == 22 || !am_sender)
|
||||
if (protocol_version == 22 || (protocol_version > 17 && !am_sender))
|
||||
io_start_multiplex_in(f_in);
|
||||
}
|
||||
|
||||
@@ -217,6 +217,10 @@ static int rsync_module(int f_in, int f_out, int i)
|
||||
int start_glob=0;
|
||||
int ret;
|
||||
char *request=NULL;
|
||||
extern int am_sender;
|
||||
extern int am_server;
|
||||
extern int am_daemon;
|
||||
extern int am_root;
|
||||
|
||||
if (!allow_access(addr, host, lp_hosts_allow(i), lp_hosts_deny(i))) {
|
||||
rprintf(FERROR,"rsync denied on module %s from %s (%s)\n",
|
||||
@@ -258,7 +262,7 @@ static int rsync_module(int f_in, int f_out, int i)
|
||||
|
||||
module_id = i;
|
||||
|
||||
am_root = (MY_UID() == 0);
|
||||
am_root = (getuid() == 0);
|
||||
|
||||
if (am_root) {
|
||||
p = lp_uid(i);
|
||||
@@ -294,19 +298,16 @@ static int rsync_module(int f_in, int f_out, int i)
|
||||
exclude_path_prefix = "";
|
||||
|
||||
p = lp_include_from(i);
|
||||
add_exclude_file(&server_exclude_list, p,
|
||||
XFLG_FATAL_ERRORS | XFLG_DEF_INCLUDE);
|
||||
add_exclude_file(&server_exclude_list, p, MISSING_FATAL, ADD_INCLUDE);
|
||||
|
||||
p = lp_include(i);
|
||||
add_exclude(&server_exclude_list, p,
|
||||
XFLG_WORD_SPLIT | XFLG_DEF_INCLUDE);
|
||||
add_exclude_line(&server_exclude_list, p, ADD_INCLUDE);
|
||||
|
||||
p = lp_exclude_from(i);
|
||||
add_exclude_file(&server_exclude_list, p,
|
||||
XFLG_FATAL_ERRORS);
|
||||
add_exclude_file(&server_exclude_list, p, MISSING_FATAL, ADD_EXCLUDE);
|
||||
|
||||
p = lp_exclude(i);
|
||||
add_exclude(&server_exclude_list, p, XFLG_WORD_SPLIT);
|
||||
add_exclude_line(&server_exclude_list, p, ADD_EXCLUDE);
|
||||
|
||||
exclude_path_prefix = NULL;
|
||||
|
||||
@@ -331,14 +332,14 @@ static int rsync_module(int f_in, int f_out, int i)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!push_dir("/")) {
|
||||
if (!push_dir("/", 0)) {
|
||||
rsyserr(FERROR, errno, "chdir %s failed\n", lp_path(i));
|
||||
io_printf(f_out, "@ERROR: chdir failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
} else {
|
||||
if (!push_dir(lp_path(i))) {
|
||||
if (!push_dir(lp_path(i), 0)) {
|
||||
rsyserr(FERROR, errno, "chdir %s failed\n", lp_path(i));
|
||||
io_printf(f_out, "@ERROR: chdir failed\n");
|
||||
return -1;
|
||||
@@ -378,7 +379,7 @@ static int rsync_module(int f_in, int f_out, int i)
|
||||
return -1;
|
||||
}
|
||||
|
||||
am_root = (MY_UID() == 0);
|
||||
am_root = (getuid() == 0);
|
||||
}
|
||||
|
||||
io_printf(f_out, "@RSYNCD: OK\n");
|
||||
@@ -418,6 +419,19 @@ static int rsync_module(int f_in, int f_out, int i)
|
||||
}
|
||||
}
|
||||
|
||||
if (sanitize_paths) {
|
||||
/*
|
||||
* Note that this is applied to all parameters, whether or not
|
||||
* they are filenames, but no other legal parameters contain
|
||||
* the forms that need to be sanitized so it doesn't hurt;
|
||||
* it is not known at this point which parameters are files
|
||||
* and which aren't.
|
||||
*/
|
||||
for (i = 1; i < argc; i++) {
|
||||
sanitize_path(argv[i], NULL);
|
||||
}
|
||||
}
|
||||
|
||||
argp = argv;
|
||||
ret = parse_arguments(&argc, (const char ***) &argp, 0);
|
||||
|
||||
@@ -439,12 +453,11 @@ static int rsync_module(int f_in, int f_out, int i)
|
||||
|
||||
#ifndef DEBUG
|
||||
/* don't allow the logs to be flooded too fast */
|
||||
if (verbose > lp_max_verbosity())
|
||||
verbose = lp_max_verbosity();
|
||||
if (verbose > 1) verbose = 1;
|
||||
#endif
|
||||
|
||||
if (protocol_version < 23) {
|
||||
if (protocol_version == 22 || am_sender)
|
||||
if (protocol_version == 22 || (protocol_version > 17 && am_sender))
|
||||
io_start_multiplex_out(f_out);
|
||||
}
|
||||
|
||||
@@ -462,6 +475,7 @@ static int rsync_module(int f_in, int f_out, int i)
|
||||
}
|
||||
|
||||
if (lp_timeout(i)) {
|
||||
extern int io_timeout;
|
||||
io_timeout = lp_timeout(i);
|
||||
}
|
||||
|
||||
@@ -493,6 +507,8 @@ int start_daemon(int f_in, int f_out)
|
||||
char line[200];
|
||||
char *motd;
|
||||
int i = -1;
|
||||
extern char *config_file;
|
||||
extern int am_server;
|
||||
|
||||
if (!lp_load(config_file, 0)) {
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
@@ -506,7 +522,7 @@ int start_daemon(int f_in, int f_out)
|
||||
set_nonblocking(f_in);
|
||||
}
|
||||
|
||||
io_printf(f_out, "@RSYNCD: %d\n", protocol_version);
|
||||
io_printf(f_out, "@RSYNCD: %d\n", PROTOCOL_VERSION);
|
||||
|
||||
motd = lp_motd_file();
|
||||
if (motd && *motd) {
|
||||
@@ -563,7 +579,10 @@ int start_daemon(int f_in, int f_out)
|
||||
|
||||
int daemon_main(void)
|
||||
{
|
||||
extern char *config_file;
|
||||
extern int orig_umask;
|
||||
char *pid_file;
|
||||
extern int no_detach;
|
||||
|
||||
if (is_a_socket(STDIN_FILENO)) {
|
||||
int i;
|
||||
@@ -597,7 +616,7 @@ int daemon_main(void)
|
||||
if (((pid_file = lp_pid_file()) != NULL) && (*pid_file != '\0')) {
|
||||
char pidbuf[16];
|
||||
int fd;
|
||||
pid_t pid = getpid();
|
||||
int pid = (int) getpid();
|
||||
cleanup_set_pid(pid);
|
||||
if ((fd = do_open(lp_pid_file(), O_WRONLY|O_CREAT|O_TRUNC,
|
||||
0666 & ~orig_umask)) == -1) {
|
||||
@@ -605,7 +624,7 @@ int daemon_main(void)
|
||||
rsyserr(FLOG, errno, "failed to create pid file %s", pid_file);
|
||||
exit_cleanup(RERR_FILEIO);
|
||||
}
|
||||
snprintf(pidbuf, sizeof pidbuf, "%ld\n", (long)pid);
|
||||
snprintf(pidbuf, sizeof(pidbuf), "%d\n", pid);
|
||||
write(fd, pidbuf, strlen(pidbuf));
|
||||
close(fd);
|
||||
}
|
||||
|
||||
7
compat.c
7
compat.c
@@ -38,6 +38,7 @@ extern int preserve_times;
|
||||
extern int always_checksum;
|
||||
extern int checksum_seed;
|
||||
|
||||
|
||||
extern int protocol_version;
|
||||
extern int verbose;
|
||||
|
||||
@@ -84,9 +85,11 @@ void setup_protocol(int f_out,int f_in)
|
||||
}
|
||||
|
||||
if (am_server) {
|
||||
if (!checksum_seed)
|
||||
if (read_batch || write_batch)
|
||||
checksum_seed = 32761;
|
||||
else
|
||||
checksum_seed = time(NULL);
|
||||
write_int(f_out, checksum_seed);
|
||||
write_int(f_out,checksum_seed);
|
||||
} else {
|
||||
checksum_seed = read_int(f_in);
|
||||
}
|
||||
|
||||
133
config.guess
vendored
133
config.guess
vendored
@@ -3,7 +3,7 @@
|
||||
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
|
||||
# 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
|
||||
|
||||
timestamp='2003-10-03'
|
||||
timestamp='2003-01-10'
|
||||
|
||||
# This file is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by
|
||||
@@ -106,7 +106,6 @@ trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
|
||||
: ${TMPDIR=/tmp} ;
|
||||
{ tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
|
||||
{ test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
|
||||
{ tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
|
||||
{ echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
|
||||
dummy=$tmp/dummy ;
|
||||
tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
|
||||
@@ -236,56 +235,74 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
||||
*:OpenBSD:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
*:MicroBSD:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-microbsd${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
alpha:OSF1:*:*)
|
||||
if test $UNAME_RELEASE = "V4.0"; then
|
||||
UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
|
||||
fi
|
||||
# According to Compaq, /usr/sbin/psrinfo has been available on
|
||||
# OSF/1 and Tru64 systems produced since 1995. I hope that
|
||||
# covers most systems running today. This code pipes the CPU
|
||||
# types through head -n 1, so we only detect the type of CPU 0.
|
||||
ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
|
||||
case "$ALPHA_CPU_TYPE" in
|
||||
"EV4 (21064)")
|
||||
UNAME_MACHINE="alpha" ;;
|
||||
"EV4.5 (21064)")
|
||||
UNAME_MACHINE="alpha" ;;
|
||||
"LCA4 (21066/21068)")
|
||||
UNAME_MACHINE="alpha" ;;
|
||||
"EV5 (21164)")
|
||||
UNAME_MACHINE="alphaev5" ;;
|
||||
"EV5.6 (21164A)")
|
||||
UNAME_MACHINE="alphaev56" ;;
|
||||
"EV5.6 (21164PC)")
|
||||
UNAME_MACHINE="alphapca56" ;;
|
||||
"EV5.7 (21164PC)")
|
||||
UNAME_MACHINE="alphapca57" ;;
|
||||
"EV6 (21264)")
|
||||
UNAME_MACHINE="alphaev6" ;;
|
||||
"EV6.7 (21264A)")
|
||||
UNAME_MACHINE="alphaev67" ;;
|
||||
"EV6.8CB (21264C)")
|
||||
UNAME_MACHINE="alphaev68" ;;
|
||||
"EV6.8AL (21264B)")
|
||||
UNAME_MACHINE="alphaev68" ;;
|
||||
"EV6.8CX (21264D)")
|
||||
UNAME_MACHINE="alphaev68" ;;
|
||||
"EV6.9A (21264/EV69A)")
|
||||
UNAME_MACHINE="alphaev69" ;;
|
||||
"EV7 (21364)")
|
||||
UNAME_MACHINE="alphaev7" ;;
|
||||
"EV7.9 (21364A)")
|
||||
UNAME_MACHINE="alphaev79" ;;
|
||||
esac
|
||||
# A Vn.n version is a released version.
|
||||
# A Tn.n version is a released field test version.
|
||||
# A Xn.n version is an unreleased experimental baselevel.
|
||||
# 1.2 uses "1.2" for uname -r.
|
||||
eval $set_cc_for_build
|
||||
cat <<EOF >$dummy.s
|
||||
.data
|
||||
\$Lformat:
|
||||
.byte 37,100,45,37,120,10,0 # "%d-%x\n"
|
||||
|
||||
.text
|
||||
.globl main
|
||||
.align 4
|
||||
.ent main
|
||||
main:
|
||||
.frame \$30,16,\$26,0
|
||||
ldgp \$29,0(\$27)
|
||||
.prologue 1
|
||||
.long 0x47e03d80 # implver \$0
|
||||
lda \$2,-1
|
||||
.long 0x47e20c21 # amask \$2,\$1
|
||||
lda \$16,\$Lformat
|
||||
mov \$0,\$17
|
||||
not \$1,\$18
|
||||
jsr \$26,printf
|
||||
ldgp \$29,0(\$26)
|
||||
mov 0,\$16
|
||||
jsr \$26,exit
|
||||
.end main
|
||||
EOF
|
||||
$CC_FOR_BUILD -o $dummy $dummy.s 2>/dev/null
|
||||
if test "$?" = 0 ; then
|
||||
case `$dummy` in
|
||||
0-0)
|
||||
UNAME_MACHINE="alpha"
|
||||
;;
|
||||
1-0)
|
||||
UNAME_MACHINE="alphaev5"
|
||||
;;
|
||||
1-1)
|
||||
UNAME_MACHINE="alphaev56"
|
||||
;;
|
||||
1-101)
|
||||
UNAME_MACHINE="alphapca56"
|
||||
;;
|
||||
2-303)
|
||||
UNAME_MACHINE="alphaev6"
|
||||
;;
|
||||
2-307)
|
||||
UNAME_MACHINE="alphaev67"
|
||||
;;
|
||||
2-1307)
|
||||
UNAME_MACHINE="alphaev68"
|
||||
;;
|
||||
3-1307)
|
||||
UNAME_MACHINE="alphaev7"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
|
||||
exit 0 ;;
|
||||
Alpha*:OpenVMS:*:*)
|
||||
echo alpha-hp-vms
|
||||
exit 0 ;;
|
||||
Alpha\ *:Windows_NT*:*)
|
||||
# How do we know it's Interix rather than the generic POSIX subsystem?
|
||||
# Should we change UNAME_MACHINE based on the output of uname instead
|
||||
@@ -324,9 +341,6 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
||||
NILE*:*:*:dcosx)
|
||||
echo pyramid-pyramid-svr4
|
||||
exit 0 ;;
|
||||
DRS?6000:unix:4.0:6*)
|
||||
echo sparc-icl-nx6
|
||||
exit 0 ;;
|
||||
DRS?6000:UNIX_SV:4.2*:7*)
|
||||
case `/usr/bin/uname -p` in
|
||||
sparc) echo sparc-icl-nx7 && exit 0 ;;
|
||||
@@ -734,7 +748,7 @@ EOF
|
||||
echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
|
||||
exit 0 ;;
|
||||
*:UNICOS/mp:*:*)
|
||||
echo nv1-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
|
||||
echo nv1-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
|
||||
exit 0 ;;
|
||||
F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
|
||||
FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
|
||||
@@ -751,7 +765,7 @@ EOF
|
||||
*:BSD/OS:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
*:FreeBSD:*:*|*:GNU/FreeBSD:*:*)
|
||||
*:FreeBSD:*:*)
|
||||
# Determine whether the default compiler uses glibc.
|
||||
eval $set_cc_for_build
|
||||
sed 's/^ //' << EOF >$dummy.c
|
||||
@@ -763,10 +777,7 @@ EOF
|
||||
#endif
|
||||
EOF
|
||||
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
|
||||
# GNU/FreeBSD systems have a "k" prefix to indicate we are using
|
||||
# FreeBSD's kernel, but not the complete OS.
|
||||
case ${LIBC} in gnu) kernel_only='k' ;; esac
|
||||
echo ${UNAME_MACHINE}-unknown-${kernel_only}freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`${LIBC:+-$LIBC}
|
||||
echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`${LIBC:+-$LIBC}
|
||||
exit 0 ;;
|
||||
i*:CYGWIN*:*)
|
||||
echo ${UNAME_MACHINE}-pc-cygwin
|
||||
@@ -777,8 +788,8 @@ EOF
|
||||
i*:PW*:*)
|
||||
echo ${UNAME_MACHINE}-pc-pw32
|
||||
exit 0 ;;
|
||||
x86:Interix*:[34]*)
|
||||
echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//'
|
||||
x86:Interix*:3*)
|
||||
echo i586-pc-interix3
|
||||
exit 0 ;;
|
||||
[345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
|
||||
echo i${UNAME_MACHINE}-pc-mks
|
||||
@@ -807,9 +818,6 @@ EOF
|
||||
arm*:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||
exit 0 ;;
|
||||
cris:Linux:*:*)
|
||||
echo cris-axis-linux-gnu
|
||||
exit 0 ;;
|
||||
ia64:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||
exit 0 ;;
|
||||
@@ -888,9 +896,6 @@ EOF
|
||||
s390:Linux:*:* | s390x:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-ibm-linux
|
||||
exit 0 ;;
|
||||
sh64*:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||
exit 0 ;;
|
||||
sh*:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||
exit 0 ;;
|
||||
@@ -948,9 +953,6 @@ EOF
|
||||
LIBC=gnuaout
|
||||
#endif
|
||||
#endif
|
||||
#ifdef __dietlibc__
|
||||
LIBC=dietlibc
|
||||
#endif
|
||||
EOF
|
||||
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
|
||||
test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0
|
||||
@@ -1052,7 +1054,7 @@ EOF
|
||||
exit 0 ;;
|
||||
M68*:*:R3V[567]*:*)
|
||||
test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
|
||||
3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0)
|
||||
3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0)
|
||||
OS_REL=''
|
||||
test -r /etc/.relid \
|
||||
&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
|
||||
@@ -1167,7 +1169,7 @@ EOF
|
||||
*:QNX:*:4*)
|
||||
echo i386-pc-qnx
|
||||
exit 0 ;;
|
||||
NSR-[DGKLNPTVWY]:NONSTOP_KERNEL:*:*)
|
||||
NSR-[DGKLNPTVW]:NONSTOP_KERNEL:*:*)
|
||||
echo nsr-tandem-nsk${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
*:NonStop-UX:*:*)
|
||||
@@ -1208,9 +1210,6 @@ EOF
|
||||
*:ITS:*:*)
|
||||
echo pdp10-unknown-its
|
||||
exit 0 ;;
|
||||
SEI:*:*:SEIUX)
|
||||
echo mips-sei-seiux${UNAME_RELEASE}
|
||||
exit 0 ;;
|
||||
esac
|
||||
|
||||
#echo '(No uname command or uname output not recognized.)' 1>&2
|
||||
|
||||
72
config.sub
vendored
72
config.sub
vendored
@@ -3,7 +3,7 @@
|
||||
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
|
||||
# 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
|
||||
|
||||
timestamp='2003-08-18'
|
||||
timestamp='2003-01-22'
|
||||
|
||||
# This file is (in principle) common to ALL GNU software.
|
||||
# The presence of a machine in this file suggests that SOME GNU software
|
||||
@@ -118,7 +118,7 @@ esac
|
||||
# Here we must recognize all the valid KERNEL-OS combinations.
|
||||
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
|
||||
case $maybe_os in
|
||||
nto-qnx* | linux-gnu* | linux-dietlibc | kfreebsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*)
|
||||
nto-qnx* | linux-gnu* | freebsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*)
|
||||
os=-$maybe_os
|
||||
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
|
||||
;;
|
||||
@@ -228,14 +228,13 @@ case $basic_machine in
|
||||
| a29k \
|
||||
| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
|
||||
| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
|
||||
| am33_2.0 \
|
||||
| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
|
||||
| c4x | clipper \
|
||||
| clipper \
|
||||
| d10v | d30v | dlx | dsp16xx \
|
||||
| fr30 | frv \
|
||||
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
|
||||
| i370 | i860 | i960 | ia64 \
|
||||
| ip2k | iq2000 \
|
||||
| ip2k \
|
||||
| m32r | m68000 | m68k | m88k | mcore \
|
||||
| mips | mipsbe | mipseb | mipsel | mipsle \
|
||||
| mips16 \
|
||||
@@ -248,7 +247,6 @@ case $basic_machine in
|
||||
| mipsisa32 | mipsisa32el \
|
||||
| mipsisa32r2 | mipsisa32r2el \
|
||||
| mipsisa64 | mipsisa64el \
|
||||
| mipsisa64r2 | mipsisa64r2el \
|
||||
| mipsisa64sb1 | mipsisa64sb1el \
|
||||
| mipsisa64sr71k | mipsisa64sr71kel \
|
||||
| mipstx39 | mipstx39el \
|
||||
@@ -259,11 +257,11 @@ case $basic_machine in
|
||||
| pdp10 | pdp11 | pj | pjl \
|
||||
| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
|
||||
| pyramid \
|
||||
| sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
|
||||
| sh | sh[1234] | sh3e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
|
||||
| sh64 | sh64le \
|
||||
| sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \
|
||||
| strongarm \
|
||||
| tahoe | thumb | tic4x | tic80 | tron \
|
||||
| tahoe | thumb | tic80 | tron \
|
||||
| v850 | v850e \
|
||||
| we32k \
|
||||
| x86 | xscale | xstormy16 | xtensa \
|
||||
@@ -298,7 +296,7 @@ case $basic_machine in
|
||||
| arm-* | armbe-* | armle-* | armeb-* | armv*-* \
|
||||
| avr-* \
|
||||
| bs2000-* \
|
||||
| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
|
||||
| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* \
|
||||
| clipper-* | cydra-* \
|
||||
| d10v-* | d30v-* | dlx-* \
|
||||
| elxsi-* \
|
||||
@@ -306,7 +304,7 @@ case $basic_machine in
|
||||
| h8300-* | h8500-* \
|
||||
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
|
||||
| i*86-* | i860-* | i960-* | ia64-* \
|
||||
| ip2k-* | iq2000-* \
|
||||
| ip2k-* \
|
||||
| m32r-* \
|
||||
| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
|
||||
| m88110-* | m88k-* | mcore-* \
|
||||
@@ -321,7 +319,6 @@ case $basic_machine in
|
||||
| mipsisa32-* | mipsisa32el-* \
|
||||
| mipsisa32r2-* | mipsisa32r2el-* \
|
||||
| mipsisa64-* | mipsisa64el-* \
|
||||
| mipsisa64r2-* | mipsisa64r2el-* \
|
||||
| mipsisa64sb1-* | mipsisa64sb1el-* \
|
||||
| mipsisa64sr71k-* | mipsisa64sr71kel-* \
|
||||
| mipstx39-* | mipstx39el-* \
|
||||
@@ -332,13 +329,11 @@ case $basic_machine in
|
||||
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
|
||||
| pyramid-* \
|
||||
| romp-* | rs6000-* \
|
||||
| sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \
|
||||
| sh-* | sh[1234]-* | sh3e-* | sh[34]eb-* | shbe-* \
|
||||
| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
|
||||
| sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \
|
||||
| sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
|
||||
| tahoe-* | thumb-* \
|
||||
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
|
||||
| tron-* \
|
||||
| tahoe-* | thumb-* | tic30-* | tic4x-* | tic54x-* | tic80-* | tron-* \
|
||||
| v850-* | v850e-* | vax-* \
|
||||
| we32k-* \
|
||||
| x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \
|
||||
@@ -376,9 +371,6 @@ case $basic_machine in
|
||||
basic_machine=a29k-none
|
||||
os=-bsd
|
||||
;;
|
||||
amd64)
|
||||
basic_machine=x86_64-pc
|
||||
;;
|
||||
amdahl)
|
||||
basic_machine=580-amdahl
|
||||
os=-sysv
|
||||
@@ -774,24 +766,18 @@ case $basic_machine in
|
||||
pentiumpro | p6 | 6x86 | athlon | athlon_*)
|
||||
basic_machine=i686-pc
|
||||
;;
|
||||
pentiumii | pentium2 | pentiumiii | pentium3)
|
||||
pentiumii | pentium2)
|
||||
basic_machine=i686-pc
|
||||
;;
|
||||
pentium4)
|
||||
basic_machine=i786-pc
|
||||
;;
|
||||
pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
|
||||
basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
pentiumpro-* | p6-* | 6x86-* | athlon-*)
|
||||
basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
|
||||
pentiumii-* | pentium2-*)
|
||||
basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
pentium4-*)
|
||||
basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
pn)
|
||||
basic_machine=pn-gould
|
||||
;;
|
||||
@@ -850,10 +836,6 @@ case $basic_machine in
|
||||
sb1el)
|
||||
basic_machine=mipsisa64sb1el-unknown
|
||||
;;
|
||||
sei)
|
||||
basic_machine=mips-sei
|
||||
os=-seiux
|
||||
;;
|
||||
sequent)
|
||||
basic_machine=i386-sequent
|
||||
;;
|
||||
@@ -861,9 +843,6 @@ case $basic_machine in
|
||||
basic_machine=sh-hitachi
|
||||
os=-hms
|
||||
;;
|
||||
sh64)
|
||||
basic_machine=sh64-unknown
|
||||
;;
|
||||
sparclite-wrs | simso-wrs)
|
||||
basic_machine=sparclite-wrs
|
||||
os=-vxworks
|
||||
@@ -938,18 +917,14 @@ case $basic_machine in
|
||||
basic_machine=t90-cray
|
||||
os=-unicos
|
||||
;;
|
||||
tic4x | c4x*)
|
||||
basic_machine=tic4x-unknown
|
||||
os=-coff
|
||||
;;
|
||||
tic54x | c54x*)
|
||||
basic_machine=tic54x-unknown
|
||||
os=-coff
|
||||
;;
|
||||
tic55x | c55x*)
|
||||
basic_machine=tic55x-unknown
|
||||
os=-coff
|
||||
;;
|
||||
tic6x | c6x*)
|
||||
basic_machine=tic6x-unknown
|
||||
os=-coff
|
||||
;;
|
||||
tx39)
|
||||
basic_machine=mipstx39-unknown
|
||||
;;
|
||||
@@ -1052,7 +1027,7 @@ case $basic_machine in
|
||||
we32k)
|
||||
basic_machine=we32k-att
|
||||
;;
|
||||
sh3 | sh4 | sh[34]eb | sh[1234]le | sh[23]ele)
|
||||
sh3 | sh4 | sh3eb | sh4eb | sh[1234]le | sh3ele)
|
||||
basic_machine=sh-unknown
|
||||
;;
|
||||
sh64)
|
||||
@@ -1131,7 +1106,7 @@ case $os in
|
||||
| -aos* \
|
||||
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
|
||||
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
|
||||
| -hiux* | -386bsd* | -netbsd* | -openbsd* | -kfreebsd* | -freebsd* | -riscix* \
|
||||
| -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \
|
||||
| -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
|
||||
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
|
||||
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
|
||||
@@ -1143,7 +1118,7 @@ case $os in
|
||||
| -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
|
||||
| -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
|
||||
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
|
||||
| -powermax* | -dnix* | -nx6 | -nx7 | -sei*)
|
||||
| -powermax* | -dnix* | -microbsd*)
|
||||
# Remember, each alternative MUST END IN *, to match a version number.
|
||||
;;
|
||||
-qnx*)
|
||||
@@ -1167,9 +1142,6 @@ case $os in
|
||||
-mac*)
|
||||
os=`echo $os | sed -e 's|mac|macos|'`
|
||||
;;
|
||||
-linux-dietlibc)
|
||||
os=-linux-dietlibc
|
||||
;;
|
||||
-linux*)
|
||||
os=`echo $os | sed -e 's|linux|linux-gnu|'`
|
||||
;;
|
||||
@@ -1258,9 +1230,6 @@ case $os in
|
||||
-aros*)
|
||||
os=-aros
|
||||
;;
|
||||
-kaos*)
|
||||
os=-kaos
|
||||
;;
|
||||
-none)
|
||||
;;
|
||||
*)
|
||||
@@ -1292,9 +1261,6 @@ case $basic_machine in
|
||||
arm*-semi)
|
||||
os=-aout
|
||||
;;
|
||||
c4x-* | tic4x-*)
|
||||
os=-coff
|
||||
;;
|
||||
# This must come before the *-dec entry.
|
||||
pdp10-*)
|
||||
os=-tops20
|
||||
|
||||
126
configure.in
126
configure.in
@@ -5,7 +5,7 @@ AC_CONFIG_SRCDIR([byteorder.h])
|
||||
AC_CONFIG_HEADER(config.h)
|
||||
AC_PREREQ(2.52)
|
||||
|
||||
RSYNC_VERSION=2.6.1
|
||||
RSYNC_VERSION=2.5.7
|
||||
AC_SUBST(RSYNC_VERSION)
|
||||
AC_MSG_NOTICE([Configuring rsync $RSYNC_VERSION])
|
||||
|
||||
@@ -18,7 +18,6 @@ AC_CANONICAL_TARGET([])
|
||||
dnl Checks for programs.
|
||||
AC_PROG_CC
|
||||
AC_PROG_CPP
|
||||
AC_PROG_EGREP
|
||||
AC_PROG_INSTALL
|
||||
AC_PROG_CC_STDC
|
||||
AC_SUBST(SHELL)
|
||||
@@ -91,35 +90,14 @@ AC_ARG_WITH(included-popt,
|
||||
[ --with-included-popt use bundled popt library, not from system])
|
||||
|
||||
AC_ARG_WITH(rsync-path,
|
||||
[ --with-rsync-path=PATH set default --rsync-path to PATH (default: rsync)],
|
||||
[ --with-rsync-path=PATH set default --rsync-path to PATH (default: \"rsync\")],
|
||||
[ RSYNC_PATH="$with_rsync_path" ],
|
||||
[ RSYNC_PATH="rsync" ])
|
||||
|
||||
AC_DEFINE_UNQUOTED(RSYNC_PATH, "$RSYNC_PATH", [location of rsync on remote machine])
|
||||
|
||||
AC_ARG_WITH(rsyncd-conf,
|
||||
AC_HELP_STRING([--with-rsyncd-conf=PATH], [set configuration file for rsync server to PATH (default: /etc/rsyncd.conf)]),
|
||||
[ if test ! -z "$with_rsyncd_conf" ; then
|
||||
case $with_rsyncd_conf in
|
||||
yes|no)
|
||||
RSYNCD_SYSCONF="/etc/rsyncd.conf"
|
||||
;;
|
||||
/*)
|
||||
RSYNCD_SYSCONF="$with_rsyncd_conf"
|
||||
;;
|
||||
*)
|
||||
AC_MSG_ERROR(You must specify an absolute path to --with-rsyncd-conf=PATH)
|
||||
;;
|
||||
esac
|
||||
else
|
||||
RSYNCD_SYSCONF="/etc/rsyncd.conf"
|
||||
fi ],
|
||||
[ RSYNCD_SYSCONF="/etc/rsyncd.conf" ])
|
||||
|
||||
AC_DEFINE_UNQUOTED(RSYNCD_SYSCONF, "$RSYNCD_SYSCONF", [location of configuration file for rsync server])
|
||||
|
||||
AC_ARG_WITH(rsh,
|
||||
AC_HELP_STRING([--with-rsh=CMD], [set remote shell command to CMD (default: ssh)]))
|
||||
AC_HELP_STRING([--with-rsh=CMD], [set rsh command to CMD (default: \"remsh\" or \"rsh\")]))
|
||||
|
||||
AC_CHECK_PROG(HAVE_REMSH, remsh, 1, 0)
|
||||
AC_DEFINE_UNQUOTED(HAVE_REMSH, $HAVE_REMSH, [remote shell is remsh not rsh])
|
||||
@@ -127,8 +105,11 @@ AC_DEFINE_UNQUOTED(HAVE_REMSH, $HAVE_REMSH, [remote shell is remsh not rsh])
|
||||
if test x"$with_rsh" != x
|
||||
then
|
||||
RSYNC_RSH="$with_rsh"
|
||||
elif test x"$HAVE_REMSH" = x1
|
||||
then
|
||||
RSYNC_RSH="remsh"
|
||||
else
|
||||
RSYNC_RSH="ssh"
|
||||
RSYNC_RSH="rsh"
|
||||
fi
|
||||
|
||||
AC_DEFINE_UNQUOTED(RSYNC_RSH, "$RSYNC_RSH", [default -e command])
|
||||
@@ -143,7 +124,7 @@ AC_TRY_RUN([
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
int main(void)
|
||||
int main(void)
|
||||
{
|
||||
struct flock lock;
|
||||
int status;
|
||||
@@ -173,7 +154,7 @@ ipv6type=unknown
|
||||
ipv6lib=none
|
||||
ipv6trylibc=yes
|
||||
|
||||
AC_ARG_ENABLE(ipv6,
|
||||
AC_ARG_ENABLE(ipv6,
|
||||
AC_HELP_STRING([--disable-ipv6], [don't even try to use IPv6]))
|
||||
|
||||
if test "x$enable_ipv6" != xno
|
||||
@@ -199,7 +180,7 @@ yes
|
||||
#ifdef __KAME__
|
||||
yes
|
||||
#endif],
|
||||
[ipv6type=$i;
|
||||
[ipv6type=$i;
|
||||
AC_DEFINE(INET6, 1, [true if you have IPv6])])
|
||||
;;
|
||||
linux-glibc)
|
||||
@@ -269,7 +250,7 @@ fi
|
||||
AC_MSG_CHECKING([whether to call shutdown on all sockets])
|
||||
case $host_os in
|
||||
*cygwin* ) AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(SHUTDOWN_ALL_SOCKETS, 1,
|
||||
AC_DEFINE(SHUTDOWN_ALL_SOCKETS, 1,
|
||||
[Define if sockets need to be shutdown])
|
||||
;;
|
||||
* ) AC_MSG_RESULT(no);;
|
||||
@@ -279,12 +260,13 @@ AC_C_BIGENDIAN
|
||||
AC_HEADER_DIRENT
|
||||
AC_HEADER_TIME
|
||||
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 sys/sysctl.h arpa/inet.h arpa/nameser.h \
|
||||
netdb.h malloc.h float.h)
|
||||
AC_HEADER_MAJOR
|
||||
AC_CHECK_HEADERS(sys/fcntl.h sys/select.h fcntl.h sys/time.h sys/unistd.h unistd.h utime.h grp.h)
|
||||
AC_CHECK_HEADERS(compat.h sys/param.h ctype.h sys/wait.h sys/ioctl.h)
|
||||
AC_CHECK_HEADERS(sys/filio.h string.h stdlib.h sys/socket.h sys/mode.h sys/un.h)
|
||||
AC_CHECK_HEADERS(glob.h mcheck.h sys/sysctl.h arpa/inet.h arpa/nameser.h)
|
||||
AC_CHECK_HEADERS(netdb.h)
|
||||
AC_CHECK_HEADERS(malloc.h)
|
||||
AC_CHECK_HEADERS(float.h)
|
||||
|
||||
AC_CHECK_SIZEOF(int)
|
||||
AC_CHECK_SIZEOF(long)
|
||||
@@ -339,7 +321,7 @@ if test x"$ac_cv_func_connect" = x"no"; then
|
||||
esac
|
||||
dnl We can't just call AC_CHECK_FUNCS(connect) here, because the value
|
||||
dnl has been cached.
|
||||
if test x"$ac_cv_lib_socket_connect" = x"yes" ||
|
||||
if test x"$ac_cv_lib_socket_connect" = x"yes" ||
|
||||
test x"$ac_cv_lib_inet_connect" = x"yes"; then
|
||||
# ac_cv_func_connect=yes
|
||||
# don't! it would cause AC_CHECK_FUNC to succeed next time configure is run
|
||||
@@ -351,8 +333,8 @@ AC_CHECK_LIB(resolv, inet_ntop)
|
||||
|
||||
dnl AC_MSG_NOTICE([Looking in libraries: $LIBS])
|
||||
|
||||
AC_CHECK_FUNCS(inet_ntop, , [AC_LIBOBJ(lib/inet_ntop)])
|
||||
AC_CHECK_FUNCS(inet_pton, , [AC_LIBOBJ(lib/inet_pton)])
|
||||
AC_CHECK_FUNCS(inet_ntop, , AC_LIBOBJ(lib/inet_ntop))
|
||||
AC_CHECK_FUNCS(inet_pton, , AC_LIBOBJ(lib/inet_pton))
|
||||
|
||||
# Irix 6.5 has getaddrinfo but not the corresponding defines, so use
|
||||
# builtin getaddrinfo if one of the defines don't exist
|
||||
@@ -364,7 +346,7 @@ AC_CACHE_CHECK([whether defines needed by getaddrinfo exist],
|
||||
#include <netdb.h>
|
||||
#ifdef AI_PASSIVE
|
||||
yes
|
||||
#endif],
|
||||
#endif],
|
||||
rsync_cv_HAVE_GETADDR_DEFINES=yes,
|
||||
rsync_cv_HAVE_GETADDR_DEFINES=no)])
|
||||
if test x"$rsync_cv_HAVE_GETADDR_DEFINES" = x"yes"; then
|
||||
@@ -381,27 +363,19 @@ if test x"$rsync_cv_HAVE_GETADDR_DEFINES" = x"yes"; then
|
||||
[Define if you have the `getaddrinfo' function.])],
|
||||
[AC_MSG_RESULT([no])
|
||||
AC_LIBOBJ(lib/getaddrinfo)])])
|
||||
AC_CHECK_FUNCS(getnameinfo, , [AC_LIBOBJ(lib/getnameinfo)])
|
||||
AC_CHECK_FUNCS(getnameinfo, , AC_LIBOBJ(lib/getnameinfo))
|
||||
else
|
||||
AC_LIBOBJ(lib/getaddrinfo)
|
||||
AC_LIBOBJ(lib/getnameinfo)
|
||||
fi
|
||||
|
||||
AC_CHECK_MEMBER([struct sockaddr.sa_len],
|
||||
[ AC_DEFINE(HAVE_SOCKADDR_LEN, 1, [Do we have sockaddr.sa_len?]) ],
|
||||
[],
|
||||
[
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
])
|
||||
|
||||
AC_CHECK_MEMBER([struct sockaddr_in.sin_len],
|
||||
[ AC_DEFINE(HAVE_SOCKADDR_IN_LEN, 1, [Do we have sockaddr_in.sin_len?]) ],
|
||||
AC_CHECK_MEMBER([struct sockaddr.sa_len],
|
||||
[ AC_DEFINE(HAVE_SOCKADDR_LEN) ],
|
||||
[],
|
||||
[
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
])
|
||||
|
||||
AC_MSG_CHECKING(struct sockaddr_storage)
|
||||
@@ -409,12 +383,12 @@ AC_TRY_COMPILE([#include <sys/types.h>
|
||||
#include <sys/socket.h>],
|
||||
[struct sockaddr_storage x;],
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_SOCKADDR_STORAGE, 1,
|
||||
AC_DEFINE(HAVE_SOCKADDR_STORAGE, 1,
|
||||
[Define if you have strct sockaddr_storage.] ),
|
||||
AC_MSG_RESULT(no))
|
||||
|
||||
AC_CHECK_MEMBER([struct sockaddr_in6.sin6_scope_id],
|
||||
[ AC_DEFINE(HAVE_SOCKADDR_IN6_SCOPE_ID, 1, [Do we have sockaddr_in6.sin6_scope_id?]) ],
|
||||
[ AC_DEFINE(HAVE_SOCKADDR_IN6_SCOPE_ID) ],
|
||||
[],
|
||||
[
|
||||
#include <sys/types.h>
|
||||
@@ -431,15 +405,15 @@ fi
|
||||
|
||||
dnl At the moment we don't test for a broken memcmp(), because all we
|
||||
dnl need to do is test for equality, not comparison, and it seems that
|
||||
dnl every platform has a memcmp that can do at least that.
|
||||
dnl every platform has a memcmp that can do at least that.
|
||||
dnl AC_FUNC_MEMCMP
|
||||
|
||||
AC_FUNC_UTIME_NULL
|
||||
AC_FUNC_ALLOCA
|
||||
AC_CHECK_FUNCS(waitpid wait4 getcwd strdup strerror chown chmod mknod mkfifo \
|
||||
fchmod fstat strchr readlink link utime utimes strftime mtrace \
|
||||
memmove lchown vsnprintf snprintf asprintf setsid glob strpbrk \
|
||||
strlcat strlcpy strtol mallinfo getgroups setgroups geteuid getegid)
|
||||
AC_CHECK_FUNCS(waitpid wait4 getcwd strdup strerror chown chmod mknod mkfifo)
|
||||
AC_CHECK_FUNCS(fchmod fstat strchr readlink link utime utimes strftime)
|
||||
AC_CHECK_FUNCS(memmove lchown vsnprintf snprintf asprintf setsid glob strpbrk)
|
||||
AC_CHECK_FUNCS(strlcat strlcpy strtol mtrace mallinfo setgroups)
|
||||
|
||||
AC_CACHE_CHECK([for working socketpair],rsync_cv_HAVE_SOCKETPAIR,[
|
||||
AC_TRY_RUN([
|
||||
@@ -455,6 +429,15 @@ if test x"$rsync_cv_HAVE_SOCKETPAIR" = x"yes"; then
|
||||
AC_DEFINE(HAVE_SOCKETPAIR, 1, [ ])
|
||||
fi
|
||||
|
||||
AC_CACHE_CHECK([for working fnmatch],rsync_cv_HAVE_FNMATCH,[
|
||||
AC_TRY_RUN([#include <fnmatch.h>
|
||||
main() { exit((fnmatch("*.o", "x.o", FNM_PATHNAME) == 0 &&
|
||||
fnmatch("a/b/*", "a/b/c/d", FNM_PATHNAME) != 0) ? 0: 1); }],
|
||||
rsync_cv_HAVE_FNMATCH=yes,rsync_cv_HAVE_FNMATCH=no,rsync_cv_HAVE_FNMATCH=cross)])
|
||||
if test x"$rsync_cv_HAVE_FNMATCH" = x"yes"; then
|
||||
AC_DEFINE(HAVE_FNMATCH, 1, [ ])
|
||||
fi
|
||||
|
||||
if test x"$with_included_popt" != x"yes"
|
||||
then
|
||||
AC_CHECK_LIB(popt, poptGetContext, , [with_included_popt=yes])
|
||||
@@ -545,7 +528,7 @@ AC_CACHE_CHECK([for C99 vsnprintf],rsync_cv_HAVE_C99_VSNPRINTF,[
|
||||
AC_TRY_RUN([
|
||||
#include <sys/types.h>
|
||||
#include <stdarg.h>
|
||||
void foo(const char *format, ...) {
|
||||
void foo(const char *format, ...) {
|
||||
va_list ap;
|
||||
int len;
|
||||
char buf[5];
|
||||
@@ -572,10 +555,10 @@ AC_TRY_RUN([#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
main() {
|
||||
main() {
|
||||
struct stat st;
|
||||
char tpl[20]="/tmp/test.XXXXXX";
|
||||
int fd = mkstemp(tpl);
|
||||
char tpl[20]="/tmp/test.XXXXXX";
|
||||
int fd = mkstemp(tpl);
|
||||
if (fd == -1) exit(1);
|
||||
unlink(tpl);
|
||||
if (fstat(fd, &st) != 0) exit(1);
|
||||
@@ -598,7 +581,7 @@ AC_TRY_RUN([
|
||||
#include <arpa/inet.h>
|
||||
main() { struct in_addr ip; ip.s_addr = 0x12345678;
|
||||
if (strcmp(inet_ntoa(ip),"18.52.86.120") &&
|
||||
strcmp(inet_ntoa(ip),"120.86.52.18")) { exit(1); }
|
||||
strcmp(inet_ntoa(ip),"120.86.52.18")) { exit(1); }
|
||||
exit(0);}],
|
||||
rsync_cv_REPLACE_INET_NTOA=no,rsync_cv_REPLACE_INET_NTOA=yes,rsync_cv_REPLACE_INET_NTOA=cross)])
|
||||
if test x"$rsync_cv_REPLACE_INET_NTOA" = x"yes"; then
|
||||
@@ -612,7 +595,7 @@ AC_TRY_RUN([
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
main() { struct in_addr ip;
|
||||
main() { struct in_addr ip;
|
||||
if (inet_aton("example", &ip) == 0) exit(0); exit(1);}],
|
||||
rsync_cv_REPLACE_INET_ATON=no,rsync_cv_REPLACE_INET_ATON=yes,rsync_cv_REPLACE_INET_ATON=cross)])
|
||||
if test x"$rsync_cv_REPLACE_INET_ATON" = x"yes"; then
|
||||
@@ -653,21 +636,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()
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#define RERR_SYNTAX 1 /* syntax or usage error */
|
||||
#define RERR_PROTOCOL 2 /* protocol incompatibility */
|
||||
#define RERR_FILESELECT 3 /* errors selecting input/output files, dirs */
|
||||
#define RERR_UNSUPPORTED 4 /* requested action not supported */
|
||||
#define RERR_UNSUPPORTED 4 /* requested action not supported */
|
||||
#define RERR_STARTCLIENT 5 /* error starting client-server protocol */
|
||||
|
||||
#define RERR_SOCKETIO 10 /* error in socket IO */
|
||||
@@ -39,7 +39,6 @@
|
||||
#define RERR_WAITCHILD 21 /* some error returned by waitpid() */
|
||||
#define RERR_MALLOC 22 /* error allocating core memory buffers */
|
||||
#define RERR_PARTIAL 23 /* partial transfer */
|
||||
#define RERR_VANISHED 24 /* file(s) vanished on sender side */
|
||||
|
||||
#define RERR_TIMEOUT 30 /* timeout in data send/receive */
|
||||
|
||||
|
||||
586
exclude.c
586
exclude.c
@@ -1,19 +1,19 @@
|
||||
/* -*- c-file-style: "linux" -*-
|
||||
*
|
||||
*
|
||||
* Copyright (C) 1996-2001 by Andrew Tridgell <tridge@samba.org>
|
||||
* Copyright (C) 1996 by Paul Mackerras
|
||||
* Copyright (C) 2002 by Martin Pool
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
@@ -27,167 +27,96 @@
|
||||
#include "rsync.h"
|
||||
|
||||
extern int verbose;
|
||||
extern int eol_nulls;
|
||||
extern int list_only;
|
||||
extern int recurse;
|
||||
extern int delete_mode;
|
||||
|
||||
extern char curr_dir[];
|
||||
|
||||
struct exclude_list_struct exclude_list = { 0, 0, "" };
|
||||
struct exclude_list_struct local_exclude_list = { 0, 0, "per-dir .cvsignore " };
|
||||
struct exclude_list_struct server_exclude_list = { 0, 0, "server " };
|
||||
char *exclude_path_prefix = NULL;
|
||||
static struct exclude_struct **exclude_list;
|
||||
|
||||
/** Build an exclude structure given a exclude pattern */
|
||||
static void make_exclude(struct exclude_list_struct *listp, const char *pattern,
|
||||
int pat_len, int include)
|
||||
static struct exclude_struct *make_exclude(const char *pattern, int include)
|
||||
{
|
||||
struct exclude_struct *ret;
|
||||
const char *cp;
|
||||
int ex_len;
|
||||
|
||||
ret = new(struct exclude_struct);
|
||||
if (!ret)
|
||||
out_of_memory("make_exclude");
|
||||
if (!ret) out_of_memory("make_exclude");
|
||||
|
||||
memset(ret, 0, sizeof ret[0]);
|
||||
ret->include = include;
|
||||
memset(ret, 0, sizeof(*ret));
|
||||
|
||||
if (exclude_path_prefix)
|
||||
ret->match_flags |= MATCHFLG_ABS_PATH;
|
||||
if (exclude_path_prefix && *pattern == '/')
|
||||
ex_len = strlen(exclude_path_prefix);
|
||||
else
|
||||
ex_len = 0;
|
||||
ret->pattern = new_array(char, ex_len + pat_len + 1);
|
||||
if (!ret->pattern)
|
||||
out_of_memory("make_exclude");
|
||||
if (ex_len)
|
||||
memcpy(ret->pattern, exclude_path_prefix, ex_len);
|
||||
strlcpy(ret->pattern + ex_len, pattern, pat_len + 1);
|
||||
pat_len += ex_len;
|
||||
|
||||
if (strpbrk(ret->pattern, "*[?")) {
|
||||
ret->match_flags |= MATCHFLG_WILD;
|
||||
if ((cp = strstr(ret->pattern, "**")) != NULL) {
|
||||
ret->match_flags |= MATCHFLG_WILD2;
|
||||
/* If the pattern starts with **, note that. */
|
||||
if (cp == ret->pattern)
|
||||
ret->match_flags |= MATCHFLG_WILD2_PREFIX;
|
||||
}
|
||||
if (strncmp(pattern,"- ",2) == 0) {
|
||||
pattern += 2;
|
||||
} else if (strncmp(pattern,"+ ",2) == 0) {
|
||||
ret->include = 1;
|
||||
pattern += 2;
|
||||
} else {
|
||||
ret->include = include;
|
||||
}
|
||||
|
||||
if (pat_len > 1 && ret->pattern[pat_len-1] == '/') {
|
||||
ret->pattern[pat_len-1] = 0;
|
||||
ret->pattern = strdup(pattern);
|
||||
|
||||
if (!ret->pattern) out_of_memory("make_exclude");
|
||||
|
||||
if (strpbrk(pattern, "*[?")) {
|
||||
ret->regular_exp = 1;
|
||||
ret->fnmatch_flags = FNM_PATHNAME;
|
||||
if (strstr(pattern, "**")) {
|
||||
static int tested;
|
||||
if (!tested) {
|
||||
tested = 1;
|
||||
if (fnmatch("a/b/*", "a/b/c/d", FNM_PATHNAME)==0) {
|
||||
rprintf(FERROR,"WARNING: fnmatch FNM_PATHNAME is broken on your system\n");
|
||||
}
|
||||
}
|
||||
ret->fnmatch_flags = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (strlen(pattern) > 1 && pattern[strlen(pattern)-1] == '/') {
|
||||
ret->pattern[strlen(pattern)-1] = 0;
|
||||
ret->directory = 1;
|
||||
}
|
||||
|
||||
for (cp = ret->pattern; (cp = strchr(cp, '/')) != NULL; cp++)
|
||||
ret->slash_cnt++;
|
||||
|
||||
if (!listp->tail)
|
||||
listp->head = listp->tail = ret;
|
||||
else {
|
||||
listp->tail->next = ret;
|
||||
listp->tail = ret;
|
||||
if (!strchr(ret->pattern,'/')) {
|
||||
ret->local = 1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void free_exclude(struct exclude_struct *ex)
|
||||
{
|
||||
free(ex->pattern);
|
||||
memset(ex,0,sizeof(*ex));
|
||||
free(ex);
|
||||
}
|
||||
|
||||
void free_exclude_list(struct exclude_list_struct *listp)
|
||||
{
|
||||
struct exclude_struct *ent, *next;
|
||||
|
||||
if (verbose > 2) {
|
||||
rprintf(FINFO, "[%s] clearing %sexclude list\n",
|
||||
who_am_i(), listp->debug_type);
|
||||
}
|
||||
|
||||
for (ent = listp->head; ent; ent = next) {
|
||||
next = ent->next;
|
||||
free_exclude(ent);
|
||||
}
|
||||
|
||||
listp->head = listp->tail = NULL;
|
||||
}
|
||||
|
||||
static int check_one_exclude(char *name, struct exclude_struct *ex,
|
||||
int name_is_dir)
|
||||
STRUCT_STAT *st)
|
||||
{
|
||||
char *p;
|
||||
int match_start = 0;
|
||||
int match_start=0;
|
||||
char *pattern = ex->pattern;
|
||||
|
||||
/* If the pattern does not have any slashes AND it does not have
|
||||
* a "**" (which could match a slash), then we just match the
|
||||
* name portion of the path. */
|
||||
if (!ex->slash_cnt && !(ex->match_flags & MATCHFLG_WILD2)) {
|
||||
if ((p = strrchr(name,'/')) != NULL)
|
||||
name = p+1;
|
||||
}
|
||||
else if ((ex->match_flags & MATCHFLG_ABS_PATH) && *name != '/') {
|
||||
static char full_name[MAXPATHLEN];
|
||||
int plus = curr_dir[1] == '\0'? 1 : 0;
|
||||
pathjoin(full_name, sizeof full_name, curr_dir+plus, name);
|
||||
name = full_name;
|
||||
}
|
||||
if (ex->local && (p=strrchr(name,'/')))
|
||||
name = p+1;
|
||||
|
||||
if (!name[0]) return 0;
|
||||
|
||||
if (ex->directory && !name_is_dir) return 0;
|
||||
if (ex->directory && !S_ISDIR(st->st_mode)) return 0;
|
||||
|
||||
if (*pattern == '/') {
|
||||
if (*pattern == '/' && *name != '/') {
|
||||
match_start = 1;
|
||||
pattern++;
|
||||
if (*name == '/')
|
||||
name++;
|
||||
}
|
||||
|
||||
if (ex->match_flags & MATCHFLG_WILD) {
|
||||
/* A non-anchored match with an infix slash and no "**"
|
||||
* needs to match the last slash_cnt+1 name elements. */
|
||||
if (!match_start && ex->slash_cnt &&
|
||||
!(ex->match_flags & MATCHFLG_WILD2)) {
|
||||
int cnt = ex->slash_cnt + 1;
|
||||
for (p = name + strlen(name) - 1; p >= name; p--) {
|
||||
if (*p == '/' && !--cnt)
|
||||
break;
|
||||
}
|
||||
name = p+1;
|
||||
}
|
||||
if (wildmatch(pattern, name))
|
||||
if (ex->regular_exp) {
|
||||
if (fnmatch(pattern, name, ex->fnmatch_flags) == 0) {
|
||||
return 1;
|
||||
if (ex->match_flags & MATCHFLG_WILD2_PREFIX) {
|
||||
/* If the **-prefixed pattern has a '/' as the next
|
||||
* character, then try to match the rest of the
|
||||
* pattern at the root. */
|
||||
if (pattern[2] == '/' && wildmatch(pattern+3, name))
|
||||
return 1;
|
||||
}
|
||||
else if (!match_start && ex->match_flags & MATCHFLG_WILD2) {
|
||||
/* A non-anchored match with an infix or trailing "**"
|
||||
* (but not a prefixed "**") needs to try matching
|
||||
* after every slash. */
|
||||
while ((name = strchr(name, '/')) != NULL) {
|
||||
name++;
|
||||
if (wildmatch(pattern, name))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
} else if (match_start) {
|
||||
if (strcmp(name,pattern) == 0)
|
||||
return 1;
|
||||
} else {
|
||||
int l1 = strlen(name);
|
||||
int l2 = strlen(pattern);
|
||||
if (l2 <= l1 &&
|
||||
if (l2 <= l1 &&
|
||||
strcmp(name+(l1-l2),pattern) == 0 &&
|
||||
(l1==l2 || name[l1-(l2+1)] == '/')) {
|
||||
(l1==l2 || (!match_start && name[l1-(l2+1)] == '/'))) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -198,249 +127,292 @@ static int check_one_exclude(char *name, struct exclude_struct *ex,
|
||||
|
||||
static void report_exclude_result(char const *name,
|
||||
struct exclude_struct const *ent,
|
||||
int name_is_dir, const char *type)
|
||||
STRUCT_STAT const *st)
|
||||
{
|
||||
/* If a trailing slash is present to match only directories,
|
||||
* then it is stripped out by make_exclude. So as a special
|
||||
* case we add it back in here. */
|
||||
|
||||
if (verbose >= 2) {
|
||||
rprintf(FINFO, "[%s] %scluding %s %s because of %spattern %s%s\n",
|
||||
who_am_i(), ent->include ? "in" : "ex",
|
||||
name_is_dir ? "directory" : "file", name, type,
|
||||
ent->pattern, ent->directory ? "/" : "");
|
||||
}
|
||||
/* If a trailing slash is present to match only directories,
|
||||
* then it is stripped out by make_exclude. So as a special
|
||||
* case we add it back in here. */
|
||||
|
||||
if (verbose >= 2)
|
||||
rprintf(FINFO, "%s %s %s because of pattern %s%s\n",
|
||||
ent->include ? "including" : "excluding",
|
||||
S_ISDIR(st->st_mode) ? "directory" : "file",
|
||||
name, ent->pattern,
|
||||
ent->directory ? "/" : "");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return -1 if file "name" is defined to be excluded by the specified
|
||||
* exclude list, 1 if it is included, and 0 if it was not matched.
|
||||
* Return true if file NAME is defined to be excluded by either
|
||||
* LOCAL_EXCLUDE_LIST or the globals EXCLUDE_LIST.
|
||||
*/
|
||||
int check_exclude(struct exclude_list_struct *listp, char *name, int name_is_dir)
|
||||
int check_exclude(char *name, struct exclude_struct **local_exclude_list,
|
||||
STRUCT_STAT *st)
|
||||
{
|
||||
struct exclude_struct *ent;
|
||||
int n;
|
||||
struct exclude_struct *ent;
|
||||
|
||||
for (ent = listp->head; ent; ent = ent->next) {
|
||||
if (check_one_exclude(name, ent, name_is_dir)) {
|
||||
report_exclude_result(name, ent, name_is_dir,
|
||||
listp->debug_type);
|
||||
return ent->include ? 1 : -1;
|
||||
}
|
||||
if (name && (name[0] == '.') && !name[1])
|
||||
/* never exclude '.', even if somebody does --exclude '*' */
|
||||
return 0;
|
||||
|
||||
if (exclude_list) {
|
||||
for (n=0; exclude_list[n]; n++) {
|
||||
ent = exclude_list[n];
|
||||
if (check_one_exclude(name, ent, st)) {
|
||||
report_exclude_result(name, ent, st);
|
||||
return !ent->include;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (local_exclude_list) {
|
||||
for (n=0; local_exclude_list[n]; n++) {
|
||||
ent = local_exclude_list[n];
|
||||
if (check_one_exclude(name, ent, st)) {
|
||||
report_exclude_result(name, ent, st);
|
||||
return !ent->include;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Get the next include/exclude arg from the string. The token will not
|
||||
* be '\0' terminated, so use the returned length to limit the string.
|
||||
* Also, be sure to add this length to the returned pointer before passing
|
||||
* it back to ask for the next token. This routine will not parse the +/-
|
||||
* prefixes or the "!" token when xflags contains XFLG_WORDS_ONLY. The
|
||||
* *incl_ptr value will be 1 for an include, 0 for an exclude, and -1 for
|
||||
* the list-clearing "!" token.
|
||||
*/
|
||||
static const char *get_exclude_tok(const char *p, int *len_ptr, int *incl_ptr,
|
||||
int xflags)
|
||||
void add_exclude_list(const char *pattern, struct exclude_struct ***list, int include)
|
||||
{
|
||||
const unsigned char *s = (const unsigned char *)p;
|
||||
int len;
|
||||
int len=0;
|
||||
if (list && *list)
|
||||
for (; (*list)[len]; len++) ;
|
||||
|
||||
if (xflags & XFLG_WORD_SPLIT) {
|
||||
/* Skip over any initial whitespace. */
|
||||
while (isspace(*s))
|
||||
s++;
|
||||
/* Update for "!" check. */
|
||||
p = (const char *)s;
|
||||
}
|
||||
|
||||
/* Is this a '+' or '-' followed by a space (not whitespace)? */
|
||||
if (!(xflags & XFLG_WORDS_ONLY)
|
||||
&& (*s == '-' || *s == '+') && s[1] == ' ') {
|
||||
*incl_ptr = *s == '+';
|
||||
s += 2;
|
||||
} else
|
||||
*incl_ptr = xflags & XFLG_DEF_INCLUDE;
|
||||
|
||||
if (xflags & XFLG_WORD_SPLIT) {
|
||||
const unsigned char *cp = s;
|
||||
/* Token ends at whitespace or the end of the string. */
|
||||
while (!isspace(*cp) && *cp != '\0')
|
||||
cp++;
|
||||
len = cp - s;
|
||||
} else
|
||||
len = strlen(s);
|
||||
|
||||
if (*p == '!' && len == 1 && !(xflags & XFLG_WORDS_ONLY))
|
||||
*incl_ptr = -1;
|
||||
|
||||
*len_ptr = len;
|
||||
return (const char *)s;
|
||||
}
|
||||
|
||||
|
||||
void add_exclude(struct exclude_list_struct *listp, const char *pattern,
|
||||
int xflags)
|
||||
{
|
||||
int pat_len, incl;
|
||||
const char *cp;
|
||||
|
||||
if (!pattern)
|
||||
return;
|
||||
|
||||
cp = pattern;
|
||||
pat_len = 0;
|
||||
while (1) {
|
||||
cp = get_exclude_tok(cp + pat_len, &pat_len, &incl, xflags);
|
||||
if (!pat_len)
|
||||
break;
|
||||
/* If we got the special "!" token, clear the list. */
|
||||
if (incl < 0)
|
||||
free_exclude_list(listp);
|
||||
else {
|
||||
make_exclude(listp, cp, pat_len, incl);
|
||||
|
||||
if (verbose > 2) {
|
||||
rprintf(FINFO, "[%s] add_exclude(%.*s, %s%s)\n",
|
||||
who_am_i(), pat_len, cp,
|
||||
listp->debug_type,
|
||||
incl ? "include" : "exclude");
|
||||
}
|
||||
if (strcmp(pattern,"!") == 0) {
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"clearing exclude list\n");
|
||||
while ((len)--) {
|
||||
free_exclude((*list)[len]);
|
||||
}
|
||||
free((*list));
|
||||
*list = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
*list = realloc_array(*list, struct exclude_struct *, len+2);
|
||||
|
||||
if (!*list || !((*list)[len] = make_exclude(pattern, include)))
|
||||
out_of_memory("add_exclude");
|
||||
|
||||
if (verbose > 2) {
|
||||
rprintf(FINFO,"add_exclude(%s,%s)\n",pattern,
|
||||
include ? "include" : "exclude");
|
||||
}
|
||||
|
||||
(*list)[len+1] = NULL;
|
||||
}
|
||||
|
||||
|
||||
void add_exclude_file(struct exclude_list_struct *listp, const char *fname,
|
||||
int xflags)
|
||||
void add_exclude(const char *pattern, int include)
|
||||
{
|
||||
FILE *fp;
|
||||
add_exclude_list(pattern,&exclude_list, include);
|
||||
}
|
||||
|
||||
struct exclude_struct **make_exclude_list(const char *fname,
|
||||
struct exclude_struct **list1,
|
||||
int fatal, int include)
|
||||
{
|
||||
struct exclude_struct **list=list1;
|
||||
FILE *f;
|
||||
char line[MAXPATHLEN];
|
||||
char *eob = line + MAXPATHLEN - 1;
|
||||
int word_split = xflags & XFLG_WORD_SPLIT;
|
||||
|
||||
if (!fname || !*fname)
|
||||
return;
|
||||
|
||||
if (*fname != '-' || fname[1])
|
||||
fp = fopen(fname, "rb");
|
||||
else
|
||||
fp = stdin;
|
||||
if (!fp) {
|
||||
if (xflags & XFLG_FATAL_ERRORS) {
|
||||
if (strcmp(fname, "-")) {
|
||||
f = fopen(fname,"r");
|
||||
} else {
|
||||
f = fdopen(0, "r");
|
||||
}
|
||||
if (!f) {
|
||||
if (fatal) {
|
||||
rsyserr(FERROR, errno,
|
||||
"failed to open %s file %s",
|
||||
xflags & XFLG_DEF_INCLUDE ? "include" : "exclude",
|
||||
fname);
|
||||
"failed to open %s file %s",
|
||||
include ? "include" : "exclude",
|
||||
fname);
|
||||
exit_cleanup(RERR_FILEIO);
|
||||
}
|
||||
return;
|
||||
return list;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
char *s = line;
|
||||
int ch;
|
||||
while (1) {
|
||||
if ((ch = getc(fp)) == EOF) {
|
||||
if (ferror(fp) && errno == EINTR)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
if (word_split && isspace(ch))
|
||||
break;
|
||||
if (eol_nulls? !ch : (ch == '\n' || ch == '\r'))
|
||||
break;
|
||||
if (s < eob)
|
||||
*s++ = ch;
|
||||
while (fgets(line,MAXPATHLEN,f)) {
|
||||
int l = strlen(line);
|
||||
while (l && (line[l-1] == '\n' || line[l-1] == '\r')) l--;
|
||||
line[l] = 0;
|
||||
if (line[0] && (line[0] != ';') && (line[0] != '#')) {
|
||||
/* Skip lines starting with semicolon or pound.
|
||||
It probably wouldn't cause any harm to not skip
|
||||
them but there's no need to save them. */
|
||||
add_exclude_list(line,&list,include);
|
||||
}
|
||||
*s = '\0';
|
||||
/* Skip an empty token and (when line parsing) comments. */
|
||||
if (*line && (word_split || (*line != ';' && *line != '#')))
|
||||
add_exclude(listp, line, xflags);
|
||||
if (ch == EOF)
|
||||
break;
|
||||
}
|
||||
fclose(fp);
|
||||
fclose(f);
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
void add_exclude_file(const char *fname, int fatal, int include)
|
||||
{
|
||||
if (!fname || !*fname) return;
|
||||
|
||||
exclude_list = make_exclude_list(fname,exclude_list,fatal,include);
|
||||
}
|
||||
|
||||
|
||||
void send_exclude_list(int f)
|
||||
{
|
||||
struct exclude_struct *ent;
|
||||
int i;
|
||||
extern int remote_version;
|
||||
extern int list_only, recurse;
|
||||
|
||||
/* This is a complete hack - blame Rusty.
|
||||
*
|
||||
* FIXME: This pattern shows up in the output of
|
||||
* report_exclude_result(), which is not ideal. */
|
||||
if (list_only && !recurse)
|
||||
add_exclude(&exclude_list, "/*/*", 0);
|
||||
|
||||
for (ent = exclude_list.head; ent; ent = ent->next) {
|
||||
unsigned int l;
|
||||
char p[MAXPATHLEN+1];
|
||||
|
||||
l = strlcpy(p, ent->pattern, sizeof p);
|
||||
if (l == 0 || l >= MAXPATHLEN)
|
||||
continue;
|
||||
if (ent->directory) {
|
||||
p[l++] = '/';
|
||||
p[l] = '\0';
|
||||
}
|
||||
|
||||
if (ent->include) {
|
||||
write_int(f, l + 2);
|
||||
write_buf(f, "+ ", 2);
|
||||
} else if ((*p == '-' || *p == '+') && p[1] == ' ') {
|
||||
write_int(f, l + 2);
|
||||
write_buf(f, "- ", 2);
|
||||
} else
|
||||
write_int(f, l);
|
||||
write_buf(f, p, l);
|
||||
if (list_only && !recurse) {
|
||||
add_exclude("/*/*", 0);
|
||||
}
|
||||
|
||||
write_int(f, 0);
|
||||
if (!exclude_list) {
|
||||
write_int(f,0);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i=0;exclude_list[i];i++) {
|
||||
int l;
|
||||
char pattern[MAXPATHLEN];
|
||||
|
||||
strlcpy(pattern,exclude_list[i]->pattern,sizeof(pattern));
|
||||
if (exclude_list[i]->directory) strlcat(pattern,"/", sizeof(pattern));
|
||||
|
||||
l = strlen(pattern);
|
||||
if (l == 0) continue;
|
||||
if (exclude_list[i]->include) {
|
||||
if (remote_version < 19) {
|
||||
rprintf(FERROR,"remote rsync does not support include syntax - aborting\n");
|
||||
exit_cleanup(RERR_UNSUPPORTED);
|
||||
}
|
||||
write_int(f,l+2);
|
||||
write_buf(f,"+ ",2);
|
||||
} else {
|
||||
write_int(f,l);
|
||||
}
|
||||
write_buf(f,pattern,l);
|
||||
}
|
||||
|
||||
write_int(f,0);
|
||||
}
|
||||
|
||||
|
||||
void recv_exclude_list(int f)
|
||||
{
|
||||
char line[MAXPATHLEN+1]; /* Allows a trailing slash on a max-len dir */
|
||||
char line[MAXPATHLEN];
|
||||
unsigned int l;
|
||||
|
||||
while ((l = read_int(f)) != 0) {
|
||||
if (l >= sizeof line)
|
||||
overflow("recv_exclude_list");
|
||||
read_sbuf(f, line, l);
|
||||
add_exclude(&exclude_list, line, 0);
|
||||
while ((l=read_int(f))) {
|
||||
if (l >= MAXPATHLEN) overflow("recv_exclude_list");
|
||||
read_sbuf(f,line,l);
|
||||
add_exclude(line,0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the next include/exclude arg from the string. It works in a similar way
|
||||
** to strtok - initially an arg is sent over, from then on NULL. This
|
||||
** routine takes into account any +/- in the strings and does not
|
||||
** consider the space following it as a delimeter.
|
||||
*/
|
||||
char *get_exclude_tok(char *p)
|
||||
{
|
||||
static char *s;
|
||||
static int more;
|
||||
char *t;
|
||||
|
||||
if (p) {
|
||||
s=p;
|
||||
if (*p)
|
||||
more=1;
|
||||
}
|
||||
|
||||
if (!more)
|
||||
return(NULL);
|
||||
|
||||
/* Skip over any initial spaces */
|
||||
while (isspace(* (unsigned char *) s))
|
||||
s++;
|
||||
|
||||
/* Are we at the end of the string? */
|
||||
if (*s) {
|
||||
/* remember the beginning of the token */
|
||||
t=s;
|
||||
|
||||
/* Is this a '+' or '-' followed by a space (not whitespace)? */
|
||||
if ((*s=='+' || *s=='-') && *(s+1)==' ')
|
||||
s+=2;
|
||||
|
||||
/* Skip to the next space or the end of the string */
|
||||
while (!isspace(* (unsigned char *) s) && *s != '\0')
|
||||
s++;
|
||||
} else {
|
||||
t=NULL;
|
||||
}
|
||||
|
||||
/* Have we reached the end of the string? */
|
||||
if (*s)
|
||||
*s++='\0';
|
||||
else
|
||||
more=0;
|
||||
return(t);
|
||||
}
|
||||
|
||||
|
||||
void add_exclude_line(char *p)
|
||||
{
|
||||
char *tok;
|
||||
if (!p || !*p) return;
|
||||
p = strdup(p);
|
||||
if (!p) out_of_memory("add_exclude_line");
|
||||
for (tok=get_exclude_tok(p); tok; tok=get_exclude_tok(NULL))
|
||||
add_exclude(tok, 0);
|
||||
free(p);
|
||||
}
|
||||
|
||||
void add_include_line(char *p)
|
||||
{
|
||||
char *tok;
|
||||
if (!p || !*p) return;
|
||||
p = strdup(p);
|
||||
if (!p) out_of_memory("add_include_line");
|
||||
for (tok=get_exclude_tok(p); tok; tok=get_exclude_tok(NULL))
|
||||
add_exclude(tok, 1);
|
||||
free(p);
|
||||
}
|
||||
|
||||
|
||||
static char *cvs_ignore_list[] = {
|
||||
"RCS/", "SCCS/", "CVS/", ".svn/", "CVS.adm", "RCSLOG", "cvslog.*",
|
||||
"tags", "TAGS", ".make.state", ".nse_depinfo",
|
||||
"*~", "#*", ".#*", ", *", "*.old", "*.bak", "*.BAK", "*.orig",
|
||||
"*.rej", ".del-*", "*.a", "*.o", "*.obj", "*.so", "*.Z", "*.elc", "*.ln",
|
||||
"core", NULL};
|
||||
|
||||
static char default_cvsignore[] =
|
||||
/* These default ignored items come from the CVS manual. */
|
||||
"RCS SCCS CVS CVS.adm RCSLOG cvslog.* tags TAGS"
|
||||
" .make.state .nse_depinfo *~ #* .#* ,* _$* *$"
|
||||
" *.old *.bak *.BAK *.orig *.rej .del-*"
|
||||
" *.a *.olb *.o *.obj *.so *.exe"
|
||||
" *.Z *.elc *.ln core"
|
||||
/* The rest we added to suit ourself. */
|
||||
" .svn/";
|
||||
|
||||
void add_cvs_excludes(void)
|
||||
{
|
||||
char fname[MAXPATHLEN];
|
||||
char *p;
|
||||
int i;
|
||||
|
||||
for (i=0; cvs_ignore_list[i]; i++)
|
||||
add_exclude(cvs_ignore_list[i], 0);
|
||||
|
||||
add_exclude(&exclude_list, default_cvsignore,
|
||||
XFLG_WORD_SPLIT | XFLG_WORDS_ONLY);
|
||||
|
||||
if ((p = getenv("HOME"))
|
||||
&& pathjoin(fname, sizeof fname, p, ".cvsignore") < sizeof fname) {
|
||||
add_exclude_file(&exclude_list, fname,
|
||||
XFLG_WORD_SPLIT | XFLG_WORDS_ONLY);
|
||||
if ((p=getenv("HOME")) && strlen(p) < (MAXPATHLEN-12)) {
|
||||
snprintf(fname,sizeof(fname), "%s/.cvsignore",p);
|
||||
add_exclude_file(fname,0,0);
|
||||
}
|
||||
|
||||
add_exclude(&exclude_list, getenv("CVSIGNORE"),
|
||||
XFLG_WORD_SPLIT | XFLG_WORDS_ONLY);
|
||||
add_exclude_line(getenv("CVSIGNORE"));
|
||||
}
|
||||
|
||||
98
fileio.c
98
fileio.c
@@ -1,24 +1,24 @@
|
||||
/*
|
||||
/*
|
||||
Copyright (C) Andrew Tridgell 1998
|
||||
Copyright (C) 2002 by Martin Pool
|
||||
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
File IO utilities used in rsync
|
||||
File IO utilities used in rsync
|
||||
*/
|
||||
#include "rsync.h"
|
||||
|
||||
@@ -42,8 +42,8 @@ static int write_sparse(int f,char *buf,size_t len)
|
||||
size_t l1=0, l2=0;
|
||||
int ret;
|
||||
|
||||
for (l1 = 0; l1 < len && buf[l1] == 0; l1++) {}
|
||||
for (l2 = 0; l2 < len-l1 && buf[len-(l2+1)] == 0; l2++) {}
|
||||
for (l1=0;l1<len && buf[l1]==0;l1++) ;
|
||||
for (l2=0;l2<(len-l1) && buf[len-(l2+1)]==0;l2++) ;
|
||||
|
||||
last_byte = buf[len-1];
|
||||
|
||||
@@ -51,79 +51,37 @@ static int write_sparse(int f,char *buf,size_t len)
|
||||
last_sparse=1;
|
||||
|
||||
if (l1 > 0) {
|
||||
do_lseek(f,l1,SEEK_CUR);
|
||||
do_lseek(f,l1,SEEK_CUR);
|
||||
}
|
||||
|
||||
if (l1 == len)
|
||||
if (l1 == len)
|
||||
return len;
|
||||
|
||||
ret = write(f, buf + l1, len - (l1+l2));
|
||||
if (ret == -1 || ret == 0)
|
||||
return ret;
|
||||
else if (ret != (int) (len - (l1+l2)))
|
||||
else if (ret != (int) (len - (l1+l2)))
|
||||
return (l1+ret);
|
||||
|
||||
if (l2 > 0)
|
||||
do_lseek(f,l2,SEEK_CUR);
|
||||
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
static char *wf_writeBuf;
|
||||
static size_t wf_writeBufSize;
|
||||
static size_t wf_writeBufCnt;
|
||||
|
||||
int flush_write_file(int f)
|
||||
{
|
||||
int ret = 0;
|
||||
char *bp = wf_writeBuf;
|
||||
|
||||
while (wf_writeBufCnt > 0) {
|
||||
if ((ret = write(f, bp, wf_writeBufCnt)) < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
return ret;
|
||||
}
|
||||
wf_writeBufCnt -= ret;
|
||||
bp += ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* write_file does not allow incomplete writes. It loops internally
|
||||
* until len bytes are written or errno is set.
|
||||
*/
|
||||
int write_file(int f,char *buf,size_t len)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
while (len > 0) {
|
||||
int r1;
|
||||
if (sparse_files) {
|
||||
int len1 = MIN(len, SPARSE_WRITE_SIZE);
|
||||
r1 = write_sparse(f, buf, len1);
|
||||
} else {
|
||||
if (!wf_writeBuf) {
|
||||
wf_writeBufSize = MAX_MAP_SIZE;
|
||||
wf_writeBufCnt = 0;
|
||||
wf_writeBuf = new_array(char, MAX_MAP_SIZE);
|
||||
if (!wf_writeBuf)
|
||||
out_of_memory("write_file");
|
||||
}
|
||||
r1 = MIN(len, wf_writeBufSize - wf_writeBufCnt);
|
||||
if (r1) {
|
||||
memcpy(wf_writeBuf + wf_writeBufCnt, buf, r1);
|
||||
wf_writeBufCnt += r1;
|
||||
}
|
||||
if (wf_writeBufCnt == wf_writeBufSize) {
|
||||
if (flush_write_file(f) < 0)
|
||||
return -1;
|
||||
if (!r1 && len)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (!sparse_files) {
|
||||
return write(f,buf,len);
|
||||
}
|
||||
|
||||
while (len>0) {
|
||||
int len1 = MIN(len, SPARSE_WRITE_SIZE);
|
||||
int r1 = write_sparse(f, buf, len1);
|
||||
if (r1 <= 0) {
|
||||
if (ret > 0) return ret;
|
||||
return r1;
|
||||
@@ -154,7 +112,6 @@ struct map_struct *map_file(int fd,OFF_T len)
|
||||
map->p_offset = 0;
|
||||
map->p_fd_offset = 0;
|
||||
map->p_len = 0;
|
||||
map->status = 0;
|
||||
|
||||
return map;
|
||||
}
|
||||
@@ -176,7 +133,7 @@ char *map_ptr(struct map_struct *map,OFF_T offset,int len)
|
||||
}
|
||||
|
||||
/* in most cases the region will already be available */
|
||||
if (offset >= map->p_offset &&
|
||||
if (offset >= map->p_offset &&
|
||||
offset+len <= map->p_offset+map->p_len) {
|
||||
return (map->p + (offset - map->p_offset));
|
||||
}
|
||||
@@ -231,11 +188,7 @@ char *map_ptr(struct map_struct *map,OFF_T offset,int len)
|
||||
}
|
||||
|
||||
if ((nread=read(map->fd,map->p + read_offset,read_size)) != read_size) {
|
||||
if (nread < 0) {
|
||||
nread = 0;
|
||||
if (!map->status)
|
||||
map->status = errno;
|
||||
}
|
||||
if (nread < 0) nread = 0;
|
||||
/* the best we can do is zero the buffer - the file
|
||||
has changed mid transfer! */
|
||||
memset(map->p+read_offset+nread, 0, read_size - nread);
|
||||
@@ -245,23 +198,18 @@ char *map_ptr(struct map_struct *map,OFF_T offset,int len)
|
||||
|
||||
map->p_offset = window_start;
|
||||
map->p_len = window_size;
|
||||
|
||||
return map->p + (offset - map->p_offset);
|
||||
|
||||
return map->p + (offset - map->p_offset);
|
||||
}
|
||||
|
||||
|
||||
int unmap_file(struct map_struct *map)
|
||||
void unmap_file(struct map_struct *map)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (map->p) {
|
||||
free(map->p);
|
||||
map->p = NULL;
|
||||
}
|
||||
ret = map->status;
|
||||
memset(map, 0, sizeof(*map));
|
||||
free(map);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
196
generator.c
196
generator.c
@@ -30,9 +30,6 @@ extern int preserve_links;
|
||||
extern int am_root;
|
||||
extern int preserve_devices;
|
||||
extern int preserve_hard_links;
|
||||
extern int preserve_perms;
|
||||
extern int preserve_uid;
|
||||
extern int preserve_gid;
|
||||
extern int update_only;
|
||||
extern int opt_ignore_existing;
|
||||
extern int csum_length;
|
||||
@@ -41,33 +38,31 @@ extern int size_only;
|
||||
extern int io_timeout;
|
||||
extern int protocol_version;
|
||||
extern int always_checksum;
|
||||
extern int modify_window;
|
||||
extern char *compare_dest;
|
||||
extern int link_dest;
|
||||
extern int whole_file;
|
||||
extern int local_server;
|
||||
extern int write_batch;
|
||||
extern int list_only;
|
||||
extern int only_existing;
|
||||
extern int orig_umask;
|
||||
extern int safe_symlinks;
|
||||
|
||||
|
||||
/* choose whether to skip a particular file */
|
||||
static int skip_file(char *fname, struct file_struct *file, STRUCT_STAT *st)
|
||||
static int skip_file(char *fname,
|
||||
struct file_struct *file, STRUCT_STAT *st)
|
||||
{
|
||||
if (st->st_size != file->length) {
|
||||
return 0;
|
||||
}
|
||||
if (link_dest) {
|
||||
if (preserve_perms
|
||||
&& (st->st_mode & CHMOD_BITS) != (file->mode & CHMOD_BITS))
|
||||
extern int preserve_perms;
|
||||
extern int preserve_uid;
|
||||
extern int preserve_gid;
|
||||
|
||||
if(preserve_perms
|
||||
&& (st->st_mode & ~_S_IFMT) != (file->mode & ~_S_IFMT))
|
||||
return 0;
|
||||
|
||||
if (am_root && preserve_uid && st->st_uid != file->uid)
|
||||
if (preserve_uid && st->st_uid != file->uid)
|
||||
return 0;
|
||||
|
||||
if (preserve_gid && file->gid != GID_NONE
|
||||
&& st->st_gid != file->gid)
|
||||
if (preserve_gid && st->st_gid != file->gid)
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -79,14 +74,17 @@ static int skip_file(char *fname, struct file_struct *file, STRUCT_STAT *st)
|
||||
|
||||
if (compare_dest != NULL) {
|
||||
if (access(fname, 0) != 0) {
|
||||
pathjoin(fnamecmpdest, sizeof fnamecmpdest,
|
||||
compare_dest, fname);
|
||||
snprintf(fnamecmpdest,MAXPATHLEN,"%s/%s",
|
||||
compare_dest,fname);
|
||||
fname = fnamecmpdest;
|
||||
}
|
||||
}
|
||||
file_checksum(fname,sum,st->st_size);
|
||||
return memcmp(sum, file->u.sum, protocol_version < 21 ? 2
|
||||
: MD4_SUM_LENGTH) == 0;
|
||||
if (protocol_version < 21) {
|
||||
return (memcmp(sum,file->sum,2) == 0);
|
||||
} else {
|
||||
return (memcmp(sum,file->sum,MD4_SUM_LENGTH) == 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (size_only) {
|
||||
@@ -102,13 +100,14 @@ static int skip_file(char *fname, struct file_struct *file, STRUCT_STAT *st)
|
||||
|
||||
|
||||
/*
|
||||
* NULL sum_struct means we have no checksums
|
||||
* NULL sum_struct means we have no checksums
|
||||
*/
|
||||
|
||||
void write_sum_head(int f, struct sum_struct *sum)
|
||||
{
|
||||
static struct sum_struct null_sum;
|
||||
|
||||
if (sum == NULL)
|
||||
if (sum == (struct sum_struct *)NULL)
|
||||
sum = &null_sum;
|
||||
|
||||
write_int(f, sum->count);
|
||||
@@ -136,11 +135,10 @@ void write_sum_head(int f, struct sum_struct *sum)
|
||||
* This might be made one of several selectable heuristics.
|
||||
*/
|
||||
|
||||
static void sum_sizes_sqroot(struct sum_struct *sum, uint64 len)
|
||||
static void sum_sizes_sqroot_baarda(struct sum_struct *sum, uint64 len)
|
||||
{
|
||||
extern unsigned int block_size;
|
||||
unsigned int blength;
|
||||
int s2length;
|
||||
extern int block_size;
|
||||
int blength, s2length, b;
|
||||
uint32 c;
|
||||
uint64 l;
|
||||
|
||||
@@ -169,7 +167,7 @@ static void sum_sizes_sqroot(struct sum_struct *sum, uint64 len)
|
||||
} else if (csum_length == SUM_LENGTH) {
|
||||
s2length = SUM_LENGTH;
|
||||
} else {
|
||||
int b = BLOCKSUM_BIAS;
|
||||
b = BLOCKSUM_BIAS;
|
||||
l = len;
|
||||
while (l >>= 1) {
|
||||
b += 2;
|
||||
@@ -194,9 +192,10 @@ static void sum_sizes_sqroot(struct sum_struct *sum, uint64 len)
|
||||
sum->remainder = (len % blength);
|
||||
|
||||
if (sum->count && verbose > 2) {
|
||||
rprintf(FINFO, "count=%.0f rem=%u blength=%u s2length=%d flength=%.0f\n",
|
||||
(double)sum->count, sum->remainder, sum->blength,
|
||||
sum->s2length, (double)sum->flength);
|
||||
rprintf(FINFO, "count=%ld rem=%ld blength=%ld s2length=%ld flength=%.0f\n",
|
||||
(long) sum->count, (long) sum->remainder,
|
||||
(long) sum->blength, (long) sum->s2length,
|
||||
(double) sum->flength);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,6 +210,10 @@ static void sum_sizes_sqroot(struct sum_struct *sum, uint64 len)
|
||||
* Whew. */
|
||||
static BOOL disable_deltas_p(void)
|
||||
{
|
||||
extern int whole_file;
|
||||
extern int local_server;
|
||||
extern int write_batch;
|
||||
|
||||
if (whole_file > 0)
|
||||
return True;
|
||||
if (whole_file == 0 || write_batch)
|
||||
@@ -224,18 +227,18 @@ static BOOL disable_deltas_p(void)
|
||||
*
|
||||
* Generate approximately one checksum every block_len bytes.
|
||||
*/
|
||||
static void generate_and_send_sums(struct map_struct *buf, size_t len, int f_out)
|
||||
static void generate_and_send_sums(struct map_struct *buf, OFF_T len, int f_out)
|
||||
{
|
||||
size_t i;
|
||||
struct sum_struct sum;
|
||||
OFF_T offset = 0;
|
||||
|
||||
sum_sizes_sqroot(&sum, len);
|
||||
sum_sizes_sqroot_baarda(&sum, len);
|
||||
|
||||
write_sum_head(f_out, &sum);
|
||||
|
||||
for (i = 0; i < sum.count; i++) {
|
||||
unsigned int n1 = MIN(len, sum.blength);
|
||||
int n1 = MIN(len, sum.blength);
|
||||
char *map = map_ptr(buf, offset, n1);
|
||||
uint32 sum1 = get_checksum1(map, n1);
|
||||
char sum2[SUM_LENGTH];
|
||||
@@ -244,9 +247,8 @@ static void generate_and_send_sums(struct map_struct *buf, size_t len, int f_out
|
||||
|
||||
if (verbose > 3) {
|
||||
rprintf(FINFO,
|
||||
"chunk[%.0f] offset=%.0f len=%u sum1=%08lx\n",
|
||||
(double)i, (double)offset, n1,
|
||||
(unsigned long)sum1);
|
||||
"chunk[%ld] offset=%.0f len=%d sum1=%08lx\n",
|
||||
(long)i,(double)offset,n1,(unsigned long)sum1);
|
||||
}
|
||||
write_int(f_out, sum1);
|
||||
write_buf(f_out, sum2, sum.s2length);
|
||||
@@ -265,17 +267,22 @@ static void generate_and_send_sums(struct map_struct *buf, size_t len, int f_out
|
||||
* @note This comment was added later by mbp who was trying to work it
|
||||
* out. It might be wrong.
|
||||
**/
|
||||
void recv_generator(char *fname, struct file_struct *file, int i, int f_out)
|
||||
void recv_generator(char *fname, struct file_list *flist, int i, int f_out)
|
||||
{
|
||||
int fd;
|
||||
STRUCT_STAT st;
|
||||
struct map_struct *mapbuf;
|
||||
struct map_struct *buf;
|
||||
int statret;
|
||||
struct file_struct *file = flist->files[i];
|
||||
char *fnamecmp;
|
||||
char fnamecmpbuf[MAXPATHLEN];
|
||||
extern char *compare_dest;
|
||||
extern int list_only;
|
||||
extern int preserve_perms;
|
||||
extern int only_existing;
|
||||
extern int orig_umask;
|
||||
|
||||
if (list_only)
|
||||
return;
|
||||
if (list_only) return;
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"recv_generator(%s,%d)\n",fname,i);
|
||||
@@ -294,8 +301,7 @@ void recv_generator(char *fname, struct file_struct *file, int i, int f_out)
|
||||
/* if the file exists already and we aren't perserving
|
||||
* permissions then act as though the remote end sent
|
||||
* us the file permissions we already have */
|
||||
file->mode = (file->mode & ~CHMOD_BITS)
|
||||
| (st.st_mode & CHMOD_BITS);
|
||||
file->mode = (file->mode & _S_IFMT) | (st.st_mode & ~_S_IFMT);
|
||||
}
|
||||
|
||||
if (S_ISDIR(file->mode)) {
|
||||
@@ -334,11 +340,12 @@ void recv_generator(char *fname, struct file_struct *file, int i, int f_out)
|
||||
#if SUPPORT_LINKS
|
||||
char lnk[MAXPATHLEN];
|
||||
int l;
|
||||
extern int safe_symlinks;
|
||||
|
||||
if (safe_symlinks && unsafe_symlink(file->u.link, fname)) {
|
||||
if (safe_symlinks && unsafe_symlink(file->link, fname)) {
|
||||
if (verbose) {
|
||||
rprintf(FINFO, "ignoring unsafe symlink %s -> \"%s\"\n",
|
||||
full_fname(fname), file->u.link);
|
||||
full_fname(fname), file->link);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -349,7 +356,7 @@ void recv_generator(char *fname, struct file_struct *file, int i, int f_out)
|
||||
/* A link already pointing to the
|
||||
* right place -- no further action
|
||||
* required. */
|
||||
if (strcmp(lnk,file->u.link) == 0) {
|
||||
if (strcmp(lnk,file->link) == 0) {
|
||||
set_perms(fname,file,&st,1);
|
||||
return;
|
||||
}
|
||||
@@ -359,13 +366,13 @@ void recv_generator(char *fname, struct file_struct *file, int i, int f_out)
|
||||
* in place. */
|
||||
delete_file(fname);
|
||||
}
|
||||
if (do_symlink(file->u.link,fname) != 0) {
|
||||
if (do_symlink(file->link,fname) != 0) {
|
||||
rprintf(FERROR, "symlink %s -> \"%s\" failed: %s\n",
|
||||
full_fname(fname), file->u.link, strerror(errno));
|
||||
full_fname(fname), file->link, strerror(errno));
|
||||
} else {
|
||||
set_perms(fname,file,NULL,0);
|
||||
if (verbose) {
|
||||
rprintf(FINFO,"%s -> %s\n", fname,file->u.link);
|
||||
rprintf(FINFO,"%s -> %s\n", fname,file->link);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -376,12 +383,12 @@ void recv_generator(char *fname, struct file_struct *file, int i, int f_out)
|
||||
if (am_root && preserve_devices && IS_DEVICE(file->mode)) {
|
||||
if (statret != 0 ||
|
||||
st.st_mode != file->mode ||
|
||||
st.st_rdev != file->u.rdev) {
|
||||
(DEV64_T)st.st_rdev != file->rdev) {
|
||||
delete_file(fname);
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"mknod(%s,0%o,0x%x)\n",
|
||||
fname,(int)file->mode,(int)file->u.rdev);
|
||||
if (do_mknod(fname,file->mode,file->u.rdev) != 0) {
|
||||
fname,(int)file->mode,(int)file->rdev);
|
||||
if (do_mknod(fname,file->mode,file->rdev) != 0) {
|
||||
rprintf(FERROR, "mknod %s failed: %s\n",
|
||||
full_fname(fname), strerror(errno));
|
||||
} else {
|
||||
@@ -396,8 +403,11 @@ void recv_generator(char *fname, struct file_struct *file, int i, int f_out)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (preserve_hard_links && hard_link_check(file, HL_CHECK_MASTER))
|
||||
if (preserve_hard_links && check_hard_link(file)) {
|
||||
if (verbose > 1)
|
||||
rprintf(FINFO, "recv_generator: \"%s\" is a hard link\n",f_name(file));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!S_ISREG(file->mode)) {
|
||||
rprintf(FINFO, "skipping non-regular file \"%s\"\n",fname);
|
||||
@@ -406,10 +416,10 @@ void recv_generator(char *fname, struct file_struct *file, int i, int f_out)
|
||||
|
||||
fnamecmp = fname;
|
||||
|
||||
if (statret == -1 && compare_dest != NULL) {
|
||||
if ((statret == -1) && (compare_dest != NULL)) {
|
||||
/* try the file at compare_dest instead */
|
||||
int saveerrno = errno;
|
||||
pathjoin(fnamecmpbuf, sizeof fnamecmpbuf, compare_dest, fname);
|
||||
snprintf(fnamecmpbuf,MAXPATHLEN,"%s/%s",compare_dest,fname);
|
||||
statret = link_stat(fnamecmpbuf,&st);
|
||||
if (!S_ISREG(st.st_mode))
|
||||
statret = -1;
|
||||
@@ -418,11 +428,11 @@ void recv_generator(char *fname, struct file_struct *file, int i, int f_out)
|
||||
#if HAVE_LINK
|
||||
else if (link_dest && !dry_run) {
|
||||
if (do_link(fnamecmpbuf, fname) != 0) {
|
||||
if (verbose > 0) {
|
||||
if (verbose > 0)
|
||||
rprintf(FINFO,"link %s => %s : %s\n",
|
||||
fnamecmpbuf, fname,
|
||||
fnamecmpbuf,
|
||||
fname,
|
||||
strerror(errno));
|
||||
}
|
||||
}
|
||||
fnamecmp = fnamecmpbuf;
|
||||
}
|
||||
@@ -432,8 +442,6 @@ void recv_generator(char *fname, struct file_struct *file, int i, int f_out)
|
||||
}
|
||||
|
||||
if (statret == -1) {
|
||||
if (preserve_hard_links && hard_link_check(file, HL_SKIP))
|
||||
return;
|
||||
if (errno == ENOENT) {
|
||||
write_int(f_out,i);
|
||||
if (!dry_run) write_sum_head(f_out, NULL);
|
||||
@@ -451,8 +459,6 @@ void recv_generator(char *fname, struct file_struct *file, int i, int f_out)
|
||||
}
|
||||
|
||||
/* now pretend the file didn't exist */
|
||||
if (preserve_hard_links && hard_link_check(file, HL_SKIP))
|
||||
return;
|
||||
write_int(f_out,i);
|
||||
if (!dry_run) write_sum_head(f_out, NULL);
|
||||
return;
|
||||
@@ -494,44 +500,40 @@ void recv_generator(char *fname, struct file_struct *file, int i, int f_out)
|
||||
rprintf(FERROR, "failed to open %s, continuing: %s\n",
|
||||
full_fname(fnamecmp), strerror(errno));
|
||||
/* pretend the file didn't exist */
|
||||
if (preserve_hard_links && hard_link_check(file, HL_SKIP))
|
||||
return;
|
||||
write_int(f_out,i);
|
||||
write_sum_head(f_out, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (st.st_size > 0)
|
||||
mapbuf = map_file(fd,st.st_size);
|
||||
else
|
||||
mapbuf = NULL;
|
||||
|
||||
if (verbose > 3) {
|
||||
rprintf(FINFO,"gen mapped %s of size %.0f\n", fnamecmp,
|
||||
(double)st.st_size);
|
||||
if (st.st_size > 0) {
|
||||
buf = map_file(fd,st.st_size);
|
||||
} else {
|
||||
buf = NULL;
|
||||
}
|
||||
|
||||
if (verbose > 3)
|
||||
rprintf(FINFO,"gen mapped %s of size %.0f\n",fnamecmp,(double)st.st_size);
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO, "generating and sending sums for %d\n", i);
|
||||
|
||||
write_int(f_out,i);
|
||||
generate_and_send_sums(mapbuf, st.st_size, f_out);
|
||||
generate_and_send_sums(buf, st.st_size, f_out);
|
||||
|
||||
close(fd);
|
||||
if (mapbuf) unmap_file(mapbuf);
|
||||
if (buf) unmap_file(buf);
|
||||
}
|
||||
|
||||
|
||||
void generate_files(int f, struct file_list *flist, char *local_name)
|
||||
|
||||
void generate_files(int f,struct file_list *flist,char *local_name,int f_recv)
|
||||
{
|
||||
int i;
|
||||
int phase=0;
|
||||
char fbuf[MAXPATHLEN];
|
||||
|
||||
if (verbose > 2) {
|
||||
rprintf(FINFO, "generator starting pid=%ld count=%d\n",
|
||||
(long)getpid(), flist->count);
|
||||
}
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"generator starting pid=%d count=%d\n",
|
||||
(int)getpid(),flist->count);
|
||||
|
||||
if (verbose >= 2) {
|
||||
rprintf(FINFO,
|
||||
@@ -547,23 +549,21 @@ void generate_files(int f, struct file_list *flist, char *local_name)
|
||||
|
||||
for (i = 0; i < flist->count; i++) {
|
||||
struct file_struct *file = flist->files[i];
|
||||
struct file_struct copy;
|
||||
mode_t saved_mode = file->mode;
|
||||
if (!file->basename) continue;
|
||||
|
||||
if (!file->basename)
|
||||
continue;
|
||||
/* we need to ensure that any directories we create have writeable
|
||||
permissions initially so that we can create the files within
|
||||
them. This is then fixed after the files are transferred */
|
||||
if (!am_root && S_ISDIR(file->mode) && !(file->mode & S_IWUSR)) {
|
||||
copy = *file;
|
||||
if (!am_root && S_ISDIR(file->mode)) {
|
||||
file->mode |= S_IWUSR; /* user write */
|
||||
/* XXX: Could this be causing a problem on SCO? Perhaps their
|
||||
* handling of permissions is strange? */
|
||||
copy.mode |= S_IWUSR; /* user write */
|
||||
file = ©
|
||||
}
|
||||
|
||||
recv_generator(local_name ? local_name : f_name_to(file, fbuf),
|
||||
file, i, f);
|
||||
recv_generator(local_name?local_name:f_name(file), flist,i,f);
|
||||
|
||||
file->mode = saved_mode;
|
||||
}
|
||||
|
||||
phase++;
|
||||
@@ -577,10 +577,9 @@ void generate_files(int f, struct file_list *flist, char *local_name)
|
||||
|
||||
/* files can cycle through the system more than once
|
||||
* to catch initial checksum errors */
|
||||
while ((i = get_redo_num()) != -1) {
|
||||
for (i=read_int(f_recv); i != -1; i=read_int(f_recv)) {
|
||||
struct file_struct *file = flist->files[i];
|
||||
recv_generator(local_name ? local_name : f_name_to(file, fbuf),
|
||||
file, i, f);
|
||||
recv_generator(local_name?local_name:f_name(file), flist,i,f);
|
||||
}
|
||||
|
||||
phase++;
|
||||
@@ -588,19 +587,4 @@ void generate_files(int f, struct file_list *flist, char *local_name)
|
||||
rprintf(FINFO,"generate_files phase=%d\n",phase);
|
||||
|
||||
write_int(f,-1);
|
||||
|
||||
if (preserve_hard_links)
|
||||
do_hard_links();
|
||||
|
||||
/* now we need to fix any directory permissions that were
|
||||
* modified during the transfer */
|
||||
for (i = 0; i < flist->count; i++) {
|
||||
struct file_struct *file = flist->files[i];
|
||||
if (!file->basename || !S_ISDIR(file->mode)) continue;
|
||||
recv_generator(local_name ? local_name : f_name(file),
|
||||
file, i, -1);
|
||||
}
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"generate_files finished\n");
|
||||
}
|
||||
|
||||
36
getgroups.c
36
getgroups.c
@@ -26,42 +26,24 @@
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
#ifndef NGROUPS
|
||||
/* It ought to be defined, but just in case. */
|
||||
# define NGROUPS 32
|
||||
#endif
|
||||
|
||||
int
|
||||
main(UNUSED(int argc), UNUSED(char *argv[]))
|
||||
{
|
||||
int n, i;
|
||||
gid_t *list;
|
||||
gid_t gid = MY_GID();
|
||||
int gid_in_list = 0;
|
||||
gid_t list[NGROUPS];
|
||||
|
||||
#ifdef HAVE_GETGROUPS
|
||||
if ((n = getgroups(0, NULL)) < 0) {
|
||||
if ((n = getgroups(NGROUPS, list)) == -1) {
|
||||
perror("getgroups");
|
||||
return 1;
|
||||
}
|
||||
#else
|
||||
n = 0;
|
||||
#endif
|
||||
|
||||
list = (gid_t*)malloc(sizeof (gid_t) * (n + 1));
|
||||
if (!list) {
|
||||
fprintf(stderr, "out of memory!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#ifdef HAVE_GETGROUPS
|
||||
if (n > 0)
|
||||
n = getgroups(n, list);
|
||||
#endif
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
printf("%lu ", (unsigned long)list[i]);
|
||||
if (list[i] == gid)
|
||||
gid_in_list = 1;
|
||||
}
|
||||
/* The default gid might not be in the list on some systems. */
|
||||
if (!gid_in_list)
|
||||
printf("%lu", (unsigned long)gid);
|
||||
for (i = 0; i < n; i++)
|
||||
printf("%u ", list[i]);
|
||||
printf("\n");
|
||||
|
||||
return 0;
|
||||
|
||||
233
hlink.c
233
hlink.c
@@ -1,18 +1,18 @@
|
||||
/*
|
||||
/*
|
||||
Copyright (C) Andrew Tridgell 1996
|
||||
Copyright (C) Paul Mackerras 1996
|
||||
Copyright (C) 2002 by Martin Pool <mbp@samba.org>
|
||||
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
@@ -22,144 +22,138 @@
|
||||
|
||||
extern int dry_run;
|
||||
extern int verbose;
|
||||
extern int make_backups;
|
||||
|
||||
#if SUPPORT_HARD_LINKS
|
||||
static int hlink_compare(struct file_struct **file1, struct file_struct **file2)
|
||||
static int hlink_compare(struct file_struct *f1, struct file_struct *f2)
|
||||
{
|
||||
struct file_struct *f1 = *file1;
|
||||
struct file_struct *f2 = *file2;
|
||||
if (!S_ISREG(f1->mode) && !S_ISREG(f2->mode))
|
||||
return 0;
|
||||
if (!S_ISREG(f1->mode))
|
||||
return -1;
|
||||
if (!S_ISREG(f2->mode))
|
||||
return 1;
|
||||
|
||||
if (f1->F_DEV != f2->F_DEV)
|
||||
return (int) (f1->F_DEV > f2->F_DEV ? 1 : -1);
|
||||
if (f1->dev != f2->dev)
|
||||
return (int) (f1->dev > f2->dev ? 1 : -1);
|
||||
|
||||
if (f1->F_INODE != f2->F_INODE)
|
||||
return (int) (f1->F_INODE > f2->F_INODE ? 1 : -1);
|
||||
if (f1->inode != f2->inode)
|
||||
return (int) (f1->inode > f2->inode ? 1 : -1);
|
||||
|
||||
return file_compare(file1, file2);
|
||||
return file_compare(&f1, &f2);
|
||||
}
|
||||
|
||||
static struct file_struct **hlink_list;
|
||||
|
||||
static struct file_struct *hlink_list;
|
||||
static int hlink_count;
|
||||
|
||||
#define LINKED(p1,p2) ((p1)->F_DEV == (p2)->F_DEV \
|
||||
&& (p1)->F_INODE == (p2)->F_INODE)
|
||||
|
||||
/* Analyze the data in the hlink_list[], remove items that aren't multiply
|
||||
* linked, and replace the dev+inode data with the hlindex+next linked list. */
|
||||
static void link_idev_data(struct file_list *flist)
|
||||
{
|
||||
struct file_struct *head;
|
||||
int from, to, start;
|
||||
|
||||
alloc_pool_t hlink_pool;
|
||||
alloc_pool_t idev_pool = flist->hlink_pool;
|
||||
|
||||
hlink_pool = pool_create(128 * 1024, sizeof (struct hlink),
|
||||
out_of_memory, POOL_INTERN);
|
||||
|
||||
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, hlink_list[from]->link_u.idev);
|
||||
hlink_list[from]->link_u.links = pool_talloc(hlink_pool,
|
||||
struct hlink, 1, "hlink_list");
|
||||
|
||||
hlink_list[from]->F_HLINDEX = to;
|
||||
hlink_list[from]->F_NEXT = hlink_list[from+1];
|
||||
from++;
|
||||
}
|
||||
if (from > start) {
|
||||
pool_free(idev_pool, 0, hlink_list[from]->link_u.idev);
|
||||
hlink_list[from]->link_u.links = pool_talloc(hlink_pool,
|
||||
struct hlink, 1, "hlink_list");
|
||||
|
||||
hlink_list[from]->F_HLINDEX = to;
|
||||
hlink_list[from]->F_NEXT = head;
|
||||
hlink_list[from]->flags |= FLAG_HLINK_EOL;
|
||||
hlink_list[to++] = head;
|
||||
} else {
|
||||
pool_free(idev_pool, 0, head->link_u.idev);
|
||||
head->link_u.idev = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!to) {
|
||||
free(hlink_list);
|
||||
hlink_list = NULL;
|
||||
pool_destroy(hlink_pool);
|
||||
hlink_pool = NULL;
|
||||
} else {
|
||||
hlink_count = to;
|
||||
if (!(hlink_list = realloc_array(hlink_list,
|
||||
struct file_struct *, hlink_count)))
|
||||
out_of_memory("init_hard_links");
|
||||
}
|
||||
flist->hlink_pool = hlink_pool;
|
||||
pool_destroy(idev_pool);
|
||||
}
|
||||
#endif
|
||||
|
||||
void init_hard_links(struct file_list *flist)
|
||||
{
|
||||
#if SUPPORT_HARD_LINKS
|
||||
int i;
|
||||
|
||||
if (flist->count < 2)
|
||||
return;
|
||||
|
||||
if (hlink_list)
|
||||
free(hlink_list);
|
||||
|
||||
if (!(hlink_list = new_array(struct file_struct *, flist->count)))
|
||||
if (!(hlink_list = new_array(struct file_struct, flist->count)))
|
||||
out_of_memory("init_hard_links");
|
||||
|
||||
hlink_count = 0;
|
||||
for (i = 0; i < flist->count; i++) {
|
||||
if (flist->files[i]->link_u.idev)
|
||||
hlink_list[hlink_count++] = flist->files[i];
|
||||
}
|
||||
for (i = 0; i < flist->count; i++)
|
||||
memcpy(&hlink_list[i], flist->files[i],
|
||||
sizeof(hlink_list[0]));
|
||||
|
||||
qsort(hlink_list, hlink_count,
|
||||
sizeof hlink_list[0], (int (*)()) hlink_compare);
|
||||
qsort(hlink_list, flist->count,
|
||||
sizeof(hlink_list[0]), (int (*)()) hlink_compare);
|
||||
|
||||
if (!hlink_count) {
|
||||
free(hlink_list);
|
||||
hlink_list = NULL;
|
||||
} else
|
||||
link_idev_data(flist);
|
||||
hlink_count = flist->count;
|
||||
#endif
|
||||
}
|
||||
|
||||
int hard_link_check(struct file_struct *file, int skip)
|
||||
/* check if a file should be skipped because it is the same as an
|
||||
earlier hard link */
|
||||
int check_hard_link(struct file_struct *file)
|
||||
{
|
||||
if (!hlink_list || !file->link_u.links)
|
||||
#if SUPPORT_HARD_LINKS
|
||||
int low = 0, high = hlink_count - 1;
|
||||
int ret = 0;
|
||||
|
||||
if (!hlink_list || !S_ISREG(file->mode))
|
||||
return 0;
|
||||
if (skip && !(file->flags & FLAG_HLINK_EOL))
|
||||
hlink_list[file->F_HLINDEX] = file->F_NEXT;
|
||||
if (hlink_list[file->F_HLINDEX] != file) {
|
||||
if (verbose > 1) {
|
||||
rprintf(FINFO, "\"%s\" is a hard link\n",
|
||||
f_name(file));
|
||||
|
||||
while (low != high) {
|
||||
int mid = (low + high) / 2;
|
||||
ret = hlink_compare(&hlink_list[mid], file);
|
||||
if (ret == 0) {
|
||||
low = mid;
|
||||
break;
|
||||
}
|
||||
if (ret > 0)
|
||||
high = mid;
|
||||
else
|
||||
low = mid + 1;
|
||||
}
|
||||
|
||||
/* XXX: To me this looks kind of dodgy -- why do we use [low]
|
||||
* here and [low-1] below? -- mbp */
|
||||
if (hlink_compare(&hlink_list[low], file) != 0)
|
||||
return 0;
|
||||
|
||||
if (low > 0 &&
|
||||
S_ISREG(hlink_list[low - 1].mode) &&
|
||||
file->dev == hlink_list[low - 1].dev &&
|
||||
file->inode == hlink_list[low - 1].inode) {
|
||||
if (verbose >= 2) {
|
||||
rprintf(FINFO, "check_hard_link: \"%s\" is a hard link to file %d, \"%s\"\n",
|
||||
f_name(file), low-1, f_name(&hlink_list[low-1]));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#if SUPPORT_HARD_LINKS
|
||||
static void hard_link_one(char *hlink1, char *hlink2)
|
||||
static void hard_link_one(int i)
|
||||
{
|
||||
if (do_link(hlink1, hlink2)) {
|
||||
if (verbose) {
|
||||
rprintf(FINFO, "link %s => %s failed: %s\n",
|
||||
hlink2, hlink1, strerror(errno));
|
||||
STRUCT_STAT st1, st2;
|
||||
|
||||
if (link_stat(f_name(&hlink_list[i - 1]), &st1) != 0)
|
||||
return;
|
||||
|
||||
if (link_stat(f_name(&hlink_list[i]), &st2) != 0) {
|
||||
if (do_link
|
||||
(f_name(&hlink_list[i - 1]),
|
||||
f_name(&hlink_list[i])) != 0) {
|
||||
if (verbose > 0)
|
||||
rprintf(FINFO, "link %s => %s : %s\n",
|
||||
f_name(&hlink_list[i]),
|
||||
f_name(&hlink_list[i - 1]),
|
||||
strerror(errno));
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (st2.st_dev == st1.st_dev && st2.st_ino == st1.st_ino)
|
||||
return;
|
||||
|
||||
if (robust_unlink(f_name(&hlink_list[i])) != 0 ||
|
||||
do_link(f_name(&hlink_list[i - 1]),
|
||||
f_name(&hlink_list[i])) != 0) {
|
||||
if (verbose > 0)
|
||||
rprintf(FINFO, "link %s => %s : %s\n",
|
||||
f_name(&hlink_list[i]),
|
||||
f_name(&hlink_list[i - 1]),
|
||||
strerror(errno));
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (verbose)
|
||||
rprintf(FINFO, "%s => %s\n", hlink2, hlink1);
|
||||
if (verbose > 0)
|
||||
rprintf(FINFO, "%s => %s\n",
|
||||
f_name(&hlink_list[i]),
|
||||
f_name(&hlink_list[i - 1]));
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -172,39 +166,18 @@ static void hard_link_one(char *hlink1, char *hlink2)
|
||||
void do_hard_links(void)
|
||||
{
|
||||
#if SUPPORT_HARD_LINKS
|
||||
struct file_struct *file, *first;
|
||||
char hlink1[MAXPATHLEN];
|
||||
char *hlink2;
|
||||
STRUCT_STAT st1, st2;
|
||||
int i;
|
||||
|
||||
if (!hlink_list)
|
||||
return;
|
||||
|
||||
for (i = 0; i < hlink_count; i++) {
|
||||
first = file = hlink_list[i];
|
||||
if (link_stat(f_name_to(first, hlink1), &st1) != 0)
|
||||
continue;
|
||||
while ((file = file->F_NEXT) != first) {
|
||||
hlink2 = f_name(file);
|
||||
if (link_stat(hlink2, &st2) == 0) {
|
||||
if (st2.st_dev == st1.st_dev
|
||||
&& st2.st_ino == st1.st_ino)
|
||||
continue;
|
||||
if (make_backups) {
|
||||
if (!make_backup(hlink2))
|
||||
continue;
|
||||
} else if (robust_unlink(hlink2)) {
|
||||
if (verbose > 0) {
|
||||
rprintf(FINFO,
|
||||
"unlink %s failed: %s\n",
|
||||
full_fname(hlink2),
|
||||
strerror(errno));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
hard_link_one(hlink1, hlink2);
|
||||
for (i = 1; i < hlink_count; i++) {
|
||||
if (S_ISREG(hlink_list[i].mode) &&
|
||||
S_ISREG(hlink_list[i - 1].mode) &&
|
||||
hlink_list[i].basename && hlink_list[i - 1].basename &&
|
||||
hlink_list[i].dev == hlink_list[i - 1].dev &&
|
||||
hlink_list[i].inode == hlink_list[i - 1].inode) {
|
||||
hard_link_one(i);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
611
io.c
611
io.c
@@ -41,17 +41,14 @@
|
||||
|
||||
static int io_multiplexing_out;
|
||||
static int io_multiplexing_in;
|
||||
static int multiplex_in_fd = -1;
|
||||
static int multiplex_out_fd = -1;
|
||||
static int multiplex_in_fd;
|
||||
static int multiplex_out_fd;
|
||||
static time_t last_io;
|
||||
static int no_flush;
|
||||
|
||||
extern int bwlimit;
|
||||
extern int verbose;
|
||||
extern int io_timeout;
|
||||
extern int am_server;
|
||||
extern int am_daemon;
|
||||
extern int am_sender;
|
||||
extern struct stats stats;
|
||||
|
||||
|
||||
@@ -77,56 +74,19 @@ const char *io_read_phase = phase_unknown;
|
||||
version is 24 or less. */
|
||||
int kludge_around_eof = False;
|
||||
|
||||
int msg_fd_in = -1;
|
||||
int msg_fd_out = -1;
|
||||
|
||||
static int io_filesfrom_f_in = -1;
|
||||
static int io_filesfrom_f_out = -1;
|
||||
static char io_filesfrom_buf[2048];
|
||||
static char *io_filesfrom_bp;
|
||||
static char io_filesfrom_lastchar;
|
||||
static int io_filesfrom_buflen;
|
||||
static int io_error_fd = -1;
|
||||
|
||||
static void read_loop(int fd, char *buf, size_t len);
|
||||
|
||||
struct redo_list {
|
||||
struct redo_list *next;
|
||||
int num;
|
||||
};
|
||||
|
||||
static struct redo_list *redo_list_head;
|
||||
static struct redo_list *redo_list_tail;
|
||||
|
||||
struct msg_list {
|
||||
struct msg_list *next;
|
||||
char *buf;
|
||||
int len;
|
||||
};
|
||||
|
||||
static struct msg_list *msg_list_head;
|
||||
static struct msg_list *msg_list_tail;
|
||||
|
||||
static void redo_list_add(int num)
|
||||
{
|
||||
struct redo_list *rl;
|
||||
|
||||
if (!(rl = new(struct redo_list)))
|
||||
exit_cleanup(RERR_MALLOC);
|
||||
rl->next = NULL;
|
||||
rl->num = num;
|
||||
if (redo_list_tail)
|
||||
redo_list_tail->next = rl;
|
||||
else
|
||||
redo_list_head = rl;
|
||||
redo_list_tail = rl;
|
||||
}
|
||||
|
||||
static void check_timeout(void)
|
||||
{
|
||||
extern int am_server, am_daemon;
|
||||
time_t t;
|
||||
|
||||
if (!io_timeout)
|
||||
return;
|
||||
err_list_push();
|
||||
|
||||
if (!io_timeout) return;
|
||||
|
||||
if (!last_io) {
|
||||
last_io = time(NULL);
|
||||
@@ -144,180 +104,43 @@ static void check_timeout(void)
|
||||
}
|
||||
}
|
||||
|
||||
/** Setup the fd used to receive MSG_* messages. Only needed when
|
||||
* we're the generator because the sender and receiver both use the
|
||||
* multiplexed IO setup. */
|
||||
void set_msg_fd_in(int fd)
|
||||
/** Setup the fd used to propagate errors */
|
||||
void io_set_error_fd(int fd)
|
||||
{
|
||||
msg_fd_in = fd;
|
||||
io_error_fd = fd;
|
||||
}
|
||||
|
||||
/** Setup the fd used to send our MSG_* messages. Only needed when
|
||||
* we're the receiver because the generator and the sender both use
|
||||
* the multiplexed IO setup. */
|
||||
void set_msg_fd_out(int fd)
|
||||
{
|
||||
msg_fd_out = fd;
|
||||
set_nonblocking(msg_fd_out);
|
||||
}
|
||||
|
||||
/* Add a message to the pending MSG_* list. */
|
||||
static void msg_list_add(int code, char *buf, int len)
|
||||
{
|
||||
struct msg_list *ml;
|
||||
|
||||
if (!(ml = new(struct msg_list)))
|
||||
exit_cleanup(RERR_MALLOC);
|
||||
ml->next = NULL;
|
||||
if (!(ml->buf = new_array(char, len+4)))
|
||||
exit_cleanup(RERR_MALLOC);
|
||||
SIVAL(ml->buf, 0, ((code+MPLEX_BASE)<<24) | len);
|
||||
memcpy(ml->buf+4, buf, len);
|
||||
ml->len = len+4;
|
||||
if (msg_list_tail)
|
||||
msg_list_tail->next = ml;
|
||||
else
|
||||
msg_list_head = ml;
|
||||
msg_list_tail = ml;
|
||||
}
|
||||
|
||||
void send_msg(enum msgcode code, char *buf, int len)
|
||||
{
|
||||
msg_list_add(code, buf, len);
|
||||
msg_list_push(NORMAL_FLUSH);
|
||||
}
|
||||
|
||||
/** Read a message from the MSG_* fd and dispatch it. This is only
|
||||
* called by the generator. */
|
||||
static void read_msg_fd(void)
|
||||
/** Read some data from the error fd and write it to the write log code */
|
||||
static void read_error_fd(void)
|
||||
{
|
||||
char buf[200];
|
||||
size_t n;
|
||||
int fd = msg_fd_in;
|
||||
int fd = io_error_fd;
|
||||
int tag, len;
|
||||
|
||||
/* Temporarily disable msg_fd_in. This is needed because we
|
||||
* may call a write routine that could try to call us back. */
|
||||
msg_fd_in = -1;
|
||||
/* io_error_fd is temporarily disabled -- is this meant to
|
||||
* prevent indefinite recursion? */
|
||||
io_error_fd = -1;
|
||||
|
||||
read_loop(fd, buf, 4);
|
||||
tag = IVAL(buf, 0);
|
||||
|
||||
len = tag & 0xFFFFFF;
|
||||
tag = (tag >> 24) - MPLEX_BASE;
|
||||
tag = tag >> 24;
|
||||
tag -= MPLEX_BASE;
|
||||
|
||||
switch (tag) {
|
||||
case MSG_DONE:
|
||||
if (len != 0) {
|
||||
rprintf(FERROR, "invalid message %d:%d\n", tag, len);
|
||||
exit_cleanup(RERR_STREAMIO);
|
||||
}
|
||||
redo_list_add(-1);
|
||||
break;
|
||||
case MSG_REDO:
|
||||
if (len != 4) {
|
||||
rprintf(FERROR, "invalid message %d:%d\n", tag, len);
|
||||
exit_cleanup(RERR_STREAMIO);
|
||||
}
|
||||
read_loop(fd, buf, 4);
|
||||
redo_list_add(IVAL(buf,0));
|
||||
break;
|
||||
case MSG_INFO:
|
||||
case MSG_ERROR:
|
||||
case MSG_LOG:
|
||||
while (len) {
|
||||
n = len;
|
||||
if (n >= sizeof buf)
|
||||
n = sizeof buf - 1;
|
||||
read_loop(fd, buf, n);
|
||||
rwrite((enum logcode)tag, buf, n);
|
||||
len -= n;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
rprintf(FERROR, "unknown message %d:%d\n", tag, len);
|
||||
exit_cleanup(RERR_STREAMIO);
|
||||
while (len) {
|
||||
n = len;
|
||||
if (n > (sizeof(buf)-1))
|
||||
n = sizeof(buf)-1;
|
||||
read_loop(fd, buf, n);
|
||||
rwrite((enum logcode)tag, buf, n);
|
||||
len -= n;
|
||||
}
|
||||
|
||||
msg_fd_in = fd;
|
||||
io_error_fd = fd;
|
||||
}
|
||||
|
||||
/* Try to push messages off the list onto the wire. If we leave with more
|
||||
* to do, return 0. On error, return -1. If everything flushed, return 1.
|
||||
* This is only called by the receiver. */
|
||||
int msg_list_push(int flush_it_all)
|
||||
{
|
||||
static int written = 0;
|
||||
struct timeval tv;
|
||||
fd_set fds;
|
||||
|
||||
if (msg_fd_out < 0)
|
||||
return -1;
|
||||
|
||||
while (msg_list_head) {
|
||||
struct msg_list *ml = msg_list_head;
|
||||
int n = write(msg_fd_out, ml->buf + written, ml->len - written);
|
||||
if (n < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
if (errno != EWOULDBLOCK && errno != EAGAIN)
|
||||
return -1;
|
||||
if (!flush_it_all)
|
||||
return 0;
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(msg_fd_out, &fds);
|
||||
tv.tv_sec = io_timeout ? io_timeout : SELECT_TIMEOUT;
|
||||
tv.tv_usec = 0;
|
||||
if (!select(msg_fd_out+1, NULL, &fds, NULL, &tv))
|
||||
check_timeout();
|
||||
} else if ((written += n) == ml->len) {
|
||||
free(ml->buf);
|
||||
msg_list_head = ml->next;
|
||||
if (!msg_list_head)
|
||||
msg_list_tail = NULL;
|
||||
free(ml);
|
||||
written = 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int get_redo_num(void)
|
||||
{
|
||||
struct redo_list *next;
|
||||
int num;
|
||||
|
||||
while (!redo_list_head)
|
||||
read_msg_fd();
|
||||
|
||||
num = redo_list_head->num;
|
||||
next = redo_list_head->next;
|
||||
free(redo_list_head);
|
||||
redo_list_head = next;
|
||||
if (!next)
|
||||
redo_list_tail = NULL;
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
/**
|
||||
* When we're the receiver and we have a local --files-from list of names
|
||||
* that needs to be sent over the socket to the sender, we have to do two
|
||||
* things at the same time: send the sender a list of what files we're
|
||||
* processing and read the incoming file+info list from the sender. We do
|
||||
* this by augmenting the read_timeout() function to copy this data. It
|
||||
* uses the io_filesfrom_buf to read a block of data from f_in (when it is
|
||||
* ready, since it might be a pipe) and then blast it out f_out (when it
|
||||
* is ready to receive more data).
|
||||
*/
|
||||
void io_set_filesfrom_fds(int f_in, int f_out)
|
||||
{
|
||||
io_filesfrom_f_in = f_in;
|
||||
io_filesfrom_f_out = f_out;
|
||||
io_filesfrom_bp = io_filesfrom_buf;
|
||||
io_filesfrom_lastchar = '\0';
|
||||
io_filesfrom_buflen = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* It's almost always an error to get an EOF when we're trying to read
|
||||
@@ -329,28 +152,28 @@ void io_set_filesfrom_fds(int f_in, int f_out)
|
||||
* program where that is a problem (start_socket_client),
|
||||
* kludge_around_eof is True and we just exit.
|
||||
*/
|
||||
static void whine_about_eof(void)
|
||||
static void whine_about_eof (void)
|
||||
{
|
||||
if (kludge_around_eof)
|
||||
exit_cleanup(0);
|
||||
exit_cleanup (0);
|
||||
else {
|
||||
rprintf(FERROR,
|
||||
"%s: connection unexpectedly closed "
|
||||
"(%.0f bytes read so far)\n",
|
||||
RSYNC_NAME, (double)stats.total_read);
|
||||
|
||||
exit_cleanup(RERR_STREAMIO);
|
||||
rprintf (FERROR,
|
||||
"%s: connection unexpectedly closed "
|
||||
"(%.0f bytes read so far)\n",
|
||||
RSYNC_NAME, (double)stats.total_read);
|
||||
|
||||
exit_cleanup (RERR_STREAMIO);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void die_from_readerr(int err)
|
||||
static void die_from_readerr (int err)
|
||||
{
|
||||
/* this prevents us trying to write errors on a dead socket */
|
||||
io_multiplexing_close();
|
||||
|
||||
|
||||
rprintf(FERROR, "%s: read error: %s\n",
|
||||
RSYNC_NAME, strerror(err));
|
||||
RSYNC_NAME, strerror (err));
|
||||
exit_cleanup(RERR_STREAMIO);
|
||||
}
|
||||
|
||||
@@ -366,43 +189,24 @@ static void die_from_readerr(int err)
|
||||
* give a better explanation. We can tell whether the connection has
|
||||
* started by looking e.g. at whether the remote version is known yet.
|
||||
*/
|
||||
static int read_timeout(int fd, char *buf, size_t len)
|
||||
static int read_timeout (int fd, char *buf, size_t len)
|
||||
{
|
||||
int n, ret=0;
|
||||
|
||||
io_flush(NORMAL_FLUSH);
|
||||
io_flush();
|
||||
|
||||
while (ret == 0) {
|
||||
/* until we manage to read *something* */
|
||||
fd_set r_fds, w_fds;
|
||||
fd_set fds;
|
||||
struct timeval tv;
|
||||
int fd_count = fd+1;
|
||||
int count;
|
||||
|
||||
FD_ZERO(&r_fds);
|
||||
FD_SET(fd, &r_fds);
|
||||
if (msg_fd_in >= 0) {
|
||||
FD_SET(msg_fd_in, &r_fds);
|
||||
if (msg_fd_in >= fd_count)
|
||||
fd_count = msg_fd_in+1;
|
||||
}
|
||||
if (io_filesfrom_f_out >= 0) {
|
||||
int new_fd;
|
||||
if (io_filesfrom_buflen == 0) {
|
||||
if (io_filesfrom_f_in >= 0) {
|
||||
FD_SET(io_filesfrom_f_in, &r_fds);
|
||||
new_fd = io_filesfrom_f_in;
|
||||
} else {
|
||||
io_filesfrom_f_out = -1;
|
||||
new_fd = -1;
|
||||
}
|
||||
} else {
|
||||
FD_ZERO(&w_fds);
|
||||
FD_SET(io_filesfrom_f_out, &w_fds);
|
||||
new_fd = io_filesfrom_f_out;
|
||||
}
|
||||
if (new_fd >= fd_count)
|
||||
fd_count = new_fd+1;
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(fd, &fds);
|
||||
if (io_error_fd != -1) {
|
||||
FD_SET(io_error_fd, &fds);
|
||||
if (io_error_fd > fd) fd_count = io_error_fd+1;
|
||||
}
|
||||
|
||||
tv.tv_sec = io_timeout?io_timeout:SELECT_TIMEOUT;
|
||||
@@ -410,12 +214,9 @@ static int read_timeout(int fd, char *buf, size_t len)
|
||||
|
||||
errno = 0;
|
||||
|
||||
count = select(fd_count, &r_fds,
|
||||
io_filesfrom_buflen? &w_fds : NULL,
|
||||
NULL, &tv);
|
||||
count = select(fd_count, &fds, NULL, NULL, &tv);
|
||||
|
||||
if (count == 0) {
|
||||
msg_list_push(NORMAL_FLUSH);
|
||||
check_timeout();
|
||||
}
|
||||
|
||||
@@ -426,74 +227,11 @@ static int read_timeout(int fd, char *buf, size_t len)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (msg_fd_in >= 0 && FD_ISSET(msg_fd_in, &r_fds))
|
||||
read_msg_fd();
|
||||
|
||||
if (io_filesfrom_f_out >= 0) {
|
||||
if (io_filesfrom_buflen) {
|
||||
if (FD_ISSET(io_filesfrom_f_out, &w_fds)) {
|
||||
int l = write(io_filesfrom_f_out,
|
||||
io_filesfrom_bp,
|
||||
io_filesfrom_buflen);
|
||||
if (l > 0) {
|
||||
if (!(io_filesfrom_buflen -= l))
|
||||
io_filesfrom_bp = io_filesfrom_buf;
|
||||
else
|
||||
io_filesfrom_bp += l;
|
||||
} else {
|
||||
/* XXX should we complain? */
|
||||
io_filesfrom_f_out = -1;
|
||||
}
|
||||
}
|
||||
} else if (io_filesfrom_f_in >= 0) {
|
||||
if (FD_ISSET(io_filesfrom_f_in, &r_fds)) {
|
||||
int l = read(io_filesfrom_f_in,
|
||||
io_filesfrom_buf,
|
||||
sizeof io_filesfrom_buf);
|
||||
if (l <= 0) {
|
||||
/* Send end-of-file marker */
|
||||
io_filesfrom_buf[0] = '\0';
|
||||
io_filesfrom_buf[1] = '\0';
|
||||
io_filesfrom_buflen = io_filesfrom_lastchar? 2 : 1;
|
||||
io_filesfrom_f_in = -1;
|
||||
} else {
|
||||
extern int eol_nulls;
|
||||
if (!eol_nulls) {
|
||||
char *s = io_filesfrom_buf + l;
|
||||
/* Transform CR and/or LF into '\0' */
|
||||
while (s-- > io_filesfrom_buf) {
|
||||
if (*s == '\n' || *s == '\r')
|
||||
*s = '\0';
|
||||
}
|
||||
}
|
||||
if (!io_filesfrom_lastchar) {
|
||||
/* Last buf ended with a '\0', so don't
|
||||
* let this buf start with one. */
|
||||
while (l && !*io_filesfrom_bp)
|
||||
io_filesfrom_bp++, l--;
|
||||
}
|
||||
if (!l)
|
||||
io_filesfrom_bp = io_filesfrom_buf;
|
||||
else {
|
||||
char *f = io_filesfrom_bp;
|
||||
char *t = f;
|
||||
char *eob = f + l;
|
||||
/* Eliminate any multi-'\0' runs. */
|
||||
while (f != eob) {
|
||||
if (!(*t++ = *f++)) {
|
||||
while (f != eob && !*f)
|
||||
f++, l--;
|
||||
}
|
||||
}
|
||||
io_filesfrom_lastchar = f[-1];
|
||||
}
|
||||
io_filesfrom_buflen = l;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (io_error_fd != -1 && FD_ISSET(io_error_fd, &fds)) {
|
||||
read_error_fd();
|
||||
}
|
||||
|
||||
if (!FD_ISSET(fd, &r_fds)) continue;
|
||||
if (!FD_ISSET(fd, &fds)) continue;
|
||||
|
||||
n = read(fd, buf, len);
|
||||
|
||||
@@ -505,75 +243,28 @@ static int read_timeout(int fd, char *buf, size_t len)
|
||||
last_io = time(NULL);
|
||||
continue;
|
||||
} else if (n == 0) {
|
||||
whine_about_eof();
|
||||
whine_about_eof ();
|
||||
return -1; /* doesn't return */
|
||||
} else if (n < 0) {
|
||||
} else if (n == -1) {
|
||||
if (errno == EINTR || errno == EWOULDBLOCK ||
|
||||
errno == EAGAIN)
|
||||
continue;
|
||||
die_from_readerr(errno);
|
||||
else
|
||||
die_from_readerr (errno);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a line into the "fname" buffer (which must be at least MAXPATHLEN
|
||||
* characters long).
|
||||
*/
|
||||
int read_filesfrom_line(int fd, char *fname)
|
||||
{
|
||||
char ch, *s, *eob = fname + MAXPATHLEN - 1;
|
||||
int cnt;
|
||||
extern int io_timeout;
|
||||
extern int eol_nulls;
|
||||
extern char *remote_filesfrom_file;
|
||||
int reading_remotely = remote_filesfrom_file != NULL;
|
||||
int nulls = eol_nulls || reading_remotely;
|
||||
|
||||
start:
|
||||
s = fname;
|
||||
while (1) {
|
||||
cnt = read(fd, &ch, 1);
|
||||
if (cnt < 0 && (errno == EWOULDBLOCK
|
||||
|| errno == EINTR || errno == EAGAIN)) {
|
||||
struct timeval tv;
|
||||
fd_set fds;
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(fd, &fds);
|
||||
tv.tv_sec = io_timeout? io_timeout : SELECT_TIMEOUT;
|
||||
tv.tv_usec = 0;
|
||||
if (!select(fd+1, &fds, NULL, NULL, &tv))
|
||||
check_timeout();
|
||||
continue;
|
||||
}
|
||||
if (cnt != 1)
|
||||
break;
|
||||
if (nulls? !ch : (ch == '\r' || ch == '\n')) {
|
||||
/* Skip empty lines if reading locally. */
|
||||
if (!reading_remotely && s == fname)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
if (s < eob)
|
||||
*s++ = ch;
|
||||
}
|
||||
*s = '\0';
|
||||
|
||||
/* Dump comments. */
|
||||
if (*fname == '#' || *fname == ';')
|
||||
goto start;
|
||||
|
||||
return s - fname;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Continue trying to read len bytes - don't return until len has been
|
||||
* read.
|
||||
**/
|
||||
static void read_loop(int fd, char *buf, size_t len)
|
||||
static void read_loop (int fd, char *buf, size_t len)
|
||||
{
|
||||
while (len) {
|
||||
int n = read_timeout(fd, buf, len);
|
||||
@@ -595,68 +286,47 @@ static int read_unbuffered(int fd, char *buf, size_t len)
|
||||
static size_t remaining;
|
||||
int tag, ret = 0;
|
||||
char line[1024];
|
||||
static char *buffer;
|
||||
static size_t bufferIdx = 0;
|
||||
static size_t bufferSz;
|
||||
|
||||
if (fd != multiplex_in_fd)
|
||||
if (!io_multiplexing_in || fd != multiplex_in_fd)
|
||||
return read_timeout(fd, buf, len);
|
||||
|
||||
if (!io_multiplexing_in && remaining == 0) {
|
||||
if (!buffer) {
|
||||
bufferSz = 2 * IO_BUFFER_SIZE;
|
||||
buffer = new_array(char, bufferSz);
|
||||
if (!buffer) out_of_memory("read_unbuffered");
|
||||
}
|
||||
remaining = read_timeout(fd, buffer, bufferSz);
|
||||
bufferIdx = 0;
|
||||
}
|
||||
|
||||
while (ret == 0) {
|
||||
if (remaining) {
|
||||
len = MIN(len, remaining);
|
||||
memcpy(buf, buffer + bufferIdx, len);
|
||||
bufferIdx += len;
|
||||
read_loop(fd, buf, len);
|
||||
remaining -= len;
|
||||
ret = len;
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
|
||||
read_loop(fd, line, 4);
|
||||
tag = IVAL(line, 0);
|
||||
|
||||
remaining = tag & 0xFFFFFF;
|
||||
tag = (tag >> 24) - MPLEX_BASE;
|
||||
tag = tag >> 24;
|
||||
|
||||
switch (tag) {
|
||||
case MSG_DATA:
|
||||
if (!buffer || remaining > bufferSz) {
|
||||
buffer = realloc_array(buffer, char, remaining);
|
||||
if (!buffer) out_of_memory("read_unbuffered");
|
||||
bufferSz = remaining;
|
||||
}
|
||||
read_loop(fd, buffer, remaining);
|
||||
bufferIdx = 0;
|
||||
break;
|
||||
case MSG_INFO:
|
||||
case MSG_ERROR:
|
||||
if (remaining >= sizeof line) {
|
||||
rprintf(FERROR, "multiplexing overflow %d:%ld\n\n",
|
||||
tag, (long)remaining);
|
||||
exit_cleanup(RERR_STREAMIO);
|
||||
}
|
||||
read_loop(fd, line, remaining);
|
||||
rwrite((enum logcode)tag, line, remaining);
|
||||
remaining = 0;
|
||||
break;
|
||||
default:
|
||||
if (tag == MPLEX_BASE)
|
||||
continue;
|
||||
|
||||
tag -= MPLEX_BASE;
|
||||
|
||||
if (tag != FERROR && tag != FINFO) {
|
||||
rprintf(FERROR, "unexpected tag %d\n", tag);
|
||||
exit_cleanup(RERR_STREAMIO);
|
||||
}
|
||||
}
|
||||
|
||||
if (remaining == 0)
|
||||
io_flush(NORMAL_FLUSH);
|
||||
if (remaining > sizeof(line) - 1) {
|
||||
rprintf(FERROR, "multiplexing overflow %d\n\n",
|
||||
remaining);
|
||||
exit_cleanup(RERR_STREAMIO);
|
||||
}
|
||||
|
||||
read_loop(fd, line, remaining);
|
||||
line[remaining] = 0;
|
||||
|
||||
rprintf((enum logcode) tag, "%s", line);
|
||||
remaining = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -668,13 +338,15 @@ static int read_unbuffered(int fd, char *buf, size_t len)
|
||||
* have been read. If all @p n can't be read then exit with an
|
||||
* error.
|
||||
**/
|
||||
static void readfd(int fd, char *buffer, size_t N)
|
||||
static void readfd (int fd, char *buffer, size_t N)
|
||||
{
|
||||
int ret;
|
||||
size_t total=0;
|
||||
|
||||
|
||||
while (total < N) {
|
||||
ret = read_unbuffered(fd, buffer + total, N-total);
|
||||
io_flush();
|
||||
|
||||
ret = read_unbuffered (fd, buffer + total, N-total);
|
||||
total += ret;
|
||||
}
|
||||
|
||||
@@ -695,6 +367,7 @@ int32 read_int(int f)
|
||||
|
||||
int64 read_longint(int f)
|
||||
{
|
||||
extern int remote_version;
|
||||
int64 ret;
|
||||
char b[8];
|
||||
ret = read_int(f);
|
||||
@@ -707,8 +380,10 @@ int64 read_longint(int f)
|
||||
rprintf(FERROR,"Integer overflow - attempted 64 bit offset\n");
|
||||
exit_cleanup(RERR_UNSUPPORTED);
|
||||
#else
|
||||
readfd(f,b,8);
|
||||
ret = IVAL(b,0) | (((int64)IVAL(b,4))<<32);
|
||||
if (remote_version >= 16) {
|
||||
readfd(f,b,8);
|
||||
ret = IVAL(b,0) | (((int64)IVAL(b,4))<<32);
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
@@ -721,14 +396,14 @@ void read_buf(int f,char *buf,size_t len)
|
||||
|
||||
void read_sbuf(int f,char *buf,size_t len)
|
||||
{
|
||||
read_buf(f,buf,len);
|
||||
read_buf (f,buf,len);
|
||||
buf[len] = 0;
|
||||
}
|
||||
|
||||
unsigned char read_byte(int f)
|
||||
{
|
||||
unsigned char c;
|
||||
read_buf(f, (char *)&c, 1);
|
||||
read_buf (f, (char *)&c, 1);
|
||||
return c;
|
||||
}
|
||||
|
||||
@@ -751,7 +426,7 @@ static void sleep_for_bwlimit(int bytes_written)
|
||||
|
||||
assert(bytes_written > 0);
|
||||
assert(bwlimit > 0);
|
||||
|
||||
|
||||
tv.tv_usec = bytes_written * 1000 / bwlimit;
|
||||
tv.tv_sec = tv.tv_usec / 1000000;
|
||||
tv.tv_usec = tv.tv_usec % 1000000;
|
||||
@@ -773,31 +448,33 @@ static void writefd_unbuffered(int fd,char *buf,size_t len)
|
||||
int fd_count, count;
|
||||
struct timeval tv;
|
||||
|
||||
msg_list_push(NORMAL_FLUSH);
|
||||
err_list_push();
|
||||
|
||||
no_flush++;
|
||||
|
||||
while (total < len) {
|
||||
FD_ZERO(&w_fds);
|
||||
FD_ZERO(&r_fds);
|
||||
FD_SET(fd,&w_fds);
|
||||
fd_count = fd;
|
||||
|
||||
if (msg_fd_in >= 0) {
|
||||
FD_ZERO(&r_fds);
|
||||
FD_SET(msg_fd_in,&r_fds);
|
||||
if (msg_fd_in > fd_count)
|
||||
fd_count = msg_fd_in;
|
||||
if (io_error_fd != -1) {
|
||||
FD_SET(io_error_fd,&r_fds);
|
||||
if (io_error_fd > fd_count)
|
||||
fd_count = io_error_fd;
|
||||
}
|
||||
|
||||
tv.tv_sec = io_timeout?io_timeout:SELECT_TIMEOUT;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
errno = 0;
|
||||
count = select(fd_count+1, msg_fd_in >= 0 ? &r_fds : NULL,
|
||||
&w_fds, NULL, &tv);
|
||||
|
||||
count = select(fd_count+1,
|
||||
io_error_fd != -1?&r_fds:NULL,
|
||||
&w_fds,NULL,
|
||||
&tv);
|
||||
|
||||
if (count == 0) {
|
||||
msg_list_push(NORMAL_FLUSH);
|
||||
check_timeout();
|
||||
}
|
||||
|
||||
@@ -808,21 +485,23 @@ static void writefd_unbuffered(int fd,char *buf,size_t len)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (msg_fd_in >= 0 && FD_ISSET(msg_fd_in, &r_fds))
|
||||
read_msg_fd();
|
||||
if (io_error_fd != -1 && FD_ISSET(io_error_fd, &r_fds)) {
|
||||
read_error_fd();
|
||||
}
|
||||
|
||||
if (FD_ISSET(fd, &w_fds)) {
|
||||
int ret;
|
||||
size_t n = len-total;
|
||||
ret = write(fd,buf+total,n);
|
||||
|
||||
if (ret < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
if (errno == EWOULDBLOCK || errno == EAGAIN) {
|
||||
msleep(1);
|
||||
continue;
|
||||
}
|
||||
if (ret == -1 && errno == EINTR) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ret == -1 &&
|
||||
(errno == EWOULDBLOCK || errno == EAGAIN)) {
|
||||
msleep(1);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ret <= 0) {
|
||||
@@ -852,7 +531,7 @@ static void writefd_unbuffered(int fd,char *buf,size_t len)
|
||||
static char *io_buffer;
|
||||
static int io_buffer_count;
|
||||
|
||||
void io_start_buffering_out(int fd)
|
||||
void io_start_buffering(int fd)
|
||||
{
|
||||
if (io_buffer) return;
|
||||
multiplex_out_fd = fd;
|
||||
@@ -861,24 +540,19 @@ void io_start_buffering_out(int fd)
|
||||
io_buffer_count = 0;
|
||||
}
|
||||
|
||||
void io_start_buffering_in(int fd)
|
||||
{
|
||||
multiplex_in_fd = fd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write an message to a multiplexed stream. If this fails then rsync
|
||||
* exits.
|
||||
**/
|
||||
static void mplex_write(int fd, enum msgcode code, char *buf, size_t len)
|
||||
static void mplex_write(int fd, enum logcode code, char *buf, size_t len)
|
||||
{
|
||||
char buffer[4096];
|
||||
size_t n = len;
|
||||
|
||||
SIVAL(buffer, 0, ((MPLEX_BASE + (int)code)<<24) + len);
|
||||
|
||||
if (n > (sizeof buffer - 4)) {
|
||||
n = sizeof buffer - 4;
|
||||
if (n > (sizeof(buffer)-4)) {
|
||||
n = sizeof(buffer)-4;
|
||||
}
|
||||
|
||||
memcpy(&buffer[4], buf, n);
|
||||
@@ -893,26 +567,26 @@ static void mplex_write(int fd, enum msgcode code, char *buf, size_t len)
|
||||
}
|
||||
|
||||
|
||||
void io_flush(int flush_it_all)
|
||||
void io_flush(void)
|
||||
{
|
||||
int fd = multiplex_out_fd;
|
||||
|
||||
msg_list_push(flush_it_all);
|
||||
|
||||
if (!io_buffer_count || no_flush)
|
||||
return;
|
||||
err_list_push();
|
||||
|
||||
if (io_multiplexing_out)
|
||||
mplex_write(fd, MSG_DATA, io_buffer, io_buffer_count);
|
||||
else
|
||||
if (!io_buffer_count || no_flush) return;
|
||||
|
||||
if (io_multiplexing_out) {
|
||||
mplex_write(fd, FNONE, io_buffer, io_buffer_count);
|
||||
} else {
|
||||
writefd_unbuffered(fd, io_buffer, io_buffer_count);
|
||||
}
|
||||
io_buffer_count = 0;
|
||||
}
|
||||
|
||||
|
||||
void io_end_buffering(void)
|
||||
{
|
||||
io_flush(NORMAL_FLUSH);
|
||||
io_flush();
|
||||
if (!io_multiplexing_out) {
|
||||
free(io_buffer);
|
||||
io_buffer = NULL;
|
||||
@@ -923,7 +597,7 @@ static void writefd(int fd,char *buf,size_t len)
|
||||
{
|
||||
stats.total_written += len;
|
||||
|
||||
msg_list_push(NORMAL_FLUSH);
|
||||
err_list_push();
|
||||
|
||||
if (!io_buffer || fd != multiplex_out_fd) {
|
||||
writefd_unbuffered(fd, buf, len);
|
||||
@@ -938,9 +612,8 @@ static void writefd(int fd,char *buf,size_t len)
|
||||
len -= n;
|
||||
io_buffer_count += n;
|
||||
}
|
||||
|
||||
if (io_buffer_count == IO_BUFFER_SIZE)
|
||||
io_flush(NORMAL_FLUSH);
|
||||
|
||||
if (io_buffer_count == IO_BUFFER_SIZE) io_flush();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -967,23 +640,19 @@ void write_int_named(int f, int32 x, const char *phase)
|
||||
*/
|
||||
void write_longint(int f, int64 x)
|
||||
{
|
||||
extern int remote_version;
|
||||
char b[8];
|
||||
|
||||
if (x <= 0x7FFFFFFF) {
|
||||
if (remote_version < 16 || x <= 0x7FFFFFFF) {
|
||||
write_int(f, (int)x);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef NO_INT64
|
||||
rprintf(FERROR,"Integer overflow - attempted 64 bit offset\n");
|
||||
exit_cleanup(RERR_UNSUPPORTED);
|
||||
#else
|
||||
write_int(f, (int32)0xFFFFFFFF);
|
||||
SIVAL(b,0,(x&0xFFFFFFFF));
|
||||
SIVAL(b,4,((x>>32)&0xFFFFFFFF));
|
||||
|
||||
writefd(f,b,8);
|
||||
#endif
|
||||
}
|
||||
|
||||
void write_buf(int f,char *buf,size_t len)
|
||||
@@ -1041,9 +710,9 @@ void io_printf(int fd, const char *format, ...)
|
||||
va_list ap;
|
||||
char buf[1024];
|
||||
int len;
|
||||
|
||||
|
||||
va_start(ap, format);
|
||||
len = vsnprintf(buf, sizeof buf, format, ap);
|
||||
len = vsnprintf(buf, sizeof(buf), format, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (len < 0) exit_cleanup(RERR_STREAMIO);
|
||||
@@ -1052,35 +721,35 @@ void io_printf(int fd, const char *format, ...)
|
||||
}
|
||||
|
||||
|
||||
/** Setup for multiplexing a MSG_* stream with the data stream. */
|
||||
/** Setup for multiplexing an error stream with the data stream */
|
||||
void io_start_multiplex_out(int fd)
|
||||
{
|
||||
multiplex_out_fd = fd;
|
||||
io_flush(NORMAL_FLUSH);
|
||||
io_start_buffering_out(fd);
|
||||
io_flush();
|
||||
io_start_buffering(fd);
|
||||
io_multiplexing_out = 1;
|
||||
}
|
||||
|
||||
/** Setup for multiplexing a MSG_* stream with the data stream. */
|
||||
/** Setup for multiplexing an error stream with the data stream */
|
||||
void io_start_multiplex_in(int fd)
|
||||
{
|
||||
multiplex_in_fd = fd;
|
||||
io_flush(NORMAL_FLUSH);
|
||||
io_flush();
|
||||
io_multiplexing_in = 1;
|
||||
}
|
||||
|
||||
/** Write an message to the multiplexed data stream. */
|
||||
int io_multiplex_write(enum msgcode code, char *buf, size_t len)
|
||||
/** Write an message to the multiplexed error stream */
|
||||
int io_multiplex_write(enum logcode code, char *buf, size_t len)
|
||||
{
|
||||
if (!io_multiplexing_out) return 0;
|
||||
|
||||
io_flush(NORMAL_FLUSH);
|
||||
io_flush();
|
||||
stats.total_written += (len+4);
|
||||
mplex_write(multiplex_out_fd, code, buf, len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Stop output multiplexing. */
|
||||
/** Stop output multiplexing */
|
||||
void io_multiplexing_close(void)
|
||||
{
|
||||
io_multiplexing_out = 0;
|
||||
|
||||
@@ -1 +1,49 @@
|
||||
.cvsignore
|
||||
Makefile
|
||||
a
|
||||
b
|
||||
config.cache
|
||||
config.h
|
||||
config.log
|
||||
config.status
|
||||
dist.tar.gz
|
||||
dummy
|
||||
rsync
|
||||
rsync-0.1
|
||||
rsync-0.1
|
||||
rsync-0.1
|
||||
rsync-0.1.tar.gz
|
||||
rsync-0.2
|
||||
rsync-0.2
|
||||
rsync-0.2.tar.gz
|
||||
rsync-0.3
|
||||
rsync-0.3
|
||||
rsync-0.3.tar.gz
|
||||
rsync-0.4
|
||||
rsync-0.4
|
||||
rsync-0.4.tar.gz
|
||||
rsync-0.5
|
||||
rsync-0.5
|
||||
rsync-0.5
|
||||
rsync-0.5
|
||||
rsync-0.5
|
||||
rsync-0.5
|
||||
rsync-0.5
|
||||
rsync-0.5
|
||||
rsync-0.5.tar.gz
|
||||
rsync-0.6
|
||||
rsync-0.7
|
||||
rsync-0.7
|
||||
rsync-0.8
|
||||
rsync-0.8
|
||||
rsync-0.8
|
||||
rsync-0.8
|
||||
rsync-ERSION
|
||||
rsync.aux
|
||||
rsync.dvi
|
||||
rsync.log
|
||||
tech_report.aux
|
||||
tech_report.dvi
|
||||
tech_report.log
|
||||
tech_report.ps
|
||||
test
|
||||
|
||||
17
lib/compat.c
17
lib/compat.c
@@ -116,12 +116,10 @@
|
||||
{
|
||||
size_t len = strlen(s);
|
||||
size_t ret = len;
|
||||
if (bufsize > 0) {
|
||||
if (len >= bufsize)
|
||||
len = bufsize-1;
|
||||
memcpy(d, s, len);
|
||||
d[len] = 0;
|
||||
}
|
||||
if (bufsize <= 0) return 0;
|
||||
if (len >= bufsize) len = bufsize-1;
|
||||
memcpy(d, s, len);
|
||||
d[len] = 0;
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
@@ -140,9 +138,10 @@
|
||||
size_t len2 = strlen(s);
|
||||
size_t ret = len1 + len2;
|
||||
|
||||
if (len1 < bufsize - 1) {
|
||||
if (len2 >= bufsize - len1)
|
||||
len2 = bufsize - len1 - 1;
|
||||
if (len1+len2 >= bufsize) {
|
||||
len2 = bufsize - (len1+1);
|
||||
}
|
||||
if (len2 > 0) {
|
||||
memcpy(d+len1, s, len2);
|
||||
d[len1+len2] = 0;
|
||||
}
|
||||
|
||||
199
lib/pool_alloc.3
199
lib/pool_alloc.3
@@ -1,199 +0,0 @@
|
||||
.ds d \-\^\-
|
||||
.ds o \fR[\fP
|
||||
.ds c \fR]\fP
|
||||
.ds | \fR|\fP
|
||||
.de D
|
||||
\\.B \*d\\$1
|
||||
..
|
||||
.de DI
|
||||
\\.BI \*d\\$1 \\$2
|
||||
..
|
||||
.de DR
|
||||
\\.BR \*d\\$1 \\$2
|
||||
..
|
||||
.de Di
|
||||
\\.BI \*d\\$1 " \\$2"
|
||||
..
|
||||
.de Db
|
||||
\\.B \*d\\$1 " \\$2"
|
||||
..
|
||||
.de Df
|
||||
\\.B \*d\*ono\*c\\$1
|
||||
..
|
||||
.de See
|
||||
See \fB\\$1\fP for details.
|
||||
..
|
||||
.de SeeIn
|
||||
See \fB\\$1\fP in \fB\\$2\fP for details.
|
||||
..
|
||||
.TH POOL_ALLOC 3
|
||||
.SH NAME
|
||||
pool_alloc, pool_free, pool_talloc, pool_tfree, pool_create, pool_destroy
|
||||
\- Allocate and free memory in managed allocation pools.
|
||||
.SH SYNOPSIS
|
||||
.B #include "pool_alloc.h"
|
||||
|
||||
\fBstruct alloc_pool *pool_create(size_t \fIsize\fB, size_t \fIquantum\fB, void (*\fIbomb\fB)(char *), int \fIflags\fB);
|
||||
|
||||
\fBvoid pool_destroy(struct alloc_pool *\fIpool\fB);
|
||||
|
||||
\fBvoid *pool_alloc(struct alloc_pool *\fIpool\fB, size_t \fIsize\fB, char *\fImsg\fB);
|
||||
|
||||
\fBvoid pool_free(struct alloc_pool *\fIpool\fB, sise_t \fIsize\fB, void *\fIaddr\fB);
|
||||
|
||||
\fBvoid *pool_talloc(struct alloc_pool *\fIpool\fB, \fItype\fB), int \fIcount\fB, char *\fImsg\fB);
|
||||
|
||||
\fBvoid pool_tfree(struct alloc_pool *\fIpool\fB, \fItype\fB, int \fIcount\fB, void *\fIaddr\fB);
|
||||
.SH DESCRIPTION
|
||||
.P
|
||||
The pool allocation routines use
|
||||
.B malloc()
|
||||
for underlying memory management.
|
||||
What allocation pools do is cause
|
||||
memory within a given pool to be in large contigious blocks
|
||||
(called extents) that when freed will be reusable. Unlike
|
||||
.B malloc()
|
||||
the allocations are not managed individually.
|
||||
Instead each extent tracks the total free memory within the
|
||||
extent. Each extent can either be used to allocate memory
|
||||
or to manage the freeing of memory within that extent.
|
||||
When an extent has less free memory than a given
|
||||
allocation request or when the first request to free
|
||||
memory within that extent is received the extent ceases to
|
||||
be used for allocation.
|
||||
.P
|
||||
This form of memory management is suited to large numbers of small
|
||||
related allocations that are held for a while
|
||||
and then freed as a group.
|
||||
Because the
|
||||
underlying allocations are done in large contigious extents
|
||||
when an extent is freed it releases a large enough
|
||||
contigious block of memory to be useful to subsequent
|
||||
.B malloc()
|
||||
and
|
||||
.B pool_alloc()
|
||||
calls even if allocations from other pools or from
|
||||
.B malloc()
|
||||
are made between allocations from a given pool.
|
||||
.P
|
||||
.B pool_create()
|
||||
Creates an allocation pool for subsequent calls to the pool
|
||||
allocation functions.
|
||||
When an extent is created for allocations it will be
|
||||
.I size
|
||||
bytes.
|
||||
Allocations from the pool have their sizes rounded up to a
|
||||
multiple of
|
||||
.I quantum
|
||||
bytes in length.
|
||||
Specifying
|
||||
.B 0
|
||||
for
|
||||
.I quantum
|
||||
Will produce a quantum that should meet maximal allignment
|
||||
on most platforms.
|
||||
If the
|
||||
.B POOL_QALIGN
|
||||
.I flag
|
||||
is set allocations will be aligned to addresses that are a
|
||||
multiple of
|
||||
.IR quantum .
|
||||
If the
|
||||
.B POOL_CLEAR
|
||||
.I flag
|
||||
is set all allocations from the pool will be zero filled.
|
||||
.P
|
||||
.B pool_destroy()
|
||||
destroys an allocation pool and frees all memory allocated
|
||||
in that pool.
|
||||
.P
|
||||
.B pool_alloc()
|
||||
allocates
|
||||
.I size
|
||||
bytes from the specified
|
||||
.IR pool .
|
||||
If
|
||||
.I size
|
||||
is
|
||||
.B 0
|
||||
.I quantum
|
||||
bytes will be freed.
|
||||
If the requested memory cannot be allocated
|
||||
.B pool_alloc()
|
||||
will call
|
||||
.I bomb()
|
||||
function, if defined, with
|
||||
.I msg
|
||||
as it's sole argument and
|
||||
.B NULL
|
||||
will be returned.
|
||||
.P
|
||||
.B pool_free()
|
||||
frees
|
||||
.I size
|
||||
bytes pointed to by
|
||||
.I addr
|
||||
previously allocated in the specified
|
||||
.IR pool .
|
||||
The memory freed within an extent will not be reusable until
|
||||
all of the memory in that extent has been freed but
|
||||
depending on the order in which the
|
||||
allocations are freed some extents may be released for reuse
|
||||
while others are still in use.
|
||||
If
|
||||
.I size
|
||||
is
|
||||
.B 0
|
||||
.I quantum
|
||||
bytes will be freed.
|
||||
If
|
||||
.I addr
|
||||
is
|
||||
.B 0
|
||||
no memory will be freed but subsequent allocations will come
|
||||
from a new extent.
|
||||
.P
|
||||
.B pool_talloc()
|
||||
is a macro that take a
|
||||
.I type
|
||||
and
|
||||
.I count
|
||||
instead of
|
||||
.I size
|
||||
and will cast the return value to the correct type.
|
||||
.P
|
||||
.B pool_tfree
|
||||
is a macro to free memory previously allocated in the
|
||||
specified
|
||||
.IR pool .
|
||||
.SH RETURN VALUE
|
||||
.B pool_create()
|
||||
returns a pointer to
|
||||
.BR "struct alloc_pool" .
|
||||
.P
|
||||
.B pool_alloc()
|
||||
and
|
||||
.B pool_talloc()
|
||||
return pointers to the allocated memory,
|
||||
or NULL if the request fails.
|
||||
For each extent so long as no allocations are smaller than varaible
|
||||
allignment requirements this pointer will be suitably
|
||||
alligned for any kind of variable.
|
||||
The return type of
|
||||
.B pool_alloc()
|
||||
will normally require casting to the desired type but
|
||||
.B pool_talloc()
|
||||
will returns a pointer of the requested
|
||||
.IR type .
|
||||
.P
|
||||
.BR pool_free() ,
|
||||
.B pool_tfree()
|
||||
and
|
||||
.B pool_destroy()
|
||||
return no value.
|
||||
.SH SEE ALSO
|
||||
.nf
|
||||
malloc(3)
|
||||
.SH AUTHOR
|
||||
pool_alloc was created by J.W. Schultz of Pegasystems Technologies.
|
||||
.SH BUGS AND ISSUES
|
||||
304
lib/pool_alloc.c
304
lib/pool_alloc.c
@@ -1,304 +0,0 @@
|
||||
#include "rsync.h"
|
||||
|
||||
#define POOL_DEF_EXTENT (32 * 1024)
|
||||
|
||||
struct alloc_pool
|
||||
{
|
||||
size_t size; /* extent size */
|
||||
size_t quantum; /* allocation quantum */
|
||||
struct pool_extent *live; /* current extent for
|
||||
* allocations */
|
||||
struct pool_extent *free; /* unfreed extent list */
|
||||
void (*bomb)();
|
||||
/* function to call if
|
||||
* malloc fails */
|
||||
int flags;
|
||||
|
||||
/* statistical data */
|
||||
unsigned long e_created; /* extents created */
|
||||
unsigned long e_freed; /* extents detroyed */
|
||||
uint64 n_allocated; /* calls to alloc */
|
||||
uint64 n_freed; /* calls to free */
|
||||
uint64 b_allocated; /* cum. bytes allocated */
|
||||
uint64 b_freed; /* cum. bytes freed */
|
||||
};
|
||||
|
||||
struct pool_extent
|
||||
{
|
||||
void *start; /* starting address */
|
||||
size_t free; /* free bytecount */
|
||||
size_t bound; /* bytes bound by padding,
|
||||
* overhead and freed */
|
||||
struct pool_extent *next;
|
||||
};
|
||||
|
||||
struct align_test {
|
||||
void *foo;
|
||||
uint64 bar;
|
||||
};
|
||||
|
||||
#define MINALIGN offsetof(struct align_test, bar)
|
||||
|
||||
/* Temporarily cast a void* var into a char* var when adding an offset (to
|
||||
* keep some compilers from complaining about the pointer arithmetic). */
|
||||
#define PTR_ADD(b,o) ( (void*) ((char*)(b) + (o)) )
|
||||
|
||||
alloc_pool_t
|
||||
pool_create(size_t size, size_t quantum,
|
||||
void (*bomb)(char *), int flags)
|
||||
{
|
||||
struct alloc_pool *pool;
|
||||
|
||||
if (!(pool = (struct alloc_pool*) malloc(sizeof (struct alloc_pool))))
|
||||
return pool;
|
||||
memset(pool, 0, sizeof (struct alloc_pool));
|
||||
|
||||
pool->size = size /* round extent size to min alignment reqs */
|
||||
? (size + MINALIGN - 1) & ~(MINALIGN - 1)
|
||||
: POOL_DEF_EXTENT;
|
||||
if (pool->flags & POOL_INTERN)
|
||||
{
|
||||
pool->size -= sizeof (struct pool_extent);
|
||||
flags |= POOL_APPEND;
|
||||
}
|
||||
pool->quantum = quantum ? quantum : MINALIGN;
|
||||
pool->bomb = bomb;
|
||||
pool->flags = flags;
|
||||
|
||||
return pool;
|
||||
}
|
||||
|
||||
void
|
||||
pool_destroy(alloc_pool_t p)
|
||||
{
|
||||
struct alloc_pool *pool = (struct alloc_pool *) p;
|
||||
struct pool_extent *cur, *next;
|
||||
|
||||
if (!pool)
|
||||
return;
|
||||
|
||||
if (pool->live)
|
||||
{
|
||||
cur = pool->live;
|
||||
free(cur->start);
|
||||
if (!(pool->flags & POOL_APPEND))
|
||||
free(cur);
|
||||
}
|
||||
for (cur = pool->free; cur; cur = next)
|
||||
{
|
||||
next = cur->next;
|
||||
free(cur->start);
|
||||
if (!(pool->flags & POOL_APPEND))
|
||||
free(cur);
|
||||
}
|
||||
free(pool);
|
||||
}
|
||||
|
||||
void *
|
||||
pool_alloc(alloc_pool_t p, size_t len, char *bomb)
|
||||
{
|
||||
struct alloc_pool *pool = (struct alloc_pool *) p;
|
||||
if (!pool)
|
||||
return NULL;
|
||||
|
||||
if (!len)
|
||||
len = pool->quantum;
|
||||
else if (pool->quantum > 1 && len % pool->quantum)
|
||||
len += pool->quantum - len % pool->quantum;
|
||||
|
||||
if (len > pool->size)
|
||||
goto bomb;
|
||||
|
||||
if (!pool->live || len > pool->live->free)
|
||||
{
|
||||
void *start;
|
||||
size_t free;
|
||||
size_t bound;
|
||||
size_t sqew;
|
||||
size_t asize;
|
||||
|
||||
if (pool->live)
|
||||
{
|
||||
pool->live->next = pool->free;
|
||||
pool->free = pool->live;
|
||||
}
|
||||
|
||||
free = pool->size;
|
||||
bound = 0;
|
||||
|
||||
asize = pool->size;
|
||||
if (pool->flags & POOL_APPEND)
|
||||
asize += sizeof (struct pool_extent);
|
||||
|
||||
if (!(start = (void *) malloc(asize)))
|
||||
goto bomb;
|
||||
|
||||
if (pool->flags & POOL_CLEAR)
|
||||
memset(start, 0, pool->size);
|
||||
|
||||
if (pool->flags & POOL_APPEND)
|
||||
{
|
||||
pool->live = PTR_ADD(start, free);
|
||||
}
|
||||
else if (!(pool->live = (struct pool_extent *) malloc(sizeof (struct pool_extent))))
|
||||
{
|
||||
goto bomb;
|
||||
}
|
||||
if (pool->flags & POOL_QALIGN && pool->quantum > 1
|
||||
&& (sqew = (size_t)PTR_ADD(start, free) % pool->quantum))
|
||||
{
|
||||
bound += sqew;
|
||||
free -= sqew;
|
||||
}
|
||||
pool->live->start = start;
|
||||
pool->live->free = free;
|
||||
pool->live->bound = bound;
|
||||
pool->live->next = NULL;
|
||||
|
||||
pool->e_created++;
|
||||
}
|
||||
|
||||
pool->n_allocated++;
|
||||
pool->b_allocated += len;
|
||||
|
||||
pool->live->free -= len;
|
||||
|
||||
return PTR_ADD(pool->live->start, pool->live->free);
|
||||
|
||||
bomb:
|
||||
if (pool->bomb)
|
||||
(*pool->bomb)(bomb);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
pool_free(alloc_pool_t p, size_t len, void *addr)
|
||||
{
|
||||
struct alloc_pool *pool = (struct alloc_pool *) p;
|
||||
struct pool_extent *cur;
|
||||
struct pool_extent *prev;
|
||||
|
||||
if (!pool)
|
||||
return;
|
||||
|
||||
if (!len)
|
||||
len = pool->quantum;
|
||||
else if (pool->quantum > 1 && len % pool->quantum)
|
||||
len += pool->quantum - len % pool->quantum;
|
||||
|
||||
if (!addr && pool->live)
|
||||
{
|
||||
pool->live->next = pool->free;
|
||||
pool->free = pool->live;
|
||||
pool->live = NULL;
|
||||
return;
|
||||
}
|
||||
pool->n_freed++;
|
||||
pool->b_freed += len;
|
||||
|
||||
cur = pool->live;
|
||||
if (cur
|
||||
&& addr >= cur->start
|
||||
&& addr < PTR_ADD(cur->start, pool->size))
|
||||
{
|
||||
if (addr == PTR_ADD(cur->start, cur->free))
|
||||
{
|
||||
if (pool->flags & POOL_CLEAR)
|
||||
memset(addr, 0, len);
|
||||
pool->b_freed += len;
|
||||
} else {
|
||||
cur->bound += len;
|
||||
}
|
||||
if (cur->free + cur->bound >= pool->size)
|
||||
{
|
||||
size_t sqew;
|
||||
|
||||
cur->free = pool->size;
|
||||
cur->bound = 0;
|
||||
if (pool->flags & POOL_QALIGN && pool->quantum > 1
|
||||
&& (sqew = (size_t)PTR_ADD(cur->start, cur->free) % pool->quantum))
|
||||
{
|
||||
cur->bound += sqew;
|
||||
cur->free -= sqew;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
for (prev = NULL, cur = pool->free; cur; prev = cur, cur = cur->next)
|
||||
{
|
||||
if (addr >= cur->start
|
||||
&& addr < PTR_ADD(cur->start, pool->size))
|
||||
break;
|
||||
}
|
||||
if (!cur)
|
||||
return;
|
||||
|
||||
if (prev)
|
||||
{
|
||||
prev->next = cur->next;
|
||||
cur->next = pool->free;
|
||||
pool->free = cur;
|
||||
}
|
||||
cur->bound += len;
|
||||
|
||||
if (cur->free + cur->bound >= pool->size)
|
||||
{
|
||||
pool->free = cur->next;
|
||||
|
||||
free(cur->start);
|
||||
if (!(pool->flags & POOL_APPEND))
|
||||
free(cur);
|
||||
pool->e_freed++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
#define FDPRINT(label, value) \
|
||||
snprintf(buf, BUFSIZ, label, value), \
|
||||
write(fd, buf, strlen(buf));
|
||||
|
||||
#define FDEXTSTAT(ext) \
|
||||
snprintf(buf, BUFSIZ, " %12ld %5ld\n", \
|
||||
(long) ext->free, \
|
||||
(long) ext->bound), \
|
||||
write(fd, buf, strlen(buf))
|
||||
|
||||
void
|
||||
pool_stats(alloc_pool_t p, int fd, int summarize)
|
||||
{
|
||||
struct alloc_pool *pool = (struct alloc_pool *) p;
|
||||
struct pool_extent *cur;
|
||||
char buf[BUFSIZ];
|
||||
|
||||
if (!pool)
|
||||
return;
|
||||
|
||||
FDPRINT(" Extent size: %12ld\n", (long) pool->size);
|
||||
FDPRINT(" Alloc quantum: %12ld\n", (long) pool->quantum);
|
||||
FDPRINT(" Extents created: %12ld\n", pool->e_created);
|
||||
FDPRINT(" Extents freed: %12ld\n", pool->e_freed);
|
||||
FDPRINT(" Alloc count: %12.0f\n", (double) pool->n_allocated);
|
||||
FDPRINT(" Free Count: %12.0f\n", (double) pool->n_freed);
|
||||
FDPRINT(" Alloc bytes: %12.0f\n", (double) pool->b_allocated);
|
||||
FDPRINT(" Free bytes: %12.0f\n", (double) pool->b_freed);
|
||||
|
||||
if (summarize)
|
||||
return;
|
||||
|
||||
if (!pool->live && !pool->free)
|
||||
return;
|
||||
|
||||
write(fd, "\n", 1);
|
||||
|
||||
if (pool->live)
|
||||
{
|
||||
FDEXTSTAT(pool->live);
|
||||
}
|
||||
strcpy(buf, " FREE BOUND\n");
|
||||
write(fd, buf, strlen(buf));
|
||||
|
||||
for (cur = pool->free; cur; cur = cur->next)
|
||||
{
|
||||
FDEXTSTAT(cur);
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
#include <stddef.h>
|
||||
|
||||
#define POOL_CLEAR (1<<0) /* zero fill allocations */
|
||||
#define POOL_QALIGN (1<<1) /* align data to quanta */
|
||||
#define POOL_INTERN (1<<2) /* Allocate extent structures */
|
||||
#define POOL_APPEND (1<<3) /* or appended to extent data */
|
||||
|
||||
typedef void *alloc_pool_t;
|
||||
|
||||
alloc_pool_t pool_create(size_t size, size_t quantum, void (*bomb)(char *), int flags);
|
||||
void pool_destroy(alloc_pool_t pool);
|
||||
void *pool_alloc(alloc_pool_t pool, size_t size, char *bomb);
|
||||
void pool_free(alloc_pool_t pool, size_t size, void *addr);
|
||||
|
||||
#define pool_talloc(pool, type, count, bomb) \
|
||||
((type *)pool_alloc(pool, sizeof(type) * count, bomb))
|
||||
|
||||
#define pool_tfree(pool, type, count, addr) \
|
||||
(pool_free(pool, sizeof(type) * count, addr))
|
||||
|
||||
91
loadparm.c
91
loadparm.c
@@ -6,17 +6,17 @@
|
||||
* Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
|
||||
*/
|
||||
|
||||
/*
|
||||
/*
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
@@ -36,7 +36,7 @@
|
||||
* 3) add it to the list of available functions (eg: using FN_GLOBAL_STRING())
|
||||
* 4) If it's a global then initialise it in init_globals. If a local
|
||||
* (ie. service) parameter then initialise it in the sDefault structure
|
||||
*
|
||||
*
|
||||
*
|
||||
* Notes:
|
||||
* The configuration file is processed sequentially for speed. It is NOT
|
||||
@@ -61,7 +61,7 @@ typedef char pstring[1024];
|
||||
typedef enum
|
||||
{
|
||||
P_BOOL,P_BOOLREV,P_CHAR,P_INTEGER,P_OCTAL,
|
||||
P_PATH,P_STRING,P_GSTRING,P_ENUM,P_SEP
|
||||
P_STRING,P_GSTRING,P_ENUM,P_SEP
|
||||
} parm_type;
|
||||
|
||||
typedef enum
|
||||
@@ -93,7 +93,7 @@ struct parm_struct
|
||||
#define iSERVICE(i) (*pSERVICE(i))
|
||||
#define LP_SNUM_OK(iService) (((iService) >= 0) && ((iService) < iNumServices))
|
||||
|
||||
/*
|
||||
/*
|
||||
* This structure describes global (ie., server-wide) parameters.
|
||||
*/
|
||||
typedef struct
|
||||
@@ -101,16 +101,16 @@ typedef struct
|
||||
char *motd_file;
|
||||
char *log_file;
|
||||
char *pid_file;
|
||||
char *socket_options;
|
||||
int syslog_facility;
|
||||
int max_verbosity;
|
||||
char *socket_options;
|
||||
} global;
|
||||
|
||||
static global Globals;
|
||||
|
||||
|
||||
/*
|
||||
* This structure describes a single service.
|
||||
|
||||
/*
|
||||
* This structure describes a single service.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
@@ -144,7 +144,7 @@ typedef struct
|
||||
|
||||
|
||||
/* This is a default service used to prime a services structure */
|
||||
static service sDefault =
|
||||
static service sDefault =
|
||||
{
|
||||
NULL, /* name */
|
||||
NULL, /* path */
|
||||
@@ -156,7 +156,7 @@ static service sDefault =
|
||||
False, /* transfer logging */
|
||||
False, /* ignore errors */
|
||||
"nobody",/* uid */
|
||||
|
||||
|
||||
/* TODO: This causes problems on Debian, where it is called
|
||||
* "nogroup". Debian patch this in their version of the
|
||||
* package, but it would be nice to be consistent. Possibly
|
||||
@@ -165,7 +165,7 @@ static service sDefault =
|
||||
* What is the best behaviour? Perhaps always using (gid_t)
|
||||
* -2? */
|
||||
"nobody",/* gid */
|
||||
|
||||
|
||||
NULL, /* hosts allow */
|
||||
NULL, /* hosts deny */
|
||||
NULL, /* auth users */
|
||||
@@ -222,7 +222,7 @@ static struct enum_list enum_facilities[] = {
|
||||
{ LOG_NEWS, "news" },
|
||||
#endif
|
||||
#ifdef LOG_AUTH
|
||||
{ LOG_AUTH, "security" },
|
||||
{ LOG_AUTH, "security" },
|
||||
#endif
|
||||
#ifdef LOG_SYSLOG
|
||||
{ LOG_SYSLOG, "syslog" },
|
||||
@@ -268,14 +268,13 @@ static struct parm_struct parm_table[] =
|
||||
{"socket options", P_STRING, P_GLOBAL, &Globals.socket_options,NULL, 0},
|
||||
{"log file", P_STRING, P_GLOBAL, &Globals.log_file, NULL, 0},
|
||||
{"pid file", P_STRING, P_GLOBAL, &Globals.pid_file, NULL, 0},
|
||||
{"max verbosity", P_INTEGER, P_GLOBAL, &Globals.max_verbosity, NULL, 0},
|
||||
|
||||
{"timeout", P_INTEGER, P_LOCAL, &sDefault.timeout, NULL, 0},
|
||||
{"max connections", P_INTEGER, P_LOCAL, &sDefault.max_connections,NULL, 0},
|
||||
{"name", P_STRING, P_LOCAL, &sDefault.name, NULL, 0},
|
||||
{"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL, 0},
|
||||
{"lock file", P_STRING, P_LOCAL, &sDefault.lock_file, NULL, 0},
|
||||
{"path", P_PATH, P_LOCAL, &sDefault.path, NULL, 0},
|
||||
{"path", P_STRING, P_LOCAL, &sDefault.path, NULL, 0},
|
||||
{"read only", P_BOOL, P_LOCAL, &sDefault.read_only, NULL, 0},
|
||||
{"list", P_BOOL, P_LOCAL, &sDefault.list, NULL, 0},
|
||||
{"use chroot", P_BOOL, P_LOCAL, &sDefault.use_chroot, NULL, 0},
|
||||
@@ -305,11 +304,10 @@ Initialise the global parameter structure.
|
||||
***************************************************************************/
|
||||
static void init_globals(void)
|
||||
{
|
||||
memset(&Globals, 0, sizeof Globals);
|
||||
memset(&Globals, 0, sizeof(Globals));
|
||||
#ifdef LOG_DAEMON
|
||||
Globals.syslog_facility = LOG_DAEMON;
|
||||
#endif
|
||||
Globals.max_verbosity = 1;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
@@ -321,8 +319,8 @@ static void init_locals(void)
|
||||
|
||||
|
||||
/*
|
||||
In this section all the functions that are used to access the
|
||||
parameters from the rest of the program are defined
|
||||
In this section all the functions that are used to access the
|
||||
parameters from the rest of the program are defined
|
||||
*/
|
||||
|
||||
#define FN_GLOBAL_STRING(fn_name,ptr) \
|
||||
@@ -349,7 +347,6 @@ FN_GLOBAL_STRING(lp_log_file, &Globals.log_file)
|
||||
FN_GLOBAL_STRING(lp_pid_file, &Globals.pid_file)
|
||||
FN_GLOBAL_STRING(lp_socket_options, &Globals.socket_options)
|
||||
FN_GLOBAL_INTEGER(lp_syslog_facility, &Globals.syslog_facility)
|
||||
FN_GLOBAL_INTEGER(lp_max_verbosity, &Globals.max_verbosity)
|
||||
|
||||
FN_LOCAL_STRING(lp_name, name)
|
||||
FN_LOCAL_STRING(lp_comment, comment)
|
||||
@@ -379,11 +376,12 @@ FN_LOCAL_INTEGER(lp_timeout, timeout)
|
||||
FN_LOCAL_INTEGER(lp_max_connections, max_connections)
|
||||
|
||||
/* local prototypes */
|
||||
static int strwicmp(char *psz1, char *psz2);
|
||||
static int map_parameter(char *parmname);
|
||||
static BOOL set_boolean(BOOL *pb, char *parmvalue);
|
||||
static int strwicmp( char *psz1, char *psz2 );
|
||||
static int map_parameter( char *parmname);
|
||||
static BOOL set_boolean( BOOL *pb, char *parmvalue );
|
||||
static int getservicebyname(char *name, service *pserviceDest);
|
||||
static void copy_service(service *pserviceDest, service *pserviceSource);
|
||||
static void copy_service( service *pserviceDest,
|
||||
service *pserviceSource);
|
||||
static BOOL do_parameter(char *parmname, char *parmvalue);
|
||||
static BOOL do_section(char *sectionname);
|
||||
|
||||
@@ -423,7 +421,7 @@ static void string_set(char **s, const char *v)
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
add a new service to the services array initialising it with the given
|
||||
add a new service to the services array initialising it with the given
|
||||
service
|
||||
***************************************************************************/
|
||||
static int add_a_service(service *pservice, char *name)
|
||||
@@ -435,7 +433,7 @@ static int add_a_service(service *pservice, char *name)
|
||||
tservice = *pservice;
|
||||
|
||||
/* it might already exist */
|
||||
if (name)
|
||||
if (name)
|
||||
{
|
||||
i = getservicebyname(name,NULL);
|
||||
if (i >= 0)
|
||||
@@ -457,7 +455,7 @@ static int add_a_service(service *pservice, char *name)
|
||||
init_service(pSERVICE(i));
|
||||
copy_service(pSERVICE(i),&tservice);
|
||||
if (name)
|
||||
string_set(&iSERVICE(i).name,name);
|
||||
string_set(&iSERVICE(i).name,name);
|
||||
|
||||
return(i);
|
||||
}
|
||||
@@ -495,7 +493,7 @@ static int strwicmp(char *psz1, char *psz2)
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
Map a parameter's string representation to something we can use.
|
||||
Map a parameter's string representation to something we can use.
|
||||
Returns False if the parameter string is not recognised, else TRUE.
|
||||
***************************************************************************/
|
||||
static int map_parameter(char *parmname)
|
||||
@@ -505,7 +503,7 @@ static int map_parameter(char *parmname)
|
||||
if (*parmname == '-')
|
||||
return(-1);
|
||||
|
||||
for (iIndex = 0; parm_table[iIndex].label; iIndex++)
|
||||
for (iIndex = 0; parm_table[iIndex].label; iIndex++)
|
||||
if (strwicmp(parm_table[iIndex].label, parmname) == 0)
|
||||
return(iIndex);
|
||||
|
||||
@@ -516,7 +514,7 @@ static int map_parameter(char *parmname)
|
||||
|
||||
/***************************************************************************
|
||||
Set a boolean variable from the text value stored in the passed string.
|
||||
Returns True in success, False if the passed string does not correctly
|
||||
Returns True in success, False if the passed string does not correctly
|
||||
represent a boolean.
|
||||
***************************************************************************/
|
||||
static BOOL set_boolean(BOOL *pb, char *parmvalue)
|
||||
@@ -550,7 +548,7 @@ static int getservicebyname(char *name, service *pserviceDest)
|
||||
int iService;
|
||||
|
||||
for (iService = iNumServices - 1; iService >= 0; iService--)
|
||||
if (strwicmp(iSERVICE(iService).name, name) == 0)
|
||||
if (strwicmp(iSERVICE(iService).name, name) == 0)
|
||||
{
|
||||
if (pserviceDest != NULL)
|
||||
copy_service(pserviceDest, pSERVICE(iService));
|
||||
@@ -566,7 +564,7 @@ static int getservicebyname(char *name, service *pserviceDest)
|
||||
Copy a service structure to another
|
||||
|
||||
***************************************************************************/
|
||||
static void copy_service(service *pserviceDest,
|
||||
static void copy_service(service *pserviceDest,
|
||||
service *pserviceSource)
|
||||
{
|
||||
int i;
|
||||
@@ -574,9 +572,9 @@ static void copy_service(service *pserviceDest,
|
||||
for (i=0;parm_table[i].label;i++)
|
||||
if (parm_table[i].ptr && parm_table[i].class == P_LOCAL) {
|
||||
void *def_ptr = parm_table[i].ptr;
|
||||
void *src_ptr =
|
||||
void *src_ptr =
|
||||
((char *)pserviceSource) + PTR_DIFF(def_ptr,&sDefault);
|
||||
void *dest_ptr =
|
||||
void *dest_ptr =
|
||||
((char *)pserviceDest) + PTR_DIFF(def_ptr,&sDefault);
|
||||
|
||||
switch (parm_table[i].type)
|
||||
@@ -596,7 +594,6 @@ static void copy_service(service *pserviceDest,
|
||||
*(char *)dest_ptr = *(char *)src_ptr;
|
||||
break;
|
||||
|
||||
case P_PATH:
|
||||
case P_STRING:
|
||||
string_set(dest_ptr,*(char **)src_ptr);
|
||||
break;
|
||||
@@ -617,7 +614,6 @@ static BOOL lp_do_parameter(int snum, char *parmname, char *parmvalue)
|
||||
int parmnum, i;
|
||||
void *parm_ptr=NULL; /* where we are going to store the result */
|
||||
void *def_ptr=NULL;
|
||||
char *cp;
|
||||
|
||||
parmnum = map_parameter(parmname);
|
||||
|
||||
@@ -664,15 +660,6 @@ static BOOL lp_do_parameter(int snum, char *parmname, char *parmvalue)
|
||||
sscanf(parmvalue,"%o",(int *)parm_ptr);
|
||||
break;
|
||||
|
||||
case P_PATH:
|
||||
string_set(parm_ptr,parmvalue);
|
||||
if ((cp = *(char**)parm_ptr) != NULL) {
|
||||
int len = strlen(cp);
|
||||
while (len > 1 && cp[len-1] == '/') len--;
|
||||
cp[len] = '\0';
|
||||
}
|
||||
break;
|
||||
|
||||
case P_STRING:
|
||||
string_set(parm_ptr,parmvalue);
|
||||
break;
|
||||
@@ -724,7 +711,7 @@ static BOOL do_section(char *sectionname)
|
||||
init_locals();
|
||||
|
||||
/* if we've just struck a global section, note the fact. */
|
||||
bInGlobalSection = isglobal;
|
||||
bInGlobalSection = isglobal;
|
||||
|
||||
/* check for multiple global sections */
|
||||
if (bInGlobalSection)
|
||||
@@ -756,7 +743,7 @@ static BOOL do_section(char *sectionname)
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
Load the services array from the services file. Return True on success,
|
||||
Load the services array from the services file. Return True on success,
|
||||
False on failure.
|
||||
***************************************************************************/
|
||||
BOOL lp_load(char *pszFname, int globals_only)
|
||||
@@ -766,11 +753,11 @@ BOOL lp_load(char *pszFname, int globals_only)
|
||||
extern int am_root;
|
||||
pstring n2;
|
||||
BOOL bRetval;
|
||||
|
||||
|
||||
bRetval = False;
|
||||
|
||||
bInGlobalSection = True;
|
||||
|
||||
|
||||
init_globals();
|
||||
|
||||
if (pszFname)
|
||||
@@ -783,7 +770,7 @@ BOOL lp_load(char *pszFname, int globals_only)
|
||||
/* We get sections first, so have to start 'behind' to make up */
|
||||
iServiceIndex = -1;
|
||||
bRetval = pm_process(n2, globals_only?NULL:do_section, do_parameter);
|
||||
|
||||
|
||||
return (bRetval);
|
||||
}
|
||||
|
||||
@@ -807,7 +794,7 @@ int lp_number(char *name)
|
||||
int iService;
|
||||
|
||||
for (iService = iNumServices - 1; iService >= 0; iService--)
|
||||
if (strequal(lp_name(iService), name))
|
||||
if (strequal(lp_name(iService), name))
|
||||
break;
|
||||
|
||||
return (iService);
|
||||
|
||||
297
log.c
297
log.c
@@ -1,18 +1,18 @@
|
||||
/* -*- c-file-style: "linux"; -*-
|
||||
|
||||
|
||||
Copyright (C) 1998-2001 by Andrew Tridgell <tridge@samba.org>
|
||||
Copyright (C) 2000-2001 by Martin Pool <mbp@samba.org>
|
||||
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
@@ -27,18 +27,10 @@
|
||||
*/
|
||||
#include "rsync.h"
|
||||
|
||||
extern int am_daemon;
|
||||
extern int am_server;
|
||||
extern int am_sender;
|
||||
extern int quiet;
|
||||
extern int module_id;
|
||||
extern int msg_fd_out;
|
||||
extern char *auth_user;
|
||||
extern char *log_format;
|
||||
|
||||
static int log_initialised;
|
||||
static char *logfname;
|
||||
static FILE *logfile;
|
||||
static int log_error_fd = -1;
|
||||
struct stats stats;
|
||||
|
||||
int log_got_error=0;
|
||||
@@ -47,27 +39,26 @@ struct {
|
||||
int code;
|
||||
char const *name;
|
||||
} const rerr_names[] = {
|
||||
{ RERR_SYNTAX , "syntax or usage error" },
|
||||
{ RERR_PROTOCOL , "protocol incompatibility" },
|
||||
{ RERR_FILESELECT , "errors selecting input/output files, dirs" },
|
||||
{ RERR_UNSUPPORTED, "requested action not supported" },
|
||||
{ RERR_STARTCLIENT, "error starting client-server protocol" },
|
||||
{ RERR_SOCKETIO , "error in socket IO" },
|
||||
{ RERR_FILEIO , "error in file IO" },
|
||||
{ RERR_STREAMIO , "error in rsync protocol data stream" },
|
||||
{ RERR_MESSAGEIO , "errors with program diagnostics" },
|
||||
{ RERR_IPC , "error in IPC code" },
|
||||
{ RERR_SIGNAL , "received SIGUSR1 or SIGINT" },
|
||||
{ RERR_WAITCHILD , "some error returned by waitpid()" },
|
||||
{ RERR_MALLOC , "error allocating core memory buffers" },
|
||||
{ RERR_PARTIAL , "some files could not be transferred" },
|
||||
{ RERR_VANISHED , "some files vanished before they could be transfered" },
|
||||
{ RERR_TIMEOUT , "timeout in data send/receive" },
|
||||
{ RERR_SYNTAX , "syntax or usage error" },
|
||||
{ RERR_PROTOCOL , "protocol incompatibility" },
|
||||
{ RERR_FILESELECT , "errors selecting input/output files, dirs" },
|
||||
{ RERR_UNSUPPORTED, "requested action not supported" },
|
||||
{ RERR_STARTCLIENT, "error starting client-server protocol" },
|
||||
{ RERR_SOCKETIO , "error in socket IO" },
|
||||
{ RERR_FILEIO , "error in file IO" },
|
||||
{ RERR_STREAMIO , "error in rsync protocol data stream" },
|
||||
{ RERR_MESSAGEIO , "errors with program diagnostics" },
|
||||
{ RERR_IPC , "error in IPC code" },
|
||||
{ RERR_SIGNAL , "received SIGUSR1 or SIGINT" },
|
||||
{ RERR_WAITCHILD , "some error returned by waitpid()" },
|
||||
{ RERR_MALLOC , "error allocating core memory buffers" },
|
||||
{ RERR_PARTIAL , "some files could not be transferred" },
|
||||
{ RERR_TIMEOUT , "timeout in data send/receive" },
|
||||
{ RERR_CMD_FAILED , "remote shell failed" },
|
||||
{ RERR_CMD_KILLED , "remote shell killed" },
|
||||
{ RERR_CMD_RUN, "remote command could not be run" },
|
||||
{ RERR_CMD_NOTFOUND, "remote command not found" },
|
||||
{ 0, NULL }
|
||||
{ RERR_CMD_NOTFOUND, "remote command not found" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
|
||||
@@ -77,12 +68,67 @@ struct {
|
||||
*/
|
||||
static char const *rerr_name(int code)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; rerr_names[i].name; i++) {
|
||||
if (rerr_names[i].code == code)
|
||||
return rerr_names[i].name;
|
||||
int i;
|
||||
for (i = 0; rerr_names[i].name; i++) {
|
||||
if (rerr_names[i].code == code)
|
||||
return rerr_names[i].name;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct err_list {
|
||||
struct err_list *next;
|
||||
char *buf;
|
||||
int len;
|
||||
int written; /* how many bytes we have written so far */
|
||||
};
|
||||
|
||||
static struct err_list *err_list_head;
|
||||
static struct err_list *err_list_tail;
|
||||
|
||||
/* add an error message to the pending error list */
|
||||
static void err_list_add(int code, char *buf, int len)
|
||||
{
|
||||
struct err_list *el;
|
||||
el = new(struct err_list);
|
||||
if (!el) exit_cleanup(RERR_MALLOC);
|
||||
el->next = NULL;
|
||||
el->buf = new_array(char, len+4);
|
||||
if (!el->buf) exit_cleanup(RERR_MALLOC);
|
||||
memcpy(el->buf+4, buf, len);
|
||||
SIVAL(el->buf, 0, ((code+MPLEX_BASE)<<24) | len);
|
||||
el->len = len+4;
|
||||
el->written = 0;
|
||||
if (err_list_tail) {
|
||||
err_list_tail->next = el;
|
||||
} else {
|
||||
err_list_head = el;
|
||||
}
|
||||
err_list_tail = el;
|
||||
}
|
||||
|
||||
|
||||
/* try to push errors off the error list onto the wire */
|
||||
void err_list_push(void)
|
||||
{
|
||||
if (log_error_fd == -1) return;
|
||||
|
||||
while (err_list_head) {
|
||||
struct err_list *el = err_list_head;
|
||||
int n = write(log_error_fd, el->buf+el->written, el->len - el->written);
|
||||
/* don't check for an error if the best way of handling the error is
|
||||
to ignore it */
|
||||
if (n == -1) break;
|
||||
if (n > 0) {
|
||||
el->written += n;
|
||||
}
|
||||
if (el->written == el->len) {
|
||||
free(el->buf);
|
||||
err_list_head = el->next;
|
||||
if (!err_list_head) err_list_tail = NULL;
|
||||
free(el);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -91,7 +137,7 @@ static void logit(int priority, char *buf)
|
||||
if (logfname) {
|
||||
if (!logfile)
|
||||
log_open();
|
||||
fprintf(logfile,"%s [%d] %s",
|
||||
fprintf(logfile,"%s [%d] %s",
|
||||
timestring(time(NULL)), (int)getpid(), buf);
|
||||
fflush(logfile);
|
||||
} else {
|
||||
@@ -108,8 +154,8 @@ void log_init(void)
|
||||
log_initialised = 1;
|
||||
|
||||
/* this looks pointless, but it is needed in order for the
|
||||
* C library on some systems to fetch the timezone info
|
||||
* before the chroot */
|
||||
C library on some systems to fetch the timezone info
|
||||
before the chroot */
|
||||
t = time(NULL);
|
||||
localtime(&t);
|
||||
|
||||
@@ -156,18 +202,27 @@ void log_close(void)
|
||||
}
|
||||
}
|
||||
|
||||
/* setup the error file descriptor - used when we are a server
|
||||
that is receiving files */
|
||||
void set_error_fd(int fd)
|
||||
{
|
||||
log_error_fd = fd;
|
||||
set_nonblocking(log_error_fd);
|
||||
}
|
||||
|
||||
/* this is the underlying (unformatted) rsync debugging function. Call
|
||||
* it with FINFO, FERROR or FLOG */
|
||||
it with FINFO, FERROR or FLOG */
|
||||
void rwrite(enum logcode code, char *buf, int len)
|
||||
{
|
||||
FILE *f=NULL;
|
||||
extern int am_daemon;
|
||||
extern int am_server;
|
||||
extern int quiet;
|
||||
/* recursion can happen with certain fatal conditions */
|
||||
|
||||
if (quiet && code == FINFO)
|
||||
return;
|
||||
if (quiet && code == FINFO) return;
|
||||
|
||||
if (len < 0)
|
||||
exit_cleanup(RERR_MESSAGEIO);
|
||||
if (len < 0) exit_cleanup(RERR_MESSAGEIO);
|
||||
|
||||
buf[len] = 0;
|
||||
|
||||
@@ -176,14 +231,17 @@ void rwrite(enum logcode code, char *buf, int len)
|
||||
return;
|
||||
}
|
||||
|
||||
if (am_server) {
|
||||
/* Pass it to non-server side, perhaps through our sibling. */
|
||||
if (msg_fd_out >= 0) {
|
||||
send_msg((enum msgcode)code, buf, len);
|
||||
return;
|
||||
}
|
||||
if (io_multiplex_write((enum msgcode)code, buf, len))
|
||||
return;
|
||||
/* first try to pass it off to our sibling */
|
||||
if (am_server && log_error_fd != -1) {
|
||||
err_list_add(code, buf, len);
|
||||
err_list_push();
|
||||
return;
|
||||
}
|
||||
|
||||
/* next, if we are a server but not in daemon mode, and multiplexing
|
||||
* is enabled, pass it to the other side. */
|
||||
if (am_server && !am_daemon && io_multiplex_write(code, buf, len)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* otherwise, if in daemon mode and either we are not a server
|
||||
@@ -192,9 +250,7 @@ void rwrite(enum logcode code, char *buf, int len)
|
||||
* side because we don't want the client to see most errors for
|
||||
* security reasons. We do want early messages when running daemon
|
||||
* mode over a remote shell to go to the remote side; those will
|
||||
* fall through to the next case.
|
||||
* Note that this is only for the time before multiplexing is enabled.
|
||||
*/
|
||||
* fall through to the next case. */
|
||||
if (am_daemon && (!am_server || log_initialised)) {
|
||||
static int depth;
|
||||
int priority = LOG_INFO;
|
||||
@@ -214,14 +270,14 @@ void rwrite(enum logcode code, char *buf, int len)
|
||||
if (code == FERROR) {
|
||||
log_got_error = 1;
|
||||
f = stderr;
|
||||
}
|
||||
}
|
||||
|
||||
if (code == FINFO) {
|
||||
if (am_server)
|
||||
if (am_server)
|
||||
f = stderr;
|
||||
else
|
||||
f = stdout;
|
||||
}
|
||||
}
|
||||
|
||||
if (!f) exit_cleanup(RERR_MESSAGEIO);
|
||||
|
||||
@@ -235,7 +291,7 @@ void rwrite(enum logcode code, char *buf, int len)
|
||||
* FLOG. */
|
||||
void rprintf(enum logcode code, const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_list ap;
|
||||
char buf[1024];
|
||||
int len;
|
||||
|
||||
@@ -284,11 +340,11 @@ void rprintf(enum logcode code, const char *format, ...)
|
||||
* message catalog we need to call it once before chroot-ing. */
|
||||
void rsyserr(enum logcode code, int errcode, const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_list ap;
|
||||
char buf[1024];
|
||||
int len;
|
||||
size_t sys_len;
|
||||
char *sysmsg;
|
||||
char *sysmsg;
|
||||
|
||||
va_start(ap, format);
|
||||
/* Note: might return <0 */
|
||||
@@ -300,17 +356,17 @@ void rsyserr(enum logcode code, int errcode, const char *format, ...)
|
||||
if ((size_t) len > sizeof(buf)-1)
|
||||
exit_cleanup(RERR_MESSAGEIO);
|
||||
|
||||
sysmsg = strerror(errcode);
|
||||
sys_len = strlen(sysmsg);
|
||||
if ((size_t) len + 3 + sys_len > sizeof(buf) - 1)
|
||||
exit_cleanup(RERR_MESSAGEIO);
|
||||
sysmsg = strerror(errcode);
|
||||
sys_len = strlen(sysmsg);
|
||||
if ((size_t) len + 3 + sys_len > sizeof(buf) - 1)
|
||||
exit_cleanup(RERR_MESSAGEIO);
|
||||
|
||||
strcpy(buf + len, ": ");
|
||||
len += 2;
|
||||
strcpy(buf + len, sysmsg);
|
||||
len += sys_len;
|
||||
strcpy(buf + len, "\n");
|
||||
len++;
|
||||
strcpy(buf + len, ": ");
|
||||
len += 2;
|
||||
strcpy(buf + len, sysmsg);
|
||||
len += sys_len;
|
||||
strcpy(buf + len, "\n");
|
||||
len++;
|
||||
|
||||
rwrite(code, buf, len);
|
||||
}
|
||||
@@ -320,6 +376,7 @@ void rsyserr(enum logcode code, int errcode, const char *format, ...)
|
||||
void rflush(enum logcode code)
|
||||
{
|
||||
FILE *f = NULL;
|
||||
extern int am_daemon;
|
||||
|
||||
if (am_daemon) {
|
||||
return;
|
||||
@@ -327,18 +384,19 @@ void rflush(enum logcode code)
|
||||
|
||||
if (code == FLOG) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (code == FERROR) {
|
||||
f = stderr;
|
||||
}
|
||||
}
|
||||
|
||||
if (code == FINFO) {
|
||||
if (am_server)
|
||||
extern int am_server;
|
||||
if (am_server)
|
||||
f = stderr;
|
||||
else
|
||||
f = stdout;
|
||||
}
|
||||
}
|
||||
|
||||
if (!f) exit_cleanup(RERR_MESSAGEIO);
|
||||
fflush(f);
|
||||
@@ -347,15 +405,20 @@ void rflush(enum logcode code)
|
||||
|
||||
|
||||
/* a generic logging routine for send/recv, with parameter
|
||||
* substitiution */
|
||||
substitiution */
|
||||
static void log_formatted(enum logcode code,
|
||||
char *format, char *op, struct file_struct *file,
|
||||
struct stats *initial_stats)
|
||||
{
|
||||
extern int module_id;
|
||||
extern char *auth_user;
|
||||
char buf[1024];
|
||||
char buf2[1024];
|
||||
char *p, *s, *n;
|
||||
size_t l;
|
||||
extern struct stats stats;
|
||||
extern int am_sender;
|
||||
extern int am_daemon;
|
||||
int64 b;
|
||||
|
||||
/* We expand % codes one by one in place in buf. We don't
|
||||
@@ -366,56 +429,57 @@ static void log_formatted(enum logcode code,
|
||||
memset(buf, 0, sizeof buf);
|
||||
strlcpy(buf, format, sizeof(buf));
|
||||
|
||||
for (s = &buf[0]; s && (p = strchr(s,'%')); ) {
|
||||
for (s=&buf[0];
|
||||
s && (p=strchr(s,'%')); ) {
|
||||
n = NULL;
|
||||
s = p + 1;
|
||||
|
||||
switch (p[1]) {
|
||||
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",
|
||||
(double)file->length);
|
||||
case 'l':
|
||||
snprintf(buf2,sizeof(buf2),"%.0f",
|
||||
(double)file->length);
|
||||
n = buf2;
|
||||
break;
|
||||
case 'p':
|
||||
snprintf(buf2,sizeof(buf2),"%d",
|
||||
(int)getpid());
|
||||
case 'p':
|
||||
snprintf(buf2,sizeof(buf2),"%d",
|
||||
(int)getpid());
|
||||
n = buf2;
|
||||
break;
|
||||
case 'o': n = op; break;
|
||||
case 'f':
|
||||
pathjoin(buf2, sizeof buf2,
|
||||
file->basedir ? file->basedir : "",
|
||||
case 'f':
|
||||
snprintf(buf2, sizeof(buf2), "%s/%s",
|
||||
file->basedir?file->basedir:"",
|
||||
f_name(file));
|
||||
clean_fname(buf2);
|
||||
n = buf2;
|
||||
n = buf2;
|
||||
if (*n == '/') n++;
|
||||
break;
|
||||
case 'm': n = lp_name(module_id); break;
|
||||
case 't': n = timestring(time(NULL)); break;
|
||||
case 'P': n = lp_path(module_id); break;
|
||||
case 'u': n = auth_user; break;
|
||||
case 'b':
|
||||
case 'b':
|
||||
if (am_sender) {
|
||||
b = stats.total_written -
|
||||
b = stats.total_written -
|
||||
initial_stats->total_written;
|
||||
} else {
|
||||
b = stats.total_read -
|
||||
b = stats.total_read -
|
||||
initial_stats->total_read;
|
||||
}
|
||||
snprintf(buf2,sizeof(buf2),"%.0f", (double)b);
|
||||
snprintf(buf2,sizeof(buf2),"%.0f", (double)b);
|
||||
n = buf2;
|
||||
break;
|
||||
case 'c':
|
||||
case 'c':
|
||||
if (!am_sender) {
|
||||
b = stats.total_written -
|
||||
b = stats.total_written -
|
||||
initial_stats->total_written;
|
||||
} else {
|
||||
b = stats.total_read -
|
||||
b = stats.total_read -
|
||||
initial_stats->total_read;
|
||||
}
|
||||
snprintf(buf2,sizeof(buf2),"%.0f", (double)b);
|
||||
snprintf(buf2,sizeof(buf2),"%.0f", (double)b);
|
||||
n = buf2;
|
||||
break;
|
||||
}
|
||||
@@ -453,6 +517,10 @@ static void log_formatted(enum logcode code,
|
||||
/* log the outgoing transfer of a file */
|
||||
void log_send(struct file_struct *file, struct stats *initial_stats)
|
||||
{
|
||||
extern int module_id;
|
||||
extern int am_server;
|
||||
extern char *log_format;
|
||||
|
||||
if (lp_transfer_logging(module_id)) {
|
||||
log_formatted(FLOG, lp_log_format(module_id), "send", file, initial_stats);
|
||||
} else if (log_format && !am_server) {
|
||||
@@ -463,6 +531,10 @@ void log_send(struct file_struct *file, struct stats *initial_stats)
|
||||
/* log the incoming transfer of a file */
|
||||
void log_recv(struct file_struct *file, struct stats *initial_stats)
|
||||
{
|
||||
extern int module_id;
|
||||
extern int am_server;
|
||||
extern char *log_format;
|
||||
|
||||
if (lp_transfer_logging(module_id)) {
|
||||
log_formatted(FLOG, lp_log_format(module_id), "recv", file, initial_stats);
|
||||
} else if (log_format && !am_server) {
|
||||
@@ -482,24 +554,33 @@ void log_recv(struct file_struct *file, struct stats *initial_stats)
|
||||
void log_exit(int code, const char *file, int line)
|
||||
{
|
||||
if (code == 0) {
|
||||
extern struct stats stats;
|
||||
rprintf(FLOG,"wrote %.0f bytes read %.0f bytes total size %.0f\n",
|
||||
(double)stats.total_written,
|
||||
(double)stats.total_read,
|
||||
(double)stats.total_size);
|
||||
} else {
|
||||
const char *name;
|
||||
const char *name;
|
||||
|
||||
name = rerr_name(code);
|
||||
if (!name)
|
||||
name = "unexplained error";
|
||||
|
||||
/* VANISHED is not an error, only a warning */
|
||||
if (code == RERR_VANISHED) {
|
||||
rprintf(FINFO, "rsync warning: %s (code %d) at %s(%d)\n",
|
||||
name, code, file, line);
|
||||
} else {
|
||||
rprintf(FERROR, "rsync error: %s (code %d) at %s(%d)\n",
|
||||
name, code, file, line);
|
||||
}
|
||||
name = rerr_name(code);
|
||||
if (!name)
|
||||
name = "unexplained error";
|
||||
|
||||
rprintf(FERROR,"rsync error: %s (code %d) at %s(%d)\n",
|
||||
name, code, file, line);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Log the incoming transfer of a file for interactive use,
|
||||
* this will be called at the end where the client was run.
|
||||
* Called when a file starts to be transferred.
|
||||
*/
|
||||
void log_transfer(struct file_struct *file, const char *fname)
|
||||
{
|
||||
extern int verbose;
|
||||
|
||||
if (!verbose) return;
|
||||
|
||||
rprintf(FINFO, "%s\n", fname);
|
||||
}
|
||||
|
||||
261
main.c
261
main.c
@@ -24,40 +24,14 @@
|
||||
time_t starttime = 0;
|
||||
|
||||
extern struct stats stats;
|
||||
extern int am_root;
|
||||
extern char *files_from;
|
||||
extern int filesfrom_fd;
|
||||
extern char *remote_filesfrom_file;
|
||||
extern int am_server;
|
||||
extern int am_sender;
|
||||
extern int am_generator;
|
||||
extern int am_daemon;
|
||||
extern int verbose;
|
||||
extern int blocking_io;
|
||||
extern int cvs_exclude;
|
||||
extern int delete_mode;
|
||||
extern int delete_excluded;
|
||||
extern int delete_after;
|
||||
extern int daemon_over_rsh;
|
||||
extern int do_stats;
|
||||
extern int dry_run;
|
||||
extern int list_only;
|
||||
extern int local_server;
|
||||
extern int log_got_error;
|
||||
extern int module_id;
|
||||
extern int orig_umask;
|
||||
extern int preserve_hard_links;
|
||||
extern int protocol_version;
|
||||
extern int recurse;
|
||||
extern int relative_paths;
|
||||
extern int rsync_port;
|
||||
extern int read_batch;
|
||||
extern int write_batch;
|
||||
extern int filesfrom_fd;
|
||||
extern pid_t cleanup_child_pid;
|
||||
extern char *files_from;
|
||||
extern char *remote_filesfrom_file;
|
||||
extern char *rsync_path;
|
||||
extern char *shell_cmd;
|
||||
extern struct file_list *batch_flist;
|
||||
|
||||
|
||||
/* there's probably never more than at most 2 outstanding child processes,
|
||||
* but set it higher just in case.
|
||||
@@ -81,7 +55,7 @@ void wait_process(pid_t pid, int *status)
|
||||
|
||||
while ((waited_pid = waitpid(pid, status, WNOHANG)) == 0) {
|
||||
msleep(20);
|
||||
io_flush(FULL_FLUSH);
|
||||
io_flush();
|
||||
}
|
||||
|
||||
if ((waited_pid == -1) && (errno == ECHILD)) {
|
||||
@@ -108,6 +82,8 @@ void wait_process(pid_t pid, int *status)
|
||||
static void report(int f)
|
||||
{
|
||||
time_t t = time(NULL);
|
||||
extern int do_stats;
|
||||
int send_stats;
|
||||
|
||||
if (do_stats && verbose > 1) {
|
||||
/* These come out from every process */
|
||||
@@ -115,16 +91,14 @@ static void report(int f)
|
||||
show_flist_stats();
|
||||
}
|
||||
|
||||
if (am_generator)
|
||||
return;
|
||||
|
||||
if (am_daemon) {
|
||||
log_exit(0, __FILE__, __LINE__);
|
||||
if (f == -1 || !am_sender) return;
|
||||
}
|
||||
|
||||
send_stats = verbose || protocol_version >= 20;
|
||||
if (am_server) {
|
||||
if (am_sender) {
|
||||
if (am_sender && send_stats) {
|
||||
int64 w;
|
||||
/* store total_written in a temporary
|
||||
* because write_longint changes it */
|
||||
@@ -138,7 +112,7 @@ static void report(int f)
|
||||
|
||||
/* this is the client */
|
||||
|
||||
if (!am_sender) {
|
||||
if (!am_sender && send_stats) {
|
||||
int64 r;
|
||||
stats.total_written = read_longint(f);
|
||||
/* store total_read in a temporary, read_longint changes it */
|
||||
@@ -148,6 +122,12 @@ static void report(int f)
|
||||
}
|
||||
|
||||
if (do_stats) {
|
||||
if (!am_sender && !send_stats) {
|
||||
/* missing the bytes written by the generator */
|
||||
rprintf(FINFO, "\nCannot show stats as receiver because remote protocol version is less than 20\n");
|
||||
rprintf(FINFO, "Use --stats -v to show stats\n");
|
||||
return;
|
||||
}
|
||||
rprintf(FINFO,"\nNumber of files: %d\n", stats.num_files);
|
||||
rprintf(FINFO,"Number of files transferred: %d\n",
|
||||
stats.num_transferred_files);
|
||||
@@ -191,18 +171,16 @@ static void show_malloc_stats(void)
|
||||
|
||||
mi = mallinfo();
|
||||
|
||||
rprintf(FINFO, "\n" RSYNC_NAME "[%d] (%s%s%s) heap statistics:\n",
|
||||
rprintf(FINFO, RSYNC_NAME "[%d] (%s%s%s) heap statistics:\n",
|
||||
getpid(),
|
||||
am_server ? "server " : "",
|
||||
am_daemon ? "daemon " : "",
|
||||
who_am_i());
|
||||
am_sender ? "sender" : "receiver");
|
||||
rprintf(FINFO, " arena: %10d (bytes from sbrk)\n", mi.arena);
|
||||
rprintf(FINFO, " ordblks: %10d (chunks not in use)\n", mi.ordblks);
|
||||
rprintf(FINFO, " smblks: %10d\n", mi.smblks);
|
||||
rprintf(FINFO, " hblks: %10d (chunks from mmap)\n", mi.hblks);
|
||||
rprintf(FINFO, " hblkhd: %10d (bytes from mmap)\n", mi.hblkhd);
|
||||
rprintf(FINFO, " allmem: %10d (bytes from sbrk + mmap)\n",
|
||||
mi.arena + mi.hblkhd);
|
||||
rprintf(FINFO, " usmblks: %10d\n", mi.usmblks);
|
||||
rprintf(FINFO, " fsmblks: %10d\n", mi.fsmblks);
|
||||
rprintf(FINFO, " uordblks: %10d (bytes used)\n", mi.uordblks);
|
||||
@@ -213,30 +191,34 @@ static void show_malloc_stats(void)
|
||||
|
||||
|
||||
/* Start the remote shell. cmd may be NULL to use the default. */
|
||||
static pid_t do_cmd(char *cmd, char *machine, char *user, char *path,
|
||||
int *f_in, int *f_out)
|
||||
static pid_t do_cmd(char *cmd,char *machine,char *user,char *path,int *f_in,int *f_out)
|
||||
{
|
||||
int i, argc = 0;
|
||||
char *args[100];
|
||||
int i,argc=0;
|
||||
pid_t ret;
|
||||
char *tok, *dir = NULL;
|
||||
char *tok,*dir=NULL;
|
||||
int dash_l_set = 0;
|
||||
extern int local_server;
|
||||
extern char *rsync_path;
|
||||
extern int blocking_io;
|
||||
extern int daemon_over_rsh;
|
||||
extern int read_batch;
|
||||
|
||||
if (!read_batch && !local_server) {
|
||||
char *rsh_env = getenv(RSYNC_RSH_ENV);
|
||||
if (!cmd)
|
||||
cmd = rsh_env;
|
||||
cmd = getenv(RSYNC_RSH_ENV);
|
||||
if (!cmd)
|
||||
cmd = RSYNC_RSH;
|
||||
cmd = strdup(cmd);
|
||||
if (!cmd)
|
||||
goto oom;
|
||||
|
||||
for (tok = strtok(cmd, " "); tok; tok = strtok(NULL, " "))
|
||||
for (tok=strtok(cmd," ");tok;tok=strtok(NULL," ")) {
|
||||
args[argc++] = tok;
|
||||
}
|
||||
|
||||
/* check to see if we've already been given '-l user' in
|
||||
* the remote-shell command */
|
||||
the remote-shell command */
|
||||
for (i = 0; i < argc-1; i++) {
|
||||
if (!strcmp(args[i], "-l") && args[i+1][0] != '-')
|
||||
dash_l_set = 1;
|
||||
@@ -259,17 +241,11 @@ static pid_t do_cmd(char *cmd, char *machine, char *user, char *path,
|
||||
|
||||
args[argc++] = rsync_path;
|
||||
|
||||
if (blocking_io < 0) {
|
||||
char *cp;
|
||||
if ((cp = strrchr(cmd, '/')) != NULL)
|
||||
cp++;
|
||||
else
|
||||
cp = cmd;
|
||||
if (strcmp(cp, "rsh") == 0 || strcmp(cp, "remsh") == 0)
|
||||
blocking_io = 1;
|
||||
}
|
||||
if ((blocking_io == -1) && (strcmp(cmd, RSYNC_RSH) == 0))
|
||||
blocking_io = 1;
|
||||
|
||||
server_options(args,&argc);
|
||||
|
||||
}
|
||||
|
||||
args[argc++] = ".";
|
||||
@@ -277,11 +253,6 @@ static pid_t do_cmd(char *cmd, char *machine, char *user, char *path,
|
||||
if (!daemon_over_rsh && path && *path)
|
||||
args[argc++] = path;
|
||||
|
||||
if (argc >= (int)(sizeof args / sizeof args[0])) {
|
||||
rprintf(FERROR, "internal: args[] overflowed in do_cmd()\n");
|
||||
exit_cleanup(RERR_MALLOC); /* XXX Need better RERR? */
|
||||
}
|
||||
|
||||
args[argc] = NULL;
|
||||
|
||||
if (verbose > 3) {
|
||||
@@ -309,10 +280,13 @@ oom:
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static char *get_local_name(struct file_list *flist,char *name)
|
||||
{
|
||||
STRUCT_STAT st;
|
||||
int e;
|
||||
extern int orig_umask;
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"get_local_name count=%d %s\n",
|
||||
@@ -323,7 +297,7 @@ static char *get_local_name(struct file_list *flist,char *name)
|
||||
|
||||
if (do_stat(name,&st) == 0) {
|
||||
if (S_ISDIR(st.st_mode)) {
|
||||
if (!push_dir(name)) {
|
||||
if (!push_dir(name, 0)) {
|
||||
rprintf(FERROR, "push_dir %s failed: %s (1)\n",
|
||||
full_fname(name), strerror(errno));
|
||||
exit_cleanup(RERR_FILESELECT);
|
||||
@@ -349,7 +323,7 @@ static char *get_local_name(struct file_list *flist,char *name)
|
||||
rprintf(FINFO,"created directory %s\n",name);
|
||||
}
|
||||
|
||||
if (!push_dir(name)) {
|
||||
if (!push_dir(name, 0)) {
|
||||
rprintf(FERROR, "push_dir %s failed: %s (2)\n",
|
||||
full_fname(name), strerror(errno));
|
||||
exit_cleanup(RERR_FILESELECT);
|
||||
@@ -359,18 +333,20 @@ static char *get_local_name(struct file_list *flist,char *name)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void do_server_sender(int f_in, int f_out, int argc,char *argv[])
|
||||
{
|
||||
int i;
|
||||
struct file_list *flist;
|
||||
char *dir = argv[0];
|
||||
extern int relative_paths;
|
||||
extern int recurse;
|
||||
|
||||
if (verbose > 2) {
|
||||
rprintf(FINFO, "server_sender starting pid=%ld\n",
|
||||
(long)getpid());
|
||||
}
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"server_sender starting pid=%d\n",(int)getpid());
|
||||
|
||||
if (!relative_paths && !push_dir(dir)) {
|
||||
if (!relative_paths && !push_dir(dir, 0)) {
|
||||
rprintf(FERROR, "push_dir %s failed: %s (3)\n",
|
||||
full_fname(dir), strerror(errno));
|
||||
exit_cleanup(RERR_FILESELECT);
|
||||
@@ -397,16 +373,14 @@ static void do_server_sender(int f_in, int f_out, int argc,char *argv[])
|
||||
exit_cleanup(0);
|
||||
}
|
||||
|
||||
io_start_buffering_in(f_in);
|
||||
io_start_buffering_out(f_out);
|
||||
send_files(flist,f_out,f_in);
|
||||
io_flush(FULL_FLUSH);
|
||||
io_flush();
|
||||
report(f_out);
|
||||
if (protocol_version >= 24) {
|
||||
/* final goodbye message */
|
||||
read_int(f_in);
|
||||
}
|
||||
io_flush(FULL_FLUSH);
|
||||
read_int(f_in);
|
||||
}
|
||||
io_flush();
|
||||
exit_cleanup(0);
|
||||
}
|
||||
|
||||
@@ -415,7 +389,12 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
|
||||
{
|
||||
int pid;
|
||||
int status=0;
|
||||
int recv_pipe[2];
|
||||
int error_pipe[2];
|
||||
extern int preserve_hard_links;
|
||||
extern int delete_after;
|
||||
extern int recurse;
|
||||
extern int delete_mode;
|
||||
|
||||
if (preserve_hard_links)
|
||||
init_hard_links(flist);
|
||||
@@ -427,14 +406,20 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
|
||||
}
|
||||
}
|
||||
|
||||
if (fd_pair(recv_pipe) < 0) {
|
||||
rprintf(FERROR,"pipe failed in do_recv\n");
|
||||
exit_cleanup(RERR_SOCKETIO);
|
||||
}
|
||||
|
||||
if (fd_pair(error_pipe) < 0) {
|
||||
rprintf(FERROR,"error pipe failed in do_recv\n");
|
||||
exit_cleanup(RERR_SOCKETIO);
|
||||
}
|
||||
|
||||
io_flush(NORMAL_FLUSH);
|
||||
io_flush();
|
||||
|
||||
if ((pid=do_fork()) == 0) {
|
||||
close(recv_pipe[0]);
|
||||
close(error_pipe[0]);
|
||||
if (f_in != f_out) close(f_out);
|
||||
|
||||
@@ -442,42 +427,41 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
|
||||
io_multiplexing_close();
|
||||
|
||||
/* set place to send errors */
|
||||
set_msg_fd_out(error_pipe[1]);
|
||||
set_error_fd(error_pipe[1]);
|
||||
|
||||
recv_files(f_in,flist,local_name);
|
||||
io_flush(FULL_FLUSH);
|
||||
recv_files(f_in,flist,local_name,recv_pipe[1]);
|
||||
io_flush();
|
||||
report(f_in);
|
||||
|
||||
send_msg(MSG_DONE, "", 0);
|
||||
io_flush(FULL_FLUSH);
|
||||
write_int(recv_pipe[1],1);
|
||||
close(recv_pipe[1]);
|
||||
io_flush();
|
||||
/* finally we go to sleep until our parent kills us
|
||||
* with a USR2 signal. We sleep for a short time as on
|
||||
* some OSes a signal won't interrupt a sleep! */
|
||||
while (1)
|
||||
msleep(20);
|
||||
with a USR2 signal. We sleep for a short time as on
|
||||
some OSes a signal won't interrupt a sleep! */
|
||||
while (msleep(20))
|
||||
;
|
||||
}
|
||||
|
||||
am_generator = 1;
|
||||
|
||||
close(recv_pipe[1]);
|
||||
close(error_pipe[1]);
|
||||
if (f_in != f_out) close(f_in);
|
||||
|
||||
io_start_buffering_out(f_out);
|
||||
io_start_buffering(f_out);
|
||||
|
||||
set_msg_fd_in(error_pipe[0]);
|
||||
io_set_error_fd(error_pipe[0]);
|
||||
|
||||
generate_files(f_out, flist, local_name);
|
||||
generate_files(f_out,flist,local_name,recv_pipe[0]);
|
||||
|
||||
get_redo_num(); /* Read final MSG_DONE and any prior messages. */
|
||||
report(-1);
|
||||
io_flush(FULL_FLUSH);
|
||||
read_int(recv_pipe[0]);
|
||||
close(recv_pipe[0]);
|
||||
if (protocol_version >= 24) {
|
||||
/* send a final goodbye message */
|
||||
write_int(f_out, -1);
|
||||
}
|
||||
io_flush(FULL_FLUSH);
|
||||
io_flush();
|
||||
|
||||
set_msg_fd_in(-1);
|
||||
io_set_error_fd(-1);
|
||||
kill(pid, SIGUSR2);
|
||||
wait_process(pid, &status);
|
||||
return status;
|
||||
@@ -488,13 +472,16 @@ static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
|
||||
{
|
||||
int status;
|
||||
struct file_list *flist;
|
||||
char *local_name = NULL;
|
||||
char *local_name=NULL;
|
||||
char *dir = NULL;
|
||||
extern int delete_mode;
|
||||
extern int delete_excluded;
|
||||
extern int module_id;
|
||||
extern int read_batch;
|
||||
extern struct file_list *batch_flist;
|
||||
|
||||
if (verbose > 2) {
|
||||
rprintf(FINFO, "server_recv(%d) starting pid=%ld\n",
|
||||
argc, (long)getpid());
|
||||
}
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"server_recv(%d) starting pid=%d\n",argc,(int)getpid());
|
||||
|
||||
if (am_daemon && lp_read_only(module_id) && !am_sender) {
|
||||
rprintf(FERROR,"ERROR: module is read only\n");
|
||||
@@ -507,14 +494,13 @@ static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
|
||||
dir = argv[0];
|
||||
argc--;
|
||||
argv++;
|
||||
if (!am_daemon && !push_dir(dir)) {
|
||||
if (!am_daemon && !push_dir(dir, 0)) {
|
||||
rprintf(FERROR, "push_dir %s failed: %s (4)\n",
|
||||
full_fname(dir), strerror(errno));
|
||||
exit_cleanup(RERR_FILESELECT);
|
||||
}
|
||||
}
|
||||
|
||||
io_start_buffering_in(f_in);
|
||||
if (delete_mode && !delete_excluded)
|
||||
recv_exclude_list(f_in);
|
||||
|
||||
@@ -558,6 +544,9 @@ int child_main(int argc, char *argv[])
|
||||
|
||||
void start_server(int f_in, int f_out, int argc, char *argv[])
|
||||
{
|
||||
extern int cvs_exclude;
|
||||
extern int read_batch;
|
||||
|
||||
setup_protocol(f_out, f_in);
|
||||
|
||||
set_nonblocking(f_in);
|
||||
@@ -589,6 +578,10 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
|
||||
struct file_list *flist = NULL;
|
||||
int status = 0, status2 = 0;
|
||||
char *local_name = NULL;
|
||||
extern pid_t cleanup_child_pid;
|
||||
extern int write_batch;
|
||||
extern int read_batch;
|
||||
extern struct file_list *batch_flist;
|
||||
|
||||
cleanup_child_pid = pid;
|
||||
if (read_batch)
|
||||
@@ -603,21 +596,21 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
|
||||
io_start_multiplex_in(f_in);
|
||||
|
||||
if (am_sender) {
|
||||
io_start_buffering_out(f_out);
|
||||
extern int cvs_exclude;
|
||||
extern int delete_mode;
|
||||
extern int delete_excluded;
|
||||
if (cvs_exclude)
|
||||
add_cvs_excludes();
|
||||
if (delete_mode && !delete_excluded)
|
||||
send_exclude_list(f_out);
|
||||
if (remote_filesfrom_file)
|
||||
filesfrom_fd = f_in;
|
||||
if (!read_batch) /* don't write to pipe */
|
||||
if (!read_batch) /* dw -- don't write to pipe */
|
||||
flist = send_file_list(f_out,argc,argv);
|
||||
if (verbose > 3)
|
||||
rprintf(FINFO,"file list sent\n");
|
||||
|
||||
io_flush(NORMAL_FLUSH);
|
||||
send_files(flist,f_out,f_in);
|
||||
io_flush(FULL_FLUSH);
|
||||
if (protocol_version >= 24) {
|
||||
/* final goodbye message */
|
||||
read_int(f_in);
|
||||
@@ -625,15 +618,15 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
|
||||
if (pid != -1) {
|
||||
if (verbose > 3)
|
||||
rprintf(FINFO,"client_run waiting on %d\n", (int) pid);
|
||||
io_flush(FULL_FLUSH);
|
||||
io_flush();
|
||||
wait_process(pid, &status);
|
||||
}
|
||||
report(-1);
|
||||
io_flush(FULL_FLUSH);
|
||||
exit_cleanup(status);
|
||||
}
|
||||
|
||||
if (argc == 0) {
|
||||
extern int list_only;
|
||||
list_only = 1;
|
||||
}
|
||||
|
||||
@@ -660,7 +653,7 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
|
||||
if (pid != -1) {
|
||||
if (verbose > 3)
|
||||
rprintf(FINFO,"client_run2 waiting on %d\n", (int) pid);
|
||||
io_flush(FULL_FLUSH);
|
||||
io_flush();
|
||||
wait_process(pid, &status);
|
||||
}
|
||||
|
||||
@@ -700,6 +693,11 @@ static int start_client(int argc, char *argv[])
|
||||
int ret;
|
||||
pid_t pid;
|
||||
int f_in,f_out;
|
||||
extern int local_server;
|
||||
extern char *shell_cmd;
|
||||
extern int rsync_port;
|
||||
extern int daemon_over_rsh;
|
||||
extern int read_batch;
|
||||
int rc;
|
||||
|
||||
/* Don't clobber argv[] so that ps(1) can still show the right
|
||||
@@ -828,7 +826,7 @@ static int start_client(int argc, char *argv[])
|
||||
}
|
||||
|
||||
if (shell_machine) {
|
||||
p = strrchr(shell_machine,'@');
|
||||
p = strchr(shell_machine,'@');
|
||||
if (p) {
|
||||
*p = 0;
|
||||
shell_user = shell_machine;
|
||||
@@ -850,6 +848,7 @@ static int start_client(int argc, char *argv[])
|
||||
}
|
||||
|
||||
if (argc == 0 && !am_sender) {
|
||||
extern int list_only;
|
||||
list_only = 1;
|
||||
}
|
||||
|
||||
@@ -857,7 +856,7 @@ static int start_client(int argc, char *argv[])
|
||||
&f_in,&f_out);
|
||||
|
||||
/* if we're running an rsync server on the remote host over a
|
||||
* remote shell command, we need to do the RSYNCD protocol first */
|
||||
remote shell command, we need to do the RSYNCD protocol first */
|
||||
if (daemon_over_rsh) {
|
||||
int tmpret;
|
||||
tmpret = start_inband_exchange(shell_user, shell_path,
|
||||
@@ -882,6 +881,7 @@ static RETSIGTYPE sigusr1_handler(UNUSED(int val))
|
||||
|
||||
static RETSIGTYPE sigusr2_handler(UNUSED(int val))
|
||||
{
|
||||
extern int log_got_error;
|
||||
if (log_got_error) _exit(RERR_PARTIAL);
|
||||
_exit(0);
|
||||
}
|
||||
@@ -898,14 +898,14 @@ static RETSIGTYPE sigchld_handler(UNUSED(int val))
|
||||
* zombie children, maybe that's why he did it.
|
||||
*/
|
||||
while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
|
||||
/* save the child's exit status */
|
||||
for (cnt = 0; cnt < MAXCHILDPROCS; cnt++) {
|
||||
if (pid_stat_table[cnt].pid == 0) {
|
||||
pid_stat_table[cnt].pid = pid;
|
||||
pid_stat_table[cnt].status = status;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* save the child's exit status */
|
||||
for (cnt = 0; cnt < MAXCHILDPROCS; cnt++) {
|
||||
if (pid_stat_table[cnt].pid == 0) {
|
||||
pid_stat_table[cnt].pid = pid;
|
||||
pid_stat_table[cnt].status = status;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -964,7 +964,11 @@ static RETSIGTYPE rsync_panic_handler(UNUSED(int whatsig))
|
||||
|
||||
int main(int argc,char *argv[])
|
||||
{
|
||||
extern int am_root;
|
||||
extern int orig_umask;
|
||||
extern int dry_run;
|
||||
int ret;
|
||||
extern int write_batch;
|
||||
int orig_argc;
|
||||
char **orig_argv;
|
||||
|
||||
@@ -982,7 +986,7 @@ int main(int argc,char *argv[])
|
||||
#endif /* def MAINTAINER_MODE */
|
||||
|
||||
starttime = time(NULL);
|
||||
am_root = (MY_UID() == 0);
|
||||
am_root = (getuid() == 0);
|
||||
|
||||
memset(&stats, 0, sizeof(stats));
|
||||
|
||||
@@ -992,7 +996,7 @@ int main(int argc,char *argv[])
|
||||
}
|
||||
|
||||
/* we set a 0 umask so that correct file permissions can be
|
||||
* carried across */
|
||||
carried across */
|
||||
orig_umask = (int)umask(0);
|
||||
|
||||
if (!parse_arguments(&argc, (const char ***) &argv, 1)) {
|
||||
@@ -1011,12 +1015,10 @@ int main(int argc,char *argv[])
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
|
||||
/* Initialize push_dir here because on some old systems getcwd
|
||||
* (implemented by forking "pwd" and reading its output) doesn't
|
||||
* work when there are other child processes. Also, on all systems
|
||||
* that implement getcwd that way "pwd" can't be found after chroot. */
|
||||
push_dir(NULL);
|
||||
|
||||
init_flist();
|
||||
(implemented by forking "pwd" and reading its output) doesn't
|
||||
work when there are other child processes. Also, on all systems
|
||||
that implement getcwd that way "pwd" can't be found after chroot. */
|
||||
push_dir(NULL,0);
|
||||
|
||||
if (write_batch && !am_server) {
|
||||
write_batch_argvs_file(orig_argc, orig_argv);
|
||||
@@ -1033,6 +1035,13 @@ int main(int argc,char *argv[])
|
||||
if (dry_run)
|
||||
verbose = MAX(verbose,1);
|
||||
|
||||
#ifndef SUPPORT_LINKS
|
||||
if (!am_server && preserve_links) {
|
||||
rprintf(FERROR,"ERROR: symbolic links not supported\n");
|
||||
exit_cleanup(RERR_UNSUPPORTED);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (am_server) {
|
||||
set_nonblocking(STDIN_FILENO);
|
||||
set_nonblocking(STDOUT_FILENO);
|
||||
|
||||
219
match.c
219
match.c
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
/*
|
||||
Copyright (C) Andrew Tridgell 1996
|
||||
Copyright (C) Paul Mackerras 1996
|
||||
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
@@ -19,14 +19,17 @@
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
extern int csum_length;
|
||||
|
||||
extern int verbose;
|
||||
extern int am_server;
|
||||
extern int do_progress;
|
||||
|
||||
extern int remote_version;
|
||||
|
||||
typedef unsigned short tag;
|
||||
|
||||
#define TABLESIZE (1<<16)
|
||||
#define NULL_TAG ((size_t)-1)
|
||||
#define NULL_TAG (-1)
|
||||
|
||||
static int false_alarms;
|
||||
static int tag_hits;
|
||||
@@ -40,46 +43,47 @@ static int total_matches;
|
||||
extern struct stats stats;
|
||||
|
||||
struct target {
|
||||
tag t;
|
||||
size_t i;
|
||||
tag t;
|
||||
int i;
|
||||
};
|
||||
|
||||
static struct target *targets;
|
||||
|
||||
static size_t *tag_table;
|
||||
static int *tag_table;
|
||||
|
||||
#define gettag2(s1,s2) (((s1) + (s2)) & 0xFFFF)
|
||||
#define gettag(sum) gettag2((sum)&0xFFFF,(sum)>>16)
|
||||
|
||||
static int compare_targets(struct target *t1,struct target *t2)
|
||||
{
|
||||
return (int)t1->t - (int)t2->t;
|
||||
return((int)t1->t - (int)t2->t);
|
||||
}
|
||||
|
||||
|
||||
static void build_hash_table(struct sum_struct *s)
|
||||
{
|
||||
size_t i;
|
||||
int i;
|
||||
|
||||
if (!tag_table)
|
||||
tag_table = new_array(size_t, TABLESIZE);
|
||||
if (!tag_table)
|
||||
tag_table = new_array(int, TABLESIZE);
|
||||
|
||||
targets = new_array(struct target, s->count);
|
||||
if (!tag_table || !targets)
|
||||
out_of_memory("build_hash_table");
|
||||
targets = new_array(struct target, s->count);
|
||||
if (!tag_table || !targets)
|
||||
out_of_memory("build_hash_table");
|
||||
|
||||
for (i = 0; i < s->count; i++) {
|
||||
targets[i].i = i;
|
||||
targets[i].t = gettag(s->sums[i].sum1);
|
||||
}
|
||||
for (i=0;i<(int) s->count;i++) {
|
||||
targets[i].i = i;
|
||||
targets[i].t = gettag(s->sums[i].sum1);
|
||||
}
|
||||
|
||||
qsort(targets,s->count,sizeof(targets[0]),(int (*)())compare_targets);
|
||||
qsort(targets,s->count,sizeof(targets[0]),(int (*)())compare_targets);
|
||||
|
||||
for (i = 0; i < TABLESIZE; i++)
|
||||
tag_table[i] = NULL_TAG;
|
||||
for (i=0;i<TABLESIZE;i++)
|
||||
tag_table[i] = NULL_TAG;
|
||||
|
||||
for (i = s->count; i-- > 0; )
|
||||
tag_table[targets[i].t] = i;
|
||||
for (i=s->count-1;i>=0;i--) {
|
||||
tag_table[targets[i].t] = i;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -105,7 +109,7 @@ static void matched(int f,struct sum_struct *s,struct map_struct *buf,
|
||||
OFF_T j;
|
||||
|
||||
if (verbose > 2 && i >= 0)
|
||||
rprintf(FINFO,"match at %.0f last_match=%.0f j=%d len=%u n=%.0f\n",
|
||||
rprintf(FINFO,"match at %.0f last_match=%.0f j=%d len=%d n=%.0f\n",
|
||||
(double)offset,(double)last_match,i,s->sums[i].len,(double)n);
|
||||
|
||||
send_token(f,i,buf,last_match,n,i<0?0:s->sums[i].len);
|
||||
@@ -115,8 +119,8 @@ static void matched(int f,struct sum_struct *s,struct map_struct *buf,
|
||||
stats.matched_data += s->sums[i].len;
|
||||
n += s->sums[i].len;
|
||||
}
|
||||
|
||||
for (j = 0; j < n; j += CHUNK_SIZE) {
|
||||
|
||||
for (j=0;j<n;j+=CHUNK_SIZE) {
|
||||
int n1 = MIN(CHUNK_SIZE,n-j);
|
||||
sum_update(map_ptr(buf,last_match+j,n1),n1);
|
||||
}
|
||||
@@ -127,134 +131,129 @@ static void matched(int f,struct sum_struct *s,struct map_struct *buf,
|
||||
else
|
||||
last_match = offset;
|
||||
|
||||
if (buf && do_progress) {
|
||||
if (buf) {
|
||||
show_progress(last_match, buf->file_size);
|
||||
|
||||
if (i == -1)
|
||||
end_progress(buf->file_size);
|
||||
if (i == -1) end_progress(buf->file_size);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void hash_search(int f,struct sum_struct *s,
|
||||
struct map_struct *buf, OFF_T len)
|
||||
struct map_struct *buf,OFF_T len)
|
||||
{
|
||||
OFF_T offset, end;
|
||||
unsigned int k;
|
||||
size_t last_i;
|
||||
int j,k, last_i;
|
||||
char sum2[SUM_LENGTH];
|
||||
uint32 s1, s2, sum;
|
||||
uint32 s1, s2, sum;
|
||||
schar *map;
|
||||
|
||||
/* last_i is used to encourage adjacent matches, allowing the RLL coding of the
|
||||
output to work more efficiently */
|
||||
last_i = (size_t)-1;
|
||||
last_i = -1;
|
||||
|
||||
if (verbose > 2) {
|
||||
rprintf(FINFO,"hash search b=%u len=%.0f\n",
|
||||
s->blength, (double)len);
|
||||
}
|
||||
|
||||
k = MIN(len, s->blength);
|
||||
|
||||
map = (schar *)map_ptr(buf, 0, k);
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"hash search b=%ld len=%.0f\n",
|
||||
(long) s->n, (double)len);
|
||||
|
||||
/* cast is to make s->n signed; it should always be reasonably
|
||||
* small */
|
||||
k = MIN(len, (OFF_T) s->n);
|
||||
|
||||
map = (schar *)map_ptr(buf,0,k);
|
||||
|
||||
sum = get_checksum1((char *)map, k);
|
||||
s1 = sum & 0xFFFF;
|
||||
s2 = sum >> 16;
|
||||
if (verbose > 3)
|
||||
rprintf(FINFO, "sum=%.8x k=%u\n", sum, k);
|
||||
|
||||
rprintf(FINFO, "sum=%.8x k=%d\n", sum, k);
|
||||
|
||||
offset = 0;
|
||||
|
||||
|
||||
end = len + 1 - s->sums[s->count-1].len;
|
||||
|
||||
if (verbose > 3) {
|
||||
rprintf(FINFO, "hash search s->blength=%u len=%.0f count=%.0f\n",
|
||||
s->blength, (double)len, (double)s->count);
|
||||
}
|
||||
|
||||
|
||||
if (verbose > 3)
|
||||
rprintf(FINFO, "hash search s->n=%ld len=%.0f count=%ld\n",
|
||||
(long) s->n, (double) len, (long) s->count);
|
||||
|
||||
do {
|
||||
tag t = gettag2(s1,s2);
|
||||
int done_csum2 = 0;
|
||||
size_t j = tag_table[t];
|
||||
|
||||
|
||||
j = tag_table[t];
|
||||
if (verbose > 4)
|
||||
rprintf(FINFO,"offset=%.0f sum=%08x\n",(double)offset,sum);
|
||||
|
||||
if (j == NULL_TAG)
|
||||
|
||||
if (j == NULL_TAG) {
|
||||
goto null_tag;
|
||||
}
|
||||
|
||||
sum = (s1 & 0xffff) | (s2 << 16);
|
||||
tag_hits++;
|
||||
for (; j < s->count && targets[j].t == t; j++) {
|
||||
unsigned int l;
|
||||
size_t i = targets[j].i;
|
||||
|
||||
if (sum != s->sums[i].sum1)
|
||||
continue;
|
||||
|
||||
for (; j < (int) s->count && targets[j].t == t; j++) {
|
||||
int l, i = targets[j].i;
|
||||
|
||||
if (sum != s->sums[i].sum1) continue;
|
||||
|
||||
/* also make sure the two blocks are the same length */
|
||||
l = MIN((OFF_T)s->blength, len-offset);
|
||||
if (l != s->sums[i].len)
|
||||
continue;
|
||||
l = MIN(s->n,len-offset);
|
||||
if (l != s->sums[i].len) continue;
|
||||
|
||||
if (verbose > 3)
|
||||
rprintf(FINFO,"potential match at %.0f target=%.0f %.0f sum=%08x\n",
|
||||
(double)offset,(double)j,(double)i,sum);
|
||||
|
||||
rprintf(FINFO,"potential match at %.0f target=%d %d sum=%08x\n",
|
||||
(double)offset,j,i,sum);
|
||||
|
||||
if (!done_csum2) {
|
||||
map = (schar *)map_ptr(buf,offset,l);
|
||||
get_checksum2((char *)map,l,sum2);
|
||||
done_csum2 = 1;
|
||||
}
|
||||
|
||||
if (memcmp(sum2,s->sums[i].sum2,s->s2length) != 0) {
|
||||
|
||||
if (memcmp(sum2,s->sums[i].sum2,csum_length) != 0) {
|
||||
false_alarms++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* we've found a match, but now check to see
|
||||
* if last_i can hint at a better match */
|
||||
for (j++; j < s->count && targets[j].t == t; j++) {
|
||||
size_t i2 = targets[j].i;
|
||||
if last_i can hint at a better match */
|
||||
for (j++; j < (int) s->count && targets[j].t == t; j++) {
|
||||
int i2 = targets[j].i;
|
||||
if (i2 == last_i + 1) {
|
||||
if (sum != s->sums[i2].sum1)
|
||||
break;
|
||||
if (memcmp(sum2,s->sums[i2].sum2,s->s2length) != 0)
|
||||
break;
|
||||
/* we've found an adjacent match - the RLL coder
|
||||
* will be happy */
|
||||
if (sum != s->sums[i2].sum1) break;
|
||||
if (memcmp(sum2,s->sums[i2].sum2,csum_length) != 0) break;
|
||||
/* we've found an adjacent match - the RLL coder
|
||||
will be happy */
|
||||
i = i2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
last_i = i;
|
||||
|
||||
|
||||
matched(f,s,buf,offset,i);
|
||||
offset += s->sums[i].len - 1;
|
||||
k = MIN(s->blength, len-offset);
|
||||
map = (schar *)map_ptr(buf, offset, k);
|
||||
k = MIN((len-offset), s->n);
|
||||
map = (schar *)map_ptr(buf,offset,k);
|
||||
sum = get_checksum1((char *)map, k);
|
||||
s1 = sum & 0xFFFF;
|
||||
s2 = sum >> 16;
|
||||
matches++;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
null_tag:
|
||||
/* Trim off the first byte from the checksum */
|
||||
map = (schar *)map_ptr(buf, offset, k+1);
|
||||
map = (schar *)map_ptr(buf,offset,k+1);
|
||||
s1 -= map[0] + CHAR_OFFSET;
|
||||
s2 -= k * (map[0]+CHAR_OFFSET);
|
||||
|
||||
|
||||
/* Add on the next byte (if there is one) to the checksum */
|
||||
if (k < (len-offset)) {
|
||||
s1 += (map[k]+CHAR_OFFSET);
|
||||
s2 += s1;
|
||||
} else
|
||||
} else {
|
||||
--k;
|
||||
}
|
||||
|
||||
/* By matching early we avoid re-reading the
|
||||
data 3 times in the case where a token
|
||||
@@ -262,13 +261,13 @@ static void hash_search(int f,struct sum_struct *s,
|
||||
match. The 3 reads are caused by the
|
||||
running match, the checksum update and the
|
||||
literal send. */
|
||||
if (offset > last_match
|
||||
&& offset-last_match >= CHUNK_SIZE+s->blength
|
||||
&& end-offset > CHUNK_SIZE) {
|
||||
matched(f,s,buf,offset - s->blength, -2);
|
||||
if (offset > last_match &&
|
||||
offset-last_match >= CHUNK_SIZE+s->n &&
|
||||
(end-offset > CHUNK_SIZE)) {
|
||||
matched(f,s,buf,offset - s->n, -2);
|
||||
}
|
||||
} while (++offset < end);
|
||||
|
||||
|
||||
matched(f,s,buf,len,-1);
|
||||
map_ptr(buf,len-1,1);
|
||||
}
|
||||
@@ -291,30 +290,30 @@ static void hash_search(int f,struct sum_struct *s,
|
||||
void match_sums(int f, struct sum_struct *s, struct map_struct *buf, OFF_T len)
|
||||
{
|
||||
char file_sum[MD4_SUM_LENGTH];
|
||||
extern int write_batch;
|
||||
extern int write_batch; /* dw */
|
||||
|
||||
last_match = 0;
|
||||
false_alarms = 0;
|
||||
tag_hits = 0;
|
||||
matches = 0;
|
||||
data_transfer = 0;
|
||||
matches=0;
|
||||
data_transfer=0;
|
||||
|
||||
sum_init();
|
||||
|
||||
if (len > 0 && s->count>0) {
|
||||
build_hash_table(s);
|
||||
|
||||
if (verbose > 2)
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"built hash table\n");
|
||||
|
||||
|
||||
hash_search(f,s,buf,len);
|
||||
|
||||
if (verbose > 2)
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"done hash search\n");
|
||||
} else {
|
||||
OFF_T j;
|
||||
/* by doing this in pieces we avoid too many seeks */
|
||||
for (j = 0; j < len-CHUNK_SIZE; j += CHUNK_SIZE) {
|
||||
for (j=0;j<(len-CHUNK_SIZE);j+=CHUNK_SIZE) {
|
||||
int n1 = MIN(CHUNK_SIZE,(len-CHUNK_SIZE)-j);
|
||||
matched(f,s,buf,j+n1,-2);
|
||||
}
|
||||
@@ -323,21 +322,23 @@ void match_sums(int f, struct sum_struct *s, struct map_struct *buf, OFF_T len)
|
||||
|
||||
sum_end(file_sum);
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"sending file_sum\n");
|
||||
write_buf(f,file_sum,MD4_SUM_LENGTH);
|
||||
if (write_batch)
|
||||
write_batch_delta_file(file_sum, MD4_SUM_LENGTH);
|
||||
if (remote_version >= 14) {
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"sending file_sum\n");
|
||||
write_buf(f,file_sum,MD4_SUM_LENGTH);
|
||||
if (write_batch) /* dw */
|
||||
write_batch_delta_file(file_sum, MD4_SUM_LENGTH);
|
||||
}
|
||||
|
||||
if (targets) {
|
||||
free(targets);
|
||||
targets=NULL;
|
||||
}
|
||||
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO, "false_alarms=%d tag_hits=%d matches=%d\n",
|
||||
false_alarms, tag_hits, matches);
|
||||
|
||||
|
||||
total_tag_hits += tag_hits;
|
||||
total_false_alarms += false_alarms;
|
||||
total_matches += matches;
|
||||
|
||||
@@ -58,7 +58,7 @@ BEGIN {
|
||||
next;
|
||||
}
|
||||
|
||||
!/^OFF_T|^size_t|^off_t|^pid_t|^unsigned|^mode_t|^DIR|^user|^int|^char|^uint|^struct|^BOOL|^void|^time|^const/ {
|
||||
!/^OFF_T|^size_t|^off_t|^pid_t|^unsigned|^mode_t|^DIR|^user|^int|^char|^uint|^struct|^BOOL|^void|^time/ {
|
||||
next;
|
||||
}
|
||||
|
||||
|
||||
402
options.c
402
options.c
@@ -21,9 +21,7 @@
|
||||
#include "rsync.h"
|
||||
#include "popt.h"
|
||||
|
||||
extern int sanitize_paths;
|
||||
extern char curr_dir[MAXPATHLEN];
|
||||
extern struct exclude_list_struct exclude_list;
|
||||
extern struct exclude_struct **exclude_list;
|
||||
|
||||
int make_backups = 0;
|
||||
|
||||
@@ -48,27 +46,27 @@ int preserve_gid = 0;
|
||||
int preserve_times = 0;
|
||||
int update_only = 0;
|
||||
int cvs_exclude = 0;
|
||||
int dry_run = 0;
|
||||
int local_server = 0;
|
||||
int ignore_times = 0;
|
||||
int delete_mode = 0;
|
||||
int delete_excluded = 0;
|
||||
int one_file_system = 0;
|
||||
int dry_run=0;
|
||||
int local_server=0;
|
||||
int ignore_times=0;
|
||||
int delete_mode=0;
|
||||
int delete_excluded=0;
|
||||
int one_file_system=0;
|
||||
int protocol_version = PROTOCOL_VERSION;
|
||||
int sparse_files = 0;
|
||||
int do_compression = 0;
|
||||
int am_root = 0;
|
||||
int orig_umask = 0;
|
||||
int sparse_files=0;
|
||||
int do_compression=0;
|
||||
int am_root=0;
|
||||
int orig_umask=0;
|
||||
int relative_paths = -1;
|
||||
int implied_dirs = 1;
|
||||
int numeric_ids = 0;
|
||||
int force_delete = 0;
|
||||
int io_timeout = 0;
|
||||
int io_error = 0;
|
||||
int read_only = 0;
|
||||
int module_id = -1;
|
||||
int am_server = 0;
|
||||
int am_sender = 0;
|
||||
int am_generator = 0;
|
||||
char *files_from = NULL;
|
||||
int filesfrom_fd = -1;
|
||||
char *remote_filesfrom_file = NULL;
|
||||
@@ -76,22 +74,21 @@ int eol_nulls = 0;
|
||||
int recurse = 0;
|
||||
int am_daemon = 0;
|
||||
int daemon_over_rsh = 0;
|
||||
int do_stats = 0;
|
||||
int do_progress = 0;
|
||||
int keep_partial = 0;
|
||||
int safe_symlinks = 0;
|
||||
int copy_unsafe_links = 0;
|
||||
int size_only = 0;
|
||||
int bwlimit = 0;
|
||||
int delete_after = 0;
|
||||
int only_existing = 0;
|
||||
int opt_ignore_existing = 0;
|
||||
int max_delete = 0;
|
||||
int ignore_errors = 0;
|
||||
int modify_window = 0;
|
||||
int blocking_io = -1;
|
||||
int checksum_seed = 0;
|
||||
unsigned int block_size = 0;
|
||||
int do_stats=0;
|
||||
int do_progress=0;
|
||||
int keep_partial=0;
|
||||
int safe_symlinks=0;
|
||||
int copy_unsafe_links=0;
|
||||
int block_size=0;
|
||||
int size_only=0;
|
||||
int bwlimit=0;
|
||||
int delete_after=0;
|
||||
int only_existing=0;
|
||||
int opt_ignore_existing=0;
|
||||
int max_delete=0;
|
||||
int ignore_errors=0;
|
||||
int modify_window=0;
|
||||
int blocking_io=-1;
|
||||
|
||||
|
||||
/** Network address family. **/
|
||||
@@ -110,7 +107,6 @@ int write_batch = 0;
|
||||
int read_batch = 0;
|
||||
int backup_dir_len = 0;
|
||||
int backup_suffix_len;
|
||||
unsigned int backup_dir_remainder;
|
||||
|
||||
char *backup_suffix = NULL;
|
||||
char *tmpdir = NULL;
|
||||
@@ -121,7 +117,6 @@ char *log_format = NULL;
|
||||
char *password_file = NULL;
|
||||
char *rsync_path = RSYNC_PATH;
|
||||
char *backup_dir = NULL;
|
||||
char backup_dir_buf[MAXPATHLEN];
|
||||
int rsync_port = RSYNC_PORT;
|
||||
int link_dest = 0;
|
||||
|
||||
@@ -130,11 +125,8 @@ int quiet = 0;
|
||||
int always_checksum = 0;
|
||||
int list_only = 0;
|
||||
|
||||
#define FIXED_CHECKSUM_SEED 32761
|
||||
#define MAX_BATCH_PREFIX_LEN 256 /* Must be less than MAXPATHLEN-13 */
|
||||
char *batch_prefix = NULL;
|
||||
|
||||
static int daemon_opt; /* sets am_daemon after option error-reporting */
|
||||
static int modify_window_set;
|
||||
|
||||
/** Local address to bind. As a character string because it's
|
||||
@@ -170,11 +162,11 @@ static void print_rsync_version(enum logcode f)
|
||||
rprintf(f, "%s version %s protocol version %d\n",
|
||||
RSYNC_NAME, RSYNC_VERSION, PROTOCOL_VERSION);
|
||||
rprintf(f,
|
||||
"Copyright (C) 1996-2004 by Andrew Tridgell and others\n");
|
||||
"Copyright (C) 1996-2002 by Andrew Tridgell and others\n");
|
||||
rprintf(f, "<http://rsync.samba.org/>\n");
|
||||
rprintf(f, "Capabilities: %d-bit files, %ssocketpairs, "
|
||||
"%shard links, %ssymlinks, batchfiles, \n",
|
||||
(int) (sizeof (OFF_T) * 8),
|
||||
(int) (sizeof(OFF_T) * 8),
|
||||
got_socketpair, hardlinks, links);
|
||||
|
||||
/* Note that this field may not have type ino_t. It depends
|
||||
@@ -182,8 +174,8 @@ static void print_rsync_version(enum logcode f)
|
||||
* macros. */
|
||||
rprintf(f, " %sIPv6, %d-bit system inums, %d-bit internal inums\n",
|
||||
ipv6,
|
||||
(int) (sizeof dumstat->st_ino * 8),
|
||||
(int) (sizeof (uint64) * 8));
|
||||
(int) (sizeof(dumstat->st_ino) * 8),
|
||||
(int) (sizeof(INO64_T) * 8));
|
||||
#ifdef MAINTAINER_MODE
|
||||
rprintf(f, " panic action: \"%s\"\n",
|
||||
get_panic_action());
|
||||
@@ -227,14 +219,14 @@ void usage(enum logcode F)
|
||||
rprintf(F," -R, --relative use relative path names\n");
|
||||
rprintf(F," --no-relative turn off --relative\n");
|
||||
rprintf(F," --no-implied-dirs don't send implied dirs with -R\n");
|
||||
rprintf(F," -b, --backup make backups (see --suffix & --backup-dir)\n");
|
||||
rprintf(F," -b, --backup make backups (default %s suffix)\n",BACKUP_SUFFIX);
|
||||
rprintf(F," --backup-dir make backups into this directory\n");
|
||||
rprintf(F," --suffix=SUFFIX backup suffix (default %s w/o --backup-dir)\n",BACKUP_SUFFIX);
|
||||
rprintf(F," --suffix=SUFFIX override backup suffix\n");
|
||||
rprintf(F," -u, --update update only (don't overwrite newer files)\n");
|
||||
rprintf(F," -l, --links copy symlinks as symlinks\n");
|
||||
rprintf(F," -L, --copy-links copy the referent of all symlinks\n");
|
||||
rprintf(F," --copy-unsafe-links copy the referent of \"unsafe\" symlinks\n");
|
||||
rprintf(F," --safe-links ignore \"unsafe\" symlinks\n");
|
||||
rprintf(F," -L, --copy-links copy the referent of symlinks\n");
|
||||
rprintf(F," --copy-unsafe-links copy links outside the source tree\n");
|
||||
rprintf(F," --safe-links ignore links outside the destination tree\n");
|
||||
rprintf(F," -H, --hard-links preserve hard links\n");
|
||||
rprintf(F," -p, --perms preserve permissions\n");
|
||||
rprintf(F," -o, --owner preserve owner (root only)\n");
|
||||
@@ -250,19 +242,19 @@ void usage(enum logcode F)
|
||||
rprintf(F," -e, --rsh=COMMAND specify the remote shell\n");
|
||||
rprintf(F," --rsync-path=PATH specify path to rsync on the remote machine\n");
|
||||
rprintf(F," --existing only update files that already exist\n");
|
||||
rprintf(F," --ignore-existing ignore files that already exist on receiving side\n");
|
||||
rprintf(F," --ignore-existing ignore files that already exist on the receiving side\n");
|
||||
rprintf(F," --delete delete files that don't exist on the sending side\n");
|
||||
rprintf(F," --delete-excluded also delete excluded files on the receiving side\n");
|
||||
rprintf(F," --delete-after receiver deletes after transferring, not before\n");
|
||||
rprintf(F," --ignore-errors delete even if there are I/O errors\n");
|
||||
rprintf(F," --delete-after delete after transferring, not before\n");
|
||||
rprintf(F," --ignore-errors delete even if there are IO errors\n");
|
||||
rprintf(F," --max-delete=NUM don't delete more than NUM files\n");
|
||||
rprintf(F," --partial keep partially transferred files\n");
|
||||
rprintf(F," --force force deletion of directories even if not empty\n");
|
||||
rprintf(F," --numeric-ids don't map uid/gid values by user/group name\n");
|
||||
rprintf(F," --timeout=TIME set I/O timeout in seconds\n");
|
||||
rprintf(F," -I, --ignore-times turn off mod time & file size quick check\n");
|
||||
rprintf(F," --size-only ignore mod time for quick check (use size)\n");
|
||||
rprintf(F," --modify-window=NUM compare mod times with reduced accuracy\n");
|
||||
rprintf(F," --timeout=TIME set IO timeout in seconds\n");
|
||||
rprintf(F," -I, --ignore-times don't exclude files that match length and time\n");
|
||||
rprintf(F," --size-only only use file size when determining if a file should be transferred\n");
|
||||
rprintf(F," --modify-window=NUM Timestamp window (seconds) for file match (default=%d)\n",modify_window);
|
||||
rprintf(F," -T --temp-dir=DIR create temporary files in directory DIR\n");
|
||||
rprintf(F," --compare-dest=DIR also compare destination files relative to DIR\n");
|
||||
rprintf(F," --link-dest=DIR create hardlinks to DIR for unchanged files\n");
|
||||
@@ -274,14 +266,14 @@ void usage(enum logcode F)
|
||||
rprintf(F," --include=PATTERN don't exclude files matching PATTERN\n");
|
||||
rprintf(F," --include-from=FILE don't exclude patterns listed in FILE\n");
|
||||
rprintf(F," --files-from=FILE read FILE for list of source-file names\n");
|
||||
rprintf(F," -0 --from0 all *-from file lists are delimited by nulls\n");
|
||||
rprintf(F," -0 --from0 file names we read are separated by nulls, not newlines\n");
|
||||
rprintf(F," --version print version number\n");
|
||||
rprintf(F," --daemon run as an rsync daemon\n");
|
||||
rprintf(F," --daemon run as a rsync daemon\n");
|
||||
rprintf(F," --no-detach do not detach from the parent\n");
|
||||
rprintf(F," --address=ADDRESS bind to the specified address\n");
|
||||
rprintf(F," --config=FILE specify alternate rsyncd.conf file\n");
|
||||
rprintf(F," --port=PORT specify alternate rsyncd port number\n");
|
||||
rprintf(F," --blocking-io use blocking I/O for the remote shell\n");
|
||||
rprintf(F," --blocking-io use blocking IO for the remote shell\n");
|
||||
rprintf(F," --no-blocking-io turn off --blocking-io\n");
|
||||
rprintf(F," --stats give some file transfer stats\n");
|
||||
rprintf(F," --progress show progress during transfer\n");
|
||||
@@ -305,8 +297,7 @@ void usage(enum logcode F)
|
||||
enum {OPT_VERSION = 1000, OPT_SENDER, OPT_EXCLUDE, OPT_EXCLUDE_FROM,
|
||||
OPT_DELETE_AFTER, OPT_DELETE_EXCLUDED, OPT_LINK_DEST,
|
||||
OPT_INCLUDE, OPT_INCLUDE_FROM, OPT_MODIFY_WINDOW,
|
||||
OPT_READ_BATCH, OPT_WRITE_BATCH,
|
||||
OPT_REFUSED_BASE = 9000};
|
||||
OPT_READ_BATCH, OPT_WRITE_BATCH};
|
||||
|
||||
static struct poptOption long_options[] = {
|
||||
/* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
|
||||
@@ -361,10 +352,10 @@ static struct poptOption long_options[] = {
|
||||
{"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, &compare_dest, 0, 0, 0 },
|
||||
{"link-dest", 0, POPT_ARG_STRING, &compare_dest, OPT_LINK_DEST, 0, 0 },
|
||||
{"link-dest", 0, POPT_ARG_STRING, 0, OPT_LINK_DEST, 0, 0 },
|
||||
/* TODO: Should this take an optional int giving the compression level? */
|
||||
{"compress", 'z', POPT_ARG_NONE, &do_compression, 0, 0, 0 },
|
||||
{"daemon", 0, POPT_ARG_NONE, &daemon_opt, 0, 0, 0 },
|
||||
{"daemon", 0, POPT_ARG_NONE, &am_daemon, 0, 0, 0 },
|
||||
{"no-detach", 0, POPT_ARG_NONE, &no_detach, 0, 0, 0 },
|
||||
{"stats", 0, POPT_ARG_NONE, &do_stats, 0, 0, 0 },
|
||||
{"progress", 0, POPT_ARG_NONE, &do_progress, 0, 0, 0 },
|
||||
@@ -417,34 +408,33 @@ void option_error(void)
|
||||
|
||||
|
||||
/**
|
||||
* Tweak the option table to disable all options that the rsyncd.conf
|
||||
* file has told us to refuse.
|
||||
* Check to see if we should refuse this option
|
||||
**/
|
||||
static void set_refuse_options(char *bp)
|
||||
static int check_refuse_options(char *ref, int opt)
|
||||
{
|
||||
struct poptOption *op;
|
||||
char *cp;
|
||||
int i, len;
|
||||
char *p;
|
||||
const char *name;
|
||||
|
||||
while (1) {
|
||||
if ((cp = strchr(bp, ' ')) != NULL)
|
||||
*cp= '\0';
|
||||
for (op = long_options; ; op++) {
|
||||
if (!op->longName) {
|
||||
rprintf(FLOG,
|
||||
"Unknown option %s in \"refuse options\" setting\n",
|
||||
bp);
|
||||
break;
|
||||
}
|
||||
if (strcmp(bp, op->longName) == 0) {
|
||||
op->val = (op - long_options)+OPT_REFUSED_BASE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!cp)
|
||||
break;
|
||||
*cp = ' ';
|
||||
bp = cp + 1;
|
||||
for (i=0; long_options[i].longName; i++) {
|
||||
if (long_options[i].val == opt) break;
|
||||
}
|
||||
|
||||
if (!long_options[i].longName) return 0;
|
||||
|
||||
name = long_options[i].longName;
|
||||
len = strlen(name);
|
||||
|
||||
while ((p = strstr(ref,name))) {
|
||||
if ((p==ref || p[-1]==' ') &&
|
||||
(p[len] == ' ' || p[len] == 0)) {
|
||||
snprintf(err_buf,sizeof(err_buf),
|
||||
"The '%s' option is not supported by this server\n", name);
|
||||
return 1;
|
||||
}
|
||||
ref += len;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -471,12 +461,8 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
|
||||
{
|
||||
int opt;
|
||||
char *ref = lp_refuse_options(module_id);
|
||||
const char *arg;
|
||||
poptContext pc;
|
||||
|
||||
if (ref && *ref)
|
||||
set_refuse_options(ref);
|
||||
|
||||
/* TODO: Call poptReadDefaultConfig; handle errors. */
|
||||
|
||||
/* The context leaks in case of an error, but if there's a
|
||||
@@ -484,6 +470,10 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
|
||||
pc = poptGetContext(RSYNC_NAME, *argc, *argv, long_options, 0);
|
||||
|
||||
while ((opt = poptGetNextOpt(pc)) != -1) {
|
||||
if (ref) {
|
||||
if (check_refuse_options(ref, opt)) return 0;
|
||||
}
|
||||
|
||||
/* most options are handled automatically by popt;
|
||||
* only special cases are returned and listed here. */
|
||||
|
||||
@@ -510,41 +500,53 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
|
||||
break;
|
||||
|
||||
case OPT_EXCLUDE:
|
||||
add_exclude(&exclude_list, poptGetOptArg(pc), 0);
|
||||
add_exclude(&exclude_list, poptGetOptArg(pc),
|
||||
ADD_EXCLUDE);
|
||||
break;
|
||||
|
||||
case OPT_INCLUDE:
|
||||
add_exclude(&exclude_list, poptGetOptArg(pc),
|
||||
XFLG_DEF_INCLUDE);
|
||||
ADD_INCLUDE);
|
||||
break;
|
||||
|
||||
case OPT_EXCLUDE_FROM:
|
||||
arg = poptGetOptArg(pc);
|
||||
if (sanitize_paths)
|
||||
arg = alloc_sanitize_path(arg, curr_dir);
|
||||
add_exclude_file(&exclude_list, arg,
|
||||
XFLG_FATAL_ERRORS);
|
||||
add_exclude_file(&exclude_list, poptGetOptArg(pc),
|
||||
MISSING_FATAL, ADD_EXCLUDE);
|
||||
break;
|
||||
|
||||
case OPT_INCLUDE_FROM:
|
||||
arg = poptGetOptArg(pc);
|
||||
if (sanitize_paths)
|
||||
arg = alloc_sanitize_path(arg, curr_dir);
|
||||
add_exclude_file(&exclude_list, arg,
|
||||
XFLG_FATAL_ERRORS | XFLG_DEF_INCLUDE);
|
||||
add_exclude_file(&exclude_list, poptGetOptArg(pc),
|
||||
MISSING_FATAL, ADD_INCLUDE);
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
usage(FINFO);
|
||||
exit_cleanup(0);
|
||||
|
||||
case 'H':
|
||||
#if SUPPORT_HARD_LINKS
|
||||
preserve_hard_links=1;
|
||||
#else
|
||||
/* FIXME: Don't say "server" if this is
|
||||
* happening on the client. */
|
||||
/* FIXME: Why do we have the duplicated
|
||||
* rprintf? Everybody who gets this message
|
||||
* ought to send it to the client and also to
|
||||
* the logs. */
|
||||
snprintf(err_buf, sizeof err_buf,
|
||||
"hard links are not supported on this %s\n",
|
||||
am_server ? "server" : "client");
|
||||
rprintf(FERROR, "ERROR: %s", err_buf);
|
||||
return 0;
|
||||
#endif /* SUPPORT_HARD_LINKS */
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
verbose++;
|
||||
break;
|
||||
|
||||
case 'q':
|
||||
if (frommain)
|
||||
quiet++;
|
||||
if (frommain) quiet++;
|
||||
break;
|
||||
|
||||
case OPT_SENDER:
|
||||
@@ -563,17 +565,16 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
|
||||
case OPT_WRITE_BATCH:
|
||||
/* popt stores the filename in batch_prefix for us */
|
||||
write_batch = 1;
|
||||
checksum_seed = FIXED_CHECKSUM_SEED;
|
||||
break;
|
||||
|
||||
case OPT_READ_BATCH:
|
||||
/* popt stores the filename in batch_prefix for us */
|
||||
read_batch = 1;
|
||||
checksum_seed = FIXED_CHECKSUM_SEED;
|
||||
break;
|
||||
|
||||
case OPT_LINK_DEST:
|
||||
#if HAVE_LINK
|
||||
compare_dest = (char *)poptGetOptArg(pc);
|
||||
link_dest = 1;
|
||||
break;
|
||||
#else
|
||||
@@ -584,66 +585,24 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
|
||||
default:
|
||||
/* A large opt value means that set_refuse_options()
|
||||
* turned this option off (opt-BASE is its index). */
|
||||
if (opt >= OPT_REFUSED_BASE) {
|
||||
struct poptOption *op =
|
||||
&long_options[opt-OPT_REFUSED_BASE];
|
||||
int n = snprintf(err_buf, sizeof err_buf,
|
||||
"This server does not support --%s\n",
|
||||
op->longName) - 1;
|
||||
if (op->shortName) {
|
||||
snprintf(err_buf+n, sizeof err_buf-n,
|
||||
" (-%c)\n", op->shortName);
|
||||
}
|
||||
} else {
|
||||
snprintf(err_buf, sizeof err_buf,
|
||||
"%s%s: %s\n",
|
||||
am_server ? "on remote machine: " : "",
|
||||
poptBadOption(pc, POPT_BADOPTION_NOALIAS),
|
||||
poptStrerror(opt));
|
||||
}
|
||||
/* FIXME: If --daemon is specified, then errors for later
|
||||
* parameters seem to disappear. */
|
||||
snprintf(err_buf, sizeof(err_buf),
|
||||
"%s%s: %s\n",
|
||||
am_server ? "on remote machine: " : "",
|
||||
poptBadOption(pc, POPT_BADOPTION_NOALIAS),
|
||||
poptStrerror(opt));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#if !SUPPORT_LINKS
|
||||
if (preserve_links && !am_sender) {
|
||||
snprintf(err_buf, sizeof err_buf,
|
||||
"symlinks are not supported on this %s\n",
|
||||
am_server ? "server" : "client");
|
||||
rprintf(FERROR, "ERROR: %s", err_buf);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !SUPPORT_HARD_LINKS
|
||||
if (preserve_hard_links) {
|
||||
snprintf(err_buf, sizeof err_buf,
|
||||
"hard links are not supported on this %s\n",
|
||||
am_server ? "server" : "client");
|
||||
rprintf(FERROR, "ERROR: %s", err_buf);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (write_batch && read_batch) {
|
||||
rprintf(FERROR,
|
||||
"write-batch and read-batch can not be used together\n");
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
}
|
||||
if (batch_prefix && strlen(batch_prefix) > MAX_BATCH_PREFIX_LEN) {
|
||||
rprintf(FERROR,
|
||||
"the batch-file prefix must be %d characters or less.\n",
|
||||
MAX_BATCH_PREFIX_LEN);
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
}
|
||||
|
||||
if (tmpdir && strlen(tmpdir) >= MAXPATHLEN - 10) {
|
||||
rprintf(FERROR, "the --temp-dir path is WAY too long.\n");
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
}
|
||||
|
||||
if (do_compression && (write_batch || read_batch)) {
|
||||
rprintf(FERROR,
|
||||
@@ -667,54 +626,17 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
|
||||
if (relative_paths < 0)
|
||||
relative_paths = files_from? 1 : 0;
|
||||
|
||||
*argv = poptGetArgs(pc);
|
||||
if (*argv)
|
||||
*argc = count_args(*argv);
|
||||
else
|
||||
*argc = 0;
|
||||
|
||||
if (sanitize_paths) {
|
||||
int i;
|
||||
for (i = *argc; i-- > 0; )
|
||||
(*argv)[i] = alloc_sanitize_path((*argv)[i], NULL);
|
||||
if (tmpdir)
|
||||
tmpdir = alloc_sanitize_path(tmpdir, curr_dir);
|
||||
if (compare_dest)
|
||||
compare_dest = alloc_sanitize_path(compare_dest, curr_dir);
|
||||
if (backup_dir)
|
||||
backup_dir = alloc_sanitize_path(backup_dir, curr_dir);
|
||||
if (files_from)
|
||||
files_from = alloc_sanitize_path(files_from, curr_dir);
|
||||
}
|
||||
|
||||
if (daemon_opt) {
|
||||
daemon_opt = 0;
|
||||
am_daemon = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!backup_suffix)
|
||||
backup_suffix = backup_dir ? "" : BACKUP_SUFFIX;
|
||||
backup_suffix = backup_dir? "" : BACKUP_SUFFIX;
|
||||
backup_suffix_len = strlen(backup_suffix);
|
||||
if (strchr(backup_suffix, '/') != NULL) {
|
||||
rprintf(FERROR, "--suffix cannot contain slashes: %s\n",
|
||||
backup_suffix);
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
}
|
||||
if (backup_dir) {
|
||||
backup_dir_len = strlcpy(backup_dir_buf, backup_dir, sizeof backup_dir_buf);
|
||||
backup_dir_remainder = sizeof backup_dir_buf - backup_dir_len;
|
||||
if (backup_dir_remainder < 32) {
|
||||
rprintf(FERROR, "the --backup-dir path is WAY too long.\n");
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
}
|
||||
if (backup_dir_buf[backup_dir_len - 1] != '/') {
|
||||
backup_dir_buf[backup_dir_len++] = '/';
|
||||
backup_dir_buf[backup_dir_len] = '\0';
|
||||
}
|
||||
if (verbose > 1 && !am_sender)
|
||||
rprintf(FINFO, "backup_dir is %s\n", backup_dir_buf);
|
||||
} else if (!backup_suffix_len && (!am_server || !am_sender)) {
|
||||
if (backup_dir)
|
||||
backup_dir_len = strlen(backup_dir);
|
||||
else if (!backup_suffix_len) {
|
||||
rprintf(FERROR,
|
||||
"--suffix cannot be a null string without --backup-dir\n");
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
@@ -723,17 +645,20 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
|
||||
if (do_progress && !verbose)
|
||||
verbose = 1;
|
||||
|
||||
*argv = poptGetArgs(pc);
|
||||
if (*argv)
|
||||
*argc = count_args(*argv);
|
||||
else
|
||||
*argc = 0;
|
||||
|
||||
if (files_from) {
|
||||
char *colon;
|
||||
if (*argc != 2 && !(am_server && am_sender && *argc == 1)) {
|
||||
if (*argc != 2) {
|
||||
usage(FERROR);
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
}
|
||||
if (strcmp(files_from, "-") == 0) {
|
||||
if (strcmp(files_from, "-") == 0)
|
||||
filesfrom_fd = 0;
|
||||
if (am_server)
|
||||
remote_filesfrom_file = "-";
|
||||
}
|
||||
else if ((colon = find_colon(files_from)) != 0) {
|
||||
if (am_server) {
|
||||
usage(FERROR);
|
||||
@@ -745,6 +670,9 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
}
|
||||
} else {
|
||||
extern int sanitize_paths;
|
||||
if (sanitize_paths)
|
||||
sanitize_path(strdup(files_from), NULL);
|
||||
filesfrom_fd = open(files_from, O_RDONLY|O_BINARY);
|
||||
if (filesfrom_fd < 0) {
|
||||
rsyserr(FERROR, errno,
|
||||
@@ -771,7 +699,13 @@ void server_options(char **args,int *argc)
|
||||
{
|
||||
int ac = *argc;
|
||||
static char argstr[50];
|
||||
char *arg;
|
||||
static char bsize[30];
|
||||
static char iotime[30];
|
||||
static char mdelete[30];
|
||||
static char mwindow[30];
|
||||
static char bw[50];
|
||||
/* Leave room for ``--(write|read)-batch='' */
|
||||
static char fext[MAXPATHLEN + 15];
|
||||
|
||||
int i, x;
|
||||
|
||||
@@ -792,7 +726,7 @@ void server_options(char **args,int *argc)
|
||||
|
||||
x = 1;
|
||||
argstr[0] = '-';
|
||||
for (i = 0; i < verbose; i++)
|
||||
for (i=0;i<verbose;i++)
|
||||
argstr[x++] = 'v';
|
||||
|
||||
/* the -q option is intentionally left out */
|
||||
@@ -851,38 +785,37 @@ void server_options(char **args,int *argc)
|
||||
|
||||
argstr[x] = 0;
|
||||
|
||||
if (x != 1)
|
||||
args[ac++] = argstr;
|
||||
if (x != 1) args[ac++] = argstr;
|
||||
|
||||
if (block_size) {
|
||||
if (asprintf(&arg, "-B%u", block_size) < 0)
|
||||
goto oom;
|
||||
args[ac++] = arg;
|
||||
snprintf(bsize,sizeof(bsize),"-B%d",block_size);
|
||||
args[ac++] = bsize;
|
||||
}
|
||||
|
||||
if (max_delete && am_sender) {
|
||||
if (asprintf(&arg, "--max-delete=%d", max_delete) < 0)
|
||||
goto oom;
|
||||
args[ac++] = arg;
|
||||
snprintf(mdelete,sizeof(mdelete),"--max-delete=%d",max_delete);
|
||||
args[ac++] = mdelete;
|
||||
}
|
||||
|
||||
if (batch_prefix) {
|
||||
char *r_or_w = write_batch ? "write" : "read";
|
||||
if (asprintf(&arg, "--%s-batch=%s", r_or_w, batch_prefix) < 0)
|
||||
goto oom;
|
||||
args[ac++] = arg;
|
||||
if (batch_prefix != NULL) {
|
||||
char *fmt = "";
|
||||
if (write_batch)
|
||||
fmt = "--write-batch=%s";
|
||||
else
|
||||
if (read_batch)
|
||||
fmt = "--read-batch=%s";
|
||||
snprintf(fext,sizeof(fext),fmt,batch_prefix);
|
||||
args[ac++] = fext;
|
||||
}
|
||||
|
||||
if (io_timeout) {
|
||||
if (asprintf(&arg, "--timeout=%d", io_timeout) < 0)
|
||||
goto oom;
|
||||
args[ac++] = arg;
|
||||
snprintf(iotime,sizeof(iotime),"--timeout=%d",io_timeout);
|
||||
args[ac++] = iotime;
|
||||
}
|
||||
|
||||
if (bwlimit) {
|
||||
if (asprintf(&arg, "--bwlimit=%d", bwlimit) < 0)
|
||||
goto oom;
|
||||
args[ac++] = arg;
|
||||
snprintf(bw,sizeof(bw),"--bwlimit=%d",bwlimit);
|
||||
args[ac++] = bw;
|
||||
}
|
||||
|
||||
if (backup_dir) {
|
||||
@@ -891,25 +824,28 @@ void server_options(char **args,int *argc)
|
||||
}
|
||||
|
||||
/* Only send --suffix if it specifies a non-default value. */
|
||||
if (strcmp(backup_suffix, backup_dir ? "" : BACKUP_SUFFIX) != 0) {
|
||||
if (strcmp(backup_suffix, backup_dir? "" : BACKUP_SUFFIX) != 0) {
|
||||
char *s = malloc(9+backup_suffix_len+1);
|
||||
if (!s)
|
||||
out_of_memory("server_options");
|
||||
/* We use the following syntax to avoid weirdness with '~'. */
|
||||
if (asprintf(&arg, "--suffix=%s", backup_suffix) < 0)
|
||||
goto oom;
|
||||
args[ac++] = arg;
|
||||
sprintf(s, "--suffix=%s", backup_suffix);
|
||||
args[ac++] = s;
|
||||
}
|
||||
|
||||
if (delete_mode && !delete_excluded)
|
||||
args[ac++] = "--delete";
|
||||
|
||||
if (delete_excluded)
|
||||
args[ac++] = "--delete-excluded";
|
||||
else if (delete_mode)
|
||||
args[ac++] = "--delete";
|
||||
|
||||
if (size_only)
|
||||
args[ac++] = "--size-only";
|
||||
|
||||
if (modify_window_set) {
|
||||
if (asprintf(&arg, "--modify-window=%d", modify_window) < 0)
|
||||
goto oom;
|
||||
args[ac++] = arg;
|
||||
snprintf(mwindow,sizeof(mwindow),"--modify-window=%d",
|
||||
modify_window);
|
||||
args[ac++] = mwindow;
|
||||
}
|
||||
|
||||
if (keep_partial)
|
||||
@@ -966,10 +902,6 @@ void server_options(char **args,int *argc)
|
||||
}
|
||||
|
||||
*argc = ac;
|
||||
return;
|
||||
|
||||
oom:
|
||||
out_of_memory("server_options");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -981,14 +913,12 @@ char *find_colon(char *s)
|
||||
char *p, *p2;
|
||||
|
||||
p = strchr(s,':');
|
||||
if (!p)
|
||||
return NULL;
|
||||
if (!p) return NULL;
|
||||
|
||||
/* now check to see if there is a / in the string before the : - if there is then
|
||||
discard the colon on the assumption that the : is part of a filename */
|
||||
p2 = strchr(s,'/');
|
||||
if (p2 && p2 < p)
|
||||
return NULL;
|
||||
if (p2 && p2 < p) return NULL;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
Summary: Program for efficient remote updates of files.
|
||||
Name: rsync
|
||||
Version: 2.6.1
|
||||
Version: 2.5.7
|
||||
Release: 1
|
||||
Copyright: GPL
|
||||
Group: Applications/Networking
|
||||
Source: ftp://samba.anu.edu.au/pub/rsync/rsync-%{version}.tar.gz
|
||||
Source: ftp://samba.anu.edu.au/pub/rsync/rsync-2.5.7.tar.gz
|
||||
URL: http://samba.anu.edu.au/rsync/
|
||||
Packager: Andrew Tridgell <tridge@samba.anu.edu.au>
|
||||
BuildRoot: /tmp/rsync
|
||||
@@ -21,18 +21,11 @@ A technical report describing the rsync algorithm is included with
|
||||
this package.
|
||||
|
||||
%changelog
|
||||
* Thu Jan 30 2003 Horst von Brand <vonbrand@inf.utfsm.cl>
|
||||
Fixed "Sept" date in %changelog here
|
||||
Use %{_mandir} to point to manpages
|
||||
Support for compressed manpages (* at end catches them in %files)
|
||||
Add doc/README-SGML and doc/rsync.sgml to %doc
|
||||
|
||||
* Mon Sep 11 2000 John H Terpstra <jht@turbolinux.com>
|
||||
* Mon Sept 11 2000 John H Terpstra <jht@turbolinux.com>
|
||||
Changed target paths to be Linux Standards Base compliant
|
||||
|
||||
* Mon Jan 25 1999 Stefan Hornburg <racke@linuxia.de>
|
||||
quoted RPM_OPT_FLAGS for the sake of robustness
|
||||
|
||||
quoted RPM_OPT_FLAGS for the sake of robustness
|
||||
* Mon May 18 1998 Andrew Tridgell <tridge@samba.anu.edu.au>
|
||||
reworked for auto-building when I release rsync (tridge@samba.anu.edu.au)
|
||||
|
||||
@@ -69,25 +62,23 @@ previous package(s).)
|
||||
%setup
|
||||
|
||||
%build
|
||||
./configure --prefix=/usr --mandir=%{_mandir}
|
||||
./configure --prefix=/usr --mandir=/usr/share/man
|
||||
make CFLAGS="$RPM_OPT_FLAGS"
|
||||
strip rsync
|
||||
|
||||
%install
|
||||
mkdir -p $RPM_BUILD_ROOT/usr/bin
|
||||
mkdir -p $RPM_BUILD_ROOT/%{_mandir}/man{1,5}
|
||||
mkdir -p $RPM_BUILD_ROOT/usr/{bin,share/man/{man1,man5}}
|
||||
install -m755 rsync $RPM_BUILD_ROOT/usr/bin
|
||||
install -m644 rsync.1 $RPM_BUILD_ROOT/%{_mandir}/man1
|
||||
install -m644 rsyncd.conf.5 $RPM_BUILD_ROOT/%{_mandir}/man5
|
||||
install -m644 rsync.1 $RPM_BUILD_ROOT/usr/share/man/man1
|
||||
install -m644 rsyncd.conf.5 $RPM_BUILD_ROOT/usr/share/man/man5
|
||||
|
||||
%clean
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
%files
|
||||
%attr(-,root,root) /usr/bin/rsync
|
||||
%attr(-,root,root) %{_mandir}/man1/rsync.1*
|
||||
%attr(-,root,root) %{_mandir}/man5/rsyncd.conf.5*
|
||||
%attr(-,root,root) /usr/share/man/man1/rsync.1
|
||||
%attr(-,root,root) /usr/share/man/man5/rsyncd.conf.5
|
||||
%attr(-,root,root) %doc tech_report.tex
|
||||
%attr(-,root,root) %doc README
|
||||
%attr(-,root,root) %doc COPYING
|
||||
%attr(-,root,root) %doc doc/README-SGML doc/rsync.sgml
|
||||
|
||||
93
packaging/lsb/rsync.spec.tmpl
Normal file
93
packaging/lsb/rsync.spec.tmpl
Normal file
@@ -0,0 +1,93 @@
|
||||
Summary: Program for efficient remote updates of files.
|
||||
Name: rsync
|
||||
Version: PVERSION
|
||||
Release: PRELEASE
|
||||
Copyright: GPL
|
||||
Group: Applications/Networking
|
||||
Source: ftp://samba.anu.edu.au/pub/rsync/rsync-PVERSION.tar.gz
|
||||
URL: http://samba.anu.edu.au/rsync/
|
||||
Packager: Andrew Tridgell <tridge@samba.anu.edu.au>
|
||||
BuildRoot: /tmp/rsync
|
||||
|
||||
%description
|
||||
rsync is a replacement for rcp that has many more features.
|
||||
|
||||
rsync uses the "rsync algorithm" which provides a very fast method for
|
||||
bringing remote files into sync. It does this by sending just the
|
||||
differences in the files across the link, without requiring that both
|
||||
sets of files are present at one of the ends of the link beforehand.
|
||||
|
||||
A technical report describing the rsync algorithm is included with
|
||||
this package.
|
||||
|
||||
%changelog
|
||||
* Thu Jan 30 2003 Horst von Brand <vonbrand@inf.utfsm.cl>
|
||||
Fixed "Sept" date in %changelog here
|
||||
Use %{_mandir} to point to manpages
|
||||
Support for compressed manpages (* at end catches them in %files)
|
||||
Add doc/README-SGML and doc/rsync.sgml to %doc
|
||||
|
||||
* Mon Sep 11 2000 John H Terpstra <jht@turbolinux.com>
|
||||
Changed target paths to be Linux Standards Base compliant
|
||||
|
||||
* Mon Jan 25 1999 Stefan Hornburg <racke@linuxia.de>
|
||||
quoted RPM_OPT_FLAGS for the sake of robustness
|
||||
|
||||
* Mon May 18 1998 Andrew Tridgell <tridge@samba.anu.edu.au>
|
||||
reworked for auto-building when I release rsync (tridge@samba.anu.edu.au)
|
||||
|
||||
* Sat May 16 1998 John H Terpstra <jht@aquasoft.com.au>
|
||||
Upgraded to Rsync 2.0.6
|
||||
-new feature anonymous rsync
|
||||
|
||||
* Mon Apr 6 1998 Douglas N. Arnold <dna@math.psu.edu>
|
||||
|
||||
Upgrade to rsync version 1.7.2.
|
||||
|
||||
* Sun Mar 1 1998 Douglas N. Arnold <dna@math.psu.edu>
|
||||
|
||||
Built 1.6.9-1 based on the 1.6.3-2 spec file of John A. Martin.
|
||||
Changes from 1.6.3-2 packaging: added latex and dvips commands
|
||||
to create tech_report.ps.
|
||||
|
||||
* Mon Aug 25 1997 John A. Martin <jam@jamux.com>
|
||||
|
||||
Built 1.6.3-2 after finding no rsync-1.6.3-1.src.rpm although there
|
||||
was an ftp://ftp.redhat.com/pub/contrib/alpha/rsync-1.6.3-1.alpha.rpm
|
||||
showing no packager nor signature but giving
|
||||
"Source RPM: rsync-1.6.3-1.src.rpm".
|
||||
|
||||
Changes from 1.6.2-1 packaging: added '$RPM_OPT_FLAGS' to make, strip
|
||||
to '%build', removed '%prefix'.
|
||||
|
||||
* Thu Apr 10 1997 Michael De La Rue <miked@ed.ac.uk>
|
||||
|
||||
rsync-1.6.2-1 packaged. (This entry by jam to credit Michael for the
|
||||
previous package(s).)
|
||||
|
||||
%prep
|
||||
%setup
|
||||
|
||||
%build
|
||||
./configure --prefix=/usr --mandir=%{_mandir}
|
||||
make CFLAGS="$RPM_OPT_FLAGS"
|
||||
strip rsync
|
||||
|
||||
%install
|
||||
mkdir -p $RPM_BUILD_ROOT/usr/bin
|
||||
mkdir -p $RPM_BUILD_ROOT/%{_mandir}/man{1,5}
|
||||
install -m755 rsync $RPM_BUILD_ROOT/usr/bin
|
||||
install -m644 rsync.1 $RPM_BUILD_ROOT/%{_mandir}/man1
|
||||
install -m644 rsyncd.conf.5 $RPM_BUILD_ROOT/%{_mandir}/man5
|
||||
|
||||
%clean
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
%files
|
||||
%attr(-,root,root) /usr/bin/rsync
|
||||
%attr(-,root,root) %{_mandir}/man1/rsync.1*
|
||||
%attr(-,root,root) %{_mandir}/man5/rsyncd.conf.5*
|
||||
%attr(-,root,root) %doc tech_report.tex
|
||||
%attr(-,root,root) %doc README
|
||||
%attr(-,root,root) %doc COPYING
|
||||
%attr(-,root,root) %doc doc/README-SGML doc/rsync.sgml
|
||||
81
packaging/redhat/5.0/rsync.spec
Normal file
81
packaging/redhat/5.0/rsync.spec
Normal file
@@ -0,0 +1,81 @@
|
||||
Summary: Program for efficient remote updates of files.
|
||||
Name: rsync
|
||||
Version: 2.5.7
|
||||
Release: 1
|
||||
Copyright: GPL
|
||||
Group: Applications/Networking
|
||||
Source: ftp://samba.anu.edu.au/pub/rsync/rsync-2.5.7.tar.gz
|
||||
URL: http://samba.anu.edu.au/rsync/
|
||||
Packager: Andrew Tridgell <tridge@samba.anu.edu.au>
|
||||
BuildRoot: /tmp/rsync
|
||||
|
||||
%description
|
||||
rsync is a replacement for rcp that has many more features.
|
||||
|
||||
rsync uses the "rsync algorithm" which provides a very fast method for
|
||||
bringing remote files into sync. It does this by sending just the
|
||||
differences in the files across the link, without requiring that both
|
||||
sets of files are present at one of the ends of the link beforehand.
|
||||
|
||||
A technical report describing the rsync algorithm is included with
|
||||
this package.
|
||||
|
||||
%changelog
|
||||
* Mon Jan 25 1999 Stefan Hornburg <racke@linuxia.de>
|
||||
quoted RPM_OPT_FLAGS for the sake of robustness
|
||||
* Mon May 18 1998 Andrew Tridgell <tridge@samba.anu.edu.au>
|
||||
reworked for auto-building when I release rsync (tridge@samba.anu.edu.au)
|
||||
|
||||
* Sat May 16 1998 John H Terpstra <jht@aquasoft.com.au>
|
||||
Upgraded to Rsync 2.0.6
|
||||
-new feature anonymous rsync
|
||||
|
||||
* Mon Apr 6 1998 Douglas N. Arnold <dna@math.psu.edu>
|
||||
|
||||
Upgrade to rsync version 1.7.2.
|
||||
|
||||
* Sun Mar 1 1998 Douglas N. Arnold <dna@math.psu.edu>
|
||||
|
||||
Built 1.6.9-1 based on the 1.6.3-2 spec file of John A. Martin.
|
||||
Changes from 1.6.3-2 packaging: added latex and dvips commands
|
||||
to create tech_report.ps.
|
||||
|
||||
* Mon Aug 25 1997 John A. Martin <jam@jamux.com>
|
||||
|
||||
Built 1.6.3-2 after finding no rsync-1.6.3-1.src.rpm although there
|
||||
was an ftp://ftp.redhat.com/pub/contrib/alpha/rsync-1.6.3-1.alpha.rpm
|
||||
showing no packager nor signature but giving
|
||||
"Source RPM: rsync-1.6.3-1.src.rpm".
|
||||
|
||||
Changes from 1.6.2-1 packaging: added '$RPM_OPT_FLAGS' to make, strip
|
||||
to '%build', removed '%prefix'.
|
||||
|
||||
* Thu Apr 10 1997 Michael De La Rue <miked@ed.ac.uk>
|
||||
|
||||
rsync-1.6.2-1 packaged. (This entry by jam to credit Michael for the
|
||||
previous package(s).)
|
||||
|
||||
%prep
|
||||
%setup
|
||||
|
||||
%build
|
||||
./configure --prefix=/usr
|
||||
make CFLAGS="$RPM_OPT_FLAGS"
|
||||
strip rsync
|
||||
|
||||
%install
|
||||
mkdir -p $RPM_BUILD_ROOT/usr/{bin,man/{man1,man5}}
|
||||
install -m755 rsync $RPM_BUILD_ROOT/usr/bin
|
||||
install -m644 rsync.1 $RPM_BUILD_ROOT/usr/man/man1
|
||||
install -m644 rsyncd.conf.5 $RPM_BUILD_ROOT/usr/man/man5
|
||||
|
||||
%clean
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
%files
|
||||
%attr(-,root,root) /usr/bin/rsync
|
||||
%attr(-,root,root) /usr/man/man1/rsync.1
|
||||
%attr(-,root,root) /usr/man/man5/rsyncd.conf.5
|
||||
%attr(-,root,root) %doc tech_report.tex
|
||||
%attr(-,root,root) %doc README
|
||||
%attr(-,root,root) %doc COPYING
|
||||
81
packaging/redhat/7.1/rsync.spec
Normal file
81
packaging/redhat/7.1/rsync.spec
Normal file
@@ -0,0 +1,81 @@
|
||||
Summary: Program for efficient remote updates of files.
|
||||
Name: rsync
|
||||
Version: 2.5.7
|
||||
Release: 1
|
||||
Copyright: GPL
|
||||
Group: Applications/Networking
|
||||
Source: ftp://samba.anu.edu.au/pub/rsync/rsync-2.5.7.tar.gz
|
||||
URL: http://samba.anu.edu.au/rsync/
|
||||
Packager: Andrew Tridgell <tridge@samba.anu.edu.au>
|
||||
BuildRoot: /tmp/rsync
|
||||
|
||||
%description
|
||||
rsync is a replacement for rcp that has many more features.
|
||||
|
||||
rsync uses the "rsync algorithm" which provides a very fast method for
|
||||
bringing remote files into sync. It does this by sending just the
|
||||
differences in the files across the link, without requiring that both
|
||||
sets of files are present at one of the ends of the link beforehand.
|
||||
|
||||
A technical report describing the rsync algorithm is included with
|
||||
this package.
|
||||
|
||||
%changelog
|
||||
* Mon Jan 25 1999 Stefan Hornburg <racke@linuxia.de>
|
||||
quoted RPM_OPT_FLAGS for the sake of robustness
|
||||
* Mon May 18 1998 Andrew Tridgell <tridge@samba.anu.edu.au>
|
||||
reworked for auto-building when I release rsync (tridge@samba.anu.edu.au)
|
||||
|
||||
* Sat May 16 1998 John H Terpstra <jht@aquasoft.com.au>
|
||||
Upgraded to Rsync 2.0.6
|
||||
-new feature anonymous rsync
|
||||
|
||||
* Mon Apr 6 1998 Douglas N. Arnold <dna@math.psu.edu>
|
||||
|
||||
Upgrade to rsync version 1.7.2.
|
||||
|
||||
* Sun Mar 1 1998 Douglas N. Arnold <dna@math.psu.edu>
|
||||
|
||||
Built 1.6.9-1 based on the 1.6.3-2 spec file of John A. Martin.
|
||||
Changes from 1.6.3-2 packaging: added latex and dvips commands
|
||||
to create tech_report.ps.
|
||||
|
||||
* Mon Aug 25 1997 John A. Martin <jam@jamux.com>
|
||||
|
||||
Built 1.6.3-2 after finding no rsync-1.6.3-1.src.rpm although there
|
||||
was an ftp://ftp.redhat.com/pub/contrib/alpha/rsync-1.6.3-1.alpha.rpm
|
||||
showing no packager nor signature but giving
|
||||
"Source RPM: rsync-1.6.3-1.src.rpm".
|
||||
|
||||
Changes from 1.6.2-1 packaging: added '$RPM_OPT_FLAGS' to make, strip
|
||||
to '%build', removed '%prefix'.
|
||||
|
||||
* Thu Apr 10 1997 Michael De La Rue <miked@ed.ac.uk>
|
||||
|
||||
rsync-1.6.2-1 packaged. (This entry by jam to credit Michael for the
|
||||
previous package(s).)
|
||||
|
||||
%prep
|
||||
%setup
|
||||
|
||||
%build
|
||||
./configure --prefix=/usr
|
||||
make CFLAGS="$RPM_OPT_FLAGS"
|
||||
strip rsync
|
||||
|
||||
%install
|
||||
mkdir -p $RPM_BUILD_ROOT/usr/{bin,man/{man1,man5}}
|
||||
install -m755 rsync $RPM_BUILD_ROOT/usr/bin
|
||||
install -m644 rsync.1* $RPM_BUILD_ROOT/usr/man/man1
|
||||
install -m644 rsyncd.conf.5* $RPM_BUILD_ROOT/usr/man/man5
|
||||
|
||||
%clean
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
%files
|
||||
%attr(-,root,root) /usr/bin/rsync
|
||||
%attr(-,root,root) /usr/man/man1/rsync.1*
|
||||
%attr(-,root,root) /usr/man/man5/rsyncd.conf.5*
|
||||
%attr(-,root,root) %doc tech_report.tex
|
||||
%attr(-,root,root) %doc README
|
||||
%attr(-,root,root) %doc COPYING
|
||||
16
pipe.c
16
pipe.c
@@ -21,13 +21,6 @@
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
extern int am_sender;
|
||||
extern int am_server;
|
||||
extern int blocking_io;
|
||||
extern int orig_umask;
|
||||
extern int read_batch;
|
||||
extern int filesfrom_fd;
|
||||
|
||||
/**
|
||||
* Create a child connected to use on stdin/stdout.
|
||||
*
|
||||
@@ -46,6 +39,7 @@ pid_t piped_child(char **command, int *f_in, int *f_out)
|
||||
pid_t pid;
|
||||
int to_child_pipe[2];
|
||||
int from_child_pipe[2];
|
||||
extern int blocking_io;
|
||||
|
||||
if (verbose >= 2) {
|
||||
print_child_argv(command);
|
||||
@@ -64,6 +58,7 @@ pid_t piped_child(char **command, int *f_in, int *f_out)
|
||||
}
|
||||
|
||||
if (pid == 0) {
|
||||
extern int orig_umask;
|
||||
if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 ||
|
||||
close(to_child_pipe[1]) < 0 ||
|
||||
close(from_child_pipe[0]) < 0 ||
|
||||
@@ -78,8 +73,9 @@ pid_t piped_child(char **command, int *f_in, int *f_out)
|
||||
close(from_child_pipe[1]);
|
||||
umask(orig_umask);
|
||||
set_blocking(STDIN_FILENO);
|
||||
if (blocking_io > 0)
|
||||
if (blocking_io) {
|
||||
set_blocking(STDOUT_FILENO);
|
||||
}
|
||||
execvp(command[0], command);
|
||||
rprintf(FERROR, "Failed to exec %s : %s\n",
|
||||
command[0], strerror(errno));
|
||||
@@ -103,6 +99,10 @@ pid_t local_child(int argc, char **argv,int *f_in,int *f_out,
|
||||
pid_t pid;
|
||||
int to_child_pipe[2];
|
||||
int from_child_pipe[2];
|
||||
extern int read_batch;
|
||||
extern int am_sender;
|
||||
extern int am_server;
|
||||
extern int filesfrom_fd;
|
||||
|
||||
if (fd_pair(to_child_pipe) < 0 ||
|
||||
fd_pair(from_child_pipe) < 0) {
|
||||
|
||||
@@ -5,3 +5,5 @@ config.h
|
||||
config.log
|
||||
config.status
|
||||
dummy
|
||||
rsync
|
||||
zlib/dummy
|
||||
|
||||
@@ -907,10 +907,10 @@ int poptGetNextOpt(poptContext con)
|
||||
#ifndef DBL_EPSILON
|
||||
#define DBL_EPSILON 2.2204460492503131e-16
|
||||
#endif
|
||||
#define MY_ABS(a) ((((a) - 0.0) < DBL_EPSILON) ? -(a) : (a))
|
||||
if ((MY_ABS(aDouble) - FLT_MAX) > DBL_EPSILON)
|
||||
#define _ABS(a) ((((a) - 0.0) < DBL_EPSILON) ? -(a) : (a))
|
||||
if ((_ABS(aDouble) - FLT_MAX) > DBL_EPSILON)
|
||||
return POPT_ERROR_OVERFLOW;
|
||||
if ((FLT_MIN - MY_ABS(aDouble)) > DBL_EPSILON)
|
||||
if ((FLT_MIN - _ABS(aDouble)) > DBL_EPSILON)
|
||||
return POPT_ERROR_OVERFLOW;
|
||||
*((float *) opt->arg) = aDouble;
|
||||
}
|
||||
@@ -1055,7 +1055,7 @@ poptContext poptFreeContext(poptContext con)
|
||||
}
|
||||
|
||||
int poptAddAlias(poptContext con, struct poptAlias alias,
|
||||
/*@unused@*/ UNUSED(int flags))
|
||||
/*@unused@*/ int flags)
|
||||
{
|
||||
poptItem item = (poptItem) alloca(sizeof(*item));
|
||||
memset(item, 0, sizeof(*item));
|
||||
|
||||
@@ -363,7 +363,7 @@ int poptDupArgv(int argc, /*@null@*/ const char **argv,
|
||||
* @retval argcPtr address of returned no. of arguments
|
||||
* @retval argvPtr address of returned argument array
|
||||
*/
|
||||
int poptParseArgvString(const unsigned char * s,
|
||||
int poptParseArgvString(const char * s,
|
||||
/*@out@*/ int * argcPtr, /*@out@*/ const char *** argvPtr)
|
||||
/*@modifies *argcPtr, *argvPtr @*/;
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include "poptint.h"
|
||||
|
||||
/*@-compmempass@*/ /* FIX: item->option.longName kept, not dependent. */
|
||||
static void configLine(poptContext con, unsigned char * line)
|
||||
static void configLine(poptContext con, char * line)
|
||||
/*@modifies con @*/
|
||||
{
|
||||
/*@-type@*/
|
||||
@@ -92,9 +92,9 @@ static void configLine(poptContext con, unsigned char * line)
|
||||
|
||||
int poptReadConfigFile(poptContext con, const char * fn)
|
||||
{
|
||||
const unsigned char * file, * chptr, * end;
|
||||
unsigned char * buf;
|
||||
/*@dependent@*/ unsigned char * dst;
|
||||
const char * file, * chptr, * end;
|
||||
char * buf;
|
||||
/*@dependent@*/ char * dst;
|
||||
int fd, rc;
|
||||
off_t fileLength;
|
||||
|
||||
@@ -159,8 +159,7 @@ int poptReadConfigFile(poptContext con, const char * fn)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int poptReadDefaultConfig(poptContext con, /*@unused@*/ UNUSED(int useEnv))
|
||||
{
|
||||
int poptReadDefaultConfig(poptContext con, /*@unused@*/ int useEnv) {
|
||||
char * fn, * home;
|
||||
int rc;
|
||||
|
||||
|
||||
@@ -17,9 +17,9 @@
|
||||
* @param key option(s)
|
||||
*/
|
||||
static void displayArgs(poptContext con,
|
||||
/*@unused@*/ UNUSED(enum poptCallbackReason foo),
|
||||
/*@unused@*/ enum poptCallbackReason foo,
|
||||
struct poptOption * key,
|
||||
/*@unused@*/ UNUSED(const char * arg), /*@unused@*/ UNUSED(void * data))
|
||||
/*@unused@*/ const char * arg, /*@unused@*/ void * data)
|
||||
/*@globals fileSystem@*/
|
||||
/*@modifies fileSystem@*/
|
||||
{
|
||||
@@ -84,7 +84,7 @@ getTableTranslationDomain(/*@null@*/ const struct poptOption *table)
|
||||
/*@observer@*/ /*@null@*/ static const char *const
|
||||
getArgDescrip(const struct poptOption * opt,
|
||||
/*@-paramuse@*/ /* FIX: wazzup? */
|
||||
/*@null@*/ UNUSED(const char * translation_domain))
|
||||
/*@null@*/ const char * translation_domain)
|
||||
/*@=paramuse@*/
|
||||
/*@*/
|
||||
{
|
||||
@@ -115,7 +115,7 @@ static /*@only@*/ /*@null@*/ char *
|
||||
singleOptionDefaultValue(int lineLength,
|
||||
const struct poptOption * opt,
|
||||
/*@-paramuse@*/ /* FIX: i18n macros disable with lclint */
|
||||
/*@null@*/ UNUSED(const char * translation_domain))
|
||||
/*@null@*/ const char * translation_domain)
|
||||
/*@=paramuse@*/
|
||||
/*@*/
|
||||
{
|
||||
@@ -191,11 +191,11 @@ static void singleOptionHelp(FILE * fp, int maxLeftCol,
|
||||
{
|
||||
int indentLength = maxLeftCol + 5;
|
||||
int lineLength = 79 - indentLength;
|
||||
const unsigned char * help = D_(translation_domain, opt->descrip);
|
||||
const char * help = D_(translation_domain, opt->descrip);
|
||||
const char * argDescrip = getArgDescrip(opt, translation_domain);
|
||||
int helpLength;
|
||||
unsigned char * defs = NULL;
|
||||
unsigned char * left;
|
||||
char * defs = NULL;
|
||||
char * left;
|
||||
int nb = maxLeftCol + 1;
|
||||
|
||||
/* Make sure there's more than enough room in target buffer. */
|
||||
@@ -314,7 +314,7 @@ static void singleOptionHelp(FILE * fp, int maxLeftCol,
|
||||
|
||||
helpLength = strlen(help);
|
||||
while (helpLength > lineLength) {
|
||||
const unsigned char * ch;
|
||||
const char * ch;
|
||||
char format[10];
|
||||
|
||||
ch = help + lineLength - 1;
|
||||
@@ -475,7 +475,7 @@ static int showHelpIntro(poptContext con, FILE * fp)
|
||||
return len;
|
||||
}
|
||||
|
||||
void poptPrintHelp(poptContext con, FILE * fp, /*@unused@*/ UNUSED(int flags))
|
||||
void poptPrintHelp(poptContext con, FILE * fp, /*@unused@*/ int flags)
|
||||
{
|
||||
int leftColWidth;
|
||||
|
||||
@@ -634,7 +634,7 @@ static int showShortOptions(const struct poptOption * opt, FILE * fp,
|
||||
return strlen(s) + 4;
|
||||
}
|
||||
|
||||
void poptPrintUsage(poptContext con, FILE * fp, /*@unused@*/ UNUSED(int flags))
|
||||
void poptPrintUsage(poptContext con, FILE * fp, /*@unused@*/ int flags)
|
||||
{
|
||||
int cursor;
|
||||
|
||||
|
||||
@@ -51,10 +51,10 @@ int poptDupArgv(int argc, const char **argv,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int poptParseArgvString(const unsigned char * s, int * argcPtr, const char *** argvPtr)
|
||||
int poptParseArgvString(const char * s, int * argcPtr, const char *** argvPtr)
|
||||
{
|
||||
const unsigned char * src;
|
||||
unsigned char quote = '\0';
|
||||
const char * src;
|
||||
char quote = '\0';
|
||||
int argvAlloced = POPT_ARGV_ARRAY_GROW_DELTA;
|
||||
const char ** argv = malloc(sizeof(*argv) * argvAlloced);
|
||||
int argc = 0;
|
||||
|
||||
@@ -69,6 +69,5 @@ char *alloca ();
|
||||
#define xstrdup(_str) strdup(_str)
|
||||
#endif /* HAVE_MCHECK_H && defined(__GNUC__) */
|
||||
|
||||
#define UNUSED(x) x __attribute__((__unused__))
|
||||
|
||||
#include "popt.h"
|
||||
|
||||
161
progress.c
161
progress.c
@@ -1,19 +1,19 @@
|
||||
/* -*- c-file-style: "linux" -*-
|
||||
*
|
||||
* Copyright (C) 1996-2000 by Andrew Tridgell
|
||||
*
|
||||
* Copyright (C) 1996-2000 by Andrew Tridgell
|
||||
* Copyright (C) Paul Mackerras 1996
|
||||
* Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
@@ -21,24 +21,15 @@
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
extern struct stats stats;
|
||||
extern int am_server;
|
||||
|
||||
#define PROGRESS_HISTORY_SECS 5
|
||||
|
||||
struct progress_history {
|
||||
struct timeval time;
|
||||
OFF_T ofs;
|
||||
};
|
||||
|
||||
static struct progress_history ph_start;
|
||||
static struct progress_history ph_list[PROGRESS_HISTORY_SECS];
|
||||
static int newest_hpos, oldest_hpos;
|
||||
static OFF_T last_ofs;
|
||||
static struct timeval print_time;
|
||||
static struct timeval start_time;
|
||||
static OFF_T start_ofs;
|
||||
|
||||
static unsigned long msdiff(struct timeval *t1, struct timeval *t2)
|
||||
{
|
||||
return (t2->tv_sec - t1->tv_sec) * 1000L
|
||||
+ (t2->tv_usec - t1->tv_usec) / 1000;
|
||||
return (t2->tv_sec - t1->tv_sec) * 1000
|
||||
+ (t2->tv_usec - t1->tv_usec) / 1000;
|
||||
}
|
||||
|
||||
|
||||
@@ -52,103 +43,79 @@ static unsigned long msdiff(struct timeval *t1, struct timeval *t2)
|
||||
static void rprint_progress(OFF_T ofs, OFF_T size, struct timeval *now,
|
||||
int is_last)
|
||||
{
|
||||
char eol[256];
|
||||
const char *units;
|
||||
int pct = ofs == size ? 100 : (int) (100.0 * ofs / size);
|
||||
unsigned long diff;
|
||||
double rate, remain;
|
||||
int remain_h, remain_m, remain_s;
|
||||
int pct = (ofs == size) ? 100 : (int)((100.0*ofs)/size);
|
||||
unsigned long diff = msdiff(&start_time, now);
|
||||
double rate = diff ? (double) (ofs-start_ofs) * 1000.0 / diff / 1024.0 : 0;
|
||||
const char *units;
|
||||
/* If we've finished transferring this file, show the time taken;
|
||||
* otherwise show expected time to complete. That's kind of
|
||||
* inconsistent, but people can probably cope. Hopefully we'll
|
||||
* get more consistent and complete progress reporting soon. --
|
||||
* mbp */
|
||||
double remain = is_last
|
||||
? (double) diff / 1000.0
|
||||
: rate ? (double) (size-ofs) / rate / 1000.0 : 0.0;
|
||||
int remain_h, remain_m, remain_s;
|
||||
|
||||
if (is_last) {
|
||||
/* Compute stats based on the starting info. */
|
||||
diff = msdiff(&ph_start.time, now);
|
||||
if (!diff)
|
||||
diff = 1;
|
||||
rate = (double) (ofs - ph_start.ofs) * 1000.0 / diff / 1024.0;
|
||||
/* Switch to total time taken for our last update. */
|
||||
remain = (double) diff / 1000.0;
|
||||
} else {
|
||||
/* Compute stats based on recent progress. */
|
||||
diff = msdiff(&ph_list[oldest_hpos].time, now);
|
||||
rate = diff ? (double) (ofs - ph_list[oldest_hpos].ofs) * 1000.0
|
||||
/ diff / 1024.0 : 0;
|
||||
remain = rate ? (double) (size - ofs) / rate / 1000.0 : 0.0;
|
||||
}
|
||||
if (rate > 1024*1024) {
|
||||
rate /= 1024.0 * 1024.0;
|
||||
units = "GB/s";
|
||||
} else if (rate > 1024) {
|
||||
rate /= 1024.0;
|
||||
units = "MB/s";
|
||||
} else {
|
||||
units = "kB/s";
|
||||
}
|
||||
|
||||
if (rate > 1024*1024) {
|
||||
rate /= 1024.0 * 1024.0;
|
||||
units = "GB/s";
|
||||
} else if (rate > 1024) {
|
||||
rate /= 1024.0;
|
||||
units = "MB/s";
|
||||
} else {
|
||||
units = "kB/s";
|
||||
}
|
||||
|
||||
remain_s = (int) remain % 60;
|
||||
remain_m = (int) (remain / 60.0) % 60;
|
||||
remain_h = (int) (remain / 3600.0);
|
||||
|
||||
if (is_last) {
|
||||
snprintf(eol, sizeof eol, " (%d, %.1f%% of %d)\n",
|
||||
stats.num_transferred_files,
|
||||
(float)((stats.current_file_index+1) * 100)
|
||||
/ stats.num_files,
|
||||
stats.num_files);
|
||||
} else
|
||||
strcpy(eol, "\r");
|
||||
rprintf(FINFO, "%12.0f %3d%% %7.2f%s %4d:%02d:%02d%s",
|
||||
(double) ofs, pct, rate, units,
|
||||
remain_h, remain_m, remain_s, eol);
|
||||
remain_s = (int) remain % 60;
|
||||
remain_m = (int) (remain / 60.0) % 60;
|
||||
remain_h = (int) (remain / 3600.0);
|
||||
|
||||
rprintf(FINFO, "%12.0f %3d%% %7.2f%s %4d:%02d:%02d%s",
|
||||
(double) ofs, pct, rate, units,
|
||||
remain_h, remain_m, remain_s,
|
||||
is_last ? "\n" : "\r");
|
||||
}
|
||||
|
||||
void end_progress(OFF_T size)
|
||||
{
|
||||
extern int am_server;
|
||||
|
||||
if (!am_server) {
|
||||
struct timeval now;
|
||||
gettimeofday(&now, NULL);
|
||||
rprint_progress(size, size, &now, True);
|
||||
}
|
||||
memset(&ph_start, 0, sizeof ph_start);
|
||||
last_ofs = 0;
|
||||
start_ofs = 0;
|
||||
print_time.tv_sec = print_time.tv_usec = 0;
|
||||
start_time.tv_sec = start_time.tv_usec = 0;
|
||||
}
|
||||
|
||||
void show_progress(OFF_T ofs, OFF_T size)
|
||||
{
|
||||
extern int am_server;
|
||||
struct timeval now;
|
||||
|
||||
if (am_server)
|
||||
return;
|
||||
|
||||
gettimeofday(&now, NULL);
|
||||
|
||||
if (!ph_start.time.tv_sec) {
|
||||
int i;
|
||||
|
||||
/* Try to guess the real starting time when the sender started
|
||||
* to send us data by using the time we last received some data
|
||||
* in the last file (if it was recent enough). */
|
||||
if (msdiff(&ph_list[newest_hpos].time, &now) <= 1500) {
|
||||
ph_start.time = ph_list[newest_hpos].time;
|
||||
ph_start.ofs = 0;
|
||||
} else {
|
||||
ph_start.time.tv_sec = now.tv_sec;
|
||||
ph_start.time.tv_usec = now.tv_usec;
|
||||
ph_start.ofs = ofs;
|
||||
}
|
||||
|
||||
for (i = 0; i < PROGRESS_HISTORY_SECS; i++)
|
||||
ph_list[i] = ph_start;
|
||||
if (!start_time.tv_sec) {
|
||||
gettimeofday(&now, NULL);
|
||||
start_time.tv_sec = now.tv_sec;
|
||||
start_time.tv_usec = now.tv_usec;
|
||||
start_ofs = ofs;
|
||||
if (am_server)
|
||||
return;
|
||||
}
|
||||
else {
|
||||
if (msdiff(&ph_list[newest_hpos].time, &now) < 1000)
|
||||
if (am_server)
|
||||
return;
|
||||
|
||||
newest_hpos = oldest_hpos;
|
||||
oldest_hpos = (oldest_hpos + 1) % PROGRESS_HISTORY_SECS;
|
||||
ph_list[newest_hpos].time.tv_sec = now.tv_sec;
|
||||
ph_list[newest_hpos].time.tv_usec = now.tv_usec;
|
||||
ph_list[newest_hpos].ofs = ofs;
|
||||
gettimeofday(&now, NULL);
|
||||
}
|
||||
|
||||
rprint_progress(ofs, size, &now, False);
|
||||
if (ofs > last_ofs + 1000
|
||||
&& msdiff(&print_time, &now) > 250) {
|
||||
rprint_progress(ofs, size, &now, False);
|
||||
last_ofs = ofs;
|
||||
print_time.tv_sec = now.tv_sec;
|
||||
print_time.tv_usec = now.tv_usec;
|
||||
}
|
||||
}
|
||||
|
||||
440
receiver.c
440
receiver.c
@@ -1,18 +1,18 @@
|
||||
/* -*- c-file-style: "linux" -*-
|
||||
|
||||
|
||||
Copyright (C) 1996-2000 by Andrew Tridgell
|
||||
Copyright (C) Paul Mackerras 1996
|
||||
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
@@ -23,65 +23,96 @@
|
||||
extern int verbose;
|
||||
extern int recurse;
|
||||
extern int delete_mode;
|
||||
extern int delete_after;
|
||||
extern int max_delete;
|
||||
extern int remote_version;
|
||||
extern int csum_length;
|
||||
extern struct stats stats;
|
||||
extern int dry_run;
|
||||
extern int am_server;
|
||||
extern int relative_paths;
|
||||
extern int preserve_hard_links;
|
||||
extern int preserve_perms;
|
||||
extern int cvs_exclude;
|
||||
extern int io_error;
|
||||
extern char *tmpdir;
|
||||
extern char *compare_dest;
|
||||
extern int make_backups;
|
||||
extern int do_progress;
|
||||
extern char *backup_dir;
|
||||
extern char *backup_suffix;
|
||||
extern int backup_suffix_len;
|
||||
extern int cleanup_got_literal;
|
||||
extern int module_id;
|
||||
extern int ignore_errors;
|
||||
extern int orig_umask;
|
||||
|
||||
static void delete_one(char *fn, int is_dir)
|
||||
static struct delete_list {
|
||||
DEV64_T dev;
|
||||
INO64_T inode;
|
||||
} *delete_list;
|
||||
static int dlist_len, dlist_alloc_len;
|
||||
|
||||
/* yuck! This function wouldn't have been necessary if I had the sorting
|
||||
algorithm right. Unfortunately fixing the sorting algorithm would introduce
|
||||
a backward incompatibility as file list indexes are sent over the link.
|
||||
*/
|
||||
static int delete_already_done(struct file_list *flist,int j)
|
||||
{
|
||||
if (!is_dir) {
|
||||
if (robust_unlink(fn) != 0) {
|
||||
rprintf(FERROR, "delete_one: unlink %s failed: %s\n",
|
||||
full_fname(fn), strerror(errno));
|
||||
int i;
|
||||
STRUCT_STAT st;
|
||||
|
||||
if (link_stat(f_name(flist->files[j]), &st)) return 1;
|
||||
|
||||
for (i=0;i<dlist_len;i++) {
|
||||
if (st.st_ino == delete_list[i].inode &&
|
||||
st.st_dev == delete_list[i].dev)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void add_delete_entry(struct file_struct *file)
|
||||
{
|
||||
if (dlist_len == dlist_alloc_len) {
|
||||
dlist_alloc_len += 1024;
|
||||
delete_list = realloc_array(delete_list, struct delete_list,
|
||||
dlist_alloc_len);
|
||||
if (!delete_list) out_of_memory("add_delete_entry");
|
||||
}
|
||||
|
||||
delete_list[dlist_len].dev = file->dev;
|
||||
delete_list[dlist_len].inode = file->inode;
|
||||
dlist_len++;
|
||||
|
||||
if (verbose > 3)
|
||||
rprintf(FINFO,"added %s to delete list\n", f_name(file));
|
||||
}
|
||||
|
||||
static void delete_one(struct file_struct *f)
|
||||
{
|
||||
if (!S_ISDIR(f->mode)) {
|
||||
if (robust_unlink(f_name(f)) != 0) {
|
||||
rprintf(FERROR,"delete_one: unlink %s: %s\n",f_name(f),strerror(errno));
|
||||
} else if (verbose) {
|
||||
rprintf(FINFO, "deleting %s\n", fn);
|
||||
rprintf(FINFO,"deleting %s\n",f_name(f));
|
||||
}
|
||||
} else {
|
||||
if (do_rmdir(fn) != 0) {
|
||||
if (errno != ENOTEMPTY && errno != EEXIST) {
|
||||
rprintf(FERROR, "delete_one: rmdir %s failed: %s\n",
|
||||
full_fname(fn), strerror(errno));
|
||||
}
|
||||
} else {
|
||||
if (do_rmdir(f_name(f)) != 0) {
|
||||
if (errno != ENOTEMPTY && errno != EEXIST)
|
||||
rprintf(FERROR,"delete_one: rmdir %s: %s\n",
|
||||
f_name(f), strerror(errno));
|
||||
} else if (verbose) {
|
||||
rprintf(FINFO, "deleting directory %s\n", fn);
|
||||
rprintf(FINFO,"deleting directory %s\n",f_name(f));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int is_backup_file(char *fn)
|
||||
{
|
||||
int k = strlen(fn) - backup_suffix_len;
|
||||
return k > 0 && strcmp(fn+k, backup_suffix) == 0;
|
||||
}
|
||||
|
||||
|
||||
/* This deletes any files on the receiving side that are not present
|
||||
* on the sending side. */
|
||||
/* this deletes any files on the receiving side that are not present
|
||||
on the sending side. For version 1.6.4 I have changed the behaviour
|
||||
to match more closely what most people seem to expect of this option */
|
||||
void delete_files(struct file_list *flist)
|
||||
{
|
||||
struct file_list *local_file_list;
|
||||
int i, j;
|
||||
char *argv[1], fbuf[MAXPATHLEN];
|
||||
char *name;
|
||||
extern int module_id;
|
||||
extern int ignore_errors;
|
||||
extern int max_delete;
|
||||
static int deletion_count;
|
||||
|
||||
if (cvs_exclude)
|
||||
@@ -92,125 +123,112 @@ void delete_files(struct file_list *flist)
|
||||
return;
|
||||
}
|
||||
|
||||
for (j = 0; j < flist->count; j++) {
|
||||
if (!(flist->files[j]->flags & FLAG_TOP_DIR)
|
||||
|| !S_ISDIR(flist->files[j]->mode))
|
||||
continue;
|
||||
for (j=0;j<flist->count;j++) {
|
||||
if (!S_ISDIR(flist->files[j]->mode) ||
|
||||
!(flist->files[j]->flags & FLAG_DELETE)) continue;
|
||||
|
||||
argv[0] = f_name_to(flist->files[j], fbuf);
|
||||
if (remote_version < 19 &&
|
||||
delete_already_done(flist, j)) continue;
|
||||
|
||||
if (!(local_file_list = send_file_list(-1, 1, argv)))
|
||||
name = strdup(f_name(flist->files[j]));
|
||||
|
||||
if (!(local_file_list = send_file_list(-1,1,&name))) {
|
||||
free(name);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (verbose > 1)
|
||||
rprintf(FINFO, "deleting in %s\n", fbuf);
|
||||
rprintf(FINFO,"deleting in %s\n", name);
|
||||
|
||||
for (i = local_file_list->count-1; i >= 0; i--) {
|
||||
if (max_delete && deletion_count > max_delete)
|
||||
break;
|
||||
if (!local_file_list->files[i]->basename)
|
||||
continue;
|
||||
if (flist_find(flist,local_file_list->files[i]) < 0) {
|
||||
for (i=local_file_list->count-1;i>=0;i--) {
|
||||
if (max_delete && deletion_count > max_delete) break;
|
||||
if (!local_file_list->files[i]->basename) continue;
|
||||
if (remote_version < 19 &&
|
||||
S_ISDIR(local_file_list->files[i]->mode))
|
||||
add_delete_entry(local_file_list->files[i]);
|
||||
if (-1 == flist_find(flist,local_file_list->files[i])) {
|
||||
char *f = f_name(local_file_list->files[i]);
|
||||
if (make_backups && (backup_dir || !is_backup_file(f))) {
|
||||
int k = strlen(f) - strlen(backup_suffix);
|
||||
/* Hi Andrew, do we really need to play with backup_suffix here? */
|
||||
if (make_backups && ((k <= 0) ||
|
||||
(strcmp(f+k,backup_suffix) != 0))) {
|
||||
(void) make_backup(f);
|
||||
if (verbose)
|
||||
rprintf(FINFO, "deleting %s\n", f);
|
||||
} else {
|
||||
int mode = local_file_list->files[i]->mode;
|
||||
delete_one(f, S_ISDIR(mode) != 0);
|
||||
deletion_count++;
|
||||
delete_one(local_file_list->files[i]);
|
||||
}
|
||||
deletion_count++;
|
||||
}
|
||||
}
|
||||
flist_free(local_file_list);
|
||||
free(name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* get_tmpname() - create a tmp filename for a given filename
|
||||
*
|
||||
* If a tmpdir is defined, use that as the directory to
|
||||
* put it in. Otherwise, the tmp filename is in the same
|
||||
* directory as the given name. Note that there may be no
|
||||
* directory at all in the given name!
|
||||
*
|
||||
* The tmp filename is basically the given filename with a
|
||||
* dot prepended, and .XXXXXX appended (for mkstemp() to
|
||||
* put its unique gunk in). Take care to not exceed
|
||||
* either the MAXPATHLEN or NAME_MAX, esp. the last, as
|
||||
* the basename basically becomes 8 chars longer. In that
|
||||
* case, the original name is shortened sufficiently to
|
||||
* make it all fit.
|
||||
*
|
||||
* Of course, there's no real reason for the tmp name to
|
||||
* look like the original, except to satisfy us humans.
|
||||
* As long as it's unique, rsync will work.
|
||||
*/
|
||||
|
||||
static int get_tmpname(char *fnametmp, char *fname)
|
||||
{
|
||||
char *f;
|
||||
int length = 0;
|
||||
int maxname;
|
||||
|
||||
/* open tmp file */
|
||||
if (tmpdir) {
|
||||
/* Note: this can't overflow, so the return value is safe */
|
||||
length = strlcpy(fnametmp, tmpdir, MAXPATHLEN - 2);
|
||||
fnametmp[length++] = '/';
|
||||
fnametmp[length] = '\0'; /* always NULL terminated */
|
||||
}
|
||||
|
||||
if ((f = strrchr(fname, '/')) != NULL) {
|
||||
++f;
|
||||
if (!tmpdir) {
|
||||
length = f - fname;
|
||||
/* copy up to and including the slash */
|
||||
strlcpy(fnametmp, fname, length + 1);
|
||||
f = strrchr(fname,'/');
|
||||
if (f == NULL)
|
||||
f = fname;
|
||||
else
|
||||
f++;
|
||||
if (strlen(tmpdir)+strlen(f)+10 > MAXPATHLEN) {
|
||||
rprintf(FERROR,"filename too long\n");
|
||||
return 0;
|
||||
}
|
||||
} else
|
||||
f = fname;
|
||||
fnametmp[length++] = '.';
|
||||
fnametmp[length] = '\0'; /* always NULL terminated */
|
||||
snprintf(fnametmp,MAXPATHLEN, "%s/.%s.XXXXXX",tmpdir,f);
|
||||
return 1;
|
||||
}
|
||||
|
||||
maxname = MIN(MAXPATHLEN - 7 - length, NAME_MAX - 8);
|
||||
f = strrchr(fname,'/');
|
||||
|
||||
if (maxname < 1) {
|
||||
rprintf(FERROR, "temporary filename too long: %s\n", fname);
|
||||
fnametmp[0] = '\0';
|
||||
if (strlen(fname)+9 > MAXPATHLEN) {
|
||||
rprintf(FERROR,"filename too long\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
strlcpy(fnametmp + length, f, maxname);
|
||||
strcat(fnametmp + length, ".XXXXXX");
|
||||
if (f) {
|
||||
*f = 0;
|
||||
snprintf(fnametmp,MAXPATHLEN,"%s/.%s.XXXXXX",
|
||||
fname,f+1);
|
||||
*f = '/';
|
||||
} else {
|
||||
snprintf(fnametmp,MAXPATHLEN,".%s.XXXXXX",fname);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int receive_data(int f_in,struct map_struct *mapbuf,int fd,char *fname,
|
||||
static int receive_data(int f_in,struct map_struct *buf,int fd,char *fname,
|
||||
OFF_T total_size)
|
||||
{
|
||||
int i;
|
||||
struct sum_struct sum;
|
||||
unsigned int len;
|
||||
unsigned int n,remainder,len,count;
|
||||
OFF_T offset = 0;
|
||||
OFF_T offset2;
|
||||
char *data;
|
||||
static char file_sum1[MD4_SUM_LENGTH];
|
||||
static char file_sum2[MD4_SUM_LENGTH];
|
||||
char *map=NULL;
|
||||
|
||||
read_sum_head(f_in, &sum);
|
||||
|
||||
|
||||
count = read_int(f_in);
|
||||
n = read_int(f_in);
|
||||
remainder = read_int(f_in);
|
||||
|
||||
sum_init();
|
||||
|
||||
for (i=recv_token(f_in,&data); i != 0; i=recv_token(f_in,&data)) {
|
||||
|
||||
while ((i = recv_token(f_in, &data)) != 0) {
|
||||
if (do_progress)
|
||||
show_progress(offset, total_size);
|
||||
show_progress(offset, total_size);
|
||||
|
||||
if (i > 0) {
|
||||
extern int cleanup_got_literal;
|
||||
|
||||
if (verbose > 3) {
|
||||
rprintf(FINFO,"data recv %d at %.0f\n",
|
||||
i,(double)offset);
|
||||
@@ -218,64 +236,63 @@ static int receive_data(int f_in,struct map_struct *mapbuf,int fd,char *fname,
|
||||
|
||||
stats.literal_data += i;
|
||||
cleanup_got_literal = 1;
|
||||
|
||||
|
||||
sum_update(data,i);
|
||||
|
||||
if (fd != -1 && write_file(fd,data,i) != i) {
|
||||
rprintf(FERROR, "write failed on %s: %s\n",
|
||||
full_fname(fname), strerror(errno));
|
||||
rprintf(FERROR,"write failed on %s : %s\n",fname,strerror(errno));
|
||||
exit_cleanup(RERR_FILEIO);
|
||||
}
|
||||
offset += i;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
i = -(i+1);
|
||||
offset2 = i*(OFF_T)sum.blength;
|
||||
len = sum.blength;
|
||||
if (i == (int) sum.count-1 && sum.remainder != 0)
|
||||
len = sum.remainder;
|
||||
|
||||
offset2 = i*(OFF_T)n;
|
||||
len = n;
|
||||
if (i == (int) count-1 && remainder != 0)
|
||||
len = remainder;
|
||||
|
||||
stats.matched_data += len;
|
||||
|
||||
|
||||
if (verbose > 3)
|
||||
rprintf(FINFO,"chunk[%d] of size %d at %.0f offset=%.0f\n",
|
||||
i,len,(double)offset2,(double)offset);
|
||||
|
||||
if (mapbuf) {
|
||||
map = map_ptr(mapbuf,offset2,len);
|
||||
|
||||
|
||||
if (buf) {
|
||||
map = map_ptr(buf,offset2,len);
|
||||
|
||||
see_token(map, len);
|
||||
sum_update(map,len);
|
||||
}
|
||||
|
||||
|
||||
if (fd != -1 && write_file(fd,map,len) != (int) len) {
|
||||
rprintf(FERROR, "write failed on %s: %s\n",
|
||||
full_fname(fname), strerror(errno));
|
||||
rprintf(FERROR,"write failed on %s : %s\n",
|
||||
fname,strerror(errno));
|
||||
exit_cleanup(RERR_FILEIO);
|
||||
}
|
||||
offset += len;
|
||||
}
|
||||
|
||||
flush_write_file(fd);
|
||||
|
||||
if (do_progress)
|
||||
end_progress(total_size);
|
||||
end_progress(total_size);
|
||||
|
||||
if (fd != -1 && offset > 0 && sparse_end(fd) != 0) {
|
||||
rprintf(FERROR, "write failed on %s: %s\n",
|
||||
full_fname(fname), strerror(errno));
|
||||
rprintf(FERROR,"write failed on %s : %s\n",
|
||||
fname,strerror(errno));
|
||||
exit_cleanup(RERR_FILEIO);
|
||||
}
|
||||
|
||||
sum_end(file_sum1);
|
||||
|
||||
read_buf(f_in,file_sum2,MD4_SUM_LENGTH);
|
||||
if (verbose > 2) {
|
||||
rprintf(FINFO,"got file_sum\n");
|
||||
}
|
||||
if (fd != -1 && memcmp(file_sum1,file_sum2,MD4_SUM_LENGTH) != 0) {
|
||||
return 0;
|
||||
if (remote_version >= 14) {
|
||||
read_buf(f_in,file_sum2,MD4_SUM_LENGTH);
|
||||
if (verbose > 2) {
|
||||
rprintf(FINFO,"got file_sum\n");
|
||||
}
|
||||
if (fd != -1 &&
|
||||
memcmp(file_sum1,file_sum2,MD4_SUM_LENGTH) != 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -285,68 +302,64 @@ static int receive_data(int f_in,struct map_struct *mapbuf,int fd,char *fname,
|
||||
* main routine for receiver process.
|
||||
*
|
||||
* Receiver process runs on the same host as the generator process. */
|
||||
int recv_files(int f_in,struct file_list *flist,char *local_name)
|
||||
{
|
||||
int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
|
||||
{
|
||||
int fd1,fd2;
|
||||
STRUCT_STAT st;
|
||||
char *fname, fbuf[MAXPATHLEN];
|
||||
char *fname;
|
||||
char template[MAXPATHLEN];
|
||||
char fnametmp[MAXPATHLEN];
|
||||
char *fnamecmp;
|
||||
char fnamecmpbuf[MAXPATHLEN];
|
||||
struct map_struct *mapbuf;
|
||||
struct map_struct *buf;
|
||||
int i;
|
||||
struct file_struct *file;
|
||||
int phase=0;
|
||||
int recv_ok;
|
||||
extern struct stats stats;
|
||||
extern int preserve_perms;
|
||||
extern int delete_after;
|
||||
extern int orig_umask;
|
||||
struct stats initial_stats;
|
||||
|
||||
if (verbose > 2) {
|
||||
rprintf(FINFO,"recv_files(%d) starting\n",flist->count);
|
||||
}
|
||||
|
||||
if (flist->hlink_pool) {
|
||||
pool_destroy(flist->hlink_pool);
|
||||
flist->hlink_pool = NULL;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
while (1) {
|
||||
cleanup_disable();
|
||||
|
||||
i = read_int(f_in);
|
||||
if (i == -1) {
|
||||
if (phase == 0) {
|
||||
if (phase==0 && remote_version >= 13) {
|
||||
phase++;
|
||||
csum_length = SUM_LENGTH;
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"recv_files phase=%d\n",phase);
|
||||
send_msg(MSG_DONE, "", 0);
|
||||
write_int(f_gen,-1);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (i < 0 || i >= flist->count) {
|
||||
rprintf(FERROR,"Invalid file index %d in recv_files (count=%d)\n",
|
||||
rprintf(FERROR,"Invalid file index %d in recv_files (count=%d)\n",
|
||||
i, flist->count);
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
}
|
||||
|
||||
file = flist->files[i];
|
||||
fname = f_name(file);
|
||||
|
||||
stats.current_file_index = i;
|
||||
stats.num_transferred_files++;
|
||||
stats.total_transferred_size += file->length;
|
||||
cleanup_got_literal = 0;
|
||||
|
||||
if (local_name)
|
||||
fname = local_name;
|
||||
else
|
||||
fname = f_name_to(file, fbuf);
|
||||
|
||||
if (dry_run) {
|
||||
if (!am_server && verbose) { /* log transfer */
|
||||
rprintf(FINFO, "%s\n", fname);
|
||||
if (!am_server) {
|
||||
log_transfer(file, fname);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -358,108 +371,95 @@ int recv_files(int f_in,struct file_list *flist,char *local_name)
|
||||
|
||||
fnamecmp = fname;
|
||||
|
||||
/* open the file */
|
||||
/* open the file */
|
||||
fd1 = do_open(fnamecmp, O_RDONLY, 0);
|
||||
|
||||
if (fd1 == -1 && compare_dest != NULL) {
|
||||
if ((fd1 == -1) && (compare_dest != NULL)) {
|
||||
/* try the file at compare_dest instead */
|
||||
pathjoin(fnamecmpbuf, sizeof fnamecmpbuf,
|
||||
compare_dest, fname);
|
||||
snprintf(fnamecmpbuf,MAXPATHLEN,"%s/%s",
|
||||
compare_dest,fname);
|
||||
fnamecmp = fnamecmpbuf;
|
||||
fd1 = do_open(fnamecmp, O_RDONLY, 0);
|
||||
}
|
||||
|
||||
if (fd1 != -1 && do_fstat(fd1,&st) != 0) {
|
||||
rprintf(FERROR, "fstat %s failed: %s\n",
|
||||
full_fname(fnamecmp), strerror(errno));
|
||||
rprintf(FERROR,"fstat %s : %s\n",fnamecmp,strerror(errno));
|
||||
receive_data(f_in,NULL,-1,NULL,file->length);
|
||||
close(fd1);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (fd1 != -1 && S_ISDIR(st.st_mode) && fnamecmp == fname) {
|
||||
/* this special handling for directories
|
||||
* wouldn't be necessary if robust_rename()
|
||||
* and the underlying robust_unlink could cope
|
||||
* with directories
|
||||
*/
|
||||
rprintf(FERROR,"recv_files: %s is a directory\n",
|
||||
full_fname(fnamecmp));
|
||||
receive_data(f_in, NULL, -1, NULL, file->length);
|
||||
if (fd1 != -1 && !S_ISREG(st.st_mode)) {
|
||||
rprintf(FERROR,"%s : not a regular file (recv_files)\n",fnamecmp);
|
||||
receive_data(f_in,NULL,-1,NULL,file->length);
|
||||
close(fd1);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (fd1 != -1 && !S_ISREG(st.st_mode)) {
|
||||
close(fd1);
|
||||
fd1 = -1;
|
||||
mapbuf = NULL;
|
||||
}
|
||||
|
||||
if (fd1 != -1 && !preserve_perms) {
|
||||
/* if the file exists already and we aren't preserving
|
||||
* permissions then act as though the remote end sent
|
||||
* us the file permissions we already have */
|
||||
/* if the file exists already and we aren't perserving
|
||||
presmissions then act as though the remote end sent
|
||||
us the file permissions we already have */
|
||||
file->mode = st.st_mode;
|
||||
}
|
||||
|
||||
if (fd1 != -1 && st.st_size > 0) {
|
||||
mapbuf = map_file(fd1,st.st_size);
|
||||
buf = map_file(fd1,st.st_size);
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"recv mapped %s of size %.0f\n",fnamecmp,(double)st.st_size);
|
||||
} else
|
||||
mapbuf = NULL;
|
||||
} else {
|
||||
buf = NULL;
|
||||
}
|
||||
|
||||
if (!get_tmpname(fnametmp,fname)) {
|
||||
if (mapbuf) unmap_file(mapbuf);
|
||||
if (buf) unmap_file(buf);
|
||||
if (fd1 != -1) close(fd1);
|
||||
continue;
|
||||
}
|
||||
|
||||
strlcpy(template, fnametmp, sizeof template);
|
||||
strlcpy(template, fnametmp, sizeof(template));
|
||||
|
||||
/* we initially set the perms without the
|
||||
* setuid/setgid bits to ensure that there is no race
|
||||
* condition. They are then correctly updated after
|
||||
* the lchown. Thanks to snabb@epipe.fi for pointing
|
||||
* this out. We also set it initially without group
|
||||
* access because of a similar race condition. */
|
||||
setuid/setgid bits to ensure that there is no race
|
||||
condition. They are then correctly updated after
|
||||
the lchown. Thanks to snabb@epipe.fi for pointing
|
||||
this out. We also set it initially without group
|
||||
access because of a similar race condition. */
|
||||
fd2 = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS);
|
||||
|
||||
/* in most cases parent directories will already exist
|
||||
* because their information should have been previously
|
||||
* transferred, but that may not be the case with -R */
|
||||
if (fd2 == -1 && relative_paths && errno == ENOENT &&
|
||||
because their information should have been previously
|
||||
transferred, but that may not be the case with -R */
|
||||
if (fd2 == -1 && relative_paths && errno == ENOENT &&
|
||||
create_directory_path(fnametmp, orig_umask) == 0) {
|
||||
strlcpy(fnametmp, template, sizeof fnametmp);
|
||||
strlcpy(fnametmp, template, sizeof(fnametmp));
|
||||
fd2 = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS);
|
||||
}
|
||||
if (fd2 == -1) {
|
||||
rprintf(FERROR, "mkstemp %s failed: %s\n",
|
||||
full_fname(fnametmp), strerror(errno));
|
||||
receive_data(f_in,mapbuf,-1,NULL,file->length);
|
||||
if (mapbuf) unmap_file(mapbuf);
|
||||
rprintf(FERROR,"mkstemp %s failed: %s\n",fnametmp,strerror(errno));
|
||||
receive_data(f_in,buf,-1,NULL,file->length);
|
||||
if (buf) unmap_file(buf);
|
||||
if (fd1 != -1) close(fd1);
|
||||
continue;
|
||||
}
|
||||
|
||||
cleanup_set(fnametmp, fname, file, buf, fd1, fd2);
|
||||
|
||||
cleanup_set(fnametmp, fname, file, mapbuf, fd1, fd2);
|
||||
|
||||
if (!am_server && verbose) { /* log transfer */
|
||||
rprintf(FINFO, "%s\n", fname);
|
||||
if (!am_server) {
|
||||
log_transfer(file, fname);
|
||||
}
|
||||
|
||||
/* recv file data */
|
||||
recv_ok = receive_data(f_in,mapbuf,fd2,fname,file->length);
|
||||
recv_ok = receive_data(f_in,buf,fd2,fname,file->length);
|
||||
|
||||
log_recv(file, &initial_stats);
|
||||
|
||||
if (mapbuf) unmap_file(mapbuf);
|
||||
|
||||
if (buf) unmap_file(buf);
|
||||
if (fd1 != -1) {
|
||||
close(fd1);
|
||||
}
|
||||
close(fd2);
|
||||
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"renaming %s to %s\n",fnametmp,fname);
|
||||
|
||||
@@ -470,23 +470,35 @@ int recv_files(int f_in,struct file_list *flist,char *local_name)
|
||||
if (!recv_ok) {
|
||||
if (csum_length == SUM_LENGTH) {
|
||||
rprintf(FERROR,"ERROR: file corruption in %s. File changed during transfer?\n",
|
||||
full_fname(fname));
|
||||
fname);
|
||||
} else {
|
||||
char buf[4];
|
||||
if (verbose > 1)
|
||||
rprintf(FINFO,"redoing %s(%d)\n",fname,i);
|
||||
SIVAL(buf, 0, i);
|
||||
send_msg(MSG_REDO, buf, 4);
|
||||
write_int(f_gen,i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (delete_after && recurse && delete_mode && !local_name
|
||||
&& flist->count > 0)
|
||||
delete_files(flist);
|
||||
if (delete_after) {
|
||||
if (recurse && delete_mode && !local_name && flist->count>0) {
|
||||
delete_files(flist);
|
||||
}
|
||||
}
|
||||
|
||||
if (preserve_hard_links)
|
||||
do_hard_links();
|
||||
|
||||
/* now we need to fix any directory permissions that were
|
||||
modified during the transfer */
|
||||
for (i = 0; i < flist->count; i++) {
|
||||
file = flist->files[i];
|
||||
if (!file->basename || !S_ISDIR(file->mode)) continue;
|
||||
recv_generator(local_name?local_name:f_name(file),flist,i,-1);
|
||||
}
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"recv_files finished\n");
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
198
rsync.c
198
rsync.c
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
/*
|
||||
Copyright (C) Andrew Tridgell 1996
|
||||
Copyright (C) Paul Mackerras 1996
|
||||
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
@@ -26,9 +26,6 @@ extern int verbose;
|
||||
extern int dry_run;
|
||||
extern int preserve_times;
|
||||
extern int am_root;
|
||||
extern int am_server;
|
||||
extern int am_sender;
|
||||
extern int am_generator;
|
||||
extern int preserve_uid;
|
||||
extern int preserve_gid;
|
||||
extern int preserve_perms;
|
||||
@@ -46,8 +43,8 @@ void free_sums(struct sum_struct *s)
|
||||
|
||||
|
||||
/*
|
||||
* delete a file or directory. If force_delete is set then delete
|
||||
* recursively
|
||||
* delete a file or directory. If force_delete is set then delete
|
||||
* recursively
|
||||
*/
|
||||
int delete_file(char *fname)
|
||||
{
|
||||
@@ -64,66 +61,91 @@ int delete_file(char *fname)
|
||||
#else
|
||||
ret = do_stat(fname, &st);
|
||||
#endif
|
||||
if (ret)
|
||||
return -1;
|
||||
|
||||
if (!S_ISDIR(st.st_mode)) {
|
||||
if (robust_unlink(fname) == 0 || errno == ENOENT)
|
||||
return 0;
|
||||
rprintf(FERROR, "delete_file: unlink %s failed: %s\n",
|
||||
full_fname(fname), strerror(errno));
|
||||
if (ret) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (do_rmdir(fname) == 0 || errno == ENOENT)
|
||||
return 0;
|
||||
if (!force_delete || !recurse
|
||||
|| (errno != ENOTEMPTY && errno != EEXIST)) {
|
||||
rprintf(FERROR, "delete_file: rmdir %s failed: %s\n",
|
||||
full_fname(fname), strerror(errno));
|
||||
if (!S_ISDIR(st.st_mode)) {
|
||||
if (robust_unlink(fname) == 0 || errno == ENOENT) return 0;
|
||||
rprintf(FERROR,"delete_file: unlink(%s) : %s\n", fname, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (do_rmdir(fname) == 0 || errno == ENOENT) return 0;
|
||||
if (!force_delete || !recurse ||
|
||||
(errno != ENOTEMPTY && errno != EEXIST)) {
|
||||
rprintf(FERROR,"delete_file: rmdir(%s) : %s\n", fname, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* now we do a recsursive delete on the directory ... */
|
||||
if (!(d = opendir(fname))) {
|
||||
rprintf(FERROR, "delete_file: opendir %s failed: %s\n",
|
||||
full_fname(fname), strerror(errno));
|
||||
d = opendir(fname);
|
||||
if (!d) {
|
||||
rprintf(FERROR,"delete_file: opendir(%s): %s\n",
|
||||
fname,strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (errno = 0, di = readdir(d); di; errno = 0, di = readdir(d)) {
|
||||
for (di=readdir(d); di; di=readdir(d)) {
|
||||
char *dname = d_name(di);
|
||||
if (dname[0] == '.' && (dname[1] == '\0'
|
||||
|| (dname[1] == '.' && dname[2] == '\0')))
|
||||
if (strcmp(dname,".")==0 ||
|
||||
strcmp(dname,"..")==0)
|
||||
continue;
|
||||
pathjoin(buf, sizeof buf, fname, dname);
|
||||
snprintf(buf, sizeof(buf), "%s/%s", fname, dname);
|
||||
if (verbose > 0)
|
||||
rprintf(FINFO, "deleting %s\n", buf);
|
||||
rprintf(FINFO,"deleting %s\n", buf);
|
||||
if (delete_file(buf) != 0) {
|
||||
closedir(d);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (errno) {
|
||||
rprintf(FERROR, "delete_file: readdir %s failed: %s\n",
|
||||
full_fname(fname), strerror(errno));
|
||||
closedir(d);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
closedir(d);
|
||||
|
||||
|
||||
if (do_rmdir(fname) != 0) {
|
||||
rprintf(FERROR, "delete_file: rmdir %s failed: %s\n",
|
||||
full_fname(fname), strerror(errno));
|
||||
rprintf(FERROR,"delete_file: rmdir(%s) : %s\n", fname, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int is_in_group(gid_t gid)
|
||||
{
|
||||
#ifdef GETGROUPS_T
|
||||
static gid_t last_in = (gid_t) -2, last_out;
|
||||
static int ngroups = -2;
|
||||
static GETGROUPS_T *gidset;
|
||||
int n;
|
||||
|
||||
if (gid == last_in)
|
||||
return last_out;
|
||||
if (ngroups < -1) {
|
||||
/* treat failure (-1) as if not member of any group */
|
||||
ngroups = getgroups(0, 0);
|
||||
if (ngroups > 0) {
|
||||
gidset = new_array(GETGROUPS_T, ngroups);
|
||||
ngroups = getgroups(ngroups, gidset);
|
||||
}
|
||||
}
|
||||
|
||||
last_in = gid;
|
||||
last_out = 0;
|
||||
for (n = 0; n < ngroups; n++) {
|
||||
if (gidset[n] == gid) {
|
||||
last_out = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return last_out;
|
||||
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
int set_perms(char *fname,struct file_struct *file,STRUCT_STAT *st,
|
||||
int report)
|
||||
int report)
|
||||
{
|
||||
int updated = 0;
|
||||
STRUCT_STAT st2;
|
||||
@@ -133,8 +155,7 @@ int set_perms(char *fname,struct file_struct *file,STRUCT_STAT *st,
|
||||
|
||||
if (!st) {
|
||||
if (link_stat(fname,&st2) != 0) {
|
||||
rprintf(FERROR, "stat %s failed: %s\n",
|
||||
full_fname(fname), strerror(errno));
|
||||
rprintf(FERROR,"stat %s : %s\n",fname,strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
st = &st2;
|
||||
@@ -143,45 +164,37 @@ int set_perms(char *fname,struct file_struct *file,STRUCT_STAT *st,
|
||||
if (preserve_times && !S_ISLNK(st->st_mode) &&
|
||||
cmp_modtime(st->st_mtime, file->modtime) != 0) {
|
||||
/* don't complain about not setting times on directories
|
||||
* because some filesystems can't do it */
|
||||
because some filesystems can't do it */
|
||||
if (set_modtime(fname,file->modtime) != 0 &&
|
||||
!S_ISDIR(st->st_mode)) {
|
||||
rprintf(FERROR, "failed to set times on %s: %s\n",
|
||||
full_fname(fname), strerror(errno));
|
||||
rprintf(FERROR,"failed to set times on %s : %s\n",
|
||||
fname,strerror(errno));
|
||||
return 0;
|
||||
} else {
|
||||
updated = 1;
|
||||
}
|
||||
updated = 1;
|
||||
}
|
||||
|
||||
change_uid = am_root && preserve_uid && st->st_uid != file->uid;
|
||||
change_gid = preserve_gid && file->gid != GID_NONE
|
||||
&& st->st_gid != file->gid;
|
||||
change_gid = preserve_gid && file->gid != (gid_t) -1 && \
|
||||
st->st_gid != file->gid;
|
||||
if (change_gid && !am_root) {
|
||||
/* enforce bsd-style group semantics: non-root can only
|
||||
change to groups that the user is a member of */
|
||||
change_gid = is_in_group(file->gid);
|
||||
}
|
||||
if (change_uid || change_gid) {
|
||||
if (verbose > 2) {
|
||||
if (change_uid) {
|
||||
rprintf(FINFO,
|
||||
"set uid of %s from %ld to %ld\n",
|
||||
fname, (long)st->st_uid, (long)file->uid);
|
||||
}
|
||||
if (change_gid) {
|
||||
rprintf(FINFO,
|
||||
"set gid of %s from %ld to %ld\n",
|
||||
fname, (long)st->st_gid, (long)file->gid);
|
||||
}
|
||||
}
|
||||
if (do_lchown(fname,
|
||||
change_uid ? file->uid : st->st_uid,
|
||||
change_gid ? file->gid : st->st_gid) != 0) {
|
||||
change_uid?file->uid:st->st_uid,
|
||||
change_gid?file->gid:st->st_gid) != 0) {
|
||||
/* shouldn't have attempted to change uid or gid
|
||||
* unless have the privilege */
|
||||
rprintf(FERROR, "%s %s failed: %s\n",
|
||||
change_uid ? "chown" : "chgrp",
|
||||
full_fname(fname), strerror(errno));
|
||||
unless have the privilege */
|
||||
rprintf(FERROR,"chown %s : %s\n", fname,strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
/* a lchown had been done - we have to re-stat if the
|
||||
* destination had the setuid or setgid bits set due
|
||||
* to the side effect of the chown call */
|
||||
destination had the setuid or setgid bits set due
|
||||
to the side effect of the chown call */
|
||||
if (st->st_mode & (S_ISUID | S_ISGID)) {
|
||||
link_stat(fname, st);
|
||||
}
|
||||
@@ -190,17 +203,17 @@ int set_perms(char *fname,struct file_struct *file,STRUCT_STAT *st,
|
||||
|
||||
#ifdef HAVE_CHMOD
|
||||
if (!S_ISLNK(st->st_mode)) {
|
||||
if ((st->st_mode & CHMOD_BITS) != (file->mode & CHMOD_BITS)) {
|
||||
if (st->st_mode != file->mode) {
|
||||
updated = 1;
|
||||
if (do_chmod(fname,(file->mode & CHMOD_BITS)) != 0) {
|
||||
rprintf(FERROR, "failed to set permissions on %s: %s\n",
|
||||
full_fname(fname), strerror(errno));
|
||||
if (do_chmod(fname,file->mode) != 0) {
|
||||
rprintf(FERROR,"failed to set permissions on %s : %s\n",
|
||||
fname,strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
if (verbose > 1 && report) {
|
||||
if (updated)
|
||||
rprintf(FINFO,"%s\n",fname);
|
||||
@@ -213,15 +226,6 @@ int set_perms(char *fname,struct file_struct *file,STRUCT_STAT *st,
|
||||
|
||||
void sig_int(void)
|
||||
{
|
||||
/* KLUGE: if the user hits Ctrl-C while ssh is prompting
|
||||
* for a password, then our cleanup's sending of a SIGUSR1
|
||||
* signal to all our children may kill ssh before it has a
|
||||
* chance to restore the tty settings (i.e. turn echo back
|
||||
* on). By sleeping for a short time, ssh gets a bigger
|
||||
* chance to do the right thing. If child processes are
|
||||
* not ssh waiting for a password, then this tiny delay
|
||||
* shouldn't hurt anything. */
|
||||
msleep(400);
|
||||
exit_cleanup(RERR_SIGNAL);
|
||||
}
|
||||
|
||||
@@ -230,24 +234,26 @@ void sig_int(void)
|
||||
and ownership */
|
||||
void finish_transfer(char *fname, char *fnametmp, struct file_struct *file)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (make_backups && !make_backup(fname))
|
||||
return;
|
||||
|
||||
/* move tmp file over real file */
|
||||
ret = robust_rename(fnametmp, fname, file->mode & INITACCESSPERMS);
|
||||
if (ret < 0) {
|
||||
rprintf(FERROR, "%s %s -> \"%s\": %s\n",
|
||||
ret == -2 ? "copy" : "rename",
|
||||
full_fname(fnametmp), fname, strerror(errno));
|
||||
if (robust_rename(fnametmp,fname) != 0) {
|
||||
if (errno == EXDEV) {
|
||||
/* rename failed on cross-filesystem link.
|
||||
Copy the file instead. */
|
||||
if (copy_file(fnametmp,fname, file->mode & INITACCESSPERMS)) {
|
||||
rprintf(FERROR,"copy %s -> %s : %s\n",
|
||||
fnametmp,fname,strerror(errno));
|
||||
} else {
|
||||
set_perms(fname,file,NULL,0);
|
||||
}
|
||||
} else {
|
||||
rprintf(FERROR,"rename %s -> %s : %s\n",
|
||||
fnametmp,fname,strerror(errno));
|
||||
}
|
||||
do_unlink(fnametmp);
|
||||
} else {
|
||||
set_perms(fname,file,NULL,0);
|
||||
}
|
||||
}
|
||||
|
||||
const char *who_am_i(void)
|
||||
{
|
||||
return am_sender ? "sender" : am_generator ? "generator" : "receiver";
|
||||
}
|
||||
|
||||
303
rsync.h
303
rsync.h
@@ -24,10 +24,9 @@
|
||||
|
||||
#define BLOCK_SIZE 700
|
||||
#define RSYNC_RSH_ENV "RSYNC_RSH"
|
||||
#define RSYNC_RSH_IO_ENV "RSYNC_RSH_IO"
|
||||
|
||||
#define RSYNC_NAME "rsync"
|
||||
/* RSYNCD_SYSCONF is now set in config.h */
|
||||
#define RSYNCD_SYSCONF "/etc/rsyncd.conf"
|
||||
#define RSYNCD_USERCONF "rsyncd.conf"
|
||||
|
||||
#define DEFAULT_LOCK_FILE "/var/run/rsyncd.lock"
|
||||
@@ -39,51 +38,32 @@
|
||||
incompatible with older versions :-( */
|
||||
#define CHAR_OFFSET 0
|
||||
|
||||
/* These flags are only used during the flist transfer. */
|
||||
|
||||
#define XMIT_TOP_DIR (1<<0)
|
||||
#define XMIT_SAME_MODE (1<<1)
|
||||
#define XMIT_EXTENDED_FLAGS (1<<2)
|
||||
#define XMIT_SAME_RDEV_pre28 XMIT_EXTENDED_FLAGS /* Only in protocols < 28 */
|
||||
#define XMIT_SAME_UID (1<<3)
|
||||
#define XMIT_SAME_GID (1<<4)
|
||||
#define XMIT_SAME_NAME (1<<5)
|
||||
#define XMIT_LONG_NAME (1<<6)
|
||||
#define XMIT_SAME_TIME (1<<7)
|
||||
#define XMIT_SAME_RDEV_MAJOR (1<<8)
|
||||
#define XMIT_HAS_IDEV_DATA (1<<9)
|
||||
#define XMIT_SAME_DEV (1<<10)
|
||||
#define XMIT_RDEV_MINOR_IS_SMALL (1<<11)
|
||||
|
||||
/* These flags are used in the live flist data. */
|
||||
|
||||
#define FLAG_TOP_DIR (1<<0)
|
||||
#define FLAG_HLINK_EOL (1<<1) /* generator only */
|
||||
#define FLAG_MOUNT_POINT (1<<2) /* sender only */
|
||||
#define FLAG_DELETE (1<<0)
|
||||
#define SAME_MODE (1<<1)
|
||||
#define SAME_RDEV (1<<2)
|
||||
#define SAME_UID (1<<3)
|
||||
#define SAME_GID (1<<4)
|
||||
#define SAME_DIR (1<<5)
|
||||
#define SAME_NAME SAME_DIR
|
||||
#define LONG_NAME (1<<6)
|
||||
#define SAME_TIME (1<<7)
|
||||
|
||||
/* update this if you make incompatible changes */
|
||||
#define PROTOCOL_VERSION 28
|
||||
#define PROTOCOL_VERSION 26
|
||||
|
||||
/* We refuse to interoperate with versions that are not in this range.
|
||||
* Note that we assume we'll work with later versions: the onus is on
|
||||
* people writing them to make sure that they don't send us anything
|
||||
* we won't understand.
|
||||
*
|
||||
* Interoperation with old but supported protocol versions
|
||||
* should cause a warning to be printed. At a future date
|
||||
* the old protocol will become the minimum and
|
||||
* compatibility code removed.
|
||||
*
|
||||
* There are two possible explanations for the limit at
|
||||
* MAX_PROTOCOL_VERSION: either to allow new major-rev versions that
|
||||
* do not interoperate with us, and (more likely) so that we can
|
||||
* detect an attempt to connect rsync to a non-rsync server, which is
|
||||
* unlikely to begin by sending a byte between MIN_PROTOCL_VERSION and
|
||||
* MAX_PROTOCOL_VERSION. */
|
||||
|
||||
#define MIN_PROTOCOL_VERSION 20
|
||||
#define OLD_PROTOCOL_VERSION 25
|
||||
#define MAX_PROTOCOL_VERSION 40
|
||||
* There are two possible explanations for the limit at thirty: either
|
||||
* to allow new major-rev versions that do not interoperate with us,
|
||||
* and (more likely) so that we can detect an attempt to connect rsync
|
||||
* to a non-rsync server, which is unlikely to begin by sending a byte
|
||||
* between 15 and 30. */
|
||||
#define MIN_PROTOCOL_VERSION 15
|
||||
#define MAX_PROTOCOL_VERSION 30
|
||||
|
||||
#define RSYNC_PORT 873
|
||||
|
||||
@@ -93,44 +73,22 @@
|
||||
#define MAX_MAP_SIZE (256*1024)
|
||||
#define IO_BUFFER_SIZE (4092)
|
||||
|
||||
#define IOERR_GENERAL (1<<0) /* For backward compatibility, this must == 1 */
|
||||
#define IOERR_VANISHED (1<<1)
|
||||
|
||||
#define MAX_ARGS 1000
|
||||
|
||||
#define MPLEX_BASE 7
|
||||
|
||||
#define NO_EXCLUDES 0
|
||||
#define SERVER_EXCLUDES 1
|
||||
#define ALL_EXCLUDES 2
|
||||
|
||||
#define XFLG_FATAL_ERRORS (1<<0)
|
||||
#define XFLG_DEF_INCLUDE (1<<1)
|
||||
#define XFLG_WORDS_ONLY (1<<2)
|
||||
#define XFLG_WORD_SPLIT (1<<3)
|
||||
|
||||
#define FULL_FLUSH 1
|
||||
#define NORMAL_FLUSH 0
|
||||
|
||||
|
||||
/* Log-message categories. FLOG is only used on the daemon side to
|
||||
* output messages to the log file. */
|
||||
enum logcode { FERROR=1, FINFO=2, FLOG=3 };
|
||||
|
||||
/* Messages types that are sent over the message channel. The logcode
|
||||
* values must all be present here with identical numbers. */
|
||||
enum msgcode {
|
||||
MSG_DATA=0, /* raw data on the multiplexed stream */
|
||||
MSG_ERROR=FERROR, MSG_INFO=FINFO, MSG_LOG=FLOG, /* remote logging */
|
||||
MSG_REDO=4, /* reprocess indicated flist index */
|
||||
MSG_DONE=5, /* current phase is done */
|
||||
};
|
||||
/* Log values. I *think* what these mean is: FLOG goes to the server
|
||||
* logfile; FERROR and FINFO try to end up on the client, with
|
||||
* different levels of filtering. */
|
||||
enum logcode {FNONE=0, FERROR=1, FINFO=2, FLOG=3 };
|
||||
|
||||
#include "errcode.h"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
/* The default RSYNC_RSH is always set in config.h. */
|
||||
/* The default RSYNC_RSH is always set in config.h, either to "remsh",
|
||||
* "rsh", or otherwise something specified by the user. HAVE_REMSH
|
||||
* controls parameter munging for HP/UX, etc. */
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
@@ -148,10 +106,6 @@ enum msgcode {
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_MALLOC_H) && (defined(HAVE_MALLINFO) || !defined(HAVE_STDLIB_H))
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
@@ -160,6 +114,10 @@ enum msgcode {
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_MALLOC_H
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
|
||||
#ifdef TIME_WITH_SYS_TIME
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
@@ -216,10 +174,20 @@ enum msgcode {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_FNMATCH
|
||||
#include <fnmatch.h>
|
||||
#else
|
||||
#include "lib/fnmatch.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GLOB_H
|
||||
#include <glob.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_MALLOC_H
|
||||
# include <malloc.h>
|
||||
#endif
|
||||
|
||||
/* these are needed for the uid/gid mapping code */
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
@@ -246,19 +214,12 @@ enum msgcode {
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if MAJOR_IN_MKDEV
|
||||
#include <sys/mkdev.h>
|
||||
#elif MAJOR_IN_SYSMACROS
|
||||
#include <sys/sysmacros.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_COMPAT_H
|
||||
#include <compat.h>
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "lib/pool_alloc.h"
|
||||
|
||||
#define BOOL int
|
||||
|
||||
@@ -312,17 +273,6 @@ enum msgcode {
|
||||
#define NO_INT64
|
||||
#endif
|
||||
|
||||
#if (SIZEOF_LONG == 8)
|
||||
#define uint64 unsigned long
|
||||
#elif (SIZEOF_INT == 8)
|
||||
#define uint64 unsigned int
|
||||
#elif HAVE_LONGLONG
|
||||
#define uint64 unsigned long long
|
||||
#else
|
||||
/* As long as it gets... */
|
||||
#define uint64 unsigned off_t
|
||||
#endif
|
||||
|
||||
/* Starting from protocol version 26, we always use 64-bit
|
||||
* ino_t and dev_t internally, even if this platform does not
|
||||
* allow files to have 64-bit inums. That's because the
|
||||
@@ -345,14 +295,17 @@ enum msgcode {
|
||||
* device numbers will be truncated. But it's a kind of silly thing
|
||||
* to do anyhow.
|
||||
*
|
||||
* FIXME: I don't think the code in flist.c has ever worked on a system
|
||||
* where dev_t is a struct.
|
||||
* FIXME: In future, we should probable split the device number into
|
||||
* major/minor, and transfer the two parts as 32-bit ints. That gives
|
||||
* you somewhat more of a chance that they'll come from a big machine
|
||||
* to a little one in a useful way.
|
||||
*
|
||||
* FIXME: Really we need an unsigned type, and we perhaps ought to
|
||||
* cope with platforms on which this is an unsigned int or even a
|
||||
* struct. Later.
|
||||
*/
|
||||
|
||||
struct idev {
|
||||
uint64 inode;
|
||||
uint64 dev;
|
||||
};
|
||||
#define INO64_T int64
|
||||
#define DEV64_T int64
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a,b) ((a)<(b)?(a):(b))
|
||||
@@ -369,17 +322,11 @@ struct idev {
|
||||
/* the length of the md4 checksum */
|
||||
#define MD4_SUM_LENGTH 16
|
||||
#define SUM_LENGTH 16
|
||||
#define SHORT_SUM_LENGTH 2
|
||||
#define BLOCKSUM_BIAS 10
|
||||
|
||||
#ifndef MAXPATHLEN
|
||||
#define MAXPATHLEN 1024
|
||||
#endif
|
||||
|
||||
#ifndef NAME_MAX
|
||||
#define NAME_MAX 255
|
||||
#endif
|
||||
|
||||
#ifndef INADDR_NONE
|
||||
#define INADDR_NONE 0xffffffff
|
||||
#endif
|
||||
@@ -388,76 +335,47 @@ struct idev {
|
||||
#define IN_LOOPBACKNET 127
|
||||
#endif
|
||||
|
||||
#define GID_NONE (gid_t) -1
|
||||
|
||||
#define HL_CHECK_MASTER 0
|
||||
#define HL_SKIP 1
|
||||
|
||||
struct hlink {
|
||||
int hlindex;
|
||||
struct file_struct *next;
|
||||
};
|
||||
|
||||
#define F_DEV link_u.idev->dev
|
||||
#define F_INODE link_u.idev->inode
|
||||
|
||||
#define F_HLINDEX link_u.links->hlindex
|
||||
#define F_NEXT link_u.links->next
|
||||
|
||||
struct file_struct {
|
||||
union {
|
||||
dev_t rdev; /* The device number, if this is a device */
|
||||
char *sum; /* Only a normal file can have a checksum */
|
||||
char *link; /* Points to symlink string, if a symlink */
|
||||
} u;
|
||||
unsigned flags;
|
||||
time_t modtime;
|
||||
OFF_T length;
|
||||
mode_t mode;
|
||||
|
||||
INO64_T inode;
|
||||
/** Device this file lives upon */
|
||||
DEV64_T dev;
|
||||
|
||||
/** If this is a device node, the device number. */
|
||||
DEV64_T rdev;
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
char *basename;
|
||||
char *dirname;
|
||||
char *basedir;
|
||||
union {
|
||||
struct idev *idev;
|
||||
struct hlink *links;
|
||||
} link_u;
|
||||
time_t modtime;
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
mode_t mode;
|
||||
uchar flags; /* this item MUST remain last */
|
||||
char *link;
|
||||
char *sum;
|
||||
};
|
||||
|
||||
/*
|
||||
* Start the flist array at FLIST_START entries and grow it
|
||||
* by doubling until FLIST_LINEAR then grow by FLIST_LINEAR
|
||||
*/
|
||||
#define FLIST_START (32 * 1024)
|
||||
#define FLIST_LINEAR (FLIST_START * 512)
|
||||
|
||||
/*
|
||||
* Extent size for allocation pools A minimum size of 128KB
|
||||
* is needed to mmap them so that freeing will release the
|
||||
* space to the OS.
|
||||
*
|
||||
* Larger sizes reduce leftover fragments and speed free calls
|
||||
* (when they happen) Smaller sizes increase the chance of
|
||||
* freed allocations freeing whole extents.
|
||||
*/
|
||||
#define FILE_EXTENT (256 * 1024)
|
||||
#define HLINK_EXTENT (128 * 1024)
|
||||
#define ARENA_SIZE (32 * 1024)
|
||||
|
||||
#define WITH_HLINK 1
|
||||
#define WITHOUT_HLINK 0
|
||||
struct string_area {
|
||||
char *base;
|
||||
char *end;
|
||||
char *current;
|
||||
struct string_area *next;
|
||||
};
|
||||
|
||||
struct file_list {
|
||||
int count;
|
||||
int malloced;
|
||||
alloc_pool_t file_pool;
|
||||
alloc_pool_t hlink_pool;
|
||||
struct file_struct **files;
|
||||
struct string_area *string_area;
|
||||
};
|
||||
|
||||
struct sum_buf {
|
||||
OFF_T offset; /**< offset in file of this chunk */
|
||||
unsigned int len; /**< length of chunk of file */
|
||||
int len; /**< length of chunk of file */
|
||||
int i; /**< index of this chunk */
|
||||
uint32 sum1; /**< simple checksum */
|
||||
char sum2[SUM_LENGTH]; /**< checksum */
|
||||
@@ -466,43 +384,24 @@ struct sum_buf {
|
||||
struct sum_struct {
|
||||
OFF_T flength; /**< total file length */
|
||||
size_t count; /**< how many chunks */
|
||||
unsigned int blength; /**< block_length */
|
||||
unsigned int remainder; /**< flength % block_length */
|
||||
int s2length; /**< sum2_length */
|
||||
size_t remainder; /**< flength % block_length */
|
||||
size_t n; /**< block_length */
|
||||
struct sum_buf *sums; /**< points to info for each chunk */
|
||||
};
|
||||
|
||||
struct map_struct {
|
||||
char *p; /* Window pointer */
|
||||
int fd; /* File Descriptor */
|
||||
int p_size; /* Window size at allocation */
|
||||
int p_len; /* Window size after fill */
|
||||
/* p_size and p_len could be
|
||||
* consolodated by using a local
|
||||
* variable in map_ptr() */
|
||||
int status; /* first errno from read errors */
|
||||
OFF_T file_size; /* File size (from stat) */
|
||||
OFF_T p_offset; /* Window start */
|
||||
OFF_T p_fd_offset; /* offset of cursor in fd ala lseek */
|
||||
char *p;
|
||||
int fd,p_size,p_len;
|
||||
OFF_T file_size, p_offset, p_fd_offset;
|
||||
};
|
||||
|
||||
#define MATCHFLG_WILD (1<<0) /* pattern has '*', '[', and/or '?' */
|
||||
#define MATCHFLG_WILD2 (1<<1) /* pattern has '**' */
|
||||
#define MATCHFLG_WILD2_PREFIX (1<<2) /* pattern starts with '**' */
|
||||
#define MATCHFLG_ABS_PATH (1<<3) /* path-match on absolute path */
|
||||
struct exclude_struct {
|
||||
struct exclude_struct *next;
|
||||
char *pattern;
|
||||
int match_flags;
|
||||
int regular_exp;
|
||||
int fnmatch_flags;
|
||||
int include;
|
||||
int directory;
|
||||
int slash_cnt;
|
||||
};
|
||||
|
||||
struct exclude_list_struct {
|
||||
struct exclude_struct *head;
|
||||
struct exclude_struct *tail;
|
||||
char *debug_type;
|
||||
int local;
|
||||
};
|
||||
|
||||
struct stats {
|
||||
@@ -515,7 +414,6 @@ struct stats {
|
||||
int flist_size;
|
||||
int num_files;
|
||||
int num_transferred_files;
|
||||
int current_file_index;
|
||||
};
|
||||
|
||||
|
||||
@@ -530,7 +428,6 @@ static inline int flist_up(struct file_list *flist, int i)
|
||||
|
||||
#include "byteorder.h"
|
||||
#include "lib/mdfour.h"
|
||||
#include "lib/wildmatch.h"
|
||||
#include "lib/permstring.h"
|
||||
#include "lib/addrinfo.h"
|
||||
|
||||
@@ -545,13 +442,11 @@ int asprintf(char **ptr, const char *format, ...);
|
||||
int vasprintf(char **ptr, const char *format, va_list ap);
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_VSNPRINTF) || !defined(HAVE_C99_VSNPRINTF)
|
||||
#define vsnprintf rsync_vsnprintf
|
||||
int vsnprintf(char *str, size_t count, const char *fmt, va_list args);
|
||||
#if !defined(HAVE_VSNPRINTF) && !defined(HAVE_C99_VSNPRINTF)
|
||||
int vsnprintf (char *str, size_t count, const char *fmt, va_list args);
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_SNPRINTF) || !defined(HAVE_C99_VSNPRINTF)
|
||||
#define snprintf rsync_snprintf
|
||||
#if !defined(HAVE_SNPRINTF) && !defined(HAVE_C99_VSNPRINTF)
|
||||
int snprintf(char *str,size_t count,const char *fmt,...);
|
||||
#endif
|
||||
|
||||
@@ -598,24 +493,10 @@ extern int errno;
|
||||
#define STDERR_FILENO 2
|
||||
#endif
|
||||
|
||||
#ifndef S_IRUSR
|
||||
#define S_IRUSR 0400
|
||||
#endif
|
||||
|
||||
#ifndef S_IWUSR
|
||||
#define S_IWUSR 0200
|
||||
#endif
|
||||
|
||||
#ifndef ACCESSPERMS
|
||||
#define ACCESSPERMS 0777
|
||||
#endif
|
||||
|
||||
#ifndef S_ISVTX
|
||||
#define S_ISVTX 0
|
||||
#endif
|
||||
|
||||
#define CHMOD_BITS (S_ISUID | S_ISGID | S_ISVTX | ACCESSPERMS)
|
||||
|
||||
#ifndef _S_IFMT
|
||||
#define _S_IFMT 0170000
|
||||
#endif
|
||||
@@ -679,6 +560,9 @@ extern int errno;
|
||||
|
||||
#define IS_DEVICE(mode) (S_ISCHR(mode) || S_ISBLK(mode) || S_ISSOCK(mode) || S_ISFIFO(mode))
|
||||
|
||||
#ifndef ACCESSPERMS
|
||||
#define ACCESSPERMS 0777
|
||||
#endif
|
||||
/* Initial mask on permissions given to temporary files. Mask off setuid
|
||||
bits and group access because of potential race-condition security
|
||||
holes, and mask other access because mode 707 is bizarre */
|
||||
@@ -715,10 +599,6 @@ void rsyserr(enum logcode, int, const char *, ...)
|
||||
#define inet_ntoa rep_inet_ntoa
|
||||
#endif
|
||||
|
||||
/* Make sure that the O_BINARY flag is defined. */
|
||||
#ifndef O_BINARY
|
||||
#define O_BINARY 0
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRLCPY
|
||||
size_t strlcpy(char *d, const char *s, size_t bufsize);
|
||||
@@ -734,17 +614,6 @@ size_t strlcat(char *d, const char *s, size_t bufsize);
|
||||
|
||||
#define exit_cleanup(code) _exit_cleanup(code, __FILE__, __LINE__)
|
||||
|
||||
#ifdef HAVE_GETEUID
|
||||
#define MY_UID() geteuid()
|
||||
#else
|
||||
#define MY_UID() getuid()
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GETEGID
|
||||
#define MY_GID() getegid()
|
||||
#else
|
||||
#define MY_GID() getgid()
|
||||
#endif
|
||||
|
||||
extern int verbose;
|
||||
|
||||
|
||||
393
rsync.yo
393
rsync.yo
@@ -1,5 +1,5 @@
|
||||
mailto(rsync-bugs@samba.org)
|
||||
manpage(rsync)(1)(26 Apr 2004)()()
|
||||
manpage(rsync)(1)(26 Jan 2003)()()
|
||||
manpagename(rsync)(faster, flexible replacement for rcp)
|
||||
manpagesynopsis()
|
||||
|
||||
@@ -35,7 +35,7 @@ itemize(
|
||||
it() support for copying links, devices, owners, groups and permissions
|
||||
it() exclude and exclude-from options similar to GNU tar
|
||||
it() a CVS exclude mode for ignoring the same files that CVS would ignore
|
||||
it() can use any transparent remote shell, including ssh or rsh
|
||||
it() can use any transparent remote shell, including rsh or ssh
|
||||
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
|
||||
@@ -51,8 +51,8 @@ itemize(
|
||||
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
|
||||
a remote shell program as the transport (such as rsh or
|
||||
ssh). This is invoked when the destination path contains a
|
||||
single : separator.
|
||||
|
||||
it() for copying from a remote machine to the local machine
|
||||
@@ -61,11 +61,11 @@ itemize(
|
||||
|
||||
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.
|
||||
separator or a 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.
|
||||
separator or a rsync:// URL.
|
||||
|
||||
it() for copying from a remote machine using a remote shell
|
||||
program as the transport, using rsync server on the remote
|
||||
@@ -77,7 +77,7 @@ itemize(
|
||||
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
|
||||
--rsh=COMMAND option is also provided.
|
||||
--rsh=COMMMAND 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
|
||||
@@ -93,9 +93,9 @@ See the file README for installation instructions.
|
||||
|
||||
Once installed, you can use rsync to any machine that you can access via
|
||||
a remote shell (as well as some that you can access using the rsync
|
||||
daemon-mode protocol). For remote transfers, a modern rsync uses ssh
|
||||
daemon-mode protocol). For remote transfers, rsync typically uses rsh
|
||||
for its communications, but it may have been configured to use a
|
||||
different remote shell by default, such as rsh or remsh.
|
||||
different remote shell by default, such as ssh.
|
||||
|
||||
You can also specify any remote shell you like, either by using the -e
|
||||
command line option, or by setting the RSYNC_RSH environment variable.
|
||||
@@ -111,7 +111,7 @@ manpagesection(USAGE)
|
||||
You use rsync in the same way you use rcp. You must specify a source
|
||||
and a destination, one of which may be remote.
|
||||
|
||||
Perhaps the best way to explain the syntax is with some examples:
|
||||
Perhaps the best way to explain the syntax is some examples:
|
||||
|
||||
quote(rsync *.c foo:src/)
|
||||
|
||||
@@ -126,7 +126,7 @@ quote(rsync -avz foo:src/bar /data/tmp)
|
||||
This would recursively transfer all files from the directory src/bar on the
|
||||
machine foo into the /data/tmp/bar directory on the local machine. The
|
||||
files are transferred in "archive" mode, which ensures that symbolic
|
||||
links, devices, attributes, permissions, ownerships, etc. are preserved
|
||||
links, devices, attributes, permissions, ownerships etc are preserved
|
||||
in the transfer. Additionally, compression will be used to reduce the
|
||||
size of data portions of the transfer.
|
||||
|
||||
@@ -162,15 +162,15 @@ running on TCP port 873.
|
||||
|
||||
You may establish the connection via a web proxy by setting the
|
||||
environment variable RSYNC_PROXY to a hostname:port pair pointing to
|
||||
your web proxy. Note that your web proxy's configuration must support
|
||||
proxy connections to port 873.
|
||||
your web proxy. Note that your web proxy's configuration must allow
|
||||
proxying to port 873.
|
||||
|
||||
Using rsync in this way is the same as using it with a remote shell except
|
||||
that:
|
||||
|
||||
itemize(
|
||||
it() you use a double colon :: instead of a single colon to
|
||||
separate the hostname from the path or an rsync:// URL.
|
||||
separate the hostname from the path or a rsync:// URL.
|
||||
|
||||
it() the remote server may print a message of the day when you
|
||||
connect.
|
||||
@@ -194,8 +194,8 @@ users. On those systems using --password-file is recommended.
|
||||
manpagesection(CONNECTING TO AN RSYNC SERVER 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
|
||||
rsh for transport. This is especially useful when you want to connect
|
||||
server capabilities on the remote machine, while still using rsh or
|
||||
ssh 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,
|
||||
@@ -217,7 +217,7 @@ used to check against the rsyncd.conf on the remote host.
|
||||
|
||||
manpagesection(RUNNING AN RSYNC SERVER)
|
||||
|
||||
An rsync server is configured using a configuration file. Please see the
|
||||
An rsync server is configured using a config 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
|
||||
@@ -234,8 +234,18 @@ 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.
|
||||
|
||||
To run an rsync server out of a single-use ssh key, see this section
|
||||
in the rsyncd.conf(5) man page.
|
||||
To run an rsync server 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
|
||||
|
||||
quote(rsync --server --daemon .)
|
||||
|
||||
NOTE: rsync's argument parsing expects the trailing ".", so make sure
|
||||
that it's there. If you want to use a rsyncd.conf(5)-style
|
||||
configuration file other than the default, you can added a
|
||||
--config option to the em(command):
|
||||
|
||||
quote(rsync --server --daemon --config=em(file) .)
|
||||
|
||||
manpagesection(EXAMPLES)
|
||||
|
||||
@@ -285,14 +295,14 @@ verb(
|
||||
-R, --relative use relative path names
|
||||
--no-relative turn off --relative
|
||||
--no-implied-dirs don't send implied dirs with -R
|
||||
-b, --backup make backups (see --suffix & --backup-dir)
|
||||
-b, --backup make backups (see --suffix)
|
||||
--backup-dir make backups into this directory
|
||||
--suffix=SUFFIX backup suffix (default ~ w/o --backup-dir)
|
||||
--suffix=SUFFIX define backup suffix (default ~ w/o --backup-dir)
|
||||
-u, --update update only (don't overwrite newer files)
|
||||
-l, --links copy symlinks as symlinks
|
||||
-L, --copy-links copy the referent of all symlinks
|
||||
--copy-unsafe-links copy the referent of "unsafe" symlinks
|
||||
--safe-links ignore "unsafe" symlinks
|
||||
-L, --copy-links copy the referent of symlinks
|
||||
--copy-unsafe-links copy links outside the source tree
|
||||
--safe-links ignore links outside the destination tree
|
||||
-H, --hard-links preserve hard links
|
||||
-p, --perms preserve permissions
|
||||
-o, --owner preserve owner (root only)
|
||||
@@ -305,24 +315,24 @@ verb(
|
||||
--no-whole-file turn off --whole-file
|
||||
-x, --one-file-system don't cross filesystem boundaries
|
||||
-B, --block-size=SIZE checksum blocking size (default 700)
|
||||
-e, --rsh=COMMAND specify the remote shell
|
||||
-e, --rsh=COMMAND specify the remote shell to use
|
||||
--rsync-path=PATH specify path to rsync on the remote machine
|
||||
--existing only update files that already exist
|
||||
--ignore-existing ignore files that already exist on receiver
|
||||
--delete delete files that don't exist on sender
|
||||
--delete-excluded also delete excluded files on receiver
|
||||
--delete-after receiver deletes after transfer, not before
|
||||
--ignore-errors delete even if there are I/O errors
|
||||
--ignore-existing ignore files that already exist on the receiving side
|
||||
--delete delete files that don't exist on the sending side
|
||||
--delete-excluded also delete excluded files on the receiving side
|
||||
--delete-after delete after transferring, not before
|
||||
--ignore-errors delete even if there are IO errors
|
||||
--max-delete=NUM don't delete more than NUM files
|
||||
--partial keep partially transferred files
|
||||
--force force deletion of dirs even if not empty
|
||||
--force force deletion of directories even if not empty
|
||||
--numeric-ids don't map uid/gid values by user/group name
|
||||
--timeout=TIME set I/O timeout in seconds
|
||||
-I, --ignore-times turn off mod time & file size quick check
|
||||
--size-only ignore mod time for quick check (use size)
|
||||
--modify-window=NUM compare mod times with reduced accuracy
|
||||
--timeout=TIME set IO timeout in seconds
|
||||
-I, --ignore-times don't exclude files that match length and time
|
||||
--size-only only use file size when determining if a file should be transferred
|
||||
--modify-window=NUM Timestamp window (seconds) for file match (default=0)
|
||||
-T --temp-dir=DIR create temporary files in directory DIR
|
||||
--compare-dest=DIR also compare received files relative to DIR
|
||||
--compare-dest=DIR also compare destination files relative to DIR
|
||||
--link-dest=DIR create hardlinks to DIR for unchanged files
|
||||
-P equivalent to --partial --progress
|
||||
-z, --compress compress file data
|
||||
@@ -332,22 +342,22 @@ verb(
|
||||
--include=PATTERN don't exclude files matching PATTERN
|
||||
--include-from=FILE don't exclude patterns listed in FILE
|
||||
--files-from=FILE read FILE for list of source-file names
|
||||
-0 --from0 all file lists are delimited by nulls
|
||||
-0 --from0 file names we read are separated by nulls, not newlines
|
||||
--version print version number
|
||||
--daemon run as an rsync daemon
|
||||
--daemon run as a rsync daemon
|
||||
--no-detach do not detach from the parent
|
||||
--address=ADDRESS bind to the specified address
|
||||
--config=FILE specify alternate rsyncd.conf file
|
||||
--port=PORT specify alternate rsyncd port number
|
||||
--blocking-io use blocking I/O for the remote shell
|
||||
--blocking-io use blocking IO for the remote shell
|
||||
--no-blocking-io turn off --blocking-io
|
||||
--stats give some file transfer stats
|
||||
--progress show progress during transfer
|
||||
--log-format=FORMAT log file transfers using specified format
|
||||
--password-file=FILE get password from FILE
|
||||
--bwlimit=KBPS limit I/O bandwidth, KBytes per second
|
||||
--write-batch=PREFIX write batch fileset starting with PREFIX
|
||||
--read-batch=PREFIX read batch fileset starting with PREFIX
|
||||
--write-batch=PREFIX write batch fileset starting with PREFIX
|
||||
-h, --help show this help screen
|
||||
|
||||
|
||||
@@ -381,12 +391,12 @@ from the remote server. This flag is useful when invoking rsync from
|
||||
cron.
|
||||
|
||||
dit(bf(-I, --ignore-times)) Normally rsync will skip any files that are
|
||||
already the same size and have the same modification time-stamp.
|
||||
This option turns off this "quick check" behavior.
|
||||
already the same length and have the same time-stamp. This option turns
|
||||
off this behavior.
|
||||
|
||||
dit(bf(--size-only)) Normally rsync will not transfer any files that are
|
||||
already the same size and have the same modification time-stamp. With the
|
||||
--size-only option, files will not be transferred if they have the same size,
|
||||
dit(bf(--size-only)) Normally rsync will skip any files that are
|
||||
already the same length and have the same time-stamp. With the
|
||||
--size-only option files will be skipped if they have the same size,
|
||||
regardless of timestamp. This is useful when starting to use rsync
|
||||
after using another mirroring system which may not preserve timestamps
|
||||
exactly.
|
||||
@@ -402,7 +412,7 @@ dit(bf(-c, --checksum)) This forces the sender to checksum all files using
|
||||
a 128-bit MD4 checksum before transfer. The checksum is then
|
||||
explicitly checked on the receiver and any files of the same name
|
||||
which already exist and have the same checksum and size on the
|
||||
receiver are not transferred. This option can be quite slow.
|
||||
receiver are skipped. This option can be quite slow.
|
||||
|
||||
dit(bf(-a, --archive)) This is equivalent to -rlptgoD. It is a quick
|
||||
way of saying you want recursion and want to preserve almost
|
||||
@@ -458,8 +468,6 @@ very useful for incremental backups. You can additionally
|
||||
specify a backup suffix using the --suffix option
|
||||
(otherwise the files backed up in the specified directory
|
||||
will keep their original filenames).
|
||||
If DIR is a relative path, it is relative to the destination directory
|
||||
(which changes in a recursive transfer).
|
||||
|
||||
dit(bf(--suffix=SUFFIX)) This option allows you to override the default
|
||||
backup suffix used with the --backup (-b) option. The default suffix is a ~
|
||||
@@ -469,26 +477,19 @@ dit(bf(-u, --update)) This forces rsync to skip any files for which the
|
||||
destination file already exists and has a date later than the source
|
||||
file.
|
||||
|
||||
In the currently implementation, a difference of file format is always
|
||||
considered to be important enough for an update, no matter what date
|
||||
is on the objects. In other words, if the source has a directory or a
|
||||
symlink where the destination has a file, the transfer would occur
|
||||
regardless of the timestamps. This might change in the future (feel
|
||||
free to comment on this on the mailing list if you have an opinion).
|
||||
|
||||
dit(bf(-l, --links)) When symlinks are encountered, recreate the
|
||||
symlink on the destination.
|
||||
|
||||
dit(bf(-L, --copy-links)) When symlinks are encountered, the file that
|
||||
they point to (the referent) is copied, rather than the symlink.
|
||||
they point to is copied, rather than the symlink.
|
||||
|
||||
dit(bf(--copy-unsafe-links)) This tells rsync to copy the referent of
|
||||
symbolic links that point outside the copied tree. Absolute symlinks
|
||||
symbolic links that point outside the source tree. Absolute symlinks
|
||||
are also treated like ordinary files, and so are any symlinks in the
|
||||
source path itself when --relative is used.
|
||||
|
||||
dit(bf(--safe-links)) This tells rsync to ignore any symbolic links
|
||||
which point outside the copied tree. All absolute symlinks are
|
||||
which point outside the destination tree. All absolute symlinks are
|
||||
also ignored. Using this option in conjunction with --relative may
|
||||
give unexpected results.
|
||||
|
||||
@@ -505,7 +506,7 @@ dit(bf(-W, --whole-file)) With this option the incremental rsync algorithm
|
||||
is not used and the whole file is sent as-is instead. The transfer may be
|
||||
faster if this option is used when the bandwidth between the source and
|
||||
target machines is higher than the bandwidth to disk (especially when the
|
||||
"disk" is actually a networked filesystem). This is the default when both
|
||||
"disk" is actually a networked file system). This is the default when both
|
||||
the source and target are on the local machine.
|
||||
|
||||
dit(bf(--no-whole-file)) Turn off --whole-file, for use when it is the
|
||||
@@ -521,16 +522,15 @@ other files (including updated files) retain their existing permissions
|
||||
|
||||
dit(bf(-o, --owner)) This option causes rsync to set the owner of the
|
||||
destination file to be the same as the source file. On most systems,
|
||||
only the super-user can set file ownership. By default, the preservation
|
||||
is done by name, but may fall back to using the ID number in some
|
||||
circumstances. See the --numeric-ids option for a full discussion.
|
||||
only the super-user can set file ownership. Note that if the remote system
|
||||
is a daemon using chroot, the --numeric-ids option is implied because the
|
||||
remote system cannot get access to the usernames from /etc/passwd.
|
||||
|
||||
dit(bf(-g, --group)) This option causes rsync to set the group of the
|
||||
destination file to be the same as the source file. If the receiving
|
||||
program is not running as the super-user, only groups that the
|
||||
receiver is a member of will be preserved. By default, the preservation
|
||||
is done by name, but may fall back to using the ID number in some
|
||||
circumstances. See the --numeric-ids option for a full discussion.
|
||||
receiver is a member of will be preserved (by group name, not group id
|
||||
number).
|
||||
|
||||
dit(bf(-D, --devices)) This option causes rsync to transfer character and
|
||||
block device information to the remote system to recreate these
|
||||
@@ -579,7 +579,7 @@ This option can be dangerous if used incorrectly! It is a very good idea
|
||||
to run first using the dry run option (-n) to see what files would be
|
||||
deleted to make sure important files aren't listed.
|
||||
|
||||
If the sending side detects any I/O errors then the deletion of any
|
||||
If the sending side detects any IO errors then the deletion of any
|
||||
files at the destination will be automatically disabled. This is to
|
||||
prevent temporary filesystem failures (such as NFS errors) on the
|
||||
sending side causing a massive deletion of files on the
|
||||
@@ -590,13 +590,13 @@ receiving side that are not on the sending side, this tells rsync to also
|
||||
delete any files on the receiving side that are excluded (see --exclude).
|
||||
Implies --delete.
|
||||
|
||||
dit(bf(--delete-after)) By default rsync does file deletions on the
|
||||
receiving side before transferring files to try to ensure that there is
|
||||
sufficient space on the receiving filesystem. If you want to delete
|
||||
after transferring, use the --delete-after switch. Implies --delete.
|
||||
dit(bf(--delete-after)) By default rsync does file deletions before
|
||||
transferring files to try to ensure that there is sufficient space on
|
||||
the receiving filesystem. If you want to delete after transferring
|
||||
then use the --delete-after switch. Implies --delete.
|
||||
|
||||
dit(bf(--ignore-errors)) Tells --delete to go ahead and delete files
|
||||
even when there are I/O errors.
|
||||
even when there are IO errors.
|
||||
|
||||
dit(bf(--force)) This options tells rsync to delete directories even if
|
||||
they are not empty when they are to be replaced by non-directories. This
|
||||
@@ -608,11 +608,11 @@ the rsync algorithm. See the technical report for details.
|
||||
|
||||
dit(bf(-e, --rsh=COMMAND)) This option allows you to choose an alternative
|
||||
remote shell program to use for communication between the local and
|
||||
remote copies of rsync. Typically, rsync is configured to use ssh by
|
||||
default, but you may prefer to use rsh on a local network.
|
||||
remote copies of rsync. Typically, rsync is configured to use rsh by
|
||||
default, but you may prefer to use ssh because of its high security.
|
||||
|
||||
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(COMMMAND) will be used to run an rsync server 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
|
||||
@@ -643,17 +643,16 @@ a file should be ignored.
|
||||
|
||||
The exclude list is initialized to:
|
||||
|
||||
quote(RCS SCCS CVS CVS.adm RCSLOG cvslog.* tags TAGS .make.state
|
||||
.nse_depinfo *~ #* .#* ,* _$* *$ *.old *.bak *.BAK *.orig *.rej
|
||||
.del-* *.a *.olb *.o *.obj *.so *.exe *.Z *.elc *.ln core .svn/)
|
||||
quote(RCS/ SCCS/ CVS/ .svn/ CVS.adm RCSLOG cvslog.* tags TAGS .make.state
|
||||
.nse_depinfo *~ #* .#* ,* *.old *.bak *.BAK *.orig *.rej .del-*
|
||||
*.a *.o *.obj *.so *.Z *.elc *.ln core)
|
||||
|
||||
then files listed in a $HOME/.cvsignore are added to the list and any
|
||||
files listed in the CVSIGNORE environment variable (all cvsignore names
|
||||
are delimited by whitespace).
|
||||
files listed in the CVSIGNORE environment variable (space delimited).
|
||||
|
||||
Finally, any file is ignored if it is in the same directory as a
|
||||
.cvsignore file and matches one of the patterns listed therein.
|
||||
See the bf(cvs(1)) manual for more information.
|
||||
.cvsignore file and matches one of the patterns listed therein. See
|
||||
the bf(cvs(1)) manual for more information.
|
||||
|
||||
dit(bf(--exclude=PATTERN)) This option allows you to selectively exclude
|
||||
certain files from the list of files to be transferred. This is most
|
||||
@@ -662,7 +661,8 @@ useful in combination with a recursive transfer.
|
||||
You may use as many --exclude options on the command line as you like
|
||||
to build up the list of files to exclude.
|
||||
|
||||
See the EXCLUDE PATTERNS section for detailed information on this option.
|
||||
See the EXCLUDE PATTERNS section for information on the syntax of
|
||||
this option.
|
||||
|
||||
dit(bf(--exclude-from=FILE)) This option is similar to the --exclude
|
||||
option, but instead it adds all exclude patterns listed in the file
|
||||
@@ -674,7 +674,8 @@ dit(bf(--include=PATTERN)) This option tells rsync to not exclude the
|
||||
specified pattern of filenames. This is useful as it allows you to
|
||||
build up quite complex exclude/include rules.
|
||||
|
||||
See the EXCLUDE PATTERNS section for detailed information on this option.
|
||||
See the EXCLUDE PATTERNS section for information on the syntax of
|
||||
this option.
|
||||
|
||||
dit(bf(--include-from=FILE)) This specifies a list of include patterns
|
||||
from a file.
|
||||
@@ -720,8 +721,6 @@ was located on the remote "src" host.
|
||||
dit(bf(-0, --from0)) This tells rsync that the filenames it reads from a
|
||||
file are terminated by a null ('\0') character, not a NL, CR, or CR+LF.
|
||||
This affects --exclude-from, --include-from, and --files-from.
|
||||
It does not affect --cvs-exclude (since all names read from a .cvsignore
|
||||
file are split on whitespace).
|
||||
|
||||
dit(bf(-T, --temp-dir=DIR)) This option instructs rsync to use DIR as a
|
||||
scratch directory when creating temporary copies of the files
|
||||
@@ -739,19 +738,14 @@ although this skips files that haven't changed; see also --link-dest).
|
||||
This option increases the usefulness of --partial because partially
|
||||
transferred files will remain in the new temporary destination until they
|
||||
have a chance to be completed. If DIR is a relative path, it is relative
|
||||
to the destination directory (which changes in a recursive transfer).
|
||||
to the destination directory.
|
||||
|
||||
dit(bf(--link-dest=DIR)) This option behaves like bf(--compare-dest) but
|
||||
also will create hard links from em(DIR) to the destination directory for
|
||||
unchanged files. Files with changed ownership or permissions will not be
|
||||
linked.
|
||||
Like bf(--compare-dest) if DIR is a relative path, it is relative
|
||||
to the destination directory (which changes in a recursive transfer).
|
||||
An example:
|
||||
|
||||
verb(
|
||||
rsync -av --link-dest=$PWD/prior_dir host:src_dir/ new_dir/
|
||||
)
|
||||
to the destination directory.
|
||||
|
||||
dit(bf(-z, --compress)) With this option, rsync compresses any data from
|
||||
the files that it sends to the destination machine. This
|
||||
@@ -764,22 +758,19 @@ compressing transport, as it takes advantage of the implicit
|
||||
information sent for matching data blocks.
|
||||
|
||||
dit(bf(--numeric-ids)) With this option rsync will transfer numeric group
|
||||
and user IDs rather than using user and group names and mapping them
|
||||
and user ids rather than using user and group names and mapping them
|
||||
at both ends.
|
||||
|
||||
By default rsync will use the username and groupname to determine
|
||||
By default rsync will use the user name and group name to determine
|
||||
what ownership to give files. The special uid 0 and the special group
|
||||
0 are never mapped via user/group names even if the --numeric-ids
|
||||
option is not specified.
|
||||
|
||||
If a user or group has no name on the source system or it has no match
|
||||
on the destination system, then the numeric ID
|
||||
from the source system is used instead. See also the comments on the
|
||||
"use chroot" setting in the rsyncd.conf manpage for information on how
|
||||
the chroot setting affects rsync's ability to look up the names of the
|
||||
users and groups and what you can do about it.
|
||||
If the source system is a daemon using chroot, or if a user or group
|
||||
name does not exist on the destination system, then the numeric id
|
||||
from the source system is used instead.
|
||||
|
||||
dit(bf(--timeout=TIMEOUT)) This option allows you to set a maximum I/O
|
||||
dit(bf(--timeout=TIMEOUT)) This option allows you to set a maximum IO
|
||||
timeout in seconds. If no data is transferred for the specified time
|
||||
then rsync will exit. The default is 0, which means no timeout.
|
||||
|
||||
@@ -818,11 +809,12 @@ the default is rsyncd.conf in the current directory (typically $HOME).
|
||||
dit(bf(--port=PORT)) This specifies an alternate TCP port number to use
|
||||
rather than the default port 873.
|
||||
|
||||
dit(bf(--blocking-io)) This tells rsync to use blocking I/O when launching
|
||||
a remote shell transport. If the remote shell is either rsh or remsh,
|
||||
rsync defaults to using
|
||||
blocking I/O, otherwise it defaults to using non-blocking I/O. (Note that
|
||||
ssh prefers non-blocking I/O.)
|
||||
dit(bf(--blocking-io)) This tells rsync to use blocking IO when launching
|
||||
a remote shell transport. If -e or --rsh are not specified or are set to
|
||||
the default "rsh", this defaults to blocking IO, otherwise it defaults to
|
||||
non-blocking IO. You may find the --blocking-io option is needed for some
|
||||
remote shells that can't handle non-blocking IO. (Note that ssh prefers
|
||||
non-blocking IO.)
|
||||
|
||||
dit(bf(--no-blocking-io)) Turn off --blocking-io, for use when it is the
|
||||
default.
|
||||
@@ -847,36 +839,13 @@ showing the progress of the transfer. This gives a bored user
|
||||
something to watch.
|
||||
Implies --verbose without incrementing verbosity.
|
||||
|
||||
When the file is transferring, the data looks like this:
|
||||
|
||||
verb(
|
||||
782448 63% 110.64kB/s 0:00:04
|
||||
)
|
||||
|
||||
This tells you the current file size, the percentage of the transfer that
|
||||
is complete, the current calculated file-completion rate (including both
|
||||
data over the wire and data being matched locally), and the estimated time
|
||||
remaining in this transfer.
|
||||
|
||||
After the a file is complete, it the data looks like this:
|
||||
|
||||
verb(
|
||||
1238099 100% 146.38kB/s 0:00:08 (5, 57.1% of 396)
|
||||
)
|
||||
|
||||
This tells you the final file size, that it's 100% complete, the final
|
||||
transfer rate for the file, the amount of elapsed time it took to transfer
|
||||
the file, and the addition of a total-transfer summary in parentheses.
|
||||
These additional numbers tell you how many files have been updated, and
|
||||
what percent of the total number of files has been scanned.
|
||||
|
||||
dit(bf(-P)) The -P option is equivalent to --partial --progress. I
|
||||
found myself typing that combination quite often so I created an
|
||||
option to make it easier.
|
||||
|
||||
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
|
||||
is only useful when accessing a rsync server 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.
|
||||
@@ -886,7 +855,7 @@ transfer rate in kilobytes per second. This option is most effective when
|
||||
using rsync with large files (several megabytes and up). Due to the nature
|
||||
of rsync transfers, blocks of data are sent, then if rsync determines the
|
||||
transfer was too fast, it will wait before sending the next data block. The
|
||||
result is an average transfer rate equaling the specified limit. A value
|
||||
result is an average transfer rate equalling the specified limit. A value
|
||||
of zero specifies no limit.
|
||||
|
||||
dit(bf(--write-batch=PREFIX)) Generate a set of files that can be
|
||||
@@ -904,7 +873,7 @@ manpagesection(EXCLUDE PATTERNS)
|
||||
The exclude and include patterns specified to rsync allow for flexible
|
||||
selection of which files to transfer and which files to skip.
|
||||
|
||||
Rsync builds an ordered list of include/exclude options as specified on
|
||||
rsync builds an ordered list of include/exclude options as specified on
|
||||
the command line. Rsync checks each file and directory
|
||||
name against each exclude/include pattern in turn. The first matching
|
||||
pattern is acted on. If it is an exclude pattern, then that file is
|
||||
@@ -912,61 +881,16 @@ skipped. If it is an include pattern then that filename is not
|
||||
skipped. If no matching include/exclude pattern is found then the
|
||||
filename is not skipped.
|
||||
|
||||
The filenames matched against the exclude/include patterns are relative
|
||||
to the "root of the transfer". If you think of the transfer as a
|
||||
subtree of names that are being sent from sender to receiver, the root
|
||||
is where the tree starts to be duplicated in the destination directory.
|
||||
This root governs where patterns that start with a / match (see below).
|
||||
The filenames matched against the exclude/include patterns
|
||||
are relative to the destination directory, or "top
|
||||
directory", so patterns should not include the path elements
|
||||
of the source or destination directories. The only way in
|
||||
which a pattern will match the absolute path of a file or
|
||||
directory is if the source path is the root directory.
|
||||
|
||||
Because the matching is relative to the transfer-root, changing the
|
||||
trailing slash on a source path or changing your use of the --relative
|
||||
option affects the path you need to use in your matching (in addition to
|
||||
changing how much of the file tree is duplicated on the destination
|
||||
system). The following examples demonstrate this.
|
||||
|
||||
Let's say that we want to match two source files, one with an absolute
|
||||
path of "/home/me/foo/bar", and one with a path of "/home/you/bar/baz".
|
||||
Here is how the various command choices differ for a 2-source transfer:
|
||||
|
||||
verb(
|
||||
Example cmd: rsync -a /home/me /home/you /dest
|
||||
+/- pattern: /me/foo/bar
|
||||
+/- pattern: /you/bar/baz
|
||||
Target file: /dest/me/foo/bar
|
||||
Target file: /dest/you/bar/baz
|
||||
|
||||
Example cmd: rsync -a /home/me/ /home/you/ /dest
|
||||
+/- pattern: /foo/bar (note missing "me")
|
||||
+/- pattern: /bar/baz (note missing "you")
|
||||
Target file: /dest/foo/bar
|
||||
Target file: /dest/bar/baz
|
||||
|
||||
Example cmd: rsync -a --relative /home/me/ /home/you /dest
|
||||
+/- pattern: /home/me/foo/bar (note full path)
|
||||
+/- pattern: /home/you/bar/baz (ditto)
|
||||
Target file: /dest/home/me/foo/bar
|
||||
Target file: /dest/home/you/bar/baz
|
||||
|
||||
Example cmd: cd /home; rsync -a --relative me/foo you/ /dest
|
||||
+/- pattern: /me/foo/bar (starts at specified path)
|
||||
+/- pattern: /you/bar/baz (ditto)
|
||||
Target file: /dest/me/foo/bar
|
||||
Target file: /dest/you/bar/baz
|
||||
)
|
||||
|
||||
The easiest way to see what name you should include/exclude is to just
|
||||
look at the output when using --verbose and put a / in front of the name
|
||||
(use the --dry-run option if you're not yet ready to copy any files).
|
||||
|
||||
Note that, when using the --recursive (-r) option (which is implied by -a),
|
||||
every subcomponent of
|
||||
every path is visited from the top down, so include/exclude patterns get
|
||||
Note that when used with -r (which is implied by -a), every subcomponent of
|
||||
every path is visited from top down, so include/exclude patterns get
|
||||
applied recursively to each subcomponent.
|
||||
The exclude patterns actually short-circuit the directory traversal stage
|
||||
when rsync finds the files to send. If a pattern excludes a particular
|
||||
parent directory, it can render a deeper include pattern ineffectual
|
||||
because rsync did not descend through that excluded section of the
|
||||
hierarchy.
|
||||
|
||||
Note also that the --include and --exclude options take one pattern
|
||||
each. To add multiple patterns use the --include-from and
|
||||
@@ -980,15 +904,16 @@ itemize(
|
||||
start of the filename, otherwise it is matched against the end of
|
||||
the filename.
|
||||
This is the equivalent of a leading ^ in regular expressions.
|
||||
Thus "/foo" would match a file called "foo" at the transfer-root
|
||||
(see above for how this is different from the filesystem-root).
|
||||
Thus "/foo" would match a file called "foo" at the top of the
|
||||
transferred tree.
|
||||
On the other hand, "foo" would match any file called "foo"
|
||||
anywhere in the tree because the algorithm is applied recursively from
|
||||
top down; it behaves as if each path component gets a turn at being the
|
||||
end of the file name.
|
||||
The leading / does not make the pattern an absolute pathname.
|
||||
|
||||
it() if the pattern ends with a / then it will only match a
|
||||
directory, not a file, link, or device.
|
||||
directory, not a file, link or device.
|
||||
|
||||
it() if the pattern contains a wildcard character from the set
|
||||
*?[ then expression matching is applied using the shell filename
|
||||
@@ -1006,11 +931,11 @@ itemize(
|
||||
|
||||
it() if the pattern starts with "+ " (a plus followed by a space)
|
||||
then it is always considered an include pattern, even if specified as
|
||||
part of an exclude option. The prefix is discarded before matching.
|
||||
part of an exclude option. The "+ " part is discarded before matching.
|
||||
|
||||
it() if the pattern starts with "- " (a minus followed by a space)
|
||||
then it is always considered an exclude pattern, even if specified as
|
||||
part of an include option. The prefix is discarded before matching.
|
||||
part of an include option. The "- " part is discarded before matching.
|
||||
|
||||
it() if the pattern is a single exclamation mark ! then the current
|
||||
include/exclude list is reset, removing all previously defined patterns.
|
||||
@@ -1018,45 +943,25 @@ itemize(
|
||||
|
||||
The +/- rules are most useful in a list that was read from a file, allowing
|
||||
you to have a single exclude list that contains both include and exclude
|
||||
options in the proper order.
|
||||
options.
|
||||
|
||||
Remember that the matching occurs at every step in the traversal of the
|
||||
directory hierarchy, so you must be sure that all the parent directories of
|
||||
the files you want to include are not excluded. This is particularly
|
||||
important when using a trailing '*' rule. For instance, this won't work:
|
||||
If you end an exclude list with --exclude '*', note that since the
|
||||
algorithm is applied recursively that unless you explicitly include
|
||||
parent directories of files you want to include then the algorithm
|
||||
will stop at the parent directories and never see the files below
|
||||
them. To include all directories, use --include '*/' before the
|
||||
--exclude '*'.
|
||||
|
||||
verb(
|
||||
+ /some/path/this-file-will-not-be-found
|
||||
+ /file-is-included
|
||||
- *
|
||||
)
|
||||
|
||||
This fails because the parent directory "some" is excluded by the '*' rule,
|
||||
so rsync never visits any of the files in the "some" or "some/path"
|
||||
directories. One solution is to ask for all directories in the hierarchy
|
||||
to be included by using a single rule: --include='*/' (put it somewhere
|
||||
before the --excludde='*' rule). Another solution is to add specific
|
||||
include rules for all the parent dirs that need to be visited. For
|
||||
instance, this set of rules works fine:
|
||||
|
||||
verb(
|
||||
+ /some/
|
||||
+ /some/path/
|
||||
+ /some/path/this-file-is-found
|
||||
+ /file-also-included
|
||||
- *
|
||||
)
|
||||
|
||||
Here are some examples of exclude/include matching:
|
||||
Here are some exclude/include examples:
|
||||
|
||||
itemize(
|
||||
it() --exclude "*.o" would exclude all filenames matching *.o
|
||||
it() --exclude "/foo" would exclude a file called foo in the transfer-root directory
|
||||
it() --exclude "/foo" would exclude a file called foo in the top directory
|
||||
it() --exclude "foo/" would exclude any directory called foo
|
||||
it() --exclude "/foo/*/bar" would exclude any file called bar two
|
||||
levels below a directory called foo in the transfer-root directory
|
||||
levels below a directory called foo in the top directory
|
||||
it() --exclude "/foo/**/bar" would exclude any file called bar two
|
||||
or more levels below a directory called foo in the transfer-root directory
|
||||
or more levels below a directory called foo in the top directory
|
||||
it() --include "*/" --include "*.c" --exclude "*" would include all
|
||||
directories and C source files
|
||||
it() --include "foo/" --include "foo/bar.c" --exclude "*" would include
|
||||
@@ -1110,11 +1015,11 @@ once, instead of sending the same data to every host individually.
|
||||
Example:
|
||||
|
||||
verb(
|
||||
$ rsync --write-batch=pfx -a /source/dir/ /adest/dir/
|
||||
$ rcp pfx.rsync_* remote:
|
||||
$ ssh remote rsync --read-batch=pfx -a /bdest/dir/
|
||||
# or alternatively
|
||||
$ ssh remote ./pfx.rsync_argvs /bdest/dir/
|
||||
$ rsync --write-batch=pfx -a /source/dir/ /adest/dir/
|
||||
$ rcp pfx.rsync_* remote:
|
||||
$ rsh remote rsync --read-batch=pfx -a /bdest/dir/
|
||||
# or alternatively
|
||||
$ rsh remote ./pfx.rsync_argvs /bdest/dir/
|
||||
)
|
||||
|
||||
In this example, rsync is used to update /adest/dir/ with /source/dir/
|
||||
@@ -1168,7 +1073,7 @@ 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 ommitted altogether.
|
||||
|
||||
Symbolic links are considered unsafe if they are absolute symlinks
|
||||
(start with bf(/)), empty, or if they contain enough bf("..")
|
||||
@@ -1186,7 +1091,7 @@ for its transport. The way to diagnose this problem is to run your
|
||||
remote shell like this:
|
||||
|
||||
verb(
|
||||
ssh remotehost /bin/true > out.dat
|
||||
rsh remotehost /bin/true > out.dat
|
||||
)
|
||||
|
||||
then look at out.dat. If everything is working correctly then out.dat
|
||||
@@ -1210,19 +1115,18 @@ dit(bf(2)) Protocol incompatibility
|
||||
dit(bf(3)) Errors selecting input/output files, dirs
|
||||
dit(bf(4)) Requested action not supported: an attempt
|
||||
was made to manipulate 64-bit files on a platform that cannot support
|
||||
them; or an option was specifed that is supported by the client and
|
||||
them; or an option was speciifed that is supported by the client and
|
||||
not by the server.
|
||||
dit(bf(5)) Error starting client-server protocol
|
||||
dit(bf(10)) Error in socket I/O
|
||||
dit(bf(11)) Error in file I/O
|
||||
dit(bf(10)) Error in socket IO
|
||||
dit(bf(11)) Error in file IO
|
||||
dit(bf(12)) Error in rsync protocol data stream
|
||||
dit(bf(13)) Errors with program diagnostics
|
||||
dit(bf(14)) Error in IPC code
|
||||
dit(bf(20)) Received SIGUSR1 or SIGINT
|
||||
dit(bf(21)) Some error returned by waitpid()
|
||||
dit(bf(22)) Error allocating core memory buffers
|
||||
dit(bf(23)) Partial transfer due to error
|
||||
dit(bf(24)) Partial transfer due to vanished source files
|
||||
dit(bf(23)) Partial transfer
|
||||
dit(bf(30)) Timeout in data send/receive
|
||||
enddit()
|
||||
|
||||
@@ -1243,13 +1147,12 @@ redirect your rsync client to use a web proxy when connecting to a
|
||||
rsync daemon. You should set RSYNC_PROXY to a hostname:port pair.
|
||||
|
||||
dit(bf(RSYNC_PASSWORD)) Setting RSYNC_PASSWORD to the required
|
||||
password allows you to run authenticated rsync connections to an rsync
|
||||
password allows you to run authenticated rsync connections to a 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.
|
||||
If neither is set, the username defaults to "nobody".
|
||||
are used to determine the default username sent to a rsync server.
|
||||
|
||||
dit(bf(HOME)) The HOME environment variable is used to find the user's
|
||||
default .cvsignore file.
|
||||
@@ -1270,11 +1173,11 @@ manpagebugs()
|
||||
|
||||
times are transferred as unix time_t values
|
||||
|
||||
When transferring to FAT filesystems rsync may resync
|
||||
When transferring to FAT filesystmes rsync may resync
|
||||
unmodified files.
|
||||
See the comments on the --modify-window option.
|
||||
|
||||
file permissions, devices, etc. are transferred as native numerical
|
||||
file permissions, devices etc are transferred as native numerical
|
||||
values
|
||||
|
||||
see also the comments on the --delete option
|
||||
@@ -1306,13 +1209,19 @@ Thanks to Richard Brent, Brendan Mackay, Bill Waite, Stephen Rothwell
|
||||
and David Bell for helpful suggestions, patches and testing of rsync.
|
||||
I've probably missed some people, my apologies if I have.
|
||||
|
||||
Especial thanks also to: David Dykstra, Jos Backus, Sebastian Krahmer,
|
||||
Martin Pool, Wayne Davison.
|
||||
Especial thanks also to: David Dykstra, Jos Backus, Sebastian Krahmer.
|
||||
|
||||
|
||||
manpageauthor()
|
||||
|
||||
rsync was originally written by Andrew Tridgell and Paul Mackerras.
|
||||
Many people have later contributed to it.
|
||||
rsync was written by Andrew Tridgell <tridge@samba.org> and Paul
|
||||
Mackerras.
|
||||
|
||||
rsync is now maintained by Martin Pool <mbp@samba.org>.
|
||||
|
||||
Mailing lists for support and development are available at
|
||||
url(http://lists.samba.org)(lists.samba.org)
|
||||
|
||||
If you suspect you have found a security vulnerability in rsync,
|
||||
please send it directly to Martin Pool and Andrew Tridgell. For other
|
||||
enquiries, please use the mailing list.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
mailto(rsync-bugs@samba.org)
|
||||
manpage(rsyncd.conf)(5)(26 Apr 2004)()()
|
||||
manpage(rsyncd.conf)(5)(26 Jan 2003)()()
|
||||
manpagename(rsyncd.conf)(configuration file for rsync server)
|
||||
manpagesynopsis()
|
||||
|
||||
@@ -93,7 +93,7 @@ useful on systems (such as AIX) where syslog() doesn't work for
|
||||
chrooted programs.
|
||||
|
||||
dit(bf(pid file)) The "pid file" option tells the rsync daemon to write
|
||||
its process ID to that file.
|
||||
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
|
||||
@@ -135,31 +135,11 @@ 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,
|
||||
of not being able to follow symbolic links outside of the new root path
|
||||
when reading, and of complicating the preservation of usernames and groups
|
||||
(see below). When "use chroot" is false, for security reasons,
|
||||
when reading, and of implying the --numeric-ids option because /etc/passwd
|
||||
becomes inaccessible. When "use chroot" is false, for security reasons
|
||||
symlinks may only be relative paths pointing to other files within the root
|
||||
path, and leading slashes are removed from most absolute paths (options
|
||||
such as --backup-dir, --compare-dest, etc. interpret an absolute path as
|
||||
rooted in the module's "path" dir, just as if chroot was specified).
|
||||
The default for "use chroot" is true.
|
||||
|
||||
In order to preserve usernames and groupnames, rsync needs to be able to
|
||||
use the standard library functions for looking up names and IDs (i.e.
|
||||
getpwuid(), getgrgid(), getpwname(), and getgrnam()). This means a
|
||||
process in the chroot namespace will need to have access to the resources
|
||||
used by these library functions (traditionally /etc/passwd and
|
||||
/etc/group). If these resources are not available, rsync will only be
|
||||
able to copy the IDs, just as if the --numeric-ids option had been
|
||||
specified.
|
||||
|
||||
Note that you are free to setup user/group information in the chroot area
|
||||
differently from your normal system. For example, you could abbreviate
|
||||
the list of users and groups. Also, you can protect this information
|
||||
from being downloaded by adding an exclude rule to the rsync.conf file
|
||||
(e.g. "exclude = /etc/"). To protect it from being changed by an upload
|
||||
(if the module is not read only), be sure to set the permissions (or
|
||||
owner) on the files and/or parent directories so that they cannot be
|
||||
written by the daemon.
|
||||
path, and leading slashes are removed from absolute paths. The default for
|
||||
"use chroot" is true.
|
||||
|
||||
dit(bf(max connections)) The "max connections" option allows you to
|
||||
specify the maximum number of simultaneous connections you will allow.
|
||||
@@ -184,13 +164,13 @@ listed when the client asks for a listing of available modules. By
|
||||
setting this to false you can create hidden modules. The default is
|
||||
for modules to be listable.
|
||||
|
||||
dit(bf(uid)) The "uid" option specifies the user name or user ID that
|
||||
dit(bf(uid)) The "uid" option specifies the user name or user id that
|
||||
file transfers to and from that module should take place as when the daemon
|
||||
was run as root. In combination with the "gid" option this determines what
|
||||
file permissions are available. The default is uid -2, which is normally
|
||||
the user "nobody".
|
||||
|
||||
dit(bf(gid)) The "gid" option specifies the group name or group ID that
|
||||
dit(bf(gid)) The "gid" option specifies the group name or group id that
|
||||
file transfers to and from that module should take place as when the daemon
|
||||
was run as root. This complements the "uid" option. The default is gid -2,
|
||||
which is normally the group "nobody".
|
||||
@@ -249,7 +229,7 @@ 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
|
||||
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 a rsync server.
|
||||
|
||||
dit(bf(secrets file)) The "secrets file" option specifies the name of
|
||||
a file that contains the username:password pairs used for
|
||||
@@ -267,7 +247,7 @@ by "other"; see "strict modes".
|
||||
|
||||
dit(bf(strict modes)) The "strict modes" option determines whether or not
|
||||
the permissions on the secrets file will be checked. If "strict modes" is
|
||||
true, then the secrets file must not be readable by any user ID other
|
||||
true, then the secrets file must not be readable by any user id other
|
||||
than the one that the rsync daemon is running under. If "strict modes" is
|
||||
false, the check is not performed. The default is true. This option
|
||||
was added to accommodate rsync running on the Windows operating system.
|
||||
@@ -326,10 +306,10 @@ 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 IO errors on the server when deciding whether to run the delete
|
||||
phase of the transfer. Normally rsync skips the --delete step if any
|
||||
I/O errors have occurred in order to prevent disasterous deletion due
|
||||
to a temporary resource shortage or other I/O error. In some cases this
|
||||
IO errors have occurred in order to prevent disasterous deletion due
|
||||
to a temporary resource shortage or other IO error. In some cases this
|
||||
test is counter productive so you can use this option to turn off this
|
||||
behaviour.
|
||||
|
||||
@@ -354,7 +334,7 @@ itemize(
|
||||
it() %h for the remote host name
|
||||
it() %a for the remote IP address
|
||||
it() %l for the length of the file in bytes
|
||||
it() %p for the process ID of this rsync session
|
||||
it() %p for the process id of this rsync session
|
||||
it() %o for the operation, which is either "send" or "recv"
|
||||
it() %f for the filename
|
||||
it() %P for the module path
|
||||
@@ -373,7 +353,7 @@ A perl script called rsyncstats to summarize this format is included
|
||||
in the rsync source code distribution.
|
||||
|
||||
dit(bf(timeout)) The "timeout" option allows you to override the
|
||||
clients choice for I/O timeout for this module. Using this option you
|
||||
clients choice for IO 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
|
||||
@@ -419,32 +399,6 @@ 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)
|
||||
|
||||
If rsync is run with both the --daemon and --rsh (-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.
|
||||
|
||||
ADVANCED: To run an rsync server 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
|
||||
|
||||
quote(rsync --server --daemon .)
|
||||
|
||||
NOTE: rsync's argument parsing expects the trailing ".", so make sure
|
||||
that it's there. If you want to use an rsyncd.conf(5)-style
|
||||
configuration file other than the default, you can added a
|
||||
--config option to the em(command):
|
||||
|
||||
quote(rsync --server --daemon --config=em(file) .)
|
||||
|
||||
Note that the "--server" here is the internal option that rsync uses to
|
||||
run the remote version of rsync that it communicates with, and thus you
|
||||
should not be using the --server option under normal circumstances.
|
||||
|
||||
manpagesection(EXAMPLES)
|
||||
|
||||
A simple rsyncd.conf file that allow anonymous rsync to a ftp area at
|
||||
@@ -514,7 +468,7 @@ 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.0 of rsync
|
||||
|
||||
manpagesection(CREDITS)
|
||||
|
||||
|
||||
@@ -142,7 +142,7 @@ echo "$0 running in `pwd`"
|
||||
echo " rsync_bin=$rsync_bin"
|
||||
echo " srcdir=$srcdir"
|
||||
|
||||
testuser=`id -un || whoami || echo UNKNOWN`
|
||||
testuser=`whoami || echo UNKNOWN`
|
||||
|
||||
echo " testuser=$testuser"
|
||||
echo " os=`uname -a`"
|
||||
@@ -220,11 +220,6 @@ do
|
||||
echo "----- $testbase log follows"
|
||||
cat "$scratchdir/test.log"
|
||||
echo "----- $testbase log ends"
|
||||
if [ -f "$scratchdir/rsyncd.log" ]; then
|
||||
echo "----- $testbase rsyncd.log follows"
|
||||
cat "$scratchdir/rsyncd.log"
|
||||
echo "----- $testbase rsyncd.log ends"
|
||||
fi
|
||||
fi
|
||||
|
||||
case $result in
|
||||
|
||||
301
sender.c
301
sender.c
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
/*
|
||||
Copyright (C) Andrew Tridgell 1996
|
||||
Copyright (C) Paul Mackerras 1996
|
||||
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
@@ -20,13 +20,12 @@
|
||||
#include "rsync.h"
|
||||
|
||||
extern int verbose;
|
||||
extern int remote_version;
|
||||
extern int csum_length;
|
||||
extern struct stats stats;
|
||||
extern int io_error;
|
||||
extern int dry_run;
|
||||
extern int am_server;
|
||||
extern int am_daemon;
|
||||
extern int protocol_version;
|
||||
|
||||
|
||||
/**
|
||||
@@ -36,22 +35,7 @@ extern int protocol_version;
|
||||
* and transmits them to the receiver. The sender process runs on the
|
||||
* machine holding the source files.
|
||||
**/
|
||||
void read_sum_head(int f, struct sum_struct *sum)
|
||||
{
|
||||
sum->count = read_int(f);
|
||||
sum->blength = read_int(f);
|
||||
if (protocol_version < 27) {
|
||||
sum->s2length = csum_length;
|
||||
} else {
|
||||
sum->s2length = read_int(f);
|
||||
if (sum->s2length > MD4_SUM_LENGTH) {
|
||||
rprintf(FERROR, "Invalid checksum length %ld\n",
|
||||
(long)sum->s2length);
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
}
|
||||
}
|
||||
sum->remainder = read_int(f);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Receive the checksums for a buffer
|
||||
@@ -65,24 +49,24 @@ static struct sum_struct *receive_sums(int f)
|
||||
s = new(struct sum_struct);
|
||||
if (!s) out_of_memory("receive_sums");
|
||||
|
||||
read_sum_head(f, s);
|
||||
|
||||
s->count = read_int(f);
|
||||
s->n = read_int(f);
|
||||
s->remainder = read_int(f);
|
||||
s->sums = NULL;
|
||||
|
||||
if (verbose > 3) {
|
||||
rprintf(FINFO, "count=%ld n=%u rem=%u\n",
|
||||
(long)s->count, s->blength, s->remainder);
|
||||
}
|
||||
if (verbose > 3)
|
||||
rprintf(FINFO,"count=%ld n=%ld rem=%ld\n",
|
||||
(long) s->count, (long) s->n, (long) s->remainder);
|
||||
|
||||
if (s->count == 0)
|
||||
if (s->count == 0)
|
||||
return(s);
|
||||
|
||||
s->sums = new_array(struct sum_buf, s->count);
|
||||
if (!s->sums) out_of_memory("receive_sums");
|
||||
|
||||
for (i = 0; i < (int) s->count; i++) {
|
||||
for (i=0; i < (int) s->count;i++) {
|
||||
s->sums[i].sum1 = read_int(f);
|
||||
read_buf(f, s->sums[i].sum2, s->s2length);
|
||||
read_buf(f,s->sums[i].sum2,csum_length);
|
||||
|
||||
s->sums[i].offset = offset;
|
||||
s->sums[i].i = i;
|
||||
@@ -90,13 +74,13 @@ static struct sum_struct *receive_sums(int f)
|
||||
if (i == (int) s->count-1 && s->remainder != 0) {
|
||||
s->sums[i].len = s->remainder;
|
||||
} else {
|
||||
s->sums[i].len = s->blength;
|
||||
s->sums[i].len = s->n;
|
||||
}
|
||||
offset += s->sums[i].len;
|
||||
|
||||
if (verbose > 3)
|
||||
rprintf(FINFO, "chunk[%d] len=%d offset=%.0f sum1=%08x\n",
|
||||
i, s->sums[i].len, (double)s->sums[i].offset, s->sums[i].sum1);
|
||||
rprintf(FINFO,"chunk[%d] len=%d offset=%.0f sum1=%08x\n",
|
||||
i,s->sums[i].len,(double)s->sums[i].offset,s->sums[i].sum1);
|
||||
}
|
||||
|
||||
s->flength = offset;
|
||||
@@ -106,74 +90,78 @@ static struct sum_struct *receive_sums(int f)
|
||||
|
||||
|
||||
|
||||
void send_files(struct file_list *flist, int f_out, int f_in)
|
||||
{
|
||||
void send_files(struct file_list *flist,int f_out,int f_in)
|
||||
{
|
||||
int fd = -1;
|
||||
struct sum_struct *s;
|
||||
struct map_struct *buf = NULL;
|
||||
STRUCT_STAT st;
|
||||
char fname[MAXPATHLEN];
|
||||
char fname[MAXPATHLEN];
|
||||
int i;
|
||||
struct file_struct *file;
|
||||
int phase = 0;
|
||||
extern struct stats stats;
|
||||
extern struct stats stats;
|
||||
struct stats initial_stats;
|
||||
extern int write_batch;
|
||||
extern int read_batch;
|
||||
int checksums_match;
|
||||
int buff_len;
|
||||
char buff[CHUNK_SIZE];
|
||||
int j;
|
||||
int done;
|
||||
extern int write_batch; /* dw */
|
||||
extern int read_batch; /* dw */
|
||||
int checksums_match; /* dw */
|
||||
int buff_len; /* dw */
|
||||
char buff[CHUNK_SIZE]; /* dw */
|
||||
int j; /* dw */
|
||||
int done; /* dw */
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO, "send_files starting\n");
|
||||
rprintf(FINFO,"send_files starting\n");
|
||||
|
||||
while (1) {
|
||||
unsigned int offset;
|
||||
int offset=0;
|
||||
|
||||
i = read_int(f_in);
|
||||
if (i == -1) {
|
||||
if (phase == 0) {
|
||||
if (phase==0 && remote_version >= 13) {
|
||||
phase++;
|
||||
csum_length = SUM_LENGTH;
|
||||
write_int(f_out, -1);
|
||||
write_int(f_out,-1);
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO, "send_files phase=%d\n", phase);
|
||||
rprintf(FINFO,"send_files phase=%d\n",phase);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (i < 0 || i >= flist->count) {
|
||||
rprintf(FERROR, "Invalid file index %d (count=%d)\n",
|
||||
rprintf(FERROR,"Invalid file index %d (count=%d)\n",
|
||||
i, flist->count);
|
||||
exit_cleanup(RERR_PROTOCOL);
|
||||
}
|
||||
|
||||
file = flist->files[i];
|
||||
|
||||
stats.current_file_index = i;
|
||||
stats.num_transferred_files++;
|
||||
stats.total_transferred_size += file->length;
|
||||
|
||||
fname[0] = 0;
|
||||
if (file->basedir) {
|
||||
/* N.B. We're sure that this fits, so offset is OK. */
|
||||
offset = strlcpy(fname, file->basedir, sizeof fname);
|
||||
if (!offset || fname[offset-1] != '/')
|
||||
fname[offset++] = '/';
|
||||
} else
|
||||
offset = 0;
|
||||
f_name_to(file, fname + offset);
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO, "send_files(%d, %s)\n", i, fname);
|
||||
|
||||
if (dry_run) {
|
||||
if (!am_server && verbose) { /* log transfer */
|
||||
rprintf(FINFO, "%s\n", fname+offset);
|
||||
strlcpy(fname,file->basedir,MAXPATHLEN);
|
||||
if (strlen(fname) == MAXPATHLEN-1) {
|
||||
io_error = 1;
|
||||
rprintf(FERROR, "send_files failed on long-named directory %s\n",
|
||||
fname);
|
||||
return;
|
||||
}
|
||||
write_int(f_out, i);
|
||||
strlcat(fname,"/",MAXPATHLEN);
|
||||
offset = strlen(file->basedir)+1;
|
||||
}
|
||||
strlcat(fname,f_name(file),MAXPATHLEN);
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"send_files(%d,%s)\n",i,fname);
|
||||
|
||||
if (dry_run) {
|
||||
if (!am_server) {
|
||||
log_transfer(file, fname+offset);
|
||||
}
|
||||
write_int(f_out,i);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -181,138 +169,129 @@ void send_files(struct file_list *flist, int f_out, int f_in)
|
||||
|
||||
s = receive_sums(f_in);
|
||||
if (!s) {
|
||||
io_error |= IOERR_GENERAL;
|
||||
rprintf(FERROR, "receive_sums failed\n");
|
||||
io_error = 1;
|
||||
rprintf(FERROR,"receive_sums failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (write_batch)
|
||||
write_batch_csum_info(&i, s);
|
||||
|
||||
write_batch_csum_info(&i,flist->count,s);
|
||||
|
||||
if (!read_batch) {
|
||||
fd = do_open(fname, O_RDONLY, 0);
|
||||
if (fd == -1) {
|
||||
if (errno == ENOENT) {
|
||||
enum logcode c = am_daemon
|
||||
&& protocol_version < 28 ? FERROR
|
||||
: FINFO;
|
||||
io_error |= IOERR_VANISHED;
|
||||
rprintf(c, "file has vanished: %s\n",
|
||||
full_fname(fname));
|
||||
} else {
|
||||
io_error |= IOERR_GENERAL;
|
||||
rprintf(FERROR, "send_files failed to open %s: %s\n",
|
||||
full_fname(fname), strerror(errno));
|
||||
}
|
||||
io_error = 1;
|
||||
rprintf(FERROR,"send_files failed to open %s: %s\n",
|
||||
fname,strerror(errno));
|
||||
free_sums(s);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
/* map the local file */
|
||||
if (do_fstat(fd, &st) != 0) {
|
||||
io_error |= IOERR_GENERAL;
|
||||
rprintf(FERROR, "fstat failed: %s\n", strerror(errno));
|
||||
if (do_fstat(fd,&st) != 0) {
|
||||
io_error = 1;
|
||||
rprintf(FERROR,"fstat failed : %s\n",strerror(errno));
|
||||
free_sums(s);
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (st.st_size > 0) {
|
||||
buf = map_file(fd, st.st_size);
|
||||
buf = map_file(fd,st.st_size);
|
||||
} else {
|
||||
buf = NULL;
|
||||
}
|
||||
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO, "send_files mapped %s of size %.0f\n",
|
||||
fname, (double)st.st_size);
|
||||
|
||||
write_int(f_out, i);
|
||||
rprintf(FINFO,"send_files mapped %s of size %.0f\n",
|
||||
fname,(double)st.st_size);
|
||||
|
||||
write_int(f_out,i);
|
||||
|
||||
if (write_batch)
|
||||
write_batch_delta_file((char *)&i, sizeof i);
|
||||
write_batch_delta_file((char *)&i,sizeof(i));
|
||||
|
||||
write_sum_head(f_out, s);
|
||||
write_int(f_out,s->count);
|
||||
write_int(f_out,s->n);
|
||||
write_int(f_out,s->remainder);
|
||||
}
|
||||
|
||||
if (verbose > 2 && !read_batch)
|
||||
rprintf(FINFO, "calling match_sums %s\n", fname);
|
||||
|
||||
if (!am_server && verbose) { /* log transfer */
|
||||
rprintf(FINFO, "%s\n", fname+offset);
|
||||
|
||||
if (verbose > 2)
|
||||
if (!read_batch)
|
||||
rprintf(FINFO,"calling match_sums %s\n",fname);
|
||||
|
||||
if (!am_server) {
|
||||
log_transfer(file, fname+offset);
|
||||
}
|
||||
|
||||
set_compression(fname);
|
||||
|
||||
if (read_batch) {
|
||||
/* read checksums originally computed on sender side */
|
||||
read_batch_csum_info(i, s, &checksums_match);
|
||||
if (checksums_match) {
|
||||
read_batch_delta_file((char*)&j, sizeof (int));
|
||||
if (j != i) { /* if flist index entries don't match*/
|
||||
rprintf(FINFO, "index mismatch in send_files\n");
|
||||
rprintf(FINFO, "read index = %d flist ndx = %d\n", j, i);
|
||||
close_batch_delta_file();
|
||||
close_batch_csums_file();
|
||||
exit_cleanup(1);
|
||||
} else {
|
||||
write_int(f_out, j);
|
||||
write_sum_head(f_out, s);
|
||||
done = 0;
|
||||
while (!done) {
|
||||
read_batch_delta_file((char*)&buff_len, sizeof (int));
|
||||
write_int(f_out, buff_len);
|
||||
if (buff_len == 0) {
|
||||
done = 1;
|
||||
} else {
|
||||
if (buff_len > 0) {
|
||||
read_batch_delta_file(buff, buff_len);
|
||||
write_buf(f_out, buff, buff_len);
|
||||
}
|
||||
}
|
||||
} /* end while */
|
||||
read_batch_delta_file( buff, MD4_SUM_LENGTH);
|
||||
write_buf(f_out, buff, MD4_SUM_LENGTH);
|
||||
if (read_batch) { /* dw */
|
||||
/* read checksums originally computed on sender side */
|
||||
read_batch_csum_info(i, s, &checksums_match);
|
||||
if (checksums_match) {
|
||||
read_batch_delta_file( (char *) &j, sizeof(int) );
|
||||
if (j != i) { /* if flist index entries don't match*/
|
||||
rprintf(FINFO,"index mismatch in send_files\n");
|
||||
rprintf(FINFO,"read index = %d flist ndx = %d\n",j,i);
|
||||
close_batch_delta_file();
|
||||
close_batch_csums_file();
|
||||
exit_cleanup(1);
|
||||
}
|
||||
else {
|
||||
write_int(f_out,j);
|
||||
write_int(f_out,s->count);
|
||||
write_int(f_out,s->n);
|
||||
write_int(f_out,s->remainder);
|
||||
done=0;
|
||||
while (!done) {
|
||||
read_batch_delta_file( (char *) &buff_len, sizeof(int) );
|
||||
write_int(f_out,buff_len);
|
||||
if (buff_len == 0) {
|
||||
done = 1;
|
||||
}
|
||||
else {
|
||||
if (buff_len > 0) {
|
||||
read_batch_delta_file(buff, buff_len);
|
||||
write_buf(f_out,buff,buff_len);
|
||||
}
|
||||
}
|
||||
} /* end while */
|
||||
read_batch_delta_file( buff, MD4_SUM_LENGTH);
|
||||
write_buf(f_out, buff, MD4_SUM_LENGTH);
|
||||
|
||||
} /* j=i */
|
||||
} else { /* not checksum match */
|
||||
rprintf (FINFO, "readbatch & checksums don't match\n");
|
||||
rprintf (FINFO, "filename=%s is being skipped\n", fname);
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
match_sums(f_out, s, buf, st.st_size);
|
||||
log_send(file, &initial_stats);
|
||||
} /* j=i */
|
||||
} else { /* not checksum match */
|
||||
rprintf (FINFO,"readbatch & checksums don't match\n");
|
||||
rprintf (FINFO,"filename=%s is being skipped\n",
|
||||
fname);
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
match_sums(f_out,s,buf,st.st_size);
|
||||
log_send(file, &initial_stats);
|
||||
}
|
||||
|
||||
if (!read_batch) { /* dw */
|
||||
if (buf) unmap_file(buf);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
if (!read_batch) {
|
||||
if (buf) {
|
||||
j = unmap_file(buf);
|
||||
if (j) {
|
||||
io_error |= IOERR_GENERAL;
|
||||
rprintf(FERROR,
|
||||
"read errors mapping %s: (%d) %s\n",
|
||||
full_fname(fname), j, strerror(j));
|
||||
}
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
|
||||
|
||||
free_sums(s);
|
||||
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO, "sender finished %s\n", fname);
|
||||
rprintf(FINFO,"sender finished %s\n",fname);
|
||||
}
|
||||
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO, "send files finished\n");
|
||||
rprintf(FINFO,"send files finished\n");
|
||||
|
||||
match_report();
|
||||
|
||||
write_int(f_out, -1);
|
||||
if (write_batch || read_batch) {
|
||||
close_batch_csums_file();
|
||||
close_batch_delta_file();
|
||||
write_int(f_out,-1);
|
||||
if (write_batch || read_batch) { /* dw */
|
||||
close_batch_csums_file();
|
||||
close_batch_delta_file();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
434
socket.c
434
socket.c
@@ -1,20 +1,20 @@
|
||||
/* -*- c-file-style: "linux" -*-
|
||||
|
||||
|
||||
rsync -- fast file replication program
|
||||
|
||||
|
||||
Copyright (C) 1992-2001 by Andrew Tridgell <tridge@samba.org>
|
||||
Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
|
||||
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
/**
|
||||
* @file socket.c
|
||||
*
|
||||
*
|
||||
* Socket functions used in rsync.
|
||||
*
|
||||
* This file is now converted to use the new-style getaddrinfo()
|
||||
@@ -36,45 +36,21 @@
|
||||
|
||||
/**
|
||||
* Establish a proxy connection on an open socket to a web proxy by
|
||||
* using the CONNECT method. If proxy_user and proxy_pass are not NULL,
|
||||
* they are used to authenticate to the proxy using the "Basic"
|
||||
* proxy-authorization protocol
|
||||
* using the HTTP CONNECT method.
|
||||
**/
|
||||
static int establish_proxy_connection(int fd, char *host, int port,
|
||||
char *proxy_user, char *proxy_pass)
|
||||
static int establish_proxy_connection(int fd, char *host, int port)
|
||||
{
|
||||
char *cp, buffer[1024];
|
||||
char *authhdr, authbuf[1024];
|
||||
int len;
|
||||
char buffer[1024];
|
||||
char *cp;
|
||||
|
||||
if (proxy_user && proxy_pass) {
|
||||
stringjoin(buffer, sizeof buffer,
|
||||
proxy_user, ":", proxy_pass, NULL);
|
||||
len = strlen(buffer);
|
||||
|
||||
if ((len*8 + 5) / 6 >= (int)sizeof authbuf) {
|
||||
rprintf(FERROR,
|
||||
"authentication information is too long\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
base64_encode(buffer, len, authbuf);
|
||||
authhdr = "\r\nProxy-Authorization: Basic ";
|
||||
} else {
|
||||
*authbuf = '\0';
|
||||
authhdr = "";
|
||||
}
|
||||
|
||||
snprintf(buffer, sizeof buffer, "CONNECT %s:%d HTTP/1.0%s%s\r\n\r\n",
|
||||
host, port, authhdr, authbuf);
|
||||
len = strlen(buffer);
|
||||
if (write(fd, buffer, len) != len) {
|
||||
snprintf(buffer, sizeof(buffer), "CONNECT %s:%d HTTP/1.0\r\n\r\n", host, port);
|
||||
if (write(fd, buffer, strlen(buffer)) != (int) strlen(buffer)) {
|
||||
rprintf(FERROR, "failed to write to proxy: %s\n",
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (cp = buffer; cp < &buffer[sizeof buffer - 1]; cp++) {
|
||||
for (cp = buffer; cp < &buffer[sizeof(buffer) - 1]; cp++) {
|
||||
if (read(fd, cp, 1) != 1) {
|
||||
rprintf(FERROR, "failed to read from proxy: %s\n",
|
||||
strerror(errno));
|
||||
@@ -94,7 +70,8 @@ static int establish_proxy_connection(int fd, char *host, int port,
|
||||
buffer);
|
||||
return -1;
|
||||
}
|
||||
for (cp = &buffer[5]; isdigit(*(uchar*)cp) || *cp == '.'; cp++) {}
|
||||
for (cp = &buffer[5]; isdigit(* (unsigned char *) cp) || (*cp == '.'); cp++)
|
||||
;
|
||||
while (*cp == ' ')
|
||||
cp++;
|
||||
if (*cp != '2') {
|
||||
@@ -104,7 +81,8 @@ static int establish_proxy_connection(int fd, char *host, int port,
|
||||
}
|
||||
/* throw away the rest of the HTTP header */
|
||||
while (1) {
|
||||
for (cp = buffer; cp < &buffer[sizeof buffer - 1]; cp++) {
|
||||
for (cp = buffer; cp < &buffer[sizeof(buffer) - 1];
|
||||
cp++) {
|
||||
if (read(fd, cp, 1) != 1) {
|
||||
rprintf(FERROR, "failed to read from proxy: %s\n",
|
||||
strerror(errno));
|
||||
@@ -113,9 +91,9 @@ static int establish_proxy_connection(int fd, char *host, int port,
|
||||
if (*cp == '\n')
|
||||
break;
|
||||
}
|
||||
if (cp > buffer && *cp == '\n')
|
||||
if ((cp > buffer) && (*cp == '\n'))
|
||||
cp--;
|
||||
if (cp == buffer && (*cp == '\n' || *cp == '\r'))
|
||||
if ((cp == buffer) && ((*cp == '\n') || (*cp == '\r')))
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
@@ -126,13 +104,14 @@ static int establish_proxy_connection(int fd, char *host, int port,
|
||||
* Try to set the local address for a newly-created socket. Return -1
|
||||
* if this fails.
|
||||
**/
|
||||
int try_bind_local(int s, int ai_family, int ai_socktype,
|
||||
int try_bind_local(int s,
|
||||
int ai_family, int ai_socktype,
|
||||
const char *bind_address)
|
||||
{
|
||||
int error;
|
||||
struct addrinfo bhints, *bres_all, *r;
|
||||
|
||||
memset(&bhints, 0, sizeof bhints);
|
||||
memset(&bhints, 0, sizeof(bhints));
|
||||
bhints.ai_family = ai_family;
|
||||
bhints.ai_socktype = ai_socktype;
|
||||
bhints.ai_flags = AI_PASSIVE;
|
||||
@@ -181,59 +160,42 @@ int open_socket_out(char *host, int port, const char *bind_address,
|
||||
int af_hint)
|
||||
{
|
||||
int type = SOCK_STREAM;
|
||||
int error, s;
|
||||
int error;
|
||||
int s;
|
||||
struct addrinfo hints, *res0, *res;
|
||||
char portbuf[10];
|
||||
char *h, *cp;
|
||||
char *h;
|
||||
int proxied = 0;
|
||||
char buffer[1024];
|
||||
char *proxy_user = NULL, *proxy_pass = NULL;
|
||||
char *cp;
|
||||
|
||||
/* if we have a RSYNC_PROXY env variable then redirect our
|
||||
* connetcion via a web proxy at the given address. */
|
||||
* connetcion via a web proxy at the given address. The format
|
||||
* is hostname:port */
|
||||
h = getenv("RSYNC_PROXY");
|
||||
proxied = h != NULL && *h != '\0';
|
||||
proxied = (h != NULL) && (*h != '\0');
|
||||
|
||||
if (proxied) {
|
||||
strlcpy(buffer, h, sizeof buffer);
|
||||
|
||||
/* Is the USER:PASS@ prefix present? */
|
||||
if ((cp = strchr(buffer, '@')) != NULL) {
|
||||
*cp++ = '\0';
|
||||
/* The remainder is the HOST:PORT part. */
|
||||
h = cp;
|
||||
|
||||
if ((cp = strchr(buffer, ':')) == NULL) {
|
||||
rprintf(FERROR,
|
||||
"invalid proxy specification: should be USER:PASS@HOST:PORT\n");
|
||||
return -1;
|
||||
}
|
||||
*cp++ = '\0';
|
||||
|
||||
proxy_user = buffer;
|
||||
proxy_pass = cp;
|
||||
} else {
|
||||
/* The whole buffer is the HOST:PORT part. */
|
||||
h = buffer;
|
||||
}
|
||||
|
||||
if ((cp = strchr(h, ':')) == NULL) {
|
||||
strlcpy(buffer, h, sizeof(buffer));
|
||||
cp = strchr(buffer, ':');
|
||||
if (cp == NULL) {
|
||||
rprintf(FERROR,
|
||||
"invalid proxy specification: should be HOST:PORT\n");
|
||||
return -1;
|
||||
}
|
||||
*cp++ = '\0';
|
||||
strlcpy(portbuf, cp, sizeof portbuf);
|
||||
strcpy(portbuf, cp);
|
||||
h = buffer;
|
||||
if (verbose >= 2) {
|
||||
rprintf(FINFO, "connection via http proxy %s port %s\n",
|
||||
h, portbuf);
|
||||
}
|
||||
} else {
|
||||
snprintf(portbuf, sizeof portbuf, "%d", port);
|
||||
snprintf(portbuf, sizeof(portbuf), "%d", port);
|
||||
h = host;
|
||||
}
|
||||
|
||||
memset(&hints, 0, sizeof hints);
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = af_hint;
|
||||
hints.ai_socktype = type;
|
||||
error = getaddrinfo(h, portbuf, &hints, &res0);
|
||||
@@ -253,26 +215,26 @@ int open_socket_out(char *host, int port, const char *bind_address,
|
||||
if (s < 0)
|
||||
continue;
|
||||
|
||||
if (bind_address
|
||||
&& try_bind_local(s, res->ai_family, type,
|
||||
bind_address) == -1) {
|
||||
close(s);
|
||||
s = -1;
|
||||
continue;
|
||||
}
|
||||
if (bind_address)
|
||||
if (try_bind_local(s, res->ai_family, type,
|
||||
bind_address) == -1) {
|
||||
close(s);
|
||||
s = -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (connect(s, res->ai_addr, res->ai_addrlen) < 0) {
|
||||
close(s);
|
||||
s = -1;
|
||||
continue;
|
||||
}
|
||||
if (proxied
|
||||
&& establish_proxy_connection(s, host, port,
|
||||
proxy_user, proxy_pass) != 0) {
|
||||
if (proxied &&
|
||||
establish_proxy_connection(s, host, port) != 0) {
|
||||
close(s);
|
||||
s = -1;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
freeaddrinfo(res0);
|
||||
if (s < 0) {
|
||||
@@ -296,19 +258,18 @@ int open_socket_out(char *host, int port, const char *bind_address,
|
||||
*
|
||||
* @param bind_address 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 af_hint)
|
||||
int open_socket_out_wrapped (char *host,
|
||||
int port,
|
||||
const char *bind_address,
|
||||
int af_hint)
|
||||
{
|
||||
char *prog = getenv("RSYNC_CONNECT_PROG");
|
||||
char *prog;
|
||||
|
||||
if (verbose >= 2) {
|
||||
rprintf(FINFO, "%sopening tcp connection to %s port %d\n",
|
||||
prog ? "Using RSYNC_CONNECT_PROG instead of " : "",
|
||||
host, port);
|
||||
}
|
||||
if (prog)
|
||||
return sock_exec(prog);
|
||||
return open_socket_out(host, port, bind_address, af_hint);
|
||||
if ((prog = getenv ("RSYNC_CONNECT_PROG")) != NULL)
|
||||
return sock_exec (prog);
|
||||
else
|
||||
return open_socket_out (host, port, bind_address,
|
||||
af_hint);
|
||||
}
|
||||
|
||||
|
||||
@@ -318,94 +279,72 @@ int open_socket_out_wrapped(char *host, int port, const char *bind_address,
|
||||
*
|
||||
* Try to be better about handling the results of getaddrinfo(): when
|
||||
* opening an inbound socket, we might get several address results,
|
||||
* e.g. for the machine's ipv4 and ipv6 name.
|
||||
*
|
||||
* e.g. for the machine's ipv4 and ipv6 name.
|
||||
*
|
||||
* If binding a wildcard, then any one of them should do. If an address
|
||||
* was specified but it's insufficiently specific then that's not our
|
||||
* fault.
|
||||
*
|
||||
* fault.
|
||||
*
|
||||
* However, some of the advertized addresses may not work because e.g. we
|
||||
* don't have IPv6 support in the kernel. In that case go on and try all
|
||||
* addresses until one succeeds.
|
||||
*
|
||||
*
|
||||
* @param bind_address Local address to bind, or NULL to allow it to
|
||||
* default.
|
||||
**/
|
||||
static int *open_socket_in(int type, int port, const char *bind_address,
|
||||
int af_hint)
|
||||
static int open_socket_in(int type, int port, const char *bind_address,
|
||||
int af_hint)
|
||||
{
|
||||
int one=1;
|
||||
int s, *sp, *socks, maxs;
|
||||
int s;
|
||||
struct addrinfo hints, *all_ai, *resp;
|
||||
char portbuf[10];
|
||||
int error;
|
||||
|
||||
memset(&hints, 0, sizeof hints);
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = af_hint;
|
||||
hints.ai_socktype = type;
|
||||
hints.ai_flags = AI_PASSIVE;
|
||||
snprintf(portbuf, sizeof portbuf, "%d", port);
|
||||
snprintf(portbuf, sizeof(portbuf), "%d", port);
|
||||
error = getaddrinfo(bind_address, portbuf, &hints, &all_ai);
|
||||
if (error) {
|
||||
rprintf(FERROR, RSYNC_NAME ": getaddrinfo: bind address %s: %s\n",
|
||||
bind_address, gai_strerror(error));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Count max number of sockets we might open. */
|
||||
for (maxs = 0, resp = all_ai; resp; resp = resp->ai_next, maxs++) {}
|
||||
socks = new_array(int, maxs + 1);
|
||||
if (!socks) {
|
||||
rprintf(FERROR,
|
||||
RSYNC_NAME "couldn't allocate memory for sockets");
|
||||
return NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* We may not be able to create the socket, if for example the
|
||||
* machine knows about IPv6 in the C library, but not in the
|
||||
* kernel. */
|
||||
sp = socks + 1; /* Leave room for count at start of array. */
|
||||
for (resp = all_ai; resp; resp = resp->ai_next) {
|
||||
s = socket(resp->ai_family, resp->ai_socktype,
|
||||
resp->ai_protocol);
|
||||
|
||||
if (s == -1) {
|
||||
if (s == -1)
|
||||
/* See if there's another address that will work... */
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
|
||||
(char *)&one, sizeof one);
|
||||
|
||||
#ifdef IPV6_V6ONLY
|
||||
if (resp->ai_family == AF_INET6) {
|
||||
setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
|
||||
(char *)&one, sizeof one);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Now we've got a socket - we need to bind it. */
|
||||
if (bind(s, resp->ai_addr, resp->ai_addrlen) < 0) {
|
||||
|
||||
/* now we've got a socket - we need to bind it */
|
||||
if (bind(s, all_ai->ai_addr, all_ai->ai_addrlen) < 0) {
|
||||
/* Nope, try another */
|
||||
close(s);
|
||||
continue;
|
||||
}
|
||||
|
||||
*sp++ = s;
|
||||
}
|
||||
*socks = sp - socks - 1; /* Save count. */
|
||||
|
||||
if (all_ai)
|
||||
freeaddrinfo(all_ai);
|
||||
|
||||
if (*socks == 0) {
|
||||
rprintf(FERROR,
|
||||
RSYNC_NAME ": open inbound socket on port %d failed: "
|
||||
"%s\n", port, strerror(errno));
|
||||
free(socks);
|
||||
return NULL;
|
||||
return s;
|
||||
}
|
||||
return socks;
|
||||
|
||||
rprintf(FERROR, RSYNC_NAME ": open inbound socket on port %d failed: "
|
||||
"%s\n",
|
||||
port,
|
||||
strerror(errno));
|
||||
|
||||
freeaddrinfo(all_ai);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -415,64 +354,55 @@ static int *open_socket_in(int type, int port, const char *bind_address,
|
||||
int is_a_socket(int fd)
|
||||
{
|
||||
int v;
|
||||
socklen_t l = sizeof (int);
|
||||
socklen_t l;
|
||||
l = sizeof(int);
|
||||
|
||||
/* Parameters to getsockopt, setsockopt etc are very
|
||||
* unstandardized across platforms, so don't be surprised if
|
||||
* there are compiler warnings on e.g. SCO OpenSwerver or AIX.
|
||||
* It seems they all eventually get the right idea.
|
||||
*
|
||||
* Debian says: ``The fifth argument of getsockopt and
|
||||
* setsockopt is in reality an int [*] (and this is what BSD
|
||||
* 4.* and libc4 and libc5 have). Some POSIX confusion
|
||||
* resulted in the present socklen_t. The draft standard has
|
||||
* not been adopted yet, but glibc2 already follows it and
|
||||
* also has socklen_t [*]. See also accept(2).''
|
||||
*
|
||||
* We now return to your regularly scheduled programming. */
|
||||
return getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&v, &l) == 0;
|
||||
/* Parameters to getsockopt, setsockopt etc are very
|
||||
* unstandardized across platforms, so don't be surprised if
|
||||
* there are compiler warnings on e.g. SCO OpenSwerver or AIX.
|
||||
* It seems they all eventually get the right idea.
|
||||
*
|
||||
* Debian says: ``The fifth argument of getsockopt and
|
||||
* setsockopt is in reality an int [*] (and this is what BSD
|
||||
* 4.* and libc4 and libc5 have). Some POSIX confusion
|
||||
* resulted in the present socklen_t. The draft standard has
|
||||
* not been adopted yet, but glibc2 already follows it and
|
||||
* also has socklen_t [*]. See also accept(2).''
|
||||
*
|
||||
* We now return to your regularly scheduled programming. */
|
||||
return(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&v, &l) == 0);
|
||||
}
|
||||
|
||||
|
||||
static RETSIGTYPE sigchld_handler(UNUSED(int val))
|
||||
{
|
||||
signal(SIGCHLD, sigchld_handler);
|
||||
#ifdef WNOHANG
|
||||
while (waitpid(-1, NULL, WNOHANG) > 0) {}
|
||||
#endif
|
||||
signal(SIGCHLD, sigchld_handler);
|
||||
}
|
||||
|
||||
|
||||
void start_accept_loop(int port, int (*fn)(int, int))
|
||||
{
|
||||
fd_set deffds;
|
||||
int *sp, maxfd, i, j;
|
||||
int s;
|
||||
extern char *bind_address;
|
||||
extern int default_af_hint;
|
||||
|
||||
/* open an incoming socket */
|
||||
sp = open_socket_in(SOCK_STREAM, port, bind_address, default_af_hint);
|
||||
if (sp == NULL)
|
||||
s = open_socket_in(SOCK_STREAM, port, bind_address, default_af_hint);
|
||||
if (s == -1)
|
||||
exit_cleanup(RERR_SOCKETIO);
|
||||
|
||||
/* ready to listen */
|
||||
FD_ZERO(&deffds);
|
||||
maxfd = -1;
|
||||
for (i = 1; i <= *sp; i++) {
|
||||
if (listen(sp[i], 5) == -1) {
|
||||
for (j = 1; j <= i; j++)
|
||||
close(sp[j]);
|
||||
free(sp);
|
||||
exit_cleanup(RERR_SOCKETIO);
|
||||
}
|
||||
FD_SET(sp[i], &deffds);
|
||||
if (maxfd < sp[i])
|
||||
maxfd = sp[i];
|
||||
if (listen(s, 5) == -1) {
|
||||
close(s);
|
||||
exit_cleanup(RERR_SOCKETIO);
|
||||
}
|
||||
|
||||
|
||||
/* now accept incoming connections - forking a new process
|
||||
* for each incoming connection */
|
||||
for each incoming connection */
|
||||
while (1) {
|
||||
fd_set fds;
|
||||
pid_t pid;
|
||||
@@ -481,38 +411,30 @@ void start_accept_loop(int port, int (*fn)(int, int))
|
||||
socklen_t addrlen = sizeof addr;
|
||||
|
||||
/* close log file before the potentially very long select so
|
||||
* file can be trimmed by another process instead of growing
|
||||
* forever */
|
||||
file can be trimmed by another process instead of growing
|
||||
forever */
|
||||
log_close();
|
||||
|
||||
#ifdef FD_COPY
|
||||
FD_COPY(&deffds, &fds);
|
||||
#else
|
||||
fds = deffds;
|
||||
#endif
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(s, &fds);
|
||||
|
||||
if (select(maxfd + 1, &fds, NULL, NULL, NULL) != 1)
|
||||
if (select(s+1, &fds, NULL, NULL, NULL) != 1) {
|
||||
continue;
|
||||
|
||||
fd = -1;
|
||||
for (i = 1; i <= *sp; i++) {
|
||||
if (FD_ISSET(sp[i], &fds)) {
|
||||
fd = accept(sp[i], (struct sockaddr *)&addr,
|
||||
&addrlen);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (fd < 0)
|
||||
continue;
|
||||
if(!FD_ISSET(s, &fds)) continue;
|
||||
|
||||
fd = accept(s,(struct sockaddr *)&addr,&addrlen);
|
||||
|
||||
if (fd == -1) continue;
|
||||
|
||||
signal(SIGCHLD, sigchld_handler);
|
||||
|
||||
if ((pid = fork()) == 0) {
|
||||
int ret;
|
||||
close(sp[i]);
|
||||
close(s);
|
||||
/* open log file in child before possibly giving
|
||||
* up privileges */
|
||||
up privileges */
|
||||
log_open();
|
||||
ret = fn(fd, fd);
|
||||
close_all();
|
||||
@@ -532,7 +454,6 @@ void start_accept_loop(int port, int (*fn)(int, int))
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
free(sp);
|
||||
}
|
||||
|
||||
|
||||
@@ -578,7 +499,7 @@ struct
|
||||
#endif
|
||||
{NULL,0,0,0,0}};
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set user socket options
|
||||
@@ -586,16 +507,13 @@ struct
|
||||
void set_socket_options(int fd, char *options)
|
||||
{
|
||||
char *tok;
|
||||
|
||||
if (!options || !*options)
|
||||
return;
|
||||
if (!options || !*options) return;
|
||||
|
||||
options = strdup(options);
|
||||
|
||||
if (!options) out_of_memory("set_socket_options");
|
||||
|
||||
if (!options)
|
||||
out_of_memory("set_socket_options");
|
||||
|
||||
for (tok = strtok(options, " \t,"); tok; tok = strtok(NULL," \t,")) {
|
||||
for (tok=strtok(options, " \t,"); tok; tok=strtok(NULL," \t,")) {
|
||||
int ret=0,i;
|
||||
int value = 1;
|
||||
char *p;
|
||||
@@ -607,10 +525,9 @@ void set_socket_options(int fd, char *options)
|
||||
got_value = 1;
|
||||
}
|
||||
|
||||
for (i = 0; socket_options[i].name; i++) {
|
||||
for (i=0;socket_options[i].name;i++)
|
||||
if (strcmp(socket_options[i].name,tok)==0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!socket_options[i].name) {
|
||||
rprintf(FERROR,"Unknown socket option %s\n",tok);
|
||||
@@ -621,10 +538,9 @@ void set_socket_options(int fd, char *options)
|
||||
case OPT_BOOL:
|
||||
case OPT_INT:
|
||||
ret = setsockopt(fd,socket_options[i].level,
|
||||
socket_options[i].option,
|
||||
(char *)&value, sizeof (int));
|
||||
socket_options[i].option,(char *)&value,sizeof(int));
|
||||
break;
|
||||
|
||||
|
||||
case OPT_ON:
|
||||
if (got_value)
|
||||
rprintf(FERROR,"syntax error - %s does not take a value\n",tok);
|
||||
@@ -632,12 +548,11 @@ void set_socket_options(int fd, char *options)
|
||||
{
|
||||
int on = socket_options[i].value;
|
||||
ret = setsockopt(fd,socket_options[i].level,
|
||||
socket_options[i].option,
|
||||
(char *)&on, sizeof (int));
|
||||
socket_options[i].option,(char *)&on,sizeof(int));
|
||||
}
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (ret != 0)
|
||||
rprintf(FERROR, "failed to set socket option %s: %s\n", tok,
|
||||
strerror(errno));
|
||||
@@ -664,15 +579,15 @@ void become_daemon(void)
|
||||
#ifdef TIOCNOTTY
|
||||
i = open("/dev/tty", O_RDWR);
|
||||
if (i >= 0) {
|
||||
ioctl(i, (int)TIOCNOTTY, (char *)0);
|
||||
ioctl(i, (int) TIOCNOTTY, (char *)0);
|
||||
close(i);
|
||||
}
|
||||
#endif /* TIOCNOTTY */
|
||||
#endif
|
||||
/* make sure that stdin, stdout an stderr don't stuff things
|
||||
* up (library functions, for example) */
|
||||
for (i = 0; i < 3; i++) {
|
||||
close(i);
|
||||
up (library functions, for example) */
|
||||
for (i=0;i<3;i++) {
|
||||
close(i);
|
||||
open("/dev/null", O_RDWR);
|
||||
}
|
||||
}
|
||||
@@ -681,7 +596,7 @@ void become_daemon(void)
|
||||
/**
|
||||
* This is like socketpair but uses tcp. It is used by the Samba
|
||||
* regression test code.
|
||||
*
|
||||
*
|
||||
* The function guarantees that nobody else can attach to the socket,
|
||||
* or if they do that this function fails and the socket gets closed
|
||||
* returns 0 on success, -1 on failure the resulting file descriptors
|
||||
@@ -692,65 +607,56 @@ static int socketpair_tcp(int fd[2])
|
||||
int listener;
|
||||
struct sockaddr_in sock;
|
||||
struct sockaddr_in sock2;
|
||||
socklen_t socklen = sizeof sock;
|
||||
socklen_t socklen = sizeof(sock);
|
||||
int connect_done = 0;
|
||||
|
||||
|
||||
fd[0] = fd[1] = listener = -1;
|
||||
|
||||
memset(&sock, 0, sizeof sock);
|
||||
memset(&sock, 0, sizeof(sock));
|
||||
|
||||
if ((listener = socket(PF_INET, SOCK_STREAM, 0)) == -1) goto failed;
|
||||
|
||||
if ((listener = socket(PF_INET, SOCK_STREAM, 0)) == -1)
|
||||
goto failed;
|
||||
|
||||
memset(&sock2, 0, sizeof sock2);
|
||||
#if HAVE_SOCKADDR_IN_LEN
|
||||
sock2.sin_len = sizeof sock2;
|
||||
memset(&sock2, 0, sizeof(sock2));
|
||||
#ifdef HAVE_SOCKADDR_LEN
|
||||
sock2.sin_len = sizeof(sock2);
|
||||
#endif
|
||||
sock2.sin_family = PF_INET;
|
||||
sock2.sin_family = PF_INET;
|
||||
|
||||
bind(listener, (struct sockaddr *)&sock2, sizeof sock2);
|
||||
bind(listener, (struct sockaddr *)&sock2, sizeof(sock2));
|
||||
|
||||
if (listen(listener, 1) != 0)
|
||||
goto failed;
|
||||
if (listen(listener, 1) != 0) goto failed;
|
||||
|
||||
if (getsockname(listener, (struct sockaddr *)&sock, &socklen) != 0)
|
||||
goto failed;
|
||||
if (getsockname(listener, (struct sockaddr *)&sock, &socklen) != 0) goto failed;
|
||||
|
||||
if ((fd[1] = socket(PF_INET, SOCK_STREAM, 0)) == -1)
|
||||
goto failed;
|
||||
if ((fd[1] = socket(PF_INET, SOCK_STREAM, 0)) == -1) goto failed;
|
||||
|
||||
set_nonblocking(fd[1]);
|
||||
|
||||
sock.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
|
||||
if (connect(fd[1], (struct sockaddr *)&sock, sizeof sock) == -1) {
|
||||
if (errno != EINPROGRESS)
|
||||
goto failed;
|
||||
} else
|
||||
if (connect(fd[1],(struct sockaddr *)&sock,sizeof(sock)) == -1) {
|
||||
if (errno != EINPROGRESS) goto failed;
|
||||
} else {
|
||||
connect_done = 1;
|
||||
}
|
||||
|
||||
if ((fd[0] = accept(listener, (struct sockaddr *)&sock, &socklen)) == -1)
|
||||
goto failed;
|
||||
if ((fd[0] = accept(listener, (struct sockaddr *)&sock, &socklen)) == -1) goto failed;
|
||||
|
||||
close(listener);
|
||||
if (connect_done == 0) {
|
||||
if (connect(fd[1], (struct sockaddr *)&sock, sizeof sock) != 0
|
||||
&& errno != EISCONN)
|
||||
goto failed;
|
||||
if (connect(fd[1],(struct sockaddr *)&sock,sizeof(sock)) != 0
|
||||
&& errno != EISCONN) goto failed;
|
||||
}
|
||||
|
||||
set_blocking(fd[1]);
|
||||
set_blocking (fd[1]);
|
||||
|
||||
/* all OK! */
|
||||
return 0;
|
||||
|
||||
failed:
|
||||
if (fd[0] != -1)
|
||||
close(fd[0]);
|
||||
if (fd[1] != -1)
|
||||
close(fd[1]);
|
||||
if (listener != -1)
|
||||
close(listener);
|
||||
if (fd[0] != -1) close(fd[0]);
|
||||
if (fd[1] != -1) close(fd[1]);
|
||||
if (listener != -1) close(listener);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -768,22 +674,30 @@ static int socketpair_tcp(int fd[2])
|
||||
int sock_exec(const char *prog)
|
||||
{
|
||||
int fd[2];
|
||||
|
||||
|
||||
if (socketpair_tcp(fd) != 0) {
|
||||
rprintf(FERROR, RSYNC_NAME ": socketpair_tcp failed (%s)\n",
|
||||
strerror(errno));
|
||||
rprintf (FERROR, RSYNC_NAME
|
||||
": socketpair_tcp failed (%s)\n",
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
if (verbose >= 2)
|
||||
rprintf(FINFO, "Running socket program: \"%s\"\n", prog);
|
||||
if (fork() == 0) {
|
||||
close(fd[0]);
|
||||
close(0);
|
||||
close(1);
|
||||
dup(fd[1]);
|
||||
dup(fd[1]);
|
||||
exit(system(prog));
|
||||
if (verbose > 3) {
|
||||
/* Can't use rprintf because we've forked. */
|
||||
fprintf (stderr,
|
||||
RSYNC_NAME ": execute socket program \"%s\"\n",
|
||||
prog);
|
||||
}
|
||||
exit (system (prog));
|
||||
}
|
||||
close(fd[1]);
|
||||
close (fd[1]);
|
||||
return fd[0];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
53
syscall.c
53
syscall.c
@@ -31,27 +31,19 @@ extern int read_only;
|
||||
extern int list_only;
|
||||
extern int preserve_perms;
|
||||
|
||||
#define RETURN_ERROR_IF(x,e) \
|
||||
do { \
|
||||
if (x) { \
|
||||
errno = (e); \
|
||||
return -1; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define RETURN_ERROR_IF_RO_OR_LO RETURN_ERROR_IF(read_only || list_only, EROFS)
|
||||
#define CHECK_RO if (read_only || list_only) {errno = EROFS; return -1;}
|
||||
|
||||
int do_unlink(char *fname)
|
||||
{
|
||||
if (dry_run) return 0;
|
||||
RETURN_ERROR_IF_RO_OR_LO;
|
||||
CHECK_RO
|
||||
return unlink(fname);
|
||||
}
|
||||
|
||||
int do_symlink(char *fname1, char *fname2)
|
||||
{
|
||||
if (dry_run) return 0;
|
||||
RETURN_ERROR_IF_RO_OR_LO;
|
||||
CHECK_RO
|
||||
return symlink(fname1, fname2);
|
||||
}
|
||||
|
||||
@@ -59,7 +51,7 @@ int do_symlink(char *fname1, char *fname2)
|
||||
int do_link(char *fname1, char *fname2)
|
||||
{
|
||||
if (dry_run) return 0;
|
||||
RETURN_ERROR_IF_RO_OR_LO;
|
||||
CHECK_RO
|
||||
return link(fname1, fname2);
|
||||
}
|
||||
#endif
|
||||
@@ -67,7 +59,7 @@ int do_link(char *fname1, char *fname2)
|
||||
int do_lchown(const char *path, uid_t owner, gid_t group)
|
||||
{
|
||||
if (dry_run) return 0;
|
||||
RETURN_ERROR_IF_RO_OR_LO;
|
||||
CHECK_RO
|
||||
return lchown(path, owner, group);
|
||||
}
|
||||
|
||||
@@ -75,7 +67,7 @@ int do_lchown(const char *path, uid_t owner, gid_t group)
|
||||
int do_mknod(char *pathname, mode_t mode, dev_t dev)
|
||||
{
|
||||
if (dry_run) return 0;
|
||||
RETURN_ERROR_IF_RO_OR_LO;
|
||||
CHECK_RO
|
||||
return mknod(pathname, mode, dev);
|
||||
}
|
||||
#endif
|
||||
@@ -83,16 +75,18 @@ int do_mknod(char *pathname, mode_t mode, dev_t dev)
|
||||
int do_rmdir(char *pathname)
|
||||
{
|
||||
if (dry_run) return 0;
|
||||
RETURN_ERROR_IF_RO_OR_LO;
|
||||
CHECK_RO
|
||||
return rmdir(pathname);
|
||||
}
|
||||
|
||||
int do_open(char *pathname, int flags, mode_t mode)
|
||||
{
|
||||
if (flags != O_RDONLY) {
|
||||
RETURN_ERROR_IF(dry_run, 0);
|
||||
RETURN_ERROR_IF_RO_OR_LO;
|
||||
if (dry_run) return -1;
|
||||
CHECK_RO
|
||||
}
|
||||
/* some systems can't handle a double / */
|
||||
if (pathname[0] == '/' && pathname[1] == '/') pathname++;
|
||||
|
||||
return open(pathname, flags | O_BINARY, mode);
|
||||
}
|
||||
@@ -102,9 +96,9 @@ int do_chmod(const char *path, mode_t mode)
|
||||
{
|
||||
int code;
|
||||
if (dry_run) return 0;
|
||||
RETURN_ERROR_IF_RO_OR_LO;
|
||||
CHECK_RO
|
||||
code = chmod(path, mode);
|
||||
if (code != 0 && preserve_perms)
|
||||
if ((code != 0) && preserve_perms)
|
||||
return code;
|
||||
return 0;
|
||||
}
|
||||
@@ -113,7 +107,7 @@ int do_chmod(const char *path, mode_t mode)
|
||||
int do_rename(char *fname1, char *fname2)
|
||||
{
|
||||
if (dry_run) return 0;
|
||||
RETURN_ERROR_IF_RO_OR_LO;
|
||||
CHECK_RO
|
||||
return rename(fname1, fname2);
|
||||
}
|
||||
|
||||
@@ -139,8 +133,9 @@ void trim_trailing_slashes(char *name)
|
||||
|
||||
int do_mkdir(char *fname, mode_t mode)
|
||||
{
|
||||
if (dry_run) return 0;
|
||||
RETURN_ERROR_IF_RO_OR_LO;
|
||||
if (dry_run)
|
||||
return 0;
|
||||
CHECK_RO;
|
||||
trim_trailing_slashes(fname);
|
||||
return mkdir(fname, mode);
|
||||
}
|
||||
@@ -149,26 +144,22 @@ int do_mkdir(char *fname, mode_t mode)
|
||||
/* like mkstemp but forces permissions */
|
||||
int do_mkstemp(char *template, mode_t perms)
|
||||
{
|
||||
RETURN_ERROR_IF(dry_run, 0);
|
||||
RETURN_ERROR_IF(read_only, EROFS);
|
||||
if (dry_run) return -1;
|
||||
if (read_only) {errno = EROFS; return -1;}
|
||||
|
||||
#if defined(HAVE_SECURE_MKSTEMP) && defined(HAVE_FCHMOD)
|
||||
{
|
||||
int fd = mkstemp(template);
|
||||
if (fd == -1)
|
||||
return -1;
|
||||
if (fchmod(fd, perms) != 0 && preserve_perms) {
|
||||
int errno_save = errno;
|
||||
if (fd == -1) return -1;
|
||||
if ((fchmod(fd, perms) != 0) && preserve_perms) {
|
||||
close(fd);
|
||||
unlink(template);
|
||||
errno = errno_save;
|
||||
return -1;
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
#else
|
||||
if (!mktemp(template))
|
||||
return -1;
|
||||
if (!mktemp(template)) return -1;
|
||||
return do_open(template, O_RDWR|O_EXCL|O_CREAT, perms);
|
||||
#endif
|
||||
}
|
||||
|
||||
4
t_stub.c
4
t_stub.c
@@ -28,7 +28,7 @@
|
||||
|
||||
int modify_window = 0;
|
||||
int module_id = -1;
|
||||
struct exclude_list_struct server_exclude_list;
|
||||
struct exclude_struct **server_exclude_list;
|
||||
|
||||
void rprintf(UNUSED(enum logcode code), const char *format, ...)
|
||||
{
|
||||
@@ -45,7 +45,7 @@ struct exclude_list_struct server_exclude_list;
|
||||
exit(code);
|
||||
}
|
||||
|
||||
int check_exclude(UNUSED(struct exclude_list_struct *listp), UNUSED(char *name),
|
||||
int check_exclude(UNUSED(struct exclude_struct **list), UNUSED(char *name),
|
||||
UNUSED(int name_is_dir))
|
||||
{
|
||||
/* This function doesn't really get called in this test context, so
|
||||
|
||||
@@ -18,6 +18,8 @@ set -x
|
||||
fromdir="$scratchdir/from"
|
||||
todir="$scratchdir/to"
|
||||
|
||||
# TODO: I guess some systems will not have 'id', and therefore we have
|
||||
# to ship or emulate it.
|
||||
mygrps="`rsync_getgroups`" || fail "Can't get groups"
|
||||
mkdir "$fromdir"
|
||||
|
||||
@@ -31,5 +33,6 @@ sleep 2
|
||||
|
||||
checkit "$RSYNC -rtgvvv \"$fromdir/\" \"$todir/\"" "$fromdir" "$todir"
|
||||
|
||||
# The script would have aborted on error, so getting here means we've won.
|
||||
exit 0
|
||||
# last [] may have failed but if we get here then we've won
|
||||
|
||||
|
||||
@@ -33,5 +33,6 @@ chgrp 5003 "$name2" || test_skipped "Can't chgrp (probably need root)"
|
||||
|
||||
checkit "$RSYNC -aHvv \"$fromdir/\" \"$todir/\"" "$fromdir" "$todir"
|
||||
|
||||
# The script would have aborted on error, so getting here means we've won.
|
||||
exit 0
|
||||
# last [] may have failed but if we get here then we've won
|
||||
|
||||
|
||||
@@ -27,7 +27,5 @@ RSYNC_CONNECT_PROG="$RSYNC --config=$conf --daemon"
|
||||
export RSYNC_CONNECT_PROG
|
||||
|
||||
hands_setup
|
||||
checkit "$RSYNC -avvvvz localhost::test-from/ \"$TO/\"" "$FROM" "$TO"
|
||||
checkit "$RSYNC -avvz localhost::test-from/ \"$TO/\"" "$FROM" "$TO"
|
||||
|
||||
# The script would have aborted on error, so getting here means we've won.
|
||||
exit 0
|
||||
|
||||
@@ -21,7 +21,5 @@ RSYNC_CONNECT_PROG="$RSYNC --config=$conf --daemon"
|
||||
export RSYNC_CONNECT_PROG
|
||||
|
||||
hands_setup
|
||||
checkit "$RSYNC -avvvvz \"$FROM/\" localhost::test-to/" "$FROM" "$TO"
|
||||
checkit "$RSYNC -avvz \"$FROM/\" localhost::test-to/" "$FROM" "$TO"
|
||||
|
||||
# The script would have aborted on error, so getting here means we've won.
|
||||
exit 0
|
||||
|
||||
@@ -16,23 +16,14 @@ set -x
|
||||
fromdir="$scratchdir/from"
|
||||
todir="$scratchdir/to"
|
||||
|
||||
case `id -u` in
|
||||
'') ;; # If "id" failed, try to continue...
|
||||
0) ;;
|
||||
*) test_skipped "Rsync won't copy devices unless we're root" ;;
|
||||
esac
|
||||
|
||||
# TODO: Need to test whether hardlinks are possible on this OS/filesystem
|
||||
|
||||
mkdir "$fromdir"
|
||||
mknod "$fromdir/char" c 41 67 || test_skipped "Can't create char device node unless root"
|
||||
mknod "$fromdir/char2" c 42 68 || test_skipped "Can't create char device node unless root"
|
||||
mknod "$fromdir/char3" c 42 69 || test_skipped "Can't create char device node unless root"
|
||||
mknod "$fromdir/char" c 42 69 || test_skipped "Can't create char device node unless root"
|
||||
mknod "$fromdir/block" b 42 69 || test_skipped "Can't create block device node unless root"
|
||||
mknod "$fromdir/block2" b 42 73 || test_skipped "Can't create block device node unless root"
|
||||
mknod "$fromdir/block3" b 105 73 || test_skipped "Can't create block device node unless root"
|
||||
|
||||
checkit "$RSYNC -aHvv \"$fromdir/\" \"$todir/\"" "$fromdir" "$todir"
|
||||
|
||||
# The script would have aborted on error, so getting here means we've won.
|
||||
exit 0
|
||||
# last [] may have failed but if we get here then we've won
|
||||
|
||||
|
||||
@@ -49,5 +49,5 @@ then
|
||||
test_fail "name2 was not copied exactly once"
|
||||
fi
|
||||
|
||||
# The script would have aborted on error, so getting here means we've won.
|
||||
exit 0
|
||||
# last [] may have failed but if we get here then we've won
|
||||
|
||||
@@ -14,36 +14,23 @@
|
||||
|
||||
set -x
|
||||
|
||||
HOME="$scratchdir"
|
||||
CVSIGNORE='*.junk'
|
||||
export HOME CVSIGNORE
|
||||
|
||||
# Build some files/dirs/links to copy
|
||||
|
||||
fromdir="$scratchdir/from"
|
||||
todir="$scratchdir/to"
|
||||
chkdir="$scratchdir/chk"
|
||||
|
||||
echo home-cvs-exclude >"$scratchdir"/.cvsignore
|
||||
makepath "$fromdir/foo/down/to/you"
|
||||
makepath "$fromdir/bar/down/to/foo/too"
|
||||
makepath "$fromdir/mid/for/foo/and/that/is/who"
|
||||
echo kept >"$fromdir/foo/file1"
|
||||
echo removed >"$fromdir/foo/file2"
|
||||
echo cvsout >"$fromdir/foo/file2.old"
|
||||
echo keeper >"$fromdir/bar/down/to/foo/file1"
|
||||
echo cvsout >"$fromdir/bar/down/to/foo/file1.bak"
|
||||
echo gone >"$fromdir/bar/down/to/foo/file3"
|
||||
echo lost >"$fromdir/bar/down/to/foo/file4"
|
||||
echo cvsout >"$fromdir/bar/down/to/foo/file4.junk"
|
||||
echo smashed >"$fromdir/bar/down/to/foo/to"
|
||||
echo cvsout >"$fromdir/bar/down/to/home-cvs-exclude"
|
||||
echo cvsout >"$fromdir/mid/one-in-one-out"
|
||||
echo one-in-one-out >"$fromdir/mid/.cvsignore"
|
||||
echo cvsin >"$fromdir/mid/one-for-all"
|
||||
echo expunged >"$fromdir/mid/for/foo/extra"
|
||||
echo retained >"$fromdir/mid/for/foo/keep"
|
||||
echo cvsin >"$fromdir/mid/for/one-in-one-out"
|
||||
ln -s too "$fromdir/bar/down/to/foo/sym"
|
||||
|
||||
# Setup our test exclude/include file.
|
||||
@@ -85,21 +72,4 @@ $RSYNC -av --existing --include='*/' --exclude='*' "$fromdir/" "$chkdir/"
|
||||
|
||||
checkit "$RSYNC -avv --exclude-from=$excl \"$fromdir/\" \"$todir/\"" "$chkdir" "$todir"
|
||||
|
||||
# Modify the chk dir by removing cvs-ignored files and then tweaking the dir times.
|
||||
|
||||
rm "$chkdir"/foo/*.old
|
||||
rm "$chkdir"/bar/down/to/foo/*.bak
|
||||
rm "$chkdir"/bar/down/to/foo/*.junk
|
||||
rm "$chkdir"/bar/down/to/home-cvs-exclude
|
||||
rm "$chkdir"/mid/one-in-one-out
|
||||
|
||||
$RSYNC -av --existing --include='*/' --exclude='*' "$fromdir/" "$chkdir/"
|
||||
|
||||
# Now, test if rsync excludes the same files, this time with --cvs-exclude
|
||||
# and --delete-excluded.
|
||||
|
||||
checkit "$RSYNC -avvC --delete-excluded --exclude-from=$excl \
|
||||
\"$fromdir/\" \"$todir/\"" "$chkdir" "$todir"
|
||||
|
||||
# The script would have aborted on error, so getting here means we've won.
|
||||
exit 0
|
||||
|
||||
@@ -25,5 +25,4 @@ runtest "extra data" 'checkit "$RSYNC -avH ${FROM}/ ${TO}" ${FROM}/ ${TO}'
|
||||
cp ${FROM}/text ${TO}/ThisShouldGo
|
||||
runtest " --delete" 'checkit "$RSYNC --delete -avH ${FROM}/ ${TO}" ${FROM}/ ${TO}'
|
||||
|
||||
# The script would have aborted on error, so getting here means we've won.
|
||||
exit 0
|
||||
|
||||
@@ -33,5 +33,6 @@ cp "$name2" "$name4" || fail "Can't copy file"
|
||||
|
||||
checkit "$RSYNC -aHvv \"$fromdir/\" \"$todir/\"" "$fromdir" "$todir"
|
||||
|
||||
# The script would have aborted on error, so getting here means we've won.
|
||||
exit 0
|
||||
# last [] may have failed but if we get here then we've won
|
||||
|
||||
|
||||
@@ -19,6 +19,3 @@ touch $LONGDIR/1 || test_skipped "unable to create files in long directory"
|
||||
date > ${LONGDIR}/1
|
||||
ls -la / > ${LONGDIR}/2
|
||||
checkit "$RSYNC --delete -avH ${FROM}/ ${TO}" ${FROM}/ ${TO}
|
||||
|
||||
# The script would have aborted on error, so getting here means we've won.
|
||||
exit 0
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
#! /bin/sh
|
||||
|
||||
# Copyright (C) 2004 by Wayne Davison <wayned@samba.org>
|
||||
|
||||
# This program is distributable under the terms of the GNU GPL (see
|
||||
# COPYING).
|
||||
|
||||
# Make sure we can merge files from multiple directories into one.
|
||||
|
||||
. $srcdir/testsuite/rsync.fns
|
||||
|
||||
set -x
|
||||
|
||||
# Build some files/dirs/links to copy
|
||||
|
||||
fromdir="$scratchdir/from"
|
||||
from1dir="${fromdir}1"
|
||||
from2dir="${fromdir}2"
|
||||
from3dir="${fromdir}3"
|
||||
todir="$scratchdir/to"
|
||||
chkdir="$scratchdir/chk"
|
||||
|
||||
mkdir "$from1dir" "$from2dir" "$from3dir"
|
||||
mkdir "$from2dir"/sub1 "$from3dir"/sub1
|
||||
mkdir "$from3dir"/sub2
|
||||
mkdir "$chkdir" "$chkdir"/sub1 "$chkdir"/sub2
|
||||
echo "one" >"$from1dir"/one
|
||||
cp -p "$from1dir"/one "$from2dir"/one
|
||||
cp -p "$from1dir"/one "$from3dir"/one
|
||||
echo "two" >"$from1dir"/two
|
||||
echo "three" >"$from2dir"/three
|
||||
echo "four" >"$from3dir"/four
|
||||
echo "five" >"$from1dir"/five
|
||||
echo "six" >"$from3dir"/six
|
||||
echo "sub1" >"$from2dir"/sub1/uno
|
||||
cp -p "$from2dir"/sub1/uno "$from3dir"/sub1/uno
|
||||
echo "sub2" >"$from3dir"/sub1/dos
|
||||
echo "sub3" >"$from2dir"/sub1/tres
|
||||
echo "subby" >"$from3dir"/sub2/subby
|
||||
|
||||
cp -p "$from1dir"/one "$from1dir"/two "$from2dir"/three "$from3dir"/four "$from1dir"/five "$from3dir"/six "$chkdir"
|
||||
cp -p "$from2dir"/sub1/uno "$from3dir"/sub1/dos "$from2dir"/sub1/tres "$chkdir"/sub1
|
||||
cp -p "$from3dir"/sub2/subby "$chkdir"/sub2
|
||||
|
||||
# Get rid of any directory-time differences
|
||||
touch "$fromdir"? "$chkdir" "$fromdir"?/sub? "$chkdir"/sub?
|
||||
|
||||
checkit "$RSYNC -aHvv \"$fromdir\"?/ \"$todir/\"" "$chkdir" "$todir"
|
||||
|
||||
# The script would have aborted on error, so getting here means we've won.
|
||||
exit 0
|
||||
@@ -196,7 +196,6 @@ pid file = $pidfile
|
||||
use chroot = no
|
||||
hosts allow = localhost, 127.0.0.1
|
||||
log file = $logfile
|
||||
max verbosity = 9
|
||||
|
||||
uid = 0
|
||||
gid = 0
|
||||
|
||||
@@ -35,5 +35,6 @@ then
|
||||
test_fail "absolute symlink was copied"
|
||||
fi
|
||||
|
||||
# The script would have aborted on error, so getting here means we've won.
|
||||
exit 0
|
||||
# last [] may have failed but if we get here then we've one
|
||||
|
||||
|
||||
@@ -24,5 +24,4 @@ diff $diffopt "$scratchdir/slash.out" - <<EOF
|
||||
/Users/Wierd Macintosh Name/// Ooh, translucent plastic
|
||||
EOF
|
||||
|
||||
# The script would have aborted on error, so getting here means we've won.
|
||||
exit 0
|
||||
|
||||
@@ -11,10 +11,9 @@
|
||||
|
||||
set -x
|
||||
|
||||
"$TOOLDIR/wildtest" "$srcdir/wildtest.txt" >"$scratchdir/wild.out"
|
||||
"$TOOLDIR/wildtest" >"$scratchdir/wild.out"
|
||||
diff $diffopt "$scratchdir/wild.out" - <<EOF
|
||||
No wildmatch errors found.
|
||||
EOF
|
||||
|
||||
# The script would have aborted on error, so getting here means we've won.
|
||||
exit 0
|
||||
|
||||
30
tls.c
30
tls.c
@@ -1,16 +1,16 @@
|
||||
/* -*- c-file-style: "linux" -*-
|
||||
*
|
||||
* Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version
|
||||
* 2 as published by the Free Software Foundation.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
@@ -86,7 +86,7 @@ static void list_file (const char *fname)
|
||||
strcpy(linkbuf, " -> ");
|
||||
/* const-cast required for silly UNICOS headers */
|
||||
len = readlink((char *) fname, linkbuf+4, sizeof(linkbuf) - 4);
|
||||
if (len == -1)
|
||||
if (len == -1)
|
||||
failed("readlink", fname);
|
||||
else
|
||||
/* it's not nul-terminated */
|
||||
@@ -99,7 +99,7 @@ static void list_file (const char *fname)
|
||||
|
||||
if (buf.st_mtime) {
|
||||
mt = gmtime(&buf.st_mtime);
|
||||
|
||||
|
||||
sprintf(datebuf, "%04d-%02d-%02d %02d:%02d:%02d",
|
||||
mt->tm_year + 1900,
|
||||
mt->tm_mon + 1,
|
||||
@@ -110,18 +110,16 @@ static void list_file (const char *fname)
|
||||
} else {
|
||||
strcpy(datebuf, " ");
|
||||
}
|
||||
|
||||
|
||||
/* TODO: Perhaps escape special characters in fname? */
|
||||
|
||||
printf("%s ", permbuf);
|
||||
if (IS_DEVICE(buf.st_mode)) {
|
||||
printf("%5ld,%6ld",
|
||||
(long)major(buf.st_rdev),
|
||||
(long)minor(buf.st_rdev));
|
||||
} else /* NB: use double for size since it might not fit in a long. */
|
||||
printf("%12.0f", (double)buf.st_size);
|
||||
printf(" %6ld.%-6ld %6ld %s %s%s\n",
|
||||
(long)buf.st_uid, (long)buf.st_gid, (long)buf.st_nlink,
|
||||
|
||||
|
||||
/* NB: need to pass size as a double because it might be be
|
||||
* too large for a long. */
|
||||
printf("%s %12.0f %6ld.%-6ld %6d %s %s%s\n",
|
||||
permbuf, (double) buf.st_size,
|
||||
(long) buf.st_uid, (long) buf.st_gid,
|
||||
buf.st_nlink,
|
||||
datebuf, fname, linkbuf);
|
||||
}
|
||||
|
||||
|
||||
81
token.c
81
token.c
@@ -51,7 +51,7 @@ void set_compression(char *fname)
|
||||
strlower(fname);
|
||||
|
||||
for (tok=strtok(dont," ");tok;tok=strtok(NULL," ")) {
|
||||
if (wildmatch(tok, fname)) {
|
||||
if (fnmatch(tok, fname, 0) == 0) {
|
||||
compression_level = 0;
|
||||
break;
|
||||
}
|
||||
@@ -90,8 +90,8 @@ static int simple_recv_token(int f,char **data)
|
||||
static void simple_send_token(int f,int token,
|
||||
struct map_struct *buf,OFF_T offset,int n)
|
||||
{
|
||||
extern int write_batch;
|
||||
int hold_int;
|
||||
extern int write_batch; /* dw */
|
||||
int hold_int; /* dw */
|
||||
|
||||
if (n > 0) {
|
||||
int l = 0;
|
||||
@@ -100,8 +100,8 @@ static void simple_send_token(int f,int token,
|
||||
write_int(f,n1);
|
||||
write_buf(f,map_ptr(buf,offset+l,n1),n1);
|
||||
if (write_batch) {
|
||||
write_batch_delta_file( (char *) &n1, sizeof(int) );
|
||||
write_batch_delta_file(map_ptr(buf,offset+l,n1),n1);
|
||||
write_batch_delta_file( (char *) &n1, sizeof(int) );
|
||||
write_batch_delta_file(map_ptr(buf,offset+l,n1),n1);
|
||||
}
|
||||
l += n1;
|
||||
}
|
||||
@@ -110,8 +110,8 @@ static void simple_send_token(int f,int token,
|
||||
if (token != -2) {
|
||||
write_int(f,-(token+1));
|
||||
if (write_batch) {
|
||||
hold_int = -(token+1);
|
||||
write_batch_delta_file( (char *) &hold_int, sizeof(int) );
|
||||
hold_int = -(token+1);
|
||||
write_batch_delta_file( (char *) &hold_int, sizeof(int) );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -127,12 +127,6 @@ static void simple_send_token(int f,int token,
|
||||
|
||||
#define MAX_DATA_COUNT 16383 /* fit 14 bit count into 2 bytes with flags */
|
||||
|
||||
/* zlib.h says that if we want to be able to compress something in a single
|
||||
* call, avail_out must be at least 0.1% larger than avail_in plus 12 bytes.
|
||||
* We'll add in 0.1%+16, just to be safe (and we'll avoid floating point,
|
||||
* to ensure that this is a compile-time value). */
|
||||
#define AVAIL_OUT_SIZE(avail_in_size) ((avail_in_size)*1001/1000+16)
|
||||
|
||||
/* For coding runs of tokens */
|
||||
static int last_token = -1;
|
||||
static int run_start;
|
||||
@@ -144,14 +138,6 @@ static z_stream tx_strm;
|
||||
/* Output buffer */
|
||||
static char *obuf;
|
||||
|
||||
/* We want obuf to be able to hold both MAX_DATA_COUNT+2 bytes as well as
|
||||
* AVAIL_OUT_SIZE(CHUNK_SIZE) bytes, so make sure that it's large enough. */
|
||||
#if MAX_DATA_COUNT+2 > AVAIL_OUT_SIZE(CHUNK_SIZE)
|
||||
#define OBUF_SIZE (MAX_DATA_COUNT+2)
|
||||
#else
|
||||
#define OBUF_SIZE AVAIL_OUT_SIZE(CHUNK_SIZE)
|
||||
#endif
|
||||
|
||||
/* Send a deflated token */
|
||||
static void
|
||||
send_deflated_token(int f, int token,
|
||||
@@ -159,8 +145,8 @@ send_deflated_token(int f, int token,
|
||||
{
|
||||
int n, r;
|
||||
static int init_done, flush_pending;
|
||||
extern int write_batch;
|
||||
char temp_byte;
|
||||
extern int write_batch; /* dw */
|
||||
char temp_byte; /* dw */
|
||||
|
||||
if (last_token == -1) {
|
||||
/* initialization */
|
||||
@@ -174,7 +160,7 @@ send_deflated_token(int f, int token,
|
||||
rprintf(FERROR, "compression init failed\n");
|
||||
exit_cleanup(RERR_STREAMIO);
|
||||
}
|
||||
if ((obuf = new_array(char, OBUF_SIZE)) == NULL)
|
||||
if ((obuf = new_array(char, MAX_DATA_COUNT+2)) == NULL)
|
||||
out_of_memory("send_deflated_token");
|
||||
init_done = 1;
|
||||
} else
|
||||
@@ -193,27 +179,26 @@ send_deflated_token(int f, int token,
|
||||
n = last_token - run_start;
|
||||
if (r >= 0 && r <= 63) {
|
||||
write_byte(f, (n==0? TOKEN_REL: TOKENRUN_REL) + r);
|
||||
if (write_batch) {
|
||||
temp_byte = (char)( (n==0? TOKEN_REL: TOKENRUN_REL) + r);
|
||||
write_batch_delta_file(&temp_byte,sizeof(char));
|
||||
if (write_batch) { /* dw */
|
||||
temp_byte = (char)( (n==0? TOKEN_REL: TOKENRUN_REL) + r);
|
||||
write_batch_delta_file(&temp_byte,sizeof(char));
|
||||
}
|
||||
} else {
|
||||
write_byte(f, (n==0? TOKEN_LONG: TOKENRUN_LONG));
|
||||
write_int(f, run_start);
|
||||
if (write_batch) {
|
||||
temp_byte = (char)(n==0? TOKEN_LONG: TOKENRUN_LONG);
|
||||
write_batch_delta_file(&temp_byte,sizeof(char));
|
||||
write_batch_delta_file((char *)&run_start,sizeof(run_start));
|
||||
if (write_batch) { /* dw */
|
||||
temp_byte = (char)(n==0? TOKEN_LONG: TOKENRUN_LONG);
|
||||
write_batch_delta_file(&temp_byte,sizeof(temp_byte));
|
||||
write_batch_delta_file((char *)&run_start,sizeof(run_start));
|
||||
}
|
||||
}
|
||||
if (n != 0) {
|
||||
write_byte(f, n);
|
||||
write_byte(f, n >> 8);
|
||||
if (write_batch) {
|
||||
temp_byte = (char)n;
|
||||
write_batch_delta_file(&temp_byte,sizeof(char));
|
||||
temp_byte = (char)(n >> 8);
|
||||
write_batch_delta_file(&temp_byte,sizeof(char));
|
||||
if (write_batch) { /* dw */
|
||||
write_batch_delta_file((char *)&n,sizeof(char));
|
||||
temp_byte = (char) n >> 8;
|
||||
write_batch_delta_file(&temp_byte,sizeof(temp_byte));
|
||||
}
|
||||
}
|
||||
last_run_end = last_token;
|
||||
@@ -273,8 +258,8 @@ send_deflated_token(int f, int token,
|
||||
obuf[0] = DEFLATED_DATA + (n >> 8);
|
||||
obuf[1] = n;
|
||||
write_buf(f, obuf, n+2);
|
||||
if (write_batch)
|
||||
write_batch_delta_file(obuf,n+2);
|
||||
if (write_batch) /* dw */
|
||||
write_batch_delta_file(obuf,n+2);
|
||||
}
|
||||
}
|
||||
} while (nb != 0 || tx_strm.avail_out == 0);
|
||||
@@ -284,9 +269,9 @@ send_deflated_token(int f, int token,
|
||||
if (token == -1) {
|
||||
/* end of file - clean up */
|
||||
write_byte(f, END_FLAG);
|
||||
if (write_batch) {
|
||||
temp_byte = END_FLAG;
|
||||
write_batch_delta_file(&temp_byte,sizeof(char));
|
||||
if (write_batch) { /* dw */
|
||||
temp_byte = END_FLAG;
|
||||
write_batch_delta_file((char *)&temp_byte,sizeof(temp_byte));
|
||||
}
|
||||
|
||||
} else if (token != -2) {
|
||||
@@ -295,7 +280,7 @@ send_deflated_token(int f, int token,
|
||||
tx_strm.next_in = (Bytef *) map_ptr(buf, offset, toklen);
|
||||
tx_strm.avail_in = toklen;
|
||||
tx_strm.next_out = (Bytef *) obuf;
|
||||
tx_strm.avail_out = AVAIL_OUT_SIZE(CHUNK_SIZE);
|
||||
tx_strm.avail_out = MAX_DATA_COUNT;
|
||||
r = deflate(&tx_strm, Z_INSERT_ONLY);
|
||||
if (r != Z_OK || tx_strm.avail_in != 0) {
|
||||
rprintf(FERROR, "deflate on token returned %d (%d bytes left)\n",
|
||||
@@ -338,7 +323,7 @@ recv_deflated_token(int f, char **data)
|
||||
exit_cleanup(RERR_STREAMIO);
|
||||
}
|
||||
if (!(cbuf = new_array(char, MAX_DATA_COUNT))
|
||||
|| !(dbuf = new_array(char, AVAIL_OUT_SIZE(CHUNK_SIZE))))
|
||||
|| !(dbuf = new_array(char, CHUNK_SIZE)))
|
||||
out_of_memory("recv_deflated_token");
|
||||
init_done = 1;
|
||||
} else {
|
||||
@@ -367,9 +352,9 @@ recv_deflated_token(int f, char **data)
|
||||
/* check previous inflated stuff ended correctly */
|
||||
rx_strm.avail_in = 0;
|
||||
rx_strm.next_out = (Bytef *)dbuf;
|
||||
rx_strm.avail_out = AVAIL_OUT_SIZE(CHUNK_SIZE);
|
||||
rx_strm.avail_out = CHUNK_SIZE;
|
||||
r = inflate(&rx_strm, Z_SYNC_FLUSH);
|
||||
n = AVAIL_OUT_SIZE(CHUNK_SIZE) - rx_strm.avail_out;
|
||||
n = CHUNK_SIZE - rx_strm.avail_out;
|
||||
/*
|
||||
* Z_BUF_ERROR just means no progress was
|
||||
* made, i.e. the decompressor didn't have
|
||||
@@ -423,9 +408,9 @@ recv_deflated_token(int f, char **data)
|
||||
|
||||
case r_inflating:
|
||||
rx_strm.next_out = (Bytef *)dbuf;
|
||||
rx_strm.avail_out = AVAIL_OUT_SIZE(CHUNK_SIZE);
|
||||
rx_strm.avail_out = CHUNK_SIZE;
|
||||
r = inflate(&rx_strm, Z_NO_FLUSH);
|
||||
n = AVAIL_OUT_SIZE(CHUNK_SIZE) - rx_strm.avail_out;
|
||||
n = CHUNK_SIZE - rx_strm.avail_out;
|
||||
if (r != Z_OK) {
|
||||
rprintf(FERROR, "inflate returned %d (%d bytes)\n", r, n);
|
||||
exit_cleanup(RERR_STREAMIO);
|
||||
@@ -480,7 +465,7 @@ static void see_deflate_token(char *buf, int len)
|
||||
}
|
||||
}
|
||||
rx_strm.next_out = (Bytef *)dbuf;
|
||||
rx_strm.avail_out = AVAIL_OUT_SIZE(CHUNK_SIZE);
|
||||
rx_strm.avail_out = CHUNK_SIZE;
|
||||
r = inflate(&rx_strm, Z_SYNC_FLUSH);
|
||||
if (r != Z_OK) {
|
||||
rprintf(FERROR, "inflate (token) returned %d\n", r);
|
||||
|
||||
335
uidlist.c
335
uidlist.c
@@ -1,17 +1,17 @@
|
||||
/*
|
||||
/*
|
||||
Copyright (C) Andrew Tridgell 1996
|
||||
Copyright (C) Paul Mackerras 1996
|
||||
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
@@ -19,19 +19,12 @@
|
||||
|
||||
/* handle the mapping of uid/gid and user/group names between systems.
|
||||
If the source username/group does not exist on the target then use
|
||||
the numeric IDs. Never do any mapping for uid=0 or gid=0 as these
|
||||
the numeric ids. Never do any mapping for uid=0 or gid=0 as these
|
||||
are special.
|
||||
*/
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
#ifdef HAVE_GETGROUPS
|
||||
# if !defined(GETGROUPS_T)
|
||||
# define GETGROUPS_T gid_t
|
||||
# endif
|
||||
#endif
|
||||
|
||||
extern int verbose;
|
||||
extern int preserve_uid;
|
||||
extern int preserve_gid;
|
||||
extern int numeric_ids;
|
||||
@@ -46,26 +39,24 @@ struct idlist {
|
||||
static struct idlist *uidlist;
|
||||
static struct idlist *gidlist;
|
||||
|
||||
static struct idlist *add_to_list(struct idlist **root, int id, char *name,
|
||||
int id2)
|
||||
static struct idlist *add_list(int id, char *name)
|
||||
{
|
||||
struct idlist *node = new(struct idlist);
|
||||
if (!node)
|
||||
out_of_memory("add_to_list");
|
||||
node->next = *root;
|
||||
node->name = name;
|
||||
node->id = id;
|
||||
node->id2 = id2;
|
||||
*root = node;
|
||||
return node;
|
||||
struct idlist *list = new(struct idlist);
|
||||
if (!list) out_of_memory("add_list");
|
||||
list->next = NULL;
|
||||
list->name = strdup(name);
|
||||
if (!list->name) out_of_memory("add_list");
|
||||
list->id = (int)id;
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* turn a uid into a user name */
|
||||
static char *uid_to_name(uid_t uid)
|
||||
{
|
||||
struct passwd *pass = getpwuid(uid);
|
||||
if (pass)
|
||||
return strdup(pass->pw_name);
|
||||
if (pass) return(pass->pw_name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -73,15 +64,14 @@ static char *uid_to_name(uid_t uid)
|
||||
static char *gid_to_name(gid_t gid)
|
||||
{
|
||||
struct group *grp = getgrgid(gid);
|
||||
if (grp)
|
||||
return strdup(grp->gr_name);
|
||||
if (grp) return(grp->gr_name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int map_uid(int id, char *name)
|
||||
{
|
||||
uid_t uid;
|
||||
if (uid != 0 && name_to_uid(name, &uid))
|
||||
if (name_to_uid(name, &uid) && uid != 0)
|
||||
return uid;
|
||||
return id;
|
||||
}
|
||||
@@ -89,180 +79,113 @@ static int map_uid(int id, char *name)
|
||||
static int map_gid(int id, char *name)
|
||||
{
|
||||
gid_t gid;
|
||||
if (gid != 0 && name_to_gid(name, &gid))
|
||||
if (name_to_gid(name, &gid) && gid != 0)
|
||||
return gid;
|
||||
return id;
|
||||
}
|
||||
|
||||
static int is_in_group(gid_t gid)
|
||||
{
|
||||
#ifdef HAVE_GETGROUPS
|
||||
static gid_t last_in = GID_NONE, last_out;
|
||||
static int ngroups = -2;
|
||||
static GETGROUPS_T *gidset;
|
||||
int n;
|
||||
|
||||
if (gid == last_in)
|
||||
return last_out;
|
||||
if (ngroups < -1) {
|
||||
gid_t mygid = MY_GID();
|
||||
if ((ngroups = getgroups(0, NULL)) < 0)
|
||||
ngroups = 0;
|
||||
gidset = new_array(GETGROUPS_T, ngroups+1);
|
||||
if (!gidset)
|
||||
out_of_memory("is_in_group");
|
||||
if (ngroups > 0)
|
||||
ngroups = getgroups(ngroups, gidset);
|
||||
/* The default gid might not be in the list on some systems. */
|
||||
for (n = 0; n < ngroups; n++) {
|
||||
if (gidset[n] == mygid)
|
||||
break;
|
||||
}
|
||||
if (n == ngroups)
|
||||
gidset[ngroups++] = mygid;
|
||||
if (verbose > 3) {
|
||||
int pos;
|
||||
char *gidbuf = new_array(char, ngroups*21+32);
|
||||
if (!gidbuf)
|
||||
out_of_memory("is_in_group");
|
||||
sprintf(gidbuf, "process has %d gid%s: ",
|
||||
ngroups, ngroups == 1? "" : "s");
|
||||
pos = strlen(gidbuf);
|
||||
for (n = 0; n < ngroups; n++) {
|
||||
sprintf(gidbuf+pos, " %d", (int)gidset[n]);
|
||||
pos += strlen(gidbuf+pos);
|
||||
}
|
||||
rprintf(FINFO, "%s\n", gidbuf);
|
||||
free(gidbuf);
|
||||
}
|
||||
}
|
||||
|
||||
last_in = gid;
|
||||
for (n = 0; n < ngroups; n++) {
|
||||
if (gidset[n] == gid)
|
||||
return last_out = 1;
|
||||
}
|
||||
return last_out = 0;
|
||||
|
||||
#else
|
||||
static gid_t mygid = GID_NONE;
|
||||
if (mygid == GID_NONE) {
|
||||
mygid = MY_GID();
|
||||
if (verbose > 3)
|
||||
rprintf(FINFO, "process has gid %d\n", (int)mygid);
|
||||
}
|
||||
return gid == mygid;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Add a uid to the list of uids. Only called on receiving side. */
|
||||
static struct idlist *recv_add_uid(int id, char *name)
|
||||
{
|
||||
int id2 = name ? map_uid(id, name) : id;
|
||||
struct idlist *node;
|
||||
|
||||
node = add_to_list(&uidlist, id, name, map_uid(id, name));
|
||||
|
||||
if (verbose > 3) {
|
||||
rprintf(FINFO, "uid %d(%s) maps to %d\n",
|
||||
id, name ? name : "", id2);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
/* Add a gid to the list of gids. Only called on receiving side. */
|
||||
static struct idlist *recv_add_gid(int id, char *name)
|
||||
{
|
||||
int id2 = name ? map_gid(id, name) : id;
|
||||
struct idlist *node;
|
||||
|
||||
if (!am_root && !is_in_group(id2))
|
||||
id2 = GID_NONE;
|
||||
node = add_to_list(&gidlist, id, name, id2);
|
||||
|
||||
if (verbose > 3) {
|
||||
rprintf(FINFO, "gid %d(%s) maps to %d\n",
|
||||
id, name ? name : "", id2);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
/* this function is a definate candidate for a faster algorithm */
|
||||
static uid_t match_uid(uid_t uid)
|
||||
{
|
||||
static uid_t last_in, last_out;
|
||||
struct idlist *list;
|
||||
struct idlist *list = uidlist;
|
||||
|
||||
if (uid == 0)
|
||||
return 0;
|
||||
|
||||
if (uid == last_in)
|
||||
return last_out;
|
||||
if (uid == last_in) return last_out;
|
||||
|
||||
last_in = uid;
|
||||
|
||||
for (list = uidlist; list; list = list->next) {
|
||||
if (list->id == (int)uid)
|
||||
return last_out = (uid_t)list->id2;
|
||||
while (list) {
|
||||
if (list->id == (int)uid) {
|
||||
last_out = (uid_t)list->id2;
|
||||
return last_out;
|
||||
}
|
||||
list = list->next;
|
||||
}
|
||||
|
||||
return last_out = uid;
|
||||
|
||||
last_out = uid;
|
||||
return last_out;
|
||||
}
|
||||
|
||||
static gid_t match_gid(gid_t gid)
|
||||
{
|
||||
static gid_t last_in = GID_NONE, last_out = GID_NONE;
|
||||
struct idlist *list;
|
||||
static gid_t last_in, last_out;
|
||||
struct idlist *list = gidlist;
|
||||
|
||||
if (gid == GID_NONE)
|
||||
return GID_NONE;
|
||||
|
||||
if (gid == last_in)
|
||||
return last_out;
|
||||
if (gid == last_in) return last_out;
|
||||
|
||||
last_in = gid;
|
||||
|
||||
for (list = gidlist; list; list = list->next) {
|
||||
if (list->id == (int)gid)
|
||||
return last_out = (gid_t)list->id2;
|
||||
while (list) {
|
||||
if (list->id == (int)gid) {
|
||||
last_out = (gid_t)list->id2;
|
||||
return last_out;
|
||||
}
|
||||
list = list->next;
|
||||
}
|
||||
|
||||
list = recv_add_gid(gid, NULL);
|
||||
return last_out = list->id2;
|
||||
|
||||
if (am_root)
|
||||
last_out = gid;
|
||||
else
|
||||
last_out = (gid_t) -1;
|
||||
return last_out;
|
||||
}
|
||||
|
||||
/* Add a uid to the list of uids. Only called on sending side. */
|
||||
/* add a uid to the list of uids */
|
||||
void add_uid(uid_t uid)
|
||||
{
|
||||
struct idlist *list;
|
||||
struct idlist *list = uidlist;
|
||||
char *name;
|
||||
|
||||
if (uid == 0) /* don't map root */
|
||||
if (numeric_ids) return;
|
||||
|
||||
/* don't map root */
|
||||
if (uid==0) return;
|
||||
|
||||
if (!list) {
|
||||
if (!(name = uid_to_name(uid))) return;
|
||||
uidlist = add_list((int)uid, name);
|
||||
return;
|
||||
|
||||
for (list = uidlist; list; list = list->next) {
|
||||
if (list->id == (int)uid)
|
||||
return;
|
||||
}
|
||||
|
||||
add_to_list(&uidlist, (int)uid, uid_to_name(uid), 0);
|
||||
while (list->next) {
|
||||
if (list->id == (int)uid) return;
|
||||
list = list->next;
|
||||
}
|
||||
|
||||
if (list->id == (int)uid) return;
|
||||
|
||||
if (!(name = uid_to_name(uid))) return;
|
||||
|
||||
list->next = add_list((int)uid, name);
|
||||
}
|
||||
|
||||
/* Add a gid to the list of gids. Only called on sending side. */
|
||||
/* add a gid to the list of gids */
|
||||
void add_gid(gid_t gid)
|
||||
{
|
||||
struct idlist *list;
|
||||
struct idlist *list = gidlist;
|
||||
char *name;
|
||||
|
||||
if (gid == 0) /* don't map root */
|
||||
if (numeric_ids) return;
|
||||
|
||||
/* don't map root */
|
||||
if (gid==0) return;
|
||||
|
||||
if (!list) {
|
||||
if (!(name = gid_to_name(gid))) return;
|
||||
gidlist = add_list((int)gid, name);
|
||||
return;
|
||||
|
||||
for (list = gidlist; list; list = list->next) {
|
||||
if (list->id == (int)gid)
|
||||
return;
|
||||
}
|
||||
|
||||
add_to_list(&gidlist, (int)gid, gid_to_name(gid), 0);
|
||||
while (list->next) {
|
||||
if (list->id == (int)gid) return;
|
||||
list = list->next;
|
||||
}
|
||||
|
||||
if (list->id == (int)gid) return;
|
||||
|
||||
if (!(name = gid_to_name(gid))) return;
|
||||
|
||||
list->next = add_list((int)gid, name);
|
||||
}
|
||||
|
||||
|
||||
@@ -271,80 +194,102 @@ void send_uid_list(int f)
|
||||
{
|
||||
struct idlist *list;
|
||||
|
||||
if (numeric_ids)
|
||||
return;
|
||||
if (numeric_ids) return;
|
||||
|
||||
if (preserve_uid) {
|
||||
int len;
|
||||
/* we send sequences of uid/byte-length/name */
|
||||
for (list = uidlist; list; list = list->next) {
|
||||
if (!list->name)
|
||||
continue;
|
||||
len = strlen(list->name);
|
||||
list = uidlist;
|
||||
while (list) {
|
||||
int len = strlen(list->name);
|
||||
write_int(f, list->id);
|
||||
write_byte(f, len);
|
||||
write_buf(f, list->name, len);
|
||||
list = list->next;
|
||||
}
|
||||
|
||||
/* terminate the uid list with a 0 uid. We explicitly exclude
|
||||
* 0 from the list */
|
||||
0 from the list */
|
||||
write_int(f, 0);
|
||||
}
|
||||
|
||||
if (preserve_gid) {
|
||||
int len;
|
||||
for (list = gidlist; list; list = list->next) {
|
||||
if (!list->name)
|
||||
continue;
|
||||
len = strlen(list->name);
|
||||
list = gidlist;
|
||||
while (list) {
|
||||
int len = strlen(list->name);
|
||||
write_int(f, list->id);
|
||||
write_byte(f, len);
|
||||
write_buf(f, list->name, len);
|
||||
list = list->next;
|
||||
}
|
||||
write_int(f, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* recv a complete uid/gid mapping from the peer and map the uid/gid
|
||||
* in the file list to local names */
|
||||
in the file list to local names */
|
||||
void recv_uid_list(int f, struct file_list *flist)
|
||||
{
|
||||
int id, i;
|
||||
char *name;
|
||||
struct idlist *list;
|
||||
|
||||
if (preserve_uid && !numeric_ids) {
|
||||
if (numeric_ids) return;
|
||||
|
||||
if (preserve_uid) {
|
||||
/* read the uid list */
|
||||
while ((id = read_int(f)) != 0) {
|
||||
list = uidlist;
|
||||
id = read_int(f);
|
||||
while (id != 0) {
|
||||
int len = read_byte(f);
|
||||
name = new_array(char, len+1);
|
||||
if (!name)
|
||||
out_of_memory("recv_uid_list");
|
||||
if (!name) out_of_memory("recv_uid_list");
|
||||
read_sbuf(f, name, len);
|
||||
recv_add_uid(id, name); /* node keeps name's memory */
|
||||
if (!list) {
|
||||
uidlist = add_list(id, name);
|
||||
list = uidlist;
|
||||
} else {
|
||||
list->next = add_list(id, name);
|
||||
list = list->next;
|
||||
}
|
||||
list->id2 = map_uid(id, name);
|
||||
free(name);
|
||||
id = read_int(f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (preserve_gid && !numeric_ids) {
|
||||
/* read the gid list */
|
||||
while ((id = read_int(f)) != 0) {
|
||||
if (preserve_gid) {
|
||||
/* and the gid list */
|
||||
list = gidlist;
|
||||
id = read_int(f);
|
||||
while (id != 0) {
|
||||
int len = read_byte(f);
|
||||
name = new_array(char, len+1);
|
||||
if (!name)
|
||||
out_of_memory("recv_uid_list");
|
||||
if (!name) out_of_memory("recv_uid_list");
|
||||
read_sbuf(f, name, len);
|
||||
recv_add_gid(id, name); /* node keeps name's memory */
|
||||
if (!list) {
|
||||
gidlist = add_list(id, name);
|
||||
list = gidlist;
|
||||
} else {
|
||||
list->next = add_list(id, name);
|
||||
list = list->next;
|
||||
}
|
||||
list->id2 = map_gid(id, name);
|
||||
free(name);
|
||||
id = read_int(f);
|
||||
}
|
||||
}
|
||||
|
||||
if (!(am_root && preserve_uid) && !preserve_gid) return;
|
||||
|
||||
/* now convert the uid/gid of all files in the list to the mapped
|
||||
* uid/gid */
|
||||
if (am_root && preserve_uid && !numeric_ids) {
|
||||
for (i = 0; i < flist->count; i++)
|
||||
uid/gid */
|
||||
for (i=0;i<flist->count;i++) {
|
||||
if (am_root && preserve_uid && flist->files[i]->uid != 0) {
|
||||
flist->files[i]->uid = match_uid(flist->files[i]->uid);
|
||||
}
|
||||
if (preserve_gid && (!am_root || !numeric_ids)) {
|
||||
for (i = 0; i < flist->count; i++)
|
||||
}
|
||||
if (preserve_gid && flist->files[i]->gid != 0) {
|
||||
flist->files[i]->gid = match_gid(flist->files[i]->gid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
401
util.c
401
util.c
@@ -1,19 +1,19 @@
|
||||
/* -*- c-file-style: "linux" -*-
|
||||
*
|
||||
* Copyright (C) 1996-2000 by Andrew Tridgell
|
||||
*
|
||||
* Copyright (C) 1996-2000 by Andrew Tridgell
|
||||
* Copyright (C) Paul Mackerras 1996
|
||||
* Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
@@ -22,13 +22,12 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Utilities used in rsync
|
||||
* Utilities used in rsync
|
||||
**/
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
extern int verbose;
|
||||
extern struct exclude_list_struct server_exclude_list;
|
||||
|
||||
int sanitize_paths = 0;
|
||||
|
||||
@@ -68,7 +67,7 @@ void set_blocking(int fd)
|
||||
/**
|
||||
* Create a file descriptor pair - like pipe() but use socketpair if
|
||||
* possible (because of blocking issues on pipes).
|
||||
*
|
||||
*
|
||||
* Always set non-blocking.
|
||||
*/
|
||||
int fd_pair(int fd[2])
|
||||
@@ -112,14 +111,14 @@ void print_child_argv(char **cmd)
|
||||
|
||||
void out_of_memory(char *str)
|
||||
{
|
||||
rprintf(FERROR, "ERROR: out of memory in %s\n", str);
|
||||
exit_cleanup(RERR_MALLOC);
|
||||
rprintf(FERROR,"ERROR: out of memory in %s\n",str);
|
||||
exit_cleanup(RERR_MALLOC);
|
||||
}
|
||||
|
||||
void overflow(char *str)
|
||||
{
|
||||
rprintf(FERROR, "ERROR: buffer overflow in %s\n", str);
|
||||
exit_cleanup(RERR_MALLOC);
|
||||
rprintf(FERROR,"ERROR: buffer overflow in %s\n",str);
|
||||
exit_cleanup(RERR_MALLOC);
|
||||
}
|
||||
|
||||
|
||||
@@ -135,10 +134,10 @@ int set_modtime(char *fname, time_t modtime)
|
||||
fname, (long) modtime,
|
||||
asctime(localtime(&modtime)));
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
#ifdef HAVE_UTIMBUF
|
||||
struct utimbuf tbuf;
|
||||
struct utimbuf tbuf;
|
||||
tbuf.actime = time(NULL);
|
||||
tbuf.modtime = modtime;
|
||||
return utime(fname,&tbuf);
|
||||
@@ -168,15 +167,13 @@ int create_directory_path(char *fname, int base_umask)
|
||||
{
|
||||
char *p;
|
||||
|
||||
while (*fname == '/')
|
||||
fname++;
|
||||
while (strncmp(fname, "./", 2) == 0)
|
||||
fname += 2;
|
||||
while (*fname == '/') fname++;
|
||||
while (strncmp(fname,"./",2)==0) fname += 2;
|
||||
|
||||
p = fname;
|
||||
while ((p = strchr(p,'/')) != NULL) {
|
||||
while ((p=strchr(p,'/'))) {
|
||||
*p = 0;
|
||||
do_mkdir(fname, 0777 & ~base_umask);
|
||||
do_mkdir(fname, 0777 & ~base_umask);
|
||||
*p = '/';
|
||||
p++;
|
||||
}
|
||||
@@ -197,13 +194,15 @@ int create_directory_path(char *fname, int base_umask)
|
||||
static int full_write(int desc, char *ptr, size_t len)
|
||||
{
|
||||
int total_written;
|
||||
|
||||
|
||||
total_written = 0;
|
||||
while (len > 0) {
|
||||
int written = write(desc, ptr, len);
|
||||
int written = write (desc, ptr, len);
|
||||
if (written < 0) {
|
||||
#ifdef EINTR
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
#endif
|
||||
return written;
|
||||
}
|
||||
total_written += written;
|
||||
@@ -228,14 +227,18 @@ static int full_write(int desc, char *ptr, size_t len)
|
||||
static int safe_read(int desc, char *ptr, size_t len)
|
||||
{
|
||||
int n_chars;
|
||||
|
||||
|
||||
if (len == 0)
|
||||
return len;
|
||||
|
||||
|
||||
#ifdef EINTR
|
||||
do {
|
||||
n_chars = read(desc, ptr, len);
|
||||
} while (n_chars < 0 && errno == EINTR);
|
||||
|
||||
#else
|
||||
n_chars = read(desc, ptr, len);
|
||||
#endif
|
||||
|
||||
return n_chars;
|
||||
}
|
||||
|
||||
@@ -271,7 +274,7 @@ int copy_file(char *source, char *dest, mode_t mode)
|
||||
return -1;
|
||||
}
|
||||
|
||||
while ((len = safe_read(ifd, buf, sizeof buf)) > 0) {
|
||||
while ((len = safe_read(ifd, buf, sizeof(buf))) > 0) {
|
||||
if (full_write(ofd, buf, len) < 0) {
|
||||
rprintf(FERROR,"write %s: %s\n",
|
||||
dest,strerror(errno));
|
||||
@@ -317,15 +320,17 @@ int robust_unlink(char *fname)
|
||||
char path[MAXPATHLEN];
|
||||
|
||||
rc = do_unlink(fname);
|
||||
if (rc == 0 || errno != ETXTBSY)
|
||||
if ((rc == 0) || (errno != ETXTBSY))
|
||||
return rc;
|
||||
|
||||
if ((pos = strlcpy(path, fname, MAXPATHLEN)) >= MAXPATHLEN)
|
||||
pos = MAXPATHLEN - 1;
|
||||
strlcpy(path, fname, MAXPATHLEN);
|
||||
|
||||
while (pos > 0 && path[pos-1] != '/')
|
||||
pos--;
|
||||
pos += strlcpy(path+pos, ".rsync", MAXPATHLEN-pos);
|
||||
pos = strlen(path);
|
||||
while((path[--pos] != '/') && (pos >= 0))
|
||||
;
|
||||
++pos;
|
||||
strlcpy(&path[pos], ".rsync", MAXPATHLEN-pos);
|
||||
pos += sizeof(".rsync")-1;
|
||||
|
||||
if (pos > (MAXPATHLEN-MAX_RENAMES_DIGITS-1)) {
|
||||
errno = ETXTBSY;
|
||||
@@ -338,12 +343,11 @@ int robust_unlink(char *fname)
|
||||
sprintf(&path[pos], "%03d", counter);
|
||||
if (++counter >= MAX_RENAMES)
|
||||
counter = 1;
|
||||
} while ((rc = access(path, 0)) == 0 && counter != start);
|
||||
} while (((rc = access(path, 0)) == 0) && (counter != start));
|
||||
|
||||
if (verbose > 0) {
|
||||
if (verbose > 0)
|
||||
rprintf(FINFO,"renaming %s to %s because of text busy\n",
|
||||
fname, path);
|
||||
}
|
||||
fname, path);
|
||||
|
||||
/* maybe we should return rename()'s exit status? Nah. */
|
||||
if (do_rename(fname, path) != 0) {
|
||||
@@ -354,33 +358,18 @@ int robust_unlink(char *fname)
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Returns 0 on success, -1 on most errors, and -2 if we got an error
|
||||
* trying to copy the file across file systems. */
|
||||
int robust_rename(char *from, char *to, int mode)
|
||||
int robust_rename(char *from, char *to)
|
||||
{
|
||||
int tries = 4;
|
||||
|
||||
while (tries--) {
|
||||
if (do_rename(from, to) == 0)
|
||||
return 0;
|
||||
|
||||
switch (errno) {
|
||||
#ifdef ETXTBSY
|
||||
case ETXTBSY:
|
||||
if (robust_unlink(to) != 0)
|
||||
return -1;
|
||||
break;
|
||||
#ifndef ETXTBSY
|
||||
return do_rename(from, to);
|
||||
#else
|
||||
int rc = do_rename(from, to);
|
||||
if ((rc == 0) || (errno != ETXTBSY))
|
||||
return rc;
|
||||
if (robust_unlink(to) != 0)
|
||||
return -1;
|
||||
return do_rename(from, to);
|
||||
#endif
|
||||
case EXDEV:
|
||||
if (copy_file(from, to, mode) != 0)
|
||||
return -2;
|
||||
do_unlink(from);
|
||||
return 0;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -391,7 +380,7 @@ static int num_pids;
|
||||
pid_t do_fork(void)
|
||||
{
|
||||
pid_t newpid = fork();
|
||||
|
||||
|
||||
if (newpid != 0 && newpid != -1) {
|
||||
all_pids[num_pids++] = newpid;
|
||||
}
|
||||
@@ -465,34 +454,18 @@ int lock_range(int fd, int offset, int len)
|
||||
lock.l_start = offset;
|
||||
lock.l_len = len;
|
||||
lock.l_pid = 0;
|
||||
|
||||
|
||||
return fcntl(fd,F_SETLK,&lock) == 0;
|
||||
}
|
||||
|
||||
static int exclude_server_path(char *arg)
|
||||
{
|
||||
char *s;
|
||||
|
||||
if (server_exclude_list.head) {
|
||||
for (s = arg; (s = strchr(s, '/')) != NULL; ) {
|
||||
*s = '\0';
|
||||
if (check_exclude(&server_exclude_list, arg, 1) < 0) {
|
||||
/* We must leave arg truncated! */
|
||||
return 1;
|
||||
}
|
||||
*s++ = '/';
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void glob_expand_one(char *s, char **argv, int *argc, int maxargs)
|
||||
{
|
||||
#if !(defined(HAVE_GLOB) && defined(HAVE_GLOB_H))
|
||||
if (!*s) s = ".";
|
||||
s = argv[*argc] = strdup(s);
|
||||
exclude_server_path(s);
|
||||
argv[*argc] = strdup(s);
|
||||
(*argc)++;
|
||||
return;
|
||||
#else
|
||||
extern int sanitize_paths;
|
||||
glob_t globbuf;
|
||||
@@ -500,60 +473,54 @@ static void glob_expand_one(char *s, char **argv, int *argc, int maxargs)
|
||||
|
||||
if (!*s) s = ".";
|
||||
|
||||
s = argv[*argc] = strdup(s);
|
||||
argv[*argc] = strdup(s);
|
||||
if (sanitize_paths) {
|
||||
sanitize_path(s, NULL);
|
||||
sanitize_path(argv[*argc], NULL);
|
||||
}
|
||||
|
||||
memset(&globbuf, 0, sizeof globbuf);
|
||||
if (!exclude_server_path(s))
|
||||
glob(s, 0, NULL, &globbuf);
|
||||
memset(&globbuf, 0, sizeof(globbuf));
|
||||
glob(argv[*argc], 0, NULL, &globbuf);
|
||||
if (globbuf.gl_pathc == 0) {
|
||||
(*argc)++;
|
||||
globfree(&globbuf);
|
||||
return;
|
||||
}
|
||||
for (i = 0; i < maxargs - *argc && i < (int)globbuf.gl_pathc; i++) {
|
||||
if (i == 0)
|
||||
free(s);
|
||||
argv[*argc + i] = strdup(globbuf.gl_pathv[i]);
|
||||
if (!argv[*argc + i])
|
||||
out_of_memory("glob_expand");
|
||||
for (i=0; i<(maxargs - (*argc)) && i < (int) globbuf.gl_pathc;i++) {
|
||||
if (i == 0) free(argv[*argc]);
|
||||
argv[(*argc) + i] = strdup(globbuf.gl_pathv[i]);
|
||||
if (!argv[(*argc) + i]) out_of_memory("glob_expand");
|
||||
}
|
||||
globfree(&globbuf);
|
||||
*argc += i;
|
||||
(*argc) += i;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* This routine is only used in daemon mode. */
|
||||
void glob_expand(char *base1, char **argv, int *argc, int maxargs)
|
||||
{
|
||||
char *s = argv[*argc];
|
||||
char *p, *q;
|
||||
char *base = base1;
|
||||
int base_len = strlen(base);
|
||||
|
||||
if (!s || !*s) return;
|
||||
|
||||
if (strncmp(s, base, base_len) == 0)
|
||||
s += base_len;
|
||||
if (strncmp(s, base, strlen(base)) == 0) {
|
||||
s += strlen(base);
|
||||
}
|
||||
|
||||
s = strdup(s);
|
||||
if (!s) out_of_memory("glob_expand");
|
||||
|
||||
if (asprintf(&base," %s/", base1) <= 0) out_of_memory("glob_expand");
|
||||
base_len++;
|
||||
|
||||
q = s;
|
||||
while ((p = strstr(q,base)) != NULL && *argc < maxargs) {
|
||||
while ((p = strstr(q,base)) && ((*argc) < maxargs)) {
|
||||
/* split it at this point */
|
||||
*p = 0;
|
||||
glob_expand_one(q, argv, argc, maxargs);
|
||||
q = p + base_len;
|
||||
q = p+strlen(base);
|
||||
}
|
||||
|
||||
if (*q && *argc < maxargs)
|
||||
glob_expand_one(q, argv, argc, maxargs);
|
||||
if (*q && (*argc < maxargs)) glob_expand_one(q, argv, argc, maxargs);
|
||||
|
||||
free(s);
|
||||
free(base);
|
||||
@@ -571,58 +538,6 @@ void strlower(char *s)
|
||||
}
|
||||
}
|
||||
|
||||
/* Join strings p1 & p2 into "dest" with a guaranteed '/' between them. (If
|
||||
* p1 ends with a '/', no extra '/' is inserted.) Returns the length of both
|
||||
* strings + 1 (if '/' was inserted), regardless of whether the null-terminated
|
||||
* string fits into destsize. */
|
||||
size_t pathjoin(char *dest, size_t destsize, const char *p1, const char *p2)
|
||||
{
|
||||
size_t len = strlcpy(dest, p1, destsize);
|
||||
if (len < destsize - 1) {
|
||||
if (!len || dest[len-1] != '/')
|
||||
dest[len++] = '/';
|
||||
if (len < destsize - 1)
|
||||
len += strlcpy(dest + len, p2, destsize - len);
|
||||
else {
|
||||
dest[len] = '\0';
|
||||
len += strlen(p2);
|
||||
}
|
||||
}
|
||||
else
|
||||
len += strlen(p2) + 1; /* Assume we'd insert a '/'. */
|
||||
return len;
|
||||
}
|
||||
|
||||
/* Join any number of strings together, putting them in "dest". The return
|
||||
* value is the length of all the strings, regardless of whether the null-
|
||||
* terminated whole fits in destsize. Your list of string pointers must end
|
||||
* with a NULL to indicate the end of the list. */
|
||||
size_t stringjoin(char *dest, size_t destsize, ...)
|
||||
{
|
||||
va_list ap;
|
||||
size_t len, ret = 0;
|
||||
const char *src;
|
||||
|
||||
va_start(ap, destsize);
|
||||
while (1) {
|
||||
if (!(src = va_arg(ap, const char *)))
|
||||
break;
|
||||
len = strlen(src);
|
||||
ret += len;
|
||||
if (destsize > 1) {
|
||||
if (len >= destsize)
|
||||
len = destsize - 1;
|
||||
memcpy(dest, src, len);
|
||||
destsize -= len;
|
||||
dest += len;
|
||||
}
|
||||
}
|
||||
*dest = '\0';
|
||||
va_end(ap);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void clean_fname(char *name)
|
||||
{
|
||||
char *p;
|
||||
@@ -634,7 +549,7 @@ void clean_fname(char *name)
|
||||
while (modified) {
|
||||
modified = 0;
|
||||
|
||||
if ((p = strstr(name,"/./")) != NULL) {
|
||||
if ((p=strstr(name,"/./"))) {
|
||||
modified = 1;
|
||||
while (*p) {
|
||||
p[0] = p[2];
|
||||
@@ -642,7 +557,7 @@ void clean_fname(char *name)
|
||||
}
|
||||
}
|
||||
|
||||
if ((p = strstr(name,"//")) != NULL) {
|
||||
if ((p=strstr(name,"//"))) {
|
||||
modified = 1;
|
||||
while (*p) {
|
||||
p[0] = p[1];
|
||||
@@ -650,14 +565,14 @@ void clean_fname(char *name)
|
||||
}
|
||||
}
|
||||
|
||||
if (strncmp(p = name, "./", 2) == 0) {
|
||||
if (strncmp(p=name,"./",2) == 0) {
|
||||
modified = 1;
|
||||
do {
|
||||
p[0] = p[2];
|
||||
} while (*p++);
|
||||
}
|
||||
|
||||
l = strlen(p = name);
|
||||
l = strlen(p=name);
|
||||
if (l > 1 && p[l-1] == '/') {
|
||||
modified = 1;
|
||||
p[l-1] = 0;
|
||||
@@ -716,7 +631,7 @@ void sanitize_path(char *p, char *reldir)
|
||||
* both p (and sanp if the original had a slash) should
|
||||
* always be left pointing after a slash
|
||||
*/
|
||||
if (*p == '.' && (p[1] == '/' || p[1] == '\0')) {
|
||||
if ((*p == '.') && ((*(p+1) == '/') || (*(p+1) == '\0'))) {
|
||||
/* skip "." component */
|
||||
while (*++p == '/') {
|
||||
/* skip following slashes */
|
||||
@@ -725,9 +640,10 @@ void sanitize_path(char *p, char *reldir)
|
||||
continue;
|
||||
}
|
||||
allowdotdot = 0;
|
||||
if (*p == '.' && p[1] == '.' && (p[2] == '/' || p[2] == '\0')) {
|
||||
if ((*p == '.') && (*(p+1) == '.') &&
|
||||
((*(p+2) == '/') || (*(p+2) == '\0'))) {
|
||||
/* ".." component followed by slash or end */
|
||||
if (depth > 0 && sanp == start) {
|
||||
if ((depth > 0) && (sanp == start)) {
|
||||
/* allow depth levels of .. at the beginning */
|
||||
--depth;
|
||||
allowdotdot = 1;
|
||||
@@ -738,7 +654,7 @@ void sanitize_path(char *p, char *reldir)
|
||||
if (sanp != start) {
|
||||
/* back up sanp one level */
|
||||
--sanp; /* now pointing at slash */
|
||||
while (sanp > start && sanp[-1] != '/') {
|
||||
while ((sanp > start) && (*(sanp - 1) != '/')) {
|
||||
/* skip back up to slash */
|
||||
sanp--;
|
||||
}
|
||||
@@ -749,7 +665,7 @@ void sanitize_path(char *p, char *reldir)
|
||||
while (1) {
|
||||
/* copy one component through next slash */
|
||||
*sanp++ = *p++;
|
||||
if (*p == '\0' || p[-1] == '/') {
|
||||
if ((*p == '\0') || (*(p-1) == '/')) {
|
||||
while (*p == '/') {
|
||||
/* skip multiple slashes */
|
||||
p++;
|
||||
@@ -762,7 +678,7 @@ void sanitize_path(char *p, char *reldir)
|
||||
start = sanp;
|
||||
}
|
||||
}
|
||||
if (sanp == start && !allowdotdot) {
|
||||
if ((sanp == start) && !allowdotdot) {
|
||||
/* ended up with nothing, so put in "." component */
|
||||
/*
|
||||
* note that the !allowdotdot doesn't prevent this from
|
||||
@@ -775,146 +691,59 @@ void sanitize_path(char *p, char *reldir)
|
||||
*sanp = '\0';
|
||||
}
|
||||
|
||||
/* Works much like sanitize_path(), with these differences: (1) a new buffer
|
||||
* is allocated for the sanitized path rather than modifying it in-place; (2)
|
||||
* a leading slash gets transformed into the rootdir value (which can be empty
|
||||
* or NULL if you just want the slash to get dropped); (3) no "reldir" can be
|
||||
* specified. */
|
||||
char *alloc_sanitize_path(const char *path, const char *rootdir)
|
||||
{
|
||||
char *buf;
|
||||
int rlen, plen = strlen(path);
|
||||
|
||||
if (*path == '/' && rootdir) {
|
||||
rlen = strlen(rootdir);
|
||||
if (rlen == 1)
|
||||
path++;
|
||||
} else
|
||||
rlen = 0;
|
||||
if (!(buf = new_array(char, rlen + plen + 1)))
|
||||
out_of_memory("alloc_sanitize_path");
|
||||
if (rlen)
|
||||
memcpy(buf, rootdir, rlen);
|
||||
memcpy(buf + rlen, path, plen + 1);
|
||||
|
||||
if (rlen > 1)
|
||||
rlen++;
|
||||
sanitize_path(buf + rlen, NULL);
|
||||
if (rlen && buf[rlen] == '.' && buf[rlen+1] == '\0') {
|
||||
if (rlen > 1)
|
||||
rlen--;
|
||||
buf[rlen] = '\0';
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
char curr_dir[MAXPATHLEN];
|
||||
unsigned int curr_dir_len;
|
||||
static char curr_dir[MAXPATHLEN];
|
||||
|
||||
/**
|
||||
* Like chdir(), but it keeps track of the current directory (in the
|
||||
* global "curr_dir"), and ensures that the path size doesn't overflow.
|
||||
* Also cleans the path using the clean_fname() function.
|
||||
* Like chdir() but can be reversed with pop_dir() if @p save is set.
|
||||
* It is also much faster as it remembers where we have been.
|
||||
**/
|
||||
int push_dir(char *dir)
|
||||
char *push_dir(char *dir, int save)
|
||||
{
|
||||
char *ret = curr_dir;
|
||||
static int initialised;
|
||||
unsigned int len;
|
||||
|
||||
if (!initialised) {
|
||||
initialised = 1;
|
||||
getcwd(curr_dir, sizeof curr_dir - 1);
|
||||
curr_dir_len = strlen(curr_dir);
|
||||
getcwd(curr_dir, sizeof(curr_dir)-1);
|
||||
}
|
||||
|
||||
if (!dir) /* this call was probably just to initialize */
|
||||
return 0;
|
||||
if (!dir) return NULL; /* this call was probably just to initialize */
|
||||
|
||||
len = strlen(dir);
|
||||
if (len == 1 && *dir == '.')
|
||||
return 1;
|
||||
if (chdir(dir)) return NULL;
|
||||
|
||||
if ((*dir == '/' ? len : curr_dir_len + 1 + len) >= sizeof curr_dir)
|
||||
return 0;
|
||||
|
||||
if (chdir(dir))
|
||||
return 0;
|
||||
if (save) {
|
||||
ret = strdup(curr_dir);
|
||||
}
|
||||
|
||||
if (*dir == '/') {
|
||||
memcpy(curr_dir, dir, len + 1);
|
||||
curr_dir_len = len;
|
||||
strlcpy(curr_dir, dir, sizeof(curr_dir));
|
||||
} else {
|
||||
curr_dir[curr_dir_len++] = '/';
|
||||
memcpy(curr_dir + curr_dir_len, dir, len + 1);
|
||||
curr_dir_len += len;
|
||||
strlcat(curr_dir,"/", sizeof(curr_dir));
|
||||
strlcat(curr_dir,dir, sizeof(curr_dir));
|
||||
}
|
||||
|
||||
clean_fname(curr_dir);
|
||||
|
||||
return 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse a push_dir() call. You must pass in an absolute path
|
||||
* that was copied from a prior value of "curr_dir".
|
||||
**/
|
||||
/** Reverse a push_dir() call */
|
||||
int pop_dir(char *dir)
|
||||
{
|
||||
if (chdir(dir))
|
||||
return 0;
|
||||
int ret;
|
||||
|
||||
curr_dir_len = strlcpy(curr_dir, dir, sizeof curr_dir);
|
||||
if (curr_dir_len >= sizeof curr_dir)
|
||||
curr_dir_len = sizeof curr_dir - 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a quoted string with the full pathname of the indicated filename.
|
||||
* The string " (in MODNAME)" may also be appended. The returned pointer
|
||||
* remains valid until the next time full_fname() is called.
|
||||
**/
|
||||
char *full_fname(char *fn)
|
||||
{
|
||||
extern int module_id;
|
||||
static char *result = NULL;
|
||||
char *m1, *m2, *m3;
|
||||
char *p1, *p2;
|
||||
|
||||
if (result)
|
||||
free(result);
|
||||
|
||||
if (*fn == '/')
|
||||
p1 = p2 = "";
|
||||
else {
|
||||
p1 = curr_dir;
|
||||
p2 = "/";
|
||||
ret = chdir(dir);
|
||||
if (ret) {
|
||||
free(dir);
|
||||
return ret;
|
||||
}
|
||||
if (module_id >= 0) {
|
||||
m1 = " (in ";
|
||||
m2 = lp_name(module_id);
|
||||
m3 = ")";
|
||||
if (*p1) {
|
||||
if (!lp_use_chroot(module_id)) {
|
||||
char *p = lp_path(module_id);
|
||||
if (*p != '/' || p[1])
|
||||
p1 += strlen(p);
|
||||
}
|
||||
if (!*p1)
|
||||
p2++;
|
||||
else
|
||||
p1++;
|
||||
}
|
||||
else
|
||||
fn++;
|
||||
} else
|
||||
m1 = m2 = m3 = "";
|
||||
|
||||
asprintf(&result, "\"%s%s%s\"%s%s%s", p1, p2, fn, m1, m2, m3);
|
||||
strlcpy(curr_dir, dir, sizeof(curr_dir));
|
||||
|
||||
return result;
|
||||
free(dir);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** We need to supply our own strcmp function for file list comparisons
|
||||
@@ -927,7 +756,7 @@ int u_strcmp(const char *cs1, const char *cs2)
|
||||
while (*s1 && *s2 && (*s1 == *s2)) {
|
||||
s1++; s2++;
|
||||
}
|
||||
|
||||
|
||||
return (int)*s1 - (int)*s2;
|
||||
}
|
||||
|
||||
@@ -968,7 +797,7 @@ int unsafe_symlink(const char *dest, const char *src)
|
||||
/* find out what our safety margin is */
|
||||
for (name = src; (slash = strchr(name, '/')) != 0; name = slash+1) {
|
||||
if (strncmp(name, "../", 3) == 0) {
|
||||
depth = 0;
|
||||
depth=0;
|
||||
} else if (strncmp(name, "./", 2) == 0) {
|
||||
/* nothing */
|
||||
} else {
|
||||
@@ -1006,9 +835,9 @@ char *timestring(time_t t)
|
||||
struct tm *tm = localtime(&t);
|
||||
|
||||
#ifdef HAVE_STRFTIME
|
||||
strftime(TimeBuf, sizeof TimeBuf - 1, "%Y/%m/%d %H:%M:%S", tm);
|
||||
strftime(TimeBuf,sizeof(TimeBuf)-1,"%Y/%m/%d %T",tm);
|
||||
#else
|
||||
strlcpy(TimeBuf, asctime(tm), sizeof TimeBuf);
|
||||
strlcpy(TimeBuf, asctime(tm), sizeof(TimeBuf));
|
||||
#endif
|
||||
|
||||
if (TimeBuf[strlen(TimeBuf)-1] == '\n') {
|
||||
@@ -1027,21 +856,21 @@ char *timestring(time_t t)
|
||||
**/
|
||||
int msleep(int t)
|
||||
{
|
||||
int tdiff = 0;
|
||||
struct timeval tval, t1, t2;
|
||||
int tdiff=0;
|
||||
struct timeval tval,t1,t2;
|
||||
|
||||
gettimeofday(&t1, NULL);
|
||||
gettimeofday(&t2, NULL);
|
||||
|
||||
|
||||
while (tdiff < t) {
|
||||
tval.tv_sec = (t-tdiff)/1000;
|
||||
tval.tv_usec = 1000*((t-tdiff)%1000);
|
||||
|
||||
|
||||
errno = 0;
|
||||
select(0,NULL,NULL, NULL, &tval);
|
||||
|
||||
gettimeofday(&t2, NULL);
|
||||
tdiff = (t2.tv_sec - t1.tv_sec)*1000 +
|
||||
tdiff = (t2.tv_sec - t1.tv_sec)*1000 +
|
||||
(t2.tv_usec - t1.tv_usec)/1000;
|
||||
}
|
||||
|
||||
@@ -1087,7 +916,7 @@ int _Insure_trap_error(int a1, int a2, int a3, int a4, int a5, int a6)
|
||||
int ret;
|
||||
char *cmd;
|
||||
|
||||
asprintf(&cmd, "/usr/X11R6/bin/xterm -display :0 -T Panic -n Panic -e /bin/sh -c 'cat /tmp/ierrs.*.%d ; gdb /proc/%d/exe %d'",
|
||||
asprintf(&cmd, "/usr/X11R6/bin/xterm -display :0 -T Panic -n Panic -e /bin/sh -c 'cat /tmp/ierrs.*.%d ; gdb /proc/%d/exe %d'",
|
||||
getpid(), getpid(), getpid());
|
||||
|
||||
if (!fn) {
|
||||
|
||||
25
wildtest.c
25
wildtest.c
@@ -19,6 +19,9 @@ int wildmatch_errors = 0;
|
||||
|
||||
typedef char bool;
|
||||
|
||||
#define false 0
|
||||
#define true 1
|
||||
|
||||
int output_iterations = 0;
|
||||
|
||||
static struct poptOption long_options[] = {
|
||||
@@ -81,14 +84,8 @@ main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
argv = (char**)poptGetArgs(pc);
|
||||
if (!argv || argv[1]) {
|
||||
fprintf(stderr, "Usage: wildtest TESTFILE\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if ((fp = fopen(*argv, "r")) == NULL) {
|
||||
fprintf(stderr, "Unable to open %s\n", *argv);
|
||||
if ((fp = fopen("wildtest.txt", "r")) == NULL) {
|
||||
fprintf(stderr, "Unable to open wildtest.txt.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -107,8 +104,8 @@ main(int argc, char **argv)
|
||||
if (*++s != ' ' && *s != '\t')
|
||||
flag[i] = -1;
|
||||
if (flag[i] < 0) {
|
||||
fprintf(stderr, "Invalid flag syntax on line %d of %s:\n%s",
|
||||
line, *argv, buf);
|
||||
fprintf(stderr, "Invalid flag syntax on line %d of wildtest.txt:%s\n",
|
||||
line, buf);
|
||||
exit(1);
|
||||
}
|
||||
while (*++s == ' ' || *s == '\t') {}
|
||||
@@ -119,16 +116,16 @@ main(int argc, char **argv)
|
||||
string[i] = s;
|
||||
while (*s && *s != quote) s++;
|
||||
if (!*s) {
|
||||
fprintf(stderr, "Unmatched quote on line %d of %s:\n%s",
|
||||
line, *argv, buf);
|
||||
fprintf(stderr, "Unmatched quote on line %d of wildtest.txt:%s\n",
|
||||
line, buf);
|
||||
exit(1);
|
||||
}
|
||||
end[i] = s;
|
||||
}
|
||||
else {
|
||||
if (!*s || *s == '\n') {
|
||||
fprintf(stderr, "Not enough strings on line %d of %s:\n%s",
|
||||
line, *argv, buf);
|
||||
fprintf(stderr, "Not enough strings on line %d of wildtest.txt:%s\n",
|
||||
line, buf);
|
||||
exit(1);
|
||||
}
|
||||
string[i] = s;
|
||||
|
||||
Reference in New Issue
Block a user