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, char *dbname, struct stat *statbuf, int seterror)
37 dbpath = solv_dupjoin(state->rootdir, state->is_ostree ? "/usr/share/rpm/" : "/var/lib/rpm/", dbname);
38 if (stat(dbpath, statbuf))
41 pool_error(state->pool, -1, "%s: %s", dbpath, strerror(errno));
50 opendbenv(struct rpmdbstate *state)
52 const char *rootdir = state->rootdir;
55 dbpath = solv_dupjoin("_dbpath ", rootdir, "/var/lib/rpm");
56 if (access(dbpath + 8, W_OK) == -1)
59 dbpath = solv_dupjoin(rootdir, "/usr/share/rpm/Packages", 0);
60 if (access(dbpath, R_OK) == 0)
63 dbpath = solv_dupjoin("_dbpath ", rootdir, state->is_ostree ? "/usr/share/rpm" : "/var/lib/rpm");
65 rpmDefineMacro(NULL, dbpath, 0);
70 pool_error(state->pool, 0, "rpmtsCreate failed");
71 delMacro(NULL, "_dbpath");
74 if (rpmtsOpenDB(ts, O_RDONLY))
76 pool_error(state->pool, 0, "rpmtsOpenDB failed: %s", strerror(errno));
78 delMacro(NULL, "_dbpath");
81 delMacro(NULL, "_dbpath");
82 rpmtsSetVSFlags(ts, _RPMVSF_NODIGESTS | _RPMVSF_NOSIGNATURES | _RPMVSF_NOHEADER);
84 state->dbenvopened = 1;
85 state->pkgdbopened = 1;
90 closedbenv(struct rpmdbstate *state)
95 state->pkgdbopened = 0;
96 state->dbenvopened = 0;
100 openpkgdb(struct rpmdbstate *state)
102 /* already done in opendbenv */
107 closepkgdb(struct rpmdbstate *state)
111 /* get the rpmdbids of all installed packages from the Name index database.
112 * This is much faster then querying the big Packages database */
113 static struct rpmdbentry *
114 getinstalledrpmdbids(struct rpmdbstate *state, const char *index, const char *match, int *nentriesp, char **namedatap, int keep_gpg_pubkey)
117 size_t keylen, matchl = 0;
122 struct rpmdbentry *entries = 0;
125 rpmdbIndexIterator ii;
132 if (state->dbenvopened != 1 && !opendbenv(state))
136 matchl = strlen(match);
137 ii = rpmdbIndexIteratorInit(rpmtsGetRdb(state->ts), RPMDBI_NAME);
139 while (rpmdbIndexIteratorNext(ii, &key, &keylen) == 0)
143 if (keylen != matchl || memcmp(key, match, keylen) != 0)
146 else if (!keep_gpg_pubkey && keylen == 10 && !memcmp(key, "gpg-pubkey", 10))
151 namedata = solv_extend(namedata, namedatal, keylen + 1, 1, NAMEDATA_BLOCK);
152 memcpy(namedata + namedatal, key, keylen);
153 namedata[namedatal + keylen] = 0;
154 namedatal += keylen + 1;
156 for (i = 0; i < rpmdbIndexIteratorNumPkgs(ii); i++)
158 entries = solv_extend(entries, nentries, 1, sizeof(*entries), ENTRIES_BLOCK);
159 entries[nentries].rpmdbid = rpmdbIndexIteratorPkgOffset(ii, i);
160 entries[nentries].nameoff = nameoff;
164 rpmdbIndexIteratorFree(ii);
165 /* make sure that enteries is != 0 if there was no error */
167 entries = solv_extend(entries, 1, 1, sizeof(*entries), ENTRIES_BLOCK);
168 *nentriesp = nentries;
170 *namedatap = namedata;
174 /* retrive header by rpmdbid, returns 0 if not found, -1 on error */
176 getrpm_dbid(struct rpmdbstate *state, Id rpmdbid)
179 rpmdbMatchIterator mi;
180 unsigned int offset = rpmdbid;
182 if (state->dbenvopened != 1 && !opendbenv(state))
184 mi = rpmtsInitIterator(state->ts, RPMDBI_PACKAGES, &offset, sizeof(offset));
185 h = rpmdbNextIterator(mi);
188 rpmdbFreeIterator(mi);
191 if (!rpm_byrpmh(state, h))
193 rpmdbFreeIterator(mi);
196 mi = rpmdbFreeIterator(mi);
201 count_headers(struct rpmdbstate *state)
204 rpmdbMatchIterator mi;
206 if (state->dbenvopened != 1 && !opendbenv(state))
208 mi = rpmtsInitIterator(state->ts, RPMDBI_NAME, NULL, 0);
209 count = rpmdbGetIteratorCount(mi);
210 rpmdbFreeIterator(mi);
215 pkgdb_cursor_open(struct rpmdbstate *state)
217 state->mi = rpmtsInitIterator(state->ts, RPMDBI_PACKAGES, NULL, 0);
222 pkgdb_cursor_close(struct rpmdbstate *state)
224 rpmdbFreeIterator(state->mi);
229 pkgdb_cursor_getrpm(struct rpmdbstate *state)
232 while ((h = rpmdbNextIterator(state->mi)))
234 Id dbid = rpmdbGetIteratorOffset(state->mi);
235 if (!rpm_byrpmh(state, h))