]> git.ipfire.org Git - pakfire.git/commitdiff
file: Store any digests as an extended attribute
authorMichael Tremer <michael.tremer@ipfire.org>
Wed, 24 Aug 2022 08:23:19 +0000 (08:23 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Wed, 24 Aug 2022 08:23:19 +0000 (08:23 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/db.c
src/libpakfire/file.c
src/libpakfire/include/pakfire/file.h

index f3b096b64a3f25baf006b4fc8a483a690d9495a9..d7c0f842449ddee76b0fbcfc2be9572dce67d3b4 100644 (file)
@@ -2033,17 +2033,8 @@ static int pakfire_db_load_file_digest(struct pakfire_db* db, struct pakfire_fil
        // Length of the stored value
        const size_t length = sqlite3_column_bytes(stmt, field);
 
-       // Check if the digest has the correct length
-       if (pakfire_digest_length(type) != length) {
-               const char* path = pakfire_file_get_path(file);
-
-               ERROR(db->pakfire, "%s: Digest has an incorrect size of %zu byte(s)\n",
-                       path, length);
-               return 1;
-       }
-
        // Store digest
-       return pakfire_file_set_digest(file, type, digest);
+       return pakfire_file_set_digest(file, type, digest, length);
 }
 
 static int pakfire_db_load_file(struct pakfire_db* db, struct pakfire_filelist* filelist,
index b4cea79a7aa09c0517b8d000ea874ccec0018c64..a46e0a38054c6c1458aa1bee6cc632002f897950 100644 (file)
@@ -92,6 +92,20 @@ struct pakfire_file {
        //int is_datafile;
 };
 
+/*
+       Returns one if the digest is not all zeros.
+*/
+#define pakfire_file_has_digest(digest) __pakfire_file_has_digest(digest, sizeof(digest))
+
+static int __pakfire_file_has_digest(const unsigned char* digest, const size_t length) {
+       for (unsigned int i = 0; i < length; i++) {
+               if (digest[i])
+                       return 1;
+       }
+
+       return 0;
+}
+
 PAKFIRE_EXPORT int pakfire_file_create(struct pakfire_file** file, struct pakfire* pakfire) {
        struct pakfire_file* f = calloc(1, sizeof(*f));
        if (!f)
@@ -127,16 +141,10 @@ ERROR:
        return r;
 }
 
-static const struct pakfire_libarchive_digest {
-       enum pakfire_digests pakfire;
-       int libarchive;
-} pakfire_libarchive_digests[] = {
-       { PAKFIRE_DIGEST_SHA512, ARCHIVE_ENTRY_DIGEST_SHA512 },
-       { PAKFIRE_DIGEST_SHA256, ARCHIVE_ENTRY_DIGEST_SHA256 },
-       { 0, 0 },
-};
-
 int pakfire_file_copy_archive_entry(struct pakfire_file* file, struct archive_entry* entry) {
+       const char* attr = NULL;
+       const void* value = NULL;
+       size_t size = 0;
        int r = 0;
 
        // Set abspath
@@ -176,17 +184,26 @@ int pakfire_file_copy_archive_entry(struct pakfire_file* file, struct archive_en
        pakfire_file_set_ctime(file, archive_entry_ctime(entry));
        pakfire_file_set_mtime(file, archive_entry_mtime(entry));
 
-       // Copy digest
-       for (const struct pakfire_libarchive_digest* type = pakfire_libarchive_digests;
-                       type->pakfire; type++) {
-               const unsigned char* digest = archive_entry_digest(entry, type->libarchive);
-               if (digest) {
-                       r = pakfire_file_set_digest(file, type->pakfire, digest);
+       // Read any extended attributes
+       while (archive_entry_xattr_next(entry, &attr, &value, &size) == ARCHIVE_OK) {
+               // Digest: SHA-512
+               if (strcmp(attr, "PAKFIRE.digests.sha512") == 0) {
+                       r = pakfire_file_set_digest(file, PAKFIRE_DIGEST_SHA512, value, size);
+                       if (r)
+                               goto ERROR;
+
+               // Digest: SHA-256
+               } else if (strcmp(attr, "PAKFIRE.digests.sha256") == 0) {
+                       r = pakfire_file_set_digest(file, PAKFIRE_DIGEST_SHA256, value, size);
                        if (r)
-                               return r;
+                               goto ERROR;
+
+               } else {
+                       DEBUG(file->pakfire, "Received an unknown extended attribute: %s\n", attr);
                }
        }
 
+ERROR:
        return r;
 }
 
@@ -225,7 +242,17 @@ struct archive_entry* pakfire_file_archive_entry(struct pakfire_file* file) {
        archive_entry_set_ctime(entry, pakfire_file_get_ctime(file), 0);
        archive_entry_set_mtime(entry, pakfire_file_get_mtime(file), 0);
 
-       // XXX copy digest
+       // Copy digests
+
+       // SHA-512
+       if (pakfire_file_has_digest(file->digests.sha512))
+               archive_entry_xattr_add_entry(entry, "PAKFIRE.digests.sha512",
+                       file->digests.sha512, sizeof(file->digests.sha512));
+
+       // SHA-256
+       if (pakfire_file_has_digest(file->digests.sha256))
+               archive_entry_xattr_add_entry(entry, "PAKFIRE.digests.sha256",
+                       file->digests.sha256, sizeof(file->digests.sha256));
 
        return entry;
 }
@@ -398,20 +425,6 @@ PAKFIRE_EXPORT void pakfire_file_set_mtime(struct pakfire_file* file, time_t tim
        file->st.st_mtime = time;
 }
 
-/*
-       Returns one if the digest is not all zeros.
-*/
-#define pakfire_file_has_digest(digest) __pakfire_file_has_digest(digest, sizeof(digest))
-
-static int __pakfire_file_has_digest(const unsigned char* digest, const size_t length) {
-       for (unsigned int i = 0; i < length; i++) {
-               if (digest[i])
-                       return 1;
-       }
-
-       return 0;
-}
-
 PAKFIRE_EXPORT const unsigned char* pakfire_file_get_digest(
                struct pakfire_file* file, const enum pakfire_digests type, size_t* length) {
 
@@ -439,12 +452,20 @@ PAKFIRE_EXPORT const unsigned char* pakfire_file_get_digest(
 }
 
 PAKFIRE_EXPORT int pakfire_file_set_digest(struct pakfire_file* file,
-               const enum pakfire_digests type, const unsigned char* digest) {
+               const enum pakfire_digests type, const unsigned char* digest, const size_t length) {
        if (!digest) {
                errno = EINVAL;
                return 1;
        }
 
+       // Check buffer length
+       if (pakfire_digest_length(type) != length) {
+               ERROR(file->pakfire, "Digest has an incorrect length of %zu byte(s)\n", length);
+               errno = ENOMSG;
+               return 1;
+       }
+
+       // Store the digest
        switch (type) {
                case PAKFIRE_DIGEST_SHA512:
                        memcpy(file->digests.sha512, digest, sizeof(file->digests.sha512));
index 6ea3250bb7cf22fefdbc82b2a077e05ff7f7d955..1df7d3727b39b30b2980ae0f9cf6d84269476c5a 100644 (file)
@@ -74,7 +74,7 @@ const unsigned char* pakfire_file_get_digest(struct pakfire_file* file,
 char* pakfire_file_get_hexdigest(struct pakfire_file* file,
        const enum pakfire_digests type);
 int pakfire_file_set_digest(struct pakfire_file* file,
-       const enum pakfire_digests type, const unsigned char* digest);
+       const enum pakfire_digests type, const unsigned char* digest, const size_t length);
 
 struct pakfire_file* pakfire_file_parse_from_file(const char* list, unsigned int format);