Create generic iterator (needs work).
authorjbj <devnull@localhost>
Sun, 10 Oct 2004 05:30:48 +0000 (05:30 +0000)
committerjbj <devnull@localhost>
Sun, 10 Oct 2004 05:30:48 +0000 (05:30 +0000)
CVS patchset: 7445
CVS date: 2004/10/10 05:30:48

lib/.cvsignore
lib/Makefile.am
lib/rpmgi.c [new file with mode: 0644]
lib/rpmgi.h [new file with mode: 0644]
lib/tgi.c [new file with mode: 0644]

index 1264c82..371104c 100644 (file)
@@ -8,3 +8,4 @@ tagtable.c
 *.la
 *.lcd
 *.lo
+tgi
index 317659e..381eaea 100644 (file)
@@ -13,12 +13,15 @@ INCLUDES = -I. \
        -I$(top_srcdir)/popt \
        @INCPATH@
 
-EXTRA_DIST = getdate.y
+EXTRA_DIST = getdate.y tgi.c rpmgi.c rpmgi.h
+
+EXTRA_PROGRAMS = tgi
 
 pkgincdir = $(pkgincludedir)
 pkginc_HEADERS = \
        misc.h rpmcli.h rpmlib.h \
-       rpmal.h rpmds.h rpmfi.h rpmps.h rpmsx.h rpmte.h rpmts.h stringbuf.h
+       rpmal.h rpmds.h rpmfi.h rpmps.h rpmsx.h rpmte.h rpmts.h \
+       stringbuf.h
 noinst_HEADERS = \
        cpio.h fsm.h manifest.h psm.h rpmlead.h signature.h rpmlock.h
 
@@ -119,3 +122,6 @@ tplatform: tplatform.o librpm.la
 
 trhn: trhn.o librpm.la
        $(LINK) @LDFLAGS_STATIC@ $(CFLAGS) $(DEFS) $(INCLUDES) -o $@ $< $(mylibs)
