2 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
6 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
7 /* All Rights Reserved */
11 * Copyright (c) 1986 Regents of the University of California.
12 * All rights reserved. The Berkeley software License Agreement
13 * specifies the terms and conditions for redistribution.
16 #pragma ident "%Z%%M% %I% %E% SMI"
19 * Compress - data compression program
21 #define min(a, b) ((a > b) ? b : a)
24 * machine variants which require cc -Dmachine: pdp11, z8000, pcxt
28 * Set USERMEM to the maximum amount of physical user memory available
29 * in bytes. USERMEM is used to determine the maximum BITS that can be used
32 * SACREDMEM is the amount of physical memory saved for others; compress
40 #define USERMEM 450000 /* default user memory */
44 #if USERMEM >= (433484+SACREDMEM)
47 #if USERMEM >= (229600+SACREDMEM)
50 #if USERMEM >= (127536+SACREDMEM)
53 #if USERMEM >= (73464+SACREDMEM)
64 #ifdef PBITS /* Preferred BITS for this memory size */
71 #define HSIZE 69001 /* 95% occupancy */
74 #define HSIZE 35023 /* 94% occupancy */
77 #define HSIZE 18013 /* 91% occupancy */
80 #define HSIZE 9001 /* 91% occupancy */
83 #define HSIZE 5003 /* 80% occupancy */
86 #define OUTSTACKSIZE (2<<BITS)
89 * a code_int must be able to hold 2**BITS values of type int, and also -1
92 typedef long int code_int
;
97 typedef long int count_int
;
98 typedef long long count_long
;
100 typedef unsigned char char_type
;
102 static char_type magic_header
[] = { "\037\235" }; /* 1F 9D */
104 /* Defines for third byte of header */
105 #define BIT_MASK 0x1f
106 #define BLOCK_MASK 0x80
108 * Masks 0x40 and 0x20 are free. I think 0x20 should mean that there is
109 * a fourth header byte(for expansion).
111 #define INIT_BITS 9 /* initial number of bits/code */
114 * compress.c - File compression ala IEEE Computer, June 1984.
116 static char rcs_ident
[] =
117 "$Header: compress.c,v 4.0 85/07/30 12:50:00 joe Release $";
121 #include <sys/param.h>
123 #include <langinfo.h>
128 #include <aclutils.h>
129 #include <libcmdutils.h>
130 #include "getresponse.h"
133 static int n_bits
; /* number of bits/code */
134 static int maxbits
= BITS
; /* user settable max # bits/code */
135 static code_int maxcode
; /* maximum code, given n_bits */
136 /* should NEVER generate this code */
137 static code_int maxmaxcode
= 1 << BITS
;
138 #define MAXCODE(n_bits) ((1 << (n_bits)) - 1)
140 static count_int htab
[OUTSTACKSIZE
];
141 static unsigned short codetab
[OUTSTACKSIZE
];
143 #define htabof(i) htab[i]
144 #define codetabof(i) codetab[i]
145 static code_int hsize
= HSIZE
; /* for dynamic table sizing */
146 static off_t fsize
; /* file size of input file */
149 * To save much memory, we overlay the table used by compress() with those
150 * used by decompress(). The tab_prefix table is the same size and type
151 * as the codetab. The tab_suffix table needs 2**BITS characters. We
152 * get this from the beginning of htab. The output stack uses the rest
153 * of htab, and contains characters. There is plenty of room for any
154 * possible stack (stack used to be 8000 characters).
157 #define tab_prefixof(i) codetabof(i)
158 #define tab_suffixof(i) ((char_type *)(htab))[i]
159 #define de_stack ((char_type *)&tab_suffixof(1<<BITS))
160 #define stack_max ((char_type *)&tab_suffixof(OUTSTACKSIZE))
162 static code_int free_ent
= 0; /* first unused entry */
163 static int newline_needed
= 0;
164 static int didnt_shrink
= 0;
165 static int perm_stat
= 0; /* permanent status */
167 static code_int
getcode();
169 /* Use a 3-byte magic number header, unless old file */
170 static int nomagic
= 0;
171 /* Write output on stdout, suppress messages */
172 static int zcat_flg
= 0; /* use stdout on all files */
173 static int zcat_cmd
= 0; /* zcat cmd */
174 static int use_stdout
= 0; /* set for each file processed */
175 /* Don't unlink output file on interrupt */
176 static int precious
= 1;
177 static int quiet
= 1; /* don't tell me about compression */
180 * block compression parameters -- after all codes are used up,
181 * and compression rate changes, start over.
183 static int block_compress
= BLOCK_MASK
;
184 static int clear_flg
= 0;
185 static long int ratio
= 0;
186 #define CHECK_GAP 10000 /* ratio check interval */
187 static count_long checkpoint
= CHECK_GAP
;
189 * the next two codes should not be changed lightly, as they must not
190 * lie within the contiguous general code space.
192 #define FIRST 257 /* first free entry */
193 #define CLEAR 256 /* table clear output code */
195 static int force
= 0;
196 static char ofname
[MAXPATHLEN
];
212 static void (*oldint
)();
213 static int bgnd_flag
;
215 static int do_decomp
= 0;
217 static char *progname
;
223 static char *local_basename(char *);
225 static int addDotZ(char *, size_t);
227 static void Usage(void);
228 static void cl_block(count_long
);
229 static void cl_hash(count_int
);
230 static void compress(void);
231 static void copystat(char *, struct stat
*, char *);
232 static void decompress(void);
233 static void ioerror(void);
234 static void onintr();
236 static void output(code_int
);
237 static void prratio(FILE *, count_long
, count_long
);
238 static void version(void);
241 static int in_stack(int, int);
242 static void dump_tab(void);
243 static void printcodes(void);
246 /* For error-handling */
250 /* For input and ouput */
252 static FILE *inp
; /* the current input file */
253 static FILE *infile
; /* disk-based input stream */
254 static FILE *outp
; /* current output file */
255 static FILE *outfile
; /* disk-based output stream */
259 static char buf
[BITS
];
261 static char_type lmask
[9] =
262 {0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00};
263 static char_type rmask
[9] =
264 {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
266 /* For compress () */
269 static count_long bytes_out
; /* length of compressed output */
270 /* # of codes output (for debugging) */
274 #define STACK_SIZE 15000
276 code_int sorttab
[1<<BITS
]; /* sorted pointers into htab */
279 /* Extended system attribute support */
281 static int saflg
= 0;
284 * *************************************************************
287 * Algorithm from "A Technique for High Performance Data Compression",
288 * Terry A. Welch, IEEE Computer Vol 17, No 6 (June 1984), pp 8-19.
290 * Usage: compress [-dfvc/] [-b bits] [file ...]
292 * -d: If given, decompression is done instead.
294 * -c: Write output on stdout, don't remove original.
296 * -b: Parameter limits the max number of bits/code.
298 * -f: Forces output file to be generated, even if one already
299 * exists, and even if no space is saved by compressing.
300 * If -f is not used, the user will be prompted if stdin is
301 * a tty, otherwise, the output file will not be overwritten.
303 * -/ Copies extended attributes and extended system attributes.
305 * -v: Write compression statistics
307 * file ...: Files to be compressed. If none specified, stdin
310 * file.Z: Compressed form of file with same mode, owner, and utimes
311 * or stdout (if stdin used as input)
314 * When filenames are given, replaces with the compressed version
315 * (.Z suffix) only if the file decreases in size.
317 * Modified Lempel-Ziv method (LZW). Basically finds common
318 * substrings and replaces them with a variable size code. This is
319 * deterministic, and can be done on the fly. Thus, the decompression
320 * procedure needs no input table, but tracks the way the table was built.
324 main(int argc
, char *argv
[])
326 int overwrite
= 0; /* Do not overwrite unless given -f flag */
327 char tempname
[MAXPATHLEN
];
329 char **filelist
, **fileptr
;
332 struct stat ostatbuf
;
335 extern int optind
, optopt
;
337 int dash_count
= 0; /* times "-" is on cmdline */
340 (void) setlocale(LC_ALL
, "");
341 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
342 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */
344 (void) textdomain(TEXT_DOMAIN
);
346 if (init_yes() < 0) {
347 (void) fprintf(stderr
, gettext(ERR_MSG_INIT_YES
),
352 /* This bg check only works for sh. */
353 if ((oldint
= signal(SIGINT
, SIG_IGN
)) != SIG_IGN
) {
354 (void) signal(SIGINT
, onintr
);
355 (void) signal(SIGSEGV
, oops
);
357 bgnd_flag
= oldint
!= SIG_DFL
;
359 /* Allocate room for argv + "-" (if stdin needs to be added) */
361 filelist
= fileptr
= (char **)(malloc((argc
+ 1) * sizeof (*argv
)));
364 if ((cp
= rindex(argv
[0], '/')) != 0) {
370 if (strcmp(cp
, "uncompress") == 0) {
372 } else if (strcmp(cp
, "zcat") == 0) {
374 zcat_cmd
= zcat_flg
= 1;
377 progname
= local_basename(argv
[0]);
380 * Argument Processing
381 * All flags are optional.
383 * -V = > print Version; debug verbose
386 * -f = > force overwrite of output file
387 * -n = > no header: useful to uncompress old files
388 * -b maxbits => maxbits. If -b is specified,
389 * then maxbits MUST be given also.
390 * -c = > cat all output to stdout
391 * -C = > generate output compatible with compress 2.0.
392 * if a string is left, must be an input filename.
395 optstr
= "b:cCdDfFnqvV/";
397 optstr
= "b:cCdfFnqvV/";
400 while ((ch
= getopt(argc
, argv
, optstr
)) != EOF
) {
401 /* Process all flags in this arg */
442 (void) fprintf(stderr
, gettext(
443 "Missing maxbits\n"));
447 maxbits
= strtoul(optarg
, &p
, 10);
449 (void) fprintf(stderr
, gettext(
450 "Missing maxbits\n"));
468 (void) fprintf(stderr
, gettext(
469 "Unknown flag: '%c'\n"), optopt
);
476 * Validate zcat syntax
479 if (zcat_cmd
&& (Fflg
| Cflg
| cflg
|
480 bflg
| qflg
| dflg
| nomagic
)) {
481 (void) fprintf(stderr
, gettext(
482 "Invalid Option\n"));
488 * Process the file list
491 for (; optind
< argc
; optind
++) {
492 if (strcmp(argv
[optind
], "-") == 0) {
496 *fileptr
++ = argv
[optind
]; /* Build input file list */
500 if (dash_count
> 1) {
501 (void) fprintf(stderr
,
502 gettext("%s may only appear once in the file"
503 " list\n"), "\"-\"");
507 if (fileptr
- filelist
== 0) {
512 if (fileptr
- filelist
> 1 && cflg
&& !do_decomp
) {
513 (void) fprintf(stderr
,
514 gettext("compress: only one file may be compressed"
519 if (maxbits
< INIT_BITS
)
523 maxmaxcode
= 1 << maxbits
;
525 /* Need to open something to close with freopen later */
527 if ((infile
= fopen("/dev/null", "r")) == NULL
) {
528 (void) fprintf(stderr
, gettext("Error opening /dev/null for "
533 if ((outfile
= fopen("/dev/null", "w")) == NULL
) {
534 (void) fprintf(stderr
, gettext("Error opening /dev/null for "
539 for (fileptr
= filelist
; *fileptr
; fileptr
++) {
547 if (strcmp(*fileptr
, "-") == 0) {
552 *fileptr
= "stdin"; /* for error messages */
554 /* process the named file */
565 /* Check for .Z suffix */
567 if (strcmp(*fileptr
+
568 strlen(*fileptr
) - 2, ".Z") != 0) {
569 /* No .Z: tack one on */
571 if (strlcpy(tempname
, *fileptr
,
572 sizeof (tempname
)) >=
574 (void) fprintf(stderr
,
575 gettext("%s: filename "
582 if (addDotZ(tempname
,
583 sizeof (tempname
)) < 0) {
591 /* Open input file */
593 if (stat(*fileptr
, &statbuf
) < 0) {
599 if ((freopen(*fileptr
, "r", inp
)) == NULL
) {
606 /* Check the magic number */
610 (magic_header
[0] & 0xFF)) ||
612 (magic_header
[1] & 0xFF))) {
613 (void) fprintf(stderr
, gettext(
614 "%s: not in compressed "
621 /* set -b from file */
622 if ((maxbits
= getc(inp
)) == EOF
&&
629 block_compress
= maxbits
& BLOCK_MASK
;
631 maxmaxcode
= 1 << maxbits
;
633 if (maxbits
> BITS
) {
634 (void) fprintf(stderr
,
635 gettext("%s: compressed "
639 *fileptr
, maxbits
, BITS
);
646 /* Generate output filename */
648 if (strlcpy(ofname
, *fileptr
,
651 (void) fprintf(stderr
,
652 gettext("%s: filename "
661 ofname
[strlen(*fileptr
) - 2] = '\0';
666 if (strcmp(*fileptr
, "-") == 0) {
671 *fileptr
= "stdin"; /* for error messages */
673 /* Use the largest possible hash table */
676 /* process the named file */
687 if (strcmp(*fileptr
+
688 strlen(*fileptr
) - 2, ".Z") == 0) {
689 (void) fprintf(stderr
, gettext(
690 "%s: already has .Z "
691 "suffix -- no change\n"),
696 /* Open input file */
698 if (stat(*fileptr
, &statbuf
) < 0) {
704 if ((freopen(*fileptr
, "r", inp
)) == NULL
) {
710 fsize
= (off_t
)statbuf
.st_size
;
713 * tune hash table size for small
715 * but the sizes match earlier #defines, which
716 * serve as upper bounds on the number of
720 if (fsize
< (1 << 12))
721 hsize
= min(5003, HSIZE
);
722 else if (fsize
< (1 << 13))
723 hsize
= min(9001, HSIZE
);
724 else if (fsize
< (1 << 14))
725 hsize
= min(18013, HSIZE
);
726 else if (fsize
< (1 << 15))
727 hsize
= min(35023, HSIZE
);
728 else if (fsize
< 47000)
729 hsize
= min(50021, HSIZE
);
732 /* Generate output filename */
734 if (strlcpy(ofname
, *fileptr
,
737 (void) fprintf(stderr
,
738 gettext("%s: filename "
746 sizeof (ofname
)) < 0) {
752 } /* if (do_decomp) */
754 /* Check for overwrite of existing file */
756 if (!overwrite
&& !use_stdout
) {
757 if (stat(ofname
, &ostatbuf
) == 0) {
758 (void) fprintf(stderr
, gettext(
759 "%s already exists;"), ofname
);
760 if (bgnd_flag
== 0 && isatty(2)) {
763 (void) fprintf(stderr
, gettext(
764 " do you wish to overwr"
765 "ite %s (%s or %s)? "),
766 ofname
, yesstr
, nostr
);
767 (void) fflush(stderr
);
768 for (cin
= 0; cin
< LINE_MAX
; cin
++)
770 (void) read(2, line
, LINE_MAX
);
772 if (yes_check(line
) == 0) {
773 (void) fprintf(stderr
,
781 * XPG4: Assertion 1009
782 * Standard input is not
783 * terminal, and no '-f',
787 (void) fprintf(stderr
, gettext(
788 "%s: File exists, -f not"
790 "nning in the backgro"
791 "und.\n"), *fileptr
);
798 if ((pathconf(ofname
, _PC_XATTR_EXISTS
) == 1) ||
799 (saflg
&& sysattr_support(ofname
,
800 _PC_SATTR_EXISTS
) == 1)) {
801 (void) unlink(ofname
);
803 /* Open output file */
804 if (freopen(ofname
, "w", outp
) == NULL
) {
811 (void) fprintf(stderr
, "%s: ",
815 } else if (!quiet
&& !do_decomp
) {
816 (void) fprintf(stderr
, "%s: ",
821 /* Actually do the compression/decompression */
823 if ((jmpval
= setjmp(env
)) == 0) {
824 /* We'll see how things go */
826 if (do_decomp
== 0) {
832 if (do_decomp
== 0) {
834 } else if (debug
== 0) {
846 * Things went badly - clean up and go on.
847 * jmpval's values break down as follows:
848 * 1 == message determined by ferror() values.
849 * 2 == input problem message needed.
850 * 3 == output problem message needed.
853 if (ferror(inp
) || jmpval
== 2) {
855 (void) fprintf(stderr
, gettext(
856 "uncompress: %s: corrupt"
857 " input\n"), *fileptr
);
863 if (ferror(outp
) || jmpval
== 3) {
864 /* handle output errors */
873 if (ofname
[0] != '\0') {
874 if (unlink(ofname
) < 0) {
885 /* Things went well */
889 copystat(*fileptr
, &statbuf
, ofname
);
891 if (newline_needed
) {
892 (void) putc('\n', stderr
);
895 * Print the info. for unchanged file
900 if (!force
&& perm_stat
== 0) {
902 (void) fprintf(stderr
, gettext(
912 if (didnt_shrink
&& !force
&& perm_stat
== 0) {
916 if (newline_needed
) {
917 (void) fprintf(stderr
, "\n");
928 /* we have exceeded the hash table */
929 (void) fprintf(stderr
,
930 "internal error: hashtable exceeded - hsize = %ld\n", hsize
);
931 (void) fprintf(stderr
, "hshift = %d, %d\n", hshift
, (1 << hshift
) -1);
932 (void) fprintf(stderr
, "maxbits = %d\n", maxbits
);
933 (void) fprintf(stderr
, "n_bits = %d\n", n_bits
);
934 (void) fprintf(stderr
, "maxcode = %ld\n", maxcode
);
939 adjusti(code_int i
, code_int hsize_reg
)
945 while (i
>= hsize_reg
) {
952 * compress inp to outp
954 * Algorithm: use open addressing double hashing(no chaining) on the
955 * prefix code / next character combination. We do a variant of Knuth's
956 * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
957 * secondary probe. Here, the modular division first probe is gives way
958 * to a faster exclusive-or manipulation. Also do block compression with
959 * an adaptive reset, whereby the code table is cleared when the compression
960 * ratio decreases, but after the table fills. The variable-length output
961 * codes are re-sized at this point, and a special CLEAR code is generated
962 * for the decompressor. Late addition: construct the table according to
963 * file size for noticeable speed improvement on small files. Please direct
964 * questions about this implementation to ames!jaw.
979 uint32_t inchi
, inclo
;
983 count_long out_count
= 0;
987 if ((putc(magic_header
[0], outp
) == EOF
||
988 putc(magic_header
[1], outp
) == EOF
||
989 putc((char)(maxbits
| block_compress
),
997 bytes_out
= 3; /* includes 3-byte header mojo */
1003 checkpoint
= CHECK_GAP
;
1004 maxcode
= MAXCODE(n_bits
= INIT_BITS
);
1005 free_ent
= ((block_compress
) ? FIRST
: 256);
1007 if ((ent
= getc(fin
)) == EOF
&& ferror(fin
)) {
1013 for (fcode
= (long)hsize
; fcode
< 65536L; fcode
*= 2L)
1016 hshift
= 8 - hshift
; /* set hash code range bound */
1019 maxbits_reg
= maxbits
;
1021 cl_hash((count_int
) hsize_reg
); /* clear hash table */
1023 while ((c
= getc(fin
)) != EOF
) {
1026 fcode
= (long)(((long)c
<< maxbits_reg
) + ent
);
1027 i
= ((c
<< hshift
) ^ ent
); /* xor hashing */
1029 if ((unsigned int)i
>= hsize_reg
)
1030 i
= adjusti(i
, hsize_reg
);
1032 if (htabof(i
) == fcode
) {
1035 } else if ((long)htabof(i
) < 0) {
1040 /* secondary hash (after G. Knott) */
1041 disp
= hsize_reg
- i
;
1049 if (++probecnt
> hsize_reg
)
1052 if ((i
-= disp
) < 0) {
1057 if (htabof(i
) == fcode
) {
1062 if ((long)htabof(i
) > 0) {
1066 output((code_int
) ent
);
1071 if (free_ent
< maxmaxcode
) {
1072 codetabof(i
) = free_ent
++;
1073 /* code -> hashtable */
1076 in_count
= ((long long)inchi
<<32|inclo
);
1077 if ((count_long
)in_count
>=
1078 (count_long
)checkpoint
&& block_compress
) {
1084 in_count
= ((long long)inchi
<<32|inclo
);
1086 if (ferror(fin
) != 0) {
1091 * Put out the final code.
1093 output((code_int
)ent
);
1098 output((code_int
)-1);
1101 * Print out stats on stderr
1105 (void) fprintf(stderr
,
1106 "%lld chars in, %lld codes (%lld bytes) out, "
1107 "compression factor: ",
1108 (count_long
)in_count
, (count_long
)out_count
,
1109 (count_long
) bytes_out
);
1110 prratio(stderr
, (count_long
)in_count
,
1111 (count_long
)bytes_out
);
1112 (void) fprintf(stderr
, "\n");
1113 (void) fprintf(stderr
, "\tCompression as in compact: ");
1115 (count_long
)in_count
-(count_long
)bytes_out
,
1116 (count_long
)in_count
);
1117 (void) fprintf(stderr
, "\n");
1118 (void) fprintf(stderr
,
1119 "\tLargest code (of last block) was %d"
1121 free_ent
- 1, n_bits
);
1123 (void) fprintf(stderr
, gettext("Compression: "));
1125 (count_long
)in_count
-(count_long
)bytes_out
,
1126 (count_long
)in_count
);
1129 /* report if no savings */
1130 if ((count_long
)bytes_out
> (count_long
)in_count
) {
1136 * **************************************************************
1139 * Output the given code.
1141 * code: A n_bits-bit integer. If == -1, then EOF. This assumes
1142 * that n_bits = < (long)wordsize - 1.
1144 * Outputs code to the file.
1146 * Chars are 8 bits long.
1148 * Maintain a BITS character long buffer(so that 8 codes will
1149 * fit in it exactly). Use the VAX insv instruction to insert each
1150 * code in turn. When the buffer fills up empty it and start over.
1154 output(code_int code
)
1160 int r_off
= offset
, bits
= n_bits
;
1165 (void) fprintf(stderr
, "%5d%c", code
,
1166 (col
+= 6) >= 74 ? (col
= 0, '\n') : ' ');
1170 * byte/bit numbering on the VAX is simulated
1171 * by the following code
1174 * Get to the first byte.
1179 * Since code is always >= 8 bits, only need to mask the first
1182 *bp
= (*bp
& rmask
[r_off
]) | (code
<< r_off
) & lmask
[r_off
];
1184 bits
-= (8 - r_off
);
1187 * Get any 8 bit parts in the middle (<=1 for up to 16
1199 if (offset
== (n_bits
<< 3)) {
1204 if (putc(*bp
, outp
) == EOF
&&
1214 * If the next entry is going to be too big for the code size,
1215 * then increase it, if possible.
1217 if (free_ent
> maxcode
|| (clear_flg
> 0)) {
1219 * Write the whole buffer, because the input
1220 * side won't discover the size increase until
1221 * after it has read it.
1224 if (fwrite(buf
, 1, n_bits
, outp
) != n_bits
) {
1227 bytes_out
+= n_bits
;
1232 maxcode
= MAXCODE(n_bits
= INIT_BITS
);
1236 if (n_bits
== maxbits
)
1237 maxcode
= maxmaxcode
;
1239 maxcode
= MAXCODE(n_bits
);
1243 (void) fprintf(stderr
,
1244 "\nChange to %d bits\n", n_bits
);
1251 * At EOF, write the rest of the buffer.
1254 if (fwrite(buf
, 1, (offset
+ 7) / 8, outp
) == 0 &&
1258 bytes_out
+= (offset
+ 7) / 8;
1261 (void) fflush(outp
);
1264 (void) fprintf(stderr
, "\n");
1272 * Decompress inp to outp. This routine adapts to the codes in the
1273 * file building the "string" table on-the-fly; requiring no table to
1274 * be stored in the compressed file. The tables used herein are shared
1275 * with those of the compress() routine. See the definitions above.
1281 char_type
*stackp
, *stack_lim
;
1283 code_int code
, oldcode
, incode
;
1287 * As above, initialize the first 256 entries in the table.
1289 maxcode
= MAXCODE(n_bits
= INIT_BITS
);
1290 for (code
= 255; code
>= 0; code
--) {
1291 tab_prefixof(code
) = 0;
1292 tab_suffixof(code
) = (char_type
)code
;
1294 free_ent
= ((block_compress
) ? FIRST
: 256);
1296 finchar
= oldcode
= getcode();
1297 if (oldcode
== -1) /* EOF already? */
1298 return; /* Get out of here */
1299 /* first code must be 8 bits = char */
1300 if (putc((char)finchar
, outp
) == EOF
&& ferror(outp
)) {
1301 /* Crash if can't write */
1305 stack_lim
= stack_max
;
1307 while ((code
= getcode()) > -1) {
1309 if ((code
== CLEAR
) && block_compress
) {
1310 for (code
= 255; code
>= 0; code
--)
1311 tab_prefixof(code
) = 0;
1313 free_ent
= FIRST
- 1;
1314 if ((code
= getcode()) == -1) /* O, untimely death! */
1319 * Special case for KwKwK string.
1321 if (code
>= free_ent
) {
1322 if (stackp
< stack_lim
) {
1323 *stackp
++ = (char_type
) finchar
;
1332 * Generate output characters in reverse order
1334 while (code
>= 256) {
1335 if (stackp
< stack_lim
) {
1336 *stackp
++ = tab_suffixof(code
);
1337 code
= tab_prefixof(code
);
1343 *stackp
++ = finchar
= tab_suffixof(code
);
1346 * And put them out in forward order
1350 (void) putc(*stackp
, fout
);
1351 } while (stackp
> de_stack
);
1357 * Generate the new entry.
1359 if ((code
= free_ent
) < maxmaxcode
) {
1360 tab_prefixof(code
) = (unsigned short) oldcode
;
1361 tab_suffixof(code
) = (char_type
) finchar
;
1365 * Remember previous code.
1369 (void) fflush(outp
);
1375 * **************************************************************
1378 * Read one code from the standard input. If EOF, return -1.
1382 * code or -1 is returned.
1388 static int offset
= 0, size
= 0;
1389 static char_type buf
[BITS
];
1391 char_type
*bp
= buf
;
1393 if (clear_flg
> 0 || offset
>= size
|| free_ent
> maxcode
) {
1395 * If the next entry will be too big for the current code
1396 * size, then we must increase the size. This implies reading
1397 * a new buffer full, too.
1399 if (free_ent
> maxcode
) {
1401 if (n_bits
== maxbits
)
1402 /* won't get any bigger now */
1403 maxcode
= maxmaxcode
;
1405 maxcode
= MAXCODE(n_bits
);
1407 if (clear_flg
> 0) {
1408 maxcode
= MAXCODE(n_bits
= INIT_BITS
);
1411 size
= fread(buf
, 1, n_bits
, inp
);
1417 } else if (ferror(inp
)) {
1423 /* Round size down to integral number of codes */
1424 size
= (size
<< 3) - (n_bits
- 1);
1429 * Get to the first byte.
1433 /* Get first part (low order bits) */
1434 code
= (*bp
++ >> r_off
);
1435 bits
-= (8 - r_off
);
1436 r_off
= 8 - r_off
; /* now, offset into code word */
1437 /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
1439 code
|= *bp
++ << r_off
;
1443 /* high order bits. */
1444 code
|= (*bp
& rmask
[bits
]) << r_off
;
1455 * Just print out codes from input file. For debugging.
1460 bits
= n_bits
= INIT_BITS
;
1461 maxcode
= MAXCODE(n_bits
);
1462 free_ent
= ((block_compress
) ? FIRST
: 256);
1463 while ((code
= getcode()) >= 0) {
1464 if ((code
== CLEAR
) && block_compress
) {
1465 free_ent
= FIRST
- 1;
1467 } else if (free_ent
< maxmaxcode
)
1469 if (bits
!= n_bits
) {
1470 (void) fprintf(stderr
, "\nChange to %d bits\n", n_bits
);
1474 (void) fprintf(stderr
, "%5d%c",
1475 code
, (col
+= 6) >= 74 ? (col
= 0, '\n') : ' ');
1477 (void) putc('\n', stderr
);
1484 dump_tab() /* dump string table */
1488 int stack_top
= STACK_SIZE
;
1491 if (do_decomp
== 0) { /* compressing */
1494 for (i
= 0; i
< hsize
; i
++) { /* build sort pointers */
1495 if ((long)htabof(i
) >= 0) {
1496 sorttab
[codetabof(i
)] = i
;
1499 first
= block_compress
? FIRST
: 256;
1500 for (i
= first
; i
< free_ent
; i
++) {
1501 (void) fprintf(stderr
, "%5d: \"", i
);
1502 de_stack
[--stack_top
] = '\n';
1503 de_stack
[--stack_top
] = '"';
1505 in_stack((htabof(sorttab
[i
]) >> maxbits
) & 0xff,
1507 for (ent
= htabof(sorttab
[i
]) & ((1 << maxbits
) -1);
1509 ent
= htabof(sorttab
[ent
]) & ((1<<maxbits
)-1)) {
1510 stack_top
= in_stack(
1511 htabof(sorttab
[ent
]) >> maxbits
,
1514 stack_top
= in_stack(ent
, stack_top
);
1515 (void) fwrite(&de_stack
[stack_top
], 1,
1516 STACK_SIZE
- stack_top
, stderr
);
1517 stack_top
= STACK_SIZE
;
1519 } else if (!debug
) { /* decompressing */
1521 for (i
= 0; i
< free_ent
; i
++) {
1523 c
= tab_suffixof(ent
);
1524 if (isascii(c
) && isprint(c
))
1525 (void) fprintf(stderr
, "%5d: %5d/'%c' \"",
1526 ent
, tab_prefixof(ent
), c
);
1528 (void) fprintf(stderr
, "%5d: %5d/\\%03o \"",
1529 ent
, tab_prefixof(ent
), c
);
1530 de_stack
[--stack_top
] = '\n';
1531 de_stack
[--stack_top
] = '"';
1533 ent
= (ent
>= FIRST
? tab_prefixof(ent
) :
1535 stack_top
= in_stack(tab_suffixof(ent
),
1538 (void) fwrite(&de_stack
[stack_top
], 1,
1539 STACK_SIZE
- stack_top
, stderr
);
1540 stack_top
= STACK_SIZE
;
1548 in_stack(int c
, int stack_top
)
1550 if ((isascii(c
) && isprint(c
) && c
!= '\\') || c
== ' ') {
1551 de_stack
[--stack_top
] = c
;
1554 case '\n': de_stack
[--stack_top
] = 'n'; break;
1555 case '\t': de_stack
[--stack_top
] = 't'; break;
1556 case '\b': de_stack
[--stack_top
] = 'b'; break;
1557 case '\f': de_stack
[--stack_top
] = 'f'; break;
1558 case '\r': de_stack
[--stack_top
] = 'r'; break;
1559 case '\\': de_stack
[--stack_top
] = '\\'; break;
1561 de_stack
[--stack_top
] = '0' + c
% 8;
1562 de_stack
[--stack_top
] = '0' + (c
/ 8) % 8;
1563 de_stack
[--stack_top
] = '0' + c
/ 64;
1566 de_stack
[--stack_top
] = '\\';
1579 copystat(char *ifname
, struct stat
*ifstat
, char *ofname
)
1582 struct utimbuf timep
;
1585 int sattr_exist
= 0;
1586 int xattr_exist
= 0;
1588 if (pathconf(ifname
, _PC_XATTR_EXISTS
) == 1)
1590 if (saflg
&& sysattr_support(ifname
, _PC_SATTR_EXISTS
) == 1)
1596 (void) fprintf(stderr
, gettext(" -- file unchanged"));
1600 } else if (ifstat
== NULL
) { /* Get stat on input file */
1603 } else if ((ifstat
->st_mode
&
1604 S_IFMT
/* 0170000 */) != S_IFREG
/* 0100000 */) {
1606 (void) fprintf(stderr
, "%s: ", ifname
);
1608 (void) fprintf(stderr
, gettext(
1609 " -- not a regular file: unchanged"));
1612 } else if (ifstat
->st_nlink
> 1) {
1614 (void) fprintf(stderr
, "%s: ", ifname
);
1616 (void) fprintf(stderr
, gettext(
1617 " -- has %d other links: unchanged"),
1618 (uint_t
)ifstat
->st_nlink
- 1);
1621 } else if (didnt_shrink
&& !force
) {
1622 /* No compression: remove file.Z */
1624 (void) fprintf(stderr
, gettext(
1625 " -- file unchanged"));
1628 } else if ((xattr_exist
|| sattr_exist
) &&
1629 (mv_xattrs(progname
, ifname
, ofname
, sattr_exist
, 0)
1631 (void) fprintf(stderr
, gettext(
1632 "%s: -- cannot preserve extended attributes or "
1633 "system attributes, file unchanged"), ifname
);
1635 /* Move attributes back ... */
1638 if (pathconf(ofname
, _PC_XATTR_EXISTS
) == 1)
1640 if (saflg
&& sysattr_support(ofname
, _PC_SATTR_EXISTS
) == 1)
1642 if (sattr_exist
|| xattr_exist
)
1643 (void) mv_xattrs(progname
, ofname
, ifname
,
1646 } else { /* ***** Successful Compression ***** */
1647 mode
= ifstat
->st_mode
& 07777;
1648 if (chmod(ofname
, mode
)) { /* Copy modes */
1649 if (errno
== EPERM
) {
1650 (void) fprintf(stderr
,
1651 gettext("failed to chmod %s"
1652 "- permisssion denied\n"), ofname
);
1656 error
= acl_get(ifname
, ACL_NO_TRIVIAL
, &aclp
);
1658 (void) fprintf(stderr
, gettext(
1659 "%s: failed to retrieve acl : %s\n"),
1660 ifname
, acl_strerror(error
));
1663 if (aclp
&& (acl_set(ofname
, aclp
) < 0)) {
1664 (void) fprintf(stderr
,
1665 gettext("%s: failed to set acl "
1666 "entries\n"), ofname
);
1674 /* Copy ownership */
1675 (void) chown(ofname
, ifstat
->st_uid
, ifstat
->st_gid
);
1676 timep
.actime
= ifstat
->st_atime
;
1677 timep
.modtime
= ifstat
->st_mtime
;
1678 /* Update last accessed and modified times */
1679 (void) utime(ofname
, &timep
);
1680 if (unlink(ifname
)) { /* Remove input file */
1681 if (errno
== EPERM
) {
1682 (void) fprintf(stderr
,
1683 gettext("failed to remove %s"
1684 "- permisssion denied\n"), ifname
);
1689 (void) fprintf(stderr
, gettext(
1690 " -- replaced with %s"), ofname
);
1693 return; /* Successful return */
1696 /* Unsuccessful return -- one of the tests failed */
1697 if (ofname
[0] != '\0') {
1698 if (unlink(ofname
)) {
1699 if (errno
== EPERM
) {
1700 (void) fprintf(stderr
,
1701 gettext("failed to remove %s"
1702 "- permisssion denied\n"), ifname
);
1714 if (!precious
&& !use_stdout
&& ofname
[0] != '\0')
1715 (void) unlink(ofname
);
1720 oops() /* wild pointer -- assume bad input */
1723 (void) fprintf(stderr
, gettext("uncompress: corrupt input\n"));
1726 if (!use_stdout
&& ofname
[0] != '\0') {
1727 (void) unlink(ofname
);
1734 cl_block(count_long in_count
) /* table clear for block compress */
1738 checkpoint
= (count_long
)in_count
+ (count_long
)CHECK_GAP
;
1741 (void) fprintf(stderr
, "count: %lld, ratio: ",
1742 (count_long
)in_count
);
1743 prratio(stderr
, (count_long
)in_count
, (count_long
)bytes_out
);
1744 (void) fprintf(stderr
, "\n");
1748 /* shift will overflow */
1749 if ((count_long
)in_count
> 0x007fffffffffffffLL
) {
1750 rat
= (count_long
)bytes_out
>> 8;
1751 if (rat
== 0) { /* Don't divide by zero */
1752 rat
= 0x7fffffffffffffffLL
;
1754 rat
= (count_long
)in_count
/ (count_long
)rat
;
1757 /* 8 fractional bits */
1758 rat
= ((count_long
)in_count
<< 8) /(count_long
)bytes_out
;
1766 dump_tab(); /* dump string table */
1768 cl_hash((count_int
) hsize
);
1771 output((code_int
) CLEAR
);
1774 (void) fprintf(stderr
, "clear\n");
1780 cl_hash(count_int hsize
) /* reset code table */
1782 count_int
*htab_p
= htab
+hsize
;
1787 do { /* might use Sys V memset(3) here */
1805 } while ((i
-= 16) >= 0);
1806 for (i
+= 16; i
> 0; i
--)
1811 prratio(FILE *stream
, count_long num
, count_long den
)
1813 int q
; /* store percentage */
1815 q
= (int)(10000LL * (count_long
)num
/ (count_long
)den
);
1817 (void) putc('-', stream
);
1820 (void) fprintf(stream
, "%d%s%02d%%", q
/ 100,
1821 localeconv()->decimal_point
, q
% 100);
1827 (void) fprintf(stderr
, "%s, Berkeley 5.9 5/11/86\n", rcs_ident
);
1828 (void) fprintf(stderr
, "Options: ");
1830 (void) fprintf(stderr
, "DEBUG, ");
1832 (void) fprintf(stderr
, "BITS = %d\n", BITS
);
1839 (void) fprintf(stderr
,
1840 "Usage: compress [-dDVfc/] [-b maxbits] [file ...]\n");
1842 if (strcmp(progname
, "compress") == 0) {
1843 (void) fprintf(stderr
,
1845 "Usage: compress [-fv/] [-b maxbits] [file ...]\n"\
1846 " compress c [-fv] [-b maxbits] [file]\n"));
1847 } else if (strcmp(progname
, "uncompress") == 0)
1848 (void) fprintf(stderr
, gettext(
1849 "Usage: uncompress [-fv] [-c || -/] [file ...]\n"));
1850 else if (strcmp(progname
, "zcat") == 0)
1851 (void) fprintf(stderr
, gettext("Usage: zcat [file ...]\n"));
1857 local_basename(char *path
)
1860 char *ret
= (char *)path
;
1862 while ((p
= (char *)strpbrk(ret
, "/")) != NULL
)
1868 addDotZ(char *fn
, size_t fnsize
)
1875 fn_dup
= strdup(fn
);
1876 dir
= dirname(fn_dup
);
1877 max_name
= pathconf(dir
, _PC_NAME_MAX
);
1878 max_path
= pathconf(dir
, _PC_PATH_MAX
);
1881 /* Check for component length too long */
1883 if ((strlen(local_basename(fn
)) + 2) > (size_t)max_name
) {
1884 (void) fprintf(stderr
,
1885 gettext("%s: filename too long to tack on .Z:"
1886 " %s\n"), progname
, fn
);
1890 /* Check for path length too long */
1892 if ((strlen(fn
) + 2) > (size_t)max_path
- 1) {
1893 (void) fprintf(stderr
,
1894 gettext("%s: Pathname too long to tack on .Z:"
1895 " %s\n"), progname
, fn
);
1899 if (strlcat(fn
, ".Z", fnsize
) >= fnsize
) {
1900 (void) fprintf(stderr
,
1901 gettext("%s: Buffer overflow adding .Z to %s\n"),