rpm  5.4.10
parsePreamble.c
Go to the documentation of this file.
1 
6 #include "system.h"
7 
8 #include <rpmio.h>
9 #include <rpmiotypes.h>
10 #include <rpmlog.h>
11 #include <rpmurl.h>
12 #include <argv.h>
13 #include <mire.h>
14 
15 #define _RPMEVR_INTERNAL
16 #define _RPMTAG_INTERNAL /* XXX rpmTags->aTags */
17 #include <rpmbuild.h>
18 #include "debug.h"
19 
20 /*@access FD_t @*/ /* compared with NULL */
21 /*@access headerTagIndices @*/ /* rpmTags->aTags */
22 
25 /*@observer@*/ /*@unchecked@*/
32  RPMTAG_GROUP, /* XXX permissive. */
33  RPMTAG_SUMMARY, /* XXX permissive. */
34  RPMTAG_DESCRIPTION, /* XXX permissive. */
40  RPMTAG_GIF,
41  RPMTAG_XPM,
42  RPMTAG_URL,
55  0
56 };
57 
60 /*@observer@*/ /*@unchecked@*/
61 static rpmTag requiredTags[] = {
68  0
69 };
70 
73 static void addOrAppendListEntry(Header h, rpmTag tag, char * line)
74  /*@modifies h @*/
75 {
76  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
77  int xx;
78  int argc;
79  const char **argv;
80 
81  xx = poptParseArgvString(line, &argc, &argv);
82  if (argc) {
83  he->tag = tag;
85  he->p.argv = argv;
86  he->c = argc;
87  he->append = 1;
88  xx = headerPut(h, he, 0);
89  he->append = 0;
90  }
91  argv = _free(argv);
92 }
93 
94 /* Parse a simple part line that only take -n <pkg> or <pkg> */
95 /* <pkg> is returned in name as a pointer into malloc'd storage. */
96 
99 static int parseSimplePart(Spec spec, /*@out@*/char ** Np,
100  /*@out@*/rpmParseState *flag)
101  /*@globals internalState@*/
102  /*@modifies *Np, *flag, internalState, spec->line @*/
103 {
104  char * s, * se;
105  int rc = 0; /* assume failure */
106 
107  if (Np)
108  *Np = NULL;
109 
110  se = strchr(spec->line, '#');
111  if (se) {
112  *se = '\0';
113  while (--se >= spec->line && strchr(" \t\n\r", *se) != NULL)
114  *se = '\0';
115  }
116 
117  s = xstrdup(spec->line);
118  /* Throw away the first token (the %xxxx) */
119  (void)strtok(s, " \t\n");
120 
121  if (!(se = strtok(NULL, " \t\n")))
122  goto exit;
123 
124  if (!strcmp(se, "-n")) {
125  if (!(se = strtok(NULL, " \t\n"))) {
126  rc = 1;
127  goto exit;
128  }
129  *flag = PART_NAME;
130  } else
131  *flag = PART_SUBNAME;
132 
133  if (Np)
134  *Np = xstrdup(se);
135 
136  rc = (strtok(NULL, " \t\n") ? 1 : 0);
137 
138 exit:
139  s = _free(s);
140  return rc;
141 }
142 
145 static inline int parseYesNo(const char * s)
146  /*@*/
147 {
148  return ((!s || (s[0] == 'n' || s[0] == 'N' || s[0] == '0') ||
149  !xstrcasecmp(s, "false") || !xstrcasecmp(s, "off"))
150  ? 0 : 1);
151 }
152 
153 typedef struct tokenBits_s {
154 /*@observer@*/ /*@null@*/
155  const char * name;
157 } * tokenBits;
158 
161 /*@observer@*/ /*@unchecked@*/
162 static struct tokenBits_s installScriptBits[] = {
163  { "interp", RPMSENSE_INTERP },
164  { "preun", RPMSENSE_SCRIPT_PREUN },
165  { "pre", RPMSENSE_SCRIPT_PRE },
166  { "postun", RPMSENSE_SCRIPT_POSTUN },
167  { "post", RPMSENSE_SCRIPT_POST },
168  { "rpmlib", RPMSENSE_RPMLIB },
169  { "verify", RPMSENSE_SCRIPT_VERIFY },
170  { "hint", RPMSENSE_MISSINGOK },
171  { NULL, 0 }
172 };
173 
176 /*@observer@*/ /*@unchecked@*/
177 static struct tokenBits_s buildScriptBits[] = {
178  { "prep", RPMSENSE_SCRIPT_PREP },
179  { "build", RPMSENSE_SCRIPT_BUILD },
180  { "install", RPMSENSE_SCRIPT_INSTALL },
181  { "clean", RPMSENSE_SCRIPT_CLEAN },
182  { "hint", RPMSENSE_MISSINGOK },
183  { NULL, 0 }
184 };
185 
188 static int parseBits(const char * s, const tokenBits tokbits,
189  /*@out@*/ rpmsenseFlags * bp)
190  /*@modifies *bp @*/
191 {
192  tokenBits tb;
193  const char * se;
194  rpmsenseFlags bits = RPMSENSE_ANY;
195  int c = 0;
196 
197  if (s) {
198  while (*s != '\0') {
199  while ((c = *s) && xisspace(c)) s++;
200  se = s;
201  while ((c = *se) && xisalpha(c)) se++;
202  if (s == se)
203  break;
204  for (tb = tokbits; tb->name; tb++) {
205  if (tb->name != NULL &&
206  strlen(tb->name) == (size_t)(se-s) && !strncmp(tb->name, s, (se-s)))
207  /*@innerbreak@*/ break;
208  }
209  if (tb->name == NULL)
210  break;
211  bits |= tb->bits;
212  while ((c = *se) && xisspace(c)) se++;
213  if (c != ',')
214  break;
215  s = ++se;
216  }
217  }
218  if (c == 0 && bp) *bp = bits;
219  return (c ? RPMRC_FAIL : RPMRC_OK);
220 }
221 
224 /*@null@*/
225 static inline char * findLastChar(char * s)
226  /*@modifies *s @*/
227 {
228  char *se = s + strlen(s);
229 
230  /* Right trim white space. */
231  while (--se > s && strchr(" \t\n\r", *se) != NULL)
232  *se = '\0';
233  /* Truncate comments. */
234  if ((se = strchr(s, '#')) != NULL) {
235  *se = '\0';
236  while (--se > s && strchr(" \t\n\r", *se) != NULL)
237  *se = '\0';
238  }
239 /*@-temptrans -retalias @*/
240  return se;
241 /*@=temptrans =retalias @*/
242 }
243 
246 static int isMemberInEntry(Header h, const char *name, rpmTag tag)
247  /*@globals internalState @*/
248  /*@modifies internalState @*/
249 {
250  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
251  int rc = -1;
252  int xx;
253 
254  he->tag = tag;
255  xx = headerGet(h, he, 0);
256  if (!xx)
257  return rc;
258  rc = 0;
259  while (he->c) {
260  he->c--;
261  if (xstrcasecmp(he->p.argv[he->c], name))
262  continue;
263  rc = 1;
264  break;
265  }
266  he->p.ptr = _free(he->p.ptr);
267  return rc;
268 }
269 
273  /*@globals rpmGlobalMacroContext, h_errno, internalState @*/
274  /*@modifies rpmGlobalMacroContext, internalState @*/
275 {
276  const char *arch = rpmExpand("%{_target_cpu}", NULL);
277  const char *os = rpmExpand("%{_target_os}", NULL);
278  int rc = RPMRC_FAIL; /* assume failure. */
279 
280  if (isMemberInEntry(spec->sourceHeader, arch, RPMTAG_EXCLUDEARCH) == 1) {
281  rpmlog(RPMLOG_ERR, _("Architecture is excluded: %s\n"), arch);
282  goto exit;
283  }
284  if (isMemberInEntry(spec->sourceHeader, arch, RPMTAG_EXCLUSIVEARCH) == 0) {
285  rpmlog(RPMLOG_ERR, _("Architecture is not included: %s\n"), arch);
286  goto exit;
287  }
288  if (isMemberInEntry(spec->sourceHeader, os, RPMTAG_EXCLUDEOS) == 1) {
289  rpmlog(RPMLOG_ERR, _("OS is excluded: %s\n"), os);
290  goto exit;
291  }
292  if (isMemberInEntry(spec->sourceHeader, os, RPMTAG_EXCLUSIVEOS) == 0) {
293  rpmlog(RPMLOG_ERR, _("OS is not included: %s\n"), os);
294  goto exit;
295  }
296  rc = 0;
297 exit:
298  arch = _free(arch);
299  os = _free(os);
300  return rc;
301 }
302 
309 static rpmRC checkForRequired(Header h, const char * NVR)
310  /*@*/
311 {
312  rpmTag * p;
313  rpmRC rc = RPMRC_OK;
314 
315  for (p = requiredTags; *p != 0; p++) {
316  if (!headerIsEntry(h, *p)) {
318  _("%s field must be present in package: %s\n"),
319  tagName(*p), NVR);
320  rc = RPMRC_FAIL;
321  }
322  }
323 
324  return rc;
325 }
326 
333 static rpmRC checkForDuplicates(Header h, const char * NVR)
334  /*@globals internalState @*/
335  /*@modifies h, internalState @*/
336 {
337  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
338  HeaderIterator hi;
339  rpmTag lastTag = 0;
340  rpmRC rc = RPMRC_OK;
341 
342  for (hi = headerInit(h);
343  headerNext(hi, he, 0);
344  he->p.ptr = _free(he->p.ptr))
345  {
346  if (he->tag != lastTag) {
347  lastTag = he->tag;
348  continue;
349  }
350  rpmlog(RPMLOG_ERR, _("Duplicate %s entries in package: %s\n"),
351  tagName(he->tag), NVR);
352  rc = RPMRC_FAIL;
353  }
354  hi = headerFini(hi);
355 
356  return rc;
357 }
358 
361 /*@observer@*/ /*@unchecked@*/
362 static struct optionalTag {
364 /*@observer@*/ /*@null@*/
365  const char * ot_mac;
366 } optionalTags[] = {
367  { RPMTAG_VENDOR, "%{vendor}" },
368  { RPMTAG_PACKAGER, "%{packager}" },
369  { RPMTAG_DISTEPOCH, "%{distepoch}" },
370  { RPMTAG_DISTRIBUTION, "%{distribution}" },
371  { RPMTAG_DISTTAG, "%{disttag}" },
372  { RPMTAG_DISTURL, "%{disturl}" },
373  { RPMTAG_BUGURL, "%{bugurl}" },
374  { 0xffffffff, "%{class}" },
375  { -1, NULL }
376 };
377 
381  /*@globals rpmGlobalMacroContext, h_errno, internalState @*/
382  /*@modifies h, rpmGlobalMacroContext, internalState @*/
383 {
384  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
385  struct optionalTag *ot;
386  int xx;
387 
388  for (ot = optionalTags; ot->ot_mac != NULL; ot++) {
389  const char * val;
390  rpmTag tag;
391 
392  tag = ot->ot_tag;
393 
394  /* Generate arbitrary tag (if necessary). */
395  if (tag == 0xffffffff) {
396  val = tagCanonicalize(ot->ot_mac + (sizeof("%{")-1));
397  tag = tagGenerate(val);
398  val = _free(val);
399  }
400 
401  if (headerIsEntry(h, tag))
402  continue;
403  val = rpmExpand(ot->ot_mac, NULL);
404  if (val && *val != '%') {
405  he->tag = tag;
406  he->t = RPM_STRING_TYPE;
407  he->p.str = val;
408  he->c = 1;
409  xx = headerPut(h, he, 0);
410  }
411  val = _free(val);
412  }
413 }
414 
417 static int doIcon(Spec spec, Header h)
418  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
419  /*@modifies h, rpmGlobalMacroContext, fileSystem, internalState @*/
420 {
421  static size_t iconsize = 0;
422  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
423  const char *fn, *Lurlfn = NULL;
424  struct Source *sp;
425  size_t nb;
426  rpmuint8_t * icon;
427  FD_t fd = NULL;
428  int rc = RPMRC_FAIL; /* assume error */
429  int urltype;
430  int xx;
431 
432  if (iconsize == 0) {
433  iconsize = rpmExpandNumeric("%{?_build_iconsize}");
434  if (iconsize < 2048)
435  iconsize = 2048;
436  }
437  icon = alloca(iconsize+1);
438 
439  for (sp = spec->sources; sp != NULL; sp = sp->next) {
440  if (sp->flags & RPMFILE_ICON)
441  break;
442  }
443  if (sp == NULL) {
444  rpmlog(RPMLOG_ERR, _("No icon file in sources\n"));
445  goto exit;
446  }
447 
448 #if defined(RPM_VENDOR_OPENPKG) /* splitted-source-directory */
449  /* support splitted source directories, i.e., source files which
450  are alternatively placed into the .spec directory and picked
451  up from there, too. */
452  Lurlfn = rpmGenPath(NULL, "%{_specdir}/", sp->source);
453  if (access(Lurlfn, F_OK) == -1) {
454  Lurlfn = _free(Lurlfn);
455  Lurlfn = rpmGenPath(NULL, "%{_icondir}/", sp->source);
456  }
457 #else
458  Lurlfn = rpmGenPath(NULL, "%{_icondir}/", sp->source);
459 #endif
460 
461  fn = NULL;
462  urltype = urlPath(Lurlfn, &fn);
463  switch (urltype) {
464  case URL_IS_HTTPS:
465  case URL_IS_HTTP:
466  case URL_IS_FTP:
467  case URL_IS_PATH:
468  case URL_IS_UNKNOWN:
469  break;
470  case URL_IS_DASH:
471  case URL_IS_HKP:
472  case URL_IS_MONGO: /* XXX FIXME */
473  rpmlog(RPMLOG_ERR, _("Invalid icon URL: %s\n"), Lurlfn);
474  goto exit;
475  /*@notreached@*/ break;
476  }
477 
478  fd = Fopen(fn, "r%{?_rpmgio}");
479  if (fd == NULL || Ferror(fd)) {
480  rpmlog(RPMLOG_ERR, _("Unable to open icon %s: %s\n"),
481  fn, Fstrerror(fd));
482  rc = RPMRC_FAIL;
483  goto exit;
484  }
485 
486  *icon = '\0';
487  nb = Fread(icon, sizeof(icon[0]), iconsize, fd);
488  if (Ferror(fd) || nb == 0) {
489  rpmlog(RPMLOG_ERR, _("Unable to read icon %s: %s\n"),
490  fn, Fstrerror(fd));
491  goto exit;
492  }
493  if (nb >= iconsize) {
494  rpmlog(RPMLOG_ERR, _("Icon %s is too big (max. %d bytes)\n"),
495  fn, (int)iconsize);
496  goto exit;
497  }
498 
499  if (icon[0] == 'G' && icon[1] == 'I' && icon[2] == 'F')
500  he->tag = RPMTAG_GIF;
501  else
502  if (icon[0] == '/' && icon[1] == '*' && icon[2] == ' '
503  && icon[3] == 'X' && icon[4] == 'P' && icon[5] == 'M')
504  he->tag = RPMTAG_XPM;
505  else
506  he->tag = tagValue("Icon");
507  he->t = RPM_BIN_TYPE;
508  he->p.ui8p = icon;
509  he->c = (rpmTagCount)nb;
510  xx = headerPut(h, he, 0);
511  rc = 0;
512 
513 exit:
514  if (fd) {
515  (void) Fclose(fd);
516  fd = NULL;
517  }
518  Lurlfn = _free(Lurlfn);
519  return rc;
520 }
521 
522 spectag stashSt(Spec spec, Header h, rpmTag tag, const char * lang)
523 {
524  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
525  spectag t = NULL;
526  int xx;
527 
528  if (spec->st) {
529  spectags st = spec->st;
530  if (st->st_ntags == st->st_nalloc) {
531  st->st_nalloc += 10;
532  st->st_t = xrealloc(st->st_t, st->st_nalloc * sizeof(*(st->st_t)));
533  }
534  t = st->st_t + st->st_ntags++;
535  t->t_tag = tag;
536  t->t_startx = spec->lineNum - 1;
537  t->t_nlines = 1;
538  t->t_lang = xstrdup(lang);
539  t->t_msgid = NULL;
540  if (!(t->t_lang && strcmp(t->t_lang, RPMBUILD_DEFAULT_LANG))) {
541  he->tag = RPMTAG_NAME;
542  xx = headerGet(h, he, 0);
543  if (xx) {
544  char buf[1024];
545  sprintf(buf, "%s(%s)", he->p.str, tagName(tag));
546  t->t_msgid = xstrdup(buf);
547  }
548  he->p.ptr = _free(he->p.ptr);
549  }
550  }
551  /*@-usereleased -compdef@*/
552  return t;
553  /*@=usereleased =compdef@*/
554 }
555 
556 #define SINGLE_TOKEN_ONLY \
557 if (multiToken) { \
558  rpmlog(RPMLOG_ERR, _("line %d: Tag takes single token only: %s\n"), \
559  spec->lineNum, spec->line); \
560  return RPMRC_FAIL; \
561 }
562 
563 /*@-redecl@*/
564 extern int noLang;
565 /*@=redecl@*/
566 
567 static rpmRC tagValidate(Spec spec, rpmTag tag, const char * value)
568  /*@*/
569 {
570  const char * tagN = tagName(tag);
571  const char * pattern = rpmExpand("%{?pattern_", tagN, "}", NULL);
572  rpmRC ec = RPMRC_OK;
573 
574  if (pattern && *pattern) {
575  miRE mire;
576  int xx;
577 
578  mire = mireNew(RPMMIRE_REGEX, tag);
579  xx = mireSetCOptions(mire, RPMMIRE_REGEX, 0, 0, NULL);
580  if (!xx)
581  xx = mireRegcomp(mire, pattern);
582  if (!xx)
583  xx = mireRegexec(mire, value, strlen(value));
584  if (!xx)
585  ec = RPMRC_OK;
586  else {
587  rpmlog(RPMLOG_ERR, _("line %d: invalid tag value(\"%s\") %s: %s\n"),
588  spec->lineNum, pattern, tagN, spec->line);
589  ec = RPMRC_FAIL;
590  }
591 
592  mire = mireFree(mire);
593  }
594 
595  pattern = _free(pattern);
596 
597  return ec;
598 }
599 
602 static rpmRC handlePreambleTag(Spec spec, Package pkg, rpmTag tag,
603  const char *macro, const char *lang)
604  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
605  /*@modifies spec->macros, spec->st,
606  spec->sources, spec->numSources, spec->noSource,
607  spec->sourceHeader, spec->BANames, spec->BACount,
608  spec->line,
609  pkg->header, pkg->autoProv, pkg->autoReq, pkg->noarch,
610  rpmGlobalMacroContext, fileSystem, internalState @*/
611 {
612  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
613  char * field = spec->line;
614  char * end;
615  int multiToken = 0;
616  rpmsenseFlags tagflags;
617  int len;
619  int rc;
620  int xx;
621 
622  if (field == NULL) return RPMRC_FAIL; /* XXX can't happen */
623  /* Find the start of the "field" and strip trailing space */
624  while ((*field) && (*field != ':'))
625  field++;
626  if (*field != ':') {
627  rpmlog(RPMLOG_ERR, _("line %d: Malformed tag: %s\n"),
628  spec->lineNum, spec->line);
629  return RPMRC_FAIL;
630  }
631  field++;
632  SKIPSPACE(field);
633  if (!*field) {
634  /* Empty field */
635  rpmlog(RPMLOG_ERR, _("line %d: Empty tag: %s\n"),
636  spec->lineNum, spec->line);
637  return RPMRC_FAIL;
638  }
639  end = findLastChar(field);
640 
641  /* Validate tag data content. */
642  if (tagValidate(spec, tag, field) != RPMRC_OK)
643  return RPMRC_FAIL;
644 
645  /* See if this is multi-token */
646  end = field;
647  SKIPNONSPACE(end);
648  if (*end != '\0')
649  multiToken = 1;
650 
651  switch (tag) {
652  case RPMTAG_NAME:
653  case RPMTAG_VERSION:
654  case RPMTAG_RELEASE:
655  case RPMTAG_DISTEPOCH:
656  case RPMTAG_URL:
657  case RPMTAG_DISTTAG:
658  case RPMTAG_REPOTAG:
659  case RPMTAG_CVSID:
660  case RPMTAG_BUGURL:
662  /* These macros are for backward compatibility */
663  if (tag == RPMTAG_VERSION) {
664  if (strchr(field, '-') != NULL) {
665  rpmlog(RPMLOG_ERR, _("line %d: Illegal char '-' in %s: %s\n"),
666  spec->lineNum, "version", spec->line);
667  return RPMRC_FAIL;
668  }
669  addMacro(spec->macros, "PACKAGE_VERSION", NULL, field, RMIL_OLDSPEC);
670  } else if (tag == RPMTAG_RELEASE) {
671  if (strchr(field, '-') != NULL) {
672  rpmlog(RPMLOG_ERR, _("line %d: Illegal char '-' in %s: %s\n"),
673  spec->lineNum, "release", spec->line);
674  return RPMRC_FAIL;
675  }
676  addMacro(spec->macros, "PACKAGE_RELEASE", NULL, field, RMIL_OLDSPEC-1);
677  }
678  he->tag = tag;
679  he->t = RPM_STRING_TYPE;
680  he->p.str = field;
681  he->c = 1;
682  xx = headerPut(pkg->header, he, 0);
683  break;
684  case RPMTAG_GROUP:
685  case RPMTAG_SUMMARY:
686 #if defined(RPM_VENDOR_OPENPKG) /* make-class-available-as-macro */
687  case RPMTAG_CLASS:
688 #endif
689  (void) stashSt(spec, pkg->header, tag, lang);
690  /*@fallthrough@*/
691  case RPMTAG_DISTRIBUTION:
692  case RPMTAG_VENDOR:
693  case RPMTAG_LICENSE:
694  case RPMTAG_PACKAGER:
695  if (!*lang) {
696  he->tag = tag;
697  he->t = RPM_STRING_TYPE;
698  he->p.str = field;
699  he->c = 1;
700  xx = headerPut(pkg->header, he, 0);
701  } else if (!(noLang && strcmp(lang, RPMBUILD_DEFAULT_LANG))) {
702 #if defined(SUPPORT_I18NSTRING_TYPE)
703  (void) headerAddI18NString(pkg->header, tag, field, lang);
704 #else
705  if (!strcmp(lang, RPMBUILD_DEFAULT_LANG)) {
706  he->tag = tag;
707  he->t = RPM_STRING_TYPE;
708  he->p.str = field;
709  he->c = 1;
710  xx = headerPut(pkg->header, he, 0);
711  }
712 #endif
713  }
714  break;
715  /* XXX silently ignore BuildRoot: */
716  case RPMTAG_BUILDROOT:
718  macro = NULL;
719 #ifdef DYING
720  buildRootURL = rpmGenPath(spec->rootURL, "%{?buildroot}", NULL);
721  (void) urlPath(buildRootURL, &buildRoot);
722  if (*buildRoot == '\0') buildRoot = "/";
723  if (!strcmp(buildRoot, "/")) {
725  _("BuildRoot can not be \"/\": %s\n"), spec->buildRootURL);
726  buildRootURL = _free(buildRootURL);
727  return RPMRC_FAIL;
728  }
729  buildRootURL = _free(buildRootURL);
730 #endif
731  break;
732  case RPMTAG_KEYWORDS:
733  case RPMTAG_VARIANTS:
734  case RPMTAG_PREFIXES:
735  addOrAppendListEntry(pkg->header, tag, field);
736  he->tag = tag;
737  xx = headerGet(pkg->header, he, 0);
738  if (tag == RPMTAG_PREFIXES)
739  while (he->c--) {
740  if (he->p.argv[he->c][0] != '/') {
742  _("line %d: Prefixes must begin with \"/\": %s\n"),
743  spec->lineNum, spec->line);
744  he->p.ptr = _free(he->p.ptr);
745  return RPMRC_FAIL;
746  }
747  len = (int)strlen(he->p.argv[he->c]);
748  if (he->p.argv[he->c][len - 1] == '/' && len > 1) {
750  _("line %d: Prefixes must not end with \"/\": %s\n"),
751  spec->lineNum, spec->line);
752  he->p.ptr = _free(he->p.ptr);
753  return RPMRC_FAIL;
754  }
755  }
756  he->p.ptr = _free(he->p.ptr);
757  break;
758  case RPMTAG_DOCDIR:
760  if (field[0] != '/') {
762  _("line %d: Docdir must begin with '/': %s\n"),
763  spec->lineNum, spec->line);
764  return RPMRC_FAIL;
765  }
766  macro = NULL;
767  delMacro(NULL, "_docdir");
768  addMacro(NULL, "_docdir", NULL, field, RMIL_SPEC);
769  break;
770  case RPMTAG_XMAJOR:
771  case RPMTAG_XMINOR:
772  case RPMTAG_EPOCH:
774  if (parseNum(field, &num)) {
776  _("line %d: %s takes an integer value: %s\n"),
777  spec->lineNum, tagName(tag), spec->line);
778  return RPMRC_FAIL;
779  }
780  he->tag = tag;
781  he->t = RPM_UINT32_TYPE;
782  he->p.ui32p = &num;
783  he->c = 1;
784  xx = headerPut(pkg->header, he, 0);
785  break;
786  case RPMTAG_AUTOREQPROV:
787  pkg->autoReq = parseYesNo(field);
788  pkg->autoProv = pkg->autoReq;
789  break;
790  case RPMTAG_AUTOREQ:
791  pkg->autoReq = parseYesNo(field);
792  break;
793  case RPMTAG_AUTOPROV:
794  pkg->autoProv = parseYesNo(field);
795  break;
796  case RPMTAG_SOURCE:
797  case RPMTAG_PATCH:
799  macro = NULL;
800  if ((rc = addSource(spec, pkg, field, tag)))
801  return rc;
802  break;
803  case RPMTAG_ICON:
805  macro = NULL;
806  if ((rc = addSource(spec, pkg, field, tag)))
807  return rc;
808  /* XXX the fetch/load of icon needs to be elsewhere. */
809  if ((rc = doIcon(spec, pkg->header)))
810  return rc;
811  break;
812  case RPMTAG_NOSOURCE:
813  case RPMTAG_NOPATCH:
814  spec->noSource = 1;
815  if ((rc = parseNoSource(spec, field, tag)))
816  return rc;
817  break;
818  case RPMTAG_BUILDPREREQ:
820  if ((rc = parseBits(lang, buildScriptBits, &tagflags))) {
822  _("line %d: Bad %s: qualifiers: %s\n"),
823  spec->lineNum, tagName(tag), spec->line);
824  return rc;
825  }
826  if ((rc = parseRCPOT(spec, pkg, field, tag, 0, tagflags)))
827  return rc;
828  break;
829  case RPMTAG_PREREQ:
830  case RPMTAG_REQUIREFLAGS:
831  if ((rc = parseBits(lang, installScriptBits, &tagflags))) {
833  _("line %d: Bad %s: qualifiers: %s\n"),
834  spec->lineNum, tagName(tag), spec->line);
835  return rc;
836  }
837  if ((rc = parseRCPOT(spec, pkg, field, tag, 0, tagflags)))
838  return rc;
839  break;
840  /* Aliases for BuildRequires(hint): */
843  tagflags = RPMSENSE_MISSINGOK;
844  if ((rc = parseRCPOT(spec, pkg, field, tag, 0, tagflags)))
845  return rc;
846  break;
847  /* Aliases for Requires(hint): */
850  tag = RPMTAG_REQUIREFLAGS;
851  tagflags = RPMSENSE_MISSINGOK;
852  if ((rc = parseRCPOT(spec, pkg, field, tag, 0, tagflags)))
853  return rc;
854  break;
860  case RPMTAG_PROVIDEFLAGS:
861  tagflags = RPMSENSE_ANY;
862  if ((rc = parseRCPOT(spec, pkg, field, tag, 0, tagflags)))
863  return rc;
864  break;
865  case RPMTAG_BUILDPLATFORMS: /* XXX needs pattern parsing */
866  case RPMTAG_EXCLUDEARCH:
868  case RPMTAG_EXCLUDEOS:
869  case RPMTAG_EXCLUSIVEOS:
870  addOrAppendListEntry(spec->sourceHeader, tag, field);
871  break;
872 
873  case RPMTAG_BUILDARCHS:
874  { const char ** BANames = NULL;
875  int BACount = 0;
876  if ((rc = poptParseArgvString(field, &BACount, &BANames))) {
878  _("line %d: Bad BuildArchitecture format: %s\n"),
879  spec->lineNum, spec->line);
880  return RPMRC_FAIL;
881  }
882  if (spec->toplevel) {
883  if (BACount > 0 && BANames != NULL) {
884  spec->BACount = BACount;
885  spec->BANames = BANames;
886  BANames = NULL; /* XXX don't free. */
887  }
888  } else {
889  if (BACount != 1 || strcmp(BANames[0], "noarch")) {
891  _("line %d: Only \"noarch\" sub-packages are supported: %s\n"),
892  spec->lineNum, spec->line);
893  BANames = _free(BANames);
894  return RPMRC_FAIL;
895  }
896  pkg->noarch = 1;
897  }
898  BANames = _free(BANames);
899  } break;
900 
901  default:
902  macro = NULL;
903  he->tag = tag;
904  he->t = RPM_STRING_ARRAY_TYPE;
905  he->p.argv= (const char **) &field; /* XXX NOCAST */
906  he->c = 1;
907  he->append = 1;
908  xx = headerPut(pkg->header, he, 0);
909  he->append = 0;
910  break;
911  }
912 
913 /*@-usereleased@*/
914  if (macro)
915  addMacro(spec->macros, macro, NULL, field, RMIL_SPEC);
916 /*@=usereleased@*/
917 
918  return RPMRC_OK;
919 }
920 
921 /* This table has to be in a peculiar order. If one tag is the */
922 /* same as another, plus a few letters, it must come first. */
923 
926 typedef struct PreambleRec_s {
929  int obsolete;
930 /*@observer@*/ /*@null@*/
931  const char * token;
932 } * PreambleRec;
933 
934 /*@unchecked@*/
935 static struct PreambleRec_s preambleList[] = {
936  {RPMTAG_NAME, 0, 0, "name"},
937  {RPMTAG_VERSION, 0, 0, "version"},
938  {RPMTAG_RELEASE, 0, 0, "release"},
939  {RPMTAG_DISTEPOCH, 0, 0, "distepoch"},
940  {RPMTAG_EPOCH, 0, 0, "epoch"},
941  {RPMTAG_EPOCH, 0, 1, "serial"},
942  {RPMTAG_SUMMARY, 1, 0, "summary"},
943  {RPMTAG_LICENSE, 0, 0, "copyright"},
944  {RPMTAG_LICENSE, 0, 0, "license"},
945  {RPMTAG_DISTRIBUTION, 0, 0, "distribution"},
946  {RPMTAG_DISTURL, 0, 0, "disturl"},
947  {RPMTAG_VENDOR, 0, 0, "vendor"},
948  {RPMTAG_GROUP, 1, 0, "group"},
949  {RPMTAG_PACKAGER, 0, 0, "packager"},
950  {RPMTAG_URL, 0, 0, "url"},
951  {RPMTAG_SOURCE, 0, 0, "source"},
952  {RPMTAG_PATCH, 0, 0, "patch"},
953  {RPMTAG_NOSOURCE, 0, 0, "nosource"},
954  {RPMTAG_NOPATCH, 0, 0, "nopatch"},
955  {RPMTAG_EXCLUDEARCH, 0, 0, "excludearch"},
956  {RPMTAG_EXCLUSIVEARCH, 0, 0, "exclusivearch"},
957  {RPMTAG_EXCLUDEOS, 0, 0, "excludeos"},
958  {RPMTAG_EXCLUSIVEOS, 0, 0, "exclusiveos"},
959  {RPMTAG_ICON, 0, 0, "icon"},
960  {RPMTAG_PROVIDEFLAGS, 0, 0, "provides"},
961  {RPMTAG_REQUIREFLAGS, 1, 0, "requires"},
962  {RPMTAG_PREREQ, 1, 0, "prereq"},
963  {RPMTAG_CONFLICTFLAGS, 0, 0, "conflicts"},
964  {RPMTAG_OBSOLETEFLAGS, 0, 0, "obsoletes"},
965  {RPMTAG_PREFIXES, 0, 0, "prefixes"},
966  {RPMTAG_PREFIXES, 0, 0, "prefix"},
967  {RPMTAG_BUILDROOT, 0, 0, "buildroot"},
968  {RPMTAG_BUILDARCHS, 0, 0, "buildarchitectures"},
969  {RPMTAG_BUILDARCHS, 0, 0, "buildarch"},
970  {RPMTAG_BUILDCONFLICTS, 0, 0, "buildconflicts"},
971  {RPMTAG_BUILDOBSOLETES, 0, 0, "buildobsoletes"},
972  {RPMTAG_BUILDPREREQ, 1, 0, "buildprereq"},
973  {RPMTAG_BUILDPROVIDES, 0, 0, "buildprovides"},
974  {RPMTAG_BUILDREQUIRES, 1, 0, "buildrequires"},
975  {RPMTAG_AUTOREQPROV, 0, 0, "autoreqprov"},
976  {RPMTAG_AUTOREQ, 0, 0, "autoreq"},
977  {RPMTAG_AUTOPROV, 0, 0, "autoprov"},
978  {RPMTAG_DOCDIR, 0, 0, "docdir"},
979  {RPMTAG_DISTTAG, 0, 0, "disttag"},
980  {RPMTAG_BUGURL, 0, 0, "bugurl"},
981  {RPMTAG_CVSID, 0, 0, "cvsid"},
982  {RPMTAG_SVNID, 0, 0, "svnid"},
983  {RPMTAG_SUGGESTSFLAGS, 0, 0, "suggests"},
984  {RPMTAG_ENHANCESFLAGS, 0, 0, "enhances"},
985  {RPMTAG_BUILDSUGGESTS, 0, 0, "buildsuggests"},
986  {RPMTAG_BUILDENHANCES, 0, 0, "buildenhances"},
987  {RPMTAG_VARIANTS, 0, 0, "variants"},
988  {RPMTAG_VARIANTS, 0, 0, "variant"},
989  {RPMTAG_XMAJOR, 0, 0, "xmajor"},
990  {RPMTAG_XMINOR, 0, 0, "xminor"},
991  {RPMTAG_REPOTAG, 0, 0, "repotag"},
992  {RPMTAG_KEYWORDS, 0, 0, "keywords"},
993  {RPMTAG_KEYWORDS, 0, 0, "keyword"},
994  {RPMTAG_BUILDPLATFORMS, 0, 0, "buildplatforms"},
995 #if defined(RPM_VENDOR_OPENPKG) /* make-class-available-as-macro */
996  {RPMTAG_CLASS, 0, 0, "class"},
997 #endif
998  /*@-nullassign@*/ /* LCL: can't add null annotation */
999  {0, 0, 0, 0}
1000  /*@=nullassign@*/
1001 };
1002 
1005 static int findPreambleTag(Spec spec, /*@out@*/rpmTag * tagp,
1006  /*@null@*/ /*@out@*/ const char ** macro, /*@out@*/ char * lang)
1007  /*@modifies *tagp, *macro, *lang @*/
1008 {
1009  PreambleRec p;
1010  char *s;
1011  size_t len = 0;
1012 
1013  /* Search for defined tags. */
1014  for (p = preambleList; p->token != NULL; p++) {
1015  len = strlen(p->token);
1016  if (!(p->token && !xstrncasecmp(spec->line, p->token, len)))
1017  continue;
1018  if (p->obsolete) {
1019  rpmlog(RPMLOG_ERR, _("Legacy syntax is unsupported: %s\n"),
1020  p->token);
1021  p = NULL;
1022  }
1023  break;
1024  }
1025  if (p == NULL)
1026  return 1;
1027 
1028  /* Search for arbitrary tags. */
1029  if (tagp && p->token == NULL) {
1030  ARGV_t aTags = NULL;
1031  int rc = 1; /* assume failure */
1032 
1033 /*@-noeffect@*/
1034  (void) tagName(0); /* XXX force arbitrary tags to be initialized. */
1035 /*@=noeffect@*/
1036  aTags = rpmTags->aTags;
1037  if (aTags != NULL && aTags[0] != NULL) {
1038  ARGV_t av;
1039  s = tagCanonicalize(spec->line);
1040 #if defined(RPM_VENDOR_OPENPKG) /* wildcard-matching-arbitrary-tagnames */
1041  av = argvSearchLinear(aTags, s, argvFnmatchCasefold);
1042 #else
1043  av = argvSearch(aTags, s, argvStrcasecmp);
1044 #endif
1045  if (av != NULL) {
1046  *tagp = tagGenerate(s);
1047  rc = 0;
1048  }
1049  s = _free(s);
1050  }
1051  return rc;
1052  }
1053 
1054  s = spec->line + len;
1055  SKIPSPACE(s);
1056 
1057  switch (p->multiLang) {
1058  default:
1059  case 0:
1060  /* Unless this is a source or a patch, a ':' better be next */
1061  if (p->tag != RPMTAG_SOURCE && p->tag != RPMTAG_PATCH) {
1062  if (*s != ':') return 1;
1063  }
1064  *lang = '\0';
1065  break;
1066  case 1: /* Parse optional ( <token> ). */
1067  if (*s == ':') {
1068  strcpy(lang, RPMBUILD_DEFAULT_LANG);
1069  break;
1070  }
1071  if (*s != '(') return 1;
1072  s++;
1073  SKIPSPACE(s);
1074  while (!xisspace(*s) && *s != ')')
1075  *lang++ = *s++;
1076  *lang = '\0';
1077  SKIPSPACE(s);
1078  if (*s != ')') return 1;
1079  s++;
1080  SKIPSPACE(s);
1081  if (*s != ':') return 1;
1082  break;
1083  }
1084 
1085  if (tagp)
1086  *tagp = p->tag;
1087  if (macro)
1088  /*@-onlytrans -observertrans -dependenttrans@*/ /* FIX: double indirection. */
1089  *macro = p->token;
1090  /*@=onlytrans =observertrans =dependenttrans@*/
1091  return 0;
1092 }
1093 
1094 /* XXX should return rpmParseState, but RPMRC_FAIL forces int return. */
1095 int parsePreamble(Spec spec, int initialPackage)
1096 {
1097  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
1098  rpmParseState nextPart;
1099  int xx;
1100  char *linep;
1101  Package pkg;
1102  char NVR[BUFSIZ];
1103  char lang[BUFSIZ];
1104  rpmRC rc;
1105 
1106  strcpy(NVR, "(main package)");
1107 
1108  pkg = newPackage(spec);
1109  if (spec->packages == NULL) {
1110  spec->packages = pkg;
1111 assert(initialPackage);
1112  } else if (! initialPackage) {
1113  char *name = NULL;
1114  rpmParseState flag;
1115  Package lastpkg;
1116 
1117  /* There is one option to %package: <pkg> or -n <pkg> */
1118  flag = PART_NONE;
1119  if (parseSimplePart(spec, &name, &flag)) {
1120  rpmlog(RPMLOG_ERR, _("Bad package specification: %s\n"),
1121  spec->line);
1122  pkg = freePackages(pkg);
1123  return RPMRC_FAIL;
1124  }
1125 
1126  lastpkg = NULL;
1127  if (lookupPackage(spec, name, flag, &lastpkg) == RPMRC_OK) {
1128  pkg->next = lastpkg->next;
1129  } else {
1130  /* Add package to end of list */
1131  for (lastpkg = spec->packages; lastpkg->next != NULL; lastpkg = lastpkg->next)
1132  {};
1133  }
1134 assert(lastpkg != NULL);
1135  lastpkg->next = pkg;
1136 
1137  /* Construct the package */
1138  if (flag == PART_SUBNAME) {
1139  he->tag = RPMTAG_NAME;
1140  xx = headerGet(spec->packages->header, he, 0);
1141  sprintf(NVR, "%s-%s", he->p.str, name);
1142  he->p.ptr = _free(he->p.ptr);
1143  } else
1144  strcpy(NVR, name);
1145  name = _free(name);
1146  he->tag = RPMTAG_NAME;
1147  he->t = RPM_STRING_TYPE;
1148  he->p.str = NVR;
1149  he->c = 1;
1150  xx = headerPut(pkg->header, he, 0);
1151  }
1152 
1153  if ((rc = readLine(spec, STRIP_TRAILINGSPACE | STRIP_COMMENTS)) > 0) {
1154  nextPart = PART_NONE;
1155  } else {
1156  if (rc)
1157  return rc;
1158  while ((nextPart = isPart(spec)) == PART_NONE) {
1159  const char * macro = NULL;
1160  rpmTag tag = 0;
1161 
1162  /* Skip blank lines */
1163  linep = spec->line;
1164  SKIPSPACE(linep);
1165  if (*linep != '\0') {
1166  if (findPreambleTag(spec, &tag, &macro, lang)) {
1167  rpmlog(RPMLOG_ERR, _("line %d: Unknown tag: %s\n"),
1168  spec->lineNum, spec->line);
1169  return RPMRC_FAIL;
1170  }
1171  if (handlePreambleTag(spec, pkg, tag, macro, lang))
1172  return RPMRC_FAIL;
1173  if (spec->BANames && !spec->recursing && spec->toplevel)
1174  return PART_BUILDARCHITECTURES;
1175  }
1176  if ((rc =
1178  nextPart = PART_NONE;
1179  break;
1180  }
1181  if (rc)
1182  return rc;
1183  }
1184  }
1185 
1186  /* Do some final processing on the header */
1187 
1188  /*
1189  * Expand buildroot one more time to get %{version} and the like
1190  * from the main package.
1191  */
1192  if (initialPackage) {
1193  const char *s = rpmExpand("%{?buildroot}", NULL);
1194  if (s && *s)
1195  (void) addMacro(NULL, "buildroot", NULL, s, -1);
1196  s = _free(s);
1197  }
1198 
1199  /* XXX Skip valid arch check if not building binary package */
1200  if (!spec->anyarch && checkForValidArchitectures(spec))
1201  return RPMRC_FAIL;
1202 
1203  if (pkg == spec->packages)
1204  fillOutMainPackage(pkg->header);
1205 
1206  if (checkForDuplicates(pkg->header, NVR) != RPMRC_OK)
1207  return RPMRC_FAIL;
1208 
1209  if (pkg != spec->packages)
1210  headerCopyTags(spec->packages->header, pkg->header,
1211  (void *)copyTagsDuringParse);
1212 
1213 #ifdef RPM_VENDOR_PLD /* rpm-epoch0 */
1214  /* Add Epoch: 0 to package header if it was not set by spec */
1215  he->tag = RPMTAG_NAME;
1216  if (headerGet(spec->packages->header, he, 0) == 0) {
1217  rpmuint32_t num = 0;
1218 
1219  he->tag = RPMTAG_EPOCH;
1220  he->t = RPM_UINT32_TYPE;
1221  he->p.ui32p = &num;
1222  he->c = 1;
1223  xx = headerPut(pkg->header, he, 0);
1224 
1225  /* also declare %{epoch} to be same */
1226  addMacro(spec->macros, "epoch", NULL, "0", RMIL_SPEC);
1227  }
1228 #endif /* RPM_VENDOR_PLD rpm-epoch0 */
1229 
1230  if (checkForRequired(pkg->header, NVR) != RPMRC_OK)
1231  return RPMRC_FAIL;
1232 
1233  return nextPart;
1234 }
rpmTagType t
Definition: rpmtag.h:505
const char * str
Definition: rpmtag.h:72
rpmTag tag
Definition: rpmtag.h:504
const char ** argv
Definition: rpmtag.h:74
miRE mireNew(rpmMireMode mode, int tag)
Create pattern container.
Definition: mire.c:113
rpmParseState isPart(Spec spec)
Check line for section separator, return next parser state.
Definition: parseSpec.c:68
int headerIsEntry(Header h, rpmTag tag)
Check if tag is in header.
Definition: header.c:1431
static rpmTag copyTagsDuringParse[]
Definition: parsePreamble.c:26
static rpmRC checkForRequired(Header h, const char *NVR)
Check that required tags are present in header.
Package next
Definition: rpmspec.h:248
enum urltype_e urltype
Supported URL types.
int noSource
Definition: rpmspec.h:159
Package newPackage(Spec spec)
Create and initialize package control structure.
Definition: spec.c:208
rpmsenseFlags bits
const char * ot_mac
char * xstrdup(const char *str)
Definition: rpmmalloc.c:322
spectag st_t
Definition: rpmspec.h:91
Package freePackages(Package packages)
Destroy all packages associated with spec file.
Definition: spec.c:245
struct tokenBits_s * tokenBits
rpmuint32_t * ui32p
Definition: rpmtag.h:69
FD_t Fopen(const char *path, const char *_fmode)
fopen(3) clone.
Definition: rpmio.c:2833
const char * rootURL
Definition: rpmspec.h:115
int headerGet(Header h, HE_t he, unsigned int flags)
Retrieve extension or tag value from a header.
Definition: header.c:2222
int headerPut(Header h, HE_t he, unsigned int flags)
Add or append tag container to header.
Definition: header.c:2285
int xstrncasecmp(const char *s1, const char *s2, size_t n)
Locale insensitive strncasecmp(3).
Definition: strcasecmp.c:30
int argvStrcasecmp(ARGstr_t *a, ARGstr_t *b)
Compare argv elements using strcasecmp (qsort/bsearch).
Definition: argv.c:102
The Header data structure.
int mireRegcomp(miRE mire, const char *pattern)
Compile pattern match.
Definition: mire.c:334
HeaderIterator headerFini(HeaderIterator hi)
Destroy header tag container iterator.
Definition: header.c:2125
int mireSetCOptions(miRE mire, rpmMireMode mode, int tag, int options, const unsigned char *table)
Initialize pattern compile options.
Definition: mire.c:121
rpmRC lookupPackage(Spec spec, const char *name, int flag, Package *pkg)
Find sub-package control structure by name.
Definition: spec.c:82
HeaderIterator headerInit(Header h)
Create header tag iterator.
Definition: header.c:2135
rpmuint32_t num
Definition: rpmspec.h:45
#define PART_NAME
Definition: rpmbuild.h:49
static int checkForValidArchitectures(Spec spec)
static char * findLastChar(char *s)
int addSource(Spec spec, Package pkg, const char *field, rpmTag tag)
addSource.
Definition: spec.c:365
Header sourceHeader
Definition: rpmspec.h:166
void addMacro(MacroContext mc, const char *n, const char *o, const char *b, int level)
Add macro to context.
Definition: macro.c:2684
struct Source * sources
Definition: rpmspec.h:157
static rpmRC checkForDuplicates(Header h, const char *NVR)
Check that no duplicate tags are present in header.
static int xisalpha(int c)
Definition: rpmiotypes.h:434
Header tag iterator data structure.
Definition: header.c:2120
static void rpmlog(int code, const char *fmt,...)
Definition: rpmlog.h:299
int noLang
Definition: poptBT.c:57
const char ** BANames
Definition: rpmspec.h:142
static struct tokenBits_s installScriptBits[]
int headerNext(HeaderIterator hi, HE_t he, unsigned int flags)
Return next tag from header.
Definition: header.c:2149
struct Source * next
Definition: rpmspec.h:47
int readLine(Spec spec, rpmStripFlags strip)
Read next line from spec file.
Definition: parseSpec.c:353
int t_tag
Definition: rpmspec.h:78
rpmTag tagValue(const char *tagstr)
Return tag value from name.
Definition: tagname.c:446
rpmTag tagGenerate(const char *s)
Generate a tag from arbitrary string.
Definition: tagname.c:456
const char * source
Definition: rpmspec.h:43
Definition: rpmspec.h:39
char * alloca()
static rpmRC handlePreambleTag(Spec spec, Package pkg, rpmTag tag, const char *macro, const char *lang)
Yet Another syslog(3) API clone.
Header header
Definition: rpmspec.h:210
unsigned int rpmuint32_t
Definition: rpmiotypes.h:25
struct _HE_s * HE_t
Definition: rpmtag.h:58
void delMacro(MacroContext mc, const char *n)
Delete macro from context.
Definition: macro.c:2723
miRE mireFree(miRE mire)
Free pattern container.
const char * Fstrerror(FD_t fd)
strerror(3) clone.
Definition: rpmio.c:2401
void * ptr
Definition: rpmtag.h:66
static rpmRC tagValidate(Spec spec, rpmTag tag, const char *value)
int parseNoSource(Spec spec, const char *field, rpmTag tag)
parseNoSource.
Definition: spec.c:321
int recursing
Definition: rpmspec.h:144
unsigned char rpmuint8_t
Private int typedefs to avoid C99 portability issues.
Definition: rpmiotypes.h:23
char * line
Definition: rpmspec.h:133
RPM pattern matching.
#define PART_SUBNAME
Definition: rpmbuild.h:48
enum evrFlags_e rpmsenseFlags
Definition: rpmevr.h:72
rpmTagData p
Definition: rpmtag.h:507
MacroContext macros
Definition: rpmspec.h:172
static int xisspace(int c)
Definition: rpmiotypes.h:446
static void addOrAppendListEntry(Header h, rpmTag tag, char *line)
Definition: parsePreamble.c:73
struct miRE_s * miRE
Definition: mire.h:60
const char * tagName(rpmTag tag)
Return tag name from value.
Definition: tagname.c:436
int t_startx
Definition: rpmspec.h:79
int autoProv
Definition: rpmspec.h:217
int anyarch
Definition: rpmspec.h:148
The FD_t File Handle data structure.
const char * rpmGenPath(const char *urlroot, const char *urlmdir, const char *urlfile)
Merge 3 args into path, any or all of which may be a url.
Definition: macro.c:3356
rpmTagCount c
Definition: rpmtag.h:508
static const char * lang
int mireRegexec(miRE mire, const char *val, size_t vallen)
Execute pattern match.
Definition: mire.c:398
int xstrcasecmp(const char *s1, const char *s2)
Locale insensitive strcasecmp(3).
Definition: strcasecmp.c:9
The structure used to store values parsed from a spec file.
Definition: rpmspec.h:108
char * rpmExpand(const char *arg,...)
Return (malloc&#39;ed) concatenated macro expansion(s).
Definition: macro.c:3117
const char * t_lang
Definition: rpmspec.h:82
size_t Fread(void *buf, size_t size, size_t nmemb, FD_t fd)
fread(3) clone.
Definition: rpmio.c:2412
rpmuint8_t * ui8p
Definition: rpmtag.h:67
int parsePreamble(Spec spec, int initialPackage)
Parse tags from preamble of a spec file.
int Fclose(FD_t fd)
fclose(3) clone.
Definition: rpmio.c:2534
spectag stashSt(Spec spec, Header h, rpmTag tag, const char *lang)
stashSt.
static int parseSimplePart(Spec spec, char **Np, rpmParseState *flag)
Definition: parsePreamble.c:99
static rpmTag requiredTags[]
Definition: parsePreamble.c:61
static int isMemberInEntry(Header h, const char *name, rpmTag tag)
static struct optionalTag optionalTags[]
static int parseBits(const char *s, const tokenBits tokbits, rpmsenseFlags *bp)
#define SINGLE_TOKEN_ONLY
spectags st
Definition: rpmspec.h:120
int BACount
Definition: rpmspec.h:143
int noarch
Definition: rpmspec.h:218
#define RMIL_SPEC
Definition: rpmmacro.h:56
enum rpmRC_e rpmRC
RPM return codes.
int Ferror(FD_t fd)
ferror(3) clone.
Definition: rpmio.c:2944
Package packages
Definition: rpmspec.h:197
Definition: rpmtag.h:503
int parseNum(const char *line, rpmuint32_t *res)
Parse a number.
Definition: misc.c:11
const char * t_msgid
Definition: rpmspec.h:84
void headerCopyTags(Header headerFrom, Header headerTo, rpmTag *tagstocopy)
Duplicate tag values from one header into another.
Definition: header.c:2202
urltype urlPath(const char *url, const char **pathp)
Return path component of URL.
Definition: url.c:429
This is the only module users of librpmbuild should need to include.
static int doIcon(Spec spec, Header h)
static struct PreambleRec_s preambleList[]
static struct tokenBits_s buildScriptBits[]
static void * _free(const void *p)
Wrapper to free(3), hides const compilation noise, permit NULL, return NULL.
Definition: rpmiotypes.h:647
static void fillOutMainPackage(Header h)
char * tagCanonicalize(const char *s)
Canonicalize a rpmTag string.
Definition: tagname.c:451
rpmRC parseRCPOT(Spec spec, Package pkg, const char *field, rpmTag tagN, rpmuint32_t index, rpmsenseFlags tagflags)
Parse dependency relations from spec file and/or autogenerated output buffer.
Definition: parseReqs.c:20
#define RPMTAG_SVNID
Definition: rpmtag.h:356
#define F_OK
Definition: system.h:216
int t_nlines
Definition: rpmspec.h:80
enum rpmParseState_e rpmParseState
int lineNum
Definition: rpmspec.h:134
static int parseYesNo(const char *s)
ARGV_t argvSearch(ARGV_t argv, ARGstr_t val, int(*compar)(ARGstr_t *, ARGstr_t *))
Find an element in an argv array.
Definition: argv.c:146
headerTagIndices rpmTags
Definition: tagname.c:184
static int findPreambleTag(Spec spec, rpmTag *tagp, const char **macro, char *lang)
#define _(Text)
Definition: system.h:30
The structure used to store values for a package.
Definition: rpmspec.h:207
#define RMIL_OLDSPEC
Definition: rpmmacro.h:57
ARGstr_t * ARGV_t
Definition: argv.h:9
int st_nalloc
Definition: rpmspec.h:92
enum rpmTag_e rpmTag
Definition: rpmtag.h:471
#define SKIPSPACE(s)
Definition: rpmbuild.h:45
#define RPMBUILD_DEFAULT_LANG
Definition: rpmspec.h:35
int st_ntags
Definition: rpmspec.h:93
int toplevel
Definition: rpmspec.h:145
const char * token
const char * name
int rpmExpandNumeric(const char *arg)
Return macro expansion as a numeric value.
Definition: macro.c:3191
struct PreambleRec_s * PreambleRec
int flags
Definition: rpmspec.h:44
#define xrealloc
Definition: system.h:36
rpmuint32_t rpmTagCount
Definition: rpmtag.h:54
#define SKIPNONSPACE(s)
Definition: rpmbuild.h:46
int autoReq
Definition: rpmspec.h:216
unsigned int append
Definition: rpmtag.h:512