mirror of
https://github.com/RsyncProject/rsync.git
synced 2026-05-25 07:15:35 -04:00
Compare commits
174 Commits
v2.4.7pre4
...
v2.4.8pre1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d19fa730b9 | ||
|
|
5c6e0ee27c | ||
|
|
0d95824995 | ||
|
|
bbc09ffba9 | ||
|
|
a4677968cf | ||
|
|
03b1cddc31 | ||
|
|
9c2dd04993 | ||
|
|
a84a93fafe | ||
|
|
5fdcc397b1 | ||
|
|
5664871e5f | ||
|
|
55d9e0fada | ||
|
|
929e3011c6 | ||
|
|
07d70ff560 | ||
|
|
58c2960960 | ||
|
|
00d943d513 | ||
|
|
71c780da06 | ||
|
|
3b18cba889 | ||
|
|
2974e20550 | ||
|
|
430d841a2c | ||
|
|
31ec50d7da | ||
|
|
5ad0e46f08 | ||
|
|
1b5814e338 | ||
|
|
255810c0d6 | ||
|
|
5d2640376e | ||
|
|
d02984bbb7 | ||
|
|
0f9555207a | ||
|
|
885448d74c | ||
|
|
b14545b3ff | ||
|
|
9a5a86734f | ||
|
|
d1d1505045 | ||
|
|
144ce1dc21 | ||
|
|
aa126974ba | ||
|
|
707de53457 | ||
|
|
10f83cf43d | ||
|
|
59ee743c5f | ||
|
|
d54765c442 | ||
|
|
91262d5d3e | ||
|
|
1c09c743b1 | ||
|
|
06ce139fcc | ||
|
|
fae5bb3183 | ||
|
|
6fe25398d6 | ||
|
|
909ce14fc4 | ||
|
|
935b920120 | ||
|
|
b31427cd4a | ||
|
|
e2e3379d79 | ||
|
|
6b1ef85dd8 | ||
|
|
92325ada0c | ||
|
|
1707e0f9e2 | ||
|
|
7ff701e816 | ||
|
|
2e3c141795 | ||
|
|
76f79ba748 | ||
|
|
9dd891bb28 | ||
|
|
99f106d1cf | ||
|
|
3816cae745 | ||
|
|
759c0627e1 | ||
|
|
e03dfae507 | ||
|
|
c7677b892a | ||
|
|
da7b63972d | ||
|
|
499957d9ba | ||
|
|
582250008b | ||
|
|
a9b31409d5 | ||
|
|
98355b8086 | ||
|
|
70ed474b38 | ||
|
|
4775934364 | ||
|
|
25f2cb3d6b | ||
|
|
154f9a3aca | ||
|
|
b9df3bf20c | ||
|
|
6abd193fe3 | ||
|
|
362099a512 | ||
|
|
fdfc3dc9f3 | ||
|
|
4937459225 | ||
|
|
be2f866b4c | ||
|
|
f08aacf7d6 | ||
|
|
4fa6112efe | ||
|
|
1623ba6889 | ||
|
|
766526c791 | ||
|
|
5c15e29f2b | ||
|
|
0413e1605f | ||
|
|
0e5a1f8352 | ||
|
|
e5a2b8544d | ||
|
|
736a6a291c | ||
|
|
6e69cff118 | ||
|
|
cf72f20426 | ||
|
|
d479210cee | ||
|
|
b781537597 | ||
|
|
ea1438dad8 | ||
|
|
d2e9d069b4 | ||
|
|
58379559cc | ||
|
|
b3e6c81565 | ||
|
|
a6a3c3df45 | ||
|
|
6e3d4c4045 | ||
|
|
ca60b701ee | ||
|
|
e24c0b98d7 | ||
|
|
f389ac80a9 | ||
|
|
50f2f002d9 | ||
|
|
9ec7528475 | ||
|
|
a8e2a43a09 | ||
|
|
eb06fa95e4 | ||
|
|
1db8b61de7 | ||
|
|
38c66db8d6 | ||
|
|
f8be7d4219 | ||
|
|
13e29995f5 | ||
|
|
7c583c7316 | ||
|
|
9fecec5e85 | ||
|
|
9e696bd468 | ||
|
|
6ab6d4bfc1 | ||
|
|
cb1bcc7ebb | ||
|
|
19ba7d6318 | ||
|
|
7753ca1f49 | ||
|
|
d52a796c39 | ||
|
|
60514d457c | ||
|
|
5bc00efe42 | ||
|
|
c45f3133bc | ||
|
|
fb47591de0 | ||
|
|
514d129c49 | ||
|
|
db843fc12d | ||
|
|
63787382d8 | ||
|
|
85d4d142d8 | ||
|
|
3cd2af41e4 | ||
|
|
b214eda4f0 | ||
|
|
0771727d41 | ||
|
|
a5d74a1876 | ||
|
|
23bf32f767 | ||
|
|
87a819edee | ||
|
|
27a1234874 | ||
|
|
51f289d1e6 | ||
|
|
d0d6dc61e8 | ||
|
|
d91c8c50d2 | ||
|
|
e20a4f84d6 | ||
|
|
bbd6f4ba8e | ||
|
|
2a951cd2f9 | ||
|
|
a538066d5a | ||
|
|
c10b0bdd50 | ||
|
|
431efc8979 | ||
|
|
2d6dbe290c | ||
|
|
c33e3e3967 | ||
|
|
71b3374bd5 | ||
|
|
de343e3cce | ||
|
|
384958ed3d | ||
|
|
1cd5beeb06 | ||
|
|
4c70e359d0 | ||
|
|
f9c3005bff | ||
|
|
9147074d8b | ||
|
|
7007bddaef | ||
|
|
2f8dc29182 | ||
|
|
6066594bbe | ||
|
|
40c0289176 | ||
|
|
acf1af0cd9 | ||
|
|
62791bdfa2 | ||
|
|
47f1218d69 | ||
|
|
1179355dab | ||
|
|
3d807132e4 | ||
|
|
42d0b4c280 | ||
|
|
d313ae7d23 | ||
|
|
28a69e25ea | ||
|
|
ad911a7ac3 | ||
|
|
5575de140d | ||
|
|
a5ce1eb1af | ||
|
|
76a78cd8bc | ||
|
|
0b25efc12a | ||
|
|
64cae087b6 | ||
|
|
b7cc59c503 | ||
|
|
7eb8d18a99 | ||
|
|
e7bf3e5e87 | ||
|
|
5aafd07b37 | ||
|
|
053f3a831d | ||
|
|
a2d2e5c047 | ||
|
|
dd3a922035 | ||
|
|
0e916c6038 | ||
|
|
87fcb63975 | ||
|
|
68b2cc5538 | ||
|
|
4dcf3697ff | ||
|
|
ea77525546 | ||
|
|
17d5a07ec2 |
@@ -4,10 +4,12 @@ config.cache
|
||||
config.h
|
||||
config.log
|
||||
config.status
|
||||
gmon.out
|
||||
rsync
|
||||
shconfig
|
||||
testdir
|
||||
tests-dont-exist
|
||||
testtmp
|
||||
testtmp.*
|
||||
tls
|
||||
zlib/dummy
|
||||
|
||||
12
INSTALL
12
INSTALL
@@ -28,3 +28,15 @@ fails:
|
||||
Install gcc or HP's "ANSI/C Compiler".
|
||||
|
||||
|
||||
|
||||
MAC OSX NOTES
|
||||
-------------
|
||||
|
||||
Mac OS X (Darwin) seems to have an IPv6 stack, but it does not
|
||||
completely implement the "New Sockets" API.
|
||||
|
||||
<http://www.ipv6.org/impl/mac.html> says that Apple do not support
|
||||
IPv6 yet. If your build fails, try again with --disable-ipv6.
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -62,8 +62,11 @@ install-strip:
|
||||
$(MAKE) INSTALLCMD='$(INSTALLCMD) -s' install
|
||||
|
||||
rsync: $(OBJS)
|
||||
@echo "Please ignore warnings below about mktemp -- it is used in a safe way"
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o rsync $(OBJS) $(LIBS)
|
||||
|
||||
$(OBJS): config.h
|
||||
|
||||
tls: $(tls_OBJ)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(tls_OBJ) $(LIBS)
|
||||
|
||||
|
||||
84
NEWS
84
NEWS
@@ -1,81 +1,7 @@
|
||||
rsync 2.4.7 (sometime in 2001, maybe :) -*- indented-text -*-
|
||||
rsync 2.4.8 (???)
|
||||
|
||||
ANNOUNCEMENTS
|
||||
|
||||
* Martin Pool <mbp@samba.org> is now a co-maintainer.
|
||||
|
||||
NEW FEATURES
|
||||
|
||||
* Support for LSB-compliant packaging <http://www.linuxbase.org/>
|
||||
|
||||
* Shell wildcards are allowed in "auth users" lines.
|
||||
|
||||
* Merged UNC rsync+ patch to support creation of standalone patch
|
||||
sets. By Bert J. Dempsey and Debra Weiss, updated by Jos
|
||||
Backus. <http://www.ils.unc.edu/i2dsi/unc_rsync+.html>
|
||||
|
||||
* IPv6 support based on a patch from KAME.net, on systems
|
||||
including modern versions of Linux, Solaris, and HP-UX. Also
|
||||
includes IPv6 compatibility functions for old OSs by the
|
||||
Internet Software Consortium, Paul Vixie, the OpenSSH
|
||||
portability project, and OpenBSD.
|
||||
|
||||
ENHANCEMENTS
|
||||
|
||||
* Include/exclude cluestick: with -vv, print out whether files are
|
||||
included or excluded and why.
|
||||
|
||||
* Many error messages have more friendly explanations and more
|
||||
details.
|
||||
|
||||
* Manual page improvements plus scanty protocol documentation.
|
||||
|
||||
* When running as --daemon in the background and using a "log
|
||||
file" rsyncd.conf directive, close the log file every time it is
|
||||
open when going to sleep on the socket. This allows the log
|
||||
file to get cleaned out by another process.
|
||||
|
||||
* Change to using libpopt rather than getopt for processing
|
||||
options. This makes the code cleaner and the behaviour more
|
||||
consistent across platforms. popt is included and built if not
|
||||
installed on the platform.
|
||||
|
||||
* More details in --version, including note about whether 64-bit
|
||||
files, symlinks and hardlinks are supported.
|
||||
|
||||
* MD4 code may use less CPU cycles.
|
||||
|
||||
* Use mkstemp on systems where it is secure. If we use mktemp,
|
||||
explain that we do it in a secure way.
|
||||
|
||||
* --whole-file is the default when source and target are on the
|
||||
local machine.
|
||||
|
||||
BUG FIXES:
|
||||
|
||||
* Fix for various bugs causing rsync to hang.
|
||||
|
||||
* Attempt to fix Large File Summit support on AIX.
|
||||
|
||||
* 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
|
||||
|
||||
* For log messages containing ridiculously long strings that might
|
||||
overflow a buffer rsync no longer aborts, but rather prints an
|
||||
ellipsis at the end of the string. (Patch from Ed Santiago.)
|
||||
|
||||
PLATFORMS:
|
||||
|
||||
* 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.
|
||||
|
||||
TESTING:
|
||||
|
||||
* The existing test.sh script by Phil Hands has been merged into a
|
||||
test framework that works from both "make check" and the Samba
|
||||
build farm.
|
||||
SECURITY FIXES:
|
||||
|
||||
* Signedness security patch from Sebastian Krahmer
|
||||
<krahmer@suse.de> -- in some cases we were not sufficiently
|
||||
careful about reading integers from the network.
|
||||
|
||||
148
OLDNEWS
Normal file
148
OLDNEWS
Normal file
@@ -0,0 +1,148 @@
|
||||
rsync 2.5.1 (2002-01-03)
|
||||
|
||||
BUG FIXES:
|
||||
|
||||
* Fix for segfault in --daemon mode configuration parser. (Paul
|
||||
Mackerras)
|
||||
|
||||
* Correct string<->address parsing for both IPv4 and 6.
|
||||
(YOSHIFUJI Hideaki, SUMIKAWA Munechika and Jun-ichiro "itojun"
|
||||
Hagino)
|
||||
|
||||
* Various fixes for IPv6 support. (Dave Dykstra)
|
||||
|
||||
* rsync.1 typo fix. (Matt Kraai)
|
||||
|
||||
* Test suite typo fixes. (Tom Schmidt)
|
||||
|
||||
* rsync.1 grammar and clarity improvements. (Edward
|
||||
Welbourne)
|
||||
|
||||
* Correction to ./configure tests for inet_ntop. (Jeff Garzik)
|
||||
|
||||
ENHANCEMENTS:
|
||||
|
||||
* --progress and -P now show estimated data transfer rate (in a
|
||||
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)
|
||||
|
||||
* Clearer error messages for some conditions.
|
||||
|
||||
rsync 2.5.0 (2001-11-30)
|
||||
|
||||
ANNOUNCEMENTS
|
||||
|
||||
* Martin Pool <mbp@samba.org> is now a co-maintainer.
|
||||
|
||||
NEW FEATURES
|
||||
|
||||
* Support for LSB-compliant packaging <http://www.linuxbase.org/>
|
||||
|
||||
* Shell wildcards are allowed in "auth users" lines.
|
||||
|
||||
* Merged UNC rsync+ patch to support creation of standalone patch
|
||||
sets. By Bert J. Dempsey and Debra Weiss, updated by Jos
|
||||
Backus. <http://www.ils.unc.edu/i2dsi/unc_rsync+.html>
|
||||
|
||||
* IPv6 support based on a patch from KAME.net, on systems
|
||||
including modern versions of Linux, Solaris, and HP-UX. Also
|
||||
includes IPv6 compatibility functions for old OSs by the
|
||||
Internet Software Consortium, Paul Vixie, the OpenSSH
|
||||
portability project, and OpenBSD.
|
||||
|
||||
ENHANCEMENTS
|
||||
|
||||
* Include/exclude cluestick: with -vv, print out whether files are
|
||||
included or excluded and why.
|
||||
|
||||
* Many error messages have more friendly explanations and more
|
||||
details.
|
||||
|
||||
* Manual page improvements plus scanty protocol documentation.
|
||||
|
||||
* When running as --daemon in the background and using a "log
|
||||
file" rsyncd.conf directive, close the log file every time it is
|
||||
open when going to sleep on the socket. This allows the log
|
||||
file to get cleaned out by another process.
|
||||
|
||||
* Change to using libpopt rather than getopt for processing
|
||||
options. This makes the code cleaner and the behaviour more
|
||||
consistent across platforms. popt is included and built if not
|
||||
installed on the platform.
|
||||
|
||||
* More details in --version, including note about whether 64-bit
|
||||
files, symlinks and hardlinks are supported.
|
||||
|
||||
* MD4 code may use less CPU cycles.
|
||||
|
||||
* Use mkstemp on systems where it is secure. If we use mktemp,
|
||||
explain that we do it in a secure way.
|
||||
|
||||
* --whole-file is the default when source and target are on the
|
||||
local machine.
|
||||
|
||||
BUG FIXES:
|
||||
|
||||
* Fix for various bugs causing rsync to hang.
|
||||
|
||||
* Attempt to fix Large File Summit support on AIX.
|
||||
|
||||
* 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
|
||||
|
||||
* For log messages containing ridiculously long strings that might
|
||||
overflow a buffer rsync no longer aborts, but rather prints an
|
||||
ellipsis at the end of the string. (Patch from Ed Santiago.)
|
||||
|
||||
PLATFORMS:
|
||||
|
||||
* 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.
|
||||
|
||||
* Platforms thought to work in this release:
|
||||
|
||||
Cray SV1 UNICOS 10.0.0.8 cc
|
||||
Debian Linux 2.2 UltraSparc gcc
|
||||
Debian Linux testing/unstable ARM gcc
|
||||
FreeBSD 3.3-RELEASE i386 cc
|
||||
FreeBSD 4.1.1-RELEASE i386 cc
|
||||
FreeBSD 4.3-STABLE i386 cc
|
||||
HP PA-RISC HP-UX 10.20 gcc
|
||||
HP PA-RISC HP-UX 11.11 cc
|
||||
IRIX 6.5 MIPS cc
|
||||
IRIX 6.5 MIPS gcc
|
||||
Mac OS X PPC (--disable-ipv6) cc
|
||||
NetBSD 1.5 i386 gcc
|
||||
NetBSD Current i386 cc
|
||||
OpenBSD 2.5 Sparc gcc
|
||||
OpenBSD 2.9 i386 cc
|
||||
OpenBSD Current i386 cc
|
||||
RedHat 6.2 i386 gcc
|
||||
RedHat 6.2 i386 insure++
|
||||
RedHat 7.0 i386 gcc
|
||||
RedHat 7.1 i386 (Kernel 2.4.10) gcc
|
||||
Slackware 8.0 i686 (Kernel 2.4.10)
|
||||
Solaris 8 UltraSparc cc
|
||||
Solaris 8 UltraSparc gcc
|
||||
Solaris 8 i386 gcc
|
||||
SuSE 7.1 i386 gcc2.95.2
|
||||
SuSE 7.1 ppc gcc2.95.2
|
||||
i386-pc-sco3.2v5.0.5 cc
|
||||
i386-pc-sco3.2v5.0.5 gcc
|
||||
powerpc-ibm-aix4.3.3.0 cc
|
||||
i686-unknown-sysv5UnixWare7.1.0 gcc
|
||||
i686-unknown-sysv5UnixWare7.1.0 cc
|
||||
|
||||
TESTING:
|
||||
|
||||
* The existing test.sh script by Phil Hands has been merged into a
|
||||
test framework that works from both "make check" and the Samba
|
||||
build farm.
|
||||
13
README
13
README
@@ -143,9 +143,7 @@ This will give you access to the bug tracking system used by the
|
||||
developers of rsync and will allow you to look at other bug reports or
|
||||
submit a new bug report.
|
||||
|
||||
If you don't have web access then mail bug reports to
|
||||
rsync-bugs@samba.org or (if you think it will be of interest to lots
|
||||
of people) send it to rsync@samba.org
|
||||
If you don't have web access then mail bug reports to rsync@samba.org.
|
||||
|
||||
|
||||
CVS TREE
|
||||
@@ -167,11 +165,12 @@ details.
|
||||
COPYRIGHT
|
||||
---------
|
||||
|
||||
Rsync was written by Andrew Tridgell and Paul Mackerras, and is
|
||||
available under the GNU General Public License.
|
||||
rsync was originally written by Andrew Tridgell and has been improved
|
||||
by many developers around the world. rsync may be used, modified and
|
||||
redistributed only under the terms of the GNU General Public License,
|
||||
found in the file COPYING in this distribution, or at
|
||||
|
||||
tridge@samba.org
|
||||
paulus@cs.anu.edu.au
|
||||
http://www.fsf.org/licenses/gpl.html
|
||||
|
||||
|
||||
AVAILABILITY
|
||||
|
||||
283
TODO
283
TODO
@@ -16,21 +16,287 @@ Cross-test versions
|
||||
some testing and also be the most common case for having different
|
||||
versions and not being able to upgrade.
|
||||
|
||||
use chroot
|
||||
|
||||
If the platform doesn't support it, then don't even try.
|
||||
|
||||
If running as non-root, then don't fail, just give a warning.
|
||||
(There was a thread about this a while ago?)
|
||||
|
||||
http://lists.samba.org/pipermail/rsync/2001-August/thread.html
|
||||
http://lists.samba.org/pipermail/rsync/2001-September/thread.html
|
||||
|
||||
--files-from
|
||||
|
||||
Avoids traversal. Better option than a pile of --include statements
|
||||
for people who want to generate the file list using a find(1)
|
||||
command or a script.
|
||||
|
||||
|
||||
Performance
|
||||
|
||||
Traverse just one directory at a time. Tridge says it's possible.
|
||||
|
||||
At the moment rsync reads the whole file list into memory at the
|
||||
start, which makes us use a lot of memory and also not pipeline
|
||||
network access as much as we could.
|
||||
|
||||
|
||||
Handling duplicate names
|
||||
|
||||
We need to be careful of duplicate names getting into the file list.
|
||||
See clean_flist(). This could happen if multiple arguments include
|
||||
the same file. Bad.
|
||||
|
||||
I think duplicates are only a problem if they're both flowing
|
||||
through the pipeline at the same time. For example we might have
|
||||
updated the first occurrence after reading the checksums for the
|
||||
second. So possibly we just need to make sure that we don't have
|
||||
both in the pipeline at the same time.
|
||||
|
||||
Possibly if we did one directory at a time that would be sufficient.
|
||||
|
||||
Alternatively we could pre-process the arguments to make sure no
|
||||
duplicates will ever be inserted. There could be some bad cases
|
||||
when we're collapsing symlinks.
|
||||
|
||||
We could have a hash table.
|
||||
|
||||
The root of the problem is that we do not want more than one file
|
||||
list entry referring to the same file. At first glance there are
|
||||
several ways this could happen: symlinks, hardlinks, and repeated
|
||||
names on the command line.
|
||||
|
||||
If names are repeated on the command line, they may be present in
|
||||
different forms, perhaps by traversing directory paths in different
|
||||
ways, traversing paths including symlinks. Also we need to allow
|
||||
for expansion of globs by rsync.
|
||||
|
||||
At the moment, clean_flist() requires having the entire file list in
|
||||
memory. Duplicate names are detected just by a string comparison.
|
||||
|
||||
We don't need to worry about hard links causing duplicates because
|
||||
files are never updated in place. Similarly for symlinks.
|
||||
|
||||
I think even if we're using a different symlink mode we don't need
|
||||
to worry.
|
||||
|
||||
Unless we're really clever this will introduce a protocol
|
||||
incompatibility, so we need to be able to accept the old format as
|
||||
well.
|
||||
|
||||
|
||||
Memory accounting
|
||||
|
||||
At exit, show how much memory was used for the file list, etc.
|
||||
|
||||
Also we do a wierd exponential-growth allocation in flist.c. I'm
|
||||
not sure this makes sense with modern mallocs. At any rate it will
|
||||
make us allocate a huge amount of memory for large file lists.
|
||||
|
||||
We can try using the GNU/SVID/XPG mallinfo() function to get some
|
||||
heap statistics.
|
||||
|
||||
|
||||
Hard-link handling
|
||||
|
||||
At the moment hardlink handling is very expensive, so it's off by
|
||||
default. It does not need to be so.
|
||||
|
||||
Since most of the solutions are rather intertwined with the file
|
||||
list it is probably better to fix that first, although fixing
|
||||
hardlinks is possibly simpler.
|
||||
|
||||
We can rule out hardlinked directories since they will probably
|
||||
screw us up in all kinds of ways. They simply should not be used.
|
||||
|
||||
At the moment rsync only cares about hardlinks to regular files. I
|
||||
guess you could also use them for sockets, devices and other beasts,
|
||||
but I have not seen them.
|
||||
|
||||
When trying to reproduce hard links, we only need to worry about
|
||||
files that have more than one name (nlinks>1 && !S_ISDIR).
|
||||
|
||||
The basic point of this is to discover alternate names that refer to
|
||||
the same file. All operations, including creating the file and
|
||||
writing modifications to it need only to be done for the first name.
|
||||
For all later names, we just create the link and then leave it
|
||||
alone.
|
||||
|
||||
If hard links are to be preserved:
|
||||
|
||||
Before the generator/receiver fork, the list of files is received
|
||||
from the sender (recv_file_list), and a table for detecting hard
|
||||
links is built.
|
||||
|
||||
The generator looks for hard links within the file list and does
|
||||
not send checksums for them, though it does send other metadata.
|
||||
|
||||
The sender sends the device number and inode with file entries, so
|
||||
that files are uniquely identified.
|
||||
|
||||
The receiver goes through and creates hard links (do_hard_links)
|
||||
after all data has been written, but before directory permissions
|
||||
are set.
|
||||
|
||||
At the moment device and inum are sent as 4-byte integers, which
|
||||
will probably cause problems on large filesystems. On Linux the
|
||||
kernel uses 64-bit ino_t's internally, and people will soon have
|
||||
filesystems big enough to use them. We ought to follow NFS4 in
|
||||
using 64-bit device and inode identification, perhaps with a
|
||||
protocol version bump.
|
||||
|
||||
Once we've seen all the names for a particular file, we no longer
|
||||
need to think about it and we can deallocate the memory.
|
||||
|
||||
We can also have the case where there are links to a file that are
|
||||
not in the tree being transferred. There's nothing we can do about
|
||||
that. Because we rename the destination into place after writing,
|
||||
any hardlinks to the old file are always going to be orphaned. In
|
||||
fact that is almost necessary because otherwise we'd get really
|
||||
confused if we were generating checksums for one name of a file and
|
||||
modifying another.
|
||||
|
||||
At the moment the code seems to make a whole second copy of the file
|
||||
list, which seems unnecessary.
|
||||
|
||||
We should have a test case that exercises hard links. Since it
|
||||
might be hard to compare ./tls output where the inodes change we
|
||||
might need a little program to check whether several names refer to
|
||||
the same file.
|
||||
|
||||
IPv6
|
||||
|
||||
Implement suggestions from http://www.kame.net/newsletter/19980604/
|
||||
and ftp://ftp.iij.ad.jp/pub/RFC/rfc2553.txt
|
||||
|
||||
If a host has multiple addresses, then listen try to connect to all
|
||||
in order until we get through. (getaddrinfo may return multiple
|
||||
addresses.) This is kind of implemented already.
|
||||
|
||||
Possibly also when starting as a server we may need to listen on
|
||||
multiple passive addresses. This might be a bit harder, because we
|
||||
may need to select on all of them. Hm.
|
||||
|
||||
Define a syntax for IPv6 literal addresses. Since they include
|
||||
colons, they tend to break most naming systems, including ours.
|
||||
Based on the HTTP IPv6 syntax, I think we should use
|
||||
|
||||
rsync://[::1]/foo/bar
|
||||
[::1]::bar
|
||||
|
||||
which should just take a small change to the parser code.
|
||||
|
||||
Errors
|
||||
|
||||
If we hang or get SIGINT, then explain where we were up to. Perhaps
|
||||
have a static buffer that contains the current function name, or
|
||||
some kind of description of what we were trying to do. This is a
|
||||
little easier on people than needing to run strace/truss.
|
||||
|
||||
"The dungeon collapses! You are killed." Rather than "unexpected
|
||||
eof" give a message that is more detailed if possible and also more
|
||||
helpful.
|
||||
|
||||
File attributes
|
||||
|
||||
Device major/minor numbers should be at least 32 bits each. See
|
||||
http://lists.samba.org/pipermail/rsync/2001-November/005357.html
|
||||
|
||||
Transfer ACLs. Need to think of a standard representation.
|
||||
Probably better not to even try to convert between NT and POSIX.
|
||||
Possibly can share some code with Samba.
|
||||
|
||||
Empty directories
|
||||
|
||||
With the current common --include '*/' --exclude '*' pattern, people
|
||||
can end up with many empty directories. We might avoid this by
|
||||
lazily creating such directories.
|
||||
|
||||
zlib
|
||||
|
||||
Perhaps don't use our own zlib. Will we actually be incompatible,
|
||||
or just be slightly less efficient?
|
||||
|
||||
logging
|
||||
|
||||
Perhaps flush stdout after each filename, so that people trying to
|
||||
monitor progress in a log file can do so more easily. See
|
||||
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=48108
|
||||
|
||||
At the connections that just get a list of modules are not logged,
|
||||
but they should be.
|
||||
|
||||
rsyncd over ssh
|
||||
|
||||
There are already some patches to do this.
|
||||
|
||||
proxy authentication
|
||||
|
||||
Allow RSYNC_PROXY to be http://user:pass@proxy.foo:3128/, and do
|
||||
HTTP Basic Proxy-Authentication.
|
||||
|
||||
Multiple schemes are possible, up to and including the insanity that
|
||||
is NTLM, but Basic probably covers most cases.
|
||||
|
||||
SOCKS
|
||||
|
||||
Add --with-socks, and then perhaps a command-line option to put them
|
||||
on or off. This might be more reliable than LD_PRELOAD hacks.
|
||||
|
||||
PLATFORMS ------------------------------------------------------------
|
||||
|
||||
Win32
|
||||
|
||||
Don't detach, because this messes up --srvany.
|
||||
|
||||
http://sources.redhat.com/ml/cygwin/2001-08/msg00234.html
|
||||
|
||||
According to "Effective TCP/IP Programming" (??) close() on a socket
|
||||
has incorrect behaviour on Windows -- it sends a RST packet to the
|
||||
other side, which gives a "connection reset by peer" error. On that
|
||||
platform we should probably do shutdown() instead. However, on Unix
|
||||
we are correct to call close(), because shutdown() discards
|
||||
untransmitted data.
|
||||
|
||||
DOCUMENTATION --------------------------------------------------------
|
||||
|
||||
Update README
|
||||
|
||||
BUILD FARM -----------------------------------------------------------
|
||||
|
||||
Add machines
|
||||
|
||||
AMDAHL UTS (Dave Dykstra)
|
||||
|
||||
Cygwin (on different versions of Win32?)
|
||||
|
||||
HP-UX variants (via HP?)
|
||||
|
||||
SCO
|
||||
|
||||
NICE -----------------------------------------------------------------
|
||||
|
||||
Merge IPv6 support ***
|
||||
--no-detach and --no-fork options
|
||||
|
||||
A patch is available at
|
||||
Very useful for debugging. Also good when running under a
|
||||
daemon-monitoring process that tries to restart the service when the
|
||||
parent exits.
|
||||
|
||||
ftp://ftp.kame.net/pub/kame/misc/rsync-244-v6-20000802.diff.gz
|
||||
hang/timeout friendliness
|
||||
|
||||
but tridge reckons it needs to be cleaned up before it can be
|
||||
accepted.
|
||||
verbose output
|
||||
|
||||
Indicate whether files are new, updated, or deleted
|
||||
|
||||
This is now on the track-kameipv6 branch and can be moved across any
|
||||
time. The KAME people say that it should work on machines without
|
||||
IPv6 stacks.
|
||||
internationalization
|
||||
|
||||
Change to using gettext(). Probably need to ship this for platforms
|
||||
that don't have it.
|
||||
|
||||
Solicit translations.
|
||||
|
||||
Does anyone care?
|
||||
|
||||
rsyncsh
|
||||
|
||||
@@ -40,3 +306,4 @@ rsyncsh
|
||||
current host, directory and so on. We can probably even do
|
||||
completion of remote filenames.
|
||||
|
||||
%K%
|
||||
|
||||
@@ -105,8 +105,8 @@ static int get_secret(int module, char *user, char *secret, int len)
|
||||
|
||||
while (!found) {
|
||||
int i = 0;
|
||||
memset(line, 0, sizeof(line));
|
||||
while (i<(sizeof(line)-1)) {
|
||||
memset(line, 0, sizeof line);
|
||||
while ((size_t) i < (sizeof(line)-1)) {
|
||||
if (read(fd, &line[i], 1) != 1) {
|
||||
memset(line, 0, sizeof(line));
|
||||
close(fd);
|
||||
|
||||
@@ -45,6 +45,7 @@ int start_socket_client(char *host, char *path, int argc, char *argv[])
|
||||
extern char *shell_cmd;
|
||||
extern int kludge_around_eof;
|
||||
extern char *bind_address;
|
||||
extern int default_af_hint;
|
||||
|
||||
if (argc == 0 && !am_sender) {
|
||||
extern int list_only;
|
||||
@@ -79,7 +80,7 @@ int start_socket_client(char *host, char *path, int argc, char *argv[])
|
||||
if (!user) user = getenv("LOGNAME");
|
||||
|
||||
fd = open_socket_out_wrapped (host, rsync_port, bind_address,
|
||||
global_opts.af_hint);
|
||||
default_af_hint);
|
||||
if (fd == -1) {
|
||||
exit_cleanup(RERR_SOCKETIO);
|
||||
}
|
||||
@@ -167,9 +168,9 @@ static int rsync_module(int fd, int i)
|
||||
|
||||
if (!allow_access(addr, host, lp_hosts_allow(i), lp_hosts_deny(i))) {
|
||||
rprintf(FERROR,"rsync denied on module %s from %s (%s)\n",
|
||||
name, client_name(fd), client_addr(fd));
|
||||
name, host, addr);
|
||||
io_printf(fd,"@ERROR: access denied to %s from %s (%s)\n",
|
||||
name, client_name(fd), client_addr(fd));
|
||||
name, host, addr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -486,6 +487,7 @@ 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;
|
||||
@@ -501,7 +503,8 @@ int daemon_main(void)
|
||||
return start_daemon(STDIN_FILENO);
|
||||
}
|
||||
|
||||
become_daemon();
|
||||
if (!no_detach)
|
||||
become_daemon();
|
||||
|
||||
if (!lp_load(config_file, 1)) {
|
||||
exit_cleanup(RERR_SYNTAX);
|
||||
@@ -513,7 +516,8 @@ int daemon_main(void)
|
||||
RSYNC_VERSION,
|
||||
rsync_port);
|
||||
/* TODO: If listening on a particular address, then show that
|
||||
* address too. */
|
||||
* address too. In fact, why not just do inet_ntop on the
|
||||
* local address??? */
|
||||
|
||||
if (((pid_file = lp_pid_file()) != NULL) && (*pid_file != '\0')) {
|
||||
char pidbuf[16];
|
||||
|
||||
86
configure.in
86
configure.in
@@ -5,6 +5,12 @@ AC_CONFIG_SRCDIR([byteorder.h])
|
||||
AC_CONFIG_HEADER(config.h)
|
||||
AC_PREREQ(2.52)
|
||||
|
||||
RSYNC_VERSION=2.5.2pre3
|
||||
AC_SUBST(RSYNC_VERSION)
|
||||
AC_MSG_NOTICE([Configuring rsync $RSYNC_VERSION])
|
||||
|
||||
AC_DEFINE_UNQUOTED(RSYNC_VERSION, ["$RSYNC_VERSION"], [rsync release version])
|
||||
|
||||
LDFLAGS=${LDFLAGS-""}
|
||||
|
||||
AC_CANONICAL_TARGET([])
|
||||
@@ -13,14 +19,21 @@ dnl Checks for programs.
|
||||
AC_PROG_CC
|
||||
AC_PROG_CPP
|
||||
AC_PROG_INSTALL
|
||||
AC_PROG_CC_STDC
|
||||
AC_SUBST(SHELL)
|
||||
|
||||
RSYNC_VERSION=2.4.7pre4
|
||||
AC_SUBST(RSYNC_VERSION)
|
||||
AC_DEFINE_UNQUOTED(RSYNC_VERSION, ["$RSYNC_VERSION"], [rsync release version])
|
||||
AC_DEFINE([_GNU_SOURCE], 1,
|
||||
[Define _GNU_SOURCE so that we get all necessary prototypes])
|
||||
|
||||
# compile with optimisation and without debugging by default, unless
|
||||
# --debug is given. We must decide this before testing the compiler.
|
||||
if test "$xac_cv_prog_cc_stdc" = xno
|
||||
then
|
||||
AC_MSG_WARN([rsync requires an ANSI C compiler and you don't seem to have one])
|
||||
fi
|
||||
|
||||
# We must decide this before testing the compiler.
|
||||
|
||||
# Please allow this to default to yes, so that your users have more
|
||||
# chance of getting a useful stack trace if problems occur.
|
||||
|
||||
AC_MSG_CHECKING([whether to include debugging symbols])
|
||||
AC_ARG_ENABLE(debug,
|
||||
@@ -35,12 +48,33 @@ then
|
||||
else
|
||||
AC_MSG_RESULT([yes])
|
||||
# leave CFLAGS alone; AC_PROG_CC will try to include -g if it can
|
||||
AC_DEFINE(DEBUG, 1, [Define to turn on debugging code that may slow normal operation])
|
||||
dnl AC_DEFINE(DEBUG, 1, [Define to turn on debugging code that may slow normal operation])
|
||||
dnl CFLAGS=${CFLAGS-"-g"}
|
||||
fi
|
||||
|
||||
|
||||
|
||||
|
||||
AC_ARG_ENABLE(profile,
|
||||
AC_HELP_STRING([--enable-profile],
|
||||
[turn on CPU profiling (default no)],
|
||||
[], []))
|
||||
if test x"$enable_profile" = xyes
|
||||
then
|
||||
CFLAGS="$CFLAGS -pg"
|
||||
fi
|
||||
|
||||
|
||||
# This is needed for our included version of popt. Kind of silly, but
|
||||
# I don't want our version too far out of sync.
|
||||
CFLAGS="$CFLAGS -DHAVE_CONFIG_H"
|
||||
|
||||
# If GCC, turn on warnings.
|
||||
if test "x$GCC" = "xyes"
|
||||
then
|
||||
CFLAGS="$CFLAGS -Wall -W"
|
||||
fi
|
||||
|
||||
AC_ARG_WITH(included-popt,
|
||||
[ --with-included-popt use bundled popt library, not from system])
|
||||
|
||||
@@ -94,6 +128,11 @@ ipv6type=unknown
|
||||
ipv6lib=none
|
||||
ipv6trylibc=yes
|
||||
|
||||
AC_ARG_ENABLE(ipv6,
|
||||
AC_HELP_STRING([--disable-ipv6], [don't even try to use IPv6]))
|
||||
|
||||
if test "x$enable_ipv6" != xno
|
||||
then
|
||||
AC_MSG_CHECKING([ipv6 stack type])
|
||||
for i in inria kame linux-glibc linux-inet6 toshiba v6d zeta; do
|
||||
case $i in
|
||||
@@ -179,7 +218,8 @@ yes
|
||||
done
|
||||
AC_MSG_RESULT($ipv6type)
|
||||
|
||||
AC_SEARCH_LIBS(getaddrinfo, inet6)
|
||||
AC_SEARCH_LIBS(getaddrinfo, inet6)
|
||||
fi
|
||||
|
||||
AC_C_BIGENDIAN
|
||||
AC_HEADER_DIRENT
|
||||
@@ -190,6 +230,7 @@ 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)
|
||||
AC_CHECK_HEADERS(glob.h alloca.h mcheck.h sys/sysctl.h arpa/inet.h arpa/nameser.h)
|
||||
AC_CHECK_HEADERS(netdb.h)
|
||||
AC_CHECK_HEADERS(malloc.h)
|
||||
|
||||
AC_CHECK_SIZEOF(int)
|
||||
AC_CHECK_SIZEOF(long)
|
||||
@@ -254,13 +295,13 @@ fi
|
||||
|
||||
AC_CHECK_LIB(resolv, inet_ntop)
|
||||
|
||||
AC_MSG_NOTICE([Looking in libraries: $LIBS])
|
||||
dnl AC_MSG_NOTICE([Looking in libraries: $LIBS])
|
||||
|
||||
AC_CHECK_FUNC(inet_ntop, , AC_LIBOBJ(lib/inet_ntop))
|
||||
AC_CHECK_FUNC(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))
|
||||
|
||||
AC_CHECK_FUNC(getaddrinfo, , AC_LIBOBJ(lib/getaddrinfo))
|
||||
AC_CHECK_FUNC(getnameinfo, , AC_LIBOBJ(lib/getnameinfo))
|
||||
AC_CHECK_FUNCS(getaddrinfo, , AC_LIBOBJ(lib/getaddrinfo))
|
||||
AC_CHECK_FUNCS(getnameinfo, , AC_LIBOBJ(lib/getnameinfo))
|
||||
|
||||
AC_CHECK_MEMBER([struct sockaddr.sa_len],
|
||||
[ AC_DEFINE(HAVE_SOCKADDR_LEN) ],
|
||||
@@ -270,6 +311,15 @@ AC_CHECK_MEMBER([struct sockaddr.sa_len],
|
||||
#include <sys/socket.h>
|
||||
])
|
||||
|
||||
AC_MSG_CHECKING(struct sockaddr_storage)
|
||||
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,
|
||||
[Define if you have strct sockaddr_storage.] ),
|
||||
AC_MSG_RESULT(no))
|
||||
|
||||
# if we can't find strcasecmp, look in -lresolv (for Unixware at least)
|
||||
#
|
||||
AC_CHECK_FUNCS(strcasecmp)
|
||||
@@ -277,12 +327,16 @@ if test x"$ac_cv_func_strcasecmp" = x"no"; then
|
||||
AC_CHECK_LIB(resolv, strcasecmp)
|
||||
fi
|
||||
|
||||
AC_FUNC_MEMCMP
|
||||
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 AC_FUNC_MEMCMP
|
||||
|
||||
AC_FUNC_UTIME_NULL
|
||||
AC_CHECK_FUNCS(waitpid wait4 getcwd strdup strerror chown chmod mknod)
|
||||
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 mtrace)
|
||||
AC_CHECK_FUNCS(strlcat strlcpy mtrace mallinfo)
|
||||
|
||||
AC_CACHE_CHECK([for working socketpair],rsync_cv_HAVE_SOCKETPAIR,[
|
||||
AC_TRY_RUN([
|
||||
@@ -498,3 +552,7 @@ AC_SUBST(BUILD_POPT)
|
||||
|
||||
AC_CONFIG_FILES([Makefile lib/dummy zlib/dummy popt/dummy shconfig])
|
||||
AC_OUTPUT
|
||||
|
||||
AC_MSG_RESULT()
|
||||
AC_MSG_RESULT([ rsync ${RSYNC_VERSION} configuration successful])
|
||||
AC_MSG_RESULT()
|
||||
|
||||
77
exclude.c
77
exclude.c
@@ -1,7 +1,6 @@
|
||||
/* -*- c-file-style: "linux" -*-
|
||||
|
||||
Copyright (C) 1996-2001 by Andrew Tridgell <tridge@samba.org>
|
||||
Copyright (C) 1996 by Paul Mackerras
|
||||
/*
|
||||
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
|
||||
@@ -21,8 +20,6 @@
|
||||
/* a lot of this stuff was originally derived from GNU tar, although
|
||||
it has now changed so much that it is hard to tell :) */
|
||||
|
||||
/* include/exclude cluestick added by Martin Pool <mbp@samba.org> */
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
extern int verbose;
|
||||
@@ -31,7 +28,7 @@ extern int delete_mode;
|
||||
static struct exclude_struct **exclude_list;
|
||||
|
||||
/* build an exclude structure given a exclude pattern */
|
||||
static struct exclude_struct *make_exclude(const char *pattern, int include)
|
||||
static struct exclude_struct *make_exclude(char *pattern, int include)
|
||||
{
|
||||
struct exclude_struct *ret;
|
||||
|
||||
@@ -87,8 +84,8 @@ static void free_exclude(struct exclude_struct *ex)
|
||||
free(ex);
|
||||
}
|
||||
|
||||
static int check_one_exclude(char *name, struct exclude_struct *ex,
|
||||
STRUCT_STAT *st)
|
||||
static int check_one_exclude(char *name,struct exclude_struct *ex,
|
||||
STRUCT_STAT *st)
|
||||
{
|
||||
char *p;
|
||||
int match_start=0;
|
||||
@@ -124,62 +121,32 @@ static int check_one_exclude(char *name, struct exclude_struct *ex,
|
||||
}
|
||||
|
||||
|
||||
static void report_exclude_result(char const *name,
|
||||
struct exclude_struct const *ent,
|
||||
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 %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 true if file NAME is defined to be excluded by either
|
||||
* LOCAL_EXCLUDE_LIST or the globals EXCLUDE_LIST.
|
||||
*/
|
||||
int check_exclude(char *name, struct exclude_struct **local_exclude_list,
|
||||
int check_exclude(char *name,struct exclude_struct **local_exclude_list,
|
||||
STRUCT_STAT *st)
|
||||
{
|
||||
int n;
|
||||
struct exclude_struct *ent;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
for (n=0; exclude_list[n]; n++)
|
||||
if (check_one_exclude(name,exclude_list[n],st))
|
||||
return !exclude_list[n]->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;
|
||||
}
|
||||
}
|
||||
for (n=0; local_exclude_list[n]; n++)
|
||||
if (check_one_exclude(name,local_exclude_list[n],st))
|
||||
return !local_exclude_list[n]->include;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void add_exclude_list(const char *pattern, struct exclude_struct ***list, int include)
|
||||
void add_exclude_list(char *pattern,struct exclude_struct ***list, int include)
|
||||
{
|
||||
int len=0;
|
||||
if (list && *list)
|
||||
@@ -207,12 +174,12 @@ void add_exclude_list(const char *pattern, struct exclude_struct ***list, int in
|
||||
(*list)[len+1] = NULL;
|
||||
}
|
||||
|
||||
void add_exclude(const char *pattern, int include)
|
||||
void add_exclude(char *pattern, int include)
|
||||
{
|
||||
add_exclude_list(pattern,&exclude_list, include);
|
||||
}
|
||||
|
||||
struct exclude_struct **make_exclude_list(const char *fname,
|
||||
struct exclude_struct **make_exclude_list(char *fname,
|
||||
struct exclude_struct **list1,
|
||||
int fatal, int include)
|
||||
{
|
||||
@@ -221,10 +188,7 @@ struct exclude_struct **make_exclude_list(const char *fname,
|
||||
char line[MAXPATHLEN];
|
||||
if (!f) {
|
||||
if (fatal) {
|
||||
rsyserr(FERROR, errno,
|
||||
"failed to open %s file %s",
|
||||
include ? "include" : "exclude",
|
||||
fname);
|
||||
rprintf(FERROR,"%s : %s\n",fname,strerror(errno));
|
||||
exit_cleanup(RERR_FILEIO);
|
||||
}
|
||||
return list;
|
||||
@@ -246,7 +210,7 @@ struct exclude_struct **make_exclude_list(const char *fname,
|
||||
}
|
||||
|
||||
|
||||
void add_exclude_file(const char *fname, int fatal, int include)
|
||||
void add_exclude_file(char *fname,int fatal,int include)
|
||||
{
|
||||
if (!fname || !*fname) return;
|
||||
|
||||
@@ -299,7 +263,8 @@ void send_exclude_list(int f)
|
||||
void recv_exclude_list(int f)
|
||||
{
|
||||
char line[MAXPATHLEN];
|
||||
int l;
|
||||
unsigned int l;
|
||||
|
||||
while ((l=read_int(f))) {
|
||||
if (l >= MAXPATHLEN) overflow("recv_exclude_list");
|
||||
read_sbuf(f,line,l);
|
||||
@@ -398,7 +363,7 @@ void add_cvs_excludes(void)
|
||||
add_exclude(cvs_ignore_list[i], 0);
|
||||
|
||||
if ((p=getenv("HOME")) && strlen(p) < (MAXPATHLEN-12)) {
|
||||
snprintf(fname,sizeof(fname), "%s/.cvsignore",p);
|
||||
slprintf(fname,sizeof(fname), "%s/.cvsignore",p);
|
||||
add_exclude_file(fname,0,0);
|
||||
}
|
||||
|
||||
|
||||
4
fileio.c
4
fileio.c
@@ -36,7 +36,7 @@ int sparse_end(int f)
|
||||
}
|
||||
|
||||
|
||||
static int write_sparse(int f,char *buf,int len)
|
||||
static int write_sparse(int f,char *buf,size_t len)
|
||||
{
|
||||
int l1=0,l2=0;
|
||||
int ret;
|
||||
@@ -69,7 +69,7 @@ static int write_sparse(int f,char *buf,int len)
|
||||
|
||||
|
||||
|
||||
int write_file(int f,char *buf,int len)
|
||||
int write_file(int f,char *buf,size_t len)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
|
||||
80
flist.c
80
flist.c
@@ -1,7 +1,6 @@
|
||||
/*
|
||||
Copyright (C) Andrew Tridgell 1996
|
||||
Copyright (C) Paul Mackerras 1996
|
||||
Copyright (C) 2001 by Martin Pool <mbp@samba.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -48,9 +47,6 @@ extern int remote_version;
|
||||
extern int io_error;
|
||||
extern int sanitize_paths;
|
||||
|
||||
extern int read_batch;
|
||||
extern int write_batch;
|
||||
|
||||
static char topsrcname[MAXPATHLEN];
|
||||
|
||||
static struct exclude_struct **local_exclude_list;
|
||||
@@ -112,14 +108,24 @@ static char *string_area_strdup(struct string_area **ap, const char *src)
|
||||
|
||||
static void list_file_entry(struct file_struct *f)
|
||||
{
|
||||
char perms[11];
|
||||
char perms[11] = "----------";
|
||||
char *perm_map = "rwxrwxrwx";
|
||||
int i;
|
||||
|
||||
if (!f->basename)
|
||||
/* this can happen if duplicate names were removed */
|
||||
return;
|
||||
|
||||
permstring(perms, f->mode);
|
||||
|
||||
for (i=0;i<9;i++) {
|
||||
if (f->mode & (1<<i)) perms[9-i] = perm_map[8-i];
|
||||
}
|
||||
if (S_ISLNK(f->mode)) perms[0] = 'l';
|
||||
if (S_ISDIR(f->mode)) perms[0] = 'd';
|
||||
if (S_ISBLK(f->mode)) perms[0] = 'b';
|
||||
if (S_ISCHR(f->mode)) perms[0] = 'c';
|
||||
if (S_ISSOCK(f->mode)) perms[0] = 's';
|
||||
if (S_ISFIFO(f->mode)) perms[0] = 'p';
|
||||
|
||||
if (preserve_links && S_ISLNK(f->mode)) {
|
||||
rprintf(FINFO,"%s %11.0f %s %s -> %s\n",
|
||||
perms,
|
||||
@@ -144,7 +150,7 @@ int readlink_stat(const char *Path, STRUCT_STAT *Buffer, char *Linkbuf)
|
||||
}
|
||||
if (S_ISLNK(Buffer->st_mode)) {
|
||||
int l;
|
||||
if ((l = readlink((char *) Path, Linkbuf, MAXPATHLEN-1))== -1) {
|
||||
if ((l = readlink(Path,Linkbuf,MAXPATHLEN-1)) == -1) {
|
||||
return -1;
|
||||
}
|
||||
Linkbuf[l] = 0;
|
||||
@@ -176,18 +182,14 @@ int link_stat(const char *Path, STRUCT_STAT *Buffer)
|
||||
This function is used to check if a file should be included/excluded
|
||||
from the list of files based on its name and type etc
|
||||
*/
|
||||
static int check_exclude_file(int f,char *fname,STRUCT_STAT *st)
|
||||
static int match_file_name(char *fname,STRUCT_STAT *st)
|
||||
{
|
||||
extern int delete_excluded;
|
||||
|
||||
/* f is set to -1 when calculating deletion file list */
|
||||
if ((f == -1) && delete_excluded) {
|
||||
return 0;
|
||||
}
|
||||
if (check_exclude(fname,local_exclude_list,st)) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
if (check_exclude(fname,local_exclude_list,st)) {
|
||||
if (verbose > 2)
|
||||
rprintf(FINFO,"excluding file %s\n",fname);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* used by the one_file_system code */
|
||||
@@ -203,7 +205,7 @@ static void set_filesystem(char *fname)
|
||||
|
||||
static int to_wire_mode(mode_t mode)
|
||||
{
|
||||
if (S_ISLNK(mode) && (_S_IFLNK != 0120000)) {
|
||||
if (S_ISLNK(mode) && (S_IFLNK != 0120000)) {
|
||||
return (mode & ~(_S_IFMT)) | 0120000;
|
||||
}
|
||||
return (int)mode;
|
||||
@@ -211,8 +213,8 @@ static int to_wire_mode(mode_t mode)
|
||||
|
||||
static mode_t from_wire_mode(int mode)
|
||||
{
|
||||
if ((mode & (_S_IFMT)) == 0120000 && (_S_IFLNK != 0120000)) {
|
||||
return (mode & ~(_S_IFMT)) | _S_IFLNK;
|
||||
if ((mode & (_S_IFMT)) == 0120000 && (S_IFLNK != 0120000)) {
|
||||
return (mode & ~(_S_IFMT)) | S_IFLNK;
|
||||
}
|
||||
return (mode_t)mode;
|
||||
}
|
||||
@@ -332,7 +334,7 @@ static void receive_file_entry(struct file_struct **fptr,
|
||||
static gid_t last_gid;
|
||||
static char lastname[MAXPATHLEN];
|
||||
char thisname[MAXPATHLEN];
|
||||
int l1=0,l2=0;
|
||||
unsigned int l1=0,l2=0;
|
||||
char *p;
|
||||
struct file_struct *file;
|
||||
|
||||
@@ -399,6 +401,10 @@ static void receive_file_entry(struct file_struct **fptr,
|
||||
|
||||
if (preserve_links && S_ISLNK(file->mode)) {
|
||||
int l = read_int(f);
|
||||
if (l < 0) {
|
||||
rprintf(FERROR,"overflow: l=%d\n", l);
|
||||
overflow("receive_file_entry");
|
||||
}
|
||||
file->link = (char *)malloc(l+1);
|
||||
if (!file->link) out_of_memory("receive_file_entry 2");
|
||||
read_sbuf(f,file->link,l);
|
||||
@@ -476,6 +482,7 @@ struct file_struct *make_file(int f, char *fname, struct string_area **ap,
|
||||
char *p;
|
||||
char cleaned_name[MAXPATHLEN];
|
||||
char linkbuf[MAXPATHLEN];
|
||||
extern int delete_excluded;
|
||||
extern int module_id;
|
||||
|
||||
strlcpy(cleaned_name, fname, MAXPATHLEN);
|
||||
@@ -489,18 +496,9 @@ struct file_struct *make_file(int f, char *fname, struct string_area **ap,
|
||||
memset(sum,0,SUM_LENGTH);
|
||||
|
||||
if (readlink_stat(fname,&st,linkbuf) != 0) {
|
||||
int save_errno = errno;
|
||||
if ((errno == ENOENT) && copy_links && !noexcludes) {
|
||||
/* symlink pointing nowhere, see if excluded */
|
||||
memset((char *)&st, 0, sizeof(st));
|
||||
if (check_exclude_file(f,fname,&st)) {
|
||||
/* file is excluded anyway, ignore silently */
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
io_error = 1;
|
||||
rprintf(FERROR,"readlink %s: %s\n",
|
||||
fname,strerror(save_errno));
|
||||
fname,strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -517,7 +515,8 @@ struct file_struct *make_file(int f, char *fname, struct string_area **ap,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (check_exclude_file(f,fname,&st))
|
||||
/* f is set to -1 when calculating deletion file list */
|
||||
if (((f != -1) || !delete_excluded) && !match_file_name(fname,&st))
|
||||
return NULL;
|
||||
|
||||
|
||||
@@ -620,9 +619,6 @@ void send_file_name(int f,struct file_list *flist,char *fname,
|
||||
out_of_memory("send_file_name");
|
||||
}
|
||||
|
||||
if (write_batch) /* dw */
|
||||
file->flags = FLAG_DELETE;
|
||||
|
||||
if (strcmp(file->basename,"")) {
|
||||
flist->files[flist->count++] = file;
|
||||
send_file_entry(file,f,base_flags);
|
||||
@@ -708,8 +704,6 @@ struct file_list *send_file_list(int f,int argc,char *argv[])
|
||||
|
||||
if (verbose && recurse && !am_server && f != -1) {
|
||||
rprintf(FINFO,"building file list ... ");
|
||||
if (verbose > 1)
|
||||
rprintf(FINFO, "\n");
|
||||
rflush(FINFO);
|
||||
}
|
||||
|
||||
@@ -851,8 +845,6 @@ struct file_list *send_file_list(int f,int argc,char *argv[])
|
||||
io_end_buffering(f);
|
||||
stats.flist_size = stats.total_written - start_write;
|
||||
stats.num_files = flist->count;
|
||||
if (write_batch) /* dw */
|
||||
write_batch_flist_info(flist->count, flist->files);
|
||||
}
|
||||
|
||||
if (verbose > 2)
|
||||
@@ -930,7 +922,7 @@ struct file_list *recv_file_list(int f)
|
||||
}
|
||||
|
||||
/* if protocol version is >= 17 then recv the io_error flag */
|
||||
if (f != -1 && remote_version >= 17 && !read_batch) { /* dw-added readbatch */
|
||||
if (f != -1 && remote_version >= 17) {
|
||||
extern int module_id;
|
||||
extern int ignore_errors;
|
||||
if (lp_ignore_errors(module_id) || ignore_errors) {
|
||||
@@ -1108,10 +1100,10 @@ static void clean_flist(struct file_list *flist, int strip_root)
|
||||
|
||||
for (i=0;i<flist->count;i++) {
|
||||
rprintf(FINFO,"[%d] i=%d %s %s mode=0%o len=%.0f\n",
|
||||
(int) getpid(), i,
|
||||
getpid(), i,
|
||||
NS(flist->files[i]->dirname),
|
||||
NS(flist->files[i]->basename),
|
||||
(int) flist->files[i]->mode,
|
||||
flist->files[i]->mode,
|
||||
(double)flist->files[i]->length);
|
||||
}
|
||||
}
|
||||
|
||||
74
generator.c
74
generator.c
@@ -1,7 +1,10 @@
|
||||
/* -*- c-file-style: "linux" -*-
|
||||
|
||||
rsync -- fast file replication program
|
||||
|
||||
Copyright (C) 1996-2000 by Andrew Tridgell
|
||||
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
|
||||
@@ -99,25 +102,30 @@ static int adapt_block_size(struct file_struct *file, int bsize)
|
||||
/*
|
||||
send a sums struct down a fd
|
||||
*/
|
||||
static void send_sums(struct sum_struct *s,int f_out)
|
||||
static void send_sums(struct sum_struct *s, int f_out)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* tell the other guy how many we are going to be doing and how many
|
||||
bytes there are in the last chunk */
|
||||
write_int(f_out,s?s->count:0);
|
||||
write_int(f_out,s?s->n:block_size);
|
||||
write_int(f_out,s?s->remainder:0);
|
||||
if (s) {
|
||||
size_t i;
|
||||
|
||||
if (!s) return;
|
||||
/* tell the other guy how many we are going to be
|
||||
doing and how many bytes there are in the last
|
||||
chunk */
|
||||
write_int(f_out, s->count);
|
||||
write_int(f_out, s->n);
|
||||
write_int(f_out, s->remainder);
|
||||
|
||||
for (i=0;i<s->count;i++) {
|
||||
write_int(f_out,s->sums[i].sum1);
|
||||
write_buf(f_out,s->sums[i].sum2,csum_length);
|
||||
for (i = 0; i < s->count; i++) {
|
||||
write_int(f_out, s->sums[i].sum1);
|
||||
write_buf(f_out, s->sums[i].sum2, csum_length);
|
||||
}
|
||||
} else {
|
||||
/* we don't have checksums */
|
||||
write_int(f_out, 0);
|
||||
write_int(f_out, block_size);
|
||||
write_int(f_out, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
generate a stream of signatures/checksums that describe a buffer
|
||||
|
||||
@@ -210,7 +218,8 @@ void recv_generator(char *fname,struct file_list *flist,int i,int f_out)
|
||||
|
||||
if (only_existing && statret == -1 && errno == ENOENT) {
|
||||
/* we only want to update existing files */
|
||||
if (verbose > 1) rprintf(FINFO,"not creating %s\n",fname);
|
||||
if (verbose > 1) rprintf(FINFO, RSYNC_NAME
|
||||
": not creating new file \"%s\"\n",fname);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -230,10 +239,11 @@ void recv_generator(char *fname,struct file_list *flist,int i,int f_out)
|
||||
* we need to delete it. If it doesn't exist, then
|
||||
* recursively create it. */
|
||||
|
||||
if (dry_run) return;
|
||||
if (dry_run) return; /* XXXX -- might cause inaccuracies?? -- mbp */
|
||||
if (statret == 0 && !S_ISDIR(st.st_mode)) {
|
||||
if (robust_unlink(fname) != 0) {
|
||||
rprintf(FERROR,"recv_generator: unlink %s: %s\n",
|
||||
rprintf(FERROR, RSYNC_NAME
|
||||
": recv_generator: unlink \"%s\" to make room for directory: %s\n",
|
||||
fname,strerror(errno));
|
||||
return;
|
||||
}
|
||||
@@ -243,11 +253,13 @@ void recv_generator(char *fname,struct file_list *flist,int i,int f_out)
|
||||
if (!(relative_paths && errno==ENOENT &&
|
||||
create_directory_path(fname)==0 &&
|
||||
do_mkdir(fname,file->mode)==0)) {
|
||||
rprintf(FERROR,"recv_generator: mkdir %s: %s (2)\n",
|
||||
rprintf(FERROR, RSYNC_NAME ": recv_generator: mkdir \"%s\": %s (2)\n",
|
||||
fname,strerror(errno));
|
||||
}
|
||||
}
|
||||
if (set_perms(fname,file,NULL,0) && verbose)
|
||||
/* f_out is set to -1 when doing final directory
|
||||
permission and modification time repair */
|
||||
if (set_perms(fname,file,NULL,0) && verbose && (f_out != -1))
|
||||
rprintf(FINFO,"%s/\n",fname);
|
||||
return;
|
||||
}
|
||||
@@ -260,7 +272,7 @@ void recv_generator(char *fname,struct file_list *flist,int i,int f_out)
|
||||
|
||||
if (safe_symlinks && unsafe_symlink(file->link, fname)) {
|
||||
if (verbose) {
|
||||
rprintf(FINFO,"ignoring unsafe symlink %s -> %s\n",
|
||||
rprintf(FINFO,RSYNC_NAME ": ignoring unsafe symlink \"%s\" -> \"%s\"\n",
|
||||
fname,file->link);
|
||||
}
|
||||
return;
|
||||
@@ -269,20 +281,26 @@ void recv_generator(char *fname,struct file_list *flist,int i,int f_out)
|
||||
l = readlink(fname,lnk,MAXPATHLEN-1);
|
||||
if (l > 0) {
|
||||
lnk[l] = 0;
|
||||
/* A link already pointing to the
|
||||
* right place -- no further action
|
||||
* required. */
|
||||
if (strcmp(lnk,file->link) == 0) {
|
||||
set_perms(fname,file,&st,1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Not a symlink, so delete whatever's
|
||||
* already there and put a new symlink
|
||||
* in place. */
|
||||
delete_file(fname);
|
||||
}
|
||||
if (do_symlink(file->link,fname) != 0) {
|
||||
rprintf(FERROR,"symlink %s -> %s : %s\n",
|
||||
rprintf(FERROR,RSYNC_NAME": symlink \"%s\" -> \"%s\": %s\n",
|
||||
fname,file->link,strerror(errno));
|
||||
} else {
|
||||
set_perms(fname,file,NULL,0);
|
||||
if (verbose) {
|
||||
rprintf(FINFO,"%s -> %s\n",
|
||||
rprintf(FINFO,RSYNC_NAME": %s -> %s\n",
|
||||
fname,file->link);
|
||||
}
|
||||
}
|
||||
@@ -315,12 +333,14 @@ void recv_generator(char *fname,struct file_list *flist,int i,int f_out)
|
||||
|
||||
if (preserve_hard_links && check_hard_link(file)) {
|
||||
if (verbose > 1)
|
||||
rprintf(FINFO,"%s is a hard link\n",f_name(file));
|
||||
rprintf(FINFO, RSYNC_NAME
|
||||
": \"%s\" is a hard link\n",f_name(file));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!S_ISREG(file->mode)) {
|
||||
rprintf(FINFO,"skipping non-regular file %s\n",fname);
|
||||
rprintf(FINFO, RSYNC_NAME
|
||||
": skipping non-regular file \"%s\"\n",fname);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -345,7 +365,9 @@ void recv_generator(char *fname,struct file_list *flist,int i,int f_out)
|
||||
if (!dry_run) send_sums(NULL,f_out);
|
||||
} else {
|
||||
if (verbose > 1)
|
||||
rprintf(FERROR,"recv_generator failed to open %s\n",fname);
|
||||
rprintf(FERROR, RSYNC_NAME
|
||||
": recv_generator failed to open \"%s\": %s\n",
|
||||
fname, strerror(errno));
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -388,7 +410,7 @@ void recv_generator(char *fname,struct file_list *flist,int i,int f_out)
|
||||
fd = do_open(fnamecmp, O_RDONLY, 0);
|
||||
|
||||
if (fd == -1) {
|
||||
rprintf(FERROR,"failed to open %s, continuing : %s\n",fnamecmp,strerror(errno));
|
||||
rprintf(FERROR,RSYNC_NAME": failed to open \"%s\", continuing : %s\n",fnamecmp,strerror(errno));
|
||||
/* pretend the file didn't exist */
|
||||
write_int(f_out,i);
|
||||
send_sums(NULL,f_out);
|
||||
|
||||
151
hlink.c
151
hlink.c
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
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
|
||||
@@ -23,19 +24,22 @@ extern int dry_run;
|
||||
extern int verbose;
|
||||
|
||||
#if SUPPORT_HARD_LINKS
|
||||
static int hlink_compare(struct file_struct *f1,struct file_struct *f2)
|
||||
static int hlink_compare(struct file_struct *f1, struct file_struct *f2)
|
||||
{
|
||||
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 (!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->dev != f2->dev)
|
||||
return (int)(f1->dev>f2->dev?1:-1);
|
||||
if (f1->dev != f2->dev)
|
||||
return (int) (f1->dev > f2->dev ? 1 : -1);
|
||||
|
||||
if (f1->inode != f2->inode)
|
||||
return (int)(f1->inode>f2->inode?1:-1);
|
||||
if (f1->inode != f2->inode)
|
||||
return (int) (f1->inode > f2->inode ? 1 : -1);
|
||||
|
||||
return file_compare(&f1,&f2);
|
||||
return file_compare(&f1, &f2);
|
||||
}
|
||||
|
||||
|
||||
@@ -47,22 +51,25 @@ void init_hard_links(struct file_list *flist)
|
||||
{
|
||||
#if SUPPORT_HARD_LINKS
|
||||
int i;
|
||||
if (flist->count < 2) return;
|
||||
if (flist->count < 2)
|
||||
return;
|
||||
|
||||
if (hlink_list) free(hlink_list);
|
||||
|
||||
if (!(hlink_list =
|
||||
(struct file_struct *)malloc(sizeof(hlink_list[0])*flist->count)))
|
||||
if (hlink_list)
|
||||
free(hlink_list);
|
||||
|
||||
if (!(hlink_list =
|
||||
(struct file_struct *) malloc(sizeof(hlink_list[0]) *
|
||||
flist->count)))
|
||||
out_of_memory("init_hard_links");
|
||||
|
||||
for (i = 0; i < flist->count; i++)
|
||||
memcpy(&hlink_list[i], flist->files[i], sizeof(hlink_list[0]));
|
||||
memcpy(&hlink_list[i], flist->files[i],
|
||||
sizeof(hlink_list[0]));
|
||||
|
||||
qsort(hlink_list,flist->count,
|
||||
sizeof(hlink_list[0]),
|
||||
(int (*)())hlink_compare);
|
||||
qsort(hlink_list, flist->count,
|
||||
sizeof(hlink_list[0]), (int (*)()) hlink_compare);
|
||||
|
||||
hlink_count=flist->count;
|
||||
hlink_count = flist->count;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -71,86 +78,102 @@ void init_hard_links(struct file_list *flist)
|
||||
int check_hard_link(struct file_struct *file)
|
||||
{
|
||||
#if SUPPORT_HARD_LINKS
|
||||
int low=0,high=hlink_count-1;
|
||||
int ret=0;
|
||||
int low = 0, high = hlink_count - 1;
|
||||
int ret = 0;
|
||||
|
||||
if (!hlink_list || !S_ISREG(file->mode)) return 0;
|
||||
if (!hlink_list || !S_ISREG(file->mode))
|
||||
return 0;
|
||||
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
if (hlink_compare(&hlink_list[low],file) != 0) return 0;
|
||||
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)
|
||||
return 1;
|
||||
if (low > 0 &&
|
||||
S_ISREG(hlink_list[low - 1].mode) &&
|
||||
file->dev == hlink_list[low - 1].dev &&
|
||||
file->inode == hlink_list[low - 1].inode)
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#if SUPPORT_HARD_LINKS
|
||||
static void hard_link_one(int i)
|
||||
{
|
||||
STRUCT_STAT st1,st2;
|
||||
STRUCT_STAT st1, st2;
|
||||
|
||||
if (link_stat(f_name(&hlink_list[i-1]),&st1) != 0) return;
|
||||
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 (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",
|
||||
rprintf(FINFO, "link %s => %s : %s\n",
|
||||
f_name(&hlink_list[i]),
|
||||
f_name(&hlink_list[i-1]),strerror(errno));
|
||||
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 (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) {
|
||||
do_link(f_name(&hlink_list[i - 1]),
|
||||
f_name(&hlink_list[i])) != 0) {
|
||||
if (verbose > 0)
|
||||
rprintf(FINFO,"link %s => %s : %s\n",
|
||||
rprintf(FINFO, "link %s => %s : %s\n",
|
||||
f_name(&hlink_list[i]),
|
||||
f_name(&hlink_list[i-1]),strerror(errno));
|
||||
f_name(&hlink_list[i - 1]),
|
||||
strerror(errno));
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (verbose > 0)
|
||||
rprintf(FINFO,"%s => %s\n",
|
||||
f_name(&hlink_list[i]),f_name(&hlink_list[i-1]));
|
||||
rprintf(FINFO, "%s => %s\n",
|
||||
f_name(&hlink_list[i]),
|
||||
f_name(&hlink_list[i - 1]));
|
||||
}
|
||||
#endif
|
||||
|
||||
/* create any hard links in the flist */
|
||||
void do_hard_links(struct file_list *flist)
|
||||
|
||||
|
||||
/**
|
||||
* Create any hard links in the global hlink_list. They were put
|
||||
* there by running init_hard_links on the filelist.
|
||||
**/
|
||||
void do_hard_links(void)
|
||||
{
|
||||
#if SUPPORT_HARD_LINKS
|
||||
int i;
|
||||
|
||||
if (!hlink_list) return;
|
||||
|
||||
for (i=1;i<hlink_count;i++) {
|
||||
if (!hlink_list)
|
||||
return;
|
||||
|
||||
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) {
|
||||
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
|
||||
}
|
||||
|
||||
225
io.c
225
io.c
@@ -1,8 +1,6 @@
|
||||
/* -*- c-file-style: "linux" -*-
|
||||
|
||||
Copyright (C) 1996-2001 by Andrew Tridgell
|
||||
/*
|
||||
Copyright (C) Andrew Tridgell 1996
|
||||
Copyright (C) Paul Mackerras 1996
|
||||
Copyright (C) 2001 by Martin Pool <mbp@samba.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -29,34 +27,26 @@
|
||||
/* if no timeout is specified then use a 60 second select timeout */
|
||||
#define SELECT_TIMEOUT 60
|
||||
|
||||
extern int bwlimit;
|
||||
|
||||
static int io_multiplexing_out;
|
||||
static int io_multiplexing_in;
|
||||
static int multiplex_in_fd;
|
||||
static int multiplex_out_fd;
|
||||
static time_t last_io;
|
||||
static int no_flush;
|
||||
|
||||
extern int bwlimit;
|
||||
static int eof_error=1;
|
||||
extern int verbose;
|
||||
extern int io_timeout;
|
||||
extern struct stats stats;
|
||||
|
||||
|
||||
/** Ignore EOF errors while reading a module listing if the remote
|
||||
version is 24 or less. */
|
||||
int kludge_around_eof = False;
|
||||
|
||||
|
||||
static int io_error_fd = -1;
|
||||
|
||||
static void read_loop(int fd, char *buf, int len);
|
||||
static void read_loop(int fd, char *buf, size_t len);
|
||||
|
||||
static void check_timeout(void)
|
||||
{
|
||||
extern int am_server, am_daemon;
|
||||
time_t t;
|
||||
|
||||
err_list_push();
|
||||
|
||||
if (!io_timeout) return;
|
||||
|
||||
@@ -69,7 +59,7 @@ static void check_timeout(void)
|
||||
|
||||
if (last_io && io_timeout && (t-last_io) >= io_timeout) {
|
||||
if (!am_server && !am_daemon) {
|
||||
rprintf(FERROR,"io timeout after %d seconds - exiting\n",
|
||||
rprintf(FERROR,"io timeout after %d second - exiting\n",
|
||||
(int)(t-last_io));
|
||||
}
|
||||
exit_cleanup(RERR_TIMEOUT);
|
||||
@@ -90,8 +80,6 @@ static void read_error_fd(void)
|
||||
int fd = io_error_fd;
|
||||
int tag, len;
|
||||
|
||||
/* io_error_fd is temporarily disabled -- is this meant to
|
||||
* prevent indefinite recursion? */
|
||||
io_error_fd = -1;
|
||||
|
||||
read_loop(fd, buf, 4);
|
||||
@@ -113,68 +101,21 @@ static void read_error_fd(void)
|
||||
}
|
||||
|
||||
|
||||
static void whine_about_eof (void)
|
||||
{
|
||||
/**
|
||||
It's almost always an error to get an EOF when we're trying
|
||||
to read from the network, because the protocol is
|
||||
self-terminating.
|
||||
|
||||
However, there is one unfortunate cases where it is not,
|
||||
which is rsync <2.4.6 sending a list of modules on a
|
||||
server, since the list is terminated by closing the socket.
|
||||
So, for the section of the program where that is a problem
|
||||
(start_socket_client), kludge_around_eof is True and we
|
||||
just exit.
|
||||
*/
|
||||
static int no_flush;
|
||||
|
||||
if (kludge_around_eof)
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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));
|
||||
exit_cleanup(RERR_STREAMIO);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
* Read from a socket with IO timeout. return the number of bytes
|
||||
* read. If no bytes can be read then exit, never return a number <= 0.
|
||||
*
|
||||
* TODO: If the remote shell connection fails, then current versions
|
||||
* actually report an "unexpected EOF" error here. Since it's a
|
||||
* fairly common mistake to try to use rsh when ssh is required, we
|
||||
* should trap that: if we fail to read any data at all, we should
|
||||
* 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, int len)
|
||||
/* read from a socket with IO timeout. return the number of
|
||||
bytes read. If no bytes can be read then exit, never return
|
||||
a number <= 0 */
|
||||
static int read_timeout(int fd, char *buf, size_t len)
|
||||
{
|
||||
int n, ret=0;
|
||||
|
||||
io_flush();
|
||||
|
||||
while (ret == 0) {
|
||||
/* until we manage to read *something* */
|
||||
fd_set fds;
|
||||
struct timeval tv;
|
||||
int fd_count = fd+1;
|
||||
int count;
|
||||
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(fd, &fds);
|
||||
@@ -188,16 +129,11 @@ static int read_timeout (int fd, char *buf, int len)
|
||||
|
||||
errno = 0;
|
||||
|
||||
count = select(fd_count, &fds, NULL, NULL, &tv);
|
||||
|
||||
if (count == 0) {
|
||||
check_timeout();
|
||||
}
|
||||
|
||||
if (count <= 0) {
|
||||
if (select(fd_count, &fds, NULL, NULL, &tv) < 1) {
|
||||
if (errno == EBADF) {
|
||||
exit_cleanup(RERR_SOCKETIO);
|
||||
}
|
||||
check_timeout();
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -216,27 +152,38 @@ static int read_timeout (int fd, char *buf, int len)
|
||||
if (io_timeout)
|
||||
last_io = time(NULL);
|
||||
continue;
|
||||
} else if (n == 0) {
|
||||
whine_about_eof ();
|
||||
return -1; /* doesn't return */
|
||||
} else if (n == -1) {
|
||||
if (errno == EINTR || errno == EWOULDBLOCK ||
|
||||
errno == EAGAIN)
|
||||
continue;
|
||||
else
|
||||
die_from_readerr (errno);
|
||||
}
|
||||
|
||||
if (n == -1 && errno == EINTR) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (n == -1 &&
|
||||
(errno == EWOULDBLOCK || errno == EAGAIN)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (n == 0) {
|
||||
if (eof_error) {
|
||||
rprintf(FERROR,"unexpected EOF in read_timeout\n");
|
||||
}
|
||||
exit_cleanup(RERR_STREAMIO);
|
||||
}
|
||||
|
||||
/* this prevents us trying to write errors on a dead socket */
|
||||
io_multiplexing_close();
|
||||
|
||||
rprintf(FERROR,"read error: %s\n", strerror(errno));
|
||||
exit_cleanup(RERR_STREAMIO);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*! Continue trying to read len bytes - don't return until len has
|
||||
been read. */
|
||||
static void read_loop (int fd, char *buf, int len)
|
||||
/* 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)
|
||||
{
|
||||
while (len) {
|
||||
int n = read_timeout(fd, buf, len);
|
||||
@@ -246,20 +193,16 @@ static void read_loop (int fd, char *buf, int len)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Read from the file descriptor handling multiplexing - return number
|
||||
* of bytes read.
|
||||
*
|
||||
* Never returns <= 0.
|
||||
*/
|
||||
static int read_unbuffered(int fd, char *buf, int len)
|
||||
/* read from the file descriptor handling multiplexing -
|
||||
return number of bytes read
|
||||
never return <= 0 */
|
||||
static int read_unbuffered(int fd, char *buf, size_t len)
|
||||
{
|
||||
static int remaining;
|
||||
int tag, ret=0;
|
||||
char line[1024];
|
||||
|
||||
if (!io_multiplexing_in || fd != multiplex_in_fd)
|
||||
if (!io_multiplexing_in || fd != multiplex_in_fd)
|
||||
return read_timeout(fd, buf, len);
|
||||
|
||||
while (ret == 0) {
|
||||
@@ -271,7 +214,7 @@ static int read_unbuffered(int fd, char *buf, int len)
|
||||
continue;
|
||||
}
|
||||
|
||||
read_loop (fd, line, 4);
|
||||
read_loop(fd, line, 4);
|
||||
tag = IVAL(line, 0);
|
||||
|
||||
remaining = tag & 0xFFFFFF;
|
||||
@@ -305,7 +248,7 @@ static int read_unbuffered(int fd, char *buf, int len)
|
||||
|
||||
/* do a buffered read from fd. don't return until all N bytes
|
||||
have been read. If all N can't be read then exit with an error */
|
||||
static void readfd (int fd, char *buffer, int N)
|
||||
static void readfd(int fd,char *buffer,size_t N)
|
||||
{
|
||||
int ret;
|
||||
int total=0;
|
||||
@@ -313,7 +256,7 @@ static void readfd (int fd, char *buffer, int N)
|
||||
while (total < N) {
|
||||
io_flush();
|
||||
|
||||
ret = read_unbuffered (fd, buffer + total, N-total);
|
||||
ret = read_unbuffered(fd,buffer + total,N-total);
|
||||
total += ret;
|
||||
}
|
||||
|
||||
@@ -356,34 +299,32 @@ int64 read_longint(int f)
|
||||
return ret;
|
||||
}
|
||||
|
||||
void read_buf(int f,char *buf,int len)
|
||||
void read_buf(int f,char *buf,size_t len)
|
||||
{
|
||||
readfd(f,buf,len);
|
||||
}
|
||||
|
||||
void read_sbuf(int f,char *buf,int 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;
|
||||
}
|
||||
|
||||
/* write len bytes to fd */
|
||||
static void writefd_unbuffered(int fd,char *buf,int len)
|
||||
static void writefd_unbuffered(int fd,char *buf,size_t len)
|
||||
{
|
||||
int total = 0;
|
||||
fd_set w_fds, r_fds;
|
||||
int fd_count, count;
|
||||
struct timeval tv;
|
||||
|
||||
err_list_push();
|
||||
|
||||
no_flush++;
|
||||
|
||||
while (total < len) {
|
||||
@@ -408,14 +349,11 @@ static void writefd_unbuffered(int fd,char *buf,int len)
|
||||
&w_fds,NULL,
|
||||
&tv);
|
||||
|
||||
if (count == 0) {
|
||||
check_timeout();
|
||||
}
|
||||
|
||||
if (count <= 0) {
|
||||
if (errno == EBADF) {
|
||||
exit_cleanup(RERR_SOCKETIO);
|
||||
}
|
||||
check_timeout();
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -425,6 +363,7 @@ static void writefd_unbuffered(int fd,char *buf,int len)
|
||||
|
||||
if (FD_ISSET(fd, &w_fds)) {
|
||||
int ret, n = len-total;
|
||||
|
||||
ret = write(fd,buf+total,n);
|
||||
|
||||
if (ret == -1 && errno == EINTR) {
|
||||
@@ -438,10 +377,7 @@ static void writefd_unbuffered(int fd,char *buf,int len)
|
||||
}
|
||||
|
||||
if (ret <= 0) {
|
||||
rprintf(FERROR,
|
||||
"error writing %d unbuffered bytes"
|
||||
" - exiting: %s\n", len,
|
||||
strerror(errno));
|
||||
rprintf(FERROR,"erroring writing %d bytes - exiting\n", len);
|
||||
exit_cleanup(RERR_STREAMIO);
|
||||
}
|
||||
|
||||
@@ -483,7 +419,7 @@ void io_start_buffering(int fd)
|
||||
|
||||
/* write an message to a multiplexed stream. If this fails then rsync
|
||||
exits */
|
||||
static void mplex_write(int fd, enum logcode code, char *buf, int len)
|
||||
static void mplex_write(int fd, enum logcode code, char *buf, size_t len)
|
||||
{
|
||||
char buffer[4096];
|
||||
int n = len;
|
||||
@@ -509,9 +445,6 @@ static void mplex_write(int fd, enum logcode code, char *buf, int len)
|
||||
void io_flush(void)
|
||||
{
|
||||
int fd = multiplex_out_fd;
|
||||
|
||||
err_list_push();
|
||||
|
||||
if (!io_buffer_count || no_flush) return;
|
||||
|
||||
if (io_multiplexing_out) {
|
||||
@@ -522,8 +455,6 @@ void io_flush(void)
|
||||
io_buffer_count = 0;
|
||||
}
|
||||
|
||||
|
||||
/* XXX: fd is ignored, which seems a little strange. */
|
||||
void io_end_buffering(int fd)
|
||||
{
|
||||
io_flush();
|
||||
@@ -533,12 +464,21 @@ void io_end_buffering(int fd)
|
||||
}
|
||||
}
|
||||
|
||||
static void writefd(int fd,char *buf,int len)
|
||||
/* some OSes have a bug where an exit causes the pending writes on
|
||||
a socket to be flushed. Do an explicit shutdown to try to prevent this */
|
||||
void io_shutdown(void)
|
||||
{
|
||||
if (multiplex_out_fd != -1) close(multiplex_out_fd);
|
||||
if (io_error_fd != -1) close(io_error_fd);
|
||||
multiplex_out_fd = -1;
|
||||
io_error_fd = -1;
|
||||
}
|
||||
|
||||
|
||||
static void writefd(int fd,char *buf,size_t len)
|
||||
{
|
||||
stats.total_written += len;
|
||||
|
||||
err_list_push();
|
||||
|
||||
if (!io_buffer || fd != multiplex_out_fd) {
|
||||
writefd_unbuffered(fd, buf, len);
|
||||
return;
|
||||
@@ -565,11 +505,6 @@ void write_int(int f,int32 x)
|
||||
writefd(f,b,4);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Note: int64 may actually be a 32-bit type if ./configure couldn't find any
|
||||
* 64-bit types on this platform.
|
||||
*/
|
||||
void write_longint(int f, int64 x)
|
||||
{
|
||||
extern int remote_version;
|
||||
@@ -587,7 +522,7 @@ void write_longint(int f, int64 x)
|
||||
writefd(f,b,8);
|
||||
}
|
||||
|
||||
void write_buf(int f,char *buf,int len)
|
||||
void write_buf(int f,char *buf,size_t len)
|
||||
{
|
||||
writefd(f,buf,len);
|
||||
}
|
||||
@@ -604,10 +539,10 @@ void write_byte(int f,unsigned char c)
|
||||
write_buf(f,(char *)&c,1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int read_line(int f, char *buf, int maxlen)
|
||||
int read_line(int f, char *buf, size_t maxlen)
|
||||
{
|
||||
eof_error = 0;
|
||||
|
||||
while (maxlen) {
|
||||
buf[0] = 0;
|
||||
read_buf(f, buf, 1);
|
||||
@@ -626,6 +561,8 @@ int read_line(int f, char *buf, int maxlen)
|
||||
return 0;
|
||||
}
|
||||
|
||||
eof_error = 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -637,7 +574,7 @@ void io_printf(int fd, const char *format, ...)
|
||||
int len;
|
||||
|
||||
va_start(ap, format);
|
||||
len = vsnprintf(buf, sizeof(buf), format, ap);
|
||||
len = vslprintf(buf, sizeof(buf), format, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (len < 0) exit_cleanup(RERR_STREAMIO);
|
||||
@@ -664,7 +601,7 @@ void io_start_multiplex_in(int fd)
|
||||
}
|
||||
|
||||
/* write an message to the multiplexed error stream */
|
||||
int io_multiplex_write(enum logcode code, char *buf, int len)
|
||||
int io_multiplex_write(enum logcode code, char *buf, size_t len)
|
||||
{
|
||||
if (!io_multiplexing_out) return 0;
|
||||
|
||||
@@ -674,6 +611,14 @@ int io_multiplex_write(enum logcode code, char *buf, int len)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* write a message to the special error fd */
|
||||
int io_error_write(int f, enum logcode code, char *buf, size_t len)
|
||||
{
|
||||
if (f == -1) return 0;
|
||||
mplex_write(f, code, buf, len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* stop output multiplexing */
|
||||
void io_multiplexing_close(void)
|
||||
{
|
||||
|
||||
@@ -97,8 +97,10 @@
|
||||
|
||||
|
||||
#ifndef HAVE_STRLCPY
|
||||
/* like strncpy but does not 0 fill the buffer and always null
|
||||
terminates. bufsize is the size of the destination buffer */
|
||||
/* Like strncpy but does not 0 fill the buffer and always null
|
||||
* terminates. bufsize is the size of the destination buffer.
|
||||
*
|
||||
* Returns the index of the terminating byte. */
|
||||
size_t strlcpy(char *d, const char *s, size_t bufsize)
|
||||
{
|
||||
size_t len = strlen(s);
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include "rsync.h"
|
||||
|
||||
/**
|
||||
* Produce a string representation of Unix mode bits like that used by
|
||||
|
||||
15
loadparm.c
15
loadparm.c
@@ -386,9 +386,16 @@ static void init_service(service *pservice)
|
||||
|
||||
|
||||
/**
|
||||
* Assign a copy of @p v to @p *s, freeing any existing values and
|
||||
* handling NULL strings. @p *v must be initialized when this is
|
||||
* called, either to NULL or a malloc'd string.
|
||||
* Assign a copy of @p v to @p *s. Handles NULL strings. @p *v must
|
||||
* be initialized when this is called, either to NULL or a malloc'd
|
||||
* string.
|
||||
*
|
||||
* @fixme There is a small leak here in that sometimes the existing
|
||||
* value will be dynamically allocated, and the old copy is lost.
|
||||
* However, we can't always deallocate the old value, because in the
|
||||
* case of sDefault, it points to a static string. It would be nice
|
||||
* to have either all-strdup'd values, or to never need to free
|
||||
* memory.
|
||||
**/
|
||||
static void string_set(char **s, const char *v)
|
||||
{
|
||||
@@ -396,8 +403,6 @@ static void string_set(char **s, const char *v)
|
||||
*s = NULL;
|
||||
return;
|
||||
}
|
||||
if (*s)
|
||||
free(*s);
|
||||
*s = strdup(v);
|
||||
if (!*s)
|
||||
exit_cleanup(RERR_MALLOC);
|
||||
|
||||
269
log.c
269
log.c
@@ -1,7 +1,5 @@
|
||||
/* -*- c-file-style: "linux"; -*-
|
||||
|
||||
Copyright (C) 1998-2001 by Andrew Tridgell <tridge@samba.org>
|
||||
Copyright (C) 2000-2001 by Martin Pool <mbp@samba.org>
|
||||
/*
|
||||
Copyright (C) Andrew Tridgell 1998
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -19,121 +17,18 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
Logging and utility functions.
|
||||
tridge, May 1998
|
||||
logging and utility functions
|
||||
|
||||
Mapping to human-readable messages added by Martin Pool
|
||||
<mbp@samba.org>, Oct 2000.
|
||||
tridge, May 1998
|
||||
*/
|
||||
#include "rsync.h"
|
||||
|
||||
static char *logfname;
|
||||
static FILE *logfile;
|
||||
static int log_error_fd = -1;
|
||||
|
||||
int log_got_error=0;
|
||||
|
||||
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_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 , "partial transfer" },
|
||||
{ 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 }
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Map from rsync error code to name, or return NULL.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
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 = (struct err_list *)malloc(sizeof(*el));
|
||||
if (!el) exit_cleanup(RERR_MALLOC);
|
||||
el->next = NULL;
|
||||
el->buf = malloc(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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void logit(int priority, char *buf)
|
||||
{
|
||||
if (logfname) {
|
||||
if (!logfile)
|
||||
log_open();
|
||||
if (logfile) {
|
||||
fprintf(logfile,"%s [%d] %s",
|
||||
timestring(time(NULL)), (int)getpid(), buf);
|
||||
fflush(logfile);
|
||||
@@ -142,11 +37,12 @@ static void logit(int priority, char *buf)
|
||||
}
|
||||
}
|
||||
|
||||
void log_init(void)
|
||||
void log_open(void)
|
||||
{
|
||||
static int initialised;
|
||||
int options = LOG_PID;
|
||||
time_t t;
|
||||
char *logf;
|
||||
|
||||
if (initialised) return;
|
||||
initialised = 1;
|
||||
@@ -158,13 +54,13 @@ void log_init(void)
|
||||
localtime(&t);
|
||||
|
||||
/* optionally use a log file instead of syslog */
|
||||
logfname = lp_log_file();
|
||||
if (logfname) {
|
||||
if (*logfname) {
|
||||
log_open();
|
||||
return;
|
||||
}
|
||||
logfname = NULL;
|
||||
logf = lp_log_file();
|
||||
if (logf && *logf) {
|
||||
extern int orig_umask;
|
||||
int old_umask = umask(022 | orig_umask);
|
||||
logfile = fopen(logf, "a");
|
||||
umask(old_umask);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef LOG_NDELAY
|
||||
@@ -182,30 +78,11 @@ void log_init(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
void log_open()
|
||||
{
|
||||
if (logfname && !logfile) {
|
||||
extern int orig_umask;
|
||||
int old_umask = umask(022 | orig_umask);
|
||||
logfile = fopen(logfname, "a");
|
||||
umask(old_umask);
|
||||
}
|
||||
}
|
||||
|
||||
void log_close()
|
||||
{
|
||||
if (logfile) {
|
||||
fclose(logfile);
|
||||
logfile = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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
|
||||
@@ -229,14 +106,12 @@ void rwrite(enum logcode code, char *buf, int 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();
|
||||
/* first try to pass it off the our sibling */
|
||||
if (am_server && io_error_write(log_error_fd, code, buf, len)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* if that fails, try to pass it to the other end */
|
||||
/* then try to pass it to the other end */
|
||||
if (am_server && io_multiplex_write(code, buf, len)) {
|
||||
return;
|
||||
}
|
||||
@@ -250,7 +125,7 @@ void rwrite(enum logcode code, char *buf, int len)
|
||||
|
||||
depth++;
|
||||
|
||||
log_init();
|
||||
log_open();
|
||||
logit(priority, buf);
|
||||
|
||||
depth--;
|
||||
@@ -258,7 +133,6 @@ void rwrite(enum logcode code, char *buf, int len)
|
||||
}
|
||||
|
||||
if (code == FERROR) {
|
||||
log_got_error = 1;
|
||||
f = stderr;
|
||||
}
|
||||
|
||||
@@ -277,86 +151,22 @@ void rwrite(enum logcode code, char *buf, int len)
|
||||
}
|
||||
|
||||
|
||||
/* This is the rsync debugging function. Call it with FINFO, FERROR or
|
||||
* FLOG. */
|
||||
void rprintf(enum logcode code, const char *format, ...)
|
||||
/* this is the rsync debugging function. Call it with FINFO, FERROR or FLOG */
|
||||
void rprintf(enum logcode code, const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char buf[1024];
|
||||
int len;
|
||||
|
||||
va_start(ap, format);
|
||||
len = vsnprintf(buf, sizeof(buf), format, ap);
|
||||
va_end(ap);
|
||||
|
||||
/* Deal with buffer overruns. Instead of panicking, just
|
||||
* truncate the resulting string. Note that some vsnprintf()s
|
||||
* return -1 on truncation, e.g., glibc 2.0.6 and earlier. */
|
||||
if (len > sizeof(buf)-1 || len < 0) {
|
||||
const char ellipsis[] = "[...]";
|
||||
|
||||
/* Reset length, and zero-terminate the end of our buffer */
|
||||
len = sizeof(buf)-1;
|
||||
buf[len] = '\0';
|
||||
|
||||
/* Copy the ellipsis to the end of the string, but give
|
||||
* us one extra character:
|
||||
*
|
||||
* v--- null byte at buf[sizeof(buf)-1]
|
||||
* abcdefghij0
|
||||
* -> abcd[...]00 <-- now two null bytes at end
|
||||
*
|
||||
* If the input format string has a trailing newline,
|
||||
* we copy it into that extra null; if it doesn't, well,
|
||||
* all we lose is one byte. */
|
||||
strncpy(buf+len-sizeof(ellipsis), ellipsis, sizeof(ellipsis));
|
||||
if (format[strlen(format)-1] == '\n') {
|
||||
buf[len-1] = '\n';
|
||||
}
|
||||
}
|
||||
|
||||
rwrite(code, buf, len);
|
||||
}
|
||||
|
||||
|
||||
/* This is like rprintf, but it also tries to print some
|
||||
* representation of the error code. Normally errcode = errno.
|
||||
*
|
||||
* Unlike rprintf, this always adds a newline and there should not be
|
||||
* one in the format string.
|
||||
*
|
||||
* Note that since strerror might involve dynamically loading a
|
||||
* message catalog we need to call it once before chroot-ing. */
|
||||
void rsyserr(enum logcode code, int errcode, const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char buf[1024];
|
||||
int len, sys_len;
|
||||
char *sysmsg;
|
||||
|
||||
va_start(ap, format);
|
||||
len = vsnprintf(buf, sizeof(buf), format, ap);
|
||||
len = vslprintf(buf, sizeof(buf), format, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (len > sizeof(buf)-1) exit_cleanup(RERR_MESSAGEIO);
|
||||
|
||||
sysmsg = strerror(errcode);
|
||||
sys_len = strlen(sysmsg);
|
||||
if (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++;
|
||||
|
||||
rwrite(code, buf, len);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void rflush(enum logcode code)
|
||||
{
|
||||
FILE *f = NULL;
|
||||
@@ -405,6 +215,8 @@ static void log_formatted(enum logcode code,
|
||||
extern int am_daemon;
|
||||
int64 b;
|
||||
|
||||
memset(buf,0,sizeof(buf));
|
||||
|
||||
strlcpy(buf, format, sizeof(buf));
|
||||
|
||||
for (s=&buf[0];
|
||||
@@ -416,18 +228,18 @@ static void log_formatted(enum logcode code,
|
||||
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",
|
||||
slprintf(buf2,sizeof(buf2),"%.0f",
|
||||
(double)file->length);
|
||||
n = buf2;
|
||||
break;
|
||||
case 'p':
|
||||
snprintf(buf2,sizeof(buf2),"%d",
|
||||
slprintf(buf2,sizeof(buf2),"%d",
|
||||
(int)getpid());
|
||||
n = buf2;
|
||||
break;
|
||||
case 'o': n = op; break;
|
||||
case 'f':
|
||||
snprintf(buf2, sizeof(buf2), "%s/%s",
|
||||
slprintf(buf2, sizeof(buf2), "%s/%s",
|
||||
file->basedir?file->basedir:"",
|
||||
f_name(file));
|
||||
clean_fname(buf2);
|
||||
@@ -446,7 +258,7 @@ static void log_formatted(enum logcode code,
|
||||
b = stats.total_read -
|
||||
initial_stats->total_read;
|
||||
}
|
||||
snprintf(buf2,sizeof(buf2),"%.0f", (double)b);
|
||||
slprintf(buf2,sizeof(buf2),"%.0f", (double)b);
|
||||
n = buf2;
|
||||
break;
|
||||
case 'c':
|
||||
@@ -457,7 +269,7 @@ static void log_formatted(enum logcode code,
|
||||
b = stats.total_read -
|
||||
initial_stats->total_read;
|
||||
}
|
||||
snprintf(buf2,sizeof(buf2),"%.0f", (double)b);
|
||||
slprintf(buf2,sizeof(buf2),"%.0f", (double)b);
|
||||
n = buf2;
|
||||
break;
|
||||
}
|
||||
@@ -466,7 +278,7 @@ static void log_formatted(enum logcode code,
|
||||
|
||||
l = strlen(n);
|
||||
|
||||
if ((l-1) + ((int)(s - &buf[0])) > sizeof(buf)) {
|
||||
if (l + ((int)(s - &buf[0])) > sizeof(buf)) {
|
||||
rprintf(FERROR,"buffer overflow expanding %%%c - exiting\n",
|
||||
p[0]);
|
||||
exit_cleanup(RERR_MESSAGEIO);
|
||||
@@ -511,15 +323,7 @@ void log_recv(struct file_struct *file, struct stats *initial_stats)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Called when the transfer is interrupted for some reason.
|
||||
*
|
||||
* Code is one of the RERR_* codes from errcode.h, or terminating
|
||||
* successfully.
|
||||
*/
|
||||
/* called when the transfer is interrupted for some reason */
|
||||
void log_exit(int code, const char *file, int line)
|
||||
{
|
||||
if (code == 0) {
|
||||
@@ -529,20 +333,11 @@ void log_exit(int code, const char *file, int line)
|
||||
(double)stats.total_read,
|
||||
(double)stats.total_size);
|
||||
} else {
|
||||
const char *name;
|
||||
|
||||
name = rerr_name(code);
|
||||
if (!name)
|
||||
name = "unexplained error";
|
||||
|
||||
rprintf(FERROR,"rsync error: %s (code %d) at %s(%d)\n",
|
||||
name, code, file, line);
|
||||
rprintf(FLOG,"transfer interrupted (code %d) at %s(%d)\n",
|
||||
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
|
||||
|
||||
|
||||
44
main.c
44
main.c
@@ -2,7 +2,7 @@
|
||||
|
||||
Copyright (C) 1996-2001 by Andrew Tridgell <tridge@samba.org>
|
||||
Copyright (C) Paul Mackerras 1996
|
||||
Copyright (C) 2001 by Martin Pool <mbp@samba.org>
|
||||
Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -27,6 +27,7 @@ struct stats stats;
|
||||
|
||||
extern int verbose;
|
||||
|
||||
static void show_malloc_stats(void);
|
||||
|
||||
/****************************************************************************
|
||||
wait for a process to exit, calling io_flush while waiting
|
||||
@@ -56,6 +57,11 @@ static void report(int f)
|
||||
extern int remote_version;
|
||||
int send_stats;
|
||||
|
||||
if (do_stats) {
|
||||
/* These come out from every process */
|
||||
show_malloc_stats();
|
||||
}
|
||||
|
||||
if (am_daemon) {
|
||||
log_exit(0, __FILE__, __LINE__);
|
||||
if (f == -1 || !am_sender) return;
|
||||
@@ -126,6 +132,38 @@ static void report(int f)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* If our C library can get malloc statistics, then show them to FINFO
|
||||
**/
|
||||
static void show_malloc_stats(void)
|
||||
{
|
||||
#ifdef HAVE_MALLINFO
|
||||
struct mallinfo mi;
|
||||
extern int am_server;
|
||||
extern int am_sender;
|
||||
extern int am_daemon;
|
||||
|
||||
mi = mallinfo();
|
||||
|
||||
rprintf(FINFO, RSYNC_NAME "[%d] (%s%s%s) heap statistics:\n",
|
||||
getpid(),
|
||||
am_server ? "server " : "",
|
||||
am_daemon ? "daemon " : "",
|
||||
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, " usmblks: %10d\n", mi.usmblks);
|
||||
rprintf(FINFO, " fsmblks: %10d\n", mi.fsmblks);
|
||||
rprintf(FINFO, " uordblks: %10d (bytes used)\n", mi.uordblks);
|
||||
rprintf(FINFO, " fordblks: %10d (bytes free)\n", mi.fordblks);
|
||||
rprintf(FINFO, " keepcost: %10d (bytes in releasable chunk)\n", mi.keepcost);
|
||||
#endif /* HAVE_MALLINFO */
|
||||
}
|
||||
|
||||
|
||||
/* 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)
|
||||
{
|
||||
@@ -765,8 +803,10 @@ int main(int argc,char *argv[])
|
||||
extern int write_batch; /* dw */
|
||||
extern char *batch_ext; /* dw */
|
||||
int orig_argc; /* dw */
|
||||
char **orig_argv;
|
||||
|
||||
orig_argc = argc; /* dw */
|
||||
orig_argv = argv;
|
||||
|
||||
signal(SIGUSR1, sigusr1_handler);
|
||||
signal(SIGUSR2, sigusr2_handler);
|
||||
@@ -806,7 +846,7 @@ int main(int argc,char *argv[])
|
||||
|
||||
if (write_batch) { /* dw */
|
||||
create_batch_file_ext();
|
||||
write_batch_argvs_file(orig_argc, argc, argv);
|
||||
write_batch_argvs_file(orig_argc, orig_argv);
|
||||
}
|
||||
|
||||
if (read_batch) { /* dw */
|
||||
|
||||
75
options.c
75
options.c
@@ -1,7 +1,7 @@
|
||||
/* -*- c-file-style: "linux" -*-
|
||||
|
||||
Copyright (C) 1998-2001 by Andrew Tridgell <tridge@samba.org>
|
||||
Copyright (C) 2000-2001 by Martin Pool <mbp@samba.org>
|
||||
Copyright (C) 2000, 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
|
||||
@@ -74,11 +74,21 @@ int modify_window=0;
|
||||
#endif
|
||||
int blocking_io=0;
|
||||
|
||||
/** Global options set from command line. **/
|
||||
struct global_opts global_opts;
|
||||
/** Network address family. **/
|
||||
#ifdef INET6
|
||||
int default_af_hint = 0; /* Any protocol */
|
||||
#else
|
||||
int default_af_hint = AF_INET; /* Must use IPv4 */
|
||||
#endif
|
||||
|
||||
int read_batch=0; /* dw */
|
||||
int write_batch=0; /* dw */
|
||||
/** Do not go into the background when run as --daemon. Good
|
||||
* for debugging and required for running as a service on W32,
|
||||
* or under Unix process-monitors. **/
|
||||
int no_detach = 0;
|
||||
|
||||
|
||||
int read_batch=0;
|
||||
int write_batch=0;
|
||||
|
||||
char *backup_suffix = BACKUP_SUFFIX;
|
||||
char *tmpdir = NULL;
|
||||
@@ -106,12 +116,13 @@ static int modify_window_set;
|
||||
char *bind_address;
|
||||
|
||||
|
||||
static void print_rsync_version(int f)
|
||||
static void print_rsync_version(enum logcode f)
|
||||
{
|
||||
char const *got_socketpair = "no ";
|
||||
char const *hardlinks = "no ";
|
||||
char const *links = "no ";
|
||||
char const *ipv6 = "no ";
|
||||
STRUCT_STAT *dumstat;
|
||||
|
||||
#ifdef HAVE_SOCKETPAIR
|
||||
got_socketpair = "";
|
||||
@@ -132,13 +143,20 @@ static void print_rsync_version(int f)
|
||||
rprintf(f, "%s version %s protocol version %d\n",
|
||||
RSYNC_NAME, RSYNC_VERSION, PROTOCOL_VERSION);
|
||||
rprintf(f,
|
||||
"Copyright (C) 1996-2001 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, %sIPv6\n\n",
|
||||
"%shard links, %ssymlinks, batchfiles, %sIPv6,\n",
|
||||
(int) (sizeof(OFF_T) * 8),
|
||||
got_socketpair, hardlinks, links, ipv6);
|
||||
|
||||
/* Note that this field may not have type ino_t. It depends
|
||||
* on the complicated interaction between largefile feature
|
||||
* macros. */
|
||||
rprintf(f, " %d-bit system inums, %d-bit internal inums\n",
|
||||
(int) (sizeof(dumstat->st_ino) * 8),
|
||||
(int) (sizeof(INO64_T) * 8));
|
||||
|
||||
#ifdef NO_INT64
|
||||
rprintf(f, "WARNING: no 64-bit integers on this platform!\n");
|
||||
#endif
|
||||
@@ -171,8 +189,8 @@ void usage(enum logcode F)
|
||||
rprintf(F," --backup-dir make backups into this directory\n");
|
||||
rprintf(F," --suffix=SUFFIX override backup suffix\n");
|
||||
rprintf(F," -u, --update update only (don't overwrite newer files)\n");
|
||||
rprintf(F," -l, --links preserve soft links\n");
|
||||
rprintf(F," -L, --copy-links treat soft links like regular files\n");
|
||||
rprintf(F," -l, --links copy symlinks as 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");
|
||||
@@ -212,7 +230,8 @@ void usage(enum logcode F)
|
||||
rprintf(F," --include-from=FILE don't exclude patterns listed in FILE\n");
|
||||
rprintf(F," --version print version number\n");
|
||||
rprintf(F," --daemon run as a rsync daemon\n");
|
||||
rprintf(F," --address bind to the specified address\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 IO for the remote shell\n");
|
||||
@@ -221,8 +240,8 @@ void usage(enum logcode F)
|
||||
rprintf(F," --log-format=FORMAT log file transfers using specified format\n");
|
||||
rprintf(F," --password-file=FILE get password from FILE\n");
|
||||
rprintf(F," --bwlimit=KBPS limit I/O bandwidth, KBytes per second\n");
|
||||
rprintf(F," -f --read-batch=EXT read batch file\n");
|
||||
rprintf(F," -F --write-batch write batch file\n");
|
||||
rprintf(F," --read-batch=EXT read batch file\n");
|
||||
rprintf(F," --write-batch write batch file\n");
|
||||
rprintf(F," -h, --help show this help screen\n");
|
||||
#ifdef INET6
|
||||
rprintf(F," -4 prefer IPv4\n");
|
||||
@@ -243,7 +262,7 @@ enum {OPT_VERSION = 1000, OPT_SUFFIX, OPT_SENDER, OPT_SERVER, OPT_EXCLUDE,
|
||||
OPT_LOG_FORMAT, OPT_PASSWORD_FILE, OPT_SIZE_ONLY, OPT_ADDRESS,
|
||||
OPT_DELETE_AFTER, OPT_EXISTING, OPT_MAX_DELETE, OPT_BACKUP_DIR,
|
||||
OPT_IGNORE_ERRORS, OPT_BWLIMIT, OPT_BLOCKING_IO,
|
||||
OPT_MODIFY_WINDOW};
|
||||
OPT_MODIFY_WINDOW, OPT_READ_BATCH, OPT_WRITE_BATCH};
|
||||
|
||||
static struct poptOption long_options[] = {
|
||||
/* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
|
||||
@@ -274,7 +293,7 @@ static struct poptOption long_options[] = {
|
||||
{"update", 'u', POPT_ARG_NONE, &update_only},
|
||||
{"links", 'l', POPT_ARG_NONE, &preserve_links},
|
||||
{"copy-links", 'L', POPT_ARG_NONE, ©_links},
|
||||
{"whole", 'W', POPT_ARG_NONE, &whole_file},
|
||||
{"whole-file", 'W', POPT_ARG_NONE, &whole_file},
|
||||
{"copy-unsafe-links", 0, POPT_ARG_NONE, ©_unsafe_links},
|
||||
{"perms", 'p', POPT_ARG_NONE, &preserve_perms},
|
||||
{"owner", 'o', POPT_ARG_NONE, &preserve_uid},
|
||||
@@ -298,6 +317,7 @@ static struct poptOption long_options[] = {
|
||||
/* TODO: Should this take an optional int giving the compression level? */
|
||||
{"compress", 'z', POPT_ARG_NONE, &do_compression},
|
||||
{"daemon", 0, POPT_ARG_NONE, &am_daemon},
|
||||
{"no-detach", 0, POPT_ARG_NONE, &no_detach},
|
||||
{"stats", 0, POPT_ARG_NONE, &do_stats},
|
||||
{"progress", 0, POPT_ARG_NONE, &do_progress},
|
||||
{"partial", 0, POPT_ARG_NONE, &keep_partial},
|
||||
@@ -311,11 +331,11 @@ static struct poptOption long_options[] = {
|
||||
{"address", 0, POPT_ARG_STRING, &bind_address, 0},
|
||||
{"backup-dir", 0, POPT_ARG_STRING, &backup_dir},
|
||||
{"hard-links", 'H', POPT_ARG_NONE, &preserve_hard_links},
|
||||
{"read-batch", 'f', POPT_ARG_STRING, &batch_ext, 'f'},
|
||||
{"write-batch", 'F', POPT_ARG_NONE, &write_batch, 0},
|
||||
{"read-batch", 0, POPT_ARG_STRING, &batch_ext, OPT_READ_BATCH},
|
||||
{"write-batch", 0, POPT_ARG_NONE, &write_batch},
|
||||
#ifdef INET6
|
||||
{0, '4', POPT_ARG_VAL, &global_opts.af_hint, AF_INET },
|
||||
{0, '6', POPT_ARG_VAL, &global_opts.af_hint, AF_INET6 },
|
||||
{0, '4', POPT_ARG_VAL, &default_af_hint, AF_INET },
|
||||
{0, '6', POPT_ARG_VAL, &default_af_hint, AF_INET6 },
|
||||
#endif
|
||||
{0,0,0,0}
|
||||
};
|
||||
@@ -491,9 +511,8 @@ int parse_arguments(int *argc, const char ***argv, int frommain)
|
||||
keep_partial = 1;
|
||||
break;
|
||||
|
||||
|
||||
case 'f':
|
||||
/* The filename is stored for us by popt */
|
||||
case OPT_READ_BATCH:
|
||||
/* The filename is stored in batch_ext for us by popt */
|
||||
read_batch = 1;
|
||||
break;
|
||||
|
||||
@@ -530,7 +549,8 @@ void server_options(char **args,int *argc)
|
||||
static char mdelete[30];
|
||||
static char mwindow[30];
|
||||
static char bw[50];
|
||||
static char fext[20]; /* dw */
|
||||
static char fext[20];
|
||||
static char wbatch[14];
|
||||
|
||||
int i, x;
|
||||
|
||||
@@ -585,8 +605,6 @@ void server_options(char **args,int *argc)
|
||||
argstr[x++] = 'S';
|
||||
if (do_compression)
|
||||
argstr[x++] = 'z';
|
||||
if (write_batch)
|
||||
argstr[x++] = 'F'; /* dw */
|
||||
|
||||
/* this is a complete hack - blame Rusty
|
||||
|
||||
@@ -609,8 +627,13 @@ void server_options(char **args,int *argc)
|
||||
args[ac++] = mdelete;
|
||||
}
|
||||
|
||||
if (write_batch) {
|
||||
snprintf(wbatch,sizeof(wbatch),"--write-batch");
|
||||
args[ac++] = wbatch;
|
||||
}
|
||||
|
||||
if (batch_ext != NULL) {
|
||||
sprintf(fext,"-f%s",batch_ext);
|
||||
snprintf(fext,sizeof(fext),"--read-batch=%s",batch_ext);
|
||||
args[ac++] = fext;
|
||||
}
|
||||
|
||||
|
||||
84
packaging/lsb/rsync.spec
Normal file
84
packaging/lsb/rsync.spec
Normal file
@@ -0,0 +1,84 @@
|
||||
Summary: Program for efficient remote updates of files.
|
||||
Name: rsync
|
||||
Version: 2.5.1
|
||||
Release: 1
|
||||
Copyright: GPL
|
||||
Group: Applications/Networking
|
||||
Source: ftp://samba.anu.edu.au/pub/rsync/rsync-2.5.1.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 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
|
||||
* 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=/usr/share/man
|
||||
make CFLAGS="$RPM_OPT_FLAGS"
|
||||
strip rsync
|
||||
|
||||
%install
|
||||
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/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) /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
|
||||
@@ -1,10 +1,10 @@
|
||||
Summary: Program for efficient remote updates of files.
|
||||
Name: rsync
|
||||
Version: 2.4.6
|
||||
Version: 2.5.1
|
||||
Release: 1
|
||||
Copyright: GPL
|
||||
Group: Applications/Networking
|
||||
Source: ftp://samba.anu.edu.au/pub/rsync/rsync-2.4.6.tar.gz
|
||||
Source: ftp://samba.anu.edu.au/pub/rsync/rsync-2.5.1.tar.gz
|
||||
URL: http://samba.anu.edu.au/rsync/
|
||||
Packager: Andrew Tridgell <tridge@samba.anu.edu.au>
|
||||
BuildRoot: /tmp/rsync
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
Summary: Program for efficient remote updates of files.
|
||||
Name: rsync
|
||||
Version: 2.4.7pre1
|
||||
Version: 2.5.1
|
||||
Release: 1
|
||||
Copyright: GPL
|
||||
Group: Applications/Networking
|
||||
Source: ftp://samba.anu.edu.au/pub/rsync/rsync-2.4.7pre1.tar.bz2
|
||||
Source: ftp://samba.anu.edu.au/pub/rsync/rsync-2.5.1.tar.gz
|
||||
URL: http://samba.anu.edu.au/rsync/
|
||||
Packager: Andrew Tridgell <tridge@samba.anu.edu.au>
|
||||
BuildRoot: /tmp/rsync
|
||||
|
||||
81
packaging/redhat/7.1/rsync.spec.tmpl
Normal file
81
packaging/redhat/7.1/rsync.spec.tmpl
Normal file
@@ -0,0 +1,81 @@
|
||||
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
|
||||
* 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
|
||||
47
receiver.c
47
receiver.c
@@ -1,6 +1,5 @@
|
||||
/* -*- c-file-style: "linux" -*-
|
||||
|
||||
Copyright (C) 1996-2000 by Andrew Tridgell
|
||||
/*
|
||||
Copyright (C) Andrew Tridgell 1996
|
||||
Copyright (C) Paul Mackerras 1996
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
@@ -83,15 +82,14 @@ 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));
|
||||
rprintf(FERROR,"unlink %s : %s\n",f_name(f),strerror(errno));
|
||||
} else if (verbose) {
|
||||
rprintf(FINFO,"deleting %s\n",f_name(f));
|
||||
}
|
||||
} 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));
|
||||
rprintf(FERROR,"rmdir %s : %s\n",f_name(f),strerror(errno));
|
||||
} else if (verbose) {
|
||||
rprintf(FINFO,"deleting directory %s\n",f_name(f));
|
||||
}
|
||||
@@ -179,7 +177,7 @@ static int get_tmpname(char *fnametmp, char *fname)
|
||||
rprintf(FERROR,"filename too long\n");
|
||||
return 0;
|
||||
}
|
||||
snprintf(fnametmp,MAXPATHLEN, "%s/.%s.XXXXXX",tmpdir,f);
|
||||
slprintf(fnametmp,MAXPATHLEN, "%s/.%s.XXXXXX",tmpdir,f);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -192,11 +190,11 @@ static int get_tmpname(char *fnametmp, char *fname)
|
||||
|
||||
if (f) {
|
||||
*f = 0;
|
||||
snprintf(fnametmp,MAXPATHLEN,"%s/.%s.XXXXXX",
|
||||
slprintf(fnametmp,MAXPATHLEN,"%s/.%s.XXXXXX",
|
||||
fname,f+1);
|
||||
*f = '/';
|
||||
} else {
|
||||
snprintf(fnametmp,MAXPATHLEN,".%s.XXXXXX",fname);
|
||||
slprintf(fnametmp,MAXPATHLEN,".%s.XXXXXX",fname);
|
||||
}
|
||||
|
||||
return 1;
|
||||
@@ -206,7 +204,8 @@ static int get_tmpname(char *fnametmp, char *fname)
|
||||
static int receive_data(int f_in,struct map_struct *buf,int fd,char *fname,
|
||||
OFF_T total_size)
|
||||
{
|
||||
int i,n,remainder,len,count;
|
||||
int i;
|
||||
unsigned int n,remainder,len,count;
|
||||
OFF_T offset = 0;
|
||||
OFF_T offset2;
|
||||
char *data;
|
||||
@@ -304,7 +303,6 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
|
||||
int fd1,fd2;
|
||||
STRUCT_STAT st;
|
||||
char *fname;
|
||||
char template[MAXPATHLEN];
|
||||
char fnametmp[MAXPATHLEN];
|
||||
char *fnamecmp;
|
||||
char fnamecmpbuf[MAXPATHLEN];
|
||||
@@ -372,7 +370,7 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
|
||||
|
||||
if ((fd1 == -1) && (compare_dest != NULL)) {
|
||||
/* try the file at compare_dest instead */
|
||||
snprintf(fnamecmpbuf,MAXPATHLEN,"%s/%s",
|
||||
slprintf(fnamecmpbuf,MAXPATHLEN,"%s/%s",
|
||||
compare_dest,fname);
|
||||
fnamecmp = fnamecmpbuf;
|
||||
fd1 = do_open(fnamecmp, O_RDONLY, 0);
|
||||
@@ -413,7 +411,17 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
|
||||
continue;
|
||||
}
|
||||
|
||||
strlcpy(template, fnametmp, sizeof(template));
|
||||
/* mktemp is deliberately used here instead of mkstemp.
|
||||
because O_EXCL is used on the open, the race condition
|
||||
is not a problem or a security hole, and we want to
|
||||
control the access permissions on the created file. */
|
||||
if (NULL == do_mktemp(fnametmp)) {
|
||||
rprintf(FERROR,"mktemp %s failed\n",fnametmp);
|
||||
receive_data(f_in,buf,-1,NULL,file->length);
|
||||
if (buf) unmap_file(buf);
|
||||
if (fd1 != -1) close(fd1);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* we initially set the perms without the
|
||||
setuid/setgid bits to ensure that there is no race
|
||||
@@ -421,21 +429,16 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
|
||||
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);
|
||||
if (fd2 == -1) {
|
||||
rprintf(FERROR,"mkstemp %s failed\n",fnametmp);
|
||||
receive_data(f_in,buf,-1,NULL,file->length);
|
||||
if (buf) unmap_file(buf);
|
||||
continue;
|
||||
}
|
||||
fd2 = do_open(fnametmp,O_WRONLY|O_CREAT|O_EXCL,
|
||||
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 &&
|
||||
create_directory_path(fnametmp) == 0) {
|
||||
strlcpy(fnametmp, template, sizeof(fnametmp));
|
||||
fd2 = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS);
|
||||
fd2 = do_open(fnametmp,O_WRONLY|O_CREAT|O_EXCL,
|
||||
file->mode & INITACCESSPERMS);
|
||||
}
|
||||
if (fd2 == -1) {
|
||||
rprintf(FERROR,"cannot create %s : %s\n",fnametmp,strerror(errno));
|
||||
|
||||
1
rsync.c
1
rsync.c
@@ -226,7 +226,6 @@ int set_perms(char *fname,struct file_struct *file,STRUCT_STAT *st,
|
||||
|
||||
void sig_int(void)
|
||||
{
|
||||
rprintf(FINFO,"\nrsync.c:sig_int() called.\n");
|
||||
exit_cleanup(RERR_SIGNAL);
|
||||
}
|
||||
|
||||
|
||||
94
rsync.h
94
rsync.h
@@ -1,7 +1,6 @@
|
||||
/*
|
||||
Copyright (C) by Andrew Tridgell 1996, 2000
|
||||
Copyright (C) Andrew Tridgell 1996
|
||||
Copyright (C) Paul Mackerras 1996
|
||||
Copyright (C) 2001 by Martin Pool <mbp@samba.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -18,7 +17,6 @@
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
|
||||
#define False 0
|
||||
#define True 1
|
||||
|
||||
@@ -49,18 +47,7 @@
|
||||
#define SAME_TIME (1<<7)
|
||||
|
||||
/* update this if you make incompatible changes */
|
||||
#define PROTOCOL_VERSION 25
|
||||
|
||||
/* 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.
|
||||
*
|
||||
* 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 PROTOCOL_VERSION 24
|
||||
#define MIN_PROTOCOL_VERSION 15
|
||||
#define MAX_PROTOCOL_VERSION 30
|
||||
|
||||
@@ -76,10 +63,7 @@
|
||||
|
||||
#define MPLEX_BASE 7
|
||||
|
||||
/* 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 };
|
||||
enum logcode {FNONE=0, FERROR=1, FINFO=2, FLOG=3};
|
||||
|
||||
#include "errcode.h"
|
||||
|
||||
@@ -93,6 +77,12 @@ enum logcode {FNONE=0, FERROR=1, FINFO=2, FLOG=3 };
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef HAVE_GETOPT_LONG
|
||||
#include <getopt.h>
|
||||
#else
|
||||
#include "lib/getopt.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
@@ -268,11 +258,9 @@ enum logcode {FNONE=0, FERROR=1, FINFO=2, FLOG=3 };
|
||||
#endif
|
||||
|
||||
#if HAVE_SHORT_INO_T
|
||||
# define INO_T uint32
|
||||
#elif HAVE_INO_T
|
||||
# define INO_T ino_t
|
||||
#define INO_T uint32
|
||||
#else
|
||||
# define INO_T unsigned
|
||||
#define INO_T ino_t
|
||||
#endif
|
||||
|
||||
#ifndef MIN
|
||||
@@ -343,9 +331,9 @@ struct sum_buf {
|
||||
|
||||
struct sum_struct {
|
||||
OFF_T flength; /* total file length */
|
||||
int count; /* how many chunks */
|
||||
int remainder; /* flength % block_length */
|
||||
int n; /* block_length */
|
||||
size_t count; /* how many chunks */
|
||||
size_t remainder; /* flength % block_length */
|
||||
size_t n; /* block_length */
|
||||
struct sum_buf *sums; /* points to info for each chunk */
|
||||
};
|
||||
|
||||
@@ -356,6 +344,7 @@ struct map_struct {
|
||||
};
|
||||
|
||||
struct exclude_struct {
|
||||
char *orig;
|
||||
char *pattern;
|
||||
int regular_exp;
|
||||
int fnmatch_flags;
|
||||
@@ -387,27 +376,9 @@ static inline int flist_up(struct file_list *flist, int i)
|
||||
}
|
||||
|
||||
#include "byteorder.h"
|
||||
#include "version.h"
|
||||
#include "proto.h"
|
||||
#include "lib/mdfour.h"
|
||||
#include "lib/permstring.h"
|
||||
|
||||
/* We have replacement versions of these if they're missing. */
|
||||
#ifndef HAVE_ASPRINTF
|
||||
int asprintf(char **ptr, const char *format, ...);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_VASPRINTF
|
||||
int vasprintf(char **ptr, const char *format, va_list ap);
|
||||
#endif
|
||||
|
||||
#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)
|
||||
int snprintf(char *str,size_t count,const char *fmt,...);
|
||||
#endif
|
||||
|
||||
|
||||
#if !HAVE_STRERROR
|
||||
extern char *sys_errlist[];
|
||||
@@ -505,13 +476,6 @@ extern int errno;
|
||||
# define NONBLOCK_FLAG FNDELAY
|
||||
#endif
|
||||
|
||||
#ifndef INADDR_LOOPBACK
|
||||
#define INADDR_LOOPBACK 0x7f000001
|
||||
#endif
|
||||
|
||||
#ifndef INADDR_NONE
|
||||
#define INADDR_NONE 0xffffffff
|
||||
#endif
|
||||
|
||||
#define IS_DEVICE(mode) (S_ISCHR(mode) || S_ISBLK(mode) || S_ISSOCK(mode) || S_ISFIFO(mode))
|
||||
|
||||
@@ -533,14 +497,6 @@ extern int errno;
|
||||
#endif
|
||||
;
|
||||
|
||||
/* This is just like rprintf, but it also tries to print some
|
||||
* representation of the error code. Normally errcode = errno. */
|
||||
void rsyserr(enum logcode, int, const char *, ...)
|
||||
#ifdef __GNUC__
|
||||
__attribute__ ((format (printf, 3, 4)))
|
||||
#endif
|
||||
;
|
||||
|
||||
#ifdef REPLACE_INET_NTOA
|
||||
#define inet_ntoa rep_inet_ntoa
|
||||
#endif
|
||||
@@ -559,21 +515,3 @@ size_t strlcat(char *d, const char *s, size_t bufsize);
|
||||
#endif
|
||||
|
||||
#define exit_cleanup(code) _exit_cleanup(code, __FILE__, __LINE__)
|
||||
|
||||
|
||||
extern int verbose;
|
||||
|
||||
extern struct global_opts {
|
||||
/** Network address family. **/
|
||||
int af_hint;
|
||||
} global_opts;
|
||||
|
||||
|
||||
#ifndef HAVE_INET_NTOP
|
||||
const char *
|
||||
inet_ntop(int af, const void *src, char *dst, size_t size);
|
||||
#endif /* !HAVE_INET_NTOP */
|
||||
|
||||
#ifndef HAVE_INET_PTON
|
||||
int isc_net_pton(int af, const char *src, void *dst);
|
||||
#endif
|
||||
|
||||
155
rsync.yo
155
rsync.yo
@@ -1,5 +1,5 @@
|
||||
mailto(rsync-bugs@samba.org)
|
||||
manpage(rsync)(1)(29 May 2001)()()
|
||||
manpage(rsync)(1)(14 Dec 2001)()()
|
||||
manpagename(rsync)(faster, flexible replacement for rcp)
|
||||
manpagesynopsis()
|
||||
|
||||
@@ -19,7 +19,7 @@ manpagedescription()
|
||||
|
||||
rsync is a program that behaves in much the same way that rcp does,
|
||||
but has many more options and uses the rsync remote-update protocol to
|
||||
greatly speedup file transfers when the destination file already
|
||||
greatly speed up file transfers when the destination file already
|
||||
exists.
|
||||
|
||||
The rsync remote-update protocol allows rsync to transfer just the
|
||||
@@ -81,7 +81,7 @@ Once installed you can use rsync to any machine that you can use rsh
|
||||
to. rsync uses rsh for its communications, unless both the source and
|
||||
destination are local.
|
||||
|
||||
You can also specify an alternative to rsh, by either using the -e
|
||||
You can also specify an alternative to rsh, either by using the -e
|
||||
command line option, or by setting the RSYNC_RSH environment variable.
|
||||
|
||||
One common substitute is to use ssh, which offers a high degree of
|
||||
@@ -139,10 +139,10 @@ It is also possible to use rsync without using rsh or ssh as the
|
||||
transport. In this case you will connect to a remote rsync server
|
||||
running on TCP port 873.
|
||||
|
||||
You may establish the connetcion via a web proxy by setting the
|
||||
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 must allow proxying to port
|
||||
873, this must be configured in your proxy servers ruleset.
|
||||
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 rsh or ssh except
|
||||
that:
|
||||
@@ -226,8 +226,8 @@ verb(
|
||||
--backup-dir make backups into this directory
|
||||
--suffix=SUFFIX override backup suffix
|
||||
-u, --update update only (don't overwrite newer files)
|
||||
-l, --links preserve soft links
|
||||
-L, --copy-links treat soft links like regular files
|
||||
-l, --links copy symlinks as 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
|
||||
@@ -267,7 +267,8 @@ verb(
|
||||
--include-from=FILE don't exclude patterns listed in FILE
|
||||
--version print version number
|
||||
--daemon run as a rsync daemon
|
||||
--address bind to the specified address
|
||||
--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 IO for the remote shell
|
||||
@@ -276,8 +277,8 @@ verb(
|
||||
--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
|
||||
-f, --read-batch=FILE read batch file
|
||||
-F, --write-batch write batch file
|
||||
--read-batch=FILE read batch file
|
||||
--write-batch write batch file
|
||||
-h, --help show this help screen
|
||||
|
||||
|
||||
@@ -334,8 +335,13 @@ 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 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 everything.
|
||||
dit(bf(-a, --archive)) This is equivalent to -rlptgoD. It is a quick
|
||||
way of saying you want recursion and want to preserve almost
|
||||
everything.
|
||||
|
||||
Note however that bf(-a) bf(does not preserve hardlinks), because
|
||||
finding multiply-linked files is expensive. You must separately
|
||||
specify bf(-H).
|
||||
|
||||
dit(bf(-r, --recursive)) This tells rsync to copy directories
|
||||
recursively. If you don't specify this then rsync won't copy
|
||||
@@ -372,17 +378,16 @@ 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.
|
||||
|
||||
dit(bf(-l, --links)) This tells rsync to recreate symbolic links on the
|
||||
remote system to be the same as the local system. Without this
|
||||
option, all symbolic links are skipped.
|
||||
dit(bf(-l, --links)) When symlinks are encountered, recreate the
|
||||
symlink on the destination.
|
||||
|
||||
dit(bf(-L, --copy-links)) This tells rsync to treat symbolic links just
|
||||
like ordinary files.
|
||||
dit(bf(-L, --copy-links)) When symlinks are encountered, the file that
|
||||
they point to is copied, rather than the symlink.
|
||||
|
||||
dit(bf(--copy-unsafe-links)) This tells rsync to treat symbolic links that
|
||||
point outside the source tree like ordinary files. Absolute symlinks are
|
||||
also treated like ordinary files, and so are any symlinks in the source
|
||||
path itself when --relative is used.
|
||||
dit(bf(--copy-unsafe-links)) This tells rsync to copy the referent of
|
||||
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 destination tree. All absolute symlinks are
|
||||
@@ -408,16 +413,15 @@ the source and target are on the local machine.
|
||||
dit(bf(-p, --perms)) This option causes rsync to update the remote
|
||||
permissions to be the same as the local permissions.
|
||||
|
||||
dit(bf(-o, --owner)) This option causes rsync to update the remote owner
|
||||
of the file to be the same as the local owner. This is only available
|
||||
to the super-user. Note that if the source system is a daemon using chroot,
|
||||
the --numeric-ids option is implied because the source system cannot get
|
||||
access to the usernames.
|
||||
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.
|
||||
|
||||
dit(bf(-g, --group)) This option causes rsync to update the remote group
|
||||
of the file to be the same as the local group. If the receving system is
|
||||
not running as the super-user, only groups that the receiver is a member of
|
||||
will be preserved (by group name, not group id number).
|
||||
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 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
|
||||
@@ -488,7 +492,7 @@ contains a directory of the same name.
|
||||
Since this option was added, deletions were reordered to be done depth-first
|
||||
so it is hardly ever needed anymore except in very obscure cases.
|
||||
|
||||
dit(bf(-B , --block_size=BLOCKSIZE)) This controls the block size used in
|
||||
dit(bf(-B , --block-size=BLOCKSIZE)) This controls the block size used in
|
||||
the rsync algorithm. See the technical report for details.
|
||||
|
||||
dit(bf(-e, --rsh=COMMAND)) This option allows you to choose an alternative
|
||||
@@ -545,8 +549,9 @@ quote(RCS SCCS CVS CVS.adm RCSLOG cvslog.* tags TAGS .make.state
|
||||
then files listed in a $HOME/.cvsignore are added to the list and any
|
||||
files listed in the CVSIGNORE environment variable (space delimited).
|
||||
|
||||
Finally in each directory any files listed in the .cvsignore file in
|
||||
that directory are added to the list.
|
||||
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.
|
||||
|
||||
dit(bf(--csum-length=LENGTH)) By default the primary checksum used in
|
||||
rsync is a very strong 16 byte MD4 checksum. In most cases you will
|
||||
@@ -603,21 +608,33 @@ 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 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.
|
||||
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 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.
|
||||
|
||||
dit(bf(--daemon)) This tells rsync that it is to run as a rsync
|
||||
daemon. If standard input is a socket then rsync will assume that it
|
||||
is being run via inetd, otherwise it will detach from the current
|
||||
terminal and become a background daemon. The daemon will read the
|
||||
config file (/etc/rsyncd.conf) on each connect made by a client and
|
||||
respond to requests accordingly. See the rsyncd.conf(5) man page for more
|
||||
details.
|
||||
dit(bf(--daemon)) This tells rsync that it is to run as a daemon. The
|
||||
daemon may be accessed using the bf(host::module) or
|
||||
bf(rsync://host/module/) syntax.
|
||||
|
||||
If standard input is a socket then rsync will assume that it is being
|
||||
run via inetd, otherwise it will detach from the current terminal and
|
||||
become a background daemon. The daemon will read the config file
|
||||
(/etc/rsyncd.conf) on each connect made by a client and respond to
|
||||
requests accordingly. See the rsyncd.conf(5) man page for more
|
||||
details.
|
||||
|
||||
dit(bf(--no-detach)) When running as a daemon, this option instructs
|
||||
rsync to not detach itself and become a background process. This
|
||||
option is required when running as a service on Cygwin, and may also
|
||||
be useful when rsync is supervised by a program such as
|
||||
bf(daemontools) or AIX's bf(System Resource Controller).
|
||||
bf(--no-detach) is also recommended when rsync is run under a
|
||||
debugger. This option has no effect if rsync is run from inetd or
|
||||
sshd.
|
||||
|
||||
dit(bf(--address)) By default rsync will bind to the wildcard address
|
||||
when run as a daemon with the --daemon option or when connecting to a
|
||||
@@ -691,7 +708,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 a ordered list of include/exclude options as specified on
|
||||
rsync builds an ordered list of include/exclude options as specified on
|
||||
the command line. When a filename is encountered, rsync checks the
|
||||
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
|
||||
@@ -744,7 +761,7 @@ itemize(
|
||||
part of an include option. The "- " part is discarded before matching.
|
||||
|
||||
it() if the pattern is a single exclamation mark ! then the current
|
||||
exclude list is reset, removing all previous exclude patterns.
|
||||
include/exclude list is reset, removing all previously defined patterns.
|
||||
)
|
||||
|
||||
The +/- rules are most useful in exclude lists, allowing you to have a
|
||||
@@ -776,12 +793,15 @@ itemize(
|
||||
|
||||
manpagesection(BATCH MODE)
|
||||
|
||||
bf(Note:) Batch mode should be considered experimental in this version
|
||||
of rsync. The interface or behaviour may change before it stabilizes.
|
||||
|
||||
The following call generates 4 files that encapsulate the information
|
||||
for synchronizing the contents of bf(target_dir) with the updates found in
|
||||
bf(src_dir)
|
||||
|
||||
quote(
|
||||
$ rsync -F [other rsync options here] \nl()
|
||||
$ rsync --write-batch [other rsync options here] \nl()
|
||||
/somewhere/src_dir /somewhere/target_dir
|
||||
)
|
||||
|
||||
@@ -797,6 +817,29 @@ it() bf(rsync_delta.<timestamp>) data blocks for file update & change
|
||||
See bf(http://www.ils.unc.edu/i2dsi/unc_rsync+.html) for papers and technical
|
||||
reports.
|
||||
|
||||
manpagesection(SYMBOLIC LINKS)
|
||||
|
||||
Three basic behaviours are possible when rsync encounters a symbolic
|
||||
link in the source directory.
|
||||
|
||||
By default, symbolic links are not transferred at all. A message
|
||||
"skipping non-regular" file is emitted for any symlinks that exist.
|
||||
|
||||
If bf(--links) is specified, then symlinks are recreated with the same
|
||||
target on the destination. Note that bf(--archive) implies
|
||||
bf(--links).
|
||||
|
||||
If bf(--copy-links) is specified, then symlinks are "collapsed" by
|
||||
copying their referent, rather than the symlink.
|
||||
|
||||
rsync also distinguishes "safe" and "unsafe" symbolic links. An
|
||||
example where this might be used is a web site mirror that wishes
|
||||
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 ommitted altogether.
|
||||
|
||||
manpagesection(DIAGNOSTICS)
|
||||
|
||||
rsync occasionally produces error messages that may seem a little
|
||||
@@ -922,16 +965,22 @@ Jean-loup Gailly and Mark Adler.
|
||||
manpagesection(THANKS)
|
||||
|
||||
Thanks to Richard Brent, Brendan Mackay, Bill Waite, Stephen Rothwell
|
||||
and David Bell for helpful suggestions and testing of rsync. I've
|
||||
probably missed some people, my apologies if I have.
|
||||
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.
|
||||
|
||||
|
||||
manpageauthor()
|
||||
|
||||
rsync was written by Andrew Tridgell and Paul Mackerras. They may be
|
||||
contacted via email at tridge@samba.org and
|
||||
Paul.Mackerras@cs.anu.edu.au
|
||||
rsync was written by Andrew Tridgell <tridge@samba.org> and Paul
|
||||
Mackerras.
|
||||
|
||||
rsync is now also maintained by Martin Pool <mbp@samba.org>
|
||||
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.
|
||||
|
||||
79
runtests.sh
79
runtests.sh
@@ -1,6 +1,6 @@
|
||||
#! /bin/sh
|
||||
|
||||
# Copyright (C) 2001 by Martin Pool <mbp@samba.org>
|
||||
# Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version
|
||||
@@ -160,16 +160,27 @@ missing=0
|
||||
passed=0
|
||||
failed=0
|
||||
|
||||
scratchdir=./testtmp
|
||||
[ -d "$scratchdir" ] && rm -r "$scratchdir"
|
||||
mkdir "$scratchdir"
|
||||
scratchdir=`cd $scratchdir && pwd`
|
||||
echo " scratchdir=$scratchdir"
|
||||
# Prefix for scratch directory. We create separate directories for
|
||||
# each test case, so that they can be left behind in case of failure
|
||||
# to aid investigation.
|
||||
scratchbase="`pwd`"/testtmp
|
||||
echo " scratchbase=$scratchbase"
|
||||
|
||||
suitedir="$srcdir/testsuite"
|
||||
|
||||
export scratchdir suitedir
|
||||
|
||||
prep_scratch() {
|
||||
[ -d "$scratchdir" ] && rm -rf "$scratchdir"
|
||||
mkdir "$scratchdir"
|
||||
return 0
|
||||
}
|
||||
|
||||
discard_scratch() {
|
||||
[ -d "$scratchdir" ] && rm -rf "$scratchdir"
|
||||
return 0
|
||||
}
|
||||
|
||||
if [ "x$whichtests" = x ]
|
||||
then
|
||||
whichtests="*.test"
|
||||
@@ -177,29 +188,45 @@ fi
|
||||
|
||||
for testscript in $suitedir/$whichtests
|
||||
do
|
||||
testbase=`echo $testscript | sed 's!.*/!!'`
|
||||
testbase=`echo $testscript | sed 's!.*/!!' | sed -e 's/.test\$//'`
|
||||
scratchdir="$scratchbase.$testbase"
|
||||
|
||||
echo "----- $testbase starting"
|
||||
prep_scratch
|
||||
|
||||
if sh $RUNSHFLAGS "$testscript"
|
||||
then
|
||||
echo "----- $testbase completed succesfully"
|
||||
set +e
|
||||
sh $RUNSHFLAGS "$testscript" >"$scratchdir/test.log" 2>&1
|
||||
result=$?
|
||||
set -e
|
||||
|
||||
case $result in
|
||||
0)
|
||||
echo "PASS $testbase"
|
||||
passed=`expr $passed + 1`
|
||||
else
|
||||
case $? in
|
||||
77)
|
||||
echo "----- $testbase skipped"
|
||||
skipped=`expr $skipped + 1`
|
||||
;;
|
||||
*)
|
||||
echo "----- $testbase failed!"
|
||||
failed=`expr $failed + 1`
|
||||
if [ "x$nopersist" = "xyes" ]
|
||||
then
|
||||
exit 1
|
||||
fi
|
||||
esac
|
||||
fi
|
||||
discard_scratch
|
||||
;;
|
||||
77)
|
||||
echo "SKIP $testbase"
|
||||
skipped=`expr $skipped + 1`
|
||||
discard_scratch
|
||||
;;
|
||||
78)
|
||||
# It failed, but we expected that. don't dump out error logs,
|
||||
# because most users won't want to see them. But do leave
|
||||
# the working directory around.
|
||||
echo "XFAIL $testbase"
|
||||
failed=`expr $failed + 1`
|
||||
;;
|
||||
*)
|
||||
echo "FAIL $testbase"
|
||||
echo "----- $testbase failed: log follows"
|
||||
cat "$scratchdir/test.log"
|
||||
echo "----- $testbase log ends"
|
||||
failed=`expr $failed + 1`
|
||||
if [ "x$nopersist" = "xyes" ]
|
||||
then
|
||||
exit 1
|
||||
fi
|
||||
esac
|
||||
done
|
||||
|
||||
echo '------------------------------------------------------------'
|
||||
|
||||
5
sender.c
5
sender.c
@@ -159,13 +159,14 @@ void send_files(struct file_list *flist,int f_out,int f_in)
|
||||
initial_stats = stats;
|
||||
|
||||
s = receive_sums(f_in);
|
||||
if (write_batch) /* dw */
|
||||
write_batch_csum_info(&i,flist->count,s);
|
||||
if (!s) {
|
||||
io_error = 1;
|
||||
rprintf(FERROR,"receive_sums failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (write_batch)
|
||||
write_batch_csum_info(&i,flist->count,s);
|
||||
|
||||
if (!read_batch) {
|
||||
fd = do_open(fname, O_RDONLY, 0);
|
||||
|
||||
355
socket.c
355
socket.c
@@ -1,7 +1,9 @@
|
||||
/* -*- c-file-style: "linux" -*-
|
||||
|
||||
rsync -- fast file replication program
|
||||
|
||||
Copyright (C) 1992-2001 by Andrew Tridgell <tridge@samba.org>
|
||||
Copyright (C) 2001 by Martin Pool <mbp@samba.org>
|
||||
Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -22,13 +24,17 @@
|
||||
* @file socket.c
|
||||
*
|
||||
* Socket functions used in rsync.
|
||||
*
|
||||
* This file is now converted to use the new-style getaddrinfo()
|
||||
* interface, which supports IPv6 but is also supported on recent
|
||||
* IPv4-only machines. On systems that don't have that interface, we
|
||||
* emulate it using the KAME implementation.
|
||||
**/
|
||||
|
||||
#include "rsync.h"
|
||||
|
||||
#ifndef HAVE_GETADDRINFO
|
||||
#include "lib/addrinfo.h"
|
||||
#endif
|
||||
static const char default_name[] = "UNKNOWN";
|
||||
|
||||
|
||||
/* Establish a proxy connection on an open socket to a web roxy by
|
||||
* using the CONNECT method. */
|
||||
@@ -38,7 +44,7 @@ static int establish_proxy_connection(int fd, char *host, int port)
|
||||
char *cp;
|
||||
|
||||
snprintf(buffer, sizeof(buffer), "CONNECT %s:%d HTTP/1.0\r\n\r\n", host, port);
|
||||
if (write(fd, buffer, strlen(buffer)) != strlen(buffer)) {
|
||||
if (write(fd, buffer, strlen(buffer)) != (int) strlen(buffer)) {
|
||||
rprintf(FERROR, "failed to write to proxy: %s\n",
|
||||
strerror(errno));
|
||||
return -1;
|
||||
@@ -94,6 +100,39 @@ 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,
|
||||
const char *bind_address)
|
||||
{
|
||||
int error;
|
||||
struct addrinfo bhints, *bres_all, *r;
|
||||
|
||||
memset(&bhints, 0, sizeof(bhints));
|
||||
bhints.ai_family = ai_family;
|
||||
bhints.ai_socktype = ai_socktype;
|
||||
bhints.ai_flags = AI_PASSIVE;
|
||||
if ((error = getaddrinfo(bind_address, NULL, &bhints, &bres_all))) {
|
||||
rprintf(FERROR, RSYNC_NAME ": getaddrinfo %s: %s\n",
|
||||
bind_address, gai_strerror(error));
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (r = bres_all; r; r = r->ai_next) {
|
||||
if (bind(s, r->ai_addr, r->ai_addrlen) == -1)
|
||||
continue;
|
||||
return s;
|
||||
}
|
||||
|
||||
/* no error message; there might be some problem that allows
|
||||
* creation of the socket but not binding, perhaps if the
|
||||
* machine has no ipv6 address of this name. */
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Open a socket to a tcp remote host with the specified port .
|
||||
@@ -121,7 +160,6 @@ int open_socket_out(char *host, int port, const char *bind_address,
|
||||
int type = SOCK_STREAM;
|
||||
int error;
|
||||
int s;
|
||||
int result;
|
||||
struct addrinfo hints, *res0, *res;
|
||||
char portbuf[10];
|
||||
char *h;
|
||||
@@ -162,32 +200,22 @@ int open_socket_out(char *host, int port, const char *bind_address,
|
||||
}
|
||||
|
||||
s = -1;
|
||||
/* Try to connect to all addresses for this machine until we get
|
||||
* through. It might e.g. be multi-homed, or have both IPv4 and IPv6
|
||||
* addresses. We need to create a socket for each record, since the
|
||||
* address record tells us what protocol to use to try to connect. */
|
||||
for (res = res0; res; res = res->ai_next) {
|
||||
s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
|
||||
if (s < 0)
|
||||
continue;
|
||||
|
||||
if (bind_address) {
|
||||
struct addrinfo bhints, *bres;
|
||||
|
||||
memset(&bhints, 0, sizeof(bhints));
|
||||
bhints.ai_family = res->ai_family;
|
||||
bhints.ai_socktype = type;
|
||||
bhints.ai_flags = AI_PASSIVE;
|
||||
error = getaddrinfo(bind_address, NULL, &bhints, &bres);
|
||||
if (error) {
|
||||
rprintf(FERROR, RSYNC_NAME ": getaddrinfo: bind address %s <noport>: %s\n",
|
||||
bind_address, gai_strerror(error));
|
||||
if (bind_address)
|
||||
if (try_bind_local(s, res->ai_family, type,
|
||||
bind_address) == -1) {
|
||||
close(s);
|
||||
s = -1;
|
||||
continue;
|
||||
}
|
||||
if (bres->ai_next) {
|
||||
rprintf(FERROR, RSYNC_NAME ": getaddrinfo: bind address %s resolved to multiple hosts\n",
|
||||
bind_address);
|
||||
freeaddrinfo(bres);
|
||||
continue;
|
||||
}
|
||||
bind(s, bres->ai_addr, bres->ai_addrlen);
|
||||
}
|
||||
|
||||
if (connect(s, res->ai_addr, res->ai_addrlen) < 0) {
|
||||
close(s);
|
||||
@@ -263,7 +291,7 @@ static int open_socket_in(int type, int port, const char *bind_address,
|
||||
{
|
||||
int one=1;
|
||||
int s;
|
||||
struct addrinfo hints, *res, *resp;
|
||||
struct addrinfo hints, *all_ai, *resp;
|
||||
char portbuf[10];
|
||||
int error;
|
||||
|
||||
@@ -272,53 +300,43 @@ static int open_socket_in(int type, int port, const char *bind_address,
|
||||
hints.ai_socktype = type;
|
||||
hints.ai_flags = AI_PASSIVE;
|
||||
snprintf(portbuf, sizeof(portbuf), "%d", port);
|
||||
error = getaddrinfo(bind_address, portbuf, &hints, &res);
|
||||
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 -1;
|
||||
}
|
||||
/* XXX: Do we need to care about getting multiple results
|
||||
* back? I think probably not; if the user passed
|
||||
* bind_address == NULL and we set AI_PASSIVE then we ought to
|
||||
* get a wildcard result. */
|
||||
|
||||
resp = res;
|
||||
while (1) {
|
||||
s = socket(resp->ai_family, resp->ai_socktype, resp->ai_protocol);
|
||||
/* We may not be able to create the socket, if for example the
|
||||
* machine knows about IPv6 in the C library, but not in the
|
||||
* kernel. */
|
||||
for (resp = all_ai; resp; resp = resp->ai_next) {
|
||||
s = socket(resp->ai_family, resp->ai_socktype,
|
||||
resp->ai_protocol);
|
||||
|
||||
if (s >= 0) {
|
||||
break; /* got a socket */
|
||||
} else if ((resp = resp->ai_next)) {
|
||||
switch (errno) {
|
||||
case EPROTONOSUPPORT:
|
||||
case EAFNOSUPPORT:
|
||||
case EPFNOSUPPORT:
|
||||
/* See if there's another address that will work... */
|
||||
continue;
|
||||
}
|
||||
if (s == -1)
|
||||
/* See if there's another address that will work... */
|
||||
continue;
|
||||
|
||||
setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
|
||||
(char *)&one, sizeof one);
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
rprintf(FERROR, RSYNC_NAME ": open inbound socket"
|
||||
"(dom=%d, type=%d, proto=%d) failed: %s\n",
|
||||
resp->ai_family, resp->ai_socktype, resp->ai_protocol,
|
||||
strerror(errno));
|
||||
goto fail;
|
||||
return s;
|
||||
}
|
||||
|
||||
setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one));
|
||||
rprintf(FERROR, RSYNC_NAME ": open inbound socket on port %d failed: "
|
||||
"%s\n",
|
||||
port,
|
||||
strerror(errno));
|
||||
|
||||
/* now we've got a socket - we need to bind it */
|
||||
if (bind(s, res->ai_addr, res->ai_addrlen) < 0) {
|
||||
rprintf(FERROR, RSYNC_NAME ": bind failed on port %d\n", port);
|
||||
close(s);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return s;
|
||||
|
||||
fail:
|
||||
freeaddrinfo(res);
|
||||
freeaddrinfo(all_ai);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -353,10 +371,10 @@ void start_accept_loop(int port, int (*fn)(int ))
|
||||
{
|
||||
int s;
|
||||
extern char *bind_address;
|
||||
extern int default_af_hint;
|
||||
|
||||
/* open an incoming socket */
|
||||
s = open_socket_in(SOCK_STREAM, port, bind_address,
|
||||
global_opts.af_hint);
|
||||
s = open_socket_in(SOCK_STREAM, port, bind_address, default_af_hint);
|
||||
if (s == -1)
|
||||
exit_cleanup(RERR_SOCKETIO);
|
||||
|
||||
@@ -372,8 +390,8 @@ void start_accept_loop(int port, int (*fn)(int ))
|
||||
while (1) {
|
||||
fd_set fds;
|
||||
int fd;
|
||||
struct sockaddr addr;
|
||||
int in_addrlen = sizeof(addr);
|
||||
struct sockaddr_storage addr;
|
||||
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
|
||||
@@ -389,7 +407,7 @@ void start_accept_loop(int port, int (*fn)(int ))
|
||||
|
||||
if(!FD_ISSET(s, &fds)) continue;
|
||||
|
||||
fd = accept(s,(struct sockaddr *)&addr,&in_addrlen);
|
||||
fd = accept(s,(struct sockaddr *)&addr,&addrlen);
|
||||
|
||||
if (fd == -1) continue;
|
||||
|
||||
@@ -555,8 +573,8 @@ void become_daemon(void)
|
||||
**/
|
||||
char *client_addr(int fd)
|
||||
{
|
||||
struct sockaddr ss;
|
||||
int length = sizeof(ss);
|
||||
struct sockaddr_storage ss;
|
||||
socklen_t length = sizeof ss;
|
||||
static char addr_buf[100];
|
||||
static int initialised;
|
||||
|
||||
@@ -564,37 +582,62 @@ char *client_addr(int fd)
|
||||
|
||||
initialised = 1;
|
||||
|
||||
if (getpeername(fd, &ss, &length)) {
|
||||
exit_cleanup(RERR_SOCKETIO);
|
||||
}
|
||||
client_sockaddr(fd, &ss, &length);
|
||||
|
||||
getnameinfo(&ss, length,
|
||||
addr_buf, sizeof(addr_buf), NULL, 0, NI_NUMERICHOST);
|
||||
getnameinfo((struct sockaddr *)&ss, length,
|
||||
addr_buf, sizeof(addr_buf), NULL, 0, NI_NUMERICHOST);
|
||||
|
||||
return addr_buf;
|
||||
}
|
||||
|
||||
|
||||
static int get_sockaddr_family(const struct sockaddr_storage *ss)
|
||||
{
|
||||
return ((struct sockaddr *) ss)->sa_family;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the DNS name of the client
|
||||
* Return the DNS name of the client.
|
||||
*
|
||||
* The name is statically cached so that repeated lookups are quick,
|
||||
* so there is a limit of one lookup per customer.
|
||||
*
|
||||
* If anything goes wrong, including the name->addr->name check, then
|
||||
* we just use "UNKNOWN", so you can use that value in hosts allow
|
||||
* lines.
|
||||
**/
|
||||
char *client_name(int fd)
|
||||
{
|
||||
struct sockaddr ss;
|
||||
int length = sizeof(ss);
|
||||
struct sockaddr_storage ss;
|
||||
socklen_t ss_len = sizeof ss;
|
||||
static char name_buf[100];
|
||||
static char port_buf[100];
|
||||
char *def = "UNKNOWN";
|
||||
static int initialised;
|
||||
struct addrinfo hints, *res, *res0;
|
||||
int error;
|
||||
|
||||
if (initialised) return name_buf;
|
||||
|
||||
strcpy(name_buf, default_name);
|
||||
initialised = 1;
|
||||
|
||||
strcpy(name_buf,def);
|
||||
client_sockaddr(fd, &ss, &ss_len);
|
||||
|
||||
if (getpeername(fd, (struct sockaddr *)&ss, &length)) {
|
||||
if (!lookup_name(fd, &ss, ss_len, name_buf, sizeof name_buf, port_buf, sizeof port_buf))
|
||||
check_name(fd, &ss, ss_len, name_buf, port_buf);
|
||||
|
||||
return name_buf;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get the sockaddr for the client.
|
||||
**/
|
||||
void client_sockaddr(int fd,
|
||||
struct sockaddr_storage *ss,
|
||||
socklen_t *ss_len)
|
||||
{
|
||||
if (getpeername(fd, (struct sockaddr *) ss, ss_len)) {
|
||||
/* FIXME: Can we really not continue? */
|
||||
rprintf(FERROR, RSYNC_NAME ": getpeername on fd%d failed: %s\n",
|
||||
fd, strerror(errno));
|
||||
@@ -602,69 +645,141 @@ char *client_name(int fd)
|
||||
}
|
||||
|
||||
#ifdef INET6
|
||||
if (ss.sa_family == AF_INET6 &&
|
||||
IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&ss)->sin6_addr)) {
|
||||
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
|
||||
* "::ffff:10.130.1.2". If we use it as-is, then the
|
||||
* reverse lookup might fail or perhaps something else
|
||||
* bad might happen. So instead we convert it to an
|
||||
* equivalent address in the IPv4 address family. */
|
||||
struct sockaddr_in6 sin6;
|
||||
struct sockaddr_in *sin;
|
||||
|
||||
memcpy(&sin6, &ss, sizeof(sin6));
|
||||
sin = (struct sockaddr_in *)&ss;
|
||||
memcpy(&sin6, ss, sizeof(sin6));
|
||||
sin = (struct sockaddr_in *)ss;
|
||||
memset(sin, 0, sizeof(*sin));
|
||||
sin->sin_family = AF_INET;
|
||||
length = sizeof(struct sockaddr_in);
|
||||
*ss_len = sizeof(struct sockaddr_in);
|
||||
#ifdef HAVE_SOCKADDR_LEN
|
||||
sin->sin_len = length;
|
||||
sin->sin_len = *ss_len;
|
||||
#endif
|
||||
sin->sin_port = sin6.sin6_port;
|
||||
|
||||
/* There is a macro to extract the mapped part
|
||||
* (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));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Look up a name from @p ss into @p name_buf.
|
||||
**/
|
||||
int lookup_name(int fd, const struct sockaddr_storage *ss,
|
||||
socklen_t ss_len,
|
||||
char *name_buf, size_t name_buf_len,
|
||||
char *port_buf, size_t port_buf_len)
|
||||
{
|
||||
int name_err;
|
||||
|
||||
/* reverse lookup */
|
||||
if (getnameinfo((struct sockaddr *)&ss, length,
|
||||
name_buf, sizeof(name_buf), port_buf, sizeof(port_buf),
|
||||
NI_NAMEREQD | NI_NUMERICSERV) != 0) {
|
||||
strcpy(name_buf, def);
|
||||
rprintf(FERROR, "reverse name lookup failed\n");
|
||||
name_err = getnameinfo((struct sockaddr *) ss, ss_len,
|
||||
name_buf, name_buf_len,
|
||||
port_buf, port_buf_len,
|
||||
NI_NAMEREQD | NI_NUMERICSERV);
|
||||
if (name_err != 0) {
|
||||
strcpy(name_buf, default_name);
|
||||
rprintf(FERROR, RSYNC_NAME ": name lookup failed for %s: %s\n",
|
||||
client_addr(fd),
|
||||
gai_strerror(name_err));
|
||||
return name_err;
|
||||
}
|
||||
|
||||
/* forward lookup */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Do a forward lookup on name_buf and make sure it corresponds to ss
|
||||
* -- otherwise we may be being spoofed. If we suspect we are, then
|
||||
* we don't abort the connection but just emit a warning. */
|
||||
int check_name(int fd,
|
||||
const struct sockaddr_storage *ss,
|
||||
socklen_t ss_len,
|
||||
char *name_buf,
|
||||
const char *port_buf)
|
||||
{
|
||||
struct addrinfo hints, *res, *res0;
|
||||
int error;
|
||||
int ss_family = get_sockaddr_family(ss);
|
||||
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = PF_UNSPEC;
|
||||
hints.ai_flags = AI_CANONNAME;
|
||||
hints.ai_flags = ss_family;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
error = getaddrinfo(name_buf, port_buf, &hints, &res0);
|
||||
if (error) {
|
||||
strcpy(name_buf, def);
|
||||
rprintf(FERROR,
|
||||
RSYNC_NAME ": forward name lookup for %s failed: %s\n",
|
||||
port_buf,
|
||||
RSYNC_NAME ": forward name lookup for %s:%s failed: %s\n",
|
||||
name_buf, port_buf,
|
||||
gai_strerror(error));
|
||||
return name_buf;
|
||||
strcpy(name_buf, default_name);
|
||||
return error;
|
||||
}
|
||||
|
||||
/* XXX sin6_flowinfo and other fields */
|
||||
|
||||
/* We expect that one of the results will be the same as ss. */
|
||||
for (res = res0; res; res = res->ai_next) {
|
||||
if (res->ai_family != ss.sa_family)
|
||||
if (res->ai_family != ss_family) {
|
||||
rprintf(FERROR,
|
||||
"check_name: response family %d != %d\n",
|
||||
res->ai_family, ss_family);
|
||||
continue;
|
||||
if (res->ai_addrlen != length)
|
||||
}
|
||||
if (res->ai_addrlen != ss_len) {
|
||||
rprintf(FERROR,
|
||||
"check_name: addrlen %d != %d\n",
|
||||
res->ai_addrlen, ss_len);
|
||||
continue;
|
||||
if (memcmp(res->ai_addr, &ss, res->ai_addrlen) == 0)
|
||||
}
|
||||
if (memcmp(res->ai_addr, ss, res->ai_addrlen) == 0) {
|
||||
rprintf(FERROR,
|
||||
"check_name: %d bytes of address identical\n",
|
||||
res->ai_addrlen);
|
||||
break;
|
||||
} else{
|
||||
rprintf(FERROR,
|
||||
"check_name: %d bytes of address NOT identical\n",
|
||||
res->ai_addrlen);
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: Do a forward lookup as well to prevent spoofing */
|
||||
|
||||
if (!res0) {
|
||||
/* We hit the end of the list without finding an
|
||||
* address that was the same as ss. */
|
||||
rprintf(FERROR, RSYNC_NAME
|
||||
": no known address for \"%s\": "
|
||||
"spoofed address?\n",
|
||||
name_buf);
|
||||
strcpy(name_buf, default_name);
|
||||
}
|
||||
if (res == NULL) {
|
||||
strcpy(name_buf, def);
|
||||
rprintf(FERROR, RSYNC_NAME ": "
|
||||
"reverse name lookup mismatch on fd%d - spoofed address?\n",
|
||||
fd);
|
||||
/* We hit the end of the list without finding an
|
||||
* address that was the same as ss. */
|
||||
rprintf(FERROR, RSYNC_NAME
|
||||
": %s is not a known address for \"%s\": "
|
||||
"spoofed address?\n",
|
||||
client_addr(fd),
|
||||
name_buf);
|
||||
strcpy(name_buf, default_name);
|
||||
}
|
||||
|
||||
freeaddrinfo(res0);
|
||||
return name_buf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -735,16 +850,20 @@ static int socketpair_tcp(int fd[2])
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
run a program on a local tcp socket, this is used to launch smbd
|
||||
when regression testing
|
||||
the return value is a socket which is attached to a subprocess
|
||||
running "prog". stdin and stdout are attached. stderr is left
|
||||
attached to the original stderr
|
||||
******************************************************************/
|
||||
|
||||
/**
|
||||
* Run a program on a local tcp socket, so that we can talk to it's
|
||||
* stdin and stdout. This is used to fake a connection to a daemon
|
||||
* for testing -- not for the normal case of running SSH.
|
||||
*
|
||||
* @return a socket which is attached to a subprocess running
|
||||
* "prog". stdin and stdout are attached. stderr is left attached to
|
||||
* the original stderr
|
||||
**/
|
||||
int sock_exec(const char *prog)
|
||||
{
|
||||
int fd[2];
|
||||
|
||||
if (socketpair_tcp(fd) != 0) {
|
||||
rprintf (FERROR, RSYNC_NAME
|
||||
": socketpair_tcp failed (%s)\n",
|
||||
@@ -757,10 +876,12 @@ int sock_exec(const char *prog)
|
||||
close(1);
|
||||
dup(fd[1]);
|
||||
dup(fd[1]);
|
||||
if (verbose > 3)
|
||||
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]);
|
||||
|
||||
@@ -132,7 +132,7 @@ int do_mkstemp(char *template, mode_t perms)
|
||||
}
|
||||
#else
|
||||
if (!mktemp(template)) return -1;
|
||||
return open(template, O_RDWR|O_EXCL|O_CREAT, perms);
|
||||
return do_open(template, O_RDWR|O_EXCL|O_CREAT, perms);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
57
testsuite/duplicates.test
Normal file
57
testsuite/duplicates.test
Normal file
@@ -0,0 +1,57 @@
|
||||
#! /bin/sh
|
||||
|
||||
# Copyright (C) 2002 by Martin Pool <mbp@samba.org>
|
||||
|
||||
# This program is distributable under the terms of the GNU GPL see
|
||||
# COPYING).
|
||||
|
||||
# Test rsync handling of duplicate filenames.
|
||||
|
||||
# It's quite possible that the user might specify the same source file
|
||||
# more than once on the command line, perhaps through shell variables
|
||||
# or wildcard expansions. It might cause problems for rsync if the
|
||||
# same name occurred more than once in the file list, because we might
|
||||
# be trying to update the first copy and generate checksums for the
|
||||
# second copy at the same time. See clean_flist() for the implementation.
|
||||
|
||||
# We don't need to worry about hardlinks or symlinks. Because we
|
||||
# always rename-and-replace the new copy, they can't affect us.
|
||||
|
||||
# This test is not great, because it is a timing-dependent bug.
|
||||
|
||||
. $srcdir/testsuite/rsync.fns
|
||||
|
||||
echo "SKIP THIS FOR NOW; It's a known bug"
|
||||
exit 77
|
||||
|
||||
set -x
|
||||
|
||||
# Build some hardlinks
|
||||
|
||||
fromdir="$scratchdir/from"
|
||||
todir="$scratchdir/to"
|
||||
|
||||
mkdir "$fromdir"
|
||||
name1="$fromdir/name1"
|
||||
name2="$fromdir/name2"
|
||||
echo "This is the file" > "$name1"
|
||||
ln -s "$name1" "$name2" || fail "can't create symlink"
|
||||
|
||||
outfile="$scratchdir/rsync.out"
|
||||
|
||||
checkit "rsync -avv \"$fromdir/\" \"$fromdir/\" \"$fromdir/\" \"$fromdir/\" \"$fromdir/\" \"$fromdir/\" \"$fromdir/\" \"$fromdir/\" \"$fromdir/\" \"$fromdir/\" \"$todir/\"" "$fromdir" "$todir" \
|
||||
| tee "$outfile"
|
||||
|
||||
# Make sure each file was only copied once...
|
||||
if [ `grep -c '^name1$' "$outfile"` != 1 ]
|
||||
then
|
||||
test_xfail "name1 was not copied exactly once"
|
||||
fi
|
||||
if [ `grep -c '^name2$' "$outfile"` != 1 ]
|
||||
then
|
||||
test_xfail "name2 was not copied exactly once"
|
||||
fi
|
||||
|
||||
exit 0
|
||||
# last [] may have failed but if we get here then we've won
|
||||
|
||||
@@ -26,3 +26,5 @@ cp ${FROM}/text ${TO}/ThisShouldGo
|
||||
runtest " --delete" 'checkit "$RSYNC --delete -avH ${FROM}/ ${TO}" ${FROM}/ ${TO}'
|
||||
|
||||
checkforlogs ${LOG}.?
|
||||
|
||||
hands_cleanup
|
||||
38
testsuite/hardlinks.test
Normal file
38
testsuite/hardlinks.test
Normal file
@@ -0,0 +1,38 @@
|
||||
#! /bin/sh
|
||||
|
||||
# Copyright (C) 2002 by Martin Pool <mbp@samba.org>
|
||||
|
||||
# This program is distributable under the terms of the GNU GPL (see
|
||||
# COPYING).
|
||||
|
||||
# Test rsync handling of hardlinks. By default (in 2.5.1) rsync does
|
||||
# not detect symlinks and they get split into different files. If you
|
||||
# specify -H, then hard links are detected and recreated as hardlinks
|
||||
# on the other end.
|
||||
|
||||
. $srcdir/testsuite/rsync.fns
|
||||
|
||||
set -x
|
||||
|
||||
# Build some hardlinks
|
||||
|
||||
fromdir="$scratchdir/from"
|
||||
todir="$scratchdir/to"
|
||||
|
||||
# TODO: Need to test whether hardlinks are possible on this OS/filesystem
|
||||
|
||||
mkdir "$fromdir"
|
||||
name1="$fromdir/name1"
|
||||
name2="$fromdir/name2"
|
||||
name3="$fromdir/name3"
|
||||
name4="$fromdir/name4"
|
||||
echo "This is the file" > "$name1"
|
||||
ln "$name1" "$name2" || fail "Can't create hardlink"
|
||||
ln "$name2" "$name3" || fail "Can't create hardlink"
|
||||
cp "$name2" "$name4" || fail "Can't copy file"
|
||||
|
||||
checkit "rsync -aHvv \"$fromdir/\" \"$todir/\"" "$fromdir" "$todir"
|
||||
|
||||
exit 0
|
||||
# last [] may have failed but if we get here then we've won
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
. "$suitedir/rsync.fns"
|
||||
|
||||
set -x
|
||||
# set -x
|
||||
|
||||
hands_setup
|
||||
|
||||
|
||||
@@ -53,7 +53,8 @@ hands_setup() {
|
||||
# Clean before creation
|
||||
rm -rf $FROM
|
||||
rm -rf $TO
|
||||
|
||||
|
||||
[ -d $TMP ] || mkdir $TMP
|
||||
[ -d $FROM ] || mkdir $FROM
|
||||
[ -d $TO ] || mkdir $TO
|
||||
|
||||
@@ -72,7 +73,7 @@ hands_setup() {
|
||||
mkdir ${FROM}/emptydir
|
||||
|
||||
# a hundred lines of text or so
|
||||
rsync_ls_lR ${srcdir} > ${FROM}/filelist
|
||||
rsync_ls_lR "${srcdir}" > ${FROM}/filelist
|
||||
|
||||
# This might fail on systems that don't have -n
|
||||
echo $ECHO_N "This file has no trailing lf$ECHO_C" > ${FROM}/nolf
|
||||
@@ -94,6 +95,11 @@ hands_setup() {
|
||||
}
|
||||
|
||||
|
||||
hands_cleanup() {
|
||||
rm -r "$TMP"
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
####################
|
||||
@@ -129,35 +135,31 @@ makepath () {
|
||||
# there are any difference. If there are, explain them.
|
||||
|
||||
checkit() {
|
||||
log=${LOG}
|
||||
failed=
|
||||
# the log accumulates all output; we only display it if there
|
||||
# is a problem.
|
||||
|
||||
echo "Running: \"$1\"" >${log}
|
||||
echo "">>${log}
|
||||
eval "$1" >>${log} 2>&1
|
||||
# We can just write everything to stdout/stderr, because the
|
||||
# wrapper hides it unless there is a problem.
|
||||
|
||||
echo "Running: \"$1\""
|
||||
eval "$1"
|
||||
status=$?
|
||||
if [ $status != 0 ]; then
|
||||
failed="YES";
|
||||
fi
|
||||
|
||||
echo "-------------">>${log}
|
||||
echo "check how the files compare with diff:">>${log}
|
||||
echo "">>${log}
|
||||
diff -cr $2 $3 >>${log} 2>&1 || failed=YES
|
||||
echo "-------------">>${log}
|
||||
echo "check how the directory listings compare with diff:">>${log}
|
||||
echo "">>${log}
|
||||
( cd "$2" && rsync_ls_lR ) > ${TMP}/ls-from 2>>${log}
|
||||
( cd "$3" && rsync_ls_lR ) > ${TMP}/ls-to 2>>${log}
|
||||
diff -c ${TMP}/ls-from ${TMP}/ls-to >>${log} 2>&1 || failed=YES
|
||||
echo "-------------"
|
||||
echo "check how the files compare with diff:"
|
||||
echo ""
|
||||
diff -cr $2 $3 || failed=YES
|
||||
echo "-------------"
|
||||
echo "check how the directory listings compare with diff:"
|
||||
echo ""
|
||||
( cd "$2" && rsync_ls_lR . ) > ${TMP}/ls-from
|
||||
( cd "$3" && rsync_ls_lR . ) > ${TMP}/ls-to
|
||||
diff -c ${TMP}/ls-from ${TMP}/ls-to || failed=YES
|
||||
if [ -z "${failed}" ] ; then
|
||||
rm $log
|
||||
return 0
|
||||
else
|
||||
cat ${log}
|
||||
rm ${log}
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
@@ -204,3 +206,29 @@ EOF
|
||||
}
|
||||
|
||||
|
||||
build_symlinks() {
|
||||
fromdir="$scratchdir/from"
|
||||
todir="$scratchdir/to"
|
||||
mkdir "$fromdir"
|
||||
date >"$fromdir/referent"
|
||||
ln -s referent "$fromdir/relative"
|
||||
ln -s "$fromdir/referent" "$fromdir/absolute"
|
||||
ln -s nonexistent "$fromdir/dangling"
|
||||
ln -s "$srcdir/rsync.c" "$fromdir/unsafe"
|
||||
}
|
||||
|
||||
test_fail() {
|
||||
echo "$@" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
# It failed, but we expected that. don't dump out error logs,
|
||||
# because most users won't want to see them. But do leave
|
||||
# the working directory around.
|
||||
test_xfail() {
|
||||
echo "$@" >&2
|
||||
exit 78
|
||||
}
|
||||
|
||||
# be reproducible
|
||||
umask 077
|
||||
29
testsuite/symlink-ignore.test
Normal file
29
testsuite/symlink-ignore.test
Normal file
@@ -0,0 +1,29 @@
|
||||
#! /bin/sh
|
||||
|
||||
# Copyright (C) 2001 by Martin Pool <mbp@samba.org>
|
||||
|
||||
# This program is distributable under the terms of the GNU GPL (see
|
||||
# COPYING).
|
||||
|
||||
# Test rsync's somewhat over-featured symlink control: the default
|
||||
# behaviour is that symlinks should not be copied at all.
|
||||
|
||||
. $srcdir/testsuite/rsync.fns
|
||||
|
||||
set -x
|
||||
|
||||
build_symlinks || test_fail "failed to build symlinks"
|
||||
|
||||
# Copy recursively, but without -l or -L or -a, and all the symlinks
|
||||
# should be missing.
|
||||
"$rsync_bin" -r "$fromdir/" "$todir" || test_fail "rsync returned $?"
|
||||
|
||||
[ -f "${todir}/referent" ] || test_fail "referent was not copied"
|
||||
[ -d "${todir}/from" ] && test_fail "extra level of directories"
|
||||
[ -L "${todir}/dangling" ] && test_fail "dangling symlink was copied"
|
||||
[ -L "${todir}/relative" ] && test_fail "relative symlink was copied"
|
||||
[ -L "${todir}/absolute" ] && test_fail "absolute symlink was copied"
|
||||
|
||||
exit 0
|
||||
# last [] may have failed but if we get here then we've one
|
||||
|
||||
14
tls.c
14
tls.c
@@ -1,6 +1,6 @@
|
||||
/* -*- c-file-style: "linux" -*-
|
||||
*
|
||||
* Copyright (C) 2001 by Martin Pool <mbp@samba.org>
|
||||
* Copyright (C) 2001, 2002 by Martin Pool <mbp@samba.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version
|
||||
@@ -80,11 +80,18 @@ static void list_file (const char *fname)
|
||||
* undefined. Also it tends not to be possible to reset a
|
||||
* symlink's mtime, so we have to ignore it too. */
|
||||
if (S_ISLNK(buf.st_mode)) {
|
||||
int len;
|
||||
buf.st_mode &= ~0777;
|
||||
buf.st_mtime = (time_t)0;
|
||||
buf.st_uid = buf.st_gid = 0;
|
||||
strcpy(linkbuf, " -> ");
|
||||
readlink(fname, linkbuf+4, sizeof(linkbuf) - 4);
|
||||
/* const-cast required for silly UNICOS headers */
|
||||
len = readlink((char *) fname, linkbuf+4, sizeof(linkbuf) - 4);
|
||||
if (len == -1)
|
||||
failed("readlink", fname);
|
||||
else
|
||||
/* it's not nul-terminated */
|
||||
linkbuf[4+len] = 0;
|
||||
} else {
|
||||
linkbuf[0] = 0;
|
||||
}
|
||||
@@ -110,9 +117,10 @@ static void list_file (const char *fname)
|
||||
|
||||
/* NB: need to pass size as a double because it might be be
|
||||
* too large for a long. */
|
||||
printf("%s %12.0f %6d.%-6d %s %s%s\n",
|
||||
printf("%s %12.0f %6d.%-6d %6d %s %s%s\n",
|
||||
permbuf, (double) buf.st_size,
|
||||
buf.st_uid, buf.st_gid,
|
||||
buf.st_nlink,
|
||||
datebuf, fname, linkbuf);
|
||||
}
|
||||
|
||||
|
||||
84
util.c
84
util.c
@@ -1,8 +1,6 @@
|
||||
/* -*- c-file-style: "linux" -*-
|
||||
|
||||
Copyright (C) 1996-2000 by Andrew Tridgell
|
||||
Copyright (C) Paul Mackerras 1996
|
||||
Copyright (C) 2001 by Martin Pool <mbp@samba.org>
|
||||
/*
|
||||
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
|
||||
@@ -94,9 +92,9 @@ int fd_pair(int fd[2])
|
||||
used to cope with badly broken rsh implementations like the one on
|
||||
solaris.
|
||||
*/
|
||||
pid_t piped_child(char **command,int *f_in,int *f_out)
|
||||
int piped_child(char **command,int *f_in,int *f_out)
|
||||
{
|
||||
pid_t pid;
|
||||
int pid;
|
||||
int to_child_pipe[2];
|
||||
int from_child_pipe[2];
|
||||
extern int blocking_io;
|
||||
@@ -109,7 +107,7 @@ pid_t piped_child(char **command,int *f_in,int *f_out)
|
||||
|
||||
|
||||
pid = do_fork();
|
||||
if (pid == -1) {
|
||||
if (pid < 0) {
|
||||
rprintf(FERROR,"fork: %s\n",strerror(errno));
|
||||
exit_cleanup(RERR_IPC);
|
||||
}
|
||||
@@ -149,12 +147,11 @@ pid_t piped_child(char **command,int *f_in,int *f_out)
|
||||
return pid;
|
||||
}
|
||||
|
||||
pid_t local_child(int argc, char **argv,int *f_in,int *f_out)
|
||||
int local_child(int argc, char **argv,int *f_in,int *f_out)
|
||||
{
|
||||
pid_t pid;
|
||||
int pid;
|
||||
int to_child_pipe[2];
|
||||
int from_child_pipe[2];
|
||||
extern int read_batch; /* dw */
|
||||
|
||||
if (fd_pair(to_child_pipe) < 0 ||
|
||||
fd_pair(from_child_pipe) < 0) {
|
||||
@@ -164,7 +161,7 @@ pid_t local_child(int argc, char **argv,int *f_in,int *f_out)
|
||||
|
||||
|
||||
pid = do_fork();
|
||||
if (pid == -1) {
|
||||
if (pid < 0) {
|
||||
rprintf(FERROR,"fork: %s\n",strerror(errno));
|
||||
exit_cleanup(RERR_IPC);
|
||||
}
|
||||
@@ -173,10 +170,7 @@ pid_t local_child(int argc, char **argv,int *f_in,int *f_out)
|
||||
extern int am_sender;
|
||||
extern int am_server;
|
||||
|
||||
if (read_batch)
|
||||
am_sender = 0;
|
||||
else
|
||||
am_sender = !am_sender;
|
||||
am_sender = !am_sender;
|
||||
am_server = 1;
|
||||
|
||||
if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 ||
|
||||
@@ -275,7 +269,7 @@ int create_directory_path(char *fname)
|
||||
|
||||
derived from GNU C's cccp.c.
|
||||
*/
|
||||
static int full_write(int desc, char *ptr, int len)
|
||||
static int full_write(int desc, char *ptr, size_t len)
|
||||
{
|
||||
int total_written;
|
||||
|
||||
@@ -301,11 +295,11 @@ static int full_write(int desc, char *ptr, int len)
|
||||
for an error.
|
||||
|
||||
derived from GNU C's cccp.c. */
|
||||
static int safe_read(int desc, char *ptr, int len)
|
||||
static int safe_read(int desc, char *ptr, size_t len)
|
||||
{
|
||||
int n_chars;
|
||||
|
||||
if (len <= 0)
|
||||
if (len == 0)
|
||||
return len;
|
||||
|
||||
#ifdef EINTR
|
||||
@@ -563,7 +557,10 @@ void glob_expand(char *base1, char **argv, int *argc, int maxargs)
|
||||
s = strdup(s);
|
||||
if (!s) out_of_memory("glob_expand");
|
||||
|
||||
if (asprintf(&base," %s/", base1) <= 0) out_of_memory("glob_expand");
|
||||
base = (char *)malloc(strlen(base1)+3);
|
||||
if (!base) out_of_memory("glob_expand");
|
||||
|
||||
sprintf(base," %s/", base1);
|
||||
|
||||
q = s;
|
||||
while ((p = strstr(q,base)) && ((*argc) < maxargs)) {
|
||||
@@ -590,6 +587,33 @@ void strlower(char *s)
|
||||
}
|
||||
}
|
||||
|
||||
/* this is like vsnprintf but it always null terminates, so you
|
||||
can fit at most n-1 chars in */
|
||||
int vslprintf(char *str, int n, const char *format, va_list ap)
|
||||
{
|
||||
int ret = vsnprintf(str, n, format, ap);
|
||||
if (ret >= n || ret < 0) {
|
||||
str[n-1] = 0;
|
||||
return -1;
|
||||
}
|
||||
str[ret] = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* like snprintf but always null terminates */
|
||||
int slprintf(char *str, int n, char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int ret;
|
||||
|
||||
va_start(ap, format);
|
||||
ret = vslprintf(str,n,format,ap);
|
||||
va_end(ap);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void *Realloc(void *p, int size)
|
||||
{
|
||||
if (!p) return (void *)malloc(size);
|
||||
@@ -906,13 +930,10 @@ char *timestring(time_t t)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sleep for a specified number of milliseconds.
|
||||
*
|
||||
* Always returns TRUE. (In the future it might return FALSE if
|
||||
* interrupted.)
|
||||
**/
|
||||
int msleep(int t)
|
||||
/*******************************************************************
|
||||
sleep for a specified number of milliseconds
|
||||
********************************************************************/
|
||||
void msleep(int t)
|
||||
{
|
||||
int tdiff=0;
|
||||
struct timeval tval,t1,t2;
|
||||
@@ -931,8 +952,6 @@ int msleep(int t)
|
||||
tdiff = (t2.tv_sec - t1.tv_sec)*1000 +
|
||||
(t2.tv_usec - t1.tv_usec)/1000;
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
|
||||
@@ -944,6 +963,7 @@ int msleep(int t)
|
||||
*******************************************************************/
|
||||
int cmp_modtime(time_t file1, time_t file2)
|
||||
{
|
||||
time_t diff;
|
||||
extern int modify_window;
|
||||
|
||||
if (file2 > file1) {
|
||||
@@ -967,9 +987,9 @@ int _Insure_trap_error(int a1, int a2, int a3, int a4, int a5, int a6)
|
||||
{
|
||||
static int (*fn)();
|
||||
int ret;
|
||||
char *cmd;
|
||||
char cmd[1024];
|
||||
|
||||
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'",
|
||||
sprintf(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) {
|
||||
@@ -982,8 +1002,6 @@ int _Insure_trap_error(int a1, int a2, int a3, int a4, int a5, int a6)
|
||||
|
||||
system(cmd);
|
||||
|
||||
free(cmd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user