#include <pakfire/private.h>
#include <pakfire/util.h>
+#define MAX_DIGESTS 4
+
+struct pakfire_file_digest {
+ enum pakfire_digests type;
+ unsigned char digest[EVP_MAX_MD_SIZE];
+ size_t length;
+
+ // Add a buffer to store the hex representation
+ char* hexdigest;
+};
+
struct pakfire_file {
struct pakfire* pakfire;
int nrefs;
time_t ctime;
time_t mtime;
- // Digest
- enum pakfire_digests digest_type;
- unsigned char digest[EVP_MAX_MD_SIZE];
- char* hexdigest;
+ // Digests
+ struct pakfire_file_digest digests[MAX_DIGESTS];
#warning TODO capabilities, config, data
// capabilities
type->pakfire; type++) {
const unsigned char* digest = archive_entry_digest(entry, type->libarchive);
if (digest) {
- r = pakfire_file_set_digest(file, type->pakfire, digest);
+ size_t length = pakfire_digest_length(type->pakfire);
+
+ r = pakfire_file_set_digest(file, type->pakfire, digest, length);
if (r)
return r;
-
- break;
}
}
}
static void pakfire_file_free(struct pakfire_file* file) {
- if (file->hexdigest)
- free(file->hexdigest);
+ struct pakfire_file_digest* digest = NULL;
+
+ // Free any generated hexdigests
+ for (unsigned int i = 0; i < MAX_DIGESTS; i++) {
+ digest = &file->digests[i];
+
+ if (digest->hexdigest)
+ free(digest->hexdigest);
+ }
pakfire_unref(file->pakfire);
free(file);
file->mtime = time;
}
-PAKFIRE_EXPORT const unsigned char* pakfire_file_get_digest(
- struct pakfire_file* file, enum pakfire_digests* type) {
- *type = file->digest_type;
+static struct pakfire_file_digest* pakfire_file_find_digest(
+ struct pakfire_file* file, enum pakfire_digests type) {
+ struct pakfire_file_digest* digest = NULL;
- if (file->digest_type)
- return file->digest;
+ for (unsigned int i = 0; i < MAX_DIGESTS; i++) {
+ digest = &file->digests[i];
+ if (digest->type == type)
+ return digest;
+ }
+
+ // No match
return NULL;
}
+PAKFIRE_EXPORT const unsigned char* pakfire_file_get_digest(
+ struct pakfire_file* file, enum pakfire_digests type, size_t* length) {
+ const struct pakfire_file_digest* digest = pakfire_file_find_digest(file, type);
+ if (!digest)
+ return NULL;
+
+ // Export length
+ if (length)
+ *length = digest->length;
+
+ return digest->digest;
+}
+
PAKFIRE_EXPORT const char* pakfire_file_get_hexdigest(
- struct pakfire_file* file, enum pakfire_digests* type) {
- *type = file->digest_type;
+ struct pakfire_file* file, enum pakfire_digests type) {
+ struct pakfire_file_digest* digest = pakfire_file_find_digest(file, type);
+ if (!digest)
+ return NULL;
- if (!file->hexdigest) {
- const size_t digest_length = pakfire_digest_length(file->digest_type);
- if (!digest_length)
+ // Generate the hexdigest if non exists
+ if (!digest->hexdigest) {
+ const size_t length = pakfire_digest_length(digest->type);
+ if (!length)
return NULL;
- file->hexdigest = __pakfire_hexlify(file->digest, digest_length);
+ digest->hexdigest = __pakfire_hexlify(digest->digest, length);
}
- return file->hexdigest;
+ return digest->hexdigest;
}
PAKFIRE_EXPORT int pakfire_file_set_digest(struct pakfire_file* file,
- enum pakfire_digests type, const unsigned char* digest) {
- if (!digest) {
+ enum pakfire_digests type, const unsigned char* digest, size_t length) {
+ if (!digest || !length) {
errno = EINVAL;
return 1;
}
- // How long would the digest be?
- const size_t digest_length = pakfire_digest_length(type);
- if (!digest_length) {
- errno = EINVAL;
+ // Find any existing digests of this type
+ struct pakfire_file_digest* d = pakfire_file_find_digest(file, type);
+
+ // If there is no digest, we will try finding a new one
+ if (!d)
+ d = pakfire_file_find_digest(file, PAKFIRE_DIGEST_NONE);
+
+ // If we could not find a free spot, we probably run out of space
+ if (!d || length > sizeof(d->digest)) {
+ errno = ENOBUFS;
return 1;
}
- // Store type
- file->digest_type = type;
+ // Store type & length
+ d->type = type;
+ d->length = length;
// Store digest
- memcpy(file->digest, digest, digest_length);
+ memcpy(d->digest, digest, d->length);
return 0;
}
// Convert from hex to binary
__pakfire_unhexlify(digest, digest_length, hexdigest);
- return pakfire_file_set_digest(file, type, digest);
+ return pakfire_file_set_digest(file, type, digest, digest_length);
}
static int pakfire_file_levels(struct pakfire_file* file) {
void pakfire_file_set_mtime(struct pakfire_file* file, time_t time);
const unsigned char* pakfire_file_get_digest(
- struct pakfire_file* file, enum pakfire_digests* type);
+ struct pakfire_file* file, enum pakfire_digests type, size_t* length);
const char* pakfire_file_get_hexdigest(
- struct pakfire_file* file, enum pakfire_digests* type);
+ struct pakfire_file* file, enum pakfire_digests type);
int pakfire_file_set_digest(struct pakfire_file* file,
- enum pakfire_digests type, const unsigned char* digest);
+ enum pakfire_digests type, const unsigned char* digest, size_t length);
int pakfire_file_set_hexdigest(struct pakfire_file* file,
enum pakfire_digests type, const char* hexdigest);