rpm 5.2.1

- Main Page
- Related Pages
- Modules
- Data Structures
- Files

- File List
- Globals

bzdio.c
Go to the documentation of this file.
1
6 #include "system.h"
7 #include "rpmio_internal.h"
8 #include <rpmmacro.h>
9 #include <rpmcb.h>
10
11 #if defined(WITH_BZIP2)
12
13 #define _RPMBZ_INTERNAL
14 #include "rpmbz.h"
15
16 #include "debug.h"
17
18 /*@access FD_t @*/
19
20 #define BZDONLY(fd) assert(fdGetIo(fd) == bzdio)
21
22 static const char * rpmbzStrerror(rpmbz bz)
23 /*@*/
24 {
25 return BZ2_bzerror(bz->bzfile, &bz->bzerr);
26 }
27
28 /*@-mustmod@*/
29 static void rpmbzClose(rpmbz bz, int abort, /*@null@*/ const char ** errmsg)
30 /*@modifies bz, *errmsg @*/
31 {
32 if (bz->bzfile != NULL) {
33 if (bz->omode == O_RDONLY)
34 BZ2_bzReadClose(&bz->bzerr, bz->bzfile);
35 else
36 BZ2_bzWriteClose(&bz->bzerr, bz->bzfile, abort,
37 &bz->nbytes_in, &bz->nbytes_out);
38 /*@-usereleased@*/ /* XXX does bz->bzfile persist after *Close? */
39 if (bz->bzerr != BZ_OK && errmsg)
40 *errmsg = rpmbzStrerror(bz);
41 /*@=usereleased@*/
42 }
43 bz->bzfile = NULL;
44 }
45 /*@=mustmod@*/
46
47 /*@only@*/ /*@null@*/
48 static rpmbz rpmbzFree(/*@only@*/ rpmbz bz, int abort)
49 /*@globals fileSystem @*/
50 /*@modifies bz, fileSystem @*/
51 {
52 rpmbzClose(bz, abort, NULL);
53 if (bz->fp != NULL) {
54 (void) fclose(bz->fp);
55 bz->fp = NULL;
56 }
57 return rpmbzFini(bz);
58 }
59
60 /*@-mustmod@*/
61 /*@only@*/
62 static rpmbz rpmbzNew(const char * path, const char * fmode, int fdno)
63 /*@globals fileSystem @*/
64 /*@modifies fileSystem @*/
65 {
66 rpmbz bz;
67 int level = -1; /* XXX use _bzdB default */
68 mode_t omode = O_RDONLY;
69 int small = -1; /* XXX use _bzdS default */
70 int verbosity = -1; /* XXX use _bzdV default */
71 const char * s = fmode;
72 char stdio[20];
73 char *t = stdio;
74 char *te = t + sizeof(stdio) - 2;
75 int c;
76
77 assert(fmode != NULL); /* XXX return NULL instead? */
78
79 switch ((c = *s++)) {
80 case 'a':
81 case 'w':
82 omode = O_WRONLY;
83 *t++ = (char)c;
84 break;
85 case 'r':
86 omode = O_RDONLY;
87 *t++ = (char)c;
88 break;
89 }
90
91 while ((c = *s++) != 0) {
92 switch (c) {
93 case '.':
94 /*@switchbreak@*/ break;
95 case '+':
96 case 'x':
97 case 'm':
98 case 'c':
99 case 'b':
100 if (t < te) *t++ = c;
101 /*@switchbreak@*/ break;
102 case 's':
103 if (small < 0) small = 0;
104 small++;
105 /*@switchbreak@*/ break;
106 case 'q':
107 verbosity = 0;
108 /*@switchbreak@*/ break;
109 case 'v':
110 if (verbosity < 0) verbosity = 0;
111 if (verbosity < 4) verbosity++;
112 /*@switchbreak@*/ break;
113 default:
114 if (c >= (int)'0' && c <= (int)'9')
115 level = c - (int)'0';
116 /*@switchbreak@*/ break;
117 }}
118 *t = '\0';
119
120 bz = rpmbzInit(level, small, verbosity, omode);
121
122 if (fdno >= 0) {
123 if ((bz->fp = fdopen(fdno, stdio)) != NULL)
124 bz->bzfile = (bz->omode == O_RDONLY)
125 ? BZ2_bzReadOpen(&bz->bzerr, bz->fp, bz->V, bz->S, NULL, 0)
126 : BZ2_bzWriteOpen(&bz->bzerr, bz->fp, bz->B, bz->V, bz->W);
127 } else if (path != NULL) {
128 if ((bz->fp = fopen(path, stdio)) != NULL)
129 bz->bzfile = (bz->omode == O_RDONLY)
130 ? BZ2_bzReadOpen(&bz->bzerr, bz->fp, bz->V, bz->S, NULL, 0)
131 : BZ2_bzWriteOpen(&bz->bzerr, bz->fp, bz->B, bz->V, bz->W);
132 }
133
134 /*@-usereleased@*/
135 return (bz->bzfile != NULL ? bz : rpmbzFree(bz, 0));
136 /*@=usereleased@*/
137 }
138 /*@=mustmod@*/
139
140 #ifdef NOTYET
141 /*@-mustmod -nullstate@*/
142 static void rpmbzCompress(rpmbz bz, rpmzJob job)
143 /*@globals fileSystem @*/
144 /*@modifies bz, job, fileSystem @*/
145 {
146 bz_stream *bzstrm = &bz->strm;
147 size_t len; /* remaining bytes to compress/check */
148 int ret;
149
150 /* initialize the deflate stream for this block */
151 bzstrm->bzfree = NULL;
152 bzstrm->bzalloc = NULL;
153 bzstrm->opaque = NULL;
154 if ((ret = BZ2_bzCompressInit(bzstrm, bz->B, bz->V, bz->W)) != BZ_OK)
155 bail("not enough memory", "BZ2_bzCompressInit");
156
157 bzstrm->next_in = job->in->buf;
158 bzstrm->next_out = job->out->buf;
159 bzstrm->avail_out = job->out->len;
160
161 /* run _PIGZMAX-sized amounts of input through deflate -- this loop is
162 * needed for those cases where the integer type is smaller than the
163 * size_t type, or when len is close to the limit of the size_t type */
164 len = job->in->len;
165 while (len > _PIGZMAX) {
166 bzstrm->avail_in = _PIGZMAX;
167 if ((ret = BZ2_bzCompress(bzstrm, BZ_RUN)) != BZ_RUN_OK)
168 fprintf(stderr, "*** BZ2_bzCompress(%d): %d\n", BZ_RUN, ret);
169 assert(bzstrm->avail_in == 0 && bzstrm->avail_out != 0);
170 len -= _PIGZMAX;
171 }
172
173 /* run the last piece through deflate -- terminate with a sync marker,
174 * or finish deflate stream if this is the last block */
175 bzstrm->avail_in = (unsigned)len;
176 ret = BZ2_bzCompress(bzstrm, BZ_FINISH);
177 if (!(ret == BZ_FINISH_OK || ret == BZ_STREAM_END))
178 fprintf(stderr, "*** BZ2_bzCompress(%d): %d\n", BZ_FINISH, ret);
179 if ((ret = BZ2_bzCompressEnd(bzstrm)) != BZ_OK)
180 fprintf(stderr, "*** BZ2_bzCompressEnd: %d\n", ret);
181 #ifdef NOTYET
182 assert(bzstrm->avail_in == 0 && bzstrm->avail_out != 0);
183 #endif
184
185 }
186 /*@=mustmod =nullstate@*/
187
188 /*@-mustmod -nullstate@*/
189 static void rpmbzDecompress(rpmbz bz, rpmzJob job)
190 /*@globals fileSystem @*/
191 /*@modifies bz, job, fileSystem @*/
192 {
193 bz_stream *bzstrm = &bz->strm;
194 int ret;
195
196 /* initialize the inflate stream for this block */
197 bzstrm->bzfree = NULL;
198 bzstrm->bzalloc = NULL;
199 bzstrm->opaque = NULL;
200 if ((ret = BZ2_bzDecompressInit(bzstrm, bz->V, bz->S)) != BZ_OK)
201 bail("not enough memory", "BZ2_bzDecompressInit");
202
203 bzstrm->next_in = job->in->buf;
204 bzstrm->avail_in = job->in->len;
205 bzstrm->next_out = job->out->buf;
206 bzstrm->avail_out = job->out->len;
207
208 if ((ret = BZ2_bzDecompress(bzstrm)) != BZ_RUN_OK)
209 fprintf(stderr, "*** BZ2_bzDecompress: %d\n", ret);
210
211 job->out->len -= bzstrm->avail_out;
212
213 if ((ret = BZ2_bzDecompressEnd(bzstrm)) != BZ_OK)
214 fprintf(stderr, "*** BZ2_bzDecompressEnd: %d\n", ret);
215
216 }
217 /*@=mustmod =nullstate@*/
218 #endif /* NOTYET */
219
220 /*@-mustmod@*/
221 static ssize_t rpmbzRead(rpmbz bz, /*@out@*/ char * buf, size_t count,
222 /*@null@*/ const char ** errmsg)
223 /*@globals internalState @*/
224 /*@modifies bz, *buf, *errmsg, internalState @*/
225 {
226 ssize_t rc = 0;
227
228 #ifdef NOTYET /* XXX hmmm, read after close needs to return EOF. */
229 assert(bz->bzfile != NULL);
230 #else
231 if (bz->bzfile == NULL) return 0;
232 #endif
233 rc = BZ2_bzRead(&bz->bzerr, bz->bzfile, buf, (int)count);
234 switch (bz->bzerr) {
235 case BZ_STREAM_END: {
236 void * unused = NULL;
237 int nUnused = 0;
238
239 BZ2_bzReadGetUnused(&bz->bzerr, bz->bzfile, &unused, &nUnused);
240 if (unused != NULL && nUnused > 0)
241 unused = memcpy(xmalloc(nUnused), unused, nUnused);
242 else {
243 unused = NULL;
244 nUnused = 0;
245 }
246 rpmbzClose(bz, 0, NULL);
247 bz->bzfile = BZ2_bzReadOpen(&bz->bzerr, bz->fp, bz->V, bz->S,
248 unused, nUnused);
249 unused = _free(unused);
250 } /*@fallthrough@*/
251 case BZ_OK:
252 assert(rc >= 0);
253 break;
254 default:
255 rc = -1;
256 if (errmsg != NULL)
257 *errmsg = rpmbzStrerror(bz);
258 rpmbzClose(bz, 1, NULL);
259 break;
260 }
261 return rc;
262 }
263 /*@=mustmod@*/
264
265 static ssize_t rpmbzWrite(rpmbz bz, const char * buf, size_t count,
266 /*@null@*/ const char ** errmsg)
267 /*@globals internalState @*/
268 /*@modifies bz, *errmsg, internalState @*/
269 {
270 ssize_t rc;
271
272 assert(bz->bzfile != NULL); /* XXX TODO: lazy open? */
273 BZ2_bzWrite(&bz->bzerr, bz->bzfile, (void *)buf, (int)count);
274 switch (bz->bzerr) {
275 case BZ_OK:
276 rc = count;
277 break;
278 default:
279 if (errmsg != NULL)
280 *errmsg = rpmbzStrerror(bz);
281 rpmbzClose(bz, 1, NULL);
282 rc = -1;
283 break;
284 }
285 return rc;
286 }
287
288 static int rpmbzSeek(/*@unused@*/ void * _bz, /*@unused@*/ _libio_pos_t pos,
289 /*@unused@*/ int whence)
290 /*@*/
291 {
292 return -2;
293 }
294
295 static /*@null@*/ rpmbz rpmbzOpen(const char * path, const char * fmode)
296 /*@globals fileSystem, internalState @*/
297 /*@modifies fileSystem, internalState @*/
298 {
299 return rpmbzNew(path, fmode, -1);
300 }
301
302 static /*@null@*/ rpmbz rpmbzFdopen(void * _fdno, const char * fmode)
303 /*@globals fileSystem, internalState @*/
304 /*@modifies fileSystem, internalState @*/
305 {
306 int fdno = (int)_fdno; /* XXX hack */
307 return rpmbzNew(NULL, fmode, fdno);
308 }
309
310 static int rpmbzFlush(void * _bz)
311 /*@*/
312 {
313 rpmbz bz = _bz;
314 return BZ2_bzflush(bz->bzfile);
315 }
316
317 /* =============================================================== */
318 static inline /*@dependent@*/ /*@null@*/ void * bzdFileno(FD_t fd)
319 /*@*/
320 {
321 void * rc = NULL;
322 int i;
323
324 FDSANE(fd);
325 for (i = fd->nfps; i >= 0; i--) {
326 FDSTACK_t * fps = &fd->fps[i];
327 if (fps->io != bzdio)
328 continue;
329 rc = fps->fp;
330 break;
331 }
332
333 return rc;
334 }
335
336 /*@-globuse@*/
337 static /*@null@*/ FD_t bzdOpen(const char * path, const char * fmode)
338 /*@globals fileSystem, internalState @*/
339 /*@modifies fileSystem, internalState @*/
340 {
341 FD_t fd;
342 rpmbz bz = rpmbzOpen(path, fmode);
343
344 if (bz == NULL)
345 return NULL;
346 fd = fdNew("open (bzdOpen)");
347 #ifdef NOTYET /* XXX persistent URI cache prevents fileno(bz->fp) */
348 fdPop(fd); fdPush(fd, bzdio, bz, fileno(bz->fp));
349 #else
350 fdPop(fd); fdPush(fd, bzdio, bz, -1);
351 #endif
352 fdSetOpen(fd, path, -1, bz->omode);
353 return fdLink(fd, "bzdOpen");
354 }
355 /*@=globuse@*/
356
357 /*@-globuse@*/
358 static /*@null@*/ FD_t bzdFdopen(void * cookie, const char * fmode)
359 /*@globals fileSystem, internalState @*/
360 /*@modifies fileSystem, internalState @*/
361 {
362 FD_t fd = c2f(cookie);
363 int fdno = fdFileno(fd);
364 rpmbz bz = rpmbzFdopen((void *)fdno, fmode);
365
366 if (bz == NULL)
367 return NULL;
368 #ifdef NOTYET /* XXX persistent URI cache prevents pop */
369 fdPop(fd); fdPush(fd, bzdio, bz, fileno(bz->fp));
370 #else
371 fdSetFdno(fd, -1); /* XXX skip the fdio close */
372 fdPush(fd, bzdio, bz, fdno); /* Push bzdio onto stack */
373 #endif
374 return fdLink(fd, "bzdFdopen");
375 }
376 /*@=globuse@*/
377
378 /*@-globuse@*/
379 static int bzdFlush(void * cookie)
380 /*@globals fileSystem @*/
381 /*@modifies fileSystem @*/
382 {
383 FD_t fd = c2f(cookie);
384 rpmbz bz = bzdFileno(fd);
385 return rpmbzFlush(bz);
386 }
387 /*@=globuse@*/
388
389 /*@-globuse@*/
390 /*@-mustmod@*/ /* LCL: *buf is modified */
391 static ssize_t bzdRead(void * cookie, /*@out@*/ char * buf, size_t count)
392 /*@globals fileSystem, internalState @*/
393 /*@modifies *buf, fileSystem, internalState @*/
394 {
395 FD_t fd = c2f(cookie);
396 rpmbz bz = bzdFileno(fd);
397 ssize_t rc = 0;
398
399 assert(bz != NULL);
400 if (fd->bytesRemain == 0) return 0; /* XXX simulate EOF */
401 fdstat_enter(fd, FDSTAT_READ);
402 /*@-modobserver@*/ /* FIX: is errcookie an observer? */
403 rc = rpmbzRead(bz, buf, count, (const char **)&fd->errcookie);
404 /*@=modobserver@*/
405 if (rc >= 0) {
406 fdstat_exit(fd, FDSTAT_READ, rc);
407 if (fd->ndigests && rc > 0) fdUpdateDigests(fd, (void *)buf, rc);
408 }
409 return rc;
410 }
411 /*@=mustmod@*/
412 /*@=globuse@*/
413
414 /*@-globuse@*/
415 static ssize_t bzdWrite(void * cookie, const char * buf, size_t count)
416 /*@globals fileSystem, internalState @*/
417 /*@modifies fileSystem, internalState @*/
418 {
419 FD_t fd = c2f(cookie);
420 rpmbz bz = bzdFileno(fd);
421 ssize_t rc;
422
423 assert(bz != NULL);
424 if (fd->bytesRemain == 0) return 0; /* XXX simulate EOF */
425
426 if (fd->ndigests && count > 0) fdUpdateDigests(fd, (void *)buf, count);
427
428 fdstat_enter(fd, FDSTAT_WRITE);
429 /*@-modobserver@*/ /* FIX: is errcookie an observer? */
430 rc = rpmbzWrite(bz, buf, count, (const char **)&fd->errcookie);
431 /*@=modobserver@*/
432 if (rc >= 0)
433 fdstat_exit(fd, FDSTAT_WRITE, rc);
434 return rc;
435 }
436 /*@=globuse@*/
437
438 static int bzdSeek(void * cookie, _libio_pos_t pos, int whence)
439 /*@*/
440 {
441 FD_t fd = c2f(cookie);
442 rpmbz bz = bzdFileno(fd);
443
444 assert(bz != NULL);
445 BZDONLY(fd);
446 return rpmbzSeek(bz, pos, whence);
447 }
448
449 static int bzdClose( /*@only@*/ void * cookie)
450 /*@globals fileSystem, internalState @*/
451 /*@modifies fileSystem, internalState @*/
452 {
453 FD_t fd = c2f(cookie);
454 rpmbz bz = bzdFileno(fd);
455 int rc;
456
457 assert(bz != NULL);
458 #ifdef DYING
459 if (bz->bzfile == NULL) /* XXX memory leak w errors? */
460 return -2;
461 #endif
462
463 fdstat_enter(fd, FDSTAT_CLOSE);
464 /*@-modobserver@*/ /* FIX: is errcookie an observer? */
465 rpmbzClose(bz, 0, (const char **)&fd->errcookie);
466 /*@=modobserver@*/
467 rc = 0; /* XXX FIXME */
468
469 /* XXX TODO: preserve fd if errors */
470
471 if (fd)
472 if (rc >= 0)
473 fdstat_exit(fd, FDSTAT_CLOSE, rc);
474
475 DBGIO(fd, (stderr, "==>\tbzdClose(%p) rc %lx %s\n", cookie, (unsigned long)rc, fdbg(fd)));
476
477 if (_rpmio_debug || rpmIsDebug()) fdstat_print(fd, "BZDIO", stderr);
478
479 if (rc == 0) {
480 /*@-dependenttrans@*/
481 bz = rpmbzFree(bz, 0);
482 /*@=dependenttrans@*/
483 fd = fdFree(fd, "open (bzdClose)");
484 }
485 return rc;
486 }
487
488 /*@-type@*/ /* LCL: function typedefs */
489 static struct FDIO_s bzdio_s = {
490 bzdRead, bzdWrite, bzdSeek, bzdClose, bzdOpen, bzdFdopen, bzdFlush,
491 };
492 /*@=type@*/
493
494 FDIO_t bzdio = /*@-compmempass@*/ &bzdio_s /*@=compmempass@*/ ;
495
496 #endif
497