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