Compare commits

...

117 Commits

Author SHA1 Message Date
rsync-bugs
c239825783 preparing for release of 2.2.0 1998-11-03 22:00:59 +00:00
David Dykstra
33e817e37e Document the fact that you can use [USER@] in an rsync URL.
Note: the same thing works for ftp and http URLs in netscape.
1998-11-03 21:58:08 +00:00
David Dykstra
1b8e662a24 Call clean_fname() in sanitize_path() to catch some more strange but
legal file name syntaxes.
1998-11-03 21:49:38 +00:00
David Dykstra
2acf81eb00 Add support for optional ":PORT" in rsync URL. 1998-11-03 21:17:40 +00:00
Andrew Tridgell
654175798b patch from Alberto Accomazzi <aaccomazzi@cfa.harvard.edu> to add
different exit codes for different conditions.
1998-11-03 07:08:27 +00:00
Andrew Tridgell
3e578a1909 documented --delete disabling on IO errors 1998-11-03 05:14:41 +00:00
Andrew Tridgell
b606265491 added the --log-format option to allow users to request arbitrary
per-file logging of interactive rsync sessions.
1998-11-03 03:48:47 +00:00
Andrew Tridgell
263cf2ed55 remove double / from filenames in display 1998-11-02 07:26:36 +00:00
Andrew Tridgell
ab7104da8f the logging wasn't showing the full prefix for filenames 1998-11-02 06:40:11 +00:00
Andrew Tridgell
1b7c47cb55 Jason told me that's its very important for his site to log exactly
how many bytes were needed to be transferred for each file. I added %b
and %c log format options to cover this. See the man page for details.
1998-11-02 04:17:56 +00:00
Andrew Tridgell
039faa8660 - document the rsync:// URL format 1998-11-02 00:55:21 +00:00
Andrew Tridgell
f7632fc60d if no local destination is provided for the transfer then provide
a "ls -l" style listing of the files that would be transferred
1998-11-02 00:52:01 +00:00
Andrew Tridgell
2f098547ea added copyright notice from Patrick Powell 1998-10-31 04:35:44 +00:00
Andrew Tridgell
c7c056410c get the date comparison the right way around 1998-10-31 00:12:59 +00:00
Andrew Tridgell
e803090538 use the orig_umask when choosing perms for the log file. 1998-10-30 23:50:12 +00:00
Andrew Tridgell
6265551a5a fixed perms on rsyncd log file 1998-10-30 23:03:08 +00:00
Andrew Tridgell
958f373550 move the time init before the logfile opening. 1998-10-30 11:18:38 +00:00
Andrew Tridgell
2c51d5deec added a perl script to summarise the rsyncd log format 1998-10-30 06:12:14 +00:00
Andrew Tridgell
97cb8dc29b added %m, %P and %u options to logging 1998-10-30 05:53:05 +00:00
Andrew Tridgell
cd957c70c4 need BIG_ENDIAN test for inet_ntoa replacement 1998-10-30 02:52:42 +00:00
Andrew Tridgell
7b3d425783 check for a broken inet_ntoa() on IRIX 1998-10-30 02:50:02 +00:00
Andrew Tridgell
b24203b323 get null termination right in logging 1998-10-30 02:43:10 +00:00
Andrew Tridgell
3472009789 get null termination right in logging 1998-10-30 02:36:05 +00:00
Andrew Tridgell
f27b53f5b5 hopefuly fix logging of "transfer interrupted" messages 1998-10-30 02:32:29 +00:00
Andrew Tridgell
e08bfe1248 added "log format" option to allow admins to choose the format for
rsyncd log file entries
1998-10-30 02:24:47 +00:00
Andrew Tridgell
74e708d85a hanle null strings in -vvv output 1998-10-30 02:23:01 +00:00
Andrew Tridgell
7597e1a96a fixed cacheing of some values (using code from Samba) 1998-10-29 23:44:30 +00:00
David Dykstra
692da0b555 Fix for systems such as Unixware that have a cc that does not support -o
with -c.
1998-10-29 22:28:56 +00:00
Andrew Tridgell
67ea0d4844 put the pid on each line of the log file to facilitate
auto-parsing. Requested by Jarkko Hietaniemi (jhi@iki.fi)
1998-10-29 11:16:51 +00:00
Andrew Tridgell
9b73d1c0e9 put the pid on each line of the log file to facilitate
auto-parsing. Requested by Jarkko Hietaniemi (jhi@iki.fi)
1998-10-29 11:11:38 +00:00
Andrew Tridgell
f3737e0648 some minor optimisations 1998-10-29 06:39:43 +00:00
Andrew Tridgell
19a013837e a change I made yesterday corrupted the displayed filename in some
cases. cosmetic fix.
1998-10-29 06:10:31 +00:00
Andrew Tridgell
d730b113f4 final change needed to get rsync working on a CRAY J90 1998-10-29 05:48:11 +00:00
Andrew Tridgell
7ae359c331 kfixed char* casts 1998-10-29 05:06:51 +00:00
Andrew Tridgell
8de330a387 changes to get rsync working on a CRAY J90. This machine doesn't have
a 4 byte integer type (short is 8 bytes). I needed to use a new md4
implementation (I used the portable one I wrote for Samba).
1998-10-29 05:01:47 +00:00
Andrew Tridgell
27d3cdbc94 syslog support in rsync daemon has been broken since I added the "log
file" option. I wonder why noone reported it? Or did everyone just use
"log file" ?
1998-10-28 10:43:31 +00:00
Andrew Tridgell
106005004e fixed handling of %.0f in replacement snprintf.c 1998-10-28 04:06:43 +00:00
Andrew Tridgell
92ad2c90c4 fixed a typo 1998-10-28 03:37:53 +00:00
Andrew Tridgell
11a5a3c704 and I thought I wasn't going to do any rsync coding for a while ...
Jason Andrade convinced me to add ftpd style logging of transfers,
enabled with a "transfer logging" option in rsyncd.conf

you can customise the format in log.c
1998-10-28 03:28:30 +00:00
David Dykstra
8bb5aa8fe8 Document the fact that --numeric-ids is implied if the source system is
a daemon using chroot.
1998-10-27 17:30:28 +00:00
David Dykstra
4040be4d60 - Define bindir and mandir as per gnu makefile standards
- Add install-strip target as per gnu makefile standards
Contributed by Fred Sanchez <wsanchez@apple.com>
1998-10-27 16:07:51 +00:00
Andrew Tridgell
a9685611e2 fixed a typecast 1998-10-27 14:19:35 +00:00
Andrew Tridgell
b280a1f47e handle OSes (such as Unicos) which use a different value for S_IFLNK 1998-10-27 14:09:28 +00:00
Andrew Tridgell
f8be5ef4cb added a vsnprintf() implementation from cvslock. See the notes on the
license at the top of lib/snprintf.c
1998-10-26 23:23:45 +00:00
David Dykstra
587cb08dc4 Fix bug in --include and --include-from which didn't work as advertised;
could only include files before if "+ " was explicitly prefixed on files
from any exclude or include option.  Also simplified the code by removing
the "orig" exclude_struct element, and reduced the number of bytes
transferred from client to server by never including "- " prefixes in the
transmitted exclude list because exclusion is the default.
1998-10-26 22:03:18 +00:00
David Dykstra
8638dd48f7 Add "use chroot" and "pid file" rsyncd.conf options. The former allows one
to disable the use of chroot so rsync --daemon can be run as a non-root
user (if a non-privileged --port is used).  The latter allows one to
specify a file in which to write the process id of the daemon, which is
useful when rsync --daemon is not run from inetd.
1998-10-26 21:51:47 +00:00
David Dykstra
2bca43f627 Optimize server for special case of a long list of includes ("+") followed
by a match-all exclude "- *".
1998-10-26 21:45:23 +00:00
David Dykstra
375a4556c7 Add --compare-dest option which enables specifying an additional destination
for comparisons when syncing.  Useful for syncing into a scratch area and
doing a flash-cutover when it is completed.
1998-10-26 21:42:38 +00:00
rsync-bugs
b41c3f9273 preparing for release of 2.1.1 1998-09-09 07:07:11 +00:00
Andrew Tridgell
35bdd146e4 fixed timestring() bug 1998-09-09 07:06:44 +00:00
Andrew Tridgell
8d249b635c don't complain about not setting times on directories
because some filesystems can't do it
1998-09-09 06:37:13 +00:00
Andrew Tridgell
932be9aa52 handle sstem (sco 3) with glob but not glob.h 1998-09-09 06:31:13 +00:00
Andrew Tridgell
c6b81a9865 handle OSes where you can't rename a open file in the cleanup code. 1998-09-09 06:23:27 +00:00
Andrew Tridgell
e0414f4202 put the time in when using log file. 1998-09-09 06:06:08 +00:00
Andrew Tridgell
6e4fb64e61 added finddead target, removed dead code and made some functions
static
1998-09-09 05:57:34 +00:00
Andrew Tridgell
37863201ad doc updates 1998-09-09 05:52:25 +00:00
Andrew Tridgell
4f6325c362 added "log file" option for those systems with broken syslog (like
AIX)
1998-09-09 05:51:42 +00:00
Andrew Tridgell
f98df1d9b7 wanr people who use path names to rsync :: 1998-09-09 05:51:08 +00:00
Andrew Tridgell
3d913675a1 fixed a small memory leak when using -C
thanks to kalt@research.bell-labs.com for this fix.
1998-08-27 05:17:21 +00:00
Andrew Tridgell
2f9af90118 removed the limit on the read buffer size until I fully understand the
interactions with ssh. The old ssh freezes have shown up again and
some debugging (with help from James Welborn) showed that the cause
was the read buffer hitting maximum size. I think this means that ssh
must be misbehaving about blocking IO.

This change gets rid of the freezes at the expense of memory
usage. Where it would have frozen it uses more memory instead.
1998-08-27 05:07:52 +00:00
Andrew Tridgell
3eb388185b a couple of changes to where the nonblocking settings are called. 1998-08-27 05:05:14 +00:00
Andrew Tridgell
858fb9ebad fix PATTERN/FILE in --help output 1998-07-25 09:20:33 +00:00
Andrew Tridgell
2f03f956f4 rsync.c was getting a bit unwieldy so I split the code into 3 modules,
for the 3 logical stages of rsync; generator, sender and receiver.
1998-07-25 02:25:22 +00:00
Andrew Tridgell
0199b05f25 fixed the relative paths bug pointed out by Alberto Accomazzi 1998-07-23 03:09:14 +00:00
rsync-bugs
e2d1033d5d preparing for release of 2.1.0 1998-07-20 05:43:51 +00:00
Andrew Tridgell
c46ded4621 I think I might havefinally fixed the rsync hanging bug. It was caused
by a read during an io_flush() triggered during a readfd(). A simple
logic bug in the io code :(
1998-07-20 05:36:25 +00:00
Andrew Tridgell
8cd9fd4e8c always use a timeout to select, even if --timeout is not
specified. This makes things easier to debug.
1998-07-19 10:51:26 +00:00
Andrew Tridgell
41979ff87c - defer the error message from the options parsing until after the
socket is multiplexed. This allows clients sending new options which
the remote server doesn't understand to get a sensible error message.
1998-07-19 05:22:05 +00:00
Andrew Tridgell
b11ed3b150 - close stdout and stderr and reopen then as /dev/null when running as
a daemon. This prevents library functions (such as getopt) stuffing up
our protocol stream when errors are detected.

- defer the error message from the options parsing until after the
socket is multiplexed. This allows clients sending new options which
the remote server doesn't understand to get a sensible error message.
1998-07-19 04:50:48 +00:00
rsync-bugs
42245f1b56 preparing for release of 2.0.19 1998-07-17 14:53:00 +00:00
Andrew Tridgell
c29ee43dbd handle hard links on systems with 16 bit ino_t 1998-07-17 14:42:59 +00:00
Andrew Tridgell
d310a212f7 added a bit in the man page about the clean shell error 1998-07-17 14:25:14 +00:00
Andrew Tridgell
ca6c93f817 check whether there is a / before a : in the rsync command line. If
there is then assume that the : is from a filename, not a host:dir
separator. This allows you to copy files with a : in them. (suggestion
from pfeifer@wait.de)
1998-07-17 14:05:57 +00:00
Andrew Tridgell
72914a606e make rsync behave more like GNU cp with regard to file permissions
when -p (preserve permissions) isn't set.

It works by taking the sending file permissions and masking them with
the umask to create the destination file permissions. (There is really
no "correct" way of doing this but at least we now behave like GNU cp
which fits the principle of least surprise.)

also fixed a race condition in copy_file()
1998-07-17 13:18:32 +00:00
Andrew Tridgell
4b957c2238 added the --safe-links option to disallow symlinks outside the
destination tree
1998-07-17 10:00:48 +00:00
Andrew Tridgell
d853783f21 added the --safe-links option to disallow symlinks outside the
destination tree
1998-07-17 10:00:43 +00:00
Andrew Tridgell
298c10d5bb some code reformatting 1998-07-17 07:42:04 +00:00
Andrew Tridgell
6608462cac removed old "make dist" target 1998-07-17 07:26:08 +00:00
Andrew Tridgell
ca8e96946e changed wording of an error message 1998-07-17 07:25:42 +00:00
Andrew Tridgell
6ed67e6dd5 moved getopt.h above unistd.h to prevent problems with uwin on NT 1998-07-17 07:17:11 +00:00
Andrew Tridgell
1f658d4207 fixed a problem with rsync buffering the debug output when redirected
to a file.
1998-07-17 07:07:23 +00:00
Andrew Tridgell
d3bc0b68ab make a function static 1998-07-17 05:38:51 +00:00
Andrew Tridgell
1a0de6c68b remove a useless debug message 1998-07-17 05:38:21 +00:00
Andrew Tridgell
eb601ffeb8 code style change 1998-07-17 05:37:56 +00:00
Andrew Tridgell
8d72ef6e52 use error to detect lockfile open failures vs. max connections reached
and report an appropriate error message
1998-07-17 05:37:18 +00:00
Andrew Tridgell
bcf5b1335d - use explicit flushes instead of setlinebuf. I've had reports of
verbose info not being line buffered to files.

- add a call to localtime() in open_log() in order to prime the C
  libraries timezone cache before the chroot(). This should fix the
  problem of rsyncd log entries being in GMT time.
1998-07-02 10:57:20 +00:00
Andrew Tridgell
bd7e05d799 remove a redundent continue statement 1998-07-02 03:02:14 +00:00
Andrew Tridgell
c95f1aa9d3 prioritise reading over writing in the select loop. (this is another
ssh-friendly attempt)
1998-07-02 02:59:04 +00:00
Andrew Tridgell
86ffe37f11 fix the problem of --timeout waiting for twice the specified time. 1998-07-02 02:48:09 +00:00
Andrew Tridgell
b536f47e3c - don't show "created directory" message unless verbose is selected
- check for null buf in show_progress
1998-07-02 02:08:55 +00:00
Andrew Tridgell
43b06eeae9 output progress % every 1k instead of every 1%, this is better for
large files.
1998-07-02 01:28:39 +00:00
Andrew Tridgell
067857e0ac the recv_generator can be static 1998-07-02 01:27:51 +00:00
Andrew Tridgell
b3e10ed75b enable output buffering in the recv generator. This makes a
significant difference when the transport is ssh as ssh will otherwise
output a complete frame for each checksum record, which increases the
checksum data in size by a factor of around 4.
1998-07-02 01:27:14 +00:00
Andrew Tridgell
a353d56337 don't need to send --progress option to server as the server never
prints progress info.
1998-07-02 00:48:20 +00:00
Andrew Tridgell
eb86d661d7 added --progress option which shows the progress of transfers. This
gives bored users something to watch.
1998-07-02 00:47:13 +00:00
Andrew Tridgell
fe055c718a - only keep a partial file if some literal data has been transferred,
this prevents a second interrupted transfer from reducing the size of
the transferred file.

- set SIGUSR1 to SIG_IGN early to prevent a race condition that
prevents the --partial code from working properly
1998-07-01 11:03:50 +00:00
Andrew Tridgell
31f440e68b I've had reports of rsyncd leaving zombies under digital unix. This
patch tries to address the problem in two ways:

1) reinstall the SIGCHLD handler before each fork
2) reap any children not caught by the handler using waitpid with
WNOHANG.

I expect this will fix the problem.
1998-07-01 05:10:42 +00:00
Andrew Tridgell
c95da96a0c added a --partial option which tells rsync to keep partially
transferred files if the transfer is interrupted.

added a "options summary" section to the man page
1998-07-01 03:36:03 +00:00
Andrew Tridgell
bf9f01689f if we get EWOULDBLOCK on a write then reduce the amount of data we are
trying to write. This guarantees that the maximum amount of data that
can be written at any one time is written.
1998-06-19 00:55:19 +00:00
Andrew Tridgell
da81e21536 use LDFLAGS in Makefile.in (fix from arndt@schoenewald.de) 1998-06-18 14:15:16 +00:00
Andrew Tridgell
46831d6fcf fixed chmod bug pointed out by Han Holl <jeholl@euronet.nl> 1998-06-18 13:26:10 +00:00
rsync-bugs
b58ad6c569 preparing for release of 2.0.18 1998-06-18 13:06:00 +00:00
Andrew Tridgell
22b1933287 fixed a race condition in rsync that opened a security hole. The
temporary files were being created with the same permissions as the
original file. So if the file was setuid but not owned by the user
doing the transfer then there was a window of opportunity for a
malicious user to execute it with the wrong permissions while it was
being transferred.

Thanks to snabb@epipe.fi for pointing this out.
1998-06-18 12:17:23 +00:00
rsync-bugs
5a03f68a5a preparing for release of 2.0.17 1998-06-18 10:30:48 +00:00
Andrew Tridgell
e81da93e86 if as non-root we failed to update the group of a file then don't
print the file name.
1998-06-18 10:03:44 +00:00
Andrew Tridgell
f578043391 for consistency use memcpy/memset everywhere instead of bcopy/bzero 1998-06-18 09:51:44 +00:00
Andrew Tridgell
e8f5b936ad move include of compat.h after other includes. 1998-06-18 09:37:21 +00:00
Andrew Tridgell
667e72a195 change the order of chmod and chown calls so that setuid bits don't
get removed by chown calls.
1998-06-18 09:36:24 +00:00
Andrew Tridgell
e1b3d5c4be set network file descriptors non-blocking before starting main rsync
algorithm.
1998-06-18 09:34:56 +00:00
Andrew Tridgell
f7b9377863 handle non-blocking file descriptors for both read and write. Add a
workaround for buggy systems that say there is space to write when
there isn't.
1998-06-18 09:33:46 +00:00
Andrew Tridgell
a5343e765b put set_nonblocking() code back in. 1998-06-18 09:32:45 +00:00
Andrew Tridgell
704f908eae --help changes suggested by Francois 1998-06-18 09:31:42 +00:00
Andrew Tridgell
de2fd20eb7 manpage updates, mostly suggested by Francois 1998-06-18 09:30:51 +00:00
Andrew Tridgell
100e5241b0 the tag table should be of type int* not tag*.
This bug resulted in rsync being much less efficient that it could be
for files with more than 64k blocks. With the adaptive block size code
giving a maximum block size of 16k this means that files larger than
1GB were handled very inefficiently. The transfer was still accurate,
just slow.
1998-06-03 02:47:52 +00:00
Andrew Tridgell
ddecf7060b if the user passes a block size on the command line then don't adapt
the block size.
1998-06-03 02:35:51 +00:00
Andrew Tridgell
56cdbccb92 added note to docs saying that --stats doesn't work unless -v is used 1998-06-02 12:50:23 +00:00
Andrew Tridgell
fc8a6b9705 added some fflush() calls to make sure the statistics lines are
printed when redirecting output to a file.
1998-06-02 12:46:46 +00:00
41 changed files with 6519 additions and 1998 deletions

View File

@@ -3,8 +3,8 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
INSTALL_BIN=$(exec_prefix)/bin
INSTALL_MAN=$(prefix)/man
bindir=@bindir@
mandir=@mandir@
LIBS=@LIBS@
CC=@CC@
@@ -12,41 +12,46 @@ CFLAGS=@CFLAGS@
INSTALLCMD=@INSTALL@
VPATH=@srcdir@
srcdir=@srcdir@
VPATH=$(srcdir)
SHELL=/bin/sh
.SUFFIXES:
.SUFFIXES: .c .o
LIBOBJ=lib/getopt.o lib/fnmatch.o lib/compat.o
LIBOBJ=lib/getopt.o lib/fnmatch.o lib/compat.o lib/snprintf.o lib/mdfour.o
ZLIBOBJ=zlib/deflate.o zlib/infblock.o zlib/infcodes.o zlib/inffast.o \
zlib/inflate.o zlib/inftrees.o zlib/infutil.o zlib/trees.o \
zlib/zutil.o zlib/adler32.o
OBJS1=rsync.o exclude.o util.o md4.o main.o checksum.o match.o syscall.o log.o
zlib/zutil.o zlib/adler32.o
OBJS1=rsync.o generator.o receiver.o cleanup.o sender.o exclude.o util.o main.o checksum.o match.o syscall.o log.o
OBJS2=options.o flist.o io.o compat.o hlink.o token.o uidlist.o socket.o fileio.o
DAEMON_OBJ = params.o loadparm.o clientserver.o access.o connection.o authenticate.o
OBJS=$(OBJS1) $(OBJS2) $(DAEMON_OBJ) $(LIBOBJ) $(ZLIBOBJ)
# note that the -I. is needed to handle config.h when using VPATH
.c.o:
$(CC) -I. -I$(srcdir) $(CFLAGS) -c $< -o $@
@OBJ_SAVE@
$(CC) -I. -I$(srcdir) $(CFLAGS) -c $< @CC_SHOBJ_FLAG@
@OBJ_RESTORE@
all: rsync
man: rsync.1 rsyncd.conf.5
install: all
-mkdir -p ${INSTALL_BIN}
${INSTALLCMD} -m 755 rsync ${INSTALL_BIN}
-mkdir -p ${INSTALL_MAN}/man1
-mkdir -p ${INSTALL_MAN}/man5
${INSTALLCMD} -m 644 $(srcdir)/rsync.1 ${INSTALL_MAN}/man1
${INSTALLCMD} -m 644 $(srcdir)/rsyncd.conf.5 ${INSTALL_MAN}/man5
-mkdir -p ${bindir}
${INSTALLCMD} -m 755 rsync ${bindir}
-mkdir -p ${mandir}/man1
-mkdir -p ${mandir}/man5
${INSTALLCMD} -m 644 $(srcdir)/rsync.1 ${mandir}/man1
${INSTALLCMD} -m 644 $(srcdir)/rsyncd.conf.5 ${mandir}/man5
install-strip:
$(MAKE) INSTALLCMD='$(INSTALLCMD) -s' install
rsync: $(OBJS)
$(CC) $(CFLAGS) -o rsync $(OBJS) $(LIBS)
$(CC) $(CFLAGS) $(LDFLAGS) -o rsync $(OBJS) $(LIBS)
rsync.1: rsync.yo
yodl2man -o rsync.1 rsync.yo
@@ -58,12 +63,13 @@ proto:
cat *.c | awk -f mkproto.awk > proto.h
clean:
rm -f *~ $(OBJS) rsync config.cache config.log config.status
rm -f *~ $(OBJS) rsync
dist:
tar --exclude-from .ignore -czf dist.tar.gz .
-mkdir rsync-$(VERSION)
(cd rsync-$(VERSION) ; tar xzf ../dist.tar.gz)
tar -czf rsync-$(VERSION).tar.gz rsync-$(VERSION)
rm -f dist.tar.gz
echo rsync-$(VERSION) >> .cvsignore
# this target is really just for my use. It only works on a limited
# range of machines and is used to produce a list of potentially
# dead (ie. unused) functions in the code. (tridge)
finddead:
nm *.o */*.o |grep 'U ' | awk '{print $$2}' | sort -u > nmused.txt
nm *.o */*.o |grep 'T ' | awk '{print $$3}' | sort -u > nmfns.txt
comm -13 nmused.txt nmfns.txt

View File

@@ -7,3 +7,5 @@
#undef HAVE_UTIMBUF
#undef ino_t
#undef HAVE_CONNECT
#undef HAVE_SHORT_INO_T
#undef REPLACE_INET_NTOA

23
aclocal.m4 vendored Normal file
View File

@@ -0,0 +1,23 @@
dnl AC_VALIDATE_CACHE_SYSTEM_TYPE[(cmd)]
dnl if the cache file is inconsistent with the current host,
dnl target and build system types, execute CMD or print a default
dnl error message.
AC_DEFUN(AC_VALIDATE_CACHE_SYSTEM_TYPE, [
AC_REQUIRE([AC_CANONICAL_SYSTEM])
AC_MSG_CHECKING([config.cache system type])
if { test x"${ac_cv_host_system_type+set}" = x"set" &&
test x"$ac_cv_host_system_type" != x"$host"; } ||
{ test x"${ac_cv_build_system_type+set}" = x"set" &&
test x"$ac_cv_build_system_type" != x"$build"; } ||
{ test x"${ac_cv_target_system_type+set}" = x"set" &&
test x"$ac_cv_target_system_type" != x"$target"; }; then
AC_MSG_RESULT([different])
ifelse($#, 1, [$1],
[AC_MSG_ERROR(["you must remove config.cache and restart configure"])])
else
AC_MSG_RESULT([same])
fi
ac_cv_host_system_type="$host"
ac_cv_build_system_type="$build"
ac_cv_target_system_type="$target"
])

View File

@@ -112,7 +112,7 @@ static int get_secret(int module, char *user, char *secret, int len)
}
/* generate a 16 byte hash from a password and challenge */
void generate_hash(char *in, char *challenge, char *out)
static void generate_hash(char *in, char *challenge, char *out)
{
char buf[16];

View File

@@ -49,82 +49,71 @@ uint32 get_checksum1(char *buf1,int len)
}
static void sum_put(MDstruct *md,char *sum)
{
SIVAL(sum,0,md->buffer[0]);
if (csum_length <= 4) return;
SIVAL(sum,4,md->buffer[1]);
if (csum_length <= 8) return;
SIVAL(sum,8,md->buffer[2]);
if (csum_length <= 12) return;
SIVAL(sum,12,md->buffer[3]);
}
void get_checksum2(char *buf,int len,char *sum)
{
int i;
MDstruct MD;
static char *buf1;
static int len1;
int i;
static char *buf1;
static int len1;
struct mdfour m;
if (len > len1) {
if (buf1) free(buf1);
buf1 = (char *)malloc(len+4);
len1 = len;
if (!buf1) out_of_memory("get_checksum2");
}
MDbegin(&MD);
bcopy(buf,buf1,len);
if (checksum_seed) {
SIVAL(buf1,len,checksum_seed);
len += 4;
}
for(i = 0; i + CSUM_CHUNK <= len; i += CSUM_CHUNK) {
MDupdate(&MD, buf1+i, CSUM_CHUNK*8);
}
if (len - i > 0)
MDupdate(&MD, buf1+i, (len-i)*8);
sum_put(&MD,sum);
if (len > len1) {
if (buf1) free(buf1);
buf1 = (char *)malloc(len+4);
len1 = len;
if (!buf1) out_of_memory("get_checksum2");
}
mdfour_begin(&m);
memcpy(buf1,buf,len);
if (checksum_seed) {
SIVAL(buf1,len,checksum_seed);
len += 4;
}
for(i = 0; i + CSUM_CHUNK <= len; i += CSUM_CHUNK) {
mdfour_update(&m, (uchar *)(buf1+i), CSUM_CHUNK);
}
if (len - i > 0) {
mdfour_update(&m, (uchar *)(buf1+i), (len-i));
}
mdfour_result(&m, (uchar *)sum);
}
void file_checksum(char *fname,char *sum,OFF_T size)
{
OFF_T i;
MDstruct MD;
struct map_struct *buf;
int fd;
OFF_T len = size;
char tmpchunk[CSUM_CHUNK];
OFF_T i;
struct map_struct *buf;
int fd;
OFF_T len = size;
char tmpchunk[CSUM_CHUNK];
struct mdfour m;
memset(sum,0,csum_length);
fd = open(fname,O_RDONLY);
if (fd == -1) return;
buf = map_file(fd,size);
mdfour_begin(&m);
bzero(sum,csum_length);
for(i = 0; i + CSUM_CHUNK <= len; i += CSUM_CHUNK) {
memcpy(tmpchunk, map_ptr(buf,i,CSUM_CHUNK), CSUM_CHUNK);
mdfour_update(&m, (uchar *)tmpchunk, CSUM_CHUNK);
}
fd = open(fname,O_RDONLY);
if (fd == -1) return;
if (len - i > 0) {
memcpy(tmpchunk, map_ptr(buf,i,len-i), len-i);
mdfour_update(&m, (uchar *)tmpchunk, (len-i));
}
buf = map_file(fd,size);
mdfour_result(&m, (uchar *)sum);
MDbegin(&MD);
for(i = 0; i + CSUM_CHUNK <= len; i += CSUM_CHUNK) {
bcopy(map_ptr(buf,i,CSUM_CHUNK),tmpchunk,CSUM_CHUNK);
MDupdate(&MD, tmpchunk, CSUM_CHUNK*8);
}
if (len - i > 0) {
bcopy(map_ptr(buf,i,len-i),tmpchunk,len-i);
MDupdate(&MD, tmpchunk, (len-i)*8);
}
sum_put(&MD,sum);
close(fd);
unmap_file(buf);
close(fd);
unmap_file(buf);
}
@@ -138,58 +127,54 @@ void checksum_init(void)
static MDstruct sumMD;
static int sumresidue;
static char sumrbuf[CSUM_CHUNK];
static struct mdfour md;
void sum_init(void)
{
char s[4];
MDbegin(&sumMD);
sumresidue=0;
SIVAL(s,0,checksum_seed);
sum_update(s,4);
char s[4];
mdfour_begin(&md);
sumresidue=0;
SIVAL(s,0,checksum_seed);
sum_update(s,4);
}
void sum_update(char *p,int len)
{
int i;
if (len + sumresidue < CSUM_CHUNK) {
bcopy(p,sumrbuf+sumresidue,len);
sumresidue += len;
return;
}
int i;
if (len + sumresidue < CSUM_CHUNK) {
memcpy(sumrbuf+sumresidue, p, len);
sumresidue += len;
return;
}
if (sumresidue) {
i = MIN(CSUM_CHUNK-sumresidue,len);
bcopy(p,sumrbuf+sumresidue,i);
MDupdate(&sumMD, sumrbuf, (i+sumresidue)*8);
len -= i;
p += i;
}
if (sumresidue) {
i = MIN(CSUM_CHUNK-sumresidue,len);
memcpy(sumrbuf+sumresidue,p,i);
mdfour_update(&md, (uchar *)sumrbuf, (i+sumresidue));
len -= i;
p += i;
}
for(i = 0; i + CSUM_CHUNK <= len; i += CSUM_CHUNK) {
bcopy(p+i,sumrbuf,CSUM_CHUNK);
MDupdate(&sumMD, sumrbuf, CSUM_CHUNK*8);
}
for(i = 0; i + CSUM_CHUNK <= len; i += CSUM_CHUNK) {
memcpy(sumrbuf,p+i,CSUM_CHUNK);
mdfour_update(&md, (uchar *)sumrbuf, CSUM_CHUNK);
}
if (len - i > 0) {
sumresidue = len-i;
bcopy(p+i,sumrbuf,sumresidue);
} else {
sumresidue = 0;
}
if (len - i > 0) {
sumresidue = len-i;
memcpy(sumrbuf,p+i,sumresidue);
} else {
sumresidue = 0;
}
}
void sum_end(char *sum)
{
if (sumresidue)
MDupdate(&sumMD, sumrbuf, sumresidue*8);
if (sumresidue) {
mdfour_update(&md, (uchar *)sumrbuf, sumresidue);
}
SIVAL(sum,0,sumMD.buffer[0]);
SIVAL(sum,4,sumMD.buffer[1]);
SIVAL(sum,8,sumMD.buffer[2]);
SIVAL(sum,12,sumMD.buffer[3]);
mdfour_result(&md, (uchar *)sum);
}

