This commit is contained in:
Nate Williams 1993-06-18 18:39:41 +00:00
parent 30154ac8a8
commit 222b83e890
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/vendor/misc-GNU/dist2/; revision=18
41 changed files with 10430 additions and 0 deletions

339
gnu/usr.bin/gzip/COPYING Normal file
View file

@ -0,0 +1,339 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
675 Mass Ave, Cambridge, MA 02139, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
Appendix: How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19yy name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

450
gnu/usr.bin/gzip/ChangeLog Normal file
View file

@ -0,0 +1,450 @@
Tue Jun 1 09:07:15 1993 Jean-loup Gailly (jloup@chorus.fr)
* version 1.1.1
Fix serious bug in vms.c (== instead of =).
Added --ascii option.
Add workaround in configure.in for Ultrix (quote eval argument)
Do not use unset in znew (not supported on Ultrix)
Use tar.gz instead of tar.z for the distribution of gzip.
Add missing menu item in gzip.texi.
Use size_t instead of unsigned, add AC_SIZE_T in configure.in.
Fri May 28 11:40:01 1993 Jean-loup Gailly (jloup@chorus.fr)
* version 1.1
Use .gz suffix by default, add --suffix option.
Let gunzip accept a "_z" suffix (used by one 'compress' on Vax/VMS).
Quit when reading garbage from stdin instead of reporting an error.
Added sub.c and add.c for compression of 8 bit images.
Added makefile for VAX/MMS and support for wildcards on VMS.
Added support for MSC under OS/2.
Added support for Prime/PRIMOS.
Display compression ratio also when decompressing.
Quit after --version (GNU standard)
Use --force to bypass isatty() check.
Accept --silent as synonym for --quiet (see longopts.table)
Accept --to-stdout as synonym for --stdout (see longopts.table)
Accept -H and -? in addition to -h and --help.
Added comparison of zip and gzip in the readme file.
Return an error code in all main compression/decompression functions.
Continue processing other files in case of recoverable error.
Add description of -f in znew.1.
Do not keep uncompressed version for znew -t if .gz already exists.
On Unix, use only st_ino and st_dev in same_file().
Use S_IRUSR and S_IWUSR if they exist.
"test $1 = -d" -> "test x$1 = x-d" in gzexe.
In match.S, use symbol sysV68 to detect the Motorola Delta.
Do not include memory.h with gcc (conflicting declarations on Sun).
Fix more typos.
On VMS, define unlink as delete also for gcc.
In "make check", unset LANG because "wc -c" fails on Kanji.
Renamed shdir as scriptdir.
Use the 68020 code instead of 68000 code on the NeXT.
Documented --uncompress as synonym for --decompress.
Include the standard header files before gzip.h (needed on Bull).
Do not assume that _POSIX_VERSION implies dirent.h present.
Removed gzip-tar.patch since tar 1.11.2 handles gzip directly.
Use less memory when compiled with -DSMALL_MEM (for MSDOS).
Optimized updcrc().
Don't complain if cc -E does not work correctly.
Do not attempt reading 64K bytes on 16 bit Unix systems.
Do not use the variable name 'overhead' which is reserved on Lynx!
One BULL compiler does not like *p++ in inflate.c => *p, p++.
Use casts on free and memcmp to avoid warnings.
Remove the "off by more than one minute" time stamp kludge, but
document how to avoid saving the time stamp on pipes if desired.
Include crypt.h in inflate.c (one system predefines the CRYPT symbol).
Add links to gunzip and (g)zcat in the default make rule.
Create installation directories if they do not exist.
Clarified --prefix option in INSTALL.
Use symbol mc68k in match.S for the DIAB DS90.
Guard against zero length _match.s in configure.in.
In zmore, restore all tty options using stty -g.
Added support for MacOS
Simplified makecrc.c.
Avoid warnings in getopt.c, util.c, unlzw.c.
Use autoconf 1.4, in particular for INSTALL and AC_HAVE_POUNDBANG
Use .so instead of hard links for zcat.1, gunzip.1 and zcmp.1.
Fixed declration of sig_type.
Make consistency check in fcfree.
Added ztouch.
Do not complain if utime fails on a directory (for OS/2).
Thu Mar 18 18:56:43 1993 Jean-loup Gailly (jloup@chorus.fr)
* version 1.0.7
Allow zmore to read from standard input (like more).
Support the 68000 (Atari ST) in match.S.
Retry partial writes (required on Linux when gzip is suspended in
a pipe).
Allow full pathnames and renamings in gzexe.
Don't let gzexe compress setuid executables or gzip itself.
Added vms/Makefile.gcc for gcc on the Vax.
Give a pointer to Solaris and VMS executables of gzip in README.
Allow installation of binaries and shell scripts in different dirs.
Do not use alloca on the Cray.
Provide strspn and strcspn if string.h does not exist.
Define O_CREAT and O_EXCL from FCREAT and FEXCL if necessary.
Remove gzip.doc in make realclean.
Fixed many typos. (Corrections to my English are welcome.)
Put "make manext=l install" at the correct place in INSTALL.
Fix incorrect examples in INSTALL and give more examples.
Include zdiff.1 for install and uninstall.
Allows complex PAGER variable in zmore (e.g.: PAGER="col -x | more")
Avoid warning on unused indfound in getopt.c.
Cast memset arg to void* (required by some buggy compilers).
Include sys/types.h before dirent.h in acgeneral.m4.
Fix acgeneral.m4 AC_COMPILE_CHECK to avoid warnings.
Don't use alloca.c with gcc. (One NeXT user did not have alloca.h).
Change all error messages according to GNU standards.
Restore time stamp only if off by more than one minute.
Allow installation of zcat as gzcat.
Suppress help message and send compressed data to the terminal when
gzip is invoked without parameters and without redirection.
(Explicit request from Noah Friedman.)
Add compile option GNU_STANDARD to respect the GNU coding standards:
with -DGNU_STANDARD, behave as gzip even if invoked under the
name gunzip. (Complaints to /dev/null or the FSF, not to me!)
Fri Mar 10 13:27:18 1993 Jean-loup Gailly (jloup@chorus.fr)
* version 1.0.6
Let gzexe detect executables that are already gzexe'd.
Don't try restoring record format on VMS (the simple 1.0.5 code
worked correctly only on fixed-512 files). Suppress text_mode.
Added asm version for 68000 in amiga/match.a.
Use asm version for Atari TT.
Fix "make clean" in vms/Makefile.vms.
For OS/2, assume HPFS by default, add flag OS2FAT if necessary.
Fixed some bugs in zdiff and define zcmp as a link to zdiff.
Added zdiff.1
Remove configure hack for NeXT; add general fix to autoconf instead
Do not strip a ".z" extension if this results in an empty name.
Avoid array overflow in get_prefix() for extensions > 10 chars.
Accept either q or e to quit zmore.
In zmore, try restoring tty mode in all cases.
Use Motorola style for match.S on the NeXT.
configure.in: unsetenv *hangs* with the Siemens csh...
Update vms/gzip.hlp.
Thu Mar 4 14:13:34 1993 Jean-loup Gailly (jloup@chorus.fr)
* version 1.0.5
For VMS, restore the file type for variable record format, otherwise
extract in fixed length format (not perfect, but better than
forcing all files to be in stream_LF format).
Use "-z" suffix for VMS.
Use only .z, .*-z, .tgz, .taz as valid gzip extensions; update
zforce accordingly.
Allow a version number in input file names for VMS.
Added sample program zread.c.
Fix "make check" for some implementations of /bin/sh.
Don't rely on stat() for filenames with extension > 3 chars
on MSDOS, OS2 and Atari.
Garbage collect files in /tmp created by gzexe.
Quote $opt in znew.
Use TOUCH env variable in znew if it exists.
Better error message for gunzip on empty or truncated file.
Allow prototypes in getopt.h when __STDC__ defined but 0.
Added "make clean" in vms/Makefile.vms.
Removed -g from default CFLAGS (with Noah's permission!)
Avoid too many HAVE_xxx_H for most systems; use common defaults.
Moved default Atari flags into tailor.h for consistency.
Use memzero() to clear the hash table.
Update vms/gzip.hlp to reflect the VMS behavior.
Fix OS_CODE (to fit in a byte).
Add utime.h for the Amiga.
Add gcc support for the Amiga.
Work around incorrect dirent.h for NeXT 2.0.
Added Makefile entry for Coherent.
Fri Feb 22 11:20:49 1993 Jean-loup Gailly (jloup@chorus.fr)
* version 1.0.4
Added optimized asm version for 68020.
Add support for DJGPP.
Add support for the Atari ST.
Added zforce to rename gzip'ed files with truncated names.
Do not install with name uncompress (some systems rely on the
absence of any check in the old uncompress).
Added missing function (fcfree) in msdos/tailor.c
Let gunzip handle .tgz files, and let gzip skip them.
Added 'stty min 1' in zmore for SysV and fixed trap code.
Suppress .PHONY in Makefile.in, which breaks old makes.
Added documentation about pcat and unpack in INSTALL.
Add cast to getenv for systems without stdlib.h.
Use VAXC instead of VMS to avoid confusion for gcc.
Add -K to znew.1.
Add gzexe.1.
Try preserving file permissions in gzexe.
Added -d option for gzexe.
Guard against spaces in file names in gzexe.
Use CMP env. variable in zcmp.
Return a warning exit status for gzip of file with .z suffix.
Suppress usage of d_ino which is not portable to all systems.
Use #ifdef instead of #if for consistency.
For VMS, use "cc util.c" instead of "cc util" (pb with logical names)
Added utime() for Amiga.
Renamed gzcat.1 as zcat.1.
Include fcntl.h for Amiga (for read and write).
For VMS, add definition of symbols and links in the makefiles.
Give a VMS look to vms/gzip.hlp.
Save the original name only when necessary.
Add a mode parameter for open in read mode (required by VMS).
For VMS, remove the version suffix from the original name.
Accept both / and \ as path separator for MSDOS.
Let gunzip extract stored .zip files correctly.
Added warning about VFC format in vms/gzip.hlp.
In znew, skip a bad file but process the others.
Cleanup tailor.h.
Use GZIP_OPT for VMS to avoid conflict with program name.
Added description of GZIP variable in gzip.texi.
Thu Feb 11 17:21:32 1993 Jean-loup Gailly (jloup@chorus.fr)
* version 1.0.3
Add -K option for znew to keep old .Z files if smaller.
Add -q option (quiet) to cancel -v in GZIP env variable.
For Turbo C, normalize pointers before freeing them.
Add more safety checks in add_envopt().
Add do_exit() for uniform exit path (always free memory).
Reduce MAX_PATH_LEN for MSDOS.
Include sys/types.h before signal.h
Avoid strdup, the NeXT does not have it.
Made gzexe safer on systems with filename limitation to 14 chars.
Fri Feb 10 09:45:49 1993 Jean-loup Gailly (jloup@chorus.fr)
* version 1.0.2
Added env variable GZIP for default options.
Added support for the Amiga.
znew now keeps the old .Z if it is smaller than the .z file.
Added gzexe to compress rarely used executables.
Reduce memory usage when using static allocation (no DYN_ALLOC).
Better separation of warning and error return codes.
Fix unlzw.c to make DYN_ALLOC and MAXSEG_64K independent options.
Allow INBUFSIZ to be >= 32K in unlzw (don't use sign of rsize)
Generate tar file in old format to avoid problems with old systems.
Preserve time stamp in znew -P if touch -r works.
Use ${PAGER-more} instead of ${PAGER:-more} in zmore.
Do not use unsigned instead of mode_t.
Better error message for trailing garbage in .z file; ignore this
garbage on VMS.
In zmore, use icanon instead of -cbreak on SYSV.
Add trap handler in zmore.
Use char* instead of void* for non STDC compilers.
Added makefile entry for Xenix on 286.
Return an error code when existing file was not overwritten.
Use prototype of lzw.h for lzw.c.
Fix znew with -P option alone.
Give warning for directories even without -v.
Close output file before unlink() in case of error.
Suppress all target dependent ifdef from the portable files.
Free all dynamically allocated variables upon exit.
Thu Feb 4 18:23:56 1993 Jean-loup Gailly (jloup@chorus.fr)
* version 1.0.1
Fixed some trivial errors in msdos/Makefile.bor
Thu Feb 4 10:00:59 1993 Jean-loup Gailly (jloup@chorus.fr)
* version 1.0
gzip now runs on Vax/VMS (Amiga support will come in next version).
Do not overwrite files without -f when using /bin/sh.
Support the test option -t for compressed (.Z) files.
Flush output for bad compressed files. Add warning in README.
Added makefiles for MSDOS.
Don't rely on presence of csh in configure
Added gunzip.1 and gzcat.1.
Updated znew.1.
Check reserved flags in unlzw().
Return dummy value in main to avoid lint warning.
Define OF in lzw.h for lint.
Allow both "znew -v -t" and "znew -vt".
Don't overwrite the output file name for multiple parts.
Echo just a warning if configure is out of date.
Use ; instead of , in trees.c (confuses the SAS Amiga compiler).
In INSTALL, document "DEFS='-DM_XENIX' ./configure".
Use OTHER_PATH_SEP for more portability (DOS, OS2, VMS, AMIGA).
Make all directories world writable for broken versions of tar.
Use gzip -cd instead of zcat in zmore, zcmp, zdiff.
Don't use GNU tar for distributions, some systems can't untar.
Do not exit() for gzip --version.
Mon Jan 26 10:26:42 1993 Jean-loup Gailly (jloup@chorus.fr)
* Beta version 0.8.2
Avoid 'far' declarations for MSDOS.
Use test -f instead of test -x in configure.in (for Ultrix)
Add empty else part to if in Makefile.in for broken shells.
Use NO_UNDERLINE instead of UNDERLINE (pb with Linux cpp)
Accept continuation files with -ff (for damage recovery)
Small patch to Makefile.os2
Use memzero instead of bzero to avoid potential conflicts
Document restriction on extraction of zip files.
Fix quoting in ACL_HAVE_SHELL_HACK.
Do not check file size on MSDOS because of bug in DIET.
Allow zcat on a file with multiple links.
Add fix in inflate.c for compatibility with pkzip 2.04c.
Release gzip in tar.z and tar format. (No tar.Z).
Fri Jan 22 10:04:13 1993 Jean-loup Gailly (jloup@chorus.fr)
* Beta version 0.8.1
Fixed Makefile.os2
Fixed #if directives that TurboC does not like.
Don't rely on uncompress in znew, use gzip -d.
Add the pipe option -P in znew.
Add some more ideas in TODO.
Support both NDIR and SYSNDIR.
Sat Jan 21 15:46:38 1993 Jean-loup Gailly (jloup@chorus.fr)
* Beta version 0.8
Support unpack.
Check for _match.o in configure.in in addition to return status.
Include <sys/types.h> in zip.c
Define local variables and functions as local.
Accept more alternative names for the program (pcat, gzcat, ...).
Accept .exe as well as .EXE.
Uncompress files with multiple links only with -f.
Better error message for gunzip of non-existent file.z.
Fix the entry for /etc/magic in INSTALL.
Use AC_HAVE_HEADERS uniformly instead of special macros.
Install the man pages as .1 by default instead of .l.
Document crypt++.el in README.
Fix for unlzw() on 16-bit machines (bitmask must be unsigned).
Complain if input and output files are identical.
Create a correct output name for files of exactly 13 chars.
Do not overwrite CPP if set
Check for i386 before trying to assemble match.s
Check for underline in external name before assembling
Add patch for tar 1.11.1.
Mon Jan 5 10:16:24 1993 Jean-loup Gailly (jloup@chorus.fr)
* Beta version 0.7
Use "make check" instead of "make test".
Do not rely on dirname in znew.
Keep time stamp and pass options to gzip in znew.
Rename .l files back to .1 to avoid conflict with lex
Do not create .z.z files with gzip -r.
Use nice_match in match.asm
Unroll loops in deflate.c
Do not attempt matches beyond the window end
Allow again gunzip .zip files (was working in 0.5)
Allow again compilation with TurboC 2.0 (was working in 0.4)
Tue Dec 30 20:00:19 1992 Jean-loup Gailly (jloup@chorus.fr)
* Beta version 0.6
The .z extension is used by pack, not compact (README, gzip.1)
Accept gzcat in addition to zcat.
Use PAGER in zmore if defined.
Man pages for /usr/local/man/manl should have extension .l.
Don't redefine bzero on the NeXT
Allow incomplete Huffman table if there is only one code.
Don't lookahead more than 7 bits (caused premature EOF).
Added "make test" to check for compiler bugs.
Don't rely on `i386`; try to assemble directly
Change magic header to avoid conflict with freeze 1.x.
Added entry for /etc/magic in INSTALL.
Do not destroy an input .zip file with more than one member.
Display "untested" instead of "OK" for gzip -t foo.Z
With -t, skip stdin in .Z format
Allow multiple compressed members in an input file.
Ignore a zero time stamp.
Made znew safer.
Tue Dec 29 10:00:19 1992 Noah Friedman (friedman@gnu.ai.mit.edu)
Added test for #!/bin/sh in configure.in.
Fix some references to $srcdir in Makefile.in
Mon Dec 21 17:33:35 1992 Jean-Loup Gailly (jloup@chorus.fr)
* Beta version 0.5
Put RCS ids in all files.
Added znew to recompress old .Z files with gzip.
Avoid "already .z suffix" messages for -r and no -v.
Put back check for d_ino in treat_dir().
Use HAVE_STRING_H instead of USG.
Added os2/Makefile.os2
Use SYSUTIME on OS/2.
Info dir is $(prefix)/info, not $(prefix)/lib/info.
Support long options, added getopt and alloca
Support -V and -t
Reorder configure.in according to suggestions in autoconf.info
Allow links when not removing original file
Allow either .z or .Z in zdiff
Wed Nov 25 11:40:04 1992 Jean-loup Gailly (jloup@chorus.fr)
* Beta version 0.4.1
Save only the original base name, don't include any directory prefix.
Don't use HAVE_LONG_FILE_NAMES (support multiple file system types).
Fix declaration of abort_gzip in gzip.h.
Include unistd.h when it exists to avoid warnings with gcc -Wall.
Mon Nov 23 12:39:01 1992 Jean-loup Gailly (jloup@chorus.fr)
* Beta version 0.4
Lots of cleanup
Use autoconf generated 'configure'
Fixed the NO_MULTIPLE_DOTS code
Fixed the save_orig_name code
Support for MSDOS (Turbo C)
Thu Nov 19 15:18:22 1992 Jean-loup Gailly (jloup@chorus.fr)
* Beta version 0.3
Added auto configuration. Just type "make" now.
Don't overwrite compress by default in "make install". Use
"make install_compress" to overwrite.
Add match.s for 386 boxes.
Added documentation in texinfo format.
Provide help for "gunzip" invoked without redirected input.
Save original file name when necessary.
Support OS/2 (Kai-Uwe Rommel).
Tue Nov 17 14:32:53 1992 Jean-loup Gailly (jloup@chorus.fr)
* Alpha version 0.2.4
Return 0 in get_istat() when ok (caused error with zcat).
Don't update crc on compressed data (caused crc errors on
large files).
Fri Nov 13 15:04:12 1992 Jean-loup Gailly (jloup@chorus.fr)
* Alpha version 0.2.3
Initialize rsize in unlzw.c
Initialize ofd for zcat.
Do not use volatile ifname as argument of treat_dir.
Add -1 to -9 in gzip.1.
Sat Oct 31 18:30:00 1992 Jean-loup Gailly (jloup@chorus.fr)
* Alpha version 0.2.2.
Fix error messages.
Accept gunzip on zip files.
Sat Oct 31 17:15:00 1992 Jean-loup Gailly (jloup@chorus.fr)
* Alpha version 0.2.1
Use ctype.h in util.c (problem on SysV).
Create BINDIR if it does not exist.
Use cc by default.
Added zcmp, zmore, zdiff.
Fixed the man page gzip.1.
Sat Oct 31 17:00:00 1992 Jean-loup Gailly (jloup@chorus.fr)
* Alpha version 0.2
Fixed compilation problems with gcc
Sat Oct 31 12:46:00 1992 Jean-loup Gailly (jloup@chorus.fr)
* Alpha version 0.1 released (under time pressure), so it's not
much tested, sorry.

25
gnu/usr.bin/gzip/Makefile Normal file
View file

@ -0,0 +1,25 @@
# @(#)Makefile 5.3 (Berkeley) 5/12/90
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
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
LINKS+= ${DESTDIR}${BINDIR}/gzip ${DESTDIR}${BINDIR}/gunzip
LINKS+= ${DESTDIR}${BINDIR}/gzip ${DESTDIR}${BINDIR}/gzcat
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 \
${DESTDIR}${BINDIR}
match.o: ${.CURDIR}/match.S
$(CPP) ${.CURDIR}/match.S >_match.s
$(CC) -c _match.s
mv _match.o match.o
rm -f _match.s
.include <bsd.prog.mk>

158
gnu/usr.bin/gzip/NEWS Normal file
View file

@ -0,0 +1,158 @@
Current Version: 1.1.1
See the file ChangeLog for the details of all changes.
Major changes from 1.1 to 1.1.1.
* Fix serious bug in vms.c (affects Vax/VMS only).
* Added --ascii option.
* Add workaround in configure.in for Ultrix (quote eval argument)
Major changes from 1.0.7 to 1.1.
* Use .gz suffix by default, add --suffix option.
* Let gunzip accept a "_z" suffix (used by one 'compress' on Vax/VMS).
* Quit when reading garbage from stdin instead of reporting an error.
* Added makefile for VAX/MMS and support for wildcards on VMS.
* Added support for MSC under OS/2.
* Added support for Prime/PRIMOS.
* Display compression ratio also when decompressing (with --verbose).
* Quit after --version (GNU standard)
* Use --force to bypass isatty() check
* Continue processing other files in case of recoverable error.
* Added comparison of zip and gzip in the readme file.
* Added small sample programs (ztouch, sub, add)
* Use less memory when compiled with -DSMALL_MEM (for MSDOS).
* Remove the "off by more than one minute" time stamp kludge
Major changes from 1.0.6 to 1.0.7.
* Allow zmore to read from standard input (like more).
* Support the 68000 (Atari ST) in match.S.
* Retry partial writes (required on Linux when gzip is suspended in a pipe).
* Allow full pathnames and renamings in gzexe.
* Don't let gzexe compress setuid executables or gzip itself.
* Added vms/Makefile.gcc for gcc on the Vax.
* Allow installation of binaries and shell scripts in different dirs.
* Allows complex PAGER variable in zmore (e.g.: PAGER="col -x | more")
* Allow installation of zcat as gzcat.
* Several small changes for portability to old or weird systems.
* Suppress help message and send compressed data to the terminal when
gzip is invoked without parameters and without redirection.
* Add compile option GNU_STANDARD to respect the GNU coding standards:
with -DGNU_STANDARD, behave as gzip even if invoked under the name gunzip.
(I don't like the last two changes, which were requested by the FSF.)
Major changes from 1.0.5 to 1.0.6.
* Let gzexe detect executables that are already gzexe'd.
* Keep file attributes in znew and gzexe if cpmod is available.
* Don't try restoring record format on VMS (1.0.5 did not work correctly)
* Added asm version for 68000 in amiga/match.a.
Use asm version for Atari TT and NeXT.
* For OS/2, assume HPFS by default, add flag OS2FAT if necessary.
* Fixed some bugs in zdiff and define zcmp as a link to zdiff.
Major changes from 1.0.4 to 1.0.5.
* For VMS, restore the file type for variable record format, otherwise
extract in fixed length format (not perfect, but better than
forcing all files to be in stream_LF format).
* For VMS, use "-z" default suffix and accept a version number in file names.
* For Unix, allow compression of files with name ending in 'z'. Use only
.z, .*-z, .tgz, .taz as valid gzip extensions. In the last two cases,
extract to .tar by default.
* On some versions of MSDOS, files with a 3 character extension could not
be compressed.
* Garbage collect files in /tmp created by gzexe.
* Fix the 'OS code' byte in the gzip header.
* For the Amiga, add the missing utime.h and add support for gcc.
Major changes from 1.0.3 to 1.0.4.
* Added optimized asm version for 68020.
* Add support for DJGPP.
* Add support for the Atari ST.
* Added zforce to rename gzip'ed files with truncated names.
* Do not install with name uncompress (some systems rely on the
absence of any check in the old uncompress).
* Added missing function (fcfree) in msdos/tailor.c
* Let gunzip handle .tgz files, and let gzip skip them.
* Added -d option (decompress) for gzexe and try preserving file permissions.
* Suppress all warnings with -q.
* Use GZIP_OPT for VMS to avoid conflict with program name.
* ... and many other small changes (see ChangeLog)
Major changes from 1.0.2 to 1.0.3
* Added -K option for znew to keep old .Z files if smaller
* Added -q option (quiet) to cancel -v in GZIP env variable.
* Made gzexe safer on systems with filename limitation to 14 chars.
* Fixed bugs in handling of GZIP env variable and incorrect free with Turbo C.
Major changes from 1.0.1 to 1.0.2
* Added env variable GZIP for default options. Example:
for sh: GZIP="-8 -v"; export GZIP
for csh: setenv GZIP "-8 -v"
* Added support for the Amiga.
* znew now keeps the old .Z if it is smaller than the .z file.
This can happen for some large and very redundant files.
* Do not complain about trailing garbage for record oriented IO (Vax/VMS).
This implies however that multi-part gzip files are not supported
on such systems.
* Added gzexe to compress rarely used executables.
* Reduce memory usage (required for MSDOS and useful on all systems).
* Preserve time stamp in znew -P (pipe option) if touch -r works.
Major changes from 1.0 to 1.0.1
* fix trivial errors in the Borland makefile (msdos/Makefile.bor)
Major changes from 0.8.2 to 1.0
* gzip now runs on Vax/VMS
* gzip will not not overwrite files without -f when using /bin/sh in
background.
* Support the test option -t for compressed (.Z) files.
Allow some data recovery for bad .Z files.
* Added makefiles for MSDOS (Only tested for MSC, not Borland).
* still more changes to configure for several systems
Major changes from 0.8.1 to 0.8.2:
* yet more changes to configure for Linux and other systems
* Allow zcat on a file with multiple links.
Major changes from 0.8 to 0.8.1:
* znew has now a pipe option -P to reduce the disk space requirements,
but this option does not preserve timestamps.
* Fixed some #if directives for compilation with TurboC.
Major changes from 0.7 to 0.8:
* gzip can now extract .z files created by 'pack'.
* configure should no longer believe that every machine is a 386
* Fix the entry for /etc/magic in INSTALL.
* Add patch for GNU tar 1.11.1 and a pointer to crypt++.el
* Uncompress files with multiple links only with -f.
* Fix for uncompress of .Z files on 16-bit machines
* Create a correct output name for file names of exactly N-1 chars when
the system has a limit of N chars.
Major changes from 0.6 to 0.7:
* Use "make check" instead of "make test".
* Keep time stamp and pass options to gzip in znew.
* Do not create .z.z files with gzip -r.
* Allow again gunzip .zip files (was working in 0.5)
* Allow again compilation with TurboC 2.0 (was working in 0.4)
Major changes form 0.5 to 0.6:
* gunzip reported an error when extracting certain .z files. The .z files
produced by gzip 0.5 are correct and can be read by gunzip 0.6.
* gunzip now supports multiple compressed members within a single .z file.
* Fix the check for i386 in configure.
* Added "make test" to check for compiler bugs. (gcc -finline-functions
is broken at least on the NeXT.)
* Use environment variable PAGER in zmore if it is defined.
* Accept gzcat in addition to zcat for people having /usr/bin before
/usr/local/bin in their path.

147
gnu/usr.bin/gzip/README Normal file
View file

@ -0,0 +1,147 @@
This is the file README for the gzip distribution, version 1.1.1.
gzip (GNU zip) is a compression utility designed to be a replacement
for 'compress'. Its main advantages over compress are much better
compression and freedom from patented algorithms. The GNU Project
uses it as the standard compression program for its system.
gzip currently uses by default the LZ77 algorithm used in zip 1.9 (the
portable pkzip compatible archiver). The gzip format was however
designed to accommodate several compression algorithms. See below
for a comparison of zip and gzip.
gunzip can currently decompress files created by gzip, compress or
pack. The detection of the input format is automatic. For the
gzip format, gunzip checks a 32 bit CRC. For pack, gunzip checks the
uncompressed length. The 'compress' format was not designed to allow
consistency checks. However gunzip is sometimes able to detect a bad
.Z file because there is some redundancy in the .Z compression format.
If you get an error when uncompressing a .Z file, do not assume that
the .Z file is correct simply because the standard uncompress does not
complain. This generally means that the standard uncompress does not
check its input, and happily generates garbage output.
gzip produces files with a .gz extension. Previous versions of gzip
used the .z extension, which was already used by the 'pack'
Huffman encoder. gunzip is able to decompress .z files (packed
or gzip'ed).
Several planned features are not yet supported (see the file TODO).
See the file NEWS for a summary of changes since 0.5. See the file
INSTALL for installation instructions. Some answers to frequently
asked questions are given in the file INSTALL, please read it. (In
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
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.
- on Sparc with SunOS 4.1.1 and the SC1.0 compiler, the optimizer
works up to -O3 but -O4 does not work.
- MSC 5.1 with -Ox and -DDYN_ALLOC generates bad code in inflate.c.
The default is static allocation (no DYN_ALLOC) and -Ox works on inflate.c.
But -Ox does not work on util.c, so you must use -Oait -Gs.
- On dnix 5.3 2.2 cc version 2.37c is buggy. Version 2.38d works.
For all machines, Use "make check" to check that gzip was compiled correctly.
Please send all comments and bug reports by electronic mail to:
Jean-loup Gailly <jloup@chorus.fr>
or, if this fails, to bug-gnu-utils@prep.ai.mit.edu.
Bug reports should ideally include:
* The complete output of "gzip -V" (or the contents of revision.h
if you can't get gzip to compile)
* The hardware and operating system (try "uname -a")
* The compiler used to compile (if it is gcc, use "gcc -v")
* A description of the bug behavior
* The input to gzip, that triggered the bug
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
anonymous ftp to roebling.poly.edu [128.238.5.31] in /pub/crypt++.el.
The same directory contains also patches to dired, ange-ftp and info.
GNU tar 1.11.2 has a -z option to invoke directly gzip, so you don't have
to patch it.
The znew and gzexe shell scripts provided with gzip benefit from
(but do not require) the cpmod utility to transfer file attributes.
It is available by anonymous ftp on gatekeeper.dec.com in
/.0/usenet/comp.sources.unix/volume11/cpmod.Z.
The sample programs zread.c, sub.c and add.c are provided as examples
of useful complements to gzip. Read the comments inside each source file.
The perl script ztouch is also provided as example (not installed
by default since it relies on perl).
gzip is free software, you can redistribute it and/or modify it under
the terms of the GNU General Public License, a copy of which is
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)
- 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.
A VMS executable is available in ftp.spc.edu:[.macro32.savesets]gzip-1-*.zip
(use [.macro32]unzip.exe to extract).
Many thanks to those who provided me with bug reports and feedback.
See the files THANKS and ChangeLog for more details.
Note about zip vs. gzip:
The name 'gzip' was a very unfortunate choice, because zip and gzip
are two really different programs, although the actual compression and
decompression sources were written by the same persons. A different
name should have been used for gzip, but it is too late to change now.
zip is an archiver: it compresses several files into a single archive
file. gzip is a simple compressor: each file is compressed separately.
Both share the same compression and decompression code for the
'deflate' method. unzip can also decompress old zip archives
(implode, shrink and reduce methods). gunzip can also decompress files
created by compress and pack. zip 1.9 and gzip do not support
compression methods other than deflation. (zip 1.0 supports shrink and
implode). Better compression methods may be added in future versions
of gzip. zip will always stick to absolute compatibility with pkzip,
it is thus constrained by PKWare, which is a commercial company. The
gzip header format is deliberately different from that of pkzip to
avoid such a constraint.
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
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
point cannot be recovered. (Future versions of gzip will have
error recovery features.)
gzip and gunzip are distributed as a single program. zip and unzip
are, for historical reasons, two separate programs, although the
authors of these two programs work closely together in the info-zip
team. zip and unzip are not associated with the GNU project.
The sources are available by ftp in
oak.oakland.edu:/pub/misc/unix/zip19p1.zip
oak.oakland.edu:/pub/misc/unix/unz50p1.tar-z

196
gnu/usr.bin/gzip/THANKS Normal file
View file

@ -0,0 +1,196 @@
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:
Mark Adler madler@cco.caltech.edu
Edwin Allum edwin@csri.toronto.edu
Joseph Arceneaux jla@gnu.ai.mit.edu
Tim Auckland tda10@cus.cam.ac.uk
Ken-ichiro Aoki aoki@madonna.physics.ucla.edu
David Ascher da@marlowe.cog.brown.edu
Eric Backus ericb@lsid.hp.com
Becky A. Badgett badgett@cs.utexas.edu
Dave Barber dbarber@apocalypse.bbn.com
Rene Beaulieu reneb@distri.hydro.qc.ca
Neal Becker neal@ctd.comsat.com
Dieter Becker becker@med-in.uni-sb.de
Nelson H. F. Beebe beebe@geronimo.math.utah.edu
Jeff Beadles jeff@onion.rain.com
David J. N. Begley dbegley@st.nepean.uws.edu.au
Jim Bernard jbernard@iola.mines.colorado.edu
Karl Berry karl@cs.umb.edu
James W. Birdsall jwbirdsa@picarefy.picarefy.com
Wayne E. Bouchard web@paladine.hacks.arizona.edu
Marc Boucher marc@cam.org
Ola Brahammar pt90ob@pt.hk-r.se
Dave Brennan brennan@hal.com
Alan Brown dogbowl@dogbox.acme.gen.nz
Rodney Brown rdb@mel.cocam.oz.au
Bruce bde@runx.oz.au
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
Paul Close pdc@lunch.wpd.sgi.com
Kevin Cosgrove kevinc@tekig6.pen.tek.com
Stephen J Cowley s.j.cowley@amtp.cam.ac.uk
Frank Crawford frank@photon.ansto.gov.au
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
Jeff Deifik jdeifik@isi.edu
Vince DeMarco vince@whatnxt.cuc.ab.ca
Michael De La Rue p91152@cplab.physics.edinburgh.ac.uk
Lawrence R. Dodd dodd@roebling.poly.edu
Matthew Donadio donadio@mxd120.rh.psu.edu
Andy Dougherty andy@crystal.phys.lafayette.edu
John Eaton jwe@che.utexas.edu
Brian Edmonds edmonds@edmonds.home.cs.ubc.ca
Paul Eggert eggert@twinsun.com
Enami enami@sys.ptg.sony.co.jp
Kristoffer Eriksson ske@pkmab.se
Daniel Eriksson m91der@bellatrix.tdb.uu.se
Rik Faith faith@cs.unc.edu
Larry Fahnoe fahnoe@c1mpls.mn.org
Cristian Ferretti cfs@poincare.mat.puc.cl
Karl-Jose Filler pla_jfi@pki-nbg.philips.de
Per Foreby perf@efd.lth.se
Alexander Fraser alex@cs.umb.edu
Noah Friedman friedman@gnu.ai.mit.edu
Bob Friesenhahn bfriesen@iphase.com
Andy Fyfe andy@scp.caltech.edu
Geoff geoff@frs.faxon.com
Kaveh R. Ghazi ghazi@staccato.rutgers.edu
Torbjorn Granlund tege@sics.se
Carl Greco cgreco@parrot.creighton.edu
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
Ruediger Helsch ruediger@ramz.ing.tu-bs.de
Mark C. Henderson mch@sqwest.wimsey.bc.ca
Karl Heuer karl@kelp.boston.ma.us
Thomas Hiller hiller@fzi.de
Eiji Hirai hirai@cc.swarthmore.edu
Kjetil Torgrim Homme kjetilho@ifi.uio.no
Preston Hunt gt5708a@prism.gatech.edu
Shane C Hutchins sch@nymph.msel.unh.edu
Hutch hutchinson@wrair-emh1.army.mil
Lester Ingber ingber@alumni.caltech.edu
Ken Ishii ishii@sni-usa.com
Per Steinar Iversen iversen@vsfys1.fi.uib.no
Michal Jaegermann ntomczak@vm.ucs.ualberta.ca
Brian Jones brianj@skat.usc.edu
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
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
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
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
Hugues Leroy hugues.leroy@irisa.fr
Charles Levert charles@aramis.comm.polymtl.ca
Torbj|rn Lindh toobii@elixir.e.kth.se
David R. Linn drl@vuse.vanderbilt.edu
Antonio Lioy cat@athena.polito.it
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
Steeve McCauley steeve@pooh.geophys.mcgill.ca
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
Luke Mewburn zak@rmit.edu.au
Jim Meyering meyering@cs.utexas.edu
Frederic Miserey miserey@laguna.ics.uci.edu
Marcel J.E. Mol marcel@duteca.et.tudelft.nl
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
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
Hal Peterson hrp@pecan.cray.com
Pascal Petit petit@cadillac.ibp.fr
Bruno Pillard bp@chorus.fr
Franc,ois Pinard pinard@iro.umontreal.ca
Jay Pinkos pinkos@butyng.bu.edu
Thomas Plass thomas@cogsci.ed.ac.uk
Mike Polo mikep@cfsmo.honeywell.com
Francesco Potorti pot@fly.cnuce.cnr.it
David Purves purves@apogee.com
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
Roland B Roberts roberts@nsrl31.nsrl.rochester.edu
Kevin Rodgers kevin@rolling-stone.den.mmc.com
Kai Uwe Rommel rommel@informatik.tu-muenchen.de
Paul Rubin phr@america.telebit.com
Wolfgang Rupprecht wolfgang@wsrcc.com
Jonathan Ryshpan jon@amito.hitachi.com
Paul A Sand pas@unh.edu
Tony Sanders sanders@bsdi.com
Mike Sangrey mike@sojurn.lns.pa.us
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
Rick Sladkey jrs@world.std.com
Daniel L Smith dls@autodesk.com
Fred Smith fredex%fcshome@merk.merk.com
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
Ed Sznyter ews@babel.babel.com
Hideaki Tanabe arctanx@iyeyasu.ynl.t.u-tokyo.ac.jp
Andrew Telford ajt@peregrin.resmel.bhp.com.au
Glenn E. Thobe thobe@getunx.info.com
Kei Thomsen kt@keihh.hanse.de
Karsten Thygesen karthy@dannug.dk
Mark Towfiq towfiq@microdyne.com
Jeff Treece treece@sabbagh.com
Oliver Trepte oliver@ikaros.fysik4.kth.se
Stephane Tsacas slt@is21.isoft.fr
Stephen Tweedie sct@dcs.ed.ac.uk
Sotiris Vassilopoulos vassilopoulos@virginia.edu
Pedro A. M. Vazquez vazquez@iqm.unicamp.br
Arjan de Vet devet@win.tue.nl
Vadim V. Vlasov vvlasov@inucres.msk.su
Eduard Vopicka eduard.vopicka@vse.cs
Theo Vosse vosse@ruls41.leidenuniv.nl
Marcel Waldvogel marcel@nice.usergroup.ethz.ch
Stephen J. Walick steve@nshore.org
Gray Watson gray@antaire.com
Scott Weikart scott@igc.apc.org
Ivo Welch iwelch@agsm.ucla.edu
Gijsb. Wiesenekker wiesenecker@sara.nl
Wietze van Winden wietze@swi.psy.uva.nl
Larry W. Virden lwv26@cas.org
Bill Wohler wohler@sap-ag.de
Jamie Zawinski jwz@lucid.com
Christos Zoulas christos@deshaw.com

58
gnu/usr.bin/gzip/TODO Normal file
View file

@ -0,0 +1,58 @@
TODO file for gzip.
Some of the planned features include:
- Structure the sources so that the compression and decompression code
form a library usable by any program, and write both gzip and zip on
top of this library. This would ideally be a reentrant (thread safe)
library, but this would degrade performance. In the meantime, you can
look at the sample program zread.c.
- Make it convenient to define alternative user interfaces (in
particular for windowing environments).
- Support in-memory compression for arbitrarily large amounts of data
(zip currently supports in-memory compression only for a single buffer.)
- Map files in memory when possible, this is generally much faster
than read/write. (zip currently maps entire files at once, this
should be done in chunks to reduce memory usage.)
- Add a super-fast compression method, suitable for implementing
file systems with transparent compression. One problem is that the
best candidate (lzrw1) is patented twice (Waterworth 4,701,745
and Gibson & Graybill 5,049,881). The lzrw series of algorithms
are available by ftp in ftp.adelaide.edu.au:/pub/compression/lzrw*.
- Add a super-tight (but slow) compression method, suitable for long
term archives. One problem is that the best versions of arithmetic
coding are patented (4,286,256 4,295,125 4,463,342 4,467,317
4,633,490 4,652,856 4,891,643 4,905,297 4,935,882 4,973,961
5,023,611 5,025,258).
Note: I will introduce new compression methods only if they are
significantly better in either speed or compression ratio than the
existing method(s). So the total number of different methods should
reasonably not exceed 3. (The current 9 compression levels are just
tuning parameters for a single method, deflation.)
- Add optional error correction. One problem is that the current version
of ecc cannot recover from inserted or missing bytes. It would be
nice to recover from the most common error (transfer of a binary
file in ascii mode).
- Add a block size (-b) option to improve error recovery in case of
failure of a complete sector. Each block could be extracted
independently, but this reduces the compression ratio.
- 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
- support .Z files in SCO 'compress -H' format.
Send comments to Jean-loup Gailly <jloup@chorus.fr>.

View file

@ -0,0 +1,141 @@
1. Algorithm
The deflation algorithm used by zip and gzip is a variation of LZ77
(Lempel-Ziv 1977, see reference below). It finds duplicated strings in
the input data. The second occurrence of a string is replaced by a
pointer to the previous string, in the form of a pair (distance,
length). Distances are limited to 32K bytes, and lengths are limited
to 258 bytes. When a string does not occur anywhere in the previous
32K bytes, it is emitted as a sequence of literal bytes. (In this
description, 'string' must be taken as an arbitrary sequence of bytes,
and is not restricted to printable characters.)
Literals or match lengths are compressed with one Huffman tree, and
match distances are compressed with another tree. The trees are stored
in a compact form at the start of each block. The blocks can have any
size (except that the compressed data for one block must fit in
available memory). A block is terminated when zip determines that it
would be useful to start another block with fresh trees. (This is
somewhat similar to compress.)
Duplicated strings are found using a hash table. All input strings of
length 3 are inserted in the hash table. A hash index is computed for
the next 3 bytes. If the hash chain for this index is not empty, all
strings in the chain are compared with the current input string, and
the longest match is selected.
The hash chains are searched starting with the most recent strings, to
favor small distances and thus take advantage of the Huffman encoding.
The hash chains are singly linked. There are no deletions from the
hash chains, the algorithm simply discards matches that are too old.
To avoid a worst-case situation, very long hash chains are arbitrarily
truncated at a certain length, determined by a runtime option (zip -1
to -9). So zip does not always find the longest possible match but
generally finds a match which is long enough.
zip also defers the selection of matches with a lazy evaluation
mechanism. After a match of length N has been found, zip searches for a
longer match at the next input byte. If a longer match is found, the
previous match is truncated to a length of one (thus producing a single
literal byte) and the longer match is emitted afterwards. Otherwise,
the original match is kept, and the next match search is attempted only
N steps later.
The lazy match evaluation is also subject to a runtime parameter. If
the current match is long enough, zip reduces the search for a longer
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.
2. gzip file format
The pkzip format imposes a lot of overhead in various headers, which
are useful for an archiver but not necessary when only one file is
compressed. gzip uses a much simpler structure. Numbers are in little
endian format, and bit 0 is the least significant bit.
A gzip file is a sequence of compressed members. Each member has the
following structure:
2 bytes magic header 0x1f, 0x8b (\037 \213)
1 byte compression method (0..7 reserved, 8 = deflate)
1 byte flags
bit 0 set: file probably ascii text
bit 1 set: continuation of multi-part gzip file
bit 2 set: extra field present
bit 3 set: original file name present
bit 4 set: file comment present
bit 5 set: file is encrypted
bit 6,7: reserved
4 bytes file modification time in Unix format
1 byte extra flags (depend on compression method)
1 byte operating system on which compression took place
2 bytes optional part number (second part=1)
2 bytes optional extra field length
? bytes optional extra field
? bytes optional original file name, zero terminated
? bytes optional file comment, zero terminated
12 bytes optional encryption header
? bytes compressed data
4 bytes crc32
4 bytes uncompressed input size modulo 2^32
The format was designed to allow single pass compression without any
backwards seek, and without a priori knowledge of the uncompressed
input size or the available size on the output media. If input does
not come from a regular disk file, the file modification time is set
to the time at which compression started.
The time stamp is useful mainly when one gzip file is transferred over
a network. In this case it would not help to keep ownership
attributes. In the local case, the ownership attributes are preserved
by gzip when compressing/decompressing the file. A time stamp of zero
is ignored.
Bit 0 in the flags is only an optional indication, which can be set by
a small lookahead in the input data. In case of doubt, the flag is
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.
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
diskettes), each part starts with a header as described above, but
only the last part has the crc32 and uncompressed size. A decompressor
may prompt for additional data for multipart compressed files. It is
desirable but not mandatory that multiple parts be extractable
independently so that partial data can be recovered if one of the
parts is damaged. This is possible only if no compression state is
kept from one part to the other. The compression-type dependent flags
can indicate this.
If the file being compressed is on a file system with case insensitive
names, the original name field must be forced to lower case. There is
no original file name if the data was compressed from standard input.
Compression is always performed, even if the compressed file is
slightly larger than the original. The worst case expansion is
a few bytes for the gzip file header, plus 5 bytes every 32K block,
or an expansion ratio of 0.015% for large files. Note that the actual
number of used disk blocks almost never increases.
The encryption is that of zip 1.9. For the encryption check, the
last byte of the decoded encryption header must be zero. The time
stamp of an encrypted file might be set to zero to avoid giving a clue
about the construction of the random header.
Jean-loup Gailly
jloup@chorus.fr
References:
[LZ77] Ziv J., Lempel A., "A Universal Algorithm for Sequential Data
Compression", IEEE Transactions on Information Theory", Vol. 23, No. 3,
pp. 337-343.
APPNOTE.TXT documentation file in PKZIP 1.93a. It is available by
ftp in ftp.cso.uiuc.edu:/pc/exec-pc/pkz193a.exe [128.174.5.59]
Use "unzip pkz193a.exe APPNOTE.TXT" to extract.

205
gnu/usr.bin/gzip/bits.c Normal file
View file

@ -0,0 +1,205 @@
/* bits.c -- output variable-length bit strings
* Copyright (C) 1992-1993 Jean-loup Gailly
* This is free software; you can redistribute it and/or modify it under the
* terms of the GNU General Public License, see the file COPYING.
*/
/*
* PURPOSE
*
* Output variable-length bit strings. Compression can be done
* to a file or to memory. (The latter is not supported in this version.)
*
* DISCUSSION
*
* The PKZIP "deflate" file format interprets compressed file data
* as a sequence of bits. Multi-bit strings in the file may cross
* byte boundaries without restriction.
*
* The first bit of each byte is the low-order bit.
*
* The routines in this file allow a variable-length bit value to
* be output right-to-left (useful for literal values). For
* left-to-right output (useful for code strings from the tree routines),
* the bits must have been reversed first with bi_reverse().
*
* For in-memory compression, the compressed bit stream goes directly
* into the requested output buffer. The input data is read in blocks
* by the mem_read() function. The buffer is limited to 64K on 16 bit
* machines.
*
* INTERFACE
*
* void bi_init (FILE *zipfile)
* Initialize the bit string routines.
*
* void send_bits (int value, int length)
* Write out a bit string, taking the source bits right to
* left.
*
* int bi_reverse (int value, int length)
* Reverse the bits of a bit string, taking the source bits left to
* right and emitting them right to left.
*
* void bi_windup (void)
* Write out any remaining bits in an incomplete byte.
*
* void copy_block(char *buf, unsigned len, int header)
* Copy a stored block to the zip file, storing first the length and
* its one's complement if requested.
*
*/
#include "tailor.h"
#include "gzip.h"
#include "crypt.h"
#ifdef DEBUG
# include <stdio.h>
#endif
#ifndef lint
static char rcsid[] = "$Id: bits.c,v 0.8 1993/02/04 13:21:06 jloup Exp $";
#endif
/* ===========================================================================
* Local data used by the "bit string" routines.
*/
local file_t zfile; /* output gzip file */
local unsigned short bi_buf;
/* Output buffer. bits are inserted starting at the bottom (least significant
* bits).
*/
#define Buf_size (8 * 2*sizeof(char))
/* Number of bits used within bi_buf. (bi_buf might be implemented on
* more than 16 bits on some systems.)
*/
local int bi_valid;
/* Number of valid bits in bi_buf. All bits above the last valid bit
* are always zero.
*/
int (*read_buf) OF((char *buf, unsigned size)) = file_read;
/* Current input function. Set to mem_read for in-memory compression */
#ifdef DEBUG
ulg bits_sent; /* bit length of the compressed data */
#endif
/* ===========================================================================
* Initialize the bit string routines.
*/
void bi_init (zipfile)
file_t zipfile; /* output zip file, NO_FILE for in-memory compression */
{
zfile = zipfile;
bi_buf = 0;
bi_valid = 0;
#ifdef DEBUG
bits_sent = 0L;
#endif
/* Set the defaults for file compression. They are set by memcompress
* for in-memory compression.
*/
if (zfile != NO_FILE) {
read_buf = file_read;
}
}
/* ===========================================================================
* Send a value on a given number of bits.
* IN assertion: length <= 16 and value fits in length bits.
*/
void send_bits(value, length)
int value; /* value to send */
int length; /* number of bits */
{
#ifdef DEBUG
Tracev((stderr," l %2d v %4x ", length, value));
Assert(length > 0 && length <= 15, "invalid length");
bits_sent += (ulg)length;
#endif
/* If not enough room in bi_buf, use (valid) bits from bi_buf and
* (16 - bi_valid) bits from value, leaving (width - (16-bi_valid))
* unused bits in value.
*/
if (bi_valid > (int)Buf_size - length) {
bi_buf |= (value << bi_valid);
put_short(bi_buf);
bi_buf = (ush)value >> (Buf_size - bi_valid);
bi_valid += length - Buf_size;
} else {
bi_buf |= value << bi_valid;
bi_valid += length;
}
}
/* ===========================================================================
* Reverse the first len bits of a code, using straightforward code (a faster
* method would use a table)
* IN assertion: 1 <= len <= 15
*/
unsigned bi_reverse(code, len)
unsigned code; /* the value to invert */
int len; /* its bit length */
{
register unsigned res = 0;
do {
res |= code & 1;
code >>= 1, res <<= 1;
} while (--len > 0);
return res >> 1;
}
/* ===========================================================================
* Write out any remaining bits in an incomplete byte.
*/
void bi_windup()
{
if (bi_valid > 8) {
put_short(bi_buf);
} else if (bi_valid > 0) {
put_byte(bi_buf);
}
bi_buf = 0;
bi_valid = 0;
#ifdef DEBUG
bits_sent = (bits_sent+7) & ~7;
#endif
}
/* ===========================================================================
* Copy a stored block to the zip file, storing first the length and its
* one's complement if requested.
*/
void copy_block(buf, len, header)
char *buf; /* the input data */
unsigned len; /* its length */
int header; /* true if block header must be written */
{
bi_windup(); /* align on byte boundary */
if (header) {
put_short((ush)len);
put_short((ush)~len);
#ifdef DEBUG
bits_sent += 2*16;
#endif
}
#ifdef DEBUG
bits_sent += (ulg)len<<3;
#endif
while (len--) {
#ifdef CRYPT
int t;
if (key) zencode(*buf, t);
#endif
put_byte(*buf++);
}
}

6
gnu/usr.bin/gzip/crypt.c Normal file
View file

@ -0,0 +1,6 @@
/* crypt.c (dummy version) -- do not perform encryption
* Hardly worth copyrighting :-)
*/
#ifndef lint
static char rcsid[] = "$Id: crypt.c,v 0.6 1993/03/22 09:48:47 jloup Exp $";
#endif

12
gnu/usr.bin/gzip/crypt.h Normal file
View file

@ -0,0 +1,12 @@
/* crypt.h (dummy version) -- do not perform encryption
* Hardly worth copyrighting :-)
*/
#ifdef CRYPT
# undef CRYPT /* dummy version */
#endif
#define RAND_HEAD_LEN 12 /* length of encryption random header */
#define zencode
#define zdecode

730
gnu/usr.bin/gzip/deflate.c Normal file
View file

@ -0,0 +1,730 @@
/* deflate.c -- compress data using the deflation algorithm
* Copyright (C) 1992-1993 Jean-loup Gailly
* This is free software; you can redistribute it and/or modify it under the
* terms of the GNU General Public License, see the file COPYING.
*/
/*
* PURPOSE
*
* Identify new text as repetitions of old text within a fixed-
* length sliding window trailing behind the new text.
*
* DISCUSSION
*
* The "deflation" process depends on being able to identify portions
* of the input text which are identical to earlier input (within a
* sliding window trailing behind the input currently being processed).
*
* The most straightforward technique turns out to be the fastest for
* most input files: try all possible matches and select the longest.
* The key feature of this algorithm is that insertions into the string
* dictionary are very simple and thus fast, and deletions are avoided
* completely. Insertions are performed at each input character, whereas
* string matches are performed only when the previous match ends. So it
* is preferable to spend more time in matches to allow very fast string
* insertions and avoid deletions. The matching algorithm for small
* strings is inspired from that of Rabin & Karp. A brute force approach
* is used to find longer strings when a small match has been found.
* A similar algorithm is used in comic (by Jan-Mark Wams) and freeze
* (by Leonid Broukhis).
* A previous version of this file used a more sophisticated algorithm
* (by Fiala and Greene) which is guaranteed to run in linear amortized
* time, but has a larger average cost, uses more memory and is patented.
* However the F&G algorithm may be faster for some highly redundant
* files if the parameter max_chain_length (described below) is too large.
*
* ACKNOWLEDGEMENTS
*
* The idea of lazy evaluation of matches is due to Jan-Mark Wams, and
* I found it in 'freeze' written by Leonid Broukhis.
* Thanks to many info-zippers for bug reports and testing.
*
* REFERENCES
*
* APPNOTE.TXT documentation file in PKZIP 1.93a distribution.
*
* A description of the Rabin and Karp algorithm is given in the book
* "Algorithms" by R. Sedgewick, Addison-Wesley, p252.
*
* Fiala,E.R., and Greene,D.H.
* Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595
*
* INTERFACE
*
* void lm_init (int pack_level, ush *flags)
* Initialize the "longest match" routines for a new file
*
* ulg deflate (void)
* Processes a new input file and return its compressed length. Sets
* the compressed length, crc, deflate flags and internal file
* attributes.
*/
#include <stdio.h>
#include "tailor.h"
#include "gzip.h"
#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 $";
#endif
/* ===========================================================================
* Configuration parameters
*/
/* Compile with MEDIUM_MEM to reduce the memory requirements or
* with SMALL_MEM to use as little memory as possible. Use BIG_MEM if the
* entire input file can be held in memory (not possible on 16 bit systems).
* Warning: defining these symbols affects HASH_BITS (see below) and thus
* affects the compression ratio. The compressed output
* is still correct, and might even be smaller in some cases.
*/
#ifdef SMALL_MEM
# define HASH_BITS 13 /* Number of bits used to hash strings */
#endif
#ifdef MEDIUM_MEM
# define HASH_BITS 14
#endif
#ifndef HASH_BITS
# define HASH_BITS 15
/* For portability to 16 bit machines, do not use values above 15. */
#endif
/* To save space (see unlzw.c), we overlay prev+head with tab_prefix and
* window with tab_suffix. Check that we can do this:
*/
#if WSIZE<<1 > 1<<BITS
error: cannot overlay window with tab_suffix and prev with tab_prefix0
#endif
#if HASH_BITS > BITS-1
error: cannot overlay head with tab_prefix1
#endif
#define HASH_SIZE (unsigned)(1<<HASH_BITS)
#define HASH_MASK (HASH_SIZE-1)
#define WMASK (WSIZE-1)
/* HASH_SIZE and WSIZE must be powers of two */
#define NIL 0
/* Tail of hash chains */
#define FAST 4
#define SLOW 2
/* speed options for the general purpose bit flag */
#ifndef TOO_FAR
# define TOO_FAR 4096
#endif
/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */
/* ===========================================================================
* Local data used by the "longest match" routines.
*/
typedef ush Pos;
typedef unsigned IPos;
/* A Pos is an index in the character window. We use short instead of int to
* save space in the various tables. IPos is used only for parameter passing.
*/
/* DECLARE(uch, window, 2L*WSIZE); */
/* Sliding window. Input bytes are read into the second half of the window,
* and move to the first half later to keep a dictionary of at least WSIZE
* bytes. With this organization, matches are limited to a distance of
* WSIZE-MAX_MATCH bytes, but this ensures that IO is always
* performed with a length multiple of the block size. Also, it limits
* the window size to 64K, which is quite useful on MSDOS.
* To do: limit the window size to WSIZE+BSZ if SMALL_MEM (the code would
* be less efficient).
*/
/* DECLARE(Pos, prev, WSIZE); */
/* Link to older string with same hash index. To limit the size of this
* array to 64K, this link is maintained only for the last 32K strings.
* An index in this array is thus a window index modulo 32K.
*/
/* DECLARE(Pos, head, 1<<HASH_BITS); */
/* Heads of the hash chains or NIL. */
ulg window_size = (ulg)2*WSIZE;
/* window size, 2*WSIZE except for MMAP or BIG_MEM, where it is the
* input file length plus MIN_LOOKAHEAD.
*/
long block_start;
/* window position at the beginning of the current output block. Gets
* negative when the window is moved backwards.
*/
local unsigned ins_h; /* hash index of string to be inserted */
#define H_SHIFT ((HASH_BITS+MIN_MATCH-1)/MIN_MATCH)
/* Number of bits by which ins_h and del_h must be shifted at each
* input step. It must be such that after MIN_MATCH steps, the oldest
* byte no longer takes part in the hash key, that is:
* H_SHIFT * MIN_MATCH >= HASH_BITS
*/
unsigned int near prev_length;
/* Length of the best match at previous step. Matches not greater than this
* are discarded. This is used in the lazy match evaluation.
*/
unsigned near strstart; /* start of string to insert */
unsigned near match_start; /* start of matching string */
local int eofile; /* flag set at end of input file */
local unsigned lookahead; /* number of valid bytes ahead in window */
unsigned near max_chain_length;
/* To speed up deflation, hash chains are never searched beyond this length.
* A higher limit improves compression ratio but degrades the speed.
*/
local unsigned int max_lazy_match;
/* Attempt to find a better match only when the current match is strictly
* smaller than this value.
*/
int near good_match;
/* Use a faster search when the previous match is longer than this */
/* Values for max_lazy_match, good_match and max_chain_length, depending on
* the desired pack level (0..9). The values given below have been tuned to
* exclude worst case performance for pathological files. Better values may be
* found for specific files.
*/
typedef struct config {
ush good_length; /* reduce lazy search above this match length */
ush max_lazy; /* do not perform lazy search above this match length */
ush nice_length; /* quit search above this match length */
ush max_chain;
} config;
#ifdef FULL_SEARCH
# define nice_match MAX_MATCH
#else
int near nice_match; /* Stop searching when current match exceeds this */
#endif
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},
/* 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.
*/
#define EQUAL 0
/* result of memcmp for equal strings */
/* ===========================================================================
* Prototypes for local functions.
*/
local void fill_window OF((void));
int longest_match OF((IPos cur_match));
#ifdef ASMV
void match_init OF((void)); /* asm code initialization */
#endif
#ifdef DEBUG
local void check_match OF((IPos start, IPos match, int length));
#endif
/* ===========================================================================
* Update a hash value with the given input byte
* IN assertion: all calls to to UPDATE_HASH are made with consecutive
* input characters, so that a running hash key can be computed from the
* previous key instead of complete recalculation each time.
*/
#define UPDATE_HASH(h,c) (h = (((h)<<H_SHIFT) ^ (c)) & HASH_MASK)
/* ===========================================================================
* Insert string s in the dictionary and set match_head to the previous head
* of the hash chain (the most recent string with same hash key). Return
* the previous length of the hash chain.
* IN assertion: all calls to to INSERT_STRING are made with consecutive
* input characters and the first MIN_MATCH bytes of s are valid
* (except for the last MIN_MATCH-1 bytes of the input file).
*/
#define INSERT_STRING(s, match_head) \
(UPDATE_HASH(ins_h, window[(s) + MIN_MATCH-1]), \
prev[(s) & WMASK] = match_head = head[ins_h], \
head[ins_h] = (s))
/* ===========================================================================
* Initialize the "longest match" routines for a new file
*/
void lm_init (pack_level, flags)
int pack_level; /* 0: store, 1: best speed, 9: best compression */
ush *flags; /* general purpose bit flag */
{
register unsigned j;
if (pack_level < 1 || pack_level > 9) error("bad pack level");
/* Initialize the hash table. */
#if defined(MAXSEG_64K) && HASH_BITS == 15
for (j = 0; j < HASH_SIZE; j++) head[j] = NIL;
#else
memzero((char*)head, HASH_SIZE*sizeof(*head));
#endif
/* prev will be initialized on the fly */
/* Set the default configuration parameters:
*/
max_lazy_match = configuration_table[pack_level].max_lazy;
good_match = configuration_table[pack_level].good_length;
#ifndef FULL_SEARCH
nice_match = configuration_table[pack_level].nice_length;
#endif
max_chain_length = configuration_table[pack_level].max_chain;
if (pack_level == 1) {
*flags |= FAST;
} else if (pack_level == 9) {
*flags |= SLOW;
}
/* ??? reduce max_chain_length for binary files */
strstart = 0;
block_start = 0L;
#ifdef ASMV
match_init(); /* initialize the asm code */
#endif
lookahead = read_buf((char*)window,
sizeof(int) <= 2 ? (unsigned)WSIZE : 2*WSIZE);
if (lookahead == 0 || lookahead == (unsigned)EOF) {
eofile = 1, lookahead = 0;
return;
}
eofile = 0;
/* Make sure that we always have enough lookahead. This is important
* if input comes from a device such as a tty.
*/
while (lookahead < MIN_LOOKAHEAD && !eofile) fill_window();
ins_h = 0;
for (j=0; j<MIN_MATCH-1; j++) UPDATE_HASH(ins_h, window[j]);
/* If lookahead < MIN_MATCH, ins_h is garbage, but this is
* not important since only literal bytes will be emitted.
*/
}
/* ===========================================================================
* Set match_start to the longest match starting at the given string and
* return its length. Matches shorter or equal to prev_length are discarded,
* in which case the result is equal to prev_length and match_start is
* garbage.
* IN assertions: cur_match is the head of the hash chain for the current
* string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
*/
#ifndef ASMV
/* For MSDOS, OS/2 and 386 Unix, an optimized version is in match.asm or
* match.s. The code is functionally equivalent, so you can use the C version
* if desired.
*/
int longest_match(cur_match)
IPos cur_match; /* current match */
{
unsigned chain_length = max_chain_length; /* max hash chain length */
register uch *scan = window + strstart; /* current string */
register uch *match; /* matched string */
register int len; /* length of current match */
int best_len = prev_length; /* best match length so far */
IPos limit = strstart > (IPos)MAX_DIST ? strstart - (IPos)MAX_DIST : NIL;
/* Stop when cur_match becomes <= limit. To simplify the code,
* we prevent matches with the string of window index 0.
*/
/* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
* It is easy to get rid of this optimization if necessary.
*/
#if HASH_BITS < 8 || MAX_MATCH != 258
error: Code too clever
#endif
#ifdef UNALIGNED_OK
/* Compare two bytes at a time. Note: this is not always beneficial.
* Try with and without -DUNALIGNED_OK to check.
*/
register uch *strend = window + strstart + MAX_MATCH - 1;
register ush scan_start = *(ush*)scan;
register ush scan_end = *(ush*)(scan+best_len-1);
#else
register uch *strend = window + strstart + MAX_MATCH;
register uch scan_end1 = scan[best_len-1];
register uch scan_end = scan[best_len];
#endif
/* Do not waste too much time if we already have a good match: */
if (prev_length >= good_match) {
chain_length >>= 2;
}
Assert(strstart <= window_size-MIN_LOOKAHEAD, "insufficient lookahead");
do {
Assert(cur_match < strstart, "no future");
match = window + cur_match;
/* Skip to next match if the match length cannot increase
* or if the match length is less than 2:
*/
#if (defined(UNALIGNED_OK) && MAX_MATCH == 258)
/* This code assumes sizeof(unsigned short) == 2. Do not use
* UNALIGNED_OK if your compiler uses a different size.
*/
if (*(ush*)(match+best_len-1) != scan_end ||
*(ush*)match != scan_start) continue;
/* It is not necessary to compare scan[2] and match[2] since they are
* always equal when the other bytes match, given that the hash keys
* are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at
* strstart+3, +5, ... up to strstart+257. We check for insufficient
* lookahead only every 4th comparison; the 128th check will be made
* at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is
* necessary to put more guard bytes at the end of the window, or
* to check more often for insufficient lookahead.
*/
scan++, match++;
do {
} while (*(ush*)(scan+=2) == *(ush*)(match+=2) &&
*(ush*)(scan+=2) == *(ush*)(match+=2) &&
*(ush*)(scan+=2) == *(ush*)(match+=2) &&
*(ush*)(scan+=2) == *(ush*)(match+=2) &&
scan < strend);
/* The funny "do {}" generates better code on most compilers */
/* Here, scan <= window+strstart+257 */
Assert(scan <= window+(unsigned)(window_size-1), "wild scan");
if (*scan == *match) scan++;
len = (MAX_MATCH - 1) - (int)(strend-scan);
scan = strend - (MAX_MATCH-1);
#else /* UNALIGNED_OK */
if (match[best_len] != scan_end ||
match[best_len-1] != scan_end1 ||
*match != *scan ||
*++match != scan[1]) continue;
/* The check at best_len-1 can be removed because it will be made
* again later. (This heuristic is not always a win.)
* It is not necessary to compare scan[2] and match[2] since they
* are always equal when the other bytes match, given that
* the hash keys are equal and that HASH_BITS >= 8.
*/
scan += 2, match++;
/* We check for insufficient lookahead only every 8th comparison;
* the 256th check will be made at strstart+258.
*/
do {
} while (*++scan == *++match && *++scan == *++match &&
*++scan == *++match && *++scan == *++match &&
*++scan == *++match && *++scan == *++match &&
*++scan == *++match && *++scan == *++match &&
scan < strend);
len = MAX_MATCH - (int)(strend - scan);
scan = strend - MAX_MATCH;
#endif /* UNALIGNED_OK */
if (len > best_len) {
match_start = cur_match;
best_len = len;
if (len >= nice_match) break;
#ifdef UNALIGNED_OK
scan_end = *(ush*)(scan+best_len-1);
#else
scan_end1 = scan[best_len-1];
scan_end = scan[best_len];
#endif
}
} while ((cur_match = prev[cur_match & WMASK]) > limit
&& --chain_length != 0);
return best_len;
}
#endif /* ASMV */
#ifdef DEBUG
/* ===========================================================================
* Check that the match at match_start is indeed a match.
*/
local void check_match(start, match, length)
IPos start, match;
int length;
{
/* check that the match is indeed a match */
if (memcmp((char*)window + match,
(char*)window + start, length) != EQUAL) {
fprintf(stderr,
" start %d, match %d, length %d\n",
start, match, length);
error("invalid match");
}
if (verbose > 1) {
fprintf(stderr,"\\[%d,%d]", start-match, length);
do { putc(window[start++], stderr); } while (--length != 0);
}
}
#else
# define check_match(start, match, length)
#endif
/* ===========================================================================
* Fill the window when the lookahead becomes insufficient.
* Updates strstart and lookahead, and sets eofile if end of input file.
* IN assertion: lookahead < MIN_LOOKAHEAD && strstart + lookahead > 0
* OUT assertions: at least one byte has been read, or eofile is set;
* file reads are performed for at least two bytes (required for the
* translate_eol option).
*/
local void fill_window()
{
register unsigned n, m;
unsigned more = (unsigned)(window_size - (ulg)lookahead - (ulg)strstart);
/* Amount of free space at the end of the window. */
/* If the window is almost full and there is insufficient lookahead,
* move the upper half to the lower one to make room in the upper half.
*/
if (more == (unsigned)EOF) {
/* Very unlikely, but possible on 16 bit machine if strstart == 0
* and lookahead == 1 (input done one byte at time)
*/
more--;
} else if (strstart >= WSIZE+MAX_DIST) {
/* By the IN assertion, the window is not empty so we can't confuse
* more == 0 with more == 64K on a 16 bit machine.
*/
Assert(window_size == (ulg)2*WSIZE, "no sliding with BIG_MEM");
memcpy((char*)window, (char*)window+WSIZE, (unsigned)WSIZE);
match_start -= WSIZE;
strstart -= WSIZE; /* we now have strstart >= MAX_DIST: */
block_start -= (long) WSIZE;
for (n = 0; n < HASH_SIZE; n++) {
m = head[n];
head[n] = (Pos)(m >= WSIZE ? m-WSIZE : NIL);
}
for (n = 0; n < WSIZE; n++) {
m = prev[n];
prev[n] = (Pos)(m >= WSIZE ? m-WSIZE : NIL);
/* If n is not on any hash chain, prev[n] is garbage but
* its value will never be used.
*/
}
more += WSIZE;
}
/* At this point, more >= 2 */
if (!eofile) {
n = read_buf((char*)window+strstart+lookahead, more);
if (n == 0 || n == (unsigned)EOF) {
eofile = 1;
} else {
lookahead += n;
}
}
}
/* ===========================================================================
* Flush the current block, with given end-of-file flag.
* IN assertion: strstart is set to the end of the current match.
*/
#define FLUSH_BLOCK(eof) \
flush_block(block_start >= 0L ? (char*)&window[(unsigned)block_start] : \
(char*)NULL, (long)strstart - block_start, (eof))
/* ===========================================================================
* Processes a new input file and return its compressed length.
*/
#ifdef NO_LAZY
ulg deflate()
{
IPos hash_head; /* head of the hash chain */
int flush; /* set if current block must be flushed */
unsigned match_length = 0; /* length of best match */
prev_length = MIN_MATCH-1;
while (lookahead != 0) {
/* Insert the string window[strstart .. strstart+2] in the
* dictionary, and set hash_head to the head of the hash chain:
*/
INSERT_STRING(strstart, hash_head);
/* Find the longest match, discarding those <= prev_length.
* At this point we have always match_length < MIN_MATCH
*/
if (hash_head != NIL && strstart - hash_head <= MAX_DIST) {
/* To simplify the code, we prevent matches with the string
* of window index 0 (in particular we have to avoid a match
* of the string with itself at the start of the input file).
*/
match_length = longest_match (hash_head);
/* longest_match() sets match_start */
if (match_length > lookahead) match_length = lookahead;
}
if (match_length >= MIN_MATCH) {
check_match(strstart, match_start, match_length);
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);
} else {
/* No match, output a literal byte */
flush = ct_tally (0, window[strstart]);
lookahead--;
}
strstart++;
if (flush) FLUSH_BLOCK(0), block_start = strstart;
/* Make sure that we always have enough lookahead, except
* at the end of the input file. We need MAX_MATCH bytes
* for the next match, plus MIN_MATCH bytes to insert the
* string following the next match.
*/
while (lookahead < MIN_LOOKAHEAD && !eofile) fill_window();
}
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
* no better match at the next window position.
*/
ulg deflate()
{
IPos hash_head; /* head of hash chain */
IPos prev_match; /* previous match */
int flush; /* set if current block must be flushed */
int match_available = 0; /* set if previous match exists */
register unsigned match_length = MIN_MATCH-1; /* length of best match */
#ifdef DEBUG
extern long isize; /* byte length of input file, for debug only */
#endif
/* Process the input block. */
while (lookahead != 0) {
/* Insert the string window[strstart .. strstart+2] in the
* dictionary, and set hash_head to the head of the hash chain:
*/
INSERT_STRING(strstart, hash_head);
/* Find the longest match, discarding those <= prev_length.
*/
prev_length = match_length, prev_match = match_start;
match_length = MIN_MATCH-1;
if (hash_head != NIL && prev_length < max_lazy_match &&
strstart - hash_head <= MAX_DIST) {
/* To simplify the code, we prevent matches with the string
* of window index 0 (in particular we have to avoid a match
* of the string with itself at the start of the input file).
*/
match_length = longest_match (hash_head);
/* longest_match() sets match_start */
if (match_length > lookahead) match_length = lookahead;
/* Ignore a length 3 match if it is too distant: */
if (match_length == MIN_MATCH && strstart-match_start > TOO_FAR){
/* If prev_match is also MIN_MATCH, match_start is garbage
* but we will ignore the current match anyway.
*/
match_length--;
}
}
/* If there was a match at the previous step and the current
* match is not better, output the previous match:
*/
if (prev_length >= MIN_MATCH && match_length <= prev_length) {
check_match(strstart-1, prev_match, prev_length);
flush = ct_tally(strstart-1-prev_match, prev_length - MIN_MATCH);
/* Insert in hash table all strings up to the end of the match.
* strstart-1 and strstart are already inserted.
*/
lookahead -= prev_length-1;
prev_length -= 2;
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 (--prev_length != 0);
match_available = 0;
match_length = MIN_MATCH-1;
strstart++;
if (flush) FLUSH_BLOCK(0), block_start = strstart;
} else if (match_available) {
/* If there was no match at the previous position, output a
* single literal. If there was a match but the current match
* is longer, truncate the previous match to a single literal.
*/
Tracevv((stderr,"%c",window[strstart-1]));
if (ct_tally (0, window[strstart-1])) {
FLUSH_BLOCK(0), block_start = strstart;
}
strstart++;
lookahead--;
} else {
/* There is no previous match to compare with, wait for
* the next step to decide.
*/
match_available = 1;
strstart++;
lookahead--;
}
Assert (strstart <= isize && lookahead <= isize, "a bit too far");
/* Make sure that we always have enough lookahead, except
* at the end of the input file. We need MAX_MATCH bytes
* for the next match, plus MIN_MATCH bytes to insert the
* string following the next match.
*/
while (lookahead < MIN_LOOKAHEAD && !eofile) fill_window();
}
if (match_available) ct_tally (0, window[strstart-1]);
return FLUSH_BLOCK(1); /* eof */
}
#endif /* LAZY */

711
gnu/usr.bin/gzip/getopt.c Normal file
View file

@ -0,0 +1,711 @@
/* Getopt for GNU.
NOTE: getopt is now part of the C library, so if you don't know what
"Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu
before changing it!
Copyright (C) 1987, 88, 89, 90, 91, 1992 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* AIX requires this to be the first thing in the file. */
#ifdef __GNUC__
#define alloca __builtin_alloca
#else /* not __GNUC__ */
#if defined (HAVE_ALLOCA_H) || (defined(sparc) && (defined(sun) || (!defined(USG) && !defined(SVR4) && !defined(__svr4__))))
#include <alloca.h>
#else
#ifdef _AIX
#pragma alloca
#else
char *alloca ();
#endif
#endif /* alloca.h */
#endif /* not __GNUC__ */
#include <stdio.h>
#if defined(USG) || defined(STDC_HEADERS) || defined(__GNU_LIBRARY__)
#include <string.h>
#endif
/* This needs to come after some library #include
to get __GNU_LIBRARY__ defined. */
#ifdef __GNU_LIBRARY__
#undef alloca
/* Don't include stdlib.h for non-GNU C libraries because some of them
contain conflicting prototypes for getopt. */
#include <stdlib.h>
#else /* Not GNU C library. */
#define __alloca alloca
#endif /* GNU C library. */
#if !__STDC__
#define const
#endif
/* If GETOPT_COMPAT is defined, `+' as well as `--' can introduce a
long-named option. Because this is not POSIX.2 compliant, it is
being phased out. */
#define GETOPT_COMPAT
/* This version of `getopt' appears to the caller like standard Unix `getopt'
but it behaves differently for the user, since it allows the user
to intersperse the options with the other arguments.
As `getopt' works, it permutes the elements of ARGV so that,
when it is done, all the options precede everything else. Thus
all application programs are extended to handle flexible argument order.
Setting the environment variable POSIXLY_CORRECT disables permutation.
Then the behavior is completely standard.
GNU application programs can use a third alternative mode in which
they can distinguish the relative order of options and other arguments. */
#include "getopt.h"
/* For communication from `getopt' to the caller.
When `getopt' finds an option that takes an argument,
the argument value is returned here.
Also, when `ordering' is RETURN_IN_ORDER,
each non-option ARGV-element is returned here. */
char *optarg = 0;
/* Index in ARGV of the next element to be scanned.
This is used for communication to and from the caller
and for communication between successive calls to `getopt'.
On entry to `getopt', zero means this is the first call; initialize.
When `getopt' returns EOF, this is the index of the first of the
non-option elements that the caller should itself scan.
Otherwise, `optind' communicates from one call to the next
how much of ARGV has been scanned so far. */
int optind = 0;
/* The next char to be scanned in the option-element
in which the last option character we returned was found.
This allows us to pick up the scan where we left off.
If this is zero, or a null string, it means resume the scan
by advancing to the next ARGV-element. */
static char *nextchar;
/* Callers store zero here to inhibit the error message
for unrecognized options. */
int opterr = 1;
/* Describe how to deal with options that follow non-option ARGV-elements.
If the caller did not specify anything,
the default is REQUIRE_ORDER if the environment variable
POSIXLY_CORRECT is defined, PERMUTE otherwise.
REQUIRE_ORDER means don't recognize them as options;
stop option processing when the first non-option is seen.
This is what Unix does.
This mode of operation is selected by either setting the environment
variable POSIXLY_CORRECT, or using `+' as the first character
of the list of option characters.
PERMUTE is the default. We permute the contents of ARGV as we scan,
so that eventually all the non-options are at the end. This allows options
to be given in any order, even with programs that were not written to
expect this.
RETURN_IN_ORDER is an option available to programs that were written
to expect options and other ARGV-elements in any order and that care about
the ordering of the two. We describe each non-option ARGV-element
as if it were the argument of an option with character code 1.
Using `-' as the first character of the list of option characters
selects this mode of operation.
The special argument `--' forces an end of option-scanning regardless
of the value of `ordering'. In the case of RETURN_IN_ORDER, only
`--' can cause `getopt' to return EOF with `optind' != ARGC. */
static enum
{
REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
} ordering;
#ifdef __GNU_LIBRARY__
#include <string.h>
#define my_index strchr
#define my_bcopy(src, dst, n) memcpy ((dst), (src), (n))
#else
/* Avoid depending on library functions or files
whose names are inconsistent. */
char *getenv ();
static char *
my_index (string, chr)
char *string;
int chr;
{
while (*string)
{
if (*string == chr)
return string;
string++;
}
return 0;
}
static void
my_bcopy (from, to, size)
char *from, *to;
int size;
{
int i;
for (i = 0; i < size; i++)
to[i] = from[i];
}
#endif /* GNU C library. */
/* Handle permutation of arguments. */
/* Describe the part of ARGV that contains non-options that have
been skipped. `first_nonopt' is the index in ARGV of the first of them;
`last_nonopt' is the index after the last of them. */
static int first_nonopt;
static int last_nonopt;
/* Exchange two adjacent subsequences of ARGV.
One subsequence is elements [first_nonopt,last_nonopt)
which contains all the non-options that have been skipped so far.
The other is elements [last_nonopt,optind), which contains all
the options processed since those non-options were skipped.
`first_nonopt' and `last_nonopt' are relocated so that they describe
the new indices of the non-options in ARGV after they are moved. */
static void
exchange (argv)
char **argv;
{
int nonopts_size = (last_nonopt - first_nonopt) * sizeof (char *);
#ifdef _CRAY
char *temp[last_nonopt - first_nonopt];
#else
char **temp = (char **) __alloca (nonopts_size);
#endif
/* Interchange the two blocks of data in ARGV. */
my_bcopy ((char *) &argv[first_nonopt], (char *) temp, nonopts_size);
my_bcopy ((char *) &argv[last_nonopt], (char *) &argv[first_nonopt],
(optind - last_nonopt) * sizeof (char *));
my_bcopy ((char *) temp,
(char *) &argv[first_nonopt + optind - last_nonopt],
nonopts_size);
/* Update records for the slots the non-options now occupy. */
first_nonopt += (optind - last_nonopt);
last_nonopt = optind;
}
/* Scan elements of ARGV (whose length is ARGC) for option characters
given in OPTSTRING.
If an element of ARGV starts with '-', and is not exactly "-" or "--",
then it is an option element. The characters of this element
(aside from the initial '-') are option characters. If `getopt'
is called repeatedly, it returns successively each of the option characters
from each of the option elements.
If `getopt' finds another option character, it returns that character,
updating `optind' and `nextchar' so that the next call to `getopt' can
resume the scan with the following option character or ARGV-element.
If there are no more option characters, `getopt' returns `EOF'.
Then `optind' is the index in ARGV of the first ARGV-element
that is not an option. (The ARGV-elements have been permuted
so that those that are not options now come last.)
OPTSTRING is a string containing the legitimate option characters.
If an option character is seen that is not listed in OPTSTRING,
return '?' after printing an error message. If you set `opterr' to
zero, the error message is suppressed but we still return '?'.
If a char in OPTSTRING is followed by a colon, that means it wants an arg,
so the following text in the same ARGV-element, or the text of the following
ARGV-element, is returned in `optarg'. Two colons mean an option that
wants an optional arg; if there is text in the current ARGV-element,
it is returned in `optarg', otherwise `optarg' is set to zero.
If OPTSTRING starts with `-' or `+', it requests different methods of
handling the non-option ARGV-elements.
See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
Long-named options begin with `--' instead of `-'.
Their names may be abbreviated as long as the abbreviation is unique
or is an exact match for some defined option. If they have an
argument, it follows the option name in the same ARGV-element, separated
from the option name by a `=', or else the in next ARGV-element.
When `getopt' finds a long-named option, it returns 0 if that option's
`flag' field is nonzero, the value of the option's `val' field
if the `flag' field is zero.
The elements of ARGV aren't really const, because we permute them.
But we pretend they're const in the prototype to be compatible
with other systems.
LONGOPTS is a vector of `struct option' terminated by an
element containing a name which is zero.
LONGIND returns the index in LONGOPT of the long-named option found.
It is only valid when a long-named option has been found by the most
recent call.
If LONG_ONLY is nonzero, '-' as well as '--' can introduce
long-named options. */
int
_getopt_internal (argc, argv, optstring, longopts, longind, long_only)
int argc;
char *const *argv;
const char *optstring;
const struct option *longopts;
int *longind;
int long_only;
{
int option_index;
optarg = 0;
/* Initialize the internal data when the first call is made.
Start processing options with ARGV-element 1 (since ARGV-element 0
is the program name); the sequence of previously skipped
non-option ARGV-elements is empty. */
if (optind == 0)
{
first_nonopt = last_nonopt = optind = 1;
nextchar = NULL;
/* Determine how to handle the ordering of options and nonoptions. */
if (optstring[0] == '-')
{
ordering = RETURN_IN_ORDER;
++optstring;
}
else if (optstring[0] == '+')
{
ordering = REQUIRE_ORDER;
++optstring;
}
else if (getenv ("POSIXLY_CORRECT") != NULL)
ordering = REQUIRE_ORDER;
else
ordering = PERMUTE;
}
if (nextchar == NULL || *nextchar == '\0')
{
if (ordering == PERMUTE)
{
/* If we have just processed some options following some non-options,
exchange them so that the options come first. */
if (first_nonopt != last_nonopt && last_nonopt != optind)
exchange ((char **) argv);
else if (last_nonopt != optind)
first_nonopt = optind;
/* Now skip any additional non-options
and extend the range of non-options previously skipped. */
while (optind < argc
&& (argv[optind][0] != '-' || argv[optind][1] == '\0')
#ifdef GETOPT_COMPAT
&& (longopts == NULL
|| argv[optind][0] != '+' || argv[optind][1] == '\0')
#endif /* GETOPT_COMPAT */
)
optind++;
last_nonopt = optind;
}
/* Special ARGV-element `--' means premature end of options.
Skip it like a null option,
then exchange with previous non-options as if it were an option,
then skip everything else like a non-option. */
if (optind != argc && !strcmp (argv[optind], "--"))
{
optind++;
if (first_nonopt != last_nonopt && last_nonopt != optind)
exchange ((char **) argv);
else if (first_nonopt == last_nonopt)
first_nonopt = optind;
last_nonopt = argc;
optind = argc;
}
/* If we have done all the ARGV-elements, stop the scan
and back over any non-options that we skipped and permuted. */
if (optind == argc)
{
/* Set the next-arg-index to point at the non-options
that we previously skipped, so the caller will digest them. */
if (first_nonopt != last_nonopt)
optind = first_nonopt;
return EOF;
}
/* If we have come to a non-option and did not permute it,
either stop the scan or describe it to the caller and pass it by. */
if ((argv[optind][0] != '-' || argv[optind][1] == '\0')
#ifdef GETOPT_COMPAT
&& (longopts == NULL
|| argv[optind][0] != '+' || argv[optind][1] == '\0')
#endif /* GETOPT_COMPAT */
)
{
if (ordering == REQUIRE_ORDER)
return EOF;
optarg = argv[optind++];
return 1;
}
/* We have found another option-ARGV-element.
Start decoding its characters. */
nextchar = (argv[optind] + 1
+ (longopts != NULL && argv[optind][1] == '-'));
}
if (longopts != NULL
&& ((argv[optind][0] == '-'
&& (argv[optind][1] == '-' || long_only))
#ifdef GETOPT_COMPAT
|| argv[optind][0] == '+'
#endif /* GETOPT_COMPAT */
))
{
const struct option *p;
char *s = nextchar;
int exact = 0;
int ambig = 0;
const struct option *pfound = NULL;
int indfound = 0;
while (*s && *s != '=')
s++;
/* Test all options for either exact match or abbreviated matches. */
for (p = longopts, option_index = 0; p->name;
p++, option_index++)
if (!strncmp (p->name, nextchar, s - nextchar))
{
if (s - nextchar == strlen (p->name))
{
/* Exact match found. */
pfound = p;
indfound = option_index;
exact = 1;
break;
}
else if (pfound == NULL)
{
/* First nonexact match found. */
pfound = p;
indfound = option_index;
}
else
/* Second nonexact match found. */
ambig = 1;
}
if (ambig && !exact)
{
if (opterr)
fprintf (stderr, "%s: option `%s' is ambiguous\n",
argv[0], argv[optind]);
nextchar += strlen (nextchar);
optind++;
return '?';
}
if (pfound != NULL)
{
option_index = indfound;
optind++;
if (*s)
{
/* Don't test has_arg with >, because some C compilers don't
allow it to be used on enums. */
if (pfound->has_arg)
optarg = s + 1;
else
{
if (opterr)
{
if (argv[optind - 1][1] == '-')
/* --option */
fprintf (stderr,
"%s: option `--%s' doesn't allow an argument\n",
argv[0], pfound->name);
else
/* +option or -option */
fprintf (stderr,
"%s: option `%c%s' doesn't allow an argument\n",
argv[0], argv[optind - 1][0], pfound->name);
}
nextchar += strlen (nextchar);
return '?';
}
}
else if (pfound->has_arg == 1)
{
if (optind < argc)
optarg = argv[optind++];
else
{
if (opterr)
fprintf (stderr, "%s: option `%s' requires an argument\n",
argv[0], argv[optind - 1]);
nextchar += strlen (nextchar);
return '?';
}
}
nextchar += strlen (nextchar);
if (longind != NULL)
*longind = option_index;
if (pfound->flag)
{
*(pfound->flag) = pfound->val;
return 0;
}
return pfound->val;
}
/* Can't find it as a long option. If this is not getopt_long_only,
or the option starts with '--' or is not a valid short
option, then it's an error.
Otherwise interpret it as a short option. */
if (!long_only || argv[optind][1] == '-'
#ifdef GETOPT_COMPAT
|| argv[optind][0] == '+'
#endif /* GETOPT_COMPAT */
|| my_index ((char*)optstring, *nextchar) == NULL)
{
if (opterr)
{
if (argv[optind][1] == '-')
/* --option */
fprintf (stderr, "%s: unrecognized option `--%s'\n",
argv[0], nextchar);
else
/* +option or -option */
fprintf (stderr, "%s: unrecognized option `%c%s'\n",
argv[0], argv[optind][0], nextchar);
}
nextchar = (char *) "";
optind++;
return '?';
}
}
/* Look at and handle the next option-character. */
{
char c = *nextchar++;
char *temp = my_index ((char*)optstring, c);
/* Increment `optind' when we start to process its last character. */
if (*nextchar == '\0')
++optind;
if (temp == NULL || c == ':')
{
if (opterr)
{
if (c < 040 || c >= 0177)
fprintf (stderr, "%s: unrecognized option, character code 0%o\n",
argv[0], c);
else
fprintf (stderr, "%s: unrecognized option `-%c'\n", argv[0], c);
}
return '?';
}
if (temp[1] == ':')
{
if (temp[2] == ':')
{
/* This is an option that accepts an argument optionally. */
if (*nextchar != '\0')
{
optarg = nextchar;
optind++;
}
else
optarg = 0;
nextchar = NULL;
}
else
{
/* This is an option that requires an argument. */
if (*nextchar != '\0')
{
optarg = nextchar;
/* If we end this ARGV-element by taking the rest as an arg,
we must advance to the next element now. */
optind++;
}
else if (optind == argc)
{
if (opterr)
fprintf (stderr, "%s: option `-%c' requires an argument\n",
argv[0], c);
c = '?';
}
else
/* We already incremented `optind' once;
increment it again when taking next ARGV-elt as argument. */
optarg = argv[optind++];
nextchar = NULL;
}
}
return c;
}
}
int
getopt (argc, argv, optstring)
int argc;
char *const *argv;
const char *optstring;
{
return _getopt_internal (argc, argv, optstring,
(const struct option *) 0,
(int *) 0,
0);
}
int
getopt_long (argc, argv, options, long_options, opt_index)
int argc;
char *const *argv;
const char *options;
const struct option *long_options;
int *opt_index;
{
return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
}
/* Like getopt_long, but '-' as well as '--' can indicate a long option.
If an option that starts with '-' (not '--') doesn't match a long option,
but does match a short option, it is parsed as a short option
instead. */
int
getopt_long_only (argc, argv, options, long_options, opt_index)
int argc;
char *const *argv;
const char *options;
const struct option *long_options;
int *opt_index;
{
return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
}
#ifdef TEST
/* Compile with -DTEST to make an executable for use in testing
the above definition of `getopt'. */
int
main (argc, argv)
int argc;
char **argv;
{
int c;
int digit_optind = 0;
while (1)
{
int this_option_optind = optind ? optind : 1;
c = getopt (argc, argv, "abc:d:0123456789");
if (c == EOF)
break;
switch (c)
{
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if (digit_optind != 0 && digit_optind != this_option_optind)
printf ("digits occur in two different argv-elements.\n");
digit_optind = this_option_optind;
printf ("option %c\n", c);
break;
case 'a':
printf ("option a\n");
break;
case 'b':
printf ("option b\n");
break;
case 'c':
printf ("option c with value `%s'\n", optarg);
break;
case '?':
break;
default:
printf ("?? getopt returned character code 0%o ??\n", c);
}
}
if (optind < argc)
{
printf ("non-option ARGV-elements: ");
while (optind < argc)
printf ("%s ", argv[optind++]);
printf ("\n");
}
exit (0);
}
#endif /* TEST */

128
gnu/usr.bin/gzip/getopt.h Normal file
View file

@ -0,0 +1,128 @@
/* Declarations for getopt.
Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef _GETOPT_H
#define _GETOPT_H 1
#ifdef __cplusplus
extern "C" {
#endif
/* For communication from `getopt' to the caller.
When `getopt' finds an option that takes an argument,
the argument value is returned here.
Also, when `ordering' is RETURN_IN_ORDER,
each non-option ARGV-element is returned here. */
extern char *optarg;
/* Index in ARGV of the next element to be scanned.
This is used for communication to and from the caller
and for communication between successive calls to `getopt'.
On entry to `getopt', zero means this is the first call; initialize.
When `getopt' returns EOF, this is the index of the first of the
non-option elements that the caller should itself scan.
Otherwise, `optind' communicates from one call to the next
how much of ARGV has been scanned so far. */
extern int optind;
/* Callers store zero here to inhibit the error message `getopt' prints
for unrecognized options. */
extern int opterr;
/* Describe the long-named options requested by the application.
The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
of `struct option' terminated by an element containing a name which is
zero.
The field `has_arg' is:
no_argument (or 0) if the option does not take an argument,
required_argument (or 1) if the option requires an argument,
optional_argument (or 2) if the option takes an optional argument.
If the field `flag' is not NULL, it points to a variable that is set
to the value given in the field `val' when the option is found, but
left unchanged if the option is not found.
To have a long-named option do something other than set an `int' to
a compiled-in constant, such as set a value from `optarg', set the
option's `flag' field to zero and its `val' field to a nonzero
value (the equivalent single-letter option character, if there is
one). For long options that have a zero `flag' field, `getopt'
returns the contents of the `val' field. */
struct option
{
#if __STDC__
const char *name;
#else
char *name;
#endif
/* has_arg can't be an enum because some compilers complain about
type mismatches in all the code that assumes it is an int. */
int has_arg;
int *flag;
int val;
};
/* Names for the values of the `has_arg' field of `struct option'. */
enum _argtype
{
no_argument,
required_argument,
optional_argument
};
#if __STDC__ || defined(PROTO)
#if defined(__GNU_LIBRARY__)
/* Many other libraries have conflicting prototypes for getopt, with
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);
extern int getopt_long_only (int argc, char *const *argv,
const char *shortopts,
const struct option *longopts, int *longind);
/* Internal only. Users should not call this directly. */
extern int _getopt_internal (int argc, char *const *argv,
const char *shortopts,
const struct option *longopts, int *longind,
int long_only);
#else /* not __STDC__ */
extern int getopt ();
extern int getopt_long ();
extern int getopt_long_only ();
extern int _getopt_internal ();
#endif /* not __STDC__ */
#ifdef __cplusplus
}
#endif
#endif /* _GETOPT_H */

134
gnu/usr.bin/gzip/gzexe Normal file
View file

@ -0,0 +1,134 @@
#!/bin/sh
# gzexe: compressor for Unix executables.
# Use this only for binaries that you do not use frequently.
#
# The compressed version is a shell script which decompresses itself after
# skipping $skip lines of shell commands. We try invoking the compressed
# executable with the original name (for programs looking at their name).
# 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
# The : is required for some old versions of csh.
x=`basename $0`
if test $# = 0; then
echo compress executables. original file foo is renamed to foo~
echo usage: ${x} [-d] files...
echo " -d decompress the executables"
exit 1
fi
tmp=gz$$
trap "rm -f $tmp; exit 1" 1 2 3 5 10 13 15
decomp=0
res=0
test "$x" = "ungzexe" && decomp=1
if test "x$1" = "x-d"; then
decomp=1
shift
fi
echo hi > zfoo1$$
echo hi > zfoo2$$
if test -z "`(${CPMOD-cpmod} zfoo1$$ zfoo2$$) 2>&1`"; then
cpmod=${CPMOD-cpmod}
fi
rm -f zfoo[12]$$
for i do
if test ! -f "$i" ; then
echo ${x}: $i not a file
res=1
continue
fi
if test $decomp -eq 0; then
if sed -e 1d -e 2q "$i" | grep "^skip=[0-9]*$" >/dev/null; then
echo "${x}: $i is already gzexe'd"
continue
fi
fi
if ls -l "$i" | grep '^...[sS]' > /dev/null; then
echo "${x}: $i has setuid permission, unchanged"
continue
fi
if ls -l "$i" | grep '^......[sS]' > /dev/null; then
echo "${x}: $i has setgid permission, unchanged"
continue
fi
if test "`basename $i`" = gzip; then
echo "${x}: cannot compress gzip itself"
continue
fi
if test -z "$cpmod"; then
cp -p "$i" $tmp 2>/dev/null || cp "$i" $tmp
if test -w $tmp 2>/dev/null; then
writable=1
else
writable=0
chmod u+w $tmp 2>/dev/null
fi
fi
if test $decomp -eq 0; then
sed 1q $0 > $tmp
cat >> $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
trap '/bin/rm -f /tmp/gztmp$$ "/tmp/$prog"; exit $res' 0
(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 &
/tmp/gztmp$$ ${1+"$@"}; res=$?
fi
else
echo Cannot decompress $0; exit 1
fi; exit $res
EOF
gzip -cv9 "$i" >> $tmp || {
/bin/rm -f $tmp
echo ${x}: compression not possible for $i, file unchanged.
res=1
continue
}
else
# decompression
skip=18
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
:
else
echo ${x}: $i probably not in gzexe format, file unchanged.
res=1
continue
fi
fi
rm -f "$i~"
mv "$i" "$i~" || {
echo ${x}: cannot backup $i as $i~
rm -f $tmp
res=1
continue
}
mv $tmp "$i" || cp -p $tmp "$i" 2>/dev/null || cp $tmp "$i" || {
echo ${x}: cannot create $i
rm -f $tmp
res=1
continue
}
rm -f $tmp
if test -n "$cpmod"; then
$cpmod "$i~" "$i" 2>/dev/null
elif test $writable -eq 0; then
chmod u-w $i 2>/dev/null
fi
done
exit $res

36
gnu/usr.bin/gzip/gzexe.1 Normal file
View file

@ -0,0 +1,36 @@
.TH GZEXE 1
.SH NAME
gzexe \- compress executable files in place
.SH SYNOPSIS
.B gzexe
[ name ... ]
.SH DESCRIPTION
The
.I gzexe
utility allows you to compress executables in place and have them
automatically uncompress and execute when you run them (at a penalty
in performance). For example if you execute ``gzexe /bin/cat'' it
will create the following two files:
.nf
.br
-r-xr-xr-x 1 root bin 9644 Feb 11 11:16 /bin/cat
-r-xr-xr-x 1 bin bin 24576 Nov 23 13:21 /bin/cat~
.fi
/bin/cat~ is the original file and /bin/cat is the self-uncompressing
executable file. You can remove /bin/cat~ once you are sure that
/bin/cat works properly.
.PP
This utility is most useful on systems with very small disks.
.SH OPTIONS
.TP
.B \-d
Decompress the given executables instead of compressing them.
.SH "SEE ALSO"
gzip(1), znew(1), zmore(1), zcmp(1), zforce(1)
.SH "BUGS"
.I gzexe
attempts to retain the original file attributes on the compressed executable,
but you may have to fix them manually in some cases, using
.I chmod
or
.I chown.

135
gnu/usr.bin/gzip/gzexe.in Normal file
View file

@ -0,0 +1,135 @@
:
#!/bin/sh
# gzexe: compressor for Unix executables.
# Use this only for binaries that you do not use frequently.
#
# The compressed version is a shell script which decompresses itself after
# skipping $skip lines of shell commands. We try invoking the compressed
# executable with the original name (for programs looking at their name).
# 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
# The : is required for some old versions of csh.
x=`basename $0`
if test $# = 0; then
echo compress executables. original file foo is renamed to foo~
echo usage: ${x} [-d] files...
echo " -d decompress the executables"
exit 1
fi
tmp=gz$$
trap "rm -f $tmp; exit 1" 1 2 3 5 10 13 15
decomp=0
res=0
test "$x" = "ungzexe" && decomp=1
if test "x$1" = "x-d"; then
decomp=1
shift
fi
echo hi > zfoo1$$
echo hi > zfoo2$$
if test -z "`(${CPMOD-cpmod} zfoo1$$ zfoo2$$) 2>&1`"; then
cpmod=${CPMOD-cpmod}
fi
rm -f zfoo[12]$$
for i do
if test ! -f "$i" ; then
echo ${x}: $i not a file
res=1
continue
fi
if test $decomp -eq 0; then
if sed -e 1d -e 2q "$i" | grep "^skip=[0-9]*$" >/dev/null; then
echo "${x}: $i is already gzexe'd"
continue
fi
fi
if ls -l "$i" | grep '^...[sS]' > /dev/null; then
echo "${x}: $i has setuid permission, unchanged"
continue
fi
if ls -l "$i" | grep '^......[sS]' > /dev/null; then
echo "${x}: $i has setgid permission, unchanged"
continue
fi
if test "`basename $i`" = gzip; then
echo "${x}: cannot compress gzip itself"
continue
fi
if test -z "$cpmod"; then
cp -p "$i" $tmp 2>/dev/null || cp "$i" $tmp
if test -w $tmp 2>/dev/null; then
writable=1
else
writable=0
chmod u+w $tmp 2>/dev/null
fi
fi
if test $decomp -eq 0; then
sed 1q $0 > $tmp
cat >> $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
trap '/bin/rm -f /tmp/gztmp$$ "/tmp/$prog"; exit $res' 0
(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 &
/tmp/gztmp$$ ${1+"$@"}; res=$?
fi
else
echo Cannot decompress $0; exit 1
fi; exit $res
EOF
gzip -cv9 "$i" >> $tmp || {
/bin/rm -f $tmp
echo ${x}: compression not possible for $i, file unchanged.
res=1
continue
}
else
# decompression
skip=18
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
:
else
echo ${x}: $i probably not in gzexe format, file unchanged.
res=1
continue
fi
fi
rm -f "$i~"
mv "$i" "$i~" || {
echo ${x}: cannot backup $i as $i~
rm -f $tmp
res=1
continue
}
mv $tmp "$i" || cp -p $tmp "$i" 2>/dev/null || cp $tmp "$i" || {
echo ${x}: cannot create $i
rm -f $tmp
res=1
continue
}
rm -f $tmp
if test -n "$cpmod"; then
$cpmod "$i~" "$i" 2>/dev/null
elif test $writable -eq 0; then
chmod u-w $i 2>/dev/null
fi
done
exit $res

360
gnu/usr.bin/gzip/gzip.1 Normal file
View file

@ -0,0 +1,360 @@
.PU
.TH GZIP 1
.SH NAME
gzip, gunzip, zcat \- compress or expand files
.SH SYNOPSIS
.ll +8
.B gzip
.RB [ " \-acdfhLrtvV19 " ]
.RB [ \-S\ suffix ]
[
.I "name \&..."
]
.ll -8
.br
.B gunzip
.RB [ " \-acfhLrtvV " ]
.RB [ \-S\ suffix ]
[
.I "name \&..."
]
.br
.B zcat
.RB [ " \-hLV " ]
[
.I "name \&..."
]
.SH DESCRIPTION
.I Gzip
reduces the size of the named files using Lempel-Ziv coding (LZ77).
Whenever possible,
each file is replaced by one with the extension
.B "\&.gz,"
while keeping the same ownership modes, access and modification times.
(The default extension is
.B "\-gz"
for VMS,
.B "z"
for MSDOS, OS/2 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.
.I Gzip
will only attempt to compress regular files.
In particular, it will ignore symbolic links.
.PP
Compressed files can be restored to their original form using
.I gzip -d
or
.I gunzip
or
.I zcat.
.PP
.I gunzip
takes a list of files on its command line and replaces each
file whose name ends with .gz, -gz, .z, -z, _z or .Z
and which begins with the correct magic number with an uncompressed
file without the original extension.
.I gunzip
also recognizes the special extensions
.B "\&.tgz"
and
.B "\&.taz"
as shorthands for
.B "\&.tar.gz"
and
.B "\&.tar.Z"
respectively.
.PP
.I gunzip
can currently decompress files created by
.I gzip, zip, compress
or
.I pack.
The detection of the input format is automatic. When using
the first two formats,
.I gunzip
checks a 32 bit CRC. For
.I pack, gunzip
checks the uncompressed length. The
.I compress
format was not designed to allow consistency checks. However
.I gunzip
is sometimes able to detect a bad .Z file. If you get an error
when uncompressing a .Z file, do not assume that the .Z file is
correct simply because the standard
.I uncompress
does not complain. This generally means that the standard
.I uncompress
does not check its input, and happily generates garbage output.
.PP
Files created by
.I zip
can be uncompressed by gzip only if they have a single member compressed
with the 'deflation' method. This feature is only intended to help
conversion of tar.zip files to the tar.gz format. To extract zip files
with several members, use
.I unzip
instead of
.I gunzip.
.PP
.I zcat
is identical to
.I gunzip
.B \-c.
(On some systems,
.I zcat
may be installed as
.I gzcat
to preserve the original link to
.I compress.)
.I zcat
uncompresses either a list of files on the command line or its
standard input and writes the uncompressed data on standard output.
.I zcat
will uncompress files that have the correct magic number whether
they have a
.B "\&.gz"
suffix or not.
.PP
.I Gzip
uses the Lempel-Ziv algorithm used in
.I zip
and PKZIP.
The amount of compression obtained depends on the size of the
input and the distribution of common substrings.
Typically, text such as source code or English
is reduced by 60\-70%.
Compression is generally much better than that achieved by
LZW (as used in
.IR compress ),
Huffman coding (as used in
.IR pack ),
or adaptive Huffman coding
.RI ( compact ).
.PP
Compression is always performed, even if the compressed file is
slightly larger than the original. The worst case expansion is
a few bytes for the gzip file header, plus 5 bytes every 32K block,
or an expansion ratio of 0.015% for large files. Note that the actual
number of used disk blocks almost never increases.
.I gzip
preserves the mode, ownership and timestamps of files when compressing
or decompressing.
.SH OPTIONS
.TP
.B \-a --ascii
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
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,
concatenate all input files before compressing them.
.TP
.B \-d --decompress --uncompress
Decompress.
.TP
.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
.B \-f
is not given,
and when not running in the background,
.I gzip
prompts to verify whether an existing file should be overwritten.
.TP
.B \-h --help
Display a help screen and quit.
.TP
.B \-L --license
Display the
.I gzip
license.
.TP
.B \-q --quiet
Suppress all warnings.
.TP
.B \-r --recurse
Travel the directory structure recursively. If any of the file names
specified on the command line are directories,
.I gzip
will descend into the directory and compress all the files it finds there
(or decompress them in the case of
.I gunzip
).
.TP
.B \-S .z --suffix .z
Use suffix .z 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
the .z suffix. This was changed to avoid a conflict with
.IR pack "(1)".
.TP
.B \-t --test
Test. Check the compressed file integrity.
.TP
.B \-v --verbose
Verbose. Display the name and percentage reduction for each file compressed.
.TP
.B \-V --version
Version. Display the version number and compilation options then quit.
.TP
.B \-# --fast --best
Regulate the speed of compression using the specified digit
.IR # ,
where
.B \-1
or
.B \-\-fast
indicates the fastest compression method (less compression)
and
.B \-9
or
.B \-\-best
indicates the slowest compression method (optimal compression).
The default compression level is
.BR \-5.
.SH "ADVANCED USAGE"
Multiple compressed files can be concatenated. In this case,
.I gunzip
will extract all members at once. For example:
gzip -c file1 > foo.gz
gzip -c file2 >> foo.gz
Then
gunzip -c foo
is equivalent to
cat file1 file2
In case of damage to one member of a .gz file, other members can
still be recovered (if the damaged member is removed). However,
you can get better compression by compressing all members at once:
cat file1 file2 | gzip > foo.gz
compresses better than
gzip -c file1 file2 > foo.gz
If you want to recompress concatenated files to get better compression, do:
zcat old.gz | gzip > new.gz
.SH "ENVIRONMENT"
The environment variable
.B GZIP
can hold a set of default options for
.I gzip.
These options are interpreted first and can be overwritten by
explicit command line parameters. For example:
for sh: GZIP="-8 -v"; export GZIP
for csh: setenv GZIP "-8 -v"
for MSDOS: set GZIP=-8 -v
On Vax/VMS, the name of the environment variable is GZIP_OPT, to
avoid a conflict with the symbol set for invocation of the program.
.SH "SEE ALSO"
znew(1), zcmp(1), zmore(1), zforce(1), gzexe(1), zip(1), unzip(1), compress(1),
pack(1), compact(1)
.SH "DIAGNOSTICS"
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 ...]
.in +8
Invalid options were specified on the command line.
.in -8
.IR file :
not in gzip format
.in +8
The file specified to
.I gunzip
has not been compressed.
.in -8
.IR file:
Corrupt input. Use zcat to recover some data.
.in +8
The compressed file has been damaged. The data up to the point of failure
can be recovered using
.in +8
zcat file > recover
.in -16
.IR file :
compressed with
.I xx
bits, can only handle
.I yy
bits
.in +8
.I File
was compressed (using LZW) by a program that could deal with
more
.I bits
than the decompress code on this machine.
Recompress the file with gzip, which compresses better and uses
less memory.
.in -8
.IR file :
already has .gz suffix -- no change
.in +8
The file is assumed to be already compressed.
Rename the file and try again.
.in -8
.I file
already exists; do you wish to overwrite (y or n)?
.in +8
Respond "y" if you want the output file to be replaced; "n" if not.
.in -8
gunzip: corrupt input
.in +8
A SIGSEGV violation was detected which usually means that the input file has
been corrupted.
.in -8
.I "xx.x%"
.in +8
Percentage of the input saved by compression.
(Relevant only for
.BR \-v \.)
.in -8
-- not a regular file or directory: ignored
.in +8
When the input file is not a regular file or directory,
(e.g. a symbolic link, socket, FIFO, device file), it is
left unaltered.
.in -8
-- has
.I xx
other links: unchanged
.in +8
The input file has links; it is left unchanged. See
.IR ln "(1)"
for more information. Use the
.B \-f
flag to force compression of multiply-linked files.
.in -8
.SH CAVEATS
When writing compressed data to a tape, it is generally necessary to
pad the output with zeroes up to a block boundary. When the data is
read and the whole block is passed to
.I gunzip
for decompression,
.I gunzip
detects that there is extra trailing garbage after the compressed data
and emits a warning by default. You have to use the --quiet option to
suppress the warning. This option can be set in the
.B GZIP
environment variable as in:
for sh: GZIP="-q" tar xfz /dev/rmt/datn
for csh: (setenv GZIP "-q"; tar xfz /dev/rmt/datn)
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.

1458
gnu/usr.bin/gzip/gzip.c Normal file

File diff suppressed because it is too large Load diff

302
gnu/usr.bin/gzip/gzip.h Normal file
View file

@ -0,0 +1,302 @@
/* gzip.h -- common declarations for all gzip modules
* Copyright (C) 1992-1993 Jean-loup Gailly.
* This is free software; you can redistribute it and/or modify it under the
* terms of the GNU General Public License, see the file COPYING.
*/
#if defined(__STDC__) || defined(PROTO)
# define OF(args) args
#else
# define OF(args) ()
#endif
#ifdef __STDC__
typedef void *voidp;
#else
typedef char *voidp;
#endif
/* I don't like nested includes, but the string functions are used too often */
#if !defined(NO_STRING_H) || defined(STDC_HEADERS)
# include <string.h>
# if !defined(STDC_HEADERS) && !defined(NO_MEMORY_H) && !defined(__GNUC__)
# include <memory.h>
# endif
# define memzero(s, n) memset ((voidp)(s), 0, (n))
#else
# include <strings.h>
# define strchr index
# define strrchr rindex
# define memcpy(d, s, n) bcopy((s), (d), (n))
# define memcmp(s1, s2, n) bcmp((s1), (s2), (n))
# define memzero(s, n) bzero((s), (n))
#endif
#ifndef RETSIGTYPE
# define RETSIGTYPE void
#endif
#define local static
typedef unsigned char uch;
typedef unsigned short ush;
typedef unsigned long ulg;
/* Return codes from gzip */
#define OK 0
#define ERROR 1
#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
extern int method; /* compression method */
/* To save memory for 16 bit systems, some arrays are overlaid between
* the various modules:
* deflate: prev+head window d_buf l_buf outbuf
* unlzw: tab_prefix tab_suffix stack inbuf outbuf
* inflate: window inbuf
* unpack: window inbuf
* For compression, input is done in window[]. For decompression, output
* is done in window except for unlzw.
*/
#ifndef INBUFSIZ
# ifdef SMALL_MEM
# define INBUFSIZ 0x2000 /* input buffer size */
# else
# define INBUFSIZ 0x8000 /* input buffer size */
# endif
#endif
#define INBUF_EXTRA 64 /* required by unlzw() */
#ifndef OUTBUFSIZ
# ifdef SMALL_MEM
# define OUTBUFSIZ 8192 /* output buffer size */
# else
# define OUTBUFSIZ 16384 /* output buffer size */
# endif
#endif
#define OUTBUF_EXTRA 2048 /* required by unlzw() */
#ifndef DIST_BUFSIZE
# ifdef SMALL_MEM
# define DIST_BUFSIZE 0x2000 /* buffer for distances, see trees.c */
# else
# define DIST_BUFSIZE 0x8000 /* buffer for distances, see trees.c */
# endif
#endif
#ifdef DYN_ALLOC
# define EXTERN(type, array) extern type * near array
# define DECLARE(type, array, size) type * near array
# define ALLOC(type, array, size) { \
array = (type*)fcalloc((size_t)(((size)+1L)/2), 2*sizeof(type)); \
if (array == NULL) error("insufficient memory"); \
}
# define FREE(array) {if (array != NULL) fcfree(array), array=NULL;}
#else
# define EXTERN(type, array) extern type array[]
# define DECLARE(type, array, size) type array[size]
# define ALLOC(type, array, size)
# define FREE(array)
#endif
EXTERN(uch, inbuf); /* input buffer */
EXTERN(uch, outbuf); /* output buffer */
EXTERN(ush, d_buf); /* buffer for distances, see trees.c */
EXTERN(uch, window); /* Sliding window and suffix table (unlzw) */
#define tab_suffix window
#ifndef MAXSEG_64K
# define tab_prefix prev /* hash link (see deflate.c) */
# define head (prev+WSIZE) /* hash head (see deflate.c) */
EXTERN(ush, tab_prefix); /* prefix code (see unlzw.c) */
#else
# define tab_prefix0 prev
# define head tab_prefix1
EXTERN(ush, tab_prefix0); /* prefix for even codes */
EXTERN(ush, tab_prefix1); /* prefix for odd codes */
#endif
extern unsigned insize; /* valid bytes in inbuf */
extern unsigned inptr; /* index of next byte to be processed in inbuf */
extern unsigned outcnt; /* bytes in output buffer */
extern long bytes_in; /* number of input bytes */
extern long bytes_out; /* number of output bytes */
extern long header_bytes;/* number of bytes in gzip header */
#define isize bytes_in
/* for compatibility with old zip sources (to be cleaned) */
extern int ifd; /* input file descriptor */
extern int ofd; /* output file descriptor */
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 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 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 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 */
#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
#define COMMENT 0x10 /* bit 4 set: file comment present */
#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */
#define RESERVED 0xC0 /* bit 6,7: reserved */
/* internal file attribute */
#define UNKNOWN 0xffff
#define BINARY 0
#define ASCII 1
#ifndef WSIZE
# define WSIZE 0x8000 /* window size--must be a power of two, and */
#endif /* at least 32K for zip's deflate method */
#define MIN_MATCH 3
#define MAX_MATCH 258
/* The minimum and maximum match lengths */
#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
/* Minimum amount of lookahead, except at the end of the input file.
* See deflate.c for comments about the MIN_MATCH+1.
*/
#define MAX_DIST (WSIZE-MIN_LOOKAHEAD)
/* In order to simplify the code, particularly on 16 bit machines, match
* distances are limited to MAX_DIST instead of WSIZE.
*/
extern int decrypt; /* flag to turn on decryption */
extern int exit_code; /* program exit code */
extern int verbose; /* be verbose (-v) */
extern int quiet; /* be quiet (-q) */
extern int level; /* compression level */
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())
/* put_byte is used for the compressed output, put_ubyte for the
* uncompressed output. However unlzw() uses window for its
* suffix table instead of its output buffer, so it does not use put_ubyte
* (to be cleaned up).
*/
#define put_byte(c) {outbuf[outcnt++]=(uch)(c); if (outcnt==OUTBUFSIZ)\
flush_outbuf();}
#define put_ubyte(c) {window[outcnt++]=(uch)(c); if (outcnt==WSIZE)\
flush_window();}
/* Output a 16 bit value, lsb first */
#define put_short(w) \
{ if (outcnt < OUTBUFSIZ-2) { \
outbuf[outcnt++] = (uch) ((w) & 0xff); \
outbuf[outcnt++] = (uch) ((ush)(w) >> 8); \
} else { \
put_byte((uch)((w) & 0xff)); \
put_byte((uch)((ush)(w) >> 8)); \
} \
}
/* Output a 32 bit value to the bit stream, lsb first */
#define put_long(n) { \
put_short((n) & 0xffff); \
put_short(((ulg)(n)) >> 16); \
}
#define seekable() 0 /* force sequential output */
#define translate_eol 0 /* no option -a yet */
#define tolow(c) (isupper(c) ? (c)-'A'+'a' : (c)) /* force to lower case */
/* Macros for getting two-byte and four-byte header values */
#define SH(p) ((ush)(uch)((p)[0]) | ((ush)(uch)((p)[1]) << 8))
#define LG(p) ((ulg)(SH(p)) | ((ulg)(SH((p)+2)) << 16))
/* Diagnostic functions */
#ifdef DEBUG
# define Assert(cond,msg) {if(!(cond)) error(msg);}
# define Trace(x) fprintf x
# define Tracev(x) {if (verbose) fprintf x ;}
# define Tracevv(x) {if (verbose>1) fprintf x ;}
# define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
#else
# define Assert(cond,msg)
# define Trace(x)
# define Tracev(x)
# define Tracevv(x)
# define Tracec(c,x)
# define Tracecv(c,x)
#endif
#define WARN(msg) {if (!quiet) fprintf msg ; \
if (exit_code == OK) exit_code = WARNING;}
/* in zip.c: */
extern int zip OF((int in, int out));
extern int file_read OF((char *buf, unsigned size));
/* in unzip.c */
extern int unzip OF((int in, int out));
extern int check_zipfile OF((int in));
/* in unpack.c */
extern int unpack OF((int in, int out));
/* in gzip.c */
RETSIGTYPE abort_gzip OF((void));
/* in deflate.c */
void lm_init OF((int pack_level, ush *flags));
ulg deflate OF((void));
/* in trees.c */
void ct_init OF((ush *attr, int *method));
int ct_tally OF((int dist, int lc));
ulg flush_block OF((char *buf, ulg stored_len, int eof));
/* in bits.c */
void bi_init OF((file_t zipfile));
void send_bits OF((int value, int length));
unsigned bi_reverse OF((unsigned value, int length));
void bi_windup OF((void));
void copy_block OF((char *buf, unsigned len, int header));
extern int (*read_buf) OF((char *buf, unsigned size));
/* in util.c: */
extern ulg updcrc OF((uch *s, unsigned n));
extern void clear_bufs OF((void));
extern int fill_inbuf OF((void));
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 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 voidp xmalloc OF((unsigned int size));
/* in inflate.c */
extern int inflate OF((void));

