|
Richard Phibel |
bd001b |
From: Richard Phibel <richardphibel@meta.com>
|
|
Richard Phibel |
bd001b |
|
|
Richard Phibel |
bd001b |
Subject: RPM with Copy on Write: workaround for corrupt signature header
|
|
Richard Phibel |
bd001b |
|
|
Richard Phibel |
bd001b |
commit 7976c921f60ec5d20c50c4c702ec5636b39210ba
|
|
Richard Phibel |
bd001b |
Author: Richard Phibel <richardphibel@meta.com>
|
|
Richard Phibel |
bd001b |
Date: Wed Oct 26 18:57:19 2022 +0200
|
|
Richard Phibel |
bd001b |
|
|
Richard Phibel |
bd001b |
RPM with Copy on Write: workaround for corrupt signature header
|
|
Richard Phibel |
bd001b |
|
|
Richard Phibel |
bd001b |
Some packages have errors in the signature header. These errors do not
|
|
Richard Phibel |
bd001b |
prevent installation of the package but cause issues in rpm2extents
|
|
Richard Phibel |
bd001b |
conversion. This commit implements the same fix as in
|
|
Richard Phibel |
bd001b |
unloadImmutableRegion.
|
|
Richard Phibel |
bd001b |
|
|
Richard Phibel |
bd001b |
Signed-off-by: Richard Phibel <richardphibel@meta.com>
|
|
Richard Phibel |
bd001b |
|
|
Richard Phibel |
bd001b |
diff --git a/rpm2extents.c b/rpm2extents.c
|
|
Richard Phibel |
bd001b |
index 702d3765d76faf618992ca112011d2312d7fcdcc..b641511fff884e3c8fb396f28acbd8e2c736e28a 100644
|
|
Richard Phibel |
bd001b |
--- a/rpm2extents.c
|
|
Richard Phibel |
bd001b |
+++ b/rpm2extents.c
|
|
Richard Phibel |
bd001b |
@@ -139,7 +139,7 @@ exit:
|
|
Richard Phibel |
bd001b |
* @param package_name package name
|
|
Richard Phibel |
bd001b |
* @return true if package is in deny list
|
|
Richard Phibel |
bd001b |
*/
|
|
Richard Phibel |
bd001b |
-static inline int isInDenyList(char * package_name)
|
|
Richard Phibel |
bd001b |
+static inline int isInDenyList(char *package_name)
|
|
Richard Phibel |
bd001b |
{
|
|
Richard Phibel |
bd001b |
int is_in_deny_list = 0;
|
|
Richard Phibel |
bd001b |
if (package_name) {
|
|
Richard Phibel |
bd001b |
@@ -153,7 +153,7 @@ static inline int isInDenyList(char * package_name)
|
|
Richard Phibel |
bd001b |
denytlist_item = strtok(NULL, ",");
|
|
Richard Phibel |
bd001b |
}
|
|
Richard Phibel |
bd001b |
}
|
|
Richard Phibel |
bd001b |
- return is_in_deny_list;
|
|
Richard Phibel |
bd001b |
+ return is_in_deny_list;
|
|
Richard Phibel |
bd001b |
}
|
|
Richard Phibel |
bd001b |
|
|
Richard Phibel |
bd001b |
static rpmRC FDWriteSignaturesValidation(FD_t fdo, int rpmvsrc, char *msg) {
|
|
Richard Phibel |
bd001b |
@@ -229,6 +229,22 @@ exit:
|
|
Richard Phibel |
bd001b |
return rc;
|
|
Richard Phibel |
bd001b |
}
|
|
Richard Phibel |
bd001b |
|
|
Richard Phibel |
bd001b |
+static void sanitizeSignatureHeader(Header * sigh)
|
|
Richard Phibel |
bd001b |
+{
|
|
Richard Phibel |
bd001b |
+ struct rpmtd_s td;
|
|
Richard Phibel |
bd001b |
+
|
|
Richard Phibel |
bd001b |
+ /* This is inspired by the code in unloadImmutableRegion. See https://github.com/rpm-software-management/rpm/pull/1330 */
|
|
Richard Phibel |
bd001b |
+ if (!headerGet(*sigh, RPMTAG_HEADERSIGNATURES, &td, HEADERGET_DEFAULT)) {
|
|
Richard Phibel |
bd001b |
+ /* Signature header corrupt/missing */
|
|
Richard Phibel |
bd001b |
+ rpmlog(RPMLOG_WARNING, _("Error verifying signature header\n"));
|
|
Richard Phibel |
bd001b |
+ rpmtdFreeData(&td);
|
|
Richard Phibel |
bd001b |
+ Header nh = headerCopy(*sigh);
|
|
Richard Phibel |
bd001b |
+ headerFree(*sigh);
|
|
Richard Phibel |
bd001b |
+ *sigh = headerLink(nh);
|
|
Richard Phibel |
bd001b |
+ headerFree(nh);
|
|
Richard Phibel |
bd001b |
+ }
|
|
Richard Phibel |
bd001b |
+}
|
|
Richard Phibel |
bd001b |
+
|
|
Richard Phibel |
bd001b |
static rpmRC process_package(FD_t fdi, FD_t digestori, FD_t validationi)
|
|
Richard Phibel |
bd001b |
{
|
|
Richard Phibel |
bd001b |
uint32_t diglen;
|
|
Richard Phibel |
bd001b |
@@ -261,7 +277,7 @@ static rpmRC process_package(FD_t fdi, FD_t digestori, FD_t validationi)
|
|
Richard Phibel |
bd001b |
uint32_t offset_ix = 0;
|
|
Richard Phibel |
bd001b |
size_t len;
|
|
Richard Phibel |
bd001b |
int next = 0;
|
|
Richard Phibel |
bd001b |
- struct rpmlead_s l;
|
|
Richard Phibel |
bd001b |
+ struct rpmlead_s l;
|
|
Richard Phibel |
bd001b |
rpmfiles files = NULL;
|
|
Richard Phibel |
bd001b |
rpmfi fi = NULL;
|
|
Richard Phibel |
bd001b |
char *msg = NULL;
|
|
Richard Phibel |
bd001b |
@@ -274,43 +290,47 @@ static rpmRC process_package(FD_t fdi, FD_t digestori, FD_t validationi)
|
|
Richard Phibel |
bd001b |
|
|
Richard Phibel |
bd001b |
/* Skip conversion if package is in deny list */
|
|
Richard Phibel |
bd001b |
if (isInDenyList(l.name)) {
|
|
Richard Phibel |
bd001b |
+ rpmlog(RPMLOG_WARNING, _("package %s is in deny list: conversion skipped\n"), l.name);
|
|
Richard Phibel |
bd001b |
if (rpmLeadWrite(fdo, l)) {
|
|
Richard Phibel |
bd001b |
- fprintf(stderr, _("Unable to write package lead: %s\n"),
|
|
Richard Phibel |
bd001b |
- Fstrerror(fdo));
|
|
Richard Phibel |
bd001b |
+ rpmlog(RPMLOG_ERR, _("Unable to write package lead: %s\n"),
|
|
Richard Phibel |
bd001b |
+ Fstrerror(fdo));
|
|
Richard Phibel |
bd001b |
rc = RPMRC_FAIL;
|
|
Richard Phibel |
bd001b |
goto exit;
|
|
Richard Phibel |
bd001b |
}
|
|
Richard Phibel |
bd001b |
|
|
Richard Phibel |
bd001b |
ssize_t fdilength = ufdCopy(fdi, fdo);
|
|
Richard Phibel |
bd001b |
if (fdilength == -1) {
|
|
Richard Phibel |
bd001b |
- fprintf(stderr, _("process_package cat failed\n"));
|
|
Richard Phibel |
bd001b |
+ rpmlog(RPMLOG_ERR, _("process_package cat failed\n"));
|
|
Richard Phibel |
bd001b |
rc = RPMRC_FAIL;
|
|
Richard Phibel |
bd001b |
goto exit;
|
|
Richard Phibel |
bd001b |
}
|
|
Richard Phibel |
bd001b |
|
|
Richard Phibel |
bd001b |
goto exit;
|
|
Richard Phibel |
bd001b |
} else {
|
|
Richard Phibel |
bd001b |
- if (rpmReadPackageRaw(fdi, &sigh, &h)) {
|
|
Richard Phibel |
bd001b |
- rpmlog(RPMLOG_ERR, _("Error reading package\n"));
|
|
Richard Phibel |
bd001b |
- exit(EXIT_FAILURE);
|
|
Richard Phibel |
bd001b |
- }
|
|
Richard Phibel |
bd001b |
+ if (rpmReadPackageRaw(fdi, &sigh, &h)) {
|
|
Richard Phibel |
bd001b |
+ rpmlog(RPMLOG_ERR, _("Error reading package\n"));
|
|
Richard Phibel |
bd001b |
+ exit(EXIT_FAILURE);
|
|
Richard Phibel |
bd001b |
+ }
|
|
Richard Phibel |
bd001b |
|
|
Richard Phibel |
bd001b |
- if (rpmLeadWriteFromHeader(fdo, h))
|
|
Richard Phibel |
bd001b |
- {
|
|
Richard Phibel |
bd001b |
- rpmlog(RPMLOG_ERR, _("Unable to write package lead: %s\n"),
|
|
Richard Phibel |
bd001b |
- Fstrerror(fdo));
|
|
Richard Phibel |
bd001b |
- exit(EXIT_FAILURE);
|
|
Richard Phibel |
bd001b |
- }
|
|
Richard Phibel |
bd001b |
+ sanitizeSignatureHeader(&sigh;;
|
|
Richard Phibel |
bd001b |
|
|
Richard Phibel |
bd001b |
- if (rpmWriteSignature(fdo, sigh)) {
|
|
Richard Phibel |
bd001b |
- rpmlog(RPMLOG_ERR, _("Unable to write signature: %s\n"), Fstrerror(fdo));
|
|
Richard Phibel |
bd001b |
- exit(EXIT_FAILURE);
|
|
Richard Phibel |
bd001b |
- }
|
|
Richard Phibel |
bd001b |
+ if (rpmLeadWriteFromHeader(fdo, h)) {
|
|
Richard Phibel |
bd001b |
+ rpmlog(RPMLOG_ERR, _("Unable to write package lead: %s\n"),
|
|
Richard Phibel |
bd001b |
+ Fstrerror(fdo));
|
|
Richard Phibel |
bd001b |
+ exit(EXIT_FAILURE);
|
|
Richard Phibel |
bd001b |
+ }
|
|
Richard Phibel |
bd001b |
|
|
Richard Phibel |
bd001b |
- if (headerWrite(fdo, h, HEADER_MAGIC_YES)) {
|
|
Richard Phibel |
bd001b |
- rpmlog(RPMLOG_ERR, _("Unable to write headers: %s\n"), Fstrerror(fdo));
|
|
Richard Phibel |
bd001b |
- exit(EXIT_FAILURE);
|
|
Richard Phibel |
bd001b |
- }
|
|
Richard Phibel |
bd001b |
+ if (rpmWriteSignature(fdo, sigh)) {
|
|
Richard Phibel |
bd001b |
+ rpmlog(RPMLOG_ERR, _("Unable to write signature: %s\n"),
|
|
Richard Phibel |
bd001b |
+ Fstrerror(fdo));
|
|
Richard Phibel |
bd001b |
+ exit(EXIT_FAILURE);
|
|
Richard Phibel |
bd001b |
+ }
|
|
Richard Phibel |
bd001b |
+
|
|
Richard Phibel |
bd001b |
+ if (headerWrite(fdo, h, HEADER_MAGIC_YES)) {
|
|
Richard Phibel |
bd001b |
+ rpmlog(RPMLOG_ERR, _("Unable to write headers: %s\n"),
|
|
Richard Phibel |
bd001b |
+ Fstrerror(fdo));
|
|
Richard Phibel |
bd001b |
+ exit(EXIT_FAILURE);
|
|
Richard Phibel |
bd001b |
+ }
|
|
Richard Phibel |
bd001b |
|
|
Richard Phibel |
bd001b |
/* Retrieve payload size and compression type. */
|
|
Richard Phibel |
bd001b |
{
|
|
Richard Phibel |
bd001b |
@@ -323,10 +343,11 @@ static rpmRC process_package(FD_t fdi, FD_t digestori, FD_t validationi)
|
|
Richard Phibel |
bd001b |
gzdi = Fdopen(fdi, rpmio_flags); /* XXX gzdi == fdi */
|
|
Richard Phibel |
bd001b |
free(rpmio_flags);
|
|
Richard Phibel |
bd001b |
|
|
Richard Phibel |
bd001b |
- if (gzdi == NULL) {
|
|
Richard Phibel |
bd001b |
- rpmlog(RPMLOG_ERR, _("cannot re-open payload: %s\n"), Fstrerror(gzdi));
|
|
Richard Phibel |
bd001b |
- exit(EXIT_FAILURE);
|
|
Richard Phibel |
bd001b |
- }
|
|
Richard Phibel |
bd001b |
+ if (gzdi == NULL) {
|
|
Richard Phibel |
bd001b |
+ rpmlog(RPMLOG_ERR, _("cannot re-open payload: %s\n"),
|
|
Richard Phibel |
bd001b |
+ Fstrerror(gzdi));
|
|
Richard Phibel |
bd001b |
+ exit(EXIT_FAILURE);
|
|
Richard Phibel |
bd001b |
+ }
|
|
Richard Phibel |
bd001b |
|
|
Richard Phibel |
bd001b |
files = rpmfilesNew(NULL, h, 0, RPMFI_KEEPHEADER);
|
|
Richard Phibel |
bd001b |
fi = rpmfiNewArchiveReader(gzdi, files,
|
|
Richard Phibel |
bd001b |
@@ -348,124 +369,128 @@ static rpmRC process_package(FD_t fdi, FD_t digestori, FD_t validationi)
|
|
Richard Phibel |
bd001b |
|
|
Richard Phibel |
bd001b |
zeros = xcalloc(fundamental_block_size, 1);
|
|
Richard Phibel |
bd001b |
|
|
Richard Phibel |
bd001b |
- while (next >= 0) {
|
|
Richard Phibel |
bd001b |
- next = rpmfiNext(fi);
|
|
Richard Phibel |
bd001b |
- if (next == RPMERR_ITER_END) {
|
|
Richard Phibel |
bd001b |
- rc = RPMRC_OK;
|
|
Richard Phibel |
bd001b |
- break;
|
|
Richard Phibel |
bd001b |
+ while (next >= 0) {
|
|
Richard Phibel |
bd001b |
+ next = rpmfiNext(fi);
|
|
Richard Phibel |
bd001b |
+ if (next == RPMERR_ITER_END) {
|
|
Richard Phibel |
bd001b |
+ rc = RPMRC_OK;
|
|
Richard Phibel |
bd001b |
+ break;
|
|
Richard Phibel |
bd001b |
+ }
|
|
Richard Phibel |
bd001b |
+ mode = rpmfiFMode(fi);
|
|
Richard Phibel |
bd001b |
+ if (!S_ISREG(mode) || !rpmfiArchiveHasContent(fi)) {
|
|
Richard Phibel |
bd001b |
+ /* not a regular file, or the archive doesn't contain any content
|
|
Richard Phibel |
bd001b |
+ * for this entry.
|
|
Richard Phibel |
bd001b |
+ */
|
|
Richard Phibel |
bd001b |
+ continue;
|
|
Richard Phibel |
bd001b |
+ }
|
|
Richard Phibel |
bd001b |
+ digest = rpmfiFDigest(fi, NULL, NULL);
|
|
Richard Phibel |
bd001b |
+ if (digestSetGetEntry(ds, digest, NULL)) {
|
|
Richard Phibel |
bd001b |
+ /* This specific digest has already been included, so skip it. */
|
|
Richard Phibel |
bd001b |
+ continue;
|
|
Richard Phibel |
bd001b |
+ }
|
|
Richard Phibel |
bd001b |
+ pad = pad_to(pos, fundamental_block_size);
|
|
Richard Phibel |
bd001b |
+ if (Fwrite(zeros, sizeof(char), pad, fdo) != pad) {
|
|
Richard Phibel |
bd001b |
+ rpmlog(RPMLOG_ERR, _("Unable to write padding\n"));
|
|
Richard Phibel |
bd001b |
+ rc = RPMRC_FAIL;
|
|
Richard Phibel |
bd001b |
+ goto exit;
|
|
Richard Phibel |
bd001b |
+ }
|
|
Richard Phibel |
bd001b |
+ /* round up to next fundamental_block_size */
|
|
Richard Phibel |
bd001b |
+ pos += pad;
|
|
Richard Phibel |
bd001b |
+ digestSetAddEntry(ds, digest);
|
|
Richard Phibel |
bd001b |
+ offsets[offset_ix].digest = digest;
|
|
Richard Phibel |
bd001b |
+ offsets[offset_ix].pos = pos;
|
|
Richard Phibel |
bd001b |
+ offset_ix++;
|
|
Richard Phibel |
bd001b |
+ size = rpmfiFSize(fi);
|
|
Richard Phibel |
bd001b |
+ rc = rpmfiArchiveReadToFile(fi, fdo, 0);
|
|
Richard Phibel |
bd001b |
+ if (rc != RPMRC_OK) {
|
|
Richard Phibel |
bd001b |
+ char *errstr = rpmfileStrerror(rc);
|
|
Richard Phibel |
bd001b |
+ rpmlog(RPMLOG_ERR,
|
|
Richard Phibel |
bd001b |
+ _("rpmfiArchiveReadToFile failed while extracting "
|
|
Richard Phibel |
bd001b |
+ "\"%s\" with RC %d: %s\n"),
|
|
Richard Phibel |
bd001b |
+ rpmfiFN(fi), rc, errstr);
|
|
Richard Phibel |
bd001b |
+ free(errstr);
|
|
Richard Phibel |
bd001b |
+ goto exit;
|
|
Richard Phibel |
bd001b |
+ }
|
|
Richard Phibel |
bd001b |
+ pos += size;
|
|
Richard Phibel |
bd001b |
}
|
|
Richard Phibel |
bd001b |
- mode = rpmfiFMode(fi);
|
|
Richard Phibel |
bd001b |
- if (!S_ISREG(mode) || !rpmfiArchiveHasContent(fi)) {
|
|
Richard Phibel |
bd001b |
- /* not a regular file, or the archive doesn't contain any content
|
|
Richard Phibel |
bd001b |
- * for this entry.
|
|
Richard Phibel |
bd001b |
- */
|
|
Richard Phibel |
bd001b |
- continue;
|
|
Richard Phibel |
bd001b |
+ Fclose(gzdi); /* XXX gzdi == fdi */
|
|
Richard Phibel |
bd001b |
+
|
|
Richard Phibel |
bd001b |
+ qsort(offsets, (size_t) offset_ix, sizeof(struct digestoffset),
|
|
Richard Phibel |
bd001b |
+ digestoffsetCmp);
|
|
Richard Phibel |
bd001b |
+
|
|
Richard Phibel |
bd001b |
+ validation_pos = pos;
|
|
Richard Phibel |
bd001b |
+ ssize_t validation_len = ufdCopy(validationi, fdo);
|
|
Richard Phibel |
bd001b |
+ if (validation_len == -1) {
|
|
Richard Phibel |
bd001b |
+ rpmlog(RPMLOG_ERR, _("validation output ufdCopy failed\n"));
|
|
Richard Phibel |
bd001b |
+ rc = RPMRC_FAIL;
|
|
Richard Phibel |
bd001b |
+ goto exit;
|
|
Richard Phibel |
bd001b |
}
|
|
Richard Phibel |
bd001b |
- digest = rpmfiFDigest(fi, NULL, NULL);
|
|
Richard Phibel |
bd001b |
- if (digestSetGetEntry(ds, digest, NULL)) {
|
|
Richard Phibel |
bd001b |
- /* This specific digest has already been included, so skip it. */
|
|
Richard Phibel |
bd001b |
- continue;
|
|
Richard Phibel |
bd001b |
+
|
|
Richard Phibel |
bd001b |
+ digest_table_pos = validation_pos + validation_len;
|
|
Richard Phibel |
bd001b |
+
|
|
Richard Phibel |
bd001b |
+ len = sizeof(offset_ix);
|
|
Richard Phibel |
bd001b |
+ if (Fwrite(&offset_ix, len, 1, fdo) != len) {
|
|
Richard Phibel |
bd001b |
+ rpmlog(RPMLOG_ERR, _("Unable to write length of table\n"));
|
|
Richard Phibel |
bd001b |
+ rc = RPMRC_FAIL;
|
|
Richard Phibel |
bd001b |
+ goto exit;
|
|
Richard Phibel |
bd001b |
}
|
|
Richard Phibel |
bd001b |
- pad = pad_to(pos, fundamental_block_size);
|
|
Richard Phibel |
bd001b |
- if (Fwrite(zeros, sizeof(char), pad, fdo) != pad) {
|
|
Richard Phibel |
bd001b |
- rpmlog(RPMLOG_ERR, _("Unable to write padding\n"));
|
|
Richard Phibel |
bd001b |
+ len = sizeof(diglen);
|
|
Richard Phibel |
bd001b |
+ if (Fwrite(&diglen, len, 1, fdo) != len) {
|
|
Richard Phibel |
bd001b |
+ rpmlog(RPMLOG_ERR, _("Unable to write length of digest\n"));
|
|
Richard Phibel |
bd001b |
rc = RPMRC_FAIL;
|
|
Richard Phibel |
bd001b |
goto exit;
|
|
Richard Phibel |
bd001b |
}
|
|
Richard Phibel |
bd001b |
- /* round up to next fundamental_block_size */
|
|
Richard Phibel |
bd001b |
- pos += pad;
|
|
Richard Phibel |
bd001b |
- digestSetAddEntry(ds, digest);
|
|
Richard Phibel |
bd001b |
- offsets[offset_ix].digest = digest;
|
|
Richard Phibel |
bd001b |
- offsets[offset_ix].pos = pos;
|
|
Richard Phibel |
bd001b |
- offset_ix++;
|
|
Richard Phibel |
bd001b |
- size = rpmfiFSize(fi);
|
|
Richard Phibel |
bd001b |
- rc = rpmfiArchiveReadToFile(fi, fdo, 0);
|
|
Richard Phibel |
bd001b |
- if (rc != RPMRC_OK) {
|
|
Richard Phibel |
bd001b |
- char *errstr = rpmfileStrerror(rc);
|
|
Richard Phibel |
bd001b |
- rpmlog(RPMLOG_ERR,
|
|
Richard Phibel |
bd001b |
- _("rpmfiArchiveReadToFile failed while extracting "\
|
|
Richard Phibel |
bd001b |
- "\"%s\" with RC %d: %s\n"),
|
|
Richard Phibel |
bd001b |
- rpmfiFN(fi), rc, errstr);
|
|
Richard Phibel |
bd001b |
- free(errstr);
|
|
Richard Phibel |
bd001b |
+ len = sizeof(rpm_loff_t);
|
|
Richard Phibel |
bd001b |
+ for (int x = 0; x < offset_ix; x++) {
|
|
Richard Phibel |
bd001b |
+ if (Fwrite(offsets[x].digest, diglen, 1, fdo) != diglen) {
|
|
Richard Phibel |
bd001b |
+ rpmlog(RPMLOG_ERR, _("Unable to write digest\n"));
|
|
Richard Phibel |
bd001b |
+ rc = RPMRC_FAIL;
|
|
Richard Phibel |
bd001b |
+ goto exit;
|
|
Richard Phibel |
bd001b |
+ }
|
|
Richard Phibel |
bd001b |
+ if (Fwrite(&offsets[x].pos, len, 1, fdo) != len) {
|
|
Richard Phibel |
bd001b |
+ rpmlog(RPMLOG_ERR, _("Unable to write offset\n"));
|
|
Richard Phibel |
bd001b |
+ rc = RPMRC_FAIL;
|
|
Richard Phibel |
bd001b |
+ goto exit;
|
|
Richard Phibel |
bd001b |
+ }
|
|
Richard Phibel |
bd001b |
+ }
|
|
Richard Phibel |
bd001b |
+ digest_pos =
|
|
Richard Phibel |
bd001b |
+ (digest_table_pos + sizeof(offset_ix) + sizeof(diglen) +
|
|
Richard Phibel |
bd001b |
+ offset_ix * (diglen + sizeof(rpm_loff_t))
|
|
Richard Phibel |
bd001b |
+ );
|
|
Richard Phibel |
bd001b |
+
|
|
Richard Phibel |
bd001b |
+ ssize_t digest_len = ufdCopy(digestori, fdo);
|
|
Richard Phibel |
bd001b |
+ if (digest_len == -1) {
|
|
Richard Phibel |
bd001b |
+ rpmlog(RPMLOG_ERR, _("digest table ufdCopy failed\n"));
|
|
Richard Phibel |
bd001b |
+ rc = RPMRC_FAIL;
|
|
Richard Phibel |
bd001b |
goto exit;
|
|
Richard Phibel |
bd001b |
}
|
|
Richard Phibel |
bd001b |
- pos += size;
|
|
Richard Phibel |
bd001b |
- }
|
|
Richard Phibel |
bd001b |
- Fclose(gzdi); /* XXX gzdi == fdi */
|
|
Richard Phibel |
bd001b |
-
|
|
Richard Phibel |
bd001b |
- qsort(offsets, (size_t) offset_ix, sizeof(struct digestoffset),
|
|
Richard Phibel |
bd001b |
- digestoffsetCmp);
|
|
Richard Phibel |
bd001b |
|
|
Richard Phibel |
bd001b |
- validation_pos = pos;
|
|
Richard Phibel |
bd001b |
- ssize_t validation_len = ufdCopy(validationi, fdo);
|
|
Richard Phibel |
bd001b |
- if (validation_len == -1) {
|
|
Richard Phibel |
bd001b |
- rpmlog(RPMLOG_ERR, _("validation output ufdCopy failed\n"));
|
|
Richard Phibel |
bd001b |
- rc = RPMRC_FAIL;
|
|
Richard Phibel |
bd001b |
- goto exit;
|
|
Richard Phibel |
bd001b |
- }
|
|
Richard Phibel |
bd001b |
-
|
|
Richard Phibel |
bd001b |
- digest_table_pos = validation_pos + validation_len;
|
|
Richard Phibel |
bd001b |
+ /* add more padding so the last file can be cloned. It doesn't matter that
|
|
Richard Phibel |
bd001b |
+ * the table and validation etc are in this space. In fact, it's pretty
|
|
Richard Phibel |
bd001b |
+ * efficient if it is.
|
|
Richard Phibel |
bd001b |
+ */
|
|
Richard Phibel |
bd001b |
|
|
Richard Phibel |
bd001b |
- len = sizeof(offset_ix);
|
|
Richard Phibel |
bd001b |
- if (Fwrite(&offset_ix, len, 1, fdo) != len) {
|
|
Richard Phibel |
bd001b |
- rpmlog(RPMLOG_ERR, _("Unable to write length of table\n"));
|
|
Richard Phibel |
bd001b |
- rc = RPMRC_FAIL;
|
|
Richard Phibel |
bd001b |
- goto exit;
|
|
Richard Phibel |
bd001b |
- }
|
|
Richard Phibel |
bd001b |
- len = sizeof(diglen);
|
|
Richard Phibel |
bd001b |
- if (Fwrite(&diglen, len, 1, fdo) != len) {
|
|
Richard Phibel |
bd001b |
- rpmlog(RPMLOG_ERR, _("Unable to write length of digest\n"));
|
|
Richard Phibel |
bd001b |
- rc = RPMRC_FAIL;
|
|
Richard Phibel |
bd001b |
- goto exit;
|
|
Richard Phibel |
bd001b |
- }
|
|
Richard Phibel |
bd001b |
- len = sizeof(rpm_loff_t);
|
|
Richard Phibel |
bd001b |
- for (int x = 0; x < offset_ix; x++) {
|
|
Richard Phibel |
bd001b |
- if (Fwrite(offsets[x].digest, diglen, 1, fdo) != diglen) {
|
|
Richard Phibel |
bd001b |
- rpmlog(RPMLOG_ERR, _("Unable to write digest\n"));
|
|
Richard Phibel |
bd001b |
+ pad =
|
|
Richard Phibel |
bd001b |
+ pad_to((validation_pos + validation_len +
|
|
Richard Phibel |
bd001b |
+ 2 * sizeof(rpm_loff_t) + sizeof(uint64_t)),
|
|
Richard Phibel |
bd001b |
+ fundamental_block_size);
|
|
Richard Phibel |
bd001b |
+ if (Fwrite(zeros, sizeof(char), pad, fdo) != pad) {
|
|
Richard Phibel |
bd001b |
+ rpmlog(RPMLOG_ERR, _("Unable to write final padding\n"));
|
|
Richard Phibel |
bd001b |
rc = RPMRC_FAIL;
|
|
Richard Phibel |
bd001b |
goto exit;
|
|
Richard Phibel |
bd001b |
}
|
|
Richard Phibel |
bd001b |
- if (Fwrite(&offsets[x].pos, len, 1, fdo) != len) {
|
|
Richard Phibel |
bd001b |
- rpmlog(RPMLOG_ERR, _("Unable to write offset\n"));
|
|
Richard Phibel |
bd001b |
+ zeros = _free(zeros);
|
|
Richard Phibel |
bd001b |
+ struct extents_footer_t footer = {.offsets =
|
|
Richard Phibel |
bd001b |
+ { validation_pos, digest_table_pos, digest_pos },.magic =
|
|
Richard Phibel |
bd001b |
+ EXTENTS_MAGIC };
|
|
Richard Phibel |
bd001b |
+ len = sizeof(footer);
|
|
Richard Phibel |
bd001b |
+ if (Fwrite(&footer, len, 1, fdo) != len) {
|
|
Richard Phibel |
bd001b |
+ rpmlog(RPMLOG_ERR, _("Unable to write footer\n"));
|
|
Richard Phibel |
bd001b |
rc = RPMRC_FAIL;
|
|
Richard Phibel |
bd001b |
goto exit;
|
|
Richard Phibel |
bd001b |
}
|
|
Richard Phibel |
bd001b |
}
|
|
Richard Phibel |
bd001b |
- digest_pos = (
|
|
Richard Phibel |
bd001b |
- digest_table_pos + sizeof(offset_ix) + sizeof(diglen) +
|
|
Richard Phibel |
bd001b |
- offset_ix * (diglen + sizeof(rpm_loff_t))
|
|
Richard Phibel |
bd001b |
- );
|
|
Richard Phibel |
bd001b |
-
|
|
Richard Phibel |
bd001b |
- ssize_t digest_len = ufdCopy(digestori, fdo);
|
|
Richard Phibel |
bd001b |
- if (digest_len == -1) {
|
|
Richard Phibel |
bd001b |
- rpmlog(RPMLOG_ERR, _("digest table ufdCopy failed\n"));
|
|
Richard Phibel |
bd001b |
- rc = RPMRC_FAIL;
|
|
Richard Phibel |
bd001b |
- goto exit;
|
|
Richard Phibel |
bd001b |
- }
|
|
Richard Phibel |
bd001b |
-
|
|
Richard Phibel |
bd001b |
- /* add more padding so the last file can be cloned. It doesn't matter that
|
|
Richard Phibel |
bd001b |
- * the table and validation etc are in this space. In fact, it's pretty
|
|
Richard Phibel |
bd001b |
- * efficient if it is.
|
|
Richard Phibel |
bd001b |
- */
|
|
Richard Phibel |
bd001b |
|
|
Richard Phibel |
bd001b |
- pad = pad_to((validation_pos + validation_len + 2 * sizeof(rpm_loff_t) +
|
|
Richard Phibel |
bd001b |
- sizeof(uint64_t)), fundamental_block_size);
|
|
Richard Phibel |
bd001b |
- if (Fwrite(zeros, sizeof(char), pad, fdo) != pad) {
|
|
Richard Phibel |
bd001b |
- rpmlog(RPMLOG_ERR, _("Unable to write final padding\n"));
|
|
Richard Phibel |
bd001b |
- rc = RPMRC_FAIL;
|
|
Richard Phibel |
bd001b |
- goto exit;
|
|
Richard Phibel |
bd001b |
- }
|
|
Richard Phibel |
bd001b |
- zeros = _free(zeros);
|
|
Richard Phibel |
bd001b |
- struct extents_footer_t footer = {.offsets = {validation_pos, digest_table_pos, digest_pos}, .magic = EXTENTS_MAGIC};
|
|
Richard Phibel |
bd001b |
- len = sizeof(footer);
|
|
Richard Phibel |
bd001b |
- if (Fwrite(&footer, len, 1, fdo) != len) {
|
|
Richard Phibel |
bd001b |
- rpmlog(RPMLOG_ERR, _("Unable to write footer\n"));
|
|
Richard Phibel |
bd001b |
- rc = RPMRC_FAIL;
|
|
Richard Phibel |
bd001b |
- goto exit;
|
|
Richard Phibel |
bd001b |
- }
|
|
Richard Phibel |
bd001b |
- }
|
|
Richard Phibel |
bd001b |
-
|
|
Richard Phibel |
bd001b |
-exit:
|
|
Richard Phibel |
bd001b |
+ exit:
|
|
Richard Phibel |
bd001b |
rpmfilesFree(files);
|
|
Richard Phibel |
bd001b |
rpmfiFree(fi);
|
|
Richard Phibel |
bd001b |
headerFree(h);
|