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