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