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