87
cleanup.c Normal file
View File

@@ -0,0 +1,87 @@
/*
Copyright (C) Andrew Tridgell 1996
Copyright (C) Paul Mackerras 1996
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "rsync.h"
/* handling the cleanup when a transfer is interrupted is tricky when
--partial is selected. We need to ensure that the partial file is
kept if any real data has been transferred */
int cleanup_got_literal=0;
static char *cleanup_fname;
static char *cleanup_new_fname;
static struct file_struct *cleanup_file;
static int cleanup_fd1, cleanup_fd2;
static struct map_struct *cleanup_buf;
static int cleanup_pid = 0;
void exit_cleanup(int code)
{
extern int keep_partial;
signal(SIGUSR1, SIG_IGN);
if (cleanup_got_literal && cleanup_fname && keep_partial) {
char *fname = cleanup_fname;
cleanup_fname = NULL;
if (cleanup_buf) unmap_file(cleanup_buf);
if (cleanup_fd1 != -1) close(cleanup_fd1);
if (cleanup_fd2 != -1) close(cleanup_fd2);
finish_transfer(cleanup_new_fname, fname, cleanup_file);
}
io_flush();
if (cleanup_fname)
do_unlink(cleanup_fname);
if (code) {
kill_all(SIGUSR1);
}
if ((cleanup_pid != 0) && (cleanup_pid == (int) getpid())) {
char *pidf = lp_pid_file();
if (pidf && *pidf) {
unlink(lp_pid_file());
}
}
if (code) log_exit(code);
exit(code);
}
void cleanup_disable(void)
{
cleanup_fname = NULL;
cleanup_got_literal = 0;
}
void cleanup_set(char *fnametmp, char *fname, struct file_struct *file,
struct map_struct *buf, int fd1, int fd2)
{
cleanup_fname = fnametmp;
cleanup_new_fname = fname;
cleanup_file = file;
cleanup_buf = buf;
cleanup_fd1 = fd1;
cleanup_fd2 = fd2;
}
void cleanup_set_pid(int pid)
{
cleanup_pid = pid;
}

View File

@@ -24,6 +24,7 @@ extern int module_id;
extern int read_only;
extern int verbose;
extern int rsync_port;
char *auth_user;
int start_socket_client(char *host, char *path, int argc, char *argv[])
{
@@ -36,6 +37,11 @@ int start_socket_client(char *host, char *path, int argc, char *argv[])
extern int am_client;
extern int am_sender;
if (*path == '/') {
rprintf(FERROR,"ERROR: The remote path must start with a module name\n");
return -1;
}
p = strchr(host, '@');
if (p) {
user = host;
@@ -50,7 +56,7 @@ int start_socket_client(char *host, char *path, int argc, char *argv[])
fd = open_socket_out(host, rsync_port);
if (fd == -1) {
exit_cleanup(1);
exit_cleanup(RERR_SOCKETIO);
}
server_options(sargs,&sargc);
@@ -116,8 +122,9 @@ static int rsync_module(int fd, int i)
char *addr = client_addr(fd);
char *host = client_name(fd);
char *name = lp_name(i);
char *user;
int use_chroot = lp_use_chroot(i);
int start_glob=0;
int ret;
char *request=NULL;
extern int am_sender;
extern int remote_version;
@@ -132,16 +139,23 @@ static int rsync_module(int fd, int i)
}
if (!claim_connection(lp_lock_file(), lp_max_connections())) {
rprintf(FERROR,"max connections (%d) reached\n",
lp_max_connections());
io_printf(fd,"@ERROR: max connections (%d) reached - try again later\n", lp_max_connections());
if (errno) {
rprintf(FERROR,"failed to open lock file %s : %s\n",
lp_lock_file(), strerror(errno));
io_printf(fd,"@ERROR: failed to open lock file %s : %s\n",
lp_lock_file(), strerror(errno));
} else {
rprintf(FERROR,"max connections (%d) reached\n",
lp_max_connections());
io_printf(fd,"@ERROR: max connections (%d) reached - try again later\n", lp_max_connections());
}
return -1;
}
user = auth_server(fd, i, addr, "@RSYNCD: AUTHREQD ");
auth_user = auth_server(fd, i, addr, "@RSYNCD: AUTHREQD ");
if (!user) {
if (!auth_user) {
rprintf(FERROR,"auth failed on module %s from %s (%s)\n",
name, client_name(fd), client_addr(fd));
io_printf(fd,"@ERROR: auth failed on module %s\n",name);
@@ -181,28 +195,37 @@ static int rsync_module(int fd, int i)
log_open();
if (chroot(lp_path(i))) {
rprintf(FERROR,"chroot %s failed\n", lp_path(i));
io_printf(fd,"@ERROR: chroot failed\n");
return -1;
}
if (use_chroot) {
if (chroot(lp_path(i))) {
rprintf(FERROR,"chroot %s failed\n", lp_path(i));
io_printf(fd,"@ERROR: chroot failed\n");
return -1;
}
if (chdir("/")) {
rprintf(FERROR,"chdir %s failed\n", lp_path(i));
io_printf(fd,"@ERROR: chdir failed\n");
return -1;
}
if (chdir("/")) {
rprintf(FERROR,"chdir %s failed\n", lp_path(i));
io_printf(fd,"@ERROR: chdir failed\n");
return -1;
}
if (setgid(gid) || getgid() != gid) {
rprintf(FERROR,"setgid %d failed\n", gid);
io_printf(fd,"@ERROR: setgid failed\n");
return -1;
}
if (setgid(gid) || getgid() != gid) {
rprintf(FERROR,"setgid %d failed\n", gid);
io_printf(fd,"@ERROR: setgid failed\n");
return -1;
}
if (setuid(uid) || getuid() != uid) {
rprintf(FERROR,"setuid %d failed\n", uid);
io_printf(fd,"@ERROR: setuid failed\n");
return -1;
if (setuid(uid) || getuid() != uid) {
rprintf(FERROR,"setuid %d failed\n", uid);
io_printf(fd,"@ERROR: setuid failed\n");
return -1;
}
} else {
if (!push_dir(lp_path(i), 0)) {
rprintf(FERROR,"chdir %s failed\n", lp_path(i));
io_printf(fd,"@ERROR: chdir failed\n");
return -1;
}
}
am_root = (getuid() == 0);
@@ -244,13 +267,28 @@ static int rsync_module(int fd, int i)
}
}
parse_arguments(argc, argv);
if (!use_chroot) {
/*
* Note that this is applied to all parameters, whether or not
* they are filenames, but no other legal parameters contain
* the forms that need to be sanitized so it doesn't hurt;
* it is not known at this point which parameters are files
* and which aren't.
*/
for (i = 1; i < argc; i++) {
char *copy = sanitize_path(argv[i]);
free((void *)argv[i]);
argv[i] = copy;
}
}
ret = parse_arguments(argc, argv);
if (request) {
if (*user) {
if (*auth_user) {
rprintf(FINFO,"rsync %s %s from %s@%s (%s)\n",
am_sender?"on":"to",
request, user, host, addr);
request, auth_user, host, addr);
} else {
rprintf(FINFO,"rsync %s %s from %s (%s)\n",
am_sender?"on":"to",
@@ -259,8 +297,10 @@ static int rsync_module(int fd, int i)
free(request);
}
#if !TRIDGE
/* don't allow the logs to be flooded too fast */
if (verbose > 1) verbose = 1;
#endif
argc -= optind;
argp = argv + optind;
@@ -269,6 +309,11 @@ static int rsync_module(int fd, int i)
if (remote_version > 17 && am_sender)
io_start_multiplex_out(fd);
if (!ret) {
rprintf(FERROR,"Error parsing options (unsupported option?) - aborting\n");
exit_cleanup(RERR_SYNTAX);
}
start_server(fd, fd, argc, argp);
return 0;
@@ -298,7 +343,7 @@ static int start_daemon(int fd)
extern int remote_version;
if (!lp_load(config_file, 0)) {
exit_cleanup(1);
exit_cleanup(RERR_SYNTAX);
}
set_socket_options(fd,"SO_KEEPALIVE");
@@ -308,7 +353,7 @@ static int start_daemon(int fd)
io_printf(fd,"@RSYNCD: %d\n", PROTOCOL_VERSION);
motd = lp_motd_file();
if (*motd) {
if (motd && *motd) {
FILE *f = fopen(motd,"r");
while (f && !feof(f)) {
int len = fread(line, 1, sizeof(line)-1, f);
@@ -361,6 +406,7 @@ static int start_daemon(int fd)
int daemon_main(void)
{
extern char *config_file;
char *pid_file;
/* this ensures that we don't call getcwd after the chroot,
which doesn't work on platforms that use popen("pwd","r")
@@ -368,7 +414,18 @@ int daemon_main(void)
push_dir("/", 0);
if (is_a_socket(STDIN_FILENO)) {
/* we are running via inetd */
int i;
/* we are running via inetd - close off stdout and
stderr so that library functions (and getopt) don't
try to use them. Redirect them to /dev/null */
for (i=1;i<3;i++) {
close(i);
open("/dev/null", O_RDWR);
}
set_nonblocking(STDIN_FILENO);
return start_daemon(STDIN_FILENO);
}
@@ -376,13 +433,26 @@ int daemon_main(void)
if (!lp_load(config_file, 1)) {
fprintf(stderr,"failed to load config file %s\n", config_file);
exit_cleanup(1);
exit_cleanup(RERR_SYNTAX);
}
log_open();
rprintf(FINFO,"rsyncd version %s starting\n",VERSION);
if (((pid_file = lp_pid_file()) != NULL) && (*pid_file != '\0')) {
FILE *f;
int pid = (int) getpid();
cleanup_set_pid(pid);
if ((f = fopen(lp_pid_file(), "w")) == NULL) {
cleanup_set_pid(0);
fprintf(stderr,"failed to create pid file %s\n", pid_file);
exit_cleanup(RERR_FILEIO);
}
fprintf(f, "%d\n", pid);
fclose(f);
}
start_accept_loop(rsync_port, start_daemon);
return -1;
}

View File

@@ -53,7 +53,8 @@ void setup_protocol(int f_out,int f_in)
if (remote_version < MIN_PROTOCOL_VERSION ||
remote_version > MAX_PROTOCOL_VERSION) {
rprintf(FERROR,"protocol version mismatch - is your shell clean?\n");
exit_cleanup(1);
rprintf(FERROR,"(see the rsync man page for an explanation)\n");
exit_cleanup(RERR_PROTOCOL);
}
if (verbose > 2)

627
config.guess vendored Executable file
View File

@@ -0,0 +1,627 @@
#! /bin/sh
# Attempt to guess a canonical system name.
# Copyright (C) 1992, 93, 94, 95, 1996 Free Software Foundation, Inc.
#
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# Written by Per Bothner <bothner@cygnus.com>.
# The master version of this file is at the FSF in /home/gd/gnu/lib.
#
# This script attempts to guess a canonical system name similar to
# config.sub. If it succeeds, it prints the system name on stdout, and
# exits with 0. Otherwise, it exits with 1.
#
# The plan is that this can be called by configure scripts if you
# don't specify an explicit system type (host/target name).
#
# Only a few systems have been added to this list; please add others
# (but try to keep the structure clean).
#
# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
# (ghazi@noc.rutgers.edu 8/24/94.)
if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
PATH=$PATH:/.attbin ; export PATH
fi
UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
trap 'rm -f dummy.c dummy.o dummy; exit 1' 1 2 15
# Note: order is significant - the case branches are not exclusive.
case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
news*:NEWS-OS:6.*:*)
echo mips-sony-newsos6
exit 0 ;;
alpha:OSF1:*:*)
# A Vn.n version is a released version.
# A Tn.n version is a released field test version.
# A Xn.n version is an unreleased experimental baselevel.
# 1.2 uses "1.2" for uname -r.
echo alpha-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//'`
exit 0 ;;
21064:Windows_NT:50:3)
echo alpha-dec-winnt3.5
exit 0 ;;
Amiga*:UNIX_System_V:4.0:*)
echo m68k-cbm-sysv4
exit 0;;
amiga:NetBSD:*:*)
echo m68k-cbm-netbsd${UNAME_RELEASE}
exit 0 ;;
amiga:OpenBSD:*:*)
echo m68k-cbm-openbsd${UNAME_RELEASE}
exit 0 ;;
arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
echo arm-acorn-riscix${UNAME_RELEASE}
exit 0;;
Pyramid*:OSx*:*:*)
if test "`(/bin/universe) 2>/dev/null`" = att ; then
echo pyramid-pyramid-sysv3
else
echo pyramid-pyramid-bsd
fi
exit 0 ;;
sun4*:SunOS:5.*:*)
echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit 0 ;;
i86pc:SunOS:5.*:*)
echo i386-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit 0 ;;
sun4*:SunOS:6*:*)
# According to config.sub, this is the proper way to canonicalize
# SunOS6. Hard to guess exactly what SunOS6 will be like, but
# it's likely to be more like Solaris than SunOS4.
echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit 0 ;;
sun4*:SunOS:*:*)
case "`/usr/bin/arch -k`" in
Series*|S4*)
UNAME_RELEASE=`uname -v`
;;
esac
# Japanese Language versions have a version number like `4.1.3-JL'.
echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
exit 0 ;;
sun3*:SunOS:*:*)
echo m68k-sun-sunos${UNAME_RELEASE}
exit 0 ;;
atari*:NetBSD:*:*)
echo m68k-atari-netbsd${UNAME_RELEASE}
exit 0 ;;
atari*:OpenBSD:*:*)
echo m68k-atari-openbsd${UNAME_RELEASE}
exit 0 ;;
sun3*:NetBSD:*:*)
echo m68k-sun-netbsd${UNAME_RELEASE}
exit 0 ;;
sun3*:OpenBSD:*:*)
echo m68k-sun-openbsd${UNAME_RELEASE}
exit 0 ;;
mac68k:NetBSD:*:*)
echo m68k-apple-netbsd${UNAME_RELEASE}
exit 0 ;;
mac68k:OpenBSD:*:*)
echo m68k-apple-openbsd${UNAME_RELEASE}
exit 0 ;;
RISC*:ULTRIX:*:*)
echo mips-dec-ultrix${UNAME_RELEASE}
exit 0 ;;
VAX*:ULTRIX*:*:*)
echo vax-dec-ultrix${UNAME_RELEASE}
exit 0 ;;
mips:*:4*:UMIPS)
echo mips-mips-riscos4sysv
exit 0 ;;
mips:*:5*:RISCos)
echo mips-mips-riscos${UNAME_RELEASE}
exit 0 ;;
Night_Hawk:Power_UNIX:*:*)
echo powerpc-harris-powerunix
exit 0 ;;
m88k:CX/UX:7*:*)
echo m88k-harris-cxux7
exit 0 ;;
m88k:*:4*:R4*)
echo m88k-motorola-sysv4
exit 0 ;;
m88k:*:3*:R3*)
echo m88k-motorola-sysv3
exit 0 ;;
AViiON:dgux:*:*)
# DG/UX returns AViiON for all architectures
UNAME_PROCESSOR=`/usr/bin/uname -p`
if [ $UNAME_PROCESSOR = mc88100 -o $UNAME_PROCESSOR = mc88110 ] ; then
if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx \
-o ${TARGET_BINARY_INTERFACE}x = x ] ; then
echo m88k-dg-dgux${UNAME_RELEASE}
else
echo m88k-dg-dguxbcs${UNAME_RELEASE}
fi
else echo i586-dg-dgux${UNAME_RELEASE}
fi
exit 0 ;;
M88*:DolphinOS:*:*) # DolphinOS (SVR3)
echo m88k-dolphin-sysv3
exit 0 ;;
M88*:*:R3*:*)
# Delta 88k system running SVR3
echo m88k-motorola-sysv3
exit 0 ;;
XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
echo m88k-tektronix-sysv3
exit 0 ;;
Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
echo m68k-tektronix-bsd
exit 0 ;;
*:IRIX*:*:*)
echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
exit 0 ;;
????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX '
i[34]86:AIX:*:*)
echo i386-ibm-aix
exit 0 ;;
*:AIX:2:3)
if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
sed 's/^ //' << EOF >dummy.c
#include <sys/systemcfg.h>
main()
{
if (!__power_pc())
exit(1);
puts("powerpc-ibm-aix3.2.5");
exit(0);
}
EOF
${CC-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0
rm -f dummy.c dummy
echo rs6000-ibm-aix3.2.5
elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
echo rs6000-ibm-aix3.2.4
else
echo rs6000-ibm-aix3.2
fi
exit 0 ;;
*:AIX:*:4)
if /usr/sbin/lsattr -EHl proc0 | grep POWER >/dev/null 2>&1; then
IBM_ARCH=rs6000
else
IBM_ARCH=powerpc
fi
if [ -x /usr/bin/oslevel ] ; then
IBM_REV=`/usr/bin/oslevel`
else
IBM_REV=4.${UNAME_RELEASE}
fi
echo ${IBM_ARCH}-ibm-aix${IBM_REV}
exit 0 ;;
*:AIX:*:*)
echo rs6000-ibm-aix
exit 0 ;;
ibmrt:4.4BSD:*|romp-ibm:BSD:*)
echo romp-ibm-bsd4.4
exit 0 ;;
ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC NetBSD and
echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
exit 0 ;; # report: romp-ibm BSD 4.3
*:BOSX:*:*)
echo rs6000-bull-bosx
exit 0 ;;
DPX/2?00:B.O.S.:*:*)
echo m68k-bull-sysv3
exit 0 ;;
9000/[34]??:4.3bsd:1.*:*)
echo m68k-hp-bsd
exit 0 ;;
hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
echo m68k-hp-bsd4.4
exit 0 ;;
9000/[3478]??:HP-UX:*:*)
case "${UNAME_MACHINE}" in
9000/31? ) HP_ARCH=m68000 ;;
9000/[34]?? ) HP_ARCH=m68k ;;
9000/7?? | 9000/8?[679] ) HP_ARCH=hppa1.1 ;;
9000/8?? ) HP_ARCH=hppa1.0 ;;
esac
HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
echo ${HP_ARCH}-hp-hpux${HPUX_REV}
exit 0 ;;
3050*:HI-UX:*:*)
sed 's/^ //' << EOF >dummy.c
#include <unistd.h>
int
main ()
{
long cpu = sysconf (_SC_CPU_VERSION);
/* The order matters, because CPU_IS_HP_MC68K erroneously returns
true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
results, however. */
if (CPU_IS_PA_RISC (cpu))
{
switch (cpu)
{
case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
default: puts ("hppa-hitachi-hiuxwe2"); break;
}
}
else if (CPU_IS_HP_MC68K (cpu))
puts ("m68k-hitachi-hiuxwe2");
else puts ("unknown-hitachi-hiuxwe2");
exit (0);
}
EOF
${CC-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0
rm -f dummy.c dummy
echo unknown-hitachi-hiuxwe2
exit 0 ;;
9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
echo hppa1.1-hp-bsd
exit 0 ;;
9000/8??:4.3bsd:*:*)
echo hppa1.0-hp-bsd
exit 0 ;;
hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
echo hppa1.1-hp-osf
exit 0 ;;
hp8??:OSF1:*:*)
echo hppa1.0-hp-osf
exit 0 ;;
parisc*:Lites*:*:*)
echo hppa1.1-hp-lites
exit 0 ;;
C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
echo c1-convex-bsd
exit 0 ;;
C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
if getsysinfo -f scalar_acc
then echo c32-convex-bsd
else echo c2-convex-bsd
fi
exit 0 ;;
C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
echo c34-convex-bsd
exit 0 ;;
C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
echo c38-convex-bsd
exit 0 ;;
C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
echo c4-convex-bsd
exit 0 ;;
CRAY*T3E:*:*:*)
echo t3e-cray-unicos_mk
exit 0 ;;
CRAY*X-MP:*:*:*)
echo xmp-cray-unicos
exit 0 ;;
CRAY*Y-MP:*:*:*)
echo ymp-cray-unicos${UNAME_RELEASE}
exit 0 ;;
CRAY*C90:*:*:*)
echo c90-cray-unicos${UNAME_RELEASE}
exit 0 ;;
CRAY*TS:*:*:*)
echo t90-cray-unicos${UNAME_RELEASE}
exit 0 ;;
CRAY-2:*:*:*)
echo cray2-cray-unicos
exit 0 ;;
hp3[0-9][05]:NetBSD:*:*)
echo m68k-hp-netbsd${UNAME_RELEASE}
exit 0 ;;
hp3[0-9][05]:OpenBSD:*:*)
echo m68k-hp-openbsd${UNAME_RELEASE}
exit 0 ;;
i[34]86:BSD/386:*:* | *:BSD/OS:*:*)
echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
exit 0 ;;
*:FreeBSD:*:*)
echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
exit 0 ;;
*:NetBSD:*:*)
echo ${UNAME_MACHINE}-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
exit 0 ;;
*:OpenBSD:*:*)
echo ${UNAME_MACHINE}-unknown-openbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
exit 0 ;;
i*:CYGWIN*:*)
echo i386-unknown-cygwin32
exit 0 ;;
p*:CYGWIN*:*)
echo powerpcle-unknown-cygwin32
exit 0 ;;
prep*:SunOS:5.*:*)
echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit 0 ;;
*:GNU:*:*)
echo `echo ${UNAME_MACHINE}|sed -e 's,/.*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
exit 0 ;;
*:Linux:*:*)
# The BFD linker knows what the default object file format is, so
# first see if it will tell us.
ld_help_string=`ld --help 2>&1`
if echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: elf_i[345]86"; then
echo "${UNAME_MACHINE}-unknown-linux" ; exit 0
elif echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: i[345]86linux"; then
echo "${UNAME_MACHINE}-unknown-linuxaout" ; exit 0
elif echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: i[345]86coff"; then
echo "${UNAME_MACHINE}-unknown-linuxcoff" ; exit 0
elif echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: m68kelf"; then
echo "${UNAME_MACHINE}-unknown-linux" ; exit 0
elif echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: m68klinux"; then
echo "${UNAME_MACHINE}-unknown-linuxaout" ; exit 0
elif test "${UNAME_MACHINE}" = "alpha" ; then
echo alpha-unknown-linux ; exit 0
else
# Either a pre-BFD a.out linker (linuxoldld) or one that does not give us
# useful --help. Gcc wants to distinguish between linuxoldld and linuxaout.
test ! -d /usr/lib/ldscripts/. \
&& echo "${UNAME_MACHINE}-unknown-linuxoldld" && exit 0
# Determine whether the default compiler is a.out or elf
cat >dummy.c <<EOF
main(argc, argv)
int argc;
char *argv[];
{
#ifdef __ELF__
printf ("%s-unknown-linux\n", argv[1]);
#else
printf ("%s-unknown-linuxaout\n", argv[1]);
#endif
return 0;
}
EOF
${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy "${UNAME_MACHINE}" && rm dummy.c dummy && exit 0
rm -f dummy.c dummy
fi ;;
# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. earlier versions
# are messed up and put the nodename in both sysname and nodename.
i[34]86:DYNIX/ptx:4*:*)
echo i386-sequent-sysv4
exit 0 ;;
i[34]86:*:4.*:* | i[34]86:SYSTEM_V:4.*:*)
if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
echo ${UNAME_MACHINE}-univel-sysv${UNAME_RELEASE}
else
echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}
fi
exit 0 ;;
i[34]86:*:3.2:*)
if test -f /usr/options/cb.name; then
UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
echo ${UNAME_MACHINE}-unknown-isc$UNAME_REL
elif /bin/uname -X 2>/dev/null >/dev/null ; then
UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')`
(/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486
(/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \
&& UNAME_MACHINE=i586
echo ${UNAME_MACHINE}-unknown-sco$UNAME_REL
else
echo ${UNAME_MACHINE}-unknown-sysv32
fi
exit 0 ;;
Intel:Mach:3*:*)
echo i386-unknown-mach3
exit 0 ;;
paragon:*:*:*)
echo i860-intel-osf1
exit 0 ;;
i860:*:4.*:*) # i860-SVR4
if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
else # Add other i860-SVR4 vendors below as they are discovered.
echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
fi
exit 0 ;;
mini*:CTIX:SYS*5:*)
# "miniframe"
echo m68010-convergent-sysv
exit 0 ;;
M680[234]0:*:R3V[567]*:*)
test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
3[34]??:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0)
uname -p 2>/dev/null | grep 86 >/dev/null \
&& echo i486-ncr-sysv4.3 && exit 0 ;;
3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
uname -p 2>/dev/null | grep 86 >/dev/null \
&& echo i486-ncr-sysv4 && exit 0 ;;
m680[234]0:LynxOS:2.[23]*:*)
echo m68k-lynx-lynxos${UNAME_RELEASE}
exit 0 ;;
mc68030:UNIX_System_V:4.*:*)
echo m68k-atari-sysv4
exit 0 ;;
i[34]86:LynxOS:2.[23]*:*)
echo i386-lynx-lynxos${UNAME_RELEASE}
exit 0 ;;
TSUNAMI:LynxOS:2.[23]*:*)
echo sparc-lynx-lynxos${UNAME_RELEASE}
exit 0 ;;
rs6000:LynxOS:2.[23]*:*)
echo rs6000-lynx-lynxos${UNAME_RELEASE}
exit 0 ;;
RM*:SINIX-*:*:*)
echo mips-sni-sysv4
exit 0 ;;
*:SINIX-*:*:*)
if uname -p 2>/dev/null >/dev/null ; then
UNAME_MACHINE=`(uname -p) 2>/dev/null`
echo ${UNAME_MACHINE}-sni-sysv4
else
echo ns32k-sni-sysv
fi
exit 0 ;;
mc68*:A/UX:*:*)
echo m68k-apple-aux${UNAME_RELEASE}
exit 0 ;;
R3000:*System_V*:*:*)
if [ -d /usr/nec ]; then
echo mips-nec-sysv${UNAME_RELEASE}
else
echo mips-unknown-sysv${UNAME_RELEASE}
fi
exit 0 ;;
esac
#echo '(No uname command or uname output not recognized.)' 1>&2
#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
cat >dummy.c <<EOF
#ifdef _SEQUENT_
# include <sys/types.h>
# include <sys/utsname.h>
#endif
main ()
{
#if defined (sony)
#if defined (MIPSEB)
/* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
I don't know.... */
printf ("mips-sony-bsd\n"); exit (0);
#else
#include <sys/param.h>
printf ("m68k-sony-newsos%s\n",
#ifdef NEWSOS4
"4"
#else
""
#endif
); exit (0);
#endif
#endif
#if defined (__arm) && defined (__acorn) && defined (__unix)
printf ("arm-acorn-riscix"); exit (0);
#endif
#if defined (hp300) && !defined (hpux)
printf ("m68k-hp-bsd\n"); exit (0);
#endif
#if defined (NeXT)
#if !defined (__ARCHITECTURE__)
#define __ARCHITECTURE__ "m68k"
#endif
int version;
version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
printf ("%s-next-nextstep%s\n", __ARCHITECTURE__, version==2 ? "2" : "3");
exit (0);
#endif
#if defined (MULTIMAX) || defined (n16)
#if defined (UMAXV)
printf ("ns32k-encore-sysv\n"); exit (0);
#else
#if defined (CMU)
printf ("ns32k-encore-mach\n"); exit (0);
#else
printf ("ns32k-encore-bsd\n"); exit (0);
#endif
#endif
#endif
#if defined (__386BSD__)
printf ("i386-unknown-bsd\n"); exit (0);
#endif
#if defined (sequent)
#if defined (i386)
printf ("i386-sequent-dynix\n"); exit (0);
#endif
#if defined (ns32000)
printf ("ns32k-sequent-dynix\n"); exit (0);
#endif
#endif
#if defined (_SEQUENT_)
struct utsname un;
uname(&un);
if (strncmp(un.version, "V2", 2) == 0) {
printf ("i386-sequent-ptx2\n"); exit (0);
}
if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
printf ("i386-sequent-ptx1\n"); exit (0);
}
printf ("i386-sequent-ptx\n"); exit (0);
#endif
#if defined (vax)
#if !defined (ultrix)
printf ("vax-dec-bsd\n"); exit (0);
#else
printf ("vax-dec-ultrix\n"); exit (0);
#endif
#endif
#if defined (alliant) && defined (i860)
printf ("i860-alliant-bsd\n"); exit (0);
#endif
exit (1);
}
EOF
${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy && rm dummy.c dummy && exit 0
rm -f dummy.c dummy
# Apollos put the system type in the environment.
test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; }
# Convex versions that predate uname can use getsysinfo(1)
if [ -x /usr/convex/getsysinfo ]
then
case `getsysinfo -f cpu_type` in
c1*)
echo c1-convex-bsd
exit 0 ;;
c2*)
if getsysinfo -f scalar_acc
then echo c32-convex-bsd
else echo c2-convex-bsd
fi
exit 0 ;;
c34*)
echo c34-convex-bsd
exit 0 ;;
c38*)
echo c38-convex-bsd
exit 0 ;;
c4*)
echo c4-convex-bsd
exit 0 ;;
esac
fi
#echo '(Unable to guess system type)' 1>&2
exit 1

1099
config.sub vendored Executable file
View File

File diff suppressed because it is too large Load Diff

View File

