]> git.ipfire.org Git - pakfire.git/commitdiff
file: Refactor digests
authorMichael Tremer <michael.tremer@ipfire.org>
Fri, 15 Jul 2022 15:35:50 +0000 (15:35 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Fri, 15 Jul 2022 15:35:50 +0000 (15:35 +0000)
Files can now hold more than one digest type and the interfaces have
been slightly improved.

Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/file.c
src/libpakfire/include/pakfire/file.h

index f5ea7527bdcb8098016981aeb7a7c5e940e3b83b..cf7f38b97cb28b19bcae6c70b057b977fe441f64 100644 (file)
 #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;
@@ -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) {
index 38fec8a6b683497c4112b0b97afa202447d57d0a..bf97ad3b1a2503b15a2fff12c3512a7a9b76c3ec 100644 (file)
@@ -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);