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