From: Michael Tremer Date: Thu, 30 Jan 2025 17:00:04 +0000 (+0000) Subject: package: Build a unified way to check if a package exists X-Git-Tag: 0.9.30~247 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=17cc8075af95bc671922821333eeca83044ab7c7;p=pakfire.git package: Build a unified way to check if a package exists This performs a quick stat() as well. Signed-off-by: Michael Tremer --- diff --git a/src/pakfire/package.c b/src/pakfire/package.c index 04f771db..c048cec5 100644 --- a/src/pakfire/package.c +++ b/src/pakfire/package.c @@ -1304,6 +1304,111 @@ ERROR: return r; } +static int pakfire_package_is_available_exists(struct pakfire_package* self, const char* path) { + struct stat st = {}; + int r; + + // Stat the path + r = stat(path, &st); + if (r < 0) { + switch (errno) { + // If path does not exist, the package is not available + case ENOENT: + return 0; + + // Fail on any other errors + default: + return -errno; + } + } + + // Check if this is a regular file + switch (st.st_mode & S_IFMT) { + case S_IFREG: + break; + + // If path is of some unknown file type we rather assume it does not exist + default: + return 0; + } + + // Fetch the download size + ssize_t size = pakfire_package_get_num(self, PAKFIRE_PKG_DOWNLOADSIZE, 0); + + // Check if the size matches - this is quite a good test to see if we have the right file + if ((size > 0) && (st.st_size != size)) + return 0; + + // Yes, this seems to be available + return 1; +} + +static int pakfire_package_is_available_local( + struct pakfire_package* self, struct pakfire_repo* repo) { + char path[PATH_MAX]; + int r; + + const char* pkg_path = pakfire_package_get_string(self, PAKFIRE_PKG_PATH); + + // Compose path + r = pakfire_repo_path(repo, path, "%s", pkg_path); + if (r < 0) { + ERROR(self->ctx, "Could not compose package path: %s\n", strerror(-r)); + return r; + } + + // Check if the package actually exists + return pakfire_package_is_available_exists(self, path); +} + +static int pakfire_package_is_available_cache(struct pakfire_package* self) { + // Fetch the path the package should be in the cache + const char* path = pakfire_package_get_string(self, PAKFIRE_PKG_CACHE_PATH); + + // Check if the package actually exists + return pakfire_package_is_available_exists(self, path); +} + +/* + This function checks if the archive is available. + + For local repositories, the path is checked, otherwise we will check the cache. +*/ +int pakfire_package_is_available(struct pakfire_package* self) { + struct pakfire_repo* repo = NULL; + int r; + + // Fetch NEVRA + const char* nevra = pakfire_package_get_string(self, PAKFIRE_PKG_NEVRA); + + // Fetch the repository + repo = pakfire_package_get_repo(self); + if (!repo) { + ERROR(self->ctx, "Could not find repository for %s\n", nevra); + r = -ENOTSUP; + goto ERROR; + } + + // Check local repositories + if (pakfire_repo_is_local(repo)) { + r = pakfire_package_is_available_local(self, repo); + if (r < 0) + goto ERROR; + + // Check remote repositories + } else { + r = pakfire_package_is_available_cache(self); + if (r < 0) + goto ERROR; + } + +ERROR: + if (repo) + pakfire_repo_unref(repo); + + return r; +} + int pakfire_package_is_installed(struct pakfire_package* pkg) { Pool* pool = pakfire_get_solv_pool(pkg->pakfire); Solvable* s = get_solvable(pkg); diff --git a/src/pakfire/package.h b/src/pakfire/package.h index d13b0979..96c499eb 100644 --- a/src/pakfire/package.h +++ b/src/pakfire/package.h @@ -170,6 +170,7 @@ int pakfire_package_supports_build_arch(struct pakfire_package* pkg, const char* char* pakfire_package_join_evr(const char* e, const char* v, const char* r); +int pakfire_package_is_available(struct pakfire_package* self); int pakfire_package_is_installed(struct pakfire_package* pkg); // Filelist