- make librpmio standalone.
authorjbj <devnull@localhost>
Fri, 9 Jun 2000 21:24:37 +0000 (21:24 +0000)
committerjbj <devnull@localhost>
Fri, 9 Jun 2000 21:24:37 +0000 (21:24 +0000)
CVS patchset: 3824
CVS date: 2000/06/09 21:24:37

15 files changed:
CHANGES
lib/Makefile.am
lib/rpmlib.h
po/rpm.pot
rpm.spec
rpmio/Makefile.am
rpmio/macro.c
rpmio/messages.c
rpmio/rpmerr.c
rpmio/rpmerr.h [new file with mode: 0644]
rpmio/rpmio.c
rpmio/rpmio_internal.h
rpmio/rpmmessages.h [new file with mode: 0644]
rpmio/rpmrpc.c [new file with mode: 0644]
rpmio/url.c

diff --git a/CHANGES b/CHANGES
index 1ecfcfe..99858f3 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -55,6 +55,7 @@
        - fix: segfault with legacy packages missing RPMTAG_FILEINODES.
        - require db3 in default configuration.
        - create rpmio directory for librpmio.
+       - make librpmio standalone.
        
 3.0.3 -> 3.0.4
        - use compressed filenames on install side.
index efc3ca3..cd90323 100644 (file)
@@ -27,7 +27,6 @@ librpm_la_SOURCES = \
        rpmlead.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
index 625ab3f..a39cbd7 100644 (file)
@@ -6,6 +6,8 @@
 /* and it shouldn't need these :-( */
 
 #include "rpmio.h"
+#include "rpmmessages.h"
+#include "rpmerr.h"
 #include "header.h"
 #include "popt.h"
 
@@ -320,26 +322,10 @@ void rpmSetMachine(const char * arch, const char * os);
 void rpmGetMachine( /*@out@*/ const char **arch, /*@out@*/ const char **os);
 void rpmFreeRpmrc(void);
 
+/* ==================================================================== */
 /** **/
-
 typedef /*@abstract@*/ struct rpmdb_s * rpmdb;
 
-typedef enum rpmCallbackType_e {
-    RPMCALLBACK_INST_PROGRESS, RPMCALLBACK_INST_START,
-    RPMCALLBACK_INST_OPEN_FILE, RPMCALLBACK_INST_CLOSE_FILE,
-    RPMCALLBACK_TRANS_PROGRESS, RPMCALLBACK_TRANS_START, RPMCALLBACK_TRANS_STOP,
-    RPMCALLBACK_UNINST_PROGRESS, RPMCALLBACK_UNINST_START, RPMCALLBACK_UNINST_STOP
-} rpmCallbackType;
-
-typedef void * (*rpmCallbackFunction)(const Header h, 
-                                     const rpmCallbackType what, 
-                                     const unsigned long amount, 
-                                     const unsigned long total,
-                                     const void * pkgKey, void * data);
-
-void   urlSetCallback(rpmCallbackFunction notify, void *notifyData, int notifyCount);
-
-/* ==================================================================== */
 /**
  * @param dbp  address of rpm database
  */
