rpm  5.4.15
parsePrep.c
Go to the documentation of this file.
1 
6 #include "system.h"
7 
8 #include <rpmio.h>
9 #include <rpmiotypes.h>
10 #include <argv.h>
11 #include <rpmcb.h>
12 #include <rpmurl.h>
13 #ifdef NOTYET
14 #include <rpmmg.h>
15 #endif
16 
17 #include <rpmbuild.h>
18 
19 #include "misc.h" /* XXX rpmMkdirPath */
20 #include "debug.h"
21 
22 /* These have to be global to make up for stupid compilers */
23 /*@unchecked@*/
25 /*@unchecked@*/
26  static int createDir, quietly;
27 /*@unchecked@*/ /*@observer@*/ /*@null@*/
28  static const char * dirName = NULL;
29 /*@unchecked@*/ /*@observer@*/
30  static struct poptOption optionsTable[] = {
31  { NULL, 'a', POPT_ARG_STRING, NULL, 'a', NULL, NULL},
32  { NULL, 'b', POPT_ARG_STRING, NULL, 'b', NULL, NULL},
33  { NULL, 'c', 0, &createDir, 0, NULL, NULL},
34  { NULL, 'D', 0, &leaveDirs, 0, NULL, NULL},
35  { NULL, 'n', POPT_ARG_STRING, &dirName, 0, NULL, NULL},
36  { NULL, 'T', 0, &skipDefaultAction, 0, NULL, NULL},
37  { NULL, 'q', 0, &quietly, 0, NULL, NULL},
38  { 0, 0, 0, 0, 0, NULL, NULL}
39  };
40 
46 static rpmRC checkOwners(const char * urlfn)
47  /*@globals h_errno, fileSystem, internalState @*/
48  /*@modifies fileSystem, internalState @*/
49 {
50  struct stat sb;
51 
52  if (Lstat(urlfn, &sb)) {
53  rpmlog(RPMLOG_ERR, _("Bad source: %s: %s\n"),
54  urlfn, strerror(errno));
55  return RPMRC_FAIL;
56  }
57  if (!getUname(sb.st_uid) || !getGname(sb.st_gid)) {
58  rpmlog(RPMLOG_ERR, _("Bad owner/group: %s\n"), urlfn);
59  return RPMRC_FAIL;
60  }
61 
62  return RPMRC_OK;
63 }
64 
65 #ifndef DYING
66 
78 /*@observer@*/
79 static char *doPatch(Spec spec, rpmuint32_t c, int strip, const char *db,
80  int reverse, int removeEmpties, int fuzz, const char *subdir)
81  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
82  /*@modifies rpmGlobalMacroContext, fileSystem, internalState @*/
83 {
84  const char *fn, *Lurlfn;
85  static char buf[BUFSIZ];
86  char args[BUFSIZ], *t = args;
87  struct Source *sp;
89  int urltype;
90  const char *patch, *flags;
91 
92  *t = '\0';
93  if (db)
94  t = stpcpy( stpcpy(t, "-b --suffix "), db);
95 #if defined(RPM_VENDOR_OPENPKG) /* always-backup-on-patching */
96  /* always create backup files in OpenPKG */
97  else
98  t = stpcpy(t, "-b --suffix .orig ");
99 #endif
100  if (subdir)
101  t = stpcpy( stpcpy(t, "-d "), subdir);
102  if (fuzz >= 0) {
103  t = stpcpy(t, "-F ");
104  sprintf(t, "%10.10d", fuzz);
105  t += strlen(t);
106  }
107  if (reverse)
108  t = stpcpy(t, " -R");
109  if (removeEmpties)
110  t = stpcpy(t, " -E");
111 
112  for (sp = spec->sources; sp != NULL; sp = sp->next) {
113  if ((sp->flags & RPMFILE_PATCH) && (sp->num == c))
114  break;
115  }
116  if (sp == NULL) {
117  rpmlog(RPMLOG_ERR, _("No patch number %d\n"), c);
118  return NULL;
119  }
120 
121  Lurlfn = rpmGenPath(NULL, "%{_patchdir}/", sp->source);
122 
123  /* XXX On non-build parse's, file cannot be stat'd or read */
124  if (!spec->force && (isCompressed(Lurlfn, &compressed) || checkOwners(Lurlfn))) {
125  Lurlfn = _free(Lurlfn);
126  return NULL;
127  }
128 
129  fn = NULL;
130  urltype = urlPath(Lurlfn, &fn);
131  switch (urltype) {
132  case URL_IS_HTTPS: /* XXX WRONG WRONG WRONG */
133  case URL_IS_HTTP: /* XXX WRONG WRONG WRONG */
134  case URL_IS_FTP: /* XXX WRONG WRONG WRONG */
135  case URL_IS_HKP: /* XXX WRONG WRONG WRONG */
136  case URL_IS_MONGO: /* XXX FIXME */
137  case URL_IS_PATH:
138  case URL_IS_UNKNOWN:
139  break;
140  case URL_IS_DASH:
141  Lurlfn = _free(Lurlfn);
142  return NULL;
143  /*@notreached@*/ break;
144  }
145 
146  patch = rpmGetPath("%{?__patch}", NULL);
147  if (!(patch && *patch != '\0')) {
148  patch = _free(patch);
149  patch = xstrdup("patch");
150  }
151 
152  flags = rpmExpand("%{?_default_patch_flags}%{!?_default_patch_flags:-s}", NULL);
153 
154  if (compressed) {
155  const char *zipper;
156 
157  switch (compressed) {
158  default:
159  case COMPRESSED_NOT: /* XXX can't happen */
160  case COMPRESSED_OTHER:
161  case COMPRESSED_ZIP: /* XXX wrong */
162  zipper = "%{__gzip}";
163  break;
164  case COMPRESSED_BZIP2:
165  zipper = "%{__bzip2}";
166  break;
167  case COMPRESSED_LZOP:
168  zipper = "%{__lzop}";
169  break;
170  case COMPRESSED_LZMA:
171  zipper = "%{__lzma}";
172  break;
173  case COMPRESSED_XZ:
174  zipper = "%{__xz}";
175  break;
176  }
177  zipper = rpmGetPath(zipper, NULL);
178 
179  sprintf(buf,
180  "echo \"Patch #%d (%s):\"\n"
181  "%s -d < '%s' | %s -p%d %s %s\n"
182  "STATUS=$?\n"
183  "if [ $STATUS -ne 0 ]; then\n"
184  " exit $STATUS\n"
185  "fi",
186  c,
187 /*@-moduncon@*/
188  (const char *) basename((char *)fn),
189 /*@=moduncon@*/
190  zipper,
191  fn, patch, strip, args, flags);
192  zipper = _free(zipper);
193  } else {
194  sprintf(buf,
195  "echo \"Patch #%d (%s):\"\n"
196  "%s -p%d %s %s < '%s'", c,
197 /*@-moduncon@*/
198  (const char *) basename((char *)fn),
199 /*@=moduncon@*/
200  patch, strip, args, flags, fn);
201  }
202 
203  patch = _free(patch);
204  flags = _free(flags);
205  Lurlfn = _free(Lurlfn);
206  return buf;
207 }
208 #endif
209 
217 /*@observer@*/
218 static const char *doUntar(Spec spec, rpmuint32_t c, int quietly)
219  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
220  /*@modifies rpmGlobalMacroContext, fileSystem, internalState @*/
221 {
222  const char *fn, *Lurlfn;
223  static char buf[BUFSIZ];
224  char taropts[8];
225  char *t = NULL;
226  struct Source *sp;
227  rpmCompressedMagic compressed = COMPRESSED_NOT;
228  int urltype;
229  const char *tar;
230  int rubygem = 0;
231 
232  for (sp = spec->sources; sp != NULL; sp = sp->next) {
233  if ((sp->flags & RPMFILE_SOURCE) && (sp->num == c)) {
234  break;
235  }
236  }
237  if (sp == NULL) {
238  rpmlog(RPMLOG_ERR, _("No source number %d\n"), c);
239  return NULL;
240  }
241 
242  t = strrchr(sp->source, '.');
243  if(t && !strcasecmp(t, ".gem"))
244  rubygem = 1;
245 
246  t = stpcpy(taropts, "-x");
247  /*@-internalglobs@*/ /* FIX: shrug */
248  if(rpmIsVerbose() && !quietly)
249  t = stpcpy(t, "vv");
250  if(rubygem)
251  t = stpcpy(t, "m");
252 
253  t = stpcpy(t, "f");
254  /*@=internalglobs@*/
255 
256 #if defined(RPM_VENDOR_OPENPKG) /* splitted-source-directory */
257  Lurlfn = rpmGenPath(NULL, getSourceDir(sp->flags, sp->source), sp->source);
258 #else
259  Lurlfn = rpmGenPath(NULL, getSourceDir(sp->flags), sp->source);
260 #endif
261 
262  /* XXX On non-build parse's, file cannot be stat'd or read */
263  if (!spec->force && (isCompressed(Lurlfn, &compressed) || checkOwners(Lurlfn))) {
264  Lurlfn = _free(Lurlfn);
265  return NULL;
266  }
267 
268  fn = NULL;
269  urltype = urlPath(Lurlfn, &fn);
270  switch (urltype) {
271  case URL_IS_HTTPS: /* XXX WRONG WRONG WRONG */
272  case URL_IS_HTTP: /* XXX WRONG WRONG WRONG */
273  case URL_IS_FTP: /* XXX WRONG WRONG WRONG */
274  case URL_IS_HKP: /* XXX WRONG WRONG WRONG */
275  case URL_IS_MONGO: /* XXX FIXME */
276  case URL_IS_PATH:
277  case URL_IS_UNKNOWN:
278  break;
279  case URL_IS_DASH:
280  Lurlfn = _free(Lurlfn);
281  return NULL;
282  /*@notreached@*/ break;
283  }
284 #ifdef NOTYET
285  { rpmmg mg;
286 
287 _rpmmg_debug = 1;
288  mg = rpmmgNew(NULL, 0);
289  t = (char *) rpmmgFile(mg, fn);
290  mg = rpmmgFree(mg);
291 fprintf(stderr, "==> %s: %s\n", fn, t);
292  t = _free(t);
293 _rpmmg_debug = 0;
294  }
295 #endif
296 
297  tar = rpmGetPath("%{?__tar}", NULL);
298  if (!(tar && *tar != '\0')) {
299  tar = _free(tar);
300  tar = xstrdup("tar");
301  }
302 
303 #if defined(RPM_VENDOR_ARK) /* use-gnu-tar-compression-detection */
304 /* We leave compression handling for all tar based files up to GNU tar */
305  if (compressed == COMPRESSED_ZIP)
306 #else
307  if (compressed != COMPRESSED_NOT)
308 #endif
309  {
310  const char *zipper;
311  int needtar = 1;
312 
313  switch (compressed) {
314  case COMPRESSED_NOT: /* XXX can't happen */
315  case COMPRESSED_OTHER:
316  t = "%{__gzip} -dc";
317  break;
318  case COMPRESSED_BZIP2:
319  t = "%{__bzip2} -dc";
320  break;
321  case COMPRESSED_LZOP:
322  t = "%{__lzop} -dc";
323  break;
324  case COMPRESSED_LZMA:
325  t = "%{__lzma} -dc";
326  break;
327  case COMPRESSED_XZ:
328  t = "%{__xz} -dc";
329  break;
330  case COMPRESSED_LZIP:
331  t = "%{__lzip} -dc";
332  break;
333  case COMPRESSED_LRZIP:
334  t = "%{__lrzip} -dqo-";
335  break;
336  case COMPRESSED_7ZIP:
337  t = "%{__7zip} x";
338  needtar = 0;
339  break;
340  case COMPRESSED_ZIP:
341 #if defined(RPM_VENDOR_OPENPKG) /* use-bsdtar-for-zip-files */
342  t = "%{__bsdtar} -x -f";
343 #else
344  if (rpmIsVerbose() && !quietly)
345  t = "%{__unzip}";
346  else
347  t = "%{__unzip} -qq";
348 #endif
349  needtar = 0;
350  break;
351  }
352  zipper = rpmGetPath(t, NULL);
353  buf[0] = '\0';
354  t = stpcpy(buf, zipper);
355  zipper = _free(zipper);
356  *t++ = ' ';
357  *t++ = '\'';
358  t = stpcpy(t, fn);
359  *t++ = '\'';
360  if (needtar) {
361  t = stpcpy(t, " | ");
362  t = stpcpy(t, tar);
363  t = stpcpy(t, " ");
364  t = stpcpy(t, taropts);
365  t = stpcpy(t, " -");
366  }
367  t = stpcpy(t,
368  "\n"
369  "STATUS=$?\n"
370  "if [ $STATUS -ne 0 ]; then\n"
371  " exit $STATUS\n"
372  "fi");
373  } else {
374  buf[0] = '\0';
375  t = stpcpy(buf, tar);
376  t = stpcpy(t, " ");
377  t = stpcpy(t, taropts);
378  *t++ = ' ';
379  t = stpcpy(t, fn);
380  if(rubygem) {
381  t = stpcpy(t,
382  "\n"
383  "if [ -f data.tar.gz ]; then\n"
384  " tar ");
385  t = stpcpy(t, taropts);
386  t = stpcpy(t,
387  " data.tar.gz\n"
388  "fi");
389  }
390  }
391 
392  tar = _free(tar);
393  Lurlfn = _free(Lurlfn);
394  return buf;
395 }
396 
404 static int doSetupMacro(Spec spec, const char * line)
405  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
406  /*@modifies spec->buildSubdir, spec->macros, spec->prep,
407  spec->packages->header,
408  rpmGlobalMacroContext, fileSystem, internalState @*/
409 {
410  char buf[BUFSIZ];
411  rpmiob before = NULL;
412  rpmiob after = NULL;
413  poptContext optCon;
414  int argc;
415  const char ** argv;
416  int arg;
417  const char * optArg;
418  int rc;
420  rpmRC ec = RPMRC_FAIL; /* XXX assume failure */
421 
422  /*@-mods@*/
424  createDir = quietly = 0;
425  dirName = NULL;
426  /*@=mods@*/
427 
428  if ((rc = poptParseArgvString(line, &argc, &argv))) {
429  rpmlog(RPMLOG_ERR, _("Error parsing %%setup: %s\n"),
430  poptStrerror(rc));
431  goto exit;
432  }
433 
434  before = rpmiobNew(0);
435  after = rpmiobNew(0);
436 
437  optCon = poptGetContext(NULL, argc, argv, optionsTable, 0);
438  while ((arg = poptGetNextOpt(optCon)) > 0) {
439  optArg = poptGetOptArg(optCon);
440 
441  /* We only parse -a and -b here */
442 
443  if (parseNum(optArg, &num)) {
444  rpmlog(RPMLOG_ERR, _("line %d: Bad arg to %%setup: %s\n"),
445  spec->lineNum, (optArg ? optArg : "???"));
446  optCon = poptFreeContext(optCon);
447  argv = _free(argv);
448  goto exit;
449  }
450 
451  { const char *chptr = doUntar(spec, num, quietly);
452  if (chptr == NULL)
453  goto exit;
454 
455  (void) rpmiobAppend((arg == 'a' ? after : before), chptr, 1);
456  }
457  }
458 
459  if (arg < -1) {
460  rpmlog(RPMLOG_ERR, _("line %d: Bad %%setup option %s: %s\n"),
461  spec->lineNum,
462  poptBadOption(optCon, POPT_BADOPTION_NOALIAS),
463  poptStrerror(arg));
464  optCon = poptFreeContext(optCon);
465  argv = _free(argv);
466  goto exit;
467  }
468 
469  if (dirName) {
470  spec->buildSubdir = xstrdup(dirName);
471  } else {
472  const char *N, *V;
473  (void) headerNEVRA(spec->packages->header, &N, NULL, &V, NULL, NULL);
474  (void) snprintf(buf, sizeof(buf), "%s-%s", N, V);
475  buf[sizeof(buf)-1] = '\0';
476  N = _free(N);
477  V = _free(V);
478  spec->buildSubdir = xstrdup(buf);
479  }
480  addMacro(spec->macros, "buildsubdir", NULL, spec->buildSubdir, RMIL_SPEC);
481 
482  optCon = poptFreeContext(optCon);
483  argv = _free(argv);
484 
485  /* cd to the build dir */
486  { const char * buildDirURL = rpmGenPath(spec->rootURL, "%{_builddir}", "");
487  const char *buildDir;
488 
489  (void) urlPath(buildDirURL, &buildDir);
490  rc = rpmioMkpath(buildDir, 0755, -1, -1);
491  sprintf(buf, "cd '%s'", buildDir);
492  spec->prep = rpmiobAppend(spec->prep, buf, 1);
493  buildDirURL = _free(buildDirURL);
494  }
495 
496  /* delete any old sources */
497  if (!leaveDirs) {
498  sprintf(buf, "rm -rf '%s'", spec->buildSubdir);
499  spec->prep = rpmiobAppend(spec->prep, buf, 1);
500  }
501 
502  /* check if source is a ruby gem */
503  { struct Source *sp;
504  for (sp = spec->sources; sp != NULL; sp = sp->next) {
505  if ((sp->flags & RPMFILE_SOURCE) && (sp->num == 0)) {
506  break;
507  }
508  }
509  if (sp != NULL) {
510  char *t = strrchr(sp->source, '.');
511  if(t && !strcasecmp(t, ".gem"))
512  createDir = 1;
513  }
514  }
515 
516  /* if necessary, create and cd into the proper dir */
517  if (createDir) {
518  char *mkdir_p;
519  mkdir_p = rpmExpand("%{?__mkdir_p}%{!?__mkdir_p:mkdir -p}", NULL);
520  if (!mkdir_p)
521  mkdir_p = xstrdup("mkdir -p");
522  sprintf(buf, "%s '%s'\ncd '%s'",
523  mkdir_p, spec->buildSubdir, spec->buildSubdir);
524  mkdir_p = _free(mkdir_p);
525  spec->prep = rpmiobAppend(spec->prep, buf, 1);
526  }
527 
528  /* do the default action */
529  if (!createDir && !skipDefaultAction) {
530  const char *chptr = doUntar(spec, 0, quietly);
531  if (chptr == NULL)
532  goto exit;
533  spec->prep = rpmiobAppend(spec->prep, chptr, 1);
534  }
535 
536  spec->prep = rpmiobAppend(spec->prep, rpmiobStr(before), 0);
537 
538  if (!createDir) {
539  sprintf(buf, "cd '%s'", spec->buildSubdir);
540  spec->prep = rpmiobAppend(spec->prep, buf, 1);
541  }
542 
543  if (createDir && !skipDefaultAction) {
544  const char * chptr = doUntar(spec, 0, quietly);
545  if (chptr == NULL)
546  goto exit;
547  spec->prep = rpmiobAppend(spec->prep, chptr, 1);
548  }
549 
550  spec->prep = rpmiobAppend(spec->prep, rpmiobStr(after), 0);
551 
552  /* XXX FIXME: owner & group fixes were conditioned on !geteuid() */
553  /* Fix the owner, group, and permissions of the setup build tree */
554  { /*@observer@*/ static const char *fixmacs[] =
555  { "%{_fixowner}", "%{_fixgroup}", "%{_fixperms}", NULL };
556  const char ** fm;
557 
558  for (fm = fixmacs; *fm; fm++) {
559  const char *fix;
560  fix = rpmExpand(*fm, " .", NULL);
561  if (fix && *fix != '%')
562  spec->prep = rpmiobAppend(spec->prep, fix, 1);
563  fix = _free(fix);
564  }
565  }
566  ec = RPMRC_OK;
567 
568 exit:
569  before = rpmiobFree(before);
570  after = rpmiobFree(after);
571  return ec;
572 }
573 
574 #ifndef DYING
575 
581 static rpmRC doPatchMacro(Spec spec, const char * line)
582  /*@globals rpmGlobalMacroContext, h_errno,
583  fileSystem, internalState @*/
584  /*@modifies spec->prep, rpmGlobalMacroContext,
585  fileSystem, internalState @*/
586 {
587  char *s;
588  char *opt_b;
589  char *opt_d;
590  rpmuint32_t opt_P, opt_p, opt_R, opt_E, opt_F;
591  char buf[BUFSIZ], *bp;
592  rpmuint32_t patch_nums[1024]; /* XXX - we can only handle 1024 patches! */
593  int patch_index, x;
594 
595  memset(patch_nums, 0, sizeof(patch_nums));
596  opt_P = opt_p = opt_R = opt_E = 0;
597  opt_F = rpmExpandNumeric("%{?_default_patch_fuzz}%{!?_default_patch_fuzz:-1}");
598  opt_b = NULL;
599  opt_d = NULL;
600  patch_index = 0;
601 
602  if (! strchr(" \t\n", line[6])) {
603  /* %patchN */
604  sprintf(buf, "%%patch -P %s", line + 6);
605  } else {
606  strncpy(buf, line, sizeof(buf)-1);
607  buf[sizeof(buf)-1] = '\0';
608  }
609 
610  /*@-internalglobs@*/ /* FIX: strtok has state */
611  for (bp = buf; (s = strtok(bp, " \t\n")) != NULL;) {
612  if (bp) { /* remove 1st token (%patch) */
613  bp = NULL;
614  continue;
615  }
616  if (!strcmp(s, "-P")) {
617  opt_P = 1;
618  } else if (!strcmp(s, "-R")) {
619  opt_R = 1;
620  } else if (!strcmp(s, "-E")) {
621  opt_E = 1;
622  } else if (!strcmp(s, "-b")) {
623  /* orig suffix */
624  opt_b = strtok(NULL, " \t\n");
625  if (! opt_b) {
627  _("line %d: Need arg to %%patch -b: %s\n"),
628  spec->lineNum, spec->line);
629  return RPMRC_FAIL;
630  }
631  } else if (!strcmp(s, "-z")) {
632  /* orig suffix */
633  opt_b = strtok(NULL, " \t\n");
634  if (! opt_b) {
636  _("line %d: Need arg to %%patch -z: %s\n"),
637  spec->lineNum, spec->line);
638  return RPMRC_FAIL;
639  }
640  } else if (!strcmp(s, "-F")) {
641  /* fuzz factor */
642  const char * fnum = (!strchr(" \t\n", s[2])
643  ? s+2 : strtok(NULL, " \t\n"));
644  char * end = NULL;
645 
646  opt_F = (fnum ? strtol(fnum, &end, 10) : 0);
647  if (! opt_F || *end) {
649  _("line %d: Bad arg to %%patch -F: %s\n"),
650  spec->lineNum, spec->line);
651  return RPMRC_FAIL;
652  }
653  } else if (!strcmp(s, "-d")) {
654  /* subdirectory */
655  opt_d = strtok(NULL, " \t\n");
656  if (! opt_d) {
658  _("line %d: Need arg to %%patch -d: %s\n"),
659  spec->lineNum, spec->line);
660  return RPMRC_FAIL;
661  }
662  } else if (!strncmp(s, "-p", sizeof("-p")-1)) {
663  /* unfortunately, we must support -pX */
664  if (! strchr(" \t\n", s[2])) {
665  s = s + 2;
666  } else {
667  s = strtok(NULL, " \t\n");
668  if (s == NULL) {
670  _("line %d: Need arg to %%patch -p: %s\n"),
671  spec->lineNum, spec->line);
672  return RPMRC_FAIL;
673  }
674  }
675  if (parseNum(s, &opt_p)) {
677  _("line %d: Bad arg to %%patch -p: %s\n"),
678  spec->lineNum, spec->line);
679  return RPMRC_FAIL;
680  }
681  } else {
682  /* Must be a patch num */
683  if (patch_index == 1024) {
684  rpmlog(RPMLOG_ERR, _("Too many patches!\n"));
685  return RPMRC_FAIL;
686  }
687  if (parseNum(s, &(patch_nums[patch_index]))) {
688  rpmlog(RPMLOG_ERR, _("line %d: Bad arg to %%patch: %s\n"),
689  spec->lineNum, spec->line);
690  return RPMRC_FAIL;
691  }
692  patch_index++;
693  }
694  }
695  /*@=internalglobs@*/
696 
697  /* All args processed */
698 
699  if (! opt_P) {
700  s = doPatch(spec, 0, opt_p, opt_b, opt_R, opt_E, opt_F, opt_d);
701  if (s == NULL)
702  return RPMRC_FAIL;
703  spec->prep = rpmiobAppend(spec->prep, s, 1);
704  }
705 
706  for (x = 0; x < patch_index; x++) {
707  s = doPatch(spec, patch_nums[x], opt_p, opt_b, opt_R, opt_E, opt_F, opt_d);
708  if (s == NULL)
709  return RPMRC_FAIL;
710  spec->prep = rpmiobAppend(spec->prep, s, 1);
711  }
712 
713  return RPMRC_OK;
714 }
715 #endif
716 
717 static void prepFetchVerbose(/*@unused@*/ struct Source *sp,
718  /*@unused@*/ struct stat *st)
719  /*@globals internalState @*/
720  /*@modifies internalState @*/
721 {
722  char *buf;
723  size_t buf_len;
724  int xx;
725  int i;
726 
728  return;
729  buf_len = 2*80;
730  if ((buf = (char *)malloc(buf_len)) == NULL)
731  return;
732  xx = snprintf(buf, buf_len, "%s%d:", (sp->flags & RPMFILE_SOURCE) ? "Source" : "Patch", sp->num);
733  for (i = (int)strlen(buf); i <= 11; i++)
734  buf[i] = ' ';
735  xx = snprintf(buf+i, buf_len-i, "%-52.52s", sp->source);
736  i = (int)strlen(buf);
737  if (st != NULL)
738  xx = snprintf(buf+i, buf_len-i, " %9lu Bytes\n", (unsigned long)st->st_size);
739  else
740  xx = snprintf(buf+i, buf_len-i, " ...MISSING\n");
741  rpmlog(RPMLOG_NOTICE, "%s", buf);
742  buf = _free(buf);
743  return;
744 }
745 
749 static int prepFetch(Spec spec)
750  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
751  /*@modifies rpmGlobalMacroContext, fileSystem, internalState @*/
752 {
753 #if defined(RPM_VENDOR_OPENPKG) /* splitted-source-directory */
754  const char *Smacro;
755 #endif
756  const char *Lmacro, *Lurlfn = NULL;
757  const char *Rmacro, *Rurlfn = NULL;
758  struct Source *sp;
759  struct stat st;
760  rpmRC rpmrc;
761  int ec, rc;
762  char *cp;
763 
764  /* XXX insure that %{_sourcedir} exists */
765  rpmrc = RPMRC_OK;
766  Lurlfn = rpmGenPath(NULL, "%{?_sourcedir}", NULL);
767  if (Lurlfn != NULL && *Lurlfn != '\0')
768  rpmrc = rpmMkdirPath(Lurlfn, "_sourcedir");
769  Lurlfn = _free(Lurlfn);
770  if (rpmrc != RPMRC_OK)
771  return -1;
772 
773  /* XXX insure that %{_patchdir} exists */
774  rpmrc = RPMRC_OK;
775  Lurlfn = rpmGenPath(NULL, "%{?_patchdir}", NULL);
776  if (Lurlfn != NULL && *Lurlfn != '\0')
777  rpmrc = rpmMkdirPath(Lurlfn, "_patchdir");
778  Lurlfn = _free(Lurlfn);
779  if (rpmrc != RPMRC_OK)
780  return -1;
781 
782  /* XXX insure that %{_icondir} exists */
783  rpmrc = RPMRC_OK;
784  Lurlfn = rpmGenPath(NULL, "%{?_icondir}", NULL);
785  if (Lurlfn != NULL && *Lurlfn != '\0')
786  rpmrc = rpmMkdirPath(Lurlfn, "_icondir");
787  Lurlfn = _free(Lurlfn);
788  if (rpmrc != RPMRC_OK)
789  return -1;
790 
792  rpmlog(RPMLOG_NOTICE, "Checking source and patch file(s):\n");
793 
794  ec = 0;
795  for (sp = spec->sources; sp != NULL; sp = sp->next) {
796 
797 #if defined(RPM_VENDOR_OPENPKG) /* splitted-source-directory */
798  Smacro = "%{?_specdir}/";
799 #endif
800 #if defined(RPM_VENDOR_OPENPKG) /* splitted-source-directory */
801  if (! (Lmacro = getSourceDir(sp->flags, sp->source)))
802 #else
803  if (! (Lmacro = getSourceDir(sp->flags)))
804 #endif
805  continue;
806  if (sp->flags & RPMFILE_SOURCE) {
807  Rmacro = "%{?_Rsourcedir}/";
808  } else
809  if (sp->flags & RPMFILE_PATCH) {
810  Rmacro = "%{?_Rpatchdir}/";
811  } else
812  if (sp->flags & RPMFILE_ICON) {
813  Rmacro = "%{?_Ricondir}/";
814  } else
815  continue;
816 
817 #if defined(RPM_VENDOR_OPENPKG) /* splitted-source-directory */
818  /* support splitted source directories, i.e., source files which
819  are alternatively placed into the .spec directory and picked
820  up from there, too. */
821  Lurlfn = rpmGenPath(NULL, Smacro, sp->source);
822  rc = Lstat(Lurlfn, &st);
823  if (rc == 0) {
824  prepFetchVerbose(sp, &st);
825  goto bottom;
826  }
827 #endif
828  Lurlfn = rpmGenPath(NULL, Lmacro, sp->source);
829  rc = Lstat(Lurlfn, &st);
830  if (rc == 0) {
831 /*@-noeffect@*/
832  prepFetchVerbose(sp, &st);
833 /*@=noeffect@*/
834  goto bottom;
835  }
836 /*@-noeffect@*/
837  prepFetchVerbose(sp, NULL);
838 /*@=noeffect@*/
839  if (errno != ENOENT) {
840  ec++;
841  rpmlog(RPMLOG_ERR, _("Missing %s%d %s: %s\n"),
842  ((sp->flags & RPMFILE_SOURCE) ? "Source" : "Patch"),
843  sp->num, sp->source, strerror(ENOENT));
844  goto bottom;
845  }
846 
847  /* try to fetch via macro-controlled remote locations */
848  cp = rpmExpand(Rmacro, NULL);
849  if (cp != NULL && strcmp(cp, "/") != 0) {
850  cp = _free(cp);
851  Rurlfn = rpmGenPath(NULL, Rmacro, sp->source);
852  if (!(Rurlfn == NULL || Rurlfn[0] == '\0' || !strcmp(Rurlfn, "/") || !strcmp(Lurlfn, Rurlfn))) {
853  rpmlog(RPMLOG_NOTICE, _("Fetching(%s%d): %s\n"),
854  (sp->flags & RPMFILE_SOURCE) ? "Source" : "Patch", sp->num, Rurlfn);
855  rc = urlGetFile(Rurlfn, Lurlfn);
856  if (rc == 0)
857  goto bottom;
858  else {
859  rpmlog(RPMLOG_ERR, _("Fetching %s%d failed: %s\n"),
860  (sp->flags & RPMFILE_SOURCE) ? "Source" : "Patch", sp->num, ftpStrerror(rc));
861  ec++;
862  }
863  }
864  }
865  cp = _free(cp);
866 
867  /* try to fetch from original location */
868  rpmlog(RPMLOG_NOTICE, _("Fetching(%s%d): %s\n"),
869  (sp->flags & RPMFILE_SOURCE) ? "Source" : "Patch", sp->num, sp->fullSource);
870  rc = urlGetFile(sp->fullSource, Lurlfn);
871  if (rc == 0)
872  goto bottom;
873  else {
874  rpmlog(RPMLOG_ERR, _("Fetching %s%d failed: %s\n"),
875  (sp->flags & RPMFILE_SOURCE) ? "Source" : "Patch", sp->num, ftpStrerror(rc));
876  ec++;
877  }
878 
879  rpmlog(RPMLOG_ERR, _("Missing %s%d: %s: %s\n"),
880  ((sp->flags & RPMFILE_SOURCE) ? "Source" : "Patch"),
881  sp->num, sp->source, strerror(ENOENT));
882  ec++;
883 
884 bottom:
885  Lurlfn = _free(Lurlfn);
886  Rurlfn = _free(Rurlfn);
887  }
888 
889  return ec;
890 }
891 
892 int parsePrep(Spec spec, int verify)
893 {
894  rpmParseState nextPart;
895  int res, rc;
896  rpmiob iob;
897  ARGV_t saveLines = NULL;
898  ARGV_t lines;
899  const char * cp;
900  int xx;
901 
902  if (spec->prep != NULL) {
903  rpmlog(RPMLOG_ERR, _("line %d: second %%prep\n"), spec->lineNum);
904  return RPMRC_FAIL;
905  }
906 
907  spec->prep = rpmiobNew(0);
908 
909  /* There are no options to %prep */
910  if ((rc = readLine(spec, STRIP_NOTHING)) > 0)
911  return PART_NONE;
912  if (rc)
913  return rc;
914 
915  /* Check to make sure that all sources/patches are present. */
916  if (verify) {
917  rc = prepFetch(spec);
918  if (rc)
919  return RPMRC_FAIL;
920  }
921 
922  iob = rpmiobNew(0);
923 
924  while ((nextPart = isPart(spec)) == PART_NONE) {
925  /* Need to expand the macros inline. That way we */
926  /* can give good line number information on error. */
927  iob = rpmiobAppend(iob, spec->line, 0);
928  if ((rc = readLine(spec, STRIP_NOTHING)) > 0) {
929  nextPart = PART_NONE;
930  break;
931  }
932  if (rc)
933  return rc;
934  }
935 
936  xx = argvSplit(&saveLines, rpmiobStr(iob), "\n");
937 
938 /*@-usereleased@*/
939  for (lines = saveLines; *lines; lines++) {
940  res = 0;
941  for (cp = *lines; *cp == ' ' || *cp == '\t'; cp++)
942  {};
943  if (!strncmp(cp, "%setup", sizeof("%setup")-1)) {
944  res = doSetupMacro(spec, cp);
945 #ifndef DYING
946  } else if (! strncmp(cp, "%patch", sizeof("%patch")-1)) {
947  res = doPatchMacro(spec, cp);
948 #endif
949  } else {
950  spec->prep = rpmiobAppend(spec->prep, *lines, 1);
951  }
952  if (res && !spec->force) {
953  saveLines = argvFree(saveLines);
954  iob = rpmiobFree(iob);
955  return res;
956  }
957  }
958 /*@=usereleased@*/
959 
960  saveLines = argvFree(saveLines);
961  iob = rpmiobFree(iob);
962 
963  return nextPart;
964 }
rpmParseState isPart(Spec spec)
Check line for section separator, return next parser state.
Definition: parseSpec.c:64
const char * rpmmgFile(rpmmg mg, const char *fn)
Return magic string for a file.
Definition: rpmmg.c:84
static int doSetupMacro(Spec spec, const char *line)
Parse setup macro.
Definition: parsePrep.c:404
int isCompressed(const char *file, rpmCompressedMagic *compressed)
Return type of compression used in file.
Definition: macro.c:3105
enum urltype_e urltype
Supported URL types.
static int quietly
Definition: parsePrep.c:26
char * xstrdup(const char *str)
Definition: rpmmalloc.c:321
const char * rootURL
Definition: rpmspec.h:120
char * rpmGetPath(const char *path,...)
Return (malloc'ed) expanded, canonicalized, file path.
Definition: macro.c:3431
static int createDir
Definition: parsePrep.c:26
int rpmioMkpath(const char *path, mode_t mode, uid_t uid, gid_t gid)
Insure that directories in path exist, creating as needed.
Definition: rpmio.c:3017
rpmuint32_t num
Definition: rpmspec.h:50
#define reverse(bot, top)
Definition: merge.c:102
int errno
struct rpmBuildArguments_s rpmBTArgs
Definition: poptBT.c:29
void addMacro(MacroContext mc, const char *n, const char *o, const char *b, int level)
Add macro to context.
Definition: macro.c:2782
static int leaveDirs
Definition: parsePrep.c:24
rpmiob rpmiobFree(rpmiob iob)
Destroy a I/O buffer instance.
struct Source * sources
Definition: rpmspec.h:162
const char * ftpStrerror(int errorNumber)
Definition: rpmio.c:753
static void rpmlog(int code, const char *fmt,...)
Definition: rpmlog.h:299
static const char * doUntar(Spec spec, rpmuint32_t c, int quietly)
Expand setup macro into prep scriptlet.
Definition: parsePrep.c:218
rpmiob rpmiobAppend(rpmiob iob, const char *s, size_t nl)
Append string to I/O buffer.
Definition: rpmiob.c:77
int parsePrep(Spec spec, int verify)
Parse %prep section of a spec file.
Definition: parsePrep.c:892
struct Source * next
Definition: rpmspec.h:52
const char * getUname(uid_t uid)
Return cached user name from user id.
Definition: names.c:41
const char * getSourceDir(rpmfileAttrs attr)
Return the macro directory location from source file flags.
Definition: build.c:24
int readLine(Spec spec, rpmStripFlags strip)
Read next line from spec file.
Definition: parseSpec.c:351
int _rpmmg_debug
Definition: rpmmg.c:21
const char * fullSource
Definition: rpmspec.h:46
rpmiob prep
Definition: rpmspec.h:186
const char * source
Definition: rpmspec.h:48
Definition: rpmspec.h:44
Header header
Definition: rpmspec.h:217
unsigned int rpmuint32_t
Definition: rpmiotypes.h:28
int urlGetFile(const char *url, const char *dest)
Copy data from URL to local file.
Definition: url.c:598
static char * doPatch(Spec spec, rpmuint32_t c, int strip, const char *db, int reverse, int removeEmpties, int fuzz, const char *subdir)
Expand patchN macro into prep scriptlet.
Definition: parsePrep.c:79
char * line
Definition: rpmspec.h:138
int Lstat(const char *path, struct stat *st)
lstat(2) clone.
Definition: rpmrpc.c:1401
static int skipDefaultAction
Definition: parsePrep.c:24
MacroContext macros
Definition: rpmspec.h:177
const char * getGname(gid_t gid)
Return cached group name from group id.
Definition: names.c:119
ARGV_t argvFree(ARGV_t argv)
Destroy an argv array.
Definition: argv.c:44
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
rpmmg rpmmgNew(const char *fn, int flags)
Create and load a magic wrapper.
Definition: rpmmg.c:57
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 * buildSubdir
Definition: rpmspec.h:118
static struct poptOption optionsTable[]
Definition: parsePrep.c:30
rpmRC rpmMkdirPath(const char *dpath, const char *dname)
Create directory if it does not exist, and make sure path is writable.
Definition: misc.c:19
const char const char int arg
Definition: mongo.h:777
rpmiob rpmiobNew(size_t len)
Create an I/O buffer.
Definition: rpmiob.c:44
const char const bson int mongo_write_concern int flags
Definition: mongo.h:485
#define RMIL_SPEC
Definition: rpmmacro.h:68
enum rpmRC_e rpmRC
RPM return codes.
char * rpmiobStr(rpmiob iob)
Return I/O buffer (as string).
Definition: rpmiob.c:112
Package packages
Definition: rpmspec.h:204
static const char * dirName
Definition: parsePrep.c:28
int parseNum(const char *line, rpmuint32_t *res)
Parse a number.
Definition: misc.c:11
static void prepFetchVerbose(struct Source *sp, struct stat *st)
Definition: parsePrep.c:717
const char const int i
Definition: bson.h:778
enum rpmCompressedMagic_e rpmCompressedMagic
urltype urlPath(const char *url, const char **pathp)
Return path component of URL.
Definition: url.c:430
static int snprintf(char *buf, int nb, const char *fmt,...)
Definition: rpmps.c:220
This is the only module users of librpmbuild should need to include.
char * stpcpy(char *dest, const char *src)
struct rpmmg_s * rpmmg
Definition: rpmmg.h:15
static void * _free(const void *p)
Wrapper to free(3), hides const compilation noise, permit NULL, return NULL.
Definition: rpmiotypes.h:756
struct rpmiob_s * rpmiob
Definition: rpmiotypes.h:60
int headerNEVRA(Header h, const char **np, const char **ep, const char **vp, const char **rp, const char **ap)
Return name, epoch, version, release, arch strings from header.
Definition: hdrNVR.c:162
static int prepFetch(Spec spec)
Check that all sources/patches/icons exist locally, fetching if necessary.
Definition: parsePrep.c:749
const char * db
Definition: mongo.h:697
static rpmRC checkOwners(const char *urlfn)
Check that file owner and group are known.
Definition: parsePrep.c:46
static rpmRC doPatchMacro(Spec spec, const char *line)
Parse patch line.
Definition: parsePrep.c:581
int argvSplit(ARGV_t *argvp, const char *str, const char *seps)
Split a string into an argv array.
Definition: argv.c:233
#define rpmIsVerbose()
Definition: rpmcb.h:21
enum rpmParseState_e rpmParseState
int lineNum
Definition: rpmspec.h:139
int force
Definition: rpmspec.h:152
#define _(Text)
Definition: system.h:29
ARGstr_t * ARGV_t
Definition: argv.h:12
int rpmExpandNumeric(const char *arg)
Return macro expansion as a numeric value.
Definition: macro.c:3312
int flags
Definition: rpmspec.h:49
rpmmg rpmmgFree(rpmmg mg)
Destroy a magic wrapper.
const char const bson int num
Definition: mongo.h:485