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)
122 struct rpmdbentry *entries = 0;
125 rpmdbIndexIterator ii;
128 if (state->dbenvopened != 1 && !opendbenv(state))
131 ii = rpmdbIndexIteratorInit(rpmtsGetRdb(state->ts), RPMDBI_NAME);
137 while (rpmdbIndexIteratorNext(ii, &key, &keylen) == 0)
140 if (keylen == 10 && !memcmp(key, "gpg-pubkey", 10))
145 namedata = solv_extend(namedata, namedatal, keylen + 1, 1, NAMEDATA_BLOCK);
146 memcpy(namedata + namedatal, key, keylen);
147 namedata[namedatal + keylen] = 0;
148 namedatal += keylen + 1;
150 for (i = 0; i < rpmdbIndexIteratorNumPkgs(ii); i++)
152 entries = solv_extend(entries, nentries, 1, sizeof(*entries), ENTRIES_BLOCK);
153 entries[nentries].rpmdbid = rpmdbIndexIteratorPkgOffset(ii, i);
154 entries[nentries].nameoff = nameoff;
158 rpmdbIndexIteratorFree(ii);
159 /* make sure that enteries is != 0 if there was no error */
161 entries = solv_extend(entries, 1, 1, sizeof(*entries), ENTRIES_BLOCK);
162 *nentriesp = nentries;
164 *namedatap = namedata;
168 /* retrive header by rpmdbid, returns 0 if not found, -1 on error */
170 getrpm_dbid(struct rpmdbstate *state, Id rpmdbid)
173 rpmdbMatchIterator mi;
174 unsigned int offset = rpmdbid;
176 if (state->dbenvopened != 1 && !opendbenv(state))
178 mi = rpmtsInitIterator(state->ts, RPMDBI_PACKAGES, &offset, sizeof(offset));
179 h = rpmdbNextIterator(mi);
182 rpmdbFreeIterator(mi);
185 if (!rpm_byrpmh(state, h))
187 rpmdbFreeIterator(mi);
190 mi = rpmdbFreeIterator(mi);
195 count_headers(struct rpmdbstate *state)
198 rpmdbMatchIterator mi;
200 if (state->dbenvopened != 1 && !opendbenv(state))
202 mi = rpmtsInitIterator(state->ts, RPMDBI_NAME, NULL, 0);
203 count = rpmdbGetIteratorCount(mi);
204 rpmdbFreeIterator(mi);
209 pkgdb_cursor_open(struct rpmdbstate *state)
211 state->mi = rpmtsInitIterator(state->ts, RPMDBI_PACKAGES, NULL, 0);
216 pkgdb_cursor_close(struct rpmdbstate *state)
218 rpmdbFreeIterator(state->mi);
223 pkgdb_cursor_getrpm(struct rpmdbstate *state)
226 while ((h = rpmdbNextIterator(state->mi)))
228 Id dbid = rpmdbGetIteratorOffset(state->mi);
229 if (!rpm_byrpmh(state, h))