pax_global_header00006660000000000000000000000064136023551200014507gustar00rootroot0000000000000052 comment=0884f323a5afc99658cf47584acfcf695717caca ncompress-4.2.4.6/000077500000000000000000000000001360235512000136735ustar00rootroot00000000000000ncompress-4.2.4.6/.travis.yml000066400000000000000000000002551360235512000160060ustar00rootroot00000000000000# Travis build integration. # https://docs.travis-ci.com/ language: c compiler: - clang - gcc sudo: false os: - linux - osx - windows script: ./travis/main.sh ncompress-4.2.4.6/Acknowleds000066400000000000000000000012551360235512000157130ustar00rootroot00000000000000Acknowledgments: (N)compress, Version 4.2 Thanks to the previous authors whom I didn't contact, for making the program available originally. Spencer W. Thomas (decvax!harpo!utah-cs!utah-gr!thomas) Jim McKie (decvax!mcvax!jim) Steve Davies (decvax!vax135!petsd!peora!srd) Ken Turkowski (decvax!decwrl!turtlevax!ken) James A. Woods (decvax!ihnp4!ames!jaw) Joe Orost (decvax!vax135!petsd!joe) Dave Mack (csu@alembic.acs.com) Also thanks to Frans Meulenbroeks, Jan Christiaan van Winkel, Peter van Hooft and the testers of comp.sources.reveiwed for testing this version on different platforms. -- Peter Jannesen ncompress-4.2.4.6/Changes000066400000000000000000000135501360235512000151720ustar00rootroot00000000000000(N)compress version 4.2.4.6 * Fix tests under macOS * Drop support for NOFUNCDEF * Drop old unused MARK & SIZE_INNER_LOOP defines * Add chmod/chown stubs for AMIGA/DOS * Add a WINDOWS define for disabling chmod/chown * Simplify LSTAT checking * Disable utime usage on AMIGA/DOS/WINDOWS * Add a fallback for access() for DOS & WINDOWS * Disable unistd.h include on DOS & WINDOWS * Disable chmod/chown/utime for mingw builds * Add xxx->_xxx redirects on WINDOWS for filesystem funcs * Add support for Windows in Travis * Add PREFIX conformance, add option to only install main program by Eli Schwartz * Don't strip binaries by default by Eli Schwartz * Set the mandir to use $(PREFIX)/share/man by default by Eli Schwartz * Do not set exit_code when an error is ignored by Petr Kubat * Use default CFLAGS when using GNU make * Fix typos in Makefile.def * Tweak Changes style for better markdown integration (N)compress version 4.2.4.5 * New homepage https://github.com/vapier/ncompress * Switch to intmax_t for nlink_t fields when printing * Make builds more reproducible by dropping datestamps * Fix integer overflow in maxmaxcode computation by Jakub Wilk * Don't leak file descriptor in error cases by Pavel Raiskup * Drop 8.3 filename checks for old DOS/Windows * Change signal ifdef logic to the signal names * Fix -Werror=parentheses errors with newer compilers * Define LSTAT=1 in modern builds by default * Change pathnames to be dynamic to avoid hardcoded 1k limit * Add a standard -h (help) option * Change version output to go to stdout * Start a testsuite! * Add support for -- to halt option parsing * Add a uncompress(1) link to compress(1) (N)compress version 4.2.4.4 * Add some spelling fixes from Kenneth J. Pronovici * Tweak makefile syntax for make 3.82 * Tweak by Kenneth J. Pronovici to escape hyphens in man pages for groff (N)compress version 4.2.4.3 * Check return value of chown(). * Fix from Fedora for checking malloc() return. * Fix from Fedora/gzip to avoid integer overflow for CVE-2010-0001. (N)compress version 4.2.4.2 * Integrate build/man touchups from Debian. * Add fix from Fedora for handling of 0 byte files. * Pull in POSIX standard headers for prototypes (stdlib,string,unistd). * Replace rindex() with strrchr(). * Don't set CC by default in Makefile.def and add CFLAGS/CPPFLAGS/LDFLAGS where appropriate by default. * Add support for DESTDIR to the install target. (N)compress version 4.2.4.1 * Fix possible bss buffer underflow CVE-2006-1168 * New homepage http://ncompress.sourceforge.net/ (N)compress version 4.2.4 * Fix '-c' flag. * Fix utime error. * Added AMIGA support (Sascha Wildner). * Div. remarks added. (N)compress version 4.2.3 * Comp.source.reveiwed release. (N)compress version 4.2.2 Minor changes after the reviewes from comp.sources.reviewed * Change the name to ncompress because of version problems. * Start all scripts with ':' * Added libary options to buidl script. * Install zmore zcmp zdiff and manuals. * Added patchlevel.h * Updated README file. Created LZW.INFO * a complete grammatical go-round * Use utime.h if availble * Change de default input/output buffer size to BUFSIZ. Because of performance problems with read a head on systems. * Build generates a makefile. compress version 4.2.1 improvements * Change the name to ncompress because of version problems. * Completly rewrite of the compress and decompress functions. compress speedup 25-50% (user cpu time). decompress speedup 20-30% (user cpu time). o Add special fast compress hash algorithm. * Fix some minor things. * use #include if availble. * Cleanup the source code (I think so). * Test if filename is not to long. This is done on runtime no fix length size any more. * Powerfull build script (test almost every thing). Modifications for version 4.1: * Added -r command line flag to allow recursive compression/ decompression of directory trees. As a side-effect, compress no longer tries to compress/decompress anything that isn't a regular file. In particular, it ignores symbolic links. * zcat no longer cares whether a filename ends in .Z or not - it relies on the magic number in the file. If zcat is given a filename that doesn't end with .Z and the file referenced doesn't exist, zcat will append a .Z and try to open that instead. * compress -f will now compress multiply hardlinked files. Uncompress does not recreate the hard link, it creates a new file. * Removed compressdir/uncompressdir - no longer needed. * Removed atob/btoa/tarmail/untarmail - my versions are based on btoa 5.2 which is not compatible with the atob included with compress4.0. Compress version 4.0 improvements: * compress() speedup (10-50%) by changing division hash to xor * decompress() speedup (5-10%) * Memory requirements reduced (3-30%) * Stack requirements reduced to less than 4kb * Removed 'Big+Fast' compress code (FBITS) because of compress speedup * Portability mods for Z8000 and PC/XT (but not zeus 3.2) * Default to 'quiet' mode * Unification of 'force' flags * Manual page overhaul * Portability enhancement for M_XENIX * Removed text on #else and #endif * Added "-V" switch to print version and options * Added #defines for SIGNED_COMPARE_SLOW * Added Makefile and "usermem" program * Removed all floating point computations * New programs: compressdir - compress all files on a directory uncompressdir - uncompress all files on a directory zcmp - cmp compressed files zdiff - diff compressed files The following are with thanks to philabs!per: btoa - convert binary to ascii for mailing atob - convert ascii to binary with checksum tarmail - tar, compress, btoa, and mail files untarmail - restore "tarmail" files WARNING: These last few programs are not compatible with the original ones from the net. The encoding has changed. See btoa.c for more info. ncompress-4.2.4.6/GNUmakefile000066400000000000000000000012361360235512000157470ustar00rootroot00000000000000# this assumes a recent system -- you're using GNU make right ? # POSIX make doesn't support default values, so we export from here. CFLAGS ?= -O2 -g CFLAGS += -Wall export CFLAGS compress cleanup install install_core install_extra: Makefile $(MAKE) -f Makefile $@ clean: cleanup distclean: cleanup rm -f Makefile Makefile: Makefile.def GNUmakefile sed \ -e 's:options= :options= -DUTIME_H -DLSTAT :' \ Makefile.def > Makefile check: ./tests/runtests.sh PN = ncompress PV = $(shell awk '{print $$NF; exit}' Changes) P = $(PN)-$(PV) dist: git archive --prefix=$(P)/ HEAD | gzip -9 > $(P).tar.gz .PHONY: check clean cleanup compress dist distclean install ncompress-4.2.4.6/LICENSE.txt000066400000000000000000000001411360235512000155120ustar00rootroot00000000000000The ncompress code is released into the public domain. See the UNLICENSE file for more details. ncompress-4.2.4.6/LZW.INFO000066400000000000000000000103731360235512000150300ustar00rootroot00000000000000The following article from James A. Woods, one of the earlier authors of compress, explains its relationship to the Unisys patent on the LZW compression method: From uunet!zephyr.ens.tek.com!uw-beaver!mit-eddie!wuarchive!usc!ucsd!ucbvax!agate!riacs!jaw Wed Aug 1 15:06:59 EDT 1990 Article: 1282 of gnu.misc.discuss Path: alembic!uunet!zephyr.ens.tek.com!uw-beaver!mit-eddie!wuarchive!usc!ucsd!ucbvax!agate!riacs!jaw From: jaw@riacs.edu (James A. Woods) Newsgroups: gnu.misc.discuss Subject: Sperry patent #4,558,302 does *not* affect 'compress' Keywords: data compression, algorithm, patent Message-ID: <1990Jul31.220935.1424@riacs.edu> Date: 31 Jul 90 22:09:35 GMT Organization: RIACS, NASA Ames Research Center Lines: 69 # "The chief defect of Henry King Was chewing little bits of string." -- Hilaire Belloc, Cautionary Tales [1907] As a co-author of 'compress' who has had contact with an attorney for Unisys (nee Sperry), I would like to relay a very basic admission from Unisys that noncommercial use of 'compress' is perfectly legal. 'Compress' is also commercially distributed by AT&T as part of Unix System 5 release 4, with no further restrictions placed upon the use of the binary, as far as I am aware. From conversations with Professor Abraham Lempel and others, it appears that neither AT&T, Sun Microsystems, Hewlett Packard, nor IBM are paying any sort of license fees to Unisys in conjunction with patent #4,558,302. It may be true that some organizations are paying fees for data compression technology licensed from one or more of the many holders of compression patents, but this is all independent from 'compress'. In particular, I received a letter at NASA dated October 1, 1987 from John B. Sowell of the Unisys law department, informing me for the first time that some form of LZW was patented. I naturally expressed skepticism that an algorithm could be patented (a murky legal area which remains so), stated that 'compress' is not identical to LZW, and in fact was designed, developed, and distributed before the ink on the patent was dry. Several telephone conversations later, Mr. Sowell intimated that they would *not* seek any fees from users of 'compress' but instead were signing licensees for hardware implementations of LZW. So, regardless of what you believe about a shady legal area, if anyone from Unisys contacts you to extract tribute for the use of 'compress', please tell them that, first, it is not theirs to begin with, and, second, there is someone who will testify in court about the conversation above. It is not even clear if anyone can "own" 'compress', since original developer Spencer Thomas, myself, and others placed the code in the public domain long before the adoption of the Berne copyright convention. In light of the events above, it seems that the Free Software Foundation is being unduly paranoid about the use of 'compress'. Now I can well believe that FSF is more likely to be a legal target than a behemoth like AT&T, but if they are simply redistributing untouched free software developed years ago in the public sector, I see no problem. Aside: I am investigating, possibly for a case history to be recycled to USENET, the particulars of data compression patents. I am aware of the following patents: IBM's Miller-Wegman LZ variant, those of Telcor and ACT [losing candidates for the British Telecom modem standard], James A. Storer's work on limited lookahead as explicated in his text "Data Compression (methods and theory)", Computer Science Press, 1988, and the various patents pending associated with the Fiala and Greene CACM article of April, 1989 on textual substitution methods. If you have any lore, send it this way. Sincerely, James A. Woods NASA Ames Research Center (RIACS) jaw@riacs.edu (or ames!jaw) P.S. The algorithm patent issue certainly is a "topic A" at the moment. One useful reference is the review article by Anthony and Colwell -- "Litigating the Validity and Infringement of Software Patents" in Washington and Lee Law Review, volume 41, fall 1984. I know Robert Colwell personally. As a practicing patent attorney, he tells me that, at a minimum, use of an invention "for research purposes" is legitimate. ncompress-4.2.4.6/MANIFEST000066400000000000000000000010361360235512000150240ustar00rootroot00000000000000 File Name Archive # Description ----------------------------------------------------------- Acknowleds 1 Changes 1 Makefile.def 1 MANIFEST 1 This shipping list LZW.INFO 1 README 1 build 1 compress.1 1 compress42.c 1/2 patchlevel.h 2 zcmp 1 zcmp.1 1 zdiff 1 zmore 1 zmore.1 1 ncompress-4.2.4.6/Makefile.def000066400000000000000000000043111360235512000160670ustar00rootroot00000000000000# Makefile generated by build. # C compiler #CC=cc # Install prefix DESTDIR= # Base install directory PREFIX=/usr/local # Install directory for binaries BINDIR=$(PREFIX)/bin # Install directory for manual MANDIR=$(PREFIX)/share/man/man1 # compiler options: # options is a collection of: # # -DAMIGA=1 Amiga support. # -DDIRENT=1 Use dirent.h # -DSYSDIR=1 Use sys/dir.h # -DLSTAT=1 Use lstat for finding symlinks. # -DUTIME_H=1 Use utime.h # -DUSERMEM= Available memory for compress (default 800k). # -DREGISTERS= Number of registers (default 2). # -DIBUFSIZ= Input buffer size (default BUFSIZ). # -DOBUFSIZ= Output buffer size (default BUFSIZ) # -DBYTEORDER= Byte order (default: unknown). # -DNOALLIGN=1 Data word alignment (default: yes). # -DDEF_ERRNO=1 Define errno (not defined in errno.h). # -DMAXSEG_64K=1 -BITS=16 Support segment processor like 80286. # options= $(CFLAGS) $(CPPFLAGS) -DDIRENT=1 -DUSERMEM=800000 -DREGISTERS=3 # library options LBOPT= $(LDFLAGS) compress: Makefile compress42.c patchlevel.h $(CC) -o compress $(options) compress42.c $(LBOPT) install_core: compress [ -f $(DESTDIR)$(BINDIR)/compress ] && \ { rm -f $(DESTDIR)$(BINDIR)/compress.old ; \ mv $(DESTDIR)$(BINDIR)/compress $(DESTDIR)$(BINDIR)/compress.old ; } || : rm -f $(DESTDIR)$(BINDIR)/uncompress $(DESTDIR)$(BINDIR)/zcat mkdir -p $(DESTDIR)$(BINDIR) $(DESTDIR)$(MANDIR) cp compress $(DESTDIR)$(BINDIR)/compress rm -f $(DESTDIR)$(BINDIR)/uncompress ln $(DESTDIR)$(BINDIR)/compress $(DESTDIR)$(BINDIR)/uncompress cp compress.1 uncompress.1 $(DESTDIR)$(MANDIR)/. chmod 0644 $(DESTDIR)$(MANDIR)/compress.1 $(DESTDIR)$(MANDIR)/uncompress.1 install_extra: install_core mkdir -p $(DESTDIR)$(BINDIR) $(DESTDIR)$(MANDIR) rm -f $(DESTDIR)$(BINDIR)/zcat ln -f $(DESTDIR)$(BINDIR)/compress $(DESTDIR)$(BINDIR)/zcat cp zcmp zdiff zmore $(DESTDIR)$(BINDIR)/. chmod 0755 $(DESTDIR)$(BINDIR)/compress $(DESTDIR)$(BINDIR)/zcmp $(DESTDIR)$(BINDIR)/zdiff $(DESTDIR)$(BINDIR)/zmore cp zcmp.1 zmore.1 $(DESTDIR)$(MANDIR)/. chmod 0644 $(DESTDIR)$(MANDIR)/zcmp.1 $(DESTDIR)$(MANDIR)/zmore.1 install: install_extra cleanup: rm -f compress compress.def comp.log ncompress-4.2.4.6/README.md000066400000000000000000000074221360235512000151570ustar00rootroot00000000000000# About This is version 4.2 of (N)compress (an improved version of compress 4.1). Compress is a fast, simple LZW file compressor. Compress does not have the highest compression rate, but it is one of the fastest programs to compress data. Compress is the defacto standard in the UNIX community for compressing files. (N)compress 4.2 has a special, fast compression hash algorithm. This algorithm uses more memory than the old hash table. If you don't want the faster hash table algorithm set 'Memory free for compress' below 800000. zcmp, zdiff, zmore were copied from version 4.1 without any changes. The output of (N)compress 4.2 is fully compatible with that of compress 3.0. In other words, the output of (N)compress 4.2 may be fed into uncompress 3.0 or the output of compress 3.0 may be fed into uncompress 4.2. The output of (N)compress 4.2 is not compatible with that of compress 2.0. However, compress 4.2 still accepts the output of compress 2.0. To generate output that is compatible with compress 2.0, use the undocumented "-C" flag. # Building For recent systems with GNU make, you can simply run `make` as the default 'GNUMakefile' will get picked up. 'build' is a menu driven shell script for compiling, testing and installing (N)compress. So to build and install (N)compress all you have to do is run build. Build will first test your system for default settings. The current compile settings are stored in a special file called compress.def. For user with problems with build there is a default makefile included called 'Makefile.def'. Also build is capable of generating a Makefile with all options (option genmake). # Support [![Build Status](https://travis-ci.org/vapier/ncompress.svg?branch=ncompress-4.2.4)](https://travis-ci.org/vapier/ncompress) Send comments, complaints and especially patches relating to https://github.com/vapier/ncompress/issues # Licensing The ncompress code is released into the public domain. See the [UNLICENSE](UNLICENSE) file for more details. # Patents All existing patents on the LZW algorithm have [expired world-wide](http://en.wikipedia.org/wiki/LZW#Patent_issues). So LZW is now patent free. # Remarks - Build is a bourne shell script. On some system it is necessary to type 'sh build'. - The build script usages tput for nice screen handling of the script. If your system has no tput no problems. - For configuration testing build uses a lot of small C programs. During those test stderr is redirected to /dev/null. During the compilation of compress output is NOT redirected. - The /bin/sh under Ultrix can't handle ${var:-str} so use ksh for the build script. - The output if (N)compress 4.2 is not exactly the same as compress 4.0 because of different table reset point. The output of (N)compress 4.2 is 100% compatible with compress 4.0 - Some systems has performance problems with reads bigger than BUFSIZ (The read a head function is not working as expected). For those system use the default BSIZE input buffer size. - (N)compress can by slower on small files (<10Kb) because of a great table reset overhead. Use cpio or tar to make 1 bigger file if possible, it is faster and also gives a better compression ratio most of the time. - (N)compress is slower in vax systems because of removing some undocumented inline assembler. - files compressed on a large machine with more bits than allowed by a version of compress on a smaller machine cannot be decompressed! Use the "-b12" flag to generate a file on a large machine that can be uncompressed on a 16-bit machine. - compatibility with compress 3.0 has not been tested in the 4.2 release of (N)compress. - There has been 1 problem report in relation to GCC 2.0 on a sparc workstation. GCC 2.0 seems to generate a bad compress. Use the standard c compiler 'cc'. ncompress-4.2.4.6/UNLICENSE000066400000000000000000000022731360235512000151470ustar00rootroot00000000000000This is free and unencumbered software released into the public domain. Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means. In jurisdictions that recognize copyright laws, the author or authors of this software dedicate any and all copyright interest in the software to the public domain. We make this dedication for the benefit of the public at large and to the detriment of our heirs and successors. We intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. For more information, please refer to ncompress-4.2.4.6/build000077500000000000000000000462421360235512000147300ustar00rootroot00000000000000: #!/bin/sh # version="4.2.4" echo "Build (N)compress ${version}" CLS=`sh -c 'tput clear' 2>/dev/null` if expr `echo "foo\c"` : '.*c' >/dev/null then n='-n' c='' else n='' c='\c' fi trap 'rm -f /tmp/sh$$.tm* /tmp/sh$$.f* /tmp/sh$$.log /tmp/sh*.c' 0 trap 'set +x ; exit 1' 1 2 15 [ -f compress.def ] && . ./compress.def while true do if [ "${DEFINED}" = yes ] then echo "${CLS} Build (N)compress ${version} 1. Directory to install compress in: ${BINDIR} manual in : ${MANDIR} 2. Memory free for compress : ${USERMEM} 3. Input/Output buffer size : ${IBUFSIZ} ${OBUFSIZ} 4. C Compiler : ${CC} 5. Compiler options : ${CCOPT:---none--} 6. Libary options : ${LBOPT:---none--} 7. Special options for your system : ${EXTRA:---none--} 8. Number of register variable : ${REGISTERS} 9. Symbolic links : ${LSTAT} 10. Use include : ${UTIME_H}" if [ ".${DIRENT}" = .yes ] then echo "11. Your system support dirent.h" else if [ ".${SYSDIR}" = .yes -a ".${DIRENT}" != .yes ] then echo "11. Your system support sys/dir.h" else echo "11. No directory support -r disabled." fi fi echo "12. Word must start at even addres: ${NOALLIGN}, Bytorder on your system: ${BYTEORDER} (1=msb)" echo " d. Set default settings mkshar. Create shell archive c. Compile compress mktar. Create tar archive t. Test compress cleanup. Cleanup i. Install compress genmake. Generate makefile q. Stop " echo ${n} " Choice [1..10,d,c,t,i,q,mkshar,mktar,cleanup] : ${c}" ( echo "# Current parameters." for var in CC CCOPT LBOPT BINDIR MANDIR DIRENT SYSDIR IBUFSIZ \ OBUFSIZ USERMEM REGISTERS LSTAT BYTEORDER NOALLIGN \ EXTRA DEFINED UTIME_H do echo "${var}='`eval echo \$\{${var}\}`'" done ) >compress.def read choice var1 var2 var3 var4 varr echo "" else choice=D fi case "${choice}" in 1) if [ ".${var1}" = . ] then echo ${n} "Directory to install compress in (default:${BINDIR}) ? ${c}" read var1 dummy fi BINDIR="${var1:-${BINDIR}}" if [ ".${var2}" = . ] then echo ${n} "Directory to install manuals in (default:${MANDIR}) ? ${c}" read var2 dummy fi MANDIR="${var2:-${MANDIR}}" ;; 2) if [ ".${var1}" = . ] then echo "Compress use a lot of memory, the more memory it can just the faster" echo "the programm is and the better compression is." echo ${n} "Memory free for compress (default:${USERMEM}) ? ${c}" read var1 dummy fi USERMEM="${var1:-${USERMEM}}" ;; 3) if [ ".${var1}" = . ] then echo "For input and output compress use buffers. A bigger buffer reduce" echo "system (kernel) overhead. If your system is a 16 bits system don't" echo "make the buffers bigger than 2048 bytes. The default 2048 is in" echo "most cases a good answer." echo ${n} "Best input buffer size (default:${IBUFSIZ}) ? ${c}" read var1 var2 dummy if [ ".${var2}" = . ] then echo ${n} "Best output buffer size (default:${OBUFSIZ}) ? ${c}" read D dummy fi fi var2="${var2:-${var1}}" IBUFSIZ="${var1:-${IBUFSIZ}}" OBUFSIZ="${var2:-${OBUFSIZ}}" ;; 4) if [ ".${var1}" = . ] then echo "C compiler to use for compilation (must by cc compatible)". echo ${n} "C Compiler (default:${CC}) ? ${c}" read var1 dummy fi CC="${var1:-${CC}}" ;; 5) if [ ".${var1}" = . ] then echo ${n} "Compiler options (default:${CCOPT:-none}) ? ${c}" read var1 fi [ ".${var1}" != . ] && CCOPT="${var1} ${var2} ${var3} ${var4} ${varr}" ;; 6) if [ ".${var1}" = . ] then echo ${n} "Libary options (default:${LBOPT:-none}) ? ${c}" read var1 fi [ ".${var1}" != . ] && LBOPT="${var1} ${var2} ${var3} ${var4} ${varr}" ;; 7) if [ ".${var1}" = . ] then echo "Some system needs extra defines see README" echo ${n} "Special for your system (default:${EXTRA:-none}) ? ${c}" read var1 fi [ ".${var1}" != . ] && EXTRA="${var1} ${var2} ${var3} ${var4} ${varr}" ;; 8) if [ ".${var1}" = . ] then echo ${n} "Number of register variable (default:${REGISTERS}) ? ${c}" read var1 dummy fi REGISTERS="${var1:-${REGISTERS}}" ;; 9) if [ ".${var1}" = . ] then echo ${n} "Symbolic links (default:${LSTAT}) ? ${c}" read var1 dummy fi case "${var1:-${DIRENT}}" in y|Y|yes|YES) LSTAT=yes; ;; *) LSTAT=no; ;; esac ;; 10) if [ ".${var1}" = . ] then echo ${n} "Do your system support utime.h (default:${UTIME_H}) ? ${c}" read var1 dummy fi case "${var1:-${DIRENT}}" in y|Y|yes|YES) UTIME_H=yes; ;; *) UTIME_H=no; ;; esac ;; 11) case "${var1}" in dirent) DIRENT=yes; SYSDIR=no; ;; sys/dir) DIRENT=no; SYSDIR=yes; ;; *) echo ${n} "Do your system support dirent.h (default:${DIRENT}) ? ${c}" read var1 dummy case "${var1:-${DIRENT}}" in y|Y|yes|YES) DIRENT=yes; SYSDIR=no; ;; *) DIRENT=no; SYSDIR=no; ;; esac if [ ${DIRENT} = no ] then echo ${n} "Do your system support sys/dir.h (default:${SYSDIR}) ? ${c}" read var1 dummy case "${var1:-${SYSDIR}}" in y|Y|yes|YES) DIRENT=no; SYSDIR=yes; ;; *) DIRENT=no; SYSDIR=no; ;; esac fi ;; esac ;; 12) if [ ".${var1}" = . ] then echo "If your system don't need word allignment for words (like 80386)" echo "compress can use this fact to by faster. If your are not sure type y" echo ${n} "Must words start at a even address (default:${NOALLIGN}) ? ${c}" read var1 var2 varr fi if [ ".${var2}" = . ] then echo ${n} "Byteorder on your system (default:${BYTEORDER}) ? ${c}" read var2 varr fi case "${var1}" in n|no|N|NO) var1=no; ;; *) var1=yes; ;; esac NOALLIGN="${var1:-${NOALLIGN}}" BYTEORDER="${var2:-${BYTEORDER}}" ;; d|D) echo "Testing the system to find out what kind of system we have." BINDIR=/usr/bin MANDIR=/usr/man/man1 DIRENT=no SYSDIR=no UTIME_H=no IBUFSIZ=2048 OBUFSIZ=2048 USERMEM=0 REGISTERS=2 LSTAT=no CCOPT='-O' LBOPT= EXTRA= [ -f /usr/include/sys/dir.h ] && { SYSDIR=yes; } [ -f /usr/include/dirent.h ] && { DIRENT=yes; } [ -f /usr/include/utime.h ] && { UTIME_H=yes; } [ -d /usr/local/bin ] && { BINDIR=/usr/local/bin; } [ -d /usr/local/man ] && { BINDIR=/usr/local/man/man1; } [ -f /usr/bin/compress ] && { BINDIR=/usr/bin; } if [ ".${CC}" = . ] then echo ${n} "Find compiler. Compiler is: ${c}" echo 'main() {return 0;}' >/tmp/sh$$.c for cc in cc gcc do if ${cc} -c /tmp/sh$$.c >/dev/null 2>&1 then rm -f sh$$.o CC=${cc} echo ${CC} break fi done if [ ".${CC}" = . ] then echo "Can't file one of the standaard compilers. Give C Compiler name" echo ${n} "C Compiler : ${c}" read CC dummy fi fi echo ${n} "Test best buffer size: ${c}" cat >/tmp/sh$$.c < main() { int size; size = 1024; #ifdef BUFSIZ if (size < BUFSIZ) size = BUFSIZ; #endif if (sizeof(int)<4) size = 2048; printf("%d\n", size); return 0; } ! ${CC} /tmp/sh$$.c && IBUFSIZ=`./a.out` rm -f /tmp/sh$$.c a.out OBUFSIZ=${IBUFSIZ} echo "${IBUFSIZ}" echo ${n} "Test byte order of system: ${c}" cat >/tmp/sh$$.c </tmp/sh$$.c </dev/null` NOALLIGN="${NOALLIGN:-yes}" echo ${NOALLIGN} rm -f /tmp/sh$$.c a.out core echo ${n} "Test number of register vars. Registers var: ${c}" cat >/tmp/sh$$.c < 0 && l1 < 21) printf("%ld", l1); exit(0); } ! cc /tmp/sh$$.c && REGISTERS=`./a.out` REGISTERS=${REGISTERS:-2}; echo ${REGISTERS} rm -f a.out /tmp/sh$$.c echo ${n} "Test if errno is declared in errno.h: ${c}" cat >/tmp/sh$$.c < #include main() { return errno; } ! if cc /tmp/sh$$.c then echo "Yes" else echo "No" EXTRA="${EXTRA} -DDEF_ERRNO=1" fi rm -f a.out /tmp/sh$$.c echo ${n} "Test if system support symbolic links? ${c}" cat >/tmp/sh$$.c </dev/null 2>&1 && LSTAT=yes echo "${LSTAT}" rm -f a.out /tmp/sh$$.c echo ${n} "Test availble memory${c}" for size in 75000 130000 230000 440000 800000 do cat >/tmp/sh$$.c </dev/null 2>&1 || break ./a.out || break rm a.out /tmp/sh$$.c USERMEM=${size} echo ${n} " ${size}${c}" done rm a.out /tmp/sh$$.c echo "" if [ ${USERMEM} = 0 ] then echo ${n} "Memory size is 0, segmented processor: ${c}" cat >/tmp/sh$$.c </dev/null 2>&1 then : else opt="-Ml" while [ ".${opt}" != . ] do if ${CC} ${opt} /tmp/sh$$.c >/dev/null 2>&1 then : else CCOPT="${CCOPT} ${opt}" break fi echo ${n} "Large model compile option: ${c}" read opt dummy done fi if [ -f ./a.out ] then if ./a.out then echo "Yes" MEMSIZE=0 EXTRA="${EXTRA} -DMAXSEG_64K=1 -DBITS=16" else echo "No" fi fi rm ./a.out /tmp/sh$$.c fi DEFINED=yes echo "" echo "I have now create the default options for compiling compress ${version}" ;; c|C) options="${CCOPT} -o compress" [ "${DIRENT}" = yes ] && options="${options} -DDIRENT=1" [ "${SYSDIR}" = yes ] && options="${options} -DSYSDIR=1" [ "${LSTAT}" != no ] && options="${options} -DLSTAT=1" [ "${UTIME_H}" != no ] && options="${options} -DUTIME_H=1" options="${options} -DUSERMEM=${USERMEM}" options="${options} -DREGISTERS=${REGISTERS}" options="${options} -DIBUFSIZ=${IBUFSIZ} -DOBUFSIZ=${OBUFSIZ}" options="${options} -DBYTEORDER=${BYTEORDER}" [ "${NOALLIGN}" = no ] && options="${options} -DNOALLIGN=1" options="${options} ${EXTRA}" echo "" echo "Compiling compress ${version}" echo ${CC} ${options} compress42.c ${LBOPT} if ${CC} ${options} compress42.c ${LBOPT} then echo "" ./compress -V echo "" echo "Compress compiled, use 'i' to install compress in ${BINDIR}" else echo "" echo "Error(s) in compilation" fi echo "" echo ${n} "Press return to continue${c}" read dummy ;; s|S) options="-O -S" [ "${DIRENT}" = yes ] && options="${options} -DDIRENT=1" [ "${SYSDIR}" = yes ] && options="${options} -DSYSDIR=1" [ "${LSTAT}" != no ] && options="${options} -DLSTAT=1" [ "${UTIME_H}" != no ] && options="${options} -DUTIME_H=1" options="${options} -DUSERMEM=${USERMEM}" options="${options} -DREGISTERS=${REGISTERS}" options="${options} -DIBUFSIZ=${IBUFSIZ} -DOBUFSIZ=${OBUFSIZ}" options="${options} -DBYTEORDER=${BYTEORDER}" [ "${NOALLIGN}" = no ] && options="${options} -DNOALLIGN=1" options="${options} ${EXTRA}" echo "" echo "Compiling compress ${version}" echo ${CC} ${options} compress42.c ${CC} ${options} compress42.c echo "" echo ${n} "Press return to continue${c}" read dummy ;; t|T) if [ ! -x ./compress ] then echo "Compile compress first before testing!" else if [ ".${var1}" = . ] then echo "To test compress you need a test set. For a test set alle filein one" echo "directory are combined to one file with cpio and compress/decompressed" echo ${n} "Test directory [default:current]: ${c}" read var1 varr fi if [ ! -d ${var1:-.} ] then echo "$var1: no directory" else var1=`cd ${var1:-.};pwd` find ${var1} -type f -print | ( while read fn ; do [ -r ${fn} ] && echo ${fn} ; done ) | sort >/tmp/sh$$.fi ( echo "===============================================================================" echo "Directory: ${var1:-/}" echo "./compress -V" ./compress -V if [ -x ${BINDIR}/compress ] then old=${var2:-${BINDIR}/compress} set -- ./compress ${old} \ ${old} ./compress \ ./compress ./compress \ ${old} ${old} echo "${old} -V" ${old} -V $2 ----------------" if [ -x /sbin/sync ] ; then /sbin/sync else sync ; fi sleep 1 cpio -o /tmp/sh$$.tm1 ) | ( time $2 -d 2>/tmp/sh$$.tm2 ) | ( cpio -ivt >/tmp/sh$$.fo ) awk /tmp/sh$$.foo if cmp /tmp/sh$$.fi /tmp/sh$$.foo then : else echo ------ ERROR diff /tmp/sh$$.fi /tmp/sh$$.foo fi echo "---------------" echo "compress $1("`cat /tmp/sh$$.tm1`")" echo "decompress $2("`cat /tmp/sh$$.tm2`")" shift 2 done ) 2>&1 | tee /tmp/sh$$.log cat /tmp/sh$$.log >>comp.log && rm /tmp/sh$$.log fi echo "" fi echo ${n} "Press return to continue${c}" read dummy ;; i|I) if [ ".${var1}" = . ] then echo ${n} "Install compress with user ? (default current user) ? ${c}" read var1 dummy fi pwd=`pwd` ( cat - <Makefile # Makefile generated by build. # C complier CC=${CC} # Install directory for binarys BINDIR=${BINDIR} # Install directory for manual MANDIR=${MANDIR} # compiler options: # options is a collection of: # # -DAMIGA=1 Amiga support. # -DDIRENT=1 Use dirent.h # -DSYSDIR=1 Use sys/dir.h # -DLSTAT=1 Use lstat for finding symlinks. # -DUTIME_H=1 Use utime.h # -DUSERMEM= Availble memory for compress (default 800k). # -DREGISTERS= Number of registers (default 2). # -DIBUFSIZ= Input buffer size (default BUFSIZ). # -DOBUFSIZ= Output buffer size (default BUFSIZ) # -DBYTEORDER= Byte order (default: unknown). # -DNOALLIGN=1 Data word allignment (default: yes). # -DDEF_ERRNO=1 Define error (not defined in errno.h). # -DMAXSEG_64K=1 -BITS=16 Support segment processsor like 80286. # options=${options} # libary options LBOPT=${LBOPT} compress: Makefile compress42.c patchlevel.h $(CC) -o compress $(options) compress42.c $(LBOPT) install: compress [ -f \$(BINDIR)/compress ] && \\ { rm -f \$(BINDIR)/compress.old ; \\ mv \$(BINDIR)/compress \$(BINDIR)/compress.old ; } rm -f \$(BINDIR)/uncompress \$(BINDIR)/zcat cp compress \$(BINDIR)/compress strip \$(BINDIR)/compress rm -f \$(BINDIR)/uncompress ln \$(BINDIR)/compress \$(BINDIR)/uncompress rm -f \$(BINDIR)/zcat ln -f \$(BINDIR)/compress \$(BINDIR)/zcat cp zcmp zdiff zmore \$(BINDIR)/. chmod 0755 \$(BINDIR)/compress \$(BINDIR)/zcmp \$(BINDIR)/zdiff \$(BINDIR)/zmore cp compress.1 zcmp.1 zmore.1 \$(MANDIR)/. chmod 0644 \$(MANDIR)/compress.1 \$(MANDIR)/zcmp.1 \$(MANDIR)/zmore.1 cleanup: rm -f compress compress.def comp.log ! ;; mkshar) xshar -sc -opart -l64 MANIFEST Acknowleds zmore Changes compress.1 \ zcmp zmore.1 README LZW.INFO zcmp.1 zdiff build Makefile.def \ compress42.c patchlevel.h ;; mktar) rm -f comp.tar tar cvf comp.tar MANIFEST Acknowleds zmore Changes compress.1 \ zcmp zmore.1 README LZW.INFO zcmp.1 zdiff build Makefile.def \ compress42.c patchlevel.h ;; cleanup) rm -f compress compress.def comp.log exit 0 ;; q|Q) exit 0 ;; *) echo " Unknown choice ${choice}" sleep 2 ;; esac done ncompress-4.2.4.6/compress.1000066400000000000000000000150101360235512000156050ustar00rootroot00000000000000.TH COMPRESS 1 local .SH NAME compress, uncompress, zcat \- compress and expand data .SH SYNOPSIS .ll +8 .B compress [ .B \-f ] [ .B \-v ] [ .B \-c ] [ .B \-V ] [ .B \-r ] [ .B \-b .I bits ] [ .B \-\- ] [ .I "name \&..." ] .ll -8 .br .B uncompress [ .B \-f ] [ .B \-v ] [ .B \-c ] [ .B \-V ] [ .B \-\- ] [ .I "name \&..." ] .br .B zcat [ .B \-V ] [ .B \-\- ] [ .I "name \&..." ] .SH DESCRIPTION .I Compress reduces the size of the named files using adaptive Lempel\-Ziv coding. Whenever possible, each file is replaced by one with the extension .B "\&.Z," while keeping the same ownership modes, access and modification times. If no files are specified, the standard input is compressed to the standard output. .I Compress will only attempt to compress regular files. In particular, it will ignore symbolic links. If a file has multiple hard links, .I compress will refuse to compress it unless the .B \-f flag is given. .PP If .B \-f is not given and .I compress is run in the foreground, the user is prompted as to whether an existing file should be overwritten. .PP Compressed files can be restored to their original form using .I uncompress or .I zcat. .PP .I uncompress takes a list of files on its command line and replaces each file whose name ends with .B "\&.Z" and which begins with the correct magic number with an uncompressed file without the .B "\&.Z." The uncompressed file will have the mode, ownership and timestamps of the compressed file. .PP The .B \-c option makes .I compress/uncompress write to the standard output; no files are changed. .PP .I zcat is identical to .I uncompress .B \-c. .I zcat uncompresses either a list of files on the command line or its standard input and writes the uncompressed data on standard output. .I zcat will uncompress files that have the correct magic number whether they have a .B "\&.Z" suffix or not. .PP If the .B \-r flag is specified, .I compress will operate recursively. If any of the file names specified on the command line are directories, .I compress will descend into the directory and compress all the files it finds there. .PP The .B \-V flag tells each of these programs to print its version and patchlevel, along with any preprocessor flags specified during compilation, on stderr before doing any compression or uncompression. .PP .I Compress uses the modified Lempel\-Ziv algorithm popularized in "A Technique for High Performance Data Compression", Terry A. Welch, .I "IEEE Computer," vol. 17, no. 6 (June 1984), pp. 8\-19. Common substrings in the file are first replaced by 9\-bit codes 257 and up. When code 512 is reached, the algorithm switches to 10\-bit codes and continues to use more bits until the limit specified by the .B \-b flag is reached (default 16). .I Bits must be between 9 and 16. The default can be changed in the source to allow .I compress to be run on a smaller machine. .PP After the .I bits limit is attained, .I compress periodically checks the compression ratio. If it is increasing, .I compress continues to use the existing code dictionary. However, if the compression ratio decreases, .I compress discards the table of substrings and rebuilds it from scratch. This allows the algorithm to adapt to the next "block" of the file. .PP Note that the .B \-b flag is omitted for .I uncompress, since the .I bits parameter specified during compression is encoded within the output, along with a magic number to ensure that neither decompression of random data nor recompression of compressed data is attempted. .PP .ne 8 The amount of compression obtained depends on the size of the input, the number of .I bits per code, and the distribution of common substrings. Typically, text such as source code or English is reduced by 50\-60%. Compression is generally much better than that achieved by Huffman coding (as used in .IR pack ), or adaptive Huffman coding .RI ( compact ), and takes less time to compute. .PP Under the .B \-v option, a message is printed yielding the percentage of reduction for each file compressed. .PP .B \-\- may be used to halt option parsing and force all remaining arguments to be treated as paths. .SH "DIAGNOSTICS" Exit status is normally 0; if the last file is larger after (attempted) compression, the status is 2; if an error occurs, exit status is 1. .PP Usage: compress [\-dfvcVr] [\-b maxbits] [file ...] .in +8 Invalid options were specified on the command line. .in -8 Missing maxbits .in +8 Maxbits must follow .BR \-b \. .in -8 .IR file : not in compressed format .in +8 The file specified to .I uncompress has not been compressed. .in -8 .IR file : compressed with .I xx bits, can only handle .I yy bits .in +8 .I File was compressed by a program that could deal with more .I bits than the compress code on this machine. Recompress the file with smaller .IR bits \. .in -8 .IR file : already has .Z suffix \-\- no change .in +8 The file is assumed to be already compressed. Rename the file and try again. .in -8 .IR file : filename too long to tack on .Z .in +8 The file cannot be compressed because its name is longer than 12 characters. Rename and try again. This message does not occur on BSD systems. .in -8 .I file already exists; do you wish to overwrite (y or n)? .in +8 Respond "y" if you want the output file to be replaced; "n" if not. .in -8 uncompress: corrupt input .in +8 A SIGSEGV violation was detected which usually means that the input file has been corrupted. .in -8 Compression: .I "xx.xx%" .in +8 Percentage of the input saved by compression. (Relevant only for .BR \-v \.) .in -8 \-\- not a regular file or directory: ignored .in +8 When the input file is not a regular file or directory, (e.g. a symbolic link, socket, FIFO, device file), it is left unaltered. .in -8 \-\- has .I xx other links: unchanged .in +8 The input file has links; it is left unchanged. See .IR ln "(1)" for more information. Use the .B \-f flag to force compression of multiply\-linked files. .in -8 \-\- file unchanged .in +8 No savings is achieved by compression. The input remains virgin. .in -8 .SH "BUGS" Although compressed files are compatible between machines with large memory, .BR \-b \12 should be used for file transfer to architectures with a small process data space (64KB or less, as exhibited by the DEC PDP series, the Intel 80286, etc.) .PP Invoking compress with a .BR \-r flag will occasionally cause it to produce spurious error warnings of the form .PP .in 8 ".Z already has .Z suffix \- ignored" .in -8 .PP These warnings can be ignored. See the comments in compress42.c:compdir() in the source distribution for an explanation. .SH "SEE ALSO" .BR pack (1), .BR compact (1) ncompress-4.2.4.6/compress42.c000066400000000000000000001345521360235512000160520ustar00rootroot00000000000000/* (N)compress42.c - File compression ala IEEE Computer, Mar 1992. * * Authors: * Spencer W. Thomas (decvax!harpo!utah-cs!utah-gr!thomas) * Jim McKie (decvax!mcvax!jim) * Steve Davies (decvax!vax135!petsd!peora!srd) * Ken Turkowski (decvax!decwrl!turtlevax!ken) * James A. Woods (decvax!ihnp4!ames!jaw) * Joe Orost (decvax!vax135!petsd!joe) * Dave Mack (csu@alembic.acs.com) * Peter Jannesen, Network Communication Systems * (peter@ncs.nl) * * Revision 4.2.3 92/03/14 peter@ncs.nl * Optimise compress and decompress function and a lot of cleanups. * New fast hash algoritme added (if more than 800Kb available). * * Revision 4.1 91/05/26 csu@alembic.acs.com * Modified to recursively compress directories ('r' flag). As a side * effect, compress will no longer attempt to compress things that * aren't "regular" files. See Changes. * * Revision 4.0 85/07/30 12:50:00 joe * Removed ferror() calls in output routine on every output except first. * Prepared for release to the world. * * Revision 3.6 85/07/04 01:22:21 joe * Remove much wasted storage by overlaying hash table with the tables * used by decompress: tab_suffix[1<putc] and * added signal catcher [plus beef in write_error()] to delete effluvia. * * Revision 2.0 84/08/28 22:00:00 petsd!joe * Add check for foreground before prompting user. Insert maxbits into * compressed file. Force file being uncompressed to end with ".Z". * Added "-c" flag and "zcat". Prepared for release. * * Revision 1.10 84/08/24 18:28:00 turtlevax!ken * Will only compress regular files (no directories), added a magic number * header (plus an undocumented -n flag to handle old files without headers), * added -f flag to force overwriting of possibly existing destination file, * otherwise the user is prompted for a response. Will tack on a .Z to a * filename if it doesn't have one when decompressing. Will only replace * file if it was compressed. * * Revision 1.9 84/08/16 17:28:00 turtlevax!ken * Removed scanargs(), getopt(), added .Z extension and unlimited number of * filenames to compress. Flags may be clustered (-Ddvb12) or separated * (-D -d -v -b 12), or combination thereof. Modes and other status is * copied with copystat(). -O bug for 4.2 seems to have disappeared with * 1.8. * * Revision 1.8 84/08/09 23:15:00 joe * Made it compatible with vax version, installed jim's fixes/enhancements * * Revision 1.6 84/08/01 22:08:00 joe * Sped up algorithm significantly by sorting the compress chain. * * Revision 1.5 84/07/13 13:11:00 srd * Added C version of vax asm routines. Changed structure to arrays to * save much memory. Do unsigned compares where possible (faster on * Perkin-Elmer) * * Revision 1.4 84/07/05 03:11:11 thomas * Clean up the code a little and lint it. (Lint complains about all * the regs used in the asm, but I'm not going to "fix" this.) * * Revision 1.3 84/07/05 02:06:54 thomas * Minor fixes. * * Revision 1.2 84/07/05 00:27:27 thomas * Add variable bit length output. * */ #ifdef _MSC_VER # define WINDOWS #endif #ifdef __MINGW32__ # define DIRENT # define MINGW #endif #include #include #include #include #include #include #include #include #include #include #if !defined(DOS) && !defined(WINDOWS) # include #endif #ifdef DIRENT # include # define RECURSIVE 1 # undef SYSDIR #endif #ifdef SYSDIR # include # define RECURSIVE 1 #endif #ifdef UTIME_H # include #else struct utimbuf { time_t actime; time_t modtime; }; #endif #ifdef __STDC__ # define ARGS(a) a #else # define ARGS(a) () #endif #ifndef SIG_TYPE # define SIG_TYPE void (*)() #endif #if defined(AMIGA) || defined(DOS) || defined(MINGW) || defined(WINDOWS) # define chmod(pathname, mode) 0 # define chown(pathname, owner, group) 0 # define utime(pathname, times) 0 #endif #if defined(WINDOWS) # define isatty(fd) 0 # define open _open # define close _close # define read _read # define strdup _strdup # define unlink _unlink # define write _write #endif #ifndef LSTAT # define lstat stat #endif #if defined(DOS) || defined(WINDOWS) # define F_OK 0 static inline access(const char *pathname, int mode) { struct stat st; return lstat(pathname, &st) == 0; } #endif #ifdef DEF_ERRNO extern int errno; #endif #include "patchlevel.h" #undef min #define min(a,b) ((a>b) ? b : a) #ifndef IBUFSIZ # define IBUFSIZ BUFSIZ /* Defailt input buffer size */ #endif #ifndef OBUFSIZ # define OBUFSIZ BUFSIZ /* Default output buffer size */ #endif /* Defines for third byte of header */ #define MAGIC_1 (char_type)'\037'/* First byte of compressed file */ #define MAGIC_2 (char_type)'\235'/* Second byte of compressed file */ #define BIT_MASK 0x1f /* Mask for 'number of compresssion bits' */ /* Masks 0x20 and 0x40 are free. */ /* I think 0x20 should mean that there is */ /* a fourth header byte (for expansion). */ #define BLOCK_MODE 0x80 /* Block compresssion if table is full and */ /* compression rate is dropping flush tables */ /* the next two codes should not be changed lightly, as they must not */ /* lie within the contiguous general code space. */ #define FIRST 257 /* first free entry */ #define CLEAR 256 /* table clear output code */ #define INIT_BITS 9 /* initial number of bits/code */ #ifndef SACREDMEM /* * SACREDMEM is the amount of physical memory saved for others; compress * will hog the rest. */ # define SACREDMEM 0 #endif #ifndef USERMEM /* * Set USERMEM to the maximum amount of physical user memory available * in bytes. USERMEM is used to determine the maximum BITS that can be used * for compression. */ # define USERMEM 450000 /* default user memory */ #endif #ifndef BYTEORDER # define BYTEORDER 0000 #endif #ifndef NOALLIGN # define NOALLIGN 0 #endif /* * machine variants which require cc -Dmachine: pdp11, z8000, DOS */ #ifdef interdata /* Perkin-Elmer */ # define SIGNED_COMPARE_SLOW /* signed compare is slower than unsigned */ #endif #ifdef pdp11 /* PDP11: don't forget to compile with -i */ # define BITS 12 /* max bits/code for 16-bit machine */ # define NO_UCHAR /* also if "unsigned char" functions as signed char */ #endif /* pdp11 */ #ifdef z8000 /* Z8000: */ # define BITS 12 /* 16-bits processor max 12 bits */ # undef vax /* weird preprocessor */ #endif /* z8000 */ #ifdef DOS /* PC/XT/AT (8088) processor */ # define BITS 16 /* 16-bits processor max 12 bits */ # if BITS == 16 # define MAXSEG_64K # endif # undef BYTEORDER # define BYTEORDER 4321 # undef NOALLIGN # define NOALLIGN 1 #endif /* DOS */ #ifndef O_BINARY # define O_BINARY 0 /* System has no binary mode */ #endif #ifdef M_XENIX /* Stupid compiler can't handle arrays with */ # if BITS == 16 /* more than 65535 bytes - so we fake it */ # define MAXSEG_64K # else # if BITS > 13 /* Code only handles BITS = 12, 13, or 16 */ # define BITS 13 # endif # endif #endif #ifndef BITS /* General processor calculate BITS */ # if USERMEM >= (800000+SACREDMEM) # define FAST # else # if USERMEM >= (433484+SACREDMEM) # define BITS 16 # else # if USERMEM >= (229600+SACREDMEM) # define BITS 15 # else # if USERMEM >= (127536+SACREDMEM) # define BITS 14 # else # if USERMEM >= (73464+SACREDMEM) # define BITS 13 # else # define BITS 12 # endif # endif # endif # endif # endif #endif /* BITS */ #ifdef FAST # define HBITS 17 /* 50% occupancy */ # define HSIZE (1<= 1 # undef REG1 # define REG1 register #endif #if REGISTERS >= 2 # undef REG2 # define REG2 register #endif #if REGISTERS >= 3 # undef REG3 # define REG3 register #endif #if REGISTERS >= 4 # undef REG4 # define REG4 register #endif #if REGISTERS >= 5 # undef REG5 # define REG5 register #endif #if REGISTERS >= 6 # undef REG6 # define REG6 register #endif #if REGISTERS >= 7 # undef REG7 # define REG7 register #endif #if REGISTERS >= 8 # undef REG8 # define REG8 register #endif #if REGISTERS >= 9 # undef REG9 # define REG9 register #endif #if REGISTERS >= 10 # undef REG10 # define REG10 register #endif #if REGISTERS >= 11 # undef REG11 # define REG11 register #endif #if REGISTERS >= 12 # undef REG12 # define REG12 register #endif #if REGISTERS >= 13 # undef REG13 # define REG13 register #endif #if REGISTERS >= 14 # undef REG14 # define REG14 register #endif #if REGISTERS >= 15 # undef REG15 # define REG15 register #endif #if REGISTERS >= 16 # undef REG16 # define REG16 register #endif union bytes { long word; struct { #if BYTEORDER == 4321 char_type b1; char_type b2; char_type b3; char_type b4; #else #if BYTEORDER == 1234 char_type b4; char_type b3; char_type b2; char_type b1; #else # undef BYTEORDER int dummy; #endif #endif } bytes; } ; #if BYTEORDER == 4321 && NOALLIGN == 1 #define output(b,o,c,n) { \ *(long *)&((b)[(o)>>3]) |= ((long)(c))<<((o)&0x7);\ (o) += (n); \ } #else #ifdef BYTEORDER #define output(b,o,c,n) { REG1 char_type *p = &(b)[(o)>>3]; \ union bytes i; \ i.word = ((long)(c))<<((o)&0x7); \ p[0] |= i.bytes.b1; \ p[1] |= i.bytes.b2; \ p[2] |= i.bytes.b3; \ (o) += (n); \ } #else #define output(b,o,c,n) { REG1 char_type *p = &(b)[(o)>>3]; \ REG2 long i = ((long)(c))<<((o)&0x7); \ p[0] |= (char_type)(i); \ p[1] |= (char_type)(i>>8); \ p[2] |= (char_type)(i>>16); \ (o) += (n); \ } #endif #endif #if BYTEORDER == 4321 && NOALLIGN == 1 #define input(b,o,c,n,m){ \ (c) = (*(long *)(&(b)[(o)>>3])>>((o)&0x7))&(m); \ (o) += (n); \ } #else #define input(b,o,c,n,m){ REG1 char_type *p = &(b)[(o)>>3]; \ (c) = ((((long)(p[0]))|((long)(p[1])<<8)| \ ((long)(p[2])<<16))>>((o)&0x7))&(m); \ (o) += (n); \ } #endif char *progname; /* Program name */ int silent = 0; /* don't tell me about errors */ int quiet = 1; /* don't tell me about compression */ int do_decomp = 0; /* Decompress mode */ int force = 0; /* Force overwrite of files and links */ int nomagic = 0; /* Use a 3-byte magic number header, */ /* unless old file */ int block_mode = BLOCK_MODE;/* Block compress mode -C compatible with 2.0*/ int maxbits = BITS; /* user settable max # bits/code */ int zcat_flg = 0; /* Write output on stdout, suppress messages */ int recursive = 0; /* compress directories */ int exit_code = -1; /* Exitcode of compress (-1 no file compressed) */ char_type inbuf[IBUFSIZ+64]; /* Input buffer */ char_type outbuf[OBUFSIZ+2048];/* Output buffer */ struct stat infstat; /* Input file status */ char *ifname; /* Input filename */ int remove_ofname = 0; /* Remove output file on a error */ char *ofname = NULL; /* Output filename */ int fgnd_flag = 0; /* Running in background (SIGINT=SIGIGN) */ long bytes_in; /* Total number of byte from input */ long bytes_out; /* Total number of byte to output */ /* * 8086 & 80286 Has a problem with array bigger than 64K so fake the array * For processors with a limited address space and segments. */ /* * To save much memory, we overlay the table used by compress() with those * used by decompress(). The tab_prefix table is the same size and type * as the codetab. The tab_suffix table needs 2**BITS characters. We * get this from the beginning of htab. The output stack uses the rest * of htab, and contains characters. There is plenty of room for any * possible stack (stack used to be 8000 characters). */ #ifdef MAXSEG_64K count_int htab0[8192]; count_int htab1[8192]; count_int htab2[8192]; count_int htab3[8192]; count_int htab4[8192]; count_int htab5[8192]; count_int htab6[8192]; count_int htab7[8192]; count_int htab8[HSIZE-65536]; count_int * htab[9] = {htab0,htab1,htab2,htab3,htab4,htab5,htab6,htab7,htab8}; unsigned short code0tab[16384]; unsigned short code1tab[16384]; unsigned short code2tab[16384]; unsigned short code3tab[16384]; unsigned short code4tab[16384]; unsigned short * codetab[5] = {code0tab,code1tab,code2tab,code3tab,code4tab}; # define htabof(i) (htab[(i) >> 13][(i) & 0x1fff]) # define codetabof(i) (codetab[(i) >> 14][(i) & 0x3fff]) # define tab_prefixof(i) codetabof(i) # define tab_suffixof(i) ((char_type *)htab[(i)>>15])[(i) & 0x7fff] # define de_stack ((char_type *)(&htab2[8191])) void clear_htab() { memset(htab0, -1, sizeof(htab0)); memset(htab1, -1, sizeof(htab1)); memset(htab2, -1, sizeof(htab2)); memset(htab3, -1, sizeof(htab3)); memset(htab4, -1, sizeof(htab4)); memset(htab5, -1, sizeof(htab5)); memset(htab6, -1, sizeof(htab6)); memset(htab7, -1, sizeof(htab7)); memset(htab8, -1, sizeof(htab8)); } # define clear_tab_prefixof() memset(code0tab, 0, 256); #else /* Normal machine */ count_int htab[HSIZE]; unsigned short codetab[HSIZE]; # define htabof(i) htab[i] # define codetabof(i) codetab[i] # define tab_prefixof(i) codetabof(i) # define tab_suffixof(i) ((char_type *)(htab))[i] # define de_stack ((char_type *)&(htab[HSIZE-1])) # define clear_htab() memset(htab, -1, sizeof(htab)) # define clear_tab_prefixof() memset(codetab, 0, 256); #endif /* MAXSEG_64K */ #ifdef FAST int primetab[256] = /* Special secudary hash table. */ { 1013, -1061, 1109, -1181, 1231, -1291, 1361, -1429, 1481, -1531, 1583, -1627, 1699, -1759, 1831, -1889, 1973, -2017, 2083, -2137, 2213, -2273, 2339, -2383, 2441, -2531, 2593, -2663, 2707, -2753, 2819, -2887, 2957, -3023, 3089, -3181, 3251, -3313, 3361, -3449, 3511, -3557, 3617, -3677, 3739, -3821, 3881, -3931, 4013, -4079, 4139, -4219, 4271, -4349, 4423, -4493, 4561, -4639, 4691, -4783, 4831, -4931, 4973, -5023, 5101, -5179, 5261, -5333, 5413, -5471, 5521, -5591, 5659, -5737, 5807, -5857, 5923, -6029, 6089, -6151, 6221, -6287, 6343, -6397, 6491, -6571, 6659, -6709, 6791, -6857, 6917, -6983, 7043, -7129, 7213, -7297, 7369, -7477, 7529, -7577, 7643, -7703, 7789, -7873, 7933, -8017, 8093, -8171, 8237, -8297, 8387, -8461, 8543, -8627, 8689, -8741, 8819, -8867, 8963, -9029, 9109, -9181, 9241, -9323, 9397, -9439, 9511, -9613, 9677, -9743, 9811, -9871, 9941,-10061,10111,-10177, 10259,-10321,10399,-10477,10567,-10639,10711,-10789, 10867,-10949,11047,-11113,11173,-11261,11329,-11423, 11491,-11587,11681,-11777,11827,-11903,11959,-12041, 12109,-12197,12263,-12343,12413,-12487,12541,-12611, 12671,-12757,12829,-12917,12979,-13043,13127,-13187, 13291,-13367,13451,-13523,13619,-13691,13751,-13829, 13901,-13967,14057,-14153,14249,-14341,14419,-14489, 14557,-14633,14717,-14767,14831,-14897,14983,-15083, 15149,-15233,15289,-15359,15427,-15497,15583,-15649, 15733,-15791,15881,-15937,16057,-16097,16189,-16267, 16363,-16447,16529,-16619,16691,-16763,16879,-16937, 17021,-17093,17183,-17257,17341,-17401,17477,-17551, 17623,-17713,17791,-17891,17957,-18041,18097,-18169, 18233,-18307,18379,-18451,18523,-18637,18731,-18803, 18919,-19031,19121,-19211,19273,-19381,19429,-19477 } ; #endif int main ARGS((int,char **)); void Usage ARGS((int)); void comprexx ARGS((const char *)); void compdir ARGS((char *)); void compress ARGS((int,int)); void decompress ARGS((int,int)); void read_error ARGS((void)); void write_error ARGS((void)); void abort_compress ARGS((void)); void prratio ARGS((FILE *,long,long)); void about ARGS((void)); /***************************************************************** * TAG( main ) * * Algorithm from "A Technique for High Performance Data Compression", * Terry A. Welch, IEEE Computer Vol 17, No 6 (June 1984), pp 8-19. * * Usage: compress [-dfvc] [-b bits] [file ...] * Inputs: * -d: If given, decompression is done instead. * * -c: Write output on stdout, don't remove original. * * -b: Parameter limits the max number of bits/code. * * -f: Forces output file to be generated, even if one already * exists, and even if no space is saved by compressing. * If -f is not used, the user will be prompted if stdin is * a tty, otherwise, the output file will not be overwritten. * * -v: Write compression statistics * * -r: Recursive. If a filename is a directory, descend * into it and compress everything in it. * * file ...: * Files to be compressed. If none specified, stdin is used. * Outputs: * file.Z: Compressed form of file with same mode, owner, and utimes * or stdout (if stdin used as input) * * Assumptions: * When filenames are given, replaces with the compressed version * (.Z suffix) only if the file decreases in size. * * Algorithm: * Modified Lempel-Ziv method (LZW). Basically finds common * substrings and replaces them with a variable size code. This is * deterministic, and can be done on the fly. Thus, the decompression * procedure needs no input table, but tracks the way the table was built. */ int main(argc, argv) REG1 int argc; REG2 char *argv[]; { REG3 char **filelist; REG4 char **fileptr; int seen_double_dash = 0; #ifdef SIGINT if ((fgnd_flag = (signal(SIGINT, SIG_IGN)) != SIG_IGN)) signal(SIGINT, (SIG_TYPE)abort_compress); #endif #ifdef SIGTERM signal(SIGTERM, (SIG_TYPE)abort_compress); #endif #ifdef SIGHUP signal(SIGHUP, (SIG_TYPE)abort_compress); #endif #ifdef COMPATIBLE nomagic = 1; /* Original didn't have a magic number */ #endif filelist = (char **)malloc(argc*sizeof(char *)); if (filelist == NULL) { fprintf(stderr, "Cannot allocate memory for file list.\n"); exit (1); } fileptr = filelist; *filelist = NULL; if((progname = strrchr(argv[0], '/')) != 0) progname++; else progname = argv[0]; if (strcmp(progname, "uncompress") == 0) do_decomp = 1; else if (strcmp(progname, "zcat") == 0) do_decomp = zcat_flg = 1; /* Argument Processing * All flags are optional. * -V => print Version; debug verbose * -d => do_decomp * -v => unquiet * -f => force overwrite of output file * -n => no header: useful to uncompress old files * -b maxbits => maxbits. If -b is specified, then maxbits MUST be given also. * -c => cat all output to stdout * -C => generate output compatible with compress 2.0. * -r => recursively compress directories * if a string is left, must be an input filename. */ for (argc--, argv++; argc > 0; argc--, argv++) { if (strcmp(*argv, "--") == 0) { seen_double_dash = 1; continue; } if (seen_double_dash == 0 && **argv == '-') {/* A flag argument */ while (*++(*argv)) {/* Process all flags in this arg */ switch (**argv) { case 'V': about(); break; case 's': silent = 1; quiet = 1; break; case 'v': silent = 0; quiet = 0; break; case 'd': do_decomp = 1; break; case 'f': case 'F': force = 1; break; case 'n': nomagic = 1; break; case 'C': block_mode = 0; break; case 'b': if (!ARGVAL()) { fprintf(stderr, "Missing maxbits\n"); Usage(1); } maxbits = atoi(*argv); goto nextarg; case 'c': zcat_flg = 1; break; case 'q': quiet = 1; break; case 'r': case 'R': #ifdef RECURSIVE recursive = 1; #else fprintf(stderr, "%s -r not available (due to missing directory functions)\n", *argv); #endif break; case 'h': Usage(0); break; default: fprintf(stderr, "Unknown flag: '%c'; ", **argv); Usage(1); } } } else { *fileptr++ = *argv; /* Build input file list */ *fileptr = NULL; } nextarg: continue; } if (maxbits < INIT_BITS) maxbits = INIT_BITS; if (maxbits > BITS) maxbits = BITS; if (*filelist != NULL) { for (fileptr = filelist; *fileptr; fileptr++) comprexx(*fileptr); } else {/* Standard input */ ifname = ""; exit_code = 0; remove_ofname = 0; if (do_decomp == 0) { compress(0, 1); if (zcat_flg == 0 && !quiet) { fprintf(stderr, "Compression: "); prratio(stderr, bytes_in-bytes_out, bytes_in); fprintf(stderr, "\n"); } if (bytes_out >= bytes_in && !(force)) exit_code = 2; } else decompress(0, 1); } exit((exit_code== -1) ? 1:exit_code); } void Usage(int status) { fprintf(status ? stderr : stdout, "\ Usage: %s [-dfhvcVr] [-b maxbits] [--] [file ...]\n\ -d If given, decompression is done instead.\n\ -c Write output on stdout, don't remove original.\n\ -b Parameter limits the max number of bits/code.\n", progname); fprintf(status ? stderr : stdout, "\ -f Forces output file to be generated, even if one already.\n\ exists, and even if no space is saved by compressing.\n\ If -f is not used, the user will be prompted if stdin is.\n\ a tty, otherwise, the output file will not be overwritten.\n\ -h This help output.\n\ -v Write compression statistics.\n\ -V Output version and compile options.\n\ -r Recursive. If a filename is a directory, descend\n\ into it and compress everything in it.\n"); exit(status); } void comprexx(fileptr) const char *fileptr; { int fdin = -1; int fdout = -1; int has_z_suffix; char *tempname; unsigned long namesize = strlen(fileptr); /* Create a temp buffer to add/remove the .Z suffix. */ tempname = malloc(namesize + 3); if (tempname == NULL) { perror("malloc"); goto error; } strcpy(tempname,fileptr); has_z_suffix = (namesize >= 2 && strcmp(&tempname[namesize - 2], ".Z") == 0); errno = 0; if (lstat(tempname,&infstat) == -1) { if (do_decomp) { switch (errno) { case ENOENT: /* file doesn't exist */ /* ** if the given name doesn't end with .Z, try appending one ** This is obviously the wrong thing to do if it's a ** directory, but it shouldn't do any harm. */ if (!has_z_suffix) { memcpy(&tempname[namesize], ".Z", 3); namesize += 2; has_z_suffix = 1; errno = 0; if (lstat(tempname,&infstat) == -1) { perror(tempname); goto error; } if ((infstat.st_mode & S_IFMT) != S_IFREG) { fprintf(stderr, "%s: Not a regular file.\n", tempname); goto error; } } else { perror(tempname); goto error; } break; default: perror(tempname); goto error; } } else { perror(tempname); goto error; } } switch (infstat.st_mode & S_IFMT) { case S_IFDIR: /* directory */ #ifdef RECURSIVE if (recursive) compdir(tempname); else #endif if (!quiet) fprintf(stderr,"%s is a directory -- ignored\n", tempname); break; case S_IFREG: /* regular file */ if (do_decomp != 0) {/* DECOMPRESSION */ if (!zcat_flg) { if (!has_z_suffix) { if (!quiet) fprintf(stderr,"%s - no .Z suffix\n",tempname); goto error; } } free(ofname); ofname = strdup(tempname); if (ofname == NULL) { perror("strdup"); goto error; } /* Strip of .Z suffix */ if (has_z_suffix) ofname[namesize - 2] = '\0'; } else {/* COMPRESSION */ if (!zcat_flg) { if (has_z_suffix) { fprintf(stderr, "%s: already has .Z suffix -- no change\n", tempname); free(tempname); return; } if (infstat.st_nlink > 1 && (!force)) { fprintf(stderr, "%s has %jd other links: unchanged\n", tempname, (intmax_t)(infstat.st_nlink - 1)); goto error; } } ofname = malloc(namesize + 3); if (ofname == NULL) { perror("malloc"); goto error; } memcpy(ofname, tempname, namesize); strcpy(&ofname[namesize], ".Z"); } if ((fdin = open(ifname = tempname, O_RDONLY|O_BINARY)) == -1) { perror(tempname); goto error; } if (zcat_flg == 0) { if (access(ofname, F_OK) == 0) { if (!force) { inbuf[0] = 'n'; fprintf(stderr, "%s already exists.\n", ofname); if (fgnd_flag && isatty(0)) { fprintf(stderr, "Do you wish to overwrite %s (y or n)? ", ofname); fflush(stderr); if (read(0, inbuf, 1) > 0) { if (inbuf[0] != '\n') { do { if (read(0, inbuf+1, 1) <= 0) { perror("stdin"); break; } } while (inbuf[1] != '\n'); } } else perror("stdin"); } if (inbuf[0] != 'y') { fprintf(stderr, "%s not overwritten\n", ofname); goto error; } } if (unlink(ofname)) { fprintf(stderr, "Can't remove old output file\n"); perror(ofname); goto error; } } if ((fdout = open(ofname, O_WRONLY|O_CREAT|O_EXCL|O_BINARY,0600)) == -1) { perror(tempname); goto error; } if(!quiet) fprintf(stderr, "%s: ", tempname); remove_ofname = 1; } else { fdout = 1; remove_ofname = 0; } if (do_decomp == 0) compress(fdin, fdout); else decompress(fdin, fdout); close(fdin); if (fdout != 1 && close(fdout)) write_error(); if ( (bytes_in == 0) && (force == 0 ) ) { if (remove_ofname) { if(!quiet) fprintf(stderr, "No compression -- %s unchanged\n", ifname); if (unlink(ofname)) /* Remove input file */ { fprintf(stderr, "\nunlink error (ignored) "); perror(ofname); } remove_ofname = 0; exit_code = 2; } } else if (zcat_flg == 0) { struct utimbuf timep; if (!do_decomp && bytes_out >= bytes_in && (!force)) {/* No compression: remove file.Z */ if(!quiet) fprintf(stderr, "No compression -- %s unchanged\n", ifname); if (unlink(ofname)) { fprintf(stderr, "unlink error (ignored) "); perror(ofname); } remove_ofname = 0; exit_code = 2; } else {/* ***** Successful Compression ***** */ if(!quiet) { fprintf(stderr, " -- replaced with %s",ofname); if (!do_decomp) { fprintf(stderr, " Compression: "); prratio(stderr, bytes_in-bytes_out, bytes_in); } fprintf(stderr, "\n"); } timep.actime = infstat.st_atime; timep.modtime = infstat.st_mtime; if (utime(ofname, &timep)) { fprintf(stderr, "\nutime error (ignored) "); perror(ofname); } if (chmod(ofname, infstat.st_mode & 07777)) /* Copy modes */ { fprintf(stderr, "\nchmod error (ignored) "); perror(ofname); } if (chown(ofname, infstat.st_uid, infstat.st_gid)) /* Copy ownership */ { fprintf(stderr, "\nchown error (ignored) "); perror(ofname); } remove_ofname = 0; if (unlink(ifname)) /* Remove input file */ { fprintf(stderr, "\nunlink error (ignored) "); perror(ifname); } } } if (exit_code == -1) exit_code = 0; break; default: fprintf(stderr,"%s is not a directory or a regular file - ignored\n", tempname); break; } free(tempname); if (!remove_ofname) { free(ofname); ofname = NULL; } return; error: free(ofname); ofname = NULL; free(tempname); exit_code = 1; if (fdin != -1) close(fdin); if (fdout != -1) close(fdout); } #ifdef RECURSIVE void compdir(dir) REG3 char *dir; { #ifndef DIRENT REG1 struct direct *dp; #else REG1 struct dirent *dp; #endif REG2 DIR *dirp; char *nptr; char *fptr; unsigned long dir_size = strlen(dir); /* The +256 is a lazy optimization. We'll resize on demand. */ unsigned long size = dir_size + 256; nptr = malloc(size); if (nptr == NULL) { perror("malloc"); exit_code = 1; return; } memcpy(nptr, dir, dir_size); nptr[dir_size] = '/'; fptr = &nptr[dir_size + 1]; dirp = opendir(dir); if (dirp == NULL) { free(nptr); printf("%s unreadable\n", dir); /* not stderr! */ return ; } /* ** WARNING: the following algorithm will occasionally cause ** compress to produce error warnings of the form ".Z ** already has .Z suffix - ignored". This occurs when the ** .Z output file is inserted into the directory below ** readdir's current pointer. ** These warnings are harmless but annoying. The alternative ** to allowing this would be to store the entire directory ** list in memory, then compress the entries in the stored ** list. Given the depth-first recursive algorithm used here, ** this could use up a tremendous amount of memory. I don't ** think it's worth it. -- Dave Mack */ while ((dp = readdir(dirp)) != NULL) { if (dp->d_ino == 0) continue; if (strcmp(dp->d_name,".") == 0 || strcmp(dp->d_name,"..") == 0) continue; if (size < dir_size + strlen(dp->d_name) + 2) { size = dir_size + strlen(dp->d_name) + 2; nptr = realloc(nptr, size); if (nptr == NULL) { perror("realloc"); exit_code = 1; break; } fptr = &nptr[dir_size + 1]; } strcpy(fptr, dp->d_name); comprexx(nptr); } closedir(dirp); free(nptr); } #endif /* * compress fdin to fdout * * Algorithm: use open addressing double hashing (no chaining) on the * prefix code / next character combination. We do a variant of Knuth's * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime * secondary probe. Here, the modular division first probe is gives way * to a faster exclusive-or manipulation. Also do block compression with * an adaptive reset, whereby the code table is cleared when the compression * ratio decreases, but after the table fills. The variable-length output * codes are re-sized at this point, and a special CLEAR code is generated * for the decompressor. Late addition: construct the table according to * file size for noticeable speed improvement on small files. Please direct * questions about this implementation to ames!jaw. */ void compress(fdin, fdout) int fdin; int fdout; { REG2 long hp; REG3 int rpos; #if REGISTERS >= 5 REG5 long fc; #endif REG6 int outbits; REG7 int rlop; REG8 int rsize; REG9 int stcode; REG10 code_int free_ent; REG11 int boff; REG12 int n_bits; REG13 int ratio; REG14 long checkpoint; REG15 code_int extcode; union { long code; struct { char_type c; unsigned short ent; } e; } fcode; ratio = 0; checkpoint = CHECK_GAP; extcode = MAXCODE(n_bits = INIT_BITS)+1; stcode = 1; free_ent = FIRST; memset(outbuf, 0, sizeof(outbuf)); bytes_out = 0; bytes_in = 0; outbuf[0] = MAGIC_1; outbuf[1] = MAGIC_2; outbuf[2] = (char)(maxbits | block_mode); boff = outbits = (3<<3); fcode.code = 0; clear_htab(); while ((rsize = read(fdin, inbuf, IBUFSIZ)) > 0) { if (bytes_in == 0) { fcode.e.ent = inbuf[0]; rpos = 1; } else rpos = 0; rlop = 0; do { if (free_ent >= extcode && fcode.e.ent < FIRST) { if (n_bits < maxbits) { boff = outbits = (outbits-1)+((n_bits<<3)- ((outbits-boff-1+(n_bits<<3))%(n_bits<<3))); if (++n_bits < maxbits) extcode = MAXCODE(n_bits)+1; else extcode = MAXCODE(n_bits); } else { extcode = MAXCODE(16)+OBUFSIZ; stcode = 0; } } if (!stcode && bytes_in >= checkpoint && fcode.e.ent < FIRST) { REG1 long int rat; checkpoint = bytes_in + CHECK_GAP; if (bytes_in > 0x007fffff) { /* shift will overflow */ rat = (bytes_out+(outbits>>3)) >> 8; if (rat == 0) /* Don't divide by zero */ rat = 0x7fffffff; else rat = bytes_in / rat; } else rat = (bytes_in << 8) / (bytes_out+(outbits>>3)); /* 8 fractional bits */ if (rat >= ratio) ratio = (int)rat; else { ratio = 0; clear_htab(); output(outbuf,outbits,CLEAR,n_bits); boff = outbits = (outbits-1)+((n_bits<<3)- ((outbits-boff-1+(n_bits<<3))%(n_bits<<3))); extcode = MAXCODE(n_bits = INIT_BITS)+1; free_ent = FIRST; stcode = 1; } } if (outbits >= (OBUFSIZ<<3)) { if (write(fdout, outbuf, OBUFSIZ) != OBUFSIZ) write_error(); outbits -= (OBUFSIZ<<3); boff = -(((OBUFSIZ<<3)-boff)%(n_bits<<3)); bytes_out += OBUFSIZ; memcpy(outbuf, outbuf+OBUFSIZ, (outbits>>3)+1); memset(outbuf+(outbits>>3)+1, '\0', OBUFSIZ); } { REG1 int i; i = rsize-rlop; if ((code_int)i > extcode-free_ent) i = (int)(extcode-free_ent); if (i > ((sizeof(outbuf) - 32)*8 - outbits)/n_bits) i = ((sizeof(outbuf) - 32)*8 - outbits)/n_bits; if (!stcode && (long)i > checkpoint-bytes_in) i = (int)(checkpoint-bytes_in); rlop += i; bytes_in += i; } goto next; hfound: fcode.e.ent = codetabof(hp); next: if (rpos >= rlop) goto endlop; next2: fcode.e.c = inbuf[rpos++]; #ifndef FAST { REG1 code_int i; #if REGISTERS >= 5 fc = fcode.code; #else # define fc fcode.code #endif hp = (((long)(fcode.e.c)) << (BITS-8)) ^ (long)(fcode.e.ent); if ((i = htabof(hp)) == fc) goto hfound; if (i != -1) { REG4 long disp; disp = (HSIZE - hp)-1; /* secondary hash (after G. Knott) */ do { if ((hp -= disp) < 0) hp += HSIZE; if ((i = htabof(hp)) == fc) goto hfound; } while (i != -1); } } #else { REG1 long i; REG4 long p; #if REGISTERS >= 5 fc = fcode.code; #else # define fc fcode.code #endif hp = ((((long)(fcode.e.c)) << (HBITS-8)) ^ (long)(fcode.e.ent)); if ((i = htabof(hp)) == fc) goto hfound; if (i == -1) goto out; p = primetab[fcode.e.c]; lookup: hp = (hp+p)&HMASK; if ((i = htabof(hp)) == fc) goto hfound; if (i == -1) goto out; hp = (hp+p)&HMASK; if ((i = htabof(hp)) == fc) goto hfound; if (i == -1) goto out; hp = (hp+p)&HMASK; if ((i = htabof(hp)) == fc) goto hfound; if (i == -1) goto out; goto lookup; } out: ; #endif output(outbuf,outbits,fcode.e.ent,n_bits); { #if REGISTERS < 5 # undef fc REG1 long fc; fc = fcode.code; #endif fcode.e.ent = fcode.e.c; if (stcode) { codetabof(hp) = (unsigned short)free_ent++; htabof(hp) = fc; } } goto next; endlop: if (fcode.e.ent >= FIRST && rpos < rsize) goto next2; if (rpos > rlop) { bytes_in += rpos-rlop; rlop = rpos; } } while (rlop < rsize); } if (rsize < 0) read_error(); if (bytes_in > 0) output(outbuf,outbits,fcode.e.ent,n_bits); if (write(fdout, outbuf, (outbits+7)>>3) != (outbits+7)>>3) write_error(); bytes_out += (outbits+7)>>3; return; } /* * Decompress stdin to stdout. This routine adapts to the codes in the * file building the "string" table on-the-fly; requiring no table to * be stored in the compressed file. The tables used herein are shared * with those of the compress() routine. See the definitions above. */ void decompress(fdin, fdout) int fdin; int fdout; { REG2 char_type *stackp; REG3 code_int code; REG4 int finchar; REG5 code_int oldcode; REG6 code_int incode; REG7 int inbits; REG8 int posbits; REG9 int outpos; REG10 int insize; REG11 int bitmask; REG12 code_int free_ent; REG13 code_int maxcode; REG14 code_int maxmaxcode; REG15 int n_bits; REG16 int rsize; bytes_in = 0; bytes_out = 0; insize = 0; while (insize < 3 && (rsize = read(fdin, inbuf+insize, IBUFSIZ)) > 0) insize += rsize; if (insize < 3 || inbuf[0] != MAGIC_1 || inbuf[1] != MAGIC_2) { if (rsize < 0) read_error(); if (insize > 0) { fprintf(stderr, "%s: not in compressed format\n", (ifname[0] != '\0'? ifname : "stdin")); exit_code = 1; } return ; } maxbits = inbuf[2] & BIT_MASK; block_mode = inbuf[2] & BLOCK_MODE; if (maxbits > BITS) { fprintf(stderr, "%s: compressed with %d bits, can only handle %d bits\n", (*ifname != '\0' ? ifname : "stdin"), maxbits, BITS); exit_code = 4; return; } maxmaxcode = MAXCODE(maxbits); bytes_in = insize; maxcode = MAXCODE(n_bits = INIT_BITS)-1; bitmask = (1<= 0 ; --code) tab_suffixof(code) = (char_type)code; do { resetbuf: ; { REG1 int i; int e; int o; o = posbits >> 3; e = o <= insize ? insize - o : 0; for (i = 0 ; i < e ; ++i) inbuf[i] = inbuf[i+o]; insize = e; posbits = 0; } if (insize < sizeof(inbuf)-IBUFSIZ) { if ((rsize = read(fdin, inbuf+insize, IBUFSIZ)) < 0) read_error(); insize += rsize; } inbits = ((rsize > 0) ? (insize - insize%n_bits)<<3 : (insize<<3)-(n_bits-1)); while (inbits > posbits) { if (free_ent > maxcode) { posbits = ((posbits-1) + ((n_bits<<3) - (posbits-1+(n_bits<<3))%(n_bits<<3))); ++n_bits; if (n_bits == maxbits) maxcode = maxmaxcode; else maxcode = MAXCODE(n_bits)-1; bitmask = (1<= 256) { fprintf(stderr, "oldcode:-1 code:%i\n", (int)(code)); fprintf(stderr, "uncompress: corrupt input\n"); abort_compress(); } outbuf[outpos++] = (char_type)(finchar = (int)(oldcode = code)); continue; } if (code == CLEAR && block_mode) { clear_tab_prefixof(); free_ent = FIRST - 1; posbits = ((posbits-1) + ((n_bits<<3) - (posbits-1+(n_bits<<3))%(n_bits<<3))); maxcode = MAXCODE(n_bits = INIT_BITS)-1; bitmask = (1<= free_ent) /* Special case for KwKwK string. */ { if (code > free_ent) { REG1 char_type *p; posbits -= n_bits; p = &inbuf[posbits>>3]; fprintf(stderr, "insize:%d posbits:%d inbuf:%02X %02X %02X %02X %02X (%d)\n", insize, posbits, p[-1],p[0],p[1],p[2],p[3], (posbits&07)); fprintf(stderr, "uncompress: corrupt input\n"); abort_compress(); } *--stackp = (char_type)finchar; code = oldcode; } while ((cmp_code_int)code >= (cmp_code_int)256) { /* Generate output characters in reverse order */ *--stackp = tab_suffixof(code); code = tab_prefixof(code); } *--stackp = (char_type)(finchar = tab_suffixof(code)); /* And put them out in forward order */ { REG1 int i; if (outpos+(i = (de_stack-stackp)) >= OBUFSIZ) { do { if (i > OBUFSIZ-outpos) i = OBUFSIZ-outpos; if (i > 0) { memcpy(outbuf+outpos, stackp, i); outpos += i; } if (outpos >= OBUFSIZ) { if (write(fdout, outbuf, outpos) != outpos) write_error(); outpos = 0; } stackp+= i; } while ((i = (de_stack-stackp)) > 0); } else { memcpy(outbuf+outpos, stackp, i); outpos += i; } } if ((code = free_ent) < maxmaxcode) /* Generate the new entry. */ { tab_prefixof(code) = (unsigned short)oldcode; tab_suffixof(code) = (char_type)finchar; free_ent = code+1; } oldcode = incode; /* Remember previous code. */ } bytes_in += rsize; } while (rsize > 0); if (outpos > 0 && write(fdout, outbuf, outpos) != outpos) write_error(); } void read_error() { fprintf(stderr, "\nread error on"); perror((ifname[0] != '\0') ? ifname : "stdin"); abort_compress(); } void write_error() { fprintf(stderr, "\nwrite error on"); perror(ofname ? ofname : "stdout"); abort_compress(); } void abort_compress() { if (remove_ofname) unlink(ofname); exit(1); } void prratio(stream, num, den) FILE *stream; long int num; long int den; { REG1 int q; /* Doesn't need to be long */ if (den > 0) { if (num > 214748L) q = (int)(num/(den/10000L)); /* 2147483647/10000 */ else q = (int)(10000L*num/den); /* Long calculations, though */ } else q = 10000; if (q < 0) { putc('-', stream); q = -q; } fprintf(stream, "%d.%02d%%", q / 100, q % 100); } void about() { printf("Compress version: %s\n", version_id); printf("Compile options:\n "); #if BYTEORDER == 4321 && NOALLIGN == 1 printf("USE_BYTEORDER, "); #endif #ifdef FAST printf("FAST, "); #endif #ifdef vax printf("vax, "); #endif #ifdef DIRENT printf("DIRENT, "); #endif #ifdef SYSDIR printf("SYSDIR, "); #endif #ifdef NO_UCHAR printf("NO_UCHAR, "); #endif #ifdef SIGNED_COMPARE_SLOW printf("SIGNED_COMPARE_SLOW, "); #endif #ifdef MAXSEG_64K printf("MAXSEG_64K, "); #endif #ifdef DOS printf("DOS, "); #endif #ifdef DEBUG printf("DEBUG, "); #endif #ifdef LSTAT printf("LSTAT, "); #endif printf("\n REGISTERS=%d IBUFSIZ=%d, OBUFSIZ=%d, BITS=%d\n", REGISTERS, IBUFSIZ, OBUFSIZ, BITS); printf("\n\ Author version 4.2.4.x (Maintenance):\n\ Mike Frysinger (vapier@gmail.com)\n\ \n\ Author version 4.2 (Speed improvement & source cleanup):\n\ Peter Jannesen (peter@ncs.nl)\n\ \n\ Author version 4.1 (Added recursive directory compress):\n\ Dave Mack (csu@alembic.acs.com)\n\ \n\ Authors version 4.0 (World release in 1985):\n\ Spencer W. Thomas, Jim McKie, Steve Davies,\n\ Ken Turkowski, James A. Woods, Joe Orost\n"); exit(0); } ncompress-4.2.4.6/patchlevel.h000066400000000000000000000001161360235512000161710ustar00rootroot00000000000000static char ident[] = "@(#)(N)compress 4.2.4.6"; #define version_id (ident+4) ncompress-4.2.4.6/tests/000077500000000000000000000000001360235512000150355ustar00rootroot00000000000000ncompress-4.2.4.6/tests/runtests.sh000077500000000000000000000060061360235512000172650ustar00rootroot00000000000000#!/bin/sh # Ugly, but works ? set -e fullpath() { # Because portability is a pita. realpath "$0" 2>/dev/null && return 0 readlink -f "$0" 2>/dev/null && return 0 python -c 'import os, sys; print(os.path.realpath(sys.argv[1]))' "$0" } SCRIPT="$(fullpath "$@")" TESTDIR="$(dirname "${SCRIPT}")" TOP_SRCDIR="$(dirname "${TESTDIR}")" if [ -z "${COMPRESS}" ]; then COMPRESS="${TOP_SRCDIR}/compress" fi compress() { "${COMPRESS}" -v "$@"; } uncompress() { "${COMPRESS}" -v -d "$@"; } echo "using compress: ${COMPRESS}" echo "Setting up test env" TMPDIR="" trap 'rm -rf "${TMPDIR}"' EXIT TMPDIR="$(mktemp -d)" cd "${TMPDIR}" cp "${TOP_SRCDIR}/README.md" input cp input i mkdir subdir cp input i subdir/ mkdir emptydir touch emptyfile set -x : "### Check basic CLI exit status" compress -V compress -h >/dev/null out=$(compress -h) [ -n "${out}" ] ( # The shell trace output can write to stderr which we check here. set +x out=$(compress -h 2>&1 >/dev/null) [ -z "${out}" ] ) if compress -X 2>/dev/null; then false; fi : "### Check unknown flags spit to stderr only" out=$(compress -X 2>/dev/null) || : [ -z "${out}" ] out=$(compress -X 2>&1) || : [ -n "${out}" ] : "### Check -- handling" cp input ./-X compress -- -X [ -e ./-X.Z ] uncompress -- -X [ -e ./-X ] rm ./-X : "### Check compression" compress input [ ! -e input ] [ -e input.Z ] : "### Check compressing .Z file fails" if compress input.Z; then false; fi : "### Check decompression w/explicit .Z" uncompress input.Z [ -e input ] [ ! -e input.Z ] : "### Check decompression w/implicit .Z" compress input uncompress input.Z [ -e input ] [ ! -e input.Z ] : "### Check uncompressing non-.Z file fails" if uncompress input; then false; fi : "### Check empty directory compression" if compress emptydir; then false; fi if compress -r emptydir; then false; fi : "### Check directory compression" compress -r subdir : "### Check empty directory decompression" if uncompress -r emptydir; then false; fi : "### Check directory decompression" uncompress -r subdir : "### Check uncompressed directory decompression" if uncompress -r subdir; then false; fi : "### Check various error edge cases" if compress missing; then false; fi if uncompress missing; then false; fi : "### Check forced compression" if compress emptyfile; then false; fi if compress /dev/null; then false; fi compress -f emptyfile uncompress emptyfile : "### Check stdin/stdout handling" compress -c input >input.Z [ -e input ] compress input.Z uncompress -c input.Z >input.new cmp input input.new uncompress input.new cmp input input.new : "### Check existing files" if compress input /tmp/$F.$$ zcat $1 | cmp $OPTIONS - /tmp/$F.$$ STAT="$?";; *) zcat $1 | cmp $OPTIONS - $2;; esac;; *) case "$2" in *.Z) F=`basename $2 .Z` zcat $2 > /tmp/$F.$$ cmp $OPTIONS $1 /tmp/$F.$$ STAT="$?";; *) cmp $OPTIONS $1 $2 STAT="$?";; esac;; esac exit "$STAT" else echo "Usage: zcmp [cmp_options] file [file]" exit 1 fi ncompress-4.2.4.6/zcmp.1000066400000000000000000000014351360235512000147310ustar00rootroot00000000000000.TH ZCMP 1 .SH NAME zcmp, zdiff \- compare compressed files .SH SYNOPSIS .B zcmp [ cmp_options ] file1 [ file2 ] .br .B zdiff [ diff_options ] file1 [ file2 ] .SH DESCRIPTION .I Zcmp and .I zdiff are used to invoke the .I cmp or the .I diff program on compressed files. All options specified are passed directly to .I cmp or .IR diff "." If only 1 file is specified, then the files compared are .I file1 and an uncompressed .IR file1 ".Z." If two files are specified, then they are uncompressed (if ending with ".Z") and fed to .I cmp or .IR diff "." The exit status from .I cmp or .I diff is preserved. .SH "SEE ALSO" cmp(1), diff(1), zmore(1), zcat(1), compress(1), uncompress(1) .SH BUGS Messages from the .I cmp or .I diff programs refer to temporary filenames instead of those specified. ncompress-4.2.4.6/zdiff000077500000000000000000000013401360235512000147210ustar00rootroot00000000000000: #!/bin/sh OPTIONS= FILES= for ARG do case "$ARG" in -*) OPTIONS="$OPTIONS $ARG";; *) FILES="$FILES $ARG";; esac done if test -z "$FILES"; then echo "Usage: zdiff [diff_options] file [file]" exit 1 fi set $FILES if test $# -eq 1; then FILE=`expr $1 : '\(.*\)\.Z' '|' $1` zcat $FILE | diff $OPTIONS - $FILE STAT="$?" elif test $# -eq 2; then case "$1" in *.Z) case "$2" in *.Z) F=`basename $2 .Z` zcat $2 > /tmp/$F.$$ zcat $1 | diff $OPTIONS - /tmp/$F.$$ STAT="$?";; *) zcat $1 | diff $OPTIONS - $2;; esac;; *) case "$2" in *.Z) zcat $2 | diff $OPTIONS $1 - STAT="$?";; *) diff $OPTIONS $1 $2 STAT="$?";; esac;; esac exit "$STAT" else echo "Usage: zdiff [diff_options] file [file]" exit 1 fi ncompress-4.2.4.6/zmore000077500000000000000000000004771360235512000147650ustar00rootroot00000000000000: #!/bin/sh FIRST=1 for FILE do if test $FIRST -eq 0; then echo "--More--(Next file: $FILE)\c" stty cbreak -echo ANS=`dd bs=1 count=1 2>/dev/null` stty -cbreak echo echo " " if test "$ANS" = 'e'; then exit fi fi echo "------> $FILE <------" zcat $FILE | more if test -t; then FIRST=0 fi done ncompress-4.2.4.6/zmore.1000066400000000000000000000071671360235512000151240ustar00rootroot00000000000000.TH ZMORE 1 .SH NAME zmore \- file perusal filter for crt viewing of compressed text .SH SYNOPSIS .B zmore [ name ... ] .SH DESCRIPTION .I Zmore is a filter which allows examination of compressed text files one screenful at a time on a soft-copy terminal. It normally pauses after each screenful, printing --More-- at the bottom of the screen. If the user then types a carriage return, one more line is displayed. If the user hits a space, another screenful is displayed. Other possibilities are enumerated later. .PP .I Zmore looks in the file .I /etc/termcap to determine terminal characteristics, and to determine the default window size. On a terminal capable of displaying 24 lines, the default window size is 22 lines. .PP Other sequences which may be typed when .I zmore pauses, and their effects, are as follows (\fIi\fP is an optional integer argument, defaulting to 1) : .PP .IP \fIi\|\fP display .I i more lines, (or another screenful if no argument is given) .PP .IP ^D display 11 more lines (a ``scroll''). If .I i is given, then the scroll size is set to \fIi\|\fP. .PP .IP d same as ^D (control-D) .PP .IP \fIi\|\fPz same as typing a space except that \fIi\|\fP, if present, becomes the new window size. Note that the window size reverts back to the default at the end of the current file. .PP .IP \fIi\|\fPs skip \fIi\|\fP lines and print a screenful of lines .PP .IP \fIi\|\fPf skip \fIi\fP screenfuls and print a screenful of lines .PP .IP "q or Q" quit reading the current file; go on to the next (if any) .PP .IP e When the prompt --More--(Next file: .IR file ) is printed, this command causes zmore to exit. .PP .IP = Display the current line number. .PP .IP \fIi\|\fP/expr search for the \fIi\|\fP-th occurrence of the regular expression \fIexpr.\fP If the pattern is not found, .I zmore goes on to the next file (if any). Otherwise, a screenful is displayed, starting two lines before the place where the expression was found. The user's erase and kill characters may be used to edit the regular expression. Erasing back past the first column cancels the search command. .PP .IP \fIi\|\fPn search for the \fIi\|\fP-th occurrence of the last regular expression entered. .PP .IP !command invoke a shell with \fIcommand\|\fP. The character `!' in "command" are replaced with the the previous shell command. The sequence "\\!" is replaced by "!". .PP .IP ":q or :Q" quit reading the current file; go on to the next (if any) (same as q or Q). .PP .IP . (dot) repeat the previous command. .PP The commands take effect immediately, i.e., it is not necessary to type a carriage return. Up to the time when the command character itself is given, the user may hit the line kill character to cancel the numerical argument being formed. In addition, the user may hit the erase character to redisplay the --More-- message. .PP At any time when output is being sent to the terminal, the user can hit the quit key (normally control\-\\). .I Zmore will stop sending output, and will display the usual --More-- prompt. The user may then enter one of the above commands in the normal manner. Unfortunately, some output is lost when this is done, due to the fact that any characters waiting in the terminal's output queue are flushed when the quit signal occurs. .PP The terminal is set to .I noecho mode by this program so that the output can be continuous. What you type will thus not show on your terminal, except for the / and ! commands. .PP If the standard output is not a teletype, then .I zmore acts just like .I zcat, except that a header is printed before each file. .SH FILES .DT /etc/termcap Terminal data base .SH "SEE ALSO" more(1), zcat(1), compress(1), uncompress(1)