1 /** \ingroup rpmts payload
3 * Package state machine to handle a package from a transaction set.
8 #include <rpm/rpmlib.h> /* rpmvercmp and others */
9 #include <rpm/rpmmacro.h>
10 #include <rpm/rpmurl.h>
11 #include <rpm/rpmds.h>
12 #include <rpm/rpmts.h>
13 #include <rpm/rpmfileutil.h> /* rpmMkTemp() */
14 #include <rpm/rpmdb.h> /* XXX for db_chrootDone */
15 #include <rpm/rpmlog.h>
16 #include <rpm/rpmstring.h>
19 #include "rpmio/rpmlua.h"
21 #include "lib/fsm.h" /* XXX CPIO_FOO/FSM_FOO constants */
23 #include "lib/rpmfi_internal.h" /* XXX replaced/states... */
24 #include "lib/rpmte_internal.h" /* XXX internal apis */
25 #include "lib/rpmlead.h" /* writeLead proto */
26 #include "lib/signature.h" /* signature constants */
31 int _psm_debug = _PSM_DEBUG;
37 struct rpmsqElem sq; /*!< Scriptlet/signal queue element. */
39 rpmts ts; /*!< transaction set */
40 rpmte te; /*!< current transaction element */
41 rpmfi fi; /*!< transaction element file info */
42 const char * stepName;
45 int scriptTag; /*!< Scriptlet data tag. */
46 int progTag; /*!< Scriptlet interpreter tag. */
47 int npkgs_installed; /*!< No. of installed instances. */
48 int scriptArg; /*!< Scriptlet package arg. */
49 rpmsenseFlags sense; /*!< One of RPMSENSE_TRIGGER{PREIN,IN,UN,POSTUN}. */
50 int countCorrection; /*!< 0 if installing, -1 if removing. */
51 int chrootDone; /*!< Was chroot(2) done by pkgStage? */
52 rpmCallbackType what; /*!< Callback type. */
53 rpm_loff_t amount; /*!< Callback amount. */
54 rpm_loff_t total; /*!< Callback total. */
56 pkgStage stage; /*!< Current psm stage. */
57 pkgStage nstage; /*!< Next psm stage. */
59 int nrefs; /*!< Reference count. */
62 int rpmVersionCompare(Header first, Header second)
64 /* Missing epoch becomes zero here, which is what we want */
65 uint32_t epochOne = headerGetNumber(first, RPMTAG_EPOCH);
66 uint32_t epochTwo = headerGetNumber(second, RPMTAG_EPOCH);
69 if (epochOne < epochTwo)
71 else if (epochOne > epochTwo)
74 rc = rpmvercmp(headerGetString(first, RPMTAG_VERSION),
75 headerGetString(second, RPMTAG_VERSION));
79 return rpmvercmp(headerGetString(first, RPMTAG_RELEASE),
80 headerGetString(second, RPMTAG_RELEASE));
84 * Macros to be defined from per-header tag values.
85 * @todo Should other macros be added from header when installing a package?
87 static struct tagMacro {
88 const char *macroname; /*!< Macro name to define. */
89 rpmTag tag; /*!< Header tag to use for value. */
90 } const tagMacros[] = {
91 { "name", RPMTAG_NAME },
92 { "version", RPMTAG_VERSION },
93 { "release", RPMTAG_RELEASE },
94 { "epoch", RPMTAG_EPOCH },
99 * Define per-header macros.
103 static void rpmInstallLoadMacros(Header h)
105 const struct tagMacro * tagm;
107 for (tagm = tagMacros; tagm->macroname != NULL; tagm++) {
110 if (!headerGet(h, tagm->tag, &td, HEADERGET_DEFAULT))
113 switch (rpmtdType(&td)) {
115 body = rpmtdFormat(&td, RPMTD_FORMAT_STRING, NULL);
116 addMacro(NULL, tagm->macroname, NULL, body, -1);
127 * Mark files in database shared with this package as "replaced".
128 * @param psm package state machine data
131 static rpmRC markReplacedFiles(const rpmpsm psm)
133 const rpmts ts = psm->ts;
134 rpmfs fs = rpmteGetFileStates(psm->te);
135 sharedFileInfo replaced = rpmfsGetReplaced(fs);
137 rpmdbMatchIterator mi;
147 for (sfi = replaced; sfi; sfi=rpmfsNextReplaced(fs, sfi)) {
148 if (prev && prev == sfi->otherPkg)
150 prev = sfi->otherPkg;
156 offsets = xmalloc(num * sizeof(*offsets));
159 for (sfi = replaced; sfi; sfi=rpmfsNextReplaced(fs, sfi)) {
160 if (prev && prev == sfi->otherPkg)
162 prev = sfi->otherPkg;
163 offsets[num++] = sfi->otherPkg;
166 mi = rpmtsInitIterator(ts, RPMDBI_PACKAGES, NULL, 0);
167 xx = rpmdbAppendIterator(mi, offsets, num);
168 xx = rpmdbSetIteratorRewrite(mi, 1);
171 while ((h = rpmdbNextIterator(mi)) != NULL) {
173 struct rpmtd_s secStates;
176 if (!headerGet(h, RPMTAG_FILESTATES, &secStates, HEADERGET_MINMEM))
179 prev = rpmdbGetIteratorOffset(mi);
181 while (sfi && sfi->otherPkg == prev) {
182 int ix = rpmtdSetIndex(&secStates, sfi->otherFileNum);
185 char *state = rpmtdGetChar(&secStates);
186 if (state && *state != RPMFILE_STATE_REPLACED) {
187 *state = RPMFILE_STATE_REPLACED;
189 /* Modified header will be rewritten. */
191 xx = rpmdbSetIteratorModified(mi, modified);
195 sfi=rpmfsNextReplaced(fs, sfi);
197 rpmtdFreeData(&secStates);
199 mi = rpmdbFreeIterator(mi);
205 static int rpmlibDeps(Header h)
207 rpmds req = rpmdsInit(rpmdsNew(h, RPMTAG_REQUIRENAME, 0));
209 rpmdsRpmlib(&rpmlib, NULL);
212 while (rpmdsNext(req) >= 0) {
213 if (!(rpmdsFlags(req) & RPMSENSE_RPMLIB))
215 if (rpmdsSearch(rpmlib, req) < 0) {
217 nvr = headerGetAsString(h, RPMTAG_NEVRA);
218 rpmlog(RPMLOG_ERR, _("Missing rpmlib features for %s:\n"), nvr);
220 rpmlog(RPMLOG_ERR, "\t%s\n", rpmdsDNEVR(req)+2);
230 rpmRC rpmInstallSourcePackage(rpmts ts, FD_t fd,
231 char ** specFilePtr, char ** cookie)
234 char * specFile = NULL;
235 const char *rootdir = rpmtsRootDir(ts);
241 struct rpmtd_s filenames;
243 rpmtdReset(&filenames);
244 rpmrc = rpmReadPackageFile(ts, fd, RPMDBG_M("InstallSourcePackage"), &h);
246 case RPMRC_NOTTRUSTED:
257 rpmrc = RPMRC_FAIL; /* assume failure */
259 if (!headerIsSource(h)) {
260 rpmlog(RPMLOG_ERR, _("source package expected, binary found\n"));
264 /* src.rpm install can require specific rpmlib features, check them */
268 if (headerGet(h, RPMTAG_BASENAMES, &filenames, HEADERGET_ALLOC)) {
271 const char *_cookie = headerGetString(h, RPMTAG_COOKIE);
272 if (cookie && _cookie) *cookie = xstrdup(_cookie);
274 /* Try to find spec by file flags */
275 if (_cookie && headerGet(h, RPMTAG_FILEFLAGS, &td, HEADERGET_MINMEM)) {
277 while (specix < 0 && (flags = rpmtdNextUint32(&td))) {
278 if (*flags & RPMFILE_SPECFILE)
279 specix = rpmtdGetIndex(&td);
282 /* Still no spec? Look by filename. */
283 while (specix < 0 && (str = rpmtdNextString(&filenames))) {
284 if (rpmFileHasSuffix(str, ".spec"))
285 specix = rpmtdGetIndex(&filenames);
289 if (rootdir && rstreq(rootdir, "/"))
292 /* Macros need to be added before trying to create directories */
293 rpmInstallLoadMacros(h);
298 headerDel(h, RPMTAG_BASENAMES);
299 headerDel(h, RPMTAG_DIRNAMES);
300 headerDel(h, RPMTAG_DIRINDEXES);
302 rpmtdInit(&filenames);
303 for (int i = 0; (bn = rpmtdNextString(&filenames)); i++) {
304 int spec = (i == specix);
305 char *fn = rpmGenPath(rpmtsRootDir(ts),
306 spec ? "%{_specdir}" : "%{_sourcedir}", bn);
307 headerPutString(h, RPMTAG_OLDFILENAMES, fn);
308 if (spec) specFile = xstrdup(fn);
311 headerConvert(h, HEADERCONV_COMPRESSFILELIST);
313 rpmlog(RPMLOG_ERR, _("source package contains no .spec file\n"));
317 if (rpmtsAddInstallElement(ts, h, NULL, 0, NULL)) {
321 te = rpmtsElement(ts, 0);
322 if (te == NULL) { /* XXX can't happen */
327 rpmteSetHeader(te, h);
328 fi = rpmfiNew(ts, h, RPMTAG_BASENAMES, RPMFI_KEEPHEADER);
331 if (fi == NULL) { /* XXX can't happen */
334 fi->apath = filenames.data; /* Ick */
338 if (rpmMkdirs(rpmtsRootDir(ts), "%{_topdir}:%{_sourcedir}:%{_specdir}")) {
343 /* set all files to be installed */
344 rpmfs fs = rpmteGetFileStates(te);
346 unsigned int fc = rpmfiFC(fi);
347 for (i=0; i<fc; i++) rpmfsSetAction(fs, i, FA_CREATE);
350 psm = rpmpsmNew(ts, te);
351 psm->goal = PSM_PKGINSTALL;
353 /* FIX: psm->fi->dnl should be owned. */
354 if (rpmpsmStage(psm, PSM_PROCESS) == RPMRC_OK)
357 (void) rpmpsmStage(psm, PSM_FINI);
358 psm = rpmpsmFree(psm);
361 if (specFilePtr && specFile && rpmrc == RPMRC_OK)
362 *specFilePtr = specFile;
364 specFile = _free(specFile);
366 if (h != NULL) h = headerFree(h);
367 if (fi != NULL) fi = rpmfiFree(fi);
369 /* XXX nuke the added package(s). */
375 static const char * const SCRIPT_PATH = "PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin";
378 * Return scriptlet name from tag.
379 * @param tag scriptlet tag
380 * @return name of scriptlet
382 static const char * tag2sln(rpmTag tag)
384 switch ((rpm_tag_t) tag) {
385 case RPMTAG_PRETRANS: return "%pretrans";
386 case RPMTAG_TRIGGERPREIN: return "%triggerprein";
387 case RPMTAG_PREIN: return "%pre";
388 case RPMTAG_POSTIN: return "%post";
389 case RPMTAG_TRIGGERIN: return "%triggerin";
390 case RPMTAG_TRIGGERUN: return "%triggerun";
391 case RPMTAG_PREUN: return "%preun";
392 case RPMTAG_POSTUN: return "%postun";
393 case RPMTAG_POSTTRANS: return "%posttrans";
394 case RPMTAG_TRIGGERPOSTUN: return "%triggerpostun";
395 case RPMTAG_VERIFYSCRIPT: return "%verify";
398 return "%unknownscript";
401 static rpmTag triggertag(rpmsenseFlags sense)
403 rpmTag tag = RPMTAG_NOT_FOUND;
405 case RPMSENSE_TRIGGERIN:
406 tag = RPMTAG_TRIGGERIN;
408 case RPMSENSE_TRIGGERUN:
409 tag = RPMTAG_TRIGGERUN;
411 case RPMSENSE_TRIGGERPOSTUN:
412 tag = RPMTAG_TRIGGERPOSTUN;
414 case RPMSENSE_TRIGGERPREIN:
415 tag = RPMTAG_TRIGGERPREIN;
424 * Wait for child process to be reaped.
425 * @param psm package state machine data
428 static pid_t psmWait(rpmpsm psm)
430 const rpmts ts = psm->ts;
433 (void) rpmsqWait(&psm->sq);
434 msecs = psm->sq.op.usecs/1000;
435 (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_SCRIPTLETS), &psm->sq.op);
438 "%s: waitpid(%d) rc %d status %x secs %u.%03u\n",
439 psm->stepName, (unsigned)psm->sq.child,
440 (unsigned)psm->sq.reaped, psm->sq.status,
441 (unsigned)msecs/1000, (unsigned)msecs%1000);
443 return psm->sq.reaped;
447 * Run internal Lua script.
449 static rpmRC runLuaScript(rpmpsm psm, Header h, rpmTag stag, ARGV_t argv,
450 const char *script, int arg1, int arg2)
452 rpmRC rc = RPMRC_FAIL;
454 const rpmts ts = psm->ts;
459 rpmlua lua = NULL; /* Global state. */
462 rasprintf(&sname, "%s(%s)", tag2sln(stag), rpmteNEVRA(psm->te));
464 rpmlog(RPMLOG_DEBUG, "%s: %s running <lua> scriptlet.\n",
465 psm->stepName, sname);
466 if (!rpmtsChrootDone(ts)) {
467 const char *rootDir = rpmtsRootDir(ts);
469 rootFd = open(".", O_RDONLY, 0);
471 if (rootDir != NULL && !rstreq(rootDir, "/") && *rootDir == '/')
472 xx = chroot(rootDir);
473 xx = rpmtsSetChrootDone(ts, 1);
477 /* Create arg variable */
478 rpmluaPushTable(lua, "arg");
480 rpmluavSetListMode(var, 1);
483 for (p = argv; *p; p++) {
484 rpmluavSetValue(var, RPMLUAV_STRING, *p);
485 rpmluaSetVar(lua, var);
489 rpmluavSetValueNum(var, arg1);
490 rpmluaSetVar(lua, var);
493 rpmluavSetValueNum(var, arg2);
494 rpmluaSetVar(lua, var);
496 var = rpmluavFree(var);
499 if (rpmluaRunScript(lua, script, sname) == 0) {
501 } else if ((stag != RPMTAG_PREIN && stag != RPMTAG_PREUN)) {
505 rpmluaDelVar(lua, "arg");
508 const char *rootDir = rpmtsRootDir(ts);
511 if (rootDir != NULL && !rstreq(rootDir, "/") && *rootDir == '/')
513 xx = rpmtsSetChrootDone(ts, 0);
517 rpmlog(RPMLOG_ERR, _("<lua> scriptlet support not built in\n"));
520 if (rc != RPMRC_OK) {
524 (void) rpmtsNotify(ts, psm->te, RPMCALLBACK_SCRIPT_ERROR, stag, rc);
529 static void doScriptExec(rpmts ts, ARGV_const_t argv, rpmtd prefixes,
530 FD_t scriptFd, FD_t out)
532 const char * rootDir;
539 (void) signal(SIGPIPE, SIG_DFL);
540 pipes[0] = pipes[1] = 0;
541 /* make stdin inaccessible */
543 xx = close(pipes[1]);
544 xx = dup2(pipes[0], STDIN_FILENO);
545 xx = close(pipes[0]);
547 /* XXX Force FD_CLOEXEC on all inherited fdno's. */
548 open_max = sysconf(_SC_OPEN_MAX);
549 if (open_max == -1) {
552 for (fdno = 3; fdno < open_max; fdno++) {
553 flag = fcntl(fdno, F_GETFD);
554 if (flag == -1 || (flag & FD_CLOEXEC))
556 xx = fcntl(fdno, F_SETFD, FD_CLOEXEC);
557 /* XXX W2DO? debug msg for inheirited fdno w/o FD_CLOEXEC */
560 if (scriptFd != NULL) {
561 int sfdno = Fileno(scriptFd);
562 int ofdno = Fileno(out);
563 if (sfdno != STDERR_FILENO)
564 xx = dup2(sfdno, STDERR_FILENO);
565 if (ofdno != STDOUT_FILENO)
566 xx = dup2(ofdno, STDOUT_FILENO);
567 /* make sure we don't close stdin/stderr/stdout by mistake! */
568 if (ofdno > STDERR_FILENO && ofdno != sfdno)
570 if (sfdno > STDERR_FILENO && ofdno != sfdno)
571 xx = Fclose (scriptFd);
574 { char *ipath = rpmExpand("%{_install_script_path}", NULL);
575 const char *path = SCRIPT_PATH;
577 if (ipath && ipath[5] != '%')
580 xx = setenv("PATH", path, 1);
581 ipath = _free(ipath);
584 if (rpmtdCount(prefixes) > 0) {
586 /* backwards compatibility */
587 if ((pfx = rpmtdGetString(prefixes))) {
588 xx = setenv("RPM_INSTALL_PREFIX", pfx, 1);
591 while ((pfx = rpmtdNextString(prefixes))) {
593 rasprintf(&name, "RPM_INSTALL_PREFIX%d", rpmtdGetIndex(prefixes));
594 xx = setenv(name, pfx, 1);
599 rootDir = rpmtsRootDir(ts);
600 if (rootDir != NULL) { /* XXX can't happen */
601 if (!rpmtsChrootDone(ts) &&
602 !(rootDir[0] == '/' && rootDir[1] == '\0'))
604 xx = chroot(rootDir);
608 /* XXX Don't mtrace into children. */
609 unsetenv("MALLOC_CHECK_");
611 /* Permit libselinux to do the scriptlet exec. */
612 if (rpmtsSELinuxEnabled(ts) == 1) {
613 xx = rpm_execcon(0, argv[0], argv, environ);
617 xx = execv(argv[0], argv);
620 _exit(127); /* exit 127 for compatibility with bash(1) */
624 * Run scriptlet with args.
626 * Run a script with an interpreter. If the interpreter is not specified,
627 * /bin/sh will be used. If the interpreter is /bin/sh, then the args from
628 * the header will be ignored, passing instead arg1 and arg2.
630 * @param psm package state machine data
632 * @param stag scriptlet section tag
633 * @param argvp ARGV_t pointer to args from header, *argvp[0] is the
634 * interpreter to use. Pointer as we might need to
635 * modify via argvAdd()
636 * @param script scriptlet from header
637 * @param arg1 no. instances of package installed after scriptlet exec
639 * @param arg2 ditto, but for the target package
640 * @return 0 on success
642 static rpmRC runScript(rpmpsm psm, Header h, rpmTag stag, ARGV_t * argvp,
643 const char * script, int arg1, int arg2)
645 const rpmts ts = psm->ts;
650 rpmRC rc = RPMRC_FAIL; /* assume failure */
653 struct rpmtd_s prefixes;
655 assert(argvp != NULL);
656 if (*argvp == NULL && script == NULL)
659 if (*argvp && *argvp[0] && rstreq(*argvp[0], "<lua>")) {
660 return runLuaScript(psm, h, stag, *argvp, script, arg1, arg2);
662 rasprintf(&sname, "%s(%s)", tag2sln(stag), rpmteNEVRA(psm->te));
666 rpmlog(RPMLOG_DEBUG, "%s: %s scriptlet start\n", psm->stepName, sname);
668 if (argvCount(*argvp) == 0) {
669 argvAdd(argvp, "/bin/sh");
672 /* Try new style prefixes first, then old. Otherwise there are none.. */
673 if (!headerGet(h, RPMTAG_INSTPREFIXES, &prefixes, HEADERGET_DEFAULT)) {
674 headerGet(h, RPMTAG_INSTALLPREFIX, &prefixes, HEADERGET_DEFAULT);
678 const char * rootDir = rpmtsRootDir(ts);
681 fd = rpmMkTempFile((!rpmtsChrootDone(ts) ? rootDir : "/"), &fn);
682 if (fd == NULL || Ferror(fd)) {
683 rpmlog(RPMLOG_ERR, _("Couldn't create temporary file for %s: %s\n"),
684 sname, strerror(errno));
689 (rstreq(*argvp[0], "/bin/sh") || rstreq(*argvp[0], "/bin/bash")))
691 static const char set_x[] = "set -x\n";
692 xx = Fwrite(set_x, sizeof(set_x[0]), sizeof(set_x)-1, fd);
695 xx = Fwrite(script, sizeof(script[0]), strlen(script), fd);
698 { const char * sn = fn;
699 if (!rpmtsChrootDone(ts) && rootDir != NULL &&
700 !(rootDir[0] == '/' && rootDir[1] == '\0'))
702 sn += strlen(rootDir)-1;
708 argvAddNum(argvp, arg1);
711 argvAddNum(argvp, arg2);
715 scriptFd = rpmtsScriptFd(ts);
716 if (scriptFd != NULL) {
717 if (rpmIsVerbose()) {
718 out = fdDup(Fileno(scriptFd));
720 out = Fopen("/dev/null", "w.fdio");
722 out = fdDup(Fileno(scriptFd));
726 out = fdDup(STDOUT_FILENO);
729 rpmlog(RPMLOG_ERR, _("Couldn't duplicate file descriptor: %s: %s\n"),
730 sname, strerror(errno));
734 xx = rpmsqFork(&psm->sq);
735 if (psm->sq.child == 0) {
736 rpmlog(RPMLOG_DEBUG, "%s: %s\texecv(%s) pid %d\n",
737 psm->stepName, sname, *argvp[0], (unsigned)getpid());
738 doScriptExec(ts, *argvp, &prefixes, scriptFd, out);
741 if (psm->sq.child == (pid_t)-1) {
742 rpmlog(RPMLOG_ERR, _("Couldn't fork %s: %s\n"), sname, strerror(errno));
748 if (psm->sq.reaped < 0) {
749 rpmlog(RPMLOG_ERR, _("%s scriptlet failed, waitpid(%d) rc %d: %s\n"),
750 sname, psm->sq.child, psm->sq.reaped, strerror(errno));
751 } else if (!WIFEXITED(psm->sq.status) || WEXITSTATUS(psm->sq.status)) {
752 if (WIFSIGNALED(psm->sq.status)) {
753 rpmlog(RPMLOG_ERR, _("%s scriptlet failed, signal %d\n"),
754 sname, WTERMSIG(psm->sq.status));
756 /* filter out "regular" error exits from non-pre scriptlets */
757 if ((stag != RPMTAG_PREIN && stag != RPMTAG_PREUN)) {
760 rpmlog(warn_only ? RPMLOG_WARNING : RPMLOG_ERR,
761 _("%s scriptlet failed, exit status %d\n"),
762 sname, WEXITSTATUS(psm->sq.status));
765 /* if we get this far we're clear */
770 rpmtdFreeData(&prefixes);
772 /* notify callback for all errors, "total" abused for warning/error */
773 if (rc != RPMRC_OK) {
777 (void) rpmtsNotify(ts, psm->te, RPMCALLBACK_SCRIPT_ERROR, stag, rc);
781 xx = Fclose(out); /* XXX dup'd STDOUT_FILENO */
794 * Retrieve and run scriptlet from header.
795 * @param psm package state machine data
796 * @return rpmRC return code
798 static rpmRC runInstScript(rpmpsm psm)
802 struct rpmtd_s script, prog;
804 Header h = rpmteHeader(psm->te);
806 if (h == NULL) /* XXX can't happen */
809 headerGet(h, psm->scriptTag, &script, HEADERGET_DEFAULT);
810 headerGet(h, psm->progTag, &prog, HEADERGET_DEFAULT);
811 if (rpmtdCount(&script) == 0 && rpmtdCount(&prog) == 0)
815 while ((str = rpmtdNextString(&prog))) {
819 rc = runScript(psm, h, psm->scriptTag, &argv,
820 rpmtdGetString(&script), psm->scriptArg, -1);
824 rpmtdFreeData(&script);
825 rpmtdFreeData(&prog);
832 * @todo Trigger on any provides, not just package NVR.
833 * @param psm package state machine data
834 * @param sourceH header of trigger source
835 * @param trigH header of triggered package
837 * @param triggersAlreadyRun
840 static rpmRC handleOneTrigger(const rpmpsm psm,
841 Header sourceH, Header trigH,
842 int arg2, unsigned char * triggersAlreadyRun)
844 const rpmts ts = psm->ts;
845 rpmds trigger = NULL;
846 const char * sourceName = headerGetString(sourceH, RPMTAG_NAME);
847 const char * triggerName = headerGetString(trigH, RPMTAG_NAME);
851 trigger = rpmdsInit(rpmdsNew(trigH, RPMTAG_TRIGGERNAME, 0));
855 (void) rpmdsSetNoPromote(trigger, 1);
857 while ((i = rpmdsNext(trigger)) >= 0) {
859 rpmsenseFlags Flags = rpmdsFlags(trigger);
860 struct rpmtd_s tscripts, tprogs, tindexes;
861 headerGetFlags hgflags = HEADERGET_MINMEM;
863 if ((Name = rpmdsN(trigger)) == NULL)
864 continue; /* XXX can't happen */
866 if (!rstreq(Name, sourceName))
868 if (!(Flags & psm->sense))
872 * XXX Trigger on any provided dependency, not just the package NEVR.
874 if (!rpmdsAnyMatchesDep(sourceH, trigger, 1))
877 if (!(headerGet(trigH, RPMTAG_TRIGGERINDEX, &tindexes, hgflags) &&
878 headerGet(trigH, RPMTAG_TRIGGERSCRIPTS, &tscripts, hgflags) &&
879 headerGet(trigH, RPMTAG_TRIGGERSCRIPTPROG, &tprogs, hgflags))) {
885 const char ** triggerScripts = tscripts.data;
886 const char ** triggerProgs = tprogs.data;
887 uint32_t * triggerIndices = tindexes.data;
889 arg1 = rpmdbCountPackages(rpmtsGetRdb(ts), triggerName);
891 /* XXX W2DO? fails as "execution of script failed" */
894 arg1 += psm->countCorrection;
895 index = triggerIndices[i];
896 if (triggersAlreadyRun == NULL ||
897 triggersAlreadyRun[index] == 0)
899 ARGV_t argv = argvNew();
900 argvAdd(&argv, *(triggerProgs + index));
901 rc = runScript(psm, trigH, triggertag(psm->sense),
902 &argv, triggerScripts[index],
904 if (triggersAlreadyRun != NULL)
905 triggersAlreadyRun[index] = 1;
911 rpmtdFreeData(&tindexes);
912 rpmtdFreeData(&tscripts);
913 rpmtdFreeData(&tprogs);
916 * Each target/source header pair can only result in a single
922 trigger = rpmdsFree(trigger);
928 * Run trigger scripts in the database that are fired by this header.
929 * @param psm package state machine data
930 * @return 0 on success
932 static rpmRC runTriggers(rpmpsm psm)
934 const rpmts ts = psm->ts;
937 const char * N = NULL;
939 if (psm->te) /* XXX can't happen */
941 if (N) /* XXX can't happen */
942 numPackage = rpmdbCountPackages(rpmtsGetRdb(ts), N)
943 + psm->countCorrection;
945 return RPMRC_NOTFOUND;
948 Header h = rpmteHeader(psm->te);
949 rpmdbMatchIterator mi;
950 int countCorrection = psm->countCorrection;
952 psm->countCorrection = 0;
953 mi = rpmtsInitIterator(ts, RPMTAG_TRIGGERNAME, N, 0);
954 while((triggeredH = rpmdbNextIterator(mi)) != NULL)
955 rc |= handleOneTrigger(psm, h, triggeredH, numPackage, NULL);
956 mi = rpmdbFreeIterator(mi);
957 psm->countCorrection = countCorrection;
965 * Run triggers from this header that are fired by headers in the database.
966 * @param psm package state machine data
967 * @return 0 on success
969 static rpmRC runImmedTriggers(rpmpsm psm)
971 const rpmts ts = psm->ts;
972 unsigned char * triggersRun;
974 struct rpmtd_s tnames, tindexes;
975 Header h = rpmteHeader(psm->te);
977 if (!(headerGet(h, RPMTAG_TRIGGERNAME, &tnames, HEADERGET_MINMEM) &&
978 headerGet(h, RPMTAG_TRIGGERINDEX, &tindexes, HEADERGET_MINMEM))) {
982 triggersRun = xcalloc(rpmtdCount(&tindexes), sizeof(*triggersRun));
983 { Header sourceH = NULL;
984 const char *trigName;
985 rpm_count_t *triggerIndices = tindexes.data;
987 while ((trigName = rpmtdNextString(&tnames))) {
988 rpmdbMatchIterator mi;
989 int i = rpmtdGetIndex(&tnames);
991 if (triggersRun[triggerIndices[i]] != 0) continue;
993 mi = rpmtsInitIterator(ts, RPMTAG_NAME, trigName, 0);
995 while((sourceH = rpmdbNextIterator(mi)) != NULL) {
996 rc |= handleOneTrigger(psm, sourceH, h,
997 rpmdbGetIteratorCount(mi),
1001 mi = rpmdbFreeIterator(mi);
1004 rpmtdFreeData(&tnames);
1005 rpmtdFreeData(&tindexes);
1013 static const char * pkgStageString(pkgStage a)
1016 case PSM_UNKNOWN: return "unknown";
1018 case PSM_PKGINSTALL: return " install";
1019 case PSM_PKGERASE: return " erase";
1020 case PSM_PKGCOMMIT: return " commit";
1022 case PSM_INIT: return "init";
1023 case PSM_PRE: return "pre";
1024 case PSM_PROCESS: return "process";
1025 case PSM_POST: return "post";
1026 case PSM_UNDO: return "undo";
1027 case PSM_FINI: return "fini";
1029 case PSM_CREATE: return "create";
1030 case PSM_NOTIFY: return "notify";
1031 case PSM_DESTROY: return "destroy";
1032 case PSM_COMMIT: return "commit";
1034 case PSM_CHROOT_IN: return "chrootin";
1035 case PSM_CHROOT_OUT: return "chrootout";
1036 case PSM_SCRIPT: return "script";
1037 case PSM_TRIGGERS: return "triggers";
1038 case PSM_IMMED_TRIGGERS: return "immedtriggers";
1040 case PSM_RPMIO_FLAGS: return "rpmioflags";
1042 case PSM_RPMDB_ADD: return "rpmdbadd";
1043 case PSM_RPMDB_REMOVE: return "rpmdbremove";
1045 default: return "???";
1049 rpmpsm rpmpsmUnlink(rpmpsm psm, const char * msg)
1051 if (psm == NULL) return NULL;
1052 if (_psm_debug && msg != NULL)
1053 fprintf(stderr, "--> psm %p -- %d: %s\n", psm, psm->nrefs, msg);
1058 rpmpsm rpmpsmLink(rpmpsm psm, const char * msg)
1060 if (psm == NULL) return NULL;
1063 if (_psm_debug && msg != NULL)
1064 fprintf(stderr, "--> psm %p ++ %d %s\n", psm, psm->nrefs, msg);
1069 rpmpsm rpmpsmFree(rpmpsm psm)
1075 return rpmpsmUnlink(psm, RPMDBG_M("rpmpsmFree"));
1077 psm->fi = rpmfiFree(psm->fi);
1079 psm->te = rpmteFree(psm->te);
1083 psm->ts = rpmtsFree(psm->ts);
1085 (void) rpmpsmUnlink(psm, RPMDBG_M("rpmpsmFree"));
1087 free(psm->rpmio_flags);
1088 memset(psm, 0, sizeof(*psm)); /* XXX trash and burn */
1094 rpmRC rpmpsmScriptStage(rpmpsm psm, rpmTag scriptTag, rpmTag progTag)
1096 assert(psm != NULL);
1097 psm->scriptTag = scriptTag;
1098 psm->progTag = progTag;
1099 if (scriptTag == RPMTAG_VERIFYSCRIPT) {
1100 psm->stepName = "verify";
1102 return rpmpsmStage(psm, PSM_SCRIPT);
1105 rpmpsm rpmpsmNew(rpmts ts, rpmte te)
1107 rpmpsm psm = xcalloc(1, sizeof(*psm));
1109 if (ts) psm->ts = rpmtsLink(ts, RPMDBG_M("rpmpsmNew"));
1112 psm->te = rpmteLink(te, RPMDBG_M("rpmpsmNew"));Â
1116 psm->fi = rpmfiLink(rpmteFI(te), RPMDBG_M("rpmpsmNew"));
1119 return rpmpsmLink(psm, RPMDBG_M("rpmpsmNew"));
1122 static void * rpmpsmThread(void * arg)
1125 return ((void *) rpmpsmStage(psm, psm->nstage));
1128 static int rpmpsmNext(rpmpsm psm, pkgStage nstage)
1130 psm->nstage = nstage;
1132 return rpmsqJoin( rpmsqThread(rpmpsmThread, psm) );
1133 return rpmpsmStage(psm, psm->nstage);
1136 rpmRC rpmpsmStage(rpmpsm psm, pkgStage stage)
1138 const rpmts ts = psm->ts;
1139 rpm_color_t tscolor = rpmtsColor(ts);
1141 rpmRC rc = RPMRC_OK;
1149 rpmlog(RPMLOG_DEBUG, "%s: %s has %d files, test = %d\n",
1150 psm->stepName, rpmteNEVR(psm->te),
1151 rpmfiFC(fi), (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST));
1154 * When we run scripts, we pass an argument which is the number of
1155 * versions of this package that will be installed when we are
1158 psm->npkgs_installed = rpmdbCountPackages(rpmtsGetRdb(ts), rpmteN(psm->te));
1159 if (psm->npkgs_installed < 0) {
1164 if (psm->goal == PSM_PKGINSTALL) {
1165 rpmdbMatchIterator mi;
1167 int fc = rpmfiFC(fi);
1169 psm->scriptArg = psm->npkgs_installed + 1;
1171 mi = rpmtsInitIterator(ts, RPMTAG_NAME, rpmteN(psm->te), 0);
1172 xx = rpmdbSetIteratorRE(mi, RPMTAG_EPOCH, RPMMIRE_STRCMP,
1174 xx = rpmdbSetIteratorRE(mi, RPMTAG_VERSION, RPMMIRE_STRCMP,
1176 xx = rpmdbSetIteratorRE(mi, RPMTAG_RELEASE, RPMMIRE_STRCMP,
1179 xx = rpmdbSetIteratorRE(mi, RPMTAG_ARCH, RPMMIRE_STRCMP,
1181 xx = rpmdbSetIteratorRE(mi, RPMTAG_OS, RPMMIRE_STRCMP,
1185 while ((oh = rpmdbNextIterator(mi)) != NULL) {
1186 rpmteSetDBInstance(psm->te, rpmdbGetIteratorOffset(mi));
1190 mi = rpmdbFreeIterator(mi);
1193 if (rpmtsFlags(ts) & RPMTRANS_FLAG_JUSTDB) break;
1197 * Old format relocatable packages need the entire default
1198 * prefix stripped to form the cpio list, while all other packages
1199 * need the leading / stripped.
1201 { struct rpmtd_s filenames;
1202 rpmTag ftag = RPMTAG_FILENAMES;
1203 Header h = rpmteHeader(psm->te);
1204 const char *p = headerGetString(h, RPMTAG_DEFAULTPREFIX);
1206 fi->striplen = p ? strlen(p) + 1 : 1;
1208 if (headerIsEntry(h, RPMTAG_ORIGBASENAMES)) {
1209 ftag = RPMTAG_ORIGFILENAMES;
1211 headerGet(h, ftag, &filenames, HEADERGET_EXT);
1212 fi->apath = filenames.data; /* Ick.. */
1218 if (psm->goal == PSM_PKGERASE) {
1219 psm->scriptArg = psm->npkgs_installed - 1;
1223 if (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST) break;
1225 /* XXX insure that trigger index is opened before entering chroot. */
1227 { static int oneshot = 0;
1230 dbi = dbiOpen(rpmtsGetRdb(ts), RPMTAG_TRIGGERNAME, 0);
1236 /* Change root directory if requested and not already done. */
1237 rc = rpmpsmNext(psm, PSM_CHROOT_IN);
1240 if (psm->goal == PSM_PKGINSTALL) {
1241 psm->scriptTag = RPMTAG_PREIN;
1242 psm->progTag = RPMTAG_PREINPROG;
1243 psm->sense = RPMSENSE_TRIGGERPREIN;
1244 psm->countCorrection = 0; /* XXX is this correct?!? */
1246 if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOTRIGGERPREIN)) {
1247 /* Run triggers in other package(s) this package sets off. */
1248 rc = rpmpsmNext(psm, PSM_TRIGGERS);
1251 /* Run triggers in this package other package(s) set off. */
1252 rc = rpmpsmNext(psm, PSM_IMMED_TRIGGERS);
1256 if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOPRE)) {
1257 rc = rpmpsmNext(psm, PSM_SCRIPT);
1258 if (rc != RPMRC_OK) {
1260 _("%s: %s scriptlet failed (%d), skipping %s\n"),
1261 psm->stepName, tag2sln(psm->scriptTag), rc,
1262 rpmteNEVR(psm->te));
1268 if (psm->goal == PSM_PKGERASE) {
1269 psm->scriptTag = RPMTAG_PREUN;
1270 psm->progTag = RPMTAG_PREUNPROG;
1271 psm->sense = RPMSENSE_TRIGGERUN;
1272 psm->countCorrection = -1;
1274 if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOTRIGGERUN)) {
1275 /* Run triggers in this package other package(s) set off. */
1276 rc = rpmpsmNext(psm, PSM_IMMED_TRIGGERS);
1279 /* Run triggers in other package(s) this package sets off. */
1280 rc = rpmpsmNext(psm, PSM_TRIGGERS);
1284 if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOPREUN))
1285 rc = rpmpsmNext(psm, PSM_SCRIPT);
1289 if (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST) break;
1291 if (psm->goal == PSM_PKGINSTALL) {
1292 FD_t payload = NULL;
1294 if (rpmtsFlags(ts) & RPMTRANS_FLAG_JUSTDB) break;
1296 /* XXX Synthesize callbacks for packages with no files. */
1297 if (rpmfiFC(fi) <= 0) {
1299 ptr = rpmtsNotify(ts, psm->te, RPMCALLBACK_INST_START, 0, 100);
1300 ptr = rpmtsNotify(ts, psm->te, RPMCALLBACK_INST_PROGRESS, 100, 100);
1304 /* Retrieve type of payload compression. */
1305 rc = rpmpsmNext(psm, PSM_RPMIO_FLAGS);
1307 if (rpmteFd(psm->te) == NULL) { /* XXX can't happen */
1312 payload = Fdopen(fdDup(Fileno(rpmteFd(psm->te))), psm->rpmio_flags);
1313 if (payload == NULL) { /* XXX can't happen */
1318 rc = fsmSetup(rpmfiFSM(fi), FSM_PKGINSTALL, ts, psm->te, fi,
1319 payload, NULL, &psm->failedFile);
1320 (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_UNCOMPRESS),
1321 fdOp(payload, FDSTAT_READ));
1322 (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_DIGEST),
1323 fdOp(payload, FDSTAT_DIGEST));
1324 xx = fsmTeardown(rpmfiFSM(fi));
1326 saveerrno = errno; /* XXX FIXME: Fclose with libio destroys errno */
1327 xx = Fclose(payload);
1328 errno = saveerrno; /* XXX FIXME: Fclose with libio destroys errno */
1331 rc = rpmpsmNext(psm, PSM_COMMIT);
1333 /* XXX make sure progress is closed out */
1334 psm->what = RPMCALLBACK_INST_PROGRESS;
1335 psm->amount = (fi->archiveSize ? fi->archiveSize : 100);
1336 psm->total = psm->amount;
1337 xx = rpmpsmNext(psm, PSM_NOTIFY);
1341 _("unpacking of archive failed%s%s: %s\n"),
1342 (psm->failedFile != NULL ? _(" on file ") : ""),
1343 (psm->failedFile != NULL ? psm->failedFile : ""),
1347 /* XXX notify callback on error. */
1348 psm->what = RPMCALLBACK_UNPACK_ERROR;
1351 xx = rpmpsmNext(psm, PSM_NOTIFY);
1356 if (psm->goal == PSM_PKGERASE) {
1357 int fc = rpmfiFC(fi);
1359 if (rpmtsFlags(ts) & RPMTRANS_FLAG_JUSTDB) break;
1360 if (rpmtsFlags(ts) & RPMTRANS_FLAG_APPLYONLY) break;
1362 /* XXX Synthesize callbacks for packages with no files. */
1363 if (rpmfiFC(fi) <= 0) {
1365 ptr = rpmtsNotify(ts, psm->te, RPMCALLBACK_UNINST_START, 0, 100);
1366 ptr = rpmtsNotify(ts, psm->te, RPMCALLBACK_UNINST_STOP, 0, 100);
1370 psm->what = RPMCALLBACK_UNINST_START;
1371 psm->amount = fc; /* XXX W2DO? looks wrong. */
1373 xx = rpmpsmNext(psm, PSM_NOTIFY);
1375 rc = fsmSetup(rpmfiFSM(fi), FSM_PKGERASE, ts, psm->te, fi,
1376 NULL, NULL, &psm->failedFile);
1377 xx = fsmTeardown(rpmfiFSM(fi));
1379 psm->what = RPMCALLBACK_UNINST_STOP;
1380 psm->amount = 0; /* XXX W2DO? looks wrong. */
1382 xx = rpmpsmNext(psm, PSM_NOTIFY);
1387 if (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST) break;
1389 if (psm->goal == PSM_PKGINSTALL) {
1390 rpm_time_t installTime = (rpm_time_t) time(NULL);
1391 rpmfs fs = rpmteGetFileStates(psm->te);
1392 rpm_count_t fc = rpmfsFC(fs);
1393 rpm_fstate_t * fileStates = rpmfsGetStates(fs);
1394 Header h = rpmteHeader(psm->te);
1396 if (fileStates != NULL && fc > 0) {
1397 headerPutChar(h, RPMTAG_FILESTATES, fileStates, fc);
1400 headerPutUint32(h, RPMTAG_INSTALLTIME, &installTime, 1);
1401 headerPutUint32(h, RPMTAG_INSTALLCOLOR, &tscolor, 1);
1405 * If this package has already been installed, remove it from
1406 * the database before adding the new one.
1408 if (rpmteDBInstance(psm->te) &&
1409 !(rpmtsFlags(ts) & RPMTRANS_FLAG_APPLYONLY)) {
1410 rc = rpmpsmNext(psm, PSM_RPMDB_REMOVE);
1414 rc = rpmpsmNext(psm, PSM_RPMDB_ADD);
1417 psm->scriptTag = RPMTAG_POSTIN;
1418 psm->progTag = RPMTAG_POSTINPROG;
1419 psm->sense = RPMSENSE_TRIGGERIN;
1420 psm->countCorrection = 0;
1422 if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOPOST)) {
1423 rc = rpmpsmNext(psm, PSM_SCRIPT);
1426 if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOTRIGGERIN)) {
1427 /* Run triggers in other package(s) this package sets off. */
1428 rc = rpmpsmNext(psm, PSM_TRIGGERS);
1431 /* Run triggers in this package other package(s) set off. */
1432 rc = rpmpsmNext(psm, PSM_IMMED_TRIGGERS);
1436 if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_APPLYONLY))
1437 rc = markReplacedFiles(psm);
1440 if (psm->goal == PSM_PKGERASE) {
1442 psm->scriptTag = RPMTAG_POSTUN;
1443 psm->progTag = RPMTAG_POSTUNPROG;
1444 psm->sense = RPMSENSE_TRIGGERPOSTUN;
1445 psm->countCorrection = -1;
1447 if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOPOSTUN)) {
1448 rc = rpmpsmNext(psm, PSM_SCRIPT);
1452 if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOTRIGGERPOSTUN)) {
1453 /* Run triggers in other package(s) this package sets off. */
1454 rc = rpmpsmNext(psm, PSM_TRIGGERS);
1458 if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_APPLYONLY))
1459 rc = rpmpsmNext(psm, PSM_RPMDB_REMOVE);
1462 /* Restore root directory if changed. */
1463 xx = rpmpsmNext(psm, PSM_CHROOT_OUT);
1468 /* Restore root directory if changed. */
1469 xx = rpmpsmNext(psm, PSM_CHROOT_OUT);
1472 if (psm->failedFile)
1474 _("%s failed on file %s: %s\n"),
1475 psm->stepName, psm->failedFile, cpioStrerror(rc));
1477 rpmlog(RPMLOG_ERR, _("%s failed: %s\n"),
1478 psm->stepName, cpioStrerror(rc));
1480 /* XXX notify callback on error. */
1481 psm->what = RPMCALLBACK_CPIO_ERROR;
1484 xx = rpmpsmNext(psm, PSM_NOTIFY);
1487 if (psm->goal == PSM_PKGERASE) {
1488 if (psm->te != NULL)
1489 rpmteSetHeader(psm->te, NULL);
1491 psm->failedFile = _free(psm->failedFile);
1493 fi->apath = _free(fi->apath);
1496 case PSM_PKGINSTALL:
1499 psm->stepName = pkgStageString(stage);
1501 rc = rpmpsmNext(psm, PSM_INIT);
1502 if (!rc) rc = rpmpsmNext(psm, PSM_PRE);
1503 if (!rc) rc = rpmpsmNext(psm, PSM_PROCESS);
1504 if (!rc) rc = rpmpsmNext(psm, PSM_POST);
1505 xx = rpmpsmNext(psm, PSM_FINI);
1514 /* FIX: psm->te may be NULL */
1515 ptr = rpmtsNotify(ts, psm->te, psm->what, psm->amount, psm->total);
1520 if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_PKGCOMMIT)) break;
1521 if (rpmtsFlags(ts) & RPMTRANS_FLAG_APPLYONLY) break;
1523 rc = fsmSetup(rpmfiFSM(fi), FSM_PKGCOMMIT, ts, psm->te, fi,
1524 NULL, NULL, &psm->failedFile);
1525 xx = fsmTeardown(rpmfiFSM(fi));
1529 { const char * rootDir = rpmtsRootDir(ts);
1530 /* Change root directory if requested and not already done. */
1531 if (rootDir != NULL && !(rootDir[0] == '/' && rootDir[1] == '\0')
1532 && !rpmtsChrootDone(ts) && !psm->chrootDone)
1535 if (rootDir != NULL && !rstreq(rootDir, "/") && *rootDir == '/')
1536 if (chroot(rootDir) == -1) {
1537 rpmlog(RPMLOG_ERR, _("Unable to change root directory: %m\n"));
1540 psm->chrootDone = 1;
1541 (void) rpmtsSetChrootDone(ts, 1);
1544 case PSM_CHROOT_OUT:
1545 /* Restore root directory if changed. */
1546 if (psm->chrootDone) {
1547 const char * rootDir = rpmtsRootDir(ts);
1548 const char * currDir = rpmtsCurrDir(ts);
1549 if (rootDir != NULL && !rstreq(rootDir, "/") && *rootDir == '/')
1551 psm->chrootDone = 0;
1552 (void) rpmtsSetChrootDone(ts, 0);
1553 if (currDir != NULL) /* XXX can't happen */
1554 xx = chdir(currDir);
1557 case PSM_SCRIPT: /* Run current package scriptlets. */
1558 rc = runInstScript(psm);
1561 /* Run triggers in other package(s) this package sets off. */
1562 rc = runTriggers(psm);
1564 case PSM_IMMED_TRIGGERS:
1565 /* Run triggers in this package other package(s) set off. */
1566 rc = runImmedTriggers(psm);
1569 case PSM_RPMIO_FLAGS:
1570 { Header h = rpmteHeader(psm->te);
1571 const char *compr = headerGetString(h, RPMTAG_PAYLOADCOMPRESSOR);
1572 psm->rpmio_flags = rstrscat(NULL, "r.", compr ? compr : "gzip", NULL);
1577 case PSM_RPMDB_ADD: {
1579 if (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST) break;
1580 h = rpmteHeader(psm->te);
1581 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DBADD), 0);
1582 if (!(rpmtsVSFlags(ts) & RPMVSF_NOHDRCHK))
1583 rc = rpmdbAdd(rpmtsGetRdb(ts), rpmtsGetTid(ts), h,
1586 rc = rpmdbAdd(rpmtsGetRdb(ts), rpmtsGetTid(ts), h,
1588 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DBADD), 0);
1591 rpmteSetDBInstance(psm->te, headerGetInstance(h));
1595 case PSM_RPMDB_REMOVE:
1596 if (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST) break;
1597 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DBREMOVE), 0);
1598 rc = rpmdbRemove(rpmtsGetRdb(ts), rpmtsGetTid(ts),
1599 rpmteDBInstance(psm->te), NULL, NULL);
1600 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DBREMOVE), 0);
1602 rpmteSetDBInstance(psm->te, 0);