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