From 8061564a7efa990840251b0fe9b55490d3896f26 Mon Sep 17 00:00:00 2001 From: Matthew Almond Date: Thu, 11 Mar 2021 10:41:23 -0800 Subject: [PATCH] Return "calculated" checksum if requested w/caching If a file is downloaded via librepo (e.g. `dnf install --downloadonly`) then a request to get the checksum via `lr_checksum_fd_compare()` will not work. It'll only return whether the checksum is valid, and not the actual checksum. This is the simple fix. Addresses #233 --- VERSION.cmake | 2 +- librepo.spec | 2 +- librepo/checksum.c | 2 ++ tests/test_checksum.c | 68 +++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 69 insertions(+), 5 deletions(-) diff --git a/VERSION.cmake b/VERSION.cmake index fdda41b3e..634c484eb 100644 --- a/VERSION.cmake +++ b/VERSION.cmake @@ -1,3 +1,3 @@ SET(LIBREPO_MAJOR "1") SET(LIBREPO_MINOR "13") -SET(LIBREPO_PATCH "0") +SET(LIBREPO_PATCH "1") diff --git a/librepo.spec b/librepo.spec index 53ab05323..8be498847 100644 --- a/librepo.spec +++ b/librepo.spec @@ -11,7 +11,7 @@ %global dnf_conflict 2.8.8 Name: librepo -Version: 1.13.0 +Version: 1.13.1 Release: 1%{?dist} Summary: Repodata downloading library diff --git a/librepo/checksum.c b/librepo/checksum.c index 47e594675..db370404c 100644 --- a/librepo/checksum.c +++ b/librepo/checksum.c @@ -248,6 +248,8 @@ lr_checksum_fd_compare(LrChecksumType type, g_debug("%s: Using checksum cached in xattr: [%s] %s", __func__, checksum_key, buf); *matches = (strcmp(expected, buf) == 0); + if (calculated) + *calculated = g_strdup(buf); return TRUE; } } else { diff --git a/tests/test_checksum.c b/tests/test_checksum.c index 06b95e3fc..3bd01e9c2 100644 --- a/tests/test_checksum.c +++ b/tests/test_checksum.c @@ -90,7 +90,7 @@ START_TEST(test_checksum_fd) } END_TEST -START_TEST(test_cached_checksum) +START_TEST(test_cached_checksum_matches) { FILE *f; int fd, ret; @@ -105,7 +105,7 @@ START_TEST(test_cached_checksum) gchar *checksum_key = g_strconcat(XATTR_CHKSUM_PREFIX, "sha256", NULL); gchar *mtime_str = NULL; - filename = lr_pathconcat(test_globals.tmpdir, "/test_checksum", NULL); + filename = lr_pathconcat(test_globals.tmpdir, "/test_checksum_matches", NULL); f = fopen(filename, "w"); fail_if(f == NULL); fwrite("foo\nbar\n", 1, 8, f); @@ -178,6 +178,67 @@ START_TEST(test_cached_checksum) } END_TEST +START_TEST(test_cached_checksum_value) +{ + FILE *f; + int fd, ret; + gboolean checksum_ret, matches; + ssize_t attr_ret; + char *filename; + static char *expected = "d78931fcf2660108eec0d6674ecb4e02401b5256a6b5ee82527766ef6d198c67"; + struct stat st; + char buf[256]; + GError *tmp_err = NULL; + gchar *timestamp_key = g_strconcat(XATTR_CHKSUM_PREFIX, "mtime", NULL); + gchar *checksum_key = g_strconcat(XATTR_CHKSUM_PREFIX, "sha256", NULL); + gchar *mtime_str = NULL; + gchar *calculated = NULL; + + filename = lr_pathconcat(test_globals.tmpdir, "/test_checksum_value", NULL); + f = fopen(filename, "w"); + fail_if(f == NULL); + fwrite("foo\nbar\n", 1, 8, f); + fclose(f); + + // Assert no cached checksum exists + attr_ret = GETXATTR(filename, timestamp_key, &buf, sizeof(buf)-1); + fail_if(attr_ret != -1); // Cached timestamp should not exists + attr_ret = GETXATTR(filename, checksum_key, &buf, sizeof(buf)-1); + fail_if(attr_ret != -1); // Cached checksum should not exists + + // Calculate checksum + fd = open(filename, O_RDONLY); + fail_if(fd < 0); + checksum_ret = lr_checksum_fd_compare(LR_CHECKSUM_SHA256, + fd, + "", + 1, + &matches, + &calculated, + &tmp_err); + fail_if(tmp_err); + fail_if(!checksum_ret); + // We pass in an empty string for expected, so we must not match. + fail_if(matches); + close(fd); + fail_if(strcmp(calculated, expected)); + + // Assert no cached checksum exists + // This assumes issue #235 is unresolved. Once it is, this code + // should fail and the test will need updated. + attr_ret = GETXATTR(filename, timestamp_key, &buf, sizeof(buf)-1); + fail_if(attr_ret != -1); // Cached timestamp should not exists + attr_ret = GETXATTR(filename, checksum_key, &buf, sizeof(buf)-1); + fail_if(attr_ret != -1); // Cached checksum should not exists + + lr_free(calculated); + lr_free(filename); + lr_free(timestamp_key); + lr_free(checksum_key); + lr_free(mtime_str); +} +END_TEST + START_TEST(test_cached_checksum_clear) { FILE *f; @@ -242,7 +303,8 @@ checksum_suite(void) Suite *s = suite_create("checksum"); TCase *tc = tcase_create("Main"); tcase_add_test(tc, test_checksum_fd); - tcase_add_test(tc, test_cached_checksum); + tcase_add_test(tc, test_cached_checksum_matches); + tcase_add_test(tc, test_cached_checksum_value); tcase_add_test(tc, test_cached_checksum_clear); suite_add_tcase(s, tc); return s;