static int hdrContains(hdrObject *s, PyObject *pytag) { rpmTagVal tag; if (!tagNumFromPyObject(pytag, &tag)) return -1; return headerIsEntry(s->h, tag); }
static int hdrPutTag(Header h, rpmTagVal tag, PyObject *value) { rpmTagType type = rpmTagGetTagType(tag); rpmTagReturnType retype = rpmTagGetReturnType(tag); int rc = 0; /* XXX this isn't really right (i18n strings etc) but for now ... */ if (headerIsEntry(h, tag)) { PyErr_SetString(PyExc_TypeError, "tag already exists"); return rc; } /* validate all data before trying to insert */ if (!validData(tag, type, retype, value)) { PyErr_SetString(PyExc_TypeError, "invalid type for tag"); return 0; } if (retype == RPM_SCALAR_RETURN_TYPE) { rc = hdrAppendItem(h, tag, type, value); } else if (retype == RPM_ARRAY_RETURN_TYPE && PyList_Check(value)) { Py_ssize_t len = PyList_Size(value); for (Py_ssize_t i = 0; i < len; i++) { PyObject *item = PyList_GetItem(value, i); rc = hdrAppendItem(h, tag, type, item); } } else { PyErr_SetString(PyExc_RuntimeError, "cant happen, right?"); } return rc; }
int showVerifyPackage(QVA_t qva, rpmts ts, Header h) { int ec = 0; int rc; if (qva->qva_flags & VERIFY_DEPS) { int save_noise = _rpmds_unspecified_epoch_noise; if (rpmIsVerbose()) _rpmds_unspecified_epoch_noise = 1; if ((rc = verifyDependencies(qva, ts, h)) != 0) ec = rc; _rpmds_unspecified_epoch_noise = save_noise; } if (qva->qva_flags & VERIFY_FILES) { if ((rc = verifyHeader(qva, ts, h)) != 0) ec = rc; } if ((qva->qva_flags & VERIFY_SCRIPT) && headerIsEntry(h, RPMTAG_VERIFYSCRIPT)) { FD_t fdo = fdDup(STDOUT_FILENO); if ((rc = rpmVerifyScript(qva, ts, h, fdo)) != 0) ec = rc; if (fdo != NULL) rc = Fclose(fdo); } return ec; }
static int replaceSignature(Header sigh, sigTarget sigt1, sigTarget sigt2) { /* Grab a copy of the header so we can compare the result */ Header oldsigh = headerCopy(sigh); int rc = -1; /* Nuke all signature tags */ deleteSigs(sigh); /* * rpmGenSignature() internals parse the actual signing result and * adds appropriate tags for DSA/RSA. */ if (rpmGenSignature(sigh, sigt1, sigt2) == 0) { /* Lets see what we got and whether its the same signature as before */ rpmTagVal sigtag = headerIsEntry(sigh, RPMSIGTAG_DSA) ? RPMSIGTAG_DSA : RPMSIGTAG_RSA; rc = sameSignature(sigtag, sigh, oldsigh); } headerFree(oldsigh); return rc; }
static void fillOutMainPackage(Header h) /*@globals rpmGlobalMacroContext, h_errno, internalState @*/ /*@modifies h, rpmGlobalMacroContext, internalState @*/ { HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he)); struct optionalTag *ot; int xx; for (ot = optionalTags; ot->ot_mac != NULL; ot++) { const char * val; rpmTag tag; tag = ot->ot_tag; /* Generate arbitrary tag (if necessary). */ if (tag == 0xffffffff) { val = tagCanonicalize(ot->ot_mac + (sizeof("%{")-1)); tag = tagGenerate(val); val = _free(val); } if (headerIsEntry(h, tag)) continue; val = rpmExpand(ot->ot_mac, NULL); if (val && *val != '%') { he->tag = tag; he->t = RPM_STRING_TYPE; he->p.str = val; he->c = 1; xx = headerPut(h, he, 0); } val = _free(val); } }
static Header do_loadrpmhdr(const char *path, int vfmode, const char *pdir_name) { struct vfile *vf = NULL; tn_buf *nbuf; tn_buf buf[4096]; int n; Header h, ch = NULL; if ((vf = vfile_open_ul(path, VFT_GZIO, vfmode, pdir_name)) == NULL) return NULL; nbuf = n_buf_new(1024 * 64); while ((n = gzread(vf->vf_gzstream, buf, sizeof(buf))) > 0) n_buf_write(nbuf, buf, n); vfile_close(vf); h = headerLoad(n_buf_ptr(nbuf)); /* rpm's memleak */ if (h == NULL) { logn(LOGERR, "%s: load header failed", n_basenam(path)); } else if (headerIsEntry(h, RPMTAG_SOURCEPACKAGE)) { /* omit src.rpms */ h = NULL; } if (h) ch = headerCopy(h); n_buf_free(nbuf); return ch; }
int headerGetRawEntry(Header h, rpm_tag_t tag, rpm_tagtype_t * type, rpm_data_t * p, rpm_count_t * c) { if (p == NULL) return headerIsEntry(h, tag); return headerGetWrap(h, tag, type, p, c, HEADERGET_RAW); }
rpmScript rpmScriptFromTag(Header h, rpmTagVal scriptTag) { rpmScript script = NULL; rpmTagVal progTag = getProgTag(scriptTag); if (headerIsEntry(h, scriptTag) || headerIsEntry(h, progTag)) { struct rpmtd_s prog; script = rpmScriptNew(h, scriptTag, headerGetString(h, scriptTag), headerGetNumber(h, getFlagTag(scriptTag))); if (headerGet(h, progTag, &prog, (HEADERGET_ALLOC|HEADERGET_ARGV))) { script->args = prog.data; } } return script; }
static int checkSpec(rpmts ts, Header h) /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ /*@modifies ts, h, rpmGlobalMacroContext, fileSystem, internalState @*/ { int rc; if (!headerIsEntry(h, RPMTAG_REQUIRENAME) && !headerIsEntry(h, RPMTAG_CONFLICTNAME)) return 0; rc = rpmtsAddInstallElement(ts, h, NULL, 0, NULL); rc = rpmcliInstallProblems(ts, _("Failed build dependencies"), rpmtsCheck(ts)); /* XXX nuke the added package. */ rpmtsClean(ts); return rc; }
static int addPrefixes(Header h, rpmRelocation *relocations, int numRelocations) { struct rpmtd_s validRelocs; const char *validprefix; const char ** actualRelocations; int numActual = 0; headerGet(h, RPMTAG_PREFIXES, &validRelocs, HEADERGET_MINMEM); /* * If no relocations are specified (usually the case), then return the * original header. If there are prefixes, however, then INSTPREFIXES * should be added for RPM_INSTALL_PREFIX environ variables in scriptlets, * but, since relocateFileList() can be called more than once for * the same header, don't bother if already present. */ if (relocations == NULL || numRelocations == 0) { if (rpmtdCount(&validRelocs) > 0) { if (!headerIsEntry(h, RPMTAG_INSTPREFIXES)) { rpmtdSetTag(&validRelocs, RPMTAG_INSTPREFIXES); headerPut(h, &validRelocs, HEADERPUT_DEFAULT); } rpmtdFreeData(&validRelocs); } return 0; } actualRelocations = xmalloc(rpmtdCount(&validRelocs) * sizeof(*actualRelocations)); rpmtdInit(&validRelocs); while ((validprefix = rpmtdNextString(&validRelocs))) { int j; for (j = 0; j < numRelocations; j++) { if (relocations[j].oldPath == NULL || /* XXX can't happen */ !rstreq(validprefix, relocations[j].oldPath)) continue; /* On install, a relocate to NULL means skip the path. */ if (relocations[j].newPath) { actualRelocations[numActual] = relocations[j].newPath; numActual++; } break; } if (j == numRelocations) { actualRelocations[numActual] = validprefix; numActual++; } } rpmtdFreeData(&validRelocs); if (numActual) { headerPutStringArray(h, RPMTAG_INSTPREFIXES, actualRelocations, numActual); } free(actualRelocations); /* When any relocations are present there'll be more work to do */ return 1; }
/* make a header with _all_ the tags we need */ static PyObject * hdrFullFilelist(hdrObject * s) { rpmtd fileNames = rpmtdNew(); Header h = s->h; DEPRECATED_METHOD("obsolete method"); if (!headerIsEntry (h, RPMTAG_BASENAMES) || !headerIsEntry (h, RPMTAG_DIRNAMES) || !headerIsEntry (h, RPMTAG_DIRINDEXES)) headerConvert(h, HEADERCONV_COMPRESSFILELIST); if (headerGet(h, RPMTAG_FILENAMES, fileNames, HEADERGET_EXT)) { rpmtdSetTag(fileNames, RPMTAG_OLDFILENAMES); headerPut(h, fileNames, HEADERPUT_DEFAULT); rpmtdFreeData(fileNames); } rpmtdFree(fileNames); Py_RETURN_NONE; }
static int makeHDRDigest(Header sigh, const char * file, rpmTagVal sigTag) { Header h = NULL; FD_t fd = NULL; char * SHA1 = NULL; int ret = -1; /* assume failure. */ switch (sigTag) { case RPMSIGTAG_SHA1: fd = Fopen(file, "r.fdio"); if (fd == NULL || Ferror(fd)) goto exit; h = headerRead(fd, HEADER_MAGIC_YES); if (h == NULL) goto exit; if (headerIsEntry(h, RPMTAG_HEADERIMMUTABLE)) { DIGEST_CTX ctx; struct rpmtd_s utd; if (!headerGet(h, RPMTAG_HEADERIMMUTABLE, &utd, HEADERGET_DEFAULT) || utd.data == NULL) { rpmlog(RPMLOG_ERR, _("Immutable header region could not be read. " "Corrupted package?\n")); goto exit; } ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE); (void) rpmDigestUpdate(ctx, rpm_header_magic, sizeof(rpm_header_magic)); (void) rpmDigestUpdate(ctx, utd.data, utd.count); (void) rpmDigestFinal(ctx, (void **)&SHA1, NULL, 1); rpmtdFreeData(&utd); } else { rpmlog(RPMLOG_ERR, _("Cannot sign RPM v3 packages\n")); goto exit; } if (SHA1 == NULL) goto exit; if (!sighdrPut(sigh, RPMSIGTAG_SHA1, RPM_STRING_TYPE, SHA1, 1)) goto exit; ret = 0; break; default: break; } exit: free(SHA1); headerFree(h); if (fd != NULL) (void) Fclose(fd); return ret; }
/* * Up to rpm 3.0.4, packages implicitly provided their own name-version-release. * Retrofit an explicit "Provides: name = epoch:version-release. */ static void providePackageNVR(Header h) { const char *name = headerGetString(h, RPMTAG_NAME); char *pEVR = headerGetAsString(h, RPMTAG_EVR); rpmsenseFlags pFlags = RPMSENSE_EQUAL; int bingo = 1; struct rpmtd_s pnames; rpmds hds, nvrds; /* Generate provides for this package name-version-release. */ if (!(name && pEVR)) return; /* * Rpm prior to 3.0.3 does not have versioned provides. * If no provides at all are available, we can just add. */ if (!headerGet(h, RPMTAG_PROVIDENAME, &pnames, HEADERGET_MINMEM)) { goto exit; } /* * Otherwise, fill in entries on legacy packages. */ if (!headerIsEntry(h, RPMTAG_PROVIDEVERSION)) { while (rpmtdNext(&pnames) >= 0) { rpmsenseFlags fdummy = RPMSENSE_ANY; headerPutString(h, RPMTAG_PROVIDEVERSION, ""); headerPutUint32(h, RPMTAG_PROVIDEFLAGS, &fdummy, 1); } goto exit; } /* see if we already have this provide */ hds = rpmdsNew(h, RPMTAG_PROVIDENAME, 0); nvrds = rpmdsSingle(RPMTAG_PROVIDENAME, name, pEVR, pFlags); if (rpmdsFind(hds, nvrds) >= 0) { bingo = 0; } rpmdsFree(hds); rpmdsFree(nvrds); exit: if (bingo) { headerPutString(h, RPMTAG_PROVIDENAME, name); headerPutString(h, RPMTAG_PROVIDEVERSION, pEVR); headerPutUint32(h, RPMTAG_PROVIDEFLAGS, &pFlags, 1); } rpmtdFreeData(&pnames); free(pEVR); }
gboolean rpmostree_script_txn_validate (DnfPackage *package, Header hdr, GHashTable *override_ignored_scripts, GCancellable *cancellable, GError **error) { gboolean ret = FALSE; guint i; for (i = 0; i < G_N_ELEMENTS (unsupported_scripts); i++) { const char *desc = unsupported_scripts[i].desc; rpmTagVal tagval = unsupported_scripts[i].tag; rpmTagVal progtagval = unsupported_scripts[i].progtag; RpmOstreeScriptAction action; if (!(headerIsEntry (hdr, tagval) || headerIsEntry (hdr, progtagval))) continue; action = lookup_script_action (package, override_ignored_scripts, desc); switch (action) { case RPMOSTREE_SCRIPT_ACTION_DEFAULT: { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Package '%s' has (currently) unsupported script of type '%s'", dnf_package_get_name (package), desc); goto out; } case RPMOSTREE_SCRIPT_ACTION_IGNORE: continue; } } ret = TRUE; out: return ret; }
static void initSourceHeader(rpmSpec spec) { Package sourcePkg = spec->sourcePackage; struct Source *srcPtr; if (headerIsEntry(sourcePkg->header, RPMTAG_NAME)) return; /* Only specific tags are added to the source package header */ headerCopyTags(spec->packages->header, sourcePkg->header, sourceTags); /* Add the build restrictions */ for (int i=0; i<PACKAGE_NUM_DEPS; i++) { rpmdsPutToHeader(sourcePkg->dependencies[i], sourcePkg->header); } { HeaderIterator hi = headerInitIterator(spec->buildRestrictions); struct rpmtd_s td; while (headerNext(hi, &td)) { if (rpmtdCount(&td) > 0) { (void) headerPut(sourcePkg->header, &td, HEADERPUT_DEFAULT); } rpmtdFreeData(&td); } headerFreeIterator(hi); } if (spec->BANames && spec->BACount > 0) { headerPutStringArray(sourcePkg->header, RPMTAG_BUILDARCHS, spec->BANames, spec->BACount); } /* Add tags for sources and patches */ for (srcPtr = spec->sources; srcPtr != NULL; srcPtr = srcPtr->next) { if (srcPtr->flags & RPMBUILD_ISSOURCE) { headerPutString(sourcePkg->header, RPMTAG_SOURCE, srcPtr->source); if (srcPtr->flags & RPMBUILD_ISNO) { headerPutUint32(sourcePkg->header, RPMTAG_NOSOURCE, &srcPtr->num, 1); } } if (srcPtr->flags & RPMBUILD_ISPATCH) { headerPutString(sourcePkg->header, RPMTAG_PATCH, srcPtr->source); if (srcPtr->flags & RPMBUILD_ISNO) { headerPutUint32(sourcePkg->header, RPMTAG_NOPATCH, &srcPtr->num, 1); } } } }
static void fillOutMainPackage(Header h) { const struct optionalTag *ot; for (ot = optionalTags; ot->ot_mac != NULL; ot++) { if (!headerIsEntry(h, ot->ot_tag)) { char *val = rpmExpand(ot->ot_mac, NULL); if (val && *val != '%') { headerPutString(h, ot->ot_tag, val); } free(val); } } }
/** * Check that required tags are present in header. * @param h header * @param NVR package name-version-release * @return RPMRC_OK if OK */ static int checkForRequired(Header h, const char * NVR) { int res = RPMRC_OK; const rpmTagVal * p; for (p = requiredTags; *p != 0; p++) { if (!headerIsEntry(h, *p)) { rpmlog(RPMLOG_ERR, _("%s field must be present in package: %s\n"), rpmTagGetName(*p), NVR); res = RPMRC_FAIL; } } return res; }
/** * Check that required tags are present in header. * @param h header * @param NVR package name-version-release * @return RPMRC_OK if OK */ static rpmRC checkForRequired(Header h, const char * NVR) /*@*/ { rpmTag * p; rpmRC rc = RPMRC_OK; for (p = requiredTags; *p != 0; p++) { if (!headerIsEntry(h, *p)) { rpmlog(RPMLOG_ERR, _("%s field must be present in package: %s\n"), tagName(*p), NVR); rc = RPMRC_FAIL; } } return rc; }
static void expandFilelist(Header h) { struct rpmtd_s filenames; if (!headerIsEntry(h, RPMTAG_OLDFILENAMES)) { (void) headerGet(h, RPMTAG_FILENAMES, &filenames, HEADERGET_EXT); if (rpmtdCount(&filenames) < 1) return; rpmtdSetTag(&filenames, RPMTAG_OLDFILENAMES); headerPut(h, &filenames, HEADERPUT_DEFAULT); rpmtdFreeData(&filenames); } (void) headerDel(h, RPMTAG_DIRNAMES); (void) headerDel(h, RPMTAG_BASENAMES); (void) headerDel(h, RPMTAG_DIRINDEXES); }
/** * Return exit code from running verify script from header. * @param ts transaction set * @param h header * @return 0 on success */ static int rpmVerifyScript(rpmts ts, Header h) { int rc = 0; if (headerIsEntry(h, RPMTAG_VERIFYSCRIPT)) { /* fake up a erasure transaction element */ rpmte p = rpmteNew(ts, h, TR_REMOVED, NULL, NULL); rpmteSetHeader(p, h); rc = (rpmpsmRun(ts, p, PKG_VERIFY) != RPMRC_OK); /* clean up our fake transaction bits */ rpmteFree(p); } return rc; }
Header headerRegenSigHeader(const Header h, int noArchiveSize) { Header sigh = rpmNewSignature(); HeaderIterator hi; struct rpmtd_s td; for (hi = headerInitIterator(h); headerNext(hi, &td); rpmtdFreeData(&td)) { switch (td.tag) { /* XXX Translate legacy signature tag values. */ case RPMTAG_SIGSIZE: td.tag = RPMSIGTAG_SIZE; break; case RPMTAG_SIGPGP: td.tag = RPMSIGTAG_PGP; break; case RPMTAG_SIGMD5: td.tag = RPMSIGTAG_MD5; break; case RPMTAG_SIGGPG: td.tag = RPMSIGTAG_GPG; break; case RPMTAG_SIGPGP5: td.tag = RPMSIGTAG_PGP5; break; case RPMTAG_ARCHIVESIZE: /* XXX rpm-4.1 and later has archive size in signature header. */ if (noArchiveSize) continue; td.tag = RPMSIGTAG_PAYLOADSIZE; break; case RPMTAG_SHA1HEADER: case RPMTAG_DSAHEADER: case RPMTAG_RSAHEADER: default: if (!(td.tag >= HEADER_SIGBASE && td.tag < HEADER_TAGBASE)) continue; break; } if (td.data == NULL) continue; /* XXX can't happen */ if (!headerIsEntry(sigh, td.tag)) (void) headerPut(sigh, &td, HEADERPUT_DEFAULT); } hi = headerFreeIterator(hi); return sigh; }
void headerCopyTags(Header headerFrom, Header headerTo, const rpmTag * tagstocopy) { const rpmTag * p; struct rpmtd_s td; if (headerFrom == headerTo) return; for (p = tagstocopy; *p != 0; p++) { if (headerIsEntry(headerTo, *p)) continue; if (!headerGet(headerFrom, *p, &td, HEADERGET_MINMEM)) continue; (void) headerPut(headerTo, &td, HEADERPUT_DEFAULT); rpmtdFreeData(&td); } }
/** * @todo If the GPG key was known available, the md5 digest could be skipped. */ static int readFile(FD_t fd, const char * fn, rpmDigestBundle plbundle, rpmDigestBundle hdrbundle) { unsigned char buf[4*BUFSIZ]; ssize_t count; int rc = 1; Header h = NULL; char *msg = NULL; /* Read the header from the package. */ if (rpmReadHeader(NULL, fd, &h, &msg) != RPMRC_OK) { rpmlog(RPMLOG_ERR, _("%s: headerRead failed: %s\n"), fn, msg); goto exit; } if (headerIsEntry(h, RPMTAG_HEADERIMMUTABLE)) { struct rpmtd_s utd; if (!headerGet(h, RPMTAG_HEADERIMMUTABLE, &utd, HEADERGET_DEFAULT)){ rpmlog(RPMLOG_ERR, _("%s: Immutable header region could not be read. " "Corrupted package?\n"), fn); goto exit; } rpmDigestBundleUpdate(hdrbundle, rpm_header_magic, sizeof(rpm_header_magic)); rpmDigestBundleUpdate(hdrbundle, utd.data, utd.count); rpmtdFreeData(&utd); } /* Read the payload from the package. */ while ((count = Fread(buf, sizeof(buf[0]), sizeof(buf), fd)) > 0) {} if (count < 0) { rpmlog(RPMLOG_ERR, _("%s: Fread failed: %s\n"), fn, Fstrerror(fd)); goto exit; } rc = 0; exit: free(msg); headerFree(h); return rc; }
static sepol *sepolNew(rpmte te) { sepol *head = NULL; sepol *ret = NULL; sepolAction action; Header h; struct rpmtd_s policies, names, types, typesidx, flags; int i, j; int count; rpmtdReset(&policies); rpmtdReset(&names); rpmtdReset(&types); rpmtdReset(&typesidx); rpmtdReset(&flags); h = rpmteHeader(te); if (!h) { goto exit; } if (!headerIsEntry(h, RPMTAG_POLICIES)) { goto exit; } if (!headerGet(h, RPMTAG_POLICIES, &policies, HEADERGET_MINMEM)) { goto exit; } count = rpmtdCount(&policies); if (count <= 0) { goto exit; } if (!headerGet(h, RPMTAG_POLICYNAMES, &names, HEADERGET_MINMEM) || rpmtdCount(&names) != count) { goto exit; } if (!headerGet(h, RPMTAG_POLICYFLAGS, &flags, HEADERGET_MINMEM) || rpmtdCount(&flags) != count) { goto exit; } if (!headerGet(h, RPMTAG_POLICYTYPES, &types, HEADERGET_MINMEM)) { goto exit; } if (!headerGet(h, RPMTAG_POLICYTYPESINDEXES, &typesidx, HEADERGET_MINMEM) || rpmtdCount(&types) != rpmtdCount(&typesidx)) { goto exit; } action = (rpmteType(te) == TR_ADDED) ? SEPOL_ACTION_INSTALL : SEPOL_ACTION_REMOVE; for (i = 0; i < count; i++) { sepol *pol = xcalloc(1, sizeof(*pol)); pol->next = head; head = pol; pol->data = xstrdup(rpmtdNextString(&policies)); pol->name = xstrdup(rpmtdNextString(&names)); pol->flags = *rpmtdNextUint32(&flags); pol->action = action; for (j = 0; j < rpmtdCount(&types); j++) { uint32_t index = ((uint32_t *) typesidx.data)[j]; if (index < 0 || index >= count) { goto exit; } if (index != i) { continue; } argvAdd(&pol->types, rpmtdNextString(&types)); } argvSort(pol->types, NULL); } ret = head; exit: headerFree(h); rpmtdFreeData(&policies); rpmtdFreeData(&names); rpmtdFreeData(&types); rpmtdFreeData(&typesidx); rpmtdFreeData(&flags); if (!ret) { sepolFree(head); } return ret; }
static rpmRC writeModuleToHeader(ModuleRec mod, Package pkg) { rpmRC rc = RPMRC_FAIL; ARGV_t av; uint32_t count; struct rpmtd_s policies; struct rpmtd_s policynames; struct rpmtd_s policyflags; struct rpmtd_s policytypes; struct rpmtd_s policytypesidx; rpmtdReset(&policies); rpmtdReset(&policynames); rpmtdReset(&policyflags); rpmtdReset(&policytypes); rpmtdReset(&policytypesidx); if (!mod || !pkg) { goto exit; } /* check for duplicates */ if (headerIsEntry(pkg->header, RPMTAG_POLICYNAMES)) { int typeCount; const char *name; char *type; int i; int idx; headerGet(pkg->header, RPMTAG_POLICYNAMES, &policynames, HEADERGET_MINMEM); headerGet(pkg->header, RPMTAG_POLICYFLAGS, &policyflags, HEADERGET_ARGV | HEADERGET_MINMEM); headerGet(pkg->header, RPMTAG_POLICYTYPES, &policytypes, HEADERGET_ARGV | HEADERGET_MINMEM); headerGet(pkg->header, RPMTAG_POLICYTYPESINDEXES, &policytypesidx, HEADERGET_ARGV | HEADERGET_MINMEM); typeCount = rpmtdCount(&policytypes); while ((name = rpmtdNextString(&policynames))) { int overlappingtypes = 0; idx = rpmtdGetIndex(&policynames); for (i = 0; i < typeCount; i++) { if (((int *) policytypesidx.data)[i] != idx) { continue; } type = ((char **) policytypes.data)[i]; if (rstreq(type, RPMPOL_TYPE_DEFAULT) || argvSearch(mod->types, type, NULL) || argvSearch(mod->types, RPMPOL_TYPE_DEFAULT, NULL)) { overlappingtypes = 1; break; } } if (!overlappingtypes) { continue; } if (rstreq(mod->name, name)) { rpmlog(RPMLOG_ERR, _("Policy module '%s' duplicated with overlapping types\n"), name); goto exit; } if ((mod->flags && RPMPOL_FLAG_BASE) && (((int *) policyflags.data)[idx] & RPMPOL_FLAG_BASE)) { rpmlog(RPMLOG_ERR, _("Base modules '%s' and '%s' have overlapping types\n"), mod->name, name); goto exit; } } } if (headerIsEntry(pkg->header, RPMTAG_POLICIES)) { if (!headerGet(pkg->header, RPMTAG_POLICIES, &policies, HEADERGET_MINMEM)) { rpmlog(RPMLOG_ERR, _("Failed to get policies from header\n")); goto exit; } count = rpmtdCount(&policies); } else { count = 0; } /* save everything to the header */ headerPutString(pkg->header, RPMTAG_POLICIES, mod->data); headerPutString(pkg->header, RPMTAG_POLICYNAMES, mod->name); headerPutUint32(pkg->header, RPMTAG_POLICYFLAGS, &mod->flags, 1); for (av = mod->types; av && *av; av++) { headerPutString(pkg->header, RPMTAG_POLICYTYPES, *av); headerPutUint32(pkg->header, RPMTAG_POLICYTYPESINDEXES, &count, 1); } rc = RPMRC_OK; exit: rpmtdFreeData(&policies); rpmtdFreeData(&policynames); rpmtdFreeData(&policyflags); rpmtdFreeData(&policytypes); rpmtdFreeData(&policytypesidx); return rc; }
/** \ingroup rpmcli * Create/modify elements in signature header. * @param rpm path to package * @param deleting adding or deleting signature? * @param signfiles sign files if non-zero * @return 0 on success, -1 on error */ static int rpmSign(const char *rpm, int deleting, int signfiles) { FD_t fd = NULL; FD_t ofd = NULL; char *trpm = NULL; Header sigh = NULL; Header h = NULL; char *msg = NULL; int res = -1; /* assume failure */ rpmRC rc; struct rpmtd_s utd; off_t headerStart; off_t sigStart; struct sigTarget_s sigt_v3; struct sigTarget_s sigt_v4; unsigned int origSigSize; int insSig = 0; fprintf(stdout, "%s:\n", rpm); if (manageFile(&fd, rpm, O_RDWR)) goto exit; if ((rc = rpmLeadRead(fd, &msg)) != RPMRC_OK) { rpmlog(RPMLOG_ERR, "%s: %s\n", rpm, msg); goto exit; } sigStart = Ftell(fd); rc = rpmReadSignature(fd, &sigh, &msg); if (rc != RPMRC_OK) { rpmlog(RPMLOG_ERR, _("%s: rpmReadSignature failed: %s"), rpm, (msg && *msg ? msg : "\n")); goto exit; } headerStart = Ftell(fd); if (rpmReadHeader(NULL, fd, &h, &msg) != RPMRC_OK) { rpmlog(RPMLOG_ERR, _("%s: headerRead failed: %s\n"), rpm, msg); goto exit; } if (!headerIsEntry(h, RPMTAG_HEADERIMMUTABLE)) { rpmlog(RPMLOG_ERR, _("Cannot sign RPM v3 packages\n")); goto exit; } unloadImmutableRegion(&sigh, RPMTAG_HEADERSIGNATURES); origSigSize = headerSizeof(sigh, HEADER_MAGIC_YES); if (signfiles) { if (includeFileSignatures(&sigh, &h)) goto exit; } if (deleting) { /* Nuke all the signature tags. */ deleteSigs(sigh); } else { /* Signature target containing header + payload */ sigt_v3.fd = fd; sigt_v3.start = headerStart; sigt_v3.fileName = rpm; sigt_v3.size = fdSize(fd) - headerStart; /* Signature target containing only header */ sigt_v4 = sigt_v3; sigt_v4.size = headerSizeof(h, HEADER_MAGIC_YES); res = replaceSignature(sigh, &sigt_v3, &sigt_v4); if (res != 0) { if (res == 1) { rpmlog(RPMLOG_WARNING, _("%s already contains identical signature, skipping\n"), rpm); /* Identical signature is not an error */ res = 0; } goto exit; } res = -1; } /* Try to make new signature smaller to have size of original signature */ rpmtdReset(&utd); if (headerGet(sigh, RPMSIGTAG_RESERVEDSPACE, &utd, HEADERGET_MINMEM)) { int diff; int count; char *reservedSpace = NULL; count = utd.count; diff = headerSizeof(sigh, HEADER_MAGIC_YES) - origSigSize; if (diff < count) { reservedSpace = xcalloc(count - diff, sizeof(char)); headerDel(sigh, RPMSIGTAG_RESERVEDSPACE); rpmtdReset(&utd); utd.tag = RPMSIGTAG_RESERVEDSPACE; utd.count = count - diff; utd.type = RPM_BIN_TYPE; utd.data = reservedSpace; headerPut(sigh, &utd, HEADERPUT_DEFAULT); free(reservedSpace); insSig = 1; } } /* Reallocate the signature into one contiguous region. */ sigh = headerReload(sigh, RPMTAG_HEADERSIGNATURES); if (sigh == NULL) /* XXX can't happen */ goto exit; if (insSig) { /* Insert new signature into original rpm */ if (Fseek(fd, sigStart, SEEK_SET) < 0) { rpmlog(RPMLOG_ERR, _("Could not seek in file %s: %s\n"), rpm, Fstrerror(fd)); goto exit; } if (rpmWriteSignature(fd, sigh)) { rpmlog(RPMLOG_ERR, _("%s: rpmWriteSignature failed: %s\n"), rpm, Fstrerror(fd)); goto exit; } res = 0; } else { /* Replace orignal rpm with new rpm containing new signature */ rasprintf(&trpm, "%s.XXXXXX", rpm); ofd = rpmMkTemp(trpm); if (ofd == NULL || Ferror(ofd)) { rpmlog(RPMLOG_ERR, _("rpmMkTemp failed\n")); goto exit; } /* Write the lead/signature of the output rpm */ rc = rpmLeadWrite(ofd, h); if (rc != RPMRC_OK) { rpmlog(RPMLOG_ERR, _("%s: writeLead failed: %s\n"), trpm, Fstrerror(ofd)); goto exit; } if (rpmWriteSignature(ofd, sigh)) { rpmlog(RPMLOG_ERR, _("%s: rpmWriteSignature failed: %s\n"), trpm, Fstrerror(ofd)); goto exit; } if (Fseek(fd, headerStart, SEEK_SET) < 0) { rpmlog(RPMLOG_ERR, _("Could not seek in file %s: %s\n"), rpm, Fstrerror(fd)); goto exit; } /* Append the header and archive from the temp file */ if (copyFile(&fd, rpm, &ofd, trpm) == 0) { struct stat st; /* Move final target into place, restore file permissions. */ if (stat(rpm, &st) == 0 && unlink(rpm) == 0 && rename(trpm, rpm) == 0 && chmod(rpm, st.st_mode) == 0) { res = 0; } else { rpmlog(RPMLOG_ERR, _("replacing %s failed: %s\n"), rpm, strerror(errno)); } } } exit: if (fd) (void) closeFile(&fd); if (ofd) (void) closeFile(&ofd); headerFree(sigh); headerFree(h); free(msg); /* Clean up intermediate target */ if (trpm) { (void) unlink(trpm); free(trpm); } return res; }
static rpmSpec parseSpec(const char *specFile, rpmSpecFlags flags, const char *buildRoot, int recursing) { int parsePart = PART_PREAMBLE; int initialPackage = 1; rpmSpec spec; /* Set up a new Spec structure with no packages. */ spec = newSpec(); spec->specFile = rpmGetPath(specFile, NULL); pushOFI(spec, spec->specFile); /* If buildRoot not specified, use default %{buildroot} */ if (buildRoot) { spec->buildRoot = xstrdup(buildRoot); } else { spec->buildRoot = rpmGetPath("%{?buildroot:%{buildroot}}", NULL); } addMacro(NULL, "_docdir", NULL, "%{_defaultdocdir}", RMIL_SPEC); addMacro(NULL, "_licensedir", NULL, "%{_defaultlicensedir}", RMIL_SPEC); spec->recursing = recursing; spec->flags = flags; /* All the parse*() functions expect to have a line pre-read */ /* in the spec's line buffer. Except for parsePreamble(), */ /* which handles the initial entry into a spec file. */ while (parsePart != PART_NONE) { int goterror = 0; switch (parsePart) { case PART_ERROR: /* fallthrough */ default: goterror = 1; break; case PART_PREAMBLE: parsePart = parsePreamble(spec, initialPackage); initialPackage = 0; break; case PART_PREP: parsePart = parsePrep(spec); break; case PART_BUILD: case PART_INSTALL: case PART_CHECK: case PART_CLEAN: parsePart = parseBuildInstallClean(spec, parsePart); break; case PART_CHANGELOG: parsePart = parseChangelog(spec); break; case PART_DESCRIPTION: parsePart = parseDescription(spec); break; case PART_PRE: case PART_POST: case PART_PREUN: case PART_POSTUN: case PART_PRETRANS: case PART_POSTTRANS: case PART_VERIFYSCRIPT: case PART_TRIGGERPREIN: case PART_TRIGGERIN: case PART_TRIGGERUN: case PART_TRIGGERPOSTUN: case PART_FILETRIGGERIN: case PART_FILETRIGGERUN: case PART_FILETRIGGERPOSTUN: case PART_TRANSFILETRIGGERIN: case PART_TRANSFILETRIGGERUN: case PART_TRANSFILETRIGGERPOSTUN: parsePart = parseScript(spec, parsePart); break; case PART_FILES: parsePart = parseFiles(spec); break; case PART_POLICIES: parsePart = parsePolicies(spec); break; case PART_NONE: /* XXX avoid gcc whining */ case PART_LAST: case PART_BUILDARCHITECTURES: break; } if (goterror || parsePart >= PART_LAST) { goto errxit; } if (parsePart == PART_BUILDARCHITECTURES) { int index; int x; closeSpec(spec); spec->BASpecs = xcalloc(spec->BACount, sizeof(*spec->BASpecs)); index = 0; if (spec->BANames != NULL) for (x = 0; x < spec->BACount; x++) { /* Skip if not arch is not compatible. */ if (!rpmMachineScore(RPM_MACHTABLE_BUILDARCH, spec->BANames[x])) continue; addMacro(NULL, "_target_cpu", NULL, spec->BANames[x], RMIL_RPMRC); spec->BASpecs[index] = parseSpec(specFile, flags, buildRoot, 1); if (spec->BASpecs[index] == NULL) { spec->BACount = index; goto errxit; } delMacro(NULL, "_target_cpu"); index++; } spec->BACount = index; if (! index) { rpmlog(RPMLOG_ERR, _("No compatible architectures found for build\n")); goto errxit; } /* * Return the 1st child's fully parsed Spec structure. * The restart of the parse when encountering BuildArch * causes problems for "rpm -q --specfile". This is * still a hack because there may be more than 1 arch * specified (unlikely but possible.) There's also the * further problem that the macro context, particularly * %{_target_cpu}, disagrees with the info in the header. */ if (spec->BACount >= 1) { rpmSpec nspec = spec->BASpecs[0]; spec->BASpecs = _free(spec->BASpecs); rpmSpecFree(spec); spec = nspec; } goto exit; } } if (spec->clean == NULL) { char *body = rpmExpand("%{?buildroot: %{__rm} -rf %{buildroot}}", NULL); spec->clean = newStringBuf(); appendLineStringBuf(spec->clean, body); free(body); } /* Check for description in each package */ for (Package pkg = spec->packages; pkg != NULL; pkg = pkg->next) { if (!headerIsEntry(pkg->header, RPMTAG_DESCRIPTION)) { rpmlog(RPMLOG_ERR, _("Package has no %%description: %s\n"), headerGetString(pkg->header, RPMTAG_NAME)); goto errxit; } } /* Add arch, os and platform, self-provides etc for each package */ addTargets(spec->packages); /* Check for encoding in each package unless disabled */ if (!(spec->flags & RPMSPEC_NOUTF8)) { int badenc = 0; for (Package pkg = spec->packages; pkg != NULL; pkg = pkg->next) { if (checkForEncoding(pkg->header, 0) != RPMRC_OK) { badenc = 1; } } if (badenc) goto errxit; } closeSpec(spec); exit: /* Assemble source header from parsed components */ initSourceHeader(spec); return spec; errxit: rpmSpecFree(spec); return NULL; }
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__); }
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; }
int parseScript(rpmSpec spec, int parsePart) { /* There are a few options to scripts: */ /* <pkg> */ /* -n <pkg> */ /* -p <sh> */ /* -p "<sh> <args>..." */ /* -f <file> */ const char *p; const char **progArgv = NULL; int progArgc; const char *partname = NULL; rpmTagVal reqtag = 0; rpmTagVal tag = 0; rpmsenseFlags tagflags = 0; rpmTagVal progtag = 0; rpmTagVal flagtag = 0; rpmscriptFlags scriptFlags = 0; int flag = PART_SUBNAME; Package pkg; StringBuf sb = NULL; int nextPart; int index; char * reqargs = NULL; int res = PART_ERROR; /* assume failure */ int rc, argc; int arg; const char **argv = NULL; poptContext optCon = NULL; const char *name = NULL; const char *prog = "/bin/sh"; const char *file = NULL; struct poptOption optionsTable[] = { { NULL, 'p', POPT_ARG_STRING, &prog, 'p', NULL, NULL}, { NULL, 'n', POPT_ARG_STRING, &name, 'n', NULL, NULL}, { NULL, 'f', POPT_ARG_STRING, &file, 'f', NULL, NULL}, { NULL, 'e', POPT_BIT_SET, &scriptFlags, RPMSCRIPT_FLAG_EXPAND, NULL, NULL}, { NULL, 'q', POPT_BIT_SET, &scriptFlags, RPMSCRIPT_FLAG_QFORMAT, NULL, NULL}, { 0, 0, 0, 0, 0, NULL, NULL} }; switch (parsePart) { case PART_PRE: tag = RPMTAG_PREIN; tagflags = RPMSENSE_SCRIPT_PRE; progtag = RPMTAG_PREINPROG; flagtag = RPMTAG_PREINFLAGS; partname = "%pre"; break; case PART_POST: tag = RPMTAG_POSTIN; tagflags = RPMSENSE_SCRIPT_POST; progtag = RPMTAG_POSTINPROG; flagtag = RPMTAG_POSTINFLAGS; partname = "%post"; break; case PART_PREUN: tag = RPMTAG_PREUN; tagflags = RPMSENSE_SCRIPT_PREUN; progtag = RPMTAG_PREUNPROG; flagtag = RPMTAG_PREUNFLAGS; partname = "%preun"; break; case PART_POSTUN: tag = RPMTAG_POSTUN; tagflags = RPMSENSE_SCRIPT_POSTUN; progtag = RPMTAG_POSTUNPROG; flagtag = RPMTAG_POSTUNFLAGS; partname = "%postun"; break; case PART_PRETRANS: tag = RPMTAG_PRETRANS; tagflags = RPMSENSE_PRETRANS; progtag = RPMTAG_PRETRANSPROG; flagtag = RPMTAG_PRETRANSFLAGS; partname = "%pretrans"; break; case PART_POSTTRANS: tag = RPMTAG_POSTTRANS; tagflags = RPMSENSE_POSTTRANS; progtag = RPMTAG_POSTTRANSPROG; flagtag = RPMTAG_POSTTRANSFLAGS; partname = "%posttrans"; break; case PART_VERIFYSCRIPT: tag = RPMTAG_VERIFYSCRIPT; tagflags = RPMSENSE_SCRIPT_VERIFY; progtag = RPMTAG_VERIFYSCRIPTPROG; flagtag = RPMTAG_VERIFYSCRIPTFLAGS; partname = "%verifyscript"; break; case PART_TRIGGERPREIN: tag = RPMTAG_TRIGGERSCRIPTS; tagflags = 0; reqtag = RPMTAG_TRIGGERPREIN; progtag = RPMTAG_TRIGGERSCRIPTPROG; flagtag = RPMTAG_TRIGGERSCRIPTFLAGS; partname = "%triggerprein"; break; case PART_TRIGGERIN: tag = RPMTAG_TRIGGERSCRIPTS; tagflags = 0; reqtag = RPMTAG_TRIGGERIN; progtag = RPMTAG_TRIGGERSCRIPTPROG; flagtag = RPMTAG_TRIGGERSCRIPTFLAGS; partname = "%triggerin"; break; case PART_TRIGGERUN: tag = RPMTAG_TRIGGERSCRIPTS; tagflags = 0; reqtag = RPMTAG_TRIGGERUN; progtag = RPMTAG_TRIGGERSCRIPTPROG; flagtag = RPMTAG_TRIGGERSCRIPTFLAGS; partname = "%triggerun"; break; case PART_TRIGGERPOSTUN: tag = RPMTAG_TRIGGERSCRIPTS; tagflags = 0; reqtag = RPMTAG_TRIGGERPOSTUN; progtag = RPMTAG_TRIGGERSCRIPTPROG; flagtag = RPMTAG_TRIGGERSCRIPTFLAGS; partname = "%triggerpostun"; break; case PART_FILETRIGGERIN: tag = RPMTAG_FILETRIGGERSCRIPTS; tagflags = 0; reqtag = RPMTAG_FILETRIGGERIN; progtag = RPMTAG_FILETRIGGERSCRIPTPROG; flagtag = RPMTAG_FILETRIGGERSCRIPTFLAGS; partname = "%filetriggerin"; break; case PART_FILETRIGGERUN: tag = RPMTAG_FILETRIGGERSCRIPTS; tagflags = 0; reqtag = RPMTAG_FILETRIGGERUN; progtag = RPMTAG_FILETRIGGERSCRIPTPROG; flagtag = RPMTAG_FILETRIGGERSCRIPTFLAGS; partname = "%filetriggerun"; break; case PART_FILETRIGGERPOSTUN: tag = RPMTAG_FILETRIGGERSCRIPTS; tagflags = 0; reqtag = RPMTAG_FILETRIGGERPOSTUN; progtag = RPMTAG_FILETRIGGERSCRIPTPROG; flagtag = RPMTAG_FILETRIGGERSCRIPTFLAGS; partname = "%filetriggerpostun"; break; case PART_TRANSFILETRIGGERIN: tag = RPMTAG_TRANSFILETRIGGERSCRIPTS; tagflags = 0; reqtag = RPMTAG_TRANSFILETRIGGERIN; progtag = RPMTAG_TRANSFILETRIGGERSCRIPTPROG; flagtag = RPMTAG_TRANSFILETRIGGERSCRIPTFLAGS; partname = "%transfiletriggerin"; break; case PART_TRANSFILETRIGGERUN: tag = RPMTAG_TRANSFILETRIGGERSCRIPTS; tagflags = 0; reqtag = RPMTAG_TRANSFILETRIGGERUN; progtag = RPMTAG_TRANSFILETRIGGERSCRIPTPROG; flagtag = RPMTAG_TRANSFILETRIGGERSCRIPTFLAGS; partname = "%transfiletriggerun"; break; case PART_TRANSFILETRIGGERPOSTUN: tag = RPMTAG_TRANSFILETRIGGERSCRIPTS; tagflags = 0; reqtag = RPMTAG_TRANSFILETRIGGERPOSTUN; progtag = RPMTAG_TRANSFILETRIGGERSCRIPTPROG; flagtag = RPMTAG_TRANSFILETRIGGERSCRIPTFLAGS; partname = "%transfiletriggerpostun"; break; } if (tag == RPMTAG_TRIGGERSCRIPTS || tag == RPMTAG_FILETRIGGERSCRIPTS || tag == RPMTAG_TRANSFILETRIGGERSCRIPTS) { /* break line into two */ char *s = strstr(spec->line, "--"); if (!s) { rpmlog(RPMLOG_ERR, _("line %d: triggers must have --: %s\n"), spec->lineNum, spec->line); return PART_ERROR; } *s = '\0'; reqargs = xstrdup(s + 2); } if ((rc = poptParseArgvString(spec->line, &argc, &argv))) { rpmlog(RPMLOG_ERR, _("line %d: Error parsing %s: %s\n"), spec->lineNum, partname, poptStrerror(rc)); goto exit; } optCon = poptGetContext(NULL, argc, argv, optionsTable, 0); while ((arg = poptGetNextOpt(optCon)) > 0) { switch (arg) { case 'p': if (prog[0] == '<') { if (prog[strlen(prog)-1] != '>') { rpmlog(RPMLOG_ERR, _("line %d: internal script must end " "with \'>\': %s\n"), spec->lineNum, prog); goto exit; } } else if (prog[0] != '/') { rpmlog(RPMLOG_ERR, _("line %d: script program must begin " "with \'/\': %s\n"), spec->lineNum, prog); goto exit; } break; case 'n': flag = PART_NAME; break; } } if (arg < -1) { rpmlog(RPMLOG_ERR, _("line %d: Bad option %s: %s\n"), spec->lineNum, poptBadOption(optCon, POPT_BADOPTION_NOALIAS), spec->line); goto exit; } if (poptPeekArg(optCon)) { if (name == NULL) name = poptGetArg(optCon); if (poptPeekArg(optCon)) { rpmlog(RPMLOG_ERR, _("line %d: Too many names: %s\n"), spec->lineNum, spec->line); goto exit; } } if (lookupPackage(spec, name, flag, &pkg)) { rpmlog(RPMLOG_ERR, _("line %d: Package does not exist: %s\n"), spec->lineNum, spec->line); goto exit; } if (tag != RPMTAG_TRIGGERSCRIPTS) { if (headerIsEntry(pkg->header, progtag)) { rpmlog(RPMLOG_ERR, _("line %d: Second %s\n"), spec->lineNum, partname); goto exit; } } if ((rc = poptParseArgvString(prog, &progArgc, &progArgv))) { rpmlog(RPMLOG_ERR, _("line %d: Error parsing %s: %s\n"), spec->lineNum, partname, poptStrerror(rc)); goto exit; } sb = newStringBuf(); if ((rc = readLine(spec, STRIP_NOTHING)) > 0) { nextPart = PART_NONE; } else if (rc < 0) { goto exit; } else { while (! (nextPart = isPart(spec->line))) { appendStringBuf(sb, spec->line); if ((rc = readLine(spec, STRIP_NOTHING)) > 0) { nextPart = PART_NONE; break; } else if (rc < 0) { goto exit; } } } stripTrailingBlanksStringBuf(sb); p = getStringBuf(sb); #ifdef WITH_LUA if (rstreq(progArgv[0], "<lua>")) { rpmlua lua = NULL; /* Global state. */ if (rpmluaCheckScript(lua, p, partname) != RPMRC_OK) { goto exit; } (void) rpmlibNeedsFeature(pkg, "BuiltinLuaScripts", "4.2.2-1"); } else #endif if (progArgv[0][0] == '<') { rpmlog(RPMLOG_ERR, _("line %d: unsupported internal script: %s\n"), spec->lineNum, progArgv[0]); goto exit; } else { (void) addReqProv(pkg, RPMTAG_REQUIRENAME, progArgv[0], NULL, (tagflags | RPMSENSE_INTERP), 0); } if (scriptFlags) { rpmlibNeedsFeature(pkg, "ScriptletExpansion", "4.9.0-1"); } /* Trigger script insertion is always delayed in order to */ /* get the index right. */ if (tag == RPMTAG_TRIGGERSCRIPTS || tag == RPMTAG_FILETRIGGERSCRIPTS || tag == RPMTAG_TRANSFILETRIGGERSCRIPTS) { if (progArgc > 1) { rpmlog(RPMLOG_ERR, _("line %d: interpreter arguments not allowed in triggers: %s\n"), spec->lineNum, prog); goto exit; } /* Add file/index/prog triple to the trigger file list */ index = addTriggerIndex(pkg, file, p, progArgv[0], scriptFlags, tag); /* Generate the trigger tags */ if (parseRCPOT(spec, pkg, reqargs, reqtag, index, tagflags)) goto exit; } else { struct rpmtd_s td; /* * XXX Ancient rpm uses STRING, not STRING_ARRAY type here. Construct * the td manually and preserve legacy compat for now... */ rpmtdReset(&td); td.tag = progtag; td.count = progArgc; if (progArgc == 1) { td.data = (void *) *progArgv; td.type = RPM_STRING_TYPE; } else { (void) rpmlibNeedsFeature(pkg, "ScriptletInterpreterArgs", "4.0.3-1"); td.data = progArgv; td.type = RPM_STRING_ARRAY_TYPE; } headerPut(pkg->header, &td, HEADERPUT_DEFAULT); if (*p != '\0') { headerPutString(pkg->header, tag, p); } if (scriptFlags) { headerPutUint32(pkg->header, flagtag, &scriptFlags, 1); } if (file) { switch (parsePart) { case PART_PRE: pkg->preInFile = xstrdup(file); break; case PART_POST: pkg->postInFile = xstrdup(file); break; case PART_PREUN: pkg->preUnFile = xstrdup(file); break; case PART_POSTUN: pkg->postUnFile = xstrdup(file); break; case PART_PRETRANS: pkg->preTransFile = xstrdup(file); break; case PART_POSTTRANS: pkg->postTransFile = xstrdup(file); break; case PART_VERIFYSCRIPT: pkg->verifyFile = xstrdup(file); break; } } } res = nextPart; exit: free(reqargs); freeStringBuf(sb); free(progArgv); free(argv); poptFreeContext(optCon); return res; }