/* XXX the signal handling in here is not thread safe */
+/* the requiredbyIndex isn't stricly necessary. In a perfect world, we could
+ have each header keep a list of packages that need it. However, we
+ can't reserve space in the header for extra information so all of the
+ required packages would move in the database every time a package was
+ added or removed. Instead, each package (or virtual package) name
+ keeps a list of package offsets of packages that might depend on this
+ one. Version numbers still need verification, but it gets us in the
+ right area w/o a linear search through the database. */
+
struct rpmdb {
faFile pkgs;
- dbIndex * nameIndex, * fileIndex, * groupIndex;
+ dbIndex * nameIndex, * fileIndex, * groupIndex, * providesIndex;
+ dbIndex * requiredbyIndex;
};
static void removeIndexEntry(dbIndex * dbi, char * name, dbIndexRecord rec,
if (!db.groupIndex) {
faClose(db.pkgs);
closeDBIndex(db.nameIndex);
+ closeDBIndex(db.fileIndex);
+ return 1;
+ }
+
+ strcpy(filename, prefix);
+ strcat(filename, "/var/lib/rpm/providesindex.rpm");
+ db.providesIndex = openDBIndex(filename, mode, 0644);
+ if (!db.providesIndex) {
+ faClose(db.pkgs);
+ closeDBIndex(db.fileIndex);
+ closeDBIndex(db.nameIndex);
+ closeDBIndex(db.groupIndex);
+ return 1;
+ }
+
+ strcpy(filename, prefix);
+ strcat(filename, "/var/lib/rpm/requiredby.rpm");
+ db.requiredbyIndex = openDBIndex(filename, mode, 0644);
+ if (!db.requiredbyIndex) {
+ faClose(db.pkgs);
+ closeDBIndex(db.fileIndex);
+ closeDBIndex(db.nameIndex);
+ closeDBIndex(db.groupIndex);
+ closeDBIndex(db.providesIndex);
return 1;
}
closeDBIndex(db->fileIndex);
closeDBIndex(db->groupIndex);
closeDBIndex(db->nameIndex);
+ closeDBIndex(db->providesIndex);
+ closeDBIndex(db->requiredbyIndex);
free(db);
}
return searchDBIndex(db->fileIndex, filespec, matches);
}
+int rpmdbFindByProvides(rpmdb db, char * filespec, dbIndexSet * matches) {
+ return searchDBIndex(db->providesIndex, filespec, matches);
+}
+
+int rpmdbFindByRequiredBy(rpmdb db, char * filespec, dbIndexSet * matches) {
+ return searchDBIndex(db->requiredbyIndex, filespec, matches);
+}
+
int rpmdbFindByGroup(rpmdb db, char * group, dbIndexSet * matches) {
return searchDBIndex(db->groupIndex, group, matches);
}
int type;
unsigned int count;
dbIndexRecord rec;
- char ** fileList;
+ char ** fileList, ** providesList, ** requiredbyList;
int i;
rec.recOffset = offset;
removeIndexEntry(db->groupIndex, group, rec, tolerant, "group index");
}
+ if (getEntry(h, RPMTAG_PROVIDES, &type, (void **) &providesList,
+ &count)) {
+ for (i = 0; i < count; i++) {
+ message(MESS_DEBUG, "removing provides index for %s\n",
+ providesList[i]);
+ removeIndexEntry(db->providesIndex, providesList[i], rec, tolerant,
+ "providesfile index");
+ }
+ free(providesList);
+ }
+
+ if (getEntry(h, RPMTAG_REQUIRENAME, &type, (void **) &requiredbyList,
+ &count)) {
+ for (i = 0; i < count; i++) {
+ message(MESS_DEBUG, "removing requiredby index for %s\n",
+ requiredbyList[i]);
+ removeIndexEntry(db->requiredbyIndex, requiredbyList[i], rec,
+ tolerant, "requiredby index");
+ }
+ free(requiredbyList);
+ }
+
if (getEntry(h, RPMTAG_FILENAMES, &type, (void **) &fileList,
&count)) {
for (i = 0; i < count; i++) {
removeIndexEntry(db->fileIndex, fileList[i], rec, tolerant,
"file index");
}
+ free(fileList);
} else {
message(MESS_DEBUG, "package has no files\n");
}
unsigned int dboffset;
unsigned int i;
char ** fileList;
+ char ** providesList;
+ char ** requiredbyList;
char * name, * group;
- int count;
+ int count, providesCount, requiredbyCount;
int type;
int rc = 0;
count = 0;
}
+ if (!getEntry(dbentry, RPMTAG_PROVIDES, &type, (void **) &providesList,
+ &providesCount)) {
+ providesCount = 0;
+ }
+
+ if (!getEntry(dbentry, RPMTAG_REQUIRENAME, &type,
+ (void **) &requiredbyList, &requiredbyCount)) {
+ requiredbyCount = 0;
+ }
+
blockSignals();
dboffset = faAlloc(db->pkgs, sizeofHeader(dbentry));
if (!dboffset) {
error(RPMERR_DBCORRUPT, "cannot allocate space for database");
unblockSignals();
+ if (providesCount) free(providesList);
+ if (requiredbyCount) free(requiredbyList);
+ if (count) free(fileList);
return 1;
}
lseek(db->pkgs->fd, dboffset, SEEK_SET);
if (addIndexEntry(db->groupIndex, group, dboffset, 0))
rc = 1;
+ for (i = 0; i < requiredbyCount; i++) {
+ if (addIndexEntry(db->requiredbyIndex, requiredbyList[i], dboffset, 0))
+ rc = 1;
+ }
+
+ for (i = 0; i < providesCount; i++) {
+ if (addIndexEntry(db->providesIndex, providesList[i], dboffset, 0))
+ rc = 1;
+ }
+
for (i = 0; i < count; i++) {
if (addIndexEntry(db->fileIndex, fileList[i], dboffset, i))
rc = 1;
syncDBIndex(db->nameIndex);
syncDBIndex(db->groupIndex);
syncDBIndex(db->fileIndex);
+ syncDBIndex(db->providesIndex);
+ syncDBIndex(db->requiredbyIndex);
unblockSignals();
+ if (requiredbyCount) free(requiredbyList);
+ if (providesCount) free(providesList);
if (count) free(fileList);
return rc;