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