@@ -2,6 +2,9 @@ dnl Process this file with autoconf to produce a configure script.
AC_INIT(byteorder.h)
AC_CONFIG_HEADER(config.h)
AC_CANONICAL_SYSTEM
AC_VALIDATE_CACHE_SYSTEM_TYPE
dnl Checks for programs.
AC_PROG_CC
AC_PROG_INSTALL
@@ -10,12 +13,14 @@ AC_SUBST(SHELL)
AC_CHECK_PROG(HAVE_REMSH, remsh, 1, 0)
AC_DEFINE_UNQUOTED(HAVE_REMSH, $HAVE_REMSH)
AC_C_BIGENDIAN
AC_HEADER_DIRENT
AC_HEADER_TIME
AC_HEADER_SYS_WAIT
AC_CHECK_HEADERS(sys/fcntl.h sys/select.h fcntl.h sys/time.h sys/unistd.h unistd.h utime.h grp.h)
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)
AC_CHECK_SIZEOF(int)
AC_CHECK_SIZEOF(long)
@@ -32,16 +37,18 @@ AC_TYPE_PID_T
AC_STRUCT_ST_RDEV
AC_CHECK_TYPE(ino_t,unsigned)
echo $ac_n "checking for errno in errno.h... $ac_c"
AC_TRY_COMPILE([#include <errno.h>],[int i = errno],
echo yes; AC_DEFINE(HAVE_ERRNO_DECL),
echo no)
AC_CACHE_CHECK([for errno in errno.h],rsync_cv_errno, [
AC_TRY_COMPILE([#include <errno.h>],[int i = errno],
rsync_cv_errno=yes,rsync_cv_have_errno_decl=no)])
if test x"$rsync_cv_errno" = x"yes"; then
AC_DEFINE(HAVE_ERRNO_DECL)
fi
AC_FUNC_MEMCMP
AC_FUNC_UTIME_NULL
AC_CHECK_FUNCS(mmap munmap waitpid getcwd strdup strerror chown chmod mknod)
AC_CHECK_FUNCS(fchmod fstat strchr bcopy bzero readlink link utime utimes)
AC_CHECK_FUNCS(memmove getopt_long lchown setlinebuf vsnprintf setsid glob strpbrk)
AC_CHECK_FUNCS(fchmod fstat strchr readlink link utime utimes strftime)
AC_CHECK_FUNCS(memmove getopt_long lchown vsnprintf snprintf setsid glob strpbrk)
echo $ac_n "checking for working fnmatch... $ac_c"
AC_TRY_RUN([#include <fnmatch.h>
@@ -49,40 +56,73 @@ main() { exit(fnmatch("*.o", "x.o", 0) == 0? 0: 1); }],
echo yes;AC_DEFINE(HAVE_FNMATCH),
echo no)
echo $ac_n "checking for long long ... $ac_c"
AC_CACHE_CHECK([for long long],rsync_cv_have_longlong,[
AC_TRY_RUN([#include <stdio.h>
main() { long long x = 1000000; x *= x; exit(((x/1000000) == 1000000)? 0: 1); }],
echo yes;AC_DEFINE(HAVE_LONGLONG),
echo no)
rsync_cv_have_longlong=yes,rsync_cv_have_longlong=no,rsync_cv_have_longlong=cross)])
if test x"$rsync_cv_have_longlong" = x"yes"; then
AC_DEFINE(HAVE_LONGLONG)
fi
echo $ac_n "checking for off64_t ... $ac_c"
AC_CACHE_CHECK([for off64_t],rsync_cv_HAVE_OFF64_T,[
AC_TRY_RUN([#include <stdio.h>
#include <sys/stat.h>
main() { struct stat64 st; off64_t s; if (sizeof(off_t) == sizeof(off64_t)) return 1; exit((lstat64("/dev/null", &st)==0)?0:1); }],
echo yes;AC_DEFINE(HAVE_OFF64_T),
main() { struct stat64 st; off64_t s; if (sizeof(off_t) == sizeof(off64_t)) exit(1); exit((lstat64("/dev/null", &st)==0)?0:1); }],
rsync_cv_HAVE_OFF64_T=yes,rsync_cv_HAVE_OFF64_T=no,rsync_cv_HAVE_OFF64_T=cross)])
if test x"$rsync_cv_HAVE_OFF64_T" = x"yes"; then
AC_DEFINE(HAVE_OFF64_T)
fi
echo $ac_n "checking for short ino_t ... $ac_c"
AC_TRY_RUN([#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
main() { if (sizeof(ino_t) < sizeof(unsigned int)) return 0; return 1; }],
echo yes;AC_DEFINE(HAVE_SHORT_INO_T),
echo no)
echo $ac_n "checking for unsigned char ... $ac_c"
AC_CACHE_CHECK([for unsigned char],rsync_cv_HAVE_UNSIGNED_CHAR,[
AC_TRY_RUN([#include <stdio.h>
main() { char c; c=250; exit((c > 0)?0:1); }],
echo yes;AC_DEFINE(HAVE_UNSIGNED_CHAR),
echo no)
rsync_cv_HAVE_UNSIGNED_CHAR=yes,rsync_cv_HAVE_UNSIGNED_CHAR=no,rsync_cv_HAVE_UNSIGNED_CHAR=cross)])
if test x"$rsync_cv_HAVE_UNSIGNED_CHAR" = x"yes"; then
AC_DEFINE(HAVE_UNSIGNED_CHAR)
fi
echo $ac_n "checking for broken readdir ... $ac_c"
AC_CACHE_CHECK([for broken readdir],rsync_cv_HAVE_BROKEN_READDIR,[
AC_TRY_RUN([#include <sys/types.h>
#include <dirent.h>
main() { struct dirent *di; DIR *d = opendir("."); di = readdir(d);
if (di && di->d_name[-2] == '.' && di->d_name[-1] == 0 &&
di->d_name[0] == 0) return 0; return 1;} ],
echo yes - you are using the broken /usr/ucb/cc;AC_DEFINE(HAVE_BROKEN_READDIR),
echo no)
di->d_name[0] == 0) exit(0); exit(1);} ],
rsync_cv_HAVE_BROKEN_READDIR=yes,rsync_cv_HAVE_BROKEN_READDIR=no,rsync_cv_HAVE_BROKEN_READDIR=cross)])
if test x"$rsync_cv_HAVE_BROKEN_READDIR" = x"yes"; then
AC_DEFINE(HAVE_BROKEN_READDIR)
fi
echo $ac_n "checking for utimbuf ... $ac_c"
AC_CACHE_CHECK([for utimbuf],rsync_cv_HAVE_UTIMBUF,[
AC_TRY_COMPILE([#include <sys/types.h>
#include <utime.h>],
[struct utimbuf tbuf; tbuf.actime = 0; tbuf.modtime = 1; return utime("foo.c",&tbuf);],
echo yes;AC_DEFINE(HAVE_UTIMBUF),
echo no)
[struct utimbuf tbuf; tbuf.actime = 0; tbuf.modtime = 1; exit(utime("foo.c",&tbuf));],
rsync_cv_HAVE_UTIMBUF=yes,rsync_cv_HAVE_UTIMBUF=no,rsync_cv_HAVE_UTIMBUF=cross)])
if test x"$rsync_cv_HAVE_UTIMBUF" = x"yes"; then
AC_DEFINE(HAVE_UTIMBUF)
fi
AC_CACHE_CHECK([for broken inet_ntoa],rsync_cv_REPLACE_INET_NTOA,[
AC_TRY_RUN([
#include <stdio.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
main() { struct in_addr ip; ip.s_addr = 0x12345678;
if (strcmp(inet_ntoa(ip),"18.52.86.120") &&
strcmp(inet_ntoa(ip),"120.86.52.18")) { exit(0); }
exit(1);}],
rsync_cv_REPLACE_INET_NTOA=yes,rsync_cv_REPLACE_INET_NTOA=no,rsync_cv_REPLACE_INET_NTOA=cross)])
if test x"$rsync_cv_REPLACE_INET_NTOA" = x"yes"; then
AC_DEFINE(REPLACE_INET_NTOA)
fi
# The following test taken from the cvs sources
# If we can't find connect, try looking in -lsocket, -lnsl, and -linet.
@@ -90,30 +130,58 @@ echo no)
# libsocket.so which has a bad implementation of gethostbyname (it
# only looks in /etc/hosts), so we only look for -lsocket if we need
# it.
AC_CHECK_FUNC(connect, :,
[case "$LIBS" in
*-lnsl*) ;;
*) AC_CHECK_LIB(nsl_s, printf) ;;
esac
case "$LIBS" in
*-lnsl*) ;;
*) AC_CHECK_LIB(nsl, printf) ;;
esac
case "$LIBS" in
*-lsocket*) ;;
*) AC_CHECK_LIB(socket, connect) ;;
esac
case "$LIBS" in
*-linet*) ;;
*) AC_CHECK_LIB(inet, connect) ;;
esac
dnl We can't just call AC_CHECK_FUNCS(connect) here, because the value
dnl has been cached.
if test "$ac_cv_lib_socket_connect" = "yes" ||
test "$ac_cv_lib_inet_connect" = "yes"; then
ac_cv_func_connect=yes
AC_DEFINE(HAVE_CONNECT)
fi])
AC_CHECK_FUNCS(connect)
if test x"$ac_cv_func_connect" = x"no"; then
case "$LIBS" in
*-lnsl*) ;;
*) AC_CHECK_LIB(nsl_s, printf) ;;
esac
case "$LIBS" in
*-lnsl*) ;;
*) AC_CHECK_LIB(nsl, printf) ;;
esac
case "$LIBS" in
*-lsocket*) ;;
*) AC_CHECK_LIB(socket, connect) ;;
esac
case "$LIBS" in
*-linet*) ;;
*) AC_CHECK_LIB(inet, connect) ;;
esac
dnl We can't just call AC_CHECK_FUNCS(connect) here, because the value
dnl has been cached.
if test x"$ac_cv_lib_socket_connect" = x"yes" ||
test x"$ac_cv_lib_inet_connect" = x"yes"; then
# ac_cv_func_connect=yes
# don't! it would cause AC_CHECK_FUNC to succeed next time configure is run
AC_DEFINE(HAVE_CONNECT)
fi
fi
#
# The following test was mostly taken from the tcl/tk plus patches
#
echo $ac_n "checking whether -c -o works ... $ac_c"
rm -rf conftest*
cat > conftest.$ac_ext <<EOF
int main() { return 0; }
EOF
${CC-cc} -c -o conftest..o conftest.$ac_ext
if test -f conftest..o; then
OBJ_SAVE="#"
OBJ_RESTORE="#"
CC_SHOBJ_FLAG='-o $@'
echo yes
else
OBJ_SAVE=' @b=`basename $@ .o`;rm -f $$b.o.sav;if test -f $$b.o; then mv $$b.o $$b.o.sav;fi;'
OBJ_RESTORE=' @b=`basename $@ .o`;if test "$$b.o" != "$@"; then mv $$b.o $@; if test -f $$b.o.sav; then mv $$b.o.sav $$b.o; fi; fi'
CC_SHOBJ_FLAG=""
echo no
fi
rm -rf conftest*
AC_SUBST(OBJ_SAVE)
AC_SUBST(OBJ_RESTORE)
AC_SUBST(CC_SHOBJ_FLAG)
AC_OUTPUT(Makefile lib/dummy zlib/dummy)

View File

@@ -29,7 +29,7 @@ int claim_connection(char *fname,int max_connections)
if (max_connections <= 0)
return 1;
fd = open(fname,O_RDWR|O_CREAT, 0600);
if (fd == -1) {
@@ -41,6 +41,9 @@ int claim_connection(char *fname,int max_connections)
if (lock_range(fd, i*4, 4)) return 1;
}
/* only interested in open failures */
errno = 0;
close(fd);
return 0;
}

18
errcode.h Normal file
View File

@@ -0,0 +1,18 @@
/* error codes returned by rsync */
#define RERR_SYNTAX 1 /* syntax or usage error */
#define RERR_PROTOCOL 2 /* protocol incompatibility */
#define RERR_FILESELECT 3 /* errors selecting input/output files, dirs */
#define RERR_NOSUPPORT 4 /* requested action not supported */
#define RERR_SOCKETIO 10 /* error in socket IO */
#define RERR_FILEIO 11 /* error in file IO */
#define RERR_STREAMIO 12 /* error in rsync protocol data stream */
#define RERR_MESSAGEIO 13 /* errors with program diagnostics */
#define RERR_IPC 14 /* error in IPC code */
#define RERR_SIGNAL 20 /* status returned when sent SIGUSR1, SIGINT */
#define RERR_WAITCHILD 21 /* some error returned by waitpid() */
#define RERR_MALLOC 22 /* error allocating core memory buffers */
#define RERR_TIMEOUT 30 /* timeout in data send/receive */

View File

@@ -26,6 +26,47 @@ extern int verbose;
static struct exclude_struct **exclude_list;
/*
* Optimization for special case when all included files are explicitly
* listed without wildcards in the "exclude" list followed by a "- *"
* to exclude the rest.
* Contributed by Dave Dykstra <dwd@bell-labs.com>
*/
static int only_included_files = 1;
static struct exclude_struct *exclude_the_rest;
int send_included_file_names(int f,struct file_list *flist)
{
struct exclude_struct *ex, **ex_list;
int n;
char *p;
if (!only_included_files || (exclude_the_rest == NULL))
return 0;
if (verbose > 1) {
rprintf(FINFO,"(using include-only optimization) ");
}
/* set exclude_list to NULL temporarily so check_exclude */
/* will always return true */
ex_list = exclude_list;
exclude_list = NULL;
for (n=0; (ex = ex_list[n]) != NULL; n++) {
if (ex == exclude_the_rest)
break;
p = ex->pattern;
while (*p == '/') {
/* skip the allowed beginning slashes */
p++;
}
send_file_name(f,flist,p,0,0);
}
exclude_list = ex_list;
return 1;
}
/* build an exclude structure given a exclude pattern */
static struct exclude_struct *make_exclude(char *pattern, int include)
{
@@ -36,8 +77,6 @@ static struct exclude_struct *make_exclude(char *pattern, int include)
memset(ret, 0, sizeof(*ret));
ret->orig = strdup(pattern);
if (strncmp(pattern,"- ",2) == 0) {
pattern += 2;
} else if (strncmp(pattern,"+ ",2) == 0) {
@@ -49,9 +88,18 @@ static struct exclude_struct *make_exclude(char *pattern, int include)
ret->pattern = strdup(pattern);
if (!ret->orig || !ret->pattern) out_of_memory("make_exclude");
if (!ret->pattern) out_of_memory("make_exclude");
if (strpbrk(pattern, "*[?")) ret->regular_exp = 1;
if (strpbrk(pattern, "*[?")) {
if (!ret->include && (*pattern == '*') && (*(pattern+1) == '\0')) {
exclude_the_rest = ret;
} else {
only_included_files = 0;
}
ret->regular_exp = 1;
} else if (!ret->include) {
only_included_files = 0;
}
if (strlen(pattern) > 1 && pattern[strlen(pattern)-1] == '/') {
ret->pattern[strlen(pattern)-1] = 0;
@@ -67,7 +115,6 @@ static struct exclude_struct *make_exclude(char *pattern, int include)
static void free_exclude(struct exclude_struct *ex)
{
free(ex->orig);
free(ex->pattern);
memset(ex,0,sizeof(*ex));
free(ex);
@@ -143,6 +190,8 @@ void add_exclude_list(char *pattern,struct exclude_struct ***list, int include)
}
free((*list));
*list = NULL;
only_included_files = 1;
exclude_the_rest = NULL;
return;
}
@@ -172,7 +221,7 @@ struct exclude_struct **make_exclude_list(char *fname,
if (!f) {
if (fatal) {
rprintf(FERROR,"%s : %s\n",fname,strerror(errno));
exit_cleanup(1);
exit_cleanup(RERR_FILEIO);
}
return list;
}
@@ -207,23 +256,21 @@ void send_exclude_list(int f)
}
for (i=0;exclude_list[i];i++) {
char *pattern = exclude_list[i]->orig;
char *pattern = exclude_list[i]->pattern;
int l;
if (remote_version < 19) {
if (strncmp(pattern,"+ ", 2)==0) {
rprintf(FERROR,"remote rsync does not support include syntax - aborting\n");
exit_cleanup(1);
}
if (strncmp(pattern,"- ", 2) == 0) {
pattern += 2;
}
}
l = strlen(pattern);
if (l == 0) continue;
write_int(f,l);
if (exclude_list[i]->include) {
if (remote_version < 19) {
rprintf(FERROR,"remote rsync does not support include syntax - aborting\n");
exit_cleanup(RERR_NOSUPPORT);
}
write_int(f,l+2);
write_buf(f,"+ ",2);
} else {
write_int(f,l);
}
write_buf(f,pattern,l);
}

View File

@@ -136,7 +136,7 @@ char *map_ptr(struct map_struct *map,OFF_T offset,int len)
}
if (munmap(map->map, map->p_len) != 0) {
rprintf(FERROR,"munmap failed : %s\n", strerror(errno));
exit_cleanup(1);
exit_cleanup(RERR_MALLOC);
}
/* align the mmap region on a nice boundary back a bit from
@@ -186,7 +186,7 @@ char *map_ptr(struct map_struct *map,OFF_T offset,int len)
if (do_lseek(map->fd,offset,SEEK_SET) != offset) {
rprintf(FERROR,"lseek failed in map_ptr\n");
exit_cleanup(1);
exit_cleanup(RERR_FILEIO);
}
if ((nread=read(map->fd,map->p,len)) != len) {

444
flist.c
View File

@@ -49,6 +49,38 @@ extern int io_error;
static struct exclude_struct **local_exclude_list;
static void clean_flist(struct file_list *flist, int strip_root);
static void list_file_entry(struct file_struct *f)
{
char perms[11] = "----------";
char *perm_map = "rwxrwxrwx";
int i;
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,
(double)f->length, timestring(f->modtime),
f_name(f), f->link);
} else {
rprintf(FINFO,"%s %11.0f %s %s\n",
perms,
(double)f->length, timestring(f->modtime), f_name(f));
}
}
int link_stat(const char *Path, STRUCT_STAT *Buffer)
{
#if SUPPORT_LINKS
@@ -87,102 +119,119 @@ static void set_filesystem(char *fname)
}
static int to_wire_mode(mode_t mode)
{
if (S_ISLNK(mode) && (S_IFLNK != 0120000)) {
return (mode & ~(_S_IFMT)) | 0120000;
}
return (int)mode;
}
static mode_t from_wire_mode(int mode)
{
if ((mode & (_S_IFMT)) == 0120000 && (S_IFLNK != 0120000)) {
return (mode & ~(_S_IFMT)) | S_IFLNK;
}
return (mode_t)mode;
}
static void send_directory(int f,struct file_list *flist,char *dir);
static char *flist_dir;
void send_file_entry(struct file_struct *file,int f,unsigned base_flags)
static void send_file_entry(struct file_struct *file,int f,unsigned base_flags)
{
unsigned char flags;
static time_t last_time;
static mode_t last_mode;
static dev_t last_rdev;
static uid_t last_uid;
static gid_t last_gid;
static char lastname[MAXPATHLEN];
char *fname;
int l1,l2;
unsigned char flags;
static time_t last_time;
static mode_t last_mode;
static dev_t last_rdev;
static uid_t last_uid;
static gid_t last_gid;
static char lastname[MAXPATHLEN];
char *fname;
int l1,l2;
if (f == -1) return;
if (f == -1) return;
if (!file) {
write_byte(f,0);
return;
}
if (!file) {
write_byte(f,0);
return;
}
fname = f_name(file);
fname = f_name(file);
flags = base_flags;
flags = base_flags;
if (file->mode == last_mode) flags |= SAME_MODE;
if (file->rdev == last_rdev) flags |= SAME_RDEV;
if (file->uid == last_uid) flags |= SAME_UID;
if (file->gid == last_gid) flags |= SAME_GID;
if (file->modtime == last_time) flags |= SAME_TIME;
if (file->mode == last_mode) flags |= SAME_MODE;
if (file->rdev == last_rdev) flags |= SAME_RDEV;
if (file->uid == last_uid) flags |= SAME_UID;
if (file->gid == last_gid) flags |= SAME_GID;
if (file->modtime == last_time) flags |= SAME_TIME;
for (l1=0;lastname[l1] && (fname[l1] == lastname[l1]) && (l1 < 255);l1++) ;
l2 = strlen(fname) - l1;
for (l1=0;lastname[l1] && (fname[l1] == lastname[l1]) && (l1 < 255);l1++) ;
l2 = strlen(fname) - l1;
if (l1 > 0) flags |= SAME_NAME;
if (l2 > 255) flags |= LONG_NAME;
if (l1 > 0) flags |= SAME_NAME;
if (l2 > 255) flags |= LONG_NAME;
/* we must make sure we don't send a zero flags byte or the other
end will terminate the flist transfer */
if (flags == 0 && !S_ISDIR(file->mode)) flags |= FLAG_DELETE;
if (flags == 0) flags |= LONG_NAME;
/* we must make sure we don't send a zero flags byte or the other
end will terminate the flist transfer */
if (flags == 0 && !S_ISDIR(file->mode)) flags |= FLAG_DELETE;
if (flags == 0) flags |= LONG_NAME;
write_byte(f,flags);
if (flags & SAME_NAME)
write_byte(f,l1);
if (flags & LONG_NAME)
write_int(f,l2);
else
write_byte(f,l2);
write_buf(f,fname+l1,l2);
write_byte(f,flags);
if (flags & SAME_NAME)
write_byte(f,l1);
if (flags & LONG_NAME)
write_int(f,l2);
else
write_byte(f,l2);
write_buf(f,fname+l1,l2);
write_longint(f,file->length);
if (!(flags & SAME_TIME))
write_int(f,(int)file->modtime);
if (!(flags & SAME_MODE))
write_int(f,(int)file->mode);
if (preserve_uid && !(flags & SAME_UID)) {
add_uid(file->uid);
write_int(f,(int)file->uid);
}
if (preserve_gid && !(flags & SAME_GID)) {
add_gid(file->gid);
write_int(f,(int)file->gid);
}
if (preserve_devices && IS_DEVICE(file->mode) && !(flags & SAME_RDEV))
write_int(f,(int)file->rdev);
write_longint(f,file->length);
if (!(flags & SAME_TIME))
write_int(f,(int)file->modtime);
if (!(flags & SAME_MODE))
write_int(f,to_wire_mode(file->mode));
if (preserve_uid && !(flags & SAME_UID)) {
add_uid(file->uid);
write_int(f,(int)file->uid);
}
if (preserve_gid && !(flags & SAME_GID)) {
add_gid(file->gid);
write_int(f,(int)file->gid);
}
if (preserve_devices && IS_DEVICE(file->mode) && !(flags & SAME_RDEV))
write_int(f,(int)file->rdev);
#if SUPPORT_LINKS
if (preserve_links && S_ISLNK(file->mode)) {
write_int(f,strlen(file->link));
write_buf(f,file->link,strlen(file->link));
}
if (preserve_links && S_ISLNK(file->mode)) {
write_int(f,strlen(file->link));
write_buf(f,file->link,strlen(file->link));
}
#endif
#if SUPPORT_HARD_LINKS
if (preserve_hard_links && S_ISREG(file->mode)) {
write_int(f,(int)file->dev);
write_int(f,(int)file->inode);
}
if (preserve_hard_links && S_ISREG(file->mode)) {
write_int(f,(int)file->dev);
write_int(f,(int)file->inode);
}
#endif
if (always_checksum) {
write_buf(f,file->sum,csum_length);
}
if (always_checksum) {
write_buf(f,file->sum,csum_length);
}
last_mode = file->mode;
last_rdev = file->rdev;
last_uid = file->uid;
last_gid = file->gid;
last_time = file->modtime;
last_mode = file->mode;
last_rdev = file->rdev;
last_uid = file->uid;
last_gid = file->gid;
last_time = file->modtime;
strlcpy(lastname,fname,MAXPATHLEN-1);
lastname[MAXPATHLEN-1] = 0;
strlcpy(lastname,fname,MAXPATHLEN-1);
lastname[MAXPATHLEN-1] = 0;
}
@@ -190,101 +239,102 @@ void send_file_entry(struct file_struct *file,int f,unsigned base_flags)
static void receive_file_entry(struct file_struct **fptr,
unsigned flags,int f)
{
static time_t last_time;
static mode_t last_mode;
static dev_t last_rdev;
static uid_t last_uid;
static gid_t last_gid;
static char lastname[MAXPATHLEN];
char thisname[MAXPATHLEN];
int l1=0,l2=0;
char *p;
struct file_struct *file;
static time_t last_time;
static mode_t last_mode;
static dev_t last_rdev;
static uid_t last_uid;
static gid_t last_gid;
static char lastname[MAXPATHLEN];
char thisname[MAXPATHLEN];
int l1=0,l2=0;
char *p;
struct file_struct *file;
if (flags & SAME_NAME)
l1 = read_byte(f);
if (flags & SAME_NAME)
l1 = read_byte(f);
if (flags & LONG_NAME)
l2 = read_int(f);
else
l2 = read_byte(f);
if (flags & LONG_NAME)
l2 = read_int(f);
else
l2 = read_byte(f);
file = (struct file_struct *)malloc(sizeof(*file));
if (!file) out_of_memory("receive_file_entry");
bzero((char *)file,sizeof(*file));
(*fptr) = file;
file = (struct file_struct *)malloc(sizeof(*file));
if (!file) out_of_memory("receive_file_entry");
memset((char *)file, 0, sizeof(*file));
(*fptr) = file;
if (l2 >= MAXPATHLEN-l1) overflow("receive_file_entry");
if (l2 >= MAXPATHLEN-l1) overflow("receive_file_entry");
strlcpy(thisname,lastname,l1);
read_sbuf(f,&thisname[l1],l2);
thisname[l1+l2] = 0;
strlcpy(thisname,lastname,l1);
read_sbuf(f,&thisname[l1],l2);
thisname[l1+l2] = 0;
strlcpy(lastname,thisname,MAXPATHLEN-1);
lastname[MAXPATHLEN-1] = 0;
strlcpy(lastname,thisname,MAXPATHLEN-1);
lastname[MAXPATHLEN-1] = 0;
clean_fname(thisname);
clean_fname(thisname);
if (relative_paths && thisname[0] == '/') {
/* strip / off absolute paths in destination */
memmove(thisname, thisname+1, strlen(thisname));
if (!thisname[0]) strcpy(thisname,".");
}
if ((p = strrchr(thisname,'/'))) {
static char *lastdir;
*p = 0;
if (lastdir && strcmp(thisname, lastdir)==0) {
file->dirname = lastdir;
} else {
file->dirname = strdup(thisname);
lastdir = file->dirname;
}
file->basename = strdup(p+1);
} else {
file->dirname = NULL;
file->basename = strdup(thisname);
}
if ((p = strrchr(thisname,'/'))) {
static char *lastdir;
*p = 0;
if (lastdir && strcmp(thisname, lastdir)==0) {
file->dirname = lastdir;
} else {
file->dirname = strdup(thisname);
lastdir = file->dirname;
}
file->basename = strdup(p+1);
} else {
file->dirname = NULL;
file->basename = strdup(thisname);
}
if (!file->basename) out_of_memory("receive_file_entry 1");
if (!file->basename) out_of_memory("receive_file_entry 1");
file->flags = flags;
file->length = read_longint(f);
file->modtime = (flags & SAME_TIME) ? last_time : (time_t)read_int(f);
file->mode = (flags & SAME_MODE) ? last_mode : (mode_t)read_int(f);
if (preserve_uid)
file->uid = (flags & SAME_UID) ? last_uid : (uid_t)read_int(f);
if (preserve_gid)
file->gid = (flags & SAME_GID) ? last_gid : (gid_t)read_int(f);
if (preserve_devices && IS_DEVICE(file->mode))
file->rdev = (flags & SAME_RDEV) ? last_rdev : (dev_t)read_int(f);
file->flags = flags;
file->length = read_longint(f);
file->modtime = (flags & SAME_TIME) ? last_time : (time_t)read_int(f);
file->mode = (flags & SAME_MODE) ? last_mode : from_wire_mode(read_int(f));
if (preserve_uid)
file->uid = (flags & SAME_UID) ? last_uid : (uid_t)read_int(f);
if (preserve_gid)
file->gid = (flags & SAME_GID) ? last_gid : (gid_t)read_int(f);
if (preserve_devices && IS_DEVICE(file->mode))
file->rdev = (flags & SAME_RDEV) ? last_rdev : (dev_t)read_int(f);
if (preserve_links && S_ISLNK(file->mode)) {
int l = read_int(f);
file->link = (char *)malloc(l+1);
if (!file->link) out_of_memory("receive_file_entry 2");
read_sbuf(f,file->link,l);
}
if (preserve_links && S_ISLNK(file->mode)) {
int l = read_int(f);
file->link = (char *)malloc(l+1);
if (!file->link) out_of_memory("receive_file_entry 2");
read_sbuf(f,file->link,l);
}
#if SUPPORT_HARD_LINKS
if (preserve_hard_links && S_ISREG(file->mode)) {
file->dev = read_int(f);
file->inode = read_int(f);
}
if (preserve_hard_links && S_ISREG(file->mode)) {
file->dev = read_int(f);
file->inode = read_int(f);
}
#endif
if (always_checksum) {
file->sum = (char *)malloc(MD4_SUM_LENGTH);
if (!file->sum) out_of_memory("md4 sum");
read_buf(f,file->sum,csum_length);
}
if (always_checksum) {
file->sum = (char *)malloc(MD4_SUM_LENGTH);
if (!file->sum) out_of_memory("md4 sum");
read_buf(f,file->sum,csum_length);
}
last_mode = file->mode;
last_rdev = file->rdev;
last_uid = file->uid;
last_gid = file->gid;
last_time = file->modtime;
last_mode = file->mode;
last_rdev = file->rdev;
last_uid = file->uid;
last_gid = file->gid;
last_time = file->modtime;
if (!preserve_perms) {
extern int orig_umask;
/* set an appropriate set of permissions based on original
permissions and umask. This emulates what GNU cp does */
file->mode &= ~orig_umask;
}
}
@@ -325,7 +375,7 @@ static struct file_struct *make_file(char *fname)
clean_fname(cleaned_name);
fname = cleaned_name;
bzero(sum,SUM_LENGTH);
memset(sum,0,SUM_LENGTH);
if (link_stat(fname,&st) != 0) {
io_error = 1;
@@ -352,7 +402,7 @@ static struct file_struct *make_file(char *fname)
file = (struct file_struct *)malloc(sizeof(*file));
if (!file) out_of_memory("make_file");
bzero((char *)file,sizeof(*file));
memset((char *)file,0,sizeof(*file));
if ((p = strrchr(fname,'/'))) {
static char *lastdir;
@@ -429,7 +479,7 @@ static struct file_struct *make_file(char *fname)
static void send_file_name(int f,struct file_list *flist,char *fname,
void send_file_name(int f,struct file_list *flist,char *fname,
int recursive, unsigned base_flags)
{
struct file_struct *file;
@@ -495,6 +545,8 @@ static void send_directory(int f,struct file_list *flist,char *dir)
}
p = fname + strlen(fname);
local_exclude_list = NULL;
if (cvs_exclude) {
if (strlen(fname) + strlen(".cvsignore") <= MAXPATHLEN-1) {
strcpy(p,".cvsignore");
@@ -514,6 +566,10 @@ static void send_directory(int f,struct file_list *flist,char *dir)
send_file_name(f,flist,fname,recurse,0);
}
if (local_exclude_list) {
add_exclude_list("!", &local_exclude_list, 0);
}
closedir(d);
}
@@ -523,7 +579,7 @@ struct file_list *send_file_list(int f,int argc,char *argv[])
{
int i,l;
STRUCT_STAT st;
char *p,*dir;
char *p,*dir,*olddir;
char lastpath[MAXPATHLEN]="";
struct file_list *flist;
int64 start_write;
@@ -571,6 +627,7 @@ struct file_list *send_file_list(int f,int argc,char *argv[])
}
dir = NULL;
olddir = NULL;
if (!relative_paths) {
p = strrchr(fname,'/');
@@ -606,7 +663,7 @@ struct file_list *send_file_list(int f,int argc,char *argv[])
fname = ".";
if (dir && *dir) {
char *olddir = push_dir(dir, 1);
olddir = push_dir(dir, 1);
if (!olddir) {
io_error=1;
@@ -616,21 +673,22 @@ struct file_list *send_file_list(int f,int argc,char *argv[])
}
flist_dir = dir;
if (one_file_system)
set_filesystem(fname);
send_file_name(f,flist,fname,recurse,FLAG_DELETE);
flist_dir = NULL;
if (pop_dir(olddir) != 0) {
rprintf(FERROR,"pop_dir %s : %s\n",
dir,strerror(errno));
exit_cleanup(1);
}
continue;
}
if (one_file_system)
set_filesystem(fname);
send_file_name(f,flist,fname,recurse,FLAG_DELETE);
if (!recurse || !send_included_file_names(f,flist))
send_file_name(f,flist,fname,recurse,FLAG_DELETE);
if (olddir != NULL) {
flist_dir = NULL;
if (pop_dir(olddir) != 0) {
rprintf(FERROR,"pop_dir %s : %s\n",
dir,strerror(errno));
exit_cleanup(RERR_FILESELECT);
}
}
}
if (f != -1) {
@@ -640,7 +698,7 @@ struct file_list *send_file_list(int f,int argc,char *argv[])
if (verbose && recurse && !am_server && f != -1)
rprintf(FINFO,"done\n");
clean_flist(flist);
clean_flist(flist, 0);
/* now send the uid/gid list. This was introduced in protocol
version 15 */
@@ -671,6 +729,7 @@ struct file_list *recv_file_list(int f)
struct file_list *flist;
unsigned char flags;
int64 start_read;
extern int list_only;
if (verbose && recurse && !am_server) {
rprintf(FINFO,"receiving file list ... ");
@@ -721,7 +780,7 @@ struct file_list *recv_file_list(int f)
if (verbose > 2)
rprintf(FINFO,"received %d names\n",flist->count);
clean_flist(flist);
clean_flist(flist, relative_paths);
if (verbose && recurse && !am_server) {
rprintf(FINFO,"done\n");
@@ -737,6 +796,14 @@ struct file_list *recv_file_list(int f)
io_error |= read_int(f);
}
if (list_only) {
int i;
for (i=0;i<flist->count;i++) {
list_file_entry(flist->files[i]);
}
}
if (verbose > 2)
rprintf(FINFO,"recv_file_list done\n");
@@ -794,7 +861,7 @@ static void free_file(struct file_struct *file)
if (file->basename) free(file->basename);
if (file->link) free(file->link);
if (file->sum) free(file->sum);
bzero((char *)file, sizeof(*file));
memset((char *)file, 0, sizeof(*file));
}
@@ -808,9 +875,9 @@ void flist_free(struct file_list *flist)
free_file(flist->files[i]);
free(flist->files[i]);
}
bzero((char *)flist->files, sizeof(flist->files[0])*flist->count);
memset((char *)flist->files, 0, sizeof(flist->files[0])*flist->count);
free(flist->files);
bzero((char *)flist, sizeof(*flist));
memset((char *)flist, 0, sizeof(*flist));
free(flist);
}
@@ -819,7 +886,7 @@ void flist_free(struct file_list *flist)
* This routine ensures we don't have any duplicate names in our file list.
* duplicate names can cause corruption because of the pipelining
*/
void clean_flist(struct file_list *flist)
static void clean_flist(struct file_list *flist, int strip_root)
{
int i;
@@ -841,6 +908,37 @@ void clean_flist(struct file_list *flist)
free_file(flist->files[i]);
}
}
if (strip_root) {
/* we need to strip off the root directory in the case
of relative paths, but this must be done _after_
the sorting phase */
for (i=0;i<flist->count;i++) {
if (flist->files[i]->dirname &&
flist->files[i]->dirname[0] == '/') {
memmove(&flist->files[i]->dirname[0],
&flist->files[i]->dirname[1],
strlen(flist->files[i]->dirname));
}
if (flist->files[i]->dirname &&
!flist->files[i]->dirname[0]) {
flist->files[i]->dirname = NULL;
}
}
}
if (verbose <= 3) return;
for (i=0;i<flist->count;i++) {
rprintf(FINFO,"[%d] i=%d %s %s mode=0%o len=%d\n",
getpid(), i,
NS(flist->files[i]->dirname),
NS(flist->files[i]->basename),
flist->files[i]->mode,
(int)flist->files[i]->length);
}
}
@@ -858,7 +956,9 @@ char *f_name(struct file_struct *f)
n = (n+1)%10;
if (f->dirname) {
slprintf(p, MAXPATHLEN-1, "%s/%s", f->dirname, f->basename);
strlcpy(p, f->dirname, MAXPATHLEN-1);
strlcat(p, "/", MAXPATHLEN-1);
strlcat(p, f->basename, MAXPATHLEN-1);
} else {
strlcpy(p, f->basename, MAXPATHLEN-1);
}

