From: Michael Tremer Date: Fri, 15 Jul 2022 15:35:50 +0000 (+0000) Subject: file: Refactor digests X-Git-Tag: 0.9.28~710 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=65131b30c52d4ea6c5659188127c69625944e0d1;p=pakfire.git file: Refactor digests Files can now hold more than one digest type and the interfaces have been slightly improved. Signed-off-by: Michael Tremer --- diff --git a/src/libpakfire/file.c b/src/libpakfire/file.c index f5ea7527b..cf7f38b97 100644 --- a/src/libpakfire/file.c +++ b/src/libpakfire/file.c @@ -36,6 +36,17 @@ #include #include +#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; @@ -52,10 +63,8 @@ struct pakfire_file { 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 @@ -167,11 +176,11 @@ int pakfire_file_copy_archive_entry(struct pakfire_file* file, struct archive_en 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; } } @@ -179,8 +188,15 @@ int pakfire_file_copy_archive_entry(struct pakfire_file* file, struct archive_en } 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); @@ -275,50 +291,78 @@ PAKFIRE_EXPORT void pakfire_file_set_mtime(struct pakfire_file* file, time_t tim 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; } @@ -339,7 +383,7 @@ PAKFIRE_EXPORT int pakfire_file_set_hexdigest(struct pakfire_file* file, // 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) { diff --git a/src/libpakfire/include/pakfire/file.h b/src/libpakfire/include/pakfire/file.h index 38fec8a6b..bf97ad3b1 100644 --- a/src/libpakfire/include/pakfire/file.h +++ b/src/libpakfire/include/pakfire/file.h @@ -59,11 +59,11 @@ time_t pakfire_file_get_mtime(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);