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