rpm  5.4.15
psm.c
Go to the documentation of this file.
1 
6 #include "system.h"
7 
8 #define _MIRE_INTERNAL /* XXX mireApply doesn't tell which pattern matched. */
9 
10 #include <rpmio_internal.h> /* XXX FDSTAT_READ */
11 #include <rpmcb.h> /* XXX fnpyKey */
12 #include <rpmsx.h>
13 #include <rpmmacro.h>
14 #include <rpmurl.h>
15 
16 #include <rpmaug.h>
17 #include <rpmficl.h>
18 #include <rpmjni.h>
19 #include <rpmjs.h>
20 #include <rpmlua.h>
21 #include <rpmmrb.h>
22 #include <rpmperl.h>
23 #include <rpmpython.h>
24 #include <rpmruby.h>
25 #include <rpmsm.h>
26 #include <rpmsql.h>
27 #include <rpmsquirrel.h>
28 #include <rpmtcl.h>
29 
30 #if defined(WITH_LUA) || defined(WITH_AUGEAS) || defined(WITH_FICL) || defined(WITH_GPSEE) || defined(WITH_MRBEMBED) || defined(WITH_PERLEMBED) || defined(WITH_PYTHONEMBED) || defined(WITH_RUBYEMBED) || defined(WITH_SEMANAGE) || defined(WITH_SQLITE) || defined(WITH_SQUIRREL) || defined(WITH_TCL)
31 #define _WITH_EMBEDDED
32 #else
33 #undef _WITH_ENBEDDED
34 #endif
35 
36 #include <rpmtag.h>
37 #include <rpmtypes.h>
38 #include <pkgio.h>
39 #define _RPMDB_INTERNAL
40 #include <rpmdb.h> /* XXX for db_chrootDone */
41 #include <rpmtxn.h>
42 #include "signature.h" /* signature constants */
43 #include <rpmlib.h>
44 
45 #define _RPMFI_INTERNAL
46 #include "rpmfi.h"
47 #include "fsm.h" /* XXX CPIO_FOO/IOSM_FOO constants */
48 #define _RPMSQ_INTERNAL
49 #define _RPMPSM_INTERNAL
50 #include "psm.h"
51 #define F_ISSET(_psm, _FLAG) ((_psm)->flags & (RPMPSM_FLAGS_##_FLAG))
52 #define F_SET(_psm, _FLAG) { \
53  unsigned ui = (unsigned)(_psm)->flags; ui |= (RPMPSM_FLAGS_##_FLAG); \
54  (_psm)->flags = (rpmpsmFlags) ui; \
55  }
56 #define F_CLR(_psm, _FLAG) { \
57  unsigned ui = (unsigned)(_psm)->flags; ui &= ~(RPMPSM_FLAGS_##_FLAG); \
58  (_psm)->flags = (rpmpsmFlags) ui; \
59  }
60 
61 #define _RPMEVR_INTERNAL
62 #include "rpmds.h"
63 
64 #define _RPMTE_INTERNAL
65 #include "rpmte.h"
66 
67 #define _RPMTS_INTERNAL /* XXX ts->notify */
68 #include "rpmts.h"
69 
70 #include "misc.h" /* XXX rpmMkdirPath, makeTempFile, doputenv */
71 
72 #include <rpmcli.h>
73 
74 #include "debug.h"
75 
76 #define _PSM_DEBUG 0
77 /*@unchecked@*/
79 /*@unchecked@*/
80 int _psm_threads = 0;
81 
82 /*@access FD_t @*/ /* XXX void * arg */
83 /*@access Header @*/ /* XXX void * arg */
84 /*@access miRE @*/
85 
86 /*@access rpmpsm @*/
87 
88 /*@access rpmfi @*/
89 /*@access rpmte @*/ /* XXX rpmInstallSourcePackage */
90 /*@access rpmts @*/ /* XXX ts->notify */
91 
92 /*@access rpmluav @*/
93 
94 #ifdef __cplusplus
95 GENfree(HE_t)
96 GENfree(int *)
97 GENfree(const struct stat *)
98 #endif /* __cplusplus */
99 
100 #ifdef DYING
101 
106 static rpmRC markReplacedFiles(const rpmpsm psm)
107  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
108  /*@modifies psm, rpmGlobalMacroContext, fileSystem, internalState @*/
109 {
110  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
111  const rpmts ts = psm->ts;
112  rpmte te = psm->te;
113  rpmfi fi = psm->fi;
114  sharedFileInfo replaced = (te ? te->replaced : NULL);
115  sharedFileInfo sfi;
116  rpmmi mi;
117  Header h;
118  uint32_t * offsets;
119  rpmuint32_t prev;
120  int num;
121  int xx;
122 
123  if (!(rpmfiFC(fi) > 0 && replaced != NULL))
124  return RPMRC_OK;
125 
126  num = prev = 0;
127  for (sfi = replaced; sfi->otherPkg; sfi++) {
128  if (prev && prev == sfi->otherPkg)
129  continue;
130  prev = sfi->otherPkg;
131  num++;
132  }
133  if (num == 0)
134  return RPMRC_OK;
135 
136  offsets = (uint32_t *) alloca(num * sizeof(*offsets));
137  offsets[0] = 0;
138  num = prev = 0;
139  for (sfi = replaced; sfi->otherPkg; sfi++) {
140  if (prev && prev == sfi->otherPkg)
141  continue;
142  prev = sfi->otherPkg;
143  offsets[num++] = sfi->otherPkg;
144  }
145 
146  mi = rpmtsInitIterator(ts, RPMDBI_PACKAGES, NULL, 0);
147  xx = rpmmiGrow(mi, offsets, num);
148  xx = rpmmiSetRewrite(mi, 1);
149 
150  sfi = replaced;
151  while ((h = rpmmiNext(mi)) != NULL) {
152  int modified;
153 
154  modified = 0;
155 
156  /* XXX FIXME: not correct yet, but headerGetEntry needs to die now! */
157  he->tag = RPMTAG_FILESTATES;
158  xx = headerGet(h, he, 0);
159  if (!xx)
160  continue;
161 
162  prev = rpmmiInstance(mi);
163  num = 0;
164  while (sfi->otherPkg && sfi->otherPkg == prev) {
165 assert(sfi->otherFileNum < he->c);
166  if (he->p.ui8p[sfi->otherFileNum] != RPMFILE_STATE_REPLACED) {
167  he->p.ui8p[sfi->otherFileNum] = RPMFILE_STATE_REPLACED;
168  if (modified == 0) {
169  /* Modified header will be rewritten. */
170  modified = 1;
171  xx = rpmmiSetModified(mi, modified);
172  }
173  num++;
174  }
175  sfi++;
176  }
177  he->p.ptr = _free(he->p.ptr);
178  }
179  mi = rpmmiFree(mi);
180 
181  return RPMRC_OK;
182 }
183 #endif
184 
185 static rpmRC createDir(rpmts ts, rpmfi fi, const char ** fn, const char * name)
186  /*@globals rpmGlobalMacroContext @*/
187  /*@modifies *fn, rpmGlobalMacroContext @*/
188 {
189  const char * N = rpmGenPath(rpmtsRootDir(ts), name, "");
190  char * t = xstrdup(name+2);
191  rpmRC rc;
192 
193  t[strlen(t)-1] = '\0';
194 
195  rc = rpmMkdirPath(N, t+1);
196  if (rc != RPMRC_OK) {
197  if (Access(N, W_OK))
198  rpmlog(RPMLOG_ERR, _("cannot write to %%%s %s\n"), t, N);
199  else if (fi && Chown(N, fi->uid, fi->gid)) /* XXX coverity #1035724 */
200  rpmlog(RPMLOG_ERR, _("cannot chown %%%s %s\n"), t, N);
201  }
202 
203  if (fn)
204  *fn = N;
205  else
206  N = _free(N);
207  t = _free(t);
208 
209  return rc;
210 }
211 
213  const char ** specFilePtr, const char ** cookie)
214 {
215  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
216  FD_t fd = (FD_t) _fd;
217  rpmfi fi = NULL;
218  rpmte p = NULL;
219  rpmpsm psm = NULL;
220  Header h = NULL;
221  int isSource;
222  rpmRC rc;
223  int i;
224 
225 /*@-mods@*/ /* Avoid void * _fd annotations for now. */
226  rc = rpmReadPackageFile(ts, fd, __FUNCTION__, &h);
227 /*@=mods@*/
228  switch (rc) {
229  case RPMRC_NOTTRUSTED:
230  case RPMRC_NOKEY:
231  case RPMRC_OK:
232  break;
233  default:
234  goto exit;
235  /*@notreached@*/ break;
236  }
237  if (h == NULL)
238  goto exit;
239 
240  rc = RPMRC_FAIL; /* assume failure */
241 
242  isSource =
243  (headerIsEntry(h, RPMTAG_SOURCERPM) == 0 &&
244  headerIsEntry(h, RPMTAG_ARCH) != 0);
245 
246  if (!isSource) {
247  rpmlog(RPMLOG_ERR, _("source package expected, binary found\n"));
248  goto exit;
249  }
250 
251  (void) rpmtsAddInstallElement(ts, h, NULL, 0, NULL);
252 
253  p = rpmtsElement(ts, 0);
254 assert(p->h == NULL);
255  (void) rpmteSetHeader(p, h);
256 /*@-mods@*/ /* LCL: avoid void * _fd annotation for now. */
257 /*@-assignexpose -castexpose -temptrans @*/
258  p->fd = fdLink(fd, __FUNCTION__);
259 /*@=assignexpose =castexpose =temptrans @*/
260 /*@=mods@*/
261 
262  fi = rpmteFI(p, RPMTAG_BASENAMES);
263  fi->h = headerLink(h);
264 /*@-onlytrans@*/ /* FIX: te reference */
265  fi->te = p;
266 /*@=onlytrans@*/
267 
268  /* XXX FIXME: don't do per-file mapping, force global flags. */
269  fi->fmapflags = _free(fi->fmapflags);
271 
272  fi->uid = getuid();
273  fi->gid = getgid();
274 #if defined(RPM_VENDOR_OPENPKG) /* switch-from-susr-to-musr-on-srpm-install */
275  /* If running as the OpenPKG "susr", do not unpack source RPM
276  packages with "susr" file ownerships as the OpenPKG Set-UID
277  wrapper switches from "musr" to "susr" on "openpkg rpm -Uvh
278  *.src.rpm". As a result the installed files could be never
279  removed again by "musr". It is more consistent to always unpack
280  as "musr" if possible. */
281  if (fi->uid == 0) {
282  char *muid_str;
283  char *mgid_str;
284  uid_t muid;
285  gid_t mgid;
286  if ((muid_str = rpmExpand("%{l_muid}", NULL)) != NULL)
287  if ((muid = (uid_t)strtol(muid_str, (char **)NULL, 10)) > 0)
288  fi->uid = muid;
289  if ((mgid_str = rpmExpand("%{l_mgid}", NULL)) != NULL)
290  if ((mgid = (gid_t)strtol(mgid_str, (char **)NULL, 10)) > 0)
291  fi->gid = mgid;
292  }
293 #endif
294  for (i = 0; i < (int)fi->fc; i++)
295  fi->actions[i] = FA_CREATE;
296 
297  /* Load relative (in a *.src.rpm) file paths as an argv array. */
298  fi->astriplen = 0;
299  fi->striplen = 0;
300  he->tag = RPMTAG_FILEPATHS;
301  if (!headerGet(h, he, 0) || he->p.argv == NULL || he->p.argv[0] == NULL)
302  goto exit;
303  fi->apath = he->p.argv;
304 
305  (void) headerMacrosLoad(h);
306 
307 #if defined(RPM_VENDOR_OPENPKG) /* switch-from-susr-to-musr-on-srpm-install */
308  if (createDir(ts, fi, NULL, "%{_topdir}")
309  || createDir(ts, fi, NULL, "%{_builddir}")
310  || createDir(ts, fi, NULL, "%{_rpmdir}")
311  || createDir(ts, fi, NULL, "%{_srcrpmdir}")
312  || createDir(ts, fi, NULL, "%{_sourcedir}")
313  || createDir(ts, fi, NULL, "%{_specdir}"))
314 #else
315  if (createDir(ts, NULL, NULL, "%{_topdir}")
316  || createDir(ts, NULL, NULL, "%{_builddir}")
317  || createDir(ts, NULL, NULL, "%{_rpmdir}")
318  || createDir(ts, NULL, NULL, "%{_srcrpmdir}")
319  || createDir(ts, NULL, NULL, "%{_sourcedir}")
320  || createDir(ts, NULL, NULL, "%{_specdir}"))
321 #endif
322  goto exit;
323 
324  /* Retrieve build cookie. */
325  if (cookie) {
326  *cookie = NULL;
327  he->tag = RPMTAG_COOKIE;
328  if (headerGet(h, he, 0)) *cookie = he->p.str;
329  }
330 
331  /* Find spec file path. */
332  if (specFilePtr) {
333  *specFilePtr = NULL;
334  fi = rpmfiInit(fi, 0);
335  while ((i = rpmfiNext(fi)) >= 0) {
336  if (!(rpmfiFFlags(fi) & RPMFILE_SPECFILE))
337  continue;
338  *specFilePtr = xstrdup(rpmfiFN(fi));
339  break;
340  }
341  if (*specFilePtr == NULL) {
342  rpmlog(RPMLOG_ERR, _("source package contains no .spec file\n"));
343  goto exit;
344  }
345  }
346 
347  /* Unpack the SRPM contents. */
348  psm = rpmpsmNew(ts, p, fi);
349  psm->goal = PSM_PKGINSTALL;
350  rc = rpmpsmStage(psm, PSM_PROCESS);
351  (void) rpmpsmStage(psm, PSM_FINI);
352  psm = rpmpsmFree(psm, __FUNCTION__);
353 
354 exit:
355  if (rc != RPMRC_OK) {
356  if (specFilePtr) *specFilePtr = _free(*specFilePtr);
357  if (cookie) *cookie = _free(*cookie);
358  }
359 
360  if (fi)
361  fi->te = NULL;
362 
363  if (p) {
364  (void) rpmteSetHeader(p, NULL);
365 /*@-mods@*/ /* Avoid void * _fd annotations for now. */
366  if (p->fd != NULL)
367  (void) Fclose(p->fd);
368 /*@=mods@*/
369  p->fd = NULL;
370  }
371 
372  /* XXX nuke the added package(s). */
373  rpmtsClean(ts);
374 
375  (void) headerFree(h);
376  h = NULL;
377 
378  return rc;
379 }
380 
381 /*@observer@*/ /*@unchecked@*/
382 static const char * SCRIPT_PATH =
383  "PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin";
384 
390 static /*@observer@*/ const char * tag2sln(rpmTag tag)
391  /*@*/
392 {
393  switch (tag) {
394  case RPMTAG_PRETRANS: return "%pretrans";
395  case RPMTAG_TRIGGERPREIN: return "%triggerprein";
396  case RPMTAG_PREIN: return "%pre";
397  case RPMTAG_POSTIN: return "%post";
398  case RPMTAG_TRIGGERIN: return "%triggerin";
399  case RPMTAG_TRIGGERUN: return "%triggerun";
400  case RPMTAG_PREUN: return "%preun";
401  case RPMTAG_POSTUN: return "%postun";
402  case RPMTAG_POSTTRANS: return "%posttrans";
403  case RPMTAG_TRIGGERPOSTUN: return "%triggerpostun";
404  case RPMTAG_VERIFYSCRIPT: return "%verify";
405  case RPMTAG_SANITYCHECK: return "%sanitycheck";
406  case RPMTAG_BUILDPREP: return "%prep";
407  case RPMTAG_BUILDBUILD: return "%build";
408  case RPMTAG_BUILDINSTALL: return "%install";
409  case RPMTAG_BUILDCHECK: return "%check";
410  default: break;
411  }
412  return "%unknownscript";
413 }
414 
421  /*@*/
422 {
423  switch (tag) {
424  case RPMTAG_PRETRANS: return RPMSCRIPT_PRETRANS;
426  case RPMTAG_PREIN: return RPMSCRIPT_PREIN;
427  case RPMTAG_POSTIN: return RPMSCRIPT_POSTIN;
430  case RPMTAG_PREUN: return RPMSCRIPT_PREUN;
431  case RPMTAG_POSTUN: return RPMSCRIPT_POSTUN;
436  case RPMTAG_BUILDPREP: return RPMSCRIPT_PREP;
437  case RPMTAG_BUILDBUILD: return RPMSCRIPT_BUILD;
439  case RPMTAG_BUILDCHECK: return RPMSCRIPT_CHECK;
440  default: break;
441  }
442  return RPMSCRIPT_MAX;
443 }
444 
450 static pid_t psmWait(rpmpsm psm)
451  /*@globals fileSystem, internalState @*/
452  /*@modifies psm, fileSystem, internalState @*/
453 {
454  const rpmts ts = psm->ts;
455  rpmtime_t msecs;
456 
457  (void) rpmsqWait(&psm->sq);
458  msecs = psm->sq.op.usecs/1000;
459  (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_SCRIPTLETS), &psm->sq.op);
460 
462  D_("%s: waitpid(%d) rc %d status %x secs %u.%03u\n"),
463  psm->stepName, (unsigned)psm->sq.child,
464  (unsigned)psm->sq.reaped, psm->sq.status,
465  (unsigned)msecs/1000, (unsigned)msecs%1000);
466 
467  if (psm->sstates != NULL)
468  { rpmuint32_t * ssp = psm->sstates + tag2slx(psm->scriptTag);
469  *ssp &= ~0xffff;
470  *ssp |= (psm->sq.status & 0xffff);
471  *ssp |= RPMSCRIPT_STATE_REAPED;
472  }
473 
474  return psm->sq.reaped;
475 }
476 
477 #ifdef WITH_LUA
478 
489 static rpmRC runLuaScript(rpmpsm psm, const char * sln, HE_t Phe,
490  const char *script, int arg1, int arg2)
491  /*@globals fileSystem, internalState @*/
492  /*@modifies psm, fileSystem, internalState @*/
493 {
494  rpmRC rc = RPMRC_OK;
495  int xx;
496  rpmlua lua = NULL; /* Global state. */
497  rpmluav var;
498 
499  /* Create arg variable */
500  rpmluaPushTable(lua, "arg");
501  var = rpmluavNew();
502  rpmluavSetListMode(var, 1);
503 /*@+relaxtypes@*/
504  if (Phe->p.argv) {
505  int i;
506  for (i = 0; i < (int)Phe->c && Phe->p.argv[i]; i++) {
507  rpmluavSetValue(var, RPMLUAV_STRING, Phe->p.argv[i]);
508  rpmluaSetVar(lua, var);
509  }
510  }
511  if (arg1 >= 0) {
512  rpmluavSetValueNum(var, arg1);
513  rpmluaSetVar(lua, var);
514  }
515  if (arg2 >= 0) {
516  rpmluavSetValueNum(var, arg2);
517  rpmluaSetVar(lua, var);
518  }
519 /*@=relaxtypes@*/
520 /*@-moduncon@*/
521  var = (rpmluav) rpmluavFree(var);
522 /*@=moduncon@*/
523  rpmluaPop(lua);
524 
525  { char buf[BUFSIZ];
526  xx = snprintf(buf, BUFSIZ, "%s(%s)", sln, psm->NVRA);
527  xx = rpmluaRunScript(lua, script, buf);
528  if (xx == -1) {
529  void * ptr = rpmtsNotify(psm->ts, psm->te, RPMCALLBACK_SCRIPT_ERROR,
530  psm->scriptTag, 1);
531  ptr = ptr; /* XXX keep gcc happy. */
532  rc = RPMRC_FAIL;
533  } else
534  rc = RPMRC_OK;
535  }
536  rpmluaDelVar(lua, "arg");
537 
538  return rc;
539 }
540 #endif /* WITH_LUA */
541 
542 #if defined(_WITH_EMBEDDED)
543 static int enterChroot(rpmpsm psm, int * pwdFdnop, int * rootFdnop)
544  /*@globals fileSystem, internalState @*/
545  /*@modifies *pwdFdnop, *rootFdnop, fileSystem, internalState @*/
546 {
547  const rpmts ts = psm->ts;
548  int inChroot;
549  int xx;
550 
551  /* Save the current working directory. */
552  if (pwdFdnop)
553  (*pwdFdnop) = open(".", O_RDONLY, 0);
554 
555  /* Save the current root directory. */
556  if (rootFdnop)
557  (*rootFdnop) = open("/", O_RDONLY, 0);
558 
559  /* Get into the chroot. */
560  if (!rpmtsChrootDone(ts)) {
561  const char *rootDir = rpmtsRootDir(ts);
562  inChroot = 0;
563  /*@-modobserver @*/
564  if (rootDir != NULL && strcmp(rootDir, "/") && *rootDir == '/') {
565  xx = Chroot(rootDir);
566  /*@=modobserver @*/
567  xx = rpmtsSetChrootDone(ts, 1);
568  }
569  } else
570  inChroot = 1;
571 
572  /* All embedded scriptlets run with CWD == "/". */
573  xx = Chdir("/");
574 
575  return inChroot;
576 }
577 
578 static int exitChroot(rpmpsm psm, int inChroot, int pwdFdno, int rootFdno)
579  /*@globals fileSystem, internalState @*/
580  /*@modifies psm, fileSystem, internalState @*/
581 {
582  const rpmts ts = psm->ts;
583  const char *rootDir = rpmtsRootDir(ts);
584  int xx;
585 
586  if (rpmtsChrootDone(ts) && !inChroot) {
587  xx = fchdir(rootFdno);
588 /*@-modobserver@*/
589  if (rootDir != NULL && strcmp(rootDir, "/") && *rootDir == '/') {
590  xx = Chroot(".");
591 /*@=modobserver@*/
592  xx = rpmtsSetChrootDone(ts, 0);
593  }
594  xx = fchdir(pwdFdno);
595  } else
596  xx = fchdir(pwdFdno);
597 
598  xx = close(rootFdno);
599  xx = close(pwdFdno);
600 
601  return 0;
602 }
603 
615 static rpmRC runEmbeddedScript(rpmpsm psm, const char * sln, HE_t Phe,
616  const char *script, int arg1, int arg2)
617  /*@globals fileSystem, internalState @*/
618  /*@modifies psm, fileSystem, internalState @*/
619 {
620  char * av[] = { NULL, NULL, NULL, NULL };
621  int pwdFdno = -1;
622  int rootFdno = -1;
623  rpmRC rc = RPMRC_OK;
624  int xx = 0;
625  rpmuint32_t * ssp = NULL;
626  int inChroot = enterChroot(psm, &pwdFdno, &rootFdno);
627 
628  if (psm->sstates != NULL)
629  ssp = psm->sstates + tag2slx(psm->scriptTag);
630  if (ssp != NULL)
632 
633  av[0] = (char *) Phe->p.argv[0];
634  /* XXX coverity #1035772 */
635  if (arg1 >= 0) {
636  av[1] = (char *) alloca(32);
637  (void) sprintf(av[1], "%d", arg1);
638  }
639  if (arg2 >= 0) {
640  av[2] = (char *) alloca(32);
641  (void) sprintf(av[2], "%d", arg2);
642  }
643 
644 #if defined(WITH_LUA)
645  if (!strcmp(Phe->p.argv[0], "<lua>")) {
646  rc = runLuaScript(psm, sln, Phe, script, arg1, arg2);
647  } else
648 #endif
649 #if defined(WITH_AUGEAS)
650  if (!strcmp(Phe->p.argv[0], "<augeas>")) {
651  /* XXX change rpmaugNew() to common embedded interpreter API */
652  rpmaug aug = NULL;
653  rc = rpmaugRun(aug, script, NULL) == RPMRC_OK
654  ? RPMRC_OK : RPMRC_FAIL;
655  aug = rpmaugFree(aug);
656  } else
657 #endif
658 #if defined(WITH_FICL)
659  if (!strcmp(Phe->p.argv[0], "<ficl>")) {
660  rpmficl ficl = rpmficlNew((char **)av, 0);
661  rc = rpmficlRun(ficl, script, NULL) == RPMRC_OK
662  ? RPMRC_OK : RPMRC_FAIL;
663  ficl = rpmficlFree(ficl);
664  } else
665 #endif
666 #if defined(WITH_JNIEMBED)
667  if (!strcmp(Phe->p.argv[0], "<java>")) {
668  rpmjni jni = rpmjniNew((char **)av, 0);
669  rc = rpmjniRun(jni, script, NULL) == RPMRC_OK
670  ? RPMRC_OK : RPMRC_FAIL;
671  jni = rpmjniFree(jni);
672  } else
673 #endif
674 #if defined(WITH_GPSEE)
675  if (!strcmp(Phe->p.argv[0], "<js>")) {
676  rpmjs js = rpmjsNew((char **)av, 0);
677  rc = rpmjsRun(js, script, NULL) == RPMRC_OK
678  ? RPMRC_OK : RPMRC_FAIL;
679  js = rpmjsFree(js);
680  } else
681 #endif
682 #if defined(WITH_MRBEMBED)
683  if (!strcmp(Phe->p.argv[0], "<mruby>")) {
684  rpmmrb mrb = rpmmrbNew((char **)av, 0);
685  rc = rpmmrbRun(mrb, script, NULL) == RPMRC_OK
686  ? RPMRC_OK : RPMRC_FAIL;
687  mrb = rpmmrbFree(mrb);
688  } else
689 #endif
690 #if defined(WITH_PERLEMBED)
691  if (!strcmp(Phe->p.argv[0], "<perl>")) {
692  rpmperl perl = rpmperlNew((char **)av, 0);
693  rc = rpmperlRun(perl, script, NULL) == RPMRC_OK
694  ? RPMRC_OK : RPMRC_FAIL;
695  perl = rpmperlFree(perl);
696  } else
697 #endif
698 #if defined(WITH_PYTHONEMBED)
699  if (!strcmp(Phe->p.argv[0], "<python>")) {
700  rpmpython python = rpmpythonNew((char **)av, 0);
701  rc = rpmpythonRun(python, script, NULL) == RPMRC_OK
702  ? RPMRC_OK : RPMRC_FAIL;
703  python = rpmpythonFree(python);
704  } else
705 #endif
706 #if defined(WITH_RUBYEMBED)
707  if (!strcmp(Phe->p.argv[0], "<ruby>")) {
708  rpmruby ruby = rpmrubyNew((char **)av, 0);
709  rc = rpmrubyRun(ruby, script, NULL) == RPMRC_OK
710  ? RPMRC_OK : RPMRC_FAIL;
711  ruby = rpmrubyFree(ruby);
712  } else
713 #endif
714 #if defined(WITH_SEMANAGE)
715  if (!strcmp(Phe->p.argv[0], "<spook>")) {
716  /* XXX change rpmsmNew() to common embedded interpreter API */
717  rpmsm sm = NULL;
718  /* XXX HACK: use an argv for now. */
719  const char * av[2];
720  av[0] = script;
721  av[1] = NULL;
722  rc = rpmsmRun(sm, (char **)av, NULL) == RPMRC_OK
723  ? RPMRC_OK : RPMRC_FAIL;
724  sm = rpmsmFree(sm);
725  } else
726 #endif
727 #if defined(WITH_SQLITE)
728  if (!strcmp(Phe->p.argv[0], "<sql>")) {
729  int Pac = Phe->c;
730  const char ** Pav = (const char **) xmalloc((Pac + 1) * sizeof(*Pav));
731  const char * result = NULL;
732  rpmsql sql;
733  int i;
734 
735  /* XXX ignore $1/$2, copy the tag array instead. */
736  /* XXX no NULL sentinel in tag arrays. */
737  for (i = 0; i < Pac; i++)
738  Pav[i] = rpmExpand(Phe->p.argv[i], NULL);
739  Pav[Pac] = NULL;
740 
741  sql = rpmsqlNew((char **)Pav, 0);
742  rc = rpmsqlRun(sql, script, &result) == RPMRC_OK
743  ? RPMRC_OK : RPMRC_FAIL;
744  sql = rpmsqlFree(sql);
745  Pav = argvFree(Pav);
746  } else
747 #endif
748 #if defined(WITH_SQUIRREL)
749  if (!strcmp(Phe->p.argv[0], "<squirrel>")) {
750  rpmsquirrel squirrel = rpmsquirrelNew((char **)av, 0);
751  rc = rpmsquirrelRun(squirrel, script, NULL) == RPMRC_OK
752  ? RPMRC_OK : RPMRC_FAIL;
753  squirrel = rpmsquirrelFree(squirrel);
754  } else
755 #endif
756 #if defined(WITH_TCL)
757  if (!strcmp(Phe->p.argv[0], "<tcl>")) {
758  rpmtcl tcl = rpmtclNew((char **)av, 0);
759  rc = rpmtclRun(tcl, script, NULL) == RPMRC_OK
760  ? RPMRC_OK : RPMRC_FAIL;
761  tcl = rpmtclFree(tcl);
762  } else
763 #endif
764  rc = RPMRC_NOTFOUND;
765 
766  if (ssp != NULL) {
767  *ssp &= ~0xffff;
768  *ssp |= (xx & 0xffff);
769  *ssp |= RPMSCRIPT_STATE_REAPED;
770  }
771 
772  xx = exitChroot(psm, inChroot, pwdFdno, rootFdno);
773 
774  return rc;
775 }
776 #endif
777 
780 /*@unchecked@*/
781 static int ldconfig_done = 0;
782 
783 /*@unchecked@*/ /*@observer@*/ /*@null@*/
784 static const char * ldconfig_path = "/sbin/ldconfig";
785 
802 static rpmRC runScript(rpmpsm psm, Header h, const char * sln, HE_t Phe,
803  const char * script, int arg1, int arg2)
804  /*@globals ldconfig_done, rpmGlobalMacroContext, h_errno,
805  fileSystem, internalState@*/
806  /*@modifies psm, ldconfig_done, rpmGlobalMacroContext,
807  fileSystem, internalState @*/
808 {
809  const rpmts ts = psm->ts;
810  const char * NVRA = psm->NVRA;
811  HE_t IPhe = psm->IPhe;
812  const char ** argv = NULL;
813  int argc = 0;
814  const char ** IP = NULL;
815  int nIP;
816  size_t maxPrefixLength;
817  size_t len;
818  char * prefixBuf = NULL;
819  const char * fn = NULL;
820  FD_t scriptFd = NULL;
821  FD_t out = NULL; /* exit: expects this to be initialized. */
822  rpmRC rc = RPMRC_FAIL; /* assume failure */
823  const char * body = NULL;
824  rpmop op = (rpmop) memset(alloca(sizeof(*op)), 0, sizeof(*op));
825  int ix = tag2slx(psm->scriptTag);
826  rpmuint32_t * ssp = NULL;
827  pid_t pid;
828  int xx;
829  int i;
830 
831  if (psm->sstates != NULL && ix >= 0 && ix < RPMSCRIPT_MAX)
832  ssp = psm->sstates + ix;
833  if (ssp != NULL)
835 
836  if (Phe->p.argv == NULL && script == NULL)
837  return RPMRC_OK;
838 
839  /* Macro expand all scriptlets. */
840  body = rpmExpand(script, NULL);
841 
842  /* XXX Load NVRA lazily. This should be done elsewhere ... */
843  if (NVRA == NULL) {
844  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
845  he->tag = RPMTAG_NVRA;
846  xx = headerGet(h, he, 0);
847 assert(he->p.str != NULL);
848  psm->NVRA = NVRA = he->p.str;
849  }
850 
851  if (op != NULL)
852  (void) rpmswEnter(op, 0);
853 
854  if (Phe->p.argv && Phe->p.argv[0])
855  if (!strcmp(Phe->p.argv[0], "<lua>")
856  || !strcmp(Phe->p.argv[0], "<augeas>")
857  || !strcmp(Phe->p.argv[0], "<ficl>")
858  || !strcmp(Phe->p.argv[0], "<java>")
859  || !strcmp(Phe->p.argv[0], "<js>")
860  || !strcmp(Phe->p.argv[0], "<mruby>")
861  || !strcmp(Phe->p.argv[0], "<perl>")
862  || !strcmp(Phe->p.argv[0], "<python>")
863  || !strcmp(Phe->p.argv[0], "<ruby>")
864  || !strcmp(Phe->p.argv[0], "<sql>")
865  || !strcmp(Phe->p.argv[0], "<squirrel>")
866  || !strcmp(Phe->p.argv[0], "<tcl>"))
867  {
868 #if defined(_WITH_EMBEDDED)
870  D_("%s: %s(%s) running %s scriptlet.\n"),
871  psm->stepName, tag2sln(psm->scriptTag), NVRA, Phe->p.argv[0]);
872  rc = runEmbeddedScript(psm, sln, Phe, body, arg1, arg2);
873 #endif
874  goto exit;
875  }
876 
877  psm->sq.reaper = 1;
878 
879  /*
880  * If a successor node, and ldconfig was just run, don't bother.
881  */
882  if (ldconfig_path && Phe->p.argv != NULL && F_ISSET(psm, UNORDERED)) {
883  if (ldconfig_done && !strcmp(Phe->p.argv[0], ldconfig_path)) {
885  D_("%s: %s(%s) skipping redundant \"%s\".\n"),
886  psm->stepName, tag2sln(psm->scriptTag), NVRA,
887  Phe->p.argv[0]);
888  rc = RPMRC_OK;
889  goto exit;
890  }
891  }
892 
894  D_("%s: %s(%s) %ssynchronous scriptlet start\n"),
895  psm->stepName, tag2sln(psm->scriptTag), NVRA,
896  (F_ISSET(psm, UNORDERED) ? "a" : ""));
897 
898  if (Phe->p.argv == NULL) {
899  argv = (const char **) alloca(5 * sizeof(*argv));
900  argv[0] = "/bin/sh";
901  argc = 1;
902  ldconfig_done = 0;
903  } else {
904  argv = (const char **) alloca((Phe->c + 4) * sizeof(*argv));
905  memcpy(argv, Phe->p.argv, Phe->c * sizeof(*argv));
906  argc = Phe->c;
907  ldconfig_done = (ldconfig_path && !strcmp(argv[0], ldconfig_path)
908  ? 1 : 0);
909  }
910 
911  /* XXX Load INSTPREFIXES lazily. This should be done elsewhere ... */
912  if (IPhe->tag == 0) {
913  IPhe->tag = RPMTAG_INSTPREFIXES;
914  xx = headerGet(h, IPhe, 0);
915  if (!xx) {
916  IPhe->p.ptr = _free(IPhe->p.ptr);
917  IPhe->tag = RPMTAG_INSTALLPREFIX;
918  xx = headerGet(h, IPhe, 0);
919  if (xx) {
920  const char ** av = (const char **)
921  xmalloc(sizeof(*av) + strlen(IPhe->p.argv[0]) + 1);
922  char * t = (char *) &av[1];
923 
924  av[0] = t;
925  t = stpcpy(t, IPhe->p.argv[0]);
926  *t = '\0';
927  IPhe->p.ptr = _free(IPhe->p.ptr);
928  IPhe->t = RPM_STRING_ARRAY_TYPE;
929  IPhe->p.argv = av;
930  IPhe->c = 1;
931  } else {
932  IPhe->p.argv = NULL;
933  IPhe->c = 0;
934  }
935  }
936  }
937  IP = IPhe->p.argv;
938  nIP = IPhe->c;
939 
940  maxPrefixLength = 0;
941  if (IP != NULL)
942  for (i = 0; i < nIP; i++) {
943  len = strlen(IP[i]);
944  if (len > maxPrefixLength) maxPrefixLength = len;
945  }
946  prefixBuf = (char *) alloca(maxPrefixLength + 50);
947 
948  if (script) {
949  const char * rootDir = rpmtsRootDir(ts);
950  FD_t fd;
951  size_t nw;
952 
953  if (rpmTempFile((!rpmtsChrootDone(ts) ? rootDir : "/"), &fn, &fd))
954  goto exit;
955 
956  if (rpmIsDebug() &&
957  (!strcmp(argv[0], "/bin/sh") || !strcmp(argv[0], "/bin/bash")))
958  {
959  static const char set_x[] = "set -x\n";
960  nw = Fwrite(set_x, sizeof(set_x[0]), sizeof(set_x)-1, fd);
961  }
962 
963  if (ldconfig_path && strstr(body, ldconfig_path) != NULL)
964  ldconfig_done = 1;
965 
966  nw = Fwrite(body, sizeof(body[0]), strlen(body), fd);
967  xx = Fclose(fd);
968 
969  { const char * sn = fn;
970  if (!rpmtsChrootDone(ts) && rootDir != NULL &&
971  !(rootDir[0] == '/' && rootDir[1] == '\0'))
972  {
973  sn += strlen(rootDir)-1;
974  }
975  argv[argc++] = sn;
976  }
977 
978  if (arg1 >= 0) {
979  char *av = (char *) alloca(20);
980  sprintf(av, "%d", arg1);
981  argv[argc++] = av;
982  }
983  if (arg2 >= 0) {
984  char *av = (char *) alloca(20);
985  sprintf(av, "%d", arg2);
986  argv[argc++] = av;
987  }
988  }
989 
990  argv[argc] = NULL;
991 
992  /* Log the scriptlet to be exec'd. */
993  switch (psm->scriptTag) {
994  default:
995  break;
996  case RPMTAG_PREIN:
997  (void) rpmlioPrein(rpmtsGetRdb(ts), argv, body);
998  break;
999  case RPMTAG_POSTIN:
1000  (void) rpmlioPostin(rpmtsGetRdb(ts), argv, body);
1001  break;
1002  case RPMTAG_PREUN:
1003  (void) rpmlioPreun(rpmtsGetRdb(ts), argv, body);
1004  break;
1005  case RPMTAG_POSTUN:
1006  (void) rpmlioPostun(rpmtsGetRdb(ts), argv, body);
1007  break;
1008  }
1009 
1010  scriptFd = rpmtsScriptFd(ts);
1011  if (scriptFd != NULL) {
1012  if (rpmIsVerbose()) {
1013  out = fdDup(Fileno(scriptFd));
1014  } else {
1015  out = Fopen("/dev/null", "w.fdio");
1016  if (Ferror(out)) {
1017  out = fdDup(Fileno(scriptFd));
1018  }
1019  }
1020  } else {
1021  out = fdDup(STDOUT_FILENO);
1022  }
1023  if (out == NULL) /* XXX can't happen */
1024  goto exit;
1025 
1026  pid = rpmsqFork(&psm->sq);
1027  if (psm->sq.child == 0) {
1028  int pipes[2];
1029  int flag;
1030  int fdno;
1031 
1032  pipes[0] = pipes[1] = 0;
1033  /* Make stdin inaccessible */
1034  xx = pipe(pipes);
1035  xx = close(pipes[1]);
1036  xx = dup2(pipes[0], STDIN_FILENO);
1037  xx = close(pipes[0]);
1038 
1039  /* XXX Force FD_CLOEXEC on 1st 100 inherited fdno's. */
1040  for (fdno = 3; fdno < 100; fdno++) {
1041  flag = fcntl(fdno, F_GETFD);
1042  if (flag == -1 || (flag & FD_CLOEXEC))
1043  continue;
1045  D_("%s: %s(%s)\tfdno(%d) missing FD_CLOEXEC\n"),
1046  psm->stepName, sln, NVRA,
1047  fdno);
1048  xx = fcntl(fdno, F_SETFD, FD_CLOEXEC);
1049  /* XXX W2DO? debug msg for inheirited fdno w/o FD_CLOEXEC */
1050  }
1051 
1052  if (scriptFd != NULL) {
1053  int sfdno = Fileno(scriptFd);
1054  int ofdno = Fileno(out);
1055  if (sfdno != STDERR_FILENO)
1056  xx = dup2(sfdno, STDERR_FILENO);
1057  if (ofdno != STDOUT_FILENO)
1058  xx = dup2(ofdno, STDOUT_FILENO);
1059  /* make sure we don't close stdin/stderr/stdout by mistake! */
1060  if (ofdno > STDERR_FILENO && ofdno != sfdno)
1061  xx = Fclose (out);
1062  if (sfdno > STDERR_FILENO && ofdno != sfdno)
1063  xx = Fclose (scriptFd);
1064  }
1065 
1066  { const char *ipath = rpmExpand("PATH=%{_install_script_path}", NULL);
1067  const char *path = SCRIPT_PATH;
1068 
1069  if (ipath && ipath[5] != '%')
1070  path = ipath;
1071 
1072  xx = doputenv(path);
1073  /*@-modobserver@*/
1074  ipath = _free(ipath);
1075  /*@=modobserver@*/
1076  }
1077 
1078  if (IP != NULL)
1079  for (i = 0; i < nIP; i++) {
1080  sprintf(prefixBuf, "RPM_INSTALL_PREFIX%d=%s", i, IP[i]);
1081  xx = doputenv(prefixBuf);
1082 
1083  /* backwards compatibility */
1084  if (i == 0) {
1085  sprintf(prefixBuf, "RPM_INSTALL_PREFIX=%s", IP[i]);
1086  xx = doputenv(prefixBuf);
1087  }
1088  }
1089 
1090  { const char * rootDir = rpmtsRootDir(ts);
1091  if (!rpmtsChrootDone(ts) && rootDir != NULL &&
1092  !(rootDir[0] == '/' && rootDir[1] == '\0'))
1093  {
1094  /*@-modobserver@*/
1095  xx = Chroot(rootDir);
1096  /*@=modobserver@*/
1097  }
1098  xx = Chdir("/");
1099  rpmlog(RPMLOG_DEBUG, D_("%s: %s(%s)\texecv(%s) pid %d\n"),
1100  psm->stepName, sln, NVRA,
1101  argv[0], (unsigned)getpid());
1102 
1103  /* XXX Don't mtrace into children. */
1104  unsetenv("MALLOC_CHECK_");
1105 
1106  if (ssp != NULL)
1107  *ssp |= RPMSCRIPT_STATE_EXEC;
1108 
1109  /* Permit libselinux to do the scriptlet exec. */
1110  if (rpmtsSELinuxEnabled(ts) == 1) {
1111  if (ssp != NULL)
1112  *ssp |= RPMSCRIPT_STATE_SELINUX;
1113  xx = rpmsxExec(NULL, 0, argv);
1114  } else {
1115 /*@-nullstate@*/
1116  xx = execv(argv[0], (char *const *)argv);
1117 /*@=nullstate@*/
1118  }
1119  }
1120 
1121  if (ssp != NULL)
1122  *ssp &= ~RPMSCRIPT_STATE_EXEC;
1123 
1124  _exit(-1);
1125  /*@notreached@*/
1126  }
1127 
1128  if (psm->sq.child == (pid_t)-1) {
1129  rpmlog(RPMLOG_ERR, _("Couldn't fork %s: %s\n"), sln, strerror(errno));
1130  goto exit;
1131  }
1132 
1133  (void) psmWait(psm);
1134 
1135  /* XXX filter order dependent multilib "other" arch helper error. */
1136  if (!(psm->sq.reaped >= 0 && !strcmp(argv[0], "/usr/sbin/glibc_post_upgrade") && WEXITSTATUS(psm->sq.status) == 110)) {
1137  void *ptr = NULL;
1138  if (psm->sq.reaped < 0) {
1140  _("%s(%s) scriptlet failed, waitpid(%d) rc %d: %s\n"),
1141  sln, NVRA, (int)psm->sq.child, (int)psm->sq.reaped,
1142  strerror(errno));
1143  goto exit;
1144  } else
1145  if (!WIFEXITED(psm->sq.status) || WEXITSTATUS(psm->sq.status)) {
1146  if (WIFSIGNALED(psm->sq.status)) {
1147  ptr = rpmtsNotify(ts, psm->te, RPMCALLBACK_SCRIPT_ERROR,
1148  psm->scriptTag, WTERMSIG(psm->sq.status));
1150  _("%s(%s) scriptlet failed, signal %d\n"),
1151  sln, NVRA, WTERMSIG(psm->sq.status));
1152  } else {
1153  ptr = rpmtsNotify(ts, psm->te, RPMCALLBACK_SCRIPT_ERROR,
1154  psm->scriptTag, WEXITSTATUS(psm->sq.status));
1156  _("%s(%s) scriptlet failed, exit status %d\n"),
1157  sln, NVRA, WEXITSTATUS(psm->sq.status));
1158  }
1159  goto exit;
1160  }
1161  }
1162 
1163  rc = RPMRC_OK;
1164 
1165 exit:
1166  if (op != NULL) {
1167  static unsigned int scale = 1000;
1168  (void) rpmswExit(op, 0);
1169  if (ix >= 0 && ix < RPMSCRIPT_MAX)
1170  psm->smetrics[ix] += op->usecs / scale;
1171  }
1172 
1173  if (out)
1174  xx = Fclose(out); /* XXX dup'd STDOUT_FILENO */
1175 
1176  if (script) {
1177  if (!rpmIsDebug() && fn != NULL)
1178  xx = Unlink(fn);
1179  fn = _free(fn);
1180  }
1181 
1182  body = _free(body);
1183 
1184  return rc;
1185 }
1186 
1193  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
1194  /*@modifies psm, rpmGlobalMacroContext, fileSystem, internalState @*/
1195 {
1196  HE_t Phe = (HE_t) memset(alloca(sizeof(*Phe)), 0, sizeof(*Phe));
1197  HE_t She = (HE_t) memset(alloca(sizeof(*She)), 0, sizeof(*She));
1198  rpmfi fi = psm->fi;
1199  const char * argv0 = NULL;
1200  rpmRC rc = RPMRC_OK;
1201 
1202 assert(fi->h != NULL);
1203  She->tag = psm->scriptTag;
1204  headerGet(fi->h, She, 0);
1205 
1206  Phe->tag = psm->progTag;
1207  if (!headerGet(fi->h, Phe, 0))
1208  goto exit;
1209 
1210  /* Coerce strings into header argv return. */
1211  if (Phe->t == RPM_STRING_TYPE) {
1212  const char * s = Phe->p.str;
1213  char * t;
1214  Phe->p.argv = (const char **)
1215  xmalloc(sizeof(Phe->p.argv[0]) + strlen(s) + 1);
1216  Phe->p.argv[0] = t = (char *) &Phe->p.argv[1];
1217  t = stpcpy(t, s);
1218  *t = '\0';
1219  s = _free(s);
1220  }
1221 
1222  /* Expand "%script -p %%{interpreter}" macros. */
1223  if (Phe->p.argv[0][0] == '%')
1224  Phe->p.argv[0] = argv0 = rpmExpand(Phe->p.argv[0], NULL);
1225 
1226  rc = runScript(psm, fi->h, tag2sln(psm->scriptTag), Phe,
1227  She->p.str, psm->scriptArg, -1);
1228 
1229 exit:
1230  argv0 = _free(argv0);
1231  Phe->p.ptr = _free(Phe->p.ptr);
1232  She->p.ptr = _free(She->p.ptr);
1233  return rc;
1234 }
1235 
1236 /*@unchecked@*/
1238 
1247 static rpmRC handleOneTrigger(const rpmpsm psm,
1248  Header sourceH, Header triggeredH, int arg2)
1249  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState@*/
1250  /*@modifies psm, sourceH, triggeredH,
1251  rpmGlobalMacroContext, fileSystem, internalState @*/
1252 {
1253  static int scareMem = 0;
1254  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
1255  HE_t Ihe = (HE_t) memset(alloca(sizeof(*Ihe)), 0, sizeof(*Ihe));
1256  HE_t She = (HE_t) memset(alloca(sizeof(*She)), 0, sizeof(*She));
1257  HE_t Phe = (HE_t) memset(alloca(sizeof(*Phe)), 0, sizeof(*Phe));
1258  miRE mire = NULL;
1259  const rpmts ts = psm->ts;
1260  rpmds Tds = NULL;
1261  rpmds Fds = NULL;
1262  rpmds Dds = NULL;
1263  rpmds Pds = NULL;
1264  const char * sourceName;
1265  const char * triggerName;
1266  rpmRC rc = RPMRC_OK;
1267  int arg1;
1268  int xx;
1269  int i;
1270 
1271  he->tag = RPMTAG_NAME;
1272  xx = headerGet(sourceH, he, 0);
1273  sourceName = he->p.str;
1274 
1275  he->tag = RPMTAG_NAME;
1276  xx = headerGet(triggeredH, he, 0);
1277  triggerName = he->p.str;
1278 
1279  arg1 = rpmdbCountPackages(rpmtsGetRdb(ts), triggerName);
1280  if (arg1 < 0) {
1281  /* XXX W2DO? fails as "execution of script failed" */
1282  rc = RPMRC_FAIL;
1283  goto exit;
1284  }
1285  arg1 += psm->countCorrection;
1286 
1287  Tds = rpmdsNew(triggeredH, RPMTAG_TRIGGERNAME, scareMem);
1288  if (Tds == NULL)
1289  goto exit;
1290  xx = rpmdsSetNoPromote(Tds, 1);
1291 
1292  Ihe->tag = RPMTAG_TRIGGERINDEX;
1293  if (!headerGet(triggeredH, Ihe, 0))
1294  goto exit;
1295 
1296  She->tag = RPMTAG_TRIGGERSCRIPTS;
1297  if (!headerGet(triggeredH, She, 0))
1298  goto exit;
1299 
1301  if (!headerGet(triggeredH, Phe, 0))
1302  goto exit;
1303 
1304  if ((Tds = rpmdsInit(Tds)) != NULL)
1305  while ((i = rpmdsNext(Tds)) >= 0) {
1306  rpmuint32_t Flags = rpmdsFlags(Tds);
1307  char * depName;
1308  int bingo;
1309 
1310  /* Skip triggers that are not in this context. */
1311  if (!(Flags & psm->sense))
1312  continue;
1313 
1314  bingo = 0; /* no trigger to fire. */
1315  depName = (char *) rpmdsN(Tds);
1316  if (depName[0] == '/') {
1317  size_t nb = strlen(depName);
1318  if (Glob_pattern_p(depName, 0)) {
1319  rpmds ds = NULL;
1320  if (depName[nb-1] == '/') {
1321  /* XXX Dirnames w trailing "/" needed. */
1322  if (Dds == NULL)
1323  Dds = rpmdsNew(sourceH, RPMTAG_DIRNAMES, 0x2);
1324  ds = rpmdsLink(Dds, "Triggers");
1325  } else {
1326  if (Fds == NULL)
1327  Fds = rpmdsNew(sourceH, RPMTAG_BASENAMES, 0);
1328  ds = rpmdsLink(Fds, "Triggers");
1329  }
1330  if (mire == NULL)
1331  mire = mireNew(RPMMIRE_GLOB, 0);
1332 
1333  xx = mireRegcomp(mire, depName);
1334  if ((ds = rpmdsInit(ds)) != NULL)
1335  while (rpmdsNext(ds) >= 0) {
1336  const char * N = rpmdsN(ds);
1337  xx = mireRegexec(mire, N, 0);
1338  if (xx < 0)
1339  /*@innercontinue@*/ continue;
1340  bingo = 1;
1341  /*@innerbreak@*/ break;
1342  }
1343  (void)rpmdsFree(ds);
1344  ds = NULL;
1345  xx = mireClean(mire);
1346  }
1347 
1348  /* If not matched, and directory trigger, try dir names. */
1349  if (!bingo && depName[nb-1] == '/') {
1350  /* XXX Dirnames w trailing "/" needed. */
1351  if (Dds == NULL)
1352  Dds = rpmdsNew(sourceH, RPMTAG_DIRNAMES, 0x2);
1353  bingo = rpmdsMatch(Tds, Dds);
1354  }
1355 
1356  /* If not matched, try file paths. */
1357  if (!bingo) {
1358  if (Fds == NULL)
1359  Fds = rpmdsNew(sourceH, RPMTAG_BASENAMES, 0);
1360  bingo = rpmdsMatch(Tds, Fds);
1361  }
1362  }
1363 
1364  /* If trigger not fired yet, try provided dependency match. */
1365  if (!bingo) {
1366  if (Pds == NULL)
1367  Pds = rpmdsNew(sourceH, RPMTAG_PROVIDENAME, 0);
1368  bingo = rpmdsMatch(Tds, Pds);
1369  bingo = rpmdsNegateRC(Tds, bingo);
1370  }
1371  if (!bingo)
1372  continue;
1373 
1374  /* Coerce strings into header argv return. */
1375  /* XXX FIXME: permit trigger scripts with arguments. */
1376  { int index = Ihe->p.ui32p[i];
1377  const char * s = Phe->p.argv[index];
1378  char * t;
1379 
1380  he->tag = Phe->tag;
1381  he->t = RPM_STRING_ARRAY_TYPE;
1382  he->c = 1;
1383  he->p.argv = (const char **)
1384  xmalloc(sizeof(Phe->p.argv[0]) + strlen(s) + 1);
1385  he->p.argv[0] = t = (char *) &he->p.argv[1];
1386  t = stpcpy(t, s);
1387  *t = '\0';
1388 
1389  if (runScript(psm, triggeredH, "%trigger", he,
1390  She->p.argv[index], arg1, arg2))
1391  rc = RPMRC_FAIL;
1392 
1393  he->p.ptr = _free(he->p.ptr);
1394  }
1395  }
1396 
1397  mire = mireFree(mire);
1398  (void)rpmdsFree(Pds);
1399  Pds = NULL;
1400  (void)rpmdsFree(Dds);
1401  Dds = NULL;
1402  (void)rpmdsFree(Fds);
1403  Fds = NULL;
1404  (void)rpmdsFree(Tds);
1405  Tds = NULL;
1406 
1407 exit:
1408  Ihe->p.ptr = _free(Ihe->p.ptr);
1409  She->p.ptr = _free(She->p.ptr);
1410  Phe->p.ptr = _free(Phe->p.ptr);
1411  triggerName = _free(triggerName);
1412  sourceName = _free(sourceName);
1413 
1414  return rc;
1415 }
1416 
1417 /* Retrieve trigger patterns from rpmdb. */
1418 static int rpmdbTriggerGlobs(rpmpsm psm)
1419  /*@globals rpmGlobalMacroContext @*/
1420  /*@modifies psm, rpmGlobalMacroContext @*/
1421 {
1422  const rpmts ts = psm->ts;
1423  ARGV_t keys = NULL;
1425  RPMMIRE_STRCMP, NULL, &keys);
1426  int nkeys = argvCount(keys);
1427  int i;
1428 
1429  if (keys)
1430  for (i = 0; i < nkeys; i++) {
1431  char * t = (char *) keys[i];
1432  if (!Glob_pattern_p(t, 0))
1433  continue;
1434  xx = mireAppend(RPMMIRE_GLOB, 0, t, NULL,
1435  (miRE *)&psm->Tmires, &psm->nTmires);
1436  xx = argvAdd(&psm->Tpats, t);
1437  }
1438  keys = argvFree(keys);
1439  return 0;
1440 }
1441 
1449 static rpmRC runTriggersLoop(rpmpsm psm, rpmTag tagno, int arg2)
1450  /*@globals rpmGlobalMacroContext, h_errno,
1451  fileSystem, internalState @*/
1452  /*@modifies psm, rpmGlobalMacroContext,
1453  fileSystem, internalState @*/
1454 {
1455  static int scareMem = 0;
1456  const rpmts ts = psm->ts;
1457  rpmfi fi = psm->fi;
1458  rpmds ds = rpmdsNew(fi->h, tagno, scareMem);
1459  char * depName = NULL;
1460  ARGI_t instances = NULL;
1461  rpmmi mi;
1462  Header triggeredH;
1463  rpmRC rc = RPMRC_OK;
1464  int i;
1465  int xx;
1466 
1467  /* Fire elements against rpmdb trigger strings. */
1468  if ((ds = rpmdsInit(ds)) != NULL)
1469  while ((i = rpmdsNext(ds)) >= 0) {
1470  const char * Name = rpmdsN(ds);
1471  size_t nName = strlen(Name);
1472  unsigned prev, instance;
1473  unsigned nvals;
1474  ARGint_t vals;
1475 
1476  depName = _free(depName);
1477  if (!strcmp(Name, "/"))
1478  depName = xstrdup(Name);
1479  else {
1480  depName = xmalloc(nName + 1 + 1);
1481  (void) stpcpy(depName, Name);
1482  /* XXX re-add the pesky trailing '/' to dirnames. */
1483  depName[nName] = (tagno == RPMTAG_DIRNAMES ? '/' : '\0');
1484  depName[nName+1] = '\0';
1485  }
1486 
1487  if (depName[0] == '/' && psm->Tmires != NULL) {
1488  miRE mire;
1489  int j;
1490 
1491  /* XXX mireApply doesn't tell which pattern matched. */
1492  for (j = 0, mire = (miRE)psm->Tmires; j < psm->nTmires; j++, mire++) {
1493  const char * pattern = psm->Tpats[j];
1494  if (depName[nName-1] != '/') {
1495  size_t npattern = strlen(pattern);
1496  depName[nName] = (pattern[npattern-1] == '/') ? '/' : '\0';
1497  }
1498  if (mireRegexec(mire, depName, 0) < 0)
1499  /*@innercontinue@*/ continue;
1500 
1501  /* Reset the primary retrieval key to the pattern. */
1502  depName = _free(depName);
1503  depName = xstrdup(pattern);
1504  /*@innerbreak@*/ break;
1505  }
1506  }
1507 
1508  /* Retrieve triggered header(s) by key. */
1509  mi = rpmtsInitIterator(ts, RPMTAG_TRIGGERNAME, depName, 0);
1510 
1511  nvals = argiCount(instances);
1512  vals = argiData(instances);
1513  if (nvals > 0)
1514  xx = rpmmiPrune(mi, (uint32_t *)vals, nvals, 1);
1515 
1516  prev = 0;
1517  while((triggeredH = rpmmiNext(mi)) != NULL) {
1518  instance = rpmmiInstance(mi);
1519  if (prev == instance)
1520  /*@innercontinue@*/ continue;
1521  if (handleOneTrigger(psm, fi->h, triggeredH, arg2))
1522  rc = RPMRC_FAIL;
1523  prev = instance;
1524  xx = argiAdd(&instances, -1, instance);
1525  xx = argiSort(instances, NULL);
1526  }
1527 
1528  mi = rpmmiFree(mi);
1529  }
1530 
1531  instances = argiFree(instances);
1532  depName = _free(depName);
1533  (void)rpmdsFree(ds);
1534  ds = NULL;
1535 
1536  return rc;
1537 }
1538 
1545  /*@globals rpmGlobalMacroContext, h_errno,
1546  fileSystem, internalState @*/
1547  /*@modifies psm, rpmGlobalMacroContext,
1548  fileSystem, internalState @*/
1549 {
1550  const rpmts ts = psm->ts;
1551  rpmfi fi = psm->fi;
1552  int numPackage;
1553  rpmTag tagno;
1554  rpmRC rc = RPMRC_OK;
1555 
1556  /* Select RPMTAG_NAME or RPMTAG_PROVIDENAME index for triggering. */
1557  if (_trigger_tag == 0) {
1558  const char * t = rpmExpand("%{?_trigger_tag}", NULL);
1559 /*@-mods@*/
1560  _trigger_tag = (!strcmp(t, "name") ? RPMTAG_NAME : RPMTAG_PROVIDENAME);
1561 /*@=mods@*/
1562  t = _free(t);
1563  }
1564  tagno = _trigger_tag;
1565 
1566 assert(psm->te != NULL);
1567  { const char * N = rpmteN(psm->te);
1568 assert(N != NULL);
1569  numPackage = rpmdbCountPackages(rpmtsGetRdb(ts), N);
1570  numPackage += psm->countCorrection;
1571  if (numPackage < 0)
1572  return RPMRC_NOTFOUND;
1573  }
1574 assert(fi != NULL);
1575 assert(fi->h != NULL);
1576 
1577  /* XXX Save/restore count correction. */
1578  { int countCorrection = psm->countCorrection;
1579 
1580  psm->countCorrection = 0;
1581 
1582  /* Try name/providename triggers first. */
1583  if (runTriggersLoop(psm, tagno, numPackage))
1584  rc = RPMRC_FAIL;
1585 
1586  /* If not limited to NEVRA triggers, also try file/dir path triggers. */
1587  if (tagno != RPMTAG_NAME) {
1588  int xx;
1589  /* Retrieve trigger patterns from rpmdb. */
1590  xx = rpmdbTriggerGlobs(psm);
1591 
1592  if (runTriggersLoop(psm, RPMTAG_BASENAMES, numPackage))
1593  rc = RPMRC_FAIL;
1594  if (runTriggersLoop(psm, RPMTAG_DIRNAMES, numPackage))
1595  rc = RPMRC_FAIL;
1596 
1597  psm->Tpats = argvFree(psm->Tpats);
1598  psm->Tmires = mireFreeAll((miRE)psm->Tmires, psm->nTmires);
1599  psm->nTmires = 0;
1600  }
1601 
1602  psm->countCorrection = countCorrection;
1603  }
1604 
1605  return rc;
1606 }
1607 
1614  /*@globals rpmGlobalMacroContext, h_errno,
1615  fileSystem, internalState @*/
1616  /*@modifies psm, rpmGlobalMacroContext,
1617  fileSystem, internalState @*/
1618 {
1619  HE_t Ihe = (HE_t) memset(alloca(sizeof(*Ihe)), 0, sizeof(*Ihe));
1620  const rpmts ts = psm->ts;
1621  rpmfi fi = psm->fi;
1622  rpmds triggers = NULL;
1623  rpmmi mi;
1624  ARGV_t keys = NULL;
1625  ARGI_t instances = NULL;
1626  Header sourceH = NULL;
1627  const char * Name;
1628  rpmTag tagno;
1629  rpmRC rc = RPMRC_OK;
1630  int i;
1631  int xx;
1632 
1633 assert(fi->h != NULL);
1634 
1635  /* Select RPMTAG_NAME or RPMTAG_PROVIDENAME index for triggering. */
1636  if (_trigger_tag == 0) {
1637  const char * t = rpmExpand("%{?_trigger_tag}", NULL);
1638 /*@-mods@*/
1639  _trigger_tag = (!strcmp(t, "name") ? RPMTAG_NAME : RPMTAG_PROVIDENAME);
1640 /*@=mods@*/
1641  t = _free(t);
1642  }
1643  tagno = _trigger_tag;
1644 
1645 /*@-castexpose@*/
1646  triggers = rpmdsLink(psm->triggers, "ImmedTriggers");
1647 /*@=castexpose@*/
1648  if (triggers == NULL)
1649  goto exit;
1650 
1651  Ihe->tag = RPMTAG_TRIGGERINDEX;
1652  xx = headerGet(fi->h, Ihe, 0);
1653  if (!(xx && Ihe->p.ui32p && Ihe->c)) goto exit;
1654 
1655  /* Collect primary trigger keys, expanding globs as needed. */
1656  triggers = rpmdsInit(triggers);
1657  if (triggers != NULL)
1658  while ((i = rpmdsNext(triggers)) >= 0) {
1659  evrFlags Flags = rpmdsFlags(triggers);
1660  const char * N = rpmdsN(triggers);
1661  const char * EVR = rpmdsEVR(triggers);
1662 
1663  /* Skip triggers that are not in this context. */
1664  if (!(Flags & psm->sense))
1665  continue;
1666 
1667  /* If not limited to NEVRA triggers, use file/dir index. */
1668  if (tagno != RPMTAG_NAME) {
1669  /* XXX if trigger name ends with '/', use dirnames instead. */
1670  if (N[0] == '/')
1671  tagno = (N[strlen(N)-1] == '/')
1673  }
1674  /* XXX For now, permit globs only in unversioned triggers. */
1675  if ((EVR == NULL || *EVR == '\0') && Glob_pattern_p(N, 0))
1676  xx = rpmdbMireApply(rpmtsGetRdb(ts), tagno, RPMMIRE_GLOB, N, &keys);
1677  else
1678  xx = argvAdd(&keys, N);
1679  }
1680  (void)rpmdsFree(triggers);
1681  triggers = NULL;
1682 
1683  /* For all primary keys, retrieve headers and fire triggers. */
1684  if (keys != NULL)
1685  for (i = 0; (Name = keys[i]) != NULL; i++) {
1686  unsigned prev, instance;
1687  unsigned nvals;
1688  ARGint_t vals;
1689 
1690  /* If not limited to NEVRA triggers, use file/dir index. */
1691  if (tagno != RPMTAG_NAME) {
1692  /* XXX if trigger name ends with '/', use dirnames instead. */
1693  if (Name[0] == '/')
1694  tagno = (Name[strlen(Name)-1] == '/')
1696  }
1697 
1698  mi = rpmtsInitIterator(ts, tagno, Name, 0);
1699 
1700  /* Don't retrieve headers that have already been processed. */
1701  nvals = argiCount(instances);
1702  vals = argiData(instances);
1703  if (nvals > 0)
1704  xx = rpmmiPrune(mi, (uint32_t *)vals, nvals, 1);
1705 
1706  prev = 0;
1707  while((sourceH = rpmmiNext(mi)) != NULL) {
1708 
1709  /* Skip headers that have already been processed. */
1710  instance = rpmmiInstance(mi);
1711  if (prev == instance)
1712  /*@innercontinue@*/ continue;
1713 
1714  if (handleOneTrigger(psm, sourceH, fi->h, rpmmiCount(mi)))
1715  rc = RPMRC_FAIL;
1716 
1717  /* Mark header instance as processed. */
1718  prev = instance;
1719  xx = argiAdd(&instances, -1, instance);
1720  xx = argiSort(instances, NULL);
1721  }
1722 
1723  mi = rpmmiFree(mi);
1724  }
1725 
1726 exit:
1727  instances = argiFree(instances);
1728  keys = argvFree(keys);
1729  Ihe->p.ptr = _free(Ihe->p.ptr);
1730  return rc;
1731 }
1732 
1733 /*@observer@*/
1734 static const char * pkgStageString(pkgStage a)
1735  /*@*/
1736 {
1737  switch(a) {
1738  case PSM_UNKNOWN: return "unknown";
1739 
1740  case PSM_PKGINSTALL: return " install";
1741  case PSM_PKGERASE: return " erase";
1742  case PSM_PKGCOMMIT: return " commit";
1743  case PSM_PKGSAVE: return "repackage";
1744 
1745  case PSM_INIT: return "init";
1746  case PSM_PRE: return "pre";
1747  case PSM_PROCESS: return "process";
1748  case PSM_POST: return "post";
1749  case PSM_UNDO: return "undo";
1750  case PSM_FINI: return "fini";
1751 
1752  case PSM_CREATE: return "create";
1753  case PSM_NOTIFY: return "notify";
1754  case PSM_DESTROY: return "destroy";
1755  case PSM_COMMIT: return "commit";
1756 
1757  case PSM_CHROOT_IN: return "chrootin";
1758  case PSM_CHROOT_OUT: return "chrootout";
1759  case PSM_SCRIPT: return "script";
1760  case PSM_TRIGGERS: return "triggers";
1761  case PSM_IMMED_TRIGGERS: return "immedtriggers";
1762 
1763  case PSM_RPMIO_FLAGS: return "rpmioflags";
1764 
1765  case PSM_RPMDB_LOAD: return "rpmdbload";
1766  case PSM_RPMDB_ADD: return "rpmdbadd";
1767  case PSM_RPMDB_REMOVE: return "rpmdbremove";
1768 
1769  default: return "???";
1770  }
1771  /*@noteached@*/
1772 }
1773 
1774 void rpmpsmSetAsync(rpmpsm psm, int async)
1775 {
1776  assert(psm != NULL);
1777 #ifdef REFERENCE
1778  psm->unorderedSuccessor = async;
1779 #else
1780  if (async) {
1781  F_SET(psm, UNORDERED);
1782  } else {
1783  F_CLR(psm, UNORDERED);
1784  }
1785 #endif
1786 }
1787 
1788 rpmRC rpmpsmScriptStage(rpmpsm psm, rpmTag scriptTag, rpmTag progTag)
1789 {
1790 assert(psm != NULL);
1791  psm->scriptTag = scriptTag;
1792  psm->progTag = progTag;
1793  /* XXX other tags needed? */
1794  switch (scriptTag) {
1795  default: break;
1796  case RPMTAG_SANITYCHECK: psm->stepName = "sanitycheck"; break;
1797  case RPMTAG_VERIFYSCRIPT: psm->stepName = "verify"; break;
1798  case RPMTAG_PRETRANS: psm->stepName = "pretrans"; break;
1799  case RPMTAG_POSTTRANS: psm->stepName = "posttrans"; break;
1800  }
1801  return rpmpsmStage(psm, PSM_SCRIPT);
1802 }
1803 
1804 /*@-mustmod@*/
1805 static void rpmpsmFini(void * _psm)
1806  /*@modifies _psm @*/
1807 {
1808  rpmpsm psm = (rpmpsm) _psm;
1809 
1810 /*@-nullstate@*/
1811  psm->fi = rpmfiFree(psm->fi);
1812 #ifdef NOTYET
1813  psm->te = rpmteFree(psm->te);
1814 #else
1815  psm->te = NULL;
1816 #endif
1817 /*@-internalglobs@*/
1818  (void)rpmtsFree(psm->ts);
1819  psm->ts = NULL;
1820 /*@=internalglobs@*/
1821 
1822  psm->IPhe->p.ptr = _free(psm->IPhe->p.ptr);
1823  psm->IPhe = _free(psm->IPhe);
1824  psm->NVRA = _free(psm->NVRA);
1825  (void)rpmdsFree(psm->triggers);
1826  psm->triggers = NULL;
1827 /*@=nullstate@*/
1828 }
1829 /*@=mustmod@*/
1830 
1831 /*@unchecked@*/ /*@only@*/ /*@null@*/
1833 
1835  /*@globals _psmPool, fileSystem, internalState @*/
1836  /*@modifies pool, _psmPool, fileSystem, internalState @*/
1837 {
1838  rpmpsm psm;
1839 
1840  if (_psmPool == NULL) {
1841  _psmPool = rpmioNewPool("psm", sizeof(*psm), -1, _psm_debug,
1842  NULL, NULL, rpmpsmFini);
1843  pool = _psmPool;
1844  }
1845  psm = (rpmpsm) rpmioGetPool(pool, sizeof(*psm));
1846  memset(((char *)psm)+sizeof(psm->_item), 0, sizeof(*psm)-sizeof(psm->_item));
1847  return psm;
1848 }
1849 
1851 {
1852  static const char msg[] = "rpmpsmNew";
1853  rpmpsm psm = rpmpsmGetPool(_psmPool);
1854 
1855 /*@-assignexpose -castexpose @*/
1856  if (ts) psm->ts = rpmtsLink(ts, msg);
1857 #ifdef NOTYET
1858  if (te) psm->te = rpmteLink(te, msg);
1859 #else
1860 /*@-temptrans @*/
1861  if (te) psm->te = te;
1862 /*@=temptrans @*/
1863 #endif
1864  if (fi) psm->fi = rpmfiLink(fi, msg);
1865 /*@=assignexpose =castexpose @*/
1866 
1867  psm->triggers = NULL;
1868  psm->NVRA = NULL;
1869  psm->IPhe = (HE_t) xcalloc(1, sizeof(*psm->IPhe));
1870  memset(psm->sstates, 0, sizeof(psm->sstates));
1871  memset(psm->smetrics, 0, sizeof(psm->smetrics));
1872 
1873  return rpmpsmLink(psm, msg);
1874 }
1875 
1883  /*@globals internalState @*/
1884  /*@modifies internalState @*/
1885 {
1886  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
1887  rpmuint32_t val;
1888  int xx;
1889 
1890  he->tag = tag;
1891  xx = headerGet(h, he, 0);
1892  val = (xx && he->p.ui32p ? he->p.ui32p[0] : 0);
1893  he->p.ptr = _free(he->p.ptr);
1894  return val;
1895 }
1896 
1904 static int hCopyTag(Header sh, Header th, rpmTag tag)
1905  /*@globals internalState @*/
1906  /*@modifies th, internalState @*/
1907 {
1908  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
1909  int xx = 1;
1910 
1911  he->tag = tag;
1912  if (headerGet(sh, he, 0) && he->c > 0)
1913  xx = headerPut(th, he, 0);
1914  he->p.ptr = _free(he->p.ptr);
1915  return 0;
1916 }
1917 
1924 static int hSaveBlinks(Header h, const struct rpmChainLink_s * blink)
1925  /*@modifies h @*/
1926 {
1927  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
1928 /*@observer@*/
1929  static const char * chain_end = RPMTE_CHAIN_END;
1930  int ac;
1931  int xx = 1;
1932 
1933  /* Save forward links into header upgrade chain. */
1934  he->tag = RPMTAG_BLINKNEVRA;
1935  he->t = RPM_STRING_ARRAY_TYPE;
1936  ac = argvCount(blink->NEVRA);
1937  if (ac > 0) {
1938  he->p.argv = argvData(blink->NEVRA);
1939  he->c = ac;
1940  } else { /* XXX Add an explicit chain terminator on 1st install. */
1941  he->p.argv = &chain_end;
1942  he->c = 1;
1943  }
1944  xx = headerPut(h, he, 0);
1945 
1946  he->tag = RPMTAG_BLINKPKGID;
1947  he->t = RPM_STRING_ARRAY_TYPE;
1948  ac = argvCount(blink->Pkgid);
1949  if (ac > 0) {
1950  he->p.argv = argvData(blink->Pkgid);
1951  he->c = ac;
1952  } else { /* XXX Add an explicit chain terminator on 1st install. */
1953  he->p.argv = &chain_end;
1954  he->c = 1;
1955  }
1956  xx = headerPut(h, he, 0);
1957 
1958  he->tag = RPMTAG_BLINKHDRID;
1959  he->t = RPM_STRING_ARRAY_TYPE;
1960  ac = argvCount(blink->Hdrid);
1961  if (ac > 0) {
1962  he->p.argv = argvData(blink->Hdrid);
1963  he->c = ac;
1964  } else { /* XXX Add an explicit chain terminator on 1st install. */
1965  he->p.argv = &chain_end;
1966  he->c = 1;
1967  }
1968  xx = headerPut(h, he, 0);
1969 
1970  return 0;
1971 }
1972 
1979 static int hSaveFlinks(Header h, const struct rpmChainLink_s * flink)
1980  /*@modifies h @*/
1981 {
1982  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
1983 #ifdef NOTYET
1984  /*@observer@*/
1985  static const char * chain_end = RPMTE_CHAIN_END;
1986 #endif
1987  int ac;
1988  int xx = 1;
1989 
1990  /* Save forward links into header upgrade chain. */
1991  he->tag = RPMTAG_FLINKNEVRA;
1992  he->t = RPM_STRING_ARRAY_TYPE;
1993  ac = argvCount(flink->NEVRA);
1994  if (ac > 0) {
1995  he->p.argv = argvData(flink->NEVRA);
1996  he->c = ac;
1997  }
1998 #ifdef NOTYET /* XXX is an explicit flink terminator needed? */
1999  else { /* XXX Add an explicit chain terminator on 1st install. */
2000  he->p.argv = &chain_end;
2001  he->c = 1;
2002  }
2003 #endif
2004  xx = headerPut(h, he, 0);
2005 
2006  he->tag = RPMTAG_FLINKPKGID;
2007  he->t = RPM_STRING_ARRAY_TYPE;
2008  ac = argvCount(flink->Pkgid);
2009  if (ac > 0) {
2010  he->p.argv = argvData(flink->Pkgid);
2011  he->c = ac;
2012  }
2013 #ifdef NOTYET /* XXX is an explicit flink terminator needed? */
2014  else { /* XXX Add an explicit chain terminator on 1st install. */
2015  he->p.argv = &chain_end;
2016  he->c = 1;
2017  }
2018 #endif
2019  xx = headerPut(h, he, 0);
2020 
2021  he->tag = RPMTAG_FLINKHDRID;
2022  he->t = RPM_STRING_ARRAY_TYPE;
2023  ac = argvCount(flink->Hdrid);
2024  if (ac > 0) {
2025  he->p.argv = argvData(flink->Hdrid);
2026  he->c = ac;
2027  }
2028 #ifdef NOTYET /* XXX is an explicit flink terminator needed? */
2029  else { /* XXX Add an explicit chain terminator on 1st install. */
2030  he->p.argv = &chain_end;
2031  he->c = 1;
2032  }
2033 #endif
2034  xx = headerPut(h, he, 0);
2035 
2036  return 0;
2037 }
2038 
2046 static int populateInstallHeader(const rpmts ts, const rpmte te, rpmfi fi)
2047  /*@globals h_errno, fileSystem, internalState @*/
2048  /*@modifies fi, fileSystem, internalState @*/
2049 {
2050  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
2051  rpmuint32_t tscolor = rpmtsColor(ts);
2052  rpmuint32_t tecolor = rpmteColor(te);
2053  rpmuint32_t * uip;
2054  rpmuint32_t installTime[2];
2055  rpmuint32_t originTime[2];
2056  rpmuint32_t originTid[2];
2057  int xx = 1;
2058 
2059 assert(fi->h != NULL);
2060 
2061  { struct timeval tv;
2062  xx = gettimeofday(&tv, NULL);
2063  installTime[0] = (rpmuint32_t) tv.tv_sec;
2064  installTime[1] = (rpmuint32_t) tv.tv_usec;
2065  }
2066  he->tag = RPMTAG_INSTALLTIME;
2067  he->t = RPM_UINT32_TYPE;
2068  he->p.ui32p = &installTime[0];
2069  he->c = 2;
2070  xx = headerPut(fi->h, he, 0);
2071 
2072  /* Propagate the tid & time that the package was first installed. */
2073  if ((uip = rpmteOriginTime(te)) != NULL)
2074  memcpy(originTime, uip, sizeof(originTime));
2075  if (originTime[0] == 0)
2076  memcpy(originTime, installTime, sizeof(originTime));
2077  he->tag = RPMTAG_ORIGINTIME;
2078  he->t = RPM_UINT32_TYPE;
2079  he->p.ui32p = originTime;
2080  he->c = 2;
2081  xx = headerPut(fi->h, he, 0);
2082 
2083  if ((uip = rpmteOriginTid(te)) != NULL)
2084  memcpy(originTid, uip, sizeof(originTid));
2085  if (originTid[0] == 0)
2086  memcpy(originTid, ts->tid, sizeof(originTid));
2087  he->tag = RPMTAG_ORIGINTID;
2088  he->t = RPM_UINT32_TYPE;
2089  he->p.ui32p = originTid;
2090  he->c = 2;
2091  xx = headerPut(fi->h, he, 0);
2092 
2093  he->tag = RPMTAG_INSTALLCOLOR;
2094  he->t = RPM_UINT32_TYPE;
2095  he->p.ui32p = &tscolor;
2096  he->c = 1;
2097  xx = headerPut(fi->h, he, 0);
2098 
2099  /* XXX FIXME: add preferred color at install. */
2100 
2101  he->tag = RPMTAG_PACKAGECOLOR;
2102  he->t = RPM_UINT32_TYPE;
2103  he->p.ui32p = &tecolor;
2104  he->c = 1;
2105  xx = headerPut(fi->h, he, 0);
2106 
2107  /* Add the header's origin/digest/stat (i.e. URL) */
2108  { const char * fn = headerGetOrigin(fi->h);
2109  const char * digest = headerGetDigest(fi->h);
2110  struct stat * st = headerGetStatbuf(fi->h);
2111 
2112  if (fn != NULL) {
2113  he->tag = RPMTAG_PACKAGEORIGIN;
2114  he->t = RPM_STRING_TYPE;
2115  he->p.str = xstrdup(fn);
2116  he->c = 1;
2117  xx = headerPut(fi->h, he, 0);
2118  he->p.ptr = _free(he->p.ptr);
2119 
2120  if (digest != NULL) {
2121  he->tag = RPMTAG_PACKAGEDIGEST;
2122  he->t = RPM_STRING_TYPE;
2123  he->p.str = headerGetDigest(fi->h);
2124  he->c = 1;
2125  xx = headerPut(fi->h, he, 0);
2126  }
2127  if (st != NULL) {
2128 /* XXX Fstat(2) in pkgio.c should set *st. Verify st->st_mode w assert(3). */
2129 #ifndef DYING
2130  int ut = urlPath(fn, NULL);
2131  /* XXX URI is active, so avoid the lazy Stat(2) for now. */
2132  if (!(ut == URL_IS_HTTP || ut == URL_IS_HTTPS))
2133  if (st->st_mode == 0 && st->st_mtime == 0 && st->st_size == 0)
2134  xx = Stat(fn, st);
2135 #endif
2136  if (st->st_mode != 0) {
2137  he->tag = RPMTAG_PACKAGESTAT;
2138  he->t = RPM_BIN_TYPE;
2139  he->p.ptr = (void *)st;
2140  he->c = (rpmTagCount) sizeof(*st);
2141  xx = headerPut(fi->h, he, 0);
2142  }
2143  }
2144  }
2145  }
2146 
2147  /* XXX Don't clobber forward/backward upgrade chain on rollbacks */
2148  if (rpmtsType(ts) != RPMTRANS_TYPE_ROLLBACK)
2149  xx = hSaveBlinks(fi->h, &te->blink);
2150 
2151  return 0;
2152 }
2153 
2161 static int postPopulateInstallHeader(/*@unused@*/ const rpmts ts,
2162  const rpmpsm psm, rpmfi fi)
2163  /*@modifies psm, fi @*/
2164 {
2165  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
2166  int fc = rpmfiFC(fi);
2167  int xx = 1;
2168 
2169  /* Add the (install) scriptlet status/metrics. */
2170  he->tag = RPMTAG_SCRIPTSTATES;
2171  he->t = RPM_UINT32_TYPE;
2172  he->p.ui32p = psm->sstates;
2173  he->c = RPMSCRIPT_MAX;
2174  xx = headerPut(fi->h, he, 0);
2175  he->tag = RPMTAG_SCRIPTMETRICS;
2176  he->t = RPM_UINT32_TYPE;
2177  he->p.ui32p = psm->smetrics;
2178  he->c = RPMSCRIPT_MAX;
2179  xx = headerPut(fi->h, he, 0);
2180 
2181  /* Add file states to install header. */
2182  if (fi->fstates != NULL && fc > 0) {
2183  he->tag = RPMTAG_FILESTATES;
2184  he->t = RPM_UINT8_TYPE;
2185  he->p.ui8p = fi->fstates;
2186  he->c = fc;
2187  xx = headerPut(fi->h, he, 0);
2188  }
2189 
2190  return 0;
2191 }
2192 
2193 #if defined(WITH_PTHREADS)
2194 static void * rpmpsmThread(void * _psm)
2195  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
2196  /*@modifies arg, rpmGlobalMacroContext, fileSystem, internalState @*/
2197 {
2198  rpmpsm psm = (rpmpsm) _psm;
2199 /*@-unqualifiedtrans@*/
2200  return ((void *) rpmpsmStage(psm, psm->nstage));
2201 /*@=unqualifiedtrans@*/
2202 }
2203 #endif
2204 
2205 static int rpmpsmNext(rpmpsm psm, pkgStage nstage)
2206  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
2207  /*@modifies psm, rpmGlobalMacroContext, fileSystem, internalState @*/
2208 {
2209  psm->nstage = nstage;
2210 #if defined(WITH_PTHREADS)
2211  if (_psm_threads)
2212  return rpmsqJoin( rpmsqThread(rpmpsmThread, psm) );
2213 #endif
2214  return rpmpsmStage(psm, psm->nstage);
2215 }
2216 
2221 /*@-nullpass@*/ /* FIX: testing null annotation for fi->h */
2223 {
2224  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
2225  const rpmts ts = psm->ts;
2226  rpmuint32_t tscolor = rpmtsColor(ts);
2227  rpmfi fi = psm->fi;
2228  rpmRC rc = psm->rc;
2229  int saveerrno;
2230  int xx;
2231 
2232 /* XXX hackery to assert(!scareMem) in rpmfiNew. */
2233 /*@-castexpose@*/
2234 if (fi->h == NULL && fi->te && ((rpmte)fi->te)->h != NULL) fi->h = headerLink(((rpmte)fi->te)->h);
2235 /*@=castexpose@*/
2236 
2237  switch (stage) {
2238  case PSM_UNKNOWN:
2239  break;
2240  case PSM_INIT:
2241  rpmlog(RPMLOG_DEBUG, D_("%s: %s has %d files, test = %d\n"),
2242  psm->stepName, rpmteNEVR(psm->te),
2243  rpmfiFC(fi), (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST));
2244 
2245  /*
2246  * When we run scripts, we pass an argument which is the number of
2247  * versions of this package that will be installed when we are
2248  * finished.
2249  */
2250  psm->npkgs_installed = rpmdbCountPackages(rpmtsGetRdb(ts), rpmteN(psm->te));
2251  if (psm->npkgs_installed < 0) {
2252  rc = RPMRC_FAIL;
2253  break;
2254  }
2255 
2256  /* Adjust package count on rollback downgrade. */
2257 assert(psm->te != NULL);
2259  (psm->goal & ~(PSM_PKGSAVE|PSM_PKGERASE)))
2260  {
2261  if (psm->te->downgrade)
2262  psm->npkgs_installed--;
2263  }
2264 
2265  if (psm->goal == PSM_PKGINSTALL) {
2266  int fc = rpmfiFC(fi);
2267  const char * hdrid;
2268 
2269  /* Add per-transaction data to install header. */
2270  xx = populateInstallHeader(ts, psm->te, fi);
2271 
2272  psm->scriptArg = psm->npkgs_installed + 1;
2273 
2274 assert(psm->mi == NULL);
2275  hdrid = rpmteHdrid(psm->te);
2276  if (hdrid != NULL) {
2277  /* XXX should use RPMTAG_HDRID not RPMTAG_SHA1HEADER */
2278  psm->mi = rpmtsInitIterator(ts, RPMTAG_SHA1HEADER, hdrid, 0);
2279  } else {
2280  psm->mi = rpmtsInitIterator(ts, RPMTAG_NAME, rpmteN(psm->te),0);
2282  rpmteE(psm->te));
2284  rpmteV(psm->te));
2286  rpmteR(psm->te));
2287 #ifdef RPM_VENDOR_MANDRIVA
2289  rpmteD(psm->te));
2290 #endif
2291  if (tscolor) {
2293  rpmteA(psm->te));
2294  xx = rpmmiAddPattern(psm->mi, RPMTAG_OS, RPMMIRE_STRCMP,
2295  rpmteO(psm->te));
2296  }
2297  }
2298 
2299  while ((psm->oh = rpmmiNext(psm->mi)) != NULL) {
2300  fi->record = rpmmiInstance(psm->mi);
2301  psm->oh = NULL;
2302  /*@loopbreak@*/ break;
2303  }
2304  psm->mi = rpmmiFree(psm->mi);
2305 
2306  rc = RPMRC_OK;
2307 
2308  /* XXX lazy alloc here may need to be done elsewhere. */
2309  if (fi->fstates == NULL && fc > 0) {
2310  fi->fstates = (rpmuint8_t *) xmalloc(sizeof(*fi->fstates) * fc);
2311  memset(fi->fstates, RPMFILE_STATE_NORMAL, fc);
2312  }
2313 
2314  xx = rpmtxnBegin(rpmtsGetRdb(ts), ts->txn, &psm->te->txn);
2315 
2316  if (rpmtsFlags(ts) & RPMTRANS_FLAG_JUSTDB) break;
2317  if (fc <= 0) break;
2318 
2319  /*
2320  * Old format relocatable packages need the entire default
2321  * prefix stripped to form the cpio list, while all other packages
2322  * need the leading / stripped.
2323  */
2324  he->tag = RPMTAG_DEFAULTPREFIX;
2325  xx = headerGet(fi->h, he, 0);
2326  fi->striplen = (xx && he->p.str ? strlen(he->p.str) + 1 : 1);
2327  he->p.ptr = _free(he->p.ptr);
2328  fi->mapflags =
2330 
2331  if (headerIsEntry(fi->h, RPMTAG_ORIGBASENAMES))
2332  he->tag = RPMTAG_ORIGPATHS;
2333  else
2334  he->tag = RPMTAG_FILEPATHS;
2335  xx = headerGet(fi->h, he, 0);
2336 assert(he->p.argv != NULL);
2337  fi->apath = he->p.argv;
2338 
2339  if (fi->fuser == NULL) {
2340  he->tag = RPMTAG_FILEUSERNAME;
2341  xx = headerGet(fi->h, he, 0);
2342  fi->fuser = he->p.argv;
2343  }
2344  if (fi->fgroup == NULL) {
2345  he->tag = RPMTAG_FILEGROUPNAME;
2346  xx = headerGet(fi->h, he, 0);
2347  fi->fgroup = he->p.argv;
2348  }
2349  rc = RPMRC_OK;
2350  }
2351  if (psm->goal == PSM_PKGERASE || psm->goal == PSM_PKGSAVE) {
2352  psm->scriptArg = psm->npkgs_installed - 1;
2353 
2354  /* XXX FIXME: PSM_PKGSAVE needs to be transactionally protected. */
2355  if (psm->goal == PSM_PKGERASE)
2356  xx = rpmtxnBegin(rpmtsGetRdb(ts), ts->txn, &psm->te->txn);
2357 
2358  /* Retrieve installed header. */
2359  rc = (rpmRC) rpmpsmNext(psm, PSM_RPMDB_LOAD);
2360  if (rc == RPMRC_OK && psm->te)
2361  (void) rpmteSetHeader(psm->te, fi->h);
2362  }
2363  if (psm->goal == PSM_PKGSAVE) {
2364  /* Open output package for writing. */
2365  { char tiddn[32];
2366  const char * bfmt;
2367  const char * pkgdn;
2368  const char * pkgbn;
2369  char * pkgdn_buf;
2370 
2371  xx = snprintf(tiddn, sizeof(tiddn), "%d", rpmtsGetTid(ts));
2372  bfmt = rpmGetPath(tiddn, "/", "%{_repackage_name_fmt}", NULL);
2373  pkgbn = headerSprintf(fi->h, bfmt,
2374  NULL, rpmHeaderFormats, NULL);
2375  bfmt = _free(bfmt);
2376  psm->pkgURL = rpmGenPath("%{?_repackage_root}",
2377  "%{?_repackage_dir}",
2378  pkgbn);
2379  pkgbn = _free(pkgbn);
2380  (void) urlPath(psm->pkgURL, &psm->pkgfn);
2381  pkgdn_buf = xstrdup(psm->pkgfn);
2382 /*@-moduncon@*/
2383  pkgdn = dirname(pkgdn_buf);
2384 /*@=moduncon@*/
2385  rc = rpmMkdirPath(pkgdn, "_repackage_dir");
2386  pkgdn_buf = _free(pkgdn_buf);
2387  if (rc == RPMRC_FAIL)
2388  break;
2389  psm->fd = Fopen(psm->pkgfn, "w.fdio");
2390  if (psm->fd == NULL || Ferror(psm->fd)) {
2391  rc = RPMRC_FAIL;
2392  break;
2393  }
2394  }
2395  }
2396  break;
2397  case PSM_PRE:
2398  if (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST) break;
2399 
2400 /* XXX insure that trigger index is opened before entering chroot. */
2401 #ifdef NOTYET
2402  { static int oneshot = 0;
2403  dbiIndex dbi;
2404  if (!oneshot) {
2405  dbi = dbiOpen(rpmtsGetRdb(ts), RPMTAG_TRIGGERNAME, 0);
2406  oneshot++;
2407  }
2408  }
2409 #endif
2410 
2411  /* Change root directory if requested and not already done. */
2412  rc = (rpmRC) rpmpsmNext(psm, PSM_CHROOT_IN);
2413 
2414  if (psm->goal == PSM_PKGINSTALL) {
2415  psm->scriptTag = RPMTAG_PREIN;
2416  psm->progTag = RPMTAG_PREINPROG;
2417  psm->sense = RPMSENSE_TRIGGERPREIN;
2418  psm->countCorrection = 0; /* XXX is this correct?!? */
2419 
2421 
2422  /* Run triggers in other package(s) this package sets off. */
2423  rc = (rpmRC) rpmpsmNext(psm, PSM_TRIGGERS);
2424  if (rc) break;
2425 
2426  /* Run triggers in this package other package(s) set off. */
2427  rc = (rpmRC) rpmpsmNext(psm, PSM_IMMED_TRIGGERS);
2428  if (rc) break;
2429  }
2430 
2431  if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOPRE)) {
2432  rc = (rpmRC) rpmpsmNext(psm, PSM_SCRIPT);
2433  if (rc != RPMRC_OK) {
2435  _("%s: %s scriptlet failed (%d), skipping %s\n"),
2436  psm->stepName, tag2sln(psm->scriptTag), rc,
2437  rpmteNEVR(psm->te));
2438  break;
2439  }
2440  }
2441  }
2442 
2443  if (psm->goal == PSM_PKGERASE) {
2444  psm->scriptTag = RPMTAG_PREUN;
2445  psm->progTag = RPMTAG_PREUNPROG;
2446  psm->sense = RPMSENSE_TRIGGERUN;
2447  psm->countCorrection = -1;
2448 
2449  if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOTRIGGERUN)) {
2450  /* Run triggers in this package other package(s) set off. */
2451  rc = (rpmRC) rpmpsmNext(psm, PSM_IMMED_TRIGGERS);
2452  if (rc) break;
2453 
2454  /* Run triggers in other package(s) this package sets off. */
2455  rc = (rpmRC) rpmpsmNext(psm, PSM_TRIGGERS);
2456  if (rc) break;
2457  }
2458 
2459  if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOPREUN))
2460  rc = (rpmRC) rpmpsmNext(psm, PSM_SCRIPT);
2461  }
2462  if (psm->goal == PSM_PKGSAVE) {
2463  int noArchiveSize = 0;
2464  const char * origin = NULL;
2465  const char * digest = NULL;
2466  const struct stat * st = NULL;
2467  size_t nstbytes = 0;
2468 
2469  /* Regenerate original header. */
2470  { void * uh = NULL;
2471 
2472  /* Save original header's origin/digest/stat (i.e. URL) */
2473  he->tag = RPMTAG_PACKAGEORIGIN;
2474  xx = headerGet(fi->h, he, 0);
2475  origin = he->p.str;
2476  he->tag = RPMTAG_PACKAGEDIGEST;
2477  xx = headerGet(fi->h, he, 0);
2478  if (xx && he->p.str != NULL)
2479  digest = he->p.str;
2480  he->tag = RPMTAG_PACKAGESTAT;
2481  xx = headerGet(fi->h, he, 0);
2482  if (xx && he->p.ptr != NULL && (size_t)he->c == sizeof(*st)) {
2483  st = (struct stat *) he->p.ptr;
2484  nstbytes = he->c;
2485  }
2486 
2487  /* Retrieve original header blob. */
2489  xx = headerGet(fi->h, he, 0);
2490  uh = he->p.ptr;
2491  if (xx && uh != NULL) {
2492  psm->oh = headerCopyLoad(uh);
2493  uh = _free(uh);
2494  } else {
2495  he->tag = RPMTAG_HEADERIMAGE;
2496  xx = headerGet(fi->h, he, 0);
2497  uh = he->p.ptr;
2498  if (xx && uh != NULL) {
2499  HeaderIterator hi;
2500  Header oh;
2501 
2502  /* Load the original header from the blob. */
2503  oh = headerCopyLoad(uh);
2504 
2505  /* XXX this is headerCopy w/o headerReload() */
2506  psm->oh = headerNew();
2507 
2508  for (hi = headerInit(oh);
2509  headerNext(hi, he, 0);
2510  he->p.ptr = _free(he->p.ptr))
2511  {
2512  if (he->tag == RPMTAG_ARCHIVESIZE)
2513  noArchiveSize = 1;
2514  xx = headerPut(psm->oh, he, 0);
2515  }
2516  hi = headerFini(hi);
2517 
2518  (void)headerFree(oh);
2519  oh = NULL;
2520  uh = _free(uh);
2521  } else
2522  break; /* XXX shouldn't ever happen */
2523  }
2524  }
2525 
2526  /* Retrieve type of payload compression. */
2527  /*@-nullstate@*/ /* FIX: psm->oh may be NULL */
2528  rc = (rpmRC) rpmpsmNext(psm, PSM_RPMIO_FLAGS);
2529  /*@=nullstate@*/
2530 
2531  /* Write the lead section into the package. */
2532  { static const char item[] = "Lead";
2533  const char * NEVR = rpmteNEVR(psm->te);
2534  const char * msg = xstrdup(NEVR); /* XXX passed to wrLead() */
2535  size_t nb = rpmpkgSizeof(item, NULL);
2536 
2537  if (nb == 0)
2538  rc = RPMRC_FAIL;
2539  else {
2540  void * l = memset(alloca(nb), 0, nb);
2541  rc = rpmpkgWrite(item, psm->fd, l, &msg);
2542  }
2543  if (rc != RPMRC_OK) {
2544  rpmlog(RPMLOG_ERR, _("Unable to write package: %s\n"),
2545  Fstrerror(psm->fd));
2546  msg = _free(msg);
2547  break;
2548  }
2549  msg = _free(msg);
2550  }
2551 
2552  /* Write the signature section into the package. */
2553  /* XXX rpm-4.1 and later has archive size in signature header. */
2554  { static const char item[] = "Signature";
2555  Header sigh = headerRegenSigHeader(fi->h, noArchiveSize);
2556  /* Reallocate the signature into one contiguous region. */
2557  sigh = headerReload(sigh, RPMTAG_HEADERSIGNATURES);
2558  if (sigh == NULL) {
2559  rpmlog(RPMLOG_ERR, _("Unable to reload signature header\n"));
2560  rc = RPMRC_FAIL;
2561  break;
2562  }
2563  rc = rpmpkgWrite(item, psm->fd, sigh, NULL);
2564  (void)headerFree(sigh);
2565  sigh = NULL;
2566  if (rc != RPMRC_OK) {
2567  break;
2568  }
2569  }
2570 
2571  /* Add remove transaction id to header. */
2572  if (psm->oh != NULL)
2573  { rpmuint32_t tid = rpmtsGetTid(ts);
2574 
2575  he->tag = RPMTAG_REMOVETID;
2576  he->t = RPM_UINT32_TYPE;
2577  he->p.ui32p = &tid;
2578  he->c = 1;
2579  xx = headerPut(psm->oh, he, 0);
2580 
2581  /* Add original header's origin/digest/stat (i.e. URL) */
2582  if (origin != NULL) {
2583  he->tag = RPMTAG_PACKAGEORIGIN;
2584  he->t = RPM_STRING_TYPE;
2585  he->p.str = origin;
2586  he->c = 1;
2587  xx = headerPut(psm->oh, he, 0);
2588  origin = _free(origin);
2589  }
2590  if (digest != NULL) {
2591  he->tag = RPMTAG_PACKAGEDIGEST;
2592  he->t = RPM_STRING_TYPE;
2593  he->p.str = digest;
2594  he->c = 1;
2595  xx = headerPut(psm->oh, he, 0);
2596  digest = _free(digest);
2597  }
2598  if (st != NULL) {
2599  he->tag = RPMTAG_PACKAGESTAT;
2600  he->t = RPM_BIN_TYPE;
2601  he->p.ptr = (void *)st;
2602  he->c = (rpmTagCount)nstbytes;
2603  xx = headerPut(psm->oh, he, 0);
2604  st = _free(st);
2605  }
2606 
2607  /* Copy upgrade chain link tags. */
2608  xx = hCopyTag(fi->h, psm->oh, RPMTAG_INSTALLTID);
2609  xx = hCopyTag(fi->h, psm->oh, RPMTAG_BLINKPKGID);
2610  xx = hCopyTag(fi->h, psm->oh, RPMTAG_BLINKHDRID);
2611  xx = hCopyTag(fi->h, psm->oh, RPMTAG_BLINKNEVRA);
2612 
2613 assert(psm->te != NULL);
2614  xx = hSaveFlinks(psm->oh, &psm->te->flink);
2615  }
2616 
2617  /* Write the metadata section into the package. */
2618  { const char item[] = "Header";
2619  const char * msg = NULL;
2620  rc = rpmpkgWrite(item, psm->fd, psm->oh, &msg);
2621  if (rc != RPMRC_OK) {
2622  rpmlog(RPMLOG_ERR, "%s: %s: %s", psm->pkgfn, item,
2623  (msg && *msg ? msg : "write failed\n"));
2624  msg = _free(msg);
2625  }
2626  }
2627  }
2628  break;
2629  case PSM_PROCESS:
2630  if (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST) break;
2631 
2632  if (psm->goal == PSM_PKGINSTALL) {
2633 
2634  if (rpmtsFlags(ts) & RPMTRANS_FLAG_JUSTDB) break;
2635 
2636  /* XXX Synthesize callbacks for packages with no files. */
2637  if (rpmfiFC(fi) <= 0) {
2638  void * ptr;
2639  ptr = rpmtsNotify(ts, (rpmte)fi->te, RPMCALLBACK_INST_START, 0, 100);
2640  ptr = rpmtsNotify(ts, (rpmte)fi->te, RPMCALLBACK_INST_PROGRESS, 100, 100);
2641  break;
2642  }
2643 
2644  /* Retrieve type of payload compression. */
2645  rc = (rpmRC) rpmpsmNext(psm, PSM_RPMIO_FLAGS);
2646 
2647  if (rpmteFd((rpmte)fi->te) == NULL) { /* XXX can't happen */
2648  rc = RPMRC_FAIL;
2649  break;
2650  }
2651 
2652  /*@-nullpass@*/ /* LCL: fi->fd != NULL here. */
2653  psm->cfd = Fdopen(fdDup(Fileno(rpmteFd((rpmte)fi->te))), psm->rpmio_flags);
2654  /*@=nullpass@*/
2655  if (psm->cfd == NULL) { /* XXX can't happen */
2656  rc = RPMRC_FAIL;
2657  break;
2658  }
2659 
2660  xx = rpmtxnBegin(rpmtsGetRdb(ts), psm->te->txn, NULL);
2661 
2662  rc = (rpmRC) fsmSetup(fi->fsm, IOSM_PKGINSTALL, psm->payload_format,
2663  ts, fi, psm->cfd, NULL, &psm->failedFile);
2664  (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_UNCOMPRESS),
2665  fdstat_op(psm->cfd, FDSTAT_READ));
2666  (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_DIGEST),
2667  fdstat_op(psm->cfd, FDSTAT_DIGEST));
2668  xx = fsmTeardown(fi->fsm);
2669 
2670  saveerrno = errno; /* XXX FIXME: Fclose with libio destroys errno */
2671  xx = Fclose(psm->cfd);
2672  psm->cfd = NULL;
2673  /*@-mods@*/
2674  errno = saveerrno; /* XXX FIXME: Fclose with libio destroys errno */
2675  /*@=mods@*/
2676 
2677  if (!rc)
2678  rc = (rpmRC) rpmpsmNext(psm, PSM_COMMIT);
2679 
2680  /* Commit/abort the SRPM install transaction. */
2681  /* XXX move into the PSM package state machine w PSM_COMMIT */
2682  { rpmdb db = rpmtsGetRdb(ts);
2683  rpmtxn _txn = (db ? db->db_txn : NULL);
2684  if (_txn != NULL) {
2685  if (rc)
2686  xx = rpmtxnAbort(_txn);
2687  else
2688  xx = rpmtxnCommit(_txn);
2689  db->db_txn = NULL;
2690  }
2691  }
2692 
2693  /* XXX make sure progress is closed out */
2694  psm->what = RPMCALLBACK_INST_PROGRESS;
2695  psm->amount = (fi->archiveSize ? fi->archiveSize : 100);
2696  psm->total = psm->amount;
2697  xx = rpmpsmNext(psm, PSM_NOTIFY);
2698 
2699  if (rc) {
2700  const char * msg = iosmStrerror(rc);
2702  _("unpacking of archive failed%s%s: %s\n"),
2703  (psm->failedFile != NULL ? _(" on file ") : ""),
2704  (psm->failedFile != NULL ? psm->failedFile : ""),
2705  msg);
2706  msg = _free(msg);
2707  rc = RPMRC_FAIL;
2708 
2709  /* XXX notify callback on error. */
2710  psm->what = RPMCALLBACK_UNPACK_ERROR;
2711  psm->amount = 0;
2712  psm->total = 0;
2713  xx = rpmpsmNext(psm, PSM_NOTIFY);
2714 
2715  break;
2716  }
2717  }
2718  if (psm->goal == PSM_PKGERASE) {
2719  int fc = rpmfiFC(fi);
2720 
2721  if (rpmtsFlags(ts) & RPMTRANS_FLAG_JUSTDB) break;
2722  if (rpmtsFlags(ts) & RPMTRANS_FLAG_APPLYONLY) break;
2723 
2724  psm->what = RPMCALLBACK_UNINST_START;
2725  psm->amount = fc;
2726  psm->total = (fc ? fc : 100);
2727  xx = rpmpsmNext(psm, PSM_NOTIFY);
2728 
2729  if (fc > 0) {
2730  rc = (rpmRC) fsmSetup(fi->fsm, IOSM_PKGERASE, psm->payload_format,
2731  ts, fi, NULL, NULL, &psm->failedFile);
2732  xx = fsmTeardown(fi->fsm);
2733  }
2734 
2735  psm->what = RPMCALLBACK_UNINST_STOP;
2736  psm->amount = (fc ? fc : 100);
2737  psm->total = (fc ? fc : 100);
2738  xx = rpmpsmNext(psm, PSM_NOTIFY);
2739 
2740  }
2741  if (psm->goal == PSM_PKGSAVE) {
2742  iosmFileAction * actions = (iosmFileAction *) fi->actions;
2743  iosmFileAction action = (iosmFileAction) fi->action;
2744 
2745  fi->action = FA_COPYOUT;
2746  fi->actions = NULL;
2747 
2748  if (psm->fd == NULL) { /* XXX can't happen */
2749  rc = RPMRC_FAIL;
2750  break;
2751  }
2752  /*@-nullpass@*/ /* FIX: fdDup mey return NULL. */
2753  xx = Fflush(psm->fd);
2754  psm->cfd = Fdopen(fdDup(Fileno(psm->fd)), psm->rpmio_flags);
2755  /*@=nullpass@*/
2756  if (psm->cfd == NULL) { /* XXX can't happen */
2757  rc = RPMRC_FAIL;
2758  break;
2759  }
2760 
2761  rc = (rpmRC) fsmSetup(fi->fsm, IOSM_PKGBUILD, psm->payload_format,
2762  ts, fi, psm->cfd, NULL, &psm->failedFile);
2763  (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_COMPRESS),
2764  fdstat_op(psm->cfd, FDSTAT_WRITE));
2765  (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_DIGEST),
2766  fdstat_op(psm->cfd, FDSTAT_DIGEST));
2767  xx = fsmTeardown(fi->fsm);
2768 
2769  saveerrno = errno; /* XXX FIXME: Fclose with libio destroys errno */
2770  xx = Fclose(psm->cfd);
2771  psm->cfd = NULL;
2772  /*@-mods@*/
2773  errno = saveerrno;
2774  /*@=mods@*/
2775 
2776  /* XXX make sure progress is closed out */
2777  psm->what = RPMCALLBACK_INST_PROGRESS;
2778  psm->amount = (fi->archiveSize ? fi->archiveSize : 100);
2779  psm->total = psm->amount;
2780  xx = rpmpsmNext(psm, PSM_NOTIFY);
2781 
2782  fi->action = (int) action;
2783  fi->actions = (int *) actions;
2784  }
2785  break;
2786  case PSM_POST:
2787  if (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST) break;
2788 
2789  if (psm->goal == PSM_PKGINSTALL) {
2790 
2791  psm->scriptTag = RPMTAG_POSTIN;
2792  psm->progTag = RPMTAG_POSTINPROG;
2793  psm->sense = RPMSENSE_TRIGGERIN;
2794  psm->countCorrection = 1;
2795 
2796  if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOPOST)) {
2797  rc = (rpmRC) rpmpsmNext(psm, PSM_SCRIPT);
2798  if (rc) break;
2799  }
2800  if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOTRIGGERIN)) {
2801  /* Run triggers in other package(s) this package sets off. */
2802  rc = (rpmRC) rpmpsmNext(psm, PSM_TRIGGERS);
2803  if (rc) break;
2804 
2805  /* Run triggers in this package other package(s) set off. */
2806  rc = (rpmRC) rpmpsmNext(psm, PSM_IMMED_TRIGGERS);
2807  if (rc) break;
2808  }
2809 
2810  /*
2811  * If this header has already been installed, remove it from
2812  * the database before adding the new header.
2813  */
2814  if (fi->record && !(rpmtsFlags(ts) & RPMTRANS_FLAG_APPLYONLY)) {
2815  rc = (rpmRC) rpmpsmNext(psm, PSM_RPMDB_REMOVE);
2816  if (rc) break;
2817  }
2818 
2819  /* Add scriptlet/file states to install header. */
2820  xx = postPopulateInstallHeader(ts, psm, fi);
2821 
2822  rc = (rpmRC) rpmpsmNext(psm, PSM_RPMDB_ADD);
2823  if (rc) break;
2824 
2825 #ifdef DYING
2826  if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_APPLYONLY))
2827  rc = markReplacedFiles(psm);
2828 #endif
2829 
2830  }
2831  if (psm->goal == PSM_PKGERASE) {
2832 
2833  psm->scriptTag = RPMTAG_POSTUN;
2834  psm->progTag = RPMTAG_POSTUNPROG;
2835  psm->sense = RPMSENSE_TRIGGERPOSTUN;
2836  psm->countCorrection = -1;
2837 
2838  if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOPOSTUN)) {
2839  if (rpmpsmNext(psm, PSM_SCRIPT))
2840  rpmlog(RPMLOG_INFO, _("Ignoring failed %%postun scriptlet\n"));
2841  }
2842 
2844  /* Run triggers in other package(s) this package sets off. */
2845  rc = (rpmRC) rpmpsmNext(psm, PSM_TRIGGERS);
2846  if (rc) break;
2847 
2848  /* Run triggers in this package other package(s) set off. */
2849  rc = (rpmRC) rpmpsmNext(psm, PSM_IMMED_TRIGGERS);
2850  if (rc) break;
2851  }
2852 
2853  if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_APPLYONLY))
2854  rc = (rpmRC) rpmpsmNext(psm, PSM_RPMDB_REMOVE);
2855  }
2856  if (psm->goal == PSM_PKGSAVE) {
2857  }
2858 
2859  /* Restore root directory if changed. */
2860  xx = rpmpsmNext(psm, PSM_CHROOT_OUT);
2861  break;
2862  case PSM_UNDO:
2863  break;
2864  case PSM_FINI:
2865  /* Restore root directory if changed. */
2866  xx = rpmpsmNext(psm, PSM_CHROOT_OUT);
2867 
2868  if (psm->fd != NULL) {
2869  saveerrno = errno; /* XXX FIXME: Fclose with libio destroys errno */
2870  xx = Fclose(psm->fd);
2871  psm->fd = NULL;
2872  /*@-mods@*/
2873  errno = saveerrno;
2874  /*@=mods@*/
2875  }
2876 
2877  if (psm->goal == PSM_PKGSAVE) {
2878  if (!rc && ts && ts->notify == NULL) {
2879  rpmlog(RPMLOG_INFO, _("Wrote: %s\n"),
2880  (psm->pkgURL ? psm->pkgURL : "???"));
2881  }
2882  }
2883 
2884  if (rc) {
2885  const char * msg = iosmStrerror(rc);
2886  if (psm->failedFile)
2888  _("%s failed on file %s: %s\n"),
2889  psm->stepName, psm->failedFile, msg);
2890  else
2891  rpmlog(RPMLOG_ERR, _("%s failed: %s\n"),
2892  psm->stepName, msg);
2893  msg = _free(msg);
2894 
2895  /* XXX notify callback on error. */
2896  psm->what = RPMCALLBACK_CPIO_ERROR;
2897  psm->amount = 0;
2898  psm->total = 0;
2899  /*@-nullstate@*/ /* FIX: psm->fd may be NULL. */
2900  xx = rpmpsmNext(psm, PSM_NOTIFY);
2901  /*@=nullstate@*/
2902  if (psm->te->txn != NULL) {
2903  xx = rpmtxnAbort(psm->te->txn);
2904  psm->te->txn = NULL;
2905  }
2906  } else {
2907  if (psm->te->txn != NULL) {
2908  xx = rpmtxnCommit(psm->te->txn);
2909  psm->te->txn = NULL;
2910  }
2911  }
2912 
2913  if (psm->goal == PSM_PKGERASE || psm->goal == PSM_PKGSAVE) {
2914  if (psm->te != NULL)
2915  (void) rpmteSetHeader(psm->te, NULL);
2916  if (fi->h != NULL) {
2917  (void)headerFree(fi->h);
2918  fi->h = NULL;
2919  }
2920  }
2921  (void)headerFree(psm->oh);
2922  psm->oh = NULL;
2923  psm->pkgURL = _free(psm->pkgURL);
2924  psm->rpmio_flags = _free(psm->rpmio_flags);
2925  psm->payload_format = _free(psm->payload_format);
2926  psm->failedFile = _free(psm->failedFile);
2927 
2928  fi->fgroup = _free(fi->fgroup);
2929  fi->fuser = _free(fi->fuser);
2930  fi->apath = _free(fi->apath);
2931  fi->fstates = _free(fi->fstates);
2932  break;
2933 
2934  case PSM_PKGINSTALL:
2935  case PSM_PKGERASE:
2936  case PSM_PKGSAVE:
2937  psm->goal = stage;
2938  psm->rc = RPMRC_OK;
2939  psm->stepName = pkgStageString(stage);
2940 
2941  rc = (rpmRC) rpmpsmNext(psm, PSM_INIT);
2942  if (!rc) rc = (rpmRC) rpmpsmNext(psm, PSM_PRE);
2943  if (!rc) rc = (rpmRC) rpmpsmNext(psm, PSM_PROCESS);
2944  if (!rc) rc = (rpmRC) rpmpsmNext(psm, PSM_POST);
2945  xx = rpmpsmNext(psm, PSM_FINI);
2946  break;
2947  case PSM_PKGCOMMIT:
2948  break;
2949 
2950  case PSM_CREATE:
2951  break;
2952  case PSM_NOTIFY:
2953  { void * ptr;
2954 /*@-nullpass@*/ /* FIX: psm->te may be NULL */
2955  ptr = rpmtsNotify(ts, psm->te, psm->what, psm->amount, psm->total);
2956 /*@-nullpass@*/
2957  } break;
2958  case PSM_DESTROY:
2959  break;
2960  case PSM_COMMIT:
2961  if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_PKGCOMMIT)) break;
2962  if (rpmtsFlags(ts) & RPMTRANS_FLAG_APPLYONLY) break;
2963 
2964  rc = (rpmRC) fsmSetup(fi->fsm, IOSM_PKGCOMMIT, psm->payload_format,
2965  ts, fi, NULL, NULL, &psm->failedFile);
2966  xx = fsmTeardown(fi->fsm);
2967  break;
2968 
2969  case PSM_CHROOT_IN:
2970  { const char * rootDir = rpmtsRootDir(ts);
2971  /* Change root directory if requested and not already done. */
2972  if (rootDir != NULL && !(rootDir[0] == '/' && rootDir[1] == '\0')
2973  && !rpmtsChrootDone(ts) && !F_ISSET(psm, CHROOTDONE))
2974  {
2975  static int _pw_loaded = 0;
2976  static int _gr_loaded = 0;
2977 
2978  if (!_pw_loaded) {
2979  (void)getpwnam("root");
2980  endpwent();
2981  _pw_loaded++;
2982  }
2983  if (!_gr_loaded) {
2984  (void)getgrnam("root");
2985  endgrent();
2986  _gr_loaded++;
2987  }
2988 
2989  xx = Chdir("/");
2990  /*@-modobserver@*/
2991  if (rootDir != NULL && strcmp(rootDir, "/") && *rootDir == '/')
2992  rc = (rpmRC) Chroot(rootDir);
2993  /*@=modobserver@*/
2994  F_SET(psm, CHROOTDONE);
2995  (void) rpmtsSetChrootDone(ts, 1);
2996  }
2997  } break;
2998  case PSM_CHROOT_OUT:
2999  /* Restore root directory if changed. */
3000  if (F_ISSET(psm, CHROOTDONE)) {
3001  const char * rootDir = rpmtsRootDir(ts);
3002  const char * currDir = rpmtsCurrDir(ts);
3003  /*@-modobserver@*/
3004  if (rootDir != NULL && strcmp(rootDir, "/") && *rootDir == '/')
3005  rc = (rpmRC) Chroot(".");
3006  /*@=modobserver@*/
3007  F_CLR(psm, CHROOTDONE);
3008  (void) rpmtsSetChrootDone(ts, 0);
3009  if (currDir != NULL) /* XXX can't happen */
3010  xx = Chdir(currDir);
3011  }
3012  break;
3013  case PSM_SCRIPT: /* Run current package scriptlets. */
3014  /* XXX running %verifyscript/%sanitycheck doesn't have psm->te */
3015  { rpmtxn _parent = (psm && psm->te ? psm->te->txn : NULL);
3016  xx = rpmtxnBegin(rpmtsGetRdb(ts), _parent, NULL);
3017  rc = runInstScript(psm);
3018  if (rc)
3019  xx = rpmtxnAbort(rpmtsGetRdb(ts)->db_txn);
3020  else
3021  xx = rpmtxnCommit(rpmtsGetRdb(ts)->db_txn);
3022  rpmtsGetRdb(ts)->db_txn = NULL;
3023  } break;
3024  case PSM_TRIGGERS:
3025  /* Run triggers in other package(s) this package sets off. */
3026  if (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST) break;
3027  rc = runTriggers(psm);
3028  break;
3029  case PSM_IMMED_TRIGGERS:
3030  /* Run triggers in this package other package(s) set off. */
3031  if (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST) break;
3032  if (!F_ISSET(psm, GOTTRIGGERS)) {
3033  psm->triggers = rpmdsNew(fi->h, RPMTAG_TRIGGERNAME, 0);
3034  F_SET(psm, GOTTRIGGERS);
3035  }
3036  if (psm->triggers != NULL)
3037  rc = runImmedTriggers(psm);
3038  break;
3039 
3040  case PSM_RPMIO_FLAGS:
3041  { const char * payload_compressor = NULL;
3042  const char * payload_format = NULL;
3043  char * t;
3044 
3046  xx = headerGet(fi->h, he, 0);
3047  payload_compressor = he->p.str;
3048  if (payload_compressor == NULL)
3049  payload_compressor = xstrdup("gzip");
3050 
3051  psm->rpmio_flags = t = (char *) xmalloc(sizeof("w9.gzdio"));
3052  *t = '\0';
3053  t = stpcpy(t, ((psm->goal == PSM_PKGSAVE) ? "w6" : "r"));
3054  if (!strcmp(payload_compressor, "gzip"))
3055  t = stpcpy(t, ".gzdio");
3056  if (!strcmp(payload_compressor, "bzip2"))
3057  t = stpcpy(t, ".bzdio");
3058  if (!strcmp(payload_compressor, "lzma"))
3059  t = stpcpy(t, ".lzdio");
3060  if (!strcmp(payload_compressor, "xz"))
3061  t = stpcpy(t, ".xzdio");
3062  payload_compressor = _free(payload_compressor);
3063 
3064  he->tag = RPMTAG_PAYLOADFORMAT;
3065  xx = headerGet(fi->h, he, 0);
3066  payload_format = he->p.str;
3067  if (!xx || payload_format == NULL || !(
3068  !strcmp(payload_format, "tar") || !strcmp(payload_format, "ustar")
3069 #if defined(SUPPORT_AR_PAYLOADS)
3070  || !strcmp(payload_format, "ar")
3071 #endif
3072  ))
3073  {
3074  payload_format = _free(payload_format);
3075  payload_format = xstrdup("cpio");
3076  }
3077  psm->payload_format = _free(psm->payload_format);
3078  psm->payload_format = payload_format;
3079  rc = RPMRC_OK;
3080  } break;
3081 
3082  case PSM_RPMDB_LOAD:
3083 assert(psm->mi == NULL);
3084  psm->mi = rpmtsInitIterator(ts, RPMDBI_PACKAGES,
3085  &fi->record, sizeof(fi->record));
3086  fi->h = rpmmiNext(psm->mi);
3087 /*@-castexpose@*/
3088  if (fi->h != NULL)
3089  fi->h = headerLink(fi->h);
3090 /*@=castexpose@*/
3091  psm->mi = rpmmiFree(psm->mi);
3092 
3093  if (fi->h != NULL) {
3094  (void) headerSetInstance(fi->h, fi->record);
3095  rc = RPMRC_OK;
3096  } else
3097  rc = RPMRC_FAIL;
3098  break;
3099  case PSM_RPMDB_ADD:
3100  if (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST) break;
3101  if (rpmtsFlags(ts) & RPMTRANS_FLAG_NORPMDB) break;
3102  if (fi->isSource) break; /* XXX never add SRPM's */
3103  if (fi->h == NULL) break; /* XXX can't happen */
3104 
3105  xx = rpmtxnBegin(rpmtsGetRdb(ts), psm->te->txn, NULL);
3106 
3107  /* Add header to db, doing header check if requested */
3108  /* XXX rollback headers propagate the previous transaction id. */
3109  { rpmuint32_t tid = ((rpmtsType(ts) == RPMTRANS_TYPE_ROLLBACK)
3110  ? hLoadTID(fi->h, RPMTAG_INSTALLTID) : rpmtsGetTid(ts));
3111  (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DBADD), 0);
3112  if (!(rpmtsVSFlags(ts) & RPMVSF_NOHDRCHK))
3113  rc = (rpmRC) rpmdbAdd(rpmtsGetRdb(ts), tid, fi->h, ts);
3114  else
3115  rc = (rpmRC) rpmdbAdd(rpmtsGetRdb(ts), tid, fi->h, NULL);
3116  (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DBADD), 0);
3117 #if defined(HAVE_SYSLOG_H) && defined(RPM_VENDOR_MANDRIVA) /* log-install-remove-to-syslog */
3118  {
3119  char *s, fmt;
3120  fmt = rpmExpand("%{___NVRA}", NULL);
3121  s = headerSprintf(fi->h, fmt,
3122  rpmTagTable, rpmHeaderFormats, NULL);
3123  syslog(LOG_NOTICE, "[RPM] %s installed\n", s);
3124  fmt = _free(fmt);
3125  s = _free(s);
3126  }
3127 #endif
3128  }
3129 
3130  if (rc != RPMRC_OK) {
3131  xx = rpmtxnAbort(rpmtsGetRdb(ts)->db_txn);
3132  rpmtsGetRdb(ts)->db_txn = NULL;
3133  break;
3134  } else
3135  xx = rpmtxnCommit(rpmtsGetRdb(ts)->db_txn);
3136  rpmtsGetRdb(ts)->db_txn = NULL;
3137 
3138 assert(psm->te != NULL);
3139  /* Mark non-rollback elements as installed. */
3140  if (rpmtsType(ts) != RPMTRANS_TYPE_ROLLBACK)
3141  psm->te->installed = 1;
3142 
3143  /* Set the database instance for (possible) rollbacks. */
3144  rpmteSetDBInstance(psm->te, headerGetInstance(fi->h));
3145 
3146  break;
3147  case PSM_RPMDB_REMOVE:
3148  {
3149  if (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST) break;
3150  if (rpmtsFlags(ts) & RPMTRANS_FLAG_NORPMDB) break;
3151 
3152  xx = rpmtxnBegin(rpmtsGetRdb(ts), psm->te->txn, NULL);
3153 
3154  (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DBREMOVE), 0);
3155  rc = (rpmRC) rpmdbRemove(rpmtsGetRdb(ts), rpmtsGetTid(ts), fi->record, NULL);
3156  (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DBREMOVE), 0);
3157 #if defined(HAVE_SYSLOG_H) && defined(RPM_VENDOR_MANDRIVA) /* log-install-remove-to-syslog */
3158  {
3159  char *s, fmt;
3160  fmt = rpmExpand("%{___NVRA}", NULL);
3161  s = headerSprintf(fi->h, fmt,
3162  rpmTagTable, rpmHeaderFormats, NULL);
3163  syslog(LOG_NOTICE, "[RPM] %s removed\n", s);
3164  fmt = _free(fmt);
3165  s = _free(s);
3166  }
3167 #endif
3168 
3169  if (rc != RPMRC_OK) {
3170  xx = rpmtxnAbort(rpmtsGetRdb(ts)->db_txn);
3171  rpmtsGetRdb(ts)->db_txn = NULL;
3172  break;
3173  } else
3174  xx = rpmtxnCommit(rpmtsGetRdb(ts)->db_txn);
3175  rpmtsGetRdb(ts)->db_txn = NULL;
3176 
3177  /* Forget the offset of a successfully removed header. */
3178  if (psm->te != NULL) /* XXX can't happen */
3179  psm->te->u.removed.dboffset = 0;
3180 
3181  } break;
3182 
3183  default:
3184  break;
3185 /*@i@*/ }
3186 
3187 /*@-nullstate@*/ /* FIX: psm->oh and psm->fi->h may be NULL. */
3188  return rc;
3189 /*@=nullstate@*/
3190 }
3191 /*@=nullpass@*/
rpmuint32_t rpmfiFFlags(rpmfi fi)
Return current file flags from file info set.
Definition: rpmfi.c:217
rpmTagType t
Definition: rpmtag.h:504
int rpmmiPrune(rpmmi mi, uint32_t *hdrNums, int nHdrNums, int sorted)
Remove items from set of package instances to iterate.
Definition: rpmdb.c:2453
static void rpmpsmFini(void *_psm)
Definition: psm.c:1805
evrFlags rpmdsFlags(const rpmds ds)
Return current dependency flags.
Definition: rpmds.c:691
const char * str
Definition: rpmtag.h:73
rpmTag tag
Definition: rpmtag.h:503
rpmioPool _psmPool
Definition: psm.c:1832
FD_t rpmteFd(rpmte te)
Retrieve file handle from transaction element.
Definition: rpmte.c:561
const char ** argv
Definition: rpmtag.h:75
static rpmRC createDir(rpmts ts, rpmfi fi, const char **fn, const char *name)
Definition: psm.c:185
rpmds rpmdsInit(rpmds ds)
Initialize dependency set iterator.
Definition: rpmds.c:943
headerTagTableEntry rpmTagTable
Automatically generated table of tag name/value pairs.
Definition: tagtbl.c:239
rpmsm rpmsmFree(rpmsm sm)
Destroy a semanage wrapper.
int rpmtxnBegin(rpmdb rpmdb, rpmtxn parent, rpmtxn *txnp)
Definition: rpmtxn.c:56
pid_t rpmsqWait(rpmsq sq)
Wait for child process to be reaped.
Definition: rpmsq.c:624
rpmuint32_t rpmteColor(rpmte te)
Retrieve color bits of transaction element.
Definition: rpmte.c:360
miRE mireNew(rpmMireMode mode, int tag)
Create pattern container.
Definition: mire.c:113
rpmtime_t rpmswExit(rpmop op, ssize_t rc)
Exit timed operation.
Definition: rpmsw.c:264
pid_t rpmsqFork(rpmsq sq)
Fork a child process.
Definition: rpmsq.c:495
const char * headerGetDigest(Header h)
Return digest of origin *.rpm file.
Definition: header.c:1242
int headerIsEntry(Header h, rpmTag tag)
Check if tag is in header.
Definition: header.c:1439
void * rpmtsNotify(rpmts ts, rpmte te, rpmCallbackType what, rpmuint64_t amount, rpmuint64_t total)
Perform transaction progress notify callback.
Definition: rpmts.c:1281
const char const char size_t len
Definition: bson.h:823
const char bson_timestamp_t * ts
Definition: bson.h:1004
rpmte rpmteFree(rpmte te)
Destroy a transaction element.
ARGI_t argiFree(ARGI_t argi)
Destroy an argi array.
Definition: argv.c:34
void * mireFreeAll(miRE mire, int nmire)
Destroy compiled patterns.
Definition: mire.c:96
rpmtime_t usecs
Definition: rpmsw.h:43
const char * rpmtsRootDir(rpmts ts)
Get transaction rootDir, i.e.
Definition: rpmts.c:903
rpmte rpmtsElement(rpmts ts, int ix)
Return (ordered) transaction set element.
Definition: rpmts.c:1317
void rpmluavSetValueNum(rpmluav var, double value)
rpmRC rpmpkgWrite(const char *fn, FD_t fd, void *ptr, const char **msg)
Write item onto file descriptor.
Definition: pkgio.c:1692
enum iosmFileAction_e iosmFileAction
File disposition(s) during package install/erase processing.
rpmsquirrel rpmsquirrelFree(rpmsquirrel squirrel)
Destroy a squirrel interpreter.
int Chroot(const char *path)
chroot(2) clone.
Definition: rpmrpc.c:176
uint32_t rpmmiInstance(rpmmi mi)
Return header instance for current position of rpmdb iterator.
Definition: rpmdb.c:1747
Structures used for an "rpmte" transaction element.
int rpmtxnCommit(rpmtxn txn)
Definition: rpmtxn.c:75
size_t Fwrite(const void *buf, size_t size, size_t nmemb, FD_t fd)
fwrite(3) clone.
Definition: rpmio.c:2434
static const char * tag2sln(rpmTag tag)
Return scriptlet name from tag.
Definition: psm.c:390
char * xstrdup(const char *str)
Definition: rpmmalloc.c:321
void * rpmluavFree(rpmluav var)
rpmuint32_t * ui32p
Definition: rpmtag.h:70
FD_t Fopen(const char *path, const char *_fmode)
fopen(3) clone.
Definition: rpmio.c:2833
struct rpmsql_s * rpmsql
Definition: rpmsql.h:20
int rpmtsAddInstallElement(rpmts ts, Header h, fnpyKey key, int upgrade, rpmRelocation relocs)
Add package to be installed to transaction set.
Definition: depends.c:547
rpmjs rpmjsFree(rpmjs js)
Destroy a js interpreter.
char * rpmGetPath(const char *path,...)
Return (malloc'ed) expanded, canonicalized, file path.
Definition: macro.c:3431
Structure(s) used for file info tag sets.
int headerGet(Header h, HE_t he, unsigned int flags)
Retrieve extension or tag value from a header.
Definition: header.c:2231
void rpmluavSetListMode(rpmluav var, int flag)
int rpmlioPrein(rpmdb rpmdb, const char **av, const char *body)
Definition: rpmlio.c:348
int headerPut(Header h, HE_t he, unsigned int flags)
Add or append tag container to header.
Definition: header.c:2294
int Access(const char *path, int amode)
access(2) clone.
Definition: rpmrpc.c:2196
static int populateInstallHeader(const rpmts ts, const rpmte te, rpmfi fi)
Add per-transaction data to an install header.
Definition: psm.c:2046
enum rpmScriptID_e rpmScriptID
Scriptlet identifiers.
The Header data structure.
int mireRegcomp(miRE mire, const char *pattern)
Compile pattern match.
Definition: mire.c:332
HeaderIterator headerFini(HeaderIterator hi)
Destroy header tag container iterator.
Definition: header.c:2134
static int hCopyTag(Header sh, Header th, rpmTag tag)
Copy a tag from a source to a target header.
Definition: psm.c:1904
headerSprintfExtension rpmHeaderFormats
Table of query format extensions.
Definition: formats.c:305
static rpmTag _trigger_tag
Definition: psm.c:1237
int mireClean(miRE mire)
Deallocate pattern match memory.
Definition: mire.c:38
rpmtime_t rpmswAdd(rpmop to, rpmop from)
Sum statistic counters.
Definition: rpmsw.c:280
void * rpmsqThread(void *(*start)(void *arg), void *arg)
Call a function in a thread.
Definition: rpmsq.c:656
const char * rpmteN(rpmte te)
Retrieve name string of transaction element.
Definition: rpmte.c:316
HeaderIterator headerInit(Header h)
Create header tag iterator.
Definition: header.c:2144
int Stat(const char *path, struct stat *st)
stat(2) clone.
Definition: rpmrpc.c:1361
int rpmlioPreun(rpmdb rpmdb, const char **av, const char *body)
Definition: rpmlio.c:398
struct rpmpsm_s * rpmpsm
Package state machine data.
Definition: psm.h:13
FD_t fdLink(void *cookie, const char *msg)
rpmficl rpmficlNew(char **av, uint32_t flags)
Create and load a ficl interpreter.
Definition: rpmficl.c:74
Definition: rpmdb.c:436
int Fflush(FD_t fd)
fflush(3) clone.
Definition: rpmio.c:2916
struct rpmsm_s * rpmsm
Definition: rpmsm.h:11
int rpmlioPostin(rpmdb rpmdb, const char **av, const char *body)
Definition: rpmlio.c:373
int errno
#define F_SET(_psm, _FLAG)
Definition: psm.c:52
struct rpmjs_s * rpmjs
Definition: rpmjs.h:11
rpmfi rpmfiFree(rpmfi fi)
Destroy a file info set.
rpmop rpmtsOp(rpmts ts, rpmtsOpX opx)
Retrieve operation timestamp from a transaction set.
Definition: pkgio.c:133
const char * rpmfiFN(rpmfi fi)
Return current file name from file info set.
Definition: rpmfi.c:163
Header headerCopyLoad(const void *uh)
Make a copy and convert header to in-memory representation.
Definition: header.c:1433
int rpmtsSetChrootDone(rpmts ts, int chrootDone)
Set chrootDone flag, i.e.
Definition: rpmts.c:1012
Header tag iterator data structure.
Definition: header.c:2129
rpmTSType rpmtsType(rpmts ts)
Return the type of a transaction.
Definition: rpmts.c:870
static void rpmlog(int code, const char *fmt,...)
Definition: rpmlog.h:299
FD_t fdDup(int fdno)
Definition: rpmio.c:266
const char * rpmteA(rpmte te)
Retrieve arch string of transaction element.
Definition: rpmte.c:345
rpmts rpmtsLink(rpmts ts, const char *msg)
Reference a transaction set instance.
int doputenv(const char *str)
Like the libc function, but malloc()'s the space needed.
Definition: misc.c:50
struct rpmds_s * rpmds
Dependency tag sets from a header, so that a header can be discarded early.
Definition: rpmtypes.h:28
int headerNext(HeaderIterator hi, HE_t he, unsigned int flags)
Return next tag from header.
Definition: header.c:2158
int argiCount(ARGI_t argi)
Return no.
Definition: argv.c:55
rpmRC rpmaugRun(rpmaug aug, const char *str, const char **resultp)
Run augeas commands from a buffer.
Definition: rpmaug.c:763
rpmds rpmdsFree(rpmds ds)
Destroy a dependency set.
char * headerSprintf(Header h, const char *fmt, headerTagTableEntry tags, headerSprintfExtension exts, errmsg_t *errmsg)
Return formatted output string from header tags.
Definition: hdrfmt.c:6730
void rpmluaPushTable(rpmlua _lua, const char *key,...)
void rpmluavSetValue(rpmluav var, rpmluavType type, const void *value)
static rpmuint32_t hLoadTID(Header h, rpmTag tag)
Load a transaction id from a header.
Definition: psm.c:1882
int rpmfiFC(rpmfi fi)
Return file count from file info set.
Definition: rpmfi.c:87
struct rpmte_s * rpmte
An element of a transaction set, i.e.
Definition: rpmtypes.h:38
static rpmop fdstat_op(FD_t fd, fdOpX opx)
unsigned int * ARGint_t
Definition: argv.h:14
#define _fd(_a)
Definition: psm.h:32
const char * rpmteE(rpmte te)
Retrieve epoch string of transaction element.
Definition: rpmte.c:321
static int postPopulateInstallHeader(const rpmts ts, const rpmpsm psm, rpmfi fi)
Add fi->states to an install header.
Definition: psm.c:2161
Definition: psm.h:40
const char * rpmtsCurrDir(rpmts ts)
Get transaction currDir, i.e.
Definition: rpmts.c:953
int rpmmiGrow(rpmmi mi, const uint32_t *hdrNums, int nHdrNums)
Append items to set of package instances to iterate.
Definition: rpmdb.c:2479
rpmsql rpmsqlNew(char **av, uint32_t flags)
Create and load a sql interpreter.
Definition: rpmsql.c:5450
void rpmluaPop(rpmlua _lua)
rpmpython rpmpythonFree(rpmpython python)
Destroy a python interpreter.
enum evrFlags_e evrFlags
Dependency Attributes.
char * alloca()
int Chown(const char *path, uid_t owner, gid_t group)
chown(2) clone.
Definition: rpmrpc.c:1674
unsigned int rpmuint32_t
Definition: rpmiotypes.h:28
struct _HE_s * HE_t
Definition: rpmtag.h:59
miRE mireFree(miRE mire)
Free pattern container.
const char * rpmteV(rpmte te)
Retrieve version string of transaction element.
Definition: rpmte.c:326
const char * Fstrerror(FD_t fd)
strerror(3) clone.
Definition: rpmio.c:2401
const char * rpmteNEVR(rpmte te)
Retrieve name-version-release string from transaction element.
Definition: rpmte.c:536
void * xcalloc(size_t nmemb, size_t size)
Definition: rpmmalloc.c:300
void * ptr
Definition: rpmtag.h:67
uint32_t headerSetInstance(Header h, uint32_t instance)
Store header instance (e.g path or URL).
Definition: header.c:1280
struct _FD_s * FD_t
Definition: rpmio.h:43
Definition: psm.h:50
rpmruby rpmrubyNew(char **av, uint32_t flags)
Creates and initializes a Ruby interpreter.
Definition: rpmruby.c:99
rpmioItem rpmioGetPool(rpmioPool pool, size_t size)
Get unused item from pool, or alloc a new item.
Definition: rpmmalloc.c:220
rpmRC rpmpythonRun(rpmpython python, const char *str, const char **resultp)
Execute python string.
Definition: rpmpython.c:159
rpmfi rpmteFI(rpmte te, rpmTag tag)
Retrieve file info tag set from transaction element.
Definition: rpmte.c:587
size_t rpmpkgSizeof(const char *fn, const void *ptr)
Return size of item in bytes.
Definition: pkgio.c:1646
unsigned char rpmuint8_t
Private int typedefs to avoid C99 portability issues.
Definition: rpmiotypes.h:26
struct rpmfi_s * rpmfi
File info tag sets from a header, so that a header can be discarded early.
Definition: rpmfi.h:83
static int hSaveFlinks(Header h, const struct rpmChainLink_s *flink)
Save forward link(s) of an upgrade chain into a header.
Definition: psm.c:1979
int rpmTempFile(const char *prefix, const char **fnptr, void *fdptr)
Return file handle for a temporaray file.
Definition: signature.c:30
int argvCount(const ARGV_t argv)
Return no.
Definition: argv.c:71
int rpmdbRemove(rpmdb db, int rid, uint32_t hdrNum, rpmts ts)
Remove package header from rpm database and indices.
Definition: rpmdb.c:2776
ARGV_t argvData(ARGV_t argv)
Return data from argv array.
Definition: argv.c:80
rpmRC rpmInstallSourcePackage(rpmts ts, void *_fd, const char **specFilePtr, const char **cookie)
Install source package.
Definition: psm.c:212
int rpmsqJoin(void *thread)
Wait for thread to terminate.
Definition: rpmsq.c:671
rpmTagData p
Definition: rpmtag.h:506
struct rpmaug_s * rpmaug
Definition: rpmaug.h:14
Definition: psm.h:54
struct rpmperl_s * rpmperl
Definition: rpmperl.h:11
ARGV_t argvFree(ARGV_t argv)
Destroy an argv array.
Definition: argv.c:44
struct miRE_s * miRE
Definition: mire.h:60
struct rpmluav_s * rpmluav
Definition: rpmlua.h:54
struct stat * headerGetStatbuf(Header h)
Return header stat(2) buffer (of origin *.rpm file).
Definition: header.c:1228
rpmRC rpmficlRun(rpmficl ficl, const char *str, const char **resultp)
Execute ficl string.
Definition: rpmficl.c:140
rpmperl rpmperlNew(char **av, uint32_t flags)
Create and load a perl interpreter.
Definition: rpmperl.c:93
rpmjs rpmjsNew(char **av, uint32_t flags)
Create and load a js interpreter.
Definition: rpmjs.c:171
const char * rpmdsEVR(const rpmds ds)
Return current dependency epoch-version-release.
Definition: rpmds.c:680
struct rpmpython_s * rpmpython
Definition: rpmpython.h:11
#define _PSM_DEBUG
Definition: psm.c:76
static int rpmdbTriggerGlobs(rpmpsm psm)
Definition: psm.c:1418
rpmRC rpmsmRun(rpmsm sm, char **av, const char **resultp)
Run semanage commands.
Definition: rpmsm.c:400
rpmRC rpmReadPackageFile(rpmts ts, FD_t fd, const char *fn, Header *hdrp)
Return package header from file handle, verifying digests/signatures.
Definition: package.c:114
int Glob_pattern_p(const char *pattern, int quote)
glob_pattern_p(3) clone.
Definition: rpmrpc.c:2231
Definition: psm.h:35
enum pkgStage_e pkgStage
int headerMacrosLoad(Header h)
Define per-header macros.
Definition: hdrNVR.c:36
int rpmdsNext(rpmds ds)
Return next dependency set iterator index.
Definition: rpmds.c:912
Structure(s) used for dependency tag sets.
struct rpmtcl_s * rpmtcl
Definition: rpmtcl.h:11
rpmpython rpmpythonNew(char **av, uint32_t flags)
Create and load a python interpreter.
Definition: rpmpython.c:72
The FD_t File Handle data structure.
rpmmi rpmtsInitIterator(const rpmts ts, rpmTag rpmtag, const void *keyp, size_t keylen)
Return transaction database iterator.
Definition: rpmts.c:212
const char * rpmGenPath(const char *urlroot, const char *urlmdir, const char *urlfile)
Merge 3 args into path, any or all of which may be a url.
Definition: macro.c:3477
const char * rpmteD(rpmte te)
Retrieve distepoch string of transaction element.
Definition: rpmte.c:336
struct rpmdb_s * rpmdb
Database of headers and tag value indices.
Definition: rpmtypes.h:43
rpmpsm rpmpsmNew(rpmts ts, rpmte te, rpmfi fi)
Create and load a package state machine.
Definition: psm.c:1850
int rpmtsChrootDone(rpmts ts)
Get chrootDone flag, i.e.
Definition: rpmts.c:1007
int argiSort(ARGI_t argi, int(*compar)(ARGint_t *, ARGint_t *))
Sort an argi array.
Definition: argv.c:125
int argvAdd(ARGV_t *argvp, ARGstr_t val)
Add a string to an argv array.
Definition: argv.c:199
rpmTagCount c
Definition: rpmtag.h:507
int rpmdbMireApply(rpmdb db, rpmTag tag, rpmMireMode mode, const char *pat, const char ***argvp)
Return array of keys matching a pattern.
Definition: rpmdb.c:1486
Generate and verify rpm package signatures.
rpmluav rpmluavNew(void)
int mireRegexec(miRE mire, const char *val, size_t vallen)
Execute pattern match.
Definition: mire.c:396
Definition: psm.h:48
Header headerFree(Header h)
Dereference a header instance.
static int hSaveBlinks(Header h, const struct rpmChainLink_s *blink)
Save backward link(s) of an upgrade chain into a header.
Definition: psm.c:1924
int rpmswEnter(rpmop op, ssize_t rc)
Enter timed operation.
Definition: rpmsw.c:248
rpmRC rpmsquirrelRun(rpmsquirrel squirrel, const char *str, const char **resultp)
Execute squirrel string.
Definition: rpmsquirrel.c:211
const char const bson const bson * op
Definition: mongo.h:505
struct rpmop_s * rpmop
Definition: rpmsw.h:24
char * rpmExpand(const char *arg,...)
Return (malloc'ed) concatenated macro expansion(s).
Definition: macro.c:3238
int Chdir(const char *path)
chdir(2) clone.
Definition: rpmrpc.c:105
static rpmpsm rpmpsmGetPool(rpmioPool pool)
Definition: psm.c:1834
rpmaug rpmaugFree(rpmaug aug)
Destroy a augeas wrapper.
const char * headerGetOrigin(Header h)
Return header origin (e.g path or URL).
Definition: header.c:1184
static const char * pkgStageString(pkgStage a)
Definition: psm.c:1734
int rpmsxExec(rpmsx sx, int verified, const char **argv)
Execute a package scriptlet within SELinux context.
Definition: rpmsx.c:275
int rpmlioPostun(rpmdb rpmdb, const char **av, const char *body)
Definition: rpmlio.c:423
rpmRC rpmMkdirPath(const char *dpath, const char *dname)
Create directory if it does not exist, and make sure path is writable.
Definition: misc.c:19
Embedded Ruby interpreter.
void rpmluaDelVar(rpmlua _lua, const char *key,...)
Header headerRegenSigHeader(const Header h, int noArchiveSize)
Regenerate signature header.
Definition: hdrNVR.c:313
rpmRC rpmpsmStage(rpmpsm psm, pkgStage stage)
Package state machine driver.
Definition: psm.c:2222
void unsetenv(const char *name)
rpmuint8_t * ui8p
Definition: rpmtag.h:68
const char * rpmteO(rpmte te)
Retrieve os string of transaction element.
Definition: rpmte.c:350
const char * rpmteHdrid(rpmte te)
Retrieve hdrid string from transaction element.
Definition: rpmte.c:551
#define F_ISSET(_psm, _FLAG)
Definition: psm.c:51
Header rpmteSetHeader(rpmte te, Header h)
Save header into transaction element.
Definition: rpmte.c:298
const char * rpmdsN(const rpmds ds)
Return current dependency name.
Definition: rpmds.c:668
#define IP
Definition: rpmio.c:1695
rpmmi rpmmiFree(rpmmi mi)
Destroy rpm database iterator.
int Fclose(FD_t fd)
fclose(3) clone.
Definition: rpmio.c:2534
static rpmRC runImmedTriggers(rpmpsm psm)
Run triggers from this header that are fired by headers in the database.
Definition: psm.c:1613
Cumulative statistics for an operation.
Definition: rpmsw.h:39
char * iosmStrerror(int rc)
Return formatted error message on payload handling failure.
Definition: iosm.c:2769
int fsmTeardown(void *_fsm)
Clean file state machine.
Definition: fsm.c:751
struct rpmruby_s * rpmruby
Definition: rpmruby.h:32
rpmuint32_t * rpmteOriginTid(rpmte te)
Retrieve transaction start time that package was first installed.
Definition: rpmte.c:380
int rpmfiNext(rpmfi fi)
Return next file iterator index.
Definition: rpmfi.c:526
static rpmRC runScript(rpmpsm psm, Header h, const char *sln, HE_t Phe, const char *script, int arg1, int arg2)
Run scriptlet with args.
Definition: psm.c:802
Header headerLink(Header h)
Reference a header instance.
rpmuint32_t * rpmteOriginTime(rpmte te)
Retrieve time that package was first installed.
Definition: rpmte.c:385
static const char * SCRIPT_PATH
Definition: psm.c:382
rpmdb rpmtsGetRdb(rpmts ts)
Get transaction set database handle.
Definition: pkgio.c:151
rpmruby rpmrubyFree(rpmruby ruby)
Destroys a Ruby interpreter instance.
struct rpmsquirrel_s * rpmsquirrel
Definition: rpmsquirrel.h:11
int _psm_debug
Definition: psm.c:78
enum rpmRC_e rpmRC
RPM return codes.
void * rpmtxn
Definition: rpmtxn.h:14
int Ferror(FD_t fd)
ferror(3) clone.
Definition: rpmio.c:2944
int rpmmiAddPattern(rpmmi mi, rpmTag tag, rpmMireMode mode, const char *pattern)
Add pattern to iterator selector.
Definition: rpmdb.c:1910
rpmsql rpmsqlFree(rpmsql sql)
Destroy a sql interpreter.
Definition: rpmtag.h:502
Definition: psm.h:39
int rpmmiSetRewrite(rpmmi mi, int rewrite)
Prepare iterator for lazy writes.
Definition: rpmdb.c:2170
rpmfi rpmfiInit(rpmfi fi, int fx)
Initialize file iterator index.
Definition: rpmfi.c:548
Definition: psm.h:47
rpmuint32_t rpmtsColor(rpmts ts)
Retrieve color bits of transaction set.
Definition: rpmts.c:1440
const char const int i
Definition: bson.h:778
Package state machine to handle a package from a transaction set.
static rpmRC runTriggers(rpmpsm psm)
Run trigger scripts in the database that are fired by this header.
Definition: psm.c:1544
static int rpmpsmNext(rpmpsm psm, pkgStage nstage)
Definition: psm.c:2205
urltype urlPath(const char *url, const char **pathp)
Return path component of URL.
Definition: url.c:430
static int snprintf(char *buf, int nb, const char *fmt,...)
Definition: rpmps.c:220
rpmfi rpmfiLink(rpmfi fi, const char *msg)
Reference a file info set instance.
const char const bson const bson bson * out
Definition: mongo.h:678
rpmts rpmtsFree(rpmts ts)
Destroy transaction set, closing the database as well.
rpmds rpmdsLink(rpmds ds, const char *msg)
Reference a dependency set instance.
Definition: iosm.h:29
dbiIndex dbiOpen(rpmdb db, rpmTag tag, unsigned int flags)
Definition: rpmdb.c:223
Methods to handle package elements.
rpmioPool rpmioNewPool(const char *name, size_t size, int limit, int flags, char *(*dbg)(void *item), void(*init)(void *item), void(*fini)(void *item))
Create a memory pool.
Definition: rpmmalloc.c:109
Definition: psm.h:38
int rpmdbCountPackages(rpmdb db, const char *N)
Return number of instances of package in Name index.
Definition: rpmdb.c:1242
char * stpcpy(char *dest, const char *src)
static int ldconfig_done
Definition: psm.c:781
struct rpmts_s * rpmts
The RPM Transaction Set.
Definition: rpmtypes.h:14
void rpmluaSetVar(rpmlua _lua, rpmluav var)
static void * _free(const void *p)
Wrapper to free(3), hides const compilation noise, permit NULL, return NULL.
Definition: rpmiotypes.h:756
Header headerReload(Header h, rpmTag tag)
Convert header to on-disk representation, and then reload.
Definition: header.c:1314
int rpmmiSetModified(rpmmi mi, int modified)
Modify iterator to mark header for lazy write on release.
Definition: rpmdb.c:2183
Structures and prototypes used for an "rpmts" transaction set.
Header rpmmiNext(rpmmi mi)
Return next package header from iteration.
Definition: rpmdb.c:2252
rpmfi fi
Definition: filetriggers.h:15
FD_t Fdopen(FD_t ofd, const char *fmode)
Definition: rpmio.c:2718
rpmVSFlags rpmtsVSFlags(rpmts ts)
Get verify signatures flag(s).
Definition: rpmts.c:840
static rpmScriptID tag2slx(rpmTag tag)
Return scriptlet id from tag.
Definition: psm.c:420
File state machine to handle a payload within an rpm package.
const char * db
Definition: mongo.h:697
int argiAdd(ARGI_t *argip, int ix, int val)
Add an int to an argi array.
Definition: argv.c:178
int _psm_threads
Definition: psm.c:80
rpmRC rpmsqlRun(rpmsql sql, const char *str, const char **resultp)
Execute sql from STRING | FILE | STDIN | INTERACTIVE.
Definition: rpmsql.c:5554
int fsmSetup(void *_fsm, iosmFileStage goal, const char *afmt, const void *_ts, const void *_fi, FD_t cfd, unsigned int *archiveSize, const char **failedFile)
Load external data into file state machine.
Definition: fsm.c:627
static rpmRC handleOneTrigger(const rpmpsm psm, Header sourceH, Header triggeredH, int arg2)
Execute triggers.
Definition: psm.c:1247
#define rpmIsVerbose()
Definition: rpmcb.h:21
rpmtcl rpmtclFree(rpmtcl tcl)
Destroy a tcl interpreter.
int rpmdsMatch(const rpmds A, rpmds B)
Compare A against every member of B, looking for 1st match.
Definition: rpmds.c:4179
rpmpsm rpmpsmFree(rpmpsm psm, const char *msg)
Destroy a package state machine.
struct rpmlua_s * rpmlua
Definition: rpmlua.h:53
int Fileno(FD_t fd)
fileno(3) clone.
Definition: rpmio.c:2991
static rpmRC runInstScript(rpmpsm psm)
Retrieve and run scriptlet from header.
Definition: psm.c:1192
struct rpmficl_s * rpmficl
Definition: rpmficl.h:11
static const char * name
rpmRC rpmrubyRun(rpmruby ruby, const char *str, const char **resultp)
Evaluates Ruby code stored in a string.
Definition: rpmruby.c:126
#define rpmIsDebug()
Definition: rpmcb.h:23
int mireAppend(rpmMireMode mode, int tag, const char *pattern, const unsigned char *table, miRE *mirep, int *nmirep)
Append pattern to array.
Definition: mire.c:497
static const char * ldconfig_path
Definition: psm.c:784
#define _(Text)
Definition: system.h:29
int rpmdbAdd(rpmdb db, int iid, Header h, rpmts ts)
Add package header to rpm database and indices.
Definition: rpmdb.c:2887
rpmficl rpmficlFree(rpmficl ficl)
Destroy a ficl interpreter.
const char const char * pattern
Definition: bson.h:971
#define xmalloc
Definition: system.h:32
void rpmteSetDBInstance(rpmte te, unsigned int instance)
Set last instance installed to the database.
Definition: rpmte.c:285
int rpmtsSELinuxEnabled(rpmts ts)
Get selinuxEnabled flag, i.e.
Definition: rpmts.c:999
static rpmRC runTriggersLoop(rpmpsm psm, rpmTag tagno, int arg2)
Run a dependency set loop against rpmdb triggers.
Definition: psm.c:1449
Database transaction wrappers.
rpmuint32_t rpmtsGetTid(rpmts ts)
Get transaction id, i.e.
Definition: rpmts.c:1024
rpmRC rpmjsRun(rpmjs js, const char *str, const char **resultp)
Execute js string.
Definition: rpmjs.c:410
ARGstr_t * ARGV_t
Definition: argv.h:12
Access RPM indices using Berkeley DB interface(s).
enum rpmTag_e rpmTag
Definition: rpmtag.h:470
#define D_(Text)
Definition: system.h:526
rpmds rpmdsNew(Header h, rpmTag tagN, int flags)
Create and load a dependency set.
Definition: rpmds.c:238
int rpmdsSetNoPromote(rpmds ds, int nopromote)
Set "Don't promote Epoch:" flag.
Definition: rpmds.c:755
rpmtransFlags rpmtsFlags(rpmts ts)
Get transaction flags, i.e.
Definition: rpmts.c:1334
rpmsquirrel rpmsquirrelNew(char **av, uint32_t flags)
Definition: rpmsquirrel.c:106
rpmperl rpmperlFree(rpmperl perl)
Destroy a perl interpreter.
Definition: argv.h:16
rpmtcl rpmtclNew(char **av, uint32_t flags)
Create and load a tcl interpreter.
Definition: rpmtcl.c:125
rpmRC rpmpsmScriptStage(rpmpsm psm, rpmTag scriptTag, rpmTag progTag)
Run rpmpsmStage(PSM_SCRIPT) for scriptTag and progTag.
Definition: psm.c:1788
unsigned int rpmmiCount(rpmmi mi)
Return number of elements in rpm database iterator.
Definition: rpmdb.c:1763
Header headerNew(void)
Create new (empty) header instance.
Definition: header.c:180
int rpmtxnAbort(rpmtxn txn)
Definition: rpmtxn.c:47
rpmRC rpmperlRun(rpmperl perl, const char *str, const char **resultp)
Execute perl string.
Definition: rpmperl.c:144
Definition: psm.h:36
const char * rpmteR(rpmte te)
Retrieve release string of transaction element.
Definition: rpmte.c:331
uint32_t headerGetInstance(Header h)
Return header instance (if from rpmdb).
Definition: header.c:1275
ARGint_t argiData(ARGI_t argi)
Return data from argi array.
Definition: argv.c:63
In Memoriam: Steve Taylor staylor@redhat.com was here, now he's not.
rpmpsm rpmpsmLink(rpmpsm psm, const char *msg)
Reference a package state machine instance.
#define RPMDBI_PACKAGES
Pseudo-tags used by the rpmdb and rpmgi iterator API's.
Definition: rpmtag.h:479
FD_t rpmtsScriptFd(rpmts ts)
Definition: rpmts.c:971
rpmuint32_t rpmTagCount
Definition: rpmtag.h:55
int rpmdsNegateRC(const rpmds ds, int rc)
Negate return code for negated comparisons.
Definition: rpmds.c:4352
int rpmluaRunScript(rpmlua _lua, const char *script, const char *name)
void rpmtsClean(rpmts ts)
Free memory needed only for dependency checks and ordering.
Definition: rpmts.c:598
static pid_t psmWait(rpmpsm psm)
Wait for child process to be reaped.
Definition: psm.c:450
rpmRC rpmtclRun(rpmtcl tcl, const char *str, const char **resultp)
Execute tcl string.
Definition: rpmtcl.c:179
#define W_OK
Definition: system.h:233
#define F_CLR(_psm, _FLAG)
Definition: psm.c:56
int j
Definition: mongo.h:438
const char const bson int num
Definition: mongo.h:485
unsigned long int rpmtime_t
Definition: rpmsw.h:16
struct _dbiIndex * dbiIndex
Definition: rpmdb.h:59
#define RPMTE_CHAIN_END
Definition: rpmte.h:722
void rpmpsmSetAsync(rpmpsm psm, int async)
Definition: psm.c:1774
int Unlink(const char *path)
unlink(2) clone.
Definition: rpmrpc.c:397