1a77d64afScf46844 /* 2a77d64afScf46844 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 3a77d64afScf46844 * Use is subject to license terms. 4a77d64afScf46844 */ 5a77d64afScf46844 67c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 77c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 87c478bd9Sstevel@tonic-gate 97c478bd9Sstevel@tonic-gate 107c478bd9Sstevel@tonic-gate /* 117c478bd9Sstevel@tonic-gate * Copyright (c) 1986 Regents of the University of California. 127c478bd9Sstevel@tonic-gate * All rights reserved. The Berkeley software License Agreement 137c478bd9Sstevel@tonic-gate * specifies the terms and conditions for redistribution. 147c478bd9Sstevel@tonic-gate */ 157c478bd9Sstevel@tonic-gate 167c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 177c478bd9Sstevel@tonic-gate 187c478bd9Sstevel@tonic-gate /* 197c478bd9Sstevel@tonic-gate * Compress - data compression program 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate #define min(a, b) ((a > b) ? b : a) 227c478bd9Sstevel@tonic-gate 237c478bd9Sstevel@tonic-gate /* 247c478bd9Sstevel@tonic-gate * machine variants which require cc -Dmachine: pdp11, z8000, pcxt 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate /* 287c478bd9Sstevel@tonic-gate * Set USERMEM to the maximum amount of physical user memory available 297c478bd9Sstevel@tonic-gate * in bytes. USERMEM is used to determine the maximum BITS that can be used 307c478bd9Sstevel@tonic-gate * for compression. 317c478bd9Sstevel@tonic-gate * 327c478bd9Sstevel@tonic-gate * SACREDMEM is the amount of physical memory saved for others; compress 337c478bd9Sstevel@tonic-gate * will hog the rest. 347c478bd9Sstevel@tonic-gate */ 357c478bd9Sstevel@tonic-gate #ifndef SACREDMEM 367c478bd9Sstevel@tonic-gate #define SACREDMEM 0 377c478bd9Sstevel@tonic-gate #endif 387c478bd9Sstevel@tonic-gate 397c478bd9Sstevel@tonic-gate #ifndef USERMEM 407c478bd9Sstevel@tonic-gate #define USERMEM 450000 /* default user memory */ 417c478bd9Sstevel@tonic-gate #endif 427c478bd9Sstevel@tonic-gate 437c478bd9Sstevel@tonic-gate #ifdef USERMEM 447c478bd9Sstevel@tonic-gate #if USERMEM >= (433484+SACREDMEM) 457c478bd9Sstevel@tonic-gate #define PBITS 16 467c478bd9Sstevel@tonic-gate #else 477c478bd9Sstevel@tonic-gate #if USERMEM >= (229600+SACREDMEM) 487c478bd9Sstevel@tonic-gate #define PBITS 15 497c478bd9Sstevel@tonic-gate #else 507c478bd9Sstevel@tonic-gate #if USERMEM >= (127536+SACREDMEM) 517c478bd9Sstevel@tonic-gate #define PBITS 14 527c478bd9Sstevel@tonic-gate #else 537c478bd9Sstevel@tonic-gate #if USERMEM >= (73464+SACREDMEM) 547c478bd9Sstevel@tonic-gate #define PBITS 13 557c478bd9Sstevel@tonic-gate #else 567c478bd9Sstevel@tonic-gate #define PBITS 12 577c478bd9Sstevel@tonic-gate #endif 587c478bd9Sstevel@tonic-gate #endif 597c478bd9Sstevel@tonic-gate #endif 607c478bd9Sstevel@tonic-gate #endif 617c478bd9Sstevel@tonic-gate #undef USERMEM 627c478bd9Sstevel@tonic-gate #endif /* USERMEM */ 637c478bd9Sstevel@tonic-gate 647c478bd9Sstevel@tonic-gate #ifdef PBITS /* Preferred BITS for this memory size */ 657c478bd9Sstevel@tonic-gate #ifndef BITS 667c478bd9Sstevel@tonic-gate #define BITS PBITS 677c478bd9Sstevel@tonic-gate #endif /* BITS */ 687c478bd9Sstevel@tonic-gate #endif /* PBITS */ 697c478bd9Sstevel@tonic-gate 707c478bd9Sstevel@tonic-gate #if BITS == 16 717c478bd9Sstevel@tonic-gate #define HSIZE 69001 /* 95% occupancy */ 727c478bd9Sstevel@tonic-gate #endif 737c478bd9Sstevel@tonic-gate #if BITS == 15 747c478bd9Sstevel@tonic-gate #define HSIZE 35023 /* 94% occupancy */ 757c478bd9Sstevel@tonic-gate #endif 767c478bd9Sstevel@tonic-gate #if BITS == 14 777c478bd9Sstevel@tonic-gate #define HSIZE 18013 /* 91% occupancy */ 787c478bd9Sstevel@tonic-gate #endif 797c478bd9Sstevel@tonic-gate #if BITS == 13 807c478bd9Sstevel@tonic-gate #define HSIZE 9001 /* 91% occupancy */ 817c478bd9Sstevel@tonic-gate #endif 827c478bd9Sstevel@tonic-gate #if BITS <= 12 837c478bd9Sstevel@tonic-gate #define HSIZE 5003 /* 80% occupancy */ 847c478bd9Sstevel@tonic-gate #endif 857c478bd9Sstevel@tonic-gate 867c478bd9Sstevel@tonic-gate #define OUTSTACKSIZE (2<<BITS) 877c478bd9Sstevel@tonic-gate 887c478bd9Sstevel@tonic-gate /* 897c478bd9Sstevel@tonic-gate * a code_int must be able to hold 2**BITS values of type int, and also -1 907c478bd9Sstevel@tonic-gate */ 917c478bd9Sstevel@tonic-gate #if BITS > 15 927c478bd9Sstevel@tonic-gate typedef long int code_int; 937c478bd9Sstevel@tonic-gate #else 947c478bd9Sstevel@tonic-gate typedef int code_int; 957c478bd9Sstevel@tonic-gate #endif 967c478bd9Sstevel@tonic-gate 977c478bd9Sstevel@tonic-gate typedef long int count_int; 987c478bd9Sstevel@tonic-gate typedef long long count_long; 997c478bd9Sstevel@tonic-gate 1007c478bd9Sstevel@tonic-gate typedef unsigned char char_type; 1017c478bd9Sstevel@tonic-gate 1027c478bd9Sstevel@tonic-gate static char_type magic_header[] = { "\037\235" }; /* 1F 9D */ 1037c478bd9Sstevel@tonic-gate 1047c478bd9Sstevel@tonic-gate /* Defines for third byte of header */ 1057c478bd9Sstevel@tonic-gate #define BIT_MASK 0x1f 1067c478bd9Sstevel@tonic-gate #define BLOCK_MASK 0x80 1077c478bd9Sstevel@tonic-gate /* 1087c478bd9Sstevel@tonic-gate * Masks 0x40 and 0x20 are free. I think 0x20 should mean that there is 1097c478bd9Sstevel@tonic-gate * a fourth header byte(for expansion). 1107c478bd9Sstevel@tonic-gate */ 1117c478bd9Sstevel@tonic-gate #define INIT_BITS 9 /* initial number of bits/code */ 1127c478bd9Sstevel@tonic-gate 1137c478bd9Sstevel@tonic-gate /* 1147c478bd9Sstevel@tonic-gate * compress.c - File compression ala IEEE Computer, June 1984. 1157c478bd9Sstevel@tonic-gate */ 1167c478bd9Sstevel@tonic-gate static char rcs_ident[] = 1177c478bd9Sstevel@tonic-gate "$Header: compress.c,v 4.0 85/07/30 12:50:00 joe Release $"; 1187c478bd9Sstevel@tonic-gate 1197c478bd9Sstevel@tonic-gate #include <stdio.h> 1207c478bd9Sstevel@tonic-gate #include <ctype.h> 1217c478bd9Sstevel@tonic-gate #include <signal.h> 1227c478bd9Sstevel@tonic-gate #include <sys/types.h> 1237c478bd9Sstevel@tonic-gate #include <sys/stat.h> 1247c478bd9Sstevel@tonic-gate #include <unistd.h> 1257c478bd9Sstevel@tonic-gate #include <sys/param.h> 1267c478bd9Sstevel@tonic-gate #include <stdlib.h> /* XCU4 */ 1277c478bd9Sstevel@tonic-gate #include <limits.h> 1287c478bd9Sstevel@tonic-gate #include <libintl.h> 1297c478bd9Sstevel@tonic-gate #include <locale.h> 1307c478bd9Sstevel@tonic-gate #include <langinfo.h> 1317c478bd9Sstevel@tonic-gate #include <string.h> 1327c478bd9Sstevel@tonic-gate #include <sys/acl.h> 1337c478bd9Sstevel@tonic-gate #include <utime.h> 1347c478bd9Sstevel@tonic-gate #include <libgen.h> 1357c478bd9Sstevel@tonic-gate #include <setjmp.h> 1367c478bd9Sstevel@tonic-gate #include <strings.h> 1377c478bd9Sstevel@tonic-gate #include <fcntl.h> 1387c478bd9Sstevel@tonic-gate #include <dirent.h> 139*fa9e4066Sahrens #include <aclutils.h> 1407c478bd9Sstevel@tonic-gate 1417c478bd9Sstevel@tonic-gate /* 1427c478bd9Sstevel@tonic-gate * Multi-byte handling for 'y' or 'n' 1437c478bd9Sstevel@tonic-gate */ 1447c478bd9Sstevel@tonic-gate static char *yesstr; /* string contains int'l for "yes" */ 1457c478bd9Sstevel@tonic-gate static char *nostr; /* string contains int'l for "yes" */ 1467c478bd9Sstevel@tonic-gate static int ynsize = 0; /* # of (multi)bytes for "y" */ 1477c478bd9Sstevel@tonic-gate static char *yesorno; /* int'l input for 'y' */ 1487c478bd9Sstevel@tonic-gate 1497c478bd9Sstevel@tonic-gate static int n_bits; /* number of bits/code */ 1507c478bd9Sstevel@tonic-gate static int maxbits = BITS; /* user settable max # bits/code */ 1517c478bd9Sstevel@tonic-gate static code_int maxcode; /* maximum code, given n_bits */ 1527c478bd9Sstevel@tonic-gate /* should NEVER generate this code */ 1537c478bd9Sstevel@tonic-gate static code_int maxmaxcode = 1 << BITS; 1547c478bd9Sstevel@tonic-gate #define MAXCODE(n_bits) ((1 << (n_bits)) - 1) 1557c478bd9Sstevel@tonic-gate 1567c478bd9Sstevel@tonic-gate static count_int htab [OUTSTACKSIZE]; 1577c478bd9Sstevel@tonic-gate static unsigned short codetab [OUTSTACKSIZE]; 1587c478bd9Sstevel@tonic-gate 1597c478bd9Sstevel@tonic-gate #define htabof(i) htab[i] 1607c478bd9Sstevel@tonic-gate #define codetabof(i) codetab[i] 1617c478bd9Sstevel@tonic-gate static code_int hsize = HSIZE; /* for dynamic table sizing */ 1627c478bd9Sstevel@tonic-gate static off_t fsize; /* file size of input file */ 1637c478bd9Sstevel@tonic-gate 1647c478bd9Sstevel@tonic-gate /* 1657c478bd9Sstevel@tonic-gate * To save much memory, we overlay the table used by compress() with those 1667c478bd9Sstevel@tonic-gate * used by decompress(). The tab_prefix table is the same size and type 1677c478bd9Sstevel@tonic-gate * as the codetab. The tab_suffix table needs 2**BITS characters. We 1687c478bd9Sstevel@tonic-gate * get this from the beginning of htab. The output stack uses the rest 1697c478bd9Sstevel@tonic-gate * of htab, and contains characters. There is plenty of room for any 1707c478bd9Sstevel@tonic-gate * possible stack (stack used to be 8000 characters). 1717c478bd9Sstevel@tonic-gate */ 1727c478bd9Sstevel@tonic-gate 1737c478bd9Sstevel@tonic-gate #define tab_prefixof(i) codetabof(i) 1747c478bd9Sstevel@tonic-gate #define tab_suffixof(i) ((char_type *)(htab))[i] 1757c478bd9Sstevel@tonic-gate #define de_stack ((char_type *)&tab_suffixof(1<<BITS)) 1767c478bd9Sstevel@tonic-gate #define stack_max ((char_type *)&tab_suffixof(OUTSTACKSIZE)) 1777c478bd9Sstevel@tonic-gate 1787c478bd9Sstevel@tonic-gate static code_int free_ent = 0; /* first unused entry */ 1797c478bd9Sstevel@tonic-gate static int newline_needed = 0; 1807c478bd9Sstevel@tonic-gate static int didnt_shrink = 0; 1817c478bd9Sstevel@tonic-gate static int perm_stat = 0; /* permanent status */ 1827c478bd9Sstevel@tonic-gate 1837c478bd9Sstevel@tonic-gate static code_int getcode(); 1847c478bd9Sstevel@tonic-gate 1857c478bd9Sstevel@tonic-gate /* Use a 3-byte magic number header, unless old file */ 1867c478bd9Sstevel@tonic-gate static int nomagic = 0; 1877c478bd9Sstevel@tonic-gate /* Write output on stdout, suppress messages */ 1887c478bd9Sstevel@tonic-gate static int zcat_flg = 0; /* use stdout on all files */ 1897c478bd9Sstevel@tonic-gate static int zcat_cmd = 0; /* zcat cmd */ 1907c478bd9Sstevel@tonic-gate static int use_stdout = 0; /* set for each file processed */ 1917c478bd9Sstevel@tonic-gate /* Don't unlink output file on interrupt */ 1927c478bd9Sstevel@tonic-gate static int precious = 1; 1937c478bd9Sstevel@tonic-gate static int quiet = 1; /* don't tell me about compression */ 1947c478bd9Sstevel@tonic-gate 1957c478bd9Sstevel@tonic-gate /* 1967c478bd9Sstevel@tonic-gate * block compression parameters -- after all codes are used up, 1977c478bd9Sstevel@tonic-gate * and compression rate changes, start over. 1987c478bd9Sstevel@tonic-gate */ 1997c478bd9Sstevel@tonic-gate static int block_compress = BLOCK_MASK; 2007c478bd9Sstevel@tonic-gate static int clear_flg = 0; 2017c478bd9Sstevel@tonic-gate static long int ratio = 0; 2027c478bd9Sstevel@tonic-gate #define CHECK_GAP 10000 /* ratio check interval */ 2037c478bd9Sstevel@tonic-gate static count_long checkpoint = CHECK_GAP; 2047c478bd9Sstevel@tonic-gate /* 2057c478bd9Sstevel@tonic-gate * the next two codes should not be changed lightly, as they must not 2067c478bd9Sstevel@tonic-gate * lie within the contiguous general code space. 2077c478bd9Sstevel@tonic-gate */ 2087c478bd9Sstevel@tonic-gate #define FIRST 257 /* first free entry */ 2097c478bd9Sstevel@tonic-gate #define CLEAR 256 /* table clear output code */ 2107c478bd9Sstevel@tonic-gate 2117c478bd9Sstevel@tonic-gate static int force = 0; 2127c478bd9Sstevel@tonic-gate static char ofname [MAXPATHLEN]; 2137c478bd9Sstevel@tonic-gate 2147c478bd9Sstevel@tonic-gate static int Vflg = 0; 2157c478bd9Sstevel@tonic-gate static int vflg = 0; 2167c478bd9Sstevel@tonic-gate static int qflg = 0; 2177c478bd9Sstevel@tonic-gate static int bflg = 0; 2187c478bd9Sstevel@tonic-gate static int Fflg = 0; 2197c478bd9Sstevel@tonic-gate static int dflg = 0; 2207c478bd9Sstevel@tonic-gate static int cflg = 0; 2217c478bd9Sstevel@tonic-gate static int Cflg = 0; 2227c478bd9Sstevel@tonic-gate 2237c478bd9Sstevel@tonic-gate #ifdef DEBUG 2247c478bd9Sstevel@tonic-gate int verbose = 0; 2257c478bd9Sstevel@tonic-gate int debug = 0; 2267c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 2277c478bd9Sstevel@tonic-gate 2287c478bd9Sstevel@tonic-gate static void (*oldint)(); 2297c478bd9Sstevel@tonic-gate static int bgnd_flag; 2307c478bd9Sstevel@tonic-gate 2317c478bd9Sstevel@tonic-gate static int do_decomp = 0; 2327c478bd9Sstevel@tonic-gate 2337c478bd9Sstevel@tonic-gate static char *progname; 2347c478bd9Sstevel@tonic-gate static char *optstr; 2357c478bd9Sstevel@tonic-gate /* 2367c478bd9Sstevel@tonic-gate * Fix lint errors 2377c478bd9Sstevel@tonic-gate */ 2387c478bd9Sstevel@tonic-gate 2397c478bd9Sstevel@tonic-gate static char *local_basename(char *); 2407c478bd9Sstevel@tonic-gate 2417c478bd9Sstevel@tonic-gate static int addDotZ(char *, size_t); 2427c478bd9Sstevel@tonic-gate 2437c478bd9Sstevel@tonic-gate static void Usage(void); 2447c478bd9Sstevel@tonic-gate static void cl_block(count_long); 2457c478bd9Sstevel@tonic-gate static void cl_hash(count_int); 2467c478bd9Sstevel@tonic-gate static void compress(void); 2477c478bd9Sstevel@tonic-gate static void copystat(char *, struct stat *, char *); 2487c478bd9Sstevel@tonic-gate static void decompress(void); 2497c478bd9Sstevel@tonic-gate static void ioerror(void); 2507c478bd9Sstevel@tonic-gate static void onintr(); 2517c478bd9Sstevel@tonic-gate static void oops(); 2527c478bd9Sstevel@tonic-gate static void output(code_int); 2537c478bd9Sstevel@tonic-gate static void prratio(FILE *, count_long, count_long); 2547c478bd9Sstevel@tonic-gate static void version(void); 2557c478bd9Sstevel@tonic-gate static int mv_xattrs(char *, char *, int); 2567c478bd9Sstevel@tonic-gate 2577c478bd9Sstevel@tonic-gate #ifdef DEBUG 2587c478bd9Sstevel@tonic-gate static int in_stack(int, int); 2597c478bd9Sstevel@tonic-gate static void dump_tab(void); 2607c478bd9Sstevel@tonic-gate static void printcodes(void); 2617c478bd9Sstevel@tonic-gate #endif 2627c478bd9Sstevel@tonic-gate 2637c478bd9Sstevel@tonic-gate /* For error-handling */ 2647c478bd9Sstevel@tonic-gate 2657c478bd9Sstevel@tonic-gate static jmp_buf env; 2667c478bd9Sstevel@tonic-gate 2677c478bd9Sstevel@tonic-gate /* For input and ouput */ 2687c478bd9Sstevel@tonic-gate 2697c478bd9Sstevel@tonic-gate static FILE *inp; /* the current input file */ 2707c478bd9Sstevel@tonic-gate static FILE *infile; /* disk-based input stream */ 2717c478bd9Sstevel@tonic-gate static FILE *outp; /* current output file */ 2727c478bd9Sstevel@tonic-gate static FILE *outfile; /* disk-based output stream */ 2737c478bd9Sstevel@tonic-gate 2747c478bd9Sstevel@tonic-gate /* For output() */ 2757c478bd9Sstevel@tonic-gate 2767c478bd9Sstevel@tonic-gate static char buf[BITS]; 2777c478bd9Sstevel@tonic-gate 2787c478bd9Sstevel@tonic-gate static char_type lmask[9] = 2797c478bd9Sstevel@tonic-gate {0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00}; 2807c478bd9Sstevel@tonic-gate static char_type rmask[9] = 2817c478bd9Sstevel@tonic-gate {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff}; 2827c478bd9Sstevel@tonic-gate 2837c478bd9Sstevel@tonic-gate /* For compress () */ 2847c478bd9Sstevel@tonic-gate 2857c478bd9Sstevel@tonic-gate static int offset; 2867c478bd9Sstevel@tonic-gate static count_long bytes_out; /* length of compressed output */ 2877c478bd9Sstevel@tonic-gate /* # of codes output (for debugging) */ 2887c478bd9Sstevel@tonic-gate 2897c478bd9Sstevel@tonic-gate /* For dump_tab() */ 2907c478bd9Sstevel@tonic-gate 2917c478bd9Sstevel@tonic-gate #define STACK_SIZE 15000 2927c478bd9Sstevel@tonic-gate #ifdef DEBUG 2937c478bd9Sstevel@tonic-gate code_int sorttab[1<<BITS]; /* sorted pointers into htab */ 2947c478bd9Sstevel@tonic-gate #endif 2957c478bd9Sstevel@tonic-gate 2967c478bd9Sstevel@tonic-gate /* 2977c478bd9Sstevel@tonic-gate * ************************************************************* 2987c478bd9Sstevel@tonic-gate * TAG( main ) 2997c478bd9Sstevel@tonic-gate * 3007c478bd9Sstevel@tonic-gate * Algorithm from "A Technique for High Performance Data Compression", 3017c478bd9Sstevel@tonic-gate * Terry A. Welch, IEEE Computer Vol 17, No 6 (June 1984), pp 8-19. 3027c478bd9Sstevel@tonic-gate * 3037c478bd9Sstevel@tonic-gate * Usage: compress [-dfvc] [-b bits] [file ...] 3047c478bd9Sstevel@tonic-gate * Inputs: 3057c478bd9Sstevel@tonic-gate * -d: If given, decompression is done instead. 3067c478bd9Sstevel@tonic-gate * 3077c478bd9Sstevel@tonic-gate * -c: Write output on stdout, don't remove original. 3087c478bd9Sstevel@tonic-gate * 3097c478bd9Sstevel@tonic-gate * -b: Parameter limits the max number of bits/code. 3107c478bd9Sstevel@tonic-gate * 3117c478bd9Sstevel@tonic-gate * -f: Forces output file to be generated, even if one already 3127c478bd9Sstevel@tonic-gate * exists, and even if no space is saved by compressing. 3137c478bd9Sstevel@tonic-gate * If -f is not used, the user will be prompted if stdin is 3147c478bd9Sstevel@tonic-gate * a tty, otherwise, the output file will not be overwritten. 3157c478bd9Sstevel@tonic-gate * 3167c478bd9Sstevel@tonic-gate * -v: Write compression statistics 3177c478bd9Sstevel@tonic-gate * 3187c478bd9Sstevel@tonic-gate * file ...: Files to be compressed. If none specified, stdin 3197c478bd9Sstevel@tonic-gate * is used. 3207c478bd9Sstevel@tonic-gate * Outputs: 3217c478bd9Sstevel@tonic-gate * file.Z: Compressed form of file with same mode, owner, and utimes 3227c478bd9Sstevel@tonic-gate * or stdout (if stdin used as input) 3237c478bd9Sstevel@tonic-gate * 3247c478bd9Sstevel@tonic-gate * Assumptions: 3257c478bd9Sstevel@tonic-gate * When filenames are given, replaces with the compressed version 3267c478bd9Sstevel@tonic-gate * (.Z suffix) only if the file decreases in size. 3277c478bd9Sstevel@tonic-gate * Algorithm: 3287c478bd9Sstevel@tonic-gate * Modified Lempel-Ziv method (LZW). Basically finds common 3297c478bd9Sstevel@tonic-gate * substrings and replaces them with a variable size code. This is 3307c478bd9Sstevel@tonic-gate * deterministic, and can be done on the fly. Thus, the decompression 3317c478bd9Sstevel@tonic-gate * procedure needs no input table, but tracks the way the table was built. 3327c478bd9Sstevel@tonic-gate */ 3337c478bd9Sstevel@tonic-gate 3347c478bd9Sstevel@tonic-gate int 3357c478bd9Sstevel@tonic-gate main(int argc, char *argv[]) 3367c478bd9Sstevel@tonic-gate { 3377c478bd9Sstevel@tonic-gate int overwrite = 0; /* Do not overwrite unless given -f flag */ 3387c478bd9Sstevel@tonic-gate char tempname[MAXPATHLEN]; 3397c478bd9Sstevel@tonic-gate char line[LINE_MAX]; 3407c478bd9Sstevel@tonic-gate char **filelist, **fileptr; 3417c478bd9Sstevel@tonic-gate char *cp; 3427c478bd9Sstevel@tonic-gate struct stat statbuf; 3437c478bd9Sstevel@tonic-gate struct stat ostatbuf; 3447c478bd9Sstevel@tonic-gate int ch; /* XCU4 */ 3457c478bd9Sstevel@tonic-gate char *p, *yptr, *nptr; 3467c478bd9Sstevel@tonic-gate extern int optind, optopt; 3477c478bd9Sstevel@tonic-gate extern char *optarg; 3487c478bd9Sstevel@tonic-gate int dash_count = 0; /* times "-" is on cmdline */ 3497c478bd9Sstevel@tonic-gate 3507c478bd9Sstevel@tonic-gate /* XCU4 changes */ 3517c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 3527c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 3537c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */ 3547c478bd9Sstevel@tonic-gate #endif 3557c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 3567c478bd9Sstevel@tonic-gate /* Build multi-byte char for 'y' char */ 3577c478bd9Sstevel@tonic-gate if ((yptr = nl_langinfo(YESSTR)) == NULL) 3587c478bd9Sstevel@tonic-gate yptr = "y"; 3597c478bd9Sstevel@tonic-gate 3607c478bd9Sstevel@tonic-gate yesstr = (char *)malloc(strlen(yptr) + 1); 3617c478bd9Sstevel@tonic-gate (void) strcpy(yesstr, yptr); 3627c478bd9Sstevel@tonic-gate /* Build multi-byte char for 'n' char */ 3637c478bd9Sstevel@tonic-gate if ((nptr = nl_langinfo(NOSTR)) == NULL) 3647c478bd9Sstevel@tonic-gate nptr = "n"; 3657c478bd9Sstevel@tonic-gate 3667c478bd9Sstevel@tonic-gate nostr = (char *)malloc(strlen(nptr) + 1); 3677c478bd9Sstevel@tonic-gate (void) strcpy(nostr, nptr); 3687c478bd9Sstevel@tonic-gate 3697c478bd9Sstevel@tonic-gate /* Build multi-byte char for input char */ 3707c478bd9Sstevel@tonic-gate yesorno = (char *)malloc((size_t)ynsize + 1); 3717c478bd9Sstevel@tonic-gate ynsize = mblen(yesstr, strlen(yesstr)); 3727c478bd9Sstevel@tonic-gate 3737c478bd9Sstevel@tonic-gate /* This bg check only works for sh. */ 3747c478bd9Sstevel@tonic-gate if ((oldint = signal(SIGINT, SIG_IGN)) != SIG_IGN) { 3757c478bd9Sstevel@tonic-gate (void) signal(SIGINT, onintr); 3767c478bd9Sstevel@tonic-gate (void) signal(SIGSEGV, oops); 3777c478bd9Sstevel@tonic-gate } 3787c478bd9Sstevel@tonic-gate bgnd_flag = oldint != SIG_DFL; 3797c478bd9Sstevel@tonic-gate 3807c478bd9Sstevel@tonic-gate /* Allocate room for argv + "-" (if stdin needs to be added) */ 3817c478bd9Sstevel@tonic-gate 3827c478bd9Sstevel@tonic-gate filelist = fileptr = (char **)(malloc((argc + 1) * sizeof (*argv))); 3837c478bd9Sstevel@tonic-gate *filelist = NULL; 3847c478bd9Sstevel@tonic-gate 3857c478bd9Sstevel@tonic-gate if ((cp = rindex(argv[0], '/')) != 0) { 3867c478bd9Sstevel@tonic-gate cp++; 3877c478bd9Sstevel@tonic-gate } else { 3887c478bd9Sstevel@tonic-gate cp = argv[0]; 3897c478bd9Sstevel@tonic-gate } 3907c478bd9Sstevel@tonic-gate 3917c478bd9Sstevel@tonic-gate if (strcmp(cp, "uncompress") == 0) { 3927c478bd9Sstevel@tonic-gate do_decomp = 1; 3937c478bd9Sstevel@tonic-gate } else if (strcmp(cp, "zcat") == 0) { 3947c478bd9Sstevel@tonic-gate do_decomp = 1; 3957c478bd9Sstevel@tonic-gate zcat_cmd = zcat_flg = 1; 3967c478bd9Sstevel@tonic-gate } 3977c478bd9Sstevel@tonic-gate 3987c478bd9Sstevel@tonic-gate progname = local_basename(argv[0]); 3997c478bd9Sstevel@tonic-gate 4007c478bd9Sstevel@tonic-gate /* 4017c478bd9Sstevel@tonic-gate * Argument Processing 4027c478bd9Sstevel@tonic-gate * All flags are optional. 4037c478bd9Sstevel@tonic-gate * -D = > debug 4047c478bd9Sstevel@tonic-gate * -V = > print Version; debug verbose 4057c478bd9Sstevel@tonic-gate * -d = > do_decomp 4067c478bd9Sstevel@tonic-gate * -v = > unquiet 4077c478bd9Sstevel@tonic-gate * -f = > force overwrite of output file 4087c478bd9Sstevel@tonic-gate * -n = > no header: useful to uncompress old files 4097c478bd9Sstevel@tonic-gate * -b maxbits => maxbits. If -b is specified, 4107c478bd9Sstevel@tonic-gate * then maxbits MUST be given also. 4117c478bd9Sstevel@tonic-gate * -c = > cat all output to stdout 4127c478bd9Sstevel@tonic-gate * -C = > generate output compatible with compress 2.0. 4137c478bd9Sstevel@tonic-gate * if a string is left, must be an input filename. 4147c478bd9Sstevel@tonic-gate */ 4157c478bd9Sstevel@tonic-gate #ifdef DEBUG 4167c478bd9Sstevel@tonic-gate optstr = "b:cCdDfFnqvV"; 4177c478bd9Sstevel@tonic-gate #else 4187c478bd9Sstevel@tonic-gate optstr = "b:cCdfFnqvV"; 4197c478bd9Sstevel@tonic-gate #endif 4207c478bd9Sstevel@tonic-gate 4217c478bd9Sstevel@tonic-gate while ((ch = getopt(argc, argv, optstr)) != EOF) { 4227c478bd9Sstevel@tonic-gate /* Process all flags in this arg */ 4237c478bd9Sstevel@tonic-gate switch (ch) { 4247c478bd9Sstevel@tonic-gate #ifdef DEBUG 4257c478bd9Sstevel@tonic-gate case 'D': 4267c478bd9Sstevel@tonic-gate debug = 1; 4277c478bd9Sstevel@tonic-gate break; 4287c478bd9Sstevel@tonic-gate case 'V': 4297c478bd9Sstevel@tonic-gate verbose = 1; 4307c478bd9Sstevel@tonic-gate version(); 4317c478bd9Sstevel@tonic-gate break; 4327c478bd9Sstevel@tonic-gate #else 4337c478bd9Sstevel@tonic-gate case 'V': 4347c478bd9Sstevel@tonic-gate version(); 4357c478bd9Sstevel@tonic-gate Vflg++; 4367c478bd9Sstevel@tonic-gate break; 4377c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 4387c478bd9Sstevel@tonic-gate case 'v': 4397c478bd9Sstevel@tonic-gate quiet = 0; 4407c478bd9Sstevel@tonic-gate vflg++; 4417c478bd9Sstevel@tonic-gate break; 4427c478bd9Sstevel@tonic-gate case 'd': 4437c478bd9Sstevel@tonic-gate do_decomp = 1; 4447c478bd9Sstevel@tonic-gate dflg++; 4457c478bd9Sstevel@tonic-gate break; 4467c478bd9Sstevel@tonic-gate case 'f': 4477c478bd9Sstevel@tonic-gate case 'F': 4487c478bd9Sstevel@tonic-gate Fflg++; 4497c478bd9Sstevel@tonic-gate overwrite = 1; 4507c478bd9Sstevel@tonic-gate force = 1; 4517c478bd9Sstevel@tonic-gate break; 4527c478bd9Sstevel@tonic-gate case 'n': 4537c478bd9Sstevel@tonic-gate nomagic = 1; 4547c478bd9Sstevel@tonic-gate break; 4557c478bd9Sstevel@tonic-gate case 'C': 4567c478bd9Sstevel@tonic-gate Cflg++; 4577c478bd9Sstevel@tonic-gate block_compress = 0; 4587c478bd9Sstevel@tonic-gate break; 4597c478bd9Sstevel@tonic-gate case 'b': 4607c478bd9Sstevel@tonic-gate bflg++; 4617c478bd9Sstevel@tonic-gate p = optarg; 4627c478bd9Sstevel@tonic-gate if (!p) { 4637c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 4647c478bd9Sstevel@tonic-gate "Missing maxbits\n")); 4657c478bd9Sstevel@tonic-gate Usage(); 4667c478bd9Sstevel@tonic-gate exit(1); 4677c478bd9Sstevel@tonic-gate } 4687c478bd9Sstevel@tonic-gate maxbits = strtoul(optarg, &p, 10); 4697c478bd9Sstevel@tonic-gate if (*p) { 4707c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 4717c478bd9Sstevel@tonic-gate "Missing maxbits\n")); 4727c478bd9Sstevel@tonic-gate Usage(); 4737c478bd9Sstevel@tonic-gate exit(1); 4747c478bd9Sstevel@tonic-gate } 4757c478bd9Sstevel@tonic-gate break; 4767c478bd9Sstevel@tonic-gate 4777c478bd9Sstevel@tonic-gate case 'c': 4787c478bd9Sstevel@tonic-gate cflg++; 4797c478bd9Sstevel@tonic-gate zcat_flg = 1; 4807c478bd9Sstevel@tonic-gate break; 4817c478bd9Sstevel@tonic-gate case 'q': 4827c478bd9Sstevel@tonic-gate qflg++; 4837c478bd9Sstevel@tonic-gate quiet = 1; 4847c478bd9Sstevel@tonic-gate break; 4857c478bd9Sstevel@tonic-gate default: 4867c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 4877c478bd9Sstevel@tonic-gate "Unknown flag: '%c'\n"), optopt); 4887c478bd9Sstevel@tonic-gate Usage(); 4897c478bd9Sstevel@tonic-gate exit(1); 4907c478bd9Sstevel@tonic-gate } 4917c478bd9Sstevel@tonic-gate } /* while */ 4927c478bd9Sstevel@tonic-gate 4937c478bd9Sstevel@tonic-gate /* 4947c478bd9Sstevel@tonic-gate * Validate zcat syntax 4957c478bd9Sstevel@tonic-gate */ 4967c478bd9Sstevel@tonic-gate 4977c478bd9Sstevel@tonic-gate if (zcat_cmd && (Fflg | Cflg | cflg | 4987c478bd9Sstevel@tonic-gate bflg | qflg | dflg | nomagic)) { 4997c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 5007c478bd9Sstevel@tonic-gate "Invalid Option\n")); 5017c478bd9Sstevel@tonic-gate Usage(); 5027c478bd9Sstevel@tonic-gate exit(1); 5037c478bd9Sstevel@tonic-gate } 5047c478bd9Sstevel@tonic-gate 5057c478bd9Sstevel@tonic-gate /* 5067c478bd9Sstevel@tonic-gate * Process the file list 5077c478bd9Sstevel@tonic-gate */ 5087c478bd9Sstevel@tonic-gate 5097c478bd9Sstevel@tonic-gate for (; optind < argc; optind++) { 5107c478bd9Sstevel@tonic-gate if (strcmp(argv[optind], "-") == 0) { 5117c478bd9Sstevel@tonic-gate dash_count++; 5127c478bd9Sstevel@tonic-gate } 5137c478bd9Sstevel@tonic-gate 5147c478bd9Sstevel@tonic-gate *fileptr++ = argv[optind]; /* Build input file list */ 5157c478bd9Sstevel@tonic-gate *fileptr = NULL; 5167c478bd9Sstevel@tonic-gate } 5177c478bd9Sstevel@tonic-gate 5187c478bd9Sstevel@tonic-gate if (dash_count > 1) { 5197c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 5207c478bd9Sstevel@tonic-gate gettext("%s may only appear once in the file" 5217c478bd9Sstevel@tonic-gate " list\n"), "\"-\""); 5227c478bd9Sstevel@tonic-gate exit(1); 5237c478bd9Sstevel@tonic-gate } 5247c478bd9Sstevel@tonic-gate 5257c478bd9Sstevel@tonic-gate if (fileptr - filelist == 0) { 5267c478bd9Sstevel@tonic-gate *fileptr++ = "-"; 5277c478bd9Sstevel@tonic-gate *fileptr = NULL; 5287c478bd9Sstevel@tonic-gate } 5297c478bd9Sstevel@tonic-gate 5307c478bd9Sstevel@tonic-gate if (fileptr - filelist > 1 && cflg && !do_decomp) { 5317c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 5327c478bd9Sstevel@tonic-gate gettext("compress: only one file may be compressed" 5337c478bd9Sstevel@tonic-gate " to stdout\n")); 5347c478bd9Sstevel@tonic-gate exit(1); 5357c478bd9Sstevel@tonic-gate } 5367c478bd9Sstevel@tonic-gate 5377c478bd9Sstevel@tonic-gate if (maxbits < INIT_BITS) 5387c478bd9Sstevel@tonic-gate maxbits = INIT_BITS; 5397c478bd9Sstevel@tonic-gate if (maxbits > BITS) 5407c478bd9Sstevel@tonic-gate maxbits = BITS; 5417c478bd9Sstevel@tonic-gate maxmaxcode = 1 << maxbits; 5427c478bd9Sstevel@tonic-gate 5437c478bd9Sstevel@tonic-gate /* Need to open something to close with freopen later */ 5447c478bd9Sstevel@tonic-gate 5457c478bd9Sstevel@tonic-gate if ((infile = fopen("/dev/null", "r")) == NULL) { 5467c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Error opening /dev/null for " 5477c478bd9Sstevel@tonic-gate "input\n")); 5487c478bd9Sstevel@tonic-gate exit(1); 5497c478bd9Sstevel@tonic-gate } 5507c478bd9Sstevel@tonic-gate 5517c478bd9Sstevel@tonic-gate if ((outfile = fopen("/dev/null", "w")) == NULL) { 5527c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Error opening /dev/null for " 5537c478bd9Sstevel@tonic-gate "output\n")); 5547c478bd9Sstevel@tonic-gate exit(1); 5557c478bd9Sstevel@tonic-gate } 5567c478bd9Sstevel@tonic-gate 5577c478bd9Sstevel@tonic-gate for (fileptr = filelist; *fileptr; fileptr++) { 5587c478bd9Sstevel@tonic-gate int jmpval = 0; 5597c478bd9Sstevel@tonic-gate didnt_shrink = 0; 5607c478bd9Sstevel@tonic-gate newline_needed = 0; 5617c478bd9Sstevel@tonic-gate 5627c478bd9Sstevel@tonic-gate if (do_decomp) { 5637c478bd9Sstevel@tonic-gate /* DECOMPRESSION */ 5647c478bd9Sstevel@tonic-gate 5657c478bd9Sstevel@tonic-gate if (strcmp(*fileptr, "-") == 0) { 5667c478bd9Sstevel@tonic-gate /* process stdin */ 5677c478bd9Sstevel@tonic-gate inp = stdin; 5687c478bd9Sstevel@tonic-gate outp = stdout; 5697c478bd9Sstevel@tonic-gate use_stdout = 1; 5707c478bd9Sstevel@tonic-gate *fileptr = "stdin"; /* for error messages */ 5717c478bd9Sstevel@tonic-gate } else { 5727c478bd9Sstevel@tonic-gate /* process the named file */ 5737c478bd9Sstevel@tonic-gate 5747c478bd9Sstevel@tonic-gate inp = infile; 5757c478bd9Sstevel@tonic-gate outp = outfile; 5767c478bd9Sstevel@tonic-gate use_stdout = 0; 5777c478bd9Sstevel@tonic-gate 5787c478bd9Sstevel@tonic-gate if (zcat_flg) { 5797c478bd9Sstevel@tonic-gate use_stdout = 1; 5807c478bd9Sstevel@tonic-gate outp = stdout; 5817c478bd9Sstevel@tonic-gate } 5827c478bd9Sstevel@tonic-gate 5837c478bd9Sstevel@tonic-gate /* Check for .Z suffix */ 5847c478bd9Sstevel@tonic-gate 5857c478bd9Sstevel@tonic-gate if (strcmp(*fileptr + 5867c478bd9Sstevel@tonic-gate strlen(*fileptr) - 2, ".Z") != 0) { 5877c478bd9Sstevel@tonic-gate /* No .Z: tack one on */ 5887c478bd9Sstevel@tonic-gate 5897c478bd9Sstevel@tonic-gate if (strlcpy(tempname, *fileptr, 5907c478bd9Sstevel@tonic-gate sizeof (tempname)) >= 5917c478bd9Sstevel@tonic-gate sizeof (tempname)) { 5927c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 5937c478bd9Sstevel@tonic-gate gettext("%s: filename " 5947c478bd9Sstevel@tonic-gate "too long\n"), 5957c478bd9Sstevel@tonic-gate *fileptr); 5967c478bd9Sstevel@tonic-gate perm_stat = 1; 5977c478bd9Sstevel@tonic-gate continue; 5987c478bd9Sstevel@tonic-gate } 5997c478bd9Sstevel@tonic-gate 6007c478bd9Sstevel@tonic-gate if (addDotZ(tempname, 6017c478bd9Sstevel@tonic-gate sizeof (tempname)) < 0) { 6027c478bd9Sstevel@tonic-gate perm_stat = 1; 6037c478bd9Sstevel@tonic-gate continue; 6047c478bd9Sstevel@tonic-gate } 6057c478bd9Sstevel@tonic-gate 6067c478bd9Sstevel@tonic-gate *fileptr = tempname; 6077c478bd9Sstevel@tonic-gate } 6087c478bd9Sstevel@tonic-gate 6097c478bd9Sstevel@tonic-gate /* Open input file */ 6107c478bd9Sstevel@tonic-gate 6117c478bd9Sstevel@tonic-gate if (stat(*fileptr, &statbuf) < 0) { 6127c478bd9Sstevel@tonic-gate perror(*fileptr); 6137c478bd9Sstevel@tonic-gate perm_stat = 1; 6147c478bd9Sstevel@tonic-gate continue; 6157c478bd9Sstevel@tonic-gate } 6167c478bd9Sstevel@tonic-gate 6177c478bd9Sstevel@tonic-gate if ((freopen(*fileptr, "r", inp)) == NULL) { 6187c478bd9Sstevel@tonic-gate perror(*fileptr); 6197c478bd9Sstevel@tonic-gate perm_stat = 1; 6207c478bd9Sstevel@tonic-gate continue; 6217c478bd9Sstevel@tonic-gate } 6227c478bd9Sstevel@tonic-gate } 6237c478bd9Sstevel@tonic-gate 6247c478bd9Sstevel@tonic-gate /* Check the magic number */ 6257c478bd9Sstevel@tonic-gate 6267c478bd9Sstevel@tonic-gate if (nomagic == 0) { 6277c478bd9Sstevel@tonic-gate if ((getc(inp) != 6287c478bd9Sstevel@tonic-gate (magic_header[0] & 0xFF)) || 6297c478bd9Sstevel@tonic-gate (getc(inp) != 6307c478bd9Sstevel@tonic-gate (magic_header[1] & 0xFF))) { 6317c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 6327c478bd9Sstevel@tonic-gate "%s: not in compressed " 6337c478bd9Sstevel@tonic-gate "format\n"), 6347c478bd9Sstevel@tonic-gate *fileptr); 6357c478bd9Sstevel@tonic-gate perm_stat = 1; 6367c478bd9Sstevel@tonic-gate continue; 6377c478bd9Sstevel@tonic-gate } 6387c478bd9Sstevel@tonic-gate 6397c478bd9Sstevel@tonic-gate /* set -b from file */ 6407c478bd9Sstevel@tonic-gate if ((maxbits = getc(inp)) == EOF && 6417c478bd9Sstevel@tonic-gate ferror(inp)) { 6427c478bd9Sstevel@tonic-gate perror(*fileptr); 6437c478bd9Sstevel@tonic-gate perm_stat = 1; 6447c478bd9Sstevel@tonic-gate continue; 6457c478bd9Sstevel@tonic-gate } 6467c478bd9Sstevel@tonic-gate 6477c478bd9Sstevel@tonic-gate block_compress = maxbits & BLOCK_MASK; 6487c478bd9Sstevel@tonic-gate maxbits &= BIT_MASK; 6497c478bd9Sstevel@tonic-gate maxmaxcode = 1 << maxbits; 6507c478bd9Sstevel@tonic-gate 6517c478bd9Sstevel@tonic-gate if (maxbits > BITS) { 6527c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 6537c478bd9Sstevel@tonic-gate gettext("%s: compressed " 6547c478bd9Sstevel@tonic-gate "with %d bits, " 6557c478bd9Sstevel@tonic-gate "can only handle" 6567c478bd9Sstevel@tonic-gate " %d bits\n"), 6577c478bd9Sstevel@tonic-gate *fileptr, maxbits, BITS); 6587c478bd9Sstevel@tonic-gate perm_stat = 1; 6597c478bd9Sstevel@tonic-gate continue; 6607c478bd9Sstevel@tonic-gate } 6617c478bd9Sstevel@tonic-gate } 6627c478bd9Sstevel@tonic-gate 6637c478bd9Sstevel@tonic-gate if (!use_stdout) { 6647c478bd9Sstevel@tonic-gate /* Generate output filename */ 6657c478bd9Sstevel@tonic-gate 6667c478bd9Sstevel@tonic-gate if (strlcpy(ofname, *fileptr, 6677c478bd9Sstevel@tonic-gate sizeof (ofname)) >= 6687c478bd9Sstevel@tonic-gate sizeof (ofname)) { 6697c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 6707c478bd9Sstevel@tonic-gate gettext("%s: filename " 6717c478bd9Sstevel@tonic-gate "too long\n"), 6727c478bd9Sstevel@tonic-gate *fileptr); 6737c478bd9Sstevel@tonic-gate perm_stat = 1; 6747c478bd9Sstevel@tonic-gate continue; 6757c478bd9Sstevel@tonic-gate } 6767c478bd9Sstevel@tonic-gate 6777c478bd9Sstevel@tonic-gate /* Strip off .Z */ 6787c478bd9Sstevel@tonic-gate 6797c478bd9Sstevel@tonic-gate ofname[strlen(*fileptr) - 2] = '\0'; 6807c478bd9Sstevel@tonic-gate } 6817c478bd9Sstevel@tonic-gate } else { 6827c478bd9Sstevel@tonic-gate /* COMPRESSION */ 6837c478bd9Sstevel@tonic-gate 6847c478bd9Sstevel@tonic-gate if (strcmp(*fileptr, "-") == 0) { 6857c478bd9Sstevel@tonic-gate /* process stdin */ 6867c478bd9Sstevel@tonic-gate inp = stdin; 6877c478bd9Sstevel@tonic-gate outp = stdout; 6887c478bd9Sstevel@tonic-gate use_stdout = 1; 6897c478bd9Sstevel@tonic-gate *fileptr = "stdin"; /* for error messages */ 6907c478bd9Sstevel@tonic-gate 6917c478bd9Sstevel@tonic-gate /* Use the largest possible hash table */ 6927c478bd9Sstevel@tonic-gate hsize = HSIZE; 6937c478bd9Sstevel@tonic-gate } else { 6947c478bd9Sstevel@tonic-gate /* process the named file */ 6957c478bd9Sstevel@tonic-gate 6967c478bd9Sstevel@tonic-gate inp = infile; 6977c478bd9Sstevel@tonic-gate outp = outfile; 6987c478bd9Sstevel@tonic-gate use_stdout = 0; 6997c478bd9Sstevel@tonic-gate 7007c478bd9Sstevel@tonic-gate if (zcat_flg) { 7017c478bd9Sstevel@tonic-gate use_stdout = 1; 7027c478bd9Sstevel@tonic-gate outp = stdout; 7037c478bd9Sstevel@tonic-gate } 7047c478bd9Sstevel@tonic-gate 7057c478bd9Sstevel@tonic-gate if (strcmp(*fileptr + 7067c478bd9Sstevel@tonic-gate strlen(*fileptr) - 2, ".Z") == 0) { 7077c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 7087c478bd9Sstevel@tonic-gate "%s: already has .Z " 7097c478bd9Sstevel@tonic-gate "suffix -- no change\n"), 7107c478bd9Sstevel@tonic-gate *fileptr); 7117c478bd9Sstevel@tonic-gate perm_stat = 1; 7127c478bd9Sstevel@tonic-gate continue; 7137c478bd9Sstevel@tonic-gate } 7147c478bd9Sstevel@tonic-gate /* Open input file */ 7157c478bd9Sstevel@tonic-gate 7167c478bd9Sstevel@tonic-gate if (stat(*fileptr, &statbuf) < 0) { 7177c478bd9Sstevel@tonic-gate perror(*fileptr); 7187c478bd9Sstevel@tonic-gate perm_stat = 1; 7197c478bd9Sstevel@tonic-gate continue; 7207c478bd9Sstevel@tonic-gate } 7217c478bd9Sstevel@tonic-gate 7227c478bd9Sstevel@tonic-gate if ((freopen(*fileptr, "r", inp)) == NULL) { 7237c478bd9Sstevel@tonic-gate perror(*fileptr); 7247c478bd9Sstevel@tonic-gate perm_stat = 1; 7257c478bd9Sstevel@tonic-gate continue; 7267c478bd9Sstevel@tonic-gate } 7277c478bd9Sstevel@tonic-gate 7287c478bd9Sstevel@tonic-gate fsize = (off_t)statbuf.st_size; 7297c478bd9Sstevel@tonic-gate 7307c478bd9Sstevel@tonic-gate /* 7317c478bd9Sstevel@tonic-gate * tune hash table size for small 7327c478bd9Sstevel@tonic-gate * files -- ad hoc, 7337c478bd9Sstevel@tonic-gate * but the sizes match earlier #defines, which 7347c478bd9Sstevel@tonic-gate * serve as upper bounds on the number of 7357c478bd9Sstevel@tonic-gate * output codes. 7367c478bd9Sstevel@tonic-gate */ 7377c478bd9Sstevel@tonic-gate hsize = HSIZE; 7387c478bd9Sstevel@tonic-gate if (fsize < (1 << 12)) 7397c478bd9Sstevel@tonic-gate hsize = min(5003, HSIZE); 7407c478bd9Sstevel@tonic-gate else if (fsize < (1 << 13)) 7417c478bd9Sstevel@tonic-gate hsize = min(9001, HSIZE); 7427c478bd9Sstevel@tonic-gate else if (fsize < (1 << 14)) 7437c478bd9Sstevel@tonic-gate hsize = min(18013, HSIZE); 7447c478bd9Sstevel@tonic-gate else if (fsize < (1 << 15)) 7457c478bd9Sstevel@tonic-gate hsize = min(35023, HSIZE); 7467c478bd9Sstevel@tonic-gate else if (fsize < 47000) 7477c478bd9Sstevel@tonic-gate hsize = min(50021, HSIZE); 7487c478bd9Sstevel@tonic-gate 7497c478bd9Sstevel@tonic-gate if (!use_stdout) { 7507c478bd9Sstevel@tonic-gate /* Generate output filename */ 7517c478bd9Sstevel@tonic-gate 7527c478bd9Sstevel@tonic-gate if (strlcpy(ofname, *fileptr, 7537c478bd9Sstevel@tonic-gate sizeof (ofname)) >= 7547c478bd9Sstevel@tonic-gate sizeof (ofname)) { 7557c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 7567c478bd9Sstevel@tonic-gate gettext("%s: filename " 7577c478bd9Sstevel@tonic-gate "too long\n"), 7587c478bd9Sstevel@tonic-gate *fileptr); 7597c478bd9Sstevel@tonic-gate perm_stat = 1; 7607c478bd9Sstevel@tonic-gate continue; 7617c478bd9Sstevel@tonic-gate } 7627c478bd9Sstevel@tonic-gate 7637c478bd9Sstevel@tonic-gate if (addDotZ(ofname, 7647c478bd9Sstevel@tonic-gate sizeof (ofname)) < 0) { 7657c478bd9Sstevel@tonic-gate perm_stat = 1; 7667c478bd9Sstevel@tonic-gate continue; 7677c478bd9Sstevel@tonic-gate } 7687c478bd9Sstevel@tonic-gate } 7697c478bd9Sstevel@tonic-gate } 7707c478bd9Sstevel@tonic-gate } /* if (do_decomp) */ 7717c478bd9Sstevel@tonic-gate 7727c478bd9Sstevel@tonic-gate /* Check for overwrite of existing file */ 7737c478bd9Sstevel@tonic-gate 7747c478bd9Sstevel@tonic-gate if (!overwrite && !use_stdout) { 7757c478bd9Sstevel@tonic-gate if (stat(ofname, &ostatbuf) == 0) { 7767c478bd9Sstevel@tonic-gate yesorno[ynsize] = (char)NULL; 7777c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 7787c478bd9Sstevel@tonic-gate "%s already exists;"), ofname); 7797c478bd9Sstevel@tonic-gate if (bgnd_flag == 0 && isatty(2)) { 7807c478bd9Sstevel@tonic-gate int cin; 7817c478bd9Sstevel@tonic-gate 7827c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 7837c478bd9Sstevel@tonic-gate " do you wish to overwr" 7847c478bd9Sstevel@tonic-gate "ite %s (%s or %s)? "), 7857c478bd9Sstevel@tonic-gate ofname, yesstr, nostr); 7867c478bd9Sstevel@tonic-gate (void) fflush(stderr); 7877c478bd9Sstevel@tonic-gate for (cin = 0; cin < LINE_MAX; 7887c478bd9Sstevel@tonic-gate cin++) 7897c478bd9Sstevel@tonic-gate line[cin] = 0; 7907c478bd9Sstevel@tonic-gate (void) read(2, line, LINE_MAX); 7917c478bd9Sstevel@tonic-gate (void) strncpy(yesorno, line, 7927c478bd9Sstevel@tonic-gate ynsize); 7937c478bd9Sstevel@tonic-gate 7947c478bd9Sstevel@tonic-gate if (!((strncmp(yesstr, yesorno, 7957c478bd9Sstevel@tonic-gate ynsize) == 0) || 7967c478bd9Sstevel@tonic-gate (yesorno[0] == 'y') || 7977c478bd9Sstevel@tonic-gate (yesorno[0] == 'Y'))) { 7987c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 7997c478bd9Sstevel@tonic-gate gettext( 8007c478bd9Sstevel@tonic-gate "\tnot overwri" 8017c478bd9Sstevel@tonic-gate "tten\n")); 8027c478bd9Sstevel@tonic-gate continue; 8037c478bd9Sstevel@tonic-gate } 8047c478bd9Sstevel@tonic-gate } else { 8057c478bd9Sstevel@tonic-gate /* 8067c478bd9Sstevel@tonic-gate * XPG4: Assertion 1009 8077c478bd9Sstevel@tonic-gate * Standard input is not 8087c478bd9Sstevel@tonic-gate * terminal, and no '-f', 8097c478bd9Sstevel@tonic-gate * and file exists. 8107c478bd9Sstevel@tonic-gate */ 8117c478bd9Sstevel@tonic-gate 8127c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 8137c478bd9Sstevel@tonic-gate "%s: File exists, -f not" 8147c478bd9Sstevel@tonic-gate " specified, and ru" 8157c478bd9Sstevel@tonic-gate "nning in the backgro" 8167c478bd9Sstevel@tonic-gate "und.\n"), *fileptr); 8177c478bd9Sstevel@tonic-gate perm_stat = 1; 8187c478bd9Sstevel@tonic-gate continue; 8197c478bd9Sstevel@tonic-gate } 8207c478bd9Sstevel@tonic-gate } 8217c478bd9Sstevel@tonic-gate } 8227c478bd9Sstevel@tonic-gate if (!use_stdout) { 8237c478bd9Sstevel@tonic-gate if (pathconf(ofname, _PC_XATTR_EXISTS) == 1) { 8247c478bd9Sstevel@tonic-gate (void) unlink(ofname); 8257c478bd9Sstevel@tonic-gate } 8267c478bd9Sstevel@tonic-gate /* Open output file */ 8277c478bd9Sstevel@tonic-gate if (freopen(ofname, "w", outp) == NULL) { 8287c478bd9Sstevel@tonic-gate perror(ofname); 8297c478bd9Sstevel@tonic-gate perm_stat = 1; 8307c478bd9Sstevel@tonic-gate continue; 8317c478bd9Sstevel@tonic-gate } 8327c478bd9Sstevel@tonic-gate precious = 0; 8337c478bd9Sstevel@tonic-gate if (!quiet) { 8347c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: ", 8357c478bd9Sstevel@tonic-gate *fileptr); 8367c478bd9Sstevel@tonic-gate newline_needed = 1; 8377c478bd9Sstevel@tonic-gate } 8387c478bd9Sstevel@tonic-gate } else if (!quiet && !do_decomp) { 8397c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: ", 8407c478bd9Sstevel@tonic-gate *fileptr); 8417c478bd9Sstevel@tonic-gate newline_needed = 1; 8427c478bd9Sstevel@tonic-gate } 8437c478bd9Sstevel@tonic-gate 8447c478bd9Sstevel@tonic-gate /* Actually do the compression/decompression */ 8457c478bd9Sstevel@tonic-gate 8467c478bd9Sstevel@tonic-gate if ((jmpval = setjmp(env)) == 0) { 8477c478bd9Sstevel@tonic-gate /* We'll see how things go */ 8487c478bd9Sstevel@tonic-gate #ifndef DEBUG 8497c478bd9Sstevel@tonic-gate if (do_decomp == 0) { 8507c478bd9Sstevel@tonic-gate compress(); 8517c478bd9Sstevel@tonic-gate } else { 8527c478bd9Sstevel@tonic-gate decompress(); 8537c478bd9Sstevel@tonic-gate } 8547c478bd9Sstevel@tonic-gate #else 8557c478bd9Sstevel@tonic-gate if (do_decomp == 0) { 8567c478bd9Sstevel@tonic-gate compress(); 8577c478bd9Sstevel@tonic-gate } else if (debug == 0) { 8587c478bd9Sstevel@tonic-gate decompress(); 8597c478bd9Sstevel@tonic-gate } else { 8607c478bd9Sstevel@tonic-gate printcodes(); 8617c478bd9Sstevel@tonic-gate } 8627c478bd9Sstevel@tonic-gate 8637c478bd9Sstevel@tonic-gate if (verbose) { 8647c478bd9Sstevel@tonic-gate dump_tab(); 8657c478bd9Sstevel@tonic-gate } 8667c478bd9Sstevel@tonic-gate #endif 8677c478bd9Sstevel@tonic-gate } else { 8687c478bd9Sstevel@tonic-gate /* 8697c478bd9Sstevel@tonic-gate * Things went badly - clean up and go on. 8707c478bd9Sstevel@tonic-gate * jmpval's values break down as follows: 8717c478bd9Sstevel@tonic-gate * 1 == message determined by ferror() values. 8727c478bd9Sstevel@tonic-gate * 2 == input problem message needed. 8737c478bd9Sstevel@tonic-gate * 3 == output problem message needed. 8747c478bd9Sstevel@tonic-gate */ 8757c478bd9Sstevel@tonic-gate 8767c478bd9Sstevel@tonic-gate if (ferror(inp) || jmpval == 2) { 8777c478bd9Sstevel@tonic-gate if (do_decomp) { 8787c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 8797c478bd9Sstevel@tonic-gate "uncompress: %s: corrupt" 8807c478bd9Sstevel@tonic-gate " input\n"), *fileptr); 8817c478bd9Sstevel@tonic-gate } else { 8827c478bd9Sstevel@tonic-gate perror(*fileptr); 8837c478bd9Sstevel@tonic-gate } 8847c478bd9Sstevel@tonic-gate } 8857c478bd9Sstevel@tonic-gate 8867c478bd9Sstevel@tonic-gate if (ferror(outp) || jmpval == 3) { 8877c478bd9Sstevel@tonic-gate /* handle output errors */ 8887c478bd9Sstevel@tonic-gate 8897c478bd9Sstevel@tonic-gate if (use_stdout) { 8907c478bd9Sstevel@tonic-gate perror(""); 8917c478bd9Sstevel@tonic-gate } else { 8927c478bd9Sstevel@tonic-gate perror(ofname); 8937c478bd9Sstevel@tonic-gate } 8947c478bd9Sstevel@tonic-gate } 8957c478bd9Sstevel@tonic-gate 8967c478bd9Sstevel@tonic-gate if (ofname[0] != '\0') { 8977c478bd9Sstevel@tonic-gate if (unlink(ofname) < 0) { 8987c478bd9Sstevel@tonic-gate perror(ofname); 8997c478bd9Sstevel@tonic-gate } 9007c478bd9Sstevel@tonic-gate 9017c478bd9Sstevel@tonic-gate ofname[0] = '\0'; 9027c478bd9Sstevel@tonic-gate } 9037c478bd9Sstevel@tonic-gate 9047c478bd9Sstevel@tonic-gate perm_stat = 1; 9057c478bd9Sstevel@tonic-gate continue; 9067c478bd9Sstevel@tonic-gate } 9077c478bd9Sstevel@tonic-gate 9087c478bd9Sstevel@tonic-gate /* Things went well */ 9097c478bd9Sstevel@tonic-gate 9107c478bd9Sstevel@tonic-gate if (!use_stdout) { 9117c478bd9Sstevel@tonic-gate /* Copy stats */ 9127c478bd9Sstevel@tonic-gate copystat(*fileptr, &statbuf, ofname); 9137c478bd9Sstevel@tonic-gate precious = 1; 9147c478bd9Sstevel@tonic-gate if (newline_needed) { 9157c478bd9Sstevel@tonic-gate (void) putc('\n', stderr); 9167c478bd9Sstevel@tonic-gate } 9177c478bd9Sstevel@tonic-gate /* 9187c478bd9Sstevel@tonic-gate * Print the info. for unchanged file 9197c478bd9Sstevel@tonic-gate * when no -v 9207c478bd9Sstevel@tonic-gate */ 9217c478bd9Sstevel@tonic-gate 9227c478bd9Sstevel@tonic-gate if (didnt_shrink) { 9237c478bd9Sstevel@tonic-gate if (!force && perm_stat == 0) { 9247c478bd9Sstevel@tonic-gate if (quiet) { 9257c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 9267c478bd9Sstevel@tonic-gate "%s: -- file " 9277c478bd9Sstevel@tonic-gate "unchanged\n"), 9287c478bd9Sstevel@tonic-gate *fileptr); 9297c478bd9Sstevel@tonic-gate } 9307c478bd9Sstevel@tonic-gate 9317c478bd9Sstevel@tonic-gate perm_stat = 2; 9327c478bd9Sstevel@tonic-gate } 9337c478bd9Sstevel@tonic-gate } 9347c478bd9Sstevel@tonic-gate } else { 9357c478bd9Sstevel@tonic-gate if (didnt_shrink && !force && perm_stat == 0) { 9367c478bd9Sstevel@tonic-gate perm_stat = 2; 9377c478bd9Sstevel@tonic-gate } 9387c478bd9Sstevel@tonic-gate 9397c478bd9Sstevel@tonic-gate if (newline_needed) { 9407c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\n"); 9417c478bd9Sstevel@tonic-gate } 9427c478bd9Sstevel@tonic-gate } 9437c478bd9Sstevel@tonic-gate } /* for */ 9447c478bd9Sstevel@tonic-gate 9457c478bd9Sstevel@tonic-gate return (perm_stat); 9467c478bd9Sstevel@tonic-gate } 9477c478bd9Sstevel@tonic-gate 9487c478bd9Sstevel@tonic-gate static void 9497c478bd9Sstevel@tonic-gate cinterr(int hshift) 9507c478bd9Sstevel@tonic-gate { 9517c478bd9Sstevel@tonic-gate /* we have exceeded the hash table */ 9527c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 9537c478bd9Sstevel@tonic-gate "internal error: hashtable exceeded - hsize = %ld\n", hsize); 9547c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "hshift = %d, %d\n", hshift, (1 << hshift) -1); 9557c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "maxbits = %d\n", maxbits); 9567c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "n_bits = %d\n", n_bits); 9577c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "maxcode = %ld\n", maxcode); 9587c478bd9Sstevel@tonic-gate longjmp(env, 1); 9597c478bd9Sstevel@tonic-gate } 9607c478bd9Sstevel@tonic-gate 9617c478bd9Sstevel@tonic-gate static code_int 9627c478bd9Sstevel@tonic-gate adjusti(code_int i, code_int hsize_reg) 9637c478bd9Sstevel@tonic-gate { 9647c478bd9Sstevel@tonic-gate while (i < 0) { 9657c478bd9Sstevel@tonic-gate i += hsize_reg; 9667c478bd9Sstevel@tonic-gate } 9677c478bd9Sstevel@tonic-gate 9687c478bd9Sstevel@tonic-gate while (i >= hsize_reg) { 9697c478bd9Sstevel@tonic-gate i -= hsize_reg; 9707c478bd9Sstevel@tonic-gate } 9717c478bd9Sstevel@tonic-gate return (i); 9727c478bd9Sstevel@tonic-gate } 9737c478bd9Sstevel@tonic-gate 9747c478bd9Sstevel@tonic-gate /* 9757c478bd9Sstevel@tonic-gate * compress inp to outp 9767c478bd9Sstevel@tonic-gate * 9777c478bd9Sstevel@tonic-gate * Algorithm: use open addressing double hashing(no chaining) on the 9787c478bd9Sstevel@tonic-gate * prefix code / next character combination. We do a variant of Knuth's 9797c478bd9Sstevel@tonic-gate * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime 9807c478bd9Sstevel@tonic-gate * secondary probe. Here, the modular division first probe is gives way 9817c478bd9Sstevel@tonic-gate * to a faster exclusive-or manipulation. Also do block compression with 9827c478bd9Sstevel@tonic-gate * an adaptive reset, whereby the code table is cleared when the compression 9837c478bd9Sstevel@tonic-gate * ratio decreases, but after the table fills. The variable-length output 9847c478bd9Sstevel@tonic-gate * codes are re-sized at this point, and a special CLEAR code is generated 9857c478bd9Sstevel@tonic-gate * for the decompressor. Late addition: construct the table according to 9867c478bd9Sstevel@tonic-gate * file size for noticeable speed improvement on small files. Please direct 9877c478bd9Sstevel@tonic-gate * questions about this implementation to ames!jaw. 9887c478bd9Sstevel@tonic-gate */ 9897c478bd9Sstevel@tonic-gate 9907c478bd9Sstevel@tonic-gate static void 9917c478bd9Sstevel@tonic-gate compress() 9927c478bd9Sstevel@tonic-gate { 9937c478bd9Sstevel@tonic-gate long fcode; 9947c478bd9Sstevel@tonic-gate code_int i = 0; 9957c478bd9Sstevel@tonic-gate int c; 9967c478bd9Sstevel@tonic-gate code_int ent; 9977c478bd9Sstevel@tonic-gate int disp; 9987c478bd9Sstevel@tonic-gate code_int hsize_reg; 9997c478bd9Sstevel@tonic-gate int hshift; 10007c478bd9Sstevel@tonic-gate int probecnt; 10017c478bd9Sstevel@tonic-gate count_long in_count; 10027c478bd9Sstevel@tonic-gate uint32_t inchi, inclo; 10037c478bd9Sstevel@tonic-gate int maxbits_reg; 10047c478bd9Sstevel@tonic-gate FILE *fin = inp; 10057c478bd9Sstevel@tonic-gate #ifdef DEBUG 10067c478bd9Sstevel@tonic-gate count_long out_count = 0; 10077c478bd9Sstevel@tonic-gate #endif 10087c478bd9Sstevel@tonic-gate 10097c478bd9Sstevel@tonic-gate if (nomagic == 0) { 10107c478bd9Sstevel@tonic-gate if ((putc(magic_header[0], outp) == EOF || 10117c478bd9Sstevel@tonic-gate putc(magic_header[1], outp) == EOF || 10127c478bd9Sstevel@tonic-gate putc((char)(maxbits | block_compress), 10137c478bd9Sstevel@tonic-gate outp) == EOF) && 10147c478bd9Sstevel@tonic-gate ferror(outp)) { 10157c478bd9Sstevel@tonic-gate ioerror(); 10167c478bd9Sstevel@tonic-gate } 10177c478bd9Sstevel@tonic-gate } 10187c478bd9Sstevel@tonic-gate 10197c478bd9Sstevel@tonic-gate offset = 0; 10207c478bd9Sstevel@tonic-gate bytes_out = 3; /* includes 3-byte header mojo */ 10217c478bd9Sstevel@tonic-gate clear_flg = 0; 10227c478bd9Sstevel@tonic-gate ratio = 0; 10237c478bd9Sstevel@tonic-gate in_count = 1; 10247c478bd9Sstevel@tonic-gate inchi = 0; 10257c478bd9Sstevel@tonic-gate inclo = 1; 10267c478bd9Sstevel@tonic-gate checkpoint = CHECK_GAP; 10277c478bd9Sstevel@tonic-gate maxcode = MAXCODE(n_bits = INIT_BITS); 10287c478bd9Sstevel@tonic-gate free_ent = ((block_compress) ? FIRST : 256); 10297c478bd9Sstevel@tonic-gate 10307c478bd9Sstevel@tonic-gate if ((ent = getc(fin)) == EOF && ferror(fin)) { 10317c478bd9Sstevel@tonic-gate ioerror(); 10327c478bd9Sstevel@tonic-gate } 10337c478bd9Sstevel@tonic-gate 10347c478bd9Sstevel@tonic-gate hshift = 0; 10357c478bd9Sstevel@tonic-gate 10367c478bd9Sstevel@tonic-gate for (fcode = (long)hsize; fcode < 65536L; fcode *= 2L) 10377c478bd9Sstevel@tonic-gate hshift++; 10387c478bd9Sstevel@tonic-gate 10397c478bd9Sstevel@tonic-gate hshift = 8 - hshift; /* set hash code range bound */ 10407c478bd9Sstevel@tonic-gate 10417c478bd9Sstevel@tonic-gate hsize_reg = hsize; 10427c478bd9Sstevel@tonic-gate maxbits_reg = maxbits; 10437c478bd9Sstevel@tonic-gate 10447c478bd9Sstevel@tonic-gate cl_hash((count_int) hsize_reg); /* clear hash table */ 10457c478bd9Sstevel@tonic-gate 10467c478bd9Sstevel@tonic-gate while ((c = getc(fin)) != EOF) { 10477c478bd9Sstevel@tonic-gate if (++inclo == 0) 10487c478bd9Sstevel@tonic-gate inchi++; 10497c478bd9Sstevel@tonic-gate fcode = (long)(((long)c << maxbits_reg) + ent); 10507c478bd9Sstevel@tonic-gate i = ((c << hshift) ^ ent); /* xor hashing */ 10517c478bd9Sstevel@tonic-gate 10527c478bd9Sstevel@tonic-gate if ((unsigned int)i >= hsize_reg) 10537c478bd9Sstevel@tonic-gate i = adjusti(i, hsize_reg); 10547c478bd9Sstevel@tonic-gate 10557c478bd9Sstevel@tonic-gate if (htabof(i) == fcode) { 10567c478bd9Sstevel@tonic-gate ent = codetabof(i); 10577c478bd9Sstevel@tonic-gate continue; 10587c478bd9Sstevel@tonic-gate } else if ((long)htabof(i) < 0) { 10597c478bd9Sstevel@tonic-gate /* empty slot */ 10607c478bd9Sstevel@tonic-gate goto nomatch; 10617c478bd9Sstevel@tonic-gate } 10627c478bd9Sstevel@tonic-gate 10637c478bd9Sstevel@tonic-gate /* secondary hash (after G. Knott) */ 10647c478bd9Sstevel@tonic-gate disp = hsize_reg - i; 10657c478bd9Sstevel@tonic-gate 10667c478bd9Sstevel@tonic-gate if (i == 0) { 10677c478bd9Sstevel@tonic-gate disp = 1; 10687c478bd9Sstevel@tonic-gate } 10697c478bd9Sstevel@tonic-gate 10707c478bd9Sstevel@tonic-gate probecnt = 0; 10717c478bd9Sstevel@tonic-gate probe: 10727c478bd9Sstevel@tonic-gate if (++probecnt > hsize_reg) 10737c478bd9Sstevel@tonic-gate cinterr(hshift); 10747c478bd9Sstevel@tonic-gate 10757c478bd9Sstevel@tonic-gate if ((i -= disp) < 0) { 10767c478bd9Sstevel@tonic-gate while (i < 0) 10777c478bd9Sstevel@tonic-gate i += hsize_reg; 10787c478bd9Sstevel@tonic-gate } 10797c478bd9Sstevel@tonic-gate 10807c478bd9Sstevel@tonic-gate if (htabof(i) == fcode) { 10817c478bd9Sstevel@tonic-gate ent = codetabof(i); 10827c478bd9Sstevel@tonic-gate continue; 10837c478bd9Sstevel@tonic-gate } 10847c478bd9Sstevel@tonic-gate 10857c478bd9Sstevel@tonic-gate if ((long)htabof(i) > 0) { 10867c478bd9Sstevel@tonic-gate goto probe; 10877c478bd9Sstevel@tonic-gate } 10887c478bd9Sstevel@tonic-gate nomatch: 10897c478bd9Sstevel@tonic-gate output((code_int) ent); 10907c478bd9Sstevel@tonic-gate #ifdef DEBUG 10917c478bd9Sstevel@tonic-gate out_count++; 10927c478bd9Sstevel@tonic-gate #endif 10937c478bd9Sstevel@tonic-gate ent = c; 10947c478bd9Sstevel@tonic-gate if (free_ent < maxmaxcode) { 10957c478bd9Sstevel@tonic-gate codetabof(i) = free_ent++; 10967c478bd9Sstevel@tonic-gate /* code -> hashtable */ 10977c478bd9Sstevel@tonic-gate htabof(i) = fcode; 10987c478bd9Sstevel@tonic-gate } else { 10997c478bd9Sstevel@tonic-gate in_count = ((long long)inchi<<32|inclo); 11007c478bd9Sstevel@tonic-gate if ((count_long)in_count >= 11017c478bd9Sstevel@tonic-gate (count_long)checkpoint && block_compress) { 11027c478bd9Sstevel@tonic-gate cl_block(in_count); 11037c478bd9Sstevel@tonic-gate } 11047c478bd9Sstevel@tonic-gate } 11057c478bd9Sstevel@tonic-gate } 11067c478bd9Sstevel@tonic-gate 11077c478bd9Sstevel@tonic-gate in_count = ((long long)inchi<<32|inclo); 11087c478bd9Sstevel@tonic-gate 11097c478bd9Sstevel@tonic-gate if (ferror(fin) != 0) { 11107c478bd9Sstevel@tonic-gate ioerror(); 11117c478bd9Sstevel@tonic-gate } 11127c478bd9Sstevel@tonic-gate 11137c478bd9Sstevel@tonic-gate /* 11147c478bd9Sstevel@tonic-gate * Put out the final code. 11157c478bd9Sstevel@tonic-gate */ 11167c478bd9Sstevel@tonic-gate output((code_int)ent); 11177c478bd9Sstevel@tonic-gate #ifdef DEBUG 11187c478bd9Sstevel@tonic-gate out_count++; 11197c478bd9Sstevel@tonic-gate #endif 11207c478bd9Sstevel@tonic-gate 11217c478bd9Sstevel@tonic-gate output((code_int)-1); 11227c478bd9Sstevel@tonic-gate 11237c478bd9Sstevel@tonic-gate /* 11247c478bd9Sstevel@tonic-gate * Print out stats on stderr 11257c478bd9Sstevel@tonic-gate */ 11267c478bd9Sstevel@tonic-gate if (!quiet) { 11277c478bd9Sstevel@tonic-gate #ifdef DEBUG 11287c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 11297c478bd9Sstevel@tonic-gate "%lld chars in, %lld codes (%lld bytes) out, " 11307c478bd9Sstevel@tonic-gate "compression factor: ", 11317c478bd9Sstevel@tonic-gate (count_long)in_count, (count_long)out_count, 11327c478bd9Sstevel@tonic-gate (count_long) bytes_out); 11337c478bd9Sstevel@tonic-gate prratio(stderr, (count_long)in_count, 11347c478bd9Sstevel@tonic-gate (count_long)bytes_out); 11357c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\n"); 11367c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\tCompression as in compact: "); 11377c478bd9Sstevel@tonic-gate prratio(stderr, 11387c478bd9Sstevel@tonic-gate (count_long)in_count-(count_long)bytes_out, 11397c478bd9Sstevel@tonic-gate (count_long)in_count); 11407c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\n"); 11417c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 11427c478bd9Sstevel@tonic-gate "\tLargest code (of last block) was %d" 11437c478bd9Sstevel@tonic-gate " (%d bits)\n", 11447c478bd9Sstevel@tonic-gate free_ent - 1, n_bits); 11457c478bd9Sstevel@tonic-gate #else /* !DEBUG */ 11467c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Compression: ")); 11477c478bd9Sstevel@tonic-gate prratio(stderr, 11487c478bd9Sstevel@tonic-gate (count_long)in_count-(count_long)bytes_out, 11497c478bd9Sstevel@tonic-gate (count_long)in_count); 11507c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 11517c478bd9Sstevel@tonic-gate } 11527c478bd9Sstevel@tonic-gate /* report if no savings */ 11537c478bd9Sstevel@tonic-gate if ((count_long)bytes_out > (count_long)in_count) { 11547c478bd9Sstevel@tonic-gate didnt_shrink = 1; 11557c478bd9Sstevel@tonic-gate } 11567c478bd9Sstevel@tonic-gate } 11577c478bd9Sstevel@tonic-gate 11587c478bd9Sstevel@tonic-gate /* 11597c478bd9Sstevel@tonic-gate * ************************************************************** 11607c478bd9Sstevel@tonic-gate * TAG(output) 11617c478bd9Sstevel@tonic-gate * 11627c478bd9Sstevel@tonic-gate * Output the given code. 11637c478bd9Sstevel@tonic-gate * Inputs: 11647c478bd9Sstevel@tonic-gate * code: A n_bits-bit integer. If == -1, then EOF. This assumes 11657c478bd9Sstevel@tonic-gate * that n_bits = < (long)wordsize - 1. 11667c478bd9Sstevel@tonic-gate * Outputs: 11677c478bd9Sstevel@tonic-gate * Outputs code to the file. 11687c478bd9Sstevel@tonic-gate * Assumptions: 11697c478bd9Sstevel@tonic-gate * Chars are 8 bits long. 11707c478bd9Sstevel@tonic-gate * Algorithm: 11717c478bd9Sstevel@tonic-gate * Maintain a BITS character long buffer(so that 8 codes will 11727c478bd9Sstevel@tonic-gate * fit in it exactly). Use the VAX insv instruction to insert each 11737c478bd9Sstevel@tonic-gate * code in turn. When the buffer fills up empty it and start over. 11747c478bd9Sstevel@tonic-gate */ 11757c478bd9Sstevel@tonic-gate 11767c478bd9Sstevel@tonic-gate static void 11777c478bd9Sstevel@tonic-gate output(code_int code) 11787c478bd9Sstevel@tonic-gate { 11797c478bd9Sstevel@tonic-gate #ifdef DEBUG 11807c478bd9Sstevel@tonic-gate static int col = 0; 11817c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 11827c478bd9Sstevel@tonic-gate 11837c478bd9Sstevel@tonic-gate int r_off = offset, bits = n_bits; 11847c478bd9Sstevel@tonic-gate char *bp = buf; 11857c478bd9Sstevel@tonic-gate 11867c478bd9Sstevel@tonic-gate #ifdef DEBUG 11877c478bd9Sstevel@tonic-gate if (verbose) 11887c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%5d%c", code, 11897c478bd9Sstevel@tonic-gate (col += 6) >= 74 ? (col = 0, '\n') : ' '); 11907c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 11917c478bd9Sstevel@tonic-gate if (code >= 0) { 11927c478bd9Sstevel@tonic-gate /* 11937c478bd9Sstevel@tonic-gate * byte/bit numbering on the VAX is simulated 11947c478bd9Sstevel@tonic-gate * by the following code 11957c478bd9Sstevel@tonic-gate */ 11967c478bd9Sstevel@tonic-gate /* 11977c478bd9Sstevel@tonic-gate * Get to the first byte. 11987c478bd9Sstevel@tonic-gate */ 11997c478bd9Sstevel@tonic-gate bp += (r_off >> 3); 12007c478bd9Sstevel@tonic-gate r_off &= 7; 12017c478bd9Sstevel@tonic-gate /* 12027c478bd9Sstevel@tonic-gate * Since code is always >= 8 bits, only need to mask the first 12037c478bd9Sstevel@tonic-gate * hunk on the left. 12047c478bd9Sstevel@tonic-gate */ 12057c478bd9Sstevel@tonic-gate *bp = (*bp & rmask[r_off]) | (code << r_off) & lmask[r_off]; 12067c478bd9Sstevel@tonic-gate bp++; 12077c478bd9Sstevel@tonic-gate bits -= (8 - r_off); 12087c478bd9Sstevel@tonic-gate code >>= 8 - r_off; 12097c478bd9Sstevel@tonic-gate /* 12107c478bd9Sstevel@tonic-gate * Get any 8 bit parts in the middle (<=1 for up to 16 12117c478bd9Sstevel@tonic-gate * bits). 12127c478bd9Sstevel@tonic-gate */ 12137c478bd9Sstevel@tonic-gate if (bits >= 8) { 12147c478bd9Sstevel@tonic-gate *bp++ = code; 12157c478bd9Sstevel@tonic-gate code >>= 8; 12167c478bd9Sstevel@tonic-gate bits -= 8; 12177c478bd9Sstevel@tonic-gate } 12187c478bd9Sstevel@tonic-gate /* Last bits. */ 12197c478bd9Sstevel@tonic-gate if (bits) 12207c478bd9Sstevel@tonic-gate *bp = code; 12217c478bd9Sstevel@tonic-gate offset += n_bits; 12227c478bd9Sstevel@tonic-gate if (offset == (n_bits << 3)) { 12237c478bd9Sstevel@tonic-gate bp = buf; 12247c478bd9Sstevel@tonic-gate bits = n_bits; 12257c478bd9Sstevel@tonic-gate bytes_out += bits; 12267c478bd9Sstevel@tonic-gate do { 12277c478bd9Sstevel@tonic-gate if (putc(*bp, outp) == EOF && 12287c478bd9Sstevel@tonic-gate ferror(outp)) { 12297c478bd9Sstevel@tonic-gate ioerror(); 12307c478bd9Sstevel@tonic-gate } 12317c478bd9Sstevel@tonic-gate bp++; 12327c478bd9Sstevel@tonic-gate } while (--bits); 12337c478bd9Sstevel@tonic-gate offset = 0; 12347c478bd9Sstevel@tonic-gate } 12357c478bd9Sstevel@tonic-gate 12367c478bd9Sstevel@tonic-gate /* 12377c478bd9Sstevel@tonic-gate * If the next entry is going to be too big for the code size, 12387c478bd9Sstevel@tonic-gate * then increase it, if possible. 12397c478bd9Sstevel@tonic-gate */ 12407c478bd9Sstevel@tonic-gate if (free_ent > maxcode || (clear_flg > 0)) { 12417c478bd9Sstevel@tonic-gate /* 12427c478bd9Sstevel@tonic-gate * Write the whole buffer, because the input 12437c478bd9Sstevel@tonic-gate * side won't discover the size increase until 12447c478bd9Sstevel@tonic-gate * after it has read it. 12457c478bd9Sstevel@tonic-gate */ 12467c478bd9Sstevel@tonic-gate if (offset > 0) { 12477c478bd9Sstevel@tonic-gate if (fwrite(buf, 1, n_bits, outp) != n_bits) { 12487c478bd9Sstevel@tonic-gate longjmp(env, 3); 12497c478bd9Sstevel@tonic-gate } 12507c478bd9Sstevel@tonic-gate bytes_out += n_bits; 12517c478bd9Sstevel@tonic-gate } 12527c478bd9Sstevel@tonic-gate offset = 0; 12537c478bd9Sstevel@tonic-gate 12547c478bd9Sstevel@tonic-gate if (clear_flg) { 12557c478bd9Sstevel@tonic-gate maxcode = MAXCODE(n_bits = INIT_BITS); 12567c478bd9Sstevel@tonic-gate clear_flg = 0; 12577c478bd9Sstevel@tonic-gate } else { 12587c478bd9Sstevel@tonic-gate n_bits++; 12597c478bd9Sstevel@tonic-gate if (n_bits == maxbits) 12607c478bd9Sstevel@tonic-gate maxcode = maxmaxcode; 12617c478bd9Sstevel@tonic-gate else 12627c478bd9Sstevel@tonic-gate maxcode = MAXCODE(n_bits); 12637c478bd9Sstevel@tonic-gate } 12647c478bd9Sstevel@tonic-gate #ifdef DEBUG 12657c478bd9Sstevel@tonic-gate if (debug) { 12667c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 12677c478bd9Sstevel@tonic-gate "\nChange to %d bits\n", n_bits); 12687c478bd9Sstevel@tonic-gate col = 0; 12697c478bd9Sstevel@tonic-gate } 12707c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 12717c478bd9Sstevel@tonic-gate } 12727c478bd9Sstevel@tonic-gate } else { 12737c478bd9Sstevel@tonic-gate /* 12747c478bd9Sstevel@tonic-gate * At EOF, write the rest of the buffer. 12757c478bd9Sstevel@tonic-gate */ 12767c478bd9Sstevel@tonic-gate if (offset > 0) { 12777c478bd9Sstevel@tonic-gate if (fwrite(buf, 1, (offset + 7) / 8, outp) == 0 && 12787c478bd9Sstevel@tonic-gate ferror(outp)) { 12797c478bd9Sstevel@tonic-gate ioerror(); 12807c478bd9Sstevel@tonic-gate } 12817c478bd9Sstevel@tonic-gate bytes_out += (offset + 7) / 8; 12827c478bd9Sstevel@tonic-gate } 12837c478bd9Sstevel@tonic-gate offset = 0; 12847c478bd9Sstevel@tonic-gate (void) fflush(outp); 12857c478bd9Sstevel@tonic-gate #ifdef DEBUG 12867c478bd9Sstevel@tonic-gate if (verbose) 12877c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\n"); 12887c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 12897c478bd9Sstevel@tonic-gate if (ferror(outp)) 12907c478bd9Sstevel@tonic-gate ioerror(); 12917c478bd9Sstevel@tonic-gate } 12927c478bd9Sstevel@tonic-gate } 12937c478bd9Sstevel@tonic-gate 12947c478bd9Sstevel@tonic-gate /* 12957c478bd9Sstevel@tonic-gate * Decompress inp to outp. This routine adapts to the codes in the 12967c478bd9Sstevel@tonic-gate * file building the "string" table on-the-fly; requiring no table to 12977c478bd9Sstevel@tonic-gate * be stored in the compressed file. The tables used herein are shared 12987c478bd9Sstevel@tonic-gate * with those of the compress() routine. See the definitions above. 12997c478bd9Sstevel@tonic-gate */ 13007c478bd9Sstevel@tonic-gate 13017c478bd9Sstevel@tonic-gate static void 13027c478bd9Sstevel@tonic-gate decompress() 13037c478bd9Sstevel@tonic-gate { 13047c478bd9Sstevel@tonic-gate char_type *stackp, *stack_lim; 13057c478bd9Sstevel@tonic-gate int finchar; 13067c478bd9Sstevel@tonic-gate code_int code, oldcode, incode; 13077c478bd9Sstevel@tonic-gate FILE *fout = outp; 13087c478bd9Sstevel@tonic-gate 13097c478bd9Sstevel@tonic-gate /* 13107c478bd9Sstevel@tonic-gate * As above, initialize the first 256 entries in the table. 13117c478bd9Sstevel@tonic-gate */ 13127c478bd9Sstevel@tonic-gate maxcode = MAXCODE(n_bits = INIT_BITS); 13137c478bd9Sstevel@tonic-gate for (code = 255; code >= 0; code--) { 13147c478bd9Sstevel@tonic-gate tab_prefixof(code) = 0; 13157c478bd9Sstevel@tonic-gate tab_suffixof(code) = (char_type)code; 13167c478bd9Sstevel@tonic-gate } 13177c478bd9Sstevel@tonic-gate free_ent = ((block_compress) ? FIRST : 256); 13187c478bd9Sstevel@tonic-gate 13197c478bd9Sstevel@tonic-gate finchar = oldcode = getcode(); 13207c478bd9Sstevel@tonic-gate if (oldcode == -1) /* EOF already? */ 13217c478bd9Sstevel@tonic-gate return; /* Get out of here */ 13227c478bd9Sstevel@tonic-gate /* first code must be 8 bits = char */ 13237c478bd9Sstevel@tonic-gate if (putc((char)finchar, outp) == EOF && ferror(outp)) { 13247c478bd9Sstevel@tonic-gate /* Crash if can't write */ 13257c478bd9Sstevel@tonic-gate ioerror(); 13267c478bd9Sstevel@tonic-gate } 13277c478bd9Sstevel@tonic-gate stackp = de_stack; 13287c478bd9Sstevel@tonic-gate stack_lim = stack_max; 13297c478bd9Sstevel@tonic-gate 13307c478bd9Sstevel@tonic-gate while ((code = getcode()) > -1) { 13317c478bd9Sstevel@tonic-gate 13327c478bd9Sstevel@tonic-gate if ((code == CLEAR) && block_compress) { 13337c478bd9Sstevel@tonic-gate for (code = 255; code >= 0; code--) 13347c478bd9Sstevel@tonic-gate tab_prefixof(code) = 0; 13357c478bd9Sstevel@tonic-gate clear_flg = 1; 13367c478bd9Sstevel@tonic-gate free_ent = FIRST - 1; 13377c478bd9Sstevel@tonic-gate if ((code = getcode()) == -1) /* O, untimely death! */ 13387c478bd9Sstevel@tonic-gate break; 13397c478bd9Sstevel@tonic-gate } 13407c478bd9Sstevel@tonic-gate incode = code; 13417c478bd9Sstevel@tonic-gate /* 13427c478bd9Sstevel@tonic-gate * Special case for KwKwK string. 13437c478bd9Sstevel@tonic-gate */ 13447c478bd9Sstevel@tonic-gate if (code >= free_ent) { 13457c478bd9Sstevel@tonic-gate if (stackp < stack_lim) { 13467c478bd9Sstevel@tonic-gate *stackp++ = (char_type) finchar; 13477c478bd9Sstevel@tonic-gate code = oldcode; 13487c478bd9Sstevel@tonic-gate } else { 13497c478bd9Sstevel@tonic-gate /* badness */ 13507c478bd9Sstevel@tonic-gate longjmp(env, 2); 13517c478bd9Sstevel@tonic-gate } 13527c478bd9Sstevel@tonic-gate } 13537c478bd9Sstevel@tonic-gate 13547c478bd9Sstevel@tonic-gate /* 13557c478bd9Sstevel@tonic-gate * Generate output characters in reverse order 13567c478bd9Sstevel@tonic-gate */ 13577c478bd9Sstevel@tonic-gate while (code >= 256) { 13587c478bd9Sstevel@tonic-gate if (stackp < stack_lim) { 13597c478bd9Sstevel@tonic-gate *stackp++ = tab_suffixof(code); 13607c478bd9Sstevel@tonic-gate code = tab_prefixof(code); 13617c478bd9Sstevel@tonic-gate } else { 13627c478bd9Sstevel@tonic-gate /* badness */ 13637c478bd9Sstevel@tonic-gate longjmp(env, 2); 13647c478bd9Sstevel@tonic-gate } 13657c478bd9Sstevel@tonic-gate } 13667c478bd9Sstevel@tonic-gate *stackp++ = finchar = tab_suffixof(code); 13677c478bd9Sstevel@tonic-gate 13687c478bd9Sstevel@tonic-gate /* 13697c478bd9Sstevel@tonic-gate * And put them out in forward order 13707c478bd9Sstevel@tonic-gate */ 13717c478bd9Sstevel@tonic-gate do { 13727c478bd9Sstevel@tonic-gate stackp--; 13737c478bd9Sstevel@tonic-gate (void) putc(*stackp, fout); 13747c478bd9Sstevel@tonic-gate } while (stackp > de_stack); 13757c478bd9Sstevel@tonic-gate 13767c478bd9Sstevel@tonic-gate if (ferror(fout)) 13777c478bd9Sstevel@tonic-gate ioerror(); 13787c478bd9Sstevel@tonic-gate 13797c478bd9Sstevel@tonic-gate /* 13807c478bd9Sstevel@tonic-gate * Generate the new entry. 13817c478bd9Sstevel@tonic-gate */ 13827c478bd9Sstevel@tonic-gate if ((code = free_ent) < maxmaxcode) { 13837c478bd9Sstevel@tonic-gate tab_prefixof(code) = (unsigned short) oldcode; 13847c478bd9Sstevel@tonic-gate tab_suffixof(code) = (char_type) finchar; 13857c478bd9Sstevel@tonic-gate free_ent = code+1; 13867c478bd9Sstevel@tonic-gate } 13877c478bd9Sstevel@tonic-gate /* 13887c478bd9Sstevel@tonic-gate * Remember previous code. 13897c478bd9Sstevel@tonic-gate */ 13907c478bd9Sstevel@tonic-gate oldcode = incode; 13917c478bd9Sstevel@tonic-gate } 13927c478bd9Sstevel@tonic-gate (void) fflush(outp); 13937c478bd9Sstevel@tonic-gate if (ferror(outp)) 13947c478bd9Sstevel@tonic-gate ioerror(); 13957c478bd9Sstevel@tonic-gate } 13967c478bd9Sstevel@tonic-gate 13977c478bd9Sstevel@tonic-gate /* 13987c478bd9Sstevel@tonic-gate * ************************************************************** 13997c478bd9Sstevel@tonic-gate * TAG( getcode ) 14007c478bd9Sstevel@tonic-gate * 14017c478bd9Sstevel@tonic-gate * Read one code from the standard input. If EOF, return -1. 14027c478bd9Sstevel@tonic-gate * Inputs: 14037c478bd9Sstevel@tonic-gate * inp 14047c478bd9Sstevel@tonic-gate * Outputs: 14057c478bd9Sstevel@tonic-gate * code or -1 is returned. 14067c478bd9Sstevel@tonic-gate */ 14077c478bd9Sstevel@tonic-gate 14087c478bd9Sstevel@tonic-gate code_int 14097c478bd9Sstevel@tonic-gate getcode() { 14107c478bd9Sstevel@tonic-gate code_int code; 14117c478bd9Sstevel@tonic-gate static int offset = 0, size = 0; 14127c478bd9Sstevel@tonic-gate static char_type buf[BITS]; 14137c478bd9Sstevel@tonic-gate int r_off, bits; 14147c478bd9Sstevel@tonic-gate char_type *bp = buf; 14157c478bd9Sstevel@tonic-gate 14167c478bd9Sstevel@tonic-gate if (clear_flg > 0 || offset >= size || free_ent > maxcode) { 14177c478bd9Sstevel@tonic-gate /* 14187c478bd9Sstevel@tonic-gate * If the next entry will be too big for the current code 14197c478bd9Sstevel@tonic-gate * size, then we must increase the size. This implies reading 14207c478bd9Sstevel@tonic-gate * a new buffer full, too. 14217c478bd9Sstevel@tonic-gate */ 14227c478bd9Sstevel@tonic-gate if (free_ent > maxcode) { 14237c478bd9Sstevel@tonic-gate n_bits++; 14247c478bd9Sstevel@tonic-gate if (n_bits == maxbits) 14257c478bd9Sstevel@tonic-gate /* won't get any bigger now */ 14267c478bd9Sstevel@tonic-gate maxcode = maxmaxcode; 14277c478bd9Sstevel@tonic-gate else 14287c478bd9Sstevel@tonic-gate maxcode = MAXCODE(n_bits); 14297c478bd9Sstevel@tonic-gate } 14307c478bd9Sstevel@tonic-gate if (clear_flg > 0) { 14317c478bd9Sstevel@tonic-gate maxcode = MAXCODE(n_bits = INIT_BITS); 14327c478bd9Sstevel@tonic-gate clear_flg = 0; 14337c478bd9Sstevel@tonic-gate } 14347c478bd9Sstevel@tonic-gate size = fread(buf, 1, n_bits, inp); 14357c478bd9Sstevel@tonic-gate 14367c478bd9Sstevel@tonic-gate if (size <= 0) { 14377c478bd9Sstevel@tonic-gate if (feof(inp)) { 14387c478bd9Sstevel@tonic-gate /* end of file */ 14397c478bd9Sstevel@tonic-gate return (-1); 14407c478bd9Sstevel@tonic-gate } else if (ferror(inp)) { 14417c478bd9Sstevel@tonic-gate ioerror(); 14427c478bd9Sstevel@tonic-gate } 14437c478bd9Sstevel@tonic-gate } 14447c478bd9Sstevel@tonic-gate 14457c478bd9Sstevel@tonic-gate offset = 0; 14467c478bd9Sstevel@tonic-gate /* Round size down to integral number of codes */ 14477c478bd9Sstevel@tonic-gate size = (size << 3) - (n_bits - 1); 14487c478bd9Sstevel@tonic-gate } 14497c478bd9Sstevel@tonic-gate r_off = offset; 14507c478bd9Sstevel@tonic-gate bits = n_bits; 14517c478bd9Sstevel@tonic-gate /* 14527c478bd9Sstevel@tonic-gate * Get to the first byte. 14537c478bd9Sstevel@tonic-gate */ 14547c478bd9Sstevel@tonic-gate bp += (r_off >> 3); 14557c478bd9Sstevel@tonic-gate r_off &= 7; 14567c478bd9Sstevel@tonic-gate /* Get first part (low order bits) */ 14577c478bd9Sstevel@tonic-gate code = (*bp++ >> r_off); 14587c478bd9Sstevel@tonic-gate bits -= (8 - r_off); 14597c478bd9Sstevel@tonic-gate r_off = 8 - r_off; /* now, offset into code word */ 14607c478bd9Sstevel@tonic-gate /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */ 14617c478bd9Sstevel@tonic-gate if (bits >= 8) { 14627c478bd9Sstevel@tonic-gate code |= *bp++ << r_off; 14637c478bd9Sstevel@tonic-gate r_off += 8; 14647c478bd9Sstevel@tonic-gate bits -= 8; 14657c478bd9Sstevel@tonic-gate } 14667c478bd9Sstevel@tonic-gate /* high order bits. */ 14677c478bd9Sstevel@tonic-gate code |= (*bp & rmask[bits]) << r_off; 14687c478bd9Sstevel@tonic-gate offset += n_bits; 14697c478bd9Sstevel@tonic-gate 14707c478bd9Sstevel@tonic-gate return (code); 14717c478bd9Sstevel@tonic-gate } 14727c478bd9Sstevel@tonic-gate 14737c478bd9Sstevel@tonic-gate #ifdef DEBUG 14747c478bd9Sstevel@tonic-gate static void 14757c478bd9Sstevel@tonic-gate printcodes() 14767c478bd9Sstevel@tonic-gate { 14777c478bd9Sstevel@tonic-gate /* 14787c478bd9Sstevel@tonic-gate * Just print out codes from input file. For debugging. 14797c478bd9Sstevel@tonic-gate */ 14807c478bd9Sstevel@tonic-gate code_int code; 14817c478bd9Sstevel@tonic-gate int col = 0, bits; 14827c478bd9Sstevel@tonic-gate 14837c478bd9Sstevel@tonic-gate bits = n_bits = INIT_BITS; 14847c478bd9Sstevel@tonic-gate maxcode = MAXCODE(n_bits); 14857c478bd9Sstevel@tonic-gate free_ent = ((block_compress) ? FIRST : 256); 14867c478bd9Sstevel@tonic-gate while ((code = getcode()) >= 0) { 14877c478bd9Sstevel@tonic-gate if ((code == CLEAR) && block_compress) { 14887c478bd9Sstevel@tonic-gate free_ent = FIRST - 1; 14897c478bd9Sstevel@tonic-gate clear_flg = 1; 14907c478bd9Sstevel@tonic-gate } else if (free_ent < maxmaxcode) 14917c478bd9Sstevel@tonic-gate free_ent++; 14927c478bd9Sstevel@tonic-gate if (bits != n_bits) { 14937c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\nChange to %d bits\n", n_bits); 14947c478bd9Sstevel@tonic-gate bits = n_bits; 14957c478bd9Sstevel@tonic-gate col = 0; 14967c478bd9Sstevel@tonic-gate } 14977c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%5d%c", 14987c478bd9Sstevel@tonic-gate code, (col += 6) >= 74 ? (col = 0, '\n') : ' '); 14997c478bd9Sstevel@tonic-gate } 15007c478bd9Sstevel@tonic-gate (void) putc('\n', stderr); 15017c478bd9Sstevel@tonic-gate } 15027c478bd9Sstevel@tonic-gate 15037c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 15047c478bd9Sstevel@tonic-gate 15057c478bd9Sstevel@tonic-gate #ifdef DEBUG 15067c478bd9Sstevel@tonic-gate static void 15077c478bd9Sstevel@tonic-gate dump_tab() /* dump string table */ 15087c478bd9Sstevel@tonic-gate { 15097c478bd9Sstevel@tonic-gate int i, first; 15107c478bd9Sstevel@tonic-gate int ent; 15117c478bd9Sstevel@tonic-gate int stack_top = STACK_SIZE; 15127c478bd9Sstevel@tonic-gate int c; 15137c478bd9Sstevel@tonic-gate 15147c478bd9Sstevel@tonic-gate if (do_decomp == 0) { /* compressing */ 15157c478bd9Sstevel@tonic-gate int flag = 1; 15167c478bd9Sstevel@tonic-gate 15177c478bd9Sstevel@tonic-gate for (i = 0; i < hsize; i++) { /* build sort pointers */ 15187c478bd9Sstevel@tonic-gate if ((long)htabof(i) >= 0) { 15197c478bd9Sstevel@tonic-gate sorttab[codetabof(i)] = i; 15207c478bd9Sstevel@tonic-gate } 15217c478bd9Sstevel@tonic-gate } 15227c478bd9Sstevel@tonic-gate first = block_compress ? FIRST : 256; 15237c478bd9Sstevel@tonic-gate for (i = first; i < free_ent; i++) { 15247c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%5d: \"", i); 15257c478bd9Sstevel@tonic-gate de_stack[--stack_top] = '\n'; 15267c478bd9Sstevel@tonic-gate de_stack[--stack_top] = '"'; 15277c478bd9Sstevel@tonic-gate stack_top = 15287c478bd9Sstevel@tonic-gate in_stack((htabof(sorttab[i]) >> maxbits) & 0xff, 15297c478bd9Sstevel@tonic-gate stack_top); 15307c478bd9Sstevel@tonic-gate for (ent = htabof(sorttab[i]) & ((1 << maxbits) -1); 15317c478bd9Sstevel@tonic-gate ent > 256; 15327c478bd9Sstevel@tonic-gate ent = htabof(sorttab[ent]) & ((1<<maxbits)-1)) { 15337c478bd9Sstevel@tonic-gate stack_top = in_stack( 15347c478bd9Sstevel@tonic-gate htabof(sorttab[ent]) >> maxbits, 15357c478bd9Sstevel@tonic-gate stack_top); 15367c478bd9Sstevel@tonic-gate } 15377c478bd9Sstevel@tonic-gate stack_top = in_stack(ent, stack_top); 15387c478bd9Sstevel@tonic-gate (void) fwrite(&de_stack[stack_top], 1, 15397c478bd9Sstevel@tonic-gate STACK_SIZE - stack_top, stderr); 15407c478bd9Sstevel@tonic-gate stack_top = STACK_SIZE; 15417c478bd9Sstevel@tonic-gate } 15427c478bd9Sstevel@tonic-gate } else if (!debug) { /* decompressing */ 15437c478bd9Sstevel@tonic-gate 15447c478bd9Sstevel@tonic-gate for (i = 0; i < free_ent; i++) { 15457c478bd9Sstevel@tonic-gate ent = i; 15467c478bd9Sstevel@tonic-gate c = tab_suffixof(ent); 15477c478bd9Sstevel@tonic-gate if (isascii(c) && isprint(c)) 15487c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%5d: %5d/'%c' \"", 15497c478bd9Sstevel@tonic-gate ent, tab_prefixof(ent), c); 15507c478bd9Sstevel@tonic-gate else 15517c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%5d: %5d/\\%03o \"", 15527c478bd9Sstevel@tonic-gate ent, tab_prefixof(ent), c); 15537c478bd9Sstevel@tonic-gate de_stack[--stack_top] = '\n'; 15547c478bd9Sstevel@tonic-gate de_stack[--stack_top] = '"'; 15557c478bd9Sstevel@tonic-gate for (; ent != NULL; 15567c478bd9Sstevel@tonic-gate ent = (ent >= FIRST ? tab_prefixof(ent) : 15577c478bd9Sstevel@tonic-gate NULL)) { 15587c478bd9Sstevel@tonic-gate stack_top = in_stack(tab_suffixof(ent), 15597c478bd9Sstevel@tonic-gate stack_top); 15607c478bd9Sstevel@tonic-gate } 15617c478bd9Sstevel@tonic-gate (void) fwrite(&de_stack[stack_top], 1, 15627c478bd9Sstevel@tonic-gate STACK_SIZE - stack_top, stderr); 15637c478bd9Sstevel@tonic-gate stack_top = STACK_SIZE; 15647c478bd9Sstevel@tonic-gate } 15657c478bd9Sstevel@tonic-gate } 15667c478bd9Sstevel@tonic-gate } 15677c478bd9Sstevel@tonic-gate 15687c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 15697c478bd9Sstevel@tonic-gate #ifdef DEBUG 15707c478bd9Sstevel@tonic-gate static int 15717c478bd9Sstevel@tonic-gate in_stack(int c, int stack_top) 15727c478bd9Sstevel@tonic-gate { 15737c478bd9Sstevel@tonic-gate if ((isascii(c) && isprint(c) && c != '\\') || c == ' ') { 15747c478bd9Sstevel@tonic-gate de_stack[--stack_top] = c; 15757c478bd9Sstevel@tonic-gate } else { 15767c478bd9Sstevel@tonic-gate switch (c) { 15777c478bd9Sstevel@tonic-gate case '\n': de_stack[--stack_top] = 'n'; break; 15787c478bd9Sstevel@tonic-gate case '\t': de_stack[--stack_top] = 't'; break; 15797c478bd9Sstevel@tonic-gate case '\b': de_stack[--stack_top] = 'b'; break; 15807c478bd9Sstevel@tonic-gate case '\f': de_stack[--stack_top] = 'f'; break; 15817c478bd9Sstevel@tonic-gate case '\r': de_stack[--stack_top] = 'r'; break; 15827c478bd9Sstevel@tonic-gate case '\\': de_stack[--stack_top] = '\\'; break; 15837c478bd9Sstevel@tonic-gate default: 15847c478bd9Sstevel@tonic-gate de_stack[--stack_top] = '0' + c % 8; 15857c478bd9Sstevel@tonic-gate de_stack[--stack_top] = '0' + (c / 8) % 8; 15867c478bd9Sstevel@tonic-gate de_stack[--stack_top] = '0' + c / 64; 15877c478bd9Sstevel@tonic-gate break; 15887c478bd9Sstevel@tonic-gate } 15897c478bd9Sstevel@tonic-gate de_stack[--stack_top] = '\\'; 15907c478bd9Sstevel@tonic-gate } 15917c478bd9Sstevel@tonic-gate return (stack_top); 15927c478bd9Sstevel@tonic-gate } 15937c478bd9Sstevel@tonic-gate 15947c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 15957c478bd9Sstevel@tonic-gate static void 15967c478bd9Sstevel@tonic-gate ioerror() 15977c478bd9Sstevel@tonic-gate { 15987c478bd9Sstevel@tonic-gate longjmp(env, 1); 15997c478bd9Sstevel@tonic-gate } 16007c478bd9Sstevel@tonic-gate 16017c478bd9Sstevel@tonic-gate static void 16027c478bd9Sstevel@tonic-gate copystat(char *ifname, struct stat *ifstat, char *ofname) 16037c478bd9Sstevel@tonic-gate { 16047c478bd9Sstevel@tonic-gate mode_t mode; 16057c478bd9Sstevel@tonic-gate struct utimbuf timep; 1606*fa9e4066Sahrens acl_t *aclp; 1607*fa9e4066Sahrens int error; 16087c478bd9Sstevel@tonic-gate 16097c478bd9Sstevel@tonic-gate if (fclose(outp)) { 16107c478bd9Sstevel@tonic-gate perror(ofname); 16117c478bd9Sstevel@tonic-gate if (!quiet) { 16127c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(" -- file unchanged")); 16137c478bd9Sstevel@tonic-gate newline_needed = 1; 16147c478bd9Sstevel@tonic-gate } 16157c478bd9Sstevel@tonic-gate perm_stat = 1; 16167c478bd9Sstevel@tonic-gate } else if (ifstat == NULL) { /* Get stat on input file */ 16177c478bd9Sstevel@tonic-gate perror(ifname); 16187c478bd9Sstevel@tonic-gate return; 16197c478bd9Sstevel@tonic-gate } else if ((ifstat->st_mode & 16207c478bd9Sstevel@tonic-gate S_IFMT /* 0170000 */) != S_IFREG /* 0100000 */) { 16217c478bd9Sstevel@tonic-gate if (quiet) { 16227c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: ", ifname); 16237c478bd9Sstevel@tonic-gate } 16247c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 16257c478bd9Sstevel@tonic-gate " -- not a regular file: unchanged")); 16267c478bd9Sstevel@tonic-gate newline_needed = 1; 16277c478bd9Sstevel@tonic-gate perm_stat = 1; 16287c478bd9Sstevel@tonic-gate } else if (ifstat->st_nlink > 1) { 16297c478bd9Sstevel@tonic-gate if (quiet) { 16307c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: ", ifname); 16317c478bd9Sstevel@tonic-gate } 16327c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 16337c478bd9Sstevel@tonic-gate " -- has %d other links: unchanged"), 16347c478bd9Sstevel@tonic-gate (uint_t)ifstat->st_nlink - 1); 16357c478bd9Sstevel@tonic-gate newline_needed = 1; 16367c478bd9Sstevel@tonic-gate perm_stat = 1; 16377c478bd9Sstevel@tonic-gate } else if (didnt_shrink && !force) { 16387c478bd9Sstevel@tonic-gate /* No compression: remove file.Z */ 16397c478bd9Sstevel@tonic-gate if (!quiet) { 16407c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 16417c478bd9Sstevel@tonic-gate " -- file unchanged")); 16427c478bd9Sstevel@tonic-gate newline_needed = 1; 16437c478bd9Sstevel@tonic-gate } 16447c478bd9Sstevel@tonic-gate } else if ((pathconf(ifname, _PC_XATTR_EXISTS) == 1) && 16457c478bd9Sstevel@tonic-gate (mv_xattrs(ifname, ofname, 0) < 0)) { 16467c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 16477c478bd9Sstevel@tonic-gate "%s: -- cannot preserve extended attributes, " 16487c478bd9Sstevel@tonic-gate "file unchanged"), ifname); 16497c478bd9Sstevel@tonic-gate newline_needed = 1; 16507c478bd9Sstevel@tonic-gate /* Move attributes back ... */ 16517c478bd9Sstevel@tonic-gate (void) mv_xattrs(ofname, ifname, 1); 16527c478bd9Sstevel@tonic-gate perm_stat = 1; 16537c478bd9Sstevel@tonic-gate } else { /* ***** Successful Compression ***** */ 16547c478bd9Sstevel@tonic-gate mode = ifstat->st_mode & 07777; 16557c478bd9Sstevel@tonic-gate if (chmod(ofname, mode)) /* Copy modes */ 16567c478bd9Sstevel@tonic-gate perror(ofname); 16577c478bd9Sstevel@tonic-gate 1658*fa9e4066Sahrens error = acl_get(ifname, ACL_NO_TRIVIAL, &aclp); 1659*fa9e4066Sahrens if (error != 0) { 16607c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 1661*fa9e4066Sahrens "%s: failed to retrieve acl : %s\n"), 1662*fa9e4066Sahrens ifname, acl_strerror(error)); 16637c478bd9Sstevel@tonic-gate perm_stat = 1; 16647c478bd9Sstevel@tonic-gate } 1665*fa9e4066Sahrens if (aclp && (acl_set(ofname, aclp) < 0)) { 1666*fa9e4066Sahrens (void) fprintf(stderr, gettext("%s: failed to set acl " 16677c478bd9Sstevel@tonic-gate "entries\n"), ofname); 16687c478bd9Sstevel@tonic-gate perm_stat = 1; 16697c478bd9Sstevel@tonic-gate } 1670*fa9e4066Sahrens if (aclp) 1671*fa9e4066Sahrens acl_free(aclp); 16727c478bd9Sstevel@tonic-gate 16737c478bd9Sstevel@tonic-gate /* Copy ownership */ 16747c478bd9Sstevel@tonic-gate (void) chown(ofname, ifstat->st_uid, ifstat->st_gid); 16757c478bd9Sstevel@tonic-gate timep.actime = ifstat->st_atime; 16767c478bd9Sstevel@tonic-gate timep.modtime = ifstat->st_mtime; 16777c478bd9Sstevel@tonic-gate /* Update last accessed and modified times */ 16787c478bd9Sstevel@tonic-gate (void) utime(ofname, &timep); 16797c478bd9Sstevel@tonic-gate if (unlink(ifname)) /* Remove input file */ 16807c478bd9Sstevel@tonic-gate perror(ifname); 16817c478bd9Sstevel@tonic-gate if (!quiet) { 16827c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 16837c478bd9Sstevel@tonic-gate " -- replaced with %s"), ofname); 16847c478bd9Sstevel@tonic-gate newline_needed = 1; 16857c478bd9Sstevel@tonic-gate } 16867c478bd9Sstevel@tonic-gate return; /* Successful return */ 16877c478bd9Sstevel@tonic-gate } 16887c478bd9Sstevel@tonic-gate 16897c478bd9Sstevel@tonic-gate /* Unsuccessful return -- one of the tests failed */ 16907c478bd9Sstevel@tonic-gate if (ofname[0] != '\0') { 16917c478bd9Sstevel@tonic-gate if (unlink(ofname)) { 16927c478bd9Sstevel@tonic-gate perror(ofname); 16937c478bd9Sstevel@tonic-gate } 16947c478bd9Sstevel@tonic-gate 16957c478bd9Sstevel@tonic-gate ofname[0] = '\0'; 16967c478bd9Sstevel@tonic-gate } 16977c478bd9Sstevel@tonic-gate } 16987c478bd9Sstevel@tonic-gate 16997c478bd9Sstevel@tonic-gate static void 17007c478bd9Sstevel@tonic-gate onintr() 17017c478bd9Sstevel@tonic-gate { 17027c478bd9Sstevel@tonic-gate if (!precious && !use_stdout && ofname[0] != '\0') 17037c478bd9Sstevel@tonic-gate (void) unlink(ofname); 17047c478bd9Sstevel@tonic-gate exit(1); 17057c478bd9Sstevel@tonic-gate } 17067c478bd9Sstevel@tonic-gate 17077c478bd9Sstevel@tonic-gate static void 17087c478bd9Sstevel@tonic-gate oops() /* wild pointer -- assume bad input */ 17097c478bd9Sstevel@tonic-gate { 17107c478bd9Sstevel@tonic-gate if (do_decomp) { 17117c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("uncompress: corrupt input\n")); 17127c478bd9Sstevel@tonic-gate } 17137c478bd9Sstevel@tonic-gate 17147c478bd9Sstevel@tonic-gate if (!use_stdout && ofname[0] != '\0') { 17157c478bd9Sstevel@tonic-gate (void) unlink(ofname); 17167c478bd9Sstevel@tonic-gate } 17177c478bd9Sstevel@tonic-gate 17187c478bd9Sstevel@tonic-gate exit(1); 17197c478bd9Sstevel@tonic-gate } 17207c478bd9Sstevel@tonic-gate 17217c478bd9Sstevel@tonic-gate static void 17227c478bd9Sstevel@tonic-gate cl_block(count_long in_count) /* table clear for block compress */ 17237c478bd9Sstevel@tonic-gate { 17247c478bd9Sstevel@tonic-gate count_long rat; 17257c478bd9Sstevel@tonic-gate 17267c478bd9Sstevel@tonic-gate checkpoint = (count_long)in_count + (count_long)CHECK_GAP; 17277c478bd9Sstevel@tonic-gate #ifdef DEBUG 17287c478bd9Sstevel@tonic-gate if (debug) { 17297c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "count: %lld, ratio: ", 17307c478bd9Sstevel@tonic-gate (count_long)in_count); 17317c478bd9Sstevel@tonic-gate prratio(stderr, (count_long)in_count, (count_long)bytes_out); 17327c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\n"); 17337c478bd9Sstevel@tonic-gate } 17347c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 17357c478bd9Sstevel@tonic-gate 17367c478bd9Sstevel@tonic-gate /* shift will overflow */ 1737a77d64afScf46844 if ((count_long)in_count > 0x007fffffffffffffLL) { 17387c478bd9Sstevel@tonic-gate rat = (count_long)bytes_out >> 8; 17397c478bd9Sstevel@tonic-gate if (rat == 0) { /* Don't divide by zero */ 1740a77d64afScf46844 rat = 0x7fffffffffffffffLL; 17417c478bd9Sstevel@tonic-gate } else { 17427c478bd9Sstevel@tonic-gate rat = (count_long)in_count / (count_long)rat; 17437c478bd9Sstevel@tonic-gate } 17447c478bd9Sstevel@tonic-gate } else { 17457c478bd9Sstevel@tonic-gate /* 8 fractional bits */ 17467c478bd9Sstevel@tonic-gate rat = ((count_long)in_count << 8) /(count_long)bytes_out; 17477c478bd9Sstevel@tonic-gate } 17487c478bd9Sstevel@tonic-gate if (rat > ratio) { 17497c478bd9Sstevel@tonic-gate ratio = rat; 17507c478bd9Sstevel@tonic-gate } else { 17517c478bd9Sstevel@tonic-gate ratio = 0; 17527c478bd9Sstevel@tonic-gate #ifdef DEBUG 17537c478bd9Sstevel@tonic-gate if (verbose) 17547c478bd9Sstevel@tonic-gate dump_tab(); /* dump string table */ 17557c478bd9Sstevel@tonic-gate #endif 17567c478bd9Sstevel@tonic-gate cl_hash((count_int) hsize); 17577c478bd9Sstevel@tonic-gate free_ent = FIRST; 17587c478bd9Sstevel@tonic-gate clear_flg = 1; 17597c478bd9Sstevel@tonic-gate output((code_int) CLEAR); 17607c478bd9Sstevel@tonic-gate #ifdef DEBUG 17617c478bd9Sstevel@tonic-gate if (debug) 17627c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "clear\n"); 17637c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 17647c478bd9Sstevel@tonic-gate } 17657c478bd9Sstevel@tonic-gate } 17667c478bd9Sstevel@tonic-gate 17677c478bd9Sstevel@tonic-gate static void 17687c478bd9Sstevel@tonic-gate cl_hash(count_int hsize) /* reset code table */ 17697c478bd9Sstevel@tonic-gate { 17707c478bd9Sstevel@tonic-gate count_int *htab_p = htab+hsize; 17717c478bd9Sstevel@tonic-gate long i; 17727c478bd9Sstevel@tonic-gate long m1 = -1; 17737c478bd9Sstevel@tonic-gate 17747c478bd9Sstevel@tonic-gate i = hsize - 16; 17757c478bd9Sstevel@tonic-gate do { /* might use Sys V memset(3) here */ 17767c478bd9Sstevel@tonic-gate *(htab_p-16) = m1; 17777c478bd9Sstevel@tonic-gate *(htab_p-15) = m1; 17787c478bd9Sstevel@tonic-gate *(htab_p-14) = m1; 17797c478bd9Sstevel@tonic-gate *(htab_p-13) = m1; 17807c478bd9Sstevel@tonic-gate *(htab_p-12) = m1; 17817c478bd9Sstevel@tonic-gate *(htab_p-11) = m1; 17827c478bd9Sstevel@tonic-gate *(htab_p-10) = m1; 17837c478bd9Sstevel@tonic-gate *(htab_p-9) = m1; 17847c478bd9Sstevel@tonic-gate *(htab_p-8) = m1; 17857c478bd9Sstevel@tonic-gate *(htab_p-7) = m1; 17867c478bd9Sstevel@tonic-gate *(htab_p-6) = m1; 17877c478bd9Sstevel@tonic-gate *(htab_p-5) = m1; 17887c478bd9Sstevel@tonic-gate *(htab_p-4) = m1; 17897c478bd9Sstevel@tonic-gate *(htab_p-3) = m1; 17907c478bd9Sstevel@tonic-gate *(htab_p-2) = m1; 17917c478bd9Sstevel@tonic-gate *(htab_p-1) = m1; 17927c478bd9Sstevel@tonic-gate htab_p -= 16; 17937c478bd9Sstevel@tonic-gate } while ((i -= 16) >= 0); 17947c478bd9Sstevel@tonic-gate for (i += 16; i > 0; i--) 17957c478bd9Sstevel@tonic-gate *--htab_p = m1; 17967c478bd9Sstevel@tonic-gate } 17977c478bd9Sstevel@tonic-gate 17987c478bd9Sstevel@tonic-gate static void 17997c478bd9Sstevel@tonic-gate prratio(FILE *stream, count_long num, count_long den) 18007c478bd9Sstevel@tonic-gate { 18017c478bd9Sstevel@tonic-gate int q; /* store percentage */ 18027c478bd9Sstevel@tonic-gate 18037c478bd9Sstevel@tonic-gate q = (int)(10000LL * (count_long)num / (count_long)den); 18047c478bd9Sstevel@tonic-gate if (q < 0) { 18057c478bd9Sstevel@tonic-gate (void) putc('-', stream); 18067c478bd9Sstevel@tonic-gate q = -q; 18077c478bd9Sstevel@tonic-gate } 18087c478bd9Sstevel@tonic-gate (void) fprintf(stream, "%d%s%02d%%", q / 100, 18097c478bd9Sstevel@tonic-gate localeconv()->decimal_point, q % 100); 18107c478bd9Sstevel@tonic-gate } 18117c478bd9Sstevel@tonic-gate 18127c478bd9Sstevel@tonic-gate static void 18137c478bd9Sstevel@tonic-gate version() 18147c478bd9Sstevel@tonic-gate { 18157c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s, Berkeley 5.9 5/11/86\n", rcs_ident); 18167c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "Options: "); 18177c478bd9Sstevel@tonic-gate #ifdef DEBUG 18187c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "DEBUG, "); 18197c478bd9Sstevel@tonic-gate #endif 18207c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "BITS = %d\n", BITS); 18217c478bd9Sstevel@tonic-gate } 18227c478bd9Sstevel@tonic-gate 18237c478bd9Sstevel@tonic-gate static void 18247c478bd9Sstevel@tonic-gate Usage() 18257c478bd9Sstevel@tonic-gate { 18267c478bd9Sstevel@tonic-gate #ifdef DEBUG 18277c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 18287c478bd9Sstevel@tonic-gate "Usage: compress [-dDVfc] [-b maxbits] [file ...]\n"); 18297c478bd9Sstevel@tonic-gate #else 18307c478bd9Sstevel@tonic-gate if (strcmp(progname, "compress") == 0) { 18317c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 18327c478bd9Sstevel@tonic-gate gettext( 18337c478bd9Sstevel@tonic-gate "Usage: compress [-fv] [-b maxbits] [file ...]\n"\ 18347c478bd9Sstevel@tonic-gate " compress [-cfv] [-b maxbits] [file]\n")); 18357c478bd9Sstevel@tonic-gate } else if (strcmp(progname, "uncompress") == 0) 18367c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 18377c478bd9Sstevel@tonic-gate "Usage: uncompress [-cfv] [file ...]\n")); 18387c478bd9Sstevel@tonic-gate else if (strcmp(progname, "zcat") == 0) 18397c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Usage: zcat [file ...]\n")); 18407c478bd9Sstevel@tonic-gate 18417c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 18427c478bd9Sstevel@tonic-gate } 18437c478bd9Sstevel@tonic-gate 18447c478bd9Sstevel@tonic-gate static char * 18457c478bd9Sstevel@tonic-gate local_basename(char *path) 18467c478bd9Sstevel@tonic-gate { 18477c478bd9Sstevel@tonic-gate char *p; 18487c478bd9Sstevel@tonic-gate char *ret = (char *)path; 18497c478bd9Sstevel@tonic-gate 18507c478bd9Sstevel@tonic-gate while ((p = (char *)strpbrk(ret, "/")) != NULL) 18517c478bd9Sstevel@tonic-gate ret = p + 1; 18527c478bd9Sstevel@tonic-gate return (ret); 18537c478bd9Sstevel@tonic-gate } 18547c478bd9Sstevel@tonic-gate 18557c478bd9Sstevel@tonic-gate static int 18567c478bd9Sstevel@tonic-gate addDotZ(char *fn, size_t fnsize) 18577c478bd9Sstevel@tonic-gate { 18587c478bd9Sstevel@tonic-gate char *fn_dup; 18597c478bd9Sstevel@tonic-gate char *dir; 18607c478bd9Sstevel@tonic-gate long int max_name; 18617c478bd9Sstevel@tonic-gate long int max_path; 18627c478bd9Sstevel@tonic-gate 18637c478bd9Sstevel@tonic-gate fn_dup = strdup(fn); 18647c478bd9Sstevel@tonic-gate dir = dirname(fn_dup); 18657c478bd9Sstevel@tonic-gate max_name = pathconf(dir, _PC_NAME_MAX); 18667c478bd9Sstevel@tonic-gate max_path = pathconf(dir, _PC_PATH_MAX); 18677c478bd9Sstevel@tonic-gate free(fn_dup); 18687c478bd9Sstevel@tonic-gate 18697c478bd9Sstevel@tonic-gate /* Check for component length too long */ 18707c478bd9Sstevel@tonic-gate 18717c478bd9Sstevel@tonic-gate if ((strlen(local_basename(fn)) + 2) > (size_t)max_name) { 18727c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 18737c478bd9Sstevel@tonic-gate gettext("%s: filename too long to tack on .Z:" 18747c478bd9Sstevel@tonic-gate " %s\n"), progname, fn); 18757c478bd9Sstevel@tonic-gate return (-1); 18767c478bd9Sstevel@tonic-gate } 18777c478bd9Sstevel@tonic-gate 18787c478bd9Sstevel@tonic-gate /* Check for path length too long */ 18797c478bd9Sstevel@tonic-gate 18807c478bd9Sstevel@tonic-gate if ((strlen(fn) + 2) > (size_t)max_path - 1) { 18817c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 18827c478bd9Sstevel@tonic-gate gettext("%s: Pathname too long to tack on .Z:" 18837c478bd9Sstevel@tonic-gate " %s\n"), progname, fn); 18847c478bd9Sstevel@tonic-gate return (-1); 18857c478bd9Sstevel@tonic-gate } 18867c478bd9Sstevel@tonic-gate 18877c478bd9Sstevel@tonic-gate if (strlcat(fn, ".Z", fnsize) >= fnsize) { 18887c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 18897c478bd9Sstevel@tonic-gate gettext("%s: Buffer overflow adding .Z to %s\n"), 18907c478bd9Sstevel@tonic-gate progname, fn); 18917c478bd9Sstevel@tonic-gate return (-1); 18927c478bd9Sstevel@tonic-gate } 18937c478bd9Sstevel@tonic-gate 18947c478bd9Sstevel@tonic-gate return (0); 18957c478bd9Sstevel@tonic-gate } 18967c478bd9Sstevel@tonic-gate 18977c478bd9Sstevel@tonic-gate /* 18987c478bd9Sstevel@tonic-gate * mv_xattrs - move (via renameat) all of the extended attributes 18997c478bd9Sstevel@tonic-gate * associated with the file infile to the file outfile. 19007c478bd9Sstevel@tonic-gate * This function returns 0 on success and -1 on error. 19017c478bd9Sstevel@tonic-gate */ 19027c478bd9Sstevel@tonic-gate static int 19037c478bd9Sstevel@tonic-gate mv_xattrs(char *infile, char *outfile, int silent) 19047c478bd9Sstevel@tonic-gate { 19057c478bd9Sstevel@tonic-gate int indfd, outdfd, tmpfd; 19067c478bd9Sstevel@tonic-gate DIR *dirp = NULL; 19077c478bd9Sstevel@tonic-gate struct dirent *dp = NULL; 19087c478bd9Sstevel@tonic-gate int error = 0; 19097c478bd9Sstevel@tonic-gate char *etext; 19107c478bd9Sstevel@tonic-gate 19117c478bd9Sstevel@tonic-gate indfd = outdfd = tmpfd = -1; 19127c478bd9Sstevel@tonic-gate 19137c478bd9Sstevel@tonic-gate if ((indfd = attropen(infile, ".", O_RDONLY)) == -1) { 19147c478bd9Sstevel@tonic-gate etext = gettext("cannot open source"); 19157c478bd9Sstevel@tonic-gate error = -1; 19167c478bd9Sstevel@tonic-gate goto out; 19177c478bd9Sstevel@tonic-gate } 19187c478bd9Sstevel@tonic-gate 19197c478bd9Sstevel@tonic-gate if ((outdfd = attropen(outfile, ".", O_RDONLY)) == -1) { 19207c478bd9Sstevel@tonic-gate etext = gettext("cannot open target"); 19217c478bd9Sstevel@tonic-gate error = -1; 19227c478bd9Sstevel@tonic-gate goto out; 19237c478bd9Sstevel@tonic-gate } 19247c478bd9Sstevel@tonic-gate 19257c478bd9Sstevel@tonic-gate if ((tmpfd = dup(indfd)) == -1) { 19267c478bd9Sstevel@tonic-gate etext = gettext("cannot dup descriptor"); 19277c478bd9Sstevel@tonic-gate error = -1; 19287c478bd9Sstevel@tonic-gate goto out; 19297c478bd9Sstevel@tonic-gate 19307c478bd9Sstevel@tonic-gate } 19317c478bd9Sstevel@tonic-gate if ((dirp = fdopendir(tmpfd)) == NULL) { 19327c478bd9Sstevel@tonic-gate etext = gettext("cannot access source"); 19337c478bd9Sstevel@tonic-gate error = -1; 19347c478bd9Sstevel@tonic-gate goto out; 19357c478bd9Sstevel@tonic-gate } 19367c478bd9Sstevel@tonic-gate 19377c478bd9Sstevel@tonic-gate while (dp = readdir(dirp)) { 19387c478bd9Sstevel@tonic-gate if ((dp->d_name[0] == '.' && dp->d_name[1] == '\0') || 19397c478bd9Sstevel@tonic-gate (dp->d_name[0] == '.' && dp->d_name[1] == '.' && 19407c478bd9Sstevel@tonic-gate dp->d_name[2] == '\0')) 19417c478bd9Sstevel@tonic-gate continue; 19427c478bd9Sstevel@tonic-gate if ((renameat(indfd, dp->d_name, outdfd, dp->d_name)) == -1) { 19437c478bd9Sstevel@tonic-gate etext = dp->d_name; 19447c478bd9Sstevel@tonic-gate error = -1; 19457c478bd9Sstevel@tonic-gate goto out; 19467c478bd9Sstevel@tonic-gate } 19477c478bd9Sstevel@tonic-gate } 19487c478bd9Sstevel@tonic-gate out: 19497c478bd9Sstevel@tonic-gate if (error == -1 && silent == 0) { 19507c478bd9Sstevel@tonic-gate if (quiet) { 19517c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: ", infile); 19527c478bd9Sstevel@tonic-gate } else { 19537c478bd9Sstevel@tonic-gate (void) fprintf(stderr, ", "); 19547c478bd9Sstevel@tonic-gate } 19557c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("extended attribute error: ")); 19567c478bd9Sstevel@tonic-gate perror(etext); 19577c478bd9Sstevel@tonic-gate } 19587c478bd9Sstevel@tonic-gate if (dirp) 19597c478bd9Sstevel@tonic-gate (void) closedir(dirp); 19607c478bd9Sstevel@tonic-gate if (indfd != -1) 19617c478bd9Sstevel@tonic-gate (void) close(indfd); 19627c478bd9Sstevel@tonic-gate if (outdfd != -1) 19637c478bd9Sstevel@tonic-gate (void) close(outdfd); 19647c478bd9Sstevel@tonic-gate return (error); 19657c478bd9Sstevel@tonic-gate } 1966