rpm 5.2.1
|
00001 00005 #include "system.h" 00006 00007 #include <rpmio.h> 00008 #include <rpmiotypes.h> /* XXX fnpyKey */ 00009 #include <rpmtypes.h> 00010 #include <yarn.h> 00011 00012 #define _RPMPS_INTERNAL 00013 #include "rpmps.h" 00014 00015 #include "debug.h" 00016 00017 /*@access fnpyKey @*/ 00018 /*@access rpmProblem @*/ 00019 00020 /*@unchecked@*/ 00021 int _rpmps_debug = 0; 00022 00023 /*@unchecked@*/ /*@only@*/ /*@null@*/ 00024 rpmioPool _rpmpsPool; 00025 00026 static rpmps rpmpsGetPool(/*@null@*/ rpmioPool pool) 00027 /*@globals _rpmpsPool, fileSystem, internalState @*/ 00028 /*@modifies pool, _rpmpsPool, fileSystem, internalState @*/ 00029 { 00030 rpmps ps; 00031 00032 if (_rpmpsPool == NULL) { 00033 _rpmpsPool = rpmioNewPool("ps", sizeof(*ps), -1, _rpmps_debug, 00034 NULL, NULL, NULL); 00035 pool = _rpmpsPool; 00036 } 00037 return (rpmps) rpmioGetPool(pool, sizeof(*ps)); 00038 } 00039 00040 int rpmpsNumProblems(rpmps ps) 00041 { 00042 int numProblems = 0; 00043 if (ps && ps->probs) 00044 numProblems = ps->numProblems; 00045 return numProblems; 00046 } 00047 00048 rpmpsi rpmpsInitIterator(rpmps ps) 00049 { 00050 rpmpsi psi = NULL; 00051 if (ps != NULL) { 00052 psi = xcalloc(1, sizeof(*psi)); 00053 /*@-assignexpose -castexpose @*/ 00054 psi->ps = rpmpsLink(ps, "iter ref"); 00055 /*@=assignexpose =castexpose @*/ 00056 psi->ix = -1; 00057 } 00058 return psi; 00059 } 00060 00061 rpmpsi rpmpsFreeIterator(rpmpsi psi) 00062 { 00063 if (psi != NULL) { 00064 psi->ps = rpmpsUnlink(psi->ps, "iter unref"); 00065 psi = _free(psi); 00066 } 00067 return NULL; 00068 } 00069 00070 int rpmpsNextIterator(rpmpsi psi) 00071 { 00072 int i = -1; 00073 00074 if (psi != NULL && ++psi->ix >= 0) { 00075 if (psi->ix < rpmpsNumProblems(psi->ps)) { 00076 i = psi->ix; 00077 } else { 00078 psi->ix = -1; 00079 } 00080 } 00081 return i; 00082 } 00083 00084 rpmProblem rpmpsProblem(rpmpsi psi) 00085 { 00086 rpmProblem p = NULL; 00087 if (psi != NULL && psi->ix >= 0 && psi->ix < rpmpsNumProblems(psi->ps)) { 00088 p = psi->ps->probs + psi->ix; 00089 } 00090 return p; 00091 } 00092 00093 rpmps rpmpsCreate(void) 00094 { 00095 #ifdef BUGGY 00096 rpmps ps = rpmpsGetPool(_rpmpsPool); 00097 #else 00098 rpmps ps = rpmpsGetPool(NULL); 00099 #endif 00100 return rpmpsLink(ps, "create"); 00101 } 00102 00103 rpmps rpmpsFree(rpmps ps) 00104 { 00105 if (ps == NULL) return NULL; 00106 yarnPossess(ps->_item.use); 00107 /*@-modfilesys@*/ 00108 if (_rpmps_debug) 00109 fprintf(stderr, "--> ps %p -- %ld %s at %s:%u\n", ps, yarnPeekLock(ps->_item.use), "rpmpsFree", __FILE__, __LINE__); 00110 /*@=modfilesys@*/ 00111 if (yarnPeekLock(ps->_item.use) <= 1L) { 00112 if (ps->probs) { 00113 int i; 00114 for (i = 0; i < ps->numProblems; i++) { 00115 rpmProblem p = ps->probs + i; 00116 p->pkgNEVR = _free(p->pkgNEVR); 00117 p->altNEVR = _free(p->altNEVR); 00118 p->str1 = _free(p->str1); 00119 } 00120 ps->probs = _free(ps->probs); 00121 } 00122 ps = (rpmps) rpmioPutPool((rpmioItem)ps); 00123 } else 00124 yarnTwist(ps->_item.use, BY, -1); 00125 return NULL; 00126 } 00127 00128 void rpmpsAppend(rpmps ps, rpmProblemType type, 00129 const char * pkgNEVR, fnpyKey key, 00130 const char * dn, const char * bn, 00131 const char * altNEVR, rpmuint64_t ulong1) 00132 { 00133 rpmProblem p; 00134 char *t; 00135 00136 if (ps == NULL) return; 00137 00138 if (ps->numProblems == ps->numProblemsAlloced) { 00139 if (ps->numProblemsAlloced) 00140 ps->numProblemsAlloced *= 2; 00141 else 00142 ps->numProblemsAlloced = 2; 00143 ps->probs = xrealloc(ps->probs, 00144 ps->numProblemsAlloced * sizeof(*ps->probs)); 00145 } 00146 00147 p = ps->probs + ps->numProblems; 00148 ps->numProblems++; 00149 memset(p, 0, sizeof(*p)); 00150 00151 p->type = type; 00152 p->key = key; 00153 p->ulong1 = ulong1; 00154 p->ignoreProblem = 0; 00155 00156 p->pkgNEVR = (pkgNEVR ? xstrdup(pkgNEVR) : NULL); 00157 p->altNEVR = (altNEVR ? xstrdup(altNEVR) : NULL); 00158 00159 p->str1 = NULL; 00160 if (dn != NULL || bn != NULL) { 00161 t = xcalloc(1, (dn != NULL ? strlen(dn) : 0) + 00162 (bn != NULL ? strlen(bn) : 0) + 1); 00163 p->str1 = t; 00164 if (dn != NULL) t = stpcpy(t, dn); 00165 if (bn != NULL) t = stpcpy(t, bn); 00166 } 00167 } 00168 00169 #define XSTRCMP(a, b) ((!(a) && !(b)) || ((a) && (b) && !strcmp((a), (b)))) 00170 00171 int rpmpsTrim(rpmps ps, rpmps filter) 00172 { 00173 rpmProblem t; 00174 rpmProblem f; 00175 int gotProblems = 0; 00176 00177 if (ps == NULL || ps->numProblems == 0) 00178 return 0; 00179 00180 if (filter == NULL) 00181 return (ps->numProblems == 0 ? 0 : 1); 00182 00183 t = ps->probs; 00184 f = filter->probs; 00185 00186 while ((f - filter->probs) < filter->numProblems) { 00187 if (!f->ignoreProblem) { 00188 f++; 00189 continue; 00190 } 00191 while ((t - ps->probs) < ps->numProblems) { 00192 /*@-nullpass@*/ /* LCL: looks good to me <shrug> */ 00193 if (f->type == t->type && t->key == f->key && 00194 XSTRCMP(f->str1, t->str1)) 00195 /*@innerbreak@*/ break; 00196 /*@=nullpass@*/ 00197 t++; 00198 gotProblems = 1; 00199 } 00200 00201 /* XXX This can't happen, but let's be sane in case it does. */ 00202 if ((t - ps->probs) == ps->numProblems) 00203 break; 00204 00205 t->ignoreProblem = f->ignoreProblem; 00206 t++, f++; 00207 } 00208 00209 if ((t - ps->probs) < ps->numProblems) 00210 gotProblems = 1; 00211 00212 return gotProblems; 00213 } 00214 00215 #if !defined(HAVE_VSNPRINTF) 00216 /*@-shadow -bufferoverflowhigh @*/ 00217 static inline int vsnprintf(/*@out@*/ char * buf, /*@unused@*/ int nb, 00218 const char * fmt, va_list ap) 00219 { 00220 return vsprintf(buf, fmt, ap); 00221 } 00222 /*@=shadow =bufferoverflowhigh @*/ 00223 #endif 00224 #if !defined(HAVE_SNPRINTF) 00225 static inline int snprintf(/*@out@*/ char * buf, int nb, const char * fmt, ...) 00226 { 00227 va_list ap; 00228 int rc; 00229 va_start(ap, fmt); 00230 rc = vsnprintf(buf, nb, fmt, ap); 00231 va_end(ap); 00232 return rc; 00233 } 00234 #endif 00235 00236 const char * rpmProblemString(const rpmProblem prob) 00237 { 00238 /*@observer@*/ 00239 const char * pkgNEVR = (prob->pkgNEVR ? prob->pkgNEVR : "?pkgNEVR?"); 00240 /*@observer@*/ 00241 const char * altNEVR = (prob->altNEVR ? prob->altNEVR : "? ?altNEVR?"); 00242 /*@observer@*/ 00243 const char * str1 = (prob->str1 ? prob->str1 : N_("different")); 00244 size_t nb = strlen(pkgNEVR) + strlen(str1) + strlen(altNEVR) + 1024; 00245 char * buf = xmalloc(nb+1); 00246 int rc; 00247 00248 switch (prob->type) { 00249 case RPMPROB_BADPLATFORM: 00250 rc = snprintf(buf, nb, 00251 _("package %s is intended for a %s platform"), 00252 pkgNEVR, str1); 00253 break; 00254 case RPMPROB_PKG_INSTALLED: 00255 rc = snprintf(buf, nb, 00256 _("package %s is already installed"), 00257 pkgNEVR); 00258 break; 00259 case RPMPROB_NOREPACKAGE: 00260 rc = snprintf(buf, nb, 00261 _("re-packaged package with %s: %s is missing"), 00262 str1, altNEVR); 00263 break; 00264 case RPMPROB_BADRELOCATE: 00265 rc = snprintf(buf, nb, 00266 _("path %s in package %s is not relocatable"), 00267 str1, pkgNEVR); 00268 break; 00269 case RPMPROB_NEW_FILE_CONFLICT: 00270 rc = snprintf(buf, nb, 00271 _("file %s conflicts between attempted installs of %s and %s"), 00272 str1, pkgNEVR, altNEVR); 00273 break; 00274 case RPMPROB_FILE_CONFLICT: 00275 rc = snprintf(buf, nb, 00276 _("file %s from install of %s conflicts with file from package %s"), 00277 str1, pkgNEVR, altNEVR); 00278 break; 00279 case RPMPROB_OLDPACKAGE: 00280 rc = snprintf(buf, nb, 00281 _("package %s (which is newer than %s) is already installed"), 00282 altNEVR, pkgNEVR); 00283 break; 00284 case RPMPROB_DISKSPACE: 00285 rc = snprintf(buf, nb, 00286 _("installing package %s needs %lu%cB on the %s filesystem"), 00287 pkgNEVR, 00288 (unsigned long) (prob->ulong1 > (1024*1024) 00289 ? (prob->ulong1 + 1024 * 1024 - 1) / (1024 * 1024) 00290 : (prob->ulong1 + 1023) / 1024), 00291 prob->ulong1 > (1024*1024) ? 'M' : 'K', 00292 str1); 00293 break; 00294 case RPMPROB_DISKNODES: 00295 rc = snprintf(buf, nb, 00296 _("installing package %s needs %lu inodes on the %s filesystem"), 00297 pkgNEVR, (unsigned long)prob->ulong1, str1); 00298 break; 00299 case RPMPROB_BADPRETRANS: 00300 rc = snprintf(buf, nb, 00301 _("package %s pre-transaction syscall(s): %s failed: %s"), 00302 pkgNEVR, str1, strerror((int)(prob->ulong1))); 00303 break; 00304 case RPMPROB_REQUIRES: 00305 rc = snprintf(buf, nb, _("%s is needed by %s%s"), 00306 altNEVR+2, 00307 (prob->ulong1 ? "" : _("(installed) ")), pkgNEVR); 00308 break; 00309 case RPMPROB_CONFLICT: 00310 rc = snprintf(buf, nb, _("%s conflicts with %s%s"), 00311 altNEVR+2, 00312 (prob->ulong1 ? "" : _("(installed) ")), pkgNEVR); 00313 break; 00314 case RPMPROB_RDONLY: 00315 rc = snprintf(buf, nb, 00316 _("installing package %s on %s rdonly filesystem"), 00317 pkgNEVR, str1); 00318 break; 00319 default: 00320 rc = snprintf(buf, nb, 00321 _("unknown error %d encountered while manipulating package %s"), 00322 prob->type, pkgNEVR); 00323 break; 00324 } 00325 00326 buf[nb] = '\0'; 00327 return buf; 00328 } 00329 00330 static int sameProblem(const rpmProblem ap, const rpmProblem bp) 00331 /*@*/ 00332 { 00333 if (ap->type != bp->type) 00334 return 1; 00335 if (ap->pkgNEVR) 00336 if (bp->pkgNEVR && strcmp(ap->pkgNEVR, bp->pkgNEVR)) 00337 return 1; 00338 if (ap->altNEVR) 00339 if (bp->altNEVR && strcmp(ap->altNEVR, bp->altNEVR)) 00340 return 1; 00341 if (ap->str1) 00342 if (bp->str1 && strcmp(ap->str1, bp->str1)) 00343 return 1; 00344 00345 if (ap->ulong1 != bp->ulong1) 00346 return 1; 00347 00348 return 0; 00349 } 00350 00351 void rpmpsPrint(FILE *fp, rpmps ps) 00352 { 00353 const char * msg; 00354 rpmpsi psi; 00355 int i; 00356 00357 if (ps == NULL || ps->probs == NULL || ps->numProblems <= 0) 00358 return; 00359 00360 if (fp == NULL) 00361 fp = stderr; 00362 00363 psi = rpmpsInitIterator(ps); 00364 while ((i = rpmpsNextIterator(psi)) >= 0) { 00365 rpmProblem p = rpmpsProblem(psi); 00366 rpmpsi psif; 00367 int j; 00368 00369 if (p->ignoreProblem) 00370 continue; 00371 00372 /* Filter already displayed problems. */ 00373 psif = rpmpsInitIterator(ps); 00374 while ((j = rpmpsNextIterator(psif)) < i) { 00375 if (!sameProblem(p, rpmpsProblem(psif))) 00376 /*@innerbreak@*/ break; 00377 } 00378 psif = rpmpsFreeIterator(psif); 00379 00380 if (j < i) 00381 continue; 00382 00383 msg = rpmProblemString(p); 00384 fprintf(fp, "\t%s\n", msg); 00385 msg = _free(msg); 00386 00387 } 00388 psi = rpmpsFreeIterator(psi); 00389 } 00390 00391 rpmProblem rpmpsGetProblem(rpmps ps, int num) 00392 { 00393 if (ps == NULL) 00394 return(NULL); 00395 /* XXX Retrieve last problem with negative index. */ 00396 if (num < 0) 00397 num = ps->numProblems - 1; 00398 if (num >= ps->numProblems) 00399 return(NULL); 00400 return (ps->probs + num); 00401 } 00402 00403 char * rpmProblemGetPkgNEVR(rpmProblem prob) 00404 { 00405 return prob->pkgNEVR; 00406 } 00407 00408 char * rpmProblemGetAltNEVR(rpmProblem prob) 00409 { 00410 return prob->altNEVR; 00411 } 00412 00413 char * rpmProblemGetStr(rpmProblem prob) 00414 { 00415 return prob->str1; 00416 } 00417 00418 rpmuint64_t rpmProblemGetDiskNeed(rpmProblem prob) 00419 { 00420 return prob->ulong1; 00421 } 00422 00423 rpmProblemType rpmProblemGetType(rpmProblem prob) 00424 { 00425 return prob->type; 00426 } 00427 00428 fnpyKey rpmProblemKey(rpmProblem prob) 00429 { 00430 return prob->key; 00431 }