Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/lib/libpz/pzopen.c
1808 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1998-2011 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* Glenn Fowler <[email protected]> *
18
* *
19
***********************************************************************/
20
#pragma prototyped
21
22
/*
23
* partitioned fixed record zip implementation
24
*/
25
26
#include "pzlib.h"
27
28
#include <ls.h>
29
30
Pzstate_t state = { "libpz:pz" };
31
32
/*
33
* print message and fail on VM_BADADDR,VM_NOMEM
34
*/
35
36
static int
37
nomalloc(Vmalloc_t* region, int type, void* obj, Vmdisc_t* disc)
38
{
39
Pz_t* pz = (Pz_t*)((char*)disc - offsetof(Pz_t, vmdisc));
40
Vmstat_t st;
41
42
switch (type)
43
{
44
case VM_BADADDR:
45
if (pz->disc->errorf)
46
(*pz->disc->errorf)(pz, pz->disc, ERROR_SYSTEM|2, "invalid pointer %p passed to free or realloc", obj);
47
return -1;
48
case VM_NOMEM:
49
if (pz->disc->errorf)
50
{
51
vmstat(region, &st);
52
(*pz->disc->errorf)(pz, pz->disc, ERROR_SYSTEM|2, "storage allocator out of space on %lu byte request ( region %lu segments %lu busy %lu:%lu:%lu free %lu:%lu:%lu )", (size_t)obj, st.extent, st.n_seg, st.n_busy, st.s_busy, st.m_busy, st.n_free, st.s_free, st.m_free);
53
}
54
return -1;
55
}
56
return 0;
57
}
58
59
/*
60
* find and open file with optional suffix and sfio mode
61
*/
62
63
Sfio_t*
64
pzfind(Pz_t* pz, const char* file, const char* suffix, const char* mode)
65
{
66
Sfio_t* sp;
67
char buf[PATH_MAX];
68
69
if (!(sp = sfopen(NiL, file, mode)))
70
{
71
if (!pathfind(file, pz->disc->lib ? pz->disc->lib : pz->id, suffix, buf, sizeof(buf)))
72
{
73
if (pz->disc->errorf)
74
(*pz->disc->errorf)(pz, pz->disc, ERROR_SYSTEM|2, "%s: cannot find %s file", file, suffix ? suffix : "data");
75
return 0;
76
}
77
if (!(sp = sfopen(NiL, buf, mode)))
78
{
79
if (pz->disc->errorf)
80
(*pz->disc->errorf)(pz, pz->disc, ERROR_SYSTEM|2, "%s: cannot read", buf);
81
return 0;
82
}
83
}
84
return sp;
85
}
86
87
/*
88
* open a new pz stream
89
*/
90
91
Pz_t*
92
pzopen(Pzdisc_t* disc, const char* path, unsigned long flags)
93
{
94
register Pz_t* pz;
95
Vmalloc_t* vm;
96
struct stat st;
97
98
if (flags & PZ_AGAIN)
99
{
100
pz = (Pz_t*)path;
101
pz->mainpart = 0;
102
pz->flags &= ~PZ_HEAD;
103
}
104
else
105
{
106
if (!(vm = vmopen(Vmdcheap, Vmlast, 0)))
107
return 0;
108
if (!(pz = vmnewof(vm, 0, Pz_t, 1, 0)) || !(pz->tmp = sfstropen()) || !(pz->str = sfstropen()) || (flags & PZ_WRITE) && !(pz->det = sfstropen()))
109
goto bad;
110
pz->vmdisc = *Vmdcheap;
111
pz->vmdisc.exceptf = nomalloc;
112
if (!vmdisc(vm, &pz->vmdisc))
113
goto bad;
114
tvgettime(&pz->start);
115
pz->major = PZ_MAJOR;
116
pz->minor = PZ_MINOR;
117
pz->id = state.id;
118
pz->disc = disc;
119
pz->flags = flags|PZ_MAINONLY;
120
pz->vm = vm;
121
pz->win = disc->window ? disc->window : PZ_WINDOW;
122
if (!path)
123
{
124
if (!isatty(sffileno(sfstdin)))
125
{
126
pz->path = "/dev/stdin";
127
if (!(pz->io = sfnew(NiL, NiL, SF_UNBOUND, sffileno(sfstdin), SF_READ)))
128
{
129
if (disc->errorf)
130
(*disc->errorf)(pz, disc, 2, "%s: cannot read", pz->path);
131
goto bad;
132
}
133
}
134
else if (!(pz->io = sfopen(NiL, pz->path = "/dev/null", "r")))
135
{
136
if (disc->errorf)
137
(*disc->errorf)(pz, disc, 2, "%s: cannot read", path);
138
goto bad;
139
}
140
else
141
pz->flags |= PZ_STREAM;
142
}
143
else if (pz->flags & PZ_STREAM)
144
{
145
pz->path = "stream";
146
pz->io = (Sfio_t*)path;
147
}
148
else if (!(pz->io = strneq(path, "pipe://", 7) ? sfpopen(NiL, path + 7, "r") : sfopen(NiL, path, "r")))
149
{
150
if (disc->errorf)
151
(*disc->errorf)(pz, disc, 2, "%s: cannot read", path);
152
goto bad;
153
}
154
else if (!(pz->path = vmstrdup(vm, path)))
155
goto bad;
156
157
/*
158
* without this large .pz and .gz terminate short of EOF
159
*/
160
161
if (!(pz->test & 0x00001000))
162
sfsetbuf(pz->io, (void*)pz->io, SF_UNBOUND);
163
if (pz->flags & PZ_DIO)
164
sfdcdio(pz->io, 0);
165
166
/*
167
* there is an sfio discipline bug (probably usage,
168
* not implementation) for piped input; the S_ISFIFO
169
* test avoids the bug until the root problem is fixed
170
*/
171
172
if (!fstat(sffileno(pz->io), &st) && S_ISFIFO(st.st_mode))
173
pz->flags &= ~PZ_CRC;
174
else if (!(pz->flags & PZ_POP) && (!(pz->flags & PZ_WRITE) && sfdcgzip(pz->io, (pz->flags & PZ_CRC) ? 0 : SFGZ_NOCRC) > 0 || (pz->flags & (PZ_PUSHED|PZ_WRITE)) == PZ_WRITE && sfdcpzip((Sfio_t*)pz, pz->path, pz->flags|PZ_FORCE|PZ_PUSHED|PZ_HANDLE, disc) > 0))
175
pz->flags |= PZ_POP;
176
else
177
pz->flags &= ~PZ_CRC;
178
pz->oip = pz->io;
179
if (disc->initf && !(*disc->initf)(pz, disc))
180
goto bad;
181
if (disc->options && (!(pz->options = vmstrdup(pz->vm, disc->options)) || pzoptions(pz, NiL, pz->options, 0) < 0))
182
goto bad;
183
}
184
if ((pz->flags & (PZ_READ|PZ_SPLIT|PZ_STAT)) || !disc->partition)
185
{
186
if (pzheadread(pz))
187
goto bad;
188
if ((pz->flags & PZ_SPLIT) && disc->partition && pzpartition(pz, disc->partition))
189
goto bad;
190
if (pz->options && pzoptions(pz, pz->part, pz->options, 1) < 0)
191
goto bad;
192
}
193
else
194
{
195
if (disc->partition && pzpartition(pz, disc->partition))
196
goto bad;
197
if (pz->disc->version >= PZ_VERSION_SPLIT && pz->disc->splitf)
198
{
199
pz->split.flags |= PZ_SPLIT_DEFLATE;
200
pz->flags |= PZ_ACCEPT|PZ_SECTION;
201
pz->flags &= ~PZ_SORT;
202
}
203
if (pz->options && pzoptions(pz, pz->part, pz->options, 1) < 0)
204
goto bad;
205
if ((pz->flags & (PZ_NOPZIP|PZ_UNKNOWN)) == PZ_UNKNOWN && !pz->disc->readf && !pz->disc->splitf)
206
{
207
if (pz->disc->errorf)
208
(*pz->disc->errorf)(pz, pz->disc, 2, "%s: unknown input format", pz->path);
209
goto bad;
210
}
211
}
212
213
/*
214
* ready to process
215
*/
216
217
pz->part = pz->mainpart;
218
if (pz->disc->eventf && (*pz->disc->eventf)(pz, (flags & PZ_AGAIN) ? PZ_REOPEN : PZ_OPEN, NiL, 0, pz->disc) < 0)
219
goto bad;
220
if (pz->disc->errorf)
221
(*pz->disc->errorf)(pz, pz->disc, -1, "%s: pzopen: flags=%08x win=(%I*u:%I*u) row=(%I*u:%I*u) buf=%p wrk=%p", pz->path, pz->flags, sizeof(pz->win), pz->win, sizeof(pz->mwin), pz->mwin, sizeof(pz->row), pz->row, sizeof(pz->mrow), pz->mrow, pz->buf, pz->wrk);
222
return pz;
223
bad:
224
pzclose(pz);
225
return 0;
226
}
227
228
/*
229
* close an open pz stream
230
*/
231
232
int
233
pzclose(register Pz_t* pz)
234
{
235
int r;
236
unsigned long e;
237
Sfoff_t p;
238
Sfio_t* op;
239
Tv_t now;
240
241
if (!pz)
242
return -1;
243
if (!(r = pzsync(pz)) && (op = pz->ws.io))
244
{
245
/*
246
* finish up the pzwrite() stream
247
*/
248
249
sfputu(op, 0);
250
if (pz->ws.pc)
251
{
252
if (pz->disc->errorf)
253
(*pz->disc->errorf)(pz, pz->disc, 1, "last record incomplete %u/%u", pz->ws.pc, pz->row);
254
sfputc(op, PZ_MARK_PART);
255
sfputu(op, pz->ws.pc);
256
sfwrite(op, pz->ws.pb, pz->ws.pc);
257
}
258
if (!(pz->flags & PZ_SECTION))
259
{
260
sfputc(op, PZ_MARK_TAIL);
261
if (pz->disc->eventf && (*pz->disc->eventf)(pz, PZ_TAILWRITE, op, 0, pz->disc) < 0)
262
return -1;
263
sfputc(op, 0);
264
}
265
if (sfsync(op))
266
{
267
if (pz->disc->errorf)
268
(*pz->disc->errorf)(pz, pz->disc, ERROR_SYSTEM|2, "write error");
269
return -1;
270
}
271
}
272
if ((pz->flags & PZ_WRITE) && (pz->flags & (PZ_DUMP|PZ_VERBOSE|PZ_SUMMARY)) && pz->disc->errorf && pz->count.records)
273
{
274
if (!pz->count.uncompressed)
275
pz->count.uncompressed = pz->part->row * pz->count.records;
276
if (!pz->count.compressed)
277
{
278
pz->count.compressed = pz->count.uncompressed;
279
if (pz->oop)
280
{
281
if (!(pz->flags & PZ_NOGZIP))
282
while (sfdisc(pz->oop, SF_POPDISC));
283
if ((p = sfsize(pz->oop)) > 0)
284
pz->count.compressed = p;
285
}
286
}
287
if (pz->flags & PZ_REGRESS)
288
e = 100;
289
else
290
{
291
tvgettime(&now);
292
if (!(e = ((unsigned long)now.tv_sec - (unsigned long)pz->start.tv_sec) * 100 + ((long)now.tv_nsec - (long)pz->start.tv_nsec) / 10000000L))
293
e = 1;
294
}
295
sfprintf(pz->tmp, _("total %s rate %.2f time %s bpr %.2f bps %s size %I*u/%I*u windows %I*u")
296
, pz->path
297
, (double)((Sflong_t)pz->count.uncompressed) / (double)((Sflong_t)pz->count.compressed)
298
, fmtelapsed(e, 100)
299
, (double)((Sflong_t)pz->count.compressed) / (double)((Sflong_t)pz->count.records)
300
, fmtnum((pz->count.uncompressed * 100) / e, 0)
301
, sizeof(pz->count.uncompressed)
302
, pz->count.uncompressed
303
, sizeof(pz->count.compressed)
304
, pz->count.compressed
305
, sizeof(pz->count.windows)
306
, pz->count.windows
307
);
308
if (pz->count.sections)
309
sfprintf(pz->tmp, _(" sections %I*u")
310
, sizeof(pz->count.sections)
311
, pz->count.sections
312
);
313
sfprintf(pz->tmp, _(" records %I*u")
314
, sizeof(pz->count.records)
315
, pz->count.records
316
);
317
if (pz->count.modules)
318
sfprintf(pz->tmp, _(" modules %I*u")
319
, sizeof(pz->count.modules)
320
, pz->count.modules
321
);
322
if (pz->count.converted)
323
sfprintf(pz->tmp, _(" converted %I*u")
324
, sizeof(pz->count.converted)
325
, pz->count.converted
326
);
327
if (pz->count.repaired)
328
sfprintf(pz->tmp, _(" repaired %I*u")
329
, sizeof(pz->count.repaired)
330
, pz->count.repaired
331
);
332
if (pz->count.truncated)
333
sfprintf(pz->tmp, _(" truncated %I*u")
334
, sizeof(pz->count.truncated)
335
, pz->count.truncated
336
);
337
if (pz->count.dropped)
338
sfprintf(pz->tmp, _(" dropped %I*u")
339
, sizeof(pz->count.dropped)
340
, pz->count.dropped
341
);
342
(*pz->disc->errorf)(pz, pz->disc, 0, "%s", sfstruse(pz->tmp));
343
}
344
if (pz->io)
345
{
346
if (pz->oip)
347
{
348
if (pz->disc->eventf)
349
r = (*pz->disc->eventf)(pz, PZ_CLOSE, NiL, 0, pz->disc);
350
if (!(pz->flags & PZ_STREAM))
351
{
352
if (sfclose(pz->oip) < 0)
353
{
354
if (pz->disc->errorf)
355
(*pz->disc->errorf)(pz, pz->disc, ERROR_SYSTEM|2, "%s: data corrupted (close error)", pz->path);
356
r = -1;
357
}
358
}
359
else if (pz->flags & PZ_POP)
360
sfdisc(pz->oip, SF_POPDISC);
361
pz->oip = 0;
362
}
363
else if (pz->flags & PZ_POP)
364
{
365
sfdisc(pz->io, SF_POPDISC);
366
if (sferror(pz->io))
367
{
368
pz->flags |= PZ_ERROR;
369
if (pz->disc->errorf)
370
(*pz->disc->errorf)(pz, pz->disc, ERROR_SYSTEM|2, (pz->flags & PZ_WRITE) ? "write error" : "read error");
371
}
372
}
373
}
374
if (pz->flags & PZ_ERROR)
375
r = -1;
376
if (pz->partdict)
377
dtclose(pz->partdict);
378
if (pz->vm)
379
vmclose(pz->vm);
380
if (pz->tmp)
381
sfclose(pz->tmp);
382
if (pz->str)
383
sfclose(pz->str);
384
if (pz->det)
385
sfclose(pz->det);
386
return r;
387
}
388
389
/*
390
* common out of space message
391
*/
392
393
int
394
pznospace(Pz_t* pz)
395
{
396
if (pz->disc->errorf)
397
(*pz->disc->errorf)(pz, pz->disc, ERROR_SYSTEM|2, "out of space");
398
return -1;
399
}
400
401
402