rpm 5.3.12
|
00001 00006 #include "system.h" 00007 00008 #include <rpmio_internal.h> /* XXX fdGetFp */ 00009 #include <rpmcb.h> 00010 #include <argv.h> 00011 00012 #define _RPMTAG_INTERNAL /* XXX rpmTags->aTags */ 00013 #include <rpmbuild.h> 00014 #include "rpmds.h" 00015 #include "rpmts.h" 00016 #include "debug.h" 00017 00018 /*@access headerTagIndices @*/ 00019 /*@access FD_t @*/ /* compared with NULL */ 00020 00023 /*@unchecked@*/ 00024 static struct PartRec { 00025 rpmParseState part; 00026 size_t len; 00027 /*@observer@*/ /*@null@*/ 00028 const char * token; 00029 } partList[] = { 00030 { PART_PREAMBLE, 0, "%package"}, 00031 { PART_PREP, 0, "%prep"}, 00032 { PART_BUILD, 0, "%build"}, 00033 { PART_INSTALL, 0, "%install"}, 00034 { PART_CHECK, 0, "%check"}, 00035 { PART_CLEAN, 0, "%clean"}, 00036 { PART_PREUN, 0, "%preun"}, 00037 { PART_POSTUN, 0, "%postun"}, 00038 { PART_PRETRANS, 0, "%pretrans"}, 00039 { PART_POSTTRANS, 0, "%posttrans"}, 00040 { PART_PRE, 0, "%pre"}, 00041 { PART_POST, 0, "%post"}, 00042 { PART_FILES, 0, "%files"}, 00043 { PART_CHANGELOG, 0, "%changelog"}, 00044 { PART_DESCRIPTION, 0, "%description"}, 00045 { PART_TRIGGERPOSTUN, 0, "%triggerpostun"}, 00046 { PART_TRIGGERPREIN, 0, "%triggerprein"}, 00047 { PART_TRIGGERUN, 0, "%triggerun"}, 00048 { PART_TRIGGERIN, 0, "%triggerin"}, 00049 { PART_TRIGGERIN, 0, "%trigger"}, 00050 { PART_VERIFYSCRIPT, 0, "%verifyscript"}, 00051 { PART_SANITYCHECK, 0, "%sanitycheck"}, /* support "%sanitycheck" scriptlet */ 00052 {0, 0, NULL} 00053 }; 00054 00057 static inline void initParts(struct PartRec *p) 00058 /*@modifies p->len @*/ 00059 { 00060 for (; p->token != NULL; p++) 00061 p->len = strlen(p->token); 00062 } 00063 00064 rpmParseState isPart(Spec spec) 00065 { 00066 const char * line = spec->line; 00067 struct PartRec *p; 00068 rpmParseState nextPart = PART_NONE; /* assume plain text */ 00069 00070 if (partList[0].len == 0) 00071 initParts(partList); 00072 00073 for (p = partList; p->token != NULL; p++) { 00074 char c; 00075 if (xstrncasecmp(line, p->token, p->len)) 00076 continue; 00077 c = *(line + p->len); 00078 if (c == '\0' || xisspace(c)) { 00079 nextPart = p->part; 00080 goto exit; 00081 } 00082 } 00083 00084 /* If %foo is not found explictly, check for an arbitrary %foo tag. */ 00085 if (line[0] == '%') { 00086 ARGV_t aTags = NULL; 00087 const char * s; 00088 /*@-noeffect@*/ 00089 (void) tagName(0); /* XXX force arbitrary tags to be initialized. */ 00090 /*@=noeffect@*/ 00091 aTags = rpmTags->aTags; 00092 if (aTags != NULL && aTags[0] != NULL) { 00093 ARGV_t av; 00094 s = tagCanonicalize(line+1); /* XXX +1 to skip leading '%' */ 00095 #if defined(RPM_VENDOR_OPENPKG) /* wildcard-matching-arbitrary-tagnames */ 00096 av = argvSearchLinear(aTags, s, argvFnmatchCasefold); 00097 #else 00098 av = argvSearch(aTags, s, argvStrcasecmp); 00099 #endif 00100 if (av != NULL) { 00101 spec->foo = xrealloc(spec->foo, (spec->nfoo + 1) * sizeof(*spec->foo)); 00102 spec->foo[spec->nfoo].str = xstrdup(s); 00103 spec->foo[spec->nfoo].tag = tagGenerate(s); 00104 spec->foo[spec->nfoo].iob = NULL; 00105 spec->nfoo++; 00106 nextPart = PART_ARBITRARY; 00107 } 00108 s = _free(s); 00109 } 00110 } 00111 00112 exit: 00113 return nextPart; 00114 } 00115 00118 static int matchTok(const char *token, const char *line) 00119 /*@*/ 00120 { 00121 const char *b, *be = line; 00122 size_t toklen = strlen(token); 00123 int rc = 0; 00124 00125 while ( *(b = be) != '\0' ) { 00126 SKIPSPACE(b); 00127 be = b; 00128 SKIPNONSPACE(be); 00129 if (be == b) 00130 break; 00131 if (toklen != (size_t)(be-b) || xstrncasecmp(token, b, (be-b))) 00132 continue; 00133 rc = 1; 00134 break; 00135 } 00136 00137 return rc; 00138 } 00139 00140 void handleComments(char *s) 00141 { 00142 SKIPSPACE(s); 00143 if (*s == '#') 00144 *s = '\0'; 00145 } 00146 00149 static void forceIncludeFile(Spec spec, const char * fileName) 00150 /*@modifies spec->fileStack @*/ 00151 { 00152 OFI_t * ofi; 00153 00154 ofi = newOpenFileInfo(); 00155 ofi->fileName = xstrdup(fileName); 00156 ofi->next = spec->fileStack; 00157 spec->fileStack = ofi; 00158 } 00159 00162 static int restoreFirstChar(Spec spec) 00163 /*@modifies spec->nextline, spec->nextpeekc @*/ 00164 { 00165 /* Restore 1st char in (possible) next line */ 00166 if (spec->nextline != NULL && spec->nextpeekc != '\0') { 00167 *spec->nextline = spec->nextpeekc; 00168 spec->nextpeekc = '\0'; 00169 return 1; 00170 } 00171 return 0; 00172 } 00173 00176 static int copyNextLineFromOFI(Spec spec, OFI_t * ofi, rpmStripFlags strip) 00177 /*@globals rpmGlobalMacroContext, h_errno, 00178 fileSystem, internalState @*/ 00179 /*@modifies spec->nextline, spec->lbuf, spec->lbufPtr, 00180 ofi->readPtr, 00181 rpmGlobalMacroContext, fileSystem, internalState @*/ 00182 { 00183 char ch; 00184 00185 /* Expand next line from file into line buffer */ 00186 if (!(spec->nextline && *spec->nextline)) { 00187 int pc = 0, bc = 0, nc = 0; 00188 char *from, *to, *p; 00189 to = spec->lbufPtr ? spec->lbufPtr : spec->lbuf; 00190 from = ofi->readPtr; 00191 ch = ' '; 00192 while (from && *from && ch != '\n') 00193 ch = *to++ = *from++; 00194 /*@-mods@*/ 00195 spec->lbufPtr = to; 00196 /*@=mods@*/ 00197 *to++ = '\0'; 00198 ofi->readPtr = from; 00199 00200 /* Check if we need another line before expanding the buffer. */ 00201 for (p = spec->lbuf; *p; p++) { 00202 switch (*p) { 00203 case '\\': 00204 switch (*(p+1)) { 00205 case '\n': p++, nc = 1; /*@innerbreak@*/ break; 00206 case '\0': /*@innerbreak@*/ break; 00207 default: p++; /*@innerbreak@*/ break; 00208 } 00209 /*@switchbreak@*/ break; 00210 case '\n': nc = 0; /*@switchbreak@*/ break; 00211 case '%': 00212 switch (*(p+1)) { 00213 case '{': p++, bc++; /*@innerbreak@*/ break; 00214 case '(': p++, pc++; /*@innerbreak@*/ break; 00215 case '%': p++; /*@innerbreak@*/ break; 00216 } 00217 /*@switchbreak@*/ break; 00218 case '{': if (bc > 0) bc++; /*@switchbreak@*/ break; 00219 case '}': if (bc > 0) bc--; /*@switchbreak@*/ break; 00220 case '(': if (pc > 0) pc++; /*@switchbreak@*/ break; 00221 case ')': if (pc > 0) pc--; /*@switchbreak@*/ break; 00222 } 00223 } 00224 00225 /* If it doesn't, ask for one more line. We need a better 00226 * error code for this. */ 00227 if (pc || bc || nc ) { 00228 /*@-observertrans -readonlytrans@*/ 00229 spec->nextline = ""; 00230 /*@=observertrans =readonlytrans@*/ 00231 return RPMRC_FAIL; 00232 } 00233 /*@-mods@*/ 00234 spec->lbufPtr = spec->lbuf; 00235 /*@=mods@*/ 00236 00237 /* Don't expand macros (eg. %define) in false branch of %if clause */ 00238 /* Also don't expand macros in %changelog if STRIP_NOEXPAND is set */ 00239 /* (first line is omitted, so %date macro will be expanded */ 00240 if (!(strip & STRIP_NOEXPAND)) { 00241 if (spec->readStack->reading && 00242 expandMacros(spec, spec->macros, spec->lbuf, spec->lbuf_len)) { 00243 rpmlog(RPMLOG_ERR, _("line %d: %s\n"), 00244 spec->lineNum, spec->lbuf); 00245 return RPMRC_FAIL; 00246 } 00247 } 00248 spec->nextline = spec->lbuf; 00249 } 00250 return 0; 00251 } 00252 00255 static int copyNextLineFinish(Spec spec, int strip) 00256 /*@modifies spec->line, spec->nextline, spec->nextpeekc @*/ 00257 { 00258 char *last; 00259 char ch; 00260 00261 /* Find next line in expanded line buffer */ 00262 spec->line = last = spec->nextline; 00263 ch = ' '; 00264 while (*spec->nextline && ch != '\n') { 00265 ch = *spec->nextline++; 00266 if (!xisspace(ch)) 00267 last = spec->nextline; 00268 } 00269 00270 /* Save 1st char of next line in order to terminate current line. */ 00271 if (*spec->nextline != '\0') { 00272 spec->nextpeekc = *spec->nextline; 00273 *spec->nextline = '\0'; 00274 } 00275 00276 if (strip & STRIP_COMMENTS) 00277 handleComments(spec->line); 00278 00279 if (strip & STRIP_TRAILINGSPACE) 00280 *last = '\0'; 00281 00282 return 0; 00283 } 00284 00287 static int readLineFromOFI(Spec spec, OFI_t *ofi) 00288 /*@globals h_errno, fileSystem, internalState @*/ 00289 /*@modifies ofi, spec->fileStack, spec->lineNum, spec->sl, 00290 fileSystem, internalState @*/ 00291 { 00292 retry: 00293 /* Make sure the current file is open */ 00294 if (ofi->fd == NULL) { 00295 ofi->fd = Fopen(ofi->fileName, "r.fpio"); 00296 if (ofi->fd == NULL || Ferror(ofi->fd)) { 00297 /* XXX Fstrerror */ 00298 rpmlog(RPMLOG_ERR, _("Unable to open %s: %s\n"), 00299 ofi->fileName, Fstrerror(ofi->fd)); 00300 return RPMRC_FAIL; 00301 } 00302 spec->lineNum = ofi->lineNum = 0; 00303 } 00304 00305 /* Make sure we have something in the read buffer */ 00306 if (!(ofi->readPtr && *(ofi->readPtr))) { 00307 /*@-type@*/ /* FIX: cast? */ 00308 FILE * f = fdGetFp(ofi->fd); 00309 /*@=type@*/ 00310 if (f == NULL || !fgets(ofi->readBuf, (int)sizeof(ofi->readBuf), f)) { 00311 /* EOF */ 00312 if (spec->readStack->next) { 00313 rpmlog(RPMLOG_ERR, _("Unclosed %%if\n")); 00314 return RPMRC_FAIL; 00315 } 00316 00317 /* remove this file from the stack */ 00318 spec->fileStack = ofi->next; 00319 (void) Fclose(ofi->fd); 00320 ofi->fileName = _free(ofi->fileName); 00321 /*@-temptrans@*/ 00322 ofi = _free(ofi); 00323 /*@=temptrans@*/ 00324 00325 /* only on last file do we signal EOF to caller */ 00326 ofi = spec->fileStack; 00327 if (ofi == NULL) 00328 return 1; 00329 00330 /* otherwise, go back and try the read again. */ 00331 goto retry; 00332 } 00333 ofi->readPtr = ofi->readBuf; 00334 ofi->lineNum++; 00335 spec->lineNum = ofi->lineNum; 00336 if (spec->sl) { 00337 speclines sl = spec->sl; 00338 if (sl->sl_nlines == sl->sl_nalloc) { 00339 sl->sl_nalloc += 100; 00340 sl->sl_lines = (char **) xrealloc(sl->sl_lines, 00341 sl->sl_nalloc * sizeof(*(sl->sl_lines))); 00342 } 00343 sl->sl_lines[sl->sl_nlines++] = xstrdup(ofi->readBuf); 00344 } 00345 } 00346 return 0; 00347 } 00348 00349 int readLine(Spec spec, rpmStripFlags strip) 00350 { 00351 char *s; 00352 int match; 00353 struct ReadLevelEntry *rl; 00354 OFI_t *ofi = spec->fileStack; 00355 int rc; 00356 00357 if (ofi == NULL) /* XXX segfault avoidance */ 00358 return 1; 00359 if (!restoreFirstChar(spec)) { 00360 retry: 00361 if ((rc = readLineFromOFI(spec, ofi)) != 0) 00362 return rc; 00363 00364 /* Copy next file line into the spec line buffer */ 00365 00366 if ((rc = copyNextLineFromOFI(spec, ofi, strip)) != 0) { 00367 if (rc == RPMRC_FAIL) 00368 goto retry; 00369 return rc; 00370 } 00371 } 00372 00373 (void) copyNextLineFinish(spec, strip); 00374 00375 s = spec->line; 00376 SKIPSPACE(s); 00377 00378 match = -1; 00379 if (!(strip & STRIP_NOEXPAND)) { 00380 if (!spec->readStack->reading && !strncmp("%if", s, sizeof("%if")-1)) { 00381 match = 0; 00382 } else if (! strncmp("%ifarch", s, sizeof("%ifarch")-1)) { 00383 const char *arch = rpmExpand("%{_target_cpu}", NULL); 00384 s += 7; 00385 match = matchTok(arch, s); 00386 arch = _free(arch); 00387 } else if (! strncmp("%ifnarch", s, sizeof("%ifnarch")-1)) { 00388 const char *arch = rpmExpand("%{_target_cpu}", NULL); 00389 s += 8; 00390 match = !matchTok(arch, s); 00391 arch = _free(arch); 00392 } else if (! strncmp("%ifos", s, sizeof("%ifos")-1)) { 00393 const char *os = rpmExpand("%{_target_os}", NULL); 00394 s += 5; 00395 match = matchTok(os, s); 00396 os = _free(os); 00397 } else if (! strncmp("%ifnos", s, sizeof("%ifnos")-1)) { 00398 const char *os = rpmExpand("%{_target_os}", NULL); 00399 s += 6; 00400 match = !matchTok(os, s); 00401 os = _free(os); 00402 } else if (! strncmp("%if", s, sizeof("%if")-1)) { 00403 s += 3; 00404 match = parseExpressionBoolean(spec, s); 00405 if (match < 0) { 00406 rpmlog(RPMLOG_ERR, 00407 _("%s:%d: parseExpressionBoolean returns %d\n"), 00408 ofi->fileName, ofi->lineNum, match); 00409 return RPMRC_FAIL; 00410 } 00411 } else if (! strncmp("%else", s, sizeof("%else")-1)) { 00412 s += 5; 00413 if (! spec->readStack->next) { 00414 /* Got an else with no %if ! */ 00415 rpmlog(RPMLOG_ERR, 00416 _("%s:%d: Got a %%else with no %%if\n"), 00417 ofi->fileName, ofi->lineNum); 00418 return RPMRC_FAIL; 00419 } 00420 spec->readStack->reading = 00421 spec->readStack->next->reading && ! spec->readStack->reading; 00422 spec->line[0] = '\0'; 00423 } else if (! strncmp("%endif", s, sizeof("%endif")-1)) { 00424 s += 6; 00425 if (! spec->readStack->next) { 00426 /* Got an end with no %if ! */ 00427 rpmlog(RPMLOG_ERR, 00428 _("%s:%d: Got a %%endif with no %%if\n"), 00429 ofi->fileName, ofi->lineNum); 00430 return RPMRC_FAIL; 00431 } 00432 rl = spec->readStack; 00433 spec->readStack = spec->readStack->next; 00434 free(rl); 00435 spec->line[0] = '\0'; 00436 } else if (! strncmp("%include", s, sizeof("%include")-1)) { 00437 char *fileName, *endFileName, *p; 00438 00439 s += 8; 00440 fileName = s; 00441 if (! xisspace(*fileName)) { 00442 rpmlog(RPMLOG_ERR, _("malformed %%include statement\n")); 00443 return RPMRC_FAIL; 00444 } 00445 SKIPSPACE(fileName); 00446 endFileName = fileName; 00447 SKIPNONSPACE(endFileName); 00448 p = endFileName; 00449 SKIPSPACE(p); 00450 if (*p != '\0') { 00451 rpmlog(RPMLOG_ERR, _("malformed %%include statement\n")); 00452 return RPMRC_FAIL; 00453 } 00454 *endFileName = '\0'; 00455 00456 forceIncludeFile(spec, fileName); 00457 00458 ofi = spec->fileStack; 00459 goto retry; 00460 } 00461 } 00462 00463 if (match != -1) { 00464 rl = xmalloc(sizeof(*rl)); 00465 rl->reading = spec->readStack->reading && match; 00466 rl->next = spec->readStack; 00467 spec->readStack = rl; 00468 spec->line[0] = '\0'; 00469 } 00470 00471 if (! spec->readStack->reading) { 00472 spec->line[0] = '\0'; 00473 } 00474 00475 /*@-compmempass@*/ /* FIX: spec->readStack->next should be dependent */ 00476 return 0; 00477 /*@=compmempass@*/ 00478 } 00479 00480 void closeSpec(Spec spec) 00481 { 00482 OFI_t *ofi; 00483 00484 while (spec->fileStack) { 00485 ofi = spec->fileStack; 00486 spec->fileStack = spec->fileStack->next; 00487 if (ofi->fd) (void) Fclose(ofi->fd); 00488 ofi->fileName = _free(ofi->fileName); 00489 ofi = _free(ofi); 00490 } 00491 } 00492 00495 static inline int genSourceRpmName(Spec spec) 00496 /*@globals internalState @*/ 00497 /*@modifies spec->sourceRpmName, spec->packages->header, 00498 internalState @*/ 00499 { 00500 if (spec->sourceRpmName == NULL) { 00501 const char *N, *V, *R; 00502 char fileName[BUFSIZ]; 00503 00504 (void) headerNEVRA(spec->packages->header, &N, NULL, &V, &R, NULL); 00505 (void) snprintf(fileName, sizeof(fileName), "%s-%s-%s.%ssrc.rpm", 00506 N, V, R, spec->noSource ? "no" : ""); 00507 fileName[sizeof(fileName)-1] = '\0'; 00508 N = _free(N); 00509 V = _free(V); 00510 R = _free(R); 00511 spec->sourceRpmName = xstrdup(fileName); 00512 } 00513 00514 return 0; 00515 } 00516 00517 /*@-redecl@*/ 00518 /*@unchecked@*/ 00519 extern int noLang; /* XXX FIXME: pass as arg */ 00520 /*@=redecl@*/ 00521 00522 /*@todo Skip parse recursion if os is not compatible. @*/ 00523 int parseSpec(rpmts ts, const char *specFile, const char *rootURL, 00524 int recursing, const char *passPhrase, 00525 const char *cookie, int anyarch, int force, int verify) 00526 { 00527 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he)); 00528 rpmParseState parsePart = PART_PREAMBLE; 00529 int initialPackage = 1; 00530 Package pkg; 00531 Spec spec; 00532 int xx; 00533 00534 /* Set up a new Spec structure with no packages. */ 00535 spec = newSpec(); 00536 00537 /* 00538 * Note: rpmGetPath should guarantee a "canonical" path. That means 00539 * that the following pathologies should be weeded out: 00540 * //bin//sh 00541 * //usr//bin/ 00542 * /.././../usr/../bin//./sh (XXX FIXME: dots not handled yet) 00543 */ 00544 spec->specFile = rpmGetPath(specFile, NULL); 00545 addMacro(spec->macros, "_specfile", NULL, spec->specFile, RMIL_SPEC); 00546 spec->fileStack = newOpenFileInfo(); 00547 spec->fileStack->fileName = xstrdup(spec->specFile); 00548 00549 spec->recursing = recursing; 00550 spec->toplevel = (!recursing ? 1 : 0); 00551 spec->anyarch = anyarch; 00552 spec->force = force; 00553 00554 if (rootURL) 00555 spec->rootURL = xstrdup(rootURL); 00556 if (passPhrase) 00557 spec->passPhrase = xstrdup(passPhrase); 00558 if (cookie) 00559 spec->cookie = xstrdup(cookie); 00560 00561 spec->timeCheck = rpmExpandNumeric("%{_timecheck}"); 00562 00563 /* XXX %_docdir should be set somewhere else. */ 00564 addMacro(NULL, "_docdir", NULL, "%{_defaultdocdir}", RMIL_SPEC); 00565 00566 /* All the parse*() functions expect to have a line pre-read */ 00567 /* in the spec's line buffer. Except for parsePreamble(), */ 00568 /* which handles the initial entry into a spec file. */ 00569 00570 /*@-infloops@*/ /* LCL: parsePart is modified @*/ 00571 while (parsePart > PART_NONE) { 00572 int goterror = 0; 00573 00574 switch (parsePart) { 00575 default: 00576 goterror = 1; 00577 /*@switchbreak@*/ break; 00578 case PART_PREAMBLE: 00579 parsePart = parsePreamble(spec, initialPackage); 00580 initialPackage = 0; 00581 /*@switchbreak@*/ break; 00582 case PART_PREP: 00583 parsePart = parsePrep(spec, verify); 00584 /*@switchbreak@*/ break; 00585 case PART_BUILD: 00586 case PART_INSTALL: 00587 case PART_CHECK: 00588 case PART_CLEAN: 00589 case PART_ARBITRARY: 00590 parsePart = parseBuildInstallClean(spec, parsePart); 00591 /*@switchbreak@*/ break; 00592 case PART_CHANGELOG: 00593 parsePart = parseChangelog(spec); 00594 /*@switchbreak@*/ break; 00595 case PART_DESCRIPTION: 00596 parsePart = parseDescription(spec); 00597 /*@switchbreak@*/ break; 00598 00599 case PART_PRE: 00600 case PART_POST: 00601 case PART_PREUN: 00602 case PART_POSTUN: 00603 case PART_PRETRANS: 00604 case PART_POSTTRANS: 00605 case PART_VERIFYSCRIPT: 00606 case PART_SANITYCHECK: 00607 case PART_TRIGGERPREIN: 00608 case PART_TRIGGERIN: 00609 case PART_TRIGGERUN: 00610 case PART_TRIGGERPOSTUN: 00611 parsePart = parseScript(spec, parsePart); 00612 /*@switchbreak@*/ break; 00613 00614 case PART_FILES: 00615 parsePart = parseFiles(spec); 00616 /*@switchbreak@*/ break; 00617 00618 case PART_NONE: /* XXX avoid gcc whining */ 00619 case PART_LAST: 00620 case PART_BUILDARCHITECTURES: 00621 /*@switchbreak@*/ break; 00622 } 00623 00624 if (goterror || parsePart >= PART_LAST) { 00625 spec = freeSpec(spec); 00626 return parsePart; 00627 } 00628 00629 /* Detect whether BuildArch: is toplevel or within %package. */ 00630 if (spec->toplevel && parsePart != PART_BUILDARCHITECTURES) 00631 spec->toplevel = 0; 00632 00633 /* Restart parse iff toplevel BuildArch: is encountered. */ 00634 if (spec->toplevel && parsePart == PART_BUILDARCHITECTURES) { 00635 int index; 00636 int x; 00637 00638 closeSpec(spec); 00639 00640 /* LCL: sizeof(spec->BASpecs[0]) -nullderef whine here */ 00641 spec->BASpecs = xcalloc(spec->BACount, sizeof(*spec->BASpecs)); 00642 index = 0; 00643 if (spec->BANames != NULL) 00644 for (x = 0; x < spec->BACount; x++) { 00645 00646 /* XXX DIEDIEDIE: filter irrelevant platforms here. */ 00647 00648 /* XXX there's more to do than set the macro. */ 00649 addMacro(NULL, "_target_cpu", NULL, spec->BANames[x], RMIL_RPMRC); 00650 spec->BASpecs[index] = NULL; 00651 if (parseSpec(ts, specFile, spec->rootURL, 1, 00652 passPhrase, cookie, anyarch, force, verify) 00653 || (spec->BASpecs[index] = rpmtsSetSpec(ts, NULL)) == NULL) 00654 { 00655 spec->BACount = index; 00656 /*@-nullstate@*/ 00657 spec = freeSpec(spec); 00658 return RPMRC_FAIL; 00659 /*@=nullstate@*/ 00660 } 00661 00662 /* XXX there's more to do than delete the macro. */ 00663 delMacro(NULL, "_target_cpu"); 00664 index++; 00665 } 00666 00667 spec->BACount = index; 00668 if (! index) { 00669 rpmlog(RPMLOG_ERR, 00670 _("No compatible architectures found for build\n")); 00671 /*@-nullstate@*/ 00672 spec = freeSpec(spec); 00673 return RPMRC_FAIL; 00674 /*@=nullstate@*/ 00675 } 00676 00677 /* 00678 * Return the 1st child's fully parsed Spec structure. 00679 * The restart of the parse when encountering BuildArch 00680 * causes problems for "rpm -q --specfile". This is 00681 * still a hack because there may be more than 1 arch 00682 * specified (unlikely but possible.) There's also the 00683 * further problem that the macro context, particularly 00684 * %{_target_cpu}, disagrees with the info in the header. 00685 */ 00686 if (spec->BACount >= 1) { 00687 Spec nspec = spec->BASpecs[0]; 00688 spec->BASpecs = _free(spec->BASpecs); 00689 spec = freeSpec(spec); 00690 spec = nspec; 00691 } 00692 00693 (void) rpmtsSetSpec(ts, spec); 00694 return 0; 00695 } 00696 } 00697 /*@=infloops@*/ /* LCL: parsePart is modified @*/ 00698 00699 /* Initialize source RPM name. */ 00700 (void) genSourceRpmName(spec); 00701 00702 /* Check for description in each package and add arch and os */ 00703 { 00704 const char *platform = rpmExpand("%{_target_platform}", NULL); 00705 #if defined(RPM_VENDOR_MANDRIVA) 00706 const char *platformNoarch = NULL; 00707 #endif 00708 const char *arch = rpmExpand("%{_target_cpu}", NULL); 00709 const char *os = rpmExpand("%{_target_os}", NULL); 00710 00711 for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) { 00712 he->tag = RPMTAG_OS; 00713 he->t = RPM_STRING_TYPE; 00714 /* XXX todo: really need "noos" like pkg->noarch somewhen. */ 00715 he->p.str = os; 00716 he->c = 1; 00717 xx = headerPut(pkg->header, he, 0); 00718 00719 he->tag = RPMTAG_ARCH; 00720 he->t = RPM_STRING_TYPE; 00721 he->p.str = (pkg->noarch ? "noarch" : arch); 00722 he->c = 1; 00723 xx = headerPut(pkg->header, he, 0); 00724 00725 #if defined(RPM_VENDOR_MANDRIVA) 00726 /* 00727 * If "noarch" subpackages of different arch, we need 00728 * to use a separate platform tag for these (mdvbz#61746). 00729 */ 00730 if(pkg->noarch && !platformNoarch && strcmp(arch, "noarch")) { 00731 addMacro(NULL, "_target_cpu", NULL, "noarch", RMIL_RPMRC); 00732 platformNoarch = rpmExpand("%{_target_platform}", NULL); 00733 addMacro(NULL, "_target_cpu", NULL, arch, RMIL_RPMRC); 00734 } 00735 #endif 00736 he->tag = RPMTAG_PLATFORM; 00737 he->t = RPM_STRING_TYPE; 00738 #if defined(RPM_VENDOR_MANDRIVA) 00739 he->p.str = (pkg->noarch && platformNoarch ? platformNoarch : platform); 00740 #else 00741 he->p.str = platform; 00742 #endif 00743 he->c = 1; 00744 xx = headerPut(pkg->header, he, 0); 00745 00746 he->tag = RPMTAG_SOURCERPM; 00747 he->t = RPM_STRING_TYPE; 00748 he->p.str = spec->sourceRpmName; 00749 he->c = 1; 00750 xx = headerPut(pkg->header, he, 0); 00751 00752 if (!headerIsEntry(pkg->header, RPMTAG_DESCRIPTION)) { 00753 he->tag = RPMTAG_NVRA; 00754 xx = headerGet(pkg->header, he, 0); 00755 rpmlog(RPMLOG_ERR, _("Package has no %%description: %s\n"), 00756 he->p.str); 00757 he->p.ptr = _free(he->p.ptr); 00758 platform = _free(platform); 00759 #if defined(RPM_VENDOR_MANDRIVA) 00760 platformNoarch = _free(platformNoarch); 00761 #endif 00762 arch = _free(arch); 00763 os = _free(os); 00764 spec = freeSpec(spec); 00765 return RPMRC_FAIL; 00766 } 00767 00768 pkg->ds = rpmdsThis(pkg->header, RPMTAG_REQUIRENAME, RPMSENSE_EQUAL); 00769 00770 } 00771 00772 platform = _free(platform); 00773 #if defined(RPM_VENDOR_MANDRIVA) 00774 platformNoarch = _free(platformNoarch); 00775 #endif 00776 arch = _free(arch); 00777 os = _free(os); 00778 } 00779 00780 closeSpec(spec); 00781 (void) rpmtsSetSpec(ts, spec); 00782 00783 return 0; 00784 }