225 lines
5.5 KiB
C
225 lines
5.5 KiB
C
/**
|
|
* \file lib/problems.c
|
|
*/
|
|
|
|
#include "system.h"
|
|
|
|
#include "rpmlib.h"
|
|
|
|
#include "depends.h"
|
|
#include "misc.h"
|
|
#include "debug.h"
|
|
|
|
/*@access rpmProblemSet@*/
|
|
/*@access rpmProblem@*/
|
|
/*@access rpmDependencyConflict@*/
|
|
|
|
/* XXX FIXME: merge into problems */
|
|
/* XXX used in verify.c rpmlibprov.c */
|
|
void printDepFlags(FILE * fp, const char * version, int flags)
|
|
{
|
|
if (flags)
|
|
fprintf(fp, " ");
|
|
|
|
if (flags & RPMSENSE_LESS)
|
|
fprintf(fp, "<");
|
|
if (flags & RPMSENSE_GREATER)
|
|
fprintf(fp, ">");
|
|
if (flags & RPMSENSE_EQUAL)
|
|
fprintf(fp, "=");
|
|
|
|
if (flags)
|
|
fprintf(fp, " %s", version);
|
|
}
|
|
|
|
static int sameProblem(const rpmDependencyConflict ap,
|
|
const rpmDependencyConflict bp)
|
|
/*@*/
|
|
{
|
|
|
|
if (ap->sense != bp->sense)
|
|
return 1;
|
|
|
|
if (ap->byName && bp->byName && strcmp(ap->byName, bp->byName))
|
|
return 1;
|
|
if (ap->byVersion && bp->byVersion && strcmp(ap->byVersion, bp->byVersion))
|
|
return 1;
|
|
if (ap->byRelease && bp->byRelease && strcmp(ap->byRelease, bp->byRelease))
|
|
return 1;
|
|
|
|
if (ap->needsName && bp->needsName && strcmp(ap->needsName, bp->needsName))
|
|
return 1;
|
|
if (ap->needsVersion && bp->needsVersion && strcmp(ap->needsVersion, bp->needsVersion))
|
|
return 1;
|
|
if (ap->needsFlags && bp->needsFlags && ap->needsFlags != bp->needsFlags)
|
|
return 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* XXX FIXME: merge into problems */
|
|
void printDepProblems(FILE * fp,
|
|
const rpmDependencyConflict conflicts, int numConflicts)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < numConflicts; i++) {
|
|
int j;
|
|
|
|
/* Filter already displayed problems. */
|
|
for (j = 0; j < i; j++) {
|
|
if (!sameProblem(conflicts + i, conflicts + j))
|
|
/*@innerbreak@*/ break;
|
|
}
|
|
if (j < i)
|
|
continue;
|
|
|
|
fprintf(fp, "\t%s", conflicts[i].needsName);
|
|
if (conflicts[i].needsFlags)
|
|
printDepFlags(fp, conflicts[i].needsVersion,
|
|
conflicts[i].needsFlags);
|
|
|
|
if (conflicts[i].sense == RPMDEP_SENSE_REQUIRES)
|
|
fprintf(fp, _(" is needed by %s-%s-%s\n"), conflicts[i].byName,
|
|
conflicts[i].byVersion, conflicts[i].byRelease);
|
|
else
|
|
fprintf(fp, _(" conflicts with %s-%s-%s\n"), conflicts[i].byName,
|
|
conflicts[i].byVersion, conflicts[i].byRelease);
|
|
}
|
|
}
|
|
|
|
#if !defined(HAVE_VSNPRINTF)
|
|
/*@-shadow -bufferoverflowhigh @*/
|
|
static inline int vsnprintf(char * buf, /*@unused@*/ int nb,
|
|
const char * fmt, va_list ap)
|
|
{
|
|
return vsprintf(buf, fmt, ap);
|
|
}
|
|
/*@=shadow =bufferoverflowhigh @*/
|
|
#endif
|
|
#if !defined(HAVE_SNPRINTF)
|
|
static inline int snprintf(char * buf, int nb, const char * fmt, ...)
|
|
{
|
|
va_list ap;
|
|
int rc;
|
|
va_start(ap, fmt);
|
|
/*@-modunconnomods@*/
|
|
rc = vsnprintf(buf, nb, fmt, ap);
|
|
/*@=modunconnomods@*/
|
|
va_end(ap);
|
|
return rc;
|
|
}
|
|
#endif
|
|
|
|
const char * rpmProblemString(const rpmProblem prob)
|
|
{
|
|
/*@observer@*/
|
|
const char * pkgNEVR = (prob->pkgNEVR ? prob->pkgNEVR : "");
|
|
/*@observer@*/
|
|
const char * altNEVR = (prob->altNEVR ? prob->altNEVR : "");
|
|
/*@observer@*/
|
|
const char * str1 = (prob->str1 ? prob->str1 : "");
|
|
int nb = strlen(pkgNEVR) + strlen(str1) + strlen(altNEVR) + 100;
|
|
char * buf = xmalloc(nb+1);
|
|
int rc;
|
|
|
|
*buf = '\0';
|
|
switch (prob->type) {
|
|
case RPMPROB_BADARCH:
|
|
rc = snprintf(buf, nb,
|
|
_("package %s is for a different architecture"),
|
|
pkgNEVR);
|
|
break;
|
|
case RPMPROB_BADOS:
|
|
rc = snprintf(buf, nb,
|
|
_("package %s is for a different operating system"),
|
|
pkgNEVR);
|
|
break;
|
|
case RPMPROB_PKG_INSTALLED:
|
|
rc = snprintf(buf, nb,
|
|
_("package %s is already installed"),
|
|
pkgNEVR);
|
|
break;
|
|
case RPMPROB_BADRELOCATE:
|
|
rc = snprintf(buf, nb,
|
|
_("path %s in package %s is not relocatable"),
|
|
str1, pkgNEVR);
|
|
break;
|
|
case RPMPROB_NEW_FILE_CONFLICT:
|
|
rc = snprintf(buf, nb,
|
|
_("file %s conflicts between attempted installs of %s and %s"),
|
|
str1, pkgNEVR, altNEVR);
|
|
break;
|
|
case RPMPROB_FILE_CONFLICT:
|
|
rc = snprintf(buf, nb,
|
|
_("file %s from install of %s conflicts with file from package %s"),
|
|
str1, pkgNEVR, altNEVR);
|
|
break;
|
|
case RPMPROB_OLDPACKAGE:
|
|
rc = snprintf(buf, nb,
|
|
_("package %s (which is newer than %s) is already installed"),
|
|
altNEVR, pkgNEVR);
|
|
break;
|
|
case RPMPROB_DISKSPACE:
|
|
rc = snprintf(buf, nb,
|
|
_("installing package %s needs %ld%cb on the %s filesystem"),
|
|
pkgNEVR,
|
|
prob->ulong1 > (1024*1024)
|
|
? (prob->ulong1 + 1024 * 1024 - 1) / (1024 * 1024)
|
|
: (prob->ulong1 + 1023) / 1024,
|
|
prob->ulong1 > (1024*1024) ? 'M' : 'K',
|
|
str1);
|
|
break;
|
|
case RPMPROB_DISKNODES:
|
|
rc = snprintf(buf, nb,
|
|
_("installing package %s needs %ld inodes on the %s filesystem"),
|
|
pkgNEVR, (long)prob->ulong1, str1);
|
|
break;
|
|
case RPMPROB_BADPRETRANS:
|
|
rc = snprintf(buf, nb,
|
|
_("package %s pre-transaction syscall(s): %s failed: %s"),
|
|
pkgNEVR, str1, strerror(prob->ulong1));
|
|
break;
|
|
case RPMPROB_REQUIRES:
|
|
rc = snprintf(buf, nb, _("package %s has unsatisfied Requires: %s\n"),
|
|
pkgNEVR, altNEVR+2);
|
|
break;
|
|
case RPMPROB_CONFLICT:
|
|
rc = snprintf(buf, nb, _("package %s has unsatisfied Conflicts: %s\n"),
|
|
pkgNEVR, altNEVR+2);
|
|
break;
|
|
default:
|
|
rc = snprintf(buf, nb,
|
|
_("unknown error %d encountered while manipulating package %s"),
|
|
prob->type, pkgNEVR);
|
|
break;
|
|
}
|
|
|
|
buf[nb] = '\0';
|
|
return buf;
|
|
}
|
|
|
|
void rpmProblemPrint(FILE *fp, rpmProblem prob)
|
|
{
|
|
const char * msg = rpmProblemString(prob);
|
|
fprintf(fp, "%s\n", msg);
|
|
msg = _free(msg);
|
|
}
|
|
|
|
void rpmProblemSetPrint(FILE *fp, rpmProblemSet probs)
|
|
{
|
|
int i;
|
|
|
|
if (probs == NULL)
|
|
return;
|
|
|
|
if (fp == NULL)
|
|
fp = stderr;
|
|
|
|
for (i = 0; i < probs->numProblems; i++) {
|
|
rpmProblem myprob = probs->probs + i;
|
|
if (!myprob->ignoreProblem)
|
|
rpmProblemPrint(fp, myprob);
|
|
}
|
|
}
|