al.c: factored from depends.c

This commit is contained in:
Alexey Tourbin 2009-10-02 11:47:28 +04:00
parent d9e8ab64f5
commit 5c8817985a
5 changed files with 553 additions and 554 deletions

View File

@ -14,7 +14,7 @@ pkgincdir = $(pkgincludedir)
pkginc_HEADERS = \
header.h misc.h rpmcli.h rpmlib.h stringbuf.h
noinst_HEADERS = \
cpio.h depends.h fsm.h header_internal.h \
al.h cpio.h depends.h fsm.h header_internal.h \
manifest.h psm.h \
rpmlead.h signature.h
@ -28,7 +28,7 @@ LIBS =
lib_LTLIBRARIES = librpm.la
librpm_la_SOURCES = \
closeall.c cpio.c depends.c formats.c fs.c fsm.c getdate.c \
al.c closeall.c cpio.c depends.c formats.c fs.c fsm.c getdate.c \
header_internal.c manifest.c misc.c package.c \
problems.c poptI.c poptK.c poptQV.c psm.c query.c \
rpmchecksig.c rpminstall.c rpmlead.c rpmlibprov.c rpmrc.c \

457
lib/al.c Normal file
View File

@ -0,0 +1,457 @@
#include "system.h"
#include "rpmlib.h"
#include "depends.h"
#include "al.h"
/** \ingroup rpmdep
* A single available item (e.g. a Provides: dependency).
*/
struct availableIndexEntry {
/*@dependent@*/ struct availablePackage * package; /*!< Containing package. */
/*@dependent@*/ const char * entry; /*!< Available item name. */
int entryLen; /*!< No. of bytes in name. */
int entryIx; /*!< Item index. */
enum indexEntryType {
IET_PROVIDES=1 /*!< A Provides: dependency. */
} type; /*!< Type of available item. */
} ;
/** \ingroup rpmdep
* Index of all available items.
*/
struct availableIndex {
int size; /*!< No. of available items. */
struct availableIndexEntry index[1]; /*!< Array of available items. */
} ;
/**
* Compare two available index entries by name (qsort/bsearch).
* @param one 1st available index entry
* @param two 2nd available index entry
* @return result of comparison
*/
static int indexcmp(const void * one, const void * two) /*@*/
{
const struct availableIndexEntry * a = one;
const struct availableIndexEntry * b = two;
int lenchk = a->entryLen - b->entryLen;
if (lenchk)
return lenchk;
return strcmp(a->entry, b->entry);
}
void alMakeIndex(availableList al)
{
if (al->index) // got an index
return;
int i, j, k;
int ai_size = 0;
for (i = 0; i < al->size; i++)
ai_size += al->list[i].providesCount;
if (ai_size == 0)
return;
struct availableIndex *ai = al->index =
xmalloc(sizeof(*ai) + sizeof(*ai->index) * (ai_size - 1));
ai->size = ai_size;
k = 0;
for (i = 0; i < al->size; i++) {
for (j = 0; j < al->list[i].providesCount; j++) {
ai->index[k].package = al->list + i;
ai->index[k].entry = al->list[i].provides[j];
ai->index[k].entryLen = strlen(al->list[i].provides[j]);
ai->index[k].entryIx = j;
ai->index[k].type = IET_PROVIDES;
k++;
}
}
qsort(ai->index, ai->size, sizeof(*ai->index), indexcmp);
}
/**
* Destroy available item index.
* @param al available list
*/
static void alFreeIndex(availableList al)
/*@modifies al @*/
{
al->index = _free(al->index);
}
/**
* Compare two directory info entries by name (qsort/bsearch).
* @param one 1st directory info
* @param two 2nd directory info
* @return result of comparison
*/
static int dirInfoCompare(const void * one, const void * two) /*@*/
{
const dirInfo a = (const dirInfo) one;
const dirInfo b = (const dirInfo) two;
int lenchk = a->dirNameLen - b->dirNameLen;
if (lenchk)
return lenchk;
/* XXX FIXME: this might do "backward" strcmp for speed */
return strcmp(a->dirName, b->dirName);
}
/**
* Check added package file lists for package(s) that provide a file.
* @param al available list
* @param keyType type of dependency
* @param fileName file name to search for
* @return available package pointer
*/
static /*@only@*/ /*@null@*/ struct availablePackage **
alAllFileSatisfiesDepend(const availableList al,
const char * keyType, const char * fileName)
/*@*/
{
int i, found;
const char * dirName;
const char * baseName;
struct dirInfo_s dirNeedle;
dirInfo dirMatch;
struct availablePackage ** ret;
/* Solaris 2.6 bsearch sucks down on this. */
if (al->numDirs == 0 || al->dirs == NULL || al->list == NULL)
return NULL;
{ char * t;
dirName = t = xstrdup(fileName);
if ((t = strrchr(t, '/')) != NULL) {
t++; /* leave the trailing '/' */
*t = '\0';
}
}
dirNeedle.dirName = (char *) dirName;
dirNeedle.dirNameLen = strlen(dirName);
dirMatch = bsearch(&dirNeedle, al->dirs, al->numDirs,
sizeof(dirNeedle), dirInfoCompare);
if (dirMatch == NULL) {
dirName = _free(dirName);
return NULL;
}
/* rewind to the first match */
while (dirMatch > al->dirs && dirInfoCompare(dirMatch-1, &dirNeedle) == 0)
dirMatch--;
/*@-nullptrarith@*/ /* FIX: fileName NULL ??? */
baseName = strrchr(fileName, '/') + 1;
/*@=nullptrarith@*/
for (found = 0, ret = NULL;
dirMatch <= al->dirs + al->numDirs &&
dirInfoCompare(dirMatch, &dirNeedle) == 0;
dirMatch++)
{
/* XXX FIXME: these file lists should be sorted and bsearched */
for (i = 0; i < dirMatch->numFiles; i++) {
if (dirMatch->files[i].baseName == NULL ||
strcmp(dirMatch->files[i].baseName, baseName))
continue;
if (keyType)
rpmMessage(RPMMESS_DEBUG, _("%s: %-45s YES (added files)\n"),
keyType, fileName);
ret = xrealloc(ret, (found+2) * sizeof(*ret));
if (ret) /* can't happen */
ret[found++] = al->list + dirMatch->files[i].pkgNum;
/*@innerbreak@*/ break;
}
}
dirName = _free(dirName);
/*@-mods@*/ /* FIX: al->list might be modified. */
if (ret)
ret[found] = NULL;
/*@=mods@*/
return ret;
}
struct availablePackage **
alAllSatisfiesDepend(const availableList al,
const char * keyType, const char * keyDepend,
const char * keyName, const char * keyEVR, int keyFlags)
{
struct availablePackage * p, ** ret = NULL;
int i, rc, found;
if (*keyName == '/') {
ret = alAllFileSatisfiesDepend(al, keyType, keyName);
/* XXX Provides: /path was broken with added packages (#52183). */
if (ret != NULL && *ret != NULL)
return ret;
}
const struct availableIndex *ai = al->index;
if (ai == NULL)
return NULL;
struct availableIndexEntry needle, * match;
needle.entry = keyName;
needle.entryLen = strlen(keyName);
match = bsearch(&needle, ai->index, ai->size, sizeof(*ai->index), indexcmp);
if (match == NULL)
return NULL;
/* rewind to the first match */
while (match > ai->index && indexcmp(match-1, &needle) == 0)
match--;
for (ret = NULL, found = 0;
match < ai->index + ai->size &&
indexcmp(match, &needle) == 0;
match++)
{
p = match->package;
rc = 0;
switch (match->type) {
case IET_PROVIDES:
i = match->entryIx;
{ const char * proEVR;
int proFlags;
proEVR = (p->providesEVR ? p->providesEVR[i] : NULL);
proFlags = (p->provideFlags ? p->provideFlags[i] : 0);
if ((keyFlags & RPMSENSE_SENSEMASK) && !(proFlags & RPMSENSE_SENSEMASK))
proFlags |= RPMSENSE_EQUAL;
rc = rpmRangesOverlap(p->provides[i], proEVR, proFlags,
keyName, keyEVR, keyFlags);
if (rc)
/*@switchbreak@*/ break;
}
if (keyType && keyDepend && rc)
rpmMessage(RPMMESS_DEBUG, _("%s: %-45s YES (added provide)\n"),
keyType, keyDepend+2);
break;
}
if (rc) {
ret = xrealloc(ret, (found + 2) * sizeof(*ret));
if (ret) /* can't happen */
ret[found++] = p;
}
}
if (ret)
ret[found] = NULL;
return ret;
}
struct availablePackage *
alAddPackage(availableList al,
Header h, /*@null@*/ /*@dependent@*/ const void * key,
/*@null@*/ FD_t fd, /*@null@*/ rpmRelocation * relocs)
{
HGE_t hge = (HGE_t)headerGetEntryMinMemory;
HFD_t hfd = headerFreeData;
rpmTagType dnt, bnt;
struct availablePackage * p;
rpmRelocation * r;
int i;
int_32 * dirIndexes;
const char ** dirNames;
int numDirs, dirNum;
int * dirMapping;
struct dirInfo_s dirNeedle;
dirInfo dirMatch;
int first, last, fileNum;
int origNumDirs;
int pkgNum;
AUTO_REALLOC(al->list, al->size);
pkgNum = al->size++;
p = al->list + pkgNum;
p->h = headerLink(h); /* XXX reference held by transaction set */
p->depth = p->npreds = 0;
memset(&p->tsi, 0, sizeof(p->tsi));
(void) headerNVR(p->h, &p->name, &p->version, &p->release);
if (!hge(h, RPMTAG_EPOCH, NULL, (void **) &p->epoch, NULL))
p->epoch = NULL;
if (!hge(h, RPMTAG_BUILDTIME, NULL, (void **) &p->buildtime, NULL))
p->buildtime = NULL;
if (!hge(h, RPMTAG_PROVIDENAME, NULL, (void **) &p->provides,
&p->providesCount)) {
p->providesCount = 0;
p->provides = NULL;
p->providesEVR = NULL;
p->provideFlags = NULL;
} else {
if (!hge(h, RPMTAG_PROVIDEVERSION,
NULL, (void **) &p->providesEVR, NULL))
p->providesEVR = NULL;
if (!hge(h, RPMTAG_PROVIDEFLAGS,
NULL, (void **) &p->provideFlags, NULL))
p->provideFlags = NULL;
}
if (!hge(h, RPMTAG_REQUIRENAME, NULL, (void **) &p->requires,
&p->requiresCount)) {
p->requiresCount = 0;
p->requires = NULL;
p->requiresEVR = NULL;
p->requireFlags = NULL;
} else {
if (!hge(h, RPMTAG_REQUIREVERSION,
NULL, (void **) &p->requiresEVR, NULL))
p->requiresEVR = NULL;
if (!hge(h, RPMTAG_REQUIREFLAGS,
NULL, (void **) &p->requireFlags, NULL))
p->requireFlags = NULL;
}
if (!hge(h, RPMTAG_BASENAMES, &bnt, (void **)&p->baseNames, &p->filesCount))
{
p->filesCount = 0;
p->baseNames = NULL;
} else {
(void) hge(h, RPMTAG_DIRNAMES, &dnt, (void **) &dirNames, &numDirs);
(void) hge(h, RPMTAG_DIRINDEXES, NULL, (void **) &dirIndexes, NULL);
/* XXX FIXME: We ought to relocate the directory list here */
dirMapping = alloca(sizeof(*dirMapping) * numDirs);
/* allocated enough space for all the directories we could possible
need to add */
al->dirs = xrealloc(al->dirs,
sizeof(*al->dirs) * (al->numDirs + numDirs));
origNumDirs = al->numDirs;
for (dirNum = 0; dirNum < numDirs; dirNum++) {
dirNeedle.dirName = (char *) dirNames[dirNum];
dirNeedle.dirNameLen = strlen(dirNames[dirNum]);
dirMatch = bsearch(&dirNeedle, al->dirs, origNumDirs,
sizeof(dirNeedle), dirInfoCompare);
if (dirMatch) {
dirMapping[dirNum] = dirMatch - al->dirs;
} else {
dirMapping[dirNum] = al->numDirs;
al->dirs[al->numDirs].dirName = xstrdup(dirNames[dirNum]);
al->dirs[al->numDirs].dirNameLen = strlen(dirNames[dirNum]);
al->dirs[al->numDirs].files = NULL;
al->dirs[al->numDirs].numFiles = 0;
al->numDirs++;
}
}
dirNames = hfd(dirNames, dnt);
first = 0;
while (first < p->filesCount) {
last = first;
while ((last + 1) < p->filesCount) {
if (dirIndexes[first] != dirIndexes[last + 1])
/*@innerbreak@*/ break;
last++;
}
dirMatch = al->dirs + dirMapping[dirIndexes[first]];
dirMatch->files = xrealloc(dirMatch->files,
sizeof(*dirMatch->files) *
(dirMatch->numFiles + last - first + 1));
if (p->baseNames != NULL) /* XXX can't happen */
for (fileNum = first; fileNum <= last; fileNum++) {
dirMatch->files[dirMatch->numFiles].baseName =
p->baseNames[fileNum];
dirMatch->files[dirMatch->numFiles].pkgNum = pkgNum;
dirMatch->numFiles++;
}
first = last + 1;
}
if (origNumDirs + al->numDirs)
qsort(al->dirs, al->numDirs, sizeof(dirNeedle), dirInfoCompare);
}
p->key = key;
p->fd = (fd != NULL ? fdLink(fd, "alAddPackage") : NULL);
if (relocs) {
for (i = 0, r = relocs; r->oldPath || r->newPath; i++, r++)
{};
p->relocs = xmalloc((i + 1) * sizeof(*p->relocs));
for (i = 0, r = relocs; r->oldPath || r->newPath; i++, r++) {
p->relocs[i].oldPath = r->oldPath ? xstrdup(r->oldPath) : NULL;
p->relocs[i].newPath = r->newPath ? xstrdup(r->newPath) : NULL;
}
p->relocs[i].oldPath = NULL;
p->relocs[i].newPath = NULL;
} else {
p->relocs = NULL;
}
alFreeIndex(al);
return p;
}
void alFree(availableList al)
{
HFD_t hfd = headerFreeData;
struct availablePackage * p;
rpmRelocation * r;
int i;
if ((p = al->list) != NULL)
for (i = 0; i < al->size; i++, p++) {
{ tsortInfo tsi;
while ((tsi = p->tsi.tsi_next) != NULL) {
p->tsi.tsi_next = tsi->tsi_next;
tsi->tsi_next = NULL;
tsi = _free(tsi);
}
}
p->provides = hfd(p->provides, -1);
p->providesEVR = hfd(p->providesEVR, -1);
p->requires = hfd(p->requires, -1);
p->requiresEVR = hfd(p->requiresEVR, -1);
p->baseNames = hfd(p->baseNames, -1);
p->h = headerFree(p->h);
if (p->relocs) {
for (r = p->relocs; (r->oldPath || r->newPath); r++) {
r->oldPath = _free(r->oldPath);
r->newPath = _free(r->newPath);
}
p->relocs = _free(p->relocs);
}
if (p->fd != NULL)
p->fd = fdFree(p->fd, "alAddPackage (alFree)");
}
if (al->dirs != NULL)
for (i = 0; i < al->numDirs; i++) {
al->dirs[i].dirName = _free(al->dirs[i].dirName);
al->dirs[i].files = _free(al->dirs[i].files);
}
al->dirs = _free(al->dirs);
al->numDirs = 0;
al->list = _free(al->list);
alFreeIndex(al);
}

