2000-08-28 03:27:03 +08:00
|
|
|
/** \ingroup rpmdep
|
|
|
|
* \file lib/depends.c
|
|
|
|
*/
|
|
|
|
|
2000-12-13 04:03:45 +08:00
|
|
|
#include "system.h"
|
|
|
|
|
1999-07-14 05:37:57 +08:00
|
|
|
#include <rpmlib.h>
|
2001-10-28 04:09:20 +08:00
|
|
|
#include <rpmmacro.h> /* XXX rpmGetPath */
|
2001-10-24 04:52:51 +08:00
|
|
|
#include <rpmpgp.h> /* XXX pgpFreeDig */
|
1997-01-18 00:20:18 +08:00
|
|
|
|
1998-03-28 00:46:39 +08:00
|
|
|
#include "depends.h"
|
2001-10-30 04:12:35 +08:00
|
|
|
#include "rpmal.h"
|
2001-06-18 06:18:03 +08:00
|
|
|
#include "rpmdb.h" /* XXX response cache needs dbiOpen et al. */
|
|
|
|
|
2000-12-13 04:03:45 +08:00
|
|
|
#include "debug.h"
|
1996-06-10 10:36:07 +08:00
|
|
|
|
2000-10-29 01:16:25 +08:00
|
|
|
/*@access dbiIndex@*/ /* XXX compared with NULL */
|
|
|
|
/*@access dbiIndexSet@*/ /* XXX compared with NULL */
|
|
|
|
/*@access Header@*/ /* XXX compared with NULL */
|
2001-04-29 09:05:43 +08:00
|
|
|
/*@access FD_t@*/ /* XXX compared with NULL */
|
2000-10-29 01:16:25 +08:00
|
|
|
/*@access rpmdb@*/ /* XXX compared with NULL */
|
2001-04-29 09:05:43 +08:00
|
|
|
/*@access rpmdbMatchIterator@*/ /* XXX compared with NULL */
|
1999-09-18 05:08:32 +08:00
|
|
|
/*@access rpmTransactionSet@*/
|
2001-06-01 06:31:14 +08:00
|
|
|
/*@access rpmDependencyConflict@*/
|
2001-10-29 06:17:47 +08:00
|
|
|
|
|
|
|
/*@access availablePackage@*/
|
|
|
|
/*@access availableIndexEntry@*/
|
|
|
|
/*@access availableIndex@*/
|
|
|
|
/*@access fileIndexEntry@*/
|
|
|
|
/*@access dirInfo@*/
|
2001-06-01 06:31:14 +08:00
|
|
|
/*@access availableList@*/
|
2001-10-29 06:17:47 +08:00
|
|
|
/*@access problemsSet@*/
|
|
|
|
/*@access orderListIndex@*/
|
2001-10-30 04:12:35 +08:00
|
|
|
/*@access tsortInfo@*/
|
2001-10-28 04:09:20 +08:00
|
|
|
|
2001-10-15 11:22:10 +08:00
|
|
|
/*@unchecked@*/
|
2001-09-16 05:21:31 +08:00
|
|
|
static int _cacheDependsRC = 1;
|
|
|
|
|
2001-10-29 06:17:47 +08:00
|
|
|
/*@unchecked@*/
|
|
|
|
int _ts_debug = 0;
|
|
|
|
|
2000-08-23 20:39:49 +08:00
|
|
|
/**
|
|
|
|
* Return formatted dependency string.
|
|
|
|
* @param depend type of dependency ("R" == Requires, "C" == Conflcts)
|
|
|
|
* @param key dependency name string
|
|
|
|
* @param keyEVR dependency [epoch:]version[-release] string
|
|
|
|
* @param keyFlags dependency logical range qualifiers
|
|
|
|
* @return formatted dependency (malloc'ed)
|
|
|
|
*/
|
2001-06-01 06:31:14 +08:00
|
|
|
static /*@only@*/ char * printDepend(const char * depend, const char * key,
|
|
|
|
const char * keyEVR, int keyFlags)
|
|
|
|
/*@*/
|
1999-09-19 08:29:44 +08:00
|
|
|
{
|
2001-06-12 12:10:21 +08:00
|
|
|
char * tbuf, * t;
|
1999-09-19 08:29:44 +08:00
|
|
|
size_t nb;
|
|
|
|
|
|
|
|
nb = 0;
|
2000-04-26 03:41:37 +08:00
|
|
|
if (depend) nb += strlen(depend) + 1;
|
1999-09-19 08:29:44 +08:00
|
|
|
if (key) nb += strlen(key);
|
2000-04-26 03:41:37 +08:00
|
|
|
if (keyFlags & RPMSENSE_SENSEMASK) {
|
1999-09-19 08:29:44 +08:00
|
|
|
if (nb) nb++;
|
|
|
|
if (keyFlags & RPMSENSE_LESS) nb++;
|
|
|
|
if (keyFlags & RPMSENSE_GREATER) nb++;
|
|
|
|
if (keyFlags & RPMSENSE_EQUAL) nb++;
|
|
|
|
}
|
2000-04-26 03:41:37 +08:00
|
|
|
if (keyEVR && *keyEVR) {
|
1999-09-19 08:29:44 +08:00
|
|
|
if (nb) nb++;
|
|
|
|
nb += strlen(keyEVR);
|
|
|
|
}
|
|
|
|
|
1999-09-21 11:22:53 +08:00
|
|
|
t = tbuf = xmalloc(nb + 1);
|
2000-04-26 03:41:37 +08:00
|
|
|
if (depend) {
|
2001-04-29 09:05:43 +08:00
|
|
|
while(*depend != '\0') *t++ = *depend++;
|
2000-04-26 03:41:37 +08:00
|
|
|
*t++ = ' ';
|
|
|
|
}
|
1999-09-19 08:29:44 +08:00
|
|
|
if (key)
|
2001-04-29 09:05:43 +08:00
|
|
|
while(*key != '\0') *t++ = *key++;
|
2000-04-26 03:41:37 +08:00
|
|
|
if (keyFlags & RPMSENSE_SENSEMASK) {
|
1999-09-19 08:29:44 +08:00
|
|
|
if (t != tbuf) *t++ = ' ';
|
|
|
|
if (keyFlags & RPMSENSE_LESS) *t++ = '<';
|
|
|
|
if (keyFlags & RPMSENSE_GREATER) *t++ = '>';
|
|
|
|
if (keyFlags & RPMSENSE_EQUAL) *t++ = '=';
|
|
|
|
}
|
2000-04-26 03:41:37 +08:00
|
|
|
if (keyEVR && *keyEVR) {
|
1999-09-19 08:29:44 +08:00
|
|
|
if (t != tbuf) *t++ = ' ';
|
2001-04-29 09:05:43 +08:00
|
|
|
while(*keyEVR != '\0') *t++ = *keyEVR++;
|
1999-09-19 08:29:44 +08:00
|
|
|
}
|
|
|
|
*t = '\0';
|
|
|
|
return tbuf;
|
|
|
|
}
|
|
|
|
|
2000-07-15 22:53:54 +08:00
|
|
|
#ifdef UNUSED
|
2000-04-14 00:00:34 +08:00
|
|
|
static /*@only@*/ const char *buildEVR(int_32 *e, const char *v, const char *r)
|
1999-09-19 08:29:44 +08:00
|
|
|
{
|
2000-04-14 00:00:34 +08:00
|
|
|
const char *pEVR;
|
|
|
|
char *p;
|
|
|
|
|
|
|
|
pEVR = p = xmalloc(21 + strlen(v) + 1 + strlen(r) + 1);
|
|
|
|
*p = '\0';
|
|
|
|
if (e) {
|
|
|
|
sprintf(p, "%d:", *e);
|
2000-04-21 08:21:15 +08:00
|
|
|
while (*p)
|
|
|
|
p++;
|
2000-04-14 00:00:34 +08:00
|
|
|
}
|
|
|
|
(void) stpcpy( stpcpy( stpcpy(p, v) , "-") , r);
|
1999-09-19 08:29:44 +08:00
|
|
|
return pEVR;
|
|
|
|
}
|
2000-04-14 00:00:34 +08:00
|
|
|
#endif
|
1999-09-19 08:29:44 +08:00
|
|
|
|
2000-08-23 20:39:49 +08:00
|
|
|
/**
|
|
|
|
* Split EVR into epoch, version, and release components.
|
|
|
|
* @param evr [epoch:]version[-release] string
|
|
|
|
* @retval *ep pointer to epoch
|
|
|
|
* @retval *vp pointer to version
|
|
|
|
* @retval *rp pointer to release
|
|
|
|
*/
|
2001-06-01 06:31:14 +08:00
|
|
|
static void parseEVR(char * evr,
|
|
|
|
/*@exposed@*/ /*@out@*/ const char ** ep,
|
|
|
|
/*@exposed@*/ /*@out@*/ const char ** vp,
|
|
|
|
/*@exposed@*/ /*@out@*/ const char ** rp)
|
|
|
|
/*@modifies *ep, *vp, *rp @*/
|
1999-07-23 01:48:31 +08:00
|
|
|
{
|
1999-09-14 13:41:13 +08:00
|
|
|
const char *epoch;
|
|
|
|
const char *version; /* assume only version is present */
|
|
|
|
const char *release;
|
1999-07-23 01:48:31 +08:00
|
|
|
char *s, *se;
|
|
|
|
|
|
|
|
s = evr;
|
2001-04-29 09:05:43 +08:00
|
|
|
while (*s && xisdigit(*s)) s++; /* s points to epoch terminator */
|
1999-07-23 01:48:31 +08:00
|
|
|
se = strrchr(s, '-'); /* se points to version terminator */
|
|
|
|
|
1999-09-14 13:41:13 +08:00
|
|
|
if (*s == ':') {
|
|
|
|
epoch = evr;
|
|
|
|
*s++ = '\0';
|
|
|
|
version = s;
|
2001-10-16 01:53:34 +08:00
|
|
|
/*@-branchstate@*/
|
1999-09-14 13:41:13 +08:00
|
|
|
if (*epoch == '\0') epoch = "0";
|
2001-10-16 01:53:34 +08:00
|
|
|
/*@=branchstate@*/
|
1999-09-14 13:41:13 +08:00
|
|
|
} else {
|
1999-09-15 00:04:03 +08:00
|
|
|
epoch = NULL; /* XXX disable epoch compare if missing */
|
1999-09-14 13:41:13 +08:00
|
|
|
version = evr;
|
1999-07-23 01:48:31 +08:00
|
|
|
}
|
1999-09-14 13:41:13 +08:00
|
|
|
if (se) {
|
|
|
|
*se++ = '\0';
|
|
|
|
release = se;
|
|
|
|
} else {
|
|
|
|
release = NULL;
|
|
|
|
}
|
|
|
|
|
1999-07-23 01:48:31 +08:00
|
|
|
if (ep) *ep = epoch;
|
|
|
|
if (vp) *vp = version;
|
|
|
|
if (rp) *rp = release;
|
|
|
|
}
|
|
|
|
|
2001-10-18 00:43:36 +08:00
|
|
|
/*@-exportheadervar@*/
|
2001-10-15 11:22:10 +08:00
|
|
|
/*@observer@*/ /*@unchecked@*/
|
|
|
|
const char *rpmNAME = PACKAGE;
|
2001-10-18 00:43:36 +08:00
|
|
|
|
2001-10-15 11:22:10 +08:00
|
|
|
/*@observer@*/ /*@unchecked@*/
|
|
|
|
const char *rpmEVR = VERSION;
|
2001-10-18 00:43:36 +08:00
|
|
|
|
2001-10-15 11:22:10 +08:00
|
|
|
/*@unchecked@*/
|
1999-09-26 23:04:03 +08:00
|
|
|
int rpmFLAGS = RPMSENSE_EQUAL;
|
2001-10-18 00:43:36 +08:00
|
|
|
/*@=exportheadervar@*/
|
1999-07-23 01:48:31 +08:00
|
|
|
|
2001-06-01 06:31:14 +08:00
|
|
|
int rpmRangesOverlap(const char * AName, const char * AEVR, int AFlags,
|
|
|
|
const char * BName, const char * BEVR, int BFlags)
|
1999-08-25 06:26:55 +08:00
|
|
|
{
|
2000-04-26 03:41:37 +08:00
|
|
|
const char *aDepend = printDepend(NULL, AName, AEVR, AFlags);
|
|
|
|
const char *bDepend = printDepend(NULL, BName, BEVR, BFlags);
|
1999-09-14 13:41:13 +08:00
|
|
|
char *aEVR, *bEVR;
|
|
|
|
const char *aE, *aV, *aR, *bE, *bV, *bR;
|
1999-08-25 06:26:55 +08:00
|
|
|
int result;
|
|
|
|
int sense;
|
|
|
|
|
1999-09-14 13:41:13 +08:00
|
|
|
/* Different names don't overlap. */
|
1999-09-19 08:29:44 +08:00
|
|
|
if (strcmp(AName, BName)) {
|
|
|
|
result = 0;
|
|
|
|
goto exit;
|
|
|
|
}
|
1999-09-14 13:41:13 +08:00
|
|
|
|
|
|
|
/* Same name. If either A or B is an existence test, always overlap. */
|
1999-09-19 08:29:44 +08:00
|
|
|
if (!((AFlags & RPMSENSE_SENSEMASK) && (BFlags & RPMSENSE_SENSEMASK))) {
|
|
|
|
result = 1;
|
|
|
|
goto exit;
|
|
|
|
}
|
1999-09-14 13:41:13 +08:00
|
|
|
|
|
|
|
/* If either EVR is non-existent or empty, always overlap. */
|
1999-09-19 08:29:44 +08:00
|
|
|
if (!(AEVR && *AEVR && BEVR && *BEVR)) {
|
|
|
|
result = 1;
|
|
|
|
goto exit;
|
|
|
|
}
|
1999-08-25 06:26:55 +08:00
|
|
|
|
1999-09-14 13:41:13 +08:00
|
|
|
/* Both AEVR and BEVR exist. */
|
1999-09-21 11:22:53 +08:00
|
|
|
aEVR = xstrdup(AEVR);
|
1999-09-14 13:41:13 +08:00
|
|
|
parseEVR(aEVR, &aE, &aV, &aR);
|
1999-09-21 11:22:53 +08:00
|
|
|
bEVR = xstrdup(BEVR);
|
1999-09-14 13:41:13 +08:00
|
|
|
parseEVR(bEVR, &bE, &bV, &bR);
|
1999-08-25 06:26:55 +08:00
|
|
|
|
1999-09-14 13:41:13 +08:00
|
|
|
/* Compare {A,B} [epoch:]version[-release] */
|
1999-09-20 21:23:46 +08:00
|
|
|
sense = 0;
|
1999-09-19 23:27:37 +08:00
|
|
|
if (aE && *aE && bE && *bE)
|
|
|
|
sense = rpmvercmp(aE, bE);
|
1999-09-25 00:02:14 +08:00
|
|
|
else if (aE && *aE && atol(aE) > 0) {
|
|
|
|
/* XXX legacy epoch-less requires/conflicts compatibility */
|
1999-09-25 07:36:52 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, _("the \"B\" dependency needs an epoch (assuming same as \"A\")\n\tA %s\tB %s\n"),
|
1999-09-25 00:02:14 +08:00
|
|
|
aDepend, bDepend);
|
|
|
|
sense = 0;
|
|
|
|
} else if (bE && *bE && atol(bE) > 0)
|
1999-09-19 23:27:37 +08:00
|
|
|
sense = -1;
|
1999-09-24 22:54:23 +08:00
|
|
|
|
1999-08-25 06:26:55 +08:00
|
|
|
if (sense == 0) {
|
1999-09-14 13:41:13 +08:00
|
|
|
sense = rpmvercmp(aV, bV);
|
|
|
|
if (sense == 0 && aR && *aR && bR && *bR) {
|
|
|
|
sense = rpmvercmp(aR, bR);
|
1999-08-25 06:26:55 +08:00
|
|
|
}
|
|
|
|
}
|
2001-04-21 14:02:09 +08:00
|
|
|
aEVR = _free(aEVR);
|
|
|
|
bEVR = _free(bEVR);
|
1999-08-25 06:26:55 +08:00
|
|
|
|
1999-09-14 13:41:13 +08:00
|
|
|
/* Detect overlap of {A,B} range. */
|
1999-08-25 06:26:55 +08:00
|
|
|
result = 0;
|
1999-09-14 13:41:13 +08:00
|
|
|
if (sense < 0 && ((AFlags & RPMSENSE_GREATER) || (BFlags & RPMSENSE_LESS))) {
|
1999-08-25 06:26:55 +08:00
|
|
|
result = 1;
|
1999-09-14 13:41:13 +08:00
|
|
|
} else if (sense > 0 && ((AFlags & RPMSENSE_LESS) || (BFlags & RPMSENSE_GREATER))) {
|
1999-08-25 06:26:55 +08:00
|
|
|
result = 1;
|
1999-09-14 13:41:13 +08:00
|
|
|
} else if (sense == 0 &&
|
|
|
|
(((AFlags & RPMSENSE_EQUAL) && (BFlags & RPMSENSE_EQUAL)) ||
|
|
|
|
((AFlags & RPMSENSE_LESS) && (BFlags & RPMSENSE_LESS)) ||
|
|
|
|
((AFlags & RPMSENSE_GREATER) && (BFlags & RPMSENSE_GREATER)))) {
|
1999-08-25 06:26:55 +08:00
|
|
|
result = 1;
|
|
|
|
}
|
|
|
|
|
1999-09-19 08:29:44 +08:00
|
|
|
exit:
|
1999-09-24 22:54:23 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, _(" %s A %s\tB %s\n"),
|
2001-04-21 14:02:09 +08:00
|
|
|
(result ? _("YES") : _("NO ")), aDepend, bDepend);
|
|
|
|
aDepend = _free(aDepend);
|
|
|
|
bDepend = _free(bDepend);
|
1999-08-25 06:26:55 +08:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2001-06-01 06:31:14 +08:00
|
|
|
static int rangeMatchesDepFlags (Header h,
|
|
|
|
const char * reqName, const char * reqEVR, int reqFlags)
|
|
|
|
/*@*/
|
1999-07-23 01:48:31 +08:00
|
|
|
{
|
2001-02-05 06:15:30 +08:00
|
|
|
HGE_t hge = (HGE_t)headerGetEntryMinMemory;
|
|
|
|
HFD_t hfd = headerFreeData;
|
2001-06-12 12:10:21 +08:00
|
|
|
rpmTagType pnt, pvt;
|
1999-09-12 05:10:02 +08:00
|
|
|
const char ** provides;
|
|
|
|
const char ** providesEVR;
|
1999-09-14 13:41:13 +08:00
|
|
|
int_32 * provideFlags;
|
1999-07-23 01:48:31 +08:00
|
|
|
int providesCount;
|
|
|
|
int result;
|
2001-10-16 22:58:57 +08:00
|
|
|
int i, xx;
|
1999-07-23 01:48:31 +08:00
|
|
|
|
1999-09-12 05:10:02 +08:00
|
|
|
if (!(reqFlags & RPMSENSE_SENSEMASK) || !reqEVR || !strlen(reqEVR))
|
1999-07-23 01:48:31 +08:00
|
|
|
return 1;
|
|
|
|
|
|
|
|
/* Get provides information from header */
|
|
|
|
/*
|
|
|
|
* Rpm prior to 3.0.3 does not have versioned provides.
|
|
|
|
* If no provides version info is available, match any requires.
|
|
|
|
*/
|
2001-02-05 06:15:30 +08:00
|
|
|
if (!hge(h, RPMTAG_PROVIDEVERSION, &pvt,
|
1999-09-12 05:10:02 +08:00
|
|
|
(void **) &providesEVR, &providesCount))
|
1999-07-23 01:48:31 +08:00
|
|
|
return 1;
|
|
|
|
|
2001-10-16 22:58:57 +08:00
|
|
|
xx = hge(h, RPMTAG_PROVIDEFLAGS, NULL, (void **) &provideFlags, NULL);
|
1999-07-23 01:48:31 +08:00
|
|
|
|
2001-02-05 06:15:30 +08:00
|
|
|
if (!hge(h, RPMTAG_PROVIDENAME, &pnt, (void **) &provides, &providesCount))
|
|
|
|
{
|
|
|
|
providesEVR = hfd(providesEVR, pvt);
|
1999-07-23 01:48:31 +08:00
|
|
|
return 0; /* XXX should never happen */
|
|
|
|
}
|
|
|
|
|
|
|
|
result = 0;
|
|
|
|
for (i = 0; i < providesCount; i++) {
|
|
|
|
|
2000-05-07 08:53:11 +08:00
|
|
|
/* Filter out provides that came along for the ride. */
|
|
|
|
if (strcmp(provides[i], reqName))
|
|
|
|
continue;
|
|
|
|
|
2000-07-11 10:12:49 +08:00
|
|
|
result = rpmRangesOverlap(provides[i], providesEVR[i], provideFlags[i],
|
2000-05-07 08:53:11 +08:00
|
|
|
reqName, reqEVR, reqFlags);
|
1999-07-23 01:48:31 +08:00
|
|
|
|
1999-09-14 13:41:13 +08:00
|
|
|
/* If this provide matches the require, we're done. */
|
1999-07-23 01:48:31 +08:00
|
|
|
if (result)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2001-02-05 06:15:30 +08:00
|
|
|
provides = hfd(provides, pnt);
|
|
|
|
providesEVR = hfd(providesEVR, pvt);
|
1999-07-23 01:48:31 +08:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2000-05-07 08:53:11 +08:00
|
|
|
int headerMatchesDepFlags(Header h,
|
2001-06-01 06:31:14 +08:00
|
|
|
const char * reqName, const char * reqEVR, int reqFlags)
|
1999-07-23 01:48:31 +08:00
|
|
|
{
|
2001-02-05 06:15:30 +08:00
|
|
|
HGE_t hge = (HGE_t)headerGetEntryMinMemory;
|
1999-09-14 13:41:13 +08:00
|
|
|
const char *name, *version, *release;
|
1999-09-15 00:04:03 +08:00
|
|
|
int_32 * epoch;
|
2000-04-14 00:00:34 +08:00
|
|
|
const char *pkgEVR;
|
|
|
|
char *p;
|
1999-09-14 13:41:13 +08:00
|
|
|
int pkgFlags = RPMSENSE_EQUAL;
|
1999-07-23 01:48:31 +08:00
|
|
|
|
1999-09-14 13:41:13 +08:00
|
|
|
if (!((reqFlags & RPMSENSE_SENSEMASK) && reqEVR && *reqEVR))
|
1999-07-23 01:48:31 +08:00
|
|
|
return 1;
|
|
|
|
|
|
|
|
/* Get package information from header */
|
2001-05-01 06:32:22 +08:00
|
|
|
(void) headerNVR(h, &name, &version, &release);
|
1999-07-23 01:48:31 +08:00
|
|
|
|
2000-04-14 00:00:34 +08:00
|
|
|
pkgEVR = p = alloca(21 + strlen(version) + 1 + strlen(release) + 1);
|
|
|
|
*p = '\0';
|
2001-02-05 06:15:30 +08:00
|
|
|
if (hge(h, RPMTAG_EPOCH, NULL, (void **) &epoch, NULL)) {
|
2000-04-14 00:00:34 +08:00
|
|
|
sprintf(p, "%d:", *epoch);
|
2001-04-29 09:05:43 +08:00
|
|
|
while (*p != '\0')
|
2000-04-21 08:21:15 +08:00
|
|
|
p++;
|
1996-06-11 01:42:57 +08:00
|
|
|
}
|
2000-04-14 00:00:34 +08:00
|
|
|
(void) stpcpy( stpcpy( stpcpy(p, version) , "-") , release);
|
1996-06-11 01:42:57 +08:00
|
|
|
|
2000-07-11 10:12:49 +08:00
|
|
|
return rpmRangesOverlap(name, pkgEVR, pkgFlags, reqName, reqEVR, reqFlags);
|
1996-06-10 10:36:07 +08:00
|
|
|
}
|
2001-10-28 06:31:10 +08:00
|
|
|
|
2001-10-29 06:17:47 +08:00
|
|
|
rpmTransactionSet XrpmtsUnlink(rpmTransactionSet ts, const char * msg, const char * fn, unsigned ln)
|
2001-10-28 06:31:10 +08:00
|
|
|
{
|
2001-10-29 06:17:47 +08:00
|
|
|
/*@-modfilesystem@*/
|
|
|
|
if (_ts_debug)
|
|
|
|
fprintf(stderr, "--> ts %p -- %d %s at %s:%u\n", ts, ts->nrefs, msg, fn, ln);
|
|
|
|
/*@=modfilesystem@*/
|
2001-10-28 06:31:10 +08:00
|
|
|
ts->nrefs--;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2001-10-29 06:17:47 +08:00
|
|
|
rpmTransactionSet XrpmtsLink(rpmTransactionSet ts, const char * msg, const char * fn, unsigned ln)
|
|
|
|
{
|
|
|
|
ts->nrefs++;
|
2001-10-28 04:09:20 +08:00
|
|
|
/*@-modfilesystem@*/
|
2001-10-29 06:17:47 +08:00
|
|
|
if (_ts_debug)
|
|
|
|
fprintf(stderr, "--> ts %p ++ %d %s at %s:%u\n", ts, ts->nrefs, msg, fn, ln);
|
|
|
|
/*@=modfilesystem@*/
|
|
|
|
/*@-refcounttrans@*/ return ts; /*@=refcounttrans@*/
|
|
|
|
}
|
|
|
|
|
2001-10-28 04:09:20 +08:00
|
|
|
int rpmtsCloseDB(rpmTransactionSet ts)
|
|
|
|
{
|
|
|
|
int rc = 0;
|
|
|
|
|
|
|
|
if (ts->rpmdb != NULL) {
|
|
|
|
rc = rpmdbClose(ts->rpmdb);
|
|
|
|
ts->rpmdb = NULL;
|
|
|
|
}
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
int rpmtsOpenDB(rpmTransactionSet ts, int dbmode)
|
|
|
|
{
|
|
|
|
int rc = 0;
|
|
|
|
|
2001-10-29 06:17:47 +08:00
|
|
|
if (ts->rpmdb != NULL && ts->dbmode == dbmode)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
(void) rpmtsCloseDB(ts);
|
|
|
|
|
|
|
|
/* XXX there's a lock race here. */
|
2001-10-28 04:09:20 +08:00
|
|
|
|
|
|
|
ts->dbmode = dbmode;
|
|
|
|
rc = rpmdbOpen(ts->rootDir, &ts->rpmdb, ts->dbmode, 0644);
|
|
|
|
if (rc) {
|
|
|
|
const char * dn;
|
|
|
|
/*@-globs -mods@*/ /* FIX: rpmGlobalMacroContext */
|
|
|
|
dn = rpmGetPath(ts->rootDir, "%{_dbpath}", NULL);
|
|
|
|
/*@=globs =mods@*/
|
|
|
|
rpmMessage(RPMMESS_ERROR,
|
|
|
|
_("cannot open Packages database in %s\n"), dn);
|
|
|
|
dn = _free(dn);
|
|
|
|
}
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
rpmdbMatchIterator rpmtsInitIterator(const rpmTransactionSet ts, int rpmtag,
|
|
|
|
const void * keyp, size_t keylen)
|
|
|
|
{
|
|
|
|
/*@-mods -onlytrans -type@*/ /* FIX: rpmdb excision */
|
|
|
|
return rpmdbInitIterator(ts->rpmdb, rpmtag, keyp, keylen);
|
|
|
|
/*@=mods =onlytrans =type@*/
|
|
|
|
}
|
1996-06-10 10:36:07 +08:00
|
|
|
|
2001-10-16 01:53:34 +08:00
|
|
|
rpmTransactionSet rpmtransCreateSet(rpmdb db, const char * rootDir)
|
1999-08-21 05:05:18 +08:00
|
|
|
{
|
2001-01-16 07:09:42 +08:00
|
|
|
rpmTransactionSet ts;
|
2000-04-14 00:00:34 +08:00
|
|
|
int rootLen;
|
1999-08-21 05:05:18 +08:00
|
|
|
|
2001-10-16 01:53:34 +08:00
|
|
|
/*@-branchstate@*/
|
2000-07-09 23:17:11 +08:00
|
|
|
if (!rootDir) rootDir = "";
|
2001-10-16 01:53:34 +08:00
|
|
|
/*@=branchstate@*/
|
1999-08-21 05:05:18 +08:00
|
|
|
|
2001-01-16 07:09:42 +08:00
|
|
|
ts = xcalloc(1, sizeof(*ts));
|
2001-01-27 01:06:09 +08:00
|
|
|
ts->filesystemCount = 0;
|
|
|
|
ts->filesystems = NULL;
|
|
|
|
ts->di = NULL;
|
2001-10-28 04:09:20 +08:00
|
|
|
if (db != NULL) {
|
|
|
|
/*@-assignexpose@*/
|
2001-10-29 06:17:47 +08:00
|
|
|
ts->rpmdb = rpmdbLink(db, "tsCreate");
|
2001-10-28 04:09:20 +08:00
|
|
|
/*@=assignexpose@*/
|
|
|
|
ts->dbmode = db->db_mode;
|
|
|
|
} else {
|
|
|
|
ts->rpmdb = NULL;
|
|
|
|
ts->dbmode = O_RDONLY;
|
|
|
|
}
|
2001-01-16 07:09:42 +08:00
|
|
|
ts->scriptFd = NULL;
|
2001-10-24 04:52:51 +08:00
|
|
|
ts->id = (int_32) time(NULL);
|
2001-01-16 07:09:42 +08:00
|
|
|
ts->delta = 5;
|
|
|
|
|
|
|
|
ts->numRemovedPackages = 0;
|
|
|
|
ts->allocedRemovedPackages = ts->delta;
|
|
|
|
ts->removedPackages = xcalloc(ts->allocedRemovedPackages,
|
|
|
|
sizeof(*ts->removedPackages));
|
1999-08-21 05:05:18 +08:00
|
|
|
|
|
|
|
/* This canonicalizes the root */
|
2000-07-09 23:17:11 +08:00
|
|
|
rootLen = strlen(rootDir);
|
|
|
|
if (!(rootLen && rootDir[rootLen - 1] == '/')) {
|
|
|
|
char * t;
|
|
|
|
|
|
|
|
t = alloca(rootLen + 2);
|
|
|
|
*t = '\0';
|
|
|
|
(void) stpcpy( stpcpy(t, rootDir), "/");
|
|
|
|
rootDir = t;
|
1999-08-21 05:05:18 +08:00
|
|
|
}
|
|
|
|
|
2001-10-28 04:09:20 +08:00
|
|
|
ts->rootDir = (rootDir != NULL ? xstrdup(rootDir) : xstrdup(""));
|
2001-01-16 07:09:42 +08:00
|
|
|
ts->currDir = NULL;
|
|
|
|
ts->chrootDone = 0;
|
1999-08-21 05:05:18 +08:00
|
|
|
|
2001-10-30 04:12:35 +08:00
|
|
|
ts->addedPackages = alCreate(ts->delta);
|
|
|
|
|
|
|
|
ts->availablePackages = alCreate(ts->delta);
|
1999-08-21 05:05:18 +08:00
|
|
|
|
2001-01-16 07:09:42 +08:00
|
|
|
ts->orderAlloced = ts->delta;
|
|
|
|
ts->orderCount = 0;
|
|
|
|
ts->order = xcalloc(ts->orderAlloced, sizeof(*ts->order));
|
1999-08-21 05:05:18 +08:00
|
|
|
|
2001-10-24 04:52:51 +08:00
|
|
|
ts->sig = NULL;
|
|
|
|
ts->dig = NULL;
|
|
|
|
|
2001-10-29 06:17:47 +08:00
|
|
|
ts->nrefs = 0;
|
|
|
|
|
|
|
|
return rpmtsLink(ts, "tsCreate");
|
1999-08-21 05:05:18 +08:00
|
|
|
}
|
|
|
|
|
2001-05-17 04:02:08 +08:00
|
|
|
/**
|
|
|
|
* Compare removed package instances (qsort/bsearch).
|
|
|
|
* @param a 1st instance address
|
|
|
|
* @param b 2nd instance address
|
|
|
|
* @return result of comparison
|
|
|
|
*/
|
2001-06-01 06:31:14 +08:00
|
|
|
static int intcmp(const void * a, const void * b) /*@*/
|
2001-05-17 04:02:08 +08:00
|
|
|
{
|
|
|
|
const int * aptr = a;
|
|
|
|
const int * bptr = b;
|
|
|
|
int rc = (*aptr - *bptr);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2000-08-23 20:39:49 +08:00
|
|
|
/**
|
|
|
|
* Add removed package instance to ordered transaction set.
|
2001-01-16 07:09:42 +08:00
|
|
|
* @param ts transaction set
|
2000-08-23 20:39:49 +08:00
|
|
|
* @param dboffset rpm database instance
|
|
|
|
* @param depends installed package of pair (or -1 on erase)
|
2001-07-07 04:37:42 +08:00
|
|
|
* @return 0 on success
|
2000-08-23 20:39:49 +08:00
|
|
|
*/
|
2001-07-07 04:37:42 +08:00
|
|
|
static int removePackage(rpmTransactionSet ts, int dboffset, int depends)
|
2001-01-16 07:09:42 +08:00
|
|
|
/*@modifies ts @*/
|
1999-08-21 05:05:18 +08:00
|
|
|
{
|
2001-05-17 03:19:15 +08:00
|
|
|
|
|
|
|
/* Filter out duplicate erasures. */
|
2001-05-17 04:02:08 +08:00
|
|
|
if (ts->numRemovedPackages > 0 && ts->removedPackages != NULL) {
|
|
|
|
if (bsearch(&dboffset, ts->removedPackages, ts->numRemovedPackages,
|
2001-10-16 22:58:57 +08:00
|
|
|
sizeof(*ts->removedPackages), intcmp) != NULL)
|
2001-07-07 04:37:42 +08:00
|
|
|
return 0;
|
2001-05-17 04:02:08 +08:00
|
|
|
}
|
2001-05-17 03:19:15 +08:00
|
|
|
|
2001-01-16 07:09:42 +08:00
|
|
|
if (ts->numRemovedPackages == ts->allocedRemovedPackages) {
|
|
|
|
ts->allocedRemovedPackages += ts->delta;
|
|
|
|
ts->removedPackages = xrealloc(ts->removedPackages,
|
2001-10-16 22:58:57 +08:00
|
|
|
sizeof(ts->removedPackages) * ts->allocedRemovedPackages);
|
1999-08-21 05:05:18 +08:00
|
|
|
}
|
|
|
|
|
2001-05-17 04:02:08 +08:00
|
|
|
if (ts->removedPackages != NULL) { /* XXX can't happen. */
|
|
|
|
ts->removedPackages[ts->numRemovedPackages++] = dboffset;
|
2001-10-16 22:58:57 +08:00
|
|
|
qsort(ts->removedPackages, ts->numRemovedPackages,
|
|
|
|
sizeof(*ts->removedPackages), intcmp);
|
2001-05-17 04:02:08 +08:00
|
|
|
}
|
1999-08-21 05:05:18 +08:00
|
|
|
|
2001-01-16 07:09:42 +08:00
|
|
|
if (ts->orderCount == ts->orderAlloced) {
|
|
|
|
ts->orderAlloced += ts->delta;
|
|
|
|
ts->order = xrealloc(ts->order, sizeof(*ts->order) * ts->orderAlloced);
|
1999-08-21 05:05:18 +08:00
|
|
|
}
|
|
|
|
|
2001-01-16 07:09:42 +08:00
|
|
|
ts->order[ts->orderCount].type = TR_REMOVED;
|
|
|
|
ts->order[ts->orderCount].u.removed.dboffset = dboffset;
|
|
|
|
ts->order[ts->orderCount++].u.removed.dependsOnIndex = depends;
|
2001-07-07 04:37:42 +08:00
|
|
|
|
|
|
|
return 0;
|
1999-08-21 05:05:18 +08:00
|
|
|
}
|
|
|
|
|
2001-10-28 04:09:20 +08:00
|
|
|
static /*@only@*/ const char * hNVRstr(Header h, /*@out@*/ const char ** np )
|
|
|
|
/*@modifies *np @*/
|
|
|
|
{
|
|
|
|
const char * NVR, * n, * v, * r;
|
|
|
|
char * t;
|
|
|
|
|
|
|
|
(void) headerNVR(h, &n, &v, &r);
|
|
|
|
NVR = t = xcalloc(1, strlen(n) + strlen(v) + strlen(r) + sizeof("--"));
|
|
|
|
t = stpcpy(t, n);
|
|
|
|
t = stpcpy(t, "-");
|
|
|
|
t = stpcpy(t, v);
|
|
|
|
t = stpcpy(t, "-");
|
|
|
|
t = stpcpy(t, r);
|
|
|
|
if (np)
|
|
|
|
*np = n;
|
|
|
|
return NVR;
|
|
|
|
}
|
|
|
|
|
2001-01-16 07:09:42 +08:00
|
|
|
int rpmtransAddPackage(rpmTransactionSet ts, Header h, FD_t fd,
|
1999-08-21 05:05:18 +08:00
|
|
|
const void * key, int upgrade, rpmRelocation * relocs)
|
|
|
|
{
|
2001-02-05 06:15:30 +08:00
|
|
|
HGE_t hge = (HGE_t)headerGetEntryMinMemory;
|
|
|
|
HFD_t hfd = headerFreeData;
|
2001-10-28 04:09:20 +08:00
|
|
|
const char * name = NULL;
|
|
|
|
const char * addNVR = hNVRstr(h, &name);
|
|
|
|
const char * pkgNVR = NULL;
|
2001-06-12 12:10:21 +08:00
|
|
|
rpmTagType ont, ovt;
|
2001-10-29 06:17:47 +08:00
|
|
|
availablePackage p;
|
2000-04-13 20:43:49 +08:00
|
|
|
int count;
|
1999-08-21 05:05:18 +08:00
|
|
|
const char ** obsoletes;
|
|
|
|
int alNum;
|
2001-10-16 22:58:57 +08:00
|
|
|
int xx;
|
2001-10-28 04:09:20 +08:00
|
|
|
int ec = 0;
|
|
|
|
int rc;
|
|
|
|
int i = ts->orderCount;
|
1999-08-21 05:05:18 +08:00
|
|
|
|
2001-01-25 20:58:03 +08:00
|
|
|
/*
|
2001-10-28 04:09:20 +08:00
|
|
|
* Check for previously added versions with the same name.
|
2001-01-25 20:58:03 +08:00
|
|
|
*/
|
2001-10-28 04:09:20 +08:00
|
|
|
i = ts->orderCount;
|
2001-10-30 04:12:35 +08:00
|
|
|
if (ts->addedPackages->list != NULL)
|
2001-10-28 04:09:20 +08:00
|
|
|
for (i = 0; i < ts->orderCount; i++) {
|
2001-10-30 04:12:35 +08:00
|
|
|
p = ts->addedPackages->list + i;
|
2001-10-28 04:09:20 +08:00
|
|
|
if (strcmp(p->name, name))
|
|
|
|
continue;
|
|
|
|
rc = rpmVersionCompare(p->h, h);
|
|
|
|
pkgNVR = hNVRstr(p->h, NULL);
|
|
|
|
if (rc > 0) {
|
|
|
|
rpmMessage(RPMMESS_WARNING,
|
|
|
|
_("newer package %s already added, skipping %s\n"),
|
|
|
|
pkgNVR, addNVR);
|
|
|
|
goto exit;
|
|
|
|
} else if (rc == 0) {
|
|
|
|
rpmMessage(RPMMESS_WARNING,
|
|
|
|
_("package %s already added, ignoring\n"),
|
|
|
|
pkgNVR);
|
|
|
|
goto exit;
|
|
|
|
} else {
|
|
|
|
rpmMessage(RPMMESS_WARNING,
|
|
|
|
_("older package %s already added, replacing with %s\n"),
|
|
|
|
pkgNVR, addNVR);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2001-10-30 04:12:35 +08:00
|
|
|
/* XXX Note: i == ts->orderCount here almost always. */
|
2001-10-28 04:09:20 +08:00
|
|
|
|
|
|
|
if (i == ts->orderAlloced) {
|
2001-01-16 07:09:42 +08:00
|
|
|
ts->orderAlloced += ts->delta;
|
2001-10-28 04:09:20 +08:00
|
|
|
ts->order = xrealloc(ts->order, ts->orderAlloced * sizeof(*ts->order));
|
1999-08-21 05:05:18 +08:00
|
|
|
}
|
2001-10-28 04:09:20 +08:00
|
|
|
ts->order[i].type = TR_ADDED;
|
2001-10-30 04:12:35 +08:00
|
|
|
if (ts->addedPackages->list == NULL)
|
2001-10-28 04:09:20 +08:00
|
|
|
goto exit;
|
2001-05-04 05:00:18 +08:00
|
|
|
|
2001-10-30 04:12:35 +08:00
|
|
|
{ availablePackage this =
|
|
|
|
alAddPackage(ts->addedPackages, i, h, key, fd, relocs);
|
|
|
|
alNum = this - ts->addedPackages->list;
|
|
|
|
ts->order[i].u.addedIndex = alNum;
|
|
|
|
}
|
1999-08-21 05:05:18 +08:00
|
|
|
|
2001-10-28 04:09:20 +08:00
|
|
|
if (i == ts->orderCount)
|
|
|
|
ts->orderCount++;
|
|
|
|
|
|
|
|
if (!upgrade)
|
|
|
|
goto exit;
|
2001-01-25 20:58:03 +08:00
|
|
|
|
|
|
|
/* XXX binary rpms always have RPMTAG_SOURCERPM, source rpms do not */
|
|
|
|
if (headerIsEntry(h, RPMTAG_SOURCEPACKAGE))
|
2001-10-28 04:09:20 +08:00
|
|
|
goto exit;
|
1999-08-21 05:05:18 +08:00
|
|
|
|
2001-10-30 04:12:35 +08:00
|
|
|
/* Do lazy (readonly?) open of rpm database. */
|
2001-10-28 04:09:20 +08:00
|
|
|
if (ts->rpmdb == NULL) {
|
|
|
|
if ((ec = rpmtsOpenDB(ts, ts->dbmode)) != 0)
|
|
|
|
goto exit;
|
|
|
|
}
|
1999-08-21 05:05:18 +08:00
|
|
|
|
2000-04-13 17:07:08 +08:00
|
|
|
{ rpmdbMatchIterator mi;
|
|
|
|
Header h2;
|
|
|
|
|
2001-10-28 04:09:20 +08:00
|
|
|
mi = rpmtsInitIterator(ts, RPMTAG_NAME, name, 0);
|
2000-04-13 17:07:08 +08:00
|
|
|
while((h2 = rpmdbNextIterator(mi)) != NULL) {
|
2001-10-16 01:53:34 +08:00
|
|
|
/*@-branchstate@*/
|
2000-04-13 17:07:08 +08:00
|
|
|
if (rpmVersionCompare(h, h2))
|
2001-10-16 22:58:57 +08:00
|
|
|
xx = removePackage(ts, rpmdbGetIteratorOffset(mi), alNum);
|
2000-07-06 04:39:15 +08:00
|
|
|
else {
|
2001-10-28 04:09:20 +08:00
|
|
|
uint_32 *pp, multiLibMask = 0, oldmultiLibMask = 0;
|
2000-07-06 04:39:15 +08:00
|
|
|
|
2001-10-28 04:09:20 +08:00
|
|
|
if (hge(h2, RPMTAG_MULTILIBS, NULL, (void **) &pp, NULL))
|
|
|
|
oldmultiLibMask = *pp;
|
|
|
|
if (hge(h, RPMTAG_MULTILIBS, NULL, (void **) &pp, NULL))
|
|
|
|
multiLibMask = *pp;
|
2000-07-06 04:39:15 +08:00
|
|
|
if (oldmultiLibMask && multiLibMask
|
|
|
|
&& !(oldmultiLibMask & multiLibMask)) {
|
2001-10-30 04:12:35 +08:00
|
|
|
ts->addedPackages->list[alNum].multiLib = multiLibMask;
|
2000-07-06 04:39:15 +08:00
|
|
|
}
|
|
|
|
}
|
2001-10-16 01:53:34 +08:00
|
|
|
/*@=branchstate@*/
|
2000-04-13 17:07:08 +08:00
|
|
|
}
|
2001-04-30 06:43:01 +08:00
|
|
|
mi = rpmdbFreeIterator(mi);
|
2000-04-13 17:07:08 +08:00
|
|
|
}
|
1999-08-21 05:05:18 +08:00
|
|
|
|
2001-02-05 06:15:30 +08:00
|
|
|
if (hge(h, RPMTAG_OBSOLETENAME, &ont, (void **) &obsoletes, &count)) {
|
2001-05-01 06:32:22 +08:00
|
|
|
const char ** obsoletesEVR;
|
|
|
|
int_32 * obsoletesFlags;
|
2000-04-13 20:43:49 +08:00
|
|
|
int j;
|
1999-08-21 05:05:18 +08:00
|
|
|
|
2001-10-16 22:58:57 +08:00
|
|
|
xx = hge(h, RPMTAG_OBSOLETEVERSION, &ovt, (void **) &obsoletesEVR,
|
2001-05-01 06:32:22 +08:00
|
|
|
NULL);
|
2001-10-16 22:58:57 +08:00
|
|
|
xx = hge(h, RPMTAG_OBSOLETEFLAGS, NULL, (void **) &obsoletesFlags,
|
2001-05-01 06:32:22 +08:00
|
|
|
NULL);
|
1999-08-21 05:05:18 +08:00
|
|
|
|
|
|
|
for (j = 0; j < count; j++) {
|
1999-09-12 07:57:59 +08:00
|
|
|
|
|
|
|
/* XXX avoid self-obsoleting packages. */
|
|
|
|
if (!strcmp(name, obsoletes[j]))
|
|
|
|
continue;
|
|
|
|
|
2000-04-13 17:07:08 +08:00
|
|
|
{ rpmdbMatchIterator mi;
|
|
|
|
Header h2;
|
|
|
|
|
2001-10-28 04:09:20 +08:00
|
|
|
mi = rpmtsInitIterator(ts, RPMTAG_NAME, obsoletes[j], 0);
|
2000-04-13 17:07:08 +08:00
|
|
|
|
2001-10-16 22:58:57 +08:00
|
|
|
xx = rpmdbPruneIterator(mi,
|
2001-01-16 07:09:42 +08:00
|
|
|
ts->removedPackages, ts->numRemovedPackages, 1);
|
2000-05-07 08:53:11 +08:00
|
|
|
|
|
|
|
while((h2 = rpmdbNextIterator(mi)) != NULL) {
|
2000-04-13 17:07:08 +08:00
|
|
|
/*
|
|
|
|
* Rpm prior to 3.0.3 does not have versioned obsoletes.
|
|
|
|
* If no obsoletes version info is available, match all names.
|
|
|
|
*/
|
2001-10-16 01:53:34 +08:00
|
|
|
/*@-branchstate@*/
|
2000-04-13 17:07:08 +08:00
|
|
|
if (obsoletesEVR == NULL ||
|
|
|
|
headerMatchesDepFlags(h2,
|
2000-05-07 08:53:11 +08:00
|
|
|
obsoletes[j], obsoletesEVR[j], obsoletesFlags[j]))
|
|
|
|
{
|
2001-10-16 22:58:57 +08:00
|
|
|
xx = removePackage(ts, rpmdbGetIteratorOffset(mi), alNum);
|
2000-04-13 17:07:08 +08:00
|
|
|
}
|
2001-10-16 01:53:34 +08:00
|
|
|
/*@=branchstate@*/
|
2000-04-13 17:07:08 +08:00
|
|
|
}
|
2001-04-30 06:43:01 +08:00
|
|
|
mi = rpmdbFreeIterator(mi);
|
2000-04-13 17:07:08 +08:00
|
|
|
}
|
1999-08-21 05:05:18 +08:00
|
|
|
}
|
|
|
|
|
2001-02-05 06:15:30 +08:00
|
|
|
obsoletesEVR = hfd(obsoletesEVR, ovt);
|
|
|
|
obsoletes = hfd(obsoletes, ont);
|
1999-08-21 05:05:18 +08:00
|
|
|
}
|
2001-10-28 04:09:20 +08:00
|
|
|
ec = 0;
|
1999-08-21 05:05:18 +08:00
|
|
|
|
2001-10-28 04:09:20 +08:00
|
|
|
exit:
|
|
|
|
pkgNVR = _free(pkgNVR);
|
|
|
|
addNVR = _free(addNVR);
|
|
|
|
return ec;
|
1999-08-21 05:05:18 +08:00
|
|
|
}
|
|
|
|
|
2001-01-27 01:06:09 +08:00
|
|
|
void rpmtransAvailablePackage(rpmTransactionSet ts, Header h, const void * key)
|
1999-08-21 05:05:18 +08:00
|
|
|
{
|
2001-10-29 06:17:47 +08:00
|
|
|
availablePackage al;
|
2001-10-30 04:12:35 +08:00
|
|
|
al = alAddPackage(ts->availablePackages, -1, h, key, NULL, NULL);
|
1999-08-21 05:05:18 +08:00
|
|
|
}
|
|
|
|
|
2001-07-07 04:37:42 +08:00
|
|
|
int rpmtransRemovePackage(rpmTransactionSet ts, int dboffset)
|
1999-08-21 05:05:18 +08:00
|
|
|
{
|
2001-07-07 04:37:42 +08:00
|
|
|
return removePackage(ts, dboffset, -1);
|
1999-08-21 05:05:18 +08:00
|
|
|
}
|
|
|
|
|
2001-10-26 12:16:19 +08:00
|
|
|
/*@-nullstate@*/ /* FIX: better annotations */
|
2001-10-24 21:48:55 +08:00
|
|
|
void rpmtransClean(rpmTransactionSet ts)
|
1999-08-21 05:05:18 +08:00
|
|
|
{
|
2001-07-07 04:37:42 +08:00
|
|
|
if (ts) {
|
2001-10-24 04:52:51 +08:00
|
|
|
HFD_t hfd = headerFreeData;
|
2001-10-25 09:36:32 +08:00
|
|
|
if (ts->sig != NULL)
|
|
|
|
ts->sig = hfd(ts->sig, ts->sigtype);
|
|
|
|
if (ts->dig != NULL)
|
|
|
|
ts->dig = pgpFreeDig(ts->dig);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
rpmTransactionSet rpmtransFree(rpmTransactionSet ts)
|
|
|
|
{
|
2001-10-29 06:17:47 +08:00
|
|
|
if (ts) {
|
|
|
|
|
|
|
|
(void) rpmtsUnlink(ts, "tsCreate");
|
|
|
|
|
|
|
|
/*@-usereleased@*/
|
|
|
|
if (ts->nrefs > 0)
|
|
|
|
return NULL;
|
2001-10-25 09:36:32 +08:00
|
|
|
|
2001-10-30 04:12:35 +08:00
|
|
|
ts->addedPackages = alFree(ts->addedPackages);
|
|
|
|
ts->availablePackages = alFree(ts->availablePackages);
|
2001-07-07 04:37:42 +08:00
|
|
|
ts->di = _free(ts->di);
|
|
|
|
ts->removedPackages = _free(ts->removedPackages);
|
|
|
|
ts->order = _free(ts->order);
|
2001-10-17 01:42:18 +08:00
|
|
|
/*@-type@*/ /* FIX: cast? */
|
2001-10-24 21:48:55 +08:00
|
|
|
if (ts->scriptFd != NULL) {
|
2001-07-07 04:37:42 +08:00
|
|
|
ts->scriptFd =
|
|
|
|
fdFree(ts->scriptFd, "rpmtransSetScriptFd (rpmtransFree");
|
2001-10-24 21:48:55 +08:00
|
|
|
ts->scriptFd = NULL;
|
|
|
|
}
|
2001-10-17 01:42:18 +08:00
|
|
|
/*@=type@*/
|
2001-07-07 04:37:42 +08:00
|
|
|
ts->rootDir = _free(ts->rootDir);
|
|
|
|
ts->currDir = _free(ts->currDir);
|
|
|
|
|
2001-10-24 21:48:55 +08:00
|
|
|
rpmtransClean(ts);
|
|
|
|
|
2001-10-28 04:09:20 +08:00
|
|
|
(void) rpmtsCloseDB(ts);
|
2001-10-24 04:52:51 +08:00
|
|
|
|
2001-10-28 06:31:10 +08:00
|
|
|
/*@-refcounttrans@*/ ts = _free(ts); /*@=refcounttrans@*/
|
2001-10-29 06:17:47 +08:00
|
|
|
/*@=usereleased@*/
|
2001-07-07 04:37:42 +08:00
|
|
|
}
|
|
|
|
return NULL;
|
1999-08-21 05:05:18 +08:00
|
|
|
}
|
2001-10-26 12:16:19 +08:00
|
|
|
/*@=nullstate@*/
|
1999-08-21 05:05:18 +08:00
|
|
|
|
2001-06-01 06:31:14 +08:00
|
|
|
rpmDependencyConflict rpmdepFreeConflicts(rpmDependencyConflict conflicts,
|
|
|
|
int numConflicts)
|
1999-08-21 05:05:18 +08:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
2001-06-01 06:31:14 +08:00
|
|
|
if (conflicts)
|
1999-08-21 05:05:18 +08:00
|
|
|
for (i = 0; i < numConflicts; i++) {
|
2001-05-23 22:25:19 +08:00
|
|
|
conflicts[i].byHeader = headerFree(conflicts[i].byHeader);
|
2001-04-21 14:02:09 +08:00
|
|
|
conflicts[i].byName = _free(conflicts[i].byName);
|
|
|
|
conflicts[i].byVersion = _free(conflicts[i].byVersion);
|
|
|
|
conflicts[i].byRelease = _free(conflicts[i].byRelease);
|
|
|
|
conflicts[i].needsName = _free(conflicts[i].needsName);
|
|
|
|
conflicts[i].needsVersion = _free(conflicts[i].needsVersion);
|
2001-06-01 06:31:14 +08:00
|
|
|
conflicts[i].suggestedPackages = _free(conflicts[i].suggestedPackages);
|
1999-08-21 05:05:18 +08:00
|
|
|
}
|
|
|
|
|
2001-06-01 06:31:14 +08:00
|
|
|
return (conflicts = _free(conflicts));
|
1999-08-21 05:05:18 +08:00
|
|
|
}
|
|
|
|
|
2001-06-01 06:31:14 +08:00
|
|
|
/**
|
|
|
|
* 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
|
|
|
|
*/
|
2001-10-29 06:17:47 +08:00
|
|
|
static inline /*@only@*/ /*@null@*/ availablePackage
|
2001-06-01 06:31:14 +08:00
|
|
|
alSatisfiesDepend(const availableList al,
|
|
|
|
const char * keyType, const char * keyDepend,
|
|
|
|
const char * keyName, const char * keyEVR, int keyFlags)
|
|
|
|
/*@*/
|
|
|
|
{
|
2001-10-29 06:17:47 +08:00
|
|
|
availablePackage ret;
|
|
|
|
availablePackage * tmp =
|
2001-06-01 06:31:14 +08:00
|
|
|
alAllSatisfiesDepend(al, keyType, keyDepend, keyName, keyEVR, keyFlags);
|
|
|
|
|
|
|
|
if (tmp) {
|
|
|
|
ret = tmp[0];
|
|
|
|
tmp = _free(tmp);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2000-08-23 20:39:49 +08:00
|
|
|
/**
|
|
|
|
* Check key for an unsatisfied dependency.
|
2001-06-01 06:31:14 +08:00
|
|
|
* @todo Eliminate rpmrc provides.
|
2000-08-23 20:39:49 +08:00
|
|
|
* @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
|
2001-06-01 06:31:14 +08:00
|
|
|
* @retval suggestion possible package(s) to resolve dependency
|
2000-08-23 20:39:49 +08:00
|
|
|
* @return 0 if satisfied, 1 if not satisfied, 2 if error
|
|
|
|
*/
|
2001-01-16 07:09:42 +08:00
|
|
|
static int unsatisfiedDepend(rpmTransactionSet ts,
|
2001-06-01 06:31:14 +08:00
|
|
|
const char * keyType, const char * keyDepend,
|
|
|
|
const char * keyName, const char * keyEVR, int keyFlags,
|
2001-10-29 06:17:47 +08:00
|
|
|
/*@null@*/ /*@out@*/ availablePackage ** suggestion)
|
2001-10-18 00:43:36 +08:00
|
|
|
/*@globals _cacheDependsRC, fileSystem @*/
|
|
|
|
/*@modifies ts, *suggestion, _cacheDependsRC, fileSystem @*/
|
1999-07-14 06:00:05 +08:00
|
|
|
{
|
2000-04-14 00:00:34 +08:00
|
|
|
rpmdbMatchIterator mi;
|
|
|
|
Header h;
|
1999-09-19 08:29:44 +08:00
|
|
|
int rc = 0; /* assume dependency is satisfied */
|
1999-09-18 05:08:32 +08:00
|
|
|
|
1996-07-18 10:25:13 +08:00
|
|
|
if (suggestion) *suggestion = NULL;
|
|
|
|
|
2000-05-02 16:30:31 +08:00
|
|
|
/*
|
|
|
|
* Check if dbiOpen/dbiPut failed (e.g. permissions), we can't cache.
|
|
|
|
*/
|
|
|
|
if (_cacheDependsRC) {
|
2000-05-07 08:53:11 +08:00
|
|
|
dbiIndex dbi;
|
2001-01-16 07:09:42 +08:00
|
|
|
dbi = dbiOpen(ts->rpmdb, RPMDBI_DEPENDS, 0);
|
2000-05-07 08:53:11 +08:00
|
|
|
if (dbi == NULL)
|
|
|
|
_cacheDependsRC = 0;
|
|
|
|
else {
|
2000-06-13 06:07:13 +08:00
|
|
|
DBC * dbcursor = NULL;
|
2000-05-07 08:53:11 +08:00
|
|
|
size_t keylen = strlen(keyDepend);
|
|
|
|
void * datap = NULL;
|
|
|
|
size_t datalen = 0;
|
|
|
|
int xx;
|
2000-06-13 06:07:13 +08:00
|
|
|
xx = dbiCopen(dbi, &dbcursor, 0);
|
2001-06-04 21:55:58 +08:00
|
|
|
/*@-mods@*/ /* FIX: keyDepends mod undocumented. */
|
2000-06-13 06:07:13 +08:00
|
|
|
xx = dbiGet(dbi, dbcursor, (void **)&keyDepend, &keylen, &datap, &datalen, 0);
|
2001-06-04 21:55:58 +08:00
|
|
|
/*@=mods@*/
|
2000-05-07 08:53:11 +08:00
|
|
|
if (xx == 0 && datap && datalen == 4) {
|
|
|
|
memcpy(&rc, datap, datalen);
|
2001-04-21 14:02:09 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, _("%s: %-45s %-s (cached)\n"),
|
|
|
|
keyType, keyDepend, (rc ? _("NO ") : _("YES")));
|
2000-05-07 08:53:11 +08:00
|
|
|
xx = dbiCclose(dbi, NULL, 0);
|
2001-06-01 06:31:14 +08:00
|
|
|
|
|
|
|
if (suggestion && rc == 1)
|
2001-10-30 04:12:35 +08:00
|
|
|
*suggestion = alAllSatisfiesDepend(ts->availablePackages,
|
2001-06-01 06:31:14 +08:00
|
|
|
NULL, NULL, keyName, keyEVR, keyFlags);
|
|
|
|
|
2000-05-07 08:53:11 +08:00
|
|
|
return rc;
|
|
|
|
}
|
2000-06-13 06:07:13 +08:00
|
|
|
xx = dbiCclose(dbi, dbcursor, 0);
|
2000-04-26 03:41:37 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-10-18 00:43:36 +08:00
|
|
|
#if defined(DYING) || defined(__LCLINT__)
|
2001-05-17 03:19:15 +08:00
|
|
|
{ static /*@observer@*/ const char noProvidesString[] = "nada";
|
|
|
|
static /*@observer@*/ const char * rcProvidesString = noProvidesString;
|
1999-09-12 05:10:02 +08:00
|
|
|
const char * start;
|
2000-08-23 20:39:49 +08:00
|
|
|
int i;
|
2000-04-14 00:00:34 +08:00
|
|
|
|
2001-05-17 03:19:15 +08:00
|
|
|
if (rcProvidesString == noProvidesString)
|
|
|
|
rcProvidesString = rpmGetVar(RPMVAR_PROVIDES);
|
|
|
|
|
|
|
|
if (rcProvidesString != NULL && !(keyFlags & RPMSENSE_SENSEMASK)) {
|
1999-09-14 13:41:13 +08:00
|
|
|
i = strlen(keyName);
|
2001-05-17 03:19:15 +08:00
|
|
|
/*@-observertrans -mayaliasunique@*/
|
1999-09-14 13:41:13 +08:00
|
|
|
while ((start = strstr(rcProvidesString, keyName))) {
|
2001-05-17 03:19:15 +08:00
|
|
|
/*@=observertrans =mayaliasunique@*/
|
2001-04-29 09:05:43 +08:00
|
|
|
if (xisspace(start[i]) || start[i] == '\0' || start[i] == ',') {
|
2000-05-07 08:53:11 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, _("%s: %-45s YES (rpmrc provides)\n"),
|
|
|
|
keyType, keyDepend+2);
|
1999-09-19 08:29:44 +08:00
|
|
|
goto exit;
|
1999-09-24 22:54:23 +08:00
|
|
|
}
|
1998-07-01 02:52:54 +08:00
|
|
|
rcProvidesString = start + 1;
|
1997-07-24 02:32:15 +08:00
|
|
|
}
|
|
|
|
}
|
1999-09-12 05:10:02 +08:00
|
|
|
}
|
2000-08-23 20:39:49 +08:00
|
|
|
#endif
|
1997-07-24 02:32:15 +08:00
|
|
|
|
2000-07-14 07:30:41 +08:00
|
|
|
/*
|
|
|
|
* New features in rpm packaging implicitly add versioned dependencies
|
|
|
|
* on rpmlib provides. The dependencies look like "rpmlib(YaddaYadda)".
|
|
|
|
* Check those dependencies now.
|
|
|
|
*/
|
2001-02-05 06:15:30 +08:00
|
|
|
if (!strncmp(keyName, "rpmlib(", sizeof("rpmlib(")-1)) {
|
2000-07-14 07:30:41 +08:00
|
|
|
if (rpmCheckRpmlibProvides(keyName, keyEVR, keyFlags)) {
|
|
|
|
rpmMessage(RPMMESS_DEBUG, _("%s: %-45s YES (rpmlib provides)\n"),
|
|
|
|
keyType, keyDepend+2);
|
|
|
|
goto exit;
|
|
|
|
}
|
2000-11-01 02:24:05 +08:00
|
|
|
goto unsatisfied;
|
2000-07-14 07:30:41 +08:00
|
|
|
}
|
|
|
|
|
2001-10-30 04:12:35 +08:00
|
|
|
if (alSatisfiesDepend(ts->addedPackages, keyType, keyDepend,
|
2001-06-01 06:31:14 +08:00
|
|
|
keyName, keyEVR, keyFlags))
|
|
|
|
{
|
1999-09-19 08:29:44 +08:00
|
|
|
goto exit;
|
1999-09-24 22:54:23 +08:00
|
|
|
}
|
1996-06-10 10:36:07 +08:00
|
|
|
|
2000-07-17 08:40:17 +08:00
|
|
|
/* XXX only the installer does not have the database open here. */
|
2001-01-16 07:09:42 +08:00
|
|
|
if (ts->rpmdb != NULL) {
|
1999-09-14 13:41:13 +08:00
|
|
|
if (*keyName == '/') {
|
|
|
|
/* keyFlags better be 0! */
|
1997-05-01 03:28:09 +08:00
|
|
|
|
2001-10-28 04:09:20 +08:00
|
|
|
mi = rpmtsInitIterator(ts, RPMTAG_BASENAMES, keyName, 0);
|
2000-05-07 08:53:11 +08:00
|
|
|
|
2001-05-01 06:32:22 +08:00
|
|
|
(void) rpmdbPruneIterator(mi,
|
2001-01-16 07:09:42 +08:00
|
|
|
ts->removedPackages, ts->numRemovedPackages, 1);
|
2000-05-07 08:53:11 +08:00
|
|
|
|
2000-04-14 00:00:34 +08:00
|
|
|
while ((h = rpmdbNextIterator(mi)) != NULL) {
|
2000-05-07 08:53:11 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, _("%s: %-45s YES (db files)\n"),
|
|
|
|
keyType, keyDepend+2);
|
2001-04-30 06:43:01 +08:00
|
|
|
mi = rpmdbFreeIterator(mi);
|
1999-09-24 22:54:23 +08:00
|
|
|
goto exit;
|
|
|
|
}
|
2001-04-30 06:43:01 +08:00
|
|
|
mi = rpmdbFreeIterator(mi);
|
1996-07-18 10:25:13 +08:00
|
|
|
}
|
2000-04-13 18:11:32 +08:00
|
|
|
|
2001-10-28 04:09:20 +08:00
|
|
|
mi = rpmtsInitIterator(ts, RPMTAG_PROVIDENAME, keyName, 0);
|
2001-05-01 06:32:22 +08:00
|
|
|
(void) rpmdbPruneIterator(mi,
|
2001-01-16 07:09:42 +08:00
|
|
|
ts->removedPackages, ts->numRemovedPackages, 1);
|
2000-04-14 00:00:34 +08:00
|
|
|
while ((h = rpmdbNextIterator(mi)) != NULL) {
|
2000-05-07 08:53:11 +08:00
|
|
|
if (rangeMatchesDepFlags(h, keyName, keyEVR, keyFlags)) {
|
|
|
|
rpmMessage(RPMMESS_DEBUG, _("%s: %-45s YES (db provides)\n"),
|
|
|
|
keyType, keyDepend+2);
|
2001-04-30 06:43:01 +08:00
|
|
|
mi = rpmdbFreeIterator(mi);
|
2000-05-07 08:53:11 +08:00
|
|
|
goto exit;
|
|
|
|
}
|
2000-04-14 00:00:34 +08:00
|
|
|
}
|
2001-04-30 06:43:01 +08:00
|
|
|
mi = rpmdbFreeIterator(mi);
|
2000-12-13 04:03:45 +08:00
|
|
|
|
2001-10-19 09:24:21 +08:00
|
|
|
#if defined(DYING) || defined(__LCLINT__)
|
2001-10-28 04:09:20 +08:00
|
|
|
mi = rpmtsInitIterator(ts, RPMTAG_NAME, keyName, 0);
|
2001-05-01 06:32:22 +08:00
|
|
|
(void) rpmdbPruneIterator(mi,
|
2001-01-16 07:09:42 +08:00
|
|
|
ts->removedPackages, ts->numRemovedPackages, 1);
|
2000-12-13 04:03:45 +08:00
|
|
|
while ((h = rpmdbNextIterator(mi)) != NULL) {
|
|
|
|
if (rangeMatchesDepFlags(h, keyName, keyEVR, keyFlags)) {
|
|
|
|
rpmMessage(RPMMESS_DEBUG, _("%s: %-45s YES (db package)\n"),
|
|
|
|
keyType, keyDepend+2);
|
2001-04-30 06:43:01 +08:00
|
|
|
mi = rpmdbFreeIterator(mi);
|
2000-12-13 04:03:45 +08:00
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
}
|
2001-04-30 06:43:01 +08:00
|
|
|
mi = rpmdbFreeIterator(mi);
|
2000-12-13 04:03:45 +08:00
|
|
|
#endif
|
|
|
|
|
1996-06-10 10:36:07 +08:00
|
|
|
}
|
|
|
|
|
1999-09-18 05:08:32 +08:00
|
|
|
if (suggestion)
|
2001-10-30 04:12:35 +08:00
|
|
|
*suggestion = alAllSatisfiesDepend(ts->availablePackages, NULL, NULL,
|
1999-09-24 22:54:23 +08:00
|
|
|
keyName, keyEVR, keyFlags);
|
1996-07-18 10:25:13 +08:00
|
|
|
|
2000-11-01 02:24:05 +08:00
|
|
|
unsatisfied:
|
2000-05-07 08:53:11 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, _("%s: %-45s NO\n"), keyType, keyDepend+2);
|
1999-09-19 08:29:44 +08:00
|
|
|
rc = 1; /* dependency is unsatisfied */
|
|
|
|
|
|
|
|
exit:
|
2000-05-02 16:30:31 +08:00
|
|
|
/*
|
|
|
|
* If dbiOpen/dbiPut fails (e.g. permissions), we can't cache.
|
|
|
|
*/
|
|
|
|
if (_cacheDependsRC) {
|
|
|
|
dbiIndex dbi;
|
2001-01-16 07:09:42 +08:00
|
|
|
dbi = dbiOpen(ts->rpmdb, RPMDBI_DEPENDS, 0);
|
2000-05-02 16:30:31 +08:00
|
|
|
if (dbi == NULL) {
|
|
|
|
_cacheDependsRC = 0;
|
|
|
|
} else {
|
2000-06-13 06:07:13 +08:00
|
|
|
DBC * dbcursor = NULL;
|
2000-04-28 23:14:47 +08:00
|
|
|
int xx;
|
2001-05-11 12:01:04 +08:00
|
|
|
xx = dbiCopen(dbi, &dbcursor, DBI_WRITECURSOR);
|
2000-06-13 06:07:13 +08:00
|
|
|
xx = dbiPut(dbi, dbcursor, keyDepend, strlen(keyDepend), &rc, sizeof(rc), 0);
|
2000-05-07 08:53:11 +08:00
|
|
|
if (xx)
|
2000-05-02 16:30:31 +08:00
|
|
|
_cacheDependsRC = 0;
|
2000-05-07 08:53:11 +08:00
|
|
|
#if 0 /* XXX NOISY */
|
|
|
|
else
|
2001-04-21 14:02:09 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, _("%s: (%s, %s) added to Depends cache.\n"), keyType, keyDepend, (rc ? _("NO ") : _("YES")));
|
2000-05-07 08:53:11 +08:00
|
|
|
#endif
|
2001-05-11 12:01:04 +08:00
|
|
|
xx = dbiCclose(dbi, dbcursor, DBI_WRITECURSOR);
|
2000-04-28 23:14:47 +08:00
|
|
|
}
|
2000-04-26 03:41:37 +08:00
|
|
|
}
|
1999-09-19 08:29:44 +08:00
|
|
|
return rc;
|
1996-06-10 10:36:07 +08:00
|
|
|
}
|
1996-06-11 01:42:57 +08:00
|
|
|
|
2001-06-01 06:31:14 +08:00
|
|
|
/**
|
|
|
|
* Check header requires/conflicts against against installed+added packages.
|
|
|
|
* @param ts transaction set
|
|
|
|
* @param psp dependency problems
|
|
|
|
* @param h header to check
|
|
|
|
* @param keyName dependency name
|
|
|
|
* @param multiLib skip multilib colored dependencies?
|
|
|
|
* @return 0 no problems found
|
|
|
|
*/
|
|
|
|
static int checkPackageDeps(rpmTransactionSet ts, problemsSet psp,
|
2000-07-06 04:39:15 +08:00
|
|
|
Header h, const char * keyName, uint_32 multiLib)
|
2001-10-15 11:22:10 +08:00
|
|
|
/*@globals fileSystem @*/
|
|
|
|
/*@modifies ts, h, psp, fileSystem */
|
1999-07-14 06:00:05 +08:00
|
|
|
{
|
2001-02-05 06:15:30 +08:00
|
|
|
HGE_t hge = (HGE_t)headerGetEntryMinMemory;
|
|
|
|
HFD_t hfd = headerFreeData;
|
2001-06-12 12:10:21 +08:00
|
|
|
rpmTagType rnt, rvt;
|
|
|
|
rpmTagType cnt, cvt;
|
1999-07-23 01:48:31 +08:00
|
|
|
const char * name, * version, * release;
|
2000-09-27 02:04:12 +08:00
|
|
|
const char ** requires;
|
|
|
|
const char ** requiresEVR = NULL;
|
|
|
|
int_32 * requireFlags = NULL;
|
|
|
|
int requiresCount = 0;
|
|
|
|
const char ** conflicts;
|
|
|
|
const char ** conflictsEVR = NULL;
|
|
|
|
int_32 * conflictFlags = NULL;
|
|
|
|
int conflictsCount = 0;
|
2001-06-12 12:10:21 +08:00
|
|
|
rpmTagType type;
|
2001-10-16 22:58:57 +08:00
|
|
|
int i, rc, xx;
|
1996-10-21 03:31:21 +08:00
|
|
|
int ourrc = 0;
|
2001-10-29 06:17:47 +08:00
|
|
|
availablePackage * suggestion;
|
1996-06-11 01:42:57 +08:00
|
|
|
|
2001-10-16 22:58:57 +08:00
|
|
|
xx = headerNVR(h, &name, &version, &release);
|
1999-09-19 08:29:44 +08:00
|
|
|
|
2001-04-21 14:02:09 +08:00
|
|
|
if (!hge(h, RPMTAG_REQUIRENAME, &rnt, (void **) &requires, &requiresCount))
|
|
|
|
{
|
1996-10-21 03:31:21 +08:00
|
|
|
requiresCount = 0;
|
2001-04-29 09:05:43 +08:00
|
|
|
rvt = RPM_STRING_ARRAY_TYPE;
|
1996-10-21 03:31:21 +08:00
|
|
|
} else {
|
2001-10-16 22:58:57 +08:00
|
|
|
xx = hge(h, RPMTAG_REQUIREFLAGS, NULL, (void **) &requireFlags, NULL);
|
|
|
|
xx = hge(h, RPMTAG_REQUIREVERSION, &rvt, (void **) &requiresEVR, NULL);
|
1996-10-21 03:31:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < requiresCount && !ourrc; i++) {
|
2001-04-21 14:02:09 +08:00
|
|
|
const char * keyDepend;
|
1999-09-14 13:41:13 +08:00
|
|
|
|
1999-09-19 08:29:44 +08:00
|
|
|
/* Filter out requires that came along for the ride. */
|
|
|
|
if (keyName && strcmp(keyName, requires[i]))
|
|
|
|
continue;
|
|
|
|
|
2000-07-06 04:39:15 +08:00
|
|
|
/* If this requirement comes from the core package only, not libraries,
|
|
|
|
then if we're installing the libraries only, don't count it in. */
|
|
|
|
if (multiLib && !isDependsMULTILIB(requireFlags[i]))
|
|
|
|
continue;
|
|
|
|
|
2001-06-13 01:06:47 +08:00
|
|
|
keyDepend = printDepend("R",
|
|
|
|
requires[i], requiresEVR[i], requireFlags[i]);
|
1996-06-11 01:42:57 +08:00
|
|
|
|
2001-01-16 07:09:42 +08:00
|
|
|
rc = unsatisfiedDepend(ts, " Requires", keyDepend,
|
1999-09-25 02:03:20 +08:00
|
|
|
requires[i], requiresEVR[i], requireFlags[i], &suggestion);
|
1999-09-14 13:41:13 +08:00
|
|
|
|
|
|
|
switch (rc) {
|
1999-09-19 08:29:44 +08:00
|
|
|
case 0: /* requirements are satisfied. */
|
2001-10-14 06:01:38 +08:00
|
|
|
/*@switchbreak@*/ break;
|
1999-09-19 08:29:44 +08:00
|
|
|
case 1: /* requirements are not satisfied. */
|
2000-07-10 07:10:25 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, _("package %s-%s-%s require not satisfied: %s\n"),
|
|
|
|
name, version, release, keyDepend+2);
|
1999-09-18 05:08:32 +08:00
|
|
|
|
1996-06-11 01:42:57 +08:00
|
|
|
if (psp->num == psp->alloced) {
|
|
|
|
psp->alloced += 5;
|
1999-09-21 11:22:53 +08:00
|
|
|
psp->problems = xrealloc(psp->problems, sizeof(*psp->problems) *
|
1996-06-11 01:42:57 +08:00
|
|
|
psp->alloced);
|
|
|
|
}
|
2001-06-13 01:06:47 +08:00
|
|
|
|
|
|
|
{ rpmDependencyConflict pp = psp->problems + psp->num;
|
|
|
|
pp->byHeader = headerLink(h);
|
|
|
|
pp->byName = xstrdup(name);
|
|
|
|
pp->byVersion = xstrdup(version);
|
|
|
|
pp->byRelease = xstrdup(release);
|
|
|
|
pp->needsName = xstrdup(requires[i]);
|
|
|
|
pp->needsVersion = xstrdup(requiresEVR[i]);
|
|
|
|
pp->needsFlags = requireFlags[i];
|
|
|
|
pp->sense = RPMDEP_SENSE_REQUIRES;
|
|
|
|
|
|
|
|
if (suggestion) {
|
|
|
|
int j;
|
|
|
|
for (j = 0; suggestion[j]; j++)
|
|
|
|
{};
|
|
|
|
pp->suggestedPackages =
|
|
|
|
xmalloc( (j + 1) * sizeof(*pp->suggestedPackages) );
|
|
|
|
for (j = 0; suggestion[j]; j++)
|
|
|
|
pp->suggestedPackages[j] = suggestion[j]->key;
|
|
|
|
pp->suggestedPackages[j] = NULL;
|
|
|
|
} else {
|
|
|
|
pp->suggestedPackages = NULL;
|
|
|
|
}
|
2001-06-01 06:31:14 +08:00
|
|
|
}
|
1996-07-11 00:29:24 +08:00
|
|
|
|
1996-06-11 01:42:57 +08:00
|
|
|
psp->num++;
|
2001-10-14 06:01:38 +08:00
|
|
|
/*@switchbreak@*/ break;
|
1999-09-14 13:41:13 +08:00
|
|
|
case 2: /* something went wrong! */
|
|
|
|
default:
|
1996-10-21 03:31:21 +08:00
|
|
|
ourrc = 1;
|
2001-10-14 06:01:38 +08:00
|
|
|
/*@switchbreak@*/ break;
|
1996-06-11 01:42:57 +08:00
|
|
|
}
|
2001-04-21 14:02:09 +08:00
|
|
|
keyDepend = _free(keyDepend);
|
1999-09-19 08:29:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (requiresCount) {
|
2001-02-05 06:15:30 +08:00
|
|
|
requiresEVR = hfd(requiresEVR, rvt);
|
|
|
|
requires = hfd(requires, rnt);
|
1999-09-19 08:29:44 +08:00
|
|
|
}
|
|
|
|
|
2001-02-05 06:15:30 +08:00
|
|
|
if (!hge(h, RPMTAG_CONFLICTNAME, &cnt, (void **)&conflicts, &conflictsCount))
|
|
|
|
{
|
1999-09-19 08:29:44 +08:00
|
|
|
conflictsCount = 0;
|
2001-04-29 09:05:43 +08:00
|
|
|
cvt = RPM_STRING_ARRAY_TYPE;
|
1999-09-19 08:29:44 +08:00
|
|
|
} else {
|
2001-10-16 22:58:57 +08:00
|
|
|
xx = hge(h, RPMTAG_CONFLICTFLAGS, &type,
|
1999-09-19 08:29:44 +08:00
|
|
|
(void **) &conflictFlags, &conflictsCount);
|
2001-10-16 22:58:57 +08:00
|
|
|
xx = hge(h, RPMTAG_CONFLICTVERSION, &cvt,
|
1999-09-19 08:29:44 +08:00
|
|
|
(void **) &conflictsEVR, &conflictsCount);
|
1996-06-11 01:42:57 +08:00
|
|
|
}
|
|
|
|
|
1996-10-21 03:31:21 +08:00
|
|
|
for (i = 0; i < conflictsCount && !ourrc; i++) {
|
2001-04-21 14:02:09 +08:00
|
|
|
const char * keyDepend;
|
1999-09-14 13:41:13 +08:00
|
|
|
|
1999-09-19 08:29:44 +08:00
|
|
|
/* Filter out conflicts that came along for the ride. */
|
|
|
|
if (keyName && strcmp(keyName, conflicts[i]))
|
|
|
|
continue;
|
|
|
|
|
2000-07-06 04:39:15 +08:00
|
|
|
/* If this requirement comes from the core package only, not libraries,
|
|
|
|
then if we're installing the libraries only, don't count it in. */
|
|
|
|
if (multiLib && !isDependsMULTILIB(conflictFlags[i]))
|
|
|
|
continue;
|
|
|
|
|
2000-04-26 03:41:37 +08:00
|
|
|
keyDepend = printDepend("C", conflicts[i], conflictsEVR[i], conflictFlags[i]);
|
1996-06-11 01:42:57 +08:00
|
|
|
|
2001-01-16 07:09:42 +08:00
|
|
|
rc = unsatisfiedDepend(ts, "Conflicts", keyDepend,
|
1999-09-25 02:03:20 +08:00
|
|
|
conflicts[i], conflictsEVR[i], conflictFlags[i], NULL);
|
1996-10-21 03:31:21 +08:00
|
|
|
|
|
|
|
/* 1 == unsatisfied, 0 == satsisfied */
|
1999-09-14 13:41:13 +08:00
|
|
|
switch (rc) {
|
1999-09-19 08:29:44 +08:00
|
|
|
case 0: /* conflicts exist. */
|
1998-09-28 06:03:52 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, _("package %s conflicts: %s\n"),
|
2000-05-07 08:53:11 +08:00
|
|
|
name, keyDepend+2);
|
1999-09-18 05:08:32 +08:00
|
|
|
|
1996-10-21 03:31:21 +08:00
|
|
|
if (psp->num == psp->alloced) {
|
|
|
|
psp->alloced += 5;
|
2001-02-05 06:15:30 +08:00
|
|
|
psp->problems = xrealloc(psp->problems,
|
|
|
|
sizeof(*psp->problems) * psp->alloced);
|
1996-10-21 03:31:21 +08:00
|
|
|
}
|
2001-06-13 01:06:47 +08:00
|
|
|
|
|
|
|
{ rpmDependencyConflict pp = psp->problems + psp->num;
|
|
|
|
pp->byHeader = headerLink(h);
|
|
|
|
pp->byName = xstrdup(name);
|
|
|
|
pp->byVersion = xstrdup(version);
|
|
|
|
pp->byRelease = xstrdup(release);
|
|
|
|
pp->needsName = xstrdup(conflicts[i]);
|
|
|
|
pp->needsVersion = xstrdup(conflictsEVR[i]);
|
|
|
|
pp->needsFlags = conflictFlags[i];
|
|
|
|
pp->sense = RPMDEP_SENSE_CONFLICTS;
|
|
|
|
pp->suggestedPackages = NULL;
|
|
|
|
}
|
1996-10-21 03:31:21 +08:00
|
|
|
|
|
|
|
psp->num++;
|
2001-10-14 06:01:38 +08:00
|
|
|
/*@switchbreak@*/ break;
|
1999-09-19 08:29:44 +08:00
|
|
|
case 1: /* conflicts don't exist. */
|
2001-10-14 06:01:38 +08:00
|
|
|
/*@switchbreak@*/ break;
|
1999-09-14 13:41:13 +08:00
|
|
|
case 2: /* something went wrong! */
|
|
|
|
default:
|
1996-10-21 03:31:21 +08:00
|
|
|
ourrc = 1;
|
2001-10-14 06:01:38 +08:00
|
|
|
/*@switchbreak@*/ break;
|
1996-10-21 03:31:21 +08:00
|
|
|
}
|
2001-04-21 14:02:09 +08:00
|
|
|
keyDepend = _free(keyDepend);
|
1996-10-21 03:31:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (conflictsCount) {
|
2001-02-05 06:15:30 +08:00
|
|
|
conflictsEVR = hfd(conflictsEVR, cvt);
|
|
|
|
conflicts = hfd(conflicts, cnt);
|
1996-10-21 03:31:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return ourrc;
|
1996-06-11 01:42:57 +08:00
|
|
|
}
|
|
|
|
|
2000-09-27 02:04:12 +08:00
|
|
|
/**
|
2001-06-01 06:31:14 +08:00
|
|
|
* Check dependency against installed packages.
|
2000-09-27 02:04:12 +08:00
|
|
|
* Adding: check name/provides key against each conflict match,
|
|
|
|
* Erasing: check name/provides/filename key against each requiredby match.
|
2001-06-01 06:31:14 +08:00
|
|
|
* @param ts transaction set
|
|
|
|
* @param psp dependency problems
|
|
|
|
* @param key dependency name
|
|
|
|
* @param mi rpm database iterator
|
|
|
|
* @return 0 no problems found
|
2000-09-27 02:04:12 +08:00
|
|
|
*/
|
2001-06-01 06:31:14 +08:00
|
|
|
static int checkPackageSet(rpmTransactionSet ts, problemsSet psp,
|
|
|
|
const char * key, /*@only@*/ /*@null@*/ rpmdbMatchIterator mi)
|
2001-10-15 11:22:10 +08:00
|
|
|
/*@globals fileSystem @*/
|
|
|
|
/*@modifies ts, mi, psp, fileSystem @*/
|
1999-07-14 06:00:05 +08:00
|
|
|
{
|
|
|
|
Header h;
|
2000-04-13 18:11:32 +08:00
|
|
|
int rc = 0;
|
1999-07-14 06:00:05 +08:00
|
|
|
|
2001-05-01 06:32:22 +08:00
|
|
|
(void) rpmdbPruneIterator(mi,
|
|
|
|
ts->removedPackages, ts->numRemovedPackages, 1);
|
2000-04-13 18:11:32 +08:00
|
|
|
while ((h = rpmdbNextIterator(mi)) != NULL) {
|
2001-01-16 07:09:42 +08:00
|
|
|
if (checkPackageDeps(ts, psp, h, key, 0)) {
|
2000-04-13 18:11:32 +08:00
|
|
|
rc = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2001-04-30 06:43:01 +08:00
|
|
|
mi = rpmdbFreeIterator(mi);
|
2000-04-13 18:11:32 +08:00
|
|
|
|
|
|
|
return rc;
|
1999-07-14 06:00:05 +08:00
|
|
|
}
|
|
|
|
|
2000-09-27 02:04:12 +08:00
|
|
|
/**
|
|
|
|
* Erasing: check name/provides/filename key against requiredby matches.
|
2001-06-01 06:31:14 +08:00
|
|
|
* @param ts transaction set
|
|
|
|
* @param psp dependency problems
|
|
|
|
* @param key requires name
|
|
|
|
* @return 0 no problems found
|
2000-09-27 02:04:12 +08:00
|
|
|
*/
|
2001-01-16 07:09:42 +08:00
|
|
|
static int checkDependentPackages(rpmTransactionSet ts,
|
2001-06-01 06:31:14 +08:00
|
|
|
problemsSet psp, const char * key)
|
2001-10-15 11:22:10 +08:00
|
|
|
/*@globals fileSystem @*/
|
|
|
|
/*@modifies ts, psp, fileSystem @*/
|
1999-07-14 06:00:05 +08:00
|
|
|
{
|
2000-04-13 18:11:32 +08:00
|
|
|
rpmdbMatchIterator mi;
|
2001-10-28 04:09:20 +08:00
|
|
|
mi = rpmtsInitIterator(ts, RPMTAG_REQUIRENAME, key, 0);
|
2001-01-16 07:09:42 +08:00
|
|
|
return checkPackageSet(ts, psp, key, mi);
|
1999-07-14 06:00:05 +08:00
|
|
|
}
|
|
|
|
|
2000-09-27 02:04:12 +08:00
|
|
|
/**
|
|
|
|
* Adding: check name/provides key against conflicts matches.
|
2001-06-01 06:31:14 +08:00
|
|
|
* @param ts transaction set
|
|
|
|
* @param psp dependency problems
|
|
|
|
* @param key conflicts name
|
|
|
|
* @return 0 no problems found
|
2000-09-27 02:04:12 +08:00
|
|
|
*/
|
2001-01-16 07:09:42 +08:00
|
|
|
static int checkDependentConflicts(rpmTransactionSet ts,
|
2001-06-01 06:31:14 +08:00
|
|
|
problemsSet psp, const char * key)
|
2001-10-15 11:22:10 +08:00
|
|
|
/*@globals fileSystem @*/
|
|
|
|
/*@modifies ts, psp, fileSystem @*/
|
1999-07-14 06:00:05 +08:00
|
|
|
{
|
2000-03-23 23:49:50 +08:00
|
|
|
int rc = 0;
|
1999-07-14 06:00:05 +08:00
|
|
|
|
2001-01-16 07:09:42 +08:00
|
|
|
if (ts->rpmdb) { /* XXX is this necessary? */
|
2000-04-13 18:11:32 +08:00
|
|
|
rpmdbMatchIterator mi;
|
2001-10-28 04:09:20 +08:00
|
|
|
mi = rpmtsInitIterator(ts, RPMTAG_CONFLICTNAME, key, 0);
|
2001-01-16 07:09:42 +08:00
|
|
|
rc = checkPackageSet(ts, psp, key, mi);
|
2000-03-23 23:49:50 +08:00
|
|
|
}
|
1999-07-14 06:00:05 +08:00
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2000-11-12 19:11:49 +08:00
|
|
|
/*
|
|
|
|
* XXX Hack to remove known Red Hat dependency loops, will be removed
|
2000-12-21 05:08:18 +08:00
|
|
|
* as soon as rpm's legacy permits.
|
2000-11-12 19:11:49 +08:00
|
|
|
*/
|
|
|
|
#define DEPENDENCY_WHITEOUT
|
|
|
|
|
|
|
|
#if defined(DEPENDENCY_WHITEOUT)
|
2001-10-15 11:22:10 +08:00
|
|
|
/*@observer@*/ /*@unchecked@*/
|
2000-09-27 02:04:12 +08:00
|
|
|
static struct badDeps_s {
|
2001-06-06 03:26:22 +08:00
|
|
|
/*@observer@*/ /*@null@*/ const char * pname;
|
|
|
|
/*@observer@*/ /*@null@*/ const char * qname;
|
2000-09-27 02:04:12 +08:00
|
|
|
} badDeps[] = {
|
|
|
|
{ "libtermcap", "bash" },
|
|
|
|
{ "modutils", "vixie-cron" },
|
|
|
|
{ "ypbind", "yp-tools" },
|
|
|
|
{ "ghostscript-fonts", "ghostscript" },
|
2001-08-29 04:33:06 +08:00
|
|
|
/* 7.2 only */
|
|
|
|
{ "libgnomeprint15", "gnome-print" },
|
|
|
|
{ "nautilus", "nautilus-mozilla" },
|
2000-12-21 05:08:18 +08:00
|
|
|
/* 7.1 only */
|
2001-01-17 05:54:59 +08:00
|
|
|
{ "arts", "kdelibs-sound" },
|
2000-11-12 19:11:49 +08:00
|
|
|
/* 7.0 only */
|
|
|
|
{ "pango-gtkbeta-devel", "pango-gtkbeta" },
|
|
|
|
{ "XFree86", "Mesa" },
|
|
|
|
{ "compat-glibc", "db2" },
|
|
|
|
{ "compat-glibc", "db1" },
|
|
|
|
{ "pam", "initscripts" },
|
|
|
|
{ "initscripts", "sysklogd" },
|
|
|
|
/* 6.2 */
|
|
|
|
{ "egcs-c++", "libstdc++" },
|
|
|
|
/* 6.1 */
|
|
|
|
{ "pilot-link-devel", "pilot-link" },
|
|
|
|
/* 5.2 */
|
|
|
|
{ "pam", "pamconfig" },
|
2000-09-27 02:04:12 +08:00
|
|
|
{ NULL, NULL }
|
|
|
|
};
|
2001-10-28 04:09:20 +08:00
|
|
|
|
2001-10-29 06:17:47 +08:00
|
|
|
static int ignoreDep(const availablePackage p,
|
|
|
|
const availablePackage q)
|
2001-06-01 06:31:14 +08:00
|
|
|
/*@*/
|
1999-07-14 06:00:05 +08:00
|
|
|
{
|
2001-06-06 03:26:22 +08:00
|
|
|
struct badDeps_s * bdp = badDeps;
|
1997-07-02 00:24:08 +08:00
|
|
|
|
2001-06-06 03:26:22 +08:00
|
|
|
while (bdp->pname != NULL && bdp->qname != NULL) {
|
2000-12-21 05:08:18 +08:00
|
|
|
if (!strcmp(p->name, bdp->pname) && !strcmp(q->name, bdp->qname))
|
2000-09-27 02:04:12 +08:00
|
|
|
return 1;
|
2001-06-06 03:26:22 +08:00
|
|
|
bdp++;
|
1997-07-02 00:24:08 +08:00
|
|
|
}
|
2000-09-27 02:04:12 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif
|
1997-07-02 00:24:08 +08:00
|
|
|
|
2000-09-27 02:04:12 +08:00
|
|
|
/**
|
|
|
|
* Recursively mark all nodes with their predecessors.
|
|
|
|
* @param tsi successor chain
|
|
|
|
* @param q predecessor
|
|
|
|
*/
|
2001-10-30 04:12:35 +08:00
|
|
|
static void markLoop(/*@special@*/ tsortInfo tsi, availablePackage q)
|
2001-10-16 01:53:34 +08:00
|
|
|
/*@globals internalState @*/
|
2001-06-06 03:26:22 +08:00
|
|
|
/*@uses tsi @*/
|
|
|
|
/*@modifies internalState @*/
|
2000-09-27 02:04:12 +08:00
|
|
|
{
|
2001-10-29 06:17:47 +08:00
|
|
|
availablePackage p;
|
1999-09-18 05:08:32 +08:00
|
|
|
|
2001-05-04 05:00:18 +08:00
|
|
|
while (tsi != NULL && (p = tsi->tsi_suc) != NULL) {
|
2000-09-27 02:04:12 +08:00
|
|
|
tsi = tsi->tsi_next;
|
|
|
|
if (p->tsi.tsi_pkg != NULL)
|
|
|
|
continue;
|
2001-10-29 06:17:47 +08:00
|
|
|
/*@-assignexpose@*/
|
2000-09-27 02:04:12 +08:00
|
|
|
p->tsi.tsi_pkg = q;
|
2001-10-29 06:17:47 +08:00
|
|
|
/*@=assignexpose@*/
|
2001-05-04 05:00:18 +08:00
|
|
|
if (p->tsi.tsi_next != NULL)
|
|
|
|
markLoop(p->tsi.tsi_next, p);
|
2000-09-27 02:04:12 +08:00
|
|
|
}
|
|
|
|
}
|
1997-07-09 02:41:10 +08:00
|
|
|
|
2001-06-01 06:31:14 +08:00
|
|
|
static inline /*@observer@*/ const char * const identifyDepend(int_32 f)
|
2001-10-14 03:35:58 +08:00
|
|
|
/*@*/
|
2001-06-01 06:31:14 +08:00
|
|
|
{
|
2000-11-12 19:11:49 +08:00
|
|
|
if (isLegacyPreReq(f))
|
|
|
|
return "PreReq:";
|
|
|
|
f = _notpre(f);
|
|
|
|
if (f & RPMSENSE_SCRIPT_PRE)
|
|
|
|
return "Requires(pre):";
|
|
|
|
if (f & RPMSENSE_SCRIPT_POST)
|
|
|
|
return "Requires(post):";
|
|
|
|
if (f & RPMSENSE_SCRIPT_PREUN)
|
|
|
|
return "Requires(preun):";
|
|
|
|
if (f & RPMSENSE_SCRIPT_POSTUN)
|
|
|
|
return "Requires(postun):";
|
|
|
|
if (f & RPMSENSE_SCRIPT_VERIFY)
|
|
|
|
return "Requires(verify):";
|
|
|
|
if (f & RPMSENSE_FIND_REQUIRES)
|
|
|
|
return "Requires(auto):";
|
|
|
|
return "Requires:";
|
|
|
|
}
|
|
|
|
|
2000-09-27 02:04:12 +08:00
|
|
|
/**
|
2000-11-12 19:11:49 +08:00
|
|
|
* Find (and eliminate co-requisites) "q <- p" relation in dependency loop.
|
2000-09-27 02:04:12 +08:00
|
|
|
* Search all successors of q for instance of p. Format the specific relation,
|
2000-11-12 19:11:49 +08:00
|
|
|
* (e.g. p contains "Requires: q"). Unlink and free co-requisite (i.e.
|
|
|
|
* pure Requires: dependencies) successor node(s).
|
2000-09-27 02:04:12 +08:00
|
|
|
* @param q sucessor (i.e. package required by p)
|
|
|
|
* @param p predecessor (i.e. package that "Requires: q")
|
2000-11-12 19:11:49 +08:00
|
|
|
* @param zap max. no. of co-requisites to remove (-1 is all)?
|
|
|
|
* @retval nzaps address of no. of relations removed
|
2000-09-27 02:04:12 +08:00
|
|
|
* @return (possibly NULL) formatted "q <- p" releation (malloc'ed)
|
|
|
|
*/
|
|
|
|
static /*@owned@*/ /*@null@*/ const char *
|
2001-10-29 06:17:47 +08:00
|
|
|
zapRelation(availablePackage q, availablePackage p,
|
2001-06-01 06:31:14 +08:00
|
|
|
int zap, /*@in@*/ /*@out@*/ int * nzaps)
|
|
|
|
/*@modifies q, p, *nzaps @*/
|
2000-09-27 02:04:12 +08:00
|
|
|
{
|
2001-10-30 04:12:35 +08:00
|
|
|
tsortInfo tsi_prev;
|
|
|
|
tsortInfo tsi;
|
2000-09-27 02:04:12 +08:00
|
|
|
const char *dp = NULL;
|
|
|
|
|
|
|
|
for (tsi_prev = &q->tsi, tsi = q->tsi.tsi_next;
|
|
|
|
tsi != NULL;
|
2001-05-04 05:00:18 +08:00
|
|
|
/* XXX Note: the loop traverses "not found", break on "found". */
|
|
|
|
/*@-nullderef@*/
|
2000-09-27 02:04:12 +08:00
|
|
|
tsi_prev = tsi, tsi = tsi->tsi_next)
|
2001-05-04 05:00:18 +08:00
|
|
|
/*@=nullderef@*/
|
2000-09-27 02:04:12 +08:00
|
|
|
{
|
|
|
|
int j;
|
1999-09-18 05:08:32 +08:00
|
|
|
|
2000-09-27 02:04:12 +08:00
|
|
|
if (tsi->tsi_suc != p)
|
|
|
|
continue;
|
2001-05-04 05:00:18 +08:00
|
|
|
if (p->requires == NULL) continue; /* XXX can't happen */
|
|
|
|
if (p->requireFlags == NULL) continue; /* XXX can't happen */
|
|
|
|
if (p->requiresEVR == NULL) continue; /* XXX can't happen */
|
|
|
|
|
2000-09-27 02:04:12 +08:00
|
|
|
j = tsi->tsi_reqx;
|
2000-11-12 19:11:49 +08:00
|
|
|
dp = printDepend( identifyDepend(p->requireFlags[j]),
|
2000-09-27 02:04:12 +08:00
|
|
|
p->requires[j], p->requiresEVR[j], p->requireFlags[j]);
|
|
|
|
|
|
|
|
/*
|
2001-06-01 06:31:14 +08:00
|
|
|
* Attempt to unravel a dependency loop by eliminating Requires's.
|
2000-09-27 02:04:12 +08:00
|
|
|
*/
|
2001-10-16 01:53:34 +08:00
|
|
|
/*@-branchstate@*/
|
2000-11-12 19:11:49 +08:00
|
|
|
if (zap && !(p->requireFlags[j] & RPMSENSE_PREREQ)) {
|
2001-06-20 04:03:13 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG,
|
2000-09-27 02:04:12 +08:00
|
|
|
_("removing %s-%s-%s \"%s\" from tsort relations.\n"),
|
|
|
|
p->name, p->version, p->release, dp);
|
|
|
|
p->tsi.tsi_count--;
|
2001-06-01 06:31:14 +08:00
|
|
|
if (tsi_prev) tsi_prev->tsi_next = tsi->tsi_next;
|
2000-09-27 02:04:12 +08:00
|
|
|
tsi->tsi_next = NULL;
|
|
|
|
tsi->tsi_suc = NULL;
|
2001-04-21 14:02:09 +08:00
|
|
|
tsi = _free(tsi);
|
2000-09-27 02:04:12 +08:00
|
|
|
if (nzaps)
|
|
|
|
(*nzaps)++;
|
2000-11-12 19:11:49 +08:00
|
|
|
if (zap)
|
|
|
|
zap--;
|
1997-07-02 00:24:08 +08:00
|
|
|
}
|
2001-10-16 01:53:34 +08:00
|
|
|
/*@=branchstate@*/
|
2001-05-04 05:00:18 +08:00
|
|
|
/* XXX Note: the loop traverses "not found", get out now! */
|
2000-09-27 02:04:12 +08:00
|
|
|
break;
|
1997-07-02 00:24:08 +08:00
|
|
|
}
|
2000-09-27 02:04:12 +08:00
|
|
|
return dp;
|
1997-07-02 00:24:08 +08:00
|
|
|
}
|
|
|
|
|
2000-11-12 19:11:49 +08:00
|
|
|
/**
|
|
|
|
* Record next "q <- p" relation (i.e. "p" requires "q").
|
2001-01-16 07:09:42 +08:00
|
|
|
* @param ts transaction set
|
2000-11-12 19:11:49 +08:00
|
|
|
* @param p predecessor (i.e. package that "Requires: q")
|
|
|
|
* @param selected boolean package selected array
|
|
|
|
* @param j relation index
|
|
|
|
* @return 0 always
|
|
|
|
*/
|
2001-01-16 07:09:42 +08:00
|
|
|
static inline int addRelation( const rpmTransactionSet ts,
|
2001-10-29 06:17:47 +08:00
|
|
|
availablePackage p, unsigned char * selected, int j)
|
|
|
|
/*@modifies p, *selected @*/
|
2000-11-12 19:11:49 +08:00
|
|
|
{
|
2001-10-29 06:17:47 +08:00
|
|
|
availablePackage q;
|
2001-10-30 04:12:35 +08:00
|
|
|
tsortInfo tsi;
|
2000-11-12 19:11:49 +08:00
|
|
|
int matchNum;
|
|
|
|
|
2001-06-01 06:31:14 +08:00
|
|
|
if (!p->requires || !p->requiresEVR || !p->requireFlags)
|
|
|
|
return 0;
|
|
|
|
|
2001-10-30 04:12:35 +08:00
|
|
|
q = alSatisfiesDepend(ts->addedPackages, NULL, NULL,
|
2000-11-12 19:11:49 +08:00
|
|
|
p->requires[j], p->requiresEVR[j], p->requireFlags[j]);
|
|
|
|
|
|
|
|
/* Ordering depends only on added package relations. */
|
|
|
|
if (q == NULL)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* Avoid rpmlib feature dependencies. */
|
|
|
|
if (!strncmp(p->requires[j], "rpmlib(", sizeof("rpmlib(")-1))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
#if defined(DEPENDENCY_WHITEOUT)
|
|
|
|
/* Avoid certain dependency relations. */
|
|
|
|
if (ignoreDep(p, q))
|
|
|
|
return 0;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Avoid redundant relations. */
|
2001-06-20 04:03:13 +08:00
|
|
|
/* XXX TODO: add control bit. */
|
2001-10-30 04:12:35 +08:00
|
|
|
matchNum = q - ts->addedPackages->list;
|
2001-04-29 09:05:43 +08:00
|
|
|
if (selected[matchNum] != 0)
|
2000-11-12 19:11:49 +08:00
|
|
|
return 0;
|
|
|
|
selected[matchNum] = 1;
|
|
|
|
|
|
|
|
/* T3. Record next "q <- p" relation (i.e. "p" requires "q"). */
|
2001-01-09 12:07:49 +08:00
|
|
|
p->tsi.tsi_count++; /* bump p predecessor count */
|
2001-04-21 14:02:09 +08:00
|
|
|
if (p->depth <= q->depth) /* Save max. depth in dependency tree */
|
|
|
|
p->depth = q->depth + 1;
|
|
|
|
|
2000-11-12 19:11:49 +08:00
|
|
|
tsi = xmalloc(sizeof(*tsi));
|
2001-10-30 04:12:35 +08:00
|
|
|
/*@-assignexpose@*/
|
2000-11-12 19:11:49 +08:00
|
|
|
tsi->tsi_suc = p;
|
2001-10-30 04:12:35 +08:00
|
|
|
/*@=assignexpose@*/
|
2000-11-12 19:11:49 +08:00
|
|
|
tsi->tsi_reqx = j;
|
|
|
|
tsi->tsi_next = q->tsi.tsi_next;
|
|
|
|
q->tsi.tsi_next = tsi;
|
2001-01-09 12:07:49 +08:00
|
|
|
q->tsi.tsi_qcnt++; /* bump q successor count */
|
2000-11-12 19:11:49 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2000-08-23 20:39:49 +08:00
|
|
|
/**
|
|
|
|
* Compare ordered list entries by index (qsort/bsearch).
|
|
|
|
* @param a 1st ordered list entry
|
|
|
|
* @param b 2nd ordered list entry
|
|
|
|
* @return result of comparison
|
|
|
|
*/
|
2001-06-01 06:31:14 +08:00
|
|
|
static int orderListIndexCmp(const void * one, const void * two) /*@*/
|
1999-07-14 06:00:05 +08:00
|
|
|
{
|
2001-10-29 06:17:47 +08:00
|
|
|
/*@-castexpose@*/
|
|
|
|
int a = ((const orderListIndex)one)->alIndex;
|
|
|
|
int b = ((const orderListIndex)two)->alIndex;
|
|
|
|
/*@=castexpose@*/
|
2000-07-10 07:10:25 +08:00
|
|
|
return (a - b);
|
1999-07-14 06:00:05 +08:00
|
|
|
}
|
|
|
|
|
2001-01-09 12:07:49 +08:00
|
|
|
/**
|
|
|
|
* Add element to list sorting by initial successor count.
|
|
|
|
* @param p new element
|
|
|
|
* @retval qp address of first element
|
|
|
|
* @retval rp address of last element
|
|
|
|
*/
|
2001-10-29 06:17:47 +08:00
|
|
|
static void addQ(availablePackage p,
|
|
|
|
/*@in@*/ /*@out@*/ availablePackage * qp,
|
|
|
|
/*@in@*/ /*@out@*/ availablePackage * rp)
|
|
|
|
/*@modifies p, *qp, *rp @*/
|
2001-01-09 12:07:49 +08:00
|
|
|
{
|
2001-10-29 06:17:47 +08:00
|
|
|
availablePackage q, qprev;
|
2001-01-09 12:07:49 +08:00
|
|
|
|
|
|
|
if ((*rp) == NULL) { /* 1st element */
|
|
|
|
(*rp) = (*qp) = p;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
for (qprev = NULL, q = (*qp); q != NULL; qprev = q, q = q->tsi.tsi_suc) {
|
2001-01-13 05:47:49 +08:00
|
|
|
if (q->tsi.tsi_qcnt <= p->tsi.tsi_qcnt)
|
2001-01-09 12:07:49 +08:00
|
|
|
break;
|
|
|
|
}
|
2001-10-29 06:17:47 +08:00
|
|
|
/*@-assignexpose@*/
|
2001-01-09 12:07:49 +08:00
|
|
|
if (qprev == NULL) { /* insert at beginning of list */
|
|
|
|
p->tsi.tsi_suc = q;
|
|
|
|
(*qp) = p; /* new head */
|
|
|
|
} else if (q == NULL) { /* insert at end of list */
|
|
|
|
qprev->tsi.tsi_suc = p;
|
|
|
|
(*rp) = p; /* new tail */
|
|
|
|
} else { /* insert between qprev and q */
|
|
|
|
p->tsi.tsi_suc = q;
|
|
|
|
qprev->tsi.tsi_suc = p;
|
|
|
|
}
|
2001-10-29 06:17:47 +08:00
|
|
|
/*@=assignexpose@*/
|
2001-01-09 12:07:49 +08:00
|
|
|
}
|
|
|
|
|
2001-01-11 06:19:55 +08:00
|
|
|
int rpmdepOrder(rpmTransactionSet ts)
|
1999-07-14 06:00:05 +08:00
|
|
|
{
|
2001-10-30 04:12:35 +08:00
|
|
|
int npkgs = ts->addedPackages->size;
|
2001-04-21 14:02:09 +08:00
|
|
|
int chainsaw = ts->transFlags & RPMTRANS_FLAG_CHAINSAW;
|
2001-10-29 06:17:47 +08:00
|
|
|
availablePackage p;
|
|
|
|
availablePackage q;
|
|
|
|
availablePackage r;
|
2001-10-30 04:12:35 +08:00
|
|
|
tsortInfo tsi;
|
|
|
|
tsortInfo tsi_next;
|
2000-09-27 02:04:12 +08:00
|
|
|
int * ordering = alloca(sizeof(*ordering) * (npkgs + 1));
|
|
|
|
int orderingCount = 0;
|
|
|
|
unsigned char * selected = alloca(sizeof(*selected) * (npkgs + 1));
|
|
|
|
int loopcheck;
|
2001-10-30 04:12:35 +08:00
|
|
|
transactionElement newOrder;
|
1999-04-05 05:26:36 +08:00
|
|
|
int newOrderCount = 0;
|
2001-10-29 06:17:47 +08:00
|
|
|
orderListIndex orderList;
|
2000-09-27 02:04:12 +08:00
|
|
|
int nrescans = 10;
|
2001-01-17 05:54:59 +08:00
|
|
|
int _printed = 0;
|
2001-01-09 12:07:49 +08:00
|
|
|
int qlen;
|
2000-09-27 02:04:12 +08:00
|
|
|
int i, j;
|
1997-07-02 00:24:08 +08:00
|
|
|
|
2001-10-30 04:12:35 +08:00
|
|
|
alMakeIndex(ts->addedPackages);
|
|
|
|
alMakeIndex(ts->availablePackages);
|
1997-07-16 09:39:54 +08:00
|
|
|
|
2000-09-27 02:04:12 +08:00
|
|
|
/* T1. Initialize. */
|
|
|
|
loopcheck = npkgs;
|
1997-07-02 00:24:08 +08:00
|
|
|
|
2000-09-27 02:04:12 +08:00
|
|
|
/* Record all relations. */
|
|
|
|
rpmMessage(RPMMESS_DEBUG, _("========== recording tsort relations\n"));
|
2001-10-30 04:12:35 +08:00
|
|
|
if ((p = ts->addedPackages->list) != NULL)
|
2001-05-04 05:00:18 +08:00
|
|
|
for (i = 0; i < npkgs; i++, p++) {
|
2000-09-27 02:04:12 +08:00
|
|
|
int matchNum;
|
1997-07-18 23:03:35 +08:00
|
|
|
|
2000-09-27 02:04:12 +08:00
|
|
|
if (p->requiresCount <= 0)
|
|
|
|
continue;
|
1997-07-02 00:24:08 +08:00
|
|
|
|
2000-09-27 02:04:12 +08:00
|
|
|
memset(selected, 0, sizeof(*selected) * npkgs);
|
|
|
|
|
|
|
|
/* Avoid narcisstic relations. */
|
2001-10-30 04:12:35 +08:00
|
|
|
matchNum = p - ts->addedPackages->list;
|
2000-09-27 02:04:12 +08:00
|
|
|
selected[matchNum] = 1;
|
|
|
|
|
|
|
|
/* T2. Next "q <- p" relation. */
|
2000-11-12 19:11:49 +08:00
|
|
|
|
|
|
|
/* First, do pre-requisites. */
|
2000-09-27 02:04:12 +08:00
|
|
|
for (j = 0; j < p->requiresCount; j++) {
|
|
|
|
|
2001-10-14 06:01:38 +08:00
|
|
|
if (p->requireFlags == NULL) /* XXX can't happen */
|
|
|
|
/*@innercontinue@*/ continue;
|
2001-05-04 05:00:18 +08:00
|
|
|
|
2000-11-12 19:11:49 +08:00
|
|
|
/* Skip if not %pre/%post requires or legacy prereq. */
|
2000-09-27 02:04:12 +08:00
|
|
|
|
2000-11-12 19:11:49 +08:00
|
|
|
if (isErasePreReq(p->requireFlags[j]) ||
|
|
|
|
!( isInstallPreReq(p->requireFlags[j]) ||
|
|
|
|
isLegacyPreReq(p->requireFlags[j]) ))
|
2001-10-14 06:01:38 +08:00
|
|
|
/*@innercontinue@*/ continue;
|
2000-09-27 02:04:12 +08:00
|
|
|
|
2000-11-12 19:11:49 +08:00
|
|
|
/* T3. Record next "q <- p" relation (i.e. "p" requires "q"). */
|
2001-01-11 06:19:55 +08:00
|
|
|
(void) addRelation(ts, p, selected, j);
|
2000-09-27 02:04:12 +08:00
|
|
|
|
2000-11-12 19:11:49 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Then do co-requisites. */
|
|
|
|
for (j = 0; j < p->requiresCount; j++) {
|
|
|
|
|
2001-10-14 06:01:38 +08:00
|
|
|
if (p->requireFlags == NULL) /* XXX can't happen */
|
|
|
|
/*@innercontinue@*/ continue;
|
2001-05-04 05:00:18 +08:00
|
|
|
|
2000-11-12 19:11:49 +08:00
|
|
|
/* Skip if %pre/%post requires or legacy prereq. */
|
2000-09-27 02:04:12 +08:00
|
|
|
|
2000-11-12 19:11:49 +08:00
|
|
|
if (isErasePreReq(p->requireFlags[j]) ||
|
|
|
|
( isInstallPreReq(p->requireFlags[j]) ||
|
|
|
|
isLegacyPreReq(p->requireFlags[j]) ))
|
2001-10-14 06:01:38 +08:00
|
|
|
/*@innercontinue@*/ continue;
|
2000-09-27 02:04:12 +08:00
|
|
|
|
|
|
|
/* T3. Record next "q <- p" relation (i.e. "p" requires "q"). */
|
2001-01-11 06:19:55 +08:00
|
|
|
(void) addRelation(ts, p, selected, j);
|
2000-11-12 19:11:49 +08:00
|
|
|
|
2000-09-27 02:04:12 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-04-21 14:02:09 +08:00
|
|
|
/* Save predecessor count. */
|
2001-10-30 04:12:35 +08:00
|
|
|
if ((p = ts->addedPackages->list) != NULL)
|
2001-05-04 05:00:18 +08:00
|
|
|
for (i = 0; i < npkgs; i++, p++) {
|
2001-04-21 14:02:09 +08:00
|
|
|
p->npreds = p->tsi.tsi_count;
|
|
|
|
}
|
|
|
|
|
2000-09-27 02:04:12 +08:00
|
|
|
/* T4. Scan for zeroes. */
|
2001-04-24 04:56:59 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, _("========== tsorting packages (order, #predecessors, #succesors, depth)\n"));
|
2000-09-27 02:04:12 +08:00
|
|
|
|
|
|
|
rescan:
|
|
|
|
q = r = NULL;
|
2001-01-11 06:19:55 +08:00
|
|
|
qlen = 0;
|
2001-10-30 04:12:35 +08:00
|
|
|
if ((p = ts->addedPackages->list) != NULL)
|
2001-05-04 05:00:18 +08:00
|
|
|
for (i = 0; i < npkgs; i++, p++) {
|
2001-01-17 01:33:59 +08:00
|
|
|
|
|
|
|
/* Prefer packages in presentation order. */
|
2001-04-21 14:02:09 +08:00
|
|
|
if (!chainsaw)
|
|
|
|
p->tsi.tsi_qcnt = (npkgs - i);
|
2001-01-17 01:33:59 +08:00
|
|
|
|
2001-01-11 04:42:32 +08:00
|
|
|
if (p->tsi.tsi_count != 0)
|
|
|
|
continue;
|
|
|
|
p->tsi.tsi_suc = NULL;
|
|
|
|
addQ(p, &q, &r);
|
|
|
|
qlen++;
|
2000-09-27 02:04:12 +08:00
|
|
|
}
|
|
|
|
|
2001-01-11 04:42:32 +08:00
|
|
|
/* T5. Output front of queue (T7. Remove from queue.) */
|
2000-09-27 02:04:12 +08:00
|
|
|
for (; q != NULL; q = q->tsi.tsi_suc) {
|
|
|
|
|
2001-08-29 04:33:06 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, "%5d%5d%5d%3d %*s %s-%s-%s\n",
|
2001-04-21 14:02:09 +08:00
|
|
|
orderingCount, q->npreds, q->tsi.tsi_qcnt, q->depth,
|
|
|
|
2*q->depth, "",
|
2001-01-13 05:47:49 +08:00
|
|
|
q->name, q->version, q->release);
|
2001-10-30 04:12:35 +08:00
|
|
|
ordering[orderingCount++] = q - ts->addedPackages->list;
|
2001-01-11 04:42:32 +08:00
|
|
|
qlen--;
|
2000-09-27 02:04:12 +08:00
|
|
|
loopcheck--;
|
|
|
|
|
|
|
|
/* T6. Erase relations. */
|
|
|
|
tsi_next = q->tsi.tsi_next;
|
|
|
|
q->tsi.tsi_next = NULL;
|
|
|
|
while ((tsi = tsi_next) != NULL) {
|
|
|
|
tsi_next = tsi->tsi_next;
|
|
|
|
tsi->tsi_next = NULL;
|
|
|
|
p = tsi->tsi_suc;
|
2001-05-04 05:00:18 +08:00
|
|
|
if (p && (--p->tsi.tsi_count) <= 0) {
|
2001-06-20 04:03:13 +08:00
|
|
|
/* XXX TODO: add control bit. */
|
2000-09-27 02:04:12 +08:00
|
|
|
p->tsi.tsi_suc = NULL;
|
2001-06-01 06:31:14 +08:00
|
|
|
/*@-nullstate@*/ /* FIX: q->tsi.tsi_u.suc may be NULL */
|
2001-01-09 12:07:49 +08:00
|
|
|
addQ(p, &q->tsi.tsi_suc, &r);
|
2001-05-04 05:00:18 +08:00
|
|
|
/*@=nullstate@*/
|
2001-01-09 12:07:49 +08:00
|
|
|
qlen++;
|
1997-07-02 00:24:08 +08:00
|
|
|
}
|
2001-04-21 14:02:09 +08:00
|
|
|
tsi = _free(tsi);
|
1997-07-02 00:24:08 +08:00
|
|
|
}
|
2001-01-21 23:43:32 +08:00
|
|
|
if (!_printed && loopcheck == qlen && q->tsi.tsi_suc != NULL) {
|
2001-01-17 05:54:59 +08:00
|
|
|
_printed++;
|
|
|
|
rpmMessage(RPMMESS_DEBUG,
|
|
|
|
_("========== successors only (presentation order)\n"));
|
|
|
|
}
|
1997-07-02 00:24:08 +08:00
|
|
|
}
|
|
|
|
|
2000-09-27 02:04:12 +08:00
|
|
|
/* T8. End of process. Check for loops. */
|
|
|
|
if (loopcheck != 0) {
|
|
|
|
int nzaps;
|
|
|
|
|
|
|
|
/* T9. Initialize predecessor chain. */
|
|
|
|
nzaps = 0;
|
2001-10-30 04:12:35 +08:00
|
|
|
if ((q = ts->addedPackages->list) != NULL)
|
2001-05-04 05:00:18 +08:00
|
|
|
for (i = 0; i < npkgs; i++, q++) {
|
2000-09-27 02:04:12 +08:00
|
|
|
q->tsi.tsi_pkg = NULL;
|
|
|
|
q->tsi.tsi_reqx = 0;
|
|
|
|
/* Mark packages already sorted. */
|
|
|
|
if (q->tsi.tsi_count == 0)
|
|
|
|
q->tsi.tsi_count = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* T10. Mark all packages with their predecessors. */
|
2001-10-30 04:12:35 +08:00
|
|
|
if ((q = ts->addedPackages->list) != NULL)
|
2001-05-04 05:00:18 +08:00
|
|
|
for (i = 0; i < npkgs; i++, q++) {
|
2000-09-27 02:04:12 +08:00
|
|
|
if ((tsi = q->tsi.tsi_next) == NULL)
|
|
|
|
continue;
|
|
|
|
q->tsi.tsi_next = NULL;
|
|
|
|
markLoop(tsi, q);
|
|
|
|
q->tsi.tsi_next = tsi;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* T11. Print all dependency loops. */
|
2001-10-30 04:12:35 +08:00
|
|
|
if ((r = ts->addedPackages->list) != NULL)
|
2001-10-16 01:53:34 +08:00
|
|
|
/*@-branchstate@*/
|
2001-05-04 05:00:18 +08:00
|
|
|
for (i = 0; i < npkgs; i++, r++) {
|
2000-09-27 02:04:12 +08:00
|
|
|
int printed;
|
|
|
|
|
|
|
|
printed = 0;
|
|
|
|
|
|
|
|
/* T12. Mark predecessor chain, looking for start of loop. */
|
|
|
|
for (q = r->tsi.tsi_pkg; q != NULL; q = q->tsi.tsi_pkg) {
|
|
|
|
if (q->tsi.tsi_reqx)
|
2001-06-06 03:26:22 +08:00
|
|
|
/*@innerbreak@*/ break;
|
2000-09-27 02:04:12 +08:00
|
|
|
q->tsi.tsi_reqx = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* T13. Print predecessor chain from start of loop. */
|
|
|
|
while ((p = q) != NULL && (q = p->tsi.tsi_pkg) != NULL) {
|
|
|
|
const char * dp;
|
|
|
|
char buf[4096];
|
|
|
|
|
|
|
|
/* Unchain predecessor loop. */
|
|
|
|
p->tsi.tsi_pkg = NULL;
|
|
|
|
|
|
|
|
if (!printed) {
|
2001-06-20 04:03:13 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, _("LOOP:\n"));
|
2000-09-27 02:04:12 +08:00
|
|
|
printed = 1;
|
|
|
|
}
|
|
|
|
|
2000-11-12 19:11:49 +08:00
|
|
|
/* Find (and destroy if co-requisite) "q <- p" relation. */
|
2000-09-27 02:04:12 +08:00
|
|
|
dp = zapRelation(q, p, 1, &nzaps);
|
|
|
|
|
|
|
|
/* Print next member of loop. */
|
|
|
|
sprintf(buf, "%s-%s-%s", p->name, p->version, p->release);
|
2001-06-20 04:03:13 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, " %-40s %s\n", buf,
|
2001-05-04 05:00:18 +08:00
|
|
|
(dp ? dp : "not found!?!"));
|
2000-09-27 02:04:12 +08:00
|
|
|
|
2001-04-29 09:05:43 +08:00
|
|
|
dp = _free(dp);
|
2000-09-27 02:04:12 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Walk (and erase) linear part of predecessor chain as well. */
|
|
|
|
for (p = r, q = r->tsi.tsi_pkg;
|
|
|
|
q != NULL;
|
|
|
|
p = q, q = q->tsi.tsi_pkg)
|
|
|
|
{
|
|
|
|
/* Unchain linear part of predecessor loop. */
|
|
|
|
p->tsi.tsi_pkg = NULL;
|
|
|
|
p->tsi.tsi_reqx = 0;
|
|
|
|
}
|
|
|
|
}
|
2001-10-16 01:53:34 +08:00
|
|
|
/*@=branchstate@*/
|
2000-09-27 02:04:12 +08:00
|
|
|
|
|
|
|
/* If a relation was eliminated, then continue sorting. */
|
2001-06-20 04:03:13 +08:00
|
|
|
/* XXX TODO: add control bit. */
|
2000-09-27 02:04:12 +08:00
|
|
|
if (nzaps && nrescans-- > 0) {
|
|
|
|
rpmMessage(RPMMESS_DEBUG, _("========== continuing tsort ...\n"));
|
|
|
|
goto rescan;
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The order ends up as installed packages followed by removed packages,
|
|
|
|
* with removes for upgrades immediately following the installation of
|
|
|
|
* the new package. This would be easier if we could sort the
|
|
|
|
* addedPackages array, but we store indexes into it in various places.
|
|
|
|
*/
|
2001-09-25 05:53:14 +08:00
|
|
|
orderList = xcalloc(npkgs, sizeof(*orderList));
|
2001-01-11 06:19:55 +08:00
|
|
|
for (i = 0, j = 0; i < ts->orderCount; i++) {
|
|
|
|
if (ts->order[i].type == TR_ADDED) {
|
|
|
|
orderList[j].alIndex = ts->order[i].u.addedIndex;
|
1999-04-05 05:26:36 +08:00
|
|
|
orderList[j].orIndex = i;
|
|
|
|
j++;
|
|
|
|
}
|
|
|
|
}
|
2001-01-11 06:19:55 +08:00
|
|
|
assert(j <= npkgs);
|
1999-04-14 01:26:43 +08:00
|
|
|
|
2001-01-11 06:19:55 +08:00
|
|
|
qsort(orderList, npkgs, sizeof(*orderList), orderListIndexCmp);
|
1999-04-05 05:26:36 +08:00
|
|
|
|
2001-09-25 05:53:14 +08:00
|
|
|
newOrder = xcalloc(ts->orderCount, sizeof(*newOrder));
|
1999-04-05 05:26:36 +08:00
|
|
|
for (i = 0, newOrderCount = 0; i < orderingCount; i++) {
|
2001-10-29 06:17:47 +08:00
|
|
|
struct orderListIndex_s key;
|
|
|
|
orderListIndex needle;
|
2000-09-27 02:04:12 +08:00
|
|
|
|
1999-04-05 05:26:36 +08:00
|
|
|
key.alIndex = ordering[i];
|
2001-01-11 06:19:55 +08:00
|
|
|
needle = bsearch(&key, orderList, npkgs, sizeof(key),orderListIndexCmp);
|
1999-04-05 05:26:36 +08:00
|
|
|
/* bsearch should never, ever fail */
|
2001-05-04 05:00:18 +08:00
|
|
|
if (needle == NULL) continue;
|
1999-09-18 05:08:32 +08:00
|
|
|
|
2001-10-30 04:12:35 +08:00
|
|
|
/*@-assignexpose@*/
|
2001-01-11 06:19:55 +08:00
|
|
|
newOrder[newOrderCount++] = ts->order[needle->orIndex];
|
2001-10-30 04:12:35 +08:00
|
|
|
/*@=assignexpose@*/
|
2001-01-11 06:19:55 +08:00
|
|
|
for (j = needle->orIndex + 1; j < ts->orderCount; j++) {
|
|
|
|
if (ts->order[j].type == TR_REMOVED &&
|
|
|
|
ts->order[j].u.removed.dependsOnIndex == needle->alIndex) {
|
2001-10-30 04:12:35 +08:00
|
|
|
/*@-assignexpose@*/
|
2001-01-11 06:19:55 +08:00
|
|
|
newOrder[newOrderCount++] = ts->order[j];
|
2001-10-30 04:12:35 +08:00
|
|
|
/*@=assignexpose@*/
|
2001-06-06 03:26:22 +08:00
|
|
|
} else
|
|
|
|
/*@innerbreak@*/ break;
|
1999-04-05 05:26:36 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-01-11 06:19:55 +08:00
|
|
|
for (i = 0; i < ts->orderCount; i++) {
|
|
|
|
if (ts->order[i].type == TR_REMOVED &&
|
|
|
|
ts->order[i].u.removed.dependsOnIndex == -1) {
|
2001-10-30 04:12:35 +08:00
|
|
|
/*@-assignexpose@*/
|
2001-01-11 06:19:55 +08:00
|
|
|
newOrder[newOrderCount++] = ts->order[i];
|
2001-10-30 04:12:35 +08:00
|
|
|
/*@=assignexpose@*/
|
1999-04-05 05:26:36 +08:00
|
|
|
}
|
|
|
|
}
|
2001-01-11 06:19:55 +08:00
|
|
|
assert(newOrderCount == ts->orderCount);
|
1999-04-14 01:26:43 +08:00
|
|
|
|
2001-04-21 14:02:09 +08:00
|
|
|
ts->order = _free(ts->order);
|
2001-01-11 06:19:55 +08:00
|
|
|
ts->order = newOrder;
|
|
|
|
ts->orderAlloced = ts->orderCount;
|
2001-04-21 14:02:09 +08:00
|
|
|
orderList = _free(orderList);
|
1999-04-05 05:26:36 +08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2001-09-16 05:21:31 +08:00
|
|
|
/**
|
|
|
|
* Close a single database index.
|
|
|
|
* @param db rpm database
|
|
|
|
* @param rpmtag rpm tag
|
|
|
|
* @return 0 on success
|
|
|
|
*/
|
2001-09-21 23:07:11 +08:00
|
|
|
static int rpmdbCloseDBI(/*@null@*/ rpmdb db, int rpmtag)
|
2001-10-15 11:22:10 +08:00
|
|
|
/*@globals fileSystem @*/
|
2001-10-14 03:35:58 +08:00
|
|
|
/*@modifies db, fileSystem @*/
|
2001-09-16 05:21:31 +08:00
|
|
|
{
|
|
|
|
int dbix;
|
|
|
|
int rc = 0;
|
|
|
|
|
|
|
|
if (db == NULL || db->_dbi == NULL || dbiTags == NULL)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
for (dbix = 0; dbix < dbiTagsMax; dbix++) {
|
|
|
|
if (dbiTags[dbix] != rpmtag)
|
|
|
|
continue;
|
|
|
|
if (db->_dbi[dbix] != NULL) {
|
|
|
|
int xx;
|
|
|
|
/*@-unqualifiedtrans@*/ /* FIX: double indirection. */
|
|
|
|
xx = dbiClose(db->_dbi[dbix], 0);
|
|
|
|
if (xx && rc == 0) rc = xx;
|
|
|
|
db->_dbi[dbix] = NULL;
|
|
|
|
/*@=unqualifiedtrans@*/
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2001-01-16 07:09:42 +08:00
|
|
|
int rpmdepCheck(rpmTransactionSet ts,
|
2001-06-01 06:31:14 +08:00
|
|
|
rpmDependencyConflict * conflicts, int * numConflicts)
|
1999-07-14 06:00:05 +08:00
|
|
|
{
|
2001-02-05 06:15:30 +08:00
|
|
|
HGE_t hge = (HGE_t)headerGetEntryMinMemory;
|
|
|
|
HFD_t hfd = headerFreeData;
|
2001-09-15 21:49:11 +08:00
|
|
|
rpmdbMatchIterator mi = NULL;
|
|
|
|
Header h = NULL;
|
2001-10-29 06:17:47 +08:00
|
|
|
availablePackage p;
|
2001-10-28 04:09:20 +08:00
|
|
|
problemsSet ps = NULL;
|
2001-09-15 21:49:11 +08:00
|
|
|
int npkgs;
|
2001-10-28 04:09:20 +08:00
|
|
|
int closeatexit = 0;
|
2001-10-16 22:58:57 +08:00
|
|
|
int i, j, xx;
|
1999-09-14 13:41:13 +08:00
|
|
|
int rc;
|
1999-04-05 05:26:36 +08:00
|
|
|
|
2001-10-28 04:09:20 +08:00
|
|
|
/* Do lazy, readonly, open of rpm database. */
|
|
|
|
if (ts->rpmdb == NULL) {
|
|
|
|
if ((rc = rpmtsOpenDB(ts, ts->dbmode)) != 0)
|
|
|
|
goto exit;
|
|
|
|
closeatexit = 1;
|
|
|
|
}
|
|
|
|
|
2001-10-30 04:12:35 +08:00
|
|
|
npkgs = ts->addedPackages->size;
|
2001-09-15 21:49:11 +08:00
|
|
|
|
|
|
|
ps = xcalloc(1, sizeof(*ps));
|
2001-06-01 06:31:14 +08:00
|
|
|
ps->alloced = 5;
|
|
|
|
ps->num = 0;
|
|
|
|
ps->problems = xcalloc(ps->alloced, sizeof(*ps->problems));
|
1999-07-14 06:00:05 +08:00
|
|
|
|
|
|
|
*conflicts = NULL;
|
|
|
|
*numConflicts = 0;
|
|
|
|
|
2001-10-30 04:12:35 +08:00
|
|
|
alMakeIndex(ts->addedPackages);
|
|
|
|
alMakeIndex(ts->availablePackages);
|
1999-09-18 05:08:32 +08:00
|
|
|
|
2001-02-05 06:15:30 +08:00
|
|
|
/*
|
|
|
|
* Look at all of the added packages and make sure their dependencies
|
2000-07-08 04:06:41 +08:00
|
|
|
* are satisfied.
|
|
|
|
*/
|
2001-10-30 04:12:35 +08:00
|
|
|
if ((p = ts->addedPackages->list) != NULL)
|
2001-05-04 05:00:18 +08:00
|
|
|
for (i = 0; i < npkgs; i++, p++)
|
2000-09-27 02:04:12 +08:00
|
|
|
{
|
1999-09-18 05:08:32 +08:00
|
|
|
|
2001-09-21 23:07:11 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, "========== +++ %s-%s-%s\n" ,
|
2001-04-24 04:56:59 +08:00
|
|
|
p->name, p->version, p->release);
|
2001-06-01 06:31:14 +08:00
|
|
|
rc = checkPackageDeps(ts, ps, p->h, NULL, p->multiLib);
|
2000-07-08 04:06:41 +08:00
|
|
|
if (rc)
|
1999-09-14 13:41:13 +08:00
|
|
|
goto exit;
|
|
|
|
|
1999-09-19 08:29:44 +08:00
|
|
|
/* Adding: check name against conflicts matches. */
|
2001-06-01 06:31:14 +08:00
|
|
|
rc = checkDependentConflicts(ts, ps, p->name);
|
2000-07-08 04:06:41 +08:00
|
|
|
if (rc)
|
1999-09-14 13:41:13 +08:00
|
|
|
goto exit;
|
|
|
|
|
1999-09-19 08:29:44 +08:00
|
|
|
if (p->providesCount == 0 || p->provides == NULL)
|
|
|
|
continue;
|
1999-09-14 13:41:13 +08:00
|
|
|
|
|
|
|
rc = 0;
|
1999-09-19 08:29:44 +08:00
|
|
|
for (j = 0; j < p->providesCount; j++) {
|
|
|
|
/* Adding: check provides key against conflicts matches. */
|
2001-06-01 06:31:14 +08:00
|
|
|
if (!checkDependentConflicts(ts, ps, p->provides[j]))
|
2001-10-14 06:01:38 +08:00
|
|
|
/*@innercontinue@*/ continue;
|
2001-02-05 06:15:30 +08:00
|
|
|
rc = 1;
|
2001-06-06 03:26:22 +08:00
|
|
|
/*@innerbreak@*/ break;
|
1999-07-14 06:00:05 +08:00
|
|
|
}
|
2000-07-08 04:06:41 +08:00
|
|
|
if (rc)
|
|
|
|
goto exit;
|
1999-07-14 06:00:05 +08:00
|
|
|
}
|
|
|
|
|
2001-02-05 06:15:30 +08:00
|
|
|
/*
|
|
|
|
* Look at the removed packages and make sure they aren't critical.
|
|
|
|
*/
|
2001-10-16 01:53:34 +08:00
|
|
|
/*@-branchstate@*/
|
2001-01-16 07:09:42 +08:00
|
|
|
if (ts->numRemovedPackages > 0) {
|
2001-10-28 04:09:20 +08:00
|
|
|
mi = rpmtsInitIterator(ts, RPMDBI_PACKAGES, NULL, 0);
|
2001-10-16 22:58:57 +08:00
|
|
|
xx = rpmdbAppendIterator(mi,
|
2001-05-01 06:32:22 +08:00
|
|
|
ts->removedPackages, ts->numRemovedPackages);
|
2000-06-07 04:06:09 +08:00
|
|
|
while ((h = rpmdbNextIterator(mi)) != NULL) {
|
1999-09-18 05:08:32 +08:00
|
|
|
|
2001-04-24 04:56:59 +08:00
|
|
|
{ const char * name, * version, * release;
|
2001-10-16 22:58:57 +08:00
|
|
|
xx = headerNVR(h, &name, &version, &release);
|
2001-09-21 23:07:11 +08:00
|
|
|
rpmMessage(RPMMESS_DEBUG, "========== --- %s-%s-%s\n" ,
|
2001-04-24 04:56:59 +08:00
|
|
|
name, version, release);
|
1999-07-14 06:00:05 +08:00
|
|
|
|
1999-12-01 02:07:08 +08:00
|
|
|
/* Erasing: check name against requiredby matches. */
|
2001-06-01 06:31:14 +08:00
|
|
|
rc = checkDependentPackages(ts, ps, name);
|
2000-07-08 04:06:41 +08:00
|
|
|
if (rc)
|
1999-12-01 02:07:08 +08:00
|
|
|
goto exit;
|
|
|
|
}
|
1999-07-14 06:00:05 +08:00
|
|
|
|
1999-12-01 02:07:08 +08:00
|
|
|
{ const char ** provides;
|
|
|
|
int providesCount;
|
2001-06-12 12:10:21 +08:00
|
|
|
rpmTagType pnt;
|
1999-12-01 02:07:08 +08:00
|
|
|
|
2001-02-05 06:15:30 +08:00
|
|
|
if (hge(h, RPMTAG_PROVIDENAME, &pnt, (void **) &provides,
|
|
|
|
&providesCount))
|
|
|
|
{
|
1999-12-01 02:07:08 +08:00
|
|
|
rc = 0;
|
|
|
|
for (j = 0; j < providesCount; j++) {
|
|
|
|
/* Erasing: check provides against requiredby matches. */
|
2001-06-01 06:31:14 +08:00
|
|
|
if (!checkDependentPackages(ts, ps, provides[j]))
|
2001-10-14 06:01:38 +08:00
|
|
|
/*@innercontinue@*/ continue;
|
1999-09-14 13:41:13 +08:00
|
|
|
rc = 1;
|
2001-06-06 03:26:22 +08:00
|
|
|
/*@innerbreak@*/ break;
|
1999-07-14 06:00:05 +08:00
|
|
|
}
|
2001-02-05 06:15:30 +08:00
|
|
|
provides = hfd(provides, pnt);
|
1999-12-01 02:07:08 +08:00
|
|
|
if (rc)
|
|
|
|
goto exit;
|
1999-07-14 06:00:05 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-12-01 02:07:08 +08:00
|
|
|
{ const char ** baseNames, ** dirNames;
|
2001-06-12 12:10:21 +08:00
|
|
|
int_32 * dirIndexes;
|
|
|
|
rpmTagType dnt, bnt;
|
1999-12-01 02:07:08 +08:00
|
|
|
int fileCount;
|
|
|
|
char * fileName = NULL;
|
|
|
|
int fileAlloced = 0;
|
|
|
|
int len;
|
|
|
|
|
2001-02-05 06:15:30 +08:00
|
|
|
if (hge(h, RPMTAG_BASENAMES, &bnt, (void **) &baseNames, &fileCount))
|
|
|
|
{
|
2001-10-16 22:58:57 +08:00
|
|
|
xx = hge(h, RPMTAG_DIRNAMES, &dnt, (void **) &dirNames, NULL);
|
|
|
|
xx = hge(h, RPMTAG_DIRINDEXES, NULL, (void **) &dirIndexes,
|
2001-05-01 06:32:22 +08:00
|
|
|
NULL);
|
1999-12-01 02:07:08 +08:00
|
|
|
rc = 0;
|
|
|
|
for (j = 0; j < fileCount; j++) {
|
2001-10-28 04:09:20 +08:00
|
|
|
len = strlen(baseNames[j]) + 1 +
|
1999-12-01 02:07:08 +08:00
|
|
|
strlen(dirNames[dirIndexes[j]]);
|
|
|
|
if (len > fileAlloced) {
|
|
|
|
fileAlloced = len * 2;
|
|
|
|
fileName = xrealloc(fileName, fileAlloced);
|
|
|
|
}
|
2000-04-14 00:00:34 +08:00
|
|
|
*fileName = '\0';
|
2000-07-08 04:06:41 +08:00
|
|
|
(void) stpcpy( stpcpy(fileName, dirNames[dirIndexes[j]]) , baseNames[j]);
|
1999-12-01 02:07:08 +08:00
|
|
|
/* Erasing: check filename against requiredby matches. */
|
2001-06-01 06:31:14 +08:00
|
|
|
if (!checkDependentPackages(ts, ps, fileName))
|
2001-10-14 06:01:38 +08:00
|
|
|
/*@innercontinue@*/ continue;
|
2001-02-05 06:15:30 +08:00
|
|
|
rc = 1;
|
2001-06-06 03:26:22 +08:00
|
|
|
/*@innerbreak@*/ break;
|
1999-10-09 04:30:49 +08:00
|
|
|
}
|
1999-07-14 06:00:05 +08:00
|
|
|
|
2001-04-21 14:02:09 +08:00
|
|
|
fileName = _free(fileName);
|
2001-02-05 06:15:30 +08:00
|
|
|
baseNames = hfd(baseNames, bnt);
|
|
|
|
dirNames = hfd(dirNames, dnt);
|
1999-12-01 02:07:08 +08:00
|
|
|
if (rc)
|
|
|
|
goto exit;
|
|
|
|
}
|
1999-07-14 06:00:05 +08:00
|
|
|
}
|
|
|
|
|
2000-06-07 04:06:09 +08:00
|
|
|
}
|
2001-04-30 06:43:01 +08:00
|
|
|
mi = rpmdbFreeIterator(mi);
|
1999-07-14 06:00:05 +08:00
|
|
|
}
|
2001-10-16 01:53:34 +08:00
|
|
|
/*@=branchstate@*/
|
1999-07-14 06:00:05 +08:00
|
|
|
|
2001-06-01 06:31:14 +08:00
|
|
|
if (ps->num) {
|
|
|
|
*conflicts = ps->problems;
|
|
|
|
ps->problems = NULL;
|
|
|
|
*numConflicts = ps->num;
|
1999-07-14 06:00:05 +08:00
|
|
|
}
|
2000-07-08 04:06:41 +08:00
|
|
|
rc = 0;
|
1999-09-14 13:41:13 +08:00
|
|
|
|
|
|
|
exit:
|
2001-04-30 06:43:01 +08:00
|
|
|
mi = rpmdbFreeIterator(mi);
|
2001-10-28 04:09:20 +08:00
|
|
|
if (ps) {
|
|
|
|
ps->problems = _free(ps->problems);
|
|
|
|
ps = _free(ps);
|
|
|
|
}
|
2001-10-16 01:53:34 +08:00
|
|
|
/*@-branchstate@*/
|
2001-10-28 04:09:20 +08:00
|
|
|
if (closeatexit)
|
|
|
|
xx = rpmtsCloseDB(ts);
|
|
|
|
else if (_cacheDependsRC)
|
2001-10-16 22:58:57 +08:00
|
|
|
xx = rpmdbCloseDBI(ts->rpmdb, RPMDBI_DEPENDS);
|
2001-10-16 01:53:34 +08:00
|
|
|
/*@=branchstate@*/
|
2000-07-08 04:06:41 +08:00
|
|
|
return rc;
|
1997-07-02 00:24:08 +08:00
|
|
|
}
|