/* * For packages being installed: * - verify package arch/os. * - verify package epoch:version-release is newer. */ static rpmps checkProblems(rpmts ts) { rpm_color_t tscolor = rpmtsColor(ts); rpmprobFilterFlags probFilter = rpmtsFilterFlags(ts); rpmstrPool tspool = rpmtsPool(ts); rpmtsi pi = rpmtsiInit(ts); rpmte p; /* The ordering doesn't matter here */ /* XXX Only added packages need be checked. */ rpmlog(RPMLOG_DEBUG, "sanity checking %d elements\n", rpmtsNElements(ts)); while ((p = rpmtsiNext(pi, TR_ADDED)) != NULL) { if (!(probFilter & RPMPROB_FILTER_IGNOREARCH) && badArch(rpmteA(p))) rpmteAddProblem(p, RPMPROB_BADARCH, rpmteA(p), NULL, 0); if (!(probFilter & RPMPROB_FILTER_IGNOREOS) && badOs(rpmteO(p))) rpmteAddProblem(p, RPMPROB_BADOS, rpmteO(p), NULL, 0); if (!(probFilter & RPMPROB_FILTER_OLDPACKAGE)) { Header h; rpmdbMatchIterator mi; mi = rpmtsInitIterator(ts, RPMDBI_NAME, rpmteN(p), 0); while ((h = rpmdbNextIterator(mi)) != NULL) ensureOlder(tspool, p, h); rpmdbFreeIterator(mi); } if (!(probFilter & RPMPROB_FILTER_REPLACEPKG)) { Header h; rpmdbMatchIterator mi; mi = rpmtsPrunedIterator(ts, RPMDBI_NAME, rpmteN(p), 1); rpmdbSetIteratorRE(mi, RPMTAG_EPOCH, RPMMIRE_STRCMP, rpmteE(p)); rpmdbSetIteratorRE(mi, RPMTAG_VERSION, RPMMIRE_STRCMP, rpmteV(p)); rpmdbSetIteratorRE(mi, RPMTAG_RELEASE, RPMMIRE_STRCMP, rpmteR(p)); if (tscolor) { rpmdbSetIteratorRE(mi, RPMTAG_ARCH, RPMMIRE_STRCMP, rpmteA(p)); rpmdbSetIteratorRE(mi, RPMTAG_OS, RPMMIRE_STRCMP, rpmteO(p)); } if ((h = rpmdbNextIterator(mi)) != NULL) { rpmteAddProblem(p, RPMPROB_PKG_INSTALLED, NULL, NULL, headerGetInstance(h)); } rpmdbFreeIterator(mi); } if (!(probFilter & RPMPROB_FILTER_FORCERELOCATE)) rpmteAddRelocProblems(p); } rpmtsiFree(pi); return rpmtsProblems(ts); }
/* * --replacepkgs hack: find the header instance we're replacing and * mark it as the db instance of the install element. In PSM_POST, * if an install element already has a db instance, it's removed * before proceeding with the adding the new header to the db. */ static void markReplacedInstance(rpmts ts, rpmte te) { rpmdbMatchIterator mi = rpmtsInitIterator(ts, RPMDBI_NAME, rpmteN(te), 0); rpmdbSetIteratorRE(mi, RPMTAG_EPOCH, RPMMIRE_STRCMP, rpmteE(te)); rpmdbSetIteratorRE(mi, RPMTAG_VERSION, RPMMIRE_STRCMP, rpmteV(te)); rpmdbSetIteratorRE(mi, RPMTAG_RELEASE, RPMMIRE_STRCMP, rpmteR(te)); /* XXX shouldn't we also do this on colorless transactions? */ if (rpmtsColor(ts)) { rpmdbSetIteratorRE(mi, RPMTAG_ARCH, RPMMIRE_STRCMP, rpmteA(te)); rpmdbSetIteratorRE(mi, RPMTAG_OS, RPMMIRE_STRCMP, rpmteO(te)); } while (rpmdbNextIterator(mi) != NULL) { rpmteSetDBInstance(te, rpmdbGetIteratorOffset(mi)); break; } rpmdbFreeIterator(mi); }
VALUE rpm_mi_set_iterator_re(VALUE mi,VALUE tag, VALUE mode, VALUE re) { if (TYPE(re) != T_STRING) rb_raise(rb_eTypeError, "illegal argument type"); rpmdbSetIteratorRE(RPM_MI(mi),NUM2INT(tag),NUM2INT(mode),RSTRING_PTR(re)); return mi; }
VALUE rpm_mi_set_iterator_version(VALUE mi, VALUE version) { /* Epoch!! */ VALUE r; if (rb_obj_is_kind_of(version, rpm_cVersion) == Qfalse) rb_raise(rb_eTypeError, "illegal argument type"); #if RPM_VERSION_CODE < RPM_VERSION(4,1,0) rpmdbSetIteratorVersion(RPM_MI(mi),RSTRING_PTR(rpm_version_get_v(version))); #else rpmdbSetIteratorRE(RPM_MI(mi),RPMTAG_VERSION,RPMMIRE_DEFAULT,RSTRING_PTR(rpm_version_get_v(version))); #endif r = rpm_version_get_r(version); if(!NIL_P(r)){ #if RPM_VERSION_CODE < RPM_VERSION(4,1,0) rpmdbSetIteratorRelease(RPM_MI(mi),RSTRING_PTR(r)); #else rpmdbSetIteratorRE(RPM_MI(mi),RPMTAG_RELEASE,RPMMIRE_DEFAULT,RSTRING_PTR(r)); #endif } return mi; }
static PyObject * rpmmi_Pattern(rpmmiObject * s, PyObject * args, PyObject * kwds) { int type; char * pattern; rpmTag tag; char * kwlist[] = {"tag", "type", "patern", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&is:Pattern", kwlist, tagNumFromPyObject, &tag, &type, &pattern)) return NULL; rpmdbSetIteratorRE(s->mi, tag, type, pattern); Py_RETURN_NONE; }
/* On --freshen, verify package is installed and newer */ static int checkFreshenStatus(rpmts ts, Header h) { rpmdbMatchIterator mi = NULL; const char * name = headerGetString(h, RPMTAG_NAME); const char *arch = headerGetString(h, RPMTAG_ARCH); Header oldH = NULL; if (name != NULL) mi = rpmtsInitIterator(ts, RPMDBI_NAME, name, 0); if (rpmtsColor(ts) && arch) rpmdbSetIteratorRE(mi, RPMTAG_ARCH, RPMMIRE_DEFAULT, arch); while ((oldH = rpmdbNextIterator(mi)) != NULL) { /* Package is newer than those currently installed. */ if (rpmVersionCompare(oldH, h) < 0) break; } rpmdbFreeIterator(mi); return (oldH != NULL); }
static PyObject * rpmmi_Pattern(rpmmiObject * s, PyObject * args, PyObject * kwds) { PyObject *TagN = NULL; int type; char * pattern; rpmTag tag; char * kwlist[] = {"tag", "type", "patern", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwds, "Ois:Pattern", kwlist, &TagN, &type, &pattern)) return NULL; if ((tag = tagNumFromPyObject (TagN)) == -1) { PyErr_SetString(PyExc_TypeError, "unknown tag type"); return NULL; } rpmdbSetIteratorRE(s->mi, tag, type, pattern); Py_INCREF (Py_None); return Py_None; }
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; }
static int rpmverify_collect(probe_ctx *ctx, const char *name, oval_operation_t name_op, const char *file, oval_operation_t file_op, SEXP_t *name_ent, SEXP_t *filepath_ent, uint64_t flags, void (*callback)(probe_ctx *, struct rpmverify_res *)) { rpmdbMatchIterator match; rpmVerifyAttrs omit = (rpmVerifyAttrs)(flags & RPMVERIFY_RPMATTRMASK); Header pkgh; pcre *re = NULL; int ret = -1; /* pre-compile regex if needed */ if (file_op == OVAL_OPERATION_PATTERN_MATCH) { const char *errmsg; int erroff; re = pcre_compile(file, PCRE_UTF8, &errmsg, &erroff, NULL); if (re == NULL) { /* TODO */ return (-1); } } RPMVERIFY_LOCK; switch (name_op) { case OVAL_OPERATION_EQUALS: match = rpmtsInitIterator (g_rpm.rpmts, RPMTAG_NAME, (const void *)name, 0); if (match == NULL) { ret = 0; goto ret; } ret = rpmdbGetIteratorCount (match); break; case OVAL_OPERATION_NOT_EQUAL: match = rpmtsInitIterator (g_rpm.rpmts, RPMDBI_PACKAGES, NULL, 0); if (match == NULL) { ret = 0; goto ret; } if (rpmdbSetIteratorRE (match, RPMTAG_NAME, RPMMIRE_GLOB, "*") != 0) { ret = -1; goto ret; } break; case OVAL_OPERATION_PATTERN_MATCH: match = rpmtsInitIterator (g_rpm.rpmts, RPMDBI_PACKAGES, NULL, 0); if (match == NULL) { ret = 0; goto ret; } if (rpmdbSetIteratorRE (match, RPMTAG_NAME, RPMMIRE_REGEX, (const char *)name) != 0) { ret = -1; goto ret; } break; default: /* not supported */ dE("package name: operation not supported"); ret = -1; goto ret; } assume_d(RPMTAG_BASENAMES != 0, -1); assume_d(RPMTAG_DIRNAMES != 0, -1); while ((pkgh = rpmdbNextIterator (match)) != NULL) { rpmfi fi; rpmTag tag[2] = { RPMTAG_BASENAMES, RPMTAG_DIRNAMES }; struct rpmverify_res res; errmsg_t rpmerr; int i; SEXP_t *name_sexp; res.name = headerFormat(pkgh, "%{NAME}", &rpmerr); name_sexp = SEXP_string_newf("%s", res.name); if (probe_entobj_cmp(name_ent, name_sexp) != OVAL_RESULT_TRUE) { SEXP_free(name_sexp); continue; } SEXP_free(name_sexp); /* * Inspect package files & directories */ for (i = 0; i < 2; ++i) { fi = rpmfiNew(g_rpm.rpmts, pkgh, tag[i], 1); while (rpmfiNext(fi) != -1) { SEXP_t *filepath_sexp; res.fflags = rpmfiFFlags(fi); res.oflags = omit; if (((res.fflags & RPMFILE_CONFIG) && (flags & RPMVERIFY_SKIP_CONFIG)) || ((res.fflags & RPMFILE_GHOST) && (flags & RPMVERIFY_SKIP_GHOST))) continue; res.file = strdup(rpmfiFN(fi)); filepath_sexp = SEXP_string_newf("%s", res.file); if (probe_entobj_cmp(filepath_ent, filepath_sexp) != OVAL_RESULT_TRUE) { SEXP_free(filepath_sexp); free(res.file); continue; } SEXP_free(filepath_sexp); if (rpmVerifyFile(g_rpm.rpmts, fi, &res.vflags, omit) != 0) res.vflags = RPMVERIFY_FAILURES; callback(ctx, &res); free(res.file); } rpmfiFree(fi); } } match = rpmdbFreeIterator (match); ret = 0; ret: if (re != NULL) pcre_free(re); RPMVERIFY_UNLOCK; return (ret); }