00001
00006 #include "system.h"
00007
00008 #include <rpmio_internal.h>
00009 #include <rpmbuild.h>
00010 #include "debug.h"
00011
00012
00013
00016
00017 static rpmTag copyTagsDuringParse[] = {
00018 RPMTAG_EPOCH,
00019 RPMTAG_VERSION,
00020 RPMTAG_RELEASE,
00021 RPMTAG_LICENSE,
00022 RPMTAG_PACKAGER,
00023 RPMTAG_DISTRIBUTION,
00024 RPMTAG_DISTURL,
00025 RPMTAG_VENDOR,
00026 RPMTAG_ICON,
00027 RPMTAG_URL,
00028 RPMTAG_CHANGELOGTIME,
00029 RPMTAG_CHANGELOGNAME,
00030 RPMTAG_CHANGELOGTEXT,
00031 RPMTAG_PREFIXES,
00032 RPMTAG_RHNPLATFORM,
00033 0
00034 };
00035
00038
00039 static rpmTag requiredTags[] = {
00040 RPMTAG_NAME,
00041 RPMTAG_VERSION,
00042 RPMTAG_RELEASE,
00043 RPMTAG_SUMMARY,
00044 RPMTAG_GROUP,
00045 RPMTAG_LICENSE,
00046 0
00047 };
00048
00051 static void addOrAppendListEntry(Header h, int_32 tag, char * line)
00052
00053 {
00054 int xx;
00055 int argc;
00056 const char **argv;
00057
00058 xx = poptParseArgvString(line, &argc, &argv);
00059 if (argc)
00060 xx = headerAddOrAppendEntry(h, tag, RPM_STRING_ARRAY_TYPE, argv, argc);
00061 argv = _free(argv);
00062 }
00063
00064
00065
00066
00069
00070 static int parseSimplePart(char *line, char **name, int *flag)
00071
00072
00073 {
00074 char *tok;
00075 char linebuf[BUFSIZ];
00076 static char buf[BUFSIZ];
00077
00078 strcpy(linebuf, line);
00079
00080
00081 (void)strtok(linebuf, " \t\n");
00082
00083 if (!(tok = strtok(NULL, " \t\n"))) {
00084 *name = NULL;
00085 return 0;
00086 }
00087
00088 if (!strcmp(tok, "-n")) {
00089 if (!(tok = strtok(NULL, " \t\n")))
00090 return 1;
00091 *flag = PART_NAME;
00092 } else {
00093 *flag = PART_SUBNAME;
00094 }
00095 strcpy(buf, tok);
00096 *name = buf;
00097
00098 return (strtok(NULL, " \t\n")) ? 1 : 0;
00099 }
00100
00101
00104 static inline int parseYesNo(const char * s)
00105
00106 {
00107 return ((!s || (s[0] == 'n' || s[0] == 'N' || s[0] == '0') ||
00108 !xstrcasecmp(s, "false") || !xstrcasecmp(s, "off"))
00109 ? 0 : 1);
00110 }
00111
00112 typedef struct tokenBits_s {
00113
00114 const char * name;
00115 rpmsenseFlags bits;
00116 } * tokenBits;
00117
00120
00121 static struct tokenBits_s installScriptBits[] = {
00122 { "interp", RPMSENSE_INTERP },
00123 { "prereq", RPMSENSE_PREREQ },
00124 { "preun", RPMSENSE_SCRIPT_PREUN },
00125 { "pre", RPMSENSE_SCRIPT_PRE },
00126 { "postun", RPMSENSE_SCRIPT_POSTUN },
00127 { "post", RPMSENSE_SCRIPT_POST },
00128 { "rpmlib", RPMSENSE_RPMLIB },
00129 { "verify", RPMSENSE_SCRIPT_VERIFY },
00130 { NULL, 0 }
00131 };
00132
00135
00136 static struct tokenBits_s buildScriptBits[] = {
00137 { "prep", RPMSENSE_SCRIPT_PREP },
00138 { "build", RPMSENSE_SCRIPT_BUILD },
00139 { "install", RPMSENSE_SCRIPT_INSTALL },
00140 { "clean", RPMSENSE_SCRIPT_CLEAN },
00141 { NULL, 0 }
00142 };
00143
00146
00147 static int parseBits(const char * s, const tokenBits tokbits,
00148 rpmsenseFlags * bp)
00149
00150 {
00151 tokenBits tb;
00152 const char * se;
00153 rpmsenseFlags bits = RPMSENSE_ANY;
00154 int c = 0;
00155
00156 if (s) {
00157 while (*s != '\0') {
00158 while ((c = *s) && xisspace(c)) s++;
00159 se = s;
00160 while ((c = *se) && xisalpha(c)) se++;
00161 if (s == se)
00162 break;
00163 for (tb = tokbits; tb->name; tb++) {
00164 if (tb->name != NULL &&
00165 strlen(tb->name) == (se-s) && !strncmp(tb->name, s, (se-s)))
00166 break;
00167 }
00168 if (tb->name == NULL)
00169 break;
00170 bits |= tb->bits;
00171 while ((c = *se) && xisspace(c)) se++;
00172 if (c != ',')
00173 break;
00174 s = ++se;
00175 }
00176 }
00177 if (c == 0 && bp) *bp = bits;
00178 return (c ? RPMERR_BADSPEC : 0);
00179 }
00180
00181
00184 static inline char * findLastChar(char * s)
00185
00186 {
00187 char *res = s;
00188
00189
00190 while (*s != '\0') {
00191 if (! xisspace(*s))
00192 res = s;
00193 s++;
00194 }
00195
00196
00197
00198 return res;
00199
00200 }
00201
00204 static int isMemberInEntry(Header h, const char *name, rpmTag tag)
00205
00206 {
00207 HGE_t hge = (HGE_t)headerGetEntryMinMemory;
00208 HFD_t hfd = headerFreeData;
00209 const char ** names;
00210 rpmTagType type;
00211 int count;
00212
00213 if (!hge(h, tag, &type, (void **)&names, &count))
00214 return -1;
00215
00216 while (count--) {
00217 if (!xstrcasecmp(names[count], name))
00218 break;
00219 }
00220 names = hfd(names, type);
00221
00222 return (count >= 0 ? 1 : 0);
00223 }
00224
00227 static int checkForValidArchitectures(Spec spec)
00228
00229 {
00230 #ifndef DYING
00231 const char *arch = NULL;
00232 const char *os = NULL;
00233
00234 rpmGetArchInfo(&arch, NULL);
00235 rpmGetOsInfo(&os, NULL);
00236 #else
00237 const char *arch = rpmExpand("%{_target_cpu}", NULL);
00238 const char *os = rpmExpand("%{_target_os}", NULL);
00239 #endif
00240
00241 if (isMemberInEntry(spec->buildRestrictions,
00242 arch, RPMTAG_EXCLUDEARCH) == 1) {
00243 rpmError(RPMERR_BADSPEC, _("Architecture is excluded: %s\n"), arch);
00244 return RPMERR_BADSPEC;
00245 }
00246 if (isMemberInEntry(spec->buildRestrictions,
00247 arch, RPMTAG_EXCLUSIVEARCH) == 0) {
00248 rpmError(RPMERR_BADSPEC, _("Architecture is not included: %s\n"), arch);
00249 return RPMERR_BADSPEC;
00250 }
00251 if (isMemberInEntry(spec->buildRestrictions,
00252 os, RPMTAG_EXCLUDEOS) == 1) {
00253 rpmError(RPMERR_BADSPEC, _("OS is excluded: %s\n"), os);
00254 return RPMERR_BADSPEC;
00255 }
00256 if (isMemberInEntry(spec->buildRestrictions,
00257 os, RPMTAG_EXCLUSIVEOS) == 0) {
00258 rpmError(RPMERR_BADSPEC, _("OS is not included: %s\n"), os);
00259 return RPMERR_BADSPEC;
00260 }
00261
00262 return 0;
00263 }
00264
00271 static int checkForRequired(Header h, const char * NVR)
00272
00273 {
00274 int res = 0;
00275 rpmTag * p;
00276
00277
00278 for (p = requiredTags; *p != 0; p++) {
00279 if (!headerIsEntry(h, *p)) {
00280 rpmError(RPMERR_BADSPEC,
00281 _("%s field must be present in package: %s\n"),
00282 tagName(*p), NVR);
00283 res = 1;
00284 }
00285 }
00286
00287
00288 return res;
00289 }
00290
00297 static int checkForDuplicates(Header h, const char * NVR)
00298
00299 {
00300 int res = 0;
00301 int lastTag, tag;
00302 HeaderIterator hi;
00303
00304 for (hi = headerInitIterator(h), lastTag = 0;
00305 headerNextIterator(hi, &tag, NULL, NULL, NULL);
00306 lastTag = tag)
00307 {
00308 if (tag != lastTag)
00309 continue;
00310 rpmError(RPMERR_BADSPEC, _("Duplicate %s entries in package: %s\n"),
00311 tagName(tag), NVR);
00312 res = 1;
00313 }
00314 hi = headerFreeIterator(hi);
00315
00316 return res;
00317 }
00318
00321
00322 static struct optionalTag {
00323 rpmTag ot_tag;
00324
00325 const char * ot_mac;
00326 } optionalTags[] = {
00327 { RPMTAG_VENDOR, "%{vendor}" },
00328 { RPMTAG_PACKAGER, "%{packager}" },
00329 { RPMTAG_DISTRIBUTION, "%{distribution}" },
00330 { RPMTAG_DISTURL, "%{disturl}" },
00331 { -1, NULL }
00332 };
00333
00336 static void fillOutMainPackage(Header h)
00337
00338
00339 {
00340 struct optionalTag *ot;
00341
00342 for (ot = optionalTags; ot->ot_mac != NULL; ot++) {
00343 if (!headerIsEntry(h, ot->ot_tag)) {
00344
00345 const char *val = rpmExpand(ot->ot_mac, NULL);
00346 if (val && *val != '%')
00347 (void) headerAddEntry(h, ot->ot_tag, RPM_STRING_TYPE, (void *)val, 1);
00348 val = _free(val);
00349
00350 }
00351 }
00352 }
00353
00356
00357 static int readIcon(Header h, const char * file)
00358
00359
00360 {
00361 const char *fn = NULL;
00362 char *icon;
00363 FD_t fd;
00364 int rc = 0;
00365 off_t size;
00366 size_t nb, iconsize;
00367
00368
00369 fn = rpmGetPath("%{_sourcedir}/", file, NULL);
00370
00371 fd = Fopen(fn, "r.ufdio");
00372 if (fd == NULL || Ferror(fd)) {
00373 rpmError(RPMERR_BADSPEC, _("Unable to open icon %s: %s\n"),
00374 fn, Fstrerror(fd));
00375 rc = RPMERR_BADSPEC;
00376 goto exit;
00377 }
00378 size = fdSize(fd);
00379 iconsize = (size >= 0 ? size : (8 * BUFSIZ));
00380 if (iconsize == 0) {
00381 (void) Fclose(fd);
00382 rc = 0;
00383 goto exit;
00384 }
00385
00386 icon = xmalloc(iconsize + 1);
00387 *icon = '\0';
00388
00389 nb = Fread(icon, sizeof(icon[0]), iconsize, fd);
00390 if (Ferror(fd) || (size >= 0 && nb != size)) {
00391 rpmError(RPMERR_BADSPEC, _("Unable to read icon %s: %s\n"),
00392 fn, Fstrerror(fd));
00393 rc = RPMERR_BADSPEC;
00394 }
00395 (void) Fclose(fd);
00396 if (rc)
00397 goto exit;
00398
00399 if (! strncmp(icon, "GIF", sizeof("GIF")-1)) {
00400 (void) headerAddEntry(h, RPMTAG_GIF, RPM_BIN_TYPE, icon, iconsize);
00401 } else if (! strncmp(icon, "/* XPM", sizeof("/* XPM")-1)) {
00402 (void) headerAddEntry(h, RPMTAG_XPM, RPM_BIN_TYPE, icon, iconsize);
00403 } else {
00404 rpmError(RPMERR_BADSPEC, _("Unknown icon type: %s\n"), file);
00405 rc = RPMERR_BADSPEC;
00406 goto exit;
00407 }
00408 icon = _free(icon);
00409
00410 exit:
00411 fn = _free(fn);
00412 return rc;
00413 }
00414
00415
00416 spectag stashSt(Spec spec, Header h, int tag, const char * lang)
00417 {
00418 HGE_t hge = (HGE_t)headerGetEntryMinMemory;
00419 spectag t = NULL;
00420
00421 if (spec->st) {
00422 spectags st = spec->st;
00423 if (st->st_ntags == st->st_nalloc) {
00424 st->st_nalloc += 10;
00425 st->st_t = xrealloc(st->st_t, st->st_nalloc * sizeof(*(st->st_t)));
00426 }
00427 t = st->st_t + st->st_ntags++;
00428 t->t_tag = tag;
00429 t->t_startx = spec->lineNum - 1;
00430 t->t_nlines = 1;
00431 t->t_lang = xstrdup(lang);
00432 t->t_msgid = NULL;
00433 if (!(t->t_lang && strcmp(t->t_lang, RPMBUILD_DEFAULT_LANG))) {
00434 char *n;
00435 if (hge(h, RPMTAG_NAME, NULL, (void **) &n, NULL)) {
00436 char buf[1024];
00437 sprintf(buf, "%s(%s)", n, tagName(tag));
00438 t->t_msgid = xstrdup(buf);
00439 }
00440 }
00441 }
00442
00443 return t;
00444
00445 }
00446
00447 #define SINGLE_TOKEN_ONLY \
00448 if (multiToken) { \
00449 rpmError(RPMERR_BADSPEC, _("line %d: Tag takes single token only: %s\n"), \
00450 spec->lineNum, spec->line); \
00451 return RPMERR_BADSPEC; \
00452 }
00453
00454
00455 extern int noLang;
00456
00457
00460
00461 static int handlePreambleTag(Spec spec, Package pkg, int tag, const char *macro,
00462 const char *lang)
00463
00464
00465
00466
00467
00468
00469
00470 {
00471 HGE_t hge = (HGE_t)headerGetEntryMinMemory;
00472 HFD_t hfd = headerFreeData;
00473 char * field = spec->line;
00474 char * end;
00475 char ** array;
00476 int multiToken = 0;
00477 rpmsenseFlags tagflags;
00478 rpmTagType type;
00479 int len;
00480 int num;
00481 int rc;
00482 int xx;
00483
00484 if (field == NULL) return RPMERR_BADSPEC;
00485
00486 while ((*field) && (*field != ':'))
00487 field++;
00488 if (*field != ':') {
00489 rpmError(RPMERR_BADSPEC, _("line %d: Malformed tag: %s\n"),
00490 spec->lineNum, spec->line);
00491 return RPMERR_BADSPEC;
00492 }
00493 field++;
00494 SKIPSPACE(field);
00495 if (!*field) {
00496
00497 rpmError(RPMERR_BADSPEC, _("line %d: Empty tag: %s\n"),
00498 spec->lineNum, spec->line);
00499 return RPMERR_BADSPEC;
00500 }
00501 end = findLastChar(field);
00502 *(end+1) = '\0';
00503
00504
00505 end = field;
00506 SKIPNONSPACE(end);
00507 if (*end != '\0')
00508 multiToken = 1;
00509
00510 switch (tag) {
00511 case RPMTAG_NAME:
00512 case RPMTAG_VERSION:
00513 case RPMTAG_RELEASE:
00514 case RPMTAG_URL:
00515 case RPMTAG_RHNPLATFORM:
00516 SINGLE_TOKEN_ONLY;
00517
00518 if (tag == RPMTAG_VERSION) {
00519 if (strchr(field, '-') != NULL) {
00520 rpmError(RPMERR_BADSPEC, _("line %d: Illegal char '-' in %s: %s\n"),
00521 spec->lineNum, "version", spec->line);
00522 return RPMERR_BADSPEC;
00523 }
00524 addMacro(spec->macros, "PACKAGE_VERSION", NULL, field, RMIL_OLDSPEC);
00525 } else if (tag == RPMTAG_RELEASE) {
00526 if (strchr(field, '-') != NULL) {
00527 rpmError(RPMERR_BADSPEC, _("line %d: Illegal char '-' in %s: %s\n"),
00528 spec->lineNum, "release", spec->line);
00529 return RPMERR_BADSPEC;
00530 }
00531 addMacro(spec->macros, "PACKAGE_RELEASE", NULL, field, RMIL_OLDSPEC-1);
00532 }
00533 (void) headerAddEntry(pkg->header, tag, RPM_STRING_TYPE, field, 1);
00534 break;
00535 case RPMTAG_GROUP:
00536 case RPMTAG_SUMMARY:
00537 (void) stashSt(spec, pkg->header, tag, lang);
00538
00539 case RPMTAG_DISTRIBUTION:
00540 case RPMTAG_VENDOR:
00541 case RPMTAG_LICENSE:
00542 case RPMTAG_PACKAGER:
00543 if (!*lang)
00544 (void) headerAddEntry(pkg->header, tag, RPM_STRING_TYPE, field, 1);
00545 else if (!(noLang && strcmp(lang, RPMBUILD_DEFAULT_LANG)))
00546 (void) headerAddI18NString(pkg->header, tag, field, lang);
00547 break;
00548 case RPMTAG_BUILDROOT:
00549 SINGLE_TOKEN_ONLY;
00550 { const char * buildRoot = NULL;
00551 const char * buildRootURL = spec->buildRootURL;
00552
00553
00554
00555
00556
00557
00558
00559
00560 if (buildRootURL == NULL) {
00561 buildRootURL = rpmGenPath(NULL, "%{?buildroot:%{buildroot}}", NULL);
00562 if (strcmp(buildRootURL, "/")) {
00563 spec->buildRootURL = buildRootURL;
00564 macro = NULL;
00565 } else {
00566 const char * specURL = field;
00567
00568 buildRootURL = _free(buildRootURL);
00569 (void) urlPath(specURL, (const char **)&field);
00570
00571 if (*field == '\0') field = "/";
00572
00573 buildRootURL = rpmGenPath(spec->rootURL, field, NULL);
00574 spec->buildRootURL = buildRootURL;
00575 field = (char *) buildRootURL;
00576 }
00577 spec->gotBuildRootURL = 1;
00578 } else {
00579 macro = NULL;
00580 }
00581 buildRootURL = rpmGenPath(NULL, spec->buildRootURL, NULL);
00582 (void) urlPath(buildRootURL, &buildRoot);
00583
00584 if (*buildRoot == '\0') buildRoot = "/";
00585
00586 if (!strcmp(buildRoot, "/")) {
00587 rpmError(RPMERR_BADSPEC,
00588 _("BuildRoot can not be \"/\": %s\n"), spec->buildRootURL);
00589 buildRootURL = _free(buildRootURL);
00590 return RPMERR_BADSPEC;
00591 }
00592 buildRootURL = _free(buildRootURL);
00593 } break;
00594 case RPMTAG_PREFIXES:
00595 addOrAppendListEntry(pkg->header, tag, field);
00596 xx = hge(pkg->header, tag, &type, (void **)&array, &num);
00597 while (num--) {
00598 len = strlen(array[num]);
00599 if (array[num][len - 1] == '/' && len > 1) {
00600 rpmError(RPMERR_BADSPEC,
00601 _("line %d: Prefixes must not end with \"/\": %s\n"),
00602 spec->lineNum, spec->line);
00603 array = hfd(array, type);
00604 return RPMERR_BADSPEC;
00605 }
00606 }
00607 array = hfd(array, type);
00608 break;
00609 case RPMTAG_DOCDIR:
00610 SINGLE_TOKEN_ONLY;
00611 if (field[0] != '/') {
00612 rpmError(RPMERR_BADSPEC,
00613 _("line %d: Docdir must begin with '/': %s\n"),
00614 spec->lineNum, spec->line);
00615 return RPMERR_BADSPEC;
00616 }
00617 macro = NULL;
00618 delMacro(NULL, "_docdir");
00619 addMacro(NULL, "_docdir", NULL, field, RMIL_SPEC);
00620 break;
00621 case RPMTAG_EPOCH:
00622 SINGLE_TOKEN_ONLY;
00623 if (parseNum(field, &num)) {
00624 rpmError(RPMERR_BADSPEC,
00625 _("line %d: Epoch/Serial field must be a number: %s\n"),
00626 spec->lineNum, spec->line);
00627 return RPMERR_BADSPEC;
00628 }
00629 xx = headerAddEntry(pkg->header, tag, RPM_INT32_TYPE, &num, 1);
00630 break;
00631 case RPMTAG_AUTOREQPROV:
00632 pkg->autoReq = parseYesNo(field);
00633 pkg->autoProv = pkg->autoReq;
00634 break;
00635 case RPMTAG_AUTOREQ:
00636 pkg->autoReq = parseYesNo(field);
00637 break;
00638 case RPMTAG_AUTOPROV:
00639 pkg->autoProv = parseYesNo(field);
00640 break;
00641 case RPMTAG_SOURCE:
00642 case RPMTAG_PATCH:
00643 SINGLE_TOKEN_ONLY;
00644 macro = NULL;
00645 if ((rc = addSource(spec, pkg, field, tag)))
00646 return rc;
00647 break;
00648 case RPMTAG_ICON:
00649 SINGLE_TOKEN_ONLY;
00650 if ((rc = addSource(spec, pkg, field, tag)))
00651 return rc;
00652 if ((rc = readIcon(pkg->header, field)))
00653 return RPMERR_BADSPEC;
00654 break;
00655 case RPMTAG_NOSOURCE:
00656 case RPMTAG_NOPATCH:
00657 spec->noSource = 1;
00658 if ((rc = parseNoSource(spec, field, tag)))
00659 return rc;
00660 break;
00661 case RPMTAG_BUILDPREREQ:
00662 case RPMTAG_BUILDREQUIRES:
00663 if ((rc = parseBits(lang, buildScriptBits, &tagflags))) {
00664 rpmError(RPMERR_BADSPEC,
00665 _("line %d: Bad %s: qualifiers: %s\n"),
00666 spec->lineNum, tagName(tag), spec->line);
00667 return rc;
00668 }
00669 if ((rc = parseRCPOT(spec, pkg, field, tag, 0, tagflags)))
00670 return rc;
00671 break;
00672 case RPMTAG_REQUIREFLAGS:
00673 case RPMTAG_PREREQ:
00674 if ((rc = parseBits(lang, installScriptBits, &tagflags))) {
00675 rpmError(RPMERR_BADSPEC,
00676 _("line %d: Bad %s: qualifiers: %s\n"),
00677 spec->lineNum, tagName(tag), spec->line);
00678 return rc;
00679 }
00680 if ((rc = parseRCPOT(spec, pkg, field, tag, 0, tagflags)))
00681 return rc;
00682 break;
00683 case RPMTAG_BUILDCONFLICTS:
00684 case RPMTAG_CONFLICTFLAGS:
00685 case RPMTAG_OBSOLETEFLAGS:
00686 case RPMTAG_PROVIDEFLAGS:
00687 tagflags = RPMSENSE_ANY;
00688 if ((rc = parseRCPOT(spec, pkg, field, tag, 0, tagflags)))
00689 return rc;
00690 break;
00691 case RPMTAG_EXCLUDEARCH:
00692 case RPMTAG_EXCLUSIVEARCH:
00693 case RPMTAG_EXCLUDEOS:
00694 case RPMTAG_EXCLUSIVEOS:
00695 addOrAppendListEntry(spec->buildRestrictions, tag, field);
00696 break;
00697 case RPMTAG_BUILDARCHS:
00698 if ((rc = poptParseArgvString(field,
00699 &(spec->BACount),
00700 &(spec->BANames)))) {
00701 rpmError(RPMERR_BADSPEC,
00702 _("line %d: Bad BuildArchitecture format: %s\n"),
00703 spec->lineNum, spec->line);
00704 return RPMERR_BADSPEC;
00705 }
00706 if (!spec->BACount)
00707 spec->BANames = _free(spec->BANames);
00708 break;
00709
00710 default:
00711 rpmError(RPMERR_INTERNAL, _("Internal error: Bogus tag %d\n"), tag);
00712 return RPMERR_INTERNAL;
00713 }
00714
00715 if (macro)
00716 addMacro(spec->macros, macro, NULL, field, RMIL_SPEC);
00717
00718 return 0;
00719 }
00720
00721
00722
00723
00724
00727 typedef struct PreambleRec_s {
00728 rpmTag tag;
00729 int len;
00730 int multiLang;
00731
00732 const char * token;
00733 } * PreambleRec;
00734
00735
00736 static struct PreambleRec_s preambleList[] = {
00737 {RPMTAG_NAME, 0, 0, "name"},
00738 {RPMTAG_VERSION, 0, 0, "version"},
00739 {RPMTAG_RELEASE, 0, 0, "release"},
00740 {RPMTAG_EPOCH, 0, 0, "epoch"},
00741 {RPMTAG_EPOCH, 0, 0, "serial"},
00742 {RPMTAG_SUMMARY, 0, 1, "summary"},
00743 {RPMTAG_LICENSE, 0, 0, "copyright"},
00744 {RPMTAG_LICENSE, 0, 0, "license"},
00745 {RPMTAG_DISTRIBUTION, 0, 0, "distribution"},
00746 {RPMTAG_DISTURL, 0, 0, "disturl"},
00747 {RPMTAG_VENDOR, 0, 0, "vendor"},
00748 {RPMTAG_GROUP, 0, 1, "group"},
00749 {RPMTAG_PACKAGER, 0, 0, "packager"},
00750 {RPMTAG_URL, 0, 0, "url"},
00751 {RPMTAG_SOURCE, 0, 0, "source"},
00752 {RPMTAG_PATCH, 0, 0, "patch"},
00753 {RPMTAG_NOSOURCE, 0, 0, "nosource"},
00754 {RPMTAG_NOPATCH, 0, 0, "nopatch"},
00755 {RPMTAG_EXCLUDEARCH, 0, 0, "excludearch"},
00756 {RPMTAG_EXCLUSIVEARCH, 0, 0, "exclusivearch"},
00757 {RPMTAG_EXCLUDEOS, 0, 0, "excludeos"},
00758 {RPMTAG_EXCLUSIVEOS, 0, 0, "exclusiveos"},
00759 {RPMTAG_ICON, 0, 0, "icon"},
00760 {RPMTAG_PROVIDEFLAGS, 0, 0, "provides"},
00761 {RPMTAG_REQUIREFLAGS, 0, 1, "requires"},
00762 {RPMTAG_PREREQ, 0, 1, "prereq"},
00763 {RPMTAG_CONFLICTFLAGS, 0, 0, "conflicts"},
00764 {RPMTAG_OBSOLETEFLAGS, 0, 0, "obsoletes"},
00765 {RPMTAG_PREFIXES, 0, 0, "prefixes"},
00766 {RPMTAG_PREFIXES, 0, 0, "prefix"},
00767 {RPMTAG_BUILDROOT, 0, 0, "buildroot"},
00768 {RPMTAG_BUILDARCHS, 0, 0, "buildarchitectures"},
00769 {RPMTAG_BUILDARCHS, 0, 0, "buildarch"},
00770 {RPMTAG_BUILDCONFLICTS, 0, 0, "buildconflicts"},
00771 {RPMTAG_BUILDPREREQ, 0, 1, "buildprereq"},
00772 {RPMTAG_BUILDREQUIRES, 0, 1, "buildrequires"},
00773 {RPMTAG_AUTOREQPROV, 0, 0, "autoreqprov"},
00774 {RPMTAG_AUTOREQ, 0, 0, "autoreq"},
00775 {RPMTAG_AUTOPROV, 0, 0, "autoprov"},
00776 {RPMTAG_DOCDIR, 0, 0, "docdir"},
00777 {RPMTAG_RHNPLATFORM, 0, 0, "rhnplatform"},
00778
00779 {0, 0, 0, 0}
00780
00781 };
00782
00785 static inline void initPreambleList(void)
00786
00787
00788 {
00789 PreambleRec p;
00790 for (p = preambleList; p->token != NULL; p++)
00791 if (p->token) p->len = strlen(p->token);
00792 }
00793
00796
00797 static int findPreambleTag(Spec spec, int * tag,
00798 const char ** macro, char * lang)
00799
00800 {
00801 PreambleRec p;
00802 char *s;
00803
00804 if (preambleList[0].len == 0)
00805 initPreambleList();
00806
00807 for (p = preambleList; p->token != NULL; p++) {
00808 if (p->token && !xstrncasecmp(spec->line, p->token, p->len))
00809 break;
00810 }
00811 if (p->token == NULL)
00812 return 1;
00813
00814 s = spec->line + p->len;
00815 SKIPSPACE(s);
00816
00817 switch (p->multiLang) {
00818 default:
00819 case 0:
00820
00821 if (p->tag != RPMTAG_SOURCE && p->tag != RPMTAG_PATCH) {
00822 if (*s != ':') return 1;
00823 }
00824 *lang = '\0';
00825 break;
00826 case 1:
00827 if (*s == ':') {
00828 strcpy(lang, RPMBUILD_DEFAULT_LANG);
00829 break;
00830 }
00831 if (*s != '(') return 1;
00832 s++;
00833 SKIPSPACE(s);
00834 while (!xisspace(*s) && *s != ')')
00835 *lang++ = *s++;
00836 *lang = '\0';
00837 SKIPSPACE(s);
00838 if (*s != ')') return 1;
00839 s++;
00840 SKIPSPACE(s);
00841 if (*s != ':') return 1;
00842 break;
00843 }
00844
00845 *tag = p->tag;
00846 if (macro)
00847
00848 *macro = p->token;
00849
00850 return 0;
00851 }
00852
00853
00854
00855 int parsePreamble(Spec spec, int initialPackage)
00856 {
00857 int nextPart;
00858 int tag, rc, xx;
00859 char *name, *linep;
00860 int flag;
00861 Package pkg;
00862 char NVR[BUFSIZ];
00863 char lang[BUFSIZ];
00864
00865 strcpy(NVR, "(main package)");
00866
00867 pkg = newPackage(spec);
00868
00869 if (! initialPackage) {
00870
00871 if (parseSimplePart(spec->line, &name, &flag)) {
00872 rpmError(RPMERR_BADSPEC, _("Bad package specification: %s\n"),
00873 spec->line);
00874 return RPMERR_BADSPEC;
00875 }
00876
00877 if (!lookupPackage(spec, name, flag, NULL)) {
00878 rpmError(RPMERR_BADSPEC, _("Package already exists: %s\n"),
00879 spec->line);
00880 return RPMERR_BADSPEC;
00881 }
00882
00883
00884 if (flag == PART_SUBNAME) {
00885 const char * mainName;
00886 xx = headerNVR(spec->packages->header, &mainName, NULL, NULL);
00887 sprintf(NVR, "%s-%s", mainName, name);
00888 } else
00889 strcpy(NVR, name);
00890 xx = headerAddEntry(pkg->header, RPMTAG_NAME, RPM_STRING_TYPE, NVR, 1);
00891 }
00892
00893 if ((rc = readLine(spec, STRIP_TRAILINGSPACE | STRIP_COMMENTS)) > 0) {
00894 nextPart = PART_NONE;
00895 } else {
00896 if (rc)
00897 return rc;
00898 while (! (nextPart = isPart(spec->line))) {
00899 const char * macro;
00900
00901 linep = spec->line;
00902 SKIPSPACE(linep);
00903 if (*linep != '\0') {
00904 if (findPreambleTag(spec, &tag, ¯o, lang)) {
00905 rpmError(RPMERR_BADSPEC, _("line %d: Unknown tag: %s\n"),
00906 spec->lineNum, spec->line);
00907 return RPMERR_BADSPEC;
00908 }
00909 if (handlePreambleTag(spec, pkg, tag, macro, lang))
00910 return RPMERR_BADSPEC;
00911 if (spec->BANames && !spec->recursing)
00912 return PART_BUILDARCHITECTURES;
00913 }
00914 if ((rc =
00915 readLine(spec, STRIP_TRAILINGSPACE | STRIP_COMMENTS)) > 0) {
00916 nextPart = PART_NONE;
00917 break;
00918 }
00919 if (rc)
00920 return rc;
00921 }
00922 }
00923
00924
00925
00926 if (!spec->gotBuildRootURL && spec->buildRootURL) {
00927 rpmError(RPMERR_BADSPEC, _("Spec file can't use BuildRoot\n"));
00928 return RPMERR_BADSPEC;
00929 }
00930
00931
00932 if (!spec->anyarch && checkForValidArchitectures(spec))
00933 return RPMERR_BADSPEC;
00934
00935 if (pkg == spec->packages)
00936 fillOutMainPackage(pkg->header);
00937
00938 if (checkForDuplicates(pkg->header, NVR))
00939 return RPMERR_BADSPEC;
00940
00941 if (pkg != spec->packages)
00942 headerCopyTags(spec->packages->header, pkg->header,
00943 (int_32 *)copyTagsDuringParse);
00944
00945 if (checkForRequired(pkg->header, NVR))
00946 return RPMERR_BADSPEC;
00947
00948 return nextPart;
00949 }
00950