static void rpmfi_dealloc(rpmfiObject * s) { s->fi = rpmfiFree(s->fi); Py_TYPE(s)->tp_free((PyObject *)s); }
/** * 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; }
/** * Skip any files that do not match install policies. * @param ts transaction set * @param fi file info set */ static void skipInstallFiles(const rpmts ts, rpmfiles files, rpmfs fs) { rpm_color_t tscolor = rpmtsColor(ts); rpm_color_t FColor; int noConfigs = (rpmtsFlags(ts) & RPMTRANS_FLAG_NOCONFIGS); int noDocs = (rpmtsFlags(ts) & RPMTRANS_FLAG_NODOCS); int * drc; char * dff; int dc; int i, j, ix; rpmfi fi = rpmfilesIter(files, RPMFI_ITER_FWD); if (!noDocs) noDocs = rpmExpandNumeric("%{_excludedocs}"); /* Compute directory refcount, skip directory if now empty. */ dc = rpmfiDC(fi); drc = xcalloc(dc, sizeof(*drc)); dff = xcalloc(dc, sizeof(*dff)); fi = rpmfiInit(fi, 0); while ((i = rpmfiNext(fi)) >= 0) { char ** nsp; const char *flangs; ix = rpmfiDX(fi); drc[ix]++; /* Don't bother with skipped files */ if (XFA_SKIPPING(rpmfsGetAction(fs, i))) { drc[ix]--; dff[ix] = 1; continue; } /* Ignore colored files not in our rainbow. */ FColor = rpmfiFColor(fi); if (tscolor && FColor && !(tscolor & FColor)) { drc[ix]--; dff[ix] = 1; rpmfsSetAction(fs, i, FA_SKIPCOLOR); continue; } /* * Skip net shared paths. * Net shared paths are not relative to the current root (though * they do need to take package relocations into account). */ if (ts->netsharedPaths) { nsp = matchNetsharedpath(ts, fi); if (nsp && *nsp) { drc[ix]--; dff[ix] = 1; rpmfsSetAction(fs, i, FA_SKIPNETSHARED); continue; } } /* * Skip i18n language specific files. */ flangs = (ts->installLangs != NULL) ? rpmfiFLangs(fi) : NULL; if (flangs != NULL && *flangs != '\0') { const char *l, *le; char **lang; for (lang = ts->installLangs; *lang != NULL; lang++) { for (l = flangs; *l != '\0'; l = le) { for (le = l; *le != '\0' && *le != '|'; le++) {}; if ((le-l) > 0 && rstreqn(*lang, l, (le-l))) break; if (*le == '|') le++; /* skip over | */ } if (*l != '\0') break; } if (*lang == NULL) { drc[ix]--; dff[ix] = 1; rpmfsSetAction(fs, i, FA_SKIPNSTATE); continue; } } /* * Skip config files if requested. */ if (noConfigs && (rpmfiFFlags(fi) & RPMFILE_CONFIG)) { drc[ix]--; dff[ix] = 1; rpmfsSetAction(fs, i, FA_SKIPNSTATE); continue; } /* * Skip documentation if requested. */ if (noDocs && (rpmfiFFlags(fi) & RPMFILE_DOC)) { drc[ix]--; dff[ix] = 1; rpmfsSetAction(fs, i, FA_SKIPNSTATE); continue; } } /* Skip (now empty) directories that had skipped files. */ for (j = 0; j < dc; j++) { const char * dn, * bn; size_t dnlen, bnlen; if (drc[j]) continue; /* dir still has files. */ if (!dff[j]) continue; /* dir was not emptied here. */ /* Find parent directory and basename. */ dn = rpmfilesDN(files, j); dnlen = strlen(dn) - 1; bn = dn + dnlen; bnlen = 0; while (bn > dn && bn[-1] != '/') { bnlen++; dnlen--; bn--; } /* If explicitly included in the package, skip the directory. */ fi = rpmfiInit(fi, 0); while ((i = rpmfiNext(fi)) >= 0) { const char * fdn, * fbn; rpm_mode_t fFMode; if (XFA_SKIPPING(rpmfsGetAction(fs, i))) continue; fFMode = rpmfiFMode(fi); if (rpmfiWhatis(fFMode) != XDIR) continue; fdn = rpmfiDN(fi); if (strlen(fdn) != dnlen) continue; if (!rstreqn(fdn, dn, dnlen)) continue; fbn = rpmfiBN(fi); if (strlen(fbn) != bnlen) continue; if (!rstreqn(fbn, bn, bnlen)) continue; rpmlog(RPMLOG_DEBUG, "excluding directory %s\n", dn); rpmfsSetAction(fs, i, FA_SKIPNSTATE); break; } } free(drc); free(dff); rpmfiFree(fi); }
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(); }
/* 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, uint64_t fileCount, rpmFpHash ht, fingerPrintCache fpc) { tsMembers tsmem = rpmtsMembers(ts); rpmte p; rpmfi fi; rpmfs fs; rpmfi otherFi=NULL; int j; unsigned int fileNum; const char * oldDir; rpmdbMatchIterator mi; Header h, newheader; int beingRemoved; rpmlog(RPMLOG_DEBUG, "computing file dispositions\n"); mi = rpmFindBaseNamesInDB(ts, fileCount); /* For all installed headers with matching basename's ... */ if (mi == NULL) return; if (rpmdbGetIteratorCount(mi) == 0) { mi = rpmdbFreeIterator(mi); return; } /* 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 = intHashHasEntry(tsmem->removedPackages, installedPkg); 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(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); 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; } rpmdbFreeIterator(mi); }
rpmfi rpmfiNew(const rpmts ts, Header h, rpmTagVal tagN, rpmfiFlags flags) { rpmfi fi = xcalloc(1, sizeof(*fi)); unsigned char * t; struct rpmtd_s fdigests, digalgo; struct rpmtd_s td; headerGetFlags scareFlags = (flags & RPMFI_KEEPHEADER) ? HEADERGET_MINMEM : HEADERGET_ALLOC; headerGetFlags defFlags = HEADERGET_ALLOC; fi->magic = RPMFIMAGIC; fi->i = -1; fi->fiflags = flags; _hgfi(h, RPMTAG_BASENAMES, &td, defFlags, fi->bnl); fi->fc = rpmtdCount(&td); if (fi->fc == 0) { goto exit; } _hgfi(h, RPMTAG_DIRNAMES, &td, defFlags, fi->dnl); fi->dc = rpmtdCount(&td); _hgfi(h, RPMTAG_DIRINDEXES, &td, scareFlags, fi->dil); /* Is our filename triplet sane? */ if (fi->dc == 0 || fi->dc > fi->fc || rpmtdCount(&td) != fi->fc) goto errxit; for (rpm_count_t i = 0; i < fi->fc; i++) { if (fi->dil[i] >= fi->fc) goto errxit; } /* XXX TODO: all these should be sanity checked, ugh... */ if (!(flags & RPMFI_NOFILEMODES)) _hgfi(h, RPMTAG_FILEMODES, &td, scareFlags, fi->fmodes); if (!(flags & RPMFI_NOFILEFLAGS)) _hgfi(h, RPMTAG_FILEFLAGS, &td, scareFlags, fi->fflags); if (!(flags & RPMFI_NOFILEVERIFYFLAGS)) _hgfi(h, RPMTAG_FILEVERIFYFLAGS, &td, scareFlags, fi->vflags); if (!(flags & RPMFI_NOFILESIZES)) _hgfi(h, RPMTAG_FILESIZES, &td, scareFlags, fi->fsizes); if (!(flags & RPMFI_NOFILECOLORS)) _hgfi(h, RPMTAG_FILECOLORS, &td, scareFlags, fi->fcolors); if (!(flags & RPMFI_NOFILECLASS)) { _hgfi(h, RPMTAG_CLASSDICT, &td, scareFlags, fi->cdict); fi->ncdict = rpmtdCount(&td); _hgfi(h, RPMTAG_FILECLASS, &td, scareFlags, fi->fcdictx); } if (!(flags & RPMFI_NOFILEDEPS)) { _hgfi(h, RPMTAG_DEPENDSDICT, &td, scareFlags, fi->ddict); fi->nddict = rpmtdCount(&td); _hgfi(h, RPMTAG_FILEDEPENDSX, &td, scareFlags, fi->fddictx); _hgfi(h, RPMTAG_FILEDEPENDSN, &td, scareFlags, fi->fddictn); } if (!(flags & RPMFI_NOFILESTATES)) _hgfi(h, RPMTAG_FILESTATES, &td, defFlags, fi->fstates); if (!(flags & RPMFI_NOFILECAPS) && headerIsEntry(h, RPMTAG_FILECAPS)) { fi->fcapcache = strcacheNew(); fi->fcaps = cacheTag(fi->fcapcache, h, RPMTAG_FILECAPS); } if (!(flags & RPMFI_NOFILELINKTOS)) { fi->flinkcache = strcacheNew(); fi->flinks = cacheTag(fi->flinkcache, h, RPMTAG_FILELINKTOS); } /* FILELANGS are only interesting when installing */ if ((headerGetInstance(h) == 0) && !(flags & RPMFI_NOFILELANGS)) fi->flangs = cacheTag(langcache, h, RPMTAG_FILELANGS); /* See if the package has non-md5 file digests */ fi->digestalgo = PGPHASHALGO_MD5; if (headerGet(h, RPMTAG_FILEDIGESTALGO, &digalgo, HEADERGET_MINMEM)) { uint32_t *algo = rpmtdGetUint32(&digalgo); /* Hmm, what to do with unknown digest algorithms? */ if (algo && rpmDigestLength(*algo) != 0) { fi->digestalgo = *algo; } } fi->digests = NULL; /* grab hex digests from header and store in binary format */ if (!(flags & RPMFI_NOFILEDIGESTS) && headerGet(h, RPMTAG_FILEDIGESTS, &fdigests, HEADERGET_MINMEM)) { const char *fdigest; size_t diglen = rpmDigestLength(fi->digestalgo); fi->digests = t = xmalloc(rpmtdCount(&fdigests) * diglen); while ((fdigest = rpmtdNextString(&fdigests))) { if (!(fdigest && *fdigest != '\0')) { memset(t, 0, diglen); t += diglen; continue; } for (int j = 0; j < diglen; j++, t++, fdigest += 2) *t = (rnibble(fdigest[0]) << 4) | rnibble(fdigest[1]); } rpmtdFreeData(&fdigests); } /* XXX TR_REMOVED doesn;t need fmtimes, frdevs, finodes */ if (!(flags & RPMFI_NOFILEMTIMES)) _hgfi(h, RPMTAG_FILEMTIMES, &td, scareFlags, fi->fmtimes); if (!(flags & RPMFI_NOFILERDEVS)) _hgfi(h, RPMTAG_FILERDEVS, &td, scareFlags, fi->frdevs); if (!(flags & RPMFI_NOFILEINODES)) _hgfi(h, RPMTAG_FILEINODES, &td, scareFlags, fi->finodes); if (!(flags & RPMFI_NOFILEUSER)) fi->fuser = cacheTag(ugcache, h, RPMTAG_FILEUSERNAME); if (!(flags & RPMFI_NOFILEGROUP)) fi->fgroup = cacheTag(ugcache, h, RPMTAG_FILEGROUPNAME); /* lazily alloced from rpmfiFN() */ fi->fn = NULL; exit: if (fi != NULL) { fi->h = (fi->fiflags & RPMFI_KEEPHEADER) ? headerLink(h) : NULL; } /* FIX: rpmfi null annotations */ return rpmfiLink(fi); errxit: rpmfiFree(fi); return NULL; }
rpmRC packageBinaries(rpmSpec spec) { struct cpioSourceArchive_s csabuf; CSA_t csa = &csabuf; rpmRC rc; const char *errorString; Package pkg; char *pkglist = NULL; for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) { char *fn; if (pkg->fileList == NULL) continue; if ((rc = processScriptFiles(spec, pkg))) return rc; if (spec->cookie) { headerPutString(pkg->header, RPMTAG_COOKIE, spec->cookie); } /* Copy changelog from src rpm */ headerCopyTags(spec->packages->header, pkg->header, copyTags); headerPutString(pkg->header, RPMTAG_RPMVERSION, VERSION); headerPutString(pkg->header, RPMTAG_BUILDHOST, buildHost()); headerPutUint32(pkg->header, RPMTAG_BUILDTIME, getBuildTime(), 1); addPackageProvides(pkg->header); { char * optflags = rpmExpand("%{optflags}", NULL); headerPutString(pkg->header, RPMTAG_OPTFLAGS, optflags); optflags = _free(optflags); } if (spec->sourcePkgId != NULL) { headerPutBin(pkg->header, RPMTAG_SOURCEPKGID, spec->sourcePkgId,16); } { char *binFormat = rpmGetPath("%{_rpmfilename}", NULL); char *binRpm, *binDir; binRpm = headerFormat(pkg->header, binFormat, &errorString); binFormat = _free(binFormat); if (binRpm == NULL) { const char *name; (void) headerNVR(pkg->header, &name, NULL, NULL); rpmlog(RPMLOG_ERR, _("Could not generate output " "filename for package %s: %s\n"), name, errorString); return RPMRC_FAIL; } fn = rpmGetPath("%{_rpmdir}/", binRpm, NULL); if ((binDir = strchr(binRpm, '/')) != NULL) { struct stat st; char *dn; *binDir = '\0'; dn = rpmGetPath("%{_rpmdir}/", binRpm, NULL); if (stat(dn, &st) < 0) { switch(errno) { case ENOENT: if (mkdir(dn, 0755) == 0) break; default: rpmlog(RPMLOG_ERR,_("cannot create %s: %s\n"), dn, strerror(errno)); break; } } dn = _free(dn); } binRpm = _free(binRpm); } memset(csa, 0, sizeof(*csa)); csa->cpioArchiveSize = 0; /* LCL: function typedefs */ csa->cpioFdIn = fdNew(RPMDBG_M("init (packageBinaries)")); csa->cpioList = rpmfiLink(pkg->cpioList, RPMDBG_M("packageBinaries")); rc = writeRPM(&pkg->header, NULL, fn, csa, spec->passPhrase, NULL); csa->cpioList = rpmfiFree(csa->cpioList); csa->cpioFdIn = fdFree(csa->cpioFdIn, RPMDBG_M("init (packageBinaries)")); if (rc == RPMRC_OK) { /* Do check each written package if enabled */ char *pkgcheck = rpmExpand("%{?_build_pkgcheck} ", fn, NULL); if (pkgcheck[0] != ' ') { rc = checkPackages(pkgcheck); } pkgcheck = _free(pkgcheck); rstrcat(&pkglist, fn); rstrcat(&pkglist, " "); } fn = _free(fn); if (rc != RPMRC_OK) { pkglist = _free(pkglist); return rc; } } /* Now check the package set if enabled */ if (pkglist != NULL) { char *pkgcheck_set = rpmExpand("%{?_build_pkgcheck_set} ", pkglist, NULL); if (pkgcheck_set[0] != ' ') { /* run only if _build_pkgcheck_set is defined */ checkPackages(pkgcheck_set); } pkgcheck_set = _free(pkgcheck_set); pkglist = _free(pkglist); } return RPMRC_OK; }
static void specFini(void * _spec) /*@modifies _spec @*/ { Spec spec = _spec; struct ReadLevelEntry *rl; if (spec == NULL) return; /* XXX assert? */ spec->lbuf = _free(spec->lbuf); spec->sl = freeSl(spec->sl); spec->st = freeSt(spec->st); spec->prep = rpmiobFree(spec->prep); spec->build = rpmiobFree(spec->build); spec->install = rpmiobFree(spec->install); spec->check = rpmiobFree(spec->check); spec->clean = rpmiobFree(spec->clean); spec->foo = tagStoreFree(spec->foo, spec->nfoo); spec->nfoo = 0; spec->buildSubdir = _free(spec->buildSubdir); spec->rootURL = _free(spec->rootURL); spec->specFile = _free(spec->specFile); closeSpec(spec); while (spec->readStack) { rl = spec->readStack; /*@-dependenttrans@*/ spec->readStack = rl->next; /*@=dependenttrans@*/ rl->next = NULL; rl = _free(rl); } spec->sourceRpmName = _free(spec->sourceRpmName); spec->sourcePkgId = _free(spec->sourcePkgId); spec->sourceHeader = headerFree(spec->sourceHeader); if (spec->fi != NULL) { rpmfi fi = spec->fi; spec->fi = NULL; fi = rpmfiFree(fi); } if (!spec->recursing) { if (spec->BASpecs != NULL) while (spec->BACount--) { /*@-unqualifiedtrans@*/ spec->BASpecs[spec->BACount] = freeSpec(spec->BASpecs[spec->BACount]); /*@=unqualifiedtrans@*/ } /*@-compdef@*/ spec->BASpecs = _free(spec->BASpecs); /*@=compdef@*/ } spec->BANames = _free(spec->BANames); spec->passPhrase = _free(spec->passPhrase); spec->cookie = _free(spec->cookie); #ifdef WITH_LUA { rpmlua lua = NULL; /* global state */ rpmluaDelVar(lua, "patches"); rpmluaDelVar(lua, "sources"); } #endif spec->sources = freeSources(spec->sources); spec->dig = pgpDigFree(spec->dig); spec->packages = freePackages(spec->packages); }