diff options
author | nate <nate@FreeBSD.org> | 1993-06-19 00:22:46 +0000 |
---|---|---|
committer | nate <nate@FreeBSD.org> | 1993-06-19 00:22:46 +0000 |
commit | 27b6ff7b29546d2f06b4766676709c0830d69643 (patch) | |
tree | 511b90cc97cd9ed9430ece39d5e20942cadef5fc /gnu/usr.bin | |
parent | 978b670e3cdaa86f5f989043fb3c7585f7d0855d (diff) | |
download | FreeBSD-src-27b6ff7b29546d2f06b4766676709c0830d69643.zip FreeBSD-src-27b6ff7b29546d2f06b4766676709c0830d69643.tar.gz |
Updated gzip from 1.1 to 1.2.2
Diffstat (limited to 'gnu/usr.bin')
39 files changed, 1460 insertions, 292 deletions
diff --git a/gnu/usr.bin/gzip/ChangeLog b/gnu/usr.bin/gzip/ChangeLog index 5238071..0506da5 100644 --- a/gnu/usr.bin/gzip/ChangeLog +++ b/gnu/usr.bin/gzip/ChangeLog @@ -1,3 +1,79 @@ +Thu Jun 17 13:47:05 1993 Jean-loup Gailly (jloup@chorus.fr) + + * version 1.2.2 + Fix a compilation error in gzip.c on Sun with cc (worked with gcc). + + +Wed Jun 16 11:20:27 1993 Jean-loup Gailly (jloup@chorus.fr) + + * version 1.2.1 + Let zmore act as more if the data is not gzipped. + By default, display output name only when name was actually truncated. + Use absolute path names in gzexe'd programs for better security. + In gzexe, use chmod 700 instead of 755 and don't gzexe tail,rm,etc... + Update vms/gzip.hlp. + Added a note about the fast options (-1 to -3) in algorithm.doc. + Improved man page for zgrep. + Minor fixes to gzip.texi. + Always set LC_ALL and LANG in configure (for tr on HPUX) + +Mon Jun 14 10:03:24 1993 Jean-loup Gailly (jloup@chorus.fr) + + * version 1.2 + Added the --list option to display the file characteristics. + Added the --no-name option: do not save or restore original filename + Save the original name by default. + Allow gunzip --suffix "" to attempt decompression on any file + regardless of its extension if an original name is present. + Add support for the SCO compress -H format. + gzip --fast now compresses faster (speed close to that of compress) + with degraded compression ratio (but still better than compress). + Default level changed to -6 (acts exactly as previous level -5) to + be a better indication of its placement in the speed/ratio range. + Use smart name truncation: 123456789012.c -> 123456789.c.gz + instead of 12345678901.gz + With --force, let zcat pass non gzip'ed data unchanged (zcat == cat) + Added the zgrep shell script. + Made sub.c useful for 16 bit sound, 24 bit images, etc.. + Supress warnings about suffix for gunzip -r, except with --verbose. + Moved the sample programs to a subdirectory sample. + On MSDOS, use .gz extension when possible (files without extension) + Added a "Special targets" section in INSTALL. + Use stty -g correctly in zmore.in. + Use cheaper test for gzipness in zforce.in. + Remove space before $ in match.S (no longer accepted by gas 2.x) + For the shell scripts, do not assume that gzip is in the path. + Fix syntax error and define lnk$library in vms/Makefile.mms + REGSIGTYPE is void on the Amiga. + Do not write empty line when decompressing stdin with --verbose. + Fix the 1.1.2 fix for VMS (bug in get_suffix) + Added warning in README about compiler bug on Solaris 2.1 for x86. + Added warning about 'rehash' in INSTALL. + Removed default value of read_buf in bits.c (supermax doesn't like). + In tailor.h, added support for Borland C and Zortech C on OS/2. + Added warning in gzexe about Ultrix buggy sh (use /bin/sh5 instead). + Added warning in zdiff about AIX buggy sh (use /bin/ksh instead). + In configure.in, do not try the asm code if DEFS contains NO_ASM + +Fri Jun 4 09:49:33 1993 Jean-loup Gailly (jloup@chorus.fr) + + * version 1.1.2 + Fix serious bug for VMS (-gz not removed when decompressing). + Allow suffix other than .gz in znew. + Do not display compression ratio when decompressing stdin. + In zmore.in, work around brain damaged stty -g (Ultrix). + Display a correct compression ratio for .Z files. + Added .z to .gz renaming script in INTALL. + Allow setting CFLAGS in configure. + Add warning in README about bug in Concentrix cc compiler. + Avoid || in Makefile.in (at least one make doesn't support this). + Disable useless --ascii option for the Amiga. + Add a pointer to the Primos executable in README. + Added description of extra field in algorithm.doc. + Do not redefine NULL in alloca.c. + Added check for unsupported compression methods. + Avoid getopt redeclaration on OSF/1. + Tue Jun 1 09:07:15 1993 Jean-loup Gailly (jloup@chorus.fr) * version 1.1.1 diff --git a/gnu/usr.bin/gzip/Makefile b/gnu/usr.bin/gzip/Makefile index 36200b8..4ac6acb 100644 --- a/gnu/usr.bin/gzip/Makefile +++ b/gnu/usr.bin/gzip/Makefile @@ -2,10 +2,10 @@ PROG= gzip SRCS= gzip.c zip.c deflate.c trees.c bits.c unzip.c inflate.c util.c \ - crypt.c lzw.c unlzw.c unpack.c getopt.c match.S + crypt.c lzw.c unlzw.c unlzh.c unpack.c getopt.c match.S MAN1= gzexe.0 gzip.0 zdiff.0 zforce.0 zmore.0 znew.0 CFLAGS+=-DASMV -DHAVE_UNISTD_H=1 -DDIRENT=1 -MLINKS= zdiff.1 zcmp.1 gzip.1 gunzip.1 gzip.1 zcat.1 gzip.1 gzcat.1 +MLINKS= gzip.1 gunzip.1 gzip.1 zcat.1 gzip.1 gzcat.1 LINKS+= ${DESTDIR}${BINDIR}/gzip ${DESTDIR}${BINDIR}/gunzip LINKS+= ${DESTDIR}${BINDIR}/gzip ${DESTDIR}${BINDIR}/gzcat LINKS+= ${DESTDIR}${BINDIR}/gzip ${DESTDIR}${BINDIR}/zcat @@ -13,7 +13,7 @@ LINKS+= ${DESTDIR}${BINDIR}/gzip ${DESTDIR}${BINDIR}/zcat afterinstall: install -c -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \ ${.CURDIR}/zforce ${.CURDIR}/gzexe ${.CURDIR}/znew \ - ${.CURDIR}/zmore ${.CURDIR}/zdiff ${.CURDIR}/zcmp \ + ${.CURDIR}/zmore ${.CURDIR}/zdiff ${.CURDIR}/zgrep \ ${DESTDIR}${BINDIR} match.o: ${.CURDIR}/match.S diff --git a/gnu/usr.bin/gzip/NEWS b/gnu/usr.bin/gzip/NEWS index 097f7b1..b47e9a5 100644 --- a/gnu/usr.bin/gzip/NEWS +++ b/gnu/usr.bin/gzip/NEWS @@ -1,6 +1,44 @@ -Current Version: 1.1.1 +Current Version: 1.2.2. See the file ChangeLog for the details of all changes. +Major changes from 1.2 to 1.2.1 +* Fix a compilation error on Sun with cc (worked with gcc). + +Major changes from 1.2 to 1.2.1 +* Let zmore act as more if the data is not gzipped. +* made gzexe more secure (don't rely on PATH). +* By default, display output name only when the name was actually truncated. + +Major changes from 1.1.2 to 1.2 +* Added the --list option to display the file characteristics. +* Added the --no-name option: do not save or restore original filename + Save the original name by default. +* Allow gunzip --suffix "" to attempt decompression on any file + regardless of its extension if an original name is present. +* Add support for the SCO compress -H format. +* gzip --fast now compresses faster (speed close to that of compress) + with degraded compression ratio (but still better than compress). + Default level changed to -6 (acts exactly as previous level -5) to + be a better indication of its placement in the speed/ratio range. +* Use smart name truncation: 123456789012.c -> 123456789.c.gz + instead of 12345678901.gz +* With --force, let zcat pass non gzip'ed data unchanged (zcat == cat) +* Added the zgrep shell script. +* Made sub.c useful for 16 bit sound, 24 bit images, etc.. +* Supress warnings about suffix for gunzip -r, except with --verbose. +* On MSDOS, use .gz extension when possible (files without extension) +* Moved the sample programs to a subdirectory sample. +* Added a "Special targets" section in INSTALL. + +Major changes from 1.1.1 to 1.1.2. +* Fix serious bug for VMS (-gz not removed when decompressing). +* Allow suffix other than .gz in znew. +* Do not display compression ratio when decompressing stdin. +* In zmore.in, work around brain damaged stty -g (Ultrix). +* Display a correct compression ratio for .Z files. +* Added .z to .gz renaming script in INTALL. +* Allow setting CFLAGS in configure. + Major changes from 1.1 to 1.1.1. * Fix serious bug in vms.c (affects Vax/VMS only). * Added --ascii option. diff --git a/gnu/usr.bin/gzip/README b/gnu/usr.bin/gzip/README index 152b7e5..3a7b283 100644 --- a/gnu/usr.bin/gzip/README +++ b/gnu/usr.bin/gzip/README @@ -1,4 +1,4 @@ -This is the file README for the gzip distribution, version 1.1.1. +This is the file README for the gzip distribution, version 1.2.2. gzip (GNU zip) is a compression utility designed to be a replacement for 'compress'. Its main advantages over compress are much better @@ -35,14 +35,17 @@ particular, please don't ask me once more for an /etc/magic entry.) WARNINGS about broken optimizers: - on the NeXT, "cc -finline-functions" is broken. gzip produces - valid .z files but they are much too large because the string + valid .gz files but they are much too large because the string matching code misses most matches. Use "cc -O" instead. - on the Mips R4000, gcc -O (version 2.3.1) generates bad code, use cc or just gcc -g instead. -- gcc 2.3.3 on the SGI Indigo IRIX 4.0.5 also produces bad code. Use - instead: make CC='cc -O2' or gcc without -O. +- gcc 2.3.3 and 2.4.3 on the SGI Indigo IRIX 4.0.5 also produce bad code. + Use instead: make CC='cc -O2' or gcc without -O. + +- On Solaris 2.1 for x86, the January 1993 "OEM" compiler release + generates bad code. This is fixed in the June 1993 "FCS" release. - on Sparc with SunOS 4.1.1 and the SC1.0 compiler, the optimizer works up to -O3 but -O4 does not work. @@ -53,6 +56,9 @@ WARNINGS about broken optimizers: - On dnix 5.3 2.2 cc version 2.37c is buggy. Version 2.38d works. +- On an Alliant running Concentrix, cc (even without optimization) generates + incorrect code. You have to use gcc. + For all machines, Use "make check" to check that gzip was compiled correctly. Please send all comments and bug reports by electronic mail to: @@ -68,6 +74,9 @@ Bug reports should ideally include: * A description of the bug behavior * The input to gzip, that triggered the bug +If you send me patches for machines I don't have access to, please test them +very carefully. gzip is used for backups, it must be extremely reliable. + The package crypt++.el is highly recommended to manipulate gzip'ed file from emacs. It recognizes automatically encrypted and compressed files when they are first visited or written. It is available via @@ -93,13 +102,16 @@ provided under the name COPYING. The latest version of gzip are always available by ftp in prep.ai.mit.edu:/pub/gnu, or in any of the prep mirror sites: -- sources in gzip-*.tar (or .shar or .tar.z) +- sources in gzip-*.tar (or .shar or .tar.gz) - Solaris 2 executables in sparc-sun-solaris2/gzip-binaries-*.tar - MSDOS lha self-extracting exe in gzip-msdos-*.exe. Once extracted, copy gzip.exe to gunzip.exe and zcat.exe, or use "gzip -d" to decompress. + gzip386.exe runs much faster but only on 386 and above; it needs go32.exe, + available in omnigate.clarkson.edu:/pub/msdos/djgpp/djdev110.zip A VMS executable is available in ftp.spc.edu:[.macro32.savesets]gzip-1-*.zip -(use [.macro32]unzip.exe to extract). +(use [.macro32]unzip.exe to extract). A PRIMOS executable is available +in ftp.lysator.liu.se:/pub/primos/run/gzip.run. Many thanks to those who provided me with bug reports and feedback. See the files THANKS and ChangeLog for more details. @@ -129,11 +141,11 @@ On Unix, gzip is mostly useful in combination with tar. GNU tar 1.11.2 has a -z option to invoke gzip automatically. "tar -z" compresses better than zip, since gzip can then take advantage of redundancy between distinct files. The drawback is that you must -scan the whole tar.z file in order to extract a single file near +scan the whole tar.gz file in order to extract a single file near the end; unzip can directly seek to the end of the zip file. There is no overhead when you extract the whole archive anyway. If a member of a .zip archive is damaged, other files can still -be recovered. If a .tar.z file is damaged, files beyond the failure +be recovered. If a .tar.gz file is damaged, files beyond the failure point cannot be recovered. (Future versions of gzip will have error recovery features.) diff --git a/gnu/usr.bin/gzip/THANKS b/gnu/usr.bin/gzip/THANKS index 5c9a47b..a5e79c1 100644 --- a/gnu/usr.bin/gzip/THANKS +++ b/gnu/usr.bin/gzip/THANKS @@ -1,9 +1,10 @@ -gzip was written by Jean-loup Gailly <jloup@chorus.fr>, with -portions written by Mark Adler (inflate.c) and Peter Jannesen -(unlzw.c). The zip deflate format was defined by Phil Katz. -Thanks to those who reported problems and suggested -various improvements. Here is a partial list of them: +gzip was written by Jean-loup Gailly <jloup@chorus.fr>, with portions +written by Mark Adler (inflate.c), Peter Jannesen (unlzw.c) and +Haruhiko Okumura (unlzh.c). The zip deflate format was defined by Phil Katz. +Thanks to those who reported problems and suggested various +improvements. Here is a partial list of them: +Jay Adams jka@ece.cmu.edu Mark Adler madler@cco.caltech.edu Edwin Allum edwin@csri.toronto.edu Joseph Arceneaux jla@gnu.ai.mit.edu @@ -29,11 +30,13 @@ Dave Brennan brennan@hal.com Alan Brown dogbowl@dogbox.acme.gen.nz Rodney Brown rdb@mel.cocam.oz.au Bruce bde@runx.oz.au +Bill Bumgarner bbum@stone.com Leila Burrell-Davis leilabd@syma.sussex.ac.uk Roger Butenuth butenuth@ira.uka.de Bud Carlson bud@isle.pegasus.com Lim Fung Chai fclim@i1sin.daq.semi.harris.com Wes Chalfant wes@kofax.com +Andrew A. Chernov ache@astral.msk.su Paul Close pdc@lunch.wpd.sgi.com Kevin Cosgrove kevinc@tekig6.pen.tek.com Stephen J Cowley s.j.cowley@amtp.cam.ac.uk @@ -42,9 +45,12 @@ James R. Crawford qralston@cislabs.pitt.edu Lawrence Crowl crowl@research.cs.orst.edu Klaus Dahlenburg kdburg@incoahe.hanse.de William E Davidsen davidsen@ariel.crd.ge.com +John M. DeDourek dedourek@aixive2.cs.unb.ca Jeff Deifik jdeifik@isi.edu Vince DeMarco vince@whatnxt.cuc.ab.ca Michael De La Rue p91152@cplab.physics.edinburgh.ac.uk +John DeRoo deroo@grout.adv.shr.dec.com +Stefano Diomedi sd@teculx.tecsiel.it Lawrence R. Dodd dodd@roebling.poly.edu Matthew Donadio donadio@mxd120.rh.psu.edu Andy Dougherty andy@crystal.phys.lafayette.edu @@ -71,12 +77,15 @@ Bruno Haible haible@ma2s2.mathematik.uni-karlsruhe.de Junio Hamano junio@shadow.twinsun.com Harald Hanche-Olsen hanche@ams.sunysb.edu Darrel R. Hankerson hankedr@mail.auburn.edu +Lars Hecking st000002@hrz1.hrz.th-darmstadt.de Ruediger Helsch ruediger@ramz.ing.tu-bs.de Mark C. Henderson mch@sqwest.wimsey.bc.ca Karl Heuer karl@kelp.boston.ma.us +Jarkko Hietaniemi jhi@dol-guldur.hut.fi Thomas Hiller hiller@fzi.de Eiji Hirai hirai@cc.swarthmore.edu Kjetil Torgrim Homme kjetilho@ifi.uio.no +Jim Howard jim_howard@mentorg.com Preston Hunt gt5708a@prism.gatech.edu Shane C Hutchins sch@nymph.msel.unh.edu Hutch hutchinson@wrair-emh1.army.mil @@ -89,24 +98,31 @@ Denny de Jonge witaddj@dutrex.tudelft.nl Arne H. Juul arnej@lise.unit.no Dana Jacobsen jacobsd@solar.cor2.epa.gov Peter Jannesen peter@ncs.nl +Tom Judson judson@scf.usc.edu +Henry G. Juengst juengst@saph2.physik.uni-bonn.de Sarantos Kapidakis sarantos%manteion@ics.forth.gr Amir J. Katz amir@matis.ingr.com Steve Kelem kelem@castor.xilinx.com Randy Kirchhof rkk@posms.aus.tx.us Ned Kittlitz kittlitz@seagoon.sw.stratus.com +Sakai Kiyotaka ksakai@mtl.t.u-tokyo.ac.jp +Philip C Kizer pckizer@gonzo.tamu.edu Pete Klammer pklammer@ouray.denver.colorado.edu Fritz Kleemann kleemann@informatik.uni-wuerzburg.dbp.de Tom Kloos tk@sequent.com Carsten Koch carsten.koch@icem.de Winfried Koenig win@in.rhein-main.de Steph Konigsdorfer s.konigsdorfer@frmy.bull.fr +Leif Kornstaedt leif@rumtifsl.ruessel.sub.org Michael D. Lawler mdlawler@bsu-cs.bsu.edu Kevin Layer layer@franz.com Howard D. Leadmon howardl@wb3ffv.ampr.org Alexander Lehmann alex@hal.rhein-main.de Simon Leinen simon@lia.di.epfl.ch +Burt Leland burt@molecular.com Hugues Leroy hugues.leroy@irisa.fr Charles Levert charles@aramis.comm.polymtl.ca +Richard Levitte levitte@e.kth.se Torbj|rn Lindh toobii@elixir.e.kth.se David R. Linn drl@vuse.vanderbilt.edu Antonio Lioy cat@athena.polito.it @@ -114,25 +130,31 @@ Jamie Lokier u90jl@ecs.oxford.ac.uk David J. MacKenzie djm@eng.umd.edu John R MacMillan john@chance.gts.org Ron Male male@eso.mc.xerox.com +Don R. Maszle maze@bea.lbl.gov Steeve McCauley steeve@pooh.geophys.mcgill.ca +Tom McConnell tmcconne@sedona.intel.com Tod McQuillin mcquill@ccit05.duq.edu Tye McQueen tye@spillman.com Bernd Melchers melchers@chemie.fu-berlin.de Jason Merrill jason@jarthur.claremont.edu Dean S. Messing deanm@medulla.labs.tek.com +M. Mesturino mesturino@cselt.stet.it Luke Mewburn zak@rmit.edu.au Jim Meyering meyering@cs.utexas.edu -Frederic Miserey miserey@laguna.ics.uci.edu +Frederic Miserey none.fred@applelink.apple.com Marcel J.E. Mol marcel@duteca.et.tudelft.nl +Soren Juul Moller sjm@dde.dk Chris Moore moore@src.bae.co.uk Helmut Muelner hmuelner@fiicmds04.tu-graz.ac.at Urban D Mueller umueller@amiga.physik.unizh.ch Timothy Murphy tim@maths.tcd.ie Greg Naber greg@squally.halcyon.com +Jay Nayegandhi jayng@bbiv02.enet.dec.com Karl L. Noell noell@informatik.fh-wiesbaden.dbp.de Arthur David Olson ado@elsie.nci.nih.gov Piet van Oostrum piet@cs.ruu.nl Rafael R. Pappalardo rafapa@obelix.cica.es +Yves Perrenoud pyves@nuga.alphanet.ch Hal Peterson hrp@pecan.cray.com Pascal Petit petit@cadillac.ibp.fr Bruno Pillard bp@chorus.fr @@ -146,7 +168,11 @@ Andreas Raab ar@nvmr.robin.de Eric S. Raymond esr@snark.thyrsus.com Klaus Reimann kr@cip.physik.uni-stuttgart.de Michael Rendell michael@mercury.cs.mun.ca +Hal Render render@massive.uccs.edu +Julian F. Reschke julian@math.uni-muenster.de +Phil Richards Phil.Richards@prg.oxford.ac.uk Roland B Roberts roberts@nsrl31.nsrl.rochester.edu +Arnold Robbins arnold@cc.gatech.edu Kevin Rodgers kevin@rolling-stone.den.mmc.com Kai Uwe Rommel rommel@informatik.tu-muenchen.de Paul Rubin phr@america.telebit.com @@ -159,13 +185,16 @@ Niimi Satoshi a01309@cfi.waseda.ac.jp Marc Schaefer sysadm@alphanet.ch Andreas Schwab schwab@lamothe.informatik.uni-dortmund.de Eric Schenk schenk@cs.toronto.edu +Sunando Sen sens@fasecon.econ.nyu.edu Rick Sladkey jrs@world.std.com Daniel L Smith dls@autodesk.com Fred Smith fredex%fcshome@merk.merk.com +Stephen Soliday soliday@ncat.edu Paul Southworth pauls@css.itd.umich.edu Rob Spencer robbie@winkle.bhpese.oz.au Richard Stallman rms@gnu.ai.mit.edu Carsten Steger carsten.steger@informatik.tu-muenchen.de +David Sundstrom sunds@anon.asic.sc.ti.com Ed Sznyter ews@babel.babel.com Hideaki Tanabe arctanx@iyeyasu.ynl.t.u-tokyo.ac.jp Andrew Telford ajt@peregrin.resmel.bhp.com.au @@ -188,6 +217,7 @@ Stephen J. Walick steve@nshore.org Gray Watson gray@antaire.com Scott Weikart scott@igc.apc.org Ivo Welch iwelch@agsm.ucla.edu +Jochen Wiedmann zrawi01@zmcipdec1.zdv.uni-tuebingen.de Gijsb. Wiesenekker wiesenecker@sara.nl Wietze van Winden wietze@swi.psy.uva.nl Larry W. Virden lwv26@cas.org diff --git a/gnu/usr.bin/gzip/TODO b/gnu/usr.bin/gzip/TODO index 1587c75..37b3c5c 100644 --- a/gnu/usr.bin/gzip/TODO +++ b/gnu/usr.bin/gzip/TODO @@ -48,11 +48,6 @@ Some of the planned features include: - Use a larger window size to deal with some large redundant files that 'compress' currently handles better than gzip. -- implement the following options: - - -e encrypt - -l list .z file contents +- Implement the -e (encrypt) option. -- support .Z files in SCO 'compress -H' format. - Send comments to Jean-loup Gailly <jloup@chorus.fr>. diff --git a/gnu/usr.bin/gzip/algorithm.doc b/gnu/usr.bin/gzip/algorithm.doc index 9c4b0c2..24f7619 100644 --- a/gnu/usr.bin/gzip/algorithm.doc +++ b/gnu/usr.bin/gzip/algorithm.doc @@ -48,6 +48,12 @@ match, thus speeding up the whole process. If compression ratio is more important than speed, zip attempts a complete second search even if the first match is already long enough. +The lazy match evaluation is no performed for the fastest compression +modes (speed options -1 to -3). For these fast modes, new strings +are inserted in the hash table only when no match was found, or +when the match is not too long. This degrades the compression ratio +but saves time since there are both fewer insertions and fewer searches. + 2. gzip file format @@ -100,6 +106,23 @@ cleared indicating binary data. For systems which have different file formats for ascii text and binary data, the decompressor can use the flag to choose the appropriate format. +The extra field, if present, must consist of one or more subfields, +each with the following format: + + subfield id : 2 bytes + subfield size : 2 bytes (little-endian format) + subfield data + +The subfield id can consist of two letters with some mnemonic value. +Please send any such id to jloup@chorus.fr. Ids with a zero second +byte are reserved for future use. The following ids are defined: + + Ap (0x41, 0x70) : Apollo file type information + +The subfield size is the size of the subfield data and does not +include the id and the size itself. The field 'extra field length' is +the total size of the extra field, including subfield ids and sizes. + It must be possible to detect the end of the compressed data with any compression format, regardless of the actual size of the compressed data. If the compressed data cannot fit in one file (in particular for diff --git a/gnu/usr.bin/gzip/bits.c b/gnu/usr.bin/gzip/bits.c index 65e78a6..610c7f0 100644 --- a/gnu/usr.bin/gzip/bits.c +++ b/gnu/usr.bin/gzip/bits.c @@ -60,7 +60,7 @@ #endif #ifndef lint -static char rcsid[] = "$Id: bits.c,v 0.8 1993/02/04 13:21:06 jloup Exp $"; +static char rcsid[] = "$Id: bits.c,v 0.9 1993/06/11 10:16:58 jloup Exp $"; #endif /* =========================================================================== @@ -84,7 +84,7 @@ local int bi_valid; * are always zero. */ -int (*read_buf) OF((char *buf, unsigned size)) = file_read; +int (*read_buf) OF((char *buf, unsigned size)); /* Current input function. Set to mem_read for in-memory compression */ #ifdef DEBUG diff --git a/gnu/usr.bin/gzip/deflate.c b/gnu/usr.bin/gzip/deflate.c index 0b3af93..eaad69a 100644 --- a/gnu/usr.bin/gzip/deflate.c +++ b/gnu/usr.bin/gzip/deflate.c @@ -68,7 +68,7 @@ #include "lzw.h" /* just for consistency checking */ #ifndef lint -static char rcsid[] = "$Id: deflate.c,v 0.13 1993/05/25 16:25:40 jloup Exp $"; +static char rcsid[] = "$Id: deflate.c,v 0.14 1993/06/12 20:11:10 jloup Exp $"; #endif /* =========================================================================== @@ -187,8 +187,17 @@ unsigned near max_chain_length; local unsigned int max_lazy_match; /* Attempt to find a better match only when the current match is strictly - * smaller than this value. + * 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. + */ + +local int compr_level; +/* compression level (1..9) */ int near good_match; /* Use a faster search when the previous match is longer than this */ @@ -216,18 +225,20 @@ typedef struct config { local config configuration_table[10] = { /* good lazy nice chain */ /* 0 */ {0, 0, 0, 0}, /* store only */ -/* 1 */ {4, 4, 16, 16}, /* maximum speed */ -/* 2 */ {6, 8, 16, 16}, -/* 3 */ {8, 16, 32, 32}, -/* 4 */ {8, 16, 64, 64}, -/* 5 */ {8, 16, 128, 128}, -/* 6 */ {8, 32, 128, 256}, -/* 7 */ {8, 64, 128, 512}, +/* 1 */ {4, 4, 8, 4}, /* maximum speed, no lazy matches */ +/* 2 */ {4, 5, 16, 8}, +/* 3 */ {4, 6, 32, 32}, + +/* 4 */ {4, 4, 16, 16}, /* lazy matches */ +/* 5 */ {8, 16, 32, 32}, +/* 6 */ {8, 16, 128, 128}, +/* 7 */ {8, 32, 128, 256}, /* 8 */ {32, 128, 258, 1024}, /* 9 */ {32, 258, 258, 4096}}; /* maximum compression */ -/* Note: the current code requires max_lazy >= MIN_MATCH and max_chain >= 4 - * but these restrictions can easily be removed at a small cost. +/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 + * For deflate_fast() (levels <= 3) good is ignored and lazy has a different + * meaning. */ #define EQUAL 0 @@ -237,6 +248,8 @@ local config configuration_table[10] = { * Prototypes for local functions. */ local void fill_window OF((void)); +local ulg deflate_fast OF((void)); + int longest_match OF((IPos cur_match)); #ifdef ASMV void match_init OF((void)); /* asm code initialization */ @@ -277,6 +290,7 @@ void lm_init (pack_level, flags) register unsigned j; if (pack_level < 1 || pack_level > 9) error("bad pack level"); + compr_level = pack_level; /* Initialize the hash table. */ #if defined(MAXSEG_64K) && HASH_BITS == 15 @@ -558,10 +572,12 @@ local void fill_window() (char*)NULL, (long)strstart - block_start, (eof)) /* =========================================================================== - * Processes a new input file and return its compressed length. + * Processes a new input file and return its compressed length. This + * function does not perform lazy evaluationof matches and inserts + * new strings in the dictionary only for unmatched strings. It is used + * only for the fast compression options. */ -#ifdef NO_LAZY -ulg deflate() +local ulg deflate_fast() { IPos hash_head; /* head of the hash chain */ int flush; /* set if current block must be flushed */ @@ -592,22 +608,38 @@ ulg deflate() flush = ct_tally(strstart-match_start, match_length - MIN_MATCH); lookahead -= match_length; - match_length--; /* string at strstart already in hash table */ - do { - strstart++; - INSERT_STRING(strstart, hash_head); - /* strstart never exceeds WSIZE-MAX_MATCH, so there are - * always MIN_MATCH bytes ahead. If lookahead < MIN_MATCH - * these bytes are garbage, but it does not matter since the - * next lookahead bytes will always be emitted as literals. - */ - } while (--match_length != 0); + + /* Insert new strings in the hash table only if the match length + * is not too large. This saves time but degrades compression. + */ + if (match_length <= max_insert_length) { + match_length--; /* string at strstart already in hash table */ + do { + strstart++; + INSERT_STRING(strstart, hash_head); + /* strstart never exceeds WSIZE-MAX_MATCH, so there are + * always MIN_MATCH bytes ahead. If lookahead < MIN_MATCH + * these bytes are garbage, but it does not matter since + * the next lookahead bytes will be emitted as literals. + */ + } while (--match_length != 0); + strstart++; + } else { + strstart += match_length; + match_length = 0; + ins_h = window[strstart]; + UPDATE_HASH(ins_h, window[strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + } } else { /* No match, output a literal byte */ + Tracevv((stderr,"%c",window[strstart])); flush = ct_tally (0, window[strstart]); lookahead--; + strstart++; } - strstart++; if (flush) FLUSH_BLOCK(0), block_start = strstart; /* Make sure that we always have enough lookahead, except @@ -620,7 +652,7 @@ ulg deflate() } return FLUSH_BLOCK(1); /* eof */ } -#else /* LAZY */ + /* =========================================================================== * Same as above, but achieves better compression. We use a lazy * evaluation for matches: a match is finally adopted only if there is @@ -637,6 +669,8 @@ ulg deflate() extern long isize; /* byte length of input file, for debug only */ #endif + if (compr_level <= 3) return deflate_fast(); /* optimized for speed */ + /* Process the input block. */ while (lookahead != 0) { /* Insert the string window[strstart .. strstart+2] in the @@ -727,4 +761,3 @@ ulg deflate() return FLUSH_BLOCK(1); /* eof */ } -#endif /* LAZY */ diff --git a/gnu/usr.bin/gzip/getopt.c b/gnu/usr.bin/gzip/getopt.c index 3bf0277..9971e7b 100644 --- a/gnu/usr.bin/gzip/getopt.c +++ b/gnu/usr.bin/gzip/getopt.c @@ -34,6 +34,11 @@ char *alloca (); #endif /* alloca.h */ #endif /* not __GNUC__ */ +/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>. */ +#ifndef _NO_PROTO +# define _NO_PROTO +#endif + #include <stdio.h> #if defined(USG) || defined(STDC_HEADERS) || defined(__GNU_LIBRARY__) diff --git a/gnu/usr.bin/gzip/getopt.h b/gnu/usr.bin/gzip/getopt.h index 764f2f4..bd3b8e4 100644 --- a/gnu/usr.bin/gzip/getopt.h +++ b/gnu/usr.bin/gzip/getopt.h @@ -99,8 +99,6 @@ enum _argtype differences in the consts, in stdlib.h. To avoid compilation errors, only prototype getopt for the GNU C library. */ extern int getopt (int argc, char *const *argv, const char *shortopts); -#else /* not __GNU_LIBRARY__ */ -extern int getopt (); #endif /* not __GNU_LIBRARY__ */ extern int getopt_long (int argc, char *const *argv, const char *shortopts, const struct option *longopts, int *longind); diff --git a/gnu/usr.bin/gzip/gzexe b/gnu/usr.bin/gzip/gzexe index ba22eb1..3382bcf 100644 --- a/gnu/usr.bin/gzip/gzexe +++ b/gnu/usr.bin/gzip/gzexe @@ -8,8 +8,9 @@ # We also try to retain the original file permissions on the compressed file. # For safety reasons, gzexe will not create setuid or setgid shell scripts. -# Warning: the first line of this file must be either : or #!/bin/sh +# WARNING: the first line of this file must be either : or #!/bin/sh # The : is required for some old versions of csh. +# On Ultrix, /bin/sh is too buggy, change the first line to: #!/bin/sh5 x=`basename $0` if test $# = 0; then @@ -37,6 +38,21 @@ if test -z "`(${CPMOD-cpmod} zfoo1$$ zfoo2$$) 2>&1`"; then fi rm -f zfoo[12]$$ +tail="" +IFS="${IFS= }"; saveifs="$IFS"; IFS="${IFS}:" +for dir in $PATH; do + test -z "$dir" && dir=. + if test -f $dir/tail; then + tail="$dir/tail" + break + fi +done +IFS="$saveifs" +if test -z "$tail"; then + echo cannot find tail + exit 1 +fi + for i do if test ! -f "$i" ; then echo ${x}: $i not a file @@ -57,10 +73,10 @@ for i do echo "${x}: $i has setgid permission, unchanged" continue fi - if test "`basename $i`" = gzip; then - echo "${x}: cannot compress gzip itself" - continue - fi + case "`basename $i`" in + gzip | tail | chmod | ln | sleep | rm) + echo "${x}: $i would depend on itself"; continue ;; + esac if test -z "$cpmod"; then cp -p "$i" $tmp 2>/dev/null || cp "$i" $tmp if test -w $tmp 2>/dev/null; then @@ -72,25 +88,25 @@ for i do fi if test $decomp -eq 0; then sed 1q $0 > $tmp - cat >> $tmp <<'EOF' + sed "s|^if tail|if $tail|" >> $tmp <<'EOF' skip=18 -if tail +$skip $0 | gzip -cd > /tmp/gztmp$$; then - chmod 755 /tmp/gztmp$$ - prog="`basename $0`" - if ln /tmp/gztmp$$ "/tmp/$prog" 2>/dev/null; then +if tail +$skip $0 | "/usr/local/bin"/gzip -cd > /tmp/gztmp$$; then + /bin/chmod 700 /tmp/gztmp$$ + prog="`echo $0 | /bin/sed 's|^.*/||`" + if /bin/ln /tmp/gztmp$$ "/tmp/$prog" 2>/dev/null; then trap '/bin/rm -f /tmp/gztmp$$ "/tmp/$prog"; exit $res' 0 - (sleep 5; /bin/rm -f /tmp/gztmp$$ "/tmp/$prog") 2>/dev/null & + (/bin/sleep 5; /bin/rm -f /tmp/gztmp$$ "/tmp/$prog") 2>/dev/null & /tmp/"$prog" ${1+"$@"}; res=$? else trap '/bin/rm -f /tmp/gztmp$$; exit $res' 0 - (sleep 5; /bin/rm -f /tmp/gztmp$$) 2>/dev/null & + (/bin/sleep 5; /bin/rm -f /tmp/gztmp$$) 2>/dev/null & /tmp/gztmp$$ ${1+"$@"}; res=$? fi else echo Cannot decompress $0; exit 1 fi; exit $res EOF - gzip -cv9 "$i" >> $tmp || { + "/usr/local/bin"/gzip -cv9 "$i" >> $tmp || { /bin/rm -f $tmp echo ${x}: compression not possible for $i, file unchanged. res=1 @@ -103,7 +119,7 @@ EOF if sed -e 1d -e 2q "$i" | grep "^skip=[0-9]*$" >/dev/null; then eval `sed -e 1d -e 2q "$i"` fi - if tail +$skip "$i" | gzip -cd > $tmp; then + if tail +$skip "$i" | "/usr/local/bin"/gzip -cd > $tmp; then : else echo ${x}: $i probably not in gzexe format, file unchanged. diff --git a/gnu/usr.bin/gzip/gzexe.1 b/gnu/usr.bin/gzip/gzexe.1 index 68e4127..8b62cd6 100644 --- a/gnu/usr.bin/gzip/gzexe.1 +++ b/gnu/usr.bin/gzip/gzexe.1 @@ -27,6 +27,13 @@ This utility is most useful on systems with very small disks. Decompress the given executables instead of compressing them. .SH "SEE ALSO" gzip(1), znew(1), zmore(1), zcmp(1), zforce(1) +.SH CAVEATS +The compressed executable is a shell script. This may create some +security holes. In particular, the compressed executable relies +on the PATH environment variable to find +.I gzip +and some other utilities +.I (tail, chmod, ln, sleep). .SH "BUGS" .I gzexe attempts to retain the original file attributes on the compressed executable, diff --git a/gnu/usr.bin/gzip/gzexe.in b/gnu/usr.bin/gzip/gzexe.in index dcbab88..a28ec3d 100644 --- a/gnu/usr.bin/gzip/gzexe.in +++ b/gnu/usr.bin/gzip/gzexe.in @@ -9,8 +9,9 @@ # We also try to retain the original file permissions on the compressed file. # For safety reasons, gzexe will not create setuid or setgid shell scripts. -# Warning: the first line of this file must be either : or #!/bin/sh +# WARNING: the first line of this file must be either : or #!/bin/sh # The : is required for some old versions of csh. +# On Ultrix, /bin/sh is too buggy, change the first line to: #!/bin/sh5 x=`basename $0` if test $# = 0; then @@ -38,6 +39,21 @@ if test -z "`(${CPMOD-cpmod} zfoo1$$ zfoo2$$) 2>&1`"; then fi rm -f zfoo[12]$$ +tail="" +IFS="${IFS= }"; saveifs="$IFS"; IFS="${IFS}:" +for dir in $PATH; do + test -z "$dir" && dir=. + if test -f $dir/tail; then + tail="$dir/tail" + break + fi +done +IFS="$saveifs" +if test -z "$tail"; then + echo cannot find tail + exit 1 +fi + for i do if test ! -f "$i" ; then echo ${x}: $i not a file @@ -58,10 +74,10 @@ for i do echo "${x}: $i has setgid permission, unchanged" continue fi - if test "`basename $i`" = gzip; then - echo "${x}: cannot compress gzip itself" - continue - fi + case "`basename $i`" in + gzip | tail | chmod | ln | sleep | rm) + echo "${x}: $i would depend on itself"; continue ;; + esac if test -z "$cpmod"; then cp -p "$i" $tmp 2>/dev/null || cp "$i" $tmp if test -w $tmp 2>/dev/null; then @@ -73,25 +89,25 @@ for i do fi if test $decomp -eq 0; then sed 1q $0 > $tmp - cat >> $tmp <<'EOF' + sed "s|^if tail|if $tail|" >> $tmp <<'EOF' skip=18 -if tail +$skip $0 | gzip -cd > /tmp/gztmp$$; then - chmod 755 /tmp/gztmp$$ - prog="`basename $0`" - if ln /tmp/gztmp$$ "/tmp/$prog" 2>/dev/null; then +if tail +$skip $0 | "BINDIR"/gzip -cd > /tmp/gztmp$$; then + /bin/chmod 700 /tmp/gztmp$$ + prog="`echo $0 | /bin/sed 's|^.*/||`" + if /bin/ln /tmp/gztmp$$ "/tmp/$prog" 2>/dev/null; then trap '/bin/rm -f /tmp/gztmp$$ "/tmp/$prog"; exit $res' 0 - (sleep 5; /bin/rm -f /tmp/gztmp$$ "/tmp/$prog") 2>/dev/null & + (/bin/sleep 5; /bin/rm -f /tmp/gztmp$$ "/tmp/$prog") 2>/dev/null & /tmp/"$prog" ${1+"$@"}; res=$? else trap '/bin/rm -f /tmp/gztmp$$; exit $res' 0 - (sleep 5; /bin/rm -f /tmp/gztmp$$) 2>/dev/null & + (/bin/sleep 5; /bin/rm -f /tmp/gztmp$$) 2>/dev/null & /tmp/gztmp$$ ${1+"$@"}; res=$? fi else echo Cannot decompress $0; exit 1 fi; exit $res EOF - gzip -cv9 "$i" >> $tmp || { + "BINDIR"/gzip -cv9 "$i" >> $tmp || { /bin/rm -f $tmp echo ${x}: compression not possible for $i, file unchanged. res=1 @@ -104,7 +120,7 @@ EOF if sed -e 1d -e 2q "$i" | grep "^skip=[0-9]*$" >/dev/null; then eval `sed -e 1d -e 2q "$i"` fi - if tail +$skip "$i" | gzip -cd > $tmp; then + if tail +$skip "$i" | "BINDIR"/gzip -cd > $tmp; then : else echo ${x}: $i probably not in gzexe format, file unchanged. diff --git a/gnu/usr.bin/gzip/gzip.1 b/gnu/usr.bin/gzip/gzip.1 index a7d331f..06ec9d9 100644 --- a/gnu/usr.bin/gzip/gzip.1 +++ b/gnu/usr.bin/gzip/gzip.1 @@ -5,7 +5,7 @@ gzip, gunzip, zcat \- compress or expand files .SH SYNOPSIS .ll +8 .B gzip -.RB [ " \-acdfhLrtvV19 " ] +.RB [ " \-acdfhlLnrtvV19 " ] .RB [ \-S\ suffix ] [ .I "name \&..." @@ -13,14 +13,14 @@ gzip, gunzip, zcat \- compress or expand files .ll -8 .br .B gunzip -.RB [ " \-acfhLrtvV " ] +.RB [ " \-acfhlLnrtvV " ] .RB [ \-S\ suffix ] [ .I "name \&..." ] .br .B zcat -.RB [ " \-hLV " ] +.RB [ " \-fhLV " ] [ .I "name \&..." ] @@ -35,21 +35,33 @@ while keeping the same ownership modes, access and modification times. .B "\-gz" for VMS, .B "z" -for MSDOS, OS/2 and Atari.) +for MSDOS, OS/2 FAT and Atari.) If no files are specified, the standard input is compressed to the -standard output. If the new file name is too long, -.I gzip -truncates it and keeps the original file name in the compressed file. +standard output. .I Gzip will only attempt to compress regular files. In particular, it will ignore symbolic links. .PP +If the new file name is too long for its file system, +.I gzip +truncates it and keeps the original file name in the compressed file. +.I Gzip +attempts to truncate only the parts of the file name longer than 3 characters. +(A part is delimited by dots.) If the name consists of small parts only, +the longest parts are truncated. For example, if file names are limited +to 14 characters, gzip.msdos.exe is compressed to gzi.msd.exe.gz. +Names are not truncated on systems which do not have a limit on file name +length. +.PP Compressed files can be restored to their original form using .I gzip -d or .I gunzip or .I zcat. +If the original name saved in the compressed file is not suitable for its +file system, a new name is constructed from the original one to make it +legal. .PP .I gunzip takes a list of files on its command line and replaces each @@ -66,10 +78,17 @@ as shorthands for and .B "\&.tar.Z" respectively. +When compressing, +.I gzip +uses the +.B "\&.tgz" +extension if necessary instead of truncating a file with a +.B "\&.tar" +extension. .PP .I gunzip can currently decompress files created by -.I gzip, zip, compress +.I gzip, zip, compress, compress -H or .I pack. The detection of the input format is automatic. When using @@ -77,7 +96,7 @@ the first two formats, .I gunzip checks a 32 bit CRC. For .I pack, gunzip -checks the uncompressed length. The +checks the uncompressed length. The standard .I compress format was not designed to allow consistency checks. However .I gunzip @@ -88,6 +107,8 @@ correct simply because the standard does not complain. This generally means that the standard .I uncompress does not check its input, and happily generates garbage output. +The SCO compress -H format (lzh compression method) does not include a CRC +but also allows some consistency checks. .PP Files created by .I zip @@ -150,7 +171,7 @@ Ascii text mode: convert end-of-lines using local conventions. This option is supported only on some non-Unix systems. For MSDOS, CR LF is converted to LF when compressing, and LF is converted to CR LF when decompressing. .TP -.B \-c --stdout +.B \-c --stdout --to-stdout Write output on standard output; keep original files unchanged. If there are several input files, the output consists of a sequence of independently compressed members. To obtain better compression, @@ -162,7 +183,15 @@ Decompress. .B \-f --force Force compression or decompression even if the file has multiple links or the corresponding file already exists, or if the compressed data -is read from or written to a terminal. If +is read from or written to a terminal. If the input data is not in +a format recognized by +.I gzip, +and if the option --stdout is also given, copy the input data without change +to the standard ouput: let +.I zcat +behave as +.I cat. +If .B \-f is not given, and when not running in the background, @@ -172,10 +201,47 @@ prompts to verify whether an existing file should be overwritten. .B \-h --help Display a help screen and quit. .TP +.B \-l --list +For each compressed file, list the following fields: + + compressed size: size of the compressed file + uncompressed size: size of the uncompressed file + ratio: compression ratio (0.0% if unknown) + uncompressed_name: name of the uncompressed file + +The uncompressed size is given as -1 for files not in gzip format, +such as compressed .Z files. To get the uncompressed size for such a file, +you can use: + + zcat file.Z | wc -c + +In combination with the --verbose option, the following fields are also +displayed: + + method: compression method + crc: the 32-bit CRC of the uncompressed data + date & time: time stamp for the uncompressed file + +The compression methods currently supported are deflate, compress, lzh +(SCO compress -H) and pack. The crc is given as ffffffff for a file +not in gzip format. + +With --verbose, the size totals and compression ratio for all files +is also displayed, unless some sizes are unknown. With --quiet, +the title and totals lines are not displayed. +.TP .B \-L --license Display the .I gzip -license. +license and quit. +.TP +.B \-n --no-name +When compressing, do not save the original file name by default. (The +original name is always saved if the name had to be truncated.) When +decompressing, do not restore the original file name if present: remove +only the +.I gzip +suffix from the compressed file name. .TP .B \-q --quiet Suppress all warnings. @@ -189,10 +255,15 @@ will descend into the directory and compress all the files it finds there .I gunzip ). .TP -.B \-S .z --suffix .z -Use suffix .z instead of .gz. Any suffix can be given, but suffixes +.B \-S .suf --suffix .suf +Use suffix .suf instead of .gz. Any suffix can be given, but suffixes other than .z and .gz should be avoided to avoid confusion when files -are transferred to other systems. Previous versions of gzip used +are transferred to other. A null suffix forces gunzip to try +decompression on all given files regardless of suffix, as in: + + gunzip -S "" * (*.* for MSDOS) + +Previous versions of gzip used the .z suffix. This was changed to avoid a conflict with .IR pack "(1)". .TP @@ -200,7 +271,8 @@ the .z suffix. This was changed to avoid a conflict with Test. Check the compressed file integrity. .TP .B \-v --verbose -Verbose. Display the name and percentage reduction for each file compressed. +Verbose. Display the name and percentage reduction for each file compressed +or decompressed. .TP .B \-V --version Version. Display the version number and compilation options then quit. @@ -219,7 +291,8 @@ or .B \-\-best indicates the slowest compression method (optimal compression). The default compression level is -.BR \-5. +.BR \-6 +(that is, biased towards high compression at expense of speed). .SH "ADVANCED USAGE" Multiple compressed files can be concatenated. In this case, .I gunzip @@ -268,7 +341,7 @@ pack(1), compact(1) Exit status is normally 0; if an error occurs, exit status is 1. If a warning occurs, exit status is 2. .PP -Usage: gzip [-cdfhLrtvV19] [-S suffix] [file ...] +Usage: gzip [-cdfhlLnrtvV19] [-S suffix] [file ...] .in +8 Invalid options were specified on the command line. .in -8 @@ -322,7 +395,9 @@ been corrupted. .in +8 Percentage of the input saved by compression. (Relevant only for -.BR \-v \.) +.BR \-v +and +.BR \-l \.) .in -8 -- not a regular file or directory: ignored .in +8 @@ -358,3 +433,7 @@ environment variable as in: In the above example, gzip is invoked implicitly by the -z option of GNU tar. Make sure that the same block size (-b option of tar) is used for reading and writing compressed data on tapes. +.SH BUGS +The --list option reports incorrect sizes if they exceed 2 gigabytes. +The --list option reports sizes as -1 and crc as ffffffff if the +compressed file is on a non seekable media. diff --git a/gnu/usr.bin/gzip/gzip.c b/gnu/usr.bin/gzip/gzip.c index 2bc1c5f..37100cd 100644 --- a/gnu/usr.bin/gzip/gzip.c +++ b/gnu/usr.bin/gzip/gzip.c @@ -31,19 +31,23 @@ static char *license_msg[] = { * Outputs: * file.gz: compressed file with same mode, owner, and utimes * or stdout with -c option or if stdin used as input. - * If the OS does not support file names with multiple dots (MSDOS, VMS) or - * if the output file name had to be truncated, the original name is kept + * If the output file name had to be truncated, the original name is kept * in the compressed file. * On MSDOS, file.tmp -> file.tmz. On VMS, file.tmp -> file.tmp-gz. * + * Using gz on MSDOS would create too many file name conflicts. For + * example, foo.txt -> foo.tgz (.tgz must be reserved as shorthand for + * tar.gz). Similarly, foo.dir and foo.doc would both be mapped to foo.dgz. + * I also considered 12345678.txt -> 12345txt.gz but this truncates the name + * too heavily. There is no ideal solution given the MSDOS 8+3 limitation. + * * For the meaning of all compilation flags, see comments in Makefile.in. */ #ifndef lint -static char rcsid[] = "$Id: gzip.c,v 0.19 1993/06/01 14:21:46 jloup Exp $"; +static char rcsid[] = "$Id: gzip.c,v 0.22 1993/06/16 16:53:43 jloup Exp $"; #endif -#include <stdio.h> #include <ctype.h> #include <sys/types.h> #include <signal.h> @@ -58,6 +62,12 @@ static char rcsid[] = "$Id: gzip.c,v 0.19 1993/06/01 14:21:46 jloup Exp $"; /* configuration */ +#ifdef NO_TIME_H +# include <sys/time.h> +#else +# include <time.h> +#endif + #ifndef NO_FCNTL_H # include <fcntl.h> #endif @@ -157,8 +167,21 @@ typedef RETSIGTYPE (*sig_type) OF((int)); # define MAX_PATH_LEN 1024 /* max pathname length */ #endif -#define MAX_HEADER_LEN 16 -/* max length of a compressed file header, fixed part only */ +#ifndef SEEK_END +# define SEEK_END 2 +#endif + +#ifdef NO_OFF_T + typedef long off_t; + off_t lseek OF((int fd, off_t offset, int whence)); +#endif + +/* Separator for file name parts (see shorten_name()) */ +#ifdef NO_MULTIPLE_DOTS +# define PART_SEP "-" +#else +# define PART_SEP "." +#endif /* global buffers */ @@ -179,7 +202,9 @@ int ascii = 0; /* convert end-of-lines to local OS conventions */ int to_stdout = 0; /* output to stdout (-c) */ int decompress = 0; /* decompress (-d) */ int force = 0; /* don't ask questions, compress links (-f) */ +int no_name = 0; /* don't save or restore the original file name */ int recursive = 0; /* recurse through directories (-r) */ +int list = 0; /* list the file contents (-l) */ int verbose = 0; /* be verbose (-v) */ int quiet = 0; /* be very quiet (-q) */ int do_lzw = 0; /* generate output compatible with old compress (-Z) */ @@ -188,12 +213,12 @@ int foreground; /* set if program run in foreground */ char *progname; /* program name */ int maxbits = BITS; /* max bits per code for LZW */ int method = DEFLATED;/* compression method */ -int level = 5; /* compression level */ +int level = 6; /* compression level */ int exit_code = OK; /* program exit code */ int save_orig_name; /* set if original name must be saved */ int last_member; /* set for .zip and .Z files */ int part_nb; /* number of parts in .gz file */ -ulg time_stamp; /* original time stamp (modification time) */ +long time_stamp; /* original time stamp (modification time) */ long ifile_size; /* input file size, -1 for devices (debug only) */ char *env; /* contents of GZIP env variable */ char **args = NULL; /* argv pointer if GZIP env variable defined */ @@ -202,6 +227,8 @@ int z_len; /* strlen(z_suffix) */ long bytes_in; /* number of input bytes */ long bytes_out; /* number of output bytes */ +long total_in = 0; /* input bytes for all files */ +long total_out = 0; /* output bytes for all files */ char ifname[MAX_PATH_LEN]; /* input file name */ char ofname[MAX_PATH_LEN]; /* output file name */ int remove_ofname = 0; /* remove output file on error */ @@ -224,8 +251,9 @@ struct option longopts[] = {"force", 0, 0, 'f'}, /* force overwrite of output file */ {"help", 0, 0, 'h'}, /* give help */ /* {"pkzip", 0, 0, 'k'}, force output in pkzip format */ - /* {"list", 0, 0, 'l'}, list .gz file contents */ + {"list", 0, 0, 'l'}, /* list .gz file contents */ {"license", 0, 0, 'L'}, /* display software license */ + {"no-name", 0, 0, 'n'}, /* don't save or restore the original name */ {"quiet", 0, 0, 'q'}, /* quiet mode */ {"silent", 0, 0, 'q'}, /* quiet mode */ {"recurse", 0, 0, 'r'}, /* recurse through directories */ @@ -255,7 +283,9 @@ local int get_istat OF((char *iname, struct stat *sbuf)); local int make_ofname OF((void)); local int same_file OF((struct stat *stat1, struct stat *stat2)); local int name_too_long OF((char *name, struct stat *statb)); +local void shorten_name OF((char *name)); local int get_method OF((int in)); +local void do_list OF((int ifd, int method)); local int check_ofname OF((void)); local void reset_times OF((char *name, struct stat *statb)); local void copy_stat OF((struct stat *ifstat)); @@ -270,7 +300,7 @@ int (*work) OF((int infile, int outfile)) = zip; /* function to call */ /* ======================================================================== */ local void usage() { - fprintf(stderr, "usage: %s [-%scdfhL%stvV19] [-S suffix] [file ...]\n", + fprintf(stderr, "usage: %s [-%scdfhlLn%stvV19] [-S suffix] [file ...]\n", progname, #if O_BINARY "a", @@ -298,16 +328,17 @@ local void help() " -f --force force overwrite of output file and compress links", " -h --help give this help", /* -k --pkzip force output in pkzip format */ -/* -l --list list .gz file contents */ + " -l --list list .gz file contents", " -L --license display software license", + " -n --no-name do not save or restore the original name", " -q --quiet suppress all warnings", #ifndef NO_DIR " -r --recurse recurse through directories", #endif #ifdef MAX_EXT_CHARS - " -S --suffix .gz use suffix .gz instead of .z", + " -S .suf --suffix .suf use suffix .suf instead of .z", #else - " -S --suffix .z use suffix .z instead of .gz", + " -S .suf --suffix .suf use suffix .suf instead of .gz", #endif " -t --test test compressed file integrity", " -v --verbose verbose mode", @@ -435,7 +466,7 @@ int main (argc, argv) strncpy(z_suffix, Z_SUFFIX, sizeof(z_suffix)-1); z_len = strlen(z_suffix); - while ((optc = getopt_long (argc, argv, "ab:cdfhLqrS:tvVZ123456789", + while ((optc = getopt_long (argc, argv, "ab:cdfhlLnqrS:tvVZ123456789", longopts, (int *)0)) != EOF) { switch (optc) { case 'a': @@ -451,8 +482,12 @@ int main (argc, argv) force++; break; case 'h': case 'H': case '?': help(); do_exit(OK); break; + case 'l': + list = decompress = to_stdout = 1; break; case 'L': license(); do_exit(OK); break; + case 'n': + no_name = 1; break; case 'q': quiet = 1; verbose = 0; break; case 'r': @@ -468,11 +503,6 @@ int main (argc, argv) if (*optarg == '.') optarg++; #endif z_len = strlen(optarg); - if (z_len == 0 || z_len > MAX_SUFFIX) { - fprintf(stderr, "%s: incorrect suffix '%s'\n", - progname, optarg); - do_exit(ERROR); - } strcpy(z_suffix, optarg); break; case 't': @@ -511,6 +541,11 @@ int main (argc, argv) progname); } #endif + if ((z_len == 0 && !decompress) || z_len > MAX_SUFFIX) { + fprintf(stderr, "%s: incorrect suffix '%s'\n", + progname, optarg); + do_exit(ERROR); + } if (do_lzw && !decompress) work = lzw; /* Allocate all global buffers (for DYN_ALLOC option) */ @@ -527,7 +562,7 @@ int main (argc, argv) /* And get to work */ if (file_count != 0) { - if (to_stdout && !test && (!decompress || !ascii)) { + if (to_stdout && !test && !list && (!decompress || !ascii)) { SET_BINARY_MODE(fileno(stdout)); } while (optind < argc) { @@ -536,6 +571,9 @@ int main (argc, argv) } else { /* Standard input */ treat_stdin(); } + if (list && !quiet) { + do_list(-1, -1); /* print totals */ + } do_exit(exit_code); return exit_code; /* just to avoid lint warning */ } @@ -569,7 +607,7 @@ local void treat_stdin() if (decompress || !ascii) { SET_BINARY_MODE(fileno(stdin)); } - if (!test && (!decompress || !ascii)) { + if (!test && !list && (!decompress || !ascii)) { SET_BINARY_MODE(fileno(stdout)); } strcpy(ifname, "stdin"); @@ -604,6 +642,10 @@ local void treat_stdin() do_exit(exit_code); /* error message already emitted */ } } + if (list) { + do_list(ifd, method); + return; + } /* Actually do the compression/decompression. Loop over zipped members. */ @@ -620,14 +662,17 @@ local void treat_stdin() if (verbose) { if (test) { - fprintf(stderr, " OK"); + fprintf(stderr, " OK\n"); - } else if (decompress) { - display_ratio(bytes_out-(bytes_in-header_bytes), bytes_out); + } else if (!decompress) { + display_ratio(bytes_in-(bytes_out-header_bytes), bytes_in, stderr); + fprintf(stderr, "\n"); +#ifdef DISPLAY_STDIN_RATIO } else { - display_ratio(bytes_in-(bytes_out-header_bytes), bytes_in); + display_ratio(bytes_out-(bytes_in-header_bytes), bytes_out,stderr); + fprintf(stderr, "\n"); +#endif } - fprintf(stderr, "\n"); } } @@ -671,7 +716,7 @@ local void treat_file(iname) time_stamp = istat.st_mtime; /* Generate output file name */ - if (to_stdout) { + if (to_stdout && !list) { strcpy(ofname, "stdout"); } else if (make_ofname() != OK) { @@ -700,6 +745,11 @@ local void treat_file(iname) return; /* error message already emitted */ } } + if (list) { + do_list(ifd, method); + close(ifd); + return; + } /* If compressing to a file, check if ofname is not ambiguous * because the operating system truncates names. Otherwise, generate @@ -716,6 +766,9 @@ local void treat_file(iname) progname, ifname, ofname); } } + /* Keep the name even if not truncated except with --no-name: */ + if (!save_orig_name) save_orig_name = !no_name; + if (verbose) { fprintf(stderr, "%s:\t%s", ifname, (int)strlen(ifname) >= 15 ? "" : ((int)strlen(ifname) >= 7 ? "\t" : "\t\t")); @@ -749,9 +802,9 @@ local void treat_file(iname) if (test) { fprintf(stderr, " OK"); } else if (decompress) { - display_ratio(bytes_out-(bytes_in-header_bytes), bytes_out); + display_ratio(bytes_out-(bytes_in-header_bytes), bytes_out,stderr); } else { - display_ratio(bytes_in-(bytes_out-header_bytes), bytes_in); + display_ratio(bytes_in-(bytes_out-header_bytes), bytes_in, stderr); } if (!test && !to_stdout) { fprintf(stderr, " -- replaced with %s", ofname); @@ -768,6 +821,7 @@ local void treat_file(iname) * Create the output file. Return OK or ERROR. * Try several times if necessary to avoid truncating the z_suffix. For * example, do not create a compressed file of name "1234567890123." + * Sets save_orig_name to true if the file name has been truncated. * IN assertions: the input file has already been open (ifd is set) and * ofname has already been updated if there was an original name. * OUT assertions: ifd and ofd are closed in case of error. @@ -775,15 +829,13 @@ local void treat_file(iname) local int create_outfile() { struct stat ostat; /* stat for ofname */ - int len; int flags = O_WRONLY | O_CREAT | O_EXCL | O_BINARY; if (ascii && decompress) { flags &= ~O_BINARY; /* force ascii text mode */ } for (;;) { - len = strlen(ofname); - if (len == 0 || ofname[len] == PATH_SEP) break; + /* Make sure that ofname is not an existing file */ if (check_ofname() != OK) { close(ifd); return ERROR; @@ -799,7 +851,11 @@ local int create_outfile() } /* Check for name truncation on new file (1234567890123.gz) */ +#ifdef NO_FSTAT + if (stat(ofname, &ostat) != 0) { +#else if (fstat(ofd, &ostat) != 0) { +#endif fprintf(stderr, "%s: ", progname); perror(ofname); close(ifd); close(ofd); @@ -814,25 +870,16 @@ local int create_outfile() WARN((stderr, "%s: %s: warning, name truncated\n", progname, ofname)); return OK; - } else { + } + close(ofd); + unlink(ofname); #ifdef NO_MULTIPLE_DOTS - /* Should never happen, see check_ofname() */ - fprintf(stderr, "%s: %s: name too long\n", progname, ofname); - do_exit(ERROR); -#else - close(ofd); - unlink(ofname); - save_orig_name = 1; - strcpy(ofname+strlen(ofname)-z_len-1, z_suffix); - /* 123456789012.gz -> 12345678901.gz */ + /* Should never happen, see check_ofname() */ + fprintf(stderr, "%s: %s: name too long\n", progname, ofname); + do_exit(ERROR); #endif - } /* decompress ? */ - } /* while non null name */ - - close(ifd); - fprintf(stderr, "%s: %s: name too long\n", progname, ofname); - exit_code = ERROR; - return ERROR; + shorten_name(ofname); + } } /* ======================================================================== @@ -861,6 +908,8 @@ local int do_stat(name, sbuf) * also accepted suffixes. For Unix, we do not want to accept any * .??z suffix as indicating a compressed file; some people use .xyz * to denote volume data. + * On systems allowing multiple versions of the same file (such as VMS), + * this function removes any version suffix in the given name. */ local char *get_suffix(name) char *name; @@ -877,19 +926,19 @@ local char *get_suffix(name) if (strequ(z_suffix, "z")) suf++; /* check long suffixes first */ +#ifdef SUFFIX_SEP + /* strip a version number from the file name */ + { + char *v = strrchr(name, SUFFIX_SEP); + if (v != NULL) *v = '\0'; + } +#endif nlen = strlen(name); if (nlen <= MAX_SUFFIX+2) { strcpy(suffix, name); } else { strcpy(suffix, name+nlen-MAX_SUFFIX-2); } -#ifdef SUFFIX_SEP - /* strip a version number from the file name */ - { - char *v = strrchr(suffix, SUFFIX_SEP); - if (v != NULL) *v = '\0', nlen = v - name; - } -#endif strlwr(suffix); slen = strlen(suffix); do { @@ -933,7 +982,8 @@ local int get_istat(iname, sbuf) exit_code = ERROR; return ERROR; } - /* file.ext doesn't exist, try adding a suffix. + /* file.ext doesn't exist, try adding a suffix (after removing any + * version number for VMS). */ s = get_suffix(ifname); if (s != NULL) { @@ -941,10 +991,6 @@ local int get_istat(iname, sbuf) exit_code = ERROR; return ERROR; } -#ifdef SUFFIX_SEP - /* strip a version number from the input file name */ - if ((s = strrchr(ifname, SUFFIX_SEP)) != NULL) *s = '\0'; -#endif #ifdef NO_MULTIPLE_DOTS dot = strrchr(ifname, '.'); if (dot == NULL) { @@ -987,20 +1033,24 @@ local int get_istat(iname, sbuf) /* ======================================================================== * Generate ofname given ifname. Return OK, or WARNING if file must be skipped. - * Initializes save_orig_name. - * IN assertion: this function is not called if to_stdout is true. + * Sets save_orig_name to true if the file name has been truncated. */ local int make_ofname() { char *suff; /* ofname z suffix */ strcpy(ofname, ifname); + /* strip a version number if any and get the gzip suffix if present: */ suff = get_suffix(ofname); if (decompress) { if (suff == NULL) { - WARN((stderr,"%s: %s: unknown suffix -- ignored\n", - progname, ifname)); + if (list) return OK; + /* Avoid annoying messages with -r */ + if (verbose || (!recursive && !quiet)) { + WARN((stderr,"%s: %s: unknown suffix -- ignored\n", + progname, ifname)); + } return WARNING; } /* Make a special case for .tgz and .taz: */ @@ -1008,7 +1058,7 @@ local int make_ofname() if (strequ(suff, ".tgz") || strequ(suff, ".taz")) { strcpy(suff, ".tar"); } else { - *suff = '\0'; /* strip z suffix and optional version number */ + *suff = '\0'; /* strip the z suffix */ } /* ofname might be changed later if infile contains an original name */ @@ -1023,16 +1073,15 @@ local int make_ofname() } else { save_orig_name = 0; -#ifdef SUFFIX_SEP - /* strip a version number from the file name */ - if ((suff = strrchr(ofname, SUFFIX_SEP)) != NULL) *suff = '\0'; -#endif - #ifdef NO_MULTIPLE_DOTS suff = strrchr(ofname, '.'); if (suff == NULL) { strcat(ofname, "."); # ifdef MAX_EXT_CHARS + if (strequ(z_suffix, "z")) { + strcat(ofname, "gz"); /* enough room */ + return OK; + } /* On the Atari and some versions of MSDOS, name_too_long() * does not work correctly because of a bug in stat(). So we * must truncate here. @@ -1066,9 +1115,17 @@ local int get_method(in) uch flags; char magic[2]; /* magic header */ - magic[0] = (char)get_byte(); - magic[1] = (char)get_byte(); - + /* If --force and --stdout, zcat == cat, so do not complain about + * premature end of file: use try_byte instead of get_byte. + */ + if (force && to_stdout) { + magic[0] = (char)try_byte(); + magic[1] = (char)try_byte(); + /* If try_byte returned EOF, magic[1] == 0xff */ + } else { + magic[0] = (char)get_byte(); + magic[1] = (char)get_byte(); + } time_stamp = istat.st_mtime; /* may be modified later for some methods */ method = -1; /* unknown yet */ part_nb++; /* number of parts in gzip file */ @@ -1079,8 +1136,15 @@ local int get_method(in) if (memcmp(magic, GZIP_MAGIC, 2) == 0 || memcmp(magic, OLD_GZIP_MAGIC, 2) == 0) { - work = unzip; method = (int)get_byte(); + if (method != DEFLATED) { + fprintf(stderr, + "%s: %s: unknown method %d -- get newer version of gzip\n", + progname, ifname, method); + exit_code = ERROR; + return -1; + } + work = unzip; flags = (uch)get_byte(); if ((flags & ENCRYPTED) != 0) { @@ -1132,13 +1196,14 @@ local int get_method(in) /* Get original file name if it was truncated */ if ((flags & ORIG_NAME) != 0) { - if (to_stdout || part_nb > 1) { + if (no_name || (to_stdout && !list) || part_nb > 1) { /* Discard the old name */ char c; /* dummy used for NeXTstep 3.0 cc optimizer bug */ while ((c=get_byte()) != 0) c++; } else { /* Copy the base name. Keep a directory prefix intact. */ - char *p = basename(ofname); + char *p = basename(ofname); + char *base = p; for (;;) { *p = (char)get_char(); if (*p++ == '\0') break; @@ -1146,8 +1211,13 @@ local int get_method(in) error("corrupted input -- file name too large"); } } - } /* to_stdout */ - } /* orig_name */ + /* If necessary, adapt the name to local OS conventions: */ + if (!list) { + MAKE_LEGAL_NAME(base); + base++; /* avoid warning about unused variable */ + } + } /* no_name || to_stdout */ + } /* ORIG_NAME */ /* Discard file comment if any */ if ((flags & COMMENT) != 0) { @@ -1171,24 +1241,126 @@ local int get_method(in) } else if (memcmp(magic, PACK_MAGIC, 2) == 0) { work = unpack; method = PACKED; + } else if (memcmp(magic, LZW_MAGIC, 2) == 0) { work = unlzw; method = COMPRESSED; last_member = 1; + + } else if (memcmp(magic, LZH_MAGIC, 2) == 0) { + work = unlzh; + method = LZHED; + last_member = 1; + + } else if (force && to_stdout) { /* pass input unchanged */ + method = STORED; + work = copy; + inptr = 0; + last_member = 1; } if (method >= 0) return method; + if (part_nb == 1) { fprintf(stderr, "\n%s: %s: not in gzip format\n", progname, ifname); exit_code = ERROR; return -1; } else { - WARN((stderr, "\n%s: %s: trailing garbage ignored\n", + WARN((stderr, "\n%s: %s: decompression OK, trailing garbage ignored\n", progname, ifname)); return -2; } } /* ======================================================================== + * Display the characteristics of the compressed file. + * If the given method is < 0, display the accumulated totals. + * IN assertions: time_stamp, header_bytes and ifile_size are initialized. + */ +local void do_list(ifd, method) + int ifd; /* input file descriptor */ + int method; /* compression method */ +{ + ulg crc; /* original crc */ + static int first_time = 1; + static char* methods[MAX_METHODS] = { + "store", /* 0 */ + "compr", /* 1 */ + "pack ", /* 2 */ + "lzh ", /* 3 */ + "", "", "", "", /* 4 to 7 reserved */ + "defla"}; /* 8 */ + char *date; + + if (first_time && method >= 0) { + first_time = 0; + if (verbose) { + printf("method crc date time "); + } + if (!quiet) { + printf("compressed uncompr. ratio uncompressed_name\n"); + } + } else if (method < 0) { + if (total_in <= 0 || total_out <= 0) return; + if (verbose) { + printf(" %9lu %9lu ", + total_in, total_out); + } else if (!quiet) { + printf("%9ld %9ld ", total_in, total_out); + } + display_ratio(total_out-(total_in-header_bytes), total_out, stdout); + /* header_bytes is not meaningful but used to ensure the same + * ratio if there is a single file. + */ + printf(" (totals)\n"); + return; + } + crc = ~0; /* unknown */ + bytes_out = -1L; + bytes_in = ifile_size; + +#if RECORD_IO == 0 + if (method == DEFLATED && !last_member) { + /* Get the crc and uncompressed size for gzip'ed (not zip'ed) files. + * If the lseek fails, we could use read() to get to the end, but + * --list is used to get quick results. + * Use "gunzip < foo.gz | wc -c" to get the uncompressed size if + * you are not concerned about speed. + */ + bytes_in = (long)lseek(ifd, (off_t)(-8), SEEK_END); + if (bytes_in != -1L) { + uch buf[8]; + bytes_in += 8L; + if (read(ifd, buf, sizeof(buf)) != sizeof(buf)) { + read_error(); + } + crc = LG(buf); + bytes_out = LG(buf+4); + } + } +#endif /* RECORD_IO */ + date = ctime(&time_stamp) + 4; /* skip the day of the week */ + date[12] = '\0'; /* suppress the 1/100sec and the year */ + if (verbose) { + printf("%5s %08lx %11s ", methods[method], crc, date); + } + printf("%9ld %9ld ", bytes_in, bytes_out); + if (bytes_in == -1L) { + total_in = -1L; + bytes_in = bytes_out = header_bytes = 0; + } else if (total_in >= 0) { + total_in += bytes_in; + } + if (bytes_out == -1L) { + total_out = -1L; + bytes_in = bytes_out = header_bytes = 0; + } else if (total_out >= 0) { + total_out += bytes_out; + } + display_ratio(bytes_out-(bytes_in-header_bytes), bytes_out, stdout); + printf(" %s\n", ofname); +} + +/* ======================================================================== * Return true if the two stat structures correspond to the same file. */ local int same_file(stat1, stat2) @@ -1232,6 +1404,62 @@ local int name_too_long(name, statb) } /* ======================================================================== + * Shorten the given name by one character, or replace a .tar extension + * with .tgz. Truncate the last part of the name which is longer than + * MIN_PART characters: 1234.678.012.gz -> 123.678.012.gz. If the name + * has only parts shorter than MIN_PART truncate the longest part. + * + * IN assertion: This function is only called for the compressed file; + * the suffix of the given name is z_suffix. + */ +local void shorten_name(name) + char *name; +{ + int len; /* length of name without z_suffix */ + char *trunc = NULL; /* character to be truncated */ + int plen; /* current part length */ + int min_part = MIN_PART; /* current minimum part length */ + char *p; + + p = get_suffix(name); + if (p == NULL) error("can't recover suffix\n"); + *p = '\0'; + len = strlen(name); + save_orig_name = 1; + + /* compress 1234567890.tar to 1234567890.tgz */ + if (len > 4 && strequ(p-4, ".tar")) { + strcpy(p-4, ".tgz"); + return; + } + /* Try keeping short extensions intact: + * 1234.678.012.gz -> 123.678.012.gz + */ + do { + p = strrchr(name, PATH_SEP); + p = p ? p+1 : name; + while (*p) { + plen = strcspn(p, PART_SEP); + p += plen; + if (plen > min_part) trunc = p-1; + if (*p) p++; + } + } while (trunc == NULL && --min_part != 0); + + if (trunc != NULL) { + do { + trunc[0] = trunc[1]; + } while (*trunc++); + trunc--; + } else { + trunc = strrchr(name, PART_SEP[0]); + if (trunc == NULL) error("internal error in shorten_name"); + if (trunc[1] == '\0') trunc--; /* force truncation */ + } + strcpy(trunc, z_suffix); +} + +/* ======================================================================== * If compressing to a file, check if ofname is not ambiguous * because the operating system truncates names. Otherwise, generate * a new ofname and save the original name in the compressed file. @@ -1247,22 +1475,15 @@ local int name_too_long(name, statb) */ local int check_ofname() { - int s = strlen(ofname); struct stat ostat; /* stat for ofname */ if (stat(ofname, &ostat) != 0) return 0; /* Check for name truncation on existing file: */ -#ifdef NO_MULTIPLE_DOTS if (!decompress && name_too_long(ofname, &ostat)) { -#else - if (!decompress && s > 8 && name_too_long(ofname, &ostat)) { -#endif - save_orig_name = 1; - strcpy(ofname+s-z_len-1, z_suffix); /* f.ext.gz -> f.ex.gz */ - + shorten_name(ofname); if (stat(ofname, &ostat) != 0) return 0; - } /* !decompress && name_too_long */ + } /* Check that the input and output files are different (could be * the same by name truncation or links). diff --git a/gnu/usr.bin/gzip/gzip.h b/gnu/usr.bin/gzip/gzip.h index a4d6376..88b0710 100644 --- a/gnu/usr.bin/gzip/gzip.h +++ b/gnu/usr.bin/gzip/gzip.h @@ -16,7 +16,10 @@ typedef char *voidp; #endif -/* I don't like nested includes, but the string functions are used too often */ +/* I don't like nested includes, but the string and io functions are used + * too often + */ +#include <stdio.h> #if !defined(NO_STRING_H) || defined(STDC_HEADERS) # include <string.h> # if !defined(STDC_HEADERS) && !defined(NO_MEMORY_H) && !defined(__GNUC__) @@ -48,11 +51,13 @@ typedef unsigned long ulg; #define WARNING 2 /* Compression methods (see algorithm.doc) */ -#define STORED 0 -#define COMPRESSED 1 -#define PACKED 2 -/* methods 3 to 7 reserved */ -#define DEFLATED 8 +#define STORED 0 +#define COMPRESSED 1 +#define PACKED 2 +#define LZHED 3 +/* methods 4 to 7 reserved */ +#define DEFLATED 8 +#define MAX_METHODS 9 extern int method; /* compression method */ /* To save memory for 16 bit systems, some arrays are overlaid between @@ -60,7 +65,8 @@ extern int method; /* compression method */ * deflate: prev+head window d_buf l_buf outbuf * unlzw: tab_prefix tab_suffix stack inbuf outbuf * inflate: window inbuf - * unpack: window inbuf + * unpack: window inbuf prefix_len + * unlzh: left+right window c_table inbuf c_len * For compression, input is done in window[]. For decompression, output * is done in window except for unlzw. */ @@ -139,17 +145,18 @@ extern char ifname[]; /* input file name or "stdin" */ extern char ofname[]; /* output file name or "stdout" */ extern char *progname; /* program name */ -extern ulg time_stamp; /* original time stamp (modification time) */ +extern long time_stamp; /* original time stamp (modification time) */ extern long ifile_size; /* input file size, -1 for devices (debug only) */ typedef int file_t; /* Do not use stdio */ #define NO_FILE (-1) /* in memory compression */ +#define PACK_MAGIC "\037\036" /* Magic header for packed files */ #define GZIP_MAGIC "\037\213" /* Magic header for gzip files, 1F 8B */ #define OLD_GZIP_MAGIC "\037\236" /* Magic header for gzip 0.5 = freeze 1.x */ +#define LZH_MAGIC "\037\240" /* Magic header for SCO LZH Compress files*/ #define PKZIP_MAGIC "\120\113\003\004" /* Magic header for pkzip files */ -#define PACK_MAGIC "\037\036" /* Magic header for packed files */ /* gzip flag byte */ #define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ @@ -192,7 +199,8 @@ extern int test; /* check .z file integrity */ extern int to_stdout; /* output to stdout (-c) */ extern int save_orig_name; /* set if original name must be saved */ -#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf()) +#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf(0)) +#define try_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf(1)) /* put_byte is used for the compressed output, put_ubyte for the * uncompressed output. However unlzw() uses window for its @@ -261,6 +269,9 @@ extern int check_zipfile OF((int in)); /* in unpack.c */ extern int unpack OF((int in, int out)); + /* in unlzh.c */ +extern int unlzh OF((int in, int out)); + /* in gzip.c */ RETSIGTYPE abort_gzip OF((void)); @@ -282,20 +293,22 @@ void copy_block OF((char *buf, unsigned len, int header)); extern int (*read_buf) OF((char *buf, unsigned size)); /* in util.c: */ +extern int copy OF((int in, int out)); extern ulg updcrc OF((uch *s, unsigned n)); extern void clear_bufs OF((void)); -extern int fill_inbuf OF((void)); +extern int fill_inbuf OF((int eof_ok)); extern void flush_outbuf OF((void)); extern void flush_window OF((void)); extern void write_buf OF((int fd, voidp buf, unsigned cnt)); extern char *strlwr OF((char *s)); extern char *basename OF((char *fname)); +extern void make_simple_name OF((char *name)); extern char *add_envopt OF((int *argcp, char ***argvp, char *env)); extern void error OF((char *m)); extern void warn OF((char *a, char *b)); extern void read_error OF((void)); extern void write_error OF((void)); -extern void display_ratio OF((long num, long den)); +extern void display_ratio OF((long num, long den, FILE *file)); extern voidp xmalloc OF((unsigned int size)); /* in inflate.c */ diff --git a/gnu/usr.bin/gzip/inflate.c b/gnu/usr.bin/gzip/inflate.c index aa31f9e..dccd597 100644 --- a/gnu/usr.bin/gzip/inflate.c +++ b/gnu/usr.bin/gzip/inflate.c @@ -97,10 +97,9 @@ */ #ifndef lint -static char rcsid[] = "$Id: inflate.c,v 0.13 1993/04/26 14:18:22 jloup Exp $"; +static char rcsid[] = "$Id: inflate.c,v 0.14 1993/06/10 13:27:04 jloup Exp $"; #endif -#include <stdio.h> #include <sys/types.h> #include "tailor.h" diff --git a/gnu/usr.bin/gzip/lzw.c b/gnu/usr.bin/gzip/lzw.c index cd09047..a360ca9 100644 --- a/gnu/usr.bin/gzip/lzw.c +++ b/gnu/usr.bin/gzip/lzw.c @@ -3,15 +3,13 @@ */ #ifndef lint -static char rcsid[] = "$Id: lzw.c,v 0.8 1993/04/25 08:09:58 jloup Exp $"; +static char rcsid[] = "$Id: lzw.c,v 0.9 1993/06/10 13:27:31 jloup Exp $"; #endif #include "tailor.h" #include "gzip.h" #include "lzw.h" -#include <stdio.h> - static int msg_done = 0; /* Compress in to out with lzw method. */ diff --git a/gnu/usr.bin/gzip/match.S b/gnu/usr.bin/gzip/match.S index cd3176b..4a3d681 100644 --- a/gnu/usr.bin/gzip/match.S +++ b/gnu/usr.bin/gzip/match.S @@ -9,7 +9,7 @@ * Kristoffer Eriksson <ske@pkmab.se> */ -/* $Id: match.S,v 0.13 1993/05/24 12:03:03 jloup Exp $ */ +/* $Id: match.S,v 0.14 1993/06/11 18:33:24 jloup Exp $ */ /* Preprocess with -DNO_UNDERLINE if your C compiler does not prefix * external symbols with an underline character '_'. @@ -44,11 +44,11 @@ .file "match.S" -#define MAX_MATCH 258 -#define MAX_MATCH2 128 /* MAX_MATCH/2-1 */ +#define MAX_MATCH 258 +#define MAX_MATCH2 $128 /* MAX_MATCH/2-1 */ #define MIN_MATCH 3 -#define WSIZE 32768 -#define MAX_DIST WSIZE - MAX_MATCH - MIN_MATCH - 1 +#define WSIZE $32768 +#define MAX_DIST WSIZE - MAX_MATCH - MIN_MATCH - 1 .globl _match_init .globl _longest_match @@ -87,11 +87,11 @@ _longest_match: /* int longest_match(cur_match) */ mov _max_chain_length,%ebp /* chain_length = max_chain_length */ mov _strstart,%edi mov %edi,%edx - sub $ MAX_DIST,%edx /* limit = strstart-MAX_DIST */ + sub MAX_DIST,%edx /* limit = strstart-MAX_DIST */ jae limit_ok sub %edx,%edx /* limit = NIL */ limit_ok: - add $ _window+2,%edi /* edi = offset(window+strstart+2) */ + add $2+_window,%edi /* edi = offset(window+strstart+2) */ mov _prev_length,%ebx /* best_len = prev_length */ movw -3(%ebx,%edi),%ax /* ax = scan[best_len-1..best_len] */ movw -2(%edi),%cx /* cx = scan[0..1] */ @@ -110,7 +110,7 @@ short_loop: * at this point, di == scan+2, si == cur_match, * ax = scan[best_len-1..best_len] and cx = scan[0..1] */ - and $ WSIZE-1, %esi + and WSIZE-1, %esi movw _prev(%esi,%esi),%si /* cur_match = prev[cur_match] */ /* top word of esi is still 0 */ cmp %edx,%esi /* cur_match <= limit ? */ @@ -125,7 +125,7 @@ do_scan: lea _window+2(%esi),%esi /* si = match */ mov %edi,%eax /* ax = scan+2 */ - mov $ MAX_MATCH2,%ecx /* scan for at most MAX_MATCH bytes */ + mov MAX_MATCH2,%ecx /* scan for at most MAX_MATCH bytes */ rep; cmpsw /* loop until mismatch */ je maxmatch /* match of length MAX_MATCH? */ mismatch: @@ -134,7 +134,7 @@ mismatch: xchg %edi,%eax /* edi = scan+2, eax = end of scan */ sub %edi,%eax /* eax = len */ sub %eax,%esi /* esi = cur_match + 2 + offset(window) */ - sub $ _window+2,%esi /* esi = cur_match */ + sub $2+_window,%esi /* esi = cur_match */ subb $1,%cl /* set carry if cl == 0 (cannot use DEC) */ adc $0,%eax /* eax = carry ? len+1 : len */ cmp %ebx,%eax /* len > best_len ? */ diff --git a/gnu/usr.bin/gzip/revision.h b/gnu/usr.bin/gzip/revision.h index 5a4e1e6..4cb03a3 100644 --- a/gnu/usr.bin/gzip/revision.h +++ b/gnu/usr.bin/gzip/revision.h @@ -4,13 +4,13 @@ * terms of the GNU General Public License, see the file COPYING. */ -#define VERSION "1.1.1" +#define VERSION "1.2.2" #define PATCHLEVEL 0 -#define REVDATE "1 Jun 93" +#define REVDATE "17 Jun 93" /* This version does not support compression into old compress format: */ #ifdef LZW # undef LZW #endif -/* $Id: revision.h,v 0.20 1993/06/01 14:03:17 jloup Exp $ */ +/* $Id: revision.h,v 0.23 1993/06/16 15:03:51 jloup Exp $ */ diff --git a/gnu/usr.bin/gzip/tailor.h b/gnu/usr.bin/gzip/tailor.h index 915760a..960ff28 100644 --- a/gnu/usr.bin/gzip/tailor.h +++ b/gnu/usr.bin/gzip/tailor.h @@ -8,12 +8,16 @@ * The target dependent functions should be defined in tailor.c. */ -/* $Id: tailor.h,v 0.16 1993/06/01 12:46:03 jloup Exp $ */ +/* $Id: tailor.h,v 0.18 1993/06/14 19:32:20 jloup Exp $ */ #if defined(__MSDOS__) && !defined(MSDOS) # define MSDOS #endif +#if defined(__OS2__) && !defined(OS2) +# define OS2 +#endif + #if defined(OS2) && defined(MSDOS) /* MS C under OS/2 */ # undef MSDOS #endif @@ -31,6 +35,7 @@ # define MAXSEG_64K # ifdef __TURBOC__ # define NO_UTIME +# define NO_OFF_T # else /* MSC */ # define HAVE_SYS_UTIME_H # define NO_UTIME_H @@ -69,22 +74,34 @@ # define NO_CHOWN # define PROTO # define STDC_HEADERS -# define HAVE_SYS_UTIME_H -# define NO_UTIME_H # define casemap(c) tolow(c) # include <io.h> # define OS_CODE 0x06 # define SET_BINARY_MODE(fd) setmode(fd, O_BINARY) # ifdef _MSC_VER +# define HAVE_SYS_UTIME_H +# define NO_UTIME_H # define MAXSEG_64K # undef near # define near _near # endif # ifdef __EMX__ +# define HAVE_SYS_UTIME_H +# define NO_UTIME_H # define DIRENT # define EXPAND(argc,argv) \ {_response(&argc, &argv); _wildcard(&argc, &argv);} # endif +# ifdef __BORLANDC__ +# define DIRENT +# endif +# ifdef __ZTC__ +# define NO_DIR +# define NO_UTIME_H +# include <dos.h> +# define EXPAND(argc,argv) \ + {response_expand(&argc, &argv);} +# endif #endif #ifdef MSDOS @@ -138,7 +155,6 @@ # ifdef __GNUC__ # define DIRENT # define HAVE_UNISTD_H -# define RETSIGTYPE int # else /* SASC */ # define NO_STDIN_FSTAT # define SYSDIR @@ -149,6 +165,7 @@ # define direct dirent extern void _expand_args(int *argc, char ***argv); # define EXPAND(argc,argv) _expand_args(&argc,&argv); +# undef O_BINARY /* disable useless --ascii option */ # endif #endif @@ -199,7 +216,9 @@ # define put_char(c) put_byte((c) & 0x7F) # define get_char(c) ascii2pascii(get_byte()) # define OS_CODE 0x0F /* temporary, subject to change */ -# undef SIGTERM /* We don't want a signal handler for SIGTERM */ +# ifdef SIGTERM +# undef SIGTERM /* We don't want a signal handler for SIGTERM */ +# endif #endif #ifdef WIN32 @@ -243,6 +262,19 @@ # define MAX_SUFFIX 30 #endif +#ifndef MAKE_LEGAL_NAME +# ifdef NO_MULTIPLE_DOTS +# define MAKE_LEGAL_NAME(name) make_simple_name(name) +# else +# define MAKE_LEGAL_NAME(name) +# endif +#endif + +#ifndef MIN_PART +# define MIN_PART 3 + /* keep at least MIN_PART chars between dots in a file name. */ +#endif + #ifndef EXPAND # define EXPAND(argc,argv) #endif diff --git a/gnu/usr.bin/gzip/trees.c b/gnu/usr.bin/gzip/trees.c index 2cf380a..673dfde 100644 --- a/gnu/usr.bin/gzip/trees.c +++ b/gnu/usr.bin/gzip/trees.c @@ -54,13 +54,12 @@ */ #include <ctype.h> -#include <stdio.h> #include "tailor.h" #include "gzip.h" #ifndef lint -static char rcsid[] = "$Id: trees.c,v 0.11 1993/03/26 14:55:43 jloup Exp $"; +static char rcsid[] = "$Id: trees.c,v 0.12 1993/06/10 13:27:54 jloup Exp $"; #endif /* =========================================================================== diff --git a/gnu/usr.bin/gzip/unlzh.c b/gnu/usr.bin/gzip/unlzh.c new file mode 100644 index 0000000..2c03d1f --- /dev/null +++ b/gnu/usr.bin/gzip/unlzh.c @@ -0,0 +1,385 @@ +/* unlzh.c -- decompress files in SCO compress -H (LZH) format. + * The code in this file is directly derived from the public domain 'ar002' + * written by Haruhiko Okumura. + */ + +#include <stdio.h> + +#include "tailor.h" +#include "gzip.h" +#include "lzw.h" /* just for consistency checking */ + +/* decode.c */ + +local unsigned decode OF((unsigned count, uch buffer[])); +local void decode_start OF((void)); + +/* huf.c */ +local void huf_decode_start OF((void)); +local unsigned decode_c OF((void)); +local unsigned decode_p OF((void)); + +/* io.c */ +local void fillbuf OF((int n)); +local unsigned getbits OF((int n)); +local void init_getbits OF((void)); + +#define DICBIT 13 /* 12(-lh4-) or 13(-lh5-) */ +#define DICSIZ ((unsigned) 1 << DICBIT) + +#ifndef CHAR_BIT +# define CHAR_BIT 8 +#endif + +#ifndef UCHAR_MAX +# define UCHAR_MAX 255 +#endif + +#define BITBUFSIZ (CHAR_BIT * 2 * sizeof(char)) +/* Do not use CHAR_BIT * sizeof(bitbuf), does not work on machines + * for which short is not on 16 bits (Cray). + */ + +/* encode.c and decode.c */ + +#define MAXMATCH 256 /* formerly F (not more than UCHAR_MAX + 1) */ +#define THRESHOLD 3 /* choose optimal value */ + +/* huf.c */ + +#define NC (UCHAR_MAX + MAXMATCH + 2 - THRESHOLD) + /* alphabet = {0, 1, 2, ..., NC - 1} */ +#define CBIT 9 /* $\lfloor \log_2 NC \rfloor + 1$ */ +#define CODE_BIT 16 /* codeword length */ + +#define NP (DICBIT + 1) +#define NT (CODE_BIT + 3) +#define PBIT 4 /* smallest integer such that (1U << PBIT) > NP */ +#define TBIT 5 /* smallest integer such that (1U << TBIT) > NT */ +#if NT > NP +# define NPT NT +#else +# define NPT NP +#endif + +/* local ush left[2 * NC - 1]; */ +/* local ush right[2 * NC - 1]; */ +#define left prev +#define right head +#if NC > 1<<(BITS-2) + error cannot overlay left+right and prev +#endif + +/* local uch c_len[NC]; */ +#define c_len outbuf +#if NC > OUTBUFSIZ + error cannot overlay c_len and outbuf +#endif + +local uch pt_len[NPT]; +local unsigned blocksize; +local ush pt_table[256]; + +/* local ush c_table[4096]; */ +#define c_table d_buf +#if DIST_BUFSIZE < 4096 + error cannot overlay c_table and d_buf +#endif + +local ush bitbuf; +local unsigned subbitbuf; +local int bitcount; + +local void fillbuf(n) /* Shift bitbuf n bits left, read n bits */ + int n; +{ + bitbuf <<= n; + while (n > bitcount) { + bitbuf |= subbitbuf << (n -= bitcount); + subbitbuf = (unsigned)try_byte(); + if ((int)subbitbuf == EOF) subbitbuf = 0; + bitcount = CHAR_BIT; + } + bitbuf |= subbitbuf >> (bitcount -= n); +} + +local unsigned getbits(n) + int n; +{ + unsigned x; + + x = bitbuf >> (BITBUFSIZ - n); fillbuf(n); + return x; +} + +local void init_getbits() +{ + bitbuf = 0; subbitbuf = 0; bitcount = 0; + fillbuf(BITBUFSIZ); +} + +/*********************************************************** + maketbl.c -- make table for decoding +***********************************************************/ + +local void make_table(nchar, bitlen, tablebits, table) + int nchar; + uch bitlen[]; + int tablebits; + ush table[]; +{ + ush count[17], weight[17], start[18], *p; + unsigned i, k, len, ch, jutbits, avail, nextcode, mask; + + for (i = 1; i <= 16; i++) count[i] = 0; + for (i = 0; i < nchar; i++) count[bitlen[i]]++; + + start[1] = 0; + for (i = 1; i <= 16; i++) + start[i + 1] = start[i] + (count[i] << (16 - i)); + if (start[17] != (ush)((unsigned) 1 << 16)) + error("Bad table\n"); + + jutbits = 16 - tablebits; + for (i = 1; i <= tablebits; i++) { + start[i] >>= jutbits; + weight[i] = (unsigned) 1 << (tablebits - i); + } + while (i <= 16) { + weight[i] = (unsigned) 1 << (16 - i); + i++; + } + + i = start[tablebits + 1] >> jutbits; + if (i != (ush)((unsigned) 1 << 16)) { + k = 1 << tablebits; + while (i != k) table[i++] = 0; + } + + avail = nchar; + mask = (unsigned) 1 << (15 - tablebits); + for (ch = 0; ch < nchar; ch++) { + if ((len = bitlen[ch]) == 0) continue; + nextcode = start[len] + weight[len]; + if (len <= tablebits) { + for (i = start[len]; i < nextcode; i++) table[i] = ch; + } else { + k = start[len]; + p = &table[k >> jutbits]; + i = len - tablebits; + while (i != 0) { + if (*p == 0) { + right[avail] = left[avail] = 0; + *p = avail++; + } + if (k & mask) p = &right[*p]; + else p = &left[*p]; + k <<= 1; i--; + } + *p = ch; + } + start[len] = nextcode; + } +} + +/*********************************************************** + huf.c -- static Huffman +***********************************************************/ + +local void read_pt_len(nn, nbit, i_special) + int nn; + int nbit; + int i_special; +{ + int i, c, n; + unsigned mask; + + n = getbits(nbit); + if (n == 0) { + c = getbits(nbit); + for (i = 0; i < nn; i++) pt_len[i] = 0; + for (i = 0; i < 256; i++) pt_table[i] = c; + } else { + i = 0; + while (i < n) { + c = bitbuf >> (BITBUFSIZ - 3); + if (c == 7) { + mask = (unsigned) 1 << (BITBUFSIZ - 1 - 3); + while (mask & bitbuf) { mask >>= 1; c++; } + } + fillbuf((c < 7) ? 3 : c - 3); + pt_len[i++] = c; + if (i == i_special) { + c = getbits(2); + while (--c >= 0) pt_len[i++] = 0; + } + } + while (i < nn) pt_len[i++] = 0; + make_table(nn, pt_len, 8, pt_table); + } +} + +local void read_c_len() +{ + int i, c, n; + unsigned mask; + + n = getbits(CBIT); + if (n == 0) { + c = getbits(CBIT); + for (i = 0; i < NC; i++) c_len[i] = 0; + for (i = 0; i < 4096; i++) c_table[i] = c; + } else { + i = 0; + while (i < n) { + c = pt_table[bitbuf >> (BITBUFSIZ - 8)]; + if (c >= NT) { + mask = (unsigned) 1 << (BITBUFSIZ - 1 - 8); + do { + if (bitbuf & mask) c = right[c]; + else c = left [c]; + mask >>= 1; + } while (c >= NT); + } + fillbuf((int) pt_len[c]); + if (c <= 2) { + if (c == 0) c = 1; + else if (c == 1) c = getbits(4) + 3; + else c = getbits(CBIT) + 20; + while (--c >= 0) c_len[i++] = 0; + } else c_len[i++] = c - 2; + } + while (i < NC) c_len[i++] = 0; + make_table(NC, c_len, 12, c_table); + } +} + +local unsigned decode_c() +{ + unsigned j, mask; + + if (blocksize == 0) { + blocksize = getbits(16); + if (blocksize == 0) { + return NC; /* end of file */ + } + read_pt_len(NT, TBIT, 3); + read_c_len(); + read_pt_len(NP, PBIT, -1); + } + blocksize--; + j = c_table[bitbuf >> (BITBUFSIZ - 12)]; + if (j >= NC) { + mask = (unsigned) 1 << (BITBUFSIZ - 1 - 12); + do { + if (bitbuf & mask) j = right[j]; + else j = left [j]; + mask >>= 1; + } while (j >= NC); + } + fillbuf((int) c_len[j]); + return j; +} + +local unsigned decode_p() +{ + unsigned j, mask; + + j = pt_table[bitbuf >> (BITBUFSIZ - 8)]; + if (j >= NP) { + mask = (unsigned) 1 << (BITBUFSIZ - 1 - 8); + do { + if (bitbuf & mask) j = right[j]; + else j = left [j]; + mask >>= 1; + } while (j >= NP); + } + fillbuf((int) pt_len[j]); + if (j != 0) j = ((unsigned) 1 << (j - 1)) + getbits((int) (j - 1)); + return j; +} + +local void huf_decode_start() +{ + init_getbits(); blocksize = 0; +} + +/*********************************************************** + decode.c +***********************************************************/ + +local int j; /* remaining bytes to copy */ +local int done; /* set at end of input */ + +local void decode_start() +{ + huf_decode_start(); + j = 0; + done = 0; +} + +/* Decode the input and return the number of decoded bytes put in buffer + */ +local unsigned decode(count, buffer) + unsigned count; + uch buffer[]; + /* The calling function must keep the number of + bytes to be processed. This function decodes + either 'count' bytes or 'DICSIZ' bytes, whichever + is smaller, into the array 'buffer[]' of size + 'DICSIZ' or more. + Call decode_start() once for each new file + before calling this function. + */ +{ + local unsigned i; + unsigned r, c; + + r = 0; + while (--j >= 0) { + buffer[r] = buffer[i]; + i = (i + 1) & (DICSIZ - 1); + if (++r == count) return r; + } + for ( ; ; ) { + c = decode_c(); + if (c == NC) { + done = 1; + return r; + } + if (c <= UCHAR_MAX) { + buffer[r] = c; + if (++r == count) return r; + } else { + j = c - (UCHAR_MAX + 1 - THRESHOLD); + i = (r - decode_p() - 1) & (DICSIZ - 1); + while (--j >= 0) { + buffer[r] = buffer[i]; + i = (i + 1) & (DICSIZ - 1); + if (++r == count) return r; + } + } + } +} + + +/* =========================================================================== + * Unlzh in to out. Return OK or ERROR. + */ +int unlzh(in, out) + int in; + int out; +{ + unsigned n; + ifd = in; + ofd = out; + + decode_start(); + while (!done) { + n = decode((unsigned) DICSIZ, window); + if (!test && n > 0) { + write_buf(out, (char*)window, n); + } + } + return OK; +} diff --git a/gnu/usr.bin/gzip/unlzw.c b/gnu/usr.bin/gzip/unlzw.c index 0687c1b..61c45fc 100644 --- a/gnu/usr.bin/gzip/unlzw.c +++ b/gnu/usr.bin/gzip/unlzw.c @@ -8,10 +8,9 @@ */ #ifndef lint -static char rcsid[] = "$Id: unlzw.c,v 0.13 1993/05/27 10:32:55 jloup Exp $"; +static char rcsid[] = "$Id: unlzw.c,v 0.15 1993/06/10 13:28:35 jloup Exp $"; #endif -#include <stdio.h> #include <sys/types.h> #include "tailor.h" @@ -263,6 +262,7 @@ int unlzw(in, out) read_error(); } insize += rsize; + bytes_in += (ulg)rsize; } inbits = ((rsize != 0) ? ((long)insize - insize%n_bits)<<3 : ((long)insize<<3)-(n_bits-1)); @@ -313,7 +313,8 @@ int unlzw(in, out) posbits, p[-1],p[0],p[1],p[2],p[3]); #endif if (!test && outpos > 0) { - write_buf(out, outbuf, outpos); + write_buf(out, (char*)outbuf, outpos); + bytes_out += (ulg)outpos; } error("corrupt input. Use zcat to recover some data."); } @@ -341,7 +342,10 @@ int unlzw(in, out) outpos += i; } if (outpos >= OUTBUFSIZ) { - if (!test) write_buf(out, outbuf, outpos); + if (!test) { + write_buf(out, (char*)outbuf, outpos); + bytes_out += (ulg)outpos; + } outpos = 0; } stackp+= i; @@ -360,10 +364,11 @@ int unlzw(in, out) } oldcode = incode; /* Remember previous code. */ } - bytes_in += rsize; - } while (rsize != 0); - if (!test && outpos > 0) write_buf(out, outbuf, outpos); + if (!test && outpos > 0) { + write_buf(out, (char*)outbuf, outpos); + bytes_out += (ulg)outpos; + } return OK; } diff --git a/gnu/usr.bin/gzip/unpack.c b/gnu/usr.bin/gzip/unpack.c index e6cf7ca..789cbc0 100644 --- a/gnu/usr.bin/gzip/unpack.c +++ b/gnu/usr.bin/gzip/unpack.c @@ -5,11 +5,9 @@ */ #ifndef lint -static char rcsid[] = "$Id: unpack.c,v 1.3 1993/05/28 17:56:07 jloup Exp $"; +static char rcsid[] = "$Id: unpack.c,v 1.4 1993/06/11 19:25:36 jloup Exp $"; #endif -#include <stdio.h> - #include "tailor.h" #include "gzip.h" #include "crypt.h" @@ -26,11 +24,7 @@ static char rcsid[] = "$Id: unpack.c,v 1.3 1993/05/28 17:56:07 jloup Exp $"; #define LITERALS 256 /* Number of literals, excluding the End of Block (EOB) code */ -#ifdef SMALL_MEM -# define MAX_PEEK 10 -#else -# define MAX_PEEK 12 -#endif +#define MAX_PEEK 12 /* Maximum number of 'peek' bits used to optimize traversal of the * Huffman tree. */ @@ -54,7 +48,8 @@ local int parents[MAX_BITLEN+1]; /* Number of parents for each bit length */ local int peek_bits; /* Number of peek bits currently used */ -local uch prefix_len[1 << MAX_PEEK]; +/* local uch prefix_len[1 << MAX_PEEK]; */ +#define prefix_len outbuf /* For each bit pattern b of peek_bits bits, prefix_len[b] is the length * of the Huffman code starting with a prefix of b (upper bits), or 0 * if all codes of prefix b have more than peek_bits bits. It is not @@ -62,6 +57,9 @@ local uch prefix_len[1 << MAX_PEEK]; * codes encountered in the input stream are short codes (by construction). * So for most codes a single lookup will be necessary. */ +#if 1<<MAX_PEEK > OUTBUFSIZ + error cannot overlay prefix_len and outbuf +#endif local ulg bitbuf; /* Bits are added on the low part of bitbuf and read from the high part. */ diff --git a/gnu/usr.bin/gzip/unzip.c b/gnu/usr.bin/gzip/unzip.c index a78622a..48cdebe 100644 --- a/gnu/usr.bin/gzip/unzip.c +++ b/gnu/usr.bin/gzip/unzip.c @@ -14,11 +14,9 @@ */ #ifndef lint -static char rcsid[] = "$Id: unzip.c,v 0.12 1993/05/28 17:56:23 jloup Exp $"; +static char rcsid[] = "$Id: unzip.c,v 0.13 1993/06/10 13:29:00 jloup Exp $"; #endif -#include <stdio.h> - #include "tailor.h" #include "gzip.h" #include "crypt.h" diff --git a/gnu/usr.bin/gzip/util.c b/gnu/usr.bin/gzip/util.c index dc3695e..52f1bdd 100644 --- a/gnu/usr.bin/gzip/util.c +++ b/gnu/usr.bin/gzip/util.c @@ -5,10 +5,9 @@ */ #ifndef lint -static char rcsid[] = "$Id: util.c,v 0.14 1993/05/27 10:31:52 jloup Exp $"; +static char rcsid[] = "$Id: util.c,v 0.15 1993/06/15 09:04:13 jloup Exp $"; #endif -#include <stdio.h> #include <ctype.h> #include <errno.h> #include <sys/types.h> @@ -34,6 +33,26 @@ static char rcsid[] = "$Id: util.c,v 0.14 1993/05/27 10:31:52 jloup Exp $"; extern ulg crc_32_tab[]; /* crc table, defined below */ /* =========================================================================== + * Copy input to output unchanged: zcat == cat with --force. + * IN assertion: insize bytes have already been read in inbuf. + */ +int copy(in, out) + int in, out; /* input and output file descriptors */ +{ + errno = 0; + while (insize != 0 && (int)insize != EOF) { + write_buf(out, (char*)inbuf, insize); + bytes_out += insize; + insize = read(in, (char*)inbuf, INBUFSIZ); + } + if ((int)insize == EOF && errno != 0) { + read_error(); + } + bytes_in = bytes_out; + return OK; +} + +/* =========================================================================== * Run a set of bytes through the crc shift register. If s is a NULL * pointer, then initialize the crc shift register contents instead. * Return the current crc in either case. @@ -69,10 +88,10 @@ void clear_bufs() } /* =========================================================================== - * Fill the input buffer. This is called only when the buffer is empty - * and at least one byte is really needed. + * Fill the input buffer. This is called only when the buffer is empty. */ -int fill_inbuf() +int fill_inbuf(eof_ok) + int eof_ok; /* set if EOF acceptable as a result */ { int len; @@ -86,6 +105,7 @@ int fill_inbuf() } while (insize < INBUFSIZ); if (insize == 0) { + if (eof_ok) return EOF; read_error(); } bytes_in += (ulg)insize; @@ -177,6 +197,26 @@ char *basename(fname) return fname; } +/* ======================================================================== + * Make a file name legal for file systems not allowing file names with + * multiple dots or starting with a dot (such as MSDOS), by changing + * all dots except the last one into underlines. A target dependent + * function can be used instead of this simple function by defining the macro + * MAKE_LEGAL_NAME in tailor.h and providing the function in a target + * dependent module. + */ +void make_simple_name(name) + char *name; +{ + char *p = strrchr(name, '.'); + if (p == NULL) return; + if (p == name) p++; + do { + if (*--p == '.') *p = '_'; + } while (p != name); +} + + #if defined(NO_STRING_H) && !defined(STDC_HEADERS) /* Provide missing strspn and strcspn functions. */ @@ -325,11 +365,12 @@ void write_error() } /* ======================================================================== - * Display compression ratio on stderr. + * Display compression ratio on the given stream on 6 characters. */ -void display_ratio(num, den) +void display_ratio(num, den, file) long num; long den; + FILE *file; { long ratio; /* 1000 times the compression ratio */ @@ -341,10 +382,12 @@ void display_ratio(num, den) ratio = num/(den/1000L); } if (ratio < 0) { - putc('-', stderr); + putc('-', file); ratio = -ratio; + } else { + putc(' ', file); } - fprintf(stderr, "%2ld.%ld%%", ratio / 10L, ratio % 10L); + fprintf(file, "%2ld.%1ld%%", ratio / 10L, ratio % 10L); } diff --git a/gnu/usr.bin/gzip/zdiff b/gnu/usr.bin/gzip/zdiff index c21e7ef..3de5cb4 100644 --- a/gnu/usr.bin/gzip/zdiff +++ b/gnu/usr.bin/gzip/zdiff @@ -1,4 +1,5 @@ #!/bin/sh +# sh is buggy on RS/6000 AIX 3.2. Replace above line with #!/bin/ksh # Zcmp and zdiff are used to invoke the cmp or the diff pro- # gram on compressed files. All options specified are passed @@ -8,6 +9,7 @@ # necessary) and fed to cmp or diff. The exit status from cmp # or diff is preserved. +PATH="/usr/local/bin:$PATH"; export PATH prog=`echo $0 | sed 's|.*/||'` case "$prog" in *cmp) comp=${CMP-cmp} ;; diff --git a/gnu/usr.bin/gzip/zdiff.1 b/gnu/usr.bin/gzip/zdiff.1 index 44f9137..ea3bf41 100644 --- a/gnu/usr.bin/gzip/zdiff.1 +++ b/gnu/usr.bin/gzip/zdiff.1 @@ -35,7 +35,7 @@ or .I diff is preserved. .SH "SEE ALSO" -cmp(1), diff(1), zmore(1), znew(1), zforce(1), gzip(1), gzexe(1) +cmp(1), diff(1), zmore(1), zgrep(1), znew(1), zforce(1), gzip(1), gzexe(1) .SH BUGS Messages from the .I cmp diff --git a/gnu/usr.bin/gzip/zforce b/gnu/usr.bin/gzip/zforce index 9fe85ad..17258a4 100644 --- a/gnu/usr.bin/gzip/zforce +++ b/gnu/usr.bin/gzip/zforce @@ -5,6 +5,7 @@ # This can be useful for files with names truncated after a file transfer. # 12345678901234 is renamed to 12345678901.gz +PATH="/usr/local/bin:$PATH"; export PATH x=`basename $0` if test $# = 0; then echo "force a '.gz' extension on all gzip files" @@ -23,17 +24,18 @@ for i do test `expr "$i" : '.*[.-]gz$'` -eq 0 || continue test `expr "$i" : '.*[.]t[ag]z$'` -eq 0 || continue - gzip -t "$i" 2>/dev/null || continue + if gzip -l < "$i" 2>/dev/null | grep '^defl' > /dev/null; then - if test `expr "$i" : '^............'` -eq 12; then - new=`expr "$i" : '\(.*\)...$`.gz - else - new="$i.gz" + if test `expr "$i" : '^............'` -eq 12; then + new=`expr "$i" : '\(.*\)...$`.gz + else + new="$i.gz" + fi + if mv "$i" "$new" 2>/dev/null; then + echo $i -- replaced with $new + continue + fi + res=1; echo ${x}: cannot rename $i to $new fi - if mv "$i" "$new" 2>/dev/null; then - echo $i -- replaced with $new - continue - fi - res=1; echo ${x}: cannot rename $i to $new done exit $res diff --git a/gnu/usr.bin/gzip/zforce.1 b/gnu/usr.bin/gzip/zforce.1 index e231815..37c6aba 100644 --- a/gnu/usr.bin/gzip/zforce.1 +++ b/gnu/usr.bin/gzip/zforce.1 @@ -17,4 +17,4 @@ is truncated to make room for the .gz suffix. For example, 12345678901234 is renamed to 12345678901.gz. A file name such as foo.tgz is left intact. .SH "SEE ALSO" -gzip(1), znew(1), zmore(1), zcmp(1), gzexe(1) +gzip(1), znew(1), zmore(1), zgrep(1), zdiff(1), gzexe(1) diff --git a/gnu/usr.bin/gzip/zgrep b/gnu/usr.bin/gzip/zgrep new file mode 100644 index 0000000..bcc10cc --- /dev/null +++ b/gnu/usr.bin/gzip/zgrep @@ -0,0 +1,72 @@ +#!/bin/sh + +# zgrep -- a wrapper around a grep program that decompresses files as needed +# Adapted from a version sent by Charles Levert <charles@comm.polymtl.ca> + +PATH="/usr/local/bin:$PATH"; export PATH + +prog=`echo $0 | sed 's|.*/||'` +case "$prog" in + *egrep) grep=${EGREP-egrep} ;; + *fgrep) grep=${FGREP-fgrep} ;; + *) grep=${GREP-grep} ;; +esac +A= +fileno=0 +pat="" +while test $# -ne 0; do + case "$1" in + -e | -f) opt="$opt $1"; shift; pat="$1" + if test "$grep" = grep; then # grep is buggy with -e on SVR4 + grep=egrep + fi;; + -*) opt="$opt $1";; + *) if test -z "$pat"; then + pat="$1" + else + fileno=`expr $fileno + 1` + eval A$fileno=\$1 + A="$A \"\$A$fileno\"" + fi + ;; + esac + shift +done + +if test -z "$pat"; then + echo "grep through gzip files" + echo "usage: $prog [grep_options] pattern [files]" + exit 1 +fi + +list=0 +silent=0 +op=`echo "$opt" | sed -e 's/ //g' -e 's/-//g'` +case "$op" in + *l*) list=1 +esac +case "$op" in + *h*) silent=1 +esac + +if test $fileno -eq 0; then + gzip -cdfq | $grep $opt "$pat" + exit $? +fi +eval set "$A" # files in $1, $2 ... + +res=0 +for i do + if test $list -eq 1; then + gzip -cdfq "$i" | $grep $opt "$pat" > /dev/null && echo $i + r=$? + elif test $# -eq 1 -o $silent -eq 1; then + gzip -cdfq "$i" | $grep $opt "$pat" + r=$? + else + gzip -cdfq "$i" | $grep $opt "$pat" | sed "s|^|${i}:|" + r=$? + fi + test "$r" -ne 0 && res="$r" +done +exit $res diff --git a/gnu/usr.bin/gzip/zgrep.1 b/gnu/usr.bin/gzip/zgrep.1 new file mode 100644 index 0000000..a52a88a --- /dev/null +++ b/gnu/usr.bin/gzip/zgrep.1 @@ -0,0 +1,44 @@ +.TH ZGREP 1 +.SH NAME +zgrep \- search possibly compressed files for a regular expression +.SH SYNOPSIS +.B zgrep +[ grep_options ] +.BI [\ -e\ ] " pattern" +.IR filename ".\|.\|." +.SH DESCRIPTION +.IR Zgrep +is used to invoke the +.I grep +on compress'ed or gzip'ed files. All options specified are passed directly to +.I grep. +If no file is specified, then the standard input is decompressed +if necessary and fed to grep. +Otherwise the given files are uncompressed if necessary and fed to +.I grep. +.PP +If +.I zgrep +is invoked as +.I zegrep +or +.I zfgrep +then +.I egrep +or +.I fgrep +is used instead of +.I grep. +If the GREP environment variable is set, +.I zgrep +uses it as the +.I grep +program to be invoked. For example: + + for sh: GREP=fgrep zgrep string files + for csh: (setenv GREP fgrep; zgrep string files) +.SH AUTHOR +Charles Levert (charles@comm.polymtl.ca) +.SH "SEE ALSO" +grep(1), egrep(1), fgrep(1), zdiff(1), zmore(1), znew(1), zforce(1), +gzip(1), gzexe(1) diff --git a/gnu/usr.bin/gzip/zip.c b/gnu/usr.bin/gzip/zip.c index 5bf172f..3928262 100644 --- a/gnu/usr.bin/gzip/zip.c +++ b/gnu/usr.bin/gzip/zip.c @@ -5,11 +5,10 @@ */ #ifndef lint -static char rcsid[] = "$Id: zip.c,v 0.16 1993/05/28 14:51:17 jloup Exp $"; +static char rcsid[] = "$Id: zip.c,v 0.17 1993/06/10 13:29:25 jloup Exp $"; #endif #include <ctype.h> -#include <stdio.h> #include <sys/types.h> #include "tailor.h" diff --git a/gnu/usr.bin/gzip/zmore b/gnu/usr.bin/gzip/zmore index 64f7b1b..6a089a2 100644 --- a/gnu/usr.bin/gzip/zmore +++ b/gnu/usr.bin/gzip/zmore @@ -1,22 +1,27 @@ #!/bin/sh +PATH="/usr/local/bin:$PATH"; export PATH if test "`echo -n a`" = "-n a"; then # looks like a SysV system: n1=''; n2='\c' else n1='-n'; n2='' fi +oldtty=`stty -g 2>/dev/null` if stty -cbreak 2>/dev/null; then cb='cbreak'; ncb='-cbreak' else # 'stty min 1' resets eof to ^a on both SunOS and SysV! cb='min 1 -icanon'; ncb='icanon eof ^d' fi -oldtty=`stty -g` -trap 'stty -g $oldtty 2>/dev/null; exit' 0 2 3 5 10 13 15 +if test $? -eq 0 -a -n "$oldtty"; then + trap 'stty $oldtty 2>/dev/null; exit' 0 2 3 5 10 13 15 +else + trap 'stty $ncb echo 2>/dev/null; exit' 0 2 3 5 10 13 15 +fi if test $# = 0; then - gzip -cd | eval ${PAGER-more} + gzip -cdfq | eval ${PAGER-more} else FIRST=1 for FILE @@ -33,7 +38,7 @@ else fi if test "$ANS" != 's'; then echo "------> $FILE <------" - gzip -cd "$FILE" | eval ${PAGER-more} + gzip -cdfq "$FILE" | eval ${PAGER-more} fi if test -t; then FIRST=0 diff --git a/gnu/usr.bin/gzip/zmore.1 b/gnu/usr.bin/gzip/zmore.1 index 08b49fb..f7f1843 100644 --- a/gnu/usr.bin/gzip/zmore.1 +++ b/gnu/usr.bin/gzip/zmore.1 @@ -6,9 +6,20 @@ zmore \- file perusal filter for crt viewing of compressed text [ name ... ] .SH DESCRIPTION .I Zmore -is a filter which allows examination of compressed text files +is a filter which allows examination of compressed or plain text files one screenful at a time on a soft-copy terminal. -It normally pauses after each screenful, printing --More-- +.I zmore +works on files compressed with +.I compress, pack +or +.I gzip, +and also on uncompressed files. +If a file does not exist, +.I zmore +looks for a file of the same name with the addition of a .gz, .z or .Z suffix. +.PP +.I Zmore +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, @@ -131,4 +142,4 @@ except that a header is printed before each file. .DT /etc/termcap Terminal data base .SH "SEE ALSO" -more(1), gzip(1), zcmp(1), znew(1), zforce(1), gzexe(1) +more(1), gzip(1), zdiff(1), zgrep(1), znew(1), zforce(1), gzexe(1) diff --git a/gnu/usr.bin/gzip/znew b/gnu/usr.bin/gzip/znew index fcbc466..01be32c 100644 --- a/gnu/usr.bin/gzip/znew +++ b/gnu/usr.bin/gzip/znew @@ -1,5 +1,6 @@ #!/bin/sh +PATH="/usr/local/bin:$PATH"; export PATH check=0 pipe=0 opt= @@ -25,7 +26,19 @@ if test -z "$cpmod" && ${TOUCH-touch} -r $tmp.1 $tmp.2 2>/dev/null; then cpmodarg="-r" warn="(does not preserve file modes)" fi -rm -f $tmp.[12] + +# check if GZIP env. variable uses -S or --suffix +gzip -q $tmp.1 +ext=`echo $tmp.1* | sed "s|$tmp.1||"` +rm -f $tmp.[12]* +if test -z "$ext"; then + echo znew: error determining gzip extension + exit 1 +fi +if test "$ext" = ".Z"; then + echo znew: cannot use .Z as gzip extension. + exit 1 +fi A= fileno=0 @@ -42,12 +55,12 @@ do done if test $fileno -eq 0; then - echo 'recompress .Z files into .gz (gzip) files' - echo usage: `echo $0 | sed 's,^.*/,,'` "[-tv9P]" file.Z... + echo "recompress .Z files into $ext (gzip) files" + echo usage: `echo $0 | sed 's,^.*/,,'` "[-tv9KP]" file.Z... echo " -t tests the new files before deleting originals" echo " -v be verbose" echo " -9 use the slowest compression method (optimal compression)" - echo " -K keep a .Z file when it is smaller than the .gz file" + echo " -K keep a .Z file when it is smaller than the $ext file" echo " -P use pipes for the conversion $warn" exit 1 fi @@ -76,9 +89,9 @@ for i do fi test $keep -eq 1 && old=`wc -c < "$n.Z"` if test $pipe -eq 1; then - if gzip -d < "$n.Z" | gzip $opt > "$n.gz"; then + if gzip -d < "$n.Z" | gzip $opt > "$n$ext"; then # Copy file attributes from old file to new one, if possible. - test -n "$cpmod" && $cpmod $cpmodarg "$n.Z" "$n.gz" 2> /dev/null + test -n "$cpmod" && $cpmod $cpmodarg "$n.Z" "$n$ext" 2> /dev/null else echo error while recompressing $n.Z res=1; continue @@ -112,25 +125,25 @@ for i do res=1; continue fi fi - test $keep -eq 1 && new=`wc -c < "$n.gz"` + test $keep -eq 1 && new=`wc -c < "$n$ext"` if test $keep -eq 1 -a `expr \( $old + $block - 1 \) / $block` -lt \ `expr \( $new + $block - 1 \) / $block`; then if test $pipe -eq 1; then - rm -f "$n.gz" + rm -f "$n$ext" elif test $check -eq 1; then - mv "$n.$$" "$n.Z" && rm -f "$n.gz" + mv "$n.$$" "$n.Z" && rm -f "$n$ext" else - gzip -d "$n.gz" && compress "$n" && rm -f "$n.gz" + gzip -d "$n$ext" && compress "$n" && rm -f "$n$ext" fi - echo "$n.Z smaller than $n.gz -- unchanged" + echo "$n.Z smaller than $n$ext -- unchanged" elif test $check -eq 1; then - if gzip -t "$n.gz" ; then + if gzip -t "$n$ext" ; then rm -f "$n.$$" "$n.Z" else test $pipe -eq 0 && mv "$n.$$" "$n.Z" - rm -f "$n.gz" - echo error while testing $n.gz, $n.Z unchanged + rm -f "$n$ext" + echo error while testing $n$ext, $n.Z unchanged res=1; continue fi elif test $pipe -eq 1; then diff --git a/gnu/usr.bin/gzip/znew.1 b/gnu/usr.bin/gzip/znew.1 index 644873b..810c51d 100644 --- a/gnu/usr.bin/gzip/znew.1 +++ b/gnu/usr.bin/gzip/znew.1 @@ -8,6 +8,7 @@ znew \- recompress .Z files to .gz files .I Znew recompresses files from .Z (compress) format to .gz (gzip) format. .SH OPTIONS +.TP .B \-f Force recompression from .Z to .gz format even if a .gz file already exists. .TP @@ -26,7 +27,7 @@ Use pipes for the conversion to reduce disk space usage. .B \-K Keep a .Z file when it is smaller than the .gz file .SH "SEE ALSO" -gzip(1), zmore(1), zcmp(1), zforce(1), gzexe(1), compress(1) +gzip(1), zmore(1), zdiff(1), zgrep(1), zforce(1), gzexe(1), compress(1) .SH BUGS .I Znew does not maintain the time stamp with the -P option if |