Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/codexlib/gzip/gzip.c
1810 views
1
#pragma prototyped
2
3
/*
4
* gzip encoder/decoder
5
*/
6
7
#include <codex.h>
8
#include <zlib.h>
9
#include <ctype.h>
10
11
#define MINLEVEL 1
12
#define MAXLEVEL 9
13
14
#define X(x) #x
15
#define S(x) X(x)
16
17
typedef struct State_s
18
{
19
Codex_t* codex;
20
gzFile* gz;
21
int crc;
22
int level;
23
} State_t;
24
25
static int
26
gzip_ident(Codexmeth_t* meth, const void* head, size_t headsize, char* name, size_t namesize)
27
{
28
unsigned char* h = (unsigned char*)head;
29
30
if (headsize >= 3 && h[0] == 0x1f && h[1] == 0x8b)
31
{
32
strncopy(name, meth->name, namesize);
33
return 1;
34
}
35
return 0;
36
}
37
38
static int
39
gzip_open(Codex_t* p, char* const args[], Codexnum_t flags)
40
{
41
register State_t* state;
42
const char* s;
43
char* e;
44
int i;
45
int v;
46
int crc = 1;
47
int level = MAXLEVEL;
48
49
i = 2;
50
while (s = args[i++])
51
{
52
if (isdigit(*s))
53
v = strton(s, &e, NiL, 0);
54
else
55
{
56
e = (char*)s;
57
if (e[0] == 'n' && e[1] == 'o')
58
{
59
e += 2;
60
v = 0;
61
}
62
else
63
v = 1;
64
}
65
if (!*e)
66
{
67
if (v < MINLEVEL || v > MAXLEVEL)
68
{
69
if (p->disc->errorf)
70
(*p->disc->errorf)(NiL, p->disc, 2, "%s: compression level must be in [%d..%d]", s, MINLEVEL, MAXLEVEL);
71
return -1;
72
}
73
level = v;
74
}
75
else if (!streq(e, "crc"))
76
crc = v;
77
else
78
{
79
if (p->disc->errorf)
80
(*p->disc->errorf)(NiL, p->disc, 2, "%s: unknown option", s);
81
return -1;
82
}
83
}
84
if (!(p->op = sfopen(NiL, "/dev/null", (p->flags & CODEX_DECODE) ? "r" : "w")))
85
{
86
if (p->disc->errorf)
87
(*p->disc->errorf)(NiL, p->disc, 2, "cannot swap main stream");
88
return -1;
89
}
90
sfswap(p->op, p->sp);
91
if (!(state = newof(0, State_t, 1, 0)))
92
{
93
if (p->disc->errorf)
94
(*p->disc->errorf)(NiL, p->disc, 2, "out of space");
95
return -1;
96
}
97
state->codex = p;
98
state->crc = crc;
99
state->level = level;
100
p->data = state;
101
return 0;
102
}
103
104
static int
105
gzip_init(Codex_t* p)
106
{
107
State_t* state = (State_t*)p->data;
108
char* m;
109
char mode[8];
110
111
m = mode;
112
if (p->flags & CODEX_ENCODE)
113
*m++ = 'w';
114
else
115
*m++ = 'r';
116
*m++ = 'b';
117
if (!state->crc)
118
*m++ = 'c';
119
*m++ = 'o';
120
*m++ = '0' + state->level;
121
*m = 0;
122
return (state->gz = gzfopen(p->op, mode)) ? 0 : -1;
123
}
124
125
static int
126
gzip_done(Codex_t* p)
127
{
128
State_t* state = (State_t*)p->data;
129
int r;
130
131
r = gzclose(state->gz) ? -1 : 0;
132
free(state);
133
return r;
134
}
135
136
static ssize_t
137
gzip_read(Sfio_t* f, Void_t* buf, size_t n, Sfdisc_t* dp)
138
{
139
return gzread(((State_t*)CODEX(dp)->data)->gz, buf, n);
140
}
141
142
static ssize_t
143
gzip_write(Sfio_t* f, const Void_t* buf, size_t n, Sfdisc_t* dp)
144
{
145
return gzwrite(((State_t*)CODEX(dp)->data)->gz, buf, n);
146
}
147
148
Codexmeth_t codex_gzip =
149
{
150
"gzip",
151
"gzip compression. The first parameter is the compression level,"
152
" " S(MINLEVEL) ":least, " S(MAXLEVEL) ":most(default). nocrc disables crc checks.",
153
0,
154
CODEX_DECODE|CODEX_ENCODE|CODEX_COMPRESS,
155
0,
156
gzip_ident,
157
gzip_open,
158
0,
159
gzip_init,
160
gzip_done,
161
gzip_read,
162
gzip_write,
163
0,
164
0,
165
0,
166
0,
167
0,
168
CODEXNEXT(gzip)
169
};
170
171
CODEXLIB(gzip)
172
173