build/parseSpec.c

Go to the documentation of this file.
00001 
00006 #include "system.h"
00007 
00008 #include <rpmio_internal.h>
00009 #include <rpmbuild.h>
00010 #include "rpmds.h"
00011 #include "rpmts.h"
00012 #include "debug.h"
00013 
00014 /*@access FD_t @*/      /* compared with NULL */
00015 
00018 /*@unchecked@*/
00019 static struct PartRec {
00020     int part;
00021     int len;
00022 /*@observer@*/ /*@null@*/
00023     const char * token;
00024 } partList[] = {
00025     { PART_PREAMBLE,      0, "%package"},
00026     { PART_PREP,          0, "%prep"},
00027     { PART_BUILD,         0, "%build"},
00028     { PART_INSTALL,       0, "%install"},
00029     { PART_CHECK,         0, "%check"},
00030     { PART_CLEAN,         0, "%clean"},
00031     { PART_PREUN,         0, "%preun"},
00032     { PART_POSTUN,        0, "%postun"},
00033     { PART_PRETRANS,      0, "%pretrans"},
00034     { PART_POSTTRANS,     0, "%posttrans"},
00035     { PART_PRE,           0, "%pre"},
00036     { PART_POST,          0, "%post"},
00037     { PART_FILES,         0, "%files"},
00038     { PART_CHANGELOG,     0, "%changelog"},
00039     { PART_DESCRIPTION,   0, "%description"},
00040     { PART_TRIGGERPOSTUN, 0, "%triggerpostun"},
00041     { PART_TRIGGERUN,     0, "%triggerun"},
00042     { PART_TRIGGERIN,     0, "%triggerin"},
00043     { PART_TRIGGERIN,     0, "%trigger"},
00044     { PART_VERIFYSCRIPT,  0, "%verifyscript"},
00045     {0, 0, 0}
00046 };
00047 
00050 static inline void initParts(struct PartRec *p)
00051         /*@modifies p->len @*/
00052 {
00053     for (; p->token != NULL; p++)
00054         p->len = strlen(p->token);
00055 }
00056 
00057 rpmParseState isPart(const char *line)
00058 {
00059     struct PartRec *p;
00060 
00061 /*@-boundsread@*/
00062     if (partList[0].len == 0)
00063         initParts(partList);
00064 /*@=boundsread@*/
00065     
00066     for (p = partList; p->token != NULL; p++) {
00067         char c;
00068         if (xstrncasecmp(line, p->token, p->len))
00069             continue;
00070 /*@-boundsread@*/
00071         c = *(line + p->len);
00072 /*@=boundsread@*/
00073         if (c == '\0' || xisspace(c))
00074             break;
00075     }
00076 
00077     return (p->token ? p->part : PART_NONE);
00078 }
00079 
00082 static int matchTok(const char *token, const char *line)
00083         /*@*/
00084 {
00085     const char *b, *be = line;
00086     size_t toklen = strlen(token);
00087     int rc = 0;
00088 
00089 /*@-boundsread@*/
00090     while ( *(b = be) != '\0' ) {
00091         SKIPSPACE(b);
00092         be = b;
00093         SKIPNONSPACE(be);
00094         if (be == b)
00095             break;
00096         if (toklen != (be-b) || xstrncasecmp(token, b, (be-b)))
00097             continue;
00098         rc = 1;
00099         break;
00100     }
00101 /*@=boundsread@*/
00102 
00103     return rc;
00104 }
00105 
00106 /*@-boundswrite@*/
00107 void handleComments(char *s)
00108 {
00109     SKIPSPACE(s);
00110     if (*s == '#')
00111         *s = '\0';
00112 }
00113 /*@=boundswrite@*/
00114 
00117 static void forceIncludeFile(Spec spec, const char * fileName)
00118         /*@modifies spec->fileStack @*/
00119 {
00120     OFI_t * ofi;
00121 
00122     ofi = newOpenFileInfo();
00123     ofi->fileName = xstrdup(fileName);
00124     ofi->next = spec->fileStack;
00125     spec->fileStack = ofi;
00126 }
00127 
00130 /*@-boundswrite@*/
00131 static int copyNextLine(Spec spec, OFI_t *ofi, int strip)
00132         /*@globals rpmGlobalMacroContext, h_errno,
00133                 fileSystem @*/
00134         /*@modifies spec->nextline, spec->nextpeekc, spec->lbuf, spec->line,
00135                 ofi->readPtr,
00136                 rpmGlobalMacroContext, fileSystem @*/
00137 {
00138     char *last;
00139     char ch;
00140 
00141     /* Restore 1st char in (possible) next line */
00142     if (spec->nextline != NULL && spec->nextpeekc != '\0') {
00143         *spec->nextline = spec->nextpeekc;
00144         spec->nextpeekc = '\0';
00145     }
00146     /* Expand next line from file into line buffer */
00147     if (!(spec->nextline && *spec->nextline)) {
00148         int pc = 0, bc = 0, nc = 0;
00149         char *from, *to, *p;
00150         to = spec->lbufPtr ? spec->lbufPtr : spec->lbuf;
00151         from = ofi->readPtr;
00152         ch = ' ';
00153         while (*from && ch != '\n')
00154             ch = *to++ = *from++;
00155 /*@-mods@*/
00156         spec->lbufPtr = to;
00157 /*@=mods@*/
00158         *to++ = '\0';
00159         ofi->readPtr = from;
00160 
00161         /* Check if we need another line before expanding the buffer. */
00162         for (p = spec->lbuf; *p; p++) {
00163             switch (*p) {
00164                 case '\\':
00165                     switch (*(p+1)) {
00166                         case '\n': p++, nc = 1; /*@innerbreak@*/ break;
00167                         case '\0': /*@innerbreak@*/ break;
00168                         default: p++; /*@innerbreak@*/ break;
00169                     }
00170                     /*@switchbreak@*/ break;
00171                 case '\n': nc = 0; /*@switchbreak@*/ break;
00172                 case '%':
00173                     switch (*(p+1)) {
00174                         case '{': p++, bc++; /*@innerbreak@*/ break;
00175                         case '(': p++, pc++; /*@innerbreak@*/ break;
00176                         case '%': p++; /*@innerbreak@*/ break;
00177                     }
00178                     /*@switchbreak@*/ break;
00179                 case '{': if (bc > 0) bc++; /*@switchbreak@*/ break;
00180                 case '}': if (bc > 0) bc--; /*@switchbreak@*/ break;
00181                 case '(': if (pc > 0) pc++; /*@switchbreak@*/ break;
00182                 case ')': if (pc > 0) pc--; /*@switchbreak@*/ break;
00183             }
00184         }
00185         
00186         /* If it doesn't, ask for one more line. We need a better
00187          * error code for this. */
00188         if (pc || bc || nc ) {
00189 /*@-observertrans -readonlytrans@*/
00190             spec->nextline = "";
00191 /*@=observertrans =readonlytrans@*/
00192             return RPMERR_UNMATCHEDIF;
00193         }
00194 /*@-mods@*/
00195         spec->lbufPtr = spec->lbuf;
00196 /*@=mods@*/
00197 
00198         /* Don't expand macros (eg. %define) in false branch of %if clause */
00199         if (spec->readStack->reading &&
00200             expandMacros(spec, spec->macros, spec->lbuf, sizeof(spec->lbuf))) {
00201                 rpmError(RPMERR_BADSPEC, _("line %d: %s\n"),
00202                         spec->lineNum, spec->lbuf);
00203                 return RPMERR_BADSPEC;
00204         }
00205         spec->nextline = spec->lbuf;
00206     }
00207 
00208     /* Find next line in expanded line buffer */
00209     spec->line = last = spec->nextline;
00210     ch = ' ';
00211     while (*spec->nextline && ch != '\n') {
00212         ch = *spec->nextline++;
00213         if (!xisspace(ch))
00214             last = spec->nextline;
00215     }
00216 
00217     /* Save 1st char of next line in order to terminate current line. */
00218     if (*spec->nextline != '\0') {
00219         spec->nextpeekc = *spec->nextline;
00220         *spec->nextline = '\0';
00221     }
00222     
00223     if (strip & STRIP_COMMENTS)
00224         handleComments(spec->line);
00225     
00226     if (strip & STRIP_TRAILINGSPACE)
00227         *last = '\0';
00228 
00229     return 0;
00230 }
00231 /*@=boundswrite@*/
00232 
00233 /*@-boundswrite@*/
00234 int readLine(Spec spec, int strip)
00235 {
00236 #ifdef  DYING
00237     const char *arch;
00238     const char *os;
00239 #endif
00240     char  *s;
00241     int match;
00242     struct ReadLevelEntry *rl;
00243     OFI_t *ofi = spec->fileStack;
00244     int rc;
00245 
00246 retry:
00247     /* Make sure the current file is open */
00248     /*@-branchstate@*/
00249     if (ofi->fd == NULL) {
00250         ofi->fd = Fopen(ofi->fileName, "r.fpio");
00251         if (ofi->fd == NULL || Ferror(ofi->fd)) {
00252             /* XXX Fstrerror */
00253             rpmError(RPMERR_BADSPEC, _("Unable to open %s: %s\n"),
00254                      ofi->fileName, Fstrerror(ofi->fd));
00255             return RPMERR_BADSPEC;
00256         }
00257         spec->lineNum = ofi->lineNum = 0;
00258     }
00259     /*@=branchstate@*/
00260 
00261     /* Make sure we have something in the read buffer */
00262     if (!(ofi->readPtr && *(ofi->readPtr))) {
00263         /*@-type@*/ /* FIX: cast? */
00264         FILE * f = fdGetFp(ofi->fd);
00265         /*@=type@*/
00266         if (f == NULL || !fgets(ofi->readBuf, BUFSIZ, f)) {
00267             /* EOF */
00268             if (spec->readStack->next) {
00269                 rpmError(RPMERR_UNMATCHEDIF, _("Unclosed %%if\n"));
00270                 return RPMERR_UNMATCHEDIF;
00271             }
00272 
00273             /* remove this file from the stack */
00274             spec->fileStack = ofi->next;
00275             (void) Fclose(ofi->fd);
00276             ofi->fileName = _free(ofi->fileName);
00277             ofi = _free(ofi);
00278 
00279             /* only on last file do we signal EOF to caller */
00280             ofi = spec->fileStack;
00281             if (ofi == NULL)
00282                 return 1;
00283 
00284             /* otherwise, go back and try the read again. */
00285             goto retry;
00286         }
00287         ofi->readPtr = ofi->readBuf;
00288         ofi->lineNum++;
00289         spec->lineNum = ofi->lineNum;
00290         if (spec->sl) {
00291             speclines sl = spec->sl;
00292             if (sl->sl_nlines == sl->sl_nalloc) {
00293                 sl->sl_nalloc += 100;
00294                 sl->sl_lines = (char **) xrealloc(sl->sl_lines, 
00295                         sl->sl_nalloc * sizeof(*(sl->sl_lines)));
00296             }
00297             sl->sl_lines[sl->sl_nlines++] = xstrdup(ofi->readBuf);
00298         }
00299     }
00300     
00301 #ifdef  DYING
00302     arch = NULL;
00303     rpmGetArchInfo(&arch, NULL);
00304     os = NULL;
00305     rpmGetOsInfo(&os, NULL);
00306 #endif
00307 
00308     /* Copy next file line into the spec line buffer */
00309     if ((rc = copyNextLine(spec, ofi, strip)) != 0) {
00310         if (rc == RPMERR_UNMATCHEDIF)
00311             goto retry;
00312         return rc;
00313     }
00314 
00315     s = spec->line;
00316     SKIPSPACE(s);
00317 
00318     match = -1;
00319     if (!spec->readStack->reading && !strncmp("%if", s, sizeof("%if")-1)) {
00320         match = 0;
00321     } else if (! strncmp("%ifarch", s, sizeof("%ifarch")-1)) {
00322         const char *arch = rpmExpand("%{_target_cpu}", NULL);
00323         s += 7;
00324         match = matchTok(arch, s);
00325         arch = _free(arch);
00326     } else if (! strncmp("%ifnarch", s, sizeof("%ifnarch")-1)) {
00327         const char *arch = rpmExpand("%{_target_cpu}", NULL);
00328         s += 8;
00329         match = !matchTok(arch, s);
00330         arch = _free(arch);
00331     } else if (! strncmp("%ifos", s, sizeof("%ifos")-1)) {
00332         const char *os = rpmExpand("%{_target_os}", NULL);
00333         s += 5;
00334         match = matchTok(os, s);
00335         os = _free(os);
00336     } else if (! strncmp("%ifnos", s, sizeof("%ifnos")-1)) {
00337         const char *os = rpmExpand("%{_target_os}", NULL);
00338         s += 6;
00339         match = !matchTok(os, s);
00340         os = _free(os);
00341     } else if (! strncmp("%if", s, sizeof("%if")-1)) {
00342         s += 3;
00343         match = parseExpressionBoolean(spec, s);
00344         if (match < 0) {
00345             rpmError(RPMERR_UNMATCHEDIF,
00346                         _("%s:%d: parseExpressionBoolean returns %d\n"),
00347                         ofi->fileName, ofi->lineNum, match);
00348             return RPMERR_BADSPEC;
00349         }
00350     } else if (! strncmp("%else", s, sizeof("%else")-1)) {
00351         s += 5;
00352         if (! spec->readStack->next) {
00353             /* Got an else with no %if ! */
00354             rpmError(RPMERR_UNMATCHEDIF,
00355                         _("%s:%d: Got a %%else with no %%if\n"),
00356                         ofi->fileName, ofi->lineNum);
00357             return RPMERR_UNMATCHEDIF;
00358         }
00359         spec->readStack->reading =
00360             spec->readStack->next->reading && ! spec->readStack->reading;
00361         spec->line[0] = '\0';
00362     } else if (! strncmp("%endif", s, sizeof("%endif")-1)) {
00363         s += 6;
00364         if (! spec->readStack->next) {
00365             /* Got an end with no %if ! */
00366             rpmError(RPMERR_UNMATCHEDIF,
00367                         _("%s:%d: Got a %%endif with no %%if\n"),
00368                         ofi->fileName, ofi->lineNum);
00369             return RPMERR_UNMATCHEDIF;
00370         }
00371         rl = spec->readStack;
00372         spec->readStack = spec->readStack->next;
00373         free(rl);
00374         spec->line[0] = '\0';
00375     } else if (! strncmp("%include", s, sizeof("%include")-1)) {
00376         char *fileName, *endFileName, *p;
00377 
00378         s += 8;
00379         fileName = s;
00380         if (! xisspace(*fileName)) {
00381             rpmError(RPMERR_BADSPEC, _("malformed %%include statement\n"));
00382             return RPMERR_BADSPEC;
00383         }
00384         SKIPSPACE(fileName);
00385         endFileName = fileName;
00386         SKIPNONSPACE(endFileName);
00387         p = endFileName;
00388         SKIPSPACE(p);
00389         if (*p != '\0') {
00390             rpmError(RPMERR_BADSPEC, _("malformed %%include statement\n"));
00391             return RPMERR_BADSPEC;
00392         }
00393         *endFileName = '\0';
00394 
00395         forceIncludeFile(spec, fileName);
00396 
00397         ofi = spec->fileStack;
00398         goto retry;
00399     }
00400 
00401     if (match != -1) {
00402         rl = xmalloc(sizeof(*rl));
00403         rl->reading = spec->readStack->reading && match;
00404         rl->next = spec->readStack;
00405         spec->readStack = rl;
00406         spec->line[0] = '\0';
00407     }
00408 
00409     if (! spec->readStack->reading) {
00410         spec->line[0] = '\0';
00411     }
00412 
00413     /*@-compmempass@*/ /* FIX: spec->readStack->next should be dependent */
00414     return 0;
00415     /*@=compmempass@*/
00416 }
00417 /*@=boundswrite@*/
00418 
00419 void closeSpec(Spec spec)
00420 {
00421     OFI_t *ofi;
00422 
00423     while (spec->fileStack) {
00424         ofi = spec->fileStack;
00425         spec->fileStack = spec->fileStack->next;
00426         if (ofi->fd) (void) Fclose(ofi->fd);
00427         ofi->fileName = _free(ofi->fileName);
00428         ofi = _free(ofi);
00429     }
00430 }
00431 
00432 /*@-redecl@*/
00433 /*@unchecked@*/
00434 extern int noLang;              /* XXX FIXME: pass as arg */
00435 /*@=redecl@*/
00436 
00437 /*@todo Skip parse recursion if os is not compatible. @*/
00438 /*@-boundswrite@*/
00439 int parseSpec(rpmts ts, const char *specFile, const char *rootURL,
00440                 const char *buildRootURL, int recursing, const char *passPhrase,
00441                 char *cookie, int anyarch, int force)
00442 {
00443     rpmParseState parsePart = PART_PREAMBLE;
00444     int initialPackage = 1;
00445 #ifdef  DYING
00446     const char *saveArch;
00447 #endif
00448     Package pkg;
00449     Spec spec;
00450     
00451     /* Set up a new Spec structure with no packages. */
00452     spec = newSpec();
00453 
00454     /*
00455      * Note: rpmGetPath should guarantee a "canonical" path. That means
00456      * that the following pathologies should be weeded out:
00457      *          //bin//sh
00458      *          //usr//bin/
00459      *          /.././../usr/../bin//./sh (XXX FIXME: dots not handled yet)
00460      */
00461     spec->specFile = rpmGetPath(specFile, NULL);
00462     spec->fileStack = newOpenFileInfo();
00463     spec->fileStack->fileName = xstrdup(spec->specFile);
00464     if (buildRootURL) {
00465         const char * buildRoot;
00466         (void) urlPath(buildRootURL, &buildRoot);
00467         /*@-branchstate@*/
00468         if (*buildRoot == '\0') buildRoot = "/";
00469         /*@=branchstate@*/
00470         if (!strcmp(buildRoot, "/")) {
00471             rpmError(RPMERR_BADSPEC,
00472                      _("BuildRoot can not be \"/\": %s\n"), buildRootURL);
00473             return RPMERR_BADSPEC;
00474         }
00475         spec->gotBuildRootURL = 1;
00476         spec->buildRootURL = xstrdup(buildRootURL);
00477         addMacro(spec->macros, "buildroot", NULL, buildRoot, RMIL_SPEC);
00478     }
00479     addMacro(NULL, "_docdir", NULL, "%{_defaultdocdir}", RMIL_SPEC);
00480     spec->recursing = recursing;
00481     spec->anyarch = anyarch;
00482     spec->force = force;
00483 
00484     if (rootURL)
00485         spec->rootURL = xstrdup(rootURL);
00486     if (passPhrase)
00487         spec->passPhrase = xstrdup(passPhrase);
00488     if (cookie)
00489         spec->cookie = xstrdup(cookie);
00490 
00491     spec->timeCheck = rpmExpandNumeric("%{_timecheck}");
00492 
00493     /* All the parse*() functions expect to have a line pre-read */
00494     /* in the spec's line buffer.  Except for parsePreamble(),   */
00495     /* which handles the initial entry into a spec file.         */
00496     
00497     /*@-infloops@*/     /* LCL: parsePart is modified @*/
00498     while (parsePart < PART_LAST && parsePart != PART_NONE) {
00499         switch (parsePart) {
00500         case PART_PREAMBLE:
00501             parsePart = parsePreamble(spec, initialPackage);
00502             initialPackage = 0;
00503             /*@switchbreak@*/ break;
00504         case PART_PREP:
00505             parsePart = parsePrep(spec);
00506             /*@switchbreak@*/ break;
00507         case PART_BUILD:
00508         case PART_INSTALL:
00509         case PART_CHECK:
00510         case PART_CLEAN:
00511             parsePart = parseBuildInstallClean(spec, parsePart);
00512             /*@switchbreak@*/ break;
00513         case PART_CHANGELOG:
00514             parsePart = parseChangelog(spec);
00515             /*@switchbreak@*/ break;
00516         case PART_DESCRIPTION:
00517             parsePart = parseDescription(spec);
00518             /*@switchbreak@*/ break;
00519 
00520         case PART_PRE:
00521         case PART_POST:
00522         case PART_PREUN:
00523         case PART_POSTUN:
00524         case PART_PRETRANS:
00525         case PART_POSTTRANS:
00526         case PART_VERIFYSCRIPT:
00527         case PART_TRIGGERIN:
00528         case PART_TRIGGERUN:
00529         case PART_TRIGGERPOSTUN:
00530             parsePart = parseScript(spec, parsePart);
00531             /*@switchbreak@*/ break;
00532 
00533         case PART_FILES:
00534             parsePart = parseFiles(spec);
00535             /*@switchbreak@*/ break;
00536 
00537         case PART_NONE:         /* XXX avoid gcc whining */
00538         case PART_LAST:
00539         case PART_BUILDARCHITECTURES:
00540             /*@switchbreak@*/ break;
00541         }
00542 
00543         if (parsePart >= PART_LAST) {
00544             spec = freeSpec(spec);
00545             return parsePart;
00546         }
00547 
00548         if (parsePart == PART_BUILDARCHITECTURES) {
00549             int index;
00550             int x;
00551 
00552             closeSpec(spec);
00553 
00554             /* LCL: sizeof(spec->BASpecs[0]) -nullderef whine here */
00555             spec->BASpecs = xcalloc(spec->BACount, sizeof(*spec->BASpecs));
00556             index = 0;
00557             if (spec->BANames != NULL)
00558             for (x = 0; x < spec->BACount; x++) {
00559 
00560                 /* Skip if not arch is not compatible. */
00561                 if (!rpmMachineScore(RPM_MACHTABLE_BUILDARCH, spec->BANames[x]))
00562                     /*@innercontinue@*/ continue;
00563 #ifdef  DYING
00564                 rpmGetMachine(&saveArch, NULL);
00565                 saveArch = xstrdup(saveArch);
00566                 rpmSetMachine(spec->BANames[x], NULL);
00567 #else
00568                 addMacro(NULL, "_target_cpu", NULL, spec->BANames[x], RMIL_RPMRC);
00569 #endif
00570                 spec->BASpecs[index] = NULL;
00571                 if (parseSpec(ts, specFile, spec->rootURL, buildRootURL, 1,
00572                                   passPhrase, cookie, anyarch, force)
00573                  || (spec->BASpecs[index] = rpmtsSetSpec(ts, NULL)) == NULL)
00574                 {
00575                         spec->BACount = index;
00576 /*@-nullstate@*/
00577                         spec = freeSpec(spec);
00578                         return RPMERR_BADSPEC;
00579 /*@=nullstate@*/
00580                 }
00581 #ifdef  DYING
00582                 rpmSetMachine(saveArch, NULL);
00583                 saveArch = _free(saveArch);
00584 #else
00585                 delMacro(NULL, "_target_cpu");
00586 #endif
00587                 index++;
00588             }
00589 
00590             spec->BACount = index;
00591             if (! index) {
00592                 rpmError(RPMERR_BADSPEC,
00593                         _("No compatible architectures found for build\n"));
00594 /*@-nullstate@*/
00595                 spec = freeSpec(spec);
00596                 return RPMERR_BADSPEC;
00597 /*@=nullstate@*/
00598             }
00599 
00600             /*
00601              * Return the 1st child's fully parsed Spec structure.
00602              * The restart of the parse when encountering BuildArch
00603              * causes problems for "rpm -q --specfile". This is
00604              * still a hack because there may be more than 1 arch
00605              * specified (unlikely but possible.) There's also the
00606              * further problem that the macro context, particularly
00607              * %{_target_cpu}, disagrees with the info in the header.
00608              */
00609             /*@-branchstate@*/
00610             if (spec->BACount >= 1) {
00611                 Spec nspec = spec->BASpecs[0];
00612                 spec->BASpecs = _free(spec->BASpecs);
00613                 spec = freeSpec(spec);
00614                 spec = nspec;
00615             }
00616             /*@=branchstate@*/
00617 
00618             (void) rpmtsSetSpec(ts, spec);
00619             return 0;
00620         }
00621     }
00622     /*@=infloops@*/     /* LCL: parsePart is modified @*/
00623 
00624     /* Check for description in each package and add arch and os */
00625   {
00626 #ifdef  DYING
00627     const char *arch = NULL;
00628     const char *os = NULL;
00629     char *myos = NULL;
00630 
00631     rpmGetArchInfo(&arch, NULL);
00632     rpmGetOsInfo(&os, NULL);
00633     /*
00634      * XXX Capitalizing the 'L' is needed to insure that old
00635      * XXX os-from-uname (e.g. "Linux") is compatible with the new
00636      * XXX os-from-platform (e.g "linux" from "sparc-*-linux").
00637      * XXX A copy of this string is embedded in headers.
00638      */
00639     if (!strcmp(os, "linux")) {
00640         myos = xstrdup(os);
00641         *myos = 'L';
00642         os = myos;
00643     }
00644 #else
00645     const char *platform = rpmExpand("%{_target_platform}", NULL);
00646     const char *arch = rpmExpand("%{_target_cpu}", NULL);
00647     const char *os = rpmExpand("%{_target_os}", NULL);
00648 #endif
00649 
00650     for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) {
00651         if (!headerIsEntry(pkg->header, RPMTAG_DESCRIPTION)) {
00652             const char * name;
00653             (void) headerNVR(pkg->header, &name, NULL, NULL);
00654             rpmError(RPMERR_BADSPEC, _("Package has no %%description: %s\n"),
00655                         name);
00656             spec = freeSpec(spec);
00657             return RPMERR_BADSPEC;
00658         }
00659 
00660         (void) headerAddEntry(pkg->header, RPMTAG_OS, RPM_STRING_TYPE, os, 1);
00661         (void) headerAddEntry(pkg->header, RPMTAG_ARCH,
00662                 RPM_STRING_TYPE, arch, 1);
00663         if (!headerIsEntry(pkg->header, RPMTAG_RHNPLATFORM))
00664             (void) headerAddEntry(pkg->header, RPMTAG_RHNPLATFORM,
00665                 RPM_STRING_TYPE, arch, 1);
00666         (void) headerAddEntry(pkg->header, RPMTAG_PLATFORM,
00667                 RPM_STRING_TYPE, platform, 1);
00668 
00669         pkg->ds = rpmdsThis(pkg->header, RPMTAG_REQUIRENAME, RPMSENSE_EQUAL);
00670 
00671     }
00672 
00673 #ifdef  DYING
00674     myos = _free(myos);
00675 #else
00676     platform = _free(platform);
00677     arch = _free(arch);
00678     os = _free(os);
00679 #endif
00680   }
00681 
00682     closeSpec(spec);
00683     (void) rpmtsSetSpec(ts, spec);
00684 
00685     return 0;
00686 }
00687 /*@=boundswrite@*/

Generated on Fri Oct 12 08:44:53 2007 for rpm by  doxygen 1.5.2