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
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
00029 static void rpmbzClose(rpmbz bz, int abort, const char ** errmsg)
00030
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
00039 if (bz->bzerr != BZ_OK && errmsg)
00040 *errmsg = rpmbzStrerror(bz);
00041
00042 }
00043 bz->bzfile = NULL;
00044 }
00045
00046
00047
00048 static rpmbz rpmbzFree( rpmbz bz, int abort)
00049
00050
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
00061
00062 static rpmbz rpmbzNew(const char * path, const char * fmode, int fdno)
00063
00064
00065 {
00066 rpmbz bz;
00067 int level = -1;
00068 mode_t omode = O_RDONLY;
00069 int small = -1;
00070 int verbosity = -1;
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);
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 break;
00095 case '+':
00096 case 'x':
00097 case 'm':
00098 case 'c':
00099 case 'b':
00100 if (t < te) *t++ = c;
00101 break;
00102 case 's':
00103 if (small < 0) small = 0;
00104 small++;
00105 break;
00106 case 'q':
00107 verbosity = 0;
00108 break;
00109 case 'v':
00110 if (verbosity < 0) verbosity = 0;
00111 if (verbosity < 4) verbosity++;
00112 break;
00113 default:
00114 if (c >= (int)'0' && c <= (int)'9')
00115 level = c - (int)'0';
00116 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
00135 return (bz->bzfile != NULL ? bz : rpmbzFree(bz, 0));
00136
00137 }
00138
00139
00140 #ifdef NOTYET
00141
00142 static void rpmbzCompress(rpmbz bz, rpmzJob job)
00143
00144
00145 {
00146 bz_stream *bzstrm = &bz->strm;
00147 size_t len;
00148 int ret;
00149
00150
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
00162
00163
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
00174
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
00187
00188
00189 static void rpmbzDecompress(rpmbz bz, rpmzJob job)
00190
00191
00192 {
00193 bz_stream *bzstrm = &bz->strm;
00194 int ret;
00195
00196
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
00218 #endif
00219
00220
00221 static ssize_t rpmbzRead(rpmbz bz, char * buf, size_t count,
00222 const char ** errmsg)
00223
00224
00225 {
00226 ssize_t rc = 0;
00227
00228 #ifdef NOTYET
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 }
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
00264
00265 static ssize_t rpmbzWrite(rpmbz bz, const char * buf, size_t count,
00266 const char ** errmsg)
00267
00268
00269 {
00270 ssize_t rc;
00271
00272 assert(bz->bzfile != NULL);
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( void * _bz, _libio_pos_t pos,
00289 int whence)
00290
00291 {
00292 return -2;
00293 }
00294
00295 static rpmbz rpmbzOpen(const char * path, const char * fmode)
00296
00297
00298 {
00299 return rpmbzNew(path, fmode, -1);
00300 }
00301
00302 static rpmbz rpmbzFdopen(void * _fdno, const char * fmode)
00303
00304
00305 {
00306 int fdno = (int)_fdno;
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 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
00337 static FD_t bzdOpen(const char * path, const char * fmode)
00338
00339
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
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
00356
00357
00358 static FD_t bzdFdopen(void * cookie, const char * fmode)
00359
00360
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
00369 fdPop(fd); fdPush(fd, bzdio, bz, fileno(bz->fp));
00370 #else
00371 fdSetFdno(fd, -1);
00372 fdPush(fd, bzdio, bz, fdno);
00373 #endif
00374 return fdLink(fd, "bzdFdopen");
00375 }
00376
00377
00378
00379 static int bzdFlush(void * cookie)
00380
00381
00382 {
00383 FD_t fd = c2f(cookie);
00384 rpmbz bz = bzdFileno(fd);
00385 return rpmbzFlush(bz);
00386 }
00387
00388
00389
00390
00391 static ssize_t bzdRead(void * cookie, char * buf, size_t count)
00392
00393
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;
00401 fdstat_enter(fd, FDSTAT_READ);
00402
00403 rc = rpmbzRead(bz, buf, count, (const char **)&fd->errcookie);
00404
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
00412
00413
00414
00415 static ssize_t bzdWrite(void * cookie, const char * buf, size_t count)
00416
00417
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;
00425
00426 if (fd->ndigests && count > 0) fdUpdateDigests(fd, (void *)buf, count);
00427
00428 fdstat_enter(fd, FDSTAT_WRITE);
00429
00430 rc = rpmbzWrite(bz, buf, count, (const char **)&fd->errcookie);
00431
00432 if (rc >= 0)
00433 fdstat_exit(fd, FDSTAT_WRITE, rc);
00434 return rc;
00435 }
00436
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( void * cookie)
00450
00451
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)
00460 return -2;
00461 #endif
00462
00463 fdstat_enter(fd, FDSTAT_CLOSE);
00464
00465 rpmbzClose(bz, 0, (const char **)&fd->errcookie);
00466
00467 rc = 0;
00468
00469
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
00481 bz = rpmbzFree(bz, 0);
00482
00483 fd = fdFree(fd, "open (bzdClose)");
00484 }
00485 return rc;
00486 }
00487
00488
00489 static struct FDIO_s bzdio_s = {
00490 bzdRead, bzdWrite, bzdSeek, bzdClose, bzdOpen, bzdFdopen, bzdFlush,
00491 };
00492
00493
00494 FDIO_t bzdio = &bzdio_s ;
00495
00496 #endif
00497