From 1d8a03a7b9121bb2c61e8ec315920c452516afcf Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Tue, 16 Jun 2026 11:37:59 +0200 Subject: [PATCH] Query the modification time with std::filesystem --- backend/job.cpp | 107 ++++++++++--------------------------------- backend/pkgtools.cpp | 2 +- backend/slackpkg.cpp | 4 +- backend/utils.cpp | 76 ++++++++++++------------------ 4 files changed, 56 insertions(+), 133 deletions(-) diff --git a/backend/job.cpp b/backend/job.cpp index 68eda1a..f95b33a 100644 --- a/backend/job.cpp +++ b/backend/job.cpp @@ -21,6 +21,7 @@ module; #include #include #include +#include export module katja.job; @@ -38,21 +39,18 @@ void pk_backend_initialize(GKeyFile *conf) int ret; std::uint8_t i; std::size_t groups_len; - GFile *conf_file; - GFileInfo *file_info; GKeyFile *key_conf; GError *err = nullptr; sqlite3 *db; sqlite3_stmt *stmt; - g_debug("backend: initialize"); curl_global_init(CURL_GLOBAL_DEFAULT); /* Open the database. We will need it to save the time the configuration file was last modified. */ auto path = std::filesystem::path(LOCALSTATEDIR) / "cache" / "katja" / "metadata.db"; if (sqlite3_open(path.c_str(), &db) != SQLITE_OK) { - g_error("%s: %s", path.c_str(), sqlite3_errmsg(db)); + std::cerr << path.native() << ": " << sqlite3_errmsg(db) << std::endl; } /* Read the configuration file */ @@ -61,27 +59,19 @@ void pk_backend_initialize(GKeyFile *conf) g_key_file_load_from_file(key_conf, path.c_str(), G_KEY_FILE_NONE, &err); if (err) { - g_error("%s: %s", path.c_str(), err->message); + std::cerr << path.native() << ": " << err->message << std::endl; g_error_free(err); } - conf_file = g_file_new_for_path(path.c_str()); - if (!(file_info = g_file_query_info(conf_file, - "time::modified-usec", - G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, - nullptr, - &err))) - { - g_error("%s", err->message); - g_error_free(err); - } + std::chrono::time_point file_info = std::filesystem::last_write_time(path); + auto microseconds = std::chrono::duration_cast(file_info.time_since_epoch()); if ((ret = sqlite3_prepare_v2(db, "UPDATE cache_info SET value = ? WHERE key LIKE 'last_modification'", -1, &stmt, nullptr)) == SQLITE_OK) { - ret = sqlite3_bind_int(stmt, 1, g_file_info_get_attribute_uint32(file_info, "time::modified-usec")); + ret = sqlite3_bind_int(stmt, 1, microseconds.count()); if (ret == SQLITE_OK) { ret = sqlite3_step(stmt); @@ -90,15 +80,12 @@ void pk_backend_initialize(GKeyFile *conf) } if ((ret != SQLITE_OK) && (ret != SQLITE_DONE)) { - g_error("%s: %s", path.c_str(), sqlite3_errstr(ret)); + std::cerr << path.native() << ": " << sqlite3_errstr(ret) << std::endl; } else if (!sqlite3_changes(db)) { - g_error("Failed to update database: %s", path.c_str()); + std::cerr << "Failed to update database: " << path.native() << std::endl; } - - g_object_unref(file_info); - g_object_unref(conf_file); sqlite3_close_v2(db); /* Initialize an object for each well-formed repository */ @@ -124,8 +111,6 @@ void pk_backend_initialize(GKeyFile *conf) void pk_backend_destroy() { - g_debug("backend: destroy"); - repos.clear(); curl_global_cleanup(); } @@ -243,8 +228,8 @@ void pk_backend_get_details(JobData *job_data, char **package_ids) { std::optional homepage; std::size_t i; - GRegex *expr; - GMatchInfo *match_info; + std::regex expr; + std::smatch match_info; GError *err = nullptr; sqlite3_stmt *stmt; std::string desc; @@ -271,19 +256,12 @@ void pk_backend_get_details(JobData *job_data, char **package_ids) desc = reinterpret_cast(sqlite3_column_text(stmt, 0)); /* Regular expression for searching a homepage */ - expr = g_regex_new("(?:http|ftp):\\/\\/[[:word:]\\/\\-\\.]+[[:word:]\\/](?=\\.?$)", - (GRegexCompileFlags)(G_REGEX_OPTIMIZE | G_REGEX_DUPNAMES), - (GRegexMatchFlags)(0), - &err); - if (err) + expr = std::regex("(?:http|ftp):\\/\\/[[:word:]\\/\\-\\.]+[[:word:]\\/](?=\\.?$)", + std::regex::optimize); + + if (std::regex_match(std::cbegin(desc), std::cend(desc), match_info, expr)) { - std::cerr << err->message << std::endl; - g_error_free(err); - goto out; - } - if (g_regex_match(expr, desc.c_str(), (GRegexMatchFlags) 0, &match_info)) - { - homepage = g_match_info_fetch(match_info, 0); /* URL */ + homepage = match_info[0]; /* URL */ /* Remove the last sentence with the copied URL */ for (i = desc.size() - 1; i > 0; i--) { @@ -293,9 +271,7 @@ void pk_backend_get_details(JobData *job_data, char **package_ids) break; } } - g_match_info_free(match_info); } - g_regex_unref(expr); /* Ready */ job_data->details(package_ids[0], @@ -531,11 +507,8 @@ void pk_backend_remove_packages(JobData* job_data, const std::vectordb, @@ -552,22 +525,10 @@ void pk_backend_get_updates(JobData *job_data) } /* Read the package metadata directory and comprare all installed packages with ones in the cache */ - pkg_metadata_dir = g_file_new_for_path("/var/log/packages"); - pkg_metadata_enumerator = g_file_enumerate_children(pkg_metadata_dir, "standard::name", - G_FILE_QUERY_INFO_NONE, - nullptr, - &err); - g_object_unref(pkg_metadata_dir); - if (err) + pkg_metadata_dir = std::filesystem::path("/var/log/packages"); + for (const auto& pkg_metadata_file_info : std::filesystem::directory_iterator{ pkg_metadata_dir }) { - std::cerr << "/var/log/packages: " << err->message << std::endl; - g_error_free(err); - goto out; - } - - while ((pkg_metadata_file_info = g_file_enumerator_next_file(pkg_metadata_enumerator, nullptr, nullptr))) - { - pkg_metadata_filename = g_file_info_get_name(pkg_metadata_file_info); + pkg_metadata_filename = pkg_metadata_file_info.path(); std::vector tokens = split_package_name(pkg_metadata_filename).value(); /* Select the package from the database */ @@ -597,10 +558,7 @@ void pk_backend_get_updates(JobData *job_data) sqlite3_clear_bindings(stmt); sqlite3_reset(stmt); - - g_object_unref(pkg_metadata_file_info); } - g_object_unref(pkg_metadata_enumerator); out: sqlite3_finalize(stmt); @@ -644,9 +602,6 @@ void pk_backend_refresh_cache(JobData *job_data, bool force) char *db_err; int ret; std::forward_list file_list; - GFile *db_file = nullptr; - GFileInfo *file_info = nullptr; - GError *err = nullptr; sqlite3_stmt *stmt = nullptr; /* Create temporary directory */ @@ -658,14 +613,8 @@ void pk_backend_refresh_cache(JobData *job_data, bool force) if (!force) { auto path = std::filesystem::path(LOCALSTATEDIR) / "cache" / "katja" / "metadata.db"; - db_file = g_file_new_for_path(path.native().c_str()); - file_info = g_file_query_info(db_file, "time::modified-usec", G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, nullptr, &err); - if (err) - { - std::cerr << path << ": " << err->message; - g_error_free(err); - goto out; - } + std::chrono::time_point file_info = std::filesystem::last_write_time(path); + auto microseconds = std::chrono::duration_cast(file_info.time_since_epoch()); ret = sqlite3_prepare_v2(job_data->db, "SELECT value FROM cache_info WHERE key LIKE 'last_modification'", -1, @@ -676,7 +625,7 @@ void pk_backend_refresh_cache(JobData *job_data, bool force) std::cerr << path << ": " << sqlite3_errstr(ret) << std::endl; goto out; } - if ((std::uint32_t) sqlite3_column_int(stmt, 0) > g_file_info_get_attribute_uint32(file_info, "time::modified-usec")) + if ((std::uint32_t) sqlite3_column_int(stmt, 0) > microseconds.count()) { force = true; } @@ -700,7 +649,7 @@ void pk_backend_refresh_cache(JobData *job_data, bool force) /* Download repository */ for (auto& l : file_list) { - get_file(&job_data->curl, l.first.c_str(), l.second.native().c_str()); + get_file(&job_data->curl, l.first.c_str(), l.second); } /* Refresh cache */ @@ -711,14 +660,6 @@ void pk_backend_refresh_cache(JobData *job_data, bool force) out: sqlite3_finalize(stmt); - if (file_info) - { - g_object_unref(file_info); - } - if (db_file) - { - g_object_unref(db_file); - } std::filesystem::remove_all(tmp_dir_name); } } diff --git a/backend/pkgtools.cpp b/backend/pkgtools.cpp index f6c9b00..e3f7355 100644 --- a/backend/pkgtools.cpp +++ b/backend/pkgtools.cpp @@ -109,7 +109,7 @@ public: + reinterpret_cast(sqlite3_column_text(statement, 1)); ret = std::filesystem::exists(dest_filename) - || get_file(&curl, source_url.c_str(), dest_filename.native().c_str()) == CURLE_OK; + || get_file(&curl, source_url.c_str(), dest_filename) == CURLE_OK; if (curl) { diff --git a/backend/slackpkg.cpp b/backend/slackpkg.cpp index 2f418a8..c240088 100644 --- a/backend/slackpkg.cpp +++ b/backend/slackpkg.cpp @@ -85,7 +85,7 @@ public: source_dest.first = this->mirror + current_priority + "/PACKAGES.TXT"; source_dest.second = tmpl / this->name / "PACKAGES.TXT"; - if (get_file(&curl, source_dest.first.c_str(), nullptr) == CURLE_OK) + if (get_file(&curl, source_dest.first.c_str(), std::nullopt) == CURLE_OK) { file_list.emplace_front(std::move(source_dest)); } @@ -98,7 +98,7 @@ public: source_dest.first = this->mirror + current_priority + "/MANIFEST.bz2"; source_dest.second = tmpl / this->name / (current_priority + "-MANIFEST.bz2"); - if (get_file(&curl, source_dest.first.c_str(), nullptr) == CURLE_OK) + if (get_file(&curl, source_dest.first.c_str(), std::nullopt) == CURLE_OK) { file_list.emplace_front(std::move(source_dest)); } diff --git a/backend/utils.cpp b/backend/utils.cpp index 871fad8..816fcfd 100644 --- a/backend/utils.cpp +++ b/backend/utils.cpp @@ -14,6 +14,8 @@ module; #include #include #include +#include +#include export module katja.utils; @@ -76,12 +78,12 @@ struct DummyJobData final : JobData * * Returns: CURLE_OK (zero) on success, non-zero otherwise. **/ -CURLcode get_file(CURL **curl, const char *source_url, const char *dest) +CURLcode get_file(CURL **curl, const char *source_url, const std::optional& dest) { - const char *dest_dir_name; FILE *fout = nullptr; CURLcode ret; glong response_code; + std::string dest_dir_name; if ((*curl == nullptr) && (!(*curl = curl_easy_init()))) { @@ -91,7 +93,7 @@ CURLcode get_file(CURL **curl, const char *source_url, const char *dest) curl_easy_setopt(*curl, CURLOPT_FOLLOWLOCATION, 1L); curl_easy_setopt(*curl, CURLOPT_URL, source_url); - if (dest == nullptr) + if (!dest.has_value()) { curl_easy_setopt(*curl, CURLOPT_NOBODY, 1L); curl_easy_setopt(*curl, CURLOPT_HEADER, 1L); @@ -105,13 +107,12 @@ CURLcode get_file(CURL **curl, const char *source_url, const char *dest) } else { - if (g_file_test(dest, G_FILE_TEST_IS_DIR)) + dest_dir_name = dest.value().native(); + if (std::filesystem::is_directory(dest.value())) { - dest_dir_name = dest; - dest = g_strconcat(dest_dir_name, g_strrstr(source_url, "/"), nullptr); - g_free(const_cast(dest_dir_name)); + dest_dir_name += strrchr(source_url, '/'); } - if ((fout = fopen(dest, "ab")) == nullptr) + if ((fout = fopen(dest_dir_name.c_str(), "ab")) == nullptr) { return CURLE_WRITE_ERROR; } @@ -132,7 +133,7 @@ CURLcode get_file(CURL **curl, const char *source_url, const char *dest) **/ std::optional> split_package_name(const std::string& pkg_filename) { - char *pkg_full_name; + std::string pkg_full_name; int len = pkg_filename.size(); if (len < 4) @@ -144,28 +145,23 @@ std::optional> split_package_name(const std::string& pk if (pkg_filename[len - 4] == '.') { /* Full name without extension */ - len -= 4; - pkg_full_name = g_strndup(pkg_filename.data(), len); - pkg_tokens[3] = g_strdup(pkg_full_name); + pkg_tokens[3] = pkg_filename; + pkg_full_name = std::string(std::crbegin(pkg_filename) + 4, std::crend(pkg_filename)); /* The last 3 characters should be the file extension */ - pkg_tokens[4] = g_strdup(pkg_filename.data() + len + 1); + pkg_tokens[4] = std::string(std::cbegin(pkg_filename) + len + 1, std::cend(pkg_filename)); } else { - pkg_full_name = g_strdup(pkg_filename.c_str()); + pkg_full_name = std::string(std::crbegin(pkg_filename), std::crend(pkg_filename)); } /* Reverse all of the bytes in the package filename to get the name, version and the architecture */ - g_strreverse (pkg_full_name); - char **reversed_tokens = g_strsplit(pkg_full_name, "-", 4); - pkg_tokens[0] = g_strreverse(reversed_tokens[3]); /* Name */ - pkg_tokens[1] = g_strreverse(reversed_tokens[2]); /* Version */ - pkg_tokens[2] = g_strreverse(reversed_tokens[1]); /* Architecture */ - - g_free(reversed_tokens[0]); /* Build number */ - g_free(reversed_tokens); - g_free(pkg_full_name); + std::vector reversed_tokens; + boost::algorithm::split(reversed_tokens, pkg_full_name, boost::is_any_of("-")); + pkg_tokens[0] = std::string(std::crbegin(reversed_tokens[3]), std::crend(reversed_tokens[3])); /* Name */ + pkg_tokens[1] = std::string(std::crbegin(reversed_tokens[2]), std::crend(reversed_tokens[2])); /* Version */ + pkg_tokens[2] = std::string(std::crbegin(reversed_tokens[1]), std::crend(reversed_tokens[1])); /* Architecture */ return pkg_tokens; } @@ -180,20 +176,18 @@ std::optional> split_package_name(const std::string& pk **/ Info is_installed(const char *pkg_fullname) { - GFileEnumerator *pkg_metadata_enumerator; - GFileInfo *pkg_metadata_file_info; - GFile *pkg_metadata_dir; Info ret = Info::installing; const char *it; std::uint8_t dashes = 0; ptrdiff_t pkg_name; - g_return_val_if_fail(pkg_fullname != nullptr, Info::unknown); + if (pkg_fullname == nullptr) + { + return Info::unknown; + } // We want to find the package name without version for the package we're // looking for. - g_debug("Looking if %s is installed", pkg_fullname); - for (it = pkg_fullname + strlen(pkg_fullname); it != pkg_fullname; --it) { if (*it == '-') @@ -213,29 +207,21 @@ Info is_installed(const char *pkg_fullname) // Read the package metadata directory and comprare all installed packages // with ones in the cache. - pkg_metadata_dir = g_file_new_for_path("/var/log/packages"); - if (!(pkg_metadata_enumerator = g_file_enumerate_children(pkg_metadata_dir, - "standard::name", - G_FILE_QUERY_INFO_NONE, - nullptr, - nullptr))) - { - g_object_unref(pkg_metadata_dir); - return Info::unknown; - } + auto pkg_metadata_dir = std::filesystem::path("/var/log/packages"); - while ((pkg_metadata_file_info = g_file_enumerator_next_file(pkg_metadata_enumerator, nullptr, nullptr))) + for (const auto& pkg_metadata_file_info : std::filesystem::directory_iterator{ pkg_metadata_dir }) { - const char *dir = g_file_info_get_name(pkg_metadata_file_info); + std::string filename = pkg_metadata_file_info.path().native(); + const char *dir = filename.c_str(); dashes = 0; - if (strcmp(dir, pkg_fullname) == 0) + if (dir == pkg_fullname) { ret = Info::installed; } else { - for (it = dir + strlen(dir); it != dir; --it) + for (it = dir + filename.size(); it != dir; --it) { if (*it == '-') { @@ -251,15 +237,11 @@ Info is_installed(const char *pkg_fullname) ret = Info::updating; } } - g_object_unref(pkg_metadata_file_info); - if (ret != Info::installing) /* If installed */ { break; } } - g_object_unref(pkg_metadata_enumerator); - g_object_unref(pkg_metadata_dir); return ret; }