richardphibel / rpms / libdnf

Forked from rpms/libdnf 2 years ago
Clone
fe1899
From 8987652fe1f1dca674a0726e6d967c60ed79e8b6 Mon Sep 17 00:00:00 2001
fe1899
From: Matthew Almond <malmond@fb.com>
fe1899
Date: Mon, 8 Mar 2021 12:57:53 -0800
fe1899
Subject: [PATCH 1/2] Expose librepo's checksum functions via SWIG
fe1899
fe1899
DNF has been carrying around yum's old checksum function. These
fe1899
functions duplicate code in librepo. They are slower because librepo can
fe1899
employ caching of digests. Lastly, these functions in Python do not know
fe1899
about changes in checksum logic like
fe1899
https://github.com/rpm-software-management/librepo/pull/222
fe1899
fe1899
The choices here are:
fe1899
fe1899
1. Replicate `lr_checksum_cow_fd()` and caching logic in Python
fe1899
2. Just use librepo from dnf.
fe1899
fe1899
This is 2. Note there was bug in librepo that forces no caching
fe1899
for `checksum_value()`
fe1899
(https://github.com/rpm-software-management/librepo/issues/233). This is
fe1899
now fixed, so we depend on librepo-1.13.1 to ensure this fix is present.
fe1899
fe1899
This change goes hand in hand with a change to `dnf` itself to make use
fe1899
of the new functions and eliminate the old ones. This is
fe1899
https://github.com/rpm-software-management/dnf/pull/1743. We bump the
fe1899
version of this library in the next commit to ensure this dependency is
fe1899
expressed properly.
fe1899
fe1899
On errors, these functions raise libdnf.error.Error which can be easily
fe1899
mapped into MiscError in dnf
fe1899
---
fe1899
 bindings/swig/utils.i  |  3 +++
fe1899
 libdnf/utils/utils.cpp | 50 ++++++++++++++++++++++++++++++++++++++++++
fe1899
 libdnf/utils/utils.hpp | 16 ++++++++++++++
fe1899
 3 files changed, 69 insertions(+)
fe1899
fe1899
diff --git a/bindings/swig/utils.i b/bindings/swig/utils.i
fe1899
index 60fabb02d..df323e375 100644
fe1899
--- a/bindings/swig/utils.i
fe1899
+++ b/bindings/swig/utils.i
fe1899
@@ -44,4 +44,7 @@ namespace libdnf { namespace filesystem {
fe1899
 
fe1899
 void decompress(const char * inPath, const char * outPath, mode_t outMode, const char * compressType = nullptr);
fe1899
 
fe1899
+bool checksum_check(const char * type, const char * inPath, const char * checksum_valid);
fe1899
+std::string checksum_value(const char * type, const char * inPath);
fe1899
+
fe1899
 }}
fe1899
diff --git a/libdnf/utils/utils.cpp b/libdnf/utils/utils.cpp
fe1899
index 1a83bfbd2..450718d37 100644
fe1899
--- a/libdnf/utils/utils.cpp
fe1899
+++ b/libdnf/utils/utils.cpp
fe1899
@@ -1,6 +1,7 @@
fe1899
 #include "utils.hpp"
fe1899
 #include "libdnf/dnf-sack-private.hpp"
fe1899
 #include "libdnf/sack/advisorymodule.hpp"
fe1899
+#include <librepo/librepo.h>
fe1899
 
fe1899
 #include <tinyformat/tinyformat.hpp>
fe1899
 
fe1899
@@ -300,6 +301,55 @@ void decompress(const char * inPath, const char * outPath, mode_t outMode, const
fe1899
     fclose(inFile);
fe1899
 }
fe1899
 
fe1899
+void checksum(const char * type, const char * inPath, const char * checksum_valid, bool * valid_out, gchar ** calculated_out)
fe1899
+{
fe1899
+    GError * errP{nullptr};
fe1899
+    gboolean valid;
fe1899
+    LrChecksumType lr_type = lr_checksum_type(type);
fe1899
+
fe1899
+    if (lr_type == LR_CHECKSUM_UNKNOWN)
fe1899
+        throw libdnf::Error(tfm::format("Unknown checksum type %s", type));
fe1899
+
fe1899
+    auto inFd = open(inPath, O_RDONLY);
fe1899
+
fe1899
+    if (inFd == -1)
fe1899
+        throw libdnf::Error(tfm::format("Error opening %s: %s", inPath, strerror(errno)));
fe1899
+
fe1899
+    auto ret = lr_checksum_fd_compare(lr_type,
fe1899
+                      inFd,
fe1899
+                      /**
fe1899
+                       * If checksum_valid references a string, pass it in, else use
fe1899
+                       * an empty string
fe1899
+                       */
fe1899
+                      checksum_valid ? checksum_valid : "",
fe1899
+                      TRUE,
fe1899
+                      &valid,
fe1899
+                      calculated_out,
fe1899
+                      &errP);
fe1899
+
fe1899
+    close(inFd);
fe1899
+    if (!ret)
fe1899
+      throw libdnf::Error(tfm::format("Error calculating checksum %s: (%d, %s)", inPath, errP->code, errP->message));
fe1899
+    if (valid_out)
fe1899
+        *valid_out = valid == TRUE; /* gboolean -> bool */
fe1899
+}
fe1899
+
fe1899
+
fe1899
+bool checksum_check(const char * type, const char * inPath, const char * checksum_valid)
fe1899
+{
fe1899
+    bool valid;
fe1899
+    checksum(type, inPath, checksum_valid, &valid, NULL);
fe1899
+    return valid;
fe1899
+}
fe1899
+
fe1899
+std::string checksum_value(const char * type, const char * inPath)
fe1899
+{
fe1899
+    g_autofree gchar *calculated = NULL;
fe1899
+    checksum(type, inPath, NULL, NULL, &calculated);
fe1899
+    std::string out(calculated);
fe1899
+    return out;
fe1899
+}
fe1899
+
fe1899
 }
fe1899
 
fe1899
 namespace numeric {
fe1899
diff --git a/libdnf/utils/utils.hpp b/libdnf/utils/utils.hpp
fe1899
index 5d755e017..43ca9ff34 100644
fe1899
--- a/libdnf/utils/utils.hpp
fe1899
+++ b/libdnf/utils/utils.hpp
fe1899
@@ -68,6 +68,22 @@ std::vector<std::string> getDirContent(const std::string &dirPath);
fe1899
 * @param compressType Type of compression (".bz2", ".gz", ...), nullptr - detect from inPath filename. Defaults to nullptr.
fe1899
 */
fe1899
 void decompress(const char * inPath, const char * outPath, mode_t outMode, const char * compressType = nullptr);
fe1899
+
fe1899
+/**
fe1899
+* @brief checksum file and return if matching.
fe1899
+*
fe1899
+* @param type Checksum type ("sha", "sha1", "sha256" etc). Raises libdnf::Error if invalid.
fe1899
+* @param inPath Path to input file
fe1899
+* @param valid_checksum hexadecimal encoded checksum string.
fe1899
+*/
fe1899
+bool checksum_check(const char * type, const char * inPath, const char * valid_checksum);
fe1899
+/**
fe1899
+* @brief checksum file and return checksum.
fe1899
+*
fe1899
+* @param type Checksum type ("sha", "sha1", "sha256" etc). Raises libdnf::Error if invalid.
fe1899
+* @param inPath Path to input file
fe1899
+*/
fe1899
+std::string checksum_value(const char * type, const char * inPath);
fe1899
 }
fe1899
 
fe1899
 namespace numeric {
fe1899