Fossil SCM

fossil-scm / compat / zlib / contrib / puff / pufftest.c
Blame History Raw 169 lines
1
/*
2
* pufftest.c
3
* Copyright (C) 2002-2026 Mark Adler
4
* For conditions of distribution and use, see copyright notice in puff.h
5
*/
6
7
/* Example of how to use puff().
8
9
Usage: puff [-w] [-f] [-nnn] file
10
... | puff [-w] [-f] [-nnn]
11
12
where file is the input file with deflate data, nnn is the number of bytes
13
of input to skip before inflating (e.g. to skip a zlib or gzip header), and
14
-w is used to write the decompressed data to stdout. -f is for coverage
15
testing, and causes pufftest to fail with not enough output space (-f does
16
a write like -w, so -w is not required). */
17
18
#if defined(_WIN32) && !defined(_CRT_NONSTDC_NO_DEPRECATE)
19
# define _CRT_NONSTDC_NO_DEPRECATE
20
#endif
21
22
#include <stdio.h>
23
#include <stdlib.h>
24
#include "puff.h"
25
26
#if defined(MSDOS) || defined(OS2) || defined(_WIN32) || defined(__CYGWIN__)
27
# include <fcntl.h>
28
# include <io.h>
29
# define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
30
#else
31
# define SET_BINARY_MODE(file)
32
#endif
33
34
#define local static
35
36
/* Return size times approximately the cube root of 2, keeping the result as 1,
37
3, or 5 times a power of 2 -- the result is always > size, until the result
38
is the maximum value of an unsigned long, where it remains. This is useful
39
to keep reallocations less than ~33% over the actual data. */
40
local size_t bythirds(size_t size)
41
{
42
int n;
43
size_t m;
44
45
m = size;
46
for (n = 0; m; n++)
47
m >>= 1;
48
if (n < 3)
49
return size + 1;
50
n -= 3;
51
m = size >> n;
52
m += m == 6 ? 2 : 1;
53
m <<= n;
54
return m > size ? m : (size_t)(-1);
55
}
56
57
/* Read the input file *name, or stdin if name is NULL, into allocated memory.
58
Reallocate to larger buffers until the entire file is read in. Return a
59
pointer to the allocated data, or NULL if there was a memory allocation
60
failure. *len is the number of bytes of data read from the input file (even
61
if load() returns NULL). If the input file was empty or could not be opened
62
or read, *len is zero. */
63
local void *load(const char *name, size_t *len)
64
{
65
size_t size;
66
void *buf, *swap;
67
FILE *in;
68
69
*len = 0;
70
buf = malloc(size = 4096);
71
if (buf == NULL)
72
return NULL;
73
in = name == NULL ? stdin : fopen(name, "rb");
74
if (in != NULL) {
75
for (;;) {
76
*len += fread((char *)buf + *len, 1, size - *len, in);
77
if (*len < size) break;
78
size = bythirds(size);
79
if (size == *len || (swap = realloc(buf, size)) == NULL) {
80
free(buf);
81
buf = NULL;
82
break;
83
}
84
buf = swap;
85
}
86
fclose(in);
87
}
88
return buf;
89
}
90
91
int main(int argc, char **argv)
92
{
93
int ret, put = 0, fail = 0;
94
unsigned skip = 0;
95
char *arg, *name = NULL;
96
unsigned char *source = NULL, *dest;
97
size_t len = 0;
98
unsigned long sourcelen, destlen;
99
100
/* process arguments */
101
while (arg = *++argv, --argc)
102
if (arg[0] == '-') {
103
if (arg[1] == 'w' && arg[2] == 0)
104
put = 1;
105
else if (arg[1] == 'f' && arg[2] == 0)
106
fail = 1, put = 1;
107
else if (arg[1] >= '0' && arg[1] <= '9')
108
skip = (unsigned)atoi(arg + 1);
109
else {
110
fprintf(stderr, "invalid option %s\n", arg);
111
return 3;
112
}
113
}
114
else if (name != NULL) {
115
fprintf(stderr, "only one file name allowed\n");
116
return 3;
117
}
118
else
119
name = arg;
120
source = load(name, &len);
121
if (source == NULL) {
122
fprintf(stderr, "memory allocation failure\n");
123
return 4;
124
}
125
if (len == 0) {
126
fprintf(stderr, "could not read %s, or it was empty\n",
127
name == NULL ? "<stdin>" : name);
128
free(source);
129
return 3;
130
}
131
if (skip >= len) {
132
fprintf(stderr, "skip request of %d leaves no input\n", skip);
133
free(source);
134
return 3;
135
}
136
137
/* test inflate data with offset skip */
138
len -= skip;
139
sourcelen = (unsigned long)len;
140
ret = puff(NIL, &destlen, source + skip, &sourcelen);
141
if (ret)
142
fprintf(stderr, "puff() failed with return code %d\n", ret);
143
else {
144
fprintf(stderr, "puff() succeeded uncompressing %lu bytes\n", destlen);
145
if (sourcelen < len) fprintf(stderr, "%lu compressed bytes unused\n",
146
len - sourcelen);
147
}
148
149
/* if requested, inflate again and write decompressed data to stdout */
150
if (put && ret == 0) {
151
if (fail)
152
destlen >>= 1;
153
dest = malloc(destlen);
154
if (dest == NULL) {
155
fprintf(stderr, "memory allocation failure\n");
156
free(source);
157
return 4;
158
}
159
puff(dest, &destlen, source + skip, &sourcelen);
160
SET_BINARY_MODE(stdout);
161
fwrite(dest, 1, destlen, stdout);
162
free(dest);
163
}
164
165
/* clean up */
166
free(source);
167
return ret;
168
}
169

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button