420
generator.c Normal file
View File

@@ -0,0 +1,420 @@
/*
Copyright (C) Andrew Tridgell 1996
Copyright (C) Paul Mackerras 1996
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "rsync.h"
extern int verbose;
extern int dry_run;
extern int relative_paths;
extern int preserve_links;
extern int am_root;
extern int preserve_devices;
extern int preserve_hard_links;
extern int update_only;
extern int whole_file;
extern int block_size;
extern int csum_length;
extern int ignore_times;
extern int io_timeout;
extern int remote_version;
extern int always_checksum;
/* choose whether to skip a particular file */
static int skip_file(char *fname,
struct file_struct *file, STRUCT_STAT *st)
{
if (st->st_size != file->length) {
return 0;
}
/* if always checksum is set then we use the checksum instead
of the file time to determine whether to sync */
if (always_checksum && S_ISREG(st->st_mode)) {
char sum[MD4_SUM_LENGTH];
file_checksum(fname,sum,st->st_size);
return (memcmp(sum,file->sum,csum_length) == 0);
}
if (ignore_times) {
return 0;
}
return (st->st_mtime == file->modtime);
}
/* use a larger block size for really big files */
static int adapt_block_size(struct file_struct *file, int bsize)
{
int ret;
if (bsize != BLOCK_SIZE) return bsize;
ret = file->length / (10000); /* rough heuristic */
ret = ret & ~15; /* multiple of 16 */
if (ret < bsize) ret = bsize;
if (ret > CHUNK_SIZE/2) ret = CHUNK_SIZE/2;
return ret;
}
/*
send a sums struct down a fd
*/
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)
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);
}
}
/*
generate a stream of signatures/checksums that describe a buffer
generate approximately one checksum every n bytes
*/
static struct sum_struct *generate_sums(struct map_struct *buf,OFF_T len,int n)
{
int i;
struct sum_struct *s;
int count;
int block_len = n;
int remainder = (len%block_len);
OFF_T offset = 0;
count = (len+(block_len-1))/block_len;
s = (struct sum_struct *)malloc(sizeof(*s));
if (!s) out_of_memory("generate_sums");
s->count = count;
s->remainder = remainder;
s->n = n;
s->flength = len;
if (count==0) {
s->sums = NULL;
return s;
}
if (verbose > 3)
rprintf(FINFO,"count=%d rem=%d n=%d flength=%d\n",
s->count,s->remainder,s->n,(int)s->flength);
s->sums = (struct sum_buf *)malloc(sizeof(s->sums[0])*s->count);
if (!s->sums) out_of_memory("generate_sums");
for (i=0;i<count;i++) {
int n1 = MIN(len,n);
char *map = map_ptr(buf,offset,n1);
s->sums[i].sum1 = get_checksum1(map,n1);
get_checksum2(map,n1,s->sums[i].sum2);
s->sums[i].offset = offset;
s->sums[i].len = n1;
s->sums[i].i = i;
if (verbose > 3)
rprintf(FINFO,"chunk[%d] offset=%d len=%d sum1=%08x\n",
i,(int)s->sums[i].offset,s->sums[i].len,s->sums[i].sum1);
len -= n1;
offset += n1;
}
return s;
}
void recv_generator(char *fname,struct file_list *flist,int i,int f_out)
{
int fd;
STRUCT_STAT st;
struct map_struct *buf;
struct sum_struct *s;
int statret;
struct file_struct *file = flist->files[i];
char *fnamecmp;
char fnamecmpbuf[MAXPATHLEN];
extern char *compare_dest;
extern int list_only;
if (list_only) return;
if (verbose > 2)
rprintf(FINFO,"recv_generator(%s,%d)\n",fname,i);
statret = link_stat(fname,&st);
if (S_ISDIR(file->mode)) {
if (dry_run) return;
if (statret == 0 && !S_ISDIR(st.st_mode)) {
if (do_unlink(fname) != 0) {
rprintf(FERROR,"unlink %s : %s\n",fname,strerror(errno));
return;
}
statret = -1;
}
if (statret != 0 && do_mkdir(fname,file->mode) != 0 && errno != EEXIST) {
if (!(relative_paths && errno==ENOENT &&
create_directory_path(fname)==0 &&
do_mkdir(fname,file->mode)==0)) {
rprintf(FERROR,"mkdir %s : %s (2)\n",
fname,strerror(errno));
}
}
if (set_perms(fname,file,NULL,0) && verbose)
rprintf(FINFO,"%s/\n",fname);
return;
}
if (preserve_links && S_ISLNK(file->mode)) {
#if SUPPORT_LINKS
char lnk[MAXPATHLEN];
int l;
extern int safe_symlinks;
if (safe_symlinks && unsafe_symlink(file->link, fname)) {
if (verbose) {
rprintf(FINFO,"ignoring unsafe symlink %s -> %s\n",
fname,file->link);
}
return;
}
if (statret == 0) {
l = readlink(fname,lnk,MAXPATHLEN-1);
if (l > 0) {
lnk[l] = 0;
if (strcmp(lnk,file->link) == 0) {
set_perms(fname,file,&st,1);
return;
}
}
}
delete_file(fname);
if (do_symlink(file->link,fname) != 0) {
rprintf(FERROR,"link %s -> %s : %s\n",
fname,file->link,strerror(errno));
} else {
set_perms(fname,file,NULL,0);
if (verbose) {
rprintf(FINFO,"%s -> %s\n",
fname,file->link);
}
}
#endif
return;
}
#ifdef HAVE_MKNOD
if (am_root && preserve_devices && IS_DEVICE(file->mode)) {
if (statret != 0 ||
st.st_mode != file->mode ||
st.st_rdev != file->rdev) {
delete_file(fname);
if (verbose > 2)
rprintf(FINFO,"mknod(%s,0%o,0x%x)\n",
fname,(int)file->mode,(int)file->rdev);
if (do_mknod(fname,file->mode,file->rdev) != 0) {
rprintf(FERROR,"mknod %s : %s\n",fname,strerror(errno));
} else {
set_perms(fname,file,NULL,0);
if (verbose)
rprintf(FINFO,"%s\n",fname);
}
} else {
set_perms(fname,file,&st,1);
}
return;
}
#endif
if (preserve_hard_links && check_hard_link(file)) {
if (verbose > 1)
rprintf(FINFO,"%s is a hard link\n",f_name(file));
return;
}
if (!S_ISREG(file->mode)) {
rprintf(FINFO,"skipping non-regular file %s\n",fname);
return;
}
fnamecmp = fname;
if ((statret == -1) && (compare_dest != NULL)) {
/* try the file at compare_dest instead */
int saveerrno = errno;
slprintf(fnamecmpbuf,MAXPATHLEN-1,"%s/%s",compare_dest,fname);
statret = link_stat(fnamecmpbuf,&st);
if (!S_ISREG(st.st_mode))
statret = -1;
if (statret == -1)
errno = saveerrno;
else
fnamecmp = fnamecmpbuf;
}
if (statret == -1) {
if (errno == ENOENT) {
write_int(f_out,i);
if (!dry_run) send_sums(NULL,f_out);
} else {
if (verbose > 1)
rprintf(FERROR,"recv_generator failed to open %s\n",fname);
}
return;
}
if (!S_ISREG(st.st_mode)) {
if (delete_file(fname) != 0) {
return;
}
/* now pretend the file didn't exist */
write_int(f_out,i);
if (!dry_run) send_sums(NULL,f_out);
return;
}
if (update_only && st.st_mtime > file->modtime && fnamecmp == fname) {
if (verbose > 1)
rprintf(FINFO,"%s is newer\n",fname);
return;
}
if (skip_file(fname, file, &st)) {
set_perms(fname,file,&st,1);
return;
}
if (dry_run) {
write_int(f_out,i);
return;
}
if (whole_file) {
write_int(f_out,i);
send_sums(NULL,f_out);
return;
}
/* open the file */
fd = open(fnamecmp,O_RDONLY);
if (fd == -1) {
rprintf(FERROR,"failed to open %s : %s\n",fnamecmp,strerror(errno));
rprintf(FERROR,"skipping %s\n",fname);
return;
}
if (st.st_size > 0) {
buf = map_file(fd,st.st_size);
} else {
buf = NULL;
}
if (verbose > 3)
rprintf(FINFO,"gen mapped %s of size %d\n",fnamecmp,(int)st.st_size);
s = generate_sums(buf,st.st_size,adapt_block_size(file, block_size));
if (verbose > 2)
rprintf(FINFO,"sending sums for %d\n",i);
write_int(f_out,i);
send_sums(s,f_out);
close(fd);
if (buf) unmap_file(buf);
free_sums(s);
}
void generate_files(int f,struct file_list *flist,char *local_name,int f_recv)
{
int i;
int phase=0;
if (verbose > 2)
rprintf(FINFO,"generator starting pid=%d count=%d\n",
(int)getpid(),flist->count);
for (i = 0; i < flist->count; i++) {
struct file_struct *file = flist->files[i];
mode_t saved_mode = file->mode;
if (!file->basename) continue;
/* we need to ensure that any directories we create have writeable
permissions initially so that we can create the files within
them. This is then fixed after the files are transferred */
if (!am_root && S_ISDIR(file->mode)) {
file->mode |= S_IWUSR; /* user write */
}
recv_generator(local_name?local_name:f_name(file),
flist,i,f);
file->mode = saved_mode;
}
phase++;
csum_length = SUM_LENGTH;
ignore_times=1;
if (verbose > 2)
rprintf(FINFO,"generate_files phase=%d\n",phase);
write_int(f,-1);
/* we expect to just sit around now, so don't exit on a
timeout. If we really get a timeout then the other process should
exit */
io_timeout = 0;
if (remote_version >= 13) {
/* in newer versions of the protocol the files can cycle through
the system more than once to catch initial checksum errors */
for (i=read_int(f_recv); i != -1; i=read_int(f_recv)) {
struct file_struct *file = flist->files[i];
recv_generator(local_name?local_name:f_name(file),
flist,i,f);
}
phase++;
if (verbose > 2)
rprintf(FINFO,"generate_files phase=%d\n",phase);
write_int(f,-1);
}
}

View File

@@ -56,7 +56,7 @@ void init_hard_links(struct file_list *flist)
out_of_memory("init_hard_links");
for (i = 0; i < flist->count; i++)
bcopy(flist->files[i], &hlink_list[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]),

106
io.c
View File

@@ -24,6 +24,9 @@
*/
#include "rsync.h"
/* if no timeout is specified then use a 60 second select timeout */
#define SELECT_TIMEOUT 60
static int io_multiplexing_out;
static int io_multiplexing_in;
static int multiplex_in_fd;
@@ -54,10 +57,10 @@ static void check_timeout(void)
t = time(NULL);
if (last_io && io_timeout && (t-last_io)>io_timeout) {
rprintf(FERROR,"read timeout after %d second - exiting\n",
if (last_io && io_timeout && (t-last_io) >= io_timeout) {
rprintf(FERROR,"io timeout after %d second - exiting\n",
(int)(t-last_io));
exit_cleanup(1);
exit_cleanup(RERR_TIMEOUT);
}
}
@@ -67,6 +70,7 @@ static char *read_buffer_p;
static int read_buffer_len;
static int read_buffer_size;
static int no_flush;
static int no_flush_read;
/* read from a socket with IO timeout. return the number of
bytes read. If no bytes can be read then exit, never return
@@ -75,7 +79,9 @@ static int read_timeout(int fd, char *buf, int len)
{
int n, ret=0;
no_flush_read++;
io_flush();
no_flush_read--;
while (ret == 0) {
fd_set fds;
@@ -83,11 +89,10 @@ static int read_timeout(int fd, char *buf, int len)
FD_ZERO(&fds);
FD_SET(fd, &fds);
tv.tv_sec = io_timeout;
tv.tv_sec = io_timeout?io_timeout:SELECT_TIMEOUT;
tv.tv_usec = 0;
if (select(fd+1, &fds, NULL, NULL,
io_timeout?&tv:NULL) != 1) {
if (select(fd+1, &fds, NULL, NULL, &tv) != 1) {
check_timeout();
continue;
}
@@ -95,7 +100,6 @@ static int read_timeout(int fd, char *buf, int len)
n = read(fd, buf, len);
if (n > 0) {
stats.total_read += n;
buf += n;
len -= n;
ret += n;
@@ -108,15 +112,24 @@ static int read_timeout(int fd, char *buf, int len)
continue;
}
if (n == -1 &&
(errno == EAGAIN || errno == EWOULDBLOCK)) {
/* this shouldn't happen, if it does then
sleep for a short time to prevent us
chewing too much CPU */
u_sleep(100);
continue;
}
if (n == 0) {
if (eof_error) {
rprintf(FERROR,"EOF in read_timeout\n");
rprintf(FERROR,"unexpected EOF in read_timeout\n");
}
exit_cleanup(1);
exit_cleanup(RERR_STREAMIO);
}
rprintf(FERROR,"read error: %s\n", strerror(errno));
exit_cleanup(1);
exit_cleanup(RERR_STREAMIO);
}
return ret;
@@ -168,13 +181,13 @@ static int read_unbuffered(int fd, char *buf, int len)
if (tag != FERROR && tag != FINFO) {
rprintf(FERROR,"unexpected tag %d\n", tag);
exit_cleanup(1);
exit_cleanup(RERR_STREAMIO);
}
if (remaining > sizeof(line)-1) {
rprintf(FERROR,"multiplexing overflow %d\n\n",
remaining);
exit_cleanup(1);
exit_cleanup(RERR_STREAMIO);
}
read_loop(fd, line, remaining);
@@ -229,7 +242,7 @@ static void readfd(int fd,char *buffer,int N)
int ret;
int total=0;
if (read_buffer_len < N && N < 1024) {
if ((read_buffer_len < N) && (N < 1024)) {
read_check(buffer_f_in);
}
@@ -243,19 +256,27 @@ static void readfd(int fd,char *buffer,int N)
continue;
}
no_flush_read++;
io_flush();
no_flush_read--;
ret = read_unbuffered(fd,buffer + total,N-total);
total += ret;
}
stats.total_read += total;
}
int32 read_int(int f)
{
char b[4];
int32 ret;
readfd(f,b,4);
return IVAL(b,0);
ret = IVAL(b,0);
if (ret == (int32)0xffffffff) return -1;
return ret;
}
int64 read_longint(int f)
@@ -265,11 +286,13 @@ int64 read_longint(int f)
char b[8];
ret = read_int(f);
if ((int32)ret != (int32)0xffffffff) return ret;
if ((int32)ret != (int32)0xffffffff) {
return ret;
}
#ifdef NO_INT64
rprintf(FERROR,"Integer overflow - attempted 64 bit offset\n");
exit_cleanup(1);
exit_cleanup(RERR_UNSUPPORTED);
#else
if (remote_version >= 16) {
readfd(f,b,8);
@@ -309,59 +332,68 @@ static void writefd_unbuffered(int fd,char *buf,int len)
fd_set w_fds, r_fds;
int fd_count, count;
struct timeval tv;
int reading;
int reading=0;
int blocked=0;
no_flush++;
reading = (buffer_f_in != -1 && read_buffer_len < MAX_READ_BUFFER);
while (total < len) {
FD_ZERO(&w_fds);
FD_ZERO(&r_fds);
FD_SET(fd,&w_fds);
fd_count = fd+1;
if (!no_flush_read) {
reading = (buffer_f_in != -1);
}
if (reading) {
FD_SET(buffer_f_in,&r_fds);
if (buffer_f_in > fd)
fd_count = buffer_f_in+1;
}
tv.tv_sec = io_timeout;
tv.tv_sec = io_timeout?io_timeout:SELECT_TIMEOUT;
tv.tv_usec = 0;
count = select(fd_count,
reading?&r_fds:NULL,
&w_fds,NULL,
io_timeout?&tv:NULL);
&tv);
if (count <= 0) {
check_timeout();
continue;
}
if (reading && FD_ISSET(buffer_f_in, &r_fds)) {
read_check(buffer_f_in);
}
if (FD_ISSET(fd, &w_fds)) {
int ret = write(fd,buf+total,len-total);
int n = (len-total)>>blocked;
int ret = write(fd,buf+total,n?n:1);
if (ret == -1 && errno == EINTR) {
continue;
}
if (ret <= 0) {
rprintf(FERROR,"erroring writing %d bytes - exiting\n", len);
exit_cleanup(1);
if (ret == -1 &&
(errno == EAGAIN || errno == EWOULDBLOCK)) {
blocked++;
continue;
}
if (ret <= 0) {
rprintf(FERROR,"erroring writing %d bytes - exiting\n", len);
exit_cleanup(RERR_STREAMIO);
}
blocked = 0;
total += ret;
stats.total_written += ret;
if (io_timeout)
last_io = time(NULL);
continue;
}
if (reading && FD_ISSET(buffer_f_in, &r_fds)) {
read_check(buffer_f_in);
}
}
@@ -409,6 +441,8 @@ void io_end_buffering(int fd)
static void writefd(int fd,char *buf,int len)
{
stats.total_written += len;
if (!io_buffer) {
writefd_unbuffered(fd, buf, len);
return;
@@ -445,7 +479,7 @@ void write_longint(int f, int64 x)
return;
}
write_int(f, -1);
write_int(f, (int32)0xFFFFFFFF);
SIVAL(b,0,(x&0xFFFFFFFF));
SIVAL(b,4,((x>>32)&0xFFFFFFFF));
@@ -458,7 +492,7 @@ void write_buf(int f,char *buf,int len)
}
/* write a string to the connection */
void write_sbuf(int f,char *buf)
static void write_sbuf(int f,char *buf)
{
write_buf(f, buf, strlen(buf));
}
@@ -507,7 +541,7 @@ void io_printf(int fd, const char *format, ...)
len = vslprintf(buf, sizeof(buf)-1, format, ap);
va_end(ap);
if (len < 0) exit_cleanup(1);
if (len < 0) exit_cleanup(RERR_STREAMIO);
write_sbuf(fd, buf);
}
@@ -529,7 +563,7 @@ void io_start_multiplex_in(int fd)
io_flush();
if (read_buffer_len) {
fprintf(stderr,"ERROR: data in read buffer at mplx start\n");
exit_cleanup(1);
exit_cleanup(RERR_STREAMIO);
}
io_multiplexing_in = 1;
@@ -545,6 +579,8 @@ int io_multiplex_write(int f, char *buf, int len)
SIVAL(io_buffer-4, 0, ((MPLEX_BASE + f)<<24) + len);
memcpy(io_buffer, buf, len);
stats.total_written += (len+4);
writefd_unbuffered(multiplex_out_fd, io_buffer-4, len+4);
return 1;
}

View File

@@ -54,7 +54,7 @@ pid_t waitpid(pid_t pid, int *statptr, int options)
#ifndef HAVE_MEMMOVE
void *memmove(void *dest, const void *src, size_t n)
{
bcopy(src, dest, n);
memcpy(dest, src, n);
return dest;
}
#endif
@@ -76,3 +76,19 @@ char *strpbrk(const char *s, const char *accept)
return NULL;
}
#endif
#ifdef REPLACE_INET_NTOA
char *rep_inet_ntoa(struct in_addr ip)
{
unsigned char *p = (unsigned char *)&ip.s_addr;
static char buf[18];
#if WORDS_BIGENDIAN
slprintf(buf, 17, "%d.%d.%d.%d",
(int)p[0], (int)p[1], (int)p[2], (int)p[3]);
#else
slprintf(buf, 17, "%d.%d.%d.%d",
(int)p[3], (int)p[2], (int)p[1], (int)p[0]);
#endif
return buf;
}
#endif

278
lib/mdfour.c Normal file
View File

@@ -0,0 +1,278 @@
/*
Unix SMB/Netbios implementation.
Version 1.9.
a implementation of MD4 designed for use in the SMB authentication protocol
Copyright (C) Andrew Tridgell 1997-1998.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "rsync.h"
/* NOTE: This code makes no attempt to be fast!
It assumes that a int is at least 32 bits long
*/
static struct mdfour *m;
static inline uint32 F(uint32 X, uint32 Y, uint32 Z)
{
return (X&Y) | ((~X)&Z);
}
static inline uint32 G(uint32 X, uint32 Y, uint32 Z)
{
return (X&Y) | (X&Z) | (Y&Z);
}
static inline uint32 H(uint32 X, uint32 Y, uint32 Z)
{
return X^Y^Z;
}
static inline uint32 lshift(uint32 x, int s)
{
#ifdef LARGE_INT32
x &= 0xFFFFFFFF;
return ((x<<s)&0xFFFFFFFF) | (x>>(32-s));
#else
return ((x<<s) | (x>>(32-s)));
#endif
}
#define ROUND1(a,b,c,d,k,s) a = lshift(a + F(b,c,d) + X[k], s)
#define ROUND2(a,b,c,d,k,s) a = lshift(a + G(b,c,d) + X[k] + 0x5A827999,s)
#define ROUND3(a,b,c,d,k,s) a = lshift(a + H(b,c,d) + X[k] + 0x6ED9EBA1,s)
/* this applies md4 to 64 byte chunks */
static void mdfour64(uint32 *M)
{
int j;
uint32 AA, BB, CC, DD;
uint32 X[16];
uint32 A,B,C,D;
for (j=0;j<16;j++)
X[j] = M[j];
A = m->A; B = m->B; C = m->C; D = m->D;
AA = A; BB = B; CC = C; DD = D;
ROUND1(A,B,C,D, 0, 3); ROUND1(D,A,B,C, 1, 7);
ROUND1(C,D,A,B, 2, 11); ROUND1(B,C,D,A, 3, 19);
ROUND1(A,B,C,D, 4, 3); ROUND1(D,A,B,C, 5, 7);
ROUND1(C,D,A,B, 6, 11); ROUND1(B,C,D,A, 7, 19);
ROUND1(A,B,C,D, 8, 3); ROUND1(D,A,B,C, 9, 7);
ROUND1(C,D,A,B, 10, 11); ROUND1(B,C,D,A, 11, 19);
ROUND1(A,B,C,D, 12, 3); ROUND1(D,A,B,C, 13, 7);
ROUND1(C,D,A,B, 14, 11); ROUND1(B,C,D,A, 15, 19);
ROUND2(A,B,C,D, 0, 3); ROUND2(D,A,B,C, 4, 5);
ROUND2(C,D,A,B, 8, 9); ROUND2(B,C,D,A, 12, 13);
ROUND2(A,B,C,D, 1, 3); ROUND2(D,A,B,C, 5, 5);
ROUND2(C,D,A,B, 9, 9); ROUND2(B,C,D,A, 13, 13);
ROUND2(A,B,C,D, 2, 3); ROUND2(D,A,B,C, 6, 5);
ROUND2(C,D,A,B, 10, 9); ROUND2(B,C,D,A, 14, 13);
ROUND2(A,B,C,D, 3, 3); ROUND2(D,A,B,C, 7, 5);
ROUND2(C,D,A,B, 11, 9); ROUND2(B,C,D,A, 15, 13);
ROUND3(A,B,C,D, 0, 3); ROUND3(D,A,B,C, 8, 9);
ROUND3(C,D,A,B, 4, 11); ROUND3(B,C,D,A, 12, 15);
ROUND3(A,B,C,D, 2, 3); ROUND3(D,A,B,C, 10, 9);
ROUND3(C,D,A,B, 6, 11); ROUND3(B,C,D,A, 14, 15);
ROUND3(A,B,C,D, 1, 3); ROUND3(D,A,B,C, 9, 9);
ROUND3(C,D,A,B, 5, 11); ROUND3(B,C,D,A, 13, 15);
ROUND3(A,B,C,D, 3, 3); ROUND3(D,A,B,C, 11, 9);
ROUND3(C,D,A,B, 7, 11); ROUND3(B,C,D,A, 15, 15);
A += AA; B += BB; C += CC; D += DD;
#ifdef LARGE_INT32
A &= 0xFFFFFFFF; B &= 0xFFFFFFFF;
C &= 0xFFFFFFFF; D &= 0xFFFFFFFF;
#endif
for (j=0;j<16;j++)
X[j] = 0;
m->A = A; m->B = B; m->C = C; m->D = D;
}
static void copy64(uint32 *M, unsigned char *in)
{
int i;
for (i=0;i<16;i++)
M[i] = (in[i*4+3]<<24) | (in[i*4+2]<<16) |
(in[i*4+1]<<8) | (in[i*4+0]<<0);
}
static void copy4(unsigned char *out,uint32 x)
{
out[0] = x&0xFF;
out[1] = (x>>8)&0xFF;
out[2] = (x>>16)&0xFF;
out[3] = (x>>24)&0xFF;
}
void mdfour_begin(struct mdfour *md)
{
md->A = 0x67452301;
md->B = 0xefcdab89;
md->C = 0x98badcfe;
md->D = 0x10325476;
md->totalN = 0;
}
static void mdfour_tail(unsigned char *in, int n)
{
unsigned char buf[128];
uint32 M[16];
uint32 b;
m->totalN += n;
b = m->totalN * 8;
memset(buf, 0, 128);
if (n) memcpy(buf, in, n);
buf[n] = 0x80;
if (n <= 55) {
copy4(buf+56, b);
copy64(M, buf);
mdfour64(M);
} else {
copy4(buf+120, b);
copy64(M, buf);
mdfour64(M);
copy64(M, buf+64);
mdfour64(M);
}
}
void mdfour_update(struct mdfour *md, unsigned char *in, int n)
{
uint32 M[16];
if (n == 0) mdfour_tail(in, n);
m = md;
while (n >= 64) {
copy64(M, in);
mdfour64(M);
in += 64;
n -= 64;
m->totalN += 64;
}
if (n) mdfour_tail(in, n);
}
void mdfour_result(struct mdfour *md, unsigned char *out)
{
m = md;
copy4(out, m->A);
copy4(out+4, m->B);
copy4(out+8, m->C);
copy4(out+12, m->D);
}
void mdfour(unsigned char *out, unsigned char *in, int n)
{
struct mdfour md;
mdfour_begin(&md);
mdfour_update(&md, in, n);
mdfour_result(&md, out);
}
#ifdef TEST_MDFOUR
static void file_checksum1(char *fname)
{
int fd, i;
struct mdfour md;
unsigned char buf[64], sum[16];
fd = open(fname,O_RDONLY);
if (fd == -1) {
perror("fname");
exit(1);
}
mdfour_begin(&md);
while (1) {
int n = read(fd, buf, sizeof(buf));
if (n <= 0) break;
mdfour_update(&md, buf, n);
}
close(fd);
mdfour_result(&md, sum);
for (i=0;i<16;i++)
printf("%02X", sum[i]);
printf("\n");
}
#include "../md4.h"
static void file_checksum2(char *fname)
{
int fd, i;
MDstruct md;
unsigned char buf[64], sum[16];
fd = open(fname,O_RDONLY);
if (fd == -1) {
perror("fname");
exit(1);
}
MDbegin(&md);
while (1) {
int n = read(fd, buf, sizeof(buf));
if (n <= 0) break;
MDupdate(&md, buf, n*8);
}
if (!md.done) {
MDupdate(&md, buf, 0);
}
close(fd);
memcpy(sum, md.buffer, 16);
for (i=0;i<16;i++)
printf("%02X", sum[i]);
printf("\n");
}
int main(int argc, char *argv[])
{
file_checksum1(argv[1]);
file_checksum2(argv[1]);
return 0;
}
#endif

34
lib/mdfour.h Normal file
View File

