• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

build/parseSpec.c

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

Generated on Mon Nov 29 2010 05:18:42 for rpm by  doxygen 1.7.2