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