00001
00006 #include "system.h"
00007
00008 #include <rpmio.h>
00009
00010 #define _RPMEVR_INTERNAL
00011 #define _RPMTAG_INTERNAL
00012 #include <rpmbuild.h>
00013 #include "debug.h"
00014
00015
00016
00017
00020
00021 static rpmTag copyTagsDuringParse[] = {
00022 RPMTAG_EPOCH,
00023 RPMTAG_VERSION,
00024 RPMTAG_RELEASE,
00025 RPMTAG_LICENSE,
00026 RPMTAG_PACKAGER,
00027 RPMTAG_DISTRIBUTION,
00028 RPMTAG_DISTURL,
00029 RPMTAG_VENDOR,
00030 RPMTAG_ICON,
00031 RPMTAG_GIF,
00032 RPMTAG_XPM,
00033 RPMTAG_URL,
00034 RPMTAG_CHANGELOGTIME,
00035 RPMTAG_CHANGELOGNAME,
00036 RPMTAG_CHANGELOGTEXT,
00037 RPMTAG_PREFIXES,
00038 RPMTAG_DISTTAG,
00039 RPMTAG_CVSID,
00040 RPMTAG_VARIANTS,
00041 RPMTAG_XMAJOR,
00042 RPMTAG_XMINOR,
00043 RPMTAG_REPOTAG,
00044 RPMTAG_KEYWORDS,
00045 0
00046 };
00047
00050
00051 static rpmTag requiredTags[] = {
00052 RPMTAG_NAME,
00053 RPMTAG_VERSION,
00054 RPMTAG_RELEASE,
00055 RPMTAG_SUMMARY,
00056 RPMTAG_GROUP,
00057 RPMTAG_LICENSE,
00058 0
00059 };
00060
00063 static void addOrAppendListEntry(Header h, rpmTag tag, char * line)
00064
00065 {
00066 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
00067 int xx;
00068 int argc;
00069 const char **argv;
00070
00071 xx = poptParseArgvString(line, &argc, &argv);
00072 if (argc) {
00073 he->tag = tag;
00074 he->t = RPM_STRING_ARRAY_TYPE;
00075 he->p.argv = argv;
00076 he->c = argc;
00077 he->append = 1;
00078 xx = headerPut(h, he, 0);
00079 he->append = 0;
00080 }
00081 argv = _free(argv);
00082 }
00083
00084
00085
00086
00089 static int parseSimplePart(char *line, char **name,
00090 rpmParseState *flag)
00091
00092
00093 {
00094 char *tok;
00095 char linebuf[BUFSIZ];
00096 static char buf[BUFSIZ];
00097
00098 strcpy(linebuf, line);
00099
00100
00101 (void)strtok(linebuf, " \t\n");
00102
00103 if (!(tok = strtok(NULL, " \t\n"))) {
00104 *name = NULL;
00105 return 0;
00106 }
00107
00108 if (!strcmp(tok, "-n")) {
00109 if (!(tok = strtok(NULL, " \t\n")))
00110 return 1;
00111 *flag = PART_NAME;
00112 } else {
00113 *flag = PART_SUBNAME;
00114 }
00115 strcpy(buf, tok);
00116 *name = buf;
00117
00118 return (strtok(NULL, " \t\n")) ? 1 : 0;
00119 }
00120
00123 static inline int parseYesNo(const char * s)
00124
00125 {
00126 return ((!s || (s[0] == 'n' || s[0] == 'N' || s[0] == '0') ||
00127 !xstrcasecmp(s, "false") || !xstrcasecmp(s, "off"))
00128 ? 0 : 1);
00129 }
00130
00131 typedef struct tokenBits_s {
00132
00133 const char * name;
00134 rpmsenseFlags bits;
00135 } * tokenBits;
00136
00139
00140 static struct tokenBits_s installScriptBits[] = {
00141 { "interp", RPMSENSE_INTERP },
00142 { "preun", RPMSENSE_SCRIPT_PREUN },
00143 { "pre", RPMSENSE_SCRIPT_PRE },
00144 { "postun", RPMSENSE_SCRIPT_POSTUN },
00145 { "post", RPMSENSE_SCRIPT_POST },
00146 { "rpmlib", RPMSENSE_RPMLIB },
00147 { "verify", RPMSENSE_SCRIPT_VERIFY },
00148 { "hint", RPMSENSE_MISSINGOK },
00149 { NULL, 0 }
00150 };
00151
00154
00155 static struct tokenBits_s buildScriptBits[] = {
00156 { "prep", RPMSENSE_SCRIPT_PREP },
00157 { "build", RPMSENSE_SCRIPT_BUILD },
00158 { "install", RPMSENSE_SCRIPT_INSTALL },
00159 { "clean", RPMSENSE_SCRIPT_CLEAN },
00160 { "hint", RPMSENSE_MISSINGOK },
00161 { NULL, 0 }
00162 };
00163
00166 static int parseBits(const char * s, const tokenBits tokbits,
00167 rpmsenseFlags * bp)
00168
00169 {
00170 tokenBits tb;
00171 const char * se;
00172 rpmsenseFlags bits = RPMSENSE_ANY;
00173 int c = 0;
00174
00175 if (s) {
00176 while (*s != '\0') {
00177 while ((c = *s) && xisspace(c)) s++;
00178 se = s;
00179 while ((c = *se) && xisalpha(c)) se++;
00180 if (s == se)
00181 break;
00182 for (tb = tokbits; tb->name; tb++) {
00183 if (tb->name != NULL &&
00184 strlen(tb->name) == (se-s) && !strncmp(tb->name, s, (se-s)))
00185 break;
00186 }
00187 if (tb->name == NULL)
00188 break;
00189 bits |= tb->bits;
00190 while ((c = *se) && xisspace(c)) se++;
00191 if (c != ',')
00192 break;
00193 s = ++se;
00194 }
00195 }
00196 if (c == 0 && bp) *bp = bits;
00197 return (c ? RPMRC_FAIL : RPMRC_OK);
00198 }
00199
00202 static inline char * findLastChar(char * s)
00203
00204 {
00205 char *se = s + strlen(s);
00206
00207 while (--se > s && strchr(" \t\n\r", *se) != NULL)
00208 *se = '\0';
00209
00210 return se;
00211
00212 }
00213
00216 static int isMemberInEntry(Header h, const char *name, rpmTag tag)
00217
00218 {
00219 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
00220 int rc = -1;
00221 int xx;
00222
00223 he->tag = tag;
00224 xx = headerGet(h, he, 0);
00225 if (!xx)
00226 return rc;
00227 rc = 0;
00228 while (he->c) {
00229 he->c--;
00230 if (xstrcasecmp(he->p.argv[he->c], name))
00231 continue;
00232 rc = 1;
00233 break;
00234 }
00235 he->p.ptr = _free(he->p.ptr);
00236 return rc;
00237 }
00238
00241 static int checkForValidArchitectures(Spec spec)
00242
00243
00244 {
00245 const char *arch = rpmExpand("%{_target_cpu}", NULL);
00246 const char *os = rpmExpand("%{_target_os}", NULL);
00247 int rc = RPMRC_FAIL;
00248
00249 if (isMemberInEntry(spec->sourceHeader, arch, RPMTAG_EXCLUDEARCH) == 1) {
00250 rpmlog(RPMLOG_ERR, _("Architecture is excluded: %s\n"), arch);
00251 goto exit;
00252 }
00253 if (isMemberInEntry(spec->sourceHeader, arch, RPMTAG_EXCLUSIVEARCH) == 0) {
00254 rpmlog(RPMLOG_ERR, _("Architecture is not included: %s\n"), arch);
00255 goto exit;
00256 }
00257 if (isMemberInEntry(spec->sourceHeader, os, RPMTAG_EXCLUDEOS) == 1) {
00258 rpmlog(RPMLOG_ERR, _("OS is excluded: %s\n"), os);
00259 goto exit;
00260 }
00261 if (isMemberInEntry(spec->sourceHeader, os, RPMTAG_EXCLUSIVEOS) == 0) {
00262 rpmlog(RPMLOG_ERR, _("OS is not included: %s\n"), os);
00263 goto exit;
00264 }
00265 rc = 0;
00266 exit:
00267 arch = _free(arch);
00268 os = _free(os);
00269 return rc;
00270 }
00271
00278 static rpmRC checkForRequired(Header h, const char * NVR)
00279
00280 {
00281 rpmTag * p;
00282 rpmRC rc = RPMRC_OK;
00283
00284 for (p = requiredTags; *p != 0; p++) {
00285 if (!headerIsEntry(h, *p)) {
00286 rpmlog(RPMLOG_ERR,
00287 _("%s field must be present in package: %s\n"),
00288 tagName(*p), NVR);
00289 rc = RPMRC_FAIL;
00290 }
00291 }
00292
00293 return rc;
00294 }
00295
00302 static rpmRC checkForDuplicates(Header h, const char * NVR)
00303
00304 {
00305 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
00306 HeaderIterator hi;
00307 rpmTag lastTag = 0;
00308 rpmRC rc = RPMRC_OK;
00309
00310 for (hi = headerInit(h);
00311 headerNext(hi, he, 0);
00312 he->p.ptr = _free(he->p.ptr))
00313 {
00314 if (he->tag != lastTag) {
00315 lastTag = he->tag;
00316 continue;
00317 }
00318 rpmlog(RPMLOG_ERR, _("Duplicate %s entries in package: %s\n"),
00319 tagName(he->tag), NVR);
00320 rc = RPMRC_FAIL;
00321 }
00322 hi = headerFini(hi);
00323
00324 return rc;
00325 }
00326
00329
00330 static struct optionalTag {
00331 rpmTag ot_tag;
00332
00333 const char * ot_mac;
00334 } optionalTags[] = {
00335 { RPMTAG_VENDOR, "%{vendor}" },
00336 { RPMTAG_PACKAGER, "%{packager}" },
00337 { RPMTAG_DISTRIBUTION, "%{distribution}" },
00338 { RPMTAG_DISTURL, "%{disturl}" },
00339 { 0xffffffff, "%{class}" },
00340 { -1, NULL }
00341 };
00342
00345 static void fillOutMainPackage(Header h)
00346
00347
00348 {
00349 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
00350 struct optionalTag *ot;
00351 int xx;
00352
00353 for (ot = optionalTags; ot->ot_mac != NULL; ot++) {
00354 const char * val;
00355 rpmTag tag;
00356
00357 tag = ot->ot_tag;
00358
00359
00360 if (tag == 0xffffffff) {
00361 val = tagCanonicalize(ot->ot_mac + (sizeof("%{")-1));
00362 tag = tagGenerate(val);
00363 val = _free(val);
00364 }
00365
00366 if (headerIsEntry(h, tag))
00367 continue;
00368 val = rpmExpand(ot->ot_mac, NULL);
00369 if (val && *val != '%') {
00370 he->tag = tag;
00371 he->t = RPM_STRING_TYPE;
00372 he->p.str = val;
00373 he->c = 1;
00374 xx = headerPut(h, he, 0);
00375 }
00376 val = _free(val);
00377 }
00378 }
00379
00382 static int doIcon(Spec spec, Header h)
00383
00384
00385 {
00386 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
00387 const char *fn, *Lurlfn = NULL;
00388 struct Source *sp;
00389 size_t iconsize = 2048;
00390 size_t nb;
00391 uint8_t * icon = alloca(iconsize+1);
00392 FD_t fd = NULL;
00393 int rc = RPMRC_FAIL;
00394 int urltype;
00395 int xx;
00396
00397 for (sp = spec->sources; sp != NULL; sp = sp->next) {
00398 if (sp->flags & RPMFILE_ICON)
00399 break;
00400 }
00401 if (sp == NULL) {
00402 rpmlog(RPMLOG_ERR, _("No icon file in sources\n"));
00403 goto exit;
00404 }
00405
00406 #if defined(RPM_VENDOR_OPENPKG)
00407
00408
00409
00410 Lurlfn = rpmGenPath(NULL, "%{_specdir}/", sp->source);
00411 if (access(Lurlfn, F_OK) == -1) {
00412 Lurlfn = _free(Lurlfn);
00413 Lurlfn = rpmGenPath(NULL, "%{_icondir}/", sp->source);
00414 }
00415 #else
00416 Lurlfn = rpmGenPath(NULL, "%{_icondir}/", sp->source);
00417 #endif
00418
00419 fn = NULL;
00420 urltype = urlPath(Lurlfn, &fn);
00421 switch (urltype) {
00422 case URL_IS_HTTPS:
00423 case URL_IS_HTTP:
00424 case URL_IS_FTP:
00425 case URL_IS_PATH:
00426 case URL_IS_UNKNOWN:
00427 break;
00428 case URL_IS_DASH:
00429 case URL_IS_HKP:
00430 rpmlog(RPMLOG_ERR, _("Invalid icon URL: %s\n"), Lurlfn);
00431 goto exit;
00432 break;
00433 }
00434
00435 fd = Fopen(fn, "r.fdio");
00436 if (fd == NULL || Ferror(fd)) {
00437 rpmlog(RPMLOG_ERR, _("Unable to open icon %s: %s\n"),
00438 fn, Fstrerror(fd));
00439 rc = RPMRC_FAIL;
00440 goto exit;
00441 }
00442
00443 *icon = '\0';
00444 nb = Fread(icon, sizeof(icon[0]), iconsize, fd);
00445 if (Ferror(fd) || nb == 0) {
00446 rpmlog(RPMLOG_ERR, _("Unable to read icon %s: %s\n"),
00447 fn, Fstrerror(fd));
00448 goto exit;
00449 }
00450 if (nb >= iconsize) {
00451 rpmlog(RPMLOG_ERR, _("Icon %s is too big (max. %d bytes)\n"),
00452 fn, iconsize);
00453 goto exit;
00454 }
00455
00456 if (icon[0] == 'G' && icon[1] == 'I' && icon[2] == 'F') {
00457 he->tag = RPMTAG_GIF;
00458 he->t = RPM_BIN_TYPE;
00459 he->p.ui8p = icon;
00460 he->c = nb;
00461 xx = headerPut(h, he, 0);
00462 } else
00463 if (icon[0] == '/' && icon[1] == '*' && icon[2] == ' '
00464 && icon[3] == 'X' && icon[4] == 'P' && icon[5] == 'M')
00465 {
00466 he->tag = RPMTAG_XPM;
00467 he->t = RPM_BIN_TYPE;
00468 he->p.ui8p = icon;
00469 he->c = nb;
00470 xx = headerPut(h, he, 0);
00471 } else {
00472 rpmlog(RPMLOG_ERR, _("Unknown icon type: %s\n"), fn);
00473 goto exit;
00474 }
00475 rc = 0;
00476
00477 exit:
00478 if (fd) {
00479 (void) Fclose(fd);
00480 fd = NULL;
00481 }
00482 Lurlfn = _free(Lurlfn);
00483 return rc;
00484 }
00485
00486 spectag stashSt(Spec spec, Header h, int tag, const char * lang)
00487 {
00488 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
00489 spectag t = NULL;
00490 int xx;
00491
00492 if (spec->st) {
00493 spectags st = spec->st;
00494 if (st->st_ntags == st->st_nalloc) {
00495 st->st_nalloc += 10;
00496 st->st_t = xrealloc(st->st_t, st->st_nalloc * sizeof(*(st->st_t)));
00497 }
00498 t = st->st_t + st->st_ntags++;
00499 t->t_tag = tag;
00500 t->t_startx = spec->lineNum - 1;
00501 t->t_nlines = 1;
00502 t->t_lang = xstrdup(lang);
00503 t->t_msgid = NULL;
00504 if (!(t->t_lang && strcmp(t->t_lang, RPMBUILD_DEFAULT_LANG))) {
00505 he->tag = RPMTAG_NAME;
00506 xx = headerGet(h, he, 0);
00507 if (xx) {
00508 char buf[1024];
00509 sprintf(buf, "%s(%s)", he->p.str, tagName(tag));
00510 t->t_msgid = xstrdup(buf);
00511 }
00512 he->p.ptr = _free(he->p.ptr);
00513 }
00514 }
00515
00516 return t;
00517
00518 }
00519
00520 #define SINGLE_TOKEN_ONLY \
00521 if (multiToken) { \
00522 rpmlog(RPMLOG_ERR, _("line %d: Tag takes single token only: %s\n"), \
00523 spec->lineNum, spec->line); \
00524 return RPMRC_FAIL; \
00525 }
00526
00527
00528 extern int noLang;
00529
00530
00533 static rpmRC handlePreambleTag(Spec spec, Package pkg, rpmTag tag,
00534 const char *macro, const char *lang)
00535
00536
00537
00538
00539
00540
00541
00542 {
00543 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
00544 char * field = spec->line;
00545 char * end;
00546 int multiToken = 0;
00547 rpmsenseFlags tagflags;
00548 int len;
00549 uint32_t num;
00550 int rc;
00551 int xx;
00552
00553 if (field == NULL) return RPMRC_FAIL;
00554
00555 while ((*field) && (*field != ':'))
00556 field++;
00557 if (*field != ':') {
00558 rpmlog(RPMLOG_ERR, _("line %d: Malformed tag: %s\n"),
00559 spec->lineNum, spec->line);
00560 return RPMRC_FAIL;
00561 }
00562 field++;
00563 SKIPSPACE(field);
00564 if (!*field) {
00565
00566 rpmlog(RPMLOG_ERR, _("line %d: Empty tag: %s\n"),
00567 spec->lineNum, spec->line);
00568 return RPMRC_FAIL;
00569 }
00570 end = findLastChar(field);
00571
00572
00573 end = field;
00574 SKIPNONSPACE(end);
00575 if (*end != '\0')
00576 multiToken = 1;
00577
00578 switch (tag) {
00579 case RPMTAG_NAME:
00580 case RPMTAG_VERSION:
00581 case RPMTAG_RELEASE:
00582 case RPMTAG_URL:
00583 case RPMTAG_DISTTAG:
00584 case RPMTAG_REPOTAG:
00585 case RPMTAG_CVSID:
00586 SINGLE_TOKEN_ONLY;
00587
00588 if (tag == RPMTAG_VERSION) {
00589 if (strchr(field, '-') != NULL) {
00590 rpmlog(RPMLOG_ERR, _("line %d: Illegal char '-' in %s: %s\n"),
00591 spec->lineNum, "version", spec->line);
00592 return RPMRC_FAIL;
00593 }
00594 addMacro(spec->macros, "PACKAGE_VERSION", NULL, field, RMIL_OLDSPEC);
00595 } else if (tag == RPMTAG_RELEASE) {
00596 if (strchr(field, '-') != NULL) {
00597 rpmlog(RPMLOG_ERR, _("line %d: Illegal char '-' in %s: %s\n"),
00598 spec->lineNum, "release", spec->line);
00599 return RPMRC_FAIL;
00600 }
00601 addMacro(spec->macros, "PACKAGE_RELEASE", NULL, field, RMIL_OLDSPEC-1);
00602 }
00603 he->tag = tag;
00604 he->t = RPM_STRING_TYPE;
00605 he->p.str = field;
00606 he->c = 1;
00607 xx = headerPut(pkg->header, he, 0);
00608 break;
00609 case RPMTAG_GROUP:
00610 case RPMTAG_SUMMARY:
00611 #if defined(RPM_VENDOR_OPENPKG)
00612 case RPMTAG_CLASS:
00613 #endif
00614 (void) stashSt(spec, pkg->header, tag, lang);
00615
00616 case RPMTAG_DISTRIBUTION:
00617 case RPMTAG_VENDOR:
00618 case RPMTAG_LICENSE:
00619 case RPMTAG_PACKAGER:
00620 if (!*lang) {
00621 he->tag = tag;
00622 he->t = RPM_STRING_TYPE;
00623 he->p.str = field;
00624 he->c = 1;
00625 xx = headerPut(pkg->header, he, 0);
00626 } else if (!(noLang && strcmp(lang, RPMBUILD_DEFAULT_LANG))) {
00627 (void) headerAddI18NString(pkg->header, tag, field, lang);
00628 }
00629 break;
00630
00631 case RPMTAG_BUILDROOT:
00632 SINGLE_TOKEN_ONLY;
00633 macro = NULL;
00634 #ifdef DYING
00635 buildRootURL = rpmGenPath(spec->rootURL, "%{?buildroot}", NULL);
00636 (void) urlPath(buildRootURL, &buildRoot);
00637 if (*buildRoot == '\0') buildRoot = "/";
00638 if (!strcmp(buildRoot, "/")) {
00639 rpmlog(RPMLOG_ERR,
00640 _("BuildRoot can not be \"/\": %s\n"), spec->buildRootURL);
00641 buildRootURL = _free(buildRootURL);
00642 return RPMRC_FAIL;
00643 }
00644 buildRootURL = _free(buildRootURL);
00645 #endif
00646 break;
00647 case RPMTAG_KEYWORDS:
00648 case RPMTAG_VARIANTS:
00649 case RPMTAG_PREFIXES:
00650 addOrAppendListEntry(pkg->header, tag, field);
00651 he->tag = tag;
00652 xx = headerGet(pkg->header, he, 0);
00653 if (tag == RPMTAG_PREFIXES)
00654 while (he->c--) {
00655 if (he->p.argv[he->c][0] != '/') {
00656 rpmlog(RPMLOG_ERR,
00657 _("line %d: Prefixes must begin with \"/\": %s\n"),
00658 spec->lineNum, spec->line);
00659 he->p.ptr = _free(he->p.ptr);
00660 return RPMRC_FAIL;
00661 }
00662 len = strlen(he->p.argv[he->c]);
00663 if (he->p.argv[he->c][len - 1] == '/' && len > 1) {
00664 rpmlog(RPMLOG_ERR,
00665 _("line %d: Prefixes must not end with \"/\": %s\n"),
00666 spec->lineNum, spec->line);
00667 he->p.ptr = _free(he->p.ptr);
00668 return RPMRC_FAIL;
00669 }
00670 }
00671 he->p.ptr = _free(he->p.ptr);
00672 break;
00673 case RPMTAG_DOCDIR:
00674 SINGLE_TOKEN_ONLY;
00675 if (field[0] != '/') {
00676 rpmlog(RPMLOG_ERR,
00677 _("line %d: Docdir must begin with '/': %s\n"),
00678 spec->lineNum, spec->line);
00679 return RPMRC_FAIL;
00680 }
00681 macro = NULL;
00682 delMacro(NULL, "_docdir");
00683 addMacro(NULL, "_docdir", NULL, field, RMIL_SPEC);
00684 break;
00685 case RPMTAG_XMAJOR:
00686 case RPMTAG_XMINOR:
00687 case RPMTAG_EPOCH:
00688 SINGLE_TOKEN_ONLY;
00689 if (parseNum(field, &num)) {
00690 rpmlog(RPMLOG_ERR,
00691 _("line %d: %s takes an integer value: %s\n"),
00692 spec->lineNum, tagName(tag), spec->line);
00693 return RPMRC_FAIL;
00694 }
00695 he->tag = tag;
00696 he->t = RPM_UINT32_TYPE;
00697 he->p.ui32p = #
00698 he->c = 1;
00699 xx = headerPut(pkg->header, he, 0);
00700 break;
00701 case RPMTAG_AUTOREQPROV:
00702 pkg->autoReq = parseYesNo(field);
00703 pkg->autoProv = pkg->autoReq;
00704 break;
00705 case RPMTAG_AUTOREQ:
00706 pkg->autoReq = parseYesNo(field);
00707 break;
00708 case RPMTAG_AUTOPROV:
00709 pkg->autoProv = parseYesNo(field);
00710 break;
00711 case RPMTAG_SOURCE:
00712 case RPMTAG_PATCH:
00713 SINGLE_TOKEN_ONLY;
00714 macro = NULL;
00715 if ((rc = addSource(spec, pkg, field, tag)))
00716 return rc;
00717 break;
00718 case RPMTAG_ICON:
00719 SINGLE_TOKEN_ONLY;
00720 macro = NULL;
00721 if ((rc = addSource(spec, pkg, field, tag)))
00722 return rc;
00723
00724 if ((rc = doIcon(spec, pkg->header)))
00725 return rc;
00726 break;
00727 case RPMTAG_NOSOURCE:
00728 case RPMTAG_NOPATCH:
00729 spec->noSource = 1;
00730 if ((rc = parseNoSource(spec, field, tag)))
00731 return rc;
00732 break;
00733 case RPMTAG_BUILDPREREQ:
00734 case RPMTAG_BUILDREQUIRES:
00735 if ((rc = parseBits(lang, buildScriptBits, &tagflags))) {
00736 rpmlog(RPMLOG_ERR,
00737 _("line %d: Bad %s: qualifiers: %s\n"),
00738 spec->lineNum, tagName(tag), spec->line);
00739 return rc;
00740 }
00741 if ((rc = parseRCPOT(spec, pkg, field, tag, 0, tagflags)))
00742 return rc;
00743 break;
00744 case RPMTAG_PREREQ:
00745 case RPMTAG_REQUIREFLAGS:
00746 if ((rc = parseBits(lang, installScriptBits, &tagflags))) {
00747 rpmlog(RPMLOG_ERR,
00748 _("line %d: Bad %s: qualifiers: %s\n"),
00749 spec->lineNum, tagName(tag), spec->line);
00750 return rc;
00751 }
00752 if ((rc = parseRCPOT(spec, pkg, field, tag, 0, tagflags)))
00753 return rc;
00754 break;
00755
00756 case RPMTAG_BUILDSUGGESTS:
00757 case RPMTAG_BUILDENHANCES:
00758 tagflags = RPMSENSE_MISSINGOK;
00759 if ((rc = parseRCPOT(spec, pkg, field, tag, 0, tagflags)))
00760 return rc;
00761 break;
00762
00763 case RPMTAG_SUGGESTSFLAGS:
00764 case RPMTAG_ENHANCESFLAGS:
00765 tag = RPMTAG_REQUIREFLAGS;
00766 tagflags = RPMSENSE_MISSINGOK;
00767 if ((rc = parseRCPOT(spec, pkg, field, tag, 0, tagflags)))
00768 return rc;
00769 break;
00770 case RPMTAG_BUILDOBSOLETES:
00771 case RPMTAG_BUILDPROVIDES:
00772 case RPMTAG_BUILDCONFLICTS:
00773 case RPMTAG_CONFLICTFLAGS:
00774 case RPMTAG_OBSOLETEFLAGS:
00775 case RPMTAG_PROVIDEFLAGS:
00776 tagflags = RPMSENSE_ANY;
00777 if ((rc = parseRCPOT(spec, pkg, field, tag, 0, tagflags)))
00778 return rc;
00779 break;
00780 case RPMTAG_BUILDPLATFORMS:
00781 case RPMTAG_EXCLUDEARCH:
00782 case RPMTAG_EXCLUSIVEARCH:
00783 case RPMTAG_EXCLUDEOS:
00784 case RPMTAG_EXCLUSIVEOS:
00785 addOrAppendListEntry(spec->sourceHeader, tag, field);
00786 break;
00787 case RPMTAG_BUILDARCHS:
00788 if ((rc = poptParseArgvString(field,
00789 &(spec->BACount),
00790 &(spec->BANames)))) {
00791 rpmlog(RPMLOG_ERR,
00792 _("line %d: Bad BuildArchitecture format: %s\n"),
00793 spec->lineNum, spec->line);
00794 return RPMRC_FAIL;
00795 }
00796 if (!spec->BACount)
00797 spec->BANames = _free(spec->BANames);
00798 break;
00799
00800 default:
00801 macro = NULL;
00802 he->tag = tag;
00803 he->t = RPM_STRING_ARRAY_TYPE;
00804 he->p.argv= (const char **) &field;
00805 he->c = 1;
00806 he->append = 1;
00807 xx = headerPut(pkg->header, he, 0);
00808 he->append = 0;
00809 break;
00810 }
00811
00812 if (macro)
00813 addMacro(spec->macros, macro, NULL, field, RMIL_SPEC);
00814
00815 return RPMRC_OK;
00816 }
00817
00818
00819
00820
00823 typedef struct PreambleRec_s {
00824 rpmTag tag;
00825 int multiLang;
00826 int obsolete;
00827
00828 const char * token;
00829 } * PreambleRec;
00830
00831
00832 static struct PreambleRec_s preambleList[] = {
00833 {RPMTAG_NAME, 0, 0, "name"},
00834 {RPMTAG_VERSION, 0, 0, "version"},
00835 {RPMTAG_RELEASE, 0, 0, "release"},
00836 {RPMTAG_EPOCH, 0, 0, "epoch"},
00837 {RPMTAG_EPOCH, 0, 1, "serial"},
00838 {RPMTAG_SUMMARY, 1, 0, "summary"},
00839 {RPMTAG_LICENSE, 0, 0, "copyright"},
00840 {RPMTAG_LICENSE, 0, 0, "license"},
00841 {RPMTAG_DISTRIBUTION, 0, 0, "distribution"},
00842 {RPMTAG_DISTURL, 0, 0, "disturl"},
00843 {RPMTAG_VENDOR, 0, 0, "vendor"},
00844 {RPMTAG_GROUP, 1, 0, "group"},
00845 {RPMTAG_PACKAGER, 0, 0, "packager"},
00846 {RPMTAG_URL, 0, 0, "url"},
00847 {RPMTAG_SOURCE, 0, 0, "source"},
00848 {RPMTAG_PATCH, 0, 0, "patch"},
00849 {RPMTAG_NOSOURCE, 0, 0, "nosource"},
00850 {RPMTAG_NOPATCH, 0, 0, "nopatch"},
00851 {RPMTAG_EXCLUDEARCH, 0, 0, "excludearch"},
00852 {RPMTAG_EXCLUSIVEARCH, 0, 0, "exclusivearch"},
00853 {RPMTAG_EXCLUDEOS, 0, 0, "excludeos"},
00854 {RPMTAG_EXCLUSIVEOS, 0, 0, "exclusiveos"},
00855 {RPMTAG_ICON, 0, 0, "icon"},
00856 {RPMTAG_PROVIDEFLAGS, 0, 0, "provides"},
00857 {RPMTAG_REQUIREFLAGS, 1, 0, "requires"},
00858 {RPMTAG_PREREQ, 1, 0, "prereq"},
00859 {RPMTAG_CONFLICTFLAGS, 0, 0, "conflicts"},
00860 {RPMTAG_OBSOLETEFLAGS, 0, 0, "obsoletes"},
00861 {RPMTAG_PREFIXES, 0, 0, "prefixes"},
00862 {RPMTAG_PREFIXES, 0, 0, "prefix"},
00863 {RPMTAG_BUILDROOT, 0, 0, "buildroot"},
00864 {RPMTAG_BUILDARCHS, 0, 0, "buildarchitectures"},
00865 {RPMTAG_BUILDARCHS, 0, 0, "buildarch"},
00866 {RPMTAG_BUILDCONFLICTS, 0, 0, "buildconflicts"},
00867 {RPMTAG_BUILDOBSOLETES, 0, 0, "buildobsoletes"},
00868 {RPMTAG_BUILDPREREQ, 1, 0, "buildprereq"},
00869 {RPMTAG_BUILDPROVIDES, 0, 0, "buildprovides"},
00870 {RPMTAG_BUILDREQUIRES, 1, 0, "buildrequires"},
00871 {RPMTAG_AUTOREQPROV, 0, 0, "autoreqprov"},
00872 {RPMTAG_AUTOREQ, 0, 0, "autoreq"},
00873 {RPMTAG_AUTOPROV, 0, 0, "autoprov"},
00874 {RPMTAG_DOCDIR, 0, 0, "docdir"},
00875 {RPMTAG_DISTTAG, 0, 0, "disttag"},
00876 {RPMTAG_CVSID, 0, 0, "cvsid"},
00877 {RPMTAG_SVNID, 0, 0, "svnid"},
00878 {RPMTAG_SUGGESTSFLAGS, 0, 0, "suggests"},
00879 {RPMTAG_ENHANCESFLAGS, 0, 0, "enhances"},
00880 {RPMTAG_BUILDSUGGESTS, 0, 0, "buildsuggests"},
00881 {RPMTAG_BUILDENHANCES, 0, 0, "buildenhances"},
00882 {RPMTAG_VARIANTS, 0, 0, "variants"},
00883 {RPMTAG_VARIANTS, 0, 0, "variant"},
00884 {RPMTAG_XMAJOR, 0, 0, "xmajor"},
00885 {RPMTAG_XMINOR, 0, 0, "xminor"},
00886 {RPMTAG_REPOTAG, 0, 0, "repotag"},
00887 {RPMTAG_KEYWORDS, 0, 0, "keywords"},
00888 {RPMTAG_KEYWORDS, 0, 0, "keyword"},
00889 {RPMTAG_BUILDPLATFORMS, 0, 0, "buildplatforms"},
00890 #if defined(RPM_VENDOR_OPENPKG)
00891 {RPMTAG_CLASS, 0, 0, "class"},
00892 #endif
00893
00894 {0, 0, 0, 0}
00895
00896 };
00897
00900 static int findPreambleTag(Spec spec, rpmTag * tagp,
00901 const char ** macro, char * lang)
00902
00903 {
00904 PreambleRec p;
00905 char *s;
00906 size_t len = 0;
00907
00908
00909 for (p = preambleList; p->token != NULL; p++) {
00910 len = strlen(p->token);
00911 if (!(p->token && !xstrncasecmp(spec->line, p->token, len)))
00912 continue;
00913 if (p->obsolete) {
00914 rpmlog(RPMLOG_ERR, _("Legacy syntax is unsupported: %s\n"),
00915 p->token);
00916 p = NULL;
00917 }
00918 break;
00919 }
00920 if (p == NULL)
00921 return 1;
00922
00923
00924 if (tagp && p->token == NULL) {
00925 ARGV_t aTags = NULL;
00926 int rc = 1;
00927
00928
00929 (void) tagName(0);
00930
00931 aTags = rpmTags->aTags;
00932 if (aTags != NULL && aTags[0] != NULL) {
00933 ARGV_t av;
00934 s = tagCanonicalize(spec->line);
00935 #if defined(RPM_VENDOR_OPENPKG)
00936 av = argvSearchLinear(aTags, s, argvFnmatchCasefold);
00937 #else
00938 av = argvSearch(aTags, s, argvStrcasecmp);
00939 #endif
00940 if (av != NULL) {
00941 *tagp = tagGenerate(s);
00942 rc = 0;
00943 }
00944 s = _free(s);
00945 }
00946 return rc;
00947 }
00948
00949 s = spec->line + len;
00950 SKIPSPACE(s);
00951
00952 switch (p->multiLang) {
00953 default:
00954 case 0:
00955
00956 if (p->tag != RPMTAG_SOURCE && p->tag != RPMTAG_PATCH) {
00957 if (*s != ':') return 1;
00958 }
00959 *lang = '\0';
00960 break;
00961 case 1:
00962 if (*s == ':') {
00963 strcpy(lang, RPMBUILD_DEFAULT_LANG);
00964 break;
00965 }
00966 if (*s != '(') return 1;
00967 s++;
00968 SKIPSPACE(s);
00969 while (!xisspace(*s) && *s != ')')
00970 *lang++ = *s++;
00971 *lang = '\0';
00972 SKIPSPACE(s);
00973 if (*s != ')') return 1;
00974 s++;
00975 SKIPSPACE(s);
00976 if (*s != ':') return 1;
00977 break;
00978 }
00979
00980 if (tagp)
00981 *tagp = p->tag;
00982 if (macro)
00983
00984 *macro = p->token;
00985
00986 return 0;
00987 }
00988
00989
00990 int parsePreamble(Spec spec, int initialPackage)
00991 {
00992 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
00993 rpmParseState nextPart;
00994 int xx;
00995 char *name, *linep;
00996 Package pkg;
00997 char NVR[BUFSIZ];
00998 char lang[BUFSIZ];
00999 rpmRC rc;
01000
01001 strcpy(NVR, "(main package)");
01002
01003 pkg = newPackage(spec);
01004
01005 if (! initialPackage) {
01006 rpmParseState flag;
01007
01008 flag = PART_NONE;
01009 if (parseSimplePart(spec->line, &name, &flag)) {
01010 rpmlog(RPMLOG_ERR, _("Bad package specification: %s\n"),
01011 spec->line);
01012 return RPMRC_FAIL;
01013 }
01014
01015 if (lookupPackage(spec, name, flag, NULL) == RPMRC_OK) {
01016 rpmlog(RPMLOG_ERR, _("Package already exists: %s\n"),
01017 spec->line);
01018 return RPMRC_FAIL;
01019 }
01020
01021
01022 if (flag == PART_SUBNAME) {
01023 he->tag = RPMTAG_NAME;
01024 xx = headerGet(spec->packages->header, he, 0);
01025 sprintf(NVR, "%s-%s", he->p.str, name);
01026 he->p.ptr = _free(he->p.ptr);
01027 } else
01028 strcpy(NVR, name);
01029 he->tag = RPMTAG_NAME;
01030 he->t = RPM_STRING_TYPE;
01031 he->p.str = NVR;
01032 he->c = 1;
01033 xx = headerPut(pkg->header, he, 0);
01034 }
01035
01036 if ((rc = readLine(spec, STRIP_TRAILINGSPACE | STRIP_COMMENTS)) > 0) {
01037 nextPart = PART_NONE;
01038 } else {
01039 if (rc)
01040 return rc;
01041 while ((nextPart = isPart(spec)) == PART_NONE) {
01042 const char * macro = NULL;
01043 rpmTag tag;
01044
01045
01046 linep = spec->line;
01047 SKIPSPACE(linep);
01048 if (*linep != '\0') {
01049 if (findPreambleTag(spec, &tag, ¯o, lang)) {
01050 rpmlog(RPMLOG_ERR, _("line %d: Unknown tag: %s\n"),
01051 spec->lineNum, spec->line);
01052 return RPMRC_FAIL;
01053 }
01054 if (handlePreambleTag(spec, pkg, tag, macro, lang))
01055 return RPMRC_FAIL;
01056 if (spec->BANames && !spec->recursing)
01057 return PART_BUILDARCHITECTURES;
01058 }
01059 if ((rc =
01060 readLine(spec, STRIP_TRAILINGSPACE | STRIP_COMMENTS)) > 0) {
01061 nextPart = PART_NONE;
01062 break;
01063 }
01064 if (rc)
01065 return rc;
01066 }
01067 }
01068
01069
01070
01071
01072 if (!spec->anyarch && checkForValidArchitectures(spec))
01073 return RPMRC_FAIL;
01074
01075 if (pkg == spec->packages)
01076 fillOutMainPackage(pkg->header);
01077
01078 if (checkForDuplicates(pkg->header, NVR) != RPMRC_OK)
01079 return RPMRC_FAIL;
01080
01081 if (pkg != spec->packages)
01082 headerCopyTags(spec->packages->header, pkg->header,
01083 (uint32_t *)copyTagsDuringParse);
01084
01085 if (checkForRequired(pkg->header, NVR) != RPMRC_OK)
01086 return RPMRC_FAIL;
01087
01088 return nextPart;
01089 }