1230837Sdelphij/* minigzip.c -- simulate gzip using the zlib compression library 2230837Sdelphij * Copyright (C) 1995-2006, 2010, 2011 Jean-loup Gailly. 3230837Sdelphij * For conditions of distribution and use, see copyright notice in zlib.h 4230837Sdelphij */ 5230837Sdelphij 6230837Sdelphij/* 7230837Sdelphij * minigzip is a minimal implementation of the gzip utility. This is 8230837Sdelphij * only an example of using zlib and isn't meant to replace the 9230837Sdelphij * full-featured gzip. No attempt is made to deal with file systems 10230837Sdelphij * limiting names to 14 or 8+3 characters, etc... Error checking is 11230837Sdelphij * very limited. So use minigzip only for testing; use gzip for the 12230837Sdelphij * real thing. On MSDOS, use only on file names without extension 13230837Sdelphij * or in pipe mode. 14230837Sdelphij */ 15230837Sdelphij 16230837Sdelphij/* @(#) $Id$ */ 17230837Sdelphij 18230837Sdelphij#include "zlib.h" 19230837Sdelphij#include <stdio.h> 20230837Sdelphij 21230837Sdelphij#ifdef STDC 22230837Sdelphij# include <string.h> 23230837Sdelphij# include <stdlib.h> 24230837Sdelphij#endif 25230837Sdelphij 26230837Sdelphij#ifdef USE_MMAP 27230837Sdelphij# include <sys/types.h> 28230837Sdelphij# include <sys/mman.h> 29230837Sdelphij# include <sys/stat.h> 30230837Sdelphij#endif 31230837Sdelphij 32230837Sdelphij#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__) 33230837Sdelphij# include <fcntl.h> 34230837Sdelphij# include <io.h> 35230837Sdelphij# ifdef UNDER_CE 36230837Sdelphij# include <stdlib.h> 37230837Sdelphij# endif 38230837Sdelphij# define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY) 39230837Sdelphij#else 40230837Sdelphij# define SET_BINARY_MODE(file) 41230837Sdelphij#endif 42230837Sdelphij 43254069Sdelphij#ifdef _MSC_VER 44254069Sdelphij# define snprintf _snprintf 45254069Sdelphij#endif 46254069Sdelphij 47230837Sdelphij#ifdef VMS 48230837Sdelphij# define unlink delete 49230837Sdelphij# define GZ_SUFFIX "-gz" 50230837Sdelphij#endif 51230837Sdelphij#ifdef RISCOS 52230837Sdelphij# define unlink remove 53230837Sdelphij# define GZ_SUFFIX "-gz" 54230837Sdelphij# define fileno(file) file->__file 55230837Sdelphij#endif 56230837Sdelphij#if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os 57230837Sdelphij# include <unix.h> /* for fileno */ 58230837Sdelphij#endif 59230837Sdelphij 60230837Sdelphij#if !defined(Z_HAVE_UNISTD_H) && !defined(_LARGEFILE64_SOURCE) 61230837Sdelphij#ifndef WIN32 /* unlink already in stdio.h for WIN32 */ 62230837Sdelphij extern int unlink OF((const char *)); 63230837Sdelphij#endif 64230837Sdelphij#endif 65230837Sdelphij 66230837Sdelphij#if defined(UNDER_CE) 67230837Sdelphij# include <windows.h> 68230837Sdelphij# define perror(s) pwinerror(s) 69230837Sdelphij 70230837Sdelphij/* Map the Windows error number in ERROR to a locale-dependent error 71230837Sdelphij message string and return a pointer to it. Typically, the values 72230837Sdelphij for ERROR come from GetLastError. 73230837Sdelphij 74230837Sdelphij The string pointed to shall not be modified by the application, 75230837Sdelphij but may be overwritten by a subsequent call to strwinerror 76230837Sdelphij 77230837Sdelphij The strwinerror function does not change the current setting 78230837Sdelphij of GetLastError. */ 79230837Sdelphij 80230837Sdelphijstatic char *strwinerror (error) 81230837Sdelphij DWORD error; 82230837Sdelphij{ 83230837Sdelphij static char buf[1024]; 84230837Sdelphij 85230837Sdelphij wchar_t *msgbuf; 86230837Sdelphij DWORD lasterr = GetLastError(); 87230837Sdelphij DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM 88230837Sdelphij | FORMAT_MESSAGE_ALLOCATE_BUFFER, 89230837Sdelphij NULL, 90230837Sdelphij error, 91230837Sdelphij 0, /* Default language */ 92230837Sdelphij (LPVOID)&msgbuf, 93230837Sdelphij 0, 94230837Sdelphij NULL); 95230837Sdelphij if (chars != 0) { 96230837Sdelphij /* If there is an \r\n appended, zap it. */ 97230837Sdelphij if (chars >= 2 98230837Sdelphij && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') { 99230837Sdelphij chars -= 2; 100230837Sdelphij msgbuf[chars] = 0; 101230837Sdelphij } 102230837Sdelphij 103230837Sdelphij if (chars > sizeof (buf) - 1) { 104230837Sdelphij chars = sizeof (buf) - 1; 105230837Sdelphij msgbuf[chars] = 0; 106230837Sdelphij } 107230837Sdelphij 108230837Sdelphij wcstombs(buf, msgbuf, chars + 1); 109230837Sdelphij LocalFree(msgbuf); 110230837Sdelphij } 111230837Sdelphij else { 112230837Sdelphij sprintf(buf, "unknown win32 error (%ld)", error); 113230837Sdelphij } 114230837Sdelphij 115230837Sdelphij SetLastError(lasterr); 116230837Sdelphij return buf; 117230837Sdelphij} 118230837Sdelphij 119230837Sdelphijstatic void pwinerror (s) 120230837Sdelphij const char *s; 121230837Sdelphij{ 122230837Sdelphij if (s && *s) 123230837Sdelphij fprintf(stderr, "%s: %s\n", s, strwinerror(GetLastError ())); 124230837Sdelphij else 125230837Sdelphij fprintf(stderr, "%s\n", strwinerror(GetLastError ())); 126230837Sdelphij} 127230837Sdelphij 128230837Sdelphij#endif /* UNDER_CE */ 129230837Sdelphij 130230837Sdelphij#ifndef GZ_SUFFIX 131230837Sdelphij# define GZ_SUFFIX ".gz" 132230837Sdelphij#endif 133230837Sdelphij#define SUFFIX_LEN (sizeof(GZ_SUFFIX)-1) 134230837Sdelphij 135230837Sdelphij#define BUFLEN 16384 136230837Sdelphij#define MAX_NAME_LEN 1024 137230837Sdelphij 138230837Sdelphij#ifdef MAXSEG_64K 139230837Sdelphij# define local static 140230837Sdelphij /* Needed for systems with limitation on stack size. */ 141230837Sdelphij#else 142230837Sdelphij# define local 143230837Sdelphij#endif 144230837Sdelphij 145230837Sdelphij#ifdef Z_SOLO 146230837Sdelphij/* for Z_SOLO, create simplified gz* functions using deflate and inflate */ 147230837Sdelphij 148230837Sdelphij#if defined(Z_HAVE_UNISTD_H) || defined(Z_LARGE) 149230837Sdelphij# include <unistd.h> /* for unlink() */ 150230837Sdelphij#endif 151230837Sdelphij 152230837Sdelphijvoid *myalloc OF((void *, unsigned, unsigned)); 153230837Sdelphijvoid myfree OF((void *, void *)); 154230837Sdelphij 155230837Sdelphijvoid *myalloc(q, n, m) 156230837Sdelphij void *q; 157230837Sdelphij unsigned n, m; 158230837Sdelphij{ 159230837Sdelphij q = Z_NULL; 160230837Sdelphij return calloc(n, m); 161230837Sdelphij} 162230837Sdelphij 163230837Sdelphijvoid myfree(q, p) 164230837Sdelphij void *q, *p; 165230837Sdelphij{ 166230837Sdelphij q = Z_NULL; 167230837Sdelphij free(p); 168230837Sdelphij} 169230837Sdelphij 170230837Sdelphijtypedef struct gzFile_s { 171230837Sdelphij FILE *file; 172230837Sdelphij int write; 173230837Sdelphij int err; 174230837Sdelphij char *msg; 175230837Sdelphij z_stream strm; 176230837Sdelphij} *gzFile; 177230837Sdelphij 178230837SdelphijgzFile gzopen OF((const char *, const char *)); 179230837SdelphijgzFile gzdopen OF((int, const char *)); 180230837SdelphijgzFile gz_open OF((const char *, int, const char *)); 181230837Sdelphij 182230837SdelphijgzFile gzopen(path, mode) 183230837Sdelphijconst char *path; 184230837Sdelphijconst char *mode; 185230837Sdelphij{ 186230837Sdelphij return gz_open(path, -1, mode); 187230837Sdelphij} 188230837Sdelphij 189230837SdelphijgzFile gzdopen(fd, mode) 190230837Sdelphijint fd; 191230837Sdelphijconst char *mode; 192230837Sdelphij{ 193230837Sdelphij return gz_open(NULL, fd, mode); 194230837Sdelphij} 195230837Sdelphij 196230837SdelphijgzFile gz_open(path, fd, mode) 197230837Sdelphij const char *path; 198230837Sdelphij int fd; 199230837Sdelphij const char *mode; 200230837Sdelphij{ 201230837Sdelphij gzFile gz; 202230837Sdelphij int ret; 203230837Sdelphij 204237248Sdelphij gz = malloc(sizeof(struct gzFile_s)); 205230837Sdelphij if (gz == NULL) 206230837Sdelphij return NULL; 207230837Sdelphij gz->write = strchr(mode, 'w') != NULL; 208230837Sdelphij gz->strm.zalloc = myalloc; 209230837Sdelphij gz->strm.zfree = myfree; 210230837Sdelphij gz->strm.opaque = Z_NULL; 211230837Sdelphij if (gz->write) 212230837Sdelphij ret = deflateInit2(&(gz->strm), -1, 8, 15 + 16, 8, 0); 213230837Sdelphij else { 214230837Sdelphij gz->strm.next_in = 0; 215230837Sdelphij gz->strm.avail_in = Z_NULL; 216230837Sdelphij ret = inflateInit2(&(gz->strm), 15 + 16); 217230837Sdelphij } 218230837Sdelphij if (ret != Z_OK) { 219230837Sdelphij free(gz); 220230837Sdelphij return NULL; 221230837Sdelphij } 222230837Sdelphij gz->file = path == NULL ? fdopen(fd, gz->write ? "wb" : "rb") : 223230837Sdelphij fopen(path, gz->write ? "wb" : "rb"); 224230837Sdelphij if (gz->file == NULL) { 225230837Sdelphij gz->write ? deflateEnd(&(gz->strm)) : inflateEnd(&(gz->strm)); 226230837Sdelphij free(gz); 227230837Sdelphij return NULL; 228230837Sdelphij } 229230837Sdelphij gz->err = 0; 230230837Sdelphij gz->msg = ""; 231230837Sdelphij return gz; 232230837Sdelphij} 233230837Sdelphij 234230837Sdelphijint gzwrite OF((gzFile, const void *, unsigned)); 235230837Sdelphij 236230837Sdelphijint gzwrite(gz, buf, len) 237230837Sdelphij gzFile gz; 238230837Sdelphij const void *buf; 239230837Sdelphij unsigned len; 240230837Sdelphij{ 241230837Sdelphij z_stream *strm; 242230837Sdelphij unsigned char out[BUFLEN]; 243230837Sdelphij 244230837Sdelphij if (gz == NULL || !gz->write) 245230837Sdelphij return 0; 246230837Sdelphij strm = &(gz->strm); 247230837Sdelphij strm->next_in = (void *)buf; 248230837Sdelphij strm->avail_in = len; 249230837Sdelphij do { 250230837Sdelphij strm->next_out = out; 251230837Sdelphij strm->avail_out = BUFLEN; 252230837Sdelphij (void)deflate(strm, Z_NO_FLUSH); 253230837Sdelphij fwrite(out, 1, BUFLEN - strm->avail_out, gz->file); 254230837Sdelphij } while (strm->avail_out == 0); 255230837Sdelphij return len; 256230837Sdelphij} 257230837Sdelphij 258230837Sdelphijint gzread OF((gzFile, void *, unsigned)); 259230837Sdelphij 260230837Sdelphijint gzread(gz, buf, len) 261230837Sdelphij gzFile gz; 262230837Sdelphij void *buf; 263230837Sdelphij unsigned len; 264230837Sdelphij{ 265230837Sdelphij int ret; 266230837Sdelphij unsigned got; 267230837Sdelphij unsigned char in[1]; 268230837Sdelphij z_stream *strm; 269230837Sdelphij 270230837Sdelphij if (gz == NULL || gz->write) 271230837Sdelphij return 0; 272230837Sdelphij if (gz->err) 273230837Sdelphij return 0; 274230837Sdelphij strm = &(gz->strm); 275230837Sdelphij strm->next_out = (void *)buf; 276230837Sdelphij strm->avail_out = len; 277230837Sdelphij do { 278230837Sdelphij got = fread(in, 1, 1, gz->file); 279230837Sdelphij if (got == 0) 280230837Sdelphij break; 281230837Sdelphij strm->next_in = in; 282230837Sdelphij strm->avail_in = 1; 283230837Sdelphij ret = inflate(strm, Z_NO_FLUSH); 284230837Sdelphij if (ret == Z_DATA_ERROR) { 285230837Sdelphij gz->err = Z_DATA_ERROR; 286230837Sdelphij gz->msg = strm->msg; 287230837Sdelphij return 0; 288230837Sdelphij } 289230837Sdelphij if (ret == Z_STREAM_END) 290230837Sdelphij inflateReset(strm); 291230837Sdelphij } while (strm->avail_out); 292230837Sdelphij return len - strm->avail_out; 293230837Sdelphij} 294230837Sdelphij 295230837Sdelphijint gzclose OF((gzFile)); 296230837Sdelphij 297230837Sdelphijint gzclose(gz) 298230837Sdelphij gzFile gz; 299230837Sdelphij{ 300230837Sdelphij z_stream *strm; 301230837Sdelphij unsigned char out[BUFLEN]; 302230837Sdelphij 303230837Sdelphij if (gz == NULL) 304230837Sdelphij return Z_STREAM_ERROR; 305230837Sdelphij strm = &(gz->strm); 306230837Sdelphij if (gz->write) { 307230837Sdelphij strm->next_in = Z_NULL; 308230837Sdelphij strm->avail_in = 0; 309230837Sdelphij do { 310230837Sdelphij strm->next_out = out; 311230837Sdelphij strm->avail_out = BUFLEN; 312230837Sdelphij (void)deflate(strm, Z_FINISH); 313230837Sdelphij fwrite(out, 1, BUFLEN - strm->avail_out, gz->file); 314230837Sdelphij } while (strm->avail_out == 0); 315230837Sdelphij deflateEnd(strm); 316230837Sdelphij } 317230837Sdelphij else 318230837Sdelphij inflateEnd(strm); 319230837Sdelphij fclose(gz->file); 320230837Sdelphij free(gz); 321230837Sdelphij return Z_OK; 322230837Sdelphij} 323230837Sdelphij 324230837Sdelphijconst char *gzerror OF((gzFile, int *)); 325230837Sdelphij 326230837Sdelphijconst char *gzerror(gz, err) 327230837Sdelphij gzFile gz; 328230837Sdelphij int *err; 329230837Sdelphij{ 330230837Sdelphij *err = gz->err; 331230837Sdelphij return gz->msg; 332230837Sdelphij} 333230837Sdelphij 334230837Sdelphij#endif 335230837Sdelphij 336230837Sdelphijchar *prog; 337230837Sdelphij 338230837Sdelphijvoid error OF((const char *msg)); 339230837Sdelphijvoid gz_compress OF((FILE *in, gzFile out)); 340230837Sdelphij#ifdef USE_MMAP 341230837Sdelphijint gz_compress_mmap OF((FILE *in, gzFile out)); 342230837Sdelphij#endif 343230837Sdelphijvoid gz_uncompress OF((gzFile in, FILE *out)); 344230837Sdelphijvoid file_compress OF((char *file, char *mode)); 345230837Sdelphijvoid file_uncompress OF((char *file)); 346230837Sdelphijint main OF((int argc, char *argv[])); 347230837Sdelphij 348230837Sdelphij/* =========================================================================== 349230837Sdelphij * Display error message and exit 350230837Sdelphij */ 351230837Sdelphijvoid error(msg) 352230837Sdelphij const char *msg; 353230837Sdelphij{ 354230837Sdelphij fprintf(stderr, "%s: %s\n", prog, msg); 355230837Sdelphij exit(1); 356230837Sdelphij} 357230837Sdelphij 358230837Sdelphij/* =========================================================================== 359230837Sdelphij * Compress input to output then close both files. 360230837Sdelphij */ 361230837Sdelphij 362230837Sdelphijvoid gz_compress(in, out) 363230837Sdelphij FILE *in; 364230837Sdelphij gzFile out; 365230837Sdelphij{ 366230837Sdelphij local char buf[BUFLEN]; 367230837Sdelphij int len; 368230837Sdelphij int err; 369230837Sdelphij 370230837Sdelphij#ifdef USE_MMAP 371230837Sdelphij /* Try first compressing with mmap. If mmap fails (minigzip used in a 372230837Sdelphij * pipe), use the normal fread loop. 373230837Sdelphij */ 374230837Sdelphij if (gz_compress_mmap(in, out) == Z_OK) return; 375230837Sdelphij#endif 376230837Sdelphij for (;;) { 377230837Sdelphij len = (int)fread(buf, 1, sizeof(buf), in); 378230837Sdelphij if (ferror(in)) { 379230837Sdelphij perror("fread"); 380230837Sdelphij exit(1); 381230837Sdelphij } 382230837Sdelphij if (len == 0) break; 383230837Sdelphij 384230837Sdelphij if (gzwrite(out, buf, (unsigned)len) != len) error(gzerror(out, &err)); 385230837Sdelphij } 386230837Sdelphij fclose(in); 387230837Sdelphij if (gzclose(out) != Z_OK) error("failed gzclose"); 388230837Sdelphij} 389230837Sdelphij 390230837Sdelphij#ifdef USE_MMAP /* MMAP version, Miguel Albrecht <malbrech@eso.org> */ 391230837Sdelphij 392230837Sdelphij/* Try compressing the input file at once using mmap. Return Z_OK if 393230837Sdelphij * if success, Z_ERRNO otherwise. 394230837Sdelphij */ 395230837Sdelphijint gz_compress_mmap(in, out) 396230837Sdelphij FILE *in; 397230837Sdelphij gzFile out; 398230837Sdelphij{ 399230837Sdelphij int len; 400230837Sdelphij int err; 401230837Sdelphij int ifd = fileno(in); 402230837Sdelphij caddr_t buf; /* mmap'ed buffer for the entire input file */ 403230837Sdelphij off_t buf_len; /* length of the input file */ 404230837Sdelphij struct stat sb; 405230837Sdelphij 406230837Sdelphij /* Determine the size of the file, needed for mmap: */ 407230837Sdelphij if (fstat(ifd, &sb) < 0) return Z_ERRNO; 408230837Sdelphij buf_len = sb.st_size; 409230837Sdelphij if (buf_len <= 0) return Z_ERRNO; 410230837Sdelphij 411230837Sdelphij /* Now do the actual mmap: */ 412230837Sdelphij buf = mmap((caddr_t) 0, buf_len, PROT_READ, MAP_SHARED, ifd, (off_t)0); 413230837Sdelphij if (buf == (caddr_t)(-1)) return Z_ERRNO; 414230837Sdelphij 415230837Sdelphij /* Compress the whole file at once: */ 416230837Sdelphij len = gzwrite(out, (char *)buf, (unsigned)buf_len); 417230837Sdelphij 418230837Sdelphij if (len != (int)buf_len) error(gzerror(out, &err)); 419230837Sdelphij 420230837Sdelphij munmap(buf, buf_len); 421230837Sdelphij fclose(in); 422230837Sdelphij if (gzclose(out) != Z_OK) error("failed gzclose"); 423230837Sdelphij return Z_OK; 424230837Sdelphij} 425230837Sdelphij#endif /* USE_MMAP */ 426230837Sdelphij 427230837Sdelphij/* =========================================================================== 428230837Sdelphij * Uncompress input to output then close both files. 429230837Sdelphij */ 430230837Sdelphijvoid gz_uncompress(in, out) 431230837Sdelphij gzFile in; 432230837Sdelphij FILE *out; 433230837Sdelphij{ 434230837Sdelphij local char buf[BUFLEN]; 435230837Sdelphij int len; 436230837Sdelphij int err; 437230837Sdelphij 438230837Sdelphij for (;;) { 439230837Sdelphij len = gzread(in, buf, sizeof(buf)); 440230837Sdelphij if (len < 0) error (gzerror(in, &err)); 441230837Sdelphij if (len == 0) break; 442230837Sdelphij 443230837Sdelphij if ((int)fwrite(buf, 1, (unsigned)len, out) != len) { 444230837Sdelphij error("failed fwrite"); 445230837Sdelphij } 446230837Sdelphij } 447230837Sdelphij if (fclose(out)) error("failed fclose"); 448230837Sdelphij 449230837Sdelphij if (gzclose(in) != Z_OK) error("failed gzclose"); 450230837Sdelphij} 451230837Sdelphij 452230837Sdelphij 453230837Sdelphij/* =========================================================================== 454230837Sdelphij * Compress the given file: create a corresponding .gz file and remove the 455230837Sdelphij * original. 456230837Sdelphij */ 457230837Sdelphijvoid file_compress(file, mode) 458230837Sdelphij char *file; 459230837Sdelphij char *mode; 460230837Sdelphij{ 461230837Sdelphij local char outfile[MAX_NAME_LEN]; 462230837Sdelphij FILE *in; 463230837Sdelphij gzFile out; 464230837Sdelphij 465230837Sdelphij if (strlen(file) + strlen(GZ_SUFFIX) >= sizeof(outfile)) { 466230837Sdelphij fprintf(stderr, "%s: filename too long\n", prog); 467230837Sdelphij exit(1); 468230837Sdelphij } 469230837Sdelphij 470254069Sdelphij#if !defined(NO_snprintf) && !defined(NO_vsnprintf) 471254069Sdelphij snprintf(outfile, sizeof(outfile), "%s%s", file, GZ_SUFFIX); 472254069Sdelphij#else 473230837Sdelphij strcpy(outfile, file); 474230837Sdelphij strcat(outfile, GZ_SUFFIX); 475254069Sdelphij#endif 476230837Sdelphij 477230837Sdelphij in = fopen(file, "rb"); 478230837Sdelphij if (in == NULL) { 479230837Sdelphij perror(file); 480230837Sdelphij exit(1); 481230837Sdelphij } 482230837Sdelphij out = gzopen(outfile, mode); 483230837Sdelphij if (out == NULL) { 484230837Sdelphij fprintf(stderr, "%s: can't gzopen %s\n", prog, outfile); 485230837Sdelphij exit(1); 486230837Sdelphij } 487230837Sdelphij gz_compress(in, out); 488230837Sdelphij 489230837Sdelphij unlink(file); 490230837Sdelphij} 491230837Sdelphij 492230837Sdelphij 493230837Sdelphij/* =========================================================================== 494230837Sdelphij * Uncompress the given file and remove the original. 495230837Sdelphij */ 496230837Sdelphijvoid file_uncompress(file) 497230837Sdelphij char *file; 498230837Sdelphij{ 499230837Sdelphij local char buf[MAX_NAME_LEN]; 500230837Sdelphij char *infile, *outfile; 501230837Sdelphij FILE *out; 502230837Sdelphij gzFile in; 503230837Sdelphij size_t len = strlen(file); 504230837Sdelphij 505230837Sdelphij if (len + strlen(GZ_SUFFIX) >= sizeof(buf)) { 506230837Sdelphij fprintf(stderr, "%s: filename too long\n", prog); 507230837Sdelphij exit(1); 508230837Sdelphij } 509230837Sdelphij 510254069Sdelphij#if !defined(NO_snprintf) && !defined(NO_vsnprintf) 511254069Sdelphij snprintf(buf, sizeof(buf), "%s", file); 512254069Sdelphij#else 513230837Sdelphij strcpy(buf, file); 514254069Sdelphij#endif 515230837Sdelphij 516230837Sdelphij if (len > SUFFIX_LEN && strcmp(file+len-SUFFIX_LEN, GZ_SUFFIX) == 0) { 517230837Sdelphij infile = file; 518230837Sdelphij outfile = buf; 519230837Sdelphij outfile[len-3] = '\0'; 520230837Sdelphij } else { 521230837Sdelphij outfile = file; 522230837Sdelphij infile = buf; 523254069Sdelphij#if !defined(NO_snprintf) && !defined(NO_vsnprintf) 524254069Sdelphij snprintf(buf + len, sizeof(buf) - len, "%s", GZ_SUFFIX); 525254069Sdelphij#else 526230837Sdelphij strcat(infile, GZ_SUFFIX); 527254069Sdelphij#endif 528230837Sdelphij } 529230837Sdelphij in = gzopen(infile, "rb"); 530230837Sdelphij if (in == NULL) { 531230837Sdelphij fprintf(stderr, "%s: can't gzopen %s\n", prog, infile); 532230837Sdelphij exit(1); 533230837Sdelphij } 534230837Sdelphij out = fopen(outfile, "wb"); 535230837Sdelphij if (out == NULL) { 536230837Sdelphij perror(file); 537230837Sdelphij exit(1); 538230837Sdelphij } 539230837Sdelphij 540230837Sdelphij gz_uncompress(in, out); 541230837Sdelphij 542230837Sdelphij unlink(infile); 543230837Sdelphij} 544230837Sdelphij 545230837Sdelphij 546230837Sdelphij/* =========================================================================== 547230837Sdelphij * Usage: minigzip [-c] [-d] [-f] [-h] [-r] [-1 to -9] [files...] 548230837Sdelphij * -c : write to standard output 549230837Sdelphij * -d : decompress 550230837Sdelphij * -f : compress with Z_FILTERED 551230837Sdelphij * -h : compress with Z_HUFFMAN_ONLY 552230837Sdelphij * -r : compress with Z_RLE 553230837Sdelphij * -1 to -9 : compression level 554230837Sdelphij */ 555230837Sdelphij 556230837Sdelphijint main(argc, argv) 557230837Sdelphij int argc; 558230837Sdelphij char *argv[]; 559230837Sdelphij{ 560230837Sdelphij int copyout = 0; 561230837Sdelphij int uncompr = 0; 562230837Sdelphij gzFile file; 563230837Sdelphij char *bname, outmode[20]; 564230837Sdelphij 565254069Sdelphij#if !defined(NO_snprintf) && !defined(NO_vsnprintf) 566254069Sdelphij snprintf(outmode, sizeof(outmode), "%s", "wb6 "); 567254069Sdelphij#else 568230837Sdelphij strcpy(outmode, "wb6 "); 569254069Sdelphij#endif 570230837Sdelphij 571230837Sdelphij prog = argv[0]; 572230837Sdelphij bname = strrchr(argv[0], '/'); 573230837Sdelphij if (bname) 574230837Sdelphij bname++; 575230837Sdelphij else 576230837Sdelphij bname = argv[0]; 577230837Sdelphij argc--, argv++; 578230837Sdelphij 579230837Sdelphij if (!strcmp(bname, "gunzip")) 580230837Sdelphij uncompr = 1; 581230837Sdelphij else if (!strcmp(bname, "zcat")) 582230837Sdelphij copyout = uncompr = 1; 583230837Sdelphij 584230837Sdelphij while (argc > 0) { 585230837Sdelphij if (strcmp(*argv, "-c") == 0) 586230837Sdelphij copyout = 1; 587230837Sdelphij else if (strcmp(*argv, "-d") == 0) 588230837Sdelphij uncompr = 1; 589230837Sdelphij else if (strcmp(*argv, "-f") == 0) 590230837Sdelphij outmode[3] = 'f'; 591230837Sdelphij else if (strcmp(*argv, "-h") == 0) 592230837Sdelphij outmode[3] = 'h'; 593230837Sdelphij else if (strcmp(*argv, "-r") == 0) 594230837Sdelphij outmode[3] = 'R'; 595230837Sdelphij else if ((*argv)[0] == '-' && (*argv)[1] >= '1' && (*argv)[1] <= '9' && 596230837Sdelphij (*argv)[2] == 0) 597230837Sdelphij outmode[2] = (*argv)[1]; 598230837Sdelphij else 599230837Sdelphij break; 600230837Sdelphij argc--, argv++; 601230837Sdelphij } 602230837Sdelphij if (outmode[3] == ' ') 603230837Sdelphij outmode[3] = 0; 604230837Sdelphij if (argc == 0) { 605230837Sdelphij SET_BINARY_MODE(stdin); 606230837Sdelphij SET_BINARY_MODE(stdout); 607230837Sdelphij if (uncompr) { 608230837Sdelphij file = gzdopen(fileno(stdin), "rb"); 609230837Sdelphij if (file == NULL) error("can't gzdopen stdin"); 610230837Sdelphij gz_uncompress(file, stdout); 611230837Sdelphij } else { 612230837Sdelphij file = gzdopen(fileno(stdout), outmode); 613230837Sdelphij if (file == NULL) error("can't gzdopen stdout"); 614230837Sdelphij gz_compress(stdin, file); 615230837Sdelphij } 616230837Sdelphij } else { 617230837Sdelphij if (copyout) { 618230837Sdelphij SET_BINARY_MODE(stdout); 619230837Sdelphij } 620230837Sdelphij do { 621230837Sdelphij if (uncompr) { 622230837Sdelphij if (copyout) { 623230837Sdelphij file = gzopen(*argv, "rb"); 624230837Sdelphij if (file == NULL) 625230837Sdelphij fprintf(stderr, "%s: can't gzopen %s\n", prog, *argv); 626230837Sdelphij else 627230837Sdelphij gz_uncompress(file, stdout); 628230837Sdelphij } else { 629230837Sdelphij file_uncompress(*argv); 630230837Sdelphij } 631230837Sdelphij } else { 632230837Sdelphij if (copyout) { 633230837Sdelphij FILE * in = fopen(*argv, "rb"); 634230837Sdelphij 635230837Sdelphij if (in == NULL) { 636230837Sdelphij perror(*argv); 637230837Sdelphij } else { 638230837Sdelphij file = gzdopen(fileno(stdout), outmode); 639230837Sdelphij if (file == NULL) error("can't gzdopen stdout"); 640230837Sdelphij 641230837Sdelphij gz_compress(in, file); 642230837Sdelphij } 643230837Sdelphij 644230837Sdelphij } else { 645230837Sdelphij file_compress(*argv, outmode); 646230837Sdelphij } 647230837Sdelphij } 648230837Sdelphij } while (argv++, --argc); 649230837Sdelphij } 650230837Sdelphij return 0; 651230837Sdelphij} 652