rpm  5.4.10
build.c
Go to the documentation of this file.
1 
5 #include "system.h"
6 
7 #include <rpmio.h>
8 #include <rpmiotypes.h>
9 #include <rpmcb.h>
10 #include <rpmurl.h>
11 
12 #include <rpmtypes.h>
13 #include <rpmtag.h>
14 
15 #include <rpmbuild.h>
16 
17 #include "rpmps.h"
18 #include "rpmte.h"
19 #include "rpmts.h"
20 
21 #include "build.h"
22 
23 #include <rpmcli.h>
24 
25 #include "debug.h"
26 
27 /*@access rpmts @*/ /* XXX compared with NULL @*/
28 /*@access rpmdb @*/ /* XXX compared with NULL @*/
29 /*@access FD_t @*/ /* XXX compared with NULL @*/
30 
31 #ifdef __cplusplus
32 
33 #define QVA_ISSET(_qvaflags, _FLAG) ((_qvaflags) & (VERIFY_##_FLAG))
34 
35 #define VSF_ISSET(_vsflags, _FLAG) ((_vsflags) & (RPMVSF_##_FLAG))
36 #define VSF_SET(_vsflags, _FLAG) \
37  (*((unsigned *)&(_vsflags)) |= (RPMVSF_##_FLAG))
38 #define VSF_CLR(_vsflags, _FLAG) \
39  (*((unsigned *)&(_vsflags)) &= ~(RPMVSF_##_FLAG))
40 
41 #else /* __cplusplus */
42 
43 #define QVA_ISSET(_qvaflags, _FLAG) ((_qvaflags) & (VERIFY_##_FLAG))
44 
45 #define VSF_ISSET(_vsflags, _FLAG) ((_vsflags) & (RPMVSF_##_FLAG))
46 #define VSF_SET(_vsflags, _FLAG) (_vsflags) |= (RPMVSF_##_FLAG)
47 #define VSF_CLR(_vsflags, _FLAG) (_vsflags) &= ~(RPMVSF_##_FLAG)
48 
49 #endif /* __cplusplus */
50 
53 static int checkSpec(rpmts ts, Header h)
54  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
55  /*@modifies ts, h, rpmGlobalMacroContext, fileSystem, internalState @*/
56 {
57  int rc;
58 
61  return 0;
62 
63  rc = rpmtsAddInstallElement(ts, h, NULL, 0, NULL);
64 
65  rc = rpmcliInstallProblems(ts, _("Failed build dependencies"), rpmtsCheck(ts));
66 
67  /* XXX nuke the added package. */
68  rpmtsClean(ts);
69 
70  return rc;
71 }
72 
73 /*
74  * Kurwa, durni ameryka?ce sobe zawsze my?l?, ?e ca?y ?wiat mówi po
75  * angielsku...
76  */
77 /* XXX this is still a dumb test but at least it's i18n aware */
80 static int isSpecFile(const char * specfile)
81  /*@globals h_errno, fileSystem, internalState @*/
82  /*@modifies fileSystem, internalState @*/
83 {
84  char buf[256];
85  const char * s;
86  FD_t fd;
87  int count;
88  int checking;
89 
90  fd = Fopen(specfile, "r");
91  if (fd == NULL || Ferror(fd)) {
92  rpmlog(RPMLOG_ERR, _("Unable to open spec file %s: %s\n"),
93  specfile, Fstrerror(fd));
94  return 0;
95  }
96  count = Fread(buf, sizeof(buf[0]), sizeof(buf), fd);
97  (void) Fclose(fd);
98 
99  checking = 1;
100  for (s = buf; count--; s++) {
101  switch (*s) {
102  case '\r':
103  case '\n':
104  checking = 1;
105  /*@switchbreak@*/ break;
106  case ':':
107  checking = 0;
108  /*@switchbreak@*/ break;
109 /*@-boundsread@*/
110  default:
111  if (checking && !(isprint(*s) || isspace(*s))) return 0;
112  /*@switchbreak@*/ break;
113 /*@=boundsread@*/
114  }
115  }
116  return 1;
117 }
118 
121 /*@-boundswrite@*/
122 static int buildForTarget(rpmts ts, BTA_t ba)
123  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
124  /*@modifies ts, rpmGlobalMacroContext, fileSystem, internalState @*/
125 {
126  const char * passPhrase = ba->passPhrase;
127  const char * cookie = ba->cookie;
128  int buildAmount = ba->buildAmount;
129  const char * specFile = NULL;
130  const char * specURL = NULL;
131  int specut;
132  const char * s;
133  char * se;
134  const char * arg = ba->specFile;
135  size_t nb = strlen(arg) + BUFSIZ;
136  char * buf = (char *) alloca(nb);
137  Spec spec = NULL;
138  int verify = ((ba->buildAmount & RPMBUILD_TRACK) ? 0 : 1);
139  int xx;
140  int rc;
141 
142  if (ba->buildMode == 't') {
143  static const char * sfpats[] = { "Specfile", "\\*.spec", NULL };
144  static const char _specfn[] = "%{mkstemp:%{_specdir}/rpm-spec.XXXXXX}";
145  char * tmpSpecFile = (char *) rpmGetPath(_specfn, NULL);
146  FILE *fp;
147  int bingo = 0;
148  int i;
149 
150  for (i = 0; sfpats[i]; i++) {
151  se = rpmExpand("%{uncompress: %{u2p:", arg, "}}",
152  " | %{__tar} -xOvf - %{?__tar_wildcards} ", sfpats[i],
153  " 2>&1 > '", tmpSpecFile, "'", NULL);
154  fp = popen(se, "r");
155  se = _free(se);
156  if (fp== NULL)
157  continue;
158  s = fgets(buf, nb - 1, fp);
159  xx = pclose(fp);
160  if (!s || !*s || strstr(s, ": Not found in archive"))
161  continue;
162  bingo = 1;
163  break;
164  }
165  if (!bingo) {
166  rpmlog(RPMLOG_ERR, _("Failed to read spec file from %s\n"), arg);
167  xx = Unlink(tmpSpecFile);
168  tmpSpecFile = _free(tmpSpecFile);
169  return 1;
170  }
171 
172  s = se = basename(buf);
173  se += strlen(se);
174  while (--se > s && strchr("\r\n", *se) != NULL)
175  *se = '\0';
176  specURL = rpmGetPath("%{_specdir}/", s, NULL);
177  specut = urlPath(specURL, &specFile);
178  xx = Rename(tmpSpecFile, specFile);
179  if (xx) {
180  rpmlog(RPMLOG_ERR, _("Failed to rename %s to %s: %m\n"),
181  tmpSpecFile, s);
182  (void) Unlink(tmpSpecFile);
183  }
184  tmpSpecFile = _free(tmpSpecFile);
185  if (xx)
186  return 1;
187 
188  se = buf; *se = '\0';
189  se = stpcpy(se, "_sourcedir ");
190  (void) urlPath(arg, &s);
191  if (*s != '/') {
192  if (getcwd(se, nb - sizeof("_sourcedir ")) != NULL)
193  se += strlen(se);
194  else
195  se = stpcpy(se, ".");
196  } else
197  se = stpcpy(se, dirname(strcpy(se, s)));
198  while (se > buf && se[-1] == '/')
199  *se-- = '0';
200  rpmCleanPath(buf + sizeof("_sourcedir ") - 1);
201  rpmDefineMacro(NULL, buf, RMIL_TARBALL);
202  } else {
203  specut = urlPath(arg, &s);
204  se = buf; *se = '\0';
205  if (*s != '/') {
206  if (getcwd(se, nb - sizeof("_sourcedir ")) != NULL)
207  se += strlen(se);
208  else
209  se = stpcpy(se, ".");
210  *se++ = '/';
211  se += strlen(strcpy(se,strcpy(se, s)));
212  } else
213  se = stpcpy(se, s);
214  specURL = rpmGetPath(buf, NULL);
215  specut = urlPath(specURL, &specFile);
216  }
217 
218  if (specut != URL_IS_DASH) {
219  struct stat sb;
220  if (Stat(specURL, &sb) < 0) {
221  rpmlog(RPMLOG_ERR, _("failed to stat %s: %m\n"), specURL);
222  rc = 1;
223  goto exit;
224  }
225  if (! S_ISREG(sb.st_mode)) {
226  rpmlog(RPMLOG_ERR, _("File %s is not a regular file.\n"),
227  specURL);
228  rc = 1;
229  goto exit;
230  }
231 
232  /* Try to verify that the file is actually a specfile */
233  if (!isSpecFile(specURL)) {
235  _("File %s does not appear to be a specfile.\n"), specURL);
236  rc = 1;
237  goto exit;
238  }
239  }
240 
241  /* Parse the spec file */
242 #define _anyarch(_f) \
243 (((_f)&(RPMBUILD_PREP|RPMBUILD_BUILD|RPMBUILD_INSTALL|RPMBUILD_PACKAGEBINARY)) == 0)
244  if (parseSpec(ts, specURL, ba->rootdir, 0, passPhrase,
245  cookie, _anyarch(buildAmount), 0, verify))
246  {
247  rc = 1;
248  goto exit;
249  }
250 #undef _anyarch
251  if ((spec = rpmtsSetSpec(ts, NULL)) == NULL) {
252  rc = 1;
253  goto exit;
254  }
255 
256  /* Assemble source header from parsed components */
257  xx = initSourceHeader(spec, NULL);
258 
259  /* Check build prerequisites */
260  if (!ba->noDeps && checkSpec(ts, spec->sourceHeader)) {
261  rc = 1;
262  goto exit;
263  }
264 
265  if (buildSpec(ts, spec, buildAmount, ba->noBuild)) {
266  rc = 1;
267  goto exit;
268  }
269 
270  if (ba->buildMode == 't')
271  (void) Unlink(specURL);
272  rc = 0;
273 
274 exit:
275  spec = freeSpec(spec);
276  specURL = _free(specURL);
277  return rc;
278 }
279 /*@=boundswrite@*/
280 
281 int build(rpmts ts, BTA_t ba, const char * rcfile)
282 {
283  const char *t, *te;
284  int rc = 0;
285  const char * targets = rpmcliTargets;
286  char *target;
287 #define buildCleanMask (RPMBUILD_RMSOURCE|RPMBUILD_RMSPEC)
288  int cleanFlags = ba->buildAmount & buildCleanMask;
289  rpmVSFlags vsflags, ovsflags;
290  int nbuilds = 0;
291 
292  vsflags = (rpmVSFlags) rpmExpandNumeric("%{?_vsflags_build}");
293  vsflags = (rpmVSFlags) 0; /* XXX FIXME: ignore default disablers. */
294 #if defined(SUPPORT_NOSIGNATURES)
295  if (!QVA_ISSET(ba->qva_flags, DIGEST)) {
296  VSF_SET(vsflags, NOSHA1HEADER);
297  VSF_SET(vsflags, NOMD5HEADER);
298  VSF_SET(vsflags, NOSHA1);
299  VSF_SET(vsflags, NOMD5);
300  }
301  if (!QVA_ISSET(ba->qva_flags, SIGNATURE)) {
302  VSF_SET(vsflags, NODSAHEADER);
303  VSF_SET(vsflags, NORSAHEADER);
304  VSF_SET(vsflags, NODSA);
305  VSF_SET(vsflags, NORSA);
306  }
307  if (!QVA_ISSET(ba->qva_flags, HDRCHK)) {
308  VSF_SET(vsflags, NOHDRCHK);
309  }
310  VSF_CLR(vsflags, NEEDPAYLOAD); /* XXX needed? */
311 #endif
312  ovsflags = rpmtsSetVSFlags(ts, vsflags);
313 
314  if (targets == NULL) {
315  rc = buildForTarget(ts, ba);
316  nbuilds++;
317  goto exit;
318  }
319 
320  /* parse up the build operators */
321 
322  printf(_("Building target platforms: %s\n"), targets);
323 
324  ba->buildAmount &= ~buildCleanMask;
325  for (t = targets; *t != '\0'; t = te) {
326  /* Parse out next target platform. */
327  if ((te = strchr(t, ',')) == NULL)
328  te = t + strlen(t);
329  target = (char *) alloca(te-t+1);
330  strncpy(target, t, (te-t));
331  target[te-t] = '\0';
332  if (*te != '\0')
333  te++;
334  else /* XXX Perform clean-up after last target build. */
335  ba->buildAmount |= cleanFlags;
336 
337  rpmlog(RPMLOG_DEBUG, _(" target platform: %s\n"), target);
338 
339  /* Read in configuration for target. */
340  if (t != targets) {
341  rpmFreeMacros(NULL);
342  rpmFreeRpmrc();
343  (void) rpmReadConfigFiles(rcfile, target);
344  }
345  rc = buildForTarget(ts, ba);
346  nbuilds++;
347  if (rc)
348  break;
349  }
350 
351 exit:
352  /* Restore original configuration. */
353  if (nbuilds > 1) {
354  t = targets;
355  if ((te = strchr(t, ',')) == NULL)
356  te = t + strlen(t);
357  target = (char *) alloca(te-t+1);
358  strncpy(target, t, (te-t));
359  target[te-t] = '\0';
360  if (*te != '\0')
361  te++;
362  rpmFreeMacros(NULL);
363  rpmFreeRpmrc();
364  (void) rpmReadConfigFiles(rcfile, target);
365  }
366  vsflags = rpmtsSetVSFlags(ts, ovsflags);
367 
368  return rc;
369 }
void rpmFreeMacros(MacroContext mc)
Destroy macro context.
Definition: macro.c:2966
#define _anyarch(_f)
int build(rpmts ts, BTA_t ba, const char *rcfile)
Definition: build.c:281
int headerIsEntry(Header h, rpmTag tag)
Check if tag is in header.
Definition: header.c:1431
static int buildForTarget(rpmts ts, BTA_t ba)
Definition: build.c:122
#define QVA_ISSET(_qvaflags, _FLAG)
Structures used for an "rpmte" transaction element.
char * rpmCleanPath(char *path)
Canonicalize file path.
Definition: macro.c:3218
FD_t Fopen(const char *path, const char *_fmode)
fopen(3) clone.
Definition: rpmio.c:2833
int rpmtsAddInstallElement(rpmts ts, Header h, fnpyKey key, int upgrade, rpmRelocation relocs)
Add package to be installed to transaction set.
Definition: depends.c:552
int rpmReadConfigFiles(const char *file, const char *target)
Definition: rpmrc.c:1099
char * rpmGetPath(const char *path,...)
Return (malloc&#39;ed) expanded, canonicalized, file path.
Definition: macro.c:3310
The Header data structure.
int Stat(const char *path, struct stat *st)
stat(2) clone.
Definition: rpmrpc.c:1361
static rpmVSFlags vsflags
Definition: rpmcache.c:547
Header sourceHeader
Definition: rpmspec.h:166
static void rpmlog(int code, const char *fmt,...)
Definition: rpmlog.h:299
int parseSpec(rpmts ts, const char *specFile, const char *rootURL, int recursing, const char *passPhrase, const char *cookie, int anyarch, int force, int verify)
Parse spec file into spec control structure.
Definition: parseSpec.c:527
char * alloca()
const char * Fstrerror(FD_t fd)
strerror(3) clone.
Definition: rpmio.c:2401
const char * specFile
Definition: rpmcli.h:729
const char * rootdir
Definition: rpmcli.h:739
Structures and prototypes used for an "rpmps" problem set.
int rpmcliInstallProblems(rpmts ts, const char *msg, int rc)
Report package problems (if any).
Definition: rpminstall.c:308
int Rename(const char *oldpath, const char *newpath)
rename(2) clone.
Definition: rpmrpc.c:286
int(* rpmtsCheck)(rpmts ts)
Perform dependency resolution on the transaction set.
Definition: depends.c:2080
int rpmDefineMacro(MacroContext mc, const char *macro, int level)
Define macro in context.
Definition: macro.c:2739
const char * rpmcliTargets
Definition: poptALL.c:175
The FD_t File Handle data structure.
The structure used to store values parsed from a spec file.
Definition: rpmspec.h:108
pgpVSFlags rpmVSFlags
Bit(s) to control digest and signature verification.
Definition: rpmts.h:30
char * rpmExpand(const char *arg,...)
Return (malloc&#39;ed) concatenated macro expansion(s).
Definition: macro.c:3117
Spec freeSpec(Spec spec)
Destroy a spec file control structure.
size_t Fread(void *buf, size_t size, size_t nmemb, FD_t fd)
fread(3) clone.
Definition: rpmio.c:2412
int Fclose(FD_t fd)
fclose(3) clone.
Definition: rpmio.c:2534
#define VSF_SET(_vsflags, _FLAG)
Spec rpmtsSetSpec(rpmts ts, Spec spec)
Set a spec control structure in transaction set.
Definition: rpmts.c:1395
static int checkSpec(rpmts ts, Header h)
Definition: build.c:53
#define buildCleanMask
int Ferror(FD_t fd)
ferror(3) clone.
Definition: rpmio.c:2944
urltype urlPath(const char *url, const char **pathp)
Return path component of URL.
Definition: url.c:429
This is the only module users of librpmbuild should need to include.
rpmVSFlags rpmtsSetVSFlags(rpmts ts, rpmVSFlags vsflags)
Set verify signatures flag(s).
Definition: rpmts.c:843
char * stpcpy(char *dest, const char *src)
struct rpmts_s * rpmts
The RPM Transaction Set.
Definition: rpmtypes.h:14
static void * _free(const void *p)
Wrapper to free(3), hides const compilation noise, permit NULL, return NULL.
Definition: rpmiotypes.h:647
Structures and prototypes used for an "rpmts" transaction set.
#define RMIL_TARBALL
Definition: rpmmacro.h:55
#define _(Text)
Definition: system.h:30
static int isSpecFile(const char *specfile)
Definition: build.c:80
int initSourceHeader(Spec spec, rpmiob *sfp)
Create and initialize header for source package.
Definition: files.c:2552
Describe build command line request.
Definition: rpmcli.h:722
int rpmExpandNumeric(const char *arg)
Return macro expansion as a numeric value.
Definition: macro.c:3191
rpmRC buildSpec(rpmts ts, Spec spec, int what, int test)
Build stages state machine driver.
Definition: build.c:338
rpmQueryFlags qva_flags
Definition: rpmcli.h:723
const char * cookie
Definition: rpmcli.h:728
void rpmFreeRpmrc(void)
Definition: rpmrc.c:1008
const char * passPhrase
Definition: rpmcli.h:726
void rpmtsClean(rpmts ts)
Free memory needed only for dependency checks and ordering.
Definition: rpmts.c:596
#define VSF_CLR(_vsflags, _FLAG)
int Unlink(const char *path)
unlink(2) clone.
Definition: rpmrpc.c:397