• 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         if (!strcmp(payload_compressor, "xz"))
02412             t = stpcpy(t, ".xzdio");
02413         payload_compressor = _free(payload_compressor);
02414 
02415         he->tag = RPMTAG_PAYLOADFORMAT;
02416         xx = headerGet(fi->h, he, 0);
02417         payload_format = he->p.str;
02418         if (!xx || payload_format == NULL
02419          || !(!strcmp(payload_format, "tar") || !strcmp(payload_format, "ustar"))) {
02420             payload_format = _free(payload_format);
02421             payload_format = xstrdup("cpio");
02422         }
02423         psm->payload_format = _free(psm->payload_format);
02424         psm->payload_format = payload_format;
02425         rc = RPMRC_OK;
02426     }   break;
02427 
02428     case PSM_RPMDB_LOAD:
02429 assert(psm->mi == NULL);
02430         psm->mi = rpmtsInitIterator(ts, RPMDBI_PACKAGES,
02431                                 &fi->record, sizeof(fi->record));
02432         fi->h = rpmdbNextIterator(psm->mi);
02433         if (fi->h != NULL)
02434             fi->h = headerLink(fi->h);
02435         psm->mi = rpmdbFreeIterator(psm->mi);
02436 
02437         if (fi->h != NULL) {
02438             (void) headerSetInstance(fi->h, fi->record);
02439             rc = RPMRC_OK;
02440         } else
02441             rc = RPMRC_FAIL;
02442         break;
02443     case PSM_RPMDB_ADD:
02444         if (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST)        break;
02445         if (fi->isSource)       break;  /* XXX never add SRPM's */
02446         if (fi->h == NULL)      break;  /* XXX can't happen */
02447 
02448         /* Add header to db, doing header check if requested */
02449         /* XXX rollback headers propagate the previous transaction id. */
02450         {   uint32_t tid = ((rpmtsType(ts) == RPMTRANS_TYPE_ROLLBACK)
02451                 ? hLoadTID(fi->h, RPMTAG_INSTALLTID) : rpmtsGetTid(ts));
02452             (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DBADD), 0);
02453             if (!(rpmtsVSFlags(ts) & RPMVSF_NOHDRCHK))
02454                 rc = rpmdbAdd(rpmtsGetRdb(ts), tid, fi->h, ts);
02455             else
02456                 rc = rpmdbAdd(rpmtsGetRdb(ts), tid, fi->h, NULL);
02457             (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DBADD), 0);
02458         }
02459 
02460         if (rc != RPMRC_OK) break;
02461 
02462 assert(psm->te != NULL);
02463         /* Mark non-rollback elements as installed. */
02464         if (rpmtsType(ts) != RPMTRANS_TYPE_ROLLBACK)
02465             psm->te->installed = 1;
02466 
02467         /* Set the database instance for (possible) rollbacks. */
02468         rpmteSetDBInstance(psm->te, headerGetInstance(fi->h));
02469 
02470         break;
02471     case PSM_RPMDB_REMOVE:
02472     {   
02473         if (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST)        break;
02474 
02475         (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DBREMOVE), 0);
02476         rc = rpmdbRemove(rpmtsGetRdb(ts), rpmtsGetTid(ts), fi->record, NULL);
02477         (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DBREMOVE), 0);
02478 
02479         if (rc != RPMRC_OK) break;
02480 
02481         /* Forget the offset of a successfully removed header. */
02482         if (psm->te != NULL)    /* XXX can't happen */
02483             psm->te->u.removed.dboffset = 0;
02484 
02485     }   break;
02486 
02487     default:
02488         break;
02489 /*@i@*/    }
02490 
02491 /*@-nullstate@*/        /* FIX: psm->oh and psm->fi->h may be NULL. */
02492     return rc;
02493 /*@=nullstate@*/
02494 }
02495 /*@=nullpass@*/

Generated on Mon Nov 29 2010 05:18:43 for rpm by  doxygen 1.7.2