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