diff options
Diffstat (limited to 'build/pack.c')
-rw-r--r-- | build/pack.c | 764 |
1 files changed, 382 insertions, 382 deletions
diff --git a/build/pack.c b/build/pack.c index 6480cecaa..34e0568a7 100644 --- a/build/pack.c +++ b/build/pack.c @@ -6,8 +6,7 @@ #include "system.h" #include <errno.h> -#include <netdb.h> -#include <time.h> +#include <sys/wait.h> #include <rpm/rpmlib.h> /* RPMSIGTAG*, rpmReadPackageFile */ #include <rpm/rpmfileutil.h> @@ -15,7 +14,6 @@ #include "rpmio/rpmio_internal.h" /* fdInitDigest, fdFiniDigest */ #include "lib/fsm.h" -#include "lib/cpio.h" #include "lib/signature.h" #include "lib/rpmlead.h" #include "build/rpmbuild_internal.h" @@ -23,15 +21,54 @@ #include "debug.h" -typedef struct cpioSourceArchive_s { - rpm_loff_t cpioArchiveSize; - rpmfi cpioList; -} * CSA_t; +static int rpmPackageFilesArchive(rpmfiles fi, int isSrc, + FD_t cfd, ARGV_t dpaths, + rpm_loff_t * archiveSize, char ** failedFile) +{ + int rc = 0; + rpmfi archive = rpmfiNewArchiveWriter(cfd, fi); + + while (!rc && (rc = rpmfiNext(archive)) >= 0) { + /* Copy file into archive. */ + FD_t rfd = NULL; + const char *path = dpaths[rpmfiFX(archive)]; + + rfd = Fopen(path, "r.ufdio"); + if (Ferror(rfd)) { + rc = RPMERR_OPEN_FAILED; + } else { + rc = rpmfiArchiveWriteFile(archive, rfd); + } + + if (rc && failedFile) + *failedFile = xstrdup(path); + if (rfd) { + /* preserve any prior errno across close */ + int myerrno = errno; + Fclose(rfd); + errno = myerrno; + } + } + + if (rc == RPMERR_ITER_END) + rc = 0; + + /* Finish the payload stream */ + if (!rc) + rc = rpmfiArchiveClose(archive); + + if (archiveSize) + *archiveSize = (rc == 0) ? rpmfiArchiveTell(archive) : 0; + + rpmfiFree(archive); + return rc; +} /** * @todo Create transaction set *much* earlier. */ -static rpmRC cpio_doio(FD_t fdo, Header h, CSA_t csa, const char * fmodeMacro) +static rpmRC cpio_doio(FD_t fdo, Package pkg, const char * fmodeMacro, + rpm_loff_t *archiveSize) { char *failedFile = NULL; FD_t cfd; @@ -42,16 +79,18 @@ static rpmRC cpio_doio(FD_t fdo, Header h, CSA_t csa, const char * fmodeMacro) if (cfd == NULL) return RPMRC_FAIL; - fsmrc = rpmPackageFilesArchive(csa->cpioList, headerIsSource(h), cfd, - &csa->cpioArchiveSize, &failedFile); + fsmrc = rpmPackageFilesArchive(pkg->cpioList, headerIsSource(pkg->header), + cfd, pkg->dpaths, + archiveSize, &failedFile); if (fsmrc) { + char *emsg = rpmfileStrerror(fsmrc); if (failedFile) rpmlog(RPMLOG_ERR, _("create archive failed on file %s: %s\n"), - failedFile, rpmcpioStrerror(fsmrc)); + failedFile, emsg); else - rpmlog(RPMLOG_ERR, _("create archive failed: %s\n"), - rpmcpioStrerror(fsmrc)); + rpmlog(RPMLOG_ERR, _("create archive failed: %s\n"), emsg); + free(emsg); } free(failedFile); @@ -92,11 +131,13 @@ static rpmRC addFileToTag(rpmSpec spec, const char * file, } while (fgets(buf, sizeof(buf), f)) { - if (expandMacros(spec, spec->macros, buf, sizeof(buf))) { + char *expanded; + if (rpmExpandMacros(spec->macros, buf, &expanded, 0) < 0) { rpmlog(RPMLOG_ERR, _("%s: line: %s\n"), fn, buf); goto exit; } - appendStringBuf(sb, buf); + appendStringBuf(sb, expanded); + free(expanded); } headerPutString(h, tag, getStringBuf(sb)); rc = RPMRC_OK; @@ -109,40 +150,31 @@ exit: return rc; } -static rpm_time_t * getBuildTime(void) -{ - static rpm_time_t buildTime[1]; - - if (buildTime[0] == 0) - buildTime[0] = (int32_t) time(NULL); - return buildTime; -} - -static const char * buildHost(void) -{ - static char hostname[1024]; - static int oneshot = 0; - struct hostent *hbn; - - if (! oneshot) { - (void) gethostname(hostname, sizeof(hostname)); - hbn = gethostbyname(hostname); - if (hbn) - strcpy(hostname, hbn->h_name); - else - rpmlog(RPMLOG_WARNING, - _("Could not canonicalize hostname: %s\n"), hostname); - oneshot = 1; - } - return(hostname); -} - static rpmRC processScriptFiles(rpmSpec spec, Package pkg) { struct TriggerFileEntry *p; int addflags = 0; rpmRC rc = RPMRC_FAIL; Header h = pkg->header; + struct TriggerFileEntry *tfa[] = {pkg->triggerFiles, + pkg->fileTriggerFiles, + pkg->transFileTriggerFiles}; + + rpmTagVal progTags[] = {RPMTAG_TRIGGERSCRIPTPROG, + RPMTAG_FILETRIGGERSCRIPTPROG, + RPMTAG_TRANSFILETRIGGERSCRIPTPROG}; + + rpmTagVal flagTags[] = {RPMTAG_TRIGGERSCRIPTFLAGS, + RPMTAG_FILETRIGGERSCRIPTFLAGS, + RPMTAG_TRANSFILETRIGGERSCRIPTFLAGS}; + + rpmTagVal scriptTags[] = {RPMTAG_TRIGGERSCRIPTS, + RPMTAG_FILETRIGGERSCRIPTS, + RPMTAG_TRANSFILETRIGGERSCRIPTS}; + rpmTagVal priorityTags[] = {0, + RPMTAG_FILETRIGGERPRIORITIES, + RPMTAG_TRANSFILETRIGGERPRIORITIES}; + int i; if (addFileToTag(spec, pkg->preInFile, h, RPMTAG_PREIN, 1) || addFileToTag(spec, pkg->preUnFile, h, RPMTAG_PREUN, 1) || @@ -155,30 +187,39 @@ static rpmRC processScriptFiles(rpmSpec spec, Package pkg) goto exit; } - /* if any trigger has flags, we need to add flags entry for all of them */ - for (p = pkg->triggerFiles; p != NULL; p = p->next) { - if (p->flags) { - addflags = 1; - break; - } - } - for (p = pkg->triggerFiles; p != NULL; p = p->next) { - headerPutString(h, RPMTAG_TRIGGERSCRIPTPROG, p->prog); - if (addflags) { - headerPutUint32(h, RPMTAG_TRIGGERSCRIPTFLAGS, &p->flags, 1); + for (i = 0; i < sizeof(tfa)/sizeof(tfa[0]); i++) { + addflags = 0; + /* if any trigger has flags, we need to add flags entry for all of them */ + for (p = tfa[i]; p != NULL; p = p->next) { + if (p->flags) { + addflags = 1; + break; + } } - if (p->script) { - headerPutString(h, RPMTAG_TRIGGERSCRIPTS, p->script); - } else if (p->fileName) { - if (addFileToTag(spec, p->fileName, h, RPMTAG_TRIGGERSCRIPTS, 0)) { - goto exit; + for (p = tfa[i]; p != NULL; p = p->next) { + headerPutString(h, progTags[i], p->prog); + + if (priorityTags[i]) { + headerPutUint32(h, priorityTags[i], &p->priority, 1); + } + + if (addflags) { + headerPutUint32(h, flagTags[i], &p->flags, 1); + } + + if (p->script) { + headerPutString(h, scriptTags[i], p->script); + } else if (p->fileName) { + if (addFileToTag(spec, p->fileName, h, scriptTags[i], 0)) { + goto exit; + } + } else { + /* This is dumb. When the header supports NULL string */ + /* this will go away. */ + headerPutString(h, scriptTags[i], ""); } - } else { - /* This is dumb. When the header supports NULL string */ - /* this will go away. */ - headerPutString(h, RPMTAG_TRIGGERSCRIPTS, ""); } } rc = RPMRC_OK; @@ -187,92 +228,40 @@ exit: return rc; } -static rpmRC copyPayload(FD_t ifd, const char *ifn, FD_t ofd, const char *ofn) +static int haveTildeDep(Package pkg) { - char buf[BUFSIZ]; - size_t nb; - rpmRC rc = RPMRC_OK; - - while ((nb = Fread(buf, 1, sizeof(buf), ifd)) > 0) { - if (Fwrite(buf, sizeof(buf[0]), nb, ofd) != nb) { - rpmlog(RPMLOG_ERR, _("Unable to write payload to %s: %s\n"), - ofn, Fstrerror(ofd)); - rc = RPMRC_FAIL; - break; + for (int i = 0; i < PACKAGE_NUM_DEPS; i++) { + rpmds ds = rpmdsInit(pkg->dependencies[i]); + while (rpmdsNext(ds) >= 0) { + if (strchr(rpmdsEVR(ds), '~')) + return 1; } } - - if (nb < 0) { - rpmlog(RPMLOG_ERR, _("Unable to read payload from %s: %s\n"), - ifn, Fstrerror(ifd)); - rc = RPMRC_FAIL; - } - - return rc; + return 0; } -static int depContainsTilde(Header h, rpmTagVal tagEVR) +static int haveRichDep(Package pkg) { - struct rpmtd_s evrs; - const char *evr = NULL; - - if (headerGet(h, tagEVR, &evrs, HEADERGET_MINMEM)) { - while ((evr = rpmtdNextString(&evrs)) != NULL) - if (strchr(evr, '~')) - break; - rpmtdFreeData(&evrs); + for (int i = 0; i < PACKAGE_NUM_DEPS; i++) { + rpmds ds = rpmdsInit(pkg->dependencies[i]); + rpmTagVal tagN = rpmdsTagN(ds); + if (tagN != RPMTAG_REQUIRENAME && tagN != RPMTAG_CONFLICTNAME) + continue; + while (rpmdsNext(ds) >= 0) { + if (rpmdsIsRich(ds)) + return 1; + } } - return evr != NULL; -} - -static rpmTagVal depevrtags[] = { - RPMTAG_PROVIDEVERSION, - RPMTAG_REQUIREVERSION, - RPMTAG_OBSOLETEVERSION, - RPMTAG_CONFLICTVERSION, - RPMTAG_ORDERVERSION, - RPMTAG_TRIGGERVERSION, - RPMTAG_SUGGESTSVERSION, - RPMTAG_ENHANCESVERSION, - 0 -}; - -static int haveTildeDep(Header h) -{ - int i; - - for (i = 0; depevrtags[i] != 0; i++) - if (depContainsTilde(h, depevrtags[i])) - return 1; return 0; } -static rpmRC writeRPM(Header *hdrp, unsigned char ** pkgidp, const char *fileName, - CSA_t csa, char **cookie) +static char *getIOFlags(Package pkg) { - FD_t fd = NULL; - FD_t ifd = NULL; - char * sigtarget = NULL;; - char * rpmio_flags = NULL; - char * SHA1 = NULL; + char *rpmio_flags; const char *s; - Header h; - Header sig = NULL; - int xx; - rpmRC rc = RPMRC_OK; - struct rpmtd_s td; - rpmTagVal sizetag; - rpmTagVal payloadtag; - - /* Transfer header reference form *hdrp to h. */ - h = headerLink(*hdrp); - *hdrp = headerFree(*hdrp); - - if (pkgidp) - *pkgidp = NULL; /* Save payload information */ - if (headerIsSource(h)) + if (headerIsSource(pkg->header)) rpmio_flags = rpmExpand("%{?_source_payload}", NULL); else rpmio_flags = rpmExpand("%{?_binary_payload}", NULL); @@ -286,7 +275,7 @@ static rpmRC writeRPM(Header *hdrp, unsigned char ** pkgidp, const char *fileNam if (s) { char *buf = NULL; const char *compr = NULL; - headerPutString(h, RPMTAG_PAYLOADFORMAT, "cpio"); + headerPutString(pkg->header, RPMTAG_PAYLOADFORMAT, "cpio"); if (rstreq(s+1, "ufdio")) { compr = NULL; @@ -296,229 +285,300 @@ static rpmRC writeRPM(Header *hdrp, unsigned char ** pkgidp, const char *fileNam } else if (rstreq(s+1, "bzdio")) { compr = "bzip2"; /* Add prereq on rpm version that understands bzip2 payloads */ - (void) rpmlibNeedsFeature(h, "PayloadIsBzip2", "3.0.5-1"); + (void) rpmlibNeedsFeature(pkg, "PayloadIsBzip2", "3.0.5-1"); #endif #if HAVE_LZMA_H } else if (rstreq(s+1, "xzdio")) { compr = "xz"; - (void) rpmlibNeedsFeature(h, "PayloadIsXz", "5.2-1"); + (void) rpmlibNeedsFeature(pkg, "PayloadIsXz", "5.2-1"); } else if (rstreq(s+1, "lzdio")) { compr = "lzma"; - (void) rpmlibNeedsFeature(h, "PayloadIsLzma", "4.4.6-1"); + (void) rpmlibNeedsFeature(pkg, "PayloadIsLzma", "4.4.6-1"); +#endif +#ifdef HAVE_ZSTD + } else if (rstreq(s+1, "zstdio")) { + compr = "zstd"; + /* Add prereq on rpm version that understands zstd payloads */ + (void) rpmlibNeedsFeature(pkg, "PayloadIsZstd", "5.4.18-1"); #endif } else { rpmlog(RPMLOG_ERR, _("Unknown payload compression: %s\n"), rpmio_flags); - rc = RPMRC_FAIL; + rpmio_flags = _free(rpmio_flags); goto exit; } if (compr) - headerPutString(h, RPMTAG_PAYLOADCOMPRESSOR, compr); + headerPutString(pkg->header, RPMTAG_PAYLOADCOMPRESSOR, compr); buf = xstrdup(rpmio_flags); buf[s - rpmio_flags] = '\0'; - headerPutString(h, RPMTAG_PAYLOADFLAGS, buf+1); + headerPutString(pkg->header, RPMTAG_PAYLOADFLAGS, buf+1); free(buf); } +exit: + return rpmio_flags; +} +static void finalizeDeps(Package pkg) +{ /* check if the package has a dependency with a '~' */ - if (haveTildeDep(h)) - (void) rpmlibNeedsFeature(h, "TildeInVersions", "4.10.0-1"); + if (haveTildeDep(pkg)) + (void) rpmlibNeedsFeature(pkg, "TildeInVersions", "4.10.0-1"); + + /* check if the package has a rich dependency */ + if (haveRichDep(pkg)) + (void) rpmlibNeedsFeature(pkg, "RichDependencies", "4.12.0-1"); + + /* All dependencies added finally, write them into the header */ + for (int i = 0; i < PACKAGE_NUM_DEPS; i++) { + /* Nuke any previously added dependencies from the header */ + headerDel(pkg->header, rpmdsTagN(pkg->dependencies[i])); + headerDel(pkg->header, rpmdsTagEVR(pkg->dependencies[i])); + headerDel(pkg->header, rpmdsTagF(pkg->dependencies[i])); + headerDel(pkg->header, rpmdsTagTi(pkg->dependencies[i])); + /* ...and add again, now with automatic dependencies included */ + rpmdsPutToHeader(pkg->dependencies[i], pkg->header); + } +} - /* Create and add the cookie */ - if (cookie) { - rasprintf(cookie, "%s %d", buildHost(), (int) (*getBuildTime())); - headerPutString(h, RPMTAG_COOKIE, *cookie); +static void *nullDigest(int algo, int ascii) +{ + void *d = NULL; + DIGEST_CTX ctx = rpmDigestInit(algo, 0); + rpmDigestFinal(ctx, &d, NULL, ascii); + return d; +} + +static rpmRC fdJump(FD_t fd, off_t offset) +{ + if (Fseek(fd, offset, SEEK_SET) < 0) { + rpmlog(RPMLOG_ERR, _("Could not seek in file %s: %s\n"), + Fdescr(fd), Fstrerror(fd)); + return RPMRC_FAIL; } - - /* Reallocate the header into one contiguous region. */ - h = headerReload(h, RPMTAG_HEADERIMMUTABLE); - if (h == NULL) { /* XXX can't happen */ - rc = RPMRC_FAIL; - rpmlog(RPMLOG_ERR, _("Unable to create immutable header region.\n")); - goto exit; + return RPMRC_OK; +} + +static rpmRC fdConsume(FD_t fd, off_t start, off_t nbytes) +{ + size_t bufsiz = 32*BUFSIZ; + unsigned char buf[bufsiz]; + off_t left = nbytes; + ssize_t nb; + + if (start && fdJump(fd, start)) + return RPMRC_FAIL; + + while (left > 0) { + nb = Fread(buf, 1, (left < bufsiz) ? left : bufsiz, fd); + if (nb > 0) + left -= nb; + else + break; + }; + + if (left) { + rpmlog(RPMLOG_ERR, _("Failed to read %jd bytes in file %s: %s\n"), + (intmax_t) nbytes, Fdescr(fd), Fstrerror(fd)); } - /* Re-reference reallocated header. */ - *hdrp = headerLink(h); - /* - * Write the header+archive into a temp file so that the size of - * archive (after compression) can be added to the header. - */ - fd = rpmMkTempFile(NULL, &sigtarget); - if (fd == NULL || Ferror(fd)) { - rc = RPMRC_FAIL; - rpmlog(RPMLOG_ERR, _("Unable to open temp file.\n")); + return (left == 0) ? RPMRC_OK : RPMRC_FAIL; +} + +static rpmRC writeHdr(FD_t fd, Header pkgh) +{ + /* Reallocate the header into one contiguous region for writing. */ + Header h = headerReload(headerCopy(pkgh), RPMTAG_HEADERIMMUTABLE); + rpmRC rc = RPMRC_FAIL; + + if (h == NULL) { + rpmlog(RPMLOG_ERR,_("Unable to create immutable header region\n")); goto exit; } - fdInitDigest(fd, PGPHASHALGO_SHA1, 0); if (headerWrite(fd, h, HEADER_MAGIC_YES)) { - rc = RPMRC_FAIL; - rpmlog(RPMLOG_ERR, _("Unable to write temp header\n")); - } else { /* Write the archive and get the size */ - (void) Fflush(fd); - fdFiniDigest(fd, PGPHASHALGO_SHA1, (void **)&SHA1, NULL, 1); - if (csa->cpioList != NULL) { - rc = cpio_doio(fd, h, csa, rpmio_flags); - } else { - rc = RPMRC_FAIL; - rpmlog(RPMLOG_ERR, _("Bad CSA data\n")); - } + rpmlog(RPMLOG_ERR, _("Unable to write header to %s: %s\n"), + Fdescr(fd), Fstrerror(fd)); + goto exit; } + (void) Fflush(fd); + rc = RPMRC_OK; + +exit: + headerFree(h); + return rc; +} + +/* + * This is more than just a little insane: + * In order to write the signature, we need to know the size and + * the size and digests of the header and payload, which are located + * after the signature on disk. We also need a digest of the compressed + * payload for the main header, and of course the payload is after the + * header on disk. So we need to create placeholders for both the + * signature and main header that exactly match the final sizes, calculate + * the payload digest, then generate and write the real main header to + * be able to FINALLY calculate the digests we need for the signature + * header. In other words, we need to write things in the exact opposite + * order to how the RPM format is laid on disk. + */ +static rpmRC writeRPM(Package pkg, unsigned char ** pkgidp, + const char *fileName, char **cookie, + rpm_time_t buildTime, const char* buildHost) +{ + FD_t fd = NULL; + char * rpmio_flags = NULL; + char * SHA1 = NULL; + char * SHA256 = NULL; + uint8_t * MD5 = NULL; + char * pld = NULL; + uint32_t pld_algo = PGPHASHALGO_SHA256; /* TODO: macro configuration */ + rpmRC rc = RPMRC_FAIL; /* assume failure */ + rpm_loff_t archiveSize = 0; + off_t sigStart, hdrStart, payloadStart, payloadEnd; + + if (pkgidp) + *pkgidp = NULL; - if (rc != RPMRC_OK) + rpmio_flags = getIOFlags(pkg); + if (!rpmio_flags) goto exit; - (void) Fclose(fd); - fd = NULL; - (void) unlink(fileName); + finalizeDeps(pkg); - /* Generate the signature */ - (void) fflush(stdout); - sig = rpmNewSignature(); + /* Create and add the cookie */ + if (cookie) { + rasprintf(cookie, "%s %d", buildHost, buildTime); + headerPutString(pkg->header, RPMTAG_COOKIE, *cookie); + } /* - * There should be rpmlib() dependency on this, but that doesn't - * really do much good as these are signature tags that get read - * way before dependency checking has a chance to figure out anything. - * On the positive side, not inserting the 32bit tag at all means - * older rpm will just bail out with error message on attempt to read - * such a package. + * Add system-wide Tizen build information */ - if (csa->cpioArchiveSize < UINT32_MAX) { - sizetag = RPMSIGTAG_SIZE; - payloadtag = RPMSIGTAG_PAYLOADSIZE; - } else { - sizetag = RPMSIGTAG_LONGSIZE; - payloadtag = RPMSIGTAG_LONGARCHIVESIZE; - } - (void) rpmGenDigest(sig, sigtarget, sizetag); - (void) rpmGenDigest(sig, sigtarget, RPMSIGTAG_MD5); - - if (SHA1) { - /* XXX can't use rpmtdFromFoo() on RPMSIGTAG_* items */ - rpmtdReset(&td); - td.tag = RPMSIGTAG_SHA1; - td.type = RPM_STRING_TYPE; - td.data = SHA1; - td.count = 1; - headerPut(sig, &td, HEADERPUT_DEFAULT); - SHA1 = _free(SHA1); - } + char *buildinfo = rpmExpand("%{?_buildinfo}", NULL); + if (buildinfo && *buildinfo) { + int xx; + int count = 0; + char **strings = NULL; - { - /* XXX can't use headerPutType() on legacy RPMSIGTAG_* items */ - rpmtdReset(&td); - td.tag = payloadtag; - td.count = 1; - if (payloadtag == RPMSIGTAG_PAYLOADSIZE) { - rpm_off_t asize = csa->cpioArchiveSize; - td.type = RPM_INT32_TYPE; - td.data = &asize; - headerPut(sig, &td, HEADERPUT_DEFAULT); - } else { - rpm_loff_t asize = csa->cpioArchiveSize; - td.type = RPM_INT64_TYPE; - td.data = &asize; - headerPut(sig, &td, HEADERPUT_DEFAULT); - } + + if ((xx = poptParseArgvString(buildinfo, &count, &strings))) { + rc = RPMRC_FAIL; + free(buildinfo); + rpmlog(RPMLOG_ERR, _("Can't parse BUILDINFO tag: %s\n"), poptStrerror(xx)); + goto exit; + } + + if (count) + headerPutStringArray(pkg->header, RPMTAG_BUILDINFO, strings, count); + + strings = _free(strings); } + free(buildinfo); - /* Reallocate the signature into one contiguous region. */ - sig = headerReload(sig, RPMTAG_HEADERSIGNATURES); - if (sig == NULL) { /* XXX can't happen */ - rc = RPMRC_FAIL; - rpmlog(RPMLOG_ERR, _("Unable to reload signature header.\n")); + /* Create a dummy payload digest to get the header size right */ + pld = nullDigest(pld_algo, 1); + headerPutUint32(pkg->header, RPMTAG_PAYLOADDIGESTALGO, &pld_algo, 1); + headerPutString(pkg->header, RPMTAG_PAYLOADDIGEST, pld); + pld = _free(pld); + + /* Check for UTF-8 encoding of string tags, add encoding tag if all good */ + if (checkForEncoding(pkg->header, 1)) goto exit; - } /* Open the output file */ - fd = Fopen(fileName, "w.ufdio"); + fd = Fopen(fileName, "w+.ufdio"); if (fd == NULL || Ferror(fd)) { - rc = RPMRC_FAIL; rpmlog(RPMLOG_ERR, _("Could not open %s: %s\n"), fileName, Fstrerror(fd)); goto exit; } /* Write the lead section into the package. */ - { - rpmlead lead = rpmLeadFromHeader(h); - rc = rpmLeadWrite(fd, lead); - rpmLeadFree(lead); - if (rc != RPMRC_OK) { - rc = RPMRC_FAIL; - rpmlog(RPMLOG_ERR, _("Unable to write package: %s\n"), - Fstrerror(fd)); - goto exit; - } + if (rpmLeadWrite(fd, pkg->header)) { + rpmlog(RPMLOG_ERR, _("Unable to write package: %s\n"), Fstrerror(fd)); + goto exit; } - /* Write the signature section into the package. */ - if (rpmWriteSignature(fd, sig)) { - rc = RPMRC_FAIL; + /* Save the position of signature section */ + sigStart = Ftell(fd); + + /* Generate and write a placeholder signature header */ + SHA1 = nullDigest(PGPHASHALGO_SHA1, 1); + SHA256 = nullDigest(PGPHASHALGO_SHA256, 1); + MD5 = nullDigest(PGPHASHALGO_MD5, 0); + if (rpmGenerateSignature(SHA256, SHA1, MD5, 0, 0, fd)) goto exit; - } + SHA1 = _free(SHA1); + SHA256 = _free(SHA256); + MD5 = _free(MD5); - /* Append the header and archive */ - ifd = Fopen(sigtarget, "r.ufdio"); - if (ifd == NULL || Ferror(ifd)) { - rc = RPMRC_FAIL; - rpmlog(RPMLOG_ERR, _("Unable to open sigtarget %s: %s\n"), - sigtarget, Fstrerror(ifd)); + /* Write a placeholder header. */ + hdrStart = Ftell(fd); + if (writeHdr(fd, pkg->header)) goto exit; - } - /* Add signatures to header, and write header into the package. */ - /* XXX header+payload digests/signatures might be checked again here. */ - { Header nh = headerRead(ifd, HEADER_MAGIC_YES); + /* Write payload section (cpio archive) */ + payloadStart = Ftell(fd); + if (cpio_doio(fd, pkg, rpmio_flags, &archiveSize)) + goto exit; + payloadEnd = Ftell(fd); - if (nh == NULL) { - rc = RPMRC_FAIL; - rpmlog(RPMLOG_ERR, _("Unable to read header from %s: %s\n"), - sigtarget, Fstrerror(ifd)); - goto exit; - } + /* Re-read payload to calculate compressed digest */ + fdInitDigestID(fd, pld_algo, RPMTAG_PAYLOADDIGEST, 0); + if (fdConsume(fd, payloadStart, payloadEnd - payloadStart)) + goto exit; + fdFiniDigest(fd, RPMTAG_PAYLOADDIGEST, (void **)&pld, NULL, 1); - xx = headerWrite(fd, nh, HEADER_MAGIC_YES); - headerFree(nh); + /* Insert the payload digest in main header */ + headerDel(pkg->header, RPMTAG_PAYLOADDIGEST); + headerPutString(pkg->header, RPMTAG_PAYLOADDIGEST, pld); + pld = _free(pld); - if (xx) { - rc = RPMRC_FAIL; - rpmlog(RPMLOG_ERR, _("Unable to write header to %s: %s\n"), - fileName, Fstrerror(fd)); - goto exit; - } - } - - /* Write the payload into the package. */ - rc = copyPayload(ifd, fileName, fd, sigtarget); + /* Write the final header */ + if (fdJump(fd, hdrStart)) + goto exit; + if (writeHdr(fd, pkg->header)) + goto exit; + + /* Calculate digests: SHA on header, legacy MD5 on header + payload */ + fdInitDigestID(fd, PGPHASHALGO_MD5, RPMTAG_SIGMD5, 0); + fdInitDigestID(fd, PGPHASHALGO_SHA1, RPMTAG_SHA1HEADER, 0); + fdInitDigestID(fd, PGPHASHALGO_SHA256, RPMTAG_SHA256HEADER, 0); + if (fdConsume(fd, hdrStart, payloadStart - hdrStart)) + goto exit; + fdFiniDigest(fd, RPMTAG_SHA1HEADER, (void **)&SHA1, NULL, 1); + fdFiniDigest(fd, RPMTAG_SHA256HEADER, (void **)&SHA256, NULL, 1); + + if (fdConsume(fd, 0, payloadEnd - payloadStart)) + goto exit; + fdFiniDigest(fd, RPMTAG_SIGMD5, (void **)&MD5, NULL, 0); + + if (fdJump(fd, sigStart)) + goto exit; + + /* Generate the signature. Now with right values */ + if (rpmGenerateSignature(SHA256, SHA1, MD5, payloadEnd - hdrStart, archiveSize, fd)) + goto exit; + + rc = RPMRC_OK; exit: free(rpmio_flags); free(SHA1); - headerFree(h); + free(SHA256); /* XXX Fish the pkgid out of the signature header. */ - if (sig != NULL && pkgidp != NULL) { - struct rpmtd_s md5tag; - headerGet(sig, RPMSIGTAG_MD5, &md5tag, HEADERGET_DEFAULT); - if (rpmtdType(&md5tag) == RPM_BIN_TYPE && - md5tag.count == 16 && md5tag.data != NULL) { - *pkgidp = md5tag.data; + if (pkgidp != NULL) { + if (MD5 != NULL) { + *pkgidp = MD5; } + } else { + free(MD5); } - rpmFreeSignature(sig); - Fclose(ifd); Fclose(fd); - if (sigtarget) { - (void) unlink(sigtarget); - free(sigtarget); - } - if (rc == RPMRC_OK) rpmlog(RPMLOG_NOTICE, _("Wrote: %s\n"), fileName); else @@ -553,78 +613,13 @@ static rpmRC checkPackages(char *pkgcheck) return RPMRC_OK; } -static void trimChangelog(Header h) -{ - static int oneshot; - static int cuttime, minnum, maxnum; - int * times; - char ** names = 0, ** texts = 0; - int i, keep, count = 0; - - if (!oneshot) { - char *binarychangelogtrim = rpmExpand("%{?_binarychangelogtrim}", NULL); - oneshot = 1; - if (binarychangelogtrim && *binarychangelogtrim) { - maxnum = atoi(binarychangelogtrim); - binarychangelogtrim = strchr(binarychangelogtrim, ','); - if (binarychangelogtrim) - binarychangelogtrim++; - } - if (binarychangelogtrim && *binarychangelogtrim) { - cuttime = atoi(binarychangelogtrim); - binarychangelogtrim = strchr(binarychangelogtrim, ','); - if (binarychangelogtrim) - binarychangelogtrim++; - } - if (binarychangelogtrim && *binarychangelogtrim) { - minnum = atoi(binarychangelogtrim); - binarychangelogtrim = strchr(binarychangelogtrim, ','); - } - } - if (!cuttime && !minnum && !maxnum) { - return; - } - if (!headerGetEntry(h, RPMTAG_CHANGELOGTIME, NULL, (void **) ×, &count)) - return; - if ((!cuttime || count <= minnum) && (!maxnum || count <= maxnum)) { - return; - } - keep = count; - if (maxnum && keep > maxnum) - keep = maxnum; - if (cuttime) { - for (i = 0; i < keep; i++) { - if (i >= minnum && times[i] < cuttime) - break; - } - keep = i; - } - if (keep >= count) - return; - headerGetEntry(h, RPMTAG_CHANGELOGNAME, NULL, (void **) &names, &count); - headerGetEntry(h, RPMTAG_CHANGELOGTEXT, NULL, (void **) &texts, &count); - headerModifyEntry(h, RPMTAG_CHANGELOGTIME, RPM_INT32_TYPE, times, keep); - headerModifyEntry(h, RPMTAG_CHANGELOGNAME, RPM_STRING_ARRAY_TYPE, names, keep); - headerModifyEntry(h, RPMTAG_CHANGELOGTEXT, RPM_STRING_ARRAY_TYPE, texts, keep); - free(names); - free(texts); -} - -rpmRC packageBinaries(rpmSpec spec, const char *cookie, int cheating) +static rpmRC packageBinary(rpmSpec spec, Package pkg, const char *cookie, int cheating, char** filename) { - struct cpioSourceArchive_s csabuf; - CSA_t csa = &csabuf; - rpmRC rc; - const char *errorString; - Package pkg; - char *pkglist = NULL; - - trimChangelog(spec->packages->header); - for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) { - char *fn; + const char *errorString; + rpmRC rc = RPMRC_OK; if (pkg->fileList == NULL) - continue; + return rc; if ((rc = processScriptFiles(spec, pkg))) return rc; @@ -637,15 +632,15 @@ rpmRC packageBinaries(rpmSpec spec, const char *cookie, int cheating) headerCopyTags(spec->packages->header, pkg->header, copyTags); headerPutString(pkg->header, RPMTAG_RPMVERSION, VERSION); - headerPutString(pkg->header, RPMTAG_BUILDHOST, buildHost()); - headerPutUint32(pkg->header, RPMTAG_BUILDTIME, getBuildTime(), 1); + headerPutString(pkg->header, RPMTAG_BUILDHOST, spec->buildHost); + headerPutUint32(pkg->header, RPMTAG_BUILDTIME, &(spec->buildTime), 1); if (spec->sourcePkgId != NULL) { headerPutBin(pkg->header, RPMTAG_SOURCEPKGID, spec->sourcePkgId,16); } if (cheating) { - (void) rpmlibNeedsFeature(pkg->header, "ShortCircuited", "4.9.0-1"); + (void) rpmlibNeedsFeature(pkg, "ShortCircuited", "4.9.0-1"); } { char *binFormat = rpmGetPath("%{_rpmfilename}", NULL); @@ -658,14 +653,14 @@ rpmRC packageBinaries(rpmSpec spec, const char *cookie, int cheating) headerGetString(pkg->header, RPMTAG_NAME), errorString); return RPMRC_FAIL; } - fn = rpmGetPath("%{_rpmdir}/", binRpm, NULL); + *filename = rpmGetPath("%{_rpmdir}/", binRpm, NULL); if ((binDir = strchr(binRpm, '/')) != NULL) { struct stat st; char *dn; *binDir = '\0'; dn = rpmGetPath("%{_rpmdir}/", binRpm, NULL); if (stat(dn, &st) < 0) { - switch(errno) { + switch (errno) { case ENOENT: if (mkdir(dn, 0755) == 0) break; @@ -680,19 +675,28 @@ rpmRC packageBinaries(rpmSpec spec, const char *cookie, int cheating) free(binRpm); } - memset(csa, 0, sizeof(*csa)); - csa->cpioArchiveSize = 0; - csa->cpioList = rpmfiLink(pkg->cpioList); - - rc = writeRPM(&pkg->header, NULL, fn, csa, NULL); - csa->cpioList = rpmfiFree(csa->cpioList); + rc = writeRPM(pkg, NULL, *filename, NULL, spec->buildTime, spec->buildHost); if (rc == RPMRC_OK) { /* Do check each written package if enabled */ - char *pkgcheck = rpmExpand("%{?_build_pkgcheck} ", fn, NULL); + char *pkgcheck = rpmExpand("%{?_build_pkgcheck} ", *filename, NULL); if (pkgcheck[0] != ' ') { rc = checkPackages(pkgcheck); } free(pkgcheck); + } + return rc; +} + +rpmRC packageBinaries(rpmSpec spec, const char *cookie, int cheating) +{ + rpmRC rc; + Package pkg; + char *pkglist = NULL; + + for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) { + char *fn = NULL; + rc = packageBinary(spec, pkg, cookie, cheating, &fn); + if (rc == RPMRC_OK) { rstrcat(&pkglist, fn); rstrcat(&pkglist, " "); } @@ -718,32 +722,28 @@ rpmRC packageBinaries(rpmSpec spec, const char *cookie, int cheating) rpmRC packageSources(rpmSpec spec, char **cookie) { - struct cpioSourceArchive_s csabuf; - CSA_t csa = &csabuf; + Package sourcePkg = spec->sourcePackage; rpmRC rc; + uint32_t one = 1; /* Add some cruft */ - headerPutString(spec->sourceHeader, RPMTAG_RPMVERSION, VERSION); - headerPutString(spec->sourceHeader, RPMTAG_BUILDHOST, buildHost()); - headerPutUint32(spec->sourceHeader, RPMTAG_BUILDTIME, getBuildTime(), 1); + headerPutString(sourcePkg->header, RPMTAG_RPMVERSION, VERSION); + headerPutString(sourcePkg->header, RPMTAG_BUILDHOST, spec->buildHost); + headerPutUint32(sourcePkg->header, RPMTAG_BUILDTIME, &(spec->buildTime), 1); + headerPutUint32(sourcePkg->header, RPMTAG_SOURCEPACKAGE, &one, 1); /* XXX this should be %_srpmdir */ { char *fn = rpmGetPath("%{_srcrpmdir}/", spec->sourceRpmName,NULL); char *pkgcheck = rpmExpand("%{?_build_pkgcheck_srpm} ", fn, NULL); - memset(csa, 0, sizeof(*csa)); - csa->cpioArchiveSize = 0; - csa->cpioList = rpmfiLink(spec->sourceCpioList); - spec->sourcePkgId = NULL; - rc = writeRPM(&spec->sourceHeader, &spec->sourcePkgId, fn, csa, cookie); + rc = writeRPM(sourcePkg, &spec->sourcePkgId, fn, cookie, spec->buildTime, spec->buildHost); /* Do check SRPM package if enabled */ if (rc == RPMRC_OK && pkgcheck[0] != ' ') { rc = checkPackages(pkgcheck); } - rpmfiFree(csa->cpioList); free(pkgcheck); free(fn); } |