rpm  4.5
build.c
Go to the documentation of this file.
1 
5 #include "system.h"
6 
7 #include <rpmcli.h>
8 #include <rpmbuild.h>
9 
10 #include "rpmps.h"
11 #include "rpmte.h"
12 #include "rpmts.h"
13 
14 #include "build.h"
15 #include "debug.h"
16 
17 /*@access rpmts @*/ /* XXX compared with NULL @*/
18 /*@access rpmdb @*/ /* XXX compared with NULL @*/
19 /*@access FD_t @*/ /* XXX compared with NULL @*/
20 
23 static int checkSpec(rpmts ts, Header h)
24  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
25  /*@modifies ts, h, rpmGlobalMacroContext, fileSystem, internalState @*/
26 {
27  rpmps ps;
28  int rc;
29 
32  return 0;
33 
34  rc = rpmtsAddInstallElement(ts, h, NULL, 0, NULL);
35 
36  rc = rpmtsCheck(ts);
37 
38  ps = rpmtsProblems(ts);
39  if (rc == 0 && rpmpsNumProblems(ps) > 0) {
40  rpmMessage(RPMMESS_ERROR, _("Failed build dependencies:\n"));
41  rpmpsPrint(NULL, ps);
42  rc = 1;
43  }
44  ps = rpmpsFree(ps);
45 
46  /* XXX nuke the added package. */
47  rpmtsClean(ts);
48 
49  return rc;
50 }
51 
52 /*
53  * Kurwa, durni ameryka?ce sobe zawsze my?l?, ?e ca?y ?wiat mówi po
54  * angielsku...
55  */
56 /* XXX this is still a dumb test but at least it's i18n aware */
59 static int isSpecFile(const char * specfile)
60  /*@globals h_errno, fileSystem, internalState @*/
61  /*@modifies fileSystem, internalState @*/
62 {
63  char buf[256];
64  const char * s;
65  FD_t fd;
66  int count;
67  int checking;
68 
69  fd = Fopen(specfile, "r");
70  if (fd == NULL || Ferror(fd)) {
71  rpmError(RPMERR_OPEN, _("Unable to open spec file %s: %s\n"),
72  specfile, Fstrerror(fd));
73  return 0;
74  }
75  count = Fread(buf, sizeof(buf[0]), sizeof(buf), fd);
76  (void) Fclose(fd);
77 
78  checking = 1;
79  for (s = buf; count--; s++) {
80  switch (*s) {
81  case '\r':
82  case '\n':
83  checking = 1;
84  /*@switchbreak@*/ break;
85  case ':':
86  checking = 0;
87  /*@switchbreak@*/ break;
88 /*@-boundsread@*/
89  default:
90  if (checking && !(isprint(*s) || isspace(*s))) return 0;
91  /*@switchbreak@*/ break;
92 /*@=boundsread@*/
93  }
94  }
95  return 1;
96 }
97 
100 /*@-boundswrite@*/
101 static int buildForTarget(rpmts ts, const char * arg, BTA_t ba)
102  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
103  /*@modifies ts, rpmGlobalMacroContext, fileSystem, internalState @*/
104 {
105  const char * passPhrase = ba->passPhrase;
106  const char * cookie = ba->cookie;
107  int buildAmount = ba->buildAmount;
108  const char * specFile;
109  const char * specURL;
110  int specut;
111  char buf[BUFSIZ];
112  Spec spec = NULL;
113  int verify = 1;
114  int xx;
115  int rc;
116 
117 #ifndef DYING
119 #endif
120 
121  /*@-compmempass@*/ /* FIX: static zcmds heartburn */
122  if (ba->buildMode == 't') {
123  FILE *fp;
124  const char * specDir;
125  char * tmpSpecFile;
126  char * cmd, * s;
128  /*@observer@*/ static const char *zcmds[] =
129  { "cat", "gunzip", "bunzip2", "cat" };
130 
131  specDir = rpmGetPath("%{_specdir}", NULL);
132 
133  tmpSpecFile = (char *) rpmGetPath("%{_specdir}/", "rpm-spec.XXXXXX", NULL);
134 #if defined(HAVE_MKSTEMP)
135  (void) close(mkstemp(tmpSpecFile));
136 #else
137  (void) mktemp(tmpSpecFile);
138 #endif
139 
140  (void) isCompressed(arg, &res);
141 
142  cmd = alloca(strlen(arg) + 50 + strlen(tmpSpecFile));
143  sprintf(cmd, "%s < %s | tar xOvf - Specfile 2>&1 > %s",
144  zcmds[res & 0x3], arg, tmpSpecFile);
145  if (!(fp = popen(cmd, "r"))) {
146  rpmError(RPMERR_POPEN, _("Failed to open tar pipe: %m\n"));
147  specDir = _free(specDir);
148  tmpSpecFile = _free(tmpSpecFile);
149  return 1;
150  }
151  if ((!fgets(buf, sizeof(buf) - 1, fp)) || !strchr(buf, '/')) {
152  /* Try again */
153  (void) pclose(fp);
154 
155  sprintf(cmd, "%s < %s | tar xOvf - --wildcards \\*.spec 2>&1 > %s",
156  zcmds[res & 0x3], arg, tmpSpecFile);
157  if (!(fp = popen(cmd, "r"))) {
158  rpmError(RPMERR_POPEN, _("Failed to open tar pipe: %m\n"));
159  specDir = _free(specDir);
160  tmpSpecFile = _free(tmpSpecFile);
161  return 1;
162  }
163  if (!fgets(buf, sizeof(buf) - 1, fp)) {
164  /* Give up */
165  rpmError(RPMERR_READ, _("Failed to read spec file from %s\n"),
166  arg);
167  (void) unlink(tmpSpecFile);
168  specDir = _free(specDir);
169  tmpSpecFile = _free(tmpSpecFile);
170  return 1;
171  }
172  }
173  (void) pclose(fp);
174 
175  cmd = s = buf;
176  while (*cmd != '\0') {
177  if (*cmd == '/') s = cmd + 1;
178  cmd++;
179  }
180 
181  cmd = s;
182 
183  /* remove trailing \n */
184  s = cmd + strlen(cmd) - 1;
185  *s = '\0';
186 
187  specURL = s = alloca(strlen(specDir) + strlen(cmd) + 5);
188  sprintf(s, "%s/%s", specDir, cmd);
189  res = rename(tmpSpecFile, s);
190  specDir = _free(specDir);
191 
192  if (res) {
193  rpmError(RPMERR_RENAME, _("Failed to rename %s to %s: %m\n"),
194  tmpSpecFile, s);
195  (void) unlink(tmpSpecFile);
196  tmpSpecFile = _free(tmpSpecFile);
197  return 1;
198  }
199  tmpSpecFile = _free(tmpSpecFile);
200 
201  /* Make the directory which contains the tarball the source
202  directory for this run */
203 
204  if (*arg != '/') {
205  if (getcwd(buf, BUFSIZ) == NULL) strcpy(buf, ".");
206  strcat(buf, "/");
207  strcat(buf, arg);
208  } else
209  strcpy(buf, arg);
210 
211  cmd = buf + strlen(buf) - 1;
212  while (*cmd != '/') cmd--;
213  *cmd = '\0';
214 
215  addMacro(NULL, "_sourcedir", NULL, buf, RMIL_TARBALL);
216  } else {
217  specURL = arg;
218  }
219  /*@=compmempass@*/
220 
221  specut = urlPath(specURL, &specFile);
222  if (*specFile != '/') {
223  char *s = alloca(BUFSIZ);
224  if (getcwd(s, BUFSIZ) == NULL) strcpy(s, ".");
225  strcat(s, "/");
226  strcat(s, arg);
227  specURL = s;
228  }
229 
230  if (specut != URL_IS_DASH) {
231  struct stat st;
232  if (Stat(specURL, &st) < 0) {
233  rpmError(RPMERR_STAT, _("failed to stat %s: %m\n"), specURL);
234  rc = 1;
235  goto exit;
236  }
237  if (! S_ISREG(st.st_mode)) {
238  rpmError(RPMERR_NOTREG, _("File %s is not a regular file.\n"),
239  specURL);
240  rc = 1;
241  goto exit;
242  }
243 
244  /* Try to verify that the file is actually a specfile */
245  if (!isSpecFile(specURL)) {
247  _("File %s does not appear to be a specfile.\n"), specURL);
248  rc = 1;
249  goto exit;
250  }
251  }
252 
253  /* Parse the spec file */
254 #define _anyarch(_f) \
255 (((_f)&(RPMBUILD_PREP|RPMBUILD_BUILD|RPMBUILD_INSTALL|RPMBUILD_PACKAGEBINARY)) == 0)
256  if (parseSpec(ts, specURL, ba->rootdir, 0, passPhrase,
257  cookie, _anyarch(buildAmount), ba->force, verify))
258  {
259  rc = 1;
260  goto exit;
261  }
262 #undef _anyarch
263  if ((spec = rpmtsSetSpec(ts, NULL)) == NULL) {
264  rc = 1;
265  goto exit;
266  }
267 
268  /* Assemble source header from parsed components */
269  xx = initSourceHeader(spec, NULL);
270 
271  /* Check build prerequisites */
272  if (!ba->noDeps && checkSpec(ts, spec->sourceHeader)) {
273  rc = 1;
274  goto exit;
275  }
276 
277  if (buildSpec(ts, spec, buildAmount, ba->noBuild)) {
278  rc = 1;
279  goto exit;
280  }
281 
282  if (ba->buildMode == 't')
283  (void) Unlink(specURL);
284  rc = 0;
285 
286 exit:
287  spec = freeSpec(spec);
288  return rc;
289 }
290 /*@=boundswrite@*/
291 
292 int build(rpmts ts, const char * arg, BTA_t ba, const char * rcfile)
293 {
294  const char *t, *te;
295  int rc = 0;
296  const char * targets = rpmcliTargets;
297  char *target;
298 #define buildCleanMask (RPMBUILD_RMSOURCE|RPMBUILD_RMSPEC)
299  int cleanFlags = ba->buildAmount & buildCleanMask;
300  rpmVSFlags vsflags, ovsflags;
301  int nbuilds = 0;
302 
303  vsflags = rpmExpandNumeric("%{_vsflags_build}");
304  if (ba->qva_flags & VERIFY_DIGEST)
305  vsflags |= _RPMVSF_NODIGESTS;
306  if (ba->qva_flags & VERIFY_SIGNATURE)
307  vsflags |= _RPMVSF_NOSIGNATURES;
308  if (ba->qva_flags & VERIFY_HDRCHK)
309  vsflags |= RPMVSF_NOHDRCHK;
310  ovsflags = rpmtsSetVSFlags(ts, vsflags);
311 
312  if (targets == NULL) {
313  rc = buildForTarget(ts, arg, ba);
314  nbuilds++;
315  goto exit;
316  }
317 
318  /* parse up the build operators */
319 
320  printf(_("Building target platforms: %s\n"), targets);
321 
322  ba->buildAmount &= ~buildCleanMask;
323  for (t = targets; *t != '\0'; t = te) {
324  /* Parse out next target platform. */
325  if ((te = strchr(t, ',')) == NULL)
326  te = t + strlen(t);
327  target = alloca(te-t+1);
328  strncpy(target, t, (te-t));
329  target[te-t] = '\0';
330  if (*te != '\0')
331  te++;
332  else /* XXX Perform clean-up after last target build. */
333  ba->buildAmount |= cleanFlags;
334 
335  rpmMessage(RPMMESS_DEBUG, D_(" target platform: %s\n"), target);
336 
337  /* Read in configuration for target. */
338  if (t != targets) {
339  rpmFreeMacros(NULL);
340  rpmFreeRpmrc();
341  (void) rpmReadConfigFiles(rcfile, target);
342  }
343  rc = buildForTarget(ts, arg, ba);
344  nbuilds++;
345  if (rc)
346  break;
347  }
348 
349 exit:
350  /* Restore original configuration. */
351  if (nbuilds > 1) {
352  t = targets;
353  if ((te = strchr(t, ',')) == NULL)
354  te = t + strlen(t);
355  target = alloca(te-t+1);
356  strncpy(target, t, (te-t));
357  target[te-t] = '\0';
358  if (*te != '\0')
359  te++;
360  rpmFreeMacros(NULL);
361  rpmFreeRpmrc();
362  (void) rpmReadConfigFiles(rcfile, target);
363  }
364  vsflags = rpmtsSetVSFlags(ts, ovsflags);
365 
366  return rc;
367 }