954
gnu/usr.bin/gzip/inflate.c Normal file
View file

@ -0,0 +1,954 @@
/* inflate.c -- Not copyrighted 1992 by Mark Adler
version c10p1, 10 January 1993 */
/* You can do whatever you like with this source file, though I would
prefer that if you modify it and redistribute it that you include
comments to that effect with your name and the date. Thank you.
[The history has been moved to the file ChangeLog.]
*/
/*
Inflate deflated (PKZIP's method 8 compressed) data. The compression
method searches for as much of the current string of bytes (up to a
length of 258) in the previous 32K bytes. If it doesn't find any
matches (of at least length 3), it codes the next byte. Otherwise, it
codes the length of the matched string and its distance backwards from
the current position. There is a single Huffman code that codes both
single bytes (called "literals") and match lengths. A second Huffman
code codes the distance information, which follows a length code. Each
length or distance code actually represents a base value and a number
of "extra" (sometimes zero) bits to get to add to the base value. At
the end of each deflated block is a special end-of-block (EOB) literal/
length code. The decoding process is basically: get a literal/length
code; if EOB then done; if a literal, emit the decoded byte; if a
length then get the distance and emit the referred-to bytes from the
sliding window of previously emitted data.
There are (currently) three kinds of inflate blocks: stored, fixed, and
dynamic. The compressor deals with some chunk of data at a time, and
decides which method to use on a chunk-by-chunk basis. A chunk might
typically be 32K or 64K. If the chunk is uncompressible, then the
"stored" method is used. In this case, the bytes are simply stored as
is, eight bits per byte, with none of the above coding. The bytes are
preceded by a count, since there is no longer an EOB code.
If the data is compressible, then either the fixed or dynamic methods
are used. In the dynamic method, the compressed data is preceded by
an encoding of the literal/length and distance Huffman codes that are
to be used to decode this block. The representation is itself Huffman
coded, and so is preceded by a description of that code. These code
descriptions take up a little space, and so for small blocks, there is
a predefined set of codes, called the fixed codes. The fixed method is
used if the block codes up smaller that way (usually for quite small
chunks), otherwise the dynamic method is used. In the latter case, the
codes are customized to the probabilities in the current block, and so
can code it much better than the pre-determined fixed codes.
The Huffman codes themselves are decoded using a mutli-level table
lookup, in order to maximize the speed of decoding plus the speed of
building the decoding tables. See the comments below that precede the
lbits and dbits tuning parameters.
*/
/*
Notes beyond the 1.93a appnote.txt:
1. Distance pointers never point before the beginning of the output
stream.
2. Distance pointers can point back across blocks, up to 32k away.
3. There is an implied maximum of 7 bits for the bit length table and
15 bits for the actual data.
4. If only one code exists, then it is encoded using one bit. (Zero
would be more efficient, but perhaps a little confusing.) If two
codes exist, they are coded using one bit each (0 and 1).
5. There is no way of sending zero distance codes--a dummy must be
sent if there are none. (History: a pre 2.0 version of PKZIP would
store blocks with no distance codes, but this was discovered to be
too harsh a criterion.) Valid only for 1.93a. 2.04c does allow
zero distance codes, which is sent as one code of zero bits in
length.
6. There are up to 286 literal/length codes. Code 256 represents the
end-of-block. Note however that the static length tree defines
288 codes just to fill out the Huffman codes. Codes 286 and 287
cannot be used though, since there is no length base or extra bits
defined for them. Similarly, there are up to 30 distance codes.
However, static trees define 32 codes (all 5 bits) to fill out the
Huffman codes, but the last two had better not show up in the data.
7. Unzip can check dynamic Huffman blocks for complete code sets.
The exception is that a single code would not be complete (see #4).
8. The five bits following the block type is really the number of
literal codes sent minus 257.
9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits
(1+6+6). Therefore, to output three times the length, you output
three codes (1+1+1), whereas to output four times the same length,
you only need two codes (1+3). Hmm.
10. In the tree reconstruction algorithm, Code = Code + Increment
only if BitLength(i) is not zero. (Pretty obvious.)
11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19)
12. Note: length code 284 can represent 227-258, but length code 285
really is 258. The last length deserves its own, short code
since it gets used a lot in very redundant files. The length
258 is special since 258 - 3 (the min match length) is 255.
13. The literal/length and distance code bit lengths are read as a
single stream of lengths. It is possible (and advantageous) for
a repeat code (16, 17, or 18) to go across the boundary between
the two sets of lengths.
*/
#ifndef lint
static char rcsid[] = "$Id: inflate.c,v 0.13 1993/04/26 14:18:22 jloup Exp $";
#endif
#include <stdio.h>
#include <sys/types.h>
#include "tailor.h"
#if defined(STDC_HEADERS) || !defined(NO_STDLIB_H)
# include <stdlib.h>
#endif
#include "gzip.h"
#define slide window
/* Huffman code lookup table entry--this entry is four bytes for machines
that have 16-bit pointers (e.g. PC's in the small or medium model).
Valid extra bits are 0..13. e == 15 is EOB (end of block), e == 16
means that v is a literal, 16 < e < 32 means that v is a pointer to
the next table, which codes e - 16 bits, and lastly e == 99 indicates
an unused code. If a code with e == 99 is looked up, this implies an
error in the data. */
struct huft {
uch e; /* number of extra bits or operation */
uch b; /* number of bits in this code or subcode */
union {
ush n; /* literal, length base, or distance base */
struct huft *t; /* pointer to next level of table */
} v;
};
/* Function prototypes */
int huft_build OF((unsigned *, unsigned, unsigned, ush *, ush *,
struct huft **, int *));
int huft_free OF((struct huft *));
int inflate_codes OF((struct huft *, struct huft *, int, int));
int inflate_stored OF((void));
int inflate_fixed OF((void));
int inflate_dynamic OF((void));
int inflate_block OF((int *));
int inflate OF((void));
/* The inflate algorithm uses a sliding 32K byte window on the uncompressed
stream to find repeated byte strings. This is implemented here as a
circular buffer. The index is updated simply by incrementing and then
and'ing with 0x7fff (32K-1). */
/* It is left to other modules to supply the 32K area. It is assumed
to be usable as if it were declared "uch slide[32768];" or as just
"uch *slide;" and then malloc'ed in the latter case. The definition
must be in unzip.h, included above. */
/* unsigned wp; current position in slide */
#define wp outcnt
#define flush_output(w) (wp=(w),flush_window())
/* Tables for deflate from PKZIP's appnote.txt. */
static unsigned border[] = { /* Order of the bit length code lengths */
16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
static ush cplens[] = { /* Copy lengths for literal codes 257..285 */
3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
/* note: see note #13 above about the 258 in this list. */
static ush cplext[] = { /* Extra bits for literal codes 257..285 */
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99}; /* 99==invalid */
static ush cpdist[] = { /* Copy offsets for distance codes 0..29 */
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
8193, 12289, 16385, 24577};
static ush cpdext[] = { /* Extra bits for distance codes */
0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
12, 12, 13, 13};
/* Macros for inflate() bit peeking and grabbing.
The usage is:
NEEDBITS(j)
x = b & mask_bits[j];
DUMPBITS(j)
where NEEDBITS makes sure that b has at least j bits in it, and
DUMPBITS removes the bits from b. The macros use the variable k
for the number of bits in b. Normally, b and k are register
variables for speed, and are initialized at the beginning of a
routine that uses these macros from a global bit buffer and count.
If we assume that EOB will be the longest code, then we will never
ask for bits with NEEDBITS that are beyond the end of the stream.
So, NEEDBITS should not read any more bytes than are needed to
meet the request. Then no bytes need to be "returned" to the buffer
at the end of the last block.
However, this assumption is not true for fixed blocks--the EOB code
is 7 bits, but the other literal/length codes can be 8 or 9 bits.
(The EOB code is shorter than other codes because fixed blocks are
generally short. So, while a block always has an EOB, many other
literal/length codes have a significantly lower probability of
showing up at all.) However, by making the first table have a
lookup of seven bits, the EOB code will be found in that first
lookup, and so will not require that too many bits be pulled from
the stream.
*/
ulg bb; /* bit buffer */
unsigned bk; /* bits in bit buffer */
ush mask_bits[] = {
0x0000,
0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
};
#ifdef CRYPT
uch cc;
# define NEXTBYTE() \
(decrypt ? (cc = get_byte(), zdecode(cc), cc) : get_byte())
#else
# define NEXTBYTE() (uch)get_byte()
#endif
#define NEEDBITS(n) {while(k<(n)){b|=((ulg)NEXTBYTE())<<k;k+=8;}}
#define DUMPBITS(n) {b>>=(n);k-=(n);}
/*
Huffman code decoding is performed using a multi-level table lookup.
The fastest way to decode is to simply build a lookup table whose
size is determined by the longest code. However, the time it takes
to build this table can also be a factor if the data being decoded
is not very long. The most common codes are necessarily the
shortest codes, so those codes dominate the decoding time, and hence
the speed. The idea is you can have a shorter table that decodes the
shorter, more probable codes, and then point to subsidiary tables for
the longer codes. The time it costs to decode the longer codes is
then traded against the time it takes to make longer tables.
This results of this trade are in the variables lbits and dbits
below. lbits is the number of bits the first level table for literal/
length codes can decode in one step, and dbits is the same thing for
the distance codes. Subsequent tables are also less than or equal to
those sizes. These values may be adjusted either when all of the
codes are shorter than that, in which case the longest code length in
bits is used, or when the shortest code is *longer* than the requested
table size, in which case the length of the shortest code in bits is
used.
There are two different values for the two tables, since they code a
different number of possibilities each. The literal/length table
codes 286 possible values, or in a flat code, a little over eight
bits. The distance table codes 30 possible values, or a little less
than five bits, flat. The optimum values for speed end up being
about one bit more than those, so lbits is 8+1 and dbits is 5+1.
The optimum values may differ though from machine to machine, and
possibly even between compilers. Your mileage may vary.
*/
int lbits = 9; /* bits in base literal/length lookup table */
int dbits = 6; /* bits in base distance lookup table */
/* If BMAX needs to be larger than 16, then h and x[] should be ulg. */
#define BMAX 16 /* maximum bit length of any code (16 for explode) */
#define N_MAX 288 /* maximum number of codes in any set */
unsigned hufts; /* track memory usage */
int huft_build(b, n, s, d, e, t, m)
unsigned *b; /* code lengths in bits (all assumed <= BMAX) */
unsigned n; /* number of codes (assumed <= N_MAX) */
unsigned s; /* number of simple-valued codes (0..s-1) */
ush *d; /* list of base values for non-simple codes */
ush *e; /* list of extra bits for non-simple codes */
struct huft **t; /* result: starting table */
int *m; /* maximum lookup bits, returns actual */
/* Given a list of code lengths and a maximum table size, make a set of
tables to decode that set of codes. Return zero on success, one if
the given code set is incomplete (the tables are still built in this
case), two if the input is invalid (all zero length codes or an
oversubscribed set of lengths), and three if not enough memory. */
{
unsigned a; /* counter for codes of length k */
unsigned c[BMAX+1]; /* bit length count table */
unsigned f; /* i repeats in table every f entries */
int g; /* maximum code length */
int h; /* table level */
register unsigned i; /* counter, current code */
register unsigned j; /* counter */
register int k; /* number of bits in current code */
int l; /* bits per table (returned in m) */
register unsigned *p; /* pointer into c[], b[], or v[] */
register struct huft *q; /* points to current table */
struct huft r; /* table entry for structure assignment */
struct huft *u[BMAX]; /* table stack */
unsigned v[N_MAX]; /* values in order of bit length */
register int w; /* bits before this table == (l * h) */
unsigned x[BMAX+1]; /* bit offsets, then code stack */
unsigned *xp; /* pointer into x */
int y; /* number of dummy codes added */
unsigned z; /* number of entries in current table */
/* Generate counts for each bit length */
memzero(c, sizeof(c));
p = b; i = n;
do {
Tracecv(*p, (stderr, (n-i >= ' ' && n-i <= '~' ? "%c %d\n" : "0x%x %d\n"),
n-i, *p));
c[*p++]++; /* assume all entries <= BMAX */
} while (--i);
if (c[0] == n) /* null input--all zero length codes */
{
*t = (struct huft *)NULL;
*m = 0;
return 0;
}
/* Find minimum and maximum length, bound *m by those */
l = *m;
for (j = 1; j <= BMAX; j++)
if (c[j])
break;
k = j; /* minimum code length */
if ((unsigned)l < j)
l = j;
for (i = BMAX; i; i--)
if (c[i])
break;
g = i; /* maximum code length */
if ((unsigned)l > i)
l = i;
*m = l;
/* Adjust last length count to fill out codes, if needed */
for (y = 1 << j; j < i; j++, y <<= 1)
if ((y -= c[j]) < 0)
return 2; /* bad input: more codes than bits */
if ((y -= c[i]) < 0)
return 2;
c[i] += y;
/* Generate starting offsets into the value table for each length */
x[1] = j = 0;
p = c + 1; xp = x + 2;
while (--i) { /* note that i == g from above */
*xp++ = (j += *p++);
}
/* Make a table of values in order of bit lengths */
p = b; i = 0;
do {
if ((j = *p++) != 0)
v[x[j]++] = i;
} while (++i < n);
/* Generate the Huffman codes and for each, make the table entries */
x[0] = i = 0; /* first Huffman code is zero */
p = v; /* grab values in bit order */
h = -1; /* no tables yet--level -1 */
w = -l; /* bits decoded == (l * h) */
u[0] = (struct huft *)NULL; /* just to keep compilers happy */
q = (struct huft *)NULL; /* ditto */
z = 0; /* ditto */
/* go through the bit lengths (k already is bits in shortest code) */
for (; k <= g; k++)
{
a = c[k];
while (a--)
{
/* here i is the Huffman code of length k bits for value *p */
/* make tables up to required level */
while (k > w + l)
{
h++;
w += l; /* previous table always l bits */
/* compute minimum size table less than or equal to l bits */
z = (z = g - w) > (unsigned)l ? l : z; /* upper limit on table size */
if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */
{ /* too few codes for k-w bit table */
f -= a + 1; /* deduct codes from patterns left */
xp = c + k;
while (++j < z) /* try smaller tables up to z bits */
{
if ((f <<= 1) <= *++xp)
break; /* enough codes to use up j bits */
f -= *xp; /* else deduct codes from patterns */
}
}
z = 1 << j; /* table entries for j-bit table */
/* allocate and link in new table */
if ((q = (struct huft *)malloc((z + 1)*sizeof(struct huft))) ==
(struct huft *)NULL)
{
if (h)
huft_free(u[0]);
return 3; /* not enough memory */
}
hufts += z + 1; /* track memory usage */
*t = q + 1; /* link to list for huft_free() */
*(t = &(q->v.t)) = (struct huft *)NULL;
u[h] = ++q; /* table starts after link */
/* connect to last table, if there is one */
if (h)
{
x[h] = i; /* save pattern for backing up */
r.b = (uch)l; /* bits to dump before this table */
r.e = (uch)(16 + j); /* bits in this table */
r.v.t = q; /* pointer to this table */
j = i >> (w - l); /* (get around Turbo C bug) */
u[h-1][j] = r; /* connect to last table */
}
}
/* set up table entry in r */
r.b = (uch)(k - w);
if (p >= v + n)
r.e = 99; /* out of values--invalid code */
else if (*p < s)
{
r.e = (uch)(*p < 256 ? 16 : 15); /* 256 is end-of-block code */
r.v.n = (ush)(*p); /* simple code is just the value */
p++; /* one compiler does not like *p++ */
}
else
{
r.e = (uch)e[*p - s]; /* non-simple--look up in lists */
r.v.n = d[*p++ - s];
}
/* fill code-like entries with r */
f = 1 << (k - w);
for (j = i >> w; j < z; j += f)
q[j] = r;
/* backwards increment the k-bit code i */
for (j = 1 << (k - 1); i & j; j >>= 1)
i ^= j;
i ^= j;
/* backup over finished tables */
while ((i & ((1 << w) - 1)) != x[h])
{
h--; /* don't need to update q */
w -= l;
}
}
}
/* Return true (1) if we were given an incomplete table */
return y != 0 && g != 1;
}
int huft_free(t)
struct huft *t; /* table to free */
/* Free the malloc'ed tables built by huft_build(), which makes a linked
list of the tables it made, with the links in a dummy first entry of
each table. */
{
register struct huft *p, *q;
/* Go through linked list, freeing from the malloced (t[-1]) address. */
p = t;
while (p != (struct huft *)NULL)
{
q = (--p)->v.t;
free((char*)p);
p = q;
}
return 0;
}
int inflate_codes(tl, td, bl, bd)
struct huft *tl, *td; /* literal/length and distance decoder tables */
int bl, bd; /* number of bits decoded by tl[] and td[] */
/* inflate (decompress) the codes in a deflated (compressed) block.
Return an error code or zero if it all goes ok. */
{
register unsigned e; /* table entry flag/number of extra bits */
unsigned n, d; /* length and index for copy */
unsigned w; /* current window position */
struct huft *t; /* pointer to table entry */
unsigned ml, md; /* masks for bl and bd bits */
register ulg b; /* bit buffer */
register unsigned k; /* number of bits in bit buffer */
/* make local copies of globals */
b = bb; /* initialize bit buffer */
k = bk;
w = wp; /* initialize window position */
/* inflate the coded data */
ml = mask_bits[bl]; /* precompute masks for speed */
md = mask_bits[bd];
for (;;) /* do until end of block */
{
NEEDBITS((unsigned)bl)
if ((e = (t = tl + ((unsigned)b & ml))->e) > 16)
do {
if (e == 99)
return 1;
DUMPBITS(t->b)
e -= 16;
NEEDBITS(e)
} while ((e = (t = t->v.t + ((unsigned)b & mask_bits[e]))->e) > 16);
DUMPBITS(t->b)
if (e == 16) /* then it's a literal */
{
slide[w++] = (uch)t->v.n;
Tracevv((stderr, "%c", slide[w-1]));
if (w == WSIZE)
{
flush_output(w);
w = 0;
}
}
else /* it's an EOB or a length */
{
/* exit if end of block */
if (e == 15)
break;
/* get length of block to copy */
NEEDBITS(e)
n = t->v.n + ((unsigned)b & mask_bits[e]);
DUMPBITS(e);
/* decode distance of block to copy */
NEEDBITS((unsigned)bd)
if ((e = (t = td + ((unsigned)b & md))->e) > 16)
do {
if (e == 99)
return 1;
DUMPBITS(t->b)
e -= 16;
NEEDBITS(e)
} while ((e = (t = t->v.t + ((unsigned)b & mask_bits[e]))->e) > 16);
DUMPBITS(t->b)
NEEDBITS(e)
d = w - t->v.n - ((unsigned)b & mask_bits[e]);
DUMPBITS(e)
Tracevv((stderr,"\\[%d,%d]", w-d, n));
/* do the copy */
do {
n -= (e = (e = WSIZE - ((d &= WSIZE-1) > w ? d : w)) > n ? n : e);
#if !defined(NOMEMCPY) && !defined(DEBUG)
if (w - d >= e) /* (this test assumes unsigned comparison) */
{
memcpy(slide + w, slide + d, e);
w += e;
d += e;
}
else /* do it slow to avoid memcpy() overlap */
#endif /* !NOMEMCPY */
do {
slide[w++] = slide[d++];
Tracevv((stderr, "%c", slide[w-1]));
} while (--e);
if (w == WSIZE)
{
flush_output(w);
w = 0;
}
} while (n);
}
}
/* restore the globals from the locals */
wp = w; /* restore global window pointer */
bb = b; /* restore global bit buffer */
bk = k;
/* done */
return 0;
}
int inflate_stored()
/* "decompress" an inflated type 0 (stored) block. */
{
unsigned n; /* number of bytes in block */
unsigned w; /* current window position */
register ulg b; /* bit buffer */
register unsigned k; /* number of bits in bit buffer */
/* make local copies of globals */
b = bb; /* initialize bit buffer */
k = bk;
w = wp; /* initialize window position */
/* go to byte boundary */
n = k & 7;
DUMPBITS(n);
/* get the length and its complement */
NEEDBITS(16)
n = ((unsigned)b & 0xffff);
DUMPBITS(16)
NEEDBITS(16)
if (n != (unsigned)((~b) & 0xffff))
return 1; /* error in compressed data */
DUMPBITS(16)
/* read and output the compressed data */
while (n--)
{
NEEDBITS(8)
slide[w++] = (uch)b;
if (w == WSIZE)
{
flush_output(w);
w = 0;
}
DUMPBITS(8)
}
/* restore the globals from the locals */
wp = w; /* restore global window pointer */
bb = b; /* restore global bit buffer */
bk = k;
return 0;
}
int inflate_fixed()
/* decompress an inflated type 1 (fixed Huffman codes) block. We should
either replace this with a custom decoder, or at least precompute the
Huffman tables. */
{
int i; /* temporary variable */
struct huft *tl; /* literal/length code table */
struct huft *td; /* distance code table */
int bl; /* lookup bits for tl */
int bd; /* lookup bits for td */
unsigned l[288]; /* length list for huft_build */
/* set up literal table */
for (i = 0; i < 144; i++)
l[i] = 8;
for (; i < 256; i++)
l[i] = 9;
for (; i < 280; i++)
l[i] = 7;
for (; i < 288; i++) /* make a complete, but wrong code set */
l[i] = 8;
bl = 7;
if ((i = huft_build(l, 288, 257, cplens, cplext, &tl, &bl)) != 0)
return i;
/* set up distance table */
for (i = 0; i < 30; i++) /* make an incomplete code set */
l[i] = 5;
bd = 5;
if ((i = huft_build(l, 30, 0, cpdist, cpdext, &td, &bd)) > 1)
{
huft_free(tl);
return i;
}
/* decompress until an end-of-block code */
if (inflate_codes(tl, td, bl, bd))
return 1;
/* free the decoding tables, return */
huft_free(tl);
huft_free(td);
return 0;
}
int inflate_dynamic()
/* decompress an inflated type 2 (dynamic Huffman codes) block. */
{
int i; /* temporary variables */
unsigned j;
unsigned l; /* last length */
unsigned m; /* mask for bit lengths table */
unsigned n; /* number of lengths to get */
struct huft *tl; /* literal/length code table */
struct huft *td; /* distance code table */
int bl; /* lookup bits for tl */
int bd; /* lookup bits for td */
unsigned nb; /* number of bit length codes */
unsigned nl; /* number of literal/length codes */
unsigned nd; /* number of distance codes */
#ifdef PKZIP_BUG_WORKAROUND
unsigned ll[288+32]; /* literal/length and distance code lengths */
#else
unsigned ll[286+30]; /* literal/length and distance code lengths */
#endif
register ulg b; /* bit buffer */
register unsigned k; /* number of bits in bit buffer */
/* make local bit buffer */
b = bb;
k = bk;
/* read in table lengths */
NEEDBITS(5)
nl = 257 + ((unsigned)b & 0x1f); /* number of literal/length codes */
DUMPBITS(5)
NEEDBITS(5)
nd = 1 + ((unsigned)b & 0x1f); /* number of distance codes */
DUMPBITS(5)
NEEDBITS(4)
nb = 4 + ((unsigned)b & 0xf); /* number of bit length codes */
DUMPBITS(4)
#ifdef PKZIP_BUG_WORKAROUND
if (nl > 288 || nd > 32)
#else
if (nl > 286 || nd > 30)
#endif
return 1; /* bad lengths */
/* read in bit-length-code lengths */
for (j = 0; j < nb; j++)
{
NEEDBITS(3)
ll[border[j]] = (unsigned)b & 7;
DUMPBITS(3)
}
for (; j < 19; j++)
ll[border[j]] = 0;
/* build decoding table for trees--single level, 7 bit lookup */
bl = 7;
if ((i = huft_build(ll, 19, 19, NULL, NULL, &tl, &bl)) != 0)
{
if (i == 1)
huft_free(tl);
return i; /* incomplete code set */
}
/* read in literal and distance code lengths */
n = nl + nd;
m = mask_bits[bl];
i = l = 0;
while ((unsigned)i < n)
{
NEEDBITS((unsigned)bl)
j = (td = tl + ((unsigned)b & m))->b;
DUMPBITS(j)
j = td->v.n;
if (j < 16) /* length of code in bits (0..15) */
ll[i++] = l = j; /* save last length in l */
else if (j == 16) /* repeat last length 3 to 6 times */
{
NEEDBITS(2)
j = 3 + ((unsigned)b & 3);
DUMPBITS(2)
if ((unsigned)i + j > n)
return 1;
while (j--)
ll[i++] = l;
}
else if (j == 17) /* 3 to 10 zero length codes */
{
NEEDBITS(3)
j = 3 + ((unsigned)b & 7);
DUMPBITS(3)
if ((unsigned)i + j > n)
return 1;
while (j--)
ll[i++] = 0;
l = 0;
}
else /* j == 18: 11 to 138 zero length codes */
{
NEEDBITS(7)
j = 11 + ((unsigned)b & 0x7f);
DUMPBITS(7)
if ((unsigned)i + j > n)
return 1;
while (j--)
ll[i++] = 0;
l = 0;
}
}
/* free decoding table for trees */
huft_free(tl);
/* restore the global bit buffer */
bb = b;
bk = k;
/* build the decoding tables for literal/length and distance codes */
bl = lbits;
if ((i = huft_build(ll, nl, 257, cplens, cplext, &tl, &bl)) != 0)
{
if (i == 1) {
fprintf(stderr, " incomplete literal tree\n");
huft_free(tl);
}
return i; /* incomplete code set */
}
bd = dbits;
if ((i = huft_build(ll + nl, nd, 0, cpdist, cpdext, &td, &bd)) != 0)
{
if (i == 1) {
fprintf(stderr, " incomplete distance tree\n");
#ifdef PKZIP_BUG_WORKAROUND
i = 0;
}
#else
huft_free(td);
}
huft_free(tl);
return i; /* incomplete code set */
#endif
}
/* decompress until an end-of-block code */
if (inflate_codes(tl, td, bl, bd))
return 1;
/* free the decoding tables, return */
huft_free(tl);
huft_free(td);
return 0;
}
int inflate_block(e)
int *e; /* last block flag */
/* decompress an inflated block */
{
unsigned t; /* block type */
register ulg b; /* bit buffer */
register unsigned k; /* number of bits in bit buffer */
/* make local bit buffer */
b = bb;
k = bk;
/* read in last block bit */
NEEDBITS(1)
*e = (int)b & 1;
DUMPBITS(1)
/* read in block type */
NEEDBITS(2)
t = (unsigned)b & 3;
DUMPBITS(2)
/* restore the global bit buffer */
bb = b;
bk = k;
/* inflate that block type */
if (t == 2)
return inflate_dynamic();
if (t == 0)
return inflate_stored();
if (t == 1)
return inflate_fixed();
/* bad block type */
return 2;
}
int inflate()
/* decompress an inflated entry */
{
int e; /* last block flag */
int r; /* result code */
unsigned h; /* maximum struct huft's malloc'ed */
/* initialize window, bit buffer */
wp = 0;
bk = 0;
bb = 0;
/* decompress until the last block */
h = 0;
do {
hufts = 0;
if ((r = inflate_block(&e)) != 0)
return r;
if (hufts > h)
h = hufts;
} while (!e);
/* Undo too much lookahead. The next read will be byte aligned so we
* can discard unused bits in the last meaningful byte.
*/
while (bk >= 8) {
bk -= 8;
inptr--;
}
/* flush out slide */
flush_output(wp);
/* return success */
#ifdef DEBUG
fprintf(stderr, "<%u> ", h);
#endif /* DEBUG */
return 0;
}

27
gnu/usr.bin/gzip/lzw.c Normal file
View file

@ -0,0 +1,27 @@
/* lzw.c -- compress files in LZW format.
* This is a dummy version avoiding patent problems.
*/
#ifndef lint
static char rcsid[] = "$Id: lzw.c,v 0.8 1993/04/25 08:09:58 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. */
int lzw(in, out)
int in, out;
{
if (msg_done) return ERROR;
msg_done = 1;
fprintf(stderr,"output in compress .Z format not supported\n");
in++, out++; /* avoid warnings on unused variables */
exit_code = ERROR;
return ERROR;
}

42
gnu/usr.bin/gzip/lzw.h Normal file
View file

@ -0,0 +1,42 @@
/* lzw.h -- define the lzw functions.
* Copyright (C) 1992-1993 Jean-loup Gailly.
* This is free software; you can redistribute it and/or modify it under the
* terms of the GNU General Public License, see the file COPYING.
*/
#if !defined(OF) && defined(lint)
# include "gzip.h"
#endif
#ifndef BITS
# define BITS 16
#endif
#define INIT_BITS 9 /* Initial number of bits per code */
#define LZW_MAGIC "\037\235" /* Magic header for lzw files, 1F 9D */
#define BIT_MASK 0x1f /* Mask for 'number of compression bits' */
/* Mask 0x20 is reserved to mean a fourth header byte, and 0x40 is free.
* It's a pity that old uncompress does not check bit 0x20. That makes
* extension of the format actually undesirable because old compress
* would just crash on the new format instead of giving a meaningful
* error message. It does check the number of bits, but it's more
* helpful to say "unsupported format, get a new version" than
* "can only handle 16 bits".
*/
#define BLOCK_MODE 0x80
/* Block compression: if table is full and compression rate is dropping,
* clear the dictionary.
*/
#define LZW_RESERVED 0x60 /* reserved bits */
#define CLEAR 256 /* flush the dictionary */
#define FIRST (CLEAR+1) /* first free entry */
extern int maxbits; /* max bits per code for LZW */
extern int block_mode; /* block compress mode -C compatible with 2.0 */
extern int lzw OF((int in, int out));
extern int unlzw OF((int in, int out));

379
gnu/usr.bin/gzip/match.S Normal file
View file

@ -0,0 +1,379 @@
/* match.s -- optional optimized asm version of longest match in deflate.c
* Copyright (C) 1992-1993 Jean-loup Gailly
* This is free software; you can redistribute it and/or modify it under the
* terms of the GNU General Public License, see the file COPYING.
*
* The 68020 version has been written by Francesco Potorti` <pot@cnuce.cnr.it>
* with adaptations by Carsten Steger <stegerc@informatik.tu-muenchen.de>,
* Andreas Schwab <schwab@lamothe.informatik.uni-dortmund.de> and
* Kristoffer Eriksson <ske@pkmab.se>
*/
/* $Id: match.S,v 0.13 1993/05/24 12:03:03 jloup Exp $ */
/* Preprocess with -DNO_UNDERLINE if your C compiler does not prefix
* external symbols with an underline character '_'.
*/
#ifdef NO_UNDERLINE
# define _prev prev
# define _window window
# define _match_start match_start
# define _prev_length prev_length
# define _good_match good_match
# define _nice_match nice_match
# define _strstart strstart
# define _max_chain_length max_chain_length
# define _match_init match_init
# define _longest_match longest_match
#endif
#ifdef DYN_ALLOC
error: DYN_ALLOC not yet supported in match.s
#endif
#if defined(i386) || defined(_I386)
/* This version is for 386 Unix or OS/2 in 32 bit mode.
* Warning: it uses the AT&T syntax: mov source,dest
* This file is only optional. If you want to force the C version,
* add -DNO_ASM to CFLAGS in Makefile and set OBJA to an empty string.
* If you have reduced WSIZE in gzip.h, then change its value below.
* This version assumes static allocation of the arrays (-DDYN_ALLOC not used).
*/
.file "match.S"
#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
.globl _match_init
.globl _longest_match
.text
_match_init:
ret
/*-----------------------------------------------------------------------
* Set match_start to the longest match starting at the given string and
* return its length. Matches shorter or equal to prev_length are discarded,
* in which case the result is equal to prev_length and match_start is
* garbage.
* IN assertions: cur_match is the head of the hash chain for the current
* string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
*/
_longest_match: /* int longest_match(cur_match) */
#define cur_match 20(%esp)
/* return address */ /* esp+16 */
push %ebp /* esp+12 */
push %edi /* esp+8 */
push %esi /* esp+4 */
push %ebx /* esp */
/*
* match equ esi
* scan equ edi
* chain_length equ ebp
* best_len equ ebx
* limit equ edx
*/
mov cur_match,%esi
mov _max_chain_length,%ebp /* chain_length = max_chain_length */
mov _strstart,%edi
mov %edi,%edx
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) */
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] */
cmp _good_match,%ebx /* do we have a good match already? */
jb do_scan
shr $2,%ebp /* chain_length >>= 2 */
jmp do_scan
.align 4
long_loop:
/* at this point, edi == scan+2, esi == cur_match */
movw -3(%ebx,%edi),%ax /* ax = scan[best_len-1..best_len] */
movw -2(%edi),%cx /* cx = scan[0..1] */
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
movw _prev(%esi,%esi),%si /* cur_match = prev[cur_match] */
/* top word of esi is still 0 */
cmp %edx,%esi /* cur_match <= limit ? */
jbe the_end
dec %ebp /* --chain_length */
jz the_end
do_scan:
cmpw _window-1(%ebx,%esi),%ax/* check match at best_len-1 */
jne short_loop
cmpw _window(%esi),%cx /* check min_match_length match */
jne short_loop
lea _window+2(%esi),%esi /* si = match */
mov %edi,%eax /* ax = scan+2 */
mov $ MAX_MATCH2,%ecx /* scan for at most MAX_MATCH bytes */
rep; cmpsw /* loop until mismatch */
je maxmatch /* match of length MAX_MATCH? */
mismatch:
movb -2(%edi),%cl /* mismatch on first or second byte? */
subb -2(%esi),%cl /* cl = 0 if first bytes equal */
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 */
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 ? */
jle long_loop
mov %esi,_match_start /* match_start = cur_match */
mov %eax,%ebx /* ebx = best_len = len */
cmp _nice_match,%eax /* len >= nice_match ? */
jl long_loop
the_end:
mov %ebx,%eax /* result = eax = best_len */
pop %ebx
pop %esi
pop %edi
pop %ebp
ret
maxmatch:
cmpsb
jmp mismatch
#else
/* ======================== 680x0 version ================================= */
#if defined(m68k)||defined(mc68k)||defined(__mc68000__)||defined(__MC68000__)
# ifndef mc68000
# define mc68000
# endif
#endif
#if defined(__mc68020__) || defined(__MC68020__) || defined(sysV68)
# ifndef mc68020
# define mc68020
# endif
#endif
#if defined(mc68020) || defined(mc68000)
#if (defined(mc68020) || defined(NeXT)) && !defined(UNALIGNED_OK)
# define UNALIGNED_OK
#endif
#ifdef sysV68 /* Try Motorola Delta style */
# define GLOBAL(symbol) global symbol
# define TEXT text
# define FILE(filename) file filename
# define invert_maybe(src,dst) dst,src
# define imm(data) &data
# define reg(register) %register
# define addl add.l
# define addql addq.l
# define blos blo.b
# define bhis bhi.b
# define bras bra.b
# define clrl clr.l
# define cmpmb cmpm.b
# define cmpw cmp.w
# define cmpl cmp.l
# define lslw lsl.w
# define lsrl lsr.l
# define movel move.l
# define movew move.w
# define moveb move.b
# define moveml movem.l
# define subl sub.l
# define subw sub.w
# define subql subq.l
# define IndBase(bd,An) (bd,An)
# define IndBaseNdxl(bd,An,Xn) (bd,An,Xn.l)
# define IndBaseNdxw(bd,An,Xn) (bd,An,Xn.w)
# define predec(An) -(An)
# define postinc(An) (An)+
#else /* default style (Sun 3, NeXT, Amiga, Atari) */
# define GLOBAL(symbol) .globl symbol
# define TEXT .text
# define FILE(filename) .even
# define invert_maybe(src,dst) src,dst
# if defined(sun) || defined(mc68k)
# define imm(data) #data
# else
# define imm(data) \#data
# endif
# define reg(register) register
# define blos bcss
# if defined(sun) || defined(mc68k)
# define movel movl
# define movew movw
# define moveb movb
# endif
# define IndBase(bd,An) An@(bd)
# define IndBaseNdxl(bd,An,Xn) An@(bd,Xn:l)
# define IndBaseNdxw(bd,An,Xn) An@(bd,Xn:w)
# define predec(An) An@-
# define postinc(An) An@+
#endif /* styles */
#define Best_Len reg(d0) /* unsigned */
#define Cur_Match reg(d1) /* Ipos */
#define Loop_Counter reg(d2) /* int */
#define Scan_Start reg(d3) /* unsigned short */
#define Scan_End reg(d4) /* unsigned short */
#define Limit reg(d5) /* IPos */
#define Chain_Length reg(d6) /* unsigned */
#define Scan_Test reg(d7)
#define Scan reg(a0) /* *uch */
#define Match reg(a1) /* *uch */
#define Prev_Address reg(a2) /* *Pos */
#define Scan_Ini reg(a3) /* *uch */
#define Match_Ini reg(a4) /* *uch */
#define Stack_Pointer reg(sp)
#define MAX_MATCH 258
#define MIN_MATCH 3
#define WSIZE 32768
#define MAX_DIST (WSIZE - MAX_MATCH - MIN_MATCH - 1)
GLOBAL (_match_init)
GLOBAL (_longest_match)
TEXT
FILE ("match.S")
_match_init:
rts
/*-----------------------------------------------------------------------
* Set match_start to the longest match starting at the given string and
* return its length. Matches shorter or equal to prev_length are discarded,
* in which case the result is equal to prev_length and match_start is
* garbage.
* IN assertions: cur_match is the head of the hash chain for the current
* string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
*/
/* int longest_match (cur_match) */
#ifdef UNALIGNED_OK
# define pushreg 15928 /* d2-d6/a2-a4 */
# define popreg 7292
#else
# define pushreg 16184 /* d2-d7/a2-a4 */
# define popreg 7420
#endif
_longest_match:
movel IndBase(4,Stack_Pointer),Cur_Match
moveml imm(pushreg),predec(Stack_Pointer)
movel _max_chain_length,Chain_Length
movel _prev_length,Best_Len
movel imm(_prev),Prev_Address
movel imm(_window+MIN_MATCH),Match_Ini
movel _strstart,Limit
movel Match_Ini,Scan_Ini
addl Limit,Scan_Ini
subw imm(MAX_DIST),Limit
bhis L__limit_ok
clrl Limit
L__limit_ok:
cmpl invert_maybe(_good_match,Best_Len)
blos L__length_ok
lsrl imm(2),Chain_Length
L__length_ok:
subql imm(1),Chain_Length
#ifdef UNALIGNED_OK
movew IndBase(-MIN_MATCH,Scan_Ini),Scan_Start
movew IndBaseNdxw(-MIN_MATCH-1,Scan_Ini,Best_Len),Scan_End
#else
moveb IndBase(-MIN_MATCH,Scan_Ini),Scan_Start
lslw imm(8),Scan_Start
moveb IndBase(-MIN_MATCH+1,Scan_Ini),Scan_Start
moveb IndBaseNdxw(-MIN_MATCH-1,Scan_Ini,Best_Len),Scan_End
lslw imm(8),Scan_End
moveb IndBaseNdxw(-MIN_MATCH,Scan_Ini,Best_Len),Scan_End
#endif
bras L__do_scan
L__long_loop:
#ifdef UNALIGNED_OK
movew IndBaseNdxw(-MIN_MATCH-1,Scan_Ini,Best_Len),Scan_End
#else
moveb IndBaseNdxw(-MIN_MATCH-1,Scan_Ini,Best_Len),Scan_End
lslw imm(8),Scan_End
moveb IndBaseNdxw(-MIN_MATCH,Scan_Ini,Best_Len),Scan_End
#endif
L__short_loop:
lslw imm(1),Cur_Match
movew IndBaseNdxl(0,Prev_Address,Cur_Match),Cur_Match
cmpw invert_maybe(Limit,Cur_Match)
dbls Chain_Length,L__do_scan
bras L__return
L__do_scan:
movel Match_Ini,Match
addl Cur_Match,Match
#ifdef UNALIGNED_OK
cmpw invert_maybe(IndBaseNdxw(-MIN_MATCH-1,Match,Best_Len),Scan_End)
bne L__short_loop
cmpw invert_maybe(IndBase(-MIN_MATCH,Match),Scan_Start)
bne L__short_loop
#else
moveb IndBaseNdxw(-MIN_MATCH-1,Match,Best_Len),Scan_Test
lslw imm(8),Scan_Test
moveb IndBaseNdxw(-MIN_MATCH,Match,Best_Len),Scan_Test
cmpw invert_maybe(Scan_Test,Scan_End)
bne L__short_loop
moveb IndBase(-MIN_MATCH,Match),Scan_Test
lslw imm(8),Scan_Test
moveb IndBase(-MIN_MATCH+1,Match),Scan_Test
cmpw invert_maybe(Scan_Test,Scan_Start)
bne L__short_loop
#endif
movew imm((MAX_MATCH-MIN_MATCH+1)-1),Loop_Counter
movel Scan_Ini,Scan
L__scan_loop:
cmpmb postinc(Match),postinc(Scan)
dbne Loop_Counter,L__scan_loop
subl Scan_Ini,Scan
addql imm(MIN_MATCH-1),Scan
cmpl invert_maybe(Best_Len,Scan)
bls L__short_loop
movel Scan,Best_Len
movel Cur_Match,_match_start
cmpl invert_maybe(_nice_match,Best_Len)
blos L__long_loop
L__return:
moveml postinc(Stack_Pointer),imm(popreg)
rts
#else
error: this asm version is for 386 or 680x0 only
#endif /* mc68000 || mc68020 */
#endif /* i386 || _I386 */