@@ -654,24 +640,6 @@ int rpmRunTransactions(rpmTransactionSet ts, rpmCallbackFunction notify,
 #define RPMPROB_FILTER_OLDPACKAGE      (1 << 6)
 #define RPMPROB_FILTER_DISKSPACE       (1 << 7)
 
-/** messages.c **/
-
-#define        RPMMESS_DEBUG      1
-#define        RPMMESS_VERBOSE    2
-#define        RPMMESS_NORMAL     3
-#define        RPMMESS_WARNING    4
-#define        RPMMESS_ERROR      5
-#define        RPMMESS_FATALERROR 6
-
-#define        RPMMESS_QUIET (RPMMESS_NORMAL + 1)
-
-void rpmIncreaseVerbosity(void);
-void rpmSetVerbosity(int level);
-int rpmGetVerbosity(void);
-int rpmIsVerbose(void);
-int rpmIsDebug(void);
-void rpmMessage(int level, const char * format, ...);
-
 /** rpmlead.c **/
 
 #define        RPMLEAD_BINARY 0
@@ -708,80 +676,6 @@ struct oldrpmlead {                /* for version 1 packages */
     unsigned int archiveOffset;
 } ;
 
-/** rpmerr.c **/
-
-typedef void (*rpmErrorCallBackType)(void);
-
-#if defined(__GNUC__)
-void rpmError(int code, char * format, ...) __attribute__ ((__format__ (__printf__, 2, 3)));
-#else
-void rpmError(int code, char * format, ...);
-#endif
-
-int rpmErrorCode(void);
-char *rpmErrorCodeString(void);
-char *rpmErrorString(void);
-rpmErrorCallBackType rpmErrorSetCallback(rpmErrorCallBackType);
-
-#define        RPMERR_GDBMOPEN         -2      /* gdbm open failed */
-#define        RPMERR_GDBMREAD         -3      /* gdbm read failed */
-#define        RPMERR_GDBMWRITE        -4      /* gdbm write failed */
-#define        RPMERR_INTERNAL         -5      /* internal RPM error */
-#define        RPMERR_DBCORRUPT        -6      /* rpm database is corrupt */
-#define        RPMERR_OLDDBCORRUPT     -7      /* old style rpm database is corrupt */
-#define        RPMERR_OLDDBMISSING     -8      /* old style rpm database is missing */
-#define        RPMERR_NOCREATEDB       -9      /* cannot create new database */
-#define        RPMERR_DBOPEN           -10     /* database open failed */
-#define        RPMERR_DBGETINDEX       -11     /* database get from index failed */
-#define        RPMERR_DBPUTINDEX       -12     /* database get from index failed */
-#define        RPMERR_NEWPACKAGE       -13     /* package is too new to handle */
-#define        RPMERR_BADMAGIC         -14     /* bad magic for an RPM */
-#define        RPMERR_RENAME           -15     /* rename(2) failed */
-#define        RPMERR_UNLINK           -16     /* unlink(2) failed */
-#define        RPMERR_RMDIR            -17     /* rmdir(2) failed */
-#define        RPMERR_PKGINSTALLED     -18     /* package already installed */
-#define        RPMERR_CHOWN            -19     /* chown() call failed */
-#define        RPMERR_NOUSER           -20     /* user does not exist */
-#define        RPMERR_NOGROUP          -21     /* group does not exist */
-#define        RPMERR_MKDIR            -22     /* mkdir() call failed */
-#define        RPMERR_FILECONFLICT     -23     /* file being installed exists */
-#define        RPMERR_RPMRC            -24     /* bad line in rpmrc */
-#define        RPMERR_NOSPEC           -25     /* .spec file is missing */
-#define        RPMERR_NOTSRPM          -26     /* a source rpm was expected */
-#define        RPMERR_FLOCK            -27     /* locking the database failed */
-#define        RPMERR_OLDPACKAGE       -28     /* trying upgrading to old version */
-/*#define      RPMERR_BADARCH  -29        bad architecture or arch mismatch */
-#define        RPMERR_CREATE           -30     /* failed to create a file */
-#define        RPMERR_NOSPACE          -31     /* out of disk space */
-#define        RPMERR_NORELOCATE       -32     /* tried to do improper relocatation */
-/*#define      RPMERR_BADOS    -33        bad architecture or arch mismatch */
-#define        RPMMESS_BACKUP          -34     /* backup made during [un]install */
-#define        RPMERR_MTAB             -35     /* failed to read mount table */
-#define        RPMERR_STAT             -36     /* failed to stat something */
-#define        RPMERR_BADDEV           -37     /* file on device not listed in mtab */
-#define        RPMMESS_ALTNAME         -38     /* file written as .rpmnew */
-#define        RPMMESS_PREREQLOOP      -39     /* loop in prerequisites */
-#define        RPMERR_BADRELOCATE      -40     /* bad relocation was specified */
-#define        RPMERR_OLDDB            -41     /* old format database */
-
-/* spec.c build.c pack.c */
-#define        RPMERR_UNMATCHEDIF      -107    /* unclosed %ifarch or %ifos */
-#define        RPMERR_BADARG           -109
-#define        RPMERR_SCRIPT           -110    /* errors related to script exec */
-#define        RPMERR_READERROR        -111
-#define        RPMERR_UNKNOWNOS        -112
-#define        RPMERR_UNKNOWNARCH      -113
-#define        RPMERR_EXEC             -114
-#define        RPMERR_FORK             -115
-#define        RPMERR_CPIO             -116
-#define        RPMERR_GZIP             -117
-#define        RPMERR_BADSPEC          -118
-#define        RPMERR_LDD              -119    /* couldn't understand ldd output */
-#define        RPMERR_BADFILENAME      -120
-
-#define        RPMERR_BADSIGTYPE       -200    /* Unknown signature type */
-#define        RPMERR_SIGGEN           -201    /* Error generating signature */
-
 /** signature.c **/
 
 /**************************************************/
index 87ae7f3..092b03c 100644 (file)
@@ -6,7 +6,7 @@
 msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
-"POT-Creation-Date: 2000-06-09 15:18-0400\n"
+"POT-Creation-Date: 2000-06-09 17:03-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 rpmio/url.c:444
+#: lib/db1.c:430 rpmio/url.c:445
 #, c-format
 msgid "failed to open %s: %s\n"
 msgstr ""
@@ -3749,141 +3749,141 @@ msgstr ""
 msgid "Unsatisfied dependencies for %s-%s-%s: "
 msgstr ""
 
-#: rpmio/rpmio.c:537
+#: rpmio/rpmio.c:532
 msgid "Success"
 msgstr ""
 
-#: rpmio/rpmio.c:540
+#: rpmio/rpmio.c:535
 msgid "Bad server response"
 msgstr ""
 
-#: rpmio/rpmio.c:543
+#: rpmio/rpmio.c:538
 msgid "Server IO error"
 msgstr ""
 
-#: rpmio/rpmio.c:546
+#: rpmio/rpmio.c:541
 msgid "Server timeout"
 msgstr ""
 
-#: rpmio/rpmio.c:549
+#: rpmio/rpmio.c:544
 msgid "Unable to lookup server host address"
 msgstr ""
 
-#: rpmio/rpmio.c:552
+#: rpmio/rpmio.c:547
 msgid "Unable to lookup server host name"
 msgstr ""
 
-#: rpmio/rpmio.c:555
+#: rpmio/rpmio.c:550
 msgid "Failed to connect to server"
 msgstr ""
 
-#: rpmio/rpmio.c:558
+#: rpmio/rpmio.c:553
 msgid "Failed to establish data connection to server"
 msgstr ""
 
-#: rpmio/rpmio.c:561
+#: rpmio/rpmio.c:556
 msgid "IO error to local file"
 msgstr ""
 
-#: rpmio/rpmio.c:564
+#: rpmio/rpmio.c:559
 msgid "Error setting remote server to passive mode"
 msgstr ""
 
-#: rpmio/rpmio.c:567
+#: rpmio/rpmio.c:562
 msgid "File not found on server"
 msgstr ""
 
-#: rpmio/rpmio.c:570
+#: rpmio/rpmio.c:565
 msgid "Abort in progress"
 msgstr ""
 
-#: rpmio/rpmio.c:574
+#: rpmio/rpmio.c:569
 msgid "Unknown or unexpected error"
 msgstr ""
 
-#: rpmio/rpmio.c:1107
+#: rpmio/rpmio.c:1164
 #, c-format
 msgid "logging into %s as %s, pw %s\n"
 msgstr ""
 
-#: rpmio/macro.c:160
+#: rpmio/macro.c:161
 #, c-format
 msgid "======================== active %d empty %d\n"
 msgstr ""
 
 #. XXX just in case
-#: rpmio/macro.c:255
+#: rpmio/macro.c:256
 #, c-format
 msgid "%3d>%*s(empty)"
 msgstr ""
 
-#: rpmio/macro.c:290
+#: rpmio/macro.c:291
 #, c-format
 msgid "%3d<%*s(empty)\n"
 msgstr ""
 
-#: rpmio/macro.c:469
+#: rpmio/macro.c:470
 msgid "Macro %%%s has unterminated body"
 msgstr ""
 
-#: rpmio/macro.c:495
+#: rpmio/macro.c:496
 msgid "Macro %%%s has illegal name (%%define)"
 msgstr ""
 
-#: rpmio/macro.c:501
+#: rpmio/macro.c:502
 msgid "Macro %%%s has unterminated opts"
 msgstr ""
 
-#: rpmio/macro.c:506
+#: rpmio/macro.c:507
 msgid "Macro %%%s has empty body"
 msgstr ""
 
-#: rpmio/macro.c:511
+#: rpmio/macro.c:512
 msgid "Macro %%%s failed to expand"
 msgstr ""
 
-#: rpmio/macro.c:536
+#: rpmio/macro.c:537
 msgid "Macro %%%s has illegal name (%%undefine)"
 msgstr ""
 
-#: rpmio/macro.c:613
+#: rpmio/macro.c:614
 msgid "Macro %%%s (%s) was not used below level %d"
 msgstr ""
 
-#: rpmio/macro.c:710
+#: rpmio/macro.c:711
 #, c-format
 msgid "Unknown option %c in %s(%s)"
 msgstr ""
 
-#: rpmio/macro.c:890
+#: rpmio/macro.c:891
 #, c-format
 msgid "Recursion depth(%d) greater than max(%d)"
 msgstr ""
 
-#: rpmio/macro.c:956 rpmio/macro.c:972
+#: rpmio/macro.c:957 rpmio/macro.c:973
 #, c-format
 msgid "Unterminated %c: %s"
 msgstr ""
 
-#: rpmio/macro.c:1012
+#: rpmio/macro.c:1013
 msgid "A %% is followed by an unparseable macro"
 msgstr ""
 
-#: rpmio/macro.c:1138
+#: rpmio/macro.c:1139
 msgid "Macro %%%.*s not found, skipping"
 msgstr ""
 
-#: rpmio/macro.c:1219
+#: rpmio/macro.c:1220
 msgid "Target buffer overflow"
 msgstr ""
 
 #. XXX Fstrerror
-#: rpmio/macro.c:1399 rpmio/macro.c:1405
+#: rpmio/macro.c:1400 rpmio/macro.c:1406
 #, c-format
 msgid "File %s: %s"
 msgstr ""
 
-#: rpmio/macro.c:1408
+#: rpmio/macro.c:1409
 #, c-format
 msgid "File %s is smaller than %d bytes"
 msgstr ""
@@ -3909,37 +3909,37 @@ msgstr ""
 msgid "memory alloc (%u bytes) returned NULL.\n"
 msgstr ""
 
-#: rpmio/url.c:87
+#: rpmio/url.c:88
 #, c-format
 msgid "warning: u %p ctrl %p nrefs != 0 (%s %s)\n"
 msgstr ""
 
-#: rpmio/url.c:104
+#: rpmio/url.c:105
 #, c-format
 msgid "warning: u %p data %p nrefs != 0 (%s %s)\n"
 msgstr ""
 
-#: rpmio/url.c:131
+#: rpmio/url.c:132
 #, c-format
 msgid "warning: uCache[%d] %p nrefs(%d) != 1 (%s %s)\n"
 msgstr ""
 
-#: rpmio/url.c:217
+#: rpmio/url.c:218
 #, c-format
 msgid "Password for %s@%s: "
 msgstr ""
 
-#: rpmio/url.c:242 rpmio/url.c:268
+#: rpmio/url.c:243 rpmio/url.c:269
 #, c-format
 msgid "error: %sport must be a number\n"
 msgstr ""
 
-#: rpmio/url.c:404
+#: rpmio/url.c:405
 msgid "url port must be a number\n"
 msgstr ""
 
 #. XXX Fstrerror
-#: rpmio/url.c:461
+#: rpmio/url.c:462
 #, c-format
 msgid "failed to create %s: %s\n"
 msgstr ""
index 78d262a..3a326ea 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.34
+Release: 0.35
 Group: System Environment/Base
 Source: ftp://ftp.rpm.org/pub/rpm/dist/rpm-3.0.x/rpm-%{version}.tar.gz
 Copyright: GPL
index 6c0d73e..4146796 100644 (file)
@@ -6,11 +6,12 @@ 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 rpmmacro.h
+pkginc_HEADERS = rpmio.h rpmurl.h rpmmacro.h rpmmessages.h rpmerr.h
 noinst_HEADERS = rpmio_internal.h ugid.h
 
 lib_LTLIBRARIES = librpmio.la
-librpmio_la_SOURCES = rpmio.c url.c macro.c ugid.c rpmmalloc.c rpmerr.c messages.c
+librpmio_la_SOURCES = rpmrpc.c rpmio.c url.c macro.c \
+       ugid.c rpmmalloc.c rpmerr.c messages.c
 librpmio_la_LDFLAGS = -L$(top_builddir)/popt/.libs -lpopt
 librpmio_la_LIBADD = @LIBMISC@
 
index 846e992..b9f5809 100644 (file)
@@ -39,8 +39,9 @@ typedef       FILE * FD_t;
 
 #else
 
-#include <rpmlib.h>
 #include <rpmio_internal.h>
+#include <rpmmessages.h>
+#include <rpmerr.h>
 
 #endif
 
index 72595b2..5853758 100644 (file)
@@ -2,7 +2,7 @@
 
 #include <stdarg.h>
 
-#include <rpmlib.h>
+#include <rpmmessages.h>
 
 static int minLevel = RPMMESS_NORMAL;
 
index fc05e7e..a15a26c 100644 (file)
@@ -2,7 +2,7 @@
 
 #include <stdarg.h>
 
-#include <rpmlib.h>
+#include <rpmerr.h>
 
 static struct err {
     int code;
diff --git a/rpmio/rpmerr.h b/rpmio/rpmerr.h
new file mode 100644 (file)
index 0000000..e80bbcf
--- /dev/null
@@ -0,0 +1,84 @@
+#ifndef H_RPMERR
+#define H_RPMERR
+
+#define        RPMERR_GDBMOPEN         -2      /* gdbm open failed */
+#define        RPMERR_GDBMREAD         -3      /* gdbm read failed */
+#define        RPMERR_GDBMWRITE        -4      /* gdbm write failed */
+#define        RPMERR_INTERNAL         -5      /* internal RPM error */
+#define        RPMERR_DBCORRUPT        -6      /* rpm database is corrupt */
+#define        RPMERR_OLDDBCORRUPT     -7      /* old style rpm database is corrupt */
+#define        RPMERR_OLDDBMISSING     -8      /* old style rpm database is missing */
+#define        RPMERR_NOCREATEDB       -9      /* cannot create new database */
+#define        RPMERR_DBOPEN           -10     /* database open failed */
+#define        RPMERR_DBGETINDEX       -11     /* database get from index failed */
+#define        RPMERR_DBPUTINDEX       -12     /* database get from index failed */
+#define        RPMERR_NEWPACKAGE       -13     /* package is too new to handle */
+#define        RPMERR_BADMAGIC         -14     /* bad magic for an RPM */
+#define        RPMERR_RENAME           -15     /* rename(2) failed */
+#define        RPMERR_UNLINK           -16     /* unlink(2) failed */
+#define        RPMERR_RMDIR            -17     /* rmdir(2) failed */
+#define        RPMERR_PKGINSTALLED     -18     /* package already installed */
+#define        RPMERR_CHOWN            -19     /* chown() call failed */
+#define        RPMERR_NOUSER           -20     /* user does not exist */
+#define        RPMERR_NOGROUP          -21     /* group does not exist */
+#define        RPMERR_MKDIR            -22     /* mkdir() call failed */
+#define        RPMERR_FILECONFLICT     -23     /* file being installed exists */
+#define        RPMERR_RPMRC            -24     /* bad line in rpmrc */
+#define        RPMERR_NOSPEC           -25     /* .spec file is missing */
+#define        RPMERR_NOTSRPM          -26     /* a source rpm was expected */
+#define        RPMERR_FLOCK            -27     /* locking the database failed */
+#define        RPMERR_OLDPACKAGE       -28     /* trying upgrading to old version */
+/*#define      RPMERR_BADARCH  -29        bad architecture or arch mismatch */
+#define        RPMERR_CREATE           -30     /* failed to create a file */
+#define        RPMERR_NOSPACE          -31     /* out of disk space */
+#define        RPMERR_NORELOCATE       -32     /* tried to do improper relocatation */
+/*#define      RPMERR_BADOS    -33        bad architecture or arch mismatch */
+#define        RPMMESS_BACKUP          -34     /* backup made during [un]install */
+#define        RPMERR_MTAB             -35     /* failed to read mount table */
+#define        RPMERR_STAT             -36     /* failed to stat something */
+#define        RPMERR_BADDEV           -37     /* file on device not listed in mtab */
+#define        RPMMESS_ALTNAME         -38     /* file written as .rpmnew */
+#define        RPMMESS_PREREQLOOP      -39     /* loop in prerequisites */
+#define        RPMERR_BADRELOCATE      -40     /* bad relocation was specified */
+#define        RPMERR_OLDDB            -41     /* old format database */
+
+/* spec.c build.c pack.c */
+#define        RPMERR_UNMATCHEDIF      -107    /* unclosed %ifarch or %ifos */
+#define        RPMERR_BADARG           -109
+#define        RPMERR_SCRIPT           -110    /* errors related to script exec */
+#define        RPMERR_READERROR        -111
+#define        RPMERR_UNKNOWNOS        -112
+#define        RPMERR_UNKNOWNARCH      -113
+#define        RPMERR_EXEC             -114
+#define        RPMERR_FORK             -115
+#define        RPMERR_CPIO             -116
+#define        RPMERR_GZIP             -117
+#define        RPMERR_BADSPEC          -118
+#define        RPMERR_LDD              -119    /* couldn't understand ldd output */
+#define        RPMERR_BADFILENAME      -120
+
+#define        RPMERR_BADSIGTYPE       -200    /* Unknown signature type */
+#define        RPMERR_SIGGEN           -201    /* Error generating signature */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void (*rpmErrorCallBackType)(void);
+
+#if defined(__GNUC__)
+void rpmError(int code, char * format, ...) __attribute__ ((__format__ (__printf__, 2, 3)));
+#else
+void rpmError(int code, char * format, ...);
+#endif
+
+int rpmErrorCode(void);
+char *rpmErrorCodeString(void);
+char *rpmErrorString(void);
+rpmErrorCallBackType rpmErrorSetCallback(rpmErrorCallBackType);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* H_RPMERR */
index 07017c2..f1e9ed5 100644 (file)
@@ -60,9 +60,9 @@ static int inet_aton(const char *cp, struct in_addr *inp)
 #include "dns.h"
 #endif
 
-#include <rpmlib.h>
 #include <rpmio_internal.h>
-#include "misc.h"
+#include "ugid.h"
+#include "rpmmessages.h"
 
 #define FDNREFS(fd)    (fd ? ((FD_t)fd)->nrefs : -9)
 #define FDTO(fd)       (fd ? ((FD_t)fd)->rd_timeoutsecs : -99)
@@ -90,11 +90,6 @@ 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)
 
 /* =============================================================== */
 
@@ -465,7 +460,7 @@ int fdReadable(FD_t fd, int secs)
     /*@notreached@*/
 }
 
