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