From: Michael Tremer Date: Sat, 22 May 2021 12:32:17 +0000 (+0000) Subject: packager: Write checksums in mtree format X-Git-Tag: 0.9.28~1285^2~100 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=265a797499d9af9427f48a013de1d355b0cb0f98;p=pakfire.git packager: Write checksums in mtree format Signed-off-by: Michael Tremer --- diff --git a/src/libpakfire/packager.c b/src/libpakfire/packager.c index fcc730e6c..948aa360b 100644 --- a/src/libpakfire/packager.c +++ b/src/libpakfire/packager.c @@ -61,9 +61,77 @@ struct pakfire_packager { size_t installsize; }; +static int pakfire_packager_create_mtree(Pakfire pakfire, struct archive** mtree, + FILE** f, const char** fields) { + char path[] = "/tmp/.pakfire-mtree.XXXXXX"; + int r; + + // Create an mtree + *mtree = archive_write_new(); + if (!*mtree) { + ERROR(pakfire, "archive_write_new() failed\n"); + goto ERROR; + } + + // Use mtree format + r = archive_write_set_format_mtree(*mtree); + if (r) { + ERROR(pakfire, "Could not set format to mtree: %s\n", + archive_error_string(*mtree)); + goto ERROR; + } + + // Always compress using Zstd + r = archive_write_add_filter_zstd(*mtree); + if (r) { + ERROR(pakfire, "Could not enable Zstandard compression: %s\n", + archive_error_string(*mtree)); + goto ERROR; + } + + // Enable mtree fields + if (fields) { + for (const char** field = fields; *field; field++) { + r = archive_write_set_options(*mtree, *field); + if (r) { + ERROR(pakfire, "Could not set mtree options %s: %s\n", + *field, archive_error_string(*mtree)); + goto ERROR; + } + } + } + + // Create a new temporary file + *f = pakfire_mktemp(path); + if (!*f) + goto ERROR; + + // Unlink the file straight away + unlink(path); + + // Write mtree to file + r = archive_write_open_FILE(*mtree, *f); + if (r) + goto ERROR; + + return 0; + +ERROR: + if (*mtree) { + archive_write_free(*mtree); + *mtree = NULL; + } + + if (*f) { + fclose(*f); + *f = NULL; + } + + return 1; +} + static int pakfire_packager_create_payload(struct pakfire_packager* p) { - char payload_path[] = "/tmp/.pakfire-payload.XXXXXX"; - char mtree_path[] = "/tmp/.pakfire-mtree.XXXXXX"; + char path[] = "/tmp/.pakfire-payload.XXXXXX"; // Do not compress source packages const int compress = !pakfire_package_is_source(p->pkg); @@ -108,41 +176,18 @@ static int pakfire_packager_create_payload(struct pakfire_packager* p) { } // Create a new temporary file - p->fpayload = pakfire_mktemp(payload_path); + p->fpayload = pakfire_mktemp(path); if (!p->fpayload) return 1; // Unlink the file straight away - unlink(payload_path); + unlink(path); // Write archive to file r = archive_write_open_FILE(p->payload, p->fpayload); if (r) return r; - // Create an mtree - p->mtree = archive_write_new(); - if (!p->mtree) { - ERROR(p->pakfire, "archive_write_new() failed\n"); - return 1; - } - - // Use mtree format - r = archive_write_set_format_mtree(p->mtree); - if (r) { - ERROR(p->pakfire, "Could not set format to mtree: %s\n", - archive_error_string(p->mtree)); - return r; - } - - // Always compress using Zstd - r = archive_write_add_filter_zstd(p->mtree); - if (r) { - ERROR(p->pakfire, "Could not enable Zstandard compression: %s\n", - archive_error_string(p->mtree)); - return r; - } - static const char* mtree_fields[] = { // Disable the default "!all", @@ -165,28 +210,12 @@ static int pakfire_packager_create_payload(struct pakfire_packager* p) { NULL, }; - // Enable mtree fields - for (const char** field = mtree_fields; *field; field++) { - r = archive_write_set_options(p->mtree, *field); - if (r) { - ERROR(p->pakfire, "Could not set mtree options %s: %s\n", - *field, archive_error_string(p->mtree)); - return r; - } - } - - // Create a new temporary file - p->fmtree = pakfire_mktemp(mtree_path); - if (!p->fmtree) - return 1; - - // Unlink the file straight away - unlink(mtree_path); - - // Write mtree to file - r = archive_write_open_FILE(p->mtree, p->fmtree); - if (r) + // Create an mtree + r = pakfire_packager_create_mtree(p->pakfire, &p->mtree, &p->fmtree, mtree_fields); + if (r) { + ERROR(p->pakfire, "Could not create mtree\n"); return r; + } return 0; } @@ -278,6 +307,8 @@ static int pakfire_packager_copy_data(struct pakfire_packager* packager, struct archive* a, FILE* f) { char buffer[BUFFER_SIZE]; + rewind(f); + while (!feof(f)) { // Read a block from file size_t bytes_read = fread(buffer, 1, sizeof(buffer), f); @@ -333,7 +364,7 @@ static struct archive_entry* pakfire_packager_create_file( } static int pakfire_packager_write_file_from_buffer(struct pakfire_packager* packager, - struct archive* a, const char* filename, const char* buffer) { + struct archive* a, struct archive* mtree, const char* filename, const char* buffer) { size_t size = strlen(buffer); // Create a new file @@ -345,28 +376,40 @@ static int pakfire_packager_write_file_from_buffer(struct pakfire_packager* pack int r = archive_write_header(a, entry); if (r) { ERROR(packager->pakfire, "Error writing header: %s\n", archive_error_string(a)); - archive_entry_free(entry); - return r; + goto ERROR; } // Write content r = archive_write_data(a, buffer, strlen(buffer)); if (r < 0) { ERROR(packager->pakfire, "Error writing data: %s\n", archive_error_string(a)); - archive_entry_free(entry); - return r; + goto ERROR; + } + + // Add this file to the mtree + if (mtree) { + r = archive_write_header(mtree, entry); + if (r) { + ERROR(packager->pakfire, "Error adding file to mtree: %s\n", + archive_error_string(mtree)); + goto ERROR; + } } + // Success + r = 0; + +ERROR: archive_entry_free(entry); - return 0; + return r; } static int pakfire_packager_write_format(struct pakfire_packager* packager, struct archive* a) { const char buffer[] = TO_STRING(PACKAGE_FORMAT) "\n"; - int r = pakfire_packager_write_file_from_buffer(packager, a, + int r = pakfire_packager_write_file_from_buffer(packager, a, NULL, PAKFIRE_ARCHIVE_FN_FORMAT, buffer); if (r) return r; @@ -578,7 +621,7 @@ ERROR: } static int pakfire_packager_write_metadata(struct pakfire_packager* packager, - struct archive* a) { + struct archive* a, struct archive* mtree) { // Make metadata char* buffer = pakfire_package_make_metadata(packager); if (!buffer) @@ -587,7 +630,7 @@ static int pakfire_packager_write_metadata(struct pakfire_packager* packager, DEBUG(packager->pakfire, "Generated package metadata:\n%s", buffer); // Write buffer - int r = pakfire_packager_write_file_from_buffer(packager, a, + int r = pakfire_packager_write_file_from_buffer(packager, a, mtree, PAKFIRE_ARCHIVE_FN_METADATA, buffer); free(buffer); @@ -596,7 +639,8 @@ static int pakfire_packager_write_metadata(struct pakfire_packager* packager, } static int pakfire_packager_write_archive(struct pakfire_packager* packager, - struct archive* a, const char* filename, struct archive** payload, FILE* f) { + struct archive* a, struct archive* mtree, const char* filename, + struct archive** payload, FILE* f) { struct stat st; // Close the payload @@ -635,6 +679,23 @@ static int pakfire_packager_write_archive(struct pakfire_packager* packager, if (r) goto ERROR; + // Add this file to the mtree + if (mtree) { + r = archive_write_header(mtree, entry); + if (r) { + ERROR(packager->pakfire, "Error adding file to mtree: %s\n", + archive_error_string(mtree)); + goto ERROR; + } + + r = pakfire_packager_copy_data(packager, mtree, f); + if (r) { + ERROR(packager->pakfire, "Error copying data to mtree: %s\n", + archive_error_string(mtree)); + goto ERROR; + } + } + // Success r = 0; @@ -650,6 +711,8 @@ ERROR: It will create a new archive and write the package to the given file descriptor. */ PAKFIRE_EXPORT int pakfire_packager_finish(struct pakfire_packager* packager, FILE* f) { + struct archive* mtree = NULL; + FILE* fmtree = NULL; int r = 1; // Store total instal size @@ -678,34 +741,88 @@ PAKFIRE_EXPORT int pakfire_packager_finish(struct pakfire_packager* packager, FI goto ERROR; } + static const char* mtree_fields[] = { + // Disable everything + "!all", + + // Include the file size + "size", + + // Add the checksums + "sha512", + "sha256", + + NULL, + }; + + // Create an mtree for the checksums + r = pakfire_packager_create_mtree(packager->pakfire, &mtree, &fmtree, mtree_fields); + if (r) { + ERROR(packager->pakfire, "Could not create mtree\n"); + goto ERROR; + } + // Start with the format file r = pakfire_packager_write_format(packager, a); - if (r) + if (r) { + ERROR(packager->pakfire, "Could not add format file to archive: %s\n", + archive_error_string(a)); goto ERROR; + } // Write the metadata - r = pakfire_packager_write_metadata(packager, a); - if (r) + r = pakfire_packager_write_metadata(packager, a, mtree); + if (r) { + ERROR(packager->pakfire, "Could not add metadata file to archive: %s\n", + archive_error_string(a)); goto ERROR; + } // Write the filelist in mtree format - r = pakfire_packager_write_archive(packager, a, PAKFIRE_ARCHIVE_FN_FILELIST, + r = pakfire_packager_write_archive(packager, a, mtree, PAKFIRE_ARCHIVE_FN_FILELIST, &packager->mtree, packager->fmtree); - if (r) + if (r) { + ERROR(packager->pakfire, "Could not add filelist to archive: %s\n", + archive_error_string(a)); goto ERROR; + } // Write the payload - r = pakfire_packager_write_archive(packager, a, PAKFIRE_ARCHIVE_FN_PAYLOAD, + r = pakfire_packager_write_archive(packager, a, mtree, PAKFIRE_ARCHIVE_FN_PAYLOAD, &packager->payload, packager->fpayload); - if (r) + if (r) { + ERROR(packager->pakfire, "Could not add payload to archive: %s\n", + archive_error_string(a)); goto ERROR; + } + + // Finish checksums + r = archive_write_finish_entry(mtree); + if (r) { + ERROR(packager->pakfire, "Could not finish mtree: %s\n", + archive_error_string(mtree)); + goto ERROR; + } + + // Write the payload + r = pakfire_packager_write_archive(packager, a, NULL, PAKFIRE_ARCHIVE_FN_CHECKSUMS, + &mtree, fmtree); + if (r) { + ERROR(packager->pakfire, "Could not add checksums to archive: %s\n", + archive_error_string(a)); + goto ERROR; + } // Success r = 0; ERROR: if (a) - archive_free(a); + archive_write_free(a); + if (mtree) + archive_write_free(mtree); + if (fmtree) + fclose(fmtree); return r; }