rpm
5.2.1
|
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