Create generic iterator (needs work).

CVS patchset: 7445
CVS date: 2004/10/10 05:30:48
This commit is contained in:
jbj 2004-10-10 05:30:48 +00:00
parent fa313c61b0
commit e7f1a0e59f
5 changed files with 440 additions and 2 deletions

View File

@ -8,3 +8,4 @@ tagtable.c
*.la
*.lcd
*.lo
tgi

View 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

212
lib/rpmgi.c Normal file
View File

@ -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@*/

119
lib/rpmgi.h Normal file
View File

@ -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 */

100
lib/tgi.c Normal file
View File

@ -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;
}