rpm 5.2.1

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

- File List
- Globals

rpmio/bzdio.c
Go to the documentation of this file.

    00001
    00006 #include "system.h"
    00007 #include "rpmio_internal.h"
    00008 #include <rpmmacro.h>
    00009 #include <rpmcb.h>
    00010
    00011 #if defined(WITH_BZIP2)
    00012
    00013 #define _RPMBZ_INTERNAL
    00014 #include "rpmbz.h"
    00015
    00016 #include "debug.h"
    00017
    00018 /*@access FD_t @*/
    00019
    00020 #define BZDONLY(fd)     assert(fdGetIo(fd) == bzdio)
    00021
    00022 static const char * rpmbzStrerror(rpmbz bz)
    00023         /*@*/
    00024 {
    00025     return BZ2_bzerror(bz->bzfile, &bz->bzerr);
    00026 }
    00027
    00028 /*@-mustmod@*/
    00029 static void rpmbzClose(rpmbz bz, int abort, /*@null@*/ const char ** errmsg)
    00030         /*@modifies bz, *errmsg @*/
    00031 {
    00032     if (bz->bzfile != NULL) {
    00033         if (bz->omode == O_RDONLY)
    00034             BZ2_bzReadClose(&bz->bzerr, bz->bzfile);
    00035         else
    00036             BZ2_bzWriteClose(&bz->bzerr, bz->bzfile, abort,
    00037                 &bz->nbytes_in, &bz->nbytes_out);
    00038 /*@-usereleased@*/      /* XXX does bz->bzfile persist after *Close? */
    00039         if (bz->bzerr != BZ_OK && errmsg)
    00040             *errmsg = rpmbzStrerror(bz);
    00041 /*@=usereleased@*/
    00042     }
    00043     bz->bzfile = NULL;
    00044 }
    00045 /*@=mustmod@*/
    00046
    00047 /*@only@*/ /*@null@*/
    00048 static rpmbz rpmbzFree(/*@only@*/ rpmbz bz, int abort)
    00049         /*@globals fileSystem @*/
    00050         /*@modifies bz, fileSystem @*/
    00051 {
    00052     rpmbzClose(bz, abort, NULL);
    00053     if (bz->fp != NULL) {
    00054         (void) fclose(bz->fp);
    00055         bz->fp = NULL;
    00056     }
    00057     return rpmbzFini(bz);
    00058 }
    00059
    00060 /*@-mustmod@*/
    00061 /*@only@*/
    00062 static rpmbz rpmbzNew(const char * path, const char * fmode, int fdno)
    00063         /*@globals fileSystem @*/
    00064         /*@modifies fileSystem @*/
    00065 {
    00066     rpmbz bz;
    00067     int level = -1;     /* XXX use _bzdB default */
    00068     mode_t omode = O_RDONLY;
    00069     int small = -1;     /* XXX use _bzdS default */
    00070     int verbosity = -1; /* XXX use _bzdV default */
    00071     const char * s = fmode;
    00072     char stdio[20];
    00073     char *t = stdio;
    00074     char *te = t + sizeof(stdio) - 2;
    00075     int c;
    00076
    00077 assert(fmode != NULL);          /* XXX return NULL instead? */
    00078
    00079     switch ((c = *s++)) {
    00080     case 'a':
    00081     case 'w':
    00082         omode = O_WRONLY;
    00083         *t++ = (char)c;
    00084         break;
    00085     case 'r':
    00086         omode = O_RDONLY;
    00087         *t++ = (char)c;
    00088         break;
    00089     }
    00090
    00091     while ((c = *s++) != 0) {
    00092     switch (c) {
    00093     case '.':
    00094         /*@switchbreak@*/ break;
    00095     case '+':
    00096     case 'x':
    00097     case 'm':
    00098     case 'c':
    00099     case 'b':
    00100         if (t < te) *t++ = c;
    00101         /*@switchbreak@*/ break;
    00102     case 's':
    00103         if (small < 0) small = 0;
    00104         small++;
    00105         /*@switchbreak@*/ break;
    00106     case 'q':
    00107         verbosity = 0;
    00108         /*@switchbreak@*/ break;
    00109     case 'v':
    00110         if (verbosity < 0) verbosity = 0;
    00111         if (verbosity < 4) verbosity++;
    00112         /*@switchbreak@*/ break;
    00113     default:
    00114         if (c >= (int)'0' && c <= (int)'9')
    00115             level = c - (int)'0';
    00116         /*@switchbreak@*/ break;
    00117     }}
    00118     *t = '\0';
    00119
    00120     bz = rpmbzInit(level, small, verbosity, omode);
    00121
    00122     if (fdno >= 0) {
    00123         if ((bz->fp = fdopen(fdno, stdio)) != NULL)
    00124             bz->bzfile = (bz->omode == O_RDONLY)
    00125                 ? BZ2_bzReadOpen(&bz->bzerr, bz->fp, bz->V, bz->S, NULL, 0)
    00126                 : BZ2_bzWriteOpen(&bz->bzerr, bz->fp, bz->B, bz->V, bz->W);
    00127     } else if (path != NULL) {
    00128         if ((bz->fp = fopen(path, stdio)) != NULL)
    00129             bz->bzfile = (bz->omode == O_RDONLY)
    00130                 ? BZ2_bzReadOpen(&bz->bzerr, bz->fp, bz->V, bz->S, NULL, 0)
    00131                 : BZ2_bzWriteOpen(&bz->bzerr, bz->fp, bz->B, bz->V, bz->W);
    00132     }
    00133
    00134 /*@-usereleased@*/
    00135     return (bz->bzfile != NULL ? bz : rpmbzFree(bz, 0));
    00136 /*@=usereleased@*/
    00137 }
    00138 /*@=mustmod@*/
    00139
    00140 #ifdef  NOTYET
    00141 /*@-mustmod -nullstate@*/
    00142 static void rpmbzCompress(rpmbz bz, rpmzJob job)
    00143         /*@globals fileSystem @*/
    00144         /*@modifies bz, job, fileSystem @*/
    00145 {
    00146     bz_stream *bzstrm = &bz->strm;
    00147     size_t len;                 /* remaining bytes to compress/check */
    00148     int ret;
    00149
    00150     /* initialize the deflate stream for this block */
    00151     bzstrm->bzfree = NULL;
    00152     bzstrm->bzalloc = NULL;
    00153     bzstrm->opaque = NULL;
    00154     if ((ret = BZ2_bzCompressInit(bzstrm, bz->B, bz->V, bz->W)) != BZ_OK)
    00155         bail("not enough memory", "BZ2_bzCompressInit");
    00156
    00157     bzstrm->next_in = job->in->buf;
    00158     bzstrm->next_out = job->out->buf;
    00159     bzstrm->avail_out = job->out->len;
    00160
    00161     /* run _PIGZMAX-sized amounts of input through deflate -- this loop is
    00162     * needed for those cases where the integer type is smaller than the
    00163     * size_t type, or when len is close to the limit of the size_t type */
    00164     len = job->in->len;
    00165     while (len > _PIGZMAX) {
    00166         bzstrm->avail_in = _PIGZMAX;
    00167         if ((ret = BZ2_bzCompress(bzstrm, BZ_RUN)) != BZ_RUN_OK)
    00168             fprintf(stderr, "*** BZ2_bzCompress(%d): %d\n", BZ_RUN, ret);
    00169 assert(bzstrm->avail_in == 0 && bzstrm->avail_out != 0);
    00170         len -= _PIGZMAX;
    00171     }
    00172
    00173     /* run the last piece through deflate -- terminate with a sync marker,
    00174     * or finish deflate stream if this is the last block */
    00175     bzstrm->avail_in = (unsigned)len;
    00176     ret = BZ2_bzCompress(bzstrm, BZ_FINISH);
    00177     if (!(ret == BZ_FINISH_OK || ret == BZ_STREAM_END))
    00178         fprintf(stderr, "*** BZ2_bzCompress(%d): %d\n", BZ_FINISH, ret);
    00179     if ((ret = BZ2_bzCompressEnd(bzstrm)) != BZ_OK)
    00180         fprintf(stderr, "*** BZ2_bzCompressEnd: %d\n", ret);
    00181 #ifdef  NOTYET
    00182 assert(bzstrm->avail_in == 0 && bzstrm->avail_out != 0);
    00183 #endif
    00184
    00185 }
    00186 /*@=mustmod =nullstate@*/
    00187
    00188 /*@-mustmod -nullstate@*/
    00189 static void rpmbzDecompress(rpmbz bz, rpmzJob job)
    00190         /*@globals fileSystem @*/
    00191         /*@modifies bz, job, fileSystem @*/
    00192 {
    00193     bz_stream *bzstrm = &bz->strm;
    00194     int ret;
    00195
    00196     /* initialize the inflate stream for this block */
    00197     bzstrm->bzfree = NULL;
    00198     bzstrm->bzalloc = NULL;
    00199     bzstrm->opaque = NULL;
    00200     if ((ret = BZ2_bzDecompressInit(bzstrm, bz->V, bz->S)) != BZ_OK)
    00201         bail("not enough memory", "BZ2_bzDecompressInit");
    00202
    00203     bzstrm->next_in = job->in->buf;
    00204     bzstrm->avail_in = job->in->len;
    00205     bzstrm->next_out = job->out->buf;
    00206     bzstrm->avail_out = job->out->len;
    00207
    00208     if ((ret = BZ2_bzDecompress(bzstrm)) != BZ_RUN_OK)
    00209         fprintf(stderr, "*** BZ2_bzDecompress: %d\n", ret);
    00210
    00211     job->out->len -= bzstrm->avail_out;
    00212
    00213     if ((ret = BZ2_bzDecompressEnd(bzstrm)) != BZ_OK)
    00214         fprintf(stderr, "*** BZ2_bzDecompressEnd: %d\n", ret);
    00215
    00216 }
    00217 /*@=mustmod =nullstate@*/
    00218 #endif  /* NOTYET */
    00219
    00220 /*@-mustmod@*/
    00221 static ssize_t rpmbzRead(rpmbz bz, /*@out@*/ char * buf, size_t count,
    00222                 /*@null@*/ const char ** errmsg)
    00223         /*@globals internalState @*/
    00224         /*@modifies bz, *buf, *errmsg, internalState @*/
    00225 {
    00226     ssize_t rc = 0;
    00227
    00228 #ifdef  NOTYET  /* XXX hmmm, read after close needs to return EOF. */
    00229 assert(bz->bzfile != NULL);
    00230 #else
    00231     if (bz->bzfile == NULL) return 0;
    00232 #endif
    00233     rc = BZ2_bzRead(&bz->bzerr, bz->bzfile, buf, (int)count);
    00234     switch (bz->bzerr) {
    00235     case BZ_STREAM_END: {
    00236         void * unused = NULL;
    00237         int nUnused = 0;
    00238
    00239         BZ2_bzReadGetUnused(&bz->bzerr, bz->bzfile, &unused, &nUnused);
    00240         if (unused != NULL && nUnused > 0)
    00241             unused = memcpy(xmalloc(nUnused), unused, nUnused);
    00242         else {
    00243             unused = NULL;
    00244             nUnused = 0;
    00245         }
    00246         rpmbzClose(bz, 0, NULL);
    00247         bz->bzfile = BZ2_bzReadOpen(&bz->bzerr, bz->fp, bz->V, bz->S,
    00248                         unused, nUnused);
    00249         unused = _free(unused);
    00250     }   /*@fallthrough@*/
    00251     case BZ_OK:
    00252 assert(rc >= 0);
    00253         break;
    00254     default:
    00255         rc = -1;
    00256         if (errmsg != NULL)
    00257             *errmsg = rpmbzStrerror(bz);
    00258         rpmbzClose(bz, 1, NULL);
    00259         break;
    00260     }
    00261     return rc;
    00262 }
    00263 /*@=mustmod@*/
    00264
    00265 static ssize_t rpmbzWrite(rpmbz bz, const char * buf, size_t count,
    00266                 /*@null@*/ const char ** errmsg)
    00267         /*@globals internalState @*/
    00268         /*@modifies bz, *errmsg, internalState @*/
    00269 {
    00270     ssize_t rc;
    00271
    00272 assert(bz->bzfile != NULL);     /* XXX TODO: lazy open? */
    00273     BZ2_bzWrite(&bz->bzerr, bz->bzfile, (void *)buf, (int)count);
    00274     switch (bz->bzerr) {
    00275     case BZ_OK:
    00276         rc = count;
    00277         break;
    00278     default:
    00279         if (errmsg != NULL)
    00280             *errmsg = rpmbzStrerror(bz);
    00281         rpmbzClose(bz, 1, NULL);
    00282         rc = -1;
    00283         break;
    00284     }
    00285     return rc;
    00286 }
    00287
    00288 static int rpmbzSeek(/*@unused@*/ void * _bz, /*@unused@*/ _libio_pos_t pos,
    00289                         /*@unused@*/ int whence)
    00290         /*@*/
    00291 {
    00292     return -2;
    00293 }
    00294
    00295 static /*@null@*/ rpmbz rpmbzOpen(const char * path, const char * fmode)
    00296         /*@globals fileSystem, internalState @*/
    00297         /*@modifies fileSystem, internalState @*/
    00298 {
    00299     return  rpmbzNew(path, fmode, -1);
    00300 }
    00301
    00302 static /*@null@*/ rpmbz rpmbzFdopen(void * _fdno, const char * fmode)
    00303         /*@globals fileSystem, internalState @*/
    00304         /*@modifies fileSystem, internalState @*/
    00305 {
    00306     int fdno = (int)_fdno;      /* XXX hack */
    00307     return  rpmbzNew(NULL, fmode, fdno);
    00308 }
    00309
    00310 static int rpmbzFlush(void * _bz)
    00311         /*@*/
    00312 {
    00313     rpmbz bz = _bz;
    00314     return BZ2_bzflush(bz->bzfile);
    00315 }
    00316
    00317 /* =============================================================== */
    00318 static inline /*@dependent@*/ /*@null@*/ void * bzdFileno(FD_t fd)
    00319         /*@*/
    00320 {
    00321     void * rc = NULL;
    00322     int i;
    00323
    00324     FDSANE(fd);
    00325     for (i = fd->nfps; i >= 0; i--) {
    00326         FDSTACK_t * fps = &fd->fps[i];
    00327         if (fps->io != bzdio)
    00328             continue;
    00329         rc = fps->fp;
    00330         break;
    00331     }
    00332
    00333     return rc;
    00334 }
    00335
    00336 /*@-globuse@*/
    00337 static /*@null@*/ FD_t bzdOpen(const char * path, const char * fmode)
    00338         /*@globals fileSystem, internalState @*/
    00339         /*@modifies fileSystem, internalState @*/
    00340 {
    00341     FD_t fd;
    00342     rpmbz bz = rpmbzOpen(path, fmode);
    00343
    00344     if (bz == NULL)
    00345         return NULL;
    00346     fd = fdNew("open (bzdOpen)");
    00347 #ifdef  NOTYET          /* XXX persistent URI cache prevents fileno(bz->fp) */
    00348     fdPop(fd); fdPush(fd, bzdio, bz, fileno(bz->fp));
    00349 #else
    00350     fdPop(fd); fdPush(fd, bzdio, bz, -1);
    00351 #endif
    00352     fdSetOpen(fd, path, -1, bz->omode);
    00353     return fdLink(fd, "bzdOpen");
    00354 }
    00355 /*@=globuse@*/
    00356
    00357 /*@-globuse@*/
    00358 static /*@null@*/ FD_t bzdFdopen(void * cookie, const char * fmode)
    00359         /*@globals fileSystem, internalState @*/
    00360         /*@modifies fileSystem, internalState @*/
    00361 {
    00362     FD_t fd = c2f(cookie);
    00363     int fdno = fdFileno(fd);
    00364     rpmbz bz = rpmbzFdopen((void *)fdno, fmode);
    00365
    00366     if (bz == NULL)
    00367         return NULL;
    00368 #ifdef  NOTYET          /* XXX persistent URI cache prevents pop */
    00369     fdPop(fd); fdPush(fd, bzdio, bz, fileno(bz->fp));
    00370 #else
    00371     fdSetFdno(fd, -1);          /* XXX skip the fdio close */
    00372     fdPush(fd, bzdio, bz, fdno);                /* Push bzdio onto stack */
    00373 #endif
    00374     return fdLink(fd, "bzdFdopen");
    00375 }
    00376 /*@=globuse@*/
    00377
    00378 /*@-globuse@*/
    00379 static int bzdFlush(void * cookie)
    00380         /*@globals fileSystem @*/
    00381         /*@modifies fileSystem @*/
    00382 {
    00383     FD_t fd = c2f(cookie);
    00384     rpmbz bz = bzdFileno(fd);
    00385     return rpmbzFlush(bz);
    00386 }
    00387 /*@=globuse@*/
    00388
    00389 /*@-globuse@*/
    00390 /*@-mustmod@*/          /* LCL: *buf is modified */
    00391 static ssize_t bzdRead(void * cookie, /*@out@*/ char * buf, size_t count)
    00392         /*@globals fileSystem, internalState @*/
    00393         /*@modifies *buf, fileSystem, internalState @*/
    00394 {
    00395     FD_t fd = c2f(cookie);
    00396     rpmbz bz = bzdFileno(fd);
    00397     ssize_t rc = 0;
    00398
    00399 assert(bz != NULL);
    00400     if (fd->bytesRemain == 0) return 0; /* XXX simulate EOF */
    00401     fdstat_enter(fd, FDSTAT_READ);
    00402 /*@-modobserver@*/ /* FIX: is errcookie an observer? */
    00403     rc = rpmbzRead(bz, buf, count, (const char **)&fd->errcookie);
    00404 /*@=modobserver@*/
    00405     if (rc >= 0) {
    00406         fdstat_exit(fd, FDSTAT_READ, rc);
    00407         if (fd->ndigests && rc > 0) fdUpdateDigests(fd, (void *)buf, rc);
    00408     }
    00409     return rc;
    00410 }
    00411 /*@=mustmod@*/
    00412 /*@=globuse@*/
    00413
    00414 /*@-globuse@*/
    00415 static ssize_t bzdWrite(void * cookie, const char * buf, size_t count)
    00416         /*@globals fileSystem, internalState @*/
    00417         /*@modifies fileSystem, internalState @*/
    00418 {
    00419     FD_t fd = c2f(cookie);
    00420     rpmbz bz = bzdFileno(fd);
    00421     ssize_t rc;
    00422
    00423 assert(bz != NULL);
    00424     if (fd->bytesRemain == 0) return 0; /* XXX simulate EOF */
    00425
    00426     if (fd->ndigests && count > 0) fdUpdateDigests(fd, (void *)buf, count);
    00427
    00428     fdstat_enter(fd, FDSTAT_WRITE);
    00429 /*@-modobserver@*/ /* FIX: is errcookie an observer? */
    00430     rc = rpmbzWrite(bz, buf, count, (const char **)&fd->errcookie);
    00431 /*@=modobserver@*/
    00432     if (rc >= 0)
    00433         fdstat_exit(fd, FDSTAT_WRITE, rc);
    00434     return rc;
    00435 }
    00436 /*@=globuse@*/
    00437
    00438 static int bzdSeek(void * cookie, _libio_pos_t pos, int whence)
    00439         /*@*/
    00440 {
    00441     FD_t fd = c2f(cookie);
    00442     rpmbz bz = bzdFileno(fd);
    00443
    00444 assert(bz != NULL);
    00445     BZDONLY(fd);
    00446     return rpmbzSeek(bz, pos, whence);
    00447 }
    00448
    00449 static int bzdClose( /*@only@*/ void * cookie)
    00450         /*@globals fileSystem, internalState @*/
    00451         /*@modifies fileSystem, internalState @*/
    00452 {
    00453     FD_t fd = c2f(cookie);
    00454     rpmbz bz = bzdFileno(fd);
    00455     int rc;
    00456
    00457 assert(bz != NULL);
    00458 #ifdef  DYING
    00459     if (bz->bzfile == NULL)     /* XXX memory leak w errors? */
    00460         return -2;
    00461 #endif
    00462
    00463     fdstat_enter(fd, FDSTAT_CLOSE);
    00464 /*@-modobserver@*/ /* FIX: is errcookie an observer? */
    00465     rpmbzClose(bz, 0, (const char **)&fd->errcookie);
    00466 /*@=modobserver@*/
    00467     rc = 0;     /* XXX FIXME */
    00468
    00469     /* XXX TODO: preserve fd if errors */
    00470
    00471     if (fd)
    00472     if (rc >= 0)
    00473         fdstat_exit(fd, FDSTAT_CLOSE, rc);
    00474
    00475 DBGIO(fd, (stderr, "==>\tbzdClose(%p) rc %lx %s\n", cookie, (unsigned long)rc, fdbg(fd)));
    00476
    00477     if (_rpmio_debug || rpmIsDebug()) fdstat_print(fd, "BZDIO", stderr);
    00478
    00479     if (rc == 0) {
    00480 /*@-dependenttrans@*/
    00481         bz = rpmbzFree(bz, 0);
    00482 /*@=dependenttrans@*/
    00483         fd = fdFree(fd, "open (bzdClose)");
    00484     }
    00485     return rc;
    00486 }
    00487
    00488 /*@-type@*/ /* LCL: function typedefs */
    00489 static struct FDIO_s bzdio_s = {
    00490   bzdRead, bzdWrite, bzdSeek, bzdClose, bzdOpen, bzdFdopen, bzdFlush,
    00491 };
    00492 /*@=type@*/
    00493
    00494 FDIO_t bzdio = /*@-compmempass@*/ &bzdio_s /*@=compmempass@*/ ;
    00495
    00496 #endif
    00497