rpm  5.2.1
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_PATH:
137  case URL_IS_UNKNOWN:
138  break;
139  case URL_IS_DASH:
140  Lurlfn = _free(Lurlfn);
141  return NULL;
142  /*@notreached@*/ break;
143  }
144 
145  patch = rpmGetPath("%{__patch}", NULL);
146  if (strcmp(patch, "%{__patch}") == 0)
147  patch = xstrdup("patch");
148 
149  flags = rpmExpand("%{?_default_patch_flags}%{!?_default_patch_flags:-s}", NULL);
150 
151  if (compressed) {
152  const char *zipper;
153 
154  switch (compressed) {
155  default:
156  case COMPRESSED_NOT: /* XXX can't happen */
157  case COMPRESSED_OTHER:
158  case COMPRESSED_ZIP: /* XXX wrong */
159  zipper = "%{__gzip}";
160  break;
161  case COMPRESSED_BZIP2:
162  zipper = "%{__bzip2}";
163  break;
164  case COMPRESSED_LZOP:
165  zipper = "%{__lzop}";
166  break;
167  case COMPRESSED_LZMA:
168  zipper = "%{__lzma}";
169  break;
170  case COMPRESSED_XZ:
171  zipper = "%{__xz}";
172  break;
173  }
174  zipper = rpmGetPath(zipper, NULL);
175 
176  sprintf(buf,
177  "echo \"Patch #%d (%s):\"\n"
178  "%s -d < '%s' | %s -p%d %s %s\n"
179  "STATUS=$?\n"
180  "if [ $STATUS -ne 0 ]; then\n"
181  " exit $STATUS\n"
182  "fi",
183  c,
184 /*@-moduncon@*/
185  (const char *) basename((char *)fn),
186 /*@=moduncon@*/
187  zipper,
188  fn, patch, strip, args, flags);
189  zipper = _free(zipper);
190  } else {
191  sprintf(buf,
192  "echo \"Patch #%d (%s):\"\n"
193  "%s -p%d %s %s < '%s'", c,
194 /*@-moduncon@*/
195  (const char *) basename((char *)fn),
196 /*@=moduncon@*/
197  patch, strip, args, flags, fn);
198  }
199 
200  patch = _free(patch);
201  flags = _free(flags);
202  Lurlfn = _free(Lurlfn);
203  return buf;
204 }
205 #endif
206 
214 /*@observer@*/
215 static const char *doUntar(Spec spec, rpmuint32_t c, int quietly)
216  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
217  /*@modifies rpmGlobalMacroContext, fileSystem, internalState @*/
218 {
219  const char *fn, *Lurlfn;
220  static char buf[BUFSIZ];
221  char *taropts;
222  char *t = NULL;
223  struct Source *sp;
224  rpmCompressedMagic compressed = COMPRESSED_NOT;
225  int urltype;
226  const char *tar;
227 
228  for (sp = spec->sources; sp != NULL; sp = sp->next) {
229  if ((sp->flags & RPMFILE_SOURCE) && (sp->num == c)) {
230  break;
231  }
232  }
233  if (sp == NULL) {
234  rpmlog(RPMLOG_ERR, _("No source number %d\n"), c);
235  return NULL;
236  }
237 
238  /*@-internalglobs@*/ /* FIX: shrug */
239  taropts = ((rpmIsVerbose() && !quietly) ? "-xvvf" : "-xf");
240  /*@=internalglobs@*/
241 
242 #if defined(RPM_VENDOR_OPENPKG) /* splitted-source-directory */
243  Lurlfn = rpmGenPath(NULL, getSourceDir(sp->flags, sp->source), sp->source);
244 #else
245  Lurlfn = rpmGenPath(NULL, getSourceDir(sp->flags), sp->source);
246 #endif
247 
248  /* XXX On non-build parse's, file cannot be stat'd or read */
249  if (!spec->force && (isCompressed(Lurlfn, &compressed) || checkOwners(Lurlfn))) {
250  Lurlfn = _free(Lurlfn);
251  return NULL;
252  }
253 
254  fn = NULL;
255  urltype = urlPath(Lurlfn, &fn);
256  switch (urltype) {
257  case URL_IS_HTTPS: /* XXX WRONG WRONG WRONG */
258  case URL_IS_HTTP: /* XXX WRONG WRONG WRONG */
259  case URL_IS_FTP: /* XXX WRONG WRONG WRONG */
260  case URL_IS_HKP: /* XXX WRONG WRONG WRONG */
261  case URL_IS_PATH:
262  case URL_IS_UNKNOWN:
263  break;
264  case URL_IS_DASH:
265  Lurlfn = _free(Lurlfn);
266  return NULL;
267  /*@notreached@*/ break;
268  }
269 #ifdef NOTYET
270  { rpmmg mg;
271 
272 _rpmmg_debug = 1;
273  mg = rpmmgNew(NULL, 0);
274  t = (char *) rpmmgFile(mg, fn);
275  mg = rpmmgFree(mg);
276 fprintf(stderr, "==> %s: %s\n", fn, t);
277  t = _free(t);
278 _rpmmg_debug = 0;
279  }
280 #endif
281 
282  tar = rpmGetPath("%{__tar}", NULL);
283  if (strcmp(tar, "%{__tar}") == 0)
284  tar = xstrdup("tar");
285 
286 #if defined(RPM_VENDOR_ARK) /* use-gnu-tar-compression-detection */
287 /* We leave compression handling for all tar based files up to GNU tar */
288  if (compressed == COMPRESSED_ZIP)
289 #else
290  if (compressed != COMPRESSED_NOT)
291 #endif
292  {
293  const char *zipper;
294  int needtar = 1;
295 
296  switch (compressed) {
297  case COMPRESSED_NOT: /* XXX can't happen */
298  case COMPRESSED_OTHER:
299  t = "%{__gzip} -dc";
300  break;
301  case COMPRESSED_BZIP2:
302  t = "%{__bzip2} -dc";
303  break;
304  case COMPRESSED_LZOP:
305  t = "%{__lzop} -dc";
306  break;
307  case COMPRESSED_LZMA:
308  t = "%{__lzma} -dc";
309  break;
310  case COMPRESSED_XZ:
311  t = "%{__xz} -dc";
312  break;
313  case COMPRESSED_ZIP:
314 #if defined(RPM_VENDOR_OPENPKG) /* use-bsdtar-for-zip-files */
315  t = "%{__bsdtar} -x -f";
316 #else
317  if (rpmIsVerbose() && !quietly)
318  t = "%{__unzip}";
319  else
320  t = "%{__unzip} -qq";
321 #endif
322  needtar = 0;
323  break;
324  }
325  zipper = rpmGetPath(t, NULL);
326  buf[0] = '\0';
327  t = stpcpy(buf, zipper);
328  zipper = _free(zipper);
329  *t++ = ' ';
330  *t++ = '\'';
331  t = stpcpy(t, fn);
332  *t++ = '\'';
333  if (needtar) {
334  t = stpcpy(t, " | ");
335  t = stpcpy(t, tar);
336  t = stpcpy(t, " ");
337  t = stpcpy(t, taropts);
338  t = stpcpy(t, " -");
339  }
340  t = stpcpy(t,
341  "\n"
342  "STATUS=$?\n"
343  "if [ $STATUS -ne 0 ]; then\n"
344  " exit $STATUS\n"
345  "fi");
346  } else {
347  buf[0] = '\0';
348  t = stpcpy(buf, tar);
349  t = stpcpy(t, " ");
350  t = stpcpy(t, taropts);
351  *t++ = ' ';
352  t = stpcpy(t, fn);
353  }
354 
355  tar = _free(tar);
356  Lurlfn = _free(Lurlfn);
357  return buf;
358 }
359 
367 static int doSetupMacro(Spec spec, const char * line)
368  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
369  /*@modifies spec->buildSubdir, spec->macros, spec->prep,
370  spec->packages->header,
371  rpmGlobalMacroContext, fileSystem, internalState @*/
372 {
373  char buf[BUFSIZ];
374  rpmiob before;
375  rpmiob after;
376  poptContext optCon;
377  int argc;
378  const char ** argv;
379  int arg;
380  const char * optArg;
381  int rc;
383 
384  /*@-mods@*/
386  createDir = quietly = 0;
387  dirName = NULL;
388  /*@=mods@*/
389 
390  if ((rc = poptParseArgvString(line, &argc, &argv))) {
391  rpmlog(RPMLOG_ERR, _("Error parsing %%setup: %s\n"),
392  poptStrerror(rc));
393  return RPMRC_FAIL;
394  }
395 
396  before = rpmiobNew(0);
397  after = rpmiobNew(0);
398 
399  optCon = poptGetContext(NULL, argc, argv, optionsTable, 0);
400  while ((arg = poptGetNextOpt(optCon)) > 0) {
401  optArg = poptGetOptArg(optCon);
402 
403  /* We only parse -a and -b here */
404 
405  if (parseNum(optArg, &num)) {
406  rpmlog(RPMLOG_ERR, _("line %d: Bad arg to %%setup: %s\n"),
407  spec->lineNum, (optArg ? optArg : "???"));
408  before = rpmiobFree(before);
409  after = rpmiobFree(after);
410  optCon = poptFreeContext(optCon);
411  argv = _free(argv);
412  return RPMRC_FAIL;
413  }
414 
415  { const char *chptr = doUntar(spec, num, quietly);
416  if (chptr == NULL)
417  return RPMRC_FAIL;
418 
419  (void) rpmiobAppend((arg == 'a' ? after : before), chptr, 1);
420  }
421  }
422 
423  if (arg < -1) {
424  rpmlog(RPMLOG_ERR, _("line %d: Bad %%setup option %s: %s\n"),
425  spec->lineNum,
426  poptBadOption(optCon, POPT_BADOPTION_NOALIAS),
427  poptStrerror(arg));
428  before = rpmiobFree(before);
429  after = rpmiobFree(after);
430  optCon = poptFreeContext(optCon);
431  argv = _free(argv);
432  return RPMRC_FAIL;
433  }
434 
435  if (dirName) {
436  spec->buildSubdir = xstrdup(dirName);
437  } else {
438  const char *N, *V;
439  (void) headerNEVRA(spec->packages->header, &N, NULL, &V, NULL, NULL);
440  (void) snprintf(buf, sizeof(buf), "%s-%s", N, V);
441  buf[sizeof(buf)-1] = '\0';
442  N = _free(N);
443  V = _free(V);
444  spec->buildSubdir = xstrdup(buf);
445  }
446  addMacro(spec->macros, "buildsubdir", NULL, spec->buildSubdir, RMIL_SPEC);
447 
448  optCon = poptFreeContext(optCon);
449  argv = _free(argv);
450 
451  /* cd to the build dir */
452  { const char * buildDirURL = rpmGenPath(spec->rootURL, "%{_builddir}", "");
453  const char *buildDir;
454 
455  (void) urlPath(buildDirURL, &buildDir);
456  rc = rpmioMkpath(buildDir, 0755, -1, -1);
457  sprintf(buf, "cd '%s'", buildDir);
458  spec->prep = rpmiobAppend(spec->prep, buf, 1);
459  buildDirURL = _free(buildDirURL);
460  }
461 
462  /* delete any old sources */
463  if (!leaveDirs) {
464  sprintf(buf, "rm -rf '%s'", spec->buildSubdir);
465  spec->prep = rpmiobAppend(spec->prep, buf, 1);
466  }
467 
468  /* if necessary, create and cd into the proper dir */
469  if (createDir) {
470  char *mkdir_p;
471  mkdir_p = rpmExpand("%{?__mkdir_p}%{!?__mkdir_p:mkdir -p}", NULL);
472  if (!mkdir_p)
473  mkdir_p = xstrdup("mkdir -p");
474  sprintf(buf, "%s '%s'\ncd '%s'",
475  mkdir_p, spec->buildSubdir, spec->buildSubdir);
476  mkdir_p = _free(mkdir_p);
477  spec->prep = rpmiobAppend(spec->prep, buf, 1);
478  }
479 
480  /* do the default action */
481  if (!createDir && !skipDefaultAction) {
482  const char *chptr = doUntar(spec, 0, quietly);
483  if (!chptr)
484  return RPMRC_FAIL;
485  spec->prep = rpmiobAppend(spec->prep, chptr, 1);
486  }
487 
488  spec->prep = rpmiobAppend(spec->prep, rpmiobStr(before), 0);
489  before = rpmiobFree(before);
490 
491  if (!createDir) {
492  sprintf(buf, "cd '%s'", spec->buildSubdir);
493  spec->prep = rpmiobAppend(spec->prep, buf, 1);
494  }
495 
496  if (createDir && !skipDefaultAction) {
497  const char * chptr = doUntar(spec, 0, quietly);
498  if (chptr == NULL)
499  return RPMRC_FAIL;
500  spec->prep = rpmiobAppend(spec->prep, chptr, 1);
501  }
502 
503  spec->prep = rpmiobAppend(spec->prep, rpmiobStr(after), 0);
504  after = rpmiobFree(after);
505 
506  /* XXX FIXME: owner & group fixes were conditioned on !geteuid() */
507  /* Fix the owner, group, and permissions of the setup build tree */
508  { /*@observer@*/ static const char *fixmacs[] =
509  { "%{_fixowner}", "%{_fixgroup}", "%{_fixperms}", NULL };
510  const char ** fm;
511 
512  for (fm = fixmacs; *fm; fm++) {
513  const char *fix;
514  fix = rpmExpand(*fm, " .", NULL);
515  if (fix && *fix != '%')
516  spec->prep = rpmiobAppend(spec->prep, fix, 1);
517  fix = _free(fix);
518  }
519  }
520 
521  return 0;
522 }
523 
524 #ifndef DYING
525 
531 static rpmRC doPatchMacro(Spec spec, const char * line)
532  /*@globals rpmGlobalMacroContext, h_errno,
533  fileSystem, internalState @*/
534  /*@modifies spec->prep, rpmGlobalMacroContext,
535  fileSystem, internalState @*/
536 {
537  char *s;
538  char *opt_b;
539  char *opt_d;
540  rpmuint32_t opt_P, opt_p, opt_R, opt_E, opt_F;
541  char buf[BUFSIZ], *bp;
542  rpmuint32_t patch_nums[1024]; /* XXX - we can only handle 1024 patches! */
543  int patch_index, x;
544 
545  memset(patch_nums, 0, sizeof(patch_nums));
546  opt_P = opt_p = opt_R = opt_E = 0;
547  opt_F = rpmExpandNumeric("%{?_default_patch_fuzz}%{!?_default_patch_fuzz:-1}");
548  opt_b = NULL;
549  opt_d = NULL;
550  patch_index = 0;
551 
552  if (! strchr(" \t\n", line[6])) {
553  /* %patchN */
554  sprintf(buf, "%%patch -P %s", line + 6);
555  } else {
556  strcpy(buf, line);
557  }
558 
559  /*@-internalglobs@*/ /* FIX: strtok has state */
560  for (bp = buf; (s = strtok(bp, " \t\n")) != NULL;) {
561  if (bp) { /* remove 1st token (%patch) */
562  bp = NULL;
563  continue;
564  }
565  if (!strcmp(s, "-P")) {
566  opt_P = 1;
567  } else if (!strcmp(s, "-R")) {
568  opt_R = 1;
569  } else if (!strcmp(s, "-E")) {
570  opt_E = 1;
571  } else if (!strcmp(s, "-b")) {
572  /* orig suffix */
573  opt_b = strtok(NULL, " \t\n");
574  if (! opt_b) {
576  _("line %d: Need arg to %%patch -b: %s\n"),
577  spec->lineNum, spec->line);
578  return RPMRC_FAIL;
579  }
580  } else if (!strcmp(s, "-z")) {
581  /* orig suffix */
582  opt_b = strtok(NULL, " \t\n");
583  if (! opt_b) {
585  _("line %d: Need arg to %%patch -z: %s\n"),
586  spec->lineNum, spec->line);
587  return RPMRC_FAIL;
588  }
589  } else if (!strcmp(s, "-F")) {
590  /* fuzz factor */
591  const char * fnum = (!strchr(" \t\n", s[2])
592  ? s+2 : strtok(NULL, " \t\n"));
593  char * end = NULL;
594 
595  opt_F = (fnum ? strtol(fnum, &end, 10) : 0);
596  if (! opt_F || *end) {
598  _("line %d: Bad arg to %%patch -F: %s\n"),
599  spec->lineNum, spec->line);
600  return RPMRC_FAIL;
601  }
602  } else if (!strcmp(s, "-d")) {
603  /* subdirectory */
604  opt_d = strtok(NULL, " \t\n");
605  if (! opt_d) {
607  _("line %d: Need arg to %%patch -d: %s\n"),
608  spec->lineNum, spec->line);
609  return RPMRC_FAIL;
610  }
611  } else if (!strncmp(s, "-p", sizeof("-p")-1)) {
612  /* unfortunately, we must support -pX */
613  if (! strchr(" \t\n", s[2])) {
614  s = s + 2;
615  } else {
616  s = strtok(NULL, " \t\n");
617  if (s == NULL) {
619  _("line %d: Need arg to %%patch -p: %s\n"),
620  spec->lineNum, spec->line);
621  return RPMRC_FAIL;
622  }
623  }
624  if (parseNum(s, &opt_p)) {
626  _("line %d: Bad arg to %%patch -p: %s\n"),
627  spec->lineNum, spec->line);
628  return RPMRC_FAIL;
629  }
630  } else {
631  /* Must be a patch num */
632  if (patch_index == 1024) {
633  rpmlog(RPMLOG_ERR, _("Too many patches!\n"));
634  return RPMRC_FAIL;
635  }
636  if (parseNum(s, &(patch_nums[patch_index]))) {
637  rpmlog(RPMLOG_ERR, _("line %d: Bad arg to %%patch: %s\n"),
638  spec->lineNum, spec->line);
639  return RPMRC_FAIL;
640  }
641  patch_index++;
642  }
643  }
644  /*@=internalglobs@*/
645 
646  /* All args processed */
647 
648  if (! opt_P) {
649  s = doPatch(spec, 0, opt_p, opt_b, opt_R, opt_E, opt_F, opt_d);
650  if (s == NULL)
651  return RPMRC_FAIL;
652  spec->prep = rpmiobAppend(spec->prep, s, 1);
653  }
654 
655  for (x = 0; x < patch_index; x++) {
656  s = doPatch(spec, patch_nums[x], opt_p, opt_b, opt_R, opt_E, opt_F, opt_d);
657  if (s == NULL)
658  return RPMRC_FAIL;
659  spec->prep = rpmiobAppend(spec->prep, s, 1);
660  }
661 
662  return RPMRC_OK;
663 }
664 #endif
665 
666 static void prepFetchVerbose(/*@unused@*/ struct Source *sp,
667  /*@unused@*/ struct stat *st)
668  /*@globals internalState @*/
669  /*@modifies internalState @*/
670 {
671  char *buf;
672  size_t buf_len;
673  int xx;
674  int i;
675 
677  return;
678  buf_len = 2*80;
679  if ((buf = (char *)malloc(buf_len)) == NULL)
680  return;
681  xx = snprintf(buf, buf_len, "%s%d:", (sp->flags & RPMFILE_SOURCE) ? "Source" : "Patch", sp->num);
682  for (i = (int)strlen(buf); i <= 11; i++)
683  buf[i] = ' ';
684  xx = snprintf(buf+i, buf_len-i, "%-52.52s", sp->source);
685  i = (int)strlen(buf);
686  if (st != NULL)
687  xx = snprintf(buf+i, buf_len-i, " %9lu Bytes\n", (unsigned long)st->st_size);
688  else
689  xx = snprintf(buf+i, buf_len-i, " ...MISSING\n");
690  rpmlog(RPMLOG_NOTICE, "%s", buf);
691  buf = _free(buf);
692  return;
693 }
694 
698 static int prepFetch(Spec spec)
699  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
700  /*@modifies rpmGlobalMacroContext, fileSystem, internalState @*/
701 {
702 #if defined(RPM_VENDOR_OPENPKG) /* splitted-source-directory */
703  const char *Smacro;
704 #endif
705  const char *Lmacro, *Lurlfn = NULL;
706  const char *Rmacro, *Rurlfn = NULL;
707  struct Source *sp;
708  struct stat st;
709  rpmRC rpmrc;
710  int ec, rc;
711  char *cp;
712 
713  /* XXX insure that %{_sourcedir} exists */
714  rpmrc = RPMRC_OK;
715  Lurlfn = rpmGenPath(NULL, "%{?_sourcedir}", NULL);
716  if (Lurlfn != NULL && *Lurlfn != '\0')
717  rpmrc = rpmMkdirPath(Lurlfn, "_sourcedir");
718  Lurlfn = _free(Lurlfn);
719  if (rpmrc != RPMRC_OK)
720  return -1;
721 
722  /* XXX insure that %{_patchdir} exists */
723  rpmrc = RPMRC_OK;
724  Lurlfn = rpmGenPath(NULL, "%{?_patchdir}", NULL);
725  if (Lurlfn != NULL && *Lurlfn != '\0')
726  rpmrc = rpmMkdirPath(Lurlfn, "_patchdir");
727  Lurlfn = _free(Lurlfn);
728  if (rpmrc != RPMRC_OK)
729  return -1;
730 
731  /* XXX insure that %{_icondir} exists */
732  rpmrc = RPMRC_OK;
733  Lurlfn = rpmGenPath(NULL, "%{?_icondir}", NULL);
734  if (Lurlfn != NULL && *Lurlfn != '\0')
735  rpmrc = rpmMkdirPath(Lurlfn, "_icondir");
736  Lurlfn = _free(Lurlfn);
737  if (rpmrc != RPMRC_OK)
738  return -1;
739 
741  rpmlog(RPMLOG_NOTICE, "Checking source and patch file(s):\n");
742 
743  ec = 0;
744  for (sp = spec->sources; sp != NULL; sp = sp->next) {
745 
746 #if defined(RPM_VENDOR_OPENPKG) /* splitted-source-directory */
747  Smacro = "%{?_specdir}/";
748 #endif
749 #if defined(RPM_VENDOR_OPENPKG) /* splitted-source-directory */
750  if (! (Lmacro = getSourceDir(sp->flags, sp->source)))
751 #else
752  if (! (Lmacro = getSourceDir(sp->flags)))
753 #endif
754  continue;
755  if (sp->flags & RPMFILE_SOURCE) {
756  Rmacro = "%{?_Rsourcedir}/";
757  } else
758  if (sp->flags & RPMFILE_PATCH) {
759  Rmacro = "%{?_Rpatchdir}/";
760  } else
761  if (sp->flags & RPMFILE_ICON) {
762  Rmacro = "%{?_Ricondir}/";
763  } else
764  continue;
765 
766 #if defined(RPM_VENDOR_OPENPKG) /* splitted-source-directory */
767  /* support splitted source directories, i.e., source files which
768  are alternatively placed into the .spec directory and picked
769  up from there, too. */
770  Lurlfn = rpmGenPath(NULL, Smacro, sp->source);
771  rc = Lstat(Lurlfn, &st);
772  if (rc == 0) {
773  prepFetchVerbose(sp, &st);
774  goto bottom;
775  }
776 #endif
777  Lurlfn = rpmGenPath(NULL, Lmacro, sp->source);
778  rc = Lstat(Lurlfn, &st);
779  if (rc == 0) {
780 /*@-noeffect@*/
781  prepFetchVerbose(sp, &st);
782 /*@=noeffect@*/
783  goto bottom;
784  }
785 /*@-noeffect@*/
786  prepFetchVerbose(sp, NULL);
787 /*@=noeffect@*/
788  if (errno != ENOENT) {
789  ec++;
790  rpmlog(RPMLOG_ERR, _("Missing %s%d %s: %s\n"),
791  ((sp->flags & RPMFILE_SOURCE) ? "Source" : "Patch"),
792  sp->num, sp->source, strerror(ENOENT));
793  goto bottom;
794  }
795 
796  /* try to fetch via macro-controlled remote locations */
797  cp = rpmExpand(Rmacro, NULL);
798  if (cp != NULL && strcmp(cp, "/") != 0) {
799  cp = _free(cp);
800  Rurlfn = rpmGenPath(NULL, Rmacro, sp->source);
801  if (!(Rurlfn == NULL || Rurlfn[0] == '\0' || !strcmp(Rurlfn, "/") || !strcmp(Lurlfn, Rurlfn))) {
802  rpmlog(RPMLOG_NOTICE, _("Fetching(%s%d): %s\n"),
803  (sp->flags & RPMFILE_SOURCE) ? "Source" : "Patch", sp->num, Rurlfn);
804  rc = urlGetFile(Rurlfn, Lurlfn);
805  if (rc == 0)
806  goto bottom;
807  else {
808  rpmlog(RPMLOG_ERR, _("Fetching %s%d failed: %s\n"),
809  (sp->flags & RPMFILE_SOURCE) ? "Source" : "Patch", sp->num, ftpStrerror(rc));
810  ec++;
811  }
812  }
813  }
814  cp = _free(cp);
815 
816  /* try to fetch from original location */
817  rpmlog(RPMLOG_NOTICE, _("Fetching(%s%d): %s\n"),
818  (sp->flags & RPMFILE_SOURCE) ? "Source" : "Patch", sp->num, sp->fullSource);
819  rc = urlGetFile(sp->fullSource, Lurlfn);
820  if (rc == 0)
821  goto bottom;
822  else {
823  rpmlog(RPMLOG_ERR, _("Fetching %s%d failed: %s\n"),
824  (sp->flags & RPMFILE_SOURCE) ? "Source" : "Patch", sp->num, ftpStrerror(rc));
825  ec++;
826  }
827 
828  rpmlog(RPMLOG_ERR, _("Missing %s%d: %s: %s\n"),
829  ((sp->flags & RPMFILE_SOURCE) ? "Source" : "Patch"),
830  sp->num, sp->source, strerror(ENOENT));
831  ec++;
832 
833 bottom:
834  Lurlfn = _free(Lurlfn);
835  Rurlfn = _free(Rurlfn);
836  }
837 
838  return ec;
839 }
840 
841 int parsePrep(Spec spec, int verify)
842 {
843  rpmParseState nextPart;
844  int res, rc;
845  rpmiob iob;
846  ARGV_t saveLines = NULL;
847  ARGV_t lines;
848  const char * cp;
849  int xx;
850 
851  if (spec->prep != NULL) {
852  rpmlog(RPMLOG_ERR, _("line %d: second %%prep\n"), spec->lineNum);
853  return RPMRC_FAIL;
854  }
855 
856  spec->prep = rpmiobNew(0);
857 
858  /* There are no options to %prep */
859  if ((rc = readLine(spec, STRIP_NOTHING)) > 0)
860  return PART_NONE;
861  if (rc)
862  return rc;
863 
864  /* Check to make sure that all sources/patches are present. */
865  if (verify) {
866  rc = prepFetch(spec);
867  if (rc)
868  return RPMRC_FAIL;
869  }
870 
871  iob = rpmiobNew(0);
872 
873  while ((nextPart = isPart(spec)) == PART_NONE) {
874  /* Need to expand the macros inline. That way we */
875  /* can give good line number information on error. */
876  iob = rpmiobAppend(iob, spec->line, 0);
877  if ((rc = readLine(spec, STRIP_NOTHING)) > 0) {
878  nextPart = PART_NONE;
879  break;
880  }
881  if (rc)
882  return rc;
883  }
884 
885  xx = argvSplit(&saveLines, rpmiobStr(iob), "\n");
886 
887 /*@-usereleased@*/
888  for (lines = saveLines; *lines; lines++) {
889  res = 0;
890  for (cp = *lines; *cp == ' ' || *cp == '\t'; cp++)
891  {};
892  if (!strncmp(cp, "%setup", sizeof("%setup")-1)) {
893  res = doSetupMacro(spec, cp);
894 #ifndef DYING
895  } else if (! strncmp(cp, "%patch", sizeof("%patch")-1)) {
896  res = doPatchMacro(spec, cp);
897 #endif
898  } else {
899  spec->prep = rpmiobAppend(spec->prep, *lines, 1);
900  }
901  if (res && !spec->force) {
902  saveLines = argvFree(saveLines);
903  iob = rpmiobFree(iob);
904  return res;
905  }
906  }
907 /*@=usereleased@*/
908 
909  saveLines = argvFree(saveLines);
910  iob = rpmiobFree(iob);
911 
912  return nextPart;
913 }