1275793eaSopenharmony_ci/* minigzip.c -- simulate gzip using the zlib compression library 2275793eaSopenharmony_ci * Copyright (C) 1995-2006, 2010, 2011, 2016 Jean-loup Gailly 3275793eaSopenharmony_ci * For conditions of distribution and use, see copyright notice in zlib.h 4275793eaSopenharmony_ci */ 5275793eaSopenharmony_ci 6275793eaSopenharmony_ci/* 7275793eaSopenharmony_ci * minigzip is a minimal implementation of the gzip utility. This is 8275793eaSopenharmony_ci * only an example of using zlib and isn't meant to replace the 9275793eaSopenharmony_ci * full-featured gzip. No attempt is made to deal with file systems 10275793eaSopenharmony_ci * limiting names to 14 or 8+3 characters, etc... Error checking is 11275793eaSopenharmony_ci * very limited. So use minigzip only for testing; use gzip for the 12275793eaSopenharmony_ci * real thing. On MSDOS, use only on file names without extension 13275793eaSopenharmony_ci * or in pipe mode. 14275793eaSopenharmony_ci */ 15275793eaSopenharmony_ci 16275793eaSopenharmony_ci/* @(#) $Id$ */ 17275793eaSopenharmony_ci 18275793eaSopenharmony_ci#include "zlib.h" 19275793eaSopenharmony_ci#include <stdio.h> 20275793eaSopenharmony_ci 21275793eaSopenharmony_ci#ifdef STDC 22275793eaSopenharmony_ci# include <string.h> 23275793eaSopenharmony_ci# include <stdlib.h> 24275793eaSopenharmony_ci#endif 25275793eaSopenharmony_ci 26275793eaSopenharmony_ci#ifdef USE_MMAP 27275793eaSopenharmony_ci# include <sys/types.h> 28275793eaSopenharmony_ci# include <sys/mman.h> 29275793eaSopenharmony_ci# include <sys/stat.h> 30275793eaSopenharmony_ci#endif 31275793eaSopenharmony_ci 32275793eaSopenharmony_ci#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__) 33275793eaSopenharmony_ci# include <fcntl.h> 34275793eaSopenharmony_ci# include <io.h> 35275793eaSopenharmony_ci# ifdef UNDER_CE 36275793eaSopenharmony_ci# include <stdlib.h> 37275793eaSopenharmony_ci# endif 38275793eaSopenharmony_ci# define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY) 39275793eaSopenharmony_ci#else 40275793eaSopenharmony_ci# define SET_BINARY_MODE(file) 41275793eaSopenharmony_ci#endif 42275793eaSopenharmony_ci 43275793eaSopenharmony_ci#if defined(_MSC_VER) && _MSC_VER < 1900 44275793eaSopenharmony_ci# define snprintf _snprintf 45275793eaSopenharmony_ci#endif 46275793eaSopenharmony_ci 47275793eaSopenharmony_ci#ifdef VMS 48275793eaSopenharmony_ci# define unlink delete 49275793eaSopenharmony_ci# define GZ_SUFFIX "-gz" 50275793eaSopenharmony_ci#endif 51275793eaSopenharmony_ci#ifdef RISCOS 52275793eaSopenharmony_ci# define unlink remove 53275793eaSopenharmony_ci# define GZ_SUFFIX "-gz" 54275793eaSopenharmony_ci# define fileno(file) file->__file 55275793eaSopenharmony_ci#endif 56275793eaSopenharmony_ci#if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os 57275793eaSopenharmony_ci# include <unix.h> /* for fileno */ 58275793eaSopenharmony_ci#endif 59275793eaSopenharmony_ci 60275793eaSopenharmony_ci#if !defined(Z_HAVE_UNISTD_H) && !defined(_LARGEFILE64_SOURCE) 61275793eaSopenharmony_ci#ifndef WIN32 /* unlink already in stdio.h for WIN32 */ 62275793eaSopenharmony_ci extern int unlink(const char *); 63275793eaSopenharmony_ci#endif 64275793eaSopenharmony_ci#endif 65275793eaSopenharmony_ci 66275793eaSopenharmony_ci#if defined(UNDER_CE) 67275793eaSopenharmony_ci# include <windows.h> 68275793eaSopenharmony_ci# define perror(s) pwinerror(s) 69275793eaSopenharmony_ci 70275793eaSopenharmony_ci/* Map the Windows error number in ERROR to a locale-dependent error 71275793eaSopenharmony_ci message string and return a pointer to it. Typically, the values 72275793eaSopenharmony_ci for ERROR come from GetLastError. 73275793eaSopenharmony_ci 74275793eaSopenharmony_ci The string pointed to shall not be modified by the application, 75275793eaSopenharmony_ci but may be overwritten by a subsequent call to strwinerror 76275793eaSopenharmony_ci 77275793eaSopenharmony_ci The strwinerror function does not change the current setting 78275793eaSopenharmony_ci of GetLastError. */ 79275793eaSopenharmony_ci 80275793eaSopenharmony_cistatic char *strwinerror (error) 81275793eaSopenharmony_ci DWORD error; 82275793eaSopenharmony_ci{ 83275793eaSopenharmony_ci static char buf[1024]; 84275793eaSopenharmony_ci 85275793eaSopenharmony_ci wchar_t *msgbuf; 86275793eaSopenharmony_ci DWORD lasterr = GetLastError(); 87275793eaSopenharmony_ci DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM 88275793eaSopenharmony_ci | FORMAT_MESSAGE_ALLOCATE_BUFFER, 89275793eaSopenharmony_ci NULL, 90275793eaSopenharmony_ci error, 91275793eaSopenharmony_ci 0, /* Default language */ 92275793eaSopenharmony_ci (LPVOID)&msgbuf, 93275793eaSopenharmony_ci 0, 94275793eaSopenharmony_ci NULL); 95275793eaSopenharmony_ci if (chars != 0) { 96275793eaSopenharmony_ci /* If there is an \r\n appended, zap it. */ 97275793eaSopenharmony_ci if (chars >= 2 98275793eaSopenharmony_ci && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') { 99275793eaSopenharmony_ci chars -= 2; 100275793eaSopenharmony_ci msgbuf[chars] = 0; 101275793eaSopenharmony_ci } 102275793eaSopenharmony_ci 103275793eaSopenharmony_ci if (chars > sizeof (buf) - 1) { 104275793eaSopenharmony_ci chars = sizeof (buf) - 1; 105275793eaSopenharmony_ci msgbuf[chars] = 0; 106275793eaSopenharmony_ci } 107275793eaSopenharmony_ci 108275793eaSopenharmony_ci wcstombs(buf, msgbuf, chars + 1); 109275793eaSopenharmony_ci LocalFree(msgbuf); 110275793eaSopenharmony_ci } 111275793eaSopenharmony_ci else { 112275793eaSopenharmony_ci sprintf(buf, "unknown win32 error (%ld)", error); 113275793eaSopenharmony_ci } 114275793eaSopenharmony_ci 115275793eaSopenharmony_ci SetLastError(lasterr); 116275793eaSopenharmony_ci return buf; 117275793eaSopenharmony_ci} 118275793eaSopenharmony_ci 119275793eaSopenharmony_cistatic void pwinerror (s) 120275793eaSopenharmony_ci const char *s; 121275793eaSopenharmony_ci{ 122275793eaSopenharmony_ci if (s && *s) 123275793eaSopenharmony_ci fprintf(stderr, "%s: %s\n", s, strwinerror(GetLastError ())); 124275793eaSopenharmony_ci else 125275793eaSopenharmony_ci fprintf(stderr, "%s\n", strwinerror(GetLastError ())); 126275793eaSopenharmony_ci} 127275793eaSopenharmony_ci 128275793eaSopenharmony_ci#endif /* UNDER_CE */ 129275793eaSopenharmony_ci 130275793eaSopenharmony_ci#ifndef GZ_SUFFIX 131275793eaSopenharmony_ci# define GZ_SUFFIX ".gz" 132275793eaSopenharmony_ci#endif 133275793eaSopenharmony_ci#define SUFFIX_LEN (sizeof(GZ_SUFFIX)-1) 134275793eaSopenharmony_ci 135275793eaSopenharmony_ci#define BUFLEN 16384 136275793eaSopenharmony_ci#define MAX_NAME_LEN 1024 137275793eaSopenharmony_ci 138275793eaSopenharmony_ci#ifdef MAXSEG_64K 139275793eaSopenharmony_ci# define local static 140275793eaSopenharmony_ci /* Needed for systems with limitation on stack size. */ 141275793eaSopenharmony_ci#else 142275793eaSopenharmony_ci# define local 143275793eaSopenharmony_ci#endif 144275793eaSopenharmony_ci 145275793eaSopenharmony_ci#ifdef Z_SOLO 146275793eaSopenharmony_ci/* for Z_SOLO, create simplified gz* functions using deflate and inflate */ 147275793eaSopenharmony_ci 148275793eaSopenharmony_ci#if defined(Z_HAVE_UNISTD_H) || defined(Z_LARGE) 149275793eaSopenharmony_ci# include <unistd.h> /* for unlink() */ 150275793eaSopenharmony_ci#endif 151275793eaSopenharmony_ci 152275793eaSopenharmony_cistatic void *myalloc(void *q, unsigned n, unsigned m) 153275793eaSopenharmony_ci{ 154275793eaSopenharmony_ci (void)q; 155275793eaSopenharmony_ci return calloc(n, m); 156275793eaSopenharmony_ci} 157275793eaSopenharmony_ci 158275793eaSopenharmony_cistatic void myfree(void *q, void *p) 159275793eaSopenharmony_ci{ 160275793eaSopenharmony_ci (void)q; 161275793eaSopenharmony_ci free(p); 162275793eaSopenharmony_ci} 163275793eaSopenharmony_ci 164275793eaSopenharmony_citypedef struct gzFile_s { 165275793eaSopenharmony_ci FILE *file; 166275793eaSopenharmony_ci int write; 167275793eaSopenharmony_ci int err; 168275793eaSopenharmony_ci char *msg; 169275793eaSopenharmony_ci z_stream strm; 170275793eaSopenharmony_ci} *gzFile; 171275793eaSopenharmony_ci 172275793eaSopenharmony_cistatic gzFile gz_open(const char *path, int fd, const char *mode) 173275793eaSopenharmony_ci{ 174275793eaSopenharmony_ci gzFile gz; 175275793eaSopenharmony_ci int ret; 176275793eaSopenharmony_ci 177275793eaSopenharmony_ci gz = malloc(sizeof(struct gzFile_s)); 178275793eaSopenharmony_ci if (gz == NULL) 179275793eaSopenharmony_ci return NULL; 180275793eaSopenharmony_ci gz->write = strchr(mode, 'w') != NULL; 181275793eaSopenharmony_ci gz->strm.zalloc = myalloc; 182275793eaSopenharmony_ci gz->strm.zfree = myfree; 183275793eaSopenharmony_ci gz->strm.opaque = Z_NULL; 184275793eaSopenharmony_ci if (gz->write) 185275793eaSopenharmony_ci ret = deflateInit2(&(gz->strm), -1, 8, 15 + 16, 8, 0); 186275793eaSopenharmony_ci else { 187275793eaSopenharmony_ci gz->strm.next_in = 0; 188275793eaSopenharmony_ci gz->strm.avail_in = Z_NULL; 189275793eaSopenharmony_ci ret = inflateInit2(&(gz->strm), 15 + 16); 190275793eaSopenharmony_ci } 191275793eaSopenharmony_ci if (ret != Z_OK) { 192275793eaSopenharmony_ci free(gz); 193275793eaSopenharmony_ci return NULL; 194275793eaSopenharmony_ci } 195275793eaSopenharmony_ci gz->file = path == NULL ? fdopen(fd, gz->write ? "wb" : "rb") : 196275793eaSopenharmony_ci fopen(path, gz->write ? "wb" : "rb"); 197275793eaSopenharmony_ci if (gz->file == NULL) { 198275793eaSopenharmony_ci gz->write ? deflateEnd(&(gz->strm)) : inflateEnd(&(gz->strm)); 199275793eaSopenharmony_ci free(gz); 200275793eaSopenharmony_ci return NULL; 201275793eaSopenharmony_ci } 202275793eaSopenharmony_ci gz->err = 0; 203275793eaSopenharmony_ci gz->msg = ""; 204275793eaSopenharmony_ci return gz; 205275793eaSopenharmony_ci} 206275793eaSopenharmony_ci 207275793eaSopenharmony_cistatic gzFile gzopen(const char *path, const char *mode) 208275793eaSopenharmony_ci{ 209275793eaSopenharmony_ci return gz_open(path, -1, mode); 210275793eaSopenharmony_ci} 211275793eaSopenharmony_ci 212275793eaSopenharmony_cistatic gzFile gzdopen(int fd, const char *mode) 213275793eaSopenharmony_ci{ 214275793eaSopenharmony_ci return gz_open(NULL, fd, mode); 215275793eaSopenharmony_ci} 216275793eaSopenharmony_ci 217275793eaSopenharmony_cistatic int gzwrite(gzFile gz, const void *buf, unsigned len) 218275793eaSopenharmony_ci{ 219275793eaSopenharmony_ci z_stream *strm; 220275793eaSopenharmony_ci unsigned char out[BUFLEN]; 221275793eaSopenharmony_ci 222275793eaSopenharmony_ci if (gz == NULL || !gz->write) 223275793eaSopenharmony_ci return 0; 224275793eaSopenharmony_ci strm = &(gz->strm); 225275793eaSopenharmony_ci strm->next_in = (void *)buf; 226275793eaSopenharmony_ci strm->avail_in = len; 227275793eaSopenharmony_ci do { 228275793eaSopenharmony_ci strm->next_out = out; 229275793eaSopenharmony_ci strm->avail_out = BUFLEN; 230275793eaSopenharmony_ci (void)deflate(strm, Z_NO_FLUSH); 231275793eaSopenharmony_ci fwrite(out, 1, BUFLEN - strm->avail_out, gz->file); 232275793eaSopenharmony_ci } while (strm->avail_out == 0); 233275793eaSopenharmony_ci return len; 234275793eaSopenharmony_ci} 235275793eaSopenharmony_ci 236275793eaSopenharmony_cistatic int gzread(gzFile gz, void *buf, unsigned len) 237275793eaSopenharmony_ci{ 238275793eaSopenharmony_ci int ret; 239275793eaSopenharmony_ci unsigned got; 240275793eaSopenharmony_ci unsigned char in[1]; 241275793eaSopenharmony_ci z_stream *strm; 242275793eaSopenharmony_ci 243275793eaSopenharmony_ci if (gz == NULL || gz->write) 244275793eaSopenharmony_ci return 0; 245275793eaSopenharmony_ci if (gz->err) 246275793eaSopenharmony_ci return 0; 247275793eaSopenharmony_ci strm = &(gz->strm); 248275793eaSopenharmony_ci strm->next_out = (void *)buf; 249275793eaSopenharmony_ci strm->avail_out = len; 250275793eaSopenharmony_ci do { 251275793eaSopenharmony_ci got = fread(in, 1, 1, gz->file); 252275793eaSopenharmony_ci if (got == 0) 253275793eaSopenharmony_ci break; 254275793eaSopenharmony_ci strm->next_in = in; 255275793eaSopenharmony_ci strm->avail_in = 1; 256275793eaSopenharmony_ci ret = inflate(strm, Z_NO_FLUSH); 257275793eaSopenharmony_ci if (ret == Z_DATA_ERROR) { 258275793eaSopenharmony_ci gz->err = Z_DATA_ERROR; 259275793eaSopenharmony_ci gz->msg = strm->msg; 260275793eaSopenharmony_ci return 0; 261275793eaSopenharmony_ci } 262275793eaSopenharmony_ci if (ret == Z_STREAM_END) 263275793eaSopenharmony_ci inflateReset(strm); 264275793eaSopenharmony_ci } while (strm->avail_out); 265275793eaSopenharmony_ci return len - strm->avail_out; 266275793eaSopenharmony_ci} 267275793eaSopenharmony_ci 268275793eaSopenharmony_cistatic int gzclose(gzFile gz) 269275793eaSopenharmony_ci{ 270275793eaSopenharmony_ci z_stream *strm; 271275793eaSopenharmony_ci unsigned char out[BUFLEN]; 272275793eaSopenharmony_ci 273275793eaSopenharmony_ci if (gz == NULL) 274275793eaSopenharmony_ci return Z_STREAM_ERROR; 275275793eaSopenharmony_ci strm = &(gz->strm); 276275793eaSopenharmony_ci if (gz->write) { 277275793eaSopenharmony_ci strm->next_in = Z_NULL; 278275793eaSopenharmony_ci strm->avail_in = 0; 279275793eaSopenharmony_ci do { 280275793eaSopenharmony_ci strm->next_out = out; 281275793eaSopenharmony_ci strm->avail_out = BUFLEN; 282275793eaSopenharmony_ci (void)deflate(strm, Z_FINISH); 283275793eaSopenharmony_ci fwrite(out, 1, BUFLEN - strm->avail_out, gz->file); 284275793eaSopenharmony_ci } while (strm->avail_out == 0); 285275793eaSopenharmony_ci deflateEnd(strm); 286275793eaSopenharmony_ci } 287275793eaSopenharmony_ci else 288275793eaSopenharmony_ci inflateEnd(strm); 289275793eaSopenharmony_ci fclose(gz->file); 290275793eaSopenharmony_ci free(gz); 291275793eaSopenharmony_ci return Z_OK; 292275793eaSopenharmony_ci} 293275793eaSopenharmony_ci 294275793eaSopenharmony_cistatic const char *gzerror(gzFile gz, int *err) 295275793eaSopenharmony_ci{ 296275793eaSopenharmony_ci *err = gz->err; 297275793eaSopenharmony_ci return gz->msg; 298275793eaSopenharmony_ci} 299275793eaSopenharmony_ci 300275793eaSopenharmony_ci#endif 301275793eaSopenharmony_ci 302275793eaSopenharmony_cistatic char *prog; 303275793eaSopenharmony_ci 304275793eaSopenharmony_ci/* =========================================================================== 305275793eaSopenharmony_ci * Display error message and exit 306275793eaSopenharmony_ci */ 307275793eaSopenharmony_cistatic void error(const char *msg) 308275793eaSopenharmony_ci{ 309275793eaSopenharmony_ci fprintf(stderr, "%s: %s\n", prog, msg); 310275793eaSopenharmony_ci exit(1); 311275793eaSopenharmony_ci} 312275793eaSopenharmony_ci 313275793eaSopenharmony_ci#ifdef USE_MMAP /* MMAP version, Miguel Albrecht <malbrech@eso.org> */ 314275793eaSopenharmony_ci 315275793eaSopenharmony_ci/* Try compressing the input file at once using mmap. Return Z_OK if 316275793eaSopenharmony_ci * success, Z_ERRNO otherwise. 317275793eaSopenharmony_ci */ 318275793eaSopenharmony_cistatic int gz_compress_mmap(FILE *in, gzFile out) 319275793eaSopenharmony_ci{ 320275793eaSopenharmony_ci int len; 321275793eaSopenharmony_ci int err; 322275793eaSopenharmony_ci int ifd = fileno(in); 323275793eaSopenharmony_ci caddr_t buf; /* mmap'ed buffer for the entire input file */ 324275793eaSopenharmony_ci off_t buf_len; /* length of the input file */ 325275793eaSopenharmony_ci struct stat sb; 326275793eaSopenharmony_ci 327275793eaSopenharmony_ci /* Determine the size of the file, needed for mmap: */ 328275793eaSopenharmony_ci if (fstat(ifd, &sb) < 0) 329275793eaSopenharmony_ci { 330275793eaSopenharmony_ci return Z_ERRNO; 331275793eaSopenharmony_ci } 332275793eaSopenharmony_ci buf_len = sb.st_size; 333275793eaSopenharmony_ci if (buf_len <= 0) 334275793eaSopenharmony_ci { 335275793eaSopenharmony_ci return Z_ERRNO; 336275793eaSopenharmony_ci } 337275793eaSopenharmony_ci 338275793eaSopenharmony_ci /* Now do the actual mmap: */ 339275793eaSopenharmony_ci buf = mmap((caddr_t) 0, buf_len, PROT_READ, MAP_SHARED, ifd, (off_t)0); 340275793eaSopenharmony_ci if (buf == (caddr_t)(-1)) 341275793eaSopenharmony_ci { 342275793eaSopenharmony_ci return Z_ERRNO; 343275793eaSopenharmony_ci } 344275793eaSopenharmony_ci 345275793eaSopenharmony_ci /* Compress the whole file at once: */ 346275793eaSopenharmony_ci len = gzwrite(out, (char *)buf, (unsigned)buf_len); 347275793eaSopenharmony_ci 348275793eaSopenharmony_ci if (len != (int)buf_len) 349275793eaSopenharmony_ci { 350275793eaSopenharmony_ci error(gzerror(out, &err)); 351275793eaSopenharmony_ci } 352275793eaSopenharmony_ci 353275793eaSopenharmony_ci munmap(buf, buf_len); 354275793eaSopenharmony_ci fclose(in); 355275793eaSopenharmony_ci if (gzclose(out) != Z_OK) 356275793eaSopenharmony_ci { 357275793eaSopenharmony_ci error("failed gzclose"); 358275793eaSopenharmony_ci } 359275793eaSopenharmony_ci return Z_OK; 360275793eaSopenharmony_ci} 361275793eaSopenharmony_ci#endif /* USE_MMAP */ 362275793eaSopenharmony_ci 363275793eaSopenharmony_ci/* =========================================================================== 364275793eaSopenharmony_ci * Compress input to output then close both files. 365275793eaSopenharmony_ci */ 366275793eaSopenharmony_ci 367275793eaSopenharmony_cistatic void gz_compress(FILE *in, gzFile out) 368275793eaSopenharmony_ci{ 369275793eaSopenharmony_ci local char buf[BUFLEN]; 370275793eaSopenharmony_ci int len; 371275793eaSopenharmony_ci int err; 372275793eaSopenharmony_ci 373275793eaSopenharmony_ci#ifdef USE_MMAP 374275793eaSopenharmony_ci /* Try first compressing with mmap. If mmap fails (minigzip used in a 375275793eaSopenharmony_ci * pipe), use the normal fread loop. 376275793eaSopenharmony_ci */ 377275793eaSopenharmony_ci if (gz_compress_mmap(in, out) == Z_OK) return; 378275793eaSopenharmony_ci#endif 379275793eaSopenharmony_ci for (;;) { 380275793eaSopenharmony_ci len = (int)fread(buf, 1, sizeof(buf), in); 381275793eaSopenharmony_ci if (ferror(in)) { 382275793eaSopenharmony_ci perror("fread"); 383275793eaSopenharmony_ci exit(1); 384275793eaSopenharmony_ci } 385275793eaSopenharmony_ci if (len == 0) 386275793eaSopenharmony_ci { 387275793eaSopenharmony_ci break; 388275793eaSopenharmony_ci } 389275793eaSopenharmony_ci 390275793eaSopenharmony_ci if (gzwrite(out, buf, (unsigned)len) != len) 391275793eaSopenharmony_ci { 392275793eaSopenharmony_ci error(gzerror(out, &err)); 393275793eaSopenharmony_ci } 394275793eaSopenharmony_ci } 395275793eaSopenharmony_ci fclose(in); 396275793eaSopenharmony_ci if (gzclose(out) != Z_OK) 397275793eaSopenharmony_ci { 398275793eaSopenharmony_ci error("failed gzclose"); 399275793eaSopenharmony_ci } 400275793eaSopenharmony_ci} 401275793eaSopenharmony_ci 402275793eaSopenharmony_ci/* =========================================================================== 403275793eaSopenharmony_ci * Uncompress input to output then close both files. 404275793eaSopenharmony_ci */ 405275793eaSopenharmony_cistatic void gz_uncompress(gzFile in, FILE *out) 406275793eaSopenharmony_ci{ 407275793eaSopenharmony_ci local char buf[BUFLEN]; 408275793eaSopenharmony_ci int len; 409275793eaSopenharmony_ci int err; 410275793eaSopenharmony_ci 411275793eaSopenharmony_ci for (;;) { 412275793eaSopenharmony_ci len = gzread(in, buf, sizeof(buf)); 413275793eaSopenharmony_ci if (len < 0) 414275793eaSopenharmony_ci { 415275793eaSopenharmony_ci error (gzerror(in, &err)); 416275793eaSopenharmony_ci } 417275793eaSopenharmony_ci if (len == 0) 418275793eaSopenharmony_ci { 419275793eaSopenharmony_ci break; 420275793eaSopenharmony_ci } 421275793eaSopenharmony_ci 422275793eaSopenharmony_ci if ((int)fwrite(buf, 1, (unsigned)len, out) != len) { 423275793eaSopenharmony_ci error("failed fwrite"); 424275793eaSopenharmony_ci } 425275793eaSopenharmony_ci } 426275793eaSopenharmony_ci if (fclose(out)) 427275793eaSopenharmony_ci { 428275793eaSopenharmony_ci error("failed fclose"); 429275793eaSopenharmony_ci } 430275793eaSopenharmony_ci 431275793eaSopenharmony_ci if (gzclose(in) != Z_OK) 432275793eaSopenharmony_ci { 433275793eaSopenharmony_ci error("failed gzclose"); 434275793eaSopenharmony_ci } 435275793eaSopenharmony_ci} 436275793eaSopenharmony_ci 437275793eaSopenharmony_ci 438275793eaSopenharmony_ci/* =========================================================================== 439275793eaSopenharmony_ci * Compress the given file: create a corresponding .gz file and remove the 440275793eaSopenharmony_ci * original. 441275793eaSopenharmony_ci */ 442275793eaSopenharmony_cistatic void file_compress(char *file, char *mode) 443275793eaSopenharmony_ci{ 444275793eaSopenharmony_ci local char outfile[MAX_NAME_LEN]; 445275793eaSopenharmony_ci FILE *in; 446275793eaSopenharmony_ci gzFile out; 447275793eaSopenharmony_ci 448275793eaSopenharmony_ci if (strlen(file) + strlen(GZ_SUFFIX) >= sizeof(outfile)) { 449275793eaSopenharmony_ci fprintf(stderr, "%s: filename too long\n", prog); 450275793eaSopenharmony_ci exit(1); 451275793eaSopenharmony_ci } 452275793eaSopenharmony_ci 453275793eaSopenharmony_ci#if !defined(NO_snprintf) && !defined(NO_vsnprintf) 454275793eaSopenharmony_ci snprintf(outfile, sizeof(outfile), "%s%s", file, GZ_SUFFIX); 455275793eaSopenharmony_ci#else 456275793eaSopenharmony_ci strcpy(outfile, file); 457275793eaSopenharmony_ci strcat(outfile, GZ_SUFFIX); 458275793eaSopenharmony_ci#endif 459275793eaSopenharmony_ci 460275793eaSopenharmony_ci in = fopen(file, "rb"); 461275793eaSopenharmony_ci if (in == NULL) { 462275793eaSopenharmony_ci perror(file); 463275793eaSopenharmony_ci exit(1); 464275793eaSopenharmony_ci } 465275793eaSopenharmony_ci out = gzopen(outfile, mode); 466275793eaSopenharmony_ci if (out == NULL) { 467275793eaSopenharmony_ci fprintf(stderr, "%s: can't gzopen %s\n", prog, outfile); 468275793eaSopenharmony_ci exit(1); 469275793eaSopenharmony_ci } 470275793eaSopenharmony_ci gz_compress(in, out); 471275793eaSopenharmony_ci 472275793eaSopenharmony_ci unlink(file); 473275793eaSopenharmony_ci} 474275793eaSopenharmony_ci 475275793eaSopenharmony_ci 476275793eaSopenharmony_ci/* =========================================================================== 477275793eaSopenharmony_ci * Uncompress the given file and remove the original. 478275793eaSopenharmony_ci */ 479275793eaSopenharmony_cistatic void file_uncompress(char *file) 480275793eaSopenharmony_ci{ 481275793eaSopenharmony_ci local char buf[MAX_NAME_LEN]; 482275793eaSopenharmony_ci char *infile, *outfile; 483275793eaSopenharmony_ci FILE *out; 484275793eaSopenharmony_ci gzFile in; 485275793eaSopenharmony_ci z_size_t len = strlen(file); 486275793eaSopenharmony_ci 487275793eaSopenharmony_ci if (len + strlen(GZ_SUFFIX) >= sizeof(buf)) { 488275793eaSopenharmony_ci fprintf(stderr, "%s: filename too long\n", prog); 489275793eaSopenharmony_ci exit(1); 490275793eaSopenharmony_ci } 491275793eaSopenharmony_ci 492275793eaSopenharmony_ci#if !defined(NO_snprintf) && !defined(NO_vsnprintf) 493275793eaSopenharmony_ci snprintf(buf, sizeof(buf), "%s", file); 494275793eaSopenharmony_ci#else 495275793eaSopenharmony_ci strcpy(buf, file); 496275793eaSopenharmony_ci#endif 497275793eaSopenharmony_ci 498275793eaSopenharmony_ci if (len > SUFFIX_LEN && strcmp(file+len-SUFFIX_LEN, GZ_SUFFIX) == 0) { 499275793eaSopenharmony_ci infile = file; 500275793eaSopenharmony_ci outfile = buf; 501275793eaSopenharmony_ci outfile[len-3] = '\0'; 502275793eaSopenharmony_ci } else { 503275793eaSopenharmony_ci outfile = file; 504275793eaSopenharmony_ci infile = buf; 505275793eaSopenharmony_ci#if !defined(NO_snprintf) && !defined(NO_vsnprintf) 506275793eaSopenharmony_ci snprintf(buf + len, sizeof(buf) - len, "%s", GZ_SUFFIX); 507275793eaSopenharmony_ci#else 508275793eaSopenharmony_ci strcat(infile, GZ_SUFFIX); 509275793eaSopenharmony_ci#endif 510275793eaSopenharmony_ci } 511275793eaSopenharmony_ci in = gzopen(infile, "rb"); 512275793eaSopenharmony_ci if (in == NULL) { 513275793eaSopenharmony_ci fprintf(stderr, "%s: can't gzopen %s\n", prog, infile); 514275793eaSopenharmony_ci exit(1); 515275793eaSopenharmony_ci } 516275793eaSopenharmony_ci out = fopen(outfile, "wb"); 517275793eaSopenharmony_ci if (out == NULL) { 518275793eaSopenharmony_ci perror(file); 519275793eaSopenharmony_ci exit(1); 520275793eaSopenharmony_ci } 521275793eaSopenharmony_ci 522275793eaSopenharmony_ci gz_uncompress(in, out); 523275793eaSopenharmony_ci 524275793eaSopenharmony_ci unlink(infile); 525275793eaSopenharmony_ci} 526275793eaSopenharmony_ci 527275793eaSopenharmony_ci 528275793eaSopenharmony_ci/* =========================================================================== 529275793eaSopenharmony_ci * Usage: minigzip [-c] [-d] [-f] [-h] [-r] [-1 to -9] [files...] 530275793eaSopenharmony_ci * -c : write to standard output 531275793eaSopenharmony_ci * -d : decompress 532275793eaSopenharmony_ci * -f : compress with Z_FILTERED 533275793eaSopenharmony_ci * -h : compress with Z_HUFFMAN_ONLY 534275793eaSopenharmony_ci * -r : compress with Z_RLE 535275793eaSopenharmony_ci * -1 to -9 : compression level 536275793eaSopenharmony_ci */ 537275793eaSopenharmony_ci 538275793eaSopenharmony_ciint main(int argc, char *argv[]) 539275793eaSopenharmony_ci{ 540275793eaSopenharmony_ci int copyout = 0; 541275793eaSopenharmony_ci int uncompr = 0; 542275793eaSopenharmony_ci gzFile file; 543275793eaSopenharmony_ci char *bname, outmode[20]; 544275793eaSopenharmony_ci 545275793eaSopenharmony_ci#if !defined(NO_snprintf) && !defined(NO_vsnprintf) 546275793eaSopenharmony_ci snprintf(outmode, sizeof(outmode), "%s", "wb6 "); 547275793eaSopenharmony_ci#else 548275793eaSopenharmony_ci strcpy(outmode, "wb6 "); 549275793eaSopenharmony_ci#endif 550275793eaSopenharmony_ci 551275793eaSopenharmony_ci prog = argv[0]; 552275793eaSopenharmony_ci bname = strrchr(argv[0], '/'); 553275793eaSopenharmony_ci if (bname) 554275793eaSopenharmony_ci { 555275793eaSopenharmony_ci bname++; 556275793eaSopenharmony_ci } 557275793eaSopenharmony_ci else 558275793eaSopenharmony_ci { 559275793eaSopenharmony_ci bname = argv[0]; 560275793eaSopenharmony_ci } 561275793eaSopenharmony_ci argc--, argv++; 562275793eaSopenharmony_ci 563275793eaSopenharmony_ci if (!strcmp(bname, "gunzip")) 564275793eaSopenharmony_ci { 565275793eaSopenharmony_ci uncompr = 1; 566275793eaSopenharmony_ci } 567275793eaSopenharmony_ci else if (!strcmp(bname, "zcat")) 568275793eaSopenharmony_ci { 569275793eaSopenharmony_ci copyout = uncompr = 1; 570275793eaSopenharmony_ci } 571275793eaSopenharmony_ci 572275793eaSopenharmony_ci while (argc > 0) { 573275793eaSopenharmony_ci if (strcmp(*argv, "-c") == 0) 574275793eaSopenharmony_ci { 575275793eaSopenharmony_ci copyout = 1; 576275793eaSopenharmony_ci } 577275793eaSopenharmony_ci else if (strcmp(*argv, "-d") == 0) 578275793eaSopenharmony_ci { 579275793eaSopenharmony_ci uncompr = 1; 580275793eaSopenharmony_ci } 581275793eaSopenharmony_ci else if (strcmp(*argv, "-f") == 0) 582275793eaSopenharmony_ci { 583275793eaSopenharmony_ci outmode[3] = 'f'; 584275793eaSopenharmony_ci } 585275793eaSopenharmony_ci else if (strcmp(*argv, "-h") == 0) 586275793eaSopenharmony_ci { 587275793eaSopenharmony_ci outmode[3] = 'h'; 588275793eaSopenharmony_ci } 589275793eaSopenharmony_ci else if (strcmp(*argv, "-r") == 0) 590275793eaSopenharmony_ci { 591275793eaSopenharmony_ci outmode[3] = 'R'; 592275793eaSopenharmony_ci } 593275793eaSopenharmony_ci else if ((*argv)[0] == '-' && (*argv)[1] >= '1' && (*argv)[1] <= '9' && 594275793eaSopenharmony_ci (*argv)[2] == 0) 595275793eaSopenharmony_ci { 596275793eaSopenharmony_ci outmode[2] = (*argv)[1]; 597275793eaSopenharmony_ci } 598275793eaSopenharmony_ci else 599275793eaSopenharmony_ci { 600275793eaSopenharmony_ci break; 601275793eaSopenharmony_ci } 602275793eaSopenharmony_ci argc--, argv++; 603275793eaSopenharmony_ci } 604275793eaSopenharmony_ci if (outmode[3] == ' ') 605275793eaSopenharmony_ci { 606275793eaSopenharmony_ci outmode[3] = 0; 607275793eaSopenharmony_ci } 608275793eaSopenharmony_ci if (argc == 0) { 609275793eaSopenharmony_ci SET_BINARY_MODE(stdin); 610275793eaSopenharmony_ci SET_BINARY_MODE(stdout); 611275793eaSopenharmony_ci if (uncompr) { 612275793eaSopenharmony_ci file = gzdopen(fileno(stdin), "rb"); 613275793eaSopenharmony_ci if (file == NULL) 614275793eaSopenharmony_ci { 615275793eaSopenharmony_ci error("can't gzdopen stdin"); 616275793eaSopenharmony_ci } 617275793eaSopenharmony_ci gz_uncompress(file, stdout); 618275793eaSopenharmony_ci } else { 619275793eaSopenharmony_ci file = gzdopen(fileno(stdout), outmode); 620275793eaSopenharmony_ci if (file == NULL) 621275793eaSopenharmony_ci { 622275793eaSopenharmony_ci error("can't gzdopen stdout"); 623275793eaSopenharmony_ci } 624275793eaSopenharmony_ci gz_compress(stdin, file); 625275793eaSopenharmony_ci } 626275793eaSopenharmony_ci } else { 627275793eaSopenharmony_ci if (copyout) { 628275793eaSopenharmony_ci SET_BINARY_MODE(stdout); 629275793eaSopenharmony_ci } 630275793eaSopenharmony_ci do { 631275793eaSopenharmony_ci if (uncompr) { 632275793eaSopenharmony_ci if (copyout) { 633275793eaSopenharmony_ci file = gzopen(*argv, "rb"); 634275793eaSopenharmony_ci if (file == NULL) 635275793eaSopenharmony_ci { 636275793eaSopenharmony_ci fprintf(stderr, "%s: can't gzopen %s\n", prog, *argv); 637275793eaSopenharmony_ci } 638275793eaSopenharmony_ci else 639275793eaSopenharmony_ci { 640275793eaSopenharmony_ci gz_uncompress(file, stdout); 641275793eaSopenharmony_ci } 642275793eaSopenharmony_ci } else { 643275793eaSopenharmony_ci file_uncompress(*argv); 644275793eaSopenharmony_ci } 645275793eaSopenharmony_ci } else { 646275793eaSopenharmony_ci if (copyout) { 647275793eaSopenharmony_ci FILE * in = fopen(*argv, "rb"); 648275793eaSopenharmony_ci 649275793eaSopenharmony_ci if (in == NULL) { 650275793eaSopenharmony_ci perror(*argv); 651275793eaSopenharmony_ci } else { 652275793eaSopenharmony_ci file = gzdopen(fileno(stdout), outmode); 653275793eaSopenharmony_ci if (file == NULL) 654275793eaSopenharmony_ci { 655275793eaSopenharmony_ci error("can't gzdopen stdout"); 656275793eaSopenharmony_ci } 657275793eaSopenharmony_ci 658275793eaSopenharmony_ci gz_compress(in, file); 659275793eaSopenharmony_ci } 660275793eaSopenharmony_ci 661275793eaSopenharmony_ci } else { 662275793eaSopenharmony_ci file_compress(*argv, outmode); 663275793eaSopenharmony_ci } 664275793eaSopenharmony_ci } 665275793eaSopenharmony_ci } while (argv++, --argc); 666275793eaSopenharmony_ci } 667275793eaSopenharmony_ci return 0; 668275793eaSopenharmony_ci} 669