return pakfire_parser_get(archive->parser, namespace, key);
}
-static int archive_copy_data(Pakfire pakfire, struct archive* in, struct archive* out) {
- int r;
- const void* buff;
+static int archive_copy_data(Pakfire pakfire, struct archive* in, struct archive* out,
+ char** hexdigest) {
+ EVP_MD_CTX* mdctx = EVP_MD_CTX_new();
+
+ // Initialize digest
+ int r = EVP_DigestInit_ex(mdctx, EVP_blake2s256(), NULL);
+ if (r != 1) {
+ ERROR(pakfire, "Could not setup digest function: %s\n",
+ ERR_error_string(ERR_get_error(), NULL));
+ r = 1;
+ goto ERROR;
+ }
+ const void* buffer;
size_t size;
off_t offset;
for (;;) {
- r = archive_read_data_block(in, &buff, &size, &offset);
+ // Read a block of data
+ r = archive_read_data_block(in, &buffer, &size, &offset);
if (r == ARCHIVE_EOF)
break;
if (r != ARCHIVE_OK) {
ERROR(pakfire, "Could not read data from archive: %s\n",
archive_error_string(in));
+ goto ERROR;
+ }
- return r;
+ // Update digest
+ r = EVP_DigestUpdate(mdctx, buffer, size);
+ if (r != 1) {
+ ERROR(pakfire, "EVP_DigestUpdate failed: %s\n",
+ ERR_error_string(ERR_get_error(), NULL));
+ r = 1;
+ goto ERROR;
}
- r = archive_write_data_block(out, buff, size, offset);
+ // Write the data
+ r = archive_write_data_block(out, buffer, size, offset);
if (r != ARCHIVE_OK) {
ERROR(pakfire, "Could not write data to disk: %s\n",
archive_error_string(out));
-
- return r;
+ goto ERROR;
}
}
- return 0;
+ char digest[EVP_MAX_MD_SIZE];
+ size_t digest_length;
+
+ // Finalize the digest
+ r = EVP_DigestFinal_ex(mdctx, (unsigned char*)digest, (unsigned int*)&digest_length);
+ if (r != 1) {
+ ERROR(pakfire, "%s\n", ERR_error_string(ERR_get_error(), NULL));
+ goto ERROR;
+ }
+
+ // Convert to hex
+ *hexdigest = pakfire_hexlify(digest, digest_length);
+
+ DEBUG(pakfire, "Computed digest of %zu bytes: %s\n", digest_length, *hexdigest);
+
+ // Success
+ r = 0;
+
+ERROR:
+ if (mdctx)
+ EVP_MD_CTX_free(mdctx);
+
+ return r;
}
static int archive_extract(Pakfire pakfire, struct archive* a, const char* prefix) {
free(h);
}
+ char* hexdigest = NULL;
+
// Create file
r = archive_write_header(ext, entry);
if (r != ARCHIVE_OK) {
// Copy payload
if (size > 0) {
- r = archive_copy_data(pakfire, a, ext);
+ r = archive_copy_data(pakfire, a, ext, &hexdigest);
if (r != ARCHIVE_OK)
break;
}
break;
}
+ if (hexdigest)
+ free(hexdigest);
+
if (r != ARCHIVE_OK)
break;
}