Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

v25i143: zip - file compression/archive tool, Part02/07

8 views
Skip to first unread message

Mark Adler

unread,
Mar 1, 1992, 10:07:05 PM3/1/92
to
Submitted-By: mad...@cco.caltech.edu (Mark Adler)
Posting-Number: Volume 25, Issue 143
Archive-Name: zip/part02

#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 2 (of 7)."
# Contents: im_lm.asm implode.c shrink.c util.c zip.h zipnote.c
# zipup.c
# Wrapped by vi...@cognition.pa.dec.com on Sun Mar 1 18:57:37 1992
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'im_lm.asm' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'im_lm.asm'\"
else
echo shar: Extracting \"'im_lm.asm'\" \(9944 characters\)
sed "s/^X//" >'im_lm.asm' <<'END_OF_FILE'
X;
X; Copyright (C) 1990,1991 Mark Adler, Richard B. Wales, and Jean-loup Gailly.
X; Permission is granted to any individual or institution to use, copy, or
X; redistribute this software so long as all of the original files are included
X; unmodified, that it is not sold for profit, and that this copyright notice
X; is retained.
X;
X
X; im_lm.asm by Jean-loup Gailly.
X
X;im_lm.asm, optimized version of longest_match() and lm_process() in im_lmat.c
X; Must be assembled with masm -ml. To be used only with C small model or
X; compact model. This file is only optional. If you don't have masm, use the
X; C version (add -DNO_ASM to CFLAGS in makefile.dos and remove im_lm.obj
X; from OBJI).
X;
X; Turbo C 2.0 does not support static allocation of far data in
X; the small model. So TC 2.0 users must assemble this with:
X; tasm -ml -DDYN_ALLOC im_lm;
X; OS/2 users must assemble this with -DOS2 -ml. To simplify the code,
X; the option -DDYN_ALLOC is not supported for OS/2.
X name im_lm
X
ifndef DYN_ALLOC
X extrn _prev : word
X extrn _next : word
X prev equ _prev
X next equ _next
load_es_prev macro
X mov cx,seg _prev
X mov es,cx
endm
load_ds_next macro
X mov si,seg _next
X mov ds,si
endm
endif
X
X_BSS segment word public 'BSS'
X extrn _window : byte
X extrn _match_length : word
X extrn _start_length : word
X extrn _strstart : word
X extrn _strsize : word
X extrn _ins_h : word
X extrn _h_shift : byte
X extrn _checkpoint : word
X extrn _bufsize : word
X extrn _max_chain_length : word
X extrn _min_match_length : word
ifdef DYN_ALLOC
X extrn _prev : word
X extrn _next : word
X prev equ 0 ; offset normalized to zero (except for OS/2)
X next equ 0 ; offset normalized to zero (except for OS/2)
load_es_prev macro
X mov es,_prev[2] ; warning: the offset should be added under OS/2
endm
load_ds_next macro
X mov ds,_next[2] ; warning: the offset should be added under OS/2
endm
endif
X cur_best dw 1 dup(?) ; best match within longest_match
X_BSS ends
X
DGROUP group _BSS
X
X_TEXT segment word public 'CODE'
X assume cs: _TEXT, ds: DGROUP, ss: DGROUP
X
X extrn _write_match : near
X
X BSZ equ 4096 ; keep consistent with tailor.h
X WSIZE equ 8192 ; keep consistent with im_lmat.c
X NIL equ (WSIZE+BSZ)
X MAX_DIST equ NIL
X MAX_LENGTH equ 320 ; keep consistent with im_lmat.c
X HASH_MASK equ 16383 ; (1<<14)-1
X
X; Process a block of characters already inserted in the window
X; IN assertion: count > 0
X public _lm_process
X_lm_process proc near
X push bp
X mov bp,sp
X push di
X push si
X
X count equ word ptr [bp+4]
X; delete_point equ ax
X; ins_h equ bx
X; h_shift equ cl
X; count equ dx
X; cur_match equ si
X; strstart equ di
X; min_match_length equ bp
X
X mov dx,count
X mov bx,_ins_h
X mov di,_strstart
X lea ax,[di+MAX_LENGTH-1]
X sub ax,_bufsize
X jae del_ok
X add ax,MAX_DIST
del_ok: shl ax,1 ;delete_point as word index
X load_es_prev
X mov cl,_h_shift
X load_ds_next
X assume ds: nothing
X jmp short insert
X
start_overflow:
X sub di,di ;strstart = 0
X sub ss:_checkpoint,MAX_DIST
X jmp short check_count
del_overflow:
X mov ax,-2 ;delete_point = 0
main_loop:
X add ax,2 ;delete_point++ (word index)
X cmp ax,2*MAX_DIST
X je del_overflow
X xchg ax,si ;si=2*delete_point
X mov bp,next[si]
X shl bp,1
X mov es:prev[bp],NIL
X xchg ax,si ;ax=2*delete_point
X
X inc di ;strstart++
X cmp di,MAX_DIST
X je start_overflow
check_count:
X dec dx ;count--
X jz end_proc_ok
insert:
X shl bx,cl ;ins_h <<= h_shift
X mov bp,ss:_min_match_length
X xor bl,_window[di+bp-1] ;ins_h ^= window[s+min_match_length-1]
X and bx,HASH_MASK
X add bx,MAX_DIST+1
X shl bx,1 ;word index
X mov si,es:prev[bx] ;cur_match = match_head[ins_h]
X mov es:prev[bx],di ;prev[ins_h+MAX_DIST+1] = strstart
X shr bx,1 ;bx = ins_h + MAX_DIST + 1
X shl di,1 ;di = strstart as word index
X mov next[di],bx
X sub bx,MAX_DIST+1 ;bx = ins_h
X mov es:prev[di],si ;prev[s] = cur_match
X shr di,1 ;di = strstart
X shl si,1
X mov next[si],di ;next[cur_match] = strstart
X cmp di,ss:_checkpoint
X jne main_loop
X
X push ax
X push bx
X push dx
X mov ax,ss
X mov ds,ax
X assume ds: DGROUP
X mov _match_length,0
X mov _strstart,di
X shr si,1 ;si = cur_match
X cmp si,NIL ;cur_match == NIL ?
X je call_write
X call _longest_match ;returns best_match in si
call_write:
X push _match_length
X push si ;best_match or NIL
X call _write_match
X add sp,4
X pop dx
X pop bx
X or al,al
X jnz failure
X pop ax
X load_es_prev
X mov cl,_h_shift
X load_ds_next
X assume ds: nothing
X jmp main_loop
end_proc_ok:
X mov ax,ss
X mov ds,ax
X assume ds: DGROUP
X sub ax,ax
X mov _strstart,di
end_proc:
X mov _ins_h,bx
X pop si
X pop di
X pop bp
X ret
failure:
X add sp,2 ;skip pushed ax
X jmp short end_proc
X
X_lm_process endp
X
X; Find the longest match starting at the given string. Return its position
X; and set its length in match_length. Matches shorter or equal to
X; start_length are discarded, in which case match_length is unchanged
X; and the result position is NIL.
X; IN assertions: cur_match is the head of the hash chain for the current
X; string (strstart) and is not NIL, start_length >= 1.
X; registers: es points to the base of the prev array (preserved)
X; si = cur_match and return value
X; di = strstart
X
X; IPos longest_match(cur_match)
X
X public _longest_match
X_longest_match proc near
X
X push bp
X push di
X
X; match equ si
X; scan equ di
X; chain_count equ bp
X; ma_length equ bx
X
X lea di,_window[di+2] ; di = window + strstart + 2
X mov cur_best,NIL
X mov bp,_max_chain_length ; chain_count = max_chain_length
X mov bx,_start_length ; ma_length = start_length
X mov ax,[bx+di-3] ; ax = scan[ma_length-1..ma_length]
X mov cx,[di-2] ; cx = scan[0..1]
X jmp short do_scan
X
X even ; align destination of branch
long_loop:
X; at this point, di == scan+2, si = cur_match
X mov ax,[bx+di-3] ; ax = scan[ma_length-1..ma_length]
X mov cx,[di-2] ; cx = scan[0..1]
short_loop:
X dec bp ; --chain_count
X jz the_end
X; at this point, di == scan+2, si = cur_match,
X; ax = scan[ma_length-1..ma_length] and cx = scan[0..1]
X shl si,1 ; cur_match as word index
X mov si,es:prev[si] ; cur_match = prev[cur_match]
X cmp si,NIL
X je the_end
do_scan:
X cmp ax,word ptr _window[bx+si-1] ; check match at ma_length-1
X jne short_loop
X cmp cx,word ptr _window[si] ; check min_match_length match
X jne short_loop
X mov dx,si ; dx = cur_match
X lea si,_window[si+2] ; si = match
X mov ax,di ; ax = scan+2
X mov cx,ds
X mov es,cx
X mov cx,(MAX_LENGTH-2)/2 ; scan for at most MAX_LENGTH bytes
X repe cmpsw ; loop until mismatch
X load_es_prev ; reset es to address the prev array
X mov cl,[di-2] ; mismatch on first or second byte?
X sub cl,[si-2] ; dl = 0 if first bytes equal
X xchg ax,di ; di = scan+2, ax = end of scan
X sub ax,di ; ax = len
X sub cl,1 ; set carry if cl == 0 (can't use DEC)
X adc ax,0 ; ax = carry ? len+1 : len
X mov si,dx ; si = cur_match
X cmp ax,bx ; len > ma_length ?
X jle long_loop
X mov cur_best,si ; cur_best = cur_match
X mov bx,ax ; bx = ma_length = len
X cmp ax,_strsize ; len >= strsize ?
X jle long_loop
the_end:
X cmp bx,_start_length ; ma_length > start_length ?
X jle return
X mov _match_length,bx ; match_length = ma_length
return:
X mov si,cur_best ; result = cur_best
X pop di
X pop bp
X ret
X
X_longest_match endp
X
X_TEXT ends
end
END_OF_FILE
if test 9944 -ne `wc -c <'im_lm.asm'`; then
echo shar: \"'im_lm.asm'\" unpacked with wrong size!
fi
# end of 'im_lm.asm'
fi
if test -f 'implode.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'implode.c'\"
else
echo shar: Extracting \"'implode.c'\" \(8838 characters\)
sed "s/^X//" >'implode.c' <<'END_OF_FILE'
X/*
X
X Copyright (C) 1990,1991 Mark Adler, Richard B. Wales, and Jean-loup Gailly.
X Permission is granted to any individual or institution to use, copy, or
X redistribute this software so long as all of the original files are included
X unmodified, that it is not sold for profit, and that this copyright notice
X is retained.
X
X*/
X
X/*
X * implode.c by Richard B. Wales.
X *
X * PURPOSE
X *
X * Compress an input file using the ZIP "implosion" method.
X *
X * DISCUSSION
X *
X * The "implosion" algorithm is a composite of (1) OPM/L compres-
X * sion within a sliding window, and (2) variable-length binary
X * encoding of various parts of the OPM/L output.
X *
X * For a detailed treatment of OPM/L compression, see the source
X * file "im_lmat.c".
X *
X * For a detailed treatment of variable-length binary encoding,
X * see the source file "im_ctree.c".
X *
X * Since Pass Two (binary encoding) depends on a statistical anal-
X * ysis of the entire output of Pass One (OPM/L compression), the
X * Pass One output is saved in a temporary file and re-read for
X * Pass Two. Implosion is thus a two-pass algorithm.
X *
X * An outline of the algorithm follows:
X *
X * (1) The entire input file is read and compressed via the OPM/L
X * technique. The OPM/L output is saved in a temporary file.
X *
X * (2) The compressed info from (1) is analyzed, and various fre-
X * quency counts are tallied.
X *
X * (3) Based on the frequency counts, a decision is made as to
X * whether or not the "literal" characters (those not matched
X * in earlier parts of the input) should be represented via a
X * binary code tree or left "as is". If there are not very
X * many literal characters, or if their frequency distribution
X * is fairly even, the number of bits saved through coding may
X * be exceeded by the amount of info which must be included to
X * describe the tree.
X *
X * (4) The temporary file from (1) is re-read. The information is
X * further compressed via the binary code trees, and the result
X * is sent to the ZIP output file.
X *
X * REFERENCES
X *
X * APPNOTE.TXT documentation file in PKZIP 1.10 distribution.
X *
X * See also references in the "im_lmat.c" and "im_ctree.c" source
X * files.
X *
X * INTERFACE
X *
X * int imp_setup (long filesize, int pack_level)
X * Initialize the "implode" routines for a new file.
X *
X * int imp_p1 (char *buf, int count)
X * Process "count" input characters pointed to by "buf". This
X * routine is called as many times as needed to process the
X * entire input file. There is no upper limit on "count".
X *
X * int imp_size (long *size, char *opts)
X * Terminate processing of the input file, and return the com-
X * pressed size ("size") and implosion option flags ("opts").
X *
X * int imp_p2 (FILE *outfp)
X * Output the entire compressed file -- including S-F trees and
X * data -- to the ZIP output file "outfp".
X *
X * int imp_clear (void)
X * Clean up after processing and outputting a file. This rou-
X * tine may be called at any time to abort further processing.
X *
X * All the above routines return zero if successful, or a non-zero
X * value if there was an error.
X */
X
X#include "implode.h"
X#include "ziperr.h"
X
X
X/***********************************************************************
X *
X * Error return codes for the main ZIP program.
X * Most of these are in "ziperr.h".
X */
X
X#define ZE_MAP(err) \
X ( ((err) == IM_OK) ? ZE_OK \
X : ((err) == IM_NOMEM) ? ZE_MEM \
X : ((err) == IM_IOERR) ? ZE_TEMP \
X : (fprintf(stderr,"\nZE_MAP(%d)",(err)), \
X ZE_LOGIC))
X
X
X/***********************************************************************
X *
X * State variable for the implosion routines.
X */
X
X#define IMP_SETUP 0 /* need to do "imp_setup" */
X#define IMP_P1 1 /* setup done, ready for Pass 1 */
X#define IMP_P2 2 /* Pass 1 done, ready for Pass 2 */
X#define IMP_CLEAR 3 /* Pass 2 done, ready for "imp_clear" */
X
local int imp_state = IMP_SETUP;
X
X
X/***********************************************************************
X *
X * Global variables.
X */
X
XFDATA fd;
X
X
X/***********************************************************************
X *
X * Set up for performing implosion on a new file.
X */
X
int
imp_setup (filesize, pack_level)
X long filesize; /* input file size */
X int pack_level; /* 0 = best speed, 9 = best compression, other = default */
X{
X ImpErr retcode;
X extern char *tempname();
X
X if (imp_state != IMP_SETUP)
X { fprintf (stderr, "\nimp_setup called with wrong state %d",
X imp_state);
X return ZE_LOGIC;
X }
X imp_state = IMP_P1;
X
X /* Set up the initial parameters. Use an 8K window if the input
X * file is greater than or equal to 5.5K, a 4K window otherwise.
X */
X fd.fd_bufsize = 8192;
X if (filesize < 5632) fd.fd_bufsize = 4096;
X
X fd.fd_strsize = 320;
X fd.fd_nbits = (fd.fd_bufsize == 4096) ? 6 : 7;
X
X /* Create a temporary file for the Pass One output. */
X fd.fd_temp = topen ('I');
X if (fd.fd_temp == NULL)
X return ZE_MEM;
X
X /*
X * Initialize the "longest match" routines.
X * "ct_init" is called at this point because the "lm_input" routine
X * (called in "imp_p1") calls the "ct_tally" routine.
X */
X retcode = lm_init (pack_level);
X if (retcode != IM_OK) return ZE_MAP (retcode);
X retcode = ct_init ();
X return ZE_MAP (retcode);
X}
X
X
X/***********************************************************************
X *
X * Feed characters to the implosion computation.
X * This routine is called as many times as needed, until the entire
X * input file has been processed.
X */
X
int
imp_p1 (buf, count)
X char *buf; /* input characters */
X int count; /* character count */
X{ ImpErr retcode;
X
X if (imp_state != IMP_P1)
X { fprintf (stderr, "\nimp_p1 called with wrong state %d",
X imp_state);
X return ZE_LOGIC;
X }
X
X if (buf == NULL || count < 0)
X { fprintf (stderr, "\nimp_p1 called with bad arguments");
X return ZE_LOGIC;
X }
X retcode = lm_input ((U_CHAR *) buf, (U_INT) count);
X return ZE_MAP (retcode);
X}
X
X
X/***********************************************************************
X *
X * Terminate processing of input for this file, and determine the size
X * this file will have if it is imploded. Also, find out whether two
X * or three S-F trees will be used (needed for directory entries).
X */
X
int
imp_size (size, opts)
X long *size; /* imploded size */
X char *opts; /* implosion option info */
X{ ImpErr retcode;
X
X if (imp_state != IMP_P1)
X { fprintf (stderr, "\nimp_size called with wrong state %d",
X imp_state);
X return ZE_LOGIC;
X }
X imp_state = IMP_P2;
X
X if (size == NULL || opts == NULL)
X { fprintf (stderr, "\nimp_size called with bad arguments");
X return ZE_LOGIC;
X }
X retcode = lm_windup ();
X if (retcode != IM_OK) return ZE_MAP (retcode);
X retcode = ct_mktrees ();
X if (retcode != IM_OK) return ZE_MAP (retcode);
X *size = fd.fd_clen;
X *opts = (char)(((fd.fd_bufsize == 8192) ? 0x02 : 0)
X | ((fd.fd_method == LITERAL_TREE) ? 0x04 : 0));
X return ZE_OK;
X}
X
X
X/***********************************************************************
X *
X * Output the imploded version of the file (but not the file directory
X * info) to the ZIP file.
X */
X
int
imp_p2 (outfp)
X FILE *outfp; /* output (ZIP) file */
X{ ImpErr retcode;
X
X if (imp_state != IMP_P2)
X { fprintf (stderr, "\nimp_p2 called with wrong state %d",
X imp_state);
X return ZE_LOGIC;
X }
X imp_state = IMP_CLEAR;
X
X if (outfp == NULL)
X { fprintf (stderr, "\nimp_p2 called with bad arguments");
X return ZE_LOGIC;
X }
X retcode = ct_wrtrees (outfp);
X if (retcode != IM_OK) return ZE_MAP (retcode);
X retcode = ct_wrdata (outfp);
X if (retcode != IM_OK) return ZE_MAP (retcode);
X fflush (outfp);
X if (ferror (outfp)) return ZE_TEMP;
X return ZE_OK;
X}
X
X
X/***********************************************************************
X *
X * Clean up after doing an implosion.
X * This routine may also be called at any time to abort an implosion.
X */
X
int
imp_clear ()
X{ (void) lm_windup ();
X if (fd.fd_temp != NULL)
X (void) tclose (fd.fd_temp);
X (void) ct_windup ();
X imp_state = IMP_SETUP;
X return ZE_OK;
X}
X
X
X/**********************************************************************/
END_OF_FILE
if test 8838 -ne `wc -c <'implode.c'`; then
echo shar: \"'implode.c'\" unpacked with wrong size!
fi
# end of 'implode.c'
fi
if test -f 'shrink.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'shrink.c'\"
else
echo shar: Extracting \"'shrink.c'\" \(10431 characters\)
sed "s/^X//" >'shrink.c' <<'END_OF_FILE'
X/*
X
X Copyright (C) 1990,1991 Mark Adler, Richard B. Wales, and Jean-loup Gailly.
X Permission is granted to any individual or institution to use, copy, or
X redistribute this software so long as all of the original files are included
X unmodified, that it is not sold for profit, and that this copyright notice
X is retained.
X
X*/
X
X/*
X * shrink.c by Mark Adler.
X */
X
X#include "zip.h"
X#include "tempf.h"
X
X
X/*
X Shrink.Pas version 1.2 by R. P. Byrne, 1989 (in Pascal and assembler).
X We here heartily acknowledge R. P. Byrne's contribution to this project.
X The existence of this program really triggered our efforts to write a
X portable Unix zip. What little remains of Byrne's program lies in this
X source file, and those remnants are mostly in the variable and routine
X names, since it has been translated and extensively modified and rewritten.
X
X Stolen, translated into C, and modified by Mark Adler, 11 October 1990.
X Severely modified again by Mark Adler, 11 July 1991, to remove the
X unnecessary FreeList and ClearTable arrays, and to replace the recursive
X Prune() routine with a non-recursive method.
X As Stravinsky once said: "Mediocre composers plagiarize.
X Great composers steal."
X*/
X
X/* Compress a set of input files into a Zip file using Lempel-Ziv-Welch */
X/* (LZW) compression techniques (the "shrink" method). */
X
X
X#define MINBITS 9 /* Starting code size of 9 bits */
X#define MAXBITS 13 /* Maximum code size of 13 bits */
X#define TABLESIZE 8191 /* We'll need 4K entries in table */
X#define SPECIAL 256 /* Special function code */
X#define INCSIZE 1 /* Code for a jump in code size */
X#define CLEARCODE 2 /* Code for code table has been cleared */
X#define FIRSTENTRY 257 /* First available table entry */
X
X
X/* Define data types needed to implement a code table for LZW compression */
X
typedef struct CodeRec {
X /* Code Table record format... */
X short Child; /* Addr of 1st suffix for this prefix */
X short Sibling; /* Addr of next suffix in chain */
X uch Suffix; /* Suffix character */
X} CodeRec;
X
typedef CodeRec CodeArray[TABLESIZE + 1]; /* Define the code table */
X
X
X
X/* Private globals */
local CodeRec far *CodeTable; /* Points to code table for LZW compression */
X
local int NextFree; /* Next free table entry */
X
local int CodeSize; /* Size of codes (in bits) currently being written */
local int MaxCode; /* Largest code that can be written in CodeSize bits */
X
local int FirstCh; /* Flag indicating the START of a shrink operation */
X
local tFILE *tempf = NULL; /* Temporary file */
local ulg count; /* Count of bytes written */
X
X
X/* Local functions */
X#ifdef PROTO
X local void PutCode(int);
X local int Build_Data_Structures(void);
X local void Destroy_Data_Structures(void);
X local void Initialize_Data_Structures(void);
X local void Clear_Table(void);
X local void Table_Add(int, int);
X#endif /* PROTO */
X
X
X/* Macro for PutCode() that writes to tempf and counts bytes in count */
X#define PUT(c) {tputc(c, tempf); count++;}
X
local void PutCode(c)
int c; /* code to send */
X/* Write out the low CodeSize bits of c using the PUT macro. If c is -1,
X then flush the bit buffer. Assumes CodeSize < 16. By Mark Adler. */
X{
X static int b = 0; /* current bits waiting to go out */
X static int n = 0; /* number of bits in b */
X /* masks for all bit values */
X static int x[] = {0, 1, 3, 7, 0xf, 0x1f, 0x3f, 0x7f, 0xff, 0x1ff,
X 0x3ff, 0x7ff, 0xfff, 0x1fff, 0x3fff, 0x7fff, 0xffff};
X
X if (c == -1)
X {
X if (n)
X {
X if (n > 8)
X {
X PUT((char)b)
X PUT((char)((b >> 8) & x[n - 8]))
X }
X else
X PUT((char)(b & x[n]))
X b = n = 0;
X }
X }
X else
X {
X b |= (c & x[CodeSize]) << n;
X n += CodeSize;
X if (n >= 16)
X {
X PUT((char)b)
X PUT((char)(b >> 8))
X if (n == 16)
X b = n = 0;
X else
X {
X n -= 16;
X b = (c >> (CodeSize - n)) & x[n];
X }
X }
X }
X}
X
X
X
local int Build_Data_Structures()
X/* Allocate tables for shrinking. Return true on failure. */
X{
X return (CodeTable = (CodeRec far *)farmalloc(sizeof(CodeArray))) == NULL;
X}
X
X
X
local void Destroy_Data_Structures()
X/* Deallocate tables for shrinking. */
X{
X if (CodeTable != NULL)
X {
X farfree((voidp far *)CodeTable);
X CodeTable = NULL;
X }
X}
X
X
X
local void Initialize_Data_Structures()
X/* Clear tables for shrinking. */
X{
X int i; /* counter for table entries */
X CodeRec far *t; /* pointer to current table entry */
X
X /* Initialize parent symbols */
X for (i = 0, t = CodeTable; i <= 255; i++, t++)
X {
X t->Child = -1;
X t->Suffix = (uch)i;
X }
X
X /* Build free list */
X NextFree = FIRSTENTRY;
X for (i = FIRSTENTRY, t = CodeTable + FIRSTENTRY; i < TABLESIZE; i++, t++)
X t->Child = i + 1;
X t->Child = -1;
X}
X
X
X
local void Clear_Table()
X/* Clear the leaves of the tree--assume all entries used (NextFree == -1) */
X{
X int n; /* node counter */
X CodeRec far *p; /* pointer to next node to look at */
X short far *q; /* pointer to node child or sibling entry */
X
X /* Mark leaf nodes */
X p = CodeTable + TABLESIZE;
X n = TABLESIZE + 1 - FIRSTENTRY;
X do {
X if (p->Child == -1)
X p->Child = -2;
X p--;
X } while (--n);
X
X /* Shake leaves from tree */
X p = CodeTable;
X n = 256;
X do {
X q = &p->Child;
X while (*q != -1 && CodeTable[*q].Child == -2)
X *q = CodeTable[*q].Sibling;
X p++;
X } while (--n);
X p = CodeTable + FIRSTENTRY;
X n = TABLESIZE + 1 - FIRSTENTRY;
X do {
X if (p->Child != -2)
X {
X q = &p->Child;
X while (*q != -1 && CodeTable[*q].Child == -2)
X *q = CodeTable[*q].Sibling;
X q = &p->Sibling;
X while (*q != -1 && CodeTable[*q].Child == -2)
X *q = CodeTable[*q].Sibling;
X }
X p++;
X } while (--n);
X
X /* Build the list of free table entries */
X NextFree = -1;
X p = CodeTable + TABLESIZE;
X n = TABLESIZE + 1 - FIRSTENTRY;
X do {
X if (p->Child == -2)
X {
X p->Child = NextFree;
X NextFree = n + FIRSTENTRY - 1;
X }
X p--;
X } while (--n);
X}
X
X
X
local void Table_Add(p, s)
int p; /* prefix to add to */
int s; /* suffix to add to it */
X/* Add an entry to the table. */
X{
X int f; /* next free node */
X
X if ((f = NextFree) != -1)
X {
X NextFree = CodeTable[f].Child;
X CodeTable[f].Child = -1;
X CodeTable[f].Sibling = -1;
X CodeTable[f].Suffix = (uch)s;
X if (CodeTable[p].Child == -1)
X CodeTable[p].Child = f;
X else
X {
X p = CodeTable[p].Child;
X while (CodeTable[p].Sibling != -1)
X p = CodeTable[p].Sibling;
X CodeTable[p].Sibling = f;
X }
X }
X}
X
X
local int lastcode;
X
int shr_setup()
X/* Initialize shrink() routines. Return an error code in the ZE_ class. */
X{
X if (Build_Data_Structures())
X return ZE_MEM;
X Initialize_Data_Structures();
X FirstCh = 1;
X lastcode = -1;
X if ((tempf = topen('S')) == NULL)
X return ZE_MEM;
X count = 0;
X return ZE_OK;
X}
X
X
int shr_p1(b, n)
uch *b; /* buffer with bytes to shrink */
extent n; /* number of bytes in buffer */
X/* Shrink n bytes at *b. Return an error code in the ZE_ class. */
X{
X int f; /* result of Table_Lookup */
X int s; /* byte to shrink */
X
X if (FirstCh && n)
X { /* If just getting started ... */
X CodeSize = MINBITS; /* Initialize code size to minimum */
X MaxCode = (1 << CodeSize) - 1;
X lastcode = *b++; n--; /* get first character from input, */
X FirstCh = 0; /* and reset the first char flag. */
X }
X while (NextFree == -1 && n)
X {
X /* Ok, lets clear the code table (adaptive reset) */
X PutCode(lastcode);
X PutCode(SPECIAL);
X PutCode(CLEARCODE);
X Clear_Table();
X Table_Add(lastcode, s = *b++); n--;
X lastcode = s;
X }
X while (n)
X {
X s = *b++; n--;
X f = CodeTable[lastcode].Child;
X while (f != -1 && CodeTable[f].Suffix != (uch)s)
X f = CodeTable[f].Sibling;
X if (f != -1)
X /* If lastcode:s pair is found in the code table, then ... */
X /* ... set lastcode to the entry where the pair is located */
X lastcode = f;
X else
X {
X /* Not in table */
X PutCode(lastcode); /* Write current lastcode */
X Table_Add(lastcode, s); /* Attempt to add to code table */
X lastcode = s; /* Reset lastcode for new char */
X if (NextFree > MaxCode && CodeSize < MAXBITS)
X {
X /* Time to increase the code size and change the max. code */
X PutCode(SPECIAL);
X PutCode(INCSIZE);
X CodeSize++;
X MaxCode = (1 << CodeSize) - 1;
X }
X while (NextFree == -1 && n)
X {
X /* Ok, lets clear the code table (adaptive reset) */
X PutCode(lastcode);
X PutCode(SPECIAL);
X PutCode(CLEARCODE);
X Clear_Table();
X Table_Add(lastcode, s = *b++); n--;
X lastcode = s;
X }
X }
X }
X return ZE_OK;
X}
X
X
int shr_size(s)
ulg *s; /* return value: size of shrunk data */
X/* End shrink and return size of shrunk data in *s. Return an error code in
X the ZE_ class. */
X{
X PutCode(lastcode); /* Write last prefix code */
X PutCode(-1); /* Tell putcode to flush remaining bits */
X Destroy_Data_Structures();
X *s = count;
X return tflush(tempf) || terror(tempf) ? ZE_TEMP : ZE_OK;
X}
X
X
int shr_p2(f)
XFILE *f; /* file to write shrunk data to */
X/* Copy shrunk data from temporary file to zip file *f. Return an error
X code in the ZE_ class. */
X{
X char *b; /* malloc'ed buffer for copying */
X extent k; /* holds result of fread */
X
X if ((b = malloc(BSZ)) == NULL)
X return ZE_MEM;
X trewind(tempf);
X while ((k = tread(b, 1, BSZ, tempf)) > 0)
X if (zfwrite(b, 1, k, f) != k)
X {
X free((voidp *)b);
X return ZE_TEMP;
X }
X free((voidp *)b);
X if (terror(tempf))
X return ZE_TEMP;
X tclose(tempf);
X tempf = NULL;
X return ZE_OK;
X}
X
X
int shr_clear()
X/* Terminate shrink procedure (at any time). Return an error code in
X the ZE_ class (always ZE_OK). */
X{
X Destroy_Data_Structures();
X if (tempf != NULL)
X {
X tclose(tempf);
X tempf = NULL;
X }
X return ZE_OK;
X}
END_OF_FILE
if test 10431 -ne `wc -c <'shrink.c'`; then
echo shar: \"'shrink.c'\" unpacked with wrong size!
fi
# end of 'shrink.c'
fi
if test -f 'util.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'util.c'\"
else
echo shar: Extracting \"'util.c'\" \(10800 characters\)
sed "s/^X//" >'util.c' <<'END_OF_FILE'
X/*
X
X Copyright (C) 1990,1991 Mark Adler, Richard B. Wales, and Jean-loup Gailly.
X Permission is granted to any individual or institution to use, copy, or
X redistribute this software so long as all of the original files are included
X unmodified, that it is not sold for profit, and that this copyright notice
X is retained.
X
X*/
X
X/*
X * util.c by Mark Adler.
X */
X
X#include "zip.h"
X
X/* Local functions */
X#ifdef PROTO
X local int recmatch(char *, char *);
X#endif /* PROTO */
X
X
char *isshexp(p)
char *p; /* candidate sh expression */
X/* If p is a sh expression, a pointer to the first special character is
X returned. Otherwise, NULL is returned. */
X{
X int c;
X
X c = -1;
X for (; *p; p++)
X#ifdef VMS
X if (c != '\\' && (*p == '%' || *p == '*'))
X#else /* !VMS */
X if (c != '\\' && (*p == '?' || *p == '*' || *p == '['))
X#endif /* ?VMS */
X return p;
X return NULL;
X}
X
X
local int recmatch(p, s)
char *p; /* sh pattern to match */
char *s; /* string to match it to */
X/* Recursively compare the sh pattern p with the string s and return 1 if
X they match, and 0 or 2 if they don't or if there is a syntax error in the
X pattern. This routine recurses on itself no deeper than the number of
X characters in the pattern. */
X{
X int c; /* pattern char or start of range in [-] loop */
X
X /* Get first character, the pattern for new recmatch calls follows */
X c = *p++;
X
X /* If that was the end of the pattern, match if string empty too */
X if (c == 0)
X return *s == 0;
X
X /* '?' (or '%') matches any character (but not an empty string) */
X#ifdef VMS
X if (c == '%')
X#else /* !VMS */
X if (c == '?')
X#endif /* ?VMS */
X return *s ? recmatch(p, s + 1) : 0;
X
X /* '*' matches any number of characters, including zero */
X if (c == '*')
X {
X if (*p == 0)
X return 1;
X for (; *s; s++)
X if ((c = recmatch(p, s)) != 0)
X return c;
X return 2; /* 2 means give up--shmatch will return false */
X }
X
X#ifndef VMS /* No bracket matching in VMS */
X /* Parse and process the list of characters and ranges in brackets */
X if (c == '[')
X {
X int e; /* flag true if next char to be taken literally */
X char *q; /* pointer to end of [-] group */
X int r; /* flag true to match anything but the range */
X
X if (*s == 0) /* need a character to match */
X return 0;
X p += (r = *p == '!'); /* see if reverse */
X for (q = p, e = 0; *q; q++) /* find closing bracket */
X if (e)
X e = 0;
X else
X if (*q == '\\')
X e = 1;
X else if (*q == ']')
X break;
X if (*q != ']') /* nothing matches if bad syntax */
X return 0;
X for (c = 0, e = *p == '-'; p < q; p++) /* go through the list */
X {
X if (e == 0 && *p == '\\') /* set escape flag if \ */
X e = 1;
X else if (e == 0 && *p == '-') /* set start of range if - */
X c = *(p-1);
X else
X {
X if (*(p+1) != '-')
X for (c = c ? c : *p; c <= *p; c++) /* compare range */
X#ifdef OS2
X if (tolower(c) == tolower(*s))
X#else /* !OS2 */
X if (c == *s)
X#endif /* ?OS2 */
X return r ? 0 : recmatch(q + 1, s + 1);
X c = e = 0; /* clear range, escape flags */
X }
X }
X return r ? recmatch(q + 1, s + 1) : 0; /* bracket match failed */
X }
X#endif /* !VMS */
X
X /* If escape ('\'), just compare next character */
X if (c == '\\')
X if ((c = *p++) == 0) /* if \ at end, then syntax error */
X return 0;
X
X /* Just a character--compare it */
X#ifdef OS2
X return tolower(c) == tolower(*s) ? recmatch(p, ++s) : 0;
X#else /* !OS2 */
X return c == *s++ ? recmatch(p, s) : 0; /* compare one character */
X#endif /* ?OS2 */
X}
X
X
int shmatch(p, s)
char *p; /* sh pattern to match */
char *s; /* string to match it to */
X/* Compare the sh pattern p with the string s and return true if they match,
X false if they don't or if there is a syntax error in the pattern. */
X{
X return recmatch(p, s) == 1;
X}
X
X
X#ifdef MSDOS
X
int dosmatch(p, s)
char *p; /* dos pattern to match */
char *s; /* string to match it to */
X/* Break the pattern and string into name and extension parts and match
X each separately using shmatch(). */
X{
X char *p1, *p2; /* pattern sections */
X char *s1, *s2; /* string sections */
X int r; /* result */
X
X if ((p1 = malloc(strlen(p) + 1)) == NULL ||
X (s1 = malloc(strlen(s) + 1)) == NULL)
X {
X if (p1 != NULL)
X free((voidp *)p1);
X return 0;
X }
X strcpy(p1, p);
X strcpy(s1, s);
X if ((p2 = strrchr(p1, '.')) != NULL)
X *p2++ = 0;
X else
X p2 = "";
X if ((s2 = strrchr(s1, '.')) != NULL)
X *s2++ = 0;
X else
X s2 = "";
X r = shmatch(p2, s2) && shmatch(p1, s1);
X free((voidp *)p1);
X free((voidp *)s1);
X return r;
X}
X
X#endif /* MSDOS */
X
X
voidp far **search(b, a, n, cmp)
voidp *b; /* pointer to value to search for */
voidp far **a; /* table of pointers to values, sorted */
extent n; /* number of pointers in a[] */
int (*cmp) OF((voidp *, voidp far *)); /* comparison function for search */
X/* Search for b in the pointer list a[0..n-1] using the compare function
X cmp(b, c) where c is an element of a[i] and cmp() returns negative if
X *b < *c, zero if *b == *c, or positive if *b > *c. If *b is found,
X search returns a pointer to the entry in a[], else search() returns
X NULL. The nature and size of *b and *c (they can be different) are
X left up to the cmp() function. A binary search is used, and it is
X assumed that the list is sorted in ascending order. */
X{
X voidp far **i; /* pointer to midpoint of current range */
X voidp far **l; /* pointer to lower end of current range */
X int r; /* result of (*cmp)() call */
X voidp far **u; /* pointer to upper end of current range */
X
X l = (voidp far **)a; u = l + (n-1);
X while (u >= l)
X if ((r = (*cmp)(b, *(i = l + ((u - l) >> 1)))) < 0)
X u = i - 1;
X else if (r > 0)
X l = i + 1;
X else
X return (voidp far **)i;
X return NULL; /* If b were in list, it would belong at l */
X}
X
X
X
X/* Table of CRC-32's of all single byte values (made by makecrc.c) */
local ulg crctab[] = {
X 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
X 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
X 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
X 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
X 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
X 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
X 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
X 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
X 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
X 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
X 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
X 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
X 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
X 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
X 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
X 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
X 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
X 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
X 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
X 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
X 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
X 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
X 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
X 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
X 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
X 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
X 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
X 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
X 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
X 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
X 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
X 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
X 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
X 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
X 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
X 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
X 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
X 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
X 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
X 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
X 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
X 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
X 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
X 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
X 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
X 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
X 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
X 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
X 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
X 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
X 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
X 0x2d02ef8dL
X};
X
X
ulg crc32(c, b)
ulg c; /* current contents of crc shift register */
int b; /* byte (eight bits) to run through */
X/* Return the CRC-32 c updated with the eight bits in b. */
X{
X return crctab[((int)c ^ b) & 0xff] ^ (c >> 8);
X}
X
X
ulg updcrc(s, n)
char *s; /* pointer to bytes to pump through */
extent n; /* number of bytes in s[] */
X/* Run a set of bytes through the crc shift register. If s is a NULL
X pointer, then initialize the crc shift register contents instead.
X Return the current crc in either case. */
X{
X register ulg c; /* temporary variable */
X
X static ulg crc = 0xffffffffL; /* shift register contents */
X
X if (s == NULL)
X c = 0xffffffffL;
X else
X {
X c = crc;
X while (n--)
X c = crctab[((int)c ^ (*s++)) & 0xff] ^ (c >> 8);
X }
X crc = c;
X return c ^ 0xffffffffL; /* (instead of ~c for 64-bit machines) */
X}
END_OF_FILE
if test 10800 -ne `wc -c <'util.c'`; then
echo shar: \"'util.c'\" unpacked with wrong size!
fi
# end of 'util.c'
fi
if test -f 'zip.h' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'zip.h'\"
else
echo shar: Extracting \"'zip.h'\" \(8017 characters\)
sed "s/^X//" >'zip.h' <<'END_OF_FILE'
X/*
X
X Copyright (C) 1990,1991 Mark Adler, Richard B. Wales, and Jean-loup Gailly.
X Permission is granted to any individual or institution to use, copy, or
X redistribute this software so long as all of the original files are included
X unmodified, that it is not sold for profit, and that this copyright notice
X is retained.
X
X*/
X
X/*
X * zip.h by Mark Adler.
X */
X
X
X/* Set up portability */
X#include "tailor.h"
X
X/* Define malloc() and string functions */
X#ifdef MODERN
X# include <string.h>
X#else /* !MODERN */
X voidp *malloc();
X char *getenv();
X long atol();
X char *strcpy();
X char *strcat();
X char *strchr();
X char *strrchr();
X# ifndef ZMEM
X char *memset();
X char *memcpy();
X# endif /* !ZMEM */
X#endif /* ?MODERN */
X
X
X/* Define fseek() commands */
X#ifndef SEEK_SET
X# define SEEK_SET 0
X#endif /* !SEEK_SET */
X
X#ifndef SEEK_CUR
X# define SEEK_CUR 1
X#endif /* !SEEK_CUR */
X
X
X/* Forget FILENAME_MAX (incorrectly = 14 on some System V) */
X#ifdef MSDOS
X# define FNMAX 256
X#else /* !MSDOS */
X# define FNMAX 1024
X#endif /* ?MSDOS */
X
X
X/* Types centralized here for easy modification */
X#define local static /* More meaningful outside functions */
typedef unsigned char uch; /* unsigned 8-bit value */
typedef unsigned short ush; /* unsigned 16-bit value */
typedef unsigned long ulg; /* unsigned 32-bit value */
X
X
X/* Lengths of headers after signatures in bytes */
X#define LOCHEAD 26
X#define CENHEAD 42
X#define ENDHEAD 18
X
X
X/* Structures for in-memory file information */
struct zlist {
X /* See central header in zipfile.c for what vem..off are */
X ush vem, ver, flg, how;
X ulg tim, crc, siz, len;
X extent nam, ext, cext, com; /* offset of ext must be >= LOCHEAD */
X ush dsk, att, lflg; /* offset of lflg must be >= LOCHEAD */
X ulg atx, off;
X char *name; /* File name in zip file */
X char *extra; /* Extra field (set only if ext != 0) */
X char *cextra; /* Extra in central (set only if cext != 0) */
X char *comment; /* Comment (set only if com != 0) */
X char *zname; /* Name for new zip file header */
X int mark; /* Marker for files to operate on */
X int trash; /* Marker for files to delete */
X struct zlist far *nxt; /* Pointer to next header in list */
X};
struct flist {
X char *name; /* Pointer to zero-delimited name */
X char *zname; /* Name used for zip file headers */
X struct flist far * far *lst; /* Pointer to link pointing here */
X struct flist far *nxt; /* Link to next name */
X};
X
X
X/* Error return codes and PERR macro */
X#include "ziperr.h"
X
X
X/* Public globals */
extern char errbuf[]; /* Handy place to build error messages */
extern int recurse; /* Recurse into directories encountered */
extern int pathput; /* Store path with name */
X#define BEST -1 /* Use best method */
X#define STORE 0 /* Store method */
X#define SHRINK 1 /* Use shrink or store only */
X#define IMPLODE 6 /* Use implode or store only */
extern int method; /* Restriction on compression method */
extern int dosify; /* Make new entries look like MSDOS */
extern char *special; /* Don't compress special suffixes */
extern int verbose; /* Report oddities in zip file structure */
extern int level; /* Compression level */
X#ifdef VMS
X extern int vmsver; /* Append VMS version number to file names */
X#endif /* VMS */
extern int linkput; /* Store symbolic links as such */
extern int noisy; /* False for quiet operation */
extern char *key; /* Scramble password or NULL */
extern char *tempath; /* Path for temporary files */
extern char *zipfile; /* New or existing zip archive (zip file) */
extern ulg zipbeg; /* Starting offset of zip structures */
extern ulg cenbeg; /* Starting offset of central directory */
extern struct zlist far *zfiles;/* Pointer to list of files in zip file */
extern extent zcount; /* Number of files in zip file */
extern extent zcomlen; /* Length of zip file comment */
extern char *zcomment; /* Zip file comment (not zero-terminated) */
extern struct zlist far **zsort;/* List of files sorted by name */
extern struct flist far *found; /* List of names found */
extern struct flist far * far *fnxt; /* Where to put next in found list */
extern extent fcount; /* Count of names in found list */
extern int shract; /* Shrink active */
extern int impact; /* Implosion active */
X
X
X/* Diagnostic function */
X#ifdef DEBUG
X# define diag(where) fprintf(stderr, "zip diagnostic: %s\n", where)
X#else /* !DEBUG */
X# define diag(where)
X#endif /* ?DEBUG */
X
X
X/* Public function prototypes */
X
X /* in zip.c, zipcloak.c, or zipsplit.c */
void warn OF((char *, char *));
X
X /* in zipup.c */
int zipcopy OF((struct zlist far *, FILE *, FILE *));
X#ifndef UTIL
X int percent OF((ulg, ulg));
X int zipup OF((struct zlist far *, FILE *));
X#endif /* !UTIL */
X
X /* in zipfile.c */
X#ifndef UTIL
X struct zlist far *zsearch OF((char *));
X int trash OF((void));
X#endif /* !UTIL */
char *ziptyp OF((char *));
int readzipfile OF((void));
int putlocal OF((struct zlist far *, FILE *));
int putcentral OF((struct zlist far *, FILE *));
int putend OF((int, ulg, ulg, extent, char *, FILE *));
X
X /* in fileio.c */
X#ifndef UTIL
X# ifdef MSDOS
X int wild OF((char *));
X# endif /* MSDOS */
X char *getnam OF((char *));
X struct flist far *fexpel OF((struct flist far *));
X char *in2ex OF((char *));
X int exclude OF((void));
X int procname OF((char *));
X void stamp OF((char *, ulg));
X ulg dostime OF((int, int, int, int, int, int));
X ulg filetime OF((char *, ulg *, long *));
X int issymlnk OF((ulg a));
X# ifdef S_IFLNK
X# define rdsymlnk(p,b,n) readlink(p,b,n)
X extern int readlink OF((char *, char *, int));
X# else /* !S_IFLNK */
X# define rdsymlnk(p,b,n) (0)
X# endif /* !S_IFLNK */
X int deletedir OF((char *));
X#endif /* !UTIL */
int destroy OF((char *));
int replace OF((char *, char *));
int getfileattr OF((char *));
int setfileattr OF((char *, int));
char *tempname OF((int));
int fcopy OF((FILE *, FILE *, ulg));
X#ifndef EXPORT
X# ifndef MSVMS
X void echoff OF((int));
X void echon OF((void));
X# endif /* !MSVMS */
X char *getp OF((char *, char *, int));
X#endif /* !EXPORT */
X#ifdef ZMEM
X char *memset OF((char *, int, unsigned int));
X char *memcpy OF((char *, char *, unsigned int));
X int memcmp OF((char *, char *, unsigned int));
X#endif /* ZMEM */
X
X /* in crypt.c */
X#ifdef EXPORT
X# define zfwrite fwrite
X#else /* !EXPORT */
X void crypthead OF((char *, ulg, FILE *));
X# ifdef UTIL
X int zipcloak OF ((struct zlist far *, FILE *, FILE *, char *));
X int zipbare OF ((struct zlist far *, FILE *, FILE *, char *));
X# else /* !UTIL */
X int zfwrite OF((voidp *, extent, extent, FILE *));
X int zfputc OF((int, FILE *));
X# endif /* ?UTIL */
X#endif /* ?EXPORT */
X
X /* in util.c */
char *isshexp OF((char *));
int shmatch OF((char *, char *));
X#ifdef MSDOS
X int dosmatch OF((char *, char *));
X#endif /* MSDOS */
voidp far **search OF((voidp *, voidp far **, extent,
X int (*)(voidp *, voidp far *)));
ulg crc32 OF((ulg, int));
ulg updcrc OF((char *, extent));
X
X /* in shrink.c */
X#ifndef UTIL
X int shr_setup OF((void));
X int shr_p1 OF((uch *, extent));
X int shr_size OF((ulg *));
X int shr_p2 OF((FILE *));
X int shr_clear OF((void));
X
X /* in implode.c */
X# ifndef NOIMPLODE
X int imp_setup OF((long, int));
X int imp_p1 OF((char *, int));
X int imp_size OF((ulg *, uch *));
X int imp_p2 OF((FILE *));
X int imp_clear OF((void));
X# endif /* !NOIMPLODE */
X#endif /* !UTIL */
X
X
X/* end of zip.h */
END_OF_FILE
if test 8017 -ne `wc -c <'zip.h'`; then
echo shar: \"'zip.h'\" unpacked with wrong size!
fi
# end of 'zip.h'
fi
if test -f 'zipnote.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'zipnote.c'\"
else
echo shar: Extracting \"'zipnote.c'\" \(9810 characters\)
sed "s/^X//" >'zipnote.c' <<'END_OF_FILE'
X/*
X
X Copyright (C) 1990,1991 Mark Adler, Richard B. Wales, and Jean-loup Gailly.
X Permission is granted to any individual or institution to use, copy, or
X redistribute this software so long as all of the original files are included
X unmodified, that it is not sold for profit, and that this copyright notice
X is retained.
X
X*/
X
X/*
X * zipnote.c by Mark Adler.
X */
X
X#define UTIL
X#include "revision.h"
X#include "zip.h"
X#include <signal.h>
X
X
X/* Character to mark zip entry names in the comment file */
X#define MARK '@'
X
X/* Temporary zip file name and file pointer */
local char *tempzip;
local FILE *tempzf;
X
X
X/* Local functions */
X#ifdef PROTO
X local void err(int, char *);
X local void handler(int);
X local void license(void);
X local void help(void);
X local void putclean(char *);
X local int catalloc(char * far *, char *);
X void main(int, char **);
X#endif /* PROTO */
X
X
X
local void err(c, h)
int c; /* error code from the ZE_ class */
char *h; /* message about how it happened */
X/* Issue a message for the error, clean up files and memory, and exit. */
X{
X if (PERR(c))
X perror("zipnote error");
X fprintf(stderr, "zipnote error: %s (%s)\n", errors[c-1], h);
X if (tempzf != NULL)
X fclose(tempzf);
X if (tempzip != NULL)
X {
X destroy(tempzip);
X free((voidp *)tempzip);
X }
X if (zipfile != NULL)
X free((voidp *)zipfile);
X#ifdef VMS
X exit(0);
X#else /* !VMS */
X exit(c);
X#endif /* ?VMS */
X}
X
X
local void handler(s)
int s; /* signal number (ignored) */
X/* Upon getting a user interrupt, abort cleanly using err(). */
X{
X#ifndef MSDOS
X putc('\n', stderr);
X#endif /* !MSDOS */
X err(ZE_ABORT, "aborting");
X s++; /* keep some compilers happy */
X}
X
X
void warn(a, b)
char *a, *b; /* message strings juxtaposed in output */
X/* Print a warning message to stderr and return. */
X{
X fprintf(stderr, "zipnote warning: %s%s\n", a, b);
X}
X
X
local void license()
X/* Print license information to stdout. */
X{
X extent i; /* counter for copyright array */
X
X for (i = 0; i < sizeof(copyright)/sizeof(char *); i++)
X puts(copyright[i]);
X for (i = 0; i < sizeof(disclaimer)/sizeof(char *); i++)
X puts(disclaimer[i]);
X}
X
X
local void help()
X/* Print help (along with license info) to stdout. */
X{
X extent i; /* counter for help array */
X
X /* help array */
X static char *text[] = {
X"",
X"ZipNote %d.%d (%s)",
X"Usage: zipnote [-w] [-b path] zipfile",
X" the default action is to write the comments in zipfile to stdout",
X" -w write the zipfile comments from stdin",
X" -b use \"path\" for the temporary zip file",
X" -h show this help -l show software license",
X"",
X"Example:",
X#ifdef VMS
X" define/user sys$output foo.tmp",
X" zipnote foo.zip",
X" edit foo.tmp",
X" ... then you edit the comments, save, and exit ...",
X" define/user sys$input foo.tmp",
X" zipnote -w foo.zip"
X#else /* !VMS */
X" zipnote foo.zip > foo.tmp",
X" ed foo.tmp",
X" ... then you edit the comments, save, and exit ...",
X" zipnote -w foo.zip < foo.tmp"
X#endif /* ?VMS */
X };
X
X for (i = 0; i < sizeof(copyright)/sizeof(char *); i++)
X puts(copyright[i]);
X for (i = 0; i < sizeof(text)/sizeof(char *); i++)
X {
X printf(text[i], REVISION / 10, REVISION % 10, REVDATE);
X putchar('\n');
X }
X}
X
X
local void putclean(s)
char *s; /* string to write to stdout */
X/* Write the string s to stdout, filtering out control characters that are
X not tab or newline (mainly to remove carriage returns), and prefix MARK's
X and backslashes with a backslash. Also, terminate with a newline if
X needed. */
X{
X int c; /* next character in string */
X int e; /* last character written */
X
X e = '\n'; /* if empty, write nothing */
X while ((c = *s++) != 0)
X {
X if (c == MARK || c == '\\')
X putchar('\\');
X if (c >= ' ' || c == '\t' || c == '\n')
X putchar(e = c);
X }
X if (e != '\n')
X putchar('\n');
X}
X
X
local int catalloc(a, s)
char * far *a; /* pointer to a pointer to a malloc'ed string */
char *s; /* string to concatenate on a */
X/* Concatentate the string s to the malloc'ed string pointed to by a.
X Preprocess s by removing backslash escape characters. */
X{
X char *p; /* temporary pointer */
X char *q; /* temporary pointer */
X
X for (p = q = s; *q; *p++ = *q++)
X if (*q == '\\' && *(q+1))
X q++;
X *p = 0;
X if ((p = malloc(strlen(*a) + strlen(s) + 3)) == NULL)
X return ZE_MEM;
X strcat(strcat(strcpy(p, *a), **a ? "\r\n" : ""), s);
X free((voidp *)*a);
X *a = p;
X return ZE_OK;
X}
X
X
void main(argc, argv)
int argc; /* number of tokens in command line */
char **argv; /* command line tokens */
X/* Write the comments in the zipfile to stdout, or read them from stdin. */
X{
X char a[FNMAX+1]; /* input line buffer */
X ulg c; /* start of central directory */
X int k; /* next argument type */
X char *q; /* steps through option arguments */
X int r; /* arg counter, temporary variable */
X ulg s; /* length of central directory */
X int t; /* attributes of zip file */
X int w; /* true if updating zip file from stdin */
X FILE *x, *y; /* input and output zip files */
X struct zlist far *z; /* steps through zfiles linked list */
X
X
X /* If no args, show help */
X if (argc == 1)
X {
X help();
X exit(0);
X }
X
X /* Go through args */
X zipfile = tempzip = NULL;
X tempzf = NULL;
X signal(SIGINT, handler);
X signal(SIGTERM, handler);
X k = w = 0;
X for (r = 1; r < argc; r++)
X if (*argv[r] == '-')
X if (argv[r][1])
X for (q = argv[r]+1; *q; q++)
X switch(*q)
X {
X case 'b': /* Specify path for temporary file */
X if (k)
X err(ZE_PARMS, "use -b before zip file name");
X else
X k = 1; /* Next non-option is path */
X break;
X case 'h': /* Show help */
X help(); exit(0);
X case 'l': /* Show copyright and disclaimer */
X license(); exit(0);
X case 'w':
X w = 1; break;
X default:
X err(ZE_PARMS, "unknown option");
X }
X else
X err(ZE_PARMS, "zip file cannot be stdin");
X else
X if (k == 0)
X if (zipfile == NULL)
X {
X if ((zipfile = ziptyp(argv[r])) == NULL)
X err(ZE_MEM, "was processing arguments");
X }
X else
X err(ZE_PARMS, "can only specify one zip file");
X else
X {
X tempath = argv[r];
X k = 0;
X }
X if (zipfile == NULL)
X err(ZE_PARMS, "need to specify zip file");
X
X /* Read zip file */
X if ((r = readzipfile()) != ZE_OK)
X err(r, zipfile);
X if (zfiles == NULL)
X err(ZE_NAME, zipfile);
X
X /* Put comments to stdout, if not -u */
X if (!w)
X {
X for (z = zfiles; z != NULL; z = z->nxt)
X {
X printf("%c %s\n", MARK, z->zname);
X if (z->com)
X putclean(z->comment);
X putchar(MARK); putchar('\n');
X }
X putchar(MARK); putchar('\n');
X if (zcomlen)
X putclean(zcomment);
X exit(ZE_OK);
X }
X
X /* If updating comments, make sure zip file is writeable */
X if ((x = fopen(zipfile, "a")) == NULL)
X err(ZE_CREAT, zipfile);
X fclose(x);
X t = getfileattr(zipfile);
X
X /* Process stdin, replacing comments */
X for (z = zfiles; z != NULL; z = z->nxt)
X {
X if (gets(a) == NULL || a[0] != MARK || a[1] != ' ' ||
X strcmp(a + 2, z->zname))
X err(ZE_NOTE, "missing entry name");
X if (z->com)
X free((voidp *)z->comment);
X z->comment = malloc(1); *(z->comment) = 0;
X while (gets(a) != NULL && *a != MARK)
X if ((r = catalloc(&(z->comment), a)) != ZE_OK)
X err(r, "was building new comments");
X if (a[1])
X err(ZE_NOTE, "missing comment end line");
X z->com = strlen(z->comment);
X }
X if (gets(a) == NULL || a[0] != MARK || a[1])
X err(ZE_NOTE, "missing zip file comment marker line");
X zcomment = malloc(1); *zcomment = 0;
X while (gets(a) != NULL)
X if ((r = catalloc(&zcomment, a)) != ZE_OK)
X err(r, "was building new comments");
X zcomlen = strlen(zcomment);
X
X /* Open output zip file for writing */
X if ((tempzf = y = fopen(tempzip = tempname('Z'), FOPW)) == NULL)
X err(ZE_TEMP, tempzip);
X
X /* Open input zip file again, copy preamble if any */
X if ((x = fopen(zipfile, FOPR)) == NULL)
X err(ZE_NAME, zipfile);
X if (zipbeg && (r = fcopy(x, y, zipbeg)) != ZE_OK)
X err(r, r == ZE_TEMP ? tempzip : zipfile);
X
X /* Go through local entries, copying them over as is */
X for (z = zfiles; z != NULL; z = z->nxt)
X if ((r = zipcopy(z, x, y)) != ZE_OK)
X err(r, "was copying an entry");
X fclose(x);
X
X /* Write central directory and end of central directory with new comments */
X if ((c = ftell(y)) == -1L) /* get start of central */
X err(ZE_TEMP, tempzip);
X for (z = zfiles; z != NULL; z = z->nxt)
X if ((r = putcentral(z, y)) != ZE_OK)
X err(r, tempzip);
X if ((s = ftell(y)) == -1L) /* get end of central */
X err(ZE_TEMP, tempzip);
X s -= c; /* compute length of central */
X if ((r = putend((int)zcount, s, c, zcomlen, zcomment, y)) != ZE_OK)
X err(r, tempzip);
X tempzf = NULL;
X if (fclose(y))
X err(ZE_TEMP, tempzip);
X if ((r = replace(zipfile, tempzip)) != ZE_OK)
X {
X warn("new zip file left as: ", tempzip);
X free((voidp *)tempzip);
X tempzip = NULL;
X err(r, "was replacing the original zip file");
X }
X free((voidp *)tempzip);
X tempzip = NULL;
X setfileattr(zipfile, t);
X free((voidp *)zipfile);
X zipfile = NULL;
X
X /* Done! */
X exit(ZE_OK);
X}
END_OF_FILE
if test 9810 -ne `wc -c <'zipnote.c'`; then
echo shar: \"'zipnote.c'\" unpacked with wrong size!
fi
# end of 'zipnote.c'
fi
if test -f 'zipup.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'zipup.c'\"
else
echo shar: Extracting \"'zipup.c'\" \(10409 characters\)
sed "s/^X//" >'zipup.c' <<'END_OF_FILE'
X/*
X
X Copyright (C) 1990,1991 Mark Adler, Richard B. Wales, and Jean-loup Gailly.
X Permission is granted to any individual or institution to use, copy, or
X redistribute this software so long as all of the original files are included
X unmodified, that it is not sold for profit, and that this copyright notice
X is retained.
X
X*/
X
X/*
X * zipup.c by Mark Adler.
X */
X
X#define NOCPYRT /* this is not a main module */
X#include "zip.h"
X#include "revision.h"
X
X/* Use the raw functions for MSDOS and Unix to save on buffer space.
X They're not used for VMS since it doesn't work (raw is weird on VMS).
X (This sort of stuff belongs in fileio.c, but oh well.) */
X#ifdef VMS
X typedef FILE *ftype;
X# define fhow FOPR
X# define fbad NULL
X# define zopen(n,p) fopen(n,p)
X# define zread(f,b,n) fread(b,1,n,f)
X# define zclose(f) fclose(f)
X# define zerr(f) ferror(f)
X# define zrew(f) rewind(f)
X#else /* !VMS */
X# ifdef MSDOS
X# include <io.h>
X# include <fcntl.h>
X# define fhow (O_RDONLY|O_BINARY)
X# else /* !MSDOS */
X int open OF((char *, int));
X int read OF((int, char *, int));
X int close OF((int));
X int lseek OF((int,long,int));
X# define fhow 0
X# endif /* ?MSDOS */
X typedef int ftype;
X# define fbad (-1)
X# define zopen(n,p) open(n,p)
X# define zread(f,b,n) read(f,b,n)
X# define zclose(f) close(f)
X# define zerr(f) (k<0)
X# define zrew(f) lseek(f,0L,0)
X#endif /* ?VMS */
X
X
X/* Local functions */
X#ifdef PROTO
X# ifndef UTIL
X local int suffixes(char *, char *);
X# endif /* !UTIL */
X#endif /* PROTO */
X
X
X/* Note: a zip "entry" includes a local header (which includes the file
X name), an encryption header if encrypting, and the compressed data. */
X
X
int zipcopy(z, x, y)
struct zlist far *z; /* zip entry to copy */
XFILE *x, *y; /* source and destination files */
X/* Copy the zip entry described by *z from file *x to file *y. Return an
X error code in the ZE_ class. */
X{
X ulg n; /* holds local header offset */
X
X if (fseek(x, z->off, SEEK_SET))
X return ferror(x) ? ZE_READ : ZE_EOF;
X if ((n = ftell(y)) == -1L)
X return ZE_TEMP;
X z->off = n;
X n = 4 + LOCHEAD + (long)z->nam + (long)z->ext + z->siz;
X return fcopy(x, y, n);
X}
X
X
X#ifndef UTIL
X
int percent(n, m)
ulg n, m; /* n is the original size, m is the new size */
X/* Return the percentage compression from n to m using only integer
X operations */
X{
X if (n > 0xffffffL) /* If n >= 16M */
X { /* then divide n and m by 256 */
X n += 0x80; n >>= 8;
X m += 0x80; m >>= 8;
X }
X return n ? (int)(1 + (200 * (n - m))/n) >> 1 : 0;
X}
X
X
local int suffixes(a, s)
char *a; /* name to check suffix of */
char *s; /* list of suffixes separated by : or ; */
X/* Return true if a ends in any of the suffixes in the list s. */
X{
X int m; /* true if suffix matches so far */
X char *p; /* pointer into special */
X char *q; /* pointer into name a */
X
X m = 1;
X q = a + strlen(a) - 1;
X for (p = s + strlen(s) - 1; p >= s; p--)
X if (*p == ':' || *p == ';')
X if (m)
X return 1;
X else
X {
X m = 1;
X q = a + strlen(a) - 1;
X }
X else
X#ifdef OS2
X {
X m = m && q >= a && tolower(*p) == tolower(*q);
X q--;
X }
X#else /* !OS2 */
X m = m && q >= a && *p == *q--;
X#endif /* ?OS2 */
X return m;
X}
X
X
int zipup(z, y)
struct zlist far *z; /* zip entry to compress */
XFILE *y; /* output file */
X/* Compress the file z->name into the zip entry described by *z and write
X it to the file *y. Determine the best method (store, shrink, or implode)
X and use it. Encrypt if requested. Return an error code in the
X ZE_ class. */
X{
X ulg a; /* attributes returned by filetime() */
X char *b; /* malloc'ed file buffer */
X ulg c; /* crc on uncompressed file data */
X ftype f; /* file to compress */
X uch g; /* flags returned by implode */
X int h; /* compression method chosen (how) */
X#ifndef NOIMPLODE
X ulg i; /* size of imploded data */
X#endif /* !NOIMPLODE */
X extent k; /* result of zread */
X int l; /* true if this file is a symbolic link */
X int m; /* method for this entry */
X ulg n; /* size of uncompressed file */
X long q; /* size returned by filetime */
X int r; /* temporary variable */
X ulg s; /* size of shrunk or compressed data */
X
X /* Open file to zip up */
X if ((z->tim = filetime(z->name, &a, &q)) == 0 || q < 0)
X return ZE_OPEN;
X l = issymlnk(a);
X if (l)
X f = fbad;
X else if ((f = zopen(z->name, fhow)) == fbad)
X return ZE_OPEN;
X
X /* Select method based on the suffix and the global method */
X m = special != NULL && suffixes(z->name, special) ? STORE : method;
X
X /* Don't bother with shrink for "large" files (320 is what PKZIP uses--the
X number used here must be <= BSZ) */
X if (m == BEST && q > 512)
X m = IMPLODE;
X if (q == 0)
X m = STORE;
X
X /* Make first pass on the file, computing the crc and length, and running
X shrink and implode on it. */
X n = 0;
X c = updcrc((char *)NULL, 0);
X if ((b = malloc(BSZ)) == NULL)
X return ZE_MEM;
X if (m == BEST || m == SHRINK)
X if ((r = shr_setup()) != ZE_OK)
X return r;
X else
X shract = 1;
X while ((k = l ? rdsymlnk(z->name, b, BSZ) : zread(f, b, BSZ)) > 0)
X {
X n += k;
X c = updcrc(b, k);
X#ifdef MINIX
X if (l)
X q = k;
X#endif /* MINIX */
X if ((m == BEST || m == SHRINK) && (r = shr_p1((uch *)b, k)) != ZE_OK)
X {
X free((voidp *)b);
X shr_clear();
X shract = 0;
X return r;
X }
X if (m == BEST) /* free up shrink data structures */
X {
X if ((!l && zread(f, b, BSZ) != 0)
X#ifndef VMS
X || n != (ulg)q
X#endif /* !VMS */
X )
X return ZE_READ;
X if ((r = shr_size(&s)) != ZE_OK)
X {
X shr_clear();
X shract = 0;
X return r;
X }
X }
X#ifndef NOIMPLODE
X if (m == BEST || m == IMPLODE)
X {
X if (!impact)
X if ((r = imp_setup(q, level)) != ZE_OK)
X return r;
X else
X impact = 1;
X if ((r = imp_p1(b, k)) != ZE_OK)
X {
X free((voidp *)b);
X imp_clear();
X impact = 0;
X return r;
X }
X }
X#endif /* !NOIMPLODE */
X if (m == BEST || l)
X break;
X }
X free((voidp *)b);
X if (!l && zerr(f))
X return ZE_READ;
X
X /* Determine the best method to use */
X g = 0;
X if (noisy && verbose)
X printf(" (n=%lu)", n);
X if (m == SHRINK && (r = shr_size(&s)) != ZE_OK)
X {
X shr_clear();
X shract = 0;
X return r;
X }
X if (noisy && verbose && (m == BEST || m == SHRINK))
X printf(" (s=%lu)", s);
X#ifndef NOIMPLODE
X if ((m == BEST || m == IMPLODE) && (r = imp_size(&i, &g)) != ZE_OK)
X {
X imp_clear();
X impact = 0;
X return r;
X }
X if (noisy && verbose && (m == BEST || m == IMPLODE))
X printf(" (i=%lu)", i);
X if ((m == BEST || m == IMPLODE) && i < n && (m == IMPLODE || i < s))
X {
X if (noisy)
X {
X printf(" (imploded %d%%)", percent(n, i));
X fflush(stdout);
X }
X h = IMPLODE;
X s = i;
X if (m == BEST)
X {
X shr_clear();
X shract = 0;
X }
X if (!l)
X zclose(f);
X }
X else
X#endif /* !NOIMPLODE */
X if ((m == BEST || m == SHRINK) && s < n)
X {
X if (noisy)
X {
X printf(" (shrunk %d%%)", percent(n, s));
X fflush(stdout);
X }
X h = SHRINK;
X#ifndef NOIMPLODE
X if (m == BEST)
X {
X imp_clear();
X impact = 0;
X }
X#endif /* !NOIMPLODE */
X if (!l)
X zclose(f);
X }
X else
X {
X if (noisy)
X {
X printf(" (stored 0%%)");
X fflush(stdout);
X }
X h = STORE;
X s = n;
X#ifndef NOIMPLODE
X if (m == BEST || m == IMPLODE)
X {
X imp_clear();
X impact = 0;
X }
X#endif /* !NOIMPLODE */
X if (m == BEST || m == SHRINK)
X {
X shr_clear();
X shract = 0;
X }
X }
X
X#ifndef VMS
X /* Check size (but not in VMS--variable record lengths mess it up) */
X if (n != (ulg)q)
X return ZE_READ;
X#endif /* !VMS */
X
X /* Fill in header information and write local header to zip file */
X#ifdef OS2
X if ( dosify < 2 )
X dosify = IsFileSystemFAT(z->name);
X#endif /* OS2 */
X
X /* (Assume ext, cext, com, and zname already filled in.) */
X z->vem = dosify ? 11 : /* Made under MSDOS by PKZIP 1.1 */
X#ifdef VMS
X 0x200 + REVISION; /* Made under VMS by this Zip */
X#else /* !VMS */
X#ifdef OS2
X 0x600 + REVISION; /* Made under OS/2 by this Zip */
X#else /* !OS2 */
X 0x300 + REVISION; /* Made under Unix by this Zip */
X#endif /* ?OS2 */
X#endif /* ?VMS */
X z->ver = 10; /* Need PKUNZIP 1.0 */
X z->flg = (ush)g;
X if (key != NULL)
X z->flg |= 1;
X z->lflg = z->flg;
X z->how = h;
X z->crc = c;
X z->siz = s;
X if (key != NULL)
X z->siz += 12;
X z->len = n;
X z->nam = strlen(z->zname);
X z->dsk = 0;
X z->att = 0; /* Assume they're all binary */
X z->atx = dosify ? a & 0xff : a; /* Attributes from filetime() */
X if ((z->off = ftell(y)) == -1L)
X return ZE_WRITE;
X if ((r = putlocal(z, y)) != ZE_OK)
X return r;
X
X /* Write stored, shrunk, or imploded file to zip file */
X#ifndef EXPORT
X if (key != NULL)
X crypthead(key, z->crc, y);
X#endif /* !EXPORT */
X n = ftell(y); /* Save offset for logic check */
X#ifndef NOIMPLODE
X if (h == IMPLODE)
X {
X if ((r = imp_p2(y)) != ZE_OK)
X return r;
X imp_clear();
X impact = 0;
X }
X else
X#endif /* !NOIMPLODE */
X if (h == SHRINK)
X {
X if ((r = shr_p2(y)) != ZE_OK)
X return r;
X shr_clear();
X shract = 0;
X }
X else
X {
X if (!l)
X zrew(f);
X if ((b = malloc(BSZ)) == NULL)
X return ZE_MEM;
X while ((k = l ? rdsymlnk(z->name, b, BSZ) : zread(f, b, BSZ)) > 0)
X {
X if (zfwrite(b, 1, k, y) != k)
X {
X free((voidp *)b);
X return ZE_TEMP;
X }
X if (l)
X break;
X }
X free((voidp *)b);
X if (!l && zerr(f))
X return ZE_READ;
X if (!l)
X zclose(f);
X }
X
X /* Check length of compressed data */
X if (ftell(y) != n + s)
X return ZE_LOGIC;
X
X /* Done--clean up and leave */
X if (noisy)
X {
X putchar('\n');
X fflush(stdout);
X }
X return ZE_OK;
X}
X
X#endif /* !UTIL */
END_OF_FILE
if test 10409 -ne `wc -c <'zipup.c'`; then
echo shar: \"'zipup.c'\" unpacked with wrong size!
fi
# end of 'zipup.c'
fi
echo shar: End of archive 2 \(of 7\).
cp /dev/null ark2isdone
MISSING=""
for I in 1 2 3 4 5 6 7 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 7 archives.
rm -f ark[1-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0

0 new messages