[4.0] Use strip (instead of eu-strip) to support --strip-debug of *.so at build time
[platform/upstream/rpm.git] / rpmio / rpmio.c
index 7ce6a05..cd223e8 100644 (file)
@@ -36,15 +36,12 @@ struct _FD_s {
     int                nrefs;
     int                flags;
 #define        RPMIO_DEBUG_IO          0x40000000
-#define        RPMIO_DEBUG_REFS        0x20000000
     int                magic;
 #define        FDMAGIC                 0x04463138
     int                nfps;
     FDSTACK_t  fps[8];
     int                urlType;        /* ufdio: */
 
-    ssize_t    bytesRemain;    /* ufdio: */
-
     int                syserrno;       /* last system errno encountered */
     const char *errcookie;     /* gzdio/bzdio/ufdio/xzdio: */
 
@@ -107,12 +104,6 @@ static void fdPop(FD_t fd)
     fd->nfps--;
 }
 
-static FD_t c2f(void * cookie)
-{
-    FD_t fd = (FD_t) cookie;
-    return (fd && fd->magic == FDMAGIC) ? fd : NULL;
-}
-
 void fdSetBundle(FD_t fd, rpmDigestBundle bundle)
 {
     if (fd)
@@ -142,33 +133,23 @@ static void * iotFileno(FD_t fd, FDIO_t iot)
     return rc;
 }
 
-#define FDNREFS(fd)    (fd ? ((FD_t)fd)->nrefs : -9)
-
-#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) == xzdio || fdGetIo(fd) == lzdio)
-
-#define        UFDONLY(fd)     /* assert(fdGetIo(fd) == ufdio) */
-
 /** \ingroup rpmio
  * \name RPMIO Vectors.
  */
-typedef ssize_t (*fdio_read_function_t) (void *cookie, void *buf, size_t nbytes);
-typedef ssize_t (*fdio_write_function_t) (void *cookie, const void *buf, size_t nbytes);
-typedef int (*fdio_seek_function_t) (void *cookie, off_t pos, int whence);
-typedef int (*fdio_close_function_t) (void *cookie);
-typedef FD_t (*fdio_ref_function_t) ( void * cookie);
+typedef ssize_t (*fdio_read_function_t) (FD_t fd, void *buf, size_t nbytes);
+typedef ssize_t (*fdio_write_function_t) (FD_t fd, const void *buf, size_t nbytes);
+typedef int (*fdio_seek_function_t) (FD_t fd, off_t pos, int whence);
+typedef int (*fdio_close_function_t) (FD_t fd);
+typedef FD_t (*fdio_ref_function_t) (FD_t fd);
 typedef FD_t (*fdio_deref_function_t) (FD_t fd);
 typedef FD_t (*fdio_new_function_t) (const char *descr);
-typedef int (*fdio_fileno_function_t) (void * cookie);
+typedef int (*fdio_fileno_function_t) (FD_t fd);
 typedef FD_t (*fdio_open_function_t) (const char * path, int flags, mode_t mode);
 typedef FD_t (*fdio_fopen_function_t) (const char * path, const char * fmode);
 typedef void * (*fdio_ffileno_function_t) (FD_t fd);
 typedef int (*fdio_fflush_function_t) (FD_t fd);
+typedef long (*fdio_ftell_function_t) (FD_t);
 
-/** \ingroup rpmio
- */
 struct FDIO_s {
   fdio_read_function_t         read;
   fdio_write_function_t                write;
@@ -184,6 +165,7 @@ struct FDIO_s {
   fdio_fopen_function_t                _fopen;
   fdio_ffileno_function_t      _ffileno;
   fdio_fflush_function_t       _fflush;
+  fdio_ftell_function_t                _ftell;
 };
 
 /* forward refs */
@@ -215,10 +197,6 @@ static const char * fdbg(FD_t fd)
     if (fd == NULL)
        return buf;
 
-    if (fd->bytesRemain != -1) {
-       sprintf(be, " clen %d", (int)fd->bytesRemain);
-       be += strlen(be);
-     }
     *be++ = '\t';
     for (i = fd->nfps; i >= 0; i--) {
        FDSTACK_t * fps = &fd->fps[i];
@@ -254,25 +232,14 @@ static const char * fdbg(FD_t fd)
 
 static void fdstat_enter(FD_t fd, fdOpX opx)
 {
-    if (fd == NULL) return;
     if (fd->stats != NULL)
        (void) rpmswEnter(fdOp(fd, opx), (ssize_t) 0);
 }
 
 static void fdstat_exit(FD_t fd, fdOpX opx, ssize_t rc)
 {
-    if (fd == NULL) return;
     if (rc == -1)
        fd->syserrno = errno;
-    else if (rc > 0 && fd->bytesRemain > 0)
-       switch (opx) {
-       case FDSTAT_READ:
-       case FDSTAT_WRITE:
-       fd->bytesRemain -= rc;
-           break;
-       default:
-           break;
-       }
     if (fd->stats != NULL)
        (void) rpmswExit(fdOp(fd, opx), rc);
 }
@@ -307,7 +274,6 @@ static void fdstat_print(FD_t fd, const char * msg, FILE * fp)
     }
 }
 