View file

@ -0,0 +1,16 @@
/* revision.h -- define the version number
* Copyright (C) 1992-1993 Jean-loup Gailly.
* This is free software; you can redistribute it and/or modify it under the
* terms of the GNU General Public License, see the file COPYING.
*/
#define VERSION "1.1.1"
#define PATCHLEVEL 0
#define REVDATE "1 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 $ */

268
gnu/usr.bin/gzip/tailor.h Normal file
View file

@ -0,0 +1,268 @@
/* tailor.h -- target dependent definitions
* Copyright (C) 1992-1993 Jean-loup Gailly.
* This is free software; you can redistribute it and/or modify it under the
* terms of the GNU General Public License, see the file COPYING.
*/
/* The target dependent definitions should be defined here only.
* The target dependent functions should be defined in tailor.c.
*/
/* $Id: tailor.h,v 0.16 1993/06/01 12:46:03 jloup Exp $ */
#if defined(__MSDOS__) && !defined(MSDOS)
# define MSDOS
#endif
#if defined(OS2) && defined(MSDOS) /* MS C under OS/2 */
# undef MSDOS
#endif
#ifdef MSDOS
# ifdef __GNUC__
/* DJGPP version 1.09+ on MS-DOS.
* The DJGPP 1.09 stat() function must be upgraded before gzip will
* fully work.
* No need for DIRENT, since <unistd.h> defines POSIX_SOURCE which
* implies DIRENT.
*/
# define near
# else
# define MAXSEG_64K
# ifdef __TURBOC__
# define NO_UTIME
# else /* MSC */
# define HAVE_SYS_UTIME_H
# define NO_UTIME_H
# endif
# endif
# define PATH_SEP2 '\\'
# define PATH_SEP3 ':'
# define MAX_PATH_LEN 128
# define NO_MULTIPLE_DOTS
# define MAX_EXT_CHARS 3
# define Z_SUFFIX "z"
# define NO_CHOWN
# define PROTO
# define STDC_HEADERS
# define NO_SIZE_CHECK
# define casemap(c) tolow(c) /* Force file names to lower case */
# include <io.h>
# define OS_CODE 0x00
# define SET_BINARY_MODE(fd) setmode(fd, O_BINARY)
# if !defined(NO_ASM) && !defined(ASMV)
# define ASMV
# endif
#else
# define near
#endif
#ifdef OS2
# define PATH_SEP2 '\\'
# define PATH_SEP3 ':'
# define MAX_PATH_LEN 260
# ifdef OS2FAT
# define NO_MULTIPLE_DOTS
# define MAX_EXT_CHARS 3
# define Z_SUFFIX "z"
# endif
# 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 MAXSEG_64K
# undef near
# define near _near
# endif
# ifdef __EMX__
# define DIRENT
# define EXPAND(argc,argv) \
{_response(&argc, &argv); _wildcard(&argc, &argv);}
# endif
#endif
#ifdef MSDOS
# ifdef __TURBOC__
# include <alloc.h>
# define DYN_ALLOC
/* Turbo C 2.0 does not accept static allocations of large arrays */
void * fcalloc (unsigned items, unsigned size);
void fcfree (void *ptr);
# else /* MSC */
# include <malloc.h>
# define fcalloc(nitems,itemsize) halloc((long)(nitems),(itemsize))
# define fcfree(ptr) hfree(ptr)
# endif
#else
# ifdef MAXSEG_64K
# define fcalloc(items,size) calloc((items),(size))
# else
# define fcalloc(items,size) malloc((size_t)(items)*(size_t)(size))
# endif
# define fcfree(ptr) free(ptr)
#endif
#if defined(VAXC) || defined(VMS)
# define PATH_SEP ']'
# define PATH_SEP2 ':'
# define SUFFIX_SEP ';'
# define NO_MULTIPLE_DOTS
# define Z_SUFFIX "-gz"
# define RECORD_IO 1
# define casemap(c) tolow(c)
# define OS_CODE 0x02
# define OPTIONS_VAR "GZIP_OPT"
# define STDC_HEADERS
# define NO_UTIME
# define EXPAND(argc,argv) vms_expand_args(&argc,&argv);
# include <file.h>
# define unlink delete
# ifdef VAXC
# define NO_FCNTL_H
# include <unixio.h>
# endif
#endif
#ifdef AMIGA
# define PATH_SEP2 ':'
# define STDC_HEADERS
# define casemap(c) tolow(c) /* Force file names to lower case */
# define OS_CODE 0x01
# define ASMV
# ifdef __GNUC__
# define DIRENT
# define HAVE_UNISTD_H
# define RETSIGTYPE int
# else /* SASC */
# define NO_STDIN_FSTAT
# define SYSDIR
# define NO_SYMLINK
# define NO_CHOWN
# define NO_FCNTL_H
# include <fcntl.h> /* for read() and write() */
# define direct dirent
extern void _expand_args(int *argc, char ***argv);
# define EXPAND(argc,argv) _expand_args(&argc,&argv);
# endif
#endif
#if defined(ATARI) || defined(atarist)
# ifndef STDC_HEADERS
# define STDC_HEADERS
# define HAVE_UNISTD_H
# define DIRENT
# endif
# define ASMV
# define OS_CODE 0x05
# ifdef TOSFS
# define NO_SYMLINK
# define NO_MULTIPLE_DOTS
# define MAX_EXT_CHARS 3
# define Z_SUFFIX "z"
# define NO_CHOWN
# endif
#endif
#ifdef MACOS
# define PATH_SEP ':'
# define DYN_ALLOC
# define PROTO
# define NO_STDIN_FSTAT
# define NO_CHOWN
# define NO_UTIME
# define chmod(file, mode) (0)
# define OPEN(name, flags, mode) open(name, flags)
# define OS_CODE 0x07
# ifdef MPW
# define isatty(fd) ((fd) <= 2)
# endif
#endif
#ifdef __50SERIES /* Prime/PRIMOS */
# define PATH_SEP '>'
# define STDC_HEADERS
# define NO_MEMORY_H
# define NO_UTIME_H
# define NO_UTIME
# define NO_CHOWN
# define NO_STDIN_FSTAT
# define NO_SIZE_CHECK
# define NO_SYMLINK
# define RECORD_IO 1
# define casemap(c) tolow(c) /* Force file names to lower case */
# 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 */
#endif
#ifdef WIN32
# define OS_CODE 0x0b
#endif
#ifdef TOPS20
# define OS_CODE 0x0a
#endif
#ifndef unix
# define NO_ST_INO /* don't rely on inode numbers */
#endif
/* Common defaults */
#ifndef OS_CODE
# define OS_CODE 0x03 /* assume Unix */
#endif
#ifndef PATH_SEP
# define PATH_SEP '/'
#endif
#ifndef casemap
# define casemap(c) (c)
#endif
#ifndef OPTIONS_VAR
# define OPTIONS_VAR "GZIP"
#endif
#ifndef Z_SUFFIX
# define Z_SUFFIX ".gz"
#endif
#ifdef MAX_EXT_CHARS
# define MAX_SUFFIX MAX_EXT_CHARS
#else
# define MAX_SUFFIX 30
#endif
#ifndef EXPAND
# define EXPAND(argc,argv)
#endif
#ifndef RECORD_IO
# define RECORD_IO 0
#endif
#ifndef SET_BINARY_MODE
# define SET_BINARY_MODE(fd)
#endif
#ifndef OPEN
# define OPEN(name, flags, mode) open(name, flags, mode)
#endif
#ifndef get_char
# define get_char() get_byte()
#endif
#ifndef put_char
# define put_char(c) put_byte(c)
#endif

