4.0.4-alt98.23
- depends.c: avoid expression dependent on evaluation order - depends.c: implemented automatic realloc - al.c: factored from depends.c - al.c: reimplemented alProvIndex and alDirIndex/alFileIndex routines
This commit is contained in:
commit
d5c7cd8f6c
@ -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 \
|
||||
|
465
lib/al.c
Normal file
465
lib/al.c
Normal file
@ -0,0 +1,465 @@
|
||||
#include "system.h"
|
||||
#include "rpmlib.h"
|
||||
#include "debug.h"
|
||||
|
||||
#include "depends.h"
|
||||
#include "al.h"
|
||||
|
||||
struct alEntry {
|
||||
const char *name;
|
||||
int len;
|
||||
/* entry-specific members */
|
||||
};
|
||||
|
||||
struct alIndex {
|
||||
int sorted;
|
||||
int size;
|
||||
/* flexible array of entries */
|
||||
};
|
||||
|
||||
/**
|
||||
* Compare two available index entries by name (qsort/bsearch).
|
||||
* @param one 1st available prov entry
|
||||
* @param two 2nd available prov entry
|
||||
* @return result of comparison
|
||||
*/
|
||||
static inline
|
||||
int nameCmp(const void * one, const void * two) /*@*/
|
||||
{
|
||||
const struct alEntry *a = one, *b = two;
|
||||
int lencmp = a->len - b->len;
|
||||
if (lencmp)
|
||||
return lencmp;
|
||||
return strcmp(a->name, b->name);
|
||||
}
|
||||
|
||||
static
|
||||
void *axSearch(void *index, int esize, const char *name, int *nfound)
|
||||
{
|
||||
if (nfound)
|
||||
*nfound = 0;
|
||||
|
||||
struct alIndex *ax = index;
|
||||
if (ax == NULL)
|
||||
return NULL;
|
||||
assert(ax->size > 0);
|
||||
|
||||
char *entries = (char *)(ax + 1);
|
||||
struct alEntry needle = { name, strlen(name) };
|
||||
if (ax->size == 1) {
|
||||
if (nameCmp(entries, &needle))
|
||||
return NULL;
|
||||
if (nfound)
|
||||
*nfound = 1;
|
||||
return entries;
|
||||
}
|
||||
if (!ax->sorted) {
|
||||
qsort(entries, ax->size, esize, nameCmp);
|
||||
ax->sorted = 1;
|
||||
}
|
||||
|
||||
char *first, *last;
|
||||
first = last = bsearch(&needle, entries, ax->size, esize, nameCmp);
|
||||
if (first == NULL)
|
||||
return NULL;
|
||||
|
||||
if (nfound) {
|
||||
*nfound = 1;
|
||||
|
||||
/* rewind to the first match */
|
||||
while (first > entries) {
|
||||
if (nameCmp(first - esize, &needle))
|
||||
break;
|
||||
first -= esize;
|
||||
(*nfound)++;
|
||||
}
|
||||
|
||||
/* rewind to the last match */
|
||||
while (last + esize < entries + esize * ax->size) {
|
||||
if (nameCmp(last + esize, &needle))
|
||||
break;
|
||||
last += esize;
|
||||
(*nfound)++;
|
||||
}
|
||||
}
|
||||
|
||||
return first;
|
||||
}
|
||||
|
||||
static
|
||||
void *axGrow(void *index, int esize, int more)
|
||||
{
|
||||
struct alIndex *ax = index;
|
||||
if (ax) {
|
||||
assert(ax->size > 0);
|
||||
ax = xrealloc(ax, sizeof(*ax) + esize * (ax->size + more));
|
||||
}
|
||||
else {
|
||||
ax = xmalloc(sizeof(*ax) + esize * more);
|
||||
ax->size = 0;
|
||||
}
|
||||
return ax;
|
||||
}
|
||||
|
||||
/** \ingroup rpmdep
|
||||
* A single available item (e.g. a Provides: dependency).
|
||||
*/
|
||||
struct alProvEntry {
|
||||
/*@dependent@*/ const char * name; /*!< Provides name. */
|
||||
int len; /*!< No. of bytes in name. */
|
||||
int pkgIx; /*!< Containing package index. */
|
||||
int provIx; /*!< Provides index in package. */
|
||||
} ;
|
||||
|
||||
/** \ingroup rpmdep
|
||||
* Index of all available items.
|
||||
*/
|
||||
struct alProvIndex {
|
||||
int sorted;
|
||||
int size; /*!< No. of available items. */
|
||||
struct alProvEntry prov[1]; /*!< Array of available items. */
|
||||
} ;
|
||||
|
||||
static
|
||||
void alIndexPkgProvides(availableList al, int pkgIx)
|
||||
{
|
||||
const struct availablePackage *alp = &al->list[pkgIx];
|
||||
if (alp->providesCount == 0)
|
||||
return;
|
||||
|
||||
struct alProvIndex *px = al->provIndex =
|
||||
axGrow(al->provIndex, sizeof(*px->prov), alp->providesCount);
|
||||
|
||||
int provIx;
|
||||
for (provIx = 0; provIx < alp->providesCount; provIx++) {
|
||||
struct alProvEntry *pe = &px->prov[px->size++];
|
||||
pe->name = alp->provides[provIx];
|
||||
pe->len = strlen(pe->name);
|
||||
pe->pkgIx = pkgIx;
|
||||
pe->provIx = provIx;
|
||||
}
|
||||
|
||||
px->sorted = 0;
|
||||
}
|
||||
|
||||
static
|
||||
struct alProvEntry *alSearchProv(availableList al, const char *name, int *n)
|
||||
{
|
||||
return axSearch(al->provIndex, sizeof(*al->provIndex->prov), name, n);
|
||||
}
|
||||
|
||||
static
|
||||
void alFreeProvIndex(availableList al)
|
||||
{
|
||||
al->provIndex = _free(al->provIndex);
|
||||
}
|
||||
|
||||
/** \ingroup rpmdep
|
||||
* A file to be installed/removed.
|
||||
*/
|
||||
struct alFileEntry {
|
||||
const char *basename; /*!< File basename. */
|
||||
int len; /*!< Basename length. */
|
||||
int pkgIx; /*!< Containing package number. */
|
||||
};
|
||||
|
||||
struct alFileIndex {
|
||||
int sorted;
|
||||
int size;
|
||||
struct alFileEntry files[1];
|
||||
};
|
||||
|
||||
/** \ingroup rpmdep
|
||||
* A directory which contains some files.
|
||||
*/
|
||||
struct alDirEntry {
|
||||
const char *dirname; /*!< Directory path (+ trailing '/'). */
|
||||
int len; /*!< No. bytes in directory path. */
|
||||
struct alFileIndex *fx; /*!< Files index this directory. */
|
||||
};
|
||||
|
||||
struct alDirIndex {
|
||||
int sorted;
|
||||
int size;
|
||||
struct alDirEntry dirs[1];
|
||||
};
|
||||
|
||||
static
|
||||
void alIndexPkgFiles(availableList al, int pkgIx)
|
||||
{
|
||||
const struct availablePackage *alp = &al->list[pkgIx];
|
||||
if (alp->filesCount == 0)
|
||||
return;
|
||||
|
||||
const HGE_t hge = (HGE_t)headerGetEntryMinMemory;
|
||||
const HFD_t hfd = headerFreeData;
|
||||
const char **bn = NULL, **dn = NULL;
|
||||
const int *di = NULL;
|
||||
rpmTagType bnt = 0, dnt = 0, dit = 0;
|
||||
int bnc = 0, dnc = 0, dic = 0;
|
||||
if (!hge(alp->h, RPMTAG_BASENAMES, &bnt, (void**)&bn, &bnc))
|
||||
goto exit;
|
||||
if (!hge(alp->h, RPMTAG_DIRNAMES, &dnt, (void**)&dn, &dnc))
|
||||
goto exit;
|
||||
if (!hge(alp->h, RPMTAG_DIRINDEXES, &dit, (void**)&di, &dic))
|
||||
goto exit;
|
||||
if (bnc != dic)
|
||||
goto exit;
|
||||
|
||||
/* XXX FIXME: We ought to relocate the directory list here */
|
||||
|
||||
struct alDirIndex *dx = al->dirIndex =
|
||||
axGrow(al->dirIndex, sizeof(*dx->dirs), dnc);
|
||||
|
||||
int i = 0;
|
||||
while (i < bnc) {
|
||||
/* maybe a few files under the same dir */
|
||||
int j = i;
|
||||
while (j + 1 < bnc) {
|
||||
if (di[i] != di[j + 1])
|
||||
break;
|
||||
j++;
|
||||
}
|
||||
/* find or create dir entry */
|
||||
const char *d = dn[di[i]];
|
||||
struct alDirEntry *de = (dx->size == 0) ? NULL :
|
||||
axSearch(dx, sizeof(*dx->dirs), d, NULL);
|
||||
if (de == NULL) {
|
||||
de = &dx->dirs[dx->size++];
|
||||
de->dirname = d;
|
||||
de->len = strlen(d);
|
||||
de->fx = NULL;
|
||||
dx->sorted = 0;
|
||||
}
|
||||
struct alFileIndex *fx = de->fx =
|
||||
axGrow(de->fx, sizeof(*fx->files), j - i + 1);
|
||||
while (i <= j) {
|
||||
/* add file entries */
|
||||
const char *b = bn[i++];
|
||||
struct alFileEntry *fe = &fx->files[fx->size++];
|
||||
fe->basename = b;
|
||||
fe->len = strlen(b);
|
||||
fe->pkgIx = pkgIx;
|
||||
}
|
||||
fx->sorted = 0;
|
||||
}
|
||||
|
||||
exit:
|
||||
/* XXX strings point to header memory */
|
||||
bn = hfd(bn, bnt);
|
||||
dn = hfd(dn, dnt);
|
||||
di = hfd(di, dit);
|
||||
}
|
||||
|
||||
static
|
||||
struct alFileEntry *alSearchFile(availableList al, const char *fname, int *n)
|
||||
{
|
||||
/* need to preserve trailing slahs in d */
|
||||
const char *b = strrchr(fname, '/') + 1;
|
||||
int dlen = b - fname;
|
||||
char *d = alloca(dlen + 1);
|
||||
memcpy(d, fname, dlen);
|
||||
d[dlen] = '\0';
|
||||
|
||||
struct alDirEntry *de = axSearch(al->dirIndex, sizeof(*de), d, NULL);
|
||||
if (de == NULL) {
|
||||
*n = 0;
|
||||
return NULL;
|
||||
}
|
||||
assert(de->fx);
|
||||
return axSearch(de->fx, sizeof(*de->fx->files), b, n);
|
||||
}
|
||||
|
||||
static
|
||||
void alFreeDirIndex(availableList al)
|
||||
{
|
||||
struct alDirIndex *dx = al->dirIndex;
|
||||
if (dx) {
|
||||
int i;
|
||||
for (i = 0; i < dx->size; i++) {
|
||||
struct alDirEntry *de = &dx->dirs[i];
|
||||
de->fx = _free(de->fx);
|
||||
}
|
||||
al->dirIndex = _free(al->dirIndex);
|
||||
}
|
||||
}
|
||||
|
||||
struct availablePackage **
|
||||
alAllSatisfiesDepend(const availableList al,
|
||||
const char * keyName, const char * keyEVR, int keyFlags)
|
||||
{
|
||||
struct availablePackage ** ret = NULL;
|
||||
int found = 0;
|
||||
int i, n;
|
||||
|
||||
if (*keyName == '/' && (keyFlags & RPMSENSE_SENSEMASK) == 0) {
|
||||
const struct alFileEntry *fe = alSearchFile(al, keyName, &n);
|
||||
for (i = 0; fe && i < n; i++, fe++) {
|
||||
struct availablePackage *alp = &al->list[fe->pkgIx];
|
||||
int j, already = 0;
|
||||
for (j = 0; j < found; j++)
|
||||
if (ret[j] == alp) {
|
||||
already = 1;
|
||||
break;
|
||||
}
|
||||
if (already)
|
||||
continue;
|
||||
ret = xrealloc(ret, (found + 2) * sizeof(*ret));
|
||||
ret[found++] = alp;
|
||||
}
|
||||
}
|
||||
|
||||
const struct alProvEntry *pe = alSearchProv(al, keyName, &n);
|
||||
for (i = 0; pe && i < n; i++, pe++) {
|
||||
struct availablePackage *alp = &al->list[pe->pkgIx];
|
||||
int j, already = 0;
|
||||
for (j = 0; j < found; j++)
|
||||
if (ret[j] == alp) {
|
||||
already = 1;
|
||||
break;
|
||||
}
|
||||
if (already)
|
||||
continue;
|
||||
if ((keyFlags & RPMSENSE_SENSEMASK)) {
|
||||
const char *provName = pe->name;
|
||||
const char *provEVR = alp->providesEVR ?
|
||||
alp->providesEVR[pe->provIx] : NULL;
|
||||
int provFlags = alp->provideFlags ?
|
||||
alp->provideFlags[pe->provIx] : 0;
|
||||
if (!(provFlags & RPMSENSE_SENSEMASK))
|
||||
provFlags |= RPMSENSE_EQUAL; /* ALT21-139-g6cb9a9a */
|
||||
int rc = rpmRangesOverlap(provName, provEVR, provFlags,
|
||||
keyName, keyEVR, keyFlags);
|
||||
if (rc == 0)
|
||||
continue;
|
||||
}
|
||||
ret = xrealloc(ret, (found + 2) * sizeof(*ret));
|
||||
ret[found++] = alp;
|
||||
}
|
||||
|
||||
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;
|
||||
struct availablePackage * p;
|
||||
rpmRelocation * r;
|
||||
int i;
|
||||
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, NULL, NULL, &p->filesCount))
|
||||
p->filesCount = 0;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
alIndexPkgProvides(al, pkgNum);
|
||||
alIndexPkgFiles(al, pkgNum);
|
||||
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->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)");
|
||||
}
|
||||
|
||||
al->list = _free(al->list);
|
||||
alFreeProvIndex(al);
|
||||
alFreeDirIndex(al);
|
||||
}
|
79
lib/al.h
Normal file
79
lib/al.h
Normal file
@ -0,0 +1,79 @@
|
||||
#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->dirIndex = NULL;
|
||||
al->provIndex = 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 @*/;
|
||||
|
||||
/**
|
||||
* Check added package file lists for package(s) that have a provide.
|
||||
* @param al available list
|
||||
* @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 * 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 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 * keyName, const char * keyEVR, int keyFlags)
|
||||
/*@*/
|
||||
{
|
||||
struct availablePackage * ret;
|
||||
struct availablePackage ** tmp =
|
||||
alAllSatisfiesDepend(al, keyName, keyEVR, keyFlags);
|
||||
|
||||
if (tmp) {
|
||||
ret = tmp[0];
|
||||
tmp = _free(tmp);
|
||||
return ret;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
613
lib/depends.c
613
lib/depends.c
@ -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,331 +98,6 @@ struct orderListIndex {
|
||||
int orIndex;
|
||||
};
|
||||
|
||||
/**
|
||||
* Destroy available item index.
|
||||
* @param al available list
|
||||
*/
|
||||
static void alFreeIndex(availableList al)
|
||||
/*@modifies al @*/
|
||||
{
|
||||
if (al->index.size) {
|
||||
al->index.index = _free(al->index.index);
|
||||
al->index.size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize available packckages, items, and directories list.
|
||||
* @param al available list
|
||||
*/
|
||||
static void alCreate(availableList al)
|
||||
/*@modifies al @*/
|
||||
{
|
||||
al->alloced = al->delta;
|
||||
al->size = 0;
|
||||
al->list = xcalloc(al->alloced, sizeof(*al->list));
|
||||
|
||||
al->index.index = NULL;
|
||||
al->index.size = 0;
|
||||
|
||||
al->numDirs = 0;
|
||||
al->dirs = 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);
|
||||
al->alloced = 0;
|
||||
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;
|
||||
|
||||
if (al->size == al->alloced) {
|
||||
al->alloced += al->delta;
|
||||
al->list = xrealloc(al->list, sizeof(*al->list) * al->alloced);
|
||||
}
|
||||
|
||||
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 @*/
|
||||
{
|
||||
struct availableIndex * ai = &al->index;
|
||||
int i, j, k;
|
||||
|
||||
if (ai->size || al->list == NULL) return;
|
||||
|
||||
for (i = 0; i < al->size; i++)
|
||||
ai->size += al->list[i].providesCount;
|
||||
|
||||
if (ai->size) {
|
||||
ai->index = xcalloc(ai->size, sizeof(*ai->index));
|
||||
|
||||
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;
|
||||
@ -536,7 +212,7 @@ static int rangeMatchesDepFlags (Header h,
|
||||
continue;
|
||||
|
||||
if (!(provideFlags[i] & RPMSENSE_SENSEMASK))
|
||||
provideFlags[i] |= RPMSENSE_EQUAL;
|
||||
provideFlags[i] |= RPMSENSE_EQUAL; /* ALT21-139-g6cb9a9a */
|
||||
result = rpmRangesOverlap(provides[i], providesEVR[i], provideFlags[i],
|
||||
reqName, reqEVR, reqFlags);
|
||||
|
||||
@ -595,12 +271,9 @@ rpmTransactionSet rpmtransCreateSet(rpmdb rpmdb, const char * rootDir)
|
||||
/*@=assignexpose@*/
|
||||
ts->scriptFd = NULL;
|
||||
ts->id = 0;
|
||||
ts->delta = 5;
|
||||
|
||||
ts->numRemovedPackages = 0;
|
||||
ts->allocedRemovedPackages = ts->delta;
|
||||
ts->removedPackages = xcalloc(ts->allocedRemovedPackages,
|
||||
sizeof(*ts->removedPackages));
|
||||
ts->removedPackages = NULL;
|
||||
|
||||
/* This canonicalizes the root */
|
||||
rootLen = strlen(rootDir);
|
||||
@ -617,12 +290,10 @@ rpmTransactionSet rpmtransCreateSet(rpmdb rpmdb, const char * rootDir)
|
||||
ts->currDir = NULL;
|
||||
ts->chrootDone = 0;
|
||||
|
||||
ts->addedPackages.delta = ts->delta;
|
||||
alCreate(&ts->addedPackages);
|
||||
|
||||
ts->orderAlloced = ts->delta;
|
||||
ts->orderCount = 0;
|
||||
ts->order = xcalloc(ts->orderAlloced, sizeof(*ts->order));
|
||||
ts->order = NULL;
|
||||
|
||||
return ts;
|
||||
}
|
||||
@ -659,22 +330,11 @@ static int removePackage(rpmTransactionSet ts, int dboffset, int depends)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ts->numRemovedPackages == ts->allocedRemovedPackages) {
|
||||
ts->allocedRemovedPackages += ts->delta;
|
||||
ts->removedPackages = xrealloc(ts->removedPackages,
|
||||
sizeof(int *) * ts->allocedRemovedPackages);
|
||||
}
|
||||
|
||||
if (ts->removedPackages != NULL) { /* XXX can't happen. */
|
||||
ts->removedPackages[ts->numRemovedPackages++] = dboffset;
|
||||
qsort(ts->removedPackages, ts->numRemovedPackages, sizeof(int), intcmp);
|
||||
}
|
||||
|
||||
if (ts->orderCount == ts->orderAlloced) {
|
||||
ts->orderAlloced += ts->delta;
|
||||
ts->order = xrealloc(ts->order, sizeof(*ts->order) * ts->orderAlloced);
|
||||
}
|
||||
AUTO_REALLOC(ts->removedPackages, ts->numRemovedPackages);
|
||||
ts->removedPackages[ts->numRemovedPackages++] = dboffset;
|
||||
qsort(ts->removedPackages, ts->numRemovedPackages, sizeof(int), intcmp);
|
||||
|
||||
AUTO_REALLOC(ts->order, ts->orderCount);
|
||||
ts->order[ts->orderCount].type = TR_REMOVED;
|
||||
ts->order[ts->orderCount].u.removed.dboffset = dboffset;
|
||||
ts->order[ts->orderCount++].u.removed.dependsOnIndex = depends;
|
||||
@ -710,7 +370,6 @@ int rpmtransAddPackage(rpmTransactionSet ts, Header h, FD_t fd,
|
||||
const char * name;
|
||||
int count;
|
||||
const char ** obsoletes;
|
||||
int alNum;
|
||||
|
||||
/*
|
||||
* FIXME: handling upgrades like this is *almost* okay. It doesn't
|
||||
@ -718,16 +377,11 @@ int rpmtransAddPackage(rpmTransactionSet ts, Header h, FD_t fd,
|
||||
* makes it difficult to generate a return code based on the number of
|
||||
* packages which failed.
|
||||
*/
|
||||
if (ts->orderCount == ts->orderAlloced) {
|
||||
ts->orderAlloced += ts->delta;
|
||||
ts->order = xrealloc(ts->order, sizeof(*ts->order) * ts->orderAlloced);
|
||||
}
|
||||
struct availablePackage *alp =
|
||||
alAddPackage(&ts->addedPackages, h, key, fd, relocs);
|
||||
int alNum = alp - ts->addedPackages.list;
|
||||
AUTO_REALLOC(ts->order, ts->orderCount);
|
||||
ts->order[ts->orderCount].type = TR_ADDED;
|
||||
if (ts->addedPackages.list == NULL)
|
||||
return 0;
|
||||
|
||||
alNum = alAddPackage(&ts->addedPackages, h, key, fd, relocs) -
|
||||
ts->addedPackages.list;
|
||||
ts->order[ts->orderCount++].u.addedIndex = alNum;
|
||||
|
||||
if (!upgrade || ts->rpmdb == NULL)
|
||||
@ -838,221 +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 availableIndexEntry needle, * match;
|
||||
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;
|
||||
}
|
||||
|
||||
if (!al->index.size || al->index.index == NULL) return NULL;
|
||||
|
||||
needle.entry = keyName;
|
||||
needle.entryLen = strlen(keyName);
|
||||
match = bsearch(&needle, al->index.index, al->index.size,
|
||||
sizeof(*al->index.index), indexcmp);
|
||||
|
||||
if (match == NULL) return NULL;
|
||||
|
||||
/* rewind to the first match */
|
||||
while (match > al->index.index && indexcmp(match-1, &needle) == 0)
|
||||
match--;
|
||||
|
||||
for (ret = NULL, found = 0;
|
||||
match < al->index.index + al->index.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.
|
||||
@ -1142,9 +581,11 @@ static int unsatisfiedDepend(rpmTransactionSet ts,
|
||||
goto unsatisfied;
|
||||
}
|
||||
|
||||
if (alSatisfiesDepend(&ts->addedPackages, keyType, keyDepend,
|
||||
keyName, keyEVR, keyFlags))
|
||||
if (alSatisfiesDepend(&ts->addedPackages, keyName, keyEVR, keyFlags))
|
||||
{
|
||||
/* XXX here we do not discern between files and provides */
|
||||
rpmMessage(RPMMESS_DEBUG, _("%s: %-45s YES (added provide)\n"),
|
||||
keyType, keyDepend+2);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
@ -1286,11 +727,7 @@ static int checkPackageDeps(rpmTransactionSet ts, problemsSet psp,
|
||||
rpmMessage(RPMMESS_DEBUG, _("package %s-%s-%s require not satisfied: %s\n"),
|
||||
name, version, release, keyDepend+2);
|
||||
|
||||
if (psp->num == psp->alloced) {
|
||||
psp->alloced += 5;
|
||||
psp->problems = xrealloc(psp->problems, sizeof(*psp->problems) *
|
||||
psp->alloced);
|
||||
}
|
||||
AUTO_REALLOC(psp->problems, psp->num);
|
||||
|
||||
{ rpmDependencyConflict pp = psp->problems + psp->num;
|
||||
pp->byHeader = headerLink(h);
|
||||
@ -1347,11 +784,7 @@ static int checkPackageDeps(rpmTransactionSet ts, problemsSet psp,
|
||||
rpmMessage(RPMMESS_DEBUG, _("package %s conflicts: %s\n"),
|
||||
name, keyDepend+2);
|
||||
|
||||
if (psp->num == psp->alloced) {
|
||||
psp->alloced += 5;
|
||||
psp->problems = xrealloc(psp->problems,
|
||||
sizeof(*psp->problems) * psp->alloced);
|
||||
}
|
||||
AUTO_REALLOC(psp->problems, psp->num);
|
||||
|
||||
{ rpmDependencyConflict pp = psp->problems + psp->num;
|
||||
pp->byHeader = headerLink(h);
|
||||
@ -1667,7 +1100,7 @@ static inline int addRelation( const rpmTransactionSet ts,
|
||||
if (!p->requires || !p->requiresEVR || !p->requireFlags)
|
||||
return 0;
|
||||
|
||||
q = alSatisfiesDepend(&ts->addedPackages, NULL, NULL,
|
||||
q = alSatisfiesDepend(&ts->addedPackages,
|
||||
p->requires[j], p->requiresEVR[j], p->requireFlags[j]);
|
||||
|
||||
/* Ordering depends only on added package relations. */
|
||||
@ -1774,8 +1207,6 @@ int rpmdepOrder(rpmTransactionSet ts)
|
||||
int qlen;
|
||||
int i, j;
|
||||
|
||||
alMakeIndex(&ts->addedPackages);
|
||||
|
||||
/* T1. Initialize. */
|
||||
loopcheck = npkgs;
|
||||
|
||||
@ -2050,7 +1481,6 @@ rescan:
|
||||
|
||||
ts->order = _free(ts->order);
|
||||
ts->order = newOrder;
|
||||
ts->orderAlloced = ts->orderCount;
|
||||
orderList = _free(orderList);
|
||||
|
||||
return 0;
|
||||
@ -2103,15 +1533,12 @@ int rpmdepCheck(rpmTransactionSet ts,
|
||||
npkgs = ts->addedPackages.size;
|
||||
|
||||
ps = xcalloc(1, sizeof(*ps));
|
||||
ps->alloced = 5;
|
||||
ps->num = 0;
|
||||
ps->problems = xcalloc(ps->alloced, sizeof(*ps->problems));
|
||||
ps->problems = NULL;
|
||||
|
||||
*conflicts = NULL;
|
||||
*numConflicts = 0;
|
||||
|
||||
alMakeIndex(&ts->addedPackages);
|
||||
|
||||
/*
|
||||
* Look at all of the added packages and make sure their dependencies
|
||||
* are satisfied.
|
||||
|
@ -43,7 +43,6 @@ struct availablePackage {
|
||||
/*@owned@*//*@null@*/ const char ** requires; /*!< Requires: name strings. */
|
||||
/*@owned@*//*@null@*/ const char ** requiresEVR;/*!< Requires: [epoch:]version[-release] strings. */
|
||||
/*@dependent@*//*@null@*/ int * requireFlags; /*!< Requires: logical range qualifiers. */
|
||||
/*@owned@*//*@null@*/ const char ** baseNames; /*!< Header file basenames. */
|
||||
/*@dependent@*//*@null@*/ int_32 * epoch; /*!< Header epoch (if any). */
|
||||
int providesCount; /*!< No. of Provide:'s in header. */
|
||||
int requiresCount; /*!< No. of Require:'s in header. */
|
||||
@ -63,56 +62,14 @@ 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 {
|
||||
/*@null@*/ struct availableIndexEntry * index; /*!< Array of available items. */
|
||||
int size; /*!< No. of available items. */
|
||||
} ;
|
||||
|
||||
/** \ingroup rpmdep
|
||||
* A file to be installed/removed.
|
||||
*/
|
||||
struct fileIndexEntry {
|
||||
int pkgNum; /*!< Containing package number. */
|
||||
/*@dependent@*/ /*@null@*/ const char * baseName; /*!< File basename. */
|
||||
} ;
|
||||
|
||||
/** \ingroup rpmdep
|
||||
* A directory to be installed/removed.
|
||||
*/
|
||||
typedef struct dirInfo_s {
|
||||
/*@owned@*/ const char * dirName; /*!< Directory path (+ trailing '/'). */
|
||||
int dirNameLen; /*!< No. bytes in directory path. */
|
||||
/*@owned@*/ struct fileIndexEntry * files; /*!< Array of files in directory. */
|
||||
int numFiles; /*!< No. files in directory. */
|
||||
} * dirInfo ;
|
||||
|
||||
/** \ingroup rpmdep
|
||||
* Set of available packages, items, and directories.
|
||||
*/
|
||||
typedef /*@abstract@*/ struct availableList_s {
|
||||
/*@owned@*/ /*@null@*/ struct availablePackage * list; /*!< Set of packages. */
|
||||
struct availableIndex index; /*!< Set of available items. */
|
||||
int delta; /*!< Delta for pkg list reallocation. */
|
||||
int size; /*!< No. of pkgs in list. */
|
||||
int alloced; /*!< No. of pkgs allocated for list. */
|
||||
int numDirs; /*!< No. of directories. */
|
||||
/*@owned@*/ /*@null@*/ dirInfo dirs; /*!< Set of directories. */
|
||||
struct alDirIndex *dirIndex; /*!< Files index. */
|
||||
struct alProvIndex *provIndex; /*!< Provides index. */
|
||||
} * availableList;
|
||||
|
||||
/** \ingroup rpmdep
|
||||
@ -148,20 +105,17 @@ struct rpmTransactionSet_s {
|
||||
/*@kept@*/ /*@null@*/ rpmdb rpmdb; /*!< Database handle. */
|
||||
/*@only@*/ int * removedPackages; /*!< Set of packages being removed. */
|
||||
int numRemovedPackages; /*!< No. removed rpmdb instances. */
|
||||
int allocedRemovedPackages; /*!< Size of removed packages array. */
|
||||
struct availableList_s addedPackages;
|
||||
/*!< Set of packages being installed. */
|
||||
/*@only@*/ transactionElement order;
|
||||
/*!< Packages sorted by dependencies. */
|
||||
int orderCount; /*!< No. of transaction elements. */
|
||||
int orderAlloced; /*!< No. of allocated transaction elements. */
|
||||
/*@only@*/ TFI_t flList; /*!< Transaction element(s) file info. */
|
||||
int flEntries; /*!< No. of transaction elements. */
|
||||
int chrootDone; /*!< Has chroot(2) been been done? */
|
||||
/*@only@*/ const char * rootDir;/*!< Path to top of install tree. */
|
||||
/*@only@*/ const char * currDir;/*!< Current working directory. */
|
||||
/*@null@*/ FD_t scriptFd; /*!< Scriptlet stdout/stderr. */
|
||||
int delta; /*!< Delta for reallocation. */
|
||||
int id; /*!< Transaction id. */
|
||||
} ;
|
||||
|
||||
@ -171,7 +125,6 @@ struct rpmTransactionSet_s {
|
||||
typedef /*@abstract@*/ struct problemsSet_s {
|
||||
rpmDependencyConflict problems; /*!< Problems encountered. */
|
||||
int num; /*!< No. of problems found. */
|
||||
int alloced; /*!< No. of problems allocated. */
|
||||
} * problemsSet;
|
||||
|
||||
#ifdef __cplusplus
|
||||
@ -196,4 +149,11 @@ int headerMatchesDepFlags(Header h,
|
||||
}
|
||||
#endif
|
||||
|
||||
#define REALLOC_DELTA 8
|
||||
#define AUTO_REALLOC(ptr, size) \
|
||||
do { \
|
||||
if (((size) & (REALLOC_DELTA - 1)) == 0) \
|
||||
ptr = xrealloc((ptr), sizeof(*(ptr)) * ((size) + REALLOC_DELTA)); \
|
||||
} while (0)
|
||||
|
||||
#endif /* H_DEPENDS */
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
Name: %rpm_name
|
||||
Version: %rpm_version
|
||||
Release: alt98.22
|
||||
Release: alt98.23
|
||||
|
||||
%define ifdef() %if %{expand:%%{?%{1}:1}%%{!?%{1}:0}}
|
||||
%define get_dep() %(rpm -q --qf '%%{NAME} >= %%|SERIAL?{%%{SERIAL}:}|%%{VERSION}-%%{RELEASE}' %1 2>/dev/null || echo '%1 >= unknown')
|
||||
@ -488,6 +488,12 @@ fi
|
||||
%_bindir/rpm2cpio.static
|
||||
|
||||
%changelog
|
||||
* Sun Oct 04 2009 Alexey Tourbin <at@altlinux.ru> 4.0.4-alt98.23
|
||||
- depends.c: avoid expression dependent on evaluation order
|
||||
- depends.c: implemented automatic realloc
|
||||
- al.c: factored from depends.c
|
||||
- al.c: reimplemented alProvIndex and alDirIndex/alFileIndex routines
|
||||
|
||||
* Thu Oct 01 2009 Alexey Tourbin <at@altlinux.ru> 4.0.4-alt98.22
|
||||
- Removed support for availablePackages/suggestedPackages.
|
||||
- Removed rebuilddb db_filter_dups code (Panu Matilainen).
|
||||
|
Loading…
Reference in New Issue
Block a user