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