1076
gnu/usr.bin/gzip/trees.c Normal file

File diff suppressed because it is too large Load diff

369
gnu/usr.bin/gzip/unlzw.c Normal file
View file

@ -0,0 +1,369 @@
/* unlzw.c -- decompress files in LZW format.
* The code in this file is directly derived from the public domain 'compress'
* written by Spencer Thomas, Joe Orost, James Woods, Jim McKie, Steve Davies,
* Ken Turkowski, Dave Mack and Peter Jannesen.
*
* This is a temporary version which will be rewritten in some future version
* to accommodate in-memory decompression.
*/
#ifndef lint
static char rcsid[] = "$Id: unlzw.c,v 0.13 1993/05/27 10:32:55 jloup Exp $";
#endif
#include <stdio.h>
#include <sys/types.h>
#include "tailor.h"
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#ifndef NO_FCNTL_H
# include <fcntl.h>
#endif
#include "gzip.h"
#include "lzw.h"
typedef unsigned char char_type;
typedef long code_int;
typedef unsigned long count_int;
typedef unsigned short count_short;
typedef unsigned long cmp_code_int;
#define MAXCODE(n) (1L << (n))
#ifndef REGISTERS
# define REGISTERS 2
#endif
#define REG1
#define REG2
#define REG3
#define REG4
#define REG5
#define REG6
#define REG7
#define REG8
#define REG9
#define REG10
#define REG11
#define REG12
#define REG13
#define REG14
#define REG15
#define REG16
#if REGISTERS >= 1
# undef REG1
# define REG1 register
#endif
#if REGISTERS >= 2
# undef REG2
# define REG2 register
#endif
#if REGISTERS >= 3
# undef REG3
# define REG3 register
#endif
#if REGISTERS >= 4
# undef REG4
# define REG4 register
#endif
#if REGISTERS >= 5
# undef REG5
# define REG5 register
#endif
#if REGISTERS >= 6
# undef REG6
# define REG6 register
#endif
#if REGISTERS >= 7
# undef REG7
# define REG7 register
#endif
#if REGISTERS >= 8
# undef REG8
# define REG8 register
#endif
#if REGISTERS >= 9
# undef REG9
# define REG9 register
#endif
#if REGISTERS >= 10
# undef REG10
# define REG10 register
#endif
#if REGISTERS >= 11
# undef REG11
# define REG11 register
#endif
#if REGISTERS >= 12
# undef REG12
# define REG12 register
#endif
#if REGISTERS >= 13
# undef REG13
# define REG13 register
#endif
#if REGISTERS >= 14
# undef REG14
# define REG14 register
#endif
#if REGISTERS >= 15
# undef REG15
# define REG15 register
#endif
#if REGISTERS >= 16
# undef REG16
# define REG16 register
#endif
#ifndef BYTEORDER
# define BYTEORDER 0000
#endif
#ifndef NOALLIGN
# define NOALLIGN 0
#endif
union bytes {
long word;
struct {
#if BYTEORDER == 4321
char_type b1;
char_type b2;
char_type b3;
char_type b4;
#else
#if BYTEORDER == 1234
char_type b4;
char_type b3;
char_type b2;
char_type b1;
#else
# undef BYTEORDER
int dummy;
#endif
#endif
} bytes;
};
#if BYTEORDER == 4321 && NOALLIGN == 1
# define input(b,o,c,n,m){ \
(c) = (*(long *)(&(b)[(o)>>3])>>((o)&0x7))&(m); \
(o) += (n); \
}
#else
# define input(b,o,c,n,m){ \
REG1 char_type *p = &(b)[(o)>>3]; \
(c) = ((((long)(p[0]))|((long)(p[1])<<8)| \
((long)(p[2])<<16))>>((o)&0x7))&(m); \
(o) += (n); \
}
#endif
#ifndef MAXSEG_64K
/* DECLARE(ush, tab_prefix, (1<<BITS)); -- prefix code */
# define tab_prefixof(i) tab_prefix[i]
# define clear_tab_prefixof() memzero(tab_prefix, 256);
#else
/* DECLARE(ush, tab_prefix0, (1<<(BITS-1)); -- prefix for even codes */
/* DECLARE(ush, tab_prefix1, (1<<(BITS-1)); -- prefix for odd codes */
ush *tab_prefix[2];
# define tab_prefixof(i) tab_prefix[(i)&1][(i)>>1]
# define clear_tab_prefixof() \
memzero(tab_prefix0, 128), \
memzero(tab_prefix1, 128);
#endif
#define de_stack ((char_type *)(&d_buf[DIST_BUFSIZE-1]))
#define tab_suffixof(i) tab_suffix[i]
int block_mode = BLOCK_MODE; /* block compress mode -C compatible with 2.0 */
/* ============================================================================
* Decompress in to out. This routine adapts to the codes in the
* file building the "string" table on-the-fly; requiring no table to
* be stored in the compressed file.
* IN assertions: the buffer inbuf contains already the beginning of
* the compressed data, from offsets iptr to insize-1 included.
* The magic header has already been checked and skipped.
* bytes_in and bytes_out have been initialized.
*/
int unlzw(in, out)
int in, out; /* input and output file descriptors */
{
REG2 char_type *stackp;
REG3 code_int code;
REG4 int finchar;
REG5 code_int oldcode;
REG6 code_int incode;
REG7 long inbits;
REG8 long posbits;
REG9 int outpos;
/* REG10 int insize; (global) */
REG11 unsigned bitmask;
REG12 code_int free_ent;
REG13 code_int maxcode;
REG14 code_int maxmaxcode;
REG15 int n_bits;
REG16 int rsize;
#ifdef MAXSEG_64K
tab_prefix[0] = tab_prefix0;
tab_prefix[1] = tab_prefix1;
#endif
maxbits = get_byte();
block_mode = maxbits & BLOCK_MODE;
if ((maxbits & LZW_RESERVED) != 0) {
WARN((stderr, "\n%s: %s: warning, unknown flags 0x%x\n",
progname, ifname, maxbits & LZW_RESERVED));
}
maxbits &= BIT_MASK;
maxmaxcode = MAXCODE(maxbits);
if (maxbits > BITS) {
fprintf(stderr,
"\n%s: %s: compressed with %d bits, can only handle %d bits\n",
progname, ifname, maxbits, BITS);
exit_code = ERROR;
return ERROR;
}
rsize = insize;
maxcode = MAXCODE(n_bits = INIT_BITS)-1;
bitmask = (1<<n_bits)-1;
oldcode = -1;
finchar = 0;
outpos = 0;
posbits = inptr<<3;
free_ent = ((block_mode) ? FIRST : 256);
clear_tab_prefixof(); /* Initialize the first 256 entries in the table. */
for (code = 255 ; code >= 0 ; --code) {
tab_suffixof(code) = (char_type)code;
}
do {
REG1 int i;
int e;
int o;
resetbuf:
e = insize-(o = (posbits>>3));
for (i = 0 ; i < e ; ++i) {
inbuf[i] = inbuf[i+o];
}
insize = e;
posbits = 0;
if (insize < INBUF_EXTRA) {
if ((rsize = read(in, (char*)inbuf+insize, INBUFSIZ)) == EOF) {
read_error();
}
insize += rsize;
}
inbits = ((rsize != 0) ? ((long)insize - insize%n_bits)<<3 :
((long)insize<<3)-(n_bits-1));
while (inbits > posbits) {
if (free_ent > maxcode) {
posbits = ((posbits-1) +
((n_bits<<3)-(posbits-1+(n_bits<<3))%(n_bits<<3)));
++n_bits;
if (n_bits == maxbits) {
maxcode = maxmaxcode;
} else {
maxcode = MAXCODE(n_bits)-1;
}
bitmask = (1<<n_bits)-1;
goto resetbuf;
}
input(inbuf,posbits,code,n_bits,bitmask);
if (oldcode == -1) {
outbuf[outpos++] = (char_type)(finchar = (int)(oldcode=code));
continue;
}
if (code == CLEAR && block_mode) {
clear_tab_prefixof();
free_ent = FIRST - 1;
posbits = ((posbits-1) +
((n_bits<<3)-(posbits-1+(n_bits<<3))%(n_bits<<3)));
maxcode = MAXCODE(n_bits = INIT_BITS)-1;
bitmask = (1<<n_bits)-1;
goto resetbuf;
}
incode = code;
stackp = de_stack;
if (code >= free_ent) { /* Special case for KwKwK string. */
if (code > free_ent) {
#ifdef DEBUG
char_type *p;
posbits -= n_bits;
p = &inbuf[posbits>>3];
fprintf(stderr,
"code:%ld free_ent:%ld n_bits:%d insize:%u\n",
code, free_ent, n_bits, insize);
fprintf(stderr,
"posbits:%ld inbuf:%02X %02X %02X %02X %02X\n",
posbits, p[-1],p[0],p[1],p[2],p[3]);
#endif
if (!test && outpos > 0) {
write_buf(out, outbuf, outpos);
}
error("corrupt input. Use zcat to recover some data.");
}
*--stackp = (char_type)finchar;
code = oldcode;
}
while ((cmp_code_int)code >= (cmp_code_int)256) {
/* Generate output characters in reverse order */
*--stackp = tab_suffixof(code);
code = tab_prefixof(code);
}
*--stackp = (char_type)(finchar = tab_suffixof(code));
/* And put them out in forward order */
{
REG1 int i;
if (outpos+(i = (de_stack-stackp)) >= OUTBUFSIZ) {
do {
if (i > OUTBUFSIZ-outpos) i = OUTBUFSIZ-outpos;
if (i > 0) {
memcpy(outbuf+outpos, stackp, i);
outpos += i;
}
if (outpos >= OUTBUFSIZ) {
if (!test) write_buf(out, outbuf, outpos);
outpos = 0;
}
stackp+= i;
} while ((i = (de_stack-stackp)) > 0);
} else {
memcpy(outbuf+outpos, stackp, i);
outpos += i;
}
}
if ((code = free_ent) < maxmaxcode) { /* Generate the new entry. */
tab_prefixof(code) = (unsigned short)oldcode;
tab_suffixof(code) = (char_type)finchar;
free_ent = code+1;
}
oldcode = incode; /* Remember previous code. */
}
bytes_in += rsize;
} while (rsize != 0);
if (!test && outpos > 0) write_buf(out, outbuf, outpos);
return OK;
}

