rpm  5.2.1
pack.c
Go to the documentation of this file.
1 
6 #include "system.h"
7 
8 #include <rpmio_internal.h> /* XXX fdGetFp, fdInitDigest, fdFiniDigest */
9 #include <rpmcb.h>
10 #include <argv.h>
11 
12 #include <rpmtypes.h>
13 #include <rpmtag.h>
14 
15 #include <pkgio.h>
16 #include "signature.h" /* XXX rpmTempFile */
17 
18 #define _RPMFI_INTERNAL /* XXX fi->fsm */
19 #define _RPMEVR_INTERNAL /* XXX RPMSENSE_ANY */
20 #define _RPMTAG_INTERNAL
21 #include <rpmbuild.h>
22 
23 #include "rpmfi.h"
24 #include "fsm.h"
25 
26 #include <rpmversion.h>
27 #include "buildio.h"
28 
29 #include "debug.h"
30 
31 /*@access rpmts @*/
32 /*@access rpmfi @*/ /* compared with NULL */
33 /*@access Header @*/ /* compared with NULL */
34 /*@access FD_t @*/ /* compared with NULL */
35 /*@access CSA_t @*/
36 
40 static rpmRC cpio_doio(FD_t fdo, /*@unused@*/ Header h, CSA_t csa,
41  const char * payload_format, const char * fmodeMacro)
42  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
43  /*@modifies fdo, csa, rpmGlobalMacroContext,
44  fileSystem, internalState @*/
45 {
46  rpmts ts = rpmtsCreate();
47  rpmfi fi = csa->cpioList;
48  const char *failedFile = NULL;
49  FD_t cfd;
50  rpmRC rc = RPMRC_OK;
51  int xx;
52 
53  { const char *fmode = rpmExpand(fmodeMacro, NULL);
54  if (!(fmode && fmode[0] == 'w'))
55  fmode = xstrdup("w9.gzdio");
56  /*@-nullpass@*/
57  (void) Fflush(fdo);
58  cfd = Fdopen(fdDup(Fileno(fdo)), fmode);
59  /*@=nullpass@*/
60  fmode = _free(fmode);
61  }
62  if (cfd == NULL)
63  return RPMRC_FAIL;
64 
65  xx = fsmSetup(fi->fsm, IOSM_PKGBUILD, payload_format, ts, fi, cfd,
66  &csa->cpioArchiveSize, &failedFile);
67  if (xx)
68  rc = RPMRC_FAIL;
69  (void) Fclose(cfd);
70  xx = fsmTeardown(fi->fsm);
71  if (rc == RPMRC_OK && xx) rc = RPMRC_FAIL;
72 
73  if (rc) {
74  const char * msg = iosmStrerror(rc);
75  if (failedFile)
76  rpmlog(RPMLOG_ERR, _("create archive failed on file %s: %s\n"),
77  failedFile, msg);
78  else
79  rpmlog(RPMLOG_ERR, _("create archive failed: %s\n"), msg);
80  msg = _free(msg);
81  rc = RPMRC_FAIL;
82  }
83 
84  failedFile = _free(failedFile);
85  (void)rpmtsFree(ts);
86  ts = NULL;
87 
88  return rc;
89 }
90 
93 static rpmRC cpio_copy(FD_t fdo, CSA_t csa)
94  /*@globals fileSystem, internalState @*/
95  /*@modifies fdo, csa, fileSystem, internalState @*/
96 {
97  char buf[BUFSIZ];
98  size_t nb;
99 
100  while((nb = Fread(buf, sizeof(buf[0]), sizeof(buf), csa->cpioFdIn)) > 0) {
101  if (Fwrite(buf, sizeof(buf[0]), nb, fdo) != nb) {
102  rpmlog(RPMLOG_ERR, _("cpio_copy write failed: %s\n"),
103  Fstrerror(fdo));
104  return RPMRC_FAIL;
105  }
106  csa->cpioArchiveSize += nb;
107  }
108  if (Ferror(csa->cpioFdIn)) {
109  rpmlog(RPMLOG_ERR, _("cpio_copy read failed: %s\n"),
110  Fstrerror(csa->cpioFdIn));
111  return RPMRC_FAIL;
112  }
113  return RPMRC_OK;
114 }
115 
118 static /*@only@*/ /*@null@*/ rpmiob addFileToTagAux(Spec spec,
119  const char * file, /*@only@*/ rpmiob iob)
120  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
121  /*@modifies rpmGlobalMacroContext, fileSystem, internalState @*/
122 {
123  char buf[BUFSIZ];
124  const char * fn = buf;
125  FILE * f;
126  FD_t fd;
127 
128  fn = rpmGetPath("%{_builddir}/%{?buildsubdir:%{buildsubdir}/}", file, NULL);
129 
130  fd = Fopen(fn, "r.fdio");
131  if (fn != buf) fn = _free(fn);
132  if (fd == NULL || Ferror(fd)) {
133  iob = rpmiobFree(iob);
134  return NULL;
135  }
136  /*@-type@*/ /* FIX: cast? */
137  if ((f = fdGetFp(fd)) != NULL)
138  /*@=type@*/
139  while (fgets(buf, (int)sizeof(buf), f)) {
140  /* XXX display fn in error msg */
141  if (expandMacros(spec, spec->macros, buf, sizeof(buf))) {
142  rpmlog(RPMLOG_ERR, _("line: %s\n"), buf);
143  iob = rpmiobFree(iob);
144  break;
145  }
146  iob = rpmiobAppend(iob, buf, 0);
147  }
148  (void) Fclose(fd);
149 
150  return iob;
151 }
152 
155 static int addFileToTag(Spec spec, const char * file, Header h, rpmTag tag)
156  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
157  /*@modifies h, rpmGlobalMacroContext, fileSystem, internalState @*/
158 {
159  HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
160  rpmiob iob = rpmiobNew(0);
161  int xx;
162 
163  he->tag = tag;
164  xx = headerGet(h, he, 0);
165  if (xx) {
166  iob = rpmiobAppend(iob, he->p.str, 1);
167  xx = headerDel(h, he, 0);
168  }
169  he->p.ptr = _free(he->p.ptr);
170 
171  if ((iob = addFileToTagAux(spec, file, iob)) == NULL)
172  return 1;
173 
174  he->tag = tag;
175  he->t = RPM_STRING_TYPE;
176  he->p.str = rpmiobStr(iob);
177  he->c = 1;
178  xx = headerPut(h, he, 0);
179 
180  iob = rpmiobFree(iob);
181  return 0;
182 }
183 
186 static int addFileToArrayTag(Spec spec, const char *file, Header h, rpmTag tag)
187  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
188  /*@modifies h, rpmGlobalMacroContext, fileSystem, internalState @*/
189 {
190  HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
191  rpmiob iob = rpmiobNew(0);
192  const char *s;
193  int xx;
194 
195  if ((iob = addFileToTagAux(spec, file, iob)) == NULL)
196  return 1;
197 
198  s = rpmiobStr(iob);
199 
200  he->tag = tag;
201  he->t = RPM_STRING_ARRAY_TYPE;
202  he->p.argv = &s;
203  he->c = 1;
204  he->append = 1;
205  xx = headerPut(h, he, 0);
206  he->append = 0;
207 
208  iob = rpmiobFree(iob);
209  return 0;
210 }
211 
213  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
214  /*@modifies pkg->header, rpmGlobalMacroContext,
215  fileSystem, internalState @*/
216 {
217  HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
218  struct TriggerFileEntry *p;
219  int xx;
220 
221  if (pkg->preInFile) {
222  if (addFileToTag(spec, pkg->preInFile, pkg->header, RPMTAG_PREIN)) {
224  _("Could not open PreIn file: %s\n"), pkg->preInFile);
225  return RPMRC_FAIL;
226  }
227  }
228  if (pkg->preUnFile) {
229  if (addFileToTag(spec, pkg->preUnFile, pkg->header, RPMTAG_PREUN)) {
231  _("Could not open PreUn file: %s\n"), pkg->preUnFile);
232  return RPMRC_FAIL;
233  }
234  }
235  if (pkg->preTransFile) {
236  if (addFileToTag(spec, pkg->preTransFile, pkg->header, RPMTAG_PRETRANS)) {
238  _("Could not open PreTrans file: %s\n"), pkg->preTransFile);
239  return RPMRC_FAIL;
240  }
241  }
242  if (pkg->postInFile) {
243  if (addFileToTag(spec, pkg->postInFile, pkg->header, RPMTAG_POSTIN)) {
245  _("Could not open PostIn file: %s\n"), pkg->postInFile);
246  return RPMRC_FAIL;
247  }
248  }
249  if (pkg->postUnFile) {
250  if (addFileToTag(spec, pkg->postUnFile, pkg->header, RPMTAG_POSTUN)) {
252  _("Could not open PostUn file: %s\n"), pkg->postUnFile);
253  return RPMRC_FAIL;
254  }
255  }
256  if (pkg->postTransFile) {
257  if (addFileToTag(spec, pkg->postTransFile, pkg->header, RPMTAG_POSTTRANS)) {
259  _("Could not open PostTrans file: %s\n"), pkg->postTransFile);
260  return RPMRC_FAIL;
261  }
262  }
263  if (pkg->verifyFile) {
264  if (addFileToTag(spec, pkg->verifyFile, pkg->header,
267  _("Could not open VerifyScript file: %s\n"), pkg->verifyFile);
268  return RPMRC_FAIL;
269  }
270  }
271 
272  if (pkg->sanityCheckFile) {
273  if (addFileToTag(spec, pkg->sanityCheckFile, pkg->header, RPMTAG_SANITYCHECK)) {
274  rpmlog(RPMLOG_ERR, _("Could not open Test file: %s\n"), pkg->sanityCheckFile);
275  return RPMRC_FAIL;
276  }
277  }
278 
279  for (p = pkg->triggerFiles; p != NULL; p = p->next) {
281  he->t = RPM_STRING_ARRAY_TYPE;
282  he->p.argv = (const char **)&p->prog; /* XXX NOCAST */
283  he->c = 1;
284  he->append = 1;
285  xx = headerPut(pkg->header, he, 0);
286  he->append = 0;
287  if (p->script) {
289  he->t = RPM_STRING_ARRAY_TYPE;
290  he->p.argv = (const char **)&p->script; /* XXX NOCAST */
291  he->c = 1;
292  he->append = 1;
293  xx = headerPut(pkg->header, he, 0);
294  he->append = 0;
295  } else if (p->fileName) {
296  if (addFileToArrayTag(spec, p->fileName, pkg->header,
299  _("Could not open Trigger script file: %s\n"),
300  p->fileName);
301  return RPMRC_FAIL;
302  }
303  } else {
304  /*@observer@*/
305  static const char *bull = "";
307  he->t = RPM_STRING_ARRAY_TYPE;
308  he->p.argv = &bull;
309  he->c = 1;
310  he->append = 1;
311  xx = headerPut(pkg->header, he, 0);
312  he->append = 0;
313  }
314  }
315 
316  return RPMRC_OK;
317 }
318 
319 #if defined(DEAD)
320 int readRPM(const char *fileName, Spec *specp, void * l,
321  Header *sigs, CSA_t csa)
322 {
323  const char * msg = "";
324  FD_t fdi;
325  Spec spec;
326  rpmRC rc;
327 
328  fdi = (fileName != NULL)
329  ? Fopen(fileName, "r.fdio")
330  : fdDup(STDIN_FILENO);
331 
332  if (fdi == NULL || Ferror(fdi)) {
333  rpmlog(RPMLOG_ERR, _("readRPM: open %s: %s\n"),
334  (fileName ? fileName : "<stdin>"),
335  Fstrerror(fdi));
336  if (fdi) (void) Fclose(fdi);
337  return RPMRC_FAIL;
338  }
339 
340  { const char item[] = "Lead";
341  size_t nl = rpmpkgSizeof(item, NULL);
342 
343  if (nl == 0) {
344  rc = RPMRC_FAIL;
345  msg = xstrdup("item size is zero");
346  } else {
347  l = xcalloc(1, nl); /* XXX memory leak */
348  msg = NULL;
349  rc = rpmpkgRead(item, fdi, l, &msg);
350  }
351  }
352 
353  if (rc != RPMRC_OK) {
354  rpmlog(RPMLOG_ERR, _("readRPM: read %s: %s\n"),
355  (fileName ? fileName : "<stdin>"), msg);
356  msg = _free(msg);
357  return RPMRC_FAIL;
358  }
359  msg = _free(msg);
360  /*@=sizeoftype@*/
361 
362  /* XXX FIXME: EPIPE on <stdin> */
363  if (Fseek(fdi, 0, SEEK_SET) == -1) {
364  rpmlog(RPMLOG_ERR, _("%s: Fseek failed: %s\n"),
365  (fileName ? fileName : "<stdin>"), Fstrerror(fdi));
366  return RPMRC_FAIL;
367  }
368 
369  /* Reallocate build data structures */
370  spec = newSpec();
371  spec->packages = newPackage(spec);
372 
373  /* XXX the header just allocated will be allocated again */
374  (void)headerFree(spec->packages->header);
375  spec->packages->header = NULL;
376 
377  /* Read the rpm lead, signatures, and header */
378  { rpmts ts = rpmtsCreate();
379 
380  /* XXX W2DO? pass fileName? */
381  /*@-mustmod@*/ /* LCL: segfault */
382  rc = rpmReadPackageFile(ts, fdi, "readRPM",
383  &spec->packages->header);
384  /*@=mustmod@*/
385 
386  (void)rpmtsFree(ts);
387  ts = NULL;
388 
389  if (sigs) *sigs = NULL; /* XXX HACK */
390  }
391 
392  switch (rc) {
393  case RPMRC_OK:
394  case RPMRC_NOKEY:
395  case RPMRC_NOTTRUSTED:
396  break;
397  case RPMRC_NOTFOUND:
398  rpmlog(RPMLOG_ERR, _("readRPM: %s is not an RPM package\n"),
399  (fileName ? fileName : "<stdin>"));
400  return RPMRC_FAIL;
401  case RPMRC_FAIL:
402  default:
403  rpmlog(RPMLOG_ERR, _("readRPM: reading header from %s\n"),
404  (fileName ? fileName : "<stdin>"));
405  return RPMRC_FAIL;
406  /*@notreached@*/ break;
407  }
408 
409  if (specp)
410  *specp = spec;
411  else
412  spec = freeSpec(spec);
413 
414  if (csa != NULL)
415  csa->cpioFdIn = fdi;
416  else
417  (void) Fclose(fdi);
418 
419  return 0;
420 }
421 #endif
422 
423 #if defined(DEAD)
424 #define RPMPKGVERSION_MIN 30004
425 #define RPMPKGVERSION_MAX 40003
426 /*@unchecked@*/
427 static int rpmpkg_version = -1;
428 
429 static int rpmLeadVersion(void)
430  /*@globals rpmpkg_version, rpmGlobalMacroContext, h_errno @*/
431  /*@modifies rpmpkg_version, rpmGlobalMacroContext @*/
432 {
433  int rpmlead_version;
434 
435  /* Intitialize packaging version from macro configuration. */
436  if (rpmpkg_version < 0) {
437  rpmpkg_version = rpmExpandNumeric("%{_package_version}");
438  if (rpmpkg_version < RPMPKGVERSION_MIN)
439  rpmpkg_version = RPMPKGVERSION_MIN;
440  if (rpmpkg_version > RPMPKGVERSION_MAX)
441  rpmpkg_version = RPMPKGVERSION_MAX;
442  }
443 
444  rpmlead_version = rpmpkg_version / 10000;
445  /* XXX silly sanity check. */
446  if (rpmlead_version < 3 || rpmlead_version > 4)
447  rpmlead_version = 3;
448  return rpmlead_version;
449 }
450 #endif
451 
453 {
454  HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
455  const char *N, *V, *R;
456 #ifdef RPM_VENDOR_MANDRIVA
457  const char *D;
458  int gotD;
459 #endif
460  rpmuint32_t E;
461  int gotE;
462  const char *pEVR;
463  char *p;
464  rpmuint32_t pFlags = RPMSENSE_EQUAL;
465  const char ** provides = NULL;
466  const char ** providesEVR = NULL;
467  rpmuint32_t * provideFlags = NULL;
468  int providesCount;
469  int bingo = 1;
470  size_t nb;
471  int xx;
472  int i;
473 
474  /* Generate provides for this package N-V-R. */
475  xx = headerNEVRA(h, &N, NULL, &V, &R, NULL);
476  if (!(N && V && R))
477  return;
478 
479  nb = 21 + strlen(V) + 1 + strlen(R) + 1;
480 #ifdef RPM_VENDOR_MANDRIVA
481  he->tag = RPMTAG_DISTEPOCH;
482  gotD = headerGet(h, he, 0);
483  D = (he->p.str ? he->p.str : NULL);
484  nb += (gotD ? strlen(D) + 1 : 0);
485 #endif
486  pEVR = p = alloca(nb);
487  *p = '\0';
488  he->tag = RPMTAG_EPOCH;
489  gotE = headerGet(h, he, 0);
490  E = (he->p.ui32p ? he->p.ui32p[0] : 0);
491  he->p.ptr = _free(he->p.ptr);
492  if (gotE) {
493  sprintf(p, "%d:", E);
494  p += strlen(p);
495  }
496  p = stpcpy( stpcpy( stpcpy(p, V) , "-") , R);
497 #ifdef RPM_VENDOR_MANDRIVA
498  if (gotD) {
499  p = stpcpy( stpcpy( p, ":"), D);
500  D = _free(D);
501  }
502 #endif
503  V = _free(V);
504  R = _free(R);
505 
506  /*
507  * Rpm prior to 3.0.3 does not have versioned provides.
508  * If no provides at all are available, we can just add.
509  */
510  he->tag = RPMTAG_PROVIDENAME;
511 /*@-nullstate@*/
512  xx = headerGet(h, he, 0);
513 /*@=nullstate@*/
514  provides = he->p.argv;
515  providesCount = he->c;
516  if (!xx)
517  goto exit;
518 
519  /*
520  * Otherwise, fill in entries on legacy packages.
521  */
523 /*@-nullstate@*/
524  xx = headerGet(h, he, 0);
525 /*@=nullstate@*/
526  providesEVR = he->p.argv;
527  if (!xx) {
528  for (i = 0; i < providesCount; i++) {
529  /*@observer@*/
530  static const char * vdummy = "";
531  static rpmsenseFlags fdummy = RPMSENSE_ANY;
532 
534  he->t = RPM_STRING_ARRAY_TYPE;
535  he->p.argv = &vdummy;
536  he->c = 1;
537  he->append = 1;
538 /*@-nullstate@*/
539  xx = headerPut(h, he, 0);
540 /*@=nullstate@*/
541  he->append = 0;
542 
543  he->tag = RPMTAG_PROVIDEFLAGS;
544  he->t = RPM_UINT32_TYPE;
545  he->p.ui32p = (rpmuint32_t *) &fdummy;
546  he->c = 1;
547  he->append = 1;
548 /*@-nullstate@*/
549  xx = headerPut(h, he, 0);
550 /*@=nullstate@*/
551  he->append = 0;
552  }
553  goto exit;
554  }
555 
556  he->tag = RPMTAG_PROVIDEFLAGS;
557 /*@-nullstate@*/
558  xx = headerGet(h, he, 0);
559 /*@=nullstate@*/
560  provideFlags = he->p.ui32p;
561 
562  /*@-nullderef@*/ /* LCL: providesEVR is not NULL */
563  if (provides && providesEVR && provideFlags)
564  for (i = 0; i < providesCount; i++) {
565  if (!(provides[i] && providesEVR[i]))
566  continue;
567  if (!(provideFlags[i] == RPMSENSE_EQUAL &&
568  !strcmp(N, provides[i]) && !strcmp(pEVR, providesEVR[i])))
569  continue;
570  bingo = 0;
571  break;
572  }
573  /*@=nullderef@*/
574 
575 exit:
576 /*@-usereleased@*/
577  provides = _free(provides);
578  providesEVR = _free(providesEVR);
579  provideFlags = _free(provideFlags);
580 /*@=usereleased@*/
581 
582  if (bingo) {
583  he->tag = RPMTAG_PROVIDENAME;
584  he->t = RPM_STRING_ARRAY_TYPE;
585  he->p.argv = &N;
586  he->c = 1;
587  he->append = 1;
588 /*@-nullstate@*/
589  xx = headerPut(h, he, 0);
590 /*@=nullstate@*/
591  he->append = 0;
592 
594  he->t = RPM_STRING_ARRAY_TYPE;
595  he->p.argv = &pEVR;
596  he->c = 1;
597  he->append = 1;
598 /*@-nullstate@*/
599  xx = headerPut(h, he, 0);
600 /*@=nullstate@*/
601  he->append = 0;
602 
603  he->tag = RPMTAG_PROVIDEFLAGS;
604  he->t = RPM_UINT32_TYPE;
605  he->p.ui32p = &pFlags;
606  he->c = 1;
607  he->append = 1;
608 /*@-nullstate@*/
609  xx = headerPut(h, he, 0);
610 /*@=nullstate@*/
611  he->append = 0;
612  }
613  N = _free(N);
614 }
615 
616 rpmRC writeRPM(Header *hdrp, unsigned char ** pkgidp, const char *fileName,
617  CSA_t csa, char *passPhrase, const char **cookie)
618 {
619  HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
620  FD_t fd = NULL;
621  FD_t ifd = NULL;
622  rpmuint32_t sigtag;
623  const char * sigtarget;
624  const char * rpmio_flags = NULL;
625  const char * payload_format = NULL;
626  const char * SHA1 = NULL;
627  const char * msg = NULL;
628  char *s;
629  char buf[BUFSIZ];
630  Header h;
631  Header sigh = NULL;
632  int addsig = 0;
633  int isSource;
634  rpmRC rc = RPMRC_OK;
635  size_t nbr;
636  size_t nbw;
637  int xx;
638 
639  /* Transfer header reference form *hdrp to h. */
640  h = headerLink(*hdrp);
641  (void)headerFree(*hdrp);
642  *hdrp = NULL;
643 
644  if (pkgidp)
645  *pkgidp = NULL;
646 
647  /* Save payload information */
648  isSource =
649  (headerIsEntry(h, RPMTAG_SOURCERPM) == 0 &&
650  headerIsEntry(h, RPMTAG_ARCH) != 0);
651  if (isSource) {
652  payload_format = rpmExpand("%{?_source_payload_format}", NULL);
653  rpmio_flags = rpmExpand("%{?_source_payload}", NULL);
654  } else {
655  payload_format = rpmExpand("%{?_binary_payload_format}", NULL);
656  rpmio_flags = rpmExpand("%{?_binary_payload}", NULL);
657  }
658 
659  if (!(payload_format && *payload_format)) {
660  payload_format = _free(payload_format);
661  payload_format = xstrdup("cpio");
662  }
663  if (!(rpmio_flags && *rpmio_flags)) {
664  rpmio_flags = _free(rpmio_flags);
665  rpmio_flags = xstrdup("w9.gzdio");
666  }
667  s = strchr(rpmio_flags, '.');
668  if (s) {
669 
670  if (payload_format) {
671  if (!strcmp(payload_format, "tar")
672  || !strcmp(payload_format, "ustar")) {
673  /* XXX addition to header is too late to be displayed/sorted. */
674  /* Add prereq on rpm version that understands tar payloads */
675  (void) rpmlibNeedsFeature(h, "PayloadIsUstar", "4.4.4-1");
676  }
677 #if defined(SUPPORT_AR_PAYLOADS)
678  if (!strcmp(payload_format, "ar")) {
679  /* XXX addition to header is too late to be displayed/sorted. */
680  /* Add prereq on rpm version that understands tar payloads */
681  (void) rpmlibNeedsFeature(h, "PayloadIsAr", "5.1-1");
682  }
683 #endif
684 
686  he->t = RPM_STRING_TYPE;
687  he->p.str = payload_format;
688  he->c = 1;
689  xx = headerPut(h, he, 0);
690  }
691 
692  /* XXX addition to header is too late to be displayed/sorted. */
693  if (s[1] == 'g' && s[2] == 'z') {
695  he->t = RPM_STRING_TYPE;
696  he->p.str = xstrdup("gzip");
697  he->c = 1;
698  xx = headerPut(h, he, 0);
699  he->p.ptr = _free(he->p.ptr);
700  } else if (s[1] == 'b' && s[2] == 'z') {
702  he->t = RPM_STRING_TYPE;
703  he->p.str = xstrdup("bzip2");
704  he->c = 1;
705  xx = headerPut(h, he, 0);
706  he->p.ptr = _free(he->p.ptr);
707  } else if (s[1] == 'l' && s[2] == 'z') {
709  he->t = RPM_STRING_TYPE;
710  he->p.str = xstrdup("lzma");
711  he->c = 1;
712  xx = headerPut(h, he, 0);
713  he->p.ptr = _free(he->p.ptr);
714  (void) rpmlibNeedsFeature(h, "PayloadIsLzma", "4.4.6-1");
715  } else if (s[1] == 'x' && s[2] == 'z') {
717  he->t = RPM_STRING_TYPE;
718  he->p.str = xstrdup("xz");
719  he->c = 1;
720  xx = headerPut(h, he, 0);
721  he->p.ptr = _free(he->p.ptr);
722  (void) rpmlibNeedsFeature(h, "PayloadIsXz", "5.2-1");
723  }
724  strcpy(buf, rpmio_flags);
725  buf[s - rpmio_flags] = '\0';
726 
727  he->tag = RPMTAG_PAYLOADFLAGS;
728  he->t = RPM_STRING_TYPE;
729  he->p.str = buf+1;
730  he->c = 1;
731  xx = headerPut(h, he, 0);
732  }
733 
734  /* Create and add the cookie */
735  if (cookie) {
736  sprintf(buf, "%s %u", buildHost(), (unsigned) (*getBuildTime()));
737  *cookie = xstrdup(buf); /* XXX memory leak */
738  he->tag = RPMTAG_COOKIE;
739  he->t = RPM_STRING_TYPE;
740  he->p.str = *cookie;
741  he->c = 1;
742  xx = headerPut(h, he, 0);
743  }
744 
745  /* Reallocate the header into one contiguous region. */
747  if (h == NULL) { /* XXX can't happen */
748  rpmlog(RPMLOG_ERR, _("Unable to create immutable header region.\n"));
749  rc = RPMRC_FAIL;
750  goto exit;
751  }
752  /* Re-reference reallocated header. */
753  *hdrp = headerLink(h);
754 
755  /*
756  * Write the header+archive into a temp file so that the size of
757  * archive (after compression) can be added to the header.
758  */
759  sigtarget = NULL;
760  if (rpmTempFile(NULL, &sigtarget, &fd)) {
761  rpmlog(RPMLOG_ERR, _("Unable to open temp file.\n"));
762  rc = RPMRC_FAIL;
763  goto exit;
764  }
765 
766  /* Write the header to a temp file, computing header SHA1 on the fly. */
768  { const char item[] = "Header";
769  msg = NULL;
770  rc = rpmpkgWrite(item, fd, h, &msg);
771  if (rc != RPMRC_OK) {
772  rpmlog(RPMLOG_ERR, "%s: %s: %s\n", sigtarget, item,
773  (msg && *msg ? msg : "write failed\n"));
774  msg = _free(msg);
775  rc = RPMRC_FAIL;
776  goto exit;
777  }
778  msg = _free(msg);
779  (void) Fflush(fd);
780  }
781  fdFiniDigest(fd, PGPHASHALGO_SHA1, &SHA1, NULL, 1);
782 
783  /* Append the payload to the temp file. */
784  if (csa->cpioList != NULL)
785  rc = cpio_doio(fd, h, csa, payload_format, rpmio_flags);
786  else if (Fileno(csa->cpioFdIn) >= 0)
787  rc = cpio_copy(fd, csa);
788  else
789 assert(0);
790 
791  rpmio_flags = _free(rpmio_flags);
792  payload_format = _free(payload_format);
793  if (rc != RPMRC_OK)
794  goto exit;
795 
796  (void) Fclose(fd);
797  fd = NULL;
798  (void) Unlink(fileName);
799 
800  /* Generate the signature */
801  (void) fflush(stdout);
802  sigh = headerNew();
803  (void) rpmAddSignature(sigh, sigtarget, RPMSIGTAG_SIZE, passPhrase);
804  (void) rpmAddSignature(sigh, sigtarget, RPMSIGTAG_MD5, passPhrase);
805 
806  sigtag = RPMSIGTAG_GPG;
807  addsig = (passPhrase && passPhrase[0]);
808 
809  if (addsig) {
810  rpmlog(RPMLOG_NOTICE, _("Generating signature: %d\n"), sigtag);
811  (void) rpmAddSignature(sigh, sigtarget, sigtag, passPhrase);
812  }
813 
814  if (SHA1) {
815  he->tag = (rpmTag) RPMSIGTAG_SHA1;
816  he->t = RPM_STRING_TYPE;
817  he->p.str = SHA1;
818  he->c = 1;
819  xx = headerPut(sigh, he, 0);
820  SHA1 = _free(SHA1);
821  }
822 
823  { rpmuint32_t payloadSize = csa->cpioArchiveSize;
825  he->t = RPM_UINT32_TYPE;
826  he->p.ui32p = &payloadSize;
827  he->c = 1;
828  xx = headerPut(sigh, he, 0);
829  }
830 
831  /* Reallocate the signature into one contiguous region. */
833  if (sigh == NULL) { /* XXX can't happen */
834  rpmlog(RPMLOG_ERR, _("Unable to reload signature header.\n"));
835  rc = RPMRC_FAIL;
836  goto exit;
837  }
838 
839  /* Pad the signature header to put the metadata header at known offset. */
840  { size_t slen = 0;
841  void * uh = headerUnload(sigh, &slen);
842  static const size_t align = 1024;
843  size_t nb = align - 96 - 16 - 16;
844  rpmuint8_t * b;
845 
846  uh = _free(uh);
847 assert(slen < nb);
848  nb -= slen;
849  b = memset(alloca(nb), 0, nb);
850  he->tag = (rpmTag) RPMSIGTAG_PADDING;
851  he->t = RPM_BIN_TYPE;
852  he->p.ui8p = b;
853  he->c = nb;
854  xx = headerPut(sigh, he, 0);
856 assert(sigh != NULL);
857  }
858 
859  /* Open the output file */
860  fd = Fopen(fileName, "w.fdio");
861  if (fd == NULL || Ferror(fd)) {
862  rpmlog(RPMLOG_ERR, _("Could not open %s: %s\n"),
863  fileName, Fstrerror(fd));
864  rc = RPMRC_FAIL;
865  goto exit;
866  }
867 
868  /* Write the lead section into the package. */
869  { const char item[] = "Lead";
870  size_t nl = rpmpkgSizeof(item, NULL);
871 
872  msg = NULL;
873  if (nl == 0)
874  rc = RPMRC_FAIL;
875  else {
876  void * l = memset(alloca(nl), 0, nl);
877  const char *N, *V, *R;
878  (void) headerNEVRA(h, &N, NULL, &V, &R, NULL);
879  sprintf(buf, "%s-%s-%s", N, V, R);
880  N = _free(N);
881  V = _free(V);
882  R = _free(R);
883  msg = buf;
884  rc = rpmpkgWrite(item, fd, l, &msg);
885  }
886 
887  if (rc != RPMRC_OK) {
888  rpmlog(RPMLOG_ERR, _("Unable to write package: %s\n"),
889  Fstrerror(fd));
890  rc = RPMRC_FAIL;
891  goto exit;
892  }
893  }
894 
895  /* Write the signature section into the package. */
896  { const char item[] = "Signature";
897 
898  msg = NULL;
899  rc = rpmpkgWrite(item, fd, sigh, &msg);
900  if (rc != RPMRC_OK) {
901  rpmlog(RPMLOG_ERR, "%s: %s: %s\n", fileName, item,
902  (msg && *msg ? msg : "write failed\n"));
903  msg = _free(msg);
904  rc = RPMRC_FAIL;
905  goto exit;
906  }
907  msg = _free(msg);
908  }
909 
910  /* Append the header and archive */
911  ifd = Fopen(sigtarget, "r.fdio");
912  if (ifd == NULL || Ferror(ifd)) {
913  rpmlog(RPMLOG_ERR, _("Unable to open sigtarget %s: %s\n"),
914  sigtarget, Fstrerror(ifd));
915  rc = RPMRC_FAIL;
916  goto exit;
917  }
918 
919  /* Add signatures to header, and write header into the package. */
920  { const char item[] = "Header";
921  Header nh = NULL;
922 
923  msg = NULL;
924  rc = rpmpkgRead(item, ifd, &nh, &msg);
925  if (rc != RPMRC_OK) {
926  rpmlog(RPMLOG_ERR, "%s: %s: %s\n", sigtarget, item,
927  (msg && *msg ? msg : "read failed\n"));
928  msg = _free(msg);
929  rc = RPMRC_FAIL;
930  goto exit;
931  }
932  msg = _free(msg);
933 
934 #ifdef NOTYET
935  (void) headerMergeLegacySigs(nh, sigh);
936 #endif
937 
938  msg = NULL;
939  rc = rpmpkgWrite(item, fd, nh, &msg);
940  (void)headerFree(nh);
941  nh = NULL;
942  if (rc != RPMRC_OK) {
943  rpmlog(RPMLOG_ERR, "%s: %s: %s\n", fileName, item,
944  (msg && *msg ? msg : "write failed\n"));
945  msg = _free(msg);
946  rc = RPMRC_FAIL;
947  goto exit;
948  }
949  msg = _free(msg);
950  }
951 
952  /* Write the payload into the package. */
953  while ((nbr = Fread(buf, sizeof(buf[0]), sizeof(buf), ifd)) > 0) {
954  if (Ferror(ifd)) {
955  rpmlog(RPMLOG_ERR, _("Unable to read payload from %s: %s\n"),
956  sigtarget, Fstrerror(ifd));
957  rc = RPMRC_FAIL;
958  goto exit;
959  }
960  nbw = (int)Fwrite(buf, sizeof(buf[0]), nbr, fd);
961  if (nbr != nbw || Ferror(fd)) {
962  rpmlog(RPMLOG_ERR, _("Unable to write payload to %s: %s\n"),
963  fileName, Fstrerror(fd));
964  rc = RPMRC_FAIL;
965  goto exit;
966  }
967  }
968  rc = RPMRC_OK;
969 
970 exit:
971  SHA1 = _free(SHA1);
972  (void)headerFree(h);
973  h = NULL;
974 
975  /* XXX Fish the pkgid out of the signature header. */
976  if (sigh != NULL && pkgidp != NULL) {
977  he->tag = (rpmTag) RPMSIGTAG_MD5;
978  xx = headerGet(sigh, he, 0);
979  if (he->t == RPM_BIN_TYPE && he->p.ptr != NULL && he->c == 16)
980  *pkgidp = he->p.ui8p; /* XXX memory leak */
981  }
982 
983  (void)headerFree(sigh);
984  sigh = NULL;
985  if (ifd) {
986  (void) Fclose(ifd);
987  ifd = NULL;
988  }
989  if (fd) {
990  (void) Fclose(fd);
991  fd = NULL;
992  }
993  if (sigtarget) {
994  (void) Unlink(sigtarget);
995  sigtarget = _free(sigtarget);
996  }
997 
998  if (rc == RPMRC_OK)
999  rpmlog(RPMLOG_NOTICE, _("Wrote: %s\n"), fileName);
1000  else
1001  (void) Unlink(fileName);
1002 
1003  return rc;
1004 }
1005 
1006 static int rpmlibMarkers(Header h)
1007  /*@modifies h @*/
1008 {
1009  HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
1010  rpmuint32_t val;
1011  int xx;
1012 
1013  he->tag = RPMTAG_RPMVERSION;
1014  he->t = RPM_STRING_TYPE;
1015  he->p.str = xstrdup(VERSION);
1016  he->c = 1;
1017  xx = headerPut(h, he, 0);
1018  he->p.ptr = _free(he->p.ptr);
1019 
1020  if (!(_rpmbuildFlags & 4)) {
1021  val = (rpmuint32_t)rpmlibTimestamp();
1023  he->t = RPM_UINT32_TYPE;
1024  he->p.ui32p = &val;
1025  he->c = 1;
1026  xx = headerPut(h, he, 0);
1027 
1028  val = (rpmuint32_t)rpmlibVendor();
1029  he->tag = RPMTAG_RPMLIBVENDOR;
1030  he->t = RPM_UINT32_TYPE;
1031  he->p.ui32p = &val;
1032  he->c = 1;
1033  xx = headerPut(h, he, 0);
1034 
1035  val = (rpmuint32_t)rpmlibVersion();
1036  he->tag = RPMTAG_RPMLIBVERSION;
1037  he->t = RPM_UINT32_TYPE;
1038  he->p.ui32p = &val;
1039  he->c = 1;
1040  xx = headerPut(h, he, 0);
1041  }
1042 
1043  he->tag = RPMTAG_BUILDHOST;
1044  he->t = RPM_STRING_TYPE;
1045  he->p.str = buildHost();
1046  he->c = 1;
1047  xx = headerPut(h, he, 0);
1048 
1049  he->tag = RPMTAG_BUILDTIME;
1050  he->t = RPM_UINT32_TYPE;
1051  he->p.ui32p = getBuildTime();
1052  he->c = 1;
1053  xx = headerPut(h, he, 0);
1054 
1055  return 0;
1056 }
1057 
1058 /*@unchecked@*/
1059 static rpmTag copyTags[] = {
1063  0
1064 };
1065 
1067 {
1068  HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
1069  struct cpioSourceArchive_s csabuf;
1070  CSA_t csa = &csabuf;
1071  const char *errorString;
1072  Package pkg;
1073  rpmRC rc;
1074  int xx;
1075 
1076  for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) {
1077  const char *fn;
1078 
1079  if (pkg->fileList == NULL)
1080  continue;
1081 
1082  if (spec->cookie) {
1083  he->tag = RPMTAG_COOKIE;
1084  he->t = RPM_STRING_TYPE;
1085  he->p.str = spec->cookie;
1086  he->c = 1;
1087  xx = headerPut(pkg->header, he, 0);
1088  }
1089 
1090  /* Copy changelog from src rpm */
1091  headerCopyTags(spec->packages->header, pkg->header, copyTags);
1092 
1093  /* Add rpmlib markers for tracking. */
1094  (void) rpmlibMarkers(pkg->header);
1095 
1096  he->tag = RPMTAG_OPTFLAGS;
1097  he->t = RPM_STRING_TYPE;
1098  he->p.str = rpmExpand("%{optflags}", NULL);
1099  he->c = 1;
1100  xx = headerPut(pkg->header, he, 0);
1101  he->p.ptr = _free(he->p.ptr);
1102 
1103 if (!(_rpmbuildFlags & 4)) {
1104  if (spec->sourcePkgId != NULL) {
1105  he->tag = RPMTAG_SOURCEPKGID;
1106  he->t = RPM_BIN_TYPE;
1107  he->p.ptr = spec->sourcePkgId;
1108  he->c = 16;
1109  xx = headerPut(pkg->header, he, 0);
1110  }
1111 }
1112 
1113  { const char *binFormat = rpmGetPath("%{_rpmfilename}", NULL);
1114  char *binRpm, *binDir;
1115  binRpm = headerSprintf(pkg->header, binFormat, NULL,
1116  rpmHeaderFormats, &errorString);
1117  binFormat = _free(binFormat);
1118  if (binRpm == NULL) {
1119  he->tag = RPMTAG_NVRA;
1120  xx = headerGet(pkg->header, he, 0);
1121  rpmlog(RPMLOG_ERR, _("Could not generate output "
1122  "filename for package %s: %s\n"), he->p.str, errorString);
1123  he->p.ptr = _free(he->p.ptr);
1124 /*@-usereleased@*/
1125  return RPMRC_FAIL;
1126 /*@=usereleased@*/
1127  }
1128  fn = rpmGetPath("%{_rpmdir}/", binRpm, NULL);
1129  if ((binDir = strchr(binRpm, '/')) != NULL) {
1130  struct stat st;
1131  const char *dn;
1132  *binDir = '\0';
1133  dn = rpmGetPath("%{_rpmdir}/", binRpm, NULL);
1134  if (Stat(dn, &st) < 0) {
1135  switch(errno) {
1136  case ENOENT:
1137  if (rpmioMkpath(dn, 0755, -1, -1) == 0)
1138  /*@switchbreak@*/ break;
1139  /*@fallthrough@*/
1140  default:
1141  rpmlog(RPMLOG_ERR,_("cannot create %s: %s\n"),
1142  dn, strerror(errno));
1143  /*@switchbreak@*/ break;
1144  }
1145  }
1146  dn = _free(dn);
1147  }
1148  binRpm = _free(binRpm);
1149  }
1150 
1151  memset(csa, 0, sizeof(*csa));
1152  csa->cpioArchiveSize = 0;
1153  /*@-type@*/ /* LCL: function typedefs */
1154 /*@-onlytrans@*/
1155  csa->cpioFdIn = fdNew("init (packageBinaries)");
1156 /*@=onlytrans@*/
1157 /*@-assignexpose -newreftrans@*/
1158  csa->cpioList = rpmfiLink(pkg->cpioList, "packageBinaries");
1159 /*@=assignexpose =newreftrans@*/
1160 assert(csa->cpioList != NULL);
1161 
1162  rc = writeRPM(&pkg->header, NULL, fn,
1163  csa, spec->passPhrase, NULL);
1164 
1165 /*@-onlytrans@*/
1166  csa->cpioList->te = _free(csa->cpioList->te); /* XXX memory leak */
1167 /*@=onlytrans@*/
1168  csa->cpioList = rpmfiFree(csa->cpioList);
1169 /*@-nullpass -onlytrans -refcounttrans @*/
1170  csa->cpioFdIn = fdFree(csa->cpioFdIn, "init (packageBinaries)");
1171 /*@=nullpass =onlytrans =refcounttrans @*/
1172  /*@=type@*/
1173  fn = _free(fn);
1174  if (rc)
1175  return rc;
1176  }
1177 
1178  return RPMRC_OK;
1179 }
1180 
1182 {
1183  HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
1184  struct cpioSourceArchive_s csabuf;
1185  CSA_t csa = &csabuf;
1186  rpmRC rc;
1187  int xx;
1188 #if defined(RPM_VENDOR_OPENPKG) || defined(RPM_VENDOR_FEDORA) || defined(RPM_VENDOR_MANDRIVA) || defined(RPM_VENDOR_ARK) /* backward-compat-rpmtag-sourcepackage */
1189  rpmuint32_t val;
1190 #endif
1191 
1192  /* Add rpmlib markers for tracking. */
1193  (void) rpmlibMarkers(spec->sourceHeader);
1194 
1195 #if defined(RPM_VENDOR_OPENPKG) || defined(RPM_VENDOR_FEDORA) || defined(RPM_VENDOR_MANDRIVA) || defined(RPM_VENDOR_ARK) /* backward-compat-rpmtag-sourcepackage */
1196  /* Mark package as a SRPM for backward compatibility with RPM < 4.4.6 */
1197  he->tag = RPMTAG_SOURCEPACKAGE;
1198  he->t = RPM_UINT32_TYPE;
1199  val = 1;
1200  he->p.ui32p = &val;
1201  he->c = 1;
1202  xx = headerPut(spec->sourceHeader, he, 0);
1203 #endif
1204 
1205  /* Add macros used during build to SRPM's. */
1206  { const char ** av = NULL;
1207  (void)rpmGetMacroEntries(NULL, NULL, 1, &av);
1208  if (av != NULL && av[0] != NULL) {
1209  he->tag = RPMTAG_BUILDMACROS;
1210  he->t = RPM_STRING_ARRAY_TYPE;
1211  he->p.argv = av;
1212  he->c = argvCount(av);
1213  xx = headerPut(spec->sourceHeader, he, 0);
1214  }
1215 /*@-nullstate@*/
1216  av = argvFree(av);
1217 /*@=nullstate@*/
1218  }
1219 
1220  spec->cookie = _free(spec->cookie);
1221 
1222  /* XXX this should be %_srpmdir */
1223  { const char *srcrpmdir = rpmGetPath("%{_srcrpmdir}/", NULL);
1224  const char *fn = rpmGetPath("%{_srcrpmdir}/", spec->sourceRpmName,NULL);
1225 
1226  rc = rpmioMkpath(srcrpmdir, 0755, -1, -1);
1227 
1228  memset(csa, 0, sizeof(*csa));
1229  csa->cpioArchiveSize = 0;
1230  /*@-type@*/ /* LCL: function typedefs */
1231 /*@-onlytrans@*/
1232  csa->cpioFdIn = fdNew("init (packageSources)");
1233 /*@=onlytrans@*/
1234 /*@-assignexpose -newreftrans@*/
1235  csa->cpioList = rpmfiLink(spec->sourceCpioList, "packageSources");
1236 /*@=assignexpose =newreftrans@*/
1237 assert(csa->cpioList != NULL);
1238 
1239  spec->sourcePkgId = NULL;
1240  rc = writeRPM(&spec->sourceHeader, &spec->sourcePkgId, fn,
1241  csa, spec->passPhrase, &(spec->cookie));
1242 
1243 /*@-onlytrans@*/
1244  csa->cpioList->te = _free(csa->cpioList->te); /* XXX memory leak */
1245 /*@=onlytrans@*/
1246  csa->cpioList = rpmfiFree(csa->cpioList);
1247 /*@-nullpass -onlytrans -refcounttrans @*/
1248  csa->cpioFdIn = fdFree(csa->cpioFdIn, "init (packageSources)");
1249 /*@=nullpass =onlytrans =refcounttrans @*/
1250  /*@=type@*/
1251  srcrpmdir = _free(srcrpmdir);
1252  fn = _free(fn);
1253  }
1254 
1255  return (rc ? RPMRC_FAIL : RPMRC_OK);
1256 }