rpm  5.4.10
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 <rpmsx.h>
12 
13 #include <rpmtypes.h>
14 #include <rpmtag.h>
15 #include <pkgio.h>
16 
17 #define _FPRINT_INTERNAL
18 #include "fprint.h"
19 
20 #define _RPMDB_INTERNAL /* XXX for dbiIndexFoo() */
21 #include <rpmdb.h>
22 #include "legacy.h" /* XXX dodigest */
23 
24 #define _RPMFI_INTERNAL
25 #include <rpmfi.h>
26 #include "fsm.h"
27 
28 #define _RPMTE_INTERNAL
29 #include "rpmte.h"
30 #define _RPMTS_INTERNAL
31 #include "rpmts.h"
32 
33 #define _RPMSQ_INTERNAL
34 #define _RPMPSM_INTERNAL
35 #include "psm.h"
36 
37 #include "rpmds.h"
38 
39 #include "rpmlock.h"
40 
41 #include "misc.h" /* XXX currentDirectory */
42 
43 #if defined(RPM_VENDOR_MANDRIVA)
44 #include "filetriggers.h" /* XXX mayAddToFilesAwaitingFiletriggers, rpmRunFileTriggers */
45 #endif
46 
47 #include <rpmcli.h> /* XXX QVA_t INSTALL_FOO flags */
48 #include <rpmrollback.h> /* IDTX prototypes */
49 
50 #include "debug.h"
51 
52 /*@access dbiIndexSet @*/
53 
54 /*@access fnpyKey @*/
55 
56 /*@access alKey @*/
57 /*@access rpmdb @*/ /* XXX cast */
58 
59 /*@access rpmfi @*/
60 /*@access rpmps @*/ /* XXX need rpmProblemSetOK() */
61 /*@access rpmpsm @*/
62 
63 /*@access rpmte @*/
64 /*@access rpmtsi @*/
65 /*@access rpmts @*/
66 
67 /*@access IDT @*/
68 /*@access IDTX @*/
69 /*@access FD_t @*/
70 
71 #if defined(RPM_VENDOR_MANDRIVA)
72 static int is_a_doc_conflict(rpmfi fi)
73 {
74  const char *ignorelist[] = {
75  "/usr/share/man/",
76  "/usr/share/gtk-doc/html/",
77  "/usr/share/gnome/html/",
78  NULL
79  };
80  const char *fn = rpmfiFN(fi);
81  const char **dnp;
82  for (dnp = ignorelist; *dnp != NULL; dnp++)
83  if (strstr(fn, *dnp) == fn) return 1;
84 
85  return 0;
86 }
87 #endif
88 
89 #ifdef __cplusplus
90 
91 #define FF_ISSET(_fflags, _FLAG) ((_fflags) & (RPMFILE_##_FLAG))
92 
93 #define QVA_ISSET(_qvaflags, _FLAG) ((_qvaflags) & (VERIFY_##_FLAG))
94 
95 #define VSF_ISSET(_vsflags, _FLAG) ((_vsflags) & (RPMVSF_##_FLAG))
96 #define VSF_SET(_vsflags, _FLAG) \
97  (*((unsigned *)&(_vsflags)) |= (RPMVSF_##_FLAG))
98 #define VSF_CLR(_vsflags, _FLAG) \
99  (*((unsigned *)&(_vsflags)) &= ~(RPMVSF_##_FLAG))
100 
101 #define TSF_ISSET(_tsflags, _FLAG) ((_tsflags) & (RPMTRANS_FLAG_##_FLAG))
102 #define TSF_SET(_tsflags, _FLAG) \
103  (*((unsigned *)&(_tsflags)) |= (RPMTRANS_FLAG_##_FLAG))
104 #define TSF_CLR(_tsflags, _FLAG) \
105  (*((unsigned *)&(_tsflags)) &= ~(RPMTRANS_FLAG_##_FLAG))
106 
107 #define IIF_ISSET(_iflags, _FLAG) ((_iflags) & (INSTALL_##_FLAG))
108 #define IIF_SET(_iflags, _FLAG) \
109  (*((unsigned *)&(_iflags)) |= (INSTALL_##_FLAG))
110 #define IIF_CLR(_iflags, _FLAG) \
111  (*((unsigned *)&(_iflags)) &= ~(INSTALL_##_FLAG))
112 
113 GENfree(int *)
114 GENfree(struct fingerPrint_s *)
115 
116 #else /* __cplusplus */
117 
118 #define FF_ISSET(_fflags, _FLAG) ((_fflags) & (RPMFILE_##_FLAG))
119 
120 #define QVA_ISSET(_qvaflags, _FLAG) ((_qvaflags) & (VERIFY_##_FLAG))
121 
122 #define VSF_ISSET(_vsflags, _FLAG) ((_vsflags) & (RPMVSF_##_FLAG))
123 #define VSF_SET(_vsflags, _FLAG) (_vsflags) |= (RPMVSF_##_FLAG)
124 #define VSF_CLR(_vsflags, _FLAG) (_vsflags) &= ~(RPMVSF_##_FLAG)
125 
126 #define TSF_ISSET(_tsflags, _FLAG) ((_tsflags) & (RPMTRANS_FLAG_##_FLAG))
127 #define TSF_SET(_tsflags, _FLAG) (_tsflags) |= (RPMTRANS_FLAG_##_FLAG)
128 #define TSF_CLR(_tsflags, _FLAG) (_tsflags) &= ~(RPMTRANS_FLAG_##_FLAG)
129 
130 #define IIF_ISSET(_iflags, _FLAG) ((_iflags) & (INSTALL_##_FLAG))
131 #define IIF_SET(_iflags, _FLAG) (_iflags) |= (INSTALL_##_FLAG)
132 #define IIF_CLR(_iflags, _FLAG) (_iflags) &= ~(INSTALL_##_FLAG)
133 
134 #endif /* __cplusplus */
135 
136 static int handleInstInstalledFile(const rpmts ts, rpmte p, rpmfi fi,
137  Header otherHeader, rpmfi otherFi,
138  int beingRemoved)
139  /*@modifies ts, p, fi @*/
140 {
141  unsigned int fx = rpmfiFX(fi);
142  int isCfgFile = (FF_ISSET(rpmfiFFlags(otherFi), CONFIG) || FF_ISSET(rpmfiFFlags(fi), CONFIG));
143 #ifdef REFERENCE
144  rpmfs fs = rpmteGetFileStates(p);
145  if (XFA_SKIPPING(rpmfsGetAction(fs, fx)))
146 #else
147  if (iosmFileActionSkipped((iosmFileAction) fi->actions[fx]))
148 #endif
149  return 0;
150 
151  if (rpmfiCompare(otherFi, fi)) {
152 #ifdef REFERENCE
153  rpm_color_t tscolor = rpmtsColor(ts);
154  rpm_color_t prefcolor = rpmtsPrefColor(ts);
155  rpm_color_t FColor = rpmfiFColor(fi) & tscolor;
156  rpm_color_t oFColor = rpmfiFColor(otherFi) & tscolor;
157 #else
158  rpmuint32_t tscolor = rpmtsColor(ts);
159  rpmuint32_t prefcolor = rpmtsPrefColor(ts);
160  rpmuint32_t FColor = rpmfiFColor(fi) & tscolor;
161  rpmuint32_t oFColor = rpmfiFColor(otherFi) & tscolor;
162 #endif
163  int rConflicts;
164 
165  rConflicts = !(beingRemoved || (rpmtsFilterFlags(ts) & RPMPROB_FILTER_REPLACEOLDFILES));
166  /* Resolve file conflicts to prefer Elf64 (if not forced). */
167  if (tscolor != 0 && FColor != 0 && FColor != oFColor) {
168  if (oFColor & prefcolor) {
169 #ifdef REFERENCE
170  rpmfsSetAction(fs, fx, FA_SKIPCOLOR);
171 #else
172  fi->actions[fx] = FA_SKIPCOLOR;
173 #endif
174  rConflicts = 0;
175  } else if (FColor & prefcolor) {
176 #ifdef REFERENCE
177  rpmfsSetAction(fs, fx, FA_CREATE);
178 #else
179  fi->actions[fx] = FA_CREATE;
180 #endif
181  rConflicts = 0;
182  }
183  }
184 
185 #if defined(RPM_VENDOR_MANDRIVA)
186  if(rpmExpandNumeric("%{?_legacy_compat_no_doc_conflicts}")) {
187  /* HACK: always install latest (arch-independent) man
188  pages and gtk/gnome html doc files. */
189  if (rConflicts && is_a_doc_conflict(fi)) {
190  fi->actions[fx] = FA_CREATE;
191  rConflicts = 0;
192  }
193  }
194 #endif
195 
196  if (rConflicts) {
197  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
198  rpmps ps = rpmtsProblems(ts);
199  int xx;
200  he->tag = RPMTAG_NVRA;
201  xx = headerGet(otherHeader, he, 0);
203  rpmteNEVRA(p), rpmteKey(p),
204  rpmfiDN(fi), rpmfiBN(fi),
205  he->p.str,
206  0);
207  he->p.ptr = _free(he->p.ptr);
208  ps = rpmpsFree(ps);
209  }
210 
211  /* Save file identifier to mark as state REPLACED. */
212 #ifdef REFERENCE
213  if ( !(isCfgFile || XFA_SKIPPING(rpmfsGetAction(fs, fx))) ) {
214  if (!beingRemoved)
215  rpmfsAddReplaced(rpmteGetFileStates(p), rpmfiFX(fi),
216  headerGetInstance(otherHeader),
217  rpmfiFX(otherFi));
218  }
219 #else
220  if ( !(isCfgFile || iosmFileActionSkipped((iosmFileAction) fi->actions[fx])) ) {
221  if (!beingRemoved) {
222  struct sharedFileInfo_s _shared;
223 
224  p->replaced = (sharedFileInfo) xrealloc(p->replaced,
225  sizeof(*p->replaced) * (p->nreplaced + 1));
226  memset(p->replaced + p->nreplaced, 0, sizeof(*p->replaced));
227 
228  _shared.pkgFileNum = fx;
229  _shared.otherFileNum = rpmfiFX(otherFi);
230  _shared.otherPkg = headerGetInstance(otherHeader);
231  _shared.isRemoved = 0;
232  p->replaced[p->nreplaced++] = _shared;
233  }
234  }
235 #endif
236  }
237 
238  /* Determine config file disposition, skipping missing files (if any). */
239  if (isCfgFile) {
240  rpmtransFlags tsflags = rpmtsFlags(ts);
241  int skipMissing = (TSF_ISSET(tsflags, ALLFILES) ? 0 : 1);
242 #ifdef REFERENCE
243  rpmFileAction action = rpmfiDecideFate(otherFi, fi, skipMissing);
244  rpmfsSetAction(fs, fx, action);
245 #else
246  fi->actions[fx] = rpmfiDecideFate(otherFi, fi, skipMissing);
247 #endif
248  }
249 #ifdef REFERENCE
250  rpmfiSetFReplacedSize(fi, rpmfiFSize(otherFi));
251 #else
252  fi->replacedSizes[fx] = rpmfiFSize(otherFi);
253 #endif
254 
255  return 0;
256 }
257 
258 #define ISROOT(_d) (((_d)[0] == '/' && (_d)[1] == '\0') ? "" : (_d))
259 
260 /*@unchecked@*/
261 int _fps_debug = 0;
262 #define FPSDEBUG(_debug, _list) if ((_debug) || _fps_debug) fprintf _list
263 
267 /* XXX only ts->{probs,di} modified */
268 static void handleOverlappedFiles(const rpmts ts, const rpmte p, rpmfi fi)
269  /*@globals h_errno, fileSystem, internalState @*/
270  /*@modifies ts, fi, fileSystem, internalState @*/
271 {
272  uint32_t fixupSize = 0;
273  rpmps ps;
274  const char * fn;
275  int i, j;
276 
277  uint32_t tscolor = rpmtsColor(ts);
278  uint32_t prefcolor = rpmtsPrefColor(ts);
279 #ifdef REFERENCE
280  rpmfs fs = rpmteGetFileStates(p);
281  rpmfs otherFs;
282 #endif /* REFERENCE */
283 
284 FPSDEBUG(0, (stderr, "--> %s(%p,%p,%p)\n", __FUNCTION__, ts, p, fi));
285  ps = rpmtsProblems(ts);
286  fi = rpmfiInit(fi, 0);
287  if (fi != NULL)
288  while ((i = rpmfiNext(fi)) >= 0) {
289  uint32_t oFColor;
290  uint32_t FColor;
291  struct fingerPrint_s * fiFps;
292  int otherPkgNum, otherFileNum;
293  rpmfi otherFi;
294 
295  rpmte otherTe;
296 #ifdef REFERENCE
297  rpmfileAttrs FFlags;
298  rpm_mode_t FMode;
299 #else /* REFERENCE */
300  rpmuint32_t FFlags;
301  rpmuint16_t FMode;
302 #endif /* REFERENCE */
303  struct rpmffi_s ** recs;
304  int numRecs;
305 
306  if (iosmFileActionSkipped((iosmFileAction) fi->actions[i]))
307  continue;
308 
309  fn = rpmfiFN(fi);
310 #ifdef REFERENCE
311  fiFps = rpmfiFpsIndex(fi, i);
312 #else /* REFERENCE */
313  fiFps = fi->fps + i;
314 #endif /* REFERENCE */
315  FFlags = rpmfiFFlags(fi);
316  FMode = rpmfiFMode(fi);
317  FColor = rpmfiFColor(fi);
318  FColor &= tscolor;
319 
320  fixupSize = 0;
321 
322  /*
323  * Retrieve all records that apply to this file. Note that the
324  * file info records were built in the same order as the packages
325  * will be installed and removed so the records for an overlapped
326  * files will be sorted in exactly the same order.
327  */
328  recs = NULL;
329  numRecs = 0;
330 #ifdef REFERENCE
331  (void) rpmFpHashGetEntry(ht, fiFps, &recs, &numRecs, NULL);
332 #else /* REFERENCE */
333  (void) htGetEntry(ts->ht, fiFps, &recs, &numRecs, NULL);
334 #endif /* REFERENCE */
335 
336  /*
337  * If this package is being added, look only at other packages
338  * being added -- removed packages dance to a different tune.
339  *
340  * If both this and the other package are being added, overlapped
341  * files must be identical (or marked as a conflict). The
342  * disposition of already installed config files leads to
343  * a small amount of extra complexity.
344  *
345  * If this package is being removed, then there are two cases that
346  * need to be worried about:
347  * If the other package is being added, then skip any overlapped files
348  * so that this package removal doesn't nuke the overlapped files
349  * that were just installed.
350  * If both this and the other package are being removed, then each
351  * file removal from preceding packages needs to be skipped so that
352  * the file removal occurs only on the last occurrence of an overlapped
353  * file in the transaction set.
354  */
355 
356  /* Locate this overlapped file in the set of added/removed packages. */
357  for (j = 0; j < numRecs && recs[j]->p != p; j++) {
358 FPSDEBUG(0, (stderr, "\trecs %p[%u:%u] te %p != %p\n", recs, (unsigned)j, (unsigned)numRecs, recs[j]->p, p));
359  }
360 FPSDEBUG(0, (stderr, "*** got recs %p[%u:%u]\n", recs, (unsigned)j, (unsigned)numRecs));
361 
362  /* Find what the previous disposition of this file was. */
363  otherFileNum = -1; /* keep gcc quiet */
364  otherFi = NULL;
365  otherTe = NULL;
366 #ifdef REFERENCE
367  otherFs = NULL;
368 #endif /* REFERENCE */
369 
370  for (otherPkgNum = j - 1; otherPkgNum >= 0; otherPkgNum--) {
371 FPSDEBUG(0, (stderr, "\trecs %p[%u:%u] %p -> {%p,%d}\n", recs, (unsigned)otherPkgNum, (unsigned)numRecs, recs[otherPkgNum], recs[otherPkgNum]->p, recs[otherPkgNum]->fileno));
372  otherTe = recs[otherPkgNum]->p;
373  otherFi = rpmteFI(otherTe, RPMTAG_BASENAMES);
374  otherFileNum = recs[otherPkgNum]->fileno;
375 #ifdef REFERENCE
376  otherFs = rpmteGetFileStates(otherTe);
377 #endif /* REFERENCE */
378 
379  /* Added packages need only look at other added packages. */
380  if (rpmteType(p) == TR_ADDED && rpmteType(otherTe) != TR_ADDED)
381  /*@innercontinue@*/ continue;
382 
383  (void) rpmfiSetFX(otherFi, otherFileNum);
384 
385  /* XXX Happens iff fingerprint for incomplete package install. */
386  if (otherFi->actions[otherFileNum] != FA_UNKNOWN)
387  /*@innerbreak@*/ break;
388  }
389 
390  oFColor = rpmfiFColor(otherFi);
391  oFColor &= tscolor;
392 
393  switch (rpmteType(p)) {
394  case TR_ADDED:
395  { int reportConflicts =
397  int done = 0;
398 
399  if (otherPkgNum < 0) {
400  iosmFileAction action;
401  /* XXX is this test still necessary? */
402  if (fi->actions[i] != FA_UNKNOWN)
403  /*@switchbreak@*/ break;
404 #ifdef REFERENCE
405  if (rpmfiConfigConflict(fi))
406 #else
407  if (FF_ISSET(FFlags, CONFIG) && FF_ISSET(FFlags, EXISTS))
408 #endif
409  {
410  /* Here is a non-overlapped pre-existing config file. */
411  action = FF_ISSET(FFlags, NOREPLACE)
412  ? FA_ALTNAME : FA_BACKUP;
413  } else {
414  action = FA_CREATE;
415  }
416 #ifdef REFERENCE
417  rpmfsSetAction(fs, i, action);
418 #else
419  fi->actions[i] = action;
420 #endif
421  /*@switchbreak@*/ break;
422  }
423 
424 assert(otherFi != NULL);
425  /* Mark added overlapped non-identical files as a conflict. */
426  if (rpmfiCompare(otherFi, fi)) {
427  int rConflicts;
428 
429  rConflicts = reportConflicts;
430  /* Resolve file conflicts to prefer Elf64 (if not forced) ... */
431  if (tscolor != 0) {
432  if (FColor & prefcolor) {
433  /* ... last file of preferred colour is installed ... */
434  if (!iosmFileActionSkipped((iosmFileAction) fi->actions[i])) {
435 #ifdef DEAD
436  /* XXX static helpers are order dependent. Ick. */
437  if (strcmp(fn, "/usr/sbin/libgcc_post_upgrade")
438  && strcmp(fn, "/usr/sbin/glibc_post_upgrade"))
439 #endif
440  otherFi->actions[otherFileNum] = FA_SKIPCOLOR;
441  }
442  fi->actions[i] = FA_CREATE;
443  rConflicts = 0;
444  } else
445  if (oFColor & prefcolor) {
446  /* ... first file of preferred colour is installed ... */
447  if (iosmFileActionSkipped((iosmFileAction) fi->actions[i]))
448  otherFi->actions[otherFileNum] = FA_CREATE;
449  fi->actions[i] = FA_SKIPCOLOR;
450  rConflicts = 0;
451  } else
452  if (FColor == 0 && oFColor == 0) {
453  /* ... otherwise, do both, last in wins. */
454  otherFi->actions[otherFileNum] = FA_CREATE;
455  fi->actions[i] = FA_CREATE;
456  rConflicts = 0;
457  }
458  done = 1;
459  }
460 
461 #if defined(RPM_VENDOR_MANDRIVA)
462  if(rpmExpandNumeric("%{?_legacy_compat_no_doc_conflicts}")) {
463  /* HACK: always install latest (arch-independent) man
464  pages and gtk/gnome html doc files. */
465  if (rConflicts && is_a_doc_conflict(fi)) {
466  fi->actions[i] = FA_CREATE;
467  rConflicts = 0;
468  }
469  }
470 #endif
471 
472  if (rConflicts) {
474  rpmteNEVR(p), rpmteKey(p),
475  fn, NULL,
476  rpmteNEVR((rpmte) otherFi->te),
477  0);
478  }
479  }
480 
481  /* Try to get the disk accounting correct even if a conflict. */
482  fixupSize = rpmfiFSize(otherFi);
483 
484 #ifdef REFERENCE
485  if (rpmfiConfigConflict(fi))
486 #else /* REFERENCE */
487  if (FF_ISSET(FFlags, CONFIG) && FF_ISSET(FFlags, EXISTS))
488 #endif /* REFERENCE */
489  {
490  /* Here is an overlapped pre-existing config file. */
491  fi->actions[i] = FF_ISSET(FFlags, NOREPLACE)
492  ? FA_ALTNAME : FA_SKIP;
493  } else {
494  if (!done)
495  fi->actions[i] = FA_CREATE;
496  }
497  } /*@switchbreak@*/ break;
498 
499  case TR_REMOVED:
500  if (otherPkgNum >= 0) {
501 assert(otherFi != NULL);
502  /* Here is an overlapped added file we don't want to nuke. */
503  if (otherFi->actions[otherFileNum] != FA_ERASE) {
504  /* On updates, don't remove files. */
505  fi->actions[i] = FA_SKIP;
506  /*@switchbreak@*/ break;
507  }
508  /* Here is an overlapped removed file: skip in previous. */
509  otherFi->actions[otherFileNum] = FA_SKIP;
510  }
511  if (iosmFileActionSkipped((iosmFileAction) fi->actions[i]))
512  /*@switchbreak@*/ break;
514  /*@switchbreak@*/ break;
515 
516  /* Disposition is assumed to be FA_ERASE. */
517  fi->actions[i] = FA_ERASE;
518  if (!(S_ISREG(FMode) && FF_ISSET(FFlags, CONFIG)))
519  /*@switchbreak@*/ break;
520 
521  /* Check for pre-existing modified config file that needs saving. */
522  if (!FF_ISSET(FFlags,SPARSE))
523  { int dalgo = 0;
524  size_t dlen = 0;
525  const unsigned char * digest = rpmfiDigest(fi, &dalgo, &dlen);
526  unsigned char * fdigest;
527 assert(digest != NULL);
528 
529  fdigest = (unsigned char *) xcalloc(1, dlen);
530  /* Save (by renaming) locally modified config files. */
531  if (!dodigest(dalgo, fn, fdigest, 0, NULL)
532  && memcmp(digest, fdigest, dlen))
533  fi->actions[i] = FA_BACKUP;
534  fdigest = _free(fdigest);
535  }
536  /*@switchbreak@*/ break;
537  }
538 
539  /* Update disk space info for a file. */
540 #ifdef REFERENCE
541  rpmtsUpdateDSI(ts, fiFps->entry->dev, rpmfiFSize(fi),
542  rpmfiFReplacedSize(fi), fixupSize, rpmfsGetAction(fs, i));
543 #else
544  rpmtsUpdateDSI(ts, fiFps->entry->dev, rpmfiFSize(fi),
545  fi->replacedSizes[i], fixupSize, fi->actions[i]);
546 #endif
547 
548  }
549  ps = rpmpsFree(ps);
550 }
551 
559 /*@-nullpass@*/
560 static int ensureOlder(rpmts ts,
561  const rpmte p, const Header h)
562  /*@globals internalState @*/
563  /*@modifies ts, internalState @*/
564 {
565  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
567  const char * reqEVR;
568  rpmds req;
569  char * t;
570  size_t nb;
571  int rc;
572 
573 FPSDEBUG(0, (stderr, "--> %s(%p,%p,%p)\n", __FUNCTION__, ts, p, h));
574  if (p == NULL || h == NULL)
575  return 1;
576 
577  nb = strlen(rpmteNEVR(p)) + (rpmteE(p) != NULL ? strlen(rpmteE(p)) : 0) + 1;
578 #ifdef RPM_VENDOR_MANDRIVA
579  nb += (rpmteD(p) != NULL ? strlen(rpmteD(p)) + 1 : 0);
580 #endif
581  t = (char *) alloca(nb);
582  *t = '\0';
583  reqEVR = t;
584  if (rpmteE(p) != NULL) t = stpcpy( stpcpy(t, rpmteE(p)), ":");
585  if (rpmteV(p) != NULL) t = stpcpy(t, rpmteV(p));
586  *t++ = '-';
587  if (rpmteR(p) != NULL) t = stpcpy(t, rpmteR(p));
588 #ifdef RPM_VENDOR_MANDRIVA
589  if (rpmteD(p) != NULL) *t++ = ':', t = stpcpy(t, rpmteD(p));
590 #endif
591 
592  req = rpmdsSingle(RPMTAG_REQUIRENAME, rpmteN(p), reqEVR, reqFlags);
593  rc = rpmdsNVRMatchesDep(h, req, _rpmds_nopromote);
594  (void)rpmdsFree(req);
595  req = NULL;
596 
597  if (rc == 0) {
598  rpmps ps = rpmtsProblems(ts);
599  he->tag = RPMTAG_NVRA;
600  rc = headerGet(h, he, 0);
601 assert(he->p.str != NULL);
603  rpmteNEVR(p), rpmteKey(p),
604  NULL, NULL,
605  he->p.str,
606  0);
607  he->p.ptr = _free(he->p.ptr);
608  ps = rpmpsFree(ps);
609  rc = 1;
610  } else
611  rc = 0;
612 
613  return rc;
614 }
615 /*@=nullpass@*/
616 
622 /*@-mustmod@*/ /* FIX: fi->actions is modified. */
623 /*@-nullpass@*/
624 static void rpmtsSkipFiles(const rpmts ts, rpmfi fi)
625  /*@globals rpmGlobalMacroContext, h_errno, internalState @*/
626  /*@modifies fi, rpmGlobalMacroContext, internalState @*/
627 {
628  rpmuint32_t tscolor = rpmtsColor(ts);
629  rpmuint32_t FColor;
630  rpmtransFlags tsflags = rpmtsFlags(ts);
631  int noConfigs = TSF_ISSET(tsflags, NOCONFIGS);
632  int noDocs = TSF_ISSET(tsflags, NODOCS);
633  ARGV_t netsharedPaths = NULL;
634  ARGV_t languages = NULL;
635  const char * dn, * bn;
636  size_t dnlen, bnlen;
637  int ix;
638  const char * s;
639  int * drc;
640  char * dff;
641  int dc;
642  int i, j;
643  int xx;
644 
645 FPSDEBUG(0, (stderr, "--> %s(%p,%p)\n", __FUNCTION__, ts, fi));
646 #if defined(RPM_VENDOR_OPENPKG) /* allow-excludedocs-default */
647  /* The "%_excludedocs" macro is intended to set the _default_ if
648  both --excludedocs and --includedocs are not specified and it
649  is evaluated already before. So, do not override it here again,
650  because it would not allow us to make "%_excludedocs 1" the
651  default. */
652 #else
653  if (!noDocs)
654  noDocs = rpmExpandNumeric("%{_excludedocs}");
655 #endif
656 
657  { const char *tmpPath = rpmExpand("%{?_netsharedpath}", NULL);
658  if (tmpPath && *tmpPath)
659  xx = argvSplit(&netsharedPaths, tmpPath, ":");
660  tmpPath = _free(tmpPath);
661  }
662 
663  s = rpmExpand("%{?_install_langs}", NULL);
664  if (!(s && *s))
665  s = _free(s);
666  if (s) {
667  xx = argvSplit(&languages, s, ":");
668  s = _free(s);
669  }
670 
671  /* Compute directory refcount, skip directory if now empty. */
672  dc = rpmfiDC(fi);
673  drc = (int *) alloca(dc * sizeof(*drc));
674  memset(drc, 0, dc * sizeof(*drc));
675  dff = (char *) alloca(dc * sizeof(*dff));
676  memset(dff, 0, dc * sizeof(*dff));
677 
678  fi = rpmfiInit(fi, 0);
679  if (fi != NULL) /* XXX lclint */
680  while ((i = rpmfiNext(fi)) >= 0)
681  {
682  ARGV_t nsp;
683 
684  bn = rpmfiBN(fi);
685  bnlen = strlen(bn);
686  ix = rpmfiDX(fi);
687  dn = rpmfiDN(fi);
688  if (dn == NULL)
689  continue; /* XXX can't happen */
690  dnlen = strlen(dn);
691 
692  drc[ix]++;
693 
694  /* Don't bother with skipped files */
695  if (iosmFileActionSkipped((iosmFileAction) fi->actions[i])) {
696  drc[ix]--; dff[ix] = 1;
697  continue;
698  }
699 
700  /* Ignore colored files not in our rainbow. */
701  FColor = rpmfiFColor(fi);
702  if (tscolor && FColor && !(tscolor & FColor)) {
703  drc[ix]--; dff[ix] = 1;
704  fi->actions[i] = FA_SKIPCOLOR;
705  continue;
706  }
707 
708  /*
709  * Skip net shared paths.
710  * Net shared paths are not relative to the current root (though
711  * they do need to take package relocations into account).
712  */
713  for (nsp = netsharedPaths; nsp && *nsp; nsp++) {
714  size_t len;
715 
716  len = strlen(*nsp);
717  if (dnlen >= len) {
718  if (strncmp(dn, *nsp, len))
719  /*@innercontinue@*/ continue;
720  /* Only directories or complete file paths can be net shared */
721  if (!(dn[len] == '/' || dn[len] == '\0'))
722  /*@innercontinue@*/ continue;
723  } else {
724  if (len < (dnlen + bnlen))
725  /*@innercontinue@*/ continue;
726  if (strncmp(dn, *nsp, dnlen))
727  /*@innercontinue@*/ continue;
728  /* Insure that only the netsharedpath basename is compared. */
729  if ((s = strchr((*nsp) + dnlen, '/')) != NULL && s[1] != '\0')
730  /*@innercontinue@*/ continue;
731  if (strncmp(bn, (*nsp) + dnlen, bnlen))
732  /*@innercontinue@*/ continue;
733  len = dnlen + bnlen;
734  /* Only directories or complete file paths can be net shared */
735  if (!((*nsp)[len] == '/' || (*nsp)[len] == '\0'))
736  /*@innercontinue@*/ continue;
737  }
738 
739  /*@innerbreak@*/ break;
740  }
741 
742  if (nsp && *nsp) {
743  drc[ix]--; dff[ix] = 1;
744  fi->actions[i] = FA_SKIPNETSHARED;
745  continue;
746  }
747 
748  /*
749  * Skip i18n language specific files.
750  */
751  if (languages != NULL && fi->flangs != NULL && *fi->flangs[i]) {
752  ARGV_t lang;
753  const char *l, *le;
754  for (lang = languages; *lang != NULL; lang++) {
755  if (!strcmp(*lang, "all"))
756  /*@innerbreak@*/ break;
757  for (l = fi->flangs[i]; *l != '\0'; l = le) {
758  for (le = l; *le != '\0' && *le != '|'; le++)
759  {};
760  if ((le-l) > 0 && !strncmp(*lang, l, (le-l)))
761  /*@innerbreak@*/ break;
762  if (*le == '|') le++; /* skip over | */
763  }
764  if (*l != '\0')
765  /*@innerbreak@*/ break;
766  }
767  if (*lang == NULL) {
768  drc[ix]--; dff[ix] = 1;
769  fi->actions[i] = FA_SKIPNSTATE;
770  continue;
771  }
772  }
773 
774  /*
775  * Skip config files if requested.
776  */
777  if (noConfigs && FF_ISSET(rpmfiFFlags(fi), CONFIG)) {
778  drc[ix]--; dff[ix] = 1;
779  fi->actions[i] = FA_SKIPNSTATE;
780  continue;
781  }
782 
783  /*
784  * Skip documentation if requested.
785  */
786  if (noDocs && FF_ISSET(rpmfiFFlags(fi), DOC)) {
787  drc[ix]--; dff[ix] = 1;
788  fi->actions[i] = FA_SKIPNSTATE;
789  continue;
790  }
791  }
792 
793  /* Skip (now empty) directories that had skipped files. */
794 #ifndef NOTYET
795  if (fi != NULL) /* XXX can't happen */
796  for (j = 0; j < dc; j++)
797 #else
798  if ((fi = rpmfiInitD(fi)) != NULL)
799  while (j = rpmfiNextD(fi) >= 0)
800 #endif
801  {
802 
803  if (drc[j]) continue; /* dir still has files. */
804  if (!dff[j]) continue; /* dir was not emptied here. */
805 
806  /* Find parent directory and basename. */
807  dn = fi->dnl[j]; dnlen = strlen(dn) - 1;
808  bn = dn + dnlen; bnlen = 0;
809  while (bn > dn && bn[-1] != '/') {
810  bnlen++;
811  dnlen--;
812  bn--;
813  }
814 
815  /* If explicitly included in the package, skip the directory. */
816  fi = rpmfiInit(fi, 0);
817  if (fi != NULL) /* XXX lclint */
818  while ((i = rpmfiNext(fi)) >= 0) {
819  const char * fdn, * fbn;
820  rpmuint16_t fFMode;
821 
822  if (iosmFileActionSkipped((iosmFileAction) fi->actions[i]))
823  /*@innercontinue@*/ continue;
824 
825  fFMode = rpmfiFMode(fi);
826 
827  if (!S_ISDIR(fFMode))
828  /*@innercontinue@*/ continue;
829  fdn = rpmfiDN(fi);
830  if (strlen(fdn) != dnlen)
831  /*@innercontinue@*/ continue;
832  if (strncmp(fdn, dn, dnlen))
833  /*@innercontinue@*/ continue;
834  fbn = rpmfiBN(fi);
835  if (strlen(fbn) != bnlen)
836  /*@innercontinue@*/ continue;
837  if (strncmp(fbn, bn, bnlen))
838  /*@innercontinue@*/ continue;
839  rpmlog(RPMLOG_DEBUG, D_("excluding directory %s\n"), dn);
840  fi->actions[i] = FA_SKIPNSTATE;
841  /*@innerbreak@*/ break;
842  }
843  }
844 
845 /*@-dependenttrans@*/
846  netsharedPaths = argvFree(netsharedPaths);
847  languages = argvFree(languages);
848 /*@=dependenttrans@*/
849 }
850 /*@=nullpass@*/
851 /*@=mustmod@*/
852 
859 static /*@null@*/
861  /*@*/
862 {
863  rpmfi fi = NULL;
864 
865  if (tsi != NULL && tsi->ocsave != -1) {
866  /*@-type -abstract@*/ /* FIX: rpmte not opaque */
867  rpmte te = rpmtsElement(tsi->ts, tsi->ocsave);
868  /*@-assignexpose@*/
869  if (te != NULL && (fi = te->fi) != NULL)
870  fi->te = te;
871  /*@=assignexpose@*/
872  /*@=type =abstract@*/
873  }
874  /*@-compdef -refcounttrans -usereleased @*/
875  return fi;
876  /*@=compdef =refcounttrans =usereleased @*/
877 }
878 
885 static int cmpArgvStr(/*@null@*/ const char ** AV, /*@null@*/ const char * B)
886  /*@*/
887 {
888  const char ** a;
889 
890  if (AV != NULL && B != NULL)
891  for (a = AV; *a != NULL; a++) {
892  if (**a && *B && !strcmp(*a, B))
893  return 1;
894  }
895  return 0;
896 }
897 
905  /*@globals fileSystem @*/
906  /*@modifies ts, p, fileSystem @*/
907 {
908  rpmtsi qi; rpmte q;
909  int bingo;
910 
911  p->linkFailed = 1;
912 
913  qi = rpmtsiInit(ts);
914  while ((q = rpmtsiNext(qi, TR_REMOVED)) != NULL) {
915 
916  if (q->done)
917  continue;
918 
919  /*
920  * Either element may have missing data and can have multiple entries.
921  * Try for hdrid, then pkgid, finally NEVRA, argv vs. argv compares.
922  */
923  bingo = cmpArgvStr(q->flink.Hdrid, p->hdrid);
924  if (!bingo)
925  bingo = cmpArgvStr(q->flink.Pkgid, p->pkgid);
926  if (!bingo)
927  bingo = cmpArgvStr(q->flink.NEVRA, p->NEVRA);
928 
929  if (!bingo)
930  continue;
931 
932  q->linkFailed = p->linkFailed;
933  }
934  qi = rpmtsiFree(qi);
935 
936  return 0;
937 }
938 
939 /* ================================================================= */
940 
941 /* Get a rpmdbMatchIterator containing all files in
942  * the rpmdb that share the basename with one from
943  * the transaction.
944  * @param ts transaction set
945  * @param fileCount no. of files
946  * @return rpmmi sorted by (package, fileNum)
947  */
948 static
949 rpmmi rpmtsFindBaseNamesInDB(rpmts ts, uint32_t fileCount)
950  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
951  /*@modifies ts, rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
952 {
953  rpmtsi pi; rpmte p;
954  rpmfi fi;
955  rpmmi mi;
956  int i, xx;
957  const char * s;
958  size_t ns;
959  void * ptr;
960  static rpmTag _tag = RPMTAG_BASENAMES;
961  size_t n = (fileCount > 10 ? fileCount : 10);
962  static double e = 1.0e-4;
963  size_t m = 0;
964  size_t k = 0;
965  rpmbf bf;
966 
967 FPSDEBUG(0, (stderr, "--> %s(%p,%u)\n", __FUNCTION__, ts, (unsigned)fileCount));
968  rpmbfParams(n, e, &m, &k);
969  bf = rpmbfNew(m, k, 0);
970 
971  mi = rpmmiInit(rpmtsGetRdb(ts), _tag, NULL, 0);
972 
973  pi = rpmtsiInit(ts);
974  while ((p = rpmtsiNext(pi, (rpmElementType) 0)) != NULL) {
975 
976  (void) rpmdbCheckSignals();
977 
978  if ((fi = rpmteFI(p, _tag)) == NULL)
979  continue; /* XXX can't happen */
980 
981  ptr = rpmtsNotify(ts, NULL, RPMCALLBACK_TRANS_PROGRESS, rpmtsiOc(pi),
982  ts->orderCount);
983 
984  /* Gather all installed headers with matching basename's. */
985  fi = rpmfiInit(fi, 0);
986  while ((i = rpmfiNext(fi)) >= 0) {
987  s = rpmfiBN(fi);
988  ns = strlen(s);
989 
990  if (ns == 0) /* XXX "/" fixup */
991  /*@innercontinue@*/ continue;
992  if (rpmbfChk(bf, s, ns))
993  /*@innercontinue@*/ continue;
994 
995  xx = rpmmiGrowBasename(mi, s);
996 
997  xx = rpmbfAdd(bf, s, ns);
998  }
999  }
1000  pi = rpmtsiFree(pi);
1001  bf = rpmbfFree(bf);
1002 
1003  (void) rpmmiSort(mi);
1004 
1005  return mi;
1006 }
1007 
1008 /* Check files in the transactions against the rpmdb
1009  * Lookup all files with the same basename in the rpmdb
1010  * and then check for matching finger prints
1011  * @param ts transaction set
1012  * @param fpc global finger print cache
1013  */
1014 static
1015 int rpmtsCheckInstalledFiles(rpmts ts, uint32_t fileCount,
1016  hashTable ht, fingerPrintCache fpc)
1017  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
1018  /*@modifies ts, fpc, rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
1019 {
1020  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
1021  rpmTagData BN = { NULL };
1022  rpmTagData DN = { NULL };
1023  rpmTagData DI = { NULL };
1024  rpmTagData FSTATES = { NULL };
1025  rpmuint32_t fc;
1026 
1027  rpmte p;
1028  rpmmi mi;
1029  Header h;
1030  rpmfi fi;
1031 
1032  const char * oldDir;
1033  int beingRemoved;
1034  rpmfi otherFi = NULL;
1035  unsigned int fileNum;
1036  int xx;
1037  int rc = 0;
1038 
1039 FPSDEBUG(0, (stderr, "--> %s(%p,%u,%p,%p)\n", __FUNCTION__, ts, (unsigned)fileCount, ht, fpc));
1040 
1041 rpmlog(RPMLOG_DEBUG, D_("computing file dispositions\n"));
1042 
1043  /* XXX fileCount == 0 installing src.rpm's */
1044  if (fileCount == 0)
1045  return rc;
1046 
1047  mi = rpmtsFindBaseNamesInDB(ts, fileCount);
1048 
1049  /* Loop over all packages from the rpmdb */
1050  while ((h = rpmmiNext(mi)) != NULL) {
1051  fingerPrint fp;
1052  uint32_t hdrNum = rpmmiInstance(mi);
1053  uint32_t tagNum = rpmmiBNTag(mi);
1054  int i;
1055  int j;
1056 
1057  /* Is this package being removed? */
1058  beingRemoved = 0;
1059  if (ts->removedPackages != NULL)
1060  for (j = 0; j < ts->numRemovedPackages; j++) {
1061  if (ts->removedPackages[j] != hdrNum)
1062  /*@innercontinue@*/ continue;
1063  beingRemoved = 1;
1064  /*@innerbreak@*/ break;
1065  }
1066 
1067  he->tag = RPMTAG_BASENAMES;
1068  xx = headerGet(h, he, 0);
1069  BN.argv = (xx ? he->p.argv : NULL);
1070  fc = (xx ? he->c : 0);
1071 
1072  he->tag = RPMTAG_DIRNAMES;
1073  xx = headerGet(h, he, 0);
1074  DN.argv = (xx ? he->p.argv : NULL);
1075  he->tag = RPMTAG_DIRINDEXES;
1076  xx = headerGet(h, he, 0);
1077  DI.ui32p = (xx ? he->p.ui32p : NULL);
1078  he->tag = RPMTAG_FILESTATES;
1079  xx = headerGet(h, he, 0);
1080  FSTATES.ui8p = (xx ? he->p.ui8p : NULL);
1081 
1082  /* loop over all interesting files in that package */
1083  oldDir = NULL;
1084  for (i = 0; i < (int)fc; i++) {
1085  const char * baseName = BN.argv[i];
1086  rpmuint32_t baseKey = hashFunctionString(0, baseName, 0);
1087  int gotRecs;
1088  struct rpmffi_s ** recs;
1089  int numRecs;
1090  const char * dirName;
1091 
1092  /* Skip uninteresting basenames. */
1093  if (baseKey != tagNum)
1094  /*@innercontinue@*/ continue;
1095  fileNum = i;
1096  dirName = DN.argv[DI.ui32p[fileNum]];
1097 
1098  /* lookup finger print for this file */
1099  if (dirName == oldDir) {
1100  /* directory is the same as last round */
1101  fp.baseName = baseName;
1102  } else {
1103  fp = fpLookup(fpc, dirName, baseName, 1);
1104  oldDir = dirName;
1105  }
1106 
1107  /* search for files in the transaction with same finger print */
1108  recs = NULL;
1109  numRecs = 0;
1110 #ifdef REFERENCE
1111  gotRecs = rpmFpHashGetEntry(ht, &fp, &recs, &numRecs, NULL);
1112 #else /* REFERENCE */
1113  gotRecs = (htGetEntry(ts->ht, &fp, &recs, &numRecs, NULL) == 0);
1114 #endif /* REFERENCE */
1115 
1116  for (j = 0; j < numRecs && gotRecs; j++) {
1117  p = recs[j]->p;
1118  fi = rpmteFI(p, RPMTAG_BASENAMES);
1119 
1120  /* Determine the fate of each file. */
1121  switch (rpmteType(p)) {
1122  case TR_ADDED:
1123  if (otherFi == NULL) {
1124  static int scareMem = 0;
1125  otherFi = rpmfiNew(ts, h, RPMTAG_BASENAMES, scareMem);
1126  }
1127  (void) rpmfiSetFX(fi, recs[j]->fileno);
1128  (void) rpmfiSetFX(otherFi, fileNum);
1129  xx = handleInstInstalledFile(ts, p, fi, h, otherFi, beingRemoved);
1130  /*@switchbreak@*/ break;
1131  case TR_REMOVED:
1132  if (!beingRemoved) {
1133  (void) rpmfiSetFX(fi, recs[j]->fileno);
1134 #ifdef REFERENCE
1135  if (*rpmtdGetChar(&ostates) == RPMFILE_STATE_NORMAL) {
1136  rpmfs fs = rpmteGetFileStates(p);
1137  rpmfsSetAction(fs, recs[j].fileno, FA_SKIP);
1138  }
1139 #else
1140  if (FSTATES.ui8p[fileNum] == RPMFILE_STATE_NORMAL)
1141  fi->actions[recs[j]->fileno] = FA_SKIP;
1142 #endif
1143  }
1144  /*@switchbreak@*/ break;
1145  }
1146  }
1147 
1148  }
1149 
1150  otherFi = rpmfiFree(otherFi);
1151  FSTATES.ptr = _free(FSTATES.ptr);
1152  DI.ptr = _free(DI.ptr);
1153  DN.ptr = _free(DN.ptr);
1154  BN.ptr = _free(BN.ptr);
1155  }
1156 
1157  mi = rpmmiFree(mi);
1158 
1159  return rc;
1160 }
1161 
1162 /*
1163  * For packages being installed:
1164  * - verify package arch/os.
1165  * - verify package epoch:version-release is newer.
1166  */
1167 static rpmps rpmtsSanityCheck(rpmts ts, uint32_t * tfcp)
1168  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
1169  /*@modifies ts, *tfcp, rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
1170 {
1171  rpmps ps;
1172  rpmtsi pi;
1173  rpmte p;
1174  rpmfi fi;
1175  uint32_t totalFileCount = 0;
1176  int fc;
1177 
1178 FPSDEBUG(0, (stderr, "--> %s(%p,%p)\n", __FUNCTION__, ts, tfcp));
1179 rpmlog(RPMLOG_DEBUG, D_("sanity checking %d elements\n"), rpmtsNElements(ts));
1180  ps = rpmtsProblems(ts);
1181  /* The ordering doesn't matter here */
1182  pi = rpmtsiInit(ts);
1183  /* XXX Only added packages need be checked. */
1184  while ((p = rpmtsiNext(pi, TR_ADDED)) != NULL) {
1185  int xx;
1186 
1187  if (p->isSource) continue;
1188  if ((fi = rpmtsiFi(pi)) == NULL)
1189  continue; /* XXX can't happen */
1190  fc = rpmfiFC(fi);
1191 
1192 #ifdef REFERENCE
1194  if (!archOkay(rpmteA(p)))
1196  rpmteNEVRA(p), rpmteKey(p),
1197  rpmteA(p), NULL,
1198  NULL, 0);
1199 
1201  if (!osOkay(rpmteO(p)))
1203  rpmteNEVRA(p), rpmteKey(p),
1204  rpmteO(p), NULL,
1205  NULL, 0);
1206 #endif /* REFERENCE */
1207 
1209  rpmmi mi = rpmtsInitIterator(ts, RPMTAG_NAME, rpmteN(p), 0);
1210  Header h;
1211  while ((h = rpmmiNext(mi)) != NULL)
1212  xx = ensureOlder(ts, p, h);
1213  mi = rpmmiFree(mi);
1214  }
1215 
1217  ARGV_t keys = NULL;
1218  int nkeys;
1220  RPMMIRE_STRCMP, rpmteNEVRA(p), &keys);
1221  nkeys = argvCount(keys);
1222 
1223  /* mdvbz: #63711
1224  * workaround for epoch & distepoch not being part of RPMTAG_NVRA,
1225  * leading to packages of same VRA but with different epoch or distepoch
1226  * being treated as the same package */
1227  if (nkeys > 0) {
1228  int i, t;
1229  rpmTag tags[2] = { RPMTAG_EPOCH, RPMTAG_DISTEPOCH };
1230  for (t = 0; t < 2; t++) {
1231  for (i = 0; i < nkeys; i++) {
1232  rpmmi mi = rpmtsInitIterator(ts, RPMTAG_NVRA, keys[i], 0);
1233  Header h;
1234  while ((h = rpmmiNext(mi)) != NULL) {
1235  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
1236  const char *val = NULL;
1237  he->tag = tags[t];
1238  xx = headerGet(h, he, 0);
1239  if (he->tag == RPMTAG_EPOCH) {
1240  val = rpmteE(p);
1241  if (val ? atoi(val) : 0 != he->p.ui32p ? *(he->p.ui32p) : 0)
1242  nkeys--;
1243  } else if (he->tag == RPMTAG_DISTEPOCH) {
1244  val = rpmteD(p);
1245  if (strcmp(he->p.str ? he->p.str : "", val ? val : ""))
1246  nkeys--;
1247  }
1248  he->p.ptr = _free(he->p.ptr);
1249  }
1250  mi = rpmmiFree(mi);
1251  }
1252  }
1253  }
1254  if (nkeys > 0)
1256  rpmteNEVR(p), rpmteKey(p),
1257  NULL, NULL,
1258  NULL, 0);
1259  keys = argvFree(keys);
1260  }
1261 
1262 #ifdef REFERENCE
1263  /* XXX rpmte problems can only be relocation problems atm */
1265  rpmpsi psi = rpmpsInitIterator(rpmteProblems(p));
1266  while (rpmpsNextIterator(psi) >= 0) {
1267  rpmpsAppendProblem(ps, rpmpsGetProblem(psi));
1268  }
1269  rpmpsFreeIterator(psi);
1270  }
1271 #endif /* REFERENCE */
1272 
1273  /* Count no. of files (if any). */
1274  totalFileCount += fc;
1275 
1276  }
1277  pi = rpmtsiFree(pi);
1278 
1279  /* The ordering doesn't matter here */
1280  pi = rpmtsiInit(ts);
1281  while ((p = rpmtsiNext(pi, TR_REMOVED)) != NULL) {
1282 
1283  if (p->isSource) continue;
1284  if ((fi = rpmtsiFi(pi)) == NULL)
1285  continue; /* XXX can't happen */
1286  fc = rpmfiFC(fi);
1287 
1288  totalFileCount += fc;
1289  }
1290  pi = rpmtsiFree(pi);
1291 
1292  if (tfcp)
1293  *tfcp = totalFileCount;
1294 
1295  return ps;
1296 }
1297 
1298 /*
1299  * Run pre/post transaction script.
1300  * param ts transaction set
1301  * param stag RPMTAG_PRETRANS or RPMTAG_POSTTRANS
1302  * return 0 on success
1303  */
1304 static int rpmtsRunScript(rpmts ts, rpmTag stag)
1305  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
1306  /*@modifies ts, rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
1307 {
1308  rpmtsi pi;
1309  rpmte p;
1310  rpmfi fi;
1311  rpmpsm psm;
1312  int xx;
1313  rpmTag ptag;
1314 
1315 FPSDEBUG(0, (stderr, "--> %s(%p,%s(%u))\n", __FUNCTION__, ts, tagName(stag), (unsigned)stag));
1316  switch (stag) {
1317  default:
1318 assert(0);
1319  /*@notreached@*/ break;
1320  case RPMTAG_PRETRANS: ptag = RPMTAG_PRETRANSPROG; break;
1321  case RPMTAG_POSTTRANS: ptag = RPMTAG_POSTTRANSPROG; break;
1322  }
1323 
1324  pi = rpmtsiInit(ts);
1325  while ((p = rpmtsiNext(pi, TR_ADDED)) != NULL) {
1326  if (p->isSource) continue;
1327  if ((fi = rpmtsiFi(pi)) == NULL)
1328  continue; /* XXX can't happen */
1329 
1330  /* If no prre/post transaction script, then don't bother. */
1331  if (!rpmteHaveTransScript(p, stag))
1332  continue;
1333 
1334  if (rpmteOpen(p, ts, 0)) {
1335  if (p->fi != NULL) /* XXX can't happen */
1336  p->fi->te = p;
1337 #ifdef REFERENCE
1338  psm = rpmpsmNew(ts, p);
1339 #else /* REFERENCE */
1340  psm = rpmpsmNew(ts, p, p->fi);
1341 #endif /* REFERENCE */
1342  xx = rpmpsmScriptStage(psm, stag, ptag);
1343  psm = rpmpsmFree(psm, __FUNCTION__);
1344  xx = rpmteClose(p, ts, 0);
1345  }
1346  }
1347  pi = rpmtsiFree(pi);
1348 
1349  return 0;
1350 }
1351 
1352 /* Add fingerprint for each file not skipped. */
1353 static void rpmtsAddFingerprints(rpmts ts, uint32_t fileCount, hashTable ht,
1354  fingerPrintCache fpc)
1355  /*@modifies ts, fpc @*/
1356 {
1357  rpmtsi pi;
1358  rpmte p;
1359  rpmfi fi;
1360  int i;
1361 
1362  hashTable symlinks = htCreate(fileCount/16+16, 0, 0, fpHashFunction, fpEqual);
1363 
1364 FPSDEBUG(0, (stderr, "--> %s(%p,%u,%p,%p)\n", __FUNCTION__, ts, (unsigned)fileCount, ht, fpc));
1365  pi = rpmtsiInit(ts);
1366  while ((p = rpmtsiNext(pi, (rpmElementType) 0)) != NULL) {
1367  (void) rpmdbCheckSignals();
1368 
1369  if (p->isSource) continue;
1370  if ((fi = rpmtsiFi(pi)) == NULL)
1371  continue; /* XXX can't happen */
1372 
1373  (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0);
1374 
1375  rpmfiFpLookup(fi, fpc);
1376 
1377  /* Collect symlinks. */
1378  fi = rpmfiInit(fi, 0);
1379  if (fi != NULL) /* XXX lclint */
1380  while ((i = rpmfiNext(fi)) >= 0) {
1381  char const *linktarget;
1382  linktarget = rpmfiFLink(fi);
1383  if (!(linktarget && *linktarget != '\0'))
1384  /*@innercontinue@*/ continue;
1385  if (iosmFileActionSkipped((iosmFileAction) fi->actions[i]))
1386  /*@innercontinue@*/ continue;
1387 #ifdef REFERENCE
1388  { struct rpmffi_s ffi;
1389  ffi.p = p;
1390  ffi.fileno = i;
1391  htAddEntry(symlinks, rpmfiFpsIndex(fi, i), ffi);
1392  }
1393 #else
1394  { struct rpmffi_s *ffip = (struct rpmffi_s *) alloca(sizeof(*ffip));
1395 /*@-dependenttrans@*/
1396  ffip->p = p;
1397 /*@=dependenttrans@*/
1398  ffip->fileno = i;
1399  htAddEntry(symlinks, fi->fps + i, (void *) ffip);
1400  }
1401 #endif
1402  }
1403 
1404  (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), rpmfiFC(fi));
1405 
1406  }
1407  pi = rpmtsiFree(pi);
1408 
1409  /* ===============================================
1410  * Check fingerprints if they contain symlinks
1411  * and add them to the hash table
1412  */
1413 
1414  pi = rpmtsiInit(ts);
1415  while ((p = rpmtsiNext(pi, (rpmElementType) 0)) != NULL) {
1416  (void) rpmdbCheckSignals();
1417 
1418  if (p->isSource) continue;
1419  if ((fi = rpmteFI(p, RPMTAG_BASENAMES)) == NULL)
1420  continue; /* XXX can't happen */
1421  fi = rpmfiInit(fi, 0);
1422  (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0);
1423  while ((i = rpmfiNext(fi)) >= 0) {
1424 #ifdef REFERENCE
1425  if (XFA_SKIPPING(rpmfsGetAction(rpmteGetFileStates(p), i)))
1426  continue;
1427 #else
1428  if (iosmFileActionSkipped((iosmFileAction) fi->actions[i]))
1429  /*@innercontinue@*/ continue;
1430 #endif
1431  fpLookupSubdir(symlinks, ht, fpc, p, i);
1432  }
1433  (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0);
1434  }
1435  pi = rpmtsiFree(pi);
1436 
1437  symlinks = htFree(symlinks);
1438 
1439 }
1440 
1441 static int rpmtsSetup(rpmts ts, rpmprobFilterFlags ignoreSet, rpmsx * sxp)
1442  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
1443  /*@modifies ts, *sxp, rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
1444 {
1445  rpmtransFlags tsflags = rpmtsFlags(ts);
1446  int xx;
1447 
1448 /*@+voidabstract@*/
1449 FPSDEBUG(0, (stderr, "--> %s(%p,0x%x,%p)\n", __FUNCTION__, ts, ignoreSet, (void *)sxp));
1450 /*@=voidabstract@*/
1451  /* --noscripts implies no scripts or triggers, duh. */
1452  if (TSF_ISSET(tsflags, NOSCRIPTS)) {
1453  TSF_SET(tsflags, NOPRETRANS);
1454  TSF_SET(tsflags, NOPRE);
1455  TSF_SET(tsflags, NOPOST);
1456  TSF_SET(tsflags, NOPREUN);
1457  TSF_SET(tsflags, NOPOSTUN);
1458  TSF_SET(tsflags, NOPOSTTRANS);
1459 
1460  TSF_SET(tsflags, NOTRIGGERPREIN);
1461  TSF_SET(tsflags, NOTRIGGERIN);
1462  TSF_SET(tsflags, NOTRIGGERUN);
1463  TSF_SET(tsflags, NOTRIGGERPOSTUN);
1464 
1465  (void) rpmtsSetFlags(ts, tsflags);
1466  }
1467  /* --notriggers implies no triggers, duh. */
1468  if (TSF_ISSET(tsflags, NOTRIGGERS)) {
1469  TSF_SET(tsflags, NOTRIGGERPREIN);
1470  TSF_SET(tsflags, NOTRIGGERIN);
1471  TSF_SET(tsflags, NOTRIGGERUN);
1472  TSF_SET(tsflags, NOTRIGGERPOSTUN);
1473  (void) rpmtsSetFlags(ts, tsflags);
1474  }
1475 
1476  /* --justdb implies no scripts or triggers, duh. */
1477  if (TSF_ISSET(tsflags, JUSTDB)) {
1478  TSF_SET(tsflags, NOPRETRANS);
1479  TSF_SET(tsflags, NOPRE);
1480  TSF_SET(tsflags, NOPOST);
1481  TSF_SET(tsflags, NOPREUN);
1482  TSF_SET(tsflags, NOPOSTUN);
1483  TSF_SET(tsflags, NOPOSTTRANS);
1484 
1485  TSF_SET(tsflags, NOTRIGGERPREIN);
1486  TSF_SET(tsflags, NOTRIGGERIN);
1487  TSF_SET(tsflags, NOTRIGGERUN);
1488  TSF_SET(tsflags, NOTRIGGERPOSTUN);
1489 
1490  (void) rpmtsSetFlags(ts, tsflags);
1491  }
1492 
1493  /* if SELinux isn't enabled or init fails, don't bother... */
1494  if (!rpmtsSELinuxEnabled(ts)) {
1495  TSF_SET(tsflags, NOCONTEXTS);
1496  TSF_SET(tsflags, NOPOLICY);
1497  (void) rpmtsSetFlags(ts, tsflags);
1498  }
1499 
1500  if (!(TSF_ISSET(tsflags, NOCONTEXTS) || TSF_ISSET(tsflags, NOPOLICY))) {
1501  *sxp = rpmsxNew("%{?_install_file_context_path}", 0);
1502  if (*sxp == NULL) {
1503  TSF_SET(tsflags, NOCONTEXTS);
1504  TSF_SET(tsflags, NOPOLICY);
1505  (void) rpmtsSetFlags(ts, tsflags);
1506  }
1507  } else
1508  *sxp = NULL;
1509 
1510  /* XXX Make sure the database is open RDWR for package install/erase. */
1511  { int dbmode = O_RDONLY;
1512 
1513  if (!TSF_ISSET(tsflags, TEST)) {
1514  rpmtsi pi;
1515  rpmte p;
1516  pi = rpmtsiInit(ts);
1517  while ((p = rpmtsiNext(pi, (rpmElementType) 0)) != NULL) {
1518  if (p->isSource) continue;
1519  dbmode = (O_RDWR|O_CREAT);
1520  break;
1521  }
1522  pi = rpmtsiFree(pi);
1523  }
1524 
1525  /* Open database RDWR for installing packages. */
1526  if (rpmtsOpenDB(ts, dbmode))
1527  return -1; /* XXX W2DO? */
1528 
1529  }
1530 
1531  ts->ignoreSet = ignoreSet;
1532  ts->probs = rpmpsFree(ts->probs);
1533 
1534  { const char * currDir = currentDirectory();
1535  rpmtsSetCurrDir(ts, currDir);
1536  currDir = _free(currDir);
1537  }
1538 
1539  (void) rpmtsSetChrootDone(ts, 0);
1540 
1541  /* XXX rpmtsCreate() sets the transaction id, but apps may not honor. */
1542  { rpmuint32_t tid = (rpmuint32_t) time(NULL);
1543  (void) rpmtsSetTid(ts, tid);
1544  }
1545 
1546  /* Get available space on mounted file systems. */
1547  xx = rpmtsInitDSI(ts);
1548 
1549  return 0;
1550 }
1551 
1552 static int rpmtsFinish(rpmts ts, /*@only@*/ rpmsx sx)
1553  /*@modifies sx @*/
1554 {
1555 FPSDEBUG(0, (stderr, "--> %s(%p,%p)\n", __FUNCTION__, ts, sx));
1556 #ifdef REFERENCE
1557  rpmtransFlags tsflags = rpmtsFlags(ts);
1558  if (!TSF_ISSET(tsflags, NOCONTEXTS))
1559  matchpathcon_fini();
1560 #else /* REFERENCE */
1561  if (sx != NULL) sx = rpmsxFree(sx);
1562 #endif /* REFERENCE */
1563  return 0;
1564 }
1565 
1566 static int rpmtsPrepare(rpmts ts, rpmsx sx, uint32_t fileCount,
1567  uint32_t * nrmvdp)
1568  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
1569  /*@modifies ts, *nrmvdp, rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
1570 {
1571  rpmtsi pi;
1572  rpmte p;
1573  fingerPrintCache fpc;
1574  rpmfi fi;
1575  int xx;
1576  int rc = 0;
1577 
1578 #ifdef REFERENCE
1579  uint64_t fileCount = countFiles(ts);
1580  const char * rootDir = rpmtsRootDir(ts);
1581  int dochroot = (rootDir != NULL && strcmp(rootDir, "/") && *rootDir == '/');
1582 
1583  rpmFpHash ht = rpmFpHashCreate(fileCount/2+1, fpHashFunction, fpEqual,
1584  NULL, NULL);
1585 
1586  fpc = fpCacheCreate(fileCount/2 + 10001);
1587 
1588  rpmlog(RPMLOG_DEBUG, "computing %" PRIu64 " file fingerprints\n", fileCount);
1589 
1590  /* Skip netshared paths, not our i18n files, and excluded docs */
1591  pi = rpmtsiInit(ts);
1592  while ((p = rpmtsiNext(pi, TR_ADDED)) != NULL) {
1593  if ((fi = rpmteFI(p)) == NULL)
1594  continue; /* XXX can't happen */
1595 
1596  if (rpmfiFC(fi) > 0)
1597  rpmtsSkipFiles(ts, p);
1598  }
1599  pi = rpmtsiFree(pi);
1600 
1601  /* Enter chroot for fingerprinting if necessary */
1602  if (!rpmtsChrootDone(ts)) {
1603  xx = chdir("/");
1604  if (dochroot) {
1605  /* opening db before chroot not optimal, see rhbz#103852 c#3 */
1606  xx = rpmdbOpenAll(ts->rdb);
1607  if (chroot(rootDir) == -1) {
1608  rpmlog(RPMLOG_ERR, _("Unable to change root directory: %m\n"));
1609  rc = -1;
1610  goto exit;
1611  }
1612  }
1613  (void) rpmtsSetChrootDone(ts, 1);
1614  }
1615 
1616 #else /* REFERENCE */
1617 
1618  void * ptr;
1619  uint32_t numAdded = 0;
1620  uint32_t numRemoved = 0;
1621 
1622 FPSDEBUG(0, (stderr, "--> %s(%p,%p,%u,%p)\n", __FUNCTION__, ts, sx, (unsigned)fileCount, nrmvdp));
1623 rpmlog(RPMLOG_DEBUG, D_("computing %u file fingerprints\n"), (unsigned)fileCount);
1624 
1625  pi = rpmtsiInit(ts);
1626  while ((p = rpmtsiNext(pi, (rpmElementType) 0)) != NULL) {
1627  int fc;
1628 
1629  if (p->isSource) continue;
1630  if ((fi = rpmtsiFi(pi)) == NULL)
1631  continue; /* XXX can't happen */
1632  fc = rpmfiFC(fi);
1633 
1634  switch (rpmteType(p)) {
1635  case TR_ADDED:
1636  numAdded++;
1637  fi->record = 0;
1638  /* Skip netshared paths, not our i18n files, and excluded docs */
1639  if (fc > 0)
1640  rpmtsSkipFiles(ts, fi);
1641  /*@switchbreak@*/ break;
1642  case TR_REMOVED:
1643  numRemoved++;
1644  fi->record = rpmteDBOffset(p);
1645  /*@switchbreak@*/ break;
1646  }
1647 
1648  fi->fps = (struct fingerPrint_s *)
1649  (fc > 0 ? xmalloc(fc * sizeof(*fi->fps)) : NULL);
1650  }
1651  pi = rpmtsiFree(pi);
1652 
1653  if (nrmvdp)
1654  *nrmvdp = numRemoved;
1655 
1656  if (!rpmtsChrootDone(ts)) {
1657  const char * rootDir = rpmtsRootDir(ts);
1658  static int openall_before_chroot = -1;
1659 
1660  if (openall_before_chroot < 0)
1661  openall_before_chroot = rpmExpandNumeric("%{?_openall_before_chroot}");
1662 
1663  xx = Chdir("/");
1664  /*@-modobserver@*/
1665  if (rootDir != NULL && strcmp(rootDir, "/") && *rootDir == '/') {
1666  if (openall_before_chroot)
1667  xx = rpmdbOpenAll(rpmtsGetRdb(ts));
1668  xx = Chroot(rootDir);
1669  }
1670  /*@=modobserver@*/
1671  (void) rpmtsSetChrootDone(ts, 1);
1672  }
1673 
1674  ts->ht = htCreate(fileCount/2 + 1, 0, 1, fpHashFunction, fpEqual);
1675  fpc = fpCacheCreate(fileCount/2 + 10001);
1676 
1677 #endif /* REFERENCE */
1678 
1679  ptr = rpmtsNotify(ts, NULL, RPMCALLBACK_TRANS_START, 6, ts->orderCount);
1680 
1681  /* ===============================================
1682  * Add fingerprint for each file not skipped.
1683  */
1684 #ifdef REFERENCE
1685  rpmtsAddFingerprints(ts, fileCount, ht, fpc);
1686 #else /* REFERENCE */
1687  rpmtsAddFingerprints(ts, fileCount, ts->ht, fpc);
1688 #endif /* REFERENCE */
1689 
1690  /* ===============================================
1691  * Compute file disposition for each package in transaction set.
1692  */
1693 #ifdef REFERENCE
1694  rpmtsCheckInstalledFiles(ts, fileCount, ht, fpc);
1695 #else /* REFERENCE */
1696  rc = rpmtsCheckInstalledFiles(ts, fileCount, ts->ht, fpc);
1697  if (rc)
1698  goto exit;
1699 #endif /* REFERENCE */
1700 
1701  pi = rpmtsiInit(ts);
1702  while ((p = rpmtsiNext(pi, (rpmElementType) 0)) != NULL) {
1703  if ((fi = rpmteFI(p, RPMTAG_BASENAMES)) == NULL)
1704  continue; /* XXX can't happen */
1705  /* XXX Set all SRPM files to FA_CREATE. */
1706  if (p->isSource) {
1707  int i;
1708  fi = rpmfiInit(fi, 0);
1709  if (fi != NULL)
1710  while ((i = rpmfiNext(fi)) >= 0)
1711  fi->actions[i] = FA_CREATE;
1712  continue;
1713  }
1714 
1715  (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0);
1716 
1717  /* Update disk space needs on each partition for this package. */
1718 /*@-nullpass@*/
1719 #ifdef REFERENCE
1720  handleOverlappedFiles(ts, ht, p, fi);
1721 #else /* REFERENCE */
1722  handleOverlappedFiles(ts, p, fi);
1723 #endif /* REFERENCE */
1724 /*@=nullpass@*/
1725 
1726  /* Check added package has sufficient space on each partition used. */
1727  switch (rpmteType(p)) {
1728  case TR_ADDED:
1729  rpmtsCheckDSIProblems(ts, p);
1730  /*@switchbreak@*/ break;
1731  case TR_REMOVED:
1732  /*@switchbreak@*/ break;
1733  }
1734  (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), rpmfiFC(fi));
1735  }
1736  pi = rpmtsiFree(pi);
1737 
1738  if (rpmtsChrootDone(ts)) {
1739  const char * rootDir = rpmtsRootDir(ts);
1740  const char * currDir = rpmtsCurrDir(ts);
1741  /*@-modobserver@*/
1742  if (rootDir != NULL && strcmp(rootDir, "/") && *rootDir == '/')
1743  xx = Chroot(".");
1744  /*@=modobserver@*/
1745  (void) rpmtsSetChrootDone(ts, 0);
1746  if (currDir != NULL)
1747  xx = Chdir(currDir);
1748  }
1749 
1750  ptr = rpmtsNotify(ts, NULL, RPMCALLBACK_TRANS_STOP, 6, ts->orderCount);
1751 
1752  /* ===============================================
1753  * Free unused memory as soon as possible.
1754  */
1755 #ifdef REFERENCE
1756  pi = rpmtsiInit(ts);
1757  while ((p = rpmtsiNext(pi, (rpmElementType) 0)) != NULL) {
1758  rpmteSetFI(p, NULL);
1759  }
1760  pi = rpmtsiFree(pi);
1761 #else /* REFERENCE */
1762  pi = rpmtsiInit(ts);
1763  while ((p = rpmtsiNext(pi, (rpmElementType) 0)) != NULL) {
1764  if (p->isSource) continue;
1765  if ((fi = rpmtsiFi(pi)) == NULL)
1766  continue; /* XXX can't happen */
1767  if (rpmfiFC(fi) == 0)
1768  continue;
1769  fi->fps = _free(fi->fps);
1770  }
1771  pi = rpmtsiFree(pi);
1772 #endif /* REFERENCE */
1773 
1774 exit:
1775 #ifdef REFERENCE
1776  ht = rpmFpHashFree(ht);
1777 #else /* REFERENCE */
1778  ts->ht = htFree(ts->ht);
1779 #endif /* REFERENCE */
1780  fpc = fpCacheFree(fpc);
1781 
1782  return rc;
1783 }
1784 
1785 /*
1786  * Transaction main loop: install and remove packages
1787  */
1788 static int rpmtsProcess(rpmts ts, rpmprobFilterFlags ignoreSet,
1789  int rollbackFailures)
1790  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
1791  /*@modifies ts, rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
1792 {
1793  rpmtsi pi;
1794  rpmte p;
1795  int rc = 0;
1796 
1797 FPSDEBUG(0, (stderr, "--> %s(%p,0x%x,%d)\n", __FUNCTION__, ts, ignoreSet, rollbackFailures));
1798  pi = rpmtsiInit(ts);
1799  while ((p = rpmtsiNext(pi, (rpmElementType) 0)) != NULL) {
1800  rpmfi fi;
1801  rpmop sw;
1802  rpmpsm psm = NULL;
1803  pkgStage stage = PSM_UNKNOWN;
1804  int failed;
1805  int gotfd;
1806  int xx;
1807 
1808 #ifdef REFERENCE
1809  rpmElementType tetype = rpmteType(p);
1810  rpmtsOpX op = (tetype == TR_ADDED) ? RPMTS_OP_INSTALL : RPMTS_OP_ERASE;
1811 #endif /* REFERENCE */
1812 
1813  (void) rpmdbCheckSignals();
1814 
1815  failed = 1;
1816  gotfd = 0;
1817  if ((fi = rpmtsiFi(pi)) == NULL)
1818  continue; /* XXX can't happen */
1819 
1820  if (rpmteFailed(p)) {
1821  /* XXX this should be a warning, need a better message though */
1822  rpmlog(RPMLOG_DEBUG, D_("element %s marked as failed, skipping\n"),
1823  rpmteNEVRA(p));
1824  rc++;
1825  continue;
1826  }
1827 
1828  psm = rpmpsmNew(ts, p, fi);
1829  { int async = (rpmtsiOc(pi) >= rpmtsUnorderedSuccessors(ts, -1)) ?
1830  1 : 0;
1831  rpmpsmSetAsync(psm, async);
1832  }
1833 
1834  switch (rpmteType(p)) {
1835  case TR_ADDED:
1836  rpmlog(RPMLOG_DEBUG, "========== +++ %s %s-%s 0x%x\n",
1837  rpmteNEVR(p), rpmteA(p), rpmteO(p), rpmteColor(p));
1838  stage = PSM_PKGINSTALL;
1839  sw = rpmtsOp(ts, RPMTS_OP_INSTALL);
1840 #ifdef REFERENCE
1841  if (rpmteOpen(p, ts, 1)) {
1842  (void) rpmswEnter(rpmtsOp(ts, op), 0);
1843  failed = rpmpsmStage(psm, stage);
1844  (void) rpmswExit(rpmtsOp(ts, op), 0);
1845  rpmteClose(p, ts, 1);
1846  }
1847 #else /* REFERENCE */
1848  if ((p->h = rpmteFDHeader(ts, p)) != NULL)
1849  gotfd = 1;
1850 
1851  if (gotfd && rpmteFd(p) != NULL) {
1852  /*
1853  * XXX Sludge necessary to transfer existing fstates/actions
1854  * XXX around a recreated file info set.
1855  */
1856  rpmuint8_t * fstates = fi->fstates;
1857  iosmFileAction * actions = (iosmFileAction *) fi->actions;
1858  int mapflags = fi->mapflags;
1859  rpmte savep;
1860  int scareMem = 0;
1861 
1862  psm->fi = rpmfiFree(psm->fi);
1863 
1864  fi->fstates = NULL;
1865  fi->actions = NULL;
1866 /*@-nullstate@*/ /* FIX: fi->actions is NULL */
1867  fi = rpmfiFree(fi);
1868 /*@=nullstate@*/
1869 
1870  savep = rpmtsSetRelocateElement(ts, p);
1871  fi = rpmfiNew(ts, p->h, RPMTAG_BASENAMES, scareMem);
1872  (void) rpmtsSetRelocateElement(ts, savep);
1873 
1874  if (fi != NULL) { /* XXX can't happen */
1875  fi->te = p;
1876  fi->fstates = _free(fi->fstates);
1877  fi->fstates = fstates;
1878  fi->actions = _free(fi->actions);
1879  fi->actions = (int *) actions;
1880  if (mapflags & IOSM_SBIT_CHECK)
1881  fi->mapflags |= IOSM_SBIT_CHECK;
1882  p->fi = fi;
1883  }
1884 
1885  psm->fi = rpmfiLink(p->fi, __FUNCTION__);
1886 
1887  (void) rpmswEnter(sw, 0);
1888  failed = (rpmpsmStage(psm, stage) != RPMRC_OK);
1889  (void) rpmswExit(sw, 0);
1890 
1891  xx = rpmteClose(p, ts, 0);
1892  gotfd = 0;
1893  }
1894 
1895 #endif /* REFERENCE */
1896  /*@switchbreak@*/ break;
1897 
1898  case TR_REMOVED:
1899  rpmlog(RPMLOG_DEBUG, "========== --- %s %s-%s 0x%x\n",
1900  rpmteNEVR(p), rpmteA(p), rpmteO(p), rpmteColor(p));
1901  stage = PSM_PKGERASE;
1902  sw = rpmtsOp(ts, RPMTS_OP_ERASE);
1903 #ifdef REFERENCE
1904  if (rpmteOpen(p, ts, 1)) {
1905  (void) rpmswEnter(rpmtsOp(ts, op), 0);
1906  failed = rpmpsmStage(psm, stage);
1907  (void) rpmswExit(rpmtsOp(ts, op), 0);
1908  rpmteClose(p, ts, 1);
1909  }
1910 #else /* REFERENCE */
1911  (void) rpmswEnter(sw, 0);
1912  failed = (rpmpsmStage(psm, stage) != RPMRC_OK);
1913  (void) rpmswExit(sw, 0);
1914 #endif /* REFERENCE */
1915  /*@switchbreak@*/ break;
1916  }
1917 
1918 #if defined(RPM_VENDOR_MANDRIVA)
1919  { rpmtransFlags tsflags = rpmtsFlags(ts);
1920  if (!failed && !TSF_ISSET(tsflags, TEST)) {
1921  if(!rpmteIsSource(p))
1922  xx = mayAddToFilesAwaitingFiletriggers(rpmtsRootDir(ts),
1923  fi, (rpmteType(p) == TR_ADDED ? 1 : 0));
1924  p->done = 1;
1925  }
1926  }
1927 #endif
1928 
1929 /*@-nullstate@*/ /* FIX: psm->fi may be NULL */
1930  psm = rpmpsmFree(psm, __FUNCTION__);
1931 /*@=nullstate@*/
1932 
1933  if (failed) {
1934  rc++;
1935 #ifdef REFERENCE
1936  rpmteMarkFailed(p, ts);
1937 #else /* REFERENCE */
1938  xx = rpmtsMarkLinkedFailed(ts, p);
1939  /* If we received an error, lets break out and rollback, provided
1940  * autorollback is enabled.
1941  */
1942  if (rollbackFailures) {
1943  xx = rpmtsRollback(ts, ignoreSet, 1, p);
1944  break;
1945  }
1946 #endif /* REFERENCE */
1947  }
1948 
1949  if (p->h != NULL) {
1950  (void) headerFree(p->h);
1951  p->h = NULL;
1952  }
1953 
1954 #ifdef REFERENCE
1955  (void) rpmdbSync(rpmtsGetRdb(ts));
1956 #endif /* REFERENCE */
1957 
1958  }
1959  pi = rpmtsiFree(pi);
1960  return rc;
1961 }
1962 
1963 /* ================================================================= */
1964 static int rpmtsRepackage(rpmts ts, uint32_t numRemoved)
1965  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
1966  /*@modifies ts, rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
1967 {
1968  rpmtransFlags tsflags = rpmtsFlags(ts);
1969  rpmpsm psm;
1970  rpmfi fi;
1971  rpmtsi pi;
1972  rpmte p;
1973  void * ptr;
1974  int progress = 0;
1975  int rc = 0;
1976  int xx;
1977 
1978 FPSDEBUG(0, (stderr, "--> %s(%p,%u)\n", __FUNCTION__, ts, (unsigned)numRemoved));
1979  pi = rpmtsiInit(ts);
1980  while ((p = rpmtsiNext(pi, (rpmElementType) 0)) != NULL) {
1981 
1982  (void) rpmdbCheckSignals();
1983 
1984  if (p->isSource) continue;
1985  if ((fi = rpmtsiFi(pi)) == NULL)
1986  continue; /* XXX can't happen */
1987  switch (rpmteType(p)) {
1988  case TR_ADDED:
1989  /*@switchbreak@*/ break;
1990  case TR_REMOVED:
1991  if (!TSF_ISSET(tsflags, REPACKAGE))
1992  /*@switchbreak@*/ break;
1993  if (!progress)
1994  ptr = rpmtsNotify(ts, NULL, RPMCALLBACK_REPACKAGE_START,
1995  7, numRemoved);
1996 
1998  progress, numRemoved);
1999  progress++;
2000 
2001  (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_REPACKAGE), 0);
2002 
2003  /* XXX TR_REMOVED needs IOSM_MAP_{ABSOLUTE,ADDDOT} IOSM_ALL_HARDLINKS */
2004  fi->mapflags |= IOSM_MAP_ABSOLUTE;
2005  fi->mapflags |= IOSM_MAP_ADDDOT;
2006  fi->mapflags |= IOSM_ALL_HARDLINKS;
2007  psm = rpmpsmNew(ts, p, fi);
2008 assert(psm != NULL);
2009  xx = rpmpsmStage(psm, PSM_PKGSAVE);
2010  psm = rpmpsmFree(psm, __FUNCTION__);
2011  fi->mapflags &= ~IOSM_MAP_ABSOLUTE;
2012  fi->mapflags &= ~IOSM_MAP_ADDDOT;
2013  fi->mapflags &= ~IOSM_ALL_HARDLINKS;
2014 
2015  (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_REPACKAGE), 0);
2016 
2017  /*@switchbreak@*/ break;
2018  }
2019  }
2020  pi = rpmtsiFree(pi);
2021  if (progress)
2022  ptr = rpmtsNotify(ts, NULL, RPMCALLBACK_REPACKAGE_STOP, 7, numRemoved);
2023 
2024  return rc;
2025 }
2026 
2033 /*@-nullpass@*/
2035  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
2036  /*@modifies ts, p, rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
2037 {
2038  int rc = RPMRC_OK; /* assume success */
2039 
2040 FPSDEBUG(0, (stderr, "--> %s(%p,%p)\n", __FUNCTION__, ts, p));
2041  /* Handle failed packages. */
2042  /* XXX TODO: Add header to rpmdb in PSM_INIT, not PSM_POST. */
2043  if (p != NULL && rpmteType(p) == TR_ADDED && !p->installed) {
2044 /*@-compdef -usereleased@*/ /* p->fi->te undefined */
2045  rpmpsm psm = rpmpsmNew(ts, p, p->fi);
2046 /*@=compdef =usereleased@*/
2047  /*
2048  * If it died before the header was put in the rpmdb, we need
2049  * do to something wacky which is add the header to the DB anyway.
2050  * This will allow us to add the failed package as an erase
2051  * to the rollback transaction. This must be done because we
2052  * want the the erase scriptlets to run, and the only way that
2053  * is going is if the header is in the rpmdb.
2054  */
2055 assert(psm != NULL);
2056  psm->stepName = "failed"; /* XXX W2DO? */
2057  rc = rpmpsmStage(psm, PSM_RPMDB_ADD);
2058  psm = rpmpsmFree(psm, __FUNCTION__);
2059  }
2060  return (rpmRC) rc;
2061 }
2062 /*@=nullpass@*/
2063 
2064 /*@-nullpass@*/
2065 rpmRC rpmtsRollback(rpmts rbts, rpmprobFilterFlags ignoreSet, int running, rpmte rbte)
2066  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
2067  /*@modifies rbts, rpmGlobalMacroContext, fileSystem, internalState @*/
2068 {
2069  const char * semfn = NULL;
2070  rpmRC rc = (rpmRC) 0;
2071  rpmuint32_t arbgoal = rpmtsARBGoal(rbts);
2072  QVA_t ia = (QVA_t) memset(alloca(sizeof(*ia)), 0, sizeof(*ia));
2073  time_t ttid;
2074  int xx;
2075 
2076 FPSDEBUG(0, (stderr, "--> %s(%p,0x%x,%d,%p)\n", __FUNCTION__, rbts, ignoreSet, running, rbte));
2077  /* Don't attempt rollback's of rollback transactions */
2078  if ((rpmtsType(rbts) & RPMTRANS_TYPE_ROLLBACK) ||
2080  return RPMRC_OK;
2081 
2082  if (arbgoal == 0xffffffff)
2083  arbgoal = rpmtsGetTid(rbts);
2084 
2085  /* Don't attempt rollbacks if no goal is set. */
2086  if (!running && arbgoal == 0xffffffff)
2087  return RPMRC_OK;
2088 
2089  /* We need to remove an headers that were going to be removed so
2090  * as to not foul up the regular rollback mechanism which will not
2091  * handle properly a file being in the repackaged package directory
2092  * and also its header still in the DB.
2093  */
2094  { rpmtsi tsi;
2095  rpmte te;
2096 
2097  /* XXX Insure an O_RDWR rpmdb. */
2098  xx = rpmtsOpenDB(rbts, O_RDWR);
2099 
2100  tsi = rpmtsiInit(rbts);
2101  while((te = rpmtsiNext(tsi, TR_REMOVED)) != NULL) {
2102  if (te->isSource) continue;
2103  if(!te->u.removed.dboffset)
2104  continue;
2105  rc = (rpmRC) rpmdbRemove(rpmtsGetRdb(rbts),
2106  rpmtsGetTid(rbts),
2107  te->u.removed.dboffset, NULL);
2108  if (rc != RPMRC_OK) {
2109  rpmlog(RPMLOG_ERR, _("rpmdb erase failed. NEVRA: %s\n"),
2110  rpmteNEVRA(te));
2111  break;
2112  }
2113  }
2114  tsi = rpmtsiFree(tsi);
2115  if (rc != RPMRC_OK)
2116  goto cleanup;
2117  }
2118 
2119  /* Process the failed package */
2120  rc = _processFailedPackage(rbts, rbte);
2121  if (rc != RPMRC_OK)
2122  goto cleanup;
2123 
2124  rpmtsEmpty(rbts);
2125 
2126  ttid = (time_t)arbgoal;
2127  rpmlog(RPMLOG_NOTICE, _("Rollback to %-24.24s (0x%08x)\n"),
2128  ctime(&ttid), arbgoal);
2129 
2130  /* Set the verify signature flags:
2131  * - can't verify signatures/digests on repackaged packages.
2132  * - header check are out.
2133  */
2134  {
2135  rpmVSFlags vsflags = (rpmVSFlags) rpmExpandNumeric("%{?_vsflags_erase}");
2136  vsflags = (rpmVSFlags) 0; /* XXX FIXME: ignore default disablers. */
2137 #if defined(SUPPORT_NOSIGNATURES)
2138  /* --nodigest */
2139  VSF_SET(vsflags, NOSHA1HEADER);
2140  VSF_SET(vsflags, NOMD5HEADER);
2141  VSF_SET(vsflags, NOSHA1);
2142  VSF_SET(vsflags, NOMD5);
2143  /* --nosignature */
2144  VSF_SET(vsflags, NODSAHEADER);
2145  VSF_SET(vsflags, NORSAHEADER);
2146  VSF_SET(vsflags, NODSA);
2147  VSF_SET(vsflags, NORSA);
2148  /* --nohdrchk */
2149  VSF_SET(vsflags, NOHDRCHK);
2150  VSF_SET(vsflags, NEEDPAYLOAD); /* XXX needed? */
2151 #endif
2152  xx = rpmtsSetVSFlags(rbts, vsflags);
2153  }
2154 
2155  /* Set transaction flags to be the same as the running transaction */
2156  {
2157  rpmtransFlags tsflags = rpmtsFlags(rbts);
2158  TSF_CLR(tsflags, DIRSTASH); /* No repackage of rollbacks */
2159  TSF_CLR(tsflags, REPACKAGE); /* No repackage of rollbacks */
2160  TSF_SET(tsflags, NOFDIGESTS); /* Don't check file digests */
2161  tsflags = rpmtsSetFlags(rbts, tsflags);
2162  }
2163 
2164  /* Create install arguments structure */
2165  ia->rbtid = arbgoal;
2166  /* transFlags/depFlags from rbts, (re-)set in rpmRollback(). */
2167  ia->transFlags = rpmtsFlags(rbts);
2168  ia->depFlags = rpmtsDFlags(rbts);
2169  /* XXX probFilter is normally set in main(). */
2170  ia->probFilter = ignoreSet; /* XXX RPMPROB_FILTER_NONE? */
2171  /* XXX installInterfaceFlags is normally set in main(). */
2172  IIF_SET(ia->installInterfaceFlags, UPGRADE);
2173  IIF_SET(ia->installInterfaceFlags, HASH);
2174 
2175  /* rpmtsCheck and rpmtsOrder failures do not have links. */
2176  ia->no_rollback_links = 1;
2177 
2178  /* Create a file semaphore. */
2179  semfn = rpmExpand("%{?semaphore_backout}", NULL);
2180  if (semfn && *semfn) {
2181  FD_t fd = Fopen(semfn, "w.fdio");
2182  if (fd)
2183  xx = Fclose(fd);
2184  }
2185 
2186 /*@-compmempass@*/
2187  rc = (rpmRC) rpmRollback(rbts, ia, NULL);
2188 /*@=compmempass@*/
2189 
2190 cleanup:
2191  /* Remove the file semaphore. */
2192  if (semfn && *semfn)
2193  xx = Unlink(semfn);
2194  semfn = _free(semfn);
2195 
2196  return rc;
2197 }
2198 /*@=nullpass@*/
2199 
2200 int _rpmtsRun(rpmts ts, rpmps okProbs, rpmprobFilterFlags ignoreSet)
2201 {
2202  rpmtransFlags tsflags = rpmtsFlags(ts);
2203  int ourrc = -1; /* assume failure */
2204  uint32_t totalFileCount = 0;
2205  rpmps ps;
2206  rpmsx sx = NULL;
2207  uint32_t numRemoved;
2208  int rollbackFailures = 0;
2209  void * lock = NULL;
2210  int xx;
2211 
2212 FPSDEBUG(0, (stderr, "--> %s(%p,%p,0x%x)\n", __FUNCTION__, ts, okProbs, ignoreSet));
2213 if (_rpmts_debug)
2214 fprintf(stderr, "--> %s(%p,%p,0x%x) tsflags 0x%x\n", __FUNCTION__, ts, okProbs, (unsigned) ignoreSet, tsflags);
2215 
2216  /* XXX programmer error segfault avoidance. */
2217  if (rpmtsNElements(ts) <= 0) {
2219  _("Invalid number of transaction elements.\n"));
2220  return -1;
2221  }
2222 
2223  /* Don't acquire the transaction lock if testing. */
2224  if (!TSF_ISSET(tsflags, TEST))
2225  lock = rpmtsAcquireLock(ts);
2226 
2227  rollbackFailures = rpmExpandNumeric("%{?_rollback_transaction_on_failure}");
2228  /* Don't rollback unless repackaging. */
2229  if (!TSF_ISSET(tsflags, REPACKAGE))
2230  rollbackFailures = 0;
2231  /* Don't rollback if testing. */
2232  if (TSF_ISSET(tsflags, TEST))
2233  rollbackFailures = 0;
2234 
2236  rollbackFailures = 0;
2237 
2238  /* ===============================================
2239  * Setup flags and such, open the rpmdb in O_RDWR mode.
2240  */
2241  sx = NULL;
2242  if (rpmtsSetup(ts, ignoreSet, &sx))
2243  goto exit;
2244 
2245  /* ===============================================
2246  * For packages being installed:
2247  * - verify package epoch:version-release is newer.
2248  * - count files.
2249  * For packages being removed:
2250  * - count files.
2251  */
2252 
2253  totalFileCount = 0;
2254  ps = rpmtsSanityCheck(ts, &totalFileCount);
2255  ps = rpmpsFree(ps);
2256 
2257  /* ===============================================
2258  * Run pre-transaction scripts, but only if no known problems exist.
2259  */
2260  if (!TSF_ISSET(tsflags, NOPRETRANS) &&
2261  (!(TSF_ISSET(tsflags, BUILD_PROBS) || TSF_ISSET(tsflags, TEST))
2262  || (rpmpsNumProblems(ts->probs) &&
2263  (okProbs == NULL || rpmpsTrim(ts->probs, okProbs)))))
2264  {
2265  rpmlog(RPMLOG_DEBUG, D_("running pre-transaction scripts\n"));
2266  xx = rpmtsRunScript(ts, RPMTAG_PRETRANS);
2267  }
2268 
2269  /* ===============================================
2270  * Compute file disposition for each package in transaction set.
2271  */
2272  numRemoved = 0;
2273  if (rpmtsPrepare(ts, sx, totalFileCount, &numRemoved))
2274  goto exit;
2275 
2276  /* ===============================================
2277  * If unfiltered problems exist, free memory and return.
2278  */
2279  if (TSF_ISSET(tsflags, BUILD_PROBS)
2280  || (rpmpsNumProblems(ts->probs) &&
2281  (okProbs == NULL || rpmpsTrim(ts->probs, okProbs)))
2282  )
2283  {
2284  lock = rpmtsFreeLock(lock);
2285  if (sx != NULL) sx = rpmsxFree(sx);
2286  return ts->orderCount;
2287  }
2288 
2289  /* ===============================================
2290  * Save removed files before erasing.
2291  */
2292  if (TSF_ISSET(tsflags, DIRSTASH) || TSF_ISSET(tsflags, REPACKAGE)) {
2293  xx = rpmtsRepackage(ts, numRemoved);
2294  }
2295 
2296 #ifdef NOTYET
2297  xx = rpmtxnBegin(rpmtsGetRdb(ts), NULL, &ts->txn);
2298 #endif
2299 
2300  /* ===============================================
2301  * Install and remove packages.
2302  */
2303  ourrc = rpmtsProcess(ts, ignoreSet, rollbackFailures);
2304 
2305  /* ===============================================
2306  * Run post-transaction scripts unless disabled.
2307  */
2308  if (!TSF_ISSET(tsflags, NOPOSTTRANS) && !TSF_ISSET(tsflags, TEST))
2309  {
2310 
2311 #if defined(RPM_VENDOR_MANDRIVA)
2312  /* XXX FIXME: simplify the logic. */
2313  if (!TSF_ISSET(tsflags, NOTRIGGERPREIN)
2314  || !TSF_ISSET(tsflags, NOTRIGGERIN)
2315  || !TSF_ISSET(tsflags, NOTRIGGERUN)
2316  || !TSF_ISSET(tsflags, NOTRIGGERPOSTUN))
2317  rpmRunFileTriggers(rpmtsRootDir(ts));
2318 #endif
2319 
2320  rpmlog(RPMLOG_DEBUG, D_("running post-transaction scripts\n"));
2321  xx = rpmtsRunScript(ts, RPMTAG_POSTTRANS);
2322  }
2323 
2324 exit:
2325  xx = rpmtsFinish(ts, sx);
2326 
2327  lock = rpmtsFreeLock(lock);
2328 
2329  /*@-nullstate@*/ /* FIX: ts->flList may be NULL */
2330  if (ourrc) {
2331  if (ts->txn != NULL)
2332  xx = rpmtxnAbort(ts->txn);
2333  ts->txn = NULL;
2334  return -1;
2335  } else {
2336  if (ts->txn != NULL)
2337  xx = rpmtxnCommit(ts->txn);
2338  ts->txn = NULL;
2339  xx = rpmtxnCheckpoint(rpmtsGetRdb(ts));
2340  return 0;
2341  }
2342  /*@=nullstate@*/
2343 }
2344 
2345 int (*rpmtsRun) (rpmts ts, rpmps okProbs, rpmprobFilterFlags ignoreSet)
2346  = _rpmtsRun;