93
lib/al.h Normal file
View File

@ -0,0 +1,93 @@
#ifndef RPM_AL_H
#define RPM_AL_H
/**
* Initialize available packckages, items, and directories list.
* @param al available list
*/
static inline
void alCreate(availableList al)
/*@modifies al @*/
{
al->list = NULL;
al->size = 0;
al->dirs = NULL;
al->numDirs = 0;
al->index = NULL;
}
/**
* Free available packages, items, and directories members.
* @param al available list
*/
void alFree(availableList al)
/*@modifies al @*/;
/**
* Add package to available list.
* @param al available list
* @param h package header
* @param key package private data
* @param fd package file handle
* @param relocs package file relocations
* @return available package pointer
*/
/*@exposed@*/ struct availablePackage *
alAddPackage(availableList al,
Header h, /*@null@*/ /*@dependent@*/ const void * key,
/*@null@*/ FD_t fd, /*@null@*/ rpmRelocation * relocs)
/*@modifies al, h @*/;
/**
* Generate index for available list.
* @param al available list
*/
void alMakeIndex(availableList al)
/*@modifies al @*/;
/**
* Check added package file lists for package(s) that have a provide.
* @param al available list
* @param keyType type of dependency
* @param keyDepend dependency string representation
* @param keyName dependency name string
* @param keyEVR dependency [epoch:]version[-release] string
* @param keyFlags dependency logical range qualifiers
* @return available package pointer
*/
/*@only@*/ /*@null@*/ struct availablePackage **
alAllSatisfiesDepend(const availableList al,
const char * keyType, const char * keyDepend,
const char * keyName, const char * keyEVR, int keyFlags)
/*@*/;
/**
* Check added package file lists for first package that has a provide.
* @todo Eliminate.
* @param al available list
* @param keyType type of dependency
* @param keyDepend dependency string representation
* @param keyName dependency name string
* @param keyEVR dependency [epoch:]version[-release] string
* @param keyFlags dependency logical range qualifiers
* @return available package pointer
*/
static inline /*@only@*/ /*@null@*/ struct availablePackage *
alSatisfiesDepend(const availableList al,
const char * keyType, const char * keyDepend,
const char * keyName, const char * keyEVR, int keyFlags)
/*@*/
{
struct availablePackage * ret;
struct availablePackage ** tmp =
alAllSatisfiesDepend(al, keyType, keyDepend, keyName, keyEVR, keyFlags);
if (tmp) {
ret = tmp[0];
tmp = _free(tmp);
return ret;
}
return NULL;
}
#endif