-/* =============================================================== */
 off_t fdSize(FD_t fd)
 {
     struct stat sb;
@@ -331,16 +297,14 @@ DBGIO(fd, (stderr, "==> fdDup(%d) fd %p %s\n", fdno, (fd ? fd : NULL), fdbg(fd))
     return fd;
 }
 
-static int fdSeekNot(void * cookie, off_t pos,  int whence)
+/* Regular fd doesn't have fflush() equivalent but its not an error either */
+static int fdFlush(FD_t fd)
 {
-    return -2;
+    return 0;
 }
 
-/** \ingroup rpmio
- */
-static int fdFileno(void * cookie)
+static int fdFileno(FD_t fd)
 {
-    FD_t fd = c2f(cookie);
     return (fd != NULL) ? fd->fps[0].fdno : -2;
 }
 
@@ -378,18 +342,13 @@ const char * Fdescr(FD_t fd)
     return fd->descr;
 }
 
-/* =============================================================== */
-
-FD_t fdLink(void * cookie)
+FD_t fdLink(FD_t fd)
 {
-    FD_t fd = c2f(cookie);
     if (fd)
        fd->nrefs++;
     return fd;
 }
 
-/**
- */
 FD_t fdFree( FD_t fd)
 {
     if (fd) {
@@ -405,8 +364,6 @@ FD_t fdFree( FD_t fd)
     return NULL;
 }
 
-/**
- */
 FD_t fdNew(const char *descr)
 {
     FD_t fd = xcalloc(1, sizeof(*fd));
@@ -424,7 +381,6 @@ FD_t fdNew(const char *descr)
     fd->fps[0].fp = NULL;
     fd->fps[0].fdno = -1;
 
-    fd->bytesRemain = -1;
     fd->syserrno = 0;
     fd->errcookie = NULL;
     fd->stats = xcalloc(1, sizeof(*fd->stats));
@@ -434,73 +390,26 @@ FD_t fdNew(const char *descr)
     return fdLink(fd);
 }
 
-/**
- */
-static ssize_t fdRead(void * cookie, void * buf, size_t count)
+static ssize_t fdRead(FD_t fd, void * buf, size_t count)
 {
-    FD_t fd = c2f(cookie);
-    ssize_t rc;
-
-    if (fd == NULL || fd->bytesRemain == 0) return 0;  /* XXX simulate EOF */
-
-    fdstat_enter(fd, FDSTAT_READ);
-    rc = read(fdFileno(fd), buf, (count > fd->bytesRemain ? fd->bytesRemain : count));
-    fdstat_exit(fd, FDSTAT_READ, rc);
-
-    if (fd->digests && rc > 0) fdUpdateDigests(fd, buf, rc);
-
-DBGIO(fd, (stderr, "==>\tfdRead(%p,%p,%ld) rc %ld %s\n", cookie, buf, (long)count, (long)rc, fdbg(fd)));
-
-    return rc;
+    return read(fdFileno(fd), buf, count);
 }
 
-/**
- */
-static ssize_t fdWrite(void * cookie, const void * buf, size_t count)
+static ssize_t fdWrite(FD_t fd, const void * buf, size_t count)
 {
-    FD_t fd = c2f(cookie);
-    int fdno = fdFileno(fd);
-    ssize_t rc;
-
-    if (fd == NULL || fd->bytesRemain == 0) return 0;  /* XXX simulate EOF */
-
-    if (fd->digests && count > 0) fdUpdateDigests(fd, buf, count);
-
-    if (count == 0) return 0;
-
-    fdstat_enter(fd, FDSTAT_WRITE);
-    rc = write(fdno, buf, (count > fd->bytesRemain ? fd->bytesRemain : count));
-    fdstat_exit(fd, FDSTAT_WRITE, rc);
-
-DBGIO(fd, (stderr, "==>\tfdWrite(%p,%p,%ld) rc %ld %s\n", cookie, buf, (long)count, (long)rc, fdbg(fd)));
+    if (count == 0)
+       return 0;
 
-    return rc;
+    return write(fdFileno(fd), buf, count);
 }
 
-static int fdSeek(void * cookie, off_t pos, int whence)
+static int fdSeek(FD_t fd, off_t pos, int whence)
 {
-    off_t p = pos;
-    FD_t fd = c2f(cookie);
-    off_t rc;
-
-    if (fd == NULL)
-       return -2;
-
-    assert(fd->bytesRemain == -1);     /* XXX FIXME fadio only for now */
-    fdstat_enter(fd, FDSTAT_SEEK);
-    rc = lseek(fdFileno(fd), p, whence);
-    fdstat_exit(fd, FDSTAT_SEEK, rc);
-
-DBGIO(fd, (stderr, "==>\tfdSeek(%p,%ld,%d) rc %lx %s\n", cookie, (long)p, whence, (unsigned long)rc, fdbg(fd)));
-
-    return rc;
+    return lseek(fdFileno(fd), pos, whence);
 }
 
-/**
- */
-static int fdClose( void * cookie)
+static int fdClose(FD_t fd)
 {
-    FD_t fd = c2f(cookie);
     int fdno;
     int rc;
 
@@ -509,18 +418,12 @@ static int fdClose( void * cookie)
 
     fdSetFdno(fd, -1);
 
-    fdstat_enter(fd, FDSTAT_CLOSE);
     rc = ((fdno >= 0) ? close(fdno) : -2);
-    fdstat_exit(fd, FDSTAT_CLOSE, rc);
-
-DBGIO(fd, (stderr, "==>\tfdClose(%p) rc %lx %s\n", (fd ? fd : NULL), (unsigned long)rc, fdbg(fd)));
 
     fdFree(fd);
     return rc;
 }
 
-/**
- */
 static FD_t fdOpen(const char *path, int flags, mode_t mode)
 {
     FD_t fd;
@@ -535,46 +438,44 @@ static FD_t fdOpen(const char *path, int flags, mode_t mode)
     fd = fdNew(path);
     fdSetFdno(fd, fdno);
     fd->flags = flags;
-DBGIO(fd, (stderr, "==>\tfdOpen(\"%s\",%x,0%o) %s\n", path, (unsigned)flags, (unsigned)mode, fdbg(fd)));
     return fd;
 }
 
+static long fdTell(FD_t fd)
+{
+    return lseek(Fileno(fd), 0, SEEK_CUR);
+}
+
 static const struct FDIO_s fdio_s = {
   fdRead, fdWrite, fdSeek, fdClose, fdLink, fdFree, fdNew, fdFileno,
-  fdOpen, NULL, fdGetFp, NULL
+  fdOpen, NULL, fdGetFp, fdFlush, fdTell
 };
 static const FDIO_t fdio = &fdio_s ;
 
-int ufdCopy(FD_t sfd, FD_t tfd)
+off_t ufdCopy(FD_t sfd, FD_t tfd)
 {
     char buf[BUFSIZ];
-    int itemsRead;
-    int itemsCopied = 0;
-    int rc = 0;
+    ssize_t rdbytes, wrbytes;
+    off_t total = 0;
 
     while (1) {
-       rc = Fread(buf, sizeof(buf[0]), sizeof(buf), sfd);
-       if (rc < 0)
-           break;
-       else if (rc == 0) {
-           rc = itemsCopied;
-           break;
-       }
-       itemsRead = rc;
-       rc = Fwrite(buf, sizeof(buf[0]), itemsRead, tfd);
-       if (rc < 0)
-           break;
-       if (rc != itemsRead) {
-           rc = -1;
+       rdbytes = Fread(buf, sizeof(buf[0]), sizeof(buf), sfd);
+
+       if (rdbytes > 0) {
+           wrbytes = Fwrite(buf, sizeof(buf[0]), rdbytes, tfd);
+           if (wrbytes != rdbytes) {
+               total = -1;
+               break;
+           }
+           total += wrbytes;
+       } else {
+           if (rdbytes < 0)
+               total = -1;
            break;
        }
-
-       itemsCopied += itemsRead;
     }
 
-    DBGIO(sfd, (stderr, "++ copied %d bytes\n", itemsCopied));
-
-    return rc;
+    return total;
 }
 
 /*
@@ -645,26 +546,23 @@ fprintf(stderr, "*** ufdOpen(%s,0x%x,0%o)\n", url, (unsigned)flags, (unsigned)mo
     if (fd == NULL) return NULL;
 
     fdSetIo(fd, ufdio);
-    fd->bytesRemain = -1;
     fd->urlType = urlType;
 
     if (Fileno(fd) < 0) {
        (void) fdClose(fd);
        return NULL;
     }
-DBGIO(fd, (stderr, "==>\tufdOpen(\"%s\",%x,0%o) %s\n", url, (unsigned)flags, (unsigned)mode, fdbg(fd)));
     return fd;
 }
 
 static const struct FDIO_s ufdio_s = {
   fdRead, fdWrite, fdSeek, fdClose, fdLink, fdFree, fdNew, fdFileno,
-  ufdOpen, NULL, fdGetFp, NULL
+  ufdOpen, NULL, fdGetFp, fdFlush, fdTell
 };
 static const FDIO_t ufdio = &ufdio_s ;
 
 /* =============================================================== */
-/* Support for GZIP library.
- */
+/* Support for GZIP library.  */
 #include <zlib.h>
 
 static void * gzdFileno(FD_t fd)
@@ -682,13 +580,11 @@ FD_t gzdOpen(const char * path, const char * fmode)
     fd = fdNew(path);
     fdPop(fd); fdPush(fd, gzdio, gzfile, -1);
     
-DBGIO(fd, (stderr, "==>\tgzdOpen(\"%s\", \"%s\") fd %p %s\n", path, fmode, (fd ? fd : NULL), fdbg(fd)));
     return fdLink(fd);
 }
 
-static FD_t gzdFdopen(void * cookie, const char *fmode)
+static FD_t gzdFdopen(FD_t fd, const char *fmode)
 {
-    FD_t fd = c2f(cookie);
     int fdno;
     gzFile gzfile;
 
@@ -712,21 +608,15 @@ static int gzdFlush(FD_t fd)
     return gzflush(gzfile, Z_SYNC_FLUSH);      /* XXX W2DO? */
 }
 
-/* =============================================================== */
-static ssize_t gzdRead(void * cookie, void * buf, size_t count)
+static ssize_t gzdRead(FD_t fd, void * buf, size_t count)
 {
-    FD_t fd = c2f(cookie);
     gzFile gzfile;
     ssize_t rc;
 
-    if (fd == NULL || fd->bytesRemain == 0) return 0;  /* XXX simulate EOF */
-
     gzfile = gzdFileno(fd);
     if (gzfile == NULL) return -2;     /* XXX can't happen */
 
-    fdstat_enter(fd, FDSTAT_READ);
     rc = gzread(gzfile, buf, count);
-DBGIO(fd, (stderr, "==>\tgzdRead(%p,%p,%u) rc %lx %s\n", cookie, buf, (unsigned)count, (unsigned long)rc, fdbg(fd)));
     if (rc < 0) {
        int zerror = 0;
        fd->errcookie = gzerror(gzfile, &zerror);
@@ -734,29 +624,19 @@ DBGIO(fd, (stderr, "==>\tgzdRead(%p,%p,%u) rc %lx %s\n", cookie, buf, (unsigned)
            fd->syserrno = errno;
            fd->errcookie = strerror(fd->syserrno);
        }
-    } else if (rc >= 0) {
-       fdstat_exit(fd, FDSTAT_READ, rc);
-       if (fd->digests && rc > 0) fdUpdateDigests(fd, buf, rc);
     }
     return rc;
 }
 
-static ssize_t gzdWrite(void * cookie, const void * buf, size_t count)
+static ssize_t gzdWrite(FD_t fd, const void * buf, size_t count)
 {
-    FD_t fd = c2f(cookie);
     gzFile gzfile;
     ssize_t rc;
 
-    if (fd == NULL || fd->bytesRemain == 0) return 0;  /* XXX simulate EOF */
-
-    if (fd->digests && count > 0) fdUpdateDigests(fd, buf, count);
-
     gzfile = gzdFileno(fd);
     if (gzfile == NULL) return -2;     /* XXX can't happen */
 
-    fdstat_enter(fd, FDSTAT_WRITE);
     rc = gzwrite(gzfile, (void *)buf, count);
-DBGIO(fd, (stderr, "==>\tgzdWrite(%p,%p,%u) rc %lx %s\n", cookie, buf, (unsigned)count, (unsigned long)rc, fdbg(fd)));
     if (rc < 0) {
        int zerror = 0;
        fd->errcookie = gzerror(gzfile, &zerror);
@@ -764,30 +644,24 @@ DBGIO(fd, (stderr, "==>\tgzdWrite(%p,%p,%u) rc %lx %s\n", cookie, buf, (unsigned
            fd->syserrno = errno;
            fd->errcookie = strerror(fd->syserrno);
        }
-    } else if (rc > 0) {
-       fdstat_exit(fd, FDSTAT_WRITE, rc);
     }
     return rc;
 }
 
 /* XXX zlib-1.0.4 has not */
-static int gzdSeek(void * cookie, off_t pos, int whence)
+static int gzdSeek(FD_t fd, off_t pos, int whence)
 {
     off_t p = pos;
     int rc;
 #if HAVE_GZSEEK
-    FD_t fd = c2f(cookie);
     gzFile gzfile;
 
     if (fd == NULL) return -2;
-    assert(fd->bytesRemain == -1);     /* XXX FIXME */
 
     gzfile = gzdFileno(fd);
     if (gzfile == NULL) return -2;     /* XXX can't happen */
 
-    fdstat_enter(fd, FDSTAT_SEEK);
     rc = gzseek(gzfile, p, whence);
-DBGIO(fd, (stderr, "==>\tgzdSeek(%p,%ld,%d) rc %lx %s\n", cookie, (long)p, whence, (unsigned long)rc, fdbg(fd)));
     if (rc < 0) {
        int zerror = 0;
        fd->errcookie = gzerror(gzfile, &zerror);
@@ -795,8 +669,6 @@ DBGIO(fd, (stderr, "==>\tgzdSeek(%p,%ld,%d) rc %lx %s\n", cookie, (long)p, whenc
            fd->syserrno = errno;
            fd->errcookie = strerror(fd->syserrno);
        }
-    } else if (rc >= 0) {
-       fdstat_exit(fd, FDSTAT_SEEK, rc);
     }
 #else
     rc = -2;
@@ -804,64 +676,68 @@ DBGIO(fd, (stderr, "==>\tgzdSeek(%p,%ld,%d) rc %lx %s\n", cookie, (long)p, whenc
     return rc;
 }
 
-static int gzdClose( void * cookie)
+static int gzdClose(FD_t fd)
 {
-    FD_t fd = c2f(cookie);
     gzFile gzfile;
     int rc;
 
     gzfile = gzdFileno(fd);
     if (gzfile == NULL) return -2;     /* XXX can't happen */
 
-    fdstat_enter(fd, FDSTAT_CLOSE);
     rc = gzclose(gzfile);
 
     /* XXX TODO: preserve fd if errors */
 
     if (fd) {
-DBGIO(fd, (stderr, "==>\tgzdClose(%p) zerror %d %s\n", cookie, rc, fdbg(fd)));
        if (rc < 0) {
            fd->errcookie = "gzclose error";
            if (rc == Z_ERRNO) {
                fd->syserrno = errno;
                fd->errcookie = strerror(fd->syserrno);
            }
-       } else if (rc >= 0) {
-           fdstat_exit(fd, FDSTAT_CLOSE, rc);
        }
     }
 
-DBGIO(fd, (stderr, "==>\tgzdClose(%p) rc %lx %s\n", cookie, (unsigned long)rc, fdbg(fd)));
-
     if (_rpmio_debug || rpmIsDebug()) fdstat_print(fd, "GZDIO", stderr);
     if (rc == 0)
        fdFree(fd);
     return rc;
 }
 
+static long gzdTell(FD_t fd)
+{
+    off_t pos = -1;
+    gzFile gzfile = gzdFileno(fd);
+
+    if (gzfile != NULL) {
+#if HAVE_GZSEEK
+       pos = gztell(gzfile);
+       if (pos < 0) {
+           int zerror = 0;
+           fd->errcookie = gzerror(gzfile, &zerror);
+           if (zerror == Z_ERRNO) {
+               fd->syserrno = errno;
+               fd->errcookie = strerror(fd->syserrno);
+           }
+       }
+#else
+       pos = -2;
+#endif    
+    }
+    return pos;
+}
 static const struct FDIO_s gzdio_s = {
   gzdRead, gzdWrite, gzdSeek, gzdClose, fdLink, fdFree, fdNew, fdFileno,
-  NULL, gzdOpen, gzdFileno, gzdFlush
+  NULL, gzdOpen, gzdFileno, gzdFlush, gzdTell
 };
 static const FDIO_t gzdio = &gzdio_s ;
 
 /* =============================================================== */
-/* Support for BZIP2 library.
- */
+/* Support for BZIP2 library.  */
 #if HAVE_BZLIB_H
 
 #include <bzlib.h>
 
-#ifdef HAVE_BZ2_1_0
-# define bzopen  BZ2_bzopen
-# define bzclose BZ2_bzclose
-# define bzdopen BZ2_bzdopen
-# define bzerror BZ2_bzerror
-# define bzflush BZ2_bzflush
-# define bzread  BZ2_bzread
-# define bzwrite BZ2_bzwrite
-#endif /* HAVE_BZ2_1_0 */
-
 static void * bzdFileno(FD_t fd)
 {
     return iotFileno(fd, bzdio);
@@ -871,16 +747,15 @@ static FD_t bzdOpen(const char * path, const char * mode)
 {
     FD_t fd;
     BZFILE *bzfile;;
-    if ((bzfile = bzopen(path, mode)) == NULL)
+    if ((bzfile = BZ2_bzopen(path, mode)) == NULL)
        return NULL;
     fd = fdNew(path);
     fdPop(fd); fdPush(fd, bzdio, bzfile, -1);
     return fdLink(fd);
 }
 
-static FD_t bzdFdopen(void * cookie, const char * fmode)
+static FD_t bzdFdopen(FD_t fd, const char * fmode)
 {
-    FD_t fd = c2f(cookie);
     int fdno;
     BZFILE *bzfile;
 
@@ -888,7 +763,7 @@ static FD_t bzdFdopen(void * cookie, const char * fmode)
     fdno = fdFileno(fd);
     fdSetFdno(fd, -1);         /* XXX skip the fdio close */
     if (fdno < 0) return NULL;
-    bzfile = bzdopen(fdno, fmode);
+    bzfile = BZ2_bzdopen(fdno, fmode);
     if (bzfile == NULL) return NULL;
 
     fdPush(fd, bzdio, bzfile, fdno);           /* Push bzdio onto stack */
@@ -898,66 +773,49 @@ static FD_t bzdFdopen(void * cookie, const char * fmode)
 
 static int bzdFlush(FD_t fd)
 {
-    return bzflush(bzdFileno(fd));
+    return BZ2_bzflush(bzdFileno(fd));
 }
 
-/* =============================================================== */
-static ssize_t bzdRead(void * cookie, void * buf, size_t count)
+static ssize_t bzdRead(FD_t fd, void * buf, size_t count)
 {
-    FD_t fd = c2f(cookie);
     BZFILE *bzfile;
     ssize_t rc = 0;
 
-    if (fd == NULL || fd->bytesRemain == 0) return 0;  /* XXX simulate EOF */
     bzfile = bzdFileno(fd);
-    fdstat_enter(fd, FDSTAT_READ);
     if (bzfile)
-       rc = bzread(bzfile, buf, count);
+       rc = BZ2_bzread(bzfile, buf, count);
     if (rc == -1) {
        int zerror = 0;
        if (bzfile)
-           fd->errcookie = bzerror(bzfile, &zerror);
-    } else if (rc >= 0) {
-       fdstat_exit(fd, FDSTAT_READ, rc);
-       if (fd->digests && rc > 0) fdUpdateDigests(fd, buf, rc);
+           fd->errcookie = BZ2_bzerror(bzfile, &zerror);
     }
     return rc;
 }
 
-static ssize_t bzdWrite(void * cookie, const void * buf, size_t count)
+static ssize_t bzdWrite(FD_t fd, const void * buf, size_t count)
 {
-    FD_t fd = c2f(cookie);
     BZFILE *bzfile;
     ssize_t rc;
 
-    if (fd == NULL || fd->bytesRemain == 0) return 0;  /* XXX simulate EOF */
-
-    if (fd->digests && count > 0) fdUpdateDigests(fd, buf, count);
-
     bzfile = bzdFileno(fd);
-    fdstat_enter(fd, FDSTAT_WRITE);
-    rc = bzwrite(bzfile, (void *)buf, count);
+    rc = BZ2_bzwrite(bzfile, (void *)buf, count);
     if (rc == -1) {
        int zerror = 0;
-       fd->errcookie = bzerror(bzfile, &zerror);
-    } else if (rc > 0) {
-       fdstat_exit(fd, FDSTAT_WRITE, rc);
+       fd->errcookie = BZ2_bzerror(bzfile, &zerror);
     }
     return rc;
 }
 
-static int bzdClose( void * cookie)
+static int bzdClose(FD_t fd)
 {
-    FD_t fd = c2f(cookie);
     BZFILE *bzfile;
     int rc;
 
     bzfile = bzdFileno(fd);
 
     if (bzfile == NULL) return -2;
-    fdstat_enter(fd, FDSTAT_CLOSE);
     /* FIX: check rc */
-    bzclose(bzfile);
+    BZ2_bzclose(bzfile);
     rc = 0;    /* XXX FIXME */
 
     /* XXX TODO: preserve fd if errors */
@@ -965,14 +823,10 @@ static int bzdClose( void * cookie)
     if (fd) {
        if (rc == -1) {
            int zerror = 0;
-           fd->errcookie = bzerror(bzfile, &zerror);
-       } else if (rc >= 0) {
-           fdstat_exit(fd, FDSTAT_CLOSE, rc);
+           fd->errcookie = BZ2_bzerror(bzfile, &zerror);
        }
     }
 
-DBGIO(fd, (stderr, "==>\tbzdClose(%p) rc %lx %s\n", cookie, (unsigned long)rc, fdbg(fd)));
-
     if (_rpmio_debug || rpmIsDebug()) fdstat_print(fd, "BZDIO", stderr);
     if (rc == 0)
        fdFree(fd);
@@ -980,14 +834,13 @@ DBGIO(fd, (stderr, "==>\tbzdClose(%p) rc %lx %s\n", cookie, (unsigned long)rc, f
 }
 
 static const struct FDIO_s bzdio_s = {
-  bzdRead, bzdWrite, fdSeekNot, bzdClose, fdLink, fdFree, fdNew, fdFileno,
-  NULL, bzdOpen, bzdFileno, bzdFlush
+  bzdRead, bzdWrite, NULL, bzdClose, fdLink, fdFree, fdNew, fdFileno,
+  NULL, bzdOpen, bzdFileno, bzdFlush, NULL
 };
 static const FDIO_t bzdio = &bzdio_s ;
 
 #endif /* HAVE_BZLIB_H */
 
-/* =============================================================== */
 static const char * getFdErrstr (FD_t fd)
 {
     const char *errstr = NULL;
@@ -1013,8 +866,7 @@ static const char * getFdErrstr (FD_t fd)
 }
 
 /* =============================================================== */
-/* Support for LZMA library.
- */
+/* Support for LZMA library.  */
 
 #ifdef HAVE_LZMA_H
 
@@ -1202,8 +1054,6 @@ static ssize_t lzwrite(LZFILE *lzfile, void *buf, size_t len)
     }
 }
 
-/* =============================================================== */
-
 static void * lzdFileno(FD_t fd)
 {
     void * rc = NULL;
@@ -1232,9 +1082,8 @@ static FD_t xzdOpen(const char * path, const char * mode)
     return fdLink(fd);
 }
 
-static FD_t xzdFdopen(void * cookie, const char * fmode)
+static FD_t xzdFdopen(FD_t fd, const char * fmode)
 {
-    FD_t fd = c2f(cookie);
     int fdno;
     LZFILE *lzfile;
 
@@ -1259,9 +1108,8 @@ static FD_t lzdOpen(const char * path, const char * mode)
     return fdLink(fd);
 }
 
-static FD_t lzdFdopen(void * cookie, const char * fmode)
+static FD_t lzdFdopen(FD_t fd, const char * fmode)
 {
-    FD_t fd = c2f(cookie);
     int fdno;
     LZFILE *lzfile;
 
@@ -1280,73 +1128,54 @@ static int lzdFlush(FD_t fd)
     return lzflush(lzdFileno(fd));
 }
 
-/* =============================================================== */
-static ssize_t lzdRead(void * cookie, void * buf, size_t count)
+static ssize_t lzdRead(FD_t fd, void * 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 */
     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->digests && rc > 0) fdUpdateDigests(fd, buf, rc);
     }
     return rc;
 }
 
-static ssize_t lzdWrite(void * cookie, const void * buf, size_t count)
+static ssize_t lzdWrite(FD_t fd, const void * 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->digests && count > 0) fdUpdateDigests(fd, 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 int lzdClose(void * cookie)
+static int lzdClose(FD_t fd)
 {
-    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);
+           fd->errcookie = "lzclose error";
+           fd->syserrno = errno;
+           fd->errcookie = strerror(fd->syserrno);
        }
     }
 
-DBGIO(fd, (stderr, "==>\tlzdClose(%p) rc %lx %s\n", cookie, (unsigned long)rc, fdbg(fd)));
-
     if (_rpmio_debug || rpmIsDebug()) fdstat_print(fd, "XZDIO", stderr);
     if (rc == 0)
        fdFree(fd);
@@ -1354,14 +1183,14 @@ DBGIO(fd, (stderr, "==>\tlzdClose(%p) rc %lx %s\n", cookie, (unsigned long)rc, f
 }
 
 static struct FDIO_s xzdio_s = {
-  lzdRead, lzdWrite, fdSeekNot, lzdClose, NULL, NULL, NULL, fdFileno,
-  NULL, xzdOpen, lzdFileno, lzdFlush
+  lzdRead, lzdWrite, NULL, lzdClose, NULL, NULL, NULL, fdFileno,
+  NULL, xzdOpen, lzdFileno, lzdFlush, NULL
 };
 static const FDIO_t xzdio = &xzdio_s;
 
 static struct FDIO_s lzdio_s = {
-  lzdRead, lzdWrite, fdSeekNot, lzdClose, NULL, NULL, NULL, fdFileno,
-  NULL, lzdOpen, lzdFileno, lzdFlush
+  lzdRead, lzdWrite, NULL, lzdClose, NULL, NULL, NULL, fdFileno,
+  NULL, lzdOpen, lzdFileno, lzdFlush, NULL
 };
 static const FDIO_t lzdio = &lzdio_s;
 
@@ -1379,45 +1208,67 @@ const char *Fstrerror(FD_t fd)
 #define        FDIOVEC(_fd, _vec)      \
   ((fdGetIo(_fd) && fdGetIo(_fd)->_vec) ? fdGetIo(_fd)->_vec : NULL)
 
-ssize_t Fread(void *buf, size_t size, size_t nmemb, FD_t fd) {
-    fdio_read_function_t _read;
-    int rc;
+ssize_t Fread(void *buf, size_t size, size_t nmemb, FD_t fd)
+{
+    ssize_t rc = -1;
 
-    if (fd == NULL)
-       return 0;
+    if (fd != NULL) {
+       fdio_read_function_t _read = FDIOVEC(fd, read);
 
-    _read = FDIOVEC(fd, read);
+       fdstat_enter(fd, FDSTAT_READ);
+       do {
+           rc = (_read ? (*_read) (fd, buf, size * nmemb) : -2);
+       } while (rc == -1 && errno == EINTR);
+       fdstat_exit(fd, FDSTAT_READ, rc);
+
+       if (fd->digests && rc > 0)
+           fdUpdateDigests(fd, buf, rc);
+    }
+
+    DBGIO(fd, (stderr, "==>\tFread(%p,%p,%ld) rc %ld %s\n",
+         fd, buf, (long)size * nmemb, (long)rc, fdbg(fd)));
 
-    rc = (_read ? (*_read) (fd, buf, size * nmemb) : -2);
     return rc;
 }
 
 ssize_t Fwrite(const void *buf, size_t size, size_t nmemb, FD_t fd)
 {
-    fdio_write_function_t _write;
-    int rc;
+    ssize_t rc = -1;
 
-    if (fd == NULL)
-       return 0;
+    if (fd != NULL) {
+       fdio_write_function_t _write = FDIOVEC(fd, write);
+       
+       fdstat_enter(fd, FDSTAT_WRITE);
+       do {
+           rc = (_write ? _write(fd, buf, size * nmemb) : -2);
+       } while (rc == -1 && errno == EINTR);
+       fdstat_exit(fd, FDSTAT_WRITE, rc);
+
+       if (fd->digests && rc > 0)
+           fdUpdateDigests(fd, buf, rc);
+    }
 
-    _write = FDIOVEC(fd, write);
+    DBGIO(fd, (stderr, "==>\tFwrite(%p,%p,%ld) rc %ld %s\n",
+         fd, buf, (long)size * nmemb, (long)rc, fdbg(fd)));
 
-    rc = (_write ? _write(fd, buf, size * nmemb) : -2);
     return rc;
 }
 
-int Fseek(FD_t fd, off_t offset, int whence) {
-    fdio_seek_function_t _seek;
-    off_t pos = offset;
+int Fseek(FD_t fd, off_t offset, int whence)
+{
+    int rc = -1;
 
-    long int rc;
+    if (fd != NULL) {
+       fdio_seek_function_t _seek = FDIOVEC(fd, seek);
 
-    if (fd == NULL)
-       return -1;
+       fdstat_enter(fd, FDSTAT_SEEK);
+       rc = (_seek ? _seek(fd, offset, whence) : -2);
+       fdstat_exit(fd, FDSTAT_SEEK, rc);
+    }
 
-    _seek = FDIOVEC(fd, seek);
+    DBGIO(fd, (stderr, "==>\tFseek(%p,%ld,%d) rc %lx %s\n",
+         fd, (long)offset, whence, (unsigned long)rc, fdbg(fd)));
 
-    rc = (_seek ? _seek(fd, pos, whence) : -2);
     return rc;
 }
 
@@ -1429,6 +1280,7 @@ int Fclose(FD_t fd)
        return -1;
 
     fd = fdLink(fd);
+    fdstat_enter(fd, FDSTAT_CLOSE);
     while (fd->nfps >= 0) {
        fdio_close_function_t _close = FDIOVEC(fd, close);
        rc = _close ? _close(fd) : -2;
@@ -1439,6 +1291,10 @@ int Fclose(FD_t fd)
            ec = rc;
        fdPop(fd);
     }
+    fdstat_exit(fd, FDSTAT_CLOSE, rc);
+    DBGIO(fd, (stderr, "==>\tFclose(%p) rc %lx %s\n",
+         (fd ? fd : NULL), (unsigned long)rc, fdbg(fd)));
+
     fdFree(fd);
     return ec;
 }
@@ -1518,7 +1374,7 @@ static void cvtfmode (const char *m,
 
 FD_t Fdopen(FD_t ofd, const char *fmode)
 {
-    char stdio[20], other[20], zstdio[20];
+    char stdio[20], other[20], zstdio[40];
     const char *end = NULL;
     FDIO_t iof = NULL;
     FD_t fd = ofd;
@@ -1533,8 +1389,8 @@ fprintf(stderr, "*** Fdopen(%p,%s) %s\n", fd, fmode, fdbg(fd));
     if (stdio[0] == '\0')
        return NULL;
     zstdio[0] = '\0';
-    strncat(zstdio, stdio, sizeof(zstdio) - strlen(zstdio));
-    strncat(zstdio, other, sizeof(zstdio) - strlen(zstdio));
+    strncat(zstdio, stdio, sizeof(zstdio) - strlen(zstdio) - 1);
+    strncat(zstdio, other, sizeof(zstdio) - strlen(zstdio) - 1);
 
     if (end == NULL && other[0] == '\0')
        return fd;
@@ -1628,41 +1484,32 @@ fprintf(stderr, "*** Fopen WTFO path %s fmode %s\n", path, fmode);
 
     if (fd)
        fd = Fdopen(fd, fmode);
+
+    DBGIO(fd, (stderr, "==>\tFopen(\"%s\",%x,0%o) %s\n",
+         path, (unsigned)flags, (unsigned)perms, fdbg(fd)));
+
     return fd;
 }
 
 int Fflush(FD_t fd)
 {
-    void * vh;
-    if (fd == NULL) return -1;
+    int rc = -1;
+    if (fd != NULL) {
+       fdio_fflush_function_t _fflush = FDIOVEC(fd, _fflush);
 
-    vh = fdGetFp(fd);
-    if (vh && fdGetIo(fd) == gzdio)
-       return gzdFlush(vh);
-#if HAVE_BZLIB_H
-    if (vh && fdGetIo(fd) == bzdio)
-       return bzdFlush(vh);
-#endif
-#if HAVE_LZMA_H
-    if (vh && (fdGetIo(fd) == xzdio || fdGetIo(fd) == lzdio))
-       return lzdFlush(vh);
-#endif
-/* FIXME: If we get here, something went wrong above */
-    return 0;
+       rc = (_fflush ? _fflush(fd) : -2);
+    }
+    return rc;
 }
 
 off_t Ftell(FD_t fd)
 {
-    FDIO_t iot;
-    off_t pos = -2; /* assume not implemented */
+    off_t pos = -1;
+    if (fd != NULL) {
+       fdio_ftell_function_t _ftell = FDIOVEC(fd, _ftell);
 
-    if (fd == NULL) return -1;
-    iot = fdGetIo(fd);
-    /* this wont work correctly for compressed types */
-    if (iot == fdio || iot == ufdio) {
-       pos = lseek(Fileno(fd), 0, SEEK_CUR);
+       pos = (_ftell ? _ftell(fd) : -2);
     }
-
     return pos;
 }