cxxll::rpmfi_handle::rpmfi_handle(Header header) { raw_ = rpmfiNew(0, header, 0, 0); if (raw_ == NULL) { throw rpm_parser_exception("rpmfiNew failed"); } }
/** \ingroup py_c */ static int rpmfi_init(rpmfiObject * s, PyObject *args, PyObject *kwds) /*@globals rpmGlobalMacroContext @*/ /*@modifies s, rpmGlobalMacroContext @*/ { hdrObject * ho = NULL; PyObject * to = NULL; rpmts ts = NULL; /* XXX FIXME: fiFromHeader should be a ts method. */ int tagN = RPMTAG_BASENAMES; int flags = 0; char * kwlist[] = {"header", "tag", "flags", NULL}; if (_rpmfi_debug < 0) fprintf(stderr, "*** rpmfi_init(%p,%p,%p)\n", s, args, kwds); if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|Oi:rpmfi_init", kwlist, &hdr_Type, &ho, &to, &flags)) return -1; if (to != NULL) { tagN = tagNumFromPyObject(to); if (tagN == -1) { PyErr_SetString(PyExc_KeyError, "unknown header tag"); return -1; } } s->fi = rpmfiNew(ts, hdrGetHeader(ho), tagN, flags); s->active = 0; return 0; }
/** * Check file info from header against what's actually installed. * @param ts transaction set * @param h header to verify * @param omitMask bits to disable verify checks * @param ghosts should ghosts be verified? * @return 0 no problems, 1 problems found */ static int verifyHeader(rpmts ts, Header h, rpmVerifyAttrs omitMask, int ghosts) { rpmVerifyAttrs verifyResult = 0; int ec = 0; /* assume no problems */ rpmfi fi = rpmfiNew(ts, h, RPMTAG_BASENAMES, RPMFI_FLAGS_VERIFY); rpmfiInit(fi, 0); while (rpmfiNext(fi) >= 0) { rpmfileAttrs fileAttrs = rpmfiFFlags(fi); char *buf = NULL, *attrFormat; char ac; int rc; /* If not verifying %ghost, skip ghost files. */ if ((fileAttrs & RPMFILE_GHOST) && !ghosts) continue; rc = rpmVerifyFile(ts, fi, &verifyResult, omitMask); /* Filter out timestamp differences of shared files */ if (rc == 0 && (verifyResult & RPMVERIFY_MTIME)) { rpmdbMatchIterator mi; mi = rpmtsInitIterator(ts, RPMDBI_BASENAMES, rpmfiFN(fi), 0); if (rpmdbGetIteratorCount(mi) > 1) verifyResult &= ~RPMVERIFY_MTIME; rpmdbFreeIterator(mi); } attrFormat = rpmFFlagsString(fileAttrs, ""); ac = rstreq(attrFormat, "") ? ' ' : attrFormat[0]; if (rc) { if (!(fileAttrs & (RPMFILE_MISSINGOK|RPMFILE_GHOST)) || rpmIsVerbose()) { rasprintf(&buf, _("missing %c %s"), ac, rpmfiFN(fi)); if ((verifyResult & RPMVERIFY_LSTATFAIL) != 0 && errno != ENOENT) { char *app; rasprintf(&app, " (%s)", strerror(errno)); rstrcat(&buf, app); free(app); } ec = rc; } } else if (verifyResult || rpmIsVerbose()) { char *verifyFormat = rpmVerifyString(verifyResult, "."); rasprintf(&buf, "%s %c %s", verifyFormat, ac, rpmfiFN(fi)); free(verifyFormat); if (verifyResult) ec = 1; } free(attrFormat); if (buf) { rpmlog(RPMLOG_NOTICE, "%s\n", buf); buf = _free(buf); } } rpmfiFree(fi); return ec; }
static int filedepTag(Header h, rpmTag tagN, rpmtd td, headerGetFlags hgflags) { rpmfi fi = rpmfiNew(NULL, h, RPMTAG_BASENAMES, RPMFI_NOHEADER); rpmds ds = NULL; char **fdeps = NULL; int numfiles; char deptype = 'R'; int fileix; int rc = 0; numfiles = rpmfiFC(fi); if (numfiles <= 0) { goto exit; } if (tagN == RPMTAG_PROVIDENAME) deptype = 'P'; else if (tagN == RPMTAG_REQUIRENAME) deptype = 'R'; ds = rpmdsNew(h, tagN, 0); fdeps = xmalloc(numfiles * sizeof(*fdeps)); while ((fileix = rpmfiNext(fi)) >= 0) { ARGV_t deps = NULL; const uint32_t * ddict = NULL; int ndx = rpmfiFDepends(fi, &ddict); if (ddict != NULL) { while (ndx-- > 0) { const char * DNEVR; unsigned dix = *ddict++; char mydt = ((dix >> 24) & 0xff); if (mydt != deptype) continue; dix &= 0x00ffffff; (void) rpmdsSetIx(ds, dix-1); if (rpmdsNext(ds) < 0) continue; DNEVR = rpmdsDNEVR(ds); if (DNEVR != NULL) { argvAdd(&deps, DNEVR + 2); } } } fdeps[fileix] = deps ? argvJoin(deps, " ") : xstrdup(""); argvFree(deps); } td->data = fdeps; td->count = numfiles; td->flags = RPMTD_ALLOCED | RPMTD_PTR_ALLOCED; td->type = RPM_STRING_ARRAY_TYPE; rc = 1; exit: rpmfiFree(fi); rpmdsFree(ds); return rc; }
void cxxll::rpmfi_handle::reset_header(Header header) { rpmfi fi = rpmfiNew(0, header, 0, 0); if (fi == NULL) { throw rpm_parser_exception("rpmfiNew failed"); } close(); raw_ = fi; }
static VALUE rpmhdr_fi(int argc, VALUE *argv, VALUE s) { VALUE v_tag; Header h = rpmhdr_ptr(s); rpmTag tag = RPMTAG_BASENAMES; int flags = 0; rb_scan_args(argc, argv, "01", &v_tag); if (!NIL_P(v_tag)) tag = FIX2INT(v_tag); if (_debug) fprintf(stderr, "==> %s(0x%lx) h %p\n", __FUNCTION__, s, h); return rpmrb_NewFi( rpmfiNew(NULL, h, tag, flags) ); }
static int filenlinksTag(Header h, rpmtd td, headerGetFlags hgflags) { rpmfi fi = rpmfiNew(NULL, h, RPMTAG_BASENAMES, RPMFI_NOHEADER); rpm_count_t fc = rpmfiFC(fi); if (fc > 0) { uint32_t *nlinks = xmalloc(fc * sizeof(*nlinks)); int ix; while ((ix = rpmfiNext(fi)) >= 0) { nlinks[ix] = rpmfiFNlink(fi); } td->data = nlinks; td->type = RPM_INT32_TYPE; td->count = fc; td->flags = RPMTD_ALLOCED; } rpmfiFree(fi); return (fc > 0); }
static PyObject * rpmfi_new(PyTypeObject * subtype, PyObject *args, PyObject *kwds) { PyObject * to = NULL; Header h = NULL; rpmfi fi = NULL; rpmTagVal tagN = RPMTAG_BASENAMES; int flags = 0; char * kwlist[] = {"header", "tag", "flags", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&|Oi:rpmfi_init", kwlist, hdrFromPyObject, &h, &to, &flags)) return NULL; fi = rpmfiNew(NULL, h, tagN, flags); if (fi == NULL) { PyErr_SetString(PyExc_ValueError, "invalid file data in header"); return NULL; } return rpmfi_Wrap(subtype, fi); }
string_list * rpm_file_list(const char * pkg) { rpmReadConfigFiles(NULL, NULL); FD_t fd = Fopen(pkg, "r.ufdio"); rpmts ts = rpmtsCreate(); Header h; rpmReadPackageFile(ts, fd, NULL, &h); rpmtsFree(ts); string_list * sl = string_list_new(); rpmfi fi = rpmfiNew(NULL, h, RPMTAG_BASENAMES, RPMFI_KEEPHEADER); if (fi) { while (rpmfiNext(fi) != -1) { string_list_append(sl, rpmfiFN(fi)); } fi = rpmfiFree(fi); } return sl; }
rpmfiObject * hdr_fiFromHeader(PyObject * s, PyObject * args, PyObject * kwds) { hdrObject * ho = (hdrObject *)s; PyObject * to = NULL; rpmts ts = NULL; /* XXX FIXME: fiFromHeader should be a ts method. */ rpmTag tagN = RPMTAG_BASENAMES; int flags = 0; char * kwlist[] = {"tag", "flags", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oi:fiFromHeader", kwlist, &to, &flags)) return NULL; if (to != NULL) { tagN = tagNumFromPyObject(to); if (tagN == (rpmTag)-1) { PyErr_SetString(PyExc_KeyError, "unknown header tag"); return NULL; } } return rpmfi_Wrap( rpmfiNew(ts, hdrGetHeader(ho), tagN, flags) ); }
/** * Retrieve/generate file classes. * @param h header * @retval td tag data container * @param hgflags header get flags * @return 1 on success */ static int fileclassTag(Header h, rpmtd td, headerGetFlags hgflags) { rpmfi fi = rpmfiNew(NULL, h, RPMTAG_BASENAMES, RPMFI_NOHEADER); int numfiles = rpmfiFC(fi); if (numfiles > 0) { char **fclasses = xmalloc(numfiles * sizeof(*fclasses)); int ix; rpmfiInit(fi, 0); while ((ix = rpmfiNext(fi)) >= 0) { fclasses[ix] = makeFClass(fi); } td->data = fclasses; td->count = numfiles; td->flags = RPMTD_ALLOCED | RPMTD_PTR_ALLOCED; td->type = RPM_STRING_ARRAY_TYPE; } rpmfiFree(fi); return (numfiles > 0); }
static VALUE rpmfi_new(int argc, VALUE *argv, VALUE s) { VALUE v_ts, v_hdr, v_tag; rpmts ts; Header h; rpmTag tag = RPMTAG_BASENAMES; int flags = 0; rpmfi fi; rb_scan_args(argc, argv, "21", &v_ts, &v_hdr, &v_tag); ts = rpmfi_ptr(v_ts); h = rpmfi_ptr(v_hdr); if (!NIL_P(v_tag)) tag = FIX2INT(v_tag); fi = rpmfiNew(ts, h, tag, flags); if (_debug) fprintf(stderr, "==> %s(%p[%d], 0x%lx) mi %p\n", __FUNCTION__, argv, argc, s, fi); return Data_Wrap_Struct(s, 0, rpmfi_free, fi); }
QueryData genRpmPackageFiles(QueryContext& context) { QueryData results; if (rpmReadConfigFiles(nullptr, nullptr) != 0) { TLOG << "Cannot read RPM configuration files."; return results; } rpmts ts = rpmtsCreate(); rpmdbMatchIterator matches; if (context.constraints["package"].exists()) { auto name = (*context.constraints["package"].getAll(EQUALS).begin()); matches = rpmtsInitIterator(ts, RPMTAG_NAME, name.c_str(), name.size()); } else { matches = rpmtsInitIterator(ts, RPMTAG_NAME, nullptr, 0); } Header header; while ((header = rpmdbNextIterator(matches)) != nullptr) { rpmtd td = rpmtdNew(); rpmfi fi = rpmfiNew(ts, header, RPMTAG_BASENAMES, RPMFI_NOHEADER); auto file_count = rpmfiFC(fi); if (file_count <= 0 || file_count > MAX_RPM_FILES) { // This package contains no or too many files. rpmfiFree(fi); continue; } // Iterate over every file in this package. for (size_t i = 0; rpmfiNext(fi) >= 0 && i < file_count; i++) { Row r; r["package"] = getRpmAttribute(header, RPMTAG_NAME, td); auto path = rpmfiFN(fi); r["path"] = (path != nullptr) ? path : ""; auto username = rpmfiFUser(fi); r["username"] = (username != nullptr) ? username : ""; auto groupname = rpmfiFGroup(fi); r["groupname"] = (groupname != nullptr) ? groupname : ""; r["mode"] = lsperms(rpmfiFMode(fi)); r["size"] = BIGINT(rpmfiFSize(fi)); #ifdef CENTOS_CENTOS6 // Older versions of rpmlib/rpmip use a hash algorithm enum. pgpHashAlgo digest_algo; #else int digest_algo; #endif auto digest = rpmfiFDigestHex(fi, &digest_algo); if (digest_algo == PGPHASHALGO_SHA256) { r["sha256"] = (digest != nullptr) ? digest : ""; } results.push_back(r); } rpmfiFree(fi); rpmtdFree(td); } rpmdbFreeIterator(matches); rpmtsFree(ts); rpmFreeRpmrc(); return results; }
/** * Check file info from header against what's actually installed. * @param qva parsed query/verify options * @param ts transaction set * @param h header to verify * @return 0 no problems, 1 problems found */ static int verifyHeader(QVA_t qva, const rpmts ts, Header h) { rpmVerifyAttrs verifyResult = 0; /* FIX: union? */ rpmVerifyAttrs omitMask = ((qva->qva_flags & VERIFY_ATTRS) ^ VERIFY_ATTRS); int ec = 0; /* assume no problems */ char *buf = NULL; int i; rpmfi fi = rpmfiNew(ts, h, RPMTAG_BASENAMES, RPMFI_FLAGS_VERIFY); rpmfiInit(fi, 0); while ((i = rpmfiNext(fi)) >= 0) { rpmfileAttrs fileAttrs; int rc; fileAttrs = rpmfiFFlags(fi); /* If not verifying %ghost, skip ghost files. */ if (!(qva->qva_fflags & RPMFILE_GHOST) && (fileAttrs & RPMFILE_GHOST)) continue; rc = rpmVerifyFile(ts, fi, &verifyResult, omitMask); if (rc) { if (!(fileAttrs & (RPMFILE_MISSINGOK|RPMFILE_GHOST)) || rpmIsVerbose()) { rasprintf(&buf, _("missing %c %s"), ((fileAttrs & RPMFILE_CONFIG) ? 'c' : (fileAttrs & RPMFILE_DOC) ? 'd' : (fileAttrs & RPMFILE_GHOST) ? 'g' : (fileAttrs & RPMFILE_LICENSE) ? 'l' : (fileAttrs & RPMFILE_PUBKEY) ? 'P' : (fileAttrs & RPMFILE_README) ? 'r' : ' '), rpmfiFN(fi)); if ((verifyResult & RPMVERIFY_LSTATFAIL) != 0 && errno != ENOENT) { char *app; rasprintf(&app, " (%s)", strerror(errno)); rstrcat(&buf, app); free(app); } ec = rc; } } else if (verifyResult || rpmIsVerbose()) { const char * size, * MD5, * link, * mtime, * mode; const char * group, * user, * rdev, *caps; static const char *const aok = "."; static const char *const unknown = "?"; ec = 1; #define _verify(_RPMVERIFY_F, _C) \ ((verifyResult & _RPMVERIFY_F) ? _C : aok) #define _verifylink(_RPMVERIFY_F, _C) \ ((verifyResult & RPMVERIFY_READLINKFAIL) ? unknown : \ (verifyResult & _RPMVERIFY_F) ? _C : aok) #define _verifyfile(_RPMVERIFY_F, _C) \ ((verifyResult & RPMVERIFY_READFAIL) ? unknown : \ (verifyResult & _RPMVERIFY_F) ? _C : aok) MD5 = _verifyfile(RPMVERIFY_MD5, "5"); size = _verify(RPMVERIFY_FILESIZE, "S"); link = _verifylink(RPMVERIFY_LINKTO, "L"); mtime = _verify(RPMVERIFY_MTIME, "T"); rdev = _verify(RPMVERIFY_RDEV, "D"); user = _verify(RPMVERIFY_USER, "U"); group = _verify(RPMVERIFY_GROUP, "G"); mode = _verify(RPMVERIFY_MODE, "M"); caps = _verify(RPMVERIFY_CAPS, "P"); #undef _verifyfile #undef _verifylink #undef _verify rasprintf(&buf, "%s%s%s%s%s%s%s%s%s %c %s", size, mode, MD5, rdev, link, user, group, mtime, caps, ((fileAttrs & RPMFILE_CONFIG) ? 'c' : (fileAttrs & RPMFILE_DOC) ? 'd' : (fileAttrs & RPMFILE_GHOST) ? 'g' : (fileAttrs & RPMFILE_LICENSE) ? 'l' : (fileAttrs & RPMFILE_PUBKEY) ? 'P' : (fileAttrs & RPMFILE_README) ? 'r' : ' '), rpmfiFN(fi)); } if (buf) { rpmlog(RPMLOG_NOTICE, "%s\n", buf); buf = _free(buf); } } rpmfiFree(fi); return ec; }
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); }
rpmRC rpmInstallSourcePackage(rpmts ts, FD_t fd, char ** specFilePtr, char ** cookie) { rpmfi fi = NULL; char * specFile = NULL; const char *rootdir = rpmtsRootDir(ts); Header h = NULL; rpmpsm psm = NULL; rpmte te = NULL; rpmRC rpmrc; int specix = -1; struct rpmtd_s filenames; rpmtdReset(&filenames); rpmrc = rpmReadPackageFile(ts, fd, NULL, &h); switch (rpmrc) { case RPMRC_NOTTRUSTED: case RPMRC_NOKEY: case RPMRC_OK: break; default: goto exit; break; } if (h == NULL) goto exit; rpmrc = RPMRC_FAIL; /* assume failure */ if (!headerIsSource(h)) { rpmlog(RPMLOG_ERR, _("source package expected, binary found\n")); goto exit; } /* src.rpm install can require specific rpmlib features, check them */ if (!rpmlibDeps(h)) goto exit; if (headerGet(h, RPMTAG_BASENAMES, &filenames, HEADERGET_ALLOC)) { struct rpmtd_s td; const char *str; const char *_cookie = headerGetString(h, RPMTAG_COOKIE); if (cookie && _cookie) *cookie = xstrdup(_cookie); /* Try to find spec by file flags */ if (_cookie && headerGet(h, RPMTAG_FILEFLAGS, &td, HEADERGET_MINMEM)) { rpmfileAttrs *flags; while (specix < 0 && (flags = rpmtdNextUint32(&td))) { if (*flags & RPMFILE_SPECFILE) specix = rpmtdGetIndex(&td); } } /* Still no spec? Look by filename. */ while (specix < 0 && (str = rpmtdNextString(&filenames))) { if (rpmFileHasSuffix(str, ".spec")) specix = rpmtdGetIndex(&filenames); } } if (rootdir && rstreq(rootdir, "/")) rootdir = NULL; /* Macros need to be added before trying to create directories */ rpmInstallLoadMacros(h); if (specix >= 0) { const char *bn; headerDel(h, RPMTAG_BASENAMES); headerDel(h, RPMTAG_DIRNAMES); headerDel(h, RPMTAG_DIRINDEXES); rpmtdInit(&filenames); for (int i = 0; (bn = rpmtdNextString(&filenames)); i++) { int spec = (i == specix); char *fn = rpmGenPath(rpmtsRootDir(ts), spec ? "%{_specdir}" : "%{_sourcedir}", bn); headerPutString(h, RPMTAG_OLDFILENAMES, fn); if (spec) specFile = xstrdup(fn); free(fn); } headerConvert(h, HEADERCONV_COMPRESSFILELIST); } else { rpmlog(RPMLOG_ERR, _("source package contains no .spec file\n")); goto exit; }; if (rpmtsAddInstallElement(ts, h, NULL, 0, NULL)) { goto exit; } te = rpmtsElement(ts, 0); if (te == NULL) { /* XXX can't happen */ goto exit; } rpmteSetFd(te, fd); rpmteSetHeader(te, h); fi = rpmfiNew(ts, h, RPMTAG_BASENAMES, RPMFI_KEEPHEADER); h = headerFree(h); if (fi == NULL) { goto exit; } fi->apath = filenames.data; /* Ick */ rpmteSetFI(te, fi); fi = rpmfiFree(fi); if (rpmMkdirs(rpmtsRootDir(ts), "%{_topdir}:%{_sourcedir}:%{_specdir}")) { goto exit; } { /* set all files to be installed */ rpmfs fs = rpmteGetFileStates(te); int i; unsigned int fc = rpmfiFC(fi); for (i=0; i<fc; i++) rpmfsSetAction(fs, i, FA_CREATE); } psm = rpmpsmNew(ts, te); psm->goal = PKG_INSTALL; /* FIX: psm->fi->dnl should be owned. */ if (rpmpsmStage(psm, PSM_PROCESS) == RPMRC_OK) rpmrc = RPMRC_OK; (void) rpmpsmStage(psm, PSM_FINI); rpmpsmFree(psm); exit: if (specFilePtr && specFile && rpmrc == RPMRC_OK) *specFilePtr = specFile; else free(specFile); headerFree(h); rpmfiFree(fi); /* XXX nuke the added package(s). */ rpmtsClean(ts); return rpmrc; }
int showVerifyPackage(QVA_t qva, rpmts ts, Header h) { static int scareMem = 0; rpmVerifyAttrs omitMask = ((qva->qva_flags & VERIFY_ATTRS) ^ VERIFY_ATTRS); int spew = (qva->qva_mode != 'v'); /* XXX no output w verify(...) probe. */ int ec = 0; int i; rpmfi fi = rpmfiNew(ts, h, RPMTAG_BASENAMES, scareMem); uint32_t fc = rpmfiFC(fi); { /* Verify header digest/signature. */ if (qva->qva_flags & (VERIFY_DIGEST | VERIFY_SIGNATURE)) { const char * horigin = headerGetOrigin(h); const char * msg = NULL; size_t uhlen = 0; void * uh = headerUnload(h, &uhlen); int lvl = headerCheck(rpmtsDig(ts), uh, uhlen, &msg) == RPMRC_FAIL ? RPMLOG_ERR : RPMLOG_DEBUG; rpmlog(lvl, "%s: %s\n", (horigin ? horigin : "verify"), (msg ? msg : "")); rpmtsCleanDig(ts); uh = _free(uh); msg = _free(msg); } /* Verify file digests. */ if (fc > 0 && (qva->qva_flags & VERIFY_FILES)) #if defined(_OPENMP) #pragma omp parallel for private(i) reduction(+:ec) #endif for (i = 0; i < (int)fc; i++) { int fflags = fi->fflags[i]; rpmvf vf; int rc; /* If not querying %config, skip config files. */ if ((qva->qva_fflags & RPMFILE_CONFIG) && (fflags & RPMFILE_CONFIG)) continue; /* If not querying %doc, skip doc files. */ if ((qva->qva_fflags & RPMFILE_DOC) && (fflags & RPMFILE_DOC)) continue; /* If not verifying %ghost, skip ghost files. */ /* XXX the broken!!! logic disables %ghost queries always. */ if (!(qva->qva_fflags & RPMFILE_GHOST) && (fflags & RPMFILE_GHOST)) continue; /* Gather per-file data into a carrier. */ vf = rpmvfNew(ts, fi, i, omitMask); /* Verify per-file metadata. */ rc = rpmvfVerify(vf, spew); if (rc) ec += rc; (void) rpmvfFree(vf); vf = NULL; } /* Run verify/sanity scripts (if any). */ if (qva->qva_flags & VERIFY_SCRIPT) { int rc; if (headerIsEntry(h, RPMTAG_VERIFYSCRIPT) || headerIsEntry(h, RPMTAG_SANITYCHECK)) { FD_t fdo = fdDup(STDOUT_FILENO); rc = rpmfiSetHeader(fi, h); if ((rc = rpmVerifyScript(qva, ts, fi, fdo)) != 0) ec += rc; if (fdo != NULL) rc = Fclose(fdo); rc = rpmfiSetHeader(fi, NULL); } } /* Verify dependency assertions. */ if (qva->qva_flags & VERIFY_DEPS) { int save_noise = _rpmds_unspecified_epoch_noise; int rc; /*@-mods@*/ if (rpmIsVerbose()) _rpmds_unspecified_epoch_noise = 1; if ((rc = verifyDependencies(qva, ts, h)) != 0) ec += rc; _rpmds_unspecified_epoch_noise = save_noise; /*@=mods@*/ } } fi = rpmfiFree(fi); return ec; }
/* Check files in the transactions against the rpmdb * Lookup all files with the same basename in the rpmdb * and then check for matching finger prints * @param ts transaction set * @param fpc global finger print cache */ static void checkInstalledFiles(rpmts ts, fingerPrintCache fpc) { rpmps ps; rpmte p; rpmfi fi; rpmfs fs; rpmfi otherFi=NULL; int j; int xx; unsigned int fileNum; const char * oldDir; rpmdbMatchIterator mi; Header h, newheader; int beingRemoved; rpmlog(RPMLOG_DEBUG, "computing file dispositions\n"); mi = rpmFindBaseNamesInDB(ts); /* For all installed headers with matching basename's ... */ if (mi == NULL) return; if (rpmdbGetIteratorCount(mi) == 0) { mi = rpmdbFreeIterator(mi); return; } ps = rpmtsProblems(ts); /* Loop over all packages from the rpmdb */ h = newheader = rpmdbNextIterator(mi); while (h != NULL) { headerGetFlags hgflags = HEADERGET_MINMEM; struct rpmtd_s bnames, dnames, dindexes, ostates; fingerPrint fp; unsigned int installedPkg; /* Is this package being removed? */ installedPkg = rpmdbGetIteratorOffset(mi); beingRemoved = 0; if (ts->removedPackages != NULL) for (j = 0; j < ts->numRemovedPackages; j++) { if (ts->removedPackages[j] != installedPkg) continue; beingRemoved = 1; break; } h = headerLink(h); headerGet(h, RPMTAG_BASENAMES, &bnames, hgflags); headerGet(h, RPMTAG_DIRNAMES, &dnames, hgflags); headerGet(h, RPMTAG_DIRINDEXES, &dindexes, hgflags); headerGet(h, RPMTAG_FILESTATES, &ostates, hgflags); oldDir = NULL; /* loop over all interesting files in that package */ do { int gotRecs; struct rpmffi_s * recs; int numRecs; const char * dirName; const char * baseName; fileNum = rpmdbGetIteratorFileNum(mi); rpmtdSetIndex(&bnames, fileNum); rpmtdSetIndex(&dindexes, fileNum); rpmtdSetIndex(&dnames, *rpmtdGetUint32(&dindexes)); rpmtdSetIndex(&ostates, fileNum); dirName = rpmtdGetString(&dnames); baseName = rpmtdGetString(&bnames); /* lookup finger print for this file */ if ( dirName == oldDir) { /* directory is the same as last round */ fp.baseName = baseName; } else { fp = fpLookup(fpc, dirName, baseName, 1); oldDir = dirName; } /* search for files in the transaction with same finger print */ gotRecs = rpmFpHashGetEntry(ts->ht, &fp, &recs, &numRecs, NULL); for (j=0; (j<numRecs)&&gotRecs; j++) { p = recs[j].p; fi = rpmteFI(p); fs = rpmteGetFileStates(p); /* Determine the fate of each file. */ switch (rpmteType(p)) { case TR_ADDED: if (!otherFi) { otherFi = rpmfiNew(ts, h, RPMTAG_BASENAMES, RPMFI_KEEPHEADER); } rpmfiSetFX(fi, recs[j].fileno); rpmfiSetFX(otherFi, fileNum); xx = handleInstInstalledFile(ts, p, fi, h, otherFi, beingRemoved); break; case TR_REMOVED: if (!beingRemoved) { rpmfiSetFX(fi, recs[j].fileno); if (*rpmtdGetChar(&ostates) == RPMFILE_STATE_NORMAL) rpmfsSetAction(fs, recs[j].fileno, FA_SKIP); } break; } } newheader = rpmdbNextIterator(mi); } while (newheader==h); otherFi = rpmfiFree(otherFi); rpmtdFreeData(&ostates); rpmtdFreeData(&bnames); rpmtdFreeData(&dnames); rpmtdFreeData(&dindexes); headerFree(h); h = newheader; } mi = rpmdbFreeIterator(mi); }
/** * Check file info from header against what's actually installed. * @param ts transaction set * @param h header to verify * @param omitMask bits to disable verify checks * @param incAttr skip files without these attrs (eg %ghost) * @param skipAttr skip files with these attrs (eg %ghost) * @return 0 no problems, 1 problems found */ static int verifyHeader(rpmts ts, Header h, rpmVerifyAttrs omitMask, rpmfileAttrs incAttrs, rpmfileAttrs skipAttrs) { rpmVerifyAttrs verifyResult = 0; rpmVerifyAttrs verifyAll = 0; /* assume no problems */ rpmfi fi = rpmfiNew(ts, h, RPMTAG_BASENAMES, RPMFI_FLAGS_VERIFY); if (fi == NULL) return 1; rpmfiInit(fi, 0); while (rpmfiNext(fi) >= 0) { rpmfileAttrs fileAttrs = rpmfiFFlags(fi); char *buf = NULL, *attrFormat; const char *fstate = NULL; char ac; /* If filtering by inclusion, skip non-matching (eg --configfiles) */ if (incAttrs && !(incAttrs & fileAttrs)) continue; /* Skip on attributes (eg from --noghost) */ if (skipAttrs & fileAttrs) continue; verifyResult = rpmfiVerify(fi, omitMask); /* Filter out timestamp differences of shared files */ if (verifyResult & RPMVERIFY_MTIME) { rpmdbMatchIterator mi; mi = rpmtsInitIterator(ts, RPMDBI_BASENAMES, rpmfiFN(fi), 0); if (rpmdbGetIteratorCount(mi) > 1) verifyResult &= ~RPMVERIFY_MTIME; rpmdbFreeIterator(mi); } /* State is only meaningful for installed packages */ if (headerGetInstance(h)) fstate = stateStr(rpmfiFState(fi)); attrFormat = rpmFFlagsString(fileAttrs, ""); ac = rstreq(attrFormat, "") ? ' ' : attrFormat[0]; if (verifyResult & RPMVERIFY_LSTATFAIL) { if (!(fileAttrs & (RPMFILE_MISSINGOK|RPMFILE_GHOST)) || rpmIsVerbose()) { rasprintf(&buf, _("missing %c %s"), ac, rpmfiFN(fi)); if ((verifyResult & RPMVERIFY_LSTATFAIL) != 0 && errno != ENOENT) { char *app; rasprintf(&app, " (%s)", strerror(errno)); rstrcat(&buf, app); free(app); } } } else if (verifyResult || fstate || rpmIsVerbose()) { char *verifyFormat = rpmVerifyString(verifyResult, "."); rasprintf(&buf, "%s %c %s", verifyFormat, ac, rpmfiFN(fi)); free(verifyFormat); } free(attrFormat); if (buf) { if (fstate) buf = rstrscat(&buf, " (", fstate, ")", NULL); rpmlog(RPMLOG_NOTICE, "%s\n", buf); buf = _free(buf); } verifyAll |= verifyResult; } rpmfiFree(fi); return (verifyAll != 0) ? 1 : 0; }
void genRpmPackageFiles(RowYield& yield, QueryContext& context) { auto dropper = DropPrivileges::get(); if (!dropper->dropTo("nobody") && isUserAdmin()) { LOG(WARNING) << "Cannot drop privileges for rpm_package_files"; return; } // Isolate RPM/package inspection to the canonical: /usr/lib/rpm. RpmEnvironmentManager env_manager; if (rpmReadConfigFiles(nullptr, nullptr) != 0) { TLOG << "Cannot read RPM configuration files"; return; } rpmts ts = rpmtsCreate(); rpmdbMatchIterator matches; if (context.constraints["package"].exists(EQUALS)) { auto name = (*context.constraints["package"].getAll(EQUALS).begin()); matches = rpmtsInitIterator(ts, RPMTAG_NAME, name.c_str(), name.size()); } else { matches = rpmtsInitIterator(ts, RPMTAG_NAME, nullptr, 0); } Header header; while ((header = rpmdbNextIterator(matches)) != nullptr) { rpmtd td = rpmtdNew(); rpmfi fi = rpmfiNew(ts, header, RPMTAG_BASENAMES, RPMFI_NOHEADER); std::string package_name = getRpmAttribute(header, RPMTAG_NAME, td); auto file_count = rpmfiFC(fi); if (file_count <= 0) { VLOG(1) << "RPM package " << package_name << " contains 0 files"; rpmfiFree(fi); continue; } else if (file_count > MAX_RPM_FILES) { VLOG(1) << "RPM package " << package_name << " contains over " << MAX_RPM_FILES << " files"; rpmfiFree(fi); continue; } // Iterate over every file in this package. for (size_t i = 0; rpmfiNext(fi) >= 0 && i < file_count; i++) { Row r; auto path = rpmfiFN(fi); r["package"] = package_name; r["path"] = (path != nullptr) ? path : ""; auto username = rpmfiFUser(fi); r["username"] = (username != nullptr) ? username : ""; auto groupname = rpmfiFGroup(fi); r["groupname"] = (groupname != nullptr) ? groupname : ""; r["mode"] = lsperms(rpmfiFMode(fi)); r["size"] = BIGINT(rpmfiFSize(fi)); int digest_algo; auto digest = rpmfiFDigestHex(fi, &digest_algo); if (digest_algo == PGPHASHALGO_SHA256) { r["sha256"] = (digest != nullptr) ? digest : ""; } yield(r); } rpmfiFree(fi); rpmtdFree(td); } rpmdbFreeIterator(matches); rpmtsFree(ts); rpmFreeRpmrc(); }