rpm/rpmdb.c

140 lines
3.4 KiB
C
Raw Normal View History

#include "system.h"
#include <popt.h>
#include <rpm/rpmcli.h>
#include <rpm/rpmdb.h>
#include "cliutils.h"
#include "debug.h"
enum modes {
MODE_INITDB = (1 << 0),
MODE_REBUILDDB = (1 << 1),
MODE_VERIFYDB = (1 << 2),
MODE_EXPORTDB = (1 << 3),
MODE_IMPORTDB = (1 << 4),
MODE_SALVAGEDB = (1 << 5),
};
static int mode = 0;
static struct poptOption dbOptsTable[] = {
{ "initdb", '\0', (POPT_ARG_VAL|POPT_ARGFLAG_OR), &mode, MODE_INITDB,
N_("initialize database"), NULL},
{ "rebuilddb", '\0', (POPT_ARG_VAL|POPT_ARGFLAG_OR), &mode, MODE_REBUILDDB,
N_("rebuild database inverted lists from installed package headers"),
NULL},
{ "verifydb", '\0', (POPT_ARG_VAL|POPT_ARGFLAG_OR|POPT_ARGFLAG_DOC_HIDDEN),
&mode, MODE_VERIFYDB, N_("verify database files"), NULL},
{ "salvagedb", '\0', (POPT_ARG_VAL|POPT_ARGFLAG_OR|POPT_ARGFLAG_DOC_HIDDEN),
&mode, MODE_SALVAGEDB, N_("salvage database"), NULL},
{ "exportdb", '\0', (POPT_ARG_VAL|POPT_ARGFLAG_OR), &mode, MODE_EXPORTDB,
N_("export database to stdout header list"),
NULL},
{ "importdb", '\0', (POPT_ARG_VAL|POPT_ARGFLAG_OR), &mode, MODE_IMPORTDB,
N_("import database from stdin header list"),
NULL},
POPT_TABLEEND
};
static struct poptOption optionsTable[] = {
{ NULL, '\0', POPT_ARG_INCLUDE_TABLE, dbOptsTable, 0,
N_("Database options:"), NULL },
{ NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmcliAllPoptTable, 0,
N_("Common options for all rpm modes and executables:"), NULL },
POPT_AUTOALIAS
POPT_AUTOHELP
POPT_TABLEEND
};
static int exportDB(rpmts ts)
{
FD_t fd = fdDup(STDOUT_FILENO);
rpmtxn txn = rpmtxnBegin(ts, RPMTXN_READ);
int rc = 0;
if (txn && fd) {
Header h;
rpmdbMatchIterator mi = rpmtsInitIterator(ts, RPMDBI_PACKAGES, NULL, 0);
while ((h = rpmdbNextIterator(mi))) {
rc += headerWrite(fd, h, HEADER_MAGIC_YES);
}
rpmdbFreeIterator(mi);
} else {
rc = -1;
}
Fclose(fd);
rpmtxnEnd(txn);
return rc;
}
/* XXX: only allow this on empty db? */
static int importDB(rpmts ts)
{
FD_t fd = fdDup(STDIN_FILENO);
rpmtxn txn = rpmtxnBegin(ts, RPMTXN_WRITE);
int rc = 0;
if (txn && fd) {
Header h;
while ((h = headerRead(fd, HEADER_MAGIC_YES))) {
rc += rpmtsImportHeader(txn, h, 0);
}
} else {
rc = -1;
}
rpmtxnEnd(txn);
Fclose(fd);
return rc;
}
int main(int argc, char *argv[])
{
int ec = EXIT_FAILURE;
Reimplement setprogname() and getprogname() to be generic and portable The RPM code contains setprogname()/getprogname() support implemented through compatiblity layer with very old GLIBC (internals supported back to '95 and earlier), before stabilization of the GNU C library. This compatiblity layer (__progname, __assert_progname, setprogname()) is supposed to support well archaic GLIBC, but on the other hand it pollutes the library namespace and introduces unpredicable compillation errors on BSD systems. The functions setprogname() and getprogname() are natively supported in NetBSD and work the same way as __progname from the GNU C library (they are even implemented in the same way - but with a slightly changed logic). The support for very old (20 years and older) GNU C Library is obfuscating the code, because it uses defines over defines without a word of explaination why to do so. It's important to note that the setprogname()/getprogname() was inconstiently implemented in the codebase, duplicating the code and/or functionality. Add new generic functions getprogname() and setprogname() and bind it to: - the current and for two decades stable GNU LIB C implementation, - the current NetBSD implementation (introduces to NetBSD in 2002), - fallback reimplementation functions of the setprogname() and getprogname() functionality for other systems. Don't support anymore old GNU Lib C internals and don't support older NetBSD systems, as they aren't supported for many years. Add to the codebase comments explaining the relevant codeparts.
2013-08-18 03:50:41 +08:00
poptContext optCon = NULL;
rpmts ts = NULL;
Reimplement setprogname() and getprogname() to be generic and portable The RPM code contains setprogname()/getprogname() support implemented through compatiblity layer with very old GLIBC (internals supported back to '95 and earlier), before stabilization of the GNU C library. This compatiblity layer (__progname, __assert_progname, setprogname()) is supposed to support well archaic GLIBC, but on the other hand it pollutes the library namespace and introduces unpredicable compillation errors on BSD systems. The functions setprogname() and getprogname() are natively supported in NetBSD and work the same way as __progname from the GNU C library (they are even implemented in the same way - but with a slightly changed logic). The support for very old (20 years and older) GNU C Library is obfuscating the code, because it uses defines over defines without a word of explaination why to do so. It's important to note that the setprogname()/getprogname() was inconstiently implemented in the codebase, duplicating the code and/or functionality. Add new generic functions getprogname() and setprogname() and bind it to: - the current and for two decades stable GNU LIB C implementation, - the current NetBSD implementation (introduces to NetBSD in 2002), - fallback reimplementation functions of the setprogname() and getprogname() functionality for other systems. Don't support anymore old GNU Lib C internals and don't support older NetBSD systems, as they aren't supported for many years. Add to the codebase comments explaining the relevant codeparts.
2013-08-18 03:50:41 +08:00
xsetprogname(argv[0]); /* Portability call -- see system.h */
optCon = rpmcliInit(argc, argv, optionsTable);
if (argc < 2 || poptPeekArg(optCon)) {
printUsage(optCon, stderr, 0);
goto exit;
}
ts = rpmtsCreate();
rpmtsSetRootDir(ts, rpmcliRootDir);
switch (mode) {
case MODE_INITDB:
ec = rpmtsInitDB(ts, 0644);
break;
case MODE_REBUILDDB:
case MODE_SALVAGEDB:
{ rpmVSFlags vsflags = rpmExpandNumeric("%{_vsflags_rebuilddb}");
rpmVSFlags ovsflags = rpmtsSetVSFlags(ts, vsflags);
if (mode == MODE_SALVAGEDB)
rpmDefineMacro(NULL, "_rebuilddb_salvage 1", 0);
ec = rpmtsRebuildDB(ts);
rpmtsSetVSFlags(ts, ovsflags);
} break;
case MODE_VERIFYDB:
ec = rpmtsVerifyDB(ts);
break;
case MODE_EXPORTDB:
ec = exportDB(ts);
break;
case MODE_IMPORTDB:
ec = importDB(ts);
break;
default:
argerror(_("only one major mode may be specified"));
}
exit:
rpmtsFree(ts);
rpmcliFini(optCon);
return ec;
}