rpm  5.2.1
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 
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) {
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 
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 =
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) {
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;
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));
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);
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@*/
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@*/
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) ||
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(). */
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) {
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 
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. */
1213  /* --notriggers implies no triggers, duh. */
1215  (void) rpmtsSetFlags(ts, (rpmtsFlags(ts) | _noTransTriggers));
1216 
1217  /* --justdb implies no scripts or triggers, duh. */
1218  if (rpmtsFlags(ts) & RPMTRANS_FLAG_JUSTDB)
1220 
1221  /* if SELinux isn't enabled or init fails, don't bother... */
1222  if (!rpmtsSELinuxEnabled(ts))
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 
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 
1304  mi = rpmtsInitIterator(ts, RPMTAG_NAME, rpmteN(p), 0);
1306  rpmteE(p));
1308  rpmteV(p));
1310  rpmteR(p));
1311 #ifdef RPM_VENDOR_MANDRIVA
1313  rpmteD(p));
1314 #endif
1315  if (tscolor) {
1317  rpmteA(p));
1319  rpmteO(p));
1320  }
1321 
1322  while (rpmmiNext(mi) != NULL) {
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;
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  */
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 
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:
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:
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;
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))
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 }