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

build/parsePreamble.c

Go to the documentation of this file.
00001 
00006 #include "system.h"
00007 
00008 #include <rpmio.h>
00009 #include <rpmiotypes.h>
00010 #include <rpmlog.h>
00011 #include <rpmurl.h>
00012 #include <argv.h>
00013 #include <mire.h>
00014 
00015 #define _RPMEVR_INTERNAL
00016 #define _RPMTAG_INTERNAL        /* XXX rpmTags->aTags */
00017 #include <rpmbuild.h>
00018 #include "debug.h"
00019 
00020 /*@access FD_t @*/      /* compared with NULL */
00021 /*@access headerTagIndices @*/  /* rpmTags->aTags */
00022 
00025 /*@observer@*/ /*@unchecked@*/
00026 static rpmTag copyTagsDuringParse[] = {
00027     RPMTAG_EPOCH,
00028     RPMTAG_VERSION,
00029     RPMTAG_RELEASE,
00030     RPMTAG_DISTEPOCH,
00031     RPMTAG_LICENSE,
00032     RPMTAG_GROUP,               /* XXX permissive. */
00033     RPMTAG_SUMMARY,             /* XXX permissive. */
00034     RPMTAG_DESCRIPTION,         /* XXX permissive. */
00035     RPMTAG_PACKAGER,
00036     RPMTAG_DISTRIBUTION,
00037     RPMTAG_DISTURL,
00038     RPMTAG_VENDOR,
00039     RPMTAG_ICON,
00040     RPMTAG_GIF,
00041     RPMTAG_XPM,
00042     RPMTAG_URL,
00043     RPMTAG_CHANGELOGTIME,
00044     RPMTAG_CHANGELOGNAME,
00045     RPMTAG_CHANGELOGTEXT,
00046     RPMTAG_PREFIXES,
00047     RPMTAG_DISTTAG,
00048     RPMTAG_CVSID,
00049     RPMTAG_VARIANTS,
00050     RPMTAG_XMAJOR,
00051     RPMTAG_XMINOR,
00052     RPMTAG_REPOTAG,
00053     RPMTAG_KEYWORDS,
00054     0
00055 };
00056 
00059 /*@observer@*/ /*@unchecked@*/
00060 static rpmTag requiredTags[] = {
00061     RPMTAG_NAME,
00062     RPMTAG_VERSION,
00063     RPMTAG_RELEASE,
00064     RPMTAG_SUMMARY,
00065     RPMTAG_GROUP,
00066     RPMTAG_LICENSE,
00067     0
00068 };
00069 
00072 static void addOrAppendListEntry(Header h, rpmTag tag, char * line)
00073         /*@modifies h @*/
00074 {
00075     HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
00076     int xx;
00077     int argc;
00078     const char **argv;
00079 
00080     xx = poptParseArgvString(line, &argc, &argv);
00081     if (argc) {
00082         he->tag = tag;
00083         he->t = RPM_STRING_ARRAY_TYPE;
00084         he->p.argv = argv;
00085         he->c = argc;
00086         he->append = 1;
00087         xx = headerPut(h, he, 0);
00088         he->append = 0;
00089     }
00090     argv = _free(argv);
00091 }
00092 
00093 /* Parse a simple part line that only take -n <pkg> or <pkg> */
00094 /* <pkg> is returned in name as a pointer into malloc'd storage. */
00095 
00098 static int parseSimplePart(Spec spec, /*@out@*/char ** Np,
00099                 /*@out@*/rpmParseState *flag)
00100         /*@globals internalState@*/
00101         /*@modifies *Np, *flag, internalState, spec->line @*/
00102 {
00103     char * s, * se;
00104     int rc = 0;         /* assume failure */
00105 
00106     if (Np)
00107         *Np = NULL;
00108 
00109     se = strchr(spec->line, '#');
00110     if (se) {
00111         *se = '\0';
00112         while (--se >= spec->line && strchr(" \t\n\r", *se) != NULL)
00113             *se = '\0';
00114     }
00115 
00116     s = xstrdup(spec->line);
00117     /* Throw away the first token (the %xxxx) */
00118     (void)strtok(s, " \t\n");
00119     
00120     if (!(se = strtok(NULL, " \t\n")))
00121         goto exit;
00122     
00123     if (!strcmp(se, "-n")) {
00124         if (!(se = strtok(NULL, " \t\n"))) {
00125             rc = 1;
00126             goto exit;
00127         }
00128         *flag = PART_NAME;
00129     } else
00130         *flag = PART_SUBNAME;
00131 
00132     if (Np)
00133         *Np = xstrdup(se);
00134 
00135     rc = (strtok(NULL, " \t\n") ? 1 : 0);
00136 
00137 exit:
00138     s = _free(s);
00139     return rc;
00140 }
00141 
00144 static inline int parseYesNo(const char * s)
00145         /*@*/
00146 {
00147     return ((!s || (s[0] == 'n' || s[0] == 'N' || s[0] == '0') ||
00148         !xstrcasecmp(s, "false") || !xstrcasecmp(s, "off"))
00149             ? 0 : 1);
00150 }
00151 
00152 typedef struct tokenBits_s {
00153 /*@observer@*/ /*@null@*/
00154     const char * name;
00155     rpmsenseFlags bits;
00156 } * tokenBits;
00157 
00160 /*@observer@*/ /*@unchecked@*/
00161 static struct tokenBits_s installScriptBits[] = {
00162     { "interp",         RPMSENSE_INTERP },
00163     { "preun",          RPMSENSE_SCRIPT_PREUN },
00164     { "pre",            RPMSENSE_SCRIPT_PRE },
00165     { "postun",         RPMSENSE_SCRIPT_POSTUN },
00166     { "post",           RPMSENSE_SCRIPT_POST },
00167     { "rpmlib",         RPMSENSE_RPMLIB },
00168     { "verify",         RPMSENSE_SCRIPT_VERIFY },
00169     { "hint",           RPMSENSE_MISSINGOK },
00170     { NULL, 0 }
00171 };
00172 
00175 /*@observer@*/ /*@unchecked@*/
00176 static struct tokenBits_s buildScriptBits[] = {
00177     { "prep",           RPMSENSE_SCRIPT_PREP },
00178     { "build",          RPMSENSE_SCRIPT_BUILD },
00179     { "install",        RPMSENSE_SCRIPT_INSTALL },
00180     { "clean",          RPMSENSE_SCRIPT_CLEAN },
00181     { "hint",           RPMSENSE_MISSINGOK },
00182     { NULL, 0 }
00183 };
00184 
00187 static int parseBits(const char * s, const tokenBits tokbits,
00188                 /*@out@*/ rpmsenseFlags * bp)
00189         /*@modifies *bp @*/
00190 {
00191     tokenBits tb;
00192     const char * se;
00193     rpmsenseFlags bits = RPMSENSE_ANY;
00194     int c = 0;
00195 
00196     if (s) {
00197         while (*s != '\0') {
00198             while ((c = *s) && xisspace(c)) s++;
00199             se = s;
00200             while ((c = *se) && xisalpha(c)) se++;
00201             if (s == se)
00202                 break;
00203             for (tb = tokbits; tb->name; tb++) {
00204                 if (tb->name != NULL &&
00205                     strlen(tb->name) == (size_t)(se-s) && !strncmp(tb->name, s, (se-s)))
00206                     /*@innerbreak@*/ break;
00207             }
00208             if (tb->name == NULL)
00209                 break;
00210             bits |= tb->bits;
00211             while ((c = *se) && xisspace(c)) se++;
00212             if (c != ',')
00213                 break;
00214             s = ++se;
00215         }
00216     }
00217     if (c == 0 && bp) *bp = bits;
00218     return (c ? RPMRC_FAIL : RPMRC_OK);
00219 }
00220 
00223 /*@null@*/
00224 static inline char * findLastChar(char * s)
00225         /*@modifies *s @*/
00226 {
00227     char *se = s + strlen(s);
00228 
00229     /* Right trim white space. */
00230     while (--se > s && strchr(" \t\n\r", *se) != NULL)
00231         *se = '\0';
00232     /* Truncate comments. */
00233     if ((se = strchr(s, '#')) != NULL) {
00234         *se = '\0';
00235         while (--se > s && strchr(" \t\n\r", *se) != NULL)
00236             *se = '\0';
00237     }
00238 /*@-temptrans -retalias @*/
00239     return se;
00240 /*@=temptrans =retalias @*/
00241 }
00242 
00245 static int isMemberInEntry(Header h, const char *name, rpmTag tag)
00246         /*@globals internalState @*/
00247         /*@modifies internalState @*/
00248 {
00249     HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
00250     int rc = -1;
00251     int xx;
00252 
00253     he->tag = tag;
00254     xx = headerGet(h, he, 0);
00255     if (!xx)
00256         return rc;
00257     rc = 0;
00258     while (he->c) {
00259         he->c--;
00260         if (xstrcasecmp(he->p.argv[he->c], name))
00261             continue;
00262         rc = 1;
00263         break;
00264     }
00265     he->p.ptr = _free(he->p.ptr);
00266     return rc;
00267 }
00268 
00271 static int checkForValidArchitectures(Spec spec)
00272         /*@globals rpmGlobalMacroContext, h_errno, internalState @*/
00273         /*@modifies rpmGlobalMacroContext, internalState @*/
00274 {
00275     const char *arch = rpmExpand("%{_target_cpu}", NULL);
00276     const char *os = rpmExpand("%{_target_os}", NULL);
00277     int rc = RPMRC_FAIL;        /* assume failure. */
00278     
00279     if (isMemberInEntry(spec->sourceHeader, arch, RPMTAG_EXCLUDEARCH) == 1) {
00280         rpmlog(RPMLOG_ERR, _("Architecture is excluded: %s\n"), arch);
00281         goto exit;
00282     }
00283     if (isMemberInEntry(spec->sourceHeader, arch, RPMTAG_EXCLUSIVEARCH) == 0) {
00284         rpmlog(RPMLOG_ERR, _("Architecture is not included: %s\n"), arch);
00285         goto exit;
00286     }
00287     if (isMemberInEntry(spec->sourceHeader, os, RPMTAG_EXCLUDEOS) == 1) {
00288         rpmlog(RPMLOG_ERR, _("OS is excluded: %s\n"), os);
00289         goto exit;
00290     }
00291     if (isMemberInEntry(spec->sourceHeader, os, RPMTAG_EXCLUSIVEOS) == 0) {
00292         rpmlog(RPMLOG_ERR, _("OS is not included: %s\n"), os);
00293         goto exit;
00294     }
00295     rc = 0;
00296 exit:
00297     arch = _free(arch);
00298     os = _free(os);
00299     return rc;
00300 }
00301 
00308 static rpmRC checkForRequired(Header h, const char * NVR)
00309         /*@*/
00310 {
00311     rpmTag * p;
00312     rpmRC rc = RPMRC_OK;
00313 
00314     for (p = requiredTags; *p != 0; p++) {
00315         if (!headerIsEntry(h, *p)) {
00316             rpmlog(RPMLOG_ERR,
00317                         _("%s field must be present in package: %s\n"),
00318                         tagName(*p), NVR);
00319             rc = RPMRC_FAIL;
00320         }
00321     }
00322 
00323     return rc;
00324 }
00325 
00332 static rpmRC checkForDuplicates(Header h, const char * NVR)
00333         /*@globals internalState @*/
00334         /*@modifies h, internalState @*/
00335 {
00336     HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
00337     HeaderIterator hi;
00338     rpmTag lastTag = 0;
00339     rpmRC rc = RPMRC_OK;
00340     
00341     for (hi = headerInit(h);
00342         headerNext(hi, he, 0);
00343         he->p.ptr = _free(he->p.ptr))
00344     {
00345         if (he->tag != lastTag) {
00346             lastTag = he->tag;
00347             continue;
00348         }
00349         rpmlog(RPMLOG_ERR, _("Duplicate %s entries in package: %s\n"),
00350                      tagName(he->tag), NVR);
00351         rc = RPMRC_FAIL;
00352     }
00353     hi = headerFini(hi);
00354 
00355     return rc;
00356 }
00357 
00360 /*@observer@*/ /*@unchecked@*/
00361 static struct optionalTag {
00362     rpmTag      ot_tag;
00363 /*@observer@*/ /*@null@*/
00364     const char * ot_mac;
00365 } optionalTags[] = {
00366     { RPMTAG_VENDOR,            "%{vendor}" },
00367     { RPMTAG_PACKAGER,          "%{packager}" },
00368     { RPMTAG_DISTEPOCH,         "%{distepoch}" },
00369     { RPMTAG_DISTRIBUTION,      "%{distribution}" },
00370     { RPMTAG_DISTTAG,           "%{disttag}" },
00371     { RPMTAG_DISTURL,           "%{disturl}" },
00372     { 0xffffffff,               "%{class}" },
00373     { -1, NULL }
00374 };
00375 
00378 static void fillOutMainPackage(Header h)
00379         /*@globals rpmGlobalMacroContext, h_errno, internalState @*/
00380         /*@modifies h, rpmGlobalMacroContext, internalState @*/
00381 {
00382     HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
00383     struct optionalTag *ot;
00384     int xx;
00385 
00386     for (ot = optionalTags; ot->ot_mac != NULL; ot++) {
00387         const char * val;
00388         rpmTag tag;
00389 
00390         tag = ot->ot_tag;
00391 
00392         /* Generate arbitrary tag (if necessary). */
00393         if (tag == 0xffffffff) {
00394             val = tagCanonicalize(ot->ot_mac + (sizeof("%{")-1));
00395             tag = tagGenerate(val);
00396             val = _free(val);
00397         }
00398 
00399         if (headerIsEntry(h, tag))
00400             continue;
00401         val = rpmExpand(ot->ot_mac, NULL);
00402         if (val && *val != '%') {
00403                 he->tag = tag;
00404                 he->t = RPM_STRING_TYPE;
00405                 he->p.str = val;
00406                 he->c = 1;
00407                 xx = headerPut(h, he, 0);
00408         }
00409         val = _free(val);
00410     }
00411 }
00412 
00415 static int doIcon(Spec spec, Header h)
00416         /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
00417         /*@modifies h, rpmGlobalMacroContext, fileSystem, internalState  @*/
00418 {
00419     static size_t iconsize = 0;
00420     HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
00421     const char *fn, *Lurlfn = NULL;
00422     struct Source *sp;
00423     size_t nb;
00424     rpmuint8_t * icon;
00425     FD_t fd = NULL;
00426     int rc = RPMRC_FAIL;        /* assume error */
00427     int urltype;
00428     int xx;
00429 
00430     if (iconsize == 0) {
00431         iconsize = rpmExpandNumeric("%{?_build_iconsize}");
00432         if (iconsize < 2048)
00433             iconsize = 2048;
00434     }
00435     icon = alloca(iconsize+1);
00436 
00437     for (sp = spec->sources; sp != NULL; sp = sp->next) {
00438         if (sp->flags & RPMFILE_ICON)
00439             break;
00440     }
00441     if (sp == NULL) {
00442         rpmlog(RPMLOG_ERR, _("No icon file in sources\n"));
00443         goto exit;
00444     }
00445 
00446 #if defined(RPM_VENDOR_OPENPKG) /* splitted-source-directory */
00447     /* support splitted source directories, i.e., source files which
00448        are alternatively placed into the .spec directory and picked
00449        up from there, too. */
00450     Lurlfn = rpmGenPath(NULL, "%{_specdir}/", sp->source);
00451     if (access(Lurlfn, F_OK) == -1) {
00452         Lurlfn = _free(Lurlfn);
00453         Lurlfn = rpmGenPath(NULL, "%{_icondir}/", sp->source);
00454     }
00455 #else
00456     Lurlfn = rpmGenPath(NULL, "%{_icondir}/", sp->source);
00457 #endif
00458 
00459     fn = NULL;
00460     urltype = urlPath(Lurlfn, &fn);
00461     switch (urltype) {  
00462     case URL_IS_HTTPS: 
00463     case URL_IS_HTTP:
00464     case URL_IS_FTP:
00465     case URL_IS_PATH:
00466     case URL_IS_UNKNOWN:
00467         break;
00468     case URL_IS_DASH:
00469     case URL_IS_HKP:
00470         rpmlog(RPMLOG_ERR, _("Invalid icon URL: %s\n"), Lurlfn);
00471         goto exit;
00472         /*@notreached@*/ break;
00473     }
00474 
00475     fd = Fopen(fn, "r%{?_rpmgio}");
00476     if (fd == NULL || Ferror(fd)) {
00477         rpmlog(RPMLOG_ERR, _("Unable to open icon %s: %s\n"),
00478                 fn, Fstrerror(fd));
00479         rc = RPMRC_FAIL;
00480         goto exit;
00481     }
00482 
00483     *icon = '\0';
00484     nb = Fread(icon, sizeof(icon[0]), iconsize, fd);
00485     if (Ferror(fd) || nb == 0) {
00486         rpmlog(RPMLOG_ERR, _("Unable to read icon %s: %s\n"),
00487                 fn, Fstrerror(fd));
00488         goto exit;
00489     }
00490     if (nb >= iconsize) {
00491         rpmlog(RPMLOG_ERR, _("Icon %s is too big (max. %d bytes)\n"),
00492                 fn, (int)iconsize);
00493         goto exit;
00494     }
00495 
00496     if (icon[0] == 'G' && icon[1] == 'I' && icon[2] == 'F')
00497         he->tag = RPMTAG_GIF;
00498     else
00499     if (icon[0] == '/' && icon[1] == '*' && icon[2] == ' '
00500      && icon[3] == 'X' && icon[4] == 'P' && icon[5] == 'M')
00501         he->tag = RPMTAG_XPM;
00502     else
00503         he->tag = tagValue("Icon");
00504     he->t = RPM_BIN_TYPE;
00505     he->p.ui8p = icon;
00506     he->c = (rpmTagCount)nb;
00507     xx = headerPut(h, he, 0);
00508     rc = 0;
00509     
00510 exit:
00511     if (fd) {
00512         (void) Fclose(fd);
00513         fd = NULL;
00514     }
00515     Lurlfn = _free(Lurlfn);
00516     return rc;
00517 }
00518 
00519 spectag stashSt(Spec spec, Header h, rpmTag tag, const char * lang)
00520 {
00521     HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
00522     spectag t = NULL;
00523     int xx;
00524 
00525     if (spec->st) {
00526         spectags st = spec->st;
00527         if (st->st_ntags == st->st_nalloc) {
00528             st->st_nalloc += 10;
00529             st->st_t = xrealloc(st->st_t, st->st_nalloc * sizeof(*(st->st_t)));
00530         }
00531         t = st->st_t + st->st_ntags++;
00532         t->t_tag = tag;
00533         t->t_startx = spec->lineNum - 1;
00534         t->t_nlines = 1;
00535         t->t_lang = xstrdup(lang);
00536         t->t_msgid = NULL;
00537         if (!(t->t_lang && strcmp(t->t_lang, RPMBUILD_DEFAULT_LANG))) {
00538             he->tag = RPMTAG_NAME;
00539             xx = headerGet(h, he, 0);
00540             if (xx) {
00541                 char buf[1024];
00542                 sprintf(buf, "%s(%s)", he->p.str, tagName(tag));
00543                 t->t_msgid = xstrdup(buf);
00544             }
00545             he->p.ptr = _free(he->p.ptr);
00546         }
00547     }
00548     /*@-usereleased -compdef@*/
00549     return t;
00550     /*@=usereleased =compdef@*/
00551 }
00552 
00553 #define SINGLE_TOKEN_ONLY \
00554 if (multiToken) { \
00555     rpmlog(RPMLOG_ERR, _("line %d: Tag takes single token only: %s\n"), \
00556              spec->lineNum, spec->line); \
00557     return RPMRC_FAIL; \
00558 }
00559 
00560 /*@-redecl@*/
00561 extern int noLang;
00562 /*@=redecl@*/
00563 
00564 static rpmRC tagValidate(Spec spec, rpmTag tag, const char * value)
00565         /*@*/
00566 {
00567     const char * tagN = tagName(tag);
00568     const char * pattern = rpmExpand("%{?pattern_", tagN, "}", NULL);
00569     rpmRC ec = RPMRC_OK;
00570 
00571     if (pattern && *pattern) {
00572         miRE mire;
00573         int xx;
00574 
00575         mire = mireNew(RPMMIRE_REGEX, tag);
00576         xx = mireSetCOptions(mire, RPMMIRE_REGEX, 0, 0, NULL);
00577         if (!xx)
00578             xx = mireRegcomp(mire, pattern);
00579         if (!xx)
00580             xx = mireRegexec(mire, value, strlen(value));
00581         if (!xx)
00582             ec = RPMRC_OK;
00583         else {
00584             rpmlog(RPMLOG_ERR, _("line %d: invalid tag value(\"%s\") %s: %s\n"),
00585                     spec->lineNum, pattern, tagN, spec->line);
00586             ec = RPMRC_FAIL;
00587         }
00588 
00589         mire = mireFree(mire);
00590     }
00591 
00592     pattern = _free(pattern);
00593 
00594     return ec;
00595 }
00596 
00599 static rpmRC handlePreambleTag(Spec spec, Package pkg, rpmTag tag,
00600                 const char *macro, const char *lang)
00601         /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
00602         /*@modifies spec->macros, spec->st,
00603                 spec->sources, spec->numSources, spec->noSource,
00604                 spec->sourceHeader, spec->BANames, spec->BACount,
00605                 spec->line,
00606                 pkg->header, pkg->autoProv, pkg->autoReq, pkg->noarch,
00607                 rpmGlobalMacroContext, fileSystem, internalState @*/
00608 {
00609     HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
00610     char * field = spec->line;
00611     char * end;
00612     int multiToken = 0;
00613     rpmsenseFlags tagflags;
00614     int len;
00615     rpmuint32_t num;
00616     int rc;
00617     int xx;
00618 #if defined(RPM_VENDOR_MANDRIVA) /* build-expand-field-for-single-token */
00619     char * expand_field = NULL;
00620 #endif
00621     
00622     if (field == NULL) return RPMRC_FAIL;       /* XXX can't happen */
00623     /* Find the start of the "field" and strip trailing space */
00624     while ((*field) && (*field != ':'))
00625         field++;
00626     if (*field != ':') {
00627         rpmlog(RPMLOG_ERR, _("line %d: Malformed tag: %s\n"),
00628                  spec->lineNum, spec->line);
00629         return RPMRC_FAIL;
00630     }
00631     field++;
00632     SKIPSPACE(field);
00633     if (!*field) {
00634         /* Empty field */
00635         rpmlog(RPMLOG_ERR, _("line %d: Empty tag: %s\n"),
00636                  spec->lineNum, spec->line);
00637         return RPMRC_FAIL;
00638     }
00639 #if defined(RPM_VENDOR_MANDRIVA) /* build-expand-field-for-single-token */
00640     expand_field = rpmExpand(field, NULL);
00641 #else
00642     end = findLastChar(field);
00643 #endif    
00644 
00645     /* Validate tag data content. */
00646     if (tagValidate(spec, tag, field) != RPMRC_OK)
00647         return RPMRC_FAIL;
00648 
00649     /* See if this is multi-token */
00650 #if defined(RPM_VENDOR_MANDRIVA) /* build-expand-field-for-single-token */
00651     end = expand_field;
00652 #else
00653     end = field;
00654 #endif
00655     SKIPNONSPACE(end);
00656     if (*end != '\0')
00657         multiToken = 1;
00658 #if defined(RPM_VENDOR_MANDRIVA) /* build-expand-field-for-single-token */
00659     _free(expand_field);
00660 #endif
00661 
00662     switch (tag) {
00663     case RPMTAG_NAME:
00664     case RPMTAG_VERSION:
00665     case RPMTAG_RELEASE:
00666     case RPMTAG_DISTEPOCH:
00667     case RPMTAG_URL:
00668     case RPMTAG_DISTTAG:
00669     case RPMTAG_REPOTAG:
00670     case RPMTAG_CVSID:
00671         SINGLE_TOKEN_ONLY;
00672         /* These macros are for backward compatibility */
00673         if (tag == RPMTAG_VERSION) {
00674             if (strchr(field, '-') != NULL) {
00675                 rpmlog(RPMLOG_ERR, _("line %d: Illegal char '-' in %s: %s\n"),
00676                     spec->lineNum, "version", spec->line);
00677                 return RPMRC_FAIL;
00678             }
00679             addMacro(spec->macros, "PACKAGE_VERSION", NULL, field, RMIL_OLDSPEC);
00680         } else if (tag == RPMTAG_RELEASE) {
00681             if (strchr(field, '-') != NULL) {
00682                 rpmlog(RPMLOG_ERR, _("line %d: Illegal char '-' in %s: %s\n"),
00683                     spec->lineNum, "release", spec->line);
00684                 return RPMRC_FAIL;
00685             }
00686             addMacro(spec->macros, "PACKAGE_RELEASE", NULL, field, RMIL_OLDSPEC-1);
00687         }
00688         he->tag = tag;
00689         he->t = RPM_STRING_TYPE;
00690         he->p.str = field;
00691         he->c = 1;
00692         xx = headerPut(pkg->header, he, 0);
00693         break;
00694     case RPMTAG_GROUP:
00695     case RPMTAG_SUMMARY:
00696 #if defined(RPM_VENDOR_OPENPKG) /* make-class-available-as-macro */
00697     case RPMTAG_CLASS:
00698 #endif
00699         (void) stashSt(spec, pkg->header, tag, lang);
00700         /*@fallthrough@*/
00701     case RPMTAG_DISTRIBUTION:
00702     case RPMTAG_VENDOR:
00703     case RPMTAG_LICENSE:
00704     case RPMTAG_PACKAGER:
00705         if (!*lang) {
00706             he->tag = tag;
00707             he->t = RPM_STRING_TYPE;
00708             he->p.str = field;
00709             he->c = 1;
00710             xx = headerPut(pkg->header, he, 0);
00711         } else if (!(noLang && strcmp(lang, RPMBUILD_DEFAULT_LANG))) {
00712             (void) headerAddI18NString(pkg->header, tag, field, lang);
00713         }
00714         break;
00715     /* XXX silently ignore BuildRoot: */
00716     case RPMTAG_BUILDROOT:
00717         SINGLE_TOKEN_ONLY;
00718         macro = NULL;
00719 #ifdef  DYING
00720         buildRootURL = rpmGenPath(spec->rootURL, "%{?buildroot}", NULL);
00721         (void) urlPath(buildRootURL, &buildRoot);
00722         if (*buildRoot == '\0') buildRoot = "/";
00723         if (!strcmp(buildRoot, "/")) {
00724             rpmlog(RPMLOG_ERR,
00725                      _("BuildRoot can not be \"/\": %s\n"), spec->buildRootURL);
00726             buildRootURL = _free(buildRootURL);
00727             return RPMRC_FAIL;
00728         }
00729         buildRootURL = _free(buildRootURL);
00730 #endif
00731         break;
00732     case RPMTAG_KEYWORDS:
00733     case RPMTAG_VARIANTS:
00734     case RPMTAG_PREFIXES:
00735         addOrAppendListEntry(pkg->header, tag, field);
00736         he->tag = tag;
00737         xx = headerGet(pkg->header, he, 0);
00738         if (tag == RPMTAG_PREFIXES)
00739         while (he->c--) {
00740             if (he->p.argv[he->c][0] != '/') {
00741                 rpmlog(RPMLOG_ERR,
00742                          _("line %d: Prefixes must begin with \"/\": %s\n"),
00743                          spec->lineNum, spec->line);
00744                 he->p.ptr = _free(he->p.ptr);
00745                 return RPMRC_FAIL;
00746             }
00747             len = (int)strlen(he->p.argv[he->c]);
00748             if (he->p.argv[he->c][len - 1] == '/' && len > 1) {
00749                 rpmlog(RPMLOG_ERR,
00750                          _("line %d: Prefixes must not end with \"/\": %s\n"),
00751                          spec->lineNum, spec->line);
00752                 he->p.ptr = _free(he->p.ptr);
00753                 return RPMRC_FAIL;
00754             }
00755         }
00756         he->p.ptr = _free(he->p.ptr);
00757         break;
00758     case RPMTAG_DOCDIR:
00759         SINGLE_TOKEN_ONLY;
00760         if (field[0] != '/') {
00761             rpmlog(RPMLOG_ERR,
00762                      _("line %d: Docdir must begin with '/': %s\n"),
00763                      spec->lineNum, spec->line);
00764             return RPMRC_FAIL;
00765         }
00766         macro = NULL;
00767         delMacro(NULL, "_docdir");
00768         addMacro(NULL, "_docdir", NULL, field, RMIL_SPEC);
00769         break;
00770     case RPMTAG_XMAJOR:
00771     case RPMTAG_XMINOR:
00772     case RPMTAG_EPOCH:
00773         SINGLE_TOKEN_ONLY;
00774         if (parseNum(field, &num)) {
00775             rpmlog(RPMLOG_ERR,
00776                      _("line %d: %s takes an integer value: %s\n"),
00777                      spec->lineNum, tagName(tag), spec->line);
00778             return RPMRC_FAIL;
00779         }
00780         he->tag = tag;
00781         he->t = RPM_UINT32_TYPE;
00782         he->p.ui32p = &num;
00783         he->c = 1;
00784         xx = headerPut(pkg->header, he, 0);
00785         break;
00786     case RPMTAG_AUTOREQPROV:
00787         pkg->autoReq = parseYesNo(field);
00788         pkg->autoProv = pkg->autoReq;
00789         break;
00790     case RPMTAG_AUTOREQ:
00791         pkg->autoReq = parseYesNo(field);
00792         break;
00793     case RPMTAG_AUTOPROV:
00794         pkg->autoProv = parseYesNo(field);
00795         break;
00796     case RPMTAG_SOURCE:
00797     case RPMTAG_PATCH:
00798         SINGLE_TOKEN_ONLY;
00799         macro = NULL;
00800         if ((rc = addSource(spec, pkg, field, tag)))
00801             return rc;
00802         break;
00803     case RPMTAG_ICON:
00804         SINGLE_TOKEN_ONLY;
00805         macro = NULL;
00806         if ((rc = addSource(spec, pkg, field, tag)))
00807             return rc;
00808         /* XXX the fetch/load of icon needs to be elsewhere. */
00809         if ((rc = doIcon(spec, pkg->header)))
00810             return rc;
00811         break;
00812     case RPMTAG_NOSOURCE:
00813     case RPMTAG_NOPATCH:
00814         spec->noSource = 1;
00815         if ((rc = parseNoSource(spec, field, tag)))
00816             return rc;
00817         break;
00818     case RPMTAG_BUILDPREREQ:
00819     case RPMTAG_BUILDREQUIRES:
00820         if ((rc = parseBits(lang, buildScriptBits, &tagflags))) {
00821             rpmlog(RPMLOG_ERR,
00822                      _("line %d: Bad %s: qualifiers: %s\n"),
00823                      spec->lineNum, tagName(tag), spec->line);
00824             return rc;
00825         }
00826         if ((rc = parseRCPOT(spec, pkg, field, tag, 0, tagflags)))
00827             return rc;
00828         break;
00829     case RPMTAG_PREREQ:
00830     case RPMTAG_REQUIREFLAGS:
00831         if ((rc = parseBits(lang, installScriptBits, &tagflags))) {
00832             rpmlog(RPMLOG_ERR,
00833                      _("line %d: Bad %s: qualifiers: %s\n"),
00834                      spec->lineNum, tagName(tag), spec->line);
00835             return rc;
00836         }
00837         if ((rc = parseRCPOT(spec, pkg, field, tag, 0, tagflags)))
00838             return rc;
00839         break;
00840     /* Aliases for BuildRequires(hint): */
00841     case RPMTAG_BUILDSUGGESTS:
00842     case RPMTAG_BUILDENHANCES:
00843         tagflags = RPMSENSE_MISSINGOK;
00844         if ((rc = parseRCPOT(spec, pkg, field, tag, 0, tagflags)))
00845             return rc;
00846         break;
00847     /* Aliases for Requires(hint): */
00848     case RPMTAG_SUGGESTSFLAGS:
00849     case RPMTAG_ENHANCESFLAGS:
00850         tag = RPMTAG_REQUIREFLAGS;
00851         tagflags = RPMSENSE_MISSINGOK;
00852         if ((rc = parseRCPOT(spec, pkg, field, tag, 0, tagflags)))
00853             return rc;
00854         break;
00855     case RPMTAG_BUILDOBSOLETES:
00856     case RPMTAG_BUILDPROVIDES:
00857     case RPMTAG_BUILDCONFLICTS:
00858     case RPMTAG_CONFLICTFLAGS:
00859     case RPMTAG_OBSOLETEFLAGS:
00860     case RPMTAG_PROVIDEFLAGS:
00861         tagflags = RPMSENSE_ANY;
00862         if ((rc = parseRCPOT(spec, pkg, field, tag, 0, tagflags)))
00863             return rc;
00864         break;
00865     case RPMTAG_BUILDPLATFORMS:         /* XXX needs pattern parsing */
00866     case RPMTAG_EXCLUDEARCH:
00867     case RPMTAG_EXCLUSIVEARCH:
00868     case RPMTAG_EXCLUDEOS:
00869     case RPMTAG_EXCLUSIVEOS:
00870         addOrAppendListEntry(spec->sourceHeader, tag, field);
00871         break;
00872 
00873     case RPMTAG_BUILDARCHS:
00874     {   const char ** BANames = NULL;
00875         int BACount = 0;
00876         if ((rc = poptParseArgvString(field, &BACount, &BANames))) {
00877             rpmlog(RPMLOG_ERR,
00878                      _("line %d: Bad BuildArchitecture format: %s\n"),
00879                      spec->lineNum, spec->line);
00880             return RPMRC_FAIL;
00881         }
00882         if (spec->toplevel) {
00883             if (BACount > 0 && BANames != NULL) {
00884                 spec->BACount = BACount;
00885                 spec->BANames = BANames;
00886                 BANames = NULL;         /* XXX don't free. */
00887             }
00888         } else {
00889             if (BACount != 1 || strcmp(BANames[0], "noarch")) {
00890                 rpmlog(RPMLOG_ERR,
00891                      _("line %d: Only \"noarch\" sub-packages are supported: %s\n"),
00892                      spec->lineNum, spec->line);
00893                 BANames = _free(BANames);
00894                 return RPMRC_FAIL;
00895             }
00896             pkg->noarch = 1;
00897         }
00898         BANames = _free(BANames);
00899     }   break;
00900 
00901     default:
00902         macro = NULL;
00903         he->tag = tag;
00904         he->t = RPM_STRING_ARRAY_TYPE;
00905         he->p.argv= (const char **) &field;     /* XXX NOCAST */
00906         he->c = 1;
00907         he->append = 1;
00908         xx = headerPut(pkg->header, he, 0);
00909         he->append = 0;
00910         break;
00911     }
00912 
00913 /*@-usereleased@*/
00914     if (macro)
00915         addMacro(spec->macros, macro, NULL, field, RMIL_SPEC);
00916 /*@=usereleased@*/
00917     
00918     return RPMRC_OK;
00919 }
00920 
00921 /* This table has to be in a peculiar order.  If one tag is the */
00922 /* same as another, plus a few letters, it must come first.     */
00923 
00926 typedef struct PreambleRec_s {
00927     rpmTag tag;
00928     int multiLang;
00929     int obsolete;
00930 /*@observer@*/ /*@null@*/
00931     const char * token;
00932 } * PreambleRec;
00933 
00934 /*@unchecked@*/
00935 static struct PreambleRec_s preambleList[] = {
00936     {RPMTAG_NAME,               0, 0, "name"},
00937     {RPMTAG_VERSION,            0, 0, "version"},
00938     {RPMTAG_RELEASE,            0, 0, "release"},
00939     {RPMTAG_DISTEPOCH,          0, 0, "distepoch"},
00940     {RPMTAG_EPOCH,              0, 0, "epoch"},
00941     {RPMTAG_EPOCH,              0, 1, "serial"},
00942     {RPMTAG_SUMMARY,            1, 0, "summary"},
00943     {RPMTAG_LICENSE,            0, 0, "copyright"},
00944     {RPMTAG_LICENSE,            0, 0, "license"},
00945     {RPMTAG_DISTRIBUTION,       0, 0, "distribution"},
00946     {RPMTAG_DISTURL,            0, 0, "disturl"},
00947     {RPMTAG_VENDOR,             0, 0, "vendor"},
00948     {RPMTAG_GROUP,              1, 0, "group"},
00949     {RPMTAG_PACKAGER,           0, 0, "packager"},
00950     {RPMTAG_URL,                0, 0, "url"},
00951     {RPMTAG_SOURCE,             0, 0, "source"},
00952     {RPMTAG_PATCH,              0, 0, "patch"},
00953     {RPMTAG_NOSOURCE,           0, 0, "nosource"},
00954     {RPMTAG_NOPATCH,            0, 0, "nopatch"},
00955     {RPMTAG_EXCLUDEARCH,        0, 0, "excludearch"},
00956     {RPMTAG_EXCLUSIVEARCH,      0, 0, "exclusivearch"},
00957     {RPMTAG_EXCLUDEOS,          0, 0, "excludeos"},
00958     {RPMTAG_EXCLUSIVEOS,        0, 0, "exclusiveos"},
00959     {RPMTAG_ICON,               0, 0, "icon"},
00960     {RPMTAG_PROVIDEFLAGS,       0, 0, "provides"},
00961     {RPMTAG_REQUIREFLAGS,       1, 0, "requires"},
00962     {RPMTAG_PREREQ,             1, 0, "prereq"},
00963     {RPMTAG_CONFLICTFLAGS,      0, 0, "conflicts"},
00964     {RPMTAG_OBSOLETEFLAGS,      0, 0, "obsoletes"},
00965     {RPMTAG_PREFIXES,           0, 0, "prefixes"},
00966     {RPMTAG_PREFIXES,           0, 0, "prefix"},
00967     {RPMTAG_BUILDROOT,          0, 0, "buildroot"},
00968     {RPMTAG_BUILDARCHS,         0, 0, "buildarchitectures"},
00969     {RPMTAG_BUILDARCHS,         0, 0, "buildarch"},
00970     {RPMTAG_BUILDCONFLICTS,     0, 0, "buildconflicts"},
00971     {RPMTAG_BUILDOBSOLETES,     0, 0, "buildobsoletes"},
00972     {RPMTAG_BUILDPREREQ,        1, 0, "buildprereq"},
00973     {RPMTAG_BUILDPROVIDES,      0, 0, "buildprovides"},
00974     {RPMTAG_BUILDREQUIRES,      1, 0, "buildrequires"},
00975     {RPMTAG_AUTOREQPROV,        0, 0, "autoreqprov"},
00976     {RPMTAG_AUTOREQ,            0, 0, "autoreq"},
00977     {RPMTAG_AUTOPROV,           0, 0, "autoprov"},
00978     {RPMTAG_DOCDIR,             0, 0, "docdir"},
00979     {RPMTAG_DISTTAG,            0, 0, "disttag"},
00980     {RPMTAG_CVSID,              0, 0, "cvsid"},
00981     {RPMTAG_SVNID,              0, 0, "svnid"},
00982     {RPMTAG_SUGGESTSFLAGS,      0, 0, "suggests"},
00983     {RPMTAG_ENHANCESFLAGS,      0, 0, "enhances"},
00984     {RPMTAG_BUILDSUGGESTS,      0, 0, "buildsuggests"},
00985     {RPMTAG_BUILDENHANCES,      0, 0, "buildenhances"},
00986     {RPMTAG_VARIANTS,           0, 0, "variants"},
00987     {RPMTAG_VARIANTS,           0, 0, "variant"},
00988     {RPMTAG_XMAJOR,             0, 0, "xmajor"},
00989     {RPMTAG_XMINOR,             0, 0, "xminor"},
00990     {RPMTAG_REPOTAG,            0, 0, "repotag"},
00991     {RPMTAG_KEYWORDS,           0, 0, "keywords"},
00992     {RPMTAG_KEYWORDS,           0, 0, "keyword"},
00993     {RPMTAG_BUILDPLATFORMS,     0, 0, "buildplatforms"},
00994 #if defined(RPM_VENDOR_OPENPKG) /* make-class-available-as-macro */
00995     {RPMTAG_CLASS,              0, 0, "class"},
00996 #endif
00997     /*@-nullassign@*/   /* LCL: can't add null annotation */
00998     {0, 0, 0, 0}
00999     /*@=nullassign@*/
01000 };
01001 
01004 static int findPreambleTag(Spec spec, /*@out@*/rpmTag * tagp,
01005                 /*@null@*/ /*@out@*/ const char ** macro, /*@out@*/ char * lang)
01006         /*@modifies *tagp, *macro, *lang @*/
01007 {
01008     PreambleRec p;
01009     char *s;
01010     size_t len = 0;
01011 
01012     /* Search for defined tags. */
01013     for (p = preambleList; p->token != NULL; p++) {
01014         len = strlen(p->token);
01015         if (!(p->token && !xstrncasecmp(spec->line, p->token, len)))
01016             continue;
01017         if (p->obsolete) {
01018             rpmlog(RPMLOG_ERR, _("Legacy syntax is unsupported: %s\n"),
01019                         p->token);
01020             p = NULL;
01021         }
01022         break;
01023     }
01024     if (p == NULL)
01025         return 1;
01026 
01027     /* Search for arbitrary tags. */
01028     if (tagp && p->token == NULL) {
01029         ARGV_t aTags = NULL;
01030         int rc = 1;     /* assume failure */
01031 
01032 /*@-noeffect@*/
01033         (void) tagName(0); /* XXX force arbitrary tags to be initialized. */
01034 /*@=noeffect@*/
01035         aTags = rpmTags->aTags;
01036         if (aTags != NULL && aTags[0] != NULL) {
01037             ARGV_t av;
01038             s = tagCanonicalize(spec->line);
01039 #if defined(RPM_VENDOR_OPENPKG) /* wildcard-matching-arbitrary-tagnames */
01040             av = argvSearchLinear(aTags, s, argvFnmatchCasefold);
01041 #else
01042             av = argvSearch(aTags, s, argvStrcasecmp);
01043 #endif
01044             if (av != NULL) {
01045                 *tagp = tagGenerate(s);
01046                 rc = 0;
01047             }
01048             s = _free(s);
01049         }
01050         return rc;
01051     }
01052 
01053     s = spec->line + len;
01054     SKIPSPACE(s);
01055 
01056     switch (p->multiLang) {
01057     default:
01058     case 0:
01059         /* Unless this is a source or a patch, a ':' better be next */
01060         if (p->tag != RPMTAG_SOURCE && p->tag != RPMTAG_PATCH) {
01061             if (*s != ':') return 1;
01062         }
01063         *lang = '\0';
01064         break;
01065     case 1:     /* Parse optional ( <token> ). */
01066         if (*s == ':') {
01067             strcpy(lang, RPMBUILD_DEFAULT_LANG);
01068             break;
01069         }
01070         if (*s != '(') return 1;
01071         s++;
01072         SKIPSPACE(s);
01073         while (!xisspace(*s) && *s != ')')
01074             *lang++ = *s++;
01075         *lang = '\0';
01076         SKIPSPACE(s);
01077         if (*s != ')') return 1;
01078         s++;
01079         SKIPSPACE(s);
01080         if (*s != ':') return 1;
01081         break;
01082     }
01083 
01084     if (tagp)
01085         *tagp = p->tag;
01086     if (macro)
01087         /*@-onlytrans -observertrans -dependenttrans@*/ /* FIX: double indirection. */
01088         *macro = p->token;
01089         /*@=onlytrans =observertrans =dependenttrans@*/
01090     return 0;
01091 }
01092 
01093 /* XXX should return rpmParseState, but RPMRC_FAIL forces int return. */
01094 int parsePreamble(Spec spec, int initialPackage)
01095 {
01096     HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
01097     rpmParseState nextPart;
01098     int xx;
01099     char *linep;
01100     Package pkg;
01101     char NVR[BUFSIZ];
01102     char lang[BUFSIZ];
01103     rpmRC rc;
01104 
01105     strcpy(NVR, "(main package)");
01106 
01107     pkg = newPackage(spec);
01108     if (spec->packages == NULL) {
01109         spec->packages = pkg;
01110 assert(initialPackage);
01111     } else if (! initialPackage) {
01112         char *name = NULL;
01113         rpmParseState flag;
01114         Package lastpkg;
01115 
01116         /* There is one option to %package: <pkg> or -n <pkg> */
01117         flag = PART_NONE;
01118         if (parseSimplePart(spec, &name, &flag)) {
01119             rpmlog(RPMLOG_ERR, _("Bad package specification: %s\n"),
01120                         spec->line);
01121             return RPMRC_FAIL;
01122         }
01123         
01124         lastpkg = NULL;
01125         if (lookupPackage(spec, name, flag, &lastpkg) == RPMRC_OK) {
01126             pkg->next = lastpkg->next;
01127         } else {
01128             /* Add package to end of list */
01129             for (lastpkg = spec->packages; lastpkg->next != NULL; lastpkg = lastpkg->next)
01130             {};
01131         }
01132 assert(lastpkg != NULL);
01133         lastpkg->next = pkg;
01134         
01135         /* Construct the package */
01136         if (flag == PART_SUBNAME) {
01137             he->tag = RPMTAG_NAME;
01138             xx = headerGet(spec->packages->header, he, 0);
01139             sprintf(NVR, "%s-%s", he->p.str, name);
01140             he->p.ptr = _free(he->p.ptr);
01141         } else
01142             strcpy(NVR, name);
01143         name = _free(name);
01144         he->tag = RPMTAG_NAME;
01145         he->t = RPM_STRING_TYPE;
01146         he->p.str = NVR;
01147         he->c = 1;
01148         xx = headerPut(pkg->header, he, 0);
01149     }
01150 
01151     if ((rc = readLine(spec, STRIP_TRAILINGSPACE | STRIP_COMMENTS)) > 0) {
01152         nextPart = PART_NONE;
01153     } else {
01154         if (rc)
01155             return rc;
01156         while ((nextPart = isPart(spec)) == PART_NONE) {
01157             const char * macro = NULL;
01158             rpmTag tag;
01159 
01160             /* Skip blank lines */
01161             linep = spec->line;
01162             SKIPSPACE(linep);
01163             if (*linep != '\0') {
01164                 if (findPreambleTag(spec, &tag, &macro, lang)) {
01165                     rpmlog(RPMLOG_ERR, _("line %d: Unknown tag: %s\n"),
01166                                 spec->lineNum, spec->line);
01167                     return RPMRC_FAIL;
01168                 }
01169                 if (handlePreambleTag(spec, pkg, tag, macro, lang))
01170                     return RPMRC_FAIL;
01171                 if (spec->BANames && !spec->recursing && spec->toplevel)
01172                     return PART_BUILDARCHITECTURES;
01173             }
01174             if ((rc =
01175                  readLine(spec, STRIP_TRAILINGSPACE | STRIP_COMMENTS)) > 0) {
01176                 nextPart = PART_NONE;
01177                 break;
01178             }
01179             if (rc)
01180                 return rc;
01181         }
01182     }
01183 
01184     /* Do some final processing on the header */
01185     
01186     /* 
01187      * Expand buildroot one more time to get %{version} and the like
01188      * from the main package.
01189      */
01190     if (initialPackage) {
01191         const char *s = rpmExpand("%{?buildroot}", NULL);
01192         if (s && *s) 
01193             (void) addMacro(NULL, "buildroot", NULL, s, -1);
01194         s = _free(s);
01195     }
01196 
01197     /* XXX Skip valid arch check if not building binary package */
01198     if (!spec->anyarch && checkForValidArchitectures(spec))
01199         return RPMRC_FAIL;
01200 
01201     if (pkg == spec->packages)
01202         fillOutMainPackage(pkg->header);
01203 
01204     if (checkForDuplicates(pkg->header, NVR) != RPMRC_OK)
01205         return RPMRC_FAIL;
01206 
01207     if (pkg != spec->packages)
01208         headerCopyTags(spec->packages->header, pkg->header,
01209                         (rpmuint32_t *)copyTagsDuringParse);
01210 
01211 #ifdef RPM_VENDOR_PLD /* rpm-epoch0 */
01212     /* Add Epoch: 0 to package header if it was not set by spec */
01213     he->tag = RPMTAG_NAME;
01214     if (headerGet(spec->packages->header, he, 0) == 0) {
01215         rpmuint32_t num = 0;
01216 
01217         he->tag = RPMTAG_EPOCH;
01218         he->t = RPM_UINT32_TYPE;
01219         he->p.ui32p = &num;
01220         he->c = 1;
01221         xx = headerPut(pkg->header, he, 0);
01222 
01223         /* also declare %{epoch} to be same */
01224         addMacro(spec->macros, "epoch", NULL, "0", RMIL_SPEC);
01225     }
01226 #endif /* RPM_VENDOR_PLD rpm-epoch0 */
01227 
01228     if (checkForRequired(pkg->header, NVR) != RPMRC_OK)
01229         return RPMRC_FAIL;
01230 
01231     return nextPart;
01232 }

Generated on Fri Dec 3 2010 20:53:16 for rpm by  doxygen 1.7.2