Skip to content

Commit 4080355

Browse files
committed
Expose librepo's checksum functions via SWIG
DNF has been carrying around yum's old checksum function. These functions duplicate code in librepo. They are slower because librepo can employ caching of digests. Lastly, these functions in Python do not know about changes in checksum logic like rpm-software-management/librepo#222 The choices here are: 1. Replicate `lr_checksum_cow_fd()` and caching logic in Python 2. Just use librepo from dnf. This is 2. Note there is an open bug in librepo that forces no caching for `checksum_value()` (rpm-software-management/librepo#233). For now we can keep the perf hit - this is no worse than the existing code and aim for more correctness. This change goes hand in hand with a change to `dnf` itself to make use of the new functions and eliminate the old ones. On errors, these functions raise libdnf.error.Error which can be easily mapped into MiscError in dnf
1 parent ddf5adf commit 4080355

File tree

3 files changed

+88
-0
lines changed

3 files changed

+88
-0
lines changed

bindings/swig/utils.i

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,7 @@ namespace libdnf { namespace filesystem {
4444

4545
void decompress(const char * inPath, const char * outPath, mode_t outMode, const char * compressType = nullptr);
4646

47+
bool checksum_check(const char * type, const char * inPath, const char * checksum_valid);
48+
std::string checksum_value(const char * type, const char * inPath);
49+
4750
}}

libdnf/utils/utils.cpp

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "utils.hpp"
22
#include "libdnf/dnf-sack-private.hpp"
33
#include "libdnf/sack/advisorymodule.hpp"
4+
#include <librepo/librepo.h>
45

56
#include <tinyformat/tinyformat.hpp>
67

@@ -311,6 +312,74 @@ void decompress(const char * inPath, const char * outPath, mode_t outMode, const
311312
fclose(inFile);
312313
}
313314

315+
bool checksum_check(const char * type, const char * inPath, const char * checksum_valid)
316+
{
317+
GError * errP{nullptr};
318+
gboolean valid;
319+
LrChecksumType lr_type = lr_checksum_type(type);
320+
321+
if (lr_type == LR_CHECKSUM_UNKNOWN)
322+
throw libdnf::Error(tfm::format("Unknown checksum type %s", type));
323+
324+
auto inFd = open(inPath, O_RDONLY);
325+
326+
if (inFd == -1)
327+
throw libdnf::Error(tfm::format("Error opening %s: %s", inPath, strerror(errno)));
328+
329+
auto ret = lr_checksum_fd_cmp(lr_type,
330+
inFd,
331+
checksum_valid,
332+
TRUE, /* use xattr value */
333+
&valid,
334+
&errP);
335+
336+
if (!ret) {
337+
close(inFd);
338+
throw libdnf::Error(tfm::format("Error checking checksum %s: (%d, %s)", inPath, errP->code, errP->message));
339+
}
340+
close(inFd);
341+
// gboolean -> bool
342+
return valid == TRUE;
343+
}
344+
345+
std::string checksum_value(const char * type, const char * inPath)
346+
{
347+
GError * errP{nullptr};
348+
gboolean valid; /* this is thrown away, we're not checking, we're just calculating it */
349+
gchar * calculated = NULL;
350+
LrChecksumType lr_type = lr_checksum_type(type);
351+
352+
if (lr_type == LR_CHECKSUM_UNKNOWN)
353+
throw libdnf::Error(tfm::format("Unknown checksum type %s", type));
354+
355+
auto inFd = open(inPath, O_RDONLY);
356+
357+
if (inFd == -1)
358+
throw libdnf::Error(tfm::format("Error opening %s: %s", inPath, strerror(errno)));
359+
360+
auto ret = lr_checksum_fd_compare(lr_type,
361+
inFd,
362+
"", /* we're calling this to get the file's checksum not compare it */
363+
/**
364+
* https://github.com/rpm-software-management/librepo/issues/233
365+
* We must pass FALSE here because librepo has a simple bug that
366+
* doesn't set calculated if the checksum is cached
367+
*/
368+
FALSE,
369+
&valid,
370+
&calculated,
371+
&errP);
372+
373+
if (!ret) {
374+
close(inFd);
375+
throw libdnf::Error(tfm::format("Error calculating checksum %s: (%d, %s)", inPath, errP->code, errP->message));
376+
}
377+
close(inFd);
378+
std::string out(calculated);
379+
g_free(calculated);
380+
return out;
381+
}
382+
314383
}
315384

316385
namespace numeric {

libdnf/utils/utils.hpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,22 @@ std::vector<std::string> getDirContent(const std::string &dirPath);
6666
* @param compressType Type of compression (".bz2", ".gz", ...), nullptr - detect from inPath filename. Defaults to nullptr.
6767
*/
6868
void decompress(const char * inPath, const char * outPath, mode_t outMode, const char * compressType = nullptr);
69+
70+
/**
71+
* @brief checksum file and return if matching.
72+
*
73+
* @param type Checksum type ("sha", "sha1", "sha256" etc). Raises libdnf::Error if invalid.
74+
* @param inPath Path to input file
75+
* @param valid_checksum hexadecimal encoded checksum string.
76+
*/
77+
bool checksum_check(const char * type, const char * inPath, const char * valid_checksum);
78+
/**
79+
* @brief checksum file and return checksum.
80+
*
81+
* @param type Checksum type ("sha", "sha1", "sha256" etc). Raises libdnf::Error if invalid.
82+
* @param inPath Path to input file
83+
*/
84+
std::string checksum_value(const char * type, const char * inPath);
6985
}
7086

7187
namespace numeric {

0 commit comments

Comments
 (0)