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);
}
// 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",
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;
}
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);
}
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
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;
}
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)
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);
}
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
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;
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
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;
}