241
gnu/usr.bin/gzip/unpack.c Normal file
View file

@ -0,0 +1,241 @@
/* unpack.c -- decompress files in pack format.
* Copyright (C) 1992-1993 Jean-loup Gailly
* This is free software; you can redistribute it and/or modify it under the
* terms of the GNU General Public License, see the file COPYING.
*/
#ifndef lint
static char rcsid[] = "$Id: unpack.c,v 1.3 1993/05/28 17:56:07 jloup Exp $";
#endif
#include <stdio.h>
#include "tailor.h"
#include "gzip.h"
#include "crypt.h"
#define MIN(a,b) ((a) <= (b) ? (a) : (b))
/* The arguments must not have side effects. */
#define MAX_BITLEN 25
/* Maximum length of Huffman codes. (Minor modifications to the code
* would be needed to support 32 bits codes, but pack never generates
* more than 24 bits anyway.)
*/
#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
/* Maximum number of 'peek' bits used to optimize traversal of the
* Huffman tree.
*/
local ulg orig_len; /* original uncompressed length */
local int max_len; /* maximum bit length of Huffman codes */
local uch literal[LITERALS];
/* The literal bytes present in the Huffman tree. The EOB code is not
* represented.
*/
local int lit_base[MAX_BITLEN+1];
/* All literals of a given bit length are contiguous in literal[] and
* have contiguous codes. literal[code+lit_base[len]] is the literal
* for a code of len bits.
*/
local int leaves [MAX_BITLEN+1]; /* Number of leaves for each bit length */
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];
/* 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
* necessary to have a huge table (large MAX_PEEK) because most of the
* codes encountered in the input stream are short codes (by construction).
* So for most codes a single lookup will be necessary.
*/
local ulg bitbuf;
/* Bits are added on the low part of bitbuf and read from the high part. */
local int valid; /* number of valid bits in bitbuf */
/* all bits above the last valid bit are always zero */
/* Set code to the next 'bits' input bits without skipping them. code
* must be the name of a simple variable and bits must not have side effects.
* IN assertions: bits <= 25 (so that we still have room for an extra byte
* when valid is only 24), and mask = (1<<bits)-1.
*/
#define look_bits(code,bits,mask) \
{ \
while (valid < (bits)) bitbuf = (bitbuf<<8) | (ulg)get_byte(), valid += 8; \
code = (bitbuf >> (valid-(bits))) & (mask); \
}
/* Skip the given number of bits (after having peeked at them): */
#define skip_bits(bits) (valid -= (bits))
#define clear_bitbuf() (valid = 0, bitbuf = 0)
/* Local functions */
local void read_tree OF((void));
local void build_tree OF((void));
/* ===========================================================================
* Read the Huffman tree.
*/
local void read_tree()
{
int len; /* bit length */
int base; /* base offset for a sequence of leaves */
int n;
/* Read the original input size, MSB first */
orig_len = 0;
for (n = 1; n <= 4; n++) orig_len = (orig_len << 8) | (ulg)get_byte();
max_len = (int)get_byte(); /* maximum bit length of Huffman codes */
if (max_len > MAX_BITLEN) {
error("invalid compressed data -- Huffman code > 32 bits");
}
/* Get the number of leaves at each bit length */
n = 0;
for (len = 1; len <= max_len; len++) {
leaves[len] = (int)get_byte();
n += leaves[len];
}
if (n > LITERALS) {
error("too many leaves in Huffman tree");
}
Trace((stderr, "orig_len %ld, max_len %d, leaves %d\n",
orig_len, max_len, n));
/* There are at least 2 and at most 256 leaves of length max_len.
* (Pack arbitrarily rejects empty files and files consisting of
* a single byte even repeated.) To fit the last leaf count in a
* byte, it is offset by 2. However, the last literal is the EOB
* code, and is not transmitted explicitly in the tree, so we must
* adjust here by one only.
*/
leaves[max_len]++;
/* Now read the leaves themselves */
base = 0;
for (len = 1; len <= max_len; len++) {
/* Remember where the literals of this length start in literal[] : */
lit_base[len] = base;
/* And read the literals: */
for (n = leaves[len]; n > 0; n--) {
literal[base++] = (uch)get_byte();
}
}
leaves[max_len]++; /* Now include the EOB code in the Huffman tree */
}
/* ===========================================================================
* Build the Huffman tree and the prefix table.
*/
local void build_tree()
{
int nodes = 0; /* number of nodes (parents+leaves) at current bit length */
int len; /* current bit length */
uch *prefixp; /* pointer in prefix_len */
for (len = max_len; len >= 1; len--) {
/* The number of parent nodes at this level is half the total
* number of nodes at parent level:
*/
nodes >>= 1;
parents[len] = nodes;
/* Update lit_base by the appropriate bias to skip the parent nodes
* (which are not represented in the literal array):
*/
lit_base[len] -= nodes;
/* Restore nodes to be parents+leaves: */
nodes += leaves[len];
}
/* Construct the prefix table, from shortest leaves to longest ones.
* The shortest code is all ones, so we start at the end of the table.
*/
peek_bits = MIN(max_len, MAX_PEEK);
prefixp = &prefix_len[1<<peek_bits];
for (len = 1; len <= peek_bits; len++) {
int prefixes = leaves[len] << (peek_bits-len); /* may be 0 */
while (prefixes--) *--prefixp = (uch)len;
}
/* The length of all other codes is unknown: */
while (prefixp > prefix_len) *--prefixp = 0;
}
/* ===========================================================================
* Unpack in to out. This routine does not support the old pack format
* with magic header \037\037.
*
* IN assertions: the buffer inbuf contains already the beginning of
* the compressed data, from offsets inptr to insize-1 included.
* The magic header has already been checked. The output buffer is cleared.
*/
int unpack(in, out)
int in, out; /* input and output file descriptors */
{
int len; /* Bit length of current code */
unsigned eob; /* End Of Block code */
register unsigned peek; /* lookahead bits */
unsigned peek_mask; /* Mask for peek_bits bits */
ifd = in;
ofd = out;
read_tree(); /* Read the Huffman tree */
build_tree(); /* Build the prefix table */
clear_bitbuf(); /* Initialize bit input */
peek_mask = (1<<peek_bits)-1;
/* The eob code is the largest code among all leaves of maximal length: */
eob = leaves[max_len]-1;
Trace((stderr, "eob %d %x\n", max_len, eob));
/* Decode the input data: */
for (;;) {
/* Since eob is the longest code and not shorter than max_len,
* we can peek at max_len bits without having the risk of reading
* beyond the end of file.
*/
look_bits(peek, peek_bits, peek_mask);
len = prefix_len[peek];
if (len > 0) {
peek >>= peek_bits - len; /* discard the extra bits */
} else {
/* Code of more than peek_bits bits, we must traverse the tree */
ulg mask = peek_mask;
len = peek_bits;
do {
len++, mask = (mask<<1)+1;
look_bits(peek, len, mask);
} while (peek < parents[len]);
/* loop as long as peek is a parent node */
}
/* At this point, peek is the next complete code, of len bits */
if (peek == eob && len == max_len) break; /* end of file? */
put_ubyte(literal[peek+lit_base[len]]);
Tracev((stderr,"%02d %04x %c\n", len, peek,
literal[peek+lit_base[len]]));
skip_bits(len);
} /* for (;;) */
flush_window();
Trace((stderr, "bytes_out %ld\n", bytes_out));
if (orig_len != bytes_out) {
error("invalid compressed data--length error");
}
return OK;
}

