rpm  4.5
pack.c
Go to the documentation of this file.
1 
6 #include "system.h"
7 
8 #include <rpmio_internal.h>
9 #define _RPMEVR_INTERNAL /* XXX RPMSENSE_ANY */
10 #include <rpmbuild.h>
11 
12 #include "rpmps.h"
13 
14 #include "cpio.h"
15 #include "fsm.h"
16 #include "psm.h"
17 
18 #define _RPMFI_INTERNAL /* XXX fi->fsm */
19 #include "rpmfi.h"
20 #include "rpmts.h"
21 
22 #include "buildio.h"
23 
24 #include "signature.h"
25 #include "rpmlead.h"
26 #include "debug.h"
27 
28 /*@access rpmts @*/
29 /*@access rpmfi @*/ /* compared with NULL */
30 /*@access Header @*/ /* compared with NULL */
31 /*@access FD_t @*/ /* compared with NULL */
32 /*@access StringBuf @*/ /* compared with NULL */
33 /*@access CSA_t @*/
34 
37 static inline int genSourceRpmName(Spec spec)
38  /*@modifies spec->sourceRpmName @*/
39 {
40  if (spec->sourceRpmName == NULL) {
41  const char *name, *version, *release;
42  char fileName[BUFSIZ];
43 
44  (void) headerNVR(spec->packages->header, &name, &version, &release);
45  sprintf(fileName, "%s-%s-%s.%ssrc.rpm", name, version, release,
46  spec->noSource ? "no" : "");
47  spec->sourceRpmName = xstrdup(fileName);
48  }
49 
50  return 0;
51 }
52 
56 static int cpio_doio(FD_t fdo, /*@unused@*/ Header h, CSA_t csa,
57  const char * payload_format, const char * fmodeMacro)
58  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
59  /*@modifies fdo, csa, rpmGlobalMacroContext,
60  fileSystem, internalState @*/
61 {
62  rpmts ts = rpmtsCreate();
63  rpmfi fi = csa->cpioList;
64  const char *failedFile = NULL;
65  FD_t cfd;
66  int rc, ec;
67 
68 /*@-boundsread@*/
69  { const char *fmode = rpmExpand(fmodeMacro, NULL);
70  if (!(fmode && fmode[0] == 'w'))
71  fmode = xstrdup("w9.gzdio");
72  /*@-nullpass@*/
73  (void) Fflush(fdo);
74  cfd = Fdopen(fdDup(Fileno(fdo)), fmode);
75  /*@=nullpass@*/
76  fmode = _free(fmode);
77  }
78 /*@=boundsread@*/
79  if (cfd == NULL)
80  return 1;
81 
82  rc = fsmSetup(fi->fsm, FSM_PKGBUILD, payload_format, ts, fi, cfd,
83  &csa->cpioArchiveSize, &failedFile);
84  (void) Fclose(cfd);
85  ec = fsmTeardown(fi->fsm);
86  if (!rc) rc = ec;
87 
88  if (rc) {
89  if (failedFile)
90  rpmError(RPMERR_CPIO, _("create archive failed on file %s: %s\n"),
91  failedFile, cpioStrerror(rc));
92  else
93  rpmError(RPMERR_CPIO, _("create archive failed: %s\n"),
94  cpioStrerror(rc));
95  rc = 1;
96  }
97 
98  failedFile = _free(failedFile);
99  ts = rpmtsFree(ts);
100 
101  return rc;
102 }
103 
106 static int cpio_copy(FD_t fdo, CSA_t csa)
107  /*@globals fileSystem, internalState @*/
108  /*@modifies fdo, csa, fileSystem, internalState @*/
109 {
110  char buf[BUFSIZ];
111  size_t nb;
112 
113  while((nb = Fread(buf, sizeof(buf[0]), sizeof(buf), csa->cpioFdIn)) > 0) {
114  if (Fwrite(buf, sizeof(buf[0]), nb, fdo) != nb) {
115  rpmError(RPMERR_CPIO, _("cpio_copy write failed: %s\n"),
116  Fstrerror(fdo));
117  return 1;
118  }
119  csa->cpioArchiveSize += nb;
120  }
121  if (Ferror(csa->cpioFdIn)) {
122  rpmError(RPMERR_CPIO, _("cpio_copy read failed: %s\n"),
123  Fstrerror(csa->cpioFdIn));
124  return 1;
125  }
126  return 0;
127 }
128 
131 static /*@only@*/ /*@null@*/ StringBuf addFileToTagAux(Spec spec,
132  const char * file, /*@only@*/ StringBuf sb)
133  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
134  /*@modifies rpmGlobalMacroContext, fileSystem, internalState @*/
135 {
136  char buf[BUFSIZ];
137  const char * fn = buf;
138  FILE * f;
139  FD_t fd;
140 
141  fn = rpmGetPath("%{_builddir}/%{?buildsubdir:%{buildsubdir}/}", file, NULL);
142 
143  fd = Fopen(fn, "r");
144  if (fn != buf) fn = _free(fn);
145  if (fd == NULL || Ferror(fd)) {
146  sb = freeStringBuf(sb);
147  return NULL;
148  }
149  /*@-type@*/ /* FIX: cast? */
150  if ((f = fdGetFp(fd)) != NULL)
151  /*@=type@*/
152  while (fgets(buf, sizeof(buf), f)) {
153  /* XXX display fn in error msg */
154  if (expandMacros(spec, spec->macros, buf, sizeof(buf))) {
155  rpmError(RPMERR_BADSPEC, _("line: %s\n"), buf);
156  sb = freeStringBuf(sb);
157  break;
158  }
159  appendStringBuf(sb, buf);
160  }
161  (void) Fclose(fd);
162 
163  return sb;
164 }
165 
168 static int addFileToTag(Spec spec, const char * file, Header h, int tag)
169  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
170  /*@modifies h, rpmGlobalMacroContext, fileSystem, internalState @*/
171 {
173  StringBuf sb = newStringBuf();
174  char *s;
175 
176  if (hge(h, tag, NULL, &s, NULL)) {
177  appendLineStringBuf(sb, s);
178  (void) headerRemoveEntry(h, tag);
179  }
180 
181  if ((sb = addFileToTagAux(spec, file, sb)) == NULL)
182  return 1;
183 
184  (void) headerAddEntry(h, tag, RPM_STRING_TYPE, getStringBuf(sb), 1);
185 
186  sb = freeStringBuf(sb);
187  return 0;
188 }
189 
192 static int addFileToArrayTag(Spec spec, const char *file, Header h, int tag)
193  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
194  /*@modifies h, rpmGlobalMacroContext, fileSystem, internalState @*/
195 {
196  StringBuf sb = newStringBuf();
197  char *s;
198 
199  if ((sb = addFileToTagAux(spec, file, sb)) == NULL)
200  return 1;
201 
202  s = getStringBuf(sb);
203  (void) headerAddOrAppendEntry(h, tag, RPM_STRING_ARRAY_TYPE, &s, 1);
204 
205  sb = freeStringBuf(sb);
206  return 0;
207 }
208 
210  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
211  /*@modifies pkg->header, rpmGlobalMacroContext,
212  fileSystem, internalState @*/
213 {
214  struct TriggerFileEntry *p;
215 
216  if (pkg->preInFile) {
217  if (addFileToTag(spec, pkg->preInFile, pkg->header, RPMTAG_PREIN)) {
219  _("Could not open PreIn file: %s\n"), pkg->preInFile);
220  return RPMERR_BADFILENAME;
221  }
222  }
223  if (pkg->preUnFile) {
224  if (addFileToTag(spec, pkg->preUnFile, pkg->header, RPMTAG_PREUN)) {
226  _("Could not open PreUn file: %s\n"), pkg->preUnFile);
227  return RPMERR_BADFILENAME;
228  }
229  }
230  if (pkg->preTransFile) {
231  if (addFileToTag(spec, pkg->preTransFile, pkg->header, RPMTAG_PRETRANS)) {
233  _("Could not open PreIn file: %s\n"), pkg->preTransFile);
234  return RPMERR_BADFILENAME;
235  }
236  }
237  if (pkg->postInFile) {
238  if (addFileToTag(spec, pkg->postInFile, pkg->header, RPMTAG_POSTIN)) {
240  _("Could not open PostIn file: %s\n"), pkg->postInFile);
241  return RPMERR_BADFILENAME;
242  }
243  }
244  if (pkg->postUnFile) {
245  if (addFileToTag(spec, pkg->postUnFile, pkg->header, RPMTAG_POSTUN)) {
247  _("Could not open PostUn file: %s\n"), pkg->postUnFile);
248  return RPMERR_BADFILENAME;
249  }
250  }
251  if (pkg->postTransFile) {
252  if (addFileToTag(spec, pkg->postTransFile, pkg->header, RPMTAG_POSTTRANS)) {
254  _("Could not open PostUn file: %s\n"), pkg->postTransFile);
255  return RPMERR_BADFILENAME;
256  }
257  }
258  if (pkg->verifyFile) {
259  if (addFileToTag(spec, pkg->verifyFile, pkg->header,
262  _("Could not open VerifyScript file: %s\n"), pkg->verifyFile);
263  return RPMERR_BADFILENAME;
264  }
265  }
266 
267  for (p = pkg->triggerFiles; p != NULL; p = p->next) {
269  RPM_STRING_ARRAY_TYPE, &(p->prog), 1);
270  if (p->script) {
272  RPM_STRING_ARRAY_TYPE, &(p->script), 1);
273  } else if (p->fileName) {
274  if (addFileToArrayTag(spec, p->fileName, pkg->header,
277  _("Could not open Trigger script file: %s\n"),
278  p->fileName);
279  return RPMERR_BADFILENAME;
280  }
281  } else {
282  /* This is dumb. When the header supports NULL string */
283  /* this will go away. */
284  char *bull = "";
286  RPM_STRING_ARRAY_TYPE, &bull, 1);
287  }
288  }
289 
290  return 0;
291 }
292 
293 /*@-boundswrite@*/
294 int readRPM(const char *fileName, Spec *specp, struct rpmlead *lead,
295  Header *sigs, CSA_t csa)
296 {
297  FD_t fdi;
298  Spec spec;
299  rpmRC rc;
300 
301  fdi = (fileName != NULL)
302  ? Fopen(fileName, "r")
303  : fdDup(STDIN_FILENO);
304 
305  if (fdi == NULL || Ferror(fdi)) {
306  rpmError(RPMERR_BADMAGIC, _("readRPM: open %s: %s\n"),
307  (fileName ? fileName : "<stdin>"),
308  Fstrerror(fdi));
309  if (fdi) (void) Fclose(fdi);
310  return RPMERR_BADMAGIC;
311  }
312 
313  /* Get copy of lead */
314  /*@-sizeoftype@*/
315  if ((rc = Fread(lead, sizeof(char), sizeof(*lead), fdi)) != sizeof(*lead)) {
316  rpmError(RPMERR_BADMAGIC, _("readRPM: read %s: %s\n"),
317  (fileName ? fileName : "<stdin>"),
318  Fstrerror(fdi));
319  return RPMERR_BADMAGIC;
320  }
321  /*@=sizeoftype@*/
322 
323  /* XXX FIXME: EPIPE on <stdin> */
324  if (Fseek(fdi, 0, SEEK_SET) == -1) {
325  rpmError(RPMERR_FSEEK, _("%s: Fseek failed: %s\n"),
326  (fileName ? fileName : "<stdin>"), Fstrerror(fdi));
327  return RPMERR_FSEEK;
328  }
329 
330  /* Reallocate build data structures */
331  spec = newSpec();
332  spec->packages = newPackage(spec);
333 
334  /* XXX the header just allocated will be allocated again */
335  spec->packages->header = headerFree(spec->packages->header);
336 
337  /* Read the rpm lead, signatures, and header */
338  { rpmts ts = rpmtsCreate();
339 
340  /* XXX W2DO? pass fileName? */
341  /*@-mustmod@*/ /* LCL: segfault */
342  rc = rpmReadPackageFile(ts, fdi, "readRPM",
343  &spec->packages->header);
344  /*@=mustmod@*/
345 
346  ts = rpmtsFree(ts);
347 
348  if (sigs) *sigs = NULL; /* XXX HACK */
349  }
350 
351  switch (rc) {
352  case RPMRC_OK:
353  case RPMRC_NOKEY:
354  case RPMRC_NOTTRUSTED:
355  break;
356  case RPMRC_NOTFOUND:
357  rpmError(RPMERR_BADMAGIC, _("readRPM: %s is not an RPM package\n"),
358  (fileName ? fileName : "<stdin>"));
359  return RPMERR_BADMAGIC;
360  case RPMRC_FAIL:
361  default:
362  rpmError(RPMERR_BADMAGIC, _("readRPM: reading header from %s\n"),
363  (fileName ? fileName : "<stdin>"));
364  return RPMERR_BADMAGIC;
365  /*@notreached@*/ break;
366  }
367 
368  /*@-branchstate@*/
369  if (specp)
370  *specp = spec;
371  else
372  spec = freeSpec(spec);
373  /*@=branchstate@*/
374 
375  if (csa != NULL)
376  csa->cpioFdIn = fdi;
377  else
378  (void) Fclose(fdi);
379 
380  return 0;
381 }
382 /*@=boundswrite@*/
383 
384 #ifdef DYING
385 /*@unchecked@*/
386 static unsigned char header_magic[8] = {
387  0x8e, 0xad, 0xe8, 0x01, 0x00, 0x00, 0x00, 0x00
388 };
389 #endif
390 
391 #define RPMPKGVERSION_MIN 30004
392 #define RPMPKGVERSION_MAX 40003
393 /*@unchecked@*/
394 static int rpmpkg_version = -1;
395 
396 static int rpmLeadVersion(void)
397  /*@globals rpmpkg_version, rpmGlobalMacroContext, h_errno @*/
398  /*@modifies rpmpkg_version, rpmGlobalMacroContext @*/
399 {
400  int rpmlead_version;
401 
402  /* Intitialize packaging version from macro configuration. */
403  if (rpmpkg_version < 0) {
404  rpmpkg_version = rpmExpandNumeric("%{_package_version}");
409  }
410 
411  rpmlead_version = rpmpkg_version / 10000;
412  /* XXX silly sanity check. */
413  if (rpmlead_version < 3 || rpmlead_version > 4)
414  rpmlead_version = 3;
415  return rpmlead_version;
416 }
417 
419 {
421  HFD_t hfd = headerFreeData;
422  const char *name, *version, *release;
423  int_32 * epoch;
424  const char *pEVR;
425  char *p;
426  int_32 pFlags = RPMSENSE_EQUAL;
427  const char ** provides = NULL;
428  const char ** providesEVR = NULL;
429  rpmTagType pnt, pvt;
430  int_32 * provideFlags = NULL;
431  int providesCount;
432  int i, xx;
433  int bingo = 1;
434 
435  /* Generate provides for this package name-version-release. */
436  xx = headerNVR(h, &name, &version, &release);
437  if (!(name && version && release))
438  return;
439  pEVR = p = alloca(21 + strlen(version) + 1 + strlen(release) + 1);
440  *p = '\0';
441  if (hge(h, RPMTAG_EPOCH, NULL, &epoch, NULL)) {
442  sprintf(p, "%d:", *epoch);
443  while (*p != '\0')
444  p++;
445  }
446  (void) stpcpy( stpcpy( stpcpy(p, version) , "-") , release);
447 
448  /*
449  * Rpm prior to 3.0.3 does not have versioned provides.
450  * If no provides at all are available, we can just add.
451  */
452  if (!hge(h, RPMTAG_PROVIDENAME, &pnt, &provides, &providesCount))
453  goto exit;
454 
455  /*
456  * Otherwise, fill in entries on legacy packages.
457  */
458  if (!hge(h, RPMTAG_PROVIDEVERSION, &pvt, &providesEVR, NULL)) {
459  for (i = 0; i < providesCount; i++) {
460  char * vdummy = "";
461  int_32 fdummy = RPMSENSE_ANY;
463  &vdummy, 1);
465  &fdummy, 1);
466  }
467  goto exit;
468  }
469 
470  xx = hge(h, RPMTAG_PROVIDEFLAGS, NULL, &provideFlags, NULL);
471 
472  /*@-nullderef@*/ /* LCL: providesEVR is not NULL */
473  if (provides && providesEVR && provideFlags)
474  for (i = 0; i < providesCount; i++) {
475  if (!(provides[i] && providesEVR[i]))
476  continue;
477  if (!(provideFlags[i] == RPMSENSE_EQUAL &&
478  !strcmp(name, provides[i]) && !strcmp(pEVR, providesEVR[i])))
479  continue;
480  bingo = 0;
481  break;
482  }
483  /*@=nullderef@*/
484 
485 exit:
486  provides = hfd(provides, pnt);
487  providesEVR = hfd(providesEVR, pvt);
488 
489  if (bingo) {
491  &name, 1);
493  &pFlags, 1);
495  &pEVR, 1);
496  }
497 }
498 
499 /*@-boundswrite@*/
500 int writeRPM(Header *hdrp, unsigned char ** pkgidp, const char *fileName,
501  int type, CSA_t csa, char *passPhrase, const char **cookie)
502 {
503  FD_t fd = NULL;
504  FD_t ifd = NULL;
505  int_32 count, sigtag;
506  const char * sigtarget = NULL;
507  const char * rpmio_flags = NULL;
508  const char * payload_format = NULL;
509  const char * SHA1 = NULL;
510  char *s;
511  char buf[BUFSIZ];
512  Header h;
513  Header sig = NULL;
514  int rc = 0;
515 
516  /* Transfer header reference form *hdrp to h. */
517  h = headerLink(*hdrp);
518  *hdrp = headerFree(*hdrp);
519 
520  if (pkgidp)
521  *pkgidp = NULL;
522 
523 #ifdef DYING
524  if (Fileno(csa->cpioFdIn) < 0) {
525  csa->cpioArchiveSize = 0;
526  /* Add a bogus archive size to the Header */
528  &csa->cpioArchiveSize, 1);
529  }
530 #endif
531 
532  /* Save payload information */
533  /*@-branchstate@*/
534  switch(type) {
535  case RPMLEAD_SOURCE:
536  payload_format = rpmExpand("%{?_source_payload_format}", NULL);
537  rpmio_flags = rpmExpand("%{?_source_payload}", NULL);
538  break;
539  case RPMLEAD_BINARY:
540  payload_format = rpmExpand("%{?_binary_payload_format}", NULL);
541  rpmio_flags = rpmExpand("%{?_binary_payload}", NULL);
542  break;
543  }
544  /*@=branchstate@*/
545  if (!(payload_format && *payload_format)) {
546  payload_format = _free(payload_format);
547  payload_format = xstrdup("cpio");
548  }
549  if (!(rpmio_flags && *rpmio_flags)) {
550  rpmio_flags = _free(rpmio_flags);
551  rpmio_flags = xstrdup("w9.gzdio");
552  }
553  s = strchr(rpmio_flags, '.');
554  if (s) {
555 
556  if (payload_format) {
557  if (!strcmp(payload_format, "tar")
558  || !strcmp(payload_format, "ustar")) {
559  /* XXX addition to header is too late to be displayed/sorted. */
560  /* Add prereq on rpm version that understands tar payloads */
561  (void) rpmlibNeedsFeature(h, "PayloadIsUstar", "4.4.4-1");
562  }
563 
565  payload_format, 1);
566  }
567 
568  /* XXX addition to header is too late to be displayed/sorted. */
569  if (s[1] == 'g' && s[2] == 'z')
571  "gzip", 1);
572  else if (s[1] == 'b' && s[2] == 'z')
574  "bzip2", 1);
575  else if (s[1] == 'l' && s[2] == 'z') {
577  "lzma", 1);
578  (void) rpmlibNeedsFeature(h, "PayloadIsLzma", "4.4.6-1");
579  }
580  strcpy(buf, rpmio_flags);
581  buf[s - rpmio_flags] = '\0';
582  (void) headerAddEntry(h, RPMTAG_PAYLOADFLAGS, RPM_STRING_TYPE, buf+1, 1);
583  }
584 
585  /* Create and add the cookie */
586  if (cookie) {
587  sprintf(buf, "%s %d", buildHost(), (int) (*getBuildTime()));
588  *cookie = xstrdup(buf);
589  (void) headerAddEntry(h, RPMTAG_COOKIE, RPM_STRING_TYPE, *cookie, 1);
590  }
591 
592  /* Reallocate the header into one contiguous region. */
594  if (h == NULL) { /* XXX can't happen */
595  rc = RPMERR_RELOAD;
596  rpmError(RPMERR_RELOAD, _("Unable to create immutable header region.\n"));
597  goto exit;
598  }
599  /* Re-reference reallocated header. */
600  *hdrp = headerLink(h);
601 
602  /*
603  * Write the header+archive into a temp file so that the size of
604  * archive (after compression) can be added to the header.
605  */
606  sigtarget = NULL;
607  if (makeTempFile(NULL, &sigtarget, &fd)) {
608  rc = RPMERR_CREATE;
609  rpmError(RPMERR_CREATE, _("Unable to open temp file.\n"));
610  goto exit;
611  }
612 
614  if (headerWrite(fd, h, HEADER_MAGIC_YES)) {
615  rc = RPMERR_NOSPACE;
616  rpmError(RPMERR_NOSPACE, _("Unable to write temp header\n"));
617  } else { /* Write the archive and get the size */
618  (void) Fflush(fd);
619  fdFiniDigest(fd, PGPHASHALGO_SHA1, &SHA1, NULL, 1);
620  if (csa->cpioList != NULL) {
621  rc = cpio_doio(fd, h, csa, payload_format, rpmio_flags);
622  } else if (Fileno(csa->cpioFdIn) >= 0) {
623  rc = cpio_copy(fd, csa);
624  } else {
625  rc = RPMERR_BADARG;
626  rpmError(RPMERR_BADARG, _("Bad CSA data\n"));
627  }
628  }
629  rpmio_flags = _free(rpmio_flags);
630  payload_format = _free(payload_format);
631 
632  if (rc)
633  goto exit;
634 
635 #ifdef DYING
636  /*
637  * Set the actual archive size, and rewrite the header.
638  * This used to be done using headerModifyEntry(), but now that headers
639  * have regions, the value is scribbled directly into the header data
640  * area. Some new scheme for adding the final archive size will have
641  * to be devised if headerGetEntryMinMemory() ever changes to return
642  * a pointer to memory not in the region, probably by appending
643  * the archive size to the header region rather than including the
644  * archive size within the header region.
645  */
646  if (Fileno(csa->cpioFdIn) < 0) {
648  int_32 * archiveSize;
649  if (hge(h, RPMTAG_ARCHIVESIZE, NULL, (void *)&archiveSize, NULL))
650  *archiveSize = csa->cpioArchiveSize;
651  }
652 
653  (void) Fflush(fd);
654  if (Fseek(fd, 0, SEEK_SET) == -1) {
655  rc = RPMERR_FSEEK;
656  rpmError(RPMERR_FSEEK, _("%s: Fseek failed: %s\n"),
657  sigtarget, Fstrerror(fd));
658  }
659 
661  if (headerWrite(fd, h, HEADER_MAGIC_YES)) {
662  rc = RPMERR_NOSPACE;
663  rpmError(RPMERR_NOSPACE, _("Unable to write final header\n"));
664  }
665  (void) Fflush(fd);
666  fdFiniDigest(fd, PGPHASHALGO_SHA1, (void **)&SHA1, NULL, 1);
667 #endif
668 
669  (void) Fclose(fd);
670  fd = NULL;
671  (void) Unlink(fileName);
672 
673  if (rc)
674  goto exit;
675 
676  /* Generate the signature */
677  (void) fflush(stdout);
678  sig = rpmNewSignature();
679  (void) rpmAddSignature(sig, sigtarget, RPMSIGTAG_SIZE, passPhrase);
680  (void) rpmAddSignature(sig, sigtarget, RPMSIGTAG_MD5, passPhrase);
681 
682  if ((sigtag = rpmLookupSignatureType(RPMLOOKUPSIG_QUERY)) > 0) {
683  rpmMessage(RPMMESS_NORMAL, _("Generating signature: %d\n"), sigtag);
684  (void) rpmAddSignature(sig, sigtarget, sigtag, passPhrase);
685  }
686 
687  if (SHA1) {
688  (void) headerAddEntry(sig, RPMSIGTAG_SHA1, RPM_STRING_TYPE, SHA1, 1);
689  SHA1 = _free(SHA1);
690  }
691 
692  { int_32 payloadSize = csa->cpioArchiveSize;
694  &payloadSize, 1);
695  }
696 
697  /* Reallocate the signature into one contiguous region. */
699  if (sig == NULL) { /* XXX can't happen */
700  rc = RPMERR_RELOAD;
701  rpmError(RPMERR_RELOAD, _("Unable to reload signature header.\n"));
702  goto exit;
703  }
704 
705  /* Pad the signature header to put the metadata header at known offset. */
706  { size_t slen = headerSizeof(sig, HEADER_MAGIC_YES);
707  void * uh = headerUnload(sig);
708  static const size_t align = 1024;
709  size_t nb = align - 96 - 16 - 8;
710  unsigned char * b;
711 
712  uh = _free(uh);
713 assert(slen < nb);
714  nb -= slen;
715  b = memset(alloca(nb), 0, nb);
716  (void) headerAddEntry(sig, RPMSIGTAG_PADDING, RPM_BIN_TYPE, b, nb);
718 assert(sig != NULL);
719  }
720 
721  /* Open the output file */
722  fd = Fopen(fileName, "w");
723  if (fd == NULL || Ferror(fd)) {
724  rc = RPMERR_CREATE;
725  rpmError(RPMERR_CREATE, _("Could not open %s: %s\n"),
726  fileName, Fstrerror(fd));
727  goto exit;
728  }
729 
730  /* Write the lead section into the package. */
731  { int archnum = -1;
732  int osnum = -1;
733  struct rpmlead lead;
734 
735  if (Fileno(csa->cpioFdIn) < 0) {
736  /* XXX DIEDIEDIE: legacy values were not 0. */
737  archnum = 0;
738  osnum = 0;
739  } else if (csa->lead != NULL) {
740  archnum = csa->lead->archnum;
741  osnum = csa->lead->osnum;
742  }
743 
744  memset(&lead, 0, sizeof(lead));
745  lead.major = rpmLeadVersion();
746  lead.minor = 0;
747  lead.type = type;
748  lead.archnum = archnum;
749  lead.osnum = osnum;
751 
752  { const char *name, *version, *release;
753  (void) headerNVR(h, &name, &version, &release);
754  sprintf(buf, "%s-%s-%s", name, version, release);
755  strncpy(lead.name, buf, sizeof(lead.name));
756  }
757 
758  if (writeLead(fd, &lead) != RPMRC_OK) {
759  rc = RPMERR_NOSPACE;
760  rpmError(RPMERR_NOSPACE, _("Unable to write package: %s\n"),
761  Fstrerror(fd));
762  goto exit;
763  }
764  }
765 
766  /* Write the signature section into the package. */
767  rc = rpmWriteSignature(fd, sig);
768  if (rc)
769  goto exit;
770 
771  /* Append the header and archive */
772  ifd = Fopen(sigtarget, "r");
773  if (ifd == NULL || Ferror(ifd)) {
774  rc = RPMERR_READ;
775  rpmError(RPMERR_READ, _("Unable to open sigtarget %s: %s\n"),
776  sigtarget, Fstrerror(ifd));
777  goto exit;
778  }
779 
780  /* Add signatures to header, and write header into the package. */
781  /* XXX header+payload digests/signatures might be checked again here. */
782  { Header nh = headerRead(ifd, HEADER_MAGIC_YES);
783 
784  if (nh == NULL) {
785  rc = RPMERR_READ;
786  rpmError(RPMERR_READ, _("Unable to read header from %s: %s\n"),
787  sigtarget, Fstrerror(ifd));
788  goto exit;
789  }
790 
791 #ifdef NOTYET
792  (void) headerMergeLegacySigs(nh, sig);
793 #endif
794 
795  rc = headerWrite(fd, nh, HEADER_MAGIC_YES);
796  nh = headerFree(nh);
797 
798  if (rc) {
799  rc = RPMERR_NOSPACE;
800  rpmError(RPMERR_NOSPACE, _("Unable to write header to %s: %s\n"),
801  fileName, Fstrerror(fd));
802  goto exit;
803  }
804  }
805 
806  /* Write the payload into the package. */
807  while ((count = Fread(buf, sizeof(buf[0]), sizeof(buf), ifd)) > 0) {
808  if (count == -1) {
809  rc = RPMERR_READ;
810  rpmError(RPMERR_READ, _("Unable to read payload from %s: %s\n"),
811  sigtarget, Fstrerror(ifd));
812  goto exit;
813  }
814  if (Fwrite(buf, sizeof(buf[0]), count, fd) != count) {
815  rc = RPMERR_NOSPACE;
816  rpmError(RPMERR_NOSPACE, _("Unable to write payload to %s: %s\n"),
817  fileName, Fstrerror(fd));
818  goto exit;
819  }
820  }
821  rc = 0;
822 
823 exit:
824  SHA1 = _free(SHA1);
825  h = headerFree(h);
826 
827  /* XXX Fish the pkgid out of the signature header. */
828  if (sig != NULL && pkgidp != NULL) {
829  int_32 tagType;
830  unsigned char * MD5 = NULL;
831  int_32 c;
832  int xx;
833  xx = headerGetEntry(sig, RPMSIGTAG_MD5, &tagType, &MD5, &c);
834  if (tagType == RPM_BIN_TYPE && MD5 != NULL && c == 16)
835  *pkgidp = MD5;
836  }
837 
838  sig = rpmFreeSignature(sig);
839  if (ifd) {
840  (void) Fclose(ifd);
841  ifd = NULL;
842  }
843  if (fd) {
844  (void) Fclose(fd);
845  fd = NULL;
846  }
847  if (sigtarget) {
848  (void) Unlink(sigtarget);
849  sigtarget = _free(sigtarget);
850  }
851 
852  if (rc == 0)
853  rpmMessage(RPMMESS_NORMAL, _("Wrote: %s\n"), fileName);
854  else
855  (void) Unlink(fileName);
856 
857  return rc;
858 }
859 /*@=boundswrite@*/
860 
861 /*@unchecked@*/
862 static int_32 copyTags[] = {
866  0
867 };
868 
869 /*@-boundswrite@*/
871 {
872  struct cpioSourceArchive_s csabuf;
873  CSA_t csa = &csabuf;
874  int rc;
875  const char *errorString;
876  Package pkg;
877 
878  for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) {
879  const char *fn;
880 
881  if (pkg->fileList == NULL)
882  continue;
883 
884  if (spec->cookie) {
885  (void) headerAddEntry(pkg->header, RPMTAG_COOKIE,
886  RPM_STRING_TYPE, spec->cookie, 1);
887  }
888 
889  /* Copy changelog from src rpm */
891 
895  RPM_STRING_TYPE, buildHost(), 1);
898 
899  { const char * optflags = rpmExpand("%{optflags}", NULL);
901  optflags, 1);
902  optflags = _free(optflags);
903  }
904 
905  (void) genSourceRpmName(spec);
907  spec->sourceRpmName, 1);
908  if (spec->sourcePkgId != NULL) {
910  spec->sourcePkgId, 16);
911  }
912 
913  { const char *binFormat = rpmGetPath("%{_rpmfilename}", NULL);
914  char *binRpm, *binDir;
915  binRpm = headerSprintf(pkg->header, binFormat, rpmTagTable,
916  rpmHeaderFormats, &errorString);
917  binFormat = _free(binFormat);
918  if (binRpm == NULL) {
919  const char *name;
920  (void) headerNVR(pkg->header, &name, NULL, NULL);
921  rpmError(RPMERR_BADFILENAME, _("Could not generate output "
922  "filename for package %s: %s\n"), name, errorString);
923  return RPMERR_BADFILENAME;
924  }
925  fn = rpmGetPath("%{_rpmdir}/", binRpm, NULL);
926  if ((binDir = strchr(binRpm, '/')) != NULL) {
927  struct stat st;
928  const char *dn;
929  *binDir = '\0';
930  dn = rpmGetPath("%{_rpmdir}/", binRpm, NULL);
931  if (Stat(dn, &st) < 0) {
932  switch(errno) {
933  case ENOENT:
934  if (Mkdir(dn, 0755) == 0)
935  /*@switchbreak@*/ break;
936  /*@fallthrough@*/
937  default:
938  rpmError(RPMERR_BADFILENAME,_("cannot create %s: %s\n"),
939  dn, strerror(errno));
940  /*@switchbreak@*/ break;
941  }
942  }
943  dn = _free(dn);
944  }
945  binRpm = _free(binRpm);
946  }
947 
948  memset(csa, 0, sizeof(*csa));
949  csa->cpioArchiveSize = 0;
950  /*@-type@*/ /* LCL: function typedefs */
951  csa->cpioFdIn = fdNew("init (packageBinaries)");
952  /*@-assignexpose -newreftrans@*/
953  csa->cpioList = rpmfiLink(pkg->cpioList, "packageBinaries");
954  /*@=assignexpose =newreftrans@*/
955 
956  rc = writeRPM(&pkg->header, NULL, fn, RPMLEAD_BINARY,
957  csa, spec->passPhrase, NULL);
958 
959  csa->cpioList = rpmfiFree(csa->cpioList);
960  csa->cpioFdIn = fdFree(csa->cpioFdIn, "init (packageBinaries)");
961  /*@=type@*/
962  fn = _free(fn);
963  if (rc)
964  return rc;
965  }
966 
967  return 0;
968 }
969 /*@=boundswrite@*/
970 
971 /*@-boundswrite@*/
973 {
974  struct cpioSourceArchive_s csabuf;
975  CSA_t csa = &csabuf;
976 #if defined(RPM_VENDOR_MANDRIVA)
977  int_32 one = 1;
978 #endif
979  int rc;
980 
981  /* Add some cruft */
985  RPM_STRING_TYPE, buildHost(), 1);
988 #if defined(RPM_VENDOR_MANDRIVA)
990  RPM_INT32_TYPE, &one, 1);
991 #endif
992 
993  (void) genSourceRpmName(spec);
994 
995  spec->cookie = _free(spec->cookie);
996 
997  /* XXX this should be %_srpmdir */
998  { const char *fn = rpmGetPath("%{_srcrpmdir}/", spec->sourceRpmName,NULL);
999 
1000  memset(csa, 0, sizeof(*csa));
1001  csa->cpioArchiveSize = 0;
1002  /*@-type@*/ /* LCL: function typedefs */
1003  csa->cpioFdIn = fdNew("init (packageSources)");
1004  /*@-assignexpose -newreftrans@*/
1005  csa->cpioList = rpmfiLink(spec->sourceCpioList, "packageSources");
1006  /*@=assignexpose =newreftrans@*/
1007 
1008  spec->sourcePkgId = NULL;
1009  rc = writeRPM(&spec->sourceHeader, &spec->sourcePkgId, fn, RPMLEAD_SOURCE,
1010  csa, spec->passPhrase, &(spec->cookie));
1011 
1012  csa->cpioList = rpmfiFree(csa->cpioList);
1013  csa->cpioFdIn = fdFree(csa->cpioFdIn, "init (packageSources)");
1014  /*@=type@*/
1015  fn = _free(fn);
1016  }
1017  return rc;
1018 }
1019 /*@=boundswrite@*/