Compare commits

...

168 Commits

Author SHA1 Message Date
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
rsync-bugs
143384f367 preparing for release of 2.0.16 1998-06-01 13:49:12 +00:00
Andrew Tridgell
8c3b04730b added some notes to test.sh 1998-06-01 13:44:06 +00:00
Andrew Tridgell
aa9b77a56c replace calls to strcmp() with a u_strcmp() function that uses only
unsigned comparisons. Transferring files between two machines that
treated strcmp() differently led to the files being given the wrong
name at the destination if the filenames had characters > 128 (such as
Kanji characters) and the source and destination machines treated
strcmp() differently (ie. one treated strings as signed and the other
as unsigned).

We now treat all string comparisons for file list sorting as unsigned.
1998-06-01 13:39:54 +00:00
Andrew Tridgell
b72f24c719 updated the usage info 1998-06-01 10:38:24 +00:00
Andrew Tridgell
a800434a82 added --stats option for verbose stats on the file transfer 1998-06-01 03:42:14 +00:00
rsync-bugs
3b3c3d4390 preparing for release of 2.0.15 1998-05-30 02:10:18 +00:00
Andrew Tridgell
d846b09874 replace BAD with zBAD so it compiles on AIX 1998-05-30 02:07:36 +00:00
Andrew Tridgell
1d3754aede cosmetic fix.
reset offset to 0 at the start of each loop so the filenames get
printed correctly when sending directories followed by local names.
1998-05-30 02:03:29 +00:00
Andrew Tridgell
e44f9a12c4 make sure that io_flush() doesn't call writefd_unbuffered from within
a writefd_unbuffered call!

this should fix the "decompressor lost sync" bug
1998-05-30 02:02:23 +00:00
Andrew Tridgell
5243c216d6 replaced chdir and getcwd calls with push_dir/pop_dir functions. These
are faster and don't cause problems in a chrooted environment on any
systems.
1998-05-29 14:36:39 +00:00
rsync-bugs
79a51e7ee6 preparing for release of 2.0.14 1998-05-29 02:29:33 +00:00
Andrew Tridgell
cad2bba7d8 fixed a bug in the flist sending code that caused the flist sending to
get out of sync.
1998-05-29 02:28:33 +00:00
Andrew Tridgell
fe8c0a9824 use Realloc instead of realloc 1998-05-28 06:40:25 +00:00
Andrew Tridgell
6cdc6b1344 fix realloc call for systems that don't handle realloc(NULL, ...) 1998-05-28 06:29:57 +00:00
Andrew Tridgell
05848a2cc7 don't do recursive deletion if the recurse option is not selected. 1998-05-28 05:05:26 +00:00
Andrew Tridgell
528bfcd79a cosmetic fix. don't display a EOF error when displaying just the motd
from a rsync server
1998-05-28 01:58:33 +00:00
rsync-bugs
a1e13a937c preparing for release of 2.0.13 1998-05-27 13:54:41 +00:00
Andrew Tridgell
e3fe383aaa reduce IO_BUFFER_SIZE by 4 bytes so when then length word gets added
it is a power of 2.
1998-05-27 13:47:34 +00:00
Andrew Tridgell
43bd68e5dd added new include/exclude options to man page 1998-05-27 13:39:40 +00:00
Andrew Tridgell
ea2111d10a - always flush the IO write buffer when reading
- handle start of line in exclude properly
1998-05-27 13:05:05 +00:00
Andrew Tridgell
4c36ddbeec heaps of cleanup in the io code.
we no longer use non-blocking IO, instead it uses select a lot more,
being careful to always allow for reading whenever a valid read fd is
available and chcking timeouts.

also split the file io calls into fileio.c
1998-05-27 12:37:22 +00:00
Andrew Tridgell
2b6b4d539b added support for --include, --include-from and the +/- syntax 1998-05-27 11:02:33 +00:00
Andrew Tridgell
35f69d8ad9 new test code from Phil 1998-05-27 06:31:37 +00:00
Andrew Tridgell
7b1ce0d746 fixed a race condition in the --delete handling code. The bug led to
spurious error messages about not be able to delete some files.

this fix also makes --delete processing more efficient
1998-05-27 06:30:50 +00:00
rsync-bugs
54816348d1 preparing for release of 2.0.12 1998-05-26 14:45:05 +00:00
Andrew Tridgell
49d11b78c1 fixed a bug in the handling of very long filenames (longer than 255
chars) where two neighboring filenames share more than 255 characters
at the start of their names.
1998-05-26 14:39:18 +00:00
Andrew Tridgell
bb0f7089fe check for munmap as well as mmap. NextStep only has mmap in standard
libs
1998-05-26 14:18:59 +00:00
Andrew Tridgell
1ff5450d31 formatting changes 1998-05-26 14:17:27 +00:00
Andrew Tridgell
2f7512b006 error formatting changes 1998-05-26 14:16:20 +00:00
Andrew Tridgell
943882a289 - don't allow chown for the group of a file if running as a daemon and
uid!=0

- reset am_root after startup as a daemon
1998-05-23 05:57:08 +00:00
Andrew Tridgell
6c82f74b6f don't treat intermediate link directories as links in the relative
path code
1998-05-23 03:13:46 +00:00
Andrew Tridgell
8a5b8b263b need strchr check in configure.in 1998-05-22 14:22:41 +00:00
Andrew Tridgell
d47a7fcf0f use a simpler mmap() test in autoconf as we don't need all the
features of mmap that the standard test uses, and it reports Ultrix as
having no working mmap() when in fact any mmap will do what we want
for rsync.
1998-05-22 14:03:30 +00:00
Andrew Tridgell
e24c850818 need a ifdef around some mmap code 1998-05-22 13:51:26 +00:00
rsync-bugs
6c612747e3 preparing for release of 2.0.11 1998-05-22 13:46:30 +00:00
Andrew Tridgell
505c7ea2bc add a cast to initialisation of mask 1998-05-22 13:27:55 +00:00
Andrew Tridgell
9add51f18e change WRAP to ZWRAP so it doesn't conflict with IRIX includes 1998-05-22 13:02:22 +00:00
Andrew Tridgell
f7bd44eb32 added a README.rsync to explain what we have changed in zlib and to
tell people that any bugs are our responsibility.
1998-05-22 12:20:07 +00:00
Andrew Tridgell
e3ac52f2e1 no longer needed 1998-05-22 12:13:07 +00:00
Andrew Tridgell
06e27ef78e - fix redefinition of MAX
- fix shadow of variable "overflow"
1998-05-22 12:08:49 +00:00
Andrew Tridgell
23e43fceeb fix shadowed variable 1998-05-22 12:07:23 +00:00
Andrew Tridgell
f900f5fe71 removing an unused variable 1998-05-22 12:06:25 +00:00
Andrew Tridgell
db199cfae0 don't need two AC_OUTPUT lines in configure.in 1998-05-22 12:05:53 +00:00
Paul Mackerras
5914bf15d2 Update to use the new zlib-1.1.2 code.
The compressed token code now handles the null (-2)
token from the match logic.
1998-05-22 06:58:52 +00:00
Andrew Tridgell
45f133b976 this fixes two problems:
1) handle 64 bit file offsets in the token code. I wonder how large
bit files worked up till now?

2) send a null token when we have passed over a large lump of data
without finding a token match. This reduces the number of IOs
considerably as it removes the need for seeks/reads on the checksum
calculation and literal send code. This is not enabled yet for the
compressed case as the deflate token code can't handle it yet.
1998-05-22 01:53:02 +00:00
Andrew Tridgell
c5eb365011 formatting changes. committed separately so they don't mask the coming
token changes.
1998-05-21 05:57:15 +00:00
Andrew Tridgell
2f326946a1 now that we slide the mmap window we can use a smaller MAX_MAP_SIZE
and thus consume less virtual memory on the sending side.
1998-05-21 05:55:33 +00:00
Andrew Tridgell
754d120c98 use mmap() for files of any size. This should be much more buffer
cache friendly.
1998-05-21 05:52:37 +00:00
Andrew Tridgell
8e9871303b someone didn't realise that you need rsync at both ends! 1998-05-21 05:32:36 +00:00
Andrew Tridgell
de5fb3744d added DNS spoofing test to host access control 1998-05-20 00:20:12 +00:00
rsync-bugs
6e47bda08e preparing for release of 2.0.10 1998-05-18 14:30:22 +00:00
Andrew Tridgell
130b4ae447 strip any leading / off absolute paths when using relative path names 1998-05-18 14:11:43 +00:00
Andrew Tridgell
ba5e128d23 fixed a bug in the glob expansion code (pointed out by
hazard.bsn@blkseanet.net.eu.org)
1998-05-18 14:00:24 +00:00
rsync-bugs
79b34efe92 preparing for release of 2.0.9 1998-05-18 10:30:53 +00:00
Andrew Tridgell
679e765768 fixed a multiplexing bug 1998-05-18 10:23:47 +00:00
Andrew Tridgell
e08c961083 handle rsh clients that don't like half-open connections 1998-05-18 09:34:33 +00:00
Andrew Tridgell
8d9dc9f99d this is a large commit which adds io multiplexing, thus giving error
messages from the server when using the socket code.

I've doen a fair bit of testing and I don't seem to have broken
anything, but it is a very complex change. More testing needed!
1998-05-18 08:20:26 +00:00
Andrew Tridgell
593fde2d3b if f_in == f_out then don't close one of them 1998-05-17 15:18:25 +00:00
rsync-bugs
7544c45b1d preparing for release of 2.0.8 1998-05-17 15:10:34 +00:00
Andrew Tridgell
fdee2ba3df rpm is fussy about changelog formats 1998-05-17 15:10:13 +00:00
rsync-bugs
c120bb2235 preparing for release of 2.0.8 1998-05-17 14:58:20 +00:00
Andrew Tridgell
5d58c8d664 updated so I can auto-build rsync packages 1998-05-17 14:32:57 +00:00
Andrew Tridgell
22d6234e04 close some unnecessary file descriptors in do_recv() 1998-05-17 07:22:53 +00:00
Andrew Tridgell
5dd7e03167 put a limit (default 1MB) on the read buffer size. This stops it
growing too much if the sender is much faster than the receiver
1998-05-17 05:56:32 +00:00
Andrew Tridgell
08ac228fbd moved usage mesage after am_daemon test (I'd broken daemon mode) 1998-05-17 03:51:41 +00:00
Andrew Tridgell
6c29af2251 close the other half of the pipe in do_recv(). This fixes the problem
where a rsync receive process could hang around after the connection
has gone away if a fatal error occurs (such as someone killing the
other end)
1998-05-17 01:24:16 +00:00
Andrew Tridgell
6c00346849 check for right number of arguments _after_ the option parsing.
this stops "rsync -v" causing a segv.
1998-05-16 15:18:07 +00:00
Andrew Tridgell
d0d56395c8 for authenticated access record the authenticated username in the logs 1998-05-16 07:45:26 +00:00
rsync-bugs
e9d736a7e8 preparing for release of 2.0.7 1998-05-16 05:38:33 +00:00
rsync-bugs
e9ace0c77a put only the ftp directory in the template file 1998-05-16 05:35:56 +00:00
rsync-bugs
1c31ffa9af added a template file for the rsync spec file to enable automatic spec
generation
1998-05-16 05:30:33 +00:00
Andrew Tridgell
d186eb1a56 - print the stats at the right place when uploading in the rsync
daemon
- update spec file
1998-05-16 05:24:40 +00:00
John H Terpstra
18baf523dc Spec file for building Red Hat RPM packages. 1998-05-16 04:23:41 +00:00
Andrew Tridgell
7b372642ec - distinguish downloads and uploads in the syslog messages
- add stats on uploads in syslog
1998-05-16 03:03:57 +00:00
rsync-bugs
4f189177dc preparing for release of 2.0.6 1998-05-16 00:57:37 +00:00
Andrew Tridgell
f72399f867 fixed handling of vsprintf on SunOS 1998-05-16 00:46:16 +00:00
rsync-bugs
d64488e169 preparing for release of 2.0.5 1998-05-15 14:12:06 +00:00
Andrew Tridgell
29110570f8 removed some debug code 1998-05-15 14:01:04 +00:00
Andrew Tridgell
3e607d2354 got rid of "EOF in map_ptr" problem. If a file shrinks mid transfer
then we supply a zero filled buffer at the end and rely on the
checksum to cause a retry. This is really the best we can do as there
is no correct semantics for copying a changing file!
1998-05-15 14:00:12 +00:00
Andrew Tridgell
a6801c3977 added a "socket options" option to rsyncd.conf. This option will
provide hours of fun for those people who like to tune their systems
to the utmost degree.
1998-05-15 13:25:19 +00:00
rsync-bugs
3ef56fee8f preparing for release of 2.0.4 1998-05-15 10:58:03 +00:00
Andrew Tridgell
f9e940efc7 load just the globals section of the config file when the daemon
starts so we know the syslog facility for the "starting" message
1998-05-15 10:52:54 +00:00
Andrew Tridgell
1a016bfdec - changed the log messages to show the requested path
- some more paranoid buffer size checks
- separate open syslog call
- handle systems without LOG_NDELAY
1998-05-15 10:34:07 +00:00
Andrew Tridgell
e42c9458c2 use strlcat() strlcpy() and slprintf() whenever possible to avoid any
chance of a buffer overflow
1998-05-15 09:26:01 +00:00
Andrew Tridgell
087bf010d2 allow the specification of multiple filenames (with or without
wildcards) to a rsync server. For example you can do:

rsync -avz samba::'ftp/pub/samba/README ftp/pub/samba/*.gz' .
1998-05-15 08:43:11 +00:00
rsync-bugs
f240c06902 preparing for release of 2.0.3 1998-05-15 07:55:05 +00:00
Andrew Tridgell
a87b3b2ac2 use a separate "make man" target so people don't need yodl 1998-05-15 07:53:41 +00:00
rsync-bugs
ed0992b888 preparing for release of 2.0.2 1998-05-15 07:37:00 +00:00
Andrew Tridgell
d6dead6bb1 added write buffering during the file list sending. This makes things
a bit more efficient (less system calls)
1998-05-15 07:34:19 +00:00
Andrew Tridgell
344fb1276b fixed a select bug which caused rsync to use far more cpu time than
necessary on the server
1998-05-15 07:11:29 +00:00
Andrew Tridgell
e095b568d0 updated the README a bit 1998-05-15 05:42:56 +00:00
Andrew Tridgell
4c3d16be50 - added some notes about encryption and authentication to the man
pages

- documented the RSYNC_PASSWORD environment variable
1998-05-15 05:37:34 +00:00
rsync-bugs
715e727784 preparing for release of 2.0.1 1998-05-15 01:19:42 +00:00
Andrew Tridgell
5805327b28 fixed typo in rsyncd exclude handling 1998-05-15 01:14:48 +00:00
Andrew Tridgell
8f3a2d54a6 added "exclude" and "exclude from" options to rsyncd.conf.
This is useful for mirroring a web site when you don't want users to
mirror everything.
1998-05-15 01:02:49 +00:00
Andrew Tridgell
e22de16264 fixed SIGCLD -> SIGCHLD
fixed formatting of man page (thanks to Karsten)
1998-05-15 00:29:45 +00:00
rsync-bugs
c725d76c5a preparing for release of 2.0.0 1998-05-14 07:22:45 +00:00
Andrew Tridgell
5315b793d2 fixed spelling mistakes 1998-05-14 06:57:50 +00:00
Andrew Tridgell
41059f75b5 documentation!
I've written a rsyncd.conf man page (in yodl) and updated the rsync
man page.
1998-05-14 06:51:28 +00:00
Andrew Tridgell
248fbb8c23 syslog some stats 1998-05-14 04:49:30 +00:00
Andrew Tridgell
fabf5ea72d now support integers or strings for syslog facility 1998-05-14 04:40:23 +00:00
Andrew Tridgell
09e13ae2dc changed "syslog facility" to an enumerated type so the string name is
used in rsyncd.conf
1998-05-14 04:38:17 +00:00
Andrew Tridgell
5a96ee0599 make host access controls case insensitive 1998-05-14 04:31:03 +00:00
Andrew Tridgell
0cea42440f removed a debug line 1998-05-13 15:56:03 +00:00
Andrew Tridgell
874895d51a added globbing support in the rsync daemon. This will allow you to
specify wildcards when grabbing files from a anon rsync daemon.
1998-05-13 15:44:04 +00:00
Andrew Tridgell
f855d1a309 vsprintf returns char* on sunos4 1998-05-13 13:48:25 +00:00
Andrew Tridgell
9fc310dafe added replacement memmove 1998-05-13 13:27:36 +00:00
Andrew Tridgell
0473e2a14a define INADDR_NONE if necessary 1998-05-13 13:22:26 +00:00
Andrew Tridgell
c8e78d87ad improved the authentication and in particular the error reporting 1998-05-13 12:21:10 +00:00
Andrew Tridgell
bcb7e50250 first working version of challenge response authentication. needs
testing.
1998-05-13 11:49:05 +00:00
Andrew Tridgell
31593dd610 improved max connections code. Now use fcntl instead of flock.
also started on authentication code (I'm doing a challenge response
system initially)
1998-05-13 09:38:54 +00:00
Andrew Tridgell
91eee5946a save another couple of round trip latencies. This set of changes is
backwards compatible.
1998-05-13 09:08:05 +00:00
Andrew Tridgell
6c8f537302 need sys/file.h for flock() 1998-05-13 09:01:11 +00:00
Andrew Tridgell
13c5fc0e14 save one round trip (version swapping) for daemon.
This is an imcompatible change in the socket protocol. You get "is
your shell clean" if using an older rsync client
1998-05-13 08:58:07 +00:00
Andrew Tridgell
0c515f17c4 added two new options "max connections" and "lock file" 1998-05-13 08:52:12 +00:00
Andrew Tridgell
851dbdb775 added "syslog facility" option. It is an integer and defaults to the
value of LOG_DAEMON.
1998-05-13 08:12:51 +00:00
Andrew Tridgell
56c473b795 added hosts allow and hosts deny support. I ended up writing my own as
the tcpd code is not quite what I wanted.
1998-05-13 08:03:47 +00:00
Andrew Tridgell
df5e03da7b check argc and show usage if no args 1998-05-13 07:04:40 +00:00
Andrew Tridgell
4cdf25e42e load the config file on each connect rather than at startup 1998-05-13 00:08:03 +00:00
Andrew Tridgell
eb697c999b fixed a bug in the new . filename code 1998-05-11 12:29:19 +00:00
Andrew Tridgell
d4ebe7a7b1 changed the name of the temporary filename to include a leading . so
that it appears hidden while being transferred. This should be useful
when using rsync for mirroring so users accessing via ftp don't get
confused by the temporary files.
1998-05-10 13:45:03 +00:00
Andrew Tridgell
d7ff63cf1a the statistics reporting was the wrong way around for client receipt
mode! It reported the read/written backwards.
1998-05-10 13:01:59 +00:00
Andrew Tridgell
e45e009309 changed a couple of places to use strlcpy() 1998-05-10 12:37:26 +00:00
Andrew Tridgell
45ccc5c08c only call openlog once
fix a segv in loadparm.c
1998-05-10 08:31:50 +00:00
Andrew Tridgell
ff8b29b8c6 use syslog instead of /var/adm/rsyncd.log 1998-05-10 08:24:38 +00:00
Andrew Tridgell
8ef4ffd698 change to allow names or numbers to be used for uid and gid. 1998-05-10 08:05:56 +00:00
Andrew Tridgell
c596dad1d1 fixed typo in socket test 1998-05-10 07:45:14 +00:00
Andrew Tridgell
7d29d4ba13 look for -lsocket by checking for connect() 1998-05-10 07:40:20 +00:00
Andrew Tridgell
7a6421fa76 split the options parsing code into options.c
added the --port and --config options

use strlcpy() instead of strncpy()

some cleanups and formatting changes
1998-05-10 07:25:40 +00:00
Andrew Tridgell
2c91d3d311 better negotiation of protocol versions 1998-05-10 03:08:22 +00:00
Andrew Tridgell
3591c0660c cleanup code a bit 1998-05-10 01:46:06 +00:00
Andrew Tridgell
0b76cd63ee configuration parsing and loading code for rsyncd. This is based
on the Samba config code, so you'll find that the config files will
be eerily familiar if you have ever worked with Samba.
1998-05-09 14:00:55 +00:00
Andrew Tridgell
f0fca04e4e first vesrion of working socket based rsync. It still needs a lot of
work, but at least it works :-)
1998-05-09 13:58:54 +00:00
Andrew Tridgell
bc2e93eb8e just a stub for now 1998-05-07 14:53:02 +00:00
Andrew Tridgell
d3394de178 removed some quoted printable stuff from this so it works again 1998-05-07 14:52:38 +00:00
Andrew Tridgell
9486289ce4 some large systematic changes to make socket conversion easier. The
biggest one is the use of rprintf() instead of fprintf()
1998-05-07 14:50:22 +00:00
Andrew Tridgell
5d6bcd4472 some code cleanup in preparation for a cleaner client/server split 1998-05-07 12:30:47 +00:00
Andrew Tridgell
94f3c3b047 improve the autoconf warning for broken readdir 1998-05-07 12:29:56 +00:00
Paul Mackerras
d4286ec49d Add pristine zlib-1.1.2 code, ready for hacking. 1998-05-07 06:19:41 +00:00
Andrew Tridgell
dad5e9d0b5 now using autoheader as well as autoconf 1998-05-07 03:57:26 +00:00
Andrew Tridgell
b79223389b hopefully better support for systems where sizeof(int)==8 1998-05-06 14:13:03 +00:00
Andrew Tridgell
fa37d4bbaf don't need off64_t code on systems where off_t is already 64 bits 1998-05-06 08:01:00 +00:00
Andrew Tridgell
f28ee65baa damn solaris doesn't prototype it's functions correctly. grrr. 1998-05-06 07:35:37 +00:00
Andrew Tridgell
94c9ef1fc3 handle mmap() failures 1998-05-06 07:28:14 +00:00
Andrew Tridgell
59503278bf better test for solaris broken readdir 1998-05-06 07:18:06 +00:00
Andrew Tridgell
d6e6ecbdbf handle broken readdir() on Solaris 2.6 (it returns the name offset by
2 characters!)
1998-05-06 07:00:38 +00:00
Andrew Tridgell
73233f0f12 add support for lseek64() under solaris 2.6 1998-05-06 06:34:18 +00:00
Andrew Tridgell
debb45054a Solaris 2.6 doesn't support "signed char". What a broken system! 1998-05-06 06:21:35 +00:00
Andrew Tridgell
efb2f6bf62 use floating point for printout of stats - this wrks on machines
without long long but with a 64 bit off_t
1998-05-06 06:07:06 +00:00
Andrew Tridgell
bcacc18bdf added support for 64 bit file offsets under Solaris 2.6. Not tested
yet.
1998-05-06 05:43:36 +00:00
Andrew Tridgell
3bee67337d fix up the int64 handling a little. It should work on a few more
systems now (tested on OSF1)
1998-05-06 05:05:00 +00:00
Andrew Tridgell
0944563eb9 a leading / in a pattern now means "use a absolute path match". This
allows you to exclude root directories without excluding
subdirectories of the same name.
1998-05-05 11:23:51 +00:00
Andrew Tridgell
a0b65b1805 added support for sockets and fifos 1998-04-28 05:53:18 +00:00
Andrew Tridgell
ddddf27b28 a much improved test script from Phil. 1998-04-17 15:48:10 +00:00
66 changed files with 14829 additions and 7370 deletions

View File

@@ -20,9 +20,14 @@ SHELL=/bin/sh
.SUFFIXES:
.SUFFIXES: .c .o
LIBOBJ=lib/getopt.o lib/fnmatch.o lib/zlib.o lib/compat.o
OBJS1=rsync.o exclude.o util.o md4.o main.o checksum.o match.o syscall.o
OBJS=$(OBJS1) flist.o io.o compat.o hlink.o token.o uidlist.o $(LIBOBJ)
LIBOBJ=lib/getopt.o lib/fnmatch.o lib/compat.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
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:
@@ -30,15 +35,25 @@ OBJS=$(OBJS1) flist.o io.o compat.o hlink.o token.o uidlist.o $(LIBOBJ)
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
rsync: $(OBJS)
$(CC) $(CFLAGS) -o rsync $(OBJS) $(LIBS)
rsync.1: rsync.yo
yodl2man -o rsync.1 rsync.yo
rsyncd.conf.5: rsyncd.conf.yo
yodl2man -o rsyncd.conf.5 rsyncd.conf.yo
proto:
cat *.c | awk -f mkproto.awk > proto.h

20
README
View File

@@ -57,6 +57,9 @@ Options:
--exclude-from FILE 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
SETUP
@@ -72,9 +75,23 @@ To install rsync, first run the "configure" script. This will create a
Makefile and config.h appropriate for your system. Then type
"make".
Note that on some systems you will have to force configure not to use
gcc because gcc may not support some features (such as 64 bit file
offsets) that your system may support. Set the environment variable CC
to the name of your native compiler before running configure in this
case.
Once built put a copy of rsync in your search path on the local and
remote systems (or use "make install"). That's it!
RSYNC SERVERS
-------------
rsync can also talk to "rsync servers" which can provide anonymous or
authenticated rsync. See the rsync.conf(5) man page for details on how
to setup a rsync server. See the rsync(1) man page for info on how to
connect to a rsync server.
MAILING LIST
------------
@@ -132,7 +149,8 @@ paulus@cs.anu.edu.au
AVAILABILITY
------------
The main ftp site for rsync is ftp://samba.anu.edu.au/pub/rsync
The main ftp site for rsync is ftp://samba.anu.edu.au/pub/rsync
This is also available as rsync://samba.anu.edu.au/rsyncftp/
Mirrors are available at:

130
access.c Normal file
View File

@@ -0,0 +1,130 @@
/*
Copyright (C) Andrew Tridgell 1998
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
hosts allow/deny code for rsync
*/
#include "rsync.h"
static int match_hostname(char *host, char *tok)
{
if (!host || !*host) return 0;
return (fnmatch(tok, host, 0) == 0);
}
static int match_address(char *addr, char *tok)
{
char *p;
unsigned long a, t, mask = (unsigned long)~0;
if (!addr || !*addr) return 0;
if (!isdigit(tok[0])) return 0;
p = strchr(tok,'/');
if (p) *p = 0;
a = inet_addr(addr);
t = inet_addr(tok);
if (p) {
*p = '/';
}
if (t == INADDR_NONE) {
rprintf(FERROR,"malformed address %s\n", tok);
return 0;
}
a = ntohl(a);
t = ntohl(t);
if (p) {
if (strchr(p+1,'.')) {
mask = inet_addr(p+1);
if (mask == INADDR_NONE) {
rprintf(FERROR,"malformed mask in %s\n", tok);
return 0;
}
mask = ntohl(mask);
} else {
int bits = atoi(p+1);
if (bits <= 0 || bits > 32) {
rprintf(FERROR,"malformed mask in %s\n", tok);
return 0;
}
mask &= (mask << (32-bits));
}
}
return ((a&mask) == (t&mask));
}
static int access_match(char *list, char *addr, char *host)
{
char *tok;
char *list2 = strdup(list);
if (!list2) out_of_memory("access_match");
strlower(list2);
if (host) strlower(host);
for (tok=strtok(list2," ,\t"); tok; tok=strtok(NULL," ,\t")) {
if (match_hostname(host, tok) || match_address(addr, tok)) {
free(list2);
return 1;
}
}
free(list2);
return 0;
}
int allow_access(char *addr, char *host, char *allow_list, char *deny_list)
{
/* if theres no deny list and no allow list then allow access */
if ((!deny_list || !*deny_list) && (!allow_list || !*allow_list))
return 1;
/* if there is an allow list but no deny list then allow only hosts
on the allow list */
if (!deny_list || !*deny_list)
return(access_match(allow_list, addr, host));
/* if theres a deny list but no allow list then allow
all hosts not on the deny list */
if (!allow_list || !*allow_list)
return(!access_match(deny_list,addr,host));
/* if there are both type of list then allow all hosts on the
allow list */
if (access_match(allow_list,addr,host))
return 1;
/* if there are both type of list and it's not on the allow then
allow it if its not on the deny */
if (access_match(deny_list,addr,host))
return 0;
return 1;
}

9
acconfig.h Normal file
View File

@@ -0,0 +1,9 @@
#undef HAVE_BROKEN_READDIR
#undef HAVE_ERRNO_DECL
#undef HAVE_LONGLONG
#undef HAVE_OFF64_T
#undef HAVE_REMSH
#undef HAVE_UNSIGNED_CHAR
#undef HAVE_UTIMBUF
#undef ino_t
#undef HAVE_CONNECT

215
authenticate.c Normal file
View File

@@ -0,0 +1,215 @@
/*
Copyright (C) Andrew Tridgell 1998
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* support rsync authentication */
#include "rsync.h"
/***************************************************************************
encode a buffer using base64 - simple and slow algorithm. null terminates
the result.
***************************************************************************/
static void base64_encode(char *buf, int len, char *out)
{
char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
int bit_offset, byte_offset, idx, i;
unsigned char *d = (unsigned char *)buf;
int bytes = (len*8 + 5)/6;
memset(out, 0, bytes+1);
for (i=0;i<bytes;i++) {
byte_offset = (i*6)/8;
bit_offset = (i*6)%8;
if (bit_offset < 3) {
idx = (d[byte_offset] >> (2-bit_offset)) & 0x3F;
} else {
idx = (d[byte_offset] << (bit_offset-2)) & 0x3F;
if (byte_offset+1 < len) {
idx |= (d[byte_offset+1] >> (8-(bit_offset-2)));
}
}
out[i] = b64[idx];
}
}
/* create a 16 byte challenge buffer */
static void gen_challenge(char *addr, char *challenge)
{
char input[32];
struct timeval tv;
memset(input, 0, sizeof(input));
strlcpy((char *)input, addr, 16);
gettimeofday(&tv, NULL);
SIVAL(input, 16, tv.tv_sec);
SIVAL(input, 20, tv.tv_usec);
SIVAL(input, 24, getpid());
sum_init();
sum_update(input, sizeof(input));
sum_end(challenge);
}
/* return the secret for a user from the sercret file. maximum length
is len. null terminate it */
static int get_secret(int module, char *user, char *secret, int len)
{
char *fname = lp_secrets_file(module);
int fd, found=0;
char line[MAXPATHLEN];
char *p, *pass=NULL;
if (!fname || !*fname) return 0;
fd = open(fname,O_RDONLY);
if (fd == -1) return 0;
while (!found) {
int i = 0;
memset(line, 0, sizeof(line));
while (i<(sizeof(line)-1)) {
if (read(fd, &line[i], 1) != 1) {
memset(line, 0, sizeof(line));
close(fd);
return 0;
}
if (line[i] == '\r') continue;
if (line[i] == '\n') break;
i++;
}
line[i] = 0;
if (line[0] == '#') continue;
p = strchr(line,':');
if (!p) continue;
*p = 0;
if (strcmp(user, line)) continue;
pass = p+1;
found = 1;
}
close(fd);
if (!found) return 0;
strlcpy(secret, pass, len);
return 1;
}
/* generate a 16 byte hash from a password and challenge */
void generate_hash(char *in, char *challenge, char *out)
{
char buf[16];
sum_init();
sum_update(in, strlen(in));
sum_update(challenge, strlen(challenge));
sum_end(buf);
base64_encode(buf, 16, out);
}
/* possible negotiate authentication with the client. Use "leader" to
start off the auth if necessary
return NULL if authentication failed
return "" if anonymous access
otherwise return username
*/
char *auth_server(int fd, int module, char *addr, char *leader)
{
char *users = lp_auth_users(module);
char challenge[16];
char b64_challenge[30];
char line[MAXPATHLEN];
static char user[100];
char secret[100];
char pass[30];
char pass2[30];
char *tok;
/* if no auth list then allow anyone in! */
if (!users || !*users) return "";
gen_challenge(addr, challenge);
base64_encode(challenge, 16, b64_challenge);
io_printf(fd,"%s%s\n", leader, b64_challenge);
if (!read_line(fd, line, sizeof(line)-1)) {
return NULL;
}
memset(user, 0, sizeof(user));
memset(pass, 0, sizeof(pass));
if (sscanf(line,"%99s %29s", user, pass) != 2) {
return NULL;
}
users = strdup(users);
if (!users) return NULL;
for (tok=strtok(users," ,\t"); tok; tok = strtok(NULL," ,\t")) {
if (strcmp(tok, user) == 0) break;
}
free(users);
if (!tok) {
return NULL;
}
memset(secret, 0, sizeof(secret));
if (!get_secret(module, user, secret, sizeof(secret)-1)) {
memset(secret, 0, sizeof(secret));
return NULL;
}
generate_hash(secret, b64_challenge, pass2);
memset(secret, 0, sizeof(secret));
if (strcmp(pass, pass2) == 0)
return user;
return NULL;
}
void auth_client(int fd, char *user, char *challenge)
{
char *pass;
char pass2[30];
if (!user || !*user) return;
if (!(pass=getenv("RSYNC_PASSWORD"))) {
pass = getpass("Password: ");
}
if (!pass || !*pass) {
pass = "";
}
generate_hash(pass, challenge, pass2);
io_printf(fd, "%s %s\n", user, pass2);
}

View File

@@ -34,7 +34,7 @@ uint32 get_checksum1(char *buf1,int len)
{
int i;
uint32 s1, s2;
signed char *buf = (signed char *)buf1;
schar *buf = (schar *)buf1;
s1 = s2 = 0;
for (i = 0; i < (len-4); i+=4) {
@@ -77,7 +77,7 @@ void get_checksum2(char *buf,int len,char *sum)
MDbegin(&MD);
bcopy(buf,buf1,len);
memcpy(buf1,buf,len);
if (checksum_seed) {
SIVAL(buf1,len,checksum_seed);
len += 4;
@@ -93,16 +93,16 @@ void get_checksum2(char *buf,int len,char *sum)
}
void file_checksum(char *fname,char *sum,off_t size)
void file_checksum(char *fname,char *sum,OFF_T size)
{
off_t i;
OFF_T i;
MDstruct MD;
struct map_struct *buf;
int fd;
off_t len = size;
OFF_T len = size;
char tmpchunk[CSUM_CHUNK];
bzero(sum,csum_length);
memset(sum,0,csum_length);
fd = open(fname,O_RDONLY);
if (fd == -1) return;
@@ -112,12 +112,12 @@ void file_checksum(char *fname,char *sum,off_t size)
MDbegin(&MD);
for(i = 0; i + CSUM_CHUNK <= len; i += CSUM_CHUNK) {
bcopy(map_ptr(buf,i,CSUM_CHUNK),tmpchunk,CSUM_CHUNK);
memcpy(tmpchunk, map_ptr(buf,i,CSUM_CHUNK), CSUM_CHUNK);
MDupdate(&MD, tmpchunk, CSUM_CHUNK*8);
}
if (len - i > 0) {
bcopy(map_ptr(buf,i,len-i),tmpchunk,len-i);
memcpy(tmpchunk, map_ptr(buf,i,len-i), len-i);
MDupdate(&MD, tmpchunk, (len-i)*8);
}
@@ -155,27 +155,27 @@ void sum_update(char *p,int len)
{
int i;
if (len + sumresidue < CSUM_CHUNK) {
bcopy(p,sumrbuf+sumresidue,len);
memcpy(sumrbuf+sumresidue, p, len);
sumresidue += len;
return;
}
if (sumresidue) {
i = MIN(CSUM_CHUNK-sumresidue,len);
bcopy(p,sumrbuf+sumresidue,i);
memcpy(sumrbuf+sumresidue,p,i);
MDupdate(&sumMD, sumrbuf, (i+sumresidue)*8);
len -= i;
p += i;
}
for(i = 0; i + CSUM_CHUNK <= len; i += CSUM_CHUNK) {
bcopy(p+i,sumrbuf,CSUM_CHUNK);
memcpy(sumrbuf,p+i,CSUM_CHUNK);
MDupdate(&sumMD, sumrbuf, CSUM_CHUNK*8);
}
if (len - i > 0) {
sumresidue = len-i;
bcopy(p+i,sumrbuf,sumresidue);
memcpy(sumrbuf,p+i,sumresidue);
} else {
sumresidue = 0;
}

389
clientserver.c Normal file
View File

@@ -0,0 +1,389 @@
/*
Copyright (C) Andrew Tridgell 1998
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* the socket based protocol for setting up a connection wit rsyncd */
#include "rsync.h"
extern int module_id;
extern int read_only;
extern int verbose;
extern int rsync_port;
int start_socket_client(char *host, char *path, int argc, char *argv[])
{
int fd, i;
char *sargs[MAX_ARGS];
int sargc=0;
char line[MAXPATHLEN];
char *p, *user=NULL;
extern int remote_version;
extern int am_client;
extern int am_sender;
p = strchr(host, '@');
if (p) {
user = host;
host = p+1;
*p = 0;
}
if (!user) user = getenv("USER");
if (!user) user = getenv("LOGNAME");
am_client = 1;
fd = open_socket_out(host, rsync_port);
if (fd == -1) {
exit_cleanup(1);
}
server_options(sargs,&sargc);
sargs[sargc++] = ".";
if (path && *path)
sargs[sargc++] = path;
sargs[sargc] = NULL;
io_printf(fd,"@RSYNCD: %d\n", PROTOCOL_VERSION);
if (!read_line(fd, line, sizeof(line)-1)) {
return -1;
}
if (sscanf(line,"@RSYNCD: %d", &remote_version) != 1) {
return -1;
}
p = strchr(path,'/');
if (p) *p = 0;
io_printf(fd,"%s\n",path);
if (p) *p = '/';
while (1) {
if (!read_line(fd, line, sizeof(line)-1)) {
return -1;
}
if (strncmp(line,"@RSYNCD: AUTHREQD ",18) == 0) {
auth_client(fd, user, line+18);
continue;
}
if (strcmp(line,"@RSYNCD: OK") == 0) break;
rprintf(FINFO,"%s\n", line);
}
for (i=0;i<sargc;i++) {
io_printf(fd,"%s\n", sargs[i]);
}
io_printf(fd,"\n");
if (remote_version > 17 && !am_sender)
io_start_multiplex_in(fd);
return client_run(fd, fd, -1, argc, argv);
}
static int rsync_module(int fd, int i)
{
int argc=0;
char *argv[MAX_ARGS];
char **argp;
char line[MAXPATHLEN];
uid_t uid = (uid_t)-2;
gid_t gid = (gid_t)-2;
char *p;
char *addr = client_addr(fd);
char *host = client_name(fd);
char *name = lp_name(i);
char *user;
int start_glob=0;
char *request=NULL;
extern int am_sender;
extern int remote_version;
extern int am_root;
if (!allow_access(addr, host, lp_hosts_allow(i), lp_hosts_deny(i))) {
rprintf(FERROR,"rsync denied on module %s from %s (%s)\n",
name, client_name(fd), client_addr(fd));
io_printf(fd,"@ERROR: access denied to %s from %s (%s)\n",
name, client_name(fd), client_addr(fd));
return -1;
}
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());
return -1;
}
user = auth_server(fd, i, addr, "@RSYNCD: AUTHREQD ");
if (!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);
return -1;
}
module_id = i;
if (lp_read_only(i))
read_only = 1;
p = lp_uid(i);
if (!name_to_uid(p, &uid)) {
if (!isdigit(*p)) {
rprintf(FERROR,"Invalid uid %s\n", p);
io_printf(fd,"@ERROR: invalid uid\n");
return -1;
}
uid = atoi(p);
}
p = lp_gid(i);
if (!name_to_gid(p, &gid)) {
if (!isdigit(*p)) {
rprintf(FERROR,"Invalid gid %s\n", p);
io_printf(fd,"@ERROR: invalid gid\n");
return -1;
}
gid = atoi(p);
}
p = lp_exclude_from(i);
add_exclude_file(p, 1, 0);
p = lp_exclude(i);
add_exclude_line(p);
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 (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 (setuid(uid) || getuid() != uid) {
rprintf(FERROR,"setuid %d failed\n", uid);
io_printf(fd,"@ERROR: setuid failed\n");
return -1;
}
am_root = (getuid() == 0);
io_printf(fd,"@RSYNCD: OK\n");
argv[argc++] = "rsyncd";
while (1) {
if (!read_line(fd, line, sizeof(line)-1)) {
return -1;
}
if (!*line) break;
p = line;
argv[argc] = strdup(p);
if (!argv[argc]) {
return -1;
}
if (start_glob) {
if (start_glob == 1) {
request = strdup(p);
start_glob++;
}
glob_expand(name, argv, &argc, MAX_ARGS);
} else {
argc++;
}
if (strcmp(line,".") == 0) {
start_glob = 1;
}
if (argc == MAX_ARGS) {
return -1;
}
}
parse_arguments(argc, argv);
if (request) {
if (*user) {
rprintf(FINFO,"rsync %s %s from %s@%s (%s)\n",
am_sender?"on":"to",
request, user, host, addr);
} else {
rprintf(FINFO,"rsync %s %s from %s (%s)\n",
am_sender?"on":"to",
request, host, addr);
}
free(request);
}
/* don't allow the logs to be flooded too fast */
if (verbose > 1) verbose = 1;
argc -= optind;
argp = argv + optind;
optind = 0;
if (remote_version > 17 && am_sender)
io_start_multiplex_out(fd);
start_server(fd, fd, argc, argp);
return 0;
}
/* send a list of available modules to the client. Don't list those
with "list = False". */
static void send_listing(int fd)
{
int n = lp_numservices();
int i;
for (i=0;i<n;i++)
if (lp_list(i))
io_printf(fd, "%-15s\t%s\n", lp_name(i), lp_comment(i));
}
/* this is called when a socket connection is established to a client
and we want to start talking. The setup of the system is done from
here */
static int start_daemon(int fd)
{
char line[200];
char *motd;
int i = -1;
extern char *config_file;
extern int remote_version;
if (!lp_load(config_file, 0)) {
exit_cleanup(1);
}
set_socket_options(fd,"SO_KEEPALIVE");
set_socket_options(fd,lp_socket_options());
io_printf(fd,"@RSYNCD: %d\n", PROTOCOL_VERSION);
motd = lp_motd_file();
if (*motd) {
FILE *f = fopen(motd,"r");
while (f && !feof(f)) {
int len = fread(line, 1, sizeof(line)-1, f);
if (len > 0) {
line[len] = 0;
io_printf(fd,"%s", line);
}
}
if (f) fclose(f);
io_printf(fd,"\n");
}
if (!read_line(fd, line, sizeof(line)-1)) {
return -1;
}
if (sscanf(line,"@RSYNCD: %d", &remote_version) != 1) {
io_printf(fd,"@ERROR: protocol startup error\n");
return -1;
}
while (i == -1) {
line[0] = 0;
if (!read_line(fd, line, sizeof(line)-1)) {
return -1;
}
if (!*line || strcmp(line,"#list")==0) {
send_listing(fd);
return -1;
}
if (*line == '#') {
/* it's some sort of command that I don't understand */
io_printf(fd,"@ERROR: Unknown command '%s'\n", line);
return -1;
}
i = lp_number(line);
if (i == -1) {
io_printf(fd,"@ERROR: Unknown module '%s'\n", line);
return -1;
}
}
return rsync_module(fd, i);
}
int daemon_main(void)
{
extern char *config_file;
/* this ensures that we don't call getcwd after the chroot,
which doesn't work on platforms that use popen("pwd","r")
for getcwd */
push_dir("/", 0);
if (is_a_socket(STDIN_FILENO)) {
/* we are running via inetd */
return start_daemon(STDIN_FILENO);
}
become_daemon();
if (!lp_load(config_file, 1)) {
fprintf(stderr,"failed to load config file %s\n", config_file);
exit_cleanup(1);
}
log_open();
rprintf(FINFO,"rsyncd version %s starting\n",VERSION);
start_accept_loop(rsync_port, start_daemon);
return -1;
}

View File

@@ -40,35 +40,35 @@ extern int verbose;
void setup_protocol(int f_out,int f_in)
{
if (am_server) {
remote_version = read_int(f_in);
write_int(f_out,PROTOCOL_VERSION);
write_flush(f_out);
} else {
write_int(f_out,PROTOCOL_VERSION);
write_flush(f_out);
remote_version = read_int(f_in);
}
if (remote_version == 0) {
if (am_server) {
remote_version = read_int(f_in);
write_int(f_out,PROTOCOL_VERSION);
} else {
write_int(f_out,PROTOCOL_VERSION);
remote_version = read_int(f_in);
}
}
if (remote_version < MIN_PROTOCOL_VERSION ||
remote_version > MAX_PROTOCOL_VERSION) {
fprintf(FERROR,"protocol version mismatch - is your shell clean?\n");
exit_cleanup(1);
}
if (verbose > 2)
fprintf(FINFO, "local_version=%d remote_version=%d\n",
PROTOCOL_VERSION, remote_version);
if (remote_version >= 12) {
if (am_server) {
checksum_seed = time(NULL);
write_int(f_out,checksum_seed);
} else {
checksum_seed = read_int(f_in);
}
}
checksum_init();
if (remote_version < MIN_PROTOCOL_VERSION ||
remote_version > MAX_PROTOCOL_VERSION) {
rprintf(FERROR,"protocol version mismatch - is your shell clean?\n");
exit_cleanup(1);
}
if (verbose > 2)
rprintf(FINFO, "local_version=%d remote_version=%d\n",
PROTOCOL_VERSION, remote_version);
if (remote_version >= 12) {
if (am_server) {
checksum_seed = time(NULL);
write_int(f_out,checksum_seed);
} else {
checksum_seed = read_int(f_in);
}
}
checksum_init();
}

View File

@@ -38,11 +38,10 @@ echo yes; AC_DEFINE(HAVE_ERRNO_DECL),
echo no)
AC_FUNC_MEMCMP
AC_FUNC_MMAP
AC_FUNC_UTIME_NULL
AC_CHECK_FUNCS(waitpid strtok pipe getcwd mkdir 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)
AC_CHECK_FUNCS(mmap munmap waitpid getcwd strdup strerror chown chmod mknod)
AC_CHECK_FUNCS(fchmod fstat strchr readlink link utime utimes)
AC_CHECK_FUNCS(memmove getopt_long lchown setlinebuf vsnprintf setsid glob strpbrk)
echo $ac_n "checking for working fnmatch... $ac_c"
AC_TRY_RUN([#include <fnmatch.h>
@@ -50,12 +49,34 @@ 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"
echo $ac_n "checking for long long ... $ac_c"
AC_TRY_RUN([#include <stdio.h>
main() { long long x = 1000000000000; char b[20]; sprintf(b,"%lld", x); exit(strcmp("1000000000000", b) == 0? 0: 1); }],
main() { long long x = 1000000; x *= x; exit(((x/1000000) == 1000000)? 0: 1); }],
echo yes;AC_DEFINE(HAVE_LONGLONG),
echo no)
echo $ac_n "checking for off64_t ... $ac_c"
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),
echo no)
echo $ac_n "checking for unsigned char ... $ac_c"
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)
echo $ac_n "checking for broken readdir ... $ac_c"
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)
echo $ac_n "checking for utimbuf ... $ac_c"
AC_TRY_COMPILE([#include <sys/types.h>
#include <utime.h>],
@@ -63,4 +84,36 @@ AC_TRY_COMPILE([#include <sys/types.h>
echo yes;AC_DEFINE(HAVE_UTIMBUF),
echo no)
AC_OUTPUT(Makefile lib/dummy)
# The following test taken from the cvs sources
# If we can't find connect, try looking in -lsocket, -lnsl, and -linet.
# The Irix 5 libc.so has connect and gethostbyname, but Irix 5 also has
# 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_OUTPUT(Makefile lib/dummy zlib/dummy)

46
connection.c Normal file
View File

@@ -0,0 +1,46 @@
/*
Copyright (C) Andrew Tridgell 1998
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* support the max connections option */
#include "rsync.h"
/****************************************************************************
simple routine to do connection counting
****************************************************************************/
int claim_connection(char *fname,int max_connections)
{
int fd, i;
if (max_connections <= 0)
return 1;
fd = open(fname,O_RDWR|O_CREAT, 0600);
if (fd == -1) {
return 0;
}
/* find a free spot */
for (i=0;i<max_connections;i++) {
if (lock_range(fd, i*4, 4)) return 1;
}
close(fd);
return 0;
}

338
exclude.c
View File

@@ -17,157 +17,241 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
a lot of this stuff was derived from GNU tar
*/
/* a lot of this stuff was originally derived from GNU tar, although
it has now changed so much that it is hard to tell :) */
#include "rsync.h"
extern int verbose;
extern int am_server;
static char **exclude_list;
static struct exclude_struct **exclude_list;
static int is_regex(char *str)
/* build an exclude structure given a exclude pattern */
static struct exclude_struct *make_exclude(char *pattern, int include)
{
return strchr(str, '*') || strchr(str, '[') || strchr(str, '?');
struct exclude_struct *ret;
ret = (struct exclude_struct *)malloc(sizeof(*ret));
if (!ret) out_of_memory("make_exclude");
memset(ret, 0, sizeof(*ret));
ret->orig = strdup(pattern);
if (strncmp(pattern,"- ",2) == 0) {
pattern += 2;
} else if (strncmp(pattern,"+ ",2) == 0) {
ret->include = 1;
pattern += 2;
} else {
ret->include = include;
}
ret->pattern = strdup(pattern);
if (!ret->orig || !ret->pattern) out_of_memory("make_exclude");
if (strpbrk(pattern, "*[?")) ret->regular_exp = 1;
if (strlen(pattern) > 1 && pattern[strlen(pattern)-1] == '/') {
ret->pattern[strlen(pattern)-1] = 0;
ret->directory = 1;
}
if (!strchr(ret->pattern,'/')) {
ret->local = 1;
}
return ret;
}
static void free_exclude(struct exclude_struct *ex)
{
free(ex->orig);
free(ex->pattern);
memset(ex,0,sizeof(*ex));
free(ex);
}
static int check_one_exclude(char *name,struct exclude_struct *ex,
STRUCT_STAT *st)
{
char *p;
int match_start=0;
char *pattern = ex->pattern;
if (ex->local && (p=strrchr(name,'/')))
name = p+1;
if (!name[0]) return 0;
if (ex->directory && !S_ISDIR(st->st_mode)) return 0;
if (*pattern == '/' && *name != '/') {
match_start = 1;
pattern++;
}
if (ex->regular_exp) {
if (fnmatch(pattern, name, 0) == 0)
return 1;
} else {
int l1 = strlen(name);
int l2 = strlen(pattern);
if (l2 <= l1 &&
strcmp(name+(l1-l2),pattern) == 0 &&
(l1==l2 || (!match_start && name[l1-(l2+1)] == '/')))
return 1;
}
return 0;
}
static int check_one_exclude(char *name,char *pattern)
int check_exclude(char *name,struct exclude_struct **local_exclude_list,
STRUCT_STAT *st)
{
char *p;
int n;
if (!strchr(pattern,'/') && (p=strrchr(name,'/')))
name = p+1;
if (exclude_list) {
for (n=0; exclude_list[n]; n++)
if (check_one_exclude(name,exclude_list[n],st))
return !exclude_list[n]->include;
}
if (!name[0]) return 0;
if (local_exclude_list) {
for (n=0; local_exclude_list[n]; n++)
if (check_one_exclude(name,local_exclude_list[n],st))
return !local_exclude_list[n]->include;
}
if (is_regex(pattern)) {
if (fnmatch(pattern, name, 0) == 0)
return 1;
} else {
int l1 = strlen(name);
int l2 = strlen(pattern);
if (l2 <= l1 &&
strcmp(name+(l1-l2),pattern) == 0 &&
(l1==l2 || name[l1-(l2+1)] == '/'))
return 1;
}
return 0;
return 0;
}
int check_exclude(char *name,char **local_exclude_list)
void add_exclude_list(char *pattern,struct exclude_struct ***list, int include)
{
int n;
int len=0;
if (list && *list)
for (; (*list)[len]; len++) ;
if (exclude_list) {
for (n=0; exclude_list[n]; n++)
if (check_one_exclude(name,exclude_list[n]))
return 1;
}
if (strcmp(pattern,"!") == 0) {
if (verbose > 2)
rprintf(FINFO,"clearing exclude list\n");
while ((len)--) {
free_exclude((*list)[len]);
}
free((*list));
*list = NULL;
return;
}
if (local_exclude_list) {
for (n=0; local_exclude_list[n]; n++)
if (check_one_exclude(name,local_exclude_list[n]))
return 1;
}
*list = (struct exclude_struct **)Realloc(*list,sizeof(struct exclude_struct *)*(len+2));
if (!*list || !((*list)[len] = make_exclude(pattern, include)))
out_of_memory("add_exclude");
if (verbose > 2)
rprintf(FINFO,"add_exclude(%s)\n",pattern);
(*list)[len+1] = NULL;
}
return 0;
void add_exclude(char *pattern, int include)
{
add_exclude_list(pattern,&exclude_list, include);
}
struct exclude_struct **make_exclude_list(char *fname,
struct exclude_struct **list1,
int fatal, int include)
{
struct exclude_struct **list=list1;
FILE *f = fopen(fname,"r");
char line[MAXPATHLEN];
if (!f) {
if (fatal) {
rprintf(FERROR,"%s : %s\n",fname,strerror(errno));
exit_cleanup(1);
}
return list;
}
while (fgets(line,MAXPATHLEN,f)) {
int l = strlen(line);
if (l && line[l-1] == '\n') l--;
line[l] = 0;
if (line[0]) add_exclude_list(line,&list,include);
}
fclose(f);
return list;
}
void add_exclude_list(char *pattern,char ***list)
void add_exclude_file(char *fname,int fatal,int include)
{
int len=0;
if (list && *list)
for (; (*list)[len]; len++) ;
if (!fname || !*fname) return;
if (strcmp(pattern,"!") == 0) {
if (verbose > 2)
fprintf(FINFO,"clearing exclude list\n");
while ((len)--)
free((*list)[len]);
free((*list));
*list = NULL;
return;
}
if (!*list) {
*list = (char **)malloc(sizeof(char *)*2);
} else {
*list = (char **)realloc(*list,sizeof(char *)*(len+2));
}
if (!*list || !((*list)[len] = strdup(pattern)))
out_of_memory("add_exclude");
if (verbose > 2)
fprintf(FINFO,"add_exclude(%s)\n",pattern);
(*list)[len+1] = NULL;
}
void add_exclude(char *pattern)
{
add_exclude_list(pattern,&exclude_list);
}
char **make_exclude_list(char *fname,char **list1,int fatal)
{
char **list=list1;
FILE *f = fopen(fname,"r");
char line[MAXPATHLEN];
if (!f) {
if (fatal) {
fprintf(FERROR,"%s : %s\n",fname,strerror(errno));
exit_cleanup(1);
}
return list;
}
while (fgets(line,MAXPATHLEN,f)) {
int l = strlen(line);
if (l && line[l-1] == '\n') l--;
line[l] = 0;
if (line[0]) add_exclude_list(line,&list);
}
fclose(f);
return list;
}
void add_exclude_file(char *fname,int fatal)
{
exclude_list = make_exclude_list(fname,exclude_list,fatal);
exclude_list = make_exclude_list(fname,exclude_list,fatal,include);
}
void send_exclude_list(int f)
{
int i;
if (exclude_list)
for (i=0;exclude_list[i];i++) {
int l = strlen(exclude_list[i]);
if (l == 0) continue;
write_int(f,l);
write_buf(f,exclude_list[i],l);
}
write_int(f,0);
int i;
extern int remote_version;
if (!exclude_list) {
write_int(f,0);
return;
}
for (i=0;exclude_list[i];i++) {
char *pattern = exclude_list[i]->orig;
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);
write_buf(f,pattern,l);
}
write_int(f,0);
}
void recv_exclude_list(int f)
{
char line[MAXPATHLEN];
int l;
while ((l=read_int(f))) {
if (l >= MAXPATHLEN) overflow("recv_exclude_list");
read_sbuf(f,line,l);
add_exclude(line);
}
char line[MAXPATHLEN];
int l;
while ((l=read_int(f))) {
if (l >= MAXPATHLEN) overflow("recv_exclude_list");
read_sbuf(f,line,l);
add_exclude(line,0);
}
}
void add_exclude_line(char *p)
{
char *tok;
if (!p || !*p) return;
p = strdup(p);
if (!p) out_of_memory("add_exclude_line");
for (tok=strtok(p," "); tok; tok=strtok(NULL," "))
add_exclude(tok, 0);
free(p);
}
@@ -182,21 +266,17 @@ static char *cvs_ignore_list[] = {
void add_cvs_excludes(void)
{
char fname[MAXPATHLEN];
char *p;
int i;
char fname[MAXPATHLEN];
char *p;
int i;
for (i=0; cvs_ignore_list[i]; i++)
add_exclude(cvs_ignore_list[i]);
for (i=0; cvs_ignore_list[i]; i++)
add_exclude(cvs_ignore_list[i], 0);
if ((p=getenv("HOME")) && strlen(p) < (MAXPATHLEN-12)) {
sprintf(fname,"%s/.cvsignore",p);
add_exclude_file(fname,0);
}
if ((p=getenv("HOME")) && strlen(p) < (MAXPATHLEN-12)) {
slprintf(fname,sizeof(fname)-1, "%s/.cvsignore",p);
add_exclude_file(fname,0,0);
}
if ((p=getenv("CVSIGNORE"))) {
char *tok;
for (tok=strtok(p," "); tok; tok=strtok(NULL," "))
add_exclude(tok);
}
add_exclude_line(getenv("CVSIGNORE"));
}

218
fileio.c Normal file
View File

@@ -0,0 +1,218 @@
/*
Copyright (C) Andrew Tridgell 1998
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
File IO utilities used in rsync
*/
#include "rsync.h"
static char last_byte;
static int last_sparse;
extern int sparse_files;
int sparse_end(int f)
{
if (last_sparse) {
do_lseek(f,-1,SEEK_CUR);
return (write(f,&last_byte,1) == 1 ? 0 : -1);
}
last_sparse = 0;
return 0;
}
static int write_sparse(int f,char *buf,int len)
{
int l1=0,l2=0;
int ret;
for (l1=0;l1<len && buf[l1]==0;l1++) ;
for (l2=0;l2<(len-l1) && buf[len-(l2+1)]==0;l2++) ;
last_byte = buf[len-1];
if (l1 == len || l2 > 0)
last_sparse=1;
if (l1 > 0)
do_lseek(f,l1,SEEK_CUR);
if (l1 == len)
return len;
if ((ret=write(f,buf+l1,len-(l1+l2))) != len-(l1+l2)) {
if (ret == -1 || ret == 0) return ret;
return (l1+ret);
}
if (l2 > 0)
do_lseek(f,l2,SEEK_CUR);
return len;
}
int write_file(int f,char *buf,int len)
{
int ret = 0;
if (!sparse_files)
return write(f,buf,len);
while (len>0) {
int len1 = MIN(len, SPARSE_WRITE_SIZE);
int r1 = write_sparse(f, buf, len1);
if (r1 <= 0) {
if (ret > 0) return ret;
return r1;
}
len -= r1;
buf += r1;
ret += r1;
}
return ret;
}
struct map_struct *map_file(int fd,OFF_T len)
{
struct map_struct *ret;
ret = (struct map_struct *)malloc(sizeof(*ret));
if (!ret) out_of_memory("map_file");
ret->map = NULL;
ret->fd = fd;
ret->size = len;
ret->p = NULL;
ret->p_size = 0;
ret->p_offset = 0;
ret->p_len = 0;
#ifdef USE_MMAP
len = MIN(len, MAX_MAP_SIZE);
ret->map = (char *)do_mmap(NULL,len,PROT_READ,MAP_SHARED,fd,0);
if (ret->map == (char *)-1) {
ret->map = NULL;
} else {
ret->p_len = len;
}
#endif
return ret;
}
char *map_ptr(struct map_struct *map,OFF_T offset,int len)
{
int nread;
if (len == 0)
return NULL;
if (len > (map->size-offset))
len = map->size-offset;
#ifdef USE_MMAP
if (map->map) {
if (offset >= map->p_offset &&
offset+len <= map->p_offset+map->p_len) {
return (map->map + (offset - map->p_offset));
}
if (munmap(map->map, map->p_len) != 0) {
rprintf(FERROR,"munmap failed : %s\n", strerror(errno));
exit_cleanup(1);
}
/* align the mmap region on a nice boundary back a bit from
where it is asked for to allow for some seeking */
if (offset > 2*CHUNK_SIZE) {
map->p_offset = offset - 2*CHUNK_SIZE;
map->p_offset &= ~((OFF_T)(CHUNK_SIZE-1));
} else {
map->p_offset = 0;
}
/* map up to MAX_MAP_SIZE */
map->p_len = MAX(len, MAX_MAP_SIZE);
map->p_len = MIN(map->p_len, map->size - map->p_offset);
map->map = (char *)do_mmap(NULL,map->p_len,PROT_READ,
MAP_SHARED,map->fd,map->p_offset);
if (map->map == (char *)-1) {
map->map = NULL;
map->p_len = 0;
map->p_offset = 0;
} else {
return (map->map + (offset - map->p_offset));
}
}
#endif
if (offset >= map->p_offset &&
offset+len <= map->p_offset+map->p_len) {
return (map->p + (offset - map->p_offset));
}
len = MAX(len,CHUNK_SIZE);
if (len > (map->size-offset))
len = map->size-offset;
if (len > map->p_size) {
if (map->p) free(map->p);
map->p = (char *)malloc(len);
if (!map->p) out_of_memory("map_ptr");
map->p_size = len;
}
map->p_offset = offset;
map->p_len = len;
if (do_lseek(map->fd,offset,SEEK_SET) != offset) {
rprintf(FERROR,"lseek failed in map_ptr\n");
exit_cleanup(1);
}
if ((nread=read(map->fd,map->p,len)) != len) {
if (nread < 0) nread = 0;
/* the best we can do is zero the buffer - the file
has changed mid transfer! */
memset(map->p+nread, 0, len - nread);
}
return map->p;
}
void unmap_file(struct map_struct *map)
{
#ifdef USE_MMAP
if (map->map) {
munmap(map->map,map->p_len);
map->map = NULL;
}
#endif
if (map->p) {
free(map->p);
map->p = NULL;
}
memset(map, 0, sizeof(*map));
free(map);
}

229
flist.c
View File

@@ -21,12 +21,13 @@
#include "rsync.h"
extern struct stats stats;
extern int csum_length;
extern int verbose;
extern int am_server;
extern int always_checksum;
extern int64 total_size;
extern int cvs_exclude;
@@ -46,18 +47,18 @@ extern int copy_links;
extern int remote_version;
extern int io_error;
static char **local_exclude_list;
static struct exclude_struct **local_exclude_list;
int link_stat(const char *Path, struct stat *Buffer)
int link_stat(const char *Path, STRUCT_STAT *Buffer)
{
#if SUPPORT_LINKS
if (copy_links) {
return stat(Path, Buffer);
return do_stat(Path, Buffer);
} else {
return lstat(Path, Buffer);
return do_lstat(Path, Buffer);
}
#else
return stat(Path, Buffer);
return do_stat(Path, Buffer);
#endif
}
@@ -65,11 +66,11 @@ int link_stat(const char *Path, struct stat *Buffer)
This function is used to check if a file should be included/excluded
from the list of files based on its name and type etc
*/
static int match_file_name(char *fname,struct stat *st)
static int match_file_name(char *fname,STRUCT_STAT *st)
{
if (check_exclude(fname,local_exclude_list)) {
if (check_exclude(fname,local_exclude_list,st)) {
if (verbose > 2)
fprintf(FINFO,"excluding file %s\n",fname);
rprintf(FINFO,"excluding file %s\n",fname);
return 0;
}
return 1;
@@ -80,7 +81,7 @@ static dev_t filesystem_dev;
static void set_filesystem(char *fname)
{
struct stat st;
STRUCT_STAT st;
if (link_stat(fname,&st) != 0) return;
filesystem_dev = st.st_dev;
}
@@ -90,49 +91,6 @@ static void send_directory(int f,struct file_list *flist,char *dir);
static char *flist_dir;
static void clean_fname(char *name)
{
char *p;
int l;
int modified = 1;
if (!name) return;
while (modified) {
modified = 0;
if ((p=strstr(name,"/./"))) {
modified = 1;
while (*p) {
p[0] = p[2];
p++;
}
}
if ((p=strstr(name,"//"))) {
modified = 1;
while (*p) {
p[0] = p[1];
p++;
}
}
if (strncmp(p=name,"./",2) == 0) {
modified = 1;
do {
p[0] = p[2];
} while (*p++);
}
l = strlen(p=name);
if (l > 1 && p[l-1] == '/') {
modified = 1;
p[l-1] = 0;
}
}
}
void send_file_entry(struct file_struct *file,int f,unsigned base_flags)
{
@@ -163,12 +121,17 @@ void send_file_entry(struct file_struct *file,int f,unsigned base_flags)
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++) ;
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;
/* 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);
@@ -218,7 +181,7 @@ void send_file_entry(struct file_struct *file,int f,unsigned base_flags)
last_gid = file->gid;
last_time = file->modtime;
strncpy(lastname,fname,MAXPATHLEN-1);
strlcpy(lastname,fname,MAXPATHLEN-1);
lastname[MAXPATHLEN-1] = 0;
}
@@ -248,20 +211,26 @@ static void receive_file_entry(struct file_struct **fptr,
file = (struct file_struct *)malloc(sizeof(*file));
if (!file) out_of_memory("receive_file_entry");
bzero((char *)file,sizeof(*file));
memset((char *)file, 0, sizeof(*file));
(*fptr) = file;
if (l2 >= MAXPATHLEN-l1) overflow("receive_file_entry");
strncpy(thisname,lastname,l1);
strlcpy(thisname,lastname,l1);
read_sbuf(f,&thisname[l1],l2);
thisname[l1+l2] = 0;
strncpy(lastname,thisname,MAXPATHLEN-1);
strlcpy(lastname,thisname,MAXPATHLEN-1);
lastname[MAXPATHLEN-1] = 0;
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;
@@ -322,9 +291,9 @@ static void receive_file_entry(struct file_struct **fptr,
/* determine if a file in a different filesstem should be skipped
when one_file_system is set. We bascally only want to include
the mount points - but they can be hard to find! */
static int skip_filesystem(char *fname, struct stat *st)
static int skip_filesystem(char *fname, STRUCT_STAT *st)
{
struct stat st2;
STRUCT_STAT st2;
char *p = strrchr(fname, '/');
/* skip all but directories */
@@ -346,27 +315,27 @@ static int skip_filesystem(char *fname, struct stat *st)
static struct file_struct *make_file(char *fname)
{
struct file_struct *file;
struct stat st;
STRUCT_STAT st;
char sum[SUM_LENGTH];
char *p;
char cleaned_name[MAXPATHLEN];
strncpy(cleaned_name, fname, MAXPATHLEN-1);
strlcpy(cleaned_name, fname, MAXPATHLEN-1);
cleaned_name[MAXPATHLEN-1] = 0;
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;
fprintf(FERROR,"%s: %s\n",
rprintf(FERROR,"%s: %s\n",
fname,strerror(errno));
return NULL;
}
if (S_ISDIR(st.st_mode) && !recurse) {
fprintf(FINFO,"skipping directory %s\n",fname);
rprintf(FINFO,"skipping directory %s\n",fname);
return NULL;
}
@@ -379,11 +348,11 @@ static struct file_struct *make_file(char *fname)
return NULL;
if (verbose > 2)
fprintf(FINFO,"make_file(%s)\n",fname);
rprintf(FINFO,"make_file(%s)\n",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;
@@ -418,7 +387,7 @@ static struct file_struct *make_file(char *fname)
char lnk[MAXPATHLEN];
if ((l=readlink(fname,lnk,MAXPATHLEN-1)) == -1) {
io_error=1;
fprintf(FERROR,"readlink %s : %s\n",
rprintf(FERROR,"readlink %s : %s\n",
fname,strerror(errno));
return NULL;
}
@@ -453,7 +422,7 @@ static struct file_struct *make_file(char *fname)
}
if (!S_ISDIR(st.st_mode))
total_size += st.st_size;
stats.total_size += st.st_size;
return file;
}
@@ -487,10 +456,10 @@ static void send_file_name(int f,struct file_list *flist,char *fname,
}
if (S_ISDIR(file->mode) && recursive) {
char **last_exclude_list = local_exclude_list;
send_directory(f,flist,f_name(file));
local_exclude_list = last_exclude_list;
return;
struct exclude_struct **last_exclude_list = local_exclude_list;
send_directory(f,flist,f_name(file));
local_exclude_list = last_exclude_list;
return;
}
}
@@ -507,22 +476,21 @@ static void send_directory(int f,struct file_list *flist,char *dir)
d = opendir(dir);
if (!d) {
io_error = 1;
fprintf(FERROR,"%s: %s\n",
rprintf(FERROR,"opendir(%s): %s\n",
dir,strerror(errno));
return;
}
strncpy(fname,dir,MAXPATHLEN-1);
fname[MAXPATHLEN-1]=0;
strlcpy(fname,dir,MAXPATHLEN-1);
l = strlen(fname);
if (fname[l-1] != '/') {
if (l == MAXPATHLEN-1) {
io_error = 1;
fprintf(FERROR,"skipping long-named directory %s\n",fname);
rprintf(FERROR,"skipping long-named directory %s\n",fname);
closedir(d);
return;
}
strcat(fname,"/");
strlcat(fname,"/", MAXPATHLEN-1);
l++;
}
p = fname + strlen(fname);
@@ -530,19 +498,20 @@ static void send_directory(int f,struct file_list *flist,char *dir)
if (cvs_exclude) {
if (strlen(fname) + strlen(".cvsignore") <= MAXPATHLEN-1) {
strcpy(p,".cvsignore");
local_exclude_list = make_exclude_list(fname,NULL,0);
local_exclude_list = make_exclude_list(fname,NULL,0,0);
} else {
io_error = 1;
fprintf(FINFO,"cannot cvs-exclude in long-named directory %s\n",fname);
rprintf(FINFO,"cannot cvs-exclude in long-named directory %s\n",fname);
}
}
for (di=readdir(d); di; di=readdir(d)) {
if (strcmp(di->d_name,".")==0 ||
strcmp(di->d_name,"..")==0)
char *dname = d_name(di);
if (strcmp(dname,".")==0 ||
strcmp(dname,"..")==0)
continue;
strncpy(p,di->d_name,MAXPATHLEN-(l+1));
send_file_name(f,flist,fname,recurse,FLAG_DELETE);
strlcpy(p,dname,MAXPATHLEN-(l+1));
send_file_name(f,flist,fname,recurse,0);
}
closedir(d);
@@ -553,17 +522,19 @@ static void send_directory(int f,struct file_list *flist,char *dir)
struct file_list *send_file_list(int f,int argc,char *argv[])
{
int i,l;
struct stat st;
STRUCT_STAT st;
char *p,*dir;
char dbuf[MAXPATHLEN];
char lastpath[MAXPATHLEN]="";
struct file_list *flist;
int64 start_write;
if (verbose && recurse && !am_server && f != -1) {
fprintf(FINFO,"building file list ... ");
fflush(FINFO);
rprintf(FINFO,"building file list ... ");
rflush(FINFO);
}
start_write = stats.total_written;
flist = (struct file_list *)malloc(sizeof(flist[0]));
if (!flist) out_of_memory("send_file_list");
@@ -573,26 +544,29 @@ struct file_list *send_file_list(int f,int argc,char *argv[])
flist->malloced);
if (!flist->files) out_of_memory("send_file_list");
if (f != -1) {
io_start_buffering(f);
}
for (i=0;i<argc;i++) {
char fname2[MAXPATHLEN];
char *fname = fname2;
strncpy(fname,argv[i],MAXPATHLEN-1);
fname[MAXPATHLEN-1] = 0;
strlcpy(fname,argv[i],MAXPATHLEN-1);
l = strlen(fname);
if (l != 1 && fname[l-1] == '/') {
strcat(fname,".");
strlcat(fname,".",MAXPATHLEN-1);
}
if (link_stat(fname,&st) != 0) {
io_error=1;
fprintf(FERROR,"%s : %s\n",fname,strerror(errno));
rprintf(FERROR,"%s : %s\n",fname,strerror(errno));
continue;
}
if (S_ISDIR(st.st_mode) && !recurse) {
fprintf(FINFO,"skipping directory %s\n",fname);
rprintf(FINFO,"skipping directory %s\n",fname);
continue;
}
@@ -613,11 +587,14 @@ struct file_list *send_file_list(int f,int argc,char *argv[])
thus getting their permissions right */
*p = 0;
if (strcmp(lastpath,fname)) {
strcpy(lastpath, fname);
strlcpy(lastpath, fname, sizeof(lastpath)-1);
*p = '/';
for (p=fname+1; (p=strchr(p,'/')); p++) {
int copy_links_saved = copy_links;
*p = 0;
copy_links = 0;
send_file_name(f, flist, fname, 0, 0);
copy_links = copy_links_saved;
*p = '/';
}
} else {
@@ -629,24 +606,23 @@ struct file_list *send_file_list(int f,int argc,char *argv[])
fname = ".";
if (dir && *dir) {
if (getcwd(dbuf,MAXPATHLEN-1) == NULL) {
fprintf(FERROR,"getwd : %s\n",strerror(errno));
exit_cleanup(1);
}
if (chdir(dir) != 0) {
char *olddir = push_dir(dir, 1);
if (!olddir) {
io_error=1;
fprintf(FERROR,"chdir %s : %s\n",
rprintf(FERROR,"push_dir %s : %s\n",
dir,strerror(errno));
continue;
}
flist_dir = dir;
if (one_file_system)
set_filesystem(fname);
send_file_name(f,flist,fname,recurse,FLAG_DELETE);
flist_dir = NULL;
if (chdir(dbuf) != 0) {
fprintf(FERROR,"chdir %s : %s\n",
dbuf,strerror(errno));
if (pop_dir(olddir) != 0) {
rprintf(FERROR,"pop_dir %s : %s\n",
dir,strerror(errno));
exit_cleanup(1);
}
continue;
@@ -659,11 +635,10 @@ struct file_list *send_file_list(int f,int argc,char *argv[])
if (f != -1) {
send_file_entry(NULL,f,0);
write_flush(f);
}
if (verbose && recurse && !am_server && f != -1)
fprintf(FINFO,"done\n");
rprintf(FINFO,"done\n");
clean_flist(flist);
@@ -678,8 +653,14 @@ struct file_list *send_file_list(int f,int argc,char *argv[])
write_int(f, io_error);
}
if (f != -1) {
io_end_buffering(f);
stats.flist_size = stats.total_written - start_write;
stats.num_files = flist->count;
}
if (verbose > 2)
fprintf(FINFO,"send_file_list done\n");
rprintf(FINFO,"send_file_list done\n");
return flist;
}
@@ -689,12 +670,15 @@ struct file_list *recv_file_list(int f)
{
struct file_list *flist;
unsigned char flags;
int64 start_read;
if (verbose && recurse && !am_server) {
fprintf(FINFO,"receiving file list ... ");
fflush(FINFO);
rprintf(FINFO,"receiving file list ... ");
rflush(FINFO);
}
start_read = stats.total_read;
flist = (struct file_list *)malloc(sizeof(flist[0]));
if (!flist)
goto oom;
@@ -725,22 +709,22 @@ struct file_list *recv_file_list(int f)
receive_file_entry(&flist->files[i],flags,f);
if (S_ISREG(flist->files[i]->mode))
total_size += flist->files[i]->length;
stats.total_size += flist->files[i]->length;
flist->count++;
if (verbose > 2)
fprintf(FINFO,"recv_file_name(%s)\n",f_name(flist->files[i]));
rprintf(FINFO,"recv_file_name(%s)\n",f_name(flist->files[i]));
}
if (verbose > 2)
fprintf(FINFO,"received %d names\n",flist->count);
rprintf(FINFO,"received %d names\n",flist->count);
clean_flist(flist);
if (verbose && recurse && !am_server) {
fprintf(FINFO,"done\n");
rprintf(FINFO,"done\n");
}
/* now recv the uid/gid list. This was introduced in protocol version 15 */
@@ -754,7 +738,10 @@ struct file_list *recv_file_list(int f)
}
if (verbose > 2)
fprintf(FINFO,"recv_file_list done\n");
rprintf(FINFO,"recv_file_list done\n");
stats.flist_size = stats.total_read - start_read;
stats.num_files = flist->count;
return flist;
@@ -770,8 +757,8 @@ int file_compare(struct file_struct **f1,struct file_struct **f2)
if (!(*f1)->basename) return -1;
if (!(*f2)->basename) return 1;
if ((*f1)->dirname == (*f2)->dirname)
return strcmp((*f1)->basename, (*f2)->basename);
return strcmp(f_name(*f1),f_name(*f2));
return u_strcmp((*f1)->basename, (*f2)->basename);
return u_strcmp(f_name(*f1),f_name(*f2));
}
@@ -807,7 +794,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));
}
@@ -821,9 +808,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);
}
@@ -849,7 +836,7 @@ void clean_flist(struct file_list *flist)
strcmp(f_name(flist->files[i]),
f_name(flist->files[i-1])) == 0) {
if (verbose > 1 && !am_server)
fprintf(FINFO,"removing duplicate name %s from file list %d\n",
rprintf(FINFO,"removing duplicate name %s from file list %d\n",
f_name(flist->files[i-1]),i-1);
free_file(flist->files[i]);
}
@@ -871,9 +858,9 @@ char *f_name(struct file_struct *f)
n = (n+1)%10;
if (f->dirname) {
sprintf(p, "%s/%s", f->dirname, f->basename);
slprintf(p, MAXPATHLEN-1, "%s/%s", f->dirname, f->basename);
} else {
strcpy(p, f->basename);
strlcpy(p, f->basename, MAXPATHLEN-1);
}
return p;

11
hlink.c
View File

@@ -19,7 +19,6 @@
#include "rsync.h"
extern int am_server;
extern int dry_run;
extern int verbose;
@@ -57,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,14 +105,14 @@ int check_hard_link(struct file_struct *file)
#if SUPPORT_HARD_LINKS
static void hard_link_one(int i)
{
struct stat st1,st2;
STRUCT_STAT st1,st2;
if (link_stat(f_name(&hlink_list[i-1]),&st1) != 0) return;
if (link_stat(f_name(&hlink_list[i]),&st2) != 0) {
if (do_link(f_name(&hlink_list[i-1]),f_name(&hlink_list[i])) != 0) {
if (verbose > 0)
fprintf(FINFO,"link %s => %s : %s\n",
rprintf(FINFO,"link %s => %s : %s\n",
f_name(&hlink_list[i]),
f_name(&hlink_list[i-1]),strerror(errno));
return;
@@ -124,14 +123,14 @@ static void hard_link_one(int i)
if (do_unlink(f_name(&hlink_list[i])) != 0 ||
do_link(f_name(&hlink_list[i-1]),f_name(&hlink_list[i])) != 0) {
if (verbose > 0)
fprintf(FINFO,"link %s => %s : %s\n",
rprintf(FINFO,"link %s => %s : %s\n",
f_name(&hlink_list[i]),
f_name(&hlink_list[i-1]),strerror(errno));
return;
}
}
if (verbose > 0)
fprintf(FINFO,"%s => %s\n",
rprintf(FINFO,"%s => %s\n",
f_name(&hlink_list[i]),f_name(&hlink_list[i-1]));
}
#endif

685
io.c
View File

@@ -24,81 +24,23 @@
*/
#include "rsync.h"
static int64 total_written;
static int64 total_read;
static int io_multiplexing_out;
static int io_multiplexing_in;
static int multiplex_in_fd;
static int multiplex_out_fd;
static time_t last_io;
static int eof_error=1;
extern int verbose;
extern int sparse_files;
extern int io_timeout;
int64 write_total(void)
{
return total_written;
}
int64 read_total(void)
{
return total_read;
}
extern struct stats stats;
static int buffer_f_in = -1;
void setup_nonblocking(int f_in,int f_out)
void setup_readbuffer(int f_in)
{
set_blocking(f_out,0);
buffer_f_in = f_in;
buffer_f_in = f_in;
}
static char *read_buffer;
static char *read_buffer_p;
static int read_buffer_len;
static int read_buffer_size;
/* This function was added to overcome a deadlock problem when using
* ssh. It looks like we can't allow our receive queue to get full or
* ssh will clag up. Uggh. */
static void read_check(int f)
{
int n;
if (f == -1) return;
if (read_buffer_len == 0) {
read_buffer_p = read_buffer;
}
if ((n=num_waiting(f)) <= 0)
return;
/* things could deteriorate if we read in really small chunks */
if (n < 10) n = 1024;
if (read_buffer_p != read_buffer) {
memmove(read_buffer,read_buffer_p,read_buffer_len);
read_buffer_p = read_buffer;
}
if (n > (read_buffer_size - read_buffer_len)) {
read_buffer_size += n;
if (!read_buffer)
read_buffer = (char *)malloc(read_buffer_size);
else
read_buffer = (char *)realloc(read_buffer,read_buffer_size);
if (!read_buffer) out_of_memory("read check");
read_buffer_p = read_buffer;
}
n = read(f,read_buffer+read_buffer_len,n);
if (n > 0) {
read_buffer_len += n;
}
}
static time_t last_io;
static void check_timeout(void)
{
time_t t;
@@ -113,20 +55,192 @@ static void check_timeout(void)
t = time(NULL);
if (last_io && io_timeout && (t-last_io)>io_timeout) {
fprintf(FERROR,"read timeout after %d second - exiting\n",
rprintf(FERROR,"read timeout after %d second - exiting\n",
(int)(t-last_io));
exit_cleanup(1);
}
}
static int readfd(int fd,char *buffer,int N)
static char *read_buffer;
static char *read_buffer_p;
static int read_buffer_len;
static int read_buffer_size;
static int no_flush;
/* read from a socket with IO timeout. return the number of
bytes read. If no bytes can be read then exit, never return
a number <= 0 */
static int read_timeout(int fd, char *buf, int len)
{
int n, ret=0;
io_flush();
while (ret == 0) {
fd_set fds;
struct timeval tv;
FD_ZERO(&fds);
FD_SET(fd, &fds);
tv.tv_sec = io_timeout;
tv.tv_usec = 0;
if (select(fd+1, &fds, NULL, NULL,
io_timeout?&tv:NULL) != 1) {
check_timeout();
continue;
}
n = read(fd, buf, len);
if (n > 0) {
stats.total_read += n;
buf += n;
len -= n;
ret += n;
if (io_timeout)
last_io = time(NULL);
continue;
}
if (n == -1 && errno == EINTR) {
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");
}
exit_cleanup(1);
}
rprintf(FERROR,"read error: %s\n", strerror(errno));
exit_cleanup(1);
}
return ret;
}
/* continue trying to read len bytes - don't return until len
has been read */
static void read_loop(int fd, char *buf, int len)
{
while (len) {
int n = read_timeout(fd, buf, len);
buf += n;
len -= n;
}
}
/* read from the file descriptor handling multiplexing -
return number of bytes read
never return <= 0 */
static int read_unbuffered(int fd, char *buf, int len)
{
static int remaining;
char ibuf[4];
int tag, ret=0;
char line[1024];
if (!io_multiplexing_in || fd != multiplex_in_fd)
return read_timeout(fd, buf, len);
while (ret == 0) {
if (remaining) {
len = MIN(len, remaining);
read_loop(fd, buf, len);
remaining -= len;
ret = len;
continue;
}
read_loop(fd, ibuf, 4);
tag = IVAL(ibuf, 0);
remaining = tag & 0xFFFFFF;
tag = tag >> 24;
if (tag == MPLEX_BASE) continue;
tag -= MPLEX_BASE;
if (tag != FERROR && tag != FINFO) {
rprintf(FERROR,"unexpected tag %d\n", tag);
exit_cleanup(1);
}
if (remaining > sizeof(line)-1) {
rprintf(FERROR,"multiplexing overflow %d\n\n",
remaining);
exit_cleanup(1);
}
read_loop(fd, line, remaining);
line[remaining] = 0;
rprintf(tag,"%s", line);
remaining = 0;
}
return ret;
}
/* This function was added to overcome a deadlock problem when using
* ssh. It looks like we can't allow our receive queue to get full or
* ssh will clag up. Uggh. */
static void read_check(int f)
{
int n = 8192;
if (f == -1) return;
if (read_buffer_len == 0) {
read_buffer_p = read_buffer;
}
if (n > MAX_READ_BUFFER/4)
n = MAX_READ_BUFFER/4;
if (read_buffer_p != read_buffer) {
memmove(read_buffer,read_buffer_p,read_buffer_len);
read_buffer_p = read_buffer;
}
if (n > (read_buffer_size - read_buffer_len)) {
read_buffer_size += n;
read_buffer = (char *)Realloc(read_buffer,read_buffer_size);
if (!read_buffer) out_of_memory("read check");
read_buffer_p = read_buffer;
}
n = read_unbuffered(f,read_buffer+read_buffer_len,n);
read_buffer_len += n;
}
/* do a buffered read from fd. don't return until all N bytes
have been read. If all N can't be read then exit with an error */
static void readfd(int fd,char *buffer,int N)
{
int ret;
int total=0;
struct timeval tv;
if (read_buffer_len < N)
if (read_buffer_len < N && N < 1024) {
read_check(buffer_f_in);
}
while (total < N) {
if (read_buffer_len > 0 && buffer_f_in == fd) {
@@ -138,44 +252,19 @@ static int readfd(int fd,char *buffer,int N)
continue;
}
while ((ret = read(fd,buffer + total,N-total)) == -1) {
fd_set fds;
io_flush();
if (errno != EAGAIN && errno != EWOULDBLOCK)
return -1;
FD_ZERO(&fds);
FD_SET(fd, &fds);
tv.tv_sec = io_timeout;
tv.tv_usec = 0;
if (select(fd+1, &fds, NULL, NULL, &tv) != 1) {
check_timeout();
}
}
if (ret <= 0)
return total;
ret = read_unbuffered(fd,buffer + total,N-total);
total += ret;
}
if (io_timeout)
last_io = time(NULL);
return total;
}
int read_int(int f)
int32 read_int(int f)
{
int ret;
char b[4];
if ((ret=readfd(f,b,4)) != 4) {
if (verbose > 1)
fprintf(FERROR,"(%d) Error reading %d bytes : %s\n",
getpid(),4,ret==-1?strerror(errno):"EOF");
exit_cleanup(1);
}
total_read += 4;
return IVAL(b,0);
char b[4];
readfd(f,b,4);
return IVAL(b,0);
}
int64 read_longint(int f)
@@ -185,20 +274,14 @@ int64 read_longint(int f)
char b[8];
ret = read_int(f);
if (ret != -1) return ret;
if ((int32)ret != (int32)0xffffffff) return ret;
#ifndef HAVE_LONGLONG
fprintf(FERROR,"Integer overflow - attempted 64 bit offset\n");
#ifdef NO_INT64
rprintf(FERROR,"Integer overflow - attempted 64 bit offset\n");
exit_cleanup(1);
#else
if (remote_version >= 16) {
if ((ret=readfd(f,b,8)) != 8) {
if (verbose > 1)
fprintf(FERROR,"(%d) Error reading %d bytes : %s\n",
getpid(),8,ret==-1?strerror(errno):"EOF");
exit_cleanup(1);
}
total_read += 8;
readfd(f,b,8);
ret = IVAL(b,0) | (((int64)IVAL(b,4))<<32);
}
#endif
@@ -208,14 +291,7 @@ int64 read_longint(int f)
void read_buf(int f,char *buf,int len)
{
int ret;
if ((ret=readfd(f,buf,len)) != len) {
if (verbose > 1)
fprintf(FERROR,"(%d) Error reading %d bytes : %s\n",
getpid(),len,ret==-1?strerror(errno):"EOF");
exit_cleanup(1);
}
total_read += len;
readfd(f,buf,len);
}
void read_sbuf(int f,char *buf,int len)
@@ -226,174 +302,161 @@ void read_sbuf(int f,char *buf,int len)
unsigned char read_byte(int f)
{
unsigned char c;
read_buf(f,(char *)&c,1);
return c;
}
static char last_byte;
static int last_sparse;
int sparse_end(int f)
{
if (last_sparse) {
lseek(f,-1,SEEK_CUR);
return (write(f,&last_byte,1) == 1 ? 0 : -1);
}
last_sparse = 0;
return 0;
}
static int write_sparse(int f,char *buf,int len)
{
int l1=0,l2=0;
int ret;
for (l1=0;l1<len && buf[l1]==0;l1++) ;
for (l2=0;l2<(len-l1) && buf[len-(l2+1)]==0;l2++) ;
last_byte = buf[len-1];
if (l1 == len || l2 > 0)
last_sparse=1;
if (l1 > 0)
lseek(f,l1,SEEK_CUR);
if (l1 == len)
return len;
if ((ret=write(f,buf+l1,len-(l1+l2))) != len-(l1+l2)) {
if (ret == -1 || ret == 0) return ret;
return (l1+ret);
}
if (l2 > 0)
lseek(f,l2,SEEK_CUR);
return len;
unsigned char c;
read_buf(f,(char *)&c,1);
return c;
}
int write_file(int f,char *buf,int len)
/* write len bytes to fd, possibly reading from buffer_f_in if set
in order to unclog the pipe. don't return until all len
bytes have been written */
static void writefd_unbuffered(int fd,char *buf,int len)
{
int ret = 0;
int total = 0;
fd_set w_fds, r_fds;
int fd_count, count;
struct timeval tv;
int reading;
if (!sparse_files)
return write(f,buf,len);
no_flush++;
while (len>0) {
int len1 = MIN(len, SPARSE_WRITE_SIZE);
int r1 = write_sparse(f, buf, len1);
if (r1 <= 0) {
if (ret > 0) return ret;
return r1;
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 (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_usec = 0;
count = select(fd_count,
reading?&r_fds:NULL,
&w_fds,NULL,
io_timeout?&tv:NULL);
if (count <= 0) {
check_timeout();
continue;
}
if (FD_ISSET(fd, &w_fds)) {
int ret = write(fd,buf+total,len-total);
if (ret == -1 && errno == EINTR) {
continue;
}
if (ret == -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 (ret <= 0) {
rprintf(FERROR,"erroring writing %d bytes - exiting\n", len);
exit_cleanup(1);
}
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);
}
len -= r1;
buf += r1;
ret += r1;
}
return ret;
no_flush--;
}
static int writefd(int fd,char *buf,int len)
static char *io_buffer;
static int io_buffer_count;
void io_start_buffering(int fd)
{
int total = 0;
fd_set w_fds, r_fds;
int fd_count, count, got_select=0;
struct timeval tv;
if (io_buffer) return;
multiplex_out_fd = fd;
io_buffer = (char *)malloc(IO_BUFFER_SIZE+4);
if (!io_buffer) out_of_memory("writefd");
io_buffer_count = 0;
if (buffer_f_in == -1)
return write(fd,buf,len);
/* leave room for the multiplex header in case it's needed */
io_buffer += 4;
}
while (total < len) {
int ret = write(fd,buf+total,len-total);
void io_flush(void)
{
int fd = multiplex_out_fd;
if (!io_buffer_count || no_flush) return;
if (ret == 0) return total;
if (io_multiplexing_out) {
SIVAL(io_buffer-4, 0, (MPLEX_BASE<<24) + io_buffer_count);
writefd_unbuffered(fd, io_buffer-4, io_buffer_count+4);
} else {
writefd_unbuffered(fd, io_buffer, io_buffer_count);
}
io_buffer_count = 0;
}
if (ret == -1 && !(errno == EWOULDBLOCK || errno == EAGAIN))
return -1;
void io_end_buffering(int fd)
{
io_flush();
if (!io_multiplexing_out) {
free(io_buffer-4);
io_buffer = NULL;
}
}
if (ret == -1 && got_select) {
/* hmmm, we got a write select on the fd and then failed to write.
Why doesn't that mean that the fd is dead? It doesn't on some
systems it seems (eg. IRIX) */
u_sleep(1000);
#if 0
fprintf(FERROR,"write exception\n");
exit_cleanup(1);
#endif
}
static void writefd(int fd,char *buf,int len)
{
if (!io_buffer) {
writefd_unbuffered(fd, buf, len);
return;
}
got_select = 0;
if (ret == -1) {
read_check(buffer_f_in);
fd_count = fd+1;
FD_ZERO(&w_fds);
FD_ZERO(&r_fds);
FD_SET(fd,&w_fds);
if (buffer_f_in != -1) {
FD_SET(buffer_f_in,&r_fds);
if (buffer_f_in > fd)
fd_count = buffer_f_in+1;
}
tv.tv_sec = BLOCKING_TIMEOUT;
tv.tv_usec = 0;
count = select(fd_count,buffer_f_in == -1? NULL: &r_fds,
&w_fds,NULL,&tv);
if (count == -1 && errno != EINTR) {
if (verbose > 1)
fprintf(FERROR,"select error: %s\n", strerror(errno));
exit_cleanup(1);
}
if (count == 0) {
check_timeout();
continue;
}
if (FD_ISSET(fd, &w_fds)) {
got_select = 1;
}
} else {
total += ret;
}
}
if (io_timeout)
last_io = time(NULL);
return total;
while (len) {
int n = MIN(len, IO_BUFFER_SIZE-io_buffer_count);
if (n > 0) {
memcpy(io_buffer+io_buffer_count, buf, n);
buf += n;
len -= n;
io_buffer_count += n;
}
if (io_buffer_count == IO_BUFFER_SIZE) io_flush();
}
}
void write_int(int f,int x)
void write_int(int f,int32 x)
{
int ret;
char b[4];
SIVAL(b,0,x);
if ((ret=writefd(f,b,4)) != 4) {
fprintf(FERROR,"write_int failed : %s\n",
ret==-1?strerror(errno):"EOF");
exit_cleanup(1);
}
total_written += 4;
char b[4];
SIVAL(b,0,x);
writefd(f,b,4);
}
void write_longint(int f, int64 x)
{
extern int remote_version;
char b[8];
int ret;
if (remote_version < 16 || x <= 0x7FFFFFFF) {
write_int(f, (int)x);
@@ -404,33 +467,107 @@ void write_longint(int f, int64 x)
SIVAL(b,0,(x&0xFFFFFFFF));
SIVAL(b,4,((x>>32)&0xFFFFFFFF));
if ((ret=writefd(f,b,8)) != 8) {
fprintf(FERROR,"write_longint failed : %s\n",
ret==-1?strerror(errno):"EOF");
exit_cleanup(1);
}
total_written += 8;
writefd(f,b,8);
}
void write_buf(int f,char *buf,int len)
{
int ret;
if ((ret=writefd(f,buf,len)) != len) {
fprintf(FERROR,"write_buf failed : %s\n",
ret==-1?strerror(errno):"EOF");
exit_cleanup(1);
}
total_written += len;
writefd(f,buf,len);
}
/* write a string to the connection */
void write_sbuf(int f,char *buf)
{
write_buf(f, buf, strlen(buf));
}
void write_byte(int f,unsigned char c)
{
write_buf(f,(char *)&c,1);
write_buf(f,(char *)&c,1);
}
void write_flush(int f)
int read_line(int f, char *buf, int maxlen)
{
eof_error = 0;
while (maxlen) {
buf[0] = 0;
read_buf(f, buf, 1);
if (buf[0] == 0) return 0;
if (buf[0] == '\n') {
buf[0] = 0;
break;
}
if (buf[0] != '\r') {
buf++;
maxlen--;
}
}
if (maxlen == 0) {
*buf = 0;
return 0;
}
eof_error = 1;
return 1;
}
void io_printf(int fd, const char *format, ...)
{
va_list ap;
char buf[1024];
int len;
va_start(ap, format);
len = vslprintf(buf, sizeof(buf)-1, format, ap);
va_end(ap);
if (len < 0) exit_cleanup(1);
write_sbuf(fd, buf);
}
/* setup for multiplexing an error stream with the data stream */
void io_start_multiplex_out(int fd)
{
multiplex_out_fd = fd;
io_flush();
io_start_buffering(fd);
io_multiplexing_out = 1;
}
/* setup for multiplexing an error stream with the data stream */
void io_start_multiplex_in(int fd)
{
multiplex_in_fd = fd;
io_flush();
if (read_buffer_len) {
fprintf(stderr,"ERROR: data in read buffer at mplx start\n");
exit_cleanup(1);
}
io_multiplexing_in = 1;
}
/* write an message to the error stream */
int io_multiplex_write(int f, char *buf, int len)
{
if (!io_multiplexing_out) return 0;
io_flush();
SIVAL(io_buffer-4, 0, ((MPLEX_BASE + f)<<24) + len);
memcpy(io_buffer, buf, len);
writefd_unbuffered(multiplex_out_fd, io_buffer-4, len+4);
return 1;
}
void io_close_input(int fd)
{
buffer_f_in = -1;
}

View File

@@ -50,3 +50,29 @@ pid_t waitpid(pid_t pid, int *statptr, int options)
}
#endif
#ifndef HAVE_MEMMOVE
void *memmove(void *dest, const void *src, size_t n)
{
memcpy(dest, src, n);
return dest;
}
#endif
#ifndef HAVE_STRPBRK
/* Find the first ocurrence in S of any character in ACCEPT.
derived from glibc
*/
char *strpbrk(const char *s, const char *accept)
{
while (*s != '\0') {
const char *a = accept;
while (*a != '\0') {
if (*a++ == *s) return (char *)s;
}
++s;
}
return NULL;
}
#endif

4601
lib/zlib.c
View File

File diff suppressed because it is too large Load Diff

View File

@@ -1,632 +0,0 @@
/* $Id$ */
/*
* This file is derived from zlib.h and zconf.h from the zlib-0.95
* distribution by Jean-loup Gailly and Mark Adler, with some additions
* by Paul Mackerras to aid in implementing Deflate compression and
* decompression for PPP packets.
*/
/* zlib.h -- interface of the 'zlib' general purpose compression library
version 0.95, Aug 16th, 1995.
Copyright (C) 1995 Jean-loup Gailly and Mark Adler
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
Jean-loup Gailly Mark Adler
gzip@prep.ai.mit.edu madler@alumni.caltech.edu
*/
#ifndef _ZLIB_H
#define _ZLIB_H
/* #include "zconf.h" */ /* included directly here */
/* zconf.h -- configuration of the zlib compression library
* Copyright (C) 1995 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* From: zconf.h,v 1.12 1995/05/03 17:27:12 jloup Exp */
/*
The library does not install any signal handler. It is recommended to
add at least a handler for SIGSEGV when decompressing; the library checks
the consistency of the input data whenever possible but may go nuts
for some forms of corrupted input.
*/
/*
* Compile with -DMAXSEG_64K if the alloc function cannot allocate more
* than 64k bytes at a time (needed on systems with 16-bit int).
* Compile with -DUNALIGNED_OK if it is OK to access shorts or ints
* at addresses which are not a multiple of their size.
* Under DOS, -DFAR=far or -DFAR=__far may be needed.
*/
#ifndef STDC
# if defined(MSDOS) || defined(__STDC__) || defined(__cplusplus)
# define STDC
# endif
#endif
#ifdef __MWERKS__ /* Metrowerks CodeWarrior declares fileno() in unix.h */
# include <unix.h>
#endif
/* Maximum value for memLevel in deflateInit2 */
#ifndef MAX_MEM_LEVEL
# ifdef MAXSEG_64K
# define MAX_MEM_LEVEL 8
# else
# define MAX_MEM_LEVEL 9
# endif
#endif
#ifndef FAR
# define FAR
#endif
/* Maximum value for windowBits in deflateInit2 and inflateInit2 */
#ifndef MAX_WBITS
# define MAX_WBITS 15 /* 32K LZ77 window */
#endif
/* The memory requirements for deflate are (in bytes):
1 << (windowBits+2) + 1 << (memLevel+9)
that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
plus a few kilobytes for small objects. For example, if you want to reduce
the default memory requirements from 256K to 128K, compile with
make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
Of course this will generally degrade compression (there's no free lunch).
The memory requirements for inflate are (in bytes) 1 << windowBits
that is, 32K for windowBits=15 (default value) plus a few kilobytes
for small objects.
*/
/* Type declarations */
#ifndef OF /* function prototypes */
# ifdef STDC
# define OF(args) args
# else
# define OF(args) ()
# endif
#endif
typedef unsigned char Byte; /* 8 bits */
typedef unsigned int uInt; /* 16 bits or more */
typedef int32 Long; /* 32 bits or more */
typedef uint32 uLong; /* 32 bits or more */
typedef Byte FAR Bytef;
typedef char FAR charf;
typedef int FAR intf;
typedef uInt FAR uIntf;
typedef uLong FAR uLongf;
#ifdef STDC
typedef void FAR *voidpf;
typedef void *voidp;
#else
typedef Byte FAR *voidpf;
typedef Byte *voidp;
#endif
/* end of original zconf.h */
#define ZLIB_VERSION "0.95P"
/*
The 'zlib' compression library provides in-memory compression and
decompression functions, including integrity checks of the uncompressed
data. This version of the library supports only one compression method
(deflation) but other algorithms may be added later and will have the same
stream interface.
For compression the application must provide the output buffer and
may optionally provide the input buffer for optimization. For decompression,
the application must provide the input buffer and may optionally provide
the output buffer for optimization.
Compression can be done in a single step if the buffers are large
enough (for example if an input file is mmap'ed), or can be done by
repeated calls of the compression function. In the latter case, the
application must provide more input and/or consume the output
(providing more output space) before each call.
*/
typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
typedef void (*free_func) OF((voidpf opaque, voidpf address, uInt nbytes));
struct internal_state;
typedef struct z_stream_s {
Bytef *next_in; /* next input byte */
uInt avail_in; /* number of bytes available at next_in */
uLong total_in; /* total nb of input bytes read so far */
Bytef *next_out; /* next output byte should be put there */
uInt avail_out; /* remaining free space at next_out */
uLong total_out; /* total nb of bytes output so far */
char *msg; /* last error message, NULL if no error */
struct internal_state FAR *state; /* not visible by applications */
alloc_func zalloc; /* used to allocate the internal state */
free_func zfree; /* used to free the internal state */
voidp opaque; /* private data object passed to zalloc and zfree */
Byte data_type; /* best guess about the data type: ascii or binary */
} z_stream;
/*
The application must update next_in and avail_in when avail_in has
dropped to zero. It must update next_out and avail_out when avail_out
has dropped to zero. The application must initialize zalloc, zfree and
opaque before calling the init function. All other fields are set by the
compression library and must not be updated by the application.
The opaque value provided by the application will be passed as the first
parameter for calls of zalloc and zfree. This can be useful for custom
memory management. The compression library attaches no meaning to the
opaque value.
zalloc must return Z_NULL if there is not enough memory for the object.
On 16-bit systems, the functions zalloc and zfree must be able to allocate
exactly 65536 bytes, but will not be required to allocate more than this
if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS,
pointers returned by zalloc for objects of exactly 65536 bytes *must*
have their offset normalized to zero. The default allocation function
provided by this library ensures this (see zutil.c). To reduce memory
requirements and avoid any allocation of 64K objects, at the expense of
compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h).
The fields total_in and total_out can be used for statistics or
progress reports. After compression, total_in holds the total size of
the uncompressed data and may be saved for use in the decompressor
(particularly if the decompressor wants to decompress everything in
a single step).
*/
/* constants */
#define Z_NO_FLUSH 0
#define Z_PARTIAL_FLUSH 1
#define Z_FULL_FLUSH 2
#define Z_SYNC_FLUSH 3 /* experimental: partial_flush + byte align */
#define Z_FINISH 4
#define Z_PACKET_FLUSH 5
#define Z_INSERT_ONLY 6 /* update hash table etc., produce no output */
/* See deflate() below for the usage of these constants */
#define Z_OK 0
#define Z_STREAM_END 1
#define Z_ERRNO (-1)
#define Z_STREAM_ERROR (-2)
#define Z_DATA_ERROR (-3)
#define Z_MEM_ERROR (-4)
#define Z_BUF_ERROR (-5)
/* error codes for the compression/decompression functions */
#define Z_BEST_SPEED 1
#define Z_BEST_COMPRESSION 9
#define Z_DEFAULT_COMPRESSION (-1)
/* compression levels */
#define Z_FILTERED 1
#define Z_HUFFMAN_ONLY 2
#define Z_DEFAULT_STRATEGY 0
#define Z_BINARY 0
#define Z_ASCII 1
#define Z_UNKNOWN 2
/* Used to set the data_type field */
#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */
extern char *zlib_version;
/* The application can compare zlib_version and ZLIB_VERSION for consistency.
If the first character differs, the library code actually used is
not compatible with the zlib.h header file used by the application.
*/
/* basic functions */
extern int deflateInit OF((z_stream *strm, int level));
/*
Initializes the internal stream state for compression. The fields
zalloc, zfree and opaque must be initialized before by the caller.
If zalloc and zfree are set to Z_NULL, deflateInit updates them to
use default allocation functions.
The compression level must be Z_DEFAULT_COMPRESSION, or between 1 and 9:
1 gives best speed, 9 gives best compression. Z_DEFAULT_COMPRESSION requests
a default compromise between speed and compression (currently equivalent
to level 6).
deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not
enough memory, Z_STREAM_ERROR if level is not a valid compression level.
msg is set to null if there is no error message. deflateInit does not
perform any compression: this will be done by deflate().
*/
extern int deflate OF((z_stream *strm, int flush));
/*
Performs one or both of the following actions:
- Compress more input starting at next_in and update next_in and avail_in
accordingly. If not all input can be processed (because there is not
enough room in the output buffer), next_in and avail_in are updated and
processing will resume at this point for the next call of deflate().
- Provide more output starting at next_out and update next_out and avail_out
accordingly. This action is forced if the parameter flush is non zero.
Forcing flush frequently degrades the compression ratio, so this parameter
should be set only when necessary (in interactive applications).
Some output may be provided even if flush is not set.
Before the call of deflate(), the application should ensure that at least
one of the actions is possible, by providing more input and/or consuming
more output, and updating avail_in or avail_out accordingly; avail_out
should never be zero before the call. The application can consume the
compressed output when it wants, for example when the output buffer is full
(avail_out == 0), or after each call of deflate().
If the parameter flush is set to Z_PARTIAL_FLUSH, the current compression
block is terminated and flushed to the output buffer so that the
decompressor can get all input data available so far. For method 9, a future
variant on method 8, the current block will be flushed but not terminated.
If flush is set to Z_FULL_FLUSH, the compression block is terminated, a
special marker is output and the compression dictionary is discarded; this
is useful to allow the decompressor to synchronize if one compressed block
has been damaged (see inflateSync below). Flushing degrades compression and
so should be used only when necessary. Using Z_FULL_FLUSH too often can
seriously degrade the compression. If deflate returns with avail_out == 0,
this function must be called again with the same value of the flush
parameter and more output space (updated avail_out), until the flush is
complete (deflate returns with non-zero avail_out).
If the parameter flush is set to Z_PACKET_FLUSH, the compression
block is terminated, and a zero-length stored block is output,
omitting the length bytes (the effect of this is that the 3-bit type
code 000 for a stored block is output, and the output is then
byte-aligned). This is designed for use at the end of a PPP packet.
In addition, if the current compression block contains all the data
since the last Z_PACKET_FLUSH, it is never output as a stored block.
If the current compression block output as a static or dynamic block
would not be at least `minCompression' bytes smaller than the
original data, then nothing is output for that block. (The type
code for the zero-length stored block is still output, resulting in
a single zero byte being output for the whole packet.)
`MinCompression' is a parameter to deflateInit2, or 0 if deflateInit
is used.
If the parameter flush is set to Z_FINISH, all pending input is processed,
all pending output is flushed and deflate returns with Z_STREAM_END if there
was enough output space; if deflate returns with Z_OK, this function must be
called again with Z_FINISH and more output space (updated avail_out) but no
more input data, until it returns with Z_STREAM_END or an error. After
deflate has returned Z_STREAM_END, the only possible operations on the
stream are deflateReset or deflateEnd.
Z_FINISH can be used immediately after deflateInit if all the compression
is to be done in a single step. In this case, avail_out must be at least
0.1% larger than avail_in plus 12 bytes. If deflate does not return
Z_STREAM_END, then it must be called again as described above.
deflate() may update data_type if it can make a good guess about
the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered
binary. This field is only for information purposes and does not affect
the compression algorithm in any manner.
deflate() returns Z_OK if some progress has been made (more input
processed or more output produced), Z_STREAM_END if all input has been
consumed and all output has been produced (only when flush is set to
Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example
if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible.
*/
extern int deflateEnd OF((z_stream *strm));
/*
All dynamically allocated data structures for this stream are freed.
This function discards any unprocessed input and does not flush any
pending output.
deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the
stream state was inconsistent. In the error case, msg may be set
but then points to a static string (which must not be deallocated).
*/
extern int inflateInit OF((z_stream *strm));
/*
Initializes the internal stream state for decompression. The fields
zalloc and zfree must be initialized before by the caller. If zalloc and
zfree are set to Z_NULL, inflateInit updates them to use default allocation
functions.
inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not
enough memory. msg is set to null if there is no error message.
inflateInit does not perform any decompression: this will be done by
inflate().
*/
extern int inflate OF((z_stream *strm, int flush));
/*
Performs one or both of the following actions:
- Decompress more input starting at next_in and update next_in and avail_in
accordingly. If not all input can be processed (because there is not
enough room in the output buffer), next_in is updated and processing
will resume at this point for the next call of inflate().
- Provide more output starting at next_out and update next_out and avail_out
accordingly. inflate() always provides as much output as possible
(until there is no more input data or no more space in the output buffer).
Before the call of inflate(), the application should ensure that at least
one of the actions is possible, by providing more input and/or consuming
more output, and updating the next_* and avail_* values accordingly.
The application can consume the uncompressed output when it wants, for
example when the output buffer is full (avail_out == 0), or after each
call of inflate().
If the parameter flush is set to Z_PARTIAL_FLUSH or Z_PACKET_FLUSH,
inflate flushes as much output as possible to the output buffer. The
flushing behavior of inflate is not specified for values of the flush
parameter other than Z_PARTIAL_FLUSH, Z_PACKET_FLUSH or Z_FINISH, but the
current implementation actually flushes as much output as possible
anyway. For Z_PACKET_FLUSH, inflate checks that once all the input data
has been consumed, it is expecting to see the length field of a stored
block; if not, it returns Z_DATA_ERROR.
inflate() should normally be called until it returns Z_STREAM_END or an
error. However if all decompression is to be performed in a single step
(a single call of inflate), the parameter flush should be set to
Z_FINISH. In this case all pending input is processed and all pending
output is flushed; avail_out must be large enough to hold all the
uncompressed data. (The size of the uncompressed data may have been saved
by the compressor for this purpose.) The next operation on this stream must
be inflateEnd to deallocate the decompression state. The use of Z_FINISH
is never required, but can be used to inform inflate that a faster routine
may be used for the single inflate() call.
inflate() returns Z_OK if some progress has been made (more input
processed or more output produced), Z_STREAM_END if the end of the
compressed data has been reached and all uncompressed output has been
produced, Z_DATA_ERROR if the input data was corrupted, Z_STREAM_ERROR if
the stream structure was inconsistent (for example if next_in or next_out
was NULL), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if no
progress is possible or if there was not enough room in the output buffer
when Z_FINISH is used. In the Z_DATA_ERROR case, the application may then
call inflateSync to look for a good compression block. */
extern int inflateEnd OF((z_stream *strm));
/*
All dynamically allocated data structures for this stream are freed.
This function discards any unprocessed input and does not flush any
pending output.
inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
was inconsistent. In the error case, msg may be set but then points to a
static string (which must not be deallocated).
*/
/* advanced functions */
/*
The following functions are needed only in some special applications.
*/
extern int deflateInit2 OF((z_stream *strm,
int level,
int method,
int windowBits,
int memLevel,
int strategy));
/*
This is another version of deflateInit with more compression options. The
fields next_in, zalloc and zfree must be initialized before by the caller.
The method parameter is the compression method. It must be 8 in this
version of the library. (Method 9 will allow a 64K history buffer and
partial block flushes.)
The windowBits parameter is the base two logarithm of the window size
(the size of the history buffer). It should be in the range 8..15 for this
version of the library (the value 16 will be allowed for method 9). Larger
values of this parameter result in better compression at the expense of
memory usage. The default value is 15 if deflateInit is used instead.
The memLevel parameter specifies how much memory should be allocated
for the internal compression state. memLevel=1 uses minimum memory but
is slow and reduces compression ratio; memLevel=9 uses maximum memory
for optimal speed. The default value is 8. See zconf.h for total memory
usage as a function of windowBits and memLevel.
The strategy parameter is used to tune the compression algorithm. Use
the value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data
produced by a filter (or predictor), or Z_HUFFMAN_ONLY to force Huffman
encoding only (no string match). Filtered data consists mostly of small
values with a somewhat random distribution. In this case, the
compression algorithm is tuned to compress them better. The strategy
parameter only affects the compression ratio but not the correctness of
the compressed output even if it is not set appropriately.
The minCompression parameter specifies the minimum reduction in size
required for a compressed block to be output when Z_PACKET_FLUSH is
used (see the description of deflate above).
If next_in is not null, the library will use this buffer to hold also
some history information; the buffer must either hold the entire input
data, or have at least 1<<(windowBits+1) bytes and be writable. If next_in
is null, the library will allocate its own history buffer (and leave next_in
null). next_out need not be provided here but must be provided by the
application for the next call of deflate().
If the history buffer is provided by the application, next_in must
must never be changed by the application since the compressor maintains
information inside this buffer from call to call; the application
must provide more input only by increasing avail_in. next_in is always
reset by the library in this case.
deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was
not enough memory, Z_STREAM_ERROR if a parameter is invalid (such as
an invalid method). msg is set to null if there is no error message.
deflateInit2 does not perform any compression: this will be done by
deflate().
*/
extern int deflateCopy OF((z_stream *dest,
z_stream *source));
/*
Sets the destination stream as a complete copy of the source stream. If
the source stream is using an application-supplied history buffer, a new
buffer is allocated for the destination stream. The compressed output
buffer is always application-supplied. It's the responsibility of the
application to provide the correct values of next_out and avail_out for the
next call of deflate.
This function is useful when several compression strategies will be
tried, for example when there are several ways of pre-processing the input
data with a filter. The streams that will be discarded should then be freed
by calling deflateEnd. Note that deflateCopy duplicates the internal
compression state which can be quite large, so this strategy is slow and
can consume lots of memory.
deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
(such as zalloc being NULL). msg is left unchanged in both source and
destination.
*/
extern int deflateReset OF((z_stream *strm));
/*
This function is equivalent to deflateEnd followed by deflateInit,
but does not free and reallocate all the internal compression state.
The stream will keep the same compression level and any other attributes
that may have been set by deflateInit2.
deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
stream state was inconsistent (such as zalloc or state being NULL).
*/
extern int inflateInit2 OF((z_stream *strm,
int windowBits));
/*
This is another version of inflateInit with more compression options. The
fields next_out, zalloc and zfree must be initialized before by the caller.
The windowBits parameter is the base two logarithm of the maximum window
size (the size of the history buffer). It should be in the range 8..15 for
this version of the library (the value 16 will be allowed soon). The
default value is 15 if inflateInit is used instead. If a compressed stream
with a larger window size is given as input, inflate() will return with
the error code Z_DATA_ERROR instead of trying to allocate a larger window.
If next_out is not null, the library will use this buffer for the history
buffer; the buffer must either be large enough to hold the entire output
data, or have at least 1<<windowBits bytes. If next_out is null, the
library will allocate its own buffer (and leave next_out null). next_in
need not be provided here but must be provided by the application for the
next call of inflate().
If the history buffer is provided by the application, next_out must
never be changed by the application since the decompressor maintains
history information inside this buffer from call to call; the application
can only reset next_out to the beginning of the history buffer when
avail_out is zero and all output has been consumed.
inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was
not enough memory, Z_STREAM_ERROR if a parameter is invalid (such as
windowBits < 8). msg is set to null if there is no error message.
inflateInit2 does not perform any decompression: this will be done by
inflate().
*/
extern int inflateSync OF((z_stream *strm));
/*
Skips invalid compressed data until the special marker (see deflate()
above) can be found, or until all available input is skipped. No output
is provided.
inflateSync returns Z_OK if the special marker has been found, Z_BUF_ERROR
if no more input was provided, Z_DATA_ERROR if no marker has been found,
or Z_STREAM_ERROR if the stream structure was inconsistent. In the success
case, the application may save the current current value of total_in which
indicates where valid compressed data was found. In the error case, the
application may repeatedly call inflateSync, providing more input each time,
until success or end of the input data.
*/
extern int inflateReset OF((z_stream *strm));
/*
This function is equivalent to inflateEnd followed by inflateInit,
but does not free and reallocate all the internal decompression state.
The stream will keep attributes that may have been set by inflateInit2.
inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
stream state was inconsistent (such as zalloc or state being NULL).
*/
extern int inflateIncomp OF((z_stream *strm));
/*
This function adds the data at next_in (avail_in bytes) to the output
history without performing any output. There must be no pending output,
and the decompressor must be expecting to see the start of a block.
Calling this function is equivalent to decompressing a stored block
containing the data at next_in (except that the data is not output).
*/
/* checksum functions */
/*
This function is not related to compression but is exported
anyway because it might be useful in applications using the
compression library.
*/
extern uLong adler32 OF((uLong adler, Bytef *buf, uInt len));
/*
Update a running Adler-32 checksum with the bytes buf[0..len-1] and
return the updated checksum. If buf is NULL, this function returns
the required initial value for the checksum.
An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
much faster. Usage example:
uLong adler = adler32(0L, Z_NULL, 0);
while (read_buffer(buffer, length) != EOF) {
adler = adler32(adler, buffer, length);
}
if (adler != original_adler) error();
*/
#ifndef _Z_UTIL_H
struct internal_state {int dummy;}; /* hack for buggy compilers */
#endif
#endif /* _ZLIB_H */

719
loadparm.c Normal file
View File

@@ -0,0 +1,719 @@
/* This is based on loadparm.c from Samba, written by Andrew Tridgell
and Karl Auer */
/*
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* Load parameters.
*
* This module provides suitable callback functions for the params
* module. It builds the internal table of service details which is
* then used by the rest of the server.
*
* To add a parameter:
*
* 1) add it to the global or service structure definition
* 2) add it to the parm_table
* 3) add it to the list of available functions (eg: using FN_GLOBAL_STRING())
* 4) If it's a global then initialise it in init_globals. If a local
* (ie. service) parameter then initialise it in the sDefault structure
*
*
* Notes:
* The configuration file is processed sequentially for speed. It is NOT
* accessed randomly as happens in 'real' Windows. For this reason, there
* is a fair bit of sequence-dependent code here - ie., code which assumes
* that certain things happen before others. In particular, the code which
* happens at the boundary between sections is delicately poised, so be
* careful!
*
*/
#include "rsync.h"
#define BOOL int
#define False 0
#define True 1
#define PTR_DIFF(p1,p2) ((ptrdiff_t)(((char *)(p1)) - (char *)(p2)))
#define strequal(a,b) (strcasecmp(a,b)==0)
#define BOOLSTR(b) ((b) ? "Yes" : "No")
typedef char pstring[1024];
#define pstrcpy(a,b) strlcpy(a,b,sizeof(pstring)-1)
/* the following are used by loadparm for option lists */
typedef enum
{
P_BOOL,P_BOOLREV,P_CHAR,P_INTEGER,P_OCTAL,
P_STRING,P_GSTRING,P_ENUM,P_SEP
} parm_type;
typedef enum
{
P_LOCAL,P_GLOBAL,P_SEPARATOR,P_NONE
} parm_class;
struct enum_list {
int value;
char *name;
};
struct parm_struct
{
char *label;
parm_type type;
parm_class class;
void *ptr;
struct enum_list *enum_list;
unsigned flags;
};
static BOOL bLoaded = False;
#ifndef GLOBAL_NAME
#define GLOBAL_NAME "global"
#endif
/* some helpful bits */
#define pSERVICE(i) ServicePtrs[i]
#define iSERVICE(i) (*pSERVICE(i))
#define LP_SNUM_OK(iService) (((iService) >= 0) && ((iService) < iNumServices))
/*
* This structure describes global (ie., server-wide) parameters.
*/
typedef struct
{
char *motd_file;
char *lock_file;
int syslog_facility;
int max_connections;
char *socket_options;
} global;
static global Globals;
/*
* This structure describes a single service.
*/
typedef struct
{
char *name;
char *path;
char *comment;
BOOL read_only;
BOOL list;
char *uid;
char *gid;
char *hosts_allow;
char *hosts_deny;
char *auth_users;
char *secrets_file;
char *exclude;
char *exclude_from;
} service;
/* This is a default service used to prime a services structure */
static service sDefault =
{
NULL, /* name */
NULL, /* path */
NULL, /* comment */
True, /* read only */
True, /* list */
"nobody",/* uid */
"nobody",/* gid */
NULL, /* hosts allow */
NULL, /* hosts deny */
NULL, /* auth users */
NULL, /* secrets file */
NULL, /* exclude */
NULL, /* exclude from */
};
/* local variables */
static service **ServicePtrs = NULL;
static int iNumServices = 0;
static int iServiceIndex = 0;
static BOOL bInGlobalSection = True;
#define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
static struct enum_list enum_facilities[] = {
#ifdef LOG_AUTH
{ LOG_AUTH, "auth" },
#endif
#ifdef LOG_AUTHPRIV
{ LOG_AUTHPRIV, "authpriv" },
#endif
#ifdef LOG_CRON
{ LOG_CRON, "cron" },
#endif
#ifdef LOG_DAEMON
{ LOG_DAEMON, "daemon" },
#endif
#ifdef LOG_FTP
{ LOG_FTP, "ftp" },
#endif
#ifdef LOG_KERN
{ LOG_KERN, "kern" },
#endif
#ifdef LOG_LPR
{ LOG_LPR, "lpr" },
#endif
#ifdef LOG_MAIL
{ LOG_MAIL, "mail" },
#endif
#ifdef LOG_NEWS
{ LOG_NEWS, "news" },
#endif
#ifdef LOG_AUTH
{ LOG_AUTH, "security" },
#endif
#ifdef LOG_SYSLOG
{ LOG_SYSLOG, "syslog" },
#endif
#ifdef LOG_USER
{ LOG_USER, "user" },
#endif
#ifdef LOG_UUCP
{ LOG_UUCP, "uucp" },
#endif
#ifdef LOG_LOCAL0
{ LOG_LOCAL0, "local0" },
#endif
#ifdef LOG_LOCAL1
{ LOG_LOCAL1, "local1" },
#endif
#ifdef LOG_LOCAL2
{ LOG_LOCAL2, "local2" },
#endif
#ifdef LOG_LOCAL3
{ LOG_LOCAL3, "local3" },
#endif
#ifdef LOG_LOCAL4
{ LOG_LOCAL4, "local4" },
#endif
#ifdef LOG_LOCAL5
{ LOG_LOCAL5, "local5" },
#endif
#ifdef LOG_LOCAL6
{ LOG_LOCAL6, "local6" },
#endif
#ifdef LOG_LOCAL7
{ LOG_LOCAL7, "local7" },
#endif
{ -1, NULL }};
/* note that we do not initialise the defaults union - it is not allowed in ANSI C */
static struct parm_struct parm_table[] =
{
{"max connections", P_INTEGER, P_GLOBAL, &Globals.max_connections,NULL, 0},
{"motd file", P_STRING, P_GLOBAL, &Globals.motd_file, NULL, 0},
{"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},
{"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},
{"uid", P_STRING, P_LOCAL, &sDefault.uid, NULL, 0},
{"gid", P_STRING, P_LOCAL, &sDefault.gid, NULL, 0},
{"hosts allow", P_STRING, P_LOCAL, &sDefault.hosts_allow, NULL, 0},
{"hosts deny", P_STRING, P_LOCAL, &sDefault.hosts_deny, NULL, 0},
{"auth users", P_STRING, P_LOCAL, &sDefault.auth_users, NULL, 0},
{"secrets file", P_STRING, P_LOCAL, &sDefault.secrets_file,NULL, 0},
{"exclude", P_STRING, P_LOCAL, &sDefault.exclude, NULL, 0},
{"exclude from", P_STRING, P_LOCAL, &sDefault.exclude_from,NULL, 0},
{NULL, P_BOOL, P_NONE, NULL, NULL, 0}
};
/***************************************************************************
Initialise the global parameter structure.
***************************************************************************/
static void init_globals(void)
{
memset(&Globals, 0, sizeof(Globals));
#ifdef LOG_DAEMON
Globals.syslog_facility = LOG_DAEMON;
#endif
Globals.lock_file = "/var/run/rsyncd.lock";
}
/***************************************************************************
Initialise the sDefault parameter structure.
***************************************************************************/
static void init_locals(void)
{
}
/*
In this section all the functions that are used to access the
parameters from the rest of the program are defined
*/
#define FN_GLOBAL_STRING(fn_name,ptr) \
char *fn_name(void) {return(*(char **)(ptr) ? *(char **)(ptr) : "");}
#define FN_GLOBAL_BOOL(fn_name,ptr) \
BOOL fn_name(void) {return(*(BOOL *)(ptr));}
#define FN_GLOBAL_CHAR(fn_name,ptr) \
char fn_name(void) {return(*(char *)(ptr));}
#define FN_GLOBAL_INTEGER(fn_name,ptr) \
int fn_name(void) {return(*(int *)(ptr));}
#define FN_LOCAL_STRING(fn_name,val) \
char *fn_name(int i) {return((LP_SNUM_OK(i)&&pSERVICE(i)->val)?pSERVICE(i)->val : (sDefault.val?sDefault.val:""));}
#define FN_LOCAL_BOOL(fn_name,val) \
BOOL fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);}
#define FN_LOCAL_CHAR(fn_name,val) \
char fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);}
#define FN_LOCAL_INTEGER(fn_name,val) \
int fn_name(int i) {return(LP_SNUM_OK(i)? pSERVICE(i)->val : sDefault.val);}
FN_GLOBAL_STRING(lp_motd_file, &Globals.motd_file)
FN_GLOBAL_STRING(lp_lock_file, &Globals.lock_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)
FN_LOCAL_STRING(lp_name, name)
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_STRING(lp_uid, uid)
FN_LOCAL_STRING(lp_gid, gid)
FN_LOCAL_STRING(lp_hosts_allow, hosts_allow)
FN_LOCAL_STRING(lp_hosts_deny, hosts_deny)
FN_LOCAL_STRING(lp_auth_users, auth_users)
FN_LOCAL_STRING(lp_secrets_file, secrets_file)
FN_LOCAL_STRING(lp_exclude, exclude)
FN_LOCAL_STRING(lp_exclude_from, exclude_from)
/* local prototypes */
static int strwicmp( char *psz1, char *psz2 );
static int map_parameter( char *parmname);
static BOOL set_boolean( BOOL *pb, char *parmvalue );
static int getservicebyname(char *name, service *pserviceDest);
static void copy_service( service *pserviceDest,
service *pserviceSource);
static BOOL do_parameter(char *parmname, char *parmvalue);
static BOOL do_section(char *sectionname);
/***************************************************************************
initialise a service to the defaults
***************************************************************************/
static void init_service(service *pservice)
{
memset((char *)pservice,0,sizeof(service));
copy_service(pservice,&sDefault);
}
static void string_set(char **s, char *v)
{
if (!v) {
*s = NULL;
return;
}
*s = strdup(v);
if (!*s) exit_cleanup(1);
}
/***************************************************************************
add a new service to the services array initialising it with the given
service
***************************************************************************/
static int add_a_service(service *pservice, char *name)
{
int i;
service tservice;
int num_to_alloc = iNumServices+1;
tservice = *pservice;
/* it might already exist */
if (name)
{
i = getservicebyname(name,NULL);
if (i >= 0)
return(i);
}
i = iNumServices;
ServicePtrs = (service **)Realloc(ServicePtrs,sizeof(service *)*num_to_alloc);
if (ServicePtrs)
pSERVICE(iNumServices) = (service *)malloc(sizeof(service));
if (!ServicePtrs || !pSERVICE(iNumServices))
return(-1);
iNumServices++;
init_service(pSERVICE(i));
copy_service(pSERVICE(i),&tservice);
if (name)
string_set(&iSERVICE(i).name,name);
return(i);
}
/***************************************************************************
Do a case-insensitive, whitespace-ignoring string compare.
***************************************************************************/
static int strwicmp(char *psz1, char *psz2)
{
/* if BOTH strings are NULL, return TRUE, if ONE is NULL return */
/* appropriate value. */
if (psz1 == psz2)
return (0);
else
if (psz1 == NULL)
return (-1);
else
if (psz2 == NULL)
return (1);
/* sync the strings on first non-whitespace */
while (1)
{
while (isspace(*psz1))
psz1++;
while (isspace(*psz2))
psz2++;
if (toupper(*psz1) != toupper(*psz2) || *psz1 == '\0' || *psz2 == '\0')
break;
psz1++;
psz2++;
}
return (*psz1 - *psz2);
}
/***************************************************************************
Map a parameter's string representation to something we can use.
Returns False if the parameter string is not recognised, else TRUE.
***************************************************************************/
static int map_parameter(char *parmname)
{
int iIndex;
if (*parmname == '-')
return(-1);
for (iIndex = 0; parm_table[iIndex].label; iIndex++)
if (strwicmp(parm_table[iIndex].label, parmname) == 0)
return(iIndex);
rprintf(FERROR, "Unknown parameter encountered: \"%s\"\n", parmname);
return(-1);
}
/***************************************************************************
Set a boolean variable from the text value stored in the passed string.
Returns True in success, False if the passed string does not correctly
represent a boolean.
***************************************************************************/
static BOOL set_boolean(BOOL *pb, char *parmvalue)
{
BOOL bRetval;
bRetval = True;
if (strwicmp(parmvalue, "yes") == 0 ||
strwicmp(parmvalue, "true") == 0 ||
strwicmp(parmvalue, "1") == 0)
*pb = True;
else
if (strwicmp(parmvalue, "no") == 0 ||
strwicmp(parmvalue, "False") == 0 ||
strwicmp(parmvalue, "0") == 0)
*pb = False;
else
{
rprintf(FERROR, "Badly formed boolean in configuration file: \"%s\".\n",
parmvalue);
bRetval = False;
}
return (bRetval);
}
/***************************************************************************
Find a service by name. Otherwise works like get_service.
***************************************************************************/
static int getservicebyname(char *name, service *pserviceDest)
{
int iService;
for (iService = iNumServices - 1; iService >= 0; iService--)
if (strwicmp(iSERVICE(iService).name, name) == 0)
{
if (pserviceDest != NULL)
copy_service(pserviceDest, pSERVICE(iService));
break;
}
return (iService);
}
/***************************************************************************
Copy a service structure to another
***************************************************************************/
static void copy_service(service *pserviceDest,
service *pserviceSource)
{
int i;
for (i=0;parm_table[i].label;i++)
if (parm_table[i].ptr && parm_table[i].class == P_LOCAL) {
void *def_ptr = parm_table[i].ptr;
void *src_ptr =
((char *)pserviceSource) + PTR_DIFF(def_ptr,&sDefault);
void *dest_ptr =
((char *)pserviceDest) + PTR_DIFF(def_ptr,&sDefault);
switch (parm_table[i].type)
{
case P_BOOL:
case P_BOOLREV:
*(BOOL *)dest_ptr = *(BOOL *)src_ptr;
break;
case P_INTEGER:
case P_ENUM:
case P_OCTAL:
*(int *)dest_ptr = *(int *)src_ptr;
break;
case P_CHAR:
*(char *)dest_ptr = *(char *)src_ptr;
break;
case P_STRING:
string_set(dest_ptr,*(char **)src_ptr);
break;
default:
break;
}
}
}
/***************************************************************************
Process a parameter for a particular service number. If snum < 0
then assume we are in the globals
***************************************************************************/
static BOOL lp_do_parameter(int snum, char *parmname, char *parmvalue)
{
int parmnum, i;
void *parm_ptr=NULL; /* where we are going to store the result */
void *def_ptr=NULL;
parmnum = map_parameter(parmname);
if (parmnum < 0)
{
rprintf(FERROR, "Ignoring unknown parameter \"%s\"\n", parmname);
return(True);
}
def_ptr = parm_table[parmnum].ptr;
/* we might point at a service, the default service or a global */
if (snum < 0) {
parm_ptr = def_ptr;
} else {
if (parm_table[parmnum].class == P_GLOBAL) {
rprintf(FERROR, "Global parameter %s found in service section!\n",parmname);
return(True);
}
parm_ptr = ((char *)pSERVICE(snum)) + PTR_DIFF(def_ptr,&sDefault);
}
/* now switch on the type of variable it is */
switch (parm_table[parmnum].type)
{
case P_BOOL:
set_boolean(parm_ptr,parmvalue);
break;
case P_BOOLREV:
set_boolean(parm_ptr,parmvalue);
*(BOOL *)parm_ptr = ! *(BOOL *)parm_ptr;
break;
case P_INTEGER:
*(int *)parm_ptr = atoi(parmvalue);
break;
case P_CHAR:
*(char *)parm_ptr = *parmvalue;
break;
case P_OCTAL:
sscanf(parmvalue,"%o",(int *)parm_ptr);
break;
case P_STRING:
string_set(parm_ptr,parmvalue);
break;
case P_GSTRING:
strlcpy((char *)parm_ptr,parmvalue,sizeof(pstring)-1);
break;
case P_ENUM:
for (i=0;parm_table[parmnum].enum_list[i].name;i++) {
if (strequal(parmvalue, parm_table[parmnum].enum_list[i].name)) {
*(int *)parm_ptr = parm_table[parmnum].enum_list[i].value;
break;
}
}
if (!parm_table[parmnum].enum_list[i].name) {
if (atoi(parmvalue) > 0)
*(int *)parm_ptr = atoi(parmvalue);
}
break;
case P_SEP:
break;
}
return(True);
}
/***************************************************************************
Process a parameter.
***************************************************************************/
static BOOL do_parameter(char *parmname, char *parmvalue)
{
return lp_do_parameter(bInGlobalSection?-2:iServiceIndex, parmname, parmvalue);
}
/***************************************************************************
Process a new section (service). At this stage all sections are services.
Later we'll have special sections that permit server parameters to be set.
Returns True on success, False on failure.
***************************************************************************/
static BOOL do_section(char *sectionname)
{
BOOL bRetval;
BOOL isglobal = (strwicmp(sectionname, GLOBAL_NAME) == 0);
bRetval = False;
/* if we were in a global section then do the local inits */
if (bInGlobalSection && !isglobal)
init_locals();
/* if we've just struck a global section, note the fact. */
bInGlobalSection = isglobal;
/* check for multiple global sections */
if (bInGlobalSection)
{
return(True);
}
/* if we have a current service, tidy it up before moving on */
bRetval = True;
if (iServiceIndex >= 0)
bRetval = True;
/* if all is still well, move to the next record in the services array */
if (bRetval)
{
/* We put this here to avoid an odd message order if messages are */
/* issued by the post-processing of a previous section. */
if ((iServiceIndex=add_a_service(&sDefault,sectionname)) < 0)
{
rprintf(FERROR,"Failed to add a new service\n");
return(False);
}
}
return (bRetval);
}
/***************************************************************************
Load the services array from the services file. Return True on success,
False on failure.
***************************************************************************/
BOOL lp_load(char *pszFname, int globals_only)
{
pstring n2;
BOOL bRetval;
bRetval = False;
bInGlobalSection = True;
init_globals();
pstrcpy(n2,pszFname);
/* We get sections first, so have to start 'behind' to make up */
iServiceIndex = -1;
bRetval = pm_process(n2, globals_only?NULL:do_section, do_parameter);
bLoaded = True;
return (bRetval);
}
/***************************************************************************
return the max number of services
***************************************************************************/
int lp_numservices(void)
{
return(iNumServices);
}
/***************************************************************************
Return the number of the service with the given name, or -1 if it doesn't
exist. Note that this is a DIFFERENT ANIMAL from the internal function
getservicebyname()! This works ONLY if all services have been loaded, and
does not copy the found service.
***************************************************************************/
int lp_number(char *name)
{
int iService;
for (iService = iNumServices - 1; iService >= 0; iService--)
if (strequal(lp_name(iService), name))
break;
return (iService);
}

132
log.c Normal file
View File

@@ -0,0 +1,132 @@
/*
Copyright (C) Andrew Tridgell 1998
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
logging and utility functions
tridge, May 1998
*/
#include "rsync.h"
void log_open(void)
{
static int initialised;
int options = LOG_PID;
if (initialised) return;
initialised = 1;
#ifdef LOG_NDELAY
options |= LOG_NDELAY;
#endif
#ifdef LOG_DAEMON
openlog("rsyncd", options, lp_syslog_facility());
#else
openlog("rsyncd", options);
#endif
#ifndef LOG_NDELAY
syslog(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, ...)
{
va_list ap;
char buf[1024];
int len;
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 > sizeof(buf)-1) exit_cleanup(1);
buf[len] = 0;
if (am_daemon) {
int priority = LOG_INFO;
if (fd == FERROR) priority = LOG_WARNING;
log_open();
if (!io_multiplex_write(fd, buf, strlen(buf))) {
syslog(priority, "%s", buf);
}
depth--;
return;
}
if (fd == FERROR) {
f = stderr;
}
if (fd == FINFO) {
extern int am_server;
if (am_server)
f = stderr;
else
f = stdout;
}
if (!f) exit_cleanup(1);
if (fwrite(buf, len, 1, f) != 1) exit_cleanup(1);
depth--;
}
void rflush(int fd)
{
FILE *f = NULL;
extern int am_daemon;
if (am_daemon) {
return;
}
if (fd == FERROR) {
f = stderr;
}
if (fd == FINFO) {
extern int am_server;
if (am_server)
f = stderr;
else
f = stdout;
}
if (!f) exit_cleanup(1);
fflush(f);
}

1123
main.c
View File

File diff suppressed because it is too large Load Diff

82
match.c
View File

@@ -29,18 +29,18 @@ 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;
static int matches;
static int data_transfer;
static int64 data_transfer;
static int total_false_alarms;
static int total_tag_hits;
static int total_matches;
static int64 total_data_transfer;
extern struct stats stats;
struct target {
tag t;
@@ -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)
@@ -87,27 +87,26 @@ static void build_hash_table(struct sum_struct *s)
}
static off_t last_match;
static OFF_T last_match;
static void matched(int f,struct sum_struct *s,struct map_struct *buf,
off_t offset,int i)
OFF_T offset,int i)
{
off_t n = offset - last_match;
OFF_T n = offset - last_match;
int j;
if (verbose > 2 && i >= 0)
fprintf(FINFO,"match at %d last_match=%d j=%d len=%d n=%d\n",
rprintf(FINFO,"match at %d last_match=%d j=%d len=%d n=%d\n",
(int)offset,(int)last_match,i,(int)s->sums[i].len,(int)n);
send_token(f,i,buf,last_match,n,i==-1?0:s->sums[i].len);
send_token(f,i,buf,last_match,n,i<0?0:s->sums[i].len);
data_transfer += n;
if (n > 0)
write_flush(f);
if (i >= 0)
if (i >= 0) {
stats.matched_data += s->sums[i].len;
n += s->sums[i].len;
}
for (j=0;j<n;j+=CHUNK_SIZE) {
int n1 = MIN(CHUNK_SIZE,n-j);
@@ -123,34 +122,34 @@ static void matched(int f,struct sum_struct *s,struct map_struct *buf,
static void hash_search(int f,struct sum_struct *s,
struct map_struct *buf,off_t len)
struct map_struct *buf,OFF_T len)
{
off_t offset;
OFF_T offset;
int j,k;
int end;
char sum2[SUM_LENGTH];
uint32 s1, s2, sum;
signed char *map;
schar *map;
if (verbose > 2)
fprintf(FINFO,"hash search b=%d len=%d\n",s->n,(int)len);
rprintf(FINFO,"hash search b=%d len=%d\n",s->n,(int)len);
k = MIN(len, s->n);
map = (signed char *)map_ptr(buf,0,k);
map = (schar *)map_ptr(buf,0,k);
sum = get_checksum1((char *)map, k);
s1 = sum & 0xFFFF;
s2 = sum >> 16;
if (verbose > 3)
fprintf(FINFO, "sum=%.8x k=%d\n", sum, k);
rprintf(FINFO, "sum=%.8x k=%d\n", sum, k);
offset = 0;
end = len + 1 - s->sums[s->count-1].len;
if (verbose > 3)
fprintf(FINFO,"hash search s->n=%d len=%d count=%d\n",
rprintf(FINFO,"hash search s->n=%d len=%d count=%d\n",
s->n,(int)len,s->count);
do {
@@ -159,7 +158,7 @@ static void hash_search(int f,struct sum_struct *s,
j = tag_table[t];
if (verbose > 4)
fprintf(FINFO,"offset=%d sum=%08x\n",(int)offset,sum);
rprintf(FINFO,"offset=%d sum=%08x\n",(int)offset,sum);
if (j == NULL_TAG) {
goto null_tag;
@@ -173,12 +172,12 @@ static void hash_search(int f,struct sum_struct *s,
if (sum != s->sums[i].sum1) continue;
if (verbose > 3)
fprintf(FINFO,"potential match at %d target=%d %d sum=%08x\n",
rprintf(FINFO,"potential match at %d target=%d %d sum=%08x\n",
(int)offset,j,i,sum);
if (!done_csum2) {
int l = MIN(s->n,len-offset);
map = (signed char *)map_ptr(buf,offset,l);
map = (schar *)map_ptr(buf,offset,l);
get_checksum2((char *)map,l,sum2);
done_csum2 = 1;
}
@@ -191,7 +190,7 @@ static void hash_search(int f,struct sum_struct *s,
matched(f,s,buf,offset,i);
offset += s->sums[i].len - 1;
k = MIN((len-offset), s->n);
map = (signed char *)map_ptr(buf,offset,k);
map = (schar *)map_ptr(buf,offset,k);
sum = get_checksum1((char *)map, k);
s1 = sum & 0xFFFF;
s2 = sum >> 16;
@@ -201,7 +200,7 @@ static void hash_search(int f,struct sum_struct *s,
null_tag:
/* Trim off the first byte from the checksum */
map = (signed char *)map_ptr(buf,offset,k+1);
map = (schar *)map_ptr(buf,offset,k+1);
s1 -= map[0] + CHAR_OFFSET;
s2 -= k * (map[0]+CHAR_OFFSET);
@@ -212,7 +211,17 @@ static void hash_search(int f,struct sum_struct *s,
} else {
--k;
}
/* By matching early we avoid re-reading the
data 3 times in the case where a token
match comes a long way after last
match. The 3 reads are caused by the
running match, the checksum update and the
literal send. */
if (offset-last_match >= CHUNK_SIZE+s->n &&
(end-offset > CHUNK_SIZE)) {
matched(f,s,buf,offset - s->n, -2);
}
} while (++offset < end);
matched(f,s,buf,len,-1);
@@ -220,7 +229,7 @@ static void hash_search(int f,struct sum_struct *s,
}
void match_sums(int f,struct sum_struct *s,struct map_struct *buf,off_t len)
void match_sums(int f,struct sum_struct *s,struct map_struct *buf,OFF_T len)
{
char file_sum[MD4_SUM_LENGTH];
@@ -236,12 +245,12 @@ void match_sums(int f,struct sum_struct *s,struct map_struct *buf,off_t len)
build_hash_table(s);
if (verbose > 2)
fprintf(FINFO,"built hash table\n");
rprintf(FINFO,"built hash table\n");
hash_search(f,s,buf,len);
if (verbose > 2)
fprintf(FINFO,"done hash search\n");
rprintf(FINFO,"done hash search\n");
} else {
matched(f,s,buf,len,-1);
}
@@ -250,7 +259,7 @@ void match_sums(int f,struct sum_struct *s,struct map_struct *buf,off_t len)
if (remote_version >= 14) {
if (verbose > 2)
fprintf(FINFO,"sending file_sum\n");
rprintf(FINFO,"sending file_sum\n");
write_buf(f,file_sum,MD4_SUM_LENGTH);
}
@@ -260,13 +269,13 @@ void match_sums(int f,struct sum_struct *s,struct map_struct *buf,off_t len)
}
if (verbose > 2)
fprintf(FINFO, "false_alarms=%d tag_hits=%d matches=%d\n",
rprintf(FINFO, "false_alarms=%d tag_hits=%d matches=%d\n",
false_alarms, tag_hits, matches);
total_tag_hits += tag_hits;
total_false_alarms += false_alarms;
total_matches += matches;
total_data_transfer += data_transfer;
stats.literal_data += data_transfer;
}
void match_report(void)
@@ -274,8 +283,9 @@ void match_report(void)
if (verbose <= 1)
return;
fprintf(FINFO,
"total: matches=%d tag_hits=%d false_alarms=%d data=%ld\n",
rprintf(FINFO,
"total: matches=%d tag_hits=%d false_alarms=%d data=%.0f\n",
total_matches,total_tag_hits,
total_false_alarms,(long)total_data_transfer);
total_false_alarms,
(double)stats.literal_data);
}

4
md4.c
View File

@@ -213,7 +213,7 @@
if (count == 0 && MDp->done) return;
/* check to see if MD is already done and report error */
if (MDp->done)
{ fprintf(FERROR,"\nError: MDupdate MD already done."); return; }
{ rprintf(FERROR,"\nError: MDupdate MD already done."); return; }
/* Add count to MDp->count */
tmp = count;
p = MDp->count;
@@ -228,7 +228,7 @@
MDblock(MDp,(unsigned int *)X);
}
else if (count > 512) /* Check for count too large */
{ fprintf(FERROR,"\nError: MDupdate called with illegal count value %d."
{ rprintf(FERROR,"\nError: MDupdate called with illegal count value %d."
,count);
return;
}

View File

@@ -19,11 +19,46 @@ BEGIN {
}
}
/^FN_LOCAL_BOOL/ {
split($0,a,"[,()]")
printf "BOOL %s(int );\n", a[2]
}
/^FN_LOCAL_STRING/ {
split($0,a,"[,()]")
printf "char *%s(int );\n", a[2]
}
/^FN_LOCAL_INT/ {
split($0,a,"[,()]")
printf "int %s(int );\n", a[2]
}
/^FN_LOCAL_CHAR/ {
split($0,a,"[,()]")
printf "char %s(int );\n", a[2]
}
/^FN_GLOBAL_BOOL/ {
split($0,a,"[,()]")
printf "BOOL %s(void);\n", a[2]
}
/^FN_GLOBAL_STRING/ {
split($0,a,"[,()]")
printf "char *%s(void);\n", a[2]
}
/^FN_GLOBAL_INT/ {
split($0,a,"[,()]")
printf "int %s(void);\n", a[2]
}
/^static|^extern/ || !/^[a-zA-Z]/ || /[;]/ {
next;
}
!/^off_t|^pid_t|^unsigned|^mode_t|^DIR|^user|^int|^char|^uint|^struct|^BOOL|^void|^time/ {
!/^OFF_T|^off_t|^pid_t|^unsigned|^mode_t|^DIR|^user|^int|^char|^uint|^struct|^BOOL|^void|^time/ {
next;
}

493
options.c Normal file
View File

@@ -0,0 +1,493 @@
/*
Copyright (C) Andrew Tridgell 1998
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* options parsing code */
#include "rsync.h"
int make_backups = 0;
int whole_file = 0;
int copy_links = 0;
int preserve_links = 0;
int preserve_hard_links = 0;
int preserve_perms = 0;
int preserve_devices = 0;
int preserve_uid = 0;
int preserve_gid = 0;
int preserve_times = 0;
int update_only = 0;
int cvs_exclude = 0;
int dry_run=0;
int local_server=0;
int ignore_times=0;
int delete_mode=0;
int one_file_system=0;
int remote_version=0;
int sparse_files=0;
int do_compression=0;
int am_root=0;
int orig_umask=0;
int relative_paths=0;
int numeric_ids = 0;
int force_delete = 0;
int io_timeout = 0;
int io_error = 0;
int read_only = 0;
int module_id = -1;
int am_server = 0;
int am_sender=0;
int recurse = 0;
int am_daemon=0;
int am_client=0;
int do_stats=0;
int block_size=BLOCK_SIZE;
char *backup_suffix = BACKUP_SUFFIX;
char *tmpdir = NULL;
char *config_file = RSYNCD_CONF;
char *shell_cmd = NULL;
char *rsync_path = RSYNC_NAME;
int rsync_port = RSYNC_PORT;
int verbose = 0;
int always_checksum = 0;
void usage(int F)
{
rprintf(F,"rsync version %s Copyright Andrew Tridgell and Paul Mackerras\n\n",
VERSION);
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,"\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=PATTERN exclude file FILE\n");
rprintf(F," --exclude-from=PATTERN exclude files listed in FILE\n");
rprintf(F," --include=PATTERN don't exclude file FILE\n");
rprintf(F," --include-from=PATTERN 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," -h, --help show this help screen\n");
rprintf(F,"\n");
rprintf(F,"the backup suffix defaults to %s\n",BACKUP_SUFFIX);
rprintf(F,"the block size defaults to %d\n",BLOCK_SIZE);
rprintf(F,"\nPlease see the rsync(1) and rsyncd.conf(5) man pages for full documentation\n");
rprintf(F,"See http://samba.anu.edu.au/rsync/ for updates and bug reports\n");
}
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};
static char *short_options = "oblLWHpguDCtcahvrRIxnSe:B:T:z";
static struct option long_options[] = {
{"version", 0, 0, OPT_VERSION},
{"server", 0, 0, OPT_SERVER},
{"sender", 0, 0, OPT_SENDER},
{"delete", 0, 0, OPT_DELETE},
{"force", 0, 0, OPT_FORCE},
{"numeric-ids", 0, 0, OPT_NUMERIC_IDS},
{"exclude", 1, 0, OPT_EXCLUDE},
{"exclude-from",1, 0, OPT_EXCLUDE_FROM},
{"include", 1, 0, OPT_INCLUDE},
{"include-from",1, 0, OPT_INCLUDE_FROM},
{"rsync-path", 1, 0, OPT_RSYNC_PATH},
{"one-file-system",0, 0, 'x'},
{"ignore-times",0, 0, 'I'},
{"help", 0, 0, 'h'},
{"dry-run", 0, 0, 'n'},
{"sparse", 0, 0, 'S'},
{"cvs-exclude", 0, 0, 'C'},
{"archive", 0, 0, 'a'},
{"checksum", 0, 0, 'c'},
{"backup", 0, 0, 'b'},
{"update", 0, 0, 'u'},
{"verbose", 0, 0, 'v'},
{"recursive", 0, 0, 'r'},
{"relative", 0, 0, 'R'},
{"devices", 0, 0, 'D'},
{"perms", 0, 0, 'p'},
{"links", 0, 0, 'l'},
{"copy-links", 0, 0, 'L'},
{"whole-file", 0, 0, 'W'},
{"hard-links", 0, 0, 'H'},
{"owner", 0, 0, 'o'},
{"group", 0, 0, 'g'},
{"times", 0, 0, 't'},
{"rsh", 1, 0, 'e'},
{"suffix", 1, 0, OPT_SUFFIX},
{"block-size", 1, 0, 'B'},
{"timeout", 1, 0, OPT_TIMEOUT},
{"temp-dir", 1, 0, 'T'},
{"compress", 0, 0, 'z'},
{"daemon", 0, 0, OPT_DAEMON},
{"stats", 0, 0, OPT_STATS},
{"config", 1, 0, OPT_CONFIG},
{"port", 1, 0, OPT_PORT},
{0,0,0,0}};
void parse_arguments(int argc, char *argv[])
{
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\n",
VERSION,PROTOCOL_VERSION);
printf("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 'x':
one_file_system=1;
break;
case OPT_DELETE:
delete_mode = 1;
break;
case OPT_FORCE:
force_delete = 1;
break;
case OPT_NUMERIC_IDS:
numeric_ids = 1;
break;
case OPT_EXCLUDE:
add_exclude(optarg, 0);
break;
case OPT_INCLUDE:
add_exclude(optarg, 1);
break;
case OPT_EXCLUDE_FROM:
add_exclude_file(optarg,1, 0);
break;
case OPT_INCLUDE_FROM:
add_exclude_file(optarg,1, 1);
break;
case 'h':
usage(FINFO);
exit_cleanup(0);
case 'b':
make_backups=1;
break;
case 'n':
dry_run=1;
break;
case 'S':
sparse_files=1;
break;
case 'C':
cvs_exclude=1;
break;
case 'u':
update_only=1;
break;
case 'l':
preserve_links=1;
break;
case 'L':
copy_links=1;
break;
case 'W':
whole_file=1;
break;
case 'H':
#if SUPPORT_HARD_LINKS
preserve_hard_links=1;
#else
rprintf(FERROR,"ERROR: hard links not supported on this platform\n");
exit_cleanup(1);
#endif
break;
case 'p':
preserve_perms=1;
break;
case 'o':
preserve_uid=1;
break;
case 'g':
preserve_gid=1;
break;
case 'D':
preserve_devices=1;
break;
case 't':
preserve_times=1;
break;
case 'c':
always_checksum=1;
break;
case 'v':
verbose++;
break;
case 'a':
recurse=1;
#if SUPPORT_LINKS
preserve_links=1;
#endif
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_SENDER:
if (!am_server) {
usage(FERROR);
exit_cleanup(1);
}
am_sender = 1;
break;
case 'r':
recurse = 1;
break;
case 'R':
relative_paths = 1;
break;
case 'e':
shell_cmd = optarg;
break;
case 'B':
block_size = atoi(optarg);
break;
case OPT_TIMEOUT:
io_timeout = atoi(optarg);
break;
case 'T':
tmpdir = optarg;
break;
case 'z':
do_compression = 1;
break;
case OPT_DAEMON:
am_daemon = 1;
break;
case OPT_STATS:
do_stats = 1;
break;
case OPT_CONFIG:
config_file = optarg;
break;
case OPT_PORT:
rsync_port = atoi(optarg);
break;
default:
/* rprintf(FERROR,"bad option -%c\n",opt); */
exit_cleanup(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;
args[ac++] = "--server";
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;
if (x != 1) args[ac++] = argstr;
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 (strcmp(backup_suffix, BACKUP_SUFFIX)) {
args[ac++] = "--suffix";
args[ac++] = backup_suffix;
}
if (delete_mode)
args[ac++] = "--delete";
if (force_delete)
args[ac++] = "--force";
if (numeric_ids)
args[ac++] = "--numeric-ids";
if (tmpdir) {
args[ac++] = "--temp-dir";
args[ac++] = tmpdir;
}
*argc = ac;
}

View File

@@ -0,0 +1,79 @@
Summary: Program for efficient remote updates of files.
Name: rsync
Version: 2.0.17
Release: 1
Copyright: GPL
Group: Applications/Networking
Source: ftp://samba.anu.edu.au/pub/rsync/rsync-2.0.17.tar.gz
URL: http://samba.anu.edu.au/rsync/
Packager: Andrew Tridgell <tridge@samba.anu.edu.au>
BuildRoot: /tmp/rsync
%description
rsync is a replacement for rcp that has many more features.
rsync uses the "rsync algorithm" which provides a very fast method for
bringing remote files into sync. It does this by sending just the
differences in the files across the link, without requiring that both
sets of files are present at one of the ends of the link beforehand.
A technical report describing the rsync algorithm is included with
this package.
%changelog
* Mon May 18 1998 Andrew Tridgell <tridge@samba.anu.edu.au>
reworked for auto-building when I release rsync (tridge@samba.anu.edu.au)
* Sat May 16 1998 John H Terpstra <jht@aquasoft.com.au>
Upgraded to Rsync 2.0.6
-new feature anonymous rsync
* Mon Apr 6 1998 Douglas N. Arnold <dna@math.psu.edu>
Upgrade to rsync version 1.7.2.
* Sun Mar 1 1998 Douglas N. Arnold <dna@math.psu.edu>
Built 1.6.9-1 based on the 1.6.3-2 spec file of John A. Martin.
Changes from 1.6.3-2 packaging: added latex and dvips commands
to create tech_report.ps.
* Mon Aug 25 1997 John A. Martin <jam@jamux.com>
Built 1.6.3-2 after finding no rsync-1.6.3-1.src.rpm although there
was an ftp://ftp.redhat.com/pub/contrib/alpha/rsync-1.6.3-1.alpha.rpm
showing no packager nor signature but giving
"Source RPM: rsync-1.6.3-1.src.rpm".
Changes from 1.6.2-1 packaging: added '$RPM_OPT_FLAGS' to make, strip
to '%build', removed '%prefix'.
* Thu Apr 10 1997 Michael De La Rue <miked@ed.ac.uk>
rsync-1.6.2-1 packaged. (This entry by jam to credit Michael for the
previous package(s).)
%prep
%setup
%build
./configure --prefix=/usr
make CFLAGS=$RPM_OPT_FLAGS
strip rsync
%install
mkdir -p $RPM_BUILD_ROOT/usr/{bin,man/{man1,man5}}
install -m755 rsync $RPM_BUILD_ROOT/usr/bin
install -m644 rsync.1 $RPM_BUILD_ROOT/usr/man/man1
install -m644 rsyncd.conf.5 $RPM_BUILD_ROOT/usr/man/man5
%clean
rm -rf $RPM_BUILD_ROOT
%files
%attr(-,root,root) /usr/bin/rsync
%attr(-,root,root) /usr/man/man1/rsync.1
%attr(-,root,root) /usr/man/man5/rsyncd.conf.5
%attr(-,root,root) %doc tech_report.tex
%attr(-,root,root) %doc README
%attr(-,root,root) %doc COPYING

View File

@@ -0,0 +1,79 @@
Summary: Program for efficient remote updates of files.
Name: rsync
Version: PVERSION
Release: PRELEASE
Copyright: GPL
Group: Applications/Networking
Source: ftp://samba.anu.edu.au/pub/rsync/rsync-PVERSION.tar.gz
URL: http://samba.anu.edu.au/rsync/
Packager: Andrew Tridgell <tridge@samba.anu.edu.au>
BuildRoot: /tmp/rsync
%description
rsync is a replacement for rcp that has many more features.
rsync uses the "rsync algorithm" which provides a very fast method for
bringing remote files into sync. It does this by sending just the
differences in the files across the link, without requiring that both
sets of files are present at one of the ends of the link beforehand.
A technical report describing the rsync algorithm is included with
this package.
%changelog
* Mon May 18 1998 Andrew Tridgell <tridge@samba.anu.edu.au>
reworked for auto-building when I release rsync (tridge@samba.anu.edu.au)
* Sat May 16 1998 John H Terpstra <jht@aquasoft.com.au>
Upgraded to Rsync 2.0.6
-new feature anonymous rsync
* Mon Apr 6 1998 Douglas N. Arnold <dna@math.psu.edu>
Upgrade to rsync version 1.7.2.
* Sun Mar 1 1998 Douglas N. Arnold <dna@math.psu.edu>
Built 1.6.9-1 based on the 1.6.3-2 spec file of John A. Martin.
Changes from 1.6.3-2 packaging: added latex and dvips commands
to create tech_report.ps.
* Mon Aug 25 1997 John A. Martin <jam@jamux.com>
Built 1.6.3-2 after finding no rsync-1.6.3-1.src.rpm although there
was an ftp://ftp.redhat.com/pub/contrib/alpha/rsync-1.6.3-1.alpha.rpm
showing no packager nor signature but giving
"Source RPM: rsync-1.6.3-1.src.rpm".
Changes from 1.6.2-1 packaging: added '$RPM_OPT_FLAGS' to make, strip
to '%build', removed '%prefix'.
* Thu Apr 10 1997 Michael De La Rue <miked@ed.ac.uk>
rsync-1.6.2-1 packaged. (This entry by jam to credit Michael for the
previous package(s).)
%prep
%setup
%build
./configure --prefix=/usr
make CFLAGS=$RPM_OPT_FLAGS
strip rsync
%install
mkdir -p $RPM_BUILD_ROOT/usr/{bin,man/{man1,man5}}
install -m755 rsync $RPM_BUILD_ROOT/usr/bin
install -m644 rsync.1 $RPM_BUILD_ROOT/usr/man/man1
install -m644 rsyncd.conf.5 $RPM_BUILD_ROOT/usr/man/man5
%clean
rm -rf $RPM_BUILD_ROOT
%files
%attr(-,root,root) /usr/bin/rsync
%attr(-,root,root) /usr/man/man1/rsync.1
%attr(-,root,root) /usr/man/man5/rsyncd.conf.5
%attr(-,root,root) %doc tech_report.tex
%attr(-,root,root) %doc README
%attr(-,root,root) %doc COPYING

561
params.c Normal file
View File

@@ -0,0 +1,561 @@
/*
This modules is based on the params.c module from Samba, written by Karl Auer
and much modifed by Christopher Hertel.
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (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.
*
* -------------------------------------------------------------------------- **
*
* Module name: params
*
* -------------------------------------------------------------------------- **
*
* This module performs lexical analysis and initial parsing of a
* Windows-like parameter file. It recognizes and handles four token
* types: section-name, parameter-name, parameter-value, and
* end-of-file. Comments and line continuation are handled
* internally.
*
* The entry point to the module is function pm_process(). This
* function opens the source file, calls the Parse() function to parse
* the input, and then closes the file when either the EOF is reached
* or a fatal error is encountered.
*
* A sample parameter file might look like this:
*
* [section one]
* parameter one = value string
* parameter two = another value
* [section two]
* new parameter = some value or t'other
*
* The parameter file is divided into sections by section headers:
* section names enclosed in square brackets (eg. [section one]).
* Each section contains parameter lines, each of which consist of a
* parameter name and value delimited by an equal sign. Roughly, the
* syntax is:
*
* <file> :== { <section> } EOF
*
* <section> :== <section header> { <parameter line> }
*
* <section header> :== '[' NAME ']'
*
* <parameter line> :== NAME '=' VALUE '\n'
*
* Blank lines and comment lines are ignored. Comment lines are lines
* beginning with either a semicolon (';') or a pound sign ('#').
*
* All whitespace in section names and parameter names is compressed
* to single spaces. Leading and trailing whitespace is stipped from
* both names and values.
*
* Only the first equals sign in a parameter line is significant.
* Parameter values may contain equals signs, square brackets and
* semicolons. Internal whitespace is retained in parameter values,
* with the exception of the '\r' character, which is stripped for
* historic reasons. Parameter names may not start with a left square
* bracket, an equal sign, a pound sign, or a semicolon, because these
* are used to identify other tokens.
*
* -------------------------------------------------------------------------- **
*/
#include "rsync.h"
#define BOOL int
#define False 0
#define True 1
/* -------------------------------------------------------------------------- **
* Constants...
*/
#define BUFR_INC 1024
/* -------------------------------------------------------------------------- **
* Variables...
*
* bufr - pointer to a global buffer. This is probably a kludge,
* but it was the nicest kludge I could think of (for now).
* bSize - The size of the global buffer <bufr>.
*/
static char *bufr = NULL;
static int bSize = 0;
/* -------------------------------------------------------------------------- **
* Functions...
*/
static int EatWhitespace( FILE *InFile )
/* ------------------------------------------------------------------------ **
* Scan past whitespace (see ctype(3C)) and return the first non-whitespace
* character, or newline, or EOF.
*
* Input: InFile - Input source.
*
* Output: The next non-whitespace character in the input stream.
*
* Notes: Because the config files use a line-oriented grammar, we
* explicitly exclude the newline character from the list of
* whitespace characters.
* - Note that both EOF (-1) and the nul character ('\0') are
* considered end-of-file markers.
*
* ------------------------------------------------------------------------ **
*/
{
int c;
for( c = getc( InFile ); isspace( c ) && ('\n' != c); c = getc( InFile ) )
;
return( c );
} /* EatWhitespace */
static int EatComment( FILE *InFile )
/* ------------------------------------------------------------------------ **
* Scan to the end of a comment.
*
* Input: InFile - Input source.
*
* Output: The character that marks the end of the comment. Normally,
* this will be a newline, but it *might* be an EOF.
*
* Notes: Because the config files use a line-oriented grammar, we
* explicitly exclude the newline character from the list of
* whitespace characters.
* - Note that both EOF (-1) and the nul character ('\0') are
* considered end-of-file markers.
*
* ------------------------------------------------------------------------ **
*/
{
int c;
for( c = getc( InFile ); ('\n'!=c) && (EOF!=c) && (c>0); c = getc( InFile ) )
;
return( c );
} /* EatComment */
static int Continuation( char *line, int pos )
/* ------------------------------------------------------------------------ **
* Scan backards within a string to discover if the last non-whitespace
* character is a line-continuation character ('\\').
*
* Input: line - A pointer to a buffer containing the string to be
* scanned.
* pos - This is taken to be the offset of the end of the
* string. This position is *not* scanned.
*
* Output: The offset of the '\\' character if it was found, or -1 to
* indicate that it was not.
*
* ------------------------------------------------------------------------ **
*/
{
pos--;
while( (pos >= 0) && isspace(line[pos]) )
pos--;
return( ((pos >= 0) && ('\\' == line[pos])) ? pos : -1 );
} /* Continuation */
static BOOL Section( FILE *InFile, BOOL (*sfunc)(char *) )
/* ------------------------------------------------------------------------ **
* Scan a section name, and pass the name to function sfunc().
*
* Input: InFile - Input source.
* sfunc - Pointer to the function to be called if the section
* name is successfully read.
*
* Output: True if the section name was read and True was returned from
* <sfunc>. False if <sfunc> failed or if a lexical error was
* encountered.
*
* ------------------------------------------------------------------------ **
*/
{
int c;
int i;
int end;
char *func = "params.c:Section() -";
i = 0; /* <i> is the offset of the next free byte in bufr[] and */
end = 0; /* <end> is the current "end of string" offset. In most */
/* cases these will be the same, but if the last */
/* character written to bufr[] is a space, then <end> */
/* will be one less than <i>. */
c = EatWhitespace( InFile ); /* We've already got the '['. Scan */
/* past initial white space. */
while( (EOF != c) && (c > 0) )
{
/* Check that the buffer is big enough for the next character. */
if( i > (bSize - 2) )
{
bSize += BUFR_INC;
bufr = Realloc( bufr, bSize );
if( NULL == bufr )
{
rprintf(FERROR, "%s Memory re-allocation failure.", func);
return( False );
}
}
/* Handle a single character. */
switch( c )
{
case ']': /* Found the closing bracket. */
bufr[end] = '\0';
if( 0 == end ) /* Don't allow an empty name. */
{
rprintf(FERROR, "%s Empty section name in configuration file.\n", func );
return( False );
}
if( !sfunc( bufr ) ) /* Got a valid name. Deal with it. */
return( False );
(void)EatComment( InFile ); /* Finish off the line. */
return( True );
case '\n': /* Got newline before closing ']'. */
i = Continuation( bufr, i ); /* Check for line continuation. */
if( i < 0 )
{
bufr[end] = '\0';
rprintf(FERROR, "%s Badly formed line in configuration file: %s\n",
func, bufr );
return( False );
}
end = ( (i > 0) && (' ' == bufr[i - 1]) ) ? (i - 1) : (i);
c = getc( InFile ); /* Continue with next line. */
break;
default: /* All else are a valid name chars. */
if( isspace( c ) ) /* One space per whitespace region. */
{
bufr[end] = ' ';
i = end + 1;
c = EatWhitespace( InFile );
}
else /* All others copy verbatim. */
{
bufr[i++] = c;
end = i;
c = getc( InFile );
}
}
}
/* We arrive here if we've met the EOF before the closing bracket. */
rprintf(FERROR, "%s Unexpected EOF in the configuration file: %s\n", func, bufr );
return( False );
} /* Section */
static BOOL Parameter( FILE *InFile, BOOL (*pfunc)(char *, char *), int c )
/* ------------------------------------------------------------------------ **
* Scan a parameter name and value, and pass these two fields to pfunc().
*
* Input: InFile - The input source.
* pfunc - A pointer to the function that will be called to
* process the parameter, once it has been scanned.
* c - The first character of the parameter name, which
* would have been read by Parse(). Unlike a comment
* line or a section header, there is no lead-in
* character that can be discarded.
*
* Output: True if the parameter name and value were scanned and processed
* successfully, else False.
*
* Notes: This function is in two parts. The first loop scans the
* parameter name. Internal whitespace is compressed, and an
* equal sign (=) terminates the token. Leading and trailing
* whitespace is discarded. The second loop scans the parameter
* value. When both have been successfully identified, they are
* passed to pfunc() for processing.
*
* ------------------------------------------------------------------------ **
*/
{
int i = 0; /* Position within bufr. */
int end = 0; /* bufr[end] is current end-of-string. */
int vstart = 0; /* Starting position of the parameter value. */
char *func = "params.c:Parameter() -";
/* Read the parameter name. */
while( 0 == vstart ) /* Loop until we've found the start of the value. */
{
if( i > (bSize - 2) ) /* Ensure there's space for next char. */
{
bSize += BUFR_INC;
bufr = Realloc( bufr, bSize );
if( NULL == bufr )
{
rprintf(FERROR, "%s Memory re-allocation failure.", func) ;
return( False );
}
}
switch( c )
{
case '=': /* Equal sign marks end of param name. */
if( 0 == end ) /* Don't allow an empty name. */
{
rprintf(FERROR, "%s Invalid parameter name in config. file.\n", func );
return( False );
}
bufr[end++] = '\0'; /* Mark end of string & advance. */
i = end; /* New string starts here. */
vstart = end; /* New string is parameter value. */
bufr[i] = '\0'; /* New string is nul, for now. */
break;
case '\n': /* Find continuation char, else error. */
i = Continuation( bufr, i );
if( i < 0 )
{
bufr[end] = '\0';
rprintf(FERROR, "%s Ignoring badly formed line in configuration file: %s\n",
func, bufr );
return( True );
}
end = ( (i > 0) && (' ' == bufr[i - 1]) ) ? (i - 1) : (i);
c = getc( InFile ); /* Read past eoln. */
break;
case '\0': /* Shouldn't have EOF within param name. */
case EOF:
bufr[i] = '\0';
rprintf(FERROR, "%s Unexpected end-of-file at: %s\n", func, bufr );
return( True );
default:
if( isspace( c ) ) /* One ' ' per whitespace region. */
{
bufr[end] = ' ';
i = end + 1;
c = EatWhitespace( InFile );
}
else /* All others verbatim. */
{
bufr[i++] = c;
end = i;
c = getc( InFile );
}
}
}
/* Now parse the value. */
c = EatWhitespace( InFile ); /* Again, trim leading whitespace. */
while( (EOF !=c) && (c > 0) )
{
if( i > (bSize - 2) ) /* Make sure there's enough room. */
{
bSize += BUFR_INC;
bufr = Realloc( bufr, bSize );
if( NULL == bufr )
{
rprintf(FERROR, "%s Memory re-allocation failure.", func) ;
return( False );
}
}
switch( c )
{
case '\r': /* Explicitly remove '\r' because the older */
c = getc( InFile ); /* version called fgets_slash() which also */
break; /* removes them. */
case '\n': /* Marks end of value unless there's a '\'. */
i = Continuation( bufr, i );
if( i < 0 )
c = 0;
else
{
for( end = i; (end >= 0) && isspace(bufr[end]); end-- )
;
c = getc( InFile );
}
break;
default: /* All others verbatim. Note that spaces do */
bufr[i++] = c; /* not advance <end>. This allows trimming */
if( !isspace( c ) ) /* of whitespace at the end of the line. */
end = i;
c = getc( InFile );
break;
}
}
bufr[end] = '\0'; /* End of value. */
return( pfunc( bufr, &bufr[vstart] ) ); /* Pass name & value to pfunc(). */
} /* Parameter */
static BOOL Parse( FILE *InFile,
BOOL (*sfunc)(char *),
BOOL (*pfunc)(char *, char *) )
/* ------------------------------------------------------------------------ **
* Scan & parse the input.
*
* Input: InFile - Input source.
* sfunc - Function to be called when a section name is scanned.
* See Section().
* pfunc - Function to be called when a parameter is scanned.
* See Parameter().
*
* Output: True if the file was successfully scanned, else False.
*
* Notes: The input can be viewed in terms of 'lines'. There are four
* types of lines:
* Blank - May contain whitespace, otherwise empty.
* Comment - First non-whitespace character is a ';' or '#'.
* The remainder of the line is ignored.
* Section - First non-whitespace character is a '['.
* Parameter - The default case.
*
* ------------------------------------------------------------------------ **
*/
{
int c;
c = EatWhitespace( InFile );
while( (EOF != c) && (c > 0) )
{
switch( c )
{
case '\n': /* Blank line. */
c = EatWhitespace( InFile );
break;
case ';': /* Comment line. */
case '#':
c = EatComment( InFile );
break;
case '[': /* Section Header. */
if (!sfunc) return True;
if( !Section( InFile, sfunc ) )
return( False );
c = EatWhitespace( InFile );
break;
case '\\': /* Bogus backslash. */
c = EatWhitespace( InFile );
break;
default: /* Parameter line. */
if( !Parameter( InFile, pfunc, c ) )
return( False );
c = EatWhitespace( InFile );
break;
}
}
return( True );
} /* Parse */
static FILE *OpenConfFile( char *FileName )
/* ------------------------------------------------------------------------ **
* Open a configuration file.
*
* Input: FileName - The pathname of the config file to be opened.
*
* Output: A pointer of type (FILE *) to the opened file, or NULL if the
* file could not be opened.
*
* ------------------------------------------------------------------------ **
*/
{
FILE *OpenedFile;
char *func = "params.c:OpenConfFile() -";
if( NULL == FileName || 0 == *FileName )
{
rprintf(FERROR,"%s No configuration filename specified.\n", func);
return( NULL );
}
OpenedFile = fopen( FileName, "r" );
if( NULL == OpenedFile )
{
rprintf(FERROR,"%s Unable to open configuration file \"%s\":\n\t%s\n",
func, FileName, strerror(errno));
}
return( OpenedFile );
} /* OpenConfFile */
BOOL pm_process( char *FileName,
BOOL (*sfunc)(char *),
BOOL (*pfunc)(char *, char *) )
/* ------------------------------------------------------------------------ **
* Process the named parameter file.
*
* Input: FileName - The pathname of the parameter file to be opened.
* sfunc - A pointer to a function that will be called when
* a section name is discovered.
* pfunc - A pointer to a function that will be called when
* a parameter name and value are discovered.
*
* Output: TRUE if the file was successfully parsed, else FALSE.
*
* ------------------------------------------------------------------------ **
*/
{
int result;
FILE *InFile;
char *func = "params.c:pm_process() -";
InFile = OpenConfFile( FileName ); /* Open the config file. */
if( NULL == InFile )
return( False );
if( NULL != bufr ) /* If we already have a buffer */
result = Parse( InFile, sfunc, pfunc ); /* (recursive call), then just */
/* use it. */
else /* If we don't have a buffer */
{ /* allocate one, then parse, */
bSize = BUFR_INC; /* then free. */
bufr = (char *)malloc( bSize );
if( NULL == bufr )
{
rprintf(FERROR,"%s memory allocation failure.\n", func);
fclose(InFile);
return( False );
}
result = Parse( InFile, sfunc, pfunc );
free( bufr );
bufr = NULL;
bSize = 0;
}
fclose(InFile);
if( !result ) /* Generic failure. */
{
rprintf(FERROR,"%s Failed. Error returned from params.c:parse().\n", func);
return( False );
}
return( True ); /* Generic success. */
} /* pm_process */
/* -------------------------------------------------------------------------- */

695
rsync.c
View File

File diff suppressed because it is too large Load Diff

164
rsync.h
View File

@@ -21,6 +21,8 @@
#define RSYNC_RSH_ENV "RSYNC_RSH"
#define RSYNC_NAME "rsync"
#define RSYNCD_CONF "/etc/rsyncd.conf"
#define BACKUP_SUFFIX "~"
/* a non-zero CHAR_OFFSET makes the rolling sum stronger, but is
@@ -39,19 +41,24 @@
#define SAME_TIME (1<<7)
/* update this if you make incompatible changes */
#define PROTOCOL_VERSION 17
#define PROTOCOL_VERSION 19
#define MIN_PROTOCOL_VERSION 11
#define MAX_PROTOCOL_VERSION 30
#define RSYNC_PORT 873
#define SPARSE_WRITE_SIZE (1024)
#define WRITE_SIZE (32*1024)
#define CHUNK_SIZE (32*1024)
#define MAX_MAP_SIZE (4*1024*1024)
#define MAX_MAP_SIZE (1*1024*1024)
#define IO_BUFFER_SIZE (4092)
#define MAX_READ_BUFFER (1024*1024)
#define BLOCKING_TIMEOUT 10
#define MAX_ARGS 1000
#define FERROR stderr
#define FINFO (am_server?stderr:stdout)
#define MPLEX_BASE 7
#define FERROR 1
#define FINFO 2
#include "config.h"
@@ -66,6 +73,7 @@
#include <unistd.h>
#endif
#include <stdio.h>
#include <stddef.h>
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
@@ -83,10 +91,6 @@
#include <string.h>
#endif
#ifdef HAVE_COMPAT_H
#include <compat.h>
#endif
#ifdef HAVE_MALLOC_H
#include <malloc.h>
#endif
@@ -132,8 +136,9 @@
#endif
#include <errno.h>
#ifdef HAVE_MMAP
#if defined(HAVE_MMAP) && defined(HAVE_MUNMAP)
#include <sys/mman.h>
#define USE_MMAP 1
#endif
#ifdef HAVE_UTIME_H
@@ -163,10 +168,41 @@
#include "lib/getopt.h"
#endif
#ifdef HAVE_GLOB
#include <glob.h>
#endif
/* these are needed for the uid/gid mapping code */
#include <pwd.h>
#include <grp.h>
#include <stdarg.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <syslog.h>
#include <sys/file.h>
#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
#ifdef HAVE_COMPAT_H
#include <compat.h>
#endif
#ifndef S_IFLNK
#define S_IFLNK 0120000
#endif
@@ -175,10 +211,18 @@
#define S_ISLNK(mode) (((mode) & S_IFLNK) == S_IFLNK)
#endif
#define BOOL int
#ifndef uchar
#define uchar unsigned char
#endif
#if HAVE_UNSIGNED_CHAR
#define schar signed char
#else
#define schar char
#endif
#ifndef int32
#if (SIZEOF_INT == 4)
#define int32 int
@@ -193,10 +237,25 @@
#define uint32 unsigned int32
#endif
#ifdef HAVE_LONGLONG
#if HAVE_OFF64_T
#define OFF_T off64_t
#define STRUCT_STAT struct stat64
#else
#define OFF_T off_t
#define STRUCT_STAT struct stat
#endif
#if HAVE_OFF64_T
#define int64 off64_t
#elif (SIZEOF_LONG == 8)
#define int64 long
#elif (SIZEOF_INT == 8)
#define int64 int
#elif HAVE_LONGLONG
#define int64 long long
#else
#define int64 off_t
#define NO_INT64
#endif
#ifndef MIN
@@ -215,10 +274,14 @@
#define MAXPATHLEN 1024
#endif
#ifndef INADDR_NONE
#define INADDR_NONE 0xffffffff
#endif
struct file_struct {
unsigned flags;
time_t modtime;
off_t length;
OFF_T length;
mode_t mode;
ino_t inode;
dev_t dev;
@@ -233,13 +296,13 @@ struct file_struct {
};
struct file_list {
int count;
int malloced;
struct file_struct **files;
int count;
int malloced;
struct file_struct **files;
};
struct sum_buf {
off_t offset; /* offset in file of this chunk */
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 */
@@ -247,7 +310,7 @@ struct sum_buf {
};
struct sum_struct {
off_t flength; /* total file length */
OFF_T flength; /* total file length */
int count; /* how many chunks */
int remainder; /* flength % block_length */
int n; /* block_length */
@@ -257,9 +320,31 @@ struct sum_struct {
struct map_struct {
char *map,*p;
int fd,p_size,p_len;
off_t size, p_offset;
OFF_T size, p_offset;
};
struct exclude_struct {
char *orig;
char *pattern;
int regular_exp;
int include;
int directory;
int local;
};
struct stats {
int64 total_size;
int64 total_transferred_size;
int64 total_written;
int64 total_read;
int64 literal_data;
int64 matched_data;
int flist_size;
int num_files;
int num_transferred_files;
};
/* we need this function because of the silly way in which duplicate
entries are handled in the file lists - we can't change this
without breaking existing versions */
@@ -269,7 +354,6 @@ static inline int flist_up(struct file_list *flist, int i)
return i;
}
#include "byteorder.h"
#include "version.h"
#include "proto.h"
@@ -285,33 +369,10 @@ extern char *sys_errlist[];
# define strrchr rindex
#endif
#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 HAVE_ERRNO_DECL
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
@@ -349,6 +410,22 @@ extern int errno;
#define S_ISCHR(mode) (((mode) & (_S_IFMT)) == (_S_IFCHR))
#endif
#ifndef S_ISSOCK
#ifdef _S_IFSOCK
#define S_ISSOCK(mode) (((mode) & (_S_IFMT)) == (_S_IFSOCK))
#else
#define S_ISSOCK(mode) (0)
#endif
#endif
#ifndef S_ISFIFO
#ifdef _S_IFIFO
#define S_ISFIFO(mode) (((mode) & (_S_IFMT)) == (_S_IFIFO))
#else
#define S_ISFIFO(mode) (0)
#endif
#endif
#ifndef S_ISDIR
#define S_ISDIR(mode) (((mode) & (_S_IFMT)) == (_S_IFDIR))
#endif
@@ -357,5 +434,6 @@ extern int errno;
#define S_ISREG(mode) (((mode) & (_S_IFMT)) == (_S_IFREG))
#endif
#define IS_DEVICE(mode) (S_ISCHR(mode) || S_ISBLK(mode))
#define IS_DEVICE(mode) (S_ISCHR(mode) || S_ISBLK(mode) || S_ISSOCK(mode) || S_ISFIFO(mode))

597
rsync.yo Normal file
View File

@@ -0,0 +1,597 @@
mailto(rsync-bugs@samba.anu.edu.au)
manpage(rsync)(1)(13 May 1998)()()
manpagename(rsync)(faster, flexible replacement for rcp)
manpagesynopsis()
rsync [options] [user@]host:path path
rsync [options] path [user@]host:path
rsync [options] path path
rsync [options] [user@]host::path path
rsync [options] path [user@]host::path
manpagedescription()
rsync is a program that behaves in much the same way that rcp does,
but has many more options and uses the rsync remote-update protocol to
greatly speedup file transfers when the destination file already
exists.
The rsync remote-update protocol allows rsync to transfer just the
differences between two sets of files across the network link, using
an efficient checksum-search algorithm described in the technical
report that accompanies this package.
Some of the additional features of rsync are:
itemize(
it() support for copying links, devices, owners, groups and permissions
it() exclude and exclude-from options similar to GNU tar
it() a CVS exclude mode for ignoring the same files that CVS would ignore
it() can use any transparent remote shell, including rsh or ssh
it() does not require root privileges
it() pipelining of file transfers to minimize latency costs
it() support for anonymous or authenticated rsync servers (ideal for
mirroring)
)
manpagesection(GENERAL)
There are five different ways of using rsync. They are:
itemize(
it() for copying local files. This is invoked when neither
source nor destination path contains a : separator
it() for copying from the local machine to a remote machine using
a remote shell program as the transport (such as rsh or
ssh). This is invoked when the destination path contains a
single : separator.
it() for copying from a remote machine to the local machine
using a remote shell program. This is invoked when the local path
contains a : separator.
it() for copying from a remote rsync server to the local
machine. This is invoked when the source path contains a ::
separator.
it() for copying from the local machine to a remote rsync
server. This is invoked when the destination path contains a ::
separator.
)
Note that in all cases at least one of the source and destination
paths must be local.
manpagesection(SETUP)
See the file README for installation instructions.
Once installed you can use rsync to any machine that you can use rsh
to. rsync uses rsh for its communications, unless both the source and
destination are local.
You can also specify a alternative to rsh, by either using the -e
command line option, or by setting the RSYNC_RSH environment variable.
One common substitute is to use ssh, which offers a high degree of
security.
Note that rsync must be installed on both the source and destination
machines.
manpagesection(USAGE)
You use rsync in the same way you use rcp. You must specify a source
and a destination, one of which may be remote.
Perhaps the best way to explain the syntax is some examples:
quote(rsync *.c foo:src/)
this would transfer all files matching the pattern *.c from the
current directory to the directory src on the machine foo. If any of
the files already exist on the remote system then the rsync
remote-update protocol is used to update the file by sending only the
differences. See the tech report for details.
quote(rsync -avz foo:src/bar /data/tmp)
recursively transfer all files from the directory src/bar on the
machine foo into the /data/tmp/bar directory on the local machine. The
files are transferred in "archive" mode, which ensures that symbolic
links, devices, attributes, permissions, ownerships etc are preserved
in the transfer. Additionally compression will be used to reduce the
size of data portions of the transfer.
quote(rsync -avz foo:src/bar/ /data/tmp)
With a trailing slash on the source this behavior changes to transfer
all files from the directory src/bar on the machine foo into the
/data/tmp/. With a trailing / on a source name it means "copy the
contents of this directory". Without a trailing slash it means "copy
the directory". This difference becomes particularly important when
using the --delete option.
You can also use rsync in local-only mode, where both the source and
destination don't have a ':' in the name. In this case it behaves like
an improved copy command.
manpagesection(CONNECTING TO AN RSYNC SERVER)
It is also possible to use rsync without using rsh or ssh as the
transport. In this case you will connect to a remote rsync server
running on TCP port 873.
Using rsync in this was is the same as using it with rsh or ssh except
that:
itemize(
it() you use a double colon :: instead of a single colon to
separate the hostname from the path.
it() the remote server may print a message of the day when you
connect
it() if you specify no path name on the remote server then the
list of accessible paths on the server will be shown.
)
Some paths on the remote server may require authentication. If so then
you will receive a password prompt when you connect. You can avoid the
password prompt by setting the environment variable RSYNC_PASSWORD to
the password you want to use. This may be useful when scripting rsync.
manpagesection(RUNNING AN RSYNC SERVER)
An rsync server is configured using a config file which by default is
called /etc/rsyncd.conf. Please see the rsyncd.conf(5) man page for more
information.
manpagesection(EXAMPLES)
Here are some examples of how I use rsync.
To backup my wife's home directory, which consists of large MS word
files and mail folders I use a cron job that runs
quote(rsync -Cavz . arvidsjaur:backup)
each night over a PPP link to a duplicate directory on my machine
"arvidsjaur".
To synchronize my samba source trees I use the following Makefile
targets:
quote( get:nl()
rsync -avuzb --exclude '*~' samba:samba/ .
put:nl()
rsync -Cavuzb . samba:samba/
sync: get put)
this allows me to sync with a CVS directory at the other end of the
link. I then do cvs operations on the remote machine, which saves a
lot of time as the remote cvs protocol isn't very efficient.
I mirror a directory between my "old" and "new" ftp sites with the
command
quote(rsync -az -e ssh --delete ~ftp/pub/samba/ nimbus:"~ftp/pub/tridge/samba")
this is launched from cron every few hours.
manpageoptions()
rsync uses the GNU long options package. Many of the command line
options have two variants, one short and one long. These are shown
below separated by commas. Some options only have a long variant.
startdit()
dit(bf(-h, --help)) Print a short help page describing the options
available in rsync
dit(bf(--version)) print the rsync version number and exit
dit(bf(-v, --verbose)) This option increases the amount of information you
are given during the transfer. By default rsync works silently. A
single -v will give you information about what files are being
transferred and a brief summary at the end. Two -v flags will give you
information on what files are being skipped and slightly more
information at the end. More than two -v flags should only be used if
you are debugging rsync
dit(bf(-I, --ignore-times)) Normally rsync will skip any files that are
already the same length and have the same time-stamp. This option turns
off this behavior.
dit(bf(-c, --checksum)) This forces the sender to checksum all files using
a 128-bit MD4 checksum before transfer. The checksum is then
explicitly checked on the receiver and any files of the same name
which already exist and have the same checksum and size on the
receiver are skipped. This option can be quite slow.
dit(bf(-a, --archive)) This is equivalent to -rlptDg. It is a quick way
of saying I want recursion and want to preserve everything.
Note: if the user launching rsync is root then the -o option (preserve
uid) is also implied.
dit(bf(-r, --recursive)) This tells rsync to copy directories recursively
dit(bf(-R, --relative)) Use relative paths. This means that the full path
names specified on the command line are sent to the server rather than
just the last parts of the filenames. This is particularly useful when
you want to sent several different directories at the same time. For
example if you used the command
verb(rsync foo/bar/foo.c remote:/tmp/)
then this would create a file called foo.c in /tmp/ on the remote
machine. If instead you used
verb(rsync -R foo/bar/foo.c remote:/tmp/)
then a file called /tmp/foo/bar/foo.c would be created on the remote
machine. The full path name is preserved.
dit(bf(-b, --backup)) With this option preexisting destination files are
renamed with a ~ extension as each file is transferred. You can
control the backup suffix using the --suffix option.
dit(bf(-u, --update)) This forces rsync to skip any files for which the
destination file already exists and has a date later than the source
file.
dit(bf(-l, --links)) This tells rsync to recreate symbolic links on the
remote system to be the same as the local system. Without this
option all symbolic links are skipped.
dit(bf(-L, --copy-links)) This tells rsync to treat symbolic links just
like ordinary files.
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.
Note that rsync can only detect hard links if both parts of the link
are in the list of files being sent.
This option can be quite slow, so only use it if you need it.
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(-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.
dit(bf(-g, --group)) This option causes rsync to update the remote group
of the file to be the same as the local group.
dit(bf(-D, --devices)) This option causes rsync to transfer character and
block device information to the remote system to recreate these
devices. This option is only available to the super-user.
dit(bf(-t, --times)) This tells rsync to transfer modification times along
with the files and update them on the remote system
dit(bf(-n, --dry-run)) This tells rsync to not do any file transfers,
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.
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.
dit(bf(--delete)) This tells rsync to delete any files on the receiving
side that aren't on the sending side. This option can be dangerous if
used incorrectly!
It is a very good idea to run first using the dry run option (-n) to
see what files would be deleted to make sure important files aren't
listed.
rsync 1.6.4 changed the behavior of --delete to make it less
dangerous. rsync now only scans directories on the receiving side
that are explicitly transferred from the sending side. Only files in
these directories are deleted.
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.
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
cases where rsync tries to copy a normal file but the destination
contains a directory of the same name. Normally rsync will refuse to
do a recursive directory deletion in such cases, by using --force
the recursive deletion will be done.
Use this option with caution!
dit(bf(-B , --block_size BLOCKSIZE)) This controls the block size used in
the rsync algorithm. See the technical report for details.
dit(bf(-e, --rsh COMMAND)) This option allows you to choose an alternative
remote shell program to use for communication between the local and
remote copies of rsync. By default rsync will use rsh, but you may
like to instead use ssh because of its high security.
You can also choose the remote shell program using the RSYNC_RSH
environment variable.
dit(bf(--rsync-path PATH)) Use this to specify the path to the copy of
rsync on the remote machine. Useful when its not in your path.
dit(bf(--exclude pattern)) This option allows you to selectively exclude
certain files from the list of files to be transferred. This is most
useful in combination with a recursive transfer.
You may use as many --exclude options on the command line as you like
to build up the list of files to exclude.
See the section of exclude patterns for information on the syntax of
this option.
dit(bf(--exclude-from FILE)) This option is similar to the --exclude
option, but instead it adds all filenames listed in the file FILE to
the exclude list.
dit(bf(--include pattern)) This option tells rsync to not exclude the
specified pattern of filenames. This is useful as it allows you to
build up quite complex exclude/include rules.
See the section of exclude patterns for information on the syntax of
this option.
dit(bf(--include-from FILE)) This specifies a list of include patterns
from a file.
dit(bf(-C, --cvs-exclude)) This is a useful shorthand for excluding a
broad range of files that you often don't want to transfer between
systems. It uses the same algorithm that CVS uses to determine if
a file should be ignored.
The exclude list is initialized to:
quote(RCS SCCS CVS CVS.adm RCSLOG cvslog.* tags TAGS .make.state
.nse_depinfo *~ #* .#* ,* *.old *.bak *.BAK *.orig *.rej .del-*
*.a *.o *.obj *.so *.Z *.elc *.ln core)
then files listed in a $HOME/.cvsignore are added to the list and any
files listed in the CVSIGNORE environment variable (space delimited).
Finally in each directory any files listed in the .cvsignore file in
that directory are added to the list.
dit(bf(--suffix SUFFIX)) This option allows you to override the default
backup suffix used with the -b option. The default is a ~.
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.
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.
Note that if you use this option then you run the risk of ending up
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.
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 options instructs rsync to use DIR as a
scratch directory when creating a 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(-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
same method that gzip uses.
Note this this option typically achieves better compression ratios
that can be achieved by using a compressing remote shell, or a
compressing transport, as it takes advantage of the implicit
information sent for matching data blocks.
dit(bf(--numeric-ids)) With this option rsync will transfer numeric group
and user ids rather than using user and group names and mapping them
at both ends.
By default rsync will use the user name and group name to determine
what ownership to give files. The special uid 0 and the special group
0 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.
dit(bf(--timeout=TIMEOUT)) This option allows you to set a maximum IO
timeout in seconds. If no data is transferred for the specified time
then rsync will exit. The default is 0, which means no timeout.
dit(bf(--daemon)) This tells rsync that it is to run as a rsync
daemon. If standard input is a socket then rsync will assume that it
is being run via inetd, otherwise it will detach from the current
terminal and become a background daemon. The daemon will read the
config file (/etc/rsyncd.conf) on each connect made by a client and
respond to requests accordingly. See the rsyncd.conf(5) man page for more
details.
dit(bf(--config FILE)) This specifies an alternate config file than
the default /etc/rsyncd.conf. This is only relevant when --daemon is
specified.
dit(bf(--port PORT)) This specifies an alternate TCP port number to use
rather than the default port 873.
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. This option only works in conjunction with
the -v (verbose) option.
enddit()
manpagesection(EXCLUDE PATTERNS)
The exclude and include patterns specified to rsync allow for flexible
selection of what files to transfer and what files to skip.
rsync build a ordered list of include/exclude options as specified on
the command line. When a filename is encountered rsync then checks the
name against each exclude/include pattern in turn. The first matching
pattern is acted on. If it is an exclude pattern than that file is
skipped. If it is an include pattern then that filename is not
skipped. If no matching include/exclude pattern is found then the
filename is not skipped.
The patterns themselves can take several forms. The rules are:
itemize(
it() if the pattern starts with a / then it is matched against the
start of the filename, otherwise it is matched against the end of
the filename. Thus /foo would match a file called foo
at the base of the tree whereas foo would match any file
called foo anywhere in the tree.
it() if the pattern ends with a / then it will only match a
directory, not a file, link or device.
it() if the pattern contains a wildcard character from the set
*?[ then regular expression matching is applied using the
normal shell filename matching rules. Otherwise a simple string
match is used.
it() if the pattern contains a / (not counting a trailing /) then it
is matched against the full filename, including any leading
directory. If the pattern doesn't contain a / then it is matched
only against the final component of the filename.
it() if the pattern starts with "+ " (a plus followed by a space)
then it is always considered a include pattern, even if specified as
part of an exclude option. The "+ " part is discarded before matching.
it() if the pattern starts with "- " (a minus followed by a space)
then it is always considered 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
single exclude list that contains both include and exclude options.
Here are some examples:
itemize(
it() --exclude "*.o" would exclude all filenames matching *.o
it() --exclude "/foo" would exclude a file in the base directory called foo
it() --exclude "foo/" would exclude any directory called foo
it() --include "*/" --include "*.c" --exclude "*" would include all
directories and C source files.
)
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
manpageseealso()
rsyncd.conf(5)
manpagediagnostics()
manpagebugs()
times are transferred as unix time_t values
file permissions, devices etc are transferred as native numerical
values
see also the comments on the --delete option
Please report bugs! The rsync bug tracking system is online at
url(http://samba.anu.edu.au/rsync/)(http://samba.anu.edu.au/rsync/)
manpagesection(VERSION)
This man page is current for version 2.0 of rsync
manpagesection(CREDITS)
rsync is distributed under the GNU public license. See the file
COPYING for details.
The primary ftp site for rsync is
url(ftp://samba.anu.edu.au/pub/rsync)(ftp://samba.anu.edu.au/pub/rsync).
A WEB site is available at
url(http://samba.anu.edu.au/rsync/)(http://samba.anu.edu.au/rsync/)
We would be delighted to hear from you if you like this program.
This program uses the zlib compression library written by Jean-loup
Gailly and Mark Adler.
manpagesection(THANKS)
Thanks to Richard Brent, Brendan Mackay, Bill Waite, Stephen Rothwell
and David Bell for helpful suggestions and testing of rsync. I've
probably missed some people, my apologies if I have.
manpageauthor()
rsync was written by Andrew Tridgell and Paul Mackerras. They may be
contacted via email at tridge@samba.anu.edu.au and
Paul.Mackerras@cs.anu.edu.au

350
rsyncd.conf.yo Normal file
View File

@@ -0,0 +1,350 @@
mailto(rsync-bugs@samba.anu.edu.au)
manpage(rsyncd.conf)(5)(13 May 1998)()()
manpagename(rsyncd.conf)(configuration file for rsync server)
manpagesynopsis()
rsyncd.conf
manpagedescription()
The rsyncd.conf file is the runtime configuration file for rsync when
run with the --daemon option. When run in this way rsync becomes a
rsync server listening on TCP port 873. Connections from rsync clients
are accepted for either anonymous or authenticated rsync sessions.
The rsyncd.conf file controls authentication, access, logging and
available modules.
manpagesection(FILE FORMAT)
The file consists of modules and parameters. A module begins with the
name of the module in square brackets and continues until the next
module begins. Modules contain parameters of the form 'name = value'.
The file is line-based - that is, each newline-terminated line represents
either a comment, a module name or a parameter.
Only the first equals sign in a parameter is significant. Whitespace before
or after the first equals sign is discarded. Leading, trailing and internal
whitespace in module and parameter names is irrelevant. Leading and
trailing whitespace in a parameter value is discarded. Internal whitespace
within a parameter value is retained verbatim.
Any line beginning with a hash (#) is ignored, as are lines containing
only whitespace.
Any line ending in a \ is "continued" on the next line in the
customary UNIX fashion.
The values following the equals sign in parameters are all either a string
(no quotes needed) or a boolean, which may be given as yes/no, 0/1 or
true/false. Case is not significant in boolean values, but is preserved
in string values.
manpagesection(LAUNCHING THE RSYNC DAEMON)
The rsync daemon is launched by specifying the --daemon option to
rsync. The daemon must run with root privileges.
You can launch it either via inetd or as a standalone daemon. If run
as a daemon then just run the command "rsync --daemon" from a suitable
startup script.
When run via inetd you should add a line like this to /etc/services:
quote(rsync 873/tcp)
and a single line something like this to /etc/inetd.conf:
quote(rsync stream tcp nowait root /usr/bin/rsync rsyncd --daemon)
You will then need to send inetd a HUP signal to tell it to reread its
config file.
Note that you should not send the rsync server a HUP signal to force
it to reread the tt(/etc/rsyncd.conf). The file is re-read on each client
connection.
manpagesection(GLOBAL OPTIONS)
The first parameters in the file (before a [module] header) are the
global parameters.
You may also include any module parameters in the global part of the
config file in which case the supplied value will override the
default for that parameter.
startdit()
dit(bf(motd file)) The "motd file" option allows you to specify a
"message of the day" to display to clients on each connect. This
usually contains site information and any legal notices. The default
is no motd file.
dit(bf(max connections)) The "max connections" option allows you to
specify the maximum number of simultaneous connections you will allow
to your rsync server. Any clients connecting when the maximum has
been reached will receive a message telling them to try later.
The default is 0 which means no limit.
dit(bf(lock file)) The "lock file" option specifies the file to use to
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(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
defined on your system. Common names are auth, authpriv, cron, daemon,
ftp, kern, lpr, mail, news, security, syslog, user, uucp, local0,
local1, local2, local3, local4, local5, local6 and local7. The default
is daemon.
dit(bf(socket options)) This option can provide endless fun for people
who like to tune their systems to the utmost degree. You can set all
sorts of socket options which may make transfers faster (or
slower!). Read the man page for the setsockopt() system call for
details on some of the options you may be able to set. By default no
special socket options are set.
enddit()
manpagesection(MODULE OPTIONS)
After the global options you should define a number of modules, each
module exports a directory tree as a symbolic name. Modules are
exported by specifying a module name in square brackets [module]
followed by the options for that module.
startdit()
dit(bf(comment)) The "comment" option specifies a description string
that is displayed next to the module name when clients obtain a list
of available modules. The default is no comment.
dit(bf(path)) The "path" option specifies the directory in the servers
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).
dit(bf(read only)) The "read only" option determines whether clients
will be able to upload files or not. If "read only" is true then any
attempted uploads will fail. If "read only" is false then uploads will
be possible if file permissions on the server allow them. The default
is for all modules to be read only.
dit(bf(list)) The "list" option determines if this module should be
listed when the client asks for a listing of available modules. By
setting this to false you can create hidden modules. The default is
for modules to be listable.
dit(bf(uid)) The "uid" option specifies the user name or user id that
file transfers to and from that module should take place as. In
combination with the "gid" option this determines what file
permissions are available. The default is the user "nobody".
dit(bf(gid)) The "gid" option specifies the group name or group id that
file transfers to and from that module should take place as. This
complements the "uid" option. The default is the group "nobody".
dit(bf(exclude)) The "exclude" option allows you to specify a space
separated list of patterns to add to the exclude list. This is
equivalent to the client specifying these patterns with the --exclude
option. Note that this option is not designed with strong security in
mind, it is quite possible that a client may find a way to bypass this
exclude list. If you want to absolutely ensure that certain files
cannot be accessed then use the uid/gid options in combination with
file permissions.
dit(bf(exclude from)) The "exclude from" option specifies a filename
on the server that contains exclude patterns, one per line. This is
equivalent to the client specifying the --exclude-from option with a
equivalent file. See also the note about security for the exclude
option above.
dit(bf(auth users)) The "auth users" option specifies a comma
and space separated list of usernames that will be allowed to connect
to this module. The usernames do not need to exist on the local
system. If "auth users" is set then the client will be challenged to
supply a username and password to connect to the module. A challenge
response authentication protocol is used for this exchange. The plain
text usernames are passwords are stored in the file specified by the
"secrets file" option. The default is for all users to be able to
connect without a password (this is called "anonymous rsync").
dit(bf(secrets file)) The "secrets file" option specifies the name of
a file that contains the username:password pairs used for
authenticating this module. This file is only consulted if the "auth
users" option is specified. The file is line based and contains
username:password pairs separated by a single colon. Any line starting
with a hash (#) is considered a comment and is skipped. The passwords
can contain any characters but be warned that many operating systems
limit the length of passwords that can be typed at the client end, so
you may find that passwords longer than 8 characters don't work.
bf(You should make sure that the secrets file is not readable by anyone
other than the system administrator.) There is no default for the
"secrets file" option, you must choose a name (such as
tt(/etc/rsyncd.secrets)).
dit(bf(hosts allow)) The "hosts allow" option allows you to specify a
list of patterns that are matched against a connecting clients
hostname and IP address. If none of the patterns match then the
connection is rejected.
Each pattern can be in one of five forms:
itemize(
it() a dotted decimal IP address. In this case the incoming machines
IP address must match exactly.
it() a address/mask in the form a.b.c.d/n were n is the number of
one bits in in the netmask. All IP addresses which match the masked
IP address will be allowed in.
it() a address/mask in the form a.b.c.d/e.f.g.h where e.f.g.h is a
netmask in dotted decimal notation. All IP addresses which match the masked
IP address will be allowed in.
it() a hostname. The hostname as determined by a reverse lookup will
be matched (case insensitive) against the pattern. Only an exact
match is allowed in.
it() a hostname pattern using wildcards. These are matched using the
same rules as normal unix filename matching. If the pattern matches
then the client is allowed in.
)
You can also combine "hosts allow" with a separate "hosts deny"
option. If both options are specified then the "hosts allow" option s
checked first and a match results in the client being able to
connect. The "hosts deny" option is then checked and a match means
that the host is rejected. If the host does not match either the
"hosts allow" or the "hosts deny" patterns then it is allowed to
connect.
The default is no "hosts allow" option, which means all hosts can connect.
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.
The default is no "hosts deny" option, which means all hosts can connect.
enddit()
manpagesection(AUTHENTICATION STRENGTH)
The authentication protocol used in rsync is a 128 bit MD4 based
challenge response system. Although I believe that no one has ever
demonstrated a brute-force break of this sort of system you should
realise that this is not a "military strength" authentication system.
It should be good enough for most purposes but if you want really top
quality security then I recommend that you run rsync over ssh.
Also note that the rsync server protocol does not currently provide any
encryption of the data that is transferred over the link. Only
authentication is provided. Use ssh as the transport if you want
encryption.
Future versions of rsync may support SSL for better authentication and
encryption, but that is still being investigated.
manpagesection(EXAMPLES)
A simple rsyncd.conf file that allow anonymous rsync to a ftp area at
tt(/home/ftp) would be:
verb(
[ftp]
path = /home/ftp
comment = ftp export area
)
A more sophisticated example would be:
uid = nobody nl()
gid = nobody nl()
max connections = 4 nl()
syslog facility = local5 nl()
verb([ftp]
path = /var/ftp/pub
comment = whole ftp area (approx 6.1 GB)
[sambaftp]
path = /var/ftp/pub/samba
comment = Samba ftp area (approx 300 MB)
[rsyncftp]
path = /var/ftp/pub/rsync
comment = rsync ftp area (approx 6 MB)
[sambawww]
path = /public_html/samba
comment = Samba WWW pages (approx 240 MB)
[cvs]
path = /data/cvs
comment = CVS repository (requires authentication)
auth users = tridge, susan
secrets file = /etc/rsyncd.secrets
)
The /etc/rsyncd.secrets file would look something like this:
tridge:mypass nl()
susan:herpass
manpagefiles()
/etc/rsyncd.conf
manpageseealso()
rsync(1)
manpagediagnostics()
manpagebugs()
The rsync server does not send all types of error messages to the
client. this means a client may be mystified as to why a transfer
failed. The error will have been logged by syslog on the server.
Please report bugs! The rsync bug tracking system is online at
url(http://samba.anu.edu.au/rsync/)(http://samba.anu.edu.au/rsync/)
manpagesection(VERSION)
This man page is current for version 2.0 of rsync
manpagesection(CREDITS)
rsync is distributed under the GNU public license. See the file
COPYING for details.
The primary ftp site for rsync is
url(ftp://samba.anu.edu.au/pub/rsync)(ftp://samba.anu.edu.au/pub/rsync).
A WEB site is available at
url(http://samba.anu.edu.au/rsync/)(http://samba.anu.edu.au/rsync/)
We would be delighted to hear from you if you like this program.
This program uses the zlib compression library written by Jean-loup
Gailly and Mark Adler.
manpagesection(THANKS)
Thanks to Warren Stanley for his original idea and patch for the rsync
server. Thanks to Karsten Thygesen for his many suggestions and
documentation!
manpageauthor()
rsync was written by Andrew Tridgell and Paul Mackerras. They may be
contacted via email at tridge@samba.anu.edu.au and
Paul.Mackerras@cs.anu.edu.au

365
socket.c Normal file
View File

@@ -0,0 +1,365 @@
/*
Copyright (C) Andrew Tridgell 1998
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
socket functions used in rsync
*/
#include "rsync.h"
/* open a socket to a tcp remote host with the specified port
based on code from Warren */
int open_socket_out(char *host, int port)
{
int type = SOCK_STREAM;
struct sockaddr_in sock_out;
int res;
struct hostent *hp;
res = socket(PF_INET, type, 0);
if (res == -1) {
return -1;
}
hp = gethostbyname(host);
if (!hp) {
rprintf(FERROR,"unknown host: %s\n", host);
return -1;
}
memcpy(&sock_out.sin_addr, hp->h_addr, hp->h_length);
sock_out.sin_port = htons(port);
sock_out.sin_family = PF_INET;
if (connect(res,(struct sockaddr *)&sock_out,sizeof(sock_out))) {
close(res);
rprintf(FERROR,"failed to connect to %s - %s\n", host, strerror(errno));
return -1;
}
return res;
}
/****************************************************************************
open a socket of the specified type, port and address for incoming data
****************************************************************************/
static int open_socket_in(int type, int port)
{
struct hostent *hp;
struct sockaddr_in sock;
char host_name[200];
int res;
int one=1;
/* get my host name */
if (gethostname(host_name, sizeof(host_name)) == -1) {
rprintf(FERROR,"gethostname failed\n");
return -1;
}
/* get host info */
if ((hp = gethostbyname(host_name)) == 0) {
rprintf(FERROR,"gethostbyname: Unknown host %s\n",host_name);
return -1;
}
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;
sock.sin_addr.s_addr = INADDR_ANY;
res = socket(hp->h_addrtype, type, 0);
if (res == -1) {
rprintf(FERROR,"socket failed\n");
return -1;
}
setsockopt(res,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one));
/* now we've got a socket - we need to bind it */
if (bind(res, (struct sockaddr * ) &sock,sizeof(sock)) == -1) {
rprintf(FERROR,"bind failed on port %d\n", port);
close(res);
return -1;
}
return res;
}
/****************************************************************************
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);
}
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);
/* ready to listen */
if (listen(s, 5) == -1) {
close(s);
exit_cleanup(1);
}
/* now accept incoming connections - forking a new process
for each incoming connection */
while (1) {
fd_set fds;
int fd;
struct sockaddr addr;
int in_addrlen = sizeof(addr);
FD_ZERO(&fds);
FD_SET(s, &fds);
if (select(s+1, &fds, NULL, NULL, NULL) != 1) {
continue;
}
if(!FD_ISSET(s, &fds)) continue;
fd = accept(s,&addr,&in_addrlen);
if (fd == -1) continue;
if (fork()==0) {
close(s);
_exit(fn(fd));
}
close(fd);
}
}
enum SOCK_OPT_TYPES {OPT_BOOL,OPT_INT,OPT_ON};
struct
{
char *name;
int level;
int option;
int value;
int opttype;
} socket_options[] = {
{"SO_KEEPALIVE", SOL_SOCKET, SO_KEEPALIVE, 0, OPT_BOOL},
{"SO_REUSEADDR", SOL_SOCKET, SO_REUSEADDR, 0, OPT_BOOL},
{"SO_BROADCAST", SOL_SOCKET, SO_BROADCAST, 0, OPT_BOOL},
#ifdef TCP_NODELAY
{"TCP_NODELAY", IPPROTO_TCP, TCP_NODELAY, 0, OPT_BOOL},
#endif
#ifdef IPTOS_LOWDELAY
{"IPTOS_LOWDELAY", IPPROTO_IP, IP_TOS, IPTOS_LOWDELAY, OPT_ON},
#endif
#ifdef IPTOS_THROUGHPUT
{"IPTOS_THROUGHPUT", IPPROTO_IP, IP_TOS, IPTOS_THROUGHPUT, OPT_ON},
#endif
#ifdef SO_SNDBUF
{"SO_SNDBUF", SOL_SOCKET, SO_SNDBUF, 0, OPT_INT},
#endif
#ifdef SO_RCVBUF
{"SO_RCVBUF", SOL_SOCKET, SO_RCVBUF, 0, OPT_INT},
#endif
#ifdef SO_SNDLOWAT
{"SO_SNDLOWAT", SOL_SOCKET, SO_SNDLOWAT, 0, OPT_INT},
#endif
#ifdef SO_RCVLOWAT
{"SO_RCVLOWAT", SOL_SOCKET, SO_RCVLOWAT, 0, OPT_INT},
#endif
#ifdef SO_SNDTIMEO
{"SO_SNDTIMEO", SOL_SOCKET, SO_SNDTIMEO, 0, OPT_INT},
#endif
#ifdef SO_RCVTIMEO
{"SO_RCVTIMEO", SOL_SOCKET, SO_RCVTIMEO, 0, OPT_INT},
#endif
{NULL,0,0,0,0}};
/****************************************************************************
set user socket options
****************************************************************************/
void set_socket_options(int fd, char *options)
{
char *tok;
if (!options || !*options) return;
options = strdup(options);
if (!options) out_of_memory("set_socket_options");
for (tok=strtok(options, " \t,"); tok; tok=strtok(NULL," \t,")) {
int ret=0,i;
int value = 1;
char *p;
int got_value = 0;
if ((p = strchr(tok,'='))) {
*p = 0;
value = atoi(p+1);
got_value = 1;
}
for (i=0;socket_options[i].name;i++)
if (strcmp(socket_options[i].name,tok)==0)
break;
if (!socket_options[i].name) {
rprintf(FERROR,"Unknown socket option %s\n",tok);
continue;
}
switch (socket_options[i].opttype) {
case OPT_BOOL:
case OPT_INT:
ret = setsockopt(fd,socket_options[i].level,
socket_options[i].option,(char *)&value,sizeof(int));
break;
case OPT_ON:
if (got_value)
rprintf(FERROR,"syntax error - %s does not take a value\n",tok);
{
int on = socket_options[i].value;
ret = setsockopt(fd,socket_options[i].level,
socket_options[i].option,(char *)&on,sizeof(int));
}
break;
}
if (ret != 0)
rprintf(FERROR,"Failed to set socket option %s\n",tok);
}
free(options);
}
/****************************************************************************
become a daemon, discarding the controlling terminal
****************************************************************************/
void become_daemon(void)
{
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);
}
}
#endif /* TIOCNOTTY */
#endif
close(0);
close(1);
close(2);
}
/*******************************************************************
return the IP addr of the client as a string
******************************************************************/
char *client_addr(int fd)
{
struct sockaddr sa;
struct sockaddr_in *sockin = (struct sockaddr_in *) (&sa);
int length = sizeof(sa);
static char addr_buf[100];
if (getpeername(fd, &sa, &length)) {
exit_cleanup(1);
}
strlcpy(addr_buf,(char *)inet_ntoa(sockin->sin_addr), sizeof(addr_buf)-1);
return addr_buf;
}
/*******************************************************************
return the DNS name of the client
******************************************************************/
char *client_name(int fd)
{
struct sockaddr sa;
struct sockaddr_in *sockin = (struct sockaddr_in *) (&sa);
int length = sizeof(sa);
static char name_buf[100];
struct hostent *hp;
char **p;
char *def = "UNKNOWN";
strcpy(name_buf,def);
if (getpeername(fd, &sa, &length)) {
exit_cleanup(1);
}
/* Look up the remote host name. */
if ((hp = gethostbyaddr((char *) &sockin->sin_addr,
sizeof(sockin->sin_addr),
AF_INET))) {
strlcpy(name_buf,(char *)hp->h_name,sizeof(name_buf) - 1);
}
/* do a forward lookup as well to prevent spoofing */
hp = gethostbyname(name_buf);
if (!hp) {
strcpy(name_buf,def);
rprintf(FERROR,"reverse name lookup failed\n");
} else {
for (p=hp->h_addr_list;*p;p++) {
if (memcmp(*p, &sockin->sin_addr, hp->h_length) == 0) {
break;
}
}
if (!*p) {
strcpy(name_buf,def);
rprintf(FERROR,"reverse name lookup mismatch - spoofed address?\n");
}
}
return name_buf;
}

View File

@@ -23,16 +23,21 @@
#include "rsync.h"
extern int dry_run;
extern int read_only;
#define CHECK_RO if (read_only) {errno = EROFS; return -1;}
int do_unlink(char *fname)
{
if (dry_run) return 0;
CHECK_RO
return unlink(fname);
}
int do_symlink(char *fname1, char *fname2)
{
if (dry_run) return 0;
CHECK_RO
return symlink(fname1, fname2);
}
@@ -40,6 +45,7 @@ int do_symlink(char *fname1, char *fname2)
int do_link(char *fname1, char *fname2)
{
if (dry_run) return 0;
CHECK_RO
return link(fname1, fname2);
}
#endif
@@ -47,6 +53,7 @@ int do_link(char *fname1, char *fname2)
int do_lchown(const char *path, uid_t owner, gid_t group)
{
if (dry_run) return 0;
CHECK_RO
return lchown(path, owner, group);
}
@@ -54,6 +61,7 @@ int do_lchown(const char *path, uid_t owner, gid_t group)
int do_mknod(char *pathname, mode_t mode, dev_t dev)
{
if (dry_run) return 0;
CHECK_RO
return mknod(pathname, mode, dev);
}
#endif
@@ -61,12 +69,14 @@ int do_mknod(char *pathname, mode_t mode, dev_t dev)
int do_rmdir(char *pathname)
{
if (dry_run) return 0;
CHECK_RO
return rmdir(pathname);
}
int do_open(char *pathname, int flags, mode_t mode)
{
if (dry_run) return -1;
CHECK_RO
return open(pathname, flags, mode);
}
@@ -74,6 +84,7 @@ int do_open(char *pathname, int flags, mode_t mode)
int do_chmod(const char *path, mode_t mode)
{
if (dry_run) return 0;
CHECK_RO
return chmod(path, mode);
}
#endif
@@ -81,17 +92,79 @@ int do_chmod(const char *path, mode_t mode)
int do_rename(char *fname1, char *fname2)
{
if (dry_run) return 0;
CHECK_RO
return rename(fname1, fname2);
}
int do_mkdir(char *fname, mode_t mode)
{
if (dry_run) return 0;
CHECK_RO
return mkdir(fname, mode);
}
char *do_mktemp(char *template)
{
if (dry_run) return NULL;
if (read_only) {errno = EROFS; return NULL;}
return mktemp(template);
}
int do_stat(const char *fname, STRUCT_STAT *st)
{
#if HAVE_OFF64_T
return stat64(fname, st);
#else
return stat(fname, st);
#endif
}
#if SUPPORT_LINKS
int do_lstat(const char *fname, STRUCT_STAT *st)
{
#if HAVE_OFF64_T
return lstat64(fname, st);
#else
return lstat(fname, st);
#endif
}
#endif
int do_fstat(int fd, STRUCT_STAT *st)
{
#if HAVE_OFF64_T
return fstat64(fd, st);
#else
return fstat(fd, st);
#endif
}
OFF_T do_lseek(int fd, OFF_T offset, int whence)
{
#if HAVE_OFF64_T
off64_t lseek64();
return lseek64(fd, offset, whence);
#else
return lseek(fd, offset, whence);
#endif
}
#ifdef USE_MMAP
void *do_mmap(void *start, int len, int prot, int flags, int fd, OFF_T offset)
{
#if HAVE_OFF64_T
return mmap64(start, len, prot, flags, fd, offset);
#else
return mmap(start, len, prot, flags, fd, offset);
#endif
}
#endif
char *d_name(struct dirent *di)
{
#if HAVE_BROKEN_READDIR
return (di->d_name - 2);
#else
return di->d_name;
#endif
}

152
test.sh
View File

@@ -1,54 +1,130 @@
#!/bin/sh -e
#!/bin/sh
#
# Copyright (C) 1998 Philip Hands <http://www.hands.com/~phil/>
#
# This program is distributable under the terms of the GNU GPL (see COPYING)
#
# This is a simple test script that tests a few rsync
# features to make sure I haven't broken them before a release. Thanks
# to Phil Hands for writing this
# features to make sure I haven't broken them before a release.
#
#
cat <<EOF
This set of tests is not completely portable. It is intended for developers
not for end users. You may experience failures on some platforms that
do not indicate a problem with rsync.
EOF
export PATH=.:$PATH
TMP=/tmp/rsync-test.$$
F1=README
FROM=${TMP}/from
TO=${TMP}/to
F1=text1
LOG=${TMP}/log
mkdir $TMP
mkdir $FROM
mkdir $TO
pause() {
echo ... press enter to continue
read
# set up test data
touch ${FROM}/empty
mkdir ${FROM}/emptydir
ps ax > ${FROM}/pslist
echo -n "This file has no trailing lf" > ${FROM}/nolf
ln -s nolf ${FROM}/nolf-symlink
cat /etc/inittab /etc/services /etc/resolv.conf > ${FROM}/${F1}
mkdir ${FROM}/dir
cp ${FROM}/${F1} ${FROM}/dir
checkit() {
echo -n "Test $4: $5:"
log=${LOG}.$4
failed=
echo "Running: \"$1\"" >${log}
echo "">>${log}
eval "$1 || failed=YES" >>${log} 2>&1
echo "-------------">>${log}
echo "check how the files compare with diff:">>${log}
echo "">>${log}
diff -ur $2 $3 >>${log} || failed=YES
echo "-------------">>${log}
echo "check how the directory listings compare with diff:">>${log}
echo "">>${log}
ls -la $2 > ${TMP}/ls-from
ls -la $3 > ${TMP}/ls-to
diff -u ${TMP}/ls-from ${TMP}/ls-to >>${log} || failed=YES
if [ -z "${failed}" ] ; then
echo " done."
rm $log
else
echo " FAILED."
fi
}
echo "Test 1 basic operation"
rsync -av testin/ ${TMP}/rsync
diff -ur testin/ ${TMP}/rsync
pause
checkforlogs() {
if [ -f $1 ] ; then
cat <<EOF
echo "Test 2 - one file"
rm ${TMP}/rsync/${F1}
rsync -av testin/ ${TMP}/rsync
diff -ur testin/ ${TMP}/rsync
pause
Failures have occured.
echo "Test 3 - extra data"
echo "extra line" >> ${TMP}/rsync/${F1}
rsync -av testin/ ${TMP}/rsync
diff -ur testin/ ${TMP}/rsync
pause
You can find the output of the tests in these files:
$@
echo "Test 4 - --delete"
cp testin/${F1} ${TMP}/rsync/f1
rsync --delete -av testin/ ${TMP}/rsync
diff -ur testin/ ${TMP}/rsync
pause
Please hit <RETURN>
EOF
read input
else
echo "Test 5 (uses ssh, so will fail if you don't have it) "
rm -rf ${TMP}/rsync
rsync -av -e ssh testin/ localhost:${TMP}/rsync
diff -ur testin/ ${TMP}/rsync
pause
rm -rf ${TMP}
echo ""
echo "Tests Completed Successfully :-)"
fi
}
echo "Test 6 (uses ssh, so will fail if you don't have it) "
mv ${TMP}/rsync/${F1} ${TMP}/rsync/f1
rsync --delete -av -e ssh testin/ localhost:${TMP}/rsync
diff -ur testin/ ${TMP}/rsync
pause
# Main script starts here
rm -rf ${TMP}
checkit "rsync -av ${FROM}/ ${TO}" ${FROM}/ ${TO} \
1 "basic operation"
echo Tests Completed
ln ${FROM}/pslist ${FROM}/dir
checkit "rsync -avH ${FROM}/ ${TO}" ${FROM}/ ${TO} \
2 "hard links"
rm ${TO}/${F1}
checkit "rsync -avH ${FROM}/ ${TO}" ${FROM}/ ${TO} \
3 "one file"
echo "extra line" >> ${TO}/${F1}
checkit "rsync -avH ${FROM}/ ${TO}" ${FROM}/ ${TO} \
4 "extra data"
cp ${FROM}/${F1} ${TO}/ThisShouldGo
checkit "rsync --delete -avH ${FROM}/ ${TO}" ${FROM}/ ${TO} \
5 " --delete"
LONGDIR=${FROM}/This-is-a-directory-with-a-stupidly-long-name-created-in-an-attempt-to-provoke-an-error-found-in-2.0.11-that-should-hopefully-never-appear-again-if-this-test-does-its-job/This-is-a-directory-with-a-stupidly-long-name-created-in-an-attempt-to-provoke-an-error-found-in-2.0.11-that-should-hopefully-never-appear-again-if-this-test-does-its-job/This-is-a-directory-with-a-stupidly-long-name-created-in-an-attempt-to-provoke-an-error-found-in-2.0.11-that-should-hopefully-never-appear-again-if-this-test-does-its-job
mkdir -p ${LONGDIR}
date > ${LONGDIR}/1
ls -la / > ${LONGDIR}/2
checkit "rsync --delete -avH ${FROM}/ ${TO}" ${FROM}/ ${TO} \
6 "long paths"
if type ssh >/dev/null ; then
rm -rf ${TO}
checkit "rsync -avH -e ssh ${FROM}/ localhost:${TO}" ${FROM}/ ${TO} \
7 "ssh: basic test"
mv ${TO}/${F1} ${TO}/ThisShouldGo
checkit "rsync --delete -avH -e ssh ${FROM}/ localhost:${TO}" ${FROM}/ ${TO}\
8 "ssh: renamed file"
else
echo ""
echo "**** Skipping SSH tests because ssh is not in the path ****"
echo ""
fi
checkforlogs ${LOG}.?

575
token.c
View File

@@ -18,7 +18,7 @@
*/
#include "rsync.h"
#include "lib/zlib.h"
#include "zlib/zlib.h"
extern int do_compression;
@@ -26,60 +26,49 @@ extern int do_compression;
/* non-compressing recv token */
static int simple_recv_token(int f,char **data)
{
static int residue;
static char *buf;
int n;
static int residue;
static char *buf;
int n;
if (!buf) {
buf = (char *)malloc(CHUNK_SIZE);
if (!buf) out_of_memory("simple_recv_token");
}
if (!buf) {
buf = (char *)malloc(CHUNK_SIZE);
if (!buf) out_of_memory("simple_recv_token");
}
if (residue == 0) {
int i = read_int(f);
if (i <= 0) return i;
residue = i;
}
if (residue == 0) {
int i = read_int(f);
if (i <= 0) return i;
residue = i;
}
*data = buf;
n = MIN(CHUNK_SIZE,residue);
residue -= n;
read_buf(f,buf,n);
return n;
*data = buf;
n = MIN(CHUNK_SIZE,residue);
residue -= n;
read_buf(f,buf,n);
return n;
}
/* non-compressing send token */
static void simple_send_token(int f,int token,
struct map_struct *buf,int offset,int n)
struct map_struct *buf,OFF_T offset,int n)
{
if (n > 0) {
int l = 0;
while (l < n) {
int n1 = MIN(CHUNK_SIZE,n-l);
write_int(f,n1);
write_buf(f,map_ptr(buf,offset+l,n1),n1);
l += n1;
}
}
write_int(f,-(token+1));
if (n > 0) {
int l = 0;
while (l < n) {
int n1 = MIN(CHUNK_SIZE,n-l);
write_int(f,n1);
write_buf(f,map_ptr(buf,offset+l,n1),n1);
l += n1;
}
}
/* a -2 token means to send data only and no token */
if (token != -2) {
write_int(f,-(token+1));
}
}
/* Memory allocation/freeing routines, called by zlib stuff. */
static void *
z_alloc(void *opaque, uInt items, uInt size)
{
return malloc(items * size);
}
static void
z_free(void *opaque, void *adrs, uInt nbytes)
{
free(adrs);
}
/* Flag bytes in compressed stream are encoded as follows: */
#define END_FLAG 0 /* that's all folks */
#define TOKEN_LONG 0x20 /* followed by 32-bit token number */
@@ -104,102 +93,131 @@ static char *obuf;
/* Send a deflated token */
static void
send_deflated_token(int f, int token,
struct map_struct *buf, int offset, int nb, int toklen)
struct map_struct *buf, OFF_T offset, int nb, int toklen)
{
int n, r;
static int init_done;
int n, r;
static int init_done, flush_pending;
if (last_token == -1) {
/* initialization */
if (!init_done) {
tx_strm.next_in = NULL;
tx_strm.zalloc = z_alloc;
tx_strm.zfree = z_free;
if (deflateInit2(&tx_strm, Z_DEFAULT_COMPRESSION, 8,
-15, 8, Z_DEFAULT_STRATEGY) != Z_OK) {
fprintf(FERROR, "compression init failed\n");
exit_cleanup(1);
}
if ((obuf = malloc(MAX_DATA_COUNT+2)) == NULL)
out_of_memory("send_deflated_token");
init_done = 1;
} else
deflateReset(&tx_strm);
run_start = token;
last_run_end = 0;
if (last_token == -1) {
/* initialization */
if (!init_done) {
tx_strm.next_in = NULL;
tx_strm.zalloc = NULL;
tx_strm.zfree = NULL;
if (deflateInit2(&tx_strm, Z_DEFAULT_COMPRESSION,
Z_DEFLATED, -15, 8,
Z_DEFAULT_STRATEGY) != Z_OK) {
rprintf(FERROR, "compression init failed\n");
exit_cleanup(1);
}
if ((obuf = malloc(MAX_DATA_COUNT+2)) == NULL)
out_of_memory("send_deflated_token");
init_done = 1;
} else
deflateReset(&tx_strm);
last_run_end = 0;
run_start = token;
flush_pending = 0;
} else if (nb != 0 || token != last_token + 1
|| token >= run_start + 65536) {
/* output previous run */
r = run_start - last_run_end;
n = last_token - run_start;
if (r >= 0 && r <= 63) {
write_byte(f, (n==0? TOKEN_REL: TOKENRUN_REL) + r);
} else {
write_byte(f, (n==0? TOKEN_LONG: TOKENRUN_LONG));
write_int(f, run_start);
}
if (n != 0) {
write_byte(f, n);
write_byte(f, n >> 8);
}
last_run_end = last_token;
run_start = token;
}
} else if (last_token == -2) {
run_start = token;
last_token = token;
if (nb != 0) {
/* deflate the data starting at offset */
tx_strm.avail_in = 0;
tx_strm.avail_out = 0;
do {
if (tx_strm.avail_in == 0 && nb != 0) {
/* give it some more input */
n = MIN(nb, CHUNK_SIZE);
tx_strm.next_in = (Bytef *)map_ptr(buf, offset, n);
tx_strm.avail_in = n;
nb -= n;
offset += n;
}
if (tx_strm.avail_out == 0) {
tx_strm.next_out = (Bytef *)(obuf + 2);
tx_strm.avail_out = MAX_DATA_COUNT;
}
r = deflate(&tx_strm, nb? Z_NO_FLUSH: Z_PACKET_FLUSH);
if (r != Z_OK) {
fprintf(FERROR, "deflate returned %d\n", r);
exit_cleanup(1);
}
if (nb == 0 || tx_strm.avail_out == 0) {
n = MAX_DATA_COUNT - tx_strm.avail_out;
if (n > 0) {
obuf[0] = DEFLATED_DATA + (n >> 8);
obuf[1] = n;
write_buf(f, obuf, n+2);
} else if (nb != 0 || token != last_token + 1
|| token >= run_start + 65536) {
/* output previous run */
r = run_start - last_run_end;
n = last_token - run_start;
if (r >= 0 && r <= 63) {
write_byte(f, (n==0? TOKEN_REL: TOKENRUN_REL) + r);
} else {
write_byte(f, (n==0? TOKEN_LONG: TOKENRUN_LONG));
write_int(f, run_start);
}
}
} while (nb != 0 || tx_strm.avail_out == 0);
}
if (token != -1) {
/* add the data in the current block to the compressor's
history and hash table */
tx_strm.next_in = (Bytef *)map_ptr(buf, offset, toklen);
tx_strm.avail_in = toklen;
tx_strm.next_out = NULL;
tx_strm.avail_out = 2 * toklen;
r = deflate(&tx_strm, Z_INSERT_ONLY);
if (r != Z_OK || tx_strm.avail_in != 0) {
fprintf(FERROR, "deflate on token returned %d (%d bytes left)\n",
r, tx_strm.avail_in);
exit_cleanup(1);
if (n != 0) {
write_byte(f, n);
write_byte(f, n >> 8);
}
last_run_end = last_token;
run_start = token;
}
} else {
/* end of file - clean up */
write_byte(f, END_FLAG);
}
last_token = token;
if (nb != 0 || flush_pending) {
/* deflate the data starting at offset */
int flush = Z_NO_FLUSH;
tx_strm.avail_in = 0;
tx_strm.avail_out = 0;
do {
if (tx_strm.avail_in == 0 && nb != 0) {
/* give it some more input */
n = MIN(nb, CHUNK_SIZE);
tx_strm.next_in = (Bytef *)
map_ptr(buf, offset, n);
tx_strm.avail_in = n;
nb -= n;
offset += n;
}
if (tx_strm.avail_out == 0) {
tx_strm.next_out = (Bytef *)(obuf + 2);
tx_strm.avail_out = MAX_DATA_COUNT;
if (flush != Z_NO_FLUSH) {
/*
* We left the last 4 bytes in the
* buffer, in case they are the
* last 4. Move them to the front.
*/
memcpy(tx_strm.next_out,
obuf+MAX_DATA_COUNT-2, 4);
tx_strm.next_out += 4;
tx_strm.avail_out -= 4;
}
}
if (nb == 0 && token != -2)
flush = Z_SYNC_FLUSH;
r = deflate(&tx_strm, flush);
if (r != Z_OK) {
rprintf(FERROR, "deflate returned %d\n", r);
exit_cleanup(1);
}
if (nb == 0 || tx_strm.avail_out == 0) {
n = MAX_DATA_COUNT - tx_strm.avail_out;
if (flush != Z_NO_FLUSH) {
/*
* We have to trim off the last 4
* bytes of output when flushing
* (they are just 0, 0, ff, ff).
*/
n -= 4;
}
if (n > 0) {
obuf[0] = DEFLATED_DATA + (n >> 8);
obuf[1] = n;
write_buf(f, obuf, n+2);
}
}
} while (nb != 0 || tx_strm.avail_out == 0);
flush_pending = token == -2;
}
if (token == -1) {
/* end of file - clean up */
write_byte(f, END_FLAG);
} else if (token != -2) {
/* add the data in the current block to the compressor's
history and hash table */
tx_strm.next_in = (Bytef *) map_ptr(buf, offset, toklen);
tx_strm.avail_in = toklen;
tx_strm.next_out = (Bytef *) obuf;
tx_strm.avail_out = MAX_DATA_COUNT;
r = deflate(&tx_strm, Z_INSERT_ONLY);
if (r != Z_OK || tx_strm.avail_in != 0) {
rprintf(FERROR, "deflate on token returned %d (%d bytes left)\n",
r, tx_strm.avail_in);
exit_cleanup(1);
}
}
}
@@ -219,113 +237,129 @@ static int rx_run;
static int
recv_deflated_token(int f, char **data)
{
int n, r, flag;
static int init_done;
static int saved_flag;
int n, r, flag;
static int init_done;
static int saved_flag;
for (;;) {
switch (recv_state) {
case r_init:
if (!init_done) {
rx_strm.next_out = NULL;
rx_strm.zalloc = z_alloc;
rx_strm.zfree = z_free;
if (inflateInit2(&rx_strm, -15) != Z_OK) {
fprintf(FERROR, "inflate init failed\n");
exit_cleanup(1);
}
if ((cbuf = malloc(MAX_DATA_COUNT)) == NULL
|| (dbuf = malloc(CHUNK_SIZE)) == NULL)
out_of_memory("recv_deflated_token");
init_done = 1;
} else {
inflateReset(&rx_strm);
}
recv_state = r_idle;
rx_token = 0;
break;
case r_idle:
case r_inflated:
if (saved_flag) {
flag = saved_flag & 0xff;
saved_flag = 0;
} else
flag = read_byte(f);
if ((flag & 0xC0) == DEFLATED_DATA) {
n = ((flag & 0x3f) << 8) + read_byte(f);
read_buf(f, cbuf, n);
rx_strm.next_in = (Bytef *)cbuf;
rx_strm.avail_in = n;
recv_state = r_inflating;
break;
}
if (recv_state == r_inflated) {
/* check previous inflated stuff ended correctly */
rx_strm.avail_in = 0;
rx_strm.next_out = (Bytef *)dbuf;
rx_strm.avail_out = CHUNK_SIZE;
r = inflate(&rx_strm, Z_PACKET_FLUSH);
n = CHUNK_SIZE - rx_strm.avail_out;
if (r != Z_OK) {
fprintf(FERROR, "inflate flush returned %d (%d bytes)\n",
r, n);
exit_cleanup(1);
}
if (n != 0) {
/* have to return some more data and
save the flag for later. */
saved_flag = flag + 0x10000;
if (rx_strm.avail_out != 0)
for (;;) {
switch (recv_state) {
case r_init:
if (!init_done) {
rx_strm.next_out = NULL;
rx_strm.zalloc = NULL;
rx_strm.zfree = NULL;
if (inflateInit2(&rx_strm, -15) != Z_OK) {
rprintf(FERROR, "inflate init failed\n");
exit_cleanup(1);
}
if ((cbuf = malloc(MAX_DATA_COUNT)) == NULL
|| (dbuf = malloc(CHUNK_SIZE)) == NULL)
out_of_memory("recv_deflated_token");
init_done = 1;
} else {
inflateReset(&rx_strm);
}
recv_state = r_idle;
*data = dbuf;
return n;
rx_token = 0;
break;
case r_idle:
case r_inflated:
if (saved_flag) {
flag = saved_flag & 0xff;
saved_flag = 0;
} else
flag = read_byte(f);
if ((flag & 0xC0) == DEFLATED_DATA) {
n = ((flag & 0x3f) << 8) + read_byte(f);
read_buf(f, cbuf, n);
rx_strm.next_in = (Bytef *)cbuf;
rx_strm.avail_in = n;
recv_state = r_inflating;
break;
}
if (recv_state == r_inflated) {
/* check previous inflated stuff ended correctly */
rx_strm.avail_in = 0;
rx_strm.next_out = (Bytef *)dbuf;
rx_strm.avail_out = CHUNK_SIZE;
r = inflate(&rx_strm, Z_SYNC_FLUSH);
n = CHUNK_SIZE - rx_strm.avail_out;
/*
* Z_BUF_ERROR just means no progress was
* made, i.e. the decompressor didn't have
* any pending output for us.
*/
if (r != Z_OK && r != Z_BUF_ERROR) {
rprintf(FERROR, "inflate flush returned %d (%d bytes)\n",
r, n);
exit_cleanup(1);
}
if (n != 0 && r != Z_BUF_ERROR) {
/* have to return some more data and
save the flag for later. */
saved_flag = flag + 0x10000;
*data = dbuf;
return n;
}
/*
* At this point the decompressor should
* be expecting to see the 0, 0, ff, ff bytes.
*/
if (!inflateSyncPoint(&rx_strm)) {
rprintf(FERROR, "decompressor lost sync!\n");
exit_cleanup(1);
}
rx_strm.avail_in = 4;
rx_strm.next_in = (Bytef *)cbuf;
cbuf[0] = cbuf[1] = 0;
cbuf[2] = cbuf[3] = 0xff;
inflate(&rx_strm, Z_SYNC_FLUSH);
recv_state = r_idle;
}
if (flag == END_FLAG) {
/* that's all folks */
recv_state = r_init;
return 0;
}
/* here we have a token of some kind */
if (flag & TOKEN_REL) {
rx_token += flag & 0x3f;
flag >>= 6;
} else
rx_token = read_int(f);
if (flag & 1) {
rx_run = read_byte(f);
rx_run += read_byte(f) << 8;
recv_state = r_running;
}
return -1 - rx_token;
case r_inflating:
rx_strm.next_out = (Bytef *)dbuf;
rx_strm.avail_out = CHUNK_SIZE;
r = inflate(&rx_strm, Z_NO_FLUSH);
n = CHUNK_SIZE - rx_strm.avail_out;
if (r != Z_OK) {
rprintf(FERROR, "inflate returned %d (%d bytes)\n", r, n);
exit_cleanup(1);
}
if (rx_strm.avail_in == 0)
recv_state = r_inflated;
if (n != 0) {
*data = dbuf;
return n;
}
break;
case r_running:
++rx_token;
if (--rx_run == 0)
recv_state = r_idle;
return -1 - rx_token;
}
recv_state = r_idle;
}
if (flag == END_FLAG) {
/* that's all folks */
recv_state = r_init;
return 0;
}
/* here we have a token of some kind */
if (flag & TOKEN_REL) {
rx_token += flag & 0x3f;
flag >>= 6;
} else
rx_token = read_int(f);
if (flag & 1) {
rx_run = read_byte(f);
rx_run += read_byte(f) << 8;
recv_state = r_running;
}
return -1 - rx_token;
case r_inflating:
rx_strm.next_out = (Bytef *)dbuf;
rx_strm.avail_out = CHUNK_SIZE;
r = inflate(&rx_strm, Z_NO_FLUSH);
n = CHUNK_SIZE - rx_strm.avail_out;
if (r != Z_OK) {
fprintf(FERROR, "inflate returned %d (%d bytes)\n", r, n);
exit_cleanup(1);
}
if (rx_strm.avail_in == 0)
recv_state = r_inflated;
if (n != 0) {
*data = dbuf;
return n;
}
break;
case r_running:
++rx_token;
if (--rx_run == 0)
recv_state = r_idle;
return -1 - rx_token;
}
}
}
/*
@@ -335,15 +369,40 @@ recv_deflated_token(int f, char **data)
void
see_deflate_token(char *buf, int len)
{
int r;
int r, blklen;
unsigned char hdr[5];
rx_strm.next_in = (Bytef *)buf;
rx_strm.avail_in = len;
r = inflateIncomp(&rx_strm);
if (r != Z_OK) {
fprintf(FERROR, "inflateIncomp returned %d\n", r);
exit_cleanup(1);
}
rx_strm.avail_in = 0;
blklen = 0;
hdr[0] = 0;
do {
if (rx_strm.avail_in == 0 && len != 0) {
if (blklen == 0) {
/* Give it a fake stored-block header. */
rx_strm.next_in = (Bytef *)hdr;
rx_strm.avail_in = 5;
blklen = len;
if (blklen > 0xffff)
blklen = 0xffff;
hdr[1] = blklen;
hdr[2] = blklen >> 8;
hdr[3] = ~hdr[1];
hdr[4] = ~hdr[2];
} else {
rx_strm.next_in = (Bytef *)buf;
rx_strm.avail_in = blklen;
len -= blklen;
blklen = 0;
}
}
rx_strm.next_out = (Bytef *)dbuf;
rx_strm.avail_out = CHUNK_SIZE;
r = inflate(&rx_strm, Z_SYNC_FLUSH);
if (r != Z_OK) {
rprintf(FERROR, "inflate (token) returned %d\n", r);
exit_cleanup(1);
}
} while (len || rx_strm.avail_out == 0);
}
/*
@@ -351,14 +410,14 @@ see_deflate_token(char *buf, int len)
* If token == -1 then we have reached EOF
* If n == 0 then don't send a buffer
*/
void send_token(int f,int token,struct map_struct *buf,int offset,
void send_token(int f,int token,struct map_struct *buf,OFF_T offset,
int n,int toklen)
{
if (!do_compression) {
simple_send_token(f,token,buf,offset,n);
} else {
send_deflated_token(f, token, buf, offset, n, toklen);
}
if (!do_compression) {
simple_send_token(f,token,buf,offset,n);
} else {
send_deflated_token(f, token, buf, offset, n, toklen);
}
}
@@ -370,14 +429,14 @@ void send_token(int f,int token,struct map_struct *buf,int offset,
*/
int recv_token(int f,char **data)
{
int tok;
int tok;
if (!do_compression) {
tok = simple_recv_token(f,data);
} else {
tok = recv_deflated_token(f, data);
}
return tok;
if (!do_compression) {
tok = simple_recv_token(f,data);
} else {
tok = recv_deflated_token(f, data);
}
return tok;
}
/*
@@ -385,6 +444,6 @@ int recv_token(int f,char **data)
*/
void see_token(char *data, int toklen)
{
if (do_compression)
see_deflate_token(data, toklen);
if (do_compression)
see_deflate_token(data, toklen);
}

View File

@@ -67,38 +67,19 @@ static char *gid_to_name(gid_t gid)
return NULL;
}
/* turn a user name into a uid */
static uid_t name_to_uid(char *name)
{
struct passwd *pass;
if (!name || !*name) return 0;
pass = getpwnam(name);
if (pass) return(pass->pw_uid);
return 0;
}
/* turn a group name into a gid */
static gid_t name_to_gid(char *name)
{
struct group *grp;
if (!name || !*name) return 0;
grp = getgrnam(name);
if (grp) return(grp->gr_gid);
return 0;
}
static int map_uid(int id, char *name)
{
uid_t uid = name_to_uid(name);
if (uid != 0) return uid;
uid_t uid;
if (name_to_uid(name, &uid) && uid != 0)
return uid;
return id;
}
static int map_gid(int id, char *name)
{
gid_t gid = name_to_gid(name);
if (gid != 0) return gid;
gid_t gid;
if (name_to_gid(name, &gid) && gid != 0)
return gid;
return id;
}

496
util.c
View File

@@ -24,87 +24,30 @@
*/
#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);
}
struct map_struct *map_file(int fd,off_t len)
{
struct map_struct *ret;
ret = (struct map_struct *)malloc(sizeof(*ret));
if (!ret) out_of_memory("map_file");
ret->map = NULL;
ret->fd = fd;
ret->size = len;
ret->p = NULL;
ret->p_size = 0;
ret->p_offset = 0;
ret->p_len = 0;
#ifdef HAVE_MMAP
if (len < MAX_MAP_SIZE)
ret->map = (char *)mmap(NULL,len,PROT_READ,MAP_SHARED,fd,0);
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
return ret;
}
char *map_ptr(struct map_struct *map,off_t offset,int len)
{
int nread = -2;
if (map->map)
return map->map+offset;
if (len == 0)
return NULL;
if (len > (map->size-offset))
len = map->size-offset;
if (offset >= map->p_offset &&
offset+len <= map->p_offset+map->p_len) {
return (map->p + (offset - map->p_offset));
}
len = MAX(len,CHUNK_SIZE);
if (len > (map->size-offset))
len = map->size-offset;
if (len > map->p_size) {
if (map->p) free(map->p);
map->p = (char *)malloc(len);
if (!map->p) out_of_memory("map_ptr");
map->p_size = len;
}
if (lseek(map->fd,offset,SEEK_SET) != offset ||
(nread=read(map->fd,map->p,len)) != len) {
fprintf(FERROR,"EOF in map_ptr! (offset=%d len=%d nread=%d errno=%d)\n",
(int)offset, len, nread, errno);
exit_cleanup(1);
}
map->p_offset = offset;
map->p_len = len;
return map->p;
}
void unmap_file(struct map_struct *map)
{
#ifdef HAVE_MMAP
if (map->map)
munmap(map->map,map->size);
#endif
if (map->p) free(map->p);
free(map);
if((val = fcntl(fd, F_GETFL, 0)) == -1)
return -1;
val |= FLAG_TO_SET;
return fcntl( fd, F_SETFL, val);
#undef FLAG_TO_SET
}
@@ -117,14 +60,14 @@ int piped_child(char **command,int *f_in,int *f_out)
if (pipe(to_child_pipe) < 0 ||
pipe(from_child_pipe) < 0) {
fprintf(FERROR,"pipe: %s\n",strerror(errno));
rprintf(FERROR,"pipe: %s\n",strerror(errno));
exit_cleanup(1);
}
pid = do_fork();
if (pid < 0) {
fprintf(FERROR,"fork: %s\n",strerror(errno));
rprintf(FERROR,"fork: %s\n",strerror(errno));
exit_cleanup(1);
}
@@ -135,21 +78,21 @@ int piped_child(char **command,int *f_in,int *f_out)
close(to_child_pipe[1]) < 0 ||
close(from_child_pipe[0]) < 0 ||
dup2(from_child_pipe[1], STDOUT_FILENO) < 0) {
fprintf(FERROR,"Failed to dup/close : %s\n",strerror(errno));
rprintf(FERROR,"Failed to dup/close : %s\n",strerror(errno));
exit_cleanup(1);
}
if (to_child_pipe[0] != STDIN_FILENO) close(to_child_pipe[0]);
if (from_child_pipe[1] != STDOUT_FILENO) close(from_child_pipe[1]);
umask(orig_umask);
execvp(command[0], command);
fprintf(FERROR,"Failed to exec %s : %s\n",
rprintf(FERROR,"Failed to exec %s : %s\n",
command[0],strerror(errno));
exit_cleanup(1);
}
if (close(from_child_pipe[1]) < 0 ||
close(to_child_pipe[0]) < 0) {
fprintf(FERROR,"Failed to close : %s\n",strerror(errno));
rprintf(FERROR,"Failed to close : %s\n",strerror(errno));
exit_cleanup(1);
}
@@ -167,14 +110,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) {
fprintf(FERROR,"pipe: %s\n",strerror(errno));
rprintf(FERROR,"pipe: %s\n",strerror(errno));
exit_cleanup(1);
}
pid = do_fork();
if (pid < 0) {
fprintf(FERROR,"fork: %s\n",strerror(errno));
rprintf(FERROR,"fork: %s\n",strerror(errno));
exit_cleanup(1);
}
@@ -189,17 +132,17 @@ int local_child(int argc, char **argv,int *f_in,int *f_out)
close(to_child_pipe[1]) < 0 ||
close(from_child_pipe[0]) < 0 ||
dup2(from_child_pipe[1], STDOUT_FILENO) < 0) {
fprintf(FERROR,"Failed to dup/close : %s\n",strerror(errno));
rprintf(FERROR,"Failed to dup/close : %s\n",strerror(errno));
exit_cleanup(1);
}
if (to_child_pipe[0] != STDIN_FILENO) close(to_child_pipe[0]);
if (from_child_pipe[1] != STDOUT_FILENO) close(from_child_pipe[1]);
start_server(argc, argv);
start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
}
if (close(from_child_pipe[1]) < 0 ||
close(to_child_pipe[0]) < 0) {
fprintf(FERROR,"Failed to close : %s\n",strerror(errno));
rprintf(FERROR,"Failed to close : %s\n",strerror(errno));
exit_cleanup(1);
}
@@ -213,13 +156,13 @@ int local_child(int argc, char **argv,int *f_in,int *f_out)
void out_of_memory(char *str)
{
fprintf(FERROR,"ERROR: out of memory in %s\n",str);
rprintf(FERROR,"ERROR: out of memory in %s\n",str);
exit_cleanup(1);
}
void overflow(char *str)
{
fprintf(FERROR,"ERROR: buffer overflow in %s\n",str);
rprintf(FERROR,"ERROR: buffer overflow in %s\n",str);
exit_cleanup(1);
}
@@ -252,36 +195,6 @@ int set_modtime(char *fname,time_t modtime)
}
/****************************************************************************
Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available,
else
if SYSV use O_NDELAY
if BSD use FNDELAY
****************************************************************************/
int set_blocking(int fd, int set)
{
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;
if(set) /* Turn blocking on - ie. clear nonblock flag */
val &= ~FLAG_TO_SET;
else
val |= FLAG_TO_SET;
return fcntl( fd, F_SETFL, val);
#undef FLAG_TO_SET
}
/****************************************************************************
create any necessary directories in fname. Unfortunately we don't know
what perms to give the directory when this is called so we need to rely
@@ -311,7 +224,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;
@@ -366,20 +279,20 @@ int copy_file(char *source, char *dest, mode_t mode)
ifd = open(source, O_RDONLY);
if (ifd == -1) {
fprintf(FERROR,"open %s: %s\n",
rprintf(FERROR,"open %s: %s\n",
source,strerror(errno));
return -1;
}
if (do_unlink(dest) && errno != ENOENT) {
fprintf(FERROR,"unlink %s: %s\n",
rprintf(FERROR,"unlink %s: %s\n",
dest,strerror(errno));
return -1;
}
ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode);
if (ofd < 0) {
fprintf(FERROR,"open %s: %s\n",
rprintf(FERROR,"open %s: %s\n",
dest,strerror(errno));
close(ifd);
return -1;
@@ -387,7 +300,7 @@ int copy_file(char *source, char *dest, mode_t mode)
while ((len = safe_read(ifd, buf, sizeof(buf))) > 0) {
if (full_write(ofd, buf, len) < 0) {
fprintf(FERROR,"write %s: %s\n",
rprintf(FERROR,"write %s: %s\n",
dest,strerror(errno));
close(ifd);
close(ofd);
@@ -399,7 +312,7 @@ int copy_file(char *source, char *dest, mode_t mode)
close(ofd);
if (len < 0) {
fprintf(FERROR,"read %s: %s\n",
rprintf(FERROR,"read %s: %s\n",
source,strerror(errno));
return -1;
}
@@ -441,3 +354,334 @@ void kill_all(int sig)
kill(all_pids[i], sig);
}
}
/* like strncpy but does not 0 fill the buffer and always null
terminates (thus it can use maxlen+1 space in d) */
void strlcpy(char *d, char *s, int maxlen)
{
int len = strlen(s);
if (len > maxlen) len = maxlen;
memcpy(d, s, len);
d[len] = 0;
}
/* like strncat but does not 0 fill the buffer and always null
terminates (thus it can use maxlen+1 space in d) */
void strlcat(char *d, char *s, int maxlen)
{
int len1 = strlen(d);
int len2 = strlen(s);
if (len1+len2 > maxlen) {
len2 = maxlen-len1;
}
if (len2 > 0) {
memcpy(d+len1, s, len2);
d[len1+len2] = 0;
}
}
/* turn a user name into a uid */
int name_to_uid(char *name, uid_t *uid)
{
struct passwd *pass;
if (!name || !*name) return 0;
pass = getpwnam(name);
if (pass) {
*uid = pass->pw_uid;
return 1;
}
return 0;
}
/* turn a group name into a gid */
int name_to_gid(char *name, gid_t *gid)
{
struct group *grp;
if (!name || !*name) return 0;
grp = getgrnam(name);
if (grp) {
*gid = grp->gr_gid;
return 1;
}
return 0;
}
/****************************************************************************
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)
{
struct flock lock;
lock.l_type = F_WRLCK;
lock.l_whence = SEEK_SET;
lock.l_start = offset;
lock.l_len = len;
lock.l_pid = 0;
return fcntl(fd,F_SETLK,&lock) == 0;
}
static void glob_expand_one(char *s, char **argv, int *argc, int maxargs)
{
#ifndef HAVE_GLOB
if (!*s) s = ".";
argv[*argc] = strdup(s);
(*argc)++;
return;
#else
glob_t globbuf;
int i;
if (!*s) s = ".";
argv[*argc] = strdup(s);
memset(&globbuf, 0, sizeof(globbuf));
glob(argv[*argc], 0, NULL, &globbuf);
if (globbuf.gl_pathc == 0) {
(*argc)++;
globfree(&globbuf);
return;
}
for (i=0; i<(maxargs - (*argc)) && i<globbuf.gl_pathc;i++) {
if (i == 0) free(argv[*argc]);
argv[(*argc) + i] = strdup(globbuf.gl_pathv[i]);
if (!argv[(*argc) + i]) out_of_memory("glob_expand");
}
globfree(&globbuf);
(*argc) += i;
#endif
}
void glob_expand(char *base1, char **argv, int *argc, int maxargs)
{
char *s = argv[*argc];
char *p, *q;
char *base = base1;
if (!s || !*s) return;
if (strncmp(s, base, strlen(base)) == 0) {
s += strlen(base);
}
s = strdup(s);
if (!s) out_of_memory("glob_expand");
base = (char *)malloc(strlen(base1)+3);
if (!base) out_of_memory("glob_expand");
sprintf(base," %s/", base1);
q = s;
while ((p = strstr(q,base)) && ((*argc) < maxargs)) {
/* split it at this point */
*p = 0;
glob_expand_one(q, argv, argc, maxargs);
q = p+strlen(base);
}
if (*q && (*argc < maxargs)) glob_expand_one(q, argv, argc, maxargs);
free(s);
free(base);
}
/*******************************************************************
convert a string to lower case
********************************************************************/
void strlower(char *s)
{
while (*s) {
if (isupper(*s)) *s = tolower(*s);
s++;
}
}
/* this is like vsnprintf but the 'n' limit does not include
the terminating null. So if you have a 1024 byte buffer then
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;
return -1;
}
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
}
/* like snprintf but always null terminates */
int slprintf(char *str, int n, char *format, ...)
{
va_list ap;
int ret;
va_start(ap, format);
ret = vslprintf(str,n,format,ap);
va_end(ap);
return ret;
}
void *Realloc(void *p, int size)
{
if (!p) return (void *)malloc(size);
return (void *)realloc(p, size);
}
void clean_fname(char *name)
{
char *p;
int l;
int modified = 1;
if (!name) return;
while (modified) {
modified = 0;
if ((p=strstr(name,"/./"))) {
modified = 1;
while (*p) {
p[0] = p[2];
p++;
}
}
if ((p=strstr(name,"//"))) {
modified = 1;
while (*p) {
p[0] = p[1];
p++;
}
}
if (strncmp(p=name,"./",2) == 0) {
modified = 1;
do {
p[0] = p[2];
} while (*p++);
}
l = strlen(p=name);
if (l > 1 && p[l-1] == '/') {
modified = 1;
p[l-1] = 0;
}
}
}
static char curr_dir[MAXPATHLEN];
/* like chdir() but can be reversed with pop_dir() if save is set. It
is also much faster as it remembers where we have been */
char *push_dir(char *dir, int save)
{
char *ret = curr_dir;
static int initialised;
if (!initialised) {
initialised = 1;
getcwd(curr_dir, sizeof(curr_dir)-1);
}
if (chdir(dir)) return NULL;
if (save) {
ret = strdup(curr_dir);
}
if (*dir == '/') {
strlcpy(curr_dir, dir, sizeof(curr_dir)-1);
} else {
strlcat(curr_dir,"/", sizeof(curr_dir)-1);
strlcat(curr_dir,dir, sizeof(curr_dir)-1);
}
clean_fname(curr_dir);
return ret;
}
/* reverse a push_dir call */
int pop_dir(char *dir)
{
int ret;
ret = chdir(dir);
if (ret) {
free(dir);
return ret;
}
strlcpy(curr_dir, dir, sizeof(curr_dir)-1);
free(dir);
return 0;
}
/* we need to supply our own strcmp function for file list comparisons
to ensure that signed/unsigned usage is consistent between machines. */
int u_strcmp(const char *cs1, const char *cs2)
{
const uchar *s1 = (uchar *)cs1;
const uchar *s2 = (uchar *)cs2;
while (*s1 && *s2 && (*s1 == *s2)) {
s1++; s2++;
}
return (int)*s1 - (int)*s2;
}

View File

@@ -1 +1 @@
#define VERSION "1.7.4"
#define VERSION "2.0.17"

423
zlib/ChangeLog Normal file
View File

@@ -0,0 +1,423 @@
ChangeLog file for zlib
Changes in 1.1.2 (19 March 98)
- added contrib/minzip, mini zip and unzip based on zlib (Gilles Vollant)
See http://www.winimage.com/zLibDll/unzip.html
- preinitialize the inflate tables for fixed codes, to make the code
completely thread safe (Mark)
- some simplifications and slight speed-up to the inflate code (Mark)
- fix gzeof on non-compressed files (Allan Schrum)
- add -std1 option in configure for OSF1 to fix gzprintf (Martin Mokrejs)
- use default value of 4K for Z_BUFSIZE for 16-bit MSDOS (Tim Wegner + Glenn)
- added os2/Makefile.def and os2/zlib.def (Andrew Zabolotny)
- add shared lib support for UNIX_SV4.2MP (MATSUURA Takanori)
- do not wrap extern "C" around system includes (Tom Lane)
- mention zlib binding for TCL in README (Andreas Kupries)
- added amiga/Makefile.pup for Amiga powerUP SAS/C PPC (Andreas Kleinert)
- allow "make install prefix=..." even after configure (Glenn Randers-Pehrson)
- allow "configure --prefix $HOME" (Tim Mooney)
- remove warnings in example.c and gzio.c (Glenn Randers-Pehrson)
- move Makefile.sas to amiga/Makefile.sas
Changes in 1.1.1 (27 Feb 98)
- fix macros _tr_tally_* in deflate.h for debug mode (Glenn Randers-Pehrson)
- remove block truncation heuristic which had very marginal effect for zlib
(smaller lit_bufsize than in gzip 1.2.4) and degraded a little the
compression ratio on some files. This also allows inlining _tr_tally for
matches in deflate_slow.
- added msdos/Makefile.w32 for WIN32 Microsoft Visual C++ (Bob Frazier)
Changes in 1.1.0 (24 Feb 98)
- do not return STREAM_END prematurely in inflate (John Bowler)
- revert to the zlib 1.0.8 inflate to avoid the gcc 2.8.0 bug (Jeremy Buhler)
- compile with -DFASTEST to get compression code optimized for speed only
- in minigzip, try mmap'ing the input file first (Miguel Albrecht)
- increase size of I/O buffers in minigzip.c and gzio.c (not a big gain
on Sun but significant on HP)
- add a pointer to experimental unzip library in README (Gilles Vollant)
- initialize variable gcc in configure (Chris Herborth)
Changes in 1.0.9 (17 Feb 1998)
- added gzputs and gzgets functions
- do not clear eof flag in gzseek (Mark Diekhans)
- fix gzseek for files in transparent mode (Mark Diekhans)
- do not assume that vsprintf returns the number of bytes written (Jens Krinke)
- replace EXPORT with ZEXPORT to avoid conflict with other programs
- added compress2 in zconf.h, zlib.def, zlib.dnt
- new asm code from Gilles Vollant in contrib/asm386
- simplify the inflate code (Mark):
. Replace ZALLOC's in huft_build() with single ZALLOC in inflate_blocks_new()
. ZALLOC the length list in inflate_trees_fixed() instead of using stack
. ZALLOC the value area for huft_build() instead of using stack
. Simplify Z_FINISH check in inflate()
- Avoid gcc 2.8.0 comparison bug a little differently than zlib 1.0.8
- in inftrees.c, avoid cc -O bug on HP (Farshid Elahi)
- in zconf.h move the ZLIB_DLL stuff earlier to avoid problems with
the declaration of FAR (Gilles VOllant)
- install libz.so* with mode 755 (executable) instead of 644 (Marc Lehmann)
- read_buf buf parameter of type Bytef* instead of charf*
- zmemcpy parameters are of type Bytef*, not charf* (Joseph Strout)
- do not redeclare unlink in minigzip.c for WIN32 (John Bowler)
- fix check for presence of directories in "make install" (Ian Willis)
Changes in 1.0.8 (27 Jan 1998)
- fixed offsets in contrib/asm386/gvmat32.asm (Gilles Vollant)
- fix gzgetc and gzputc for big endian systems (Markus Oberhumer)
- added compress2() to allow setting the compression level
- include sys/types.h to get off_t on some systems (Marc Lehmann & QingLong)
- use constant arrays for the static trees in trees.c instead of computing
them at run time (thanks to Ken Raeburn for this suggestion). To create
trees.h, compile with GEN_TREES_H and run "make test".
- check return code of example in "make test" and display result
- pass minigzip command line options to file_compress
- simplifying code of inflateSync to avoid gcc 2.8 bug
- support CC="gcc -Wall" in configure -s (QingLong)
- avoid a flush caused by ftell in gzopen for write mode (Ken Raeburn)
- fix test for shared library support to avoid compiler warnings
- zlib.lib -> zlib.dll in msdos/zlib.rc (Gilles Vollant)
- check for TARGET_OS_MAC in addition to MACOS (Brad Pettit)
- do not use fdopen for Metrowerks on Mac (Brad Pettit))
- add checks for gzputc and gzputc in example.c
- avoid warnings in gzio.c and deflate.c (Andreas Kleinert)
- use const for the CRC table (Ken Raeburn)
- fixed "make uninstall" for shared libraries
- use Tracev instead of Trace in infblock.c
- in example.c use correct compressed length for test_sync
- suppress +vnocompatwarnings in configure for HPUX (not always supported)
Changes in 1.0.7 (20 Jan 1998)
- fix gzseek which was broken in write mode
- return error for gzseek to negative absolute position
- fix configure for Linux (Chun-Chung Chen)
- increase stack space for MSC (Tim Wegner)
- get_crc_table and inflateSyncPoint are EXPORTed (Gilles Vollant)
- define EXPORTVA for gzprintf (Gilles Vollant)
- added man page zlib.3 (Rick Rodgers)
- for contrib/untgz, fix makedir() and improve Makefile
- check gzseek in write mode in example.c
- allocate extra buffer for seeks only if gzseek is actually called
- avoid signed/unsigned comparisons (Tim Wegner, Gilles Vollant)
- add inflateSyncPoint in zconf.h
- fix list of exported functions in nt/zlib.dnt and mdsos/zlib.def
Changes in 1.0.6 (19 Jan 1998)
- add functions gzprintf, gzputc, gzgetc, gztell, gzeof, gzseek, gzrewind and
gzsetparams (thanks to Roland Giersig and Kevin Ruland for some of this code)
- Fix a deflate bug occuring only with compression level 0 (thanks to
Andy Buckler for finding this one).
- In minigzip, pass transparently also the first byte for .Z files.
- return Z_BUF_ERROR instead of Z_OK if output buffer full in uncompress()
- check Z_FINISH in inflate (thanks to Marc Schluper)
- Implement deflateCopy (thanks to Adam Costello)
- make static libraries by default in configure, add --shared option.
- move MSDOS or Windows specific files to directory msdos
- suppress the notion of partial flush to simplify the interface
(but the symbol Z_PARTIAL_FLUSH is kept for compatibility with 1.0.4)
- suppress history buffer provided by application to simplify the interface
(this feature was not implemented anyway in 1.0.4)
- next_in and avail_in must be initialized before calling inflateInit or
inflateInit2
- add EXPORT in all exported functions (for Windows DLL)
- added Makefile.nt (thanks to Stephen Williams)
- added the unsupported "contrib" directory:
contrib/asm386/ by Gilles Vollant <info@winimage.com>
386 asm code replacing longest_match().
contrib/iostream/ by Kevin Ruland <kevin@rodin.wustl.edu>
A C++ I/O streams interface to the zlib gz* functions
contrib/iostream2/ by Tyge L<>vset <Tyge.Lovset@cmr.no>
Another C++ I/O streams interface
contrib/untgz/ by "Pedro A. Aranda Guti\irrez" <paag@tid.es>
A very simple tar.gz file extractor using zlib
contrib/visual-basic.txt by Carlos Rios <c_rios@sonda.cl>
How to use compress(), uncompress() and the gz* functions from VB.
- pass params -f (filtered data), -h (huffman only), -1 to -9 (compression
level) in minigzip (thanks to Tom Lane)
- use const for rommable constants in deflate
- added test for gzseek and gztell in example.c
- add undocumented function inflateSyncPoint() (hack for Paul Mackerras)
- add undocumented function zError to convert error code to string
(for Tim Smithers)
- Allow compilation of gzio with -DNO_DEFLATE to avoid the compression code.
- Use default memcpy for Symantec MSDOS compiler.
- Add EXPORT keyword for check_func (needed for Windows DLL)
- add current directory to LD_LIBRARY_PATH for "make test"
- create also a link for libz.so.1
- added support for FUJITSU UXP/DS (thanks to Toshiaki Nomura)
- use $(SHAREDLIB) instead of libz.so in Makefile.in (for HPUX)
- added -soname for Linux in configure (Chun-Chung Chen,
- assign numbers to the exported functions in zlib.def (for Windows DLL)
- add advice in zlib.h for best usage of deflateSetDictionary
- work around compiler bug on Atari (cast Z_NULL in call of s->checkfn)
- allow compilation with ANSI keywords only enabled for TurboC in large model
- avoid "versionString"[0] (Borland bug)
- add NEED_DUMMY_RETURN for Borland
- use variable z_verbose for tracing in debug mode (L. Peter Deutsch).
- allow compilation with CC
- defined STDC for OS/2 (David Charlap)
- limit external names to 8 chars for MVS (Thomas Lund)
- in minigzip.c, use static buffers only for 16-bit systems
- fix suffix check for "minigzip -d foo.gz"
- do not return an error for the 2nd of two consecutive gzflush() (Felix Lee)
- use _fdopen instead of fdopen for MSC >= 6.0 (Thomas Fanslau)
- added makelcc.bat for lcc-win32 (Tom St Denis)
- in Makefile.dj2, use copy and del instead of install and rm (Frank Donahoe)
- Avoid expanded $Id$. Use "rcs -kb" or "cvs admin -kb" to avoid Id expansion.
- check for unistd.h in configure (for off_t)
- remove useless check parameter in inflate_blocks_free
- avoid useless assignment of s->check to itself in inflate_blocks_new
- do not flush twice in gzclose (thanks to Ken Raeburn)
- rename FOPEN as F_OPEN to avoid clash with /usr/include/sys/file.h
- use NO_ERRNO_H instead of enumeration of operating systems with errno.h
- work around buggy fclose on pipes for HP/UX
- support zlib DLL with BORLAND C++ 5.0 (thanks to Glenn Randers-Pehrson)
- fix configure if CC is already equal to gcc
Changes in 1.0.5 (3 Jan 98)
- Fix inflate to terminate gracefully when fed corrupted or invalid data
- Use const for rommable constants in inflate
- Eliminate memory leaks on error conditions in inflate
- Removed some vestigial code in inflate
- Update web address in README
Changes in 1.0.4 (24 Jul 96)
- In very rare conditions, deflate(s, Z_FINISH) could fail to produce an EOF
bit, so the decompressor could decompress all the correct data but went
on to attempt decompressing extra garbage data. This affected minigzip too.
- zlibVersion and gzerror return const char* (needed for DLL)
- port to RISCOS (no fdopen, no multiple dots, no unlink, no fileno)
- use z_error only for DEBUG (avoid problem with DLLs)
Changes in 1.0.3 (2 Jul 96)
- use z_streamp instead of z_stream *, which is now a far pointer in MSDOS
small and medium models; this makes the library incompatible with previous
versions for these models. (No effect in large model or on other systems.)
- return OK instead of BUF_ERROR if previous deflate call returned with
avail_out as zero but there is nothing to do
- added memcmp for non STDC compilers
- define NO_DUMMY_DECL for more Mac compilers (.h files merged incorrectly)
- define __32BIT__ if __386__ or i386 is defined (pb. with Watcom and SCO)
- better check for 16-bit mode MSC (avoids problem with Symantec)
Changes in 1.0.2 (23 May 96)
- added Windows DLL support
- added a function zlibVersion (for the DLL support)
- fixed declarations using Bytef in infutil.c (pb with MSDOS medium model)
- Bytef is define's instead of typedef'd only for Borland C
- avoid reading uninitialized memory in example.c
- mention in README that the zlib format is now RFC1950
- updated Makefile.dj2
- added algorithm.doc
Changes in 1.0.1 (20 May 96) [1.0 skipped to avoid confusion]
- fix array overlay in deflate.c which sometimes caused bad compressed data
- fix inflate bug with empty stored block
- fix MSDOS medium model which was broken in 0.99
- fix deflateParams() which could generated bad compressed data.
- Bytef is define'd instead of typedef'ed (work around Borland bug)
- added an INDEX file
- new makefiles for DJGPP (Makefile.dj2), 32-bit Borland (Makefile.b32),
Watcom (Makefile.wat), Amiga SAS/C (Makefile.sas)
- speed up adler32 for modern machines without auto-increment
- added -ansi for IRIX in configure
- static_init_done in trees.c is an int
- define unlink as delete for VMS
- fix configure for QNX
- add configure branch for SCO and HPUX
- avoid many warnings (unused variables, dead assignments, etc...)
- no fdopen for BeOS
- fix the Watcom fix for 32 bit mode (define FAR as empty)
- removed redefinition of Byte for MKWERKS
- work around an MWKERKS bug (incorrect merge of all .h files)
Changes in 0.99 (27 Jan 96)
- allow preset dictionary shared between compressor and decompressor
- allow compression level 0 (no compression)
- add deflateParams in zlib.h: allow dynamic change of compression level
and compression strategy.
- test large buffers and deflateParams in example.c
- add optional "configure" to build zlib as a shared library
- suppress Makefile.qnx, use configure instead
- fixed deflate for 64-bit systems (detected on Cray)
- fixed inflate_blocks for 64-bit systems (detected on Alpha)
- declare Z_DEFLATED in zlib.h (possible parameter for deflateInit2)
- always return Z_BUF_ERROR when deflate() has nothing to do
- deflateInit and inflateInit are now macros to allow version checking
- prefix all global functions and types with z_ with -DZ_PREFIX
- make falloc completely reentrant (inftrees.c)
- fixed very unlikely race condition in ct_static_init
- free in reverse order of allocation to help memory manager
- use zlib-1.0/* instead of zlib/* inside the tar.gz
- make zlib warning-free with "gcc -O3 -Wall -Wwrite-strings -Wpointer-arith
-Wconversion -Wstrict-prototypes -Wmissing-prototypes"
- allow gzread on concatenated .gz files
- deflateEnd now returns Z_DATA_ERROR if it was premature
- deflate is finally (?) fully deterministic (no matches beyond end of input)
- Document Z_SYNC_FLUSH
- add uninstall in Makefile
- Check for __cpluplus in zlib.h
- Better test in ct_align for partial flush
- avoid harmless warnings for Borland C++
- initialize hash_head in deflate.c
- avoid warning on fdopen (gzio.c) for HP cc -Aa
- include stdlib.h for STDC compilers
- include errno.h for Cray
- ignore error if ranlib doesn't exist
- call ranlib twice for NeXTSTEP
- use exec_prefix instead of prefix for libz.a
- renamed ct_* as _tr_* to avoid conflict with applications
- clear z->msg in inflateInit2 before any error return
- initialize opaque in example.c, gzio.c, deflate.c and inflate.c
- fixed typo in zconf.h (_GNUC__ => __GNUC__)
- check for WIN32 in zconf.h and zutil.c (avoid farmalloc in 32-bit mode)
- fix typo in Make_vms.com (f$trnlnm -> f$getsyi)
- in fcalloc, normalize pointer if size > 65520 bytes
- don't use special fcalloc for 32 bit Borland C++
- use STDC instead of __GO32__ to avoid redeclaring exit, calloc, etc...
- use Z_BINARY instead of BINARY
- document that gzclose after gzdopen will close the file
- allow "a" as mode in gzopen.
- fix error checking in gzread
- allow skipping .gz extra-field on pipes
- added reference to Perl interface in README
- put the crc table in FAR data (I dislike more and more the medium model :)
- added get_crc_table
- added a dimension to all arrays (Borland C can't count).
- workaround Borland C bug in declaration of inflate_codes_new & inflate_fast
- guard against multiple inclusion of *.h (for precompiled header on Mac)
- Watcom C pretends to be Microsoft C small model even in 32 bit mode.
- don't use unsized arrays to avoid silly warnings by Visual C++:
warning C4746: 'inflate_mask' : unsized array treated as '__far'
(what's wrong with far data in far model?).
- define enum out of inflate_blocks_state to allow compilation with C++
Changes in 0.95 (16 Aug 95)
- fix MSDOS small and medium model (now easier to adapt to any compiler)
- inlined send_bits
- fix the final (:-) bug for deflate with flush (output was correct but
not completely flushed in rare occasions).
- default window size is same for compression and decompression
(it's now sufficient to set MAX_WBITS in zconf.h).
- voidp -> voidpf and voidnp -> voidp (for consistency with other
typedefs and because voidnp was not near in large model).
Changes in 0.94 (13 Aug 95)
- support MSDOS medium model
- fix deflate with flush (could sometimes generate bad output)
- fix deflateReset (zlib header was incorrectly suppressed)
- added support for VMS
- allow a compression level in gzopen()
- gzflush now calls fflush
- For deflate with flush, flush even if no more input is provided.
- rename libgz.a as libz.a
- avoid complex expression in infcodes.c triggering Turbo C bug
- work around a problem with gcc on Alpha (in INSERT_STRING)
- don't use inline functions (problem with some gcc versions)
- allow renaming of Byte, uInt, etc... with #define.
- avoid warning about (unused) pointer before start of array in deflate.c
- avoid various warnings in gzio.c, example.c, infblock.c, adler32.c, zutil.c
- avoid reserved word 'new' in trees.c
Changes in 0.93 (25 June 95)
- temporarily disable inline functions
- make deflate deterministic
- give enough lookahead for PARTIAL_FLUSH
- Set binary mode for stdin/stdout in minigzip.c for OS/2
- don't even use signed char in inflate (not portable enough)
- fix inflate memory leak for segmented architectures
Changes in 0.92 (3 May 95)
- don't assume that char is signed (problem on SGI)
- Clear bit buffer when starting a stored block
- no memcpy on Pyramid
- suppressed inftest.c
- optimized fill_window, put longest_match inline for gcc
- optimized inflate on stored blocks.
- untabify all sources to simplify patches
Changes in 0.91 (2 May 95)
- Default MEM_LEVEL is 8 (not 9 for Unix) as documented in zlib.h
- Document the memory requirements in zconf.h
- added "make install"
- fix sync search logic in inflateSync
- deflate(Z_FULL_FLUSH) now works even if output buffer too short
- after inflateSync, don't scare people with just "lo world"
- added support for DJGPP
Changes in 0.9 (1 May 95)
- don't assume that zalloc clears the allocated memory (the TurboC bug
was Mark's bug after all :)
- let again gzread copy uncompressed data unchanged (was working in 0.71)
- deflate(Z_FULL_FLUSH), inflateReset and inflateSync are now fully implemented
- added a test of inflateSync in example.c
- moved MAX_WBITS to zconf.h because users might want to change that.
- document explicitly that zalloc(64K) on MSDOS must return a normalized
pointer (zero offset)
- added Makefiles for Microsoft C, Turbo C, Borland C++
- faster crc32()
Changes in 0.8 (29 April 95)
- added fast inflate (inffast.c)
- deflate(Z_FINISH) now returns Z_STREAM_END when done. Warning: this
is incompatible with previous versions of zlib which returned Z_OK.
- work around a TurboC compiler bug (bad code for b << 0, see infutil.h)
(actually that was not a compiler bug, see 0.81 above)
- gzread no longer reads one extra byte in certain cases
- In gzio destroy(), don't reference a freed structure
- avoid many warnings for MSDOS
- avoid the ERROR symbol which is used by MS Windows
Changes in 0.71 (14 April 95)
- Fixed more MSDOS compilation problems :( There is still a bug with
TurboC large model.
Changes in 0.7 (14 April 95)
- Added full inflate support.
- Simplified the crc32() interface. The pre- and post-conditioning
(one's complement) is now done inside crc32(). WARNING: this is
incompatible with previous versions; see zlib.h for the new usage.
Changes in 0.61 (12 April 95)
- workaround for a bug in TurboC. example and minigzip now work on MSDOS.
Changes in 0.6 (11 April 95)
- added minigzip.c
- added gzdopen to reopen a file descriptor as gzFile
- added transparent reading of non-gziped files in gzread.
- fixed bug in gzread (don't read crc as data)
- fixed bug in destroy (gzio.c) (don't return Z_STREAM_END for gzclose).
- don't allocate big arrays in the stack (for MSDOS)
- fix some MSDOS compilation problems
Changes in 0.5:
- do real compression in deflate.c. Z_PARTIAL_FLUSH is supported but
not yet Z_FULL_FLUSH.
- support decompression but only in a single step (forced Z_FINISH)
- added opaque object for zalloc and zfree.
- added deflateReset and inflateReset
- added a variable zlib_version for consistency checking.
- renamed the 'filter' parameter of deflateInit2 as 'strategy'.
Added Z_FILTERED and Z_HUFFMAN_ONLY constants.
Changes in 0.4:
- avoid "zip" everywhere, use zlib instead of ziplib.
- suppress Z_BLOCK_FLUSH, interpret Z_PARTIAL_FLUSH as block flush
if compression method == 8.
- added adler32 and crc32
- renamed deflateOptions as deflateInit2, call one or the other but not both
- added the method parameter for deflateInit2.
- added inflateInit2
- simplied considerably deflateInit and inflateInit by not supporting
user-provided history buffer. This is supported only in deflateInit2
and inflateInit2.
Changes in 0.3:
- prefix all macro names with Z_
- use Z_FINISH instead of deflateEnd to finish compression.
- added Z_HUFFMAN_ONLY
- added gzerror()

160
zlib/Makefile Normal file
View File

@@ -0,0 +1,160 @@
# Makefile for zlib
# Copyright (C) 1995-1998 Jean-loup Gailly.
# For conditions of distribution and use, see copyright notice in zlib.h
# To compile and test, type:
# ./configure; make test
# The call of configure is optional if you don't have special requirements
# If you wish to build zlib as a shared library, use: ./configure -s
# To install /usr/local/lib/libz.* and /usr/local/include/zlib.h, type:
# make install
# To install in $HOME instead of /usr/local, use:
# make install prefix=$HOME
CC=cc
CFLAGS=-O
#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7
#CFLAGS=-g -DDEBUG
#CFLAGS=-O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \
# -Wstrict-prototypes -Wmissing-prototypes
LDFLAGS=-L. -lz
LDSHARED=$(CC)
VER=1.1.2
LIBS=libz.a
SHAREDLIB=libz.so
AR=ar rc
RANLIB=ranlib
TAR=tar
SHELL=/bin/sh
prefix = /usr/local
exec_prefix = ${prefix}
OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \
zutil.o inflate.o infblock.o inftrees.o infcodes.o infutil.o inffast.o
TEST_OBJS = example.o minigzip.o
DISTFILES = README INDEX ChangeLog configure Make*[a-z0-9] *.[ch] descrip.mms \
algorithm.txt zlib.3 msdos/Make*[a-z0-9] msdos/zlib.def msdos/zlib.rc \
nt/Makefile.nt nt/zlib.dnt amiga/Make*.??? contrib/README.contrib \
contrib/*.txt contrib/asm386/*.asm contrib/asm386/*.c \
contrib/asm386/*.bat contrib/asm386/zlibvc.d?? contrib/iostream/*.cpp \
contrib/iostream/*.h contrib/iostream2/*.h contrib/iostream2/*.cpp \
contrib/untgz/Makefile contrib/untgz/*.c contrib/untgz/*.w32 \
contrib/minizip/[CM]*[pe] contrib/minizip/*.[ch] contrib/minizip/*.[td]??
all: example minigzip
test: all
@LD_LIBRARY_PATH=.:$(LD_LIBRARY_PATH) ; export LD_LIBRARY_PATH; \
echo hello world | ./minigzip | ./minigzip -d || \
echo ' *** minigzip test FAILED ***' ; \
if ./example; then \
echo ' *** zlib test OK ***'; \
else \
echo ' *** zlib test FAILED ***'; \
fi
libz.a: $(OBJS)
$(AR) $@ $(OBJS)
-@ ($(RANLIB) $@ || true) >/dev/null 2>&1
$(SHAREDLIB).$(VER): $(OBJS)
$(LDSHARED) -o $@ $(OBJS)
rm -f $(SHAREDLIB) $(SHAREDLIB).1
ln -s $@ $(SHAREDLIB)
ln -s $@ $(SHAREDLIB).1
example: example.o $(LIBS)
$(CC) $(CFLAGS) -o $@ example.o $(LDFLAGS)
minigzip: minigzip.o $(LIBS)
$(CC) $(CFLAGS) -o $@ minigzip.o $(LDFLAGS)
install: $(LIBS)
-@if [ ! -d $(prefix)/include ]; then mkdir $(prefix)/include; fi
-@if [ ! -d $(exec_prefix)/lib ]; then mkdir $(exec_prefix)/lib; fi
cp zlib.h zconf.h $(prefix)/include
chmod 644 $(prefix)/include/zlib.h $(prefix)/include/zconf.h
cp $(LIBS) $(exec_prefix)/lib
cd $(exec_prefix)/lib; chmod 755 $(LIBS)
-@(cd $(exec_prefix)/lib; $(RANLIB) libz.a || true) >/dev/null 2>&1
cd $(exec_prefix)/lib; if test -f $(SHAREDLIB).$(VER); then \
rm -f $(SHAREDLIB) $(SHAREDLIB).1; \
ln -s $(SHAREDLIB).$(VER) $(SHAREDLIB); \
ln -s $(SHAREDLIB).$(VER) $(SHAREDLIB).1; \
(ldconfig || true) >/dev/null 2>&1; \
fi
# The ranlib in install is needed on NeXTSTEP which checks file times
# ldconfig is for Linux
uninstall:
cd $(prefix)/include; \
v=$(VER); \
if test -f zlib.h; then \
v=`sed -n '/VERSION "/s/.*"\(.*\)".*/\1/p' < zlib.h`; \
rm -f zlib.h zconf.h; \
fi; \
cd $(exec_prefix)/lib; rm -f libz.a; \
if test -f $(SHAREDLIB).$$v; then \
rm -f $(SHAREDLIB).$$v $(SHAREDLIB) $(SHAREDLIB).1; \
fi
clean:
rm -f *.o *~ example minigzip libz.a libz.so* foo.gz
distclean: clean
zip:
mv Makefile Makefile~; cp -p Makefile.in Makefile
rm -f test.c ztest*.c contrib/minizip/test.zip
v=`sed -n -e 's/\.//g' -e '/VERSION "/s/.*"\(.*\)".*/\1/p' < zlib.h`;\
zip -ul9 zlib$$v $(DISTFILES)
mv Makefile~ Makefile
dist:
mv Makefile Makefile~; cp -p Makefile.in Makefile
rm -f test.c ztest*.c contrib/minizip/test.zip
d=zlib-`sed -n '/VERSION "/s/.*"\(.*\)".*/\1/p' < zlib.h`;\
rm -f $$d.tar.gz; \
if test ! -d ../$$d; then rm -f ../$$d; ln -s `pwd` ../$$d; fi; \
files=""; \
for f in $(DISTFILES); do files="$$files $$d/$$f"; done; \
cd ..; \
GZIP=-9 $(TAR) chofz $$d/$$d.tar.gz $$files; \
if test ! -d $$d; then rm -f $$d; fi
mv Makefile~ Makefile
tags:
etags *.[ch]
depend:
makedepend -- $(CFLAGS) -- *.[ch]
# DO NOT DELETE THIS LINE -- make depend depends on it.
adler32.o: zlib.h zconf.h
compress.o: zlib.h zconf.h
crc32.o: zlib.h zconf.h
deflate.o: deflate.h zutil.h zlib.h zconf.h
example.o: zlib.h zconf.h
gzio.o: zutil.h zlib.h zconf.h
infblock.o: infblock.h inftrees.h infcodes.h infutil.h zutil.h zlib.h zconf.h
infcodes.o: zutil.h zlib.h zconf.h
infcodes.o: inftrees.h infblock.h infcodes.h infutil.h inffast.h
inffast.o: zutil.h zlib.h zconf.h inftrees.h
inffast.o: infblock.h infcodes.h infutil.h inffast.h
inflate.o: zutil.h zlib.h zconf.h infblock.h
inftrees.o: zutil.h zlib.h zconf.h inftrees.h
infutil.o: zutil.h zlib.h zconf.h infblock.h inftrees.h infcodes.h infutil.h
minigzip.o: zlib.h zconf.h
trees.o: deflate.h zutil.h zlib.h zconf.h trees.h
uncompr.o: zlib.h zconf.h
zutil.o: zutil.h zlib.h zconf.h

143
zlib/README Normal file
View File

@@ -0,0 +1,143 @@
zlib 1.1.2 is a general purpose data compression library. All the code
is thread safe. The data format used by the zlib library
is described by RFCs (Request for Comments) 1950 to 1952 in the files
ftp://ds.internic.net/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate
format) and rfc1952.txt (gzip format). These documents are also available in
other formats from ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html
All functions of the compression library are documented in the file zlib.h
(volunteer to write man pages welcome, contact jloup@gzip.org). A usage
example of the library is given in the file example.c which also tests that
the library is working correctly. Another example is given in the file
minigzip.c. The compression library itself is composed of all source files
except example.c and minigzip.c.
To compile all files and run the test program, follow the instructions
given at the top of Makefile. In short "make test; make install"
should work for most machines. For MSDOS, use one of the special
makefiles such as Makefile.msc; for VMS, use Make_vms.com or descrip.mms.
Questions about zlib should be sent to <zlib@quest.jpl.nasa.gov> or,
if this fails, to the addresses given below in the Copyright section.
The zlib home page is http://www.cdrom.com/pub/infozip/zlib/
The official zlib ftp site is ftp://ftp.cdrom.com/pub/infozip/zlib/
Mark Nelson <markn@tiny.com> wrote an article about zlib for the Jan. 1997
issue of Dr. Dobb's Journal; a copy of the article is available in
http://web2.airmail.net/markn/articles/zlibtool/zlibtool.htm
The changes made in version 1.1.2 are documented in the file ChangeLog.
The main changes since 1.1.1 are:
- added contrib/minzip, mini zip and unzip based on zlib (Gilles Vollant)
See http://www.winimage.com/zLibDll/unzip.html
- preinitialize the inflate tables for fixed codes, to make the code
completely thread safe (Mark)
- some simplifications and slight speed-up to the inflate code (Mark)
- fix gzeof on non-compressed files (Allan Schrum)
- add -std1 option in configure for OSF1 to fix gzprintf (Martin Mokrejs)
- use default value of 4K for Z_BUFSIZE for 16-bit MSDOS (Tim Wegner + Glenn)
- added os2/Makefile.def and os2/zlib.def (Andrew Zabolotny)
- add shared lib support for UNIX_SV4.2MP (MATSUURA Takanori)
- do not wrap extern "C" around system includes (Tom Lane)
- added amiga/Makefile.pup for Amiga powerUP SAS/C PPC (Andreas Kleinert)
- allow "make install prefix=..." even after configure (Glenn Randers-Pehrson)
- allow "configure --prefix $HOME" (Tim Mooney)
Unsupported third party contributions are provided in directory "contrib".
A Java implementation of zlib is available in the Java Development Kit 1.1
http://www.javasoft.com/products/JDK/1.1/docs/api/Package-java.util.zip.html
See the zlib home page http://www.cdrom.com/pub/infozip/zlib/ for details.
A Perl interface to zlib written by Paul Marquess <pmarquess@bfsec.bt.co.uk>
is in the CPAN (Comprehensive Perl Archive Network) sites, such as:
ftp://ftp.cis.ufl.edu/pub/perl/CPAN/modules/by-module/Compress/Compress-Zlib*
A Python interface to zlib written by A.M. Kuchling <amk@magnet.com>
is available from the Python Software Association sites, such as:
ftp://ftp.python.org/pub/python/contrib/Encoding/zlib*.tar.gz
A zlib binding for TCL written by Andreas Kupries <a.kupries@westend.com>
is availlable at http://www.westend.com/~kupries/doc/trf/man/man.html
An experimental package to read and write files in .zip format,
written on top of zlib by Gilles Vollant <info@winimage.com>, is
available at http://www.winimage.com/zLibDll/unzip.html
and also in the contrib/minizip directory of zlib.
Notes for some targets:
- To build a Windows DLL version, include in a DLL project zlib.def, zlib.rc
and all .c files except example.c and minigzip.c; compile with -DZLIB_DLL
The zlib DLL support was initially done by Alessandro Iacopetti and is
now maintained by Gilles Vollant <info@winimage.com>. Check the zlib DLL
home page at http://www.winimage.com/zLibDll
From Visual Basic, you can call the DLL functions which do not take
a structure as argument: compress, uncompress and all gz* functions.
See contrib/visual-basic.txt for more information.
I don't know how to handle structures in Visual Basic, sorry.
- For 64-bit Irix, deflate.c must be compiled without any optimization.
With -O, one libpng test fails. The test works in 32 bit mode (with
the -n32 compiler flag). The compiler bug has been reported to SGI.
- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1
it works when compiled with cc.
- on Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1
is necessary to get gzprintf working correctly. This is done by configure.
- zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works
with other compilers. Use "make test" to check your compiler.
- For shared memory multiprocessors, the decompression code assumes that
writes to pointers are atomic. Also the functions zalloc and zfree passed
to deflateInit must be multi-threaded in this case.
- gzdopen is not supported on RISCOS, BEOS and by some Mac compilers.
- For Turbo C the small model is supported only with reduced performance to
avoid any far allocation; it was tested with -DMAX_WBITS=11 -DMAX_MEM_LEVEL=3
Acknowledgments:
The deflate format used by zlib was defined by Phil Katz. The deflate
and zlib specifications were written by L. Peter Deutsch. Thanks to all the
people who reported problems and suggested various improvements in zlib;
they are too numerous to cite here.
Copyright notice:
(C) 1995-1998 Jean-loup Gailly and Mark Adler
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
Jean-loup Gailly Mark Adler
jloup@gzip.org madler@alumni.caltech.edu
If you use the zlib library in a product, we would appreciate *not*
receiving lengthy legal documents to sign. The sources are provided
for free but without warranty of any kind. The library has been
entirely written by Jean-loup Gailly and Mark Adler; it does not
include third-party code.
If you redistribute modified sources, we would appreciate that you include
in the file ChangeLog history information documenting your changes.

19
zlib/README.rsync Normal file
View File

@@ -0,0 +1,19 @@
zlib has been adapted slightly for use in rsync. Please don't bother
the zlib authors with problems related to the use of zlib in rsync as
any bugs are likely to be our fault and not theirs.
Specific changes that have been made to zlib for rsync include:
- add Z_INSERT_ONLY to allow for efficient history updating without
actually emitting any data. This is used to compress the matched
blocks that don't cross the wire, which gives better compression
ratios on the literal data.
- fixed a number of minor compilation issues. (redefinition of MAX and
other such trivial things)
- include rsync.h to ensure that we get a consistent set of includes
for all C code in rsync and to take advantage of autoconf
--
Paul Mackerras and Andrew Tridgell

48
zlib/adler32.c Normal file
View File

@@ -0,0 +1,48 @@
/* adler32.c -- compute the Adler-32 checksum of a data stream
* Copyright (C) 1995-1998 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* @(#) $Id$ */
#include "zlib.h"
#define BASE 65521L /* largest prime smaller than 65536 */
#define NMAX 5552
/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
#define DO1(buf,i) {s1 += buf[i]; s2 += s1;}
#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
#define DO16(buf) DO8(buf,0); DO8(buf,8);
/* ========================================================================= */
uLong ZEXPORT adler32(adler, buf, len)
uLong adler;
const Bytef *buf;
uInt len;
{
unsigned long s1 = adler & 0xffff;
unsigned long s2 = (adler >> 16) & 0xffff;
int k;
if (buf == Z_NULL) return 1L;
while (len > 0) {
k = len < NMAX ? len : NMAX;
len -= k;
while (k >= 16) {
DO16(buf);
buf += 16;
k -= 16;
}
if (k != 0) do {
s1 += *buf++;
s2 += s1;
} while (--k);
s1 %= BASE;
s2 %= BASE;
}
return (s2 << 16) | s1;
}

162
zlib/crc32.c Normal file
View File

@@ -0,0 +1,162 @@
/* crc32.c -- compute the CRC-32 of a data stream
* Copyright (C) 1995-1998 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* @(#) $Id$ */
#include "zlib.h"
#define local static
#ifdef DYNAMIC_CRC_TABLE
local int crc_table_empty = 1;
local uLongf crc_table[256];
local void make_crc_table OF((void));
/*
Generate a table for a byte-wise 32-bit CRC calculation on the polynomial:
x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
Polynomials over GF(2) are represented in binary, one bit per coefficient,
with the lowest powers in the most significant bit. Then adding polynomials
is just exclusive-or, and multiplying a polynomial by x is a right shift by
one. If we call the above polynomial p, and represent a byte as the
polynomial q, also with the lowest power in the most significant bit (so the
byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
where a mod b means the remainder after dividing a by b.
This calculation is done using the shift-register method of multiplying and
taking the remainder. The register is initialized to zero, and for each
incoming bit, x^32 is added mod p to the register if the bit is a one (where
x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
x (which is shifting right by one and adding x^32 mod p if the bit shifted
out is a one). We start with the highest power (least significant bit) of
q and repeat for all eight bits of q.
The table is simply the CRC of all possible eight bit values. This is all
the information needed to generate CRC's on data a byte at a time for all
combinations of CRC register values and incoming bytes.
*/
local void make_crc_table()
{
uLong c;
int n, k;
uLong poly; /* polynomial exclusive-or pattern */
/* terms of polynomial defining this crc (except x^32): */
static const Byte p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
/* make exclusive-or pattern from polynomial (0xedb88320L) */
poly = 0L;
for (n = 0; n < sizeof(p)/sizeof(Byte); n++)
poly |= 1L << (31 - p[n]);
for (n = 0; n < 256; n++)
{
c = (uLong)n;
for (k = 0; k < 8; k++)
c = c & 1 ? poly ^ (c >> 1) : c >> 1;
crc_table[n] = c;
}
crc_table_empty = 0;
}
#else
/* ========================================================================
* Table of CRC-32's of all single-byte values (made by make_crc_table)
*/
local const uLongf crc_table[256] = {
0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
0x2d02ef8dL
};
#endif
/* =========================================================================
* This function can be used by asm versions of crc32()
*/
const uLongf * ZEXPORT get_crc_table()
{
#ifdef DYNAMIC_CRC_TABLE
if (crc_table_empty) make_crc_table();
#endif
return (const uLongf *)crc_table;
}
/* ========================================================================= */
#define DO1(buf) crc = crc_table[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8);
#define DO2(buf) DO1(buf); DO1(buf);
#define DO4(buf) DO2(buf); DO2(buf);
#define DO8(buf) DO4(buf); DO4(buf);
/* ========================================================================= */
uLong ZEXPORT crc32(crc, buf, len)
uLong crc;
const Bytef *buf;
uInt len;
{
if (buf == Z_NULL) return 0L;
#ifdef DYNAMIC_CRC_TABLE
if (crc_table_empty)
make_crc_table();
#endif
crc = crc ^ 0xffffffffL;
while (len >= 8)
{
DO8(buf);
len -= 8;
}
if (len) do {
DO1(buf);
} while (--len);
return crc ^ 0xffffffffL;
}

1368
zlib/deflate.c Normal file
View File

File diff suppressed because it is too large Load Diff

318
zlib/deflate.h Normal file
View File

@@ -0,0 +1,318 @@
/* deflate.h -- internal compression state
* Copyright (C) 1995-1998 Jean-loup Gailly
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* WARNING: this file should *not* be used by applications. It is
part of the implementation of the compression library and is
subject to change. Applications should only use zlib.h.
*/
/* @(#) $Id$ */
#ifndef _DEFLATE_H
#define _DEFLATE_H
#include "zutil.h"
/* ===========================================================================
* Internal compression state.
*/
#define LENGTH_CODES 29
/* number of length codes, not counting the special END_BLOCK code */
#define LITERALS 256
/* number of literal bytes 0..255 */
#define L_CODES (LITERALS+1+LENGTH_CODES)
/* number of Literal or Length codes, including the END_BLOCK code */
#define D_CODES 30
/* number of distance codes */
#define BL_CODES 19
/* number of codes used to transfer the bit lengths */
#define HEAP_SIZE (2*L_CODES+1)
/* maximum heap size */
#define MAX_BITS 15
/* All codes must not exceed MAX_BITS bits */
#define INIT_STATE 42
#define BUSY_STATE 113
#define FINISH_STATE 666
/* Stream status */
/* Data structure describing a single value and its code string. */
typedef struct ct_data_s {
union {
ush freq; /* frequency count */
ush code; /* bit string */
} fc;
union {
ush dad; /* father node in Huffman tree */
ush len; /* length of bit string */
} dl;
} FAR ct_data;
#define Freq fc.freq
#define Code fc.code
#define Dad dl.dad
#define Len dl.len
typedef struct static_tree_desc_s static_tree_desc;
typedef struct tree_desc_s {
ct_data *dyn_tree; /* the dynamic tree */
int max_code; /* largest code with non zero frequency */
static_tree_desc *stat_desc; /* the corresponding static tree */
} FAR tree_desc;
typedef ush Pos;
typedef Pos FAR Posf;
typedef unsigned IPos;
/* A Pos is an index in the character window. We use short instead of int to
* save space in the various tables. IPos is used only for parameter passing.
*/
typedef struct internal_state {
z_streamp strm; /* pointer back to this zlib stream */
int status; /* as the name implies */
Bytef *pending_buf; /* output still pending */
ulg pending_buf_size; /* size of pending_buf */
Bytef *pending_out; /* next pending byte to output to the stream */
int pending; /* nb of bytes in the pending buffer */
int noheader; /* suppress zlib header and adler32 */
Byte data_type; /* UNKNOWN, BINARY or ASCII */
Byte method; /* STORED (for zip only) or DEFLATED */
int last_flush; /* value of flush param for previous deflate call */
/* used by deflate.c: */
uInt w_size; /* LZ77 window size (32K by default) */
uInt w_bits; /* log2(w_size) (8..16) */
uInt w_mask; /* w_size - 1 */
Bytef *window;
/* Sliding window. Input bytes are read into the second half of the window,
* and move to the first half later to keep a dictionary of at least wSize
* bytes. With this organization, matches are limited to a distance of
* wSize-MAX_MATCH bytes, but this ensures that IO is always
* performed with a length multiple of the block size. Also, it limits
* the window size to 64K, which is quite useful on MSDOS.
* To do: use the user input buffer as sliding window.
*/
ulg window_size;
/* Actual size of window: 2*wSize, except when the user input buffer
* is directly used as sliding window.
*/
Posf *prev;
/* Link to older string with same hash index. To limit the size of this
* array to 64K, this link is maintained only for the last 32K strings.
* An index in this array is thus a window index modulo 32K.
*/
Posf *head; /* Heads of the hash chains or NIL. */
uInt ins_h; /* hash index of string to be inserted */
uInt hash_size; /* number of elements in hash table */
uInt hash_bits; /* log2(hash_size) */
uInt hash_mask; /* hash_size-1 */
uInt hash_shift;
/* Number of bits by which ins_h must be shifted at each input
* step. It must be such that after MIN_MATCH steps, the oldest
* byte no longer takes part in the hash key, that is:
* hash_shift * MIN_MATCH >= hash_bits
*/
long block_start;
/* Window position at the beginning of the current output block. Gets
* negative when the window is moved backwards.
*/
uInt match_length; /* length of best match */
IPos prev_match; /* previous match */
int match_available; /* set if previous match exists */
uInt strstart; /* start of string to insert */
uInt match_start; /* start of matching string */
uInt lookahead; /* number of valid bytes ahead in window */
uInt prev_length;
/* Length of the best match at previous step. Matches not greater than this
* are discarded. This is used in the lazy match evaluation.
*/
uInt max_chain_length;
/* To speed up deflation, hash chains are never searched beyond this
* length. A higher limit improves compression ratio but degrades the
* speed.
*/
uInt max_lazy_match;
/* Attempt to find a better match only when the current match is strictly
* smaller than this value. This mechanism is used only for compression
* levels >= 4.
*/
# define max_insert_length max_lazy_match
/* Insert new strings in the hash table only if the match length is not
* greater than this length. This saves time but degrades compression.
* max_insert_length is used only for compression levels <= 3.
*/
int level; /* compression level (1..9) */
int strategy; /* favor or force Huffman coding*/
uInt good_match;
/* Use a faster search when the previous match is longer than this */
int nice_match; /* Stop searching when current match exceeds this */
/* used by trees.c: */
/* Didn't use ct_data typedef below to supress compiler warning */
struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */
struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */
struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */
struct tree_desc_s l_desc; /* desc. for literal tree */
struct tree_desc_s d_desc; /* desc. for distance tree */
struct tree_desc_s bl_desc; /* desc. for bit length tree */
ush bl_count[MAX_BITS+1];
/* number of codes at each bit length for an optimal tree */
int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */
int heap_len; /* number of elements in the heap */
int heap_max; /* element of largest frequency */
/* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
* The same heap array is used to build all trees.
*/
uch depth[2*L_CODES+1];
/* Depth of each subtree used as tie breaker for trees of equal frequency
*/
uchf *l_buf; /* buffer for literals or lengths */
uInt lit_bufsize;
/* Size of match buffer for literals/lengths. There are 4 reasons for
* limiting lit_bufsize to 64K:
* - frequencies can be kept in 16 bit counters
* - if compression is not successful for the first block, all input
* data is still in the window so we can still emit a stored block even
* when input comes from standard input. (This can also be done for
* all blocks if lit_bufsize is not greater than 32K.)
* - if compression is not successful for a file smaller than 64K, we can
* even emit a stored file instead of a stored block (saving 5 bytes).
* This is applicable only for zip (not gzip or zlib).
* - creating new Huffman trees less frequently may not provide fast
* adaptation to changes in the input data statistics. (Take for
* example a binary file with poorly compressible code followed by
* a highly compressible string table.) Smaller buffer sizes give
* fast adaptation but have of course the overhead of transmitting
* trees more frequently.
* - I can't count above 4
*/
uInt last_lit; /* running index in l_buf */
ushf *d_buf;
/* Buffer for distances. To simplify the code, d_buf and l_buf have
* the same number of elements. To use different lengths, an extra flag
* array would be necessary.
*/
ulg opt_len; /* bit length of current block with optimal trees */
ulg static_len; /* bit length of current block with static trees */
ulg compressed_len; /* total bit length of compressed file */
uInt matches; /* number of string matches in current block */
int last_eob_len; /* bit length of EOB code for last block */
#ifdef DEBUG
ulg bits_sent; /* bit length of the compressed data */
#endif
ush bi_buf;
/* Output buffer. bits are inserted starting at the bottom (least
* significant bits).
*/
int bi_valid;
/* Number of valid bits in bi_buf. All bits above the last valid bit
* are always zero.
*/
} FAR deflate_state;
/* Output a byte on the stream.
* IN assertion: there is enough room in pending_buf.
*/
#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);}
#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
/* Minimum amount of lookahead, except at the end of the input file.
* See deflate.c for comments about the MIN_MATCH+1.
*/
#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD)
/* In order to simplify the code, particularly on 16 bit machines, match
* distances are limited to MAX_DIST instead of WSIZE.
*/
/* in trees.c */
void _tr_init OF((deflate_state *s));
int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc));
ulg _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len,
int eof));
void _tr_align OF((deflate_state *s));
void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len,
int eof));
#define d_code(dist) \
((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)])
/* Mapping from a distance to a distance code. dist is the distance - 1 and
* must not have side effects. _dist_code[256] and _dist_code[257] are never
* used.
*/
#ifndef DEBUG
/* Inline versions of _tr_tally for speed: */
#if defined(GEN_TREES_H) || !defined(STDC)
extern uch _length_code[];
extern uch _dist_code[];
#else
extern const uch _length_code[];
extern const uch _dist_code[];
#endif
# define _tr_tally_lit(s, c, flush) \
{ uch cc = (c); \
s->d_buf[s->last_lit] = 0; \
s->l_buf[s->last_lit++] = cc; \
s->dyn_ltree[cc].Freq++; \
flush = (s->last_lit == s->lit_bufsize-1); \
}
# define _tr_tally_dist(s, distance, length, flush) \
{ uch len = (length); \
ush dist = (distance); \
s->d_buf[s->last_lit] = dist; \
s->l_buf[s->last_lit++] = len; \
dist--; \
s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \
s->dyn_dtree[d_code(dist)].Freq++; \
flush = (s->last_lit == s->lit_bufsize-1); \
}
#else
# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c)
# define _tr_tally_dist(s, distance, length, flush) \
flush = _tr_tally(s, distance, length)
#endif
#endif

2
zlib/dummy.in Normal file
View File

@@ -0,0 +1,2 @@
This is a dummy file to ensure that the lib directory gets created
by configure when a VPATH is used.

405
zlib/infblock.c Normal file
View File

@@ -0,0 +1,405 @@
/* infblock.c -- interpret and process block types to last block
* Copyright (C) 1995-1998 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
#include "zutil.h"
#include "infblock.h"
#include "inftrees.h"
#include "infcodes.h"
#include "infutil.h"
struct inflate_codes_state {int dummy;}; /* for buggy compilers */
/* simplify the use of the inflate_huft type with some defines */
#define exop word.what.Exop
#define bits word.what.Bits
/* Table for deflate from PKZIP's appnote.txt. */
local const uInt border[] = { /* Order of the bit length code lengths */
16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
/*
Notes beyond the 1.93a appnote.txt:
1. Distance pointers never point before the beginning of the output
stream.
2. Distance pointers can point back across blocks, up to 32k away.
3. There is an implied maximum of 7 bits for the bit length table and
15 bits for the actual data.
4. If only one code exists, then it is encoded using one bit. (Zero
would be more efficient, but perhaps a little confusing.) If two
codes exist, they are coded using one bit each (0 and 1).
5. There is no way of sending zero distance codes--a dummy must be
sent if there are none. (History: a pre 2.0 version of PKZIP would
store blocks with no distance codes, but this was discovered to be
too harsh a criterion.) Valid only for 1.93a. 2.04c does allow
zero distance codes, which is sent as one code of zero bits in
length.
6. There are up to 286 literal/length codes. Code 256 represents the
end-of-block. Note however that the static length tree defines
288 codes just to fill out the Huffman codes. Codes 286 and 287
cannot be used though, since there is no length base or extra bits
defined for them. Similarily, there are up to 30 distance codes.
However, static trees define 32 codes (all 5 bits) to fill out the
Huffman codes, but the last two had better not show up in the data.
7. Unzip can check dynamic Huffman blocks for complete code sets.
The exception is that a single code would not be complete (see #4).
8. The five bits following the block type is really the number of
literal codes sent minus 257.
9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits
(1+6+6). Therefore, to output three times the length, you output
three codes (1+1+1), whereas to output four times the same length,
you only need two codes (1+3). Hmm.
10. In the tree reconstruction algorithm, Code = Code + Increment
only if BitLength(i) is not zero. (Pretty obvious.)
11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19)
12. Note: length code 284 can represent 227-258, but length code 285
really is 258. The last length deserves its own, short code
since it gets used a lot in very redundant files. The length
258 is special since 258 - 3 (the min match length) is 255.
13. The literal/length and distance code bit lengths are read as a
single stream of lengths. It is possible (and advantageous) for
a repeat code (16, 17, or 18) to go across the boundary between
the two sets of lengths.
*/
void inflate_blocks_reset(s, z, c)
inflate_blocks_statef *s;
z_streamp z;
uLongf *c;
{
if (c != Z_NULL)
*c = s->check;
if (s->mode == BTREE || s->mode == DTREE)
ZFREE(z, s->sub.trees.blens);
if (s->mode == CODES)
inflate_codes_free(s->sub.decode.codes, z);
s->mode = TYPE;
s->bitk = 0;
s->bitb = 0;
s->read = s->write = s->window;
if (s->checkfn != Z_NULL)
z->adler = s->check = (*s->checkfn)(0L, (const Bytef *)Z_NULL, 0);
Tracev((stderr, "inflate: blocks reset\n"));
}
inflate_blocks_statef *inflate_blocks_new(z, c, w)
z_streamp z;
check_func c;
uInt w;
{
inflate_blocks_statef *s;
if ((s = (inflate_blocks_statef *)ZALLOC
(z,1,sizeof(struct inflate_blocks_state))) == Z_NULL)
return s;
if ((s->hufts =
(inflate_huft *)ZALLOC(z, sizeof(inflate_huft), MANY)) == Z_NULL)
{
ZFREE(z, s);
return Z_NULL;
}
if ((s->window = (Bytef *)ZALLOC(z, 1, w)) == Z_NULL)
{
ZFREE(z, s->hufts);
ZFREE(z, s);
return Z_NULL;
}
s->end = s->window + w;
s->checkfn = c;
s->mode = TYPE;
Tracev((stderr, "inflate: blocks allocated\n"));
inflate_blocks_reset(s, z, Z_NULL);
return s;
}
int inflate_blocks(s, z, r)
inflate_blocks_statef *s;
z_streamp z;
int r;
{
uInt t; /* temporary storage */
uLong b; /* bit buffer */
uInt k; /* bits in bit buffer */
Bytef *p; /* input data pointer */
uInt n; /* bytes available there */
Bytef *q; /* output window write pointer */
uInt m; /* bytes to end of window or read pointer */
/* copy input/output information to locals (UPDATE macro restores) */
LOAD
/* process input based on current state */
while (1) switch (s->mode)
{
case TYPE:
NEEDBITS(3)
t = (uInt)b & 7;
s->last = t & 1;
switch (t >> 1)
{
case 0: /* stored */
Tracev((stderr, "inflate: stored block%s\n",
s->last ? " (last)" : ""));
DUMPBITS(3)
t = k & 7; /* go to byte boundary */
DUMPBITS(t)
s->mode = LENS; /* get length of stored block */
break;
case 1: /* fixed */
Tracev((stderr, "inflate: fixed codes block%s\n",
s->last ? " (last)" : ""));
{
uInt bl, bd;
inflate_huft *tl, *td;
inflate_trees_fixed(&bl, &bd, &tl, &td, z);
s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z);
if (s->sub.decode.codes == Z_NULL)
{
r = Z_MEM_ERROR;
LEAVE
}
}
DUMPBITS(3)
s->mode = CODES;
break;
case 2: /* dynamic */
Tracev((stderr, "inflate: dynamic codes block%s\n",
s->last ? " (last)" : ""));
DUMPBITS(3)
s->mode = TABLE;
break;
case 3: /* illegal */
DUMPBITS(3)
s->mode = zBAD;
z->msg = (char*)"invalid block type";
r = Z_DATA_ERROR;
LEAVE
}
break;
case LENS:
NEEDBITS(32)
if ((((~b) >> 16) & 0xffff) != (b & 0xffff))
{
s->mode = zBAD;
z->msg = (char*)"invalid stored block lengths";
r = Z_DATA_ERROR;
LEAVE
}
s->sub.left = (uInt)b & 0xffff;
b = k = 0; /* dump bits */
Tracev((stderr, "inflate: stored length %u\n", s->sub.left));
s->mode = s->sub.left ? STORED : (s->last ? DRY : TYPE);
break;
case STORED:
if (n == 0)
LEAVE
NEEDOUT
t = s->sub.left;
if (t > n) t = n;
if (t > m) t = m;
zmemcpy(q, p, t);
p += t; n -= t;
q += t; m -= t;
if ((s->sub.left -= t) != 0)
break;
Tracev((stderr, "inflate: stored end, %lu total out\n",
z->total_out + (q >= s->read ? q - s->read :
(s->end - s->read) + (q - s->window))));
s->mode = s->last ? DRY : TYPE;
break;
case TABLE:
NEEDBITS(14)
s->sub.trees.table = t = (uInt)b & 0x3fff;
#ifndef PKZIP_BUG_WORKAROUND
if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29)
{
s->mode = zBAD;
z->msg = (char*)"too many length or distance symbols";
r = Z_DATA_ERROR;
LEAVE
}
#endif
t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);
if ((s->sub.trees.blens = (uIntf*)ZALLOC(z, t, sizeof(uInt))) == Z_NULL)
{
r = Z_MEM_ERROR;
LEAVE
}
DUMPBITS(14)
s->sub.trees.index = 0;
Tracev((stderr, "inflate: table sizes ok\n"));
s->mode = BTREE;
case BTREE:
while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10))
{
NEEDBITS(3)
s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7;
DUMPBITS(3)
}
while (s->sub.trees.index < 19)
s->sub.trees.blens[border[s->sub.trees.index++]] = 0;
s->sub.trees.bb = 7;
t = inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb,
&s->sub.trees.tb, s->hufts, z);
if (t != Z_OK)
{
ZFREE(z, s->sub.trees.blens);
r = t;
if (r == Z_DATA_ERROR)
s->mode = zBAD;
LEAVE
}
s->sub.trees.index = 0;
Tracev((stderr, "inflate: bits tree ok\n"));
s->mode = DTREE;
case DTREE:
while (t = s->sub.trees.table,
s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f))
{
inflate_huft *h;
uInt i, j, c;
t = s->sub.trees.bb;
NEEDBITS(t)
h = s->sub.trees.tb + ((uInt)b & inflate_mask[t]);
t = h->bits;
c = h->base;
if (c < 16)
{
DUMPBITS(t)
s->sub.trees.blens[s->sub.trees.index++] = c;
}
else /* c == 16..18 */
{
i = c == 18 ? 7 : c - 14;
j = c == 18 ? 11 : 3;
NEEDBITS(t + i)
DUMPBITS(t)
j += (uInt)b & inflate_mask[i];
DUMPBITS(i)
i = s->sub.trees.index;
t = s->sub.trees.table;
if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) ||
(c == 16 && i < 1))
{
ZFREE(z, s->sub.trees.blens);
s->mode = zBAD;
z->msg = (char*)"invalid bit length repeat";
r = Z_DATA_ERROR;
LEAVE
}
c = c == 16 ? s->sub.trees.blens[i - 1] : 0;
do {
s->sub.trees.blens[i++] = c;
} while (--j);
s->sub.trees.index = i;
}
}
s->sub.trees.tb = Z_NULL;
{
uInt bl, bd;
inflate_huft *tl, *td;
inflate_codes_statef *c;
bl = 9; /* must be <= 9 for lookahead assumptions */
bd = 6; /* must be <= 9 for lookahead assumptions */
t = s->sub.trees.table;
t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f),
s->sub.trees.blens, &bl, &bd, &tl, &td,
s->hufts, z);
ZFREE(z, s->sub.trees.blens);
if (t != Z_OK)
{
if (t == (uInt)Z_DATA_ERROR)
s->mode = zBAD;
r = t;
LEAVE
}
Tracev((stderr, "inflate: trees ok\n"));
if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL)
{
r = Z_MEM_ERROR;
LEAVE
}
s->sub.decode.codes = c;
}
s->mode = CODES;
case CODES:
UPDATE
if ((r = inflate_codes(s, z, r)) != Z_STREAM_END)
return inflate_flush(s, z, r);
r = Z_OK;
inflate_codes_free(s->sub.decode.codes, z);
LOAD
Tracev((stderr, "inflate: codes end, %lu total out\n",
z->total_out + (q >= s->read ? q - s->read :
(s->end - s->read) + (q - s->window))));
if (!s->last)
{
s->mode = TYPE;
break;
}
if (k > 7) /* return unused byte, if any */
{
Assert(k < 16, "inflate_codes grabbed too many bytes")
k -= 8;
n++;
p--; /* can always return one */
}
s->mode = DRY;
case DRY:
FLUSH
if (s->read != s->write)
LEAVE
s->mode = DONE;
case DONE:
r = Z_STREAM_END;
LEAVE
case zBAD:
r = Z_DATA_ERROR;
LEAVE
default:
r = Z_STREAM_ERROR;
LEAVE
}
}
int inflate_blocks_free(s, z)
inflate_blocks_statef *s;
z_streamp z;
{
inflate_blocks_reset(s, z, Z_NULL);
ZFREE(z, s->window);
ZFREE(z, s->hufts);
ZFREE(z, s);
Tracev((stderr, "inflate: blocks freed\n"));
return Z_OK;
}
void inflate_set_dictionary(s, d, n)
inflate_blocks_statef *s;
const Bytef *d;
uInt n;
{
zmemcpy(s->window, d, n);
s->read = s->write = s->window + n;
}
/* Returns true if inflate is currently at the end of a block generated
* by Z_SYNC_FLUSH or Z_FULL_FLUSH.
* IN assertion: s != Z_NULL
*/
int inflate_blocks_sync_point(s)
inflate_blocks_statef *s;
{
return s->mode == LENS;
}

39
zlib/infblock.h Normal file
View File

@@ -0,0 +1,39 @@
/* infblock.h -- header to use infblock.c
* Copyright (C) 1995-1998 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* WARNING: this file should *not* be used by applications. It is
part of the implementation of the compression library and is
subject to change. Applications should only use zlib.h.
*/
struct inflate_blocks_state;
typedef struct inflate_blocks_state FAR inflate_blocks_statef;
extern inflate_blocks_statef * inflate_blocks_new OF((
z_streamp z,
check_func c, /* check function */
uInt w)); /* window size */
extern int inflate_blocks OF((
inflate_blocks_statef *,
z_streamp ,
int)); /* initial return code */
extern void inflate_blocks_reset OF((
inflate_blocks_statef *,
z_streamp ,
uLongf *)); /* check value on output */
extern int inflate_blocks_free OF((
inflate_blocks_statef *,
z_streamp));
extern void inflate_set_dictionary OF((
inflate_blocks_statef *s,
const Bytef *d, /* dictionary */
uInt n)); /* dictionary length */
extern int inflate_blocks_sync_point OF((
inflate_blocks_statef *s));

250
zlib/infcodes.c Normal file
View File

@@ -0,0 +1,250 @@
/* infcodes.c -- process literals and length/distance pairs
* Copyright (C) 1995-1998 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
#include "zutil.h"
#include "inftrees.h"
#include "infblock.h"
#include "infcodes.h"
#include "infutil.h"
#include "inffast.h"
/* simplify the use of the inflate_huft type with some defines */
#define exop word.what.Exop
#define bits word.what.Bits
typedef enum { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
START, /* x: set up for LEN */
LEN, /* i: get length/literal/eob next */
LENEXT, /* i: getting length extra (have base) */
DIST, /* i: get distance next */
DISTEXT, /* i: getting distance extra */
COPY, /* o: copying bytes in window, waiting for space */
LIT, /* o: got literal, waiting for output space */
WASH, /* o: got eob, possibly still output waiting */
END, /* x: got eob and all data flushed */
BADCODE} /* x: got error */
inflate_codes_mode;
/* inflate codes private state */
struct inflate_codes_state {
/* mode */
inflate_codes_mode mode; /* current inflate_codes mode */
/* mode dependent information */
uInt len;
union {
struct {
inflate_huft *tree; /* pointer into tree */
uInt need; /* bits needed */
} code; /* if LEN or DIST, where in tree */
uInt lit; /* if LIT, literal */
struct {
uInt get; /* bits to get for extra */
uInt dist; /* distance back to copy from */
} copy; /* if EXT or COPY, where and how much */
} sub; /* submode */
/* mode independent information */
Byte lbits; /* ltree bits decoded per branch */
Byte dbits; /* dtree bits decoder per branch */
inflate_huft *ltree; /* literal/length/eob tree */
inflate_huft *dtree; /* distance tree */
};
inflate_codes_statef *inflate_codes_new(bl, bd, tl, td, z)
uInt bl, bd;
inflate_huft *tl;
inflate_huft *td; /* need separate declaration for Borland C++ */
z_streamp z;
{
inflate_codes_statef *c;
if ((c = (inflate_codes_statef *)
ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL)
{
c->mode = START;
c->lbits = (Byte)bl;
c->dbits = (Byte)bd;
c->ltree = tl;
c->dtree = td;
Tracev((stderr, "inflate: codes new\n"));
}
return c;
}
int inflate_codes(s, z, r)
inflate_blocks_statef *s;
z_streamp z;
int r;
{
uInt j; /* temporary storage */
inflate_huft *t; /* temporary pointer */
uInt e; /* extra bits or operation */
uLong b; /* bit buffer */
uInt k; /* bits in bit buffer */
Bytef *p; /* input data pointer */
uInt n; /* bytes available there */
Bytef *q; /* output window write pointer */
uInt m; /* bytes to end of window or read pointer */
Bytef *f; /* pointer to copy strings from */
inflate_codes_statef *c = s->sub.decode.codes; /* codes state */
/* copy input/output information to locals (UPDATE macro restores) */
LOAD
/* process input and output based on current state */
while (1) switch (c->mode)
{ /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
case START: /* x: set up for LEN */
#ifndef SLOW
if (m >= 258 && n >= 10)
{
UPDATE
r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z);
LOAD
if (r != Z_OK)
{
c->mode = r == Z_STREAM_END ? WASH : BADCODE;
break;
}
}
#endif /* !SLOW */
c->sub.code.need = c->lbits;
c->sub.code.tree = c->ltree;
c->mode = LEN;
case LEN: /* i: get length/literal/eob next */
j = c->sub.code.need;
NEEDBITS(j)
t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
DUMPBITS(t->bits)
e = (uInt)(t->exop);
if (e == 0) /* literal */
{
c->sub.lit = t->base;
Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
"inflate: literal '%c'\n" :
"inflate: literal 0x%02x\n", t->base));
c->mode = LIT;
break;
}
if (e & 16) /* length */
{
c->sub.copy.get = e & 15;
c->len = t->base;
c->mode = LENEXT;
break;
}
if ((e & 64) == 0) /* next table */
{
c->sub.code.need = e;
c->sub.code.tree = t + t->base;
break;
}
if (e & 32) /* end of block */
{
Tracevv((stderr, "inflate: end of block\n"));
c->mode = WASH;
break;
}
c->mode = BADCODE; /* invalid code */
z->msg = (char*)"invalid literal/length code";
r = Z_DATA_ERROR;
LEAVE
case LENEXT: /* i: getting length extra (have base) */
j = c->sub.copy.get;
NEEDBITS(j)
c->len += (uInt)b & inflate_mask[j];
DUMPBITS(j)
c->sub.code.need = c->dbits;
c->sub.code.tree = c->dtree;
Tracevv((stderr, "inflate: length %u\n", c->len));
c->mode = DIST;
case DIST: /* i: get distance next */
j = c->sub.code.need;
NEEDBITS(j)
t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
DUMPBITS(t->bits)
e = (uInt)(t->exop);
if (e & 16) /* distance */
{
c->sub.copy.get = e & 15;
c->sub.copy.dist = t->base;
c->mode = DISTEXT;
break;
}
if ((e & 64) == 0) /* next table */
{
c->sub.code.need = e;
c->sub.code.tree = t + t->base;
break;
}
c->mode = BADCODE; /* invalid code */
z->msg = (char*)"invalid distance code";
r = Z_DATA_ERROR;
LEAVE
case DISTEXT: /* i: getting distance extra */
j = c->sub.copy.get;
NEEDBITS(j)
c->sub.copy.dist += (uInt)b & inflate_mask[j];
DUMPBITS(j)
Tracevv((stderr, "inflate: distance %u\n", c->sub.copy.dist));
c->mode = COPY;
case COPY: /* o: copying bytes in window, waiting for space */
#ifndef __TURBOC__ /* Turbo C bug for following expression */
f = (uInt)(q - s->window) < c->sub.copy.dist ?
s->end - (c->sub.copy.dist - (q - s->window)) :
q - c->sub.copy.dist;
#else
f = q - c->sub.copy.dist;
if ((uInt)(q - s->window) < c->sub.copy.dist)
f = s->end - (c->sub.copy.dist - (uInt)(q - s->window));
#endif
while (c->len)
{
NEEDOUT
OUTBYTE(*f++)
if (f == s->end)
f = s->window;
c->len--;
}
c->mode = START;
break;
case LIT: /* o: got literal, waiting for output space */
NEEDOUT
OUTBYTE(c->sub.lit)
c->mode = START;
break;
case WASH: /* o: got eob, possibly more output */
FLUSH
if (s->read != s->write)
LEAVE
c->mode = END;
case END:
r = Z_STREAM_END;
LEAVE
case BADCODE: /* x: got error */
r = Z_DATA_ERROR;
LEAVE
default:
r = Z_STREAM_ERROR;
LEAVE
}
#ifdef NEED_DUMMY_RETURN
return Z_STREAM_ERROR; /* Some dumb compilers complain without this */
#endif
}
void inflate_codes_free(c, z)
inflate_codes_statef *c;
z_streamp z;
{
ZFREE(z, c);
Tracev((stderr, "inflate: codes free\n"));
}

27
zlib/infcodes.h Normal file
View File

@@ -0,0 +1,27 @@
/* infcodes.h -- header to use infcodes.c
* Copyright (C) 1995-1998 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* WARNING: this file should *not* be used by applications. It is
part of the implementation of the compression library and is
subject to change. Applications should only use zlib.h.
*/
struct inflate_codes_state;
typedef struct inflate_codes_state FAR inflate_codes_statef;
extern inflate_codes_statef *inflate_codes_new OF((
uInt, uInt,
inflate_huft *, inflate_huft *,
z_streamp ));
extern int inflate_codes OF((
inflate_blocks_statef *,
z_streamp ,
int));
extern void inflate_codes_free OF((
inflate_codes_statef *,
z_streamp ));

170
zlib/inffast.c Normal file
View File

@@ -0,0 +1,170 @@
/* inffast.c -- process literals and length/distance pairs fast
* Copyright (C) 1995-1998 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
#include "zutil.h"
#include "inftrees.h"
#include "infblock.h"
#include "infcodes.h"
#include "infutil.h"
#include "inffast.h"
struct inflate_codes_state {int dummy;}; /* for buggy compilers */
/* simplify the use of the inflate_huft type with some defines */
#define exop word.what.Exop
#define bits word.what.Bits
/* macros for bit input with no checking and for returning unused bytes */
#define GRABBITS(j) {while(k<(j)){b|=((uLong)NEXTBYTE)<<k;k+=8;}}
#define UNGRAB {c=z->avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;}
/* Called with number of bytes left to write in window at least 258
(the maximum string length) and number of input bytes available
at least ten. The ten bytes are six bytes for the longest length/
distance pair plus four bytes for overloading the bit buffer. */
int inflate_fast(bl, bd, tl, td, s, z)
uInt bl, bd;
inflate_huft *tl;
inflate_huft *td; /* need separate declaration for Borland C++ */
inflate_blocks_statef *s;
z_streamp z;
{
inflate_huft *t; /* temporary pointer */
uInt e; /* extra bits or operation */
uLong b; /* bit buffer */
uInt k; /* bits in bit buffer */
Bytef *p; /* input data pointer */
uInt n; /* bytes available there */
Bytef *q; /* output window write pointer */
uInt m; /* bytes to end of window or read pointer */
uInt ml; /* mask for literal/length tree */
uInt md; /* mask for distance tree */
uInt c; /* bytes to copy */
uInt d; /* distance back to copy from */
Bytef *r; /* copy source pointer */
/* load input, output, bit values */
LOAD
/* initialize masks */
ml = inflate_mask[bl];
md = inflate_mask[bd];
/* do until not enough input or output space for fast loop */
do { /* assume called with m >= 258 && n >= 10 */
/* get literal/length code */
GRABBITS(20) /* max bits for literal/length code */
if ((e = (t = tl + ((uInt)b & ml))->exop) == 0)
{
DUMPBITS(t->bits)
Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
"inflate: * literal '%c'\n" :
"inflate: * literal 0x%02x\n", t->base));
*q++ = (Byte)t->base;
m--;
continue;
}
do {
DUMPBITS(t->bits)
if (e & 16)
{
/* get extra bits for length */
e &= 15;
c = t->base + ((uInt)b & inflate_mask[e]);
DUMPBITS(e)
Tracevv((stderr, "inflate: * length %u\n", c));
/* decode distance base of block to copy */
GRABBITS(15); /* max bits for distance code */
e = (t = td + ((uInt)b & md))->exop;
do {
DUMPBITS(t->bits)
if (e & 16)
{
/* get extra bits to add to distance base */
e &= 15;
GRABBITS(e) /* get extra bits (up to 13) */
d = t->base + ((uInt)b & inflate_mask[e]);
DUMPBITS(e)
Tracevv((stderr, "inflate: * distance %u\n", d));
/* do the copy */
m -= c;
if ((uInt)(q - s->window) >= d) /* offset before dest */
{ /* just copy */
r = q - d;
*q++ = *r++; c--; /* minimum count is three, */
*q++ = *r++; c--; /* so unroll loop a little */
}
else /* else offset after destination */
{
e = d - (uInt)(q - s->window); /* bytes from offset to end */
r = s->end - e; /* pointer to offset */
if (c > e) /* if source crosses, */
{
c -= e; /* copy to end of window */
do {
*q++ = *r++;
} while (--e);
r = s->window; /* copy rest from start of window */
}
}
do { /* copy all or what's left */
*q++ = *r++;
} while (--c);
break;
}
else if ((e & 64) == 0)
{
t += t->base;
e = (t += ((uInt)b & inflate_mask[e]))->exop;
}
else
{
z->msg = (char*)"invalid distance code";
UNGRAB
UPDATE
return Z_DATA_ERROR;
}
} while (1);
break;
}
if ((e & 64) == 0)
{
t += t->base;
if ((e = (t += ((uInt)b & inflate_mask[e]))->exop) == 0)
{
DUMPBITS(t->bits)
Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
"inflate: * literal '%c'\n" :
"inflate: * literal 0x%02x\n", t->base));
*q++ = (Byte)t->base;
m--;
break;
}
}
else if (e & 32)
{
Tracevv((stderr, "inflate: * end of block\n"));
UNGRAB
UPDATE
return Z_STREAM_END;
}
else
{
z->msg = (char*)"invalid literal/length code";
UNGRAB
UPDATE
return Z_DATA_ERROR;
}
} while (1);
} while (m >= 258 && n >= 10);
/* not enough input or output--restore pointers and return */
UNGRAB
UPDATE
return Z_OK;
}

17
zlib/inffast.h Normal file
View File

@@ -0,0 +1,17 @@
/* inffast.h -- header to use inffast.c
* Copyright (C) 1995-1998 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* WARNING: this file should *not* be used by applications. It is
part of the implementation of the compression library and is
subject to change. Applications should only use zlib.h.
*/
extern int inflate_fast OF((
uInt,
uInt,
inflate_huft *,
inflate_huft *,
inflate_blocks_statef *,
z_streamp ));

125
zlib/inffixed.h Normal file
View File

@@ -0,0 +1,125 @@
/* inffixed.h -- table for decoding fixed codes
* Generated automatically by the maketree.c program
*/
/* WARNING: this file should *not* be used by applications. It is
part of the implementation of the compression library and is
subject to change. Applications should only use zlib.h.
*/
local uInt fixed_bl = 9;
local uInt fixed_bd = 5;
local inflate_huft fixed_tl[] = {
{{96,7},256}, {{0,8},80}, {{0,8},16}, {{84,8},115}, {{82,7},31},
{{0,8},112}, {{0,8},48}, {{0,9},192}, {{80,7},10}, {{0,8},96},
{{0,8},32}, {{0,9},160}, {{0,8},0}, {{0,8},128}, {{0,8},64},
{{0,9},224}, {{80,7},6}, {{0,8},88}, {{0,8},24}, {{0,9},144},
{{83,7},59}, {{0,8},120}, {{0,8},56}, {{0,9},208}, {{81,7},17},
{{0,8},104}, {{0,8},40}, {{0,9},176}, {{0,8},8}, {{0,8},136},
{{0,8},72}, {{0,9},240}, {{80,7},4}, {{0,8},84}, {{0,8},20},
{{85,8},227}, {{83,7},43}, {{0,8},116}, {{0,8},52}, {{0,9},200},
{{81,7},13}, {{0,8},100}, {{0,8},36}, {{0,9},168}, {{0,8},4},
{{0,8},132}, {{0,8},68}, {{0,9},232}, {{80,7},8}, {{0,8},92},
{{0,8},28}, {{0,9},152}, {{84,7},83}, {{0,8},124}, {{0,8},60},
{{0,9},216}, {{82,7},23}, {{0,8},108}, {{0,8},44}, {{0,9},184},
{{0,8},12}, {{0,8},140}, {{0,8},76}, {{0,9},248}, {{80,7},3},
{{0,8},82}, {{0,8},18}, {{85,8},163}, {{83,7},35}, {{0,8},114},
{{0,8},50}, {{0,9},196}, {{81,7},11}, {{0,8},98}, {{0,8},34},
{{0,9},164}, {{0,8},2}, {{0,8},130}, {{0,8},66}, {{0,9},228},
{{80,7},7}, {{0,8},90}, {{0,8},26}, {{0,9},148}, {{84,7},67},
{{0,8},122}, {{0,8},58}, {{0,9},212}, {{82,7},19}, {{0,8},106},
{{0,8},42}, {{0,9},180}, {{0,8},10}, {{0,8},138}, {{0,8},74},
{{0,9},244}, {{80,7},5}, {{0,8},86}, {{0,8},22}, {{192,8},0},
{{83,7},51}, {{0,8},118}, {{0,8},54}, {{0,9},204}, {{81,7},15},
{{0,8},102}, {{0,8},38}, {{0,9},172}, {{0,8},6}, {{0,8},134},
{{0,8},70}, {{0,9},236}, {{80,7},9}, {{0,8},94}, {{0,8},30},
{{0,9},156}, {{84,7},99}, {{0,8},126}, {{0,8},62}, {{0,9},220},
{{82,7},27}, {{0,8},110}, {{0,8},46}, {{0,9},188}, {{0,8},14},
{{0,8},142}, {{0,8},78}, {{0,9},252}, {{96,7},256}, {{0,8},81},
{{0,8},17}, {{85,8},131}, {{82,7},31}, {{0,8},113}, {{0,8},49},
{{0,9},194}, {{80,7},10}, {{0,8},97}, {{0,8},33}, {{0,9},162},
{{0,8},1}, {{0,8},129}, {{0,8},65}, {{0,9},226}, {{80,7},6},
{{0,8},89}, {{0,8},25}, {{0,9},146}, {{83,7},59}, {{0,8},121},
{{0,8},57}, {{0,9},210}, {{81,7},17}, {{0,8},105}, {{0,8},41},
{{0,9},178}, {{0,8},9}, {{0,8},137}, {{0,8},73}, {{0,9},242},
{{80,7},4}, {{0,8},85}, {{0,8},21}, {{80,8},258}, {{83,7},43},
{{0,8},117}, {{0,8},53}, {{0,9},202}, {{81,7},13}, {{0,8},101},
{{0,8},37}, {{0,9},170}, {{0,8},5}, {{0,8},133}, {{0,8},69},
{{0,9},234}, {{80,7},8}, {{0,8},93}, {{0,8},29}, {{0,9},154},
{{84,7},83}, {{0,8},125}, {{0,8},61}, {{0,9},218}, {{82,7},23},
{{0,8},109}, {{0,8},45}, {{0,9},186}, {{0,8},13}, {{0,8},141},
{{0,8},77}, {{0,9},250}, {{80,7},3}, {{0,8},83}, {{0,8},19},
{{85,8},195}, {{83,7},35}, {{0,8},115}, {{0,8},51}, {{0,9},198},
{{81,7},11}, {{0,8},99}, {{0,8},35}, {{0,9},166}, {{0,8},3},
{{0,8},131}, {{0,8},67}, {{0,9},230}, {{80,7},7}, {{0,8},91},
{{0,8},27}, {{0,9},150}, {{84,7},67}, {{0,8},123}, {{0,8},59},
{{0,9},214}, {{82,7},19}, {{0,8},107}, {{0,8},43}, {{0,9},182},
{{0,8},11}, {{0,8},139}, {{0,8},75}, {{0,9},246}, {{80,7},5},
{{0,8},87}, {{0,8},23}, {{192,8},0}, {{83,7},51}, {{0,8},119},
{{0,8},55}, {{0,9},206}, {{81,7},15}, {{0,8},103}, {{0,8},39},
{{0,9},174}, {{0,8},7}, {{0,8},135}, {{0,8},71}, {{0,9},238},
{{80,7},9}, {{0,8},95}, {{0,8},31}, {{0,9},158}, {{84,7},99},
{{0,8},127}, {{0,8},63}, {{0,9},222}, {{82,7},27}, {{0,8},111},
{{0,8},47}, {{0,9},190}, {{0,8},15}, {{0,8},143}, {{0,8},79},
{{0,9},254}, {{96,7},256}, {{0,8},80}, {{0,8},16}, {{84,8},115},
{{82,7},31}, {{0,8},112}, {{0,8},48}, {{0,9},193}, {{80,7},10},
{{0,8},96}, {{0,8},32}, {{0,9},161}, {{0,8},0}, {{0,8},128},
{{0,8},64}, {{0,9},225}, {{80,7},6}, {{0,8},88}, {{0,8},24},
{{0,9},145}, {{83,7},59}, {{0,8},120}, {{0,8},56}, {{0,9},209},
{{81,7},17}, {{0,8},104}, {{0,8},40}, {{0,9},177}, {{0,8},8},
{{0,8},136}, {{0,8},72}, {{0,9},241}, {{80,7},4}, {{0,8},84},
{{0,8},20}, {{85,8},227}, {{83,7},43}, {{0,8},116}, {{0,8},52},
{{0,9},201}, {{81,7},13}, {{0,8},100}, {{0,8},36}, {{0,9},169},
{{0,8},4}, {{0,8},132}, {{0,8},68}, {{0,9},233}, {{80,7},8},
{{0,8},92}, {{0,8},28}, {{0,9},153}, {{84,7},83}, {{0,8},124},
{{0,8},60}, {{0,9},217}, {{82,7},23}, {{0,8},108}, {{0,8},44},
{{0,9},185}, {{0,8},12}, {{0,8},140}, {{0,8},76}, {{0,9},249},
{{80,7},3}, {{0,8},82}, {{0,8},18}, {{85,8},163}, {{83,7},35},
{{0,8},114}, {{0,8},50}, {{0,9},197}, {{81,7},11}, {{0,8},98},
{{0,8},34}, {{0,9},165}, {{0,8},2}, {{0,8},130}, {{0,8},66},
{{0,9},229}, {{80,7},7}, {{0,8},90}, {{0,8},26}, {{0,9},149},
{{84,7},67}, {{0,8},122}, {{0,8},58}, {{0,9},213}, {{82,7},19},
{{0,8},106}, {{0,8},42}, {{0,9},181}, {{0,8},10}, {{0,8},138},
{{0,8},74}, {{0,9},245}, {{80,7},5}, {{0,8},86}, {{0,8},22},
{{192,8},0}, {{83,7},51}, {{0,8},118}, {{0,8},54}, {{0,9},205},
{{81,7},15}, {{0,8},102}, {{0,8},38}, {{0,9},173}, {{0,8},6},
{{0,8},134}, {{0,8},70}, {{0,9},237}, {{80,7},9}, {{0,8},94},
{{0,8},30}, {{0,9},157}, {{84,7},99}, {{0,8},126}, {{0,8},62},
{{0,9},221}, {{82,7},27}, {{0,8},110}, {{0,8},46}, {{0,9},189},
{{0,8},14}, {{0,8},142}, {{0,8},78}, {{0,9},253}, {{96,7},256},
{{0,8},81}, {{0,8},17}, {{85,8},131}, {{82,7},31}, {{0,8},113},
{{0,8},49}, {{0,9},195}, {{80,7},10}, {{0,8},97}, {{0,8},33},
{{0,9},163}, {{0,8},1}, {{0,8},129}, {{0,8},65}, {{0,9},227},
{{80,7},6}, {{0,8},89}, {{0,8},25}, {{0,9},147}, {{83,7},59},
{{0,8},121}, {{0,8},57}, {{0,9},211}, {{81,7},17}, {{0,8},105},
{{0,8},41}, {{0,9},179}, {{0,8},9}, {{0,8},137}, {{0,8},73},
{{0,9},243}, {{80,7},4}, {{0,8},85}, {{0,8},21}, {{80,8},258},
{{83,7},43}, {{0,8},117}, {{0,8},53}, {{0,9},203}, {{81,7},13},
{{0,8},101}, {{0,8},37}, {{0,9},171}, {{0,8},5}, {{0,8},133},
{{0,8},69}, {{0,9},235}, {{80,7},8}, {{0,8},93}, {{0,8},29},
{{0,9},155}, {{84,7},83}, {{0,8},125}, {{0,8},61}, {{0,9},219},
{{82,7},23}, {{0,8},109}, {{0,8},45}, {{0,9},187}, {{0,8},13},
{{0,8},141}, {{0,8},77}, {{0,9},251}, {{80,7},3}, {{0,8},83},
{{0,8},19}, {{85,8},195}, {{83,7},35}, {{0,8},115}, {{0,8},51},
{{0,9},199}, {{81,7},11}, {{0,8},99}, {{0,8},35}, {{0,9},167},
{{0,8},3}, {{0,8},131}, {{0,8},67}, {{0,9},231}, {{80,7},7},
{{0,8},91}, {{0,8},27}, {{0,9},151}, {{84,7},67}, {{0,8},123},
{{0,8},59}, {{0,9},215}, {{82,7},19}, {{0,8},107}, {{0,8},43},
{{0,9},183}, {{0,8},11}, {{0,8},139}, {{0,8},75}, {{0,9},247},
{{80,7},5}, {{0,8},87}, {{0,8},23}, {{192,8},0}, {{83,7},51},
{{0,8},119}, {{0,8},55}, {{0,9},207}, {{81,7},15}, {{0,8},103},
{{0,8},39}, {{0,9},175}, {{0,8},7}, {{0,8},135}, {{0,8},71},
{{0,9},239}, {{80,7},9}, {{0,8},95}, {{0,8},31}, {{0,9},159},
{{84,7},99}, {{0,8},127}, {{0,8},63}, {{0,9},223}, {{82,7},27},
{{0,8},111}, {{0,8},47}, {{0,9},191}, {{0,8},15}, {{0,8},143},
{{0,8},79}, {{0,9},255}
};
local inflate_huft fixed_td[] = {
{{80,5},1}, {{87,5},257}, {{83,5},17}, {{91,5},4097}, {{81,5},5},
{{89,5},1025}, {{85,5},65}, {{93,5},16385}, {{80,5},3}, {{88,5},513},
{{84,5},33}, {{92,5},8193}, {{82,5},9}, {{90,5},2049}, {{86,5},129},
{{192,5},24577}, {{80,5},2}, {{87,5},385}, {{83,5},25}, {{91,5},6145},
{{81,5},7}, {{89,5},1537}, {{85,5},97}, {{93,5},24577}, {{80,5},4},
{{88,5},769}, {{84,5},49}, {{92,5},12289}, {{82,5},13}, {{90,5},3073},
{{86,5},193}, {{192,5},24577}
};

366
zlib/inflate.c Normal file
View File

@@ -0,0 +1,366 @@
/* inflate.c -- zlib interface to inflate modules
* Copyright (C) 1995-1998 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
#include "zutil.h"
#include "infblock.h"
struct inflate_blocks_state {int dummy;}; /* for buggy compilers */
typedef enum {
METHOD, /* waiting for method byte */
FLAG, /* waiting for flag byte */
DICT4, /* four dictionary check bytes to go */
DICT3, /* three dictionary check bytes to go */
DICT2, /* two dictionary check bytes to go */
DICT1, /* one dictionary check byte to go */
DICT0, /* waiting for inflateSetDictionary */
BLOCKS, /* decompressing blocks */
CHECK4, /* four check bytes to go */
CHECK3, /* three check bytes to go */
CHECK2, /* two check bytes to go */
CHECK1, /* one check byte to go */
DONE, /* finished check, done */
zBAD} /* got an error--stay here */
inflate_mode;
/* inflate private state */
struct internal_state {
/* mode */
inflate_mode mode; /* current inflate mode */
/* mode dependent information */
union {
uInt method; /* if FLAGS, method byte */
struct {
uLong was; /* computed check value */
uLong need; /* stream check value */
} check; /* if CHECK, check values to compare */
uInt marker; /* if zBAD, inflateSync's marker bytes count */
} sub; /* submode */
/* mode independent information */
int nowrap; /* flag for no wrapper */
uInt wbits; /* log2(window size) (8..15, defaults to 15) */
inflate_blocks_statef
*blocks; /* current inflate_blocks state */
};
int ZEXPORT inflateReset(z)
z_streamp z;
{
if (z == Z_NULL || z->state == Z_NULL)
return Z_STREAM_ERROR;
z->total_in = z->total_out = 0;
z->msg = Z_NULL;
z->state->mode = z->state->nowrap ? BLOCKS : METHOD;
inflate_blocks_reset(z->state->blocks, z, Z_NULL);
Tracev((stderr, "inflate: reset\n"));
return Z_OK;
}
int ZEXPORT inflateEnd(z)
z_streamp z;
{
if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL)
return Z_STREAM_ERROR;
if (z->state->blocks != Z_NULL)
inflate_blocks_free(z->state->blocks, z);
ZFREE(z, z->state);
z->state = Z_NULL;
Tracev((stderr, "inflate: end\n"));
return Z_OK;
}
int ZEXPORT inflateInit2_(z, w, version, stream_size)
z_streamp z;
int w;
const char *version;
int stream_size;
{
if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
stream_size != sizeof(z_stream))
return Z_VERSION_ERROR;
/* initialize state */
if (z == Z_NULL)
return Z_STREAM_ERROR;
z->msg = Z_NULL;
if (z->zalloc == Z_NULL)
{
z->zalloc = zcalloc;
z->opaque = (voidpf)0;
}
if (z->zfree == Z_NULL) z->zfree = zcfree;
if ((z->state = (struct internal_state FAR *)
ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL)
return Z_MEM_ERROR;
z->state->blocks = Z_NULL;
/* handle undocumented nowrap option (no zlib header or check) */
z->state->nowrap = 0;
if (w < 0)
{
w = - w;
z->state->nowrap = 1;
}
/* set window size */
if (w < 8 || w > 15)
{
inflateEnd(z);
return Z_STREAM_ERROR;
}
z->state->wbits = (uInt)w;
/* create inflate_blocks state */
if ((z->state->blocks =
inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, (uInt)1 << w))
== Z_NULL)
{
inflateEnd(z);
return Z_MEM_ERROR;
}
Tracev((stderr, "inflate: allocated\n"));
/* reset state */
inflateReset(z);
return Z_OK;
}
int ZEXPORT inflateInit_(z, version, stream_size)
z_streamp z;
const char *version;
int stream_size;
{
return inflateInit2_(z, DEF_WBITS, version, stream_size);
}
#define NEEDBYTE {if(z->avail_in==0)return r;r=f;}
#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++)
int ZEXPORT inflate(z, f)
z_streamp z;
int f;
{
int r;
uInt b;
if (z == Z_NULL || z->state == Z_NULL || z->next_in == Z_NULL)
return Z_STREAM_ERROR;
f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK;
r = Z_BUF_ERROR;
while (1) switch (z->state->mode)
{
case METHOD:
NEEDBYTE
if (((z->state->sub.method = NEXTBYTE) & 0xf) != Z_DEFLATED)
{
z->state->mode = zBAD;
z->msg = (char*)"unknown compression method";
z->state->sub.marker = 5; /* can't try inflateSync */
break;
}
if ((z->state->sub.method >> 4) + 8 > z->state->wbits)
{
z->state->mode = zBAD;
z->msg = (char*)"invalid window size";
z->state->sub.marker = 5; /* can't try inflateSync */
break;
}
z->state->mode = FLAG;
case FLAG:
NEEDBYTE
b = NEXTBYTE;
if (((z->state->sub.method << 8) + b) % 31)
{
z->state->mode = zBAD;
z->msg = (char*)"incorrect header check";
z->state->sub.marker = 5; /* can't try inflateSync */
break;
}
Tracev((stderr, "inflate: zlib header ok\n"));
if (!(b & PRESET_DICT))
{
z->state->mode = BLOCKS;
break;
}
z->state->mode = DICT4;
case DICT4:
NEEDBYTE
z->state->sub.check.need = (uLong)NEXTBYTE << 24;
z->state->mode = DICT3;
case DICT3:
NEEDBYTE
z->state->sub.check.need += (uLong)NEXTBYTE << 16;
z->state->mode = DICT2;
case DICT2:
NEEDBYTE
z->state->sub.check.need += (uLong)NEXTBYTE << 8;
z->state->mode = DICT1;
case DICT1:
NEEDBYTE
z->state->sub.check.need += (uLong)NEXTBYTE;
z->adler = z->state->sub.check.need;
z->state->mode = DICT0;
return Z_NEED_DICT;
case DICT0:
z->state->mode = zBAD;
z->msg = (char*)"need dictionary";
z->state->sub.marker = 0; /* can try inflateSync */
return Z_STREAM_ERROR;
case BLOCKS:
r = inflate_blocks(z->state->blocks, z, r);
if (r == Z_DATA_ERROR)
{
z->state->mode = zBAD;
z->state->sub.marker = 0; /* can try inflateSync */
break;
}
if (r == Z_OK)
r = f;
if (r != Z_STREAM_END)
return r;
r = f;
inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was);
if (z->state->nowrap)
{
z->state->mode = DONE;
break;
}
z->state->mode = CHECK4;
case CHECK4:
NEEDBYTE
z->state->sub.check.need = (uLong)NEXTBYTE << 24;
z->state->mode = CHECK3;
case CHECK3:
NEEDBYTE
z->state->sub.check.need += (uLong)NEXTBYTE << 16;
z->state->mode = CHECK2;
case CHECK2:
NEEDBYTE
z->state->sub.check.need += (uLong)NEXTBYTE << 8;
z->state->mode = CHECK1;
case CHECK1:
NEEDBYTE
z->state->sub.check.need += (uLong)NEXTBYTE;
if (z->state->sub.check.was != z->state->sub.check.need)
{
z->state->mode = zBAD;
z->msg = (char*)"incorrect data check";
z->state->sub.marker = 5; /* can't try inflateSync */
break;
}
Tracev((stderr, "inflate: zlib check ok\n"));
z->state->mode = DONE;
case DONE:
return Z_STREAM_END;
case zBAD:
return Z_DATA_ERROR;
default:
return Z_STREAM_ERROR;
}
#ifdef NEED_DUMMY_RETURN
return Z_STREAM_ERROR; /* Some dumb compilers complain without this */
#endif
}
int ZEXPORT inflateSetDictionary(z, dictionary, dictLength)
z_streamp z;
const Bytef *dictionary;
uInt dictLength;
{
uInt length = dictLength;
if (z == Z_NULL || z->state == Z_NULL || z->state->mode != DICT0)
return Z_STREAM_ERROR;
if (adler32(1L, dictionary, dictLength) != z->adler) return Z_DATA_ERROR;
z->adler = 1L;
if (length >= ((uInt)1<<z->state->wbits))
{
length = (1<<z->state->wbits)-1;
dictionary += dictLength - length;
}
inflate_set_dictionary(z->state->blocks, dictionary, length);
z->state->mode = BLOCKS;
return Z_OK;
}
int ZEXPORT inflateSync(z)
z_streamp z;
{
uInt n; /* number of bytes to look at */
Bytef *p; /* pointer to bytes */
uInt m; /* number of marker bytes found in a row */
uLong r, w; /* temporaries to save total_in and total_out */
/* set up */
if (z == Z_NULL || z->state == Z_NULL)
return Z_STREAM_ERROR;
if (z->state->mode != zBAD)
{
z->state->mode = zBAD;
z->state->sub.marker = 0;
}
if ((n = z->avail_in) == 0)
return Z_BUF_ERROR;
p = z->next_in;
m = z->state->sub.marker;
/* search */
while (n && m < 4)
{
static const Byte mark[4] = {0, 0, 0xff, 0xff};
if (*p == mark[m])
m++;
else if (*p)
m = 0;
else
m = 4 - m;
p++, n--;
}
/* restore */
z->total_in += p - z->next_in;
z->next_in = p;
z->avail_in = n;
z->state->sub.marker = m;
/* return no joy or set up to restart on a new block */
if (m != 4)
return Z_DATA_ERROR;
r = z->total_in; w = z->total_out;
inflateReset(z);
z->total_in = r; z->total_out = w;
z->state->mode = BLOCKS;
return Z_OK;
}
/* Returns true if inflate is currently at the end of a block generated
* by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
* implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH
* but removes the length bytes of the resulting empty stored block. When
* decompressing, PPP checks that at the end of input packet, inflate is
* waiting for these length bytes.
*/
int ZEXPORT inflateSyncPoint(z)
z_streamp z;
{
if (z == Z_NULL || z->state == Z_NULL || z->state->blocks == Z_NULL)
return Z_STREAM_ERROR;
return inflate_blocks_sync_point(z->state->blocks);
}

455
zlib/inftrees.c Normal file
View File

@@ -0,0 +1,455 @@
/* inftrees.c -- generate Huffman trees for efficient decoding
* Copyright (C) 1995-1998 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
#include "zutil.h"
#include "inftrees.h"
#if !defined(BUILDFIXED) && !defined(STDC)
# define BUILDFIXED /* non ANSI compilers may not accept inffixed.h */
#endif
const char inflate_copyright[] =
" inflate 1.1.2 Copyright 1995-1998 Mark Adler ";
/*
If you use the zlib library in a product, an acknowledgment is welcome
in the documentation of your product. If for some reason you cannot
include such an acknowledgment, I would appreciate that you keep this
copyright string in the executable of your product.
*/
struct internal_state {int dummy;}; /* for buggy compilers */
/* simplify the use of the inflate_huft type with some defines */
#define exop word.what.Exop
#define bits word.what.Bits
local int huft_build OF((
uIntf *, /* code lengths in bits */
uInt, /* number of codes */
uInt, /* number of "simple" codes */
const uIntf *, /* list of base values for non-simple codes */
const uIntf *, /* list of extra bits for non-simple codes */
inflate_huft * FAR*,/* result: starting table */
uIntf *, /* maximum lookup bits (returns actual) */
inflate_huft *, /* space for trees */
uInt *, /* hufts used in space */
uIntf * )); /* space for values */
/* Tables for deflate from PKZIP's appnote.txt. */
local const uInt cplens[31] = { /* Copy lengths for literal codes 257..285 */
3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
/* see note #13 above about 258 */
local const uInt cplext[31] = { /* Extra bits for literal codes 257..285 */
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112}; /* 112==invalid */
local const uInt cpdist[30] = { /* Copy offsets for distance codes 0..29 */
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
8193, 12289, 16385, 24577};
local const uInt cpdext[30] = { /* Extra bits for distance codes */
0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
12, 12, 13, 13};
/*
Huffman code decoding is performed using a multi-level table lookup.
The fastest way to decode is to simply build a lookup table whose
size is determined by the longest code. However, the time it takes
to build this table can also be a factor if the data being decoded
is not very long. The most common codes are necessarily the
shortest codes, so those codes dominate the decoding time, and hence
the speed. The idea is you can have a shorter table that decodes the
shorter, more probable codes, and then point to subsidiary tables for
the longer codes. The time it costs to decode the longer codes is
then traded against the time it takes to make longer tables.
This results of this trade are in the variables lbits and dbits
below. lbits is the number of bits the first level table for literal/
length codes can decode in one step, and dbits is the same thing for
the distance codes. Subsequent tables are also less than or equal to
those sizes. These values may be adjusted either when all of the
codes are shorter than that, in which case the longest code length in
bits is used, or when the shortest code is *longer* than the requested
table size, in which case the length of the shortest code in bits is
used.
There are two different values for the two tables, since they code a
different number of possibilities each. The literal/length table
codes 286 possible values, or in a flat code, a little over eight
bits. The distance table codes 30 possible values, or a little less
than five bits, flat. The optimum values for speed end up being
about one bit more than those, so lbits is 8+1 and dbits is 5+1.
The optimum values may differ though from machine to machine, and
possibly even between compilers. Your mileage may vary.
*/
/* If BMAX needs to be larger than 16, then h and x[] should be uLong. */
#define BMAX 15 /* maximum bit length of any code */
local int huft_build(b, n, s, d, e, t, m, hp, hn, v)
uIntf *b; /* code lengths in bits (all assumed <= BMAX) */
uInt n; /* number of codes (assumed <= 288) */
uInt s; /* number of simple-valued codes (0..s-1) */
const uIntf *d; /* list of base values for non-simple codes */
const uIntf *e; /* list of extra bits for non-simple codes */
inflate_huft * FAR *t; /* result: starting table */
uIntf *m; /* maximum lookup bits, returns actual */
inflate_huft *hp; /* space for trees */
uInt *hn; /* hufts used in space */
uIntf *v; /* working area: values in order of bit length */
/* Given a list of code lengths and a maximum table size, make a set of
tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR
if the given code set is incomplete (the tables are still built in this
case), Z_DATA_ERROR if the input is invalid (an over-subscribed set of
lengths), or Z_MEM_ERROR if not enough memory. */
{
uInt a; /* counter for codes of length k */
uInt c[BMAX+1]; /* bit length count table */
uInt f; /* i repeats in table every f entries */
int g; /* maximum code length */
int h; /* table level */
register uInt i; /* counter, current code */
register uInt j; /* counter */
register int k; /* number of bits in current code */
int l; /* bits per table (returned in m) */
uInt mask; /* (1 << w) - 1, to avoid cc -O bug on HP */
register uIntf *p; /* pointer into c[], b[], or v[] */
inflate_huft *q; /* points to current table */
struct inflate_huft_s r; /* table entry for structure assignment */
inflate_huft *u[BMAX]; /* table stack */
register int w; /* bits before this table == (l * h) */
uInt x[BMAX+1]; /* bit offsets, then code stack */
uIntf *xp; /* pointer into x */
int y; /* number of dummy codes added */
uInt z; /* number of entries in current table */
/* Generate counts for each bit length */
p = c;
#define C0 *p++ = 0;
#define C2 C0 C0 C0 C0
#define C4 C2 C2 C2 C2
C4 /* clear c[]--assume BMAX+1 is 16 */
p = b; i = n;
do {
c[*p++]++; /* assume all entries <= BMAX */
} while (--i);
if (c[0] == n) /* null input--all zero length codes */
{
*t = (inflate_huft *)Z_NULL;
*m = 0;
return Z_OK;
}
/* Find minimum and maximum length, bound *m by those */
l = *m;
for (j = 1; j <= BMAX; j++)
if (c[j])
break;
k = j; /* minimum code length */
if ((uInt)l < j)
l = j;
for (i = BMAX; i; i--)
if (c[i])
break;
g = i; /* maximum code length */
if ((uInt)l > i)
l = i;
*m = l;
/* Adjust last length count to fill out codes, if needed */
for (y = 1 << j; j < i; j++, y <<= 1)
if ((y -= c[j]) < 0)
return Z_DATA_ERROR;
if ((y -= c[i]) < 0)
return Z_DATA_ERROR;
c[i] += y;
/* Generate starting offsets into the value table for each length */
x[1] = j = 0;
p = c + 1; xp = x + 2;
while (--i) { /* note that i == g from above */
*xp++ = (j += *p++);
}
/* Make a table of values in order of bit lengths */
p = b; i = 0;
do {
if ((j = *p++) != 0)
v[x[j]++] = i;
} while (++i < n);
n = x[g]; /* set n to length of v */
/* Generate the Huffman codes and for each, make the table entries */
x[0] = i = 0; /* first Huffman code is zero */
p = v; /* grab values in bit order */
h = -1; /* no tables yet--level -1 */
w = -l; /* bits decoded == (l * h) */
u[0] = (inflate_huft *)Z_NULL; /* just to keep compilers happy */
q = (inflate_huft *)Z_NULL; /* ditto */
z = 0; /* ditto */
/* go through the bit lengths (k already is bits in shortest code) */
for (; k <= g; k++)
{
a = c[k];
while (a--)
{
/* here i is the Huffman code of length k bits for value *p */
/* make tables up to required level */
while (k > w + l)
{
h++;
w += l; /* previous table always l bits */
/* compute minimum size table less than or equal to l bits */
z = g - w;
z = z > (uInt)l ? l : z; /* table size upper limit */
if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */
{ /* too few codes for k-w bit table */
f -= a + 1; /* deduct codes from patterns left */
xp = c + k;
if (j < z)
while (++j < z) /* try smaller tables up to z bits */
{
if ((f <<= 1) <= *++xp)
break; /* enough codes to use up j bits */
f -= *xp; /* else deduct codes from patterns */
}
}
z = 1 << j; /* table entries for j-bit table */
/* allocate new table */
if (*hn + z > MANY) /* (note: doesn't matter for fixed) */
return Z_MEM_ERROR; /* not enough memory */
u[h] = q = hp + *hn;
*hn += z;
/* connect to last table, if there is one */
if (h)
{
x[h] = i; /* save pattern for backing up */
r.bits = (Byte)l; /* bits to dump before this table */
r.exop = (Byte)j; /* bits in this table */
j = i >> (w - l);
r.base = (uInt)(q - u[h-1] - j); /* offset to this table */
u[h-1][j] = r; /* connect to last table */
}
else
*t = q; /* first table is returned result */
}
/* set up table entry in r */
r.bits = (Byte)(k - w);
if (p >= v + n)
r.exop = 128 + 64; /* out of values--invalid code */
else if (*p < s)
{
r.exop = (Byte)(*p < 256 ? 0 : 32 + 64); /* 256 is end-of-block */
r.base = *p++; /* simple code is just the value */
}
else
{
r.exop = (Byte)(e[*p - s] + 16 + 64);/* non-simple--look up in lists */
r.base = d[*p++ - s];
}
/* fill code-like entries with r */
f = 1 << (k - w);
for (j = i >> w; j < z; j += f)
q[j] = r;
/* backwards increment the k-bit code i */
for (j = 1 << (k - 1); i & j; j >>= 1)
i ^= j;
i ^= j;
/* backup over finished tables */
mask = (1 << w) - 1; /* needed on HP, cc -O bug */
while ((i & mask) != x[h])
{
h--; /* don't need to update q */
w -= l;
mask = (1 << w) - 1;
}
}
}
/* Return Z_BUF_ERROR if we were given an incomplete table */
return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK;
}
int inflate_trees_bits(c, bb, tb, hp, z)
uIntf *c; /* 19 code lengths */
uIntf *bb; /* bits tree desired/actual depth */
inflate_huft * FAR *tb; /* bits tree result */
inflate_huft *hp; /* space for trees */
z_streamp z; /* for messages */
{
int r;
uInt hn = 0; /* hufts used in space */
uIntf *v; /* work area for huft_build */
if ((v = (uIntf*)ZALLOC(z, 19, sizeof(uInt))) == Z_NULL)
return Z_MEM_ERROR;
r = huft_build(c, 19, 19, (uIntf*)Z_NULL, (uIntf*)Z_NULL,
tb, bb, hp, &hn, v);
if (r == Z_DATA_ERROR)
z->msg = (char*)"oversubscribed dynamic bit lengths tree";
else if (r == Z_BUF_ERROR || *bb == 0)
{
z->msg = (char*)"incomplete dynamic bit lengths tree";
r = Z_DATA_ERROR;
}
ZFREE(z, v);
return r;
}
int inflate_trees_dynamic(nl, nd, c, bl, bd, tl, td, hp, z)
uInt nl; /* number of literal/length codes */
uInt nd; /* number of distance codes */
uIntf *c; /* that many (total) code lengths */
uIntf *bl; /* literal desired/actual bit depth */
uIntf *bd; /* distance desired/actual bit depth */
inflate_huft * FAR *tl; /* literal/length tree result */
inflate_huft * FAR *td; /* distance tree result */
inflate_huft *hp; /* space for trees */
z_streamp z; /* for messages */
{
int r;
uInt hn = 0; /* hufts used in space */
uIntf *v; /* work area for huft_build */
/* allocate work area */
if ((v = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL)
return Z_MEM_ERROR;
/* build literal/length tree */
r = huft_build(c, nl, 257, cplens, cplext, tl, bl, hp, &hn, v);
if (r != Z_OK || *bl == 0)
{
if (r == Z_DATA_ERROR)
z->msg = (char*)"oversubscribed literal/length tree";
else if (r != Z_MEM_ERROR)
{
z->msg = (char*)"incomplete literal/length tree";
r = Z_DATA_ERROR;
}
ZFREE(z, v);
return r;
}
/* build distance tree */
r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, hp, &hn, v);
if (r != Z_OK || (*bd == 0 && nl > 257))
{
if (r == Z_DATA_ERROR)
z->msg = (char*)"oversubscribed distance tree";
else if (r == Z_BUF_ERROR) {
#ifdef PKZIP_BUG_WORKAROUND
r = Z_OK;
}
#else
z->msg = (char*)"incomplete distance tree";
r = Z_DATA_ERROR;
}
else if (r != Z_MEM_ERROR)
{
z->msg = (char*)"empty distance tree with lengths";
r = Z_DATA_ERROR;
}
ZFREE(z, v);
return r;
#endif
}
/* done */
ZFREE(z, v);
return Z_OK;
}
/* build fixed tables only once--keep them here */
#ifdef BUILDFIXED
local int fixed_built = 0;
#define FIXEDH 544 /* number of hufts used by fixed tables */
local inflate_huft fixed_mem[FIXEDH];
local uInt fixed_bl;
local uInt fixed_bd;
local inflate_huft *fixed_tl;
local inflate_huft *fixed_td;
#else
#include "inffixed.h"
#endif
int inflate_trees_fixed(bl, bd, tl, td, z)
uIntf *bl; /* literal desired/actual bit depth */
uIntf *bd; /* distance desired/actual bit depth */
inflate_huft * FAR *tl; /* literal/length tree result */
inflate_huft * FAR *td; /* distance tree result */
z_streamp z; /* for memory allocation */
{
#ifdef BUILDFIXED
/* build fixed tables if not already */
if (!fixed_built)
{
int k; /* temporary variable */
uInt f = 0; /* number of hufts used in fixed_mem */
uIntf *c; /* length list for huft_build */
uIntf *v; /* work area for huft_build */
/* allocate memory */
if ((c = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL)
return Z_MEM_ERROR;
if ((v = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL)
{
ZFREE(z, c);
return Z_MEM_ERROR;
}
/* literal table */
for (k = 0; k < 144; k++)
c[k] = 8;
for (; k < 256; k++)
c[k] = 9;
for (; k < 280; k++)
c[k] = 7;
for (; k < 288; k++)
c[k] = 8;
fixed_bl = 9;
huft_build(c, 288, 257, cplens, cplext, &fixed_tl, &fixed_bl,
fixed_mem, &f, v);
/* distance table */
for (k = 0; k < 30; k++)
c[k] = 5;
fixed_bd = 5;
huft_build(c, 30, 0, cpdist, cpdext, &fixed_td, &fixed_bd,
fixed_mem, &f, v);
/* done */
ZFREE(z, v);
ZFREE(z, c);
fixed_built = 1;
}
#endif
*bl = fixed_bl;
*bd = fixed_bd;
*tl = fixed_tl;
*td = fixed_td;
return Z_OK;
}

58
zlib/inftrees.h Normal file
View File

@@ -0,0 +1,58 @@
/* inftrees.h -- header to use inftrees.c
* Copyright (C) 1995-1998 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* WARNING: this file should *not* be used by applications. It is
part of the implementation of the compression library and is
subject to change. Applications should only use zlib.h.
*/
/* Huffman code lookup table entry--this entry is four bytes for machines
that have 16-bit pointers (e.g. PC's in the small or medium model). */
typedef struct inflate_huft_s FAR inflate_huft;
struct inflate_huft_s {
union {
struct {
Byte Exop; /* number of extra bits or operation */
Byte Bits; /* number of bits in this code or subcode */
} what;
uInt pad; /* pad structure to a power of 2 (4 bytes for */
} word; /* 16-bit, 8 bytes for 32-bit int's) */
uInt base; /* literal, length base, distance base,
or table offset */
};
/* Maximum size of dynamic tree. The maximum found in a long but non-
exhaustive search was 1004 huft structures (850 for length/literals
and 154 for distances, the latter actually the result of an
exhaustive search). The actual maximum is not known, but the
value below is more than safe. */
#define MANY 1440
extern int inflate_trees_bits OF((
uIntf *, /* 19 code lengths */
uIntf *, /* bits tree desired/actual depth */
inflate_huft * FAR *, /* bits tree result */
inflate_huft *, /* space for trees */
z_streamp)); /* for messages */
extern int inflate_trees_dynamic OF((
uInt, /* number of literal/length codes */
uInt, /* number of distance codes */
uIntf *, /* that many (total) code lengths */
uIntf *, /* literal desired/actual bit depth */
uIntf *, /* distance desired/actual bit depth */
inflate_huft * FAR *, /* literal/length tree result */
inflate_huft * FAR *, /* distance tree result */
inflate_huft *, /* space for trees */
z_streamp)); /* for messages */
extern int inflate_trees_fixed OF((
uIntf *, /* literal desired/actual bit depth */
uIntf *, /* distance desired/actual bit depth */
inflate_huft * FAR *, /* literal/length tree result */
inflate_huft * FAR *, /* distance tree result */
z_streamp)); /* for memory allocation */

87
zlib/infutil.c Normal file
View File

@@ -0,0 +1,87 @@
/* inflate_util.c -- data and routines common to blocks and codes
* Copyright (C) 1995-1998 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
#include "zutil.h"
#include "infblock.h"
#include "inftrees.h"
#include "infcodes.h"
#include "infutil.h"
struct inflate_codes_state {int dummy;}; /* for buggy compilers */
/* And'ing with mask[n] masks the lower n bits */
uInt inflate_mask[17] = {
0x0000,
0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
};
/* copy as much as possible from the sliding window to the output area */
int inflate_flush(s, z, r)
inflate_blocks_statef *s;
z_streamp z;
int r;
{
uInt n;
Bytef *p;
Bytef *q;
/* local copies of source and destination pointers */
p = z->next_out;
q = s->read;
/* compute number of bytes to copy as far as end of window */
n = (uInt)((q <= s->write ? s->write : s->end) - q);
if (n > z->avail_out) n = z->avail_out;
if (n && r == Z_BUF_ERROR) r = Z_OK;
/* update counters */
z->avail_out -= n;
z->total_out += n;
/* update check information */
if (s->checkfn != Z_NULL)
z->adler = s->check = (*s->checkfn)(s->check, q, n);
/* copy as far as end of window */
zmemcpy(p, q, n);
p += n;
q += n;
/* see if more to copy at beginning of window */
if (q == s->end)
{
/* wrap pointers */
q = s->window;
if (s->write == s->end)
s->write = s->window;
/* compute bytes to copy */
n = (uInt)(s->write - q);
if (n > z->avail_out) n = z->avail_out;
if (n && r == Z_BUF_ERROR) r = Z_OK;
/* update counters */
z->avail_out -= n;
z->total_out += n;
/* update check information */
if (s->checkfn != Z_NULL)
z->adler = s->check = (*s->checkfn)(s->check, q, n);
/* copy */
zmemcpy(p, q, n);
p += n;
q += n;
}
/* update pointers */
z->next_out = p;
s->read = q;
/* done */
return r;
}

98
zlib/infutil.h Normal file
View File

@@ -0,0 +1,98 @@
/* infutil.h -- types and macros common to blocks and codes
* Copyright (C) 1995-1998 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* WARNING: this file should *not* be used by applications. It is
part of the implementation of the compression library and is
subject to change. Applications should only use zlib.h.
*/
#ifndef _INFUTIL_H
#define _INFUTIL_H
typedef enum {
TYPE, /* get type bits (3, including end bit) */
LENS, /* get lengths for stored */
STORED, /* processing stored block */
TABLE, /* get table lengths */
BTREE, /* get bit lengths tree for a dynamic block */
DTREE, /* get length, distance trees for a dynamic block */
CODES, /* processing fixed or dynamic block */
DRY, /* output remaining window bytes */
DONE, /* finished last block, done */
zBAD} /* got a data error--stuck here */
inflate_block_mode;
/* inflate blocks semi-private state */
struct inflate_blocks_state {
/* mode */
inflate_block_mode mode; /* current inflate_block mode */
/* mode dependent information */
union {
uInt left; /* if STORED, bytes left to copy */
struct {
uInt table; /* table lengths (14 bits) */
uInt index; /* index into blens (or border) */
uIntf *blens; /* bit lengths of codes */
uInt bb; /* bit length tree depth */
inflate_huft *tb; /* bit length decoding tree */
} trees; /* if DTREE, decoding info for trees */
struct {
inflate_codes_statef
*codes;
} decode; /* if CODES, current state */
} sub; /* submode */
uInt last; /* true if this block is the last block */
/* mode independent information */
uInt bitk; /* bits in bit buffer */
uLong bitb; /* bit buffer */
inflate_huft *hufts; /* single malloc for tree space */
Bytef *window; /* sliding window */
Bytef *end; /* one byte after sliding window */
Bytef *read; /* window read pointer */
Bytef *write; /* window write pointer */
check_func checkfn; /* check function */
uLong check; /* check on output */
};
/* defines for inflate input/output */
/* update pointers and return */
#define UPDBITS {s->bitb=b;s->bitk=k;}
#define UPDIN {z->avail_in=n;z->total_in+=p-z->next_in;z->next_in=p;}
#define UPDOUT {s->write=q;}
#define UPDATE {UPDBITS UPDIN UPDOUT}
#define LEAVE {UPDATE return inflate_flush(s,z,r);}
/* get bytes and bits */
#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;}
#define NEEDBYTE {if(n)r=Z_OK;else LEAVE}
#define NEXTBYTE (n--,*p++)
#define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<<k;k+=8;}}
#define DUMPBITS(j) {b>>=(j);k-=(j);}
/* output bytes */
#define WAVAIL (uInt)(q<s->read?s->read-q-1:s->end-q)
#define LOADOUT {q=s->write;m=(uInt)WAVAIL;}
#define ZWRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=(uInt)WAVAIL;}}
#define FLUSH {UPDOUT r=inflate_flush(s,z,r); LOADOUT}
#define NEEDOUT {if(m==0){ZWRAP if(m==0){FLUSH ZWRAP if(m==0) LEAVE}}r=Z_OK;}
#define OUTBYTE(a) {*q++=(Byte)(a);m--;}
/* load local pointers */
#define LOAD {LOADIN LOADOUT}
/* masks for lower bits (size given to avoid silly warnings with Visual C++) */
extern uInt inflate_mask[17];
/* copy as much as possible from the sliding window to the output area */
extern int inflate_flush OF((
inflate_blocks_statef *,
z_streamp ,
int));
struct internal_state {int dummy;}; /* for buggy compilers */
#endif

1218
zlib/trees.c Normal file
View File

File diff suppressed because it is too large Load Diff

128
zlib/trees.h Normal file
View File

@@ -0,0 +1,128 @@
/* header created automatically with -DGEN_TREES_H */
local const ct_data static_ltree[L_CODES+2] = {
{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}},
{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}},
{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}},
{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}},
{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}},
{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}},
{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}},
{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}},
{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}},
{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}},
{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}},
{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}},
{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}},
{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}},
{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}},
{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}},
{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}},
{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}},
{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}},
{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}},
{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}},
{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}},
{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}},
{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}},
{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}},
{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}},
{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}},
{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}},
{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}},
{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}},
{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}},
{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}},
{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}},
{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}},
{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}},
{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}},
{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}},
{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}},
{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}},
{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}},
{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}},
{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}},
{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}},
{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}},
{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}},
{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}},
{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}},
{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}},
{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}},
{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}},
{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}},
{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}},
{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}},
{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}},
{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}},
{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}},
{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}},
{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}}
};
local const ct_data static_dtree[D_CODES] = {
{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}},
{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}},
{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}},
{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}},
{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}},
{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}}
};
const uch _dist_code[DIST_CODE_LEN] = {
0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8,
8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10,
10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13,
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17,
18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22,
23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27,
27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29
};
const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {
0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12,
13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,
17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19,
19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,
23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26,
26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28
};
local const int base_length[LENGTH_CODES] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56,
64, 80, 96, 112, 128, 160, 192, 224, 0
};
local const int base_dist[D_CODES] = {
0, 1, 2, 3, 4, 6, 8, 12, 16, 24,
32, 48, 64, 96, 128, 192, 256, 384, 512, 768,
1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576
};

252
zlib/zconf.h Normal file
View File

@@ -0,0 +1,252 @@
/* zconf.h -- configuration of the zlib compression library
* Copyright (C) 1995-1998 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* @(#) $Id$ */
#ifndef _ZCONF_H
#define _ZCONF_H
/*
* If you *really* need a unique prefix for all types and library functions,
* compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
*/
#ifdef Z_PREFIX
# define deflateInit_ z_deflateInit_
# define deflate z_deflate
# define deflateEnd z_deflateEnd
# define inflateInit_ z_inflateInit_
# define inflate z_inflate
# define inflateEnd z_inflateEnd
# define deflateInit2_ z_deflateInit2_
# define deflateSetDictionary z_deflateSetDictionary
# define deflateCopy z_deflateCopy
# define deflateReset z_deflateReset
# define deflateParams z_deflateParams
# define inflateInit2_ z_inflateInit2_
# define inflateSetDictionary z_inflateSetDictionary
# define inflateSync z_inflateSync
# define inflateSyncPoint z_inflateSyncPoint
# define inflateReset z_inflateReset
# define compress z_compress
# define compress2 z_compress2
# define uncompress z_uncompress
# define adler32 z_adler32
# define crc32 z_crc32
# define get_crc_table z_get_crc_table
# define Byte z_Byte
# define uInt z_uInt
# define uLong z_uLong
# define Bytef z_Bytef
# define charf z_charf
# define intf z_intf
# define uIntf z_uIntf
# define uLongf z_uLongf
# define voidpf z_voidpf
# define voidp z_voidp
#endif
#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32)
# define WIN32
#endif
#if defined(__GNUC__) || defined(WIN32) || defined(__386__) || defined(i386)
# ifndef __32BIT__
# define __32BIT__
# endif
#endif
#if defined(__MSDOS__) && !defined(MSDOS)
# define MSDOS
#endif
/*
* Compile with -DMAXSEG_64K if the alloc function cannot allocate more
* than 64k bytes at a time (needed on systems with 16-bit int).
*/
#if defined(MSDOS) && !defined(__32BIT__)
# define MAXSEG_64K
#endif
#ifdef MSDOS
# define UNALIGNED_OK
#endif
#if (defined(MSDOS) || defined(_WINDOWS) || defined(WIN32)) && !defined(STDC)
# define STDC
#endif
#if defined(__STDC__) || defined(__cplusplus) || defined(__OS2__)
# ifndef STDC
# define STDC
# endif
#endif
#ifndef STDC
# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
# define const
# endif
#endif
/* Some Mac compilers merge all .h files incorrectly: */
#if defined(__MWERKS__) || defined(applec) ||defined(THINK_C) ||defined(__SC__)
# define NO_DUMMY_DECL
#endif
/* Borland C incorrectly complains about missing returns: */
#if defined(__BORLANDC__)
# define NEED_DUMMY_RETURN
#endif
/* Maximum value for memLevel in deflateInit2 */
#ifndef MAX_MEM_LEVEL
# ifdef MAXSEG_64K
# define MAX_MEM_LEVEL 8
# else
# define MAX_MEM_LEVEL 9
# endif
#endif
/* Maximum value for windowBits in deflateInit2 and inflateInit2.
* WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
* created by gzip. (Files created by minigzip can still be extracted by
* gzip.)
*/
#ifndef MAX_WBITS
# define MAX_WBITS 15 /* 32K LZ77 window */
#endif
/* The memory requirements for deflate are (in bytes):
(1 << (windowBits+2)) + (1 << (memLevel+9))
that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
plus a few kilobytes for small objects. For example, if you want to reduce
the default memory requirements from 256K to 128K, compile with
make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
Of course this will generally degrade compression (there's no free lunch).
The memory requirements for inflate are (in bytes) 1 << windowBits
that is, 32K for windowBits=15 (default value) plus a few kilobytes
for small objects.
*/
/* Type declarations */
#ifndef OF /* function prototypes */
# ifdef STDC
# define OF(args) args
# else
# define OF(args) ()
# endif
#endif
/* The following definitions for FAR are needed only for MSDOS mixed
* model programming (small or medium model with some far allocations).
* This was tested only with MSC; for other MSDOS compilers you may have
* to define NO_MEMCPY in zutil.h. If you don't need the mixed model,
* just define FAR to be empty.
*/
#if (defined(M_I86SM) || defined(M_I86MM)) && !defined(__32BIT__)
/* MSC small or medium model */
# define SMALL_MEDIUM
# ifdef _MSC_VER
# define FAR __far
# else
# define FAR far
# endif
#endif
#if defined(__BORLANDC__) && (defined(__SMALL__) || defined(__MEDIUM__))
# ifndef __32BIT__
# define SMALL_MEDIUM
# define FAR __far
# endif
#endif
/* Compile with -DZLIB_DLL for Windows DLL support */
#if (defined(_WINDOWS) || defined(WINDOWS)) && defined(ZLIB_DLL)
# ifdef FAR
# undef FAR
# endif
# include <windows.h>
# define ZEXPORT WINAPI
# ifdef WIN32
# define ZEXPORTVA WINAPIV
# else
# define ZEXPORTVA FAR _cdecl _export
# endif
#else
# if defined (__BORLANDC__) && defined (_Windows) && defined (__DLL__)
# define ZEXPORT _export
# define ZEXPORTVA _export
# else
# define ZEXPORT
# define ZEXPORTVA
# endif
#endif
#ifndef FAR
# define FAR
#endif
typedef unsigned char Byte; /* 8 bits */
typedef unsigned int uInt; /* 16 bits or more */
typedef unsigned long uLong; /* 32 bits or more */
#if defined(__BORLANDC__) && defined(SMALL_MEDIUM)
/* Borland C/C++ ignores FAR inside typedef */
# define Bytef Byte FAR
#else
typedef Byte FAR Bytef;
#endif
typedef char FAR charf;
typedef int FAR intf;
typedef uInt FAR uIntf;
typedef uLong FAR uLongf;
#ifdef STDC
typedef void FAR *voidpf;
typedef void *voidp;
#else
typedef Byte FAR *voidpf;
typedef Byte *voidp;
#endif
#ifdef HAVE_UNISTD_H
# include <sys/types.h> /* for off_t */
# include <unistd.h> /* for SEEK_* and off_t */
# define z_off_t off_t
#endif
#ifndef SEEK_SET
# define SEEK_SET 0 /* Seek from beginning of file. */
# define SEEK_CUR 1 /* Seek from current position. */
#endif
#ifndef z_off_t
# define z_off_t long
#endif
/* MVS linker does not support external names larger than 8 bytes */
#if defined(__MVS__)
# pragma map(deflateInit_,"DEIN")
# pragma map(deflateInit2_,"DEIN2")
# pragma map(deflateEnd,"DEEND")
# pragma map(inflateInit_,"ININ")
# pragma map(inflateInit2_,"ININ2")
# pragma map(inflateEnd,"INEND")
# pragma map(inflateSync,"INSY")
# pragma map(inflateSetDictionary,"INSEDI")
# pragma map(inflate_blocks,"INBL")
# pragma map(inflate_blocks_new,"INBLNE")
# pragma map(inflate_blocks_free,"INBLFR")
# pragma map(inflate_blocks_reset,"INBLRE")
# pragma map(inflate_codes_free,"INCOFR")
# pragma map(inflate_codes,"INCO")
# pragma map(inflate_fast,"INFA")
# pragma map(inflate_flush,"INFLU")
# pragma map(inflate_mask,"INMA")
# pragma map(inflate_set_dictionary,"INSEDI2")
# pragma map(inflate_copyright,"INCOPY")
# pragma map(inflate_trees_bits,"INTRBI")
# pragma map(inflate_trees_dynamic,"INTRDY")
# pragma map(inflate_trees_fixed,"INTRFI")
# pragma map(inflate_trees_free,"INTRFR")
#endif
#endif /* _ZCONF_H */

889
zlib/zlib.h Normal file
View File

@@ -0,0 +1,889 @@
/* zlib.h -- interface of the 'zlib' general purpose compression library
version 1.1.2, March 19th, 1998
Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
Jean-loup Gailly Mark Adler
jloup@gzip.org madler@alumni.caltech.edu
The data format used by the zlib library is described by RFCs (Request for
Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt
(zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).
*/
#ifndef _ZLIB_H
#define _ZLIB_H
#include "zconf.h"
#ifdef __cplusplus
extern "C" {
#endif
#define ZLIB_VERSION "1.1.2"
/*
The 'zlib' compression library provides in-memory compression and
decompression functions, including integrity checks of the uncompressed
data. This version of the library supports only one compression method
(deflation) but other algorithms will be added later and will have the same
stream interface.
Compression can be done in a single step if the buffers are large
enough (for example if an input file is mmap'ed), or can be done by
repeated calls of the compression function. In the latter case, the
application must provide more input and/or consume the output
(providing more output space) before each call.
The library also supports reading and writing files in gzip (.gz) format
with an interface similar to that of stdio.
The library does not install any signal handler. The decoder checks
the consistency of the compressed data, so the library should never
crash even in case of corrupted input.
*/
typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
typedef void (*free_func) OF((voidpf opaque, voidpf address));
struct internal_state;
typedef struct z_stream_s {
Bytef *next_in; /* next input byte */
uInt avail_in; /* number of bytes available at next_in */
uLong total_in; /* total nb of input bytes read so far */
Bytef *next_out; /* next output byte should be put there */
uInt avail_out; /* remaining free space at next_out */
uLong total_out; /* total nb of bytes output so far */
char *msg; /* last error message, NULL if no error */
struct internal_state FAR *state; /* not visible by applications */
alloc_func zalloc; /* used to allocate the internal state */
free_func zfree; /* used to free the internal state */
voidpf opaque; /* private data object passed to zalloc and zfree */
int data_type; /* best guess about the data type: ascii or binary */
uLong adler; /* adler32 value of the uncompressed data */
uLong reserved; /* reserved for future use */
} z_stream;
typedef z_stream FAR *z_streamp;
/*
The application must update next_in and avail_in when avail_in has
dropped to zero. It must update next_out and avail_out when avail_out
has dropped to zero. The application must initialize zalloc, zfree and
opaque before calling the init function. All other fields are set by the
compression library and must not be updated by the application.
The opaque value provided by the application will be passed as the first
parameter for calls of zalloc and zfree. This can be useful for custom
memory management. The compression library attaches no meaning to the
opaque value.
zalloc must return Z_NULL if there is not enough memory for the object.
If zlib is used in a multi-threaded application, zalloc and zfree must be
thread safe.
On 16-bit systems, the functions zalloc and zfree must be able to allocate
exactly 65536 bytes, but will not be required to allocate more than this
if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS,
pointers returned by zalloc for objects of exactly 65536 bytes *must*
have their offset normalized to zero. The default allocation function
provided by this library ensures this (see zutil.c). To reduce memory
requirements and avoid any allocation of 64K objects, at the expense of
compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h).
The fields total_in and total_out can be used for statistics or
progress reports. After compression, total_in holds the total size of
the uncompressed data and may be saved for use in the decompressor
(particularly if the decompressor wants to decompress everything in
a single step).
*/
/* constants */
#define Z_NO_FLUSH 0
#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */
#define Z_SYNC_FLUSH 2
#define Z_FULL_FLUSH 3
#define Z_FINISH 4
#define Z_INSERT_ONLY 5
/* Allowed flush values; see deflate() below for details */
#define Z_OK 0
#define Z_STREAM_END 1
#define Z_NEED_DICT 2
#define Z_ERRNO (-1)
#define Z_STREAM_ERROR (-2)
#define Z_DATA_ERROR (-3)
#define Z_MEM_ERROR (-4)
#define Z_BUF_ERROR (-5)
#define Z_VERSION_ERROR (-6)
/* Return codes for the compression/decompression functions. Negative
* values are errors, positive values are used for special but normal events.
*/
#define Z_NO_COMPRESSION 0
#define Z_BEST_SPEED 1
#define Z_BEST_COMPRESSION 9
#define Z_DEFAULT_COMPRESSION (-1)
/* compression levels */
#define Z_FILTERED 1
#define Z_HUFFMAN_ONLY 2
#define Z_DEFAULT_STRATEGY 0
/* compression strategy; see deflateInit2() below for details */
#define Z_BINARY 0
#define Z_ASCII 1
#define Z_UNKNOWN 2
/* Possible values of the data_type field */
#define Z_DEFLATED 8
/* The deflate compression method (the only one supported in this version) */
#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */
#define zlib_version zlibVersion()
/* for compatibility with versions < 1.0.2 */
/* basic functions */
extern const char * ZEXPORT zlibVersion OF((void));
/* The application can compare zlibVersion and ZLIB_VERSION for consistency.
If the first character differs, the library code actually used is
not compatible with the zlib.h header file used by the application.
This check is automatically made by deflateInit and inflateInit.
*/
/*
extern int ZEXPORT deflateInit OF((z_streamp strm, int level));
Initializes the internal stream state for compression. The fields
zalloc, zfree and opaque must be initialized before by the caller.
If zalloc and zfree are set to Z_NULL, deflateInit updates them to
use default allocation functions.
The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9:
1 gives best speed, 9 gives best compression, 0 gives no compression at
all (the input data is simply copied a block at a time).
Z_DEFAULT_COMPRESSION requests a default compromise between speed and
compression (currently equivalent to level 6).
deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not
enough memory, Z_STREAM_ERROR if level is not a valid compression level,
Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible
with the version assumed by the caller (ZLIB_VERSION).
msg is set to null if there is no error message. deflateInit does not
perform any compression: this will be done by deflate().
*/
extern int ZEXPORT deflate OF((z_streamp strm, int flush));
/*
deflate compresses as much data as possible, and stops when the input
buffer becomes empty or the output buffer becomes full. It may introduce some
output latency (reading input without producing any output) except when
forced to flush.
The detailed semantics are as follows. deflate performs one or both of the
following actions:
- Compress more input starting at next_in and update next_in and avail_in
accordingly. If not all input can be processed (because there is not
enough room in the output buffer), next_in and avail_in are updated and
processing will resume at this point for the next call of deflate().
- Provide more output starting at next_out and update next_out and avail_out
accordingly. This action is forced if the parameter flush is non zero.
Forcing flush frequently degrades the compression ratio, so this parameter
should be set only when necessary (in interactive applications).
Some output may be provided even if flush is not set.
Before the call of deflate(), the application should ensure that at least
one of the actions is possible, by providing more input and/or consuming
more output, and updating avail_in or avail_out accordingly; avail_out
should never be zero before the call. The application can consume the
compressed output when it wants, for example when the output buffer is full
(avail_out == 0), or after each call of deflate(). If deflate returns Z_OK
and with zero avail_out, it must be called again after making room in the
output buffer because there might be more output pending.
If the parameter flush is set to Z_SYNC_FLUSH, all pending output is
flushed to the output buffer and the output is aligned on a byte boundary, so
that the decompressor can get all input data available so far. (In particular
avail_in is zero after the call if enough output space has been provided
before the call.) Flushing may degrade compression for some compression
algorithms and so it should be used only when necessary.
If flush is set to Z_FULL_FLUSH, all output is flushed as with
Z_SYNC_FLUSH, and the compression state is reset so that decompression can
restart from this point if previous compressed data has been damaged or if
random access is desired. Using Z_FULL_FLUSH too often can seriously degrade
the compression.
If deflate returns with avail_out == 0, this function must be called again
with the same value of the flush parameter and more output space (updated
avail_out), until the flush is complete (deflate returns with non-zero
avail_out).
If the parameter flush is set to Z_FINISH, pending input is processed,
pending output is flushed and deflate returns with Z_STREAM_END if there
was enough output space; if deflate returns with Z_OK, this function must be
called again with Z_FINISH and more output space (updated avail_out) but no
more input data, until it returns with Z_STREAM_END or an error. After
deflate has returned Z_STREAM_END, the only possible operations on the
stream are deflateReset or deflateEnd.
Z_FINISH can be used immediately after deflateInit if all the compression
is to be done in a single step. In this case, avail_out must be at least
0.1% larger than avail_in plus 12 bytes. If deflate does not return
Z_STREAM_END, then it must be called again as described above.
deflate() sets strm->adler to the adler32 checksum of all input read
so far (that is, total_in bytes).
deflate() may update data_type if it can make a good guess about
the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered
binary. This field is only for information purposes and does not affect
the compression algorithm in any manner.
deflate() returns Z_OK if some progress has been made (more input
processed or more output produced), Z_STREAM_END if all input has been
consumed and all output has been produced (only when flush is set to
Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example
if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible.
*/
extern int ZEXPORT deflateEnd OF((z_streamp strm));
/*
All dynamically allocated data structures for this stream are freed.
This function discards any unprocessed input and does not flush any
pending output.
deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the
stream state was inconsistent, Z_DATA_ERROR if the stream was freed
prematurely (some input or output was discarded). In the error case,
msg may be set but then points to a static string (which must not be
deallocated).
*/
/*
extern int ZEXPORT inflateInit OF((z_streamp strm));
Initializes the internal stream state for decompression. The fields
next_in, avail_in, zalloc, zfree and opaque must be initialized before by
the caller. If next_in is not Z_NULL and avail_in is large enough (the exact
value depends on the compression method), inflateInit determines the
compression method from the zlib header and allocates all data structures
accordingly; otherwise the allocation will be deferred to the first call of
inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to
use default allocation functions.
inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
version assumed by the caller. msg is set to null if there is no error
message. inflateInit does not perform any decompression apart from reading
the zlib header if present: this will be done by inflate(). (So next_in and
avail_in may be modified, but next_out and avail_out are unchanged.)
*/
extern int ZEXPORT inflate OF((z_streamp strm, int flush));
/*
inflate decompresses as much data as possible, and stops when the input
buffer becomes empty or the output buffer becomes full. It may some
introduce some output latency (reading input without producing any output)
except when forced to flush.
The detailed semantics are as follows. inflate performs one or both of the
following actions:
- Decompress more input starting at next_in and update next_in and avail_in
accordingly. If not all input can be processed (because there is not
enough room in the output buffer), next_in is updated and processing
will resume at this point for the next call of inflate().
- Provide more output starting at next_out and update next_out and avail_out
accordingly. inflate() provides as much output as possible, until there
is no more input data or no more space in the output buffer (see below
about the flush parameter).
Before the call of inflate(), the application should ensure that at least
one of the actions is possible, by providing more input and/or consuming
more output, and updating the next_* and avail_* values accordingly.
The application can consume the uncompressed output when it wants, for
example when the output buffer is full (avail_out == 0), or after each
call of inflate(). If inflate returns Z_OK and with zero avail_out, it
must be called again after making room in the output buffer because there
might be more output pending.
If the parameter flush is set to Z_SYNC_FLUSH, inflate flushes as much
output as possible to the output buffer. The flushing behavior of inflate is
not specified for values of the flush parameter other than Z_SYNC_FLUSH
and Z_FINISH, but the current implementation actually flushes as much output
as possible anyway.
inflate() should normally be called until it returns Z_STREAM_END or an
error. However if all decompression is to be performed in a single step
(a single call of inflate), the parameter flush should be set to
Z_FINISH. In this case all pending input is processed and all pending
output is flushed; avail_out must be large enough to hold all the
uncompressed data. (The size of the uncompressed data may have been saved
by the compressor for this purpose.) The next operation on this stream must
be inflateEnd to deallocate the decompression state. The use of Z_FINISH
is never required, but can be used to inform inflate that a faster routine
may be used for the single inflate() call.
If a preset dictionary is needed at this point (see inflateSetDictionary
below), inflate sets strm-adler to the adler32 checksum of the
dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise
it sets strm->adler to the adler32 checksum of all output produced
so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or
an error code as described below. At the end of the stream, inflate()
checks that its computed adler32 checksum is equal to that saved by the
compressor and returns Z_STREAM_END only if the checksum is correct.
inflate() returns Z_OK if some progress has been made (more input processed
or more output produced), Z_STREAM_END if the end of the compressed data has
been reached and all uncompressed output has been produced, Z_NEED_DICT if a
preset dictionary is needed at this point, Z_DATA_ERROR if the input data was
corrupted (input stream not conforming to the zlib format or incorrect
adler32 checksum), Z_STREAM_ERROR if the stream structure was inconsistent
(for example if next_in or next_out was NULL), Z_MEM_ERROR if there was not
enough memory, Z_BUF_ERROR if no progress is possible or if there was not
enough room in the output buffer when Z_FINISH is used. In the Z_DATA_ERROR
case, the application may then call inflateSync to look for a good
compression block.
*/
extern int ZEXPORT inflateEnd OF((z_streamp strm));
/*
All dynamically allocated data structures for this stream are freed.
This function discards any unprocessed input and does not flush any
pending output.
inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
was inconsistent. In the error case, msg may be set but then points to a
static string (which must not be deallocated).
*/
/* Advanced functions */
/*
The following functions are needed only in some special applications.
*/
/*
extern int ZEXPORT deflateInit2 OF((z_streamp strm,
int level,
int method,
int windowBits,
int memLevel,
int strategy));
This is another version of deflateInit with more compression options. The
fields next_in, zalloc, zfree and opaque must be initialized before by
the caller.
The method parameter is the compression method. It must be Z_DEFLATED in
this version of the library.
The windowBits parameter is the base two logarithm of the window size
(the size of the history buffer). It should be in the range 8..15 for this
version of the library. Larger values of this parameter result in better
compression at the expense of memory usage. The default value is 15 if
deflateInit is used instead.
The memLevel parameter specifies how much memory should be allocated
for the internal compression state. memLevel=1 uses minimum memory but
is slow and reduces compression ratio; memLevel=9 uses maximum memory
for optimal speed. The default value is 8. See zconf.h for total memory
usage as a function of windowBits and memLevel.
The strategy parameter is used to tune the compression algorithm. Use the
value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a
filter (or predictor), or Z_HUFFMAN_ONLY to force Huffman encoding only (no
string match). Filtered data consists mostly of small values with a
somewhat random distribution. In this case, the compression algorithm is
tuned to compress them better. The effect of Z_FILTERED is to force more
Huffman coding and less string matching; it is somewhat intermediate
between Z_DEFAULT and Z_HUFFMAN_ONLY. The strategy parameter only affects
the compression ratio but not the correctness of the compressed output even
if it is not set appropriately.
deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid
method). msg is set to null if there is no error message. deflateInit2 does
not perform any compression: this will be done by deflate().
*/
extern int ZEXPORT deflateSetDictionary OF((z_streamp strm,
const Bytef *dictionary,
uInt dictLength));
/*
Initializes the compression dictionary from the given byte sequence
without producing any compressed output. This function must be called
immediately after deflateInit or deflateInit2, before any call of
deflate. The compressor and decompressor must use exactly the same
dictionary (see inflateSetDictionary).
The dictionary should consist of strings (byte sequences) that are likely
to be encountered later in the data to be compressed, with the most commonly
used strings preferably put towards the end of the dictionary. Using a
dictionary is most useful when the data to be compressed is short and can be
predicted with good accuracy; the data can then be compressed better than
with the default empty dictionary.
Depending on the size of the compression data structures selected by
deflateInit or deflateInit2, a part of the dictionary may in effect be
discarded, for example if the dictionary is larger than the window size in
deflate or deflate2. Thus the strings most likely to be useful should be
put at the end of the dictionary, not at the front.
Upon return of this function, strm->adler is set to the Adler32 value
of the dictionary; the decompressor may later use this value to determine
which dictionary has been used by the compressor. (The Adler32 value
applies to the whole dictionary even if only a subset of the dictionary is
actually used by the compressor.)
deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a
parameter is invalid (such as NULL dictionary) or the stream state is
inconsistent (for example if deflate has already been called for this stream
or if the compression method is bsort). deflateSetDictionary does not
perform any compression: this will be done by deflate().
*/
extern int ZEXPORT deflateCopy OF((z_streamp dest,
z_streamp source));
/*
Sets the destination stream as a complete copy of the source stream.
This function can be useful when several compression strategies will be
tried, for example when there are several ways of pre-processing the input
data with a filter. The streams that will be discarded should then be freed
by calling deflateEnd. Note that deflateCopy duplicates the internal
compression state which can be quite large, so this strategy is slow and
can consume lots of memory.
deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
(such as zalloc being NULL). msg is left unchanged in both source and
destination.
*/
extern int ZEXPORT deflateReset OF((z_streamp strm));
/*
This function is equivalent to deflateEnd followed by deflateInit,
but does not free and reallocate all the internal compression state.
The stream will keep the same compression level and any other attributes
that may have been set by deflateInit2.
deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
stream state was inconsistent (such as zalloc or state being NULL).
*/
extern int ZEXPORT deflateParams OF((z_streamp strm, int level, int strategy));
/*
Dynamically update the compression level and compression strategy. The
interpretation of level and strategy is as in deflateInit2. This can be
used to switch between compression and straight copy of the input data, or
to switch to a different kind of input data requiring a different
strategy. If the compression level is changed, the input available so far
is compressed with the old level (and may be flushed); the new level will
take effect only at the next call of deflate().
Before the call of deflateParams, the stream state must be set as for
a call of deflate(), since the currently available input may have to
be compressed and flushed. In particular, strm->avail_out must be non-zero.
deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source
stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR
if strm->avail_out was zero.
*/
/*
extern int ZEXPORT inflateInit2 OF((z_streamp strm,
int windowBits));
This is another version of inflateInit with an extra parameter. The
fields next_in, avail_in, zalloc, zfree and opaque must be initialized
before by the caller.
The windowBits parameter is the base two logarithm of the maximum window
size (the size of the history buffer). It should be in the range 8..15 for
this version of the library. The default value is 15 if inflateInit is used
instead. If a compressed stream with a larger window size is given as
input, inflate() will return with the error code Z_DATA_ERROR instead of
trying to allocate a larger window.
inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative
memLevel). msg is set to null if there is no error message. inflateInit2
does not perform any decompression apart from reading the zlib header if
present: this will be done by inflate(). (So next_in and avail_in may be
modified, but next_out and avail_out are unchanged.)
*/
extern int ZEXPORT inflateSetDictionary OF((z_streamp strm,
const Bytef *dictionary,
uInt dictLength));
/*
Initializes the decompression dictionary from the given uncompressed byte
sequence. This function must be called immediately after a call of inflate
if this call returned Z_NEED_DICT. The dictionary chosen by the compressor
can be determined from the Adler32 value returned by this call of
inflate. The compressor and decompressor must use exactly the same
dictionary (see deflateSetDictionary).
inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
parameter is invalid (such as NULL dictionary) or the stream state is
inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the
expected one (incorrect Adler32 value). inflateSetDictionary does not
perform any decompression: this will be done by subsequent calls of
inflate().
*/
extern int ZEXPORT inflateSync OF((z_streamp strm));
/*
Skips invalid compressed data until a full flush point (see above the
description of deflate with Z_FULL_FLUSH) can be found, or until all
available input is skipped. No output is provided.
inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR
if no more input was provided, Z_DATA_ERROR if no flush point has been found,
or Z_STREAM_ERROR if the stream structure was inconsistent. In the success
case, the application may save the current current value of total_in which
indicates where valid compressed data was found. In the error case, the
application may repeatedly call inflateSync, providing more input each time,
until success or end of the input data.
*/
extern int ZEXPORT inflateReset OF((z_streamp strm));
/*
This function is equivalent to inflateEnd followed by inflateInit,
but does not free and reallocate all the internal decompression state.
The stream will keep attributes that may have been set by inflateInit2.
inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
stream state was inconsistent (such as zalloc or state being NULL).
*/
/* utility functions */
/*
The following utility functions are implemented on top of the
basic stream-oriented functions. To simplify the interface, some
default options are assumed (compression level and memory usage,
standard memory allocation functions). The source code of these
utility functions can easily be modified if you need special options.
*/
extern int ZEXPORT compress OF((Bytef *dest, uLongf *destLen,
const Bytef *source, uLong sourceLen));
/*
Compresses the source buffer into the destination buffer. sourceLen is
the byte length of the source buffer. Upon entry, destLen is the total
size of the destination buffer, which must be at least 0.1% larger than
sourceLen plus 12 bytes. Upon exit, destLen is the actual size of the
compressed buffer.
This function can be used to compress a whole file at once if the
input file is mmap'ed.
compress returns Z_OK if success, Z_MEM_ERROR if there was not
enough memory, Z_BUF_ERROR if there was not enough room in the output
buffer.
*/
extern int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen,
const Bytef *source, uLong sourceLen,
int level));
/*
Compresses the source buffer into the destination buffer. The level
parameter has the same meaning as in deflateInit. sourceLen is the byte
length of the source buffer. Upon entry, destLen is the total size of the
destination buffer, which must be at least 0.1% larger than sourceLen plus
12 bytes. Upon exit, destLen is the actual size of the compressed buffer.
compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
memory, Z_BUF_ERROR if there was not enough room in the output buffer,
Z_STREAM_ERROR if the level parameter is invalid.
*/
extern int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen,
const Bytef *source, uLong sourceLen));
/*
Decompresses the source buffer into the destination buffer. sourceLen is
the byte length of the source buffer. Upon entry, destLen is the total
size of the destination buffer, which must be large enough to hold the
entire uncompressed data. (The size of the uncompressed data must have
been saved previously by the compressor and transmitted to the decompressor
by some mechanism outside the scope of this compression library.)
Upon exit, destLen is the actual size of the compressed buffer.
This function can be used to decompress a whole file at once if the
input file is mmap'ed.
uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
enough memory, Z_BUF_ERROR if there was not enough room in the output
buffer, or Z_DATA_ERROR if the input data was corrupted.
*/
typedef voidp gzFile;
extern gzFile ZEXPORT gzopen OF((const char *path, const char *mode));
/*
Opens a gzip (.gz) file for reading or writing. The mode parameter
is as in fopen ("rb" or "wb") but can also include a compression level
("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for
Huffman only compression as in "wb1h". (See the description
of deflateInit2 for more information about the strategy parameter.)
gzopen can be used to read a file which is not in gzip format; in this
case gzread will directly read from the file without decompression.
gzopen returns NULL if the file could not be opened or if there was
insufficient memory to allocate the (de)compression state; errno
can be checked to distinguish the two cases (if errno is zero, the
zlib error is Z_MEM_ERROR). */
extern gzFile ZEXPORT gzdopen OF((int fd, const char *mode));
/*
gzdopen() associates a gzFile with the file descriptor fd. File
descriptors are obtained from calls like open, dup, creat, pipe or
fileno (in the file has been previously opened with fopen).
The mode parameter is as in gzopen.
The next call of gzclose on the returned gzFile will also close the
file descriptor fd, just like fclose(fdopen(fd), mode) closes the file
descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode).
gzdopen returns NULL if there was insufficient memory to allocate
the (de)compression state.
*/
extern int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy));
/*
Dynamically update the compression level or strategy. See the description
of deflateInit2 for the meaning of these parameters.
gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not
opened for writing.
*/
extern int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len));
/*
Reads the given number of uncompressed bytes from the compressed file.
If the input file was not in gzip format, gzread copies the given number
of bytes into the buffer.
gzread returns the number of uncompressed bytes actually read (0 for
end of file, -1 for error). */
extern int ZEXPORT gzwrite OF((gzFile file, const voidp buf, unsigned len));
/*
Writes the given number of uncompressed bytes into the compressed file.
gzwrite returns the number of uncompressed bytes actually written
(0 in case of error).
*/
extern int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...));
/*
Converts, formats, and writes the args to the compressed file under
control of the format string, as in fprintf. gzprintf returns the number of
uncompressed bytes actually written (0 in case of error).
*/
extern int ZEXPORT gzputs OF((gzFile file, const char *s));
/*
Writes the given null-terminated string to the compressed file, excluding
the terminating null character.
gzputs returns the number of characters written, or -1 in case of error.
*/
extern char * ZEXPORT gzgets OF((gzFile file, char *buf, int len));
/*
Reads bytes from the compressed file until len-1 characters are read, or
a newline character is read and transferred to buf, or an end-of-file
condition is encountered. The string is then terminated with a null
character.
gzgets returns buf, or Z_NULL in case of error.
*/
extern int ZEXPORT gzputc OF((gzFile file, int c));
/*
Writes c, converted to an unsigned char, into the compressed file.
gzputc returns the value that was written, or -1 in case of error.
*/
extern int ZEXPORT gzgetc OF((gzFile file));
/*
Reads one byte from the compressed file. gzgetc returns this byte
or -1 in case of end of file or error.
*/
extern int ZEXPORT gzflush OF((gzFile file, int flush));
/*
Flushes all pending output into the compressed file. The parameter
flush is as in the deflate() function. The return value is the zlib
error number (see function gzerror below). gzflush returns Z_OK if
the flush parameter is Z_FINISH and all output could be flushed.
gzflush should be called only when strictly necessary because it can
degrade compression.
*/
extern z_off_t ZEXPORT gzseek OF((gzFile file, z_off_t offset, int whence));
/*
Sets the starting position for the next gzread or gzwrite on the given
compressed file. The offset represents a number of bytes in the
uncompressed data stream. The whence parameter is defined as in lseek(2);
the value SEEK_END is not supported.
If the file is opened for reading, this function is emulated but can be
extremely slow. If the file is opened for writing, only forward seeks are
supported; gzseek then compresses a sequence of zeroes up to the new
starting position.
gzseek returns the resulting offset location as measured in bytes from
the beginning of the uncompressed stream, or -1 in case of error, in
particular if the file is opened for writing and the new starting position
would be before the current position.
*/
extern int ZEXPORT gzrewind OF((gzFile file));
/*
Rewinds the given file. This function is supported only for reading.
gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET)
*/
extern z_off_t ZEXPORT gztell OF((gzFile file));
/*
Returns the starting position for the next gzread or gzwrite on the
given compressed file. This position represents a number of bytes in the
uncompressed data stream.
gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)
*/
extern int ZEXPORT gzeof OF((gzFile file));
/*
Returns 1 when EOF has previously been detected reading the given
input stream, otherwise zero.
*/
extern int ZEXPORT gzclose OF((gzFile file));
/*
Flushes all pending output if necessary, closes the compressed file
and deallocates all the (de)compression state. The return value is the zlib
error number (see function gzerror below).
*/
extern const char * ZEXPORT gzerror OF((gzFile file, int *errnum));
/*
Returns the error message for the last error which occurred on the
given compressed file. errnum is set to zlib error number. If an
error occurred in the file system and not in the compression library,
errnum is set to Z_ERRNO and the application may consult errno
to get the exact error code.
*/
/* checksum functions */
/*
These functions are not related to compression but are exported
anyway because they might be useful in applications using the
compression library.
*/
extern uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));
/*
Update a running Adler-32 checksum with the bytes buf[0..len-1] and
return the updated checksum. If buf is NULL, this function returns
the required initial value for the checksum.
An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
much faster. Usage example:
uLong adler = adler32(0L, Z_NULL, 0);
while (read_buffer(buffer, length) != EOF) {
adler = adler32(adler, buffer, length);
}
if (adler != original_adler) error();
*/
extern uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len));
/*
Update a running crc with the bytes buf[0..len-1] and return the updated
crc. If buf is NULL, this function returns the required initial value
for the crc. Pre- and post-conditioning (one's complement) is performed
within this function so it shouldn't be done by the application.
Usage example:
uLong crc = crc32(0L, Z_NULL, 0);
while (read_buffer(buffer, length) != EOF) {
crc = crc32(crc, buffer, length);
}
if (crc != original_crc) error();
*/
/* various hacks, don't look :) */
/* deflateInit and inflateInit are macros to allow checking the zlib version
* and the compiler's view of z_stream:
*/
extern int ZEXPORT deflateInit_ OF((z_streamp strm, int level,
const char *version, int stream_size));
extern int ZEXPORT inflateInit_ OF((z_streamp strm,
const char *version, int stream_size));
extern int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method,
int windowBits, int memLevel,
int strategy, const char *version,
int stream_size));
extern int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits,
const char *version, int stream_size));
#define deflateInit(strm, level) \
deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream))
#define inflateInit(strm) \
inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream))
#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
(strategy), ZLIB_VERSION, sizeof(z_stream))
#define inflateInit2(strm, windowBits) \
inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream))
#if !defined(_Z_UTIL_H) && !defined(NO_DUMMY_DECL)
struct internal_state {int dummy;}; /* hack for buggy compilers */
#endif
extern const char * ZEXPORT zError OF((int err));
extern int ZEXPORT inflateSyncPoint OF((z_streamp z));
extern const uLongf * ZEXPORT get_crc_table OF((void));
#ifdef __cplusplus
}
#endif
#endif /* _ZLIB_H */

220
zlib/zutil.c Normal file
View File

@@ -0,0 +1,220 @@
/* zutil.c -- target dependent utility functions for the compression library
* Copyright (C) 1995-1998 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* @(#) $Id$ */
#include "zutil.h"
struct internal_state {int dummy;}; /* for buggy compilers */
#ifndef STDC
extern void exit OF((int));
#endif
const char *z_errmsg[10] = {
"need dictionary", /* Z_NEED_DICT 2 */
"stream end", /* Z_STREAM_END 1 */
"", /* Z_OK 0 */
"file error", /* Z_ERRNO (-1) */
"stream error", /* Z_STREAM_ERROR (-2) */
"data error", /* Z_DATA_ERROR (-3) */
"insufficient memory", /* Z_MEM_ERROR (-4) */
"buffer error", /* Z_BUF_ERROR (-5) */
"incompatible version",/* Z_VERSION_ERROR (-6) */
""};
const char * ZEXPORT zlibVersion()
{
return ZLIB_VERSION;
}
#ifdef DEBUG
# ifndef verbose
# define verbose 0
# endif
int z_verbose = verbose;
void z_error (m)
char *m;
{
fprintf(stderr, "%s\n", m);
exit(1);
}
#endif
/* exported to allow conversion of error code to string for compress() and
* uncompress()
*/
const char * ZEXPORT zError(err)
int err;
{
return ERR_MSG(err);
}
#ifndef HAVE_MEMCPY
void zmemcpy(dest, source, len)
Bytef* dest;
Bytef* source;
uInt len;
{
if (len == 0) return;
do {
*dest++ = *source++; /* ??? to be unrolled */
} while (--len != 0);
}
int zmemcmp(s1, s2, len)
Bytef* s1;
Bytef* s2;
uInt len;
{
uInt j;
for (j = 0; j < len; j++) {
if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1;
}
return 0;
}
void zmemzero(dest, len)
Bytef* dest;
uInt len;
{
if (len == 0) return;
do {
*dest++ = 0; /* ??? to be unrolled */
} while (--len != 0);
}
#endif
#ifdef __TURBOC__
#if (defined( __BORLANDC__) || !defined(SMALL_MEDIUM)) && !defined(__32BIT__)
/* Small and medium model in Turbo C are for now limited to near allocation
* with reduced MAX_WBITS and MAX_MEM_LEVEL
*/
# define MY_ZCALLOC
/* Turbo C malloc() does not allow dynamic allocation of 64K bytes
* and farmalloc(64K) returns a pointer with an offset of 8, so we
* must fix the pointer. Warning: the pointer must be put back to its
* original form in order to free it, use zcfree().
*/
#define MAX_PTR 10
/* 10*64K = 640K */
local int next_ptr = 0;
typedef struct ptr_table_s {
voidpf org_ptr;
voidpf new_ptr;
} ptr_table;
local ptr_table table[MAX_PTR];
/* This table is used to remember the original form of pointers
* to large buffers (64K). Such pointers are normalized with a zero offset.
* Since MSDOS is not a preemptive multitasking OS, this table is not
* protected from concurrent access. This hack doesn't work anyway on
* a protected system like OS/2. Use Microsoft C instead.
*/
voidpf zcalloc (voidpf opaque, unsigned items, unsigned size)
{
voidpf buf = opaque; /* just to make some compilers happy */
ulg bsize = (ulg)items*size;
/* If we allocate less than 65520 bytes, we assume that farmalloc
* will return a usable pointer which doesn't have to be normalized.
*/
if (bsize < 65520L) {
buf = farmalloc(bsize);
if (*(ush*)&buf != 0) return buf;
} else {
buf = farmalloc(bsize + 16L);
}
if (buf == NULL || next_ptr >= MAX_PTR) return NULL;
table[next_ptr].org_ptr = buf;
/* Normalize the pointer to seg:0 */
*((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4;
*(ush*)&buf = 0;
table[next_ptr++].new_ptr = buf;
return buf;
}
void zcfree (voidpf opaque, voidpf ptr)
{
int n;
if (*(ush*)&ptr != 0) { /* object < 64K */
farfree(ptr);
return;
}
/* Find the original pointer */
for (n = 0; n < next_ptr; n++) {
if (ptr != table[n].new_ptr) continue;
farfree(table[n].org_ptr);
while (++n < next_ptr) {
table[n-1] = table[n];
}
next_ptr--;
return;
}
ptr = opaque; /* just to make some compilers happy */
Assert(0, "zcfree: ptr not found");
}
#endif
#endif /* __TURBOC__ */
#if defined(M_I86) && !defined(__32BIT__)
/* Microsoft C in 16-bit mode */
# define MY_ZCALLOC
#if (!defined(_MSC_VER) || (_MSC_VER < 600))
# define _halloc halloc
# define _hfree hfree
#endif
voidpf zcalloc (voidpf opaque, unsigned items, unsigned size)
{
if (opaque) opaque = 0; /* to make compiler happy */
return _halloc((long)items, size);
}
void zcfree (voidpf opaque, voidpf ptr)
{
if (opaque) opaque = 0; /* to make compiler happy */
_hfree(ptr);
}
#endif /* MSC */
#ifndef MY_ZCALLOC /* Any system without a special alloc function */
voidpf zcalloc (opaque, items, size)
voidpf opaque;
unsigned items;
unsigned size;
{
if (opaque) items += size - size; /* make compiler happy */
return (voidpf)calloc(items, size);
}
void zcfree (opaque, ptr)
voidpf opaque;
voidpf ptr;
{
free(ptr);
if (opaque) return; /* make compiler happy */
}
#endif /* MY_ZCALLOC */

224
zlib/zutil.h Normal file
View File

@@ -0,0 +1,224 @@
/* zutil.h -- internal interface and configuration of the compression library
* Copyright (C) 1995-1998 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* WARNING: this file should *not* be used by applications. It is
part of the implementation of the compression library and is
subject to change. Applications should only use zlib.h.
*/
/* @(#) $Id$ */
#ifndef _Z_UTIL_H
#define _Z_UTIL_H
#include "../rsync.h"
#include "zlib.h"
#if 0
#ifdef STDC
# include <stddef.h>
# include <string.h>
# include <stdlib.h>
#endif
#ifdef NO_ERRNO_H
extern int errno;
#else
# include <errno.h>
#endif
#endif
#ifndef local
# define local static
#endif
/* compile with -Dlocal if your debugger can't find static symbols */
typedef unsigned char uch;
typedef uch FAR uchf;
typedef unsigned short ush;
typedef ush FAR ushf;
typedef unsigned long ulg;
extern const char *z_errmsg[10]; /* indexed by 2-zlib_error */
/* (size given to avoid silly warnings with Visual C++) */
#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)]
#define ERR_RETURN(strm,err) \
return (strm->msg = (char*)ERR_MSG(err), (err))
/* To be used only when the state is known to be valid */
/* common constants */
#ifndef DEF_WBITS
# define DEF_WBITS MAX_WBITS
#endif
/* default windowBits for decompression. MAX_WBITS is for compression only */
#if MAX_MEM_LEVEL >= 8
# define DEF_MEM_LEVEL 8
#else
# define DEF_MEM_LEVEL MAX_MEM_LEVEL
#endif
/* default memLevel */
#define STORED_BLOCK 0
#define STATIC_TREES 1
#define DYN_TREES 2
/* The three kinds of block type */
#define MIN_MATCH 3
#define MAX_MATCH 258
/* The minimum and maximum match lengths */
#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */
/* target dependencies */
#ifdef MSDOS
# define OS_CODE 0x00
# ifdef __TURBOC__
# if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__))
/* Allow compilation with ANSI keywords only enabled */
void _Cdecl farfree( void *block );
void *_Cdecl farmalloc( unsigned long nbytes );
# else
# include <alloc.h>
# endif
# else /* MSC or DJGPP */
# include <malloc.h>
# endif
#endif
#ifdef OS2
# define OS_CODE 0x06
#endif
#ifdef WIN32 /* Window 95 & Windows NT */
# define OS_CODE 0x0b
#endif
#if defined(VAXC) || defined(VMS)
# define OS_CODE 0x02
# define F_OPEN(name, mode) \
fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512")
#endif
#ifdef AMIGA
# define OS_CODE 0x01
#endif
#if defined(ATARI) || defined(atarist)
# define OS_CODE 0x05
#endif
#if defined(MACOS) || defined(TARGET_OS_MAC)
# define OS_CODE 0x07
# ifndef fdopen
# define fdopen(fd,mode) NULL /* No fdopen() */
# endif
#endif
#if defined(__MWERKS__) && !defined(fdopen)
# if __dest_os != __be_os && __dest_os != __win32_os
# define fdopen(fd,mode) NULL
# endif
#endif
#ifdef __50SERIES /* Prime/PRIMOS */
# define OS_CODE 0x0F
#endif
#ifdef TOPS20
# define OS_CODE 0x0a
#endif
#if defined(_BEOS_) || defined(RISCOS)
# define fdopen(fd,mode) NULL /* No fdopen() */
#endif
#if (defined(_MSC_VER) && (_MSC_VER >= 600))
# define fdopen(fd,type) _fdopen(fd,type)
#endif
/* Common defaults */
#ifndef OS_CODE
# define OS_CODE 0x03 /* assume Unix */
#endif
#ifndef F_OPEN
# define F_OPEN(name, mode) fopen((name), (mode))
#endif
/* functions */
#ifdef HAVE_STRERROR
extern char *strerror OF((int));
# define zstrerror(errnum) strerror(errnum)
#else
# define zstrerror(errnum) ""
#endif
#if defined(pyr)
# define NO_MEMCPY
#endif
#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__)
/* Use our own functions for small and medium model with MSC <= 5.0.
* You may have to use the same strategy for Borland C (untested).
* The __SC__ check is for Symantec.
*/
# define NO_MEMCPY
#endif
#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY)
# define HAVE_MEMCPY
#endif
#ifdef HAVE_MEMCPY
# ifdef SMALL_MEDIUM /* MSDOS small or medium model */
# define zmemcpy _fmemcpy
# define zmemcmp _fmemcmp
# define zmemzero(dest, len) _fmemset(dest, 0, len)
# else
# define zmemcpy memcpy
# define zmemcmp memcmp
# define zmemzero(dest, len) memset(dest, 0, len)
# endif
#else
extern void zmemcpy OF((Bytef* dest, Bytef* source, uInt len));
extern int zmemcmp OF((Bytef* s1, Bytef* s2, uInt len));
extern void zmemzero OF((Bytef* dest, uInt len));
#endif
/* Diagnostic functions */
#ifdef DEBUG
# include <stdio.h>
extern int z_verbose;
extern void z_error OF((char *m));
# define Assert(cond,msg) {if(!(cond)) z_error(msg);}
# define Trace(x) {if (z_verbose>=0) fprintf x ;}
# define Tracev(x) {if (z_verbose>0) fprintf x ;}
# define Tracevv(x) {if (z_verbose>1) fprintf x ;}
# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;}
# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;}
#else
# define Assert(cond,msg)
# define Trace(x)
# define Tracev(x)
# define Tracevv(x)
# define Tracec(c,x)
# define Tracecv(c,x)
#endif
typedef uLong (ZEXPORT *check_func) OF((uLong check, const Bytef *buf,
uInt len));
voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size));
void zcfree OF((voidpf opaque, voidpf ptr));
#define ZALLOC(strm, items, size) \
(*((strm)->zalloc))((strm)->opaque, (items), (size))
#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr))
#define TRY_FREE(s, p) {if (p) ZFREE(s, p);}
#endif /* _Z_UTIL_H */