Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/contrib/zstd/zlibWrapper/examples/minigzip.c
48375 views
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
#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 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 (error)
86
DWORD error;
87
{
88
static char buf[1024];
89
90
wchar_t *msgbuf;
91
DWORD lasterr = GetLastError();
92
DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
93
| FORMAT_MESSAGE_ALLOCATE_BUFFER,
94
NULL,
95
error,
96
0, /* Default language */
97
(LPVOID)&msgbuf,
98
0,
99
NULL);
100
if (chars != 0) {
101
/* If there is an \r\n appended, zap it. */
102
if (chars >= 2
103
&& msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') {
104
chars -= 2;
105
msgbuf[chars] = 0;
106
}
107
108
if (chars > sizeof (buf) - 1) {
109
chars = sizeof (buf) - 1;
110
msgbuf[chars] = 0;
111
}
112
113
wcstombs(buf, msgbuf, chars + 1);
114
LocalFree(msgbuf);
115
}
116
else {
117
sprintf(buf, "unknown win32 error (%ld)", error);
118
}
119
120
SetLastError(lasterr);
121
return buf;
122
}
123
124
static void pwinerror (s)
125
const char *s;
126
{
127
if (s && *s)
128
fprintf(stderr, "%s: %s\n", s, strwinerror(GetLastError ()));
129
else
130
fprintf(stderr, "%s\n", strwinerror(GetLastError ()));
131
}
132
133
#endif /* UNDER_CE */
134
135
#ifndef GZ_SUFFIX
136
# define GZ_SUFFIX ".gz"
137
#endif
138
#define SUFFIX_LEN (sizeof(GZ_SUFFIX)-1)
139
140
#define BUFLEN 16384
141
#define MAX_NAME_LEN 1024
142
143
#ifdef MAXSEG_64K
144
# define local static
145
/* Needed for systems with limitation on stack size. */
146
#else
147
# define local
148
#endif
149
150
#ifdef Z_SOLO
151
/* for Z_SOLO, create simplified gz* functions using deflate and inflate */
152
153
#if defined(Z_HAVE_UNISTD_H) || defined(Z_LARGE)
154
# include <unistd.h> /* for unlink() */
155
#endif
156
157
void *myalloc OF((void *, unsigned, unsigned));
158
void myfree OF((void *, void *));
159
160
void *myalloc(q, n, m)
161
void *q;
162
unsigned n, m;
163
{
164
q = Z_NULL;
165
return calloc(n, m);
166
}
167
168
void myfree(q, p)
169
void *q, *p;
170
{
171
q = Z_NULL;
172
free(p);
173
}
174
175
typedef struct gzFile_s {
176
FILE *file;
177
int write;
178
int err;
179
char *msg;
180
z_stream strm;
181
} *gzFile;
182
183
gzFile gzopen OF((const char *, const char *));
184
gzFile gzdopen OF((int, const char *));
185
gzFile gz_open OF((const char *, int, const char *));
186
187
gzFile gzopen(path, mode)
188
const char *path;
189
const char *mode;
190
{
191
return gz_open(path, -1, mode);
192
}
193
194
gzFile gzdopen(fd, mode)
195
int fd;
196
const char *mode;
197
{
198
return gz_open(NULL, fd, mode);
199
}
200
201
gzFile gz_open(path, fd, mode)
202
const char *path;
203
int fd;
204
const char *mode;
205
{
206
gzFile gz;
207
int ret;
208
209
gz = malloc(sizeof(struct gzFile_s));
210
if (gz == NULL)
211
return NULL;
212
gz->write = strchr(mode, 'w') != NULL;
213
gz->strm.zalloc = myalloc;
214
gz->strm.zfree = myfree;
215
gz->strm.opaque = Z_NULL;
216
if (gz->write)
217
ret = deflateInit2(&(gz->strm), -1, 8, 15 + 16, 8, 0);
218
else {
219
gz->strm.next_in = 0;
220
gz->strm.avail_in = Z_NULL;
221
ret = inflateInit2(&(gz->strm), 15 + 16);
222
}
223
if (ret != Z_OK) {
224
free(gz);
225
return NULL;
226
}
227
gz->file = path == NULL ? fdopen(fd, gz->write ? "wb" : "rb") :
228
fopen(path, gz->write ? "wb" : "rb");
229
if (gz->file == NULL) {
230
gz->write ? deflateEnd(&(gz->strm)) : inflateEnd(&(gz->strm));
231
free(gz);
232
return NULL;
233
}
234
gz->err = 0;
235
gz->msg = "";
236
return gz;
237
}
238
239
int gzwrite OF((gzFile, const void *, unsigned));
240
241
int gzwrite(gz, buf, len)
242
gzFile gz;
243
const void *buf;
244
unsigned len;
245
{
246
z_stream *strm;
247
unsigned char out[BUFLEN];
248
249
if (gz == NULL || !gz->write)
250
return 0;
251
strm = &(gz->strm);
252
strm->next_in = (void *)buf;
253
strm->avail_in = len;
254
do {
255
strm->next_out = out;
256
strm->avail_out = BUFLEN;
257
(void)deflate(strm, Z_NO_FLUSH);
258
fwrite(out, 1, BUFLEN - strm->avail_out, gz->file);
259
} while (strm->avail_out == 0);
260
return len;
261
}
262
263
int gzread OF((gzFile, void *, unsigned));
264
265
int gzread(gz, buf, len)
266
gzFile gz;
267
void *buf;
268
unsigned len;
269
{
270
int ret;
271
unsigned got;
272
unsigned char in[1];
273
z_stream *strm;
274
275
if (gz == NULL || gz->write)
276
return 0;
277
if (gz->err)
278
return 0;
279
strm = &(gz->strm);
280
strm->next_out = (void *)buf;
281
strm->avail_out = len;
282
do {
283
got = fread(in, 1, 1, gz->file);
284
if (got == 0)
285
break;
286
strm->next_in = in;
287
strm->avail_in = 1;
288
ret = inflate(strm, Z_NO_FLUSH);
289
if (ret == Z_DATA_ERROR) {
290
gz->err = Z_DATA_ERROR;
291
gz->msg = strm->msg;
292
return 0;
293
}
294
if (ret == Z_STREAM_END)
295
inflateReset(strm);
296
} while (strm->avail_out);
297
return len - strm->avail_out;
298
}
299
300
int gzclose OF((gzFile));
301
302
int gzclose(gz)
303
gzFile gz;
304
{
305
z_stream *strm;
306
unsigned char out[BUFLEN];
307
308
if (gz == NULL)
309
return Z_STREAM_ERROR;
310
strm = &(gz->strm);
311
if (gz->write) {
312
strm->next_in = Z_NULL;
313
strm->avail_in = 0;
314
do {
315
strm->next_out = out;
316
strm->avail_out = BUFLEN;
317
(void)deflate(strm, Z_FINISH);
318
fwrite(out, 1, BUFLEN - strm->avail_out, gz->file);
319
} while (strm->avail_out == 0);
320
deflateEnd(strm);
321
}
322
else
323
inflateEnd(strm);
324
fclose(gz->file);
325
free(gz);
326
return Z_OK;
327
}
328
329
const char *gzerror OF((gzFile, int *));
330
331
const char *gzerror(gz, err)
332
gzFile gz;
333
int *err;
334
{
335
*err = gz->err;
336
return gz->msg;
337
}
338
339
#endif
340
341
char *prog;
342
343
void error OF((const char *msg));
344
void gz_compress OF((FILE *in, gzFile out));
345
#ifdef USE_MMAP
346
int gz_compress_mmap OF((FILE *in, gzFile out));
347
#endif
348
void gz_uncompress OF((gzFile in, FILE *out));
349
void file_compress OF((char *file, char *mode));
350
void file_uncompress OF((char *file));
351
int main OF((int argc, char *argv[]));
352
353
/* ===========================================================================
354
* Display error message and exit
355
*/
356
void error(msg)
357
const char *msg;
358
{
359
fprintf(stderr, "%s: %s\n", prog, msg);
360
exit(1);
361
}
362
363
/* ===========================================================================
364
* Compress input to output then close both files.
365
*/
366
367
void gz_compress(in, out)
368
FILE *in;
369
gzFile out;
370
{
371
local char buf[BUFLEN];
372
int len;
373
int err;
374
375
#ifdef USE_MMAP
376
/* Try first compressing with mmap. If mmap fails (minigzip used in a
377
* pipe), use the normal fread loop.
378
*/
379
if (gz_compress_mmap(in, out) == Z_OK) return;
380
#endif
381
for (;;) {
382
len = (int)fread(buf, 1, sizeof(buf), in);
383
if (ferror(in)) {
384
perror("fread");
385
exit(1);
386
}
387
if (len == 0) break;
388
389
if (gzwrite(out, buf, (unsigned)len) != len) error(gzerror(out, &err));
390
}
391
fclose(in);
392
if (gzclose(out) != Z_OK) error("failed gzclose");
393
}
394
395
#ifdef USE_MMAP /* MMAP version, Miguel Albrecht <[email protected]> */
396
397
/* Try compressing the input file at once using mmap. Return Z_OK if
398
* if success, Z_ERRNO otherwise.
399
*/
400
int gz_compress_mmap(in, out)
401
FILE *in;
402
gzFile out;
403
{
404
int len;
405
int err;
406
int ifd = fileno(in);
407
caddr_t buf; /* mmap'ed buffer for the entire input file */
408
off_t buf_len; /* length of the input file */
409
struct stat sb;
410
411
/* Determine the size of the file, needed for mmap: */
412
if (fstat(ifd, &sb) < 0) return Z_ERRNO;
413
buf_len = sb.st_size;
414
if (buf_len <= 0) return Z_ERRNO;
415
416
/* Now do the actual mmap: */
417
buf = mmap((caddr_t) 0, buf_len, PROT_READ, MAP_SHARED, ifd, (off_t)0);
418
if (buf == (caddr_t)(-1)) return Z_ERRNO;
419
420
/* Compress the whole file at once: */
421
len = gzwrite(out, (char *)buf, (unsigned)buf_len);
422
423
if (len != (int)buf_len) error(gzerror(out, &err));
424
425
munmap(buf, buf_len);
426
fclose(in);
427
if (gzclose(out) != Z_OK) error("failed gzclose");
428
return Z_OK;
429
}
430
#endif /* USE_MMAP */
431
432
/* ===========================================================================
433
* Uncompress input to output then close both files.
434
*/
435
void gz_uncompress(in, out)
436
gzFile in;
437
FILE *out;
438
{
439
local char buf[BUFLEN];
440
int len;
441
int err;
442
443
for (;;) {
444
len = gzread(in, buf, sizeof(buf));
445
if (len < 0) error (gzerror(in, &err));
446
if (len == 0) break;
447
448
if ((int)fwrite(buf, 1, (unsigned)len, out) != len) {
449
error("failed fwrite");
450
}
451
}
452
if (fclose(out)) error("failed fclose");
453
454
if (gzclose(in) != Z_OK) error("failed gzclose");
455
}
456
457
458
/* ===========================================================================
459
* Compress the given file: create a corresponding .gz file and remove the
460
* original.
461
*/
462
void file_compress(file, mode)
463
char *file;
464
char *mode;
465
{
466
local char outfile[MAX_NAME_LEN];
467
FILE *in;
468
gzFile out;
469
470
if (strlen(file) + strlen(GZ_SUFFIX) >= sizeof(outfile)) {
471
fprintf(stderr, "%s: filename too long\n", prog);
472
exit(1);
473
}
474
475
strcpy(outfile, file);
476
strcat(outfile, GZ_SUFFIX);
477
478
in = fopen(file, "rb");
479
if (in == NULL) {
480
perror(file);
481
exit(1);
482
}
483
out = gzopen(outfile, mode);
484
if (out == NULL) {
485
fprintf(stderr, "%s: can't gzopen %s\n", prog, outfile);
486
exit(1);
487
}
488
gz_compress(in, out);
489
490
unlink(file);
491
}
492
493
494
/* ===========================================================================
495
* Uncompress the given file and remove the original.
496
*/
497
void file_uncompress(file)
498
char *file;
499
{
500
local char buf[MAX_NAME_LEN];
501
char *infile, *outfile;
502
FILE *out;
503
gzFile in;
504
size_t len = strlen(file);
505
506
if (len + strlen(GZ_SUFFIX) >= sizeof(buf)) {
507
fprintf(stderr, "%s: filename too long\n", prog);
508
exit(1);
509
}
510
511
strcpy(buf, file);
512
513
if (len > SUFFIX_LEN && strcmp(file+len-SUFFIX_LEN, GZ_SUFFIX) == 0) {
514
infile = file;
515
outfile = buf;
516
outfile[len-3] = '\0';
517
} else {
518
outfile = file;
519
infile = buf;
520
strcat(infile, GZ_SUFFIX);
521
}
522
in = gzopen(infile, "rb");
523
if (in == NULL) {
524
fprintf(stderr, "%s: can't gzopen %s\n", prog, infile);
525
exit(1);
526
}
527
out = fopen(outfile, "wb");
528
if (out == NULL) {
529
perror(file);
530
exit(1);
531
}
532
533
gz_uncompress(in, out);
534
535
unlink(infile);
536
}
537
538
539
/* ===========================================================================
540
* Usage: minigzip [-c] [-d] [-f] [-h] [-r] [-1 to -9] [files...]
541
* -c : write to standard output
542
* -d : decompress
543
* -f : compress with Z_FILTERED
544
* -h : compress with Z_HUFFMAN_ONLY
545
* -r : compress with Z_RLE
546
* -1 to -9 : compression level
547
*/
548
549
int main(argc, argv)
550
int argc;
551
char *argv[];
552
{
553
int copyout = 0;
554
int uncompr = 0;
555
gzFile file;
556
char *bname, outmode[20];
557
558
strcpy(outmode, "wb6 ");
559
560
prog = argv[0];
561
bname = strrchr(argv[0], '/');
562
if (bname)
563
bname++;
564
else
565
bname = argv[0];
566
argc--, argv++;
567
568
if (!strcmp(bname, "gunzip"))
569
uncompr = 1;
570
else if (!strcmp(bname, "zcat"))
571
copyout = uncompr = 1;
572
573
while (argc > 0) {
574
if (strcmp(*argv, "-c") == 0)
575
copyout = 1;
576
else if (strcmp(*argv, "-d") == 0)
577
uncompr = 1;
578
else if (strcmp(*argv, "-f") == 0)
579
outmode[3] = 'f';
580
else if (strcmp(*argv, "-h") == 0)
581
outmode[3] = 'h';
582
else if (strcmp(*argv, "-r") == 0)
583
outmode[3] = 'R';
584
else if ((*argv)[0] == '-' && (*argv)[1] >= '1' && (*argv)[1] <= '9' &&
585
(*argv)[2] == 0)
586
outmode[2] = (*argv)[1];
587
else
588
break;
589
argc--, argv++;
590
}
591
if (outmode[3] == ' ')
592
outmode[3] = 0;
593
if (argc == 0) {
594
SET_BINARY_MODE(stdin);
595
SET_BINARY_MODE(stdout);
596
if (uncompr) {
597
file = gzdopen(fileno(stdin), "rb");
598
if (file == NULL) error("can't gzdopen stdin");
599
gz_uncompress(file, stdout);
600
} else {
601
file = gzdopen(fileno(stdout), outmode);
602
if (file == NULL) error("can't gzdopen stdout");
603
gz_compress(stdin, file);
604
}
605
} else {
606
if (copyout) {
607
SET_BINARY_MODE(stdout);
608
}
609
do {
610
if (uncompr) {
611
if (copyout) {
612
file = gzopen(*argv, "rb");
613
if (file == NULL)
614
fprintf(stderr, "%s: can't gzopen %s\n", prog, *argv);
615
else
616
gz_uncompress(file, stdout);
617
} else {
618
file_uncompress(*argv);
619
}
620
} else {
621
if (copyout) {
622
FILE * in = fopen(*argv, "rb");
623
624
if (in == NULL) {
625
perror(*argv);
626
} else {
627
file = gzdopen(fileno(stdout), outmode);
628
if (file == NULL) error("can't gzdopen stdout");
629
630
gz_compress(in, file);
631
}
632
633
} else {
634
file_compress(*argv, outmode);
635
}
636
}
637
} while (argv++, --argc);
638
}
639
return 0;
640
}
641
642