1 #include "system.h"
2 
3 #include <popt.h>
4 #include <rpm/rpmcli.h>
5 #include <rpm/rpmdb.h>
6 #include "cliutils.h"
7 #include "debug.h"
8 
9 enum modes {
10     MODE_INITDB		= (1 << 0),
11     MODE_REBUILDDB	= (1 << 1),
12     MODE_VERIFYDB	= (1 << 2),
13     MODE_EXPORTDB	= (1 << 3),
14     MODE_IMPORTDB	= (1 << 4),
15     MODE_SALVAGEDB	= (1 << 5),
16 };
17 
18 static int mode = 0;
19 
20 static struct poptOption dbOptsTable[] = {
21     { "initdb", '\0', (POPT_ARG_VAL|POPT_ARGFLAG_OR), &mode, MODE_INITDB,
22 	N_("initialize database"), NULL},
23     { "rebuilddb", '\0', (POPT_ARG_VAL|POPT_ARGFLAG_OR), &mode, MODE_REBUILDDB,
24 	N_("rebuild database inverted lists from installed package headers"),
25 	NULL},
26     { "verifydb", '\0', (POPT_ARG_VAL|POPT_ARGFLAG_OR|POPT_ARGFLAG_DOC_HIDDEN),
27 	&mode, MODE_VERIFYDB, N_("verify database files"), NULL},
28     { "salvagedb", '\0', (POPT_ARG_VAL|POPT_ARGFLAG_OR|POPT_ARGFLAG_DOC_HIDDEN),
29 	&mode, MODE_SALVAGEDB, N_("salvage database"), NULL},
30     { "exportdb", '\0', (POPT_ARG_VAL|POPT_ARGFLAG_OR), &mode, MODE_EXPORTDB,
31 	N_("export database to stdout header list"),
32 	NULL},
33     { "importdb", '\0', (POPT_ARG_VAL|POPT_ARGFLAG_OR), &mode, MODE_IMPORTDB,
34 	N_("import database from stdin header list"),
35 	NULL},
36     POPT_TABLEEND
37 };
38 
39 static struct poptOption optionsTable[] = {
40     { NULL, '\0', POPT_ARG_INCLUDE_TABLE, dbOptsTable, 0,
41 	N_("Database options:"), NULL },
42     { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmcliAllPoptTable, 0,
43 	N_("Common options for all rpm modes and executables:"), NULL },
44 
45     POPT_AUTOALIAS
46     POPT_AUTOHELP
47     POPT_TABLEEND
48 };
49 
exportDB(rpmts ts)50 static int exportDB(rpmts ts)
51 {
52     FD_t fd = fdDup(STDOUT_FILENO);
53     rpmtxn txn = rpmtxnBegin(ts, RPMTXN_READ);
54     int rc = 0;
55 
56     if (txn && fd) {
57 	Header h;
58 	rpmdbMatchIterator mi = rpmtsInitIterator(ts, RPMDBI_PACKAGES, NULL, 0);
59 	while ((h = rpmdbNextIterator(mi))) {
60 	    rc += headerWrite(fd, h, HEADER_MAGIC_YES);
61 	}
62 	rpmdbFreeIterator(mi);
63     } else {
64 	rc = -1;
65     }
66     Fclose(fd);
67     rpmtxnEnd(txn);
68     return rc;
69 }
70 
71 /* XXX: only allow this on empty db? */
importDB(rpmts ts)72 static int importDB(rpmts ts)
73 {
74     FD_t fd = fdDup(STDIN_FILENO);
75     rpmtxn txn = rpmtxnBegin(ts, RPMTXN_WRITE);
76     int rc = 0;
77 
78     if (txn && fd) {
79 	Header h;
80 	while ((h = headerRead(fd, HEADER_MAGIC_YES))) {
81 	    rc += rpmtsImportHeader(txn, h, 0);
82 	}
83     } else {
84 	rc = -1;
85     }
86     rpmtxnEnd(txn);
87     Fclose(fd);
88     return rc;
89 }
90 
main(int argc,char * argv[])91 int main(int argc, char *argv[])
92 {
93     int ec = EXIT_FAILURE;
94     poptContext optCon = NULL;
95     rpmts ts = NULL;
96 
97     xsetprogname(argv[0]); /* Portability call -- see system.h */
98 
99     optCon = rpmcliInit(argc, argv, optionsTable);
100 
101     if (argc < 2 || poptPeekArg(optCon)) {
102 	printUsage(optCon, stderr, 0);
103 	goto exit;
104     }
105 
106     ts = rpmtsCreate();
107     rpmtsSetRootDir(ts, rpmcliRootDir);
108 
109     switch (mode) {
110     case MODE_INITDB:
111 	ec = rpmtsInitDB(ts, 0644);
112 	break;
113     case MODE_REBUILDDB:
114     case MODE_SALVAGEDB:
115     {   rpmVSFlags vsflags = rpmExpandNumeric("%{_vsflags_rebuilddb}");
116 	rpmVSFlags ovsflags = rpmtsSetVSFlags(ts, vsflags);
117 	if (mode == MODE_SALVAGEDB)
118 	    rpmDefineMacro(NULL, "_rebuilddb_salvage 1", 0);
119 	ec = rpmtsRebuildDB(ts);
120 	rpmtsSetVSFlags(ts, ovsflags);
121     }	break;
122     case MODE_VERIFYDB:
123 	ec = rpmtsVerifyDB(ts);
124 	break;
125     case MODE_EXPORTDB:
126 	ec = exportDB(ts);
127 	break;
128     case MODE_IMPORTDB:
129 	ec = importDB(ts);
130 	break;
131     default:
132 	argerror(_("only one major mode may be specified"));
133     }
134 
135 exit:
136     rpmtsFree(ts);
137     rpmcliFini(optCon);
138     return ec;
139 }
140