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