// 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);
}
// 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);
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);
// 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;
}
// Copy data
- r = pakfire_packager_copy_data(packager, a, packager->fpayload);
+ r = pakfire_packager_copy_data(packager, a, f);
if (r)
goto ERROR;
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;
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);