- Main Page
- Related Pages
- Modules
- Data Structures
- Files

- File List
- Globals

# lib/psm.c

Go to the documentation of this file.

    00001
    00006 #include "system.h"
    00007
    00008 #include <rpmio_internal.h>     /* XXX FDSTAT_READ */
    00009 #include <rpmcb.h>              /* XXX fnpyKey */
    00010 #include <rpmmacro.h>
    00011 #include <rpmurl.h>
    00012 #include <rpmlua.h>
    00013 #include <rpmtag.h>
    00014 #include <rpmlib.h>
    00015
    00016 #include "cpio.h"
    00017 #define _RPMFI_INTERNAL
    00018 #include "fsm.h"                /* XXX CPIO_FOO/FSM_FOO constants */
    00019 #define _RPMSQ_INTERNAL
    00020 #include "psm.h"
    00021
    00022 #define _RPMEVR_INTERNAL
    00023 #include "rpmds.h"
    00024
    00025 #define _RPMTE_INTERNAL
    00026 #include "rpmte.h"
    00027
    00028 #define _RPMTS_INTERNAL         /* XXX ts->notify */
    00029 #include "rpmts.h"
    00030
    00031 #include <pkgio.h>
    00032 #include "misc.h"               /* XXX rpmMkdirPath, makeTempFile, doputenv */
    00033 #include "rpmdb.h"              /* XXX for db_chrootDone */
    00034 #include "signature.h"          /* signature constants */
    00035 #include "debug.h"
    00036
    00037 #define _PSM_DEBUG      0
    00038 /*@unchecked@*/
    00039 int _psm_debug = _PSM_DEBUG;
    00040 /*@unchecked@*/
    00041 int _psm_threads = 0;
    00042
    00043 /*@access FD_t @*/              /* XXX void * arg */
    00044 /*@access Header @*/            /* XXX void * arg */
    00045
    00046 /*@access rpmpsm @*/
    00047
    00048 /*@access rpmfi @*/
    00049 /*@access rpmte @*/     /* XXX rpmInstallSourcePackage */
    00050 /*@access rpmts @*/     /* XXX ts->notify */
    00051
    00052 /*@access rpmluav @*/
    00053
    00054 int rpmVersionCompare(Header first, Header second)
    00055 {
    00056     HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
    00057     const char * one, * two;
    00058     uint32_t Eone, Etwo;
    00059     int rc;
    00060     int xx;
    00061
    00062     he->tag = RPMTAG_EPOCH;
    00063     xx = headerGet(first, he, 0);
    00064     Eone = (xx && he->p.ui32p ? he->p.ui32p[0] : 0);
    00065     he->p.ptr = _free(he->p.ptr);
    00066     he->tag = RPMTAG_EPOCH;
    00067     xx = headerGet(second, he, 0);
    00068     Etwo = (xx && he->p.ui32p ? he->p.ui32p[0] : 0);
    00069     he->p.ptr = _free(he->p.ptr);
    00070
    00071     if (Eone < Etwo)
    00072         return -1;
    00073     else if (Eone > Etwo)
    00074         return 1;
    00075
    00076     he->tag = RPMTAG_VERSION;
    00077     xx = headerGet(first, he, 0);
    00078     one = he->p.str;
    00079     he->tag = RPMTAG_VERSION;
    00080     xx = headerGet(second, he, 0);
    00081     two = he->p.str;
    00082     rc = rpmvercmp(one, two);
    00083     one = _free(one);
    00084     two = _free(two);
    00085     if (rc)
    00086         return rc;
    00087
    00088     he->tag = RPMTAG_RELEASE;
    00089     xx = headerGet(first, he, 0);
    00090     one = he->p.str;
    00091     he->tag = RPMTAG_RELEASE;
    00092     xx = headerGet(second, he, 0);
    00093     two = he->p.str;
    00094     rc = rpmvercmp(one, two);
    00095     one = _free(one);
    00096     two = _free(two);
    00097
    00098     return rc;
    00099 }
    00100
    00106 static rpmRC markReplacedFiles(const rpmpsm psm)
    00107         /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
    00108         /*@modifies psm, rpmGlobalMacroContext, fileSystem, internalState @*/
    00109 {
    00110     HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
    00111     const rpmts ts = psm->ts;
    00112     rpmte te = psm->te;
    00113     rpmfi fi = psm->fi;
    00114     sharedFileInfo replaced = (te ? te->replaced : NULL);
    00115     sharedFileInfo sfi;
    00116     rpmdbMatchIterator mi;
    00117     Header h;
    00118     int * offsets;
    00119     unsigned int prev;
    00120     int num;
    00121     int xx;
    00122
    00123     if (!(rpmfiFC(fi) > 0 && replaced != NULL))
    00124         return RPMRC_OK;
    00125
    00126     num = prev = 0;
    00127     for (sfi = replaced; sfi->otherPkg; sfi++) {
    00128         if (prev && prev == sfi->otherPkg)
    00129             continue;
    00130         prev = sfi->otherPkg;
    00131         num++;
    00132     }
    00133     if (num == 0)
    00134         return RPMRC_OK;
    00135
    00136     offsets = alloca(num * sizeof(*offsets));
    00137     offsets[0] = 0;
    00138     num = prev = 0;
    00139     for (sfi = replaced; sfi->otherPkg; sfi++) {
    00140         if (prev && prev == sfi->otherPkg)
    00141             continue;
    00142         prev = sfi->otherPkg;
    00143         offsets[num++] = sfi->otherPkg;
    00144     }
    00145
    00146     mi = rpmtsInitIterator(ts, RPMDBI_PACKAGES, NULL, 0);
    00147     xx = rpmdbAppendIterator(mi, offsets, num);
    00148     xx = rpmdbSetIteratorRewrite(mi, 1);
    00149
    00150     sfi = replaced;
    00151     while ((h = rpmdbNextIterator(mi)) != NULL) {
    00152         int modified;
    00153
    00154         modified = 0;
    00155
    00156         /* XXX FIXME: not correct yet, but headerGetEntry needs to die now! */
    00157         he->tag = RPMTAG_FILESTATES;
    00158         xx = headerGet(h, he, 0);
    00159         if (!xx)
    00160             continue;
    00161
    00162         prev = rpmdbGetIteratorOffset(mi);
    00163         num = 0;
    00164         while (sfi->otherPkg && sfi->otherPkg == prev) {
    00165 assert(sfi->otherFileNum < he->c);
    00166             if (he->p.ui8p[sfi->otherFileNum] != RPMFILE_STATE_REPLACED) {
    00167                 he->p.ui8p[sfi->otherFileNum] = RPMFILE_STATE_REPLACED;
    00168                 if (modified == 0) {
    00169                     /* Modified header will be rewritten. */
    00170                     modified = 1;
    00171                     xx = rpmdbSetIteratorModified(mi, modified);
    00172                 }
    00173                 num++;
    00174             }
    00175             sfi++;
    00176         }
    00177         he->p.ptr = _free(he->p.ptr);
    00178     }
    00179     mi = rpmdbFreeIterator(mi);
    00180
    00181     return RPMRC_OK;
    00182 }
    00183
    00184 rpmRC rpmInstallSourcePackage(rpmts ts, void * _fd,
    00185                 const char ** specFilePtr, const char ** cookie)
    00186 {
    00187     HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
    00188     FD_t fd = _fd;
    00189     int scareMem = 0;
    00190     rpmfi fi = NULL;
    00191     const char * _sourcedir = NULL;
    00192     const char * _specdir = NULL;
    00193     const char * specFile = NULL;
    00194     Header h = NULL;
    00195     struct rpmpsm_s psmbuf;
    00196     rpmpsm psm = &psmbuf;
    00197     int isSource;
    00198     rpmRC rpmrc;
    00199     int xx;
    00200     int i;
    00201
    00202     memset(psm, 0, sizeof(*psm));
    00203     psm->ts = rpmtsLink(ts, "InstallSourcePackage");
    00204
    00205     rpmrc = rpmReadPackageFile(ts, fd, "InstallSourcePackage", &h);
    00206     switch (rpmrc) {
    00207     case RPMRC_NOTTRUSTED:
    00208     case RPMRC_NOKEY:
    00209     case RPMRC_OK:
    00210         break;
    00211     default:
    00212         goto exit;
    00213         /*@notreached@*/ break;
    00214     }
    00215     if (h == NULL)
    00216         goto exit;
    00217
    00218     rpmrc = RPMRC_OK;
    00219
    00220     isSource =
    00221         (headerIsEntry(h, RPMTAG_SOURCERPM) == 0 &&
    00222          headerIsEntry(h, RPMTAG_ARCH) != 0);
    00223
    00224     if (!isSource) {
    00225         rpmlog(RPMLOG_ERR, _("source package expected, binary found\n"));
    00226         rpmrc = RPMRC_FAIL;
    00227         goto exit;
    00228     }
    00229
    00230     (void) rpmtsAddInstallElement(ts, h, NULL, 0, NULL);
    00231
    00232     fi = rpmfiNew(ts, h, RPMTAG_BASENAMES, scareMem);
    00233     fi->h = headerLink(h);
    00234     h = headerFree(h);
    00235
    00236     if (fi == NULL) {   /* XXX can't happen */
    00237         rpmrc = RPMRC_FAIL;
    00238         goto exit;
    00239     }
    00240
    00241 /*@-onlytrans@*/        /* FIX: te reference */
    00242     fi->te = rpmtsElement(ts, 0);
    00243 /*@=onlytrans@*/
    00244     if (fi->te == NULL) {       /* XXX can't happen */
    00245         rpmrc = RPMRC_FAIL;
    00246         goto exit;
    00247     }
    00248
    00249 assert(fi->h != NULL);
    00250 assert(fi->te->h == NULL);      /* XXX headerFree side effect */
    00251     (void) rpmteSetHeader(fi->te, fi->h);
    00252     fi->te->fd = fdLink(fd, "installSourcePackage");
    00253
    00254     (void) headerMacrosLoad(fi->h);
    00255
    00256     psm->fi = rpmfiLink(fi, NULL);
    00257     /*@-assignexpose -usereleased @*/
    00258     psm->te = fi->te;
    00259     /*@=assignexpose =usereleased @*/
    00260
    00261     if (cookie) {
    00262         *cookie = NULL;
    00263         he->tag = RPMTAG_COOKIE;
    00264         xx = headerGet(fi->h, he, 0);
    00265         *cookie = he->p.str;
    00266     }
    00267
    00268     /* XXX FIXME: don't do per-file mapping, force global flags. */
    00269     fi->fmapflags = _free(fi->fmapflags);
    00270     fi->mapflags = CPIO_MAP_PATH | CPIO_MAP_MODE | CPIO_MAP_UID | CPIO_MAP_GID;
    00271
    00272     fi->uid = getuid();
    00273     fi->gid = getgid();
    00274 #if defined(RPM_VENDOR_OPENPKG) /* switch-from-susr-to-musr-on-srpm-install */
    00275     /* If running as the OpenPKG "susr", do not unpack source RPM
    00276        packages with "susr" file ownerships as the OpenPKG Set-UID
    00277        wrapper switches from "musr" to "susr" on "openpkg rpm -Uvh
    00278        *.src.rpm". As a result the installed files could be never
    00279        removed again by "musr". It is more consistent to always unpack
    00280        as "musr" if possible. */
    00281     if (fi->uid == 0) {
    00282         char *muid_str;
    00283         char *mgid_str;
    00284         uid_t muid;
    00285         gid_t mgid;
    00286         if ((muid_str = rpmExpand("%{l_muid}", NULL)) != NULL)
    00287             if ((muid = (uid_t)strtol(muid_str, (char **)NULL, 10)) > 0)
    00288                 fi->uid = muid;
    00289         if ((mgid_str = rpmExpand("%{l_mgid}", NULL)) != NULL)
    00290             if ((mgid = (gid_t)strtol(mgid_str, (char **)NULL, 10)) > 0)
    00291                 fi->gid = mgid;
    00292     }
    00293 #endif
    00294     fi->astriplen = 0;
    00295     fi->striplen = 0;
    00296
    00297     for (i = 0; i < fi->fc; i++)
    00298         fi->actions[i] = FA_CREATE;
    00299
    00300     i = fi->fc;
    00301
    00302     if (fi->h != NULL) {        /* XXX can't happen */
    00303         he->tag = RPMTAG_FILEPATHS;
    00304         xx = headerGet(fi->h, he, 0);
    00305         fi->apath = he->p.argv;
    00306
    00307         if (headerIsEntry(fi->h, RPMTAG_COOKIE))
    00308             for (i = 0; i < fi->fc; i++)
    00309                 if (fi->fflags[i] & RPMFILE_SPECFILE) break;
    00310     }
    00311
    00312     if (i == fi->fc) {
    00313         /* Find the spec file by name. */
    00314         for (i = 0; i < fi->fc; i++) {
    00315             const char * t = fi->apath[i];
    00316             t += strlen(fi->apath[i]) - 5;
    00317             if (!strcmp(t, ".spec")) break;
    00318         }
    00319     }
    00320
    00321     _sourcedir = rpmGenPath(rpmtsRootDir(ts), "%{_sourcedir}", "");
    00322     rpmrc = rpmMkdirPath(_sourcedir, "sourcedir");
    00323     if (rpmrc) {
    00324         rpmrc = RPMRC_FAIL;
    00325         goto exit;
    00326     }
    00327     if (Access(_sourcedir, W_OK)) {
    00328         rpmlog(RPMLOG_ERR, _("cannot write to %%%s %s\n"),
    00329                 "_sourcedir", _sourcedir);
    00330         rpmrc = RPMRC_FAIL;
    00331         goto exit;
    00332     }
    00333 #if defined(RPM_VENDOR_OPENPKG) /* switch-from-susr-to-musr-on-srpm-install */
    00334     chown(_sourcedir, fi->uid, fi->gid);
    00335 #endif
    00336
    00337     _specdir = rpmGenPath(rpmtsRootDir(ts), "%{_specdir}", "");
    00338     rpmrc = rpmMkdirPath(_specdir, "specdir");
    00339     if (rpmrc) {
    00340         rpmrc = RPMRC_FAIL;
    00341         goto exit;
    00342     }
    00343     if (Access(_specdir, W_OK)) {
    00344         rpmlog(RPMLOG_ERR, _("cannot write to %%%s %s\n"),
    00345                 "_specdir", _specdir);
    00346         rpmrc = RPMRC_FAIL;
    00347         goto exit;
    00348     }
    00349 #if defined(RPM_VENDOR_OPENPKG) /* switch-from-susr-to-musr-on-srpm-install */
    00350     chown(_specdir, fi->uid, fi->gid);
    00351 #endif
    00352
    00353     /* Build dnl/dil with {_sourcedir, _specdir} as values. */
    00354     if (i < fi->fc) {
    00355         size_t speclen = strlen(_specdir) + 2;
    00356         size_t sourcelen = strlen(_sourcedir) + 2;
    00357         char * t;
    00358
    00359 /*@i@*/ fi->dnl = _free(fi->dnl);
    00360
    00361         fi->dc = 2;
    00362         fi->dnl = xmalloc(fi->dc * sizeof(*fi->dnl)
    00363                         + fi->fc * sizeof(*fi->dil)
    00364                         + speclen + sourcelen);
    00365         /*@-dependenttrans@*/
    00366         fi->dil = (unsigned int *)(fi->dnl + fi->dc);
    00367         /*@=dependenttrans@*/
    00368         memset(fi->dil, 0, fi->fc * sizeof(*fi->dil));
    00369         fi->dil[i] = 1;
    00370         /*@-dependenttrans@*/
    00371         fi->dnl[0] = t = (char *)(fi->dil + fi->fc);
    00372         fi->dnl[1] = t = stpcpy( stpcpy(t, _sourcedir), "/") + 1;
    00373         /*@=dependenttrans@*/
    00374         (void) stpcpy( stpcpy(t, _specdir), "/");
    00375
    00376         t = xmalloc(speclen + strlen(fi->bnl[i]) + 1);
    00377         (void) stpcpy( stpcpy( stpcpy(t, _specdir), "/"), fi->bnl[i]);
    00378         specFile = t;
    00379     } else {
    00380         rpmlog(RPMLOG_ERR, _("source package contains no .spec file\n"));
    00381         rpmrc = RPMRC_FAIL;
    00382         goto exit;
    00383     }
    00384
    00385     psm->goal = PSM_PKGINSTALL;
    00386
    00387     /*@-compmempass@*/  /* FIX: psm->fi->dnl should be owned. */
    00388     rpmrc = rpmpsmStage(psm, PSM_PROCESS);
    00389
    00390     (void) rpmpsmStage(psm, PSM_FINI);
    00391     /*@=compmempass@*/
    00392
    00393     if (rpmrc) rpmrc = RPMRC_FAIL;
    00394
    00395 exit:
    00396     if (specFilePtr && specFile && rpmrc == RPMRC_OK)
    00397         *specFilePtr = specFile;
    00398     else
    00399         specFile = _free(specFile);
    00400
    00401     _specdir = _free(_specdir);
    00402     _sourcedir = _free(_sourcedir);
    00403
    00404     psm->fi = rpmfiFree(psm->fi);
    00405     psm->te = NULL;
    00406
    00407     if (h != NULL) h = headerFree(h);
    00408
    00409     if (fi != NULL) {
    00410         (void) rpmteSetHeader(fi->te, NULL);
    00411         if (fi->te->fd != NULL)
    00412             (void) Fclose(fi->te->fd);
    00413         fi->te->fd = NULL;
    00414         fi->te = NULL;
    00415 #if 0
    00416         fi = rpmfiFree(fi);
    00417 #endif
    00418     }
    00419
    00420     /* XXX nuke the added package(s). */
    00421     rpmtsClean(ts);
    00422
    00423     psm->ts = rpmtsFree(psm->ts);
    00424
    00425     return rpmrc;
    00426 }
    00427
    00428 /*@observer@*/ /*@unchecked@*/
    00429 static char * SCRIPT_PATH = "PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin";
    00430
    00436 static /*@observer@*/ const char * tag2sln(int tag)
    00437         /*@*/
    00438 {
    00439     switch (tag) {
    00440     case RPMTAG_PRETRANS:       return "%pretrans";
    00441     case RPMTAG_TRIGGERPREIN:   return "%triggerprein";
    00442     case RPMTAG_PREIN:          return "%pre";
    00443     case RPMTAG_POSTIN:         return "%post";
    00444     case RPMTAG_TRIGGERIN:      return "%triggerin";
    00445     case RPMTAG_TRIGGERUN:      return "%triggerun";
    00446     case RPMTAG_PREUN:          return "%preun";
    00447     case RPMTAG_POSTUN:         return "%postun";
    00448     case RPMTAG_POSTTRANS:      return "%posttrans";
    00449     case RPMTAG_TRIGGERPOSTUN:  return "%triggerpostun";
    00450     case RPMTAG_VERIFYSCRIPT:   return "%verify";
    00451     case RPMTAG_SANITYCHECK:    return "%sanitycheck";
    00452     }
    00453     return "%unknownscript";
    00454 }
    00455
    00461 static rpmScriptID tag2slx(int tag)
    00462         /*@*/
    00463 {
    00464     switch (tag) {
    00465     case RPMTAG_PRETRANS:       return RPMSCRIPT_PRETRANS;
    00466     case RPMTAG_TRIGGERPREIN:   return RPMSCRIPT_TRIGGERPREIN;
    00467     case RPMTAG_PREIN:          return RPMSCRIPT_PREIN;
    00468     case RPMTAG_POSTIN:         return RPMSCRIPT_POSTIN;
    00469     case RPMTAG_TRIGGERIN:      return RPMSCRIPT_TRIGGERIN;
    00470     case RPMTAG_TRIGGERUN:      return RPMSCRIPT_TRIGGERUN;
    00471     case RPMTAG_PREUN:          return RPMSCRIPT_PREUN;
    00472     case RPMTAG_POSTUN:         return RPMSCRIPT_POSTUN;
    00473     case RPMTAG_POSTTRANS:      return RPMSCRIPT_POSTTRANS;
    00474     case RPMTAG_TRIGGERPOSTUN:  return RPMSCRIPT_TRIGGERPOSTUN;
    00475     case RPMTAG_VERIFYSCRIPT:   return RPMSCRIPT_VERIFY;
    00476     case RPMTAG_SANITYCHECK:    return RPMSCRIPT_SANITYCHECK;
    00477     }
    00478     return RPMSCRIPT_UNKNOWN;
    00479 }
    00480
    00486 static pid_t psmWait(rpmpsm psm)
    00487         /*@globals fileSystem, internalState @*/
    00488         /*@modifies psm, fileSystem, internalState @*/
    00489 {
    00490     const rpmts ts = psm->ts;
    00491     rpmtime_t msecs;
    00492
    00493     (void) rpmsqWait(&psm->sq);
    00494     msecs = psm->sq.op.usecs/1000;
    00495     (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_SCRIPTLETS), &psm->sq.op);
    00496
    00497     rpmlog(RPMLOG_DEBUG,
    00498         D_("%s: waitpid(%d) rc %d status %x secs %u.%03u\n"),
    00499         psm->stepName, (unsigned)psm->sq.child,
    00500         (unsigned)psm->sq.reaped, psm->sq.status,
    00501         (unsigned)msecs/1000, (unsigned)msecs%1000);
    00502
    00503     if (psm->sstates != NULL)
    00504     {   int * ssp = psm->sstates + tag2slx(psm->scriptTag);
    00505         *ssp &= ~0xffff;
    00506         *ssp |= (psm->sq.status & 0xffff);
    00507         *ssp |= RPMSCRIPT_STATE_REAPED;
    00508     }
    00509
    00510     return psm->sq.reaped;
    00511 }
    00512
    00513 #ifdef WITH_LUA
    00514
    00517 static rpmRC runLuaScript(rpmpsm psm, Header h, const char *sln,
    00518                    int progArgc, const char **progArgv,
    00519                    const char *script, int arg1, int arg2)
    00520         /*@globals h_errno, fileSystem, internalState @*/
    00521         /*@modifies psm, fileSystem, internalState @*/
    00522 {
    00523     HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
    00524     const rpmts ts = psm->ts;
    00525     int rootFdno = -1;
    00526     rpmRC rc = RPMRC_OK;
    00527     int i;
    00528     int xx;
    00529     rpmlua lua = NULL; /* Global state. */
    00530     rpmluav var;
    00531     int * ssp = NULL;
    00532
    00533     if (psm->sstates != NULL)
    00534         ssp = psm->sstates + tag2slx(psm->scriptTag);
    00535     if (ssp != NULL)
    00536         *ssp |= (RPMSCRIPT_STATE_LUA|RPMSCRIPT_STATE_EXEC);
    00537
    00538     he->tag = RPMTAG_NVRA;
    00539     xx = headerGet(h, he, 0);
    00540 assert(he->p.str != NULL);
    00541
    00542     /* Save the current working directory. */
    00543 /*@-nullpass@*/
    00544     rootFdno = open(".", O_RDONLY, 0);
    00545 /*@=nullpass@*/
    00546
    00547     /* Get into the chroot. */
    00548     if (!rpmtsChrootDone(ts)) {
    00549         const char *rootDir = rpmtsRootDir(ts);
    00550         /*@-modobserver @*/
    00551         if (rootDir != NULL && strcmp(rootDir, "/") && *rootDir == '/') {
    00552             xx = Chroot(rootDir);
    00553         /*@=modobserver @*/
    00554             xx = rpmtsSetChrootDone(ts, 1);
    00555         }
    00556     }
    00557
    00558     /* All lua scripts run with CWD == "/". */
    00559     xx = Chdir("/");
    00560
    00561     /* Create arg variable */
    00562     rpmluaPushTable(lua, "arg");
    00563     var = rpmluavNew();
    00564     rpmluavSetListMode(var, 1);
    00565 /*@+relaxtypes@*/
    00566     if (progArgv) {
    00567         for (i = 0; i < progArgc && progArgv[i]; i++) {
    00568             rpmluavSetValue(var, RPMLUAV_STRING, progArgv[i]);
    00569             rpmluaSetVar(lua, var);
    00570         }
    00571     }
    00572     if (arg1 >= 0) {
    00573         rpmluavSetValueNum(var, arg1);
    00574         rpmluaSetVar(lua, var);
    00575     }
    00576     if (arg2 >= 0) {
    00577         rpmluavSetValueNum(var, arg2);
    00578         rpmluaSetVar(lua, var);
    00579     }
    00580 /*@=relaxtypes@*/
    00581 /*@-moduncon@*/
    00582     var = rpmluavFree(var);
    00583 /*@=moduncon@*/
    00584     rpmluaPop(lua);
    00585
    00586     {
    00587         char buf[BUFSIZ];
    00588         xx = snprintf(buf, BUFSIZ, "%s(%s)", sln, he->p.str);
    00589         xx = rpmluaRunScript(lua, script, buf);
    00590         if (xx == -1) {
    00591             void * ptr = rpmtsNotify(ts, psm->te, RPMCALLBACK_SCRIPT_ERROR,
    00592                                  psm->scriptTag, 1);
    00593             ptr = ptr;  /* XXX keep gcc happy. */
    00594             rc = RPMRC_FAIL;
    00595         }
    00596         if (ssp != NULL) {
    00597             *ssp &= ~0xffff;
    00598             *ssp |= (xx & 0xffff);
    00599             *ssp |= RPMSCRIPT_STATE_REAPED;
    00600         }
    00601     }
    00602
    00603     rpmluaDelVar(lua, "arg");
    00604
    00605     /* Get out of chroot. */
    00606     if (rpmtsChrootDone(ts)) {
    00607         const char *rootDir = rpmtsRootDir(ts);
    00608         xx = fchdir(rootFdno);
    00609         /*@-modobserver@*/
    00610         if (rootDir != NULL && strcmp(rootDir, "/") && *rootDir == '/') {
    00611             xx = Chroot(".");
    00612         /*@=modobserver@*/
    00613             xx = rpmtsSetChrootDone(ts, 0);
    00614         }
    00615     } else
    00616         xx = fchdir(rootFdno);
    00617
    00618     xx = close(rootFdno);
    00619     he->p.ptr = _free(he->p.ptr);
    00620
    00621     return rc;
    00622 }
    00623 #endif
    00624
    00627 /*@unchecked@*/
    00628 static int ldconfig_done = 0;
    00629
    00630 /*@unchecked@*/ /*@observer@*/ /*@null@*/
    00631 static const char * ldconfig_path = "/sbin/ldconfig";
    00632
    00651 static rpmRC runScript(rpmpsm psm, Header h, const char * sln,
    00652                 int progArgc, const char ** progArgv,
    00653                 const char * script, int arg1, int arg2)
    00654         /*@globals ldconfig_done, rpmGlobalMacroContext, h_errno,
    00655                 fileSystem, internalState@*/
    00656         /*@modifies psm, ldconfig_done, rpmGlobalMacroContext,
    00657                 fileSystem, internalState @*/
    00658 {
    00659     HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
    00660     const rpmts ts = psm->ts;
    00661     const char ** argv = NULL;
    00662     int argc = 0;
    00663     const char ** prefixes = NULL;
    00664     int numPrefixes;
    00665     size_t maxPrefixLength;
    00666     size_t len;
    00667     char * prefixBuf = NULL;
    00668     const char * fn = NULL;
    00669     FD_t scriptFd;
    00670     FD_t out;
    00671     rpmRC rc = RPMRC_FAIL;      /* assume failure */
    00672     const char * NVRA;
    00673     const char * body = NULL;
    00674     int * ssp = NULL;
    00675     int xx;
    00676     int i;
    00677
    00678     if (psm->sstates != NULL)
    00679         ssp = psm->sstates + tag2slx(psm->scriptTag);
    00680     if (ssp != NULL)
    00681         *ssp = RPMSCRIPT_STATE_UNKNOWN;
    00682
    00683     if (progArgv == NULL && script == NULL)
    00684         return RPMRC_OK;
    00685
    00686     /* Macro expand all scriptlets. */
    00687     body = rpmExpand(script, NULL);
    00688
    00689     he->tag = RPMTAG_NVRA;
    00690     xx = headerGet(h, he, 0);
    00691 assert(he->p.str != NULL);
    00692     NVRA = he->p.str;
    00693
    00694     if (progArgv && strcmp(progArgv[0], "<lua>") == 0) {
    00695 #ifdef WITH_LUA
    00696         rpmlog(RPMLOG_DEBUG,
    00697                 D_("%s: %s(%s) running <lua> scriptlet.\n"),
    00698                 psm->stepName, tag2sln(psm->scriptTag), NVRA);
    00699         rc = runLuaScript(psm, h, sln, progArgc, progArgv,
    00700                             body, arg1, arg2);
    00701 #endif
    00702         goto exit;
    00703     }
    00704
    00705     psm->sq.reaper = 1;
    00706
    00707     /*
    00708      * If a successor node, and ldconfig was just run, don't bother.
    00709      */
    00710     if (ldconfig_path && progArgv != NULL && psm->unorderedSuccessor) {
    00711         if (ldconfig_done && !strcmp(progArgv[0], ldconfig_path)) {
    00712             rpmlog(RPMLOG_DEBUG,
    00713                 D_("%s: %s(%s) skipping redundant \"%s\".\n"),
    00714                 psm->stepName, tag2sln(psm->scriptTag), NVRA,
    00715                 progArgv[0]);
    00716             rc = RPMRC_OK;
    00717             goto exit;
    00718         }
    00719     }
    00720
    00721     rpmlog(RPMLOG_DEBUG,
    00722                 D_("%s: %s(%s) %ssynchronous scriptlet start\n"),
    00723                 psm->stepName, tag2sln(psm->scriptTag), NVRA,
    00724                 (psm->unorderedSuccessor ? "a" : ""));
    00725
    00726     if (!progArgv) {
    00727         argv = alloca(5 * sizeof(*argv));
    00728         argv[0] = "/bin/sh";
    00729         argc = 1;
    00730         ldconfig_done = 0;
    00731     } else {
    00732         argv = alloca((progArgc + 4) * sizeof(*argv));
    00733         memcpy(argv, progArgv, progArgc * sizeof(*argv));
    00734         argc = progArgc;
    00735         ldconfig_done = (ldconfig_path && !strcmp(argv[0], ldconfig_path)
    00736                 ? 1 : 0);
    00737     }
    00738
    00739     he->tag = RPMTAG_INSTPREFIXES;
    00740     xx = headerGet(h, he, 0);
    00741     prefixes = he->p.argv;
    00742     numPrefixes = he->c;
    00743     if (!xx) {
    00744         he->p.ptr = _free(he->p.ptr);
    00745         he->tag = RPMTAG_INSTALLPREFIX;
    00746         xx = headerGet(h, he, 0);
    00747         if (xx) {
    00748             char * t;
    00749             prefixes = xmalloc(sizeof(*prefixes) + strlen(he->p.argv[0]) + 1);
    00750             prefixes[0] = t = (char *) &prefixes[1];
    00751             t = stpcpy(t, he->p.argv[0]);
    00752             *t = '\0';
    00753             he->p.ptr = _free(he->p.ptr);
    00754             numPrefixes = 1;
    00755         } else {
    00756             prefixes = NULL;
    00757             numPrefixes = 0;
    00758         }
    00759     }
    00760
    00761     maxPrefixLength = 0;
    00762     if (prefixes != NULL)
    00763     for (i = 0; i < numPrefixes; i++) {
    00764         len = strlen(prefixes[i]);
    00765         if (len > maxPrefixLength) maxPrefixLength = len;
    00766     }
    00767     prefixBuf = alloca(maxPrefixLength + 50);
    00768
    00769     if (script) {
    00770         const char * rootDir = rpmtsRootDir(ts);
    00771         FD_t fd;
    00772
    00773         if (rpmTempFile((!rpmtsChrootDone(ts) ? rootDir : "/"), &fn, &fd))
    00774             goto exit;
    00775
    00776         if (rpmIsDebug() &&
    00777             (!strcmp(argv[0], "/bin/sh") || !strcmp(argv[0], "/bin/bash")))
    00778         {
    00779             static const char set_x[] = "set -x\n";
    00780             xx = Fwrite(set_x, sizeof(set_x[0]), sizeof(set_x)-1, fd);
    00781         }
    00782
    00783         if (ldconfig_path && strstr(body, ldconfig_path) != NULL)
    00784             ldconfig_done = 1;
    00785
    00786         xx = Fwrite(body, sizeof(body[0]), strlen(body), fd);
    00787         xx = Fclose(fd);
    00788
    00789         {   const char * sn = fn;
    00790             if (!rpmtsChrootDone(ts) && rootDir != NULL &&
    00791                 !(rootDir[0] == '/' && rootDir[1] == '\0'))
    00792             {
    00793                 sn += strlen(rootDir)-1;
    00794             }
    00795             argv[argc++] = sn;
    00796         }
    00797
    00798         if (arg1 >= 0) {
    00799             char *av = alloca(20);
    00800             sprintf(av, "%d", arg1);
    00801             argv[argc++] = av;
    00802         }
    00803         if (arg2 >= 0) {
    00804             char *av = alloca(20);
    00805             sprintf(av, "%d", arg2);
    00806             argv[argc++] = av;
    00807         }
    00808     }
    00809
    00810     argv[argc] = NULL;
    00811
    00812     scriptFd = rpmtsScriptFd(ts);
    00813     if (scriptFd != NULL) {
    00814         if (rpmIsVerbose()) {
    00815             out = fdDup(Fileno(scriptFd));
    00816         } else {
    00817             out = Fopen("/dev/null", "w.fdio");
    00818             if (Ferror(out)) {
    00819                 out = fdDup(Fileno(scriptFd));
    00820             }
    00821         }
    00822     } else {
    00823         out = fdDup(STDOUT_FILENO);
    00824     }
    00825     if (out == NULL)    /* XXX can't happen */
    00826         goto exit;
    00827
    00828     xx = rpmsqFork(&psm->sq);
    00829     if (psm->sq.child == 0) {
    00830         int pipes[2];
    00831         int flag;
    00832         int fdno;
    00833
    00834         pipes[0] = pipes[1] = 0;
    00835         /* Make stdin inaccessible */
    00836         xx = pipe(pipes);
    00837         xx = close(pipes[1]);
    00838         xx = dup2(pipes[0], STDIN_FILENO);
    00839         xx = close(pipes[0]);
    00840
    00841         /* XXX Force FD_CLOEXEC on 1st 100 inherited fdno's. */
    00842         for (fdno = 3; fdno < 100; fdno++) {
    00843             flag = fcntl(fdno, F_GETFD);
    00844             if (flag == -1 || (flag & FD_CLOEXEC))
    00845                 continue;
    00846             rpmlog(RPMLOG_DEBUG,
    00847                         D_("%s: %s(%s)\tfdno(%d) missing FD_CLOEXEC\n"),
    00848                         psm->stepName, sln, NVRA,
    00849                         fdno);
    00850             xx = fcntl(fdno, F_SETFD, FD_CLOEXEC);
    00851             /* XXX W2DO? debug msg for inheirited fdno w/o FD_CLOEXEC */
    00852         }
    00853
    00854         if (scriptFd != NULL) {
    00855             int sfdno = Fileno(scriptFd);
    00856             int ofdno = Fileno(out);
    00857             if (sfdno != STDERR_FILENO)
    00858                 xx = dup2(sfdno, STDERR_FILENO);
    00859             if (ofdno != STDOUT_FILENO)
    00860                 xx = dup2(ofdno, STDOUT_FILENO);
    00861             /* make sure we don't close stdin/stderr/stdout by mistake! */
    00862             if (ofdno > STDERR_FILENO && ofdno != sfdno)
    00863                 xx = Fclose (out);
    00864             if (sfdno > STDERR_FILENO && ofdno != sfdno)
    00865                 xx = Fclose (scriptFd);
    00866         }
    00867
    00868         {   const char *ipath = rpmExpand("PATH=%{_install_script_path}", NULL);
    00869             const char *path = SCRIPT_PATH;
    00870
    00871             if (ipath && ipath[5] != '%')
    00872                 path = ipath;
    00873
    00874             xx = doputenv(path);
    00875             /*@-modobserver@*/
    00876             ipath = _free(ipath);
    00877             /*@=modobserver@*/
    00878         }
    00879
    00880         if (prefixes != NULL)
    00881         for (i = 0; i < numPrefixes; i++) {
    00882             sprintf(prefixBuf, "RPM_INSTALL_PREFIX%d=%s", i, prefixes[i]);
    00883             xx = doputenv(prefixBuf);
    00884
    00885             /* backwards compatibility */
    00886             if (i == 0) {
    00887                 sprintf(prefixBuf, "RPM_INSTALL_PREFIX=%s", prefixes[i]);
    00888                 xx = doputenv(prefixBuf);
    00889             }
    00890         }
    00891
    00892         {   const char * rootDir = rpmtsRootDir(ts);
    00893             if (!rpmtsChrootDone(ts) && rootDir != NULL &&
    00894                 !(rootDir[0] == '/' && rootDir[1] == '\0'))
    00895             {
    00896                 /*@-modobserver@*/
    00897                 xx = Chroot(rootDir);
    00898                 /*@=modobserver@*/
    00899             }
    00900             xx = Chdir("/");
    00901             rpmlog(RPMLOG_DEBUG, D_("%s: %s(%s)\texecv(%s) pid %d\n"),
    00902                         psm->stepName, sln, NVRA,
    00903                         argv[0], (unsigned)getpid());
    00904
    00905             /* XXX Don't mtrace into children. */
    00906             unsetenv("MALLOC_CHECK_");
    00907
    00908             if (ssp != NULL)
    00909                 *ssp |= RPMSCRIPT_STATE_EXEC;
    00910
    00911             /* Permit libselinux to do the scriptlet exec. */
    00912             if (rpmtsSELinuxEnabled(ts) == 1) {
    00913                 if (ssp != NULL)
    00914                     *ssp |= RPMSCRIPT_STATE_SELINUX;
    00915 /*@-moduncon@*/
    00916                 xx = rpm_execcon(0, argv[0], (char *const *)argv, environ);
    00917 /*@=moduncon@*/
    00918             } else {
    00919 /*@-nullstate@*/
    00920                 xx = execv(argv[0], (char *const *)argv);
    00921 /*@=nullstate@*/
    00922             }
    00923         }
    00924
    00925         if (ssp != NULL)
    00926             *ssp &= ~RPMSCRIPT_STATE_EXEC;
    00927
    00928         _exit(-1);
    00929         /*@notreached@*/
    00930     }
    00931
    00932     if (psm->sq.child == (pid_t)-1) {
    00933         rpmlog(RPMLOG_ERR, _("Couldn't fork %s: %s\n"), sln, strerror(errno));
    00934         goto exit;
    00935     }
    00936
    00937     (void) psmWait(psm);
    00938
    00939   /* XXX filter order dependent multilib "other" arch helper error. */
    00940   if (!(psm->sq.reaped >= 0 && !strcmp(argv[0], "/usr/sbin/glibc_post_upgrade") && WEXITSTATUS(psm->sq.status) == 110)) {
    00941     void *ptr = NULL;
    00942     if (psm->sq.reaped < 0) {
    00943         rpmlog(RPMLOG_ERR,
    00944                 _("%s(%s) scriptlet failed, waitpid(%d) rc %d: %s\n"),
    00945                  sln, NVRA, psm->sq.child, psm->sq.reaped, strerror(errno));
    00946         goto exit;
    00947     } else
    00948     if (!WIFEXITED(psm->sq.status) || WEXITSTATUS(psm->sq.status)) {
    00949         if (WIFSIGNALED(psm->sq.status)) {
    00950             ptr = rpmtsNotify(ts, psm->te, RPMCALLBACK_SCRIPT_ERROR,
    00951                                  psm->scriptTag, WTERMSIG(psm->sq.status));
    00952             rpmlog(RPMLOG_ERR,
    00953                  _("%s(%s) scriptlet failed, signal %d\n"),
    00954                  sln, NVRA, WTERMSIG(psm->sq.status));
    00955         } else {
    00956             ptr = rpmtsNotify(ts, psm->te, RPMCALLBACK_SCRIPT_ERROR,
    00957                                  psm->scriptTag, WEXITSTATUS(psm->sq.status));
    00958             rpmlog(RPMLOG_ERR,
    00959                 _("%s(%s) scriptlet failed, exit status %d\n"),
    00960                 sln, NVRA, WEXITSTATUS(psm->sq.status));
    00961         }
    00962         goto exit;
    00963     }
    00964   }
    00965
    00966     rc = RPMRC_OK;
    00967
    00968 exit:
    00969     prefixes = _free(prefixes);
    00970
    00971     if (out)
    00972         xx = Fclose(out);       /* XXX dup'd STDOUT_FILENO */
    00973
    00974     if (script) {
    00975         if (!rpmIsDebug())
    00976             xx = Unlink(fn);
    00977         fn = _free(fn);
    00978     }
    00979
    00980     body = _free(body);
    00981     NVRA = _free(NVRA);
    00982
    00983     return rc;
    00984 }
    00985
    00991 static rpmRC runInstScript(rpmpsm psm)
    00992         /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
    00993         /*@modifies psm, rpmGlobalMacroContext, fileSystem, internalState @*/
    00994 {
    00995     HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
    00996     rpmfi fi = psm->fi;
    00997     const char * argv0 = NULL;
    00998     const char * script;
    00999     rpmRC rc = RPMRC_OK;
    01000     int xx;
    01001
    01002 assert(fi->h != NULL);
    01003     he->tag = psm->scriptTag;
    01004     xx = headerGet(fi->h, he, 0);
    01005     script = he->p.str;
    01006     if (script == NULL)
    01007         goto exit;
    01008     he->tag = psm->progTag;
    01009     xx = headerGet(fi->h, he, 0);
    01010     if (he->p.ptr == NULL)
    01011         goto exit;
    01012
    01013     /* Coerce strings into header argv return. */
    01014     if (he->t == RPM_STRING_TYPE) {
    01015         const char * s = he->p.str;
    01016         char * t;
    01017         he->p.argv = xmalloc(sizeof(*he->p.argv)+strlen(s)+1);
    01018         he->p.argv[0] = t = (char *) &he->p.argv[1];
    01019         t = stpcpy(t, s);
    01020         *t = '\0';
    01021         s = _free(s);
    01022     }
    01023
    01024     /* Expand "%script -p %%{interpreter}" macros. */
    01025     if (he->p.argv[0][0] == '%')
    01026         he->p.argv[0] = argv0 = rpmExpand(he->p.argv[0], NULL);
    01027
    01028     rc = runScript(psm, fi->h, tag2sln(psm->scriptTag), he->c, he->p.argv,
    01029                 script, psm->scriptArg, -1);
    01030
    01031 exit:
    01032     argv0 = _free(argv0);
    01033     he->p.ptr = _free(he->p.ptr);
    01034     script = _free(script);
    01035     return rc;
    01036 }
    01037
    01048 static rpmRC handleOneTrigger(const rpmpsm psm,
    01049                         Header sourceH, Header triggeredH,
    01050                         int arg2, unsigned char * triggersAlreadyRun)
    01051         /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState@*/
    01052         /*@modifies psm, sourceH, triggeredH, *triggersAlreadyRun,
    01053                 rpmGlobalMacroContext, fileSystem, internalState @*/
    01054 {
    01055     int scareMem = 0;
    01056     HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
    01057     const rpmts ts = psm->ts;
    01058     rpmds trigger = NULL;
    01059     const char ** triggerScripts;
    01060     const char ** triggerProgs;
    01061     uint32_t * triggerIndices;
    01062     const char * sourceName;
    01063     const char * triggerName;
    01064     rpmRC rc = RPMRC_OK;
    01065     int xx;
    01066     int i;
    01067
    01068     he->tag = RPMTAG_NAME;
    01069     xx = headerGet(sourceH, he, 0);
    01070     sourceName = he->p.str;
    01071     he->tag = RPMTAG_NAME;
    01072     xx = headerGet(triggeredH, he, 0);
    01073     triggerName = he->p.str;
    01074
    01075     trigger = rpmdsInit(rpmdsNew(triggeredH, RPMTAG_TRIGGERNAME, scareMem));
    01076     if (trigger == NULL)
    01077         goto exit;
    01078
    01079     (void) rpmdsSetNoPromote(trigger, 1);
    01080
    01081     while ((i = rpmdsNext(trigger)) >= 0) {
    01082         const char * Name;
    01083         uint32_t Flags = rpmdsFlags(trigger);
    01084
    01085         if ((Name = rpmdsN(trigger)) == NULL)
    01086             continue;   /* XXX can't happen */
    01087
    01088         if (strcmp(Name, sourceName))
    01089             continue;
    01090         if (!(Flags & psm->sense))
    01091             continue;
    01092
    01093         /*
    01094          * XXX Trigger on any provided dependency, not just the package NEVR.
    01095          */
    01096         if (!rpmdsAnyMatchesDep(sourceH, trigger, 1))
    01097             continue;
    01098
    01099         he->tag = RPMTAG_TRIGGERINDEX;
    01100         xx = headerGet(triggeredH, he, 0);
    01101         triggerIndices = he->p.ui32p;
    01102         he->tag = RPMTAG_TRIGGERSCRIPTS;
    01103         xx = headerGet(triggeredH, he, 0);
    01104         triggerScripts = he->p.argv;
    01105         he->tag = RPMTAG_TRIGGERSCRIPTPROG;
    01106         xx = headerGet(triggeredH, he, 0);
    01107         triggerProgs = he->p.argv;
    01108
    01109         if (triggerIndices && triggerScripts && triggerProgs) {
    01110             int arg1;
    01111             int index;
    01112
    01113             arg1 = rpmdbCountPackages(rpmtsGetRdb(ts), triggerName);
    01114             if (arg1 < 0) {
    01115                 /* XXX W2DO? fails as "execution of script failed" */
    01116                 rc = RPMRC_FAIL;
    01117             } else {
    01118                 arg1 += psm->countCorrection;
    01119                 index = triggerIndices[i];
    01120                 if (triggersAlreadyRun == NULL ||
    01121                     triggersAlreadyRun[index] == 0)
    01122                 {
    01123                     rc = runScript(psm, triggeredH, "%trigger", 1,
    01124                             triggerProgs + index, triggerScripts[index],
    01125                             arg1, arg2);
    01126                     if (triggersAlreadyRun != NULL)
    01127                         triggersAlreadyRun[index] = 1;
    01128                 }
    01129             }
    01130         }
    01131
    01132         triggerIndices = _free(triggerIndices);
    01133         triggerScripts = _free(triggerScripts);
    01134         triggerProgs = _free(triggerProgs);
    01135
    01136         /*
    01137          * Each target/source header pair can only result in a single
    01138          * script being run.
    01139          */
    01140         break;
    01141     }
    01142
    01143     trigger = rpmdsFree(trigger);
    01144
    01145 exit:
    01146     sourceName = _free(sourceName);
    01147     triggerName = _free(triggerName);
    01148
    01149     return rc;
    01150 }
    01151
    01157 static rpmRC runTriggers(rpmpsm psm)
    01158         /*@globals rpmGlobalMacroContext, h_errno,
    01159                 fileSystem, internalState @*/
    01160         /*@modifies psm, rpmGlobalMacroContext,
    01161                 fileSystem, internalState @*/
    01162 {
    01163     const rpmts ts = psm->ts;
    01164     rpmfi fi = psm->fi;
    01165     int numPackage = -1;
    01166     rpmRC rc = RPMRC_OK;
    01167     const char * N = NULL;
    01168
    01169     if (psm->te)        /* XXX can't happen */
    01170         N = rpmteN(psm->te);
    01171 /* XXX: Might need to adjust instance counts for autorollback. */
    01172     if (N)              /* XXX can't happen */
    01173         numPackage = rpmdbCountPackages(rpmtsGetRdb(ts), N)
    01174                                 + psm->countCorrection;
    01175     if (numPackage < 0)
    01176         return RPMRC_NOTFOUND;
    01177
    01178     if (fi != NULL && fi->h != NULL)    /* XXX can't happen */
    01179     {   Header triggeredH;
    01180         rpmdbMatchIterator mi;
    01181         int countCorrection = psm->countCorrection;
    01182
    01183         psm->countCorrection = 0;
    01184         mi = rpmtsInitIterator(ts, RPMTAG_TRIGGERNAME, N, 0);
    01185         while((triggeredH = rpmdbNextIterator(mi)) != NULL)
    01186             rc |= handleOneTrigger(psm, fi->h, triggeredH, numPackage, NULL);
    01187         mi = rpmdbFreeIterator(mi);
    01188         psm->countCorrection = countCorrection;
    01189     }
    01190
    01191     return rc;
    01192 }
    01193
    01199 static rpmRC runImmedTriggers(rpmpsm psm)
    01200         /*@globals rpmGlobalMacroContext, h_errno,
    01201                 fileSystem, internalState @*/
    01202         /*@modifies psm, rpmGlobalMacroContext,
    01203                 fileSystem, internalState @*/
    01204 {
    01205     HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
    01206     const rpmts ts = psm->ts;
    01207     rpmfi fi = psm->fi;
    01208     const char ** triggerNames;
    01209     int numTriggers;
    01210     uint32_t * triggerIndices;
    01211     int numTriggerIndices;
    01212     unsigned char * triggersRun;
    01213     rpmRC rc = RPMRC_OK;
    01214     size_t nb;
    01215     int xx;
    01216
    01217 assert(fi->h != NULL);
    01218     if (fi->h == NULL)  return rc;      /* XXX can't happen */
    01219
    01220     he->tag = RPMTAG_TRIGGERNAME;
    01221     xx = headerGet(fi->h, he, 0);
    01222     triggerNames = he->p.argv;
    01223     numTriggers = he->c;
    01224     he->tag = RPMTAG_TRIGGERINDEX;
    01225     xx = headerGet(fi->h, he, 0);
    01226     triggerIndices = he->p.ui32p;
    01227     numTriggerIndices = he->c;
    01228
    01229     if (!(triggerNames && numTriggers > 0 && triggerIndices && numTriggerIndices > 0))
    01230         goto exit;
    01231
    01232     nb = sizeof(*triggersRun) * numTriggerIndices;
    01233     triggersRun = memset(alloca(nb), 0, nb);
    01234
    01235     {   Header sourceH = NULL;
    01236         int i;
    01237
    01238         for (i = 0; i < numTriggers; i++) {
    01239             rpmdbMatchIterator mi;
    01240
    01241             if (triggersRun[triggerIndices[i]] != 0) continue;
    01242
    01243             mi = rpmtsInitIterator(ts, RPMTAG_NAME, triggerNames[i], 0);
    01244
    01245             while((sourceH = rpmdbNextIterator(mi)) != NULL) {
    01246                 rc |= handleOneTrigger(psm, sourceH, fi->h,
    01247                                 rpmdbGetIteratorCount(mi),
    01248                                 triggersRun);
    01249             }
    01250
    01251             mi = rpmdbFreeIterator(mi);
    01252         }
    01253     }
    01254
    01255 exit:
    01256     triggerIndices = _free(triggerIndices);
    01257     triggerNames = _free(triggerNames);
    01258     return rc;
    01259 }
    01260
    01261 /*@observer@*/
    01262 static const char * pkgStageString(pkgStage a)
    01263         /*@*/
    01264 {
    01265     switch(a) {
    01266     case PSM_UNKNOWN:           return "unknown";
    01267
    01268     case PSM_PKGINSTALL:        return "  install";
    01269     case PSM_PKGERASE:          return "    erase";
    01270     case PSM_PKGCOMMIT:         return "   commit";
    01271     case PSM_PKGSAVE:           return "repackage";
    01272
    01273     case PSM_INIT:              return "init";
    01274     case PSM_PRE:               return "pre";
    01275     case PSM_PROCESS:           return "process";
    01276     case PSM_POST:              return "post";
    01277     case PSM_UNDO:              return "undo";
    01278     case PSM_FINI:              return "fini";
    01279
    01280     case PSM_CREATE:            return "create";
    01281     case PSM_NOTIFY:            return "notify";
    01282     case PSM_DESTROY:           return "destroy";
    01283     case PSM_COMMIT:            return "commit";
    01284
    01285     case PSM_CHROOT_IN:         return "chrootin";
    01286     case PSM_CHROOT_OUT:        return "chrootout";
    01287     case PSM_SCRIPT:            return "script";
    01288     case PSM_TRIGGERS:          return "triggers";
    01289     case PSM_IMMED_TRIGGERS:    return "immedtriggers";
    01290
    01291     case PSM_RPMIO_FLAGS:       return "rpmioflags";
    01292
    01293     case PSM_RPMDB_LOAD:        return "rpmdbload";
    01294     case PSM_RPMDB_ADD:         return "rpmdbadd";
    01295     case PSM_RPMDB_REMOVE:      return "rpmdbremove";
    01296
    01297     default:                    return "???";
    01298     }
    01299     /*@noteached@*/
    01300 }
    01301
    01302 rpmpsm XrpmpsmUnlink(rpmpsm psm, const char * msg, const char * fn, unsigned ln)
    01303 {
    01304     if (psm == NULL) return NULL;
    01305 /*@-modfilesys@*/
    01306 if (_psm_debug && msg != NULL)
    01307 fprintf(stderr, "--> psm %p -- %d %s at %s:%u\n", psm, psm->nrefs, msg, fn, ln);
    01308 /*@=modfilesys@*/
    01309     psm->nrefs--;
    01310     return NULL;
    01311 }
    01312
    01313 rpmpsm XrpmpsmLink(rpmpsm psm, const char * msg, const char * fn, unsigned ln)
    01314 {
    01315     if (psm == NULL) return NULL;
    01316     psm->nrefs++;
    01317
    01318 /*@-modfilesys@*/
    01319 if (_psm_debug && msg != NULL)
    01320 fprintf(stderr, "--> psm %p ++ %d %s at %s:%u\n", psm, psm->nrefs, msg, fn, ln);
    01321 /*@=modfilesys@*/
    01322
    01323     /*@-refcounttrans@*/ return psm; /*@=refcounttrans@*/
    01324 }
    01325
    01326 rpmpsm rpmpsmFree(rpmpsm psm)
    01327 {
    01328     const char * msg = "rpmpsmFree";
    01329     if (psm == NULL)
    01330         return NULL;
    01331
    01332     if (psm->nrefs > 1)
    01333         return rpmpsmUnlink(psm, msg);
    01334
    01335 /*@-nullstate@*/
    01336     psm->fi = rpmfiFree(psm->fi);
    01337 #ifdef  NOTYET
    01338     psm->te = rpmteFree(psm->te);
    01339 #else
    01340     psm->te = NULL;
    01341 #endif
    01342 /*@-internalglobs@*/
    01343     psm->ts = rpmtsFree(psm->ts);
    01344 /*@=internalglobs@*/
    01345
    01346     psm->sstates = _free(psm->sstates);
    01347
    01348     (void) rpmpsmUnlink(psm, msg);
    01349
    01350     /*@-refcounttrans -usereleased@*/
    01351     memset(psm, 0, sizeof(*psm));               /* XXX trash and burn */
    01352     psm = _free(psm);
    01353     /*@=refcounttrans =usereleased@*/
    01354
    01355     return NULL;
    01356 /*@=nullstate@*/
    01357 }
    01358
    01359 rpmpsm rpmpsmNew(rpmts ts, rpmte te, rpmfi fi)
    01360 {
    01361     const char * msg = "rpmpsmNew";
    01362     rpmpsm psm = xcalloc(1, sizeof(*psm));
    01363
    01364     if (ts)     psm->ts = rpmtsLink(ts, msg);
    01365 #ifdef  NOTYET
    01366     if (te)     psm->te = rpmteLink(te, msg);
    01367 #else
    01368 /*@-assignexpose -temptrans @*/
    01369     if (te)     psm->te = te;
    01370 /*@=assignexpose =temptrans @*/
    01371 #endif
    01372     if (fi)     psm->fi = rpmfiLink(fi, msg);
    01373
    01374     psm->sstates = xcalloc(RPMSCRIPT_MAX, sizeof(*psm->sstates));
    01375
    01376     return rpmpsmLink(psm, msg);
    01377 }
    01378
    01385 static uint32_t hLoadTID(Header h, rpmTag tag)
    01386         /*@*/
    01387 {
    01388     HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
    01389     uint32_t val;
    01390     int xx;
    01391
    01392     he->tag = tag;
    01393     xx = headerGet(h, he, 0);
    01394     val = (xx && he->p.ui32p ? he->p.ui32p[0] : 0);
    01395     he->p.ptr = _free(he->p.ptr);
    01396     return val;
    01397 }
    01398
    01406 static int hCopyTag(Header sh, Header th, rpmTag tag)
    01407         /*@modifies th @*/
    01408 {
    01409     HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
    01410     int xx = 1;
    01411
    01412     he->tag = tag;
    01413     if (headerGet(sh, he, 0) && he->c > 0)
    01414         xx = headerPut(th, he, 0);
    01415     he->p.ptr = _free(he->p.ptr);
    01416     return 0;
    01417 }
    01418
    01425 static int hSaveBlinks(Header h, const struct rpmChainLink_s * blink)
    01426         /*@modifies h @*/
    01427 {
    01428     HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
    01429 /*@observer@*/
    01430     static const char * chain_end = RPMTE_CHAIN_END;
    01431     int ac;
    01432     int xx = 1;
    01433
    01434     /* Save forward links into header upgrade chain. */
    01435     he->tag = RPMTAG_BLINKNEVRA;
    01436     he->t = RPM_STRING_ARRAY_TYPE;
    01437     ac = argvCount(blink->NEVRA);
    01438     if (ac > 0) {
    01439         he->p.argv = argvData(blink->NEVRA);
    01440         he->c = ac;
    01441     } else {    /* XXX Add an explicit chain terminator on 1st install. */
    01442         he->p.argv = &chain_end;
    01443         he->c = 1;
    01444     }
    01445     xx = headerPut(h, he, 0);
    01446
    01447     he->tag = RPMTAG_BLINKPKGID;
    01448     he->t = RPM_STRING_ARRAY_TYPE;
    01449     ac = argvCount(blink->Pkgid);
    01450     if (ac > 0) {
    01451         he->p.argv = argvData(blink->Pkgid);
    01452         he->c = ac;
    01453     } else {    /* XXX Add an explicit chain terminator on 1st install. */
    01454         he->p.argv = &chain_end;
    01455         he->c = 1;
    01456     }
    01457     xx = headerPut(h, he, 0);
    01458
    01459     he->tag = RPMTAG_BLINKHDRID;
    01460     he->t = RPM_STRING_ARRAY_TYPE;
    01461     ac = argvCount(blink->Hdrid);
    01462     if (ac > 0) {
    01463         he->p.argv = argvData(blink->Hdrid);
    01464         he->c = ac;
    01465     } else {    /* XXX Add an explicit chain terminator on 1st install. */
    01466         he->p.argv = &chain_end;
    01467         he->c = 1;
    01468     }
    01469     xx = headerPut(h, he, 0);
    01470
    01471     return 0;
    01472 }
    01473
    01480 static int hSaveFlinks(Header h, const struct rpmChainLink_s * flink)
    01481         /*@modifies h @*/
    01482 {
    01483     HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
    01484 #ifdef  NOTYET
    01485     /*@observer@*/
    01486     static const char * chain_end = RPMTE_CHAIN_END;
    01487 #endif
    01488     int ac;
    01489     int xx = 1;
    01490
    01491     /* Save forward links into header upgrade chain. */
    01492     he->tag = RPMTAG_FLINKNEVRA;
    01493     he->t = RPM_STRING_ARRAY_TYPE;
    01494     ac = argvCount(flink->NEVRA);
    01495     if (ac > 0) {
    01496         he->p.argv = argvData(flink->NEVRA);
    01497         he->c = ac;
    01498     }
    01499 #ifdef  NOTYET  /* XXX is an explicit flink terminator needed? */
    01500     else {      /* XXX Add an explicit chain terminator on 1st install. */
    01501         he->p.argv = &chain_end;
    01502         he->c = 1;
    01503     }
    01504 #endif
    01505     xx = headerPut(h, he, 0);
    01506
    01507     he->tag = RPMTAG_FLINKPKGID;
    01508     he->t = RPM_STRING_ARRAY_TYPE;
    01509     ac = argvCount(flink->Pkgid);
    01510     if (ac > 0) {
    01511         he->p.argv = argvData(flink->Pkgid);
    01512         he->c = ac;
    01513     }
    01514 #ifdef  NOTYET  /* XXX is an explicit flink terminator needed? */
    01515     else {      /* XXX Add an explicit chain terminator on 1st install. */
    01516         he->p.argv = &chain_end;
    01517         he->c = 1;
    01518     }
    01519 #endif
    01520     xx = headerPut(h, he, 0);
    01521
    01522     he->tag = RPMTAG_FLINKHDRID;
    01523     he->t = RPM_STRING_ARRAY_TYPE;
    01524     ac = argvCount(flink->Hdrid);
    01525     if (ac > 0) {
    01526         he->p.argv = argvData(flink->Hdrid);
    01527         he->c = ac;
    01528     }
    01529 #ifdef  NOTYET  /* XXX is an explicit flink terminator needed? */
    01530     else {      /* XXX Add an explicit chain terminator on 1st install. */
    01531         he->p.argv = &chain_end;
    01532         he->c = 1;
    01533     }
    01534 #endif
    01535     xx = headerPut(h, he, 0);
    01536
    01537     return 0;
    01538 }
    01539
    01547 static int populateInstallHeader(const rpmts ts, const rpmte te, rpmfi fi)
    01548         /*@modifies fi @*/
    01549 {
    01550     HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
    01551     uint32_t tscolor = rpmtsColor(ts);
    01552     uint32_t tecolor = rpmteColor(te);
    01553     uint32_t installTime = (uint32_t) time(NULL);
    01554     int fc = rpmfiFC(fi);
    01555     int xx = 1;
    01556
    01557 assert(fi->h != NULL);
    01558
    01559     he->tag = RPMTAG_INSTALLTIME;
    01560     he->t = RPM_UINT32_TYPE;
    01561     he->p.ui32p = &installTime;
    01562     he->c = 1;
    01563     xx = headerPut(fi->h, he, 0);
    01564
    01565     he->tag = RPMTAG_INSTALLCOLOR;
    01566     he->t = RPM_UINT32_TYPE;
    01567     he->p.ui32p = &tscolor;
    01568     he->c = 1;
    01569     xx = headerPut(fi->h, he, 0);
    01570
    01571     /* XXX FIXME: add preferred color at install. */
    01572
    01573     he->tag = RPMTAG_PACKAGECOLOR;
    01574     he->t = RPM_UINT32_TYPE;
    01575     he->p.ui32p = &tecolor;
    01576     he->c = 1;
    01577     xx = headerPut(fi->h, he, 0);
    01578
    01579     /* Add the header's origin (i.e. URL) */
    01580     he->tag = RPMTAG_PACKAGEORIGIN;
    01581     he->t = RPM_STRING_TYPE;
    01582     he->p.str = headerGetOrigin(fi->h);
    01583     he->c = 1;
    01584     if (he->p.str != NULL)
    01585         xx = headerPut(fi->h, he, 0);
    01586
    01587     /* XXX Don't clobber forward/backward upgrade chain on rollbacks */
    01588     if (rpmtsType(ts) != RPMTRANS_TYPE_ROLLBACK)
    01589         xx = hSaveBlinks(fi->h, &te->blink);
    01590
    01591     return 0;
    01592 }
    01593
    01594
    01602 static int postPopulateInstallHeader(const rpmts ts, const rpmte te, rpmfi fi)
    01603         /*@modifies fi @*/
    01604 {
    01605     HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
    01606     int fc = rpmfiFC(fi);
    01607     int xx = 1;
    01608
    01609     if (fi->fstates != NULL && fc > 0) {
    01610         he->tag = RPMTAG_FILESTATES;
    01611         he->t = RPM_UINT8_TYPE;
    01612         he->p.ui8p = fi->fstates;
    01613         he->c = fc;
    01614         xx = headerPut(fi->h, he, 0);
    01615     }
    01616
    01617     return 0;
    01618 }
    01619
    01620 #if defined(HAVE_PTHREAD_H)
    01621 static void * rpmpsmThread(void * arg)
    01622         /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
    01623         /*@modifies arg, rpmGlobalMacroContext, fileSystem, internalState @*/
    01624 {
    01625     rpmpsm psm = arg;
    01626 /*@-unqualifiedtrans@*/
    01627     return ((void *) rpmpsmStage(psm, psm->nstage));
    01628 /*@=unqualifiedtrans@*/
    01629 }
    01630 #endif
    01631
    01632 static int rpmpsmNext(rpmpsm psm, pkgStage nstage)
    01633         /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
    01634         /*@modifies psm, rpmGlobalMacroContext, fileSystem, internalState @*/
    01635 {
    01636     psm->nstage = nstage;
    01637 #if defined(HAVE_PTHREAD_H)
    01638     if (_psm_threads)
    01639         return rpmsqJoin( rpmsqThread(rpmpsmThread, psm) );
    01640 #endif
    01641     return rpmpsmStage(psm, psm->nstage);
    01642 }
    01643
    01648 /*@-nullpass@*/ /* FIX: testing null annotation for fi->h */
    01649 rpmRC rpmpsmStage(rpmpsm psm, pkgStage stage)
    01650 {
    01651     HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
    01652     const rpmts ts = psm->ts;
    01653     uint32_t tscolor = rpmtsColor(ts);
    01654     rpmfi fi = psm->fi;
    01655     rpmRC rc = psm->rc;
    01656     int saveerrno;
    01657     int xx;
    01658
    01659 /* XXX hackery to assert(!scaremem) in rpmfiNew. */
    01660 if (fi->h == NULL && fi->te && fi->te->h != NULL) fi->h = headerLink(fi->te->h);
    01661 #if 0
    01662 assert(fi->h != NULL);  /* XXX install/verify have fi->h, erasures doesn't. */
    01663 #endif
    01664
    01665     switch (stage) {
    01666     case PSM_UNKNOWN:
    01667         break;
    01668     case PSM_INIT:
    01669         rpmlog(RPMLOG_DEBUG, D_("%s: %s has %d files, test = %d\n"),
    01670                 psm->stepName, rpmteNEVR(psm->te),
    01671                 rpmfiFC(fi), (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST));
    01672
    01673         /*
    01674          * When we run scripts, we pass an argument which is the number of
    01675          * versions of this package that will be installed when we are
    01676          * finished.
    01677          */
    01678         psm->npkgs_installed = rpmdbCountPackages(rpmtsGetRdb(ts), rpmteN(psm->te));
    01679         if (psm->npkgs_installed < 0) {
    01680             rc = RPMRC_FAIL;
    01681             break;
    01682         }
    01683
    01684         /* Adjust package count on rollback downgrade. */
    01685 assert(psm->te != NULL);
    01686         if (rpmtsType(ts) == RPMTRANS_TYPE_AUTOROLLBACK &&
    01687             (psm->goal & ~(PSM_PKGSAVE|PSM_PKGERASE)))
    01688         {
    01689             if (psm->te->downgrade)
    01690                 psm->npkgs_installed--;
    01691         }
    01692
    01693         if (psm->goal == PSM_PKGINSTALL) {
    01694             int fc = rpmfiFC(fi);
    01695             const char * hdrid;
    01696
    01697             /* Add per-transaction data to install header. */
    01698             xx = populateInstallHeader(ts, psm->te, fi);
    01699
    01700             psm->scriptArg = psm->npkgs_installed + 1;
    01701
    01702 assert(psm->mi == NULL);
    01703             hdrid = rpmteHdrid(psm->te);
    01704             if (hdrid != NULL) {
    01705                 /* XXX should use RPMTAG_HDRID not RPMTAG_SHA1HEADER */
    01706                 psm->mi = rpmtsInitIterator(ts, RPMTAG_SHA1HEADER, hdrid, 0);
    01707             } else {
    01708                 psm->mi = rpmtsInitIterator(ts, RPMTAG_NAME, rpmteN(psm->te),0);
    01709                 xx = rpmdbSetIteratorRE(psm->mi, RPMTAG_EPOCH, RPMMIRE_STRCMP,
    01710                         rpmteE(psm->te));
    01711                 xx = rpmdbSetIteratorRE(psm->mi, RPMTAG_VERSION, RPMMIRE_STRCMP,
    01712                         rpmteV(psm->te));
    01713                 xx = rpmdbSetIteratorRE(psm->mi, RPMTAG_RELEASE, RPMMIRE_STRCMP,
    01714                         rpmteR(psm->te));
    01715                 if (tscolor) {
    01716                     xx = rpmdbSetIteratorRE(psm->mi,RPMTAG_ARCH, RPMMIRE_STRCMP,
    01717                         rpmteA(psm->te));
    01718                     xx = rpmdbSetIteratorRE(psm->mi, RPMTAG_OS, RPMMIRE_STRCMP,
    01719                         rpmteO(psm->te));
    01720                 }
    01721             }
    01722
    01723             while ((psm->oh = rpmdbNextIterator(psm->mi)) != NULL) {
    01724                 fi->record = rpmdbGetIteratorOffset(psm->mi);
    01725                 psm->oh = NULL;
    01726                 /*@loopbreak@*/ break;
    01727             }
    01728             psm->mi = rpmdbFreeIterator(psm->mi);
    01729
    01730             rc = RPMRC_OK;
    01731
    01732             /* XXX lazy alloc here may need to be done elsewhere. */
    01733             if (fi->fstates == NULL && fc > 0) {
    01734                 fi->fstates = xmalloc(sizeof(*fi->fstates) * fc);
    01735                 memset(fi->fstates, RPMFILE_STATE_NORMAL, fc);
    01736             }
    01737
    01738             if (rpmtsFlags(ts) & RPMTRANS_FLAG_JUSTDB)  break;
    01739             if (fc <= 0)                                break;
    01740
    01741             /*
    01742              * Old format relocatable packages need the entire default
    01743              * prefix stripped to form the cpio list, while all other packages
    01744              * need the leading / stripped.
    01745              */
    01746             he->tag = RPMTAG_DEFAULTPREFIX;
    01747             xx = headerGet(fi->h, he, 0);
    01748             fi->striplen = (xx && he->p.str ? strlen(he->p.str) + 1 : 1);
    01749             he->p.ptr = _free(he->p.ptr);
    01750             fi->mapflags =
    01751                 CPIO_MAP_PATH | CPIO_MAP_MODE | CPIO_MAP_UID | CPIO_MAP_GID | (fi->mapflags & CPIO_SBIT_CHECK);
    01752
    01753             if (headerIsEntry(fi->h, RPMTAG_ORIGBASENAMES))
    01754                 he->tag = RPMTAG_ORIGPATHS;
    01755             else
    01756                 he->tag = RPMTAG_FILEPATHS;
    01757             xx = headerGet(fi->h, he, 0);
    01758 assert(he->p.argv != NULL);
    01759             fi->apath = he->p.argv;
    01760
    01761             if (fi->fuser == NULL) {
    01762                 he->tag = RPMTAG_FILEUSERNAME;
    01763                 xx = headerGet(fi->h, he, 0);
    01764                 fi->fuser = he->p.argv;
    01765             }
    01766             if (fi->fgroup == NULL) {
    01767                 he->tag = RPMTAG_FILEGROUPNAME;
    01768                 xx = headerGet(fi->h, he, 0);
    01769                 fi->fgroup = he->p.argv;
    01770             }
    01771             rc = RPMRC_OK;
    01772         }
    01773         if (psm->goal == PSM_PKGERASE || psm->goal == PSM_PKGSAVE) {
    01774             psm->scriptArg = psm->npkgs_installed - 1;
    01775
    01776             /* Retrieve installed header. */
    01777             rc = rpmpsmNext(psm, PSM_RPMDB_LOAD);
    01778 #ifdef  DYING
    01779 if (rc == RPMRC_OK)
    01780 if (psm->te)
    01781 psm->te->h = headerLink(fi->h);
    01782 #else
    01783             if (rc == RPMRC_OK && psm->te)
    01784                 (void) rpmteSetHeader(psm->te, fi->h);
    01785 #endif
    01786         }
    01787         if (psm->goal == PSM_PKGSAVE) {
    01788             /* Open output package for writing. */
    01789             {   char tiddn[32];
    01790                 const char * bfmt;
    01791                 const char * pkgdn;
    01792                 const char * pkgbn;
    01793                 char * pkgdn_buf;
    01794
    01795                 xx = snprintf(tiddn, sizeof(tiddn), "%d", rpmtsGetTid(ts));
    01796                 bfmt = rpmGetPath(tiddn, "/", "%{_repackage_name_fmt}", NULL);
    01797                 pkgbn = headerSprintf(fi->h, bfmt,
    01798                                         NULL, rpmHeaderFormats, NULL);
    01799                 bfmt = _free(bfmt);
    01800                 psm->pkgURL = rpmGenPath("%{?_repackage_root}",
    01801                                          "%{?_repackage_dir}",
    01802                                         pkgbn);
    01803                 pkgbn = _free(pkgbn);
    01804                 (void) urlPath(psm->pkgURL, &psm->pkgfn);
    01805                 pkgdn_buf = xstrdup(psm->pkgfn);
    01806 /*@-moduncon@*/
    01807                 pkgdn = dirname(pkgdn_buf);
    01808 /*@=moduncon@*/
    01809                 rc = rpmMkdirPath(pkgdn, "_repackage_dir");
    01810                 pkgdn_buf = _free(pkgdn_buf);
    01811                 if (rc == RPMRC_FAIL)
    01812                     break;
    01813                 psm->fd = Fopen(psm->pkgfn, "w.fdio");
    01814                 if (psm->fd == NULL || Ferror(psm->fd)) {
    01815                     rc = RPMRC_FAIL;
    01816                     break;
    01817                 }
    01818             }
    01819         }
    01820         break;
    01821     case PSM_PRE:
    01822         if (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST)        break;
    01823
    01824 /* XXX insure that trigger index is opened before entering chroot. */
    01825 #ifdef  NOTYET
    01826  { static int oneshot = 0;
    01827    dbiIndex dbi;
    01828    if (!oneshot) {
    01829      dbi = dbiOpen(rpmtsGetRdb(ts), RPMTAG_TRIGGERNAME, 0);
    01830      oneshot++;
    01831    }
    01832  }
    01833 #endif
    01834
    01835         /* Change root directory if requested and not already done. */
    01836         rc = rpmpsmNext(psm, PSM_CHROOT_IN);
    01837
    01838         if (psm->goal == PSM_PKGINSTALL) {
    01839             psm->scriptTag = RPMTAG_PREIN;
    01840             psm->progTag = RPMTAG_PREINPROG;
    01841             psm->sense = RPMSENSE_TRIGGERPREIN;
    01842             psm->countCorrection = 0;   /* XXX is this correct?!? */
    01843
    01844             if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOTRIGGERPREIN)) {
    01845
    01846                 /* Run triggers in other package(s) this package sets off. */
    01847                 rc = rpmpsmNext(psm, PSM_TRIGGERS);
    01848                 if (rc) break;
    01849
    01850                 /* Run triggers in this package other package(s) set off. */
    01851                 rc = rpmpsmNext(psm, PSM_IMMED_TRIGGERS);
    01852                 if (rc) break;
    01853             }
    01854
    01855             if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOPRE)) {
    01856                 rc = rpmpsmNext(psm, PSM_SCRIPT);
    01857                 if (rc != RPMRC_OK) {
    01858                     rpmlog(RPMLOG_ERR,
    01859                         _("%s: %s scriptlet failed (%d), skipping %s\n"),
    01860                         psm->stepName, tag2sln(psm->scriptTag), rc,
    01861                         rpmteNEVR(psm->te));
    01862                     break;
    01863                 }
    01864             }
    01865         }
    01866
    01867         if (psm->goal == PSM_PKGERASE) {
    01868             psm->scriptTag = RPMTAG_PREUN;
    01869             psm->progTag = RPMTAG_PREUNPROG;
    01870             psm->sense = RPMSENSE_TRIGGERUN;
    01871             psm->countCorrection = -1;
    01872
    01873             if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOTRIGGERUN)) {
    01874                 /* Run triggers in this package other package(s) set off. */
    01875                 rc = rpmpsmNext(psm, PSM_IMMED_TRIGGERS);
    01876                 if (rc) break;
    01877
    01878                 /* Run triggers in other package(s) this package sets off. */
    01879                 rc = rpmpsmNext(psm, PSM_TRIGGERS);
    01880                 if (rc) break;
    01881             }
    01882
    01883             if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOPREUN))
    01884                 rc = rpmpsmNext(psm, PSM_SCRIPT);
    01885         }
    01886         if (psm->goal == PSM_PKGSAVE) {
    01887             int noArchiveSize = 0;
    01888             const char * origin;
    01889
    01890             /* Regenerate original header. */
    01891             {   void * uh = NULL;
    01892
    01893                 /* Save original header's origin (i.e. URL) */
    01894                 he->tag = RPMTAG_PACKAGEORIGIN;
    01895                 xx = headerGet(fi->h, he, 0);
    01896                 origin = he->p.str;
    01897
    01898                 /* Retrieve original header blob. */
    01899                 he->tag = RPMTAG_HEADERIMMUTABLE;
    01900                 xx = headerGet(fi->h, he, 0);
    01901                 uh = he->p.ptr;
    01902                 if (xx && uh != NULL) {
    01903                     psm->oh = headerCopyLoad(uh);
    01904                     uh = _free(uh);
    01905                 } else {
    01906                     he->tag = RPMTAG_HEADERIMAGE;
    01907                     xx = headerGet(fi->h, he, 0);
    01908                     uh = he->p.ptr;
    01909                     if (xx && uh != NULL) {
    01910                         HeaderIterator hi;
    01911                         Header oh;
    01912
    01913                         /* Load the original header from the blob. */
    01914                         oh = headerCopyLoad(uh);
    01915
    01916                         /* XXX this is headerCopy w/o headerReload() */
    01917                         psm->oh = headerNew();
    01918
    01919                         for (hi = headerInit(oh);
    01920                              headerNext(hi, he, 0);
    01921                              he->p.ptr = _free(he->p.ptr))
    01922                         {
    01923                             if (he->tag == RPMTAG_ARCHIVESIZE)
    01924                                 noArchiveSize = 1;
    01925                             xx = headerPut(psm->oh, he, 0);
    01926                         }
    01927                         hi = headerFini(hi);
    01928
    01929                         oh = headerFree(oh);
    01930                         uh = _free(uh);
    01931                     } else
    01932                         break;  /* XXX shouldn't ever happen */
    01933                 }
    01934             }
    01935
    01936             /* Retrieve type of payload compression. */
    01937             /*@-nullstate@*/    /* FIX: psm->oh may be NULL */
    01938             rc = rpmpsmNext(psm, PSM_RPMIO_FLAGS);
    01939             /*@=nullstate@*/
    01940
    01941             /* Write the lead section into the package. */
    01942             {   static const char item[] = "Lead";
    01943                 const char * NEVR = rpmteNEVR(psm->te);
    01944                 size_t nb = rpmpkgSizeof(item, NULL);
    01945
    01946                 if (nb == 0)
    01947                     rc = RPMRC_FAIL;
    01948                 else {
    01949                     void * l = alloca(nb);
    01950                     memset(l, 0, nb);
    01951                     rc = rpmpkgWrite(item, psm->fd, l, &NEVR);
    01952                 }
    01953                 if (rc != RPMRC_OK) {
    01954                     rpmlog(RPMLOG_ERR, _("Unable to write package: %s\n"),
    01955                                 Fstrerror(psm->fd));
    01956                     break;
    01957                 }
    01958             }
    01959
    01960             /* Write the signature section into the package. */
    01961             /* XXX rpm-4.1 and later has archive size in signature header. */
    01962             {   static const char item[] = "Signature";
    01963                 Header sigh = headerRegenSigHeader(fi->h, noArchiveSize);
    01964                 /* Reallocate the signature into one contiguous region. */
    01965                 sigh = headerReload(sigh, RPMTAG_HEADERSIGNATURES);
    01966                 if (sigh == NULL) {
    01967                     rpmlog(RPMLOG_ERR, _("Unable to reload signature header\n"));
    01968                     rc = RPMRC_FAIL;
    01969                     break;
    01970                 }
    01971                 rc = rpmpkgWrite(item, psm->fd, sigh, NULL);
    01972                 sigh = headerFree(sigh);
    01973                 if (rc != RPMRC_OK) {
    01974                     break;
    01975                 }
    01976             }
    01977
    01978             /* Add remove transaction id to header. */
    01979             if (psm->oh != NULL)
    01980             {   uint32_t tid = rpmtsGetTid(ts);
    01981
    01982                 he->tag = RPMTAG_REMOVETID;
    01983                 he->t = RPM_UINT32_TYPE;
    01984                 he->p.ui32p = &tid;
    01985                 he->c = 1;
    01986                 xx = headerPut(psm->oh, he, 0);
    01987
    01988                 /* Add original header's origin (i.e. URL) */
    01989                 if (origin != NULL) {
    01990                     he->tag = RPMTAG_PACKAGEORIGIN;
    01991                     he->t = RPM_STRING_TYPE;
    01992                     he->p.str = origin;
    01993                     he->c = 1;
    01994                     xx = headerPut(psm->oh, he, 0);
    01995                     origin = _free(origin);
    01996                 }
    01997
    01998                 /* Copy upgrade chain link tags. */
    01999                 xx = hCopyTag(fi->h, psm->oh, RPMTAG_INSTALLTID);
    02000                 xx = hCopyTag(fi->h, psm->oh, RPMTAG_BLINKPKGID);
    02001                 xx = hCopyTag(fi->h, psm->oh, RPMTAG_BLINKHDRID);
    02002                 xx = hCopyTag(fi->h, psm->oh, RPMTAG_BLINKNEVRA);
    02003
    02004 assert(psm->te != NULL);
    02005                 xx = hSaveFlinks(psm->oh, &psm->te->flink);
    02006             }
    02007
    02008             /* Write the metadata section into the package. */
    02009             {   const char item[] = "Header";
    02010                 const char * msg = NULL;
    02011                 rc = rpmpkgWrite(item, psm->fd, psm->oh, &msg);
    02012                 if (rc != RPMRC_OK) {
    02013                     rpmlog(RPMLOG_ERR, "%s: %s: %s", psm->pkgfn, item,
    02014                         (msg && *msg ? msg : "write failed\n"));
    02015                     msg = _free(msg);
    02016                 }
    02017             }
    02018         }
    02019         break;
    02020     case PSM_PROCESS:
    02021         if (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST)        break;
    02022
    02023         if (psm->goal == PSM_PKGINSTALL) {
    02024
    02025             if (rpmtsFlags(ts) & RPMTRANS_FLAG_JUSTDB)  break;
    02026
    02027             /* XXX Synthesize callbacks for packages with no files. */
    02028             if (rpmfiFC(fi) <= 0) {
    02029                 void * ptr;
    02030                 ptr = rpmtsNotify(ts, fi->te, RPMCALLBACK_INST_START, 0, 100);
    02031                 ptr = rpmtsNotify(ts, fi->te, RPMCALLBACK_INST_PROGRESS, 100, 100);
    02032                 break;
    02033             }
    02034
    02035             /* Retrieve type of payload compression. */
    02036             rc = rpmpsmNext(psm, PSM_RPMIO_FLAGS);
    02037
    02038             if (rpmteFd(fi->te) == NULL) {      /* XXX can't happen */
    02039                 rc = RPMRC_FAIL;
    02040                 break;
    02041             }
    02042
    02043             /*@-nullpass@*/     /* LCL: fi->fd != NULL here. */
    02044             psm->cfd = Fdopen(fdDup(Fileno(rpmteFd(fi->te))), psm->rpmio_flags);
    02045             /*@=nullpass@*/
    02046             if (psm->cfd == NULL) {     /* XXX can't happen */
    02047                 rc = RPMRC_FAIL;
    02048                 break;
    02049             }
    02050
    02051             rc = fsmSetup(fi->fsm, FSM_PKGINSTALL, psm->payload_format, ts, fi,
    02052                         psm->cfd, NULL, &psm->failedFile);
    02053             (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_UNCOMPRESS),
    02054                         fdstat_op(psm->cfd, FDSTAT_READ));
    02055             (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_DIGEST),
    02056                         fdstat_op(psm->cfd, FDSTAT_DIGEST));
    02057             xx = fsmTeardown(fi->fsm);
    02058
    02059             saveerrno = errno; /* XXX FIXME: Fclose with libio destroys errno */
    02060             xx = Fclose(psm->cfd);
    02061             psm->cfd = NULL;
    02062             /*@-mods@*/
    02063             errno = saveerrno; /* XXX FIXME: Fclose with libio destroys errno */
    02064             /*@=mods@*/
    02065
    02066             if (!rc)
    02067                 rc = rpmpsmNext(psm, PSM_COMMIT);
    02068
    02069             /* XXX make sure progress is closed out */
    02070             psm->what = RPMCALLBACK_INST_PROGRESS;
    02071             psm->amount = (fi->archiveSize ? fi->archiveSize : 100);
    02072             psm->total = psm->amount;
    02073             xx = rpmpsmNext(psm, PSM_NOTIFY);
    02074
    02075             if (rc) {
    02076                 rpmlog(RPMLOG_ERR,
    02077                         _("unpacking of archive failed%s%s: %s\n"),
    02078                         (psm->failedFile != NULL ? _(" on file ") : ""),
    02079                         (psm->failedFile != NULL ? psm->failedFile : ""),
    02080                         cpioStrerror(rc));
    02081                 rc = RPMRC_FAIL;
    02082
    02083                 /* XXX notify callback on error. */
    02084                 psm->what = RPMCALLBACK_UNPACK_ERROR;
    02085                 psm->amount = 0;
    02086                 psm->total = 0;
    02087                 xx = rpmpsmNext(psm, PSM_NOTIFY);
    02088
    02089                 break;
    02090             }
    02091         }
    02092         if (psm->goal == PSM_PKGERASE) {
    02093             int fc = rpmfiFC(fi);
    02094
    02095             if (rpmtsFlags(ts) & RPMTRANS_FLAG_JUSTDB)  break;
    02096             if (rpmtsFlags(ts) & RPMTRANS_FLAG_APPLYONLY)       break;
    02097
    02098             psm->what = RPMCALLBACK_UNINST_START;
    02099             psm->amount = fc;
    02100             psm->total = (fc ? fc : 100);
    02101             xx = rpmpsmNext(psm, PSM_NOTIFY);
    02102
    02103             if (fc > 0) {
    02104                 rc = fsmSetup(fi->fsm, FSM_PKGERASE, psm->payload_format, ts, fi,
    02105                         NULL, NULL, &psm->failedFile);
    02106                 xx = fsmTeardown(fi->fsm);
    02107             }
    02108
    02109             psm->what = RPMCALLBACK_UNINST_STOP;
    02110             psm->amount = (fc ? fc : 100);
    02111             psm->total = (fc ? fc : 100);
    02112             xx = rpmpsmNext(psm, PSM_NOTIFY);
    02113
    02114         }
    02115         if (psm->goal == PSM_PKGSAVE) {
    02116             fileAction * actions = fi->actions;
    02117             fileAction action = fi->action;
    02118
    02119             fi->action = FA_COPYOUT;
    02120             fi->actions = NULL;
    02121
    02122             if (psm->fd == NULL) {      /* XXX can't happen */
    02123                 rc = RPMRC_FAIL;
    02124                 break;
    02125             }
    02126             /*@-nullpass@*/     /* FIX: fdDup mey return NULL. */
    02127             xx = Fflush(psm->fd);
    02128             psm->cfd = Fdopen(fdDup(Fileno(psm->fd)), psm->rpmio_flags);
    02129             /*@=nullpass@*/
    02130             if (psm->cfd == NULL) {     /* XXX can't happen */
    02131                 rc = RPMRC_FAIL;
    02132                 break;
    02133             }
    02134
    02135             rc = fsmSetup(fi->fsm, FSM_PKGBUILD, psm->payload_format, ts, fi,
    02136                         psm->cfd, NULL, &psm->failedFile);
    02137             (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_COMPRESS),
    02138                         fdstat_op(psm->cfd, FDSTAT_WRITE));
    02139             (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_DIGEST),
    02140                         fdstat_op(psm->cfd, FDSTAT_DIGEST));
    02141             xx = fsmTeardown(fi->fsm);
    02142
    02143             saveerrno = errno; /* XXX FIXME: Fclose with libio destroys errno */
    02144             xx = Fclose(psm->cfd);
    02145             psm->cfd = NULL;
    02146             /*@-mods@*/
    02147             errno = saveerrno;
    02148             /*@=mods@*/
    02149
    02150             /* XXX make sure progress is closed out */
    02151             psm->what = RPMCALLBACK_INST_PROGRESS;
    02152             psm->amount = (fi->archiveSize ? fi->archiveSize : 100);
    02153             psm->total = psm->amount;
    02154             xx = rpmpsmNext(psm, PSM_NOTIFY);
    02155
    02156             fi->action = action;
    02157             fi->actions = actions;
    02158         }
    02159         break;
    02160     case PSM_POST:
    02161         if (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST)        break;
    02162
    02163         if (psm->goal == PSM_PKGINSTALL) {
    02164
    02165             /*
    02166              * If this header has already been installed, remove it from
    02167              * the database before adding the new header.
    02168              */
    02169             if (fi->record && !(rpmtsFlags(ts) & RPMTRANS_FLAG_APPLYONLY)) {
    02170                 rc = rpmpsmNext(psm, PSM_RPMDB_REMOVE);
    02171                 if (rc) break;
    02172             }
    02173
    02174             /* Add fi->fstates to install header. */
    02175             xx = postPopulateInstallHeader(ts, psm->te, fi);
    02176
    02177             rc = rpmpsmNext(psm, PSM_RPMDB_ADD);
    02178             if (rc) break;
    02179
    02180             psm->scriptTag = RPMTAG_POSTIN;
    02181             psm->progTag = RPMTAG_POSTINPROG;
    02182             psm->sense = RPMSENSE_TRIGGERIN;
    02183             psm->countCorrection = 0;
    02184
    02185             if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOPOST)) {
    02186                 rc = rpmpsmNext(psm, PSM_SCRIPT);
    02187                 if (rc) break;
    02188             }
    02189             if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOTRIGGERIN)) {
    02190                 /* Run triggers in other package(s) this package sets off. */
    02191                 rc = rpmpsmNext(psm, PSM_TRIGGERS);
    02192                 if (rc) break;
    02193
    02194                 /* Run triggers in this package other package(s) set off. */
    02195                 rc = rpmpsmNext(psm, PSM_IMMED_TRIGGERS);
    02196                 if (rc) break;
    02197             }
    02198
    02199             if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_APPLYONLY))
    02200                 rc = markReplacedFiles(psm);
    02201
    02202         }
    02203         if (psm->goal == PSM_PKGERASE) {
    02204
    02205             psm->scriptTag = RPMTAG_POSTUN;
    02206             psm->progTag = RPMTAG_POSTUNPROG;
    02207             psm->sense = RPMSENSE_TRIGGERPOSTUN;
    02208             psm->countCorrection = -1;
    02209
    02210             if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOPOSTUN)) {
    02211                 rc = rpmpsmNext(psm, PSM_SCRIPT);
    02212                 if (rc) break;
    02213             }
    02214
    02215             if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOTRIGGERPOSTUN)) {
    02216                 /* Run triggers in other package(s) this package sets off. */
    02217                 rc = rpmpsmNext(psm, PSM_TRIGGERS);
    02218                 if (rc) break;
    02219
    02220                 /* Run triggers in this package other package(s) set off. */
    02221                 rc = rpmpsmNext(psm, PSM_IMMED_TRIGGERS);
    02222                 if (rc) break;
    02223             }
    02224
    02225             if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_APPLYONLY))
    02226                 rc = rpmpsmNext(psm, PSM_RPMDB_REMOVE);
    02227         }
    02228         if (psm->goal == PSM_PKGSAVE) {
    02229         }
    02230
    02231         /* Restore root directory if changed. */
    02232         xx = rpmpsmNext(psm, PSM_CHROOT_OUT);
    02233         break;
    02234     case PSM_UNDO:
    02235         break;
    02236     case PSM_FINI:
    02237         /* Restore root directory if changed. */
    02238         xx = rpmpsmNext(psm, PSM_CHROOT_OUT);
    02239
    02240         if (psm->fd != NULL) {
    02241             saveerrno = errno; /* XXX FIXME: Fclose with libio destroys errno */
    02242             xx = Fclose(psm->fd);
    02243             psm->fd = NULL;
    02244             /*@-mods@*/
    02245             errno = saveerrno;
    02246             /*@=mods@*/
    02247         }
    02248
    02249         if (psm->goal == PSM_PKGSAVE) {
    02250             if (!rc && ts && ts->notify == NULL) {
    02251                 rpmlog(RPMLOG_INFO, _("Wrote: %s\n"),
    02252                         (psm->pkgURL ? psm->pkgURL : "???"));
    02253             }
    02254         }
    02255
    02256         if (rc) {
    02257             if (psm->failedFile)
    02258                 rpmlog(RPMLOG_ERR,
    02259                         _("%s failed on file %s: %s\n"),
    02260                         psm->stepName, psm->failedFile, cpioStrerror(rc));
    02261             else
    02262                 rpmlog(RPMLOG_ERR, _("%s failed: %s\n"),
    02263                         psm->stepName, cpioStrerror(rc));
    02264
    02265             /* XXX notify callback on error. */
    02266             psm->what = RPMCALLBACK_CPIO_ERROR;
    02267             psm->amount = 0;
    02268             psm->total = 0;
    02269             /*@-nullstate@*/ /* FIX: psm->fd may be NULL. */
    02270             xx = rpmpsmNext(psm, PSM_NOTIFY);
    02271             /*@=nullstate@*/
    02272         }
    02273
    02274         if (psm->goal == PSM_PKGERASE || psm->goal == PSM_PKGSAVE) {
    02275 #ifdef  DYING
    02276 if (psm->te != NULL)
    02277 if (psm->te->h != NULL)
    02278 psm->te->h = headerFree(psm->te->h);
    02279 #else
    02280             if (psm->te != NULL)
    02281                 (void) rpmteSetHeader(psm->te, NULL);
    02282 #endif
    02283             if (fi->h != NULL)
    02284                 fi->h = headerFree(fi->h);
    02285         }
    02286         psm->oh = headerFree(psm->oh);
    02287         psm->pkgURL = _free(psm->pkgURL);
    02288         psm->rpmio_flags = _free(psm->rpmio_flags);
    02289         psm->payload_format = _free(psm->payload_format);
    02290         psm->failedFile = _free(psm->failedFile);
    02291
    02292         fi->fgroup = _free(fi->fgroup);
    02293         fi->fuser = _free(fi->fuser);
    02294         fi->apath = _free(fi->apath);
    02295         fi->fstates = _free(fi->fstates);
    02296         break;
    02297
    02298     case PSM_PKGINSTALL:
    02299     case PSM_PKGERASE:
    02300     case PSM_PKGSAVE:
    02301         psm->goal = stage;
    02302         psm->rc = RPMRC_OK;
    02303         psm->stepName = pkgStageString(stage);
    02304
    02305         rc = rpmpsmNext(psm, PSM_INIT);
    02306         if (!rc) rc = rpmpsmNext(psm, PSM_PRE);
    02307         if (!rc) rc = rpmpsmNext(psm, PSM_PROCESS);
    02308         if (!rc) rc = rpmpsmNext(psm, PSM_POST);
    02309         xx = rpmpsmNext(psm, PSM_FINI);
    02310         break;
    02311     case PSM_PKGCOMMIT:
    02312         break;
    02313
    02314     case PSM_CREATE:
    02315         break;
    02316     case PSM_NOTIFY:
    02317     {   void * ptr;
    02318 /*@-nullpass@*/ /* FIX: psm->te may be NULL */
    02319         ptr = rpmtsNotify(ts, psm->te, psm->what, psm->amount, psm->total);
    02320 /*@-nullpass@*/
    02321     }   break;
    02322     case PSM_DESTROY:
    02323         break;
    02324     case PSM_COMMIT:
    02325         if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_PKGCOMMIT)) break;
    02326         if (rpmtsFlags(ts) & RPMTRANS_FLAG_APPLYONLY) break;
    02327
    02328         rc = fsmSetup(fi->fsm, FSM_PKGCOMMIT, psm->payload_format, ts, fi,
    02329                         NULL, NULL, &psm->failedFile);
    02330         xx = fsmTeardown(fi->fsm);
    02331         break;
    02332
    02333     case PSM_CHROOT_IN:
    02334     {   const char * rootDir = rpmtsRootDir(ts);
    02335         /* Change root directory if requested and not already done. */
    02336         if (rootDir != NULL && !(rootDir[0] == '/' && rootDir[1] == '\0')
    02337          && !rpmtsChrootDone(ts) && !psm->chrootDone)
    02338         {
    02339             static int _pw_loaded = 0;
    02340             static int _gr_loaded = 0;
    02341
    02342             if (!_pw_loaded) {
    02343                 (void)getpwnam("root");
    02344                 endpwent();
    02345                 _pw_loaded++;
    02346             }
    02347             if (!_gr_loaded) {
    02348                 (void)getgrnam("root");
    02349                 endgrent();
    02350                 _gr_loaded++;
    02351             }
    02352
    02353             xx = Chdir("/");
    02354             /*@-modobserver@*/
    02355             if (rootDir != NULL && strcmp(rootDir, "/") && *rootDir == '/')
    02356                 rc = Chroot(rootDir);
    02357             /*@=modobserver@*/
    02358             psm->chrootDone = 1;
    02359             (void) rpmtsSetChrootDone(ts, 1);
    02360         }
    02361     }   break;
    02362     case PSM_CHROOT_OUT:
    02363         /* Restore root directory if changed. */
    02364         if (psm->chrootDone) {
    02365             const char * rootDir = rpmtsRootDir(ts);
    02366             const char * currDir = rpmtsCurrDir(ts);
    02367             /*@-modobserver@*/
    02368             if (rootDir != NULL && strcmp(rootDir, "/") && *rootDir == '/')
    02369                 rc = Chroot(".");
    02370             /*@=modobserver@*/
    02371             psm->chrootDone = 0;
    02372             (void) rpmtsSetChrootDone(ts, 0);
    02373             if (currDir != NULL)        /* XXX can't happen */
    02374                 xx = Chdir(currDir);
    02375         }
    02376         break;
    02377     case PSM_SCRIPT:    /* Run current package scriptlets. */
    02378         rc = runInstScript(psm);
    02379         break;
    02380     case PSM_TRIGGERS:
    02381         /* Run triggers in other package(s) this package sets off. */
    02382         if (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST)        break;
    02383         rc = runTriggers(psm);
    02384         break;
    02385     case PSM_IMMED_TRIGGERS:
    02386         /* Run triggers in this package other package(s) set off. */
    02387         if (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST)        break;
    02388         rc = runImmedTriggers(psm);
    02389         break;
    02390
    02391     case PSM_RPMIO_FLAGS:
    02392     {   const char * payload_compressor = NULL;
    02393         const char * payload_format = NULL;
    02394         char * t;
    02395
    02396         he->tag = RPMTAG_PAYLOADCOMPRESSOR;
    02397         xx = headerGet(fi->h, he, 0);
    02398         payload_compressor = he->p.str;
    02399         if (payload_compressor == NULL)
    02400             payload_compressor = xstrdup("gzip");
    02401
    02402         psm->rpmio_flags = t = xmalloc(sizeof("w9.gzdio"));
    02403         *t = '\0';
    02404         t = stpcpy(t, ((psm->goal == PSM_PKGSAVE) ? "w9" : "r"));
    02405         if (!strcmp(payload_compressor, "gzip"))
    02406             t = stpcpy(t, ".gzdio");
    02407         if (!strcmp(payload_compressor, "bzip2"))
    02408             t = stpcpy(t, ".bzdio");
    02409         if (!strcmp(payload_compressor, "lzma"))
    02410             t = stpcpy(t, ".lzdio");
    02411         payload_compressor = _free(payload_compressor);
    02412
    02413         he->tag = RPMTAG_PAYLOADFORMAT;
    02414         xx = headerGet(fi->h, he, 0);
    02415         payload_format = he->p.str;
    02416         if (!xx || payload_format == NULL
    02417          || !(!strcmp(payload_format, "tar") || !strcmp(payload_format, "ustar"))) {
    02418             payload_format = _free(payload_format);
    02419             payload_format = xstrdup("cpio");
    02420         }
    02421         psm->payload_format = _free(psm->payload_format);
    02422         psm->payload_format = payload_format;
    02423         rc = RPMRC_OK;
    02424     }   break;
    02425
    02426     case PSM_RPMDB_LOAD:
    02427 assert(psm->mi == NULL);
    02428         psm->mi = rpmtsInitIterator(ts, RPMDBI_PACKAGES,
    02429                                 &fi->record, sizeof(fi->record));
    02430         fi->h = rpmdbNextIterator(psm->mi);
    02431         if (fi->h != NULL)
    02432             fi->h = headerLink(fi->h);
    02433         psm->mi = rpmdbFreeIterator(psm->mi);
    02434
    02435         if (fi->h != NULL) {
    02436             (void) headerSetInstance(fi->h, fi->record);
    02437             rc = RPMRC_OK;
    02438         } else
    02439             rc = RPMRC_FAIL;
    02440         break;
    02441     case PSM_RPMDB_ADD:
    02442         if (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST)        break;
    02443         if (fi->isSource)       break;  /* XXX never add SRPM's */
    02444         if (fi->h == NULL)      break;  /* XXX can't happen */
    02445
    02446         /* Add header to db, doing header check if requested */
    02447         /* XXX rollback headers propagate the previous transaction id. */
    02448         {   uint32_t tid = ((rpmtsType(ts) == RPMTRANS_TYPE_ROLLBACK)
    02449                 ? hLoadTID(fi->h, RPMTAG_INSTALLTID) : rpmtsGetTid(ts));
    02450             (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DBADD), 0);
    02451             if (!(rpmtsVSFlags(ts) & RPMVSF_NOHDRCHK))
    02452                 rc = rpmdbAdd(rpmtsGetRdb(ts), tid, fi->h, ts);
    02453             else
    02454                 rc = rpmdbAdd(rpmtsGetRdb(ts), tid, fi->h, NULL);
    02455             (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DBADD), 0);
    02456         }
    02457
    02458         if (rc != RPMRC_OK) break;
    02459
    02460 assert(psm->te != NULL);
    02461         /* Mark non-rollback elements as installed. */
    02462         if (rpmtsType(ts) != RPMTRANS_TYPE_ROLLBACK)
    02463             psm->te->installed = 1;
    02464
    02465         /* Set the database instance for (possible) rollbacks. */
    02466         rpmteSetDBInstance(psm->te, headerGetInstance(fi->h));
    02467
    02468         break;
    02469     case PSM_RPMDB_REMOVE:
    02470     {
    02471         if (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST)        break;
    02472
    02473         (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DBREMOVE), 0);
    02474         rc = rpmdbRemove(rpmtsGetRdb(ts), rpmtsGetTid(ts), fi->record, NULL);
    02475         (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DBREMOVE), 0);
    02476
    02477         if (rc != RPMRC_OK) break;
    02478
    02479         /* Forget the offset of a successfully removed header. */
    02480         if (psm->te != NULL)    /* XXX can't happen */
    02481             psm->te->u.removed.dboffset = 0;
    02482
    02483     }   break;
    02484
    02485     default:
    02486         break;
    02487 /*@i@*/    }
    02488
    02489 /*@-nullstate@*/        /* FIX: psm->oh and psm->fi->h may be NULL. */
    02490     return rc;
    02491 /*@=nullstate@*/
    02492 }
    02493 /*@=nullpass@*/