1*3117ece4Schristos /* minigzip.c contains minimal changes required to be compiled with zlibWrapper: 2*3117ece4Schristos * - #include "zlib.h" was changed to #include "zstd_zlibwrapper.h" */ 3*3117ece4Schristos 4*3117ece4Schristos /* minigzip.c -- simulate gzip using the zlib compression library 5*3117ece4Schristos * Copyright (C) 1995-2006, 2010, 2011 Jean-loup Gailly. 6*3117ece4Schristos * For conditions of distribution and use, see https://www.zlib.net/zlib_license.html 7*3117ece4Schristos */ 8*3117ece4Schristos 9*3117ece4Schristos /* 10*3117ece4Schristos * minigzip is a minimal implementation of the gzip utility. This is 11*3117ece4Schristos * only an example of using zlib and isn't meant to replace the 12*3117ece4Schristos * full-featured gzip. No attempt is made to deal with file systems 13*3117ece4Schristos * limiting names to 14 or 8+3 characters, etc... Error checking is 14*3117ece4Schristos * very limited. So use minigzip only for testing; use gzip for the 15*3117ece4Schristos * real thing. On MSDOS, use only on file names without extension 16*3117ece4Schristos * or in pipe mode. 17*3117ece4Schristos */ 18*3117ece4Schristos 19*3117ece4Schristos /* @(#) $Id: minigzip.c,v 1.1.1.1 2024/10/27 22:44:15 christos Exp $ */ 20*3117ece4Schristos 21*3117ece4Schristos #define _POSIX_SOURCE /* fileno */ 22*3117ece4Schristos 23*3117ece4Schristos #include "zstd_zlibwrapper.h" 24*3117ece4Schristos #include <stdio.h> 25*3117ece4Schristos 26*3117ece4Schristos #ifdef STDC 27*3117ece4Schristos # include <string.h> 28*3117ece4Schristos # include <stdlib.h> 29*3117ece4Schristos #endif 30*3117ece4Schristos 31*3117ece4Schristos #ifdef USE_MMAP 32*3117ece4Schristos # include <sys/types.h> 33*3117ece4Schristos # include <sys/mman.h> 34*3117ece4Schristos # include <sys/stat.h> 35*3117ece4Schristos #endif 36*3117ece4Schristos 37*3117ece4Schristos #if defined(MSDOS) || defined(OS2) || defined(_WIN32) || defined(__CYGWIN__) 38*3117ece4Schristos # include <fcntl.h> 39*3117ece4Schristos # include <io.h> 40*3117ece4Schristos # ifdef UNDER_CE 41*3117ece4Schristos # include <stdlib.h> 42*3117ece4Schristos # endif 43*3117ece4Schristos # define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY) 44*3117ece4Schristos #else 45*3117ece4Schristos # define SET_BINARY_MODE(file) 46*3117ece4Schristos #endif 47*3117ece4Schristos 48*3117ece4Schristos #ifdef _MSC_VER 49*3117ece4Schristos # define snprintf _snprintf 50*3117ece4Schristos #endif 51*3117ece4Schristos 52*3117ece4Schristos #ifdef VMS 53*3117ece4Schristos # define unlink delete 54*3117ece4Schristos # define GZ_SUFFIX "-gz" 55*3117ece4Schristos #endif 56*3117ece4Schristos #ifdef RISCOS 57*3117ece4Schristos # define unlink remove 58*3117ece4Schristos # define GZ_SUFFIX "-gz" 59*3117ece4Schristos # define fileno(file) file->__file 60*3117ece4Schristos #endif 61*3117ece4Schristos #if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os 62*3117ece4Schristos # include <unix.h> /* for fileno */ 63*3117ece4Schristos #endif 64*3117ece4Schristos 65*3117ece4Schristos #if !defined(Z_HAVE_UNISTD_H) && !defined(_LARGEFILE64_SOURCE) 66*3117ece4Schristos #ifndef _WIN32 /* unlink already in stdio.h for WIN32 */ 67*3117ece4Schristos extern int unlink _Z_OF((const char *)); 68*3117ece4Schristos #endif 69*3117ece4Schristos #endif 70*3117ece4Schristos 71*3117ece4Schristos #if defined(UNDER_CE) 72*3117ece4Schristos # include <windows.h> 73*3117ece4Schristos # define perror(s) pwinerror(s) 74*3117ece4Schristos 75*3117ece4Schristos /* Map the Windows error number in ERROR to a locale-dependent error 76*3117ece4Schristos message string and return a pointer to it. Typically, the values 77*3117ece4Schristos for ERROR come from GetLastError. 78*3117ece4Schristos 79*3117ece4Schristos The string pointed to shall not be modified by the application, 80*3117ece4Schristos but may be overwritten by a subsequent call to strwinerror 81*3117ece4Schristos 82*3117ece4Schristos The strwinerror function does not change the current setting 83*3117ece4Schristos of GetLastError. */ 84*3117ece4Schristos 85*3117ece4Schristos static char *strwinerror(DWORD error) 86*3117ece4Schristos { 87*3117ece4Schristos static char buf[1024]; 88*3117ece4Schristos 89*3117ece4Schristos wchar_t *msgbuf; 90*3117ece4Schristos DWORD lasterr = GetLastError(); 91*3117ece4Schristos DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM 92*3117ece4Schristos | FORMAT_MESSAGE_ALLOCATE_BUFFER, 93*3117ece4Schristos NULL, 94*3117ece4Schristos error, 95*3117ece4Schristos 0, /* Default language */ 96*3117ece4Schristos (LPVOID)&msgbuf, 97*3117ece4Schristos 0, 98*3117ece4Schristos NULL); 99*3117ece4Schristos if (chars != 0) { 100*3117ece4Schristos /* If there is an \r\n appended, zap it. */ 101*3117ece4Schristos if (chars >= 2 102*3117ece4Schristos && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') { 103*3117ece4Schristos chars -= 2; 104*3117ece4Schristos msgbuf[chars] = 0; 105*3117ece4Schristos } 106*3117ece4Schristos 107*3117ece4Schristos if (chars > sizeof (buf) - 1) { 108*3117ece4Schristos chars = sizeof (buf) - 1; 109*3117ece4Schristos msgbuf[chars] = 0; 110*3117ece4Schristos } 111*3117ece4Schristos 112*3117ece4Schristos wcstombs(buf, msgbuf, chars + 1); 113*3117ece4Schristos LocalFree(msgbuf); 114*3117ece4Schristos } 115*3117ece4Schristos else { 116*3117ece4Schristos sprintf(buf, "unknown win32 error (%ld)", error); 117*3117ece4Schristos } 118*3117ece4Schristos 119*3117ece4Schristos SetLastError(lasterr); 120*3117ece4Schristos return buf; 121*3117ece4Schristos } 122*3117ece4Schristos 123*3117ece4Schristos static void pwinerror (const char *s) 124*3117ece4Schristos { 125*3117ece4Schristos if (s && *s) 126*3117ece4Schristos fprintf(stderr, "%s: %s\n", s, strwinerror(GetLastError ())); 127*3117ece4Schristos else 128*3117ece4Schristos fprintf(stderr, "%s\n", strwinerror(GetLastError ())); 129*3117ece4Schristos } 130*3117ece4Schristos 131*3117ece4Schristos #endif /* UNDER_CE */ 132*3117ece4Schristos 133*3117ece4Schristos #ifndef GZ_SUFFIX 134*3117ece4Schristos # define GZ_SUFFIX ".gz" 135*3117ece4Schristos #endif 136*3117ece4Schristos #define SUFFIX_LEN (sizeof(GZ_SUFFIX)-1) 137*3117ece4Schristos 138*3117ece4Schristos #define BUFLEN 16384 139*3117ece4Schristos #define MAX_NAME_LEN 1024 140*3117ece4Schristos 141*3117ece4Schristos #ifdef MAXSEG_64K 142*3117ece4Schristos # define local static 143*3117ece4Schristos /* Needed for systems with limitation on stack size. */ 144*3117ece4Schristos #else 145*3117ece4Schristos # define local 146*3117ece4Schristos #endif 147*3117ece4Schristos 148*3117ece4Schristos #ifdef Z_SOLO 149*3117ece4Schristos /* for Z_SOLO, create simplified gz* functions using deflate and inflate */ 150*3117ece4Schristos 151*3117ece4Schristos #if defined(Z_HAVE_UNISTD_H) || defined(Z_LARGE) 152*3117ece4Schristos # include <unistd.h> /* for unlink() */ 153*3117ece4Schristos #endif 154*3117ece4Schristos 155*3117ece4Schristos void *myalloc _Z_OF((void *, unsigned, unsigned)); 156*3117ece4Schristos void myfree _Z_OF((void *, void *)); 157*3117ece4Schristos 158*3117ece4Schristos void *myalloc(q, n, m) 159*3117ece4Schristos void *q; 160*3117ece4Schristos unsigned n, m; 161*3117ece4Schristos { 162*3117ece4Schristos q = Z_NULL; 163*3117ece4Schristos return calloc(n, m); 164*3117ece4Schristos } 165*3117ece4Schristos 166*3117ece4Schristos void myfree(q, p) 167*3117ece4Schristos void *q, *p; 168*3117ece4Schristos { 169*3117ece4Schristos q = Z_NULL; 170*3117ece4Schristos free(p); 171*3117ece4Schristos } 172*3117ece4Schristos 173*3117ece4Schristos typedef struct gzFile_s { 174*3117ece4Schristos FILE *file; 175*3117ece4Schristos int write; 176*3117ece4Schristos int err; 177*3117ece4Schristos char *msg; 178*3117ece4Schristos z_stream strm; 179*3117ece4Schristos } *gzFile; 180*3117ece4Schristos 181*3117ece4Schristos gzFile gzopen _Z_OF((const char *, const char *)); 182*3117ece4Schristos gzFile gzdopen _Z_OF((int, const char *)); 183*3117ece4Schristos gzFile gz_open _Z_OF((const char *, int, const char *)); 184*3117ece4Schristos 185*3117ece4Schristos gzFile gzopen(path, mode) 186*3117ece4Schristos const char *path; 187*3117ece4Schristos const char *mode; 188*3117ece4Schristos { 189*3117ece4Schristos return gz_open(path, -1, mode); 190*3117ece4Schristos } 191*3117ece4Schristos 192*3117ece4Schristos gzFile gzdopen(fd, mode) 193*3117ece4Schristos int fd; 194*3117ece4Schristos const char *mode; 195*3117ece4Schristos { 196*3117ece4Schristos return gz_open(NULL, fd, mode); 197*3117ece4Schristos } 198*3117ece4Schristos 199*3117ece4Schristos gzFile gz_open(const char *path, int fd, const char *mode) { 200*3117ece4Schristos gzFile gz; 201*3117ece4Schristos int ret; 202*3117ece4Schristos 203*3117ece4Schristos gz = malloc(sizeof(struct gzFile_s)); 204*3117ece4Schristos if (gz == NULL) 205*3117ece4Schristos return NULL; 206*3117ece4Schristos gz->write = strchr(mode, 'w') != NULL; 207*3117ece4Schristos gz->strm.zalloc = myalloc; 208*3117ece4Schristos gz->strm.zfree = myfree; 209*3117ece4Schristos gz->strm.opaque = Z_NULL; 210*3117ece4Schristos if (gz->write) 211*3117ece4Schristos ret = deflateInit2(&(gz->strm), -1, 8, 15 + 16, 8, 0); 212*3117ece4Schristos else { 213*3117ece4Schristos gz->strm.next_in = 0; 214*3117ece4Schristos gz->strm.avail_in = Z_NULL; 215*3117ece4Schristos ret = inflateInit2(&(gz->strm), 15 + 16); 216*3117ece4Schristos } 217*3117ece4Schristos if (ret != Z_OK) { 218*3117ece4Schristos free(gz); 219*3117ece4Schristos return NULL; 220*3117ece4Schristos } 221*3117ece4Schristos gz->file = path == NULL ? fdopen(fd, gz->write ? "wb" : "rb") : 222*3117ece4Schristos fopen(path, gz->write ? "wb" : "rb"); 223*3117ece4Schristos if (gz->file == NULL) { 224*3117ece4Schristos gz->write ? deflateEnd(&(gz->strm)) : inflateEnd(&(gz->strm)); 225*3117ece4Schristos free(gz); 226*3117ece4Schristos return NULL; 227*3117ece4Schristos } 228*3117ece4Schristos gz->err = 0; 229*3117ece4Schristos gz->msg = ""; 230*3117ece4Schristos return gz; 231*3117ece4Schristos } 232*3117ece4Schristos 233*3117ece4Schristos int gzwrite _Z_OF((gzFile, const void *, unsigned)); 234*3117ece4Schristos 235*3117ece4Schristos int gzwrite(gzFile gz, const void *buf, unsigned len) { 236*3117ece4Schristos z_stream *strm; 237*3117ece4Schristos unsigned char out[BUFLEN]; 238*3117ece4Schristos 239*3117ece4Schristos if (gz == NULL || !gz->write) 240*3117ece4Schristos return 0; 241*3117ece4Schristos strm = &(gz->strm); 242*3117ece4Schristos strm->next_in = (void *)buf; 243*3117ece4Schristos strm->avail_in = len; 244*3117ece4Schristos do { 245*3117ece4Schristos strm->next_out = out; 246*3117ece4Schristos strm->avail_out = BUFLEN; 247*3117ece4Schristos (void)deflate(strm, Z_NO_FLUSH); 248*3117ece4Schristos fwrite(out, 1, BUFLEN - strm->avail_out, gz->file); 249*3117ece4Schristos } while (strm->avail_out == 0); 250*3117ece4Schristos return len; 251*3117ece4Schristos } 252*3117ece4Schristos 253*3117ece4Schristos int gzread _Z_OF((gzFile, void *, unsigned)); 254*3117ece4Schristos 255*3117ece4Schristos int gzread(gzFile gz, void *buf, unsigned len) { 256*3117ece4Schristos int ret; 257*3117ece4Schristos unsigned got; 258*3117ece4Schristos unsigned char in[1]; 259*3117ece4Schristos z_stream *strm; 260*3117ece4Schristos 261*3117ece4Schristos if (gz == NULL || gz->write) 262*3117ece4Schristos return 0; 263*3117ece4Schristos if (gz->err) 264*3117ece4Schristos return 0; 265*3117ece4Schristos strm = &(gz->strm); 266*3117ece4Schristos strm->next_out = (void *)buf; 267*3117ece4Schristos strm->avail_out = len; 268*3117ece4Schristos do { 269*3117ece4Schristos got = fread(in, 1, 1, gz->file); 270*3117ece4Schristos if (got == 0) 271*3117ece4Schristos break; 272*3117ece4Schristos strm->next_in = in; 273*3117ece4Schristos strm->avail_in = 1; 274*3117ece4Schristos ret = inflate(strm, Z_NO_FLUSH); 275*3117ece4Schristos if (ret == Z_DATA_ERROR) { 276*3117ece4Schristos gz->err = Z_DATA_ERROR; 277*3117ece4Schristos gz->msg = strm->msg; 278*3117ece4Schristos return 0; 279*3117ece4Schristos } 280*3117ece4Schristos if (ret == Z_STREAM_END) 281*3117ece4Schristos inflateReset(strm); 282*3117ece4Schristos } while (strm->avail_out); 283*3117ece4Schristos return len - strm->avail_out; 284*3117ece4Schristos } 285*3117ece4Schristos 286*3117ece4Schristos int gzclose _Z_OF((gzFile)); 287*3117ece4Schristos 288*3117ece4Schristos int gzclose(gzFile gz) { 289*3117ece4Schristos z_stream *strm; 290*3117ece4Schristos unsigned char out[BUFLEN]; 291*3117ece4Schristos 292*3117ece4Schristos if (gz == NULL) 293*3117ece4Schristos return Z_STREAM_ERROR; 294*3117ece4Schristos strm = &(gz->strm); 295*3117ece4Schristos if (gz->write) { 296*3117ece4Schristos strm->next_in = Z_NULL; 297*3117ece4Schristos strm->avail_in = 0; 298*3117ece4Schristos do { 299*3117ece4Schristos strm->next_out = out; 300*3117ece4Schristos strm->avail_out = BUFLEN; 301*3117ece4Schristos (void)deflate(strm, Z_FINISH); 302*3117ece4Schristos fwrite(out, 1, BUFLEN - strm->avail_out, gz->file); 303*3117ece4Schristos } while (strm->avail_out == 0); 304*3117ece4Schristos deflateEnd(strm); 305*3117ece4Schristos } 306*3117ece4Schristos else 307*3117ece4Schristos inflateEnd(strm); 308*3117ece4Schristos fclose(gz->file); 309*3117ece4Schristos free(gz); 310*3117ece4Schristos return Z_OK; 311*3117ece4Schristos } 312*3117ece4Schristos 313*3117ece4Schristos const char *gzerror _Z_OF((gzFile, int *)); 314*3117ece4Schristos 315*3117ece4Schristos const char *gzerror(gzFile gz, int *err) 316*3117ece4Schristos { 317*3117ece4Schristos *err = gz->err; 318*3117ece4Schristos return gz->msg; 319*3117ece4Schristos } 320*3117ece4Schristos 321*3117ece4Schristos #endif 322*3117ece4Schristos 323*3117ece4Schristos char *prog; 324*3117ece4Schristos 325*3117ece4Schristos void error _Z_OF((const char *msg)); 326*3117ece4Schristos void gz_compress _Z_OF((FILE *in, gzFile out)); 327*3117ece4Schristos #ifdef USE_MMAP 328*3117ece4Schristos int gz_compress_mmap _Z_OF((FILE *in, gzFile out)); 329*3117ece4Schristos #endif 330*3117ece4Schristos void gz_uncompress _Z_OF((gzFile in, FILE *out)); 331*3117ece4Schristos void file_compress _Z_OF((char *file, char *mode)); 332*3117ece4Schristos void file_uncompress _Z_OF((char *file)); 333*3117ece4Schristos int main _Z_OF((int argc, char *argv[])); 334*3117ece4Schristos 335*3117ece4Schristos /* =========================================================================== 336*3117ece4Schristos * Display error message and exit 337*3117ece4Schristos */ 338*3117ece4Schristos void error(const char *msg) 339*3117ece4Schristos { 340*3117ece4Schristos fprintf(stderr, "%s: %s\n", prog, msg); 341*3117ece4Schristos exit(1); 342*3117ece4Schristos } 343*3117ece4Schristos 344*3117ece4Schristos /* =========================================================================== 345*3117ece4Schristos * Compress input to output then close both files. 346*3117ece4Schristos */ 347*3117ece4Schristos 348*3117ece4Schristos void gz_compress(FILE *in, gzFile out) 349*3117ece4Schristos { 350*3117ece4Schristos local char buf[BUFLEN]; 351*3117ece4Schristos int len; 352*3117ece4Schristos int err; 353*3117ece4Schristos 354*3117ece4Schristos #ifdef USE_MMAP 355*3117ece4Schristos /* Try first compressing with mmap. If mmap fails (minigzip used in a 356*3117ece4Schristos * pipe), use the normal fread loop. 357*3117ece4Schristos */ 358*3117ece4Schristos if (gz_compress_mmap(in, out) == Z_OK) return; 359*3117ece4Schristos #endif 360*3117ece4Schristos for (;;) { 361*3117ece4Schristos len = (int)fread(buf, 1, sizeof(buf), in); 362*3117ece4Schristos if (ferror(in)) { 363*3117ece4Schristos perror("fread"); 364*3117ece4Schristos exit(1); 365*3117ece4Schristos } 366*3117ece4Schristos if (len == 0) break; 367*3117ece4Schristos 368*3117ece4Schristos if (gzwrite(out, buf, (unsigned)len) != len) error(gzerror(out, &err)); 369*3117ece4Schristos } 370*3117ece4Schristos fclose(in); 371*3117ece4Schristos if (gzclose(out) != Z_OK) error("failed gzclose"); 372*3117ece4Schristos } 373*3117ece4Schristos 374*3117ece4Schristos #ifdef USE_MMAP /* MMAP version, Miguel Albrecht <malbrech@eso.org> */ 375*3117ece4Schristos 376*3117ece4Schristos /* Try compressing the input file at once using mmap. Return Z_OK if 377*3117ece4Schristos * if success, Z_ERRNO otherwise. 378*3117ece4Schristos */ 379*3117ece4Schristos int gz_compress_mmap(FILE *in, gzFile out) { 380*3117ece4Schristos int len; 381*3117ece4Schristos int err; 382*3117ece4Schristos int ifd = fileno(in); 383*3117ece4Schristos caddr_t buf; /* mmap'ed buffer for the entire input file */ 384*3117ece4Schristos off_t buf_len; /* length of the input file */ 385*3117ece4Schristos struct stat sb; 386*3117ece4Schristos 387*3117ece4Schristos /* Determine the size of the file, needed for mmap: */ 388*3117ece4Schristos if (fstat(ifd, &sb) < 0) return Z_ERRNO; 389*3117ece4Schristos buf_len = sb.st_size; 390*3117ece4Schristos if (buf_len <= 0) return Z_ERRNO; 391*3117ece4Schristos 392*3117ece4Schristos /* Now do the actual mmap: */ 393*3117ece4Schristos buf = mmap((caddr_t) 0, buf_len, PROT_READ, MAP_SHARED, ifd, (off_t)0); 394*3117ece4Schristos if (buf == (caddr_t)(-1)) return Z_ERRNO; 395*3117ece4Schristos 396*3117ece4Schristos /* Compress the whole file at once: */ 397*3117ece4Schristos len = gzwrite(out, (char *)buf, (unsigned)buf_len); 398*3117ece4Schristos 399*3117ece4Schristos if (len != (int)buf_len) error(gzerror(out, &err)); 400*3117ece4Schristos 401*3117ece4Schristos munmap(buf, buf_len); 402*3117ece4Schristos fclose(in); 403*3117ece4Schristos if (gzclose(out) != Z_OK) error("failed gzclose"); 404*3117ece4Schristos return Z_OK; 405*3117ece4Schristos } 406*3117ece4Schristos #endif /* USE_MMAP */ 407*3117ece4Schristos 408*3117ece4Schristos /* =========================================================================== 409*3117ece4Schristos * Uncompress input to output then close both files. 410*3117ece4Schristos */ 411*3117ece4Schristos void gz_uncompress(gzFile in, FILE *out) { 412*3117ece4Schristos local char buf[BUFLEN]; 413*3117ece4Schristos int len; 414*3117ece4Schristos int err; 415*3117ece4Schristos 416*3117ece4Schristos for (;;) { 417*3117ece4Schristos len = gzread(in, buf, sizeof(buf)); 418*3117ece4Schristos if (len < 0) error (gzerror(in, &err)); 419*3117ece4Schristos if (len == 0) break; 420*3117ece4Schristos 421*3117ece4Schristos if ((int)fwrite(buf, 1, (unsigned)len, out) != len) { 422*3117ece4Schristos error("failed fwrite"); 423*3117ece4Schristos } 424*3117ece4Schristos } 425*3117ece4Schristos if (fclose(out)) error("failed fclose"); 426*3117ece4Schristos 427*3117ece4Schristos if (gzclose(in) != Z_OK) error("failed gzclose"); 428*3117ece4Schristos } 429*3117ece4Schristos 430*3117ece4Schristos 431*3117ece4Schristos /* =========================================================================== 432*3117ece4Schristos * Compress the given file: create a corresponding .gz file and remove the 433*3117ece4Schristos * original. 434*3117ece4Schristos */ 435*3117ece4Schristos void file_compress(char *file, char *mode) { 436*3117ece4Schristos local char outfile[MAX_NAME_LEN]; 437*3117ece4Schristos FILE *in; 438*3117ece4Schristos gzFile out; 439*3117ece4Schristos 440*3117ece4Schristos if (strlen(file) + strlen(GZ_SUFFIX) >= sizeof(outfile)) { 441*3117ece4Schristos fprintf(stderr, "%s: filename too long\n", prog); 442*3117ece4Schristos exit(1); 443*3117ece4Schristos } 444*3117ece4Schristos 445*3117ece4Schristos strcpy(outfile, file); 446*3117ece4Schristos strcat(outfile, GZ_SUFFIX); 447*3117ece4Schristos 448*3117ece4Schristos in = fopen(file, "rb"); 449*3117ece4Schristos if (in == NULL) { 450*3117ece4Schristos perror(file); 451*3117ece4Schristos exit(1); 452*3117ece4Schristos } 453*3117ece4Schristos out = gzopen(outfile, mode); 454*3117ece4Schristos if (out == NULL) { 455*3117ece4Schristos fprintf(stderr, "%s: can't gzopen %s\n", prog, outfile); 456*3117ece4Schristos exit(1); 457*3117ece4Schristos } 458*3117ece4Schristos gz_compress(in, out); 459*3117ece4Schristos 460*3117ece4Schristos unlink(file); 461*3117ece4Schristos } 462*3117ece4Schristos 463*3117ece4Schristos 464*3117ece4Schristos /* =========================================================================== 465*3117ece4Schristos * Uncompress the given file and remove the original. 466*3117ece4Schristos */ 467*3117ece4Schristos void file_uncompress(char *file) { 468*3117ece4Schristos local char buf[MAX_NAME_LEN]; 469*3117ece4Schristos char *infile, *outfile; 470*3117ece4Schristos FILE *out; 471*3117ece4Schristos gzFile in; 472*3117ece4Schristos size_t len = strlen(file); 473*3117ece4Schristos 474*3117ece4Schristos if (len + strlen(GZ_SUFFIX) >= sizeof(buf)) { 475*3117ece4Schristos fprintf(stderr, "%s: filename too long\n", prog); 476*3117ece4Schristos exit(1); 477*3117ece4Schristos } 478*3117ece4Schristos 479*3117ece4Schristos strcpy(buf, file); 480*3117ece4Schristos 481*3117ece4Schristos if (len > SUFFIX_LEN && strcmp(file+len-SUFFIX_LEN, GZ_SUFFIX) == 0) { 482*3117ece4Schristos infile = file; 483*3117ece4Schristos outfile = buf; 484*3117ece4Schristos outfile[len-3] = '\0'; 485*3117ece4Schristos } else { 486*3117ece4Schristos outfile = file; 487*3117ece4Schristos infile = buf; 488*3117ece4Schristos strcat(infile, GZ_SUFFIX); 489*3117ece4Schristos } 490*3117ece4Schristos in = gzopen(infile, "rb"); 491*3117ece4Schristos if (in == NULL) { 492*3117ece4Schristos fprintf(stderr, "%s: can't gzopen %s\n", prog, infile); 493*3117ece4Schristos exit(1); 494*3117ece4Schristos } 495*3117ece4Schristos out = fopen(outfile, "wb"); 496*3117ece4Schristos if (out == NULL) { 497*3117ece4Schristos perror(file); 498*3117ece4Schristos exit(1); 499*3117ece4Schristos } 500*3117ece4Schristos 501*3117ece4Schristos gz_uncompress(in, out); 502*3117ece4Schristos 503*3117ece4Schristos unlink(infile); 504*3117ece4Schristos } 505*3117ece4Schristos 506*3117ece4Schristos 507*3117ece4Schristos /* =========================================================================== 508*3117ece4Schristos * Usage: minigzip [-c] [-d] [-f] [-h] [-r] [-1 to -9] [files...] 509*3117ece4Schristos * -c : write to standard output 510*3117ece4Schristos * -d : decompress 511*3117ece4Schristos * -f : compress with Z_FILTERED 512*3117ece4Schristos * -h : compress with Z_HUFFMAN_ONLY 513*3117ece4Schristos * -r : compress with Z_RLE 514*3117ece4Schristos * -1 to -9 : compression level 515*3117ece4Schristos */ 516*3117ece4Schristos 517*3117ece4Schristos int main(int argc, char *argv[]) { 518*3117ece4Schristos int copyout = 0; 519*3117ece4Schristos int uncompr = 0; 520*3117ece4Schristos gzFile file; 521*3117ece4Schristos char *bname, outmode[20]; 522*3117ece4Schristos 523*3117ece4Schristos strcpy(outmode, "wb6 "); 524*3117ece4Schristos 525*3117ece4Schristos prog = argv[0]; 526*3117ece4Schristos bname = strrchr(argv[0], '/'); 527*3117ece4Schristos if (bname) 528*3117ece4Schristos bname++; 529*3117ece4Schristos else 530*3117ece4Schristos bname = argv[0]; 531*3117ece4Schristos argc--, argv++; 532*3117ece4Schristos 533*3117ece4Schristos if (!strcmp(bname, "gunzip")) 534*3117ece4Schristos uncompr = 1; 535*3117ece4Schristos else if (!strcmp(bname, "zcat")) 536*3117ece4Schristos copyout = uncompr = 1; 537*3117ece4Schristos 538*3117ece4Schristos while (argc > 0) { 539*3117ece4Schristos if (strcmp(*argv, "-c") == 0) 540*3117ece4Schristos copyout = 1; 541*3117ece4Schristos else if (strcmp(*argv, "-d") == 0) 542*3117ece4Schristos uncompr = 1; 543*3117ece4Schristos else if (strcmp(*argv, "-f") == 0) 544*3117ece4Schristos outmode[3] = 'f'; 545*3117ece4Schristos else if (strcmp(*argv, "-h") == 0) 546*3117ece4Schristos outmode[3] = 'h'; 547*3117ece4Schristos else if (strcmp(*argv, "-r") == 0) 548*3117ece4Schristos outmode[3] = 'R'; 549*3117ece4Schristos else if ((*argv)[0] == '-' && (*argv)[1] >= '1' && (*argv)[1] <= '9' && 550*3117ece4Schristos (*argv)[2] == 0) 551*3117ece4Schristos outmode[2] = (*argv)[1]; 552*3117ece4Schristos else 553*3117ece4Schristos break; 554*3117ece4Schristos argc--, argv++; 555*3117ece4Schristos } 556*3117ece4Schristos if (outmode[3] == ' ') 557*3117ece4Schristos outmode[3] = 0; 558*3117ece4Schristos if (argc == 0) { 559*3117ece4Schristos SET_BINARY_MODE(stdin); 560*3117ece4Schristos SET_BINARY_MODE(stdout); 561*3117ece4Schristos if (uncompr) { 562*3117ece4Schristos file = gzdopen(fileno(stdin), "rb"); 563*3117ece4Schristos if (file == NULL) error("can't gzdopen stdin"); 564*3117ece4Schristos gz_uncompress(file, stdout); 565*3117ece4Schristos } else { 566*3117ece4Schristos file = gzdopen(fileno(stdout), outmode); 567*3117ece4Schristos if (file == NULL) error("can't gzdopen stdout"); 568*3117ece4Schristos gz_compress(stdin, file); 569*3117ece4Schristos } 570*3117ece4Schristos } else { 571*3117ece4Schristos if (copyout) { 572*3117ece4Schristos SET_BINARY_MODE(stdout); 573*3117ece4Schristos } 574*3117ece4Schristos do { 575*3117ece4Schristos if (uncompr) { 576*3117ece4Schristos if (copyout) { 577*3117ece4Schristos file = gzopen(*argv, "rb"); 578*3117ece4Schristos if (file == NULL) 579*3117ece4Schristos fprintf(stderr, "%s: can't gzopen %s\n", prog, *argv); 580*3117ece4Schristos else 581*3117ece4Schristos gz_uncompress(file, stdout); 582*3117ece4Schristos } else { 583*3117ece4Schristos file_uncompress(*argv); 584*3117ece4Schristos } 585*3117ece4Schristos } else { 586*3117ece4Schristos if (copyout) { 587*3117ece4Schristos FILE * in = fopen(*argv, "rb"); 588*3117ece4Schristos 589*3117ece4Schristos if (in == NULL) { 590*3117ece4Schristos perror(*argv); 591*3117ece4Schristos } else { 592*3117ece4Schristos file = gzdopen(fileno(stdout), outmode); 593*3117ece4Schristos if (file == NULL) error("can't gzdopen stdout"); 594*3117ece4Schristos 595*3117ece4Schristos gz_compress(in, file); 596*3117ece4Schristos } 597*3117ece4Schristos 598*3117ece4Schristos } else { 599*3117ece4Schristos file_compress(*argv, outmode); 600*3117ece4Schristos } 601*3117ece4Schristos } 602*3117ece4Schristos } while (argv++, --argc); 603*3117ece4Schristos } 604*3117ece4Schristos return 0; 605*3117ece4Schristos } 606