• 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 #define _MIRE_INTERNAL  /* XXX mireApply doesn't tell which pattern matched. */
00009 
00010 #include <rpmio_internal.h>     /* XXX FDSTAT_READ */
00011 #include <rpmcb.h>              /* XXX fnpyKey */
00012 #include <rpmmacro.h>
00013 #include <rpmurl.h>
00014 
00015 #include <rpmficl.h>
00016 #include <rpmjs.h>
00017 #include <rpmlua.h>
00018 #include <rpmperl.h>
00019 #include <rpmpython.h>
00020 #include <rpmruby.h>
00021 #include <rpmtcl.h>
00022 
00023 #include <rpmtag.h>
00024 #include <rpmtypes.h>
00025 #include <rpmlib.h>
00026 
00027 #define _RPMFI_INTERNAL
00028 #include "rpmfi.h"
00029 #include "fsm.h"                /* XXX CPIO_FOO/IOSM_FOO constants */
00030 #define _RPMSQ_INTERNAL
00031 #include "psm.h"
00032 #define F_ISSET(_psm, _FLAG)    ((_psm)->flags & (RPMPSM_FLAGS_##_FLAG))
00033 #define F_SET(_psm, _FLAG)      ((_psm)->flags |=  (RPMPSM_FLAGS_##_FLAG))
00034 #define F_CLR(_psm, _FLAG)      ((_psm)->flags &= ~(RPMPSM_FLAGS_##_FLAG))
00035 
00036 #define _RPMEVR_INTERNAL
00037 #include "rpmds.h"
00038 
00039 #define _RPMTE_INTERNAL
00040 #include "rpmte.h"
00041 
00042 #define _RPMTS_INTERNAL         /* XXX ts->notify */
00043 #include "rpmts.h"
00044 
00045 #include <pkgio.h>
00046 #include "misc.h"               /* XXX rpmMkdirPath, makeTempFile, doputenv */
00047 #include "rpmdb.h"              /* XXX for db_chrootDone */
00048 #include "signature.h"          /* signature constants */
00049 
00050 #include <rpmcli.h>
00051 
00052 #include "debug.h"
00053 
00054 #define _PSM_DEBUG      0
00055 /*@unchecked@*/
00056 int _psm_debug = _PSM_DEBUG;
00057 /*@unchecked@*/
00058 int _psm_threads = 0;
00059 
00060 /*@access FD_t @*/              /* XXX void * arg */
00061 /*@access Header @*/            /* XXX void * arg */
00062 /*@access miRE @*/
00063 
00064 /*@access rpmpsm @*/
00065 
00066 /*@access rpmfi @*/
00067 /*@access rpmte @*/     /* XXX rpmInstallSourcePackage */
00068 /*@access rpmts @*/     /* XXX ts->notify */
00069 
00070 /*@access rpmluav @*/
00071 
00077 static rpmRC markReplacedFiles(const rpmpsm psm)
00078         /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
00079         /*@modifies psm, rpmGlobalMacroContext, fileSystem, internalState @*/
00080 {
00081     HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
00082     const rpmts ts = psm->ts;
00083     rpmte te = psm->te;
00084     rpmfi fi = psm->fi;
00085     sharedFileInfo replaced = (te ? te->replaced : NULL);
00086     sharedFileInfo sfi;
00087     rpmmi mi;
00088     Header h;
00089     int * offsets;
00090     rpmuint32_t prev;
00091     int num;
00092     int xx;
00093 
00094     if (!(rpmfiFC(fi) > 0 && replaced != NULL))
00095         return RPMRC_OK;
00096 
00097     num = prev = 0;
00098     for (sfi = replaced; sfi->otherPkg; sfi++) {
00099         if (prev && prev == sfi->otherPkg)
00100             continue;
00101         prev = sfi->otherPkg;
00102         num++;
00103     }
00104     if (num == 0)
00105         return RPMRC_OK;
00106 
00107     offsets = alloca(num * sizeof(*offsets));
00108     offsets[0] = 0;
00109     num = prev = 0;
00110     for (sfi = replaced; sfi->otherPkg; sfi++) {
00111         if (prev && prev == sfi->otherPkg)
00112             continue;
00113         prev = sfi->otherPkg;
00114         offsets[num++] = sfi->otherPkg;
00115     }
00116 
00117     mi = rpmtsInitIterator(ts, RPMDBI_PACKAGES, NULL, 0);
00118     xx = rpmmiGrow(mi, offsets, num);
00119     xx = rpmmiSetRewrite(mi, 1);
00120 
00121     sfi = replaced;
00122     while ((h = rpmmiNext(mi)) != NULL) {
00123         int modified;
00124 
00125         modified = 0;
00126 
00127         /* XXX FIXME: not correct yet, but headerGetEntry needs to die now! */
00128         he->tag = RPMTAG_FILESTATES;
00129         xx = headerGet(h, he, 0);
00130         if (!xx)
00131             continue;
00132         
00133         prev = rpmmiInstance(mi);
00134         num = 0;
00135         while (sfi->otherPkg && sfi->otherPkg == prev) {
00136 assert(sfi->otherFileNum < he->c);
00137             if (he->p.ui8p[sfi->otherFileNum] != RPMFILE_STATE_REPLACED) {
00138                 he->p.ui8p[sfi->otherFileNum] = RPMFILE_STATE_REPLACED;
00139                 if (modified == 0) {
00140                     /* Modified header will be rewritten. */
00141                     modified = 1;
00142                     xx = rpmmiSetModified(mi, modified);
00143                 }
00144                 num++;
00145             }
00146             sfi++;
00147         }
00148         he->p.ptr = _free(he->p.ptr);
00149     }
00150     mi = rpmmiFree(mi);
00151 
00152     return RPMRC_OK;
00153 }
00154 
00155 #if defined(RPM_VENDOR_OPENPKG) /* switch-from-susr-to-musr-on-srpm-install */
00156 static rpmRC createDir(rpmfi fi, rpmts ts, const char ** fn, const char * name)
00157 #else
00158 static rpmRC createDir(rpmts ts, const char ** fn, const char * name)
00159 #endif
00160         /*@globals rpmGlobalMacroContext @*/
00161         /*@modifies *fn, rpmGlobalMacroContext @*/
00162 {
00163     const char * N = rpmGenPath(rpmtsRootDir(ts), name, "");
00164     char * t = xstrdup(name+2);
00165     rpmRC rc;
00166 
00167     t[strlen(t)-1] = '\0';
00168 
00169     if(fn) *fn = N;
00170 
00171     rc = rpmMkdirPath(N, t+1);
00172     if (rc != RPMRC_OK) {
00173         if (Access(N, W_OK))
00174             rpmlog(RPMLOG_ERR, _("cannot write to %%%s %s\n"), t, N);
00175 #if defined(RPM_VENDOR_OPENPKG) /* switch-from-susr-to-musr-on-srpm-install */
00176         else
00177             Chown(N, fi->uid, fi->gid);
00178 #endif
00179     }
00180     t = _free(t);
00181     return rc;
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 /*@-assignexpose -castexpose @*/
00204     psm->ts = rpmtsLink(ts, "InstallSourcePackage");
00205 /*@=assignexpose =castexpose @*/
00206 
00207 /*@-mods@*/     /* Avoid void * _fd annotations for now. */
00208     rpmrc = rpmReadPackageFile(ts, fd, "InstallSourcePackage", &h);
00209 /*@=mods@*/
00210     switch (rpmrc) {
00211     case RPMRC_NOTTRUSTED:
00212     case RPMRC_NOKEY:
00213     case RPMRC_OK:
00214         break;
00215     default:
00216         goto exit;
00217         /*@notreached@*/ break;
00218     }
00219     if (h == NULL)
00220         goto exit;
00221 
00222     rpmrc = RPMRC_OK;
00223 
00224     isSource =
00225         (headerIsEntry(h, RPMTAG_SOURCERPM) == 0 &&
00226          headerIsEntry(h, RPMTAG_ARCH) != 0);
00227 
00228     if (!isSource) {
00229         rpmlog(RPMLOG_ERR, _("source package expected, binary found\n"));
00230         rpmrc = RPMRC_FAIL;
00231         goto exit;
00232     }
00233 
00234     (void) rpmtsAddInstallElement(ts, h, NULL, 0, NULL);
00235 
00236     fi = rpmfiNew(ts, h, RPMTAG_BASENAMES, scareMem);
00237     fi->h = headerLink(h);
00238     (void)headerFree(h);
00239     h = NULL;
00240 
00241     if (fi == NULL) {   /* XXX can't happen */
00242         rpmrc = RPMRC_FAIL;
00243         goto exit;
00244     }
00245 
00246 /*@-onlytrans@*/        /* FIX: te reference */
00247     fi->te = rpmtsElement(ts, 0);
00248 /*@=onlytrans@*/
00249     if (fi->te == NULL) {       /* XXX can't happen */
00250         rpmrc = RPMRC_FAIL;
00251         goto exit;
00252     }
00253 
00254 assert(fi->h != NULL);
00255 assert(((rpmte)fi->te)->h == NULL);     /* XXX headerFree side effect */
00256     (void) rpmteSetHeader(fi->te, fi->h);
00257 /*@-mods@*/     /* LCL: avoid void * _fd annotation for now. */
00258 /*@-assignexpose -castexpose -temptrans @*/
00259     ((rpmte)fi->te)->fd = fdLink(fd, "installSourcePackage");
00260 /*@=assignexpose =castexpose =temptrans @*/
00261 /*@=mods@*/
00262 
00263     (void) headerMacrosLoad(fi->h);
00264 
00265     psm->fi = rpmfiLink(fi, NULL);
00266     /*@-assignexpose -usereleased @*/
00267     psm->te = fi->te;
00268     /*@=assignexpose =usereleased @*/
00269 
00270     if (cookie) {
00271         *cookie = NULL;
00272         he->tag = RPMTAG_COOKIE;
00273         xx = headerGet(fi->h, he, 0);
00274         *cookie = he->p.str;
00275     }
00276 
00277     /* XXX FIXME: don't do per-file mapping, force global flags. */
00278     fi->fmapflags = _free(fi->fmapflags);
00279     fi->mapflags = IOSM_MAP_PATH | IOSM_MAP_MODE | IOSM_MAP_UID | IOSM_MAP_GID;
00280 
00281     fi->uid = getuid();
00282     fi->gid = getgid();
00283 #if defined(RPM_VENDOR_OPENPKG) /* switch-from-susr-to-musr-on-srpm-install */
00284     /* If running as the OpenPKG "susr", do not unpack source RPM
00285        packages with "susr" file ownerships as the OpenPKG Set-UID
00286        wrapper switches from "musr" to "susr" on "openpkg rpm -Uvh
00287        *.src.rpm". As a result the installed files could be never
00288        removed again by "musr". It is more consistent to always unpack
00289        as "musr" if possible. */
00290     if (fi->uid == 0) {
00291         char *muid_str;
00292         char *mgid_str;
00293         uid_t muid;
00294         gid_t mgid;
00295         if ((muid_str = rpmExpand("%{l_muid}", NULL)) != NULL)
00296             if ((muid = (uid_t)strtol(muid_str, (char **)NULL, 10)) > 0)
00297                 fi->uid = muid;
00298         if ((mgid_str = rpmExpand("%{l_mgid}", NULL)) != NULL)
00299             if ((mgid = (gid_t)strtol(mgid_str, (char **)NULL, 10)) > 0)
00300                 fi->gid = mgid;
00301     }
00302 #endif
00303     fi->astriplen = 0;
00304     fi->striplen = 0;
00305 
00306     for (i = 0; i < (int)fi->fc; i++)
00307         fi->actions[i] = FA_CREATE;
00308 
00309     i = fi->fc;
00310 
00311     if (fi->h != NULL) {        /* XXX can't happen */
00312         he->tag = RPMTAG_FILEPATHS;
00313         xx = headerGet(fi->h, he, 0);
00314         fi->apath = he->p.argv;
00315 
00316         if (headerIsEntry(fi->h, RPMTAG_COOKIE))
00317             for (i = 0; i < (int)fi->fc; i++)
00318                 if (fi->fflags[i] & RPMFILE_SPECFILE) break;
00319     }
00320 
00321     if (i == (int)fi->fc) {
00322         /* Find the spec file by name. */
00323         for (i = 0; i < (int)fi->fc; i++) {
00324             const char * t = fi->apath[i];
00325             t += strlen(fi->apath[i]) - 5;
00326             if (!strcmp(t, ".spec")) break;
00327         }
00328     }
00329 
00330 #if defined(RPM_VENDOR_OPENPKG) /* switch-from-susr-to-musr-on-srpm-install */
00331     if(createDir(fi, ts, NULL, "%{_topdir}") ||
00332             createDir(fi, ts, NULL, "%{_builddir}") ||
00333             createDir(fi, ts, NULL, "%{_rpmdir}") ||
00334             createDir(fi, ts, NULL, "%{_srcrpmdir}") ||
00335             createDir(fi, ts, &_sourcedir, "%{_sourcedir}") ||
00336             createDir(fi, ts, &_specdir, "%{_specdir}"))
00337 #else
00338     if(createDir(ts, NULL, "%{_topdir}") ||
00339             createDir(ts, NULL, "%{_builddir}") ||
00340             createDir(ts, NULL, "%{_rpmdir}") ||
00341             createDir(ts, NULL, "%{_srcrpmdir}") ||
00342             createDir(ts, &_sourcedir, "%{_sourcedir}") ||
00343             createDir(ts, &_specdir, "%{_specdir}"))
00344 #endif
00345         goto exit;
00346 
00347     /* Build dnl/dil with {_sourcedir, _specdir} as values. */
00348     if (i < (int)fi->fc) {
00349         size_t speclen = strlen(_specdir) + 2;
00350         size_t sourcelen = strlen(_sourcedir) + 2;
00351         char * t;
00352 
00353 /*@i@*/ fi->dnl = _free(fi->dnl);
00354 
00355         fi->dc = 2;
00356         fi->dnl = xmalloc(fi->dc * sizeof(*fi->dnl)
00357                         + fi->fc * sizeof(*fi->dil)
00358                         + speclen + sourcelen);
00359         /*@-dependenttrans@*/
00360         fi->dil = (unsigned int *)(fi->dnl + fi->dc);
00361         /*@=dependenttrans@*/
00362         memset(fi->dil, 0, fi->fc * sizeof(*fi->dil));
00363         fi->dil[i] = 1;
00364         /*@-dependenttrans@*/
00365         fi->dnl[0] = t = (char *)(fi->dil + fi->fc);
00366         fi->dnl[1] = t = stpcpy( stpcpy(t, _sourcedir), "/") + 1;
00367         /*@=dependenttrans@*/
00368         (void) stpcpy( stpcpy(t, _specdir), "/");
00369 
00370         t = xmalloc(speclen + strlen(fi->bnl[i]) + 1);
00371         (void) stpcpy( stpcpy( stpcpy(t, _specdir), "/"), fi->bnl[i]);
00372         specFile = t;
00373     } else {
00374         rpmlog(RPMLOG_ERR, _("source package contains no .spec file\n"));
00375         rpmrc = RPMRC_FAIL;
00376         goto exit;
00377     }
00378 
00379     psm->goal = PSM_PKGINSTALL;
00380 
00381     /*@-compmempass@*/  /* FIX: psm->fi->dnl should be owned. */
00382     rpmrc = rpmpsmStage(psm, PSM_PROCESS);
00383 
00384     (void) rpmpsmStage(psm, PSM_FINI);
00385     /*@=compmempass@*/
00386 
00387     if (rpmrc) rpmrc = RPMRC_FAIL;
00388 
00389 exit:
00390     if (specFilePtr && specFile && rpmrc == RPMRC_OK)
00391         *specFilePtr = specFile;
00392     else
00393         specFile = _free(specFile);
00394 
00395     _specdir = _free(_specdir);
00396     _sourcedir = _free(_sourcedir);
00397 
00398     psm->fi = rpmfiFree(psm->fi);
00399     psm->te = NULL;
00400 
00401     if (h != NULL) (void)headerFree(h);
00402     h = NULL;
00403 
00404     if (fi != NULL) {
00405         (void) rpmteSetHeader(fi->te, NULL);
00406 /*@-mods@*/     /* Avoid void * _fd annotations for now. */
00407         if (((rpmte)fi->te)->fd != NULL)
00408             (void) Fclose(((rpmte)fi->te)->fd);
00409 /*@=mods@*/
00410         ((rpmte)fi->te)->fd = NULL;
00411         fi->te = NULL;
00412 #if 0
00413         fi = rpmfiFree(fi);
00414 #endif
00415     }
00416 
00417     /* XXX nuke the added package(s). */
00418     rpmtsClean(ts);
00419 
00420     (void)rpmtsFree(psm->ts); 
00421     psm->ts = NULL;
00422 
00423     return rpmrc;
00424 }
00425 
00426 /*@observer@*/ /*@unchecked@*/
00427 static char * SCRIPT_PATH = "PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin";
00428 
00434 static /*@observer@*/ const char * tag2sln(rpmTag tag)
00435         /*@*/
00436 {
00437     switch (tag) {
00438     case RPMTAG_PRETRANS:       return "%pretrans";
00439     case RPMTAG_TRIGGERPREIN:   return "%triggerprein";
00440     case RPMTAG_PREIN:          return "%pre";
00441     case RPMTAG_POSTIN:         return "%post";
00442     case RPMTAG_TRIGGERIN:      return "%triggerin";
00443     case RPMTAG_TRIGGERUN:      return "%triggerun";
00444     case RPMTAG_PREUN:          return "%preun";
00445     case RPMTAG_POSTUN:         return "%postun";
00446     case RPMTAG_POSTTRANS:      return "%posttrans";
00447     case RPMTAG_TRIGGERPOSTUN:  return "%triggerpostun";
00448     case RPMTAG_VERIFYSCRIPT:   return "%verify";
00449     case RPMTAG_SANITYCHECK:    return "%sanitycheck";
00450     default:    break;
00451     }
00452     return "%unknownscript";
00453 }
00454 
00460 static rpmScriptID tag2slx(rpmTag tag)
00461         /*@*/
00462 {
00463     switch (tag) {
00464     case RPMTAG_PRETRANS:       return RPMSCRIPT_PRETRANS;
00465     case RPMTAG_TRIGGERPREIN:   return RPMSCRIPT_TRIGGERPREIN;
00466     case RPMTAG_PREIN:          return RPMSCRIPT_PREIN;
00467     case RPMTAG_POSTIN:         return RPMSCRIPT_POSTIN;
00468     case RPMTAG_TRIGGERIN:      return RPMSCRIPT_TRIGGERIN;
00469     case RPMTAG_TRIGGERUN:      return RPMSCRIPT_TRIGGERUN;
00470     case RPMTAG_PREUN:          return RPMSCRIPT_PREUN;
00471     case RPMTAG_POSTUN:         return RPMSCRIPT_POSTUN;
00472     case RPMTAG_POSTTRANS:      return RPMSCRIPT_POSTTRANS;
00473     case RPMTAG_TRIGGERPOSTUN:  return RPMSCRIPT_TRIGGERPOSTUN;
00474     case RPMTAG_VERIFYSCRIPT:   return RPMSCRIPT_VERIFY;
00475     case RPMTAG_SANITYCHECK:    return RPMSCRIPT_SANITYCHECK;
00476     default:    break;
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 
00525 static rpmRC runLuaScript(rpmpsm psm, const char * sln, HE_t Phe,
00526                    const char *script, int arg1, int arg2)
00527         /*@globals h_errno, fileSystem, internalState @*/
00528         /*@modifies psm, fileSystem, internalState @*/
00529 {
00530     rpmRC rc = RPMRC_OK;
00531     int xx;
00532     rpmlua lua = NULL;  /* Global state. */
00533     rpmluav var;
00534 
00535     /* Create arg variable */
00536     rpmluaPushTable(lua, "arg");
00537     var = rpmluavNew();
00538     rpmluavSetListMode(var, 1);
00539 /*@+relaxtypes@*/
00540     if (Phe->p.argv) {
00541         int i;
00542         for (i = 0; i < (int)Phe->c && Phe->p.argv[i]; i++) {
00543             rpmluavSetValue(var, RPMLUAV_STRING, Phe->p.argv[i]);
00544             rpmluaSetVar(lua, var);
00545         }
00546     }
00547     if (arg1 >= 0) {
00548         rpmluavSetValueNum(var, arg1);
00549         rpmluaSetVar(lua, var);
00550     }
00551     if (arg2 >= 0) {
00552         rpmluavSetValueNum(var, arg2);
00553         rpmluaSetVar(lua, var);
00554     }
00555 /*@=relaxtypes@*/
00556 /*@-moduncon@*/
00557     var = rpmluavFree(var);
00558 /*@=moduncon@*/
00559     rpmluaPop(lua);
00560 
00561     {   char buf[BUFSIZ];
00562         xx = snprintf(buf, BUFSIZ, "%s(%s)", sln, psm->NVRA);
00563         xx = rpmluaRunScript(lua, script, buf);
00564         if (xx == -1) {
00565             void * ptr = rpmtsNotify(psm->ts, psm->te, RPMCALLBACK_SCRIPT_ERROR,
00566                                  psm->scriptTag, 1);
00567             ptr = ptr;  /* XXX keep gcc happy. */
00568             rc = RPMRC_FAIL;
00569         } else
00570             rc = RPMRC_OK;
00571     }
00572     rpmluaDelVar(lua, "arg");
00573 
00574     return rc;
00575 }
00576 #endif  /* WITH_LUA */
00577 
00578 #if defined(WITH_LUA) || defined(WITH_FICL) || defined(WITH_JS) || defined(WITH_PERLEMBED) || defined(WITH_PYTHONEMBED) || defined(WITH_RUBYEMBED) || defined(WITH_TCL)
00579 static int enterChroot(rpmpsm psm, int * fdnop)
00580         /*@globals fileSystem, internalState @*/
00581         /*@modifies *fdnop, fileSystem, internalState @*/
00582 {
00583     const rpmts ts = psm->ts;
00584     int inChroot;
00585     int xx;
00586 
00587     /* Save the current working directory. */
00588     if (fdnop)
00589         (*fdnop) = open(".", O_RDONLY, 0);
00590 
00591     /* Get into the chroot. */
00592     if (!rpmtsChrootDone(ts)) {
00593         const char *rootDir = rpmtsRootDir(ts);
00594         inChroot = 0;
00595         /*@-modobserver @*/
00596         if (rootDir != NULL && strcmp(rootDir, "/") && *rootDir == '/') {
00597             xx = Chroot(rootDir);
00598         /*@=modobserver @*/
00599             xx = rpmtsSetChrootDone(ts, 1);
00600         }
00601     } else
00602        inChroot = 1;
00603 
00604     /* All embedded scriptlets run with CWD == "/". */
00605     xx = Chdir("/");
00606 
00607     return inChroot;
00608 }
00609 
00610 static int exitChroot(rpmpsm psm, int inChroot, int rootFdno)
00611         /*@globals fileSystem, internalState @*/
00612         /*@modifies fileSystem, internalState @*/
00613 {
00614     const rpmts ts = psm->ts;
00615     const char *rootDir = rpmtsRootDir(ts);
00616     int xx;
00617 
00618     if (rpmtsChrootDone(ts) && !inChroot) {
00619         xx = fchdir(rootFdno);
00620 /*@-modobserver@*/
00621         if (rootDir != NULL && strcmp(rootDir, "/") && *rootDir == '/') {
00622             xx = Chroot(".");
00623 /*@=modobserver@*/
00624             xx = rpmtsSetChrootDone(ts, 0);
00625         }
00626     } else
00627         xx = fchdir(rootFdno);
00628 
00629     xx = close(rootFdno);
00630 
00631     return 0;
00632 }
00633 
00645 static rpmRC runEmbeddedScript(rpmpsm psm, const char * sln, HE_t Phe,
00646                    const char *script, int arg1, int arg2)
00647         /*@globals h_errno, fileSystem, internalState @*/
00648         /*@modifies psm, fileSystem, internalState @*/
00649 {
00650     char * av[] = { NULL, NULL, NULL, NULL };
00651     int rootFdno = -1;
00652     rpmRC rc = RPMRC_OK;
00653     int xx = 0;
00654     int * ssp = NULL;
00655     int inChroot = enterChroot(psm, &rootFdno);
00656 
00657     if (psm->sstates != NULL)
00658         ssp = psm->sstates + tag2slx(psm->scriptTag);
00659     if (ssp != NULL)
00660         *ssp |= (RPMSCRIPT_STATE_LUA|RPMSCRIPT_STATE_EXEC);
00661 
00662     av[0] = (char *) Phe->p.argv[0];
00663     if (arg1 >= 0)
00664         (void) sprintf((av[1] = alloca(32)), "%d", arg1);
00665     if (arg2 >= 0)
00666         (void) sprintf((av[2] = alloca(32)), "%d", arg2);
00667 
00668 #if defined(WITH_LUA)
00669     if (!strcmp(Phe->p.argv[0], "<lua>")) {
00670         rc = runLuaScript(psm, sln, Phe, script, arg1, arg2);
00671     } else
00672 #endif
00673 #if defined(WITH_FICL)
00674     if (!strcmp(Phe->p.argv[0], "<ficl>")) {
00675         rpmficl ficl = rpmficlNew((const char **)av, 0);
00676         rc = rpmficlRun(ficl, script, NULL) == RPMRC_OK
00677             ? RPMRC_OK : RPMRC_FAIL;
00678         ficl = rpmficlFree(ficl);
00679     } else
00680 #endif
00681 #if defined(WITH_JS)
00682     if (!strcmp(Phe->p.argv[0], "<js>")) {
00683         rpmjs js = rpmjsNew((const char **)av, 0);
00684         rc = rpmjsRun(js, script, NULL) == RPMRC_OK
00685             ? RPMRC_OK : RPMRC_FAIL;
00686         js = rpmjsFree(js);
00687     } else
00688 #endif
00689 #if defined(WITH_PERLEMBED)
00690     if (!strcmp(Phe->p.argv[0], "<perl>")) {
00691         rpmperl perl = rpmperlNew((const char **)av, 0);
00692         rc = rpmperlRun(perl, script, NULL) == RPMRC_OK
00693             ? RPMRC_OK : RPMRC_FAIL;
00694         perl = rpmperlFree(perl);
00695     } else
00696 #endif
00697 #if defined(WITH_PYTHONEMBED)
00698     if (!strcmp(Phe->p.argv[0], "<python>")) {
00699         rpmpython python = rpmpythonNew((const char **)av, 0);
00700         rc = rpmpythonRun(python, script, NULL) == RPMRC_OK
00701             ? RPMRC_OK : RPMRC_FAIL;
00702         python = rpmpythonFree(python);
00703     } else
00704 #endif
00705 #if defined(WITH_RUBYEMBED)
00706     if (!strcmp(Phe->p.argv[0], "<ruby>")) {
00707         rpmruby ruby = rpmrubyNew((const char **)av, 0);
00708         rc = rpmrubyRun(ruby, script, NULL) == RPMRC_OK
00709             ? RPMRC_OK : RPMRC_FAIL;
00710         ruby = rpmrubyFree(ruby);
00711     } else
00712 #endif
00713 #if defined(WITH_TCL)
00714     if (!strcmp(Phe->p.argv[0], "<tcl>")) {
00715         rpmtcl tcl = rpmtclNew((const char **)av, 0);
00716         rc = rpmtclRun(tcl, script, NULL) == RPMRC_OK
00717             ? RPMRC_OK : RPMRC_FAIL;
00718         tcl = rpmtclFree(tcl);
00719     } else
00720 #endif
00721         rc = RPMRC_NOTFOUND;
00722 
00723     if (ssp != NULL) {
00724         *ssp &= ~0xffff;
00725         *ssp |= (xx & 0xffff);
00726         *ssp |= RPMSCRIPT_STATE_REAPED;
00727     }
00728 
00729     xx = exitChroot(psm, inChroot, rootFdno);
00730 
00731     return rc;
00732 }
00733 #endif
00734 
00737 /*@unchecked@*/
00738 static int ldconfig_done = 0;
00739 
00740 /*@unchecked@*/ /*@observer@*/ /*@null@*/
00741 static const char * ldconfig_path = "/sbin/ldconfig";
00742 
00759 static rpmRC runScript(rpmpsm psm, Header h, const char * sln, HE_t Phe,
00760                 const char * script, int arg1, int arg2)
00761         /*@globals ldconfig_done, rpmGlobalMacroContext, h_errno,
00762                 fileSystem, internalState@*/
00763         /*@modifies psm, ldconfig_done, rpmGlobalMacroContext,
00764                 fileSystem, internalState @*/
00765 {
00766     const rpmts ts = psm->ts;
00767     const char * NVRA = psm->NVRA;
00768     HE_t IPhe = psm->IPhe;
00769     const char ** argv = NULL;
00770     int argc = 0;
00771     const char ** IP = NULL;
00772     int nIP;
00773     size_t maxPrefixLength;
00774     size_t len;
00775     char * prefixBuf = NULL;
00776     const char * fn = NULL;
00777     FD_t scriptFd = NULL;
00778     FD_t out = NULL;            /* exit: expects this to be initialized. */
00779     rpmRC rc = RPMRC_FAIL;      /* assume failure */
00780     const char * body = NULL;
00781     int * ssp = NULL;
00782     pid_t pid;
00783     int xx;
00784     int i;
00785 
00786     if (psm->sstates != NULL)
00787         ssp = psm->sstates + tag2slx(psm->scriptTag);
00788     if (ssp != NULL)
00789         *ssp = RPMSCRIPT_STATE_UNKNOWN;
00790 
00791     if (Phe->p.argv == NULL && script == NULL)
00792         return RPMRC_OK;
00793 
00794     /* Macro expand all scriptlets. */
00795     body = rpmExpand(script, NULL);
00796 
00797     /* XXX Load NVRA lazily. This should be done elsewhere ... */
00798     if (NVRA == NULL) {
00799         HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
00800         he->tag = RPMTAG_NVRA;
00801         xx = headerGet(h, he, 0);
00802 assert(he->p.str != NULL);
00803         psm->NVRA = NVRA = he->p.str;
00804     }
00805 
00806     if (Phe->p.argv && Phe->p.argv[0])
00807     if (!strcmp(Phe->p.argv[0], "<lua>")
00808      || !strcmp(Phe->p.argv[0], "<ficl>")
00809      || !strcmp(Phe->p.argv[0], "<js>")
00810      || !strcmp(Phe->p.argv[0], "<perl>")
00811      || !strcmp(Phe->p.argv[0], "<python>")
00812      || !strcmp(Phe->p.argv[0], "<ruby>")
00813      || !strcmp(Phe->p.argv[0], "<tcl>"))
00814     {
00815 #if defined(WITH_LUA) || defined(WITH_FICL) || defined(WITH_JS) || defined(WITH_PERLEMBED) || defined(WITH_PYTHONEMBED) || defined(WITH_RUBYEMBED) || defined(WITH_TCL)
00816         rpmlog(RPMLOG_DEBUG,
00817                 D_("%s: %s(%s) running %s scriptlet.\n"),
00818                 psm->stepName, tag2sln(psm->scriptTag), NVRA, Phe->p.argv[0]);
00819         rc = runEmbeddedScript(psm, sln, Phe, body, arg1, arg2);
00820 #endif
00821         goto exit;
00822     }
00823 
00824     psm->sq.reaper = 1;
00825 
00826     /*
00827      * If a successor node, and ldconfig was just run, don't bother.
00828      */
00829     if (ldconfig_path && Phe->p.argv != NULL && F_ISSET(psm, UNORDERED)) {
00830         if (ldconfig_done && !strcmp(Phe->p.argv[0], ldconfig_path)) {
00831             rpmlog(RPMLOG_DEBUG,
00832                 D_("%s: %s(%s) skipping redundant \"%s\".\n"),
00833                 psm->stepName, tag2sln(psm->scriptTag), NVRA,
00834                 Phe->p.argv[0]);
00835             rc = RPMRC_OK;
00836             goto exit;
00837         }
00838     }
00839 
00840     rpmlog(RPMLOG_DEBUG,
00841                 D_("%s: %s(%s) %ssynchronous scriptlet start\n"),
00842                 psm->stepName, tag2sln(psm->scriptTag), NVRA,
00843                 (F_ISSET(psm, UNORDERED) ? "a" : ""));
00844 
00845     if (Phe->p.argv == NULL) {
00846         argv = alloca(5 * sizeof(*argv));
00847         argv[0] = "/bin/sh";
00848         argc = 1;
00849         ldconfig_done = 0;
00850     } else {
00851         argv = alloca((Phe->c + 4) * sizeof(*argv));
00852         memcpy(argv, Phe->p.argv, Phe->c * sizeof(*argv));
00853         argc = Phe->c;
00854         ldconfig_done = (ldconfig_path && !strcmp(argv[0], ldconfig_path)
00855                 ? 1 : 0);
00856     }
00857 
00858     /* XXX Load INSTPREFIXES lazily. This should be done elsewhere ... */
00859     if (IPhe->tag == 0) {
00860         IPhe->tag = RPMTAG_INSTPREFIXES;
00861         xx = headerGet(h, IPhe, 0);
00862         if (!xx) {
00863             IPhe->p.ptr = _free(IPhe->p.ptr);
00864             IPhe->tag = RPMTAG_INSTALLPREFIX;
00865             xx = headerGet(h, IPhe, 0);
00866             if (xx) {
00867                 const char ** av =
00868                         xmalloc(sizeof(*av) + strlen(IPhe->p.argv[0]) + 1);
00869                 char * t = (char *) &av[1];
00870 
00871                 av[0] = t;
00872                 t = stpcpy(t, IPhe->p.argv[0]);
00873                 *t = '\0';
00874                 IPhe->p.ptr = _free(IPhe->p.ptr);
00875                 IPhe->t = RPM_STRING_ARRAY_TYPE;
00876                 IPhe->p.argv = av;
00877                 IPhe->c = 1;
00878             } else {
00879                 IPhe->p.argv = NULL;
00880                 IPhe->c = 0;
00881             }
00882         }
00883     }
00884     IP = IPhe->p.argv;
00885     nIP = IPhe->c;
00886 
00887     maxPrefixLength = 0;
00888     if (IP != NULL)
00889     for (i = 0; i < nIP; i++) {
00890         len = strlen(IP[i]);
00891         if (len > maxPrefixLength) maxPrefixLength = len;
00892     }
00893     prefixBuf = alloca(maxPrefixLength + 50);
00894 
00895     if (script) {
00896         const char * rootDir = rpmtsRootDir(ts);
00897         FD_t fd;
00898         size_t nw;
00899 
00900         if (rpmTempFile((!rpmtsChrootDone(ts) ? rootDir : "/"), &fn, &fd))
00901             goto exit;
00902 
00903         if (rpmIsDebug() &&
00904             (!strcmp(argv[0], "/bin/sh") || !strcmp(argv[0], "/bin/bash")))
00905         {
00906             static const char set_x[] = "set -x\n";
00907             nw = Fwrite(set_x, sizeof(set_x[0]), sizeof(set_x)-1, fd);
00908         }
00909 
00910         if (ldconfig_path && strstr(body, ldconfig_path) != NULL)
00911             ldconfig_done = 1;
00912 
00913         nw = Fwrite(body, sizeof(body[0]), strlen(body), fd);
00914         xx = Fclose(fd);
00915 
00916         {   const char * sn = fn;
00917             if (!rpmtsChrootDone(ts) && rootDir != NULL &&
00918                 !(rootDir[0] == '/' && rootDir[1] == '\0'))
00919             {
00920                 sn += strlen(rootDir)-1;
00921             }
00922             argv[argc++] = sn;
00923         }
00924 
00925         if (arg1 >= 0) {
00926             char *av = alloca(20);
00927             sprintf(av, "%d", arg1);
00928             argv[argc++] = av;
00929         }
00930         if (arg2 >= 0) {
00931             char *av = alloca(20);
00932             sprintf(av, "%d", arg2);
00933             argv[argc++] = av;
00934         }
00935     }
00936 
00937     argv[argc] = NULL;
00938 
00939     scriptFd = rpmtsScriptFd(ts);
00940     if (scriptFd != NULL) {
00941         if (rpmIsVerbose()) {
00942             out = fdDup(Fileno(scriptFd));
00943         } else {
00944             out = Fopen("/dev/null", "w.fdio");
00945             if (Ferror(out)) {
00946                 out = fdDup(Fileno(scriptFd));
00947             }
00948         }
00949     } else {
00950         out = fdDup(STDOUT_FILENO);
00951     }
00952     if (out == NULL)    /* XXX can't happen */
00953         goto exit;
00954 
00955     pid = rpmsqFork(&psm->sq);
00956     if (psm->sq.child == 0) {
00957         int pipes[2];
00958         int flag;
00959         int fdno;
00960 
00961         pipes[0] = pipes[1] = 0;
00962         /* Make stdin inaccessible */
00963         xx = pipe(pipes);
00964         xx = close(pipes[1]);
00965         xx = dup2(pipes[0], STDIN_FILENO);
00966         xx = close(pipes[0]);
00967 
00968         /* XXX Force FD_CLOEXEC on 1st 100 inherited fdno's. */
00969         for (fdno = 3; fdno < 100; fdno++) {
00970             flag = fcntl(fdno, F_GETFD);
00971             if (flag == -1 || (flag & FD_CLOEXEC))
00972                 continue;
00973             rpmlog(RPMLOG_DEBUG,
00974                         D_("%s: %s(%s)\tfdno(%d) missing FD_CLOEXEC\n"),
00975                         psm->stepName, sln, NVRA,
00976                         fdno);
00977             xx = fcntl(fdno, F_SETFD, FD_CLOEXEC);
00978             /* XXX W2DO? debug msg for inheirited fdno w/o FD_CLOEXEC */
00979         }
00980 
00981         if (scriptFd != NULL) {
00982             int sfdno = Fileno(scriptFd);
00983             int ofdno = Fileno(out);
00984             if (sfdno != STDERR_FILENO)
00985                 xx = dup2(sfdno, STDERR_FILENO);
00986             if (ofdno != STDOUT_FILENO)
00987                 xx = dup2(ofdno, STDOUT_FILENO);
00988             /* make sure we don't close stdin/stderr/stdout by mistake! */
00989             if (ofdno > STDERR_FILENO && ofdno != sfdno)
00990                 xx = Fclose (out);
00991             if (sfdno > STDERR_FILENO && ofdno != sfdno)
00992                 xx = Fclose (scriptFd);
00993         }
00994 
00995         {   const char *ipath = rpmExpand("PATH=%{_install_script_path}", NULL);
00996             const char *path = SCRIPT_PATH;
00997 
00998             if (ipath && ipath[5] != '%')
00999                 path = ipath;
01000 
01001             xx = doputenv(path);
01002             /*@-modobserver@*/
01003             ipath = _free(ipath);
01004             /*@=modobserver@*/
01005         }
01006 
01007         if (IP != NULL)
01008         for (i = 0; i < nIP; i++) {
01009             sprintf(prefixBuf, "RPM_INSTALL_PREFIX%d=%s", i, IP[i]);
01010             xx = doputenv(prefixBuf);
01011 
01012             /* backwards compatibility */
01013             if (i == 0) {
01014                 sprintf(prefixBuf, "RPM_INSTALL_PREFIX=%s", IP[i]);
01015                 xx = doputenv(prefixBuf);
01016             }
01017         }
01018 
01019         {   const char * rootDir = rpmtsRootDir(ts);
01020             if (!rpmtsChrootDone(ts) && rootDir != NULL &&
01021                 !(rootDir[0] == '/' && rootDir[1] == '\0'))
01022             {
01023                 /*@-modobserver@*/
01024                 xx = Chroot(rootDir);
01025                 /*@=modobserver@*/
01026             }
01027             xx = Chdir("/");
01028             rpmlog(RPMLOG_DEBUG, D_("%s: %s(%s)\texecv(%s) pid %d\n"),
01029                         psm->stepName, sln, NVRA,
01030                         argv[0], (unsigned)getpid());
01031 
01032             /* XXX Don't mtrace into children. */
01033             unsetenv("MALLOC_CHECK_");
01034 
01035             if (ssp != NULL)
01036                 *ssp |= RPMSCRIPT_STATE_EXEC;
01037 
01038             /* Permit libselinux to do the scriptlet exec. */
01039             if (rpmtsSELinuxEnabled(ts) == 1) { 
01040                 if (ssp != NULL)
01041                     *ssp |= RPMSCRIPT_STATE_SELINUX;
01042 /*@-moduncon@*/
01043                 xx = rpm_execcon(0, argv[0], (char *const *)argv, environ);
01044 /*@=moduncon@*/
01045             } else {
01046 /*@-nullstate@*/
01047                 xx = execv(argv[0], (char *const *)argv);
01048 /*@=nullstate@*/
01049             }
01050         }
01051 
01052         if (ssp != NULL)
01053             *ssp &= ~RPMSCRIPT_STATE_EXEC;
01054 
01055         _exit(-1);
01056         /*@notreached@*/
01057     }
01058 
01059     if (psm->sq.child == (pid_t)-1) {
01060         rpmlog(RPMLOG_ERR, _("Couldn't fork %s: %s\n"), sln, strerror(errno));
01061         goto exit;
01062     }
01063 
01064     (void) psmWait(psm);
01065 
01066   /* XXX filter order dependent multilib "other" arch helper error. */
01067   if (!(psm->sq.reaped >= 0 && !strcmp(argv[0], "/usr/sbin/glibc_post_upgrade") && WEXITSTATUS(psm->sq.status) == 110)) {
01068     void *ptr = NULL;
01069     if (psm->sq.reaped < 0) {
01070         rpmlog(RPMLOG_ERR,
01071                 _("%s(%s) scriptlet failed, waitpid(%d) rc %d: %s\n"),
01072                  sln, NVRA, (int)psm->sq.child, (int)psm->sq.reaped,
01073                 strerror(errno));
01074         goto exit;
01075     } else
01076     if (!WIFEXITED(psm->sq.status) || WEXITSTATUS(psm->sq.status)) {
01077         if (WIFSIGNALED(psm->sq.status)) {
01078             ptr = rpmtsNotify(ts, psm->te, RPMCALLBACK_SCRIPT_ERROR,
01079                                  psm->scriptTag, WTERMSIG(psm->sq.status));
01080             rpmlog(RPMLOG_ERR,
01081                  _("%s(%s) scriptlet failed, signal %d\n"),
01082                  sln, NVRA, WTERMSIG(psm->sq.status));
01083         } else {
01084             ptr = rpmtsNotify(ts, psm->te, RPMCALLBACK_SCRIPT_ERROR,
01085                                  psm->scriptTag, WEXITSTATUS(psm->sq.status));
01086             rpmlog(RPMLOG_ERR,
01087                 _("%s(%s) scriptlet failed, exit status %d\n"),
01088                 sln, NVRA, WEXITSTATUS(psm->sq.status));
01089         }
01090         goto exit;
01091     }
01092   }
01093 
01094     rc = RPMRC_OK;
01095 
01096 exit:
01097     if (out)
01098         xx = Fclose(out);       /* XXX dup'd STDOUT_FILENO */
01099 
01100     if (script) {
01101         if (!rpmIsDebug() && fn != NULL)
01102             xx = Unlink(fn);
01103         fn = _free(fn);
01104     }
01105 
01106     body = _free(body);
01107 
01108     return rc;
01109 }
01110 
01116 static rpmRC runInstScript(rpmpsm psm)
01117         /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
01118         /*@modifies psm, rpmGlobalMacroContext, fileSystem, internalState @*/
01119 {
01120     HE_t Phe = memset(alloca(sizeof(*Phe)), 0, sizeof(*Phe));
01121     HE_t She = memset(alloca(sizeof(*She)), 0, sizeof(*She));
01122     rpmfi fi = psm->fi;
01123     const char * argv0 = NULL;
01124     rpmRC rc = RPMRC_OK;
01125 
01126 assert(fi->h != NULL);
01127     She->tag = psm->scriptTag;
01128     if (!headerGet(fi->h, She, 0))
01129         goto exit;
01130 
01131     Phe->tag = psm->progTag;
01132     if (!headerGet(fi->h, Phe, 0))
01133         goto exit;
01134 
01135     /* Coerce strings into header argv return. */
01136     if (Phe->t == RPM_STRING_TYPE) {
01137         const char * s = Phe->p.str;
01138         char * t;
01139         Phe->p.argv = xmalloc(sizeof(Phe->p.argv[0]) + strlen(s) + 1);
01140         Phe->p.argv[0] = t = (char *) &Phe->p.argv[1];
01141         t = stpcpy(t, s);
01142         *t = '\0';
01143         s = _free(s);
01144     }
01145 
01146     /* Expand "%script -p %%{interpreter}" macros. */
01147     if (Phe->p.argv[0][0] == '%')
01148         Phe->p.argv[0] = argv0 = rpmExpand(Phe->p.argv[0], NULL);
01149 
01150     rc = runScript(psm, fi->h, tag2sln(psm->scriptTag), Phe,
01151                 She->p.str, psm->scriptArg, -1);
01152 
01153 exit:
01154     argv0 = _free(argv0);
01155     Phe->p.ptr = _free(Phe->p.ptr);
01156     She->p.ptr = _free(She->p.ptr);
01157     return rc;
01158 }
01159 
01160 /*@unchecked@*/
01161 static rpmTag _trigger_tag;
01162 
01171 static rpmRC handleOneTrigger(const rpmpsm psm,
01172                         Header sourceH, Header triggeredH, int arg2)
01173         /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState@*/
01174         /*@modifies psm, sourceH, triggeredH,
01175                 rpmGlobalMacroContext, fileSystem, internalState @*/
01176 {
01177     static int scareMem = 0;
01178     HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
01179     HE_t Ihe = memset(alloca(sizeof(*Ihe)), 0, sizeof(*Ihe));
01180     HE_t She = memset(alloca(sizeof(*She)), 0, sizeof(*She));
01181     HE_t Phe = memset(alloca(sizeof(*Phe)), 0, sizeof(*Phe));
01182     miRE mire = NULL;
01183     const rpmts ts = psm->ts;
01184     rpmds Tds = NULL;
01185     rpmds Fds = NULL;
01186     rpmds Dds = NULL;
01187     rpmds Pds = NULL;
01188     const char * sourceName;
01189     const char * triggerName;
01190     rpmRC rc = RPMRC_OK;
01191     int arg1;
01192     int xx;
01193     int i;
01194 
01195     he->tag = RPMTAG_NAME;
01196     xx = headerGet(sourceH, he, 0);
01197     sourceName = he->p.str;
01198 
01199     he->tag = RPMTAG_NAME;
01200     xx = headerGet(triggeredH, he, 0);
01201     triggerName = he->p.str;
01202 
01203     arg1 = rpmdbCountPackages(rpmtsGetRdb(ts), triggerName);
01204     if (arg1 < 0) {
01205         /* XXX W2DO? fails as "execution of script failed" */
01206         rc = RPMRC_FAIL;
01207         goto exit;
01208     }
01209     arg1 += psm->countCorrection;
01210 
01211     Tds = rpmdsNew(triggeredH, RPMTAG_TRIGGERNAME, scareMem);
01212     if (Tds == NULL)
01213         goto exit;
01214     xx = rpmdsSetNoPromote(Tds, 1);
01215 
01216     Ihe->tag = RPMTAG_TRIGGERINDEX;
01217     if (!headerGet(triggeredH, Ihe, 0))
01218         goto exit;
01219 
01220     She->tag = RPMTAG_TRIGGERSCRIPTS;
01221     if (!headerGet(triggeredH, She, 0))
01222         goto exit;
01223 
01224     Phe->tag = RPMTAG_TRIGGERSCRIPTPROG;
01225     if (!headerGet(triggeredH, Phe, 0))
01226         goto exit;
01227 
01228     if ((Tds = rpmdsInit(Tds)) != NULL)
01229     while ((i = rpmdsNext(Tds)) >= 0) {
01230         rpmuint32_t Flags = rpmdsFlags(Tds);
01231         char * depName;
01232         int bingo;
01233 
01234         /* Skip triggers that are not in this context. */
01235         if (!(Flags & psm->sense))
01236             continue;
01237 
01238         bingo = 0;              /* no trigger to fire. */
01239         depName = (char *) rpmdsN(Tds);
01240         if (depName[0] == '/') {
01241             size_t nb = strlen(depName);
01242             if (Glob_pattern_p(depName, 0)) {
01243                 rpmds ds = NULL;
01244                 if (depName[nb-1] == '/') {
01245                     /* XXX Dirnames w trailing "/" needed. */
01246                     if (Dds == NULL)
01247                         Dds = rpmdsNew(sourceH, RPMTAG_DIRNAMES, 0x2);
01248                     ds = rpmdsLink(Dds, "Triggers");
01249                 } else {
01250                     if (Fds == NULL)
01251                         Fds = rpmdsNew(sourceH, RPMTAG_BASENAMES, 0);
01252                     ds = rpmdsLink(Fds, "Triggers");
01253                 }
01254                 if (mire == NULL)
01255                     mire = mireNew(RPMMIRE_GLOB, 0);
01256 
01257                 xx = mireRegcomp(mire, depName);
01258                 if ((ds = rpmdsInit(ds)) != NULL)
01259                 while (rpmdsNext(ds) >= 0) {
01260                     const char * N = rpmdsN(ds);
01261                     xx = mireRegexec(mire, N, 0);
01262                     if (xx < 0)
01263                         /*@innercontinue@*/ continue;
01264                     bingo = 1;
01265                     /*@innerbreak@*/ break;
01266                 }
01267                 (void)rpmdsFree(ds);
01268                 ds = NULL;
01269                 xx = mireClean(mire);
01270             }
01271 
01272             /* If not matched, and directory trigger, try dir names. */
01273             if (!bingo && depName[nb-1] == '/') {
01274                 /* XXX Dirnames w trailing "/" needed. */
01275                 if (Dds == NULL)
01276                     Dds = rpmdsNew(sourceH, RPMTAG_DIRNAMES, 0x2);
01277                 bingo = rpmdsMatch(Tds, Dds);
01278             }
01279 
01280             /* If not matched, try file paths. */
01281             if (!bingo) {
01282                 if (Fds == NULL)
01283                     Fds = rpmdsNew(sourceH, RPMTAG_BASENAMES, 0);
01284                 bingo = rpmdsMatch(Tds, Fds);
01285             }
01286         }
01287 
01288         /* If trigger not fired yet, try provided dependency match. */
01289         if (!bingo) {
01290             if (Pds == NULL)
01291                 Pds = rpmdsNew(sourceH, RPMTAG_PROVIDENAME, 0);
01292             bingo = rpmdsMatch(Tds, Pds);
01293             bingo = rpmdsNegateRC(Tds, bingo);
01294         }
01295         if (!bingo)
01296             continue;
01297 
01298         /* Coerce strings into header argv return. */
01299         /* XXX FIXME: permit trigger scripts with arguments. */
01300         {   int index = Ihe->p.ui32p[i];
01301             const char * s = Phe->p.argv[index];
01302             char * t;
01303             
01304             he->tag = Phe->tag;
01305             he->t = RPM_STRING_ARRAY_TYPE;
01306             he->c = 1;
01307             he->p.argv = xmalloc(sizeof(Phe->p.argv[0]) + strlen(s) + 1);
01308             he->p.argv[0] = t = (char *) &he->p.argv[1];
01309             t = stpcpy(t, s);
01310             *t = '\0';
01311 
01312             rc |= runScript(psm, triggeredH, "%trigger", he,
01313                         She->p.argv[index], arg1, arg2);
01314 
01315             he->p.ptr = _free(he->p.ptr);
01316         }
01317     }
01318 
01319     mire = mireFree(mire);
01320     (void)rpmdsFree(Pds);
01321     Pds = NULL;
01322     (void)rpmdsFree(Dds);
01323     Dds = NULL;
01324     (void)rpmdsFree(Fds);
01325     Fds = NULL;
01326     (void)rpmdsFree(Tds);
01327     Tds = NULL;
01328 
01329 exit:
01330     Ihe->p.ptr = _free(Ihe->p.ptr);
01331     She->p.ptr = _free(She->p.ptr);
01332     Phe->p.ptr = _free(Phe->p.ptr);
01333     triggerName = _free(triggerName);
01334     sourceName = _free(sourceName);
01335 
01336     return rc;
01337 }
01338 
01339 /* Retrieve trigger patterns from rpmdb. */
01340 static int rpmdbTriggerGlobs(rpmpsm psm)
01341         /*@globals rpmGlobalMacroContext @*/
01342         /*@modifies psm, rpmGlobalMacroContext @*/
01343 {
01344     const rpmts ts = psm->ts;
01345     ARGV_t keys = NULL;
01346     int xx = rpmdbMireApply(rpmtsGetRdb(ts), RPMTAG_TRIGGERNAME,
01347                 RPMMIRE_STRCMP, NULL, &keys);
01348     int nkeys = argvCount(keys);
01349     int i;
01350     
01351     if (keys)
01352     for (i = 0; i < nkeys; i++) {
01353         char * t = (char *) keys[i];
01354         if (!Glob_pattern_p(t, 0))
01355             continue;
01356         xx = mireAppend(RPMMIRE_GLOB, 0, t, NULL,
01357                 (miRE *)&psm->Tmires, &psm->nTmires);
01358         xx = argvAdd(&psm->Tpats, t);
01359     }
01360     keys = argvFree(keys);
01361     return 0;
01362 }
01363 
01371 static rpmRC runTriggersLoop(rpmpsm psm, rpmTag tagno, int arg2)
01372         /*@globals rpmGlobalMacroContext, h_errno,
01373                 fileSystem, internalState @*/
01374         /*@modifies psm, rpmGlobalMacroContext,
01375                 fileSystem, internalState @*/
01376 {
01377     static int scareMem = 0;
01378     const rpmts ts = psm->ts;
01379     rpmfi fi = psm->fi;
01380     rpmds ds = rpmdsNew(fi->h, tagno, scareMem);
01381     char * depName = NULL;
01382     ARGI_t instances = NULL;
01383     rpmmi mi;
01384     Header triggeredH;
01385     rpmRC rc = RPMRC_OK;
01386     int i;
01387     int xx;
01388 
01389     /* Fire elements against rpmdb trigger strings. */
01390     if ((ds = rpmdsInit(ds)) != NULL)
01391     while ((i = rpmdsNext(ds)) >= 0) {
01392         const char * Name = rpmdsN(ds);
01393         size_t nName = strlen(Name);
01394         unsigned prev, instance;
01395         unsigned nvals;
01396         ARGint_t vals;
01397 
01398         depName = _free(depName);
01399         depName = xmalloc(nName + 1 + 1);
01400         (void) stpcpy(depName, Name);
01401         /* XXX re-add the pesky trailing '/' to dirnames. */
01402         depName[nName] = (tagno == RPMTAG_DIRNAMES ? '/' : '\0');
01403         depName[nName+1] = '\0';
01404 
01405         if (depName[0] == '/' && psm->Tmires != NULL) {
01406             miRE mire;
01407             int j;
01408 
01409             /* XXX mireApply doesn't tell which pattern matched. */
01410             for (j = 0, mire = psm->Tmires; j < psm->nTmires; j++, mire++) {
01411                 const char * pattern = psm->Tpats[j];
01412                 if (depName[nName-1] != '/') {
01413                     size_t npattern = strlen(pattern);
01414                     depName[nName] = (pattern[npattern-1] == '/') ? '/' : '\0';
01415                 }
01416                 if (mireRegexec(mire, depName, 0) < 0)
01417                     /*@innercontinue@*/ continue;
01418 
01419                 /* Reset the primary retrieval key to the pattern. */
01420                 depName = _free(depName);
01421                 depName = xstrdup(pattern);
01422                 /*@innerbreak@*/ break;
01423             }
01424         }
01425 
01426         /* Retrieve triggered header(s) by key. */
01427         mi = rpmtsInitIterator(ts, RPMTAG_TRIGGERNAME, depName, 0);
01428 
01429         nvals = argiCount(instances);
01430         vals = argiData(instances);
01431         if (nvals > 0)
01432             xx = rpmmiPrune(mi, (int *)vals, nvals, 1);
01433 
01434         prev = 0;
01435         while((triggeredH = rpmmiNext(mi)) != NULL) {
01436             instance = rpmmiInstance(mi);
01437             if (prev == instance)
01438                 /*@innercontinue@*/ continue;
01439             rc |= handleOneTrigger(psm, fi->h, triggeredH, arg2);
01440             prev = instance;
01441             xx = argiAdd(&instances, -1, instance);
01442             xx = argiSort(instances, NULL);
01443         }
01444 
01445         mi = rpmmiFree(mi);
01446     }
01447 
01448     instances = argiFree(instances);
01449     depName = _free(depName);
01450     (void)rpmdsFree(ds);
01451     ds = NULL;
01452 
01453     return rc;
01454 }
01455 
01461 static rpmRC runTriggers(rpmpsm psm)
01462         /*@globals rpmGlobalMacroContext, h_errno,
01463                 fileSystem, internalState @*/
01464         /*@modifies psm, rpmGlobalMacroContext,
01465                 fileSystem, internalState @*/
01466 {
01467     const rpmts ts = psm->ts;
01468     rpmfi fi = psm->fi;
01469     int numPackage;
01470     rpmTag tagno;
01471     rpmRC rc = RPMRC_OK;
01472 
01473     /* Select RPMTAG_NAME or RPMTAG_PROVIDENAME index for triggering. */
01474     if (_trigger_tag == 0) {
01475         const char * t = rpmExpand("%{?_trigger_tag}", NULL);
01476 /*@-mods@*/
01477         _trigger_tag = (!strcmp(t, "name") ? RPMTAG_NAME : RPMTAG_PROVIDENAME);
01478 /*@=mods@*/
01479         t = _free(t);
01480     }
01481     tagno = _trigger_tag;
01482 
01483 assert(psm->te != NULL);
01484     {   const char * N = rpmteN(psm->te);
01485 assert(N != NULL);
01486         numPackage = rpmdbCountPackages(rpmtsGetRdb(ts), N);
01487         numPackage += psm->countCorrection;
01488         if (numPackage < 0)
01489             return RPMRC_NOTFOUND;
01490     }
01491 assert(fi != NULL);
01492 assert(fi->h != NULL);
01493 
01494     /* XXX Save/restore count correction. */
01495     {   int countCorrection = psm->countCorrection;
01496 
01497         psm->countCorrection = 0;
01498 
01499         /* Try name/providename triggers first. */
01500         rc |= runTriggersLoop(psm, tagno, numPackage);
01501 
01502         /* If not limited to NEVRA triggers, also try file/dir path triggers. */
01503         if (tagno != RPMTAG_NAME) {
01504             int xx;
01505             /* Retrieve trigger patterns from rpmdb. */
01506             xx = rpmdbTriggerGlobs(psm);
01507 
01508             rc |= runTriggersLoop(psm, RPMTAG_BASENAMES, numPackage);
01509             rc |= runTriggersLoop(psm, RPMTAG_DIRNAMES, numPackage);
01510 
01511             psm->Tpats = argvFree(psm->Tpats);
01512             psm->Tmires = mireFreeAll(psm->Tmires, psm->nTmires);
01513             psm->nTmires = 0;
01514         }
01515 
01516         psm->countCorrection = countCorrection;
01517     }
01518 
01519     return rc;
01520 }
01521 
01527 static rpmRC runImmedTriggers(rpmpsm psm)
01528         /*@globals rpmGlobalMacroContext, h_errno,
01529                 fileSystem, internalState @*/
01530         /*@modifies psm, rpmGlobalMacroContext,
01531                 fileSystem, internalState @*/
01532 {
01533     HE_t Ihe = memset(alloca(sizeof(*Ihe)), 0, sizeof(*Ihe));
01534     const rpmts ts = psm->ts;
01535     rpmfi fi = psm->fi;
01536     rpmds triggers = NULL;
01537     rpmmi mi;
01538     ARGV_t keys = NULL;
01539     ARGI_t instances = NULL;
01540     Header sourceH = NULL;
01541     const char * Name;
01542     rpmTag tagno;
01543     rpmRC rc = RPMRC_OK;
01544     int i;
01545     int xx;
01546 
01547 assert(fi->h != NULL);
01548 
01549     /* Select RPMTAG_NAME or RPMTAG_PROVIDENAME index for triggering. */
01550     if (_trigger_tag == 0) {
01551         const char * t = rpmExpand("%{?_trigger_tag}", NULL);
01552 /*@-mods@*/
01553         _trigger_tag = (!strcmp(t, "name") ? RPMTAG_NAME : RPMTAG_PROVIDENAME);
01554 /*@=mods@*/
01555         t = _free(t);
01556     }
01557     tagno = _trigger_tag;
01558 
01559 /*@-castexpose@*/
01560     triggers = rpmdsLink(psm->triggers, "ImmedTriggers");
01561 /*@=castexpose@*/
01562     if (triggers == NULL)
01563         goto exit;
01564 
01565     Ihe->tag = RPMTAG_TRIGGERINDEX;
01566     xx = headerGet(fi->h, Ihe, 0);
01567     if (!(xx && Ihe->p.ui32p && Ihe->c)) goto exit;
01568 
01569     /* Collect primary trigger keys, expanding globs as needed. */
01570     triggers = rpmdsInit(triggers);
01571     if (triggers != NULL)
01572     while ((i = rpmdsNext(triggers)) >= 0) {
01573         evrFlags Flags = rpmdsFlags(triggers);
01574         const char * N = rpmdsN(triggers);
01575         const char * EVR = rpmdsEVR(triggers);
01576 
01577         /* Skip triggers that are not in this context. */
01578         if (!(Flags & psm->sense))
01579             continue;
01580 
01581         /* If not limited to NEVRA triggers, use file/dir index. */
01582         if (tagno != RPMTAG_NAME) {
01583             /* XXX if trigger name ends with '/', use dirnames instead. */
01584             if (N[0] == '/') 
01585                 tagno = (N[strlen(N)-1] == '/')
01586                         ? RPMTAG_DIRNAMES : RPMTAG_FILEPATHS;
01587         }
01588         /* XXX For now, permit globs only in unversioned triggers. */
01589         if ((EVR == NULL || *EVR == '\0') && Glob_pattern_p(N, 0))
01590             xx = rpmdbMireApply(rpmtsGetRdb(ts), tagno, RPMMIRE_GLOB, N, &keys);
01591         else
01592             xx = argvAdd(&keys, N);
01593     }
01594     (void)rpmdsFree(triggers);
01595     triggers = NULL;
01596 
01597     /* For all primary keys, retrieve headers and fire triggers. */
01598     if (keys != NULL)
01599     for (i = 0; (Name = keys[i]) != NULL; i++) {
01600         unsigned prev, instance;
01601         unsigned nvals;
01602         ARGint_t vals;
01603 
01604         /* If not limited to NEVRA triggers, use file/dir index. */
01605         if (tagno != RPMTAG_NAME) {
01606             /* XXX if trigger name ends with '/', use dirnames instead. */
01607             if (Name[0] == '/') 
01608                 tagno = (Name[strlen(Name)-1] == '/')
01609                         ? RPMTAG_DIRNAMES : RPMTAG_FILEPATHS;
01610         }
01611 
01612         mi = rpmtsInitIterator(ts, tagno, Name, 0);
01613 
01614         /* Don't retrieve headers that have already been processed. */
01615         nvals = argiCount(instances);
01616         vals = argiData(instances);
01617         if (nvals > 0)
01618             xx = rpmmiPrune(mi, (int *)vals, nvals, 1);
01619 
01620         prev = 0;
01621         while((sourceH = rpmmiNext(mi)) != NULL) {
01622 
01623             /* Skip headers that have already been processed. */
01624             instance = rpmmiInstance(mi);
01625             if (prev == instance)
01626                 /*@innercontinue@*/ continue;
01627 
01628             rc |= handleOneTrigger(psm, sourceH, fi->h, rpmmiCount(mi));
01629 
01630             /* Mark header instance as processed. */
01631             prev = instance;
01632             xx = argiAdd(&instances, -1, instance);
01633             xx = argiSort(instances, NULL);
01634         }
01635 
01636         mi = rpmmiFree(mi);
01637     }
01638 
01639 exit:
01640     instances = argiFree(instances);
01641     keys = argvFree(keys);
01642     Ihe->p.ptr = _free(Ihe->p.ptr);
01643     return rc;
01644 }
01645 
01646 /*@observer@*/
01647 static const char * pkgStageString(pkgStage a)
01648         /*@*/
01649 {
01650     switch(a) {
01651     case PSM_UNKNOWN:           return "unknown";
01652 
01653     case PSM_PKGINSTALL:        return "  install";
01654     case PSM_PKGERASE:          return "    erase";
01655     case PSM_PKGCOMMIT:         return "   commit";
01656     case PSM_PKGSAVE:           return "repackage";
01657 
01658     case PSM_INIT:              return "init";
01659     case PSM_PRE:               return "pre";
01660     case PSM_PROCESS:           return "process";
01661     case PSM_POST:              return "post";
01662     case PSM_UNDO:              return "undo";
01663     case PSM_FINI:              return "fini";
01664 
01665     case PSM_CREATE:            return "create";
01666     case PSM_NOTIFY:            return "notify";
01667     case PSM_DESTROY:           return "destroy";
01668     case PSM_COMMIT:            return "commit";
01669 
01670     case PSM_CHROOT_IN:         return "chrootin";
01671     case PSM_CHROOT_OUT:        return "chrootout";
01672     case PSM_SCRIPT:            return "script";
01673     case PSM_TRIGGERS:          return "triggers";
01674     case PSM_IMMED_TRIGGERS:    return "immedtriggers";
01675 
01676     case PSM_RPMIO_FLAGS:       return "rpmioflags";
01677 
01678     case PSM_RPMDB_LOAD:        return "rpmdbload";
01679     case PSM_RPMDB_ADD:         return "rpmdbadd";
01680     case PSM_RPMDB_REMOVE:      return "rpmdbremove";
01681 
01682     default:                    return "???";
01683     }
01684     /*@noteached@*/
01685 }
01686 
01687 /*@-mustmod@*/
01688 static void rpmpsmFini(void * _psm)
01689         /*@modifies _psm @*/
01690 {
01691     rpmpsm psm = _psm;
01692 
01693 /*@-nullstate@*/
01694     psm->fi = rpmfiFree(psm->fi);
01695 #ifdef  NOTYET
01696     psm->te = rpmteFree(psm->te);
01697 #else
01698     psm->te = NULL;
01699 #endif
01700 /*@-internalglobs@*/
01701     (void)rpmtsFree(psm->ts); 
01702     psm->ts = NULL;
01703 /*@=internalglobs@*/
01704 
01705     psm->sstates = _free(psm->sstates);
01706     psm->IPhe->p.ptr = _free(psm->IPhe->p.ptr);
01707     psm->IPhe = _free(psm->IPhe);
01708     psm->NVRA = _free(psm->NVRA);
01709     (void)rpmdsFree(psm->triggers);
01710     psm->triggers = NULL;
01711 /*@=nullstate@*/
01712 }
01713 /*@=mustmod@*/
01714 
01715 /*@unchecked@*/ /*@only@*/ /*@null@*/
01716 rpmioPool _psmPool;
01717 
01718 static rpmpsm rpmpsmGetPool(/*@null@*/ rpmioPool pool)
01719         /*@globals _psmPool, fileSystem, internalState @*/
01720         /*@modifies pool, _psmPool, fileSystem, internalState @*/
01721 {
01722     rpmpsm psm;
01723 
01724     if (_psmPool == NULL) {
01725         _psmPool = rpmioNewPool("psm", sizeof(*psm), -1, _psm_debug,
01726                         NULL, NULL, rpmpsmFini);
01727         pool = _psmPool;
01728     }
01729     return (rpmpsm) rpmioGetPool(pool, sizeof(*psm));
01730 }
01731 
01732 rpmpsm rpmpsmNew(rpmts ts, rpmte te, rpmfi fi)
01733 {
01734     static const char msg[] = "rpmpsmNew";
01735     rpmpsm psm = rpmpsmGetPool(_psmPool);
01736 
01737 /*@-assignexpose -castexpose @*/
01738     if (ts)     psm->ts = rpmtsLink(ts, msg);
01739 #ifdef  NOTYET
01740     if (te)     psm->te = rpmteLink(te, msg);
01741 #else
01742 /*@-temptrans @*/
01743     if (te)     psm->te = te;
01744 /*@=temptrans @*/
01745 #endif
01746     if (fi)     psm->fi = rpmfiLink(fi, msg);
01747 /*@=assignexpose =castexpose @*/
01748 
01749     psm->triggers = NULL;
01750     psm->NVRA = NULL;
01751     psm->IPhe = xcalloc(1, sizeof(*psm->IPhe));
01752     psm->sstates = xcalloc(RPMSCRIPT_MAX, sizeof(*psm->sstates));
01753 
01754     return rpmpsmLink(psm, msg);
01755 }
01756 
01763 static rpmuint32_t hLoadTID(Header h, rpmTag tag)
01764         /*@globals internalState @*/
01765         /*@modifies internalState @*/
01766 {
01767     HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
01768     rpmuint32_t val;
01769     int xx;
01770 
01771     he->tag = tag;
01772     xx = headerGet(h, he, 0);
01773     val = (xx && he->p.ui32p ? he->p.ui32p[0] : 0);
01774     he->p.ptr = _free(he->p.ptr);
01775     return val;
01776 }
01777 
01785 static int hCopyTag(Header sh, Header th, rpmTag tag)
01786         /*@globals internalState @*/
01787         /*@modifies th, internalState @*/
01788 {
01789     HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
01790     int xx = 1;
01791 
01792     he->tag = tag;
01793     if (headerGet(sh, he, 0) && he->c > 0)
01794         xx = headerPut(th, he, 0);
01795     he->p.ptr = _free(he->p.ptr);
01796     return 0;
01797 }
01798 
01805 static int hSaveBlinks(Header h, const struct rpmChainLink_s * blink)
01806         /*@modifies h @*/
01807 {
01808     HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
01809 /*@observer@*/
01810     static const char * chain_end = RPMTE_CHAIN_END;
01811     int ac;
01812     int xx = 1;
01813 
01814     /* Save forward links into header upgrade chain. */
01815     he->tag = RPMTAG_BLINKNEVRA;
01816     he->t = RPM_STRING_ARRAY_TYPE;
01817     ac = argvCount(blink->NEVRA);
01818     if (ac > 0) {
01819         he->p.argv = argvData(blink->NEVRA);
01820         he->c = ac;
01821     } else {    /* XXX Add an explicit chain terminator on 1st install. */
01822         he->p.argv = &chain_end;
01823         he->c = 1;
01824     }
01825     xx = headerPut(h, he, 0);
01826     
01827     he->tag = RPMTAG_BLINKPKGID;
01828     he->t = RPM_STRING_ARRAY_TYPE;
01829     ac = argvCount(blink->Pkgid);
01830     if (ac > 0) {
01831         he->p.argv = argvData(blink->Pkgid);
01832         he->c = ac;
01833     } else {    /* XXX Add an explicit chain terminator on 1st install. */
01834         he->p.argv = &chain_end;
01835         he->c = 1;
01836     }
01837     xx = headerPut(h, he, 0);
01838 
01839     he->tag = RPMTAG_BLINKHDRID;
01840     he->t = RPM_STRING_ARRAY_TYPE;
01841     ac = argvCount(blink->Hdrid);
01842     if (ac > 0) {
01843         he->p.argv = argvData(blink->Hdrid);
01844         he->c = ac;
01845     } else {    /* XXX Add an explicit chain terminator on 1st install. */
01846         he->p.argv = &chain_end;
01847         he->c = 1;
01848     }
01849     xx = headerPut(h, he, 0);
01850 
01851     return 0;
01852 }
01853 
01860 static int hSaveFlinks(Header h, const struct rpmChainLink_s * flink)
01861         /*@modifies h @*/
01862 {
01863     HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
01864 #ifdef  NOTYET
01865     /*@observer@*/
01866     static const char * chain_end = RPMTE_CHAIN_END;
01867 #endif
01868     int ac;
01869     int xx = 1;
01870 
01871     /* Save forward links into header upgrade chain. */
01872     he->tag = RPMTAG_FLINKNEVRA;
01873     he->t = RPM_STRING_ARRAY_TYPE;
01874     ac = argvCount(flink->NEVRA);
01875     if (ac > 0) {
01876         he->p.argv = argvData(flink->NEVRA);
01877         he->c = ac;
01878     }
01879 #ifdef  NOTYET  /* XXX is an explicit flink terminator needed? */
01880     else {      /* XXX Add an explicit chain terminator on 1st install. */
01881         he->p.argv = &chain_end;
01882         he->c = 1;
01883     }
01884 #endif
01885     xx = headerPut(h, he, 0);
01886 
01887     he->tag = RPMTAG_FLINKPKGID;
01888     he->t = RPM_STRING_ARRAY_TYPE;
01889     ac = argvCount(flink->Pkgid);
01890     if (ac > 0) {
01891         he->p.argv = argvData(flink->Pkgid);
01892         he->c = ac;
01893     }
01894 #ifdef  NOTYET  /* XXX is an explicit flink terminator needed? */
01895     else {      /* XXX Add an explicit chain terminator on 1st install. */
01896         he->p.argv = &chain_end;
01897         he->c = 1;
01898     }
01899 #endif
01900     xx = headerPut(h, he, 0);
01901 
01902     he->tag = RPMTAG_FLINKHDRID;
01903     he->t = RPM_STRING_ARRAY_TYPE;
01904     ac = argvCount(flink->Hdrid);
01905     if (ac > 0) {
01906         he->p.argv = argvData(flink->Hdrid);
01907         he->c = ac;
01908     }
01909 #ifdef  NOTYET  /* XXX is an explicit flink terminator needed? */
01910     else {      /* XXX Add an explicit chain terminator on 1st install. */
01911         he->p.argv = &chain_end;
01912         he->c = 1;
01913     }
01914 #endif
01915     xx = headerPut(h, he, 0);
01916 
01917     return 0;
01918 }
01919 
01927 static int populateInstallHeader(const rpmts ts, const rpmte te, rpmfi fi)
01928         /*@globals h_errno, fileSystem, internalState @*/
01929         /*@modifies fi, fileSystem, internalState @*/
01930 {
01931     HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
01932     rpmuint32_t tscolor = rpmtsColor(ts);
01933     rpmuint32_t tecolor = rpmteColor(te);
01934     rpmuint32_t * uip;
01935     rpmuint32_t installTime[2];
01936     rpmuint32_t originTime[2];
01937     rpmuint32_t originTid[2];
01938     int xx = 1;
01939 
01940 assert(fi->h != NULL);
01941 
01942     {   struct timeval tv;
01943         xx = gettimeofday(&tv, NULL);
01944         installTime[0] = (rpmuint32_t) tv.tv_sec;
01945         installTime[1] = (rpmuint32_t) tv.tv_usec;
01946     }
01947     he->tag = RPMTAG_INSTALLTIME;
01948     he->t = RPM_UINT32_TYPE;
01949     he->p.ui32p = &installTime[0];
01950     he->c = 2;
01951     xx = headerPut(fi->h, he, 0);
01952 
01953     /* Propagate the tid & time that the package was first installed. */
01954     if ((uip = rpmteOriginTime(te)) != NULL)
01955         memcpy(originTime, uip, sizeof(originTime));
01956     if (originTime[0] == 0)
01957         memcpy(originTime, installTime, sizeof(originTime));
01958     he->tag = RPMTAG_ORIGINTIME;
01959     he->t = RPM_UINT32_TYPE;
01960     he->p.ui32p = originTime;
01961     he->c = 2;
01962     xx = headerPut(fi->h, he, 0);
01963 
01964     if ((uip = rpmteOriginTid(te)) != NULL)
01965         memcpy(originTid, uip, sizeof(originTid));
01966     if (originTid[0] == 0)
01967         memcpy(originTid, ts->tid, sizeof(originTid));
01968     he->tag = RPMTAG_ORIGINTID;
01969     he->t = RPM_UINT32_TYPE;
01970     he->p.ui32p = originTid;
01971     he->c = 2;
01972     xx = headerPut(fi->h, he, 0);
01973 
01974     he->tag = RPMTAG_INSTALLCOLOR;
01975     he->t = RPM_UINT32_TYPE;
01976     he->p.ui32p = &tscolor;
01977     he->c = 1;
01978     xx = headerPut(fi->h, he, 0);
01979 
01980     /* XXX FIXME: add preferred color at install. */
01981 
01982     he->tag = RPMTAG_PACKAGECOLOR;
01983     he->t = RPM_UINT32_TYPE;
01984     he->p.ui32p = &tecolor;
01985     he->c = 1;
01986     xx = headerPut(fi->h, he, 0);
01987 
01988     /* Add the header's origin/digest/stat (i.e. URL) */
01989     {   const char * fn = headerGetOrigin(fi->h);
01990         const char * digest = headerGetDigest(fi->h);
01991         struct stat * st = headerGetStatbuf(fi->h);
01992 
01993         if (fn != NULL) {
01994             he->tag = RPMTAG_PACKAGEORIGIN;
01995             he->t = RPM_STRING_TYPE;
01996             he->p.str = xstrdup(fn);
01997             he->c = 1;
01998             xx = headerPut(fi->h, he, 0);
01999             he->p.ptr = _free(he->p.ptr);
02000 
02001             if (digest != NULL) {
02002                 he->tag = RPMTAG_PACKAGEDIGEST;
02003                 he->t = RPM_STRING_TYPE;
02004                 he->p.str = headerGetDigest(fi->h);
02005                 he->c = 1;
02006                 xx = headerPut(fi->h, he, 0);
02007             }
02008             if (st != NULL) {
02009 /* XXX Fstat(2) in pkgio.c should set *st. Verify st->st_mode w assert(3). */
02010 #ifndef DYING
02011                 int ut = urlPath(fn, NULL);
02012                 /* XXX URI is active, so avoid the lazy Stat(2) for now. */
02013                 if (!(ut == URL_IS_HTTP || ut == URL_IS_HTTPS))
02014                 if (st->st_mode == 0 && st->st_mtime == 0 && st->st_size == 0)
02015                     xx = Stat(fn, st);
02016 #endif
02017                 if (st->st_mode != 0) {
02018                     he->tag = RPMTAG_PACKAGESTAT;
02019                     he->t = RPM_BIN_TYPE;
02020                     he->p.ptr = (void *)st;
02021                     he->c = (rpmTagCount) sizeof(*st);
02022                     xx = headerPut(fi->h, he, 0);
02023                 }
02024             }
02025         }
02026     }
02027 
02028     /* XXX Don't clobber forward/backward upgrade chain on rollbacks */
02029     if (rpmtsType(ts) != RPMTRANS_TYPE_ROLLBACK)
02030         xx = hSaveBlinks(fi->h, &te->blink);
02031 
02032     return 0;
02033 }
02034 
02035 
02043 static int postPopulateInstallHeader(/*@unused@*/ const rpmts ts,
02044                 /*@unused@*/ const rpmte te, rpmfi fi)
02045         /*@modifies fi @*/
02046 {
02047     HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
02048     int fc = rpmfiFC(fi);
02049     int xx = 1;
02050 
02051     if (fi->fstates != NULL && fc > 0) {
02052         he->tag = RPMTAG_FILESTATES;
02053         he->t = RPM_UINT8_TYPE;
02054         he->p.ui8p = fi->fstates;
02055         he->c = fc;
02056         xx = headerPut(fi->h, he, 0);
02057     }
02058 
02059     return 0;
02060 }
02061 
02062 #if defined(WITH_PTHREADS)
02063 static void * rpmpsmThread(void * arg)
02064         /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
02065         /*@modifies arg, rpmGlobalMacroContext, fileSystem, internalState @*/
02066 {
02067     rpmpsm psm = arg;
02068 /*@-unqualifiedtrans@*/
02069     return ((void *) rpmpsmStage(psm, psm->nstage));
02070 /*@=unqualifiedtrans@*/
02071 }
02072 #endif
02073 
02074 static int rpmpsmNext(rpmpsm psm, pkgStage nstage)
02075         /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
02076         /*@modifies psm, rpmGlobalMacroContext, fileSystem, internalState @*/
02077 {
02078     psm->nstage = nstage;
02079 #if defined(WITH_PTHREADS)
02080     if (_psm_threads)
02081         return rpmsqJoin( rpmsqThread(rpmpsmThread, psm) );
02082 #endif
02083     return rpmpsmStage(psm, psm->nstage);
02084 }
02085 
02090 /*@-nullpass@*/ /* FIX: testing null annotation for fi->h */
02091 rpmRC rpmpsmStage(rpmpsm psm, pkgStage stage)
02092 {
02093     HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
02094     const rpmts ts = psm->ts;
02095     rpmuint32_t tscolor = rpmtsColor(ts);
02096     rpmfi fi = psm->fi;
02097     rpmRC rc = psm->rc;
02098     int saveerrno;
02099     int xx;
02100 
02101 /* XXX hackery to assert(!scaremem) in rpmfiNew. */
02102 /*@-castexpose@*/
02103 if (fi->h == NULL && fi->te && ((rpmte)fi->te)->h != NULL) fi->h = headerLink(((rpmte)fi->te)->h);
02104 /*@=castexpose@*/
02105 
02106     switch (stage) {
02107     case PSM_UNKNOWN:
02108         break;
02109     case PSM_INIT:
02110         rpmlog(RPMLOG_DEBUG, D_("%s: %s has %d files, test = %d\n"),
02111                 psm->stepName, rpmteNEVR(psm->te),
02112                 rpmfiFC(fi), (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST));
02113 
02114         /*
02115          * When we run scripts, we pass an argument which is the number of
02116          * versions of this package that will be installed when we are
02117          * finished.
02118          */
02119         psm->npkgs_installed = rpmdbCountPackages(rpmtsGetRdb(ts), rpmteN(psm->te));
02120         if (psm->npkgs_installed < 0) {
02121             rc = RPMRC_FAIL;
02122             break;
02123         }
02124 
02125         /* Adjust package count on rollback downgrade. */
02126 assert(psm->te != NULL);
02127         if (rpmtsType(ts) == RPMTRANS_TYPE_AUTOROLLBACK &&
02128             (psm->goal & ~(PSM_PKGSAVE|PSM_PKGERASE)))
02129         {
02130             if (psm->te->downgrade)
02131                 psm->npkgs_installed--;
02132         }
02133 
02134         if (psm->goal == PSM_PKGINSTALL) {
02135             int fc = rpmfiFC(fi);
02136             const char * hdrid;
02137 
02138             /* Add per-transaction data to install header. */
02139             xx = populateInstallHeader(ts, psm->te, fi);
02140 
02141             psm->scriptArg = psm->npkgs_installed + 1;
02142 
02143 assert(psm->mi == NULL);
02144             hdrid = rpmteHdrid(psm->te);
02145             if (hdrid != NULL) {
02146                 /* XXX should use RPMTAG_HDRID not RPMTAG_SHA1HEADER */
02147                 psm->mi = rpmtsInitIterator(ts, RPMTAG_SHA1HEADER, hdrid, 0);
02148             } else {
02149                 psm->mi = rpmtsInitIterator(ts, RPMTAG_NAME, rpmteN(psm->te),0);
02150                 xx = rpmmiAddPattern(psm->mi, RPMTAG_EPOCH, RPMMIRE_STRCMP,
02151                         rpmteE(psm->te));
02152                 xx = rpmmiAddPattern(psm->mi, RPMTAG_VERSION, RPMMIRE_STRCMP,
02153                         rpmteV(psm->te));
02154                 xx = rpmmiAddPattern(psm->mi, RPMTAG_RELEASE, RPMMIRE_STRCMP,
02155                         rpmteR(psm->te));
02156 #ifdef  RPM_VENDOR_MANDRIVA
02157                 xx = rpmmiAddPattern(psm->mi, RPMTAG_DISTEPOCH, RPMMIRE_STRCMP,
02158                         rpmteD(psm->te));
02159 #endif
02160                 if (tscolor) {
02161                     xx = rpmmiAddPattern(psm->mi,RPMTAG_ARCH, RPMMIRE_STRCMP,
02162                         rpmteA(psm->te));
02163                     xx = rpmmiAddPattern(psm->mi, RPMTAG_OS, RPMMIRE_STRCMP,
02164                         rpmteO(psm->te));
02165                 }
02166             }
02167 
02168             while ((psm->oh = rpmmiNext(psm->mi)) != NULL) {
02169                 fi->record = rpmmiInstance(psm->mi);
02170                 psm->oh = NULL;
02171                 /*@loopbreak@*/ break;
02172             }
02173             psm->mi = rpmmiFree(psm->mi);
02174 
02175             rc = RPMRC_OK;
02176 
02177             /* XXX lazy alloc here may need to be done elsewhere. */
02178             if (fi->fstates == NULL && fc > 0) {
02179                 fi->fstates = xmalloc(sizeof(*fi->fstates) * fc);
02180                 memset(fi->fstates, RPMFILE_STATE_NORMAL, fc);
02181             }
02182 
02183             if (rpmtsFlags(ts) & RPMTRANS_FLAG_JUSTDB)  break;
02184             if (fc <= 0)                                break;
02185         
02186             /*
02187              * Old format relocatable packages need the entire default
02188              * prefix stripped to form the cpio list, while all other packages
02189              * need the leading / stripped.
02190              */
02191             he->tag = RPMTAG_DEFAULTPREFIX;
02192             xx = headerGet(fi->h, he, 0);
02193             fi->striplen = (xx && he->p.str ? strlen(he->p.str) + 1 : 1);
02194             he->p.ptr = _free(he->p.ptr);
02195             fi->mapflags =
02196                 IOSM_MAP_PATH | IOSM_MAP_MODE | IOSM_MAP_UID | IOSM_MAP_GID | (fi->mapflags & IOSM_SBIT_CHECK);
02197         
02198             if (headerIsEntry(fi->h, RPMTAG_ORIGBASENAMES))
02199                 he->tag = RPMTAG_ORIGPATHS;
02200             else
02201                 he->tag = RPMTAG_FILEPATHS;
02202             xx = headerGet(fi->h, he, 0);
02203 assert(he->p.argv != NULL);
02204             fi->apath = he->p.argv;
02205         
02206             if (fi->fuser == NULL) {
02207                 he->tag = RPMTAG_FILEUSERNAME;
02208                 xx = headerGet(fi->h, he, 0);
02209                 fi->fuser = he->p.argv;
02210             }
02211             if (fi->fgroup == NULL) {
02212                 he->tag = RPMTAG_FILEGROUPNAME;
02213                 xx = headerGet(fi->h, he, 0);
02214                 fi->fgroup = he->p.argv;
02215             }
02216             rc = RPMRC_OK;
02217         }
02218         if (psm->goal == PSM_PKGERASE || psm->goal == PSM_PKGSAVE) {
02219             psm->scriptArg = psm->npkgs_installed - 1;
02220         
02221             /* Retrieve installed header. */
02222             rc = rpmpsmNext(psm, PSM_RPMDB_LOAD);
02223 #ifdef  DYING
02224 if (rc == RPMRC_OK)
02225 if (psm->te)
02226 psm->te->h = headerLink(fi->h);
02227 #else
02228             if (rc == RPMRC_OK && psm->te)
02229                 (void) rpmteSetHeader(psm->te, fi->h);
02230 #endif
02231         }
02232         if (psm->goal == PSM_PKGSAVE) {
02233             /* Open output package for writing. */
02234             {   char tiddn[32];
02235                 const char * bfmt;
02236                 const char * pkgdn;
02237                 const char * pkgbn;
02238                 char * pkgdn_buf;
02239 
02240                 xx = snprintf(tiddn, sizeof(tiddn), "%d", rpmtsGetTid(ts));
02241                 bfmt = rpmGetPath(tiddn, "/", "%{_repackage_name_fmt}", NULL);
02242                 pkgbn = headerSprintf(fi->h, bfmt,
02243                                         NULL, rpmHeaderFormats, NULL);
02244                 bfmt = _free(bfmt);
02245                 psm->pkgURL = rpmGenPath("%{?_repackage_root}",
02246                                          "%{?_repackage_dir}",
02247                                         pkgbn);
02248                 pkgbn = _free(pkgbn);
02249                 (void) urlPath(psm->pkgURL, &psm->pkgfn);
02250                 pkgdn_buf = xstrdup(psm->pkgfn);
02251 /*@-moduncon@*/
02252                 pkgdn = dirname(pkgdn_buf);
02253 /*@=moduncon@*/
02254                 rc = rpmMkdirPath(pkgdn, "_repackage_dir");
02255                 pkgdn_buf = _free(pkgdn_buf);
02256                 if (rc == RPMRC_FAIL)
02257                     break;
02258                 psm->fd = Fopen(psm->pkgfn, "w.fdio");
02259                 if (psm->fd == NULL || Ferror(psm->fd)) {
02260                     rc = RPMRC_FAIL;
02261                     break;
02262                 }
02263             }
02264         }
02265         break;
02266     case PSM_PRE:
02267         if (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST)        break;
02268 
02269 /* XXX insure that trigger index is opened before entering chroot. */
02270 #ifdef  NOTYET
02271  { static int oneshot = 0;
02272    dbiIndex dbi;
02273    if (!oneshot) {
02274      dbi = dbiOpen(rpmtsGetRdb(ts), RPMTAG_TRIGGERNAME, 0);
02275      oneshot++;
02276    }
02277  }
02278 #endif
02279 
02280         /* Change root directory if requested and not already done. */
02281         rc = rpmpsmNext(psm, PSM_CHROOT_IN);
02282 
02283         if (psm->goal == PSM_PKGINSTALL) {
02284             psm->scriptTag = RPMTAG_PREIN;
02285             psm->progTag = RPMTAG_PREINPROG;
02286             psm->sense = RPMSENSE_TRIGGERPREIN;
02287             psm->countCorrection = 0;   /* XXX is this correct?!? */
02288 
02289             if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOTRIGGERPREIN)) {
02290 
02291                 /* Run triggers in other package(s) this package sets off. */
02292                 rc = rpmpsmNext(psm, PSM_TRIGGERS);
02293                 if (rc) break;
02294 
02295                 /* Run triggers in this package other package(s) set off. */
02296                 rc = rpmpsmNext(psm, PSM_IMMED_TRIGGERS);
02297                 if (rc) break;
02298             }
02299 
02300             if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOPRE)) {
02301                 rc = rpmpsmNext(psm, PSM_SCRIPT);
02302                 if (rc != RPMRC_OK) {
02303                     rpmlog(RPMLOG_ERR,
02304                         _("%s: %s scriptlet failed (%d), skipping %s\n"),
02305                         psm->stepName, tag2sln(psm->scriptTag), rc,
02306                         rpmteNEVR(psm->te));
02307                     break;
02308                 }
02309             }
02310         }
02311 
02312         if (psm->goal == PSM_PKGERASE) {
02313             psm->scriptTag = RPMTAG_PREUN;
02314             psm->progTag = RPMTAG_PREUNPROG;
02315             psm->sense = RPMSENSE_TRIGGERUN;
02316             psm->countCorrection = -1;
02317 
02318             if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOTRIGGERUN)) {
02319                 /* Run triggers in this package other package(s) set off. */
02320                 rc = rpmpsmNext(psm, PSM_IMMED_TRIGGERS);
02321                 if (rc) break;
02322 
02323                 /* Run triggers in other package(s) this package sets off. */
02324                 rc = rpmpsmNext(psm, PSM_TRIGGERS);
02325                 if (rc) break;
02326             }
02327 
02328             if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOPREUN))
02329                 rc = rpmpsmNext(psm, PSM_SCRIPT);
02330         }
02331         if (psm->goal == PSM_PKGSAVE) {
02332             int noArchiveSize = 0;
02333             const char * origin = NULL;
02334             const char * digest = NULL;
02335             const struct stat * st = NULL;
02336             size_t nstbytes = 0;
02337 
02338             /* Regenerate original header. */
02339             {   void * uh = NULL;
02340 
02341                 /* Save original header's origin/digest/stat (i.e. URL) */
02342                 he->tag = RPMTAG_PACKAGEORIGIN;
02343                 xx = headerGet(fi->h, he, 0);
02344                 origin = he->p.str;
02345                 he->tag = RPMTAG_PACKAGEDIGEST;
02346                 xx = headerGet(fi->h, he, 0);
02347                 if (xx && he->p.str != NULL)
02348                     digest = he->p.str;
02349                 he->tag = RPMTAG_PACKAGESTAT;
02350                 xx = headerGet(fi->h, he, 0);
02351                 if (xx && he->p.ptr != NULL && (size_t)he->c == sizeof(*st)) {
02352                     st = he->p.ptr;
02353                     nstbytes = he->c;
02354                 }
02355 
02356                 /* Retrieve original header blob. */
02357                 he->tag = RPMTAG_HEADERIMMUTABLE;
02358                 xx = headerGet(fi->h, he, 0);
02359                 uh = he->p.ptr;
02360                 if (xx && uh != NULL) {
02361                     psm->oh = headerCopyLoad(uh);
02362                     uh = _free(uh);
02363                 } else {
02364                     he->tag = RPMTAG_HEADERIMAGE;
02365                     xx = headerGet(fi->h, he, 0);
02366                     uh = he->p.ptr;
02367                     if (xx && uh != NULL) {
02368                         HeaderIterator hi;
02369                         Header oh;
02370 
02371                         /* Load the original header from the blob. */
02372                         oh = headerCopyLoad(uh);
02373 
02374                         /* XXX this is headerCopy w/o headerReload() */
02375                         psm->oh = headerNew();
02376 
02377                         for (hi = headerInit(oh);
02378                              headerNext(hi, he, 0);
02379                              he->p.ptr = _free(he->p.ptr))
02380                         {
02381                             if (he->tag == RPMTAG_ARCHIVESIZE)
02382                                 noArchiveSize = 1;
02383                             xx = headerPut(psm->oh, he, 0);
02384                         }
02385                         hi = headerFini(hi);
02386 
02387                         (void)headerFree(oh);
02388                         oh = NULL;
02389                         uh = _free(uh);
02390                     } else
02391                         break;  /* XXX shouldn't ever happen */
02392                 }
02393             }
02394 
02395             /* Retrieve type of payload compression. */
02396             /*@-nullstate@*/    /* FIX: psm->oh may be NULL */
02397             rc = rpmpsmNext(psm, PSM_RPMIO_FLAGS);
02398             /*@=nullstate@*/
02399 
02400             /* Write the lead section into the package. */
02401             {   static const char item[] = "Lead";
02402                 const char * NEVR = rpmteNEVR(psm->te);
02403                 size_t nb = rpmpkgSizeof(item, NULL);
02404         
02405                 if (nb == 0)
02406                     rc = RPMRC_FAIL;
02407                 else {
02408                     void * l = alloca(nb);
02409                     memset(l, 0, nb);
02410                     rc = rpmpkgWrite(item, psm->fd, l, &NEVR);
02411                 }
02412                 if (rc != RPMRC_OK) {
02413                     rpmlog(RPMLOG_ERR, _("Unable to write package: %s\n"),
02414                                 Fstrerror(psm->fd));
02415                     break;
02416                 }
02417             }
02418 
02419             /* Write the signature section into the package. */
02420             /* XXX rpm-4.1 and later has archive size in signature header. */
02421             {   static const char item[] = "Signature";
02422                 Header sigh = headerRegenSigHeader(fi->h, noArchiveSize);
02423                 /* Reallocate the signature into one contiguous region. */
02424                 sigh = headerReload(sigh, RPMTAG_HEADERSIGNATURES);
02425                 if (sigh == NULL) {
02426                     rpmlog(RPMLOG_ERR, _("Unable to reload signature header\n"));
02427                     rc = RPMRC_FAIL;
02428                     break;
02429                 }
02430                 rc = rpmpkgWrite(item, psm->fd, sigh, NULL);
02431                 (void)headerFree(sigh);
02432                 sigh = NULL;
02433                 if (rc != RPMRC_OK) {
02434                     break;
02435                 }
02436             }
02437 
02438             /* Add remove transaction id to header. */
02439             if (psm->oh != NULL)
02440             {   rpmuint32_t tid = rpmtsGetTid(ts);
02441 
02442                 he->tag = RPMTAG_REMOVETID;
02443                 he->t = RPM_UINT32_TYPE;
02444                 he->p.ui32p = &tid;
02445                 he->c = 1;
02446                 xx = headerPut(psm->oh, he, 0);
02447 
02448                 /* Add original header's origin/digest/stat (i.e. URL) */
02449                 if (origin != NULL) {
02450                     he->tag = RPMTAG_PACKAGEORIGIN;
02451                     he->t = RPM_STRING_TYPE;
02452                     he->p.str = origin;
02453                     he->c = 1;
02454                     xx = headerPut(psm->oh, he, 0);
02455                     origin = _free(origin);
02456                 }
02457                 if (digest != NULL) {
02458                     he->tag = RPMTAG_PACKAGEDIGEST;
02459                     he->t = RPM_STRING_TYPE;
02460                     he->p.str = digest;
02461                     he->c = 1;
02462                     xx = headerPut(psm->oh, he, 0);
02463                     digest = _free(digest);
02464                 }
02465                 if (st != NULL) {
02466                     he->tag = RPMTAG_PACKAGESTAT;
02467                     he->t = RPM_BIN_TYPE;
02468                     he->p.ptr = (void *)st;
02469                     he->c = (rpmTagCount)nstbytes;
02470                     xx = headerPut(psm->oh, he, 0);
02471                     st = _free(st);
02472                 }
02473 
02474                 /* Copy upgrade chain link tags. */
02475                 xx = hCopyTag(fi->h, psm->oh, RPMTAG_INSTALLTID);
02476                 xx = hCopyTag(fi->h, psm->oh, RPMTAG_BLINKPKGID);
02477                 xx = hCopyTag(fi->h, psm->oh, RPMTAG_BLINKHDRID);
02478                 xx = hCopyTag(fi->h, psm->oh, RPMTAG_BLINKNEVRA);
02479 
02480 assert(psm->te != NULL);
02481                 xx = hSaveFlinks(psm->oh, &psm->te->flink);
02482             }
02483 
02484             /* Write the metadata section into the package. */
02485             {   const char item[] = "Header";
02486                 const char * msg = NULL;
02487                 rc = rpmpkgWrite(item, psm->fd, psm->oh, &msg);
02488                 if (rc != RPMRC_OK) {
02489                     rpmlog(RPMLOG_ERR, "%s: %s: %s", psm->pkgfn, item,
02490                         (msg && *msg ? msg : "write failed\n"));
02491                     msg = _free(msg);
02492                 }
02493             }
02494         }
02495         break;
02496     case PSM_PROCESS:
02497         if (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST)        break;
02498 
02499         if (psm->goal == PSM_PKGINSTALL) {
02500 
02501             if (rpmtsFlags(ts) & RPMTRANS_FLAG_JUSTDB)  break;
02502 
02503             /* XXX Synthesize callbacks for packages with no files. */
02504             if (rpmfiFC(fi) <= 0) {
02505                 void * ptr;
02506                 ptr = rpmtsNotify(ts, fi->te, RPMCALLBACK_INST_START, 0, 100);
02507                 ptr = rpmtsNotify(ts, fi->te, RPMCALLBACK_INST_PROGRESS, 100, 100);
02508                 break;
02509             }
02510 
02511             /* Retrieve type of payload compression. */
02512             rc = rpmpsmNext(psm, PSM_RPMIO_FLAGS);
02513 
02514             if (rpmteFd(fi->te) == NULL) {      /* XXX can't happen */
02515                 rc = RPMRC_FAIL;
02516                 break;
02517             }
02518 
02519             /*@-nullpass@*/     /* LCL: fi->fd != NULL here. */
02520             psm->cfd = Fdopen(fdDup(Fileno(rpmteFd(fi->te))), psm->rpmio_flags);
02521             /*@=nullpass@*/
02522             if (psm->cfd == NULL) {     /* XXX can't happen */
02523                 rc = RPMRC_FAIL;
02524                 break;
02525             }
02526 
02527             rc = fsmSetup(fi->fsm, IOSM_PKGINSTALL, psm->payload_format, ts, fi,
02528                         psm->cfd, NULL, &psm->failedFile);
02529             (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_UNCOMPRESS),
02530                         fdstat_op(psm->cfd, FDSTAT_READ));
02531             (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_DIGEST),
02532                         fdstat_op(psm->cfd, FDSTAT_DIGEST));
02533             xx = fsmTeardown(fi->fsm);
02534 
02535             saveerrno = errno; /* XXX FIXME: Fclose with libio destroys errno */
02536             xx = Fclose(psm->cfd);
02537             psm->cfd = NULL;
02538             /*@-mods@*/
02539             errno = saveerrno; /* XXX FIXME: Fclose with libio destroys errno */
02540             /*@=mods@*/
02541 
02542             if (!rc)
02543                 rc = rpmpsmNext(psm, PSM_COMMIT);
02544 
02545             /* XXX make sure progress is closed out */
02546             psm->what = RPMCALLBACK_INST_PROGRESS;
02547             psm->amount = (fi->archiveSize ? fi->archiveSize : 100);
02548             psm->total = psm->amount;
02549             xx = rpmpsmNext(psm, PSM_NOTIFY);
02550 
02551             if (rc) {
02552                 const char * msg = iosmStrerror(rc);
02553                 rpmlog(RPMLOG_ERR,
02554                         _("unpacking of archive failed%s%s: %s\n"),
02555                         (psm->failedFile != NULL ? _(" on file ") : ""),
02556                         (psm->failedFile != NULL ? psm->failedFile : ""),
02557                         msg);
02558                 msg = _free(msg);
02559                 rc = RPMRC_FAIL;
02560 
02561                 /* XXX notify callback on error. */
02562                 psm->what = RPMCALLBACK_UNPACK_ERROR;
02563                 psm->amount = 0;
02564                 psm->total = 0;
02565                 xx = rpmpsmNext(psm, PSM_NOTIFY);
02566 
02567                 break;
02568             }
02569         }
02570         if (psm->goal == PSM_PKGERASE) {
02571             int fc = rpmfiFC(fi);
02572 
02573             if (rpmtsFlags(ts) & RPMTRANS_FLAG_JUSTDB)  break;
02574             if (rpmtsFlags(ts) & RPMTRANS_FLAG_APPLYONLY)       break;
02575 
02576             psm->what = RPMCALLBACK_UNINST_START;
02577             psm->amount = fc;
02578             psm->total = (fc ? fc : 100);
02579             xx = rpmpsmNext(psm, PSM_NOTIFY);
02580 
02581             if (fc > 0) {
02582                 rc = fsmSetup(fi->fsm, IOSM_PKGERASE, psm->payload_format, ts, fi,
02583                         NULL, NULL, &psm->failedFile);
02584                 xx = fsmTeardown(fi->fsm);
02585             }
02586 
02587             psm->what = RPMCALLBACK_UNINST_STOP;
02588             psm->amount = (fc ? fc : 100);
02589             psm->total = (fc ? fc : 100);
02590             xx = rpmpsmNext(psm, PSM_NOTIFY);
02591 
02592         }
02593         if (psm->goal == PSM_PKGSAVE) {
02594             iosmFileAction * actions = (iosmFileAction *) fi->actions;
02595             iosmFileAction action = (iosmFileAction) fi->action;
02596 
02597             fi->action = FA_COPYOUT;
02598             fi->actions = NULL;
02599 
02600             if (psm->fd == NULL) {      /* XXX can't happen */
02601                 rc = RPMRC_FAIL;
02602                 break;
02603             }
02604             /*@-nullpass@*/     /* FIX: fdDup mey return NULL. */
02605             xx = Fflush(psm->fd);
02606             psm->cfd = Fdopen(fdDup(Fileno(psm->fd)), psm->rpmio_flags);
02607             /*@=nullpass@*/
02608             if (psm->cfd == NULL) {     /* XXX can't happen */
02609                 rc = RPMRC_FAIL;
02610                 break;
02611             }
02612 
02613             rc = fsmSetup(fi->fsm, IOSM_PKGBUILD, psm->payload_format, ts, fi,
02614                         psm->cfd, NULL, &psm->failedFile);
02615             (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_COMPRESS),
02616                         fdstat_op(psm->cfd, FDSTAT_WRITE));
02617             (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_DIGEST),
02618                         fdstat_op(psm->cfd, FDSTAT_DIGEST));
02619             xx = fsmTeardown(fi->fsm);
02620 
02621             saveerrno = errno; /* XXX FIXME: Fclose with libio destroys errno */
02622             xx = Fclose(psm->cfd);
02623             psm->cfd = NULL;
02624             /*@-mods@*/
02625             errno = saveerrno;
02626             /*@=mods@*/
02627 
02628             /* XXX make sure progress is closed out */
02629             psm->what = RPMCALLBACK_INST_PROGRESS;
02630             psm->amount = (fi->archiveSize ? fi->archiveSize : 100);
02631             psm->total = psm->amount;
02632             xx = rpmpsmNext(psm, PSM_NOTIFY);
02633 
02634             fi->action = (int) action;
02635             fi->actions = (int *) actions;
02636         }
02637         break;
02638     case PSM_POST:
02639         if (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST)        break;
02640 
02641         if (psm->goal == PSM_PKGINSTALL) {
02642 
02643             /*
02644              * If this header has already been installed, remove it from
02645              * the database before adding the new header.
02646              */
02647             if (fi->record && !(rpmtsFlags(ts) & RPMTRANS_FLAG_APPLYONLY)) {
02648                 rc = rpmpsmNext(psm, PSM_RPMDB_REMOVE);
02649                 if (rc) break;
02650             }
02651 
02652             /* Add fi->fstates to install header. */
02653             xx = postPopulateInstallHeader(ts, psm->te, fi);
02654 
02655             rc = rpmpsmNext(psm, PSM_RPMDB_ADD);
02656             if (rc) break;
02657 
02658             psm->scriptTag = RPMTAG_POSTIN;
02659             psm->progTag = RPMTAG_POSTINPROG;
02660             psm->sense = RPMSENSE_TRIGGERIN;
02661             psm->countCorrection = 0;
02662 
02663             if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOPOST)) {
02664                 rc = rpmpsmNext(psm, PSM_SCRIPT);
02665                 if (rc) break;
02666             }
02667             if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOTRIGGERIN)) {
02668                 /* Run triggers in other package(s) this package sets off. */
02669                 rc = rpmpsmNext(psm, PSM_TRIGGERS);
02670                 if (rc) break;
02671 
02672                 /* Run triggers in this package other package(s) set off. */
02673                 rc = rpmpsmNext(psm, PSM_IMMED_TRIGGERS);
02674                 if (rc) break;
02675             }
02676 
02677             if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_APPLYONLY))
02678                 rc = markReplacedFiles(psm);
02679 
02680         }
02681         if (psm->goal == PSM_PKGERASE) {
02682 
02683             psm->scriptTag = RPMTAG_POSTUN;
02684             psm->progTag = RPMTAG_POSTUNPROG;
02685             psm->sense = RPMSENSE_TRIGGERPOSTUN;
02686             psm->countCorrection = -1;
02687 
02688             if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOPOSTUN)) {
02689                 rc = rpmpsmNext(psm, PSM_SCRIPT);
02690                 if (rc) break;
02691             }
02692 
02693             if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOTRIGGERPOSTUN)) {
02694                 /* Run triggers in other package(s) this package sets off. */
02695                 rc = rpmpsmNext(psm, PSM_TRIGGERS);
02696                 if (rc) break;
02697 
02698                 /* Run triggers in this package other package(s) set off. */
02699                 rc = rpmpsmNext(psm, PSM_IMMED_TRIGGERS);
02700                 if (rc) break;
02701             }
02702 
02703             if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_APPLYONLY))
02704                 rc = rpmpsmNext(psm, PSM_RPMDB_REMOVE);
02705         }
02706         if (psm->goal == PSM_PKGSAVE) {
02707         }
02708 
02709         /* Restore root directory if changed. */
02710         xx = rpmpsmNext(psm, PSM_CHROOT_OUT);
02711         break;
02712     case PSM_UNDO:
02713         break;
02714     case PSM_FINI:
02715         /* Restore root directory if changed. */
02716         xx = rpmpsmNext(psm, PSM_CHROOT_OUT);
02717 
02718         if (psm->fd != NULL) {
02719             saveerrno = errno; /* XXX FIXME: Fclose with libio destroys errno */
02720             xx = Fclose(psm->fd);
02721             psm->fd = NULL;
02722             /*@-mods@*/
02723             errno = saveerrno;
02724             /*@=mods@*/
02725         }
02726 
02727         if (psm->goal == PSM_PKGSAVE) {
02728             if (!rc && ts && ts->notify == NULL) {
02729                 rpmlog(RPMLOG_INFO, _("Wrote: %s\n"),
02730                         (psm->pkgURL ? psm->pkgURL : "???"));
02731             }
02732         }
02733 
02734         if (rc) {
02735             const char * msg = iosmStrerror(rc);
02736             if (psm->failedFile)
02737                 rpmlog(RPMLOG_ERR,
02738                         _("%s failed on file %s: %s\n"),
02739                         psm->stepName, psm->failedFile, msg);
02740             else
02741                 rpmlog(RPMLOG_ERR, _("%s failed: %s\n"),
02742                         psm->stepName, msg);
02743             msg = _free(msg);
02744 
02745             /* XXX notify callback on error. */
02746             psm->what = RPMCALLBACK_CPIO_ERROR;
02747             psm->amount = 0;
02748             psm->total = 0;
02749             /*@-nullstate@*/ /* FIX: psm->fd may be NULL. */
02750             xx = rpmpsmNext(psm, PSM_NOTIFY);
02751             /*@=nullstate@*/
02752         }
02753 
02754         if (psm->goal == PSM_PKGERASE || psm->goal == PSM_PKGSAVE) {
02755 #ifdef  DYING
02756 if (psm->te != NULL)
02757 if (psm->te->h != NULL) {
02758 (void)headerFree(psm->te->h);
02759 psm->te->h = NULL;
02760 }
02761 #else
02762             if (psm->te != NULL)
02763                 (void) rpmteSetHeader(psm->te, NULL);
02764 #endif
02765             if (fi->h != NULL) {
02766                 (void)headerFree(fi->h);
02767                 fi->h = NULL;
02768             }
02769         }
02770         (void)headerFree(psm->oh);
02771         psm->oh = NULL;
02772         psm->pkgURL = _free(psm->pkgURL);
02773         psm->rpmio_flags = _free(psm->rpmio_flags);
02774         psm->payload_format = _free(psm->payload_format);
02775         psm->failedFile = _free(psm->failedFile);
02776 
02777         fi->fgroup = _free(fi->fgroup);
02778         fi->fuser = _free(fi->fuser);
02779         fi->apath = _free(fi->apath);
02780         fi->fstates = _free(fi->fstates);
02781         break;
02782 
02783     case PSM_PKGINSTALL:
02784     case PSM_PKGERASE:
02785     case PSM_PKGSAVE:
02786         psm->goal = stage;
02787         psm->rc = RPMRC_OK;
02788         psm->stepName = pkgStageString(stage);
02789 
02790         rc = rpmpsmNext(psm, PSM_INIT);
02791         if (!rc) rc = rpmpsmNext(psm, PSM_PRE);
02792         if (!rc) rc = rpmpsmNext(psm, PSM_PROCESS);
02793         if (!rc) rc = rpmpsmNext(psm, PSM_POST);
02794         xx = rpmpsmNext(psm, PSM_FINI);
02795         break;
02796     case PSM_PKGCOMMIT:
02797         break;
02798 
02799     case PSM_CREATE:
02800         break;
02801     case PSM_NOTIFY:
02802     {   void * ptr;
02803 /*@-nullpass@*/ /* FIX: psm->te may be NULL */
02804         ptr = rpmtsNotify(ts, psm->te, psm->what, psm->amount, psm->total);
02805 /*@-nullpass@*/
02806     }   break;
02807     case PSM_DESTROY:
02808         break;
02809     case PSM_COMMIT:
02810         if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_PKGCOMMIT)) break;
02811         if (rpmtsFlags(ts) & RPMTRANS_FLAG_APPLYONLY) break;
02812 
02813         rc = fsmSetup(fi->fsm, IOSM_PKGCOMMIT, psm->payload_format, ts, fi,
02814                         NULL, NULL, &psm->failedFile);
02815         xx = fsmTeardown(fi->fsm);
02816         break;
02817 
02818     case PSM_CHROOT_IN:
02819     {   const char * rootDir = rpmtsRootDir(ts);
02820         /* Change root directory if requested and not already done. */
02821         if (rootDir != NULL && !(rootDir[0] == '/' && rootDir[1] == '\0')
02822          && !rpmtsChrootDone(ts) && !F_ISSET(psm, CHROOTDONE))
02823         {
02824             static int _pw_loaded = 0;
02825             static int _gr_loaded = 0;
02826 
02827             if (!_pw_loaded) {
02828                 (void)getpwnam("root");
02829                 endpwent();
02830                 _pw_loaded++;
02831             }
02832             if (!_gr_loaded) {
02833                 (void)getgrnam("root");
02834                 endgrent();
02835                 _gr_loaded++;
02836             }
02837 
02838             xx = Chdir("/");
02839             /*@-modobserver@*/
02840             if (rootDir != NULL && strcmp(rootDir, "/") && *rootDir == '/')
02841                 rc = Chroot(rootDir);
02842             /*@=modobserver@*/
02843             F_SET(psm, CHROOTDONE);
02844             (void) rpmtsSetChrootDone(ts, 1);
02845         }
02846     }   break;
02847     case PSM_CHROOT_OUT:
02848         /* Restore root directory if changed. */
02849         if (F_ISSET(psm, CHROOTDONE)) {
02850             const char * rootDir = rpmtsRootDir(ts);
02851             const char * currDir = rpmtsCurrDir(ts);
02852             /*@-modobserver@*/
02853             if (rootDir != NULL && strcmp(rootDir, "/") && *rootDir == '/')
02854                 rc = Chroot(".");
02855             /*@=modobserver@*/
02856             F_CLR(psm, CHROOTDONE);
02857             (void) rpmtsSetChrootDone(ts, 0);
02858             if (currDir != NULL)        /* XXX can't happen */
02859                 xx = Chdir(currDir);
02860         }
02861         break;
02862     case PSM_SCRIPT:    /* Run current package scriptlets. */
02863         rc = runInstScript(psm);
02864         break;
02865     case PSM_TRIGGERS:
02866         /* Run triggers in other package(s) this package sets off. */
02867         if (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST)        break;
02868         rc = runTriggers(psm);
02869         break;
02870     case PSM_IMMED_TRIGGERS:
02871         /* Run triggers in this package other package(s) set off. */
02872         if (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST)        break;
02873         if (!F_ISSET(psm, GOTTRIGGERS)) {
02874             psm->triggers = rpmdsNew(fi->h, RPMTAG_TRIGGERNAME, 0);
02875             F_SET(psm, GOTTRIGGERS);
02876         }
02877         if (psm->triggers != NULL)
02878             rc = runImmedTriggers(psm);
02879         break;
02880 
02881     case PSM_RPMIO_FLAGS:
02882     {   const char * payload_compressor = NULL;
02883         const char * payload_format = NULL;
02884         char * t;
02885 
02886         he->tag = RPMTAG_PAYLOADCOMPRESSOR;
02887         xx = headerGet(fi->h, he, 0);
02888         payload_compressor = he->p.str;
02889         if (payload_compressor == NULL)
02890             payload_compressor = xstrdup("gzip");
02891 
02892         psm->rpmio_flags = t = xmalloc(sizeof("w9.gzdio"));
02893         *t = '\0';
02894         t = stpcpy(t, ((psm->goal == PSM_PKGSAVE) ? "w9" : "r"));
02895         if (!strcmp(payload_compressor, "gzip"))
02896             t = stpcpy(t, ".gzdio");
02897         if (!strcmp(payload_compressor, "bzip2"))
02898             t = stpcpy(t, ".bzdio");
02899         if (!strcmp(payload_compressor, "lzma"))
02900             t = stpcpy(t, ".lzdio");
02901         if (!strcmp(payload_compressor, "xz"))
02902             t = stpcpy(t, ".xzdio");
02903         payload_compressor = _free(payload_compressor);
02904 
02905         he->tag = RPMTAG_PAYLOADFORMAT;
02906         xx = headerGet(fi->h, he, 0);
02907         payload_format = he->p.str;
02908         if (!xx || payload_format == NULL || !(
02909           !strcmp(payload_format, "tar") || !strcmp(payload_format, "ustar")
02910 #if defined(SUPPORT_AR_PAYLOADS)
02911          || !strcmp(payload_format, "ar")
02912 #endif
02913            ))
02914         {
02915             payload_format = _free(payload_format);
02916             payload_format = xstrdup("cpio");
02917         }
02918         psm->payload_format = _free(psm->payload_format);
02919         psm->payload_format = payload_format;
02920         rc = RPMRC_OK;
02921     }   break;
02922 
02923     case PSM_RPMDB_LOAD:
02924 assert(psm->mi == NULL);
02925         psm->mi = rpmtsInitIterator(ts, RPMDBI_PACKAGES,
02926                                 &fi->record, sizeof(fi->record));
02927         fi->h = rpmmiNext(psm->mi);
02928 /*@-castexpose@*/
02929         if (fi->h != NULL)
02930             fi->h = headerLink(fi->h);
02931 /*@=castexpose@*/
02932         psm->mi = rpmmiFree(psm->mi);
02933 
02934         if (fi->h != NULL) {
02935             (void) headerSetInstance(fi->h, fi->record);
02936             rc = RPMRC_OK;
02937         } else
02938             rc = RPMRC_FAIL;
02939         break;
02940     case PSM_RPMDB_ADD:
02941         if (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST)        break;
02942         if (rpmtsFlags(ts) & RPMTRANS_FLAG_NORPMDB)     break;
02943         if (fi->isSource)       break;  /* XXX never add SRPM's */
02944         if (fi->h == NULL)      break;  /* XXX can't happen */
02945 
02946         /* Add header to db, doing header check if requested */
02947         /* XXX rollback headers propagate the previous transaction id. */
02948         {   rpmuint32_t tid = ((rpmtsType(ts) == RPMTRANS_TYPE_ROLLBACK)
02949                 ? hLoadTID(fi->h, RPMTAG_INSTALLTID) : rpmtsGetTid(ts));
02950             (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DBADD), 0);
02951             if (!(rpmtsVSFlags(ts) & RPMVSF_NOHDRCHK))
02952                 rc = rpmdbAdd(rpmtsGetRdb(ts), tid, fi->h, ts);
02953             else
02954                 rc = rpmdbAdd(rpmtsGetRdb(ts), tid, fi->h, NULL);
02955             (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DBADD), 0);
02956 #if defined(HAVE_SYSLOG_H) && defined(RPM_VENDOR_MANDRIVA) /* log-install-remove-to-syslog */
02957             {
02958                     char *s;
02959 
02960                     s = headerSprintf(fi->h, "%{NAME}-%{VERSION}-%{RELEASE}",
02961                                     rpmTagTable, rpmHeaderFormats, NULL);
02962                     syslog(LOG_NOTICE, "[RPM] %s installed\n", s);
02963                     s = _free(s);
02964             }
02965 #endif
02966         }
02967 
02968         if (rc != RPMRC_OK) break;
02969 
02970 assert(psm->te != NULL);
02971         /* Mark non-rollback elements as installed. */
02972         if (rpmtsType(ts) != RPMTRANS_TYPE_ROLLBACK)
02973             psm->te->installed = 1;
02974 
02975         /* Set the database instance for (possible) rollbacks. */
02976         rpmteSetDBInstance(psm->te, headerGetInstance(fi->h));
02977 
02978         break;
02979     case PSM_RPMDB_REMOVE:
02980     {   
02981         if (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST)        break;
02982         if (rpmtsFlags(ts) & RPMTRANS_FLAG_NORPMDB)     break;
02983 
02984         (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DBREMOVE), 0);
02985         rc = rpmdbRemove(rpmtsGetRdb(ts), rpmtsGetTid(ts), fi->record, NULL);
02986         (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DBREMOVE), 0);
02987 #if defined(HAVE_SYSLOG_H) && defined(RPM_VENDOR_MANDRIVA) /* log-install-remove-to-syslog */
02988         {
02989           char *s;
02990 
02991           s = headerSprintf(fi->h, "%{NAME}-%{VERSION}-%{RELEASE}",
02992                             rpmTagTable, rpmHeaderFormats, NULL);
02993           syslog(LOG_NOTICE, "[RPM] %s removed\n", s);
02994           s = _free(s);
02995         }
02996 #endif
02997 
02998         if (rc != RPMRC_OK) break;
02999 
03000         /* Forget the offset of a successfully removed header. */
03001         if (psm->te != NULL)    /* XXX can't happen */
03002             psm->te->u.removed.dboffset = 0;
03003 
03004     }   break;
03005 
03006     default:
03007         break;
03008 /*@i@*/    }
03009 
03010 /*@-nullstate@*/        /* FIX: psm->oh and psm->fi->h may be NULL. */
03011     return rc;
03012 /*@=nullstate@*/
03013 }
03014 /*@=nullpass@*/

Generated on Fri Dec 3 2010 20:53:27 for rpm by  doxygen 1.7.2