2 * Copyright (c) 2018, SUSE Inc.
4 * This program is licensed under the BSD license, read LICENSE.BSD
5 * for further information
11 * Use librpm to access the rpm database
15 #include <rpm/rpmts.h>
16 #include <rpm/rpmmacro.h>
22 RpmHead *rpmhead; /* header storage space */
25 int dbenvopened; /* database environment opened */
26 int pkgdbopened; /* package database openend */
27 int is_ostree; /* read-only db that lives in /usr/share/rpm */
30 rpmdbMatchIterator mi; /* iterator over packages database */
34 stat_database(struct rpmdbstate *state, struct stat *statbuf)
36 static const char *dbname[] = {
41 "Packages", /* for error reporting */
48 char *dbpath = solv_dupjoin(state->rootdir, state->is_ostree ? "/usr/share/rpm/" : "/var/lib/rpm/", dbname[i]);
49 if (!stat(dbpath, statbuf))
54 if (errno != ENOENT || !dbname[i + 1])
56 pool_error(state->pool, -1, "%s: %s", dbpath, strerror(errno));
66 opendbenv(struct rpmdbstate *state)
68 const char *rootdir = state->rootdir;
71 dbpath = solv_dupjoin("_dbpath ", rootdir, "/var/lib/rpm");
72 if (access(dbpath + 8, W_OK) == -1)
75 dbpath = solv_dupjoin(rootdir, "/usr/share/rpm/Packages", 0);
76 if (access(dbpath, R_OK) == 0)
79 dbpath = solv_dupjoin("_dbpath ", rootdir, state->is_ostree ? "/usr/share/rpm" : "/var/lib/rpm");
81 rpmDefineMacro(NULL, dbpath, 0);
86 pool_error(state->pool, 0, "rpmtsCreate failed");
87 delMacro(NULL, "_dbpath");
90 if (rpmtsOpenDB(ts, O_RDONLY))
92 pool_error(state->pool, 0, "rpmtsOpenDB failed: %s", strerror(errno));
94 delMacro(NULL, "_dbpath");
97 delMacro(NULL, "_dbpath");
98 rpmtsSetVSFlags(ts, _RPMVSF_NODIGESTS | _RPMVSF_NOSIGNATURES | _RPMVSF_NOHEADER);
100 state->dbenvopened = 1;
101 state->pkgdbopened = 1;
106 closedbenv(struct rpmdbstate *state)
109 rpmtsFree(state->ts);
111 state->pkgdbopened = 0;
112 state->dbenvopened = 0;
116 openpkgdb(struct rpmdbstate *state)
118 /* already done in opendbenv */
123 closepkgdb(struct rpmdbstate *state)
127 /* get the rpmdbids of all installed packages from the Name index database.
128 * This is much faster then querying the big Packages database */
129 static struct rpmdbentry *
130 getinstalledrpmdbids(struct rpmdbstate *state, const char *index, const char *match, int *nentriesp, char **namedatap, int keep_gpg_pubkey)
133 size_t keylen, matchl = 0;
138 struct rpmdbentry *entries = 0;
141 rpmdbIndexIterator ii;
148 if (state->dbenvopened != 1 && !opendbenv(state))
152 matchl = strlen(match);
153 ii = rpmdbIndexIteratorInit(rpmtsGetRdb(state->ts), RPMDBI_NAME);
155 while (rpmdbIndexIteratorNext(ii, &key, &keylen) == 0)
159 if (keylen != matchl || memcmp(key, match, keylen) != 0)
162 else if (!keep_gpg_pubkey && keylen == 10 && !memcmp(key, "gpg-pubkey", 10))
167 namedata = solv_extend(namedata, namedatal, keylen + 1, 1, NAMEDATA_BLOCK);
168 memcpy(namedata + namedatal, key, keylen);
169 namedata[namedatal + keylen] = 0;
170 namedatal += keylen + 1;
172 for (i = 0; i < rpmdbIndexIteratorNumPkgs(ii); i++)
174 entries = solv_extend(entries, nentries, 1, sizeof(*entries), ENTRIES_BLOCK);
175 entries[nentries].rpmdbid = rpmdbIndexIteratorPkgOffset(ii, i);
176 entries[nentries].nameoff = nameoff;
180 rpmdbIndexIteratorFree(ii);
181 /* make sure that enteries is != 0 if there was no error */
183 entries = solv_extend(entries, 1, 1, sizeof(*entries), ENTRIES_BLOCK);
184 *nentriesp = nentries;
186 *namedatap = namedata;
190 /* retrive header by rpmdbid, returns 0 if not found, -1 on error */
192 getrpm_dbid(struct rpmdbstate *state, Id rpmdbid)
195 rpmdbMatchIterator mi;
196 unsigned int offset = rpmdbid;
198 if (state->dbenvopened != 1 && !opendbenv(state))
200 mi = rpmtsInitIterator(state->ts, RPMDBI_PACKAGES, &offset, sizeof(offset));
201 h = rpmdbNextIterator(mi);
204 rpmdbFreeIterator(mi);
207 if (!rpm_byrpmh(state, h))
209 rpmdbFreeIterator(mi);
212 mi = rpmdbFreeIterator(mi);
217 count_headers(struct rpmdbstate *state)
220 rpmdbMatchIterator mi;
222 if (state->dbenvopened != 1 && !opendbenv(state))
224 mi = rpmtsInitIterator(state->ts, RPMDBI_NAME, NULL, 0);
225 count = rpmdbGetIteratorCount(mi);
226 rpmdbFreeIterator(mi);
231 pkgdb_cursor_open(struct rpmdbstate *state)
233 state->mi = rpmtsInitIterator(state->ts, RPMDBI_PACKAGES, NULL, 0);
238 pkgdb_cursor_close(struct rpmdbstate *state)
240 rpmdbFreeIterator(state->mi);
245 pkgdb_cursor_getrpm(struct rpmdbstate *state)
248 while ((h = rpmdbNextIterator(state->mi)))
250 Id dbid = rpmdbGetIteratorOffset(state->mi);
251 if (!rpm_byrpmh(state, h))