static StringBuf addFileToTagAux(rpmSpec spec, const char * file, StringBuf sb) { char buf[BUFSIZ]; char * fn; FILE * f; fn = rpmGetPath("%{_builddir}/%{?buildsubdir:%{buildsubdir}/}", file, NULL); f = fopen(fn, "r"); if (f == NULL || ferror(f)) { sb = freeStringBuf(sb); goto exit; } while (fgets(buf, sizeof(buf), f)) { if (expandMacros(spec, spec->macros, buf, sizeof(buf))) { rpmlog(RPMLOG_ERR, _("%s: line: %s\n"), fn, buf); sb = freeStringBuf(sb); break; } appendStringBuf(sb, buf); } (void) fclose(f); exit: free(fn); return sb; }
int parseChangelog(rpmSpec spec) { int nextPart, rc, res = PART_ERROR; StringBuf sb = newStringBuf(); /* There are no options to %changelog */ if ((rc = readLine(spec, STRIP_COMMENTS)) > 0) { res = PART_NONE; goto exit; } else if (rc < 0) { goto exit; } while (! (nextPart = isPart(spec->line))) { appendStringBuf(sb, spec->line); if ((rc = readLine(spec, STRIP_COMMENTS)) > 0) { nextPart = PART_NONE; break; } else if (rc < 0) { goto exit; } } if (addChangelog(spec->packages->header, sb)) { goto exit; } res = nextPart; exit: sb = freeStringBuf(sb); return res; }
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 addFileToArrayTag(rpmSpec spec, const char *file, Header h, rpmTagVal tag) { StringBuf sb = newStringBuf(); const char *s; if ((sb = addFileToTagAux(spec, file, sb)) == NULL) return 1; s = getStringBuf(sb); headerPutString(h, tag, s); sb = freeStringBuf(sb); return 0; }
static rpmRC addFileToTag(rpmSpec spec, const char * file, Header h, rpmTagVal tag, int append) { StringBuf sb = NULL; char buf[BUFSIZ]; char * fn; FILE * f; rpmRC rc = RPMRC_FAIL; /* assume failure */ /* no script file is not an error */ if (file == NULL) return RPMRC_OK; fn = rpmGetPath("%{_builddir}/%{?buildsubdir:%{buildsubdir}/}", file, NULL); f = fopen(fn, "r"); if (f == NULL) { rpmlog(RPMLOG_ERR,_("Could not open %s file: %s\n"), rpmTagGetName(tag), file); goto exit; } sb = newStringBuf(); if (append) { const char *s = headerGetString(h, tag); if (s) { appendLineStringBuf(sb, s); headerDel(h, tag); } } while (fgets(buf, sizeof(buf), f)) { char *expanded; if (rpmExpandMacros(spec->macros, buf, &expanded, 0) < 0) { rpmlog(RPMLOG_ERR, _("%s: line: %s\n"), fn, buf); goto exit; } appendStringBuf(sb, expanded); free(expanded); } headerPutString(h, tag, getStringBuf(sb)); rc = RPMRC_OK; exit: if (f) fclose(f); free(fn); freeStringBuf(sb); return rc; }
static int addFileToTag(rpmSpec spec, const char * file, Header h, rpmTagVal tag) { StringBuf sb = newStringBuf(); const char *s = headerGetString(h, tag); if (s) { appendLineStringBuf(sb, s); (void) headerDel(h, tag); } if ((sb = addFileToTagAux(spec, file, sb)) == NULL) return 1; headerPutString(h, tag, getStringBuf(sb)); sb = freeStringBuf(sb); return 0; }
static int addFileToTag(rpmSpec spec, const char * file, Header h, rpmTag tag) { StringBuf sb = newStringBuf(); const char *s; struct rpmtd_s td; headerGet(h, tag, &td, HEADERGET_MINMEM); if ((s = rpmtdGetString(&td))) { appendLineStringBuf(sb, s); rpmtdFreeData(&td); (void) headerDel(h, tag); } if ((sb = addFileToTagAux(spec, file, sb)) == NULL) return 1; headerPutString(h, tag, getStringBuf(sb)); sb = freeStringBuf(sb); return 0; }
int parseScript(rpmSpec spec, int parsePart) { /* There are a few options to scripts: */ /* <pkg> */ /* -n <pkg> */ /* -p <sh> */ /* -p "<sh> <args>..." */ /* -f <file> */ const char *p; const char **progArgv = NULL; int progArgc; const char *partname = NULL; rpmTagVal reqtag = 0; rpmTagVal tag = 0; rpmsenseFlags tagflags = 0; rpmTagVal progtag = 0; rpmTagVal flagtag = 0; rpmscriptFlags scriptFlags = 0; int flag = PART_SUBNAME; Package pkg; StringBuf sb = NULL; int nextPart; int index; char * reqargs = NULL; int res = PART_ERROR; /* assume failure */ int rc, argc; int arg; const char **argv = NULL; poptContext optCon = NULL; const char *name = NULL; const char *prog = "/bin/sh"; const char *file = NULL; struct poptOption optionsTable[] = { { NULL, 'p', POPT_ARG_STRING, &prog, 'p', NULL, NULL}, { NULL, 'n', POPT_ARG_STRING, &name, 'n', NULL, NULL}, { NULL, 'f', POPT_ARG_STRING, &file, 'f', NULL, NULL}, { NULL, 'e', POPT_BIT_SET, &scriptFlags, RPMSCRIPT_FLAG_EXPAND, NULL, NULL}, { NULL, 'q', POPT_BIT_SET, &scriptFlags, RPMSCRIPT_FLAG_QFORMAT, NULL, NULL}, { 0, 0, 0, 0, 0, NULL, NULL} }; switch (parsePart) { case PART_PRE: tag = RPMTAG_PREIN; tagflags = RPMSENSE_SCRIPT_PRE; progtag = RPMTAG_PREINPROG; flagtag = RPMTAG_PREINFLAGS; partname = "%pre"; break; case PART_POST: tag = RPMTAG_POSTIN; tagflags = RPMSENSE_SCRIPT_POST; progtag = RPMTAG_POSTINPROG; flagtag = RPMTAG_POSTINFLAGS; partname = "%post"; break; case PART_PREUN: tag = RPMTAG_PREUN; tagflags = RPMSENSE_SCRIPT_PREUN; progtag = RPMTAG_PREUNPROG; flagtag = RPMTAG_PREUNFLAGS; partname = "%preun"; break; case PART_POSTUN: tag = RPMTAG_POSTUN; tagflags = RPMSENSE_SCRIPT_POSTUN; progtag = RPMTAG_POSTUNPROG; flagtag = RPMTAG_POSTUNFLAGS; partname = "%postun"; break; case PART_PRETRANS: tag = RPMTAG_PRETRANS; tagflags = RPMSENSE_PRETRANS; progtag = RPMTAG_PRETRANSPROG; flagtag = RPMTAG_PRETRANSFLAGS; partname = "%pretrans"; break; case PART_POSTTRANS: tag = RPMTAG_POSTTRANS; tagflags = RPMSENSE_POSTTRANS; progtag = RPMTAG_POSTTRANSPROG; flagtag = RPMTAG_POSTTRANSFLAGS; partname = "%posttrans"; break; case PART_VERIFYSCRIPT: tag = RPMTAG_VERIFYSCRIPT; tagflags = RPMSENSE_SCRIPT_VERIFY; progtag = RPMTAG_VERIFYSCRIPTPROG; flagtag = RPMTAG_VERIFYSCRIPTFLAGS; partname = "%verifyscript"; break; case PART_TRIGGERPREIN: tag = RPMTAG_TRIGGERSCRIPTS; tagflags = 0; reqtag = RPMTAG_TRIGGERPREIN; progtag = RPMTAG_TRIGGERSCRIPTPROG; flagtag = RPMTAG_TRIGGERSCRIPTFLAGS; partname = "%triggerprein"; break; case PART_TRIGGERIN: tag = RPMTAG_TRIGGERSCRIPTS; tagflags = 0; reqtag = RPMTAG_TRIGGERIN; progtag = RPMTAG_TRIGGERSCRIPTPROG; flagtag = RPMTAG_TRIGGERSCRIPTFLAGS; partname = "%triggerin"; break; case PART_TRIGGERUN: tag = RPMTAG_TRIGGERSCRIPTS; tagflags = 0; reqtag = RPMTAG_TRIGGERUN; progtag = RPMTAG_TRIGGERSCRIPTPROG; flagtag = RPMTAG_TRIGGERSCRIPTFLAGS; partname = "%triggerun"; break; case PART_TRIGGERPOSTUN: tag = RPMTAG_TRIGGERSCRIPTS; tagflags = 0; reqtag = RPMTAG_TRIGGERPOSTUN; progtag = RPMTAG_TRIGGERSCRIPTPROG; flagtag = RPMTAG_TRIGGERSCRIPTFLAGS; partname = "%triggerpostun"; break; case PART_FILETRIGGERIN: tag = RPMTAG_FILETRIGGERSCRIPTS; tagflags = 0; reqtag = RPMTAG_FILETRIGGERIN; progtag = RPMTAG_FILETRIGGERSCRIPTPROG; flagtag = RPMTAG_FILETRIGGERSCRIPTFLAGS; partname = "%filetriggerin"; break; case PART_FILETRIGGERUN: tag = RPMTAG_FILETRIGGERSCRIPTS; tagflags = 0; reqtag = RPMTAG_FILETRIGGERUN; progtag = RPMTAG_FILETRIGGERSCRIPTPROG; flagtag = RPMTAG_FILETRIGGERSCRIPTFLAGS; partname = "%filetriggerun"; break; case PART_FILETRIGGERPOSTUN: tag = RPMTAG_FILETRIGGERSCRIPTS; tagflags = 0; reqtag = RPMTAG_FILETRIGGERPOSTUN; progtag = RPMTAG_FILETRIGGERSCRIPTPROG; flagtag = RPMTAG_FILETRIGGERSCRIPTFLAGS; partname = "%filetriggerpostun"; break; case PART_TRANSFILETRIGGERIN: tag = RPMTAG_TRANSFILETRIGGERSCRIPTS; tagflags = 0; reqtag = RPMTAG_TRANSFILETRIGGERIN; progtag = RPMTAG_TRANSFILETRIGGERSCRIPTPROG; flagtag = RPMTAG_TRANSFILETRIGGERSCRIPTFLAGS; partname = "%transfiletriggerin"; break; case PART_TRANSFILETRIGGERUN: tag = RPMTAG_TRANSFILETRIGGERSCRIPTS; tagflags = 0; reqtag = RPMTAG_TRANSFILETRIGGERUN; progtag = RPMTAG_TRANSFILETRIGGERSCRIPTPROG; flagtag = RPMTAG_TRANSFILETRIGGERSCRIPTFLAGS; partname = "%transfiletriggerun"; break; case PART_TRANSFILETRIGGERPOSTUN: tag = RPMTAG_TRANSFILETRIGGERSCRIPTS; tagflags = 0; reqtag = RPMTAG_TRANSFILETRIGGERPOSTUN; progtag = RPMTAG_TRANSFILETRIGGERSCRIPTPROG; flagtag = RPMTAG_TRANSFILETRIGGERSCRIPTFLAGS; partname = "%transfiletriggerpostun"; break; } if (tag == RPMTAG_TRIGGERSCRIPTS || tag == RPMTAG_FILETRIGGERSCRIPTS || tag == RPMTAG_TRANSFILETRIGGERSCRIPTS) { /* break line into two */ char *s = strstr(spec->line, "--"); if (!s) { rpmlog(RPMLOG_ERR, _("line %d: triggers must have --: %s\n"), spec->lineNum, spec->line); return PART_ERROR; } *s = '\0'; reqargs = xstrdup(s + 2); } if ((rc = poptParseArgvString(spec->line, &argc, &argv))) { rpmlog(RPMLOG_ERR, _("line %d: Error parsing %s: %s\n"), spec->lineNum, partname, poptStrerror(rc)); goto exit; } optCon = poptGetContext(NULL, argc, argv, optionsTable, 0); while ((arg = poptGetNextOpt(optCon)) > 0) { switch (arg) { case 'p': if (prog[0] == '<') { if (prog[strlen(prog)-1] != '>') { rpmlog(RPMLOG_ERR, _("line %d: internal script must end " "with \'>\': %s\n"), spec->lineNum, prog); goto exit; } } else if (prog[0] != '/') { rpmlog(RPMLOG_ERR, _("line %d: script program must begin " "with \'/\': %s\n"), spec->lineNum, prog); goto exit; } break; case 'n': flag = PART_NAME; break; } } if (arg < -1) { rpmlog(RPMLOG_ERR, _("line %d: Bad option %s: %s\n"), spec->lineNum, poptBadOption(optCon, POPT_BADOPTION_NOALIAS), spec->line); goto exit; } if (poptPeekArg(optCon)) { if (name == NULL) name = poptGetArg(optCon); if (poptPeekArg(optCon)) { rpmlog(RPMLOG_ERR, _("line %d: Too many names: %s\n"), spec->lineNum, spec->line); goto exit; } } if (lookupPackage(spec, name, flag, &pkg)) { rpmlog(RPMLOG_ERR, _("line %d: Package does not exist: %s\n"), spec->lineNum, spec->line); goto exit; } if (tag != RPMTAG_TRIGGERSCRIPTS) { if (headerIsEntry(pkg->header, progtag)) { rpmlog(RPMLOG_ERR, _("line %d: Second %s\n"), spec->lineNum, partname); goto exit; } } if ((rc = poptParseArgvString(prog, &progArgc, &progArgv))) { rpmlog(RPMLOG_ERR, _("line %d: Error parsing %s: %s\n"), spec->lineNum, partname, poptStrerror(rc)); goto exit; } sb = newStringBuf(); if ((rc = readLine(spec, STRIP_NOTHING)) > 0) { nextPart = PART_NONE; } else if (rc < 0) { goto exit; } else { while (! (nextPart = isPart(spec->line))) { appendStringBuf(sb, spec->line); if ((rc = readLine(spec, STRIP_NOTHING)) > 0) { nextPart = PART_NONE; break; } else if (rc < 0) { goto exit; } } } stripTrailingBlanksStringBuf(sb); p = getStringBuf(sb); #ifdef WITH_LUA if (rstreq(progArgv[0], "<lua>")) { rpmlua lua = NULL; /* Global state. */ if (rpmluaCheckScript(lua, p, partname) != RPMRC_OK) { goto exit; } (void) rpmlibNeedsFeature(pkg, "BuiltinLuaScripts", "4.2.2-1"); } else #endif if (progArgv[0][0] == '<') { rpmlog(RPMLOG_ERR, _("line %d: unsupported internal script: %s\n"), spec->lineNum, progArgv[0]); goto exit; } else { (void) addReqProv(pkg, RPMTAG_REQUIRENAME, progArgv[0], NULL, (tagflags | RPMSENSE_INTERP), 0); } if (scriptFlags) { rpmlibNeedsFeature(pkg, "ScriptletExpansion", "4.9.0-1"); } /* Trigger script insertion is always delayed in order to */ /* get the index right. */ if (tag == RPMTAG_TRIGGERSCRIPTS || tag == RPMTAG_FILETRIGGERSCRIPTS || tag == RPMTAG_TRANSFILETRIGGERSCRIPTS) { if (progArgc > 1) { rpmlog(RPMLOG_ERR, _("line %d: interpreter arguments not allowed in triggers: %s\n"), spec->lineNum, prog); goto exit; } /* Add file/index/prog triple to the trigger file list */ index = addTriggerIndex(pkg, file, p, progArgv[0], scriptFlags, tag); /* Generate the trigger tags */ if (parseRCPOT(spec, pkg, reqargs, reqtag, index, tagflags)) goto exit; } else { struct rpmtd_s td; /* * XXX Ancient rpm uses STRING, not STRING_ARRAY type here. Construct * the td manually and preserve legacy compat for now... */ rpmtdReset(&td); td.tag = progtag; td.count = progArgc; if (progArgc == 1) { td.data = (void *) *progArgv; td.type = RPM_STRING_TYPE; } else { (void) rpmlibNeedsFeature(pkg, "ScriptletInterpreterArgs", "4.0.3-1"); td.data = progArgv; td.type = RPM_STRING_ARRAY_TYPE; } headerPut(pkg->header, &td, HEADERPUT_DEFAULT); if (*p != '\0') { headerPutString(pkg->header, tag, p); } if (scriptFlags) { headerPutUint32(pkg->header, flagtag, &scriptFlags, 1); } if (file) { switch (parsePart) { case PART_PRE: pkg->preInFile = xstrdup(file); break; case PART_POST: pkg->postInFile = xstrdup(file); break; case PART_PREUN: pkg->preUnFile = xstrdup(file); break; case PART_POSTUN: pkg->postUnFile = xstrdup(file); break; case PART_PRETRANS: pkg->preTransFile = xstrdup(file); break; case PART_POSTTRANS: pkg->postTransFile = xstrdup(file); break; case PART_VERIFYSCRIPT: pkg->verifyFile = xstrdup(file); break; } } } res = nextPart; exit: free(reqargs); freeStringBuf(sb); free(progArgv); free(argv); poptFreeContext(optCon); return res; }
rpmRC parseRCPOT(rpmSpec spec, Package pkg, const char *field, rpmTagVal tagN, int index, rpmsenseFlags tagflags) { const char *r, *re, *v, *ve; char *emsg = NULL; char * N = NULL, * EVR = NULL; rpmTagVal nametag = RPMTAG_NOT_FOUND; rpmsenseFlags Flags; rpmds *pdsp = NULL; rpmRC rc = RPMRC_FAIL; /* assume failure */ switch (tagN) { default: case RPMTAG_REQUIREFLAGS: nametag = RPMTAG_REQUIRENAME; tagflags |= RPMSENSE_ANY; break; case RPMTAG_RECOMMENDFLAGS: nametag = RPMTAG_RECOMMENDNAME; break; case RPMTAG_SUGGESTFLAGS: nametag = RPMTAG_SUGGESTNAME; break; case RPMTAG_SUPPLEMENTFLAGS: nametag = RPMTAG_SUPPLEMENTNAME; break; case RPMTAG_ENHANCEFLAGS: nametag = RPMTAG_ENHANCENAME; break; case RPMTAG_PROVIDEFLAGS: nametag = RPMTAG_PROVIDENAME; break; case RPMTAG_OBSOLETEFLAGS: nametag = RPMTAG_OBSOLETENAME; break; case RPMTAG_CONFLICTFLAGS: nametag = RPMTAG_CONFLICTNAME; break; case RPMTAG_ORDERFLAGS: nametag = RPMTAG_ORDERNAME; break; case RPMTAG_PREREQ: /* XXX map legacy PreReq into Requires(pre,preun) */ nametag = RPMTAG_REQUIRENAME; tagflags |= (RPMSENSE_SCRIPT_PRE|RPMSENSE_SCRIPT_PREUN); break; case RPMTAG_TRIGGERPREIN: nametag = RPMTAG_TRIGGERNAME; tagflags |= RPMSENSE_TRIGGERPREIN; break; case RPMTAG_TRIGGERIN: nametag = RPMTAG_TRIGGERNAME; tagflags |= RPMSENSE_TRIGGERIN; break; case RPMTAG_TRIGGERPOSTUN: nametag = RPMTAG_TRIGGERNAME; tagflags |= RPMSENSE_TRIGGERPOSTUN; break; case RPMTAG_TRIGGERUN: nametag = RPMTAG_TRIGGERNAME; tagflags |= RPMSENSE_TRIGGERUN; break; case RPMTAG_BUILDPREREQ: case RPMTAG_BUILDREQUIRES: nametag = RPMTAG_REQUIRENAME; tagflags |= RPMSENSE_ANY; break; case RPMTAG_BUILDCONFLICTS: nametag = RPMTAG_CONFLICTNAME; break; case RPMTAG_FILETRIGGERIN: nametag = RPMTAG_FILETRIGGERNAME; tagflags |= RPMSENSE_TRIGGERIN; break; case RPMTAG_FILETRIGGERUN: nametag = RPMTAG_FILETRIGGERNAME; tagflags |= RPMSENSE_TRIGGERUN; break; case RPMTAG_FILETRIGGERPOSTUN: nametag = RPMTAG_FILETRIGGERNAME; tagflags |= RPMSENSE_TRIGGERPOSTUN; break; case RPMTAG_TRANSFILETRIGGERIN: nametag = RPMTAG_TRANSFILETRIGGERNAME; tagflags |= RPMSENSE_TRIGGERIN; break; case RPMTAG_TRANSFILETRIGGERUN: nametag = RPMTAG_TRANSFILETRIGGERNAME; tagflags |= RPMSENSE_TRIGGERUN; break; case RPMTAG_TRANSFILETRIGGERPOSTUN: nametag = RPMTAG_TRANSFILETRIGGERNAME; tagflags |= RPMSENSE_TRIGGERPOSTUN; break; } for (r = field; *r != '\0'; r = re) { SKIPWHITE(r); if (*r == '\0') break; Flags = (tagflags & ~RPMSENSE_SENSEMASK); if (r[0] == '(') { struct parseRCPOTRichData data; if (nametag != RPMTAG_REQUIRENAME && nametag != RPMTAG_CONFLICTNAME && nametag != RPMTAG_RECOMMENDNAME && nametag != RPMTAG_SUPPLEMENTNAME && nametag != RPMTAG_SUGGESTNAME && nametag != RPMTAG_ENHANCENAME) { rasprintf(&emsg, _("No rich dependencies allowed for this type")); goto exit; } data.spec = spec; data.sb = newStringBuf(); if (rpmrichParse(&r, &emsg, parseRCPOTRichCB, &data) != RPMRC_OK) { freeStringBuf(data.sb); goto exit; } if (addReqProv(pkg, nametag, getStringBuf(data.sb), NULL, Flags | RPMSENSE_RICH, index)) { rasprintf(&emsg, _("invalid dependency")); freeStringBuf(data.sb); goto exit; } freeStringBuf(data.sb); re = r; continue; } re = r; SKIPNONWHITE(re); N = xmalloc((re-r) + 1); rstrlcpy(N, r, (re-r) + 1); /* Parse EVR */ EVR = NULL; v = re; SKIPWHITE(v); ve = v; SKIPNONWHITE(ve); re = v; /* ==> next token (if no EVR found) starts here */ /* Check for possible logical operator */ if (ve > v) { rpmsenseFlags sense = rpmParseDSFlags(v, ve - v); if (sense) { Flags |= sense; /* now parse EVR */ v = ve; SKIPWHITE(v); ve = v; SKIPNONWHITE(ve); if (*v == '\0' || ve == v) { rasprintf(&emsg, _("Version required")); goto exit; } EVR = xmalloc((ve-v) + 1); rstrlcpy(EVR, v, (ve-v) + 1); re = ve; /* ==> next token after EVR string starts here */ } } /* check that dependency is well-formed */ if (checkDep(spec, N, EVR, &emsg)) goto exit; if (nametag == RPMTAG_FILETRIGGERNAME || nametag == RPMTAG_TRANSFILETRIGGERNAME) { if (N[0] != '/') { rasprintf(&emsg, _("Only absolute paths are allowed in " "file triggers")); } } /* Deny more "normal" triggers fired by the same pakage. File triggers are ok */ pdsp = packageDependencies(pkg, nametag); rpmdsInit(*pdsp); if (nametag == RPMTAG_TRIGGERNAME) { while (rpmdsNext(*pdsp) >= 0) { if (rstreq(rpmdsN(*pdsp), N) && ((rpmdsFlags(*pdsp) & tagflags))) { rasprintf(&emsg, _("Trigger fired by the same package " "is already defined in spec file")); goto exit; } } } if (addReqProv(pkg, nametag, N, EVR, Flags, index)) { rasprintf(&emsg, _("invalid dependency")); goto exit; } N = _free(N); EVR = _free(EVR); } rc = RPMRC_OK; exit: if (emsg) { int lvl = (rc == RPMRC_OK) ? RPMLOG_WARNING : RPMLOG_ERR; /* Automatic dependencies don't relate to spec lines */ if (tagflags & (RPMSENSE_FIND_REQUIRES|RPMSENSE_FIND_PROVIDES)) { rpmlog(lvl, "%s: %s\n", emsg, r); } else { rpmlog(lvl, _("line %d: %s: %s\n"), spec->lineNum, emsg, spec->line); } free(emsg); } _free(N); _free(EVR); return rc; }
/**@todo Infinite loops through manifest files exist, operator error for now. */ rpmRC rpmReadPackageManifest(FD_t fd, int * argcPtr, char *** argvPtr) { StringBuf sb = newStringBuf(); char * s = NULL; char * se; int ac = 0; char ** av = NULL; int argc = (argcPtr ? *argcPtr : 0); char ** argv = (argvPtr ? *argvPtr : NULL); FILE * f = fdGetFILE(fd); rpmRC rpmrc = RPMRC_OK; int i, j, next, npre; if (f != NULL) while (1) { char line[BUFSIZ]; /* Read next line. */ s = fgets(line, sizeof(line) - 1, f); if (s == NULL) { /* XXX Ferror check needed */ break; } /* Skip comments. */ if ((se = strchr(s, '#')) != NULL) *se = '\0'; /* Trim white space. */ se = s + strlen(s); while (se > s && (se[-1] == '\n' || se[-1] == '\r')) *(--se) = '\0'; while (*s && strchr(" \f\n\r\t\v", *s) != NULL) s++; if (*s == '\0') continue; /* Sanity checks: skip obviously binary lines and dash (for stdin) */ if (*s < 32 || rstreq(s, "-")) { rpmrc = RPMRC_NOTFOUND; goto exit; } /* Concatenate next line in buffer. */ *se++ = ' '; *se = '\0'; appendStringBuf(sb, s); } if (s == NULL) /* XXX always true */ s = getStringBuf(sb); if (!(s && *s)) { rpmrc = RPMRC_NOTFOUND; goto exit; } /* Glob manifest items. */ rpmrc = rpmGlob(s, &ac, &av); if (rpmrc != RPMRC_OK) goto exit; rpmlog(RPMLOG_DEBUG, "adding %d args from manifest.\n", ac); /* Count non-NULL args, keeping track of 1st arg after last NULL. */ npre = 0; next = 0; if (argv != NULL) for (i = 0; i < argc; i++) { if (argv[i] != NULL) npre++; else if (i >= next) next = i + 1; } /* Copy old arg list, inserting manifest before argv[next]. */ if (argv != NULL) { int nac = npre + ac; char ** nav = xcalloc((nac + 1), sizeof(*nav)); for (i = 0, j = 0; i < next; i++) { if (argv[i] != NULL) nav[j++] = argv[i]; } if (ac) memcpy(nav + j, av, ac * sizeof(*nav)); if ((argc - next) > 0) memcpy(nav + j + ac, argv + next, (argc - next) * sizeof(*nav)); nav[nac] = NULL; if (argvPtr) *argvPtr = argv = _free(argv); av = _free(av); av = nav; ac = nac; } /* Save new argc/argv list. */ if (argvPtr) { *argvPtr = _free(*argvPtr); *argvPtr = av; } if (argcPtr) *argcPtr = ac; exit: if (argvPtr == NULL || (rpmrc != RPMRC_OK && av)) { if (av) for (i = 0; i < ac; i++) av[i] = _free(av[i]); av = _free(av); } sb = freeStringBuf(sb); /* FIX: *argvPtr may be NULL. */ return rpmrc; }
/** * 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 RPMRC_OK on success */ static int doSetupMacro(rpmSpec spec, const char *line) { char *buf = NULL; StringBuf before = newStringBuf(); StringBuf after = newStringBuf(); poptContext optCon = NULL; int argc; const char ** argv = NULL; int arg; const char * optArg; int xx; rpmRC rc = RPMRC_FAIL; uint32_t num; int leaveDirs = 0, skipDefaultAction = 0; int createDir = 0, quietly = 0; const char * dirName = NULL; struct poptOption optionsTable[] = { { NULL, 'a', POPT_ARG_STRING, NULL, 'a', NULL, NULL}, { NULL, 'b', POPT_ARG_STRING, NULL, 'b', NULL, NULL}, { NULL, 'c', 0, &createDir, 0, NULL, NULL}, { NULL, 'D', 0, &leaveDirs, 0, NULL, NULL}, { NULL, 'n', POPT_ARG_STRING, &dirName, 0, NULL, NULL}, { NULL, 'T', 0, &skipDefaultAction, 0, NULL, NULL}, { NULL, 'q', 0, &quietly, 0, NULL, NULL}, { 0, 0, 0, 0, 0, NULL, NULL} }; if ((xx = poptParseArgvString(line, &argc, &argv))) { rpmlog(RPMLOG_ERR, _("Error parsing %%setup: %s\n"), poptStrerror(xx)); goto exit; } optCon = poptGetContext(NULL, argc, argv, optionsTable, 0); while ((arg = poptGetNextOpt(optCon)) > 0) { optArg = poptGetOptArg(optCon); /* We only parse -a and -b here */ if (parseUnsignedNum(optArg, &num)) { rpmlog(RPMLOG_ERR, _("line %d: Bad arg to %%setup: %s\n"), spec->lineNum, (optArg ? optArg : "???")); goto exit; } { char *chptr = doUntar(spec, num, quietly); if (chptr == NULL) goto exit; appendLineStringBuf((arg == 'a' ? after : before), chptr); free(chptr); } } if (arg < -1) { rpmlog(RPMLOG_ERR, _("line %d: Bad %%setup option %s: %s\n"), spec->lineNum, poptBadOption(optCon, POPT_BADOPTION_NOALIAS), poptStrerror(arg)); goto exit; } if (dirName) { spec->buildSubdir = xstrdup(dirName); } else { rasprintf(&spec->buildSubdir, "%s-%s", headerGetString(spec->packages->header, RPMTAG_NAME), headerGetString(spec->packages->header, RPMTAG_VERSION)); } addMacro(spec->macros, "buildsubdir", NULL, spec->buildSubdir, RMIL_SPEC); /* cd to the build dir */ { char * buildDir = rpmGenPath(spec->rootDir, "%{_builddir}", ""); rasprintf(&buf, "cd '%s'", buildDir); appendLineStringBuf(spec->prep, buf); free(buf); free(buildDir); } /* delete any old sources */ if (!leaveDirs) { rasprintf(&buf, "rm -rf '%s'", spec->buildSubdir); appendLineStringBuf(spec->prep, buf); free(buf); } /* if necessary, create and cd into the proper dir */ if (createDir) { rasprintf(&buf, RPM_MKDIR_P " %s\ncd '%s'", spec->buildSubdir, spec->buildSubdir); appendLineStringBuf(spec->prep, buf); free(buf); } /* do the default action */ if (!createDir && !skipDefaultAction) { char *chptr = doUntar(spec, 0, quietly); if (!chptr) goto exit; appendLineStringBuf(spec->prep, chptr); free(chptr); } appendStringBuf(spec->prep, getStringBuf(before)); if (!createDir) { rasprintf(&buf, "cd '%s'", spec->buildSubdir); appendLineStringBuf(spec->prep, buf); free(buf); } if (createDir && !skipDefaultAction) { char *chptr = doUntar(spec, 0, quietly); if (chptr == NULL) goto exit; appendLineStringBuf(spec->prep, chptr); free(chptr); } appendStringBuf(spec->prep, getStringBuf(after)); /* Fix the permissions of the setup build tree */ { char *fix = rpmExpand("%{_fixperms} .", NULL); if (fix && *fix != '%') { appendLineStringBuf(spec->prep, fix); } free(fix); } rc = RPMRC_OK; exit: freeStringBuf(before); freeStringBuf(after); poptFreeContext(optCon); free(argv); return rc; }