201
gnu/usr.bin/gzip/unzip.c Normal file
View file

@ -0,0 +1,201 @@
/* unzip.c -- decompress files in gzip or pkzip format.
* Copyright (C) 1992-1993 Jean-loup Gailly
* This is free software; you can redistribute it and/or modify it under the
* terms of the GNU General Public License, see the file COPYING.
*
* The code in this file is derived from the file funzip.c written
* and put in the public domain by Mark Adler.
*/
/*
This version can extract files in gzip or pkzip format.
For the latter, only the first entry is extracted, and it has to be
either deflated or stored.
*/
#ifndef lint
static char rcsid[] = "$Id: unzip.c,v 0.12 1993/05/28 17:56:23 jloup Exp $";
#endif
#include <stdio.h>
#include "tailor.h"
#include "gzip.h"
#include "crypt.h"
/* PKZIP header definitions */
#define LOCSIG 0x04034b50L /* four-byte lead-in (lsb first) */
#define LOCFLG 6 /* offset of bit flag */
#define CRPFLG 1 /* bit for encrypted entry */
#define EXTFLG 8 /* bit for extended local header */
#define LOCHOW 8 /* offset of compression method */
#define LOCTIM 10 /* file mod time (for decryption) */
#define LOCCRC 14 /* offset of crc */
#define LOCSIZ 18 /* offset of compressed size */
#define LOCLEN 22 /* offset of uncompressed length */
#define LOCFIL 26 /* offset of file name field length */
#define LOCEXT 28 /* offset of extra field length */
#define LOCHDR 30 /* size of local header, including sig */
#define EXTHDR 16 /* size of extended local header, inc sig */
/* Globals */
int decrypt; /* flag to turn on decryption */
char *key; /* not used--needed to link crypt.c */
int pkzip = 0; /* set for a pkzip file */
int ext_header = 0; /* set if extended local header */
/* ===========================================================================
* Check zip file and advance inptr to the start of the compressed data.
* Get ofname from the local header if necessary.
*/
int check_zipfile(in)
int in; /* input file descriptors */
{
uch *h = inbuf + inptr; /* first local header */
ifd = in;
/* Check validity of local header, and skip name and extra fields */
inptr += LOCHDR + SH(h + LOCFIL) + SH(h + LOCEXT);
if (inptr > insize || LG(h) != LOCSIG) {
fprintf(stderr, "\n%s: %s: not a valid zip file\n",
progname, ifname);
exit_code = ERROR;
return ERROR;
}
method = h[LOCHOW];
if (method != STORED && method != DEFLATED) {
fprintf(stderr,
"\n%s: %s: first entry not deflated or stored -- use unzip\n",
progname, ifname);
exit_code = ERROR;
return ERROR;
}
/* If entry encrypted, decrypt and validate encryption header */
if ((decrypt = h[LOCFLG] & CRPFLG) != 0) {
fprintf(stderr, "\n%s: %s: encrypted file -- use unzip\n",
progname, ifname);
exit_code = ERROR;
return ERROR;
}
/* Save flags for unzip() */
ext_header = (h[LOCFLG] & EXTFLG) != 0;
pkzip = 1;
/* Get ofname and time stamp from local header (to be done) */
return OK;
}
/* ===========================================================================
* Unzip in to out. This routine works on both gzip and pkzip files.
*
* IN assertions: the buffer inbuf contains already the beginning of
* the compressed data, from offsets inptr to insize-1 included.
* The magic header has already been checked. The output buffer is cleared.
*/
int unzip(in, out)
int in, out; /* input and output file descriptors */
{
ulg orig_crc = 0; /* original crc */
ulg orig_len = 0; /* original uncompressed length */
int n;
uch buf[EXTHDR]; /* extended local header */
ifd = in;
ofd = out;
updcrc(NULL, 0); /* initialize crc */
if (pkzip && !ext_header) { /* crc and length at the end otherwise */
orig_crc = LG(inbuf + LOCCRC);
orig_len = LG(inbuf + LOCLEN);
}
/* Decompress */
if (method == DEFLATED) {
int res = inflate();
if (res == 3) {
error("out of memory");
} else if (res != 0) {
error("invalid compressed data--format violated");
}
} else if (pkzip && method == STORED) {
register ulg n = LG(inbuf + LOCLEN);
if (n != LG(inbuf + LOCSIZ) - (decrypt ? RAND_HEAD_LEN : 0)) {
fprintf(stderr, "len %ld, siz %ld\n", n, LG(inbuf + LOCSIZ));
error("invalid compressed data--length mismatch");
}
while (n--) {
uch c = (uch)get_byte();
#ifdef CRYPT
if (decrypt) zdecode(c);
#endif
put_ubyte(c);
}
flush_window();
} else {
error("internal error, invalid method");
}
/* Get the crc and original length */
if (!pkzip) {
/* crc32 (see algorithm.doc)
* uncompressed input size modulo 2^32
*/
for (n = 0; n < 8; n++) {
buf[n] = (uch)get_byte(); /* may cause an error if EOF */
}
orig_crc = LG(buf);
orig_len = LG(buf+4);
} else if (ext_header) { /* If extended header, check it */
/* signature - 4bytes: 0x50 0x4b 0x07 0x08
* CRC-32 value
* compressed size 4-bytes
* uncompressed size 4-bytes
*/
for (n = 0; n < EXTHDR; n++) {
buf[n] = (uch)get_byte(); /* may cause an error if EOF */
}
orig_crc = LG(buf+4);
orig_len = LG(buf+12);
}
/* Validate decompression */
if (orig_crc != updcrc(outbuf, 0)) {
error("invalid compressed data--crc error");
}
if (orig_len != bytes_out) {
error("invalid compressed data--length error");
}
/* Check if there are more entries in a pkzip file */
if (pkzip && inptr + 4 < insize && LG(inbuf+inptr) == LOCSIG) {
if (to_stdout) {
WARN((stderr,
"%s: %s has more than one entry--rest ignored\n",
progname, ifname));
} else {
/* Don't destroy the input zip file */
fprintf(stderr,
"%s: %s has more than one entry -- unchanged\n",
progname, ifname);
exit_code = ERROR;
ext_header = pkzip = 0;
return ERROR;
}
}
ext_header = pkzip = 0; /* for next file */
return OK;
}

