00001
00006 #include "system.h"
00007
00008
00009 static int _debug = 0;
00010
00011 #include <rpmio_internal.h>
00012 #include <rpmbuild.h>
00013 #include "rpmds.h"
00014 #include "rpmts.h"
00015 #include "debug.h"
00016
00017
00018
00021
00022 static struct PartRec {
00023 int part;
00024 int len;
00025
00026 const char * token;
00027 } partList[] = {
00028 { PART_PREAMBLE, 0, "%package"},
00029 { PART_PREP, 0, "%prep"},
00030 { PART_BUILD, 0, "%build"},
00031 { PART_INSTALL, 0, "%install"},
00032 { PART_CHECK, 0, "%check"},
00033 { PART_CLEAN, 0, "%clean"},
00034 { PART_PREUN, 0, "%preun"},
00035 { PART_POSTUN, 0, "%postun"},
00036 { PART_PRE, 0, "%pre"},
00037 { PART_POST, 0, "%post"},
00038 { PART_FILES, 0, "%files"},
00039 { PART_CHANGELOG, 0, "%changelog"},
00040 { PART_DESCRIPTION, 0, "%description"},
00041 { PART_TRIGGERPOSTUN, 0, "%triggerpostun"},
00042 { PART_TRIGGERUN, 0, "%triggerun"},
00043 { PART_TRIGGERIN, 0, "%triggerin"},
00044 { PART_TRIGGERIN, 0, "%trigger"},
00045 { PART_VERIFYSCRIPT, 0, "%verifyscript"},
00046 {0, 0, 0}
00047 };
00048
00051 static inline void initParts(struct PartRec *p)
00052
00053 {
00054 for (; p->token != NULL; p++)
00055 p->len = strlen(p->token);
00056 }
00057
00058 rpmParseState isPart(const char *line)
00059 {
00060 struct PartRec *p;
00061
00062
00063 if (partList[0].len == 0)
00064 initParts(partList);
00065
00066
00067 for (p = partList; p->token != NULL; p++) {
00068 char c;
00069 if (xstrncasecmp(line, p->token, p->len))
00070 continue;
00071
00072 c = *(line + p->len);
00073
00074 if (c == '\0' || xisspace(c))
00075 break;
00076 }
00077
00078 return (p->token ? p->part : PART_NONE);
00079 }
00080
00083 static int matchTok(const char *token, const char *line)
00084
00085 {
00086 const char *b, *be = line;
00087 size_t toklen = strlen(token);
00088 int rc = 0;
00089
00090
00091 while ( *(b = be) != '\0' ) {
00092 SKIPSPACE(b);
00093 be = b;
00094 SKIPNONSPACE(be);
00095 if (be == b)
00096 break;
00097 if (toklen != (be-b) || xstrncasecmp(token, b, (be-b)))
00098 continue;
00099 rc = 1;
00100 break;
00101 }
00102
00103
00104 return rc;
00105 }
00106
00107
00108 void handleComments(char *s)
00109 {
00110 SKIPSPACE(s);
00111 if (*s == '#')
00112 *s = '\0';
00113 }
00114
00115
00118 static void forceIncludeFile(Spec spec, const char * fileName)
00119
00120 {
00121 OFI_t * ofi;
00122
00123 ofi = newOpenFileInfo();
00124 ofi->fileName = xstrdup(fileName);
00125 ofi->next = spec->fileStack;
00126 spec->fileStack = ofi;
00127 }
00128
00131
00132 static int copyNextLine(Spec spec, OFI_t *ofi, int strip)
00133
00134
00135
00136
00137
00138 {
00139 char *last;
00140 char ch;
00141
00142
00143 if (spec->nextline != NULL && spec->nextpeekc != '\0') {
00144 *spec->nextline = spec->nextpeekc;
00145 spec->nextpeekc = '\0';
00146 }
00147
00148 if (!(spec->nextline && *spec->nextline)) {
00149 char *from, *to;
00150 to = last = spec->lbuf;
00151 from = ofi->readPtr;
00152 ch = ' ';
00153 while (*from && ch != '\n')
00154 ch = *to++ = *from++;
00155 *to++ = '\0';
00156 ofi->readPtr = from;
00157
00158
00159 if (spec->readStack->reading &&
00160 expandMacros(spec, spec->macros, spec->lbuf, sizeof(spec->lbuf))) {
00161 rpmError(RPMERR_BADSPEC, _("line %d: %s\n"),
00162 spec->lineNum, spec->lbuf);
00163 return RPMERR_BADSPEC;
00164 }
00165 spec->nextline = spec->lbuf;
00166 }
00167
00168
00169 spec->line = last = spec->nextline;
00170 ch = ' ';
00171 while (*spec->nextline && ch != '\n') {
00172 ch = *spec->nextline++;
00173 if (!xisspace(ch))
00174 last = spec->nextline;
00175 }
00176
00177
00178 if (*spec->nextline != '\0') {
00179 spec->nextpeekc = *spec->nextline;
00180 *spec->nextline = '\0';
00181 }
00182
00183 if (strip & STRIP_COMMENTS)
00184 handleComments(spec->line);
00185
00186 if (strip & STRIP_TRAILINGSPACE)
00187 *last = '\0';
00188
00189 return 0;
00190 }
00191
00192
00193
00194 int readLine(Spec spec, int strip)
00195 {
00196 #ifdef DYING
00197 const char *arch;
00198 const char *os;
00199 #endif
00200 char *s;
00201 int match;
00202 struct ReadLevelEntry *rl;
00203 OFI_t *ofi = spec->fileStack;
00204 int rc;
00205
00206 retry:
00207
00208
00209 if (ofi->fd == NULL) {
00210 ofi->fd = Fopen(ofi->fileName, "r.fpio");
00211 if (ofi->fd == NULL || Ferror(ofi->fd)) {
00212
00213 rpmError(RPMERR_BADSPEC, _("Unable to open %s: %s\n"),
00214 ofi->fileName, Fstrerror(ofi->fd));
00215 return RPMERR_BADSPEC;
00216 }
00217 spec->lineNum = ofi->lineNum = 0;
00218 }
00219
00220
00221
00222 if (!(ofi->readPtr && *(ofi->readPtr))) {
00223
00224 FILE * f = fdGetFp(ofi->fd);
00225
00226 if (f == NULL || !fgets(ofi->readBuf, BUFSIZ, f)) {
00227
00228 if (spec->readStack->next) {
00229 rpmError(RPMERR_UNMATCHEDIF, _("Unclosed %%if\n"));
00230 return RPMERR_UNMATCHEDIF;
00231 }
00232
00233
00234 spec->fileStack = ofi->next;
00235 (void) Fclose(ofi->fd);
00236 ofi->fileName = _free(ofi->fileName);
00237 ofi = _free(ofi);
00238
00239
00240 ofi = spec->fileStack;
00241 if (ofi == NULL)
00242 return 1;
00243
00244
00245 goto retry;
00246 }
00247 ofi->readPtr = ofi->readBuf;
00248 ofi->lineNum++;
00249 spec->lineNum = ofi->lineNum;
00250 if (spec->sl) {
00251 speclines sl = spec->sl;
00252 if (sl->sl_nlines == sl->sl_nalloc) {
00253 sl->sl_nalloc += 100;
00254 sl->sl_lines = (char **) xrealloc(sl->sl_lines,
00255 sl->sl_nalloc * sizeof(*(sl->sl_lines)));
00256 }
00257 sl->sl_lines[sl->sl_nlines++] = xstrdup(ofi->readBuf);
00258 }
00259 }
00260
00261 #ifdef DYING
00262 arch = NULL;
00263 rpmGetArchInfo(&arch, NULL);
00264 os = NULL;
00265 rpmGetOsInfo(&os, NULL);
00266 #endif
00267
00268
00269 if ((rc = copyNextLine(spec, ofi, strip)) != 0)
00270 return rc;
00271
00272 s = spec->line;
00273 SKIPSPACE(s);
00274
00275 match = -1;
00276 if (!spec->readStack->reading && !strncmp("%if", s, sizeof("%if")-1)) {
00277 match = 0;
00278 } else if (! strncmp("%ifarch", s, sizeof("%ifarch")-1)) {
00279 const char *arch = rpmExpand("%{_target_cpu}", NULL);
00280 s += 7;
00281 match = matchTok(arch, s);
00282 arch = _free(arch);
00283 } else if (! strncmp("%ifnarch", s, sizeof("%ifnarch")-1)) {
00284 const char *arch = rpmExpand("%{_target_cpu}", NULL);
00285 s += 8;
00286 match = !matchTok(arch, s);
00287 arch = _free(arch);
00288 } else if (! strncmp("%ifos", s, sizeof("%ifos")-1)) {
00289 const char *os = rpmExpand("%{_target_os}", NULL);
00290 s += 5;
00291 match = matchTok(os, s);
00292 os = _free(os);
00293 } else if (! strncmp("%ifnos", s, sizeof("%ifnos")-1)) {
00294 const char *os = rpmExpand("%{_target_os}", NULL);
00295 s += 6;
00296 match = !matchTok(os, s);
00297 os = _free(os);
00298 } else if (! strncmp("%if", s, sizeof("%if")-1)) {
00299 s += 3;
00300 match = parseExpressionBoolean(spec, s);
00301 if (match < 0) {
00302 rpmError(RPMERR_UNMATCHEDIF,
00303 _("%s:%d: parseExpressionBoolean returns %d\n"),
00304 ofi->fileName, ofi->lineNum, match);
00305 return RPMERR_BADSPEC;
00306 }
00307 } else if (! strncmp("%else", s, sizeof("%else")-1)) {
00308 s += 5;
00309 if (! spec->readStack->next) {
00310
00311 rpmError(RPMERR_UNMATCHEDIF,
00312 _("%s:%d: Got a %%else with no %%if\n"),
00313 ofi->fileName, ofi->lineNum);
00314 return RPMERR_UNMATCHEDIF;
00315 }
00316 spec->readStack->reading =
00317 spec->readStack->next->reading && ! spec->readStack->reading;
00318 spec->line[0] = '\0';
00319 } else if (! strncmp("%endif", s, sizeof("%endif")-1)) {
00320 s += 6;
00321 if (! spec->readStack->next) {
00322
00323 rpmError(RPMERR_UNMATCHEDIF,
00324 _("%s:%d: Got a %%endif with no %%if\n"),
00325 ofi->fileName, ofi->lineNum);
00326 return RPMERR_UNMATCHEDIF;
00327 }
00328 rl = spec->readStack;
00329 spec->readStack = spec->readStack->next;
00330 free(rl);
00331 spec->line[0] = '\0';
00332 } else if (! strncmp("%include", s, sizeof("%include")-1)) {
00333 char *fileName, *endFileName, *p;
00334
00335 s += 8;
00336 fileName = s;
00337 if (! xisspace(*fileName)) {
00338 rpmError(RPMERR_BADSPEC, _("malformed %%include statement\n"));
00339 return RPMERR_BADSPEC;
00340 }
00341 SKIPSPACE(fileName);
00342 endFileName = fileName;
00343 SKIPNONSPACE(endFileName);
00344 p = endFileName;
00345 SKIPSPACE(p);
00346 if (*p != '\0') {
00347 rpmError(RPMERR_BADSPEC, _("malformed %%include statement\n"));
00348 return RPMERR_BADSPEC;
00349 }
00350 *endFileName = '\0';
00351
00352 forceIncludeFile(spec, fileName);
00353
00354 ofi = spec->fileStack;
00355 goto retry;
00356 }
00357
00358 if (match != -1) {
00359 rl = xmalloc(sizeof(*rl));
00360 rl->reading = spec->readStack->reading && match;
00361 rl->next = spec->readStack;
00362 spec->readStack = rl;
00363 spec->line[0] = '\0';
00364 }
00365
00366 if (! spec->readStack->reading) {
00367 spec->line[0] = '\0';
00368 }
00369
00370
00371 return 0;
00372
00373 }
00374
00375
00376 void closeSpec(Spec spec)
00377 {
00378 OFI_t *ofi;
00379
00380 while (spec->fileStack) {
00381 ofi = spec->fileStack;
00382 spec->fileStack = spec->fileStack->next;
00383 if (ofi->fd) (void) Fclose(ofi->fd);
00384 ofi->fileName = _free(ofi->fileName);
00385 ofi = _free(ofi);
00386 }
00387 }
00388
00389
00390
00391 extern int noLang;
00392
00393
00394
00395
00396 int parseSpec(rpmts ts, const char *specFile, const char *rootURL,
00397 const char *buildRootURL, int recursing, const char *passPhrase,
00398 char *cookie, int anyarch, int force)
00399 {
00400 rpmParseState parsePart = PART_PREAMBLE;
00401 int initialPackage = 1;
00402 #ifdef DYING
00403 const char *saveArch;
00404 #endif
00405 Package pkg;
00406 Spec spec;
00407
00408
00409 spec = newSpec();
00410
00411
00412
00413
00414
00415
00416
00417
00418 spec->specFile = rpmGetPath(specFile, NULL);
00419 spec->fileStack = newOpenFileInfo();
00420 spec->fileStack->fileName = xstrdup(spec->specFile);
00421 if (buildRootURL) {
00422 const char * buildRoot;
00423 (void) urlPath(buildRootURL, &buildRoot);
00424
00425 if (*buildRoot == '\0') buildRoot = "/";
00426
00427 if (!strcmp(buildRoot, "/")) {
00428 rpmError(RPMERR_BADSPEC,
00429 _("BuildRoot can not be \"/\": %s\n"), buildRootURL);
00430 return RPMERR_BADSPEC;
00431 }
00432 spec->gotBuildRootURL = 1;
00433 spec->buildRootURL = xstrdup(buildRootURL);
00434 addMacro(spec->macros, "buildroot", NULL, buildRoot, RMIL_SPEC);
00435 }
00436 addMacro(NULL, "_docdir", NULL, "%{_defaultdocdir}", RMIL_SPEC);
00437 spec->recursing = recursing;
00438 spec->anyarch = anyarch;
00439 spec->force = force;
00440
00441 if (rootURL)
00442 spec->rootURL = xstrdup(rootURL);
00443 if (passPhrase)
00444 spec->passPhrase = xstrdup(passPhrase);
00445 if (cookie)
00446 spec->cookie = xstrdup(cookie);
00447
00448 spec->timeCheck = rpmExpandNumeric("%{_timecheck}");
00449
00450
00451
00452
00453
00454
00455 while (parsePart < PART_LAST && parsePart != PART_NONE) {
00456 switch (parsePart) {
00457 case PART_PREAMBLE:
00458 parsePart = parsePreamble(spec, initialPackage);
00459 initialPackage = 0;
00460 break;
00461 case PART_PREP:
00462 parsePart = parsePrep(spec);
00463 break;
00464 case PART_BUILD:
00465 case PART_INSTALL:
00466 case PART_CHECK:
00467 case PART_CLEAN:
00468 parsePart = parseBuildInstallClean(spec, parsePart);
00469 break;
00470 case PART_CHANGELOG:
00471 parsePart = parseChangelog(spec);
00472 break;
00473 case PART_DESCRIPTION:
00474 parsePart = parseDescription(spec);
00475 break;
00476
00477 case PART_PRE:
00478 case PART_POST:
00479 case PART_PREUN:
00480 case PART_POSTUN:
00481 case PART_VERIFYSCRIPT:
00482 case PART_TRIGGERIN:
00483 case PART_TRIGGERUN:
00484 case PART_TRIGGERPOSTUN:
00485 parsePart = parseScript(spec, parsePart);
00486 break;
00487
00488 case PART_FILES:
00489 parsePart = parseFiles(spec);
00490 break;
00491
00492 case PART_NONE:
00493 case PART_LAST:
00494 case PART_BUILDARCHITECTURES:
00495 break;
00496 }
00497
00498 if (parsePart >= PART_LAST) {
00499 spec = freeSpec(spec);
00500 return parsePart;
00501 }
00502
00503 if (parsePart == PART_BUILDARCHITECTURES) {
00504 int index;
00505 int x;
00506
00507 closeSpec(spec);
00508
00509
00510 spec->BASpecs = xcalloc(spec->BACount, sizeof(*spec->BASpecs));
00511 index = 0;
00512 if (spec->BANames != NULL)
00513 for (x = 0; x < spec->BACount; x++) {
00514
00515
00516 if (!rpmMachineScore(RPM_MACHTABLE_BUILDARCH, spec->BANames[x]))
00517 continue;
00518 #ifdef DYING
00519 rpmGetMachine(&saveArch, NULL);
00520 saveArch = xstrdup(saveArch);
00521 rpmSetMachine(spec->BANames[x], NULL);
00522 #else
00523 addMacro(NULL, "_target_cpu", NULL, spec->BANames[x], RMIL_RPMRC);
00524 #endif
00525 spec->BASpecs[index] = NULL;
00526 if (parseSpec(ts, specFile, spec->rootURL, buildRootURL, 1,
00527 passPhrase, cookie, anyarch, force)
00528 || (spec->BASpecs[index] = rpmtsSetSpec(ts, NULL)) == NULL)
00529 {
00530 spec->BACount = index;
00531
00532 spec = freeSpec(spec);
00533 return RPMERR_BADSPEC;
00534
00535 }
00536 #ifdef DYING
00537 rpmSetMachine(saveArch, NULL);
00538 saveArch = _free(saveArch);
00539 #else
00540 delMacro(NULL, "_target_cpu");
00541 #endif
00542 index++;
00543 }
00544
00545 spec->BACount = index;
00546 if (! index) {
00547 rpmError(RPMERR_BADSPEC,
00548 _("No compatible architectures found for build\n"));
00549
00550 spec = freeSpec(spec);
00551 return RPMERR_BADSPEC;
00552
00553 }
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565 if (spec->BACount >= 1) {
00566 Spec nspec = spec->BASpecs[0];
00567 spec->BASpecs = _free(spec->BASpecs);
00568 spec = freeSpec(spec);
00569 spec = nspec;
00570 }
00571
00572
00573 (void) rpmtsSetSpec(ts, spec);
00574 return 0;
00575 }
00576 }
00577
00578
00579
00580 {
00581 #ifdef DYING
00582 const char *arch = NULL;
00583 const char *os = NULL;
00584 char *myos = NULL;
00585
00586 rpmGetArchInfo(&arch, NULL);
00587 rpmGetOsInfo(&os, NULL);
00588
00589
00590
00591
00592
00593
00594 if (!strcmp(os, "linux")) {
00595 myos = xstrdup(os);
00596 *myos = 'L';
00597 os = myos;
00598 }
00599 #else
00600 const char *platform = rpmExpand("%{_target_platform}", NULL);
00601 const char *arch = rpmExpand("%{_target_cpu}", NULL);
00602 const char *os = rpmExpand("%{_target_os}", NULL);
00603 #endif
00604
00605 for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) {
00606 if (!headerIsEntry(pkg->header, RPMTAG_DESCRIPTION)) {
00607 const char * name;
00608 (void) headerNVR(pkg->header, &name, NULL, NULL);
00609 rpmError(RPMERR_BADSPEC, _("Package has no %%description: %s\n"),
00610 name);
00611 spec = freeSpec(spec);
00612 return RPMERR_BADSPEC;
00613 }
00614
00615 (void) headerAddEntry(pkg->header, RPMTAG_OS, RPM_STRING_TYPE, os, 1);
00616 (void) headerAddEntry(pkg->header, RPMTAG_ARCH,
00617 RPM_STRING_TYPE, arch, 1);
00618 if (!headerIsEntry(pkg->header, RPMTAG_RHNPLATFORM))
00619 (void) headerAddEntry(pkg->header, RPMTAG_RHNPLATFORM,
00620 RPM_STRING_TYPE, arch, 1);
00621 (void) headerAddEntry(pkg->header, RPMTAG_PLATFORM,
00622 RPM_STRING_TYPE, platform, 1);
00623
00624 pkg->ds = rpmdsThis(pkg->header, RPMTAG_REQUIRENAME, RPMSENSE_EQUAL);
00625
00626 }
00627
00628 #ifdef DYING
00629 myos = _free(myos);
00630 #else
00631 platform = _free(platform);
00632 arch = _free(arch);
00633 os = _free(os);
00634 #endif
00635 }
00636
00637 closeSpec(spec);
00638 (void) rpmtsSetSpec(ts, spec);
00639
00640 return 0;
00641 }
00642