static int rpmcliTransaction(rpmts ts, struct rpmInstallArguments_s * ia, int numPackages) { rpmps ps; int rc = 0; int stop = 0; int eflags = ia->installInterfaceFlags & INSTALL_ERASE; if (!(ia->installInterfaceFlags & INSTALL_NODEPS)) { if (rpmtsCheck(ts)) { rc = numPackages; stop = 1; } ps = rpmtsProblems(ts); if (!stop && rpmpsNumProblems(ps) > 0) { rpmlog(RPMLOG_ERR, _("Failed dependencies:\n")); rpmpsPrint(NULL, ps); rc = numPackages; stop = 1; } ps = rpmpsFree(ps); } if (!stop && !(ia->installInterfaceFlags & INSTALL_NOORDER)) { if (rpmtsOrder(ts)) { rc = numPackages; stop = 1; } } if (numPackages && !stop) { rpmlog(RPMLOG_DEBUG, eflags ? "erasing packages\n" : "installing binary packages\n"); rpmtsClean(ts); rc = rpmtsRun(ts, NULL, ia->probFilter); ps = rpmtsProblems(ts); if (rpmpsNumProblems(ps) > 0 && (eflags || rc > 0)) rpmpsPrint(NULL, ps); ps = rpmpsFree(ps); } return rc; }
int doCheck(PTDNFRPMTS pTS) { int nResult = 0; rpmpsi psi = NULL; rpmProblem prob = NULL; nResult = rpmtsCheck(pTS->pTS); rpmps ps = rpmtsProblems(pTS->pTS); if(ps) { int nProbs = rpmpsNumProblems(ps); if(nProbs > 0) { printf("Found %d problems\n", nProbs); psi = rpmpsInitIterator(ps); while(rpmpsNextIterator(psi) >= 0) { prob = rpmpsGetProblem(psi); printf("Prob = %s, type = %d, nevr1=%s, nevr2=%s\n", rpmProblemGetStr(prob), rpmProblemGetType(prob), rpmProblemGetPkgNEVR(prob), rpmProblemGetAltNEVR(prob)); rpmProblemFree(prob); } rpmpsFreeIterator(psi); } } return nResult; }
/** * Check installed package dependencies for problems. * @param qva parsed query/verify options * @param ts transaction set * @param h header * @return number of problems found (0 for no problems) */ static int verifyDependencies(QVA_t qva, rpmts ts, Header h) { rpmps ps; rpmpsi psi; int rc = 0; /* assume no problems */ int xx; rpmtsEmpty(ts); (void) rpmtsAddInstallElement(ts, h, NULL, 0, NULL); xx = rpmtsCheck(ts); ps = rpmtsProblems(ts); psi = rpmpsInitIterator(ps); if (rpmpsNumProblems(ps) > 0) { char *nevra = headerGetNEVRA(h, NULL); rpmlog(RPMLOG_NOTICE, _("Unsatisfied dependencies for %s:\n"), nevra); free(nevra); while (rpmpsNextIterator(psi) >= 0) { rpmProblem p = rpmpsGetProblem(psi); char * ps = rpmProblemString(p); rpmlog(RPMLOG_NOTICE, "\t%s\n", ps); free(ps); rc++; } } psi = rpmpsFreeIterator(psi); ps = rpmpsFree(ps); rpmtsEmpty(ts); return rc; }
/** * Check installed package dependencies for problems. * @param ts transaction set * @param h header * @return number of problems found (0 for no problems) */ static int verifyDependencies(rpmts ts, Header h) { rpmps ps; rpmte te; int rc; rpmtsEmpty(ts); (void) rpmtsAddInstallElement(ts, h, NULL, 0, NULL); (void) rpmtsCheck(ts); te = rpmtsElement(ts, 0); ps = rpmteProblems(te); rc = rpmpsNumProblems(ps); if (rc > 0) { rpmlog(RPMLOG_NOTICE, _("Unsatisfied dependencies for %s:\n"), rpmteNEVRA(te)); rpmpsi psi = rpmpsInitIterator(ps); rpmProblem p; while ((p = rpmpsiNext(psi)) != NULL) { char * ps = rpmProblemString(p); rpmlog(RPMLOG_NOTICE, "\t%s\n", ps); free(ps); } rpmpsFreeIterator(psi); } rpmpsFree(ps); rpmtsEmpty(ts); return rc; }
rpmProblem rpmpsGetProblem(rpmpsi psi) { rpmProblem *p = NULL; if (psi != NULL && psi->ix >= 0 && psi->ix < rpmpsNumProblems(psi->ps)) { p = psi->ps->probs + psi->ix; } return p ? *p : NULL; }
rpmProblem rpmpsGetProblem(rpmpsi psi) { rpmProblem p = NULL; if (psi != NULL && psi->ix >= 0 && psi->ix < rpmpsNumProblems(psi->ps)) { p = psi->ps->probs[psi->ix]; } return p; }
/************************************************************************* * FUNCTION : RPMTransaction_Set::Problems * * ARGUMENTS : interp * * RETURNS : TCL_OK or TCL_ERROR * * EXCEPTIONS : none * * PURPOSE : Return current problem set as TCL list * *************************************************************************/ int RPMTransaction_Set::Problems(Tcl_Interp *interp,int , Tcl_Obj *const []) { rpmps problems = rpmtsProblems(transaction); int num_probs = rpmpsNumProblems(problems); Tcl_Obj *rv = 0; for (int i = 0; i < num_probs; ++i) { rpmProblem what = &problems->probs[i]; rv = Grow_list(rv,RPMPRoblem_Obj::Create_from_problem(*what)); } return OK(rv); }
int rpmpsNextIterator(rpmpsi psi) { int i = -1; if (psi != NULL && ++psi->ix >= 0) { if (psi->ix < rpmpsNumProblems(psi->ps)) { i = psi->ix; } else { psi->ix = -1; } } return i; }
rpmps rpmtsProblems(rpmts ts) { rpmps ps = rpmpsCreate(); rpmtsi pi = rpmtsiInit(ts); rpmte p; while ((p = rpmtsiNext(pi, 0)) != NULL) { rpmps teprobs = rpmteProblems(p); rpmpsMerge(ps, teprobs); rpmpsFree(teprobs); } rpmtsiFree(pi); /* Return NULL on no problems instead of an empty set */ if (rpmpsNumProblems(ps) == 0) { ps = rpmpsFree(ps); } return ps; }
static JSBool rpmps_getprop(JSContext *cx, JSObject *obj, jsid id, jsval *vp) { void * ptr = JS_GetInstancePrivate(cx, obj, &rpmpsClass, NULL); rpmps ps = ptr; jsint tiny = JSVAL_TO_INT(id); /* XXX the class has ptr == NULL, instances have ptr != NULL. */ if (ptr == NULL) return JS_TRUE; switch (tiny) { case _DEBUG: *vp = INT_TO_JSVAL(_debug); break; case _LENGTH: *vp = INT_TO_JSVAL(rpmpsNumProblems(ps)); break; default: break; } return JS_TRUE; }
/* * Performs the transaction. * @param [Number] flag Transaction flags, default +RPM::TRANS_FLAG_NONE+ * @param [Number] filter Transaction filter, default +RPM::PROB_FILTER_NONE+ * @example * transaction.commit do |sig| * end * @yield [CallbackData] sig Transaction progress */ VALUE rpm_transaction_commit(int argc, VALUE* argv, VALUE trans) { #if RPM_VERSION_CODE < RPM_VERSION(4,1,0) rpmProblemSet probset; int flags = RPMTRANS_FLAG_NONE; int ignores = RPMPROB_FILTER_NONE; int rc; VALUE db; db = rb_ivar_get(trans, id_db); if (OBJ_FROZEN(db)) { rb_error_frozen("RPM::DB"); } switch (argc) { case 0: break; case 1: case 2: flags = NUM2INT(rb_Integer(argv[0])); if (argc == 2) { ignores = NUM2INT(rb_Integer(argv[1])); } break; default: rb_raise(rb_eArgError, "too many arguments(0..2)"); } if (rb_block_given_p() == Qtrue) rc = rpmRunTransactions(RPM_TRANSACTION(trans), transaction_callback, (void*)trans, NULL, &probset, flags, ignores); else{ VALUE keys; /* rpmcli.h:extern int packagesTotal; */ packagesTotal = 0; keys = rpm_transaction_keys(trans); if (!NIL_P(keys)) packagesTotal = NUM2INT(rb_funcall(keys,rb_intern("length"),0)); rc = rpmRunTransactions(RPM_TRANSACTION(trans), rpmShowProgress, (void*)((long)(INSTALL_HASH|INSTALL_LABEL)), NULL, &probset, flags, ignores); } if (probset != NULL) { VALUE list = rb_ary_new(); register int i; for (i = 0; i < probset->numProblems; i++) { rpmProblem prob = probset->probs + i; VALUE prb = rb_struct_new(rpm_sProblem, INT2NUM(prob->type), (VALUE)prob->key, rpm_package_new_from_header(prob->h), rb_str_new2(rpmProblemString(prob))); rb_ary_push(list, prb); } rb_ivar_set(trans, id_pl, list); } #else rpmps ps; int flags = RPMTRANS_FLAG_NONE; int ignores = RPMPROB_FILTER_NONE; int rc; VALUE db; db = rb_ivar_get(trans, id_db); if (OBJ_FROZEN(db)) { rb_error_frozen("RPM::DB"); } switch (argc) { case 0: break; case 1: case 2: flags = NUM2INT(rb_Integer(argv[0])); if (argc == 2) { ignores = NUM2INT(rb_Integer(argv[1])); } break; default: rb_raise(rb_eArgError, "too many arguments(0..2)"); } /* Drop added/available package indices and dependency sets. */ //rpmtsClean(RPM_TRANSACTION(trans)); // zaki: required? if (rb_block_given_p() == Qtrue) { rpmtsSetNotifyCallback(RPM_TRANSACTION(trans), (rpmCallbackFunction)transaction_callback,(void *)trans); }else{ VALUE keys; /* rpmcli.h:extern int rpmcliPackagesTotal; */ rpmcliPackagesTotal = 0; keys = rpm_transaction_keys(trans); if (!NIL_P(keys)) rpmcliPackagesTotal = NUM2INT(rb_funcall(keys,rb_intern("length"),0)); rpmtsSetNotifyCallback(RPM_TRANSACTION(trans), rpmShowProgress, (void*)((long)(INSTALL_HASH|INSTALL_LABEL))); } rc = rpmtsRun(RPM_TRANSACTION(trans), NULL, ignores); ps = rpmtsProblems(RPM_TRANSACTION(trans)); { VALUE list = rb_ary_new(); #ifdef RPMPS_OPAQUE rpmpsi psi = rpmpsInitIterator(ps); while (rpmpsNextIterator(psi) >= 0) { rpmProblem p = rpmpsGetProblem(psi); VALUE prb = rb_struct_new(rpm_sProblem, INT2NUM(rpmProblemGetType(p)), (VALUE)rpmProblemGetKey(p), package_new_from_NEVR( rpmProblemGetAltNEVR(p)+2 ), rb_str_new2(rpmProblemString(p))); rb_ary_push(list, prb); } #else if (ps != NULL && rpmpsNumProblems(ps) > 0) { register int i; for (i = 0; i < rpmpsNumProblems(ps); i++) { rpmProblem p = ps->probs + i; const char *altNEVR = (p->altNEVR ? p->altNEVR : "? ?altNEVR?"); VALUE prb = rb_struct_new(rpm_sProblem, INT2NUM(p->type), (VALUE)p->key, package_new_from_NEVR(altNEVR+2), rb_str_new2(rpmProblemString(p))); rb_ary_push(list, prb); } } #endif rb_ivar_set(trans, id_pl, list); } if (ps) ps = rpmpsFree(ps); #endif rb_ivar_set(trans, id_commited, Qtrue); rb_throw("abort", Qnil); return Qnil; /* NOT REACHED */ }
int main(int argc, char **argv) { rpmts ts; rpmps probs; int probFilter = 0; int notifyFlags = 0; int tsFlags = 0; int rc = 0; /* Read configuration, initialize transaction */ rpmReadConfigFiles(NULL, NULL); ts = rpmtsCreate(); /* Set verification flags if needed, for example --nomd5 */ /* rpmtsSetVSFlags(ts, rpmtsVSFlags(ts) | RPMVSF_NOMD5); */ /* Open rpmdb */ //rpmtsSetRootDir(ts, NULL); rc = rpmtsOpenDB(ts, O_RDWR); if (rc) { printf("Error opening rpmdb\n"); goto exit; } /* Add packages for install/upgrade/erase */ while (optind < argc) { int upgrade = 0; switch (getopt(argc, argv, "i:U:e:")) { case 'U': upgrade = 1; case 'i': add_for_install(ts, optarg, upgrade); break; case 'e': add_for_erase(ts, optarg); break; default: printf("usage ...\n"); goto exit; } } /* Set problem filters if needed, for example --oldpackage */ /* rpmbFilter |= RPMPROB_FILTER_OLDPACKAGE /* /* Set transaction flags if needed, for example --excludedocs */ /* tsFlags |= RPMTRANS_FLAG_NODOCS */ /* Check transaction sanity */ rc = rpmtsCheck(ts); probs = rpmtsProblems(ts); if (rc || rpmpsNumProblems(probs)) { rpmpsPrint(NULL, probs); rpmpsFree(probs); goto exit; } /* Create ordering for the transaction */ rc = rpmtsOrder(ts); if (rc > 0) { printf("Ordering failed\n"); goto exit; } rpmtsClean(ts); /* Set callback routine & flags, for example -vh */ notifyFlags |= INSTALL_LABEL | INSTALL_HASH; rpmtsSetNotifyCallback(ts, rpmShowProgress, (void *)notifyFlags); /* Set transaction flags and run the actual transaction */ rpmtsSetFlags(ts, (rpmtransFlags)(rpmtsFlags(ts) | tsFlags)); rc = rpmtsRun(ts, NULL, (rpmprobFilterFlags)probFilter); /* Check for results .. */ if (rc || rpmpsNumProblems(probs) > 0) rpmpsPrint(stderr, probs); rpmpsFree(probs); exit: /* ..and clean up */ rpmtsFree(ts); exit(rc); }
int rpmErase(rpmts ts, struct rpmInstallArguments_s * ia, ARGV_const_t argv) { char * const * arg; char *qfmt = NULL; int numFailed = 0; int stopUninstall = 0; int numPackages = 0; rpmVSFlags vsflags, ovsflags; rpmps ps; if (argv == NULL) return 0; vsflags = rpmExpandNumeric("%{?_vsflags_erase}"); if (ia->qva_flags & VERIFY_DIGEST) vsflags |= _RPMVSF_NODIGESTS; if (ia->qva_flags & VERIFY_SIGNATURE) vsflags |= _RPMVSF_NOSIGNATURES; if (ia->qva_flags & VERIFY_HDRCHK) vsflags |= RPMVSF_NOHDRCHK; ovsflags = rpmtsSetVSFlags(ts, vsflags); /* XXX suggest mechanism only meaningful when installing */ ia->transFlags |= RPMTRANS_FLAG_NOSUGGEST; (void) rpmtsSetFlags(ts, ia->transFlags); #ifdef NOTYET /* XXX no callbacks on erase yet */ { int notifyFlags, xx; notifyFlags = ia->eraseInterfaceFlags | (rpmIsVerbose() ? INSTALL_LABEL : 0 ); xx = rpmtsSetNotifyCallback(ts, rpmShowProgress, (void *) ((long)notifyFlags)); } #endif qfmt = rpmExpand("%{?_query_all_fmt}\n", NULL); for (arg = argv; *arg; arg++) { rpmdbMatchIterator mi; int matches = 0; int erasing = 1; /* Iterator count isn't reliable with labels, count manually... */ mi = rpmtsInitIterator(ts, RPMDBI_LABEL, *arg, 0); while (rpmdbNextIterator(mi) != NULL) { matches++; } rpmdbFreeIterator(mi); if (! matches) { rpmlog(RPMLOG_ERR, _("package %s is not installed\n"), *arg); numFailed++; } else { Header h; /* XXX iterator owns the reference */ if (matches > 1 && !(ia->eraseInterfaceFlags & UNINSTALL_ALLMATCHES)) { rpmlog(RPMLOG_ERR, _("\"%s\" specifies multiple packages:\n"), *arg); numFailed++; erasing = 0; } mi = rpmtsInitIterator(ts, RPMDBI_LABEL, *arg, 0); while ((h = rpmdbNextIterator(mi)) != NULL) { if (erasing) { (void) rpmtsAddEraseElement(ts, h, -1); numPackages++; } else { char *nevra = headerFormat(h, qfmt, NULL); rpmlog(RPMLOG_NOTICE, " %s", nevra); free(nevra); } } mi = rpmdbFreeIterator(mi); } } free(qfmt); if (numFailed) goto exit; if (!(ia->eraseInterfaceFlags & UNINSTALL_NODEPS)) { if (rpmtsCheck(ts)) { numFailed = numPackages; stopUninstall = 1; } ps = rpmtsProblems(ts); if (!stopUninstall && rpmpsNumProblems(ps) > 0) { rpmlog(RPMLOG_ERR, _("Failed dependencies:\n")); rpmpsPrint(NULL, ps); numFailed += numPackages; stopUninstall = 1; } ps = rpmpsFree(ps); } if (!stopUninstall && !(ia->installInterfaceFlags & INSTALL_NOORDER)) { if (rpmtsOrder(ts)) { numFailed += numPackages; stopUninstall = 1; } } if (numPackages && !stopUninstall) { (void) rpmtsSetFlags(ts, (rpmtsFlags(ts) | RPMTRANS_FLAG_REVERSE)); /* Drop added/available package indices and dependency sets. */ rpmtsClean(ts); numPackages = rpmtsRun(ts, NULL, ia->probFilter & (RPMPROB_FILTER_DISKSPACE|RPMPROB_FILTER_DISKNODES)); ps = rpmtsProblems(ts); if (rpmpsNumProblems(ps) > 0) rpmpsPrint(NULL, ps); numFailed += numPackages; stopUninstall = 1; ps = rpmpsFree(ps); } exit: rpmtsEmpty(ts); return numFailed; }
/** @todo Generalize --freshen policies. */ int rpmInstall(rpmts ts, struct rpmInstallArguments_s * ia, ARGV_t fileArgv) { struct rpmEIU * eiu = xcalloc(1, sizeof(*eiu)); rpmps ps; rpmprobFilterFlags probFilter; rpmRelocation * relocations; char * fileURL = NULL; int stopInstall = 0; rpmVSFlags vsflags, ovsflags, tvsflags; int rc; int xx; int i; if (fileArgv == NULL) goto exit; rpmcliPackagesTotal = 0; (void) rpmtsSetFlags(ts, ia->transFlags); probFilter = ia->probFilter; relocations = ia->relocations; if (ia->installInterfaceFlags & INSTALL_UPGRADE) vsflags = rpmExpandNumeric("%{?_vsflags_erase}"); else vsflags = rpmExpandNumeric("%{?_vsflags_install}"); if (ia->qva_flags & VERIFY_DIGEST) vsflags |= _RPMVSF_NODIGESTS; if (ia->qva_flags & VERIFY_SIGNATURE) vsflags |= _RPMVSF_NOSIGNATURES; if (ia->qva_flags & VERIFY_HDRCHK) vsflags |= RPMVSF_NOHDRCHK; ovsflags = rpmtsSetVSFlags(ts, (vsflags | RPMVSF_NEEDPAYLOAD)); { int notifyFlags; notifyFlags = ia->installInterfaceFlags | (rpmIsVerbose() ? INSTALL_LABEL : 0 ); xx = rpmtsSetNotifyCallback(ts, rpmShowProgress, (void *) ((long)notifyFlags)); } if ((eiu->relocations = relocations) != NULL) { while (eiu->relocations->oldPath) eiu->relocations++; if (eiu->relocations->newPath == NULL) eiu->relocations = NULL; } /* Build fully globbed list of arguments in argv[argc]. */ for (eiu->fnp = fileArgv; *eiu->fnp != NULL; eiu->fnp++) { ARGV_t av = NULL; int ac = 0; char * fn; fn = rpmEscapeSpaces(*eiu->fnp); rc = rpmGlob(fn, &ac, &av); fn = _free(fn); if (rc || ac == 0) { rpmlog(RPMLOG_ERR, _("File not found by glob: %s\n"), *eiu->fnp); eiu->numFailed++; continue; } argvAppend(&(eiu->argv), av); argvFree(av); eiu->argc += ac; } restart: /* Allocate sufficient storage for next set of args. */ if (eiu->pkgx >= eiu->numPkgs) { eiu->numPkgs = eiu->pkgx + eiu->argc; eiu->pkgURL = xrealloc(eiu->pkgURL, (eiu->numPkgs + 1) * sizeof(*eiu->pkgURL)); memset(eiu->pkgURL + eiu->pkgx, 0, ((eiu->argc + 1) * sizeof(*eiu->pkgURL))); eiu->pkgState = xrealloc(eiu->pkgState, (eiu->numPkgs + 1) * sizeof(*eiu->pkgState)); memset(eiu->pkgState + eiu->pkgx, 0, ((eiu->argc + 1) * sizeof(*eiu->pkgState))); } /* Retrieve next set of args, cache on local storage. */ for (i = 0; i < eiu->argc; i++) { fileURL = _free(fileURL); fileURL = eiu->argv[i]; eiu->argv[i] = NULL; switch (urlIsURL(fileURL)) { case URL_IS_HTTPS: case URL_IS_HTTP: case URL_IS_FTP: { char *tfn; FD_t tfd; if (rpmIsVerbose()) fprintf(stdout, _("Retrieving %s\n"), fileURL); tfd = rpmMkTempFile(rpmtsRootDir(ts), &tfn); if (tfd && tfn) { Fclose(tfd); rc = urlGetFile(fileURL, tfn); } else { rc = -1; } if (rc != 0) { rpmlog(RPMLOG_ERR, _("skipping %s - transfer failed\n"), fileURL); eiu->numFailed++; eiu->pkgURL[eiu->pkgx] = NULL; tfn = _free(tfn); break; } eiu->pkgState[eiu->pkgx] = 1; eiu->pkgURL[eiu->pkgx] = tfn; eiu->pkgx++; } break; case URL_IS_PATH: case URL_IS_DASH: /* WRONG WRONG WRONG */ case URL_IS_HKP: /* WRONG WRONG WRONG */ default: eiu->pkgURL[eiu->pkgx] = fileURL; fileURL = NULL; eiu->pkgx++; break; } } fileURL = _free(fileURL); if (eiu->numFailed) goto exit; /* Continue processing file arguments, building transaction set. */ for (eiu->fnp = eiu->pkgURL+eiu->prevx; *eiu->fnp != NULL; eiu->fnp++, eiu->prevx++) { const char * fileName; rpmlog(RPMLOG_DEBUG, "============== %s\n", *eiu->fnp); (void) urlPath(*eiu->fnp, &fileName); /* Try to read the header from a package file. */ eiu->fd = Fopen(*eiu->fnp, "r.ufdio"); if (eiu->fd == NULL || Ferror(eiu->fd)) { rpmlog(RPMLOG_ERR, _("open of %s failed: %s\n"), *eiu->fnp, Fstrerror(eiu->fd)); if (eiu->fd != NULL) { xx = Fclose(eiu->fd); eiu->fd = NULL; } eiu->numFailed++; *eiu->fnp = NULL; continue; } /* Read the header, verifying signatures (if present). */ tvsflags = rpmtsSetVSFlags(ts, vsflags); eiu->rpmrc = rpmReadPackageFile(ts, eiu->fd, *eiu->fnp, &eiu->h); tvsflags = rpmtsSetVSFlags(ts, tvsflags); xx = Fclose(eiu->fd); eiu->fd = NULL; switch (eiu->rpmrc) { case RPMRC_FAIL: rpmlog(RPMLOG_ERR, _("%s cannot be installed\n"), *eiu->fnp); eiu->numFailed++; *eiu->fnp = NULL; continue; break; case RPMRC_NOTFOUND: goto maybe_manifest; break; case RPMRC_NOTTRUSTED: case RPMRC_NOKEY: case RPMRC_OK: default: break; } eiu->isSource = headerIsSource(eiu->h); if (eiu->isSource) { rpmlog(RPMLOG_DEBUG, "\tadded source package [%d]\n", eiu->numSRPMS); eiu->sourceURL = xrealloc(eiu->sourceURL, (eiu->numSRPMS + 2) * sizeof(*eiu->sourceURL)); eiu->sourceURL[eiu->numSRPMS] = *eiu->fnp; *eiu->fnp = NULL; eiu->numSRPMS++; eiu->sourceURL[eiu->numSRPMS] = NULL; continue; } if (eiu->relocations) { struct rpmtd_s prefixes; headerGet(eiu->h, RPMTAG_PREFIXES, &prefixes, HEADERGET_DEFAULT); if (rpmtdCount(&prefixes) == 1) { eiu->relocations->oldPath = xstrdup(rpmtdGetString(&prefixes)); rpmtdFreeData(&prefixes); } else { const char * name; xx = headerNVR(eiu->h, &name, NULL, NULL); rpmlog(RPMLOG_ERR, _("package %s is not relocatable\n"), name); eiu->numFailed++; goto exit; } } /* On --freshen, verify package is installed and newer */ if (ia->installInterfaceFlags & INSTALL_FRESHEN) { rpmdbMatchIterator mi; const char * name; Header oldH; int count; xx = headerNVR(eiu->h, &name, NULL, NULL); mi = rpmtsInitIterator(ts, RPMTAG_NAME, name, 0); count = rpmdbGetIteratorCount(mi); while ((oldH = rpmdbNextIterator(mi)) != NULL) { if (rpmVersionCompare(oldH, eiu->h) < 0) continue; /* same or newer package already installed */ count = 0; break; } mi = rpmdbFreeIterator(mi); if (count == 0) { eiu->h = headerFree(eiu->h); continue; } /* Package is newer than those currently installed. */ } rc = rpmtsAddInstallElement(ts, eiu->h, (fnpyKey)fileName, (ia->installInterfaceFlags & INSTALL_UPGRADE) != 0, relocations); /* XXX reference held by transaction set */ eiu->h = headerFree(eiu->h); if (eiu->relocations) eiu->relocations->oldPath = _free(eiu->relocations->oldPath); switch(rc) { case 0: rpmlog(RPMLOG_DEBUG, "\tadded binary package [%d]\n", eiu->numRPMS); break; case 1: rpmlog(RPMLOG_ERR, _("error reading from file %s\n"), *eiu->fnp); eiu->numFailed++; goto exit; break; case 2: rpmlog(RPMLOG_ERR, _("file %s requires a newer version of RPM\n"), *eiu->fnp); eiu->numFailed++; goto exit; break; default: eiu->numFailed++; goto exit; break; } eiu->numRPMS++; continue; maybe_manifest: /* Try to read a package manifest. */ eiu->fd = Fopen(*eiu->fnp, "r.fpio"); if (eiu->fd == NULL || Ferror(eiu->fd)) { rpmlog(RPMLOG_ERR, _("open of %s failed: %s\n"), *eiu->fnp, Fstrerror(eiu->fd)); if (eiu->fd != NULL) { xx = Fclose(eiu->fd); eiu->fd = NULL; } eiu->numFailed++; *eiu->fnp = NULL; break; } /* Read list of packages from manifest. */ /* FIX: *eiu->argv can be NULL */ rc = rpmReadPackageManifest(eiu->fd, &eiu->argc, &eiu->argv); if (rc != RPMRC_OK) rpmlog(RPMLOG_ERR, _("%s: not an rpm package (or package manifest): %s\n"), *eiu->fnp, Fstrerror(eiu->fd)); xx = Fclose(eiu->fd); eiu->fd = NULL; /* If successful, restart the query loop. */ if (rc == RPMRC_OK) { eiu->prevx++; goto restart; } eiu->numFailed++; *eiu->fnp = NULL; break; } rpmlog(RPMLOG_DEBUG, "found %d source and %d binary packages\n", eiu->numSRPMS, eiu->numRPMS); if (eiu->numFailed) goto exit; if (eiu->numRPMS && !(ia->installInterfaceFlags & INSTALL_NODEPS)) { if (rpmtsCheck(ts)) { eiu->numFailed = eiu->numPkgs; stopInstall = 1; } ps = rpmtsProblems(ts); if (!stopInstall && rpmpsNumProblems(ps) > 0) { rpmlog(RPMLOG_ERR, _("Failed dependencies:\n")); rpmpsPrint(NULL, ps); eiu->numFailed = eiu->numPkgs; stopInstall = 1; } ps = rpmpsFree(ps); } if (eiu->numRPMS && !(ia->installInterfaceFlags & INSTALL_NOORDER)) { if (rpmtsOrder(ts)) { eiu->numFailed = eiu->numPkgs; stopInstall = 1; } } if (eiu->numRPMS && !stopInstall) { rpmcliPackagesTotal += eiu->numSRPMS; rpmlog(RPMLOG_DEBUG, "installing binary packages\n"); /* Drop added/available package indices and dependency sets. */ rpmtsClean(ts); rc = rpmtsRun(ts, NULL, probFilter); ps = rpmtsProblems(ts); if (rc < 0) { eiu->numFailed += eiu->numRPMS; } else if (rc > 0) { eiu->numFailed += rc; if (rpmpsNumProblems(ps) > 0) rpmpsPrint(stderr, ps); } ps = rpmpsFree(ps); } if (eiu->numSRPMS && !stopInstall) { if (eiu->sourceURL != NULL) for (i = 0; i < eiu->numSRPMS; i++) { rpmdbCheckSignals(); if (eiu->sourceURL[i] == NULL) continue; eiu->fd = Fopen(eiu->sourceURL[i], "r.ufdio"); if (eiu->fd == NULL || Ferror(eiu->fd)) { rpmlog(RPMLOG_ERR, _("cannot open file %s: %s\n"), eiu->sourceURL[i], Fstrerror(eiu->fd)); if (eiu->fd != NULL) { xx = Fclose(eiu->fd); eiu->fd = NULL; } continue; } if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_TEST)) { eiu->rpmrc = rpmInstallSourcePackage(ts, eiu->fd, NULL, NULL); if (eiu->rpmrc != RPMRC_OK) eiu->numFailed++; } xx = Fclose(eiu->fd); eiu->fd = NULL; } } exit: if (eiu->pkgURL != NULL) for (i = 0; i < eiu->numPkgs; i++) { if (eiu->pkgURL[i] == NULL) continue; if (eiu->pkgState[i] == 1) (void) unlink(eiu->pkgURL[i]); eiu->pkgURL[i] = _free(eiu->pkgURL[i]); } eiu->pkgState = _free(eiu->pkgState); eiu->pkgURL = _free(eiu->pkgURL); eiu->argv = _free(eiu->argv); rc = eiu->numFailed; free(eiu); rpmtsEmpty(ts); return rc; }
/** * Check installed package dependencies for problems. * @param qva parsed query/verify options * @param ts transaction set * @param h header * @return number of problems found (0 for no problems) */ static int verifyDependencies(/*@unused@*/ QVA_t qva, rpmts ts, Header h) /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ /*@modifies ts, h, rpmGlobalMacroContext, fileSystem, internalState @*/ { #ifdef NOTYET uint32_t hdrNum = headerGetInstance(h); #endif rpmps ps; int rc = 0; /* assume no problems */ int xx; rpmtsEmpty(ts); #ifdef NOTYET if (hdrNum > 0) (void) rpmtsAddEraseElement(ts, h, hdrNum); else #endif (void) rpmtsAddInstallElement(ts, h, headerGetOrigin(h), 0, NULL); xx = rpmtsCheck(ts); ps = rpmtsProblems(ts); if (rpmpsNumProblems(ps) > 0) { const char * altNEVR; const char * pkgNEVR = NULL; rpmpsi psi; rpmProblem prob; char * t, * te; int nb = 512; psi = rpmpsInitIterator(ps); while (rpmpsNextIterator(psi) >= 0) { prob = rpmpsProblem(psi); if (pkgNEVR == NULL) pkgNEVR = rpmProblemGetPkgNEVR(prob); altNEVR = rpmProblemGetAltNEVR(prob); assert(altNEVR != NULL); if (altNEVR[0] == 'R' && altNEVR[1] == ' ') nb += sizeof("\tRequires: ")-1; if (altNEVR[0] == 'C' && altNEVR[1] == ' ') nb += sizeof("\tConflicts: ")-1; nb += strlen(altNEVR+2) + sizeof("\n") - 1; } psi = rpmpsFreeIterator(psi); te = t = alloca(nb); *te = '\0'; sprintf(te, _("Unsatisfied dependencies for %s:\n"), pkgNEVR); te += strlen(te); psi = rpmpsInitIterator(ps); while (rpmpsNextIterator(psi) >= 0) { prob = rpmpsProblem(psi); if ((altNEVR = rpmProblemGetAltNEVR(prob)) == NULL) altNEVR = "? ?altNEVR?"; if (altNEVR[0] == 'R' && altNEVR[1] == ' ') te = stpcpy(te, "\tRequires: "); if (altNEVR[0] == 'C' && altNEVR[1] == ' ') te = stpcpy(te, "\tConflicts: "); te = stpcpy( stpcpy(te, altNEVR+2), "\n"); rc++; } psi = rpmpsFreeIterator(psi); if (te > t) { *te++ = '\n'; *te = '\0'; rpmlog(RPMLOG_NOTICE, "%s", t); te = t; *t = '\0'; } } ps = rpmpsFree(ps); rpmtsEmpty(ts); return rc; }
int rpmtsRun(rpmts ts, rpmps okProbs, rpmprobFilterFlags ignoreSet) { int rc = -1; /* assume failure */ tsMembers tsmem = rpmtsMembers(ts); rpmtxn txn = NULL; rpmps tsprobs = NULL; int TsmPreDone = 0; /* TsmPre hook hasn't been called */ /* Force default 022 umask during transaction for consistent results */ mode_t oldmask = umask(022); /* Empty transaction, nothing to do */ if (rpmtsNElements(ts) <= 0) { rc = 0; goto exit; } /* If we are in test mode, then there's no need for transaction lock. */ if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_TEST)) { if (!(txn = rpmtxnBegin(ts, RPMTXN_WRITE))) { goto exit; } } /* Setup flags and such, open the DB */ if (rpmtsSetup(ts, ignoreSet)) { goto exit; } /* Check package set for problems */ tsprobs = checkProblems(ts); /* Run pre transaction hook for all plugins */ TsmPreDone = 1; if (rpmpluginsCallTsmPre(rpmtsPlugins(ts), ts) == RPMRC_FAIL) { goto exit; } if (!rpmpsNumProblems(tsprobs)) { /* Run file triggers in this package other package(s) set off. */ runFileTriggers(ts, NULL, RPMSENSE_TRIGGERUN, RPMSCRIPT_TRANSFILETRIGGER, 0); /* Run file triggers in other package(s) this package sets off. */ runTransScripts(ts, PKG_TRANSFILETRIGGERUN); } /* Run pre-transaction scripts, but only if there are no known * problems up to this point and not disabled otherwise. */ if (!((rpmtsFlags(ts) & (RPMTRANS_FLAG_BUILD_PROBS|RPMTRANS_FLAG_NOPRETRANS)) || (rpmpsNumProblems(tsprobs)))) { rpmlog(RPMLOG_DEBUG, "running pre-transaction scripts\n"); runTransScripts(ts, PKG_PRETRANS); } tsprobs = rpmpsFree(tsprobs); /* Compute file disposition for each package in transaction set. */ if (rpmtsPrepare(ts)) { goto exit; } /* Check again for problems (now including file conflicts, duh */ tsprobs = rpmtsProblems(ts); /* If unfiltered problems exist, free memory and return. */ if ((rpmtsFlags(ts) & RPMTRANS_FLAG_BUILD_PROBS) || (rpmpsNumProblems(tsprobs))) { rc = tsmem->orderCount; goto exit; } /* Free up memory taken by problem sets */ tsprobs = rpmpsFree(tsprobs); rpmtsCleanProblems(ts); /* * Free up the global string pool unless we expect it to be needed * again. During the transaction, private pools will be used for * rpmfi's etc. */ if (!(rpmtsFlags(ts) & (RPMTRANS_FLAG_TEST|RPMTRANS_FLAG_BUILD_PROBS))) tsmem->pool = rpmstrPoolFree(tsmem->pool); /* Actually install and remove packages, get final exit code */ rc = rpmtsProcess(ts) ? -1 : 0; /* Run post-transaction scripts unless disabled */ if (!(rpmtsFlags(ts) & (RPMTRANS_FLAG_NOPOSTTRANS))) { rpmlog(RPMLOG_DEBUG, "running post-transaction scripts\n"); runTransScripts(ts, PKG_POSTTRANS); } /* Run file triggers in other package(s) this package sets off. */ runFileTriggers(ts, NULL, RPMSENSE_TRIGGERIN, RPMSCRIPT_TRANSFILETRIGGER, 0); runPostUnTransFileTrigs(ts); /* Run file triggers in this package other package(s) set off. */ runTransScripts(ts, PKG_TRANSFILETRIGGERIN); exit: /* Run post transaction hook for all plugins */ if (TsmPreDone) /* If TsmPre hook has been called, call the TsmPost hook */ rpmpluginsCallTsmPost(rpmtsPlugins(ts), ts, rc); /* Finish up... */ (void) umask(oldmask); (void) rpmtsFinish(ts); rpmpsFree(tsprobs); rpmtxnEnd(txn); return rc; }
int rpmtsRun(rpmts ts, rpmps okProbs, rpmprobFilterFlags ignoreSet) { rpm_color_t tscolor = rpmtsColor(ts); int i; int rc = 0; int totalFileCount = 0; rpmfi fi; fingerPrintCache fpc; rpmps ps; rpmtsi pi; rpmte p; int numAdded; int numRemoved; void * lock = NULL; int xx; /* XXX programmer error segfault avoidance. */ if (rpmtsNElements(ts) <= 0) return -1; /* If we are in test mode, then there's no need for transaction lock. */ if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_TEST)) { lock = rpmtsAcquireLock(ts); if (lock == NULL) return -1; /* XXX W2DO? */ } if (rpmtsFlags(ts) & RPMTRANS_FLAG_NOSCRIPTS) (void) rpmtsSetFlags(ts, (rpmtsFlags(ts) | _noTransScripts | _noTransTriggers)); if (rpmtsFlags(ts) & RPMTRANS_FLAG_NOTRIGGERS) (void) rpmtsSetFlags(ts, (rpmtsFlags(ts) | _noTransTriggers)); if (rpmtsFlags(ts) & RPMTRANS_FLAG_JUSTDB) (void) rpmtsSetFlags(ts, (rpmtsFlags(ts) | _noTransScripts | _noTransTriggers)); /* if SELinux isn't enabled or init fails, don't bother... */ if (!rpmtsSELinuxEnabled(ts)) { rpmtsSetFlags(ts, (rpmtsFlags(ts) | RPMTRANS_FLAG_NOCONTEXTS)); } if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOCONTEXTS)) { char *fn = rpmGetPath("%{?_install_file_context_path}", NULL); if (matchpathcon_init(fn) == -1) { rpmtsSetFlags(ts, (rpmtsFlags(ts) | RPMTRANS_FLAG_NOCONTEXTS)); } free(fn); } ts->probs = rpmpsFree(ts->probs); ts->probs = rpmpsCreate(); /* XXX Make sure the database is open RDWR for package install/erase. */ { int dbmode = (rpmtsFlags(ts) & RPMTRANS_FLAG_TEST) ? O_RDONLY : (O_RDWR|O_CREAT); /* Open database RDWR for installing packages. */ if (rpmtsOpenDB(ts, dbmode)) { rpmtsFreeLock(lock); return -1; /* XXX W2DO? */ } } ts->ignoreSet = ignoreSet; { char * currDir = rpmGetCwd(); rpmtsSetCurrDir(ts, currDir); currDir = _free(currDir); } (void) rpmtsSetChrootDone(ts, 0); { rpm_tid_t tid = (rpm_tid_t) time(NULL); (void) rpmtsSetTid(ts, tid); } /* Get available space on mounted file systems. */ xx = rpmtsInitDSI(ts); /* =============================================== * For packages being installed: * - verify package arch/os. * - verify package epoch:version-release is newer. * - count files. * For packages being removed: * - count files. */ rpmlog(RPMLOG_DEBUG, "sanity checking %d elements\n", rpmtsNElements(ts)); ps = rpmtsProblems(ts); /* The ordering doesn't matter here */ pi = rpmtsiInit(ts); /* XXX Only added packages need be checked. */ while ((p = rpmtsiNext(pi, TR_ADDED)) != NULL) { rpmdbMatchIterator mi; int fc; if ((fi = rpmteFI(p)) == NULL) continue; /* XXX can't happen */ fc = rpmfiFC(fi); if (!(rpmtsFilterFlags(ts) & RPMPROB_FILTER_IGNOREARCH)) if (!archOkay(rpmteA(p))) rpmpsAppend(ps, RPMPROB_BADARCH, rpmteNEVRA(p), rpmteKey(p), rpmteA(p), NULL, NULL, 0); if (!(rpmtsFilterFlags(ts) & RPMPROB_FILTER_IGNOREOS)) if (!osOkay(rpmteO(p))) rpmpsAppend(ps, RPMPROB_BADOS, rpmteNEVRA(p), rpmteKey(p), rpmteO(p), NULL, NULL, 0); if (!(rpmtsFilterFlags(ts) & RPMPROB_FILTER_OLDPACKAGE)) { Header h; mi = rpmtsInitIterator(ts, RPMTAG_NAME, rpmteN(p), 0); while ((h = rpmdbNextIterator(mi)) != NULL) xx = ensureOlder(ts, p, h); mi = rpmdbFreeIterator(mi); } if (!(rpmtsFilterFlags(ts) & RPMPROB_FILTER_REPLACEPKG)) { mi = rpmtsInitIterator(ts, RPMTAG_NAME, rpmteN(p), 0); xx = rpmdbSetIteratorRE(mi, RPMTAG_EPOCH, RPMMIRE_STRCMP, rpmteE(p)); xx = rpmdbSetIteratorRE(mi, RPMTAG_VERSION, RPMMIRE_STRCMP, rpmteV(p)); xx = rpmdbSetIteratorRE(mi, RPMTAG_RELEASE, RPMMIRE_STRCMP, rpmteR(p)); if (tscolor) { xx = rpmdbSetIteratorRE(mi, RPMTAG_ARCH, RPMMIRE_STRCMP, rpmteA(p)); xx = rpmdbSetIteratorRE(mi, RPMTAG_OS, RPMMIRE_STRCMP, rpmteO(p)); } while (rpmdbNextIterator(mi) != NULL) { rpmpsAppend(ps, RPMPROB_PKG_INSTALLED, rpmteNEVRA(p), rpmteKey(p), NULL, NULL, NULL, 0); break; } mi = rpmdbFreeIterator(mi); } /* Count no. of files (if any). */ totalFileCount += fc; } pi = rpmtsiFree(pi); ps = rpmpsFree(ps); /* The ordering doesn't matter here */ pi = rpmtsiInit(ts); while ((p = rpmtsiNext(pi, TR_REMOVED)) != NULL) { int fc; if ((fi = rpmteFI(p)) == NULL) continue; /* XXX can't happen */ fc = rpmfiFC(fi); totalFileCount += fc; } pi = rpmtsiFree(pi); /* Run pre-transaction scripts, but only if there are no known * problems up to this point and not disabled otherwise. */ if (!((rpmtsFlags(ts) & (RPMTRANS_FLAG_BUILD_PROBS|RPMTRANS_FLAG_TEST|RPMTRANS_FLAG_NOPRE)) || (rpmpsNumProblems(ts->probs) && (okProbs == NULL || rpmpsTrim(ts->probs, okProbs))))) { rpmlog(RPMLOG_DEBUG, "running pre-transaction scripts\n"); runTransScripts(ts, RPMTAG_PRETRANS); } /* =============================================== * Initialize transaction element file info for package: */ /* * FIXME?: we'd be better off assembling one very large file list and * calling fpLookupList only once. I'm not sure that the speedup is * worth the trouble though. */ rpmlog(RPMLOG_DEBUG, "computing %d file fingerprints\n", totalFileCount); numAdded = numRemoved = 0; pi = rpmtsiInit(ts); while ((p = rpmtsiNext(pi, 0)) != NULL) { int fc; if ((fi = rpmteFI(p)) == NULL) continue; /* XXX can't happen */ fc = rpmfiFC(fi); switch (rpmteType(p)) { case TR_ADDED: numAdded++; /* Skip netshared paths, not our i18n files, and excluded docs */ if (fc > 0) skipFiles(ts, p); break; case TR_REMOVED: numRemoved++; break; } } pi = rpmtsiFree(pi); if (!rpmtsChrootDone(ts)) { const char * rootDir = rpmtsRootDir(ts); xx = chdir("/"); if (rootDir != NULL && strcmp(rootDir, "/") && *rootDir == '/') { /* opening db before chroot not optimal, see rhbz#103852 c#3 */ xx = rpmdbOpenAll(ts->rdb); if (chroot(rootDir) == -1) { rpmlog(RPMLOG_ERR, _("Unable to change root directory: %m\n")); return -1; } } (void) rpmtsSetChrootDone(ts, 1); } ts->ht = rpmFpHashCreate(totalFileCount/2+1, fpHashFunction, fpEqual, NULL, NULL); rpmFpHash symlinks = rpmFpHashCreate(totalFileCount/16+16, fpHashFunction, fpEqual, NULL, NULL); fpc = fpCacheCreate(totalFileCount/2 + 10001); /* =============================================== * Add fingerprint for each file not skipped. */ pi = rpmtsiInit(ts); while ((p = rpmtsiNext(pi, 0)) != NULL) { int fc; (void) rpmdbCheckSignals(); if ((fi = rpmteFI(p)) == NULL) continue; /* XXX can't happen */ fc = rpmfiFC(fi); (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0); rpmfiFpLookup(fi, fpc); /* collect symbolic links */ fi = rpmfiInit(fi, 0); if (fi != NULL) /* XXX lclint */ while ((i = rpmfiNext(fi)) >= 0) { struct rpmffi_s ffi; char const *linktarget; linktarget = rpmfiFLink(fi); if (!(linktarget && *linktarget != '\0')) continue; if (XFA_SKIPPING(rpmfsGetAction(rpmteGetFileStates(p), i))) continue; ffi.p = p; ffi.fileno = i; rpmFpHashAddEntry(symlinks, rpmfiFpsIndex(fi, i), ffi); } (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), fc); } pi = rpmtsiFree(pi); /* =============================================== * Check fingerprints if they contain symlinks * and add them to the ts->ht hash table */ pi = rpmtsiInit(ts); while ((p = rpmtsiNext(pi, 0)) != NULL) { (void) rpmdbCheckSignals(); if ((fi = rpmteFI(p)) == NULL) continue; /* XXX can't happen */ fi = rpmfiInit(fi, 0); (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0); if (fi != NULL) /* XXX lclint */ while ((i = rpmfiNext(fi)) >= 0) { if (XFA_SKIPPING(rpmfsGetAction(rpmteGetFileStates(p), i))) continue; fpLookupSubdir(symlinks, ts->ht, fpc, p, i); } (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0); } pi = rpmtsiFree(pi); rpmFpHashFree(symlinks); /* =============================================== * Compute file disposition for each package in transaction set. */ rpmtsNotify(ts, NULL, RPMCALLBACK_TRANS_START, 6, ts->orderCount); /* check against files in the rpmdb */ checkInstalledFiles(ts, fpc); pi = rpmtsiInit(ts); while ((p = rpmtsiNext(pi, 0)) != NULL) { if ((fi = rpmteFI(p)) == NULL) continue; /* XXX can't happen */ (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0); /* check files in ts against each other and update disk space needs on each partition for this package. */ handleOverlappedFiles(ts, p, fi); /* Check added package has sufficient space on each partition used. */ if (rpmteType(p) == TR_ADDED) { rpmtsCheckDSIProblems(ts, p); } (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_FINGERPRINT), 0); } pi = rpmtsiFree(pi); if (rpmtsChrootDone(ts)) { const char * rootDir = rpmtsRootDir(ts); const char * currDir = rpmtsCurrDir(ts); if (rootDir != NULL && strcmp(rootDir, "/") && *rootDir == '/') xx = chroot("."); (void) rpmtsSetChrootDone(ts, 0); if (currDir != NULL) xx = chdir(currDir); } rpmtsNotify(ts, NULL, RPMCALLBACK_TRANS_STOP, 6, ts->orderCount); /* =============================================== * Free unused memory as soon as possible. */ pi = rpmtsiInit(ts); while ((p = rpmtsiNext(pi, 0)) != NULL) { rpmteSetFI(p, NULL); } pi = rpmtsiFree(pi); fpc = fpCacheFree(fpc); ts->ht = rpmFpHashFree(ts->ht); /* =============================================== * If unfiltered problems exist, free memory and return. */ if ((rpmtsFlags(ts) & RPMTRANS_FLAG_BUILD_PROBS) || (rpmpsNumProblems(ts->probs) && (okProbs == NULL || rpmpsTrim(ts->probs, okProbs))) ) { rpmtsFreeLock(lock); return ts->orderCount; } /* Actually install and remove packages */ rc = rpmtsProcess(ts); if (!(rpmtsFlags(ts) & (RPMTRANS_FLAG_TEST|RPMTRANS_FLAG_NOPOST))) { rpmlog(RPMLOG_DEBUG, "running post-transaction scripts\n"); runTransScripts(ts, RPMTAG_POSTTRANS); } if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_NOCONTEXTS)) { matchpathcon_fini(); } rpmtsFreeLock(lock); /* FIX: ts->flList may be NULL */ if (rc) return -1; else return 0; }
int rpmtsRun(rpmts ts, rpmps okProbs, rpmprobFilterFlags ignoreSet) { int rc = -1; /* assume failure */ rpmlock lock = NULL; rpmps tsprobs = NULL; /* Force default 022 umask during transaction for consistent results */ mode_t oldmask = umask(022); /* Empty transaction, nothing to do */ if (rpmtsNElements(ts) <= 0) { rc = 0; goto exit; } /* If we are in test mode, then there's no need for transaction lock. */ if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_TEST)) { if (!(lock = rpmtsAcquireLock(ts))) { goto exit; } } /* Setup flags and such, open the DB */ if (rpmtsSetup(ts, ignoreSet)) { goto exit; } rpmtsSetupCollections(ts); /* Check package set for problems */ tsprobs = checkProblems(ts); /* Run pre-transaction scripts, but only if there are no known * problems up to this point and not disabled otherwise. */ if (!((rpmtsFlags(ts) & (RPMTRANS_FLAG_BUILD_PROBS|RPMTRANS_FLAG_NOPRE)) || (rpmpsNumProblems(tsprobs)))) { rpmlog(RPMLOG_DEBUG, "running pre-transaction scripts\n"); runTransScripts(ts, PKG_PRETRANS); } tsprobs = rpmpsFree(tsprobs); /* Compute file disposition for each package in transaction set. */ if (rpmtsPrepare(ts)) { goto exit; } /* Check again for problems (now including file conflicts, duh */ tsprobs = rpmtsProblems(ts); /* If unfiltered problems exist, free memory and return. */ if ((rpmtsFlags(ts) & RPMTRANS_FLAG_BUILD_PROBS) || (rpmpsNumProblems(tsprobs))) { tsMembers tsmem = rpmtsMembers(ts); rc = tsmem->orderCount; goto exit; } /* Free up memory taken by problem sets */ tsprobs = rpmpsFree(tsprobs); rpmtsCleanProblems(ts); /* Actually install and remove packages, get final exit code */ rc = rpmtsProcess(ts) ? -1 : 0; /* Run post-transaction scripts unless disabled */ if (!(rpmtsFlags(ts) & (RPMTRANS_FLAG_NOPOST))) { rpmlog(RPMLOG_DEBUG, "running post-transaction scripts\n"); runTransScripts(ts, PKG_POSTTRANS); } exit: /* Finish up... */ (void) umask(oldmask); (void) rpmtsFinish(ts); rpmpsFree(tsprobs); rpmlockFree(lock); return rc; }
/* * Check the dependencies. * @return [Array<Dependency>, +nil+] If dependencies are not met returns an * array with dependencies. Otherwise +nil+. */ VALUE rpm_transaction_check(VALUE trans) { #if RPM_VERSION_CODE < RPM_VERSION(4,1,0) rpmDependencyConflict conflicts; int num; rpmdepCheck(RPM_TRANSACTION(trans), &conflicts, &num); if (num) { VALUE list = rb_ary_new(); register int i; for (i = 0; i < num; i++) { VALUE dep; switch (conflicts[i].sense) { case RPMDEP_SENSE_REQUIRES: dep = rpm_require_new(conflicts[i].needsName, rpm_version_new(conflicts[i].needsVersion), conflicts[i].needsFlags, rpm_package_new_from_header(conflicts[i].byHeader)); break; case RPMDEP_SENSE_CONFLICTS: dep = rpm_conflict_new(conflicts[i].needsName, rpm_version_new(conflicts[i].needsVersion), conflicts[i].needsFlags, rpm_package_new_from_header(conflicts[i].byHeader)); break; } rb_ary_push(list, dep); } rpmdepFreeConflicts(conflicts, num); return list; } return Qnil; #else int rc; rpmps ps; int num; VALUE list = Qnil; rc = rpmtsCheck(RPM_TRANSACTION(trans)); ps = rpmtsProblems(RPM_TRANSACTION(trans)); #if RPM_VERSION_CODE < RPM_VERSION(4,9,0) || RPM_VERSION_CODE >= RPM_VERSION(5,0,0) /* get rid of duplicate problems */ rpmpsTrim(ps, RPMPROB_FILTER_NONE); #endif num = rpmpsNumProblems(ps); #ifdef RPMPS_OPAQUE rpmpsi psi = rpmpsInitIterator(ps); if (num > 0) { list = rb_ary_new(); } while (rpmpsNextIterator(psi) >= 0) { rpmProblem p = rpmpsGetProblem(psi); VALUE dep; switch (rpmProblemGetType(p)) { case RPMPROB_REQUIRES: { char *buf = strdup (rpmProblemGetAltNEVR(p)); /* TODO: zaki: NULL check*/ char *end; char *name = buf+2; char *relation = NULL; char *evr = NULL; rpmsenseFlags sense_flags = 0; end = strchr ( name, ' '); if ( end ) { *end = '\0'; relation = end + 1; end = strchr ( relation, ' '); if ( end ) { *end = '\0'; evr = end + 1; } for ( ; (*relation) != '\0'; relation++ ) { if ( (*relation) == '=' ) { sense_flags |= RPMSENSE_EQUAL; } else if ( (*relation) == '>' ) { sense_flags |= RPMSENSE_GREATER; } else if ( (*relation) == '<' ) { sense_flags |= RPMSENSE_LESS; } } } dep = rpm_require_new(name, rpm_version_new(evr ? evr : ""), sense_flags, package_new_from_NEVR( rpmProblemGetPkgNEVR(p) )); free ( buf ); rb_ary_push(list, dep); break; } default: break; } } #else if (ps != NULL && 0 < num) { rpmProblem p; int i; list = rb_ary_new(); for (i = 0; i < num; i++) { const char *altNEVR; VALUE dep; p = ps->probs + i; altNEVR = (p->altNEVR ? p->altNEVR : "? ?altNEVR?"); if (p->ignoreProblem) continue; #if 0 /* XXX shouldn't be needed at all due to rpmpsTrim() */ /* Filter already appended problems. */ for (j = 0; j < i; j++) { if (!sameProblem(p, ps->probs + j)) break; } if (j < i) continue; #endif if ( p->type == RPMPROB_REQUIRES ) { char *buf = strdup ( altNEVR ); /* TODO: zaki: NULL check*/ char *end; char *name = buf+2; char *relation = NULL; char *evr = ""; rpmsenseFlags sense_flags = 0; end = strchr ( name, ' '); if ( end ) { *end = '\0'; relation = end + 1; end = strchr ( relation, ' '); if ( end ) { *end = '\0'; evr = end + 1; } for ( ; (*relation) != '\0'; relation++ ) { if ( (*relation) == '=' ) { sense_flags |= RPMSENSE_EQUAL; } else if ( (*relation) == '>' ) { sense_flags |= RPMSENSE_GREATER; } else if ( (*relation) == '<' ) { sense_flags |= RPMSENSE_LESS; } } } dep = rpm_require_new(name, rpm_version_new(evr), sense_flags, package_new_from_NEVR(p->pkgNEVR) ); free ( buf ); rb_ary_push(list, dep); } else { #if 0 RPMPROB_CONFLICT: RPMPROB_BADARCH: RPMPROB_BADOS: RPMPROB_PKG_INSTALLED: RPMPROB_BADRELOCATE: RPMPROB_NEW_FILE_CONFLICT: RPMPROB_FILE_CONFLICT: RPMPROB_OLDPACKAGE: RPMPROB_DISKSPACE: RPMPROB_DISKNODES: RPMPROB_BADPRETRANS: #endif break; } #if 0 printf ("%d, type=%d, ignoreProblem=%d, str1=%s pkgNEVR=%s, %s\n", i, p->type, p->ignoreProblem, p->str1, p->pkgNEVR, altNEVR); #endif } } #endif /* RPMPS_OPAQUE */ ps = rpmpsFree(ps); return list; #endif }