Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/lib/libz/sfdcgzip.c
1808 views
1
/***********************************************************************
2
* *
3
* This software is part of the zlib package *
4
* Copyright (c) 1995-2009 Jean-loup Gailly and Mark Adler *
5
* *
6
* This software is provided 'as-is', without any express or implied *
7
* warranty. In no event will the authors be held liable for any *
8
* damages arising from the use of this software. *
9
* *
10
* Permission is granted to anyone to use this software for any *
11
* purpose, including commercial applications, and to alter it and *
12
* redistribute it freely, subject to the following restrictions: *
13
* *
14
* 1. The origin of this software must not be misrepresented; *
15
* you must not claim that you wrote the original software. If *
16
* you use this software in a product, an acknowledgment in the *
17
* product documentation would be appreciated but is not *
18
* required. *
19
* *
20
* 2. Altered source versions must be plainly marked as such, *
21
* and must not be misrepresented as being the original *
22
* software. *
23
* *
24
* 3. This notice may not be removed or altered from any source *
25
* distribution. *
26
* *
27
* This software is provided "as-is", without any express or implied *
28
* warranty. In no event will the authors be held liable for any damages*
29
* arising from the use of this software. *
30
* *
31
* Permission is granted to anyone to use this software for any purpose,*
32
* including commercial applications, and to alter it and redistribute i*
33
* freely, subject to the following restrictions: *
34
* *
35
* 1. The origin of this software must not be misrepresented; you must n*
36
* claim that you wrote the original software. If you use this softwa*
37
* in a product, an acknowledgment in the product documentation would*
38
* be appreciated but is not required. *
39
* *
40
* 2. Altered source versions must be plainly marked as such, and must n*
41
* be misrepresented as being the original software. *
42
* *
43
* 3. This notice may not be removed or altered from any source *
44
* distribution. *
45
* *
46
* Jean-loup Gailly *
47
* Mark Adler *
48
* *
49
***********************************************************************/
50
#pragma prototyped
51
52
/*
53
* sfio gzip discipline
54
*
55
* handles { gzip compress vczip } on input
56
* handles { gzip compress } on output
57
*/
58
59
#include <sfio_t.h>
60
#include <ast.h>
61
#include <zlib.h>
62
#include <sfdcgzip.h>
63
64
#ifdef z_off64_t
65
#undef z_off_t
66
#define z_off_t z_off64_t
67
#undef gzsync
68
#define gzsync gzsync64
69
#endif
70
71
typedef struct
72
{
73
Sfdisc_t disc; /* sfio discipline */
74
gzFile* gz; /* gz handle */
75
Sfio_t* op; /* original stream */
76
} Sfgzip_t;
77
78
/*
79
* gzip exception handler
80
* free on close
81
*/
82
83
static int
84
sfgzexcept(Sfio_t* sp, int op, void* val, Sfdisc_t* dp)
85
{
86
register Sfgzip_t* gz = (Sfgzip_t*)dp;
87
int f;
88
int r;
89
90
NoP(sp);
91
#if 0
92
{
93
static char aha[] = "AHA sfdcgzip event 0\n";
94
static int init;
95
96
if (!init)
97
init = getenv("SFGZ_DEBUG") ? 1 : -1;
98
if (init > 0)
99
{
100
aha[sizeof(aha) - 3] = '0' + op;
101
write(2, aha, sizeof(aha) - 1);
102
}
103
}
104
#endif
105
switch (op)
106
{
107
case SF_ATEXIT:
108
sfdisc(sp, SF_POPDISC);
109
return 0;
110
case SF_CLOSING:
111
case SF_DPOP:
112
case SF_FINAL:
113
if (gz->gz)
114
{
115
SFDCNEXT(sp, f);
116
if (r = gzclose(gz->gz) ? -1 : 0)
117
sp->_flags |= SF_ERROR;
118
gz->gz = 0;
119
SFDCPREV(sp, f);
120
}
121
else
122
r = 0;
123
if (gz->op)
124
{
125
sfclose(gz->op);
126
gz->op = 0;
127
}
128
if (op != SF_CLOSING)
129
free(dp);
130
return r;
131
case SF_DBUFFER:
132
return 1;
133
case SF_SYNC:
134
if (!val && gzsync(gz->gz, (z_off_t)(-1)) < 0)
135
sp->_flags |= SF_ERROR;
136
return 0;
137
case SFGZ_HANDLE:
138
return (*((gzFile**)val) = gz->gz) ? 1 : -1;
139
case SFGZ_GETPOS:
140
return (*((Sfoff_t*)val) = gzsync(gz->gz, (z_off_t)(-1))) < 0 ? -1 : 0;
141
case SFGZ_SETPOS:
142
return gzsync(gz->gz, (z_off_t)(*((Sfoff_t*)val))) < 0 ? -1 : 0;
143
}
144
return 0;
145
}
146
147
/*
148
* sfio gzip discipline seek
149
*/
150
151
static Sfoff_t
152
sfgzseek(Sfio_t* fp, Sfoff_t off, int op, Sfdisc_t* dp)
153
{
154
return sfsk(fp, off, op, dp);
155
}
156
157
/*
158
* sfio gzip discipline read
159
*/
160
161
static ssize_t
162
sfgzread(Sfio_t* fp, Void_t* buf, size_t size, Sfdisc_t* dp)
163
{
164
register Sfgzip_t* gz = (Sfgzip_t*)dp;
165
166
return gzread(gz->gz, buf, size);
167
}
168
169
/*
170
* sfio gzip discipline write
171
*/
172
173
static ssize_t
174
sfgzwrite(Sfio_t* fp, const Void_t* buf, size_t size, Sfdisc_t* dp)
175
{
176
register Sfgzip_t* gz = (Sfgzip_t*)dp;
177
178
return gzwrite(gz->gz, (void*)buf, size);
179
}
180
181
/*
182
* create and push the sfio gzip discipline
183
*
184
* (flags&SFGZ_VERIFY) return
185
* >0 is a { g:gzip c:compress v:vczip } file
186
* 0 not a { gzip compress vczip } file
187
* <0 error
188
* otherwise return
189
* >0 discipline pushed { g:gzip c:compress v:vczip }
190
* 0 discipline not needed
191
* <0 error
192
*/
193
194
#undef PRIVATE
195
#define PRIVATE 0
196
197
int
198
sfdcgzip(Sfio_t* sp, int flags)
199
{
200
char* m;
201
Sfgzip_t* gz;
202
int fd;
203
int rd;
204
size_t z;
205
char mode[10];
206
207
rd = sfset(sp, 0, 0) & SF_READ;
208
if (rd)
209
{
210
register unsigned char* s;
211
register int n;
212
register int r;
213
214
/*
215
* peek the first 4 bytes to verify the magic
216
*
217
* 0x1f8b.... sfdcgzip gzip
218
* 0x1f9d.... sfdclzw compress
219
* 0xd6c3c4d8 sfpopen vcunzip
220
*/
221
222
#if PRIVATE
223
if (!(n = sfset(sp, 0, 0) & SF_SHARE))
224
sfset(sp, SF_SHARE, 1);
225
#endif
226
s = (unsigned char*)sfreserve(sp, 4, SF_LOCKR);
227
#if PRIVATE
228
if (!n)
229
sfset(sp, SF_SHARE, 0);
230
#endif
231
if (!s)
232
return -1;
233
n = 0;
234
if (s[0] == 0x1f)
235
{
236
if (s[1] == 0x8b)
237
n = 'g';
238
else if (s[1] == 0x9d)
239
n = 'c';
240
}
241
else if (s[0] == 0xd6 && s[1] == 0xc3 && s[2] == 0xc4 && s[3] == 0xd8)
242
n = 'v';
243
sfread(sp, s, 0);
244
if (!n)
245
return 0;
246
if (flags & SFGZ_VERIFY)
247
return n != 0;
248
switch (n)
249
{
250
case 'c':
251
return (r = sfdclzw(sp, flags)) > 0 ? 'c' : r;
252
case 'v':
253
r = 0;
254
n = dup(0);
255
close(0);
256
if (dup(sffileno(sp)) || !sfpopen(sp, "vcunzip", "r"))
257
r = -1;
258
close(0);
259
if (n > 0 && dup(n))
260
r = -1;
261
close(n);
262
return r > 0 ? 'v' : r;
263
}
264
}
265
else if (flags & SFGZ_VERIFY)
266
return -1;
267
if (!(gz = newof(0, Sfgzip_t, 1, 0)))
268
return -1;
269
gz->disc.exceptf = sfgzexcept;
270
if (rd)
271
gz->disc.readf = sfgzread;
272
else
273
gz->disc.writef = sfgzwrite;
274
gz->disc.seekf = sfgzseek;
275
m = mode;
276
*m++ = rd ? 'r' : 'w';
277
*m++ = 'b';
278
if (flags & SFGZ_NOCRC)
279
*m++ = 'n';
280
*m++ = 'o';
281
if ((flags &= 0xf) > 0 && flags <= 9)
282
*m++ = '0' + flags;
283
*m = 0;
284
#if PRIVATE
285
sfset(sp, SF_SHARE|SF_PUBLIC, 0);
286
#endif
287
if (!rd)
288
{
289
m = 0;
290
z = 0;
291
}
292
else if (!(z = sfreserve(sp, 0, -1) ? (size_t)sfvalue(sp) : 0))
293
m = 0;
294
else if (m = sfreserve(sp, z, 0))
295
z = (size_t)sfvalue(sp);
296
else
297
z = 0;
298
fd = sffileno(sp);
299
if (rd && (gz->op = sfopen(NiL, "/dev/null", "r")))
300
sfswap(sp, gz->op);
301
if (!(gz->gz = gzbopen(fd, mode, m, z)) || sfdisc(sp, &gz->disc) != &gz->disc)
302
{
303
free(gz);
304
return -1;
305
}
306
#if PRIVATE
307
#if 0
308
{
309
char* v;
310
long n;
311
312
if ((v = getenv("SFGZ_sfdcgzip_bufsize")) || (v = getenv("SFGZ_bufsize")))
313
{
314
if ((n = strtol(v, NiL, 0)) > 0)
315
sfsetbuf(sp, NiL, n);
316
}
317
else
318
sfsetbuf(sp, NiL, SF_BUFSIZE);
319
}
320
#else
321
sfsetbuf(sp, NiL, SF_BUFSIZE);
322
#endif
323
#endif
324
if (!rd)
325
sfset(sp, SF_IOCHECK, 1);
326
return 'g';
327
}
328
329
#if __OBSOLETE__ < 19990717
330
331
#if defined(__EXPORT__)
332
#define extern __EXPORT__
333
#endif
334
335
extern int
336
sfgzip(Sfio_t* sp)
337
{
338
return sfdcgzip(sp, 0);
339
}
340
341
#undef extern
342
343
#endif
344
345