View File

@ -8,6 +8,7 @@
#include "rpmmacro.h" /* XXX for rpmExpand() */
#include "depends.h"
#include "al.h"
#include "rpmdb.h" /* XXX response cache needs dbiOpen et al. */
#include "debug.h"
@ -97,321 +98,6 @@ struct orderListIndex {
int orIndex;
};
/**
* Destroy available item index.
* @param al available list
*/
static void alFreeIndex(availableList al)
/*@modifies al @*/
{
al->index = _free(al->index);
}
/**
* Initialize available packckages, items, and directories list.
* @param al available list
*/
static void alCreate(availableList al)
/*@modifies al @*/
{
al->list = NULL;
al->size = 0;
al->dirs = NULL;
al->numDirs = 0;
al->index = NULL;
}
/**
* Free available packages, items, and directories members.
* @param al available list
*/
static void alFree(availableList al)
/*@modifies al @*/
{
HFD_t hfd = headerFreeData;
struct availablePackage * p;
rpmRelocation * r;
int i;
if ((p = al->list) != NULL)
for (i = 0; i < al->size; i++, p++) {
{ tsortInfo tsi;
while ((tsi = p->tsi.tsi_next) != NULL) {
p->tsi.tsi_next = tsi->tsi_next;
tsi->tsi_next = NULL;
tsi = _free(tsi);
}
}
p->provides = hfd(p->provides, -1);
p->providesEVR = hfd(p->providesEVR, -1);
p->requires = hfd(p->requires, -1);
p->requiresEVR = hfd(p->requiresEVR, -1);
p->baseNames = hfd(p->baseNames, -1);
p->h = headerFree(p->h);
if (p->relocs) {
for (r = p->relocs; (r->oldPath || r->newPath); r++) {
r->oldPath = _free(r->oldPath);
r->newPath = _free(r->newPath);
}
p->relocs = _free(p->relocs);
}
if (p->fd != NULL)
p->fd = fdFree(p->fd, "alAddPackage (alFree)");
}
if (al->dirs != NULL)
for (i = 0; i < al->numDirs; i++) {
al->dirs[i].dirName = _free(al->dirs[i].dirName);
al->dirs[i].files = _free(al->dirs[i].files);
}
al->dirs = _free(al->dirs);
al->numDirs = 0;
al->list = _free(al->list);
alFreeIndex(al);
}
/**
* Compare two directory info entries by name (qsort/bsearch).
* @param one 1st directory info
* @param two 2nd directory info
* @return result of comparison
*/
static int dirInfoCompare(const void * one, const void * two) /*@*/
{
const dirInfo a = (const dirInfo) one;
const dirInfo b = (const dirInfo) two;
int lenchk = a->dirNameLen - b->dirNameLen;
if (lenchk)
return lenchk;
/* XXX FIXME: this might do "backward" strcmp for speed */
return strcmp(a->dirName, b->dirName);
}
/**
* Add package to available list.
* @param al available list
* @param h package header
* @param key package private data
* @param fd package file handle
* @param relocs package file relocations
* @return available package pointer
*/
static /*@exposed@*/ struct availablePackage *
alAddPackage(availableList al,
Header h, /*@null@*/ /*@dependent@*/ const void * key,
/*@null@*/ FD_t fd, /*@null@*/ rpmRelocation * relocs)
/*@modifies al, h @*/
{
HGE_t hge = (HGE_t)headerGetEntryMinMemory;
HFD_t hfd = headerFreeData;
rpmTagType dnt, bnt;
struct availablePackage * p;
rpmRelocation * r;
int i;
int_32 * dirIndexes;
const char ** dirNames;
int numDirs, dirNum;
int * dirMapping;
struct dirInfo_s dirNeedle;
dirInfo dirMatch;
int first, last, fileNum;
int origNumDirs;
int pkgNum;
AUTO_REALLOC(al->list, al->size);
pkgNum = al->size++;
p = al->list + pkgNum;
p->h = headerLink(h); /* XXX reference held by transaction set */
p->depth = p->npreds = 0;
memset(&p->tsi, 0, sizeof(p->tsi));
(void) headerNVR(p->h, &p->name, &p->version, &p->release);
if (!hge(h, RPMTAG_EPOCH, NULL, (void **) &p->epoch, NULL))
p->epoch = NULL;
if (!hge(h, RPMTAG_BUILDTIME, NULL, (void **) &p->buildtime, NULL))
p->buildtime = NULL;
if (!hge(h, RPMTAG_PROVIDENAME, NULL, (void **) &p->provides,
&p->providesCount)) {
p->providesCount = 0;
p->provides = NULL;
p->providesEVR = NULL;
p->provideFlags = NULL;
} else {
if (!hge(h, RPMTAG_PROVIDEVERSION,
NULL, (void **) &p->providesEVR, NULL))
p->providesEVR = NULL;
if (!hge(h, RPMTAG_PROVIDEFLAGS,
NULL, (void **) &p->provideFlags, NULL))
p->provideFlags = NULL;
}
if (!hge(h, RPMTAG_REQUIRENAME, NULL, (void **) &p->requires,
&p->requiresCount)) {
p->requiresCount = 0;
p->requires = NULL;
p->requiresEVR = NULL;
p->requireFlags = NULL;
} else {
if (!hge(h, RPMTAG_REQUIREVERSION,
NULL, (void **) &p->requiresEVR, NULL))
p->requiresEVR = NULL;
if (!hge(h, RPMTAG_REQUIREFLAGS,
NULL, (void **) &p->requireFlags, NULL))
p->requireFlags = NULL;
}
if (!hge(h, RPMTAG_BASENAMES, &bnt, (void **)&p->baseNames, &p->filesCount))
{
p->filesCount = 0;
p->baseNames = NULL;
} else {
(void) hge(h, RPMTAG_DIRNAMES, &dnt, (void **) &dirNames, &numDirs);
(void) hge(h, RPMTAG_DIRINDEXES, NULL, (void **) &dirIndexes, NULL);
/* XXX FIXME: We ought to relocate the directory list here */
dirMapping = alloca(sizeof(*dirMapping) * numDirs);
/* allocated enough space for all the directories we could possible
need to add */
al->dirs = xrealloc(al->dirs,
sizeof(*al->dirs) * (al->numDirs + numDirs));
origNumDirs = al->numDirs;
for (dirNum = 0; dirNum < numDirs; dirNum++) {
dirNeedle.dirName = (char *) dirNames[dirNum];
dirNeedle.dirNameLen = strlen(dirNames[dirNum]);
dirMatch = bsearch(&dirNeedle, al->dirs, origNumDirs,
sizeof(dirNeedle), dirInfoCompare);
if (dirMatch) {
dirMapping[dirNum] = dirMatch - al->dirs;
} else {
dirMapping[dirNum] = al->numDirs;
al->dirs[al->numDirs].dirName = xstrdup(dirNames[dirNum]);
al->dirs[al->numDirs].dirNameLen = strlen(dirNames[dirNum]);
al->dirs[al->numDirs].files = NULL;
al->dirs[al->numDirs].numFiles = 0;
al->numDirs++;
}
}
dirNames = hfd(dirNames, dnt);
first = 0;
while (first < p->filesCount) {
last = first;
while ((last + 1) < p->filesCount) {
if (dirIndexes[first] != dirIndexes[last + 1])
/*@innerbreak@*/ break;
last++;
}
dirMatch = al->dirs + dirMapping[dirIndexes[first]];
dirMatch->files = xrealloc(dirMatch->files,
sizeof(*dirMatch->files) *
(dirMatch->numFiles + last - first + 1));
if (p->baseNames != NULL) /* XXX can't happen */
for (fileNum = first; fileNum <= last; fileNum++) {
dirMatch->files[dirMatch->numFiles].baseName =
p->baseNames[fileNum];
dirMatch->files[dirMatch->numFiles].pkgNum = pkgNum;
dirMatch->numFiles++;
}
first = last + 1;
}
if (origNumDirs + al->numDirs)
qsort(al->dirs, al->numDirs, sizeof(dirNeedle), dirInfoCompare);
}
p->key = key;
p->fd = (fd != NULL ? fdLink(fd, "alAddPackage") : NULL);
if (relocs) {
for (i = 0, r = relocs; r->oldPath || r->newPath; i++, r++)
{};
p->relocs = xmalloc((i + 1) * sizeof(*p->relocs));
for (i = 0, r = relocs; r->oldPath || r->newPath; i++, r++) {
p->relocs[i].oldPath = r->oldPath ? xstrdup(r->oldPath) : NULL;
p->relocs[i].newPath = r->newPath ? xstrdup(r->newPath) : NULL;
}
p->relocs[i].oldPath = NULL;
p->relocs[i].newPath = NULL;
} else {
p->relocs = NULL;
}
alFreeIndex(al);
return p;
}
/**
* Compare two available index entries by name (qsort/bsearch).
* @param one 1st available index entry
* @param two 2nd available index entry
* @return result of comparison
*/
static int indexcmp(const void * one, const void * two) /*@*/
{
const struct availableIndexEntry * a = one;
const struct availableIndexEntry * b = two;
int lenchk = a->entryLen - b->entryLen;
if (lenchk)
return lenchk;
return strcmp(a->entry, b->entry);
}
/**
* Generate index for available list.
* @param al available list
*/
static void alMakeIndex(availableList al)
/*@modifies al @*/
{
if (al->index) // got an index
return;
int i, j, k;
int ai_size = 0;
for (i = 0; i < al->size; i++)
ai_size += al->list[i].providesCount;
if (ai_size == 0)
return;
struct availableIndex *ai = al->index =
xmalloc(sizeof(*ai) + sizeof(*ai->index) * (ai_size - 1));
ai->size = ai_size;
k = 0;
for (i = 0; i < al->size; i++) {
for (j = 0; j < al->list[i].providesCount; j++) {
ai->index[k].package = al->list + i;
ai->index[k].entry = al->list[i].provides[j];
ai->index[k].entryLen = strlen(al->list[i].provides[j]);
ai->index[k].entryIx = j;
ai->index[k].type = IET_PROVIDES;
k++;
}
}
qsort(ai->index, ai->size, sizeof(*ai->index), indexcmp);
}
/* parseEVR() moved to rpmvercmp.c */
const char *rpmNAME = PACKAGE;
@ -806,222 +492,6 @@ rpmDependencyConflict rpmdepFreeConflicts(rpmDependencyConflict conflicts,
return (conflicts = _free(conflicts));
}
/**
* Check added package file lists for package(s) that provide a file.
* @param al available list
* @param keyType type of dependency
* @param fileName file name to search for
* @return available package pointer
*/
static /*@only@*/ /*@null@*/ struct availablePackage **
alAllFileSatisfiesDepend(const availableList al,
const char * keyType, const char * fileName)
/*@*/
{
int i, found;
const char * dirName;
const char * baseName;
struct dirInfo_s dirNeedle;
dirInfo dirMatch;
struct availablePackage ** ret;
/* Solaris 2.6 bsearch sucks down on this. */
if (al->numDirs == 0 || al->dirs == NULL || al->list == NULL)
return NULL;
{ char * t;
dirName = t = xstrdup(fileName);
if ((t = strrchr(t, '/')) != NULL) {
t++; /* leave the trailing '/' */
*t = '\0';
}
}
dirNeedle.dirName = (char *) dirName;
dirNeedle.dirNameLen = strlen(dirName);
dirMatch = bsearch(&dirNeedle, al->dirs, al->numDirs,
sizeof(dirNeedle), dirInfoCompare);
if (dirMatch == NULL) {
dirName = _free(dirName);
return NULL;
}
/* rewind to the first match */
while (dirMatch > al->dirs && dirInfoCompare(dirMatch-1, &dirNeedle) == 0)
dirMatch--;
/*@-nullptrarith@*/ /* FIX: fileName NULL ??? */
baseName = strrchr(fileName, '/') + 1;
/*@=nullptrarith@*/
for (found = 0, ret = NULL;
dirMatch <= al->dirs + al->numDirs &&
dirInfoCompare(dirMatch, &dirNeedle) == 0;
dirMatch++)
{
/* XXX FIXME: these file lists should be sorted and bsearched */
for (i = 0; i < dirMatch->numFiles; i++) {
if (dirMatch->files[i].baseName == NULL ||
strcmp(dirMatch->files[i].baseName, baseName))
continue;
if (keyType)
rpmMessage(RPMMESS_DEBUG, _("%s: %-45s YES (added files)\n"),
keyType, fileName);
ret = xrealloc(ret, (found+2) * sizeof(*ret));
if (ret) /* can't happen */
ret[found++] = al->list + dirMatch->files[i].pkgNum;
/*@innerbreak@*/ break;
}
}
dirName = _free(dirName);
/*@-mods@*/ /* FIX: al->list might be modified. */
if (ret)
ret[found] = NULL;
/*@=mods@*/
return ret;
}
#ifdef DYING
/**
* Check added package file lists for first package that provides a file.
* @param al available list
* @param keyType type of dependency
* @param fileName file name to search for
* @return available package pointer
*/
/*@unused@*/ static /*@dependent@*/ /*@null@*/ struct availablePackage *
alFileSatisfiesDepend(const availableList al,
const char * keyType, const char * fileName)
/*@*/
{
struct availablePackage * ret;
struct availablePackage ** tmp =
alAllFileSatisfiesDepend(al, keyType, fileName);
if (tmp) {
ret = tmp[0];
tmp = _free(tmp);
return ret;
}
return NULL;
}
#endif /* DYING */
/**
* Check added package file lists for package(s) that have a provide.
* @param al available list
* @param keyType type of dependency
* @param keyDepend dependency string representation
* @param keyName dependency name string
* @param keyEVR dependency [epoch:]version[-release] string
* @param keyFlags dependency logical range qualifiers
* @return available package pointer
*/
static /*@only@*/ /*@null@*/ struct availablePackage **
alAllSatisfiesDepend(const availableList al,
const char * keyType, const char * keyDepend,
const char * keyName, const char * keyEVR, int keyFlags)
/*@*/
{
struct availablePackage * p, ** ret = NULL;
int i, rc, found;
if (*keyName == '/') {
ret = alAllFileSatisfiesDepend(al, keyType, keyName);
/* XXX Provides: /path was broken with added packages (#52183). */
if (ret != NULL && *ret != NULL)
return ret;
}
const struct availableIndex *ai = al->index;
if (ai == NULL)
return NULL;
struct availableIndexEntry needle, * match;
needle.entry = keyName;
needle.entryLen = strlen(keyName);
match = bsearch(&needle, ai->index, ai->size, sizeof(*ai->index), indexcmp);
if (match == NULL)
return NULL;
/* rewind to the first match */
while (match > ai->index && indexcmp(match-1, &needle) == 0)
match--;
for (ret = NULL, found = 0;
match < ai->index + ai->size &&
indexcmp(match, &needle) == 0;
match++)
{
p = match->package;
rc = 0;
switch (match->type) {
case IET_PROVIDES:
i = match->entryIx;
{ const char * proEVR;
int proFlags;
proEVR = (p->providesEVR ? p->providesEVR[i] : NULL);
proFlags = (p->provideFlags ? p->provideFlags[i] : 0);
if ((keyFlags & RPMSENSE_SENSEMASK) && !(proFlags & RPMSENSE_SENSEMASK))
proFlags |= RPMSENSE_EQUAL;
rc = rpmRangesOverlap(p->provides[i], proEVR, proFlags,
keyName, keyEVR, keyFlags);
if (rc)
/*@switchbreak@*/ break;
}
if (keyType && keyDepend && rc)
rpmMessage(RPMMESS_DEBUG, _("%s: %-45s YES (added provide)\n"),
keyType, keyDepend+2);
break;
}
if (rc) {
ret = xrealloc(ret, (found + 2) * sizeof(*ret));
if (ret) /* can't happen */
ret[found++] = p;
}
}
if (ret)
ret[found] = NULL;
return ret;
}
/**
* Check added package file lists for first package that has a provide.
* @todo Eliminate.
* @param al available list
* @param keyType type of dependency
* @param keyDepend dependency string representation
* @param keyName dependency name string
* @param keyEVR dependency [epoch:]version[-release] string
* @param keyFlags dependency logical range qualifiers
* @return available package pointer
*/
static inline /*@only@*/ /*@null@*/ struct availablePackage *
alSatisfiesDepend(const availableList al,
const char * keyType, const char * keyDepend,
const char * keyName, const char * keyEVR, int keyFlags)
/*@*/
{
struct availablePackage * ret;
struct availablePackage ** tmp =
alAllSatisfiesDepend(al, keyType, keyDepend, keyName, keyEVR, keyFlags);
if (tmp) {
ret = tmp[0];
tmp = _free(tmp);
return ret;
}
return NULL;
}
/**
* Check key for an unsatisfied dependency.
* @todo Eliminate rpmrc provides.

View File

@ -63,27 +63,6 @@ struct availablePackage {
int_32 * buildtime;
} ;
/** \ingroup rpmdep
* A single available item (e.g. a Provides: dependency).
*/
struct availableIndexEntry {
/*@dependent@*/ struct availablePackage * package; /*!< Containing package. */
/*@dependent@*/ const char * entry; /*!< Available item name. */
int entryLen; /*!< No. of bytes in name. */
int entryIx; /*!< Item index. */
enum indexEntryType {
IET_PROVIDES=1 /*!< A Provides: dependency. */
} type; /*!< Type of available item. */
} ;
/** \ingroup rpmdep
* Index of all available items.
*/
struct availableIndex {
int size; /*!< No. of available items. */
struct availableIndexEntry index[1]; /*!< Array of available items. */
} ;
/** \ingroup rpmdep
* A file to be installed/removed.
*/