1 /** \ingroup rpmdep
2 * \file lib/rpmte.c
3 * Routine(s) to handle an "rpmte" transaction element.
4 */
5 #include "system.h"
6
7 #include <rpm/rpmtypes.h>
8 #include <rpm/rpmlib.h> /* RPM_MACHTABLE_* */
9 #include <rpm/rpmmacro.h>
10 #include <rpm/rpmds.h>
11 #include <rpm/rpmfi.h>
12 #include <rpm/rpmts.h>
13 #include <rpm/rpmdb.h>
14 #include <rpm/rpmlog.h>
15
16 #include "lib/misc.h"
17 #include "lib/rpmplugins.h"
18 #include "lib/rpmte_internal.h"
19 /* strpool-related interfaces */
20 #include "lib/rpmfi_internal.h"
21 #include "lib/rpmds_internal.h"
22 #include "lib/rpmts_internal.h"
23
24 #include "debug.h"
25
26 /** \ingroup rpmte
27 * A single package instance to be installed/removed atomically.
28 */
29 struct rpmte_s {
30 rpmElementType type; /*!< Package disposition (installed/removed). */
31
32 Header h; /*!< Package header. */
33 char * NEVR; /*!< Package name-version-release. */
34 char * NEVRA; /*!< Package name-version-release.arch. */
35 char * name; /*!< Name: */
36 char * epoch;
37 char * version; /*!< Version: */
38 char * release; /*!< Release: */
39 char * arch; /*!< Architecture hint. */
40 char * os; /*!< Operating system hint. */
41 int isSource; /*!< (TR_ADDED) source rpm? */
42
43 rpmte depends; /*!< Package updated by this package (ERASE te) */
44 rpmte parent; /*!< Parent transaction element. */
45 unsigned int db_instance; /*!< Database instance (of removed pkgs) */
46 tsortInfo tsi; /*!< Dependency ordering chains. */
47
48 rpmds thisds; /*!< This package's provided NEVR. */
49 rpmds provides; /*!< Provides: dependencies. */
50 rpmds requires; /*!< Requires: dependencies. */
51 rpmds conflicts; /*!< Conflicts: dependencies. */
52 rpmds obsoletes; /*!< Obsoletes: dependencies. */
53 rpmds order; /*!< Order: dependencies. */
54 rpmds recommends; /*!< Recommends: dependencies. */
55 rpmds suggests; /*!< Suggests: dependencies. */
56 rpmds supplements; /*!< Supplements: dependencies. */
57 rpmds enhances; /*!< Enhances: dependencies. */
58 rpmfiles files; /*!< File information. */
59 rpmfi fi; /*!< File iterator (backwards compat) */
60 rpmps probs; /*!< Problems (relocations) */
61 rpmts ts; /*!< Parent transaction */
62
63 rpm_color_t color; /*!< Color bit(s) from package dependencies. */
64 rpm_loff_t pkgFileSize; /*!< No. of bytes in package file (approx). */
65 unsigned int headerSize; /*!< No. of bytes in package header */
66
67 fnpyKey key; /*!< (TR_ADDED) Retrieval key. */
68 rpmRelocation * relocs; /*!< (TR_ADDED) Payload file relocations. */
69 int nrelocs; /*!< (TR_ADDED) No. of relocations. */
70 uint8_t *badrelocs; /*!< (TR_ADDED) Bad relocations (or NULL) */
71 FD_t fd; /*!< (TR_ADDED) Payload file descriptor. */
72 int verified; /*!< (TR_ADDED) Verification status */
73 int addop; /*!< (TR_ADDED) RPMTE_INSTALL/UPDATE/REINSTALL */
74
75 #define RPMTE_HAVE_PRETRANS (1 << 0)
76 #define RPMTE_HAVE_POSTTRANS (1 << 1)
77 int transscripts; /*!< pre/posttrans script existence */
78 int failed; /*!< (parent) install/erase failed */
79
80 rpmfs fs;
81 };
82
83 /* forward declarations */
84 static void rpmteColorDS(rpmte te, rpmTag tag);
85 static int rpmteClose(rpmte te, int reset_fi);
86
rpmteCleanDS(rpmte te)87 void rpmteCleanDS(rpmte te)
88 {
89 te->thisds = rpmdsFree(te->thisds);
90 te->provides = rpmdsFree(te->provides);
91 te->requires = rpmdsFree(te->requires);
92 te->conflicts = rpmdsFree(te->conflicts);
93 te->obsoletes = rpmdsFree(te->obsoletes);
94 te->recommends = rpmdsFree(te->recommends);
95 te->suggests = rpmdsFree(te->suggests);
96 te->supplements = rpmdsFree(te->supplements);
97 te->enhances = rpmdsFree(te->enhances);
98 te->order = rpmdsFree(te->order);
99 }
100
getFiles(rpmte p,Header h)101 static rpmfiles getFiles(rpmte p, Header h)
102 {
103 /* TR_RPMDB handled as TR_ERASED for now, doesn't really matter */
104 rpmfiFlags fiflags;
105 fiflags = (p->type == TR_ADDED) ? (RPMFI_NOHEADER | RPMFI_FLAGS_INSTALL) :
106 (RPMFI_NOHEADER | RPMFI_FLAGS_ERASE);
107
108 /* relocate stuff in header if necessary */
109 if (rpmteType(p) == TR_ADDED && rpmfsFC(p->fs) > 0) {
110 if (!headerIsEntry(h, RPMTAG_ORIGBASENAMES)) {
111 if (rpmteIsSource(p)) {
112 /* Unlike binary packages, source relocation can fail */
113 if (rpmRelocateSrpmFileList(h, rpmtsRootDir(p->ts)) < 0) {
114 return NULL;
115 }
116 } else {
117 rpmRelocateFileList(p->relocs, p->nrelocs, p->fs, h);
118 }
119 }
120 }
121 return rpmfilesNew(rpmtsPool(p->ts), h, RPMTAG_BASENAMES, fiflags);
122 }
123
124 /**
125 * Initialize transaction element data from header.
126 * @param p transaction element
127 * @param h header
128 * @param key (TR_ADDED) package retrieval key (e.g. file name)
129 * @param relocs (TR_ADDED) package file relocations
130 */
addTE(rpmte p,Header h,fnpyKey key,rpmRelocation * relocs)131 static int addTE(rpmte p, Header h, fnpyKey key, rpmRelocation * relocs)
132 {
133 rpmstrPool tspool = rpmtsPool(p->ts);
134 struct rpmtd_s bnames;
135 int rc = 1; /* assume failure */
136
137 p->name = headerGetAsString(h, RPMTAG_NAME);
138 p->version = headerGetAsString(h, RPMTAG_VERSION);
139 p->release = headerGetAsString(h, RPMTAG_RELEASE);
140
141 /* name, version and release are required in all packages */
142 if (p->name == NULL || p->version == NULL || p->release == NULL)
143 goto exit;
144
145 p->epoch = headerGetAsString(h, RPMTAG_EPOCH);
146
147 p->arch = headerGetAsString(h, RPMTAG_ARCH);
148 p->os = headerGetAsString(h, RPMTAG_OS);
149
150 /* gpg-pubkey's dont have os or arch (sigh), for others they are required */
151 if (!rstreq(p->name, "gpg-pubkey") && (p->arch == NULL || p->os == NULL))
152 goto exit;
153
154 p->isSource = headerIsSource(h);
155
156 p->NEVR = headerGetAsString(h, RPMTAG_NEVR);
157 p->NEVRA = headerGetAsString(h, RPMTAG_NEVRA);
158
159 p->nrelocs = 0;
160 p->relocs = NULL;
161 p->badrelocs = NULL;
162 if (relocs != NULL)
163 rpmRelocationBuild(h, relocs, &p->nrelocs, &p->relocs, &p->badrelocs);
164
165 p->db_instance = headerGetInstance(h);
166 p->key = key;
167 p->fd = NULL;
168
169 p->pkgFileSize = 0;
170 p->headerSize = headerSizeof(h, HEADER_MAGIC_NO);
171
172 p->thisds = rpmdsThisPool(tspool, h, RPMTAG_PROVIDENAME, RPMSENSE_EQUAL);
173 p->provides = rpmdsNewPool(tspool, h, RPMTAG_PROVIDENAME, 0);
174 p->requires = rpmdsNewPool(tspool, h, RPMTAG_REQUIRENAME, 0);
175 p->conflicts = rpmdsNewPool(tspool, h, RPMTAG_CONFLICTNAME, 0);
176 p->obsoletes = rpmdsNewPool(tspool, h, RPMTAG_OBSOLETENAME, 0);
177 p->order = rpmdsNewPool(tspool, h, RPMTAG_ORDERNAME, 0);
178 p->recommends = rpmdsNewPool(tspool, h, RPMTAG_RECOMMENDNAME, 0);
179 p->suggests = rpmdsNewPool(tspool, h, RPMTAG_SUGGESTNAME, 0);
180 p->supplements = rpmdsNewPool(tspool, h, RPMTAG_SUPPLEMENTNAME, 0);
181 p->enhances = rpmdsNewPool(tspool, h, RPMTAG_ENHANCENAME, 0);
182
183 /* Relocation needs to know file count before rpmfiNew() */
184 headerGet(h, RPMTAG_BASENAMES, &bnames, HEADERGET_MINMEM);
185 p->fs = rpmfsNew(rpmtdCount(&bnames), (p->type == TR_ADDED));
186 rpmtdFreeData(&bnames);
187
188 p->files = getFiles(p, h);
189
190 /* Packages with no files return an empty file info set, NULL is an error */
191 if (p->files == NULL)
192 goto exit;
193
194 /* See if we have pre/posttrans scripts. */
195 p->transscripts |= (headerIsEntry(h, RPMTAG_PRETRANS) ||
196 headerIsEntry(h, RPMTAG_PRETRANSPROG)) ?
197 RPMTE_HAVE_PRETRANS : 0;
198 p->transscripts |= (headerIsEntry(h, RPMTAG_POSTTRANS) ||
199 headerIsEntry(h, RPMTAG_POSTTRANSPROG)) ?
200 RPMTE_HAVE_POSTTRANS : 0;
201
202 rpmteColorDS(p, RPMTAG_PROVIDENAME);
203 rpmteColorDS(p, RPMTAG_REQUIRENAME);
204
205 if (p->type == TR_ADDED)
206 p->pkgFileSize = headerGetNumber(h, RPMTAG_LONGSIGSIZE) + 96 + 256;
207
208 rc = 0;
209
210 exit:
211 return rc;
212 }
213
rpmteFree(rpmte te)214 rpmte rpmteFree(rpmte te)
215 {
216 if (te != NULL) {
217 if (te->relocs) {
218 for (int i = 0; i < te->nrelocs; i++) {
219 free(te->relocs[i].oldPath);
220 free(te->relocs[i].newPath);
221 }
222 free(te->relocs);
223 free(te->badrelocs);
224 }
225
226 free(te->os);
227 free(te->arch);
228 free(te->epoch);
229 free(te->name);
230 free(te->version);
231 free(te->release);
232 free(te->NEVR);
233 free(te->NEVRA);
234
235 fdFree(te->fd);
236 rpmfiFree(te->fi);
237 rpmfilesFree(te->files);
238 headerFree(te->h);
239 rpmfsFree(te->fs);
240 rpmpsFree(te->probs);
241 rpmteCleanDS(te);
242
243 memset(te, 0, sizeof(*te)); /* XXX trash and burn */
244 free(te);
245 }
246 return NULL;
247 }
248
rpmteNew(rpmts ts,Header h,rpmElementType type,fnpyKey key,rpmRelocation * relocs,int addop)249 rpmte rpmteNew(rpmts ts, Header h, rpmElementType type, fnpyKey key,
250 rpmRelocation * relocs, int addop)
251 {
252 rpmte p = xcalloc(1, sizeof(*p));
253 p->ts = ts;
254 p->type = type;
255 p->addop = addop;
256 p->verified = RPMSIG_UNVERIFIED_TYPE;
257
258 if (addTE(p, h, key, relocs)) {
259 rpmteFree(p);
260 return NULL;
261 }
262
263 return p;
264 }
265
rpmteDBInstance(rpmte te)266 unsigned int rpmteDBInstance(rpmte te)
267 {
268 return (te != NULL ? te->db_instance : 0);
269 }
270
rpmteSetDBInstance(rpmte te,unsigned int instance)271 void rpmteSetDBInstance(rpmte te, unsigned int instance)
272 {
273 if (te != NULL)
274 te->db_instance = instance;
275 }
276
rpmteHeader(rpmte te)277 Header rpmteHeader(rpmte te)
278 {
279 return (te != NULL && te->h != NULL ? headerLink(te->h) : NULL);
280 }
281
rpmteSetHeader(rpmte te,Header h)282 Header rpmteSetHeader(rpmte te, Header h)
283 {
284 if (te != NULL) {
285 te->h = headerFree(te->h);
286 if (h != NULL)
287 te->h = headerLink(h);
288 }
289 return NULL;
290 }
291
rpmteType(rpmte te)292 rpmElementType rpmteType(rpmte te)
293 {
294 /* XXX returning negative for unsigned type */
295 return (te != NULL ? te->type : -1);
296 }
297
rpmteN(rpmte te)298 const char * rpmteN(rpmte te)
299 {
300 return (te != NULL ? te->name : NULL);
301 }
302
rpmteE(rpmte te)303 const char * rpmteE(rpmte te)
304 {
305 return (te != NULL ? te->epoch : NULL);
306 }
307
rpmteV(rpmte te)308 const char * rpmteV(rpmte te)
309 {
310 return (te != NULL ? te->version : NULL);
311 }
312
rpmteR(rpmte te)313 const char * rpmteR(rpmte te)
314 {
315 return (te != NULL ? te->release : NULL);
316 }
317
rpmteA(rpmte te)318 const char * rpmteA(rpmte te)
319 {
320 return (te != NULL ? te->arch : NULL);
321 }
322
rpmteO(rpmte te)323 const char * rpmteO(rpmte te)
324 {
325 return (te != NULL ? te->os : NULL);
326 }
327
rpmteIsSource(rpmte te)328 int rpmteIsSource(rpmte te)
329 {
330 return (te != NULL ? te->isSource : 0);
331 }
332
rpmteColor(rpmte te)333 rpm_color_t rpmteColor(rpmte te)
334 {
335 return (te != NULL ? te->color : 0);
336 }
337
rpmteSetColor(rpmte te,rpm_color_t color)338 rpm_color_t rpmteSetColor(rpmte te, rpm_color_t color)
339 {
340 rpm_color_t ocolor = 0;
341 if (te != NULL) {
342 ocolor = te->color;
343 te->color = color;
344 }
345 return ocolor;
346 }
347
rpmtePkgFileSize(rpmte te)348 rpm_loff_t rpmtePkgFileSize(rpmte te)
349 {
350 return (te != NULL ? te->pkgFileSize : 0);
351 }
352
rpmteHeaderSize(rpmte te)353 unsigned int rpmteHeaderSize(rpmte te)
354 {
355 return (te != NULL ? te->headerSize : 0);
356 }
357
rpmteParent(rpmte te)358 rpmte rpmteParent(rpmte te)
359 {
360 return (te != NULL ? te->parent : NULL);
361 }
362
rpmteSetParent(rpmte te,rpmte pte)363 rpmte rpmteSetParent(rpmte te, rpmte pte)
364 {
365 rpmte opte = NULL;
366 if (te != NULL) {
367 opte = te->parent;
368 te->parent = pte;
369 }
370 return opte;
371 }
372
rpmteTSI(rpmte te)373 tsortInfo rpmteTSI(rpmte te)
374 {
375 return te->tsi;
376 }
377
rpmteSetTSI(rpmte te,tsortInfo tsi)378 void rpmteSetTSI(rpmte te, tsortInfo tsi)
379 {
380 te->tsi = tsi;
381 }
382
rpmteSetDependsOn(rpmte te,rpmte depends)383 void rpmteSetDependsOn(rpmte te, rpmte depends)
384 {
385 te->depends = depends;
386 }
387
rpmteDependsOn(rpmte te)388 rpmte rpmteDependsOn(rpmte te)
389 {
390 return te->depends;
391 }
392
rpmteDBOffset(rpmte te)393 int rpmteDBOffset(rpmte te)
394 {
395 return rpmteDBInstance(te);
396 }
397
rpmteEVR(rpmte te)398 const char * rpmteEVR(rpmte te)
399 {
400 return (te != NULL ? te->NEVR + strlen(te->name) + 1 : NULL);
401 }
402
rpmteNEVR(rpmte te)403 const char * rpmteNEVR(rpmte te)
404 {
405 return (te != NULL ? te->NEVR : NULL);
406 }
407
rpmteNEVRA(rpmte te)408 const char * rpmteNEVRA(rpmte te)
409 {
410 return (te != NULL ? te->NEVRA : NULL);
411 }
412
rpmteSetFd(rpmte te,FD_t fd)413 FD_t rpmteSetFd(rpmte te, FD_t fd)
414 {
415 if (te != NULL) {
416 if (te->fd != NULL)
417 te->fd = fdFree(te->fd);
418 if (fd != NULL)
419 te->fd = fdLink(fd);
420 }
421 return NULL;
422 }
423
rpmteKey(rpmte te)424 fnpyKey rpmteKey(rpmte te)
425 {
426 return (te != NULL ? te->key : NULL);
427 }
428
rpmteDS(rpmte te,rpmTagVal tag)429 rpmds rpmteDS(rpmte te, rpmTagVal tag)
430 {
431 if (te == NULL)
432 return NULL;
433
434 switch (tag) {
435 case RPMTAG_NAME: return te->thisds;
436 case RPMTAG_PROVIDENAME: return te->provides;
437 case RPMTAG_REQUIRENAME: return te->requires;
438 case RPMTAG_CONFLICTNAME: return te->conflicts;
439 case RPMTAG_OBSOLETENAME: return te->obsoletes;
440 case RPMTAG_ORDERNAME: return te->order;
441 case RPMTAG_RECOMMENDNAME: return te->recommends;
442 case RPMTAG_SUGGESTNAME: return te->suggests;
443 case RPMTAG_SUPPLEMENTNAME: return te->supplements;
444 case RPMTAG_ENHANCENAME: return te->enhances;
445 default: break;
446 }
447 return NULL;
448 }
449
rpmteCleanFiles(rpmte te)450 void rpmteCleanFiles(rpmte te)
451 {
452 if (te != NULL) {
453 te->fi = rpmfiFree(te->fi);
454 te->files = rpmfilesFree(te->files);
455 }
456 }
457
rpmteFI(rpmte te)458 rpmfi rpmteFI(rpmte te)
459 {
460 if (te == NULL)
461 return NULL;
462
463 if (te->fi == NULL)
464 te->fi = rpmfilesIter(te->files, RPMFI_ITER_FWD);
465
466 return te->fi; /* XXX take fi reference here? */
467 }
468
rpmteFiles(rpmte te)469 rpmfiles rpmteFiles(rpmte te)
470 {
471 return (te != NULL) ? rpmfilesLink(te->files) : NULL;
472 }
473
rpmteColorDS(rpmte te,rpmTag tag)474 static void rpmteColorDS(rpmte te, rpmTag tag)
475 {
476 rpmfi fi;
477 rpmds ds = rpmteDS(te, tag);
478 char deptype = 'R';
479 char mydt;
480 const uint32_t * ddict;
481 rpm_color_t * colors;
482 rpm_color_t val;
483 int Count;
484 unsigned ix;
485 int ndx, i;
486
487 if (!(te && (Count = rpmdsCount(ds)) > 0 && rpmfilesFC(te->files) > 0))
488 return;
489
490 switch (tag) {
491 default:
492 return;
493 break;
494 case RPMTAG_PROVIDENAME:
495 deptype = 'P';
496 break;
497 case RPMTAG_REQUIRENAME:
498 deptype = 'R';
499 break;
500 }
501
502 colors = xcalloc(Count, sizeof(*colors));
503
504 /* Calculate dependency color. */
505 fi = rpmfilesIter(te->files, RPMFI_ITER_FWD);
506 while (rpmfiNext(fi) >= 0) {
507 val = rpmfiFColor(fi);
508 ddict = NULL;
509 ndx = rpmfiFDepends(fi, &ddict);
510 if (ddict != NULL)
511 while (ndx-- > 0) {
512 ix = *ddict++;
513 mydt = ((ix >> 24) & 0xff);
514 if (mydt != deptype)
515 continue;
516 ix &= 0x00ffffff;
517 assert (ix < Count);
518 colors[ix] |= val;
519 }
520 }
521
522 /* Set color values in dependency set. */
523 ds = rpmdsInit(ds);
524 while ((i = rpmdsNext(ds)) >= 0) {
525 val = colors[i];
526 te->color |= val;
527 (void) rpmdsSetColor(ds, val);
528 }
529 free(colors);
530 rpmfiFree(fi);
531 }
532
rpmteDBHeader(rpmte te)533 static Header rpmteDBHeader(rpmte te)
534 {
535 Header h = NULL;
536 rpmdbMatchIterator mi;
537
538 mi = rpmtsInitIterator(te->ts, RPMDBI_PACKAGES,
539 &te->db_instance, sizeof(te->db_instance));
540 /* iterator returns weak refs, grab hold of header */
541 if ((h = rpmdbNextIterator(mi)))
542 h = headerLink(h);
543 rpmdbFreeIterator(mi);
544 return h;
545 }
546
rpmteFDHeader(rpmte te)547 static Header rpmteFDHeader(rpmte te)
548 {
549 Header h = NULL;
550 te->fd = rpmtsNotify(te->ts, te, RPMCALLBACK_INST_OPEN_FILE, 0, 0);
551 if (te->fd != NULL) {
552 rpmVSFlags ovsflags;
553 rpmRC pkgrc;
554
555 ovsflags = rpmtsSetVSFlags(te->ts,
556 rpmtsVSFlags(te->ts) | RPMVSF_NEEDPAYLOAD);
557 pkgrc = rpmReadPackageFile(te->ts, te->fd, rpmteNEVRA(te), &h);
558 rpmtsSetVSFlags(te->ts, ovsflags);
559 switch (pkgrc) {
560 default:
561 rpmteClose(te, 1);
562 break;
563 case RPMRC_NOTTRUSTED:
564 case RPMRC_NOKEY:
565 case RPMRC_OK:
566 break;
567 }
568 }
569 return h;
570 }
571
rpmteOpen(rpmte te,int reload_fi)572 static int rpmteOpen(rpmte te, int reload_fi)
573 {
574 int rc = 0; /* assume failure */
575 Header h = NULL;
576 if (te == NULL || te->ts == NULL || rpmteFailed(te))
577 goto exit;
578
579 rpmteSetHeader(te, NULL);
580
581 switch (rpmteType(te)) {
582 case TR_ADDED:
583 h = rpmteDBInstance(te) ? rpmteDBHeader(te) : rpmteFDHeader(te);
584 break;
585 case TR_REMOVED:
586 case TR_RPMDB:
587 h = rpmteDBHeader(te);
588 break;
589 }
590 if (h != NULL) {
591 if (reload_fi) {
592 /* This can fail if we get a different, bad header from callback */
593 te->files = getFiles(te, h);
594 rc = (te->files != NULL);
595 } else {
596 rc = 1;
597 }
598
599 rpmteSetHeader(te, h);
600 headerFree(h);
601 }
602
603 exit:
604 return rc;
605 }
606
rpmteClose(rpmte te,int reset_fi)607 static int rpmteClose(rpmte te, int reset_fi)
608 {
609 if (te == NULL || te->ts == NULL)
610 return 0;
611
612 switch (te->type) {
613 case TR_ADDED:
614 if (te->fd) {
615 rpmtsNotify(te->ts, te, RPMCALLBACK_INST_CLOSE_FILE, 0, 0);
616 te->fd = NULL;
617 }
618 break;
619 case TR_REMOVED:
620 case TR_RPMDB:
621 /* eventually we'll want notifications for erase open too */
622 break;
623 }
624 rpmteSetHeader(te, NULL);
625 if (reset_fi) {
626 rpmteCleanFiles(te);
627 }
628 return 1;
629 }
630
rpmtePayload(rpmte te)631 FD_t rpmtePayload(rpmte te)
632 {
633 FD_t payload = NULL;
634 if (te->fd && te->h) {
635 const char *compr = headerGetString(te->h, RPMTAG_PAYLOADCOMPRESSOR);
636 char *ioflags = rstrscat(NULL, "r.", compr ? compr : "gzip", NULL);
637 payload = Fdopen(fdDup(Fileno(te->fd)), ioflags);
638 free(ioflags);
639 }
640 return payload;
641 }
642
rpmteMarkFailed(rpmte te)643 static int rpmteMarkFailed(rpmte te)
644 {
645 te->failed++;
646
647 /* No need to do this more than once, avoid recursion loops */
648 if (te->failed == 1) {
649 rpmtsi pi = rpmtsiInit(te->ts);
650 rpmte p;
651
652 /* XXX we can do a much better here than this... */
653 while ((p = rpmtsiNext(pi, TR_REMOVED))) {
654 if (rpmteDependsOn(p) == te) {
655 rpmteMarkFailed(p);
656 }
657 }
658 rpmtsiFree(pi);
659 }
660 return te->failed;
661 }
662
rpmteFailed(rpmte te)663 int rpmteFailed(rpmte te)
664 {
665 return (te != NULL) ? te->failed : -1;
666 }
667
rpmteHaveTransScript(rpmte te,rpmTagVal tag)668 int rpmteHaveTransScript(rpmte te, rpmTagVal tag)
669 {
670 int rc = 0;
671 if (tag == RPMTAG_PRETRANS) {
672 rc = (te->transscripts & RPMTE_HAVE_PRETRANS);
673 } else if (tag == RPMTAG_POSTTRANS) {
674 rc = (te->transscripts & RPMTE_HAVE_POSTTRANS);
675 }
676 return rc;
677 }
678
rpmteProblems(rpmte te)679 rpmps rpmteProblems(rpmte te)
680 {
681 return (te != NULL) ? rpmpsLink(te->probs) : NULL;
682 }
683
rpmteCleanProblems(rpmte te)684 void rpmteCleanProblems(rpmte te)
685 {
686 if (te != NULL && te->probs != NULL) {
687 te->probs = rpmpsFree(te->probs);
688 }
689 }
690
appendProblem(rpmte te,rpmProblemType type,fnpyKey key,const char * altNEVR,const char * str,uint64_t number)691 static void appendProblem(rpmte te, rpmProblemType type,
692 fnpyKey key, const char * altNEVR,
693 const char * str, uint64_t number)
694 {
695 rpmProblem o;
696 rpmProblem p = rpmProblemCreate(type, te->NEVRA, key, altNEVR, str, number);
697 rpmpsi psi = rpmpsInitIterator(te->probs);
698
699 /* Only add new, unique problems to the set */
700 while ((o = rpmpsiNext(psi))) {
701 if (rpmProblemCompare(p, o) == 0)
702 break;
703 }
704 rpmpsFreeIterator(psi);
705
706 if (o == NULL) {
707 if (te->probs == NULL)
708 te->probs = rpmpsCreate();
709 rpmpsAppendProblem(te->probs, p);
710 rpmteMarkFailed(te);
711 }
712 rpmProblemFree(p);
713 }
714
rpmteAddProblem(rpmte te,rpmProblemType type,const char * altNEVR,const char * str,uint64_t number)715 void rpmteAddProblem(rpmte te, rpmProblemType type,
716 const char *altNEVR, const char *str, uint64_t number)
717 {
718 if (te != NULL) {
719 appendProblem(te, type, rpmteKey(te), altNEVR, str, number);
720 }
721 }
722
rpmteAddDepProblem(rpmte te,const char * altNEVR,rpmds ds,fnpyKey * suggestedKeys)723 void rpmteAddDepProblem(rpmte te, const char * altNEVR, rpmds ds,
724 fnpyKey * suggestedKeys)
725 {
726 if (te != NULL) {
727 const char * DNEVR = rpmdsDNEVR(ds);
728 rpmProblemType type;
729 fnpyKey key = (suggestedKeys ? suggestedKeys[0] : NULL);
730
731 switch ((unsigned)DNEVR[0]) {
732 case 'O': type = RPMPROB_OBSOLETES; break;
733 case 'C': type = RPMPROB_CONFLICT; break;
734 default:
735 case 'R': type = RPMPROB_REQUIRES; break;
736 }
737
738 appendProblem(te, type, key, altNEVR, DNEVR+2, rpmdsInstance(ds));
739 }
740 }
741
rpmteAddRelocProblems(rpmte te)742 void rpmteAddRelocProblems(rpmte te)
743 {
744 if (te && te->badrelocs) {
745 for (int i = 0; i < te->nrelocs; i++) {
746 if (te->badrelocs[i]) {
747 rpmteAddProblem(te, RPMPROB_BADRELOCATE, NULL,
748 te->relocs[i].oldPath, 0);
749 }
750 }
751 }
752 }
753
rpmteTypeString(rpmte te)754 const char * rpmteTypeString(rpmte te)
755 {
756 switch (rpmteType(te)) {
757 case TR_ADDED: return _("install");
758 case TR_REMOVED: return _("erase");
759 case TR_RPMDB: return _("rpmdb");
760 default: return "???";
761 }
762 }
763
rpmteGetFileStates(rpmte te)764 rpmfs rpmteGetFileStates(rpmte te)
765 {
766 return te->fs;
767 }
768
rpmteSetVerified(rpmte te,int verified)769 void rpmteSetVerified(rpmte te, int verified)
770 {
771 te->verified = verified;
772 }
773
rpmteVerified(rpmte te)774 int rpmteVerified(rpmte te)
775 {
776 return (te != NULL) ? te->verified : 0;
777 }
778
rpmteAddOp(rpmte te)779 int rpmteAddOp(rpmte te)
780 {
781 return te->addop;
782 }
783
rpmteProcess(rpmte te,pkgGoal goal,int num)784 int rpmteProcess(rpmte te, pkgGoal goal, int num)
785 {
786 /* Only install/erase resets pkg file info */
787 int scriptstage = (goal != PKG_INSTALL && goal != PKG_ERASE);
788 int test = (rpmtsFlags(te->ts) & RPMTRANS_FLAG_TEST);
789 int reset_fi = (scriptstage == 0 && test == 0);
790 int failed = 1;
791
792 /* Dont bother opening for elements without pre/posttrans scripts */
793 if (goal == PKG_PRETRANS || goal == PKG_POSTTRANS) {
794 if (!rpmteHaveTransScript(te, goal)) {
795 return 0;
796 }
797 }
798
799 if (rpmteOpen(te, reset_fi)) {
800 if (!scriptstage) {
801 rpmtsNotify(te->ts, te, RPMCALLBACK_ELEM_PROGRESS, num,
802 rpmtsMembers(te->ts)->orderCount);
803 }
804
805 failed = rpmpsmRun(te->ts, te, goal);
806 rpmteClose(te, reset_fi);
807 }
808
809 if (failed) {
810 failed = rpmteMarkFailed(te);
811 }
812
813 return failed;
814 }
815