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