@@ -0,0 +1,34 @@
/*
Unix SMB/Netbios implementation.
Version 1.9.
a implementation of MD4 designed for use in the SMB authentication protocol
Copyright (C) Andrew Tridgell 1997-1998.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
struct mdfour {
uint32 A, B, C, D;
uint32 totalN;
};
void mdfour_begin(struct mdfour *md);
void mdfour_update(struct mdfour *md, unsigned char *in, int n);
void mdfour_result(struct mdfour *md, unsigned char *out);
void mdfour(unsigned char *out, unsigned char *in, int n);

820
lib/snprintf.c Normal file
View File

@@ -0,0 +1,820 @@
/*
* Copyright Patrick Powell 1995
* This code is based on code written by Patrick Powell (papowell@astart.com)
* It may be used for any purpose as long as this notice remains intact
* on all source code distributions
*/
/**************************************************************
* Original:
* Patrick Powell Tue Apr 11 09:48:21 PDT 1995
* A bombproof version of doprnt (dopr) included.
* Sigh. This sort of thing is always nasty do deal with. Note that
* the version here does not include floating point...
*
* snprintf() is used instead of sprintf() as it does limit checks
* for string length. This covers a nasty loophole.
*
* The other functions are there to prevent NULL pointers from
* causing nast effects.
*
* More Recently:
* Brandon Long <blong@fiction.net> 9/15/96 for mutt 0.43
* This was ugly. It is still ugly. I opted out of floating point
* numbers, but the formatter understands just about everything
* from the normal C string format, at least as far as I can tell from
* the Solaris 2.5 printf(3S) man page.
*
* Brandon Long <blong@fiction.net> 10/22/97 for mutt 0.87.1
* Ok, added some minimal floating point support, which means this
* probably requires libm on most operating systems. Don't yet
* support the exponent (e,E) and sigfig (g,G). Also, fmtint()
* was pretty badly broken, it just wasn't being exercised in ways
* which showed it, so that's been fixed. Also, formated the code
* to mutt conventions, and removed dead code left over from the
* original. Also, there is now a builtin-test, just compile with:
* gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm
* and run snprintf for results.
*
* Thomas Roessler <roessler@guug.de> 01/27/98 for mutt 0.89i
* The PGP code was using unsigned hexadecimal formats.
* Unfortunately, unsigned formats simply didn't work.
*
* Michael Elkins <me@cs.hmc.edu> 03/05/98 for mutt 0.90.8
* The original code assumed that both snprintf() and vsnprintf() were
* missing. Some systems only have snprintf() but not vsnprintf(), so
* the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF.
*
* Andrew Tridgell (tridge@samba.anu.edu.au) Oct 1998
* fixed handling of %.0f
* added test for HAVE_LONG_DOUBLE
*
**************************************************************/
#include "config.h"
#include <string.h>
# include <ctype.h>
#include <sys/types.h>
#if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF)
/* Define this as a fall through, HAVE_STDARG_H is probably already set */
#define HAVE_VARARGS_H
/* varargs declarations: */
#if defined(HAVE_STDARG_H)
# include <stdarg.h>
# define HAVE_STDARGS /* let's hope that works everywhere (mj) */
# define VA_LOCAL_DECL va_list ap
# define VA_START(f) va_start(ap, f)
# define VA_SHIFT(v,t) ; /* no-op for ANSI */
# define VA_END va_end(ap)
#else
# if defined(HAVE_VARARGS_H)
# include <varargs.h>
# undef HAVE_STDARGS
# define VA_LOCAL_DECL va_list ap
# define VA_START(f) va_start(ap) /* f is ignored! */
# define VA_SHIFT(v,t) v = va_arg(ap,t)
# define VA_END va_end(ap)
# else
/*XX ** NO VARARGS ** XX*/
# endif
#endif
#ifdef HAVE_LONG_DOUBLE
#define LDOUBLE long double
#else
#define LDOUBLE double
#endif
/*int snprintf (char *str, size_t count, const char *fmt, ...);*/
/*int vsnprintf (char *str, size_t count, const char *fmt, va_list arg);*/
static void dopr (char *buffer, size_t maxlen, const char *format,
va_list args);
static void fmtstr (char *buffer, size_t *currlen, size_t maxlen,
char *value, int flags, int min, int max);
static void fmtint (char *buffer, size_t *currlen, size_t maxlen,
long value, int base, int min, int max, int flags);
static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
LDOUBLE fvalue, int min, int max, int flags);
static void dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c );
/*
* dopr(): poor man's version of doprintf
*/
/* format read states */
#define DP_S_DEFAULT 0
#define DP_S_FLAGS 1
#define DP_S_MIN 2
#define DP_S_DOT 3
#define DP_S_MAX 4
#define DP_S_MOD 5
#define DP_S_CONV 6
#define DP_S_DONE 7
/* format flags - Bits */
#define DP_F_MINUS (1 << 0)
#define DP_F_PLUS (1 << 1)
#define DP_F_SPACE (1 << 2)
#define DP_F_NUM (1 << 3)
#define DP_F_ZERO (1 << 4)
#define DP_F_UP (1 << 5)
#define DP_F_UNSIGNED (1 << 6)
/* Conversion Flags */
#define DP_C_SHORT 1
#define DP_C_LONG 2
#define DP_C_LDOUBLE 3
#define char_to_int(p) (p - '0')
#define MAX(p,q) ((p >= q) ? p : q)
static void dopr (char *buffer, size_t maxlen, const char *format, va_list args)
{
char ch;
long value;
LDOUBLE fvalue;
char *strvalue;
int min;
int max;
int state;
int flags;
int cflags;
size_t currlen;
state = DP_S_DEFAULT;
currlen = flags = cflags = min = 0;
max = -1;
ch = *format++;
while (state != DP_S_DONE)
{
if ((ch == '\0') || (currlen >= maxlen))
state = DP_S_DONE;
switch(state)
{
case DP_S_DEFAULT:
if (ch == '%')
state = DP_S_FLAGS;
else
dopr_outch (buffer, &currlen, maxlen, ch);
ch = *format++;
break;
case DP_S_FLAGS:
switch (ch)
{
case '-':
flags |= DP_F_MINUS;
ch = *format++;
break;
case '+':
flags |= DP_F_PLUS;
ch = *format++;
break;
case ' ':
flags |= DP_F_SPACE;
ch = *format++;
break;
case '#':
flags |= DP_F_NUM;
ch = *format++;
break;
case '0':
flags |= DP_F_ZERO;
ch = *format++;
break;
default:
state = DP_S_MIN;
break;
}
break;
case DP_S_MIN:
if (isdigit((unsigned char)ch))
{
min = 10*min + char_to_int (ch);
ch = *format++;
}
else if (ch == '*')
{
min = va_arg (args, int);
ch = *format++;
state = DP_S_DOT;
}
else
state = DP_S_DOT;
break;
case DP_S_DOT:
if (ch == '.')
{
state = DP_S_MAX;
ch = *format++;
}
else
state = DP_S_MOD;
break;
case DP_S_MAX:
if (isdigit((unsigned char)ch))
{
if (max < 0)
max = 0;
max = 10*max + char_to_int (ch);
ch = *format++;
}
else if (ch == '*')
{
max = va_arg (args, int);
ch = *format++;
state = DP_S_MOD;
}
else
state = DP_S_MOD;
break;
case DP_S_MOD:
/* Currently, we don't support Long Long, bummer */
switch (ch)
{
case 'h':
cflags = DP_C_SHORT;
ch = *format++;
break;
case 'l':
cflags = DP_C_LONG;
ch = *format++;
break;
case 'L':
cflags = DP_C_LDOUBLE;
ch = *format++;
break;
default:
break;
}
state = DP_S_CONV;
break;
case DP_S_CONV:
switch (ch)
{
case 'd':
case 'i':
if (cflags == DP_C_SHORT)
value = va_arg (args, short int);
else if (cflags == DP_C_LONG)
value = va_arg (args, long int);
else
value = va_arg (args, int);
fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags);
break;
case 'o':
flags |= DP_F_UNSIGNED;
if (cflags == DP_C_SHORT)
value = va_arg (args, unsigned short int);
else if (cflags == DP_C_LONG)
value = (long)va_arg (args, unsigned long int);
else
value = (long)va_arg (args, unsigned int);
fmtint (buffer, &currlen, maxlen, value, 8, min, max, flags);
break;
case 'u':
flags |= DP_F_UNSIGNED;
if (cflags == DP_C_SHORT)
value = va_arg (args, unsigned short int);
else if (cflags == DP_C_LONG)
value = (long)va_arg (args, unsigned long int);
else
value = (long)va_arg (args, unsigned int);
fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags);
break;
case 'X':
flags |= DP_F_UP;
case 'x':
flags |= DP_F_UNSIGNED;
if (cflags == DP_C_SHORT)
value = va_arg (args, unsigned short int);
else if (cflags == DP_C_LONG)
value = (long)va_arg (args, unsigned long int);
else
value = (long)va_arg (args, unsigned int);
fmtint (buffer, &currlen, maxlen, value, 16, min, max, flags);
break;
case 'f':
if (cflags == DP_C_LDOUBLE)
fvalue = va_arg (args, LDOUBLE);
else
fvalue = va_arg (args, double);
/* um, floating point? */
fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags);
break;
case 'E':
flags |= DP_F_UP;
case 'e':
if (cflags == DP_C_LDOUBLE)
fvalue = va_arg (args, LDOUBLE);
else
fvalue = va_arg (args, double);
break;
case 'G':
flags |= DP_F_UP;
case 'g':
if (cflags == DP_C_LDOUBLE)
fvalue = va_arg (args, LDOUBLE);
else
fvalue = va_arg (args, double);
break;
case 'c':
dopr_outch (buffer, &currlen, maxlen, va_arg (args, int));
break;
case 's':
strvalue = va_arg (args, char *);
if (max < 0)
max = maxlen; /* ie, no max */
fmtstr (buffer, &currlen, maxlen, strvalue, flags, min, max);
break;
case 'p':
strvalue = va_arg (args, void *);
fmtint (buffer, &currlen, maxlen, (long) strvalue, 16, min, max, flags);
break;
case 'n':
if (cflags == DP_C_SHORT)
{
short int *num;
num = va_arg (args, short int *);
*num = currlen;
}
else if (cflags == DP_C_LONG)
{
long int *num;
num = va_arg (args, long int *);
*num = (long int)currlen;
}
else
{
int *num;
num = va_arg (args, int *);
*num = currlen;
}
break;
case '%':
dopr_outch (buffer, &currlen, maxlen, ch);
break;
case 'w':
/* not supported yet, treat as next char */
ch = *format++;
break;
default:
/* Unknown, skip */
break;
}
ch = *format++;
state = DP_S_DEFAULT;
flags = cflags = min = 0;
max = -1;
break;
case DP_S_DONE:
break;
default:
/* hmm? */
break; /* some picky compilers need this */
}
}
if (currlen < maxlen - 1)
buffer[currlen] = '\0';
else
buffer[maxlen - 1] = '\0';
}
static void fmtstr (char *buffer, size_t *currlen, size_t maxlen,
char *value, int flags, int min, int max)
{
int padlen, strln; /* amount to pad */
int cnt = 0;
if (value == 0)
{
value = "<NULL>";
}
for (strln = 0; value[strln]; ++strln); /* strlen */
padlen = min - strln;
if (padlen < 0)
padlen = 0;
if (flags & DP_F_MINUS)
padlen = -padlen; /* Left Justify */
while ((padlen > 0) && (cnt < max))
{
dopr_outch (buffer, currlen, maxlen, ' ');
--padlen;
++cnt;
}
while (*value && (cnt < max))
{
dopr_outch (buffer, currlen, maxlen, *value++);
++cnt;
}
while ((padlen < 0) && (cnt < max))
{
dopr_outch (buffer, currlen, maxlen, ' ');
++padlen;
++cnt;
}
}
/* Have to handle DP_F_NUM (ie 0x and 0 alternates) */
static void fmtint (char *buffer, size_t *currlen, size_t maxlen,
long value, int base, int min, int max, int flags)
{
int signvalue = 0;
unsigned long uvalue;
char convert[20];
int place = 0;
int spadlen = 0; /* amount to space pad */
int zpadlen = 0; /* amount to zero pad */
int caps = 0;
if (max < 0)
max = 0;
uvalue = value;
if(!(flags & DP_F_UNSIGNED))
{
if( value < 0 ) {
signvalue = '-';
uvalue = -value;
}
else
if (flags & DP_F_PLUS) /* Do a sign (+/i) */
signvalue = '+';
else
if (flags & DP_F_SPACE)
signvalue = ' ';
}
if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */
do {
convert[place++] =
(caps? "0123456789ABCDEF":"0123456789abcdef")
[uvalue % (unsigned)base ];
uvalue = (uvalue / (unsigned)base );
} while(uvalue && (place < 20));
if (place == 20) place--;
convert[place] = 0;
zpadlen = max - place;
spadlen = min - MAX (max, place) - (signvalue ? 1 : 0);
if (zpadlen < 0) zpadlen = 0;
if (spadlen < 0) spadlen = 0;
if (flags & DP_F_ZERO)
{
zpadlen = MAX(zpadlen, spadlen);
spadlen = 0;
}
if (flags & DP_F_MINUS)
spadlen = -spadlen; /* Left Justifty */
#ifdef DEBUG_SNPRINTF
printf("zpad: %d, spad: %d, min: %d, max: %d, place: %d\n",
zpadlen, spadlen, min, max, place);
#endif
/* Spaces */
while (spadlen > 0)
{
dopr_outch (buffer, currlen, maxlen, ' ');
--spadlen;
}
/* Sign */
if (signvalue)
dopr_outch (buffer, currlen, maxlen, signvalue);
/* Zeros */
if (zpadlen > 0)
{
while (zpadlen > 0)
{
dopr_outch (buffer, currlen, maxlen, '0');
--zpadlen;
}
}
/* Digits */
while (place > 0)
dopr_outch (buffer, currlen, maxlen, convert[--place]);
/* Left Justified spaces */
while (spadlen < 0) {
dopr_outch (buffer, currlen, maxlen, ' ');
++spadlen;
}
}
static LDOUBLE abs_val (LDOUBLE value)
{
LDOUBLE result = value;
if (value < 0)
result = -value;
return result;
}
static LDOUBLE pow10 (int exp)
{
LDOUBLE result = 1;
while (exp)
{
result *= 10;
exp--;
}
return result;
}
static long round (LDOUBLE value)
{
long intpart;
intpart = (long)value;
value = value - intpart;
if (value >= 0.5)
intpart++;
return intpart;
}
static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
LDOUBLE fvalue, int min, int max, int flags)
{
int signvalue = 0;
LDOUBLE ufvalue;
char iconvert[20];
char fconvert[20];
int iplace = 0;
int fplace = 0;
int padlen = 0; /* amount to pad */
int zpadlen = 0;
int caps = 0;
long intpart;
long fracpart;
/*
* AIX manpage says the default is 0, but Solaris says the default
* is 6, and sprintf on AIX defaults to 6
*/
if (max < 0)
max = 6;
ufvalue = abs_val (fvalue);
if (fvalue < 0)
signvalue = '-';
else
if (flags & DP_F_PLUS) /* Do a sign (+/i) */
signvalue = '+';
else
if (flags & DP_F_SPACE)
signvalue = ' ';
#if 0
if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */
#endif
intpart = (long)ufvalue;
/*
* Sorry, we only support 9 digits past the decimal because of our
* conversion method
*/
if (max > 9)
max = 9;
/* We "cheat" by converting the fractional part to integer by
* multiplying by a factor of 10
*/
fracpart = round ((pow10 (max)) * (ufvalue - intpart));
if (fracpart >= pow10 (max))
{
intpart++;
fracpart -= pow10 (max);
}
#ifdef DEBUG_SNPRINTF
printf("fmtfp: %g %d.%d min=%d max=%d\n",
(double)fvalue, intpart, fracpart, min, max);
#endif
/* Convert integer part */
do {
iconvert[iplace++] =
(caps? "0123456789ABCDEF":"0123456789abcdef")[intpart % 10];
intpart = (intpart / 10);
} while(intpart && (iplace < 20));
if (iplace == 20) iplace--;
iconvert[iplace] = 0;
/* Convert fractional part */
do {
fconvert[fplace++] =
(caps? "0123456789ABCDEF":"0123456789abcdef")[fracpart % 10];
fracpart = (fracpart / 10);
} while(fracpart && (fplace < 20));
if (fplace == 20) fplace--;
fconvert[fplace] = 0;
/* -1 for decimal point, another -1 if we are printing a sign */
padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0);
zpadlen = max - fplace;
if (zpadlen < 0)
zpadlen = 0;
if (padlen < 0)
padlen = 0;
if (flags & DP_F_MINUS)
padlen = -padlen; /* Left Justifty */
if ((flags & DP_F_ZERO) && (padlen > 0))
{
if (signvalue)
{
dopr_outch (buffer, currlen, maxlen, signvalue);
--padlen;
signvalue = 0;
}
while (padlen > 0)
{
dopr_outch (buffer, currlen, maxlen, '0');
--padlen;
}
}
while (padlen > 0)
{
dopr_outch (buffer, currlen, maxlen, ' ');
--padlen;
}
if (signvalue)
dopr_outch (buffer, currlen, maxlen, signvalue);
while (iplace > 0)
dopr_outch (buffer, currlen, maxlen, iconvert[--iplace]);
#ifdef DEBUG_SNPRINTF
printf("fmtfp: fplace=%d zpadlen=%d\n", fplace, zpadlen);
#endif
/*
* Decimal point. This should probably use locale to find the correct
* char to print out.
*/
if (max > 0) {
dopr_outch (buffer, currlen, maxlen, '.');
while (fplace > 0)
dopr_outch (buffer, currlen, maxlen, fconvert[--fplace]);
}
while (zpadlen > 0)
{
dopr_outch (buffer, currlen, maxlen, '0');
--zpadlen;
}
while (padlen < 0)
{
dopr_outch (buffer, currlen, maxlen, ' ');
++padlen;
}
}
static void dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c)
{
if (*currlen < maxlen)
buffer[(*currlen)++] = c;
}
#endif /* !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) */
#ifndef HAVE_VSNPRINTF
int vsnprintf (char *str, size_t count, const char *fmt, va_list args)
{
str[0] = 0;
dopr(str, count, fmt, args);
return(strlen(str));
}
#endif /* !HAVE_VSNPRINTF */
#ifndef HAVE_SNPRINTF
/* VARARGS3 */
#ifdef HAVE_STDARGS
int snprintf (char *str,size_t count,const char *fmt,...)
#else
int snprintf (va_alist) va_dcl
#endif
{
#ifndef HAVE_STDARGS
char *str;
size_t count;
char *fmt;
#endif
VA_LOCAL_DECL;
VA_START (fmt);
VA_SHIFT (str, char *);
VA_SHIFT (count, size_t );
VA_SHIFT (fmt, char *);
(void) vsnprintf(str, count, fmt, ap);
VA_END;
return(strlen(str));
}
#else
/* keep compilers happy about empty files */
void dummy_snprintf(void) {}
#endif /* !HAVE_SNPRINTF */
#ifdef TEST_SNPRINTF
#ifndef LONG_STRING
#define LONG_STRING 1024
#endif
int main (void)
{
char buf1[LONG_STRING];
char buf2[LONG_STRING];
char *fp_fmt[] = {
"%-1.5f",
"%1.5f",
"%123.9f",
"%10.5f",
"% 10.5f",
"%+22.9f",
"%+4.9f",
"%01.3f",
"%4f",
"%3.1f",
"%3.2f",
"%.0f",
"%.1f",
NULL
};
double fp_nums[] = { -1.5, 134.21, 91340.2, 341.1234, 0203.9, 0.96, 0.996,
0.9996, 1.996, 4.136, 0};
char *int_fmt[] = {
"%-1.5d",
"%1.5d",
"%123.9d",
"%5.5d",
"%10.5d",
"% 10.5d",
"%+22.33d",
"%01.3d",
"%4d",
NULL
};
long int_nums[] = { -1, 134, 91340, 341, 0203, 0};
int x, y;
int fail = 0;
int num = 0;
printf ("Testing snprintf format codes against system sprintf...\n");
for (x = 0; fp_fmt[x] != NULL ; x++)
for (y = 0; fp_nums[y] != 0 ; y++)
{
snprintf (buf1, sizeof (buf1), fp_fmt[x], fp_nums[y]);
sprintf (buf2, fp_fmt[x], fp_nums[y]);
if (strcmp (buf1, buf2))
{
printf("snprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf = %s\n",
fp_fmt[x], buf1, buf2);
fail++;
}
num++;
}
for (x = 0; int_fmt[x] != NULL ; x++)
for (y = 0; int_nums[y] != 0 ; y++)
{
snprintf (buf1, sizeof (buf1), int_fmt[x], int_nums[y]);
sprintf (buf2, int_fmt[x], int_nums[y]);
if (strcmp (buf1, buf2))
{
printf("snprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf = %s\n",
int_fmt[x], buf1, buf2);
fail++;
}
num++;
}
printf ("%d tests failed out of %d.\n", fail, num);
}
#endif /* SNPRINTF_TEST */

View File

@@ -98,6 +98,8 @@ typedef struct
{
char *motd_file;
char *lock_file;
char *log_file;
char *pid_file;
int syslog_facility;
int max_connections;
char *socket_options;
@@ -117,6 +119,8 @@ typedef struct
char *comment;
BOOL read_only;
BOOL list;
BOOL use_chroot;
BOOL transfer_logging;
char *uid;
char *gid;
char *hosts_allow;
@@ -125,6 +129,7 @@ typedef struct
char *secrets_file;
char *exclude;
char *exclude_from;
char *log_format;
} service;
@@ -136,6 +141,8 @@ static service sDefault =
NULL, /* comment */
True, /* read only */
True, /* list */
True, /* use chroot */
False, /* transfer logging */
"nobody",/* uid */
"nobody",/* gid */
NULL, /* hosts allow */
@@ -144,6 +151,7 @@ static service sDefault =
NULL, /* secrets file */
NULL, /* exclude */
NULL, /* exclude from */
"%o %h [%a] %m (%u) %f %l", /* log format */
};
@@ -231,12 +239,15 @@ static struct parm_struct parm_table[] =
{"lock file", P_STRING, P_GLOBAL, &Globals.lock_file, NULL, 0},
{"syslog facility", P_ENUM, P_GLOBAL, &Globals.syslog_facility, enum_facilities,0},
{"socket options", P_STRING, P_GLOBAL, &Globals.socket_options,NULL, 0},
{"log file", P_STRING, P_GLOBAL, &Globals.log_file, NULL, 0},
{"pid file", P_STRING, P_GLOBAL, &Globals.pid_file, NULL, 0},
{"name", P_STRING, P_LOCAL, &sDefault.name, NULL, 0},
{"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL, 0},
{"path", P_STRING, P_LOCAL, &sDefault.path, NULL, 0},
{"read only", P_BOOL, P_LOCAL, &sDefault.read_only, NULL, 0},
{"list", P_BOOL, P_LOCAL, &sDefault.list, NULL, 0},
{"use chroot", P_BOOL, P_LOCAL, &sDefault.use_chroot, NULL, 0},
{"uid", P_STRING, P_LOCAL, &sDefault.uid, NULL, 0},
{"gid", P_STRING, P_LOCAL, &sDefault.gid, NULL, 0},
{"hosts allow", P_STRING, P_LOCAL, &sDefault.hosts_allow, NULL, 0},
@@ -245,6 +256,8 @@ static struct parm_struct parm_table[] =
{"secrets file", P_STRING, P_LOCAL, &sDefault.secrets_file,NULL, 0},
{"exclude", P_STRING, P_LOCAL, &sDefault.exclude, NULL, 0},
{"exclude from", P_STRING, P_LOCAL, &sDefault.exclude_from,NULL, 0},
{"transfer logging", P_BOOL, P_LOCAL, &sDefault.transfer_logging,NULL,0},
{"log format", P_STRING, P_LOCAL, &sDefault.log_format, NULL, 0},
{NULL, P_BOOL, P_NONE, NULL, NULL, 0}
};
@@ -295,6 +308,8 @@ static void init_locals(void)
FN_GLOBAL_STRING(lp_motd_file, &Globals.motd_file)
FN_GLOBAL_STRING(lp_lock_file, &Globals.lock_file)
FN_GLOBAL_STRING(lp_log_file, &Globals.log_file)
FN_GLOBAL_STRING(lp_pid_file, &Globals.pid_file)
FN_GLOBAL_STRING(lp_socket_options, &Globals.socket_options)
FN_GLOBAL_INTEGER(lp_max_connections, &Globals.max_connections)
FN_GLOBAL_INTEGER(lp_syslog_facility, &Globals.syslog_facility)
@@ -304,6 +319,8 @@ FN_LOCAL_STRING(lp_comment, comment)
FN_LOCAL_STRING(lp_path, path)
FN_LOCAL_BOOL(lp_read_only, read_only)
FN_LOCAL_BOOL(lp_list, list)
FN_LOCAL_BOOL(lp_use_chroot, use_chroot)
FN_LOCAL_BOOL(lp_transfer_logging, transfer_logging)
FN_LOCAL_STRING(lp_uid, uid)
FN_LOCAL_STRING(lp_gid, gid)
FN_LOCAL_STRING(lp_hosts_allow, hosts_allow)
@@ -312,6 +329,7 @@ FN_LOCAL_STRING(lp_auth_users, auth_users)
FN_LOCAL_STRING(lp_secrets_file, secrets_file)
FN_LOCAL_STRING(lp_exclude, exclude)
FN_LOCAL_STRING(lp_exclude_from, exclude_from)
FN_LOCAL_STRING(lp_log_format, log_format)
/* local prototypes */
static int strwicmp( char *psz1, char *psz2 );
@@ -329,7 +347,7 @@ initialise a service to the defaults
***************************************************************************/
static void init_service(service *pservice)
{
bzero((char *)pservice,sizeof(service));
memset((char *)pservice,0,sizeof(service));
copy_service(pservice,&sDefault);
}
@@ -340,7 +358,7 @@ static void string_set(char **s, char *v)
return;
}
*s = strdup(v);
if (!*s) exit_cleanup(1);
if (!*s) exit_cleanup(RERR_MALLOC);
}

222
log.c
View File

@@ -23,15 +23,46 @@
*/
#include "rsync.h"
static FILE *logfile;
static void logit(int priority, char *buf)
{
if (logfile) {
fprintf(logfile,"%s [%d] %s",
timestring(time(NULL)), (int)getpid(), buf);
fflush(logfile);
} else {
syslog(priority, "%s", buf);
}
}
void log_open(void)
{
static int initialised;
int options = LOG_PID;
time_t t;
char *logf;
if (initialised) return;
initialised = 1;
/* this looks pointless, but it is needed in order for the
C library on some systems to fetch the timezone info
before the chroot */
t = time(NULL);
localtime(&t);
/* optionally use a log file instead of syslog */
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
options |= LOG_NDELAY;
#endif
@@ -43,13 +74,13 @@ void log_open(void)
#endif
#ifndef LOG_NDELAY
syslog(LOG_INFO,"rsyncd started\n");
logit(LOG_INFO,"rsyncd started\n");
#endif
}
/* this is the rsync debugging function. Call it with FINFO or FERROR */
void rprintf(int fd, const char *format, ...)
/* this is the rsync debugging function. Call it with FINFO, FERROR or FLOG */
void rprintf(int fd, const char *format, ...)
{
va_list ap;
char buf[1024];
@@ -57,29 +88,34 @@ void rprintf(int fd, const char *format, ...)
FILE *f=NULL;
extern int am_daemon;
/* recursion can happen with certain fatal conditions */
static int depth;
if (depth) return;
depth++;
va_start(ap, format);
len = vslprintf(buf, sizeof(buf)-1, format, ap);
va_end(ap);
if (len < 0) exit_cleanup(1);
if (len < 0) exit_cleanup(RERR_MESSAGEIO);
if (len > sizeof(buf)-1) exit_cleanup(1);
if (len > sizeof(buf)-1) exit_cleanup(RERR_MESSAGEIO);
buf[len] = 0;
if (fd == FLOG) {
if (am_daemon) logit(LOG_INFO, buf);
return;
}
if (am_daemon) {
static int depth;
int priority = LOG_INFO;
if (fd == FERROR) priority = LOG_WARNING;
if (depth) return;
depth++;
log_open();
if (!io_multiplex_write(fd, buf, strlen(buf))) {
syslog(priority, "%s", buf);
logit(priority, buf);
}
depth--;
@@ -98,11 +134,11 @@ void rprintf(int fd, const char *format, ...)
f = stdout;
}
if (!f) exit_cleanup(1);
if (!f) exit_cleanup(RERR_MESSAGEIO);
if (fwrite(buf, len, 1, f) != 1) exit_cleanup(1);
if (fwrite(buf, len, 1, f) != 1) exit_cleanup(RERR_MESSAGEIO);
depth--;
if (buf[len-1] == '\r' || buf[len-1] == '\n') fflush(f);
}
void rflush(int fd)
@@ -114,6 +150,10 @@ void rflush(int fd)
return;
}
if (fd == FLOG) {
return;
}
if (fd == FERROR) {
f = stderr;
}
@@ -126,7 +166,159 @@ void rflush(int fd)
f = stdout;
}
if (!f) exit_cleanup(1);
if (!f) exit_cleanup(RERR_MESSAGEIO);
fflush(f);
}
/* a generic logging routine for send/recv, with parameter
substitiution */
static void log_formatted(int fd,
char *format, char *op, struct file_struct *file,
struct stats *initial_stats)
{
extern int module_id;
extern char *auth_user;
char buf[1024];
char buf2[1024];
char *p, *s, *n;
int l;
extern struct stats stats;
extern int am_sender;
int64 b;
strlcpy(buf, format, sizeof(buf)-1);
for (s=&buf[0];
s && (p=strchr(s,'%')); ) {
n = NULL;
s = p + 1;
switch (p[1]) {
case 'h': n = client_name(0); break;
case 'a': n = client_addr(0); break;
case 'l':
slprintf(buf2,sizeof(buf2)-1,"%.0f",
(double)file->length);
n = buf2;
break;
case 'p':
slprintf(buf2,sizeof(buf2)-1,"%d",
(int)getpid());
n = buf2;
break;
case 'o': n = op; break;
case 'f':
slprintf(buf2, sizeof(buf2)-1, "%s/%s",
file->basedir?file->basedir:"",
f_name(file));
clean_fname(buf2);
n = buf2;
if (*n == '/') n++;
break;
case 'm': n = lp_name(module_id); break;
case 't': n = timestring(time(NULL)); break;
case 'P': n = lp_path(module_id); break;
case 'u': n = auth_user; break;
case 'b':
if (am_sender) {
b = stats.total_written -
initial_stats->total_written;
} else {
b = stats.total_read -
initial_stats->total_read;
}
slprintf(buf2,sizeof(buf2)-1,"%.0f", (double)b);
n = buf2;
break;
case 'c':
if (!am_sender) {
b = stats.total_written -
initial_stats->total_written;
} else {
b = stats.total_read -
initial_stats->total_read;
}
slprintf(buf2,sizeof(buf2)-1,"%.0f", (double)b);
n = buf2;
break;
}
if (!n) continue;
l = strlen(n);
if ((l-1) + ((int)(s - &buf[0])) > sizeof(buf)) {
rprintf(FERROR,"buffer overflow expanding %%%c - exiting\n",
p[0]);
exit_cleanup(RERR_MESSAGEIO);
}
if (l != 2) {
memmove(s+(l-1), s+1, strlen(s+1)+1);
}
memcpy(p, n, l);
s = p+l;
}
rprintf(fd,"%s\n", buf);
}
/* log the outgoing transfer of a file */
void log_send(struct file_struct *file, struct stats *initial_stats)
{
extern int module_id;
extern int am_server;
extern char *log_format;
if (lp_transfer_logging(module_id)) {
log_formatted(FLOG, lp_log_format(module_id), "send", file, initial_stats);
} else if (log_format && !am_server) {
log_formatted(FINFO, log_format, "send", file, initial_stats);
}
}
/* log the incoming transfer of a file */
void log_recv(struct file_struct *file, struct stats *initial_stats)
{
extern int module_id;
extern int am_server;
extern char *log_format;
if (lp_transfer_logging(module_id)) {
log_formatted(FLOG, lp_log_format(module_id), "send", file, initial_stats);
} else if (log_format && !am_server) {
log_formatted(FINFO, log_format, "send", file, initial_stats);
}
}
/* called when the transfer is interrupted for some reason */
void log_exit(int code)
{
if (code == 0) {
extern struct stats stats;
rprintf(FLOG,"wrote %.0f bytes read %.0f bytes total size %.0f\n",
(double)stats.total_written,
(double)stats.total_read,
(double)stats.total_size);
} else {
rprintf(FLOG,"transfer interrupted (code %d)\n", code);
}
}
/* log the incoming transfer of a file for interactive use, this
will be called at the end where the client was run
it i called when a file starts to be transferred
*/
void log_transfer(struct file_struct *file, char *fname)
{
extern int verbose;
if (!verbose) return;
rprintf(FINFO,"%s\n", fname);
}

160
main.c
View File

