Main lzma rpmio part based on SuSE patches, thanks for them!

This commit is contained in:
Jindrich Novy 2008-04-22 12:38:51 +02:00
parent 3626f25462
commit 94958a3bfb
1 changed files with 334 additions and 1 deletions

View File

@ -37,6 +37,7 @@ extern int h_errno;
#define FDONLY(fd) assert(fdGetIo(fd) == fdio)
#define GZDONLY(fd) assert(fdGetIo(fd) == gzdio)
#define BZDONLY(fd) assert(fdGetIo(fd) == bzdio)
#define LZDONLY(fd) assert(fdGetIo(fd) == lzdio)
#define UFDONLY(fd) /* assert(fdGetIo(fd) == ufdio) */
@ -91,6 +92,7 @@ static const FDIO_t fpio;
static const FDIO_t ufdio;
static const FDIO_t gzdio;
static const FDIO_t bzdio;
static const FDIO_t lzdio;
/**
*/
@ -141,6 +143,10 @@ static const char * fdbg(FD_t fd)
#if HAVE_BZLIB_H
} else if (fps->io == bzdio) {
sprintf(be, "BZD %p fdno %d", fps->fp, fps->fdno);
#endif
#if HAVE_LZMA_H
} else if (fps->io == lzdio) {
sprintf(be, "LZD %p fdno %d", fps->fp, fps->fdno);
#endif
} else if (fps->io == fpio) {
sprintf(be, "%s %p(%d) fdno %d",
@ -1233,7 +1239,11 @@ static const char * getFdErrstr (FD_t fd)
errstr = fd->errcookie;
} else
#endif /* HAVE_BZLIB_H */
#ifdef HAVE_LZMA_H
if (fdGetIo(fd) == lzdio) {
errstr = fd->errcookie;
} else
#endif /* HAVE_LZMA_H */
{
errstr = (fd->syserrno ? strerror(fd->syserrno) : "");
}
@ -1241,6 +1251,318 @@ static const char * getFdErrstr (FD_t fd)
return errstr;
}
/* =============================================================== */
/* Support for LZMA library.
*/
#ifdef HAVE_LZMA_H
#include <sys/types.h>
#include <inttypes.h>
#include <lzma.h>
#define kBufferSize (1 << 15)
typedef struct lzfile {
/* IO buffer */
uint8_t buf[kBufferSize];
lzma_stream strm;
FILE *file;
int encoding;
int eof;
} LZFILE;
static LZFILE *lzopen_internal(const char *path, const char *mode, int fd)
{
int level = 5;
int encoding = 0;
FILE *fp;
LZFILE *lzfile;
lzma_ret ret;
for (; *mode; mode++) {
if (*mode == 'w')
encoding = 1;
else if (*mode == 'r')
encoding = 0;
else if (*mode >= '1' && *mode <= '9')
level = *mode - '0';
}
if (fd != -1)
fp = fdopen(fd, encoding ? "w" : "r");
else
fp = fopen(path, encoding ? "w" : "r");
if (!fp)
return 0;
lzfile = calloc(1, sizeof(*lzfile));
if (!lzfile) {
fclose(fp);
return 0;
}
lzfile->file = fp;
lzfile->encoding = encoding;
lzfile->eof = 0;
lzfile->strm = LZMA_STREAM_INIT_VAR;
if (encoding) {
lzma_options_alone alone;
alone.uncompressed_size = LZMA_VLI_VALUE_UNKNOWN;
memcpy(&alone.lzma, &lzma_preset_lzma[level - 1], sizeof(alone.lzma));
ret = lzma_alone_encoder(&lzfile->strm, &alone);
} else {
ret = lzma_auto_decoder(&lzfile->strm, 0, 0);
}
if (ret != LZMA_OK) {
fclose(fp);
free(lzfile);
return 0;
}
return lzfile;
}
static LZFILE *lzopen(const char *path, const char *mode)
{
return lzopen_internal(path, mode, -1);
}
static LZFILE *lzdopen(int fd, const char *mode)
{
if (fd < 0)
return 0;
return lzopen_internal(0, mode, fd);
}
static int lzflush(LZFILE *lzfile)
{
return fflush(lzfile->file);
}
static int lzclose(LZFILE *lzfile)
{
lzma_ret ret;
int n;
if (!lzfile)
return -1;
if (lzfile->encoding) {
for (;;) {
lzfile->strm.avail_out = kBufferSize;
lzfile->strm.next_out = lzfile->buf;
ret = lzma_code(&lzfile->strm, LZMA_FINISH);
if (ret != LZMA_OK && ret != LZMA_STREAM_END)
return -1;
n = kBufferSize - lzfile->strm.avail_out;
if (n && fwrite(lzfile->buf, 1, n, lzfile->file) != n)
return -1;
if (ret == LZMA_STREAM_END)
break;
}
}
lzma_end(&lzfile->strm);
return fclose(lzfile->file);
free(lzfile);
}
static ssize_t lzread(LZFILE *lzfile, void *buf, size_t len)
{
lzma_ret ret;
int eof = 0;
if (!lzfile || lzfile->encoding)
return -1;
if (lzfile->eof)
return 0;
lzfile->strm.next_out = buf;
lzfile->strm.avail_out = len;
for (;;) {
if (!lzfile->strm.avail_in) {
lzfile->strm.next_in = lzfile->buf;
lzfile->strm.avail_in = fread(lzfile->buf, 1, kBufferSize, lzfile->file);
if (!lzfile->strm.avail_in)
eof = 1;
}
ret = lzma_code(&lzfile->strm, LZMA_RUN);
if (ret == LZMA_STREAM_END) {
lzfile->eof = 1;
return len - lzfile->strm.avail_out;
}
if (ret != LZMA_OK)
return -1;
if (!lzfile->strm.avail_out)
return len;
if (eof)
return -1;
}
}
static ssize_t lzwrite(LZFILE *lzfile, void *buf, size_t len)
{
lzma_ret ret;
int n;
if (!lzfile || !lzfile->encoding)
return -1;
if (!len)
return 0;
lzfile->strm.next_in = buf;
lzfile->strm.avail_in = len;
for (;;) {
lzfile->strm.next_out = lzfile->buf;
lzfile->strm.avail_out = kBufferSize;
ret = lzma_code(&lzfile->strm, LZMA_RUN);
if (ret != LZMA_OK)
return -1;
n = kBufferSize - lzfile->strm.avail_out;
if (n && fwrite(lzfile->buf, 1, n, lzfile->file) != n)
return -1;
if (!lzfile->strm.avail_in)
return len;
}
}
/* =============================================================== */
static inline void * lzdFileno(FD_t fd)
{
void * rc = NULL;
int i;
FDSANE(fd);
for (i = fd->nfps; i >= 0; i--) {
FDSTACK_t * fps = &fd->fps[i];
if (fps->io != lzdio)
continue;
rc = fps->fp;
break;
}
return rc;
}
static FD_t lzdOpen(const char * path, const char * mode)
{
FD_t fd;
LZFILE *lzfile;
if ((lzfile = lzopen(path, mode)) == NULL)
return NULL;
fd = fdNew("open (lzdOpen)");
fdPop(fd); fdPush(fd, lzdio, lzfile, -1);
return fdLink(fd, "lzdOpen");
}
static FD_t lzdFdopen(void * cookie, const char * fmode)
{
FD_t fd = c2f(cookie);
int fdno;
LZFILE *lzfile;
if (fmode == NULL) return NULL;
fdno = fdFileno(fd);
fdSetFdno(fd, -1); /* XXX skip the fdio close */
if (fdno < 0) return NULL;
lzfile = lzdopen(fdno, fmode);
if (lzfile == NULL) return NULL;
fdPush(fd, lzdio, lzfile, fdno);
return fdLink(fd, "lzdFdopen");
}
static int lzdFlush(FD_t fd)
{
return lzflush(lzdFileno(fd));
}
/* =============================================================== */
static ssize_t lzdRead(void * cookie, char * buf, size_t count)
{
FD_t fd = c2f(cookie);
LZFILE *lzfile;
ssize_t rc = 0;
if (fd->bytesRemain == 0) return 0; /* XXX simulate EOF */
lzfile = lzdFileno(fd);
fdstat_enter(fd, FDSTAT_READ);
if (lzfile)
rc = lzread(lzfile, buf, count);
if (rc == -1) {
fd->errcookie = "Lzma: decoding error";
} else if (rc >= 0) {
fdstat_exit(fd, FDSTAT_READ, rc);
if (fd->ndigests && rc > 0) fdUpdateDigests(fd, (void *)buf, rc);
}
return rc;
}
static ssize_t lzdWrite(void * cookie, const char * buf, size_t count)
{
FD_t fd = c2f(cookie);
LZFILE *lzfile;
ssize_t rc = 0;
if (fd == NULL || fd->bytesRemain == 0) return 0; /* XXX simulate EOF */
if (fd->ndigests && count > 0) fdUpdateDigests(fd, (void *)buf, count);
lzfile = lzdFileno(fd);
fdstat_enter(fd, FDSTAT_WRITE);
rc = lzwrite(lzfile, (void *)buf, count);
if (rc < 0) {
fd->errcookie = "Lzma: encoding error";
} else if (rc > 0) {
fdstat_exit(fd, FDSTAT_WRITE, rc);
}
return rc;
}
static inline int lzdSeek(void * cookie, _libio_pos_t pos, int whence)
{
FD_t fd = c2f(cookie);
LZDONLY(fd);
return -2;
}
static int lzdClose(void * cookie)
{
FD_t fd = c2f(cookie);
LZFILE *lzfile;
int rc;
lzfile = lzdFileno(fd);
if (lzfile == NULL) return -2;
fdstat_enter(fd, FDSTAT_CLOSE);
rc = lzclose(lzfile);
/* XXX TODO: preserve fd if errors */
if (fd) {
if (rc == -1) {
fd->errcookie = strerror(ferror(lzfile->file));
} else if (rc >= 0) {
fdstat_exit(fd, FDSTAT_CLOSE, rc);
}
}
DBGIO(fd, (stderr, "==>\tlzdClose(%p) rc %lx %s\n", cookie, (unsigned long)rc, fdbg(fd)));
if (_rpmio_debug || rpmIsDebug()) fdstat_print(fd, "LZDIO", stderr);
if (rc == 0)
fd = fdFree(fd, "open (lzdClose)");
return rc;
}
static struct FDIO_s lzdio_s = {
lzdRead, lzdWrite, lzdSeek, lzdClose, NULL, NULL, NULL, fdFileno,
NULL, lzdOpen, lzdFileno, lzdFlush
};
static const FDIO_t lzdio = &lzdio_s;
#endif /* HAVE_LZMA_H */
/* =============================================================== */
const char *Fstrerror(FD_t fd)
@ -1472,6 +1794,11 @@ fprintf(stderr, "*** Fdopen(%p,%s) %s\n", fd, fmode, fdbg(fd));
} else if (!strcmp(end, "bzdio")) {
iof = bzdio;
fd = bzdFdopen(fd, zstdio);
#endif
#if HAVE_LZMA_H
} else if (!strcmp(end, "lzdio")) {
iof = lzdio;
fd = lzdFdopen(fd, zstdio);
#endif
} else if (!strcmp(end, "ufdio")) {
iof = ufdio;
@ -1623,6 +1950,11 @@ int Ferror(FD_t fd)
} else if (fps->io == bzdio) {
ec = (fd->syserrno || fd->errcookie != NULL) ? -1 : 0;
i--; /* XXX fdio under bzdio always has fdno == -1 */
#endif
#if HAVE_LZMA_H
} else if (fps->io == lzdio) {
ec = (fd->syserrno || fd->errcookie != NULL) ? -1 : 0;
i--; /* XXX fdio under lzdio always has fdno == -1 */
#endif
} else {
/* XXX need to check ufdio/gzdio/bzdio/fdio errors correctly. */
@ -1719,3 +2051,4 @@ static const struct FDIO_s fpio_s = {
ufdOpen, NULL, fdGetFp, NULL
};
static const FDIO_t fpio = &fpio_s ;