Drop the useless "tag" argument from rpmteFI()
[platform/upstream/rpm.git] / lib / rpmte.c
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/rpmds.h>
10 #include <rpm/rpmfi.h>
11 #include <rpm/rpmts.h>
12 #include <rpm/rpmdb.h>
13
14 #include "lib/rpmte_internal.h"
15
16 #include "debug.h"
17
18 int _rpmte_debug = 0;
19
20
21 void rpmteCleanDS(rpmte te)
22 {
23     te->this = rpmdsFree(te->this);
24     te->provides = rpmdsFree(te->provides);
25     te->requires = rpmdsFree(te->requires);
26     te->conflicts = rpmdsFree(te->conflicts);
27     te->obsoletes = rpmdsFree(te->obsoletes);
28 }
29
30 /**
31  * Destroy transaction element data.
32  * @param p             transaction element
33  */
34 static void delTE(rpmte p)
35 {
36     rpmRelocation * r;
37
38     if (p->relocs) {
39         for (r = p->relocs; (r->oldPath || r->newPath); r++) {
40             r->oldPath = _free(r->oldPath);
41             r->newPath = _free(r->newPath);
42         }
43         p->relocs = _free(p->relocs);
44     }
45
46     rpmteCleanDS(p);
47
48     p->fi = rpmfiFree(p->fi);
49
50     if (p->fd != NULL)
51         p->fd = fdFree(p->fd, RPMDBG_M("delTE"));
52
53     p->os = _free(p->os);
54     p->arch = _free(p->arch);
55     p->epoch = _free(p->epoch);
56     p->name = _free(p->name);
57     p->version = _free(p->version);
58     p->release = _free(p->release);
59     p->NEVR = _free(p->NEVR);
60     p->NEVRA = _free(p->NEVRA);
61
62     p->h = headerFree(p->h);
63
64     memset(p, 0, sizeof(*p));   /* XXX trash and burn */
65     /* FIX: p->{NEVR,name} annotations */
66     return;
67 }
68
69 /**
70  * Initialize transaction element data from header.
71  * @param ts            transaction set
72  * @param p             transaction element
73  * @param h             header
74  * @param key           (TR_ADDED) package retrieval key (e.g. file name)
75  * @param relocs        (TR_ADDED) package file relocations
76  */
77 static void addTE(rpmts ts, rpmte p, Header h,
78                 fnpyKey key,
79                 rpmRelocation * relocs)
80 {
81     rpmte savep;
82     const char *name, *version, *release, *arch, *os;
83     struct rpmtd_s td;
84     rpmfiFlags fiflags;
85
86     name = version = release = arch = NULL;
87     headerNEVRA(h, &name, NULL, &version, &release, &arch);
88
89
90     p->name = xstrdup(name);
91     p->version = xstrdup(version);
92     p->release = xstrdup(release);
93
94     if (headerGet(h, RPMTAG_EPOCH, &td, HEADERGET_MINMEM)) {
95         p->epoch = rpmtdFormat(&td, RPMTD_FORMAT_STRING, NULL);
96     } else {
97         p->epoch = NULL;
98     }
99
100     p->arch = arch ? xstrdup(arch) : NULL;
101     p->archScore = arch ? rpmMachineScore(RPM_MACHTABLE_INSTARCH, arch) : 0;
102
103     headerGet(h, RPMTAG_OS, &td, HEADERGET_MINMEM);
104     os = rpmtdGetString(&td);
105     p->os = os ? xstrdup(os) : NULL;
106     p->osScore = p->os ? rpmMachineScore(RPM_MACHTABLE_INSTOS, p->os) : 0;
107
108     p->isSource = headerIsSource(h);
109     
110     p->NEVR = headerGetNEVR(h, NULL);
111     p->NEVRA = headerGetNEVRA(h, NULL);
112
113     p->nrelocs = 0;
114     p->relocs = NULL;
115     if (relocs != NULL) {
116         rpmRelocation * r;
117         int i;
118
119         for (r = relocs; r->oldPath || r->newPath; r++)
120             p->nrelocs++;
121         p->relocs = xmalloc((p->nrelocs + 1) * sizeof(*p->relocs));
122
123         for (i = 0, r = relocs; r->oldPath || r->newPath; i++, r++) {
124             p->relocs[i].oldPath = r->oldPath ? xstrdup(r->oldPath) : NULL;
125             p->relocs[i].newPath = r->newPath ? xstrdup(r->newPath) : NULL;
126         }
127         p->relocs[i].oldPath = NULL;
128         p->relocs[i].newPath = NULL;
129     }
130
131     p->db_instance = headerGetInstance(h);
132     p->key = key;
133     p->fd = NULL;
134
135     p->pkgFileSize = 0;
136
137     p->this = rpmdsThis(h, RPMTAG_PROVIDENAME, RPMSENSE_EQUAL);
138     p->provides = rpmdsNew(h, RPMTAG_PROVIDENAME, 0);
139     p->requires = rpmdsNew(h, RPMTAG_REQUIRENAME, 0);
140     p->conflicts = rpmdsNew(h, RPMTAG_CONFLICTNAME, 0);
141     p->obsoletes = rpmdsNew(h, RPMTAG_OBSOLETENAME, 0);
142
143     fiflags = (p->type == TR_ADDED) ? (RPMFI_NOHEADER | RPMFI_FLAGS_INSTALL) :
144                                       (RPMFI_NOHEADER | RPMFI_FLAGS_ERASE);
145     savep = rpmtsSetRelocateElement(ts, p);
146     p->fi = rpmfiNew(ts, h, RPMTAG_BASENAMES, fiflags);
147     (void) rpmtsSetRelocateElement(ts, savep);
148
149     /* See if we have pre/posttrans scripts. */
150     p->transscripts |= (headerIsEntry(h, RPMTAG_PRETRANS) &&
151                          headerIsEntry(h, RPMTAG_PRETRANSPROG)) ?
152                         RPMTE_HAVE_PRETRANS : 0;
153     p->transscripts |= (headerIsEntry(h, RPMTAG_POSTTRANS) &&
154                          headerIsEntry(h, RPMTAG_POSTTRANSPROG)) ?
155                         RPMTE_HAVE_POSTTRANS : 0;
156
157     rpmteColorDS(p, RPMTAG_PROVIDENAME);
158     rpmteColorDS(p, RPMTAG_REQUIRENAME);
159     return;
160 }
161
162 rpmte rpmteFree(rpmte te)
163 {
164     if (te != NULL) {
165         delTE(te);
166         te = _free(te);
167     }
168     return NULL;
169 }
170
171 rpmte rpmteNew(const rpmts ts, Header h,
172                 rpmElementType type,
173                 fnpyKey key,
174                 rpmRelocation * relocs,
175                 int dboffset,
176                 rpmalKey pkgKey)
177 {
178     rpmte p = xcalloc(1, sizeof(*p));
179     uint32_t *ep; 
180     struct rpmtd_s size;
181
182     p->type = type;
183     p->pkgKey = pkgKey;
184     addTE(ts, p, h, key, relocs);
185     switch (type) {
186     case TR_ADDED:
187         headerGet(h, RPMTAG_SIGSIZE, &size, HEADERGET_DEFAULT);
188         if ((ep = rpmtdGetUint32(&size))) {
189             p->pkgFileSize += 96 + 256 + *ep;
190         }
191         break;
192     case TR_REMOVED:
193         /* nothing to do */
194         break;
195     }
196     return p;
197 }
198
199 unsigned int rpmteDBInstance(rpmte te) 
200 {
201     return (te != NULL ? te->db_instance : 0);
202 }
203
204 void rpmteSetDBInstance(rpmte te, unsigned int instance) 
205 {
206     if (te != NULL) 
207         te->db_instance = instance;
208 }
209
210 Header rpmteHeader(rpmte te)
211 {
212     return (te != NULL && te->h != NULL ? headerLink(te->h) : NULL);
213 }
214
215 Header rpmteSetHeader(rpmte te, Header h)
216 {
217     if (te != NULL)  {
218         te->h = headerFree(te->h);
219         if (h != NULL)
220             te->h = headerLink(h);
221     }
222     return NULL;
223 }
224
225 rpmElementType rpmteType(rpmte te)
226 {
227     /* XXX returning negative for unsigned type */
228     return (te != NULL ? te->type : -1);
229 }
230
231 const char * rpmteN(rpmte te)
232 {
233     return (te != NULL ? te->name : NULL);
234 }
235
236 const char * rpmteE(rpmte te)
237 {
238     return (te != NULL ? te->epoch : NULL);
239 }
240
241 const char * rpmteV(rpmte te)
242 {
243     return (te != NULL ? te->version : NULL);
244 }
245
246 const char * rpmteR(rpmte te)
247 {
248     return (te != NULL ? te->release : NULL);
249 }
250
251 const char * rpmteA(rpmte te)
252 {
253     return (te != NULL ? te->arch : NULL);
254 }
255
256 const char * rpmteO(rpmte te)
257 {
258     return (te != NULL ? te->os : NULL);
259 }
260
261 int rpmteIsSource(rpmte te)
262 {
263     return (te != NULL ? te->isSource : 0);
264 }
265
266 rpm_color_t rpmteColor(rpmte te)
267 {
268     return (te != NULL ? te->color : 0);
269 }
270
271 rpm_color_t rpmteSetColor(rpmte te, rpm_color_t color)
272 {
273     rpm_color_t ocolor = 0;
274     if (te != NULL) {
275         ocolor = te->color;
276         te->color = color;
277     }
278     return ocolor;
279 }
280
281 rpm_loff_t rpmtePkgFileSize(rpmte te)
282 {
283     return (te != NULL ? te->pkgFileSize : 0);
284 }
285
286 int rpmteDepth(rpmte te)
287 {
288     return (te != NULL ? te->depth : 0);
289 }
290
291 int rpmteSetDepth(rpmte te, int ndepth)
292 {
293     int odepth = 0;
294     if (te != NULL) {
295         odepth = te->depth;
296         te->depth = ndepth;
297     }
298     return odepth;
299 }
300
301 int rpmteBreadth(rpmte te)
302 {
303     return (te != NULL ? te->depth : 0);
304 }
305
306 int rpmteSetBreadth(rpmte te, int nbreadth)
307 {
308     int obreadth = 0;
309     if (te != NULL) {
310         obreadth = te->breadth;
311         te->breadth = nbreadth;
312     }
313     return obreadth;
314 }
315
316 int rpmteNpreds(rpmte te)
317 {
318     return (te != NULL ? te->npreds : 0);
319 }
320
321 int rpmteSetNpreds(rpmte te, int npreds)
322 {
323     int opreds = 0;
324     if (te != NULL) {
325         opreds = te->npreds;
326         te->npreds = npreds;
327     }
328     return opreds;
329 }
330
331 int rpmteTree(rpmte te)
332 {
333     return (te != NULL ? te->tree : 0);
334 }
335
336 int rpmteSetTree(rpmte te, int ntree)
337 {
338     int otree = 0;
339     if (te != NULL) {
340         otree = te->tree;
341         te->tree = ntree;
342     }
343     return otree;
344 }
345
346 rpmte rpmteParent(rpmte te)
347 {
348     return (te != NULL ? te->parent : NULL);
349 }
350
351 rpmte rpmteSetParent(rpmte te, rpmte pte)
352 {
353     rpmte opte = NULL;
354     if (te != NULL) {
355         opte = te->parent;
356         te->parent = pte;
357     }
358     return opte;
359 }
360
361 int rpmteDegree(rpmte te)
362 {
363     return (te != NULL ? te->degree : 0);
364 }
365
366 int rpmteSetDegree(rpmte te, int ndegree)
367 {
368     int odegree = 0;
369     if (te != NULL) {
370         odegree = te->degree;
371         te->degree = ndegree;
372     }
373     return odegree;
374 }
375
376 tsortInfo rpmteTSI(rpmte te)
377 {
378     return te->tsi;
379 }
380
381 void rpmteFreeTSI(rpmte te)
382 {
383     if (te != NULL && rpmteTSI(te) != NULL) {
384         tsortInfo tsi;
385
386         /* Clean up tsort remnants (if any). */
387         while ((tsi = rpmteTSI(te)->tsi_next) != NULL) {
388             rpmteTSI(te)->tsi_next = tsi->tsi_next;
389             tsi->tsi_next = NULL;
390             tsi = _free(tsi);
391         }
392         te->tsi = _free(te->tsi);
393     }
394     /* FIX: te->tsi is NULL */
395     return;
396 }
397
398 void rpmteNewTSI(rpmte te)
399 {
400     if (te != NULL) {
401         rpmteFreeTSI(te);
402         te->tsi = xcalloc(1, sizeof(*te->tsi));
403     }
404 }
405
406 rpmalKey rpmteAddedKey(rpmte te)
407 {
408     return (te != NULL && te->type == TR_ADDED ? te->pkgKey : RPMAL_NOMATCH);
409 }
410
411 rpmalKey rpmteSetAddedKey(rpmte te, rpmalKey npkgKey)
412 {
413     rpmalKey opkgKey = RPMAL_NOMATCH;
414     if (te != NULL && te->type == TR_ADDED) {
415         opkgKey = te->pkgKey;
416         te->pkgKey = npkgKey;
417     }
418     return opkgKey;
419 }
420
421
422 rpmalKey rpmteDependsOnKey(rpmte te)
423 {
424     return (te != NULL && te->type == TR_REMOVED ? te->pkgKey : RPMAL_NOMATCH);
425 }
426
427 int rpmteDBOffset(rpmte te)
428 {
429     return rpmteDBInstance(te);
430 }
431
432 const char * rpmteEVR(rpmte te)
433 {
434     return (te != NULL ? te->NEVR + strlen(te->name) + 1 : NULL);
435 }
436
437 const char * rpmteNEVR(rpmte te)
438 {
439     return (te != NULL ? te->NEVR : NULL);
440 }
441
442 const char * rpmteNEVRA(rpmte te)
443 {
444     return (te != NULL ? te->NEVRA : NULL);
445 }
446
447 FD_t rpmteFd(rpmte te)
448 {
449     return (te != NULL ? te->fd : NULL);
450 }
451
452 fnpyKey rpmteKey(rpmte te)
453 {
454     return (te != NULL ? te->key : NULL);
455 }
456
457 rpmds rpmteDS(rpmte te, rpmTag tag)
458 {
459     if (te == NULL)
460         return NULL;
461
462     if (tag == RPMTAG_NAME)
463         return te->this;
464     else
465     if (tag == RPMTAG_PROVIDENAME)
466         return te->provides;
467     else
468     if (tag == RPMTAG_REQUIRENAME)
469         return te->requires;
470     else
471     if (tag == RPMTAG_CONFLICTNAME)
472         return te->conflicts;
473     else
474     if (tag == RPMTAG_OBSOLETENAME)
475         return te->obsoletes;
476     else
477         return NULL;
478 }
479
480 rpmfi rpmteFI(rpmte te)
481 {
482     if (te == NULL)
483         return NULL;
484
485     return te->fi; /* XXX take fi reference here? */
486 }
487
488 void rpmteColorDS(rpmte te, rpmTag tag)
489 {
490     rpmfi fi = rpmteFI(te);
491     rpmds ds = rpmteDS(te, tag);
492     char deptype = 'R';
493     char mydt;
494     const uint32_t * ddict;
495     rpm_color_t * colors;
496     int32_t * refs;
497     rpm_color_t val;
498     int Count;
499     size_t nb;
500     unsigned ix;
501     int ndx, i;
502
503     if (!(te && (Count = rpmdsCount(ds)) > 0 && rpmfiFC(fi) > 0))
504         return;
505
506     switch (tag) {
507     default:
508         return;
509         break;
510     case RPMTAG_PROVIDENAME:
511         deptype = 'P';
512         break;
513     case RPMTAG_REQUIRENAME:
514         deptype = 'R';
515         break;
516     }
517
518     colors = xcalloc(Count, sizeof(*colors));
519     nb = Count * sizeof(*refs);
520     refs = memset(xmalloc(nb), -1, nb);
521
522     /* Calculate dependency color and reference count. */
523     fi = rpmfiInit(fi, 0);
524     if (fi != NULL)
525     while (rpmfiNext(fi) >= 0) {
526         val = rpmfiFColor(fi);
527         ddict = NULL;
528         ndx = rpmfiFDepends(fi, &ddict);
529         if (ddict != NULL)
530         while (ndx-- > 0) {
531             ix = *ddict++;
532             mydt = ((ix >> 24) & 0xff);
533             if (mydt != deptype)
534                 continue;
535             ix &= 0x00ffffff;
536 assert (ix < Count);
537             colors[ix] |= val;
538             refs[ix]++;
539         }
540     }
541
542     /* Set color/refs values in dependency set. */
543     ds = rpmdsInit(ds);
544     while ((i = rpmdsNext(ds)) >= 0) {
545         val = colors[i];
546         te->color |= val;
547         (void) rpmdsSetColor(ds, val);
548         val = refs[i];
549         if (val >= 0)
550             val++;
551         (void) rpmdsSetRefs(ds, val);
552     }
553     free(colors);
554     free(refs);
555 }
556
557 int rpmtsiOc(rpmtsi tsi)
558 {
559     return tsi->ocsave;
560 }
561
562 rpmtsi rpmtsiFree(rpmtsi tsi)
563 {
564     /* XXX watchout: a funky recursion segfaults here iff nrefs is wrong. */
565     if (tsi)
566         tsi->ts = rpmtsFree(tsi->ts);
567     return _free(tsi);
568 }
569
570 rpmtsi rpmtsiInit(rpmts ts)
571 {
572     rpmtsi tsi = NULL;
573
574     tsi = xcalloc(1, sizeof(*tsi));
575     tsi->ts = rpmtsLink(ts, RPMDBG_M("rpmtsi"));
576     tsi->reverse = ((rpmtsFlags(ts) & RPMTRANS_FLAG_REVERSE) ? 1 : 0);
577     tsi->oc = (tsi->reverse ? (rpmtsNElements(ts) - 1) : 0);
578     tsi->ocsave = tsi->oc;
579     return tsi;
580 }
581
582 /**
583  * Return next transaction element.
584  * @param tsi           transaction element iterator
585  * @return              transaction element, NULL on termination
586  */
587 static
588 rpmte rpmtsiNextElement(rpmtsi tsi)
589 {
590     rpmte te = NULL;
591     int oc = -1;
592
593     if (tsi == NULL || tsi->ts == NULL || rpmtsNElements(tsi->ts) <= 0)
594         return te;
595
596     if (tsi->reverse) {
597         if (tsi->oc >= 0)               oc = tsi->oc--;
598     } else {
599         if (tsi->oc < rpmtsNElements(tsi->ts))  oc = tsi->oc++;
600     }
601     tsi->ocsave = oc;
602     if (oc != -1)
603         te = rpmtsElement(tsi->ts, oc);
604     return te;
605 }
606
607 rpmte rpmtsiNext(rpmtsi tsi, rpmElementType type)
608 {
609     rpmte te;
610
611     while ((te = rpmtsiNextElement(tsi)) != NULL) {
612         if (type == 0 || (te->type & type) != 0)
613             break;
614     }
615     return te;
616 }
617
618 int rpmteOpen(rpmte te, rpmts ts)
619 {
620     Header h = NULL;
621     if (te == NULL || ts == NULL)
622         goto exit;
623
624     rpmteSetHeader(te, NULL);
625     switch (te->type) {
626     case TR_ADDED:
627         te->h = NULL;
628         te->fd = rpmtsNotify(ts, te, RPMCALLBACK_INST_OPEN_FILE, 0, 0);
629         if (te->fd != NULL) {
630             rpmVSFlags ovsflags;
631             rpmRC pkgrc;
632
633             ovsflags = rpmtsSetVSFlags(ts, rpmtsVSFlags(ts) | RPMVSF_NEEDPAYLOAD);
634             pkgrc = rpmReadPackageFile(ts, rpmteFd(te), rpmteNEVRA(te), &h);
635             rpmtsSetVSFlags(ts, ovsflags);
636             switch (pkgrc) {
637             default:
638                 rpmteClose(te, ts);
639                 break;
640             case RPMRC_NOTTRUSTED:
641             case RPMRC_NOKEY:
642             case RPMRC_OK:
643                 break;
644             }
645         }
646         break;
647     case TR_REMOVED: {
648         unsigned int rec = rpmteDBInstance(te);
649         rpmdbMatchIterator mi;
650
651         /* eventually we'll want notifications for erase open too */
652         mi = rpmtsInitIterator(ts, RPMDBI_PACKAGES, &rec, sizeof(rec));
653         /* iterator returns weak refs, grab hold of header */
654         if ((h = rpmdbNextIterator(mi)))
655             h = headerLink(h);
656         mi = rpmdbFreeIterator(mi);
657         }
658         break;
659     }
660     if (h != NULL) {
661         rpmteSetHeader(te, h);
662         headerFree(h);
663     }
664
665 exit:
666     return (h != NULL);
667 }
668
669 int rpmteClose(rpmte te, rpmts ts)
670 {
671     if (te == NULL || ts == NULL)
672         return 0;
673
674     switch (te->type) {
675     case TR_ADDED:
676         rpmtsNotify(ts, te, RPMCALLBACK_INST_CLOSE_FILE, 0, 0);
677         te->fd = NULL;
678         break;
679     case TR_REMOVED:
680         /* eventually we'll want notifications for erase open too */
681         break;
682     }
683     rpmteSetHeader(te, NULL);
684     return 1;
685 }
686
687 int rpmteMarkFailed(rpmte te, rpmts ts)
688 {
689     rpmtsi pi = rpmtsiInit(ts);
690     int rc = 0;
691     rpmte p;
692     rpmalKey key = rpmteAddedKey(te);
693
694     te->failed = 1;
695     /* XXX we can do a much better here than this... */
696     while ((p = rpmtsiNext(pi, TR_REMOVED))) {
697         if (rpmteDependsOnKey(p) == key) {
698             p->failed = 1;
699         }
700     }
701     rpmtsiFree(pi);
702     return rc;
703 }
704
705 int rpmteFailed(rpmte te)
706 {
707     return (te != NULL) ? te->failed : -1;
708 }