- create rpmio directory for librpmio.
authorjbj <devnull@localhost>
Wed, 7 Jun 2000 23:25:41 +0000 (23:25 +0000)
committerjbj <devnull@localhost>
Wed, 7 Jun 2000 23:25:41 +0000 (23:25 +0000)
CVS patchset: 3820
CVS date: 2000/06/07 23:25:41

31 files changed:
CHANGES
Makefile.am
build/Makefile.am
configure.in
lib/Makefile.am
lib/rpmio.c [new file with mode: 0644]
po/POTFILES.in
po/cs.po
po/de.po
po/fi.po
po/fr.po
po/ja.po
po/pl.po
po/pt_BR.po
po/rpm.pot
po/ru.po
po/sk.po
po/sl.po
po/sr.po
po/sv.po
po/tr.po
python/Makefile.am
python/Makefile.in
rpm.spec
rpmio/.cvsignore [new file with mode: 0644]
rpmio/Makefile.am [new file with mode: 0644]
rpmio/rpmio.c [new file with mode: 0644]
rpmio/rpmio.h [moved from lib/rpmio.h with 100% similarity]
rpmio/rpmurl.h [moved from lib/rpmurl.h with 100% similarity]
rpmio/url.c [moved from lib/url.c with 100% similarity]
tools/Makefile.am

diff --git a/CHANGES b/CHANGES
index cfc235d..1ecfcfe 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -54,6 +54,7 @@
        - add optflags for i486 and i586.
        - fix: segfault with legacy packages missing RPMTAG_FILEINODES.
        - require db3 in default configuration.
+       - create rpmio directory for librpmio.
        
 3.0.3 -> 3.0.4
        - use compressed filenames on install side.
index 8a1a914..7c8353a 100644 (file)
@@ -13,20 +13,23 @@ EXTRA_DIST = CHANGES CREDITS GROUPS README.amiga INSTALL \
 EXTRA_PROGRAMS = rpmconvert
 
 # XXX TODO: python perl
-SUBDIRS = intl po popt lib build misc tools scripts tests doc .
+SUBDIRS = intl po popt rpmio lib build misc tools scripts tests doc .
 
-INCLUDES = -I$(top_srcdir)/build -I$(top_srcdir)/lib -I$(top_srcdir)/popt \
-       @INCPATH@
+INCLUDES = -I$(top_srcdir)/build -I$(top_srcdir)/lib -I$(top_srcdir)/rpmio \
+       -I$(top_srcdir)/popt @INCPATH@
 
-myLDFLAGS = -L$(top_builddir)/build -L$(top_builddir)/lib -L$(top_builddir)/popt
+myLDFLAGS = -L$(top_builddir)/build/.libs -L$(top_builddir)/lib/.libs \
+       -L$(top_builddir)/rpmio/.libs -L$(top_builddir)/popt/.libs
 
 # XXX libtool can/should generate dependent libs.
 # XXX solaris2.6 cannot use *.la with --all-static (downrev binutils/egcs?)
+# XXX top_builddir ldpaths are wrong building in tree
 myLDADD = \
-       $(top_builddir)/popt/libpopt.la \
-       $(top_builddir)/lib/librpm.la \
        $(top_builddir)/build/librpmbuild.la \
-       @INTLLIBS@ @LIBMISC@
+       $(top_builddir)/lib/librpm.la \
+       $(top_builddir)/rpmio/librpmio.la \
+       $(top_builddir)/popt/libpopt.la \
+       @INTLLIBS@
 
 rpmbindir = `echo $(bindir) | sed -e s,usr/bin,bin,`
 rpmbin_PROGRAMS = rpm
@@ -47,39 +50,45 @@ noinst_HEADERS = \
 
 rpm_SOURCES =          rpm.c
 rpm_LDFLAGS =          @LDFLAGS_STATIC@ $(myLDFLAGS)
-rpm_LDADD =            $(myLDADD)
+rpm_LDADD =            $(myLDADD) @LIBMISC@
 
 rpmb_SOURCES =         build.c
+rpmb_LDFLAGS =         $(myLDFLAGS)
 rpmb_LDADD =           rpmb.o $(myLDADD)
 rpmb.o:        rpmqv.c
        $(COMPILE) -DIAM_RPMBT -o $@ -c $<
 
 rpmdb_SOURCES =
+rpmdb_LDFLAGS =                $(myLDFLAGS)
 rpmdb_LDADD =          rpmdb.o $(myLDADD)
 rpmdb.o:       rpmqv.c
        $(COMPILE) -DIAM_RPMDB -o $@ -c $<
 
 rpmi_SOURCES =
+rpmi_LDFLAGS =         $(myLDFLAGS)
 rpmi_LDADD =           rpmi.o $(myLDADD)
 rpmi.o:        rpmqv.c
        $(COMPILE) -DIAM_RPMEIU -o $@ -c $<
 
 rpmk_SOURCES =
+rpmk_LDFLAGS =         $(myLDFLAGS)
 rpmk_LDADD =           rpmk.o $(myLDADD)
 rpmk.o:        rpmqv.c
        $(COMPILE) -DIAM_RPMK -o $@ -c $<
 
 rpmq_SOURCES =
+rpmq_LDFLAGS =         $(myLDFLAGS)
 rpmq_LDADD =           rpmq.o $(myLDADD)
 rpmq.o:        rpmqv.c
        $(COMPILE) -DIAM_RPMQV -o $@ -c $<
 
 rpm2cpio_SOURCES =     rpm2cpio.c
 rpm2cpio_LDFLAGS =     @LDFLAGS_STATIC@ $(myLDFLAGS)
-rpm2cpio_LDADD =       $(myLDADD)
+rpm2cpio_LDADD =       $(myLDADD) @LIBMISC@
 
 rpmconvert_SOURCES =   convertdb.c oldrpmdb.c
 ## Libmisc.a is required for rpmconvert.
+rpmconvert_LDFLAGS =   $(myLDFLAGS)
 rpmconvert_LDADD =     $(myLDADD) -lgdbm
 
 $(PROGRAMS):           $(myLDADD)
index 2254f95..71a24be 100644 (file)
@@ -2,8 +2,8 @@
 
 AUTOMAKE_OPTIONS = 1.4 foreign
 
-INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_srcdir)/popt \
-       @INCPATH@
+INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_srcdir)/rpmio \
+       -I$(top_srcdir)/popt @INCPATH@
 
 pkgincdir = $(pkgincludedir)
 pkginc_HEADERS = rpmbuild.h rpmspec.h
@@ -15,7 +15,14 @@ librpmbuild_la_SOURCES = \
        parseBuildInstallClean.c parseChangelog.c parseDescription.c \
        parseFiles.c parsePreamble.c parsePrep.c parseReqs.c parseScript.c \
        parseSpec.c reqprov.c spec.c
-librpmbuild_la_LIBADD = -lrpm
+librpmbuild_la_LIBADD = -L$(top_builddir)/lib/.libs -lrpm
+
+# XXX Drill out -L ldflags remnants until libtool-1.4 appears
+install-data-local:
+       @cd $(libdir) && \
+       sed -e "s|-L$(top_builddir)/lib/.libs ||" < librpmbuild.la > .librpmbuild.la && \
+       mv .librpmbuild.la librpmio.la
+
 
 .PHONY:        lclint
 lclint:
index f240ba8..ed58a36 100644 (file)
@@ -963,7 +963,8 @@ dnl export LIBS INCPATH CONFIG_SITE
 
 AC_CONFIG_SUBDIRS(popt)
 AC_OUTPUT([Doxyfile Makefile rpmrc macros platform rpmpopt scripts/brp-redhat
-       lib/Makefile build/Makefile tools/Makefile scripts/Makefile
+       rpmio/Makefile lib/Makefile build/Makefile tools/Makefile
+       scripts/Makefile
        tests/Makefile tests/rpmrc tests/macros tests/hello-test/Makefile
        misc/Makefile po/Makefile.in intl/Makefile
        doc/Makefile doc/manual/Makefile
index 2d365a1..ec97235 100644 (file)
@@ -2,20 +2,21 @@
 
 AUTOMAKE_OPTIONS = 1.4 foreign
 
-INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/build -I$(top_srcdir)/popt @INCPATH@
+INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/build -I$(top_srcdir)/rpmio \
+       -I$(top_srcdir)/popt @INCPATH@
 
 EXTRA_DIST = falloc.c db1.c db2.c db3.c
 
 pkgincdir = $(pkgincludedir)
 pkginc_HEADERS = \
-       header.h misc.h rpmio.h rpmlib.h rpmmacro.h rpmurl.h stringbuf.h
+       header.h misc.h rpmlib.h rpmmacro.h stringbuf.h
 noinst_HEADERS = \
        cpio.h depends.h falloc.h fprint.h hash.h install.h \
        md5.h oldheader.h oldrpmdb.h rpm_malloc.h \
        rpmdb.h rpmlead.h signature.h
 
-mylibpaths= -L$(top_builddir)/lib -L$(top_builddir)/popt
-mylibs=        -lrpm -lpopt @INTLLIBS@ @LIBMISC@
+mylibpaths =   -L$(top_builddir)/lib -L$(top_builddir)/popt
+mylibs =       -lrpm -lrpmio -lpopt @INTLLIBS@ @LIBMISC@
 
 lib_LTLIBRARIES = librpm.la
 librpm_la_SOURCES = \
@@ -25,11 +26,19 @@ librpm_la_SOURCES = \
        messages.c misc.c oldheader.c package.c problems.c \
        poptBT.c poptQV.c query.c \
        rpmchecksig.c rpmdb.c rpmerr.c rpminstall.c \
-       rpmio.c rpmlead.c rpmmalloc.c rpmrc.c signature.c stringbuf.c stubs.c \
-       tagName.c tagtable.c transaction.c uninstall.c url.c verify.c
-librpm_la_LIBADD = $(subst .c,.lo,$(DBLIBOBJS)) -lpopt
-
-falloc.lo: falloc.c $(top_srcdir)/system.h rpmio.h falloc.h
+       rpmlead.c rpmmalloc.c rpmrc.c signature.c stringbuf.c stubs.c \
+       tagName.c tagtable.c transaction.c uninstall.c verify.c
+librpm_la_LDFLAGS = -L$(top_builddir)/rpmio/.libs -lrpmio
+#      -L$(top_builddir)/popt -lpopt
+librpm_la_LIBADD = $(subst .c,.lo,$(DBLIBOBJS))
+
+# XXX Drill out -L ldflags remnants until libtool-1.4 appears
+install-data-local:
+       @cd $(libdir) && \
+       sed -e "s|-L$(top_builddir)/rpmio/.libs ||" < librpm.la > .librpm.la && \
+       mv .librpm.la librpm.la
+
+falloc.lo: falloc.c $(top_srcdir)/system.h $(top_srcdir)/rpmio/rpmio.h falloc.h
        $(LIBTOOL) --mode=compile $(COMPILE) -c $<
 
 db3.lo: db3.c $(top_srcdir)/system.h rpmlib.h rpmdb.h
diff --git a/lib/rpmio.c b/lib/rpmio.c
new file mode 100644 (file)
index 0000000..8d10dc2
--- /dev/null
@@ -0,0 +1,4074 @@
+#include "system.h"
+
+#include <stdarg.h>
+
+#ifdef __LCLINT__
+#define        ntohl(_x)       (_x)
+#define        ntohs(_x)       (_x)
+#define        htonl(_x)       (_x)
+#define        htons(_x)       (_x)
+typedef        unsigned int            uint32_t;
+#define        INADDR_ANY              ((uint32_t) 0x00000000)
+#define        IPPROTO_IP              0
+
+#else  /* __LCLINT__ */
+
+#if HAVE_MACHINE_TYPES_H
+# include <machine/types.h>
+#endif
+
+#include <netinet/in.h>
+#include <arpa/inet.h>         /* XXX for inet_aton and HP-UX */
+
+#if HAVE_NETINET_IN_SYSTM_H
+# include <sys/types.h>
+# include <netinet/in_systm.h>
+#endif
+
+#if HAVE_LIBIO_H && defined(_IO_BAD_SEEN)
+#define        _USE_LIBIO      1
+#endif
+
+#endif /* __LCLINT__ */
+
+#if HAVE_HERRNO && defined(__hpux) /* XXX HP-UX w/o -D_XOPEN_SOURCE needs */
+extern int h_errno;
+#endif
+
+#ifndef IPPORT_FTP
+#define IPPORT_FTP     21
+#endif
+#ifndef        IPPORT_HTTP
+#define        IPPORT_HTTP     80
+#endif
+
+
+#if !defined(HAVE_INET_ATON)
+static int inet_aton(const char *cp, struct in_addr *inp)
+{
+    long addr;
+
+    addr = inet_addr(cp);
+    if (addr == ((long) -1)) return 0;
+
+    memcpy(inp, &addr, sizeof(addr));
+    return 1;
+}
+#endif
+
+#if defined(USE_ALT_DNS) && USE_ALT_DNS
+#include "dns.h"
+#endif
+
+#include <rpmlib.h>
+#include <rpmio.h>
+#include <rpmurl.h>
+#include "misc.h"
+
+#include <assert.h>
+
+typedef struct _FDSTACK_s {
+       FDIO_t          io;
+/*@dependent@*/ void * fp;
+       int             fdno;
+} FDSTACK_t;
+
+typedef struct {
+       int             count;
+       off_t           bytes;
+       time_t          msecs;
+} OPSTAT_t;
+
+typedef        struct {
+       struct timeval  create;
+       struct timeval  begin;
+       OPSTAT_t        ops[4];
+#define        FDSTAT_READ     0
+#define        FDSTAT_WRITE    1
+#define        FDSTAT_SEEK     2
+#define        FDSTAT_CLOSE    3
+} FDSTAT_t;
+
+struct _FD_s {
+/*@refs@*/ int         nrefs;
+       int             flags;
+#define        RPMIO_DEBUG_IO          0x40000000
+#define        RPMIO_DEBUG_REFS        0x20000000
+       int             magic;
+#define        FDMAGIC         0xbeefdead
+
+       int             nfps;
+       FDSTACK_t       fps[8];
+       int             urlType;        /* ufdio: */
+
+/*@dependent@*/ void * url;            /* ufdio: URL info */
+       int             rd_timeoutsecs; /* ufdRead: per FD_t timer */
+       ssize_t         bytesRemain;    /* ufdio: */
+       ssize_t         contentLength;  /* ufdio: */
+       int             persist;        /* ufdio: */
+       int             wr_chunked;     /* ufdio: */
+
+       int             syserrno;       /* last system errno encountered */
+/*@observer@*/ const void *errcookie;  /* gzdio/bzdio/ufdio: */
+
+       FDSTAT_t        *stats;         /* I/O statistics */
+
+       int             ftpFileDoneNeeded; /* ufdio: (FTP) */
+       unsigned int    firstFree;      /* fadio: */
+       long int        fileSize;       /* fadio: */
+       long int        fd_cpioPos;     /* cpio: */
+};
+
+#define        FDSANE(fd)      assert(fd && fd->magic == FDMAGIC)
+#define FDNREFS(fd)    (fd ? ((FD_t)fd)->nrefs : -9)
+#define FDTO(fd)       (fd ? ((FD_t)fd)->rd_timeoutsecs : -99)
+#define FDCPIOPOS(fd)  (fd ? ((FD_t)fd)->fd_cpioPos : -99)
+
+#define        FDONLY(fd)      assert(fdGetIo(fd) == fdio)
+#define        GZDONLY(fd)     assert(fdGetIo(fd) == gzdio)
+#define        BZDONLY(fd)     assert(fdGetIo(fd) == bzdio)
+
+#define        UFDONLY(fd)     /* assert(fdGetIo(fd) == ufdio) */
+
+#define        fdGetFILE(_fd)  ((FILE *)fdGetFp(_fd))
+
+/*@access urlinfo@*/
+
+#if _USE_LIBIO
+int noLibio = 0;
+#else
+int noLibio = 1;
+#endif
+
+#define TIMEOUT_SECS 60
+static int ftpTimeoutSecs = TIMEOUT_SECS;
+static int httpTimeoutSecs = TIMEOUT_SECS;
+
+int _ftp_debug = 0;
+int _rpmio_debug = 0;
+#define        DBG(_f, _m, _x) \
+    if ((_rpmio_debug | ((_f) ? ((FD_t)(_f))->flags : 0)) & (_m)) fprintf _x
+
+#define DBGIO(_f, _x)  DBG((_f), RPMIO_DEBUG_IO, _x)
+#define DBGREFS(_f, _x)        DBG((_f), RPMIO_DEBUG_REFS, _x)
+
+/* =============================================================== */
+const FDIO_t fdGetIo(FD_t fd) {
+#ifdef NOISY
+DBGIO(0, (stderr, "==>\tfdGetIo(%p)\n", fd));
+#endif
+    FDSANE(fd);
+    return fd->fps[fd->nfps].io;
+}
+
+void fdSetIo(FD_t fd, FDIO_t io) {
+#ifdef NOISY
+DBGIO(0, (stderr, "==>\tfdSetIo(%p,%p) lvl %d \n", fd, io, (fd ? fd->nfps : -1)));
+#endif
+    FDSANE(fd);
+    fd->fps[fd->nfps].io = io;
+    return;
+}
+
+inline /*@dependent@*/ /*@null@*/ void * fdGetFp(FD_t fd) {
+#ifdef NOISY
+DBGIO(0, (stderr, "==>\tfdGetFp(%p) lvl %d\n", fd, (fd ? fd->nfps : -1)));
+#endif
+    FDSANE(fd);
+    return fd->fps[fd->nfps].fp;
+}
+
+static inline void fdSetFp(FD_t fd, /*@keep@*/ void * fp) {
+#ifdef NOISY
+DBGIO(0, (stderr, "==>\tfdSetFp(%p,%p) lvl %d\n", fd, fp, (fd ? fd->nfps : -1)));
+#endif
+    FDSANE(fd);
+    fd->fps[fd->nfps].fp = fp;
+}
+
+static inline int fdGetFdno(FD_t fd) {
+#ifdef NOISY
+DBGIO(0, (stderr, "==>\tfdGetFdno(%p) lvl %d\n", fd, (fd ? fd->nfps : -1)));
+#endif
+    FDSANE(fd);
+    return fd->fps[fd->nfps].fdno;
+}
+
+void fdSetFdno(FD_t fd, int fdno) {
+#ifdef NOISY
+DBGIO(0, (stderr, "==>\tfdSetFdno(%p,%d)\n", fd, fdno));
+#endif
+    FDSANE(fd);
+    fd->fps[fd->nfps].fdno = fdno;
+}
+
+void fdSetContentLength(FD_t fd, ssize_t contentLength)
+{
+    FDSANE(fd);
+    fd->contentLength = fd->bytesRemain = contentLength;
+}
+
+static /*@observer@*/ const char * fdbg(FD_t fd)
+{
+    static char buf[BUFSIZ];
+    char *be = buf;
+    int i;
+
+#if DYING
+    sprintf(be, "fd %p", fd);  be += strlen(be);
+    if (fd->rd_timeoutsecs >= 0) {
+       sprintf(be, " secs %d", fd->rd_timeoutsecs);
+       be += strlen(be);
+    }
+#endif
+    if (fd->bytesRemain != -1) {
+       sprintf(be, " clen %d", (int)fd->bytesRemain);
+       be += strlen(be);
+     }
+    if (fd->wr_chunked) {
+       strcpy(be, " chunked");
+       be += strlen(be);
+     }
+    *be++ = '\t';
+    for (i = fd->nfps; i >= 0; i--) {
+       FDSTACK_t * fps = &fd->fps[i];
+       if (i != fd->nfps)
+           *be++ = ' ';
+       *be++ = '|';
+       *be++ = ' ';
+       if (fps->io == fdio) {
+           sprintf(be, "FD %d fp %p", fps->fdno, fps->fp);
+       } else if (fps->io == ufdio) {
+           sprintf(be, "UFD %d fp %p", fps->fdno, fps->fp);
+       } else if (fps->io == fadio) {
+           sprintf(be, "FAD %d fp %p", fps->fdno, fps->fp);
+       } else if (fps->io == gzdio) {
+           sprintf(be, "GZD %p fdno %d", fps->fp, fps->fdno);
+#if HAVE_BZLIB_H
+       } else if (fps->io == bzdio) {
+           sprintf(be, "BZD %p fdno %d", fps->fp, fps->fdno);
+#endif
+       } else if (fps->io == fpio) {
+           sprintf(be, "%s %p(%d) fdno %d",
+               (fps->fdno < 0 ? "LIBIO" : "FP"),
+               fps->fp, fileno(((FILE *)fps->fp)), fps->fdno);
+       } else {
+           sprintf(be, "??? io %p fp %p fdno %d ???",
+               fps->io, fps->fp, fps->fdno);
+       }
+       be += strlen(be);
+       *be = '\0';
+    }
+    return buf;
+}
+
+inline void fdPush(FD_t fd, FDIO_t io, void * fp, int fdno) {
+    FDSANE(fd);
+    if (fd->nfps >= (sizeof(fd->fps)/sizeof(fd->fps[0]) - 1))
+       return;
+    fd->nfps++;
+    fdSetIo(fd, io);
+    fdSetFp(fd, fp);
+    fdSetFdno(fd, fdno);
+DBGIO(0, (stderr, "==>\tfdPush(%p,%p,%p,%d) lvl %d %s\n", fd, io, fp, fdno, fd->nfps, fdbg(fd)));
+}
+
+inline void fdPop(FD_t fd) {
+    FDSANE(fd);
+    if (fd->nfps < 0) return;
+DBGIO(0, (stderr, "==>\tfdPop(%p) lvl %d io %p fp %p fdno %d %s\n", fd, fd->nfps, fdGetIo(fd), fdGetFp(fd), fdGetFdno(fd), fdbg(fd)));
+    fdSetIo(fd, NULL);
+    fdSetFp(fd, NULL);
+    fdSetFdno(fd, -1);
+    fd->nfps--;
+}
+
+static inline void fdstat_enter(FD_t fd, int opx)
+{
+    if (fd->stats == NULL) return;
+    fd->stats->ops[opx].count++;
+    gettimeofday(&fd->stats->begin, NULL);
+}
+
+static inline time_t tvsub(struct timeval *etv, struct timeval *btv) {
+    time_t secs, usecs;
+    if (!(etv && btv)) return 0;
+    secs = etv->tv_sec - btv->tv_sec;
+    usecs = etv->tv_usec - btv->tv_usec;
+    while (usecs < 0) {
+       secs++;
+       usecs += 1000000;
+    }
+    return ((secs * 1000) + (usecs/1000));
+}
+
+static inline void fdstat_exit(FD_t fd, int opx, ssize_t rc)
+{
+    struct timeval end;
+    if (rc == -1) fd->syserrno = errno;
+    if (fd->stats == NULL) return;
+    gettimeofday(&end, NULL);
+    if (rc >= 0) {
+       switch(opx) {
+       case FDSTAT_SEEK:
+           fd->stats->ops[opx].bytes = rc;
+           break;
+       default:
+           fd->stats->ops[opx].bytes += rc;
+           if (fd->bytesRemain > 0) fd->bytesRemain -= rc;
+           break;
+       }
+    }
+    fd->stats->ops[opx].msecs += tvsub(&end, &fd->stats->begin);
+    fd->stats->begin = end;    /* structure assignment */
+}
+
+static void fdstat_print(FD_t fd, const char * msg, FILE * fp) {
+    int opx;
+    if (fd->stats == NULL) return;
+    for (opx = 0; opx < 4; opx++) {
+       OPSTAT_t *ops = &fd->stats->ops[opx];
+       if (ops->count <= 0) continue;
+       switch (opx) {
+       case FDSTAT_READ:
+           if (msg) fprintf(fp, "%s:", msg);
+           fprintf(fp, "%8d reads, %8ld total bytes in %d.%03d secs\n",
+               ops->count, (long)ops->bytes,
+               (int)(ops->msecs/1000), (int)(ops->msecs%1000));
+           break;
+       case FDSTAT_WRITE:
+           if (msg) fprintf(fp, "%s:", msg);
+           fprintf(fp, "%8d writes, %8ld total bytes in %d.%03d secs\n",
+               ops->count, (long)ops->bytes,
+               (int)(ops->msecs/1000), (int)(ops->msecs%1000));
+           break;
+       case FDSTAT_SEEK:
+           break;
+       case FDSTAT_CLOSE:
+           break;
+       }
+    }
+}
+
+/* =============================================================== */
+off_t fdSize(FD_t fd) {
+    struct stat sb;
+    off_t rc = -1; 
+
+#ifdef NOISY
+DBGIO(0, (stderr, "==>\tfdSize(%p) rc %ld\n", fd, (long)rc));
+#endif
+    FDSANE(fd);
+    if (fd->contentLength >= 0)
+       rc = fd->contentLength;
+    else switch (fd->urlType) {
+    case URL_IS_PATH:
+    case URL_IS_UNKNOWN:
+       if (fstat(Fileno(fd), &sb) == 0)
+           rc = sb.st_size;
+       /*@fallthrough@*/
+    case URL_IS_FTP:
+    case URL_IS_HTTP:
+    case URL_IS_DASH:
+       break;
+    }
+    return rc;
+}
+
+void fdSetSyserrno(FD_t fd, int syserrno, const void * errcookie) {
+    FDSANE(fd);
+    fd->syserrno = syserrno;
+    fd->errcookie = errcookie;
+}
+
+int fdGetRdTimeoutSecs(FD_t fd) {
+#ifdef NOISY
+DBGIO(0, (stderr, "==>\tfdGetRdTimeoutSecs(%p) timeout %d\n", fd, FDTO(fd)));
+#endif
+    FDSANE(fd);
+    return fd->rd_timeoutsecs;
+}
+
+#ifdef DYING
+int fdGetFtpFileDoneNeeded(FD_t fd) {
+    FDSANE(fd);
+    return fd->ftpFileDoneNeeded;
+}
+
+void fdSetFtpFileDoneNeeded(FD_t fd, int ftpFileDoneNeeded) {
+    FDSANE(fd);
+    fd->ftpFileDoneNeeded = ftpFileDoneNeeded;
+}
+#endif
+
+long int fdGetCpioPos(FD_t fd) {
+    FDSANE(fd);
+    return fd->fd_cpioPos;
+}
+
+void fdSetCpioPos(FD_t fd, long int cpioPos) {
+    FDSANE(fd);
+    fd->fd_cpioPos = cpioPos;
+}
+
+FD_t fdDup(int fdno) {
+    FD_t fd;
+    int nfdno;
+
+    if ((nfdno = dup(fdno)) < 0)
+       return NULL;
+    fd = fdNew("open (fdDup)");
+    fdSetFdno(fd, nfdno);
+DBGIO(fd, (stderr, "==> fdDup(%d) fd %p %s\n", fdno, fd, fdbg(fd)));
+    return fd;
+}
+
+static inline FD_t c2f(void * cookie) {
+       FD_t fd = (FD_t) cookie;
+       FDSANE(fd);
+       return fd;
+}
+
+#ifdef USE_COOKIE_SEEK_POINTER
+static inline int fdSeekNot(void * cookie,  /*@unused@*/ _IO_off64_t *pos,  /*@unused@*/ int whence) {
+#else
+static inline int fdSeekNot(void * cookie,  /*@unused@*/ off_t pos,  /*@unused@*/ int whence) {
+#endif
+    FD_t fd = c2f(cookie);
+    FDSANE(fd);                /* XXX keep gcc quiet */
+    return -2;
+}
+
+#ifdef UNUSED
+FILE *fdFdopen(void * cookie, const char *fmode) {
+    FD_t fd = c2f(cookie);
+    int fdno;
+    FILE * fp;
+
+    if (fmode == NULL) return NULL;
+    fdno = fdFileno(fd);
+    if (fdno < 0) return NULL;
+    fp = fdopen(fdno, fmode);
+DBGIO(fd, (stderr, "==> fdFdopen(%p,\"%s\") fdno %d -> fp %p fdno %d\n", cookie, fmode, fdno, fp, fileno(fp)));
+    fd = fdFree(fd, "open (fdFdopen)");
+    return fp;
+}
+#endif
+
+#undef fdRead
+#undef fdWrite
+#undef fdSeek
+#undef fdClose
+#if 0
+#undef fdLink
+#undef fdFree
+#undef fdNew
+#endif
+#undef fdFileno
+#undef fdOpen
+
+/* =============================================================== */
+static inline FD_t XfdLink(void * cookie, const char *msg, const char *file, unsigned line) {
+    FD_t fd;
+if (cookie == NULL)
+DBGREFS(0, (stderr, "--> fd  %p ++ %d %s at %s:%u\n", cookie, FDNREFS(cookie)+1, msg, file, line));
+    fd = c2f(cookie);
+    if (fd) {
+       fd->nrefs++;
+DBGREFS(fd, (stderr, "--> fd  %p ++ %d %s at %s:%u %s\n", fd, fd->nrefs, msg, file, line, fdbg(fd)));
+    }
+    return fd;
+}
+
+static inline /*@null@*/ FD_t XfdFree( /*@killref@*/ FD_t fd, const char *msg, const char *file, unsigned line) {
+if (fd == NULL)
+DBGREFS(0, (stderr, "--> fd  %p -- %d %s at %s:%u\n", fd, FDNREFS(fd), msg, file, line));
+    FDSANE(fd);
+    if (fd) {
+DBGREFS(fd, (stderr, "--> fd  %p -- %d %s at %s:%u %s\n", fd, fd->nrefs, msg, file, line, fdbg(fd)));
+       if (--fd->nrefs > 0)
+           /*@-refcounttrans@*/ return fd; /*@=refcounttrans@*/
+       if (fd->stats) free(fd->stats);
+       /*@-refcounttrans@*/ free(fd); /*@=refcounttrans@*/
+    }
+    return NULL;
+}
+
+static inline /*@null@*/ FD_t XfdNew(const char *msg, const char *file, unsigned line) {
+    FD_t fd = (FD_t) xmalloc(sizeof(struct _FD_s));
+    if (fd == NULL)
+       return NULL;
+    fd->nrefs = 0;
+    fd->flags = 0;
+    fd->magic = FDMAGIC;
+    fd->urlType = URL_IS_UNKNOWN;
+
+    fd->nfps = 0;
+    memset(fd->fps, 0, sizeof(fd->fps));
+
+    fd->fps[0].io = fdio;
+    fd->fps[0].fp = NULL;
+    fd->fps[0].fdno = -1;
+
+    fd->url = NULL;
+    fd->rd_timeoutsecs = 1;    /* XXX default value used to be -1 */
+    fd->contentLength = fd->bytesRemain = -1;
+    fd->wr_chunked = 0;
+    fd->syserrno = 0;
+    fd->errcookie = NULL;
+    fd->stats = calloc(1, sizeof(FDSTAT_t));
+    gettimeofday(&fd->stats->create, NULL);
+    fd->stats->begin = fd->stats->create;      /* structure assignment */
+
+    fd->ftpFileDoneNeeded = 0;
+    fd->firstFree = 0;
+    fd->fileSize = 0;
+    fd->fd_cpioPos = 0;
+
+    return XfdLink(fd, msg, file, line);
+}
+
+static inline int fdFileno(void * cookie) {
+    FD_t fd;
+    if (cookie == NULL) return -2;
+    fd = c2f(cookie);
+    return fd->fps[0].fdno;    /* XXX WRONG but expedient */
+}
+
+static inline ssize_t fdRead(void * cookie, /*@out@*/ char * buf, size_t count) {
+    FD_t fd = c2f(cookie);
+    ssize_t rc;
+
+    if (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);
+
+DBGIO(fd, (stderr, "==>\tfdRead(%p,%p,%ld) rc %ld %s\n", cookie, buf, (long)count, (long)rc, fdbg(fd)));
+
+    return rc;
+}
+
+static inline ssize_t fdWrite(void * cookie, const char * buf, size_t count) {
+    FD_t fd = c2f(cookie);
+    int fdno = fdFileno(fd);
+    ssize_t rc;
+
+    if (fd->bytesRemain == 0) return 0;        /* XXX simulate EOF */
+    if (fd->wr_chunked) {
+       char chunksize[20];
+       sprintf(chunksize, "%x\r\n", (unsigned)count);
+#ifdef DYING
+if (_ftp_debug)
+fprintf(stderr, "-> %s", chunksize);
+#endif
+       rc = write(fdno, chunksize, strlen(chunksize));
+       if (rc == -1)   fd->syserrno = errno;
+    }
+    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);
+
+    if (fd->wr_chunked) {
+       int ec;
+#ifdef DYING
+if (_ftp_debug)
+fprintf(stderr, "-> \r\n");
+#endif
+       ec = write(fdno, "\r\n", sizeof("\r\n")-1);
+       if (ec == -1)   fd->syserrno = errno;
+    }
+
+DBGIO(fd, (stderr, "==>\tfdWrite(%p,%p,%ld) rc %ld %s\n", cookie, buf, (long)count, (long)rc, fdbg(fd)));
+
+    return rc;
+}
+
+#ifdef USE_COOKIE_SEEK_POINTER
+static inline int fdSeek(void * cookie, _IO_off64_t *pos, int whence) {
+    _IO_off64_t p = *pos;
+#else
+static inline int fdSeek(void * cookie, off_t p, int whence) {
+#endif
+    FD_t fd = c2f(cookie);
+    off_t rc;
+
+    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, (long)rc, fdbg(fd)));
+
+    return rc;
+}
+
+static inline int fdClose( /*@only@*/ void * cookie) {
+    FD_t fd;
+    int fdno;
+    int rc;
+
+    if (cookie == NULL) return -2;
+    fd = c2f(cookie);
+    fdno = fdFileno(fd);
+
+    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, (long)rc, fdbg(fd)));
+
+    fd = fdFree(fd, "open (fdClose)");
+    return rc;
+}
+
+static inline /*@null@*/ FD_t fdOpen(const char *path, int flags, mode_t mode) {
+    FD_t fd;
+    int fdno;
+
+#ifdef DYING
+if (_rpmio_debug)
+fprintf(stderr, "*** fdOpen(%s,0x%x,0%o)\n", path, flags, (unsigned)mode);
+#endif
+    fdno = open(path, flags, mode);
+    if (fdno < 0) return NULL;
+    fd = fdNew("open (fdOpen)");
+    fdSetFdno(fd, fdno);
+    fd->flags = flags;
+DBGIO(fd, (stderr, "==>\tfdOpen(\"%s\",%x,0%o) %s\n", path, flags, (unsigned)mode, fdbg(fd)));
+    return fd;
+}
+
+static struct FDIO_s fdio_s = {
+  fdRead, fdWrite, fdSeek, fdClose, XfdLink, XfdFree, XfdNew, fdFileno,
+  fdOpen, NULL, fdGetFp, NULL, mkdir, chdir, rmdir, rename, unlink
+};
+FDIO_t fdio = /*@-compmempass@*/ &fdio_s /*@=compmempass@*/ ;
+
+int fdWritable(FD_t fd, int secs)
+{
+    int fdno;
+    fd_set wrfds;
+    struct timeval timeout, *tvp = (secs >= 0 ? &timeout : NULL);
+    int rc;
+       
+    if ((fdno = fdFileno(fd)) < 0)
+       return -1;      /* XXX W2DO? */
+       
+    FD_ZERO(&wrfds);
+    do {
+       FD_SET(fdno, &wrfds);
+
+       if (tvp) {
+           tvp->tv_sec = secs;
+           tvp->tv_usec = 0;
+       }
+       errno = 0;
+       rc = select(fdno + 1, NULL, &wrfds, NULL, tvp);
+
+if (_rpmio_debug && !(rc == 1 && errno == 0))
+fprintf(stderr, "*** fdWritable fdno %d rc %d %s\n", fdno, rc, strerror(errno));
+       if (rc < 0) {
+           switch (errno) {
+           case EINTR:
+               continue;
+               /*@notreached@*/ break;
+           default:
+               return rc;
+               /*@notreached@*/ break;
+           }
+       }
+       return rc;
+    } while (1);
+    /*@notreached@*/
+}
+
+int fdReadable(FD_t fd, int secs)
+{
+    int fdno;
+    fd_set rdfds;
+    struct timeval timeout, *tvp = (secs >= 0 ? &timeout : NULL);
+    int rc;
+
+    if ((fdno = fdFileno(fd)) < 0)
+       return -1;      /* XXX W2DO? */
+       
+    FD_ZERO(&rdfds);
+    do {
+       FD_SET(fdno, &rdfds);
+
+       if (tvp) {
+           tvp->tv_sec = secs;
+           tvp->tv_usec = 0;
+       }
+       errno = 0;
+       rc = select(fdno + 1, &rdfds, NULL, NULL, tvp);
+
+       if (rc < 0) {
+           switch (errno) {
+           case EINTR:
+               continue;
+               /*@notreached@*/ break;
+           default:
+               return rc;
+               /*@notreached@*/ break;
+           }
+       }
+       return rc;
+    } while (1);
+    /*@notreached@*/
+}
+
+static int fdFgets(FD_t fd, char * buf, size_t len)
+{
+    int fdno;
+    int secs = fd->rd_timeoutsecs;
+    size_t nb = 0;
+    int ec = 0;
+    char lastchar = '\0';
+
+    if ((fdno = fdFileno(fd)) < 0)
+       return 0;       /* XXX W2DO? */
+       
+    do {
+       int rc;
+
+       /* Is there data to read? */
+       rc = fdReadable(fd, secs);
+
+       switch (rc) {
+       case -1:        /* error */
+           ec = -1;
+           continue;
+           /*@notreached@*/ break;
+       case  0:        /* timeout */
+           ec = -1;
+           continue;
+           /*@notreached@*/ break;
+       default:        /* data to read */
+           break;
+       }
+
+       errno = 0;
+#ifdef NOISY
+       rc = fdRead(fd, buf + nb, 1);
+#else
+       rc = read(fdFileno(fd), buf + nb, 1);
+#endif
+       if (rc < 0) {
+           fd->syserrno = errno;
+           switch (errno) {
+           case EWOULDBLOCK:
+               continue;
+               /*@notreached@*/ break;
+           default:
+               break;
+           }
+if (_rpmio_debug)
+fprintf(stderr, "*** read: fd %p rc %d errno %d %s \"%s\"\n", fd, rc, errno, strerror(errno), buf);
+           ec = -1;
+           break;
+       } else if (rc == 0) {
+if (_rpmio_debug)
+fprintf(stderr, "*** read: fd %p rc %d EOF errno %d %s \"%s\"\n", fd, rc, errno, strerror(errno), buf);
+           break;
+       } else {
+           nb += rc;
+           buf[nb] = '\0';
+           lastchar = buf[nb - 1];
+       }
+    } while (ec == 0 && nb < len && lastchar != '\n');
+
+    return (ec >= 0 ? nb : ec);
+}
+
+/* =============================================================== */
+/* Support for FTP/HTTP I/O.
+ */
+const char *const ftpStrerror(int errorNumber) {
+  switch (errorNumber) {
+    case 0:
+       return _("Success");
+
+    case FTPERR_BAD_SERVER_RESPONSE:
+       return _("Bad server response");
+
+    case FTPERR_SERVER_IO_ERROR:
+       return _("Server IO error");
+
+    case FTPERR_SERVER_TIMEOUT:
+       return _("Server timeout");
+
+    case FTPERR_BAD_HOST_ADDR:
+       return _("Unable to lookup server host address");
+
+    case FTPERR_BAD_HOSTNAME:
+       return _("Unable to lookup server host name");
+
+    case FTPERR_FAILED_CONNECT:
+       return _("Failed to connect to server");
+
+    case FTPERR_FAILED_DATA_CONNECT:
+       return _("Failed to establish data connection to server");
+
+    case FTPERR_FILE_IO_ERROR:
+       return _("IO error to local file");
+
+    case FTPERR_PASSIVE_ERROR:
+       return _("Error setting remote server to passive mode");
+
+    case FTPERR_FILE_NOT_FOUND:
+       return _("File not found on server");
+
+    case FTPERR_NIC_ABORT_IN_PROGRESS:
+       return _("Abort in progress");
+
+    case FTPERR_UNKNOWN:
+    default:
+       return _("Unknown or unexpected error");
+  }
+}
+
+const char *urlStrerror(const char *url)
+{
+    const char *retstr;
+    switch (urlIsURL(url)) {
+    case URL_IS_FTP:
+    case URL_IS_HTTP:
+    {  urlinfo u;
+/* XXX This only works for httpReq/ftpLogin/ftpReq failures */
+       if (urlSplit(url, &u) == 0) {
+           retstr = ftpStrerror(u->openError);
+       } else
+           retstr = "Malformed URL";
+    }  break;
+    default:
+       retstr = strerror(errno);
+       break;
+    }
+    return retstr;
+}
+
+#if !defined(USE_ALT_DNS) || !USE_ALT_DNS 
+static int mygethostbyname(const char * host, struct in_addr * address)
+{
+    struct hostent * hostinfo;
+
+    hostinfo = /*@-unrecog@*/ gethostbyname(host) /*@=unrecog@*/;
+    if (!hostinfo) return 1;
+
+    memcpy(address, hostinfo->h_addr_list[0], sizeof(*address));
+    return 0;
+}
+#endif
+
+static int getHostAddress(const char * host, struct in_addr * address)
+{
+    if (isdigit(host[0])) {
+      if (! /*@-unrecog@*/ inet_aton(host, address) /*@=unrecog@*/ ) {
+         return FTPERR_BAD_HOST_ADDR;
+      }
+    } else {
+      if (mygethostbyname(host, address)) {
+         errno = h_errno;
+         return FTPERR_BAD_HOSTNAME;
+      }
+    }
+    
+    return 0;
+}
+
+static int tcpConnect(FD_t ctrl, const char *host, int port)
+{
+    struct sockaddr_in sin;
+    int fdno = -1;
+    int rc;
+
+    sin.sin_family = AF_INET;
+    sin.sin_port = htons(port);
+    sin.sin_addr.s_addr = INADDR_ANY;
+    
+  do {
+    if ((rc = getHostAddress(host, &sin.sin_addr)) < 0)
+       break;
+
+    if ((fdno = socket(sin.sin_family, SOCK_STREAM, IPPROTO_IP)) < 0) {
+       rc = FTPERR_FAILED_CONNECT;
+       break;
+    }
+
+    if (connect(fdno, (struct sockaddr *) &sin, sizeof(sin))) {
+       rc = FTPERR_FAILED_CONNECT;
+       break;
+    }
+  } while (0);
+
+    if (rc < 0)
+       goto errxit;
+
+if (_ftp_debug)
+fprintf(stderr,"++ connect %s:%d on fdno %d\n",
+/*@-unrecog@*/ inet_ntoa(sin.sin_addr) /*@=unrecog@*/ ,
+ntohs(sin.sin_port), fdno);
+
+    fdSetFdno(ctrl, (fdno >= 0 ? fdno : -1));
+    return 0;
+
+errxit:
+    fdSetSyserrno(ctrl, errno, ftpStrerror(rc));
+    if (fdno >= 0)
+       close(fdno);
+    return rc;
+}
+
+static int checkResponse(void * uu, FD_t ctrl, /*@out@*/ int *ecp, /*@out@*/ char ** str)
+{
+    urlinfo u = uu;
+    char *buf;
+    size_t bufAlloced;
+    int bufLength = 0; 
+    const char *s;
+    char *se;
+    int ec = 0;
+    int moretodo = 1;
+    char errorCode[4];
+    URLSANE(u);
+    if (u->bufAlloced == 0 || u->buf == NULL) {
+       u->bufAlloced = url_iobuf_size;
+       u->buf = xcalloc(u->bufAlloced, sizeof(char));
+    }
+    buf = u->buf;
+    bufAlloced = u->bufAlloced;
+    *buf = '\0';
+
+    errorCode[0] = '\0';
+    
+    do {
+       int rc;
+
+       /*
+        * Read next line from server.
+        */
+       se = buf + bufLength;
+       *se = '\0';
+       rc = fdFgets(ctrl, se, (bufAlloced - bufLength));
+       if (rc < 0) {
+           ec = FTPERR_BAD_SERVER_RESPONSE;
+           continue;
+       } else if (rc == 0 || fdWritable(ctrl, 0) < 1)
+           moretodo = 0;
+
+       /*
+        * Process next line from server.
+        */
+       for (s = se; *s != '\0'; s = se) {
+               const char *e;
+
+               while (*se && *se != '\n') se++;
+
+               if (se > s && se[-1] == '\r')
+                  se[-1] = '\0';
+               if (*se == '\0')
+                   break;
+
+if (_ftp_debug)
+fprintf(stderr, "<- %s\n", s);
+
+               /* HTTP: header termination on empty line */
+               if (*s == '\0') {
+                   moretodo = 0;
+                   break;
+               }
+               *se++ = '\0';
+
+               /* HTTP: look for "HTTP/1.1 123 ..." */
+               if (!strncmp(s, "HTTP", sizeof("HTTP")-1)) {
+                   ctrl->contentLength = -1;
+                   if ((e = strchr(s, '.')) != NULL) {
+                       e++;
+                       u->httpVersion = *e - '0';
+                       if (u->httpVersion < 1 || u->httpVersion > 2)
+                           ctrl->persist = u->httpVersion = 0;
+                       else
+                           ctrl->persist = 1;
+                   }
+                   if ((e = strchr(s, ' ')) != NULL) {
+                       e++;
+                       if (strchr("0123456789", *e))
+                           strncpy(errorCode, e, 3);
+                       errorCode[3] = '\0';
+                   }
+                   continue;
+               }
+
+               /* HTTP: look for "token: ..." */
+               for (e = s; *e && !(*e == ' ' || *e == ':'); e++)
+                   ;
+               if (e > s && *e++ == ':') {
+                   size_t ne = (e - s);
+                   while (*e && *e == ' ') e++;
+#if 0
+                   if (!strncmp(s, "Date:", ne)) {
+                   } else
+                   if (!strncmp(s, "Server:", ne)) {
+                   } else
+                   if (!strncmp(s, "Last-Modified:", ne)) {
+                   } else
+                   if (!strncmp(s, "ETag:", ne)) {
+                   } else
+#endif
+                   if (!strncmp(s, "Accept-Ranges:", ne)) {
+                       if (!strcmp(e, "bytes"))
+                           u->httpHasRange = 1;
+                       if (!strcmp(e, "none"))
+                           u->httpHasRange = 0;
+                   } else
+                   if (!strncmp(s, "Content-Length:", ne)) {
+                       if (strchr("0123456789", *e))
+                           ctrl->contentLength = atoi(e);
+                   } else
+                   if (!strncmp(s, "Connection:", ne)) {
+                       if (!strcmp(e, "close"))
+                           ctrl->persist = 0;
+                   } else
+#if 0
+                   if (!strncmp(s, "Content-Type:", ne)) {
+                   } else
+                   if (!strncmp(s, "Transfer-Encoding:", ne)) {
+                       if (!strcmp(e, "chunked"))
+                           ctrl->wr_chunked = 1;
+                       else
+                           ctrl->wr_chunked = 0;
+                   } else
+                   if (!strncmp(s, "Allow:", ne)) {
+                   } else
+#endif
+                       ;
+                   continue;
+               }
+
+               /* HTTP: look for "<TITLE>501 ... </TITLE>" */
+               if (!strncmp(s, "<TITLE>", sizeof("<TITLE>")-1))
+                   s += sizeof("<TITLE>") - 1;
+
+               /* FTP: look for "123-" and/or "123 " */
+               if (strchr("0123456789", *s)) {
+                   if (errorCode[0]) {
+                       if (!strncmp(s, errorCode, sizeof("123")-1) && s[3] == ' ')
+                           moretodo = 0;
+                   } else {
+                       strncpy(errorCode, s, sizeof("123")-1);
+                       errorCode[3] = '\0';
+                       if (s[3] != '-')
+                           moretodo = 0;
+                   }
+               }
+       }
+
+       if (moretodo && se > s) {
+           bufLength = se - s - 1;
+           if (s != buf)
+               memmove(buf, s, bufLength);
+       } else {
+           bufLength = 0;
+       }
+    } while (moretodo && ec == 0);
+
+    if (str)   *str = buf;
+    if (ecp)   *ecp = atoi(errorCode);
+
+    return ec;
+}
+
+static int ftpCheckResponse(urlinfo u, /*@out@*/ char ** str)
+{
+    int ec = 0;
+    int rc;
+
+    URLSANE(u);
+    rc = checkResponse(u, u->ctrl, &ec, str);
+
+    switch (ec) {
+    case 550:
+       return FTPERR_FILE_NOT_FOUND;
+       /*@notreached@*/ break;
+    case 552:
+       return FTPERR_NIC_ABORT_IN_PROGRESS;
+       /*@notreached@*/ break;
+    default:
+       if (ec >= 400 && ec <= 599) {
+           return FTPERR_BAD_SERVER_RESPONSE;
+       }
+       break;
+    }
+    return rc;
+}
+
+static int ftpCommand(urlinfo u, char ** str, ...)
+{
+    va_list ap;
+    int len = 0;
+    const char * s, * t;
+    char * te;
+    int rc;
+
+    URLSANE(u);
+    va_start(ap, str);
+    while ((s = va_arg(ap, const char *)) != NULL) {
+       if (len) len++;
+       len += strlen(s);
+    }
+    len += sizeof("\r\n")-1;
+    va_end(ap);
+
+    t = te = alloca(len + 1);
+
+    va_start(ap, str);
+    while ((s = va_arg(ap, const char *)) != NULL) {
+       if (te > t) *te++ = ' ';
+       te = stpcpy(te, s);
+    }
+    te = stpcpy(te, "\r\n");
+    va_end(ap);
+
+if (_ftp_debug)
+fprintf(stderr, "-> %s", t);
+    if (fdWrite(u->ctrl, t, (te-t)) != (te-t))
+       return FTPERR_SERVER_IO_ERROR;
+
+    rc = ftpCheckResponse(u, str);
+    return rc;
+}
+
+static int ftpLogin(urlinfo u)
+{
+    const char * host;
+    const char * user;
+    const char * password;
+    int port;
+    int rc;
+
+    URLSANE(u);
+    u->ctrl = fdLink(u->ctrl, "open ctrl");
+
+    if (((host = (u->proxyh ? u->proxyh : u->host)) == NULL)) {
+       rc = FTPERR_BAD_HOSTNAME;
+       goto errxit;
+    }
+
+    if ((port = (u->proxyp > 0 ? u->proxyp : u->port)) < 0) port = IPPORT_FTP;
+
+    if ((user = (u->proxyu ? u->proxyu : u->user)) == NULL)
+       user = "anonymous";
+
+    if ((password = u->password) == NULL) {
+       if (getuid()) {
+           struct passwd * pw = getpwuid(getuid());
+           char *myp = alloca(strlen(pw->pw_name) + sizeof("@"));
+           strcpy(myp, pw->pw_name);
+           strcat(myp, "@");
+           password = myp;
+       } else {
+           password = "root@";
+       }
+    }
+
+    if (fdFileno(u->ctrl) >= 0 && fdWritable(u->ctrl, 0) < 1)
+       fdClose(u->ctrl);
+
+    if (fdFileno(u->ctrl) < 0) {
+       rc = tcpConnect(u->ctrl, host, port);
+       if (rc < 0)
+           goto errxit2;
+    }
+
+    if ((rc = ftpCheckResponse(u, NULL)))
+       goto errxit;
+
+    if ((rc = ftpCommand(u, NULL, "USER", user, NULL)))
+       goto errxit;
+
+    if ((rc = ftpCommand(u, NULL, "PASS", password, NULL)))
+       goto errxit;
+
+    if ((rc = ftpCommand(u, NULL, "TYPE", "I", NULL)))
+       goto errxit;
+
+    return 0;
+
+errxit:
+    fdSetSyserrno(u->ctrl, errno, ftpStrerror(rc));
+errxit2:
+    if (fdFileno(u->ctrl) >= 0)
+       fdClose(u->ctrl);
+    return rc;
+}
+
+static int ftpReq(FD_t data, const char * ftpCmd, const char * ftpArg)
+{
+    urlinfo u = data->url;
+    struct sockaddr_in dataAddress;
+    char * cmd;
+    int cmdlen;
+    char * passReply;
+    char * chptr;
+    int rc;
+
+    URLSANE(u);
+    if (ftpCmd == NULL)
+       return FTPERR_UNKNOWN;  /* XXX W2DO? */
+
+    cmdlen = strlen(ftpCmd) + (ftpArg ? 1+strlen(ftpArg) : 0) + sizeof("\r\n");
+    chptr = cmd = alloca(cmdlen);
+    chptr = stpcpy(chptr, ftpCmd);
+    if (ftpArg) {
+       *chptr++ = ' ';
+       chptr = stpcpy(chptr, ftpArg);
+    }
+    chptr = stpcpy(chptr, "\r\n");
+    cmdlen = chptr - cmd;
+
+/*
+ * Get the ftp version of the Content-Length.
+ */
+    if (!strncmp(cmd, "RETR", 4)) {
+       unsigned cl;
+
+       passReply = NULL;
+       rc = ftpCommand(u, &passReply, "SIZE", ftpArg, NULL);
+       if (rc)
+           goto errxit;
+       if (sscanf(passReply, "%d %u", &rc, &cl) != 2) {
+           rc = FTPERR_BAD_SERVER_RESPONSE;
+           goto errxit;
+       }
+       rc = 0;
+       data->contentLength = cl;
+    }
+
+    passReply = NULL;
+    rc = ftpCommand(u, &passReply, "PASV", NULL);
+    if (rc) {
+       rc = FTPERR_PASSIVE_ERROR;
+       goto errxit;
+    }
+
+    chptr = passReply;
+    while (*chptr && *chptr != '(') chptr++;
+    if (*chptr != '(') return FTPERR_PASSIVE_ERROR; 
+    chptr++;
+    passReply = chptr;
+    while (*chptr && *chptr != ')') chptr++;
+    if (*chptr != ')') return FTPERR_PASSIVE_ERROR;
+    *chptr-- = '\0';
+
+    while (*chptr && *chptr != ',') chptr--;
+    if (*chptr != ',') return FTPERR_PASSIVE_ERROR;
+    chptr--;
+    while (*chptr && *chptr != ',') chptr--;
+    if (*chptr != ',') return FTPERR_PASSIVE_ERROR;
+    *chptr++ = '\0';
+    
+    /* now passReply points to the IP portion, and chptr points to the
+       port number portion */
+
+    {  int i, j;
+       dataAddress.sin_family = AF_INET;
+       if (sscanf(chptr, "%d,%d", &i, &j) != 2) {
+           rc = FTPERR_PASSIVE_ERROR;
+           goto errxit;
+       }
+       dataAddress.sin_port = htons((((unsigned)i) << 8) + j);
+    }
+
+    chptr = passReply;
+    while (*chptr++) {
+       if (*chptr == ',') *chptr = '.';
+    }
+
+    if (!inet_aton(passReply, &dataAddress.sin_addr)) {
+       rc = FTPERR_PASSIVE_ERROR;
+       goto errxit;
+    }
+
+    rc = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
+    fdSetFdno(data, (rc >= 0 ? rc : -1));
+    if (rc < 0) {
+       rc = FTPERR_FAILED_CONNECT;
+       goto errxit;
+    }
+    data = fdLink(data, "open data (ftpReq)");
+
+    /* XXX setsockopt SO_LINGER */
+    /* XXX setsockopt SO_KEEPALIVE */
+    /* XXX setsockopt SO_TOS IPTOS_THROUGHPUT */
+
+    while (connect(fdFileno(data), (struct sockaddr *) &dataAddress, 
+               sizeof(dataAddress)) < 0) {
+       if (errno == EINTR)
+           continue;
+       rc = FTPERR_FAILED_DATA_CONNECT;
+       goto errxit;
+    }
+
+if (_ftp_debug)
+fprintf(stderr, "-> %s", cmd);
+    if (fdWrite(u->ctrl, cmd, cmdlen) != cmdlen) {
+       rc = FTPERR_SERVER_IO_ERROR;
+       goto errxit;
+    }
+
+    if ((rc = ftpCheckResponse(u, NULL))) {
+       goto errxit;
+    }
+
+    data->ftpFileDoneNeeded = 1;
+    u->ctrl = fdLink(u->ctrl, "grab data (ftpReq)");
+    u->ctrl = fdLink(u->ctrl, "open data (ftpReq)");
+    return 0;
+
+errxit:
+    fdSetSyserrno(u->ctrl, errno, ftpStrerror(rc));
+    if (fdFileno(data) >= 0)
+       fdClose(data);
+    return rc;
+}
+
+static int urlConnect(const char * url, /*@out@*/ urlinfo * uret)
+{
+    urlinfo u;
+    int rc = 0;
+
+    if (urlSplit(url, &u) < 0)
+       return -1;
+
+    if (u->urltype == URL_IS_FTP) {
+       FD_t fd;
+
+       if ((fd = u->ctrl) == NULL) {
+           fd = u->ctrl = fdNew("persist ctrl (urlConnect FTP)");
+           fdSetIo(u->ctrl, ufdio);
+       }
+       
+       fd->rd_timeoutsecs = ftpTimeoutSecs;
+       fd->contentLength = fd->bytesRemain = -1;
+       fd->url = NULL;         /* XXX FTP ctrl has not */
+       fd->ftpFileDoneNeeded = 0;
+       fd = fdLink(fd, "grab ctrl (urlConnect FTP)");
+
+       if (fdFileno(u->ctrl) < 0) {
+           rpmMessage(RPMMESS_DEBUG, _("logging into %s as %s, pw %s\n"),
+                       u->host,
+                       u->user ? u->user : "ftp",
+                       u->password ? u->password : "(username)");
+
+           if ((rc = ftpLogin(u)) < 0) {       /* XXX save ftpLogin error */
+               u->ctrl = fdFree(fd, "grab ctrl (urlConnect FTP)");
+               u->openError = rc;
+           }
+       }
+    }
+
+    if (uret != NULL)
+       *uret = urlLink(u, "urlConnect");
+    u = urlFree(u, "urlSplit (urlConnect)");   
+
+    return rc;
+}
+
+/*@null@*/ static rpmCallbackFunction  urlNotify = NULL;
+/*@null@*/ static void *       urlNotifyData = NULL;
+static int                     urlNotifyCount = -1;
+
+void urlSetCallback(rpmCallbackFunction notify, void *notifyData, int notifyCount) {
+    urlNotify = notify;
+    urlNotifyData = notifyData;
+    urlNotifyCount = (notifyCount >= 0) ? notifyCount : 4096;
+}
+
+int ufdCopy(FD_t sfd, FD_t tfd)
+{
+    char buf[BUFSIZ];
+    int itemsRead;
+    int itemsCopied = 0;
+    int rc = 0;
+    int notifier = -1;
+
+    if (urlNotify) {
+       (void)(*urlNotify) (NULL, RPMCALLBACK_INST_OPEN_FILE,
+               0, 0, NULL, urlNotifyData);
+    }
+    
+    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 = FTPERR_FILE_IO_ERROR;
+           break;
+       }
+
+       itemsCopied += itemsRead;
+       if (urlNotify && urlNotifyCount > 0) {
+           int n = itemsCopied/urlNotifyCount;
+           if (n != notifier) {
+               (void)(*urlNotify) (NULL, RPMCALLBACK_INST_PROGRESS,
+                       itemsCopied, 0, NULL, urlNotifyData);
+               notifier = n;
+           }
+       }
+    }
+
+    DBGIO(sfd, (stderr, "++ copied %d bytes: %s\n", itemsCopied,
+       ftpStrerror(rc)));
+
+    if (urlNotify) {
+       (void)(*urlNotify) (NULL, RPMCALLBACK_INST_OPEN_FILE,
+               itemsCopied, itemsCopied, NULL, urlNotifyData);
+    }
+    
+    return rc;
+}
+
+int ufdGetFile(FD_t sfd, FD_t tfd)
+{
+    int rc;
+
+    FDSANE(sfd);
+    FDSANE(tfd);
+    rc = ufdCopy(sfd, tfd);
+    Fclose(sfd);
+    if (rc > 0)                /* XXX ufdCopy now returns no. bytes copied */
+       rc = 0;
+    return rc;
+}
+
+static int ftpCmd(const char * cmd, const char * url, const char * arg2) {
+    urlinfo u;
+    int rc;
+    const char * path;
+
+    if (urlConnect(url, &u) < 0)
+       return -1;
+
+    (void) urlPath(url, &path);
+
+    rc = ftpCommand(u, NULL, cmd, path, arg2, NULL);
+    u->ctrl = fdFree(u->ctrl, "grab ctrl (ftpCmd)");
+#ifdef DYING
+if (_rpmio_debug)
+fprintf(stderr, "*** ftpCmd %s %s %s rc %d\n", cmd, path, arg2, rc);
+#endif
+    return rc;
+}
+
+static int ftpMkdir(const char * path, /*@unused@*/ mode_t mode) {
+    int rc;
+    if ((rc = ftpCmd("MKD", path, NULL)) != 0)
+       return rc;
+#if NOTYET
+    {  char buf[20];
+       sprintf(buf, " 0%o", mode);
+       (void) ftpCmd("SITE CHMOD", path, buf);
+    }
+#endif
+    return rc;
+}
+
+static int ftpChdir(const char * path) {
+    return ftpCmd("CWD", path, NULL);
+}
+
+static int ftpRmdir(const char * path) {
+    return ftpCmd("RMD", path, NULL);
+}
+
+static int ftpRename(const char * oldpath, const char * newpath) {
+    int rc;
+    if ((rc = ftpCmd("RNFR", oldpath, NULL)) != 0)
+       return rc;
+    return ftpCmd("RNTO", newpath, NULL);
+}
+
+static int ftpUnlink(const char * path) {
+    return ftpCmd("DELE", path, NULL);
+}
+
+/* XXX these aren't worth the pain of including correctly */
+#if !defined(IAC)
+#define        IAC     255             /* interpret as command: */
+#endif
+#if !defined(IP)
+#define        IP      244             /* interrupt process--permanently */
+#endif
+#if !defined(DM)
+#define        DM      242             /* data mark--for connect. cleaning */
+#endif
+#if !defined(SHUT_RDWR)
+#define        SHUT_RDWR       1+1
+#endif
+
+static int ftpAbort(urlinfo u, FD_t data) {
+    static unsigned char ipbuf[3] = { IAC, IP, IAC };
+    FD_t ctrl;
+    int rc;
+    int tosecs;
+
+    URLSANE(u);
+
+    if (data != NULL) {
+       data->ftpFileDoneNeeded = 0;
+       if (fdFileno(data) >= 0)
+           u->ctrl = fdFree(u->ctrl, "open data (ftpAbort)");
+       u->ctrl = fdFree(u->ctrl, "grab data (ftpAbort)");
+    }
+    ctrl = u->ctrl;
+
+    DBGIO(0, (stderr, "-> ABOR\n"));
+
+    if (send(fdFileno(ctrl), ipbuf, sizeof(ipbuf), MSG_OOB) != sizeof(ipbuf)) {
+       fdClose(ctrl);
+       return FTPERR_SERVER_IO_ERROR;
+    }
+
+    sprintf(u->buf, "%cABOR\r\n",(char) DM);
+    if (fdWrite(ctrl, u->buf, 7) != 7) {
+       fdClose(ctrl);
+       return FTPERR_SERVER_IO_ERROR;
+    }
+
+    if (data && fdFileno(data) >= 0) {
+       /* XXX shorten data drain time wait */
+       tosecs = data->rd_timeoutsecs;
+       data->rd_timeoutsecs = 10;
+       if (fdReadable(data, data->rd_timeoutsecs) > 0) {
+           while (timedRead(data, u->buf, u->bufAlloced) > 0)
+               ;
+       }
+       data->rd_timeoutsecs = tosecs;
+       /* XXX ftp abort needs to close the data channel to receive status */
+       shutdown(fdFileno(data), SHUT_RDWR);
+       close(fdFileno(data));
+       data->fps[0].fdno = -1; /* XXX WRONG but expedient */
+    }
+
+    /* XXX shorten ctrl drain time wait */
+    tosecs = u->ctrl->rd_timeoutsecs;
+    u->ctrl->rd_timeoutsecs = 10;
+    if ((rc = ftpCheckResponse(u, NULL)) == FTPERR_NIC_ABORT_IN_PROGRESS) {
+       rc = ftpCheckResponse(u, NULL);
+    }
+    rc = ftpCheckResponse(u, NULL);
+    u->ctrl->rd_timeoutsecs = tosecs;
+
+    return rc;
+}
+
+static int ftpFileDone(urlinfo u, FD_t data)
+{
+    int rc = 0;
+
+    URLSANE(u);
+    assert(data->ftpFileDoneNeeded);
+
+    if (data->ftpFileDoneNeeded) {
+       data->ftpFileDoneNeeded = 0;
+       u->ctrl = fdFree(u->ctrl, "open data (ftpFileDone)");
+       u->ctrl = fdFree(u->ctrl, "grab data (ftpFileDone)");
+       rc = ftpCheckResponse(u, NULL);
+    }
+    return rc;
+}
+
+static int httpResp(urlinfo u, FD_t ctrl, /*@out@*/ char ** str)
+{
+    int ec = 0;
+    int rc;
+
+    URLSANE(u);
+    rc = checkResponse(u, ctrl, &ec, str);
+
+if (_ftp_debug && !(rc == 0 && ec == 200))
+fprintf(stderr, "*** httpResp: rc %d ec %d\n", rc, ec);
+
+    switch (ec) {
+    case 200:
+       break;
+    default:
+       rc = FTPERR_FILE_NOT_FOUND;
+       break;
+    }
+
+    return rc;
+}
+
+static int httpReq(FD_t ctrl, const char * httpCmd, const char * httpArg)
+{
+    urlinfo u = ctrl->url;
+    const char * host;
+    const char * path;
+    int port;
+    int rc;
+    char * req;
+    size_t len;
+    int retrying = 0;
+
+    URLSANE(u);
+    assert(ctrl != NULL);
+
+    if (((host = (u->proxyh ? u->proxyh : u->host)) == NULL))
+       return FTPERR_BAD_HOSTNAME;
+
+    if ((port = (u->proxyp > 0 ? u->proxyp : u->port)) < 0) port = 80;
+    path = (u->proxyh || u->proxyp > 0) ? u->url : httpArg;
+
+reopen:
+    if (fdFileno(ctrl) >= 0 && (rc = fdWritable(ctrl, 0)) < 1) {
+#ifdef DYING
+if (_ftp_debug)
+fprintf(stderr, "*** httpReq closing ctrl fdno %d rc %d\n", fdFileno(ctrl), rc);
+#endif
+       fdClose(ctrl);
+    }
+
+    if (fdFileno(ctrl) < 0) {
+       rc = tcpConnect(ctrl, host, port);
+       if (rc < 0)
+           goto errxit2;
+       ctrl = fdLink(ctrl, "open ctrl (httpReq)");
+    }
+
+    len = sizeof("\
+req x HTTP/1.0\r\n\
+User-Agent: rpm/3.0.4\r\n\
+Host: y:z\r\n\
+Accept: text/plain\r\n\
+Transfer-Encoding: chunked\r\n\
+\r\n\
+") + strlen(httpCmd) + strlen(path) + sizeof(VERSION) + strlen(host) + 20;
+
+    req = alloca(len);
+    *req = '\0';
+
+  if (!strcmp(httpCmd, "PUT")) {
+    sprintf(req, "\
+%s %s HTTP/1.%d\r\n\
+User-Agent: rpm/%s\r\n\
+Host: %s:%d\r\n\
+Accept: text/plain\r\n\
+Transfer-Encoding: chunked\r\n\
+\r\n\
+",     httpCmd, path, (u->httpVersion ? 1 : 0), VERSION, host, port);
+} else {
+    sprintf(req, "\
+%s %s HTTP/1.%d\r\n\
+User-Agent: rpm/%s\r\n\
+Host: %s:%d\r\n\
+Accept: text/plain\r\n\
+\r\n\
+",     httpCmd, path, (u->httpVersion ? 1 : 0), VERSION, host, port);
+}
+
+if (_ftp_debug)
+fprintf(stderr, "-> %s", req);
+
+    len = strlen(req);
+    if (fdWrite(ctrl, req, len) != len) {
+       rc = FTPERR_SERVER_IO_ERROR;
+       goto errxit;
+    }
+
+    if (!strcmp(httpCmd, "PUT")) {
+       ctrl->wr_chunked = 1;
+    } else {
+
+       rc = httpResp(u, ctrl, NULL);
+
+       if (rc) {
+           if (!retrying) {    /* not HTTP_OK */
+#ifdef DYING
+if (_ftp_debug)
+fprintf(stderr, "*** httpReq ctrl %p reopening ...\n", ctrl);
+#endif
+               retrying = 1;
+               fdClose(ctrl);
+               goto reopen;
+           }
+           goto errxit;
+       }
+    }
+
+    ctrl = fdLink(ctrl, "open data (httpReq)");
+    return 0;
+
+errxit:
+    fdSetSyserrno(ctrl, errno, ftpStrerror(rc));
+errxit2:
+    if (fdFileno(ctrl) >= 0)
+       fdClose(ctrl);
+    return rc;
+}
+
+/* XXX DYING: unused */
+void * ufdGetUrlinfo(FD_t fd) {
+    FDSANE(fd);
+    if (fd->url == NULL)
+       return NULL;
+    return urlLink(fd->url, "ufdGetUrlinfo");
+}
+
+/* =============================================================== */
+static ssize_t ufdRead(void * cookie, /*@out@*/ char * buf, size_t count) {
+    FD_t fd = c2f(cookie);
+    int bytesRead;
+    int total;
+
+    /* XXX preserve timedRead() behavior */
+    if (fdGetIo(fd) == fdio) {
+       struct stat sb;
+       int fdno = fdFileno(fd);
+       fstat(fdno, &sb);
+       if (S_ISREG(sb.st_mode))
+           return fdRead(fd, buf, count);
+    }
+
+    UFDONLY(fd);
+    assert(fd->rd_timeoutsecs >= 0);
+
+    for (total = 0; total < count; total += bytesRead) {
+
+       int rc;
+
+       bytesRead = 0;
+
+       /* Is there data to read? */
+       if (fd->bytesRemain == 0) return total; /* XXX simulate EOF */
+       rc = fdReadable(fd, fd->rd_timeoutsecs);
+
+       switch (rc) {
+       case -1:        /* error */
+       case  0:        /* timeout */
+           return total;
+           /*@notreached@*/ break;
+       default:        /* data to read */
+           break;
+       }
+
+       rc = fdRead(fd, buf + total, count - total);
+
+       if (rc < 0) {
+           switch (errno) {
+           case EWOULDBLOCK:
+               continue;
+               /*@notreached@*/ break;
+           default:
+               break;
+           }
+if (_rpmio_debug)
+fprintf(stderr, "*** read: rc %d errno %d %s \"%s\"\n", rc, errno, strerror(errno), buf);
+           return rc;
+           /*@notreached@*/ break;
+       } else if (rc == 0) {
+           return total;
+           /*@notreached@*/ break;
+       }
+       bytesRead = rc;
+    }
+
+    return count;
+}
+
+static ssize_t ufdWrite(void * cookie, const char * buf, size_t count)
+{
+    FD_t fd = c2f(cookie);
+    int bytesWritten;
+    int total = 0;
+
+#ifdef NOTYET
+    if (fdGetIo(fd) == fdio) {
+       struct stat sb;
+       fstat(fdGetFdno(fd), &sb);
+       if (S_ISREG(sb.st_mode))
+           return fdWrite(fd, buf, count);
+    }
+#endif
+
+    UFDONLY(fd);
+
+    for (total = 0; total < count; total += bytesWritten) {
+
+       int rc;
+
+       bytesWritten = 0;
+
+       /* Is there room to write data? */
+       if (fd->bytesRemain == 0) {
+fprintf(stderr, "*** ufdWrite fd %p WRITE PAST END OF CONTENT\n", fd);
+           return total;       /* XXX simulate EOF */
+       }
+       rc = fdWritable(fd, 2);         /* XXX configurable? */
+
+       switch (rc) {
+       case -1:        /* error */
+       case  0:        /* timeout */
+           return total;
+           /*@notreached@*/ break;
+       default:        /* data to write */
+           break;
+       }
+
+       rc = fdWrite(fd, buf + total, count - total);
+
+       if (rc < 0) {
+           switch (errno) {
+           case EWOULDBLOCK:
+               continue;
+               /*@notreached@*/ break;
+           default:
+               break;
+           }
+if (_rpmio_debug)
+fprintf(stderr, "*** write: rc %d errno %d %s \"%s\"\n", rc, errno, strerror(errno), buf);
+           return rc;
+           /*@notreached@*/ break;
+       } else if (rc == 0) {
+           return total;
+           /*@notreached@*/ break;
+       }
+       bytesWritten = rc;
+    }
+
+    return count;
+}
+
+#ifdef USE_COOKIE_SEEK_POINTER
+static inline int ufdSeek(void * cookie, _IO_off64_t *pos, int whence) {
+#else
+static inline int ufdSeek(void * cookie, off_t pos, int whence) {
+#endif
+    FD_t fd = c2f(cookie);
+
+    switch (fd->urlType) {
+    case URL_IS_UNKNOWN:
+    case URL_IS_PATH:
+       break;
+    case URL_IS_DASH:
+    case URL_IS_FTP:
+    case URL_IS_HTTP:
+    default:
+        return -2;
+       /*@notreached@*/ break;
+    }
+    return fdSeek(cookie, pos, whence);
+}
+
+static int ufdClose( /*@only@*/ void * cookie)
+{
+    FD_t fd = c2f(cookie);
+
+    UFDONLY(fd);
+
+    if (fd->url) {
+       urlinfo u = fd->url;
+
+       if (fd == u->data)
+               fd = u->data = fdFree(fd, "grab data (ufdClose persist)");
+       else
+               fd = fdFree(fd, "grab data (ufdClose)");
+       (void) urlFree(fd->url, "url (ufdClose)");
+       fd->url = NULL;
+       u->ctrl = fdFree(u->ctrl, "grab ctrl (ufdClose)");
+
+       if (u->urltype == URL_IS_FTP) {
+
+           /* XXX if not using libio, lose the fp from fpio */
+           {   FILE * fp = fdGetFILE(fd);
+               if (noLibio && fp)
+                   fdSetFp(fd, NULL);
+           }
+
+           /*
+            * Normal FTP has 4 refs on the data fd:
+            *  "persist data (ufdOpen FTP)"            rpmio.c:888
+            *  "grab data (ufdOpen FTP)"               rpmio.c:892
+            *  "open data (ftpReq)"                    ftp.c:633
+            *  "fopencookie"                           rpmio.c:1507
+            */
+
+           /*
+            * Normal FTP has 5 refs on the ctrl fd:
+            *  "persist ctrl"                          url.c:176
+            *  "grab ctrl (urlConnect FTP)"            rpmio.c:404
+            *  "open ctrl"                             ftp.c:504
+            *  "grab data (ftpReq)"                    ftp.c:661
+            *  "open data (ftpReq)"                    ftp.c:662
+            */
+           if (fd->bytesRemain > 0) {
+               if (fd->ftpFileDoneNeeded) {
+                   if (fdReadable(u->ctrl, 0) > 0)
+                       ftpFileDone(u, fd);
+                   else
+                       ftpAbort(u, fd);
+               }
+           } else {
+               int rc;
+               /* XXX STOR et al require close before ftpFileDone */
+               rc = fdClose(fd);
+#if 0  /* XXX error exit from ufdOpen does not have this set */
+               assert(fd->ftpFileDoneNeeded != 0);
+#endif
+               if (fd->ftpFileDoneNeeded)
+                   ftpFileDone(u, fd);
+               return rc;
+           }
+       }
+
+       if (!strcmp(u->service, "http")) {
+           if (fd->wr_chunked) {
+               int rc;
+           /* XXX HTTP PUT requires terminating 0 length chunk. */
+               fdWrite(fd, NULL, 0);
+               fd->wr_chunked = 0;
+           /* XXX HTTP PUT requires terminating entity-header. */
+if (_ftp_debug)
+fprintf(stderr, "-> \r\n");
+               (void) fdWrite(fd, "\r\n", sizeof("\r\n")-1);
+               rc = httpResp(u, fd, NULL);
+           }
+
+           if (fd == u->ctrl)
+               fd = u->ctrl = fdFree(fd, "open data (ufdClose HTTP persist ctrl)");
+           else if (fd == u->data)
+               fd = u->data = fdFree(fd, "open data (ufdClose HTTP persist data)");
+           else
+               fd = fdFree(fd, "open data (ufdClose HTTP)");
+
+           /*
+            * HTTP has 4 (or 5 if persistent malloc) refs on the fd:
+            *  "persist ctrl"                          url.c:177
+            *  "grab ctrl (ufdOpen HTTP)"              rpmio.c:924
+            *  "grab data (ufdOpen HTTP)"              rpmio.c:928
+            *  "open ctrl (httpReq)"                   ftp.c:382
+            *  "open data (httpReq)"                   ftp.c:435
+            */
+
+           /* XXX if not using libio, lose the fp from fpio */
+           {   FILE * fp = fdGetFILE(fd);
+               if (noLibio && fp)
+                   fdSetFp(fd, NULL);
+           }
+
+           if (fd->persist && u->httpVersion &&
+               (fd == u->ctrl || fd == u->data) && fd->bytesRemain == 0) {
+               fd->contentLength = fd->bytesRemain = -1;
+               return 0;
+           } else {
+               fd->contentLength = fd->bytesRemain = -1;
+           }
+       }
+    }
+    return fdClose(fd);
+}
+
+static /*@null@*/ FD_t ftpOpen(const char *url, /*@unused@*/ int flags,
+               /*@unused@*/ mode_t mode, /*@out@*/ urlinfo *uret)
+{
+    urlinfo u = NULL;
+    FD_t fd = NULL;
+
+#if 0  /* XXX makeTempFile() heartburn */
+    assert(!(flags & O_RDWR));
+#endif
+    if (urlConnect(url, &u) < 0)
+       goto exit;
+
+    if (u->data == NULL)
+       u->data = fdNew("persist data (ftpOpen)");
+
+    if (u->data->url == NULL)
+       fd = fdLink(u->data, "grab data (ftpOpen persist data)");
+    else
+       fd = fdNew("grab data (ftpOpen)");
+
+    if (fd) {
+       fdSetIo(fd, ufdio);
+       fd->ftpFileDoneNeeded = 0;
+       fd->rd_timeoutsecs = ftpTimeoutSecs;
+       fd->contentLength = fd->bytesRemain = -1;
+       fd->url = urlLink(u, "url (ufdOpen FTP)");
+       fd->urlType = URL_IS_FTP;
+    }
+
+exit:
+    if (uret)
+       *uret = u;
+    return fd;
+}
+
+static /*@null@*/ FD_t httpOpen(const char *url, int flags, mode_t mode,
+               /*@out@*/ urlinfo *uret)
+{
+    urlinfo u = NULL;
+    FD_t fd = NULL;
+
+#if 0  /* XXX makeTempFile() heartburn */
+    assert(!(flags & O_RDWR));
+#endif
+    if (urlSplit(url, &u))
+       goto exit;
+
+    if (u->ctrl == NULL)
+       u->ctrl = fdNew("persist ctrl (httpOpen)");
+    if (u->ctrl->nrefs > 2 && u->data == NULL)
+       u->data = fdNew("persist data (httpOpen)");
+
+    if (u->ctrl->url == NULL)
+       fd = fdLink(u->ctrl, "grab ctrl (httpOpen persist ctrl)");
+    else if (u->data->url == NULL)
+       fd = fdLink(u->data, "grab ctrl (httpOpen persist data)");
+    else
+       fd = fdNew("grab ctrl (httpOpen)");
+
+    if (fd) {
+       fdSetIo(fd, ufdio);
+       fd->ftpFileDoneNeeded = 0;
+       fd->rd_timeoutsecs = httpTimeoutSecs;
+       fd->contentLength = fd->bytesRemain = -1;
+       fd->url = urlLink(u, "url (httpOpen)");
+       fd = fdLink(fd, "grab data (httpOpen)");
+       fd->urlType = URL_IS_HTTP;
+    }
+
+exit:
+    if (uret)
+       *uret = u;
+    return fd;
+}
+
+static /*@null@*/ FD_t ufdOpen(const char *url, int flags, mode_t mode)
+{
+    FD_t fd = NULL;
+    const char * cmd;
+    urlinfo u;
+    const char * path;
+    urltype urlType = urlPath(url, &path);
+
+if (_rpmio_debug)
+fprintf(stderr, "*** ufdOpen(%s,0x%x,0%o)\n", url, flags, (unsigned)mode);
+
+    switch (urlType) {
+    case URL_IS_FTP:
+       fd = ftpOpen(url, flags, mode, &u);
+       if (fd == NULL || u == NULL)
+           break;
+
+       /* XXX W2DO? use STOU rather than STOR to prevent clobbering */
+       cmd = ((flags & O_WRONLY) 
+               ?  ((flags & O_APPEND) ? "APPE" :
+                  ((flags & O_CREAT) ? "STOR" : "STOR"))
+               :  ((flags & O_CREAT) ? "STOR" : "RETR"));
+       u->openError = ftpReq(fd, cmd, path);
+       if (u->openError < 0) {
+           /* XXX make sure that we can exit through ufdClose */
+           fd = fdLink(fd, "error data (ufdOpen FTP)");
+       } else {
+           fd->bytesRemain = ((!strcmp(cmd, "RETR"))
+               ?  fd->contentLength : -1);
+           fd->wr_chunked = 0;
+       }
+       break;
+    case URL_IS_HTTP:
+       fd = httpOpen(url, flags, mode, &u);
+       if (fd == NULL || u == NULL)
+           break;
+
+       cmd = ((flags & O_WRONLY)
+               ?  ((flags & O_APPEND) ? "PUT" :
+                  ((flags & O_CREAT) ? "PUT" : "PUT"))
+               : "GET");
+       u->openError = httpReq(fd, cmd, path);
+       if (u->openError < 0) {
+           /* XXX make sure that we can exit through ufdClose */
+           fd = fdLink(fd, "error ctrl (ufdOpen HTTP)");
+           fd = fdLink(fd, "error data (ufdOpen HTTP)");
+       } else {
+           fd->bytesRemain = ((!strcmp(cmd, "GET"))
+               ?  fd->contentLength : -1);
+           fd->wr_chunked = ((!strcmp(cmd, "PUT"))
+               ?  fd->wr_chunked : 0);
+       }
+       break;
+    case URL_IS_DASH:
+       assert(!(flags & O_RDWR));
+       fd = fdDup( ((flags & O_WRONLY) ? STDOUT_FILENO : STDIN_FILENO) );
+       if (fd) {
+           fdSetIo(fd, ufdio);
+           fd->rd_timeoutsecs = 600;   /* XXX W2DO? 10 mins? */
+           fd->contentLength = fd->bytesRemain = -1;
+       }
+       break;
+    case URL_IS_PATH:
+    case URL_IS_UNKNOWN:
+    default:
+       fd = fdOpen(path, flags, mode);
+       if (fd) {
+           fdSetIo(fd, ufdio);
+           fd->rd_timeoutsecs = 1;
+           fd->contentLength = fd->bytesRemain = -1;
+       }
+       break;
+    }
+
+    if (fd == NULL) return NULL;
+    fd->urlType = urlType;
+    if (Fileno(fd) < 0) {
+       ufdClose(fd);
+       return NULL;
+    }
+DBGIO(fd, (stderr, "==>\tufdOpen(\"%s\",%x,0%o) %s\n", url, flags, (unsigned)mode, fdbg(fd)));
+    return fd;
+}
+
+static struct FDIO_s ufdio_s = {
+  ufdRead, ufdWrite, ufdSeek, ufdClose, XfdLink, XfdFree, XfdNew, fdFileno,
+  ufdOpen, NULL, fdGetFp, NULL,        Mkdir, Chdir, Rmdir, Rename, Unlink
+};
+FDIO_t ufdio = /*@-compmempass@*/ &ufdio_s /*@=compmempass@*/ ;
+
+/* =============================================================== */
+/* Support for first fit File Allocation I/O.
+ */
+long int fadGetFileSize(FD_t fd) {
+    FDSANE(fd);
+    return fd->fileSize;
+}
+
+void fadSetFileSize(FD_t fd, long int fileSize) {
+    FDSANE(fd);
+    fd->fileSize = fileSize;
+}
+
+unsigned int fadGetFirstFree(FD_t fd) {
+    FDSANE(fd);
+    return fd->firstFree;
+}
+
+void fadSetFirstFree(FD_t fd, unsigned int firstFree) {
+    FDSANE(fd);
+    fd->firstFree = firstFree;
+}
+
+/* =============================================================== */
+#ifdef DYING
+extern fdio_open_function_t fadOpen;
+static struct FDIO_s fadio_s = {
+  fdRead, fdWrite, fdSeek, fdClose, XfdLink, XfdFree, XfdNew, fdFileno,
+  fadOpen, NULL, fdGetFp,      NULL, NULL, NULL, NULL, NULL
+};
+FDIO_t fadio = /*@-compmempass@*/ &fadio_s /*@=compmempass@*/ ;
+#else
+extern FDIO_t fadio;
+#endif
+
+/* =============================================================== */
+/* Support for GZIP library.
+ */
+#ifdef HAVE_ZLIB_H
+
+#include <zlib.h>
+
+static inline /*@dependent@*/ /*@null@*/ void * gzdFileno(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 != gzdio)
+           continue;
+       rc = fps->fp;
+       break;
+    }
+    
+    return rc;
+}
+
+static /*@null@*/ FD_t gzdOpen(const char *path, const char *fmode) {
+    FD_t fd;
+    gzFile *gzfile;
+    if ((gzfile = gzopen(path, fmode)) == NULL)
+       return NULL;
+    fd = fdNew("open (gzdOpen)");
+    fdPop(fd); fdPush(fd, gzdio, gzfile, -1);
+    
+DBGIO(fd, (stderr, "==>\tgzdOpen(\"%s\", \"%s\") fd %p %s\n", path, fmode, fd, fdbg(fd)));
+    return fdLink(fd, "gzdOpen");
+}
+
+static /*@null@*/ FD_t gzdFdopen(void * cookie, const char *fmode) {
+    FD_t fd = c2f(cookie);
+    int fdno;
+    gzFile *gzfile;
+
+    if (fmode == NULL) return NULL;
+    fdno = fdFileno(fd);
+    fdSetFdno(fd, -1);         /* XXX skip the fdio close */
+    if (fdno < 0) return NULL;
+    gzfile = gzdopen(fdno, fmode);
+    if (gzfile == NULL) return NULL;
+
+    fdPush(fd, gzdio, gzfile, fdno);           /* Push gzdio onto stack */
+
+    return fdLink(fd, "gzdFdopen");
+}
+
+static int gzdFlush(FD_t fd) {
+    return gzflush(gzdFileno(fd), Z_SYNC_FLUSH);       /* XXX W2DO? */
+}
+
+/* =============================================================== */
+static ssize_t gzdRead(void * cookie, /*@out@*/ char * buf, size_t count) {
+    FD_t fd = c2f(cookie);
+    gzFile *gzfile;
+    ssize_t rc;
+
+    if (fd->bytesRemain == 0) return 0;        /* XXX simulate EOF */
+    gzfile = gzdFileno(fd);
+    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, (long)rc, fdbg(fd)));
+    if (rc < 0) {
+       int zerror = 0;
+       fd->errcookie = gzerror(gzfile, &zerror);
+       if (zerror == Z_ERRNO) {
+           fd->syserrno = errno;
+           fd->errcookie = strerror(fd->syserrno);
+       }
+    } else if (rc >= 0) {
+       fdstat_exit(fd, FDSTAT_READ, rc);
+    }
+    return rc;
+}
+
+static ssize_t gzdWrite(void * cookie, const char * buf, size_t count) {
+    FD_t fd = c2f(cookie);
+    gzFile *gzfile;
+    ssize_t rc;
+
+    if (fd->bytesRemain == 0) return 0;        /* XXX simulate EOF */
+    gzfile = gzdFileno(fd);
+    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, (long)rc, fdbg(fd)));
+    if (rc < 0) {
+       int zerror = 0;
+       fd->errcookie = gzerror(gzfile, &zerror);
+       if (zerror == Z_ERRNO) {
+           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 */
+#ifdef USE_COOKIE_SEEK_POINTER
+static inline int gzdSeek(void * cookie, _IO_off64_t *pos, int whence) {
+    _IO_off64_t p = *pos;
+#else
+static inline int gzdSeek(void * cookie, off_t p, int whence) {
+#endif
+    int rc;
+#if HAVE_GZSEEK
+    FD_t fd = c2f(cookie);
+    gzFile *gzfile;
+
+    assert(fd->bytesRemain == -1);     /* XXX FIXME */
+    gzfile = gzdFileno(fd);
+    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, (long)rc, fdbg(fd)));
+    if (rc < 0) {
+       int zerror = 0;
+       fd->errcookie = gzerror(gzfile, &zerror);
+       if (zerror == Z_ERRNO) {
+           fd->syserrno = errno;
+           fd->errcookie = strerror(fd->syserrno);
+       }
+    } else if (rc >= 0) {
+       fdstat_exit(fd, FDSTAT_SEEK, rc);
+    }
+#else
+    rc = -2;
+#endif
+    return rc;
+}
+
+static int gzdClose( /*@only@*/ void * cookie) {
+    FD_t fd = c2f(cookie);
+    gzFile *gzfile;
+    int rc;
+
+    gzfile = gzdFileno(fd);
+
+    if (gzfile == NULL) return -2;
+    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 = gzerror(gzfile, &rc);
+           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, (long)rc, fdbg(fd)));
+
+    if (_rpmio_debug || rpmIsDebug()) fdstat_print(fd, "GZDIO", stderr);
+    if (rc == 0)
+       fd = fdFree(fd, "open (gzdClose)");
+    return rc;
+}
+
+static struct FDIO_s gzdio_s = {
+  gzdRead, gzdWrite, gzdSeek, gzdClose, XfdLink, XfdFree, XfdNew, fdFileno,
+  NULL, gzdOpen, gzdFileno, gzdFlush,  NULL, NULL, NULL, NULL, NULL
+};
+FDIO_t gzdio = /*@-compmempass@*/ &gzdio_s /*@=compmempass@*/ ;
+
+#endif /* HAVE_ZLIB_H */
+
+/* =============================================================== */
+/* 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 inline /*@dependent@*/ /*@null@*/ void * bzdFileno(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 != bzdio)
+           continue;
+       rc = fps->fp;
+       break;
+    }
+    
+    return rc;
+}
+
+static /*@null@*/ FD_t bzdOpen(const char *path, const char *mode) {
+    FD_t fd;
+    BZFILE *bzfile;;
+    if ((bzfile = bzopen(path, mode)) == NULL)
+       return NULL;
+    fd = fdNew("open (bzdOpen)");
+    fdPop(fd); fdPush(fd, bzdio, bzfile, -1);
+    return fdLink(fd, "bzdOpen");
+}
+
+static /*@null@*/ FD_t bzdFdopen(void * cookie, const char * fmode) {
+    FD_t fd = c2f(cookie);
+    int fdno;
+    BZFILE *bzfile;
+
+    if (fmode == NULL) return NULL;
+    fdno = fdFileno(fd);
+    fdSetFdno(fd, -1);         /* XXX skip the fdio close */
+    if (fdno < 0) return NULL;
+    bzfile = bzdopen(fdno, fmode);
+    if (bzfile == NULL) return NULL;
+
+    fdPush(fd, bzdio, bzfile, fdno);           /* Push bzdio onto stack */
+
+    return fdLink(fd, "bzdFdopen");
+}
+
+static int bzdFlush(FD_t fd) {
+    return bzflush(bzdFileno(fd));
+}
+
+/* =============================================================== */
+static ssize_t bzdRead(void * cookie, /*@out@*/ char * buf, size_t count) {
+    FD_t fd = c2f(cookie);
+    BZFILE *bzfile;
+    ssize_t rc;
+
+    if (fd->bytesRemain == 0) return 0;        /* XXX simulate EOF */
+    bzfile = bzdFileno(fd);
+    fdstat_enter(fd, FDSTAT_READ);
+    rc = bzread(bzfile, buf, count);
+    if (rc == -1) {
+       int zerror = 0;
+       fd->errcookie = bzerror(bzfile, &zerror);
+    } else if (rc >= 0) {
+       fdstat_exit(fd, FDSTAT_READ, rc);
+    }
+    return rc;
+}
+
+static ssize_t bzdWrite(void * cookie, const char * buf, size_t count) {
+    FD_t fd = c2f(cookie);
+    BZFILE *bzfile;
+    ssize_t rc;
+
+    if (fd->bytesRemain == 0) return 0;        /* XXX simulate EOF */
+    bzfile = bzdFileno(fd);
+    fdstat_enter(fd, FDSTAT_WRITE);
+    rc = 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);
+    }
+    return rc;
+}
+
+#ifdef USE_COOKIE_SEEK_POINTER
+static inline int bzdSeek(void * cookie, _IO_off64_t *pos, int whence) {
+#else
+static inline int bzdSeek(void * cookie, off_t p, int whence) {
+#endif
+    FD_t fd = c2f(cookie);
+
+    BZDONLY(fd);
+    return -2;
+}
+
+static int bzdClose( /*@only@*/ void * cookie) {
+    FD_t fd = c2f(cookie);
+    BZFILE *bzfile;
+    int rc;
+
+    bzfile = bzdFileno(fd);
+
+    if (bzfile == NULL) return -2;
+    fdstat_enter(fd, FDSTAT_CLOSE);
+    bzclose(bzfile);
+    rc = 0;    /* XXX FIXME */
+
+    /* XXX TODO: preserve fd if errors */
+
+    if (fd) {
+       if (rc == -1) {
+           int zerror = 0;
+           fd->errcookie = bzerror(bzfile, &zerror);
+       } else if (rc >= 0) {
+           fdstat_exit(fd, FDSTAT_CLOSE, rc);
+       }
+    }
+
+DBGIO(fd, (stderr, "==>\tbzdClose(%p) rc %lx %s\n", cookie, (long)rc, fdbg(fd)));
+
+    if (_rpmio_debug || rpmIsDebug()) fdstat_print(fd, "BZDIO", stderr);
+    if (rc == 0)
+       fd = fdFree(fd, "open (bzdClose)");
+    return rc;
+}
+
+static struct FDIO_s bzdio_s = {
+  bzdRead, bzdWrite, bzdSeek, bzdClose, XfdLink, XfdFree, XfdNew, fdFileno,
+  NULL, bzdOpen, bzdFileno, bzdFlush,  NULL, NULL, NULL, NULL, NULL
+};
+FDIO_t bzdio = /*@-compmempass@*/ &bzdio_s /*@=compmempass@*/ ;
+
+#endif /* HAVE_BZLIB_H */
+
+/* =============================================================== */
+/*@observer@*/ static const char * getFdErrstr (FD_t fd) {
+    const char *errstr = NULL;
+
+#ifdef HAVE_ZLIB_H
+    if (fdGetIo(fd) == gzdio) {
+       errstr = fd->errcookie;
+    } else
+#endif /* HAVE_ZLIB_H */
+
+#ifdef HAVE_BZLIB_H
+    if (fdGetIo(fd) == bzdio) {
+       errstr = fd->errcookie;
+    } else
+#endif /* HAVE_BZLIB_H */
+
+    {
+       errstr = strerror(fd->syserrno);
+    }
+
+    return errstr;
+}
+
+/* =============================================================== */
+
+const char *Fstrerror(FD_t fd) {
+    if (fd == NULL)
+       return strerror(errno);
+    FDSANE(fd);
+    return getFdErrstr(fd);
+}
+
+#define        FDIOVEC(_fd, _vec)      \
+  ((fdGetIo(_fd) && fdGetIo(_fd)->_vec) ? fdGetIo(_fd)->_vec : NULL)
+
+size_t Fread(void *buf, size_t size, size_t nmemb, FD_t fd) {
+    fdio_read_function_t *_read;
+    int rc;
+
+    FDSANE(fd);
+#ifdef __LCLINT__
+    *(char *)buf = '\0';
+#endif
+DBGIO(fd, (stderr, "==> Fread(%p,%u,%u,%p) %s\n", buf, (unsigned)size, (unsigned)nmemb, fd, fdbg(fd)));
+
+    if (fdGetIo(fd) == fpio) {
+       rc = fread(buf, size, nmemb, fdGetFILE(fd));
+       return rc;
+    }
+
+    _read = FDIOVEC(fd, read);
+
+    rc = (_read ? (*_read) (fd, buf, size * nmemb) : -2);
+    return rc;
+}
+
+size_t Fwrite(const void *buf, size_t size, size_t nmemb, FD_t fd) {
+    fdio_write_function_t *_write;
+    int rc;
+
+    FDSANE(fd);
+DBGIO(fd, (stderr, "==> Fwrite(%p,%u,%u,%p) %s\n", buf, (unsigned)size, (unsigned)nmemb, fd, fdbg(fd)));
+
+    if (fdGetIo(fd) == fpio) {
+       rc = fwrite(buf, size, nmemb, fdGetFILE(fd));
+       return rc;
+    }
+
+    _write = FDIOVEC(fd, write);
+
+    rc = (_write ? _write(fd, buf, size * nmemb) : -2);
+    return rc;
+}
+
+#ifdef USE_COOKIE_SEEK_POINTER
+int Fseek(FD_t fd, _IO_off64_t offset, int whence) {
+#else 
+int Fseek(FD_t fd, off_t offset, int whence) {
+#endif
+    fdio_seek_function_t *_seek;
+    long int rc;
+
+    FDSANE(fd);
+DBGIO(fd, (stderr, "==> Fseek(%p,%ld,%d) %s\n", fd, (long)offset, whence, fdbg(fd)));
+
+    if (fdGetIo(fd) == fpio) {
+       FILE *f;
+
+       f = fdGetFILE(fd);
+       rc = fseek(f, offset, whence);
+       return rc;
+    }
+
+    _seek = FDIOVEC(fd, seek);
+
+#ifdef USE_COOKIE_SEEK_POINTER
+    rc = (_seek ? _seek(fd, &offset, whence) : -2);
+#else
+    rc = (_seek ? _seek(fd, offset, whence) : -2);
+#endif
+    return rc;
+}
+
+int Fclose(FD_t fd) {
+    int rc, ec = 0;
+
+    FDSANE(fd);
+DBGIO(fd, (stderr, "==> Fclose(%p) %s\n", fd, fdbg(fd)));
+
+    fd = fdLink(fd, "Fclose");
+    while (fd->nfps >= 0) {
+       FDSTACK_t * fps = &fd->fps[fd->nfps];
+       
+       if (fps->io == fpio) {
+           FILE *fp = fdGetFILE(fd);
+           int fpno = fileno(fp);
+
+       /* XXX persistent HTTP/1.1 returns the previously opened fp */
+           if (fd->nfps > 0 && fpno == -1 &&
+               fd->fps[fd->nfps-1].io == ufdio &&
+               fd->fps[fd->nfps-1].fp == fp &&
+               fd->fps[fd->nfps-1].fdno >= 0)
+           {
+               fflush(fp);
+               fd->nfps--;
+               rc = ufdClose(fd);
+               if (fdGetFdno(fd) >= 0)
+                   break;
+               fdSetFp(fd, NULL);
+               fd->nfps++;
+               rc = fclose(fp);
+               fdPop(fd);
+               if (noLibio)
+                   fdSetFp(fd, NULL);
+           } else {
+               rc = fclose(fp);
+               if (fpno == -1) {
+                   fd = fdFree(fd, "fopencookie (Fclose)");
+                   fdPop(fd);
+               }
+           }
+       } else {
+           fdio_close_function_t * _close = FDIOVEC(fd, close);
+           rc = _close(fd);
+       }
+       if (fd->nfps == 0)
+           break;
+       if (ec == 0 && rc)
+           ec = rc;
+       fdPop(fd);
+    }
+    fd = fdFree(fd, "Fclose");
+    return ec;
+}
+
+/*
+ * Convert stdio fmode to open(2) mode, filtering out zlib/bzlib flags.
+ *     returns stdio[0] = '\0' on error.
+ *
+ * gzopen:     [0-9] is compession level
+ * gzopen:     'f' is filtered (Z_FILTERED)
+ * gzopen:     'h' is Huffman encoding (Z_HUFFMAN_ONLY)
+ * bzopen:     [1-9] is block size (modulo 100K)
+ * bzopen:     's' is smallmode
+ * HACK:       '.' terminates, rest is type of I/O
+ */
+static inline void cvtfmode (const char *m,
+                               /*@out@*/ char *stdio, size_t nstdio,
+                               /*@out@*/ char *other, size_t nother,
+                               /*@out@*/ const char **end, /*@out@*/ int * f)
+{
+    int flags = 0;
+    char c;
+
+    switch (*m) {
+    case 'a':
+       flags |= O_WRONLY | O_CREAT | O_APPEND;
+       if (--nstdio > 0) *stdio++ = *m;
+       break;
+    case 'w':
+       flags |= O_WRONLY | O_CREAT | O_TRUNC;
+       if (--nstdio > 0) *stdio++ = *m;
+       break;
+    case 'r':
+       flags |= O_RDONLY;
+       if (--nstdio > 0) *stdio++ = *m;
+       break;
+    default:
+       *stdio = '\0';
+       return;
+       /*@notreached@*/ break;
+    }
+    m++;
+
+    while ((c = *m++) != '\0') {
+       switch (c) {
+       case '.':
+           break;
+       case '+':
+           flags &= ~(O_RDONLY|O_WRONLY);
+           flags |= O_RDWR;
+           if (--nstdio > 0) *stdio++ = c;
+           continue;
+       case 'b':
+           if (--nstdio > 0) *stdio++ = c;
+           continue;
+       case 'x':
+           flags |= O_EXCL;
+           if (--nstdio > 0) *stdio++ = c;
+           continue;
+       default:
+           if (--nother > 0) *other++ = c;
+           continue;
+       }
+       break;
+    }
+
+    *stdio = *other = '\0';
+    if (end)
+       *end = (*m ? m : NULL);
+    if (f)
+       *f = flags;
+}
+
+#if _USE_LIBIO
+#if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ == 0
+/* XXX retrofit glibc-2.1.x typedef on glibc-2.0.x systems */
+typedef _IO_cookie_io_functions_t cookie_io_functions_t;
+#endif
+#endif
+
+FD_t Fdopen(FD_t ofd, const char *fmode)
+{
+    char stdio[20], other[20], zstdio[20];
+    const char *end = NULL;
+    FDIO_t iof = NULL;
+    FD_t fd = ofd;
+
+if (_rpmio_debug)
+fprintf(stderr, "*** Fdopen(%p,%s) %s\n", fd, fmode, fdbg(fd));
+    FDSANE(fd);
+
+    if (fmode == NULL)
+       return NULL;
+
+    cvtfmode(fmode, stdio, sizeof(stdio), other, sizeof(other), &end, NULL);
+    if (stdio[0] == '\0')
+       return NULL;
+    zstdio[0] = '\0';
+    strncat(zstdio, stdio, sizeof(zstdio) - strlen(zstdio));
+    strncat(zstdio, other, sizeof(zstdio) - strlen(zstdio));
+
+    if (end == NULL && other[0] == '\0')
+       return fd;
+
+    if (end && *end) {
+       if (!strcmp(end, "fdio")) {
+           iof = fdio;
+       } else if (!strcmp(end, "gzdio")) {
+           iof = gzdio;
+           fd = gzdFdopen(fd, zstdio);
+#if HAVE_BZLIB_H
+       } else if (!strcmp(end, "bzdio")) {
+           iof = bzdio;
+           fd = bzdFdopen(fd, zstdio);
+#endif
+       } else if (!strcmp(end, "ufdio")) {
+           iof = ufdio;
+       } else if (!strcmp(end, "fadio")) {
+           iof = fadio;
+       } else if (!strcmp(end, "fpio")) {
+           iof = fpio;
+           if (noLibio) {
+               int fdno = Fileno(fd);
+               FILE * fp = fdopen(fdno, stdio);
+if (_rpmio_debug)
+fprintf(stderr, "*** Fdopen fpio fp %p\n", fp);
+               if (fp == NULL)
+                   return NULL;
+               /* XXX gzdio/bzdio use fp for private data */
+               if (fdGetFp(fd) == NULL)
+                   fdSetFp(fd, fp);
+               fdPush(fd, fpio, fp, fdno);     /* Push fpio onto stack */
+           }
+       }
+    } else if (other[0]) {
+       for (end = other; *end && strchr("0123456789fh", *end); end++)
+           ;
+       if (*end == '\0') {
+           iof = gzdio;
+           fd = gzdFdopen(fd, zstdio);
+       }
+    }
+    if (iof == NULL)
+       return fd;
+
+    if (!noLibio) {
+       FILE * fp = NULL;
+
+#if _USE_LIBIO
+       {   cookie_io_functions_t ciof;
+           ciof.read = iof->read;
+           ciof.write = iof->write;
+           ciof.seek = iof->seek;
+           ciof.close = iof->close;
+           fp = fopencookie(fd, stdio, ciof);
+DBGIO(fd, (stderr, "==> fopencookie(%p,\"%s\",*%p) returns fp %p\n", fd, stdio, iof, fp));
+       }
+#endif
+
+       if (fp) {
+           /* XXX gzdio/bzdio use fp for private data */
+           if (fdGetFp(fd) == NULL)
+               fdSetFp(fd, fp);
+           fdPush(fd, fpio, fp, fileno(fp));   /* Push fpio onto stack */
+           fd = fdLink(fd, "fopencookie");
+       }
+    }
+
+DBGIO(fd, (stderr, "==> Fdopen(%p,\"%s\") returns fd %p %s\n", ofd, fmode, fd, fdbg(fd)));
+    return fd;
+}
+
+FD_t Fopen(const char *path, const char *fmode)
+{
+    char stdio[20], other[20];
+    const char *end = NULL;
+    mode_t perms = 0666;
+    int flags;
+    FD_t fd;
+
+    if (path == NULL || fmode == NULL)
+       return NULL;
+
+    cvtfmode(fmode, stdio, sizeof(stdio), other, sizeof(other), &end, &flags);
+    if (stdio[0] == '\0')
+       return NULL;
+
+    if (end == NULL || !strcmp(end, "fdio")) {
+if (_rpmio_debug)
+fprintf(stderr, "*** Fopen fdio path %s fmode %s\n", path, fmode);
+       fd = fdOpen(path, flags, perms);
+       if (fdFileno(fd) < 0) {
+           fdClose(fd);
+           return NULL;
+       }
+    } else if (!strcmp(end, "fadio")) {
+if (_rpmio_debug)
+fprintf(stderr, "*** Fopen fadio path %s fmode %s\n", path, fmode);
+       fd = fadio->_open(path, flags, perms);
+       if (fdFileno(fd) < 0) {
+           fdClose(fd);
+           return NULL;
+       }
+    } else {
+       FILE *fp;
+       int fdno;
+       int isHTTP = 0;
+
+       /* XXX gzdio and bzdio here too */
+
+       switch (urlIsURL(path)) {
+       case URL_IS_HTTP:
+           isHTTP = 1;
+           /*@fallthrough@*/
+       case URL_IS_PATH:
+       case URL_IS_DASH:
+       case URL_IS_FTP:
+       case URL_IS_UNKNOWN:
+if (_rpmio_debug)
+fprintf(stderr, "*** Fopen ufdio path %s fmode %s\n", path, fmode);
+           fd = ufdOpen(path, flags, perms);
+           if (fd == NULL || fdFileno(fd) < 0)
+               return fd;
+           break;
+       default:
+if (_rpmio_debug)
+fprintf(stderr, "*** Fopen WTFO path %s fmode %s\n", path, fmode);
+           return NULL;
+           /*@notreached@*/ break;
+       }
+
+       /* XXX persistent HTTP/1.1 returns the previously opened fp */
+       if (isHTTP && ((fp = fdGetFp(fd)) != NULL) && ((fdno = fdGetFdno(fd)) >= 0)) {
+           fdPush(fd, fpio, fp, fileno(fp));   /* Push fpio onto stack */
+           return fd;
+       }
+    }
+
+    fd = Fdopen(fd, fmode);
+    return fd;
+}
+
+int Fflush(FD_t fd)
+{
+    if (fd == NULL) return -1;
+    if (fdGetIo(fd) == fpio)
+       return fflush(fdGetFILE(fd));
+    if (fdGetIo(fd) == gzdio)
+       return gzdFlush(fdGetFp(fd));
+#if HAVE_BZLIB_H
+    if (fdGetIo(fd) == bzdio)
+       return bzdFlush(fdGetFp(fd));
+#endif
+    return 0;
+}
+
+int Ferror(FD_t fd) {
+    int i, rc = 0;
+
+    if (fd == NULL) return -1;
+    for (i = fd->nfps; rc == 0 && i >= 0; i--) {
+       FDSTACK_t * fps = &fd->fps[i];
+       int ec;
+       
+       if (fps->io == fpio) {
+           ec = ferror(fdGetFILE(fd));
+       } else if (fps->io == gzdio) {
+           ec = (fd->syserrno  || fd->errcookie != NULL) ? -1 : 0;
+#if HAVE_BZLIB_H
+       } else if (fps->io == bzdio) {
+           ec = (fd->syserrno  || fd->errcookie != NULL) ? -1 : 0;
+#endif
+       } else {
+       /* XXX need to check ufdio/gzdio/bzdio/fdio errors correctly. */
+           ec = (fdFileno(fd) < 0 ? -1 : 0);
+       }
+
+       if (rc == 0 && ec)
+           rc = ec;
+    }
+DBGIO(fd, (stderr, "==> Ferror(%p) rc %d %s\n", fd, rc, fdbg(fd)));
+    return rc;
+}
+
+int Fileno(FD_t fd) {
+    int i, rc = -1;
+
+    for (i = fd->nfps ; rc == -1 && i >= 0; i--) {
+       rc = fd->fps[i].fdno;
+    }
+DBGIO(fd, (stderr, "==> Fileno(%p) rc %d %s\n", fd, rc, fdbg(fd)));
+    return rc;
+}
+
+/* XXX this is naive */
+int Fcntl(FD_t fd, int op, void *lip) {
+    return fcntl(Fileno(fd), op, lip);
+}
+
+/* =============================================================== */
+/* Helper routines that may be generally useful.
+ */
+
+/* XXX falloc.c: analogues to pread(3)/pwrite(3). */
+#ifdef USE_COOKIE_SEEK_POINTER
+ssize_t Pread(FD_t fd, void * buf, size_t count, _IO_off64_t offset) {
+#else
+ssize_t Pread(FD_t fd, void * buf, size_t count, off_t offset) {
+#endif
+    if (Fseek(fd, offset, SEEK_SET) < 0)
+       return -1;
+    return Fread(buf, sizeof(char), count, fd);
+}
+
+#ifdef USE_COOKIE_SEEK_POINTER
+ssize_t Pwrite(FD_t fd, const void * buf, size_t count, _IO_off64_t offset) {
+#else
+ssize_t Pwrite(FD_t fd, const void * buf, size_t count, off_t offset) {
+#endif
+    if (Fseek(fd, offset, SEEK_SET) < 0)
+       return -1;
+    return Fwrite(buf, sizeof(char), count, fd);
+}
+
+/* XXX rebuilddb.c: analogues to mkdir(2)/rmdir(2). */
+int Mkdir (const char *path, mode_t mode) {
+    const char * lpath;
+    int ut = urlPath(path, &lpath);
+
+    switch (ut) {
+    case URL_IS_FTP:
+       return ftpMkdir(path, mode);
+       /*@notreached@*/ break;
+    case URL_IS_HTTP:          /* XXX WRONG WRONG WRONG */
+    case URL_IS_PATH:
+       path = lpath;
+       /*@fallthrough@*/
+    case URL_IS_UNKNOWN:
+       break;
+    case URL_IS_DASH:
+    default:
+       return -2;
+       /*@notreached@*/ break;
+    }
+    return mkdir(path, mode);
+}
+
+int Chdir (const char *path) {
+    const char * lpath;
+    int ut = urlPath(path, &lpath);
+
+    switch (ut) {
+    case URL_IS_FTP:
+       return ftpChdir(path);
+       /*@notreached@*/ break;
+    case URL_IS_HTTP:          /* XXX WRONG WRONG WRONG */
+    case URL_IS_PATH:
+       path = lpath;
+       /*@fallthrough@*/
+    case URL_IS_UNKNOWN:
+       break;
+    case URL_IS_DASH:
+    default:
+       return -2;
+       /*@notreached@*/ break;
+    }
+    return chdir(path);
+}
+
+int Rmdir (const char *path) {
+    const char * lpath;
+    int ut = urlPath(path, &lpath);
+
+    switch (ut) {
+    case URL_IS_FTP:
+       return ftpRmdir(path);
+       /*@notreached@*/ break;
+    case URL_IS_HTTP:          /* XXX WRONG WRONG WRONG */
+    case URL_IS_PATH:
+       path = lpath;
+       /*@fallthrough@*/
+    case URL_IS_UNKNOWN:
+       break;
+    case URL_IS_DASH:
+    default:
+       return -2;
+       /*@notreached@*/ break;
+    }
+    return rmdir(path);
+}
+
+/* XXX rpmdb.c: analogue to rename(2). */
+
+int Rename (const char *oldpath, const char * newpath) {
+    const char *oe = NULL;
+    const char *ne = NULL;
+    int oldut, newut;
+
+    /* XXX lib/install.c used to rely on this behavior. */
+    if (!strcmp(oldpath, newpath)) return 0;
+
+    oldut = urlPath(oldpath, &oe);
+    switch (oldut) {
+    case URL_IS_FTP:           /* XXX WRONG WRONG WRONG */
+    case URL_IS_HTTP:          /* XXX WRONG WRONG WRONG */
+    case URL_IS_PATH:
+    case URL_IS_UNKNOWN:
+       break;
+    case URL_IS_DASH:
+    default:
+       return -2;
+       /*@notreached@*/ break;
+    }
+
+    newut = urlPath(newpath, &ne);
+    switch (newut) {
+    case URL_IS_FTP:
+if (_rpmio_debug)
+fprintf(stderr, "*** rename old %*s new %*s\n", (int)(oe - oldpath), oldpath, (int)(ne - newpath), newpath);
+       if (!(oldut == newut && oe && ne && (oe - oldpath) == (ne - newpath) &&
+           !strncasecmp(oldpath, newpath, (oe - oldpath))))
+           return -2;
+       return ftpRename(oldpath, newpath);
+       /*@notreached@*/ break;
+    case URL_IS_HTTP:          /* XXX WRONG WRONG WRONG */
+    case URL_IS_PATH:
+       oldpath = oe;
+       newpath = ne;
+       break;
+    case URL_IS_UNKNOWN:
+       break;
+    case URL_IS_DASH:
+    default:
+       return -2;
+       /*@notreached@*/ break;
+    }
+    return rename(oldpath, newpath);
+}
+
+int Link (const char *oldpath, const char * newpath) {
+    const char *oe = NULL;
+    const char *ne = NULL;
+    int oldut, newut;
+
+    oldut = urlPath(oldpath, &oe);
+    switch (oldut) {
+    case URL_IS_FTP:           /* XXX WRONG WRONG WRONG */
+    case URL_IS_HTTP:          /* XXX WRONG WRONG WRONG */
+    case URL_IS_PATH:
+    case URL_IS_UNKNOWN:
+       break;
+    case URL_IS_DASH:
+    default:
+       return -2;
+       /*@notreached@*/ break;
+    }
+
+    newut = urlPath(newpath, &ne);
+    switch (newut) {
+    case URL_IS_HTTP:          /* XXX WRONG WRONG WRONG */
+    case URL_IS_FTP:           /* XXX WRONG WRONG WRONG */
+    case URL_IS_PATH:
+if (_rpmio_debug)
+fprintf(stderr, "*** link old %*s new %*s\n", (int)(oe - oldpath), oldpath, (int)(ne - newpath), newpath);
+       if (!(oldut == newut && oe && ne && (oe - oldpath) == (ne - newpath) &&
+           !strncasecmp(oldpath, newpath, (oe - oldpath))))
+           return -2;
+       oldpath = oe;
+       newpath = ne;
+       break;
+    case URL_IS_UNKNOWN:
+       break;
+    case URL_IS_DASH:
+    default:
+       return -2;
+       /*@notreached@*/ break;
+    }
+    return link(oldpath, newpath);
+}
+
+/* XXX build/build.c: analogue to unlink(2). */
+
+int Unlink(const char * path) {
+    const char * lpath;
+    int ut = urlPath(path, &lpath);
+
+    switch (ut) {
+    case URL_IS_FTP:
+       return ftpUnlink(path);
+       /*@notreached@*/ break;
+    case URL_IS_HTTP:          /* XXX WRONG WRONG WRONG */
+    case URL_IS_PATH:
+       path = lpath;
+       /*@fallthrough@*/
+    case URL_IS_UNKNOWN:
+       break;
+    case URL_IS_DASH:
+    default:
+       return -2;
+       /*@notreached@*/ break;
+    }
+    return unlink(path);
+}
+
+/* XXX swiped from mc-4.5.39-pre9 vfs/ftpfs.c */
+
+#define        g_strdup        xstrdup
+#define        g_free          xfree
+
+/*
+ * FIXME: this is broken. It depends on mc not crossing border on month!
+ */
+static int current_mday;
+static int current_mon;
+static int current_year;
+
+/* Following stuff (parse_ls_lga) is used by ftpfs and extfs */
+#define MAXCOLS                30
+
+static char *columns [MAXCOLS];        /* Points to the string in column n */
+static int   column_ptr [MAXCOLS]; /* Index from 0 to the starting positions of the columns */
+
+static int
+vfs_split_text (char *p)
+{
+    char *original = p;
+    int  numcols;
+
+
+    for (numcols = 0; *p && numcols < MAXCOLS; numcols++){
+       while (*p == ' ' || *p == '\r' || *p == '\n'){
+           *p = 0;
+           p++;
+       }
+       columns [numcols] = p;
+       column_ptr [numcols] = p - original;
+       while (*p && *p != ' ' && *p != '\r' && *p != '\n')
+           p++;
+    }
+    return numcols;
+}
+
+static int
+is_num (int idx)
+{
+    if (!columns [idx] || columns [idx][0] < '0' || columns [idx][0] > '9')
+       return 0;
+    return 1;
+}
+
+static int
+is_dos_date(char *str)
+{
+    if (strlen(str) == 8 && str[2] == str[5] && strchr("\\-/", (int)str[2]) != NULL)
+       return (1);
+
+    return (0);
+}
+
+static int
+is_week (char *str, struct tm *tim)
+{
+    static char *week = "SunMonTueWedThuFriSat";
+    char *pos;
+
+    if((pos=strstr(week, str)) != NULL){
+        if(tim != NULL)
+           tim->tm_wday = (pos - week)/3;
+       return (1);
+    }
+    return (0);    
+}
+
+static int
+is_month (char *str, struct tm *tim)
+{
+    static char *month = "JanFebMarAprMayJunJulAugSepOctNovDec";
+    char *pos;
+    
+    if((pos=strstr(month, str)) != NULL){
+        if(tim != NULL)
+           tim->tm_mon = (pos - month)/3;
+       return (1);
+    }
+    return (0);
+}
+
+static int
+is_time (char *str, struct tm *tim)
+{
+    char *p, *p2;
+
+    if ((p=strchr(str, ':')) && (p2=strrchr(str, ':'))) {
+       if (p != p2) {
+           if (sscanf (str, "%2d:%2d:%2d", &tim->tm_hour, &tim->tm_min, &tim->tm_sec) != 3)
+               return (0);
+       }
+       else {
+           if (sscanf (str, "%2d:%2d", &tim->tm_hour, &tim->tm_min) != 2)
+               return (0);
+       }
+    }
+    else 
+        return (0);
+    
+    return (1);
+}
+
+static int is_year(char *str, struct tm *tim)
+{
+    long year;
+
+    if (strchr(str,':'))
+        return (0);
+
+    if (strlen(str)!=4)
+        return (0);
+
+    if (sscanf(str, "%ld", &year) != 1)
+        return (0);
+
+    if (year < 1900 || year > 3000)
+        return (0);
+
+    tim->tm_year = (int) (year - 1900);
+
+    return (1);
+}
+
+/*
+ * FIXME: this is broken. Consider following entry:
+ * -rwx------   1 root     root            1 Aug 31 10:04 2904 1234
+ * where "2904 1234" is filename. Well, this code decodes it as year :-(.
+ */
+
+static int
+vfs_parse_filetype (char c)
+{
+    switch (c){
+        case 'd': return S_IFDIR; 
+        case 'b': return S_IFBLK;
+        case 'c': return S_IFCHR;
+        case 'l': return S_IFLNK;
+        case 's':
+#ifdef IS_IFSOCK /* And if not, we fall through to IFIFO, which is pretty close */
+                 return S_IFSOCK;
+#endif
+        case 'p': return S_IFIFO;
+        case 'm': case 'n':            /* Don't know what these are :-) */
+        case '-': case '?': return S_IFREG;
+        default: return -1;
+    }
+}
+
+static int vfs_parse_filemode (char *p)
+{      /* converts rw-rw-rw- into 0666 */
+    int res = 0;
+    switch (*(p++)){
+       case 'r': res |= 0400; break;
+       case '-': break;
+       default: return -1;
+    }
+    switch (*(p++)){
+       case 'w': res |= 0200; break;
+       case '-': break;
+       default: return -1;
+    }
+    switch (*(p++)){
+       case 'x': res |= 0100; break;
+       case 's': res |= 0100 | S_ISUID; break;
+       case 'S': res |= S_ISUID; break;
+       case '-': break;
+       default: return -1;
+    }
+    switch (*(p++)){
+       case 'r': res |= 0040; break;
+       case '-': break;
+       default: return -1;
+    }
+    switch (*(p++)){
+       case 'w': res |= 0020; break;
+       case '-': break;
+       default: return -1;
+    }
+    switch (*(p++)){
+       case 'x': res |= 0010; break;
+       case 's': res |= 0010 | S_ISGID; break;
+        case 'l': /* Solaris produces these */
+       case 'S': res |= S_ISGID; break;
+       case '-': break;
+       default: return -1;
+    }
+    switch (*(p++)){
+       case 'r': res |= 0004; break;
+       case '-': break;
+       default: return -1;
+    }
+    switch (*(p++)){
+       case 'w': res |= 0002; break;
+       case '-': break;
+       default: return -1;
+    }
+    switch (*(p++)){
+       case 'x': res |= 0001; break;
+       case 't': res |= 0001 | S_ISVTX; break;
+       case 'T': res |= S_ISVTX; break;
+       case '-': break;
+       default: return -1;
+    }
+    return res;
+}
+
+static int vfs_parse_filedate(int idx, time_t *t)
+{      /* This thing parses from idx in columns[] array */
+
+    char *p;
+    struct tm tim;
+    int d[3];
+    int        got_year = 0;
+
+    /* Let's setup default time values */
+    tim.tm_year = current_year;
+    tim.tm_mon  = current_mon;
+    tim.tm_mday = current_mday;
+    tim.tm_hour = 0;
+    tim.tm_min  = 0;
+    tim.tm_sec  = 0;
+    tim.tm_isdst = -1; /* Let mktime() try to guess correct dst offset */
+    
+    p = columns [idx++];
+    
+    /* We eat weekday name in case of extfs */
+    if(is_week(p, &tim))
+       p = columns [idx++];
+
+    /* Month name */
+    if(is_month(p, &tim)){
+       /* And we expect, it followed by day number */
+       if (is_num (idx))
+           tim.tm_mday = (int)atol (columns [idx++]);
+       else
+           return 0; /* No day */
+
+    } else {
+        /* We usually expect:
+           Mon DD hh:mm
+           Mon DD  YYYY
+          But in case of extfs we allow these date formats:
+           Mon DD YYYY hh:mm
+          Mon DD hh:mm YYYY
+          Wek Mon DD hh:mm:ss YYYY
+           MM-DD-YY hh:mm
+           where Mon is Jan-Dec, DD, MM, YY two digit day, month, year,
+           YYYY four digit year, hh, mm, ss two digit hour, minute or second. */
+
+       /* Here just this special case with MM-DD-YY */
+        if (is_dos_date(p)){
+            p[2] = p[5] = '-';
+           
+           if(sscanf(p, "%2d-%2d-%2d", &d[0], &d[1], &d[2]) == 3){
+           /*  We expect to get:
+               1. MM-DD-YY
+               2. DD-MM-YY
+               3. YY-MM-DD
+               4. YY-DD-MM  */
+               
+               /* Hmm... maybe, next time :)*/
+               
+               /* At last, MM-DD-YY */
+               d[0]--; /* Months are zerobased */
+               /* Y2K madness */
+               if(d[2] < 70)
+                   d[2] += 100;
+
+               tim.tm_mon  = d[0];
+               tim.tm_mday = d[1];
+               tim.tm_year = d[2];
+               got_year = 1;
+           } else
+               return 0; /* sscanf failed */
+        } else
+            return 0; /* unsupported format */
+    }
+
+    /* Here we expect to find time and/or year */
+    
+    if (is_num (idx)) {
+        if(is_time(columns[idx], &tim) || (got_year = is_year(columns[idx], &tim))) {
+       idx++;
+
+       /* This is a special case for ctime() or Mon DD YYYY hh:mm */
+       if(is_num (idx) && 
+           ((got_year = is_year(columns[idx], &tim)) || is_time(columns[idx], &tim)))
+               idx++; /* time & year or reverse */
+       } /* only time or date */
+    }
+    else 
+        return 0; /* Nor time or date */
+
+    /*
+     * If the date is less than 6 months in the past, it is shown without year
+     * other dates in the past or future are shown with year but without time
+     * This does not check for years before 1900 ... I don't know, how
+     * to represent them at all
+     */
+    if (!got_year &&
+       current_mon < 6 && current_mon < tim.tm_mon && 
+       tim.tm_mon - current_mon >= 6)
+
+       tim.tm_year--;
+
+    if ((*t = mktime(&tim)) < 0)
+        *t = 0;
+    return idx;
+}
+
+static int
+vfs_parse_ls_lga (char *p, struct stat *s, char **filename, char **linkname)
+{
+    int idx, idx2, num_cols;
+    int i;
+    char *p_copy;
+    
+    if (strncmp (p, "total", 5) == 0)
+        return 0;
+
+    p_copy = g_strdup(p);
+/* XXX FIXME: parse out inode number from "NLST -lai ." */
+/* XXX FIXME: parse out sizein blocks from "NLST -lais ." */
+
+    if ((i = vfs_parse_filetype(*(p++))) == -1)
+        goto error;
+
+    s->st_mode = i;
+    if (*p == ' ')     /* Notwell 4 */
+        p++;
+    if (*p == '['){
+       if (strlen (p) <= 8 || p [8] != ']')
+           goto error;
+       /* Should parse here the Notwell permissions :) */
+       if (S_ISDIR (s->st_mode))
+           s->st_mode |= (S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR | S_IXUSR | S_IXGRP | S_IXOTH);
+       else
+           s->st_mode |= (S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR);
+       p += 9;
+    } else {
+       if ((i = vfs_parse_filemode(p)) == -1)
+           goto error;
+        s->st_mode |= i;
+       p += 9;
+
+        /* This is for an extra ACL attribute (HP-UX) */
+        if (*p == '+')
+            p++;
+    }
+
+    g_free(p_copy);
+    p_copy = g_strdup(p);
+    num_cols = vfs_split_text (p);
+
+    s->st_nlink = atol (columns [0]);
+    if (s->st_nlink < 0)
+        goto error;
+
+    if (!is_num (1))
+#ifdef HACK
+       s->st_uid = finduid (columns [1]);
+#else
+       unameToUid (columns [1], &s->st_uid);
+#endif
+    else
+        s->st_uid = (uid_t) atol (columns [1]);
+
+    /* Mhm, the ls -lg did not produce a group field */
+    for (idx = 3; idx <= 5; idx++) 
+        if (is_month(columns [idx], NULL) || is_week(columns [idx], NULL) || is_dos_date(columns[idx]))
+            break;
+
+    if (idx == 6 || (idx == 5 && !S_ISCHR (s->st_mode) && !S_ISBLK (s->st_mode)))
+       goto error;
+
+    /* We don't have gid */    
+    if (idx == 3 || (idx == 4 && (S_ISCHR(s->st_mode) || S_ISBLK (s->st_mode))))
+        idx2 = 2;
+    else { 
+       /* We have gid field */
+       if (is_num (2))
+           s->st_gid = (gid_t) atol (columns [2]);
+       else
+#ifdef HACK
+           s->st_gid = findgid (columns [2]);
+#else
+           gnameToGid (columns [1], &s->st_gid);
+#endif
+       idx2 = 3;
+    }
+
+    /* This is device */
+    if (S_ISCHR (s->st_mode) || S_ISBLK (s->st_mode)){
+       int maj, min;
+       
+       if (!is_num (idx2) || sscanf(columns [idx2], " %d,", &maj) != 1)
+           goto error;
+       
+       if (!is_num (++idx2) || sscanf(columns [idx2], " %d", &min) != 1)
+           goto error;
+       
+#ifdef HAVE_ST_RDEV
+       s->st_rdev = ((maj & 0xff) << 8) | (min & 0xffff00ff);
+#endif
+       s->st_size = 0;
+       
+    } else {
+       /* Common file size */
+       if (!is_num (idx2))
+           goto error;
+       
+       s->st_size = (size_t) atol (columns [idx2]);
+#ifdef HAVE_ST_RDEV
+       s->st_rdev = 0;
+#endif
+    }
+
+    idx = vfs_parse_filedate(idx, &s->st_mtime);
+    if (!idx)
+        goto error;
+    /* Use resulting time value */
+    s->st_atime = s->st_ctime = s->st_mtime;
+    s->st_dev = 0;
+    s->st_ino = 0;
+#ifdef HAVE_ST_BLKSIZE
+    s->st_blksize = 512;
+#endif
+#ifdef HAVE_ST_BLOCKS
+    s->st_blocks = (s->st_size + 511) / 512;
+#endif
+
+    for (i = idx + 1, idx2 = 0; i < num_cols; i++ ) 
+       if (strcmp (columns [i], "->") == 0){
+           idx2 = i;
+           break;
+       }
+    
+    if (((S_ISLNK (s->st_mode) || 
+        (num_cols == idx + 3 && s->st_nlink > 1))) /* Maybe a hardlink? (in extfs) */
+        && idx2){
+       int p;
+       char *s;
+           
+       if (filename){
+#ifdef HACK
+           s = g_strndup (p_copy + column_ptr [idx], column_ptr [idx2] - column_ptr [idx] - 1);
+#else
+           int nb = column_ptr [idx2] - column_ptr [idx] - 1;
+           s = xmalloc(nb+1);
+           strncpy(s, p_copy + column_ptr [idx], nb);
+#endif
+           *filename = s;
+       }
+       if (linkname){
+           s = g_strdup (p_copy + column_ptr [idx2+1]);
+           p = strlen (s);
+           if (s [p-1] == '\r' || s [p-1] == '\n')
+               s [p-1] = 0;
+           if (s [p-2] == '\r' || s [p-2] == '\n')
+               s [p-2] = 0;
+               
+           *linkname = s;
+       }
+    } else {
+       /* Extract the filename from the string copy, not from the columns
+        * this way we have a chance of entering hidden directories like ". ."
+        */
+       if (filename){
+           /* 
+           *filename = g_strdup (columns [idx++]);
+           */
+           int p;
+           char *s;
+           
+           s = g_strdup (p_copy + column_ptr [idx++]);
+           p = strlen (s);
+           /* g_strchomp(); */
+           if (s [p-1] == '\r' || s [p-1] == '\n')
+               s [p-1] = 0;
+           if (s [p-2] == '\r' || s [p-2] == '\n')
+               s [p-2] = 0;
+           
+           *filename = s;
+       }
+       if (linkname)
+           *linkname = NULL;
+    }
+    g_free (p_copy);
+    return 1;
+
+error:
+#ifdef HACK
+    {
+      static int errorcount = 0;
+
+      if (++errorcount < 5) {
+       message_1s (1, "Could not parse:", p_copy);
+      } else if (errorcount == 5)
+       message_1s (1, "More parsing errors will be ignored.", "(sorry)" );
+    }
+#endif
+
+    if (p_copy != p)           /* Carefull! */
+       g_free (p_copy);
+    return 0;
+}
+
+typedef enum {
+       DO_FTP_STAT     = 1,
+       DO_FTP_LSTAT    = 2,
+       DO_FTP_READLINK = 3,
+       DO_FTP_ACCESS   = 4,
+       DO_FTP_GLOB     = 5
+} ftpSysCall_t;
+static size_t ftpBufAlloced = 0;
+static char * ftpBuf = NULL;
+       
+#define alloca_strdup(_s)       strcpy(alloca(strlen(_s)+1), (_s))
+
+static int ftpNLST(const char * url, ftpSysCall_t ftpSysCall,
+       struct stat * st, char * rlbuf, size_t rlbufsiz)
+{
+    FD_t fd;
+    const char * path;
+    int bufLength, moretodo;
+    const char *n, *ne, *o, *oe;
+    char * s;
+    char * se;
+    const char * urldn;
+    char * bn = NULL;
+    int nbn = 0;
+    urlinfo u;
+    int rc;
+
+    n = ne = o = oe = NULL;
+    (void) urlPath(url, &path);
+    if (*path == '\0')
+       return -2;
+
+    switch (ftpSysCall) {
+    case DO_FTP_GLOB:
+       fd = ftpOpen(url, 0, 0, &u);
+       if (fd == NULL || u == NULL)
+           return -1;
+
+       u->openError = ftpReq(fd, "NLST", path);
+       break;
+    default:
+       urldn = alloca_strdup(url);
+       if ((bn = strrchr(urldn, '/')) == NULL)
+           return -2;
+       else if (bn == path)
+           bn = ".";
+       else
+           *bn++ = '\0';
+       nbn = strlen(bn);
+
+       rc = ftpChdir(urldn);           /* XXX don't care about CWD */
+       if (rc < 0)
+           return rc;
+
+       fd = ftpOpen(url, 0, 0, &u);
+       if (fd == NULL || u == NULL)
+           return -1;
+
+       /* XXX possibly should do "NLST -lais" to get st_ino/st_blocks also */
+       u->openError = ftpReq(fd, "NLST", "-la");
+       break;
+    }
+
+    if (u->openError < 0) {
+       fd = fdLink(fd, "error data (ftpStat)");
+       rc = -2;
+       goto exit;
+    }
+
+    if (ftpBufAlloced == 0 || ftpBuf == NULL) {
+        ftpBufAlloced = url_iobuf_size;
+        ftpBuf = xcalloc(ftpBufAlloced, sizeof(ftpBuf[0]));
+    }
+    *ftpBuf = '\0';
+
+    bufLength = 0;
+    moretodo = 1;
+
+    do {
+
+       /* XXX FIXME: realloc ftpBuf is < ~128 chars remain */
+       if ((ftpBufAlloced - bufLength) < (1024+80)) {
+           ftpBufAlloced <<= 2;
+           ftpBuf = xrealloc(ftpBuf, ftpBufAlloced);
+       }
+       s = se = ftpBuf + bufLength;
+       *se = '\0';
+
+       rc = fdFgets(fd, se, (ftpBufAlloced - bufLength));
+       if (rc <= 0) {
+           moretodo = 0;
+           break;
+       }
+       if (ftpSysCall == DO_FTP_GLOB) {        /* XXX HACK */
+           bufLength += strlen(se);
+           continue;
+       }
+
+       for (s = se; *s != '\0'; s = se) {
+           int bingo;
+
+           while (*se && *se != '\n') se++;
+           if (se > s && se[-1] == '\r') se[-1] = '\0';
+           if (*se == '\0') break;
+           *se++ = '\0';
+
+           if (!strncmp(s, "total ", sizeof("total ")-1)) continue;
+
+           o = NULL;
+           for (bingo = 0, n = se; n >= s; n--) {
+               switch (*n) {
+               case '\0':
+                   oe = ne = n;
+                   break;
+               case ' ':
+                   if (o || !(n[-3] == ' ' && n[-2] == '-' && n[-1] == '>')) {
+                       while (*(++n) == ' ');
+                       bingo++;
+                       break;
+                   }
+                   for (o = n + 1; *o == ' '; o++);
+                   n -= 3;
+                   ne = n;
+                   break;
+               default:
+                   break;
+               }
+               if (bingo) break;
+           }
+
+           if (nbn != (ne - n))        continue;       /* Same name length? */
+           if (strncmp(n, bn, nbn))    continue;       /* Same name? */
+
+           moretodo = 0;
+           break;
+       }
+
+        if (moretodo && se > s) {
+            bufLength = se - s - 1;
+            if (s != ftpBuf)
+                memmove(ftpBuf, s, bufLength);
+        } else {
+           bufLength = 0;
+       }
+    } while (moretodo);
+
+    switch (ftpSysCall) {
+    case DO_FTP_STAT:
+       if (o && oe) {
+           /* XXX FIXME: symlink, replace urldn/bn from [o,oe) and restart */
+       }
+       /*@fallthrough@*/
+    case DO_FTP_LSTAT:
+       if (st == NULL || !(n && ne)) {
+           rc = -1;
+       } else {
+           rc = ((vfs_parse_ls_lga(s, st, NULL, NULL) > 0) ? 0 : -1);
+       }
+       break;
+    case DO_FTP_READLINK:
+       if (rlbuf == NULL || !(o && oe)) {
+           rc = -1;
+       } else {
+           rc = oe - o;
+           if (rc > rlbufsiz)
+               rc = rlbufsiz;
+           memcpy(rlbuf, o, rc);
+           if (rc < rlbufsiz)
+               rlbuf[rc] = '\0';
+       }
+       break;
+    case DO_FTP_ACCESS:
+       rc = 0;         /* XXX WRONG WRONG WRONG */
+       break;
+    case DO_FTP_GLOB:
+       rc = 0;         /* XXX WRONG WRONG WRONG */
+       break;
+    }
+
+exit:
+    ufdClose(fd);
+    return rc;
+}
+
+static int ftpStat(const char * path, struct stat *st)
+{
+    return ftpNLST(path, DO_FTP_STAT, st, NULL, 0);
+}
+
+static int ftpLstat(const char * path, struct stat *st) {
+    int rc;
+    rc = ftpNLST(path, DO_FTP_LSTAT, st, NULL, 0);
+if (_rpmio_debug)
+fprintf(stderr, "*** ftpLstat(%s) rc %d\n", path, rc);
+    return rc;
+}
+
+static int ftpReadlink(const char * path, char * buf, size_t bufsiz) {
+    return ftpNLST(path, DO_FTP_READLINK, NULL, buf, bufsiz);
+}
+
+static int ftpGlob(const char * path, int flags,
+               int errfunc(const char * epath, int eerno), glob_t * pglob)
+{
+    int rc;
+
+    if (pglob == NULL)
+       return -2;
+    rc = ftpNLST(path, DO_FTP_GLOB, NULL, NULL, 0);
+if (_rpmio_debug)
+fprintf(stderr, "*** ftpGlob(%s,0x%x,%p,%p) ftpNLST rc %d\n", path, flags, errfunc, pglob, rc);
+    if (rc)
+       return rc;
+    rc = poptParseArgvString(ftpBuf, &pglob->gl_pathc, (const char ***)&pglob->gl_pathv);
+    pglob->gl_offs = -1;       /* XXX HACK HACK HACK */
+    return rc;
+}
+
+static void ftpGlobfree(glob_t * pglob) {
+if (_rpmio_debug)
+fprintf(stderr, "*** ftpGlobfree(%p)\n", pglob);
+    if (pglob->gl_offs == -1)  /* XXX HACK HACK HACK */
+       xfree(pglob->gl_pathv);
+}
+
+int Stat(const char * path, struct stat * st) {
+    const char * lpath;
+    int ut = urlPath(path, &lpath);
+
+if (_rpmio_debug)
+fprintf(stderr, "*** Stat(%s,%p)\n", path, st);
+    switch (ut) {
+    case URL_IS_FTP:
+       return ftpStat(path, st);
+       /*@notreached@*/ break;
+    case URL_IS_HTTP:          /* XXX WRONG WRONG WRONG */
+    case URL_IS_PATH:
+       path = lpath;
+       /*@fallthrough@*/
+    case URL_IS_UNKNOWN:
+       break;
+    case URL_IS_DASH:
+    default:
+       return -2;
+       /*@notreached@*/ break;
+    }
+    return stat(path, st);
+}
+
+int Lstat(const char * path, struct stat * st) {
+    const char * lpath;
+    int ut = urlPath(path, &lpath);
+
+if (_rpmio_debug)
+fprintf(stderr, "*** Lstat(%s,%p)\n", path, st);
+    switch (ut) {
+    case URL_IS_FTP:
+       return ftpLstat(path, st);
+       /*@notreached@*/ break;
+    case URL_IS_HTTP:          /* XXX WRONG WRONG WRONG */
+    case URL_IS_PATH:
+       path = lpath;
+       /*@fallthrough@*/
+    case URL_IS_UNKNOWN:
+       break;
+    case URL_IS_DASH:
+    default:
+       return -2;
+       /*@notreached@*/ break;
+    }
+    return lstat(path, st);
+}
+
+int Readlink(const char * path, char * buf, size_t bufsiz) {
+    const char * lpath;
+    int ut = urlPath(path, &lpath);
+
+    switch (ut) {
+    case URL_IS_FTP:
+       return ftpReadlink(path, buf, bufsiz);
+       /*@notreached@*/ break;
+    case URL_IS_HTTP:          /* XXX WRONG WRONG WRONG */
+    case URL_IS_PATH:
+       path = lpath;
+       /*@fallthrough@*/
+    case URL_IS_UNKNOWN:
+       break;
+    case URL_IS_DASH:
+    default:
+       return -2;
+       /*@notreached@*/ break;
+    }
+    return readlink(path, buf, bufsiz);
+}
+
+int Access(const char * path, int amode) {
+    const char * lpath;
+    int ut = urlPath(path, &lpath);
+
+if (_rpmio_debug)
+fprintf(stderr, "*** Access(%s,%d)\n", path, amode);
+    switch (ut) {
+    case URL_IS_FTP:           /* XXX WRONG WRONG WRONG */
+    case URL_IS_HTTP:          /* XXX WRONG WRONG WRONG */
+    case URL_IS_PATH:
+       path = lpath;
+       /*@fallthrough@*/
+    case URL_IS_UNKNOWN:
+       break;
+    case URL_IS_DASH:
+    default:
+       return -2;
+       /*@notreached@*/ break;
+    }
+    return access(path, amode);
+}
+
+int Glob(const char *path, int flags,
+       int errfunc(const char * epath, int eerrno), glob_t *pglob)
+{
+    const char * lpath;
+    int ut = urlPath(path, &lpath);
+
+if (_rpmio_debug)
+fprintf(stderr, "*** Glob(%s,0x%x,%p,%p)\n", path, flags, errfunc, pglob);
+    switch (ut) {
+    case URL_IS_FTP:           /* XXX WRONG WRONG WRONG */
+       return ftpGlob(path, flags, errfunc, pglob);
+       /*@notreached@*/ break;
+    case URL_IS_HTTP:          /* XXX WRONG WRONG WRONG */
+    case URL_IS_PATH:
+       path = lpath;
+       /*@fallthrough@*/
+    case URL_IS_UNKNOWN:
+       break;
+    case URL_IS_DASH:
+    default:
+       return -2;
+       /*@notreached@*/ break;
+    }
+    return glob(path, flags, errfunc, pglob);
+}
+
+void Globfree(glob_t *pglob)
+{
+if (_rpmio_debug)
+fprintf(stderr, "*** Globfree(%p)\n", pglob);
+    if (pglob->gl_offs == -1) /* XXX HACK HACK HACK */
+       ftpGlobfree(pglob);
+    else
+       globfree(pglob);
+}
+
+DIR * Opendir(const char * path)
+{
+    const char * lpath;
+    int ut = urlPath(path, &lpath);
+
+if (_rpmio_debug)
+fprintf(stderr, "*** Opendir(%s)\n", path);
+    switch (ut) {
+    case URL_IS_FTP:           /* XXX WRONG WRONG WRONG */
+    case URL_IS_HTTP:          /* XXX WRONG WRONG WRONG */
+    case URL_IS_PATH:
+       path = lpath;
+       /*@fallthrough@*/
+    case URL_IS_UNKNOWN:
+       break;
+    case URL_IS_DASH:
+    default:
+       return NULL;
+       /*@notreached@*/ break;
+    }
+    return opendir(path);
+}
+
+struct dirent * Readdir(DIR * dir)
+{
+if (_rpmio_debug)
+fprintf(stderr, "*** Readdir(%p)\n", dir);
+    return readdir(dir);
+}
+
+int Closedir(DIR * dir)
+{
+if (_rpmio_debug)
+fprintf(stderr, "*** Closedir(%p)\n", dir);
+    return closedir(dir);
+}
+
+static struct FDIO_s fpio_s = {
+  ufdRead, ufdWrite, fdSeek, ufdClose, XfdLink, XfdFree, XfdNew, fdFileno,
+  ufdOpen, NULL, fdGetFp, NULL,        Mkdir, Chdir, Rmdir, Rename, Unlink
+};
+FDIO_t fpio = /*@-compmempass@*/ &fpio_s /*@=compmempass@*/ ;
index 83f0545..c698988 100644 (file)
@@ -53,12 +53,12 @@ lib/rpmchecksig.c
 lib/rpmdb.c
 lib/rpmerr.c
 lib/rpminstall.c
-lib/rpmio.c
 lib/rpmlead.c
 lib/rpmrc.c
 lib/signature.c
 lib/stringbuf.c
 lib/transaction.c
 lib/uninstall.c
-lib/url.c
 lib/verify.c
+rpmio/rpmio.c
+rpmio/url.c
index 0d0f294..580160a 100644 (file)
--- a/po/cs.po
+++ b/po/cs.po
@@ -6,7 +6,7 @@
 msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
-"POT-Creation-Date: 2000-06-06 15:54-0400\n"
+"POT-Creation-Date: 2000-06-07 14:46-0400\n"
 "PO-Revision-Date: 1998-10-10 10:10+0200\n"
 "Last-Translator: Pavel Makovec <pavelm@terminal.cz>\n"
 "Language-Team: Czech <pavelm@terminal.cz>\n"
@@ -2565,7 +2565,7 @@ msgstr "nelze prov
 msgid "opening db file        %s mode 0x%x\n"
 msgstr "probíhá otevírání databázového re¾imu: 0%o\n"
 
-#: lib/db1.c:430 lib/url.c:445
+#: lib/db1.c:430 rpmio/url.c:445
 #, fuzzy, c-format
 msgid "failed to open %s: %s\n"
 msgstr "nelze otevøít %s: %s"
@@ -3757,71 +3757,6 @@ msgstr "chyba: nelze otev
 msgid "Installing %s\n"
 msgstr "Probíhá instalace %s\n"
 
-#: lib/rpmio.c:796
-msgid "Success"
-msgstr ""
-
-#: lib/rpmio.c:799
-#, fuzzy
-msgid "Bad server response"
-msgstr "Chybná odezva serveru FTP"
-
-#: lib/rpmio.c:802
-#, fuzzy
-msgid "Server IO error"
-msgstr "V/V chyba FTP"
-
-#: lib/rpmio.c:805
-#, fuzzy
-msgid "Server timeout"
-msgstr "Promlka serveru FTP"
-
-#: lib/rpmio.c:808
-#, fuzzy
-msgid "Unable to lookup server host address"
-msgstr "Nelze vyhledat adresu hostitelského serveru FTP"
-
-#: lib/rpmio.c:811
-#, fuzzy
-msgid "Unable to lookup server host name"
-msgstr "Nelze vyhledat název hostitelského serveru FTP"
-
-#: lib/rpmio.c:814
-#, fuzzy
-msgid "Failed to connect to server"
-msgstr "K serveru FTP se nelze pøipojit"
-
-#: lib/rpmio.c:817
-#, fuzzy
-msgid "Failed to establish data connection to server"
-msgstr "Se serverem FTP nelze navázat datové spojení"
-
-#: lib/rpmio.c:820
-msgid "IO error to local file"
-msgstr "V/V chyba na místní soubor"
-
-#: lib/rpmio.c:823
-msgid "Error setting remote server to passive mode"
-msgstr "Chyba pøi nastavení vzdáleného serveru na pasivní re¾im"
-
-#: lib/rpmio.c:826
-msgid "File not found on server"
-msgstr "Soubor nebyl na serveru nalezen"
-
-#: lib/rpmio.c:829
-msgid "Abort in progress"
-msgstr ""
-
-#: lib/rpmio.c:833
-#, fuzzy
-msgid "Unknown or unexpected error"
-msgstr "Neznámá nebo neèekaná chyba FTP"
-
-#: lib/rpmio.c:1366
-#, c-format
-msgid "logging into %s as %s, pw %s\n"
-msgstr "probíhá pøihla¹ování na %s jako %s, h. %s\n"
-
 #: lib/rpmlead.c:48
 #, c-format
 msgid "read failed: %s (%d)"
@@ -4115,65 +4050,130 @@ msgstr "spou
 msgid "execution of script failed"
 msgstr "skript nelze spustit"
 
-#: lib/url.c:88
+#: lib/verify.c:39
+#, fuzzy
+msgid "don't verify files in package"
+msgstr "binární balíèek starého typu\n"
+
+#: lib/verify.c:215
+msgid "package lacks both user name and id lists (this should never happen)"
+msgstr ""
+
+#: lib/verify.c:233
+msgid "package lacks both group name and id lists (this should never happen)"
+msgstr ""
+
+#: lib/verify.c:269
+#, c-format
+msgid "missing    %s\n"
+msgstr "chybí      %s\n"
+
+#: lib/verify.c:331
+#, c-format
+msgid "Unsatisfied dependencies for %s-%s-%s: "
+msgstr "Nevyøe¹ené závislosti pro %s-%s-%s: "
+
+#: rpmio/rpmio.c:796
+msgid "Success"
+msgstr ""
+
+#: rpmio/rpmio.c:799
+#, fuzzy
+msgid "Bad server response"
+msgstr "Chybná odezva serveru FTP"
+
+#: rpmio/rpmio.c:802
+#, fuzzy
+msgid "Server IO error"
+msgstr "V/V chyba FTP"
+
+#: rpmio/rpmio.c:805
+#, fuzzy
+msgid "Server timeout"
+msgstr "Promlka serveru FTP"
+
+#: rpmio/rpmio.c:808
+#, fuzzy
+msgid "Unable to lookup server host address"
+msgstr "Nelze vyhledat adresu hostitelského serveru FTP"
+
+#: rpmio/rpmio.c:811
+#, fuzzy
+msgid "Unable to lookup server host name"
+msgstr "Nelze vyhledat název hostitelského serveru FTP"
+
+#: rpmio/rpmio.c:814
+#, fuzzy
+msgid "Failed to connect to server"
+msgstr "K serveru FTP se nelze pøipojit"
+
+#: rpmio/rpmio.c:817
+#, fuzzy
+msgid "Failed to establish data connection to server"
+msgstr "Se serverem FTP nelze navázat datové spojení"
+
+#: rpmio/rpmio.c:820
+msgid "IO error to local file"
+msgstr "V/V chyba na místní soubor"
+
+#: rpmio/rpmio.c:823
+msgid "Error setting remote server to passive mode"
+msgstr "Chyba pøi nastavení vzdáleného serveru na pasivní re¾im"
+
+#: rpmio/rpmio.c:826
+msgid "File not found on server"
+msgstr "Soubor nebyl na serveru nalezen"
+
+#: rpmio/rpmio.c:829
+msgid "Abort in progress"
+msgstr ""
+
+#: rpmio/rpmio.c:833
+#, fuzzy
+msgid "Unknown or unexpected error"
+msgstr "Neznámá nebo neèekaná chyba FTP"
+
+#: rpmio/rpmio.c:1366
+#, c-format
+msgid "logging into %s as %s, pw %s\n"
+msgstr "probíhá pøihla¹ování na %s jako %s, h. %s\n"
+
+#: rpmio/url.c:88
 #, c-format
 msgid "warning: u %p ctrl %p nrefs != 0 (%s %s)\n"
 msgstr ""
 
-#: lib/url.c:105
+#: rpmio/url.c:105
 #, c-format
 msgid "warning: u %p data %p nrefs != 0 (%s %s)\n"
 msgstr ""
 
-#: lib/url.c:132
+#: rpmio/url.c:132
 #, c-format
 msgid "warning: uCache[%d] %p nrefs(%d) != 1 (%s %s)\n"
 msgstr ""
 
-#: lib/url.c:218
+#: rpmio/url.c:218
 #, c-format
 msgid "Password for %s@%s: "
 msgstr "Heslo pro %s@%s: "
 
-#: lib/url.c:243 lib/url.c:269
+#: rpmio/url.c:243 rpmio/url.c:269
 #, fuzzy, c-format
 msgid "error: %sport must be a number\n"
 msgstr "chyba: ftpport musí být èíslo\n"
 
-#: lib/url.c:405
+#: rpmio/url.c:405
 #, fuzzy
 msgid "url port must be a number\n"
 msgstr "chyba: ftpport musí být èíslo\n"
 
 #. XXX Fstrerror
-#: lib/url.c:462
+#: rpmio/url.c:462
 #, fuzzy, c-format
 msgid "failed to create %s: %s\n"
 msgstr "%s nelze vytvoøit\n"
 
-#: lib/verify.c:39
-#, fuzzy
-msgid "don't verify files in package"
-msgstr "binární balíèek starého typu\n"
-
-#: lib/verify.c:215
-msgid "package lacks both user name and id lists (this should never happen)"
-msgstr ""
-
-#: lib/verify.c:233
-msgid "package lacks both group name and id lists (this should never happen)"
-msgstr ""
-
-#: lib/verify.c:269
-#, c-format
-msgid "missing    %s\n"
-msgstr "chybí      %s\n"
-
-#: lib/verify.c:331
-#, c-format
-msgid "Unsatisfied dependencies for %s-%s-%s: "
-msgstr "Nevyøe¹ené závislosti pro %s-%s-%s: "
-
 #, fuzzy
 #~ msgid "cannot retrieve package \"%s\" from db"
 #~ msgstr "chyba: nelze otevøít %s%s/packages.rpm\n"
index cc3d298..3636274 100644 (file)
--- a/po/de.po
+++ b/po/de.po
@@ -37,7 +37,7 @@
 msgid ""
 msgstr ""
 "Project-Id-Version: rpm 2.5.2\n"
-"POT-Creation-Date: 2000-06-06 15:54-0400\n"
+"POT-Creation-Date: 2000-06-07 14:46-0400\n"
 "PO-Revision-Date: 1998-08-03 18:02+02:00\n"
 "Last-Translator: Karl Eichwalder <ke@SuSE.DE>\n"
 "Language-Team: German <de@li.org>\n"
@@ -2659,7 +2659,7 @@ msgid "opening db file        %s mode 0x%x\n"
 msgstr "Datenbank aus der vorhandenen neu erstellen"
 
 # , c-format
-#: lib/db1.c:430 lib/url.c:445
+#: lib/db1.c:430 rpmio/url.c:445
 #, fuzzy, c-format
 msgid "failed to open %s: %s\n"
 msgstr "Öffnen von %s fehlgeschlagen: %s"
@@ -3874,71 +3874,6 @@ msgstr "Fehler: kann %s nicht 
 msgid "Installing %s\n"
 msgstr "Installiere %s\n"
 
-#: lib/rpmio.c:796
-msgid "Success"
-msgstr ""
-
-#: lib/rpmio.c:799
-#, fuzzy
-msgid "Bad server response"
-msgstr "Nicht passende Antwort des FTP-Servers"
-
-#: lib/rpmio.c:802
-#, fuzzy
-msgid "Server IO error"
-msgstr "FTP IO-Fehler"
-
-#: lib/rpmio.c:805
-#, fuzzy
-msgid "Server timeout"
-msgstr "Timeout des FTP-Servers"
-
-#: lib/rpmio.c:808
-#, fuzzy
-msgid "Unable to lookup server host address"
-msgstr "Unmöglich die Hostadresse des FTP-Servers zu bestimmen"
-
-#: lib/rpmio.c:811
-#, fuzzy
-msgid "Unable to lookup server host name"
-msgstr "Unmöglich den Hostnamen des FTP-Servers zu bestimmen"
-
-#: lib/rpmio.c:814
-#, fuzzy
-msgid "Failed to connect to server"
-msgstr "Verbindung zum FTP-Server fehlgeschlagen"
-
-#: lib/rpmio.c:817
-#, fuzzy
-msgid "Failed to establish data connection to server"
-msgstr "Aufbau einer Datenverbindung zum FTP-Server fehlgeschlagen"
-
-#: lib/rpmio.c:820
-msgid "IO error to local file"
-msgstr "IO-Fehler bei lokaler Datei"
-
-#: lib/rpmio.c:823
-msgid "Error setting remote server to passive mode"
-msgstr "Fehler beim Setzen des FTP-Servers in den passiven Modus"
-
-#: lib/rpmio.c:826
-msgid "File not found on server"
-msgstr "Datei auf dem Server nicht gefunden"
-
-#: lib/rpmio.c:829
-msgid "Abort in progress"
-msgstr ""
-
-#: lib/rpmio.c:833
-#, fuzzy
-msgid "Unknown or unexpected error"
-msgstr "FTP Unbekannter oder nicht erwarteter Fehler"
-
-#: lib/rpmio.c:1366
-#, c-format
-msgid "logging into %s as %s, pw %s\n"
-msgstr ""
-
 #: lib/rpmlead.c:48
 #, c-format
 msgid "read failed: %s (%d)"
@@ -4240,66 +4175,131 @@ msgstr ""
 msgid "execution of script failed"
 msgstr "Ausführung des Skripts fehlgeschlagen"
 
-#: lib/url.c:88
+#: lib/verify.c:39
+#, fuzzy
+msgid "don't verify files in package"
+msgstr "Paket installieren"
+
+#: lib/verify.c:215
+msgid "package lacks both user name and id lists (this should never happen)"
+msgstr ""
+
+#: lib/verify.c:233
+msgid "package lacks both group name and id lists (this should never happen)"
+msgstr ""
+
+#: lib/verify.c:269
+#, fuzzy, c-format
+msgid "missing    %s\n"
+msgstr "fehlende { nach %{"
+
+#: lib/verify.c:331
+#, c-format
+msgid "Unsatisfied dependencies for %s-%s-%s: "
+msgstr "Nicht erfüllte Abhängigkeiten von %s-%s-%s: "
+
+#: rpmio/rpmio.c:796
+msgid "Success"
+msgstr ""
+
+#: rpmio/rpmio.c:799
+#, fuzzy
+msgid "Bad server response"
+msgstr "Nicht passende Antwort des FTP-Servers"
+
+#: rpmio/rpmio.c:802
+#, fuzzy
+msgid "Server IO error"
+msgstr "FTP IO-Fehler"
+
+#: rpmio/rpmio.c:805
+#, fuzzy
+msgid "Server timeout"
+msgstr "Timeout des FTP-Servers"
+
+#: rpmio/rpmio.c:808
+#, fuzzy
+msgid "Unable to lookup server host address"
+msgstr "Unmöglich die Hostadresse des FTP-Servers zu bestimmen"
+
+#: rpmio/rpmio.c:811
+#, fuzzy
+msgid "Unable to lookup server host name"
+msgstr "Unmöglich den Hostnamen des FTP-Servers zu bestimmen"
+
+#: rpmio/rpmio.c:814
+#, fuzzy
+msgid "Failed to connect to server"
+msgstr "Verbindung zum FTP-Server fehlgeschlagen"
+
+#: rpmio/rpmio.c:817
+#, fuzzy
+msgid "Failed to establish data connection to server"
+msgstr "Aufbau einer Datenverbindung zum FTP-Server fehlgeschlagen"
+
+#: rpmio/rpmio.c:820
+msgid "IO error to local file"
+msgstr "IO-Fehler bei lokaler Datei"
+
+#: rpmio/rpmio.c:823
+msgid "Error setting remote server to passive mode"
+msgstr "Fehler beim Setzen des FTP-Servers in den passiven Modus"
+
+#: rpmio/rpmio.c:826
+msgid "File not found on server"
+msgstr "Datei auf dem Server nicht gefunden"
+
+#: rpmio/rpmio.c:829
+msgid "Abort in progress"
+msgstr ""
+
+#: rpmio/rpmio.c:833
+#, fuzzy
+msgid "Unknown or unexpected error"
+msgstr "FTP Unbekannter oder nicht erwarteter Fehler"
+
+#: rpmio/rpmio.c:1366
+#, c-format
+msgid "logging into %s as %s, pw %s\n"
+msgstr ""
+
+#: rpmio/url.c:88
 #, c-format
 msgid "warning: u %p ctrl %p nrefs != 0 (%s %s)\n"
 msgstr ""
 
-#: lib/url.c:105
+#: rpmio/url.c:105
 #, c-format
 msgid "warning: u %p data %p nrefs != 0 (%s %s)\n"
 msgstr ""
 
-#: lib/url.c:132
+#: rpmio/url.c:132
 #, c-format
 msgid "warning: uCache[%d] %p nrefs(%d) != 1 (%s %s)\n"
 msgstr ""
 
-#: lib/url.c:218
+#: rpmio/url.c:218
 #, c-format
 msgid "Password for %s@%s: "
 msgstr "Passworf für %s@%s: "
 
-#: lib/url.c:243 lib/url.c:269
+#: rpmio/url.c:243 rpmio/url.c:269
 #, fuzzy, c-format
 msgid "error: %sport must be a number\n"
 msgstr "Fehler: der FTP-Port muss eine Zahl sein\n"
 
-#: lib/url.c:405
+#: rpmio/url.c:405
 #, fuzzy
 msgid "url port must be a number\n"
 msgstr "Fehler: der FTP-Port muss eine Zahl sein\n"
 
 # , c-format
 #. XXX Fstrerror
-#: lib/url.c:462
+#: rpmio/url.c:462
 #, fuzzy, c-format
 msgid "failed to create %s: %s\n"
 msgstr "anlegen von %s fehlgeschlagen\n"
 
-#: lib/verify.c:39
-#, fuzzy
-msgid "don't verify files in package"
-msgstr "Paket installieren"
-
-#: lib/verify.c:215
-msgid "package lacks both user name and id lists (this should never happen)"
-msgstr ""
-
-#: lib/verify.c:233
-msgid "package lacks both group name and id lists (this should never happen)"
-msgstr ""
-
-#: lib/verify.c:269
-#, fuzzy, c-format
-msgid "missing    %s\n"
-msgstr "fehlende { nach %{"
-
-#: lib/verify.c:331
-#, c-format
-msgid "Unsatisfied dependencies for %s-%s-%s: "
-msgstr "Nicht erfüllte Abhängigkeiten von %s-%s-%s: "
-
 #, fuzzy
 #~ msgid "cannot retrieve package \"%s\" from db"
 #~ msgstr "Fehler: kann nicht öffnen %s%s/packages.rpm\n"
index fc3ad8f..e4f777f 100644 (file)
--- a/po/fi.po
+++ b/po/fi.po
@@ -1,6 +1,6 @@
 msgid ""
 msgstr ""
-"POT-Creation-Date: 2000-06-06 15:54-0400\n"
+"POT-Creation-Date: 2000-06-07 14:46-0400\n"
 "Last-Translator: Raimo Koski <rkoski@pp.weppi.fi>\n"
 "Language-Team: Finnish <linux@sot.com>\n"
 "Content-Type: text/plain; charset=\n"
@@ -2600,7 +2600,7 @@ msgstr "en voinut avata %s: %s"
 msgid "opening db file        %s mode 0x%x\n"
 msgstr "kokoa tietokanta uudelleen vanhasta tietokannasta"
 
-#: lib/db1.c:430 lib/url.c:445
+#: lib/db1.c:430 rpmio/url.c:445
 #, fuzzy, c-format
 msgid "failed to open %s: %s\n"
 msgstr "en voinut avata %s: %s"
@@ -3794,71 +3794,6 @@ msgstr "virhe: en voi avata %s\n"
 msgid "Installing %s\n"
 msgstr "Asennan: %s\n"
 
-#: lib/rpmio.c:796
-msgid "Success"
-msgstr ""
-
-#: lib/rpmio.c:799
-#, fuzzy
-msgid "Bad server response"
-msgstr "Virheellinen FTP-palvelijan vastaus"
-
-#: lib/rpmio.c:802
-#, fuzzy
-msgid "Server IO error"
-msgstr "FTP:n IO-virhe"
-
-#: lib/rpmio.c:805
-#, fuzzy
-msgid "Server timeout"
-msgstr "FTP-palvelimen timeout"
-
-#: lib/rpmio.c:808
-#, fuzzy
-msgid "Unable to lookup server host address"
-msgstr "FTP-palvelimen osoitetta ei löytynyt"
-
-#: lib/rpmio.c:811
-#, fuzzy
-msgid "Unable to lookup server host name"
-msgstr "FTP-palvelimen nimeä ei löytynyt"
-
-#: lib/rpmio.c:814
-#, fuzzy
-msgid "Failed to connect to server"
-msgstr "En saanut yhteyttä FTP-palvelijaan"
-
-#: lib/rpmio.c:817
-#, fuzzy
-msgid "Failed to establish data connection to server"
-msgstr "En saanut data-yhteyttä FTP-palvelijaan"
-
-#: lib/rpmio.c:820
-msgid "IO error to local file"
-msgstr "Paikallisen tiedoston IO-virhe"
-
-#: lib/rpmio.c:823
-msgid "Error setting remote server to passive mode"
-msgstr "Virhe asetettaessa palvelinta passiiviin moodiin"
-
-#: lib/rpmio.c:826
-msgid "File not found on server"
-msgstr "Tiedostoa ei löytynyt palvelimelta"
-
-#: lib/rpmio.c:829
-msgid "Abort in progress"
-msgstr ""
-
-#: lib/rpmio.c:833
-#, fuzzy
-msgid "Unknown or unexpected error"
-msgstr "FTP:n tuntematon tai odottamaton virhe"
-
-#: lib/rpmio.c:1366
-#, c-format
-msgid "logging into %s as %s, pw %s\n"
-msgstr ""
-
 #: lib/rpmlead.c:48
 #, c-format
 msgid "read failed: %s (%d)"
@@ -4156,65 +4091,130 @@ msgstr ""
 msgid "execution of script failed"
 msgstr "skriptin ajo epäonnistui"
 
-#: lib/url.c:88
+#: lib/verify.c:39
+#, fuzzy
+msgid "don't verify files in package"
+msgstr "asenna paketti"
+
+#: lib/verify.c:215
+msgid "package lacks both user name and id lists (this should never happen)"
+msgstr ""
+
+#: lib/verify.c:233
+msgid "package lacks both group name and id lists (this should never happen)"
+msgstr ""
+
+#: lib/verify.c:269
+#, fuzzy, c-format
+msgid "missing    %s\n"
+msgstr "puuttuva '{' '%':n jälkeen"
+
+#: lib/verify.c:331
+#, c-format
+msgid "Unsatisfied dependencies for %s-%s-%s: "
+msgstr "%s-%s-%s:n tyydyttämättömät riippuvuudet:"
+
+#: rpmio/rpmio.c:796
+msgid "Success"
+msgstr ""
+
+#: rpmio/rpmio.c:799
+#, fuzzy
+msgid "Bad server response"
+msgstr "Virheellinen FTP-palvelijan vastaus"
+
+#: rpmio/rpmio.c:802
+#, fuzzy
+msgid "Server IO error"
+msgstr "FTP:n IO-virhe"
+
+#: rpmio/rpmio.c:805
+#, fuzzy
+msgid "Server timeout"
+msgstr "FTP-palvelimen timeout"
+
+#: rpmio/rpmio.c:808
+#, fuzzy
+msgid "Unable to lookup server host address"
+msgstr "FTP-palvelimen osoitetta ei löytynyt"
+
+#: rpmio/rpmio.c:811
+#, fuzzy
+msgid "Unable to lookup server host name"
+msgstr "FTP-palvelimen nimeä ei löytynyt"
+
+#: rpmio/rpmio.c:814
+#, fuzzy
+msgid "Failed to connect to server"
+msgstr "En saanut yhteyttä FTP-palvelijaan"
+
+#: rpmio/rpmio.c:817
+#, fuzzy
+msgid "Failed to establish data connection to server"
+msgstr "En saanut data-yhteyttä FTP-palvelijaan"
+
+#: rpmio/rpmio.c:820
+msgid "IO error to local file"
+msgstr "Paikallisen tiedoston IO-virhe"
+
+#: rpmio/rpmio.c:823
+msgid "Error setting remote server to passive mode"
+msgstr "Virhe asetettaessa palvelinta passiiviin moodiin"
+
+#: rpmio/rpmio.c:826
+msgid "File not found on server"
+msgstr "Tiedostoa ei löytynyt palvelimelta"
+
+#: rpmio/rpmio.c:829
+msgid "Abort in progress"
+msgstr ""
+
+#: rpmio/rpmio.c:833
+#, fuzzy
+msgid "Unknown or unexpected error"
+msgstr "FTP:n tuntematon tai odottamaton virhe"
+
+#: rpmio/rpmio.c:1366
+#, c-format
+msgid "logging into %s as %s, pw %s\n"
+msgstr ""
+
+#: rpmio/url.c:88
 #, c-format
 msgid "warning: u %p ctrl %p nrefs != 0 (%s %s)\n"
 msgstr ""
 
-#: lib/url.c:105
+#: rpmio/url.c:105
 #, c-format
 msgid "warning: u %p data %p nrefs != 0 (%s %s)\n"
 msgstr ""
 
-#: lib/url.c:132
+#: rpmio/url.c:132
 #, c-format
 msgid "warning: uCache[%d] %p nrefs(%d) != 1 (%s %s)\n"
 msgstr ""
 
-#: lib/url.c:218
+#: rpmio/url.c:218
 #, c-format
 msgid "Password for %s@%s: "
 msgstr "%s@%s:n salasana: "
 
-#: lib/url.c:243 lib/url.c:269
+#: rpmio/url.c:243 rpmio/url.c:269
 #, fuzzy, c-format
 msgid "error: %sport must be a number\n"
 msgstr "virhe: ftpport pitää olla luku\n"
 
-#: lib/url.c:405
+#: rpmio/url.c:405
 #, fuzzy
 msgid "url port must be a number\n"
 msgstr "virhe: ftpport pitää olla luku\n"
 
 #. XXX Fstrerror
-#: lib/url.c:462
+#: rpmio/url.c:462
 #, fuzzy, c-format
 msgid "failed to create %s: %s\n"
 msgstr "%s:n luonti epäonnistui\n"
 
-#: lib/verify.c:39
-#, fuzzy
-msgid "don't verify files in package"
-msgstr "asenna paketti"
-
-#: lib/verify.c:215
-msgid "package lacks both user name and id lists (this should never happen)"
-msgstr ""
-
-#: lib/verify.c:233
-msgid "package lacks both group name and id lists (this should never happen)"
-msgstr ""
-
-#: lib/verify.c:269
-#, fuzzy, c-format
-msgid "missing    %s\n"
-msgstr "puuttuva '{' '%':n jälkeen"
-
-#: lib/verify.c:331
-#, c-format
-msgid "Unsatisfied dependencies for %s-%s-%s: "
-msgstr "%s-%s-%s:n tyydyttämättömät riippuvuudet:"
-
 #, fuzzy
 #~ msgid "cannot retrieve package \"%s\" from db"
 #~ msgstr "virhe: en voi avata %s%s/packages.rpm\n"
index 14d432f..caed422 100644 (file)
--- a/po/fr.po
+++ b/po/fr.po
@@ -1,5 +1,5 @@
 msgid ""
-msgstr "POT-Creation-Date: 2000-06-06 15:54-0400\n"
+msgstr "POT-Creation-Date: 2000-06-07 14:46-0400\n"
 
 #: build.c:25 lib/rpminstall.c:250 lib/rpminstall.c:422
 #, c-format
@@ -2583,7 +2583,7 @@ msgstr "impossible d'ouvrir: %s\n"
 msgid "opening db file        %s mode 0x%x\n"
 msgstr "impossible d'ouvrir: %s\n"
 
-#: lib/db1.c:430 lib/url.c:445
+#: lib/db1.c:430 rpmio/url.c:445
 #, fuzzy, c-format
 msgid "failed to open %s: %s\n"
 msgstr "impossible d'ouvrir: %s\n"
@@ -3777,63 +3777,6 @@ msgstr "impossible d'ouvrir: %s\n"
 msgid "Installing %s\n"
 msgstr ""
 
-#: lib/rpmio.c:796
-msgid "Success"
-msgstr ""
-
-#: lib/rpmio.c:799
-msgid "Bad server response"
-msgstr ""
-
-#: lib/rpmio.c:802
-msgid "Server IO error"
-msgstr ""
-
-#: lib/rpmio.c:805
-msgid "Server timeout"
-msgstr ""
-
-#: lib/rpmio.c:808
-msgid "Unable to lookup server host address"
-msgstr ""
-
-#: lib/rpmio.c:811
-msgid "Unable to lookup server host name"
-msgstr ""
-
-#: lib/rpmio.c:814
-msgid "Failed to connect to server"
-msgstr ""
-
-#: lib/rpmio.c:817
-msgid "Failed to establish data connection to server"
-msgstr ""
-
-#: lib/rpmio.c:820
-msgid "IO error to local file"
-msgstr ""
-
-#: lib/rpmio.c:823
-msgid "Error setting remote server to passive mode"
-msgstr ""
-
-#: lib/rpmio.c:826
-msgid "File not found on server"
-msgstr ""
-
-#: lib/rpmio.c:829
-msgid "Abort in progress"
-msgstr ""
-
-#: lib/rpmio.c:833
-msgid "Unknown or unexpected error"
-msgstr ""
-
-#: lib/rpmio.c:1366
-#, c-format
-msgid "logging into %s as %s, pw %s\n"
-msgstr ""
-
 #: lib/rpmlead.c:48
 #, c-format
 msgid "read failed: %s (%d)"
@@ -4125,63 +4068,120 @@ msgstr ""
 msgid "execution of script failed"
 msgstr ""
 
-#: lib/url.c:88
+#: lib/verify.c:39
+msgid "don't verify files in package"
+msgstr ""
+
+#: lib/verify.c:215
+msgid "package lacks both user name and id lists (this should never happen)"
+msgstr ""
+
+#: lib/verify.c:233
+msgid "package lacks both group name and id lists (this should never happen)"
+msgstr ""
+
+#: lib/verify.c:269
+#, c-format
+msgid "missing    %s\n"
+msgstr ""
+
+#: lib/verify.c:331
+#, c-format
+msgid "Unsatisfied dependencies for %s-%s-%s: "
+msgstr ""
+
+#: rpmio/rpmio.c:796
+msgid "Success"
+msgstr ""
+
+#: rpmio/rpmio.c:799
+msgid "Bad server response"
+msgstr ""
+
+#: rpmio/rpmio.c:802
+msgid "Server IO error"
+msgstr ""
+
+#: rpmio/rpmio.c:805
+msgid "Server timeout"
+msgstr ""
+
+#: rpmio/rpmio.c:808
+msgid "Unable to lookup server host address"
+msgstr ""
+
+#: rpmio/rpmio.c:811
+msgid "Unable to lookup server host name"
+msgstr ""
+
+#: rpmio/rpmio.c:814
+msgid "Failed to connect to server"
+msgstr ""
+
+#: rpmio/rpmio.c:817
+msgid "Failed to establish data connection to server"
+msgstr ""
+
+#: rpmio/rpmio.c:820
+msgid "IO error to local file"
+msgstr ""
+
+#: rpmio/rpmio.c:823
+msgid "Error setting remote server to passive mode"
+msgstr ""
+
+#: rpmio/rpmio.c:826
+msgid "File not found on server"
+msgstr ""
+
+#: rpmio/rpmio.c:829
+msgid "Abort in progress"
+msgstr ""
+
+#: rpmio/rpmio.c:833
+msgid "Unknown or unexpected error"
+msgstr ""
+
+#: rpmio/rpmio.c:1366
+#, c-format
+msgid "logging into %s as %s, pw %s\n"
+msgstr ""
+
+#: rpmio/url.c:88
 #, c-format
 msgid "warning: u %p ctrl %p nrefs != 0 (%s %s)\n"
 msgstr ""
 
-#: lib/url.c:105
+#: rpmio/url.c:105
 #, c-format
 msgid "warning: u %p data %p nrefs != 0 (%s %s)\n"
 msgstr ""
 
-#: lib/url.c:132
+#: rpmio/url.c:132
 #, c-format
 msgid "warning: uCache[%d] %p nrefs(%d) != 1 (%s %s)\n"
 msgstr ""
 
-#: lib/url.c:218
+#: rpmio/url.c:218
 #, c-format
 msgid "Password for %s@%s: "
 msgstr ""
 
-#: lib/url.c:243 lib/url.c:269
+#: rpmio/url.c:243 rpmio/url.c:269
 #, c-format
 msgid "error: %sport must be a number\n"
 msgstr ""
 
-#: lib/url.c:405
+#: rpmio/url.c:405
 msgid "url port must be a number\n"
 msgstr ""
 
 #. XXX Fstrerror
-#: lib/url.c:462
+#: rpmio/url.c:462
 #, fuzzy, c-format
 msgid "failed to create %s: %s\n"
 msgstr "impossible d'ouvrir: %s\n"
 
-#: lib/verify.c:39
-msgid "don't verify files in package"
-msgstr ""
-
-#: lib/verify.c:215
-msgid "package lacks both user name and id lists (this should never happen)"
-msgstr ""
-
-#: lib/verify.c:233
-msgid "package lacks both group name and id lists (this should never happen)"
-msgstr ""
-
-#: lib/verify.c:269
-#, c-format
-msgid "missing    %s\n"
-msgstr ""
-
-#: lib/verify.c:331
-#, c-format
-msgid "Unsatisfied dependencies for %s-%s-%s: "
-msgstr ""
-
 #, fuzzy
 #~ msgid "cannot retrieve package \"%s\" from db"
 #~ msgstr "impossible d'ouvrir: %s\n"
index 9b2423b..24abf1c 100644 (file)
--- a/po/ja.po
+++ b/po/ja.po
@@ -6,7 +6,7 @@
 msgid ""
 msgstr ""
 "Project-Id-Version: rpm-3.0.4\n"
-"POT-Creation-Date: 2000-06-06 15:54-0400\n"
+"POT-Creation-Date: 2000-06-07 14:46-0400\n"
 "PO-Revision-Date: 1999-12-01 22:49 +JST\n"
 "Last-Translator: Kanda Mitsuru <kanda@nn.iij4u.or.jp>\n"
 "Language-Team: JRPM <jrpm@linux.or.jp>\n"
@@ -127,7 +127,7 @@ msgstr "copyright 
 # build root [BuildRoot]
 # net share [¥Í¥Ã¥È¶¦Í­]
 # reloate [ºÆÇÛÃÖ/°ÜÆ°¤¹¤ë]
-# $Id: ja.po,v 1.68 2000/06/06 20:06:09 jbj Exp $
+# $Id: ja.po,v 1.69 2000/06/07 23:25:42 jbj Exp $
 #: rpm.c:179 rpmqv.c:257
 #, c-format
 msgid "rpm: %s\n"
@@ -2530,7 +2530,7 @@ msgstr "
 msgid "opening db file        %s mode 0x%x\n"
 msgstr "¥Ç¡¼¥¿¥Ù¡¼¥¹¥â¡¼¥É 0x%x ¤Î¥ª¡¼¥×¥ó (%s)\n"
 
-#: lib/db1.c:430 lib/url.c:445
+#: lib/db1.c:430 rpmio/url.c:445
 #, fuzzy, c-format
 msgid "failed to open %s: %s\n"
 msgstr "%s ¤Î¥ª¡¼¥×¥ó¤Ë¼ºÇÔ: %s"
@@ -3735,71 +3735,6 @@ msgstr "%s 
 msgid "Installing %s\n"
 msgstr "%s ¤ò¥¤¥ó¥¹¥È¡¼¥ëÃæ\n"
 
-#: lib/rpmio.c:796
-msgid "Success"
-msgstr "À®¸ù"
-
-#: lib/rpmio.c:799
-#, fuzzy
-msgid "Bad server response"
-msgstr "¥µ¡¼¥Ð¤«¤éÀµ¾ï¤Ê±þÅú¤¬¤¢¤ê¤Þ¤»¤ó"
-
-#: lib/rpmio.c:802
-#, fuzzy
-msgid "Server IO error"
-msgstr "¥µ¡¼¥Ð IO ¥¨¥é¡¼"
-
-#: lib/rpmio.c:805
-#, fuzzy
-msgid "Server timeout"
-msgstr "¥µ¡¼¥Ð¥¿¥¤¥à¥¢¥¦¥È"
-
-#: lib/rpmio.c:808
-#, fuzzy
-msgid "Unable to lookup server host address"
-msgstr "¥µ¡¼¥Ð¤Î¥Û¥¹¥È¥¢¥É¥ì¥¹¤òÄ´¤Ù¤é¤ì¤Þ¤»¤ó"
-
-#: lib/rpmio.c:811
-#, fuzzy
-msgid "Unable to lookup server host name"
-msgstr "¥µ¡¼¥Ð¤Î¥Û¥¹¥È̾¤òÄ´¤Ù¤é¤ì¤Þ¤»¤ó"
-
-#: lib/rpmio.c:814
-#, fuzzy
-msgid "Failed to connect to server"
-msgstr "¥µ¡¼¥Ð¤Ø¤ÎÀܳ¤Ë¼ºÇÔ¤·¤Þ¤·¤¿"
-
-#: lib/rpmio.c:817
-#, fuzzy
-msgid "Failed to establish data connection to server"
-msgstr "¥µ¡¼¥Ð¤È¤Î¥Ç¡¼¥¿¥³¥Í¥¯¥·¥ç¥ó¤Î³ÎΩ¤Ë¼ºÇÔ¤·¤Þ¤·¤¿"
-
-#: lib/rpmio.c:820
-msgid "IO error to local file"
-msgstr "¥í¡¼¥«¥ë¥Õ¥¡¥¤¥ë¤Î IO ¥¨¥é¡¼"
-
-#: lib/rpmio.c:823
-msgid "Error setting remote server to passive mode"
-msgstr "¥ê¥â¡¼¥È¥µ¡¼¥Ð¤Î¥Ñ¥Ã¥·¥Ö¥â¡¼¥ÉÀßÄꥨ¥é¡¼"
-
-#: lib/rpmio.c:826
-msgid "File not found on server"
-msgstr "¥µ¡¼¥Ð¾å¤Ë¥Õ¥¡¥¤¥ë¤¬¸«¤Ä¤«¤ê¤Þ¤»¤ó"
-
-#: lib/rpmio.c:829
-msgid "Abort in progress"
-msgstr "½èÍýÃæ¤Î¥¢¥Ü¡¼¥È"
-
-#: lib/rpmio.c:833
-#, fuzzy
-msgid "Unknown or unexpected error"
-msgstr "ÉÔÌÀ¤â¤·¤¯¤Ïͽ´ü¤»¤Ì¥¨¥é¡¼"
-
-#: lib/rpmio.c:1366
-#, c-format
-msgid "logging into %s as %s, pw %s\n"
-msgstr "%s ¤Ø %s pw %s ¤È¤·¤Æ¥í¥°¥¤¥óÃæ\n"
-
 #: lib/rpmlead.c:48
 #, c-format
 msgid "read failed: %s (%d)"
@@ -4098,69 +4033,134 @@ msgstr "
 msgid "execution of script failed"
 msgstr "¥¹¥¯¥ê¥×¥È¤Î¼Â¹Ô¤Ë¼ºÇÔ"
 
-#: lib/url.c:88
+#: lib/verify.c:39
+#, fuzzy
+msgid "don't verify files in package"
+msgstr "¥Ñ¥Ã¥±¡¼¥¸Ãæ¤Î¥Õ¥¡¥¤¥ë¤Î¸¡¾Ú¤ò¤·¤Þ¤»¤ó"
+
+#: lib/verify.c:215
+msgid "package lacks both user name and id lists (this should never happen)"
+msgstr ""
+"¥Ñ¥Ã¥±¡¼¥¸¤Ï ¥æ¡¼¥¶Ì¾¤È id "
+"¥ê¥¹¥È¤ÎξÊý¤¬·ç¤±¤Æ¤¤¤Þ¤¹(¤³¤ì¤Ï·è¤·¤Æµ¯¤­¤Æ¤Ï¤Ê¤é¤Ê¤¤)"
+
+#: lib/verify.c:233
+msgid "package lacks both group name and id lists (this should never happen)"
+msgstr ""
+"¥Ñ¥Ã¥±¡¼¥¸¤Ï¥°¥ë¡¼¥×̾¤È id "
+"¥ê¥¹¥È¤ÎξÊý¤¬·ç¤±¤Æ¤¤¤Þ¤¹(¤³¤ì¤Ï·è¤·¤Æµ¯¤­¤Æ¤Ï¤Ê¤é¤Ê¤¤)"
+
+#: lib/verify.c:269
+#, c-format
+msgid "missing    %s\n"
+msgstr "%s ¤¬¸«¤Ä¤«¤ê¤Þ¤»¤ó\n"
+
+#: lib/verify.c:331
+#, c-format
+msgid "Unsatisfied dependencies for %s-%s-%s: "
+msgstr "%s-%s-%s ¤Î¤¿¤á¤Î°Í¸À­¤òËþ¤¿¤·¤Æ¤¤¤Þ¤»¤ó:"
+
+#: rpmio/rpmio.c:796
+msgid "Success"
+msgstr "À®¸ù"
+
+#: rpmio/rpmio.c:799
+#, fuzzy
+msgid "Bad server response"
+msgstr "¥µ¡¼¥Ð¤«¤éÀµ¾ï¤Ê±þÅú¤¬¤¢¤ê¤Þ¤»¤ó"
+
+#: rpmio/rpmio.c:802
+#, fuzzy
+msgid "Server IO error"
+msgstr "¥µ¡¼¥Ð IO ¥¨¥é¡¼"
+
+#: rpmio/rpmio.c:805
+#, fuzzy
+msgid "Server timeout"
+msgstr "¥µ¡¼¥Ð¥¿¥¤¥à¥¢¥¦¥È"
+
+#: rpmio/rpmio.c:808
+#, fuzzy
+msgid "Unable to lookup server host address"
+msgstr "¥µ¡¼¥Ð¤Î¥Û¥¹¥È¥¢¥É¥ì¥¹¤òÄ´¤Ù¤é¤ì¤Þ¤»¤ó"
+
+#: rpmio/rpmio.c:811
+#, fuzzy
+msgid "Unable to lookup server host name"
+msgstr "¥µ¡¼¥Ð¤Î¥Û¥¹¥È̾¤òÄ´¤Ù¤é¤ì¤Þ¤»¤ó"
+
+#: rpmio/rpmio.c:814
+#, fuzzy
+msgid "Failed to connect to server"
+msgstr "¥µ¡¼¥Ð¤Ø¤ÎÀܳ¤Ë¼ºÇÔ¤·¤Þ¤·¤¿"
+
+#: rpmio/rpmio.c:817
+#, fuzzy
+msgid "Failed to establish data connection to server"
+msgstr "¥µ¡¼¥Ð¤È¤Î¥Ç¡¼¥¿¥³¥Í¥¯¥·¥ç¥ó¤Î³ÎΩ¤Ë¼ºÇÔ¤·¤Þ¤·¤¿"
+
+#: rpmio/rpmio.c:820
+msgid "IO error to local file"
+msgstr "¥í¡¼¥«¥ë¥Õ¥¡¥¤¥ë¤Î IO ¥¨¥é¡¼"
+
+#: rpmio/rpmio.c:823
+msgid "Error setting remote server to passive mode"
+msgstr "¥ê¥â¡¼¥È¥µ¡¼¥Ð¤Î¥Ñ¥Ã¥·¥Ö¥â¡¼¥ÉÀßÄꥨ¥é¡¼"
+
+#: rpmio/rpmio.c:826
+msgid "File not found on server"
+msgstr "¥µ¡¼¥Ð¾å¤Ë¥Õ¥¡¥¤¥ë¤¬¸«¤Ä¤«¤ê¤Þ¤»¤ó"
+
+#: rpmio/rpmio.c:829
+msgid "Abort in progress"
+msgstr "½èÍýÃæ¤Î¥¢¥Ü¡¼¥È"
+
+#: rpmio/rpmio.c:833
+#, fuzzy
+msgid "Unknown or unexpected error"
+msgstr "ÉÔÌÀ¤â¤·¤¯¤Ïͽ´ü¤»¤Ì¥¨¥é¡¼"
+
+#: rpmio/rpmio.c:1366
+#, c-format
+msgid "logging into %s as %s, pw %s\n"
+msgstr "%s ¤Ø %s pw %s ¤È¤·¤Æ¥í¥°¥¤¥óÃæ\n"
+
+#: rpmio/url.c:88
 #, c-format
 msgid "warning: u %p ctrl %p nrefs != 0 (%s %s)\n"
 msgstr ""
 
-#: lib/url.c:105
+#: rpmio/url.c:105
 #, c-format
 msgid "warning: u %p data %p nrefs != 0 (%s %s)\n"
 msgstr ""
 
-#: lib/url.c:132
+#: rpmio/url.c:132
 #, c-format
 msgid "warning: uCache[%d] %p nrefs(%d) != 1 (%s %s)\n"
 msgstr ""
 
-#: lib/url.c:218
+#: rpmio/url.c:218
 #, c-format
 msgid "Password for %s@%s: "
 msgstr "%s@%s ¤Î¥Ñ¥¹¥ï¡¼¥É:"
 
-#: lib/url.c:243 lib/url.c:269
+#: rpmio/url.c:243 rpmio/url.c:269
 #, fuzzy, c-format
 msgid "error: %sport must be a number\n"
 msgstr "¥¨¥é¡¼: %s¥Ý¡¼¥È¤Ï¿ô»ú¤Ç¤Ê¤±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó\n"
 
-#: lib/url.c:405
+#: rpmio/url.c:405
 #, fuzzy
 msgid "url port must be a number\n"
 msgstr "url ¥Ý¡¼¥È¤Ï¿ô»ú¤Ç¤Ê¤±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó\n"
 
 #. XXX Fstrerror
-#: lib/url.c:462
+#: rpmio/url.c:462
 #, fuzzy, c-format
 msgid "failed to create %s: %s\n"
 msgstr "%s ¤ÎºîÀ®¤Ë¼ºÇÔ¤·¤Þ¤·¤¿\n"
 
-#: lib/verify.c:39
-#, fuzzy
-msgid "don't verify files in package"
-msgstr "¥Ñ¥Ã¥±¡¼¥¸Ãæ¤Î¥Õ¥¡¥¤¥ë¤Î¸¡¾Ú¤ò¤·¤Þ¤»¤ó"
-
-#: lib/verify.c:215
-msgid "package lacks both user name and id lists (this should never happen)"
-msgstr ""
-"¥Ñ¥Ã¥±¡¼¥¸¤Ï ¥æ¡¼¥¶Ì¾¤È id "
-"¥ê¥¹¥È¤ÎξÊý¤¬·ç¤±¤Æ¤¤¤Þ¤¹(¤³¤ì¤Ï·è¤·¤Æµ¯¤­¤Æ¤Ï¤Ê¤é¤Ê¤¤)"
-
-#: lib/verify.c:233
-msgid "package lacks both group name and id lists (this should never happen)"
-msgstr ""
-"¥Ñ¥Ã¥±¡¼¥¸¤Ï¥°¥ë¡¼¥×̾¤È id "
-"¥ê¥¹¥È¤ÎξÊý¤¬·ç¤±¤Æ¤¤¤Þ¤¹(¤³¤ì¤Ï·è¤·¤Æµ¯¤­¤Æ¤Ï¤Ê¤é¤Ê¤¤)"
-
-#: lib/verify.c:269
-#, c-format
-msgid "missing    %s\n"
-msgstr "%s ¤¬¸«¤Ä¤«¤ê¤Þ¤»¤ó\n"
-
-#: lib/verify.c:331
-#, c-format
-msgid "Unsatisfied dependencies for %s-%s-%s: "
-msgstr "%s-%s-%s ¤Î¤¿¤á¤Î°Í¸À­¤òËþ¤¿¤·¤Æ¤¤¤Þ¤»¤ó:"
-
 #, fuzzy
 #~ msgid "cannot retrieve package \"%s\" from db"
 #~ msgstr "%s/packages.rpm ¤ò¥ª¡¼¥×¥ó¤Ç¤­¤Þ¤»¤ó\n"
index 109a86b..a44b532 100644 (file)
--- a/po/pl.po
+++ b/po/pl.po
@@ -8,7 +8,7 @@
 msgid ""
 msgstr ""
 "Project-Id-Version: rpm-3.0.2\n"
-"POT-Creation-Date: 2000-06-06 15:54-0400\n"
+"POT-Creation-Date: 2000-06-07 14:46-0400\n"
 "PO-Revision-Date: 1999-05-25 17:00+0100\n"
 "Last-Translator: Pawe³ Dziekoñski <pdziekonski@mml.ch.pwr.wroc.pl>\n"
 "Language-Team: Polish <pl@li.org>\n"
@@ -2537,7 +2537,7 @@ msgstr "b
 msgid "opening db file        %s mode 0x%x\n"
 msgstr "otwiernie bazê danych w trybie 0x%x w %s\n"
 
-#: lib/db1.c:430 lib/url.c:445
+#: lib/db1.c:430 rpmio/url.c:445
 #, fuzzy, c-format
 msgid "failed to open %s: %s\n"
 msgstr "nie mo¿na otworzyæ %s: %s"
@@ -3710,63 +3710,6 @@ msgstr "nie mo
 msgid "Installing %s\n"
 msgstr "Instalacja %s\n"
 
-#: lib/rpmio.c:796
-msgid "Success"
-msgstr "Sukces"
-
-#: lib/rpmio.c:799
-msgid "Bad server response"
-msgstr "B³êdna odpowied¼ serwera"
-
-#: lib/rpmio.c:802
-msgid "Server IO error"
-msgstr "B³±d WE/WY(IO) serwera"
-
-#: lib/rpmio.c:805
-msgid "Server timeout"
-msgstr "Przekroczony limit czasu serwera"
-
-#: lib/rpmio.c:808
-msgid "Unable to lookup server host address"
-msgstr "Nie mo¿na znale¼æ adresu serwera"
-
-#: lib/rpmio.c:811
-msgid "Unable to lookup server host name"
-msgstr "Nie mo¿na znale¼æ nazwy serwera"
-
-#: lib/rpmio.c:814
-msgid "Failed to connect to server"
-msgstr "Po³±czenie z serwerem nie powiod³o siê"
-
-#: lib/rpmio.c:817
-msgid "Failed to establish data connection to server"
-msgstr "Otwarcie transmisji danych z serwera nie powiod³o siê"
-
-#: lib/rpmio.c:820
-msgid "IO error to local file"
-msgstr "B³±d WE/WY(IO) na lokalnym pliku"
-
-#: lib/rpmio.c:823
-msgid "Error setting remote server to passive mode"
-msgstr "B³±d: ustawienie zdalnego serwera w tryb pasywny nie powiod³o siê"
-
-#: lib/rpmio.c:826
-msgid "File not found on server"
-msgstr "Plik nie zosta³ znaleziony na serwerze"
-
-#: lib/rpmio.c:829
-msgid "Abort in progress"
-msgstr "Przerywanie ..."
-
-#: lib/rpmio.c:833
-msgid "Unknown or unexpected error"
-msgstr "Nieznany lub nieoczekiwany b³±d"
-
-#: lib/rpmio.c:1366
-#, c-format
-msgid "logging into %s as %s, pw %s\n"
-msgstr "logowanie do %s jako %s, has³o %s\n"
-
 #: lib/rpmlead.c:48
 #, c-format
 msgid "read failed: %s (%d)"
@@ -4054,67 +3997,124 @@ msgstr "uruchamianie skryptu postinstalacyjnego (je
 msgid "execution of script failed"
 msgstr "wykonanie skryptu nie powiod³o siê"
 
-#: lib/url.c:88
+#: lib/verify.c:39
+msgid "don't verify files in package"
+msgstr "nie sprawdzaj plików pakietu"
+
+#: lib/verify.c:215
+msgid "package lacks both user name and id lists (this should never happen)"
+msgstr ""
+"pakiet nie specyfikuje ani nazwy u¿ytkownika ani list id (to nie powinno siê "
+"zdarzyæ)"
+
+#: lib/verify.c:233
+msgid "package lacks both group name and id lists (this should never happen)"
+msgstr ""
+"pakiet nie specyfikuje ani nazwy grupy ani list id (to nie powinno siê "
+"zdarzyæ)"
+
+#: lib/verify.c:269
+#, c-format
+msgid "missing    %s\n"
+msgstr "brak    %s\n"
+
+#: lib/verify.c:331
+#, c-format
+msgid "Unsatisfied dependencies for %s-%s-%s: "
+msgstr "Niespe³nione zale¿no¶ci dla %s-%s-%s: "
+
+#: rpmio/rpmio.c:796
+msgid "Success"
+msgstr "Sukces"
+
+#: rpmio/rpmio.c:799
+msgid "Bad server response"
+msgstr "B³êdna odpowied¼ serwera"
+
+#: rpmio/rpmio.c:802
+msgid "Server IO error"
+msgstr "B³±d WE/WY(IO) serwera"
+
+#: rpmio/rpmio.c:805
+msgid "Server timeout"
+msgstr "Przekroczony limit czasu serwera"
+
+#: rpmio/rpmio.c:808
+msgid "Unable to lookup server host address"
+msgstr "Nie mo¿na znale¼æ adresu serwera"
+
+#: rpmio/rpmio.c:811
+msgid "Unable to lookup server host name"
+msgstr "Nie mo¿na znale¼æ nazwy serwera"
+
+#: rpmio/rpmio.c:814
+msgid "Failed to connect to server"
+msgstr "Po³±czenie z serwerem nie powiod³o siê"
+
+#: rpmio/rpmio.c:817
+msgid "Failed to establish data connection to server"
+msgstr "Otwarcie transmisji danych z serwera nie powiod³o siê"
+
+#: rpmio/rpmio.c:820
+msgid "IO error to local file"
+msgstr "B³±d WE/WY(IO) na lokalnym pliku"
+
+#: rpmio/rpmio.c:823
+msgid "Error setting remote server to passive mode"
+msgstr "B³±d: ustawienie zdalnego serwera w tryb pasywny nie powiod³o siê"
+
+#: rpmio/rpmio.c:826
+msgid "File not found on server"
+msgstr "Plik nie zosta³ znaleziony na serwerze"
+
+#: rpmio/rpmio.c:829
+msgid "Abort in progress"
+msgstr "Przerywanie ..."
+
+#: rpmio/rpmio.c:833
+msgid "Unknown or unexpected error"
+msgstr "Nieznany lub nieoczekiwany b³±d"
+
+#: rpmio/rpmio.c:1366
+#, c-format
+msgid "logging into %s as %s, pw %s\n"
+msgstr "logowanie do %s jako %s, has³o %s\n"
+
+#: rpmio/url.c:88
 #, c-format
 msgid "warning: u %p ctrl %p nrefs != 0 (%s %s)\n"
 msgstr ""
 
-#: lib/url.c:105
+#: rpmio/url.c:105
 #, c-format
 msgid "warning: u %p data %p nrefs != 0 (%s %s)\n"
 msgstr ""
 
-#: lib/url.c:132
+#: rpmio/url.c:132
 #, c-format
 msgid "warning: uCache[%d] %p nrefs(%d) != 1 (%s %s)\n"
 msgstr ""
 
-#: lib/url.c:218
+#: rpmio/url.c:218
 #, c-format
 msgid "Password for %s@%s: "
 msgstr "Has³o dla %s@%s: "
 
-#: lib/url.c:243 lib/url.c:269
+#: rpmio/url.c:243 rpmio/url.c:269
 #, c-format
 msgid "error: %sport must be a number\n"
 msgstr "b³±d: %sport musi byæ liczb±\n"
 
-#: lib/url.c:405
+#: rpmio/url.c:405
 msgid "url port must be a number\n"
 msgstr "port musi byæ liczb±\n"
 
 #. XXX Fstrerror
-#: lib/url.c:462
+#: rpmio/url.c:462
 #, fuzzy, c-format
 msgid "failed to create %s: %s\n"
 msgstr "utworzenie %s nie powiod³o siê\n"
 
-#: lib/verify.c:39
-msgid "don't verify files in package"
-msgstr "nie sprawdzaj plików pakietu"
-
-#: lib/verify.c:215
-msgid "package lacks both user name and id lists (this should never happen)"
-msgstr ""
-"pakiet nie specyfikuje ani nazwy u¿ytkownika ani list id (to nie powinno siê "
-"zdarzyæ)"
-
-#: lib/verify.c:233
-msgid "package lacks both group name and id lists (this should never happen)"
-msgstr ""
-"pakiet nie specyfikuje ani nazwy grupy ani list id (to nie powinno siê "
-"zdarzyæ)"
-
-#: lib/verify.c:269
-#, c-format
-msgid "missing    %s\n"
-msgstr "brak    %s\n"
-
-#: lib/verify.c:331
-#, c-format
-msgid "Unsatisfied dependencies for %s-%s-%s: "
-msgstr "Niespe³nione zale¿no¶ci dla %s-%s-%s: "
-
 #, fuzzy
 #~ msgid "cannot retrieve package \"%s\" from db"
 #~ msgstr "nie mo¿na otworzyæ %s/packages.rpm\n"
index ec0baf4..6d9946c 100644 (file)
@@ -2,7 +2,7 @@
 # Revised by Arnaldo Carvalho de Melo <acme@conectiva.com.br>, 1998.
 #
 msgid ""
-msgstr "POT-Creation-Date: 2000-06-06 15:54-0400\n"
+msgstr "POT-Creation-Date: 2000-06-07 14:46-0400\n"
 
 #: build.c:25 lib/rpminstall.c:250 lib/rpminstall.c:422
 #, c-format
@@ -2662,7 +2662,7 @@ msgid "opening db file        %s mode 0x%x\n"
 msgstr "reconstrua o banco de dados a partir de um banco de dados existente"
 
 # , c-format
-#: lib/db1.c:430 lib/url.c:445
+#: lib/db1.c:430 rpmio/url.c:445
 #, fuzzy, c-format
 msgid "failed to open %s: %s\n"
 msgstr "Não consegui abrir: %s\n"
@@ -3890,63 +3890,6 @@ msgstr "N
 msgid "Installing %s\n"
 msgstr ""
 
-#: lib/rpmio.c:796
-msgid "Success"
-msgstr ""
-
-#: lib/rpmio.c:799
-msgid "Bad server response"
-msgstr ""
-
-#: lib/rpmio.c:802
-msgid "Server IO error"
-msgstr ""
-
-#: lib/rpmio.c:805
-msgid "Server timeout"
-msgstr ""
-
-#: lib/rpmio.c:808
-msgid "Unable to lookup server host address"
-msgstr ""
-
-#: lib/rpmio.c:811
-msgid "Unable to lookup server host name"
-msgstr ""
-
-#: lib/rpmio.c:814
-msgid "Failed to connect to server"
-msgstr ""
-
-#: lib/rpmio.c:817
-msgid "Failed to establish data connection to server"
-msgstr ""
-
-#: lib/rpmio.c:820
-msgid "IO error to local file"
-msgstr ""
-
-#: lib/rpmio.c:823
-msgid "Error setting remote server to passive mode"
-msgstr ""
-
-#: lib/rpmio.c:826
-msgid "File not found on server"
-msgstr ""
-
-#: lib/rpmio.c:829
-msgid "Abort in progress"
-msgstr ""
-
-#: lib/rpmio.c:833
-msgid "Unknown or unexpected error"
-msgstr ""
-
-#: lib/rpmio.c:1366
-#, c-format
-msgid "logging into %s as %s, pw %s\n"
-msgstr ""
-
 #: lib/rpmlead.c:48
 #, c-format
 msgid "read failed: %s (%d)"
@@ -4260,65 +4203,122 @@ msgstr ""
 msgid "execution of script failed"
 msgstr ""
 
-#: lib/url.c:88
+#: lib/verify.c:39
+#, fuzzy
+msgid "don't verify files in package"
+msgstr "instale pacote"
+
+#: lib/verify.c:215
+msgid "package lacks both user name and id lists (this should never happen)"
+msgstr ""
+
+#: lib/verify.c:233
+msgid "package lacks both group name and id lists (this should never happen)"
+msgstr ""
+
+#: lib/verify.c:269
+#, c-format
+msgid "missing    %s\n"
+msgstr ""
+
+#: lib/verify.c:331
+#, c-format
+msgid "Unsatisfied dependencies for %s-%s-%s: "
+msgstr ""
+
+#: rpmio/rpmio.c:796
+msgid "Success"
+msgstr ""
+
+#: rpmio/rpmio.c:799
+msgid "Bad server response"
+msgstr ""
+
+#: rpmio/rpmio.c:802
+msgid "Server IO error"
+msgstr ""
+
+#: rpmio/rpmio.c:805
+msgid "Server timeout"
+msgstr ""
+
+#: rpmio/rpmio.c:808
+msgid "Unable to lookup server host address"
+msgstr ""
+
+#: rpmio/rpmio.c:811
+msgid "Unable to lookup server host name"
+msgstr ""
+
+#: rpmio/rpmio.c:814
+msgid "Failed to connect to server"
+msgstr ""
+
+#: rpmio/rpmio.c:817
+msgid "Failed to establish data connection to server"
+msgstr ""
+
+#: rpmio/rpmio.c:820
+msgid "IO error to local file"
+msgstr ""
+
+#: rpmio/rpmio.c:823
+msgid "Error setting remote server to passive mode"
+msgstr ""
+
+#: rpmio/rpmio.c:826
+msgid "File not found on server"
+msgstr ""
+
+#: rpmio/rpmio.c:829
+msgid "Abort in progress"
+msgstr ""
+
+#: rpmio/rpmio.c:833
+msgid "Unknown or unexpected error"
+msgstr ""
+
+#: rpmio/rpmio.c:1366
+#, c-format
+msgid "logging into %s as %s, pw %s\n"
+msgstr ""
+
+#: rpmio/url.c:88
 #, c-format
 msgid "warning: u %p ctrl %p nrefs != 0 (%s %s)\n"
 msgstr ""
 
-#: lib/url.c:105
+#: rpmio/url.c:105
 #, c-format
 msgid "warning: u %p data %p nrefs != 0 (%s %s)\n"
 msgstr ""
 
-#: lib/url.c:132
+#: rpmio/url.c:132
 #, c-format
 msgid "warning: uCache[%d] %p nrefs(%d) != 1 (%s %s)\n"
 msgstr ""
 
-#: lib/url.c:218
+#: rpmio/url.c:218
 #, c-format
 msgid "Password for %s@%s: "
 msgstr ""
 
-#: lib/url.c:243 lib/url.c:269
+#: rpmio/url.c:243 rpmio/url.c:269
 #, c-format
 msgid "error: %sport must be a number\n"
 msgstr ""
 
-#: lib/url.c:405
+#: rpmio/url.c:405
 msgid "url port must be a number\n"
 msgstr ""
 
 # , c-format
 #. XXX Fstrerror
-#: lib/url.c:462
+#: rpmio/url.c:462
 #, fuzzy, c-format
 msgid "failed to create %s: %s\n"
 msgstr "Não consegui abrir o pipe tar: %s\n"
 
-#: lib/verify.c:39
-#, fuzzy
-msgid "don't verify files in package"
-msgstr "instale pacote"
-
-#: lib/verify.c:215
-msgid "package lacks both user name and id lists (this should never happen)"
-msgstr ""
-
-#: lib/verify.c:233
-msgid "package lacks both group name and id lists (this should never happen)"
-msgstr ""
-
-#: lib/verify.c:269
-#, c-format
-msgid "missing    %s\n"
-msgstr ""
-
-#: lib/verify.c:331
-#, c-format
-msgid "Unsatisfied dependencies for %s-%s-%s: "
-msgstr ""
-
 # , c-format
 #, fuzzy
 #~ msgid "cannot retrieve package \"%s\" from db"
index 83d1709..0519cde 100644 (file)
@@ -6,7 +6,7 @@
 msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
-"POT-Creation-Date: 2000-06-06 15:54-0400\n"
+"POT-Creation-Date: 2000-06-07 14:46-0400\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -2387,7 +2387,7 @@ msgstr ""
 msgid "opening db file        %s mode 0x%x\n"
 msgstr ""
 
-#: lib/db1.c:430 lib/url.c:445
+#: lib/db1.c:430 rpmio/url.c:445
 #, c-format
 msgid "failed to open %s: %s\n"
 msgstr ""
@@ -3540,63 +3540,6 @@ msgstr ""
 msgid "Installing %s\n"
 msgstr ""
 
-#: lib/rpmio.c:796
-msgid "Success"
-msgstr ""
-
-#: lib/rpmio.c:799
-msgid "Bad server response"
-msgstr ""
-
-#: lib/rpmio.c:802
-msgid "Server IO error"
-msgstr ""
-
-#: lib/rpmio.c:805
-msgid "Server timeout"
-msgstr ""
-
-#: lib/rpmio.c:808
-msgid "Unable to lookup server host address"
-msgstr ""
-
-#: lib/rpmio.c:811
-msgid "Unable to lookup server host name"
-msgstr ""
-
-#: lib/rpmio.c:814
-msgid "Failed to connect to server"
-msgstr ""
-
-#: lib/rpmio.c:817
-msgid "Failed to establish data connection to server"
-msgstr ""
-
-#: lib/rpmio.c:820
-msgid "IO error to local file"
-msgstr ""
-
-#: lib/rpmio.c:823
-msgid "Error setting remote server to passive mode"
-msgstr ""
-
-#: lib/rpmio.c:826
-msgid "File not found on server"
-msgstr ""
-
-#: lib/rpmio.c:829
-msgid "Abort in progress"
-msgstr ""
-
-#: lib/rpmio.c:833
-msgid "Unknown or unexpected error"
-msgstr ""
-
-#: lib/rpmio.c:1366
-#, c-format
-msgid "logging into %s as %s, pw %s\n"
-msgstr ""
-
 #: lib/rpmlead.c:48
 #, c-format
 msgid "read failed: %s (%d)"
@@ -3882,59 +3825,116 @@ msgstr ""
 msgid "execution of script failed"
 msgstr ""
 
-#: lib/url.c:88
-#, c-format
-msgid "warning: u %p ctrl %p nrefs != 0 (%s %s)\n"
+#: lib/verify.c:39
+msgid "don't verify files in package"
 msgstr ""
 
-#: lib/url.c:105
-#, c-format
-msgid "warning: u %p data %p nrefs != 0 (%s %s)\n"
+#: lib/verify.c:215
+msgid "package lacks both user name and id lists (this should never happen)"
 msgstr ""
 
-#: lib/url.c:132
-#, c-format
-msgid "warning: uCache[%d] %p nrefs(%d) != 1 (%s %s)\n"
+#: lib/verify.c:233
+msgid "package lacks both group name and id lists (this should never happen)"
 msgstr ""
 
-#: lib/url.c:218
+#: lib/verify.c:269
 #, c-format
-msgid "Password for %s@%s: "
+msgid "missing    %s\n"
 msgstr ""
 
-#: lib/url.c:243 lib/url.c:269
+#: lib/verify.c:331
 #, c-format
-msgid "error: %sport must be a number\n"
+msgid "Unsatisfied dependencies for %s-%s-%s: "
 msgstr ""
 
-#: lib/url.c:405
-msgid "url port must be a number\n"
+#: rpmio/rpmio.c:796
+msgid "Success"
 msgstr ""
 
-#. XXX Fstrerror
-#: lib/url.c:462
+#: rpmio/rpmio.c:799
+msgid "Bad server response"
+msgstr ""
+
+#: rpmio/rpmio.c:802
+msgid "Server IO error"
+msgstr ""
+
+#: rpmio/rpmio.c:805
+msgid "Server timeout"
+msgstr ""
+
+#: rpmio/rpmio.c:808
+msgid "Unable to lookup server host address"
+msgstr ""
+
+#: rpmio/rpmio.c:811
+msgid "Unable to lookup server host name"
+msgstr ""
+
+#: rpmio/rpmio.c:814
+msgid "Failed to connect to server"
+msgstr ""
+
+#: rpmio/rpmio.c:817
+msgid "Failed to establish data connection to server"
+msgstr ""
+
+#: rpmio/rpmio.c:820
+msgid "IO error to local file"
+msgstr ""
+
+#: rpmio/rpmio.c:823
+msgid "Error setting remote server to passive mode"
+msgstr ""
+
+#: rpmio/rpmio.c:826
+msgid "File not found on server"
+msgstr ""
+
+#: rpmio/rpmio.c:829
+msgid "Abort in progress"
+msgstr ""
+
+#: rpmio/rpmio.c:833
+msgid "Unknown or unexpected error"
+msgstr ""
+
+#: rpmio/rpmio.c:1366
 #, c-format
-msgid "failed to create %s: %s\n"
+msgid "logging into %s as %s, pw %s\n"
 msgstr ""
 
-#: lib/verify.c:39
-msgid "don't verify files in package"
+#: rpmio/url.c:88
+#, c-format
+msgid "warning: u %p ctrl %p nrefs != 0 (%s %s)\n"
 msgstr ""
 
-#: lib/verify.c:215
-msgid "package lacks both user name and id lists (this should never happen)"
+#: rpmio/url.c:105
+#, c-format
+msgid "warning: u %p data %p nrefs != 0 (%s %s)\n"
 msgstr ""
 
-#: lib/verify.c:233
-msgid "package lacks both group name and id lists (this should never happen)"
+#: rpmio/url.c:132
+#, c-format
+msgid "warning: uCache[%d] %p nrefs(%d) != 1 (%s %s)\n"
 msgstr ""
 
-#: lib/verify.c:269
+#: rpmio/url.c:218
 #, c-format
-msgid "missing    %s\n"
+msgid "Password for %s@%s: "
 msgstr ""
 
-#: lib/verify.c:331
+#: rpmio/url.c:243 rpmio/url.c:269
 #, c-format
-msgid "Unsatisfied dependencies for %s-%s-%s: "
+msgid "error: %sport must be a number\n"
+msgstr ""
+
+#: rpmio/url.c:405
+msgid "url port must be a number\n"
+msgstr ""
+
+#. XXX Fstrerror
+#: rpmio/url.c:462
+#, c-format
+msgid "failed to create %s: %s\n"
 msgstr ""
index a18fb75..2ef4805 100644 (file)
--- a/po/ru.po
+++ b/po/ru.po
@@ -1,6 +1,6 @@
 msgid ""
 msgstr ""
-"POT-Creation-Date: 2000-06-06 15:54-0400\n"
+"POT-Creation-Date: 2000-06-07 14:46-0400\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=koi8-r\n"
 "Content-Transfer-Encoding: 8bit\n"
@@ -2540,7 +2540,7 @@ msgstr "
 msgid "opening db file        %s mode 0x%x\n"
 msgstr "ÏÔËÒÙ×ÁÀ ÂÁÚÕ × ÒÅÖÉÍÅ 0x%x × %s\n"
 
-#: lib/db1.c:430 lib/url.c:445
+#: lib/db1.c:430 rpmio/url.c:445
 #, fuzzy, c-format
 msgid "failed to open %s: %s\n"
 msgstr "ÎÅ ÍÏÇÕ ÏÔËÒÙÔØ %s: %s"
@@ -3710,63 +3710,6 @@ msgstr "
 msgid "Installing %s\n"
 msgstr "õÓÔÁÎÁ×ÌÉ×ÁÀ %s\n"
 
-#: lib/rpmio.c:796
-msgid "Success"
-msgstr "õÄÁÌÏÓØ"
-
-#: lib/rpmio.c:799
-msgid "Bad server response"
-msgstr "îÅ×ÅÒÎÙÊ ÏÔ×ÅÔ ÓÅÒ×ÅÒÁ"
-
-#: lib/rpmio.c:802
-msgid "Server IO error"
-msgstr "ïÛÉÂËÁ ××ÏÄÁ/×Ù×ÏÄÁ ÓÅÒ×ÅÒÁ"
-
-#: lib/rpmio.c:805
-msgid "Server timeout"
-msgstr "ôÁÊÍÁÕÔ ÓÅÒ×ÅÒÁ"
-
-#: lib/rpmio.c:808
-msgid "Unable to lookup server host address"
-msgstr "îÅ ÍÏÇÕ ÎÁÊÔÉ IP-ÁÄÒÅÓ ÓÅÒ×ÅÒÁ"
-
-#: lib/rpmio.c:811
-msgid "Unable to lookup server host name"
-msgstr "îÅ ÍÏÇÕ ÎÁÊÔÉ ÉÍÑ ÓÅÒ×ÅÒÁ"
-
-#: lib/rpmio.c:814
-msgid "Failed to connect to server"
-msgstr "îÅ ÍÏÇÕ ÓÏÅÄÉÎÉÔØÓÑ Ó ÓÅÒ×ÅÒÏÍ"
-
-#: lib/rpmio.c:817
-msgid "Failed to establish data connection to server"
-msgstr "îÅ ÍÏÇÕ ÕÓÔÁÎÏ×ÉÔØ ÓÏÅÄÉÎÅÎÉÅ ÄÌÑ ÄÁÎÎÙÈ Ó ÓÅÒ×ÅÒÏÍ"
-
-#: lib/rpmio.c:820
-msgid "IO error to local file"
-msgstr "ïÛÉÂËÁ ××ÏÄÁ/×Ù×ÏÄÁ × ÌÏËÁÌØÎÙÊ ÆÁÊÌ"
-
-#: lib/rpmio.c:823
-msgid "Error setting remote server to passive mode"
-msgstr "ïÛÉÂËÁ ÐÒÉ ÐÅÒÅ×ÏÄÅ ÕÄÁÌÅÎÎÏÇÏ ÓÅÒ×ÅÒÁ × ÐÁÓÓÉ×ÎÙÊ ÒÅÖÉÍ"
-
-#: lib/rpmio.c:826
-msgid "File not found on server"
-msgstr "æÁÊÌ ÎÅ ÎÁÊÄÅΠÎÁ ÓÅÒ×ÅÒÅ"
-
-#: lib/rpmio.c:829
-msgid "Abort in progress"
-msgstr "ïÔÍÅÎÁ × ÐÒÏÃÅÓÓÅ"
-
-#: lib/rpmio.c:833
-msgid "Unknown or unexpected error"
-msgstr "îÅÉÚ×ÅÓÔÎÁÑ ÉÌÉ ÎÅÏÖÉÄÁÎÎÁÑ ÏÛÉÂËÁ"
-
-#: lib/rpmio.c:1366
-#, c-format
-msgid "logging into %s as %s, pw %s\n"
-msgstr "ÒÅÇÉÓÔÒÉÒÕÀÓØ × %s ËÁË %s, ÐÁÒÏÌØ %s\n"
-
 #: lib/rpmlead.c:48
 #, c-format
 msgid "read failed: %s (%d)"
@@ -4057,63 +4000,120 @@ msgstr "
 msgid "execution of script failed"
 msgstr "ÏÛÉÂËÁ ÉÓÐÏÌÎÅÎÉÑ ÓËÒÉÐÔÁ"
 
-#: lib/url.c:88
+#: lib/verify.c:39
+msgid "don't verify files in package"
+msgstr "ÎÅ ÐÒÏ×ÅÒÑÔØ ÆÁÊÌÙ ÐÁËÅÔÁ"
+
+#: lib/verify.c:215
+msgid "package lacks both user name and id lists (this should never happen)"
+msgstr "× ÐÁËÅÔÅ ÎÅÔ ÎÉ ÉÍÅΠÐÏÌØÚÏ×ÁÔÅÌÅÊ, ÎÉ ÉÈ ID (ÔÁË ÎÅ ÂÙ×ÁÅÔ)"
+
+#: lib/verify.c:233
+msgid "package lacks both group name and id lists (this should never happen)"
+msgstr "× ÐÁËÅÔÅ ÎÅÔ ÎÉ ÉÍÅΠÇÒÕÐÐ, ÎÉ ÉÈ ID (ÔÁË ÎÅ ÂÙ×ÁÅÔ)"
+
+#: lib/verify.c:269
+#, c-format
+msgid "missing    %s\n"
+msgstr "ÏÔÓÕÔÓÔ×ÕÅÔ %s\n"
+
+#: lib/verify.c:331
+#, c-format
+msgid "Unsatisfied dependencies for %s-%s-%s: "
+msgstr "îÅÕÄÏ×ÌÅÔ×ÏÒÅÎÎÙÅ ÚÁ×ÉÓÉÍÏÓÔÉ ÄÌÑ %s-%s-%s: "
+
+#: rpmio/rpmio.c:796
+msgid "Success"
+msgstr "õÄÁÌÏÓØ"
+
+#: rpmio/rpmio.c:799
+msgid "Bad server response"
+msgstr "îÅ×ÅÒÎÙÊ ÏÔ×ÅÔ ÓÅÒ×ÅÒÁ"
+
+#: rpmio/rpmio.c:802
+msgid "Server IO error"
+msgstr "ïÛÉÂËÁ ××ÏÄÁ/×Ù×ÏÄÁ ÓÅÒ×ÅÒÁ"
+
+#: rpmio/rpmio.c:805
+msgid "Server timeout"
+msgstr "ôÁÊÍÁÕÔ ÓÅÒ×ÅÒÁ"
+
+#: rpmio/rpmio.c:808
+msgid "Unable to lookup server host address"
+msgstr "îÅ ÍÏÇÕ ÎÁÊÔÉ IP-ÁÄÒÅÓ ÓÅÒ×ÅÒÁ"
+
+#: rpmio/rpmio.c:811
+msgid "Unable to lookup server host name"
+msgstr "îÅ ÍÏÇÕ ÎÁÊÔÉ ÉÍÑ ÓÅÒ×ÅÒÁ"
+
+#: rpmio/rpmio.c:814
+msgid "Failed to connect to server"
+msgstr "îÅ ÍÏÇÕ ÓÏÅÄÉÎÉÔØÓÑ Ó ÓÅÒ×ÅÒÏÍ"
+
+#: rpmio/rpmio.c:817
+msgid "Failed to establish data connection to server"
+msgstr "îÅ ÍÏÇÕ ÕÓÔÁÎÏ×ÉÔØ ÓÏÅÄÉÎÅÎÉÅ ÄÌÑ ÄÁÎÎÙÈ Ó ÓÅÒ×ÅÒÏÍ"
+
+#: rpmio/rpmio.c:820
+msgid "IO error to local file"
+msgstr "ïÛÉÂËÁ ××ÏÄÁ/×Ù×ÏÄÁ × ÌÏËÁÌØÎÙÊ ÆÁÊÌ"
+
+#: rpmio/rpmio.c:823
+msgid "Error setting remote server to passive mode"
+msgstr "ïÛÉÂËÁ ÐÒÉ ÐÅÒÅ×ÏÄÅ ÕÄÁÌÅÎÎÏÇÏ ÓÅÒ×ÅÒÁ × ÐÁÓÓÉ×ÎÙÊ ÒÅÖÉÍ"
+
+#: rpmio/rpmio.c:826
+msgid "File not found on server"
+msgstr "æÁÊÌ ÎÅ ÎÁÊÄÅΠÎÁ ÓÅÒ×ÅÒÅ"
+
+#: rpmio/rpmio.c:829
+msgid "Abort in progress"
+msgstr "ïÔÍÅÎÁ × ÐÒÏÃÅÓÓÅ"
+
+#: rpmio/rpmio.c:833
+msgid "Unknown or unexpected error"
+msgstr "îÅÉÚ×ÅÓÔÎÁÑ ÉÌÉ ÎÅÏÖÉÄÁÎÎÁÑ ÏÛÉÂËÁ"
+
+#: rpmio/rpmio.c:1366
+#, c-format
+msgid "logging into %s as %s, pw %s\n"
+msgstr "ÒÅÇÉÓÔÒÉÒÕÀÓØ × %s ËÁË %s, ÐÁÒÏÌØ %s\n"
+
+#: rpmio/url.c:88
 #, c-format
 msgid "warning: u %p ctrl %p nrefs != 0 (%s %s)\n"
 msgstr ""
 
-#: lib/url.c:105
+#: rpmio/url.c:105
 #, c-format
 msgid "warning: u %p data %p nrefs != 0 (%s %s)\n"
 msgstr ""
 
-#: lib/url.c:132
+#: rpmio/url.c:132
 #, c-format
 msgid "warning: uCache[%d] %p nrefs(%d) != 1 (%s %s)\n"
 msgstr ""
 
-#: lib/url.c:218
+#: rpmio/url.c:218
 #, c-format
 msgid "Password for %s@%s: "
 msgstr "ðÁÒÏÌØ ÄÌÑ %s@%s: "
 
-#: lib/url.c:243 lib/url.c:269
+#: rpmio/url.c:243 rpmio/url.c:269
 #, c-format
 msgid "error: %sport must be a number\n"
 msgstr "ÏÛÉÂËÁ: %sport ÄÏÌÖÅΠÂÙÔØ ÞÉÓÌÏÍ\n"
 
-#: lib/url.c:405
+#: rpmio/url.c:405
 msgid "url port must be a number\n"
 msgstr "url port ÄÏÌÖÅΠÂÙÔØ ÞÉÓÌÏÍ\n"
 
 #. XXX Fstrerror
-#: lib/url.c:462
+#: rpmio/url.c:462
 #, fuzzy, c-format
 msgid "failed to create %s: %s\n"
 msgstr "ÎÅ ÍÏÇÕ ÓÏÚÄÁÔØ %s\n"
 
-#: lib/verify.c:39
-msgid "don't verify files in package"
-msgstr "ÎÅ ÐÒÏ×ÅÒÑÔØ ÆÁÊÌÙ ÐÁËÅÔÁ"
-
-#: lib/verify.c:215
-msgid "package lacks both user name and id lists (this should never happen)"
-msgstr "× ÐÁËÅÔÅ ÎÅÔ ÎÉ ÉÍÅΠÐÏÌØÚÏ×ÁÔÅÌÅÊ, ÎÉ ÉÈ ID (ÔÁË ÎÅ ÂÙ×ÁÅÔ)"
-
-#: lib/verify.c:233
-msgid "package lacks both group name and id lists (this should never happen)"
-msgstr "× ÐÁËÅÔÅ ÎÅÔ ÎÉ ÉÍÅΠÇÒÕÐÐ, ÎÉ ÉÈ ID (ÔÁË ÎÅ ÂÙ×ÁÅÔ)"
-
-#: lib/verify.c:269
-#, c-format
-msgid "missing    %s\n"
-msgstr "ÏÔÓÕÔÓÔ×ÕÅÔ %s\n"
-
-#: lib/verify.c:331
-#, c-format
-msgid "Unsatisfied dependencies for %s-%s-%s: "
-msgstr "îÅÕÄÏ×ÌÅÔ×ÏÒÅÎÎÙÅ ÚÁ×ÉÓÉÍÏÓÔÉ ÄÌÑ %s-%s-%s: "
-
 #, fuzzy
 #~ msgid "cannot retrieve package \"%s\" from db"
 #~ msgstr "ÎÅ ÍÏÇÕ ÏÔËÒÙÔØ %s/packages.rpm\n"
index 1f592b6..1bda10e 100644 (file)
--- a/po/sk.po
+++ b/po/sk.po
@@ -1,7 +1,7 @@
 msgid ""
 msgstr ""
 "Project-Id-Version: rpm 2.93\n"
-"POT-Creation-Date: 2000-06-06 15:54-0400\n"
+"POT-Creation-Date: 2000-06-07 14:46-0400\n"
 "PO-Revision-Date: 1999-04-08 21:37+02:00\n"
 "Last-Translator: Stanislav Meduna <stano@eunet.sk>\n"
 "Language-Team: Slovak <sk-i18n@rak.isternet.sk>\n"
@@ -2544,7 +2544,7 @@ msgstr "chybn
 msgid "opening db file        %s mode 0x%x\n"
 msgstr "otvára sa databáza s právami 0x%x v %s\n"
 
-#: lib/db1.c:430 lib/url.c:445
+#: lib/db1.c:430 rpmio/url.c:445
 #, fuzzy, c-format
 msgid "failed to open %s: %s\n"
 msgstr "nepodarilo sa otvori» %s: %s"
@@ -3717,63 +3717,6 @@ msgstr "nie je mo
 msgid "Installing %s\n"
 msgstr "In¹taluje sa %s\n"
 
-#: lib/rpmio.c:796
-msgid "Success"
-msgstr "Úspech"
-
-#: lib/rpmio.c:799
-msgid "Bad server response"
-msgstr "Chybná odpoveï servera"
-
-#: lib/rpmio.c:802
-msgid "Server IO error"
-msgstr "Chyba vstupu/výstupu servera"
-
-#: lib/rpmio.c:805
-msgid "Server timeout"
-msgstr "Prekroèenie èasového limitu servera"
-
-#: lib/rpmio.c:808
-msgid "Unable to lookup server host address"
-msgstr "Nie je mo¾né vyhµada» adresu servera"
-
-#: lib/rpmio.c:811
-msgid "Unable to lookup server host name"
-msgstr "Nie je mo¾né vyhµada» názov servera"
-
-#: lib/rpmio.c:814
-msgid "Failed to connect to server"
-msgstr "Pripojenie k serveru zlyhalo"
-
-#: lib/rpmio.c:817
-msgid "Failed to establish data connection to server"
-msgstr "Vytvorenie dátového spojenia k serveru zlyhalo"
-
-#: lib/rpmio.c:820
-msgid "IO error to local file"
-msgstr "Chyba vstupu/výstupu lokálneho súboru"
-
-#: lib/rpmio.c:823
-msgid "Error setting remote server to passive mode"
-msgstr "Chyba pri nastavení vzdialeného servera do pasívneho re¾imu"
-
-#: lib/rpmio.c:826
-msgid "File not found on server"
-msgstr "Súbor sa na serveri nenachádza"
-
-#: lib/rpmio.c:829
-msgid "Abort in progress"
-msgstr "Zru¹enie prebieha"
-
-#: lib/rpmio.c:833
-msgid "Unknown or unexpected error"
-msgstr "Neznáma alebo neoèakávaná chyba"
-
-#: lib/rpmio.c:1366
-#, c-format
-msgid "logging into %s as %s, pw %s\n"
-msgstr "prihlasuje sa na %s ako %s, heslo %s\n"
-
 #: lib/rpmlead.c:48
 #, c-format
 msgid "read failed: %s (%d)"
@@ -4061,68 +4004,125 @@ msgstr "vykon
 msgid "execution of script failed"
 msgstr "vykonanie skriptu zlyhalo"
 
-#: lib/url.c:88
+#: lib/verify.c:39
+#, fuzzy
+msgid "don't verify files in package"
+msgstr "zobrazi» súbory v balíku"
+
+#: lib/verify.c:215
+msgid "package lacks both user name and id lists (this should never happen)"
+msgstr ""
+"v balíku chýba tak meno pou¾ívateµa, ako aj zoznamy identifikácií (nemalo by "
+"sa nikdy sta»)"
+
+#: lib/verify.c:233
+msgid "package lacks both group name and id lists (this should never happen)"
+msgstr ""
+"v balíku chýba tak meno skupiny, ako aj zoznamy identifikácií (nemalo by sa "
+"nikdy sta»)"
+
+#: lib/verify.c:269
+#, c-format
+msgid "missing    %s\n"
+msgstr "chýbajúce    %s\n"
+
+#: lib/verify.c:331
+#, c-format
+msgid "Unsatisfied dependencies for %s-%s-%s: "
+msgstr "Nevyrie¹ené závislosti pre %s-%s-%s: "
+
+#: rpmio/rpmio.c:796
+msgid "Success"
+msgstr "Úspech"
+
+#: rpmio/rpmio.c:799
+msgid "Bad server response"
+msgstr "Chybná odpoveï servera"
+
+#: rpmio/rpmio.c:802
+msgid "Server IO error"
+msgstr "Chyba vstupu/výstupu servera"
+
+#: rpmio/rpmio.c:805
+msgid "Server timeout"
+msgstr "Prekroèenie èasového limitu servera"
+
+#: rpmio/rpmio.c:808
+msgid "Unable to lookup server host address"
+msgstr "Nie je mo¾né vyhµada» adresu servera"
+
+#: rpmio/rpmio.c:811
+msgid "Unable to lookup server host name"
+msgstr "Nie je mo¾né vyhµada» názov servera"
+
+#: rpmio/rpmio.c:814
+msgid "Failed to connect to server"
+msgstr "Pripojenie k serveru zlyhalo"
+
+#: rpmio/rpmio.c:817
+msgid "Failed to establish data connection to server"
+msgstr "Vytvorenie dátového spojenia k serveru zlyhalo"
+
+#: rpmio/rpmio.c:820
+msgid "IO error to local file"
+msgstr "Chyba vstupu/výstupu lokálneho súboru"
+
+#: rpmio/rpmio.c:823
+msgid "Error setting remote server to passive mode"
+msgstr "Chyba pri nastavení vzdialeného servera do pasívneho re¾imu"
+
+#: rpmio/rpmio.c:826
+msgid "File not found on server"
+msgstr "Súbor sa na serveri nenachádza"
+
+#: rpmio/rpmio.c:829
+msgid "Abort in progress"
+msgstr "Zru¹enie prebieha"
+
+#: rpmio/rpmio.c:833
+msgid "Unknown or unexpected error"
+msgstr "Neznáma alebo neoèakávaná chyba"
+
+#: rpmio/rpmio.c:1366
+#, c-format
+msgid "logging into %s as %s, pw %s\n"
+msgstr "prihlasuje sa na %s ako %s, heslo %s\n"
+
+#: rpmio/url.c:88
 #, c-format
 msgid "warning: u %p ctrl %p nrefs != 0 (%s %s)\n"
 msgstr ""
 
-#: lib/url.c:105
+#: rpmio/url.c:105
 #, c-format
 msgid "warning: u %p data %p nrefs != 0 (%s %s)\n"
 msgstr ""
 
-#: lib/url.c:132
+#: rpmio/url.c:132
 #, c-format
 msgid "warning: uCache[%d] %p nrefs(%d) != 1 (%s %s)\n"
 msgstr ""
 
-#: lib/url.c:218
+#: rpmio/url.c:218
 #, c-format
 msgid "Password for %s@%s: "
 msgstr "Heslo pre %s@%s: "
 
-#: lib/url.c:243 lib/url.c:269
+#: rpmio/url.c:243 rpmio/url.c:269
 #, c-format
 msgid "error: %sport must be a number\n"
 msgstr "chyba: %sport musí by» èíslo\n"
 
-#: lib/url.c:405
+#: rpmio/url.c:405
 msgid "url port must be a number\n"
 msgstr "url port musí by» èíslo\n"
 
 #. XXX Fstrerror
-#: lib/url.c:462
+#: rpmio/url.c:462
 #, fuzzy, c-format
 msgid "failed to create %s: %s\n"
 msgstr "nepodarilo sa vytvori» %s\n"
 
-#: lib/verify.c:39
-#, fuzzy
-msgid "don't verify files in package"
-msgstr "zobrazi» súbory v balíku"
-
-#: lib/verify.c:215
-msgid "package lacks both user name and id lists (this should never happen)"
-msgstr ""
-"v balíku chýba tak meno pou¾ívateµa, ako aj zoznamy identifikácií (nemalo by "
-"sa nikdy sta»)"
-
-#: lib/verify.c:233
-msgid "package lacks both group name and id lists (this should never happen)"
-msgstr ""
-"v balíku chýba tak meno skupiny, ako aj zoznamy identifikácií (nemalo by sa "
-"nikdy sta»)"
-
-#: lib/verify.c:269
-#, c-format
-msgid "missing    %s\n"
-msgstr "chýbajúce    %s\n"
-
-#: lib/verify.c:331
-#, c-format
-msgid "Unsatisfied dependencies for %s-%s-%s: "
-msgstr "Nevyrie¹ené závislosti pre %s-%s-%s: "
-
 #, fuzzy
 #~ msgid "cannot retrieve package \"%s\" from db"
 #~ msgstr "nie je mo¾né otvori» %s/packages.rpm\n"
index 1e2fe74..fd02d91 100644 (file)
--- a/po/sl.po
+++ b/po/sl.po
@@ -1,12 +1,12 @@
 # -*- mode:po; coding:iso-latin-2; -*- Slovenian messages for Redhat pkg. mngr.
 # Copyright (C) 2000 Free Software Foundation, Inc.
 # Primo¾ Peterlin <primoz.peterlin@biofiz.mf.uni-lj.si>, 2000.
-# $Id: sl.po,v 1.53 2000/06/06 20:06:10 jbj Exp $
+# $Id: sl.po,v 1.54 2000/06/07 23:25:43 jbj Exp $
 #
 msgid ""
 msgstr ""
 "Project-Id-Version: rpm 3.0.4\n"
-"POT-Creation-Date: 2000-06-06 15:54-0400\n"
+"POT-Creation-Date: 2000-06-07 14:46-0400\n"
 "PO-Revision-Date: 2000-02-17 22:25+01:00\n"
 "Last-Translator: Primo¾ Peterlin <primoz.peterlin@biofiz.mf.uni-lj.si>\n"
 "Language-Team: Slovenian <sl@li.org>\n"
@@ -2529,7 +2529,7 @@ msgstr "okvarjeno stanje datoteke: %s"
 msgid "opening db file        %s mode 0x%x\n"
 msgstr "odpiramo datoteko z naèinom 0x%x v %s\n"
 
-#: lib/db1.c:430 lib/url.c:445
+#: lib/db1.c:430 rpmio/url.c:445
 #, c-format
 msgid "failed to open %s: %s\n"
 msgstr "neuspe¹no odpiranje %s: %s\n"
@@ -3701,63 +3701,6 @@ msgstr "ni mo
 msgid "Installing %s\n"
 msgstr "Name¹èamo %s\n"
 
-#: lib/rpmio.c:796
-msgid "Success"
-msgstr "Uspe¹no"
-
-#: lib/rpmio.c:799
-msgid "Bad server response"
-msgstr "Okvarjen odziv stre¾nika"
-
-#: lib/rpmio.c:802
-msgid "Server IO error"
-msgstr "V/I napaka na stre¾niku"
-
-#: lib/rpmio.c:805
-msgid "Server timeout"
-msgstr "Potekel èas na stre¾niku"
-
-#: lib/rpmio.c:808
-msgid "Unable to lookup server host address"
-msgstr "Naslov stre¾nika ni ugotovljiv"
-
-#: lib/rpmio.c:811
-msgid "Unable to lookup server host name"
-msgstr "Ime stre¾nika ni ugotovljivo"
-
-#: lib/rpmio.c:814
-msgid "Failed to connect to server"
-msgstr "Neuspe¹en poskus prikljuèitve na stre¾nik"
-
-#: lib/rpmio.c:817
-msgid "Failed to establish data connection to server"
-msgstr "Neuspe¹na vzpostavitev podatkovne povezave s stre¾nikom"
-
-#: lib/rpmio.c:820
-msgid "IO error to local file"
-msgstr "V/I napaka na lokalni datoteki"
-
-#: lib/rpmio.c:823
-msgid "Error setting remote server to passive mode"
-msgstr "Napaka pri nastavitvi oddaljenega stre¾nika v pasivni naèin"
-
-#: lib/rpmio.c:826
-msgid "File not found on server"
-msgstr "Datoteke ni mo¾no najti na stre¾niku"
-
-#: lib/rpmio.c:829
-msgid "Abort in progress"
-msgstr "Prekinitev v teku"
-
-#: lib/rpmio.c:833
-msgid "Unknown or unexpected error"
-msgstr "Neznana ali neprièakovana napaka"
-
-#: lib/rpmio.c:1366
-#, c-format
-msgid "logging into %s as %s, pw %s\n"
-msgstr "prijava na %s kot %s, geslo %s\n"
-
 #: lib/rpmlead.c:48
 #, c-format
 msgid "read failed: %s (%d)"
@@ -4043,65 +3986,122 @@ msgstr "poganjamo poodnamestitvene skripte (
 msgid "execution of script failed"
 msgstr "skript se ni uspe¹no izvedel"
 
-#: lib/url.c:88
+#: lib/verify.c:39
+msgid "don't verify files in package"
+msgstr "brez preverjanja datotek v paketu"
+
+#: lib/verify.c:215
+msgid "package lacks both user name and id lists (this should never happen)"
+msgstr ""
+"v paketu manjka tako seznam uporabnikov kot identitet (to se ne more zgoditi)"
+
+#: lib/verify.c:233
+msgid "package lacks both group name and id lists (this should never happen)"
+msgstr ""
+"v paketu manjka tako seznam skupin kot identitet (to se ne more zgoditi)"
+
+#: lib/verify.c:269
+#, c-format
+msgid "missing    %s\n"
+msgstr "manjka     %s\n"
+
+#: lib/verify.c:331
+#, c-format
+msgid "Unsatisfied dependencies for %s-%s-%s: "
+msgstr "Nezadovoljene soodvisnosti za %s-%s-%s: "
+
+#: rpmio/rpmio.c:796
+msgid "Success"
+msgstr "Uspe¹no"
+
+#: rpmio/rpmio.c:799
+msgid "Bad server response"
+msgstr "Okvarjen odziv stre¾nika"
+
+#: rpmio/rpmio.c:802
+msgid "Server IO error"
+msgstr "V/I napaka na stre¾niku"
+
+#: rpmio/rpmio.c:805
+msgid "Server timeout"
+msgstr "Potekel èas na stre¾niku"
+
+#: rpmio/rpmio.c:808
+msgid "Unable to lookup server host address"
+msgstr "Naslov stre¾nika ni ugotovljiv"
+
+#: rpmio/rpmio.c:811
+msgid "Unable to lookup server host name"
+msgstr "Ime stre¾nika ni ugotovljivo"
+
+#: rpmio/rpmio.c:814
+msgid "Failed to connect to server"
+msgstr "Neuspe¹en poskus prikljuèitve na stre¾nik"
+
+#: rpmio/rpmio.c:817
+msgid "Failed to establish data connection to server"
+msgstr "Neuspe¹na vzpostavitev podatkovne povezave s stre¾nikom"
+
+#: rpmio/rpmio.c:820
+msgid "IO error to local file"
+msgstr "V/I napaka na lokalni datoteki"
+
+#: rpmio/rpmio.c:823
+msgid "Error setting remote server to passive mode"
+msgstr "Napaka pri nastavitvi oddaljenega stre¾nika v pasivni naèin"
+
+#: rpmio/rpmio.c:826
+msgid "File not found on server"
+msgstr "Datoteke ni mo¾no najti na stre¾niku"
+
+#: rpmio/rpmio.c:829
+msgid "Abort in progress"
+msgstr "Prekinitev v teku"
+
+#: rpmio/rpmio.c:833
+msgid "Unknown or unexpected error"
+msgstr "Neznana ali neprièakovana napaka"
+
+#: rpmio/rpmio.c:1366
+#, c-format
+msgid "logging into %s as %s, pw %s\n"
+msgstr "prijava na %s kot %s, geslo %s\n"
+
+#: rpmio/url.c:88
 #, c-format
 msgid "warning: u %p ctrl %p nrefs != 0 (%s %s)\n"
 msgstr "opozorilo: u %p ctrl %p nrefs != 0 (%s %s)\n"
 
-#: lib/url.c:105
+#: rpmio/url.c:105
 #, c-format
 msgid "warning: u %p data %p nrefs != 0 (%s %s)\n"
 msgstr "opozorilo: u %p data %p nrefs != 0 (%s %s)\n"
 
-#: lib/url.c:132
+#: rpmio/url.c:132
 #, c-format
 msgid "warning: uCache[%d] %p nrefs(%d) != 1 (%s %s)\n"
 msgstr "opozorilo: uCache[%d] %p nrefs(%d) != 1 (%s %s)\n"
 
-#: lib/url.c:218
+#: rpmio/url.c:218
 #, c-format
 msgid "Password for %s@%s: "
 msgstr "Geslo za %s@%s: "
 
-#: lib/url.c:243 lib/url.c:269
+#: rpmio/url.c:243 rpmio/url.c:269
 #, c-format
 msgid "error: %sport must be a number\n"
 msgstr "napaka: vrata %s morajo biti ¹tevilka\n"
 
-#: lib/url.c:405
+#: rpmio/url.c:405
 msgid "url port must be a number\n"
 msgstr "vrata URL morajo biti ¹tevilka\n"
 
 #. XXX Fstrerror
-#: lib/url.c:462
+#: rpmio/url.c:462
 #, c-format
 msgid "failed to create %s: %s\n"
 msgstr "neuspe¹no ustvarjanje %s: %s\n"
 
-#: lib/verify.c:39
-msgid "don't verify files in package"
-msgstr "brez preverjanja datotek v paketu"
-
-#: lib/verify.c:215
-msgid "package lacks both user name and id lists (this should never happen)"
-msgstr ""
-"v paketu manjka tako seznam uporabnikov kot identitet (to se ne more zgoditi)"
-
-#: lib/verify.c:233
-msgid "package lacks both group name and id lists (this should never happen)"
-msgstr ""
-"v paketu manjka tako seznam skupin kot identitet (to se ne more zgoditi)"
-
-#: lib/verify.c:269
-#, c-format
-msgid "missing    %s\n"
-msgstr "manjka     %s\n"
-
-#: lib/verify.c:331
-#, c-format
-msgid "Unsatisfied dependencies for %s-%s-%s: "
-msgstr "Nezadovoljene soodvisnosti za %s-%s-%s: "
-
 #, fuzzy
 #~ msgid "cannot retrieve package \"%s\" from db"
 #~ msgstr "paketa ni mo¾no odpreti: %s\n"
index bea44fb..b88313c 100644 (file)
--- a/po/sr.po
+++ b/po/sr.po
@@ -1,6 +1,6 @@
 msgid ""
 msgstr ""
-"POT-Creation-Date: 2000-06-06 15:54-0400\n"
+"POT-Creation-Date: 2000-06-07 14:46-0400\n"
 "Content-Type: text/plain; charset=\n"
 "Date: 1998-05-02 21:41:47-0400\n"
 "From: Erik Troan <ewt@lacrosse.redhat.com>\n"
@@ -2548,7 +2548,7 @@ msgstr "neuspelo otvaranje %s: %s"
 msgid "opening db file        %s mode 0x%x\n"
 msgstr "rekreiraj bazu podataka iz postojeæe baze"
 
-#: lib/db1.c:430 lib/url.c:445
+#: lib/db1.c:430 rpmio/url.c:445
 #, fuzzy, c-format
 msgid "failed to open %s: %s\n"
 msgstr "neuspelo otvaranje %s: %s"
@@ -3741,71 +3741,6 @@ msgstr "gre
 msgid "Installing %s\n"
 msgstr "Instaliram %s\n"
 
-#: lib/rpmio.c:796
-msgid "Success"
-msgstr ""
-
-#: lib/rpmio.c:799
-#, fuzzy
-msgid "Bad server response"
-msgstr "Lo¹ odgovor FTP servera"
-
-#: lib/rpmio.c:802
-#, fuzzy
-msgid "Server IO error"
-msgstr "Ulazno/izlazna FTP gre¹ka"
-
-#: lib/rpmio.c:805
-#, fuzzy
-msgid "Server timeout"
-msgstr "Tajm-aut FTP servera"
-
-#: lib/rpmio.c:808
-#, fuzzy
-msgid "Unable to lookup server host address"
-msgstr "Ne mogu da odredim host adresu FTP servera"
-
-#: lib/rpmio.c:811
-#, fuzzy
-msgid "Unable to lookup server host name"
-msgstr "Ne mogu da odredim ime FTP hosta"
-
-#: lib/rpmio.c:814
-#, fuzzy
-msgid "Failed to connect to server"
-msgstr "Ne mogu da se pove¾em sa FTP serverom"
-
-#: lib/rpmio.c:817
-#, fuzzy
-msgid "Failed to establish data connection to server"
-msgstr "Ne mogu da uspostavim vezu podataka sa FTP serverom"
-
-#: lib/rpmio.c:820
-msgid "IO error to local file"
-msgstr "Ulazno/izlazna gre¹ka kod lokalne datoteke"
-
-#: lib/rpmio.c:823
-msgid "Error setting remote server to passive mode"
-msgstr "Gre¹ka kod stavljanja udaljenog servera u pasivni re¾im"
-
-#: lib/rpmio.c:826
-msgid "File not found on server"
-msgstr "Datoteka nije pronaðena na serveru"
-
-#: lib/rpmio.c:829
-msgid "Abort in progress"
-msgstr ""
-
-#: lib/rpmio.c:833
-#, fuzzy
-msgid "Unknown or unexpected error"
-msgstr "Neoèekivana ili nepoznata FTP gre¹ka"
-
-#: lib/rpmio.c:1366
-#, c-format
-msgid "logging into %s as %s, pw %s\n"
-msgstr ""
-
 #: lib/rpmlead.c:48
 #, c-format
 msgid "read failed: %s (%d)"
@@ -4103,65 +4038,130 @@ msgstr ""
 msgid "execution of script failed"
 msgstr "neuspelo izvr¹avanje skripta"
 
-#: lib/url.c:88
+#: lib/verify.c:39
+#, fuzzy
+msgid "don't verify files in package"
+msgstr "instaliraj paket"
+
+#: lib/verify.c:215
+msgid "package lacks both user name and id lists (this should never happen)"
+msgstr ""
+
+#: lib/verify.c:233
+msgid "package lacks both group name and id lists (this should never happen)"
+msgstr ""
+
+#: lib/verify.c:269
+#, fuzzy, c-format
+msgid "missing    %s\n"
+msgstr "nedostaje { posle %"
+
+#: lib/verify.c:331
+#, c-format
+msgid "Unsatisfied dependencies for %s-%s-%s: "
+msgstr "Nezadovoljene meðuzavisnosti za %s-%s-%s: "
+
+#: rpmio/rpmio.c:796
+msgid "Success"
+msgstr ""
+
+#: rpmio/rpmio.c:799
+#, fuzzy
+msgid "Bad server response"
+msgstr "Lo¹ odgovor FTP servera"
+
+#: rpmio/rpmio.c:802
+#, fuzzy
+msgid "Server IO error"
+msgstr "Ulazno/izlazna FTP gre¹ka"
+
+#: rpmio/rpmio.c:805
+#, fuzzy
+msgid "Server timeout"
+msgstr "Tajm-aut FTP servera"
+
+#: rpmio/rpmio.c:808
+#, fuzzy
+msgid "Unable to lookup server host address"
+msgstr "Ne mogu da odredim host adresu FTP servera"
+
+#: rpmio/rpmio.c:811
+#, fuzzy
+msgid "Unable to lookup server host name"
+msgstr "Ne mogu da odredim ime FTP hosta"
+
+#: rpmio/rpmio.c:814
+#, fuzzy
+msgid "Failed to connect to server"
+msgstr "Ne mogu da se pove¾em sa FTP serverom"
+
+#: rpmio/rpmio.c:817
+#, fuzzy
+msgid "Failed to establish data connection to server"
+msgstr "Ne mogu da uspostavim vezu podataka sa FTP serverom"
+
+#: rpmio/rpmio.c:820
+msgid "IO error to local file"
+msgstr "Ulazno/izlazna gre¹ka kod lokalne datoteke"
+
+#: rpmio/rpmio.c:823
+msgid "Error setting remote server to passive mode"
+msgstr "Gre¹ka kod stavljanja udaljenog servera u pasivni re¾im"
+
+#: rpmio/rpmio.c:826
+msgid "File not found on server"
+msgstr "Datoteka nije pronaðena na serveru"
+
+#: rpmio/rpmio.c:829
+msgid "Abort in progress"
+msgstr ""
+
+#: rpmio/rpmio.c:833
+#, fuzzy
+msgid "Unknown or unexpected error"
+msgstr "Neoèekivana ili nepoznata FTP gre¹ka"
+
+#: rpmio/rpmio.c:1366
+#, c-format
+msgid "logging into %s as %s, pw %s\n"
+msgstr ""
+
+#: rpmio/url.c:88
 #, c-format
 msgid "warning: u %p ctrl %p nrefs != 0 (%s %s)\n"
 msgstr ""
 
-#: lib/url.c:105
+#: rpmio/url.c:105
 #, c-format
 msgid "warning: u %p data %p nrefs != 0 (%s %s)\n"
 msgstr ""
 
-#: lib/url.c:132
+#: rpmio/url.c:132
 #, c-format
 msgid "warning: uCache[%d] %p nrefs(%d) != 1 (%s %s)\n"
 msgstr ""
 
-#: lib/url.c:218
+#: rpmio/url.c:218
 #, c-format
 msgid "Password for %s@%s: "
 msgstr "Lozinka za %s@%s: "
 
-#: lib/url.c:243 lib/url.c:269
+#: rpmio/url.c:243 rpmio/url.c:269
 #, fuzzy, c-format
 msgid "error: %sport must be a number\n"
 msgstr "gre¹ka: FTP port mora biti broj\n"
 
-#: lib/url.c:405
+#: rpmio/url.c:405
 #, fuzzy
 msgid "url port must be a number\n"
 msgstr "gre¹ka: FTP port mora biti broj\n"
 
 #. XXX Fstrerror
-#: lib/url.c:462
+#: rpmio/url.c:462
 #, fuzzy, c-format
 msgid "failed to create %s: %s\n"
 msgstr "neuspelo kreiranje %s\n"
 
-#: lib/verify.c:39
-#, fuzzy
-msgid "don't verify files in package"
-msgstr "instaliraj paket"
-
-#: lib/verify.c:215
-msgid "package lacks both user name and id lists (this should never happen)"
-msgstr ""
-
-#: lib/verify.c:233
-msgid "package lacks both group name and id lists (this should never happen)"
-msgstr ""
-
-#: lib/verify.c:269
-#, fuzzy, c-format
-msgid "missing    %s\n"
-msgstr "nedostaje { posle %"
-
-#: lib/verify.c:331
-#, c-format
-msgid "Unsatisfied dependencies for %s-%s-%s: "
-msgstr "Nezadovoljene meðuzavisnosti za %s-%s-%s: "
-
 #, fuzzy
 #~ msgid "cannot retrieve package \"%s\" from db"
 #~ msgstr "gre¹ka: ne mogu da otvorim %s%s/packages.rpm\n"
index 224fd41..8f467b5 100644 (file)
--- a/po/sv.po
+++ b/po/sv.po
@@ -1,12 +1,12 @@
 # Swedish messages for RPM
 # Copyright © 1999 Free Software Foundation, Inc.
 # Göran Uddeborg <göran@uddeborg.pp.se>, 1999, 2000.
-# $Revision: 1.113 $
+# $Revision: 1.114 $
 #
 msgid ""
 msgstr ""
 "Project-Id-Version: rpm 3.0.4\n"
-"POT-Creation-Date: 2000-06-06 15:54-0400\n"
+"POT-Creation-Date: 2000-06-07 14:46-0400\n"
 "PO-Revision-Date: 2000-02-21 12:20+0100\n"
 "Last-Translator: Göran Uddeborg <göran@uddeborg.pp.se>\n"
 "Language-Team: Swedish <sv@li.org>\n"
@@ -2513,7 +2513,7 @@ msgstr "felaktig filstatus: %s"
 msgid "opening db file        %s mode 0x%x\n"
 msgstr "öppnar databas med rättighet 0x%x i %s\n"
 
-#: lib/db1.c:430 lib/url.c:445
+#: lib/db1.c:430 rpmio/url.c:445
 #, c-format
 msgid "failed to open %s: %s\n"
 msgstr "kunde inte öppna %s: %s\n"
@@ -3689,63 +3689,6 @@ msgstr "kan inte 
 msgid "Installing %s\n"
 msgstr "Installerar %s\n"
 
-#: lib/rpmio.c:796
-msgid "Success"
-msgstr "Lyckades"
-
-#: lib/rpmio.c:799
-msgid "Bad server response"
-msgstr "Konstigt svar från server"
-
-#: lib/rpmio.c:802
-msgid "Server IO error"
-msgstr "IO-fel mot server"
-
-#: lib/rpmio.c:805
-msgid "Server timeout"
-msgstr "Förbindelsen med servern dog ut (timeout)"
-
-#: lib/rpmio.c:808
-msgid "Unable to lookup server host address"
-msgstr "Kunde inte slå upp serverns adress"
-
-#: lib/rpmio.c:811
-msgid "Unable to lookup server host name"
-msgstr "Kunde inte slå upp serverns namn"
-
-#: lib/rpmio.c:814
-msgid "Failed to connect to server"
-msgstr "Misslyckades med att kontakta servern"
-
-#: lib/rpmio.c:817
-msgid "Failed to establish data connection to server"
-msgstr "Misslyckades med att etablera en dataförbindelse till servern"
-
-#: lib/rpmio.c:820
-msgid "IO error to local file"
-msgstr "IO-fel mot lokal fil"
-
-#: lib/rpmio.c:823
-msgid "Error setting remote server to passive mode"
-msgstr "Fel när den fjärrservern sattes i passivt läge"
-
-#: lib/rpmio.c:826
-msgid "File not found on server"
-msgstr "Filen fanns inte på servern"
-
-#: lib/rpmio.c:829
-msgid "Abort in progress"
-msgstr "Avbruten under gång"
-
-#: lib/rpmio.c:833
-msgid "Unknown or unexpected error"
-msgstr "Okänt eller oväntat fel"
-
-#: lib/rpmio.c:1366
-#, c-format
-msgid "logging into %s as %s, pw %s\n"
-msgstr "loggar in på %s som %s, lösenord %s\n"
-
 #: lib/rpmlead.c:48
 #, c-format
 msgid "read failed: %s (%d)"
@@ -4031,65 +3974,122 @@ msgstr "k
 msgid "execution of script failed"
 msgstr "skriptkörning misslyckades"
 
-#: lib/url.c:88
+#: lib/verify.c:39
+msgid "don't verify files in package"
+msgstr "verifiera inte filerna i paketet"
+
+#: lib/verify.c:215
+msgid "package lacks both user name and id lists (this should never happen)"
+msgstr ""
+"paket saknar både användarnamn och id-listor (detta borde aldrig inträffa)"
+
+#: lib/verify.c:233
+msgid "package lacks both group name and id lists (this should never happen)"
+msgstr ""
+"paket saknar både gruppnamn och id-listor (detta borde aldrig inträffa)"
+
+#: lib/verify.c:269
+#, c-format
+msgid "missing    %s\n"
+msgstr "saknas     %s\n"
+
+#: lib/verify.c:331
+#, c-format
+msgid "Unsatisfied dependencies for %s-%s-%s: "
+msgstr "Ouppfyllda beroenden för %s-%s-%s: "
+
+#: rpmio/rpmio.c:796
+msgid "Success"
+msgstr "Lyckades"
+
+#: rpmio/rpmio.c:799
+msgid "Bad server response"
+msgstr "Konstigt svar från server"
+
+#: rpmio/rpmio.c:802
+msgid "Server IO error"
+msgstr "IO-fel mot server"
+
+#: rpmio/rpmio.c:805
+msgid "Server timeout"
+msgstr "Förbindelsen med servern dog ut (timeout)"
+
+#: rpmio/rpmio.c:808
+msgid "Unable to lookup server host address"
+msgstr "Kunde inte slå upp serverns adress"
+
+#: rpmio/rpmio.c:811
+msgid "Unable to lookup server host name"
+msgstr "Kunde inte slå upp serverns namn"
+
+#: rpmio/rpmio.c:814
+msgid "Failed to connect to server"
+msgstr "Misslyckades med att kontakta servern"
+
+#: rpmio/rpmio.c:817
+msgid "Failed to establish data connection to server"
+msgstr "Misslyckades med att etablera en dataförbindelse till servern"
+
+#: rpmio/rpmio.c:820
+msgid "IO error to local file"
+msgstr "IO-fel mot lokal fil"
+
+#: rpmio/rpmio.c:823
+msgid "Error setting remote server to passive mode"
+msgstr "Fel när den fjärrservern sattes i passivt läge"
+
+#: rpmio/rpmio.c:826
+msgid "File not found on server"
+msgstr "Filen fanns inte på servern"
+
+#: rpmio/rpmio.c:829
+msgid "Abort in progress"
+msgstr "Avbruten under gång"
+
+#: rpmio/rpmio.c:833
+msgid "Unknown or unexpected error"
+msgstr "Okänt eller oväntat fel"
+
+#: rpmio/rpmio.c:1366
+#, c-format
+msgid "logging into %s as %s, pw %s\n"
+msgstr "loggar in på %s som %s, lösenord %s\n"
+
+#: rpmio/url.c:88
 #, c-format
 msgid "warning: u %p ctrl %p nrefs != 0 (%s %s)\n"
 msgstr "varning: u %p ctrl %p nrefs != 0 (%s %s)\n"
 
-#: lib/url.c:105
+#: rpmio/url.c:105
 #, c-format
 msgid "warning: u %p data %p nrefs != 0 (%s %s)\n"
 msgstr "varning: u %p data %p nrefs != 0 (%s %s)\n"
 
-#: lib/url.c:132
+#: rpmio/url.c:132
 #, c-format
 msgid "warning: uCache[%d] %p nrefs(%d) != 1 (%s %s)\n"
 msgstr "varning: uCache[%d] %p nrefs(%d) != 1 (%s %s)\n"
 
-#: lib/url.c:218
+#: rpmio/url.c:218
 #, c-format
 msgid "Password for %s@%s: "
 msgstr "Lösenord för %s@%s: "
 
-#: lib/url.c:243 lib/url.c:269
+#: rpmio/url.c:243 rpmio/url.c:269
 #, c-format
 msgid "error: %sport must be a number\n"
 msgstr "fel: %s-port måste vara ett tal\n"
 
-#: lib/url.c:405
+#: rpmio/url.c:405
 msgid "url port must be a number\n"
 msgstr "url-port måste vara ett tal\n"
 
 #. XXX Fstrerror
-#: lib/url.c:462
+#: rpmio/url.c:462
 #, c-format
 msgid "failed to create %s: %s\n"
 msgstr "kunde inte skapa %s: %s\n"
 
-#: lib/verify.c:39
-msgid "don't verify files in package"
-msgstr "verifiera inte filerna i paketet"
-
-#: lib/verify.c:215
-msgid "package lacks both user name and id lists (this should never happen)"
-msgstr ""
-"paket saknar både användarnamn och id-listor (detta borde aldrig inträffa)"
-
-#: lib/verify.c:233
-msgid "package lacks both group name and id lists (this should never happen)"
-msgstr ""
-"paket saknar både gruppnamn och id-listor (detta borde aldrig inträffa)"
-
-#: lib/verify.c:269
-#, c-format
-msgid "missing    %s\n"
-msgstr "saknas     %s\n"
-
-#: lib/verify.c:331
-#, c-format
-msgid "Unsatisfied dependencies for %s-%s-%s: "
-msgstr "Ouppfyllda beroenden för %s-%s-%s: "
-
 #, fuzzy
 #~ msgid "cannot retrieve package \"%s\" from db"
 #~ msgstr "kan inte öppna paket: %s\n"
index ec8deca..71a8615 100644 (file)
--- a/po/tr.po
+++ b/po/tr.po
@@ -6,7 +6,7 @@
 msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
-"POT-Creation-Date: 2000-06-06 15:54-0400\n"
+"POT-Creation-Date: 2000-06-07 14:46-0400\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -2598,7 +2598,7 @@ msgstr "%s a
 msgid "opening db file        %s mode 0x%x\n"
 msgstr "mevcut veritabanýný kullanýlarak veritabýnýný yeniden oluþturur"
 
-#: lib/db1.c:430 lib/url.c:445
+#: lib/db1.c:430 rpmio/url.c:445
 #, fuzzy, c-format
 msgid "failed to open %s: %s\n"
 msgstr "%s açýlamadý: %s"
@@ -3794,71 +3794,6 @@ msgstr "hata: %s eri
 msgid "Installing %s\n"
 msgstr "%s yükleniyor\n"
 
-#: lib/rpmio.c:796
-msgid "Success"
-msgstr ""
-
-#: lib/rpmio.c:799
-#, fuzzy
-msgid "Bad server response"
-msgstr "FTP sunucusundan kötü yanýt"
-
-#: lib/rpmio.c:802
-#, fuzzy
-msgid "Server IO error"
-msgstr "FTP I/O hatasý"
-
-#: lib/rpmio.c:805
-#, fuzzy
-msgid "Server timeout"
-msgstr "FTP sunucusu zaman aþýmý"
-
-#: lib/rpmio.c:808
-#, fuzzy
-msgid "Unable to lookup server host address"
-msgstr "FTP sunucusunun isim adres dönüþümü yapýlamadý"
-
-#: lib/rpmio.c:811
-#, fuzzy
-msgid "Unable to lookup server host name"
-msgstr "FTP sunucusunun adres isim dönüþümü yapýlamadý"
-
-#: lib/rpmio.c:814
-#, fuzzy
-msgid "Failed to connect to server"
-msgstr "FTP sunucusuna baðlanýlamadý"
-
-#: lib/rpmio.c:817
-#, fuzzy
-msgid "Failed to establish data connection to server"
-msgstr "FTP sunucusu ile veri alýþveriþi yapýlamadý"
-
-#: lib/rpmio.c:820
-msgid "IO error to local file"
-msgstr "Yerel dosyaya eriþim sýrasýnda I/O hatasý"
-
-#: lib/rpmio.c:823
-msgid "Error setting remote server to passive mode"
-msgstr "Karþý sunucuyu pasif kipe sokam hatasý"
-
-#: lib/rpmio.c:826
-msgid "File not found on server"
-msgstr "Dosya sunucuda bulunamadý"
-
-#: lib/rpmio.c:829
-msgid "Abort in progress"
-msgstr ""
-
-#: lib/rpmio.c:833
-#, fuzzy
-msgid "Unknown or unexpected error"
-msgstr "FTP bilinmeyen ya da beklenmeyen hata"
-
-#: lib/rpmio.c:1366
-#, c-format
-msgid "logging into %s as %s, pw %s\n"
-msgstr ""
-
 #: lib/rpmlead.c:48
 #, c-format
 msgid "read failed: %s (%d)"
@@ -4156,65 +4091,130 @@ msgstr ""
 msgid "execution of script failed"
 msgstr "betik (script) çalýþtýrýlamadý "
 
-#: lib/url.c:88
+#: lib/verify.c:39
+#, fuzzy
+msgid "don't verify files in package"
+msgstr "paket yüklemek"
+
+#: lib/verify.c:215
+msgid "package lacks both user name and id lists (this should never happen)"
+msgstr ""
+
+#: lib/verify.c:233
+msgid "package lacks both group name and id lists (this should never happen)"
+msgstr ""
+
+#: lib/verify.c:269
+#, fuzzy, c-format
+msgid "missing    %s\n"
+msgstr "% den sonra eksik {"
+
+#: lib/verify.c:331
+#, c-format
+msgid "Unsatisfied dependencies for %s-%s-%s: "
+msgstr "%s-%s-%s 'nin baðýmlýlýk sorunlarý: "
+
+#: rpmio/rpmio.c:796
+msgid "Success"
+msgstr ""
+
+#: rpmio/rpmio.c:799
+#, fuzzy
+msgid "Bad server response"
+msgstr "FTP sunucusundan kötü yanýt"
+
+#: rpmio/rpmio.c:802
+#, fuzzy
+msgid "Server IO error"
+msgstr "FTP I/O hatasý"
+
+#: rpmio/rpmio.c:805
+#, fuzzy
+msgid "Server timeout"
+msgstr "FTP sunucusu zaman aþýmý"
+
+#: rpmio/rpmio.c:808
+#, fuzzy
+msgid "Unable to lookup server host address"
+msgstr "FTP sunucusunun isim adres dönüþümü yapýlamadý"
+
+#: rpmio/rpmio.c:811
+#, fuzzy
+msgid "Unable to lookup server host name"
+msgstr "FTP sunucusunun adres isim dönüþümü yapýlamadý"
+
+#: rpmio/rpmio.c:814
+#, fuzzy
+msgid "Failed to connect to server"
+msgstr "FTP sunucusuna baðlanýlamadý"
+
+#: rpmio/rpmio.c:817
+#, fuzzy
+msgid "Failed to establish data connection to server"
+msgstr "FTP sunucusu ile veri alýþveriþi yapýlamadý"
+
+#: rpmio/rpmio.c:820
+msgid "IO error to local file"
+msgstr "Yerel dosyaya eriþim sýrasýnda I/O hatasý"
+
+#: rpmio/rpmio.c:823
+msgid "Error setting remote server to passive mode"
+msgstr "Karþý sunucuyu pasif kipe sokam hatasý"
+
+#: rpmio/rpmio.c:826
+msgid "File not found on server"
+msgstr "Dosya sunucuda bulunamadý"
+
+#: rpmio/rpmio.c:829
+msgid "Abort in progress"
+msgstr ""
+
+#: rpmio/rpmio.c:833
+#, fuzzy
+msgid "Unknown or unexpected error"
+msgstr "FTP bilinmeyen ya da beklenmeyen hata"
+
+#: rpmio/rpmio.c:1366
+#, c-format
+msgid "logging into %s as %s, pw %s\n"
+msgstr ""
+
+#: rpmio/url.c:88
 #, c-format
 msgid "warning: u %p ctrl %p nrefs != 0 (%s %s)\n"
 msgstr ""
 
-#: lib/url.c:105
+#: rpmio/url.c:105
 #, c-format
 msgid "warning: u %p data %p nrefs != 0 (%s %s)\n"
 msgstr ""
 
-#: lib/url.c:132
+#: rpmio/url.c:132
 #, c-format
 msgid "warning: uCache[%d] %p nrefs(%d) != 1 (%s %s)\n"
 msgstr ""
 
-#: lib/url.c:218
+#: rpmio/url.c:218
 #, c-format
 msgid "Password for %s@%s: "
 msgstr "%s'%s için parola"
 
-#: lib/url.c:243 lib/url.c:269
+#: rpmio/url.c:243 rpmio/url.c:269
 #, fuzzy, c-format
 msgid "error: %sport must be a number\n"
 msgstr "hata: ftpport bir sayý olmalý\n"
 
-#: lib/url.c:405
+#: rpmio/url.c:405
 #, fuzzy
 msgid "url port must be a number\n"
 msgstr "hata: ftpport bir sayý olmalý\n"
 
 #. XXX Fstrerror
-#: lib/url.c:462
+#: rpmio/url.c:462
 #, fuzzy, c-format
 msgid "failed to create %s: %s\n"
 msgstr "%s yaratýlamýyor\n"
 
-#: lib/verify.c:39
-#, fuzzy
-msgid "don't verify files in package"
-msgstr "paket yüklemek"
-
-#: lib/verify.c:215
-msgid "package lacks both user name and id lists (this should never happen)"
-msgstr ""
-
-#: lib/verify.c:233
-msgid "package lacks both group name and id lists (this should never happen)"
-msgstr ""
-
-#: lib/verify.c:269
-#, fuzzy, c-format
-msgid "missing    %s\n"
-msgstr "% den sonra eksik {"
-
-#: lib/verify.c:331
-#, c-format
-msgid "Unsatisfied dependencies for %s-%s-%s: "
-msgstr "%s-%s-%s 'nin baðýmlýlýk sorunlarý: "
-
 #, fuzzy
 #~ msgid "cannot retrieve package \"%s\" from db"
 #~ msgstr "hata: %s%s/packages.rpm açýlamýyor\n"
index 9fb06e3..978def0 100644 (file)
@@ -2,16 +2,13 @@
 
 AUTOMAKE_OPTIONS = 1.4 foreign
 
-INCLUDES = \
-       -I$(top_srcdir) \
-       -I$(top_srcdir)/lib \
-       -I$(top_srcdir)/popt \
-       -I/usr/include/python1.5 \
-        @INCPATH@
+INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_srcdir)/rpmio \
+       -I$(top_srcdir)/popt -I/usr/include/python1.5 @INCPATH@
 
 EXTRA_DIST = hash.h upgrade.h
 mylibs= \
        $(top_builddir)/lib/librpm.la \
+       $(top_builddir)/lib/librpmio.la \
        $(top_builddir)/popt/libpopt.la
 
 LDADD =
@@ -20,10 +17,11 @@ pythondir = $(prefix)/lib/python1.5/site-packages
 python_PROGRAMS = rpmmodule.so
 rpmmodule_so_SOURCES =
 # XXX rpmmodule_so_LDFLAGS = -L../lib/.libs -lrpm -L../popt/.libs -lpopt $(LIBS) -shared -Wl,-soname,rpmmodule.so
-rpmmodule_so_LDFLAGS = -lrpm -lpopt $(LIBS) -shared -Wl,-soname,rpmmodule.so
+rpmmodule_so_LDFLAGS = $(top_builddir)/lib/librpm.la \
+       $(LIBS) -shared -Wl,-soname,rpmmodule.so
 
 noinst_LTLIBRARIES = librpmmodule.la
 librpmmodule_la_SOURCES = rpmmodule.c hash.c upgrade.c
 
 rpmmodule.so: $(librpmmodule_la_OBJECTS)
-       $(CC) -o $@ $^ $(rpmmodule_so_LDFLAGS)
+       $(LINK) -o $@ $^ $(rpmmodule_so_LDFLAGS)
index f4cfe70..92dae89 100644 (file)
@@ -161,11 +161,11 @@ varprefix = @varprefix@
 
 AUTOMAKE_OPTIONS = 1.4 foreign
 
-INCLUDES =     -I$(top_srcdir)         -I$(top_srcdir)/lib     -I$(top_srcdir)/popt    -I/usr/include/python1.5         @INCPATH@
+INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/lib -I$(top_srcdir)/rpmio   -I$(top_srcdir)/popt -I/usr/include/python1.5 @INCPATH@
 
 
 EXTRA_DIST = hash.h upgrade.h
-mylibs =       $(top_builddir)/lib/librpm.la   $(top_builddir)/popt/libpopt.la
+mylibs =       $(top_builddir)/lib/librpm.la   $(top_builddir)/lib/librpmio.la         $(top_builddir)/popt/libpopt.la
 
 
 LDADD = 
@@ -174,7 +174,8 @@ pythondir = $(prefix)/lib/python1.5/site-packages
 python_PROGRAMS = rpmmodule.so
 rpmmodule_so_SOURCES = 
 # XXX rpmmodule_so_LDFLAGS = -L../lib/.libs -lrpm -L../popt/.libs -lpopt $(LIBS) -shared -Wl,-soname,rpmmodule.so
-rpmmodule_so_LDFLAGS = -lrpm -lpopt $(LIBS) -shared -Wl,-soname,rpmmodule.so
+rpmmodule_so_LDFLAGS = $(top_builddir)/lib/librpm.la   $(LIBS) -shared -Wl,-soname,rpmmodule.so
+
 
 noinst_LTLIBRARIES = librpmmodule.la
 librpmmodule_la_SOURCES = rpmmodule.c hash.c upgrade.c
@@ -456,7 +457,7 @@ mostlyclean distclean maintainer-clean
 
 
 rpmmodule.so: $(librpmmodule_la_OBJECTS)
-       $(CC) -o $@ $^ $(rpmmodule_so_LDFLAGS)
+       $(LINK) -o $@ $^ $(rpmmodule_so_LDFLAGS)
 
 # Tell versions [3.59,3.63) of GNU make to not export all variables.
 # Otherwise a system limit (for SysV at least) may be exceeded.
index 409fee2..78d262a 100644 (file)
--- a/rpm.spec
+++ b/rpm.spec
@@ -5,7 +5,7 @@ Summary: The Red Hat package management system.
 Name: rpm
 %define version 4.0
 Version: %{version}
-Release: 0.33
+Release: 0.34
 Group: System Environment/Base
 Source: ftp://ftp.rpm.org/pub/rpm/dist/rpm-3.0.x/rpm-%{version}.tar.gz
 Copyright: GPL
@@ -153,6 +153,7 @@ fi
 %{__prefix}/bin/rpmdb
 %{__prefix}/bin/rpm[eiukqv]
 %{__prefix}/lib/librpm.so.*
+%{__prefix}/lib/librpmio.so.*
 %{__prefix}/lib/librpmbuild.so.*
 
 %{__prefix}/lib/rpm/brp-*
@@ -234,6 +235,9 @@ fi
 %{__prefix}/lib/librpm.a
 %{__prefix}/lib/librpm.la
 %{__prefix}/lib/librpm.so
+%{__prefix}/lib/librpmio.a
+%{__prefix}/lib/librpmio.la
+%{__prefix}/lib/librpmio.so
 %{__prefix}/lib/librpmbuild.a
 %{__prefix}/lib/librpmbuild.la
 %{__prefix}/lib/librpmbuild.so
@@ -251,6 +255,9 @@ fi
 %{__prefix}/include/popt.h
 
 %changelog
+* Wed Jun  7 2000 Jeff Johnson <jbj@redhat.com>
+- create rpmio directory for librpmio.
+
 * Tue Jun  6 2000 Jeff Johnson <jbj@redhat.com>
 - require db3 in default configuration.
 
diff --git a/rpmio/.cvsignore b/rpmio/.cvsignore
new file mode 100644 (file)
index 0000000..dcf4bef
--- /dev/null
@@ -0,0 +1,7 @@
+.deps
+.depend
+Makefile
+Makefile.in
+.libs
+*.la
+*.lo
diff --git a/rpmio/Makefile.am b/rpmio/Makefile.am
new file mode 100644 (file)
index 0000000..202327c
--- /dev/null
@@ -0,0 +1,25 @@
+# Makefile for rpm library.
+
+AUTOMAKE_OPTIONS = 1.4 foreign
+
+INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/build -I$(top_srcdir)/lib \
+       -I$(top_srcdir)/popt @INCPATH@
+
+pkgincdir = $(pkgincludedir)
+pkginc_HEADERS = rpmio.h rpmurl.h
+
+lib_LTLIBRARIES = librpmio.la
+librpmio_la_SOURCES = rpmio.c url.c
+librpmio_la_LDFLAGS = -L$(top_builddir)/popt/.libs -lpopt
+librpmio_la_LIBADD = @LIBMISC@
+
+# XXX Drill out -L ldflags remnants until libtool-1.4 appears
+install-data-local:
+       @cd $(libdir) && \
+       sed -e "s|-L$(top_builddir)/popt/.libs ||" < librpmio.la > .librpmio.la && \
+       mv .librpmio.la librpmio.la
+
+.PHONY:        lclint
+.PHONY:        lclint
+lclint:
+       lclint $(DEFS) $(INCLUDES) $(librpmio_la_SOURCES)
diff --git a/rpmio/rpmio.c b/rpmio/rpmio.c
new file mode 100644 (file)
index 0000000..8d10dc2
--- /dev/null
@@ -0,0 +1,4074 @@
+#include "system.h"
+
+#include <stdarg.h>
+
+#ifdef __LCLINT__
+#define        ntohl(_x)       (_x)
+#define        ntohs(_x)       (_x)
+#define        htonl(_x)       (_x)
+#define        htons(_x)       (_x)
+typedef        unsigned int            uint32_t;
+#define        INADDR_ANY              ((uint32_t) 0x00000000)
+#define        IPPROTO_IP              0
+
+#else  /* __LCLINT__ */
+
+#if HAVE_MACHINE_TYPES_H
+# include <machine/types.h>
+#endif
+
+#include <netinet/in.h>
+#include <arpa/inet.h>         /* XXX for inet_aton and HP-UX */
+
+#if HAVE_NETINET_IN_SYSTM_H
+# include <sys/types.h>
+# include <netinet/in_systm.h>
+#endif
+
+#if HAVE_LIBIO_H && defined(_IO_BAD_SEEN)
+#define        _USE_LIBIO      1
+#endif
+
+#endif /* __LCLINT__ */
+
+#if HAVE_HERRNO && defined(__hpux) /* XXX HP-UX w/o -D_XOPEN_SOURCE needs */
+extern int h_errno;
+#endif
+
+#ifndef IPPORT_FTP
+#define IPPORT_FTP     21
+#endif
+#ifndef        IPPORT_HTTP
+#define        IPPORT_HTTP     80
+#endif
+
+
+#if !defined(HAVE_INET_ATON)
+static int inet_aton(const char *cp, struct in_addr *inp)
+{
+    long addr;
+
+    addr = inet_addr(cp);
+    if (addr == ((long) -1)) return 0;
+
+    memcpy(inp, &addr, sizeof(addr));
+    return 1;
+}
+#endif
+
+#if defined(USE_ALT_DNS) && USE_ALT_DNS
+#include "dns.h"
+#endif
+
+#include <rpmlib.h>
+#include <rpmio.h>
+#include <rpmurl.h>
+#include "misc.h"
+
+#include <assert.h>
+
+typedef struct _FDSTACK_s {
+       FDIO_t          io;
+/*@dependent@*/ void * fp;
+       int             fdno;
+} FDSTACK_t;
+
+typedef struct {
+       int             count;
+       off_t           bytes;
+       time_t          msecs;
+} OPSTAT_t;
+
+typedef        struct {
+       struct timeval  create;
+       struct timeval  begin;
+       OPSTAT_t        ops[4];
+#define        FDSTAT_READ     0
+#define        FDSTAT_WRITE    1
+#define        FDSTAT_SEEK     2
+#define        FDSTAT_CLOSE    3
+} FDSTAT_t;
+
+struct _FD_s {
+/*@refs@*/ int         nrefs;
+       int             flags;
+#define        RPMIO_DEBUG_IO          0x40000000
+#define        RPMIO_DEBUG_REFS        0x20000000
+       int             magic;
+#define        FDMAGIC         0xbeefdead
+
+       int             nfps;
+       FDSTACK_t       fps[8];
+       int             urlType;        /* ufdio: */
+
+/*@dependent@*/ void * url;            /* ufdio: URL info */
+       int             rd_timeoutsecs; /* ufdRead: per FD_t timer */
+       ssize_t         bytesRemain;    /* ufdio: */
+       ssize_t         contentLength;  /* ufdio: */
+       int             persist;        /* ufdio: */
+       int             wr_chunked;     /* ufdio: */
+
+       int             syserrno;       /* last system errno encountered */
+/*@observer@*/ const void *errcookie;  /* gzdio/bzdio/ufdio: */
+
+       FDSTAT_t        *stats;         /* I/O statistics */
+
+       int             ftpFileDoneNeeded; /* ufdio: (FTP) */
+       unsigned int    firstFree;      /* fadio: */
+       long int        fileSize;       /* fadio: */
+       long int        fd_cpioPos;     /* cpio: */
+};
+
+#define        FDSANE(fd)      assert(fd && fd->magic == FDMAGIC)
+#define FDNREFS(fd)    (fd ? ((FD_t)fd)->nrefs : -9)
+#define FDTO(fd)       (fd ? ((FD_t)fd)->rd_timeoutsecs : -99)
+#define FDCPIOPOS(fd)  (fd ? ((FD_t)fd)->fd_cpioPos : -99)
+
+#define        FDONLY(fd)      assert(fdGetIo(fd) == fdio)
+#define        GZDONLY(fd)     assert(fdGetIo(fd) == gzdio)
+#define        BZDONLY(fd)     assert(fdGetIo(fd) == bzdio)
+
+#define        UFDONLY(fd)     /* assert(fdGetIo(fd) == ufdio) */
+
+#define        fdGetFILE(_fd)  ((FILE *)fdGetFp(_fd))
+
+/*@access urlinfo@*/
+
+#if _USE_LIBIO
+int noLibio = 0;
+#else
+int noLibio = 1;
+#endif
+
+#define TIMEOUT_SECS 60
+static int ftpTimeoutSecs = TIMEOUT_SECS;
+static int httpTimeoutSecs = TIMEOUT_SECS;
+
+int _ftp_debug = 0;
+int _rpmio_debug = 0;
+#define        DBG(_f, _m, _x) \
+    if ((_rpmio_debug | ((_f) ? ((FD_t)(_f))->flags : 0)) & (_m)) fprintf _x
+
+#define DBGIO(_f, _x)  DBG((_f), RPMIO_DEBUG_IO, _x)
+#define DBGREFS(_f, _x)        DBG((_f), RPMIO_DEBUG_REFS, _x)
+
+/* =============================================================== */
+const FDIO_t fdGetIo(FD_t fd) {
+#ifdef NOISY
+DBGIO(0, (stderr, "==>\tfdGetIo(%p)\n", fd));
+#endif
+    FDSANE(fd);
+    return fd->fps[fd->nfps].io;
+}
+
+void fdSetIo(FD_t fd, FDIO_t io) {
+#ifdef NOISY
+DBGIO(0, (stderr, "==>\tfdSetIo(%p,%p) lvl %d \n", fd, io, (fd ? fd->nfps : -1)));
+#endif
+    FDSANE(fd);
+    fd->fps[fd->nfps].io = io;
+    return;
+}
+
+inline /*@dependent@*/ /*@null@*/ void * fdGetFp(FD_t fd) {
+#ifdef NOISY
+DBGIO(0, (stderr, "==>\tfdGetFp(%p) lvl %d\n", fd, (fd ? fd->nfps : -1)));
+#endif
+    FDSANE(fd);
+    return fd->fps[fd->nfps].fp;
+}
+
+static inline void fdSetFp(FD_t fd, /*@keep@*/ void * fp) {
+#ifdef NOISY
+DBGIO(0, (stderr, "==>\tfdSetFp(%p,%p) lvl %d\n", fd, fp, (fd ? fd->nfps : -1)));
+#endif
+    FDSANE(fd);
+    fd->fps[fd->nfps].fp = fp;
+}
+
+static inline int fdGetFdno(FD_t fd) {
+#ifdef NOISY
+DBGIO(0, (stderr, "==>\tfdGetFdno(%p) lvl %d\n", fd, (fd ? fd->nfps : -1)));
+#endif
+    FDSANE(fd);
+    return fd->fps[fd->nfps].fdno;
+}
+
+void fdSetFdno(FD_t fd, int fdno) {
+#ifdef NOISY
+DBGIO(0, (stderr, "==>\tfdSetFdno(%p,%d)\n", fd, fdno));
+#endif
+    FDSANE(fd);
+    fd->fps[fd->nfps].fdno = fdno;
+}
+
+void fdSetContentLength(FD_t fd, ssize_t contentLength)
+{
+    FDSANE(fd);
+    fd->contentLength = fd->bytesRemain = contentLength;
+}
+
+static /*@observer@*/ const char * fdbg(FD_t fd)
+{
+    static char buf[BUFSIZ];
+    char *be = buf;
+    int i;
+
+#if DYING
+    sprintf(be, "fd %p", fd);  be += strlen(be);
+    if (fd->rd_timeoutsecs >= 0) {
+       sprintf(be, " secs %d", fd->rd_timeoutsecs);
+       be += strlen(be);
+    }
+#endif
+    if (fd->bytesRemain != -1) {
+       sprintf(be, " clen %d", (int)fd->bytesRemain);
+       be += strlen(be);
+     }
+    if (fd->wr_chunked) {
+       strcpy(be, " chunked");
+       be += strlen(be);
+     }
+    *be++ = '\t';
+    for (i = fd->nfps; i >= 0; i--) {
+       FDSTACK_t * fps = &fd->fps[i];
+       if (i != fd->nfps)
+           *be++ = ' ';
+       *be++ = '|';
+       *be++ = ' ';
+       if (fps->io == fdio) {
+           sprintf(be, "FD %d fp %p", fps->fdno, fps->fp);
+       } else if (fps->io == ufdio) {
+           sprintf(be, "UFD %d fp %p", fps->fdno, fps->fp);
+       } else if (fps->io == fadio) {
+           sprintf(be, "FAD %d fp %p", fps->fdno, fps->fp);
+       } else if (fps->io == gzdio) {
+           sprintf(be, "GZD %p fdno %d", fps->fp, fps->fdno);
+#if HAVE_BZLIB_H
+       } else if (fps->io == bzdio) {
+           sprintf(be, "BZD %p fdno %d", fps->fp, fps->fdno);
+#endif
+       } else if (fps->io == fpio) {
+           sprintf(be, "%s %p(%d) fdno %d",
+               (fps->fdno < 0 ? "LIBIO" : "FP"),
+               fps->fp, fileno(((FILE *)fps->fp)), fps->fdno);
+       } else {
+           sprintf(be, "??? io %p fp %p fdno %d ???",
+               fps->io, fps->fp, fps->fdno);
+       }
+       be += strlen(be);
+       *be = '\0';
+    }
+    return buf;
+}
+
+inline void fdPush(FD_t fd, FDIO_t io, void * fp, int fdno) {
+    FDSANE(fd);
+    if (fd->nfps >= (sizeof(fd->fps)/sizeof(fd->fps[0]) - 1))
+       return;
+    fd->nfps++;
+    fdSetIo(fd, io);
+    fdSetFp(fd, fp);
+    fdSetFdno(fd, fdno);
+DBGIO(0, (stderr, "==>\tfdPush(%p,%p,%p,%d) lvl %d %s\n", fd, io, fp, fdno, fd->nfps, fdbg(fd)));
+}
+
+inline void fdPop(FD_t fd) {
+    FDSANE(fd);
+    if (fd->nfps < 0) return;
+DBGIO(0, (stderr, "==>\tfdPop(%p) lvl %d io %p fp %p fdno %d %s\n", fd, fd->nfps, fdGetIo(fd), fdGetFp(fd), fdGetFdno(fd), fdbg(fd)));
+    fdSetIo(fd, NULL);
+    fdSetFp(fd, NULL);
+    fdSetFdno(fd, -1);
+    fd->nfps--;
+}
+
+static inline void fdstat_enter(FD_t fd, int opx)
+{
+    if (fd->stats == NULL) return;
+    fd->stats->ops[opx].count++;
+    gettimeofday(&fd->stats->begin, NULL);
+}
+
+static inline time_t tvsub(struct timeval *etv, struct timeval *btv) {
+    time_t secs, usecs;
+    if (!(etv && btv)) return 0;
+    secs = etv->tv_sec - btv->tv_sec;
+    usecs = etv->tv_usec - btv->tv_usec;
+    while (usecs < 0) {
+       secs++;
+       usecs += 1000000;
+    }
+    return ((secs * 1000) + (usecs/1000));
+}
+
+static inline void fdstat_exit(FD_t fd, int opx, ssize_t rc)
+{
+    struct timeval end;
+    if (rc == -1) fd->syserrno = errno;
+    if (fd->stats == NULL) return;
+    gettimeofday(&end, NULL);
+    if (rc >= 0) {
+       switch(opx) {
+       case FDSTAT_SEEK:
+           fd->stats->ops[opx].bytes = rc;
+           break;
+       default:
+           fd->stats->ops[opx].bytes += rc;
+           if (fd->bytesRemain > 0) fd->bytesRemain -= rc;
+           break;
+       }
+    }
+    fd->stats->ops[opx].msecs += tvsub(&end, &fd->stats->begin);
+    fd->stats->begin = end;    /* structure assignment */
+}
+
+static void fdstat_print(FD_t fd, const char * msg, FILE * fp) {
+    int opx;
+    if (fd->stats == NULL) return;
+    for (opx = 0; opx < 4; opx++) {
+       OPSTAT_t *ops = &fd->stats->ops[opx];
+       if (ops->count <= 0) continue;
+       switch (opx) {
+       case FDSTAT_READ:
+           if (msg) fprintf(fp, "%s:", msg);
+           fprintf(fp, "%8d reads, %8ld total bytes in %d.%03d secs\n",
+               ops->count, (long)ops->bytes,
+               (int)(ops->msecs/1000), (int)(ops->msecs%1000));
+           break;
+       case FDSTAT_WRITE:
+           if (msg) fprintf(fp, "%s:", msg);
+           fprintf(fp, "%8d writes, %8ld total bytes in %d.%03d secs\n",
+               ops->count, (long)ops->bytes,
+               (int)(ops->msecs/1000), (int)(ops->msecs%1000));
+           break;
+       case FDSTAT_SEEK:
+           break;
+       case FDSTAT_CLOSE:
+           break;
+       }
+    }
+}
+
+/* =============================================================== */
+off_t fdSize(FD_t fd) {
+    struct stat sb;
+    off_t rc = -1; 
+
+#ifdef NOISY
+DBGIO(0, (stderr, "==>\tfdSize(%p) rc %ld\n", fd, (long)rc));
+#endif
+    FDSANE(fd);
+    if (fd->contentLength >= 0)
+       rc = fd->contentLength;
+    else switch (fd->urlType) {
+    case URL_IS_PATH:
+    case URL_IS_UNKNOWN:
+       if (fstat(Fileno(fd), &sb) == 0)
+           rc = sb.st_size;
+       /*@fallthrough@*/
+    case URL_IS_FTP:
+    case URL_IS_HTTP:
+    case URL_IS_DASH:
+       break;
+    }
+    return rc;
+}
+
+void fdSetSyserrno(FD_t fd, int syserrno, const void * errcookie) {
+    FDSANE(fd);
+    fd->syserrno = syserrno;
+    fd->errcookie = errcookie;
+}
+
+int fdGetRdTimeoutSecs(FD_t fd) {
+#ifdef NOISY
+DBGIO(0, (stderr, "==>\tfdGetRdTimeoutSecs(%p) timeout %d\n", fd, FDTO(fd)));
+#endif
+    FDSANE(fd);
+    return fd->rd_timeoutsecs;
+}
+
+#ifdef DYING
+int fdGetFtpFileDoneNeeded(FD_t fd) {
+    FDSANE(fd);
+    return fd->ftpFileDoneNeeded;
+}
+
+void fdSetFtpFileDoneNeeded(FD_t fd, int ftpFileDoneNeeded) {
+    FDSANE(fd);
+    fd->ftpFileDoneNeeded = ftpFileDoneNeeded;
+}
+#endif
+
+long int fdGetCpioPos(FD_t fd) {
+    FDSANE(fd);
+    return fd->fd_cpioPos;
+}
+
+void fdSetCpioPos(FD_t fd, long int cpioPos) {
+    FDSANE(fd);
+    fd->fd_cpioPos = cpioPos;
+}
+
+FD_t fdDup(int fdno) {
+    FD_t fd;
+    int nfdno;
+
+    if ((nfdno = dup(fdno)) < 0)
+       return NULL;
+    fd = fdNew("open (fdDup)");
+    fdSetFdno(fd, nfdno);
+DBGIO(fd, (stderr, "==> fdDup(%d) fd %p %s\n", fdno, fd, fdbg(fd)));
+    return fd;
+}
+
+static inline FD_t c2f(void * cookie) {
+       FD_t fd = (FD_t) cookie;
+       FDSANE(fd);
+       return fd;
+}
+
+#ifdef USE_COOKIE_SEEK_POINTER
+static inline int fdSeekNot(void * cookie,  /*@unused@*/ _IO_off64_t *pos,  /*@unused@*/ int whence) {
+#else
+static inline int fdSeekNot(void * cookie,  /*@unused@*/ off_t pos,  /*@unused@*/ int whence) {
+#endif
+    FD_t fd = c2f(cookie);
+    FDSANE(fd);                /* XXX keep gcc quiet */
+    return -2;
+}
+
+#ifdef UNUSED
+FILE *fdFdopen(void * cookie, const char *fmode) {
+    FD_t fd = c2f(cookie);
+    int fdno;
+    FILE * fp;
+
+    if (fmode == NULL) return NULL;
+    fdno = fdFileno(fd);
+    if (fdno < 0) return NULL;
+    fp = fdopen(fdno, fmode);
+DBGIO(fd, (stderr, "==> fdFdopen(%p,\"%s\") fdno %d -> fp %p fdno %d\n", cookie, fmode, fdno, fp, fileno(fp)));
+    fd = fdFree(fd, "open (fdFdopen)");
+    return fp;
+}
+#endif
+
+#undef fdRead
+#undef fdWrite
+#undef fdSeek
+#undef fdClose
+#if 0
+#undef fdLink
+#undef fdFree
+#undef fdNew
+#endif
+#undef fdFileno
+#undef fdOpen
+
+/* =============================================================== */
+static inline FD_t XfdLink(void * cookie, const char *msg, const char *file, unsigned line) {
+    FD_t fd;
+if (cookie == NULL)
+DBGREFS(0, (stderr, "--> fd  %p ++ %d %s at %s:%u\n", cookie, FDNREFS(cookie)+1, msg, file, line));
+    fd = c2f(cookie);
+    if (fd) {
+       fd->nrefs++;
+DBGREFS(fd, (stderr, "--> fd  %p ++ %d %s at %s:%u %s\n", fd, fd->nrefs, msg, file, line, fdbg(fd)));
+    }
+    return fd;
+}
+
+static inline /*@null@*/ FD_t XfdFree( /*@killref@*/ FD_t fd, const char *msg, const char *file, unsigned line) {
+if (fd == NULL)
+DBGREFS(0, (stderr, "--> fd  %p -- %d %s at %s:%u\n", fd, FDNREFS(fd), msg, file, line));
+    FDSANE(fd);
+    if (fd) {
+DBGREFS(fd, (stderr, "--> fd  %p -- %d %s at %s:%u %s\n", fd, fd->nrefs, msg, file, line, fdbg(fd)));
+       if (--fd->nrefs > 0)
+           /*@-refcounttrans@*/ return fd; /*@=refcounttrans@*/
+       if (fd->stats) free(fd->stats);
+       /*@-refcounttrans@*/ free(fd); /*@=refcounttrans@*/
+    }
+    return NULL;
+}
+
+static inline /*@null@*/ FD_t XfdNew(const char *msg, const char *file, unsigned line) {
+    FD_t fd = (FD_t) xmalloc(sizeof(struct _FD_s));
+    if (fd == NULL)
+       return NULL;
+    fd->nrefs = 0;
+    fd->flags = 0;
+    fd->magic = FDMAGIC;
+    fd->urlType = URL_IS_UNKNOWN;
+
+    fd->nfps = 0;
+    memset(fd->fps, 0, sizeof(fd->fps));
+
+    fd->fps[0].io = fdio;
+    fd->fps[0].fp = NULL;
+    fd->fps[0].fdno = -1;
+
+    fd->url = NULL;
+    fd->rd_timeoutsecs = 1;    /* XXX default value used to be -1 */
+    fd->contentLength = fd->bytesRemain = -1;
+    fd->wr_chunked = 0;
+    fd->syserrno = 0;
+    fd->errcookie = NULL;
+    fd->stats = calloc(1, sizeof(FDSTAT_t));
+    gettimeofday(&fd->stats->create, NULL);
+    fd->stats->begin = fd->stats->create;      /* structure assignment */
+
+    fd->ftpFileDoneNeeded = 0;
+    fd->firstFree = 0;
+    fd->fileSize = 0;
+    fd->fd_cpioPos = 0;
+
+    return XfdLink(fd, msg, file, line);
+}
+
+static inline int fdFileno(void * cookie) {
+    FD_t fd;
+    if (cookie == NULL) return -2;
+    fd = c2f(cookie);
+    return fd->fps[0].fdno;    /* XXX WRONG but expedient */
+}
+
+static inline ssize_t fdRead(void * cookie, /*@out@*/ char * buf, size_t count) {
+    FD_t fd = c2f(cookie);
+    ssize_t rc;
+
+    if (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);
+
+DBGIO(fd, (stderr, "==>\tfdRead(%p,%p,%ld) rc %ld %s\n", cookie, buf, (long)count, (long)rc, fdbg(fd)));
+
+    return rc;
+}
+
+static inline ssize_t fdWrite(void * cookie, const char * buf, size_t count) {
+    FD_t fd = c2f(cookie);
+    int fdno = fdFileno(fd);
+    ssize_t rc;
+
+    if (fd->bytesRemain == 0) return 0;        /* XXX simulate EOF */
+    if (fd->wr_chunked) {
+       char chunksize[20];
+       sprintf(chunksize, "%x\r\n", (unsigned)count);
+#ifdef DYING
+if (_ftp_debug)
+fprintf(stderr, "-> %s", chunksize);
+#endif
+       rc = write(fdno, chunksize, strlen(chunksize));
+       if (rc == -1)   fd->syserrno = errno;
+    }
+    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);
+
+    if (fd->wr_chunked) {
+       int ec;
+#ifdef DYING
+if (_ftp_debug)
+fprintf(stderr, "-> \r\n");
+#endif
+       ec = write(fdno, "\r\n", sizeof("\r\n")-1);
+       if (ec == -1)   fd->syserrno = errno;
+    }
+
+DBGIO(fd, (stderr, "==>\tfdWrite(%p,%p,%ld) rc %ld %s\n", cookie, buf, (long)count, (long)rc, fdbg(fd)));
+
+    return rc;
+}
+
+#ifdef USE_COOKIE_SEEK_POINTER
+static inline int fdSeek(void * cookie, _IO_off64_t *pos, int whence) {
+    _IO_off64_t p = *pos;
+#else
+static inline int fdSeek(void * cookie, off_t p, int whence) {
+#endif
+    FD_t fd = c2f(cookie);
+    off_t rc;
+
+    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, (long)rc, fdbg(fd)));
+
+    return rc;
+}
+
+static inline int fdClose( /*@only@*/ void * cookie) {
+    FD_t fd;
+    int fdno;
+    int rc;
+
+    if (cookie == NULL) return -2;
+    fd = c2f(cookie);
+    fdno = fdFileno(fd);
+
+    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, (long)rc, fdbg(fd)));
+
+    fd = fdFree(fd, "open (fdClose)");
+    return rc;
+}
+
+static inline /*@null@*/ FD_t fdOpen(const char *path, int flags, mode_t mode) {
+    FD_t fd;
+    int fdno;
+
+#ifdef DYING
+if (_rpmio_debug)
+fprintf(stderr, "*** fdOpen(%s,0x%x,0%o)\n", path, flags, (unsigned)mode);
+#endif
+    fdno = open(path, flags, mode);
+    if (fdno < 0) return NULL;
+    fd = fdNew("open (fdOpen)");
+    fdSetFdno(fd, fdno);
+    fd->flags = flags;
+DBGIO(fd, (stderr, "==>\tfdOpen(\"%s\",%x,0%o) %s\n", path, flags, (unsigned)mode, fdbg(fd)));
+    return fd;
+}
+
+static struct FDIO_s fdio_s = {
+  fdRead, fdWrite, fdSeek, fdClose, XfdLink, XfdFree, XfdNew, fdFileno,
+  fdOpen, NULL, fdGetFp, NULL, mkdir, chdir, rmdir, rename, unlink
+};
+FDIO_t fdio = /*@-compmempass@*/ &fdio_s /*@=compmempass@*/ ;
+
+int fdWritable(FD_t fd, int secs)
+{
+    int fdno;
+    fd_set wrfds;
+    struct timeval timeout, *tvp = (secs >= 0 ? &timeout : NULL);
+    int rc;
+       
+    if ((fdno = fdFileno(fd)) < 0)
+       return -1;      /* XXX W2DO? */
+       
+    FD_ZERO(&wrfds);
+    do {
+       FD_SET(fdno, &wrfds);
+
+       if (tvp) {
+           tvp->tv_sec = secs;
+           tvp->tv_usec = 0;
+       }
+       errno = 0;
+       rc = select(fdno + 1, NULL, &wrfds, NULL, tvp);
+
+if (_rpmio_debug && !(rc == 1 && errno == 0))
+fprintf(stderr, "*** fdWritable fdno %d rc %d %s\n", fdno, rc, strerror(errno));
+       if (rc < 0) {
+           switch (errno) {
+           case EINTR:
+               continue;
+               /*@notreached@*/ break;
+           default:
+               return rc;
+               /*@notreached@*/ break;
+           }
+       }
+       return rc;
+    } while (1);
+    /*@notreached@*/
+}
+
+int fdReadable(FD_t fd, int secs)
+{
+    int fdno;
+    fd_set rdfds;
+    struct timeval timeout, *tvp = (secs >= 0 ? &timeout : NULL);
+    int rc;
+
+    if ((fdno = fdFileno(fd)) < 0)
+       return -1;      /* XXX W2DO? */
+       
+    FD_ZERO(&rdfds);
+    do {
+       FD_SET(fdno, &rdfds);
+
+       if (tvp) {
+           tvp->tv_sec = secs;
+           tvp->tv_usec = 0;
+       }
+       errno = 0;
+       rc = select(fdno + 1, &rdfds, NULL, NULL, tvp);
+
+       if (rc < 0) {
+           switch (errno) {
+           case EINTR:
+               continue;
+               /*@notreached@*/ break;
+           default:
+               return rc;
+               /*@notreached@*/ break;
+           }
+       }
+       return rc;
+    } while (1);
+    /*@notreached@*/
+}
+
+static int fdFgets(FD_t fd, char * buf, size_t len)
+{
+    int fdno;
+    int secs = fd->rd_timeoutsecs;
+    size_t nb = 0;
+    int ec = 0;
+    char lastchar = '\0';
+
+    if ((fdno = fdFileno(fd)) < 0)
+       return 0;       /* XXX W2DO? */
+       
+    do {
+       int rc;
+
+       /* Is there data to read? */
+       rc = fdReadable(fd, secs);
+
+       switch (rc) {
+       case -1:        /* error */
+           ec = -1;
+           continue;
+           /*@notreached@*/ break;
+       case  0:        /* timeout */
+           ec = -1;
+           continue;
+           /*@notreached@*/ break;
+       default:        /* data to read */
+           break;
+       }
+
+       errno = 0;
+#ifdef NOISY
+       rc = fdRead(fd, buf + nb, 1);
+#else
+       rc = read(fdFileno(fd), buf + nb, 1);
+#endif
+       if (rc < 0) {
+           fd->syserrno = errno;
+           switch (errno) {
+           case EWOULDBLOCK:
+               continue;
+               /*@notreached@*/ break;
+           default:
+               break;
+           }
+if (_rpmio_debug)
+fprintf(stderr, "*** read: fd %p rc %d errno %d %s \"%s\"\n", fd, rc, errno, strerror(errno), buf);
+           ec = -1;
+           break;
+       } else if (rc == 0) {
+if (_rpmio_debug)
+fprintf(stderr, "*** read: fd %p rc %d EOF errno %d %s \"%s\"\n", fd, rc, errno, strerror(errno), buf);
+           break;
+       } else {
+           nb += rc;
+           buf[nb] = '\0';
+           lastchar = buf[nb - 1];
+       }
+    } while (ec == 0 && nb < len && lastchar != '\n');
+
+    return (ec >= 0 ? nb : ec);
+}
+
+/* =============================================================== */
+/* Support for FTP/HTTP I/O.
+ */
+const char *const ftpStrerror(int errorNumber) {
+  switch (errorNumber) {
+    case 0:
+       return _("Success");
+
+    case FTPERR_BAD_SERVER_RESPONSE:
+       return _("Bad server response");
+
+    case FTPERR_SERVER_IO_ERROR:
+       return _("Server IO error");
+
+    case FTPERR_SERVER_TIMEOUT:
+       return _("Server timeout");
+
+    case FTPERR_BAD_HOST_ADDR:
+       return _("Unable to lookup server host address");
+
+    case FTPERR_BAD_HOSTNAME:
+       return _("Unable to lookup server host name");
+
+    case FTPERR_FAILED_CONNECT:
+       return _("Failed to connect to server");
+
+    case FTPERR_FAILED_DATA_CONNECT:
+       return _("Failed to establish data connection to server");
+
+    case FTPERR_FILE_IO_ERROR:
+       return _("IO error to local file");
+
+    case FTPERR_PASSIVE_ERROR:
+       return _("Error setting remote server to passive mode");
+
+    case FTPERR_FILE_NOT_FOUND:
+       return _("File not found on server");
+
+    case FTPERR_NIC_ABORT_IN_PROGRESS:
+       return _("Abort in progress");
+
+    case FTPERR_UNKNOWN:
+    default:
+       return _("Unknown or unexpected error");
+  }
+}
+
+const char *urlStrerror(const char *url)
+{
+    const char *retstr;
+    switch (urlIsURL(url)) {
+    case URL_IS_FTP:
+    case URL_IS_HTTP:
+    {  urlinfo u;
+/* XXX This only works for httpReq/ftpLogin/ftpReq failures */
+       if (urlSplit(url, &u) == 0) {
+           retstr = ftpStrerror(u->openError);
+       } else
+           retstr = "Malformed URL";
+    }  break;
+    default:
+       retstr = strerror(errno);
+       break;
+    }
+    return retstr;
+}
+
+#if !defined(USE_ALT_DNS) || !USE_ALT_DNS 
+static int mygethostbyname(const char * host, struct in_addr * address)
+{
+    struct hostent * hostinfo;
+
+    hostinfo = /*@-unrecog@*/ gethostbyname(host) /*@=unrecog@*/;
+    if (!hostinfo) return 1;
+
+    memcpy(address, hostinfo->h_addr_list[0], sizeof(*address));
+    return 0;
+}
+#endif
+
+static int getHostAddress(const char * host, struct in_addr * address)
+{
+    if (isdigit(host[0])) {
+      if (! /*@-unrecog@*/ inet_aton(host, address) /*@=unrecog@*/ ) {
+         return FTPERR_BAD_HOST_ADDR;
+      }
+    } else {
+      if (mygethostbyname(host, address)) {
+         errno = h_errno;
+         return FTPERR_BAD_HOSTNAME;
+      }
+    }
+    
+    return 0;
+}
+
+static int tcpConnect(FD_t ctrl, const char *host, int port)
+{
+    struct sockaddr_in sin;
+    int fdno = -1;
+    int rc;
+
+    sin.sin_family = AF_INET;
+    sin.sin_port = htons(port);
+    sin.sin_addr.s_addr = INADDR_ANY;
+    
+  do {
+    if ((rc = getHostAddress(host, &sin.sin_addr)) < 0)
+       break;
+
+    if ((fdno = socket(sin.sin_family, SOCK_STREAM, IPPROTO_IP)) < 0) {
+       rc = FTPERR_FAILED_CONNECT;
+       break;
+    }
+
+    if (connect(fdno, (struct sockaddr *) &sin, sizeof(sin))) {
+       rc = FTPERR_FAILED_CONNECT;
+       break;
+    }
+  } while (0);
+
+    if (rc < 0)
+       goto errxit;
+
+if (_ftp_debug)
+fprintf(stderr,"++ connect %s:%d on fdno %d\n",
+/*@-unrecog@*/ inet_ntoa(sin.sin_addr) /*@=unrecog@*/ ,
+ntohs(sin.sin_port), fdno);
+
+    fdSetFdno(ctrl, (fdno >= 0 ? fdno : -1));
+    return 0;
+
+errxit:
+    fdSetSyserrno(ctrl, errno, ftpStrerror(rc));
+    if (fdno >= 0)
+       close(fdno);
+    return rc;
+}
+
+static int checkResponse(void * uu, FD_t ctrl, /*@out@*/ int *ecp, /*@out@*/ char ** str)
+{
+    urlinfo u = uu;
+    char *buf;
+    size_t bufAlloced;
+    int bufLength = 0; 
+    const char *s;
+    char *se;
+    int ec = 0;
+    int moretodo = 1;
+    char errorCode[4];
+    URLSANE(u);
+    if (u->bufAlloced == 0 || u->buf == NULL) {
+       u->bufAlloced = url_iobuf_size;
+       u->buf = xcalloc(u->bufAlloced, sizeof(char));
+    }
+    buf = u->buf;
+    bufAlloced = u->bufAlloced;
+    *buf = '\0';
+
+    errorCode[0] = '\0';
+    
+    do {
+       int rc;
+
+       /*
+        * Read next line from server.
+        */
+       se = buf + bufLength;
+       *se = '\0';
+       rc = fdFgets(ctrl, se, (bufAlloced - bufLength));
+       if (rc < 0) {
+           ec = FTPERR_BAD_SERVER_RESPONSE;
+           continue;
+       } else if (rc == 0 || fdWritable(ctrl, 0) < 1)
+           moretodo = 0;
+
+       /*
+        * Process next line from server.
+        */
+       for (s = se; *s != '\0'; s = se) {
+               const char *e;
+
+               while (*se && *se != '\n') se++;
+
+               if (se > s && se[-1] == '\r')
+                  se[-1] = '\0';
+               if (*se == '\0')
+                   break;
+
+if (_ftp_debug)
+fprintf(stderr, "<- %s\n", s);
+
+               /* HTTP: header termination on empty line */
+               if (*s == '\0') {
+                   moretodo = 0;
+                   break;
+               }
+               *se++ = '\0';
+
+               /* HTTP: look for "HTTP/1.1 123 ..." */
+               if (!strncmp(s, "HTTP", sizeof("HTTP")-1)) {
+                   ctrl->contentLength = -1;
+                   if ((e = strchr(s, '.')) != NULL) {
+                       e++;
+                       u->httpVersion = *e - '0';
+                       if (u->httpVersion < 1 || u->httpVersion > 2)
+                           ctrl->persist = u->httpVersion = 0;
+                       else
+                           ctrl->persist = 1;
+                   }
+                   if ((e = strchr(s, ' ')) != NULL) {
+                       e++;
+                       if (strchr("0123456789", *e))
+                           strncpy(errorCode, e, 3);
+                       errorCode[3] = '\0';
+                   }
+                   continue;
+               }
+
+               /* HTTP: look for "token: ..." */
+               for (e = s; *e && !(*e == ' ' || *e == ':'); e++)
+                   ;
+               if (e > s && *e++ == ':') {
+                   size_t ne = (e - s);
+                   while (*e && *e == ' ') e++;
+#if 0
+                   if (!strncmp(s, "Date:", ne)) {
+                   } else
+                   if (!strncmp(s, "Server:", ne)) {
+                   } else
+                   if (!strncmp(s, "Last-Modified:", ne)) {
+                   } else
+                   if (!strncmp(s, "ETag:", ne)) {
+                   } else
+#endif
+                   if (!strncmp(s, "Accept-Ranges:", ne)) {
+                       if (!strcmp(e, "bytes"))
+                           u->httpHasRange = 1;
+                       if (!strcmp(e, "none"))
+                           u->httpHasRange = 0;
+                   } else
+                   if (!strncmp(s, "Content-Length:", ne)) {
+                       if (strchr("0123456789", *e))
+                           ctrl->contentLength = atoi(e);
+                   } else
+                   if (!strncmp(s, "Connection:", ne)) {
+                       if (!strcmp(e, "close"))
+                           ctrl->persist = 0;
+                   } else
+#if 0
+                   if (!strncmp(s, "Content-Type:", ne)) {
+                   } else
+                   if (!strncmp(s, "Transfer-Encoding:", ne)) {
+                       if (!strcmp(e, "chunked"))
+                           ctrl->wr_chunked = 1;
+                       else
+                           ctrl->wr_chunked = 0;
+                   } else
+                   if (!strncmp(s, "Allow:", ne)) {
+                   } else
+#endif
+                       ;
+                   continue;
+               }
+
+               /* HTTP: look for "<TITLE>501 ... </TITLE>" */
+               if (!strncmp(s, "<TITLE>", sizeof("<TITLE>")-1))
+                   s += sizeof("<TITLE>") - 1;
+
+               /* FTP: look for "123-" and/or "123 " */
+               if (strchr("0123456789", *s)) {
+                   if (errorCode[0]) {
+                       if (!strncmp(s, errorCode, sizeof("123")-1) && s[3] == ' ')
+                           moretodo = 0;
+                   } else {
+                       strncpy(errorCode, s, sizeof("123")-1);
+                       errorCode[3] = '\0';
+                       if (s[3] != '-')
+                           moretodo = 0;
+                   }
+               }
+       }
+
+       if (moretodo && se > s) {
+           bufLength = se - s - 1;
+           if (s != buf)
+               memmove(buf, s, bufLength);
+       } else {
+           bufLength = 0;
+       }
+    } while (moretodo && ec == 0);
+
+    if (str)   *str = buf;
+    if (ecp)   *ecp = atoi(errorCode);
+
+    return ec;
+}
+
+static int ftpCheckResponse(urlinfo u, /*@out@*/ char ** str)
+{
+    int ec = 0;
+    int rc;
+
+    URLSANE(u);
+    rc = checkResponse(u, u->ctrl, &ec, str);
+
+    switch (ec) {
+    case 550:
+       return FTPERR_FILE_NOT_FOUND;
+       /*@notreached@*/ break;
+    case 552:
+       return FTPERR_NIC_ABORT_IN_PROGRESS;
+       /*@notreached@*/ break;
+    default:
+       if (ec >= 400 && ec <= 599) {
+           return FTPERR_BAD_SERVER_RESPONSE;
+       }
+       break;
+    }
+    return rc;
+}
+
+static int ftpCommand(urlinfo u, char ** str, ...)
+{
+    va_list ap;
+    int len = 0;
+    const char * s, * t;
+    char * te;
+    int rc;
+
+    URLSANE(u);
+    va_start(ap, str);
+    while ((s = va_arg(ap, const char *)) != NULL) {
+       if (len) len++;
+       len += strlen(s);
+    }
+    len += sizeof("\r\n")-1;
+    va_end(ap);
+
+    t = te = alloca(len + 1);
+
+    va_start(ap, str);
+    while ((s = va_arg(ap, const char *)) != NULL) {
+       if (te > t) *te++ = ' ';
+       te = stpcpy(te, s);
+    }
+    te = stpcpy(te, "\r\n");
+    va_end(ap);
+
+if (_ftp_debug)
+fprintf(stderr, "-> %s", t);
+    if (fdWrite(u->ctrl, t, (te-t)) != (te-t))
+       return FTPERR_SERVER_IO_ERROR;
+
+    rc = ftpCheckResponse(u, str);
+    return rc;
+}
+
+static int ftpLogin(urlinfo u)
+{
+    const char * host;
+    const char * user;
+    const char * password;
+    int port;
+    int rc;
+
+    URLSANE(u);
+    u->ctrl = fdLink(u->ctrl, "open ctrl");
+
+    if (((host = (u->proxyh ? u->proxyh : u->host)) == NULL)) {
+       rc = FTPERR_BAD_HOSTNAME;
+       goto errxit;
+    }
+
+    if ((port = (u->proxyp > 0 ? u->proxyp : u->port)) < 0) port = IPPORT_FTP;
+
+    if ((user = (u->proxyu ? u->proxyu : u->user)) == NULL)
+       user = "anonymous";
+
+    if ((password = u->password) == NULL) {
+       if (getuid()) {
+           struct passwd * pw = getpwuid(getuid());
+           char *myp = alloca(strlen(pw->pw_name) + sizeof("@"));
+           strcpy(myp, pw->pw_name);
+           strcat(myp, "@");
+           password = myp;
+       } else {
+           password = "root@";
+       }
+    }
+
+    if (fdFileno(u->ctrl) >= 0 && fdWritable(u->ctrl, 0) < 1)
+       fdClose(u->ctrl);
+
+    if (fdFileno(u->ctrl) < 0) {
+       rc = tcpConnect(u->ctrl, host, port);
+       if (rc < 0)
+           goto errxit2;
+    }
+
+    if ((rc = ftpCheckResponse(u, NULL)))
+       goto errxit;
+
+    if ((rc = ftpCommand(u, NULL, "USER", user, NULL)))
+       goto errxit;
+
+    if ((rc = ftpCommand(u, NULL, "PASS", password, NULL)))
+       goto errxit;
+
+    if ((rc = ftpCommand(u, NULL, "TYPE", "I", NULL)))
+       goto errxit;
+
+    return 0;
+
+errxit:
+    fdSetSyserrno(u->ctrl, errno, ftpStrerror(rc));
+errxit2:
+    if (fdFileno(u->ctrl) >= 0)
+       fdClose(u->ctrl);
+    return rc;
+}
+
+static int ftpReq(FD_t data, const char * ftpCmd, const char * ftpArg)
+{
+    urlinfo u = data->url;
+    struct sockaddr_in dataAddress;
+    char * cmd;
+    int cmdlen;
+    char * passReply;
+    char * chptr;
+    int rc;
+
+    URLSANE(u);
+    if (ftpCmd == NULL)
+       return FTPERR_UNKNOWN;  /* XXX W2DO? */
+
+    cmdlen = strlen(ftpCmd) + (ftpArg ? 1+strlen(ftpArg) : 0) + sizeof("\r\n");
+    chptr = cmd = alloca(cmdlen);
+    chptr = stpcpy(chptr, ftpCmd);
+    if (ftpArg) {
+       *chptr++ = ' ';
+       chptr = stpcpy(chptr, ftpArg);
+    }
+    chptr = stpcpy(chptr, "\r\n");
+    cmdlen = chptr - cmd;
+
+/*
+ * Get the ftp version of the Content-Length.
+ */
+    if (!strncmp(cmd, "RETR", 4)) {
+       unsigned cl;
+
+       passReply = NULL;
+       rc = ftpCommand(u, &passReply, "SIZE", ftpArg, NULL);
+       if (rc)
+           goto errxit;
+       if (sscanf(passReply, "%d %u", &rc, &cl) != 2) {
+           rc = FTPERR_BAD_SERVER_RESPONSE;
+           goto errxit;
+       }
+       rc = 0;
+       data->contentLength = cl;
+    }
+
+    passReply = NULL;
+    rc = ftpCommand(u, &passReply, "PASV", NULL);
+    if (rc) {
+       rc = FTPERR_PASSIVE_ERROR;
+       goto errxit;
+    }
+
+    chptr = passReply;
+    while (*chptr && *chptr != '(') chptr++;
+    if (*chptr != '(') return FTPERR_PASSIVE_ERROR; 
+    chptr++;
+    passReply = chptr;
+    while (*chptr && *chptr != ')') chptr++;
+    if (*chptr != ')') return FTPERR_PASSIVE_ERROR;
+    *chptr-- = '\0';
+
+    while (*chptr && *chptr != ',') chptr--;
+    if (*chptr != ',') return FTPERR_PASSIVE_ERROR;
+    chptr--;
+    while (*chptr && *chptr != ',') chptr--;
+    if (*chptr != ',') return FTPERR_PASSIVE_ERROR;
+    *chptr++ = '\0';
+    
+    /* now passReply points to the IP portion, and chptr points to the
+       port number portion */
+
+    {  int i, j;
+       dataAddress.sin_family = AF_INET;
+       if (sscanf(chptr, "%d,%d", &i, &j) != 2) {
+           rc = FTPERR_PASSIVE_ERROR;
+           goto errxit;
+       }
+       dataAddress.sin_port = htons((((unsigned)i) << 8) + j);
+    }
+
+    chptr = passReply;
+    while (*chptr++) {
+       if (*chptr == ',') *chptr = '.';
+    }
+
+    if (!inet_aton(passReply, &dataAddress.sin_addr)) {
+       rc = FTPERR_PASSIVE_ERROR;
+       goto errxit;
+    }
+
+    rc = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
+    fdSetFdno(data, (rc >= 0 ? rc : -1));
+    if (rc < 0) {
+       rc = FTPERR_FAILED_CONNECT;
+       goto errxit;
+    }
+    data = fdLink(data, "open data (ftpReq)");
+
+    /* XXX setsockopt SO_LINGER */
+    /* XXX setsockopt SO_KEEPALIVE */
+    /* XXX setsockopt SO_TOS IPTOS_THROUGHPUT */
+
+    while (connect(fdFileno(data), (struct sockaddr *) &dataAddress, 
+               sizeof(dataAddress)) < 0) {
+       if (errno == EINTR)
+           continue;
+       rc = FTPERR_FAILED_DATA_CONNECT;
+       goto errxit;
+    }
+
+if (_ftp_debug)
+fprintf(stderr, "-> %s", cmd);
+    if (fdWrite(u->ctrl, cmd, cmdlen) != cmdlen) {
+       rc = FTPERR_SERVER_IO_ERROR;
+       goto errxit;
+    }
+
+    if ((rc = ftpCheckResponse(u, NULL))) {
+       goto errxit;
+    }
+
+    data->ftpFileDoneNeeded = 1;
+    u->ctrl = fdLink(u->ctrl, "grab data (ftpReq)");
+    u->ctrl = fdLink(u->ctrl, "open data (ftpReq)");
+    return 0;
+
+errxit:
+    fdSetSyserrno(u->ctrl, errno, ftpStrerror(rc));
+    if (fdFileno(data) >= 0)
+       fdClose(data);
+    return rc;
+}
+
+static int urlConnect(const char * url, /*@out@*/ urlinfo * uret)
+{
+    urlinfo u;
+    int rc = 0;
+
+    if (urlSplit(url, &u) < 0)
+       return -1;
+
+    if (u->urltype == URL_IS_FTP) {
+       FD_t fd;
+
+       if ((fd = u->ctrl) == NULL) {
+           fd = u->ctrl = fdNew("persist ctrl (urlConnect FTP)");
+           fdSetIo(u->ctrl, ufdio);
+       }
+       
+       fd->rd_timeoutsecs = ftpTimeoutSecs;
+       fd->contentLength = fd->bytesRemain = -1;
+       fd->url = NULL;         /* XXX FTP ctrl has not */
+       fd->ftpFileDoneNeeded = 0;
+       fd = fdLink(fd, "grab ctrl (urlConnect FTP)");
+
+       if (fdFileno(u->ctrl) < 0) {
+           rpmMessage(RPMMESS_DEBUG, _("logging into %s as %s, pw %s\n"),
+                       u->host,
+                       u->user ? u->user : "ftp",
+                       u->password ? u->password : "(username)");
+
+           if ((rc = ftpLogin(u)) < 0) {       /* XXX save ftpLogin error */
+               u->ctrl = fdFree(fd, "grab ctrl (urlConnect FTP)");
+               u->openError = rc;
+           }
+       }
+    }
+
+    if (uret != NULL)
+       *uret = urlLink(u, "urlConnect");
+    u = urlFree(u, "urlSplit (urlConnect)");   
+
+    return rc;
+}
+
+/*@null@*/ static rpmCallbackFunction  urlNotify = NULL;
+/*@null@*/ static void *       urlNotifyData = NULL;
+static int                     urlNotifyCount = -1;
+
+void urlSetCallback(rpmCallbackFunction notify, void *notifyData, int notifyCount) {
+    urlNotify = notify;
+    urlNotifyData = notifyData;
+    urlNotifyCount = (notifyCount >= 0) ? notifyCount : 4096;
+}
+
+int ufdCopy(FD_t sfd, FD_t tfd)
+{
+    char buf[BUFSIZ];
+    int itemsRead;
+    int itemsCopied = 0;
+    int rc = 0;
+    int notifier = -1;
+
+    if (urlNotify) {
+       (void)(*urlNotify) (NULL, RPMCALLBACK_INST_OPEN_FILE,
+               0, 0, NULL, urlNotifyData);
+    }
+    
+    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 = FTPERR_FILE_IO_ERROR;
+           break;
+       }
+
+       itemsCopied += itemsRead;
+       if (urlNotify && urlNotifyCount > 0) {
+           int n = itemsCopied/urlNotifyCount;
+           if (n != notifier) {
+               (void)(*urlNotify) (NULL, RPMCALLBACK_INST_PROGRESS,
+                       itemsCopied, 0, NULL, urlNotifyData);
+               notifier = n;
+           }
+       }
+    }
+
+    DBGIO(sfd, (stderr, "++ copied %d bytes: %s\n", itemsCopied,
+       ftpStrerror(rc)));
+
+    if (urlNotify) {
+       (void)(*urlNotify) (NULL, RPMCALLBACK_INST_OPEN_FILE,
+               itemsCopied, itemsCopied, NULL, urlNotifyData);
+    }
+    
+    return rc;
+}
+
+int ufdGetFile(FD_t sfd, FD_t tfd)
+{
+    int rc;
+
+    FDSANE(sfd);
+    FDSANE(tfd);
+    rc = ufdCopy(sfd, tfd);
+    Fclose(sfd);
+    if (rc > 0)                /* XXX ufdCopy now returns no. bytes copied */
+       rc = 0;
+    return rc;
+}
+
+static int ftpCmd(const char * cmd, const char * url, const char * arg2) {
+    urlinfo u;
+    int rc;
+    const char * path;
+
+    if (urlConnect(url, &u) < 0)
+       return -1;
+
+    (void) urlPath(url, &path);
+
+    rc = ftpCommand(u, NULL, cmd, path, arg2, NULL);
+    u->ctrl = fdFree(u->ctrl, "grab ctrl (ftpCmd)");
+#ifdef DYING
+if (_rpmio_debug)
+fprintf(stderr, "*** ftpCmd %s %s %s rc %d\n", cmd, path, arg2, rc);
+#endif
+    return rc;
+}
+
+static int ftpMkdir(const char * path, /*@unused@*/ mode_t mode) {
+    int rc;
+    if ((rc = ftpCmd("MKD", path, NULL)) != 0)
+       return rc;
+#if NOTYET
+    {  char buf[20];
+       sprintf(buf, " 0%o", mode);
+       (void) ftpCmd("SITE CHMOD", path, buf);
+    }
+#endif
+    return rc;
+}
+
+static int ftpChdir(const char * path) {
+    return ftpCmd("CWD", path, NULL);
+}
+
+static int ftpRmdir(const char * path) {
+    return ftpCmd("RMD", path, NULL);
+}
+
+static int ftpRename(const char * oldpath, const char * newpath) {
+    int rc;
+    if ((rc = ftpCmd("RNFR", oldpath, NULL)) != 0)
+       return rc;
+    return ftpCmd("RNTO", newpath, NULL);
+}
+
+static int ftpUnlink(const char * path) {
+    return ftpCmd("DELE", path, NULL);
+}
+
+/* XXX these aren't worth the pain of including correctly */
+#if !defined(IAC)
+#define        IAC     255             /* interpret as command: */
+#endif
+#if !defined(IP)
+#define        IP      244             /* interrupt process--permanently */
+#endif
+#if !defined(DM)
+#define        DM      242             /* data mark--for connect. cleaning */
+#endif
+#if !defined(SHUT_RDWR)
+#define        SHUT_RDWR       1+1
+#endif
+
+static int ftpAbort(urlinfo u, FD_t data) {
+    static unsigned char ipbuf[3] = { IAC, IP, IAC };
+    FD_t ctrl;
+    int rc;
+    int tosecs;
+
+    URLSANE(u);
+
+    if (data != NULL) {
+       data->ftpFileDoneNeeded = 0;
+       if (fdFileno(data) >= 0)
+           u->ctrl = fdFree(u->ctrl, "open data (ftpAbort)");
+       u->ctrl = fdFree(u->ctrl, "grab data (ftpAbort)");
+    }
+    ctrl = u->ctrl;
+
+    DBGIO(0, (stderr, "-> ABOR\n"));
+
+    if (send(fdFileno(ctrl), ipbuf, sizeof(ipbuf), MSG_OOB) != sizeof(ipbuf)) {
+       fdClose(ctrl);
+       return FTPERR_SERVER_IO_ERROR;
+    }
+
+    sprintf(u->buf, "%cABOR\r\n",(char) DM);
+    if (fdWrite(ctrl, u->buf, 7) != 7) {
+       fdClose(ctrl);
+       return FTPERR_SERVER_IO_ERROR;
+    }
+
+    if (data && fdFileno(data) >= 0) {
+       /* XXX shorten data drain time wait */
+       tosecs = data->rd_timeoutsecs;
+       data->rd_timeoutsecs = 10;
+       if (fdReadable(data, data->rd_timeoutsecs) > 0) {
+           while (timedRead(data, u->buf, u->bufAlloced) > 0)
+               ;
+       }
+       data->rd_timeoutsecs = tosecs;
+       /* XXX ftp abort needs to close the data channel to receive status */
+       shutdown(fdFileno(data), SHUT_RDWR);
+       close(fdFileno(data));
+       data->fps[0].fdno = -1; /* XXX WRONG but expedient */
+    }
+
+    /* XXX shorten ctrl drain time wait */
+    tosecs = u->ctrl->rd_timeoutsecs;
+    u->ctrl->rd_timeoutsecs = 10;
+    if ((rc = ftpCheckResponse(u, NULL)) == FTPERR_NIC_ABORT_IN_PROGRESS) {
+       rc = ftpCheckResponse(u, NULL);
+    }
+    rc = ftpCheckResponse(u, NULL);
+    u->ctrl->rd_timeoutsecs = tosecs;
+
+    return rc;
+}
+
+static int ftpFileDone(urlinfo u, FD_t data)
+{
+    int rc = 0;
+
+    URLSANE(u);
+    assert(data->ftpFileDoneNeeded);
+
+    if (data->ftpFileDoneNeeded) {
+       data->ftpFileDoneNeeded = 0;
+       u->ctrl = fdFree(u->ctrl, "open data (ftpFileDone)");
+       u->ctrl = fdFree(u->ctrl, "grab data (ftpFileDone)");
+       rc = ftpCheckResponse(u, NULL);
+    }
+    return rc;
+}
+
+static int httpResp(urlinfo u, FD_t ctrl, /*@out@*/ char ** str)
+{
+    int ec = 0;
+    int rc;
+
+    URLSANE(u);
+    rc = checkResponse(u, ctrl, &ec, str);
+
+if (_ftp_debug && !(rc == 0 && ec == 200))
+fprintf(stderr, "*** httpResp: rc %d ec %d\n", rc, ec);
+
+    switch (ec) {
+    case 200:
+       break;
+    default:
+       rc = FTPERR_FILE_NOT_FOUND;
+       break;
+    }
+
+    return rc;
+}
+
+static int httpReq(FD_t ctrl, const char * httpCmd, const char * httpArg)
+{
+    urlinfo u = ctrl->url;
+    const char * host;
+    const char * path;
+    int port;
+    int rc;
+    char * req;
+    size_t len;
+    int retrying = 0;
+
+    URLSANE(u);
+    assert(ctrl != NULL);
+
+    if (((host = (u->proxyh ? u->proxyh : u->host)) == NULL))
+       return FTPERR_BAD_HOSTNAME;
+
+    if ((port = (u->proxyp > 0 ? u->proxyp : u->port)) < 0) port = 80;
+    path = (u->proxyh || u->proxyp > 0) ? u->url : httpArg;
+
+reopen:
+    if (fdFileno(ctrl) >= 0 && (rc = fdWritable(ctrl, 0)) < 1) {
+#ifdef DYING
+if (_ftp_debug)
+fprintf(stderr, "*** httpReq closing ctrl fdno %d rc %d\n", fdFileno(ctrl), rc);
+#endif
+       fdClose(ctrl);
+    }
+
+    if (fdFileno(ctrl) < 0) {
+       rc = tcpConnect(ctrl, host, port);
+       if (rc < 0)
+           goto errxit2;
+       ctrl = fdLink(ctrl, "open ctrl (httpReq)");
+    }
+
+    len = sizeof("\
+req x HTTP/1.0\r\n\
+User-Agent: rpm/3.0.4\r\n\
+Host: y:z\r\n\
+Accept: text/plain\r\n\
+Transfer-Encoding: chunked\r\n\
+\r\n\
+") + strlen(httpCmd) + strlen(path) + sizeof(VERSION) + strlen(host) + 20;
+
+    req = alloca(len);
+    *req = '\0';
+
+  if (!strcmp(httpCmd, "PUT")) {
+    sprintf(req, "\
+%s %s HTTP/1.%d\r\n\
+User-Agent: rpm/%s\r\n\
+Host: %s:%d\r\n\
+Accept: text/plain\r\n\
+Transfer-Encoding: chunked\r\n\
+\r\n\
+",     httpCmd, path, (u->httpVersion ? 1 : 0), VERSION, host, port);
+} else {
+    sprintf(req, "\
+%s %s HTTP/1.%d\r\n\
+User-Agent: rpm/%s\r\n\
+Host: %s:%d\r\n\
+Accept: text/plain\r\n\
+\r\n\
+",     httpCmd, path, (u->httpVersion ? 1 : 0), VERSION, host, port);
+}
+
+if (_ftp_debug)
+fprintf(stderr, "-> %s", req);
+
+    len = strlen(req);
+    if (fdWrite(ctrl, req, len) != len) {
+       rc = FTPERR_SERVER_IO_ERROR;
+       goto errxit;
+    }
+
+    if (!strcmp(httpCmd, "PUT")) {
+       ctrl->wr_chunked = 1;
+    } else {
+
+       rc = httpResp(u, ctrl, NULL);
+
+       if (rc) {
+           if (!retrying) {    /* not HTTP_OK */
+#ifdef DYING
+if (_ftp_debug)
+fprintf(stderr, "*** httpReq ctrl %p reopening ...\n", ctrl);
+#endif
+               retrying = 1;
+               fdClose(ctrl);
+               goto reopen;
+           }
+           goto errxit;
+       }
+    }
+
+    ctrl = fdLink(ctrl, "open data (httpReq)");
+    return 0;
+
+errxit:
+    fdSetSyserrno(ctrl, errno, ftpStrerror(rc));
+errxit2:
+    if (fdFileno(ctrl) >= 0)
+       fdClose(ctrl);
+    return rc;
+}
+
+/* XXX DYING: unused */
+void * ufdGetUrlinfo(FD_t fd) {
+    FDSANE(fd);
+    if (fd->url == NULL)
+       return NULL;
+    return urlLink(fd->url, "ufdGetUrlinfo");
+}
+
+/* =============================================================== */
+static ssize_t ufdRead(void * cookie, /*@out@*/ char * buf, size_t count) {
+    FD_t fd = c2f(cookie);
+    int bytesRead;
+    int total;
+
+    /* XXX preserve timedRead() behavior */
+    if (fdGetIo(fd) == fdio) {
+       struct stat sb;
+       int fdno = fdFileno(fd);
+       fstat(fdno, &sb);
+       if (S_ISREG(sb.st_mode))
+           return fdRead(fd, buf, count);
+    }
+
+    UFDONLY(fd);
+    assert(fd->rd_timeoutsecs >= 0);
+
+    for (total = 0; total < count; total += bytesRead) {
+
+       int rc;
+
+       bytesRead = 0;
+
+       /* Is there data to read? */
+       if (fd->bytesRemain == 0) return total; /* XXX simulate EOF */
+       rc = fdReadable(fd, fd->rd_timeoutsecs);
+
+       switch (rc) {
+       case -1:        /* error */
+       case  0:        /* timeout */
+           return total;
+           /*@notreached@*/ break;
+       default:        /* data to read */
+           break;
+       }
+
+       rc = fdRead(fd, buf + total, count - total);
+
+       if (rc < 0) {
+           switch (errno) {
+           case EWOULDBLOCK:
+               continue;
+               /*@notreached@*/ break;
+           default:
+               break;
+           }
+if (_rpmio_debug)
+fprintf(stderr, "*** read: rc %d errno %d %s \"%s\"\n", rc, errno, strerror(errno), buf);
+           return rc;
+           /*@notreached@*/ break;
+       } else if (rc == 0) {
+           return total;
+           /*@notreached@*/ break;
+       }
+       bytesRead = rc;
+    }
+
+    return count;
+}
+
+static ssize_t ufdWrite(void * cookie, const char * buf, size_t count)
+{
+    FD_t fd = c2f(cookie);
+    int bytesWritten;
+    int total = 0;
+
+#ifdef NOTYET
+    if (fdGetIo(fd) == fdio) {
+       struct stat sb;
+       fstat(fdGetFdno(fd), &sb);
+       if (S_ISREG(sb.st_mode))
+           return fdWrite(fd, buf, count);
+    }
+#endif
+
+    UFDONLY(fd);
+
+    for (total = 0; total < count; total += bytesWritten) {
+
+       int rc;
+
+       bytesWritten = 0;
+
+       /* Is there room to write data? */
+       if (fd->bytesRemain == 0) {
+fprintf(stderr, "*** ufdWrite fd %p WRITE PAST END OF CONTENT\n", fd);
+           return total;       /* XXX simulate EOF */
+       }
+       rc = fdWritable(fd, 2);         /* XXX configurable? */
+
+       switch (rc) {
+       case -1:        /* error */
+       case  0:        /* timeout */
+           return total;
+           /*@notreached@*/ break;
+       default:        /* data to write */
+           break;
+       }
+
+       rc = fdWrite(fd, buf + total, count - total);
+
+       if (rc < 0) {
+           switch (errno) {
+           case EWOULDBLOCK:
+               continue;
+               /*@notreached@*/ break;
+           default:
+               break;
+           }
+if (_rpmio_debug)
+fprintf(stderr, "*** write: rc %d errno %d %s \"%s\"\n", rc, errno, strerror(errno), buf);
+           return rc;
+           /*@notreached@*/ break;
+       } else if (rc == 0) {
+           return total;
+           /*@notreached@*/ break;
+       }
+       bytesWritten = rc;
+    }
+
+    return count;
+}
+
+#ifdef USE_COOKIE_SEEK_POINTER
+static inline int ufdSeek(void * cookie, _IO_off64_t *pos, int whence) {
+#else
+static inline int ufdSeek(void * cookie, off_t pos, int whence) {
+#endif
+    FD_t fd = c2f(cookie);
+
+    switch (fd->urlType) {
+    case URL_IS_UNKNOWN:
+    case URL_IS_PATH:
+       break;
+    case URL_IS_DASH:
+    case URL_IS_FTP:
+    case URL_IS_HTTP:
+    default:
+        return -2;
+       /*@notreached@*/ break;
+    }
+    return fdSeek(cookie, pos, whence);
+}
+
+static int ufdClose( /*@only@*/ void * cookie)
+{
+    FD_t fd = c2f(cookie);
+
+    UFDONLY(fd);
+
+    if (fd->url) {
+       urlinfo u = fd->url;
+
+       if (fd == u->data)
+               fd = u->data = fdFree(fd, "grab data (ufdClose persist)");
+       else
+               fd = fdFree(fd, "grab data (ufdClose)");
+       (void) urlFree(fd->url, "url (ufdClose)");
+       fd->url = NULL;
+       u->ctrl = fdFree(u->ctrl, "grab ctrl (ufdClose)");
+
+       if (u->urltype == URL_IS_FTP) {
+
+           /* XXX if not using libio, lose the fp from fpio */
+           {   FILE * fp = fdGetFILE(fd);
+               if (noLibio && fp)
+                   fdSetFp(fd, NULL);
+           }
+
+           /*
+            * Normal FTP has 4 refs on the data fd:
+            *  "persist data (ufdOpen FTP)"            rpmio.c:888
+            *  "grab data (ufdOpen FTP)"               rpmio.c:892
+            *  "open data (ftpReq)"                    ftp.c:633
+            *  "fopencookie"                           rpmio.c:1507
+            */
+
+           /*
+            * Normal FTP has 5 refs on the ctrl fd:
+            *  "persist ctrl"                          url.c:176
+            *  "grab ctrl (urlConnect FTP)"            rpmio.c:404
+            *  "open ctrl"                             ftp.c:504
+            *  "grab data (ftpReq)"                    ftp.c:661
+            *  "open data (ftpReq)"                    ftp.c:662
+            */
+           if (fd->bytesRemain > 0) {
+               if (fd->ftpFileDoneNeeded) {
+                   if (fdReadable(u->ctrl, 0) > 0)
+                       ftpFileDone(u, fd);
+                   else
+                       ftpAbort(u, fd);
+               }
+           } else {
+               int rc;
+               /* XXX STOR et al require close before ftpFileDone */
+               rc = fdClose(fd);
+#if 0  /* XXX error exit from ufdOpen does not have this set */
+               assert(fd->ftpFileDoneNeeded != 0);
+#endif
+               if (fd->ftpFileDoneNeeded)
+                   ftpFileDone(u, fd);
+               return rc;
+           }
+       }
+
+       if (!strcmp(u->service, "http")) {
+           if (fd->wr_chunked) {
+               int rc;
+           /* XXX HTTP PUT requires terminating 0 length chunk. */
+               fdWrite(fd, NULL, 0);
+               fd->wr_chunked = 0;
+           /* XXX HTTP PUT requires terminating entity-header. */
+if (_ftp_debug)
+fprintf(stderr, "-> \r\n");
+               (void) fdWrite(fd, "\r\n", sizeof("\r\n")-1);
+               rc = httpResp(u, fd, NULL);
+           }
+
+           if (fd == u->ctrl)
+               fd = u->ctrl = fdFree(fd, "open data (ufdClose HTTP persist ctrl)");
+           else if (fd == u->data)
+               fd = u->data = fdFree(fd, "open data (ufdClose HTTP persist data)");
+           else
+               fd = fdFree(fd, "open data (ufdClose HTTP)");
+
+           /*
+            * HTTP has 4 (or 5 if persistent malloc) refs on the fd:
+            *  "persist ctrl"                          url.c:177
+            *  "grab ctrl (ufdOpen HTTP)"              rpmio.c:924
+            *  "grab data (ufdOpen HTTP)"              rpmio.c:928
+            *  "open ctrl (httpReq)"                   ftp.c:382
+            *  "open data (httpReq)"                   ftp.c:435
+            */
+
+           /* XXX if not using libio, lose the fp from fpio */
+           {   FILE * fp = fdGetFILE(fd);
+               if (noLibio && fp)
+                   fdSetFp(fd, NULL);
+           }
+
+           if (fd->persist && u->httpVersion &&
+               (fd == u->ctrl || fd == u->data) && fd->bytesRemain == 0) {
+               fd->contentLength = fd->bytesRemain = -1;
+               return 0;
+           } else {
+               fd->contentLength = fd->bytesRemain = -1;
+           }
+       }
+    }
+    return fdClose(fd);
+}
+
+static /*@null@*/ FD_t ftpOpen(const char *url, /*@unused@*/ int flags,
+               /*@unused@*/ mode_t mode, /*@out@*/ urlinfo *uret)
+{
+    urlinfo u = NULL;
+    FD_t fd = NULL;
+
+#if 0  /* XXX makeTempFile() heartburn */
+    assert(!(flags & O_RDWR));
+#endif
+    if (urlConnect(url, &u) < 0)
+       goto exit;
+
+    if (u->data == NULL)
+       u->data = fdNew("persist data (ftpOpen)");
+
+    if (u->data->url == NULL)
+       fd = fdLink(u->data, "grab data (ftpOpen persist data)");
+    else
+       fd = fdNew("grab data (ftpOpen)");
+
+    if (fd) {
+       fdSetIo(fd, ufdio);
+       fd->ftpFileDoneNeeded = 0;
+       fd->rd_timeoutsecs = ftpTimeoutSecs;
+       fd->contentLength = fd->bytesRemain = -1;
+       fd->url = urlLink(u, "url (ufdOpen FTP)");
+       fd->urlType = URL_IS_FTP;
+    }
+
+exit:
+    if (uret)
+       *uret = u;
+    return fd;
+}
+
+static /*@null@*/ FD_t httpOpen(const char *url, int flags, mode_t mode,
+               /*@out@*/ urlinfo *uret)
+{
+    urlinfo u = NULL;
+    FD_t fd = NULL;
+
+#if 0  /* XXX makeTempFile() heartburn */
+    assert(!(flags & O_RDWR));
+#endif
+    if (urlSplit(url, &u))
+       goto exit;
+
+    if (u->ctrl == NULL)
+       u->ctrl = fdNew("persist ctrl (httpOpen)");
+    if (u->ctrl->nrefs > 2 && u->data == NULL)
+       u->data = fdNew("persist data (httpOpen)");
+
+    if (u->ctrl->url == NULL)
+       fd = fdLink(u->ctrl, "grab ctrl (httpOpen persist ctrl)");
+    else if (u->data->url == NULL)
+       fd = fdLink(u->data, "grab ctrl (httpOpen persist data)");
+    else
+       fd = fdNew("grab ctrl (httpOpen)");
+
+    if (fd) {
+       fdSetIo(fd, ufdio);
+       fd->ftpFileDoneNeeded = 0;
+       fd->rd_timeoutsecs = httpTimeoutSecs;
+       fd->contentLength = fd->bytesRemain = -1;
+       fd->url = urlLink(u, "url (httpOpen)");
+       fd = fdLink(fd, "grab data (httpOpen)");
+       fd->urlType = URL_IS_HTTP;
+    }
+
+exit:
+    if (uret)
+       *uret = u;
+    return fd;
+}
+
+static /*@null@*/ FD_t ufdOpen(const char *url, int flags, mode_t mode)
+{
+    FD_t fd = NULL;
+    const char * cmd;
+    urlinfo u;
+    const char * path;
+    urltype urlType = urlPath(url, &path);
+
+if (_rpmio_debug)
+fprintf(stderr, "*** ufdOpen(%s,0x%x,0%o)\n", url, flags, (unsigned)mode);
+
+    switch (urlType) {
+    case URL_IS_FTP:
+       fd = ftpOpen(url, flags, mode, &u);
+       if (fd == NULL || u == NULL)
+           break;
+
+       /* XXX W2DO? use STOU rather than STOR to prevent clobbering */
+       cmd = ((flags & O_WRONLY) 
+               ?  ((flags & O_APPEND) ? "APPE" :
+                  ((flags & O_CREAT) ? "STOR" : "STOR"))
+               :  ((flags & O_CREAT) ? "STOR" : "RETR"));
+       u->openError = ftpReq(fd, cmd, path);
+       if (u->openError < 0) {
+           /* XXX make sure that we can exit through ufdClose */
+           fd = fdLink(fd, "error data (ufdOpen FTP)");
+       } else {
+           fd->bytesRemain = ((!strcmp(cmd, "RETR"))
+               ?  fd->contentLength : -1);
+           fd->wr_chunked = 0;
+       }
+       break;
+    case URL_IS_HTTP:
+       fd = httpOpen(url, flags, mode, &u);
+       if (fd == NULL || u == NULL)
+           break;
+
+       cmd = ((flags & O_WRONLY)
+               ?  ((flags & O_APPEND) ? "PUT" :
+                  ((flags & O_CREAT) ? "PUT" : "PUT"))
+               : "GET");
+       u->openError = httpReq(fd, cmd, path);
+       if (u->openError < 0) {
+           /* XXX make sure that we can exit through ufdClose */
+           fd = fdLink(fd, "error ctrl (ufdOpen HTTP)");
+           fd = fdLink(fd, "error data (ufdOpen HTTP)");
+       } else {
+           fd->bytesRemain = ((!strcmp(cmd, "GET"))
+               ?  fd->contentLength : -1);
+           fd->wr_chunked = ((!strcmp(cmd, "PUT"))
+               ?  fd->wr_chunked : 0);
+       }
+       break;
+    case URL_IS_DASH:
+       assert(!(flags & O_RDWR));
+       fd = fdDup( ((flags & O_WRONLY) ? STDOUT_FILENO : STDIN_FILENO) );
+       if (fd) {
+           fdSetIo(fd, ufdio);
+           fd->rd_timeoutsecs = 600;   /* XXX W2DO? 10 mins? */
+           fd->contentLength = fd->bytesRemain = -1;
+       }
+       break;
+    case URL_IS_PATH:
+    case URL_IS_UNKNOWN:
+    default:
+       fd = fdOpen(path, flags, mode);
+       if (fd) {
+           fdSetIo(fd, ufdio);
+           fd->rd_timeoutsecs = 1;
+           fd->contentLength = fd->bytesRemain = -1;
+       }
+       break;
+    }
+
+    if (fd == NULL) return NULL;
+    fd->urlType = urlType;
+    if (Fileno(fd) < 0) {
+       ufdClose(fd);
+       return NULL;
+    }
+DBGIO(fd, (stderr, "==>\tufdOpen(\"%s\",%x,0%o) %s\n", url, flags, (unsigned)mode, fdbg(fd)));
+    return fd;
+}
+
+static struct FDIO_s ufdio_s = {
+  ufdRead, ufdWrite, ufdSeek, ufdClose, XfdLink, XfdFree, XfdNew, fdFileno,
+  ufdOpen, NULL, fdGetFp, NULL,        Mkdir, Chdir, Rmdir, Rename, Unlink
+};
+FDIO_t ufdio = /*@-compmempass@*/ &ufdio_s /*@=compmempass@*/ ;
+
+/* =============================================================== */
+/* Support for first fit File Allocation I/O.
+ */
+long int fadGetFileSize(FD_t fd) {
+    FDSANE(fd);
+    return fd->fileSize;
+}
+
+void fadSetFileSize(FD_t fd, long int fileSize) {
+    FDSANE(fd);
+    fd->fileSize = fileSize;
+}
+
+unsigned int fadGetFirstFree(FD_t fd) {
+    FDSANE(fd);
+    return fd->firstFree;
+}
+
+void fadSetFirstFree(FD_t fd, unsigned int firstFree) {
+    FDSANE(fd);
+    fd->firstFree = firstFree;
+}
+
+/* =============================================================== */
+#ifdef DYING
+extern fdio_open_function_t fadOpen;
+static struct FDIO_s fadio_s = {
+  fdRead, fdWrite, fdSeek, fdClose, XfdLink, XfdFree, XfdNew, fdFileno,
+  fadOpen, NULL, fdGetFp,      NULL, NULL, NULL, NULL, NULL
+};
+FDIO_t fadio = /*@-compmempass@*/ &fadio_s /*@=compmempass@*/ ;
+#else
+extern FDIO_t fadio;
+#endif
+
+/* =============================================================== */
+/* Support for GZIP library.
+ */
+#ifdef HAVE_ZLIB_H
+
+#include <zlib.h>
+
+static inline /*@dependent@*/ /*@null@*/ void * gzdFileno(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 != gzdio)
+           continue;
+       rc = fps->fp;
+       break;
+    }
+    
+    return rc;
+}
+
+static /*@null@*/ FD_t gzdOpen(const char *path, const char *fmode) {
+    FD_t fd;
+    gzFile *gzfile;
+    if ((gzfile = gzopen(path, fmode)) == NULL)
+       return NULL;
+    fd = fdNew("open (gzdOpen)");
+    fdPop(fd); fdPush(fd, gzdio, gzfile, -1);
+    
+DBGIO(fd, (stderr, "==>\tgzdOpen(\"%s\", \"%s\") fd %p %s\n", path, fmode, fd, fdbg(fd)));
+    return fdLink(fd, "gzdOpen");
+}
+
+static /*@null@*/ FD_t gzdFdopen(void * cookie, const char *fmode) {
+    FD_t fd = c2f(cookie);
+    int fdno;
+    gzFile *gzfile;
+
+    if (fmode == NULL) return NULL;
+    fdno = fdFileno(fd);
+    fdSetFdno(fd, -1);         /* XXX skip the fdio close */
+    if (fdno < 0) return NULL;
+    gzfile = gzdopen(fdno, fmode);
+    if (gzfile == NULL) return NULL;
+
+    fdPush(fd, gzdio, gzfile, fdno);           /* Push gzdio onto stack */
+
+    return fdLink(fd, "gzdFdopen");
+}
+
+static int gzdFlush(FD_t fd) {
+    return gzflush(gzdFileno(fd), Z_SYNC_FLUSH);       /* XXX W2DO? */
+}
+
+/* =============================================================== */
+static ssize_t gzdRead(void * cookie, /*@out@*/ char * buf, size_t count) {
+    FD_t fd = c2f(cookie);
+    gzFile *gzfile;
+    ssize_t rc;
+
+    if (fd->bytesRemain == 0) return 0;        /* XXX simulate EOF */
+    gzfile = gzdFileno(fd);
+    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, (long)rc, fdbg(fd)));
+    if (rc < 0) {
+       int zerror = 0;
+       fd->errcookie = gzerror(gzfile, &zerror);
+       if (zerror == Z_ERRNO) {
+           fd->syserrno = errno;
+           fd->errcookie = strerror(fd->syserrno);
+       }
+    } else if (rc >= 0) {
+       fdstat_exit(fd, FDSTAT_READ, rc);
+    }
+    return rc;
+}
+
+static ssize_t gzdWrite(void * cookie, const char * buf, size_t count) {
+    FD_t fd = c2f(cookie);
+    gzFile *gzfile;
+    ssize_t rc;
+
+    if (fd->bytesRemain == 0) return 0;        /* XXX simulate EOF */
+    gzfile = gzdFileno(fd);
+    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, (long)rc, fdbg(fd)));
+    if (rc < 0) {
+       int zerror = 0;
+       fd->errcookie = gzerror(gzfile, &zerror);
+       if (zerror == Z_ERRNO) {
+           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 */
+#ifdef USE_COOKIE_SEEK_POINTER
+static inline int gzdSeek(void * cookie, _IO_off64_t *pos, int whence) {
+    _IO_off64_t p = *pos;
+#else
+static inline int gzdSeek(void * cookie, off_t p, int whence) {
+#endif
+    int rc;
+#if HAVE_GZSEEK
+    FD_t fd = c2f(cookie);
+    gzFile *gzfile;
+
+    assert(fd->bytesRemain == -1);     /* XXX FIXME */
+    gzfile = gzdFileno(fd);
+    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, (long)rc, fdbg(fd)));
+    if (rc < 0) {
+       int zerror = 0;
+       fd->errcookie = gzerror(gzfile, &zerror);
+       if (zerror == Z_ERRNO) {
+           fd->syserrno = errno;
+           fd->errcookie = strerror(fd->syserrno);
+       }
+    } else if (rc >= 0) {
+       fdstat_exit(fd, FDSTAT_SEEK, rc);
+    }
+#else
+    rc = -2;
+#endif
+    return rc;
+}
+
+static int gzdClose( /*@only@*/ void * cookie) {
+    FD_t fd = c2f(cookie);
+    gzFile *gzfile;
+    int rc;
+
+    gzfile = gzdFileno(fd);
+
+    if (gzfile == NULL) return -2;
+    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 = gzerror(gzfile, &rc);
+           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, (long)rc, fdbg(fd)));
+
+    if (_rpmio_debug || rpmIsDebug()) fdstat_print(fd, "GZDIO", stderr);
+    if (rc == 0)
+       fd = fdFree(fd, "open (gzdClose)");
+    return rc;
+}
+
+static struct FDIO_s gzdio_s = {
+  gzdRead, gzdWrite, gzdSeek, gzdClose, XfdLink, XfdFree, XfdNew, fdFileno,
+  NULL, gzdOpen, gzdFileno, gzdFlush,  NULL, NULL, NULL, NULL, NULL
+};
+FDIO_t gzdio = /*@-compmempass@*/ &gzdio_s /*@=compmempass@*/ ;
+
+#endif /* HAVE_ZLIB_H */
+
+/* =============================================================== */
+/* 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 inline /*@dependent@*/ /*@null@*/ void * bzdFileno(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 != bzdio)
+           continue;
+       rc = fps->fp;
+       break;
+    }
+    
+    return rc;
+}
+
+static /*@null@*/ FD_t bzdOpen(const char *path, const char *mode) {
+    FD_t fd;
+    BZFILE *bzfile;;
+    if ((bzfile = bzopen(path, mode)) == NULL)
+       return NULL;
+    fd = fdNew("open (bzdOpen)");
+    fdPop(fd); fdPush(fd, bzdio, bzfile, -1);
+    return fdLink(fd, "bzdOpen");
+}
+
+static /*@null@*/ FD_t bzdFdopen(void * cookie, const char * fmode) {
+    FD_t fd = c2f(cookie);
+    int fdno;
+    BZFILE *bzfile;
+
+    if (fmode == NULL) return NULL;
+    fdno = fdFileno(fd);
+    fdSetFdno(fd, -1);         /* XXX skip the fdio close */
+    if (fdno < 0) return NULL;
+    bzfile = bzdopen(fdno, fmode);
+    if (bzfile == NULL) return NULL;
+
+    fdPush(fd, bzdio, bzfile, fdno);           /* Push bzdio onto stack */
+
+    return fdLink(fd, "bzdFdopen");
+}
+
+static int bzdFlush(FD_t fd) {
+    return bzflush(bzdFileno(fd));
+}
+
+/* =============================================================== */
+static ssize_t bzdRead(void * cookie, /*@out@*/ char * buf, size_t count) {
+    FD_t fd = c2f(cookie);
+    BZFILE *bzfile;
+    ssize_t rc;
+
+    if (fd->bytesRemain == 0) return 0;        /* XXX simulate EOF */
+    bzfile = bzdFileno(fd);
+    fdstat_enter(fd, FDSTAT_READ);
+    rc = bzread(bzfile, buf, count);
+    if (rc == -1) {
+       int zerror = 0;
+       fd->errcookie = bzerror(bzfile, &zerror);
+    } else if (rc >= 0) {
+       fdstat_exit(fd, FDSTAT_READ, rc);
+    }
+    return rc;
+}
+
+static ssize_t bzdWrite(void * cookie, const char * buf, size_t count) {
+    FD_t fd = c2f(cookie);
+    BZFILE *bzfile;
+    ssize_t rc;
+
+    if (fd->bytesRemain == 0) return 0;        /* XXX simulate EOF */
+    bzfile = bzdFileno(fd);
+    fdstat_enter(fd, FDSTAT_WRITE);
+    rc = 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);
+    }
+    return rc;
+}
+
+#ifdef USE_COOKIE_SEEK_POINTER
+static inline int bzdSeek(void * cookie, _IO_off64_t *pos, int whence) {
+#else
+static inline int bzdSeek(void * cookie, off_t p, int whence) {
+#endif
+    FD_t fd = c2f(cookie);
+
+    BZDONLY(fd);
+    return -2;
+}
+
+static int bzdClose( /*@only@*/ void * cookie) {
+    FD_t fd = c2f(cookie);
+    BZFILE *bzfile;
+    int rc;
+
+    bzfile = bzdFileno(fd);
+
+    if (bzfile == NULL) return -2;
+    fdstat_enter(fd, FDSTAT_CLOSE);
+    bzclose(bzfile);
+    rc = 0;    /* XXX FIXME */
+
+    /* XXX TODO: preserve fd if errors */
+
+    if (fd) {
+       if (rc == -1) {
+           int zerror = 0;
+           fd->errcookie = bzerror(bzfile, &zerror);
+       } else if (rc >= 0) {
+           fdstat_exit(fd, FDSTAT_CLOSE, rc);
+       }
+    }
+
+DBGIO(fd, (stderr, "==>\tbzdClose(%p) rc %lx %s\n", cookie, (long)rc, fdbg(fd)));
+
+    if (_rpmio_debug || rpmIsDebug()) fdstat_print(fd, "BZDIO", stderr);
+    if (rc == 0)
+       fd = fdFree(fd, "open (bzdClose)");
+    return rc;
+}
+
+static struct FDIO_s bzdio_s = {
+  bzdRead, bzdWrite, bzdSeek, bzdClose, XfdLink, XfdFree, XfdNew, fdFileno,
+  NULL, bzdOpen, bzdFileno, bzdFlush,  NULL, NULL, NULL, NULL, NULL
+};
+FDIO_t bzdio = /*@-compmempass@*/ &bzdio_s /*@=compmempass@*/ ;
+
+#endif /* HAVE_BZLIB_H */
+
+/* =============================================================== */
+/*@observer@*/ static const char * getFdErrstr (FD_t fd) {
+    const char *errstr = NULL;
+
+#ifdef HAVE_ZLIB_H
+    if (fdGetIo(fd) == gzdio) {
+       errstr = fd->errcookie;
+    } else
+#endif /* HAVE_ZLIB_H */
+
+#ifdef HAVE_BZLIB_H
+    if (fdGetIo(fd) == bzdio) {
+       errstr = fd->errcookie;
+    } else
+#endif /* HAVE_BZLIB_H */
+
+    {
+       errstr = strerror(fd->syserrno);
+    }
+
+    return errstr;
+}
+
+/* =============================================================== */
+
+const char *Fstrerror(FD_t fd) {
+    if (fd == NULL)
+       return strerror(errno);
+    FDSANE(fd);
+    return getFdErrstr(fd);
+}
+
+#define        FDIOVEC(_fd, _vec)      \
+  ((fdGetIo(_fd) && fdGetIo(_fd)->_vec) ? fdGetIo(_fd)->_vec : NULL)
+
+size_t Fread(void *buf, size_t size, size_t nmemb, FD_t fd) {
+    fdio_read_function_t *_read;
+    int rc;
+
+    FDSANE(fd);
+#ifdef __LCLINT__
+    *(char *)buf = '\0';
+#endif
+DBGIO(fd, (stderr, "==> Fread(%p,%u,%u,%p) %s\n", buf, (unsigned)size, (unsigned)nmemb, fd, fdbg(fd)));
+
+    if (fdGetIo(fd) == fpio) {
+       rc = fread(buf, size, nmemb, fdGetFILE(fd));
+       return rc;
+    }
+
+    _read = FDIOVEC(fd, read);
+
+    rc = (_read ? (*_read) (fd, buf, size * nmemb) : -2);
+    return rc;
+}
+
+size_t Fwrite(const void *buf, size_t size, size_t nmemb, FD_t fd) {
+    fdio_write_function_t *_write;
+    int rc;
+
+    FDSANE(fd);
+DBGIO(fd, (stderr, "==> Fwrite(%p,%u,%u,%p) %s\n", buf, (unsigned)size, (unsigned)nmemb, fd, fdbg(fd)));
+
+    if (fdGetIo(fd) == fpio) {
+       rc = fwrite(buf, size, nmemb, fdGetFILE(fd));
+       return rc;
+    }
+
+    _write = FDIOVEC(fd, write);
+
+    rc = (_write ? _write(fd, buf, size * nmemb) : -2);
+    return rc;
+}
+
+#ifdef USE_COOKIE_SEEK_POINTER
+int Fseek(FD_t fd, _IO_off64_t offset, int whence) {
+#else 
+int Fseek(FD_t fd, off_t offset, int whence) {
+#endif
+    fdio_seek_function_t *_seek;
+    long int rc;
+
+    FDSANE(fd);
+DBGIO(fd, (stderr, "==> Fseek(%p,%ld,%d) %s\n", fd, (long)offset, whence, fdbg(fd)));
+
+    if (fdGetIo(fd) == fpio) {
+       FILE *f;
+
+       f = fdGetFILE(fd);
+       rc = fseek(f, offset, whence);
+       return rc;
+    }
+
+    _seek = FDIOVEC(fd, seek);
+
+#ifdef USE_COOKIE_SEEK_POINTER
+    rc = (_seek ? _seek(fd, &offset, whence) : -2);
+#else
+    rc = (_seek ? _seek(fd, offset, whence) : -2);
+#endif
+    return rc;
+}
+
+int Fclose(FD_t fd) {
+    int rc, ec = 0;
+
+    FDSANE(fd);
+DBGIO(fd, (stderr, "==> Fclose(%p) %s\n", fd, fdbg(fd)));
+
+    fd = fdLink(fd, "Fclose");
+    while (fd->nfps >= 0) {
+       FDSTACK_t * fps = &fd->fps[fd->nfps];
+       
+       if (fps->io == fpio) {
+           FILE *fp = fdGetFILE(fd);
+           int fpno = fileno(fp);
+
+       /* XXX persistent HTTP/1.1 returns the previously opened fp */
+           if (fd->nfps > 0 && fpno == -1 &&
+               fd->fps[fd->nfps-1].io == ufdio &&
+               fd->fps[fd->nfps-1].fp == fp &&
+               fd->fps[fd->nfps-1].fdno >= 0)
+           {
+               fflush(fp);
+               fd->nfps--;
+               rc = ufdClose(fd);
+               if (fdGetFdno(fd) >= 0)
+                   break;
+               fdSetFp(fd, NULL);
+               fd->nfps++;
+               rc = fclose(fp);
+               fdPop(fd);
+               if (noLibio)
+                   fdSetFp(fd, NULL);
+           } else {
+               rc = fclose(fp);
+               if (fpno == -1) {
+                   fd = fdFree(fd, "fopencookie (Fclose)");
+                   fdPop(fd);
+               }
+           }
+       } else {
+           fdio_close_function_t * _close = FDIOVEC(fd, close);
+           rc = _close(fd);
+       }
+       if (fd->nfps == 0)
+           break;
+       if (ec == 0 && rc)
+           ec = rc;
+       fdPop(fd);
+    }
+    fd = fdFree(fd, "Fclose");
+    return ec;
+}
+
+/*
+ * Convert stdio fmode to open(2) mode, filtering out zlib/bzlib flags.
+ *     returns stdio[0] = '\0' on error.
+ *
+ * gzopen:     [0-9] is compession level
+ * gzopen:     'f' is filtered (Z_FILTERED)
+ * gzopen:     'h' is Huffman encoding (Z_HUFFMAN_ONLY)
+ * bzopen:     [1-9] is block size (modulo 100K)
+ * bzopen:     's' is smallmode
+ * HACK:       '.' terminates, rest is type of I/O
+ */
+static inline void cvtfmode (const char *m,
+                               /*@out@*/ char *stdio, size_t nstdio,
+                               /*@out@*/ char *other, size_t nother,
+                               /*@out@*/ const char **end, /*@out@*/ int * f)
+{
+    int flags = 0;
+    char c;
+
+    switch (*m) {
+    case 'a':
+       flags |= O_WRONLY | O_CREAT | O_APPEND;
+       if (--nstdio > 0) *stdio++ = *m;
+       break;
+    case 'w':
+       flags |= O_WRONLY | O_CREAT | O_TRUNC;
+       if (--nstdio > 0) *stdio++ = *m;
+       break;
+    case 'r':
+       flags |= O_RDONLY;
+       if (--nstdio > 0) *stdio++ = *m;
+       break;
+    default:
+       *stdio = '\0';
+       return;
+       /*@notreached@*/ break;
+    }
+    m++;
+
+    while ((c = *m++) != '\0') {
+       switch (c) {
+       case '.':
+           break;
+       case '+':
+           flags &= ~(O_RDONLY|O_WRONLY);
+           flags |= O_RDWR;
+           if (--nstdio > 0) *stdio++ = c;
+           continue;
+       case 'b':
+           if (--nstdio > 0) *stdio++ = c;
+           continue;
+       case 'x':
+           flags |= O_EXCL;
+           if (--nstdio > 0) *stdio++ = c;
+           continue;
+       default:
+           if (--nother > 0) *other++ = c;
+           continue;
+       }
+       break;
+    }
+
+    *stdio = *other = '\0';
+    if (end)
+       *end = (*m ? m : NULL);
+    if (f)
+       *f = flags;
+}
+
+#if _USE_LIBIO
+#if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ == 0
+/* XXX retrofit glibc-2.1.x typedef on glibc-2.0.x systems */
+typedef _IO_cookie_io_functions_t cookie_io_functions_t;
+#endif
+#endif
+
+FD_t Fdopen(FD_t ofd, const char *fmode)
+{
+    char stdio[20], other[20], zstdio[20];
+    const char *end = NULL;
+    FDIO_t iof = NULL;
+    FD_t fd = ofd;
+
+if (_rpmio_debug)
+fprintf(stderr, "*** Fdopen(%p,%s) %s\n", fd, fmode, fdbg(fd));
+    FDSANE(fd);
+
+    if (fmode == NULL)
+       return NULL;
+
+    cvtfmode(fmode, stdio, sizeof(stdio), other, sizeof(other), &end, NULL);
+    if (stdio[0] == '\0')
+       return NULL;
+    zstdio[0] = '\0';
+    strncat(zstdio, stdio, sizeof(zstdio) - strlen(zstdio));
+    strncat(zstdio, other, sizeof(zstdio) - strlen(zstdio));
+
+    if (end == NULL && other[0] == '\0')
+       return fd;
+
+    if (end && *end) {
+       if (!strcmp(end, "fdio")) {
+           iof = fdio;
+       } else if (!strcmp(end, "gzdio")) {
+           iof = gzdio;
+           fd = gzdFdopen(fd, zstdio);
+#if HAVE_BZLIB_H
+       } else if (!strcmp(end, "bzdio")) {
+           iof = bzdio;
+           fd = bzdFdopen(fd, zstdio);
+#endif
+       } else if (!strcmp(end, "ufdio")) {
+           iof = ufdio;
+       } else if (!strcmp(end, "fadio")) {
+           iof = fadio;
+       } else if (!strcmp(end, "fpio")) {
+           iof = fpio;
+           if (noLibio) {
+               int fdno = Fileno(fd);
+               FILE * fp = fdopen(fdno, stdio);
+if (_rpmio_debug)
+fprintf(stderr, "*** Fdopen fpio fp %p\n", fp);
+               if (fp == NULL)
+                   return NULL;
+               /* XXX gzdio/bzdio use fp for private data */
+               if (fdGetFp(fd) == NULL)
+                   fdSetFp(fd, fp);
+               fdPush(fd, fpio, fp, fdno);     /* Push fpio onto stack */
+           }
+       }
+    } else if (other[0]) {
+       for (end = other; *end && strchr("0123456789fh", *end); end++)
+           ;
+       if (*end == '\0') {
+           iof = gzdio;
+           fd = gzdFdopen(fd, zstdio);
+       }
+    }
+    if (iof == NULL)
+       return fd;
+
+    if (!noLibio) {
+       FILE * fp = NULL;
+
+#if _USE_LIBIO
+       {   cookie_io_functions_t ciof;
+           ciof.read = iof->read;
+           ciof.write = iof->write;
+           ciof.seek = iof->seek;
+           ciof.close = iof->close;
+           fp = fopencookie(fd, stdio, ciof);
+DBGIO(fd, (stderr, "==> fopencookie(%p,\"%s\",*%p) returns fp %p\n", fd, stdio, iof, fp));
+       }
+#endif
+
+       if (fp) {
+           /* XXX gzdio/bzdio use fp for private data */
+           if (fdGetFp(fd) == NULL)
+               fdSetFp(fd, fp);
+           fdPush(fd, fpio, fp, fileno(fp));   /* Push fpio onto stack */
+           fd = fdLink(fd, "fopencookie");
+       }
+    }
+
+DBGIO(fd, (stderr, "==> Fdopen(%p,\"%s\") returns fd %p %s\n", ofd, fmode, fd, fdbg(fd)));
+    return fd;
+}
+
+FD_t Fopen(const char *path, const char *fmode)
+{
+    char stdio[20], other[20];
+    const char *end = NULL;
+    mode_t perms = 0666;
+    int flags;
+    FD_t fd;
+
+    if (path == NULL || fmode == NULL)
+       return NULL;
+
+    cvtfmode(fmode, stdio, sizeof(stdio), other, sizeof(other), &end, &flags);
+    if (stdio[0] == '\0')
+       return NULL;
+
+    if (end == NULL || !strcmp(end, "fdio")) {
+if (_rpmio_debug)
+fprintf(stderr, "*** Fopen fdio path %s fmode %s\n", path, fmode);
+       fd = fdOpen(path, flags, perms);
+       if (fdFileno(fd) < 0) {
+           fdClose(fd);
+           return NULL;
+       }
+    } else if (!strcmp(end, "fadio")) {
+if (_rpmio_debug)
+fprintf(stderr, "*** Fopen fadio path %s fmode %s\n", path, fmode);
+       fd = fadio->_open(path, flags, perms);
+       if (fdFileno(fd) < 0) {
+           fdClose(fd);
+           return NULL;
+       }
+    } else {
+       FILE *fp;
+       int fdno;
+       int isHTTP = 0;
+
+       /* XXX gzdio and bzdio here too */
+
+       switch (urlIsURL(path)) {
+       case URL_IS_HTTP:
+           isHTTP = 1;
+           /*@fallthrough@*/
+       case URL_IS_PATH:
+       case URL_IS_DASH:
+       case URL_IS_FTP:
+       case URL_IS_UNKNOWN:
+if (_rpmio_debug)
+fprintf(stderr, "*** Fopen ufdio path %s fmode %s\n", path, fmode);
+           fd = ufdOpen(path, flags, perms);
+           if (fd == NULL || fdFileno(fd) < 0)
+               return fd;
+           break;
+       default:
+if (_rpmio_debug)
+fprintf(stderr, "*** Fopen WTFO path %s fmode %s\n", path, fmode);
+           return NULL;
+           /*@notreached@*/ break;
+       }
+
+       /* XXX persistent HTTP/1.1 returns the previously opened fp */
+       if (isHTTP && ((fp = fdGetFp(fd)) != NULL) && ((fdno = fdGetFdno(fd)) >= 0)) {
+           fdPush(fd, fpio, fp, fileno(fp));   /* Push fpio onto stack */
+           return fd;
+       }
+    }
+
+    fd = Fdopen(fd, fmode);
+    return fd;
+}
+
+int Fflush(FD_t fd)
+{
+    if (fd == NULL) return -1;
+    if (fdGetIo(fd) == fpio)
+       return fflush(fdGetFILE(fd));
+    if (fdGetIo(fd) == gzdio)
+       return gzdFlush(fdGetFp(fd));
+#if HAVE_BZLIB_H
+    if (fdGetIo(fd) == bzdio)
+       return bzdFlush(fdGetFp(fd));
+#endif
+    return 0;
+}
+
+int Ferror(FD_t fd) {
+    int i, rc = 0;
+
+    if (fd == NULL) return -1;
+    for (i = fd->nfps; rc == 0 && i >= 0; i--) {
+       FDSTACK_t * fps = &fd->fps[i];
+       int ec;
+       
+       if (fps->io == fpio) {
+           ec = ferror(fdGetFILE(fd));
+       } else if (fps->io == gzdio) {
+           ec = (fd->syserrno  || fd->errcookie != NULL) ? -1 : 0;
+#if HAVE_BZLIB_H
+       } else if (fps->io == bzdio) {
+           ec = (fd->syserrno  || fd->errcookie != NULL) ? -1 : 0;
+#endif
+       } else {
+       /* XXX need to check ufdio/gzdio/bzdio/fdio errors correctly. */
+           ec = (fdFileno(fd) < 0 ? -1 : 0);
+       }
+
+       if (rc == 0 && ec)
+           rc = ec;
+    }
+DBGIO(fd, (stderr, "==> Ferror(%p) rc %d %s\n", fd, rc, fdbg(fd)));
+    return rc;
+}
+
+int Fileno(FD_t fd) {
+    int i, rc = -1;
+
+    for (i = fd->nfps ; rc == -1 && i >= 0; i--) {
+       rc = fd->fps[i].fdno;
+    }
+DBGIO(fd, (stderr, "==> Fileno(%p) rc %d %s\n", fd, rc, fdbg(fd)));
+    return rc;
+}
+
+/* XXX this is naive */
+int Fcntl(FD_t fd, int op, void *lip) {
+    return fcntl(Fileno(fd), op, lip);
+}
+
+/* =============================================================== */
+/* Helper routines that may be generally useful.
+ */
+
+/* XXX falloc.c: analogues to pread(3)/pwrite(3). */
+#ifdef USE_COOKIE_SEEK_POINTER
+ssize_t Pread(FD_t fd, void * buf, size_t count, _IO_off64_t offset) {
+#else
+ssize_t Pread(FD_t fd, void * buf, size_t count, off_t offset) {
+#endif
+    if (Fseek(fd, offset, SEEK_SET) < 0)
+       return -1;
+    return Fread(buf, sizeof(char), count, fd);
+}
+
+#ifdef USE_COOKIE_SEEK_POINTER
+ssize_t Pwrite(FD_t fd, const void * buf, size_t count, _IO_off64_t offset) {
+#else
+ssize_t Pwrite(FD_t fd, const void * buf, size_t count, off_t offset) {
+#endif
+    if (Fseek(fd, offset, SEEK_SET) < 0)
+       return -1;
+    return Fwrite(buf, sizeof(char), count, fd);
+}
+
+/* XXX rebuilddb.c: analogues to mkdir(2)/rmdir(2). */
+int Mkdir (const char *path, mode_t mode) {
+    const char * lpath;
+    int ut = urlPath(path, &lpath);
+
+    switch (ut) {
+    case URL_IS_FTP:
+       return ftpMkdir(path, mode);
+       /*@notreached@*/ break;
+    case URL_IS_HTTP:          /* XXX WRONG WRONG WRONG */
+    case URL_IS_PATH:
+       path = lpath;
+       /*@fallthrough@*/
+    case URL_IS_UNKNOWN:
+       break;
+    case URL_IS_DASH:
+    default:
+       return -2;
+       /*@notreached@*/ break;
+    }
+    return mkdir(path, mode);
+}
+
+int Chdir (const char *path) {
+    const char * lpath;
+    int ut = urlPath(path, &lpath);
+
+    switch (ut) {
+    case URL_IS_FTP:
+       return ftpChdir(path);
+       /*@notreached@*/ break;
+    case URL_IS_HTTP:          /* XXX WRONG WRONG WRONG */
+    case URL_IS_PATH:
+       path = lpath;
+       /*@fallthrough@*/
+    case URL_IS_UNKNOWN:
+       break;
+    case URL_IS_DASH:
+    default:
+       return -2;
+       /*@notreached@*/ break;
+    }
+    return chdir(path);
+}
+
+int Rmdir (const char *path) {
+    const char * lpath;
+    int ut = urlPath(path, &lpath);
+
+    switch (ut) {
+    case URL_IS_FTP:
+       return ftpRmdir(path);
+       /*@notreached@*/ break;
+    case URL_IS_HTTP:          /* XXX WRONG WRONG WRONG */
+    case URL_IS_PATH:
+       path = lpath;
+       /*@fallthrough@*/
+    case URL_IS_UNKNOWN:
+       break;
+    case URL_IS_DASH:
+    default:
+       return -2;
+       /*@notreached@*/ break;
+    }
+    return rmdir(path);
+}
+
+/* XXX rpmdb.c: analogue to rename(2). */
+
+int Rename (const char *oldpath, const char * newpath) {
+    const char *oe = NULL;
+    const char *ne = NULL;
+    int oldut, newut;
+
+    /* XXX lib/install.c used to rely on this behavior. */
+    if (!strcmp(oldpath, newpath)) return 0;
+
+    oldut = urlPath(oldpath, &oe);
+    switch (oldut) {
+    case URL_IS_FTP:           /* XXX WRONG WRONG WRONG */
+    case URL_IS_HTTP:          /* XXX WRONG WRONG WRONG */
+    case URL_IS_PATH:
+    case URL_IS_UNKNOWN:
+       break;
+    case URL_IS_DASH:
+    default:
+       return -2;
+       /*@notreached@*/ break;
+    }
+
+    newut = urlPath(newpath, &ne);
+    switch (newut) {
+    case URL_IS_FTP:
+if (_rpmio_debug)
+fprintf(stderr, "*** rename old %*s new %*s\n", (int)(oe - oldpath), oldpath, (int)(ne - newpath), newpath);
+       if (!(oldut == newut && oe && ne && (oe - oldpath) == (ne - newpath) &&
+           !strncasecmp(oldpath, newpath, (oe - oldpath))))
+           return -2;
+       return ftpRename(oldpath, newpath);
+       /*@notreached@*/ break;
+    case URL_IS_HTTP:          /* XXX WRONG WRONG WRONG */
+    case URL_IS_PATH:
+       oldpath = oe;
+       newpath = ne;
+       break;
+    case URL_IS_UNKNOWN:
+       break;
+    case URL_IS_DASH:
+    default:
+       return -2;
+       /*@notreached@*/ break;
+    }
+    return rename(oldpath, newpath);
+}
+
+int Link (const char *oldpath, const char * newpath) {
+    const char *oe = NULL;
+    const char *ne = NULL;
+    int oldut, newut;
+
+    oldut = urlPath(oldpath, &oe);
+    switch (oldut) {
+    case URL_IS_FTP:           /* XXX WRONG WRONG WRONG */
+    case URL_IS_HTTP:          /* XXX WRONG WRONG WRONG */
+    case URL_IS_PATH:
+    case URL_IS_UNKNOWN:
+       break;
+    case URL_IS_DASH:
+    default:
+       return -2;
+       /*@notreached@*/ break;
+    }
+
+    newut = urlPath(newpath, &ne);
+    switch (newut) {
+    case URL_IS_HTTP:          /* XXX WRONG WRONG WRONG */
+    case URL_IS_FTP:           /* XXX WRONG WRONG WRONG */
+    case URL_IS_PATH:
+if (_rpmio_debug)
+fprintf(stderr, "*** link old %*s new %*s\n", (int)(oe - oldpath), oldpath, (int)(ne - newpath), newpath);
+       if (!(oldut == newut && oe && ne && (oe - oldpath) == (ne - newpath) &&
+           !strncasecmp(oldpath, newpath, (oe - oldpath))))
+           return -2;
+       oldpath = oe;
+       newpath = ne;
+       break;
+    case URL_IS_UNKNOWN:
+       break;
+    case URL_IS_DASH:
+    default:
+       return -2;
+       /*@notreached@*/ break;
+    }
+    return link(oldpath, newpath);
+}
+
+/* XXX build/build.c: analogue to unlink(2). */
+
+int Unlink(const char * path) {
+    const char * lpath;
+    int ut = urlPath(path, &lpath);
+
+    switch (ut) {
+    case URL_IS_FTP:
+       return ftpUnlink(path);
+       /*@notreached@*/ break;
+    case URL_IS_HTTP:          /* XXX WRONG WRONG WRONG */
+    case URL_IS_PATH:
+       path = lpath;
+       /*@fallthrough@*/
+    case URL_IS_UNKNOWN:
+       break;
+    case URL_IS_DASH:
+    default:
+       return -2;
+       /*@notreached@*/ break;
+    }
+    return unlink(path);
+}
+
+/* XXX swiped from mc-4.5.39-pre9 vfs/ftpfs.c */
+
+#define        g_strdup        xstrdup
+#define        g_free          xfree
+
+/*
+ * FIXME: this is broken. It depends on mc not crossing border on month!
+ */
+static int current_mday;
+static int current_mon;
+static int current_year;
+
+/* Following stuff (parse_ls_lga) is used by ftpfs and extfs */
+#define MAXCOLS                30
+
+static char *columns [MAXCOLS];        /* Points to the string in column n */
+static int   column_ptr [MAXCOLS]; /* Index from 0 to the starting positions of the columns */
+
+static int
+vfs_split_text (char *p)
+{
+    char *original = p;
+    int  numcols;
+
+
+    for (numcols = 0; *p && numcols < MAXCOLS; numcols++){
+       while (*p == ' ' || *p == '\r' || *p == '\n'){
+           *p = 0;
+           p++;
+       }
+       columns [numcols] = p;
+       column_ptr [numcols] = p - original;
+       while (*p && *p != ' ' && *p != '\r' && *p != '\n')
+           p++;
+    }
+    return numcols;
+}
+
+static int
+is_num (int idx)
+{
+    if (!columns [idx] || columns [idx][0] < '0' || columns [idx][0] > '9')
+       return 0;
+    return 1;
+}
+
+static int
+is_dos_date(char *str)
+{
+    if (strlen(str) == 8 && str[2] == str[5] && strchr("\\-/", (int)str[2]) != NULL)
+       return (1);
+
+    return (0);
+}
+
+static int
+is_week (char *str, struct tm *tim)
+{
+    static char *week = "SunMonTueWedThuFriSat";
+    char *pos;
+
+    if((pos=strstr(week, str)) != NULL){
+        if(tim != NULL)
+           tim->tm_wday = (pos - week)/3;
+       return (1);
+    }
+    return (0);    
+}
+
+static int
+is_month (char *str, struct tm *tim)
+{
+    static char *month = "JanFebMarAprMayJunJulAugSepOctNovDec";
+    char *pos;
+    
+    if((pos=strstr(month, str)) != NULL){
+        if(tim != NULL)
+           tim->tm_mon = (pos - month)/3;
+       return (1);
+    }
+    return (0);
+}
+
+static int
+is_time (char *str, struct tm *tim)
+{
+    char *p, *p2;
+
+    if ((p=strchr(str, ':')) && (p2=strrchr(str, ':'))) {
+       if (p != p2) {
+           if (sscanf (str, "%2d:%2d:%2d", &tim->tm_hour, &tim->tm_min, &tim->tm_sec) != 3)
+               return (0);
+       }
+       else {
+           if (sscanf (str, "%2d:%2d", &tim->tm_hour, &tim->tm_min) != 2)
+               return (0);
+       }
+    }
+    else 
+        return (0);
+    
+    return (1);
+}
+
+static int is_year(char *str, struct tm *tim)
+{
+    long year;
+
+    if (strchr(str,':'))
+        return (0);
+
+    if (strlen(str)!=4)
+        return (0);
+
+    if (sscanf(str, "%ld", &year) != 1)
+        return (0);
+
+    if (year < 1900 || year > 3000)
+        return (0);
+
+    tim->tm_year = (int) (year - 1900);
+
+    return (1);
+}
+
+/*
+ * FIXME: this is broken. Consider following entry:
+ * -rwx------   1 root     root            1 Aug 31 10:04 2904 1234
+ * where "2904 1234" is filename. Well, this code decodes it as year :-(.
+ */
+
+static int
+vfs_parse_filetype (char c)
+{
+    switch (c){
+        case 'd': return S_IFDIR; 
+        case 'b': return S_IFBLK;
+        case 'c': return S_IFCHR;
+        case 'l': return S_IFLNK;
+        case 's':
+#ifdef IS_IFSOCK /* And if not, we fall through to IFIFO, which is pretty close */
+                 return S_IFSOCK;
+#endif
+        case 'p': return S_IFIFO;
+        case 'm': case 'n':            /* Don't know what these are :-) */
+        case '-': case '?': return S_IFREG;
+        default: return -1;
+    }
+}
+
+static int vfs_parse_filemode (char *p)
+{      /* converts rw-rw-rw- into 0666 */
+    int res = 0;
+    switch (*(p++)){
+       case 'r': res |= 0400; break;
+       case '-': break;
+       default: return -1;
+    }
+    switch (*(p++)){
+       case 'w': res |= 0200; break;
+       case '-': break;
+       default: return -1;
+    }
+    switch (*(p++)){
+       case 'x': res |= 0100; break;
+       case 's': res |= 0100 | S_ISUID; break;
+       case 'S': res |= S_ISUID; break;
+       case '-': break;
+       default: return -1;
+    }
+    switch (*(p++)){
+       case 'r': res |= 0040; break;
+       case '-': break;
+       default: return -1;
+    }
+    switch (*(p++)){
+       case 'w': res |= 0020; break;
+       case '-': break;
+       default: return -1;
+    }
+    switch (*(p++)){
+       case 'x': res |= 0010; break;
+       case 's': res |= 0010 | S_ISGID; break;
+        case 'l': /* Solaris produces these */
+       case 'S': res |= S_ISGID; break;
+       case '-': break;
+       default: return -1;
+    }
+    switch (*(p++)){
+       case 'r': res |= 0004; break;
+       case '-': break;
+       default: return -1;
+    }
+    switch (*(p++)){
+       case 'w': res |= 0002; break;
+       case '-': break;
+       default: return -1;
+    }
+    switch (*(p++)){
+       case 'x': res |= 0001; break;
+       case 't': res |= 0001 | S_ISVTX; break;
+       case 'T': res |= S_ISVTX; break;
+       case '-': break;
+       default: return -1;
+    }
+    return res;
+}
+
+static int vfs_parse_filedate(int idx, time_t *t)
+{      /* This thing parses from idx in columns[] array */
+
+    char *p;
+    struct tm tim;
+    int d[3];
+    int        got_year = 0;
+
+    /* Let's setup default time values */
+    tim.tm_year = current_year;
+    tim.tm_mon  = current_mon;
+    tim.tm_mday = current_mday;
+    tim.tm_hour = 0;
+    tim.tm_min  = 0;
+    tim.tm_sec  = 0;
+    tim.tm_isdst = -1; /* Let mktime() try to guess correct dst offset */
+    
+    p = columns [idx++];
+    
+    /* We eat weekday name in case of extfs */
+    if(is_week(p, &tim))
+       p = columns [idx++];
+
+    /* Month name */
+    if(is_month(p, &tim)){
+       /* And we expect, it followed by day number */
+       if (is_num (idx))
+           tim.tm_mday = (int)atol (columns [idx++]);
+       else
+           return 0; /* No day */
+
+    } else {
+        /* We usually expect:
+           Mon DD hh:mm
+           Mon DD  YYYY
+          But in case of extfs we allow these date formats:
+           Mon DD YYYY hh:mm
+          Mon DD hh:mm YYYY
+          Wek Mon DD hh:mm:ss YYYY
+           MM-DD-YY hh:mm
+           where Mon is Jan-Dec, DD, MM, YY two digit day, month, year,
+           YYYY four digit year, hh, mm, ss two digit hour, minute or second. */
+
+       /* Here just this special case with MM-DD-YY */
+        if (is_dos_date(p)){
+            p[2] = p[5] = '-';
+           
+           if(sscanf(p, "%2d-%2d-%2d", &d[0], &d[1], &d[2]) == 3){
+           /*  We expect to get:
+               1. MM-DD-YY
+               2. DD-MM-YY
+               3. YY-MM-DD
+               4. YY-DD-MM  */
+               
+               /* Hmm... maybe, next time :)*/
+               
+               /* At last, MM-DD-YY */
+               d[0]--; /* Months are zerobased */
+               /* Y2K madness */
+               if(d[2] < 70)
+                   d[2] += 100;
+
+               tim.tm_mon  = d[0];
+               tim.tm_mday = d[1];
+               tim.tm_year = d[2];
+               got_year = 1;
+           } else
+               return 0; /* sscanf failed */
+        } else
+            return 0; /* unsupported format */
+    }
+
+    /* Here we expect to find time and/or year */
+    
+    if (is_num (idx)) {
+        if(is_time(columns[idx], &tim) || (got_year = is_year(columns[idx], &tim))) {
+       idx++;
+
+       /* This is a special case for ctime() or Mon DD YYYY hh:mm */
+       if(is_num (idx) && 
+           ((got_year = is_year(columns[idx], &tim)) || is_time(columns[idx], &tim)))
+               idx++; /* time & year or reverse */
+       } /* only time or date */
+    }
+    else 
+        return 0; /* Nor time or date */
+
+    /*
+     * If the date is less than 6 months in the past, it is shown without year
+     * other dates in the past or future are shown with year but without time
+     * This does not check for years before 1900 ... I don't know, how
+     * to represent them at all
+     */
+    if (!got_year &&
+       current_mon < 6 && current_mon < tim.tm_mon && 
+       tim.tm_mon - current_mon >= 6)
+
+       tim.tm_year--;
+
+    if ((*t = mktime(&tim)) < 0)
+        *t = 0;
+    return idx;
+}
+
+static int
+vfs_parse_ls_lga (char *p, struct stat *s, char **filename, char **linkname)
+{
+    int idx, idx2, num_cols;
+    int i;
+    char *p_copy;
+    
+    if (strncmp (p, "total", 5) == 0)
+        return 0;
+
+    p_copy = g_strdup(p);
+/* XXX FIXME: parse out inode number from "NLST -lai ." */
+/* XXX FIXME: parse out sizein blocks from "NLST -lais ." */
+
+    if ((i = vfs_parse_filetype(*(p++))) == -1)
+        goto error;
+
+    s->st_mode = i;
+    if (*p == ' ')     /* Notwell 4 */
+        p++;
+    if (*p == '['){
+       if (strlen (p) <= 8 || p [8] != ']')
+           goto error;
+       /* Should parse here the Notwell permissions :) */
+       if (S_ISDIR (s->st_mode))
+           s->st_mode |= (S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR | S_IXUSR | S_IXGRP | S_IXOTH);
+       else
+           s->st_mode |= (S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR);
+       p += 9;
+    } else {
+       if ((i = vfs_parse_filemode(p)) == -1)
+           goto error;
+        s->st_mode |= i;
+       p += 9;
+
+        /* This is for an extra ACL attribute (HP-UX) */
+        if (*p == '+')
+            p++;
+    }
+
+    g_free(p_copy);
+    p_copy = g_strdup(p);
+    num_cols = vfs_split_text (p);
+
+    s->st_nlink = atol (columns [0]);
+    if (s->st_nlink < 0)
+        goto error;
+
+    if (!is_num (1))
+#ifdef HACK
+       s->st_uid = finduid (columns [1]);
+#else
+       unameToUid (columns [1], &s->st_uid);
+#endif
+    else
+        s->st_uid = (uid_t) atol (columns [1]);
+
+    /* Mhm, the ls -lg did not produce a group field */
+    for (idx = 3; idx <= 5; idx++) 
+        if (is_month(columns [idx], NULL) || is_week(columns [idx], NULL) || is_dos_date(columns[idx]))
+            break;
+
+    if (idx == 6 || (idx == 5 && !S_ISCHR (s->st_mode) && !S_ISBLK (s->st_mode)))
+       goto error;
+
+    /* We don't have gid */    
+    if (idx == 3 || (idx == 4 && (S_ISCHR(s->st_mode) || S_ISBLK (s->st_mode))))
+        idx2 = 2;
+    else { 
+       /* We have gid field */
+       if (is_num (2))
+           s->st_gid = (gid_t) atol (columns [2]);
+       else
+#ifdef HACK
+           s->st_gid = findgid (columns [2]);
+#else
+           gnameToGid (columns [1], &s->st_gid);
+#endif
+       idx2 = 3;
+    }
+
+    /* This is device */
+    if (S_ISCHR (s->st_mode) || S_ISBLK (s->st_mode)){
+       int maj, min;
+       
+       if (!is_num (idx2) || sscanf(columns [idx2], " %d,", &maj) != 1)
+           goto error;
+       
+       if (!is_num (++idx2) || sscanf(columns [idx2], " %d", &min) != 1)
+           goto error;
+       
+#ifdef HAVE_ST_RDEV
+       s->st_rdev = ((maj & 0xff) << 8) | (min & 0xffff00ff);
+#endif
+       s->st_size = 0;
+       
+    } else {
+       /* Common file size */
+       if (!is_num (idx2))
+           goto error;
+       
+       s->st_size = (size_t) atol (columns [idx2]);
+#ifdef HAVE_ST_RDEV
+       s->st_rdev = 0;
+#endif
+    }
+
+    idx = vfs_parse_filedate(idx, &s->st_mtime);
+    if (!idx)
+        goto error;
+    /* Use resulting time value */
+    s->st_atime = s->st_ctime = s->st_mtime;
+    s->st_dev = 0;
+    s->st_ino = 0;
+#ifdef HAVE_ST_BLKSIZE
+    s->st_blksize = 512;
+#endif
+#ifdef HAVE_ST_BLOCKS
+    s->st_blocks = (s->st_size + 511) / 512;
+#endif
+
+    for (i = idx + 1, idx2 = 0; i < num_cols; i++ ) 
+       if (strcmp (columns [i], "->") == 0){
+           idx2 = i;
+           break;
+       }
+    
+    if (((S_ISLNK (s->st_mode) || 
+        (num_cols == idx + 3 && s->st_nlink > 1))) /* Maybe a hardlink? (in extfs) */
+        && idx2){
+       int p;
+       char *s;
+           
+       if (filename){
+#ifdef HACK
+           s = g_strndup (p_copy + column_ptr [idx], column_ptr [idx2] - column_ptr [idx] - 1);
+#else
+           int nb = column_ptr [idx2] - column_ptr [idx] - 1;
+           s = xmalloc(nb+1);
+           strncpy(s, p_copy + column_ptr [idx], nb);
+#endif
+           *filename = s;
+       }
+       if (linkname){
+           s = g_strdup (p_copy + column_ptr [idx2+1]);
+           p = strlen (s);
+           if (s [p-1] == '\r' || s [p-1] == '\n')
+               s [p-1] = 0;
+           if (s [p-2] == '\r' || s [p-2] == '\n')
+               s [p-2] = 0;
+               
+           *linkname = s;
+       }
+    } else {
+       /* Extract the filename from the string copy, not from the columns
+        * this way we have a chance of entering hidden directories like ". ."
+        */
+       if (filename){
+           /* 
+           *filename = g_strdup (columns [idx++]);
+           */
+           int p;
+           char *s;
+           
+           s = g_strdup (p_copy + column_ptr [idx++]);
+           p = strlen (s);
+           /* g_strchomp(); */
+           if (s [p-1] == '\r' || s [p-1] == '\n')
+               s [p-1] = 0;
+           if (s [p-2] == '\r' || s [p-2] == '\n')
+               s [p-2] = 0;
+           
+           *filename = s;
+       }
+       if (linkname)
+           *linkname = NULL;
+    }
+    g_free (p_copy);
+    return 1;
+
+error:
+#ifdef HACK
+    {
+      static int errorcount = 0;
+
+      if (++errorcount < 5) {
+       message_1s (1, "Could not parse:", p_copy);
+      } else if (errorcount == 5)
+       message_1s (1, "More parsing errors will be ignored.", "(sorry)" );
+    }
+#endif
+
+    if (p_copy != p)           /* Carefull! */
+       g_free (p_copy);
+    return 0;
+}
+
+typedef enum {
+       DO_FTP_STAT     = 1,
+       DO_FTP_LSTAT    = 2,
+       DO_FTP_READLINK = 3,
+       DO_FTP_ACCESS   = 4,
+       DO_FTP_GLOB     = 5
+} ftpSysCall_t;
+static size_t ftpBufAlloced = 0;
+static char * ftpBuf = NULL;
+       
+#define alloca_strdup(_s)       strcpy(alloca(strlen(_s)+1), (_s))
+
+static int ftpNLST(const char * url, ftpSysCall_t ftpSysCall,
+       struct stat * st, char * rlbuf, size_t rlbufsiz)
+{
+    FD_t fd;
+    const char * path;
+    int bufLength, moretodo;
+    const char *n, *ne, *o, *oe;
+    char * s;
+    char * se;
+    const char * urldn;
+    char * bn = NULL;
+    int nbn = 0;
+    urlinfo u;
+    int rc;
+
+    n = ne = o = oe = NULL;
+    (void) urlPath(url, &path);
+    if (*path == '\0')
+       return -2;
+
+    switch (ftpSysCall) {
+    case DO_FTP_GLOB:
+       fd = ftpOpen(url, 0, 0, &u);
+       if (fd == NULL || u == NULL)
+           return -1;
+
+       u->openError = ftpReq(fd, "NLST", path);
+       break;
+    default:
+       urldn = alloca_strdup(url);
+       if ((bn = strrchr(urldn, '/')) == NULL)
+           return -2;
+       else if (bn == path)
+           bn = ".";
+       else
+           *bn++ = '\0';
+       nbn = strlen(bn);
+
+       rc = ftpChdir(urldn);           /* XXX don't care about CWD */
+       if (rc < 0)
+           return rc;
+
+       fd = ftpOpen(url, 0, 0, &u);
+       if (fd == NULL || u == NULL)
+           return -1;
+
+       /* XXX possibly should do "NLST -lais" to get st_ino/st_blocks also */
+       u->openError = ftpReq(fd, "NLST", "-la");
+       break;
+    }
+
+    if (u->openError < 0) {
+       fd = fdLink(fd, "error data (ftpStat)");
+       rc = -2;
+       goto exit;
+    }
+
+    if (ftpBufAlloced == 0 || ftpBuf == NULL) {
+        ftpBufAlloced = url_iobuf_size;
+        ftpBuf = xcalloc(ftpBufAlloced, sizeof(ftpBuf[0]));
+    }
+    *ftpBuf = '\0';
+
+    bufLength = 0;
+    moretodo = 1;
+
+    do {
+
+       /* XXX FIXME: realloc ftpBuf is < ~128 chars remain */
+       if ((ftpBufAlloced - bufLength) < (1024+80)) {
+           ftpBufAlloced <<= 2;
+           ftpBuf = xrealloc(ftpBuf, ftpBufAlloced);
+       }
+       s = se = ftpBuf + bufLength;
+       *se = '\0';
+
+       rc = fdFgets(fd, se, (ftpBufAlloced - bufLength));
+       if (rc <= 0) {
+           moretodo = 0;
+           break;
+       }
+       if (ftpSysCall == DO_FTP_GLOB) {        /* XXX HACK */
+           bufLength += strlen(se);
+           continue;
+       }
+
+       for (s = se; *s != '\0'; s = se) {
+           int bingo;
+
+           while (*se && *se != '\n') se++;
+           if (se > s && se[-1] == '\r') se[-1] = '\0';
+           if (*se == '\0') break;
+           *se++ = '\0';
+
+           if (!strncmp(s, "total ", sizeof("total ")-1)) continue;
+
+           o = NULL;
+           for (bingo = 0, n = se; n >= s; n--) {
+               switch (*n) {
+               case '\0':
+                   oe = ne = n;
+                   break;
+               case ' ':
+                   if (o || !(n[-3] == ' ' && n[-2] == '-' && n[-1] == '>')) {
+                       while (*(++n) == ' ');
+                       bingo++;
+                       break;
+                   }
+                   for (o = n + 1; *o == ' '; o++);
+                   n -= 3;
+                   ne = n;
+                   break;
+               default:
+                   break;
+               }
+               if (bingo) break;
+           }
+
+           if (nbn != (ne - n))        continue;       /* Same name length? */
+           if (strncmp(n, bn, nbn))    continue;       /* Same name? */
+
+           moretodo = 0;
+           break;
+       }
+
+        if (moretodo && se > s) {
+            bufLength = se - s - 1;
+            if (s != ftpBuf)
+                memmove(ftpBuf, s, bufLength);
+        } else {
+           bufLength = 0;
+       }
+    } while (moretodo);
+
+    switch (ftpSysCall) {
+    case DO_FTP_STAT:
+       if (o && oe) {
+           /* XXX FIXME: symlink, replace urldn/bn from [o,oe) and restart */
+       }
+       /*@fallthrough@*/
+    case DO_FTP_LSTAT:
+       if (st == NULL || !(n && ne)) {
+           rc = -1;
+       } else {
+           rc = ((vfs_parse_ls_lga(s, st, NULL, NULL) > 0) ? 0 : -1);
+       }
+       break;
+    case DO_FTP_READLINK:
+       if (rlbuf == NULL || !(o && oe)) {
+           rc = -1;
+       } else {
+           rc = oe - o;
+           if (rc > rlbufsiz)
+               rc = rlbufsiz;
+           memcpy(rlbuf, o, rc);
+           if (rc < rlbufsiz)
+               rlbuf[rc] = '\0';
+       }
+       break;
+    case DO_FTP_ACCESS:
+       rc = 0;         /* XXX WRONG WRONG WRONG */
+       break;
+    case DO_FTP_GLOB:
+       rc = 0;         /* XXX WRONG WRONG WRONG */
+       break;
+    }
+
+exit:
+    ufdClose(fd);
+    return rc;
+}
+
+static int ftpStat(const char * path, struct stat *st)
+{
+    return ftpNLST(path, DO_FTP_STAT, st, NULL, 0);
+}
+
+static int ftpLstat(const char * path, struct stat *st) {
+    int rc;
+    rc = ftpNLST(path, DO_FTP_LSTAT, st, NULL, 0);
+if (_rpmio_debug)
+fprintf(stderr, "*** ftpLstat(%s) rc %d\n", path, rc);
+    return rc;
+}
+
+static int ftpReadlink(const char * path, char * buf, size_t bufsiz) {
+    return ftpNLST(path, DO_FTP_READLINK, NULL, buf, bufsiz);
+}
+
+static int ftpGlob(const char * path, int flags,
+               int errfunc(const char * epath, int eerno), glob_t * pglob)
+{
+    int rc;
+
+    if (pglob == NULL)
+       return -2;
+    rc = ftpNLST(path, DO_FTP_GLOB, NULL, NULL, 0);
+if (_rpmio_debug)
+fprintf(stderr, "*** ftpGlob(%s,0x%x,%p,%p) ftpNLST rc %d\n", path, flags, errfunc, pglob, rc);
+    if (rc)
+       return rc;
+    rc = poptParseArgvString(ftpBuf, &pglob->gl_pathc, (const char ***)&pglob->gl_pathv);
+    pglob->gl_offs = -1;       /* XXX HACK HACK HACK */
+    return rc;
+}
+
+static void ftpGlobfree(glob_t * pglob) {
+if (_rpmio_debug)
+fprintf(stderr, "*** ftpGlobfree(%p)\n", pglob);
+    if (pglob->gl_offs == -1)  /* XXX HACK HACK HACK */
+       xfree(pglob->gl_pathv);
+}
+
+int Stat(const char * path, struct stat * st) {
+    const char * lpath;
+    int ut = urlPath(path, &lpath);
+
+if (_rpmio_debug)
+fprintf(stderr, "*** Stat(%s,%p)\n", path, st);
+    switch (ut) {
+    case URL_IS_FTP:
+       return ftpStat(path, st);
+       /*@notreached@*/ break;
+    case URL_IS_HTTP:          /* XXX WRONG WRONG WRONG */
+    case URL_IS_PATH:
+       path = lpath;
+       /*@fallthrough@*/
+    case URL_IS_UNKNOWN:
+       break;
+    case URL_IS_DASH:
+    default:
+       return -2;
+       /*@notreached@*/ break;
+    }
+    return stat(path, st);
+}
+
+int Lstat(const char * path, struct stat * st) {
+    const char * lpath;
+    int ut = urlPath(path, &lpath);
+
+if (_rpmio_debug)
+fprintf(stderr, "*** Lstat(%s,%p)\n", path, st);
+    switch (ut) {
+    case URL_IS_FTP:
+       return ftpLstat(path, st);
+       /*@notreached@*/ break;
+    case URL_IS_HTTP:          /* XXX WRONG WRONG WRONG */
+    case URL_IS_PATH:
+       path = lpath;
+       /*@fallthrough@*/
+    case URL_IS_UNKNOWN:
+       break;
+    case URL_IS_DASH:
+    default:
+       return -2;
+       /*@notreached@*/ break;
+    }
+    return lstat(path, st);
+}
+
+int Readlink(const char * path, char * buf, size_t bufsiz) {
+    const char * lpath;
+    int ut = urlPath(path, &lpath);
+
+    switch (ut) {
+    case URL_IS_FTP:
+       return ftpReadlink(path, buf, bufsiz);
+       /*@notreached@*/ break;
+    case URL_IS_HTTP:          /* XXX WRONG WRONG WRONG */
+    case URL_IS_PATH:
+       path = lpath;
+       /*@fallthrough@*/
+    case URL_IS_UNKNOWN:
+       break;
+    case URL_IS_DASH:
+    default:
+       return -2;
+       /*@notreached@*/ break;
+    }
+    return readlink(path, buf, bufsiz);
+}
+
+int Access(const char * path, int amode) {
+    const char * lpath;
+    int ut = urlPath(path, &lpath);
+
+if (_rpmio_debug)
+fprintf(stderr, "*** Access(%s,%d)\n", path, amode);
+    switch (ut) {
+    case URL_IS_FTP:           /* XXX WRONG WRONG WRONG */
+    case URL_IS_HTTP:          /* XXX WRONG WRONG WRONG */
+    case URL_IS_PATH:
+       path = lpath;
+       /*@fallthrough@*/
+    case URL_IS_UNKNOWN:
+       break;
+    case URL_IS_DASH:
+    default:
+       return -2;
+       /*@notreached@*/ break;
+    }
+    return access(path, amode);
+}
+
+int Glob(const char *path, int flags,
+       int errfunc(const char * epath, int eerrno), glob_t *pglob)
+{
+    const char * lpath;
+    int ut = urlPath(path, &lpath);
+
+if (_rpmio_debug)
+fprintf(stderr, "*** Glob(%s,0x%x,%p,%p)\n", path, flags, errfunc, pglob);
+    switch (ut) {
+    case URL_IS_FTP:           /* XXX WRONG WRONG WRONG */
+       return ftpGlob(path, flags, errfunc, pglob);
+       /*@notreached@*/ break;
+    case URL_IS_HTTP:          /* XXX WRONG WRONG WRONG */
+    case URL_IS_PATH:
+       path = lpath;
+       /*@fallthrough@*/
+    case URL_IS_UNKNOWN:
+       break;
+    case URL_IS_DASH:
+    default:
+       return -2;
+       /*@notreached@*/ break;
+    }
+    return glob(path, flags, errfunc, pglob);
+}
+
+void Globfree(glob_t *pglob)
+{
+if (_rpmio_debug)
+fprintf(stderr, "*** Globfree(%p)\n", pglob);
+    if (pglob->gl_offs == -1) /* XXX HACK HACK HACK */
+       ftpGlobfree(pglob);
+    else
+       globfree(pglob);
+}
+
+DIR * Opendir(const char * path)
+{
+    const char * lpath;
+    int ut = urlPath(path, &lpath);
+
+if (_rpmio_debug)
+fprintf(stderr, "*** Opendir(%s)\n", path);
+    switch (ut) {
+    case URL_IS_FTP:           /* XXX WRONG WRONG WRONG */
+    case URL_IS_HTTP:          /* XXX WRONG WRONG WRONG */
+    case URL_IS_PATH:
+       path = lpath;
+       /*@fallthrough@*/
+    case URL_IS_UNKNOWN:
+       break;
+    case URL_IS_DASH:
+    default:
+       return NULL;
+       /*@notreached@*/ break;
+    }
+    return opendir(path);
+}
+
+struct dirent * Readdir(DIR * dir)
+{
+if (_rpmio_debug)
+fprintf(stderr, "*** Readdir(%p)\n", dir);
+    return readdir(dir);
+}
+
+int Closedir(DIR * dir)
+{
+if (_rpmio_debug)
+fprintf(stderr, "*** Closedir(%p)\n", dir);
+    return closedir(dir);
+}
+
+static struct FDIO_s fpio_s = {
+  ufdRead, ufdWrite, fdSeek, ufdClose, XfdLink, XfdFree, XfdNew, fdFileno,
+  ufdOpen, NULL, fdGetFp, NULL,        Mkdir, Chdir, Rmdir, Rename, Unlink
+};
+FDIO_t fpio = /*@-compmempass@*/ &fpio_s /*@=compmempass@*/ ;
similarity index 100%
rename from lib/rpmio.h
rename to rpmio/rpmio.h
similarity index 100%
rename from lib/rpmurl.h
rename to rpmio/rpmurl.h
similarity index 100%
rename from lib/url.c
rename to rpmio/url.c
index 6fd2218..5ee4004 100644 (file)
@@ -2,23 +2,24 @@
 
 AUTOMAKE_OPTIONS = 1.4 foreign
 
-INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/build \
-       -I$(top_srcdir)/lib -I$(top_srcdir)/popt \
+INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/build -I$(top_srcdir)/lib \
+       -I$(top_srcdir)/rpmio -I$(top_srcdir)/popt \
        @INCPATH@ -I$(top_srcdir)/misc
 
 EXTRA_DIST =   fstrcmp.c message.c str-list.c rpmchecksig.c
 
 EXTRA_PROGRAMS = rpmgettext rpmputtext rpminject
 
-myLDFLAGS= -L$(top_builddir)/build -L$(top_builddir)/lib -L$(top_builddir)/popt
-# XXX should libtool generate dependent libs?
-myLDADD = \
-       $(top_builddir)/popt/libpopt.la \
+#myLDFLAGS= -L$(top_builddir)/build -L$(top_builddir)/lib \
+#      -L$(top_builddir)/rpmio -L$(top_builddir)/popt
+
+myLDADD = $(top_builddir)/build/librpmbuild.la \
        $(top_builddir)/lib/librpm.la \
-       $(top_builddir)/build/librpmbuild.la \
-       @INTLLIBS@ @LIBMISC@
+       $(top_builddir)/rpmio/librpmio.la \
+       $(top_builddir)/popt/libpopt.la \
+       @INTLLIBS@
 
-LDFLAGS = $(myLDFLAGS)
+#LDFLAGS = $(myLDFLAGS)
 LDADD = $(myLDADD)
 
 noinst_PROGRAMS = \