3 * Assemble components of an RPM package.
8 #include <rpm/rpmlib.h> /* RPMSIGTAG*, rpmReadPackageFile */
10 #include <rpm/rpmbuild.h>
11 #include <rpm/rpmfileutil.h>
12 #include <rpm/rpmlog.h>
14 #include "rpmio/rpmio_internal.h" /* fdInitDigest, fdFiniDigest */
17 #include "lib/rpmfi_internal.h" /* rpmfiFSM() */
18 #include "lib/rpmte_internal.h" /* rpmfs */
19 #include "lib/signature.h"
20 #include "lib/rpmlead.h"
21 #include "build/buildio.h"
26 * @todo Create transaction set *much* earlier.
28 static rpmRC cpio_doio(FD_t fdo, Header h, CSA_t csa,
29 const char * fmodeMacro)
31 rpmts ts = rpmtsCreate();
32 rpmfi fi = csa->cpioList;
35 char *failedFile = NULL;
40 { char *fmode = rpmExpand(fmodeMacro, NULL);
41 if (!(fmode && fmode[0] == 'w'))
42 fmode = xstrdup("w9.gzdio");
44 cfd = Fdopen(fdDup(Fileno(fdo)), fmode);
50 /* make up a transaction element for passing to fsm */
51 rpmtsAddInstallElement(ts, h, NULL, 0, NULL);
52 te = rpmtsElement(ts, 0);
53 fs = rpmteGetFileStates(te);
55 fi = rpmfiInit(fi, 0);
56 while ((i = rpmfiNext(fi)) >= 0) {
57 if (rpmfiFFlags(fi) & RPMFILE_GHOST)
58 rpmfsSetAction(fs, i, FA_SKIP);
60 rpmfsSetAction(fs, i, FA_COPYOUT);
63 xx = fsmSetup(rpmfiFSM(fi), FSM_PKGBUILD, ts, te, fi, cfd,
64 &csa->cpioArchiveSize, &failedFile);
68 xx = fsmTeardown(rpmfiFSM(fi));
69 if (rc == RPMRC_OK && xx) rc = RPMRC_FAIL;
73 rpmlog(RPMLOG_ERR, _("create archive failed on file %s: %s\n"),
74 failedFile, cpioStrerror(rc));
76 rpmlog(RPMLOG_ERR, _("create archive failed: %s\n"),
82 failedFile = _free(failedFile);
90 static rpmRC cpio_copy(FD_t fdo, CSA_t csa)
95 while((nb = Fread(buf, sizeof(buf[0]), sizeof(buf), csa->cpioFdIn)) > 0) {
96 if (Fwrite(buf, sizeof(buf[0]), nb, fdo) != nb) {
97 rpmlog(RPMLOG_ERR, _("cpio_copy write failed: %s\n"),
101 csa->cpioArchiveSize += nb;
103 if (Ferror(csa->cpioFdIn)) {
104 rpmlog(RPMLOG_ERR, _("cpio_copy read failed: %s\n"),
105 Fstrerror(csa->cpioFdIn));
113 static StringBuf addFileToTagAux(rpmSpec spec,
114 const char * file, StringBuf sb)
120 fn = rpmGetPath("%{_builddir}/%{?buildsubdir:%{buildsubdir}/}", file, NULL);
123 if (f == NULL || ferror(f)) {
124 sb = freeStringBuf(sb);
127 while (fgets(buf, sizeof(buf), f)) {
128 if (expandMacros(spec, spec->macros, buf, sizeof(buf))) {
129 rpmlog(RPMLOG_ERR, _("%s: line: %s\n"), fn, buf);
130 sb = freeStringBuf(sb);
133 appendStringBuf(sb, buf);
145 static int addFileToTag(rpmSpec spec, const char * file, Header h, rpmTag tag)
147 StringBuf sb = newStringBuf();
148 const char *s = headerGetString(h, tag);
151 appendLineStringBuf(sb, s);
152 (void) headerDel(h, tag);
155 if ((sb = addFileToTagAux(spec, file, sb)) == NULL)
158 headerPutString(h, tag, getStringBuf(sb));
160 sb = freeStringBuf(sb);
166 static int addFileToArrayTag(rpmSpec spec, const char *file, Header h, rpmTag tag)
168 StringBuf sb = newStringBuf();
171 if ((sb = addFileToTagAux(spec, file, sb)) == NULL)
174 s = getStringBuf(sb);
175 headerPutString(h, tag, s);
177 sb = freeStringBuf(sb);
183 static rpmRC processScriptFiles(rpmSpec spec, Package pkg)
185 struct TriggerFileEntry *p;
187 if (pkg->preInFile) {
188 if (addFileToTag(spec, pkg->preInFile, pkg->header, RPMTAG_PREIN)) {
190 _("Could not open PreIn file: %s\n"), pkg->preInFile);
194 if (pkg->preUnFile) {
195 if (addFileToTag(spec, pkg->preUnFile, pkg->header, RPMTAG_PREUN)) {
197 _("Could not open PreUn file: %s\n"), pkg->preUnFile);
201 if (pkg->preTransFile) {
202 if (addFileToTag(spec, pkg->preTransFile, pkg->header, RPMTAG_PRETRANS)) {
204 _("Could not open PreTrans file: %s\n"), pkg->preTransFile);
208 if (pkg->postInFile) {
209 if (addFileToTag(spec, pkg->postInFile, pkg->header, RPMTAG_POSTIN)) {
211 _("Could not open PostIn file: %s\n"), pkg->postInFile);
215 if (pkg->postUnFile) {
216 if (addFileToTag(spec, pkg->postUnFile, pkg->header, RPMTAG_POSTUN)) {
218 _("Could not open PostUn file: %s\n"), pkg->postUnFile);
222 if (pkg->postTransFile) {
223 if (addFileToTag(spec, pkg->postTransFile, pkg->header, RPMTAG_POSTTRANS)) {
225 _("Could not open PostTrans file: %s\n"), pkg->postTransFile);
229 if (pkg->verifyFile) {
230 if (addFileToTag(spec, pkg->verifyFile, pkg->header,
231 RPMTAG_VERIFYSCRIPT)) {
233 _("Could not open VerifyScript file: %s\n"), pkg->verifyFile);
238 for (p = pkg->triggerFiles; p != NULL; p = p->next) {
239 headerPutString(pkg->header, RPMTAG_TRIGGERSCRIPTPROG, p->prog);
242 headerPutString(pkg->header, RPMTAG_TRIGGERSCRIPTS, p->script);
243 } else if (p->fileName) {
244 if (addFileToArrayTag(spec, p->fileName, pkg->header,
245 RPMTAG_TRIGGERSCRIPTS)) {
247 _("Could not open Trigger script file: %s\n"),
252 /* This is dumb. When the header supports NULL string */
253 /* this will go away. */
254 headerPutString(pkg->header, RPMTAG_TRIGGERSCRIPTS, "");
261 rpmRC readRPM(const char *fileName, rpmSpec *specp,
262 Header *sigs, CSA_t csa)
268 fdi = (fileName != NULL)
269 ? Fopen(fileName, "r.ufdio")
270 : fdDup(STDIN_FILENO);
272 if (fdi == NULL || Ferror(fdi)) {
273 rpmlog(RPMLOG_ERR, _("readRPM: open %s: %s\n"),
274 (fileName ? fileName : "<stdin>"),
276 if (fdi) (void) Fclose(fdi);
280 /* XXX FIXME: EPIPE on <stdin> */
281 if (Fseek(fdi, 0, SEEK_SET) == -1) {
282 rpmlog(RPMLOG_ERR, _("%s: Fseek failed: %s\n"),
283 (fileName ? fileName : "<stdin>"), Fstrerror(fdi));
287 /* Reallocate build data structures */
289 spec->packages = newPackage(spec);
291 /* XXX the header just allocated will be allocated again */
292 spec->packages->header = headerFree(spec->packages->header);
294 /* Read the rpm lead, signatures, and header */
295 { rpmts ts = rpmtsCreate();
297 /* XXX W2DO? pass fileName? */
298 rc = rpmReadPackageFile(ts, fdi, "readRPM",
299 &spec->packages->header);
303 if (sigs) *sigs = NULL; /* XXX HACK */
309 case RPMRC_NOTTRUSTED:
312 rpmlog(RPMLOG_ERR, _("readRPM: %s is not an RPM package\n"),
313 (fileName ? fileName : "<stdin>"));
317 rpmlog(RPMLOG_ERR, _("readRPM: reading header from %s\n"),
318 (fileName ? fileName : "<stdin>"));
326 spec = freeSpec(spec);
336 rpmRC writeRPM(Header *hdrp, unsigned char ** pkgidp, const char *fileName,
337 CSA_t csa, char *passPhrase, char **cookie)
343 char * sigtarget = NULL;;
344 char * rpmio_flags = NULL;
356 /* Transfer header reference form *hdrp to h. */
357 h = headerLink(*hdrp);
358 *hdrp = headerFree(*hdrp);
363 /* Save payload information */
364 if (headerIsSource(h))
365 rpmio_flags = rpmExpand("%{?_source_payload}", NULL);
367 rpmio_flags = rpmExpand("%{?_binary_payload}", NULL);
369 if (!(rpmio_flags && *rpmio_flags)) {
370 rpmio_flags = _free(rpmio_flags);
371 rpmio_flags = xstrdup("w9.gzdio");
373 s = strchr(rpmio_flags, '.');
375 const char *compr = NULL;
376 headerPutString(h, RPMTAG_PAYLOADFORMAT, "cpio");
378 if (rstreq(s+1, "gzdio")) {
381 } else if (rstreq(s+1, "bzdio")) {
383 /* Add prereq on rpm version that understands bzip2 payloads */
384 (void) rpmlibNeedsFeature(h, "PayloadIsBzip2", "3.0.5-1");
387 } else if (rstreq(s+1, "xzdio")) {
389 (void) rpmlibNeedsFeature(h, "PayloadIsXz", "5.2-1");
390 } else if (rstreq(s+1, "lzdio")) {
392 (void) rpmlibNeedsFeature(h, "PayloadIsLzma", "4.4.6-1");
395 rpmlog(RPMLOG_ERR, _("Unknown payload compression: %s\n"),
401 headerPutString(h, RPMTAG_PAYLOADCOMPRESSOR, compr);
402 buf = xstrdup(rpmio_flags);
403 buf[s - rpmio_flags] = '\0';
404 headerPutString(h, RPMTAG_PAYLOADFLAGS, buf+1);
408 /* Create and add the cookie */
410 rasprintf(cookie, "%s %d", buildHost(), (int) (*getBuildTime()));
411 headerPutString(h, RPMTAG_COOKIE, *cookie);
414 /* Reallocate the header into one contiguous region. */
415 h = headerReload(h, RPMTAG_HEADERIMMUTABLE);
416 if (h == NULL) { /* XXX can't happen */
418 rpmlog(RPMLOG_ERR, _("Unable to create immutable header region.\n"));
421 /* Re-reference reallocated header. */
422 *hdrp = headerLink(h);
425 * Write the header+archive into a temp file so that the size of
426 * archive (after compression) can be added to the header.
428 fd = rpmMkTempFile(NULL, &sigtarget);
429 if (fd == NULL || Ferror(fd)) {
431 rpmlog(RPMLOG_ERR, _("Unable to open temp file.\n"));
435 fdInitDigest(fd, PGPHASHALGO_SHA1, 0);
436 if (headerWrite(fd, h, HEADER_MAGIC_YES)) {
438 rpmlog(RPMLOG_ERR, _("Unable to write temp header\n"));
439 } else { /* Write the archive and get the size */
441 fdFiniDigest(fd, PGPHASHALGO_SHA1, (void **)&SHA1, NULL, 1);
442 if (csa->cpioList != NULL) {
443 rc = cpio_doio(fd, h, csa, rpmio_flags);
444 } else if (Fileno(csa->cpioFdIn) >= 0) {
445 rc = cpio_copy(fd, csa);
448 rpmlog(RPMLOG_ERR, _("Bad CSA data\n"));
451 rpmio_flags = _free(rpmio_flags);
458 (void) unlink(fileName);
460 /* Generate the signature */
461 (void) fflush(stdout);
462 sig = rpmNewSignature();
465 * There should be rpmlib() dependency on this, but that doesn't
466 * really do much good as these are signature tags that get read
467 * way before dependency checking has a chance to figure out anything.
468 * On the positive side, not inserting the 32bit tag at all means
469 * older rpm will just bail out with error message on attempt to read
472 if (csa->cpioArchiveSize < UINT32_MAX) {
473 sizetag = RPMSIGTAG_SIZE;
474 payloadtag = RPMSIGTAG_PAYLOADSIZE;
476 sizetag = RPMSIGTAG_LONGSIZE;
477 payloadtag = RPMSIGTAG_LONGARCHIVESIZE;
479 (void) rpmAddSignature(sig, sigtarget, sizetag, passPhrase);
480 (void) rpmAddSignature(sig, sigtarget, RPMSIGTAG_MD5, passPhrase);
482 if ((sigtag = rpmLookupSignatureType(RPMLOOKUPSIG_QUERY)) > 0) {
483 rpmlog(RPMLOG_NOTICE, _("Generating signature: %d\n"), sigtag);
484 (void) rpmAddSignature(sig, sigtarget, sigtag, passPhrase);
488 /* XXX can't use rpmtdFromFoo() on RPMSIGTAG_* items */
490 td.tag = RPMSIGTAG_SHA1;
491 td.type = RPM_STRING_TYPE;
494 headerPut(sig, &td, HEADERPUT_DEFAULT);
499 /* XXX can't use headerPutType() on legacy RPMSIGTAG_* items */
503 if (payloadtag == RPMSIGTAG_PAYLOADSIZE) {
504 rpm_off_t asize = csa->cpioArchiveSize;
505 td.type = RPM_INT32_TYPE;
507 headerPut(sig, &td, HEADERPUT_DEFAULT);
509 rpm_loff_t asize = csa->cpioArchiveSize;
510 td.type = RPM_INT64_TYPE;
512 headerPut(sig, &td, HEADERPUT_DEFAULT);
516 /* Reallocate the signature into one contiguous region. */
517 sig = headerReload(sig, RPMTAG_HEADERSIGNATURES);
518 if (sig == NULL) { /* XXX can't happen */
520 rpmlog(RPMLOG_ERR, _("Unable to reload signature header.\n"));
524 /* Open the output file */
525 fd = Fopen(fileName, "w.ufdio");
526 if (fd == NULL || Ferror(fd)) {
528 rpmlog(RPMLOG_ERR, _("Could not open %s: %s\n"),
529 fileName, Fstrerror(fd));
533 /* Write the lead section into the package. */
535 rpmlead lead = rpmLeadFromHeader(h);
536 rc = rpmLeadWrite(fd, lead);
537 lead = rpmLeadFree(lead);
538 if (rc != RPMRC_OK) {
540 rpmlog(RPMLOG_ERR, _("Unable to write package: %s\n"),
546 /* Write the signature section into the package. */
547 if (rpmWriteSignature(fd, sig)) {
552 /* Append the header and archive */
553 ifd = Fopen(sigtarget, "r.ufdio");
554 if (ifd == NULL || Ferror(ifd)) {
556 rpmlog(RPMLOG_ERR, _("Unable to open sigtarget %s: %s\n"),
557 sigtarget, Fstrerror(ifd));
561 /* Add signatures to header, and write header into the package. */
562 /* XXX header+payload digests/signatures might be checked again here. */
563 { Header nh = headerRead(ifd, HEADER_MAGIC_YES);
567 rpmlog(RPMLOG_ERR, _("Unable to read header from %s: %s\n"),
568 sigtarget, Fstrerror(ifd));
573 (void) headerMergeLegacySigs(nh, sig);
576 xx = headerWrite(fd, nh, HEADER_MAGIC_YES);
581 rpmlog(RPMLOG_ERR, _("Unable to write header to %s: %s\n"),
582 fileName, Fstrerror(fd));
587 /* Write the payload into the package. */
588 buf = xmalloc(BUFSIZ);
589 while ((count = Fread(buf, 1, BUFSIZ, ifd)) > 0) {
593 rpmlog(RPMLOG_ERR, _("Unable to read payload from %s: %s\n"),
594 sigtarget, Fstrerror(ifd));
597 if (Fwrite(buf, sizeof(buf[0]), count, fd) != count) {
600 rpmlog(RPMLOG_ERR, _("Unable to write payload to %s: %s\n"),
601 fileName, Fstrerror(fd));
612 /* XXX Fish the pkgid out of the signature header. */
613 if (sig != NULL && pkgidp != NULL) {
614 struct rpmtd_s md5tag;
615 headerGet(sig, RPMSIGTAG_MD5, &md5tag, HEADERGET_DEFAULT);
616 if (rpmtdType(&md5tag) == RPM_BIN_TYPE &&
617 md5tag.count == 16 && md5tag.data != NULL) {
618 *pkgidp = md5tag.data;
622 sig = rpmFreeSignature(sig);
632 (void) unlink(sigtarget);
633 sigtarget = _free(sigtarget);
637 rpmlog(RPMLOG_NOTICE, _("Wrote: %s\n"), fileName);
639 (void) unlink(fileName);
644 static const rpmTag copyTags[] = {
645 RPMTAG_CHANGELOGTIME,
646 RPMTAG_CHANGELOGNAME,
647 RPMTAG_CHANGELOGTEXT,
652 * Add extra provides to package.
654 static void addPackageProvides(Header h)
656 const char *arch, *name;
658 rpmsenseFlags pflags = RPMSENSE_EQUAL;
660 /* <name> = <evr> provide */
661 name = headerGetString(h, RPMTAG_NAME);
662 arch = headerGetString(h, RPMTAG_ARCH);
663 evr = headerGetAsString(h, RPMTAG_EVR);
664 headerPutString(h, RPMTAG_PROVIDENAME, name);
665 headerPutString(h, RPMTAG_PROVIDEVERSION, evr);
666 headerPutUint32(h, RPMTAG_PROVIDEFLAGS, &pflags, 1);
669 * <name>(<isa>) = <evr> provide
670 * FIXME: noarch needs special casing for now as BuildArch: noarch doesn't
671 * cause reading in the noarch macros :-/
673 isaprov = rpmExpand(name, "%{?_isa}", NULL);
674 if (!rstreq(arch, "noarch") && !rstreq(name, isaprov)) {
675 headerPutString(h, RPMTAG_PROVIDENAME, isaprov);
676 headerPutString(h, RPMTAG_PROVIDEVERSION, evr);
677 headerPutUint32(h, RPMTAG_PROVIDEFLAGS, &pflags, 1);
683 rpmRC checkPackages(char *pkgcheck)
685 int fail = rpmExpandNumeric("%{?_nonzero_exit_pkgcheck_terminate_build}");
688 rpmlog(RPMLOG_NOTICE, _("Executing \"%s\":\n"), pkgcheck);
689 xx = system(pkgcheck);
690 if (WEXITSTATUS(xx) == -1 || WEXITSTATUS(xx) == 127) {
691 rpmlog(RPMLOG_ERR, _("Execution of \"%s\" failed.\n"), pkgcheck);
692 if (fail) return 127;
694 if (WEXITSTATUS(xx) != 0) {
695 rpmlog(RPMLOG_ERR, _("Package check \"%s\" failed.\n"), pkgcheck);
696 if (fail) return RPMRC_FAIL;
702 rpmRC packageBinaries(rpmSpec spec)
704 struct cpioSourceArchive_s csabuf;
707 const char *errorString;
709 char *pkglist = NULL;
711 for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) {
714 if (pkg->fileList == NULL)
717 if ((rc = processScriptFiles(spec, pkg)))
721 headerPutString(pkg->header, RPMTAG_COOKIE, spec->cookie);
724 /* Copy changelog from src rpm */
725 headerCopyTags(spec->packages->header, pkg->header, copyTags);
727 headerPutString(pkg->header, RPMTAG_RPMVERSION, VERSION);
728 headerPutString(pkg->header, RPMTAG_BUILDHOST, buildHost());
729 headerPutUint32(pkg->header, RPMTAG_BUILDTIME, getBuildTime(), 1);
731 addPackageProvides(pkg->header);
733 { char * optflags = rpmExpand("%{optflags}", NULL);
734 headerPutString(pkg->header, RPMTAG_OPTFLAGS, optflags);
735 optflags = _free(optflags);
738 if (spec->sourcePkgId != NULL) {
739 headerPutBin(pkg->header, RPMTAG_SOURCEPKGID, spec->sourcePkgId,16);
742 { char *binFormat = rpmGetPath("%{_rpmfilename}", NULL);
743 char *binRpm, *binDir;
744 binRpm = headerFormat(pkg->header, binFormat, &errorString);
745 binFormat = _free(binFormat);
746 if (binRpm == NULL) {
747 rpmlog(RPMLOG_ERR, _("Could not generate output "
748 "filename for package %s: %s\n"),
749 headerGetString(pkg->header, RPMTAG_NAME), errorString);
752 fn = rpmGetPath("%{_rpmdir}/", binRpm, NULL);
753 if ((binDir = strchr(binRpm, '/')) != NULL) {
757 dn = rpmGetPath("%{_rpmdir}/", binRpm, NULL);
758 if (stat(dn, &st) < 0) {
761 if (mkdir(dn, 0755) == 0)
764 rpmlog(RPMLOG_ERR,_("cannot create %s: %s\n"),
765 dn, strerror(errno));
771 binRpm = _free(binRpm);
774 memset(csa, 0, sizeof(*csa));
775 csa->cpioArchiveSize = 0;
776 csa->cpioFdIn = fdNew(RPMDBG_M("init (packageBinaries)"));
777 csa->cpioList = rpmfiLink(pkg->cpioList, RPMDBG_M("packageBinaries"));
779 rc = writeRPM(&pkg->header, NULL, fn, csa, spec->passPhrase, NULL);
780 csa->cpioList = rpmfiFree(csa->cpioList);
781 csa->cpioFdIn = fdFree(csa->cpioFdIn,
782 RPMDBG_M("init (packageBinaries)"));
783 if (rc == RPMRC_OK) {
784 /* Do check each written package if enabled */
785 char *pkgcheck = rpmExpand("%{?_build_pkgcheck} ", fn, NULL);
786 if (pkgcheck[0] != ' ') {
787 rc = checkPackages(pkgcheck);
789 pkgcheck = _free(pkgcheck);
790 rstrcat(&pkglist, fn);
791 rstrcat(&pkglist, " ");
794 if (rc != RPMRC_OK) {
795 pkglist = _free(pkglist);
800 /* Now check the package set if enabled */
801 if (pkglist != NULL) {
802 char *pkgcheck_set = rpmExpand("%{?_build_pkgcheck_set} ", pkglist, NULL);
803 if (pkgcheck_set[0] != ' ') { /* run only if _build_pkgcheck_set is defined */
804 checkPackages(pkgcheck_set);
806 pkgcheck_set = _free(pkgcheck_set);
807 pkglist = _free(pkglist);
813 rpmRC packageSources(rpmSpec spec)
815 struct cpioSourceArchive_s csabuf;
820 headerPutString(spec->sourceHeader, RPMTAG_RPMVERSION, VERSION);
821 headerPutString(spec->sourceHeader, RPMTAG_BUILDHOST, buildHost());
822 headerPutUint32(spec->sourceHeader, RPMTAG_BUILDTIME, getBuildTime(), 1);
824 spec->cookie = _free(spec->cookie);
826 /* XXX this should be %_srpmdir */
827 { char *fn = rpmGetPath("%{_srcrpmdir}/", spec->sourceRpmName,NULL);
828 char *pkgcheck = rpmExpand("%{?_build_pkgcheck_srpm} ", fn, NULL);
830 memset(csa, 0, sizeof(*csa));
831 csa->cpioArchiveSize = 0;
832 csa->cpioFdIn = fdNew(RPMDBG_M("init (packageSources)"));
833 csa->cpioList = rpmfiLink(spec->sourceCpioList,
834 RPMDBG_M("packageSources"));
836 spec->sourcePkgId = NULL;
837 rc = writeRPM(&spec->sourceHeader, &spec->sourcePkgId, fn,
838 csa, spec->passPhrase, &(spec->cookie));
840 /* Do check SRPM package if enabled */
841 if (rc == RPMRC_OK && pkgcheck[0] != ' ') {
842 rc = checkPackages(pkgcheck);
845 csa->cpioList = rpmfiFree(csa->cpioList);
846 csa->cpioFdIn = fdFree(csa->cpioFdIn,
847 RPMDBG_M("init (packageSources)"));
848 pkgcheck = _free(pkgcheck);