rpm 5.2.1

- Main Page
- Related Pages
- Modules
- Data Structures
- Files

- File List
- Globals

transaction.c
Go to the documentation of this file.
1
5 #include "system.h"
6
7 #include <rpmio.h>
8 #include <rpmiotypes.h>
9 #include <rpmlog.h>
10 #include <rpmmacro.h> /* XXX for rpmExpand */
11 #include "fprint.h"
12
13 #include <rpmtypes.h>
14 #include <rpmtag.h>
15 #include <pkgio.h>
16
17 #define _RPMDB_INTERNAL /* XXX for dbiIndexFoo() */
18 #include <rpmdb.h>
19 #include "legacy.h" /* XXX dodigest */
20
21 #define _RPMFI_INTERNAL
22 #include <rpmfi.h>
23 #include "fsm.h"
24
25 #define _RPMTE_INTERNAL
26 #include "rpmte.h"
27 #define _RPMTS_INTERNAL
28 #include "rpmts.h"
29
30 #define _RPMSQ_INTERNAL
31 #include "psm.h"
32
33 #include "rpmds.h"
34
35 #include "rpmlock.h"
36
37 #include "misc.h" /* XXX currentDirectory */
38
39 #if defined(RPM_VENDOR_MANDRIVA)
40 #include "filetriggers.h" /* XXX mayAddToFilesAwaitingFiletriggers, rpmRunFileTriggers */
41 #endif
42
43 #include <rpmcli.h> /* XXX QVA_t INSTALL_FOO flags */
44 #include <rpmrollback.h> /* IDTX prototypes */
45
46 #include "debug.h"
47
48 /*@access dbiIndexSet @*/
49
50 /*@access fnpyKey @*/
51
52 /*@access alKey @*/
53 /*@access rpmdb @*/ /* XXX cast */
54
55 /*@access rpmfi @*/
56 /*@access rpmps @*/ /* XXX need rpmProblemSetOK() */
57 /*@access rpmpsm @*/
58
59 /*@access rpmte @*/
60 /*@access rpmtsi @*/
61 /*@access rpmts @*/
62
63 /*@access IDT @*/
64 /*@access IDTX @*/
65 /*@access FD_t @*/
66
69 static int sharedCmp(const void * one, const void * two)
70 /*@*/
71 {
72 sharedFileInfo a = (sharedFileInfo) one;
73 sharedFileInfo b = (sharedFileInfo) two;
74
75 if (a->otherPkg < b->otherPkg)
76 return -1;
77 else if (a->otherPkg > b->otherPkg)
78 return 1;
79
80 return 0;
81 }
82
95 static int handleInstInstalledFiles(const rpmts ts,
96 rpmte p, rpmfi fi,
97 sharedFileInfo shared,
98 int sharedCount, int reportConflicts)
99 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
100 /*@modifies ts, p, fi, rpmGlobalMacroContext, fileSystem, internalState @*/
101 {
102 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
103 const char * altNVRA = NULL;
104 rpmuint32_t tscolor = rpmtsColor(ts);
105 rpmuint32_t prefcolor = rpmtsPrefColor(ts);
106 rpmuint32_t otecolor, tecolor;
107 rpmuint32_t oFColor, FColor;
108 rpmuint32_t oFFlags, FFlags;
109 rpmfi otherFi = NULL;
110 rpmps ps;
111 int xx;
112 int i;
113
114 { rpmmi mi;
115 Header h;
116 int scareMem = 0;
117
118 mi = rpmtsInitIterator(ts, RPMDBI_PACKAGES,
119 &shared->otherPkg, sizeof(shared->otherPkg));
120 while ((h = rpmmiNext(mi)) != NULL) {
121 he->tag = RPMTAG_NVRA;
122 xx = headerGet(h, he, 0);
123 assert(he->p.str != NULL);
124 altNVRA = he->p.str;
125 otherFi = rpmfiNew(ts, h, RPMTAG_BASENAMES, scareMem);
126 break;
127 }
128 mi = rpmmiFree(mi);
129 }
130
131 /* Compute package color. */
132 tecolor = rpmteColor(p);
133 tecolor &= tscolor;
134
135 /* Compute other pkg color. */
136 otecolor = 0;
137 otherFi = rpmfiInit(otherFi, 0);
138 if (otherFi != NULL)
139 while (rpmfiNext(otherFi) >= 0)
140 otecolor |= rpmfiFColor(otherFi);
141 otecolor &= tscolor;
142
143 if (otherFi == NULL)
144 return 1;
145
146 p->replaced = xcalloc(sharedCount, sizeof(*p->replaced));
147 p->nreplaced = 0;
148
149 ps = rpmtsProblems(ts);
150 for (i = 0; i < sharedCount; i++, shared++) {
151 int otherFileNum, fileNum;
152
153 otherFileNum = shared->otherFileNum;
154 (void) rpmfiSetFX(otherFi, otherFileNum);
155 oFFlags = rpmfiFFlags(otherFi);
156 oFColor = rpmfiFColor(otherFi);
157 oFColor &= tscolor;
158
159 fileNum = shared->pkgFileNum;
160 (void) rpmfiSetFX(fi, fileNum);
161 FFlags = rpmfiFFlags(fi);
162 FColor = rpmfiFColor(fi);
163 FColor &= tscolor;
164
165 #ifdef DYING
166 /* XXX another tedious segfault, assume file state normal. */
167 if (otherStates && otherStates[otherFileNum] != RPMFILE_STATE_NORMAL)
168 continue;
169 #endif
170
171 if (iosmFileActionSkipped(fi->actions[fileNum]))
172 continue;
173
174 /* Remove setuid/setgid bits on other (possibly hardlinked) files. */
175 if (!(fi->mapflags & IOSM_SBIT_CHECK)) {
176 rpmuint16_t omode = rpmfiFMode(otherFi);
177 if (S_ISREG(omode) && (omode & 06000) != 0)
178 fi->mapflags |= IOSM_SBIT_CHECK;
179 }
180
181 if (((FFlags | oFFlags) & RPMFILE_GHOST))
182 continue;
183
184 if (rpmfiCompare(otherFi, fi)) {
185 int rConflicts;
186
187 rConflicts = reportConflicts;
188 /* Resolve file conflicts to prefer Elf64 (if not forced). */
189 if (tscolor != 0 && FColor != 0 && FColor != oFColor)
190 {
191 if (oFColor & prefcolor) {
192 fi->actions[fileNum] = FA_SKIPCOLOR;
193 rConflicts = 0;
194 } else
195 if (FColor & prefcolor) {
196 fi->actions[fileNum] = FA_CREATE;
197 rConflicts = 0;
198 }
199 }
200 #if defined(RPM_VENDOR_MANDRIVA) /* no-doc-conflicts */
201 /* HACK: always install latest (arch-independent) man
202 pages and gtk/gnome html doc files. */
203 if (rConflicts && tscolor != 0 && FColor == 0 && oFColor == 0) {
204 const char *ignorelist[] = {
205 "/usr/share/man/",
206 "/usr/share/gtk-doc/html/",
207 "/usr/share/gnome/html/",
208 NULL
209 };
210 const char *fn = rpmfiFN(fi);
211 const char **dnp;
212 for (dnp = ignorelist; *dnp != NULL; dnp++) {
213 if (strstr(fn, *dnp) == fn) {
214 fi->actions[fileNum] = FA_CREATE;
215 rConflicts = 0;
216 break;
217 }
218 }
219 }
220 #endif
221
222 if (rConflicts) {
223 rpmpsAppend(ps, RPMPROB_FILE_CONFLICT,
224 rpmteNEVRA(p), rpmteKey(p),
225 rpmfiDN(fi), rpmfiBN(fi),
226 altNVRA,
227 0);
228 }
229
230 /* Save file identifier to mark as state REPLACED. */
231 if ( !(((FFlags | oFFlags) & RPMFILE_CONFIG) || iosmFileActionSkipped(fi->actions[fileNum])) ) {
232 /*@-assignexpose@*/
233 if (!shared->isRemoved)
234 p->replaced[p->nreplaced++] = *shared;
235 /*@=assignexpose@*/
236 }
237 }
238
239 /* Determine config file dispostion, skipping missing files (if any). */
240 if (((FFlags | oFFlags) & RPMFILE_CONFIG)) {
241 int skipMissing =
242 ((rpmtsFlags(ts) & RPMTRANS_FLAG_ALLFILES) ? 0 : 1);
243 iosmFileAction action = rpmfiDecideFate(otherFi, fi, skipMissing);
244 fi->actions[fileNum] = action;
245 }
246 fi->replacedSizes[fileNum] = rpmfiFSize(otherFi);
247 }
248 ps = rpmpsFree(ps);
249
250 altNVRA = _free(altNVRA);
251 otherFi = rpmfiFree(otherFi);
252
253 p->replaced = xrealloc(p->replaced,
254 sizeof(*p->replaced) * (p->nreplaced + 1));
255 memset(p->replaced + p->nreplaced, 0, sizeof(*p->replaced));
256
257 return 0;
258 }
259
262 /* XXX only ts->rpmdb modified */
263 static int handleRmvdInstalledFiles(const rpmts ts, rpmfi fi,
264 sharedFileInfo shared, int sharedCount)
265 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
266 /*@modifies ts, fi, rpmGlobalMacroContext, fileSystem, internalState @*/
267 {
268 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
269 Header h;
270 const unsigned char * otherStates;
271 int i, xx;
272
273 rpmmi mi;
274
275 mi = rpmtsInitIterator(ts, RPMDBI_PACKAGES,
276 &shared->otherPkg, sizeof(shared->otherPkg));
277 h = rpmmiNext(mi);
278 if (h == NULL) {
279 mi = rpmmiFree(mi);
280 return 1;
281 }
282
283 he->tag = RPMTAG_FILESTATES;
284 xx = headerGet(h, he, 0);
285 otherStates = he->p.ptr;
286
287 /* XXX there's an obscure segfault here w/o NULL check ... */
288 if (otherStates != NULL)
289 for (i = 0; i < sharedCount; i++, shared++) {
290 int otherFileNum, fileNum;
291 otherFileNum = shared->otherFileNum;
292 fileNum = shared->pkgFileNum;
293
294 if (otherStates[otherFileNum] != RPMFILE_STATE_NORMAL)
295 continue;
296
297 fi->actions[fileNum] = FA_SKIP;
298 }
299 he->p.ptr = _free(he->p.ptr);
300 mi = rpmmiFree(mi);
301
302 return 0;
303 }
304
305 #define ISROOT(_d) (((_d)[0] == '/' && (_d)[1] == '\0') ? "" : (_d))
306
307 /*@unchecked@*/
308 int _fps_debug = 0;
309
310 static int fpsCompare (const void * one, const void * two)
311 /*@*/
312 {
313 const struct fingerPrint_s * a = (const struct fingerPrint_s *)one;
314 const struct fingerPrint_s * b = (const struct fingerPrint_s *)two;
315 size_t adnlen = strlen(a->entry->dirName);
316 size_t asnlen = (a->subDir ? strlen(a->subDir) : 0);
317 size_t abnlen = strlen(a->baseName);
318 size_t bdnlen = strlen(b->entry->dirName);
319 size_t bsnlen = (b->subDir ? strlen(b->subDir) : 0);
320 size_t bbnlen = strlen(b->baseName);
321 char * afn, * bfn, * t;
322 int rc = 0;
323
324 if (adnlen == 1 && asnlen != 0) adnlen = 0;
325 if (bdnlen == 1 && bsnlen != 0) bdnlen = 0;
326
327 afn = t = alloca(adnlen+asnlen+abnlen+2);
328 if (adnlen) t = stpcpy(t, a->entry->dirName);
329 *t++ = '/';
330 if (a->subDir && asnlen) t = stpcpy(t, a->subDir);
331 if (abnlen) t = stpcpy(t, a->baseName);
332 if (afn[0] == '/' && afn[1] == '/') afn++;
333
334 bfn = t = alloca(bdnlen+bsnlen+bbnlen+2);
335 if (bdnlen) t = stpcpy(t, b->entry->dirName);
336 *t++ = '/';
337 if (b->subDir && bsnlen) t = stpcpy(t, b->subDir);
338 if (bbnlen) t = stpcpy(t, b->baseName);
339 if (bfn[0] == '/' && bfn[1] == '/') bfn++;
340
341 rc = strcmp(afn, bfn);
342
343 return rc;
344 }
345
346 /*@unchecked@*/
347 static int _linear_fps_search = 0;
348
349 static int findFps(const struct fingerPrint_s * fiFps,
350 const struct fingerPrint_s * otherFps,
351 int otherFc)
352 /*@*/
353 {
354 int otherFileNum;
355
356 if (_linear_fps_search) {
357
358 linear:
359 for (otherFileNum = 0; otherFileNum < otherFc; otherFileNum++, otherFps++) {
360
361 /* If the addresses are the same, so are the values. */
362 if (fiFps == otherFps)
363 break;
364
365 /* Otherwise, compare fingerprints by value. */
366 /*@-nullpass@*/ /* LCL: looks good to me */
367 if (FP_EQUAL((*fiFps), (*otherFps)))
368 break;
369 /*@=nullpass@*/
370 }
371
372 return otherFileNum;
373
374 } else {
375
376 const struct fingerPrint_s * bingoFps;
377
378 bingoFps = bsearch(fiFps, otherFps, otherFc, sizeof(*otherFps), fpsCompare);
379 if (bingoFps == NULL)
380 goto linear;
381
382 /* If the addresses are the same, so are the values. */
383 if (!(fiFps == bingoFps || FP_EQUAL((*fiFps), (*bingoFps))))
384 goto linear;
385
386 otherFileNum = (bingoFps != NULL ? (bingoFps - otherFps) : 0);
387
388 }
389
390 return otherFileNum;
391 }
392
396 /* XXX only ts->{probs,di} modified */
397 static void handleOverlappedFiles(const rpmts ts,
398 const rpmte p, rpmfi fi)
399 /*@globals h_errno, fileSystem, internalState @*/
400 /*@modifies ts, fi, fileSystem, internalState @*/
401 {
402 rpmuint32_t fixupSize = 0;
403 rpmps ps;
404 const char * fn;
405 int i, j;
406
407 ps = rpmtsProblems(ts);
408 fi = rpmfiInit(fi, 0);
409 if (fi != NULL)
410 while ((i = rpmfiNext(fi)) >= 0) {
411 rpmuint32_t tscolor = rpmtsColor(ts);
412 rpmuint32_t prefcolor = rpmtsPrefColor(ts);
413 rpmuint32_t oFColor, FColor;
414 struct fingerPrint_s * fiFps;
415 int otherPkgNum, otherFileNum;
416 rpmfi otherFi;
417 rpmuint32_t FFlags;
418 rpmuint16_t FMode;
419 const rpmfi * recs;
420 int numRecs;
421
422 if (iosmFileActionSkipped(fi->actions[i]))
423 continue;
424
425 fn = rpmfiFN(fi);
426 fiFps = fi->fps + i;
427 FFlags = rpmfiFFlags(fi);
428 FMode = rpmfiFMode(fi);
429 FColor = rpmfiFColor(fi);
430 FColor &= tscolor;
431
432 fixupSize = 0;
433
434 /*
435 * Retrieve all records that apply to this file. Note that the
436 * file info records were built in the same order as the packages
437 * will be installed and removed so the records for an overlapped
438 * files will be sorted in exactly the same order.
439 */
440 (void) htGetEntry(ts->ht, fiFps, &recs, &numRecs, NULL);
441
442 /*
443 * If this package is being added, look only at other packages
444 * being added -- removed packages dance to a different tune.
445 *
446 * If both this and the other package are being added, overlapped
447 * files must be identical (or marked as a conflict). The
448 * disposition of already installed config files leads to
449 * a small amount of extra complexity.
450 *
451 * If this package is being removed, then there are two cases that
452 * need to be worried about:
453 * If the other package is being added, then skip any overlapped files
454 * so that this package removal doesn't nuke the overlapped files
455 * that were just installed.
456 * If both this and the other package are being removed, then each
457 * file removal from preceding packages needs to be skipped so that
458 * the file removal occurs only on the last occurence of an overlapped
459 * file in the transaction set.
460 *
461 */
462
463 /* Locate this overlapped file in the set of added/removed packages. */
464 for (j = 0; j < numRecs && recs[j] != fi; j++)
465 {};
466
467 /* Find what the previous disposition of this file was. */
468 otherFileNum = -1; /* keep gcc quiet */
469 otherFi = NULL;
470 for (otherPkgNum = j - 1; otherPkgNum >= 0; otherPkgNum--) {
471 struct fingerPrint_s * otherFps;
472 int otherFc;
473
474 otherFi = recs[otherPkgNum];
475
476 /* Added packages need only look at other added packages. */
477 if (rpmteType(p) == TR_ADDED && rpmteType(otherFi->te) != TR_ADDED)
478 /*@innercontinue@*/ continue;
479
480 otherFps = otherFi->fps;
481 otherFc = rpmfiFC(otherFi);
482
483 otherFileNum = findFps(fiFps, otherFps, otherFc);
484 (void) rpmfiSetFX(otherFi, otherFileNum);
485
486 /* XXX Happens iff fingerprint for incomplete package install. */
487 if (otherFi->actions[otherFileNum] != FA_UNKNOWN)
488 /*@innerbreak@*/ break;
489 }
490
491 oFColor = rpmfiFColor(otherFi);
492 oFColor &= tscolor;
493
494 switch (rpmteType(p)) {
495 case TR_ADDED:
496 { int reportConflicts =
497 !(rpmtsFilterFlags(ts) & RPMPROB_FILTER_REPLACENEWFILES);
498 int done = 0;
499
500 if (otherPkgNum < 0) {
501 /* XXX is this test still necessary? */
502 if (fi->actions[i] != FA_UNKNOWN)
503 /*@switchbreak@*/ break;
504 if ((FFlags & RPMFILE_CONFIG) && (FFlags & RPMFILE_EXISTS)) {
505 /* Here is a non-overlapped pre-existing config file. */
506 fi->actions[i] = (FFlags & RPMFILE_NOREPLACE)
507 ? FA_ALTNAME : FA_BACKUP;
508 } else {
509 fi->actions[i] = FA_CREATE;
510 }
511 /*@switchbreak@*/ break;
512 }
513
514 assert(otherFi != NULL);
515 /* Mark added overlapped non-identical files as a conflict. */
516 if (rpmfiCompare(otherFi, fi)) {
517 int rConflicts;
518
519 rConflicts = reportConflicts;
520 /* Resolve file conflicts to prefer Elf64 (if not forced) ... */
521 if (tscolor != 0) {
522 if (FColor & prefcolor) {
523 /* ... last file of preferred colour is installed ... */
524 if (!iosmFileActionSkipped(fi->actions[i])) {
525 /* XXX static helpers are order dependent. Ick. */
526 if (strcmp(fn, "/usr/sbin/libgcc_post_upgrade")
527 && strcmp(fn, "/usr/sbin/glibc_post_upgrade"))
528 otherFi->actions[otherFileNum] = FA_SKIPCOLOR;
529 }
530 fi->actions[i] = FA_CREATE;
531 rConflicts = 0;
532 } else
533 if (oFColor & prefcolor) {
534 /* ... first file of preferred colour is installed ... */
535 if (iosmFileActionSkipped(fi->actions[i]))
536 otherFi->actions[otherFileNum] = FA_CREATE;
537 fi->actions[i] = FA_SKIPCOLOR;
538 rConflicts = 0;
539 } else
540 if (FColor == 0 && oFColor == 0) {
541 /* ... otherwise, do both, last in wins. */
542 otherFi->actions[otherFileNum] = FA_CREATE;
543 fi->actions[i] = FA_CREATE;
544 rConflicts = 0;
545 }
546 done = 1;
547 }
548
549 if (rConflicts) {
550 rpmpsAppend(ps, RPMPROB_NEW_FILE_CONFLICT,
551 rpmteNEVR(p), rpmteKey(p),
552 fn, NULL,
553 rpmteNEVR(otherFi->te),
554 0);
555 }
556 }
557
558 /* Try to get the disk accounting correct even if a conflict. */
559 fixupSize = rpmfiFSize(otherFi);
560
561 if ((FFlags & RPMFILE_CONFIG) && (FFlags & RPMFILE_EXISTS)) {
562 /* Here is an overlapped pre-existing config file. */
563 fi->actions[i] = (FFlags & RPMFILE_NOREPLACE)
564 ? FA_ALTNAME : FA_SKIP;
565 } else {
566 if (!done)
567 fi->actions[i] = FA_CREATE;
568 }
569 } /*@switchbreak@*/ break;
570
571 case TR_REMOVED:
572 if (otherPkgNum >= 0) {
573 assert(otherFi != NULL);
574 /* Here is an overlapped added file we don't want to nuke. */
575 if (otherFi->actions[otherFileNum] != FA_ERASE) {
576 /* On updates, don't remove files. */
577 fi->actions[i] = FA_SKIP;
578 /*@switchbreak@*/ break;
579 }
580 /* Here is an overlapped removed file: skip in previous. */
581 otherFi->actions[otherFileNum] = FA_SKIP;
582 }
583 if (iosmFileActionSkipped(fi->actions[i]))
584 /*@switchbreak@*/ break;
585 if (rpmfiFState(fi) != RPMFILE_STATE_NORMAL)
586 /*@switchbreak@*/ break;
587
588 /* Disposition is assumed to be FA_ERASE. */
589 fi->actions[i] = FA_ERASE;
590 if (!(S_ISREG(FMode) && (FFlags & RPMFILE_CONFIG)))
591 /*@switchbreak@*/ break;
592
593 /* Check for pre-existing modified config file that needs saving. */
594 if (!(FFlags & RPMFILE_SPARSE))
595 { int dalgo = 0;
596 size_t dlen = 0;
597 const unsigned char * digest = rpmfiDigest(fi, &dalgo, &dlen);
598 unsigned char * fdigest;
599 assert(digest != NULL);
600
601 fdigest = xcalloc(1, dlen);
602 /* Save (by renaming) locally modified config files. */
603 if (!dodigest(dalgo, fn, fdigest, 0, NULL)
604 && memcmp(digest, fdigest, dlen))
605 fi->actions[i] = FA_BACKUP;
606 fdigest = _free(fdigest);
607 }
608 /*@switchbreak@*/ break;
609 }
610
611 /* Update disk space info for a file. */
612 rpmtsUpdateDSI(ts, fiFps->entry->dev, rpmfiFSize(fi),
613 fi->replacedSizes[i], fixupSize, fi->actions[i]);
614
615 }
616 ps = rpmpsFree(ps);
617 }
618
626 /*@-nullpass@*/
627 static int ensureOlder(rpmts ts,
628 const rpmte p, const Header h)
629 /*@globals internalState @*/
630 /*@modifies ts, internalState @*/
631 {
632 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
633 rpmuint32_t reqFlags = (RPMSENSE_LESS | RPMSENSE_EQUAL);
634 const char * reqEVR;
635 rpmds req;
636 char * t;
637 size_t nb;
638 int rc;
639
640 if (p == NULL || h == NULL)
641 return 1;
642
643 nb = strlen(rpmteNEVR(p)) + (rpmteE(p) != NULL ? strlen(rpmteE(p)) : 0) + 1;
644 #ifdef RPM_VENDOR_MANDRIVA
645 nb += (rpmteD(p) != NULL ? strlen(rpmteD(p)) + 1 : 0);
646 #endif
647 t = alloca(nb);
648 *t = '\0';
649 reqEVR = t;
650 if (rpmteE(p) != NULL) t = stpcpy( stpcpy(t, rpmteE(p)), ":");
651 if (rpmteV(p) != NULL) t = stpcpy(t, rpmteV(p));
652 *t++ = '-';
653 if (rpmteR(p) != NULL) t = stpcpy(t, rpmteR(p));
654 #ifdef RPM_VENDOR_MANDRIVA
655 if (rpmteD(p) != NULL) *t++ = ':', t = stpcpy(t, rpmteD(p));
656 #endif
657
658 req = rpmdsSingle(RPMTAG_REQUIRENAME, rpmteN(p), reqEVR, reqFlags);
659 rc = rpmdsNVRMatchesDep(h, req, _rpmds_nopromote);
660 (void)rpmdsFree(req);
661 req = NULL;
662
663 if (rc == 0) {
664 rpmps ps = rpmtsProblems(ts);
665 he->tag = RPMTAG_NVRA;
666 rc = headerGet(h, he, 0);
667 assert(he->p.str != NULL);
668 rpmpsAppend(ps, RPMPROB_OLDPACKAGE,
669 rpmteNEVR(p), rpmteKey(p),
670 NULL, NULL,
671 he->p.str,
672 0);
673 he->p.ptr = _free(he->p.ptr);
674 ps = rpmpsFree(ps);
675 rc = 1;
676 } else
677 rc = 0;
678
679 return rc;
680 }
681 /*@=nullpass@*/
682
688 /*@-mustmod@*/ /* FIX: fi->actions is modified. */
689 /*@-nullpass@*/
690 static void skipFiles(const rpmts ts, rpmfi fi)
691 /*@globals rpmGlobalMacroContext, h_errno, internalState @*/
692 /*@modifies fi, rpmGlobalMacroContext, internalState @*/
693 {
694 rpmuint32_t tscolor = rpmtsColor(ts);
695 rpmuint32_t FColor;
696 int noConfigs = (rpmtsFlags(ts) & RPMTRANS_FLAG_NOCONFIGS);
697 int noDocs = (rpmtsFlags(ts) & RPMTRANS_FLAG_NODOCS);
698 ARGV_t netsharedPaths = NULL;
699 ARGV_t languages = NULL;
700 const char * dn, * bn;
701 size_t dnlen, bnlen;
702 int ix;
703 const char * s;
704 int * drc;
705 char * dff;
706 int dc;
707 int i, j;
708 int xx;
709
710 #if defined(RPM_VENDOR_OPENPKG) /* allow-excludedocs-default */
711 /* The "%_excludedocs" macro is intended to set the _default_ if
712 both --excludedocs and --includedocs are not specified and it
713 is evaluated already before. So, do not override it here again,
714 because it would not allow us to make "%_excludedocs 1" the
715 default. */
716 #else
717 if (!noDocs)
718 noDocs = rpmExpandNumeric("%{_excludedocs}");
719 #endif
720
721 { const char *tmpPath = rpmExpand("%{?_netsharedpath}", NULL);
722 if (tmpPath && *tmpPath)
723 xx = argvSplit(&netsharedPaths, tmpPath, ":");
724 tmpPath = _free(tmpPath);
725 }
726
727 s = rpmExpand("%{?_install_langs}", NULL);
728 if (!(s && *s))
729 s = _free(s);
730 if (s) {
731 xx = argvSplit(&languages, s, ":");
732 s = _free(s);
733 }
734
735 /* Compute directory refcount, skip directory if now empty. */
736 dc = rpmfiDC(fi);
737 drc = alloca(dc * sizeof(*drc));
738 memset(drc, 0, dc * sizeof(*drc));
739 dff = alloca(dc * sizeof(*dff));
740 memset(dff, 0, dc * sizeof(*dff));
741
742 fi = rpmfiInit(fi, 0);
743 if (fi != NULL) /* XXX lclint */
744 while ((i = rpmfiNext(fi)) >= 0)
745 {
746 ARGV_t nsp;
747
748 bn = rpmfiBN(fi);
749 bnlen = strlen(bn);
750 ix = rpmfiDX(fi);
751 dn = rpmfiDN(fi);
752 if (dn == NULL)
753 continue; /* XXX can't happen */
754 dnlen = strlen(dn);
755
756 drc[ix]++;
757
758 /* Don't bother with skipped files */
759 if (iosmFileActionSkipped(fi->actions[i])) {
760 drc[ix]--; dff[ix] = 1;
761 continue;
762 }
763
764 /* Ignore colored files not in our rainbow. */
765 FColor = rpmfiFColor(fi);
766 if (tscolor && FColor && !(tscolor & FColor)) {
767 drc[ix]--; dff[ix] = 1;
768 fi->actions[i] = FA_SKIPCOLOR;
769 continue;
770 }
771
772 /*
773 * Skip net shared paths.
774 * Net shared paths are not relative to the current root (though
775 * they do need to take package relocations into account).
776 */
777 for (nsp = netsharedPaths; nsp && *nsp; nsp++) {
778 size_t len;
779
780 len = strlen(*nsp);
781 if (dnlen >= len) {
782 if (strncmp(dn, *nsp, len))
783 /*@innercontinue@*/ continue;
784 /* Only directories or complete file paths can be net shared */
785 if (!(dn[len] == '/' || dn[len] == '\0'))
786 /*@innercontinue@*/ continue;
787 } else {
788 if (len < (dnlen + bnlen))
789 /*@innercontinue@*/ continue;
790 if (strncmp(dn, *nsp, dnlen))
791 /*@innercontinue@*/ continue;
792 /* Insure that only the netsharedpath basename is compared. */
793 if ((s = strchr((*nsp) + dnlen, '/')) != NULL && s[1] != '\0')
794 /*@innercontinue@*/ continue;
795 if (strncmp(bn, (*nsp) + dnlen, bnlen))
796 /*@innercontinue@*/ continue;
797 len = dnlen + bnlen;
798 /* Only directories or complete file paths can be net shared */
799 if (!((*nsp)[len] == '/' || (*nsp)[len] == '\0'))
800 /*@innercontinue@*/ continue;
801 }
802
803 /*@innerbreak@*/ break;
804 }
805
806 if (nsp && *nsp) {
807 drc[ix]--; dff[ix] = 1;
808 fi->actions[i] = FA_SKIPNETSHARED;
809 continue;
810 }
811
812 /*
813 * Skip i18n language specific files.
814 */
815 if (languages != NULL && fi->flangs != NULL && *fi->flangs[i]) {
816 ARGV_t lang;
817 const char *l, *le;
818 for (lang = languages; *lang != NULL; lang++) {
819 if (!strcmp(*lang, "all"))
820 /*@innerbreak@*/ break;
821 for (l = fi->flangs[i]; *l != '\0'; l = le) {
822 for (le = l; *le != '\0' && *le != '|'; le++)
823 {};
824 if ((le-l) > 0 && !strncmp(*lang, l, (le-l)))
825 /*@innerbreak@*/ break;
826 if (*le == '|') le++; /* skip over | */
827 }
828 if (*l != '\0')
829 /*@innerbreak@*/ break;
830 }
831 if (*lang == NULL) {
832 drc[ix]--; dff[ix] = 1;
833 fi->actions[i] = FA_SKIPNSTATE;
834 continue;
835 }
836 }
837
838 /*
839 * Skip config files if requested.
840 */
841 if (noConfigs && (rpmfiFFlags(fi) & RPMFILE_CONFIG)) {
842 drc[ix]--; dff[ix] = 1;
843 fi->actions[i] = FA_SKIPNSTATE;
844 continue;
845 }
846
847 /*
848 * Skip documentation if requested.
849 */
850 if (noDocs && (rpmfiFFlags(fi) & RPMFILE_DOC)) {
851 drc[ix]--; dff[ix] = 1;
852 fi->actions[i] = FA_SKIPNSTATE;
853 continue;
854 }
855 }
856
857 /* Skip (now empty) directories that had skipped files. */
858 #ifndef NOTYET
859 if (fi != NULL) /* XXX can't happen */
860 for (j = 0; j < dc; j++)
861 #else
862 if ((fi = rpmfiInitD(fi)) != NULL)
863 while (j = rpmfiNextD(fi) >= 0)
864 #endif
865 {
866
867 if (drc[j]) continue; /* dir still has files. */
868 if (!dff[j]) continue; /* dir was not emptied here. */
869
870 /* Find parent directory and basename. */
871 dn = fi->dnl[j]; dnlen = strlen(dn) - 1;
872 bn = dn + dnlen; bnlen = 0;
873 while (bn > dn && bn[-1] != '/') {
874 bnlen++;
875 dnlen--;
876 bn--;
877 }
878
879 /* If explicitly included in the package, skip the directory. */
880 fi = rpmfiInit(fi, 0);
881 if (fi != NULL) /* XXX lclint */
882 while ((i = rpmfiNext(fi)) >= 0) {
883 const char * fdn, * fbn;
884 rpmuint16_t fFMode;
885
886 if (iosmFileActionSkipped(fi->actions[i]))
887 /*@innercontinue@*/ continue;
888
889 fFMode = rpmfiFMode(fi);
890
891 if (!S_ISDIR(fFMode))
892 /*@innercontinue@*/ continue;
893 fdn = rpmfiDN(fi);
894 if (strlen(fdn) != dnlen)
895 /*@innercontinue@*/ continue;
896 if (strncmp(fdn, dn, dnlen))
897 /*@innercontinue@*/ continue;
898 fbn = rpmfiBN(fi);
899 if (strlen(fbn) != bnlen)
900 /*@innercontinue@*/ continue;
901 if (strncmp(fbn, bn, bnlen))
902 /*@innercontinue@*/ continue;
903 rpmlog(RPMLOG_DEBUG, D_("excluding directory %s\n"), dn);
904 fi->actions[i] = FA_SKIPNSTATE;
905 /*@innerbreak@*/ break;
906 }
907 }
908
909 /*@-dependenttrans@*/
910 netsharedPaths = argvFree(netsharedPaths);
911 languages = argvFree(languages);
912 /*@=dependenttrans@*/
913 }
914 /*@=nullpass@*/
915 /*@=mustmod@*/
916
923 static /*@null@*/
924 rpmfi rpmtsiFi(const rpmtsi tsi)
925 /*@*/
926 {
927 rpmfi fi = NULL;
928
929 if (tsi != NULL && tsi->ocsave != -1) {
930 /*@-type -abstract@*/ /* FIX: rpmte not opaque */
931 rpmte te = rpmtsElement(tsi->ts, tsi->ocsave);
932 /*@-assignexpose@*/
933 if (te != NULL && (fi = te->fi) != NULL)
934 fi->te = te;
935 /*@=assignexpose@*/
936 /*@=type =abstract@*/
937 }
938 /*@-compdef -refcounttrans -usereleased @*/
939 return fi;
940 /*@=compdef =refcounttrans =usereleased @*/
941 }
942
949 /*@-nullpass@*/
950 static rpmRC _processFailedPackage(rpmts ts, rpmte p)
951 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
952 /*@modifies ts, p, rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
953 {
954 int rc = RPMRC_OK; /* assume success */
955
956 /* Handle failed packages. */
957 /* XXX TODO: Add header to rpmdb in PSM_INIT, not PSM_POST. */
958 if (p != NULL && rpmteType(p) == TR_ADDED && !p->installed) {
959 /*@-compdef -usereleased@*/ /* p->fi->te undefined */
960 rpmpsm psm = rpmpsmNew(ts, p, p->fi);
961 /*@=compdef =usereleased@*/
962 /*
963 * If it died before the header was put in the rpmdb, we need
964 * do to something wacky which is add the header to the DB anyway.
965 * This will allow us to add the failed package as an erase
966 * to the rollback transaction. This must be done because we
967 * want the the erase scriptlets to run, and the only way that
968 * is going is if the header is in the rpmdb.
969 */
970 assert(psm != NULL);
971 psm->stepName = "failed"; /* XXX W2DO? */
972 rc = rpmpsmStage(psm, PSM_RPMDB_ADD);
973 psm = rpmpsmFree(psm, "_processFailedPackage");
974 }
975 return rc;
976 }
977 /*@=nullpass@*/
978
979 /*@-nullpass@*/
980 rpmRC rpmtsRollback(rpmts rbts, rpmprobFilterFlags ignoreSet, int running, rpmte rbte)
981 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
982 /*@modifies rbts, rpmGlobalMacroContext, fileSystem, internalState @*/
983 {
984 const char * semfn = NULL;
985 rpmRC rc = 0;
986 rpmuint32_t arbgoal = rpmtsARBGoal(rbts);
987 QVA_t ia = memset(alloca(sizeof(*ia)), 0, sizeof(*ia));
988 time_t ttid;
989 int xx;
990
991 /* Don't attempt rollback's of rollback transactions */
992 if ((rpmtsType(rbts) & RPMTRANS_TYPE_ROLLBACK) ||
993 (rpmtsType(rbts) & RPMTRANS_TYPE_AUTOROLLBACK))
994 return RPMRC_OK;
995
996 if (arbgoal == 0xffffffff)
997 arbgoal = rpmtsGetTid(rbts);
998
999 /* Don't attempt rollbacks if no goal is set. */
1000 if (!running && arbgoal == 0xffffffff)
1001 return RPMRC_OK;
1002
1003 /* We need to remove an headers that were going to be removed so
1004 * as to not foul up the regular rollback mechanism which will not
1005 * handle properly a file being in the repackaged package directory
1006 * and also its header still in the DB.
1007 */
1008 { rpmtsi tsi;
1009 rpmte te;
1010
1011 /* XXX Insure an O_RDWR rpmdb. */
1012 xx = rpmtsOpenDB(rbts, O_RDWR);
1013
1014 tsi = rpmtsiInit(rbts);
1015 while((te = rpmtsiNext(tsi, TR_REMOVED)) != NULL) {
1016 if (te->isSource) continue;
1017 if(!te->u.removed.dboffset)
1018 continue;
1019 rc = rpmdbRemove(rpmtsGetRdb(rbts),
1020 rpmtsGetTid(rbts),
1021 te->u.removed.dboffset, NULL);
1022 if (rc != RPMRC_OK) {
1023 rpmlog(RPMLOG_ERR, _("rpmdb erase failed. NEVRA: %s\n"),
1024 rpmteNEVRA(te));
1025 break;
1026 }
1027 }
1028 tsi = rpmtsiFree(tsi);
1029 if (rc != RPMRC_OK)
1030 goto cleanup;
1031 }
1032
1033 /* Process the failed package */
1034 rc = _processFailedPackage(rbts, rbte);
1035 if (rc != RPMRC_OK)
1036 goto cleanup;
1037
1038 rpmtsEmpty(rbts);
1039
1040 ttid = (time_t)arbgoal;
1041 rpmlog(RPMLOG_NOTICE, _("Rollback to %-24.24s (0x%08x)\n"),
1042 ctime(&ttid), arbgoal);
1043
1044 /* Set the verify signature flags:
1045 * - can't verify signatures/digests on repackaged packages.
1046 * - header check are out.
1047 */
1048 {
1049 rpmVSFlags vsflags = rpmExpandNumeric("%{?_vsflags_erase}");
1050 vsflags |= _RPMVSF_NODIGESTS;
1051 vsflags |= _RPMVSF_NOSIGNATURES;
1052 vsflags |= RPMVSF_NOHDRCHK;
1053 vsflags |= RPMVSF_NEEDPAYLOAD;
1054 xx = rpmtsSetVSFlags(rbts, vsflags);
1055 }
1056
1057 /* Set transaction flags to be the same as the running transaction */
1058 {
1059 rpmtransFlags tsFlags = rpmtsFlags(rbts);
1060 tsFlags &= ~RPMTRANS_FLAG_DIRSTASH; /* No repackage of rollbacks */
1061 tsFlags &= ~RPMTRANS_FLAG_REPACKAGE; /* No repackage of rollbacks */
1062 tsFlags |= RPMTRANS_FLAG_NOFDIGESTS; /* Don't check file digests */
1063 tsFlags = rpmtsSetFlags(rbts, tsFlags);
1064 }
1065
1066 /* Create install arguments structure */
1067 ia->rbtid = arbgoal;
1068 /* transFlags/depFlags from rbts, (re-)set in rpmRollback(). */
1069 ia->transFlags = rpmtsFlags(rbts);
1070 ia->depFlags = rpmtsDFlags(rbts);
1071 /* XXX probFilter is normally set in main(). */
1072 ia->probFilter = ignoreSet; /* XXX RPMPROB_FILTER_NONE? */
1073 /* XXX installInterfaceFlags is normally set in main(). */
1074 ia->installInterfaceFlags = INSTALL_UPGRADE | INSTALL_HASH ;
1075
1076 /* rpmtsCheck and rpmtsOrder failures do not have links. */
1077 ia->no_rollback_links = 1;
1078
1079 /* Create a file semaphore. */
1080 semfn = rpmExpand("%{?semaphore_backout}", NULL);
1081 if (semfn && *semfn) {
1082 FD_t fd = Fopen(semfn, "w.fdio");
1083 if (fd)
1084 xx = Fclose(fd);
1085 }
1086
1087 /*@-compmempass@*/
1088 rc = rpmRollback(rbts, ia, NULL);
1089 /*@=compmempass@*/
1090
1091 cleanup:
1092 /* Remove the file semaphore. */
1093 if (semfn && *semfn)
1094 xx = Unlink(semfn);
1095 semfn = _free(semfn);
1096
1097 return rc;
1098 }
1099 /*@=nullpass@*/
1100
1107 static int cmpArgvStr(/*@null@*/ const char ** AV, /*@null@*/ const char * B)
1108 /*@*/
1109 {
1110 const char ** a;
1111
1112 if (AV != NULL && B != NULL)
1113 for (a = AV; *a != NULL; a++) {
1114 if (**a && *B && !strcmp(*a, B))
1115 return 1;
1116 }
1117 return 0;
1118 }
1119
1120
1127 static int markLinkedFailed(rpmts ts, rpmte p)
1128 /*@globals fileSystem @*/
1129 /*@modifies ts, p, fileSystem @*/
1130 {
1131 rpmtsi qi; rpmte q;
1132 int bingo;
1133
1134 p->linkFailed = 1;
1135
1136 qi = rpmtsiInit(ts);
1137 while ((q = rpmtsiNext(qi, TR_REMOVED)) != NULL) {
1138
1139 if (q->done)
1140 continue;
1141
1142 /*
1143 * Either element may have missing data and can have multiple entries.
1144 * Try for hdrid, then pkgid, finally NEVRA, argv vs. argv compares.
1145 */
1146 bingo = cmpArgvStr(q->flink.Hdrid, p->hdrid);
1147 if (!bingo)
1148 bingo = cmpArgvStr(q->flink.Pkgid, p->pkgid);
1149 if (!bingo)
1150 bingo = cmpArgvStr(q->flink.NEVRA, p->NEVRA);
1151
1152 if (!bingo)
1153 continue;
1154
1155 q->linkFailed = p->linkFailed;
1156 }
1157 qi = rpmtsiFree(qi);
1158
1159 return 0;
1160 }
1161
1162 int rpmtsRun(rpmts ts, rpmps okProbs, rpmprobFilterFlags ignoreSet)
1163 {
1164 static const char msg[] = "rpmtsRun";
1165 rpmuint32_t tscolor = rpmtsColor(ts);
1166 int i, j;
1167 int ourrc = 0;
1168 int totalFileCount = 0;
1169 rpmfi fi;
1170 sharedFileInfo shared, sharedList;
1171 int numShared;
1172 int nexti;
1173 fingerPrintCache fpc;
1174 rpmps ps;
1175 rpmpsm psm;
1176 rpmtsi pi; rpmte p;
1177 rpmtsi qi; rpmte q;
1178 int numAdded;
1179 int numRemoved;
1180 int rollbackFailures = 0;
1181 void * lock = NULL;
1182 void * ptr;
1183 int xx;
1184
1185 /* XXX programmer error segfault avoidance. */
1186 if (rpmtsNElements(ts) <= 0) {
1187 rpmlog(RPMLOG_ERR,
1188 _("Invalid number of transaction elements.\n"));
1189 return -1;
1190 }
1191
1192 rollbackFailures = rpmExpandNumeric("%{?_rollback_transaction_on_failure}");
1193 /* Don't rollback unless repackaging. */
1194 if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_REPACKAGE))
1195 rollbackFailures = 0;
1196 /* Don't rollback if testing. */
1197 if (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST)
1198 rollbackFailures = 0;
1199
1200 if (rpmtsType(ts) & (RPMTRANS_TYPE_ROLLBACK | RPMTRANS_TYPE_AUTOROLLBACK))
1201 rollbackFailures = 0;
1202
1203 /* If we are in test mode, there is no need to rollback on
1204 * failure, nor acquire the transaction lock.
1205 */
1206 /* Don't acquire the transaction lock if testing. */
1207 if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_TEST))
1208 lock = rpmtsAcquireLock(ts);
1209
1210 /* --noscripts implies no scripts or triggers, duh. */
1211 if (rpmtsFlags(ts) & RPMTRANS_FLAG_NOSCRIPTS)
1212 (void) rpmtsSetFlags(ts, (rpmtsFlags(ts) | _noTransScripts | _noTransTriggers));
1213 /* --notriggers implies no triggers, duh. */
1214 if (rpmtsFlags(ts) & RPMTRANS_FLAG_NOTRIGGERS)
1215 (void) rpmtsSetFlags(ts, (rpmtsFlags(ts) | _noTransTriggers));
1216
1217 /* --justdb implies no scripts or triggers, duh. */
1218 if (rpmtsFlags(ts) & RPMTRANS_FLAG_JUSTDB)
1219 (void) rpmtsSetFlags(ts, (rpmtsFlags(ts) | _noTransScripts | _noTransTriggers));
1220
1221 /* if SELinux isn't enabled or init fails, don't bother... */
1222 if (!rpmtsSELinuxEnabled(ts))
1223 (void) rpmtsSetFlags(ts, (rpmtsFlags(ts) | RPMTRANS_FLAG_NOCONTEXTS));
1224
1225 if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOCONTEXTS)) {
1226 const char * fn = rpmGetPath("%{?_install_file_context_path}", NULL);
1227 /*@-moduncon@*/
1228 int xx = matchpathcon_init(fn);
1229 /*@=moduncon@*/
1230 if (xx == -1)
1231 (void) rpmtsSetFlags(ts, (rpmtsFlags(ts) | RPMTRANS_FLAG_NOCONTEXTS));
1232 fn = _free(fn);
1233 }
1234
1235 ts->probs = rpmpsFree(ts->probs);
1236
1237 /* XXX Make sure the database is open RDWR for package install/erase. */
1238 { int dbmode = O_RDONLY;
1239
1240 if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_TEST)) {
1241 pi = rpmtsiInit(ts);
1242 while ((p = rpmtsiNext(pi, 0)) != NULL) {
1243 if (p->isSource) continue;
1244 dbmode = (O_RDWR|O_CREAT);
1245 break;
1246 }
1247 pi = rpmtsiFree(pi);
1248 }
1249
1250 /* Open database RDWR for installing packages. */
1251 if (rpmtsOpenDB(ts, dbmode)) {
1252 lock = rpmtsFreeLock(lock);
1253 return -1; /* XXX W2DO? */
1254 }
1255 }
1256
1257 ts->ignoreSet = ignoreSet;
1258 { const char * currDir = currentDirectory();
1259 rpmtsSetCurrDir(ts, currDir);
1260 currDir = _free(currDir);
1261 }
1262
1263 (void) rpmtsSetChrootDone(ts, 0);
1264
1265 /* XXX rpmtsCreate() sets the transaction id, but apps may not honor. */
1266 { rpmuint32_t tid = (rpmuint32_t) time(NULL);
1267 (void) rpmtsSetTid(ts, tid);
1268 }
1269
1270 /* Get available space on mounted file systems. */
1271 xx = rpmtsInitDSI(ts);
1272
1273 /* ===============================================
1274 * For packages being installed:
1275 * - verify package epoch:version-release is newer.
1276 * - count files.
1277 * For packages being removed:
1278 * - count files.
1279 */
1280
1281 rpmlog(RPMLOG_DEBUG, D_("sanity checking %d elements\n"), rpmtsNElements(ts));
1282 ps = rpmtsProblems(ts);
1283 /* The ordering doesn't matter here */
1284 pi = rpmtsiInit(ts);
1285 /* XXX Only added packages need be checked. */
1286 while ((p = rpmtsiNext(pi, TR_ADDED)) != NULL) {
1287 rpmmi mi;
1288 int fc;
1289
1290 if (p->isSource) continue;
1291 if ((fi = rpmtsiFi(pi)) == NULL)
1292 continue; /* XXX can't happen */
1293 fc = rpmfiFC(fi);
1294
1295 if (!(rpmtsFilterFlags(ts) & RPMPROB_FILTER_OLDPACKAGE)) {
1296 Header h;
1297 mi = rpmtsInitIterator(ts, RPMTAG_NAME, rpmteN(p), 0);
1298 while ((h = rpmmiNext(mi)) != NULL)
1299 xx = ensureOlder(ts, p, h);
1300 mi = rpmmiFree(mi);
1301 }
1302
1303 if (!(rpmtsFilterFlags(ts) & RPMPROB_FILTER_REPLACEPKG)) {
1304 mi = rpmtsInitIterator(ts, RPMTAG_NAME, rpmteN(p), 0);
1305 xx = rpmmiAddPattern(mi, RPMTAG_EPOCH, RPMMIRE_STRCMP,
1306 rpmteE(p));
1307 xx = rpmmiAddPattern(mi, RPMTAG_VERSION, RPMMIRE_STRCMP,
1308 rpmteV(p));
1309 xx = rpmmiAddPattern(mi, RPMTAG_RELEASE, RPMMIRE_STRCMP,
1310 rpmteR(p));
1311 #ifdef RPM_VENDOR_MANDRIVA
1312 xx = rpmmiAddPattern(mi, RPMTAG_DISTEPOCH, RPMMIRE_STRCMP,
1313 rpmteD(p));
1314 #endif
1315 if (tscolor) {
1316 xx = rpmmiAddPattern(mi, RPMTAG_ARCH, RPMMIRE_STRCMP,
1317 rpmteA(p));
1318 xx = rpmmiAddPattern(mi, RPMTAG_OS, RPMMIRE_STRCMP,
1319 rpmteO(p));
1320 }
1321
1322 while (rpmmiNext(mi) != NULL) {
1323 rpmpsAppend(ps, RPMPROB_PKG_INSTALLED,
1324 rpmteNEVR(p), rpmteKey(p),
1325 NULL, NULL,
1326 NULL, 0);
1327 /*@innerbreak@*/ break;
1328 }
1329 mi = rpmmiFree(mi);
1330 }
1331
1332 /* Count no. of files (if any). */
1333 totalFileCount += fc;
1334
1335 }
1336 pi = rpmtsiFree(pi);
1337 ps = rpmpsFree(ps);
1338
1339 /* The ordering doesn't matter here */
1340 pi = rpmtsiInit(ts);
1341 while ((p = rpmtsiNext(pi, TR_REMOVED)) != NULL) {
1342 int fc;
1343
1344 if (p->isSource) continue;
1345 if ((fi = rpmtsiFi(pi)) == NULL)
1346 continue; /* XXX can't happen */
1347 fc = rpmfiFC(fi);
1348
1349 totalFileCount += fc;
1350 }
1351 pi = rpmtsiFree(pi);
1352
1353
1354 /* Run pre-transaction scripts, but only if there are no known
1355 * problems up to this point. */
1356 if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOPRETRANS) &&
1357 (!((rpmtsFlags(ts) & (RPMTRANS_FLAG_BUILD_PROBS|RPMTRANS_FLAG_TEST))
1358 || (rpmpsNumProblems(ts->probs) &&
1359 (okProbs == NULL || rpmpsTrim(ts->probs, okProbs))))))
1360 {
1361 rpmlog(RPMLOG_DEBUG, D_("running pre-transaction scripts\n"));
1362 pi = rpmtsiInit(ts);
1363 while ((p = rpmtsiNext(pi, TR_ADDED)) != NULL) {
1364 if (p->isSource) continue;
1365 if ((fi = rpmtsiFi(pi)) == NULL)
1366 continue; /* XXX can't happen */
1367
1368 /* If no pre-transaction script, then don't bother. */
1369 if (fi->pretrans == NULL)
1370 continue;
1371
1372 p->h = NULL;
1373 p->fd = rpmtsNotify(ts, p, RPMCALLBACK_INST_OPEN_FILE, 0, 0);
1374 if (rpmteFd(p) != NULL) {
1375 rpmVSFlags ovsflags = rpmtsVSFlags(ts);
1376 rpmVSFlags vsflags = ovsflags | RPMVSF_NEEDPAYLOAD;
1377 rpmRC rpmrc;
1378 ovsflags = rpmtsSetVSFlags(ts, vsflags);
1379 rpmrc = rpmReadPackageFile(ts, rpmteFd(p),
1380 rpmteNEVR(p), &p->h);
1381 vsflags = rpmtsSetVSFlags(ts, ovsflags);
1382 switch (rpmrc) {
1383 default:
1384 p->fd = rpmtsNotify(ts, p, RPMCALLBACK_INST_CLOSE_FILE, 0, 0);
1385 p->fd = NULL;
1386 /*@switchbreak@*/ break;
1387 case RPMRC_NOTTRUSTED:
1388 case RPMRC_NOKEY:
1389 case RPMRC_OK:
1390 /*@switchbreak@*/ break;
1391 }
1392 }
1393
1394 if (rpmteFd(p) != NULL) {
1395 int scareMem = 0;
1396 fi = rpmfiNew(ts, p->h, RPMTAG_BASENAMES, scareMem);
1397 if (fi != NULL) { /* XXX can't happen */
1398 fi->te = p;
1399 p->fi = fi;
1400 }
1401 /*@-compdef -usereleased@*/ /* p->fi->te undefined */
1402 psm = rpmpsmNew(ts, p, p->fi);
1403 /*@=compdef =usereleased@*/
1404 assert(psm != NULL);
1405 psm->stepName = "pretrans";
1406 psm->scriptTag = RPMTAG_PRETRANS;
1407 psm->progTag = RPMTAG_PRETRANSPROG;
1408 xx = rpmpsmStage(psm, PSM_SCRIPT);
1409 psm = rpmpsmFree(psm, msg);
1410
1411 /*@-compdef -usereleased @*/
1412 p->fd = rpmtsNotify(ts, p, RPMCALLBACK_INST_CLOSE_FILE, 0, 0);
1413 /*@=compdef =usereleased @*/
1414 p->fd = NULL;
1415 (void)headerFree(p->h);
1416 p->h = NULL;
1417 }
1418 }
1419 pi = rpmtsiFree(pi);
1420 }
1421
1422 /* ===============================================
1423 * Initialize transaction element file info for package:
1424 */
1425
1426 /*
1427 * FIXME?: we'd be better off assembling one very large file list and
1428 * calling fpLookupList only once. I'm not sure that the speedup is
1429 * worth the trouble though.
1430 */
1431 rpmlog(RPMLOG_DEBUG, D_("computing %d file fingerprints\n"), totalFileCount);
1432
1433 numAdded = numRemoved = 0;
1434 pi = rpmtsiInit(ts);
1435 while ((p = rpmtsiNext(pi, 0)) != NULL) {
1436 int fc;
1437
1438 if (p->isSource) continue;
1439 if ((fi = rpmtsiFi(pi)) == NULL)
1440 continue; /* XXX can't happen */
1441 fc = rpmfiFC(fi);
1442
1443 switch (rpmteType(p)) {
1444 case TR_ADDED:
1445 numAdded++;
1446 fi->record = 0;
1447 /* Skip netshared paths, not our i18n files, and excluded docs */
1448 if (fc > 0)
1449 skipFiles(ts, fi);
1450 /*@switchbreak@*/ break;
1451 case TR_REMOVED:
1452 numRemoved++;
1453 fi->record = rpmteDBOffset(p);
1454 /*@switchbreak@*/ break;
1455 }
1456
1457 fi->fps = (fc > 0 ? xmalloc(fc * sizeof(*fi->fps)) : NULL);
1458 }
1459 pi = rpmtsiFree(pi);
1460
1461 if (!rpmtsChrootDone(ts)) {
1462 const char * rootDir = rpmtsRootDir(ts);
1463 static int openall_before_chroot = -1;
1464
1465 if (openall_before_chroot < 0)
1466 openall_before_chroot = rpmExpandNumeric("%{?_openall_before_chroot}");
1467
1468 xx = Chdir("/");
1469 /*@-modobserver@*/
1470 if (rootDir != NULL && strcmp(rootDir, "/") && *rootDir == '/') {
1471 if (openall_before_chroot)
1472 xx = rpmdbOpenAll(rpmtsGetRdb(ts));
1473 xx = Chroot(rootDir);
1474 }
1475 /*@=modobserver@*/
1476 (void) rpmtsSetChrootDone(ts, 1);
1477 }
1478
1479 ts->ht = htCreate(totalFileCount * 2, 0, 0, fpHashFunction, fpEqual);
1480 fpc = fpCacheCreate(totalFileCount);
1481
1482 /* ===============================================
1483 * Add fingerprint for each file not skipped.
1484 */
1485 pi = rpmtsiInit(ts);
1486 while ((p = rpmtsiNext(pi, 0)) != NULL) {
1487 int fc;
1488
1489 (void) rpmdbCheckSignals();
1490
1491 if (p->isSource) continue;
1492 if ((fi = rpmtsiFi(pi)) == NULL)
1493 continue; /* XXX can't happen */
1494 fc = rpmfiFC(fi);
1495
1496 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0);
1497 fpLookupList(fpc, fi->dnl, fi->bnl, fi->dil, fc, fi->fps);
1498 fi = rpmfiInit(fi, 0);
1499 if (fi != NULL) /* XXX lclint */
1500 while ((i = rpmfiNext(fi)) >= 0) {
1501 if (iosmFileActionSkipped(fi->actions[i]))
1502 /*@innercontinue@*/ continue;
1503 /*@-dependenttrans@*/
1504 htAddEntry(ts->ht, fi->fps + i, (void *) fi);
1505 /*@=dependenttrans@*/
1506 }
1507 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), fc);
1508
1509 }
1510 pi = rpmtsiFree(pi);
1511
1512 ptr = rpmtsNotify(ts, NULL, RPMCALLBACK_TRANS_START, 6, ts->orderCount);
1513
1514 /* ===============================================
1515 * Compute file disposition for each package in transaction set.
1516 */
1517 rpmlog(RPMLOG_DEBUG, D_("computing file dispositions\n"));
1518 ps = rpmtsProblems(ts);
1519 pi = rpmtsiInit(ts);
1520 /*@-nullpass@*/
1521 while ((p = rpmtsiNext(pi, 0)) != NULL) {
1522 dbiIndexSet * matches;
1523 unsigned int exclude;
1524 int knownBad;
1525 int fc;
1526
1527 (void) rpmdbCheckSignals();
1528
1529 if ((fi = rpmtsiFi(pi)) == NULL)
1530 continue; /* XXX can't happen */
1531 fc = rpmfiFC(fi);
1532
1533 ptr = rpmtsNotify(ts, NULL, RPMCALLBACK_TRANS_PROGRESS, rpmtsiOc(pi),
1534 ts->orderCount);
1535
1536 if (fc == 0) continue;
1537
1538 /* All source files get installed. */
1539 if (p->isSource) {
1540 fi = rpmfiInit(fi, 0);
1541 if (fi != NULL)
1542 while ((i = rpmfiNext(fi)) >= 0)
1543 fi->actions[i] = FA_CREATE;
1544 continue;
1545 }
1546
1547 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0);
1548 /* Extract file info for all files in this package from the database. */
1549 matches = xcalloc(fc, sizeof(*matches));
1550 exclude = (rpmteType(p) == TR_REMOVED ? fi->record : 0);
1551 if (rpmdbFindFpList(rpmtsGetRdb(ts), fi->fps, matches, fc, exclude)) {
1552 ps = rpmpsFree(ps);
1553 lock = rpmtsFreeLock(lock);
1554 return 1; /* XXX WTFO? */
1555 }
1556
1557 numShared = 0;
1558 fi = rpmfiInit(fi, 0);
1559 while ((i = rpmfiNext(fi)) >= 0) {
1560 struct stat sb, *st = &sb;
1561 rpmuint32_t FFlags = rpmfiFFlags(fi);
1562 numShared += dbiIndexSetCount(matches[i]);
1563 if (!(FFlags & RPMFILE_CONFIG))
1564 /*@innercontinue@*/ continue;
1565 if (!Lstat(rpmfiFN(fi), st)) {
1566 FFlags |= RPMFILE_EXISTS;
1567 if ((512 * st->st_blocks) < st->st_size)
1568 FFlags |= RPMFILE_SPARSE;
1569 (void) rpmfiSetFFlags(fi, FFlags);
1570 }
1571 }
1572
1573 /* Build sorted file info list for this package. */
1574 shared = sharedList = xcalloc((numShared + 1), sizeof(*sharedList));
1575
1576 fi = rpmfiInit(fi, 0);
1577 while ((i = rpmfiNext(fi)) >= 0) {
1578 /*
1579 * Take care not to mark files as replaced in packages that will
1580 * have been removed before we will get here.
1581 */
1582 for (j = 0; j < (int)dbiIndexSetCount(matches[i]); j++) {
1583 int ro;
1584 ro = dbiIndexRecordOffset(matches[i], j);
1585 knownBad = 0;
1586 qi = rpmtsiInit(ts);
1587 while ((q = rpmtsiNext(qi, TR_REMOVED)) != NULL) {
1588 if (ro == knownBad)
1589 /*@innerbreak@*/ break;
1590 if (rpmteDBOffset(q) == ro)
1591 knownBad = ro;
1592 }
1593 qi = rpmtsiFree(qi);
1594
1595 shared->pkgFileNum = i;
1596 shared->otherPkg = dbiIndexRecordOffset(matches[i], j);
1597 shared->otherFileNum = dbiIndexRecordFileNumber(matches[i], j);
1598 shared->isRemoved = (knownBad == ro);
1599 shared++;
1600 }
1601 matches[i] = dbiFreeIndexSet(matches[i]);
1602 }
1603 numShared = shared - sharedList;
1604 shared->otherPkg = -1;
1605 matches = _free(matches);
1606
1607 /* Sort file info by other package index (otherPkg) */
1608 qsort(sharedList, numShared, sizeof(*shared), sharedCmp);
1609
1610 /* For all files from this package that are in the database ... */
1611 /*@-nullpass@*/
1612 for (i = 0; i < numShared; i = nexti) {
1613 int beingRemoved;
1614
1615 shared = sharedList + i;
1616
1617 /* Find the end of the files in the other package. */
1618 for (nexti = i + 1; nexti < numShared; nexti++) {
1619 if (sharedList[nexti].otherPkg != shared->otherPkg)
1620 /*@innerbreak@*/ break;
1621 }
1622
1623 /* Is this file from a package being removed? */
1624 beingRemoved = 0;
1625 if (ts->removedPackages != NULL)
1626 for (j = 0; j < ts->numRemovedPackages; j++) {
1627 if (ts->removedPackages[j] != (int)shared->otherPkg)
1628 /*@innercontinue@*/ continue;
1629 beingRemoved = 1;
1630 /*@innerbreak@*/ break;
1631 }
1632
1633 /* Determine the fate of each file. */
1634 switch (rpmteType(p)) {
1635 case TR_ADDED:
1636 xx = handleInstInstalledFiles(ts, p, fi, shared, nexti - i,
1637 !(beingRemoved || (rpmtsFilterFlags(ts) & RPMPROB_FILTER_REPLACEOLDFILES)));
1638 /*@switchbreak@*/ break;
1639 case TR_REMOVED:
1640 if (!beingRemoved)
1641 xx = handleRmvdInstalledFiles(ts, fi, shared, nexti - i);
1642 /*@switchbreak@*/ break;
1643 }
1644 }
1645 /*@=nullpass@*/
1646
1647 free(sharedList);
1648
1649 /* Update disk space needs on each partition for this package. */
1650 /*@-nullpass@*/
1651 handleOverlappedFiles(ts, p, fi);
1652 /*@=nullpass@*/
1653
1654 /* Check added package has sufficient space on each partition used. */
1655 switch (rpmteType(p)) {
1656 case TR_ADDED:
1657 rpmtsCheckDSIProblems(ts, p);
1658 /*@switchbreak@*/ break;
1659 case TR_REMOVED:
1660 /*@switchbreak@*/ break;
1661 }
1662 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), fc);
1663 }
1664 /*@=nullpass@*/
1665 pi = rpmtsiFree(pi);
1666 ps = rpmpsFree(ps);
1667
1668 if (rpmtsChrootDone(ts)) {
1669 const char * rootDir = rpmtsRootDir(ts);
1670 const char * currDir = rpmtsCurrDir(ts);
1671 /*@-modobserver@*/
1672 if (rootDir != NULL && strcmp(rootDir, "/") && *rootDir == '/')
1673 xx = Chroot(".");
1674 /*@=modobserver@*/
1675 (void) rpmtsSetChrootDone(ts, 0);
1676 if (currDir != NULL)
1677 xx = Chdir(currDir);
1678 }
1679
1680 ptr = rpmtsNotify(ts, NULL, RPMCALLBACK_TRANS_STOP, 6, ts->orderCount);
1681
1682 /* ===============================================
1683 * Free unused memory as soon as possible.
1684 */
1685 pi = rpmtsiInit(ts);
1686 while ((p = rpmtsiNext(pi, 0)) != NULL) {
1687 if (p->isSource) continue;
1688 if ((fi = rpmtsiFi(pi)) == NULL)
1689 continue; /* XXX can't happen */
1690 if (rpmfiFC(fi) == 0)
1691 continue;
1692 fi->fps = _free(fi->fps);
1693 }
1694 pi = rpmtsiFree(pi);
1695
1696 fpc = fpCacheFree(fpc);
1697 ts->ht = htFree(ts->ht);
1698
1699 /* ===============================================
1700 * If unfiltered problems exist, free memory and return.
1701 */
1702 if ((rpmtsFlags(ts) & RPMTRANS_FLAG_BUILD_PROBS)
1703 || (rpmpsNumProblems(ts->probs) &&
1704 (okProbs == NULL || rpmpsTrim(ts->probs, okProbs)))
1705 )
1706 {
1707 lock = rpmtsFreeLock(lock);
1708 return ts->orderCount;
1709 }
1710
1711 /* ===============================================
1712 * Save removed files before erasing.
1713 */
1714 if (rpmtsFlags(ts) & (RPMTRANS_FLAG_DIRSTASH | RPMTRANS_FLAG_REPACKAGE)) {
1715 int progress = 0;
1716
1717 pi = rpmtsiInit(ts);
1718 while ((p = rpmtsiNext(pi, 0)) != NULL) {
1719
1720 (void) rpmdbCheckSignals();
1721
1722 if (p->isSource) continue;
1723 if ((fi = rpmtsiFi(pi)) == NULL)
1724 continue; /* XXX can't happen */
1725 switch (rpmteType(p)) {
1726 case TR_ADDED:
1727 /*@switchbreak@*/ break;
1728 case TR_REMOVED:
1729 if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_REPACKAGE))
1730 /*@switchbreak@*/ break;
1731 if (!progress)
1732 ptr = rpmtsNotify(ts, NULL, RPMCALLBACK_REPACKAGE_START,
1733 7, numRemoved);
1734
1735 ptr = rpmtsNotify(ts, NULL, RPMCALLBACK_REPACKAGE_PROGRESS,
1736 progress, numRemoved);
1737 progress++;
1738
1739 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_REPACKAGE), 0);
1740
1741 /* XXX TR_REMOVED needs IOSM_MAP_{ABSOLUTE,ADDDOT} IOSM_ALL_HARDLINKS */
1742 fi->mapflags |= IOSM_MAP_ABSOLUTE;
1743 fi->mapflags |= IOSM_MAP_ADDDOT;
1744 fi->mapflags |= IOSM_ALL_HARDLINKS;
1745 psm = rpmpsmNew(ts, p, fi);
1746 assert(psm != NULL);
1747 xx = rpmpsmStage(psm, PSM_PKGSAVE);
1748 psm = rpmpsmFree(psm, msg);
1749 fi->mapflags &= ~IOSM_MAP_ABSOLUTE;
1750 fi->mapflags &= ~IOSM_MAP_ADDDOT;
1751 fi->mapflags &= ~IOSM_ALL_HARDLINKS;
1752
1753 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_REPACKAGE), 0);
1754
1755 /*@switchbreak@*/ break;
1756 }
1757 }
1758 pi = rpmtsiFree(pi);
1759 if (progress)
1760 ptr = rpmtsNotify(ts, NULL, RPMCALLBACK_REPACKAGE_STOP,
1761 7, numRemoved);
1762 }
1763
1764 /* ===============================================
1765 * Install and remove packages.
1766 */
1767 /*@-nullpass@*/
1768 pi = rpmtsiInit(ts);
1769 while ((p = rpmtsiNext(pi, 0)) != NULL) {
1770 alKey pkgKey;
1771 int gotfd;
1772
1773 (void) rpmdbCheckSignals();
1774
1775 gotfd = 0;
1776 if ((fi = rpmtsiFi(pi)) == NULL)
1777 continue; /* XXX can't happen */
1778
1779 psm = rpmpsmNew(ts, p, fi);
1780 assert(psm != NULL);
1781 if (rpmtsiOc(pi) >= rpmtsUnorderedSuccessors(ts, -1))
1782 psm->flags |= RPMPSM_FLAGS_UNORDERED;
1783 else
1784 psm->flags &= ~RPMPSM_FLAGS_UNORDERED;
1785
1786 switch (rpmteType(p)) {
1787 case TR_ADDED:
1788 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_INSTALL), 0);
1789
1790 pkgKey = rpmteAddedKey(p);
1791
1792 rpmlog(RPMLOG_DEBUG, "========== +++ %s %s-%s 0x%x\n",
1793 rpmteNEVR(p), rpmteA(p), rpmteO(p), rpmteColor(p));
1794
1795 p->h = NULL;
1796 /*@-type@*/ /* FIX: rpmte not opaque */
1797 {
1798 p->fd = rpmtsNotify(ts, p, RPMCALLBACK_INST_OPEN_FILE, 0, 0);
1799 if (rpmteFd(p) != NULL) {
1800 rpmVSFlags ovsflags = rpmtsVSFlags(ts);
1801 rpmVSFlags vsflags = ovsflags | RPMVSF_NEEDPAYLOAD;
1802 rpmRC rpmrc;
1803
1804 ovsflags = rpmtsSetVSFlags(ts, vsflags);
1805 rpmrc = rpmReadPackageFile(ts, rpmteFd(p),
1806 rpmteNEVR(p), &p->h);
1807 vsflags = rpmtsSetVSFlags(ts, ovsflags);
1808
1809 switch (rpmrc) {
1810 default:
1811 p->fd = rpmtsNotify(ts, p, RPMCALLBACK_INST_CLOSE_FILE,
1812 0, 0);
1813 p->fd = NULL;
1814 ourrc++;
1815 /*@innerbreak@*/ break;
1816 case RPMRC_NOTTRUSTED:
1817 case RPMRC_NOKEY:
1818 case RPMRC_OK:
1819 /*@innerbreak@*/ break;
1820 }
1821 if (rpmteFd(p) != NULL) gotfd = 1;
1822 } else {
1823 ourrc++;
1824 xx = markLinkedFailed(ts, p);
1825 }
1826 }
1827 /*@=type@*/
1828
1829 if (rpmteFd(p) != NULL) {
1830 /*
1831 * XXX Sludge necessary to tranfer existing fstates/actions
1832 * XXX around a recreated file info set.
1833 */
1834 psm->fi = rpmfiFree(psm->fi);
1835 {
1836 rpmuint8_t * fstates = fi->fstates;
1837 iosmFileAction * actions = (iosmFileAction *) fi->actions;
1838 int mapflags = fi->mapflags;
1839 rpmte savep;
1840 int scareMem = 0;
1841
1842 fi->fstates = NULL;
1843 fi->actions = NULL;
1844 /*@-nullstate@*/ /* FIX: fi->actions is NULL */
1845 fi = rpmfiFree(fi);
1846 /*@=nullstate@*/
1847
1848 savep = rpmtsSetRelocateElement(ts, p);
1849 fi = rpmfiNew(ts, p->h, RPMTAG_BASENAMES, scareMem);
1850 (void) rpmtsSetRelocateElement(ts, savep);
1851
1852 if (fi != NULL) { /* XXX can't happen */
1853 fi->te = p;
1854 fi->fstates = _free(fi->fstates);
1855 fi->fstates = fstates;
1856 fi->actions = _free(fi->actions);
1857 fi->actions = (int *) actions;
1858 if (mapflags & IOSM_SBIT_CHECK)
1859 fi->mapflags |= IOSM_SBIT_CHECK;
1860 p->fi = fi;
1861 }
1862 }
1863 psm->fi = rpmfiLink(p->fi, NULL);
1864
1865 if ((xx = rpmpsmStage(psm, PSM_PKGINSTALL)) != 0) {
1866 ourrc++;
1867 xx = markLinkedFailed(ts, p);
1868 }
1869 #if defined(RPM_VENDOR_MANDRIVA)
1870 else {
1871 if(!rpmteIsSource(fi->te))
1872 xx = mayAddToFilesAwaitingFiletriggers(rpmtsRootDir(ts), psm->fi, 1);
1873 p->done = 1;
1874 }
1875 #endif
1876
1877 } else {
1878 ourrc++;
1879 }
1880
1881 if (gotfd) {
1882 p->fd = rpmtsNotify(ts, p, RPMCALLBACK_INST_CLOSE_FILE, 0, 0);
1883 p->fd = NULL;
1884 }
1885
1886 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_INSTALL), 0);
1887
1888 /*@switchbreak@*/ break;
1889
1890 case TR_REMOVED:
1891 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_ERASE), 0);
1892
1893 rpmlog(RPMLOG_DEBUG, "========== --- %s %s-%s 0x%x\n",
1894 rpmteNEVR(p), rpmteA(p), rpmteO(p), rpmteColor(p));
1895
1896 /* If linked element install failed, then don't erase. */
1897 if (p->linkFailed == 0) {
1898 if ((xx = rpmpsmStage(psm, PSM_PKGERASE)) != 0) {
1899 ourrc++;
1900 }
1901 #if defined(RPM_VENDOR_MANDRIVA)
1902 else {
1903 if(!rpmteIsSource(fi->te))
1904 xx = mayAddToFilesAwaitingFiletriggers(rpmtsRootDir(ts), psm->fi, 0);
1905 p->done = 1;
1906 }
1907 #endif
1908 } else
1909 ourrc++;
1910
1911 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_ERASE), 0);
1912
1913 /*@switchbreak@*/ break;
1914 }
1915
1916 /* Would have freed header above in TR_ADD portion of switch
1917 * but needed the header to add it to the autorollback transaction.
1918 */
1919 if (rpmteType(p) == TR_ADDED) {
1920 (void)headerFree(p->h);
1921 p->h = NULL;
1922 }
1923
1924 xx = rpmdbSync(rpmtsGetRdb(ts));
1925
1926 /*@-nullstate@*/ /* FIX: psm->fi may be NULL */
1927 psm = rpmpsmFree(psm, msg);
1928 /*@=nullstate@*/
1929
1930 /* If we received an error, lets break out and rollback, provided
1931 * autorollback is enabled.
1932 */
1933 if (ourrc && rollbackFailures) {
1934 xx = rpmtsRollback(ts, ignoreSet, 1, p);
1935 break;
1936 }
1937 }
1938 /*@=nullpass@*/
1939 pi = rpmtsiFree(pi);
1940
1941 if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOPOSTTRANS) &&
1942 !(rpmtsFlags(ts) & RPMTRANS_FLAG_TEST))
1943 {
1944
1945 #if defined(RPM_VENDOR_MANDRIVA)
1946 if ((rpmtsFlags(ts) & _noTransTriggers) != _noTransTriggers)
1947 rpmRunFileTriggers(rpmtsRootDir(ts));
1948 #endif
1949
1950 rpmlog(RPMLOG_DEBUG, D_("running post-transaction scripts\n"));
1951 pi = rpmtsiInit(ts);
1952 while ((p = rpmtsiNext(pi, TR_ADDED)) != NULL) {
1953 int haspostscript;
1954
1955 if ((fi = rpmtsiFi(pi)) == NULL)
1956 continue; /* XXX can't happen */
1957
1958 haspostscript = (fi->posttrans || fi->posttransprog ? 1 : 0);
1959 p->fi = rpmfiFree(p->fi);
1960
1961 /* If no post-transaction script, then don't bother. */
1962 if (!haspostscript)
1963 continue;
1964
1965 p->h = NULL;
1966 p->fd = rpmtsNotify(ts, p, RPMCALLBACK_INST_OPEN_FILE, 0, 0);
1967 if (rpmteFd(p) != NULL) {
1968 rpmVSFlags ovsflags = rpmtsVSFlags(ts);
1969 rpmVSFlags vsflags = ovsflags | RPMVSF_NEEDPAYLOAD;
1970 rpmRC rpmrc;
1971 ovsflags = rpmtsSetVSFlags(ts, vsflags);
1972 rpmrc = rpmReadPackageFile(ts, rpmteFd(p),
1973 rpmteNEVR(p), &p->h);
1974 vsflags = rpmtsSetVSFlags(ts, ovsflags);
1975 switch (rpmrc) {
1976 default:
1977 p->fd = rpmtsNotify(ts, p, RPMCALLBACK_INST_CLOSE_FILE,
1978 0, 0);
1979 p->fd = NULL;
1980 /*@switchbreak@*/ break;
1981 case RPMRC_NOTTRUSTED:
1982 case RPMRC_NOKEY:
1983 case RPMRC_OK:
1984 /*@switchbreak@*/ break;
1985 }
1986 }
1987
1988 /*@-nullpass@*/
1989 if (rpmteFd(p) != NULL) {
1990 int scareMem = 0;
1991 p->fi = rpmfiNew(ts, p->h, RPMTAG_BASENAMES, scareMem);
1992 if (p->fi != NULL) /* XXX can't happen */
1993 p->fi->te = p;
1994 /*@-compdef -usereleased@*/ /* p->fi->te undefined */
1995 psm = rpmpsmNew(ts, p, p->fi);
1996 /*@=compdef =usereleased@*/
1997 assert(psm != NULL);
1998 psm->stepName = "posttrans";
1999 psm->scriptTag = RPMTAG_POSTTRANS;
2000 psm->progTag = RPMTAG_POSTTRANSPROG;
2001 xx = rpmpsmStage(psm, PSM_SCRIPT);
2002 psm = rpmpsmFree(psm, msg);
2003
2004 /*@-compdef -usereleased @*/
2005 p->fd = rpmtsNotify(ts, p, RPMCALLBACK_INST_CLOSE_FILE, 0, 0);
2006 /*@=compdef =usereleased @*/
2007 p->fd = NULL;
2008 p->fi = rpmfiFree(p->fi);
2009 (void)headerFree(p->h);
2010 p->h = NULL;
2011 }
2012 /*@=nullpass@*/
2013 }
2014 pi = rpmtsiFree(pi);
2015 }
2016
2017 /*@-moduncon -noeffectuncon @*/
2018 if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOCONTEXTS))
2019 matchpathcon_fini();
2020 /*@=moduncon =noeffectuncon @*/
2021
2022 lock = rpmtsFreeLock(lock);
2023
2024 /*@-nullstate@*/ /* FIX: ts->flList may be NULL */
2025 if (ourrc)
2026 return -1;
2027 else
2028 return 0;
2029 /*@=nullstate@*/
2030 }