]> git.ipfire.org Git - pakfire.git/commitdiff
packager: Write filelist of payload in mtree format
authorMichael Tremer <michael.tremer@ipfire.org>
Fri, 21 May 2021 18:51:21 +0000 (18:51 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Fri, 21 May 2021 18:54:25 +0000 (18:54 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/packager.c

index 976abe48bf585d34e65544ff561693e9039c9958..ac25f08283a6c42273e3c0cfd40110b56ba2747e 100644 (file)
@@ -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);