int rpmPkgSign(const char *path, const struct rpmSignArgs * args) { int rc; if (args) { if (args->hashalgo) { char *algo = NULL; rasprintf(&algo, "%d", args->hashalgo); addMacro(NULL, "_gpg_digest_algo", NULL, algo, RMIL_GLOBAL); free(algo); } if (args->keyid) { addMacro(NULL, "_gpg_name", NULL, args->keyid, RMIL_GLOBAL); } } rc = rpmSign(path, 0, args->signfiles); if (args) { if (args->hashalgo) { delMacro(NULL, "_gpg_digest_algo"); } if (args->keyid) { delMacro(NULL, "_gpg_name"); } } return rc; }
/** * Define or undefine per-header macros. * @param h header * @param define define/undefine? * @return 0 always */ static void rpmInstallLoadMacros(Header h, int define) { const struct tagMacro * tagm; for (tagm = tagMacros; tagm->macroname != NULL; tagm++) { struct rpmtd_s td; char *body; if (!headerGet(h, tagm->tag, &td, HEADERGET_DEFAULT)) continue; /* * Undefine doesn't need the actual data for anything, but * this way ensures we only undefine what was defined earlier. */ switch (rpmtdType(&td)) { default: if (define) { body = rpmtdFormat(&td, RPMTD_FORMAT_STRING, NULL); addMacro(NULL, tagm->macroname, NULL, body, -1); free(body); } else { delMacro(NULL, tagm->macroname); } break; case RPM_NULL_TYPE: break; } rpmtdFreeData(&td); } }
/** * Parse (and execute) macro undefinition. * @param mc macro context * @param se macro name to undefine * @return address to continue parsing */ static const char * doUndefine(rpmMacroContext mc, const char * se) { const char *s = se; char *buf = xmalloc(MACROBUFSIZ); char *n = buf, *ne = n; int c; COPYNAME(ne, s, c); /* Move scan over body */ while (iseol(*s)) s++; se = s; /* Names must start with alphabetic or _ and be at least 3 chars */ if (!((c = *n) && (risalpha(c) || c == '_') && (ne - n) > 2)) { rpmlog(RPMLOG_ERR, _("Macro %%%s has illegal name (%%undefine)\n"), n); goto exit; } delMacro(mc, n); exit: _free(buf); return se; }
PyObject * rpmmacro_DelMacro(PyObject * self, PyObject * args, PyObject * kwds) { char * name; char * kwlist[] = {"name", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwds, "s:DelMacro", kwlist, &name)) return NULL; delMacro(NULL, name); Py_RETURN_NONE; }
PyObject * rpmmacro_DelMacro(/*@unused@*/ PyObject * s, PyObject * args, PyObject * kwds) { char * name; char * kwlist[] = {"name", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwds, "s:DelMacro", kwlist, &name)) return NULL; delMacro(NULL, name); Py_INCREF(Py_None); return Py_None; }
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; }
/* * @todo Single use by %%doc in files.c prevents static. */ rpmRC doScript(Spec spec, int what, const char *name, rpmiob iob, int test) { const char * rootURL = spec->rootURL; const char * rootDir; const char * scriptName = NULL; const char * buildDirURL = rpmGenPath(rootURL, "%{_builddir}", ""); const char * buildScript; const char * buildCmd = NULL; const char * buildTemplate = NULL; const char * buildPost = NULL; const char * mTemplate = NULL; const char * mCmd = NULL; const char * mPost = NULL; int argc = 0; const char **argv = NULL; FILE * fp = NULL; urlinfo u = NULL; rpmop op = NULL; int ix = -1; FD_t fd; FD_t xfd; int status; rpmRC rc; size_t i; switch (what) { case RPMBUILD_PREP: name = "%prep"; iob = spec->prep; op = memset(alloca(sizeof(*op)), 0, sizeof(*op)); ix = RPMSCRIPT_PREP; mTemplate = "%{__spec_prep_template}"; mPost = "%{__spec_prep_post}"; mCmd = "%{__spec_prep_cmd}"; break; case RPMBUILD_BUILD: name = "%build"; iob = spec->build; op = memset(alloca(sizeof(*op)), 0, sizeof(*op)); ix = RPMSCRIPT_BUILD; mTemplate = "%{__spec_build_template}"; mPost = "%{__spec_build_post}"; mCmd = "%{__spec_build_cmd}"; break; case RPMBUILD_INSTALL: name = "%install"; iob = spec->install; op = memset(alloca(sizeof(*op)), 0, sizeof(*op)); ix = RPMSCRIPT_INSTALL; mTemplate = "%{__spec_install_template}"; mPost = "%{__spec_install_post}"; mCmd = "%{__spec_install_cmd}"; break; case RPMBUILD_CHECK: name = "%check"; iob = spec->check; op = memset(alloca(sizeof(*op)), 0, sizeof(*op)); ix = RPMSCRIPT_CHECK; mTemplate = "%{__spec_check_template}"; mPost = "%{__spec_check_post}"; mCmd = "%{__spec_check_cmd}"; break; case RPMBUILD_CLEAN: name = "%clean"; iob = spec->clean; mTemplate = "%{__spec_clean_template}"; mPost = "%{__spec_clean_post}"; mCmd = "%{__spec_clean_cmd}"; break; case RPMBUILD_RMBUILD: name = "--clean"; mTemplate = "%{__spec_clean_template}"; mPost = "%{__spec_clean_post}"; mCmd = "%{__spec_clean_cmd}"; break; /* support "%track" script/section */ case RPMBUILD_TRACK: name = "%track"; iob = NULL; if (spec->foo) for (i = 0; i < spec->nfoo; i++) { if (spec->foo[i].str == NULL || spec->foo[i].iob == NULL) continue; if (xstrcasecmp(spec->foo[i].str, "track")) continue; iob = spec->foo[i].iob; /*@loopbreak@*/ break; } mTemplate = "%{__spec_track_template}"; mPost = "%{__spec_track_post}"; mCmd = "%{__spec_track_cmd}"; break; case RPMBUILD_STRINGBUF: default: mTemplate = "%{___build_template}"; mPost = "%{___build_post}"; mCmd = "%{___build_cmd}"; break; } assert(name != NULL); if ((what != RPMBUILD_RMBUILD) && iob == NULL) { rc = RPMRC_OK; goto exit; } if (rpmTempFile(rootURL, &scriptName, &fd) || fd == NULL || Ferror(fd)) { rpmlog(RPMLOG_ERR, _("Unable to open temp file.\n")); rc = RPMRC_FAIL; goto exit; } if (fdGetFp(fd) == NULL) xfd = Fdopen(fd, "w.fpio"); else xfd = fd; /*@-type@*/ /* FIX: cast? */ if ((fp = fdGetFp(xfd)) == NULL) { rc = RPMRC_FAIL; goto exit; } /*@=type@*/ (void) urlPath(rootURL, &rootDir); if (*rootDir == '\0') rootDir = "/"; (void) urlPath(scriptName, &buildScript); buildTemplate = rpmExpand(mTemplate, NULL); buildPost = rpmExpand(mPost, NULL); (void) fputs(buildTemplate, fp); /* support "%track" script/section */ if (what != RPMBUILD_PREP && what != RPMBUILD_RMBUILD && spec->buildSubdir && what != RPMBUILD_TRACK) fprintf(fp, "cd '%s'\n", spec->buildSubdir); if (what == RPMBUILD_RMBUILD) { if (spec->buildSubdir) fprintf(fp, "rm -rf '%s'\n", spec->buildSubdir); } else if (iob != NULL) fprintf(fp, "%s", rpmiobStr(iob)); (void) fputs(buildPost, fp); (void) Fclose(xfd); if (test) { rc = RPMRC_OK; goto exit; } if (buildDirURL && buildDirURL[0] != '/' && (urlSplit(buildDirURL, &u) != 0)) { rc = RPMRC_FAIL; goto exit; } switch (urlType(u)) { case URL_IS_HTTPS: case URL_IS_HTTP: case URL_IS_FTP: addMacro(spec->macros, "_remsh", NULL, "%{__remsh}", RMIL_SPEC); addMacro(spec->macros, "_remhost", NULL, u->host, RMIL_SPEC); if (strcmp(rootDir, "/")) addMacro(spec->macros, "_remroot", NULL, rootDir, RMIL_SPEC); break; case URL_IS_UNKNOWN: case URL_IS_DASH: case URL_IS_PATH: case URL_IS_HKP: default: break; } buildCmd = rpmExpand(mCmd, " ", buildScript, NULL); (void) poptParseArgvString(buildCmd, &argc, &argv); if (what != RPMBUILD_TRACK) /* support "%track" script/section */ rpmlog(RPMLOG_NOTICE, _("Executing(%s): %s\n"), name, buildCmd); /* Run the script with a stopwatch. */ if (op != NULL) (void) rpmswEnter(op, 0); status = rpmsqExecve(argv); if (ix >= 0 && ix < RPMSCRIPT_MAX) spec->sstates[ix] = (RPMSCRIPT_STATE_EXEC | RPMSCRIPT_STATE_REAPED) | (status & 0xffff); if (!WIFEXITED(status) || WEXITSTATUS(status)) { rpmlog(RPMLOG_ERR, _("Bad exit status from %s (%s)\n"), scriptName, name); rc = RPMRC_FAIL; } else rc = RPMRC_OK; if (op != NULL) { static unsigned int scale = 1000; (void) rpmswExit(op, 0); if (ix >= 0 && ix < RPMSCRIPT_MAX) spec->smetrics[ix] += op->usecs / scale; } exit: if (scriptName) { #if defined(RPM_VENDOR_OPENPKG) /* always-remove-tempfiles */ /* Unconditionally remove temporary files ("rpm-tmp.XXXXX") which were generated for the executed scripts. In OpenPKG we run the scripts in debug mode ("set -x") anyway, so we never need to see the whole generated script -- not even if it breaks. Instead we would just have temporary files staying around forever. */ #else if (rc == RPMRC_OK) #endif (void) Unlink(scriptName); scriptName = _free(scriptName); } switch (urlType(u)) { case URL_IS_HTTPS: case URL_IS_HTTP: case URL_IS_FTP: delMacro(spec->macros, "_remsh"); delMacro(spec->macros, "_remhost"); if (strcmp(rootDir, "/")) delMacro(spec->macros, "_remroot"); break; case URL_IS_UNKNOWN: case URL_IS_DASH: case URL_IS_PATH: case URL_IS_HKP: default: break; } argv = _free(argv); buildCmd = _free(buildCmd); buildTemplate = _free(buildTemplate); buildPost = _free(buildPost); buildDirURL = _free(buildDirURL); return rc; }
static void rpmcliAllArgCallback( poptContext con, enum poptCallbackReason reason, const struct poptOption * opt, const char * arg, const void * data) { /* XXX avoid accidental collisions with POPT_BIT_SET for flags */ if (opt->arg == NULL) switch (opt->val) { case 'q': rpmSetVerbosity(RPMLOG_WARNING); break; case 'v': rpmIncreaseVerbosity(); break; case POPT_PREDEFINE: (void) rpmDefineMacro(NULL, arg, RMIL_CMDLINE); break; case 'D': { char *s, *t; /* XXX Convert '-' in macro name to underscore, skip leading %. */ s = t = xstrdup(arg); while (*t && !risspace(*t)) { if (*t == '-') *t = '_'; t++; } t = s; if (*t == '%') t++; /* XXX Predefine macro if not initialized yet. */ if (rpmcliInitialized < 0) (void) rpmDefineMacro(NULL, t, RMIL_CMDLINE); rpmcliConfigured(); (void) rpmDefineMacro(NULL, t, RMIL_CMDLINE); (void) rpmDefineMacro(rpmCLIMacroContext, t, RMIL_CMDLINE); free(s); break; } case POPT_UNDEFINE: rpmcliConfigured(); if (*arg == '%') arg++; delMacro(NULL, arg); break; case 'E': rpmcliConfigured(); { char *val = rpmExpand(arg, NULL); fprintf(stdout, "%s\n", val); free(val); } break; case POPT_DBPATH: rpmcliConfigured(); addMacro(NULL, "_dbpath", NULL, arg, RMIL_CMDLINE); break; case POPT_SHOWVERSION: printVersion(stdout); exit(EXIT_SUCCESS); break; case POPT_SHOWRC: rpmcliConfigured(); (void) rpmShowRC(stdout); exit(EXIT_SUCCESS); break; case POPT_QUERYTAGS: rpmDisplayQueryTags(stdout); exit(EXIT_SUCCESS); break; case POPT_PIPE: if (rpmcliPipeOutput) { fprintf(stderr, _("%s: error: more than one --pipe specified " "(incompatible popt aliases?)\n"), __progname); exit(EXIT_FAILURE); } rpmcliPipeOutput = xstrdup(arg); break; case RPMCLI_POPT_NODIGEST: rpmcliQueryFlags |= VERIFY_DIGEST; break; case RPMCLI_POPT_NOSIGNATURE: rpmcliQueryFlags |= VERIFY_SIGNATURE; break; case RPMCLI_POPT_NOHDRCHK: rpmcliQueryFlags |= VERIFY_HDRCHK; break; } }
int parseSpec(rpmts ts, const char *specFile, const char *rootDir, const char *buildRoot, int recursing, const char *passPhrase, const char *cookie, int anyarch, int force) { rpmParseState parsePart = PART_PREAMBLE; int initialPackage = 1; Package pkg; rpmSpec spec; /* Set up a new Spec structure with no packages. */ spec = newSpec(); spec->specFile = rpmGetPath(specFile, NULL); spec->fileStack = newOpenFileInfo(); spec->fileStack->fileName = xstrdup(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); spec->recursing = recursing; spec->anyarch = anyarch; spec->force = force; if (rootDir) spec->rootDir = xstrdup(rootDir); if (passPhrase) spec->passPhrase = xstrdup(passPhrase); if (cookie) spec->cookie = xstrdup(cookie); spec->timeCheck = rpmExpandNumeric("%{_timecheck}"); /* 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) { /* XXX Trap unexpected RPMRC_FAIL returns for now */ case RPMRC_FAIL: rpmlog(RPMLOG_ERR, "FIXME: got RPMRC_FAIL from spec parse\n"); abort(); 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: parsePart = parseScript(spec, parsePart); break; case PART_FILES: parsePart = parseFiles(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] = NULL; if (parseSpec(ts, specFile, spec->rootDir, buildRoot, 1, passPhrase, cookie, anyarch, force) || (spec->BASpecs[index] = rpmtsSetSpec(ts, NULL)) == 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); spec = freeSpec(spec); spec = nspec; } (void) rpmtsSetSpec(ts, spec); return 0; } } 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 and add arch and os */ { char *platform = rpmExpand("%{_target_platform}", NULL); char *arch = rpmExpand("%{_target_cpu}", NULL); char *os = rpmExpand("%{_target_os}", NULL); for (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; } headerPutString(pkg->header, RPMTAG_OS, os); /* noarch subpackages already have arch set here, leave it alone */ if (!headerIsEntry(pkg->header, RPMTAG_ARCH)) { headerPutString(pkg->header, RPMTAG_ARCH, arch); } headerPutString(pkg->header, RPMTAG_PLATFORM, platform); pkg->ds = rpmdsThis(pkg->header, RPMTAG_REQUIRENAME, RPMSENSE_EQUAL); } platform = _free(platform); arch = _free(arch); os = _free(os); } closeSpec(spec); (void) rpmtsSetSpec(ts, spec); return 0; errxit: spec = freeSpec(spec); return PART_ERROR; }
static int runGPG(sigTarget sigt, const char *sigfile) { int pid = 0, status; FD_t fnamedPipe = NULL; char *namedPipeName = NULL; unsigned char buf[BUFSIZ]; ssize_t count; ssize_t wantCount; rpm_loff_t size; int rc = 1; /* assume failure */ namedPipeName = mkTempFifo(); addMacro(NULL, "__plaintext_filename", NULL, namedPipeName, -1); addMacro(NULL, "__signature_filename", NULL, sigfile, -1); if (!(pid = fork())) { char *const *av; char *cmd = NULL; const char *gpg_path = rpmExpand("%{?_gpg_path}", NULL); if (gpg_path && *gpg_path != '\0') (void) setenv("GNUPGHOME", gpg_path, 1); unsetenv("MALLOC_CHECK_"); cmd = rpmExpand("%{?__gpg_sign_cmd}", NULL); rc = poptParseArgvString(cmd, NULL, (const char ***)&av); if (!rc) rc = execve(av[0], av+1, environ); rpmlog(RPMLOG_ERR, _("Could not exec %s: %s\n"), "gpg", strerror(errno)); _exit(EXIT_FAILURE); } delMacro(NULL, "__plaintext_filename"); delMacro(NULL, "__signature_filename"); fnamedPipe = Fopen(namedPipeName, "w"); if (!fnamedPipe) { rpmlog(RPMLOG_ERR, _("Fopen failed\n")); goto exit; } if (Fseek(sigt->fd, sigt->start, SEEK_SET) < 0) { rpmlog(RPMLOG_ERR, _("Could not seek in file %s: %s\n"), sigt->fileName, Fstrerror(sigt->fd)); goto exit; } size = sigt->size; wantCount = size < sizeof(buf) ? size : sizeof(buf); while ((count = Fread(buf, sizeof(buf[0]), wantCount, sigt->fd)) > 0) { Fwrite(buf, sizeof(buf[0]), count, fnamedPipe); if (Ferror(fnamedPipe)) { rpmlog(RPMLOG_ERR, _("Could not write to pipe\n")); goto exit; } size -= count; wantCount = size < sizeof(buf) ? size : sizeof(buf); } if (count < 0) { rpmlog(RPMLOG_ERR, _("Could not read from file %s: %s\n"), sigt->fileName, Fstrerror(sigt->fd)); goto exit; } Fclose(fnamedPipe); fnamedPipe = NULL; (void) waitpid(pid, &status, 0); pid = 0; if (!WIFEXITED(status) || WEXITSTATUS(status)) { rpmlog(RPMLOG_ERR, _("gpg exec failed (%d)\n"), WEXITSTATUS(status)); } else { rc = 0; } exit: if (fnamedPipe) Fclose(fnamedPipe); if (pid) waitpid(pid, &status, 0); if (namedPipeName) { rpmRmTempFifo(namedPipeName); free(namedPipeName); } return rc; }
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; }
static rpmRC handlePreambleTag(Spec spec, Package pkg, rpmTag tag, const char *macro, const char *lang) /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ /*@modifies spec->macros, spec->st, spec->sources, spec->numSources, spec->noSource, spec->sourceHeader, spec->BANames, spec->BACount, spec->line, pkg->header, pkg->autoProv, pkg->autoReq, pkg->noarch, rpmGlobalMacroContext, fileSystem, internalState @*/ { HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he)); char * field = spec->line; char * end; int multiToken = 0; rpmsenseFlags tagflags; int len; rpmuint32_t num; int rc; int xx; if (field == NULL) return RPMRC_FAIL; /* XXX can't happen */ /* Find the start of the "field" and strip trailing space */ while ((*field) && (*field != ':')) field++; if (*field != ':') { rpmlog(RPMLOG_ERR, _("line %d: Malformed tag: %s\n"), spec->lineNum, spec->line); return RPMRC_FAIL; } field++; SKIPSPACE(field); if (!*field) { /* Empty field */ rpmlog(RPMLOG_ERR, _("line %d: Empty tag: %s\n"), spec->lineNum, spec->line); return RPMRC_FAIL; } end = findLastChar(field); /* Validate tag data content. */ if (tagValidate(spec, tag, field) != RPMRC_OK) return RPMRC_FAIL; /* See if this is multi-token */ end = field; SKIPNONSPACE(end); if (*end != '\0') multiToken = 1; switch (tag) { case RPMTAG_NAME: case RPMTAG_VERSION: case RPMTAG_RELEASE: case RPMTAG_DISTEPOCH: case RPMTAG_URL: case RPMTAG_DISTTAG: case RPMTAG_REPOTAG: case RPMTAG_CVSID: case RPMTAG_BUGURL: SINGLE_TOKEN_ONLY; /* These macros are for backward compatibility */ if (tag == RPMTAG_VERSION) { if (strchr(field, '-') != NULL) { rpmlog(RPMLOG_ERR, _("line %d: Illegal char '-' in %s: %s\n"), spec->lineNum, "version", spec->line); return RPMRC_FAIL; } addMacro(spec->macros, "PACKAGE_VERSION", NULL, field, RMIL_OLDSPEC); } else if (tag == RPMTAG_RELEASE) { if (strchr(field, '-') != NULL) { rpmlog(RPMLOG_ERR, _("line %d: Illegal char '-' in %s: %s\n"), spec->lineNum, "release", spec->line); return RPMRC_FAIL; } addMacro(spec->macros, "PACKAGE_RELEASE", NULL, field, RMIL_OLDSPEC-1); } he->tag = tag; he->t = RPM_STRING_TYPE; he->p.str = field; he->c = 1; xx = headerPut(pkg->header, he, 0); break; case RPMTAG_GROUP: case RPMTAG_SUMMARY: #if defined(RPM_VENDOR_OPENPKG) /* make-class-available-as-macro */ case RPMTAG_CLASS: #endif (void) stashSt(spec, pkg->header, tag, lang); /*@fallthrough@*/ case RPMTAG_DISTRIBUTION: case RPMTAG_VENDOR: case RPMTAG_LICENSE: case RPMTAG_PACKAGER: if (!*lang) { he->tag = tag; he->t = RPM_STRING_TYPE; he->p.str = field; he->c = 1; xx = headerPut(pkg->header, he, 0); } else if (!(noLang && strcmp(lang, RPMBUILD_DEFAULT_LANG))) { (void) headerAddI18NString(pkg->header, tag, field, lang); } break; /* XXX silently ignore BuildRoot: */ case RPMTAG_BUILDROOT: SINGLE_TOKEN_ONLY; macro = NULL; #ifdef DYING buildRootURL = rpmGenPath(spec->rootURL, "%{?buildroot}", NULL); (void) urlPath(buildRootURL, &buildRoot); if (*buildRoot == '\0') buildRoot = "/"; if (!strcmp(buildRoot, "/")) { rpmlog(RPMLOG_ERR, _("BuildRoot can not be \"/\": %s\n"), spec->buildRootURL); buildRootURL = _free(buildRootURL); return RPMRC_FAIL; } buildRootURL = _free(buildRootURL); #endif break; case RPMTAG_KEYWORDS: case RPMTAG_VARIANTS: case RPMTAG_PREFIXES: addOrAppendListEntry(pkg->header, tag, field); he->tag = tag; xx = headerGet(pkg->header, he, 0); if (tag == RPMTAG_PREFIXES) while (he->c--) { if (he->p.argv[he->c][0] != '/') { rpmlog(RPMLOG_ERR, _("line %d: Prefixes must begin with \"/\": %s\n"), spec->lineNum, spec->line); he->p.ptr = _free(he->p.ptr); return RPMRC_FAIL; } len = (int)strlen(he->p.argv[he->c]); if (he->p.argv[he->c][len - 1] == '/' && len > 1) { rpmlog(RPMLOG_ERR, _("line %d: Prefixes must not end with \"/\": %s\n"), spec->lineNum, spec->line); he->p.ptr = _free(he->p.ptr); return RPMRC_FAIL; } } he->p.ptr = _free(he->p.ptr); break; case RPMTAG_DOCDIR: SINGLE_TOKEN_ONLY; if (field[0] != '/') { rpmlog(RPMLOG_ERR, _("line %d: Docdir must begin with '/': %s\n"), spec->lineNum, spec->line); return RPMRC_FAIL; } macro = NULL; delMacro(NULL, "_docdir"); addMacro(NULL, "_docdir", NULL, field, RMIL_SPEC); break; case RPMTAG_XMAJOR: case RPMTAG_XMINOR: case RPMTAG_EPOCH: SINGLE_TOKEN_ONLY; if (parseNum(field, &num)) { rpmlog(RPMLOG_ERR, _("line %d: %s takes an integer value: %s\n"), spec->lineNum, tagName(tag), spec->line); return RPMRC_FAIL; } he->tag = tag; he->t = RPM_UINT32_TYPE; he->p.ui32p = # he->c = 1; xx = headerPut(pkg->header, he, 0); break; case RPMTAG_AUTOREQPROV: pkg->autoReq = parseYesNo(field); pkg->autoProv = pkg->autoReq; break; case RPMTAG_AUTOREQ: pkg->autoReq = parseYesNo(field); break; case RPMTAG_AUTOPROV: pkg->autoProv = parseYesNo(field); break; case RPMTAG_SOURCE: case RPMTAG_PATCH: SINGLE_TOKEN_ONLY; macro = NULL; if ((rc = addSource(spec, pkg, field, tag))) return rc; break; case RPMTAG_ICON: SINGLE_TOKEN_ONLY; macro = NULL; if ((rc = addSource(spec, pkg, field, tag))) return rc; /* XXX the fetch/load of icon needs to be elsewhere. */ if ((rc = doIcon(spec, pkg->header))) return rc; break; case RPMTAG_NOSOURCE: case RPMTAG_NOPATCH: spec->noSource = 1; if ((rc = parseNoSource(spec, field, tag))) return rc; break; case RPMTAG_BUILDPREREQ: case RPMTAG_BUILDREQUIRES: if ((rc = parseBits(lang, buildScriptBits, &tagflags))) { rpmlog(RPMLOG_ERR, _("line %d: Bad %s: qualifiers: %s\n"), spec->lineNum, tagName(tag), spec->line); return rc; } if ((rc = parseRCPOT(spec, pkg, field, tag, 0, tagflags))) return rc; break; case RPMTAG_PREREQ: case RPMTAG_REQUIREFLAGS: if ((rc = parseBits(lang, installScriptBits, &tagflags))) { rpmlog(RPMLOG_ERR, _("line %d: Bad %s: qualifiers: %s\n"), spec->lineNum, tagName(tag), spec->line); return rc; } if ((rc = parseRCPOT(spec, pkg, field, tag, 0, tagflags))) return rc; break; /* Aliases for BuildRequires(hint): */ case RPMTAG_BUILDSUGGESTS: case RPMTAG_BUILDENHANCES: tagflags = RPMSENSE_MISSINGOK; if ((rc = parseRCPOT(spec, pkg, field, tag, 0, tagflags))) return rc; break; /* Aliases for Requires(hint): */ case RPMTAG_SUGGESTSFLAGS: case RPMTAG_ENHANCESFLAGS: tag = RPMTAG_REQUIREFLAGS; tagflags = RPMSENSE_MISSINGOK; if ((rc = parseRCPOT(spec, pkg, field, tag, 0, tagflags))) return rc; break; case RPMTAG_BUILDOBSOLETES: case RPMTAG_BUILDPROVIDES: case RPMTAG_BUILDCONFLICTS: case RPMTAG_CONFLICTFLAGS: case RPMTAG_OBSOLETEFLAGS: case RPMTAG_PROVIDEFLAGS: tagflags = RPMSENSE_ANY; if ((rc = parseRCPOT(spec, pkg, field, tag, 0, tagflags))) return rc; break; case RPMTAG_BUILDPLATFORMS: /* XXX needs pattern parsing */ case RPMTAG_EXCLUDEARCH: case RPMTAG_EXCLUSIVEARCH: case RPMTAG_EXCLUDEOS: case RPMTAG_EXCLUSIVEOS: addOrAppendListEntry(spec->sourceHeader, tag, field); break; case RPMTAG_BUILDARCHS: { const char ** BANames = NULL; int BACount = 0; if ((rc = poptParseArgvString(field, &BACount, &BANames))) { rpmlog(RPMLOG_ERR, _("line %d: Bad BuildArchitecture format: %s\n"), spec->lineNum, spec->line); return RPMRC_FAIL; } if (spec->toplevel) { if (BACount > 0 && BANames != NULL) { spec->BACount = BACount; spec->BANames = BANames; BANames = NULL; /* XXX don't free. */ } } else { if (BACount != 1 || strcmp(BANames[0], "noarch")) { rpmlog(RPMLOG_ERR, _("line %d: Only \"noarch\" sub-packages are supported: %s\n"), spec->lineNum, spec->line); BANames = _free(BANames); return RPMRC_FAIL; } pkg->noarch = 1; } BANames = _free(BANames); } break; default: macro = NULL; he->tag = tag; he->t = RPM_STRING_ARRAY_TYPE; he->p.argv= (const char **) &field; /* XXX NOCAST */ he->c = 1; he->append = 1; xx = headerPut(pkg->header, he, 0); he->append = 0; break; } /*@-usereleased@*/ if (macro) addMacro(spec->macros, macro, NULL, field, RMIL_SPEC); /*@=usereleased@*/ return RPMRC_OK; }