-static int fdFgets(FD_t fd, char * buf, size_t len)
+int fdFgets(FD_t fd, char * buf, size_t len)
 {
     int fdno;
     int secs = fd->rd_timeoutsecs;
@@ -951,7 +946,7 @@ errxit2:
     return rc;
 }
 
-static int ftpReq(FD_t data, const char * ftpCmd, const char * ftpArg)
+int ftpReq(FD_t data, const char * ftpCmd, const char * ftpArg)
 {
     urlinfo u = data->url;
     struct sockaddr_in dataAddress;
@@ -1081,48 +1076,6 @@ errxit:
     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;
@@ -1185,6 +1138,48 @@ int ufdCopy(FD_t sfd, FD_t tfd)
     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;
+}
+
 int ufdGetFile(FD_t sfd, FD_t tfd)
 {
     int rc;
@@ -1198,7 +1193,7 @@ int ufdGetFile(FD_t sfd, FD_t tfd)
     return rc;
 }
 
-static int ftpCmd(const char * cmd, const char * url, const char * arg2) {
+int ftpCmd(const char * cmd, const char * url, const char * arg2) {
     urlinfo u;
     int rc;
     const char * path;
@@ -1213,38 +1208,6 @@ static int ftpCmd(const char * cmd, const char * url, const char * arg2) {
     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: */
@@ -1605,7 +1568,7 @@ static inline int ufdSeek(void * cookie, off_t pos, int whence) {
     return fdSeek(cookie, pos, whence);
 }
 
-static int ufdClose( /*@only@*/ void * cookie)
+int ufdClose( /*@only@*/ void * cookie)
 {
     FD_t fd = c2f(cookie);
 
@@ -1713,7 +1676,7 @@ fprintf(stderr, "-> \r\n");
     return fdClose(fd);
 }
 
-static /*@null@*/ FD_t ftpOpen(const char *url, /*@unused@*/ int flags,
+/*@null@*/ FD_t ftpOpen(const char *url, /*@unused@*/ int flags,
                /*@unused@*/ mode_t mode, /*@out@*/ urlinfo *uret)
 {
     urlinfo u = NULL;
@@ -2682,1085 +2645,6 @@ ssize_t Pwrite(FD_t fd, const void * buf, size_t count, off_t offset) {
     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
index 6a61f62..2146dd8 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <rpmio.h>
 #include <rpmurl.h>
+#include <assert.h>
 
 typedef struct _FDSTACK_s {
        FDIO_t          io;
@@ -56,9 +57,31 @@ struct _FD_s {
 };
 /*@access FD_t */
 
-#include <assert.h>
 #define        FDSANE(fd)      assert(fd && fd->magic == FDMAGIC)
 
+extern int _rpmio_debug;
+
+#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)
+
+#define xfree(_p)       free((void *)_p)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int fdFgets(FD_t fd, char * buf, size_t len);
+
+/*@null@*/ FD_t ftpOpen(const char *url, /*@unused@*/ int flags,
+                /*@unused@*/ mode_t mode, /*@out@*/ urlinfo *uret);
+int ftpReq(FD_t data, const char * ftpCmd, const char * ftpArg);
+int ftpCmd(const char * cmd, const char * url, const char * arg2);
+
+int ufdClose( /*@only@*/ void * cookie);
+
 static inline /*@null@*/ const FDIO_t fdGetIo(FD_t fd) {
     FDSANE(fd);
     return fd->fps[fd->nfps].io;
@@ -241,4 +264,8 @@ static inline void fadSetFirstFree(FD_t fd, unsigned int firstFree) {
     fd->firstFree = firstFree;
 }
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* H_RPMIO_INTERNAL */
diff --git a/rpmio/rpmmessages.h b/rpmio/rpmmessages.h
new file mode 100644 (file)
index 0000000..67f2d1c
--- /dev/null
@@ -0,0 +1,43 @@
+#ifndef H_RPMMESSAGES
+#define H_RPMMESSAGES
+
+#define        RPMMESS_DEBUG      1
+#define        RPMMESS_VERBOSE    2
+#define        RPMMESS_NORMAL     3
+#define        RPMMESS_WARNING    4
+#define        RPMMESS_ERROR      5
+#define        RPMMESS_FATALERROR 6
+
+#define        RPMMESS_QUIET (RPMMESS_NORMAL + 1)
+
+typedef enum rpmCallbackType_e {
+    RPMCALLBACK_INST_PROGRESS, RPMCALLBACK_INST_START,
+    RPMCALLBACK_INST_OPEN_FILE, RPMCALLBACK_INST_CLOSE_FILE,
+    RPMCALLBACK_TRANS_PROGRESS, RPMCALLBACK_TRANS_START, RPMCALLBACK_TRANS_STOP,
+    RPMCALLBACK_UNINST_PROGRESS, RPMCALLBACK_UNINST_START, RPMCALLBACK_UNINST_STOP
+} rpmCallbackType;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void * (*rpmCallbackFunction)(const void * h, 
+                                     const rpmCallbackType what, 
+                                     const unsigned long amount, 
+                                     const unsigned long total,
+                                     const void * pkgKey, void * data);
+
+void   urlSetCallback(rpmCallbackFunction notify, void *notifyData, int notifyCount);
+
+void rpmIncreaseVerbosity(void);
+void rpmSetVerbosity(int level);
+int rpmGetVerbosity(void);
+int rpmIsVerbose(void);
+int rpmIsDebug(void);
+void rpmMessage(int level, const char * format, ...);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* H_RPMMESSAGES */
diff --git a/rpmio/rpmrpc.c b/rpmio/rpmrpc.c
new file mode 100644 (file)
index 0000000..bf69c15
--- /dev/null
@@ -0,0 +1,1120 @@
+#include "system.h"
+
+#include <rpmio_internal.h>
+#include <popt.h>
+#include "ugid.h"
+
+extern int _rpmio_debug;
+
+/* =============================================================== */
+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 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);
+}
index a49877e..6374757 100644 (file)
@@ -9,7 +9,8 @@
 #include <netinet/in.h>
 #endif /* __LCLINT__ */
 
-#include <rpmbuild.h>
+#include <rpmmacro.h>
+#include <rpmmessages.h>
 #include <rpmio_internal.h>
 
 #ifndef        IPPORT_FTP
@@ -28,10 +29,10 @@ int url_iobuf_size = URL_IOBUF_SIZE;
 #define        RPMURL_DEBUG_REFS       0x20000000
 
 int _url_debug = 0;
-#define        DBG(_f, _m, _x) if ((_url_debug | (_f)) & (_m)) fprintf _x
+#define        URLDBG(_f, _m, _x)      if ((_url_debug | (_f)) & (_m)) fprintf _x
 
-#define DBGIO(_f, _x)  DBG((_f), RPMURL_DEBUG_IO, _x)
-#define DBGREFS(_f, _x)        DBG((_f), RPMURL_DEBUG_REFS, _x)
+#define URLDBGIO(_f, _x)       URLDBG((_f), RPMURL_DEBUG_IO, _x)
+#define URLDBGREFS(_f, _x)     URLDBG((_f), RPMURL_DEBUG_REFS, _x)
 
 /*@only@*/ /*@null@*/ static urlinfo *uCache = NULL;
 static int uCount = 0;
@@ -40,7 +41,7 @@ urlinfo XurlLink(urlinfo u, const char *msg, const char *file, unsigned line)
 {
     URLSANE(u);
     u->nrefs++;
-DBGREFS(0, (stderr, "--> url %p ++ %d %s at %s:%u\n", u, u->nrefs, msg, file, line));
+URLDBGREFS(0, (stderr, "--> url %p ++ %d %s at %s:%u\n", u, u->nrefs, msg, file, line));
     return u;
 }
 
@@ -67,7 +68,7 @@ urlinfo XurlNew(const char *msg, const char *file, unsigned line)
 urlinfo XurlFree(urlinfo u, const char *msg, const char *file, unsigned line)
 {
     URLSANE(u);
-DBGREFS(0, (stderr, "--> url %p -- %d %s at %s:%u\n", u, u->nrefs, msg, file, line));
+URLDBGREFS(0, (stderr, "--> url %p -- %d %s at %s:%u\n", u, u->nrefs, msg, file, line));
     if (--u->nrefs > 0)
        return u;
     if (u->ctrl) {
@@ -108,16 +109,16 @@ DBGREFS(0, (stderr, "--> url %p -- %d %s at %s:%u\n", u, u->nrefs, msg, file, li
        free(u->buf);
        u->buf = NULL;
     }
-    FREE(u->url);
-    FREE(u->service);
-    FREE(u->user);
-    FREE(u->password);
-    FREE(u->host);
-    FREE(u->portstr);
-    FREE(u->proxyu);
-    FREE(u->proxyh);
-
-    /*@-refcounttrans@*/ FREE(u); /*@-refcounttrans@*/
+    if (u->url)                xfree(u->url);
+    if (u->service)    xfree(u->service);
+    if (u->user)       xfree(u->user);
+    if (u->password)   xfree(u->password);
+    if (u->host)       xfree(u->host);
+    if (u->portstr)    xfree(u->portstr);
+    if (u->proxyu)     xfree(u->proxyu);
+    if (u->proxyh)     xfree(u->proxyh);
+
+    /*@-refcounttrans@*/ xfree(u); /*@-refcounttrans@*/
     return NULL;
 }
 
@@ -206,7 +207,7 @@ static void urlFind(urlinfo *uret, int mustAsk)
 
     /* Zap proxy host and port in case they have been reset */
     u->proxyp = -1;
-    FREE(u->proxyh);
+    if (u->proxyh)     xfree(u->proxyh);
 
     /* Perform one-time FTP initialization */
     if (u->urltype == URL_IS_FTP) {
@@ -215,7 +216,7 @@ static void urlFind(urlinfo *uret, int mustAsk)
            char * prompt;
            prompt = alloca(strlen(u->host) + strlen(u->user) + 256);
            sprintf(prompt, _("Password for %s@%s: "), u->user, u->host);
-           FREE(u->password);
+           if (u->password)    xfree(u->password);
            u->password = xstrdup( /*@-unrecog@*/ getpass(prompt) /*@=unrecog@*/ );
        }