From: Michael Tremer Date: Fri, 21 May 2021 18:51:21 +0000 (+0000) Subject: packager: Write filelist of payload in mtree format X-Git-Tag: 0.9.28~1285^2~107 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4eab50792305f5b1e64fb08bfdcf44828bdff585;p=pakfire.git packager: Write filelist of payload in mtree format Signed-off-by: Michael Tremer --- diff --git a/src/libpakfire/packager.c b/src/libpakfire/packager.c index 976abe48b..ac25f0828 100644 --- a/src/libpakfire/packager.c +++ b/src/libpakfire/packager.c @@ -59,10 +59,13 @@ struct pakfire_packager { // Payload struct archive* payload; FILE* fpayload; + struct archive* mtree; + FILE* fmtree; }; static int pakfire_packager_create_payload(struct pakfire_packager* p) { - char path[] = "/tmp/.pakfire-payload.XXXXXX"; + char payload_path[] = "/tmp/.pakfire-payload.XXXXXX"; + char mtree_path[] = "/tmp/.pakfire-mtree.XXXXXX"; // Do not compress source packages const int compress = !pakfire_package_is_source(p->pkg); @@ -107,28 +110,104 @@ static int pakfire_packager_create_payload(struct pakfire_packager* p) { } // Create a new temporary file - p->fpayload = pakfire_mktemp(path); + p->fpayload = pakfire_mktemp(payload_path); if (!p->fpayload) return 1; // Unlink the file straight away - unlink(path); + unlink(payload_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", + + // Enable standard file fields + "device", + "gname", + "link", + "mode", + "nlink", + "size", + "time", + "type", + "uname", + + // Enable cryptographic checksums + "sha512", + "sha256", + + 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) + return r; + return 0; } static void pakfire_packager_free(struct pakfire_packager* packager) { + // Payload if (packager->payload) archive_write_free(packager->payload); if (packager->fpayload) fclose(packager->fpayload); + // mtree + if (packager->mtree) + archive_write_free(packager->mtree); + + if (packager->fmtree) + fclose(packager->fmtree); + if (packager->reader) archive_read_free(packager->reader); @@ -522,20 +601,20 @@ static int pakfire_packager_write_metadata(struct pakfire_packager* packager, return r; } -static int pakfire_packager_write_payload(struct pakfire_packager* packager, - struct archive* a) { +static int pakfire_packager_write_archive(struct pakfire_packager* packager, + struct archive* a, const char* filename, struct archive** payload, FILE* f) { struct stat st; // Close the payload - if (packager->payload) { - archive_write_free(packager->payload); - packager->payload = NULL; + if (*payload) { + archive_write_free(*payload); + *payload = NULL; } // Reset fd to beginning of the file - rewind(packager->fpayload); + rewind(f); - int fd = fileno(packager->fpayload); + int fd = fileno(f); // Stat the payload file int r = fstat(fd, &st); @@ -546,7 +625,7 @@ static int pakfire_packager_write_payload(struct pakfire_packager* packager, // Create a new file struct archive_entry* entry = pakfire_packager_create_file(packager, - PAKFIRE_ARCHIVE_FN_PAYLOAD, st.st_size); + filename, st.st_size); if (!entry) return 1; @@ -558,7 +637,7 @@ static int pakfire_packager_write_payload(struct pakfire_packager* packager, } // Copy data - r = pakfire_packager_copy_data(packager, a, packager->fpayload); + r = pakfire_packager_copy_data(packager, a, f); if (r) goto ERROR; @@ -616,8 +695,15 @@ PAKFIRE_EXPORT int pakfire_packager_finish(struct pakfire_packager* packager, FI if (r) goto ERROR; + // Write the filelist in mtree format + r = pakfire_packager_write_archive(packager, a, PAKFIRE_ARCHIVE_FN_FILELIST, + &packager->mtree, packager->fmtree); + if (r) + goto ERROR; + // Write the payload - r = pakfire_packager_write_payload(packager, a); + r = pakfire_packager_write_archive(packager, a, PAKFIRE_ARCHIVE_FN_PAYLOAD, + &packager->payload, packager->fpayload); if (r) goto ERROR; @@ -692,6 +778,14 @@ PAKFIRE_EXPORT int pakfire_packager_add(struct pakfire_packager* packager, goto ERROR; } + // Write to mtree + r = archive_write_header(packager->mtree, entry); + if (r) { + ERROR(packager->pakfire, "Adding file to mtree failed: %s\n", + archive_error_string(packager->mtree)); + goto ERROR; + } + // Create a file PakfireFile file; r = pakfire_file_create(&file, packager->pakfire);