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