1 /** \ingroup rpmts payload
3 * Package state machine to handle a package from a transaction set.
8 #include <rpmio_internal.h>
14 #include "fsm.h" /* XXX CPIO_FOO/FSM_FOO constants */
19 #define _RPMFI_INTERNAL
22 #define _RPMTE_INTERNAL
25 #define _RPMTS_INTERNAL /* XXX ts->notify */
28 #include "rpmlead.h" /* writeLead proto */
29 #include "signature.h" /* signature constants */
30 #include "legacy.h" /* XXX rpmfiBuildFNames() */
31 #include "ugid.h" /* XXX unameToUid() and gnameToGid() */
32 #include "misc.h" /* XXX stripTrailingChar() */
33 #include "rpmdb.h" /* XXX for db_chrootDone */
38 int _psm_debug = _PSM_DEBUG;
42 /*@access FD_t @*/ /* XXX void ptr args */
46 /*@access rpmte @*/ /* XXX rpmInstallSourcePackage */
47 /*@access rpmts @*/ /* XXX ts->notify */
49 int rpmVersionCompare(Header first, Header second)
51 const char * one, * two;
52 int_32 * epochOne, * epochTwo;
55 if (!headerGetEntry(first, RPMTAG_EPOCH, NULL, (void **) &epochOne, NULL))
57 if (!headerGetEntry(second, RPMTAG_EPOCH, NULL, (void **) &epochTwo, NULL))
60 if (epochOne != NULL && epochTwo == NULL)
62 else if (epochOne == NULL && epochTwo != NULL)
64 else if (epochOne != NULL && epochTwo != NULL) {
66 if (*epochOne < *epochTwo)
68 else if (*epochOne > *epochTwo)
73 rc = headerGetEntry(first, RPMTAG_VERSION, NULL, (void **) &one, NULL);
74 rc = headerGetEntry(second, RPMTAG_VERSION, NULL, (void **) &two, NULL);
76 rc = rpmvercmp(one, two);
80 rc = headerGetEntry(first, RPMTAG_RELEASE, NULL, (void **) &one, NULL);
81 rc = headerGetEntry(second, RPMTAG_RELEASE, NULL, (void **) &two, NULL);
83 return rpmvercmp(one, two);
87 * Macros to be defined from per-header tag values.
88 * @todo Should other macros be added from header when installing a package?
90 /*@observer@*/ /*@unchecked@*/
91 static struct tagMacro {
92 /*@observer@*/ /*@null@*/ const char * macroname; /*!< Macro name to define. */
93 rpmTag tag; /*!< Header tag to use for value. */
95 { "name", RPMTAG_NAME },
96 { "version", RPMTAG_VERSION },
97 { "release", RPMTAG_RELEASE },
98 { "epoch", RPMTAG_EPOCH },
103 * Define per-header macros.
104 * @param fi transaction element file info
108 static int rpmInstallLoadMacros(rpmfi fi, Header h)
109 /*@globals rpmGlobalMacroContext @*/
110 /*@modifies rpmGlobalMacroContext @*/
112 HGE_t hge = (HGE_t) fi->hge;
113 struct tagMacro * tagm;
115 /*@unused@*/ void * ptr;
116 /*@unused@*/ const char ** argv;
123 for (tagm = tagMacros; tagm->macroname != NULL; tagm++) {
124 if (!hge(h, tagm->tag, &type, (void **) &body, NULL))
129 sprintf(numbuf, "%d", *body.i32p);
131 addMacro(NULL, tagm->macroname, NULL, numbuf, -1);
132 /*@switchbreak@*/ break;
133 case RPM_STRING_TYPE:
134 addMacro(NULL, tagm->macroname, NULL, body.str, -1);
135 /*@switchbreak@*/ break;
141 case RPM_STRING_ARRAY_TYPE:
142 case RPM_I18NSTRING_TYPE:
144 /*@switchbreak@*/ break;
151 * Mark files in database shared with this package as "replaced".
152 * @param psm package state machine data
156 static rpmRC markReplacedFiles(const rpmpsm psm)
157 /*@globals rpmGlobalMacroContext, fileSystem, internalState @*/
158 /*@modifies psm, rpmGlobalMacroContext, fileSystem, internalState @*/
160 const rpmts ts = psm->ts;
162 HGE_t hge = (HGE_t)fi->hge;
163 sharedFileInfo replaced = fi->replaced;
165 rpmdbMatchIterator mi;
167 unsigned int * offsets;
171 if (!(rpmfiFC(fi) > 0 && fi->replaced))
175 for (sfi = replaced; sfi->otherPkg; sfi++) {
176 if (prev && prev == sfi->otherPkg)
178 prev = sfi->otherPkg;
184 offsets = alloca(num * sizeof(*offsets));
187 for (sfi = replaced; sfi->otherPkg; sfi++) {
188 if (prev && prev == sfi->otherPkg)
190 prev = sfi->otherPkg;
191 offsets[num++] = sfi->otherPkg;
194 mi = rpmtsInitIterator(ts, RPMDBI_PACKAGES, NULL, 0);
195 xx = rpmdbAppendIterator(mi, offsets, num);
196 xx = rpmdbSetIteratorRewrite(mi, 1);
199 while ((h = rpmdbNextIterator(mi)) != NULL) {
206 if (!hge(h, RPMTAG_FILESTATES, NULL, (void **)&secStates, &count))
209 prev = rpmdbGetIteratorOffset(mi);
211 while (sfi->otherPkg && sfi->otherPkg == prev) {
212 assert(sfi->otherFileNum < count);
213 if (secStates[sfi->otherFileNum] != RPMFILE_STATE_REPLACED) {
214 secStates[sfi->otherFileNum] = RPMFILE_STATE_REPLACED;
216 /* Modified header will be rewritten. */
218 xx = rpmdbSetIteratorModified(mi, modified);
225 mi = rpmdbFreeIterator(mi);
231 rpmRC rpmInstallSourcePackage(rpmts ts, FD_t fd,
232 const char ** specFilePtr, const char ** cookie)
236 const char * _sourcedir = NULL;
237 const char * _specdir = NULL;
238 const char * specFile = NULL;
242 struct rpmpsm_s psmbuf;
243 rpmpsm psm = &psmbuf;
248 memset(psm, 0, sizeof(*psm));
249 psm->ts = rpmtsLink(ts, "InstallSourcePackage");
251 rc = rpmReadPackageFile(ts, fd, "InstallSourcePackage", &h);
253 case RPMRC_NOTTRUSTED:
259 /*@notreached@*/ break;
266 isSource = headerIsEntry(h, RPMTAG_SOURCEPACKAGE);
269 rpmError(RPMERR_NOTSRPM, _("source package expected, binary found\n"));
274 (void) rpmtsAddInstallElement(ts, h, NULL, 0, NULL);
276 fi = rpmfiNew(ts, h, RPMTAG_BASENAMES, scareMem);
279 if (fi == NULL) { /* XXX can't happen */
284 /*@-onlytrans@*/ /* FIX: te reference */
285 fi->te = rpmtsElement(ts, 0);
287 if (fi->te == NULL) { /* XXX can't happen */
292 /*@-nullpass@*/ /* FIX fi->h may be null */
293 fi->te->h = headerLink(fi->h);
295 fi->te->fd = fdLink(fd, "installSourcePackage");
299 /*@i@*/ (void) rpmInstallLoadMacros(fi, fi->h);
301 psm->fi = rpmfiLink(fi, NULL);
302 /*@-assignexpose -usereleased @*/
304 /*@=assignexpose =usereleased @*/
308 if (hge(fi->h, RPMTAG_COOKIE, NULL, (void **) cookie, NULL))
309 *cookie = xstrdup(*cookie);
312 /* XXX FIXME: can't do endian neutral MD5 verification yet. */
313 /*@i@*/ fi->fmd5s = hfd(fi->fmd5s, -1);
315 /* XXX FIXME: don't do per-file mapping, force global flags. */
316 fi->fmapflags = _free(fi->fmapflags);
317 fi->mapflags = CPIO_MAP_PATH | CPIO_MAP_MODE | CPIO_MAP_UID | CPIO_MAP_GID;
324 fi->fuids = xcalloc(sizeof(*fi->fuids), fi->fc);
325 fi->fgids = xcalloc(sizeof(*fi->fgids), fi->fc);
326 for (i = 0; i < fi->fc; i++) {
327 fi->fuids[i] = fi->uid;
328 fi->fgids[i] = fi->gid;
331 for (i = 0; i < fi->fc; i++)
332 fi->actions[i] = FA_CREATE;
336 if (fi->h != NULL) { /* XXX can't happen */
337 rpmfiBuildFNames(fi->h, RPMTAG_BASENAMES, &fi->apath, NULL);
339 if (headerIsEntry(fi->h, RPMTAG_COOKIE))
340 for (i = 0; i < fi->fc; i++)
341 if (fi->fflags[i] & RPMFILE_SPECFILE) break;
345 /* Find the spec file by name. */
346 for (i = 0; i < fi->fc; i++) {
347 const char * t = fi->apath[i];
348 t += strlen(fi->apath[i]) - 5;
349 if (!strcmp(t, ".spec")) break;
353 _sourcedir = rpmGenPath(rpmtsRootDir(ts), "%{_sourcedir}", "");
354 rc = rpmMkdirPath(_sourcedir, "sourcedir");
360 _specdir = rpmGenPath(rpmtsRootDir(ts), "%{_specdir}", "");
361 rc = rpmMkdirPath(_specdir, "specdir");
367 /* Build dnl/dil with {_sourcedir, _specdir} as values. */
369 int speclen = strlen(_specdir) + 2;
370 int sourcelen = strlen(_sourcedir) + 2;
373 /*@i@*/ fi->dnl = hfd(fi->dnl, -1);
376 fi->dnl = xmalloc(fi->dc * sizeof(*fi->dnl)
377 + fi->fc * sizeof(*fi->dil)
378 + speclen + sourcelen);
379 /*@-dependenttrans@*/
380 fi->dil = (int *)(fi->dnl + fi->dc);
381 /*@=dependenttrans@*/
382 memset(fi->dil, 0, fi->fc * sizeof(*fi->dil));
384 /*@-dependenttrans@*/
385 fi->dnl[0] = t = (char *)(fi->dil + fi->fc);
386 fi->dnl[1] = t = stpcpy( stpcpy(t, _sourcedir), "/") + 1;
387 /*@=dependenttrans@*/
388 (void) stpcpy( stpcpy(t, _specdir), "/");
390 t = xmalloc(speclen + strlen(fi->bnl[i]) + 1);
391 (void) stpcpy( stpcpy( stpcpy(t, _specdir), "/"), fi->bnl[i]);
394 rpmError(RPMERR_NOSPEC, _("source package contains no .spec file\n"));
399 psm->goal = PSM_PKGINSTALL;
401 /*@-compmempass@*/ /* FIX: psm->fi->dnl should be owned. */
402 rc = rpmpsmStage(psm, PSM_PROCESS);
404 (void) rpmpsmStage(psm, PSM_FINI);
407 if (rc) rc = RPMRC_FAIL;
410 if (specFilePtr && specFile && rc == RPMRC_OK)
411 *specFilePtr = specFile;
413 specFile = _free(specFile);
415 _specdir = _free(_specdir);
416 _sourcedir = _free(_sourcedir);
418 psm->fi = rpmfiFree(psm->fi);
421 if (h != NULL) h = headerFree(h);
425 fi->te->h = headerFree(fi->te->h);
426 if (fi->te->fd != NULL)
427 (void) Fclose(fi->te->fd);
434 /* XXX nuke the added package(s). */
437 psm->ts = rpmtsFree(psm->ts);
442 /*@observer@*/ /*@unchecked@*/
443 static char * SCRIPT_PATH = "PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin";
446 * Return scriptlet name from tag.
447 * @param tag scriptlet tag
448 * @return name of scriptlet
450 static /*@observer@*/ const char * const tag2sln(int tag)
454 case RPMTAG_PREIN: return "%pre";
455 case RPMTAG_POSTIN: return "%post";
456 case RPMTAG_PREUN: return "%preun";
457 case RPMTAG_POSTUN: return "%postun";
458 case RPMTAG_VERIFYSCRIPT: return "%verify";
460 return "%unknownscript";
464 * Wait for child process to be reaped.
465 * @param psm package state machine data
468 static pid_t psmWait(rpmpsm psm)
469 /*@globals fileSystem, internalState @*/
470 /*@modifies psm, fileSystem, internalState @*/
472 const rpmts ts = psm->ts;
475 (void) rpmsqWait(&psm->sq);
476 msecs = psm->sq.op.usecs/1000;
477 (void) rpmswAdd(&ts->op_scriptlets, &psm->sq.op);
479 rpmMessage(RPMMESS_DEBUG,
480 _("%s: waitpid(%d) rc %d status %x secs %u.%03u\n"),
481 psm->stepName, (unsigned)psm->sq.child,
482 (unsigned)psm->sq.reaped, psm->sq.status,
483 (unsigned)msecs/1000, (unsigned)msecs%1000);
485 return psm->sq.reaped;
491 static int ldconfig_done = 0;
493 /*@unchecked@*/ /*@observer@*/ /*@null@*/
494 static const char * ldconfig_path = "/sbin/ldconfig";
497 * Run scriptlet with args.
499 * Run a script with an interpreter. If the interpreter is not specified,
500 * /bin/sh will be used. If the interpreter is /bin/sh, then the args from
501 * the header will be ignored, passing instead arg1 and arg2.
503 * @param psm package state machine data
505 * @param sln name of scriptlet section
506 * @param progArgc no. of args from header
507 * @param progArgv args from header, progArgv[0] is the interpreter to use
508 * @param script scriptlet from header
509 * @param arg1 no. instances of package installed after scriptlet exec
511 * @param arg2 ditto, but for the target package
512 * @return 0 on success
514 static rpmRC runScript(rpmpsm psm, Header h, const char * sln,
515 int progArgc, const char ** progArgv,
516 const char * script, int arg1, int arg2)
517 /*@globals ldconfig_done, rpmGlobalMacroContext,
518 fileSystem, internalState@*/
519 /*@modifies psm, ldconfig_done, rpmGlobalMacroContext,
520 fileSystem, internalState @*/
522 const rpmts ts = psm->ts;
525 HFD_t hfd = (fi->hfd ? fi->hfd : headerFreeData);
526 const char ** argv = NULL;
528 const char ** prefixes = NULL;
531 const char * oldPrefix;
534 char * prefixBuf = NULL;
535 const char * fn = NULL;
538 int freePrefixes = 0;
542 const char *n, *v, *r;
544 if (progArgv == NULL && script == NULL)
549 /* XXX FIXME: except for %verifyscript, rpmteNEVR can be used. */
550 xx = headerNVR(h, &n, &v, &r);
552 /* XXX bash must have functional libtermcap.so.2 */
553 if (!strcmp(n, "libtermcap"))
557 * If a successor node, and ldconfig was just run, don't bother.
559 if (ldconfig_path && progArgv && psm->unorderedSuccessor) {
560 if (ldconfig_done && !strcmp(progArgv[0], ldconfig_path)) {
561 rpmMessage(RPMMESS_DEBUG,
562 _("%s: %s(%s-%s-%s) skipping redundant \"%s\".\n"),
563 psm->stepName, tag2sln(psm->scriptTag), n, v, r,
569 rpmMessage(RPMMESS_DEBUG,
570 _("%s: %s(%s-%s-%s) %ssynchronous scriptlet start\n"),
571 psm->stepName, tag2sln(psm->scriptTag), n, v, r,
572 (psm->unorderedSuccessor ? "a" : ""));
575 argv = alloca(5 * sizeof(*argv));
580 argv = alloca((progArgc + 4) * sizeof(*argv));
581 memcpy(argv, progArgv, progArgc * sizeof(*argv));
583 ldconfig_done = (ldconfig_path && !strcmp(argv[0], ldconfig_path)
587 if (hge(h, RPMTAG_INSTPREFIXES, &ipt, (void **) &prefixes, &numPrefixes)) {
589 } else if (hge(h, RPMTAG_INSTALLPREFIX, NULL, (void **) &oldPrefix, NULL)) {
590 prefixes = &oldPrefix;
597 if (prefixes != NULL)
598 for (i = 0; i < numPrefixes; i++) {
599 len = strlen(prefixes[i]);
600 if (len > maxPrefixLength) maxPrefixLength = len;
602 prefixBuf = alloca(maxPrefixLength + 50);
605 const char * rootDir = rpmtsRootDir(ts);
609 if (makeTempFile((!rpmtsChrootDone(ts) ? rootDir : "/"), &fn, &fd)) {
610 if (prefixes != NULL && freePrefixes) free(prefixes);
616 (!strcmp(argv[0], "/bin/sh") || !strcmp(argv[0], "/bin/bash")))
618 static const char set_x[] = "set -x\n";
619 xx = Fwrite(set_x, sizeof(set_x[0]), sizeof(set_x)-1, fd);
622 if (ldconfig_path && strstr(script, ldconfig_path) != NULL)
625 xx = Fwrite(script, sizeof(script[0]), strlen(script), fd);
628 { const char * sn = fn;
629 if (!rpmtsChrootDone(ts) && rootDir != NULL &&
630 !(rootDir[0] == '/' && rootDir[1] == '\0'))
632 sn += strlen(rootDir)-1;
638 char *av = alloca(20);
639 sprintf(av, "%d", arg1);
643 char *av = alloca(20);
644 sprintf(av, "%d", arg2);
651 scriptFd = rpmtsScriptFd(ts);
652 if (scriptFd != NULL) {
653 if (rpmIsVerbose()) {
654 out = fdDup(Fileno(scriptFd));
656 out = Fopen("/dev/null", "w.fdio");
658 out = fdDup(Fileno(scriptFd));
662 out = fdDup(STDOUT_FILENO);
664 if (out == NULL) return RPMRC_FAIL; /* XXX can't happen */
667 xx = rpmsqFork(&psm->sq);
668 if (psm->sq.child == 0) {
669 const char * rootDir;
672 pipes[0] = pipes[1] = 0;
673 /* make stdin inaccessible */
675 xx = close(pipes[1]);
676 xx = dup2(pipes[0], STDIN_FILENO);
677 xx = close(pipes[0]);
679 if (scriptFd != NULL) {
680 int sfdno = Fileno(scriptFd);
681 int ofdno = Fileno(out);
682 if (sfdno != STDERR_FILENO)
683 xx = dup2(sfdno, STDERR_FILENO);
684 if (ofdno != STDOUT_FILENO)
685 xx = dup2(ofdno, STDOUT_FILENO);
686 /* make sure we don't close stdin/stderr/stdout by mistake! */
687 if (ofdno > STDERR_FILENO && ofdno != sfdno) {
690 if (sfdno > STDERR_FILENO) {
691 xx = Fclose (scriptFd);
695 { const char *ipath = rpmExpand("PATH=%{_install_script_path}", NULL);
696 const char *path = SCRIPT_PATH;
698 if (ipath && ipath[5] != '%')
703 ipath = _free(ipath);
707 if (prefixes != NULL)
708 for (i = 0; i < numPrefixes; i++) {
709 sprintf(prefixBuf, "RPM_INSTALL_PREFIX%d=%s", i, prefixes[i]);
710 xx = doputenv(prefixBuf);
712 /* backwards compatibility */
714 sprintf(prefixBuf, "RPM_INSTALL_PREFIX=%s", prefixes[i]);
715 xx = doputenv(prefixBuf);
719 rootDir = rpmtsRootDir(ts);
720 if (rootDir != NULL) /* XXX can't happen */
721 switch(urlIsURL(rootDir)) {
723 rootDir += sizeof("file://") - 1;
724 rootDir = strchr(rootDir, '/');
727 if (!rpmtsChrootDone(ts) &&
728 !(rootDir[0] == '/' && rootDir[1] == '\0'))
730 /*@-superuser -noeffect @*/
731 xx = chroot(rootDir);
732 /*@=superuser =noeffect @*/
735 rpmMessage(RPMMESS_DEBUG, _("%s: %s(%s-%s-%s)\texecv(%s) pid %d\n"),
736 psm->stepName, sln, n, v, r,
737 argv[0], (unsigned)getpid());
738 unsetenv("MALLOC_CHECK_");
740 xx = execv(argv[0], (char *const *)argv);
754 if (psm->sq.reaped < 0) {
755 rpmError(RPMERR_SCRIPT,
756 _("%s(%s-%s-%s) scriptlet failed, waitpid(%d) rc %d: %s\n"),
757 sln, n, v, r, psm->sq.child, psm->sq.reaped, strerror(errno));
760 if (!WIFEXITED(psm->sq.status) || WEXITSTATUS(psm->sq.status)) {
761 rpmError(RPMERR_SCRIPT,
762 _("%s(%s-%s-%s) scriptlet failed, exit status %d\n"),
763 sln, n, v, r, WEXITSTATUS(psm->sq.status));
767 if (freePrefixes) prefixes = hfd(prefixes, ipt);
769 xx = Fclose(out); /* XXX dup'd STDOUT_FILENO */
783 * Retrieve and run scriptlet from header.
784 * @param psm package state machine data
785 * @return rpmRC return code
787 static rpmRC runInstScript(rpmpsm psm)
788 /*@globals rpmGlobalMacroContext, fileSystem, internalState @*/
789 /*@modifies psm, rpmGlobalMacroContext, fileSystem, internalState @*/
793 HFD_t hfd = (fi->hfd ? fi->hfd : headerFreeData);
803 * headerGetEntry() sets the data pointer to NULL if the entry does
806 xx = hge(fi->h, psm->scriptTag, &stt, (void **) &script, NULL);
807 xx = hge(fi->h, psm->progTag, &ptt, (void **) &progArgv, &progArgc);
808 if (progArgv == NULL && script == NULL)
812 if (progArgv && ptt == RPM_STRING_TYPE) {
813 argv = alloca(sizeof(*argv));
814 *argv = (const char *) progArgv;
816 argv = (const char **) progArgv;
820 if (fi->h != NULL) /* XXX can't happen */
821 rc = runScript(psm, fi->h, tag2sln(psm->scriptTag), progArgc, argv,
822 script, psm->scriptArg, -1);
825 progArgv = hfd(progArgv, ptt);
826 script = hfd(script, stt);
832 * @todo Trigger on any provides, not just package NVR.
833 * @param psm package state machine data
837 * @param triggersAlreadyRun
840 static rpmRC handleOneTrigger(const rpmpsm psm,
841 Header sourceH, Header triggeredH,
842 int arg2, unsigned char * triggersAlreadyRun)
843 /*@globals rpmGlobalMacroContext, fileSystem, internalState@*/
844 /*@modifies psm, sourceH, triggeredH, *triggersAlreadyRun,
845 rpmGlobalMacroContext, fileSystem, internalState @*/
848 const rpmts ts = psm->ts;
851 HFD_t hfd = (fi->hfd ? fi->hfd : headerFreeData);
852 rpmds trigger = NULL;
853 const char ** triggerScripts;
854 const char ** triggerProgs;
855 int_32 * triggerIndices;
856 const char * sourceName;
861 xx = headerNVR(sourceH, &sourceName, NULL, NULL);
863 trigger = rpmdsInit(rpmdsNew(triggeredH, RPMTAG_TRIGGERNAME, scareMem));
867 (void) rpmdsSetNoPromote(trigger, 1);
869 while ((i = rpmdsNext(trigger)) >= 0) {
870 rpmTagType tit, tst, tpt;
872 int_32 Flags = rpmdsFlags(trigger);
874 if ((Name = rpmdsN(trigger)) == NULL)
875 continue; /* XXX can't happen */
877 if (strcmp(Name, sourceName))
879 if (!(Flags & psm->sense))
883 * XXX Trigger on any provided dependency, not just the package NEVR.
885 if (!rpmdsAnyMatchesDep(sourceH, trigger, 1))
888 if (!( hge(triggeredH, RPMTAG_TRIGGERINDEX, &tit,
889 (void **) &triggerIndices, NULL) &&
890 hge(triggeredH, RPMTAG_TRIGGERSCRIPTS, &tst,
891 (void **) &triggerScripts, NULL) &&
892 hge(triggeredH, RPMTAG_TRIGGERSCRIPTPROG, &tpt,
893 (void **) &triggerProgs, NULL))
900 arg1 = rpmdbCountPackages(rpmtsGetRdb(ts), Name);
902 /* XXX W2DO? fails as "execution of script failed" */
905 arg1 += psm->countCorrection;
906 index = triggerIndices[i];
907 if (triggersAlreadyRun == NULL ||
908 triggersAlreadyRun[index] == 0)
910 rc = runScript(psm, triggeredH, "%trigger", 1,
911 triggerProgs + index, triggerScripts[index],
913 if (triggersAlreadyRun != NULL)
914 triggersAlreadyRun[index] = 1;
919 triggerIndices = hfd(triggerIndices, tit);
920 triggerScripts = hfd(triggerScripts, tst);
921 triggerProgs = hfd(triggerProgs, tpt);
924 * Each target/source header pair can only result in a single
930 trigger = rpmdsFree(trigger);
936 * Run trigger scripts in the database that are fired by this header.
937 * @param psm package state machine data
938 * @return 0 on success
940 static rpmRC runTriggers(rpmpsm psm)
941 /*@globals rpmGlobalMacroContext,
942 fileSystem, internalState @*/
943 /*@modifies psm, rpmGlobalMacroContext,
944 fileSystem, internalState @*/
946 const rpmts ts = psm->ts;
950 const char * N = NULL;
952 if (psm->te) /* XXX can't happen */
954 if (N) /* XXX can't happen */
955 numPackage = rpmdbCountPackages(rpmtsGetRdb(ts), N)
956 + psm->countCorrection;
958 return RPMRC_NOTFOUND;
960 if (fi != NULL && fi->h != NULL) /* XXX can't happen */
962 rpmdbMatchIterator mi;
963 int countCorrection = psm->countCorrection;
965 psm->countCorrection = 0;
966 mi = rpmtsInitIterator(ts, RPMTAG_TRIGGERNAME, N, 0);
967 while((triggeredH = rpmdbNextIterator(mi)) != NULL)
968 rc |= handleOneTrigger(psm, fi->h, triggeredH, numPackage, NULL);
969 mi = rpmdbFreeIterator(mi);
970 psm->countCorrection = countCorrection;
977 * Run triggers from this header that are fired by headers in the database.
978 * @param psm package state machine data
979 * @return 0 on success
981 static rpmRC runImmedTriggers(rpmpsm psm)
982 /*@globals rpmGlobalMacroContext,
983 fileSystem, internalState @*/
984 /*@modifies psm, rpmGlobalMacroContext,
985 fileSystem, internalState @*/
987 const rpmts ts = psm->ts;
990 HFD_t hfd = (fi->hfd ? fi->hfd : headerFreeData);
991 const char ** triggerNames;
993 int_32 * triggerIndices;
995 int numTriggerIndices;
996 unsigned char * triggersRun;
999 if (fi->h == NULL) return rc; /* XXX can't happen */
1001 if (!( hge(fi->h, RPMTAG_TRIGGERNAME, &tnt,
1002 (void **) &triggerNames, &numTriggers) &&
1003 hge(fi->h, RPMTAG_TRIGGERINDEX, &tit,
1004 (void **) &triggerIndices, &numTriggerIndices))
1008 triggersRun = alloca(sizeof(*triggersRun) * numTriggerIndices);
1009 memset(triggersRun, 0, sizeof(*triggersRun) * numTriggerIndices);
1011 { Header sourceH = NULL;
1014 for (i = 0; i < numTriggers; i++) {
1015 rpmdbMatchIterator mi;
1017 if (triggersRun[triggerIndices[i]] != 0) continue;
1019 mi = rpmtsInitIterator(ts, RPMTAG_NAME, triggerNames[i], 0);
1021 while((sourceH = rpmdbNextIterator(mi)) != NULL) {
1022 rc |= handleOneTrigger(psm, sourceH, fi->h,
1023 rpmdbGetIteratorCount(mi),
1027 mi = rpmdbFreeIterator(mi);
1030 triggerIndices = hfd(triggerIndices, tit);
1031 triggerNames = hfd(triggerNames, tnt);
1035 /*@observer@*/ static const char *const pkgStageString(pkgStage a)
1039 case PSM_UNKNOWN: return "unknown";
1041 case PSM_PKGINSTALL: return " install";
1042 case PSM_PKGERASE: return " erase";
1043 case PSM_PKGCOMMIT: return " commit";
1044 case PSM_PKGSAVE: return "repackage";
1046 case PSM_INIT: return "init";
1047 case PSM_PRE: return "pre";
1048 case PSM_PROCESS: return "process";
1049 case PSM_POST: return "post";
1050 case PSM_UNDO: return "undo";
1051 case PSM_FINI: return "fini";
1053 case PSM_CREATE: return "create";
1054 case PSM_NOTIFY: return "notify";
1055 case PSM_DESTROY: return "destroy";
1056 case PSM_COMMIT: return "commit";
1058 case PSM_CHROOT_IN: return "chrootin";
1059 case PSM_CHROOT_OUT: return "chrootout";
1060 case PSM_SCRIPT: return "script";
1061 case PSM_TRIGGERS: return "triggers";
1062 case PSM_IMMED_TRIGGERS: return "immedtriggers";
1064 case PSM_RPMIO_FLAGS: return "rpmioflags";
1066 case PSM_RPMDB_LOAD: return "rpmdbload";
1067 case PSM_RPMDB_ADD: return "rpmdbadd";
1068 case PSM_RPMDB_REMOVE: return "rpmdbremove";
1070 default: return "???";
1075 rpmpsm XrpmpsmUnlink(rpmpsm psm, const char * msg, const char * fn, unsigned ln)
1077 if (psm == NULL) return NULL;
1079 if (_psm_debug && msg != NULL)
1080 fprintf(stderr, "--> psm %p -- %d %s at %s:%u\n", psm, psm->nrefs, msg, fn, ln);
1086 rpmpsm XrpmpsmLink(rpmpsm psm, const char * msg, const char * fn, unsigned ln)
1088 if (psm == NULL) return NULL;
1092 if (_psm_debug && msg != NULL)
1093 fprintf(stderr, "--> psm %p ++ %d %s at %s:%u\n", psm, psm->nrefs, msg, fn, ln);
1096 /*@-refcounttrans@*/ return psm; /*@=refcounttrans@*/
1099 rpmpsm rpmpsmFree(rpmpsm psm)
1101 const char * msg = "rpmpsmFree";
1106 return rpmpsmUnlink(psm, msg);
1109 psm->fi = rpmfiFree(psm->fi);
1111 psm->te = rpmteFree(psm->te);
1115 psm->ts = rpmtsFree(psm->ts);
1117 (void) rpmpsmUnlink(psm, msg);
1119 /*@-refcounttrans -usereleased@*/
1121 memset(psm, 0, sizeof(*psm)); /* XXX trash and burn */
1124 /*@=refcounttrans =usereleased@*/
1130 rpmpsm rpmpsmNew(rpmts ts, rpmte te, rpmfi fi)
1132 const char * msg = "rpmpsmNew";
1133 rpmpsm psm = xcalloc(1, sizeof(*psm));
1135 if (ts) psm->ts = rpmtsLink(ts, msg);
1137 if (te) psm->te = rpmteLink(te, msg);
1139 /*@-assignexpose -temptrans @*/
1140 if (te) psm->te = te;
1141 /*@=assignexpose =temptrans @*/
1143 if (fi) psm->fi = rpmfiLink(fi, msg);
1145 return rpmpsmLink(psm, msg);
1148 static void * rpmpsmThread(void * arg)
1149 /*@globals rpmGlobalMacroContext, fileSystem, internalState @*/
1150 /*@modifies arg, rpmGlobalMacroContext, fileSystem, internalState @*/
1153 /*@-unqualifiedtrans@*/
1154 return ((void *) rpmpsmStage(psm, psm->nstage));
1155 /*@=unqualifiedtrans@*/
1158 static int rpmpsmNext(rpmpsm psm, pkgStage nstage)
1159 /*@globals rpmGlobalMacroContext, fileSystem, internalState @*/
1160 /*@modifies psm, rpmGlobalMacroContext, fileSystem, internalState @*/
1162 psm->nstage = nstage;
1164 return rpmsqJoin( rpmsqThread(rpmpsmThread, psm) );
1165 return rpmpsmStage(psm, psm->nstage);
1169 * @todo Packages w/o files never get a callback, hence don't get displayed
1170 * on install with -v.
1172 /*@-bounds -nullpass@*/ /* FIX: testing null annotation for fi->h */
1173 rpmRC rpmpsmStage(rpmpsm psm, pkgStage stage)
1175 const rpmts ts = psm->ts;
1176 uint_32 tscolor = rpmtsColor(ts);
1178 HGE_t hge = fi->hge;
1179 HFD_t hfd = (fi->hfd ? fi->hfd : headerFreeData);
1189 rpmMessage(RPMMESS_DEBUG, _("%s: %s has %d files, test = %d\n"),
1190 psm->stepName, rpmteNEVR(psm->te),
1191 rpmfiFC(fi), (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST));
1194 * When we run scripts, we pass an argument which is the number of
1195 * versions of this package that will be installed when we are
1198 psm->npkgs_installed = rpmdbCountPackages(rpmtsGetRdb(ts), rpmteN(psm->te));
1199 if (psm->npkgs_installed < 0) {
1204 if (psm->goal == PSM_PKGINSTALL) {
1205 int fc = rpmfiFC(fi);
1207 psm->scriptArg = psm->npkgs_installed + 1;
1209 assert(psm->mi == NULL);
1210 psm->mi = rpmtsInitIterator(ts, RPMTAG_NAME, rpmteN(psm->te), 0);
1211 xx = rpmdbSetIteratorRE(psm->mi, RPMTAG_EPOCH, RPMMIRE_DEFAULT,
1213 xx = rpmdbSetIteratorRE(psm->mi, RPMTAG_VERSION, RPMMIRE_DEFAULT,
1215 xx = rpmdbSetIteratorRE(psm->mi, RPMTAG_RELEASE, RPMMIRE_DEFAULT,
1218 xx = rpmdbSetIteratorRE(psm->mi, RPMTAG_ARCH, RPMMIRE_DEFAULT,
1220 xx = rpmdbSetIteratorRE(psm->mi, RPMTAG_OS, RPMMIRE_DEFAULT,
1224 while ((psm->oh = rpmdbNextIterator(psm->mi)) != NULL) {
1225 fi->record = rpmdbGetIteratorOffset(psm->mi);
1227 /*@loopbreak@*/ break;
1229 psm->mi = rpmdbFreeIterator(psm->mi);
1232 /* XXX lazy alloc here may need to be done elsewhere. */
1233 if (fi->fstates == NULL && fc > 0) {
1234 fi->fstates = xmalloc(sizeof(*fi->fstates) * fc);
1235 memset(fi->fstates, RPMFILE_STATE_NORMAL, fc);
1238 if (rpmtsFlags(ts) & RPMTRANS_FLAG_JUSTDB) break;
1242 * Old format relocateable packages need the entire default
1243 * prefix stripped to form the cpio list, while all other packages
1244 * need the leading / stripped.
1247 xx = hge(fi->h, RPMTAG_DEFAULTPREFIX, NULL, (void **) &p, NULL);
1248 fi->striplen = (xx ? strlen(p) + 1 : 1);
1251 CPIO_MAP_PATH | CPIO_MAP_MODE | CPIO_MAP_UID | CPIO_MAP_GID;
1253 if (headerIsEntry(fi->h, RPMTAG_ORIGBASENAMES))
1254 rpmfiBuildFNames(fi->h, RPMTAG_ORIGBASENAMES, &fi->apath, NULL);
1256 rpmfiBuildFNames(fi->h, RPMTAG_BASENAMES, &fi->apath, NULL);
1258 if (fi->fuser == NULL)
1259 xx = hge(fi->h, RPMTAG_FILEUSERNAME, NULL,
1260 (void **) &fi->fuser, NULL);
1261 if (fi->fgroup == NULL)
1262 xx = hge(fi->h, RPMTAG_FILEGROUPNAME, NULL,
1263 (void **) &fi->fgroup, NULL);
1264 if (fi->fuids == NULL)
1265 fi->fuids = xcalloc(sizeof(*fi->fuids), fc);
1266 if (fi->fgids == NULL)
1267 fi->fgids = xcalloc(sizeof(*fi->fgids), fc);
1270 if (psm->goal == PSM_PKGERASE || psm->goal == PSM_PKGSAVE) {
1271 psm->scriptArg = psm->npkgs_installed - 1;
1273 /* Retrieve installed header. */
1274 rc = rpmpsmNext(psm, PSM_RPMDB_LOAD);
1277 psm->te->h = headerLink(fi->h);
1279 if (psm->goal == PSM_PKGSAVE) {
1280 /* Open output package for writing. */
1281 { const char * bfmt = rpmGetPath("%{_repackage_name_fmt}", NULL);
1282 const char * pkgbn =
1283 headerSprintf(fi->h, bfmt, rpmTagTable, rpmHeaderFormats, NULL);
1286 psm->pkgURL = rpmGenPath("%{?_repackage_root}",
1287 "%{?_repackage_dir}",
1289 pkgbn = _free(pkgbn);
1290 (void) urlPath(psm->pkgURL, &psm->pkgfn);
1291 psm->fd = Fopen(psm->pkgfn, "w.ufdio");
1292 if (psm->fd == NULL || Ferror(psm->fd)) {
1300 if (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST) break;
1302 /* XXX insure that trigger index is opened before entering chroot. */
1304 { static int oneshot = 0;
1307 dbi = dbiOpen(rpmtsGetRdb(ts), RPMTAG_TRIGGERNAME, 0);
1313 /* Change root directory if requested and not already done. */
1314 rc = rpmpsmNext(psm, PSM_CHROOT_IN);
1316 if (psm->goal == PSM_PKGINSTALL) {
1317 psm->scriptTag = RPMTAG_PREIN;
1318 psm->progTag = RPMTAG_PREINPROG;
1320 if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOTRIGGERPREIN)) {
1321 /* XXX FIXME: implement %triggerprein. */
1324 if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOPRE)) {
1325 rc = rpmpsmNext(psm, PSM_SCRIPT);
1326 if (rc != RPMRC_OK) {
1327 rpmError(RPMERR_SCRIPT,
1328 _("%s: %s scriptlet failed (%d), skipping %s\n"),
1329 psm->stepName, tag2sln(psm->scriptTag), rc,
1330 rpmteNEVR(psm->te));
1336 if (psm->goal == PSM_PKGERASE) {
1337 psm->scriptTag = RPMTAG_PREUN;
1338 psm->progTag = RPMTAG_PREUNPROG;
1339 psm->sense = RPMSENSE_TRIGGERUN;
1340 psm->countCorrection = -1;
1342 if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOTRIGGERUN)) {
1343 /* Run triggers in this package other package(s) set off. */
1344 rc = rpmpsmNext(psm, PSM_IMMED_TRIGGERS);
1347 /* Run triggers in other package(s) this package sets off. */
1348 rc = rpmpsmNext(psm, PSM_TRIGGERS);
1352 if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOPREUN))
1353 rc = rpmpsmNext(psm, PSM_SCRIPT);
1355 if (psm->goal == PSM_PKGSAVE) {
1356 int noArchiveSize = 0;
1358 /* Regenerate original header. */
1362 if (headerGetEntry(fi->h, RPMTAG_HEADERIMMUTABLE, &uht, &uh, &uhc)) {
1363 psm->oh = headerCopyLoad(uh);
1366 if (headerGetEntry(fi->h, RPMTAG_HEADERIMAGE, &uht, &uh, &uhc))
1369 int_32 tag, type, count;
1373 /* Load the original header from the blob. */
1374 oh = headerCopyLoad(uh);
1376 /* XXX this is headerCopy w/o headerReload() */
1377 psm->oh = headerNew();
1380 for (hi = headerInitIterator(oh);
1381 headerNextIterator(hi, &tag, &type, &ptr, &count);
1382 ptr = headerFreeData((void *)ptr, type))
1384 if (tag == RPMTAG_ARCHIVESIZE)
1386 if (ptr) (void) headerAddEntry(psm->oh, tag, type, ptr, count);
1388 hi = headerFreeIterator(hi);
1391 oh = headerFree(oh);
1394 break; /* XXX shouldn't ever happen */
1397 /* Retrieve type of payload compression. */
1398 /*@-nullstate@*/ /* FIX: psm->oh may be NULL */
1399 rc = rpmpsmNext(psm, PSM_RPMIO_FLAGS);
1402 /* Write the lead section into the package. */
1405 struct rpmlead lead;
1408 rpmGetArchInfo(NULL, &archnum);
1409 rpmGetOsInfo(NULL, &osnum);
1412 memset(&lead, 0, sizeof(lead));
1413 /* XXX Set package version conditioned on noDirTokens. */
1416 lead.type = RPMLEAD_BINARY;
1417 lead.archnum = archnum;
1419 lead.signature_type = RPMSIGTYPE_HEADERSIG;
1421 strncpy(lead.name, rpmteNEVR(psm->te), sizeof(lead.name));
1423 rc = writeLead(psm->fd, &lead);
1424 if (rc != RPMRC_OK) {
1425 rpmError(RPMERR_NOSPACE, _("Unable to write package: %s\n"),
1426 Fstrerror(psm->fd));
1431 /* Write the signature section into the package. */
1432 /* XXX rpm-4.1 and later has archive size in signature header. */
1433 { Header sigh = headerRegenSigHeader(fi->h, noArchiveSize);
1434 /* Reallocate the signature into one contiguous region. */
1435 sigh = headerReload(sigh, RPMTAG_HEADERSIGNATURES);
1437 rpmError(RPMERR_NOSPACE, _("Unable to reload signature header\n"));
1441 rc = rpmWriteSignature(psm->fd, sigh);
1442 sigh = rpmFreeSignature(sigh);
1446 /* Add remove transaction id to header. */
1447 if (psm->oh != NULL)
1448 { int_32 tid = rpmtsGetTid(ts);
1449 xx = headerAddEntry(psm->oh, RPMTAG_REMOVETID,
1450 RPM_INT32_TYPE, &tid, 1);
1453 /* Write the metadata section into the package. */
1454 rc = headerWrite(psm->fd, psm->oh, HEADER_MAGIC_YES);
1459 if (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST) break;
1461 if (psm->goal == PSM_PKGINSTALL) {
1464 if (rpmtsFlags(ts) & RPMTRANS_FLAG_JUSTDB) break;
1466 /* XXX Synthesize callbacks for packages with no files. */
1467 if (rpmfiFC(fi) <= 0) {
1469 ptr = rpmtsNotify(ts, fi->te, RPMCALLBACK_INST_START, 0, 100);
1470 ptr = rpmtsNotify(ts, fi->te, RPMCALLBACK_INST_PROGRESS, 100, 100);
1474 (void) rpmfiInit(fi, 0);
1475 while ((i = rpmfiNext(fi)) >= 0) {
1481 if (fi->fuser && unameToUid(fi->fuser[i], &uid)) {
1482 rpmMessage(RPMMESS_WARNING,
1483 _("user %s does not exist - using root\n"),
1486 /* XXX this diddles header memory. */
1487 fi->fmodes[i] &= ~S_ISUID; /* turn off the suid bit */
1490 if (fi->fgroup && gnameToGid(fi->fgroup[i], &gid)) {
1491 rpmMessage(RPMMESS_WARNING,
1492 _("group %s does not exist - using root\n"),
1495 /* XXX this diddles header memory. */
1496 fi->fmodes[i] &= ~S_ISGID; /* turn off the sgid bit */
1498 if (fi->fuids) fi->fuids[i] = uid;
1499 if (fi->fgids) fi->fgids[i] = gid;
1502 /* Retrieve type of payload compression. */
1503 rc = rpmpsmNext(psm, PSM_RPMIO_FLAGS);
1505 if (rpmteFd(fi->te) == NULL) { /* XXX can't happen */
1510 /*@-nullpass@*/ /* LCL: fi->fd != NULL here. */
1511 psm->cfd = Fdopen(fdDup(Fileno(rpmteFd(fi->te))), psm->rpmio_flags);
1513 if (psm->cfd == NULL) { /* XXX can't happen */
1518 rc = fsmSetup(fi->fsm, FSM_PKGINSTALL, ts, fi,
1519 psm->cfd, NULL, &psm->failedFile);
1520 if (psm->cfd->stats != NULL) {
1521 FDSTAT_t stats = psm->cfd->stats;
1522 (void) rpmswAdd(&ts->op_uncompress, &stats->ops[FDSTAT_READ]);
1523 (void) rpmswAdd(&ts->op_digest, &stats->ops[FDSTAT_DIGEST]);
1525 xx = fsmTeardown(fi->fsm);
1527 saveerrno = errno; /* XXX FIXME: Fclose with libio destroys errno */
1528 xx = Fclose(psm->cfd);
1531 errno = saveerrno; /* XXX FIXME: Fclose with libio destroys errno */
1535 rc = rpmpsmNext(psm, PSM_COMMIT);
1537 /* XXX make sure progress is closed out */
1538 psm->what = RPMCALLBACK_INST_PROGRESS;
1539 psm->amount = (fi->archiveSize ? fi->archiveSize : 100);
1540 psm->total = psm->amount;
1541 xx = rpmpsmNext(psm, PSM_NOTIFY);
1544 rpmError(RPMERR_CPIO,
1545 _("unpacking of archive failed%s%s: %s\n"),
1546 (psm->failedFile != NULL ? _(" on file ") : ""),
1547 (psm->failedFile != NULL ? psm->failedFile : ""),
1551 /* XXX notify callback on error. */
1552 psm->what = RPMCALLBACK_UNPACK_ERROR;
1555 xx = rpmpsmNext(psm, PSM_NOTIFY);
1560 if (psm->goal == PSM_PKGERASE) {
1561 int fc = rpmfiFC(fi);
1563 if (rpmtsFlags(ts) & RPMTRANS_FLAG_JUSTDB) break;
1564 if (rpmtsFlags(ts) & RPMTRANS_FLAG_APPLYONLY) break;
1567 psm->what = RPMCALLBACK_UNINST_START;
1568 psm->amount = fc; /* XXX W2DO? looks wrong. */
1570 xx = rpmpsmNext(psm, PSM_NOTIFY);
1572 rc = fsmSetup(fi->fsm, FSM_PKGERASE, ts, fi,
1573 NULL, NULL, &psm->failedFile);
1574 xx = fsmTeardown(fi->fsm);
1576 psm->what = RPMCALLBACK_UNINST_STOP;
1577 psm->amount = 0; /* XXX W2DO? looks wrong. */
1579 xx = rpmpsmNext(psm, PSM_NOTIFY);
1582 if (psm->goal == PSM_PKGSAVE) {
1583 fileAction * actions = fi->actions;
1584 fileAction action = fi->action;
1586 fi->action = FA_COPYOUT;
1589 if (psm->fd == NULL) { /* XXX can't happen */
1593 /*@-nullpass@*/ /* FIX: fdDup mey return NULL. */
1594 xx = Fflush(psm->fd);
1595 psm->cfd = Fdopen(fdDup(Fileno(psm->fd)), psm->rpmio_flags);
1597 if (psm->cfd == NULL) { /* XXX can't happen */
1602 rc = fsmSetup(fi->fsm, FSM_PKGBUILD, ts, fi, psm->cfd,
1603 NULL, &psm->failedFile);
1604 if (psm->cfd->stats != NULL) {
1605 FDSTAT_t stats = psm->cfd->stats;
1606 (void) rpmswAdd(&ts->op_uncompress, &stats->ops[FDSTAT_WRITE]);
1607 (void) rpmswAdd(&ts->op_digest, &stats->ops[FDSTAT_DIGEST]);
1609 xx = fsmTeardown(fi->fsm);
1611 saveerrno = errno; /* XXX FIXME: Fclose with libio destroys errno */
1612 xx = Fclose(psm->cfd);
1618 /* XXX make sure progress is closed out */
1619 psm->what = RPMCALLBACK_INST_PROGRESS;
1620 psm->amount = (fi->archiveSize ? fi->archiveSize : 100);
1621 psm->total = psm->amount;
1622 xx = rpmpsmNext(psm, PSM_NOTIFY);
1624 fi->action = action;
1625 fi->actions = actions;
1629 if (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST) break;
1631 if (psm->goal == PSM_PKGINSTALL) {
1632 int_32 installTime = (int_32) time(NULL);
1633 int fc = rpmfiFC(fi);
1635 if (fi->h == NULL) break; /* XXX can't happen */
1636 if (fi->fstates != NULL && fc > 0)
1637 xx = headerAddEntry(fi->h, RPMTAG_FILESTATES, RPM_CHAR_TYPE,
1640 xx = headerAddEntry(fi->h, RPMTAG_INSTALLTIME, RPM_INT32_TYPE,
1643 xx = headerAddEntry(fi->h, RPMTAG_INSTALLCOLOR, RPM_INT32_TYPE,
1647 * If this package has already been installed, remove it from
1648 * the database before adding the new one.
1650 if (fi->record && !(rpmtsFlags(ts) & RPMTRANS_FLAG_APPLYONLY)) {
1651 rc = rpmpsmNext(psm, PSM_RPMDB_REMOVE);
1655 rc = rpmpsmNext(psm, PSM_RPMDB_ADD);
1658 psm->scriptTag = RPMTAG_POSTIN;
1659 psm->progTag = RPMTAG_POSTINPROG;
1660 psm->sense = RPMSENSE_TRIGGERIN;
1661 psm->countCorrection = 0;
1663 if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOPOST)) {
1664 rc = rpmpsmNext(psm, PSM_SCRIPT);
1667 if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOTRIGGERIN)) {
1668 /* Run triggers in other package(s) this package sets off. */
1669 rc = rpmpsmNext(psm, PSM_TRIGGERS);
1672 /* Run triggers in this package other package(s) set off. */
1673 rc = rpmpsmNext(psm, PSM_IMMED_TRIGGERS);
1677 if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_APPLYONLY))
1678 rc = markReplacedFiles(psm);
1681 if (psm->goal == PSM_PKGERASE) {
1683 psm->scriptTag = RPMTAG_POSTUN;
1684 psm->progTag = RPMTAG_POSTUNPROG;
1685 psm->sense = RPMSENSE_TRIGGERPOSTUN;
1686 psm->countCorrection = -1;
1688 if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOPOSTUN)) {
1689 rc = rpmpsmNext(psm, PSM_SCRIPT);
1690 /* XXX WTFO? postun failures don't cause erasure failure. */
1693 if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOTRIGGERPOSTUN)) {
1694 /* Run triggers in other package(s) this package sets off. */
1695 rc = rpmpsmNext(psm, PSM_TRIGGERS);
1699 if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_APPLYONLY))
1700 rc = rpmpsmNext(psm, PSM_RPMDB_REMOVE);
1702 if (psm->goal == PSM_PKGSAVE) {
1705 /* Restore root directory if changed. */
1706 xx = rpmpsmNext(psm, PSM_CHROOT_OUT);
1711 /* Restore root directory if changed. */
1712 xx = rpmpsmNext(psm, PSM_CHROOT_OUT);
1714 if (psm->fd != NULL) {
1715 saveerrno = errno; /* XXX FIXME: Fclose with libio destroys errno */
1716 xx = Fclose(psm->fd);
1723 if (psm->goal == PSM_PKGSAVE) {
1724 if (!rc && ts && ts->notify == NULL) {
1725 rpmMessage(RPMMESS_VERBOSE, _("Wrote: %s\n"),
1726 (psm->pkgURL ? psm->pkgURL : "???"));
1731 if (psm->failedFile)
1732 rpmError(RPMERR_CPIO,
1733 _("%s failed on file %s: %s\n"),
1734 psm->stepName, psm->failedFile, cpioStrerror(rc));
1736 rpmError(RPMERR_CPIO, _("%s failed: %s\n"),
1737 psm->stepName, cpioStrerror(rc));
1739 /* XXX notify callback on error. */
1740 psm->what = RPMCALLBACK_CPIO_ERROR;
1743 /*@-nullstate@*/ /* FIX: psm->fd may be NULL. */
1744 xx = rpmpsmNext(psm, PSM_NOTIFY);
1749 if (psm->goal == PSM_PKGERASE || psm->goal == PSM_PKGSAVE) {
1750 if (psm->te != NULL)
1751 if (psm->te->h != NULL)
1752 psm->te->h = headerFree(psm->te->h);
1754 fi->h = headerFree(fi->h);
1757 psm->oh = headerFree(psm->oh);
1758 psm->pkgURL = _free(psm->pkgURL);
1759 psm->rpmio_flags = _free(psm->rpmio_flags);
1760 psm->failedFile = _free(psm->failedFile);
1762 fi->fgids = _free(fi->fgids);
1763 fi->fuids = _free(fi->fuids);
1764 fi->fgroup = hfd(fi->fgroup, -1);
1765 fi->fuser = hfd(fi->fuser, -1);
1766 fi->apath = _free(fi->apath);
1767 fi->fstates = _free(fi->fstates);
1770 case PSM_PKGINSTALL:
1775 psm->stepName = pkgStageString(stage);
1777 rc = rpmpsmNext(psm, PSM_INIT);
1778 if (!rc) rc = rpmpsmNext(psm, PSM_PRE);
1779 if (!rc) rc = rpmpsmNext(psm, PSM_PROCESS);
1780 if (!rc) rc = rpmpsmNext(psm, PSM_POST);
1781 xx = rpmpsmNext(psm, PSM_FINI);
1790 /*@-nullpass@*/ /* FIX: psm->te may be NULL */
1791 ptr = rpmtsNotify(ts, psm->te, psm->what, psm->amount, psm->total);
1797 if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_PKGCOMMIT)) break;
1798 if (rpmtsFlags(ts) & RPMTRANS_FLAG_APPLYONLY) break;
1800 rc = fsmSetup(fi->fsm, FSM_PKGCOMMIT, ts, fi,
1801 NULL, NULL, &psm->failedFile);
1802 xx = fsmTeardown(fi->fsm);
1806 { const char * rootDir = rpmtsRootDir(ts);
1807 /* Change root directory if requested and not already done. */
1808 if (rootDir != NULL && !rpmtsChrootDone(ts) && !psm->chrootDone) {
1809 static int _loaded = 0;
1812 * This loads all of the name services libraries, in case we
1813 * don't have access to them in the chroot().
1816 (void)getpwnam("root");
1823 rc = chroot(rootDir);
1825 psm->chrootDone = 1;
1826 (void) rpmtsSetChrootDone(ts, 1);
1829 case PSM_CHROOT_OUT:
1830 /* Restore root directory if changed. */
1831 if (psm->chrootDone) {
1832 const char * currDir = rpmtsCurrDir(ts);
1836 psm->chrootDone = 0;
1837 (void) rpmtsSetChrootDone(ts, 0);
1838 if (currDir != NULL) /* XXX can't happen */
1839 xx = chdir(currDir);
1842 case PSM_SCRIPT: /* Run current package scriptlets. */
1843 rc = runInstScript(psm);
1846 /* Run triggers in other package(s) this package sets off. */
1847 rc = runTriggers(psm);
1849 case PSM_IMMED_TRIGGERS:
1850 /* Run triggers in this package other package(s) set off. */
1851 rc = runImmedTriggers(psm);
1854 case PSM_RPMIO_FLAGS:
1855 { const char * payload_compressor = NULL;
1859 if (!hge(fi->h, RPMTAG_PAYLOADCOMPRESSOR, NULL,
1860 (void **) &payload_compressor, NULL))
1861 payload_compressor = "gzip";
1863 psm->rpmio_flags = t = xmalloc(sizeof("w9.gzdio"));
1865 t = stpcpy(t, ((psm->goal == PSM_PKGSAVE) ? "w9" : "r"));
1866 if (!strcmp(payload_compressor, "gzip"))
1867 t = stpcpy(t, ".gzdio");
1868 if (!strcmp(payload_compressor, "bzip2"))
1869 t = stpcpy(t, ".bzdio");
1873 case PSM_RPMDB_LOAD:
1874 assert(psm->mi == NULL);
1875 psm->mi = rpmtsInitIterator(ts, RPMDBI_PACKAGES,
1876 &fi->record, sizeof(fi->record));
1878 fi->h = rpmdbNextIterator(psm->mi);
1880 fi->h = headerLink(fi->h);
1882 psm->mi = rpmdbFreeIterator(psm->mi);
1883 rc = (fi->h != NULL ? RPMRC_OK : RPMRC_FAIL);
1886 if (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST) break;
1887 if (fi->h == NULL) break; /* XXX can't happen */
1888 (void) rpmswEnter(&ts->op_dbadd, 0);
1889 if (!(rpmtsVSFlags(ts) & RPMVSF_NOHDRCHK))
1890 rc = rpmdbAdd(rpmtsGetRdb(ts), rpmtsGetTid(ts), fi->h,
1893 rc = rpmdbAdd(rpmtsGetRdb(ts), rpmtsGetTid(ts), fi->h,
1895 (void) rpmswExit(&ts->op_dbadd, 0);
1897 case PSM_RPMDB_REMOVE:
1898 if (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST) break;
1899 (void) rpmswEnter(&ts->op_dbremove, 0);
1900 rc = rpmdbRemove(rpmtsGetRdb(ts), rpmtsGetTid(ts), fi->record,
1902 (void) rpmswExit(&ts->op_dbremove, 0);
1910 /*@-nullstate@*/ /* FIX: psm->oh and psm->fi->h may be NULL. */
1914 /*@=bounds =nullpass@*/