rpm 5.2.1

- 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@*/