static Header make_pkguinf_hdr(struct pkguinf *pkgu, int *langs_cnt) { int i, nlangs = 0; Header hdr = NULL; unsigned hdr_size; tn_array *langs; hdr = headerNew(); if ((langs = pkgu->_langs_rpmhdr) == NULL) langs = pkguinf_langs(pkgu); for (i=0; i < n_array_size(langs); i++) { const char *lang = n_array_nth(langs, i); struct pkguinf_i18n *inf = n_hash_get(pkgu->_ht, lang); headerAddI18NString(hdr, RPMTAG_SUMMARY, inf->summary, lang); headerAddI18NString(hdr, RPMTAG_DESCRIPTION, inf->description, lang); } #if 0 if (pkgu->vendor) headerAddEntry(hdr, RPMTAG_VENDOR, RPM_STRING_TYPE, pkgu->vendor, 1); if (pkgu->license) headerAddEntry(hdr, PM_RPMTAG_LICENSE, RPM_STRING_TYPE, pkgu->license, 1); if (pkgu->url) headerAddEntry(hdr, RPMTAG_URL, RPM_STRING_TYPE, pkgu->url, 1); if (pkgu->distro) headerAddEntry(hdr, RPMTAG_DISTRIBUTION, RPM_STRING_TYPE, pkgu->distro, 1); if (pkgu->buildhost) headerAddEntry(hdr, RPMTAG_BUILDHOST, RPM_STRING_TYPE, pkgu->buildhost, 1); #endif hdr_size = hacked_headerSizeof(hdr); if (hdr_size > UINT16_MAX) { logn(LOGERR, "internal: header size too large: %d", hdr_size); headerFree(hdr); hdr = NULL; } if (langs_cnt) *langs_cnt = nlangs; return hdr; }
int addLangTag(rpmSpec spec, Header h, rpmTagVal tag, const char *field, const char *lang) { int skip = 0; if (haveLangTag(h, tag, lang)) { /* Turn this into an error eventually */ rpmlog(RPMLOG_WARNING, _("line %d: second %s\n"), spec->lineNum, rpmTagGetName(tag)); } if (!*lang) { headerPutString(h, tag, field); } else { skip = ((spec->flags & RPMSPEC_NOLANG) && !rstreq(lang, RPMBUILD_DEFAULT_LANG)); if (skip) return 0; headerAddI18NString(h, tag, field, lang); } return 0; }
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; }
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; }