@@ -36,10 +36,7 @@ static void report(int f)
extern int do_stats;
if (am_daemon) {
syslog(LOG_INFO,"wrote %.0f bytes read %.0f bytes total size %.0f\n",
(double)stats.total_written,
(double)stats.total_read,
(double)stats.total_size);
log_exit(0);
if (f == -1 || !am_sender) return;
}
@@ -63,31 +60,34 @@ static void report(int f)
}
if (do_stats) {
printf("\nNumber of files: %d\n", stats.num_files);
printf("Number of files transferred: %d\n",
rprintf(FINFO,"\nNumber of files: %d\n", stats.num_files);
rprintf(FINFO,"Number of files transferred: %d\n",
stats.num_transferred_files);
printf("Total file size: %.0f bytes\n",
rprintf(FINFO,"Total file size: %.0f bytes\n",
(double)stats.total_size);
printf("Total transferred file size: %.0f bytes\n",
rprintf(FINFO,"Total transferred file size: %.0f bytes\n",
(double)stats.total_transferred_size);
printf("Literal data: %.0f bytes\n",
rprintf(FINFO,"Literal data: %.0f bytes\n",
(double)stats.literal_data);
printf("Matched data: %.0f bytes\n",
rprintf(FINFO,"Matched data: %.0f bytes\n",
(double)stats.matched_data);
printf("File list size: %d\n", stats.flist_size);
printf("Total bytes written: %.0f\n",
rprintf(FINFO,"File list size: %d\n", stats.flist_size);
rprintf(FINFO,"Total bytes written: %.0f\n",
(double)stats.total_written);
printf("Total bytes read: %.0f\n\n",
rprintf(FINFO,"Total bytes read: %.0f\n\n",
(double)stats.total_read);
}
printf("wrote %.0f bytes read %.0f bytes %.2f bytes/sec\n",
rprintf(FINFO,"wrote %.0f bytes read %.0f bytes %.2f bytes/sec\n",
(double)stats.total_written,
(double)stats.total_read,
(stats.total_written+stats.total_read)/(0.5 + (t-starttime)));
printf("total size is %.0f speedup is %.2f\n",
rprintf(FINFO,"total size is %.0f speedup is %.2f\n",
(double)stats.total_size,
(1.0*stats.total_size)/(stats.total_written+stats.total_read));
fflush(stdout);
fflush(stderr);
}
@@ -169,18 +169,22 @@ static char *get_local_name(struct file_list *flist,char *name)
STRUCT_STAT st;
extern int orig_umask;
if (verbose > 2)
rprintf(FINFO,"get_local_name count=%d %s\n",
flist->count, name);
if (do_stat(name,&st) == 0) {
if (S_ISDIR(st.st_mode)) {
if (!push_dir(name, 0)) {
rprintf(FERROR,"push_dir %s : %s (1)\n",
name,strerror(errno));
exit_cleanup(1);
exit_cleanup(RERR_FILESELECT);
}
return NULL;
}
if (flist->count > 1) {
rprintf(FERROR,"ERROR: destination must be a directory when copying more than 1 file\n");
exit_cleanup(1);
exit_cleanup(RERR_FILESELECT);
}
return name;
}
@@ -193,15 +197,16 @@ static char *get_local_name(struct file_list *flist,char *name)
if (do_mkdir(name,0777 & ~orig_umask) != 0) {
rprintf(FERROR,"mkdir %s : %s (1)\n",name,strerror(errno));
exit_cleanup(1);
exit_cleanup(RERR_FILEIO);
} else {
rprintf(FINFO,"created directory %s\n",name);
if (verbose > 0)
rprintf(FINFO,"created directory %s\n",name);
}
if (!push_dir(name, 0)) {
rprintf(FERROR,"push_dir %s : %s (2)\n",
name,strerror(errno));
exit_cleanup(1);
exit_cleanup(RERR_FILESELECT);
}
return NULL;
@@ -223,7 +228,7 @@ static void do_server_sender(int f_in, int f_out, int argc,char *argv[])
if (!relative_paths && !push_dir(dir, 0)) {
rprintf(FERROR,"push_dir %s: %s (3)\n",dir,strerror(errno));
exit_cleanup(1);
exit_cleanup(RERR_FILESELECT);
}
argc--;
argv++;
@@ -242,6 +247,10 @@ static void do_server_sender(int f_in, int f_out, int argc,char *argv[])
argv[0] = ".";
}
set_nonblocking(f_out);
if (f_in != f_out)
set_nonblocking(f_in);
flist = send_file_list(f_out,argc,argv);
if (!flist || flist->count == 0) {
exit_cleanup(0);
@@ -266,7 +275,7 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
if (pipe(recv_pipe) < 0) {
rprintf(FERROR,"pipe failed in do_recv\n");
exit_cleanup(1);
exit_cleanup(RERR_SOCKETIO);
}
io_flush();
@@ -275,12 +284,12 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
close(recv_pipe[0]);
if (f_in != f_out) close(f_out);
set_nonblocking(f_in);
set_nonblocking(recv_pipe[1]);
recv_files(f_in,flist,local_name,recv_pipe[1]);
report(f_in);
if (verbose > 3)
rprintf(FINFO,"do_recv waiting on %d\n",pid);
io_flush();
_exit(0);
}
@@ -288,6 +297,12 @@ static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
close(recv_pipe[1]);
io_close_input(f_in);
if (f_in != f_out) close(f_in);
set_nonblocking(f_out);
set_nonblocking(recv_pipe[0]);
io_start_buffering(f_out);
generate_files(f_out,flist,local_name,recv_pipe[0]);
io_flush();
@@ -315,7 +330,7 @@ static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
if (!am_daemon && !push_dir(dir, 0)) {
rprintf(FERROR,"push_dir %s : %s (4)\n",
dir,strerror(errno));
exit_cleanup(1);
exit_cleanup(RERR_FILESELECT);
}
}
@@ -325,7 +340,7 @@ static void do_server_recv(int f_in, int f_out, int argc,char *argv[])
flist = recv_file_list(f_in);
if (!flist || flist->count == 0) {
rprintf(FERROR,"server_recv: nothing to do\n");
exit_cleanup(1);
exit_cleanup(RERR_FILESELECT);
}
if (argc > 0) {
@@ -346,8 +361,12 @@ void start_server(int f_in, int f_out, int argc, char *argv[])
extern int cvs_exclude;
extern int am_sender;
set_nonblocking(f_out);
if (f_in != f_out)
set_nonblocking(f_in);
setup_protocol(f_out, f_in);
if (am_sender) {
recv_exclude_list(f_in);
if (cvs_exclude)
@@ -365,6 +384,7 @@ int client_run(int f_in, int f_out, int pid, int argc, char *argv[])
int status = 0, status2 = 0;
char *local_name = NULL;
extern int am_sender;
extern int list_only;
setup_protocol(f_out,f_in);
@@ -378,6 +398,11 @@ int client_run(int f_in, int f_out, int pid, int argc, char *argv[])
flist = send_file_list(f_out,argc,argv);
if (verbose > 3)
rprintf(FINFO,"file list sent\n");
set_nonblocking(f_out);
if (f_in != f_out)
set_nonblocking(f_in);
send_files(flist,f_out,f_in);
if (pid != -1) {
if (verbose > 3)
@@ -388,6 +413,8 @@ int client_run(int f_in, int f_out, int pid, int argc, char *argv[])
report(-1);
exit_cleanup(status);
}
if (argc == 0) list_only = 1;
send_exclude_list(f_out);
@@ -411,20 +438,54 @@ int client_run(int f_in, int f_out, int pid, int argc, char *argv[])
return status | status2;
}
static char *find_colon(char *s)
{
char *p, *p2;
int start_client(int argc, char *argv[])
p = strchr(s,':');
if (!p) return NULL;
/* now check to see if there is a / in the string before the : - if there is then
discard the colon on the assumption that the : is part of a filename */
p2 = strchr(s,'/');
if (p2 && p2 < p) return NULL;
return p;
}
static int start_client(int argc, char *argv[])
{
char *p;
char *shell_machine = NULL;
char *shell_path = NULL;
char *shell_user = NULL;
int pid;
int pid, ret;
int f_in,f_out;
extern int local_server;
extern int am_sender;
extern char *shell_cmd;
extern int rsync_port;
p = strchr(argv[0],':');
if (strncasecmp(URL_PREFIX, argv[0], strlen(URL_PREFIX)) == 0) {
char *host, *path;
host = argv[0] + strlen(URL_PREFIX);
p = strchr(host,'/');
if (p) {
*p = 0;
path = p+1;
} else {
path="";
}
p = strchr(host,':');
if (p) {
rsync_port = atoi(p+1);
*p = 0;
}
return start_socket_client(host, path, argc-1, argv+1);
}
p = find_colon(argv[0]);
if (p) {
if (p[1] == ':') {
@@ -432,9 +493,9 @@ int start_client(int argc, char *argv[])
return start_socket_client(argv[0], p+2, argc-1, argv+1);
}
if (argc < 2) {
if (argc < 1) {
usage(FERROR);
exit_cleanup(1);
exit_cleanup(RERR_SYNTAX);
}
am_sender = 0;
@@ -446,7 +507,7 @@ int start_client(int argc, char *argv[])
} else {
am_sender = 1;
p = strchr(argv[argc-1],':');
p = find_colon(argv[argc-1]);
if (!p) {
local_server = 1;
} else if (p[1] == ':') {
@@ -456,7 +517,7 @@ int start_client(int argc, char *argv[])
if (argc < 2) {
usage(FERROR);
exit_cleanup(1);
exit_cleanup(RERR_SYNTAX);
}
if (local_server) {
@@ -487,24 +548,24 @@ int start_client(int argc, char *argv[])
shell_path?shell_path:"");
}
if (!am_sender && argc != 1) {
if (!am_sender && argc > 1) {
usage(FERROR);
exit_cleanup(1);
exit_cleanup(RERR_SYNTAX);
}
pid = do_cmd(shell_cmd,shell_machine,shell_user,shell_path,&f_in,&f_out);
#if HAVE_SETLINEBUF
setlinebuf(stdout);
setlinebuf(stderr);
#endif
ret = client_run(f_in, f_out, pid, argc, argv);
return client_run(f_in, f_out, pid, argc, argv);
fflush(stdout);
fflush(stderr);
return ret;
}
RETSIGTYPE sigusr1_handler(int val) {
exit_cleanup(1);
static RETSIGTYPE sigusr1_handler(int val) {
exit_cleanup(RERR_SIGNAL);
}
int main(int argc,char *argv[])
@@ -524,14 +585,16 @@ int main(int argc,char *argv[])
if (argc < 2) {
usage(FERROR);
exit_cleanup(1);
exit_cleanup(RERR_SYNTAX);
}
/* we set a 0 umask so that correct file permissions can be
carried across */
orig_umask = (int)umask(0);
parse_arguments(argc, argv);
if (!parse_arguments(argc, argv)) {
exit_cleanup(RERR_SYNTAX);
}
argc -= optind;
argv += optind;
@@ -541,6 +604,7 @@ int main(int argc,char *argv[])
signal(SIGINT,SIGNAL_CAST sig_int);
signal(SIGPIPE,SIGNAL_CAST sig_int);
signal(SIGHUP,SIGNAL_CAST sig_int);
signal(SIGTERM,SIGNAL_CAST sig_int);
if (am_daemon) {
return daemon_main();
@@ -548,7 +612,7 @@ int main(int argc,char *argv[])
if (argc < 1) {
usage(FERROR);
exit_cleanup(1);
exit_cleanup(RERR_SYNTAX);
}
if (dry_run)
@@ -557,7 +621,7 @@ int main(int argc,char *argv[])
#ifndef SUPPORT_LINKS
if (!am_server && preserve_links) {
rprintf(FERROR,"ERROR: symbolic links not supported\n");
exit_cleanup(1);
exit_cleanup(RERR_UNSUPPORTED);
}
#endif

17
match.c
View File

@@ -29,7 +29,7 @@ extern int remote_version;
typedef unsigned short tag;
#define TABLESIZE (1<<16)
#define NULL_TAG ((tag)-1)
#define NULL_TAG (-1)
static int false_alarms;
static int tag_hits;
@@ -49,7 +49,7 @@ struct target {
static struct target *targets;
static tag *tag_table;
static int *tag_table;
#define gettag2(s1,s2) (((s1) + (s2)) & 0xFFFF)
#define gettag(sum) gettag2((sum)&0xFFFF,(sum)>>16)
@@ -65,7 +65,7 @@ static void build_hash_table(struct sum_struct *s)
int i;
if (!tag_table)
tag_table = (tag *)malloc(sizeof(tag)*TABLESIZE);
tag_table = (int *)malloc(sizeof(tag_table[0])*TABLESIZE);
targets = (struct target *)malloc(sizeof(targets[0])*s->count);
if (!tag_table || !targets)
@@ -118,6 +118,11 @@ static void matched(int f,struct sum_struct *s,struct map_struct *buf,
last_match = offset + s->sums[i].len;
else
last_match = offset;
if (buf)
show_progress(last_match, buf->size);
if (i == -1) end_progress();
}
@@ -252,6 +257,12 @@ void match_sums(int f,struct sum_struct *s,struct map_struct *buf,OFF_T len)
if (verbose > 2)
rprintf(FINFO,"done hash search\n");
} else {
OFF_T j;
/* by doing this in pieces we avoid too many seeks */
for (j=0;j<(len-CHUNK_SIZE);j+=CHUNK_SIZE) {
int n1 = MIN(CHUNK_SIZE,(len-CHUNK_SIZE)-j);
matched(f,s,buf,j+n1,-2);
}
matched(f,s,buf,len,-1);
}

4
md4.c
View File

@@ -102,7 +102,7 @@
** Assumes X is an array of 16 ints.
** The macro revx reverses the byte-ordering of the next word of X.
*/
void MDreverse(X)
static void MDreverse(X)
unsigned int32 *X;
{ register unsigned int32 t;
register unsigned int i;
@@ -225,7 +225,7 @@
/* Process data */
if (count == 512)
{ /* Full block of data to handle */
MDblock(MDp,(unsigned int *)X);
MDblock(MDp,(unsigned int32 *)X);
}
else if (count > 512) /* Check for count too large */
{ rprintf(FERROR,"\nError: MDupdate called with illegal count value %d."

624
options.c
View File

@@ -56,71 +56,86 @@ int recurse = 0;
int am_daemon=0;
int am_client=0;
int do_stats=0;
int do_progress=0;
int keep_partial=0;
int safe_symlinks=0;
int block_size=BLOCK_SIZE;
char *backup_suffix = BACKUP_SUFFIX;
char *tmpdir = NULL;
char *compare_dest = NULL;
char *config_file = RSYNCD_CONF;
char *shell_cmd = NULL;
char *log_format = NULL;
char *rsync_path = RSYNC_NAME;
int rsync_port = RSYNC_PORT;
int verbose = 0;
int always_checksum = 0;
int list_only = 0;
void usage(int F)
{
rprintf(F,"rsync version %s Copyright Andrew Tridgell and Paul Mackerras\n\n",
VERSION);
rprintf(F,"Usage:\t%s [options] src user@host:dest\n",RSYNC_NAME);
rprintf(F,"OR\t%s [options] user@host:src dest\n",RSYNC_NAME);
rprintf(F,"OR\t%s [options] src dest\n",RSYNC_NAME);
rprintf(F,"OR\t%s [options] user@host::src dest\n",RSYNC_NAME);
rprintf(F,"OR\t%s [options] src user@host::dest\n",RSYNC_NAME);
rprintf(F,"\nOptions:\n");
rprintf(F,"-v, --verbose increase verbosity\n");
rprintf(F,"-c, --checksum always checksum\n");
rprintf(F,"-a, --archive archive mode\n");
rprintf(F,"-r, --recursive recurse into directories\n");
rprintf(F,"-R, --relative use relative path names\n");
rprintf(F,"-b, --backup make backups (default ~ extension)\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,"-H, --hard-links preserve hard links\n");
rprintf(F,"-p, --perms preserve permissions\n");
rprintf(F,"-o, --owner preserve owner (root only)\n");
rprintf(F,"-g, --group preserve group\n");
rprintf(F,"-D, --devices preserve devices (root only)\n");
rprintf(F,"-t, --times preserve times\n");
rprintf(F,"-S, --sparse handle sparse files efficiently\n");
rprintf(F,"-n, --dry-run show what would have been transferred\n");
rprintf(F,"-W, --whole-file copy whole files, no incremental checks\n");
rprintf(F,"-x, --one-file-system don't cross filesystem boundaries\n");
rprintf(F,"-B, --block-size SIZE checksum blocking size\n");
rprintf(F,"-e, --rsh COMMAND specify rsh replacement\n");
rprintf(F," --rsync-path PATH specify path to rsync on the remote machine\n");
rprintf(F,"-C, --cvs-exclude auto ignore files in the same way CVS does\n");
rprintf(F," --delete delete files that don't exist on the sending side\n");
rprintf(F," --force force deletion of directories even if not empty\n");
rprintf(F," --numeric-ids don't map uid/gid values by user/group name\n");
rprintf(F," --timeout TIME set IO timeout in seconds\n");
rprintf(F,"-I, --ignore-times don't exclude files that match length and time\n");
rprintf(F,"-T --temp-dir DIR create temporary files in directory DIR\n");
rprintf(F,"-z, --compress compress file data\n");
rprintf(F," --exclude FILE exclude file FILE\n");
rprintf(F," --exclude-from FILE exclude files listed in FILE\n");
rprintf(F," --include FILE don't exclude file FILE\n");
rprintf(F," --include-from FILE don't exclude files listed in FILE\n");
rprintf(F," --suffix SUFFIX override backup suffix\n");
rprintf(F," --version print version number\n");
rprintf(F," --daemon run as a rsync daemon\n");
rprintf(F," --config FILE specify alternate rsyncd.conf file\n");
rprintf(F," --port PORT specify alternate rsyncd port number\n");
rprintf(F," --stats give some file transfer stats\n");
rprintf(F,"rsync is a file transfer program capable of efficient remote update\nvia a fast differencing algorithm.\n\n");
rprintf(F,"Usage: rsync [OPTION]... SRC [USER@]HOST:DEST\n");
rprintf(F," or rsync [OPTION]... [USER@]HOST:SRC DEST\n");
rprintf(F," or rsync [OPTION]... SRC DEST\n");
rprintf(F," or rsync [OPTION]... [USER@]HOST::SRC DEST\n");
rprintf(F," or rsync [OPTION]... SRC [USER@]HOST::DEST\n");
rprintf(F," or rsync [OPTION]... rsync://[USER@]HOST[:PORT]/SRC DEST\n");
rprintf(F,"\nOptions\n");
rprintf(F," -v, --verbose increase verbosity\n");
rprintf(F," -c, --checksum always checksum\n");
rprintf(F," -a, --archive archive mode\n");
rprintf(F," -r, --recursive recurse into directories\n");
rprintf(F," -R, --relative use relative path names\n");
rprintf(F," -b, --backup make backups (default ~ extension)\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," --safe-links ignore links outside the destination tree\n");
rprintf(F," -H, --hard-links preserve hard links\n");
rprintf(F," -p, --perms preserve permissions\n");
rprintf(F," -o, --owner preserve owner (root only)\n");
rprintf(F," -g, --group preserve group\n");
rprintf(F," -D, --devices preserve devices (root only)\n");
rprintf(F," -t, --times preserve times\n");
rprintf(F," -S, --sparse handle sparse files efficiently\n");
rprintf(F," -n, --dry-run show what would have been transferred\n");
rprintf(F," -W, --whole-file copy whole files, no incremental checks\n");
rprintf(F," -x, --one-file-system don't cross filesystem boundaries\n");
rprintf(F," -B, --block-size=SIZE checksum blocking size\n");
rprintf(F," -e, --rsh=COMMAND specify rsh replacement\n");
rprintf(F," --rsync-path=PATH specify path to rsync on the remote machine\n");
rprintf(F," -C, --cvs-exclude auto ignore files in the same way CVS does\n");
rprintf(F," --delete delete files that don't exist on the sending side\n");
rprintf(F," --partial keep partially transferred files\n");
rprintf(F," --force force deletion of directories even if not empty\n");
rprintf(F," --numeric-ids don't map uid/gid values by user/group name\n");
rprintf(F," --timeout=TIME set IO timeout in seconds\n");
rprintf(F," -I, --ignore-times don't exclude files that match length and time\n");
rprintf(F," -T --temp-dir=DIR create temporary files in directory DIR\n");
rprintf(F," --compare-dest=DIR also compare destination files relative to DIR\n");
rprintf(F," -z, --compress compress file data\n");
rprintf(F," --exclude=PATTERN exclude files matching PATTERN\n");
rprintf(F," --exclude-from=FILE exclude patterns listed in FILE\n");
rprintf(F," --include=PATTERN don't exclude files matching PATTERN\n");
rprintf(F," --include-from=FILE don't exclude patterns listed in FILE\n");
rprintf(F," --suffix=SUFFIX override backup suffix\n");
rprintf(F," --version print version number\n");
rprintf(F," --daemon run as a rsync daemon\n");
rprintf(F," --config=FILE specify alternate rsyncd.conf file\n");
rprintf(F," --port=PORT specify alternate rsyncd port number\n");
rprintf(F," --stats give some file transfer stats\n");
rprintf(F," --progress show progress during transfer\n");
rprintf(F," --log-format=FORMAT log file transfers using specified format\n");
rprintf(F," -h, --help show this help screen\n");
rprintf(F,"\n");
rprintf(F,"the backup suffix defaults to %s\n",BACKUP_SUFFIX);
@@ -133,7 +148,8 @@ void usage(int F)
enum {OPT_VERSION,OPT_SUFFIX,OPT_SENDER,OPT_SERVER,OPT_EXCLUDE,
OPT_EXCLUDE_FROM,OPT_DELETE,OPT_NUMERIC_IDS,OPT_RSYNC_PATH,
OPT_FORCE,OPT_TIMEOUT,OPT_DAEMON,OPT_CONFIG,OPT_PORT,
OPT_INCLUDE, OPT_INCLUDE_FROM, OPT_STATS};
OPT_INCLUDE, OPT_INCLUDE_FROM, OPT_STATS, OPT_PARTIAL, OPT_PROGRESS,
OPT_SAFE_LINKS, OPT_COMPARE_DEST, OPT_LOG_FORMAT};
static char *short_options = "oblLWHpguDCtcahvrRIxnSe:B:T:z";
@@ -166,6 +182,7 @@ static struct option long_options[] = {
{"perms", 0, 0, 'p'},
{"links", 0, 0, 'l'},
{"copy-links", 0, 0, 'L'},
{"safe-links", 0, 0, OPT_SAFE_LINKS},
{"whole-file", 0, 0, 'W'},
{"hard-links", 0, 0, 'H'},
{"owner", 0, 0, 'o'},
@@ -176,313 +193,354 @@ static struct option long_options[] = {
{"block-size", 1, 0, 'B'},
{"timeout", 1, 0, OPT_TIMEOUT},
{"temp-dir", 1, 0, 'T'},
{"compare-dest", 1, 0, OPT_COMPARE_DEST},
{"compress", 0, 0, 'z'},
{"daemon", 0, 0, OPT_DAEMON},
{"stats", 0, 0, OPT_STATS},
{"progress", 0, 0, OPT_PROGRESS},
{"partial", 0, 0, OPT_PARTIAL},
{"config", 1, 0, OPT_CONFIG},
{"port", 1, 0, OPT_PORT},
{"log-format", 1, 0, OPT_LOG_FORMAT},
{0,0,0,0}};
void parse_arguments(int argc, char *argv[])
int parse_arguments(int argc, char *argv[])
{
int opt;
int option_index;
int opt;
int option_index;
while ((opt = getopt_long(argc, argv,
short_options, long_options, &option_index))
!= -1) {
switch (opt)
{
case OPT_VERSION:
printf("rsync version %s protocol version %d\n",
VERSION,PROTOCOL_VERSION);
exit_cleanup(0);
while ((opt = getopt_long(argc, argv,
short_options, long_options, &option_index))
!= -1) {
switch (opt) {
case OPT_VERSION:
rprintf(FINFO,"rsync version %s protocol version %d\n\n",
VERSION,PROTOCOL_VERSION);
rprintf(FINFO,"Written by Andrew Tridgell and Paul Mackerras\n");
exit_cleanup(0);
case OPT_SUFFIX:
backup_suffix = optarg;
break;
case OPT_RSYNC_PATH:
rsync_path = optarg;
break;
case 'I':
ignore_times = 1;
break;
case OPT_SUFFIX:
backup_suffix = optarg;
break;
case 'x':
one_file_system=1;
break;
case OPT_RSYNC_PATH:
rsync_path = optarg;
break;
case OPT_DELETE:
delete_mode = 1;
break;
case 'I':
ignore_times = 1;
break;
case OPT_FORCE:
force_delete = 1;
break;
case 'x':
one_file_system=1;
break;
case OPT_NUMERIC_IDS:
numeric_ids = 1;
break;
case OPT_DELETE:
delete_mode = 1;
break;
case OPT_EXCLUDE:
add_exclude(optarg, 0);
break;
case OPT_FORCE:
force_delete = 1;
break;
case OPT_INCLUDE:
add_exclude(optarg, 1);
break;
case OPT_NUMERIC_IDS:
numeric_ids = 1;
break;
case OPT_EXCLUDE_FROM:
add_exclude_file(optarg,1, 0);
break;
case OPT_EXCLUDE:
add_exclude(optarg, 0);
break;
case OPT_INCLUDE_FROM:
add_exclude_file(optarg,1, 1);
break;
case OPT_INCLUDE:
add_exclude(optarg, 1);
break;
case OPT_SAFE_LINKS:
safe_symlinks=1;
break;
case OPT_EXCLUDE_FROM:
add_exclude_file(optarg,1, 0);
break;
case 'h':
usage(FINFO);
exit_cleanup(0);
case OPT_INCLUDE_FROM:
add_exclude_file(optarg,1, 1);
break;
case 'b':
make_backups=1;
break;
case 'h':
usage(FINFO);
exit_cleanup(0);
case 'n':
dry_run=1;
break;
case 'b':
make_backups=1;
break;
case 'S':
sparse_files=1;
break;
case 'n':
dry_run=1;
break;
case 'C':
cvs_exclude=1;
break;
case 'S':
sparse_files=1;
break;
case 'u':
update_only=1;
break;
case 'C':
cvs_exclude=1;
break;
case 'l':
preserve_links=1;
break;
case 'u':
update_only=1;
break;
case 'L':
copy_links=1;
break;
case 'l':
preserve_links=1;
break;
case 'W':
whole_file=1;
break;
case 'L':
copy_links=1;
break;
case 'W':
whole_file=1;
break;
case 'H':
case 'H':
#if SUPPORT_HARD_LINKS
preserve_hard_links=1;
preserve_hard_links=1;
#else
rprintf(FERROR,"ERROR: hard links not supported on this platform\n");
exit_cleanup(1);
rprintf(FERROR,"ERROR: hard links not supported on this platform\n");
return 0;
#endif
break;
break;
case 'p':
preserve_perms=1;
break;
case 'p':
preserve_perms=1;
break;
case 'o':
preserve_uid=1;
break;
case 'o':
preserve_uid=1;
break;
case 'g':
preserve_gid=1;
break;
case 'g':
preserve_gid=1;
break;
case 'D':
preserve_devices=1;
break;
case 'D':
preserve_devices=1;
break;
case 't':
preserve_times=1;
break;
case 't':
preserve_times=1;
break;
case 'c':
always_checksum=1;
break;
case 'c':
always_checksum=1;
break;
case 'v':
verbose++;
break;
case 'v':
verbose++;
break;
case 'a':
recurse=1;
case 'a':
recurse=1;
#if SUPPORT_LINKS
preserve_links=1;
preserve_links=1;
#endif
preserve_perms=1;
preserve_times=1;
preserve_gid=1;
if (am_root) {
preserve_devices=1;
preserve_uid=1;
}
break;
preserve_perms=1;
preserve_times=1;
preserve_gid=1;
if (am_root) {
preserve_devices=1;
preserve_uid=1;
}
break;
case OPT_SERVER:
am_server = 1;
break;
case OPT_SERVER:
am_server = 1;
break;
case OPT_SENDER:
if (!am_server) {
usage(FERROR);
exit_cleanup(1);
}
am_sender = 1;
break;
case OPT_SENDER:
if (!am_server) {
usage(FERROR);
exit_cleanup(RERR_SYNTAX);
}
am_sender = 1;
break;
case 'r':
recurse = 1;
break;
case 'r':
recurse = 1;
break;
case 'R':
relative_paths = 1;
break;
case 'R':
relative_paths = 1;
break;
case 'e':
shell_cmd = optarg;
break;
case 'e':
shell_cmd = optarg;
break;
case 'B':
block_size = atoi(optarg);
break;
case 'B':
block_size = atoi(optarg);
break;
case OPT_TIMEOUT:
io_timeout = atoi(optarg);
break;
case OPT_TIMEOUT:
io_timeout = atoi(optarg);
break;
case 'T':
tmpdir = optarg;
break;
case 'T':
tmpdir = optarg;
break;
case 'z':
do_compression = 1;
break;
case OPT_COMPARE_DEST:
compare_dest = optarg;
break;
case OPT_DAEMON:
am_daemon = 1;
break;
case 'z':
do_compression = 1;
break;
case OPT_STATS:
do_stats = 1;
break;
case OPT_DAEMON:
am_daemon = 1;
break;
case OPT_CONFIG:
config_file = optarg;
break;
case OPT_STATS:
do_stats = 1;
break;
case OPT_PORT:
rsync_port = atoi(optarg);
break;
case OPT_PROGRESS:
do_progress = 1;
break;
default:
/* rprintf(FERROR,"bad option -%c\n",opt); */
exit_cleanup(1);
case OPT_PARTIAL:
keep_partial = 1;
break;
case OPT_CONFIG:
config_file = optarg;
break;
case OPT_PORT:
rsync_port = atoi(optarg);
break;
case OPT_LOG_FORMAT:
log_format = optarg;
break;
default:
return 0;
}
}
}
return 1;
}
void server_options(char **args,int *argc)
{
int ac = *argc;
static char argstr[50];
static char bsize[30];
static char iotime[30];
int i, x;
int ac = *argc;
static char argstr[50];
static char bsize[30];
static char iotime[30];
int i, x;
args[ac++] = "--server";
args[ac++] = "--server";
if (!am_sender)
args[ac++] = "--sender";
if (!am_sender)
args[ac++] = "--sender";
x = 1;
argstr[0] = '-';
for (i=0;i<verbose;i++)
argstr[x++] = 'v';
if (make_backups)
argstr[x++] = 'b';
if (update_only)
argstr[x++] = 'u';
if (dry_run)
argstr[x++] = 'n';
if (preserve_links)
argstr[x++] = 'l';
if (copy_links)
argstr[x++] = 'L';
if (whole_file)
argstr[x++] = 'W';
if (preserve_hard_links)
argstr[x++] = 'H';
if (preserve_uid)
argstr[x++] = 'o';
if (preserve_gid)
argstr[x++] = 'g';
if (preserve_devices)
argstr[x++] = 'D';
if (preserve_times)
argstr[x++] = 't';
if (preserve_perms)
argstr[x++] = 'p';
if (recurse)
argstr[x++] = 'r';
if (always_checksum)
argstr[x++] = 'c';
if (cvs_exclude)
argstr[x++] = 'C';
if (ignore_times)
argstr[x++] = 'I';
if (relative_paths)
argstr[x++] = 'R';
if (one_file_system)
argstr[x++] = 'x';
if (sparse_files)
argstr[x++] = 'S';
if (do_compression)
argstr[x++] = 'z';
argstr[x] = 0;
x = 1;
argstr[0] = '-';
for (i=0;i<verbose;i++)
argstr[x++] = 'v';
if (make_backups)
argstr[x++] = 'b';
if (update_only)
argstr[x++] = 'u';
if (dry_run)
argstr[x++] = 'n';
if (preserve_links)
argstr[x++] = 'l';
if (copy_links)
argstr[x++] = 'L';
if (whole_file)
argstr[x++] = 'W';
if (preserve_hard_links)
argstr[x++] = 'H';
if (preserve_uid)
argstr[x++] = 'o';
if (preserve_gid)
argstr[x++] = 'g';
if (preserve_devices)
argstr[x++] = 'D';
if (preserve_times)
argstr[x++] = 't';
if (preserve_perms)
argstr[x++] = 'p';
if (recurse)
argstr[x++] = 'r';
if (always_checksum)
argstr[x++] = 'c';
if (cvs_exclude)
argstr[x++] = 'C';
if (ignore_times)
argstr[x++] = 'I';
if (relative_paths)
argstr[x++] = 'R';
if (one_file_system)
argstr[x++] = 'x';
if (sparse_files)
argstr[x++] = 'S';
if (do_compression)
argstr[x++] = 'z';
argstr[x] = 0;
if (x != 1) args[ac++] = argstr;
if (x != 1) args[ac++] = argstr;
if (block_size != BLOCK_SIZE) {
sprintf(bsize,"-B%d",block_size);
args[ac++] = bsize;
}
if (block_size != BLOCK_SIZE) {
sprintf(bsize,"-B%d",block_size);
args[ac++] = bsize;
}
if (io_timeout) {
sprintf(iotime,"--timeout=%d",io_timeout);
args[ac++] = iotime;
}
if (io_timeout) {
sprintf(iotime,"--timeout=%d",io_timeout);
args[ac++] = iotime;
}
if (strcmp(backup_suffix, BACKUP_SUFFIX)) {
args[ac++] = "--suffix";
args[ac++] = backup_suffix;
}
if (strcmp(backup_suffix, BACKUP_SUFFIX)) {
args[ac++] = "--suffix";
args[ac++] = backup_suffix;
}
if (delete_mode)
args[ac++] = "--delete";
if (delete_mode)
args[ac++] = "--delete";
if (force_delete)
args[ac++] = "--force";
if (keep_partial)
args[ac++] = "--partial";
if (numeric_ids)
args[ac++] = "--numeric-ids";
if (force_delete)
args[ac++] = "--force";
if (tmpdir) {
args[ac++] = "--temp-dir";
args[ac++] = tmpdir;
}
if (safe_symlinks)
args[ac++] = "--safe-links";
*argc = ac;
if (numeric_ids)
args[ac++] = "--numeric-ids";
if (tmpdir) {
args[ac++] = "--temp-dir";
args[ac++] = tmpdir;
}
if (compare_dest && am_sender) {
/* the server only needs this option if it is not the sender,
* and it may be an older version that doesn't know this
* option, so don't send it if client is the sender.
*/
args[ac++] = "--compare-dest";
args[ac++] = compare_dest;
}
*argc = ac;
}

View File

@@ -1,10 +1,10 @@
Summary: Program for efficient remote updates of files.
Name: rsync
Version: 2.0.16
Version: 2.2.0
Release: 1
Copyright: GPL
Group: Applications/Networking
Source: ftp://samba.anu.edu.au/pub/rsync/rsync-2.0.16.tar.gz
Source: ftp://samba.anu.edu.au/pub/rsync/rsync-2.2.0.tar.gz
URL: http://samba.anu.edu.au/rsync/
Packager: Andrew Tridgell <tridge@samba.anu.edu.au>
BuildRoot: /tmp/rsync

471
receiver.c Normal file
View File

@@ -0,0 +1,471 @@
/*
Copyright (C) Andrew Tridgell 1996
Copyright (C) Paul Mackerras 1996
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "rsync.h"
extern int verbose;
extern int recurse;
extern int delete_mode;
extern int remote_version;
extern int csum_length;
extern struct stats stats;
extern int dry_run;
extern int am_server;
extern int relative_paths;
extern int preserve_hard_links;
extern int cvs_exclude;
extern int io_error;
extern char *tmpdir;
extern char *compare_dest;
static struct delete_list {
dev_t dev;
INO_T inode;
} *delete_list;
static int dlist_len, dlist_alloc_len;
/* yuck! This function wouldn't have been necessary if I had the sorting
algorithm right. Unfortunately fixing the sorting algorithm would introduce
a backward incompatibility as file list indexes are sent over the link.
*/
static int delete_already_done(struct file_list *flist,int j)
{
int i;
STRUCT_STAT st;
if (link_stat(f_name(flist->files[j]), &st)) return 1;
for (i=0;i<dlist_len;i++) {
if (st.st_ino == delete_list[i].inode &&
st.st_dev == delete_list[i].dev)
return 1;
}
return 0;
}
static void add_delete_entry(struct file_struct *file)
{
if (dlist_len == dlist_alloc_len) {
dlist_alloc_len += 1024;
delete_list = (struct delete_list *)Realloc(delete_list, sizeof(delete_list[0])*dlist_alloc_len);
if (!delete_list) out_of_memory("add_delete_entry");
}
delete_list[dlist_len].dev = file->dev;
delete_list[dlist_len].inode = file->inode;
dlist_len++;
if (verbose > 3)
rprintf(FINFO,"added %s to delete list\n", f_name(file));
}
static void delete_one(struct file_struct *f)
{
if (!S_ISDIR(f->mode)) {
if (do_unlink(f_name(f)) != 0) {
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,"rmdir %s : %s\n",f_name(f),strerror(errno));
} else if (verbose) {
rprintf(FINFO,"deleting directory %s\n",f_name(f));
}
}
}
/* this deletes any files on the receiving side that are not present
on the sending side. For version 1.6.4 I have changed the behaviour
to match more closely what most people seem to expect of this option */
static void delete_files(struct file_list *flist)
{
struct file_list *local_file_list;
int i, j;
char *name;
if (cvs_exclude)
add_cvs_excludes();
if (io_error) {
rprintf(FINFO,"IO error encountered - skipping file deletion\n");
return;
}
for (j=0;j<flist->count;j++) {
if (!S_ISDIR(flist->files[j]->mode) ||
!(flist->files[j]->flags & FLAG_DELETE)) continue;
if (remote_version < 19 &&
delete_already_done(flist, j)) continue;
name = strdup(f_name(flist->files[j]));
if (!(local_file_list = send_file_list(-1,1,&name))) {
free(name);
continue;
}
if (verbose > 1)
rprintf(FINFO,"deleting in %s\n", name);
for (i=local_file_list->count-1;i>=0;i--) {
if (!local_file_list->files[i]->basename) continue;
if (remote_version < 19 &&
S_ISDIR(local_file_list->files[i]->mode))
add_delete_entry(local_file_list->files[i]);
if (-1 == flist_find(flist,local_file_list->files[i])) {
delete_one(local_file_list->files[i]);
}
}
flist_free(local_file_list);
free(name);
}
}
static int get_tmpname(char *fnametmp, char *fname)
{
char *f;
/* open tmp file */
if (tmpdir) {
f = strrchr(fname,'/');
if (f == NULL)
f = fname;
else
f++;
if (strlen(tmpdir)+strlen(f)+10 > MAXPATHLEN) {
rprintf(FERROR,"filename too long\n");
return 0;
}
slprintf(fnametmp,MAXPATHLEN-1, "%s/.%s.XXXXXX",tmpdir,f);
return 1;
}
f = strrchr(fname,'/');
if (strlen(fname)+9 > MAXPATHLEN) {
rprintf(FERROR,"filename too long\n");
return 0;
}
if (f) {
*f = 0;
slprintf(fnametmp,MAXPATHLEN-1,"%s/.%s.XXXXXX",
fname,f+1);
*f = '/';
} else {
slprintf(fnametmp,MAXPATHLEN-1,".%s.XXXXXX",fname);
}
return 1;
}
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;
OFF_T offset = 0;
OFF_T offset2;
char *data;
static char file_sum1[MD4_SUM_LENGTH];
static char file_sum2[MD4_SUM_LENGTH];
char *map=NULL;
count = read_int(f_in);
n = read_int(f_in);
remainder = read_int(f_in);
sum_init();
for (i=recv_token(f_in,&data); i != 0; i=recv_token(f_in,&data)) {
show_progress(offset, total_size);
if (i > 0) {
extern int cleanup_got_literal;
if (verbose > 3) {
rprintf(FINFO,"data recv %d at %d\n",
i,(int)offset);
}
stats.literal_data += i;
cleanup_got_literal = 1;
sum_update(data,i);
if (fd != -1 && write_file(fd,data,i) != i) {
rprintf(FERROR,"write failed on %s : %s\n",fname,strerror(errno));
exit_cleanup(RERR_FILEIO);
}
offset += i;
continue;
}
i = -(i+1);
offset2 = i*n;
len = n;
if (i == count-1 && remainder != 0)
len = remainder;
stats.matched_data += len;
if (verbose > 3)
rprintf(FINFO,"chunk[%d] of size %d at %d offset=%d\n",
i,len,(int)offset2,(int)offset);
map = map_ptr(buf,offset2,len);
see_token(map, len);
sum_update(map,len);
if (fd != -1 && write_file(fd,map,len) != len) {
rprintf(FERROR,"write failed on %s : %s\n",
fname,strerror(errno));
exit_cleanup(RERR_FILEIO);
}
offset += len;
}
end_progress();
if (fd != -1 && offset > 0 && sparse_end(fd) != 0) {
rprintf(FERROR,"write failed on %s : %s\n",
fname,strerror(errno));
exit_cleanup(RERR_FILEIO);
}
sum_end(file_sum1);
if (remote_version >= 14) {
read_buf(f_in,file_sum2,MD4_SUM_LENGTH);
if (verbose > 2) {
rprintf(FINFO,"got file_sum\n");
}
if (fd != -1 &&
memcmp(file_sum1,file_sum2,MD4_SUM_LENGTH) != 0) {
return 0;
}
}
return 1;
}
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 fnametmp[MAXPATHLEN];
char *fnamecmp;
char fnamecmpbuf[MAXPATHLEN];
struct map_struct *buf;
int i;
struct file_struct *file;
int phase=0;
int recv_ok;
extern struct stats stats;
struct stats initial_stats;
if (verbose > 2) {
rprintf(FINFO,"recv_files(%d) starting\n",flist->count);
}
if (recurse && delete_mode && !local_name && flist->count>0) {
delete_files(flist);
}
while (1) {
cleanup_disable();
i = read_int(f_in);
if (i == -1) {
if (phase==0 && remote_version >= 13) {
phase++;
csum_length = SUM_LENGTH;
if (verbose > 2)
rprintf(FINFO,"recv_files phase=%d\n",phase);
write_int(f_gen,-1);
continue;
}
break;
}
if (i < 0 || i >= flist->count) {
rprintf(FERROR,"Invalid file index %d in recv_files (count=%d)\n",
i, flist->count);
exit_cleanup(RERR_PROTOCOL);
}
file = flist->files[i];
fname = f_name(file);
stats.num_transferred_files++;
stats.total_transferred_size += file->length;
if (local_name)
fname = local_name;
if (dry_run) {
if (!am_server) {
log_transfer(file, fname);
}
continue;
}
initial_stats = stats;
if (verbose > 2)
rprintf(FINFO,"recv_files(%s)\n",fname);
fnamecmp = fname;
/* open the file */
fd1 = open(fnamecmp,O_RDONLY);
if ((fd1 == -1) && (compare_dest != NULL)) {
/* try the file at compare_dest instead */
slprintf(fnamecmpbuf,MAXPATHLEN-1,"%s/%s",
compare_dest,fname);
fnamecmp = fnamecmpbuf;
fd1 = open(fnamecmp,O_RDONLY);
}
if (fd1 != -1 && do_fstat(fd1,&st) != 0) {
rprintf(FERROR,"fstat %s : %s\n",fnamecmp,strerror(errno));
receive_data(f_in,NULL,-1,NULL,file->length);
close(fd1);
continue;
}
if (fd1 != -1 && !S_ISREG(st.st_mode)) {
rprintf(FERROR,"%s : not a regular file (recv_files)\n",fnamecmp);
receive_data(f_in,NULL,-1,NULL,file->length);
close(fd1);
continue;
}
if (fd1 != -1 && st.st_size > 0) {
buf = map_file(fd1,st.st_size);
if (verbose > 2)
rprintf(FINFO,"recv mapped %s of size %d\n",fnamecmp,(int)st.st_size);
} else {
buf = NULL;
}
if (!get_tmpname(fnametmp,fname)) {
if (buf) unmap_file(buf);
if (fd1 != -1) close(fd1);
continue;
}
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
condition. They are then correctly updated after
the lchown. Thanks to snabb@epipe.fi for pointing
this out */
fd2 = do_open(fnametmp,O_WRONLY|O_CREAT|O_EXCL,
file->mode & ACCESSPERMS);
if (fd2 == -1 && relative_paths && errno == ENOENT &&
create_directory_path(fnametmp) == 0) {
fd2 = do_open(fnametmp,O_WRONLY|O_CREAT|O_EXCL,
file->mode & ACCESSPERMS);
}
if (fd2 == -1) {
rprintf(FERROR,"open %s : %s\n",fnametmp,strerror(errno));
receive_data(f_in,buf,-1,NULL,file->length);
if (buf) unmap_file(buf);
if (fd1 != -1) close(fd1);
continue;
}
cleanup_set(fnametmp, fname, file, buf, fd1, fd2);
if (!am_server) {
log_transfer(file, fname);
}
/* recv file data */
recv_ok = receive_data(f_in,buf,fd2,fname,file->length);
log_recv(file, &initial_stats);
if (buf) unmap_file(buf);
if (fd1 != -1) {
close(fd1);
}
close(fd2);
if (verbose > 2)
rprintf(FINFO,"renaming %s to %s\n",fnametmp,fname);
finish_transfer(fname, fnametmp, file);
cleanup_disable();
if (!recv_ok) {
if (csum_length == SUM_LENGTH) {
rprintf(FERROR,"ERROR: file corruption in %s. File changed during transfer?\n",
fname);
} else {
if (verbose > 1)
rprintf(FINFO,"redoing %s(%d)\n",fname,i);
write_int(f_gen,i);
}
}
}
if (preserve_hard_links)
do_hard_links(flist);
/* now we need to fix any directory permissions that were
modified during the transfer */
for (i = 0; i < flist->count; i++) {
file = flist->files[i];
if (!file->basename || !S_ISDIR(file->mode)) continue;
recv_generator(f_name(file),flist,i,-1);
}
if (verbose > 2)
rprintf(FINFO,"recv_files finished\n");
return 0;
}

1144
rsync.c
View File

File diff suppressed because it is too large Load Diff

120
rsync.h
View File

@@ -23,6 +23,8 @@
#define RSYNC_NAME "rsync"
#define RSYNCD_CONF "/etc/rsyncd.conf"
#define URL_PREFIX "rsync://"
#define BACKUP_SUFFIX "~"
/* a non-zero CHAR_OFFSET makes the rolling sum stronger, but is
@@ -59,6 +61,9 @@
#define MPLEX_BASE 7
#define FERROR 1
#define FINFO 2
#define FLOG 3
#include "errcode.h"
#include "config.h"
@@ -69,6 +74,13 @@
#endif
#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
@@ -91,10 +103,6 @@
#include <string.h>
#endif
#ifdef HAVE_COMPAT_H
#include <compat.h>
#endif
#ifdef HAVE_MALLOC_H
#include <malloc.h>
#endif
@@ -166,13 +174,7 @@
#include "lib/fnmatch.h"
#endif
#ifdef HAVE_GETOPT_LONG
#include <getopt.h>
#else
#include "lib/getopt.h"
#endif
#ifdef HAVE_GLOB
#ifdef HAVE_GLOB_H
#include <glob.h>
#endif
@@ -187,14 +189,26 @@
#include <syslog.h>
#include <sys/file.h>
#ifndef S_IFLNK
#define S_IFLNK 0120000
#if HAVE_DIRENT_H
# include <dirent.h>
#else
# define dirent direct
# if HAVE_SYS_NDIR_H
# include <sys/ndir.h>
# endif
# if HAVE_SYS_DIR_H
# include <sys/dir.h>
# endif
# if HAVE_NDIR_H
# include <ndir.h>
# endif
#endif
#ifndef S_ISLNK
#define S_ISLNK(mode) (((mode) & S_IFLNK) == S_IFLNK)
#ifdef HAVE_COMPAT_H
#include <compat.h>
#endif
#define BOOL int
#ifndef uchar
@@ -214,6 +228,10 @@
#define int32 long
#elif (SIZEOF_SHORT == 4)
#define int32 short
#else
/* I hope this works */
#define int32 int
#define LARGE_INT32
#endif
#endif
@@ -242,6 +260,12 @@
#define NO_INT64
#endif
#if HAVE_SHORT_INO_T
#define INO_T uint32
#else
#define INO_T ino_t
#endif
#ifndef MIN
#define MIN(a,b) ((a)<(b)?(a):(b))
#endif
@@ -267,7 +291,7 @@ struct file_struct {
time_t modtime;
OFF_T length;
mode_t mode;
ino_t inode;
INO_T inode;
dev_t dev;
dev_t rdev;
uid_t uid;
@@ -286,11 +310,11 @@ struct file_list {
};
struct sum_buf {
OFF_T offset; /* offset in file of this chunk */
int len; /* length of chunk of file */
int i; /* index of this chunk */
uint32 sum1; /* simple checksum */
char sum2[SUM_LENGTH]; /* checksum */
OFF_T offset; /* offset in file of this chunk */
int len; /* length of chunk of file */
int i; /* index of this chunk */
uint32 sum1; /* simple checksum */
char sum2[SUM_LENGTH]; /* checksum */
};
struct sum_struct {
@@ -338,25 +362,10 @@ static inline int flist_up(struct file_list *flist, int i)
return i;
}
#if HAVE_DIRENT_H
# include <dirent.h>
#else
# define dirent direct
# if HAVE_SYS_NDIR_H
# include <sys/ndir.h>
# endif
# if HAVE_SYS_DIR_H
# include <sys/dir.h>
# endif
# if HAVE_NDIR_H
# include <ndir.h>
# endif
#endif
#include "byteorder.h"
#include "version.h"
#include "proto.h"
#include "md4.h"
#include "lib/mdfour.h"
#if !HAVE_STRERROR
extern char *sys_errlist[];
@@ -372,14 +381,6 @@ extern char *sys_errlist[];
extern int errno;
#endif
#ifndef HAVE_BCOPY
#define bcopy(src,dest,n) memcpy(dest,src,n)
#endif
#ifndef HAVE_BZERO
#define bzero(buf,n) memset(buf,0,n)
#endif
#define SUPPORT_LINKS HAVE_READLINK
#define SUPPORT_HARD_LINKS HAVE_LINK
@@ -409,6 +410,18 @@ extern int errno;
#define S_IWUSR 0200
#endif
#ifndef _S_IFMT
#define _S_IFMT 0170000
#endif
#ifndef _S_IFLNK
#define _S_IFLNK 0120000
#endif
#ifndef S_ISLNK
#define S_ISLNK(mode) (((mode) & (_S_IFMT)) == (_S_IFLNK))
#endif
#ifndef S_ISBLK
#define S_ISBLK(mode) (((mode) & (_S_IFMT)) == (_S_IFBLK))
#endif
@@ -444,3 +457,20 @@ extern int errno;
#define IS_DEVICE(mode) (S_ISCHR(mode) || S_ISBLK(mode) || S_ISSOCK(mode) || S_ISFIFO(mode))
#ifndef ACCESSPERMS
#define ACCESSPERMS 0777
#endif
/* handler for null strings in printf format */
#define NS(s) ((s)?(s):"<NULL>")
/* use magic gcc attributes to catch format errors */
void rprintf(int , const char *, ...)
#ifdef __GNUC__
__attribute__ ((format (printf, 2, 3)))
#endif
;
#ifdef REPLACE_INET_NTOA
#define inet_ntoa rep_inet_ntoa
#endif

206
rsync.yo
View File

@@ -9,9 +9,11 @@ rsync [options] path [user@]host:path
rsync [options] path path
rsync [options] [user@]host::path path
rsync [options] [user@]host::module[/path] path
rsync [options] path [user@]host::path
rsync [options] path [user@]host::module[/path]
rsync [options] rsync://[user@]host[:port]/module/path path
manpagedescription()
@@ -40,7 +42,7 @@ itemize(
manpagesection(GENERAL)
There are five different ways of using rsync. They are:
There are six different ways of using rsync. They are:
itemize(
it() for copying local files. This is invoked when neither
@@ -57,11 +59,16 @@ itemize(
it() for copying from a remote rsync server to the local
machine. This is invoked when the source path contains a ::
separator.
separator. You can also use a rsync:// URL if no username
is required.
it() for copying from the local machine to a remote rsync
server. This is invoked when the destination path contains a ::
separator.
it() for listing files on a remote machine. This is done the
same way as rsync transfers except that you leave off the
local destination.
)
Note that in all cases at least one of the source and destination
@@ -140,6 +147,9 @@ itemize(
it() if you specify no path name on the remote server then the
list of accessible paths on the server will be shown.
it() if you specify no local destination then a listing of the
specified files on the remote server is provided
)
Some paths on the remote server may require authentication. If so then
@@ -187,6 +197,68 @@ quote(rsync -az -e ssh --delete ~ftp/pub/samba/ nimbus:"~ftp/pub/tridge/samba")
this is launched from cron every few hours.
manpagesection(OPTIONS SUMMARY)
Here is a short summary of the options avalable in rsync. Please refer
to the detailed description below for a complete description.
verb(
Usage: rsync [OPTION]... SRC [USER@]HOST:DEST
or rsync [OPTION]... [USER@]HOST:SRC DEST
or rsync [OPTION]... SRC DEST
or rsync [OPTION]... [USER@]HOST::SRC DEST
or rsync [OPTION]... SRC [USER@]HOST::DEST
or rsync [OPTION]... rsync://[USER@]HOST[:PORT]/SRC DEST
Options
-v, --verbose increase verbosity
-c, --checksum always checksum
-a, --archive archive mode
-r, --recursive recurse into directories
-R, --relative use relative path names
-b, --backup make backups (default ~ extension)
-u, --update update only (don't overwrite newer files)
-l, --links preserve soft links
-L, --copy-links treat soft links like regular files
--safe-links ignore links outside the destination tree
-H, --hard-links preserve hard links
-p, --perms preserve permissions
-o, --owner preserve owner (root only)
-g, --group preserve group
-D, --devices preserve devices (root only)
-t, --times preserve times
-S, --sparse handle sparse files efficiently
-n, --dry-run show what would have been transferred
-W, --whole-file copy whole files, no incremental checks
-x, --one-file-system don't cross filesystem boundaries
-B, --block-size=SIZE checksum blocking size
-e, --rsh=COMMAND specify rsh replacement
--rsync-path=PATH specify path to rsync on the remote machine
-C, --cvs-exclude auto ignore files in the same way CVS does
--delete delete files that don't exist on the sending side
--partial keep partially transferred files
--force force deletion of directories even if not empty
--numeric-ids don't map uid/gid values by user/group name
--timeout=TIME set IO timeout in seconds
-I, --ignore-times don't exclude files that match length and time
-T --temp-dir=DIR create temporary files in directory DIR
--compare-dest=DIR also compare destination files relative to DIR
-z, --compress compress file data
--exclude=PATTERN exclude files matching PATTERN
--exclude-from=FILE exclude files listed in FILE
--include=PATTERN don't exclude files matching PATTERN
--include-from=FILE don't exclude files listed in FILE
--suffix=SUFFIX override backup suffix
--version print version number
--daemon run as a rsync daemon
--config=FILE specify alternate rsyncd.conf file
--port=PORT specify alternate rsyncd port number
--stats give some file transfer stats
--progress show progress during transfer
--log-format=FORMAT log file transfers using specified format
-h, --help show this help screen
)
manpageoptions()
rsync uses the GNU long options package. Many of the command line
@@ -256,6 +328,11 @@ option all symbolic links are skipped.
dit(bf(-L, --copy-links)) This tells rsync to treat symbolic links just
like ordinary files.
dit(bf(--safe-links)) This tells rsync to ignore any symbolic links
which point outside the destination tree. All absolute symlinks are
also ignored. Using this option in conjunction with --relative may
give unexpecetd results.
dit(bf(-H, --hard-links)) This tells rsync to recreate hard links on
the remote system to be the same as the local system. Without this
option hard links are treated like regular files.
@@ -269,15 +346,25 @@ dit(bf(-W, --whole-file)) With this option the incremental rsync algorithm
is not used and the whole file is sent as-is instead. This may be
useful when using rsync with a local machine.
dit(bf(--partial)) By default rsync will delete any partially
transferred file if the transfer is interrupted. In some circumstances
it is more desirable to keep partially transferred files. Using the
--partial option tells rsync to keep the partial file which should
make a subsequent transfer of the rest of the file much faster.
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.
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 user names.
dit(bf(-g, --group)) This option causes rsync to update the remote group
of the file to be the same as the local group.
of the file to be the same as the local group. 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 group names.
dit(bf(-D, --devices)) This option causes rsync to transfer character and
block device information to the remote system to recreate these
@@ -292,6 +379,10 @@ instead it will just report the actions it would have taken.
dit(bf(-S, --sparse)) Try to handle sparse files efficiently so they take
up less space on the destination.
NOTE: Don't use this option when the destination is a Solaris "tmpfs"
filesystem. It doesn't seem to handle seeks over null regions
correctly and ends up corrupting the files.
dit(bf(-x, --one-file-system)) This tells rsync not to cross filesystem
boundaries when recursing. This is useful for transferring the
contents of only one filesystem.
@@ -313,9 +404,11 @@ Still, it is probably easy to get burnt with this option. The moral
of the story is to use the -n option until you get used to the
behavior of --delete.
NOTE: It also may delete files on the destination if the sending side
can't open them or stat them. This is a bug that hopefully will be
fixed in a future release.
If the sending side detects any IO errors then the deletion of any
files at the destination will be automatically disabled. This is to
prevent temporary filesystem failures (such as NFS errors) on the
sending side causing a massive deletion of files on the
destination.
dit(bf(--force)) This options tells rsync to delete directories even if
they are not empty. This applies to both the --delete option and to
@@ -388,7 +481,7 @@ 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
find that a truncated version of this checksum is quite efficient, and
this will decrease the size of the checksum data sent over the link,
making things faster.
making things faster.
You can choose the number of bytes in the truncated checksum using the
--csum-length option. Any value less than or equal to 16 is valid.
@@ -398,11 +491,26 @@ with an incorrect target file. The risk with a value of 16 is
microscopic and can be safely ignored (the universe will probably end
before it fails) but with smaller values the risk is higher.
dit(bf(-T, --temp-dir DIR)) This options instructs rsync to use DIR as a
scratch directory when creating a temporary copies of the files
Current versions of rsync actually use an adaptive algorithm for the
checksum length by default, using a 16 byte file checksum to determine
if a 2nd pass is required with a longer block checksum. Only use this
option if you have read the source code and know what you are doing.
dit(bf(-T, --temp-dir DIR)) This option instructs rsync to use DIR as a
scratch directory when creating temporary copies of the files
transferred on the receiving side. The default behavior is to create
the temporary files in the receiving directory.
dit(bf(--compare-dest DIR)) This option instructs rsync to use DIR as an
additional directory to compare destination files against when doing
transfers. This is useful for doing transfers to a new destination while
leaving existing files intact, and then doing a flash-cutover when all
files have been successfully transfered (for example by moving directories
around and removing the old directory). This option increases the
usefulness of --partial because partially transferred files will remain in
the new temporary destination until they have a chance to be completed.
If DIR is a relative path, it is relative to the destination directory.
dit(bf(-z, --compress)) With this option, rsync compresses any data from
the source file(s) which it sends to the destination machine. This
option is useful on slow links. The compression method used is the
@@ -422,12 +530,13 @@ what ownership to give files. The special uid 0 and the special group
0 and never mapped via user/group names even if the --numeric-ids
option is not specified.
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)) 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(--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
@@ -444,9 +553,19 @@ specified.
dit(bf(--port PORT)) This specifies an alternate TCP port number to use
rather than the default port 873.
dit(bf(--log-format=FORMAT)) Normally rsync just logs filenames as
they are transferred. This allows you to specify exactly what gets
logged on a per file basis. The log format is specified using the same
format conventions as the log format option in rsyncd.conf.
dit(bf(--stats)) This tells rsync to print a verbose set of statistics
on the file transfer, allowing you to tell how effective the rsync
algorithm is for your data.
algorithm is for your data. This option only works in conjunction with
the -v (verbose) option.
dit(bf(--progress)) This option tells rsync to print information
showing the progress of the transfer. This gives a bored user
something to watch.
enddit()
@@ -492,6 +611,9 @@ itemize(
it() if the pattern starts with "- " (a minus followed by a space)
then it is always considered a exclude pattern, even if specified as
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.
)
The +/- rules are most useful in exclude lists, allowing you to have a
@@ -507,6 +629,54 @@ itemize(
directories and C source files.
)
manpagesection(DIAGNOSTICS)
rsync occasinally produces error messages that may seem a little
cryptic. The one that seems to cause the most confusion is "protocol
version mismatch - is your shell clean?".
This message is usually caused by your startup scripts or remote shell
facility producing unwanted garbage on the stream that rsync is using
for its transport. The way ot diagnose this problem is to run your
remote shell like this:
verb(
rsh remotehost /bin/true > out.dat
)
then look at out.dat. If everything is working correctly then out.dat
should be a zero length file. You you are getting the above error from
rsync then you will probably find that out.dat contains some text or
data. Look at the contents and try to work out what is producing
it. The most common cause is incorrectly configued shell startup
scripts (such as .cshrc or .profile) that contain output statements
for non-interactive logins.
manpagesection(ENVIRONMENT VARIABLES)
startdit()
dit(bf(CVSIGNORE)) The CVSIGNORE environment variable supplements any
ignore patterns in .cvsignore files. See the --cvs-exclude option for
more details.
dit(bf(RSYNC_RSH)) The RSYNC_RSH environment variable allows you to
override the default shell used as the transport for rsync. This can
be used instead of the -e option.
dit(bf(RSYNC_PASSWORD)) Setting RSYNC_PASSWORD to the required
password allows you to run authenticated rsync connections to a rsync
daemon without user intervention. Note that this does not supply a
password to a shell transport such as ssh.
dit(bf(USER) or bf(LOGNAME)) The USER or LOGNAME environment variables
are used to determine the default username sent to a rsync server.
dit(bf(HOME)) The HOME environment variable is used to find the users
default .cvsignore file.
enddit()
manpagefiles()
/etc/rsyncd.conf

View File

@@ -91,6 +91,14 @@ support the "max connections" option. The rsync server uses record
locking on this file to ensure that the max connections limit is not
exceeded. The default is tt(/var/run/rsyncd.lock).
dit(bf(log file)) The "log file" option tells the rsync daemon to log
messages to that file rather than using syslog. This is particularly
useful on systems (such as AIX) where syslog() doesn't work for
chrooted programs.
dit(bf(pid file)) The "pid file" option tells the rsync daemon to write
its process id to that file.
dit(bf(syslog facility)) The "syslog facility" option allows you to
specify the syslog facility name to use when logging messages from the
rsync server. You may use any standard syslog facility name which is
@@ -99,6 +107,39 @@ ftp, kern, lpr, mail, news, security, syslog, user, uucp, local0,
local1, local2, local3, local4, local5, local6 and local7. The default
is daemon.
dit(bf(transfer logging)) The "transfer logging" option enables per-file
logging of downloads and uploads in a format somewhat similar to that
used by ftp daemons. If you want to customise the log formats look at
log_send, log_recv and log_transfer in log.c
dit(bf(log format)) The "log format" option allows you to specify the
format used for logging file transfers when transfer logging is
enabled. The format is a text string containing embedded single
character escape sequences prefixed with a percent (%) character.
The prefixes that are understood are:
itemize(
it() %h for the remote host name
it() %a for the remote IP address
it() %l for the length of the file in bytes
it() %p for the process id of this rsync session
it() %o for the operation, which is either "send" or "recv"
it() %f for the filename
it() %P for the module path
it() %m for the module name
it() %t for the current time
it() %u for the authenticated username (or the null string)
it() %b for the number of bytes actually transferred
it() %c when sending files this gives the number of checksum bytes
received for this file
)
The default log format is "%o %h [%a] %m (%u) %f %l"
A perl script called rsyncstats to summarise this format is included
in the rsync source code distribution.
dit(bf(socket options)) This option can provide endless fun for people
who like to tune their systems to the utmost degree. You can set all
sorts of socket options which may make transfers faster (or
@@ -123,9 +164,15 @@ that is displayed next to the module name when clients obtain a list
of available modules. The default is no comment.
dit(bf(path)) The "path" option specifies the directory in the servers
filesystem to make available in this module. The rsync server will
chroot to this path before starting the file transfer with the
client. You must specify this option for each module in tt(/etc/rsyncd.conf).
filesystem to make available in this module. You must specify this option
for each module in tt(/etc/rsyncd.conf).
dit(bf(use chroot)) If "use chroot" is true, the rsync server will chroot
to the "path" before starting the file transfer with the client. This has
the advantage of extra protection against possible implementation security
holes, but it has the disadvantages of requiring super-user privileges and
of not being able to follow symbolic links outside of the new root path.
The default is to use chroot.
dit(bf(read only)) The "read only" option determines whether clients
will be able to upload files or not. If "read only" is true then any
@@ -225,7 +272,7 @@ connect.
The default is no "hosts allow" option, which means all hosts can connect.
dit(bf(hosts allow)) The "hosts deny" option allows you to specify a
dit(bf(hosts deny)) The "hosts deny" option allows you to specify a
list of patterns that are matched against a connecting clients
hostname and IP address. If the pattern matches then the connection is
rejected. See the "hosts allow" option for more information.
@@ -267,8 +314,10 @@ A more sophisticated example would be:
uid = nobody nl()
gid = nobody nl()
use chroot = no nl()
max connections = 4 nl()
syslog facility = local5 nl()
pid file = /etc/rsyncd.pid
verb([ftp]
path = /var/ftp/pub

228
sender.c Normal file
View File

@@ -0,0 +1,228 @@
/*
Copyright (C) Andrew Tridgell 1996
Copyright (C) Paul Mackerras 1996
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "rsync.h"
extern int verbose;
extern int remote_version;
extern int csum_length;
extern struct stats stats;
extern int io_error;
extern int dry_run;
extern int am_server;
/*
receive the checksums for a buffer
*/
static struct sum_struct *receive_sums(int f)
{
struct sum_struct *s;
int i;
OFF_T offset = 0;
s = (struct sum_struct *)malloc(sizeof(*s));
if (!s) out_of_memory("receive_sums");
s->count = read_int(f);
s->n = read_int(f);
s->remainder = read_int(f);
s->sums = NULL;
if (verbose > 3)
rprintf(FINFO,"count=%d n=%d rem=%d\n",
s->count,s->n,s->remainder);
if (s->count == 0)
return(s);
s->sums = (struct sum_buf *)malloc(sizeof(s->sums[0])*s->count);
if (!s->sums) out_of_memory("receive_sums");
for (i=0;i<s->count;i++) {
s->sums[i].sum1 = read_int(f);
read_buf(f,s->sums[i].sum2,csum_length);
s->sums[i].offset = offset;
s->sums[i].i = i;
if (i == s->count-1 && s->remainder != 0) {
s->sums[i].len = s->remainder;
} else {
s->sums[i].len = s->n;
}
offset += s->sums[i].len;
if (verbose > 3)
rprintf(FINFO,"chunk[%d] len=%d offset=%d sum1=%08x\n",
i,s->sums[i].len,(int)s->sums[i].offset,s->sums[i].sum1);
}
s->flength = offset;
return s;
}
void send_files(struct file_list *flist,int f_out,int f_in)
{
int fd;
struct sum_struct *s;
struct map_struct *buf;
STRUCT_STAT st;
char fname[MAXPATHLEN];
int i;
struct file_struct *file;
int phase = 0;
extern struct stats stats;
struct stats initial_stats;
if (verbose > 2)
rprintf(FINFO,"send_files starting\n");
setup_readbuffer(f_in);
while (1) {
int offset=0;
i = read_int(f_in);
if (i == -1) {
if (phase==0 && remote_version >= 13) {
phase++;
csum_length = SUM_LENGTH;
write_int(f_out,-1);
if (verbose > 2)
rprintf(FINFO,"send_files phase=%d\n",phase);
continue;
}
break;
}
if (i < 0 || i >= flist->count) {
rprintf(FERROR,"Invalid file index %d (count=%d)\n",
i, flist->count);
exit_cleanup(RERR_PROTOCOL);
}
file = flist->files[i];
stats.num_transferred_files++;
stats.total_transferred_size += file->length;
fname[0] = 0;
if (file->basedir) {
strlcpy(fname,file->basedir,MAXPATHLEN-1);
if (strlen(fname) == MAXPATHLEN-1) {
io_error = 1;
rprintf(FERROR, "send_files failed on long-named directory %s\n",
fname);
return;
}
strlcat(fname,"/",MAXPATHLEN-1);
offset = strlen(file->basedir)+1;
}
strlcat(fname,f_name(file),MAXPATHLEN-strlen(fname));
if (verbose > 2)
rprintf(FINFO,"send_files(%d,%s)\n",i,fname);
if (dry_run) {
if (!am_server) {
log_transfer(file, fname+offset);
}
write_int(f_out,i);
continue;
}
initial_stats = stats;
s = receive_sums(f_in);
if (!s) {
io_error = 1;
rprintf(FERROR,"receive_sums failed\n");
return;
}
fd = open(fname,O_RDONLY);
if (fd == -1) {
io_error = 1;
rprintf(FERROR,"send_files failed to open %s: %s\n",
fname,strerror(errno));
free_sums(s);
continue;
}
/* map the local file */
if (do_fstat(fd,&st) != 0) {
io_error = 1;
rprintf(FERROR,"fstat failed : %s\n",strerror(errno));
free_sums(s);
close(fd);
return;
}
if (st.st_size > 0) {
buf = map_file(fd,st.st_size);
} else {
buf = NULL;
}
if (verbose > 2)
rprintf(FINFO,"send_files mapped %s of size %d\n",
fname,(int)st.st_size);
write_int(f_out,i);
write_int(f_out,s->count);
write_int(f_out,s->n);
write_int(f_out,s->remainder);
if (verbose > 2)
rprintf(FINFO,"calling match_sums %s\n",fname);
if (!am_server) {
log_transfer(file, fname+offset);
}
match_sums(f_out,s,buf,st.st_size);
log_send(file, &initial_stats);
if (buf) unmap_file(buf);
close(fd);
free_sums(s);
if (verbose > 2)
rprintf(FINFO,"sender finished %s\n",fname);
}
if (verbose > 2)
rprintf(FINFO,"send files finished\n");
match_report();
write_int(f_out,-1);
}

View File

@@ -54,6 +54,8 @@ int open_socket_out(char *host, int port)
return -1;
}
set_nonblocking(res);
return res;
}
@@ -81,7 +83,7 @@ static int open_socket_in(int type, int port)
return -1;
}
bzero((char *)&sock,sizeof(sock));
memset((char *)&sock,0,sizeof(sock));
memcpy((char *)&sock.sin_addr,(char *)hp->h_addr, hp->h_length);
sock.sin_port = htons(port);
sock.sin_family = hp->h_addrtype;
@@ -110,9 +112,9 @@ determine if a file descriptor is in fact a socket
****************************************************************************/
int is_a_socket(int fd)
{
int v,l;
l = sizeof(int);
return(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&v, &l) == 0);
int v,l;
l = sizeof(int);
return(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&v, &l) == 0);
}
@@ -120,17 +122,15 @@ void start_accept_loop(int port, int (*fn)(int ))
{
int s;
signal(SIGCHLD, SIG_IGN);
/* open an incoming socket */
s = open_socket_in(SOCK_STREAM, port);
if (s == -1)
exit_cleanup(1);
exit_cleanup(RERR_SOCKETIO);
/* ready to listen */
if (listen(s, 5) == -1) {
close(s);
exit_cleanup(1);
exit_cleanup(RERR_SOCKETIO);
}
@@ -155,9 +155,20 @@ void start_accept_loop(int port, int (*fn)(int ))
if (fd == -1) continue;
signal(SIGCHLD, SIG_IGN);
/* we shouldn't have any children left hanging around
but I have had reports that on Digital Unix zombies
are produced, so this ensures that they are reaped */
#ifdef WNOHANG
waitpid(-1, NULL, WNOHANG);
#endif
if (fork()==0) {
close(s);
set_nonblocking(fd);
_exit(fn(fd));
}
@@ -274,27 +285,30 @@ become a daemon, discarding the controlling terminal
****************************************************************************/
void become_daemon(void)
{
if (fork())
int i;
if (fork()) {
_exit(0);
}
/* detach from the terminal */
#ifdef HAVE_SETSID
setsid();
#else
#ifdef TIOCNOTTY
{
int i = open("/dev/tty", O_RDWR);
if (i >= 0)
{
ioctl(i, (int) TIOCNOTTY, (char *)0);
close(i);
}
i = open("/dev/tty", O_RDWR);
if (i >= 0) {
ioctl(i, (int) TIOCNOTTY, (char *)0);
close(i);
}
#endif /* TIOCNOTTY */
#endif
close(0);
close(1);
close(2);
/* make sure that stdin, stdout an stderr don't stuff things
up (library functions, for example) */
for (i=0;i<3;i++) {
close(i);
open("/dev/null", O_RDWR);
}
}
/*******************************************************************
@@ -306,13 +320,17 @@ char *client_addr(int fd)
struct sockaddr_in *sockin = (struct sockaddr_in *) (&sa);
int length = sizeof(sa);
static char addr_buf[100];
static int initialised;
if (initialised) return addr_buf;
initialised = 1;
if (getpeername(fd, &sa, &length)) {
exit_cleanup(1);
exit_cleanup(RERR_SOCKETIO);
}
strlcpy(addr_buf,(char *)inet_ntoa(sockin->sin_addr), sizeof(addr_buf)-1);
return addr_buf;
}
@@ -329,11 +347,16 @@ char *client_name(int fd)
struct hostent *hp;
char **p;
char *def = "UNKNOWN";
static int initialised;
if (initialised) return name_buf;
initialised = 1;
strcpy(name_buf,def);
if (getpeername(fd, &sa, &length)) {
exit_cleanup(1);
exit_cleanup(RERR_SOCKETIO);
}
/* Look up the remote host name. */

286
support/rsyncstats Executable file
View File

@@ -0,0 +1,286 @@
#! /usr/bin/perl
# ---------------------------------------------------------------------------
#
# USAGE: rsyncstats <options>
#
# OPTIONS:
# -f <filename> Use <filename> for the log file
# -h include report on hourly traffic
# -d include report on domain traffic
# -t report on total traffic by section
# -D <domain> report only on traffic from <domain>
# -l <depth> Depth of path detail for sections
# -s <section> Section to report on, For example: -s /pub will report
# only on paths under /pub
#
# This script parses the default logfile format produced by rsync when running
# as a daemon with transfer logging enabled. It is derived from the xferstats
# script that comes with wuftpd
#
# Andrew Tridgell, October 1998
# rsync-bugs@samba.anu.edu.au
#
# ---------------------------------------------------------------------------
# edit the next line to customize for your default log file
$usage_file = "/var/adm/rsyncd.log";
# Edit the following lines for default report settings.
# Entries defined here will be over-ridden by the command line.
$opt_h = 1;
$opt_d = 0;
$opt_t = 1;
$opt_l = 2;
require 'getopts.pl';
&Getopts('f:rahdD:l:s:');
if ($opt_r) { $real = 1;}
if ($opt_a) { $anon = 1;}
if ($real == 0 && $anon == 0) { $anon = 1; }
if ($opt_f) {$usage_file = $opt_f;}
open (LOG,$usage_file) || die "Error opening usage log file: $usage_file\n";
if ($opt_D) {print "Transfer Totals include the '$opt_D' domain only.\n";
print "All other domains are filtered out for this report.\n\n";}
if ($opt_s) {print "Transfer Totals include the '$opt_s' section only.\n";
print "All other sections are filtered out for this report.\n\n";}
line: while (<LOG>) {
@line = split;
$day = $line[0];
$time = $line[1];
$pid = $line[2];
$op = $line[3];
$host = $line[4];
$ip = $line[5];
$module = $line[6];
$user = $line[7];
$file = $line[8];
$bytes = $line[9];
next if ($#line != 9);
next if ($op != "send" && $op != "recv");
$daytime = $day;
$hour = substr($time,0,2);
$file = $module . "/" . $file;
$file =~ s|//|/|mg;
@path = split(/\//, $file);
$pathkey = "";
for ($i=0; $i <= $#path && $i <= $opt_l;$i++) {
$pathkey = $pathkey . "/" . $path[$i];
}
next if (substr($pathkey,0,length("$opt_s")) ne "$opt_s");
$host =~ tr/A-Z/a-z/;
@address = split(/\./, $host);
$domain = $address[$#address];
if ( int($address[0]) > 0 || $#address < 2 )
{ $domain = "unresolved"; }
if ($opt_D) {
next unless (substr($domain,0,length("$opt_D")) eq "$opt_D");
}
# printf ("c=%d day=%s bytes=%d file=%s path=%s\n",
# $#line, $daytime, $bytes, $file, $pathkey);
$xferfiles++; # total files sent
$xfertfiles++; # total files sent
$xferfiles{$daytime}++; # files per day
$groupfiles{$pathkey}++; # per-group accesses
$domainfiles{$domain}++;
$xferbytes{$daytime} += $bytes; # bytes per day
$domainbytes{$domain} += $bytes; # xmit bytes to domain
$xferbytes += $bytes; # total bytes sent
$groupbytes{$pathkey} += $bytes; # per-group bytes sent
$xfertfiles{$hour}++; # files per hour
$xfertbytes{$hour} += $bytes; # bytes per hour
$xfertbytes += $bytes; # total bytes sent
}
close LOG;
@syslist = keys(systemfiles);
@dates = sort datecompare keys(xferbytes);
if ($xferfiles == 0) {die "There was no data to process.\n";}
print "TOTALS FOR SUMMARY PERIOD ", $dates[0], " TO ", $dates[$#dates], "\n\n";
printf ("Files Transmitted During Summary Period %12.0f\n", $xferfiles);
printf ("Bytes Transmitted During Summary Period %12.0f\n", $xferbytes);
printf ("Systems Using Archives %12.0f\n\n", $#syslist+1);
printf ("Average Files Transmitted Daily %12.0f\n",
$xferfiles / ($#dates + 1));
printf ("Average Bytes Transmitted Daily %12.0f\n",
$xferbytes / ($#dates + 1));
format top1 =
Daily Transmission Statistics
Number Of Number of Percent Of Percent Of
Date Files Sent MB Sent Files Sent Bytes Sent
--------------- ---------- ----------- ---------- ----------
.
format line1 =
@<<<<<<<<<<<<<< @>>>>>>>>> @>>>>>>>>>> @>>>>>>> @>>>>>>>
$date, $nfiles, $nbytes/(1024*1024), $pctfiles, $pctbytes
.
$^ = top1;
$~ = line1;
foreach $date ( sort datecompare keys(xferbytes) ) {
$nfiles = $xferfiles{$date};
$nbytes = $xferbytes{$date};
$pctfiles = sprintf("%8.2f", 100*$xferfiles{$date} / $xferfiles);
$pctbytes = sprintf("%8.2f", 100*$xferbytes{$date} / $xferbytes);
write;
}
if ($opt_t) {
format top2 =
Total Transfers from each Archive Section (By bytes)
- Percent -
Archive Section NFiles MB Files Bytes
------------------------------------- ------- ----------- ----- -------
.
format line2 =
@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @>>>>>> @>>>>>>>>>> @>>>> @>>>>
$section, $files, $bytes/(1024*1024), $pctfiles, $pctbytes
.
$| = 1;
$- = 0;
$^ = top2;
$~ = line2;
foreach $section ( sort bytecompare keys(groupfiles) ) {
$files = $groupfiles{$section};
$bytes = $groupbytes{$section};
$pctbytes = sprintf("%8.2f", 100 * $groupbytes{$section} / $xferbytes);
$pctfiles = sprintf("%8.2f", 100 * $groupfiles{$section} / $xferfiles);
write;
}
if ( $xferfiles < 1 ) { $xferfiles = 1; }
if ( $xferbytes < 1 ) { $xferbytes = 1; }
}
if ($opt_d) {
format top3 =
Total Transfer Amount By Domain
Number Of Number of Percent Of Percent Of
Domain Name Files Sent MB Sent Files Sent Bytes Sent
----------- ---------- ------------ ---------- ----------
.
format line3 =
@<<<<<<<<<< @>>>>>>>>> @>>>>>>>>>>> @>>>>>>> @>>>>>>>
$domain, $files, $bytes/(1024*1024), $pctfiles, $pctbytes
.
$- = 0;
$^ = top3;
$~ = line3;
foreach $domain ( sort domnamcompare keys(domainfiles) ) {
if ( $domainsecs{$domain} < 1 ) { $domainsecs{$domain} = 1; }
$files = $domainfiles{$domain};
$bytes = $domainbytes{$domain};
$pctfiles = sprintf("%8.2f", 100 * $domainfiles{$domain} / $xferfiles);
$pctbytes = sprintf("%8.2f", 100 * $domainbytes{$domain} / $xferbytes);
write;
}
}
if ($opt_h) {
format top8 =
Hourly Transmission Statistics
Number Of Number of Percent Of Percent Of
Time Files Sent MB Sent Files Sent Bytes Sent
--------------- ---------- ----------- ---------- ----------
.
format line8 =
@<<<<<<<<<<<<<< @>>>>>>>>> @>>>>>>>>>> @>>>>>>> @>>>>>>>
$hour, $nfiles, $nbytes/(1024*1024), $pctfiles, $pctbytes
.
$| = 1;
$- = 0;
$^ = top8;
$~ = line8;
foreach $hour ( sort keys(xfertbytes) ) {
$nfiles = $xfertfiles{$hour};
$nbytes = $xfertbytes{$hour};
$pctfiles = sprintf("%8.2f", 100*$xfertfiles{$hour} / $xferfiles);
$pctbytes = sprintf("%8.2f", 100*$xfertbytes{$hour} / $xferbytes);
write;
}
}
exit(0);
sub datecompare {
$a gt $b;
}
sub domnamcompare {
$sdiff = length($a) - length($b);
($sdiff < 0) ? -1 : ($sdiff > 0) ? 1 : ($a lt $b) ? -1 : ($a gt $b) ? 1 : 0;
}
sub bytecompare {
$bdiff = $groupbytes{$b} - $groupbytes{$a};
($bdiff < 0) ? -1 : ($bdiff > 0) ? 1 : ($a lt $b) ? -1 : ($a gt $b) ? 1 : 0;
}
sub faccompare {
$fdiff = $fac{$b} - $fac{$a};
($fdiff < 0) ? -1 : ($fdiff > 0) ? 1 : ($a lt $b) ? -1 : ($a gt $b) ? 1 : 0;
}

19
token.c
View File

@@ -108,7 +108,7 @@ send_deflated_token(int f, int token,
Z_DEFLATED, -15, 8,
Z_DEFAULT_STRATEGY) != Z_OK) {
rprintf(FERROR, "compression init failed\n");
exit_cleanup(1);
exit_cleanup(RERR_STREAMIO);
}
if ((obuf = malloc(MAX_DATA_COUNT+2)) == NULL)
out_of_memory("send_deflated_token");
@@ -178,7 +178,7 @@ send_deflated_token(int f, int token,
r = deflate(&tx_strm, flush);
if (r != Z_OK) {
rprintf(FERROR, "deflate returned %d\n", r);
exit_cleanup(1);
exit_cleanup(RERR_STREAMIO);
}
if (nb == 0 || tx_strm.avail_out == 0) {
n = MAX_DATA_COUNT - tx_strm.avail_out;
@@ -215,7 +215,7 @@ send_deflated_token(int f, int token,
if (r != Z_OK || tx_strm.avail_in != 0) {
rprintf(FERROR, "deflate on token returned %d (%d bytes left)\n",
r, tx_strm.avail_in);
exit_cleanup(1);
exit_cleanup(RERR_STREAMIO);
}
}
}
@@ -250,7 +250,7 @@ recv_deflated_token(int f, char **data)
rx_strm.zfree = NULL;
if (inflateInit2(&rx_strm, -15) != Z_OK) {
rprintf(FERROR, "inflate init failed\n");
exit_cleanup(1);
exit_cleanup(RERR_STREAMIO);
}
if ((cbuf = malloc(MAX_DATA_COUNT)) == NULL
|| (dbuf = malloc(CHUNK_SIZE)) == NULL)
@@ -293,7 +293,7 @@ recv_deflated_token(int f, char **data)
if (r != Z_OK && r != Z_BUF_ERROR) {
rprintf(FERROR, "inflate flush returned %d (%d bytes)\n",
r, n);
exit_cleanup(1);
exit_cleanup(RERR_STREAMIO);
}
if (n != 0 && r != Z_BUF_ERROR) {
/* have to return some more data and
@@ -308,7 +308,7 @@ recv_deflated_token(int f, char **data)
*/
if (!inflateSyncPoint(&rx_strm)) {
rprintf(FERROR, "decompressor lost sync!\n");
exit_cleanup(1);
exit_cleanup(RERR_STREAMIO);
}
rx_strm.avail_in = 4;
rx_strm.next_in = (Bytef *)cbuf;
@@ -343,7 +343,7 @@ recv_deflated_token(int f, char **data)
n = CHUNK_SIZE - rx_strm.avail_out;
if (r != Z_OK) {
rprintf(FERROR, "inflate returned %d (%d bytes)\n", r, n);
exit_cleanup(1);
exit_cleanup(RERR_STREAMIO);
}
if (rx_strm.avail_in == 0)
recv_state = r_inflated;
@@ -366,8 +366,7 @@ recv_deflated_token(int f, char **data)
* put the data corresponding to a token that we've just returned
* from recv_deflated_token into the decompressor's history buffer.
*/
void
see_deflate_token(char *buf, int len)
static void see_deflate_token(char *buf, int len)
{
int r, blklen;
unsigned char hdr[5];
@@ -400,7 +399,7 @@ see_deflate_token(char *buf, int len)
r = inflate(&rx_strm, Z_SYNC_FLUSH);
if (r != Z_OK) {
rprintf(FERROR, "inflate (token) returned %d\n", r);
exit_cleanup(1);
exit_cleanup(RERR_STREAMIO);
}
} while (len || rx_strm.avail_out == 0);
}

250
util.c
View File

@@ -24,15 +24,33 @@
*/
#include "rsync.h"
int num_waiting(int fd)
/****************************************************************************
Set a fd into nonblocking mode. Uses POSIX O_NONBLOCK if available,
else
if SYSV use O_NDELAY
if BSD use FNDELAY
****************************************************************************/
int set_nonblocking(int fd)
{
int len=0;
ioctl(fd,FIONREAD,&len);
return(len);
int val;
#ifdef O_NONBLOCK
#define FLAG_TO_SET O_NONBLOCK
#else
#ifdef SYSV
#define FLAG_TO_SET O_NDELAY
#else /* BSD */
#define FLAG_TO_SET FNDELAY
#endif
#endif
if((val = fcntl(fd, F_GETFL, 0)) == -1)
return -1;
val |= FLAG_TO_SET;
return fcntl( fd, F_SETFL, val);
#undef FLAG_TO_SET
}
/* this is taken from CVS */
int piped_child(char **command,int *f_in,int *f_out)
{
@@ -43,14 +61,14 @@ int piped_child(char **command,int *f_in,int *f_out)
if (pipe(to_child_pipe) < 0 ||
pipe(from_child_pipe) < 0) {
rprintf(FERROR,"pipe: %s\n",strerror(errno));
exit_cleanup(1);
exit_cleanup(RERR_IPC);
}
pid = do_fork();
if (pid < 0) {
rprintf(FERROR,"fork: %s\n",strerror(errno));
exit_cleanup(1);
exit_cleanup(RERR_IPC);
}
if (pid == 0)
@@ -61,7 +79,7 @@ int piped_child(char **command,int *f_in,int *f_out)
close(from_child_pipe[0]) < 0 ||
dup2(from_child_pipe[1], STDOUT_FILENO) < 0) {
rprintf(FERROR,"Failed to dup/close : %s\n",strerror(errno));
exit_cleanup(1);
exit_cleanup(RERR_IPC);
}
if (to_child_pipe[0] != STDIN_FILENO) close(to_child_pipe[0]);
if (from_child_pipe[1] != STDOUT_FILENO) close(from_child_pipe[1]);
@@ -69,17 +87,20 @@ int piped_child(char **command,int *f_in,int *f_out)
execvp(command[0], command);
rprintf(FERROR,"Failed to exec %s : %s\n",
command[0],strerror(errno));
exit_cleanup(1);
exit_cleanup(RERR_IPC);
}
if (close(from_child_pipe[1]) < 0 ||
close(to_child_pipe[0]) < 0) {
rprintf(FERROR,"Failed to close : %s\n",strerror(errno));
exit_cleanup(1);
exit_cleanup(RERR_IPC);
}
*f_in = from_child_pipe[0];
*f_out = to_child_pipe[1];
set_nonblocking(*f_in);
set_nonblocking(*f_out);
return pid;
}
@@ -93,14 +114,14 @@ int local_child(int argc, char **argv,int *f_in,int *f_out)
if (pipe(to_child_pipe) < 0 ||
pipe(from_child_pipe) < 0) {
rprintf(FERROR,"pipe: %s\n",strerror(errno));
exit_cleanup(1);
exit_cleanup(RERR_IPC);
}
pid = do_fork();
if (pid < 0) {
rprintf(FERROR,"fork: %s\n",strerror(errno));
exit_cleanup(1);
exit_cleanup(RERR_IPC);
}
if (pid == 0) {
@@ -115,7 +136,7 @@ int local_child(int argc, char **argv,int *f_in,int *f_out)
close(from_child_pipe[0]) < 0 ||
dup2(from_child_pipe[1], STDOUT_FILENO) < 0) {
rprintf(FERROR,"Failed to dup/close : %s\n",strerror(errno));
exit_cleanup(1);
exit_cleanup(RERR_IPC);
}
if (to_child_pipe[0] != STDIN_FILENO) close(to_child_pipe[0]);
if (from_child_pipe[1] != STDOUT_FILENO) close(from_child_pipe[1]);
@@ -125,7 +146,7 @@ int local_child(int argc, char **argv,int *f_in,int *f_out)
if (close(from_child_pipe[1]) < 0 ||
close(to_child_pipe[0]) < 0) {
rprintf(FERROR,"Failed to close : %s\n",strerror(errno));
exit_cleanup(1);
exit_cleanup(RERR_IPC);
}
*f_in = from_child_pipe[0];
@@ -139,13 +160,13 @@ int local_child(int argc, char **argv,int *f_in,int *f_out)
void out_of_memory(char *str)
{
rprintf(FERROR,"ERROR: out of memory in %s\n",str);
exit_cleanup(1);
exit_cleanup(RERR_MALLOC);
}
void overflow(char *str)
{
rprintf(FERROR,"ERROR: buffer overflow in %s\n",str);
exit_cleanup(1);
exit_cleanup(RERR_MALLOC);
}
@@ -206,7 +227,7 @@ int create_directory_path(char *fname)
derived from GNU C's cccp.c.
*/
int full_write(int desc, char *ptr, int len)
static int full_write(int desc, char *ptr, int len)
{
int total_written;
@@ -232,7 +253,7 @@ int full_write(int desc, char *ptr, int len)
for an error.
derived from GNU C's cccp.c. */
int safe_read(int desc, char *ptr, int len)
static int safe_read(int desc, char *ptr, int len)
{
int n_chars;
@@ -273,7 +294,7 @@ int copy_file(char *source, char *dest, mode_t mode)
}
ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode);
if (ofd < 0) {
if (ofd == -1) {
rprintf(FERROR,"open %s: %s\n",
dest,strerror(errno));
close(ifd);
@@ -389,14 +410,6 @@ int name_to_gid(char *name, gid_t *gid)
}
/****************************************************************************
check if a process exists.
****************************************************************************/
int process_exists(int pid)
{
return(kill(pid,0) == 0 || errno != ESRCH);
}
/* lock a byte range in a open file */
int lock_range(int fd, int offset, int len)
{
@@ -414,7 +427,7 @@ int lock_range(int fd, int offset, int len)
static void glob_expand_one(char *s, char **argv, int *argc, int maxargs)
{
#ifndef HAVE_GLOB
#if !(defined(HAVE_GLOB) && defined(HAVE_GLOB_H))
if (!*s) s = ".";
argv[*argc] = strdup(s);
(*argc)++;
@@ -494,7 +507,6 @@ void strlower(char *s)
pass 1023 for n */
int vslprintf(char *str, int n, const char *format, va_list ap)
{
#ifdef HAVE_VSNPRINTF
int ret = vsnprintf(str, n, format, ap);
if (ret > n || ret < 0) {
str[n] = 0;
@@ -502,42 +514,6 @@ int vslprintf(char *str, int n, const char *format, va_list ap)
}
str[ret] = 0;
return ret;
#else
static char *buf;
static int len=MAXPATHLEN*8;
int ret;
/* this code is NOT a proper vsnprintf() implementation. It
relies on the fact that all calls to slprintf() in rsync
pass strings which have already been checked to be less
than MAXPATHLEN in length and never more than 2 strings are
concatenated. This means the above buffer is absolutely
ample and can never be overflowed.
In the future we would like to replace this with a proper
vsnprintf() implementation but right now we need a solution
that is secure and portable. This is it. */
if (!buf) {
buf = malloc(len);
if (!buf) {
/* can't call debug or we would recurse */
exit_cleanup(1);
}
}
vsprintf(buf, format, ap);
ret = strlen(buf);
if (ret > n) {
/* yikes! */
exit_cleanup(1);
}
buf[ret] = 0;
memcpy(str, buf, ret+1);
return ret;
#endif
}
@@ -603,6 +579,55 @@ void clean_fname(char *name)
}
}
/*
* Make path appear as if a chroot had occurred:
* 0. call clean_fname on it.
* 1. remove leading "/" (or replace with "." if at end)
* 2. remove leading ".." components
* 3. delete any other "<dir>/.." (recursively)
* Return a malloc'ed copy.
* Contributed by Dave Dykstra <dwd@bell-labs.com>
*/
char *sanitize_path(char *p)
{
char *copy, *copyp;
clean_fname(p);
copy = (char *) malloc(strlen(p)+1);
copyp = copy;
while (*p != '\0') {
if ((*p == '/') && (copyp == copy)) {
/* remove leading slash */
p++;
}
else if ((*p == '.') && (*(p+1) == '.') &&
((*(p+2) == '/') || (*(p+2) == '\0'))) {
/* remove .. followed by slash or end */
p += 2;
if (copyp != copy) {
/* backup the copy one level */
while ((--copyp != copy) && (*copyp == '/'))
/* skip trailing slashes */
;
while ((copyp != copy) && (*copyp != '/'))
/* skip back through slash */
copyp--;
}
} else {
/* copy one component */
while (1) {
*copyp++ = *p++;
if ((*p == '\0') || (*(p-1) == '/'))
break;
}
}
}
*copyp = '\0';
return(copy);
}
static char curr_dir[MAXPATHLEN];
@@ -667,3 +692,98 @@ int u_strcmp(const char *cs1, const char *cs2)
return (int)*s1 - (int)*s2;
}
static OFF_T last_ofs;
void end_progress(void)
{
extern int do_progress, am_server;
if (do_progress && !am_server) {
rprintf(FINFO,"\n");
}
last_ofs = 0;
}
void show_progress(OFF_T ofs, OFF_T size)
{
extern int do_progress, am_server;
if (do_progress && !am_server) {
if (ofs > last_ofs + 1000) {
int pct = (int)((100.0*ofs)/size);
rprintf(FINFO,"%.0f (%d%%)\r", (double)ofs, pct);
last_ofs = ofs;
}
}
}
/* determine if a symlink points outside the current directory tree */
int unsafe_symlink(char *dest, char *src)
{
char *tok;
int depth = 0;
/* all absolute and null symlinks are unsafe */
if (!dest || !(*dest) || (*dest == '/')) return 1;
src = strdup(src);
if (!src) out_of_memory("unsafe_symlink");
/* find out what our safety margin is */
for (tok=strtok(src,"/"); tok; tok=strtok(NULL,"/")) {
if (strcmp(tok,"..") == 0) {
depth=0;
} else if (strcmp(tok,".") == 0) {
/* nothing */
} else {
depth++;
}
}
free(src);
/* drop by one to account for the filename portion */
depth--;
dest = strdup(dest);
if (!dest) out_of_memory("unsafe_symlink");
for (tok=strtok(dest,"/"); tok; tok=strtok(NULL,"/")) {
if (strcmp(tok,"..") == 0) {
depth--;
} else if (strcmp(tok,".") == 0) {
/* nothing */
} else {
depth++;
}
/* if at any point we go outside the current directory then
stop - it is unsafe */
if (depth < 0) break;
}
free(dest);
return (depth < 0);
}
/****************************************************************************
return the date and time as a string
****************************************************************************/
char *timestring(time_t t)
{
static char TimeBuf[200];
struct tm *tm = localtime(&t);
#ifdef HAVE_STRFTIME
strftime(TimeBuf,sizeof(TimeBuf)-1,"%Y/%m/%d %T",tm);
#else
strlcpy(TimeBuf, asctime(tm), sizeof(TimeBuf)-1);
#endif
if (TimeBuf[strlen(TimeBuf)-1] == '\n') {
TimeBuf[strlen(TimeBuf)-1] = 0;
}
return(TimeBuf);
}

View File

@@ -1 +1 @@
#define VERSION "2.0.16"
#define VERSION "2.2.0"