static int rpm_slurp(lua_State *L) /*@globals fileSystem, internalState @*/ /*@modifies L, fileSystem, internalState @*/ { rpmiob iob = NULL; const char *fn; int rc; if (lua_isstring(L, 1)) fn = lua_tostring(L, 1); else { (void)luaL_argerror(L, 1, "filename"); return 0; } /*@-globs@*/ rc = rpmiobSlurp(fn, &iob); /*@=globs@*/ if (rc || iob == NULL) { (void)luaL_error(L, "failed to slurp data"); return 0; } lua_pushlstring(L, (const char *)rpmiobStr(iob), rpmiobLen(iob)); iob = rpmiobFree(iob); return 1; }
/** * Add expanded build scriptlet to srpm header. * @param h srpm header * @param progTag interpreter tag (0 disables) * @param scriptTag script tag (0 disables) * @param iob script body sting buf (NULL disables) * @return 0 always */ static int initSourceHeaderScriptlet(Header h, rpmTag progTag, rpmTag scriptTag, rpmiob iob) /*@modifies h @*/ { HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he)); int xx; if (progTag !=(rpmTag) 0) { static const char prog[] = "/bin/sh"; /* XXX FIXME */ he->tag = progTag; he->t = RPM_STRING_TYPE; he->p.str = prog; he->c = 1; xx = headerPut(h, he, 0); } if (scriptTag != (rpmTag)0 && iob != NULL) { he->tag = scriptTag; he->t = RPM_STRING_TYPE; he->p.str = rpmiobStr(iob); he->c = 1; xx = headerPut(h, he, 0); } return 0; }
rpmRC rpmpythonRunFile(rpmpython python, const char * fn, const char ** resultp) { rpmRC rc = RPMRC_FAIL; if (_rpmpython_debug) fprintf(stderr, "==> %s(%p,%s)\n", __FUNCTION__, python, fn); if (python == NULL) python = rpmpythonI(); if (fn != NULL) { #if defined(WITH_PYTHONEMBED) const char * pyfn = ((fn == NULL || !strcmp(fn, "-")) ? "<stdin>" : fn); FILE * pyfp = (!strcmp(pyfn, "<stdin>") ? stdin : fopen(fn, "rb")); int closeit = (pyfp != stdin); PyCompilerFlags cf = { .cf_flags = 0 }; if (pyfp != NULL) { PyRun_AnyFileExFlags(pyfp, pyfn, closeit, &cf); rc = RPMRC_OK; } #endif } return rc; } static const char * rpmpythonSlurp(const char * arg) /*@*/ { rpmiob iob = NULL; const char * val = NULL; struct stat sb; int xx; if (!strcmp(arg, "-")) { /* Macros from stdin arg. */ xx = rpmiobSlurp(arg, &iob); } else if ((arg[0] == '/' || strchr(arg, ' ') == NULL) && !Stat(arg, &sb) && S_ISREG(sb.st_mode)) { /* Macros from a file arg. */ xx = rpmiobSlurp(arg, &iob); } else { /* Macros from string arg. */ iob = rpmiobAppend(rpmiobNew(strlen(arg)+1), arg, 0); } val = xstrdup(rpmiobStr(iob)); iob = rpmiobFree(iob); return val; }
rpmRC rpmtclRun(rpmtcl tcl, const char * str, const char ** resultp) { rpmRC rc = RPMRC_FAIL; if (_rpmtcl_debug) fprintf(stderr, "==> %s(%p,%s)\n", __FUNCTION__, tcl, str); if (tcl == NULL) tcl = rpmtclI(); #if defined(WITH_TCL) if (str != NULL && Tcl_Eval((Tcl_Interp *)tcl->I, str) == TCL_OK) { rc = RPMRC_OK; if (resultp) *resultp = rpmiobStr(tcl->iob); } #endif return rc; }
/** * Add %changelog section to header. * @param h header * @param iob changelog strings * @return RPMRC_OK on success */ static rpmRC addChangelog(Header h, rpmiob iob) /*@globals rpmGlobalMacroContext, h_errno, internalState @*/ /*@modifies h, rpmGlobalMacroContext, internalState @*/ { char * s = rpmiobStr(iob); char * se; char *date, *name, *text; int i; time_t time; time_t lastTime = 0; int nentries = 0; static time_t last = 0; static int oneshot = 0; /* Determine changelog truncation criteria. */ if (!oneshot++) { char * t = rpmExpand("%{?_changelog_truncate}", NULL); char *te = NULL; if (t && *t) { long res = strtol(t, &te, 0); if (res >= 0 && *te == '\0') { last = res; /* truncate to no. of entries. */ } else { /*@-moduncon@*/ res = (long)get_date (t, NULL); /*@=moduncon@*/ /* XXX malformed date string silently ignored. */ if (res > 0) { last = res; /* truncate to date. */ } } } t = _free(t); } /* skip space */ mySKIPSPACE(s); while (*s != '\0') { if (*s != '*') { rpmlog(RPMLOG_ERR, _("%%changelog entries must start with *\n")); return RPMRC_FAIL; } /* find end of line */ date = s; while(*s && *s != '\n') s++; if (! *s) { rpmlog(RPMLOG_ERR, _("incomplete %%changelog entry\n")); return RPMRC_FAIL; } /*@-modobserver@*/ *s = '\0'; /*@=modobserver@*/ text = s + 1; /* 4 fields of date */ date++; s = date; for (i = 0; i < 4; i++) { mySKIPSPACE(s); mySKIPNONSPACE(s); } mySKIPSPACE(date); if (dateToTimet(date, &time)) { rpmlog(RPMLOG_ERR, _("bad date in %%changelog: %s\n"), date); return RPMRC_FAIL; } if (lastTime && lastTime < time) { rpmlog(RPMLOG_ERR, _("%%changelog not in descending chronological order\n")); return RPMRC_FAIL; } lastTime = time; /* skip space to the name */ mySKIPSPACE(s); if (! *s) { rpmlog(RPMLOG_ERR, _("missing name in %%changelog\n")); return RPMRC_FAIL; } /* name */ name = s; while (*s != '\0') s++; while (s > name && isspace(*s)) *s-- = '\0'; if (s == name) { rpmlog(RPMLOG_ERR, _("missing name in %%changelog\n")); return RPMRC_FAIL; } /* text */ mySKIPSPACE(text); if (! *text) { rpmlog(RPMLOG_ERR, _("no description in %%changelog\n")); return RPMRC_FAIL; } /* find the next leading '*' (or eos) */ s = text; do { s++; } while (*s && (*(s-1) != '\n' || *s != '*')); se = s; s--; /* backup to end of description */ while ((s > text) && xisspace(*s)) *s-- = '\0'; /* Add entry if not truncated. */ nentries++; if (last <= 0 || (last < 1000 && nentries < (int)last) || (last > 1000 && time >= last)) addChangelogEntry(h, time, name, text); s = se; } return 0; }
/* * @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 integrity_check(const char *progname, enum modes progmode_num) { rpmts ts = NULL; rpmlua lua = NULL; char *spec_fn = NULL; char *proc_fn = NULL; char *pkey_fn = NULL; char *spec = NULL; char *proc = NULL; rpmiob spec_iob = NULL; rpmiob proc_iob = NULL; const char *result = NULL; const char *error = NULL; int xx; const char *progmode; int rc = INTEGRITY_ERROR; /* determine paths of integrity checking related files */ spec_fn = rpmExpand("%{?_integrity_spec_cfg}%{!?_integrity_spec_cfg:scripts/integrity.cfg}", NULL); if (spec_fn == NULL || spec_fn[0] == '\0') { integrity_check_message("ERROR: Integrity Configuration Specification file not configured.\n" "rpm: HINT: macro %%{_integrity_spec_cfg} not configured correctly.\n"); goto failure; } proc_fn = rpmExpand("%{?_integrity_proc_lua}%{!?_integrity_proc_lua:scripts/integrity.lua}", NULL); if (proc_fn == NULL || proc_fn[0] == '\0') { integrity_check_message("ERROR: Integrity Validation Processor file not configured.\n" "rpm: HINT: macro %%{_integrity_proc_lua} not configured correctly.\n"); goto failure; } pkey_fn = rpmExpand("%{?_integrity_pkey_pgp}%{!?_integrity_pkey_pgp:scripts/integrity.pgp}", NULL); if (pkey_fn == NULL || pkey_fn[0] == '\0') { integrity_check_message("ERROR: Integrity Autority Public-Key file not configured.\n" "rpm: HINT: macro %%{_integrity_pkey_pgp} not configured correctly.\n"); goto failure; } /* create RPM transaction environment and open RPM database */ ts = rpmtsCreate(); (void)rpmtsOpenDB(ts, O_RDONLY); /* check signature on integrity configuration specification file */ if (rpmnsProbeSignature(ts, spec_fn, NULL, pkey_fn, RPM_INTEGRITY_FP, 0) != RPMRC_OK) { integrity_check_message("ERROR: Integrity Configuration Specification file contains invalid signature.\n" "rpm: HINT: Check file \"%s\".\n", spec_fn); goto failure; } /* check signature on integrity validation processor file */ if (rpmnsProbeSignature(ts, proc_fn, NULL, pkey_fn, RPM_INTEGRITY_FP, 0) != RPMRC_OK) { integrity_check_message("ERROR: Integrity Validation Processor file contains invalid signature.\n" "rpm: HINT: Check file \"%s\".\n", proc_fn); goto failure; } /* load integrity configuration specification file */ xx = rpmiobSlurp(spec_fn, &spec_iob); if (!(xx == 0 && spec_iob != NULL)) { integrity_check_message("ERROR: Unable to load Integrity Configuration Specification file.\n" "rpm: HINT: Check file \"%s\".\n", spec_fn); goto failure; } spec = rpmiobStr(spec_iob); /* load integrity validation processor file */ xx = rpmiobSlurp(proc_fn, &proc_iob); if (!(xx == 0 && proc_iob != NULL)) { integrity_check_message("ERROR: Unable to load Integrity Validation Processor file.\n" "rpm: HINT: Check file \"%s\".\n", proc_fn); goto failure; } proc = rpmiobStr(proc_iob); /* provision program name and mode */ if (progname == NULL || progname[0] == '\0') progname = "rpm"; switch (progmode_num) { case MODE_QUERY: progmode = "query"; break; case MODE_VERIFY: progmode = "verify"; break; case MODE_CHECKSIG: progmode = "checksig"; break; case MODE_RESIGN: progmode = "resign"; break; case MODE_INSTALL: progmode = "install"; break; case MODE_ERASE: progmode = "erase"; break; case MODE_BUILD: progmode = "build"; break; case MODE_REBUILD: progmode = "rebuild"; break; case MODE_RECOMPILE: progmode = "recompile"; break; case MODE_TARBUILD: progmode = "tarbuild"; break; case MODE_REBUILDDB: progmode = "rebuilddb"; break; case MODE_UNKNOWN: progmode = "unknown"; break; default: progmode = "unknown"; break; } /* execute Integrity Validation Processor via Lua glue code */ lua = rpmluaNew(); rpmluaSetPrintBuffer(lua, 1); rpmluaextActivate(lua); lua_getfield(lua->L, LUA_GLOBALSINDEX, "integrity"); lua_getfield(lua->L, -1, "processor"); lua_remove(lua->L, -2); lua_pushstring(lua->L, progname); lua_pushstring(lua->L, progmode); lua_pushstring(lua->L, spec_fn); lua_pushstring(lua->L, spec); lua_pushstring(lua->L, proc_fn); lua_pushstring(lua->L, proc); #ifdef RPM_INTEGRITY_MV lua_pushstring(lua->L, RPM_INTEGRITY_MV); #else lua_pushstring(lua->L, "0"); #endif if (lua_pcall(lua->L, 7, 1, 0) != 0) { error = lua_isstring(lua->L, -1) ? lua_tostring(lua->L, -1) : "unknown error"; lua_pop(lua->L, 1); integrity_check_message("ERROR: Failed to execute Integrity Validation Processor.\n" "rpm: ERROR: Lua: %s.\n" "rpm: HINT: Check file \"%s\".\n", error, proc_fn); goto failure; } /* check Integrity Validation Processor results */ if (!lua_isstring(lua->L, -1)) { integrity_check_message("ERROR: Failed to fetch Integrity Validation Processor results.\n" "rpm: HINT: Check file \"%s\".\n", proc_fn); goto failure; } result = lua_tostring(lua->L, -1); if (strcmp(result, "OK") == 0) rc = INTEGRITY_OK; else if (strncmp(result, "WARNING:", 8) == 0) { rc = INTEGRITY_WARNING; integrity_check_message("%s\n", result); } else { rc = INTEGRITY_ERROR; integrity_check_message("%s\n", result); } /* cleanup processing */ failure: if (lua != NULL) rpmluaFree(lua); if (ts != NULL) (void)rpmtsFree(ts); ts = NULL; if (spec_iob != NULL) spec_iob = rpmiobFree(spec_iob); if (proc_iob != NULL) proc_iob = rpmiobFree(proc_iob); /* final result handling */ if (rc != INTEGRITY_OK) { if (isatty(STDIN_FILENO) || isatty(STDOUT_FILENO)) sleep(4); if (rc == INTEGRITY_ERROR) exit(42); } return; }
int parseDescription(Spec spec) /*@globals name, lang @*/ /*@modifies name, lang @*/ { rpmParseState nextPart = (rpmParseState) RPMRC_FAIL; /* assume error */ rpmiob iob = NULL; int flag = PART_SUBNAME; Package pkg; int rc, argc; int arg; const char **argv = NULL; poptContext optCon = NULL; spectag t = NULL; { char * se = strchr(spec->line, '#'); if (se) { *se = '\0'; while (--se >= spec->line && strchr(" \t\n\r", *se) != NULL) *se = '\0'; } } if ((rc = poptParseArgvString(spec->line, &argc, &argv))) { rpmlog(RPMLOG_ERR, _("line %d: Error parsing %%description: %s\n"), spec->lineNum, poptStrerror(rc)); goto exit; } name = NULL; lang = RPMBUILD_DEFAULT_LANG; optCon = poptGetContext(NULL, argc, argv, optionsTable, 0); while ((arg = poptGetNextOpt(optCon)) > 0) {;} if (name != NULL) 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) != RPMRC_OK) { rpmlog(RPMLOG_ERR, _("line %d: Package does not exist: %s\n"), spec->lineNum, spec->line); goto exit; } /* Lose the inheirited %description (if present). */ if (spec->packages->header != pkg->header) { HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he)); int xx; he->tag = RPMTAG_DESCRIPTION; xx = headerGet(pkg->header, he, 0); he->p.ptr = _free(he->p.ptr); if (xx && he->t == RPM_STRING_TYPE) xx = headerDel(pkg->header, he, 0); } t = stashSt(spec, pkg->header, RPMTAG_DESCRIPTION, lang); iob = rpmiobNew(0); if ((rc = readLine(spec, STRIP_TRAILINGSPACE | STRIP_COMMENTS)) > 0) { nextPart = PART_NONE; goto exit; } if (rc < 0) { nextPart = (rpmParseState) RPMRC_FAIL; goto exit; } while ((nextPart = isPart(spec)) == PART_NONE) { iob = rpmiobAppend(iob, spec->line, 1); if (t) t->t_nlines++; if ((rc = readLine(spec, STRIP_TRAILINGSPACE | STRIP_COMMENTS)) > 0) { nextPart = PART_NONE; break; } if (rc) { nextPart = (rpmParseState) RPMRC_FAIL; goto exit; } } iob = rpmiobRTrim(iob); if (!(noLang && strcmp(lang, RPMBUILD_DEFAULT_LANG))) { const char * s = rpmiobStr(iob); (void) headerAddI18NString(pkg->header, RPMTAG_DESCRIPTION, s, lang); } exit: iob = rpmiobFree(iob); argv = _free(argv); optCon = poptFreeContext(optCon); return nextPart; }
int parsePrep(Spec spec, int verify) { rpmParseState nextPart; int res, rc; rpmiob iob; ARGV_t saveLines = NULL; ARGV_t lines; const char * cp; int xx; if (spec->prep != NULL) { rpmlog(RPMLOG_ERR, _("line %d: second %%prep\n"), spec->lineNum); return RPMRC_FAIL; } spec->prep = rpmiobNew(0); /* There are no options to %prep */ if ((rc = readLine(spec, STRIP_NOTHING)) > 0) return PART_NONE; if (rc) return rc; /* Check to make sure that all sources/patches are present. */ if (verify) { rc = prepFetch(spec); if (rc) return RPMRC_FAIL; } iob = rpmiobNew(0); while ((nextPart = isPart(spec)) == PART_NONE) { /* Need to expand the macros inline. That way we */ /* can give good line number information on error. */ iob = rpmiobAppend(iob, spec->line, 0); if ((rc = readLine(spec, STRIP_NOTHING)) > 0) { nextPart = PART_NONE; break; } if (rc) return rc; } xx = argvSplit(&saveLines, rpmiobStr(iob), "\n"); /*@-usereleased@*/ for (lines = saveLines; *lines; lines++) { res = 0; for (cp = *lines; *cp == ' ' || *cp == '\t'; cp++) {}; if (!strncmp(cp, "%setup", sizeof("%setup")-1)) { res = doSetupMacro(spec, cp); #ifndef DYING } else if (! strncmp(cp, "%patch", sizeof("%patch")-1)) { res = doPatchMacro(spec, cp); #endif } else { spec->prep = rpmiobAppend(spec->prep, *lines, 1); } if (res && !spec->force) { saveLines = argvFree(saveLines); iob = rpmiobFree(iob); return res; } } /*@=usereleased@*/ saveLines = argvFree(saveLines); iob = rpmiobFree(iob); return nextPart; }
/** * Parse %setup macro. * @todo FIXME: Option -q broken when not immediately after %setup. * @param spec build info * @param line current line from spec file * @return 0 on success */ static int doSetupMacro(Spec spec, const char * line) /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/ /*@modifies spec->buildSubdir, spec->macros, spec->prep, spec->packages->header, rpmGlobalMacroContext, fileSystem, internalState @*/ { char buf[BUFSIZ]; rpmiob before = NULL; rpmiob after = NULL; poptContext optCon; int argc; const char ** argv; int arg; const char * optArg; int rc; rpmuint32_t num; rpmRC ec = RPMRC_FAIL; /* XXX assume failure */ /*@-mods@*/ leaveDirs = skipDefaultAction = 0; createDir = quietly = 0; dirName = NULL; /*@=mods@*/ if ((rc = poptParseArgvString(line, &argc, &argv))) { rpmlog(RPMLOG_ERR, _("Error parsing %%setup: %s\n"), poptStrerror(rc)); goto exit; } before = rpmiobNew(0); after = rpmiobNew(0); optCon = poptGetContext(NULL, argc, argv, optionsTable, 0); while ((arg = poptGetNextOpt(optCon)) > 0) { optArg = poptGetOptArg(optCon); /* We only parse -a and -b here */ if (parseNum(optArg, &num)) { rpmlog(RPMLOG_ERR, _("line %d: Bad arg to %%setup: %s\n"), spec->lineNum, (optArg ? optArg : "???")); optCon = poptFreeContext(optCon); argv = _free(argv); goto exit; } { const char *chptr = doUntar(spec, num, quietly); if (chptr == NULL) goto exit; (void) rpmiobAppend((arg == 'a' ? after : before), chptr, 1); } } if (arg < -1) { rpmlog(RPMLOG_ERR, _("line %d: Bad %%setup option %s: %s\n"), spec->lineNum, poptBadOption(optCon, POPT_BADOPTION_NOALIAS), poptStrerror(arg)); optCon = poptFreeContext(optCon); argv = _free(argv); goto exit; } if (dirName) { spec->buildSubdir = xstrdup(dirName); } else { const char *N, *V; (void) headerNEVRA(spec->packages->header, &N, NULL, &V, NULL, NULL); (void) snprintf(buf, sizeof(buf), "%s-%s", N, V); buf[sizeof(buf)-1] = '\0'; N = _free(N); V = _free(V); spec->buildSubdir = xstrdup(buf); } addMacro(spec->macros, "buildsubdir", NULL, spec->buildSubdir, RMIL_SPEC); optCon = poptFreeContext(optCon); argv = _free(argv); /* cd to the build dir */ { const char * buildDirURL = rpmGenPath(spec->rootURL, "%{_builddir}", ""); const char *buildDir; (void) urlPath(buildDirURL, &buildDir); rc = rpmioMkpath(buildDir, 0755, -1, -1); sprintf(buf, "cd '%s'", buildDir); spec->prep = rpmiobAppend(spec->prep, buf, 1); buildDirURL = _free(buildDirURL); } /* delete any old sources */ if (!leaveDirs) { sprintf(buf, "rm -rf '%s'", spec->buildSubdir); spec->prep = rpmiobAppend(spec->prep, buf, 1); } /* check if source is a ruby gem */ { struct Source *sp; for (sp = spec->sources; sp != NULL; sp = sp->next) { if ((sp->flags & RPMFILE_SOURCE) && (sp->num == 0)) { break; } } if (sp != NULL) { char *t = strrchr(sp->source, '.'); if(t && !strcasecmp(t, ".gem")) createDir = 1; } } /* if necessary, create and cd into the proper dir */ if (createDir) { char *mkdir_p; mkdir_p = rpmExpand("%{?__mkdir_p}%{!?__mkdir_p:mkdir -p}", NULL); if (!mkdir_p) mkdir_p = xstrdup("mkdir -p"); sprintf(buf, "%s '%s'\ncd '%s'", mkdir_p, spec->buildSubdir, spec->buildSubdir); mkdir_p = _free(mkdir_p); spec->prep = rpmiobAppend(spec->prep, buf, 1); } /* do the default action */ if (!createDir && !skipDefaultAction) { const char *chptr = doUntar(spec, 0, quietly); if (chptr == NULL) goto exit; spec->prep = rpmiobAppend(spec->prep, chptr, 1); } spec->prep = rpmiobAppend(spec->prep, rpmiobStr(before), 0); if (!createDir) { sprintf(buf, "cd '%s'", spec->buildSubdir); spec->prep = rpmiobAppend(spec->prep, buf, 1); } if (createDir && !skipDefaultAction) { const char * chptr = doUntar(spec, 0, quietly); if (chptr == NULL) goto exit; spec->prep = rpmiobAppend(spec->prep, chptr, 1); } spec->prep = rpmiobAppend(spec->prep, rpmiobStr(after), 0); /* XXX FIXME: owner & group fixes were conditioned on !geteuid() */ /* Fix the owner, group, and permissions of the setup build tree */ { /*@observer@*/ static const char *fixmacs[] = { "%{_fixowner}", "%{_fixgroup}", "%{_fixperms}", NULL }; const char ** fm; for (fm = fixmacs; *fm; fm++) { const char *fix; fix = rpmExpand(*fm, " .", NULL); if (fix && *fix != '%') spec->prep = rpmiobAppend(spec->prep, fix, 1); fix = _free(fix); } } ec = RPMRC_OK; exit: before = rpmiobFree(before); after = rpmiobFree(after); return ec; }