419
gnu/usr.bin/gzip/util.c Normal file
View file

@ -0,0 +1,419 @@
/* util.c -- utility functions for gzip support
* Copyright (C) 1992-1993 Jean-loup Gailly
* This is free software; you can redistribute it and/or modify it under the
* terms of the GNU General Public License, see the file COPYING.
*/
#ifndef lint
static char rcsid[] = "$Id: util.c,v 0.14 1993/05/27 10:31:52 jloup Exp $";
#endif
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include <sys/types.h>
#include "tailor.h"
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#ifndef NO_FCNTL_H
# include <fcntl.h>
#endif
#if defined(STDC_HEADERS) || !defined(NO_STDLIB_H)
# include <stdlib.h>
#else
extern int errno;
#endif
#include "gzip.h"
#include "crypt.h"
extern ulg crc_32_tab[]; /* crc table, defined below */
/* ===========================================================================
* 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.
*/
ulg updcrc(s, n)
uch *s; /* pointer to bytes to pump through */
unsigned n; /* number of bytes in s[] */
{
register ulg c; /* temporary variable */
static ulg crc = (ulg)0xffffffffL; /* shift register contents */
if (s == NULL) {
c = 0xffffffffL;
} else {
c = crc;
if (n) do {
c = crc_32_tab[((int)c ^ (*s++)) & 0xff] ^ (c >> 8);
} while (--n);
}
crc = c;
return c ^ 0xffffffffL; /* (instead of ~c for 64-bit machines) */
}
/* ===========================================================================
* Clear input and output buffers
*/
void clear_bufs()
{
outcnt = 0;
insize = inptr = 0;
bytes_in = bytes_out = 0L;
}
/* ===========================================================================
* Fill the input buffer. This is called only when the buffer is empty
* and at least one byte is really needed.
*/
int fill_inbuf()
{
int len;
/* Read as much as possible */
insize = 0;
errno = 0;
do {
len = read(ifd, (char*)inbuf+insize, INBUFSIZ-insize);
if (len == 0 || len == EOF) break;
insize += len;
} while (insize < INBUFSIZ);
if (insize == 0) {
read_error();
}
bytes_in += (ulg)insize;
inptr = 1;
return inbuf[0];
}
/* ===========================================================================
* Write the output buffer outbuf[0..outcnt-1] and update bytes_out.
* (used for the compressed data only)
*/
void flush_outbuf()
{
if (outcnt == 0) return;
write_buf(ofd, (char *)outbuf, outcnt);
bytes_out += (ulg)outcnt;
outcnt = 0;
}
/* ===========================================================================
* Write the output window window[0..outcnt-1] and update crc and bytes_out.
* (Used for the decompressed data only.)
*/
void flush_window()
{
if (outcnt == 0) return;
updcrc(window, outcnt);
if (!test) {
write_buf(ofd, (char *)window, outcnt);
}
bytes_out += (ulg)outcnt;
outcnt = 0;
}
/* ===========================================================================
* Does the same as write(), but also handles partial pipe writes and checks
* for error return.
*/
void write_buf(fd, buf, cnt)
int fd;
voidp buf;
unsigned cnt;
{
unsigned n;
while ((n = write(fd, buf, cnt)) != cnt) {
if (n == (unsigned)(-1)) {
write_error();
}
cnt -= n;
buf = (voidp)((char*)buf+n);
}
}
/* ========================================================================
* Put string s in lower case, return s.
*/
char *strlwr(s)
char *s;
{
char *t;
for (t = s; *t; t++) *t = tolow(*t);
return s;
}
/* ========================================================================
* Return the base name of a file (remove any directory prefix and
* any version suffix). For systems with file names that are not
* case sensitive, force the base name to lower case.
*/
char *basename(fname)
char *fname;
{
char *p;
if ((p = strrchr(fname, PATH_SEP)) != NULL) fname = p+1;
#ifdef PATH_SEP2
if ((p = strrchr(fname, PATH_SEP2)) != NULL) fname = p+1;
#endif
#ifdef PATH_SEP3
if ((p = strrchr(fname, PATH_SEP3)) != NULL) fname = p+1;
#endif
#ifdef SUFFIX_SEP
if ((p = strrchr(fname, SUFFIX_SEP)) != NULL) *p = '\0';
#endif
if (casemap('A') == 'a') strlwr(fname);
return fname;
}
#if defined(NO_STRING_H) && !defined(STDC_HEADERS)
/* Provide missing strspn and strcspn functions. */
# ifndef __STDC__
# define const
# endif
int strspn OF((const char *s, const char *accept));
int strcspn OF((const char *s, const char *reject));
/* ========================================================================
* Return the length of the maximum initial segment
* of s which contains only characters in accept.
*/
int strspn(s, accept)
const char *s;
const char *accept;
{
register const char *p;
register const char *a;
register int count = 0;
for (p = s; *p != '\0'; ++p) {
for (a = accept; *a != '\0'; ++a) {
if (*p == *a) break;
}
if (*a == '\0') return count;
++count;
}
return count;
}
/* ========================================================================
* Return the length of the maximum inital segment of s
* which contains no characters from reject.
*/
int strcspn(s, reject)
const char *s;
const char *reject;
{
register int count = 0;
while (*s != '\0') {
if (strchr(reject, *s++) != NULL) return count;
++count;
}
return count;
}
#endif /* NO_STRING_H */
/* ========================================================================
* Add an environment variable (if any) before argv, and update argc.
* Return the expanded environment variable to be freed later, or NULL
* if no options were added to argv.
*/
#define SEPARATOR " \t" /* separators in env variable */
char *add_envopt(argcp, argvp, env)
int *argcp; /* pointer to argc */
char ***argvp; /* pointer to argv */
char *env; /* name of environment variable */
{
char *p; /* running pointer through env variable */
char **oargv; /* runs through old argv array */
char **nargv; /* runs through new argv array */
int oargc = *argcp; /* old argc */
int nargc = 0; /* number of arguments in env variable */
env = (char*)getenv(env);
if (env == NULL) return NULL;
p = (char*)xmalloc(strlen(env)+1);
env = strcpy(p, env); /* keep env variable intact */
for (p = env; *p; nargc++ ) { /* move through env */
p += strspn(p, SEPARATOR); /* skip leading separators */
if (*p == '\0') break;
p += strcspn(p, SEPARATOR); /* find end of word */
if (*p) *p++ = '\0'; /* mark it */
}
if (nargc == 0) {
free(env); env = NULL;
return NULL;
}
*argcp += nargc;
/* Allocate the new argv array, with an extra element just in case
* the original arg list did not end with a NULL.
*/
nargv = (char**)calloc(*argcp+1, sizeof(char *));
if (nargv == NULL) error("out of memory");
oargv = *argvp;
*argvp = nargv;
/* Copy the program name first */
if (oargc-- < 0) error("argc<=0");
*(nargv++) = *(oargv++);
/* Then copy the environment args */
for (p = env; nargc > 0; nargc--) {
p += strspn(p, SEPARATOR); /* skip separators */
*(nargv++) = p; /* store start */
while (*p++) ; /* skip over word */
}
/* Finally copy the old args and add a NULL (usual convention) */
while (oargc--) *(nargv++) = *(oargv++);
*nargv = NULL;
return env;
}
/* ========================================================================
* Error handlers.
*/
void error(m)
char *m;
{
fprintf(stderr, "\n%s: %s: %s\n", progname, ifname, m);
abort_gzip();
}
void warn(a, b)
char *a, *b; /* message strings juxtaposed in output */
{
WARN((stderr, "%s: %s: warning: %s%s\n", progname, ifname, a, b));
}
void read_error()
{
fprintf(stderr, "\n%s: ", progname);
if (errno != 0) {
perror(ifname);
} else {
fprintf(stderr, "%s: unexpected end of file\n", ifname);
}
abort_gzip();
}
void write_error()
{
fprintf(stderr, "\n%s: ", progname);
perror(ofname);
abort_gzip();
}
/* ========================================================================
* Display compression ratio on stderr.
*/
void display_ratio(num, den)
long num;
long den;
{
long ratio; /* 1000 times the compression ratio */
if (den == 0) {
ratio = 0; /* no compression */
} else if (den < 2147483L) { /* (2**31 -1)/1000 */
ratio = 1000L*num/den;
} else {
ratio = num/(den/1000L);
}
if (ratio < 0) {
putc('-', stderr);
ratio = -ratio;
}
fprintf(stderr, "%2ld.%ld%%", ratio / 10L, ratio % 10L);
}
/* ========================================================================
* Semi-safe malloc -- never returns NULL.
*/
voidp xmalloc (size)
unsigned size;
{
voidp cp = (voidp)malloc (size);
if (cp == NULL) error("out of memory");
return cp;
}
/* ========================================================================
* Table of CRC-32's of all single-byte values (made by makecrc.c)
*/
ulg crc_32_tab[] = {
0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
0x2d02ef8dL
};

