• 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 

Generated on Fri Dec 3 2010 20:54:16 for rpm by  doxygen 1.7.2