int parseFiles(rpmSpec spec) { int nextPart, res = PART_ERROR; Package pkg; int rc, argc; int arg; const char ** argv = NULL; const char *name = NULL; int flag = PART_SUBNAME; poptContext optCon = NULL; struct poptOption optionsTable[] = { { NULL, 'n', POPT_ARG_STRING, &name, 'n', NULL, NULL}, { NULL, 'f', POPT_ARG_STRING, NULL, 'f', NULL, NULL}, { 0, 0, 0, 0, 0, NULL, NULL} }; /* XXX unmask %license while parsing %files */ rpmPushMacro(spec->macros, "license", NULL, "%%license", RMIL_SPEC); if ((rc = poptParseArgvString(spec->line, &argc, &argv))) { rpmlog(RPMLOG_ERR, _("line %d: Error parsing %%files: %s\n"), spec->lineNum, poptStrerror(rc)); goto exit; } optCon = poptGetContext(NULL, argc, argv, optionsTable, 0); while ((arg = poptGetNextOpt(optCon)) > 0) { if (arg == 'n') { flag = PART_NAME; } } if (arg < -1) { rpmlog(RPMLOG_ERR, _("line %d: Bad option %s: %s\n"), spec->lineNum, poptBadOption(optCon, POPT_BADOPTION_NOALIAS), spec->line); goto exit; } if (poptPeekArg(optCon)) { if (name == NULL) name = poptGetArg(optCon); if (poptPeekArg(optCon)) { rpmlog(RPMLOG_ERR, _("line %d: Too many names: %s\n"), spec->lineNum, spec->line); goto exit; } } if (lookupPackage(spec, name, flag, &pkg)) goto exit; /* * This should be an error, but its surprisingly commonly abused for the * effect of multiple -f arguments in versions that dont support it. * Warn but preserve behavior, except for leaking memory. */ if (pkg->fileList != NULL) { rpmlog(RPMLOG_WARNING, _("line %d: multiple %%files for package '%s'\n"), spec->lineNum, rpmstrPoolStr(pkg->pool, pkg->name)); pkg->fileList = argvFree(pkg->fileList); } for (arg=1; arg<argc; arg++) { if (rstreq(argv[arg], "-f") && argv[arg+1]) { char *file = rpmGetPath(argv[arg+1], NULL); argvAdd(&(pkg->fileFile), file); free(file); } } pkg->fileList = argvNew(); if ((rc = readLine(spec, STRIP_COMMENTS)) > 0) { nextPart = PART_NONE; } else if (rc < 0) { goto exit; } else { while (! (nextPart = isPart(spec->line))) { argvAdd(&(pkg->fileList), spec->line); if ((rc = readLine(spec, STRIP_COMMENTS)) > 0) { nextPart = PART_NONE; break; } else if (rc < 0) { goto exit; } } } res = nextPart; exit: rpmPopMacro(NULL, "license"); free(argv); poptFreeContext(optCon); return res; }
int 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; }
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 parseFiles(rpmSpec spec) { int nextPart, res = PART_ERROR; Package pkg; int rc, argc; int arg; const char ** argv = NULL; const char *name = NULL; const char *file = 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, &file, 'f', NULL, NULL}, { 0, 0, 0, 0, 0, NULL, NULL} }; 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; } if (pkg->fileList != NULL) { rpmlog(RPMLOG_ERR, _("line %d: Second %%files list\n"), spec->lineNum); goto exit; } if (file) { /* XXX not necessary as readline has expanded already, but won't hurt. */ pkg->fileFile = rpmGetPath(file, NULL); } pkg->fileList = newStringBuf(); if ((rc = readLine(spec, STRIP_COMMENTS)) > 0) { nextPart = PART_NONE; } else if (rc < 0) { goto exit; } else { while (! (nextPart = isPart(spec->line))) { appendStringBuf(pkg->fileList, spec->line); if ((rc = readLine(spec, STRIP_COMMENTS)) > 0) { nextPart = PART_NONE; break; } else if (rc < 0) { goto exit; } } } res = nextPart; exit: argv = _free(argv); optCon = poptFreeContext(optCon); return res; }
int parseFiles(rpmSpec spec) { int nextPart, res = PART_ERROR; Package pkg; int rc, argc; int arg; const char ** argv = NULL; const char *name = NULL; int flag = PART_SUBNAME; poptContext optCon = NULL; struct poptOption optionsTable[] = { { NULL, 'n', POPT_ARG_STRING, &name, 'n', NULL, NULL}, { NULL, 'f', POPT_ARG_STRING, NULL, 'f', NULL, NULL}, { 0, 0, 0, 0, 0, NULL, NULL} }; /* XXX unmask %license while parsing %files */ 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; }
/* XXX should return rpmParseState, but RPMRC_FAIL forces int return. */ int parsePreamble(Spec spec, int initialPackage) { HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he)); rpmParseState nextPart; int xx; char *linep; Package pkg; char NVR[BUFSIZ]; char lang[BUFSIZ]; rpmRC rc; strcpy(NVR, "(main package)"); pkg = newPackage(spec); if (spec->packages == NULL) { spec->packages = pkg; assert(initialPackage); } else if (! initialPackage) { char *name = NULL; rpmParseState flag; Package lastpkg; /* There is one option to %package: <pkg> or -n <pkg> */ flag = PART_NONE; if (parseSimplePart(spec, &name, &flag)) { rpmlog(RPMLOG_ERR, _("Bad package specification: %s\n"), spec->line); pkg = freePackages(pkg); return RPMRC_FAIL; } lastpkg = NULL; if (lookupPackage(spec, name, flag, &lastpkg) == RPMRC_OK) { pkg->next = lastpkg->next; } else { /* Add package to end of list */ for (lastpkg = spec->packages; lastpkg->next != NULL; lastpkg = lastpkg->next) {}; } assert(lastpkg != NULL); lastpkg->next = pkg; /* Construct the package */ if (flag == PART_SUBNAME) { he->tag = RPMTAG_NAME; xx = headerGet(spec->packages->header, he, 0); sprintf(NVR, "%s-%s", he->p.str, name); he->p.ptr = _free(he->p.ptr); } else strcpy(NVR, name); name = _free(name); he->tag = RPMTAG_NAME; he->t = RPM_STRING_TYPE; he->p.str = NVR; he->c = 1; xx = headerPut(pkg->header, he, 0); } if ((rc = readLine(spec, STRIP_TRAILINGSPACE | STRIP_COMMENTS)) > 0) { nextPart = PART_NONE; } else { if (rc) return rc; while ((nextPart = isPart(spec)) == PART_NONE) { const char * macro = NULL; rpmTag tag = 0; /* Skip blank lines */ linep = spec->line; SKIPSPACE(linep); if (*linep != '\0') { if (findPreambleTag(spec, &tag, ¯o, lang)) { rpmlog(RPMLOG_ERR, _("line %d: Unknown tag: %s\n"), spec->lineNum, spec->line); return RPMRC_FAIL; } if (handlePreambleTag(spec, pkg, tag, macro, lang)) return RPMRC_FAIL; if (spec->BANames && !spec->recursing && spec->toplevel) return PART_BUILDARCHITECTURES; } if ((rc = readLine(spec, STRIP_TRAILINGSPACE | STRIP_COMMENTS)) > 0) { nextPart = PART_NONE; break; } if (rc) return rc; } } /* Do some final processing on the header */ /* * Expand buildroot one more time to get %{version} and the like * from the main package. */ if (initialPackage) { const char *s = rpmExpand("%{?buildroot}", NULL); if (s && *s) (void) addMacro(NULL, "buildroot", NULL, s, -1); s = _free(s); } /* XXX Skip valid arch check if not building binary package */ if (!spec->anyarch && checkForValidArchitectures(spec)) return RPMRC_FAIL; if (pkg == spec->packages) fillOutMainPackage(pkg->header); if (checkForDuplicates(pkg->header, NVR) != RPMRC_OK) return RPMRC_FAIL; if (pkg != spec->packages) headerCopyTags(spec->packages->header, pkg->header, (void *)copyTagsDuringParse); #ifdef RPM_VENDOR_PLD /* rpm-epoch0 */ /* Add Epoch: 0 to package header if it was not set by spec */ he->tag = RPMTAG_NAME; if (headerGet(spec->packages->header, he, 0) == 0) { rpmuint32_t num = 0; he->tag = RPMTAG_EPOCH; he->t = RPM_UINT32_TYPE; he->p.ui32p = # he->c = 1; xx = headerPut(pkg->header, he, 0); /* also declare %{epoch} to be same */ addMacro(spec->macros, "epoch", NULL, "0", RMIL_SPEC); } #endif /* RPM_VENDOR_PLD rpm-epoch0 */ if (checkForRequired(pkg->header, NVR) != RPMRC_OK) return RPMRC_FAIL; return nextPart; }
int parsePreamble(rpmSpec spec, int initialPackage) { int nextPart = PART_ERROR; int res = PART_ERROR; /* assume failure */ int rc; char *name, *linep; int flag = 0; Package pkg; char *NVR = NULL; char lang[BUFSIZ]; if (! initialPackage) { /* There is one option to %package: <pkg> or -n <pkg> */ if (parseSimplePart(spec->line, &name, &flag)) { rpmlog(RPMLOG_ERR, _("Bad package specification: %s\n"), spec->line); goto exit; } if (rpmCharCheck(spec, name, WHITELIST_NAME)) goto exit; if (!lookupPackage(spec, name, flag, NULL)) { free(name); goto exit; } /* Construct the package */ if (flag == PART_SUBNAME) { rasprintf(&NVR, "%s-%s", headerGetString(spec->packages->header, RPMTAG_NAME), name); } else NVR = xstrdup(name); free(name); pkg = newPackage(NVR, spec->pool, &spec->packages); headerPutString(pkg->header, RPMTAG_NAME, NVR); } else { NVR = xstrdup("(main package)"); pkg = newPackage(NULL, spec->pool, &spec->packages); spec->sourcePackage = newPackage(NULL, spec->pool, NULL); } if ((rc = readLine(spec, STRIP_TRAILINGSPACE | STRIP_COMMENTS)) > 0) { nextPart = PART_NONE; } else if (rc < 0) { goto exit; } else { while (! (nextPart = isPart(spec->line))) { const char * macro; rpmTagVal tag; /* Skip blank lines */ linep = spec->line; SKIPSPACE(linep); if (*linep != '\0') { if (findPreambleTag(spec, &tag, ¯o, lang)) { if (spec->lineNum == 1 && (unsigned char)(spec->line[0]) == 0xed && (unsigned char)(spec->line[1]) == 0xab && (unsigned char)(spec->line[2]) == 0xee && (unsigned char)(spec->line[3]) == 0xdb) { rpmlog(RPMLOG_ERR, _("Binary rpm package found. Expected spec file!\n")); goto exit; } rpmlog(RPMLOG_ERR, _("line %d: Unknown tag: %s\n"), spec->lineNum, spec->line); goto exit; } if (handlePreambleTag(spec, pkg, tag, macro, lang)) { goto exit; } if (spec->BANames && !spec->recursing) { res = PART_BUILDARCHITECTURES; goto exit; } } if ((rc = readLine(spec, STRIP_TRAILINGSPACE | STRIP_COMMENTS)) > 0) { nextPart = PART_NONE; break; } if (rc) { goto exit; } } } /* * Expand buildroot one more time to get %{version} and the like * from the main package, validate sanity. The spec->buildRoot could * still contain unexpanded macros but it cannot be empty or '/', and it * can't be messed with by anything spec does beyond this point. */ if (initialPackage) { char *buildRoot = rpmGetPath(spec->buildRoot, NULL); if (*buildRoot == '\0') { rpmlog(RPMLOG_ERR, _("%%{buildroot} couldn't be empty\n")); goto exit; } if (rstreq(buildRoot, "/")) { rpmlog(RPMLOG_ERR, _("%%{buildroot} can not be \"/\"\n")); goto exit; } free(spec->buildRoot); spec->buildRoot = buildRoot; rpmPushMacro(spec->macros, "buildroot", NULL, spec->buildRoot, RMIL_SPEC); } /* XXX Skip valid arch check if not building binary package */ if (!(spec->flags & RPMSPEC_ANYARCH) && checkForValidArchitectures(spec)) { goto exit; } /* It is the main package */ if (pkg == spec->packages) { fillOutMainPackage(pkg->header); /* Define group tag to something when group is undefined in main package*/ if (!headerIsEntry(pkg->header, RPMTAG_GROUP)) { headerPutString(pkg->header, RPMTAG_GROUP, "Unspecified"); } } if (checkForDuplicates(pkg->header, NVR)) { goto exit; } if (pkg != spec->packages) { headerCopyTags(spec->packages->header, pkg->header, (rpmTagVal *)copyTagsDuringParse); } if (checkForRequired(pkg->header, NVR)) { goto exit; } /* if we get down here nextPart has been set to non-error */ res = nextPart; exit: free(NVR); return res; }