Main Page | Modules | Data Structures | File List | Data Fields | Globals | Related Pages

lib/psm.c

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

Generated on Sat Oct 1 16:24:14 2011 for rpm by  doxygen 1.4.4