1 /** \ingroup rpmts payload
3 * Package state machine to handle a package from a transaction set.
11 #include "rpmio/rpmlua.h"
14 #include "lib/fsm.h" /* XXX CPIO_FOO/FSM_FOO constants */
19 #define _RPMFI_INTERNAL /* XXX replaced/states, fi->hge, fi->te... */
22 #define _RPMTE_INTERNAL /* XXX te->fd */
25 #include "lib/rpmtsscore.h"
28 #include "lib/rpmlead.h" /* writeLead proto */
29 #include "lib/signature.h" /* signature constants */
30 #include <rpmfileutil.h> /* rpmMkTempFile() */
31 #include "lib/misc.h" /* XXX rpmMkdirPath, doputenv */
32 #include <rpmdb.h> /* XXX for db_chrootDone */
37 int _psm_debug = _PSM_DEBUG;
40 /* Give access to the rpmte global tracking the last instance added
43 extern unsigned int myinstall_instance;
45 int rpmVersionCompare(Header first, Header second)
47 const char * one, * two;
48 int32_t * epochOne, * epochTwo;
49 static int32_t zero = 0;
52 if (!headerGetEntry(first, RPMTAG_EPOCH, NULL, (void **) &epochOne, NULL))
54 if (!headerGetEntry(second, RPMTAG_EPOCH, NULL, (void **) &epochTwo, NULL))
57 if (*epochOne < *epochTwo)
59 else if (*epochOne > *epochTwo)
62 rc = headerGetEntry(first, RPMTAG_VERSION, NULL, (void **) &one, NULL);
63 rc = headerGetEntry(second, RPMTAG_VERSION, NULL, (void **) &two, NULL);
65 rc = rpmvercmp(one, two);
69 rc = headerGetEntry(first, RPMTAG_RELEASE, NULL, (void **) &one, NULL);
70 rc = headerGetEntry(second, RPMTAG_RELEASE, NULL, (void **) &two, NULL);
72 return rpmvercmp(one, two);
76 * Macros to be defined from per-header tag values.
77 * @todo Should other macros be added from header when installing a package?
79 static struct tagMacro {
80 const char * macroname; /*!< Macro name to define. */
81 rpmTag tag; /*!< Header tag to use for value. */
83 { "name", RPMTAG_NAME },
84 { "version", RPMTAG_VERSION },
85 { "release", RPMTAG_RELEASE },
86 { "epoch", RPMTAG_EPOCH },
91 * Define per-header macros.
92 * @param fi transaction element file info
96 static int rpmInstallLoadMacros(rpmfi fi, Header h)
98 HGE_t hge = (HGE_t) fi->hge;
99 struct tagMacro * tagm;
109 for (tagm = tagMacros; tagm->macroname != NULL; tagm++) {
110 if (!hge(h, tagm->tag, &type, (void **) &body, NULL))
114 sprintf(numbuf, "%d", *body.i32p);
115 addMacro(NULL, tagm->macroname, NULL, numbuf, -1);
117 case RPM_STRING_TYPE:
118 addMacro(NULL, tagm->macroname, NULL, body.str, -1);
125 case RPM_STRING_ARRAY_TYPE:
126 case RPM_I18NSTRING_TYPE:
135 * Mark files in database shared with this package as "replaced".
136 * @param psm package state machine data
139 static rpmRC markReplacedFiles(const rpmpsm psm)
141 const rpmts ts = psm->ts;
143 HGE_t hge = (HGE_t)fi->hge;
144 sharedFileInfo replaced = fi->replaced;
146 rpmdbMatchIterator mi;
152 if (!(rpmfiFC(fi) > 0 && fi->replaced))
156 for (sfi = replaced; sfi->otherPkg; sfi++) {
157 if (prev && prev == sfi->otherPkg)
159 prev = sfi->otherPkg;
165 offsets = alloca(num * sizeof(*offsets));
168 for (sfi = replaced; sfi->otherPkg; sfi++) {
169 if (prev && prev == sfi->otherPkg)
171 prev = sfi->otherPkg;
172 offsets[num++] = sfi->otherPkg;
175 mi = rpmtsInitIterator(ts, RPMDBI_PACKAGES, NULL, 0);
176 xx = rpmdbAppendIterator(mi, offsets, num);
177 xx = rpmdbSetIteratorRewrite(mi, 1);
180 while ((h = rpmdbNextIterator(mi)) != NULL) {
187 if (!hge(h, RPMTAG_FILESTATES, NULL, (void **)&secStates, &count))
190 prev = rpmdbGetIteratorOffset(mi);
192 while (sfi->otherPkg && sfi->otherPkg == prev) {
193 assert(sfi->otherFileNum < count);
194 if (secStates[sfi->otherFileNum] != RPMFILE_STATE_REPLACED) {
195 secStates[sfi->otherFileNum] = RPMFILE_STATE_REPLACED;
197 /* Modified header will be rewritten. */
199 xx = rpmdbSetIteratorModified(mi, modified);
206 mi = rpmdbFreeIterator(mi);
211 rpmRC rpmInstallSourcePackage(rpmts ts, FD_t fd,
212 const char ** specFilePtr, const char ** cookie)
216 const char * _sourcedir = NULL;
217 const char * _specdir = NULL;
218 const char * specFile = NULL;
222 struct rpmpsm_s psmbuf;
223 rpmpsm psm = &psmbuf;
228 memset(psm, 0, sizeof(*psm));
229 psm->ts = rpmtsLink(ts, "InstallSourcePackage");
231 rpmrc = rpmReadPackageFile(ts, fd, "InstallSourcePackage", &h);
233 case RPMRC_NOTTRUSTED:
246 isSource = headerIsEntry(h, RPMTAG_SOURCEPACKAGE);
249 rpmlog(RPMLOG_ERR, _("source package expected, binary found\n"));
254 if (rpmtsAddInstallElement(ts, h, NULL, 0, NULL)) {
259 fi = rpmfiNew(ts, h, RPMTAG_BASENAMES, scareMem);
262 if (fi == NULL) { /* XXX can't happen */
267 fi->te = rpmtsElement(ts, 0);
268 if (fi->te == NULL) { /* XXX can't happen */
273 rpmteSetHeader(fi->te, fi->h);
274 fi->te->fd = fdLink(fd, "installSourcePackage");
278 (void) rpmInstallLoadMacros(fi, fi->h);
280 psm->fi = rpmfiLink(fi, NULL);
285 if (hge(fi->h, RPMTAG_COOKIE, NULL, (void **) cookie, NULL))
286 *cookie = xstrdup(*cookie);
289 /* XXX FIXME: can't do endian neutral MD5 verification yet. */
290 fi->fmd5s = hfd(fi->fmd5s, -1);
292 /* XXX FIXME: don't do per-file mapping, force global flags. */
293 fi->fmapflags = _free(fi->fmapflags);
294 fi->mapflags = CPIO_MAP_PATH | CPIO_MAP_MODE | CPIO_MAP_UID | CPIO_MAP_GID;
301 for (i = 0; i < fi->fc; i++)
302 fi->actions[i] = FA_CREATE;
306 if (fi->h != NULL) { /* XXX can't happen */
307 rpmfiBuildFNames(fi->h, RPMTAG_BASENAMES, &fi->apath, NULL);
309 if (headerIsEntry(fi->h, RPMTAG_COOKIE))
310 for (i = 0; i < fi->fc; i++)
311 if (fi->fflags[i] & RPMFILE_SPECFILE) break;
315 /* Find the spec file by name. */
316 for (i = 0; i < fi->fc; i++) {
317 const char * t = fi->apath[i];
318 t += strlen(fi->apath[i]) - 5;
319 if (!strcmp(t, ".spec")) break;
323 _sourcedir = rpmGenPath(rpmtsRootDir(ts), "%{_sourcedir}", "");
324 rpmrc = rpmMkdirPath(_sourcedir, "sourcedir");
330 _specdir = rpmGenPath(rpmtsRootDir(ts), "%{_specdir}", "");
331 rpmrc = rpmMkdirPath(_specdir, "specdir");
337 /* Build dnl/dil with {_sourcedir, _specdir} as values. */
339 int speclen = strlen(_specdir) + 2;
340 int sourcelen = strlen(_sourcedir) + 2;
343 fi->dnl = hfd(fi->dnl, -1);
346 fi->dnl = xmalloc(fi->dc * sizeof(*fi->dnl)
347 + fi->fc * sizeof(*fi->dil)
348 + speclen + sourcelen);
349 fi->dil = (unsigned int *)(fi->dnl + fi->dc);
350 memset(fi->dil, 0, fi->fc * sizeof(*fi->dil));
352 fi->dnl[0] = t = (char *)(fi->dil + fi->fc);
353 fi->dnl[1] = t = stpcpy( stpcpy(t, _sourcedir), "/") + 1;
354 (void) stpcpy( stpcpy(t, _specdir), "/");
356 t = xmalloc(speclen + strlen(fi->bnl[i]) + 1);
357 (void) stpcpy( stpcpy( stpcpy(t, _specdir), "/"), fi->bnl[i]);
360 rpmlog(RPMLOG_ERR, _("source package contains no .spec file\n"));
365 psm->goal = PSM_PKGINSTALL;
367 /* FIX: psm->fi->dnl should be owned. */
368 rpmrc = rpmpsmStage(psm, PSM_PROCESS);
370 (void) rpmpsmStage(psm, PSM_FINI);
372 if (rpmrc) rpmrc = RPMRC_FAIL;
375 if (specFilePtr && specFile && rpmrc == RPMRC_OK)
376 *specFilePtr = specFile;
378 specFile = _free(specFile);
380 _specdir = _free(_specdir);
381 _sourcedir = _free(_sourcedir);
383 psm->fi = rpmfiFree(psm->fi);
386 if (h != NULL) h = headerFree(h);
389 rpmteSetHeader(fi->te, NULL);
390 if (fi->te->fd != NULL)
391 (void) Fclose(fi->te->fd);
397 /* XXX nuke the added package(s). */
400 psm->ts = rpmtsFree(psm->ts);
405 static char * SCRIPT_PATH = "PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin";
408 * Return scriptlet name from tag.
409 * @param tag scriptlet tag
410 * @return name of scriptlet
412 static const char * tag2sln(int tag)
415 case RPMTAG_PRETRANS: return "%pretrans";
416 case RPMTAG_TRIGGERPREIN: return "%triggerprein";
417 case RPMTAG_PREIN: return "%pre";
418 case RPMTAG_POSTIN: return "%post";
419 case RPMTAG_TRIGGERIN: return "%triggerin";
420 case RPMTAG_TRIGGERUN: return "%triggerun";
421 case RPMTAG_PREUN: return "%preun";
422 case RPMTAG_POSTUN: return "%postun";
423 case RPMTAG_POSTTRANS: return "%posttrans";
424 case RPMTAG_TRIGGERPOSTUN: return "%triggerpostun";
425 case RPMTAG_VERIFYSCRIPT: return "%verify";
427 return "%unknownscript";
431 * Wait for child process to be reaped.
432 * @param psm package state machine data
435 static pid_t psmWait(rpmpsm psm)
437 const rpmts ts = psm->ts;
440 (void) rpmsqWait(&psm->sq);
441 msecs = psm->sq.op.usecs/1000;
442 (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_SCRIPTLETS), &psm->sq.op);
445 _("%s: waitpid(%d) rc %d status %x secs %u.%03u\n"),
446 psm->stepName, (unsigned)psm->sq.child,
447 (unsigned)psm->sq.reaped, psm->sq.status,
448 (unsigned)msecs/1000, (unsigned)msecs%1000);
450 return psm->sq.reaped;
455 * Run internal Lua script.
457 static rpmRC runLuaScript(rpmpsm psm, Header h, const char *sln,
458 int progArgc, const char **progArgv,
459 const char *script, int arg1, int arg2)
461 const rpmts ts = psm->ts;
463 const char *n, *v, *r;
467 rpmlua lua = NULL; /* Global state. */
470 xx = headerNVR(h, &n, &v, &r);
472 if (!rpmtsChrootDone(ts)) {
473 const char *rootDir = rpmtsRootDir(ts);
475 rootFd = open(".", O_RDONLY, 0);
477 if (rootDir != NULL && strcmp(rootDir, "/") && *rootDir == '/')
478 xx = chroot(rootDir);
479 xx = rpmtsSetChrootDone(ts, 1);
483 /* Create arg variable */
484 rpmluaPushTable(lua, "arg");
486 rpmluavSetListMode(var, 1);
488 for (i = 0; i < progArgc && progArgv[i]; i++) {
489 rpmluavSetValue(var, RPMLUAV_STRING, progArgv[i]);
490 rpmluaSetVar(lua, var);
494 rpmluavSetValueNum(var, arg1);
495 rpmluaSetVar(lua, var);
498 rpmluavSetValueNum(var, arg2);
499 rpmluaSetVar(lua, var);
501 var = rpmluavFree(var);
506 xx = snprintf(buf, BUFSIZ, "%s(%s-%s-%s)", sln, n, v, r);
507 if (rpmluaRunScript(lua, script, buf) == -1)
511 rpmluaDelVar(lua, "arg");
514 const char *rootDir = rpmtsRootDir(ts);
517 if (rootDir != NULL && strcmp(rootDir, "/") && *rootDir == '/')
519 xx = rpmtsSetChrootDone(ts, 0);
528 static int ldconfig_done = 0;
530 static const char * ldconfig_path = "/sbin/ldconfig";
533 * Run scriptlet with args.
535 * Run a script with an interpreter. If the interpreter is not specified,
536 * /bin/sh will be used. If the interpreter is /bin/sh, then the args from
537 * the header will be ignored, passing instead arg1 and arg2.
539 * @param psm package state machine data
541 * @param sln name of scriptlet section
542 * @param progArgc no. of args from header
543 * @param progArgv args from header, progArgv[0] is the interpreter to use
544 * @param script scriptlet from header
545 * @param arg1 no. instances of package installed after scriptlet exec
547 * @param arg2 ditto, but for the target package
548 * @return 0 on success
550 static rpmRC runScript(rpmpsm psm, Header h, const char * sln,
551 int progArgc, const char ** progArgv,
552 const char * script, int arg1, int arg2)
554 const rpmts ts = psm->ts;
557 HFD_t hfd = (fi->hfd ? fi->hfd : headerFreeData);
558 const char ** argv = NULL;
560 const char ** prefixes = NULL;
563 const char * oldPrefix;
566 char * prefixBuf = NULL;
567 const char * fn = NULL;
570 int freePrefixes = 0;
574 const char *n, *v, *r, *a;
576 if (progArgv == NULL && script == NULL)
579 /* XXX FIXME: except for %verifyscript, rpmteNEVR can be used. */
580 xx = headerNVR(h, &n, &v, &r);
581 xx = hge(h, RPMTAG_ARCH, NULL, (void **) &a, NULL);
583 if (progArgv && strcmp(progArgv[0], "<lua>") == 0) {
586 _("%s: %s(%s-%s-%s.%s) running <lua> scriptlet.\n"),
587 psm->stepName, tag2sln(psm->scriptTag), n, v, r, a);
588 return runLuaScript(psm, h, sln, progArgc, progArgv,
598 * If a successor node, and ldconfig was just run, don't bother.
600 if (ldconfig_path && progArgv != NULL && psm->unorderedSuccessor) {
601 if (ldconfig_done && !strcmp(progArgv[0], ldconfig_path)) {
603 _("%s: %s(%s-%s-%s.%s) skipping redundant \"%s\".\n"),
604 psm->stepName, tag2sln(psm->scriptTag), n, v, r, a,
611 _("%s: %s(%s-%s-%s.%s) %ssynchronous scriptlet start\n"),
612 psm->stepName, tag2sln(psm->scriptTag), n, v, r, a,
613 (psm->unorderedSuccessor ? "a" : ""));
616 argv = alloca(5 * sizeof(*argv));
621 argv = alloca((progArgc + 4) * sizeof(*argv));
622 memcpy(argv, progArgv, progArgc * sizeof(*argv));
624 ldconfig_done = (ldconfig_path && !strcmp(argv[0], ldconfig_path)
629 /* XXX This assumes that all interpreters are elf executables. */
630 if ((a != NULL && a[0] == 'i' && a[1] != '\0' && a[2] == '8' && a[3] == '6')
631 && strcmp(argv[0], "/sbin/ldconfig"))
633 const char * fmt = rpmGetPath("%{?_autorelocate_path}", NULL);
638 newPath = headerSprintf(h, fmt, rpmTagTable, rpmHeaderFormats, &errstr);
641 /* XXX On ia64, change leading /emul/ix86 -> /emul/ia32, ick. */
642 if (newPath != NULL && *newPath != '\0'
643 && strlen(newPath) >= (sizeof("/emul/i386")-1)
644 && newPath[0] == '/' && newPath[1] == 'e' && newPath[2] == 'm'
645 && newPath[3] == 'u' && newPath[4] == 'l' && newPath[5] == '/'
646 && newPath[6] == 'i' && newPath[8] == '8' && newPath[9] == '6')
653 t = alloca(strlen(newPath) + strlen(argv[0]) + 1);
655 (void) stpcpy( stpcpy(t, newPath), argv[0]);
656 newPath = _free(newPath);
661 if (hge(h, RPMTAG_INSTPREFIXES, &ipt, (void **) &prefixes, &numPrefixes)) {
663 } else if (hge(h, RPMTAG_INSTALLPREFIX, NULL, (void **) &oldPrefix, NULL)) {
664 prefixes = &oldPrefix;
671 if (prefixes != NULL)
672 for (i = 0; i < numPrefixes; i++) {
673 len = strlen(prefixes[i]);
674 if (len > maxPrefixLength) maxPrefixLength = len;
676 prefixBuf = alloca(maxPrefixLength + 50);
679 const char * rootDir = rpmtsRootDir(ts);
682 if (rpmMkTempFile((!rpmtsChrootDone(ts) ? rootDir : "/"), &fn, &fd)) {
683 if (prefixes != NULL && freePrefixes) free(prefixes);
688 (!strcmp(argv[0], "/bin/sh") || !strcmp(argv[0], "/bin/bash")))
690 static const char set_x[] = "set -x\n";
691 xx = Fwrite(set_x, sizeof(set_x[0]), sizeof(set_x)-1, fd);
694 if (ldconfig_path && strstr(script, ldconfig_path) != NULL)
697 xx = Fwrite(script, sizeof(script[0]), strlen(script), fd);
700 { const char * sn = fn;
701 if (!rpmtsChrootDone(ts) && rootDir != NULL &&
702 !(rootDir[0] == '/' && rootDir[1] == '\0'))
704 sn += strlen(rootDir)-1;
710 char *av = alloca(20);
711 sprintf(av, "%d", arg1);
715 char *av = alloca(20);
716 sprintf(av, "%d", arg2);
723 scriptFd = rpmtsScriptFd(ts);
724 if (scriptFd != NULL) {
725 if (rpmIsVerbose()) {
726 out = fdDup(Fileno(scriptFd));
728 out = Fopen("/dev/null", "w.fdio");
730 out = fdDup(Fileno(scriptFd));
734 out = fdDup(STDOUT_FILENO);
736 if (out == NULL) return RPMRC_FAIL; /* XXX can't happen */
738 xx = rpmsqFork(&psm->sq);
739 if (psm->sq.child == 0) {
740 const char * rootDir;
745 pipes[0] = pipes[1] = 0;
746 /* make stdin inaccessible */
748 xx = close(pipes[1]);
749 xx = dup2(pipes[0], STDIN_FILENO);
750 xx = close(pipes[0]);
752 /* XXX Force FD_CLOEXEC on 1st 100 inherited fdno's. */
753 for (fdno = 3; fdno < 100; fdno++) {
754 flag = fcntl(fdno, F_GETFD);
755 if (flag == -1 || (flag & FD_CLOEXEC))
757 xx = fcntl(fdno, F_SETFD, FD_CLOEXEC);
758 /* XXX W2DO? debug msg for inheirited fdno w/o FD_CLOEXEC */
761 if (scriptFd != NULL) {
762 int sfdno = Fileno(scriptFd);
763 int ofdno = Fileno(out);
764 if (sfdno != STDERR_FILENO)
765 xx = dup2(sfdno, STDERR_FILENO);
766 if (ofdno != STDOUT_FILENO)
767 xx = dup2(ofdno, STDOUT_FILENO);
768 /* make sure we don't close stdin/stderr/stdout by mistake! */
769 if (ofdno > STDERR_FILENO && ofdno != sfdno)
771 if (sfdno > STDERR_FILENO && ofdno != sfdno)
772 xx = Fclose (scriptFd);
775 { const char *ipath = rpmExpand("PATH=%{_install_script_path}", NULL);
776 const char *path = SCRIPT_PATH;
778 if (ipath && ipath[5] != '%')
782 ipath = _free(ipath);
785 if (prefixes != NULL)
786 for (i = 0; i < numPrefixes; i++) {
787 sprintf(prefixBuf, "RPM_INSTALL_PREFIX%d=%s", i, prefixes[i]);
788 xx = doputenv(prefixBuf);
790 /* backwards compatibility */
792 sprintf(prefixBuf, "RPM_INSTALL_PREFIX=%s", prefixes[i]);
793 xx = doputenv(prefixBuf);
797 rootDir = rpmtsRootDir(ts);
798 if (rootDir != NULL) { /* XXX can't happen */
799 if (!rpmtsChrootDone(ts) &&
800 !(rootDir[0] == '/' && rootDir[1] == '\0'))
802 xx = chroot(rootDir);
805 rpmlog(RPMLOG_DEBUG, _("%s: %s(%s-%s-%s.%s)\texecv(%s) pid %d\n"),
806 psm->stepName, sln, n, v, r, a,
807 argv[0], (unsigned)getpid());
809 /* XXX Don't mtrace into children. */
810 unsetenv("MALLOC_CHECK_");
812 /* Permit libselinux to do the scriptlet exec. */
813 if (rpmtsSELinuxEnabled(ts) == 1) {
814 xx = rpm_execcon(0, argv[0], (char ** const) argv, environ);
818 xx = execv(argv[0], (char *const *)argv);
824 if (psm->sq.child == (pid_t)-1) {
825 rpmlog(RPMLOG_ERR, _("Couldn't fork %s: %s\n"), sln, strerror(errno));
832 /* XXX filter order dependent multilib "other" arch helper error. */
833 if (!(psm->sq.reaped >= 0 && !strcmp(argv[0], "/usr/sbin/glibc_post_upgrade") && WEXITSTATUS(psm->sq.status) == 110)) {
834 if (psm->sq.reaped < 0) {
836 _("%s(%s-%s-%s.%s) scriptlet failed, waitpid(%d) rc %d: %s\n"),
837 sln, n, v, r, a, psm->sq.child, psm->sq.reaped, strerror(errno));
840 if (!WIFEXITED(psm->sq.status) || WEXITSTATUS(psm->sq.status)) {
841 if (WIFSIGNALED(psm->sq.status)) {
843 _("%s(%s-%s-%s.%s) scriptlet failed, signal %d\n"),
844 sln, n, v, r, a, WTERMSIG(psm->sq.status));
847 _("%s(%s-%s-%s.%s) scriptlet failed, exit status %d\n"),
848 sln, n, v, r, a, WEXITSTATUS(psm->sq.status));
855 if (freePrefixes) prefixes = hfd(prefixes, ipt);
857 xx = Fclose(out); /* XXX dup'd STDOUT_FILENO */
869 * Retrieve and run scriptlet from header.
870 * @param psm package state machine data
871 * @return rpmRC return code
873 static rpmRC runInstScript(rpmpsm psm)
877 HFD_t hfd = (fi->hfd ? fi->hfd : headerFreeData);
887 * headerGetEntry() sets the data pointer to NULL if the entry does
890 xx = hge(fi->h, psm->scriptTag, &stt, (void **) &script, NULL);
891 xx = hge(fi->h, psm->progTag, &ptt, (void **) &progArgv, &progArgc);
892 if (progArgv == NULL && script == NULL)
895 if (progArgv && ptt == RPM_STRING_TYPE) {
896 argv = alloca(sizeof(*argv));
897 *argv = (const char *) progArgv;
899 argv = (const char **) progArgv;
902 if (fi->h != NULL) /* XXX can't happen */
903 rc = runScript(psm, fi->h, tag2sln(psm->scriptTag), progArgc, argv,
904 script, psm->scriptArg, -1);
907 progArgv = hfd(progArgv, ptt);
908 script = hfd(script, stt);
914 * @todo Trigger on any provides, not just package NVR.
915 * @param psm package state machine data
919 * @param triggersAlreadyRun
922 static rpmRC handleOneTrigger(const rpmpsm psm,
923 Header sourceH, Header triggeredH,
924 int arg2, unsigned char * triggersAlreadyRun)
927 const rpmts ts = psm->ts;
930 HFD_t hfd = (fi->hfd ? fi->hfd : headerFreeData);
931 rpmds trigger = NULL;
932 const char ** triggerScripts;
933 const char ** triggerProgs;
934 int32_t * triggerIndices;
935 const char * sourceName;
936 const char * triggerName;
941 xx = headerNVR(sourceH, &sourceName, NULL, NULL);
942 xx = headerNVR(triggeredH, &triggerName, NULL, NULL);
944 trigger = rpmdsInit(rpmdsNew(triggeredH, RPMTAG_TRIGGERNAME, scareMem));
948 (void) rpmdsSetNoPromote(trigger, 1);
950 while ((i = rpmdsNext(trigger)) >= 0) {
951 rpmTagType tit, tst, tpt;
953 int32_t Flags = rpmdsFlags(trigger);
955 if ((Name = rpmdsN(trigger)) == NULL)
956 continue; /* XXX can't happen */
958 if (strcmp(Name, sourceName))
960 if (!(Flags & psm->sense))
964 * XXX Trigger on any provided dependency, not just the package NEVR.
966 if (!rpmdsAnyMatchesDep(sourceH, trigger, 1))
969 if (!( hge(triggeredH, RPMTAG_TRIGGERINDEX, &tit,
970 (void **) &triggerIndices, NULL) &&
971 hge(triggeredH, RPMTAG_TRIGGERSCRIPTS, &tst,
972 (void **) &triggerScripts, NULL) &&
973 hge(triggeredH, RPMTAG_TRIGGERSCRIPTPROG, &tpt,
974 (void **) &triggerProgs, NULL))
981 arg1 = rpmdbCountPackages(rpmtsGetRdb(ts), triggerName);
983 /* XXX W2DO? fails as "execution of script failed" */
986 arg1 += psm->countCorrection;
987 index = triggerIndices[i];
988 if (triggersAlreadyRun == NULL ||
989 triggersAlreadyRun[index] == 0)
991 rc = runScript(psm, triggeredH, "%trigger", 1,
992 triggerProgs + index, triggerScripts[index],
994 if (triggersAlreadyRun != NULL)
995 triggersAlreadyRun[index] = 1;
1000 triggerIndices = hfd(triggerIndices, tit);
1001 triggerScripts = hfd(triggerScripts, tst);
1002 triggerProgs = hfd(triggerProgs, tpt);
1005 * Each target/source header pair can only result in a single
1011 trigger = rpmdsFree(trigger);
1017 * Run trigger scripts in the database that are fired by this header.
1018 * @param psm package state machine data
1019 * @return 0 on success
1021 static rpmRC runTriggers(rpmpsm psm)
1023 const rpmts ts = psm->ts;
1025 int numPackage = -1;
1026 rpmRC rc = RPMRC_OK;
1027 const char * N = NULL;
1029 if (psm->te) /* XXX can't happen */
1030 N = rpmteN(psm->te);
1031 /* XXX: Might need to adjust instance counts four autorollback. */
1032 if (N) /* XXX can't happen */
1033 numPackage = rpmdbCountPackages(rpmtsGetRdb(ts), N)
1034 + psm->countCorrection;
1036 return RPMRC_NOTFOUND;
1038 if (fi != NULL && fi->h != NULL) /* XXX can't happen */
1039 { Header triggeredH;
1040 rpmdbMatchIterator mi;
1041 int countCorrection = psm->countCorrection;
1043 psm->countCorrection = 0;
1044 mi = rpmtsInitIterator(ts, RPMTAG_TRIGGERNAME, N, 0);
1045 while((triggeredH = rpmdbNextIterator(mi)) != NULL)
1046 rc |= handleOneTrigger(psm, fi->h, triggeredH, numPackage, NULL);
1047 mi = rpmdbFreeIterator(mi);
1048 psm->countCorrection = countCorrection;
1055 * Run triggers from this header that are fired by headers in the database.
1056 * @param psm package state machine data
1057 * @return 0 on success
1059 static rpmRC runImmedTriggers(rpmpsm psm)
1061 const rpmts ts = psm->ts;
1063 HGE_t hge = fi->hge;
1064 HFD_t hfd = (fi->hfd ? fi->hfd : headerFreeData);
1065 const char ** triggerNames;
1067 int32_t * triggerIndices;
1068 rpmTagType tnt, tit;
1069 int numTriggerIndices;
1070 unsigned char * triggersRun;
1071 rpmRC rc = RPMRC_OK;
1073 if (fi->h == NULL) return rc; /* XXX can't happen */
1075 if (!( hge(fi->h, RPMTAG_TRIGGERNAME, &tnt,
1076 (void **) &triggerNames, &numTriggers) &&
1077 hge(fi->h, RPMTAG_TRIGGERINDEX, &tit,
1078 (void **) &triggerIndices, &numTriggerIndices))
1082 triggersRun = alloca(sizeof(*triggersRun) * numTriggerIndices);
1083 memset(triggersRun, 0, sizeof(*triggersRun) * numTriggerIndices);
1085 { Header sourceH = NULL;
1088 for (i = 0; i < numTriggers; i++) {
1089 rpmdbMatchIterator mi;
1091 if (triggersRun[triggerIndices[i]] != 0) continue;
1093 mi = rpmtsInitIterator(ts, RPMTAG_NAME, triggerNames[i], 0);
1095 while((sourceH = rpmdbNextIterator(mi)) != NULL) {
1096 rc |= handleOneTrigger(psm, sourceH, fi->h,
1097 rpmdbGetIteratorCount(mi),
1101 mi = rpmdbFreeIterator(mi);
1104 triggerIndices = hfd(triggerIndices, tit);
1105 triggerNames = hfd(triggerNames, tnt);
1109 static const char * pkgStageString(pkgStage a)
1112 case PSM_UNKNOWN: return "unknown";
1114 case PSM_PKGINSTALL: return " install";
1115 case PSM_PKGERASE: return " erase";
1116 case PSM_PKGCOMMIT: return " commit";
1117 case PSM_PKGSAVE: return "repackage";
1119 case PSM_INIT: return "init";
1120 case PSM_PRE: return "pre";
1121 case PSM_PROCESS: return "process";
1122 case PSM_POST: return "post";
1123 case PSM_UNDO: return "undo";
1124 case PSM_FINI: return "fini";
1126 case PSM_CREATE: return "create";
1127 case PSM_NOTIFY: return "notify";
1128 case PSM_DESTROY: return "destroy";
1129 case PSM_COMMIT: return "commit";
1131 case PSM_CHROOT_IN: return "chrootin";
1132 case PSM_CHROOT_OUT: return "chrootout";
1133 case PSM_SCRIPT: return "script";
1134 case PSM_TRIGGERS: return "triggers";
1135 case PSM_IMMED_TRIGGERS: return "immedtriggers";
1137 case PSM_RPMIO_FLAGS: return "rpmioflags";
1139 case PSM_RPMDB_LOAD: return "rpmdbload";
1140 case PSM_RPMDB_ADD: return "rpmdbadd";
1141 case PSM_RPMDB_REMOVE: return "rpmdbremove";
1143 default: return "???";
1147 rpmpsm XrpmpsmUnlink(rpmpsm psm, const char * msg, const char * fn, unsigned ln)
1149 if (psm == NULL) return NULL;
1150 if (_psm_debug && msg != NULL)
1151 fprintf(stderr, "--> psm %p -- %d %s at %s:%u\n", psm, psm->nrefs, msg, fn, ln);
1156 rpmpsm XrpmpsmLink(rpmpsm psm, const char * msg, const char * fn, unsigned ln)
1158 if (psm == NULL) return NULL;
1161 if (_psm_debug && msg != NULL)
1162 fprintf(stderr, "--> psm %p ++ %d %s at %s:%u\n", psm, psm->nrefs, msg, fn, ln);
1167 rpmpsm rpmpsmFree(rpmpsm psm)
1169 const char * msg = "rpmpsmFree";
1174 return rpmpsmUnlink(psm, msg);
1176 psm->fi = rpmfiFree(psm->fi);
1178 psm->te = rpmteFree(psm->te);
1182 psm->ts = rpmtsFree(psm->ts);
1184 (void) rpmpsmUnlink(psm, msg);
1186 memset(psm, 0, sizeof(*psm)); /* XXX trash and burn */
1192 rpmpsm rpmpsmNew(rpmts ts, rpmte te, rpmfi fi)
1194 const char * msg = "rpmpsmNew";
1195 rpmpsm psm = xcalloc(1, sizeof(*psm));
1197 if (ts) psm->ts = rpmtsLink(ts, msg);
1199 if (te) psm->te = rpmteLink(te, msg);
1201 if (te) psm->te = te;
1203 if (fi) psm->fi = rpmfiLink(fi, msg);
1205 return rpmpsmLink(psm, msg);
1208 static void * rpmpsmThread(void * arg)
1211 return ((void *) rpmpsmStage(psm, psm->nstage));
1214 static int rpmpsmNext(rpmpsm psm, pkgStage nstage)
1216 psm->nstage = nstage;
1218 return rpmsqJoin( rpmsqThread(rpmpsmThread, psm) );
1219 return rpmpsmStage(psm, psm->nstage);
1223 * @todo Packages w/o files never get a callback, hence don't get displayed
1224 * on install with -v.
1226 /* FIX: testing null annotation for fi->h */
1227 rpmRC rpmpsmStage(rpmpsm psm, pkgStage stage)
1229 const rpmts ts = psm->ts;
1230 uint32_t tscolor = rpmtsColor(ts);
1232 HGE_t hge = fi->hge;
1233 HFD_t hfd = (fi->hfd ? fi->hfd : headerFreeData);
1242 rpmlog(RPMLOG_DEBUG, _("%s: %s has %d files, test = %d\n"),
1243 psm->stepName, rpmteNEVR(psm->te),
1244 rpmfiFC(fi), (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST));
1247 * When we run scripts, we pass an argument which is the number of
1248 * versions of this package that will be installed when we are
1251 psm->npkgs_installed = rpmdbCountPackages(rpmtsGetRdb(ts), rpmteN(psm->te));
1252 if (psm->npkgs_installed < 0) {
1257 /* If we have a score then autorollback is enabled. If autorollback is
1258 * enabled, and this is an autorollback transaction, then we may need to
1259 * adjust the pkgs installed count.
1261 * If all this is true, this adjustment should only be made if the PSM goal
1262 * is an install. No need to make this adjustment on the erase
1263 * component of the upgrade, or even more absurd to do this when doing a
1266 if (rpmtsGetScore(ts) != NULL &&
1267 rpmtsGetType(ts) == RPMTRANS_TYPE_AUTOROLLBACK &&
1268 (psm->goal & ~(PSM_PKGSAVE|PSM_PKGERASE))) {
1269 /* Get the score, if its not NULL, get the appropriate
1272 rpmtsScore score = rpmtsGetScore(ts);
1273 if (score != NULL) {
1274 /* OK, we got a real score so lets get the appropriate
1278 se = rpmtsScoreGetEntry(score, rpmteN(psm->te));
1280 /* IF the header for the install element has been installed,
1281 * but the header for the erase element has not been erased,
1282 * then decrement the instance count. This is because in an
1283 * autorollback, if the header was added in the initial transaction
1284 * then in the case of an upgrade the instance count will be
1285 * 2 instead of one when re-installing the old package, and 3 when
1286 * erasing the new package.
1288 * Another wrinkle is we only want to make this adjustement
1289 * if the thing we are rollback was an upgrade of package. A pure
1290 * install or erase does not need the adjustment
1292 if (se && se->installed &&
1294 (se->te_types & (TR_ADDED|TR_REMOVED)))
1295 psm->npkgs_installed--;
1299 if (psm->goal == PSM_PKGINSTALL) {
1300 int fc = rpmfiFC(fi);
1302 psm->scriptArg = psm->npkgs_installed + 1;
1304 assert(psm->mi == NULL);
1305 psm->mi = rpmtsInitIterator(ts, RPMTAG_NAME, rpmteN(psm->te), 0);
1306 xx = rpmdbSetIteratorRE(psm->mi, RPMTAG_EPOCH, RPMMIRE_STRCMP,
1308 xx = rpmdbSetIteratorRE(psm->mi, RPMTAG_VERSION, RPMMIRE_STRCMP,
1310 xx = rpmdbSetIteratorRE(psm->mi, RPMTAG_RELEASE, RPMMIRE_STRCMP,
1313 xx = rpmdbSetIteratorRE(psm->mi, RPMTAG_ARCH, RPMMIRE_STRCMP,
1315 xx = rpmdbSetIteratorRE(psm->mi, RPMTAG_OS, RPMMIRE_STRCMP,
1319 while ((psm->oh = rpmdbNextIterator(psm->mi)) != NULL) {
1320 fi->record = rpmdbGetIteratorOffset(psm->mi);
1324 psm->mi = rpmdbFreeIterator(psm->mi);
1327 /* XXX lazy alloc here may need to be done elsewhere. */
1328 if (fi->fstates == NULL && fc > 0) {
1329 fi->fstates = xmalloc(sizeof(*fi->fstates) * fc);
1330 memset(fi->fstates, RPMFILE_STATE_NORMAL, fc);
1333 if (rpmtsFlags(ts) & RPMTRANS_FLAG_JUSTDB) break;
1337 * Old format relocatable packages need the entire default
1338 * prefix stripped to form the cpio list, while all other packages
1339 * need the leading / stripped.
1342 xx = hge(fi->h, RPMTAG_DEFAULTPREFIX, NULL, (void **) &p, NULL);
1343 fi->striplen = (xx ? strlen(p) + 1 : 1);
1346 CPIO_MAP_PATH | CPIO_MAP_MODE | CPIO_MAP_UID | CPIO_MAP_GID | (fi->mapflags & CPIO_SBIT_CHECK);
1348 if (headerIsEntry(fi->h, RPMTAG_ORIGBASENAMES))
1349 rpmfiBuildFNames(fi->h, RPMTAG_ORIGBASENAMES, &fi->apath, NULL);
1351 rpmfiBuildFNames(fi->h, RPMTAG_BASENAMES, &fi->apath, NULL);
1353 if (fi->fuser == NULL)
1354 xx = hge(fi->h, RPMTAG_FILEUSERNAME, NULL,
1355 (void **) &fi->fuser, NULL);
1356 if (fi->fgroup == NULL)
1357 xx = hge(fi->h, RPMTAG_FILEGROUPNAME, NULL,
1358 (void **) &fi->fgroup, NULL);
1361 if (psm->goal == PSM_PKGERASE || psm->goal == PSM_PKGSAVE) {
1362 psm->scriptArg = psm->npkgs_installed - 1;
1364 /* Retrieve installed header. */
1365 rc = rpmpsmNext(psm, PSM_RPMDB_LOAD);
1366 if (rc == RPMRC_OK && psm->te)
1367 rpmteSetHeader(psm->te, fi->h);
1369 if (psm->goal == PSM_PKGSAVE) {
1370 /* Open output package for writing. */
1371 { const char * bfmt = rpmGetPath("%{_repackage_name_fmt}", NULL);
1372 const char * pkgbn =
1373 headerSprintf(fi->h, bfmt, rpmTagTable, rpmHeaderFormats, NULL);
1376 psm->pkgURL = rpmGenPath("%{?_repackage_root}",
1377 "%{?_repackage_dir}",
1379 pkgbn = _free(pkgbn);
1380 (void) urlPath(psm->pkgURL, &psm->pkgfn);
1381 psm->fd = Fopen(psm->pkgfn, "w.ufdio");
1382 if (psm->fd == NULL || Ferror(psm->fd)) {
1390 if (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST) break;
1392 /* XXX insure that trigger index is opened before entering chroot. */
1394 { static int oneshot = 0;
1397 dbi = dbiOpen(rpmtsGetRdb(ts), RPMTAG_TRIGGERNAME, 0);
1403 /* Change root directory if requested and not already done. */
1404 rc = rpmpsmNext(psm, PSM_CHROOT_IN);
1406 if (psm->goal == PSM_PKGINSTALL) {
1407 psm->scriptTag = RPMTAG_PREIN;
1408 psm->progTag = RPMTAG_PREINPROG;
1410 if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOTRIGGERPREIN)) {
1411 /* XXX FIXME: implement %triggerprein. */
1414 if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOPRE)) {
1415 rc = rpmpsmNext(psm, PSM_SCRIPT);
1416 if (rc != RPMRC_OK) {
1418 _("%s: %s scriptlet failed (%d), skipping %s\n"),
1419 psm->stepName, tag2sln(psm->scriptTag), rc,
1420 rpmteNEVR(psm->te));
1426 if (psm->goal == PSM_PKGERASE) {
1427 psm->scriptTag = RPMTAG_PREUN;
1428 psm->progTag = RPMTAG_PREUNPROG;
1429 psm->sense = RPMSENSE_TRIGGERUN;
1430 psm->countCorrection = -1;
1432 if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOTRIGGERUN)) {
1433 /* Run triggers in this package other package(s) set off. */
1434 rc = rpmpsmNext(psm, PSM_IMMED_TRIGGERS);
1437 /* Run triggers in other package(s) this package sets off. */
1438 rc = rpmpsmNext(psm, PSM_TRIGGERS);
1442 if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOPREUN))
1443 rc = rpmpsmNext(psm, PSM_SCRIPT);
1445 if (psm->goal == PSM_PKGSAVE) {
1446 int noArchiveSize = 0;
1448 /* Regenerate original header. */
1452 if (headerGetEntry(fi->h, RPMTAG_HEADERIMMUTABLE, &uht, &uh, &uhc)) {
1453 psm->oh = headerCopyLoad(uh);
1456 if (headerGetEntry(fi->h, RPMTAG_HEADERIMAGE, &uht, &uh, &uhc))
1459 int32_t tag, type, count;
1463 /* Load the original header from the blob. */
1464 oh = headerCopyLoad(uh);
1466 /* XXX this is headerCopy w/o headerReload() */
1467 psm->oh = headerNew();
1469 for (hi = headerInitIterator(oh);
1470 headerNextIterator(hi, &tag, &type, &ptr, &count);
1471 ptr = headerFreeData((void *)ptr, type))
1473 if (tag == RPMTAG_ARCHIVESIZE)
1475 if (ptr) (void) headerAddEntry(psm->oh, tag, type, ptr, count);
1477 hi = headerFreeIterator(hi);
1479 oh = headerFree(oh);
1482 break; /* XXX shouldn't ever happen */
1485 /* Retrieve type of payload compression. */
1486 /* FIX: psm->oh may be NULL */
1487 rc = rpmpsmNext(psm, PSM_RPMIO_FLAGS);
1489 /* Write the lead section into the package. */
1491 rpmlead lead = rpmLeadFromHeader(psm->oh);
1492 rc = rpmLeadWrite(psm->fd, lead);
1493 lead = rpmLeadFree(lead);
1494 if (rc != RPMRC_OK) {
1495 rpmlog(RPMLOG_ERR, _("Unable to write package: %s\n"),
1496 Fstrerror(psm->fd));
1501 /* Write the signature section into the package. */
1502 /* XXX rpm-4.1 and later has archive size in signature header. */
1503 { Header sigh = headerRegenSigHeader(fi->h, noArchiveSize);
1504 /* Reallocate the signature into one contiguous region. */
1505 sigh = headerReload(sigh, RPMTAG_HEADERSIGNATURES);
1507 rpmlog(RPMLOG_ERR, _("Unable to reload signature header\n"));
1511 rc = rpmWriteSignature(psm->fd, sigh);
1512 sigh = rpmFreeSignature(sigh);
1516 /* Add remove transaction id to header. */
1517 if (psm->oh != NULL)
1518 { int32_t tid = rpmtsGetTid(ts);
1519 xx = headerAddEntry(psm->oh, RPMTAG_REMOVETID,
1520 RPM_INT32_TYPE, &tid, 1);
1523 /* Write the metadata section into the package. */
1524 rc = headerWrite(psm->fd, psm->oh, HEADER_MAGIC_YES);
1529 if (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST) break;
1531 if (psm->goal == PSM_PKGINSTALL) {
1533 if (rpmtsFlags(ts) & RPMTRANS_FLAG_JUSTDB) break;
1535 /* XXX Synthesize callbacks for packages with no files. */
1536 if (rpmfiFC(fi) <= 0) {
1538 ptr = rpmtsNotify(ts, fi->te, RPMCALLBACK_INST_START, 0, 100);
1539 ptr = rpmtsNotify(ts, fi->te, RPMCALLBACK_INST_PROGRESS, 100, 100);
1543 /* Retrieve type of payload compression. */
1544 rc = rpmpsmNext(psm, PSM_RPMIO_FLAGS);
1546 if (rpmteFd(fi->te) == NULL) { /* XXX can't happen */
1551 /* LCL: fi->fd != NULL here. */
1552 psm->cfd = Fdopen(fdDup(Fileno(rpmteFd(fi->te))), psm->rpmio_flags);
1553 if (psm->cfd == NULL) { /* XXX can't happen */
1558 rc = fsmSetup(fi->fsm, FSM_PKGINSTALL, ts, fi,
1559 psm->cfd, NULL, &psm->failedFile);
1560 (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_UNCOMPRESS),
1561 fdOp(psm->cfd, FDSTAT_READ));
1562 (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_DIGEST),
1563 fdOp(psm->cfd, FDSTAT_DIGEST));
1564 xx = fsmTeardown(fi->fsm);
1566 saveerrno = errno; /* XXX FIXME: Fclose with libio destroys errno */
1567 xx = Fclose(psm->cfd);
1569 errno = saveerrno; /* XXX FIXME: Fclose with libio destroys errno */
1572 rc = rpmpsmNext(psm, PSM_COMMIT);
1574 /* XXX make sure progress is closed out */
1575 psm->what = RPMCALLBACK_INST_PROGRESS;
1576 psm->amount = (fi->archiveSize ? fi->archiveSize : 100);
1577 psm->total = psm->amount;
1578 xx = rpmpsmNext(psm, PSM_NOTIFY);
1582 _("unpacking of archive failed%s%s: %s\n"),
1583 (psm->failedFile != NULL ? _(" on file ") : ""),
1584 (psm->failedFile != NULL ? psm->failedFile : ""),
1588 /* XXX notify callback on error. */
1589 psm->what = RPMCALLBACK_UNPACK_ERROR;
1592 xx = rpmpsmNext(psm, PSM_NOTIFY);
1597 if (psm->goal == PSM_PKGERASE) {
1598 int fc = rpmfiFC(fi);
1600 if (rpmtsFlags(ts) & RPMTRANS_FLAG_JUSTDB) break;
1601 if (rpmtsFlags(ts) & RPMTRANS_FLAG_APPLYONLY) break;
1603 /* XXX Synthesize callbacks for packages with no files. */
1604 if (rpmfiFC(fi) <= 0) {
1606 ptr = rpmtsNotify(ts, fi->te, RPMCALLBACK_UNINST_START, 0, 100);
1607 ptr = rpmtsNotify(ts, fi->te, RPMCALLBACK_UNINST_STOP, 0, 100);
1611 psm->what = RPMCALLBACK_UNINST_START;
1612 psm->amount = fc; /* XXX W2DO? looks wrong. */
1614 xx = rpmpsmNext(psm, PSM_NOTIFY);
1616 rc = fsmSetup(fi->fsm, FSM_PKGERASE, ts, fi,
1617 NULL, NULL, &psm->failedFile);
1618 xx = fsmTeardown(fi->fsm);
1620 psm->what = RPMCALLBACK_UNINST_STOP;
1621 psm->amount = 0; /* XXX W2DO? looks wrong. */
1623 xx = rpmpsmNext(psm, PSM_NOTIFY);
1626 if (psm->goal == PSM_PKGSAVE) {
1627 rpmFileAction * actions = fi->actions;
1628 rpmFileAction action = fi->action;
1630 fi->action = FA_COPYOUT;
1633 if (psm->fd == NULL) { /* XXX can't happen */
1637 /* FIX: fdDup mey return NULL. */
1638 xx = Fflush(psm->fd);
1639 psm->cfd = Fdopen(fdDup(Fileno(psm->fd)), psm->rpmio_flags);
1640 if (psm->cfd == NULL) { /* XXX can't happen */
1645 rc = fsmSetup(fi->fsm, FSM_PKGBUILD, ts, fi, psm->cfd,
1646 NULL, &psm->failedFile);
1647 (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_COMPRESS),
1648 fdOp(psm->cfd, FDSTAT_WRITE));
1649 (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_DIGEST),
1650 fdOp(psm->cfd, FDSTAT_DIGEST));
1651 xx = fsmTeardown(fi->fsm);
1653 saveerrno = errno; /* XXX FIXME: Fclose with libio destroys errno */
1654 xx = Fclose(psm->cfd);
1658 /* XXX make sure progress is closed out */
1659 psm->what = RPMCALLBACK_INST_PROGRESS;
1660 psm->amount = (fi->archiveSize ? fi->archiveSize : 100);
1661 psm->total = psm->amount;
1662 xx = rpmpsmNext(psm, PSM_NOTIFY);
1664 fi->action = action;
1665 fi->actions = actions;
1669 if (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST) break;
1671 if (psm->goal == PSM_PKGINSTALL) {
1672 int32_t installTime = (int32_t) time(NULL);
1673 int fc = rpmfiFC(fi);
1675 if (fi->h == NULL) break; /* XXX can't happen */
1676 if (fi->fstates != NULL && fc > 0)
1677 xx = headerAddEntry(fi->h, RPMTAG_FILESTATES, RPM_CHAR_TYPE,
1680 xx = headerAddEntry(fi->h, RPMTAG_INSTALLTIME, RPM_INT32_TYPE,
1683 xx = headerAddEntry(fi->h, RPMTAG_INSTALLCOLOR, RPM_INT32_TYPE,
1687 * If this package has already been installed, remove it from
1688 * the database before adding the new one.
1690 if (fi->record && !(rpmtsFlags(ts) & RPMTRANS_FLAG_APPLYONLY)) {
1691 rc = rpmpsmNext(psm, PSM_RPMDB_REMOVE);
1695 rc = rpmpsmNext(psm, PSM_RPMDB_ADD);
1698 psm->scriptTag = RPMTAG_POSTIN;
1699 psm->progTag = RPMTAG_POSTINPROG;
1700 psm->sense = RPMSENSE_TRIGGERIN;
1701 psm->countCorrection = 0;
1703 if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOPOST)) {
1704 rc = rpmpsmNext(psm, PSM_SCRIPT);
1707 if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOTRIGGERIN)) {
1708 /* Run triggers in other package(s) this package sets off. */
1709 rc = rpmpsmNext(psm, PSM_TRIGGERS);
1712 /* Run triggers in this package other package(s) set off. */
1713 rc = rpmpsmNext(psm, PSM_IMMED_TRIGGERS);
1717 if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_APPLYONLY))
1718 rc = markReplacedFiles(psm);
1721 if (psm->goal == PSM_PKGERASE) {
1723 psm->scriptTag = RPMTAG_POSTUN;
1724 psm->progTag = RPMTAG_POSTUNPROG;
1725 psm->sense = RPMSENSE_TRIGGERPOSTUN;
1726 psm->countCorrection = -1;
1728 if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOPOSTUN)) {
1729 rc = rpmpsmNext(psm, PSM_SCRIPT);
1733 if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOTRIGGERPOSTUN)) {
1734 /* Run triggers in other package(s) this package sets off. */
1735 rc = rpmpsmNext(psm, PSM_TRIGGERS);
1739 if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_APPLYONLY))
1740 rc = rpmpsmNext(psm, PSM_RPMDB_REMOVE);
1742 if (psm->goal == PSM_PKGSAVE) {
1745 /* Restore root directory if changed. */
1746 xx = rpmpsmNext(psm, PSM_CHROOT_OUT);
1751 /* Restore root directory if changed. */
1752 xx = rpmpsmNext(psm, PSM_CHROOT_OUT);
1754 if (psm->fd != NULL) {
1755 saveerrno = errno; /* XXX FIXME: Fclose with libio destroys errno */
1756 xx = Fclose(psm->fd);
1762 if (psm->failedFile)
1764 _("%s failed on file %s: %s\n"),
1765 psm->stepName, psm->failedFile, cpioStrerror(rc));
1767 rpmlog(RPMLOG_ERR, _("%s failed: %s\n"),
1768 psm->stepName, cpioStrerror(rc));
1770 /* XXX notify callback on error. */
1771 psm->what = RPMCALLBACK_CPIO_ERROR;
1774 /* FIX: psm->fd may be NULL. */
1775 xx = rpmpsmNext(psm, PSM_NOTIFY);
1778 if (psm->goal == PSM_PKGERASE || psm->goal == PSM_PKGSAVE) {
1779 if (psm->te != NULL)
1780 rpmteSetHeader(psm->te, NULL);
1782 fi->h = headerFree(fi->h);
1784 psm->oh = headerFree(psm->oh);
1785 psm->pkgURL = _free(psm->pkgURL);
1786 psm->rpmio_flags = _free(psm->rpmio_flags);
1787 psm->failedFile = _free(psm->failedFile);
1789 fi->fgroup = hfd(fi->fgroup, -1);
1790 fi->fuser = hfd(fi->fuser, -1);
1791 fi->apath = _free(fi->apath);
1792 fi->fstates = _free(fi->fstates);
1795 case PSM_PKGINSTALL:
1800 psm->stepName = pkgStageString(stage);
1802 rc = rpmpsmNext(psm, PSM_INIT);
1803 if (!rc) rc = rpmpsmNext(psm, PSM_PRE);
1804 if (!rc) rc = rpmpsmNext(psm, PSM_PROCESS);
1805 if (!rc) rc = rpmpsmNext(psm, PSM_POST);
1806 xx = rpmpsmNext(psm, PSM_FINI);
1815 /* FIX: psm->te may be NULL */
1816 ptr = rpmtsNotify(ts, psm->te, psm->what, psm->amount, psm->total);
1821 if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_PKGCOMMIT)) break;
1822 if (rpmtsFlags(ts) & RPMTRANS_FLAG_APPLYONLY) break;
1824 rc = fsmSetup(fi->fsm, FSM_PKGCOMMIT, ts, fi,
1825 NULL, NULL, &psm->failedFile);
1826 xx = fsmTeardown(fi->fsm);
1830 { const char * rootDir = rpmtsRootDir(ts);
1831 /* Change root directory if requested and not already done. */
1832 if (rootDir != NULL && !(rootDir[0] == '/' && rootDir[1] == '\0')
1833 && !rpmtsChrootDone(ts) && !psm->chrootDone)
1835 static int _pw_loaded = 0;
1836 static int _gr_loaded = 0;
1839 (void)getpwnam("root");
1844 (void)getgrnam("root");
1850 if (rootDir != NULL && strcmp(rootDir, "/") && *rootDir == '/')
1851 rc = chroot(rootDir);
1852 psm->chrootDone = 1;
1853 (void) rpmtsSetChrootDone(ts, 1);
1856 case PSM_CHROOT_OUT:
1857 /* Restore root directory if changed. */
1858 if (psm->chrootDone) {
1859 const char * rootDir = rpmtsRootDir(ts);
1860 const char * currDir = rpmtsCurrDir(ts);
1861 if (rootDir != NULL && strcmp(rootDir, "/") && *rootDir == '/')
1863 psm->chrootDone = 0;
1864 (void) rpmtsSetChrootDone(ts, 0);
1865 if (currDir != NULL) /* XXX can't happen */
1866 xx = chdir(currDir);
1869 case PSM_SCRIPT: /* Run current package scriptlets. */
1870 rc = runInstScript(psm);
1873 /* Run triggers in other package(s) this package sets off. */
1874 rc = runTriggers(psm);
1876 case PSM_IMMED_TRIGGERS:
1877 /* Run triggers in this package other package(s) set off. */
1878 rc = runImmedTriggers(psm);
1881 case PSM_RPMIO_FLAGS:
1882 { const char * payload_compressor = NULL;
1885 if (!hge(fi->h, RPMTAG_PAYLOADCOMPRESSOR, NULL,
1886 (void **) &payload_compressor, NULL))
1887 payload_compressor = "gzip";
1888 psm->rpmio_flags = t = xmalloc(sizeof("w9.gzdio"));
1890 t = stpcpy(t, ((psm->goal == PSM_PKGSAVE) ? "w9" : "r"));
1891 if (!strcmp(payload_compressor, "gzip"))
1892 t = stpcpy(t, ".gzdio");
1893 if (!strcmp(payload_compressor, "bzip2"))
1894 t = stpcpy(t, ".bzdio");
1898 case PSM_RPMDB_LOAD:
1899 assert(psm->mi == NULL);
1900 psm->mi = rpmtsInitIterator(ts, RPMDBI_PACKAGES,
1901 &fi->record, sizeof(fi->record));
1903 fi->h = rpmdbNextIterator(psm->mi);
1905 fi->h = headerLink(fi->h);
1907 psm->mi = rpmdbFreeIterator(psm->mi);
1908 rc = (fi->h != NULL ? RPMRC_OK : RPMRC_FAIL);
1911 if (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST) break;
1912 if (fi->h == NULL) break; /* XXX can't happen */
1913 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DBADD), 0);
1914 if (!(rpmtsVSFlags(ts) & RPMVSF_NOHDRCHK))
1915 rc = rpmdbAdd(rpmtsGetRdb(ts), rpmtsGetTid(ts), fi->h,
1918 rc = rpmdbAdd(rpmtsGetRdb(ts), rpmtsGetTid(ts), fi->h,
1921 /* Set the database instance so consumers (i.e. rpmtsRun())
1922 * can add this to a rollback transaction.
1924 rpmteSetDBInstance(psm->te, myinstall_instance);
1927 * If the score exists and this is not a rollback or autorollback
1928 * then lets check off installed for this package.
1930 if (rpmtsGetScore(ts) != NULL &&
1931 rpmtsGetType(ts) != RPMTRANS_TYPE_ROLLBACK &&
1932 rpmtsGetType(ts) != RPMTRANS_TYPE_AUTOROLLBACK)
1934 /* Get the score, if its not NULL, get the appropriate
1937 rpmtsScore score = rpmtsGetScore(ts);
1938 if (score != NULL) {
1940 /* OK, we got a real score so lets get the appropriate
1943 rpmlog(RPMLOG_DEBUG,
1944 _("Attempting to mark %s as installed in score board(%p).\n"),
1945 rpmteN(psm->te), score);
1946 se = rpmtsScoreGetEntry(score, rpmteN(psm->te));
1947 if (se != NULL) se->installed = 1;
1950 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DBADD), 0);
1952 case PSM_RPMDB_REMOVE:
1953 if (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST) break;
1954 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DBREMOVE), 0);
1955 rc = rpmdbRemove(rpmtsGetRdb(ts), rpmtsGetTid(ts), fi->record,
1959 * If the score exists and this is not a rollback or autorollback
1960 * then lets check off erased for this package.
1962 if (rpmtsGetScore(ts) != NULL &&
1963 rpmtsGetType(ts) != RPMTRANS_TYPE_ROLLBACK &&
1964 rpmtsGetType(ts) != RPMTRANS_TYPE_AUTOROLLBACK)
1966 /* Get the score, if its not NULL, get the appropriate
1969 rpmtsScore score = rpmtsGetScore(ts);
1971 if (score != NULL) { /* XXX: Can't happen */
1973 /* OK, we got a real score so lets get the appropriate
1976 rpmlog(RPMLOG_DEBUG,
1977 _("Attempting to mark %s as erased in score board(%p).\n"),
1978 rpmteN(psm->te), score);
1979 se = rpmtsScoreGetEntry(score, rpmteN(psm->te));
1980 if (se != NULL) se->erased = 1;
1984 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DBREMOVE), 0);
1991 /* FIX: psm->oh and psm->fi->h may be NULL. */