2000-08-28 03:27:03 +08:00
|
|
|
/**
|
2002-05-20 02:42:25 +08:00
|
|
|
* \file lib/rpmps.c
|
2000-08-28 03:27:03 +08:00
|
|
|
*/
|
|
|
|
|
1998-12-19 03:09:38 +08:00
|
|
|
#include "system.h"
|
|
|
|
|
1999-07-14 05:37:57 +08:00
|
|
|
#include <rpmlib.h>
|
1998-12-19 03:09:38 +08:00
|
|
|
|
2002-05-20 02:42:25 +08:00
|
|
|
#include "rpmps.h"
|
2002-04-12 00:55:19 +08:00
|
|
|
|
1998-12-19 03:09:38 +08:00
|
|
|
#include "misc.h"
|
2000-12-13 04:03:45 +08:00
|
|
|
#include "debug.h"
|
1998-12-19 03:09:38 +08:00
|
|
|
|
2001-10-30 00:35:01 +08:00
|
|
|
|
2002-07-28 22:52:33 +08:00
|
|
|
int _rpmps_debug = 0;
|
2001-11-10 01:22:08 +08:00
|
|
|
|
2002-05-20 02:42:25 +08:00
|
|
|
rpmps XrpmpsUnlink(rpmps ps, const char * msg,
|
2001-11-10 01:22:08 +08:00
|
|
|
const char * fn, unsigned ln)
|
|
|
|
{
|
2002-07-28 22:52:33 +08:00
|
|
|
if (_rpmps_debug > 0 && msg != NULL)
|
2001-11-10 01:22:08 +08:00
|
|
|
fprintf(stderr, "--> ps %p -- %d %s at %s:%u\n", ps, ps->nrefs, msg, fn, ln);
|
|
|
|
ps->nrefs--;
|
2002-05-18 05:08:39 +08:00
|
|
|
return ps;
|
2001-11-10 01:22:08 +08:00
|
|
|
}
|
|
|
|
|
2002-05-20 02:42:25 +08:00
|
|
|
rpmps XrpmpsLink(rpmps ps, const char * msg,
|
2001-11-10 01:22:08 +08:00
|
|
|
const char * fn, unsigned ln)
|
|
|
|
{
|
|
|
|
ps->nrefs++;
|
2002-07-28 22:52:33 +08:00
|
|
|
if (_rpmps_debug > 0 && msg != NULL)
|
2001-11-10 01:22:08 +08:00
|
|
|
fprintf(stderr, "--> ps %p ++ %d %s at %s:%u\n", ps, ps->nrefs, msg, fn, ln);
|
2002-05-18 05:08:39 +08:00
|
|
|
return ps;
|
2001-11-10 01:22:08 +08:00
|
|
|
}
|
|
|
|
|
2002-06-12 22:52:59 +08:00
|
|
|
int rpmpsNumProblems(rpmps ps)
|
|
|
|
{
|
|
|
|
int numProblems = 0;
|
|
|
|
if (ps && ps->probs)
|
|
|
|
numProblems = ps->numProblems;
|
|
|
|
return numProblems;
|
|
|
|
}
|
|
|
|
|
2002-05-20 02:42:25 +08:00
|
|
|
rpmps rpmpsCreate(void)
|
2001-10-30 00:35:01 +08:00
|
|
|
{
|
2002-05-20 02:42:25 +08:00
|
|
|
rpmps ps = xcalloc(1, sizeof(*ps));
|
2001-11-10 01:22:08 +08:00
|
|
|
return rpmpsLink(ps, "create");
|
2001-10-30 00:35:01 +08:00
|
|
|
}
|
|
|
|
|
2002-05-20 02:42:25 +08:00
|
|
|
rpmps rpmpsFree(rpmps ps)
|
2001-11-10 01:22:08 +08:00
|
|
|
{
|
|
|
|
if (ps == NULL) return NULL;
|
2002-05-18 05:08:39 +08:00
|
|
|
ps = rpmpsUnlink(ps, "dereference");
|
|
|
|
if (ps->nrefs > 0)
|
|
|
|
return NULL;
|
2001-11-10 01:22:08 +08:00
|
|
|
|
|
|
|
if (ps->probs) {
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < ps->numProblems; i++) {
|
|
|
|
rpmProblem p = ps->probs + i;
|
|
|
|
p->pkgNEVR = _free(p->pkgNEVR);
|
|
|
|
p->altNEVR = _free(p->altNEVR);
|
|
|
|
p->str1 = _free(p->str1);
|
|
|
|
}
|
2002-05-07 09:07:41 +08:00
|
|
|
ps->probs = _free(ps->probs);
|
2001-11-10 01:22:08 +08:00
|
|
|
}
|
|
|
|
ps = _free(ps);
|
|
|
|
return NULL;
|
2001-10-30 00:35:01 +08:00
|
|
|
}
|
|
|
|
|
2002-05-20 02:42:25 +08:00
|
|
|
void rpmpsAppend(rpmps ps, rpmProblemType type,
|
2001-11-08 08:12:49 +08:00
|
|
|
const char * pkgNEVR, fnpyKey key,
|
2001-10-30 00:35:01 +08:00
|
|
|
const char * dn, const char * bn,
|
2001-10-31 02:00:21 +08:00
|
|
|
const char * altNEVR, unsigned long ulong1)
|
2001-10-30 00:35:01 +08:00
|
|
|
{
|
|
|
|
rpmProblem p;
|
|
|
|
char *t;
|
|
|
|
|
2001-11-10 01:22:08 +08:00
|
|
|
if (ps == NULL) return;
|
|
|
|
|
|
|
|
if (ps->numProblems == ps->numProblemsAlloced) {
|
|
|
|
if (ps->numProblemsAlloced)
|
|
|
|
ps->numProblemsAlloced *= 2;
|
2001-10-30 00:35:01 +08:00
|
|
|
else
|
2001-11-10 01:22:08 +08:00
|
|
|
ps->numProblemsAlloced = 2;
|
|
|
|
ps->probs = xrealloc(ps->probs,
|
|
|
|
ps->numProblemsAlloced * sizeof(*ps->probs));
|
2001-10-30 00:35:01 +08:00
|
|
|
}
|
|
|
|
|
2001-11-10 01:22:08 +08:00
|
|
|
p = ps->probs + ps->numProblems;
|
|
|
|
ps->numProblems++;
|
2001-10-30 00:35:01 +08:00
|
|
|
memset(p, 0, sizeof(*p));
|
2001-10-31 02:00:21 +08:00
|
|
|
|
2001-10-30 00:35:01 +08:00
|
|
|
p->type = type;
|
2001-10-31 02:00:21 +08:00
|
|
|
p->key = key;
|
2001-10-30 00:35:01 +08:00
|
|
|
p->ulong1 = ulong1;
|
|
|
|
p->ignoreProblem = 0;
|
|
|
|
|
2001-11-10 01:22:08 +08:00
|
|
|
p->pkgNEVR = (pkgNEVR ? xstrdup(pkgNEVR) : NULL);
|
|
|
|
p->altNEVR = (altNEVR ? xstrdup(altNEVR) : NULL);
|
2001-11-01 06:19:42 +08:00
|
|
|
|
|
|
|
p->str1 = NULL;
|
2001-10-30 00:35:01 +08:00
|
|
|
if (dn != NULL || bn != NULL) {
|
|
|
|
t = xcalloc(1, (dn != NULL ? strlen(dn) : 0) +
|
|
|
|
(bn != NULL ? strlen(bn) : 0) + 1);
|
|
|
|
p->str1 = t;
|
|
|
|
if (dn != NULL) t = stpcpy(t, dn);
|
|
|
|
if (bn != NULL) t = stpcpy(t, bn);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#define XSTRCMP(a, b) ((!(a) && !(b)) || ((a) && (b) && !strcmp((a), (b))))
|
|
|
|
|
2002-05-20 02:42:25 +08:00
|
|
|
int rpmpsTrim(rpmps ps, rpmps filter)
|
2001-10-30 00:35:01 +08:00
|
|
|
{
|
|
|
|
rpmProblem t;
|
|
|
|
rpmProblem f;
|
|
|
|
int gotProblems = 0;
|
|
|
|
|
2001-11-10 01:22:08 +08:00
|
|
|
if (ps == NULL || ps->numProblems == 0)
|
2001-10-30 00:35:01 +08:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (filter == NULL)
|
2001-11-10 01:22:08 +08:00
|
|
|
return (ps->numProblems == 0 ? 0 : 1);
|
2001-10-30 00:35:01 +08:00
|
|
|
|
2001-11-10 01:22:08 +08:00
|
|
|
t = ps->probs;
|
2001-10-30 00:35:01 +08:00
|
|
|
f = filter->probs;
|
|
|
|
|
|
|
|
while ((f - filter->probs) < filter->numProblems) {
|
|
|
|
if (!f->ignoreProblem) {
|
|
|
|
f++;
|
|
|
|
continue;
|
|
|
|
}
|
2001-11-10 01:22:08 +08:00
|
|
|
while ((t - ps->probs) < ps->numProblems) {
|
2007-09-12 01:07:39 +08:00
|
|
|
/* LCL: looks good to me <shrug> */
|
2001-10-30 07:39:51 +08:00
|
|
|
if (f->type == t->type && t->key == f->key &&
|
|
|
|
XSTRCMP(f->str1, t->str1))
|
2007-09-12 01:07:39 +08:00
|
|
|
break;
|
2001-10-30 00:35:01 +08:00
|
|
|
t++;
|
|
|
|
gotProblems = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* XXX This can't happen, but let's be sane in case it does. */
|
2001-11-10 01:22:08 +08:00
|
|
|
if ((t - ps->probs) == ps->numProblems)
|
2001-10-30 00:35:01 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
t->ignoreProblem = f->ignoreProblem;
|
|
|
|
t++, f++;
|
|
|
|
}
|
|
|
|
|
2001-11-10 01:22:08 +08:00
|
|
|
if ((t - ps->probs) < ps->numProblems)
|
2001-10-30 00:35:01 +08:00
|
|
|
gotProblems = 1;
|
|
|
|
|
|
|
|
return gotProblems;
|
|
|
|
}
|
1999-09-18 04:52:46 +08:00
|
|
|
|
2001-10-09 00:12:33 +08:00
|
|
|
#if !defined(HAVE_VSNPRINTF)
|
2007-09-12 01:07:39 +08:00
|
|
|
static inline int vsnprintf(char * buf, int nb,
|
2001-04-18 03:29:12 +08:00
|
|
|
const char * fmt, va_list ap)
|
|
|
|
{
|
|
|
|
return vsprintf(buf, fmt, ap);
|
|
|
|
}
|
|
|
|
#endif
|
2001-10-09 00:12:33 +08:00
|
|
|
#if !defined(HAVE_SNPRINTF)
|
2007-09-12 01:07:39 +08:00
|
|
|
static inline int snprintf(char * buf, int nb, const char * fmt, ...)
|
2001-04-18 03:29:12 +08:00
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
int rc;
|
|
|
|
va_start(ap, fmt);
|
|
|
|
rc = vsnprintf(buf, nb, fmt, ap);
|
|
|
|
va_end(ap);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2001-06-01 06:31:14 +08:00
|
|
|
const char * rpmProblemString(const rpmProblem prob)
|
1999-07-14 07:33:02 +08:00
|
|
|
{
|
2001-11-09 06:04:35 +08:00
|
|
|
const char * pkgNEVR = (prob->pkgNEVR ? prob->pkgNEVR : "?pkgNEVR?");
|
2002-06-29 05:54:24 +08:00
|
|
|
const char * altNEVR = (prob->altNEVR ? prob->altNEVR : "? ?altNEVR?");
|
2001-11-10 01:22:08 +08:00
|
|
|
const char * str1 = (prob->str1 ? prob->str1 : N_("different"));
|
2001-05-04 05:00:18 +08:00
|
|
|
int nb = strlen(pkgNEVR) + strlen(str1) + strlen(altNEVR) + 100;
|
2000-12-13 04:03:45 +08:00
|
|
|
char * buf = xmalloc(nb+1);
|
2001-10-14 03:35:58 +08:00
|
|
|
int rc;
|
1998-12-19 03:09:38 +08:00
|
|
|
|
2000-08-30 06:04:33 +08:00
|
|
|
switch (prob->type) {
|
2000-12-13 04:03:45 +08:00
|
|
|
case RPMPROB_BADARCH:
|
2001-10-14 03:35:58 +08:00
|
|
|
rc = snprintf(buf, nb,
|
2001-11-10 01:22:08 +08:00
|
|
|
_("package %s is intended for a %s architecture"),
|
|
|
|
pkgNEVR, str1);
|
1998-12-19 03:09:38 +08:00
|
|
|
break;
|
2000-12-13 04:03:45 +08:00
|
|
|
case RPMPROB_BADOS:
|
2001-10-14 03:35:58 +08:00
|
|
|
rc = snprintf(buf, nb,
|
2001-11-10 01:22:08 +08:00
|
|
|
_("package %s is intended for a %s operating system"),
|
|
|
|
pkgNEVR, str1);
|
1999-06-03 02:08:50 +08:00
|
|
|
break;
|
2000-12-13 04:03:45 +08:00
|
|
|
case RPMPROB_PKG_INSTALLED:
|
2001-10-14 03:35:58 +08:00
|
|
|
rc = snprintf(buf, nb,
|
2001-05-01 06:32:22 +08:00
|
|
|
_("package %s is already installed"),
|
2001-05-04 05:00:18 +08:00
|
|
|
pkgNEVR);
|
1998-12-19 03:09:38 +08:00
|
|
|
break;
|
2000-12-13 04:03:45 +08:00
|
|
|
case RPMPROB_BADRELOCATE:
|
2001-10-14 03:35:58 +08:00
|
|
|
rc = snprintf(buf, nb,
|
2003-12-30 21:14:49 +08:00
|
|
|
_("path %s in package %s is not relocatable"),
|
2001-05-04 05:00:18 +08:00
|
|
|
str1, pkgNEVR);
|
1998-12-27 00:33:51 +08:00
|
|
|
break;
|
2000-12-13 04:03:45 +08:00
|
|
|
case RPMPROB_NEW_FILE_CONFLICT:
|
2001-10-14 03:35:58 +08:00
|
|
|
rc = snprintf(buf, nb,
|
2000-12-17 09:16:14 +08:00
|
|
|
_("file %s conflicts between attempted installs of %s and %s"),
|
2001-05-04 05:00:18 +08:00
|
|
|
str1, pkgNEVR, altNEVR);
|
1998-12-19 03:09:38 +08:00
|
|
|
break;
|
2000-12-13 04:03:45 +08:00
|
|
|
case RPMPROB_FILE_CONFLICT:
|
2001-10-14 03:35:58 +08:00
|
|
|
rc = snprintf(buf, nb,
|
2000-12-13 04:03:45 +08:00
|
|
|
_("file %s from install of %s conflicts with file from package %s"),
|
2001-05-04 05:00:18 +08:00
|
|
|
str1, pkgNEVR, altNEVR);
|
1998-12-31 07:02:49 +08:00
|
|
|
break;
|
2000-12-13 04:03:45 +08:00
|
|
|
case RPMPROB_OLDPACKAGE:
|
2001-10-14 03:35:58 +08:00
|
|
|
rc = snprintf(buf, nb,
|
2000-12-13 04:03:45 +08:00
|
|
|
_("package %s (which is newer than %s) is already installed"),
|
2001-05-04 05:00:18 +08:00
|
|
|
altNEVR, pkgNEVR);
|
1999-02-17 12:32:55 +08:00
|
|
|
break;
|
2000-12-13 04:03:45 +08:00
|
|
|
case RPMPROB_DISKSPACE:
|
2001-10-14 03:35:58 +08:00
|
|
|
rc = snprintf(buf, nb,
|
2002-06-06 04:26:57 +08:00
|
|
|
_("installing package %s needs %ld%cB on the %s filesystem"),
|
2001-05-04 05:00:18 +08:00
|
|
|
pkgNEVR,
|
2000-12-13 04:03:45 +08:00
|
|
|
prob->ulong1 > (1024*1024)
|
|
|
|
? (prob->ulong1 + 1024 * 1024 - 1) / (1024 * 1024)
|
|
|
|
: (prob->ulong1 + 1023) / 1024,
|
|
|
|
prob->ulong1 > (1024*1024) ? 'M' : 'K',
|
2001-05-04 05:00:18 +08:00
|
|
|
str1);
|
2000-07-09 12:42:12 +08:00
|
|
|
break;
|
2000-12-13 04:03:45 +08:00
|
|
|
case RPMPROB_DISKNODES:
|
2001-10-14 03:35:58 +08:00
|
|
|
rc = snprintf(buf, nb,
|
2000-12-13 04:03:45 +08:00
|
|
|
_("installing package %s needs %ld inodes on the %s filesystem"),
|
2001-05-04 05:00:18 +08:00
|
|
|
pkgNEVR, (long)prob->ulong1, str1);
|
2000-10-21 00:47:00 +08:00
|
|
|
break;
|
2000-12-13 04:03:45 +08:00
|
|
|
case RPMPROB_REQUIRES:
|
2002-06-29 05:54:24 +08:00
|
|
|
rc = snprintf(buf, nb, _("%s is needed by %s%s"),
|
|
|
|
altNEVR+2,
|
|
|
|
(prob->ulong1 ? "" : _("(installed) ")), pkgNEVR);
|
2001-11-09 06:04:35 +08:00
|
|
|
break;
|
2000-12-13 04:03:45 +08:00
|
|
|
case RPMPROB_CONFLICT:
|
2002-06-29 05:54:24 +08:00
|
|
|
rc = snprintf(buf, nb, _("%s conflicts with %s%s"),
|
|
|
|
altNEVR+2,
|
|
|
|
(prob->ulong1 ? "" : _("(installed) ")), pkgNEVR);
|
2001-11-09 06:04:35 +08:00
|
|
|
break;
|
2000-12-13 04:03:45 +08:00
|
|
|
default:
|
2001-10-14 03:35:58 +08:00
|
|
|
rc = snprintf(buf, nb,
|
2000-12-13 04:03:45 +08:00
|
|
|
_("unknown error %d encountered while manipulating package %s"),
|
2001-05-04 05:00:18 +08:00
|
|
|
prob->type, pkgNEVR);
|
1998-12-19 03:09:38 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2000-12-13 04:03:45 +08:00
|
|
|
buf[nb] = '\0';
|
1998-12-19 03:09:38 +08:00
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
|
2001-11-10 01:22:08 +08:00
|
|
|
static int sameProblem(const rpmProblem ap, const rpmProblem bp)
|
|
|
|
{
|
|
|
|
if (ap->type != bp->type)
|
|
|
|
return 1;
|
|
|
|
if (ap->pkgNEVR)
|
|
|
|
if (bp->pkgNEVR && strcmp(ap->pkgNEVR, bp->pkgNEVR))
|
|
|
|
return 1;
|
|
|
|
if (ap->altNEVR)
|
|
|
|
if (bp->altNEVR && strcmp(ap->altNEVR, bp->altNEVR))
|
|
|
|
return 1;
|
|
|
|
if (ap->str1)
|
|
|
|
if (bp->str1 && strcmp(ap->str1, bp->str1))
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
if (ap->ulong1 != bp->ulong1)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2002-06-29 05:54:24 +08:00
|
|
|
void rpmpsPrint(FILE *fp, rpmps ps)
|
2001-11-10 01:22:08 +08:00
|
|
|
{
|
2002-06-29 05:54:24 +08:00
|
|
|
const char * msg;
|
2001-11-10 01:22:08 +08:00
|
|
|
int i;
|
|
|
|
|
2002-06-29 05:54:24 +08:00
|
|
|
if (ps == NULL || ps->probs == NULL || ps->numProblems <= 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (fp == NULL)
|
|
|
|
fp = stderr;
|
|
|
|
|
2002-04-14 02:52:18 +08:00
|
|
|
for (i = 0; i < ps->numProblems; i++) {
|
|
|
|
rpmProblem p;
|
2001-11-10 01:22:08 +08:00
|
|
|
int j;
|
|
|
|
|
2002-04-14 02:52:18 +08:00
|
|
|
p = ps->probs + i;
|
2001-11-10 01:22:08 +08:00
|
|
|
|
2002-06-29 05:54:24 +08:00
|
|
|
if (p->ignoreProblem)
|
|
|
|
continue;
|
|
|
|
|
2001-11-10 01:22:08 +08:00
|
|
|
/* Filter already displayed problems. */
|
|
|
|
for (j = 0; j < i; j++) {
|
2002-04-14 02:52:18 +08:00
|
|
|
if (!sameProblem(p, ps->probs + j))
|
2007-09-12 01:07:39 +08:00
|
|
|
break;
|
2001-11-10 01:22:08 +08:00
|
|
|
}
|
|
|
|
if (j < i)
|
|
|
|
continue;
|
|
|
|
|
2002-06-29 05:54:24 +08:00
|
|
|
msg = rpmProblemString(p);
|
|
|
|
fprintf(fp, "\t%s\n", msg);
|
|
|
|
msg = _free(msg);
|
2001-11-10 01:22:08 +08:00
|
|
|
|
|
|
|
}
|
|
|
|
}
|