static sepoltrans *sepoltransFree(sepoltrans * pt) { ARGV_t file; if (!pt) { return NULL; } for (file = pt->filelist; file && *file; file++) { if (unlink(*file) < 0) { rpmlog(RPMLOG_WARNING, _("Failed to remove temporary policy file %s: %s\n"), *file, strerror(errno)); } } argvFree(pt->filelist); if (pt->execsemodule) { argvFree(pt->semodargs); } else { semanage_disconnect(pt->sh); semanage_handle_destroy(pt->sh); } free(pt->semodulepath); memset(pt, 0, sizeof(*pt)); /* trash and burn */ free(pt); return NULL; }
void rpmInitMacros(rpmMacroContext mc, const char * macrofiles) { ARGV_t pattern, globs = NULL; if (macrofiles == NULL) return; argvSplit(&globs, macrofiles, ":"); for (pattern = globs; *pattern; pattern++) { ARGV_t path, files = NULL; /* Glob expand the macro file path element, expanding ~ to $HOME. */ if (rpmGlob(*pattern, NULL, &files) != 0) { continue; } /* Read macros from each file. */ for (path = files; *path; path++) { if (rpmFileHasSuffix(*path, ".rpmnew") || rpmFileHasSuffix(*path, ".rpmsave") || rpmFileHasSuffix(*path, ".rpmorig")) { continue; } (void) rpmLoadMacroFile(mc, *path); } argvFree(files); } argvFree(globs); /* Reload cmdline macros */ rpmLoadMacros(rpmCLIMacroContext, RMIL_CMDLINE); }
/*@-mustmod@*/ static void rpmgiFini(void * _gi) /*@modifies _gi @*/ { rpmgi gi = _gi; int xx; gi->hdrPath = _free(gi->hdrPath); (void)headerFree(gi->h); gi->h = NULL; gi->argv = argvFree(gi->argv); if (gi->ftsp != NULL) { xx = Fts_close(gi->ftsp); gi->ftsp = NULL; gi->fts = NULL; } if (gi->fd != NULL) { xx = Fclose(gi->fd); gi->fd = NULL; } gi->tsi = rpmtsiFree(gi->tsi); gi->mi = rpmmiFree(gi->mi); (void)rpmtsFree(gi->ts); gi->ts = NULL; }
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 int loadKeyringFromFiles(rpmts ts) { ARGV_t files = NULL; /* XXX TODO: deal with chroot path issues */ char *pkpath = rpmGetPath(ts->rootDir, "%{_keyringpath}/*.key", NULL); int nkeys = 0; rpmlog(RPMLOG_DEBUG, "loading keyring from pubkeys in %s\n", pkpath); if (rpmGlob(pkpath, NULL, &files)) { rpmlog(RPMLOG_DEBUG, "couldn't find any keys in %s\n", pkpath); goto exit; } for (char **f = files; *f; f++) { rpmPubkey key = rpmPubkeyRead(*f); if (!key) { rpmlog(RPMLOG_ERR, _("%s: reading of public key failed.\n"), *f); continue; } if (rpmKeyringAddKey(ts->keyring, key) == 0) { nkeys++; rpmlog(RPMLOG_DEBUG, "added key %s to keyring\n", *f); } rpmPubkeyFree(key); } exit: free(pkpath); argvFree(files); return nkeys; }
char * _RequestPass(/*@unused@*/ const char * prompt) { /*@only@*/ /*@relnull@*/ static char * password = NULL; #if defined(HAVE_KEYUTILS_H) const char * foo = "user rpm:yyyy spoon"; ARGV_t av = NULL; int xx = argvSplit(&av, foo, NULL); key_serial_t dest = 0; key_serial_t key = 0; if (password != NULL) { free(password); password = NULL; } assert(av != NULL); assert(av[0] != NULL); assert(av[1] != NULL); assert(av[2] != NULL); key = request_key(av[0], av[1], av[2], dest); av = argvFree(av); /*@-nullstate@*/ /* XXX *password may be null. */ xx = keyctl_read_alloc(key, (void **)&password); /*@=nullstate@*/ if (password == NULL) password = (char *) ""; #endif /* HAVE_KEYUTILS_H */ /*@-statictrans@*/ return password; /*@=statictrans@*/ }
/*@-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 void rpmrubyFini(void * _ruby) /*@globals fileSystem @*/ /*@modifies *_ruby, fileSystem @*/ { rpmruby ruby = _ruby; /* XXX FIXME: 0x40000000 => xruby.c wrapper without interpreter. */ if (ruby->flags & 0x40000000) { ruby->main_coroutine_lock = yarnFreeLock(ruby->main_coroutine_lock); ruby->ruby_coroutine_lock = yarnFreeLock(ruby->ruby_coroutine_lock); ruby->zlog = rpmzLogDump(ruby->zlog, NULL); ruby->stack = _free(ruby->stack); ruby->nstack = 0; _rpmrubyI = NULL; } else { #if defined(WITH_RUBYEMBED) ruby_finalize(); ruby_cleanup(0); #endif } ruby->I = NULL; ruby->flags = 0; ruby->av = argvFree(ruby->av); ruby->ac = 0; }
rpmRC rpmtsSetupTransactionPlugins(rpmts ts) { rpmRC rc = RPMRC_OK; ARGV_t files = NULL; int nfiles = 0; char *dsoPath = NULL; /* * Assume allocated equals initialized. There are some oddball cases * (verification of non-installed package) where this is not true * currently but that's not a new issue. */ if ((rpmtsFlags(ts) & RPMTRANS_FLAG_NOPLUGINS) || ts->plugins != NULL) return RPMRC_OK; dsoPath = rpmExpand("%{__plugindir}/*.so", NULL); if (rpmGlob(dsoPath, &nfiles, &files) == 0) { rpmPlugins tsplugins = rpmtsPlugins(ts); for (int i = 0; i < nfiles; i++) { char *bn = basename(files[i]); bn[strlen(bn)-strlen(".so")] = '\0'; if (rpmpluginsAddPlugin(tsplugins, "transaction", bn) == RPMRC_FAIL) rc = RPMRC_FAIL; } files = argvFree(files); } free(dsoPath); return rc; }
int parsePrep(rpmSpec spec) { int nextPart, res, rc; StringBuf sb; char **lines; ARGV_t saveLines = NULL; if (spec->prep != NULL) { rpmlog(RPMLOG_ERR, _("line %d: second %%prep\n"), spec->lineNum); return PART_ERROR; } spec->prep = newStringBuf(); /* There are no options to %prep */ if ((rc = readLine(spec, STRIP_NOTHING)) > 0) { return PART_NONE; } else if (rc < 0) { return PART_ERROR; } sb = newStringBuf(); while (! (nextPart = isPart(spec->line))) { /* Need to expand the macros inline. That way we */ /* can give good line number information on error. */ appendStringBuf(sb, spec->line); if ((rc = readLine(spec, STRIP_NOTHING)) > 0) { nextPart = PART_NONE; break; } else if (rc < 0) { goto exit; } } saveLines = argvSplitString(getStringBuf(sb), "\n", ARGV_NONE); for (lines = saveLines; *lines; lines++) { res = 0; if (rstreqn(*lines, "%setup", sizeof("%setup")-1)) { res = doSetupMacro(spec, *lines); } else if (rstreqn(*lines, "%patch", sizeof("%patch")-1)) { res = doPatchMacro(spec, *lines); } else { appendLineStringBuf(spec->prep, *lines); } if (res && !spec->force) { /* fixup from RPMRC_FAIL do*Macro() codes for now */ nextPart = PART_ERROR; goto exit; } } res = nextPart; exit: argvFree(saveLines); sb = freeStringBuf(sb); return nextPart; }
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; }
/*@null@*/ static rpmdict rpmdictFree(/*@only@*/ rpmdict dict) { if (dict != NULL) { dict->ht = (dict->ht ? htFree(dict->ht) : NULL); dict->av = argvFree(dict->av); dict = _free(dict); } return NULL; }
rpmts rpmtsFree(rpmts ts) { tsMembers tsmem = rpmtsMembers(ts); if (ts == NULL) return NULL; if (ts->nrefs > 1) return rpmtsUnlink(ts); rpmtsEmpty(ts); (void) rpmtsCloseDB(ts); tsmem->removedPackages = removedHashFree(tsmem->removedPackages); tsmem->order = _free(tsmem->order); ts->members = _free(ts->members); ts->dsi = _free(ts->dsi); if (ts->scriptFd != NULL) { ts->scriptFd = fdFree(ts->scriptFd); ts->scriptFd = NULL; } ts->rootDir = _free(ts->rootDir); ts->lockPath = _free(ts->lockPath); ts->lock = rpmlockFree(ts->lock); ts->keyring = rpmKeyringFree(ts->keyring); ts->netsharedPaths = argvFree(ts->netsharedPaths); ts->installLangs = argvFree(ts->installLangs); ts->plugins = rpmpluginsFree(ts->plugins); if (_rpmts_stats) rpmtsPrintStats(ts); (void) rpmtsUnlink(ts); ts = _free(ts); return NULL; }
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 rpm_macros(lua_State *L) /*@modifies L @*/ { const char ** av = NULL; int ac = 0; int i; /*@-modunconnomods@*/ lua_newtable(L); /*@=modunconnomods@*/ /*@-globs@*/ ac = rpmGetMacroEntries(NULL, NULL, -1, &av); /*@=globs@*/ if (av != NULL) for (i = 0; i < ac; i++) { char *n, *o, *b; /* Parse out "%name(opts)\tbody" into n/o/b strings. */ n = (char *) av[i]; b = strchr(n, '\t'); assert(b != NULL); o = ((b > n && b[-1] == ')') ? strchr(n, '(') : NULL); if (*n == '%') n++; if (o != NULL && *o == '(') { b[-1] = '\0'; o++; o[-1] = '\0'; } else b[0] = '\0'; b++; /*@-modunconnomods@*/ lua_pushstring(L, n); lua_newtable(L); if (o) { lua_pushstring(L, "opts"); lua_pushstring(L, o); lua_settable(L, -3); } if (b) { lua_pushstring(L, "body"); lua_pushstring(L, b); lua_settable(L, -3); } lua_settable(L, -3); /*@=modunconnomods@*/ } av = argvFree(av); return 1; }
static ModuleRec freeModule(ModuleRec mod) { if (mod) { _free(mod->path); _free(mod->data); _free(mod->name); argvFree(mod->types); _free(mod); } return NULL; }
static sepol *sepolFree(sepol * pol) { while (pol) { sepol *next = pol->next; pol->data = _free(pol->data); pol->name = _free(pol->name); pol->types = argvFree(pol->types); pol->next = NULL; _free(pol); pol = next; } return NULL; }
int main(int argc, char **argv) { poptContext optCon = rpmioInit(argc, argv, optionsTable); const char ** av = NULL; int ac; int r = -1; _rpmaug_debug = -1; if (_rpmaugLoadargv != NULL) _rpmaugLoadpath = argvJoin(_rpmaugLoadargv, PATH_SEP_CHAR); _rpmaugI = rpmaugNew(_rpmaugRoot, _rpmaugLoadpath, _rpmaugFlags); if (_rpmaugI == NULL) { fprintf(stderr, "Failed to initialize Augeas\n"); goto exit; } #if defined(WITH_READLINE) readline_init(); #endif av = poptGetArgs(optCon); ac = argvCount(av); if (ac > 0) { // Accept one command from the command line const char * cmd = argvJoin(av, ' '); const char *buf; buf = NULL; r = rpmaugRun(NULL, cmd, &buf); cmd = _free(cmd); if (buf && *buf) fprintf(stdout, "%s", buf); } else { r = main_loop(); } exit: if (_rpmaugLoadargv) _rpmaugLoadpath = _free(_rpmaugLoadpath); _rpmaugLoadargv = argvFree(_rpmaugLoadargv); _rpmaugI = rpmaugFree(_rpmaugI); optCon = rpmioFini(optCon); return (r == 0 ? EXIT_SUCCESS : EXIT_FAILURE); }
/** * 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; }
int argvSplit(ARGV_t * argvp, const char * str, const char * seps) { static char whitespace[] = " \f\n\r\t\v"; char * dest = xmalloc(strlen(str) + 1); ARGV_t argv; int argc = 1; const char * s; char * t; int c; if (seps == NULL) seps = whitespace; for (argc = 1, s = str, t = dest; (c = (int) *s); s++, t++) { if (strchr(seps, c) && !(s[0] == ':' && s[1] == '/' && s[2] == '/')) { argc++; c = (int) '\0'; } *t = (char) c; } *t = '\0'; argv = xmalloc( (argc + 1) * sizeof(*argv)); for (c = 0, s = dest; s < t; s += strlen(s) + 1) { /* XXX Skip repeated seperators (i.e. whitespace). */ if (seps == whitespace && s[0] == '\0') continue; argv[c++] = xstrdup(s); } argv[c] = NULL; if (argvp) *argvp = argv; else argv = argvFree(argv); dest = _free(dest); /*@-nullstate@*/ return 0; /*@=nullstate@*/ }
/** * Append globbed arg list to iterator. * @param gi generalized iterator * @param argv arg list to be globbed (or NULL) * @returns RPMRC_OK on success */ static rpmRC rpmgiGlobArgv(rpmgi gi, /*@null@*/ ARGV_t argv) /*@globals internalState @*/ /*@modifies gi, internalState @*/ { const char * arg; rpmRC rpmrc = RPMRC_OK; int ac = 0; int xx; /* XXX Expand globs only if requested or for gi specific tags */ if ((gi->flags & RPMGI_NOGLOB) || !(gi->tag == RPMDBI_HDLIST || gi->tag == RPMDBI_ARGLIST || gi->tag == RPMDBI_FTSWALK)) { if (argv != NULL) { while (argv[ac] != NULL) ac++; /*@-nullstate@*/ /* XXX argv is not NULL */ xx = argvAppend(&gi->argv, argv); /*@=nullstate@*/ } gi->argc = ac; return rpmrc; } if (argv != NULL) while ((arg = *argv++) != NULL) { const char * t = rpmgiEscapeSpaces(arg); ARGV_t av = NULL; xx = rpmGlob(t, &ac, &av); xx = argvAppend(&gi->argv, av); gi->argc += ac; av = argvFree(av); t = _free(t); ac = 0; } return rpmrc; }
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; }
int rpmMkdirs(const char *root, const char *pathstr) { ARGV_t dirs = NULL; int rc = 0; argvSplit(&dirs, pathstr, ":"); for (char **d = dirs; *d; d++) { char *path = rpmGetPath(root ? root : "", *d, NULL); if ((rc = rpmioMkpath(path, 0755, -1, -1)) != 0) { const char *msg = _("failed to create directory"); /* try to be more informative if the failing part was a macro */ if (**d == '%') { rpmlog(RPMLOG_ERR, "%s %s: %s: %m\n", msg, *d, path); } else { rpmlog(RPMLOG_ERR, "%s %s: %m\n", msg, path); } } free(path); if (rc) break; } argvFree(dirs); return rc; }
static int tgetFini(rpmtget tget) { int rc = 0; if (tget->sop) { rpmswPrint("stat:", tget->sop, NULL); tget->sop = _free(tget->sop); } if (tget->gop) { rpmswPrint(" get:", tget->gop, NULL); tget->gop = _free(tget->gop); } tget->buf = _free(tget->buf); tget->nbuf = 0; if (tget->fd) (void) Fclose(tget->fd); tget->fd = NULL; argvPrint(tget->uri, tget->av, NULL); tget->av = argvFree(tget->av); 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; }
/** @todo Generalize --freshen policies. */ int rpmInstall(rpmts ts, struct rpmInstallArguments_s * ia, ARGV_t fileArgv) { struct rpmEIU * eiu = xcalloc(1, sizeof(*eiu)); rpmRelocation * relocations; char * fileURL = NULL; rpmVSFlags vsflags, ovsflags; int rc; int i; vsflags = setvsFlags(ia); ovsflags = rpmtsSetVSFlags(ts, (vsflags | RPMVSF_NEEDPAYLOAD)); if (fileArgv == NULL) goto exit; (void) rpmtsSetFlags(ts, ia->transFlags); relocations = ia->relocations; setNotifyFlag(ia, ts); if ((eiu->relocations = relocations) != NULL) { while (eiu->relocations->oldPath) eiu->relocations++; if (eiu->relocations->newPath == NULL) eiu->relocations = NULL; } /* Build fully globbed list of arguments in argv[argc]. */ for (eiu->fnp = fileArgv; *eiu->fnp != NULL; eiu->fnp++) { ARGV_t av = NULL; int ac = 0; if (giFlags & RPMGI_NOGLOB) { rc = rpmNoGlob(*eiu->fnp, &ac, &av); } else { char * fn = rpmEscapeSpaces(*eiu->fnp); rc = rpmGlob(fn, &ac, &av); fn = _free(fn); } if (rc || ac == 0) { if (giFlags & RPMGI_NOGLOB) { rpmlog(RPMLOG_ERR, _("File not found: %s\n"), *eiu->fnp); } else { rpmlog(RPMLOG_ERR, _("File not found by glob: %s\n"), *eiu->fnp); } eiu->numFailed++; continue; } argvAppend(&(eiu->argv), av); argvFree(av); eiu->argc += ac; } restart: /* Allocate sufficient storage for next set of args. */ if (eiu->pkgx >= eiu->numPkgs) { eiu->numPkgs = eiu->pkgx + eiu->argc; eiu->pkgURL = xrealloc(eiu->pkgURL, (eiu->numPkgs + 1) * sizeof(*eiu->pkgURL)); memset(eiu->pkgURL + eiu->pkgx, 0, ((eiu->argc + 1) * sizeof(*eiu->pkgURL))); eiu->pkgState = xrealloc(eiu->pkgState, (eiu->numPkgs + 1) * sizeof(*eiu->pkgState)); memset(eiu->pkgState + eiu->pkgx, 0, ((eiu->argc + 1) * sizeof(*eiu->pkgState))); } /* Retrieve next set of args, cache on local storage. */ for (i = 0; i < eiu->argc; i++) { fileURL = _free(fileURL); fileURL = eiu->argv[i]; eiu->argv[i] = NULL; switch (urlIsURL(fileURL)) { case URL_IS_HTTPS: case URL_IS_HTTP: case URL_IS_FTP: { char *tfn = NULL; FD_t tfd; if (rpmIsVerbose()) fprintf(stdout, _("Retrieving %s\n"), fileURL); tfd = rpmMkTempFile(rpmtsRootDir(ts), &tfn); if (tfd && tfn) { Fclose(tfd); rc = urlGetFile(fileURL, tfn); } else { rc = -1; } if (rc != 0) { rpmlog(RPMLOG_ERR, _("skipping %s - transfer failed\n"), fileURL); eiu->numFailed++; eiu->pkgURL[eiu->pkgx] = NULL; tfn = _free(tfn); break; } eiu->pkgState[eiu->pkgx] = 1; eiu->pkgURL[eiu->pkgx] = tfn; eiu->pkgx++; } break; case URL_IS_PATH: case URL_IS_DASH: /* WRONG WRONG WRONG */ case URL_IS_HKP: /* WRONG WRONG WRONG */ default: eiu->pkgURL[eiu->pkgx] = fileURL; fileURL = NULL; eiu->pkgx++; break; } } fileURL = _free(fileURL); if (eiu->numFailed) goto exit; /* Continue processing file arguments, building transaction set. */ for (eiu->fnp = eiu->pkgURL+eiu->prevx; *eiu->fnp != NULL; eiu->fnp++, eiu->prevx++) { Header h = NULL; const char * fileName; rpmlog(RPMLOG_DEBUG, "============== %s\n", *eiu->fnp); (void) urlPath(*eiu->fnp, &fileName); if (tryReadHeader(ts, eiu, &h) == RPMRC_FAIL) continue; if (eiu->rpmrc == RPMRC_NOTFOUND) { rc = tryReadManifest(eiu); if (rc == RPMRC_OK) { eiu->prevx++; goto restart; } } if (headerIsSource(h)) { if (ia->installInterfaceFlags & INSTALL_FRESHEN) { headerFree(h); continue; } rpmlog(RPMLOG_DEBUG, "\tadded source package [%d]\n", eiu->numSRPMS); eiu->sourceURL = xrealloc(eiu->sourceURL, (eiu->numSRPMS + 2) * sizeof(*eiu->sourceURL)); eiu->sourceURL[eiu->numSRPMS] = *eiu->fnp; *eiu->fnp = NULL; eiu->numSRPMS++; eiu->sourceURL[eiu->numSRPMS] = NULL; continue; } if (eiu->relocations) { struct rpmtd_s prefixes; headerGet(h, RPMTAG_PREFIXES, &prefixes, HEADERGET_DEFAULT); if (rpmtdCount(&prefixes) == 1) { eiu->relocations->oldPath = xstrdup(rpmtdGetString(&prefixes)); rpmtdFreeData(&prefixes); } else { rpmlog(RPMLOG_ERR, _("package %s is not relocatable\n"), headerGetString(h, RPMTAG_NAME)); eiu->numFailed++; goto exit; } } if (ia->installInterfaceFlags & INSTALL_FRESHEN) if (checkFreshenStatus(ts, h) != 1) { headerFree(h); continue; } if (ia->installInterfaceFlags & INSTALL_REINSTALL) rc = rpmtsAddReinstallElement(ts, h, (fnpyKey)fileName); else rc = rpmtsAddInstallElement(ts, h, (fnpyKey)fileName, (ia->installInterfaceFlags & INSTALL_UPGRADE) != 0, relocations); headerFree(h); if (eiu->relocations) eiu->relocations->oldPath = _free(eiu->relocations->oldPath); switch (rc) { case 0: rpmlog(RPMLOG_DEBUG, "\tadded binary package [%d]\n", eiu->numRPMS); break; case 1: rpmlog(RPMLOG_ERR, _("error reading from file %s\n"), *eiu->fnp); eiu->numFailed++; goto exit; break; default: eiu->numFailed++; goto exit; break; } eiu->numRPMS++; } rpmlog(RPMLOG_DEBUG, "found %d source and %d binary packages\n", eiu->numSRPMS, eiu->numRPMS); if (eiu->numFailed) goto exit; if (eiu->numRPMS) { int rc = rpmcliTransaction(ts, ia, eiu->numPkgs); if (rc < 0) eiu->numFailed += eiu->numRPMS; else if (rc > 0) eiu->numFailed += rc; } if (eiu->numSRPMS && (eiu->sourceURL != NULL)) { rpmcliProgressState = 0; rpmcliProgressTotal = 0; rpmcliProgressCurrent = 0; for (i = 0; i < eiu->numSRPMS; i++) { rpmsqPoll(); if (eiu->sourceURL[i] != NULL) { rc = RPMRC_OK; if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_TEST)) rc = rpmInstallSource(ts, eiu->sourceURL[i], NULL, NULL); if (rc != 0) eiu->numFailed++; } } } exit: if (eiu->pkgURL != NULL) { for (i = 0; i < eiu->numPkgs; i++) { if (eiu->pkgURL[i] == NULL) continue; if (eiu->pkgState[i] == 1) (void) unlink(eiu->pkgURL[i]); eiu->pkgURL[i] = _free(eiu->pkgURL[i]); } } eiu->pkgState = _free(eiu->pkgState); eiu->pkgURL = _free(eiu->pkgURL); eiu->argv = _free(eiu->argv); rc = eiu->numFailed; free(eiu); rpmtsEmpty(ts); rpmtsSetVSFlags(ts, ovsflags); return rc; }
/** @todo Generalize --freshen policies. */ int rpmInstall(rpmts ts, struct rpmInstallArguments_s * ia, ARGV_t fileArgv) { struct rpmEIU * eiu = xcalloc(1, sizeof(*eiu)); rpmps ps; rpmprobFilterFlags probFilter; rpmRelocation * relocations; char * fileURL = NULL; int stopInstall = 0; rpmVSFlags vsflags, ovsflags, tvsflags; int rc; int xx; int i; if (fileArgv == NULL) goto exit; rpmcliPackagesTotal = 0; (void) rpmtsSetFlags(ts, ia->transFlags); probFilter = ia->probFilter; relocations = ia->relocations; if (ia->installInterfaceFlags & INSTALL_UPGRADE) vsflags = rpmExpandNumeric("%{?_vsflags_erase}"); else vsflags = rpmExpandNumeric("%{?_vsflags_install}"); if (ia->qva_flags & VERIFY_DIGEST) vsflags |= _RPMVSF_NODIGESTS; if (ia->qva_flags & VERIFY_SIGNATURE) vsflags |= _RPMVSF_NOSIGNATURES; if (ia->qva_flags & VERIFY_HDRCHK) vsflags |= RPMVSF_NOHDRCHK; ovsflags = rpmtsSetVSFlags(ts, (vsflags | RPMVSF_NEEDPAYLOAD)); { int notifyFlags; notifyFlags = ia->installInterfaceFlags | (rpmIsVerbose() ? INSTALL_LABEL : 0 ); xx = rpmtsSetNotifyCallback(ts, rpmShowProgress, (void *) ((long)notifyFlags)); } if ((eiu->relocations = relocations) != NULL) { while (eiu->relocations->oldPath) eiu->relocations++; if (eiu->relocations->newPath == NULL) eiu->relocations = NULL; } /* Build fully globbed list of arguments in argv[argc]. */ for (eiu->fnp = fileArgv; *eiu->fnp != NULL; eiu->fnp++) { ARGV_t av = NULL; int ac = 0; char * fn; fn = rpmEscapeSpaces(*eiu->fnp); rc = rpmGlob(fn, &ac, &av); fn = _free(fn); if (rc || ac == 0) { rpmlog(RPMLOG_ERR, _("File not found by glob: %s\n"), *eiu->fnp); eiu->numFailed++; continue; } argvAppend(&(eiu->argv), av); argvFree(av); eiu->argc += ac; } restart: /* Allocate sufficient storage for next set of args. */ if (eiu->pkgx >= eiu->numPkgs) { eiu->numPkgs = eiu->pkgx + eiu->argc; eiu->pkgURL = xrealloc(eiu->pkgURL, (eiu->numPkgs + 1) * sizeof(*eiu->pkgURL)); memset(eiu->pkgURL + eiu->pkgx, 0, ((eiu->argc + 1) * sizeof(*eiu->pkgURL))); eiu->pkgState = xrealloc(eiu->pkgState, (eiu->numPkgs + 1) * sizeof(*eiu->pkgState)); memset(eiu->pkgState + eiu->pkgx, 0, ((eiu->argc + 1) * sizeof(*eiu->pkgState))); } /* Retrieve next set of args, cache on local storage. */ for (i = 0; i < eiu->argc; i++) { fileURL = _free(fileURL); fileURL = eiu->argv[i]; eiu->argv[i] = NULL; switch (urlIsURL(fileURL)) { case URL_IS_HTTPS: case URL_IS_HTTP: case URL_IS_FTP: { char *tfn; FD_t tfd; if (rpmIsVerbose()) fprintf(stdout, _("Retrieving %s\n"), fileURL); tfd = rpmMkTempFile(rpmtsRootDir(ts), &tfn); if (tfd && tfn) { Fclose(tfd); rc = urlGetFile(fileURL, tfn); } else { rc = -1; } if (rc != 0) { rpmlog(RPMLOG_ERR, _("skipping %s - transfer failed\n"), fileURL); eiu->numFailed++; eiu->pkgURL[eiu->pkgx] = NULL; tfn = _free(tfn); break; } eiu->pkgState[eiu->pkgx] = 1; eiu->pkgURL[eiu->pkgx] = tfn; eiu->pkgx++; } break; case URL_IS_PATH: case URL_IS_DASH: /* WRONG WRONG WRONG */ case URL_IS_HKP: /* WRONG WRONG WRONG */ default: eiu->pkgURL[eiu->pkgx] = fileURL; fileURL = NULL; eiu->pkgx++; break; } } fileURL = _free(fileURL); if (eiu->numFailed) goto exit; /* Continue processing file arguments, building transaction set. */ for (eiu->fnp = eiu->pkgURL+eiu->prevx; *eiu->fnp != NULL; eiu->fnp++, eiu->prevx++) { const char * fileName; rpmlog(RPMLOG_DEBUG, "============== %s\n", *eiu->fnp); (void) urlPath(*eiu->fnp, &fileName); /* Try to read the header from a package file. */ eiu->fd = Fopen(*eiu->fnp, "r.ufdio"); if (eiu->fd == NULL || Ferror(eiu->fd)) { rpmlog(RPMLOG_ERR, _("open of %s failed: %s\n"), *eiu->fnp, Fstrerror(eiu->fd)); if (eiu->fd != NULL) { xx = Fclose(eiu->fd); eiu->fd = NULL; } eiu->numFailed++; *eiu->fnp = NULL; continue; } /* Read the header, verifying signatures (if present). */ tvsflags = rpmtsSetVSFlags(ts, vsflags); eiu->rpmrc = rpmReadPackageFile(ts, eiu->fd, *eiu->fnp, &eiu->h); tvsflags = rpmtsSetVSFlags(ts, tvsflags); xx = Fclose(eiu->fd); eiu->fd = NULL; switch (eiu->rpmrc) { case RPMRC_FAIL: rpmlog(RPMLOG_ERR, _("%s cannot be installed\n"), *eiu->fnp); eiu->numFailed++; *eiu->fnp = NULL; continue; break; case RPMRC_NOTFOUND: goto maybe_manifest; break; case RPMRC_NOTTRUSTED: case RPMRC_NOKEY: case RPMRC_OK: default: break; } eiu->isSource = headerIsSource(eiu->h); if (eiu->isSource) { rpmlog(RPMLOG_DEBUG, "\tadded source package [%d]\n", eiu->numSRPMS); eiu->sourceURL = xrealloc(eiu->sourceURL, (eiu->numSRPMS + 2) * sizeof(*eiu->sourceURL)); eiu->sourceURL[eiu->numSRPMS] = *eiu->fnp; *eiu->fnp = NULL; eiu->numSRPMS++; eiu->sourceURL[eiu->numSRPMS] = NULL; continue; } if (eiu->relocations) { struct rpmtd_s prefixes; headerGet(eiu->h, RPMTAG_PREFIXES, &prefixes, HEADERGET_DEFAULT); if (rpmtdCount(&prefixes) == 1) { eiu->relocations->oldPath = xstrdup(rpmtdGetString(&prefixes)); rpmtdFreeData(&prefixes); } else { const char * name; xx = headerNVR(eiu->h, &name, NULL, NULL); rpmlog(RPMLOG_ERR, _("package %s is not relocatable\n"), name); eiu->numFailed++; goto exit; } } /* On --freshen, verify package is installed and newer */ if (ia->installInterfaceFlags & INSTALL_FRESHEN) { rpmdbMatchIterator mi; const char * name; Header oldH; int count; xx = headerNVR(eiu->h, &name, NULL, NULL); mi = rpmtsInitIterator(ts, RPMTAG_NAME, name, 0); count = rpmdbGetIteratorCount(mi); while ((oldH = rpmdbNextIterator(mi)) != NULL) { if (rpmVersionCompare(oldH, eiu->h) < 0) continue; /* same or newer package already installed */ count = 0; break; } mi = rpmdbFreeIterator(mi); if (count == 0) { eiu->h = headerFree(eiu->h); continue; } /* Package is newer than those currently installed. */ } rc = rpmtsAddInstallElement(ts, eiu->h, (fnpyKey)fileName, (ia->installInterfaceFlags & INSTALL_UPGRADE) != 0, relocations); /* XXX reference held by transaction set */ eiu->h = headerFree(eiu->h); if (eiu->relocations) eiu->relocations->oldPath = _free(eiu->relocations->oldPath); switch(rc) { case 0: rpmlog(RPMLOG_DEBUG, "\tadded binary package [%d]\n", eiu->numRPMS); break; case 1: rpmlog(RPMLOG_ERR, _("error reading from file %s\n"), *eiu->fnp); eiu->numFailed++; goto exit; break; case 2: rpmlog(RPMLOG_ERR, _("file %s requires a newer version of RPM\n"), *eiu->fnp); eiu->numFailed++; goto exit; break; default: eiu->numFailed++; goto exit; break; } eiu->numRPMS++; continue; maybe_manifest: /* Try to read a package manifest. */ eiu->fd = Fopen(*eiu->fnp, "r.fpio"); if (eiu->fd == NULL || Ferror(eiu->fd)) { rpmlog(RPMLOG_ERR, _("open of %s failed: %s\n"), *eiu->fnp, Fstrerror(eiu->fd)); if (eiu->fd != NULL) { xx = Fclose(eiu->fd); eiu->fd = NULL; } eiu->numFailed++; *eiu->fnp = NULL; break; } /* Read list of packages from manifest. */ /* FIX: *eiu->argv can be NULL */ rc = rpmReadPackageManifest(eiu->fd, &eiu->argc, &eiu->argv); if (rc != RPMRC_OK) rpmlog(RPMLOG_ERR, _("%s: not an rpm package (or package manifest): %s\n"), *eiu->fnp, Fstrerror(eiu->fd)); xx = Fclose(eiu->fd); eiu->fd = NULL; /* If successful, restart the query loop. */ if (rc == RPMRC_OK) { eiu->prevx++; goto restart; } eiu->numFailed++; *eiu->fnp = NULL; break; } rpmlog(RPMLOG_DEBUG, "found %d source and %d binary packages\n", eiu->numSRPMS, eiu->numRPMS); if (eiu->numFailed) goto exit; if (eiu->numRPMS && !(ia->installInterfaceFlags & INSTALL_NODEPS)) { if (rpmtsCheck(ts)) { eiu->numFailed = eiu->numPkgs; stopInstall = 1; } ps = rpmtsProblems(ts); if (!stopInstall && rpmpsNumProblems(ps) > 0) { rpmlog(RPMLOG_ERR, _("Failed dependencies:\n")); rpmpsPrint(NULL, ps); eiu->numFailed = eiu->numPkgs; stopInstall = 1; } ps = rpmpsFree(ps); } if (eiu->numRPMS && !(ia->installInterfaceFlags & INSTALL_NOORDER)) { if (rpmtsOrder(ts)) { eiu->numFailed = eiu->numPkgs; stopInstall = 1; } } if (eiu->numRPMS && !stopInstall) { rpmcliPackagesTotal += eiu->numSRPMS; rpmlog(RPMLOG_DEBUG, "installing binary packages\n"); /* Drop added/available package indices and dependency sets. */ rpmtsClean(ts); rc = rpmtsRun(ts, NULL, probFilter); ps = rpmtsProblems(ts); if (rc < 0) { eiu->numFailed += eiu->numRPMS; } else if (rc > 0) { eiu->numFailed += rc; if (rpmpsNumProblems(ps) > 0) rpmpsPrint(stderr, ps); } ps = rpmpsFree(ps); } if (eiu->numSRPMS && !stopInstall) { if (eiu->sourceURL != NULL) for (i = 0; i < eiu->numSRPMS; i++) { rpmdbCheckSignals(); if (eiu->sourceURL[i] == NULL) continue; eiu->fd = Fopen(eiu->sourceURL[i], "r.ufdio"); if (eiu->fd == NULL || Ferror(eiu->fd)) { rpmlog(RPMLOG_ERR, _("cannot open file %s: %s\n"), eiu->sourceURL[i], Fstrerror(eiu->fd)); if (eiu->fd != NULL) { xx = Fclose(eiu->fd); eiu->fd = NULL; } continue; } if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_TEST)) { eiu->rpmrc = rpmInstallSourcePackage(ts, eiu->fd, NULL, NULL); if (eiu->rpmrc != RPMRC_OK) eiu->numFailed++; } xx = Fclose(eiu->fd); eiu->fd = NULL; } } exit: if (eiu->pkgURL != NULL) for (i = 0; i < eiu->numPkgs; i++) { if (eiu->pkgURL[i] == NULL) continue; if (eiu->pkgState[i] == 1) (void) unlink(eiu->pkgURL[i]); eiu->pkgURL[i] = _free(eiu->pkgURL[i]); } eiu->pkgState = _free(eiu->pkgState); eiu->pkgURL = _free(eiu->pkgURL); eiu->argv = _free(eiu->argv); rc = eiu->numFailed; free(eiu); rpmtsEmpty(ts); 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; }
static void ruleFree(struct matchRule *rule) { regFree(rule->path); regFree(rule->magic); argvFree(rule->flags); }