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