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