// Read chksums
int r = open_archive_and_read(archive, "chksums", &buffer, &length);
- if (r)
+ if (r) {
+ ERROR(archive->pakfire, "Could not read chksums file: %m\n");
goto ERROR;
+ }
// Use the key to sign the buffer
r = pakfire_key_sign(key, buffer, length, signature, signature_length, timestamp);
return r;
}
+/*
+ This function appends a single file to the archive
+
+ Unfortunately libarchive cannot do this, so we have to manually find the end of the
+ archive and write another entry...
+*/
+static int pakfire_archive_append_file(struct pakfire_archive* archive,
+ struct archive_entry* entry, const char* buffer, const size_t length) {
+ off_t offset = 0;
+
+ // Find the end of the archive (exclusing the tar trailer)
+ int r = pakfire_archive_find_end(archive, &offset);
+ if (r)
+ return r;
+
+ // Create a new archive writer
+ struct archive* a = archive_write_new();
+ if (!a) {
+ ERROR(archive->pakfire, "Could not create an archive writer: %m\n");
+ return 1;
+ }
+
+ // Use the PAX format
+ r = archive_write_set_format_pax(a);
+ if (r) {
+ ERROR(archive->pakfire, "Could not set format to PAX: %s\n", archive_error_string(a));
+ goto ERROR;
+ }
+
+ // Seek to the end of the archive
+ r = fseek(archive->f, offset, SEEK_SET);
+ if (r) {
+ ERROR(archive->pakfire, "Could not seek to position %jd in archive: %m\n", offset);
+ return r;
+ }
+
+ // Write archive to f
+ r = archive_write_open_FILE(a, archive->f);
+ if (r) {
+ ERROR(archive->pakfire, "archive_write_open_FILE() failed: %s\n",
+ archive_error_string(a));
+ goto ERROR;
+ }
+
+ // Write the header
+ r = archive_write_header(a, entry);
+ if (r) {
+ ERROR(archive->pakfire, "Error writing file header: %s\n",
+ archive_error_string(a));
+ goto ERROR;
+ }
+
+ // Write the payload
+ ssize_t bytes_written = archive_write_data(a, buffer, length);
+ if (bytes_written < 0) {
+ ERROR(archive->pakfire, "Error writing data: %s\n",
+ archive_error_string(a));
+ goto ERROR;
+ }
+
+ // Finish writing
+ r = archive_write_finish_entry(a);
+ if (r) {
+ ERROR(archive->pakfire, "Could not finish entry: %s\n",
+ archive_error_string(a));
+ goto ERROR;
+ }
+
+ // Success
+ r = 0;
+
+ERROR:
+ archive_write_free(a);
+
+ return r;
+}
+
+static int pakfire_archive_append_signature(struct pakfire_archive* archive,
+ struct pakfire_key* key, const char* signature, size_t length, time_t timestamp) {
+ char path[PATH_MAX];
+ int r;
+
+ // Make filename
+ r = pakfire_string_format(path, "signatures/%s", pakfire_key_get_fingerprint(key));
+ if (r < 0)
+ return 1;
+
+ // Create a new file entry
+ struct archive_entry* entry = archive_entry_new();
+ if (!entry)
+ return 1;
+
+ // Set filename
+ archive_entry_set_pathname(entry, path);
+
+ // This is a regular file
+ archive_entry_set_filetype(entry, AE_IFREG);
+ archive_entry_set_perm(entry, 0444);
+
+ // Set size
+ archive_entry_set_size(entry, length);
+
+ // Set ownership
+ archive_entry_set_uname(entry, "root");
+ archive_entry_set_uid(entry, 0);
+ archive_entry_set_gname(entry, "root");
+ archive_entry_set_gid(entry, 0);
+
+ // Set times
+ archive_entry_set_birthtime(entry, timestamp, 0);
+ archive_entry_set_ctime(entry, timestamp, 0);
+ archive_entry_set_mtime(entry, timestamp, 0);
+ archive_entry_set_atime(entry, timestamp, 0);
+
+ // Write entry
+ r = pakfire_archive_append_file(archive, entry, signature, length);
+ archive_entry_free(entry);
+
+ return r;
+}
+
PAKFIRE_EXPORT int pakfire_archive_sign(struct pakfire_archive* archive, struct pakfire_key* key) {
int r;
if (r)
return r;
- // XXX write signature to archive
+ // Append signature to archive
+ r = pakfire_archive_append_signature(archive, key,
+ signature, signature_length, timestamp);
+ if (r)
+ return r;
return 0;
}