67
gnu/usr.bin/gzip/zcmp Normal file
View file

@ -0,0 +1,67 @@
#!/bin/sh
# Zcmp and zdiff are used to invoke the cmp or the diff pro-
# gram on compressed files. All options specified are passed
# directly to cmp or diff. If only 1 file is specified, then
# the files compared are file1 and an uncompressed file1.gz.
# If two files are specified, then they are uncompressed (if
# necessary) and fed to cmp or diff. The exit status from cmp
# or diff is preserved.
prog=`echo $0 | sed 's|.*/||'`
case "$prog" in
*cmp) comp=${CMP-cmp} ;;
*) comp=${DIFF-diff} ;;
esac
OPTIONS=
FILES=
for ARG
do
case "$ARG" in
-*) OPTIONS="$OPTIONS $ARG";;
*) if test -f "$ARG"; then
FILES="$FILES $ARG"
else
echo "${prog}: $ARG not found or not a regular file"
exit 1
fi ;;
esac
done
if test -z "$FILES"; then
echo "Usage: $prog [${comp}_options] file [file]"
exit 1
fi
set $FILES
if test $# -eq 1; then
FILE=`echo "$1" | sed 's/[-.][zZtga]*$//'`
gzip -cd "$1" | $comp $OPTIONS - "$FILE"
STAT="$?"
elif test $# -eq 2; then
case "$1" in
*[-.]gz | *[-.][zZ] | *.t[ga]z)
case "$2" in
*[-.]gz | *[-.][zZ] | *.t[ga]z)
F=`echo "$2" | sed 's|.*/||;s|[-.][zZtga]*$||'`
gzip -cd "$2" > /tmp/"$F".$$
gzip -cd "$1" | $comp $OPTIONS - /tmp/"$F".$$
STAT="$?"
/bin/rm -f /tmp/"$F".$$;;
*) gzip -cd "$1" | $comp $OPTIONS - "$2"
STAT="$?";;
esac;;
*) case "$2" in
*[-.]gz | *[-.][zZ] | *.t[ga]z)
gzip -cd "$2" | $comp $OPTIONS "$1" -
STAT="$?";;
*) $comp $OPTIONS "$1" "$2"
STAT="$?";;
esac;;
esac
exit "$STAT"
else
echo "Usage: $prog [${comp}_options] file [file]"
exit 1
fi

67
gnu/usr.bin/gzip/zdiff Normal file
View file

@ -0,0 +1,67 @@
#!/bin/sh
# Zcmp and zdiff are used to invoke the cmp or the diff pro-
# gram on compressed files. All options specified are passed
# directly to cmp or diff. If only 1 file is specified, then
# the files compared are file1 and an uncompressed file1.gz.
# If two files are specified, then they are uncompressed (if
# necessary) and fed to cmp or diff. The exit status from cmp
# or diff is preserved.
prog=`echo $0 | sed 's|.*/||'`
case "$prog" in
*cmp) comp=${CMP-cmp} ;;
*) comp=${DIFF-diff} ;;
esac
OPTIONS=
FILES=
for ARG
do
case "$ARG" in
-*) OPTIONS="$OPTIONS $ARG";;
*) if test -f "$ARG"; then
FILES="$FILES $ARG"
else
echo "${prog}: $ARG not found or not a regular file"
exit 1
fi ;;
esac
done
if test -z "$FILES"; then
echo "Usage: $prog [${comp}_options] file [file]"
exit 1
fi
set $FILES
if test $# -eq 1; then
FILE=`echo "$1" | sed 's/[-.][zZtga]*$//'`
gzip -cd "$1" | $comp $OPTIONS - "$FILE"
STAT="$?"
elif test $# -eq 2; then
case "$1" in
*[-.]gz | *[-.][zZ] | *.t[ga]z)
case "$2" in
*[-.]gz | *[-.][zZ] | *.t[ga]z)
F=`echo "$2" | sed 's|.*/||;s|[-.][zZtga]*$||'`
gzip -cd "$2" > /tmp/"$F".$$
gzip -cd "$1" | $comp $OPTIONS - /tmp/"$F".$$
STAT="$?"
/bin/rm -f /tmp/"$F".$$;;
*) gzip -cd "$1" | $comp $OPTIONS - "$2"
STAT="$?";;
esac;;
*) case "$2" in
*[-.]gz | *[-.][zZ] | *.t[ga]z)
gzip -cd "$2" | $comp $OPTIONS "$1" -
STAT="$?";;
*) $comp $OPTIONS "$1" "$2"
STAT="$?";;
esac;;
esac
exit "$STAT"
else
echo "Usage: $prog [${comp}_options] file [file]"
exit 1
fi

44
gnu/usr.bin/gzip/zdiff.1 Normal file
View file

@ -0,0 +1,44 @@
.TH ZDIFF 1
.SH NAME
zcmp, zdiff \- compare compressed files
.SH SYNOPSIS
.B zcmp
[ cmp_options ] file1
[ file2 ]
.br
.B zdiff
[ diff_options ] file1
[ file2 ]
.SH DESCRIPTION
.I Zcmp
and
.I zdiff
are used to invoke the
.I cmp
or the
.I diff
program on compressed files. All options specified are passed directly to
.I cmp
or
.IR diff "."
If only 1 file is specified, then the files compared are
.I file1
and an uncompressed
.IR file1 ".gz."
If two files are specified, then they are uncompressed if necessary and fed to
.I cmp
or
.IR diff "."
The exit status from
.I cmp
or
.I diff
is preserved.
.SH "SEE ALSO"
cmp(1), diff(1), zmore(1), znew(1), zforce(1), gzip(1), gzexe(1)
.SH BUGS
Messages from the
.I cmp
or
.I diff
programs refer to temporary filenames instead of those specified.

39
gnu/usr.bin/gzip/zforce Normal file
View file

@ -0,0 +1,39 @@
#!/bin/sh
# zforce: force a gz extension on all gzip files so that gzip will not
# compress them twice.
#
# This can be useful for files with names truncated after a file transfer.
# 12345678901234 is renamed to 12345678901.gz
x=`basename $0`
if test $# = 0; then
echo "force a '.gz' extension on all gzip files"
echo usage: $x files...
exit 1
fi
res=0
for i do
if test ! -f "$i" ; then
echo ${x}: $i not a file
res=1
continue
fi
test `expr "$i" : '.*[.-]z$'` -eq 0 || continue
test `expr "$i" : '.*[.-]gz$'` -eq 0 || continue
test `expr "$i" : '.*[.]t[ag]z$'` -eq 0 || continue
gzip -t "$i" 2>/dev/null || continue
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
done
exit $res

20
gnu/usr.bin/gzip/zforce.1 Normal file
View file

@ -0,0 +1,20 @@
.TH ZFORCE 1
.SH NAME
zforce \- force a '.gz' extension on all gzip files
.SH SYNOPSIS
.B zforce
[ name ... ]
.SH DESCRIPTION
.I zforce
forces a .gz extension on all
.I gzip
files so that
.I gzip
will not compress them twice.
This can be useful for files with names truncated after a file transfer.
On systems with a 14 char limitation on file names, the original name
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)

118
gnu/usr.bin/gzip/zip.c Normal file
View file

@ -0,0 +1,118 @@
/* zip.c -- compress files to the gzip or pkzip format
* Copyright (C) 1992-1993 Jean-loup Gailly
* This is free software; you can redistribute it and/or modify it under the
* terms of the GNU General Public License, see the file COPYING.
*/
#ifndef lint
static char rcsid[] = "$Id: zip.c,v 0.16 1993/05/28 14:51:17 jloup Exp $";
#endif
#include <ctype.h>
#include <stdio.h>
#include <sys/types.h>
#include "tailor.h"
#include "gzip.h"
#include "crypt.h"
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#ifndef NO_FCNTL_H
# include <fcntl.h>
#endif
local ulg crc; /* crc on uncompressed file data */
long header_bytes; /* number of bytes in gzip header */
/* ===========================================================================
* Deflate in to out.
* IN assertions: the input and output buffers are cleared.
* The variables time_stamp and save_orig_name are initialized.
*/
int zip(in, out)
int in, out; /* input and output file descriptors */
{
uch flags = 0; /* general purpose bit flags */
ush attr = 0; /* ascii/binary flag */
ush deflate_flags = 0; /* pkzip -es, -en or -ex equivalent */
ifd = in;
ofd = out;
outcnt = 0;
/* Write the header to the gzip file. See algorithm.doc for the format */
method = DEFLATED;
put_byte(GZIP_MAGIC[0]); /* magic header */
put_byte(GZIP_MAGIC[1]);
put_byte(DEFLATED); /* compression method */
if (save_orig_name) {
flags |= ORIG_NAME;
}
put_byte(flags); /* general flags */
put_long(time_stamp);
/* Write deflated file to zip file */
crc = updcrc(0, 0);
bi_init(out);
ct_init(&attr, &method);
lm_init(level, &deflate_flags);
put_byte((uch)deflate_flags); /* extra flags */
put_byte(OS_CODE); /* OS identifier */
if (save_orig_name) {
char *p = basename(ifname); /* Don't save the directory part. */
do {
put_char(*p);
} while (*p++);
}
header_bytes = (long)outcnt;
(void)deflate();
#if !defined(NO_SIZE_CHECK) && !defined(RECORD_IO)
/* Check input size (but not in VMS -- variable record lengths mess it up)
* and not on MSDOS -- diet in TSR mode reports an incorrect file size)
*/
if (ifile_size != -1L && isize != (ulg)ifile_size) {
Trace((stderr, " actual=%ld, read=%ld ", ifile_size, isize));
fprintf(stderr, "%s: %s: file size changed while zipping\n",
progname, ifname);
}
#endif
/* Write the crc and uncompressed size */
put_long(crc);
put_long(isize);
header_bytes += 2*sizeof(long);
flush_outbuf();
return OK;
}
/* ===========================================================================
* Read a new buffer from the current input file, perform end-of-line
* translation, and update the crc and input file size.
* IN assertion: size >= 2 (for end-of-line translation)
*/
int file_read(buf, size)
char *buf;
unsigned size;
{
unsigned len;
Assert(insize == 0, "inbuf not empty");
len = read(ifd, buf, size);
if (len == (unsigned)(-1) || len == 0) return (int)len;
crc = updcrc((uch*)buf, len);
isize += (ulg)len;
return (int)len;
}

42
gnu/usr.bin/gzip/zmore Normal file
View file

@ -0,0 +1,42 @@
#!/bin/sh
if test "`echo -n a`" = "-n a"; then
# looks like a SysV system:
n1=''; n2='\c'
else
n1='-n'; n2=''
fi
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 $# = 0; then
gzip -cd | eval ${PAGER-more}
else
FIRST=1
for FILE
do
if test $FIRST -eq 0; then
echo $n1 "--More--(Next file: $FILE)$n2"
stty $cb -echo 2>/dev/null
ANS=`dd bs=1 count=1 2>/dev/null`
stty $ncb echo 2>/dev/null
echo " "
if test "$ANS" = 'e' -o "$ANS" = 'q'; then
exit
fi
fi
if test "$ANS" != 's'; then
echo "------> $FILE <------"
gzip -cd "$FILE" | eval ${PAGER-more}
fi
if test -t; then
FIRST=0
fi
done
fi

134
gnu/usr.bin/gzip/zmore.1 Normal file
View file

@ -0,0 +1,134 @@
.TH ZMORE 1
.SH NAME
zmore \- file perusal filter for crt viewing of compressed text
.SH SYNOPSIS
.B zmore
[ name ... ]
.SH DESCRIPTION
.I Zmore
is a filter which allows examination of compressed text files
one screenful at a time on a soft-copy terminal.
It normally pauses after each screenful, printing --More--
at the bottom of the screen.
If the user then types a carriage return, one more line is displayed.
If the user hits a space,
another screenful is displayed. Other possibilities are enumerated later.
.PP
.I Zmore
looks in the file
.I /etc/termcap
to determine terminal characteristics,
and to determine the default window size.
On a terminal capable of displaying 24 lines,
the default window size is 22 lines.
To use a pager other than the default
.I more,
set environment variable PAGER to the name of the desired program, such as
.I less.
.PP
Other sequences which may be typed when
.I zmore
pauses, and their effects, are as follows (\fIi\fP is an optional integer
argument, defaulting to 1) :
.PP
.IP \fIi\|\fP<space>
display
.I i
more lines, (or another screenful if no argument is given)
.PP
.IP ^D
display 11 more lines (a ``scroll'').
If
.I i
is given, then the scroll size is set to \fIi\|\fP.
.PP
.IP d
same as ^D (control-D)
.PP
.IP \fIi\|\fPz
same as typing a space except that \fIi\|\fP, if present, becomes the new
window size. Note that the window size reverts back to the default at the
end of the current file.
.PP
.IP \fIi\|\fPs
skip \fIi\|\fP lines and print a screenful of lines
.PP
.IP \fIi\|\fPf
skip \fIi\fP screenfuls and print a screenful of lines
.PP
.IP "q or Q"
quit reading the current file; go on to the next (if any)
.PP
.IP "e or q"
When the prompt --More--(Next file:
.IR file )
is printed, this command causes zmore to exit.
.PP
.IP s
When the prompt --More--(Next file:
.IR file )
is printed, this command causes zmore to skip the next file and continue.
.PP
.IP =
Display the current line number.
.PP
.IP \fIi\|\fP/expr
search for the \fIi\|\fP-th occurrence of the regular expression \fIexpr.\fP
If the pattern is not found,
.I zmore
goes on to the next file (if any).
Otherwise, a screenful is displayed, starting two lines before the place
where the expression was found.
The user's erase and kill characters may be used to edit the regular
expression.
Erasing back past the first column cancels the search command.
.PP
.IP \fIi\|\fPn
search for the \fIi\|\fP-th occurrence of the last regular expression entered.
.PP
.IP !command
invoke a shell with \fIcommand\|\fP.
The character `!' in "command" are replaced with the
previous shell command. The sequence "\\!" is replaced by "!".
.PP
.IP ":q or :Q"
quit reading the current file; go on to the next (if any)
(same as q or Q).
.PP
.IP .
(dot) repeat the previous command.
.PP
The commands take effect immediately, i.e., it is not necessary to
type a carriage return.
Up to the time when the command character itself is given,
the user may hit the line kill character to cancel the numerical
argument being formed.
In addition, the user may hit the erase character to redisplay the
--More-- message.
.PP
At any time when output is being sent to the terminal, the user can
hit the quit key (normally control\-\\).
.I Zmore
will stop sending output, and will display the usual --More--
prompt.
The user may then enter one of the above commands in the normal manner.
Unfortunately, some output is lost when this is done, due to the
fact that any characters waiting in the terminal's output queue
are flushed when the quit signal occurs.
.PP
The terminal is set to
.I noecho
mode by this program so that the output can be continuous.
What you type will thus not show on your terminal, except for the / and !
commands.
.PP
If the standard output is not a teletype, then
.I zmore
acts just like
.I zcat,
except that a header is printed before each file.
.SH FILES
.DT
/etc/termcap Terminal data base
.SH "SEE ALSO"
more(1), gzip(1), zcmp(1), znew(1), zforce(1), gzexe(1)

140
gnu/usr.bin/gzip/znew Normal file
View file

@ -0,0 +1,140 @@
#!/bin/sh
check=0
pipe=0
opt=
files=
keep=0
res=0
old=0
new=0
block=1024
# block is the disk block size (best guess, need not be exact)
warn="(does not preserve modes and timestamp)"
tmp=/tmp/zfoo.$$
echo hi > $tmp.1
echo hi > $tmp.2
if test -z "`(${CPMOD-cpmod} $tmp.1 $tmp.2) 2>&1`"; then
cpmod=${CPMOD-cpmod}
warn=""
fi
if test -z "$cpmod" && ${TOUCH-touch} -r $tmp.1 $tmp.2 2>/dev/null; then
cpmod="${TOUCH-touch}"
cpmodarg="-r"
warn="(does not preserve file modes)"
fi
rm -f $tmp.[12]
A=
fileno=0
for arg
do
case "$arg" in
-*) opt="$opt $arg";;
*) fileno=`expr $fileno + 1`
eval A$fileno=\$arg
A="$A \"\$A$fileno\""
;;
esac
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 " -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 " -P use pipes for the conversion $warn"
exit 1
fi
eval set "$A" # the files are now in $1, $2, ...
opt=`echo "$opt" | sed -e 's/ //g' -e 's/-//g'`
case "$opt" in
*t*) check=1; opt=`echo "$opt" | sed 's/t//g'`
esac
case "$opt" in
*K*) keep=1; opt=`echo "$opt" | sed 's/K//g'`
esac
case "$opt" in
*P*) pipe=1; opt=`echo "$opt" | sed 's/P//g'`
esac
if test -n "$opt"; then
opt="-$opt"
fi
for i do
n=`echo $i | sed 's/.Z$//'`
if test ! -f "$n.Z" ; then
echo $n.Z not found
res=1; continue
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
# Copy file attributes from old file to new one, if possible.
test -n "$cpmod" && $cpmod $cpmodarg "$n.Z" "$n.gz" 2> /dev/null
else
echo error while recompressing $n.Z
res=1; continue
fi
else
if test $check -eq 1; then
if cp -p "$n.Z" "$n.$$" 2> /dev/null || cp "$n.Z" "$n.$$"; then
:
else
echo cannot backup "$n.Z"
res=1; continue
fi
fi
if gzip -d "$n.Z"; then
:
else
test $check -eq 1 && mv "$n.$$" "$n.Z"
echo error while uncompressing $n.Z
res=1; continue
fi
if gzip $opt "$n"; then
:
else
if test $check -eq 1; then
mv "$n.$$" "$n.Z" && rm -f "$n"
echo error while recompressing $n
else
# compress $n (might be dangerous if disk full)
echo error while recompressing $n, left uncompressed
fi
res=1; continue
fi
fi
test $keep -eq 1 && new=`wc -c < "$n.gz"`
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"
elif test $check -eq 1; then
mv "$n.$$" "$n.Z" && rm -f "$n.gz"
else
gzip -d "$n.gz" && compress "$n" && rm -f "$n.gz"
fi
echo "$n.Z smaller than $n.gz -- unchanged"
elif test $check -eq 1; then
if gzip -t "$n.gz" ; 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
res=1; continue
fi
elif test $pipe -eq 1; then
rm -f "$n.Z"
fi
done
exit $res

36
gnu/usr.bin/gzip/znew.1 Normal file
View file

@ -0,0 +1,36 @@
.TH ZNEW 1
.SH NAME
znew \- recompress .Z files to .gz files
.SH SYNOPSIS
.B znew
[ -ftv9PK] [ name.Z ... ]
.SH DESCRIPTION
.I Znew
recompresses files from .Z (compress) format to .gz (gzip) format.
.SH OPTIONS
.B \-f
Force recompression from .Z to .gz format even if a .gz file already exists.
.TP
.B \-t
Tests the new files before deleting originals.
.TP
.B \-v
Verbose. Display the name and percentage reduction for each file compressed.
.TP
.B \-9
Use the slowest compression method (optimal compression).
.TP
.B \-P
Use pipes for the conversion to reduce disk space usage.
.TP
.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)
.SH BUGS
.I Znew
does not maintain the time stamp with the -P option if
.I cpmod(1)
is not available and
.I touch(1)
does not support the -r option.