+
+tgi_SOURCES = tgi.c rpmgi.c
+tgi_LDADD = librpm.la
diff --git a/lib/rpmgi.c b/lib/rpmgi.c
new file mode 100644 (file)
index 0000000..42fd7a2
--- /dev/null
@@ -0,0 +1,212 @@
+/*@-modfilesys@*/
+/** \ingroup rpmio
+ * \file rpmio/rpmio.c
+ */
+#include "system.h"
+
+#define        _RPMGI_INTERNAL
+#include <rpmgi.h>
+
+#include <rpmdb.h>
+
+#include "debug.h"
+
+/*@unchecked@*/
+int _rpmgi_debug = 0;
+
+rpmgi XrpmgiUnlink(rpmgi gi, const char * msg, const char * fn, unsigned ln)
+{
+    if (gi == NULL) return NULL;
+
+if (_rpmgi_debug && msg != NULL)
+fprintf(stderr, "--> gi %p -- %d %s at %s:%u\n", gi, gi->nrefs, msg, fn, ln);
+
+    gi->nrefs--;
+    return NULL;
+}
+
+rpmgi XrpmgiLink(rpmgi gi, const char * msg, const char * fn, unsigned ln)
+{
+    if (gi == NULL) return NULL;
+    gi->nrefs++;
+
+if (_rpmgi_debug && msg != NULL)
+fprintf(stderr, "--> gi %p ++ %d %s at %s:%u\n", gi, gi->nrefs, msg, fn, ln);
+
+    /*@-refcounttrans@*/ return gi; /*@=refcounttrans@*/
+}
+
+rpmgi rpmgiFree(rpmgi gi)
+{
+    if (gi == NULL)
+       return NULL;
+
+    if (gi->nrefs > 1)
+       return rpmgiUnlink(gi, NULL);
+
+if (_rpmgi_debug < 0)
+fprintf(stderr, "*** gi %p\t%p[%d]\n", gi, gi->argv, gi->argc);
+
+    (void) rpmgiUnlink(gi, NULL);
+
+    switch (gi->tag) {
+    default:
+    case RPMGI_RPMDB:
+       break;
+    case RPMGI_HDLIST:
+       break;
+    case RPMGI_ARGLIST:
+       break;
+    case RPMGI_FTSWALK:
+       break;
+    }
+
+    if (gi->ftsp != NULL) {
+       int xx;
+       xx = Fts_close(gi->ftsp);
+       gi->ftsp = NULL;
+       gi->fts = NULL;
+    }
+    gi->mi = rpmdbFreeIterator(gi->mi);
+    gi->ts = rpmtsFree(gi->ts);
+
+    memset(gi, 0, sizeof(*gi));                /* XXX trash and burn */
+    gi = _free(gi);
+    return NULL;
+}
+
+rpmgi rpmgiNew(rpmts ts, int tag, const void * keyp, size_t keylen)
+{
+    rpmgi gi = xcalloc(1, sizeof(*gi));
+
+    if (gi == NULL)
+       return NULL;
+
+    gi->ts = rpmtsLink(ts, NULL);
+    gi->tag = tag;
+    gi->i = -1;
+
+    switch (gi->tag) {
+    default:
+    case RPMGI_RPMDB:
+       gi->mi = rpmtsInitIterator(ts, RPMDBI_PACKAGES, NULL, 0);
+
+if (_rpmgi_debug < 0)
+fprintf(stderr, "*** gi %p\t%p\n", gi, gi->mi);
+
+       break;
+    case RPMGI_HDLIST:
+       break;
+    case RPMGI_ARGLIST:
+    case RPMGI_FTSWALK:
+    {   char *const * argv = keyp;
+       unsigned flags = keylen;
+
+       gi->argv = argv;
+       gi->argc = 0;
+       if (argv != NULL)
+        while (*argv++ != NULL)
+          gi->argc++;
+       gi->ftsOpts = flags;
+
+if (_rpmgi_debug < 0)
+fprintf(stderr, "*** gi %p\t%p[%d]\n", gi, gi->argv, gi->argc);
+
+    }  break;
+    }
+
+    gi = rpmgiLink(gi, NULL);
+
+    return gi;
+}
+
+static int indent = 2;
+
+static const char * ftsInfoStrings[] = {
+    "UNKNOWN",
+    "D",
+    "DC",
+    "DEFAULT",
+    "DNR",
+    "DOT",
+    "DP",
+    "ERR",
+    "F",
+    "INIT",
+    "NS",
+    "NSOK",
+    "SL",
+    "SLNONE",
+    "W",
+};
+
+static const char * ftsInfoStr(int fts_info) {
+    if (!(fts_info >= 1 && fts_info <= 14))
+       fts_info = 0;
+    return ftsInfoStrings[ fts_info ];
+}
+
+const char * rpmgiNext(/*@null@*/ rpmgi gi)
+       /*@modifies gi @*/
+{
+    const char * val = NULL;
+    Header h = NULL;
+
+    if (gi != NULL && ++gi->i >= 0)
+    switch (gi->tag) {
+    default:
+    case RPMGI_RPMDB:
+       h = rpmdbNextIterator(gi->mi);
+       if (h != NULL) {
+           const char * fmt = "%{NAME}-%{VERSION}-%{RELEASE}";
+           val = headerSprintf(h, fmt, rpmTagTable, rpmHeaderFormats, NULL);
+       } else {
+           gi->mi = rpmdbFreeIterator(gi->mi);
+           gi->i = -1;
+       }
+       break;
+    case RPMGI_HDLIST:
+       break;
+    case RPMGI_ARGLIST:
+       if (gi->argv != NULL && gi->argv[gi->i] != NULL) {
+if (_rpmgi_debug  < 0)
+fprintf(stderr, "*** gi %p\t%p[%d]: %s\n", gi, gi->argv, gi->i, gi->argv[gi->i]);
+           val = xstrdup(gi->argv[gi->i]);
+       } else
+           gi->i = -1;
+       break;
+    case RPMGI_FTSWALK:
+       if (gi->ftsp == NULL && gi->i == 0)
+           gi->ftsp = Fts_open(gi->argv, gi->ftsOpts, NULL);
+
+       while (val == NULL && (gi->fts = Fts_read(gi->ftsp)) != NULL) {
+           FTSENT * fts = gi->fts;
+
+if (_rpmgi_debug < 0)
+fprintf(stderr, "FTS_%s\t%*s %s\n", ftsInfoStr(fts->fts_info),
+               indent * (fts->fts_level < 0 ? 0 : fts->fts_level), "",
+               fts->fts_name);
+
+           switch (fts->fts_info) {
+           case FTS_F:
+           case FTS_SL:
+if (_rpmgi_debug  < 0)
+fprintf(stderr, "*** gi %p\t%p[%d]: %s\n", gi, gi->ftsp, gi->i, fts->fts_path);
+               val = xstrdup(fts->fts_path);
+               break;
+           default:
+               break;
+           }
+       }
+       if (gi->fts == NULL && gi->ftsp != NULL) {
+           int xx;
+           xx = Fts_close(gi->ftsp);
+           gi->ftsp = NULL;
+           gi->i = -1;
+       }
+       break;
+    }
+
+    return val;
+}
+/*@=modfilesys@*/
diff --git a/lib/rpmgi.h b/lib/rpmgi.h
new file mode 100644 (file)
index 0000000..0ee41c5
--- /dev/null
@@ -0,0 +1,119 @@
+#ifndef        H_RPMGI
+#define        H_RPMGI
+
+/** \ingroup rpmio
+ * \file rpmio/rpmgi.h
+ */
+
+#include <rpmlib.h>
+#include <rpmts.h>
+#include <fts.h>
+#include <argv.h>
+
+/**
+ */
+/*@-exportlocal@*/
+/*@unchecked@*/
+extern int _rpmgi_debug;
+/*@=exportlocal@*/
+
+/**
+ */
+typedef /*@abstract@*/ struct rpmgi_s * rpmgi;
+
+/**
+ */
+typedef enum rpmgiTag_e {
+    RPMGI_RPMDB                = RPMDBI_PACKAGES,
+    RPMGI_HDLIST       = 6,    /* XXX next after RPMDBI_AVAILABLE */
+    RPMGI_ARGLIST      = 7,
+    RPMGI_FTSWALK      = 8
+} rpmgiTag;
+
+#if defined(_RPMGI_INTERNAL)
+/** \ingroup rpmio
+ */
+struct rpmgi_s {
+    rpmts ts;
+    int tag;
+    int i;
+
+    rpmdbMatchIterator mi;
+
+    char *const * argv;
+    int argc;
+    int ftsOpts;
+    FTS * ftsp;
+    FTSENT * fts;
+
+/*@refs@*/
+    int nrefs;
+};
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Unreference a generalized iterator instance.
+ * @param gi           generalized iterator
+ * @param msg
+ * @return             NULL always
+ */
+/*@unused@*/ /*@null@*/
+rpmgi rpmgiUnlink (/*@killref@*/ /*@only@*/ /*@null@*/ rpmgi gi,
+               /*@null@*/ const char * msg)
+       /*@modifies gi @*/;
+
+/** @todo Remove debugging entry from the ABI. */
+/*@-exportlocal@*/
+/*@null@*/
+rpmgi XrpmgiUnlink (/*@killref@*/ /*@only@*/ /*@null@*/ rpmgi gi,
+               /*@null@*/ const char * msg, const char * fn, unsigned ln)
+       /*@modifies gi @*/;
+/*@=exportlocal@*/
+#define        rpmgiUnlink(_gi, _msg)  XrpmgiUnlink(_gi, _msg, __FILE__, __LINE__)
+
+/**
+ * Reference a generalized iterator instance.
+ * @param gi           generalized iterator
+ * @param msg
+ * @return             new generalized iterator reference
+ */
+/*@unused@*/ /*@newref@*/ /*@null@*/
+rpmgi rpmgiLink (/*@null@*/ rpmgi gi, /*@null@*/ const char * msg)
+       /*@modifies gi @*/;
+
+/** @todo Remove debugging entry from the ABI. */
+/*@newref@*/ /*@null@*/
+rpmgi XrpmgiLink (/*@null@*/ rpmgi gi, /*@null@*/ const char * msg,
+               const char * fn, unsigned ln)
+        /*@modifies gi @*/;
+#define        rpmgiLink(_gi, _msg)    XrpmgiLink(_gi, _msg, __FILE__, __LINE__)
+
+/** Destroy a generalized iterator.
+ * @param gi           generalized iterator
+ * @return             NULL always
+ */
+/*@only@*/
+rpmgi rpmgiFree(/*@killref@*/ /*@only@*/ /*@null@*/ rpmgi gi)
+       /*@modifies gi @*/;
+
+/** Create a generalized iterator.
+ * @param argv         iterator argv array
+ * @param flags                iterator flags
+ * @return             new general iterator
+ */
+/*@only@*/
+rpmgi rpmgiNew(rpmts ts, int tag, const void * keyp, size_t keylen)
+       /*@*/;
+
+const char * rpmgiNext(/*@null@*/ rpmgi gi)
+        /*@modifies gi @*/;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* H_RPMGI */
diff --git a/lib/tgi.c b/lib/tgi.c
new file mode 100644 (file)
index 0000000..580d7f6
--- /dev/null
+++ b/lib/tgi.c
@@ -0,0 +1,100 @@
+#include "system.h"
+
+#include <rpmio_internal.h>
+#define        _RPMGI_INTERNAL
+#include <rpmgi.h>
+#include <rpmcli.h>
+
+#include <rpmmacro.h>
+#include <rpmmessages.h>
+#include <popt.h>
+
+#include "debug.h"
+
+static int gitag = RPMGI_FTSWALK;
+static int ftsOpts = 0;
+
+static struct poptOption optionsTable[] = {
+ { "rpmgidebug", 'd', POPT_ARG_VAL|POPT_ARGFLAG_DOC_HIDDEN, &_rpmgi_debug, -1,
+       N_("debug generalized iterator"), NULL},
+
+ { "rpmdb", '\0', POPT_ARG_VAL, &gitag, RPMGI_RPMDB,
+       N_("iterate rpmdb"), NULL },
+ { "hdlist", '\0', POPT_ARG_VAL, &gitag, RPMGI_HDLIST,
+       N_("iterate hdlist"), NULL },
+ { "arglist", '\0', POPT_ARG_VAL, &gitag, RPMGI_ARGLIST,
+       N_("iterate arglist"), NULL },
+ { "ftswalk", '\0', POPT_ARG_VAL, &gitag, RPMGI_FTSWALK,
+       N_("iterate fts(3) walk"), NULL },
+
+ { "comfollow", '\0', POPT_BIT_SET,    &ftsOpts, FTS_COMFOLLOW,
+       N_("follow command line symlinks"), NULL },
+ { "logical", '\0', POPT_BIT_SET,      &ftsOpts, FTS_LOGICAL,
+       N_("logical walk"), NULL },
+ { "nochdir", '\0', POPT_BIT_SET,      &ftsOpts, FTS_NOCHDIR,
+       N_("don't change directories"), NULL },
+ { "nostat", '\0', POPT_BIT_SET,       &ftsOpts, FTS_NOSTAT,
+       N_("don't get stat info"), NULL },
+ { "physical", '\0', POPT_BIT_SET,     &ftsOpts, FTS_PHYSICAL,
+       N_("physical walk"), NULL },
+ { "seedot", '\0', POPT_BIT_SET,       &ftsOpts, FTS_SEEDOT,
+       N_("return dot and dot-dot"), NULL },
+ { "xdev", '\0', POPT_BIT_SET,         &ftsOpts, FTS_XDEV,
+       N_("don't cross devices"), NULL },
+ { "whiteout", '\0', POPT_BIT_SET,     &ftsOpts, FTS_WHITEOUT,
+       N_("return whiteout information"), NULL },
+
+#ifdef DYING
+ { "ftpdebug", '\0', POPT_ARG_VAL|POPT_ARGFLAG_DOC_HIDDEN, &_ftp_debug, -1,
+       N_("debug protocol data stream"), NULL},
+ { "rpmiodebug", '\0', POPT_ARG_VAL|POPT_ARGFLAG_DOC_HIDDEN, &_rpmio_debug, -1,
+       N_("debug rpmio I/O"), NULL},
+ { "urldebug", '\0', POPT_ARG_VAL|POPT_ARGFLAG_DOC_HIDDEN, &_url_debug, -1,
+       N_("debug URL cache handling"), NULL},
+ { "verbose", 'v', 0, 0, 'v',                          NULL, NULL },
+#endif
+
+ { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmcliAllPoptTable, 0,
+        N_("Common options for all rpm modes and executables:"),
+        NULL },
+
+  POPT_AUTOALIAS
+  POPT_AUTOHELP
+  POPT_TABLEEND
+};
+
+int
+main(int argc, char *const argv[])
+{
+    poptContext optCon;
+    rpmts ts = NULL;
+    rpmgi gi = NULL;
+    const char ** av;
+    const char * arg;
+    int ac;
+    int rc = 0;
+
+    optCon = rpmcliInit(argc, argv, optionsTable);
+    if (optCon == NULL)
+        exit(EXIT_FAILURE);
+
+    if (ftsOpts == 0)
+       ftsOpts = (FTS_COMFOLLOW | FTS_LOGICAL | FTS_NOSTAT);
+
+    ts = rpmtsCreate();
+    av = poptGetArgs(optCon);
+    gi = rpmgiNew(ts, gitag, av, ftsOpts);
+
+    ac = 0;
+    while ((arg = rpmgiNext(gi)) != NULL) {
+       fprintf(stderr, "%5d %s\n", ac, arg);
+       arg = _free(arg);
+       ac++;
+    }
+
+    gi = rpmgiFree(gi);
+    ts = rpmtsFree(ts);
+    optCon = rpmcliFini(optCon);
+
+    return rc;
+}