static char * prDbiOpenFlags(int dbflags, int print_dbenv_flags) { ARGV_t flags = NULL; const struct poptOption *opt; char *buf; for (opt = rdbOptions; opt->longName != NULL; opt++) { if (opt->argInfo != POPT_BIT_SET) continue; if (print_dbenv_flags) { if (!(opt->arg == &staticcfg.db_eflags)) continue; } else { if (!(opt->arg == &staticdbicfg.dbi_oflags)) continue; } if ((dbflags & opt->val) != opt->val) continue; argvAdd(&flags, opt->longName); dbflags &= ~opt->val; } if (dbflags) { char *df = NULL; rasprintf(&df, "0x%x", (unsigned)dbflags); argvAdd(&flags, df); free(df); } buf = argvJoin(flags, ":"); argvFree(flags); return buf ? buf : xstrdup("(none)"); }
static rpmRC sepoltransRemove(sepoltrans * pt, const sepol * pol) { rpmRC rc = RPMRC_OK; if (pol->flags & RPMPOL_FLAG_BASE) { return RPMRC_FAIL; } if (pt->execsemodule) { if (argvAdd(&pt->semodargs, "-r") < 0 || argvAdd(&pt->semodargs, pol->name) < 0) { rc = RPMRC_FAIL; } } else { if (semanage_module_remove(pt->sh, (char *) pol->name) < 0) { rc = RPMRC_FAIL; } } if (rc != RPMRC_OK) { rpmlog(RPMLOG_ERR, _("Failed to remove policy module: %s\n"), pol->name); } else { pt->changes++; } return rc; }
/*@-mustmod@*/ int argvFgets(ARGV_t * argvp, void * fd) { FILE * fp = (fd ? fdGetFILE(fd) : stdin); ARGV_t av = NULL; char buf[BUFSIZ]; char * b, * be; int rc = 0; if (fp == NULL) return -2; while (!rc && (b = fgets(buf, (int)sizeof(buf), fp)) != NULL) { buf[sizeof(buf)-1] = '\0'; be = b + strlen(buf); if (be > b) be--; while (strchr("\r\n", *be) != NULL) *be-- = '\0'; rc = argvAdd(&av, b); } if (!rc) rc = ferror(fp); if (!rc) rc = (feof(fp) ? 0 : 1); if (!rc && argvp) *argvp = av; else av = argvFree(av); /*@-nullstate@*/ /* XXX *argvp may be NULL. */ return rc; /*@=nullstate@*/ }
static int filedepTag(Header h, rpmTag tagN, rpmtd td, headerGetFlags hgflags) { rpmfi fi = rpmfiNew(NULL, h, RPMTAG_BASENAMES, RPMFI_NOHEADER); rpmds ds = NULL; char **fdeps = NULL; int numfiles; char deptype = 'R'; int fileix; int rc = 0; numfiles = rpmfiFC(fi); if (numfiles <= 0) { goto exit; } if (tagN == RPMTAG_PROVIDENAME) deptype = 'P'; else if (tagN == RPMTAG_REQUIRENAME) deptype = 'R'; ds = rpmdsNew(h, tagN, 0); fdeps = xmalloc(numfiles * sizeof(*fdeps)); while ((fileix = rpmfiNext(fi)) >= 0) { ARGV_t deps = NULL; const uint32_t * ddict = NULL; int ndx = rpmfiFDepends(fi, &ddict); if (ddict != NULL) { while (ndx-- > 0) { const char * DNEVR; unsigned dix = *ddict++; char mydt = ((dix >> 24) & 0xff); if (mydt != deptype) continue; dix &= 0x00ffffff; (void) rpmdsSetIx(ds, dix-1); if (rpmdsNext(ds) < 0) continue; DNEVR = rpmdsDNEVR(ds); if (DNEVR != NULL) { argvAdd(&deps, DNEVR + 2); } } } fdeps[fileix] = deps ? argvJoin(deps, " ") : xstrdup(""); argvFree(deps); } td->data = fdeps; td->count = numfiles; td->flags = RPMTD_ALLOCED | RPMTD_PTR_ALLOCED; td->type = RPM_STRING_ARRAY_TYPE; rc = 1; exit: rpmfiFree(fi); rpmdsFree(ds); return rc; }
int argvAddNum(ARGV_t *argvp, int val) { char *valstr = NULL; int rc; rasprintf(&valstr, "%d", val); rc = argvAdd(argvp, valstr); free(valstr); return rc; }
int main(int argc, char *argv[]) { poptContext con = rpmioInit(argc, argv, optionsTable); ARGV_t av = poptGetArgs(con); int ac = argvCount(av);; const char ** keyids = NULL; int ec = 0; int xx; _rpmhkp_lvl = RPMLOG_INFO; /* XXX default is RPMLOG_DEBUG */ if (_hkp_keyserver == NULL) _hkp_keyserver = xstrdup("keys.rpm5.org"); if (_rpmhkp_spew) _rpmhkp_debug = -1; /* XXX no macros are loaded if using poptIO. */ addMacro(NULL, "_hkp_keyserver", NULL, _hkp_keyserver, -1); addMacro(NULL, "_hkp_keyserver_query", NULL, _hkp_keyserver_query, -1); if (ac == 0) { xx = argvAppend(&keyids, _keyids); } else { int gotstdin = 0; int i; for (i = 0; i < ac; i++) { if (strcmp(av[i], "-")) { xx = argvAdd(&keyids, (ARGstr_t)av[i]); continue; } if (gotstdin) continue; gotstdin++; if (argvFgets(&keyids, NULL)) goto exit; } } ec = rpmhkpReadKeys(keyids); if (_rpmhkp_stats) _rpmhkpPrintStats(NULL); exit: keyids = argvFree(keyids); _hkp_keyserver = _free(_hkp_keyserver); /*@i@*/ urlFreeCache(); con = rpmioFini(con); return ec; }
static int rpmNoGlob(const char *fn, int *argcPtr, ARGV_t * argvPtr) { struct stat sb; int rc = stat(fn, &sb); if (rc == 0) { argvAdd(argvPtr, fn); *argcPtr = 1; } else { *argcPtr = 0; } return rc; }
static void rpmdictAdd(rpmdict dict, const char * key) { rpmuint64_t * val = NULL; void ** data = (void **)&val; if (htGetEntry(dict->ht, key, &data, NULL, NULL)) { (void) argvAdd(&dict->av, key); val = (rpmuint64_t *) xcalloc(1, sizeof(*val)); htAddEntry(dict->ht, dict->av[dict->ac++], val); } else val = (rpmuint64_t *)data[0]; val[0]++; }
static rpmRC sepoltransInstall(sepoltrans * pt, const sepol * pol) { rpmRC rc = RPMRC_OK; char *path = NULL; rc = sepolWritePolicy(pol, &path); if (rc != RPMRC_OK) { return rc; } argvAdd(&pt->filelist, path); if (pt->execsemodule) { const char *flag = (pol->flags & RPMPOL_FLAG_BASE) ? "-b" : "-i"; if (argvAdd(&pt->semodargs, flag) < 0 || argvAdd(&pt->semodargs, path) < 0) { rc = RPMRC_FAIL; } } else { if (pol->flags & RPMPOL_FLAG_BASE) { if (semanage_module_install_base_file(pt->sh, path) < 0) { rc = RPMRC_FAIL; } } else { if (semanage_module_install_file(pt->sh, path) < 0) { rc = RPMRC_FAIL; } } } if (rc != RPMRC_OK) { rpmlog(RPMLOG_ERR, _("Failed to install policy module: %s (%s)\n"), pol->name, path); } else { pt->changes++; } _free(path); return rc; }
static void addDep(ARGV_t *deps, const char *soname, const char *ver, const char *marker) { char *dep = NULL; if (skipSoname(soname)) return; if (ver || marker) { rasprintf(&dep, "%s(%s)%s", soname, ver ? ver : "", marker ? marker : ""); } argvAdd(deps, dep ? dep : soname); free(dep); }
static sepoltrans *sepoltransNew(void) { sepoltrans *pt = xcalloc(1, sizeof(*pt)); pt->semodulepath = rpmExpand("%{__semodule}", NULL); pt->execsemodule = (!rpmChrootDone() && access(pt->semodulepath, X_OK) == 0); pt->changes = 0; if (pt->execsemodule) { argvAdd(&pt->semodargs, "semodule"); } else { pt->sh = semanage_handle_create(); if (!pt->sh) { rpmlog(RPMLOG_ERR, _("Failed to create semanage handle\n")); goto err; } semanage_set_create_store(pt->sh, 1); semanage_set_check_contexts(pt->sh, 0); if (semanage_connect(pt->sh) < 0) { rpmlog(RPMLOG_ERR, _("Failed to connect to policy handler\n")); goto err; } if (semanage_begin_transaction(pt->sh) < 0) { rpmlog(RPMLOG_ERR, _("Failed to begin policy transaction: %s\n"), errno ? strerror(errno) : ""); goto err; } semanage_set_reload(pt->sh, !rpmChrootDone()); } return pt; err: if (pt->sh) { if (semanage_is_connected(pt->sh)) { semanage_disconnect(pt->sh); } semanage_handle_destroy(pt->sh); } free(pt); return NULL; }
rpmRC rpmScriptRun(rpmScript script, int arg1, int arg2, FD_t scriptFd, ARGV_const_t prefixes, int warn_only, rpmPlugins plugins) { ARGV_t args = NULL; rpmlogLvl lvl = warn_only ? RPMLOG_WARNING : RPMLOG_ERR; rpmRC rc; int script_type = RPMSCRIPTLET_FORK | RPMSCRIPTLET_EXEC; if (script == NULL) return RPMRC_OK; /* construct a new argv as we can't modify the one from header */ if (script->args) { argvAppend(&args, script->args); } else { argvAdd(&args, "/bin/sh"); } if (rstreq(args[0], "<lua>")) script_type = RPMSCRIPTLET_NONE; /* Run scriptlet pre hook for all plugins */ rc = rpmpluginsCallScriptletPre(plugins, script->descr, script_type); if (rc != RPMRC_FAIL) { if (script_type & RPMSCRIPTLET_EXEC) { rc = runExtScript(plugins, prefixes, script->descr, lvl, scriptFd, &args, script->body, arg1, arg2); } else { rc = runLuaScript(plugins, prefixes, script->descr, lvl, scriptFd, &args, script->body, arg1, arg2); } } /* Run scriptlet post hook for all plugins */ rpmpluginsCallScriptletPost(plugins, script->descr, script_type, rc); argvFree(args); return rc; }
static ModuleRec newModule(const char *path, const char *name, const char *types, uint32_t flags) { ModuleRec mod; uint8_t *raw = NULL; ssize_t rawlen = 0; const char *buildDir = "%{_builddir}/%{?buildsubdir}/"; if (!path) { rpmlog(RPMLOG_ERR, _("%%semodule requires a file path\n")); return NULL; } mod = xcalloc(1, sizeof(*mod)); mod->path = rpmGenPath(buildDir, NULL, path); if ((rpmioSlurp(mod->path, &raw, &rawlen)) != 0 || raw == NULL) { rpmlog(RPMLOG_ERR, _("Failed to read policy file: %s\n"), mod->path); goto err; } mod->data = b64encode(raw, rawlen, -1); if (!mod->data) { rpmlog(RPMLOG_ERR, _("Failed to encode policy file: %s\n"), mod->path); goto err; } if (name) { mod->name = xstrdup(name); } else { /* assume base name (minus extension) if name is not given */ char *tmp = xstrdup(mod->path); char *bname = basename(tmp); char *end = strchr(bname, '.'); if (end) *end = '\0'; if (strlen(bname) > 0) { mod->name = xstrdup(bname); } else { rpmlog(RPMLOG_ERR, _("Failed to determine a policy name: %s\n"), mod->path); _free(tmp); goto err; } _free(tmp); } if (types) { mod->types = argvSplitString(types, ",", ARGV_SKIPEMPTY); argvSort(mod->types, NULL); if (argvSearch(mod->types, RPMPOL_TYPE_DEFAULT, NULL) && argvCount(mod->types) > 1) { rpmlog(RPMLOG_WARNING, _("'%s' type given with other types in %%semodule %s. Compacting types to '%s'.\n"), RPMPOL_TYPE_DEFAULT, mod->path, RPMPOL_TYPE_DEFAULT); mod->types = argvFree(mod->types); argvAdd(&mod->types, RPMPOL_TYPE_DEFAULT); } } else { argvAdd(&mod->types, RPMPOL_TYPE_DEFAULT); } mod->flags = flags; return mod; err: freeModule(mod); return NULL; }
/** * 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; }
static int rpmtsSetupCollections(rpmts ts) { /* seenCollectionsPost and TEs are basically a key-value pair. each item in * seenCollectionsPost is a collection that has been seen from any package, * and the associated index in the TEs is the last transaction element * where that collection was seen. */ ARGV_t seenCollectionsPost = NULL; rpmte *TEs = NULL; int numSeenPost = 0; /* seenCollectionsPre is a list of collections that have been seen from * only removed packages */ ARGV_t seenCollectionsPre = NULL; int numSeenPre = 0; ARGV_const_t collname; int installing = 1; int i; rpmte p; rpmtsi pi = rpmtsiInit(ts); while ((p = rpmtsiNext(pi, 0)) != NULL) { /* detect when we switch from installing to removing packages, and * update the lastInCollectionAdd lists */ if (installing && rpmteType(p) == TR_REMOVED) { installing = 0; for (i = 0; i < numSeenPost; i++) { rpmteAddToLastInCollectionAdd(TEs[i], seenCollectionsPost[i]); } } rpmteSetupCollectionPlugins(p); for (collname = rpmteCollections(p); collname && *collname; collname++) { /* figure out if we've seen this collection in post before */ for (i = 0; i < numSeenPost && strcmp(*collname, seenCollectionsPost[i]); i++) { } if (i < numSeenPost) { /* we've seen the collection, update the index */ TEs[i] = p; } else { /* haven't seen the collection yet, add it */ argvAdd(&seenCollectionsPost, *collname); TEs = xrealloc(TEs, sizeof(*TEs) * (numSeenPost + 1)); TEs[numSeenPost] = p; numSeenPost++; } /* figure out if we've seen this collection in pre remove before */ if (installing == 0) { for (i = 0; i < numSeenPre && strcmp(*collname, seenCollectionsPre[i]); i++) { } if (i >= numSeenPre) { /* haven't seen this collection, add it */ rpmteAddToFirstInCollectionRemove(p, *collname); argvAdd(&seenCollectionsPre, *collname); numSeenPre++; } } } } rpmtsiFree(pi); /* we've looked at all the rpmte's, update the lastInCollectionAny lists */ for (i = 0; i < numSeenPost; i++) { rpmteAddToLastInCollectionAny(TEs[i], seenCollectionsPost[i]); if (installing == 1) { /* lastInCollectionAdd is only updated above if packages were * removed. if nothing is removed in the transaction, we need to * update that list here */ rpmteAddToLastInCollectionAdd(TEs[i], seenCollectionsPost[i]); } } argvFree(seenCollectionsPost); argvFree(seenCollectionsPre); _free(TEs); return 0; }
/** * Identify type of dependency. * @param td tag data container * @return formatted string */ static char * deptypeFormat(rpmtd td) { char *val = NULL; if (rpmtdClass(td) != RPM_NUMERIC_CLASS) { val = xstrdup(_("(not a number)")); } else { ARGV_t sdeps = NULL; uint64_t item = rpmtdGetNumber(td); if (item & RPMSENSE_SCRIPT_PRE) argvAdd(&sdeps, "pre"); if (item & RPMSENSE_SCRIPT_POST) argvAdd(&sdeps, "post"); if (item & RPMSENSE_SCRIPT_PREUN) argvAdd(&sdeps, "preun"); if (item & RPMSENSE_SCRIPT_POSTUN) argvAdd(&sdeps, "postun"); if (item & RPMSENSE_SCRIPT_VERIFY) argvAdd(&sdeps, "verify"); if (item & RPMSENSE_INTERP) argvAdd(&sdeps, "interp"); if (item & RPMSENSE_RPMLIB) argvAdd(&sdeps, "rpmlib"); if ((item & RPMSENSE_FIND_REQUIRES) || (item & RPMSENSE_FIND_PROVIDES)) argvAdd(&sdeps, "auto"); if (item & RPMSENSE_PREREQ) argvAdd(&sdeps, "prereq"); if (item & RPMSENSE_PRETRANS) argvAdd(&sdeps, "pretrans"); if (item & RPMSENSE_POSTTRANS) argvAdd(&sdeps, "posttrans"); if (item & RPMSENSE_CONFIG) argvAdd(&sdeps, "config"); if (item & RPMSENSE_MISSINGOK) argvAdd(&sdeps, "missingok"); if (sdeps) { val = argvJoin(sdeps, ","); } else { val = xstrdup("manual"); } argvFree(sdeps); } return val; }
static int parseHTML(rpmtget tget) { miRE mire = tget->mires; int noffsets = 3; int offsets[3]; ssize_t nr = (tget->b != NULL ? (ssize_t)tget->nb : tgetFill(tget)); int xx; xx = mireSetEOptions(mire, offsets, noffsets); while (tget->nb > 0) { char * gbn, * hbn; char * f, * fe; char * g, * ge; char * h, * he; char * t; mode_t mode; size_t nb; offsets[0] = offsets[1] = -1; xx = mireRegexec(mire, tget->b, tget->nb); if (xx == 0 && offsets[0] != -1 && offsets[1] != -1) { /* [f:fe) contains |<a href="..."| match. */ f = tget->b + offsets[0]; fe = tget->b + offsets[1]; /* [h:he) contains the href basename. */ he = fe; if (he[-1] == '"') he--; if (he[-1] == '/') { mode = S_IFDIR | 0755; he--; } else mode = S_IFREG | 0644; h = he; while (h > f && (h[-1] != '"' && h[-1] != '/')) h--; nb = (size_t)(he - h); hbn = t = xmalloc(nb + 1 + 1); while (h < he) *t++ = *h++; if (S_ISDIR(mode)) *t++ = '/'; *t = '\0'; /* [g:ge) contains the URI basename. */ g = fe; while (*g != '>') g++; ge = ++g; while (*ge != '<') ge++; nb = (size_t)(ge - g); gbn = t = xmalloc(nb + 1 + 1); while (g < ge) *t++ = *g++; if (S_ISDIR(mode)) *t++ = '/'; *t = '\0'; /* Filter out weirdos and "." and "..". */ if (!strcmp(gbn, hbn) && strcmp(hbn, "./") && strcmp(hbn, "../")) { fprintf(stderr, "\t%s\n", gbn); xx = argvAdd(&tget->av, gbn); } gbn = _free(gbn); hbn = _free(hbn); offsets[1] += (ge - fe); tget->b += offsets[1]; tget->nb -= offsets[1]; } else { size_t nb = tget->nb; if (nr > 0) nb -= 1024; /* XXX overlap a bit if filling. */ tget->b += nb; tget->nb -= nb; } if (nr > 0) nr = tgetFill(tget); } xx = mireSetEOptions(mire, NULL, 0); return 0; }
/** * Run an external script. */ static rpmRC runExtScript(rpmPlugins plugins, ARGV_const_t prefixes, const char *sname, rpmlogLvl lvl, FD_t scriptFd, ARGV_t * argvp, const char *script, int arg1, int arg2) { FD_t out = NULL; char * fn = NULL; pid_t pid, reaped; int status; rpmRC rc = RPMRC_FAIL; rpmlog(RPMLOG_DEBUG, "%s: scriptlet start\n", sname); if (script) { fn = writeScript(*argvp[0], script); if (fn == NULL) { rpmlog(RPMLOG_ERR, _("Couldn't create temporary file for %s: %s\n"), sname, strerror(errno)); goto exit; } argvAdd(argvp, fn); if (arg1 >= 0) { argvAddNum(argvp, arg1); } if (arg2 >= 0) { argvAddNum(argvp, arg2); } } if (scriptFd != NULL) { if (rpmIsVerbose()) { out = fdDup(Fileno(scriptFd)); } else { out = Fopen("/dev/null", "w.fdio"); if (Ferror(out)) { out = fdDup(Fileno(scriptFd)); } } } else { out = fdDup(STDOUT_FILENO); } if (out == NULL) { rpmlog(RPMLOG_ERR, _("Couldn't duplicate file descriptor: %s: %s\n"), sname, strerror(errno)); goto exit; } pid = fork(); if (pid == (pid_t) -1) { rpmlog(RPMLOG_ERR, _("Couldn't fork %s: %s\n"), sname, strerror(errno)); goto exit; } else if (pid == 0) {/* Child */ rpmlog(RPMLOG_DEBUG, "%s: execv(%s) pid %d\n", sname, *argvp[0], (unsigned)getpid()); /* Run scriptlet post fork hook for all plugins */ if (rpmpluginsCallScriptletForkPost(plugins, *argvp[0], RPMSCRIPTLET_FORK | RPMSCRIPTLET_EXEC) != RPMRC_FAIL) { doScriptExec(*argvp, prefixes, scriptFd, out); } else { _exit(126); /* exit 126 for compatibility with bash(1) */ } } do { reaped = waitpid(pid, &status, 0); } while (reaped == -1 && errno == EINTR); rpmlog(RPMLOG_DEBUG, "%s: waitpid(%d) rc %d status %x\n", sname, (unsigned)pid, (unsigned)reaped, status); if (reaped < 0) { rpmlog(lvl, _("%s scriptlet failed, waitpid(%d) rc %d: %s\n"), sname, pid, reaped, strerror(errno)); } else if (!WIFEXITED(status) || WEXITSTATUS(status)) { if (WIFSIGNALED(status)) { rpmlog(lvl, _("%s scriptlet failed, signal %d\n"), sname, WTERMSIG(status)); } else { rpmlog(lvl, _("%s scriptlet failed, exit status %d\n"), sname, WEXITSTATUS(status)); } } else { /* if we get this far we're clear */ rc = RPMRC_OK; } exit: if (out) Fclose(out); /* XXX dup'd STDOUT_FILENO */ if (fn) { if (!rpmIsDebug()) unlink(fn); free(fn); } return rc; }
/** * Parse arguments (to next new line) for parameterized macro. * @todo Use popt rather than getopt to parse args. * @param mb macro expansion state * @param me macro entry slot * @param se arguments to parse * @param lastc stop parsing at lastc * @return address to continue parsing */ static const char * grabArgs(MacroBuf mb, const rpmMacroEntry me, const char * se, const char * lastc) { const char *opts, *o; char *args = NULL; ARGV_t argv = NULL; int argc = 0; int c; /* Copy macro name as argv[0] */ argvAdd(&argv, me->name); addMacro(mb->mc, "0", NULL, me->name, mb->depth); /* * Make a copy of se up to lastc string that we can pass to argvSplit(). * Append the results to main argv. */ { ARGV_t av = NULL; char *s = xcalloc((lastc-se)+1, sizeof(*s)); memcpy(s, se, (lastc-se)); argvSplit(&av, s, " \t"); argvAppend(&argv, av); argvFree(av); free(s); } /* * The macro %* analoguous to the shell's $* means "Pass all non-macro * parameters." Consequently, there needs to be a macro that means "Pass all * (including macro parameters) options". This is useful for verifying * parameters during expansion and yet transparently passing all parameters * through for higher level processing (e.g. %description and/or %setup). * This is the (potential) justification for %{**} ... */ args = argvJoin(argv + 1, " "); addMacro(mb->mc, "**", NULL, args, mb->depth); free(args); /* * POSIX states optind must be 1 before any call but glibc uses 0 * to (re)initialize getopt structures, eww. */ #ifdef __GLIBC__ optind = 0; #else optind = 1; #endif opts = me->opts; argc = argvCount(argv); /* Define option macros. */ while((c = getopt(argc, argv, opts)) != -1) { char *name = NULL, *body = NULL; if (c == '?' || (o = strchr(opts, c)) == NULL) { rpmlog(RPMLOG_ERR, _("Unknown option %c in %s(%s)\n"), (char)c, me->name, opts); goto exit; } rasprintf(&name, "-%c", c); if (optarg) { rasprintf(&body, "-%c %s", c, optarg); } else { rasprintf(&body, "-%c", c); } addMacro(mb->mc, name, NULL, body, mb->depth); free(name); free(body); if (optarg) { rasprintf(&name, "-%c*", c); addMacro(mb->mc, name, NULL, optarg, mb->depth); free(name); } } /* Add argument count (remaining non-option items) as macro. */ { char *ac = NULL; rasprintf(&ac, "%d", (argc - optind)); addMacro(mb->mc, "#", NULL, ac, mb->depth); free(ac); } /* Add macro for each argument */ if (argc - optind) { for (c = optind; c < argc; c++) { char *name = NULL; rasprintf(&name, "%d", (c - optind + 1)); addMacro(mb->mc, name, NULL, argv[c], mb->depth); free(name); } } /* Add concatenated unexpanded arguments as yet another macro. */ args = argvJoin(argv + optind, " "); addMacro(mb->mc, "*", NULL, args ? args : "", mb->depth); free(args); exit: argvFree(argv); return *lastc ? lastc + 1 : lastc; }
int parseFiles(rpmSpec spec) { int nextPart, res = PART_ERROR; Package pkg; int rc, argc; int arg; const char ** argv = NULL; const char *name = NULL; int flag = PART_SUBNAME; poptContext optCon = NULL; struct poptOption optionsTable[] = { { NULL, 'n', POPT_ARG_STRING, &name, 'n', NULL, NULL}, { NULL, 'f', POPT_ARG_STRING, NULL, 'f', NULL, NULL}, { 0, 0, 0, 0, 0, NULL, NULL} }; /* XXX unmask %license while parsing %files */ addMacro(spec->macros, "license", NULL, "%%license", RMIL_SPEC); if ((rc = poptParseArgvString(spec->line, &argc, &argv))) { rpmlog(RPMLOG_ERR, _("line %d: Error parsing %%files: %s\n"), spec->lineNum, poptStrerror(rc)); goto exit; } optCon = poptGetContext(NULL, argc, argv, optionsTable, 0); while ((arg = poptGetNextOpt(optCon)) > 0) { if (arg == 'n') { flag = PART_NAME; } } 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; } for (arg=1; arg<argc; arg++) { if (rstreq(argv[arg], "-f") && argv[arg+1]) { char *file = rpmGetPath(argv[arg+1], NULL); argvAdd(&(pkg->fileFile), file); free(file); } } pkg->fileList = argvNew(); if ((rc = readLine(spec, STRIP_COMMENTS)) > 0) { nextPart = PART_NONE; } else if (rc < 0) { goto exit; } else { while (! (nextPart = isPart(spec->line))) { argvAdd(&(pkg->fileList), spec->line); if ((rc = readLine(spec, STRIP_COMMENTS)) > 0) { nextPart = PART_NONE; break; } else if (rc < 0) { goto exit; } } } res = nextPart; exit: delMacro(NULL, "license"); free(argv); poptFreeContext(optCon); return res; }
int parseFiles(rpmSpec spec) { int nextPart, res = PART_ERROR; Package pkg; int rc, argc; int arg; const char ** argv = NULL; const char *name = NULL; int flag = PART_SUBNAME; poptContext optCon = NULL; struct poptOption optionsTable[] = { { NULL, 'n', POPT_ARG_STRING, &name, 'n', NULL, NULL}, { NULL, 'f', POPT_ARG_STRING, NULL, 'f', NULL, NULL}, { 0, 0, 0, 0, 0, NULL, NULL} }; /* XXX unmask %license while parsing %files */ rpmPushMacro(spec->macros, "license", NULL, "%%license", RMIL_SPEC); if ((rc = poptParseArgvString(spec->line, &argc, &argv))) { rpmlog(RPMLOG_ERR, _("line %d: Error parsing %%files: %s\n"), spec->lineNum, poptStrerror(rc)); goto exit; } optCon = poptGetContext(NULL, argc, argv, optionsTable, 0); while ((arg = poptGetNextOpt(optCon)) > 0) { if (arg == 'n') { flag = PART_NAME; } } 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)) goto exit; /* * This should be an error, but its surprisingly commonly abused for the * effect of multiple -f arguments in versions that dont support it. * Warn but preserve behavior, except for leaking memory. */ if (pkg->fileList != NULL) { rpmlog(RPMLOG_WARNING, _("line %d: multiple %%files for package '%s'\n"), spec->lineNum, rpmstrPoolStr(pkg->pool, pkg->name)); pkg->fileList = argvFree(pkg->fileList); } for (arg=1; arg<argc; arg++) { if (rstreq(argv[arg], "-f") && argv[arg+1]) { char *file = rpmGetPath(argv[arg+1], NULL); argvAdd(&(pkg->fileFile), file); free(file); } } pkg->fileList = argvNew(); if ((rc = readLine(spec, STRIP_COMMENTS)) > 0) { nextPart = PART_NONE; } else if (rc < 0) { goto exit; } else { while (! (nextPart = isPart(spec->line))) { argvAdd(&(pkg->fileList), spec->line); if ((rc = readLine(spec, STRIP_COMMENTS)) > 0) { nextPart = PART_NONE; break; } else if (rc < 0) { goto exit; } } } res = nextPart; exit: rpmPopMacro(NULL, "license"); free(argv); poptFreeContext(optCon); return res; }
int main(int argc, char *argv[]) { poptContext optCon = NULL; ARGV_t av = NULL; rpmfc fc = NULL; int ec = 1; char buf[BUFSIZ]; xsetprogname(argv[0]); /* Portability call -- see system.h */ optCon = rpmcliInit(argc, argv, optionsTable); if (optCon == NULL) goto exit; /* normally files get passed through stdin but also accept files as args */ if (poptPeekArg(optCon)) { const char *arg; while ((arg = poptGetArg(optCon)) != NULL) { argvAdd(&av, arg); } } else { while (fgets(buf, sizeof(buf), stdin) != NULL) { char *be = buf + strlen(buf) - 1; while (strchr("\r\n", *be) != NULL) *be-- = '\0'; argvAdd(&av, buf); } } /* Make sure file names are sorted. */ argvSort(av, NULL); /* Build file/package class and dependency dictionaries. */ fc = rpmfcCreate(getenv("RPM_BUILD_ROOT"), 0); if (rpmfcClassify(fc, av, NULL) || rpmfcApply(fc)) goto exit; if (_rpmfc_debug) rpmfcPrint(buf, fc, NULL); if (print_provides) rpmdsPrint(NULL, rpmfcProvides(fc), stdout); if (print_requires) rpmdsPrint(NULL, rpmfcRequires(fc), stdout); if (print_recommends) rpmdsPrint(NULL, rpmfcRecommends(fc), stdout); if (print_suggests) rpmdsPrint(NULL, rpmfcSuggests(fc), stdout); if (print_supplements) rpmdsPrint(NULL, rpmfcSupplements(fc), stdout); if (print_enhances) rpmdsPrint(NULL, rpmfcEnhances(fc), stdout); if (print_conflicts) rpmdsPrint(NULL, rpmfcConflicts(fc), stdout); if (print_obsoletes) rpmdsPrint(NULL, rpmfcObsoletes(fc), stdout); ec = 0; exit: argvFree(av); rpmfcFree(fc); rpmcliFini(optCon); return ec; }
static int processFile(const char *fn, int dtype) { int rc = 1; int fdno = -1; struct stat st; GElf_Ehdr *ehdr, ehdr_mem; elfInfo *ei = rcalloc(1, sizeof(*ei)); fdno = open(fn, O_RDONLY); if (fdno < 0 || fstat(fdno, &st) < 0) goto exit; (void) elf_version(EV_CURRENT); ei->elf = elf_begin(fdno, ELF_C_READ, NULL); if (ei->elf == NULL || elf_kind(ei->elf) != ELF_K_ELF) goto exit; ehdr = gelf_getehdr(ei->elf, &ehdr_mem); if (ehdr == NULL) goto exit; if (ehdr->e_type == ET_DYN || ehdr->e_type == ET_EXEC) { ei->marker = mkmarker(ehdr); ei->isDSO = (ehdr->e_type == ET_DYN); ei->isExec = (st.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)); processProgHeaders(ei, ehdr); processSections(ei); } /* * For DSOs which use the .gnu_hash section and don't have a .hash * section, we need to ensure that we have a new enough glibc. */ if (ei->isExec && ei->gotGNUHASH && !ei->gotHASH && !soname_only) { argvAdd(&ei->requires, "rtld(GNU_HASH)"); } /* * For DSOs, add DT_SONAME as provide. If its missing, we can fake * it from the basename if requested. The bizarre looking DT_DEBUG * check is used to avoid adding basename provides for PIE executables. */ if (ei->isDSO && !ei->gotDEBUG) { if (!ei->soname && fake_soname) { const char *bn = strrchr(fn, '/'); ei->soname = rstrdup(bn ? bn + 1 : fn); } if (ei->soname) addDep(&ei->provides, ei->soname, NULL, ei->marker); } /* If requested and present, add dep for interpreter (ie dynamic linker) */ if (ei->interp && require_interp) argvAdd(&ei->requires, ei->interp); rc = 0; /* dump the requested dependencies for this file */ for (ARGV_t dep = dtype ? ei->requires : ei->provides; dep && *dep; dep++) { fprintf(stdout, "%s\n", *dep); } exit: if (fdno >= 0) close(fdno); if (ei) { argvFree(ei->provides); argvFree(ei->requires); free(ei->soname); free(ei->interp); if (ei->elf) elf_end(ei->elf); rfree(ei); } 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; }
/** * Parse %patch line. * This supports too many crazy syntaxes: * - %patchN is equal to %patch -P<N> * - -P<N> -P<N+1>... can be used to apply several patch on a single line * - Any trailing arguments are treated as patch numbers * - Any combination of the above, except unless at least one -P is specified, * %patch is treated as %patch -P0 so that "%patch 1" is actually * equal to "%patch -P0 -P1". * * @param spec build info * @param line current line from spec file * @return RPMRC_OK on success */ static rpmRC doPatchMacro(rpmSpec spec, const char *line) { char *opt_b, *opt_P, *opt_d; char *buf = NULL; int opt_p, opt_R, opt_E, opt_F; int argc, c; const char **argv = NULL; ARGV_t patch, patchnums = NULL; rpmRC rc = RPMRC_FAIL; /* assume failure */ struct poptOption const patchOpts[] = { { NULL, 'P', POPT_ARG_STRING, &opt_P, 'P', NULL, NULL }, { NULL, 'p', POPT_ARG_INT, &opt_p, 'p', NULL, NULL }, { NULL, 'R', POPT_ARG_NONE, &opt_R, 'R', NULL, NULL }, { NULL, 'E', POPT_ARG_NONE, &opt_E, 'E', NULL, NULL }, { NULL, 'b', POPT_ARG_STRING, &opt_b, 'b', NULL, NULL }, { NULL, 'z', POPT_ARG_STRING, &opt_b, 'z', NULL, NULL }, { NULL, 'F', POPT_ARG_INT, &opt_F, 'F', NULL, NULL }, { NULL, 'd', POPT_ARG_STRING, &opt_d, 'd', NULL, NULL }, { NULL, 0, 0, NULL, 0, NULL, NULL } }; poptContext optCon = NULL; opt_p = opt_R = opt_E = 0; opt_F = rpmExpandNumeric("%{_default_patch_fuzz}"); /* get default fuzz factor for %patch */ opt_b = opt_d = NULL; /* Convert %patchN to %patch -PN to simplify further processing */ if (! strchr(" \t\n", line[6])) { rasprintf(&buf, "%%patch -P %s", line + 6); } else { if (strstr(line+6, " -P") == NULL) rasprintf(&buf, "%%patch -P %d %s", INT_MAX, line + 6); /* INT_MAX denotes not numbered %patch */ else buf = xstrdup(line); /* it is not numberless patch because -P is present */ } poptParseArgvString(buf, &argc, &argv); free(buf); /* * Grab all -P<N> numbers for later processing. Stored as strings * at this point so we only have to worry about conversion in one place. */ optCon = poptGetContext(NULL, argc, argv, patchOpts, 0); while ((c = poptGetNextOpt(optCon)) > 0) { switch (c) { case 'P': { char *arg = poptGetOptArg(optCon); if (arg) { argvAdd(&patchnums, arg); free(arg); } break; } default: break; } } if (c < -1) { rpmlog(RPMLOG_ERR, _("%s: %s: %s\n"), poptStrerror(c), poptBadOption(optCon, POPT_BADOPTION_NOALIAS), line); goto exit; } /* Any trailing arguments are treated as patch numbers */ argvAppend(&patchnums, (ARGV_const_t) poptGetArgs(optCon)); /* Convert to number, generate patch command and append to %prep script */ for (patch = patchnums; *patch; patch++) { uint32_t pnum; char *s; if (parseUnsignedNum(*patch, &pnum)) { rpmlog(RPMLOG_ERR, _("Invalid patch number %s: %s\n"), *patch, line); goto exit; } s = doPatch(spec, pnum, opt_p, opt_b, opt_R, opt_E, opt_F, opt_d); if (s == NULL) { goto exit; } appendLineStringBuf(spec->prep, s); free(s); } rc = RPMRC_OK; exit: argvFree(patchnums); free(argv); poptFreeContext(optCon); return rc; }