/** * Print package size (debug purposes only) * @param fd package file handle * @param sigh signature header */ static void printSize(FD_t fd, Header sigh) { struct stat st; int fdno = Fileno(fd); size_t siglen = headerSizeof(sigh, HEADER_MAGIC_YES); size_t pad = (8 - (siglen % 8)) % 8; /* 8-byte pad */ struct rpmtd_s sizetag; rpm_loff_t datalen = 0; /* Print package component sizes. */ if (headerGet(sigh, RPMSIGTAG_LONGSIZE, &sizetag, HEADERGET_DEFAULT)) { rpm_loff_t *tsize = rpmtdGetUint64(&sizetag); datalen = (tsize) ? *tsize : 0; } else if (headerGet(sigh, RPMSIGTAG_SIZE, &sizetag, HEADERGET_DEFAULT)) { rpm_off_t *tsize = rpmtdGetUint32(&sizetag); datalen = (tsize) ? *tsize : 0; } rpmtdFreeData(&sizetag); rpmlog(RPMLOG_DEBUG, "Expected size: %12" PRIu64 \ " = lead(%d)+sigs(%zd)+pad(%zd)+data(%" PRIu64 ")\n", RPMLEAD_SIZE+siglen+pad+datalen, RPMLEAD_SIZE, siglen, pad, datalen); if (fstat(fdno, &st) == 0) { rpmlog(RPMLOG_DEBUG, " Actual size: %12" PRIu64 "\n", (rpm_loff_t) st.st_size); } }
/* * Convert single tag data item to python object of suitable type */ PyObject * rpmtd_ItemAsPyobj(rpmtd td) { PyObject *res = NULL; char *str = NULL; switch (rpmtdType(td)) { case RPM_STRING_TYPE: case RPM_I18NSTRING_TYPE: case RPM_STRING_ARRAY_TYPE: res = PyString_FromString(rpmtdGetString(td)); break; case RPM_INT64_TYPE: res = PyLong_FromLongLong(*rpmtdGetUint64(td)); break; case RPM_INT32_TYPE: res = PyInt_FromLong(*rpmtdGetUint32(td)); break; case RPM_INT16_TYPE: res = PyInt_FromLong(*rpmtdGetUint16(td)); break; case RPM_BIN_TYPE: str = rpmtdFormat(td, RPMTD_FORMAT_STRING, NULL); res = PyString_FromString(str); free(str); break; default: PyErr_SetString(PyExc_KeyError, "unhandled data type"); break; } return res; }
/** * Retrieve trigger type info. * @param h header * @retval td tag data container * @return 1 on success */ static int triggertypeTag(Header h, rpmtd td, headerGetFlags hgflags) { int i; char ** conds; struct rpmtd_s indices, flags, scripts; if (!headerGet(h, RPMTAG_TRIGGERINDEX, &indices, HEADERGET_MINMEM)) { return 0; } headerGet(h, RPMTAG_TRIGGERFLAGS, &flags, HEADERGET_MINMEM); headerGet(h, RPMTAG_TRIGGERSCRIPTS, &scripts, HEADERGET_MINMEM); td->flags = RPMTD_ALLOCED | RPMTD_PTR_ALLOCED; td->count = rpmtdCount(&scripts); td->data = conds = xmalloc(sizeof(*conds) * td->count); td->type = RPM_STRING_ARRAY_TYPE; while ((i = rpmtdNext(&scripts)) >= 0) { rpm_flag_t *flag; rpmtdInit(&indices); rpmtdInit(&flags); while (rpmtdNext(&indices) >= 0 && rpmtdNext(&flags) >= 0) { if (*rpmtdGetUint32(&indices) != i) continue; flag = rpmtdGetUint32(&flags); if (*flag & RPMSENSE_TRIGGERPREIN) conds[i] = xstrdup("prein"); else if (*flag & RPMSENSE_TRIGGERIN) conds[i] = xstrdup("in"); else if (*flag & RPMSENSE_TRIGGERUN) conds[i] = xstrdup("un"); else if (*flag & RPMSENSE_TRIGGERPOSTUN) conds[i] = xstrdup("postun"); else conds[i] = xstrdup(""); break; } } rpmtdFreeData(&indices); rpmtdFreeData(&flags); rpmtdFreeData(&scripts); return 1; }
uint32_t *rpmtdNextUint32(rpmtd td) { assert(td != NULL); uint32_t *res = NULL; if (rpmtdNext(td) >= 0) { res = rpmtdGetUint32(td); } return res; }
void rpmtriggersPrepPostUnTransFileTrigs(rpmts ts, rpmte te) { rpmdbMatchIterator mi; rpmdbIndexIterator ii; Header trigH; const void *key; size_t keylen; rpmfiles files; rpmds rpmdsTriggers; rpmds rpmdsTrigger; int tix = 0; ii = rpmdbIndexIteratorInit(rpmtsGetRdb(ts), RPMDBI_TRANSFILETRIGGERNAME); mi = rpmdbNewIterator(rpmtsGetRdb(ts), RPMDBI_PACKAGES); files = rpmteFiles(te); /* Iterate over file triggers in rpmdb */ while ((rpmdbIndexIteratorNext(ii, &key, &keylen)) == 0) { char pfx[keylen + 1]; memcpy(pfx, key, keylen); pfx[keylen] = '\0'; /* Check if file trigger matches any file in this te */ rpmfi fi = rpmfilesFindPrefix(files, pfx); if (rpmfiFC(fi) > 0) { /* If yes then store it */ rpmdbAppendIterator(mi, rpmdbIndexIteratorPkgOffsets(ii), rpmdbIndexIteratorNumPkgs(ii)); } rpmfiFree(fi); } rpmdbIndexIteratorFree(ii); if (rpmdbGetIteratorCount(mi)) { /* Filter triggers and save only trans postun triggers into ts */ while((trigH = rpmdbNextIterator(mi)) != NULL) { rpmdsTriggers = rpmdsNew(trigH, RPMTAG_TRANSFILETRIGGERNAME, 0); while ((rpmdsTrigger = rpmdsFilterTi(rpmdsTriggers, tix))) { if ((rpmdsNext(rpmdsTrigger) >= 0) && (rpmdsFlags(rpmdsTrigger) & RPMSENSE_TRIGGERPOSTUN)) { struct rpmtd_s priorities; headerGet(trigH, RPMTAG_TRANSFILETRIGGERPRIORITIES, &priorities, HEADERGET_MINMEM); rpmtdSetIndex(&priorities, tix); rpmtriggersAdd(ts->trigs2run, rpmdbGetIteratorOffset(mi), tix, *rpmtdGetUint32(&priorities)); } rpmdsFree(rpmdsTrigger); tix++; } rpmdsFree(rpmdsTriggers); } } rpmdbFreeIterator(mi); }
static int NEVRA(Header h, const char **np, uint32_t **ep, const char **vp, const char **rp, const char **ap) { if (np) *np = headerGetString(h, RPMTAG_NAME); if (vp) *vp = headerGetString(h, RPMTAG_VERSION); if (rp) *rp = headerGetString(h, RPMTAG_RELEASE); if (ap) *ap = headerGetString(h, RPMTAG_ARCH); if (ep) { struct rpmtd_s td; headerGet(h, RPMTAG_EPOCH, &td, HEADERGET_DEFAULT); *ep = rpmtdGetUint32(&td); } return 0; }
rpmRC runImmedFileTriggers(rpmts ts, rpmte te, rpmsenseFlags sense, rpmscriptTriggerModes tm, int priorityClass) { int nerrors = 0; int triggersCount, i; Header trigH = rpmteHeader(te); struct rpmtd_s priorities; rpmTagVal priorityTag; rpmtriggers triggers; if (tm == RPMSCRIPT_FILETRIGGER) { priorityTag = RPMTAG_FILETRIGGERPRIORITIES; } else { priorityTag = RPMTAG_TRANSFILETRIGGERPRIORITIES; } headerGet(trigH, priorityTag, &priorities, HEADERGET_MINMEM); triggersCount = rpmtdCount(&priorities); triggers = rpmtriggersCreate(triggersCount); for (i = 0; i < triggersCount; i++) { rpmtdSetIndex(&priorities, i); /* Offset is not important, all triggers are from the same package */ rpmtriggersAdd(triggers, 0, i, *rpmtdGetUint32(&priorities)); } /* Sort triggers by priority, offset, trigger index */ rpmtriggersSortAndUniq(triggers); for (i = 0; i < triggersCount; i++) { if (priorityClass == 1) { if (triggers->triggerInfo[i].priority < TRIGGER_PRIORITY_BOUND) continue; } else if (priorityClass == 2) { if (triggers->triggerInfo[i].priority >= TRIGGER_PRIORITY_BOUND) continue; } nerrors += runHandleTriggersInPkg(ts, te, trigH, sense, tm, 2, triggers->triggerInfo[i].tix); } rpmtriggersFree(triggers); headerFree(trigH); return (nerrors == 0) ? RPMRC_OK : RPMRC_FAIL; }
/** * Retrieve trigger info. * @param mode type of trigger (see tMode_e) * @param h header * @retval td tag data container * @param hgflags header get flags * @return 1 on success */ static int triggercondsTagFor(tMode mode, Header h, rpmtd td, headerGetFlags hgflags) { uint32_t * indices; int i, j; char ** conds; struct rpmtd_s nametd, indextd, flagtd, versiontd, scripttd; int hgeflags = HEADERGET_MINMEM; rpmTagVal triggername, triggerindex, triggerflags; rpmTagVal triggerversion, triggerscripts; switch (mode) { case NORMALTRIGGER: triggername = RPMTAG_TRIGGERNAME; triggerindex = RPMTAG_TRIGGERINDEX; triggerflags = RPMTAG_TRIGGERFLAGS; triggerversion = RPMTAG_TRIGGERVERSION; triggerscripts = RPMTAG_TRIGGERSCRIPTS; break; case FILETRIGGER: triggername = RPMTAG_FILETRIGGERNAME; triggerindex = RPMTAG_FILETRIGGERINDEX; triggerflags = RPMTAG_FILETRIGGERFLAGS; triggerversion = RPMTAG_FILETRIGGERVERSION; triggerscripts = RPMTAG_FILETRIGGERSCRIPTS; break; case TRANSFILETRIGGER: triggername = RPMTAG_TRANSFILETRIGGERNAME; triggerindex = RPMTAG_TRANSFILETRIGGERINDEX; triggerflags = RPMTAG_TRANSFILETRIGGERFLAGS; triggerversion = RPMTAG_TRANSFILETRIGGERVERSION; triggerscripts = RPMTAG_TRANSFILETRIGGERSCRIPTS; break; default: return 0; } if (!headerGet(h, triggername, &nametd, hgeflags)) { return 0; } headerGet(h, triggerindex, &indextd, hgeflags); headerGet(h, triggerflags, &flagtd, hgeflags); headerGet(h, triggerversion, &versiontd, hgeflags); headerGet(h, triggerscripts, &scripttd, hgeflags); td->type = RPM_STRING_ARRAY_TYPE; td->flags = RPMTD_ALLOCED | RPMTD_PTR_ALLOCED; td->data = conds = xmalloc(sizeof(*conds) * rpmtdCount(&scripttd)); td->count = rpmtdCount(&scripttd); indices = indextd.data; while ((i = rpmtdNext(&scripttd)) >= 0) { rpm_flag_t *flag; char *flagStr, *item; ARGV_t items = NULL; rpmtdInit(&nametd); rpmtdInit(&flagtd); rpmtdInit(&versiontd); while ((j = rpmtdNext(&nametd)) >= 0) { /* flag and version arrays match name array size always */ rpmtdNext(&flagtd); rpmtdNext(&versiontd); if (indices[j] != i) continue; flag = rpmtdGetUint32(&flagtd); if (flag && *flag & RPMSENSE_SENSEMASK) { flagStr = rpmtdFormat(&flagtd, RPMTD_FORMAT_DEPFLAGS, NULL); rasprintf(&item, "%s %s %s", rpmtdGetString(&nametd), flagStr, rpmtdGetString(&versiontd)); free(flagStr); } else { item = xstrdup(rpmtdGetString(&nametd)); } argvAdd(&items, item); free(item); } conds[i] = argvJoin(items, ", "); argvFree(items); } rpmtdFreeData(&nametd); rpmtdFreeData(&versiontd); rpmtdFreeData(&flagtd); rpmtdFreeData(&indextd); rpmtdFreeData(&scripttd); return 1; }
rpmfi rpmfiNew(const rpmts ts, Header h, rpmTag tagN, rpmfiFlags flags) { rpmfi fi = NULL; rpm_loff_t *asize = NULL; unsigned char * t; int isBuild, isSource; struct rpmtd_s fdigests, digalgo; struct rpmtd_s td; headerGetFlags scareFlags = (flags & RPMFI_KEEPHEADER) ? HEADERGET_MINMEM : HEADERGET_ALLOC; headerGetFlags defFlags = HEADERGET_ALLOC; fi = xcalloc(1, sizeof(*fi)); if (fi == NULL) /* XXX can't happen */ goto exit; fi->magic = RPMFIMAGIC; fi->i = -1; fi->fiflags = flags; fi->scareFlags = scareFlags; if (headerGet(h, RPMTAG_LONGARCHIVESIZE, &td, HEADERGET_EXT)) { asize = rpmtdGetUint64(&td); } /* 0 means unknown */ fi->archiveSize = asize ? *asize : 0; rpmtdFreeData(&td); /* Archive size is not set when this gets called from build */ isBuild = (asize == NULL); isSource = headerIsSource(h); if (isBuild) fi->fiflags |= RPMFI_ISBUILD; if (isSource) fi->fiflags |= RPMFI_ISSOURCE; _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); 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)) { pgpHashAlgo *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 (_rpmfi_debug < 0) fprintf(stderr, "*** fi %p\t[%d]\n", fi, (fi ? fi->fc : 0)); if (fi != NULL) { fi->h = (fi->fiflags & RPMFI_KEEPHEADER) ? headerLink(h) : NULL; } /* FIX: rpmfi null annotations */ return rpmfiLink(fi, __FUNCTION__); }
/* 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, fingerPrintCache fpc) { tsMembers tsmem = rpmtsMembers(ts); rpmte p; rpmfiles fi; rpmfs fs; int j; unsigned int fileNum; rpmdbMatchIterator mi; Header h, newheader; 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 *fpp = NULL; unsigned int installedPkg; int beingRemoved = 0; rpmfiles otherFi = NULL; rpmte *removedPkg = NULL; /* Is this package being removed? */ installedPkg = rpmdbGetIteratorOffset(mi); if (packageHashGetEntry(tsmem->removedPackages, installedPkg, &removedPkg, NULL, NULL)) { beingRemoved = 1; otherFi = rpmteFiles(removedPkg[0]); } h = headerLink(h); /* For packages being removed we can use its rpmfi to avoid all this */ if (!beingRemoved) { headerGet(h, RPMTAG_BASENAMES, &bnames, hgflags); headerGet(h, RPMTAG_DIRNAMES, &dnames, hgflags); headerGet(h, RPMTAG_DIRINDEXES, &dindexes, hgflags); headerGet(h, RPMTAG_FILESTATES, &ostates, hgflags); } /* loop over all interesting files in that package */ do { int fpIx; struct rpmffi_s * recs; int numRecs; const char * dirName; const char * baseName; /* lookup finger print for this file */ fileNum = rpmdbGetIteratorFileNum(mi); if (!beingRemoved) { rpmtdSetIndex(&bnames, fileNum); rpmtdSetIndex(&dindexes, fileNum); rpmtdSetIndex(&dnames, *rpmtdGetUint32(&dindexes)); rpmtdSetIndex(&ostates, fileNum); dirName = rpmtdGetString(&dnames); baseName = rpmtdGetString(&bnames); fpLookup(fpc, dirName, baseName, &fpp); fpIx = 0; } else { fpp = rpmfilesFps(otherFi); fpIx = fileNum; } /* search for files in the transaction with same finger print */ fpCacheGetByFp(fpc, fpp, fpIx, &recs, &numRecs); for (j = 0; j < numRecs; j++) { p = recs[j].p; fi = rpmteFiles(p); fs = rpmteGetFileStates(p); /* Determine the fate of each file. */ switch (rpmteType(p)) { case TR_ADDED: if (!otherFi) { /* XXX What to do if this fails? */ otherFi = rpmfilesNew(NULL, h, RPMTAG_BASENAMES, RPMFI_KEEPHEADER); } handleInstInstalledFile(ts, p, fi, recs[j].fileno, h, otherFi, fileNum, beingRemoved); break; case TR_REMOVED: if (!beingRemoved) { if (*rpmtdGetChar(&ostates) == RPMFILE_STATE_NORMAL) rpmfsSetAction(fs, recs[j].fileno, FA_SKIP); } break; } rpmfilesFree(fi); } newheader = rpmdbNextIterator(mi); } while (newheader==h); otherFi = rpmfilesFree(otherFi); if (!beingRemoved) { rpmtdFreeData(&ostates); rpmtdFreeData(&bnames); rpmtdFreeData(&dnames); rpmtdFreeData(&dindexes); free(fpp); } 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; }
/* 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); }
rpmRC rpmReadSignature(FD_t fd, Header * sighp, sigType sig_type, char ** msg) { char *buf = NULL; int32_t block[4]; int32_t il; int32_t dl; int32_t * ei = NULL; entryInfo pe; unsigned int nb, uc; struct indexEntry_s entry; unsigned char * dataStart; Header sigh = NULL; rpmRC rc = RPMRC_FAIL; /* assume failure */ int xx; int i; if (sighp) *sighp = NULL; if (sig_type != RPMSIGTYPE_HEADERSIG) goto exit; memset(block, 0, sizeof(block)); if ((xx = Freadall(fd, block, sizeof(block))) != sizeof(block)) { rasprintf(&buf, _("sigh size(%d): BAD, read returned %d"), (int)sizeof(block), xx); goto exit; } if (memcmp(block, rpm_header_magic, sizeof(rpm_header_magic))) { rasprintf(&buf, _("sigh magic: BAD")); goto exit; } il = ntohl(block[2]); if (il < 0 || il > 32) { rasprintf(&buf, _("sigh tags: BAD, no. of tags(%d) out of range"), il); goto exit; } dl = ntohl(block[3]); if (dl < 0 || dl > 8192) { rasprintf(&buf, _("sigh data: BAD, no. of bytes(%d) out of range"), dl); goto exit; } memset(&entry, 0, sizeof(entry)); nb = (il * sizeof(struct entryInfo_s)) + dl; uc = sizeof(il) + sizeof(dl) + nb; ei = xmalloc(uc); ei[0] = block[2]; ei[1] = block[3]; pe = (entryInfo) &ei[2]; dataStart = (unsigned char *) (pe + il); if ((xx = Freadall(fd, pe, nb)) != nb) { rasprintf(&buf, _("sigh blob(%d): BAD, read returned %d"), (int)nb, xx); goto exit; } /* Verify header immutable region if there is one */ xx = headerVerifyRegion(RPMTAG_HEADERSIGNATURES, &entry, il, dl, pe, dataStart, NULL, NULL, &buf); /* Not found means a legacy V3 package with no immutable region */ if (xx != RPMRC_OK && xx != RPMRC_NOTFOUND) goto exit; /* Sanity check signature tags */ for (i = 1; i < il; i++) { xx = headerVerifyInfo(1, dl, pe+i, &entry.info, 0); if (xx != -1) { rasprintf(&buf, _("sigh tag[%d]: BAD, tag %d type %d offset %d count %d"), i, entry.info.tag, entry.info.type, entry.info.offset, entry.info.count); goto exit; } } /* OK, blob looks sane, load the header. */ sigh = headerImport(ei, uc, 0); if (sigh == NULL) { rasprintf(&buf, _("sigh load: BAD")); goto exit; } ei = NULL; /* XXX will be freed with header */ { size_t sigSize = headerSizeof(sigh, HEADER_MAGIC_YES); size_t pad = (8 - (sigSize % 8)) % 8; /* 8-byte pad */ ssize_t trc; struct rpmtd_s sizetag; rpm_loff_t archSize = 0; /* Position at beginning of header. */ if (pad && (trc = Freadall(fd, block, pad)) != pad) { rasprintf(&buf, _("sigh pad(%zd): BAD, read %zd bytes"), pad, trc); goto exit; } /* Print package component sizes. */ if (headerGet(sigh, RPMSIGTAG_LONGSIZE, &sizetag, HEADERGET_DEFAULT)) { rpm_loff_t *tsize = rpmtdGetUint64(&sizetag); archSize = (tsize) ? *tsize : 0; } else if (headerGet(sigh, RPMSIGTAG_SIZE, &sizetag, HEADERGET_DEFAULT)) { rpm_off_t *tsize = rpmtdGetUint32(&sizetag); archSize = (tsize) ? *tsize : 0; } rpmtdFreeData(&sizetag); rc = printSize(fd, sigSize, pad, archSize); if (rc != RPMRC_OK) { rasprintf(&buf, _("sigh sigSize(%zd): BAD, fstat(2) failed"), sigSize); goto exit; } } exit: if (sighp && sigh && rc == RPMRC_OK) *sighp = headerLink(sigh); headerFree(sigh); free(ei); if (msg != NULL) { *msg = buf; } else { free(buf); } return rc; }
/** * Retrieve trigger type info. * @param mode type of trigger (see tMode_e) * @param h header * @retval td tag data container * @param hgflags header get flags * @return 1 on success */ static int triggertypeTagFor(tMode mode, Header h, rpmtd td, headerGetFlags hgflags) { int i; char ** conds; struct rpmtd_s indices, flags, scripts; rpmTagVal triggerindex, triggerflags, triggerscripts; switch (mode) { case NORMALTRIGGER: triggerindex = RPMTAG_TRIGGERINDEX; triggerflags = RPMTAG_TRIGGERFLAGS; triggerscripts = RPMTAG_TRIGGERSCRIPTS; break; case FILETRIGGER: triggerindex = RPMTAG_FILETRIGGERINDEX; triggerflags = RPMTAG_FILETRIGGERFLAGS; triggerscripts = RPMTAG_FILETRIGGERSCRIPTS; break; case TRANSFILETRIGGER: triggerindex = RPMTAG_TRANSFILETRIGGERINDEX; triggerflags = RPMTAG_TRANSFILETRIGGERFLAGS; triggerscripts = RPMTAG_TRANSFILETRIGGERSCRIPTS; break; default: return 0; } if (!headerGet(h, triggerindex, &indices, HEADERGET_MINMEM)) { return 0; } headerGet(h, triggerflags, &flags, HEADERGET_MINMEM); headerGet(h, triggerscripts, &scripts, HEADERGET_MINMEM); td->flags = RPMTD_ALLOCED | RPMTD_PTR_ALLOCED; td->count = rpmtdCount(&scripts); td->data = conds = xmalloc(sizeof(*conds) * td->count); td->type = RPM_STRING_ARRAY_TYPE; while ((i = rpmtdNext(&scripts)) >= 0) { rpm_flag_t *flag; rpmtdInit(&indices); rpmtdInit(&flags); while (rpmtdNext(&indices) >= 0 && rpmtdNext(&flags) >= 0) { if (*rpmtdGetUint32(&indices) != i) continue; flag = rpmtdGetUint32(&flags); if (*flag & RPMSENSE_TRIGGERPREIN) conds[i] = xstrdup("prein"); else if (*flag & RPMSENSE_TRIGGERIN) conds[i] = xstrdup("in"); else if (*flag & RPMSENSE_TRIGGERUN) conds[i] = xstrdup("un"); else if (*flag & RPMSENSE_TRIGGERPOSTUN) conds[i] = xstrdup("postun"); else conds[i] = xstrdup(""); break; } } rpmtdFreeData(&indices); rpmtdFreeData(&flags); rpmtdFreeData(&scripts); return 1; }
rpmRC runFileTriggers(rpmts ts, rpmte te, rpmsenseFlags sense, rpmscriptTriggerModes tm, int priorityClass) { int nerrors = 0, i; rpmdbIndexIterator ii; const void *key; char *pfx; size_t keylen; Header trigH; int (*matchFunc)(rpmts, rpmte, const char*, rpmsenseFlags sense); rpmTagVal priorityTag; rpmtriggers triggers = rpmtriggersCreate(10); /* Decide if we match triggers against files in te or in whole ts */ if (tm == RPMSCRIPT_FILETRIGGER) { matchFunc = matchFilesInPkg; priorityTag = RPMTAG_FILETRIGGERPRIORITIES; } else { matchFunc = matchFilesInTran; priorityTag = RPMTAG_TRANSFILETRIGGERPRIORITIES; } ii = rpmdbIndexIteratorInit(rpmtsGetRdb(ts), triggerDsTag(tm)); /* Loop over all file triggers in rpmdb */ while ((rpmdbIndexIteratorNext(ii, &key, &keylen)) == 0) { pfx = xmalloc(keylen + 1); memcpy(pfx, key, keylen); pfx[keylen] = '\0'; /* Check if file trigger is fired by any file in ts/te */ if (matchFunc(ts, te, pfx, sense)) { for (i = 0; i < rpmdbIndexIteratorNumPkgs(ii); i++) { struct rpmtd_s priorities; unsigned int priority; unsigned int offset = rpmdbIndexIteratorPkgOffset(ii, i); unsigned int tix = rpmdbIndexIteratorTagNum(ii, i); /* * Don't handle transaction triggers installed in current * transaction to avoid executing the same script two times. * These triggers are handled in runImmedFileTriggers(). */ if (tm == RPMSCRIPT_TRANSFILETRIGGER && (packageHashHasEntry(ts->members->removedPackages, offset) || packageHashHasEntry(ts->members->installedPackages, offset))) continue; /* Get priority of trigger from header */ trigH = rpmdbGetHeaderAt(rpmtsGetRdb(ts), offset); headerGet(trigH, priorityTag, &priorities, HEADERGET_MINMEM); rpmtdSetIndex(&priorities, tix); priority = *rpmtdGetUint32(&priorities); headerFree(trigH); /* Store file trigger in array */ rpmtriggersAdd(triggers, offset, tix, priority); } } free(pfx); } rpmdbIndexIteratorFree(ii); /* Sort triggers by priority, offset, trigger index */ rpmtriggersSortAndUniq(triggers); if (rpmChrootIn() != 0) { rpmtriggersFree(triggers); return RPMRC_FAIL; } /* Handle stored triggers */ for (i = 0; i < triggers->count; i++) { if (priorityClass == 1) { if (triggers->triggerInfo[i].priority < TRIGGER_PRIORITY_BOUND) continue; } else if (priorityClass == 2) { if (triggers->triggerInfo[i].priority >= TRIGGER_PRIORITY_BOUND) continue; } trigH = rpmdbGetHeaderAt(rpmtsGetRdb(ts), triggers->triggerInfo[i].hdrNum); if (tm == RPMSCRIPT_FILETRIGGER) nerrors += runHandleTriggersInPkg(ts, te, trigH, sense, tm, 0, triggers->triggerInfo[i].tix); else nerrors += runHandleTriggersInPkg(ts, te, trigH, sense, tm, 1, triggers->triggerInfo[i].tix); headerFree(trigH); } rpmtriggersFree(triggers); /* XXX an error here would require a full abort */ (void) rpmChrootOut(); return (nerrors == 0) ? RPMRC_OK : RPMRC_FAIL; }
rpmRC rpmReadSignature(FD_t fd, Header * sighp, sigType sig_type, char ** msg) { char *buf = NULL; int32_t block[4]; int32_t il; int32_t dl; int32_t * ei = NULL; entryInfo pe; unsigned int nb, uc; int32_t ril = 0; struct indexEntry_s entry; struct entryInfo_s info; unsigned char * dataStart; unsigned char * dataEnd = NULL; Header sigh = NULL; rpmRC rc = RPMRC_FAIL; /* assume failure */ int xx; int i; if (sighp) *sighp = NULL; if (sig_type != RPMSIGTYPE_HEADERSIG) goto exit; memset(block, 0, sizeof(block)); if ((xx = Fread(block, 1, sizeof(block), fd)) != sizeof(block)) { rasprintf(&buf, _("sigh size(%d): BAD, read returned %d\n"), (int)sizeof(block), xx); goto exit; } if (memcmp(block, rpm_header_magic, sizeof(rpm_header_magic))) { rasprintf(&buf, _("sigh magic: BAD\n")); goto exit; } il = ntohl(block[2]); if (il < 0 || il > 32) { rasprintf(&buf, _("sigh tags: BAD, no. of tags(%d) out of range\n"), il); goto exit; } dl = ntohl(block[3]); if (dl < 0 || dl > 8192) { rasprintf(&buf, _("sigh data: BAD, no. of bytes(%d) out of range\n"), dl); goto exit; } memset(&entry, 0, sizeof(entry)); memset(&info, 0, sizeof(info)); nb = (il * sizeof(struct entryInfo_s)) + dl; uc = sizeof(il) + sizeof(dl) + nb; ei = xmalloc(uc); ei[0] = block[2]; ei[1] = block[3]; pe = (entryInfo) &ei[2]; dataStart = (unsigned char *) (pe + il); if ((xx = Fread(pe, 1, nb, fd)) != nb) { rasprintf(&buf, _("sigh blob(%d): BAD, read returned %d\n"), (int)nb, xx); goto exit; } /* Check (and convert) the 1st tag element. */ xx = headerVerifyInfo(1, dl, pe, &entry.info, 0); if (xx != -1) { rasprintf(&buf, _("tag[%d]: BAD, tag %d type %d offset %d count %d\n"), 0, entry.info.tag, entry.info.type, entry.info.offset, entry.info.count); goto exit; } /* Is there an immutable header region tag? */ if (entry.info.tag == RPMTAG_HEADERSIGNATURES) { /* Is the region tag sane? */ if (!(entry.info.type == REGION_TAG_TYPE && entry.info.count == REGION_TAG_COUNT)) { rasprintf(&buf, _("region tag: BAD, tag %d type %d offset %d count %d\n"), entry.info.tag, entry.info.type, entry.info.offset, entry.info.count); goto exit; } /* Is the trailer within the data area? */ if (entry.info.offset + REGION_TAG_COUNT > dl) { rasprintf(&buf, _("region offset: BAD, tag %d type %d offset %d count %d\n"), entry.info.tag, entry.info.type, entry.info.offset, entry.info.count); goto exit; } /* Is there an immutable header region tag trailer? */ dataEnd = dataStart + entry.info.offset; (void) memcpy(&info, dataEnd, REGION_TAG_COUNT); /* XXX Really old packages have HEADER_IMAGE, not HEADER_SIGNATURES. */ if (info.tag == htonl(RPMTAG_HEADERIMAGE)) { rpmTagVal stag = htonl(RPMTAG_HEADERSIGNATURES); info.tag = stag; memcpy(dataEnd, &stag, sizeof(stag)); } dataEnd += REGION_TAG_COUNT; xx = headerVerifyInfo(1, il * sizeof(*pe), &info, &entry.info, 1); if (xx != -1 || !((entry.info.tag == RPMTAG_HEADERSIGNATURES || entry.info.tag == RPMTAG_HEADERIMAGE) && entry.info.type == REGION_TAG_TYPE && entry.info.count == REGION_TAG_COUNT)) { rasprintf(&buf, _("region trailer: BAD, tag %d type %d offset %d count %d\n"), entry.info.tag, entry.info.type, entry.info.offset, entry.info.count); goto exit; } memset(&info, 0, sizeof(info)); /* Is the no. of tags in the region less than the total no. of tags? */ ril = entry.info.offset/sizeof(*pe); if ((entry.info.offset % sizeof(*pe)) || ril > il) { rasprintf(&buf, _("region size: BAD, ril(%d) > il(%d)\n"), ril, il); goto exit; } } /* Sanity check signature tags */ memset(&info, 0, sizeof(info)); for (i = 1; i < il; i++) { xx = headerVerifyInfo(1, dl, pe+i, &entry.info, 0); if (xx != -1) { rasprintf(&buf, _("sigh tag[%d]: BAD, tag %d type %d offset %d count %d\n"), i, entry.info.tag, entry.info.type, entry.info.offset, entry.info.count); goto exit; } } /* OK, blob looks sane, load the header. */ sigh = headerImport(ei, uc, 0); if (sigh == NULL) { rasprintf(&buf, _("sigh load: BAD\n")); goto exit; } { size_t sigSize = headerSizeof(sigh, HEADER_MAGIC_YES); size_t pad = (8 - (sigSize % 8)) % 8; /* 8-byte pad */ ssize_t trc; struct rpmtd_s sizetag; rpm_loff_t archSize = 0; /* Position at beginning of header. */ if (pad && (trc = Fread(block, 1, pad, fd)) != pad) { rasprintf(&buf, _("sigh pad(%zd): BAD, read %zd bytes\n"), pad, trc); goto exit; } /* Print package component sizes. */ if (headerGet(sigh, RPMSIGTAG_LONGSIZE, &sizetag, HEADERGET_DEFAULT)) { rpm_loff_t *tsize = rpmtdGetUint64(&sizetag); archSize = (tsize) ? *tsize : 0; } else if (headerGet(sigh, RPMSIGTAG_SIZE, &sizetag, HEADERGET_DEFAULT)) { rpm_off_t *tsize = rpmtdGetUint32(&sizetag); archSize = (tsize) ? *tsize : 0; } rpmtdFreeData(&sizetag); rc = printSize(fd, sigSize, pad, archSize); if (rc != RPMRC_OK) { rasprintf(&buf, _("sigh sigSize(%zd): BAD, fstat(2) failed\n"), sigSize); goto exit; } } ei = NULL; /* XXX will be freed with header */ exit: if (sighp && sigh && rc == RPMRC_OK) *sighp = headerLink(sigh); headerFree(sigh); free(ei); if (msg != NULL) { *msg = buf; } else { free(buf); } return rc; }
static int rpmfiPopulate(rpmfi fi, Header h, rpmfiFlags flags) { headerGetFlags scareFlags = (flags & RPMFI_KEEPHEADER) ? HEADERGET_MINMEM : HEADERGET_ALLOC; headerGetFlags defFlags = HEADERGET_ALLOC; struct rpmtd_s fdigests, digalgo, td; unsigned char * t; /* 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); _hgfi(h, RPMTAG_LONGFILESIZES, &td, scareFlags, fi->lfsizes); } 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)) _hgfi(h, RPMTAG_FILECAPS, &td, defFlags, fi->fcaps); if (!(flags & RPMFI_NOFILELINKTOS)) fi->flinks = tag2pool(fi->pool, h, RPMTAG_FILELINKTOS); /* FILELANGS are only interesting when installing */ if ((headerGetInstance(h) == 0) && !(flags & RPMFI_NOFILELANGS)) fi->flangs = tag2pool(fi->pool, 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 = tag2pool(fi->pool, h, RPMTAG_FILEUSERNAME); if (!(flags & RPMFI_NOFILEGROUP)) fi->fgroup = tag2pool(fi->pool, h, RPMTAG_FILEGROUPNAME); /* TODO: validate and return a real error */ return 0; }