File: | lib/depends.c |
Warning: | line 455, column 6 Value stored to 'p' is never read |
1 | /** \ingroup rpmts |
2 | * \file lib/depends.c |
3 | */ |
4 | |
5 | #include "system.h" |
6 | |
7 | #include <rpm/rpmlib.h> /* rpmVersionCompare, rpmlib provides */ |
8 | #include <rpm/rpmtag.h> |
9 | #include <rpm/rpmlog.h> |
10 | #include <rpm/rpmdb.h> |
11 | #include <rpm/rpmds.h> |
12 | #include <rpm/rpmfi.h> |
13 | |
14 | #include "lib/rpmts_internal.h" |
15 | #include "lib/rpmte_internal.h" |
16 | #include "lib/rpmds_internal.h" |
17 | #include "lib/rpmfi_internal.h" /* rpmfiles stuff for now */ |
18 | #include "lib/misc.h" |
19 | |
20 | #include "lib/backend/dbiset.h" |
21 | |
22 | #include "debug.h" |
23 | |
24 | const char * const RPMVERSION = VERSION"4.14.90"; |
25 | |
26 | const char * const rpmNAME = PACKAGE"rpm"; |
27 | |
28 | const char * const rpmEVR = VERSION"4.14.90"; |
29 | |
30 | const int rpmFLAGS = RPMSENSE_EQUAL; |
31 | |
32 | #undef HASHTYPE |
33 | #undef HTKEYTYPE |
34 | #undef HTDATATYPE |
35 | |
36 | #define HASHTYPE depCache |
37 | #define HTKEYTYPE const char * |
38 | #define HTDATATYPE int |
39 | #include "lib/rpmhash.H" |
40 | #include "lib/rpmhash.C" |
41 | #undef HASHTYPE |
42 | #undef HTKEYTYPE |
43 | #undef HTDATATYPE |
44 | |
45 | #define HASHTYPE packageHash |
46 | #define HTKEYTYPE unsigned int |
47 | #define HTDATATYPE struct rpmte_s * |
48 | #include "rpmhash.C" |
49 | #undef HASHTYPE |
50 | #undef HTKEYTYPE |
51 | #undef HTDATATYPE |
52 | |
53 | #define HASHTYPE filedepHash |
54 | #define HTKEYTYPE const char * |
55 | #define HTDATATYPE const char * |
56 | #include "rpmhash.H" |
57 | #include "rpmhash.C" |
58 | #undef HASHTYPE |
59 | #undef HTKEYTYPE |
60 | #undef HTDATATYPE |
61 | |
62 | #define HASHTYPE depexistsHash |
63 | #define HTKEYTYPE const char * |
64 | #include "lib/rpmhash.H" |
65 | #include "lib/rpmhash.C" |
66 | #undef HASHTYPE |
67 | #undef HTKEYTYPE |
68 | |
69 | enum addOp_e { |
70 | RPMTE_INSTALL = 0, |
71 | RPMTE_UPGRADE = 1, |
72 | RPMTE_REINSTALL = 2, |
73 | }; |
74 | |
75 | /** |
76 | * Check for supported payload format in header. |
77 | * @param h header to check |
78 | * @return RPMRC_OK if supported, RPMRC_FAIL otherwise |
79 | */ |
80 | static rpmRC headerCheckPayloadFormat(Header h) { |
81 | rpmRC rc = RPMRC_OK; |
82 | const char *payloadfmt = headerGetString(h, RPMTAG_PAYLOADFORMAT); |
83 | /* |
84 | * XXX Ugh, rpm 3.x packages don't have payload format tag. Instead |
85 | * of blindly allowing, should check somehow (HDRID existence or... ?) |
86 | */ |
87 | if (!payloadfmt) return rc; |
88 | |
89 | if (!rstreq(payloadfmt, "cpio")) { |
90 | char *nevra = headerGetAsString(h, RPMTAG_NEVRA); |
91 | if (payloadfmt && rstreq(payloadfmt, "drpm")) { |
92 | rpmlog(RPMLOG_ERR, |
93 | _("%s is a Delta RPM and cannot be directly installed\n")dcgettext ("rpm", "%s is a Delta RPM and cannot be directly installed\n" , 5), |
94 | nevra); |
95 | } else { |
96 | rpmlog(RPMLOG_ERR, |
97 | _("Unsupported payload (%s) in package %s\n")dcgettext ("rpm", "Unsupported payload (%s) in package %s\n", 5), |
98 | payloadfmt ? payloadfmt : "none", nevra); |
99 | } |
100 | free(nevra); |
101 | rc = RPMRC_FAIL; |
102 | } |
103 | return rc; |
104 | } |
105 | |
106 | /** |
107 | * Add removed package instance to ordered transaction set. |
108 | * @param ts transaction set |
109 | * @param h header |
110 | * @param depends installed package of pair (or RPMAL_NOMATCH on erase) |
111 | * @return 0 on success |
112 | */ |
113 | static int removePackage(rpmts ts, Header h, rpmte depends) |
114 | { |
115 | tsMembers tsmem = rpmtsMembers(ts); |
116 | rpmte p, *pp; |
117 | unsigned int dboffset = headerGetInstance(h); |
118 | |
119 | /* Can't remove what's not installed */ |
120 | if (dboffset == 0) return 1; |
121 | |
122 | /* Filter out duplicate erasures. */ |
123 | if (packageHashGetEntry(tsmem->removedPackages, dboffset, &pp, NULL((void*)0), NULL((void*)0))) { |
124 | rpmteSetDependsOn(pp[0], depends); |
125 | return 0; |
126 | } |
127 | |
128 | p = rpmteNew(ts, h, TR_REMOVED, NULL((void*)0), NULL((void*)0)); |
129 | if (p == NULL((void*)0)) |
130 | return 1; |
131 | |
132 | packageHashAddEntry(tsmem->removedPackages, dboffset, p); |
133 | |
134 | if (tsmem->orderCount >= tsmem->orderAlloced) { |
135 | tsmem->orderAlloced += (tsmem->orderCount - tsmem->orderAlloced) + tsmem->delta; |
136 | tsmem->order = xrealloc(tsmem->order, sizeof(*tsmem->order) * tsmem->orderAlloced)rrealloc((tsmem->order), (sizeof(*tsmem->order) * tsmem ->orderAlloced)); |
137 | } |
138 | |
139 | rpmteSetDependsOn(p, depends); |
140 | |
141 | tsmem->order[tsmem->orderCount] = p; |
142 | tsmem->orderCount++; |
143 | |
144 | return 0; |
145 | } |
146 | |
147 | /* Return rpmdb iterator with removals optionally pruned out */ |
148 | rpmdbMatchIterator rpmtsPrunedIterator(rpmts ts, rpmDbiTagVal tag, |
149 | const char * key, int prune) |
150 | { |
151 | rpmdbMatchIterator mi = rpmtsInitIterator(ts, tag, key, 0); |
152 | if (prune) { |
153 | tsMembers tsmem = rpmtsMembers(ts); |
154 | rpmdbPruneIterator(mi, tsmem->removedPackages); |
155 | } |
156 | return mi; |
157 | } |
158 | |
159 | /** |
160 | * Decides whether to skip a package upgrade/obsoletion on TE color. |
161 | * |
162 | * @param tscolor color of this transaction |
163 | * @param color color of this transaction element |
164 | * @param ocolor header color of the upgraded/obsoleted package |
165 | * |
166 | * @return non-zero if the package should be skipped |
167 | */ |
168 | static int skipColor(rpm_color_t tscolor, rpm_color_t color, rpm_color_t ocolor) |
169 | { |
170 | return tscolor && color && ocolor && !(color & ocolor); |
171 | } |
172 | |
173 | /* Add erase elements for older packages of same color (if any). */ |
174 | static int addSelfErasures(rpmts ts, rpm_color_t tscolor, int op, |
175 | rpmte p, rpm_color_t hcolor, Header h) |
176 | { |
177 | Header oh; |
178 | rpmdbMatchIterator mi = rpmtsInitIterator(ts, RPMDBI_NAME, rpmteN(p), 0); |
179 | int rc = 0; |
180 | int cmp; |
181 | |
182 | while ((oh = rpmdbNextIterator(mi)) != NULL((void*)0)) { |
183 | /* Ignore colored packages not in our rainbow. */ |
184 | if (skipColor(tscolor, hcolor, headerGetNumber(oh, RPMTAG_HEADERCOLOR))) |
185 | continue; |
186 | |
187 | cmp = rpmVersionCompare(h, oh); |
188 | |
189 | /* On upgrade, skip packages that contain identical NEVR. */ |
190 | if ((op == RPMTE_UPGRADE) && (cmp == 0)) |
191 | continue; |
192 | |
193 | /* On reinstall, skip packages with differing NEVR. */ |
194 | if ((op == RPMTE_REINSTALL) && (cmp != 0)) |
195 | continue; |
196 | |
197 | if (removePackage(ts, oh, p)) { |
198 | rc = 1; |
199 | break; |
200 | } |
201 | } |
202 | rpmdbFreeIterator(mi); |
203 | return rc; |
204 | } |
205 | |
206 | /* Add erase elements for obsoleted packages of same color (if any). */ |
207 | static int addObsoleteErasures(rpmts ts, rpm_color_t tscolor, rpmte p) |
208 | { |
209 | rpmstrPool tspool = rpmtsPool(ts); |
210 | rpmds obsoletes = rpmdsInit(rpmteDS(p, RPMTAG_OBSOLETENAME)); |
211 | Header oh; |
212 | int rc = 0; |
213 | |
214 | while (rpmdsNext(obsoletes) >= 0 && rc == 0) { |
215 | const char * Name; |
216 | rpmdbMatchIterator mi = NULL((void*)0); |
217 | |
218 | if ((Name = rpmdsN(obsoletes)) == NULL((void*)0)) |
219 | continue; /* XXX can't happen */ |
220 | |
221 | mi = rpmtsPrunedIterator(ts, RPMDBI_NAME, Name, 1); |
222 | |
223 | while ((oh = rpmdbNextIterator(mi)) != NULL((void*)0)) { |
224 | const char *oarch = headerGetString(oh, RPMTAG_ARCH); |
225 | int match; |
226 | |
227 | /* avoid self-obsoleting packages */ |
228 | if (rstreq(rpmteN(p), Name) && rstreq(rpmteA(p), oarch)) { |
229 | char * ohNEVRA = headerGetAsString(oh, RPMTAG_NEVRA); |
230 | rpmlog(RPMLOG_DEBUG, " Not obsoleting: %s\n", ohNEVRA); |
231 | free(ohNEVRA); |
232 | continue; |
233 | } |
234 | |
235 | /* |
236 | * Rpm prior to 3.0.3 does not have versioned obsoletes. |
237 | * If no obsoletes version info is available, match all names. |
238 | */ |
239 | match = (rpmdsEVR(obsoletes) == NULL((void*)0)); |
240 | if (!match) |
241 | match = rpmdsMatches(tspool, oh, -1, obsoletes, 1, |
242 | _rpmds_nopromote); |
243 | |
244 | if (match) { |
245 | char * ohNEVRA = headerGetAsString(oh, RPMTAG_NEVRA); |
246 | rpmlog(RPMLOG_DEBUG, " Obsoletes: %s\t\terases %s\n", |
247 | rpmdsDNEVR(obsoletes)+2, ohNEVRA); |
248 | free(ohNEVRA); |
249 | |
250 | if (removePackage(ts, oh, p)) { |
251 | rc = 1; |
252 | break; |
253 | } |
254 | } |
255 | } |
256 | rpmdbFreeIterator(mi); |
257 | } |
258 | return rc; |
259 | } |
260 | |
261 | /* |
262 | * Lookup obsoletions in the added set. In theory there could |
263 | * be more than one obsoleting package, but we only care whether this |
264 | * has been obsoleted by *something* or not. |
265 | */ |
266 | static rpmte checkObsoleted(rpmal addedPackages, rpmds thisds) |
267 | { |
268 | rpmte p = NULL((void*)0); |
269 | rpmte *matches = NULL((void*)0); |
270 | |
271 | matches = rpmalAllObsoletes(addedPackages, thisds); |
272 | if (matches) { |
273 | p = matches[0]; |
274 | free(matches); |
275 | } |
276 | return p; |
277 | } |
278 | |
279 | /* |
280 | * Filtered rpmal lookup: on colored transactions there can be more |
281 | * than one identical NEVR but different arch, this must be allowed. |
282 | * Only a single element needs to be considred as there can only ever |
283 | * be one previous element to be replaced. |
284 | */ |
285 | static rpmte checkAdded(rpmal addedPackages, rpm_color_t tscolor, |
286 | rpmte te, rpmds ds) |
287 | { |
288 | rpmte p = NULL((void*)0); |
289 | rpmte *matches = NULL((void*)0); |
290 | |
291 | matches = rpmalAllSatisfiesDepend(addedPackages, ds); |
292 | if (matches) { |
293 | const char * arch = rpmteA(te); |
294 | const char * os = rpmteO(te); |
295 | |
296 | for (rpmte *m = matches; m && *m; m++) { |
297 | if (tscolor) { |
298 | const char * parch = rpmteA(*m); |
299 | const char * pos = rpmteO(*m); |
300 | |
301 | if (arch == NULL((void*)0) || parch == NULL((void*)0) || os == NULL((void*)0) || pos == NULL((void*)0)) |
302 | continue; |
303 | if (!rstreq(arch, parch) || !rstreq(os, pos)) |
304 | continue; |
305 | } |
306 | p = *m; |
307 | break; |
308 | } |
309 | free(matches); |
310 | } |
311 | return p; |
312 | } |
313 | |
314 | /* |
315 | * Check for previously added versions and obsoletions. |
316 | * Return index where to place this element, or -1 to skip. |
317 | * XXX OBSOLETENAME is a bit of a hack, but gives us what |
318 | * we want from rpmal: we're only interested in added package |
319 | * names here, not their provides. |
320 | */ |
321 | static int findPos(rpmts ts, rpm_color_t tscolor, rpmte te, int upgrade) |
322 | { |
323 | tsMembers tsmem = rpmtsMembers(ts); |
324 | int oc = tsmem->orderCount; |
325 | int skip = 0; |
326 | const char * name = rpmteN(te); |
327 | const char * evr = rpmteEVR(te); |
328 | rpmte p; |
329 | rpmstrPool tspool = rpmtsPool(ts); |
330 | rpmds oldChk = rpmdsSinglePool(tspool, RPMTAG_OBSOLETENAME, |
331 | name, evr, (RPMSENSE_LESS)); |
332 | rpmds newChk = rpmdsSinglePool(tspool, RPMTAG_OBSOLETENAME, |
333 | name, evr, (RPMSENSE_GREATER)); |
334 | rpmds sameChk = rpmdsSinglePool(tspool, RPMTAG_OBSOLETENAME, |
335 | name, evr, (RPMSENSE_EQUAL)); |
336 | rpmds obsChk = rpmteDS(te, RPMTAG_OBSOLETENAME); |
337 | |
338 | /* If obsoleting package has already been added, skip this. */ |
339 | if ((p = checkObsoleted(tsmem->addedPackages, rpmteDS(te, RPMTAG_NAME)))) { |
340 | skip = 1; |
341 | goto exit; |
342 | } |
343 | |
344 | /* If obsoleted package has already been added, replace with this. */ |
345 | rpmdsInit(obsChk); |
346 | while (rpmdsNext(obsChk) >= 0) { |
347 | /* XXX Obsoletes are not colored */ |
348 | if ((p = checkAdded(tsmem->addedPackages, 0, te, obsChk))) { |
349 | goto exit; |
350 | } |
351 | } |
352 | |
353 | /* If same NEVR has already been added, skip this. */ |
354 | if ((p = checkAdded(tsmem->addedPackages, tscolor, te, sameChk))) { |
355 | skip = 1; |
356 | goto exit; |
357 | } |
358 | |
359 | /* On upgrades... */ |
360 | if (upgrade) { |
361 | /* ...if newer NEVR has already been added, skip this. */ |
362 | if ((p = checkAdded(tsmem->addedPackages, tscolor, te, newChk))) { |
363 | skip = 1; |
364 | goto exit; |
365 | } |
366 | |
367 | /* ...if older NEVR has already been added, replace with this. */ |
368 | if ((p = checkAdded(tsmem->addedPackages, tscolor, te, oldChk))) { |
369 | goto exit; |
370 | } |
371 | } |
372 | |
373 | exit: |
374 | /* If we found a previous element we've something to say */ |
375 | if (p != NULL((void*)0) && rpmIsVerbose()(rpmlogSetMask(0) >= (1 << ((unsigned)(RPMLOG_INFO)) ))) { |
376 | const char *msg = skip ? |
377 | _("package %s was already added, skipping %s\n")dcgettext ("rpm", "package %s was already added, skipping %s\n" , 5) : |
378 | _("package %s was already added, replacing with %s\n")dcgettext ("rpm", "package %s was already added, replacing with %s\n" , 5); |
379 | rpmlog(RPMLOG_WARNING, msg, rpmteNEVRA(p), rpmteNEVRA(te)); |
380 | } |
381 | |
382 | /* If replacing a previous element, find out where it is. Pooh. */ |
383 | if (!skip && p != NULL((void*)0)) { |
384 | for (oc = 0; oc < tsmem->orderCount; oc++) { |
385 | if (p == tsmem->order[oc]) |
386 | break; |
387 | } |
388 | } |
389 | |
390 | rpmdsFree(oldChk); |
391 | rpmdsFree(newChk); |
392 | rpmdsFree(sameChk); |
393 | return (skip) ? -1 : oc; |
394 | } |
395 | |
396 | rpmal rpmtsCreateAl(rpmts ts, rpmElementTypes types) |
397 | { |
398 | rpmal al = NULL((void*)0); |
399 | if (ts) { |
400 | rpmte p; |
401 | rpmtsi pi; |
402 | rpmstrPool tspool = rpmtsPool(ts); |
403 | |
404 | al = rpmalCreate(tspool, (rpmtsNElements(ts) / 4) + 1, rpmtsFlags(ts), |
405 | rpmtsColor(ts), rpmtsPrefColor(ts)); |
406 | pi = rpmtsiInit(ts); |
407 | while ((p = rpmtsiNext(pi, types))) |
408 | rpmalAdd(al, p); |
409 | rpmtsiFree(pi); |
410 | } |
411 | return al; |
412 | } |
413 | |
414 | static int addPackage(rpmts ts, Header h, |
415 | fnpyKey key, int op, rpmRelocation * relocs) |
416 | { |
417 | tsMembers tsmem = rpmtsMembers(ts); |
418 | rpm_color_t tscolor = rpmtsColor(ts); |
419 | rpmte p = NULL((void*)0); |
420 | int isSource = headerIsSource(h); |
421 | int ec = 0; |
422 | int oc = tsmem->orderCount; |
423 | |
424 | /* Check for supported payload format if it's a package */ |
425 | if (key && headerCheckPayloadFormat(h) != RPMRC_OK) { |
426 | ec = 1; |
427 | goto exit; |
428 | } |
429 | |
430 | /* Source packages are never "upgraded" */ |
431 | if (isSource) |
432 | op = RPMTE_INSTALL; |
433 | |
434 | /* Do lazy (readonly?) open of rpm database for upgrades. */ |
435 | if (op != RPMTE_INSTALL && rpmtsGetRdb(ts) == NULL((void*)0) && rpmtsGetDBMode(ts) != -1) { |
436 | if ((ec = rpmtsOpenDB(ts, rpmtsGetDBMode(ts))) != 0) |
437 | goto exit; |
438 | } |
439 | |
440 | p = rpmteNew(ts, h, TR_ADDED, key, relocs); |
441 | if (p == NULL((void*)0)) { |
442 | ec = 1; |
443 | goto exit; |
444 | } |
445 | |
446 | /* Check binary packages for redundancies in the set */ |
447 | if (!isSource) { |
448 | oc = findPos(ts, tscolor, p, (op == RPMTE_UPGRADE)); |
449 | /* If we're replacing a previously added element, free the old one */ |
450 | if (oc >= 0 && oc < tsmem->orderCount) { |
451 | rpmalDel(tsmem->addedPackages, tsmem->order[oc]); |
452 | tsmem->order[oc] = rpmteFree(tsmem->order[oc]); |
453 | /* If newer NEVR was already added, we're done */ |
454 | } else if (oc < 0) { |
455 | p = rpmteFree(p); |
Value stored to 'p' is never read | |
456 | goto exit; |
457 | } |
458 | } |
459 | |
460 | if (oc >= tsmem->orderAlloced) { |
461 | tsmem->orderAlloced += (oc - tsmem->orderAlloced) + tsmem->delta; |
462 | tsmem->order = xrealloc(tsmem->order,rrealloc((tsmem->order), (tsmem->orderAlloced * sizeof( *tsmem->order))) |
463 | tsmem->orderAlloced * sizeof(*tsmem->order))rrealloc((tsmem->order), (tsmem->orderAlloced * sizeof( *tsmem->order))); |
464 | } |
465 | |
466 | |
467 | tsmem->order[oc] = p; |
468 | if (oc == tsmem->orderCount) { |
469 | tsmem->orderCount++; |
470 | } |
471 | |
472 | if (tsmem->addedPackages == NULL((void*)0)) { |
473 | tsmem->addedPackages = rpmalCreate(rpmtsPool(ts), 5, rpmtsFlags(ts), |
474 | tscolor, rpmtsPrefColor(ts)); |
475 | } |
476 | rpmalAdd(tsmem->addedPackages, p); |
477 | |
478 | /* Add erasure elements for old versions and obsoletions on upgrades */ |
479 | /* XXX TODO: If either of these fails, we'd need to undo all additions */ |
480 | if (op != RPMTE_INSTALL) |
481 | addSelfErasures(ts, tscolor, op, p, rpmteColor(p), h); |
482 | if (op == RPMTE_UPGRADE) |
483 | addObsoleteErasures(ts, tscolor, p); |
484 | |
485 | exit: |
486 | return ec; |
487 | } |
488 | |
489 | int rpmtsAddInstallElement(rpmts ts, Header h, |
490 | fnpyKey key, int upgrade, rpmRelocation * relocs) |
491 | { |
492 | int op = (upgrade == 0) ? RPMTE_INSTALL : RPMTE_UPGRADE; |
493 | if (rpmtsSetupTransactionPlugins(ts) == RPMRC_FAIL) |
494 | return 1; |
495 | return addPackage(ts, h, key, op, relocs); |
496 | } |
497 | |
498 | int rpmtsAddReinstallElement(rpmts ts, Header h, fnpyKey key) |
499 | { |
500 | if (rpmtsSetupTransactionPlugins(ts) == RPMRC_FAIL) |
501 | return 1; |
502 | /* TODO: pull relocations from installed package */ |
503 | /* TODO: should reinstall of non-installed package fail? */ |
504 | return addPackage(ts, h, key, RPMTE_REINSTALL, NULL((void*)0)); |
505 | } |
506 | |
507 | int rpmtsAddEraseElement(rpmts ts, Header h, int dboffset) |
508 | { |
509 | if (rpmtsSetupTransactionPlugins(ts) == RPMRC_FAIL) |
510 | return 1; |
511 | return removePackage(ts, h, NULL((void*)0)); |
512 | } |
513 | |
514 | /* Cached rpmdb provide lookup, returns 0 if satisfied, 1 otherwise */ |
515 | static int rpmdbProvides(rpmts ts, depCache dcache, rpmds dep, dbiIndexSet *matches) |
516 | { |
517 | const char * Name = rpmdsN(dep); |
518 | const char * DNEVR = rpmdsDNEVR(dep); |
519 | rpmTagVal deptag = rpmdsTagN(dep); |
520 | int *cachedrc = NULL((void*)0); |
521 | rpmdbMatchIterator mi = NULL((void*)0); |
522 | Header h = NULL((void*)0); |
523 | int rc = 0; |
524 | /* pretrans deps are provided by current packages, don't prune erasures */ |
525 | int prune = (rpmdsFlags(dep) & RPMSENSE_PRETRANS) ? 0 : 1; |
526 | unsigned int keyhash = 0; |
527 | |
528 | /* See if we already looked this up */ |
529 | if (prune && !matches) { |
530 | keyhash = depCacheKeyHash(dcache, DNEVR); |
531 | if (depCacheGetHEntry(dcache, DNEVR, keyhash, &cachedrc, NULL((void*)0), NULL((void*)0))) { |
532 | rc = *cachedrc; |
533 | rpmdsNotify(dep, "(cached)", rc); |
534 | return rc; |
535 | } |
536 | } |
537 | |
538 | if (matches) |
539 | *matches = dbiIndexSetNew(0); |
540 | /* |
541 | * See if a filename dependency is a real file in some package, |
542 | * taking file state into account: replaced, wrong colored and |
543 | * not installed files can not satisfy a dependency. |
544 | */ |
545 | if (deptag != RPMTAG_OBSOLETENAME && Name[0] == '/') { |
546 | mi = rpmtsPrunedIterator(ts, RPMDBI_INSTFILENAMES, Name, prune); |
547 | while ((h = rpmdbNextIterator(mi)) != NULL((void*)0)) { |
548 | /* Ignore self-conflicts */ |
549 | if (deptag == RPMTAG_CONFLICTNAME) { |
550 | unsigned int instance = headerGetInstance(h); |
551 | if (instance && instance == rpmdsInstance(dep)) |
552 | continue; |
553 | } |
554 | if (matches) { |
555 | dbiIndexSetAppendOne(*matches, headerGetInstance(h), 0, 0); |
556 | continue; |
557 | } |
558 | rpmdsNotify(dep, "(db files)", rc); |
559 | break; |
560 | } |
561 | rpmdbFreeIterator(mi); |
562 | } |
563 | |
564 | /* Otherwise look in provides no matter what the dependency looks like */ |
565 | if (h == NULL((void*)0)) { |
566 | rpmstrPool tspool = rpmtsPool(ts); |
567 | /* Obsoletes use just name alone, everything else uses provides */ |
568 | rpmTagVal dbtag = RPMDBI_PROVIDENAME; |
569 | int selfevr = 0; |
570 | if (deptag == RPMTAG_OBSOLETENAME) { |
571 | dbtag = RPMDBI_NAME; |
572 | selfevr = 1; |
573 | } |
574 | |
575 | mi = rpmtsPrunedIterator(ts, dbtag, Name, prune); |
576 | while ((h = rpmdbNextIterator(mi)) != NULL((void*)0)) { |
577 | /* Provide-indexes can't be used with nevr-only matching */ |
578 | int prix = (selfevr) ? -1 : rpmdbGetIteratorFileNum(mi); |
579 | int match = rpmdsMatches(tspool, h, prix, dep, selfevr, |
580 | _rpmds_nopromote); |
581 | /* Ignore self-obsoletes and self-conflicts */ |
582 | if (match && (deptag == RPMTAG_OBSOLETENAME || deptag == RPMTAG_CONFLICTNAME)) { |
583 | unsigned int instance = headerGetInstance(h); |
584 | if (instance && instance == rpmdsInstance(dep)) |
585 | match = 0; |
586 | } |
587 | if (match) { |
588 | if (matches) { |
589 | dbiIndexSetAppendOne(*matches, headerGetInstance(h), 0, 0); |
590 | continue; |
591 | } |
592 | rpmdsNotify(dep, "(db provides)", rc); |
593 | break; |
594 | } |
595 | } |
596 | rpmdbFreeIterator(mi); |
597 | } |
598 | rc = (h != NULL((void*)0)) ? 0 : 1; |
599 | |
600 | if (matches) { |
601 | dbiIndexSetUniq(*matches, 0); |
602 | rc = dbiIndexSetCount(*matches) ? 0 : 1; |
603 | } |
604 | |
605 | /* Cache the relatively expensive rpmdb lookup results */ |
606 | /* Caching the oddball non-pruned case would mess up other results */ |
607 | if (prune && !matches) |
608 | depCacheAddHEntry(dcache, xstrdup(DNEVR)rstrdup((DNEVR)), keyhash, rc); |
609 | return rc; |
610 | } |
611 | |
612 | static dbiIndexSet unsatisfiedDependSet(rpmts ts, rpmds dep) |
613 | { |
614 | dbiIndexSet set1 = NULL((void*)0), set2 = NULL((void*)0); |
615 | tsMembers tsmem = rpmtsMembers(ts); |
616 | rpmsenseFlags dsflags = rpmdsFlags(dep); |
617 | |
618 | if (dsflags & RPMSENSE_RPMLIB) |
619 | goto exit; |
620 | |
621 | if (rpmdsIsRich(dep)) { |
622 | rpmds ds1, ds2; |
623 | rpmrichOp op; |
624 | char *emsg = 0; |
625 | |
626 | if (rpmdsParseRichDep(dep, &ds1, &ds2, &op, &emsg) != RPMRC_OK) { |
627 | rpmdsNotify(dep, emsg ? emsg : "(parse error)", 1); |
628 | _free(emsg)rfree((emsg)); |
629 | goto exit; |
630 | } |
631 | /* only a subset of ops is supported in set mode */ |
632 | if (op != RPMRICHOP_WITH && op != RPMRICHOP_WITHOUT |
633 | && op != RPMRICHOP_OR && op != RPMRICHOP_SINGLE) { |
634 | rpmdsNotify(dep, "(unsupported op in set mode)", 1); |
635 | goto exit_rich; |
636 | } |
637 | |
638 | set1 = unsatisfiedDependSet(ts, ds1); |
639 | if (op == RPMRICHOP_SINGLE) |
640 | goto exit_rich; |
641 | if (op != RPMRICHOP_OR && dbiIndexSetCount(set1) == 0) |
642 | goto exit_rich; |
643 | set2 = unsatisfiedDependSet(ts, ds2); |
644 | if (op == RPMRICHOP_WITH) { |
645 | dbiIndexSetFilterSet(set1, set2, 0); |
646 | } else if (op == RPMRICHOP_WITHOUT) { |
647 | dbiIndexSetPruneSet(set1, set2, 0); |
648 | } else if (op == RPMRICHOP_OR) { |
649 | dbiIndexSetAppendSet(set1, set2, 0); |
650 | } |
651 | exit_rich: |
652 | ds1 = rpmdsFree(ds1); |
653 | ds2 = rpmdsFree(ds2); |
654 | goto exit; |
655 | } |
656 | |
657 | /* match database entries */ |
658 | rpmdbProvides(ts, NULL((void*)0), dep, &set1); |
659 | |
660 | /* Pretrans dependencies can't be satisfied by added packages. */ |
661 | if (!(dsflags & RPMSENSE_PRETRANS)) { |
662 | rpmte *matches = rpmalAllSatisfiesDepend(tsmem->addedPackages, dep); |
663 | if (matches) { |
664 | for (rpmte *p = matches; *p; p++) |
665 | dbiIndexSetAppendOne(set1, rpmalLookupTE(tsmem->addedPackages, *p), 1, 0); |
666 | } |
667 | _free(matches)rfree((matches)); |
668 | } |
669 | |
670 | exit: |
671 | set2 = dbiIndexSetFree(set2); |
672 | return set1 ? set1 : dbiIndexSetNew(0); |
673 | } |
674 | |
675 | /** |
676 | * Check dep for an unsatisfied dependency. |
677 | * @param ts transaction set |
678 | * @param dcache dependency cache |
679 | * @param dep dependency |
680 | * @return 0 if satisfied, 1 if not satisfied |
681 | */ |
682 | static int unsatisfiedDepend(rpmts ts, depCache dcache, rpmds dep) |
683 | { |
684 | tsMembers tsmem = rpmtsMembers(ts); |
685 | int rc; |
686 | int retrying = 0; |
687 | int adding = (rpmdsInstance(dep) == 0); |
688 | rpmsenseFlags dsflags = rpmdsFlags(dep); |
689 | |
690 | retry: |
691 | rc = 0; /* assume dependency is satisfied */ |
692 | |
693 | /* |
694 | * New features in rpm packaging implicitly add versioned dependencies |
695 | * on rpmlib provides. The dependencies look like "rpmlib(YaddaYadda)". |
696 | * Check those dependencies now. |
697 | */ |
698 | if (dsflags & RPMSENSE_RPMLIB) { |
699 | if (tsmem->rpmlib == NULL((void*)0)) |
700 | rpmdsRpmlibPool(rpmtsPool(ts), &(tsmem->rpmlib), NULL((void*)0)); |
701 | |
702 | if (tsmem->rpmlib != NULL((void*)0) && rpmdsSearch(tsmem->rpmlib, dep) >= 0) { |
703 | rpmdsNotify(dep, "(rpmlib provides)", rc); |
704 | goto exit; |
705 | } |
706 | goto unsatisfied; |
707 | } |
708 | |
709 | /* Dont look at pre-requisites of already installed packages */ |
710 | if (!adding && isInstallPreReq(dsflags)((dsflags) & ((RPMSENSE_SCRIPT_PRE|RPMSENSE_SCRIPT_POST|RPMSENSE_RPMLIB |RPMSENSE_KEYRING|RPMSENSE_PRETRANS|RPMSENSE_POSTTRANS) & ~RPMSENSE_PREREQ)) && !isErasePreReq(dsflags)((dsflags) & ((RPMSENSE_SCRIPT_PREUN|RPMSENSE_SCRIPT_POSTUN ) & ~RPMSENSE_PREREQ))) |
711 | goto exit; |
712 | |
713 | /* Handle rich dependencies */ |
714 | if (rpmdsIsRich(dep)) { |
715 | rpmds ds1, ds2; |
716 | rpmrichOp op; |
717 | char *emsg = 0; |
718 | if (rpmdsParseRichDep(dep, &ds1, &ds2, &op, &emsg) != RPMRC_OK) { |
719 | rc = rpmdsTagN(dep) == RPMTAG_CONFLICTNAME ? 0 : 1; |
720 | if (rpmdsInstance(dep) != 0) |
721 | rc = !rc; /* ignore errors for installed packages */ |
722 | rpmdsNotify(dep, emsg ? emsg : "(parse error)", rc); |
723 | _free(emsg)rfree((emsg)); |
724 | goto exit; |
725 | } |
726 | if (op == RPMRICHOP_WITH || op == RPMRICHOP_WITHOUT) { |
727 | /* switch to set mode processing */ |
728 | dbiIndexSet set = unsatisfiedDependSet(ts, dep); |
729 | rc = dbiIndexSetCount(set) ? 0 : 1; |
730 | dbiIndexSetFree(set); |
731 | ds1 = rpmdsFree(ds1); |
732 | ds2 = rpmdsFree(ds2); |
733 | rpmdsNotify(dep, "(rich)", rc); |
734 | goto exit; |
735 | } |
736 | if (op == RPMRICHOP_IF) { |
737 | if (rpmdsIsRich(ds2)) { |
738 | /* check if this is a IF...ELSE combination */ |
739 | rpmds ds21 = NULL((void*)0), ds22 = NULL((void*)0); |
740 | rpmrichOp op2; |
741 | if (rpmdsParseRichDep(ds2, &ds21, &ds22, &op2, NULL((void*)0)) == RPMRC_OK && op2 == RPMRICHOP_ELSE) { |
742 | rc = unsatisfiedDepend(ts, dcache, ds21); |
743 | if (rc) { |
744 | rpmdsFree(ds1); |
745 | ds1 = ds22; |
746 | ds22 = NULL((void*)0); |
747 | } |
748 | rc = 1; |
749 | } |
750 | rpmdsFree(ds21); |
751 | rpmdsFree(ds22); |
752 | } |
753 | if (!rc) |
754 | rc = !unsatisfiedDepend(ts, dcache, ds2); |
755 | } |
756 | if (op != RPMRICHOP_IF || rc) |
757 | rc = unsatisfiedDepend(ts, dcache, ds1); |
758 | if ((rc && op == RPMRICHOP_OR) || (!rc && op == RPMRICHOP_AND)) |
759 | rc = unsatisfiedDepend(ts, dcache, ds2); |
760 | ds1 = rpmdsFree(ds1); |
761 | ds2 = rpmdsFree(ds2); |
762 | rpmdsNotify(dep, "(rich)", rc); |
763 | goto exit; |
764 | } |
765 | |
766 | /* Pretrans dependencies can't be satisfied by added packages. */ |
767 | if (!(dsflags & RPMSENSE_PRETRANS)) { |
768 | rpmte *matches = rpmalAllSatisfiesDepend(tsmem->addedPackages, dep); |
769 | int match = matches && *matches; |
770 | _free(matches)rfree((matches)); |
771 | if (match) |
772 | goto exit; |
773 | } |
774 | |
775 | /* See if the rpmdb provides it */ |
776 | if (rpmdbProvides(ts, dcache, dep, NULL((void*)0)) == 0) |
777 | goto exit; |
778 | |
779 | /* Search for an unsatisfied dependency. */ |
780 | if (adding && !retrying && !(dsflags & RPMSENSE_PRETRANS)) { |
781 | int xx = rpmtsSolve(ts, dep); |
782 | if (xx == 0) |
783 | goto exit; |
784 | if (xx == -1) { |
785 | retrying = 1; |
786 | goto retry; |
787 | } |
788 | } |
789 | |
790 | unsatisfied: |
791 | if (dsflags & RPMSENSE_MISSINGOK) { |
792 | /* note the result, but missingok deps are never unsatisfied */ |
793 | rpmdsNotify(dep, "(missingok)", 1); |
794 | } else { |
795 | /* dependency is unsatisfied */ |
796 | rc = 1; |
797 | rpmdsNotify(dep, NULL((void*)0), rc); |
798 | } |
799 | |
800 | exit: |
801 | return rc; |
802 | } |
803 | |
804 | /* Check a dependency set for problems */ |
805 | static void checkDS(rpmts ts, depCache dcache, rpmte te, |
806 | const char * pkgNEVRA, rpmds ds, |
807 | rpm_color_t tscolor) |
808 | { |
809 | rpm_color_t dscolor; |
810 | /* require-problems are unsatisfied, others appear "satisfied" */ |
811 | int is_problem = (rpmdsTagN(ds) == RPMTAG_REQUIRENAME); |
812 | |
813 | ds = rpmdsInit(ds); |
814 | while (rpmdsNext(ds) >= 0) { |
815 | /* Ignore colored dependencies not in our rainbow. */ |
816 | dscolor = rpmdsColor(ds); |
817 | if (tscolor && dscolor && !(tscolor & dscolor)) |
818 | continue; |
819 | |
820 | if (unsatisfiedDepend(ts, dcache, ds) == is_problem) |
821 | rpmteAddDepProblem(te, pkgNEVRA, ds, NULL((void*)0)); |
822 | } |
823 | } |
824 | |
825 | /* Check a given dependency against installed packages */ |
826 | static void checkInstDeps(rpmts ts, depCache dcache, rpmte te, |
827 | rpmTag depTag, const char *dep) |
828 | { |
829 | Header h; |
830 | rpmdbMatchIterator mi = rpmtsPrunedIterator(ts, depTag, dep, 1); |
831 | rpmstrPool pool = rpmtsPool(ts); |
832 | /* require-problems are unsatisfied, others appear "satisfied" */ |
833 | int is_problem = (depTag == RPMTAG_REQUIRENAME); |
834 | |
835 | while ((h = rpmdbNextIterator(mi)) != NULL((void*)0)) { |
836 | char * pkgNEVRA; |
837 | rpmds ds; |
838 | |
839 | /* Ignore self-obsoletes and self-conflicts */ |
840 | if (depTag == RPMTAG_OBSOLETENAME || depTag == RPMTAG_CONFLICTNAME) { |
841 | unsigned int instance = headerGetInstance(h); |
842 | if (instance && instance == rpmteDBInstance(te)) |
843 | continue; |
844 | } |
845 | |
846 | pkgNEVRA = headerGetAsString(h, RPMTAG_NEVRA); |
847 | ds = rpmdsNewPool(pool, h, depTag, 0); |
848 | rpmdsSetIx(ds, rpmdbGetIteratorFileNum(mi)); |
849 | |
850 | if (unsatisfiedDepend(ts, dcache, ds) == is_problem) |
851 | rpmteAddDepProblem(te, pkgNEVRA, ds, NULL((void*)0)); |
852 | |
853 | rpmdsFree(ds); |
854 | free(pkgNEVRA); |
855 | } |
856 | rpmdbFreeIterator(mi); |
857 | } |
858 | |
859 | static void checkNotInstDeps(rpmts ts, depCache dcache, rpmte te, |
860 | rpmTag depTag, const char *dep) |
861 | { |
862 | char *ndep = rmalloc(strlen(dep) + 2); |
863 | ndep[0] = '!'; |
864 | strcpy(ndep + 1, dep); |
865 | checkInstDeps(ts, dcache, te, depTag, ndep); |
866 | free(ndep); |
867 | } |
868 | |
869 | static void checkInstFileDeps(rpmts ts, depCache dcache, rpmte te, |
870 | rpmTag depTag, rpmfi fi, int is_not, |
871 | filedepHash cache, fingerPrintCache *fpcp) |
872 | { |
873 | fingerPrintCache fpc = *fpcp; |
874 | fingerPrint * fp = NULL((void*)0); |
875 | const char *basename = rpmfiBN(fi); |
876 | const char *dirname; |
877 | const char **dirnames = 0; |
878 | int ndirnames = 0; |
879 | int i; |
880 | |
881 | filedepHashGetEntry(cache, basename, &dirnames, &ndirnames, NULL((void*)0)); |
882 | if (!ndirnames) |
883 | return; |
884 | if (!fpc) |
885 | *fpcp = fpc = fpCacheCreate(1001, NULL((void*)0)); |
886 | dirname = rpmfiDN(fi); |
887 | fpLookup(fpc, dirname, basename, &fp); |
888 | for (i = 0; i < ndirnames; i++) { |
889 | char *fpdep = 0; |
890 | const char *dep; |
891 | if (!strcmp(dirnames[i], dirname)) { |
892 | dep = rpmfiFN(fi); |
893 | } else if (fpLookupEquals(fpc, fp, dirnames[i], basename)) { |
894 | fpdep = rmalloc(strlen(dirnames[i]) + strlen(basename) + 1); |
895 | strcpy(fpdep, dirnames[i]); |
896 | strcat(fpdep, basename); |
897 | dep = fpdep; |
898 | } else { |
899 | continue; |
900 | } |
901 | if (!is_not) |
902 | checkInstDeps(ts, dcache, te, depTag, dep); |
903 | else |
904 | checkNotInstDeps(ts, dcache, te, depTag, dep); |
905 | _free(fpdep)rfree((fpdep)); |
906 | } |
907 | _free(fp)rfree((fp)); |
908 | } |
909 | |
910 | static void addFileDepToHash(filedepHash hash, char *key, size_t keylen) |
911 | { |
912 | int i; |
913 | char *basename, *dirname; |
914 | if (!keylen || key[0] != '/') |
915 | return; |
916 | for (i = keylen - 1; key[i] != '/'; i--) |
917 | ; |
918 | dirname = rmalloc(i + 2); |
919 | memcpy(dirname, key, i + 1); |
920 | dirname[i + 1] = 0; |
921 | basename = rmalloc(keylen - i); |
922 | memcpy(basename, key + i + 1, keylen - i - 1); |
923 | basename[keylen - i - 1] = 0; |
924 | filedepHashAddEntry(hash, basename, dirname); |
925 | } |
926 | |
927 | static void addDepToHash(depexistsHash hash, char *key, size_t keylen) |
928 | { |
929 | char *keystr; |
930 | if (!keylen) |
931 | return; |
932 | keystr = rmalloc(keylen + 1); |
933 | strncpy(keystr, key, keylen); |
934 | keystr[keylen] = 0; |
935 | depexistsHashAddEntry(hash, keystr); |
936 | } |
937 | |
938 | static void addIndexToDepHashes(rpmts ts, rpmDbiTag tag, |
939 | depexistsHash dephash, filedepHash filehash, |
940 | depexistsHash depnothash, filedepHash filenothash) |
941 | { |
942 | char *key; |
943 | size_t keylen; |
944 | rpmdbIndexIterator ii = rpmdbIndexIteratorInit(rpmtsGetRdb(ts), tag); |
945 | |
946 | if (!ii) |
947 | return; |
948 | while ((rpmdbIndexIteratorNext(ii, (const void**)&key, &keylen)) == 0) { |
949 | if (!key || !keylen) |
950 | continue; |
951 | if (*key == '!' && keylen > 1) { |
952 | key++; |
953 | keylen--; |
954 | if (*key == '/' && filenothash) |
955 | addFileDepToHash(filenothash, key, keylen); |
956 | if (depnothash) |
957 | addDepToHash(depnothash, key, keylen); |
958 | } else { |
959 | if (*key == '/' && filehash) |
960 | addFileDepToHash(filehash, key, keylen); |
961 | if (dephash) |
962 | addDepToHash(dephash, key, keylen); |
963 | } |
964 | } |
965 | rpmdbIndexIteratorFree(ii); |
966 | } |
967 | |
968 | |
969 | int rpmtsCheck(rpmts ts) |
970 | { |
971 | rpm_color_t tscolor = rpmtsColor(ts); |
972 | rpmtsi pi = NULL((void*)0); rpmte p; |
973 | int closeatexit = 0; |
974 | int rc = 0; |
975 | depCache dcache = NULL((void*)0); |
976 | filedepHash confilehash = NULL((void*)0); /* file conflicts of installed packages */ |
977 | filedepHash connotfilehash = NULL((void*)0); /* file conflicts of installed packages */ |
978 | depexistsHash connothash = NULL((void*)0); |
979 | filedepHash reqfilehash = NULL((void*)0); /* file requires of installed packages */ |
980 | filedepHash reqnotfilehash = NULL((void*)0); /* file requires of installed packages */ |
981 | depexistsHash reqnothash = NULL((void*)0); |
982 | fingerPrintCache fpc = NULL((void*)0); |
983 | rpmdb rdb = NULL((void*)0); |
984 | |
985 | (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_CHECK), 0); |
986 | |
987 | /* Do lazy, readonly, open of rpm database. */ |
988 | rdb = rpmtsGetRdb(ts); |
989 | if (rdb == NULL((void*)0) && rpmtsGetDBMode(ts) != -1) { |
990 | if ((rc = rpmtsOpenDB(ts, rpmtsGetDBMode(ts))) != 0) |
991 | goto exit; |
992 | rdb = rpmtsGetRdb(ts); |
993 | closeatexit = 1; |
994 | } |
995 | |
996 | if (rdb) |
997 | rpmdbCtrl(rdb, RPMDB_CTRL_LOCK_RO); |
998 | |
999 | /* XXX FIXME: figure some kind of heuristic for the cache size */ |
1000 | dcache = depCacheCreate(5001, rstrhash, strcmp, |
1001 | (depCacheFreeKey)rfree, NULL((void*)0)); |
1002 | |
1003 | /* build hashes of all confilict sdependencies */ |
1004 | confilehash = filedepHashCreate(257, rstrhash, strcmp, |
1005 | (filedepHashFreeKey)rfree, |
1006 | (filedepHashFreeData)rfree); |
1007 | connothash = depexistsHashCreate(257, rstrhash, strcmp, |
1008 | (filedepHashFreeKey)rfree); |
1009 | connotfilehash = filedepHashCreate(257, rstrhash, strcmp, |
1010 | (filedepHashFreeKey)rfree, |
1011 | (filedepHashFreeData)rfree); |
1012 | addIndexToDepHashes(ts, RPMTAG_CONFLICTNAME, NULL((void*)0), confilehash, connothash, connotfilehash); |
1013 | if (!filedepHashNumKeys(confilehash)) |
1014 | confilehash = filedepHashFree(confilehash); |
1015 | if (!depexistsHashNumKeys(connothash)) |
1016 | connothash= depexistsHashFree(connothash); |
1017 | if (!filedepHashNumKeys(connotfilehash)) |
1018 | connotfilehash = filedepHashFree(connotfilehash); |
1019 | |
1020 | /* build hashes of all requires dependencies */ |
1021 | reqfilehash = filedepHashCreate(8191, rstrhash, strcmp, |
1022 | (filedepHashFreeKey)rfree, |
1023 | (filedepHashFreeData)rfree); |
1024 | reqnothash = depexistsHashCreate(257, rstrhash, strcmp, |
1025 | (filedepHashFreeKey)rfree); |
1026 | reqnotfilehash = filedepHashCreate(257, rstrhash, strcmp, |
1027 | (filedepHashFreeKey)rfree, |
1028 | (filedepHashFreeData)rfree); |
1029 | addIndexToDepHashes(ts, RPMTAG_REQUIRENAME, NULL((void*)0), reqfilehash, reqnothash, reqnotfilehash); |
1030 | if (!filedepHashNumKeys(reqfilehash)) |
1031 | reqfilehash = filedepHashFree(reqfilehash); |
1032 | if (!depexistsHashNumKeys(reqnothash)) |
1033 | reqnothash= depexistsHashFree(reqnothash); |
1034 | if (!filedepHashNumKeys(reqnotfilehash)) |
1035 | reqnotfilehash = filedepHashFree(reqnotfilehash); |
1036 | |
1037 | /* |
1038 | * Look at all of the added packages and make sure their dependencies |
1039 | * are satisfied. |
1040 | */ |
1041 | pi = rpmtsiInit(ts); |
1042 | while ((p = rpmtsiNext(pi, TR_ADDED)) != NULL((void*)0)) { |
1043 | rpmds provides = rpmdsInit(rpmteDS(p, RPMTAG_PROVIDENAME)); |
1044 | |
1045 | rpmlog(RPMLOG_DEBUG, "========== +++ %s %s/%s 0x%x\n", |
1046 | rpmteNEVR(p), rpmteA(p), rpmteO(p), rpmteColor(p)); |
1047 | |
1048 | checkDS(ts, dcache, p, rpmteNEVRA(p), rpmteDS(p, RPMTAG_REQUIRENAME), |
1049 | tscolor); |
1050 | checkDS(ts, dcache, p, rpmteNEVRA(p), rpmteDS(p, RPMTAG_CONFLICTNAME), |
1051 | tscolor); |
1052 | checkDS(ts, dcache, p, rpmteNEVRA(p), rpmteDS(p, RPMTAG_OBSOLETENAME), |
1053 | tscolor); |
1054 | |
1055 | /* Check provides against conflicts in installed packages. */ |
1056 | while (rpmdsNext(provides) >= 0) { |
1057 | const char *dep = rpmdsN(provides); |
1058 | checkInstDeps(ts, dcache, p, RPMTAG_CONFLICTNAME, dep); |
1059 | if (reqnothash && depexistsHashHasEntry(reqnothash, dep)) |
1060 | checkNotInstDeps(ts, dcache, p, RPMTAG_REQUIRENAME, dep); |
1061 | } |
1062 | |
1063 | /* Skip obsoletion checks for source packages (ie build) */ |
1064 | if (rpmteIsSource(p)) |
1065 | continue; |
1066 | |
1067 | /* Check package name (not provides!) against installed obsoletes */ |
1068 | checkInstDeps(ts, dcache, p, RPMTAG_OBSOLETENAME, rpmteN(p)); |
1069 | |
1070 | /* Check filenames against installed conflicts */ |
1071 | if (confilehash || reqnotfilehash) { |
1072 | rpmfiles files = rpmteFiles(p); |
1073 | rpmfi fi = rpmfilesIter(files, RPMFI_ITER_FWD); |
1074 | while (rpmfiNext(fi) >= 0) { |
1075 | if (confilehash) |
1076 | checkInstFileDeps(ts, dcache, p, RPMTAG_CONFLICTNAME, fi, 0, confilehash, &fpc); |
1077 | if (reqnotfilehash) |
1078 | checkInstFileDeps(ts, dcache, p, RPMTAG_REQUIRENAME, fi, 1, reqnotfilehash, &fpc); |
1079 | } |
1080 | rpmfiFree(fi); |
1081 | rpmfilesFree(files); |
1082 | } |
1083 | } |
1084 | rpmtsiFree(pi); |
1085 | |
1086 | /* |
1087 | * Look at the removed packages and make sure they aren't critical. |
1088 | */ |
1089 | pi = rpmtsiInit(ts); |
1090 | while ((p = rpmtsiNext(pi, TR_REMOVED)) != NULL((void*)0)) { |
1091 | rpmds provides = rpmdsInit(rpmteDS(p, RPMTAG_PROVIDENAME)); |
1092 | |
1093 | rpmlog(RPMLOG_DEBUG, "========== --- %s %s/%s 0x%x\n", |
1094 | rpmteNEVR(p), rpmteA(p), rpmteO(p), rpmteColor(p)); |
1095 | |
1096 | /* Check provides and filenames against installed dependencies. */ |
1097 | while (rpmdsNext(provides) >= 0) { |
1098 | const char *dep = rpmdsN(provides); |
1099 | checkInstDeps(ts, dcache, p, RPMTAG_REQUIRENAME, dep); |
1100 | if (connothash && depexistsHashHasEntry(connothash, dep)) |
1101 | checkNotInstDeps(ts, dcache, p, RPMTAG_CONFLICTNAME, dep); |
1102 | } |
1103 | |
1104 | if (reqfilehash || connotfilehash) { |
1105 | rpmfiles files = rpmteFiles(p); |
1106 | rpmfi fi = rpmfilesIter(files, RPMFI_ITER_FWD);; |
1107 | while (rpmfiNext(fi) >= 0) { |
1108 | if (RPMFILE_IS_INSTALLED(rpmfiFState(fi))((rpmfiFState(fi)) == RPMFILE_STATE_NORMAL || (rpmfiFState(fi )) == RPMFILE_STATE_NETSHARED)) { |
1109 | if (reqfilehash) |
1110 | checkInstFileDeps(ts, dcache, p, RPMTAG_REQUIRENAME, fi, 0, reqfilehash, &fpc); |
1111 | if (connotfilehash) |
1112 | checkInstFileDeps(ts, dcache, p, RPMTAG_CONFLICTNAME, fi, 1, connotfilehash, &fpc); |
1113 | } |
1114 | } |
1115 | rpmfiFree(fi); |
1116 | rpmfilesFree(files); |
1117 | } |
1118 | } |
1119 | rpmtsiFree(pi); |
1120 | |
1121 | if (rdb) |
1122 | rpmdbCtrl(rdb, RPMDB_CTRL_UNLOCK_RO); |
1123 | |
1124 | exit: |
1125 | depCacheFree(dcache); |
1126 | filedepHashFree(confilehash); |
1127 | filedepHashFree(connotfilehash); |
1128 | depexistsHashFree(connothash); |
1129 | filedepHashFree(reqfilehash); |
1130 | filedepHashFree(reqnotfilehash); |
1131 | depexistsHashFree(reqnothash); |
1132 | fpCacheFree(fpc); |
1133 | |
1134 | (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_CHECK), 0); |
1135 | |
1136 | if (closeatexit) |
1137 | (void) rpmtsCloseDB(ts); |
1138 | return rc; |
1139 | } |