From 494504dbeced77ae755cc67646213a62a8b34167 Mon Sep 17 00:00:00 2001 From: Juan RP Date: Sat, 28 Nov 2009 02:38:41 +0100 Subject: [PATCH] Added support for a cachedir to store downloaded binpkgs. libxbps: * Added xbps_set_cachedir() and xbps_get_cachedir(). By default it's set to /var/cache/xbps if not specified and it's always relative to the root directory. * Move mkpath() code from sync_remote_pkgidc.c into its own file mkpath.c to use it in another parts of the code. * Added xbps_get_binpkg_local_path(), that returns the local path to a binary package file, stored in cachedir or local repo. * Remote pkg index files are now stored directly in metadir/repodir, skipping the arch directory because binpkgs are now in cachedir. xbps-bin: * Added -c flag to set the cachedir. * Check sha256 hashes in the download stage so that it can check a downloaded binpkg immediately once is stored. * If a binpkg doesn't match the hash it will be refetched. Bump XBPS_RELVER to 20091128. --HG-- extra : convert_revision : xtraeme%40gmail.com-20091128013841-kkcvk07lsqdr26w8 --- bin/xbps-bin/install.c | 166 +++++++++++++++--------------------- bin/xbps-bin/main.c | 9 +- bin/xbps-bin/xbps-bin.8.txt | 7 ++ include/xbps_api.h | 16 +++- lib/Makefile | 2 +- lib/mkpath.c | 98 +++++++++++++++++++++ lib/sync_remote_pkgidx.c | 163 +++-------------------------------- lib/unpack.c | 17 +--- lib/util.c | 67 +++++++++++++-- 9 files changed, 270 insertions(+), 275 deletions(-) create mode 100644 lib/mkpath.c diff --git a/bin/xbps-bin/install.c b/bin/xbps-bin/install.c index a213c490..66ea558f 100644 --- a/bin/xbps-bin/install.c +++ b/bin/xbps-bin/install.c @@ -72,68 +72,45 @@ show_missing_dep_cb(prop_object_t obj, void *arg, bool *loop_done) return EINVAL; } -static int -check_pkg_hashes(prop_object_iterator_t iter) +static bool +check_binpkg_hash(const char *path, const char *filename, + const char *sha256) { - prop_object_t obj; - const char *pkgname, *repoloc, *filename; int rv = 0; - pkg_state_t state = 0; - printf("Checking binary package file(s) integrity...\n"); - while ((obj = prop_object_iterator_next(iter)) != NULL) { - if (!prop_dictionary_get_cstring_nocopy(obj, - "pkgname", &pkgname)) - return errno; - - state = 0; - if (xbps_get_pkg_state_dictionary(obj, &state) != 0) - return EINVAL; - - if (state == XBPS_PKG_STATE_UNPACKED) - continue; - - if (!prop_dictionary_get_cstring_nocopy(obj, - "repository", &repoloc)) - return errno; - if (!prop_dictionary_get_cstring_nocopy(obj, - "filename", &filename)) - return errno; - rv = xbps_check_pkg_file_hash(obj, repoloc); - if (rv != 0 && rv != ERANGE) { - printf("Unexpected error while checking hash for " - "%s (%s)\n", filename, strerror(rv)); - return -1; - } else if (rv != 0 && rv == ERANGE) { - printf("Hash mismatch for %s, exiting.\n", - filename); - return -1; - } + printf("Checking %s integrity... ", filename); + rv = xbps_check_file_hash(path, sha256); + errno = rv; + if (rv != 0 && rv != ERANGE) { + printf("unexpected error: %s\n", strerror(rv)); + return false; + } else if (rv == ERANGE) { + printf("hash mismatch!.\n"); + return false; } - prop_object_iterator_reset(iter); + printf("OK.\n"); - return 0; + return true; } static int download_package_list(prop_object_iterator_t iter) { prop_object_t obj; - const char *pkgver, *repoloc, *filename, *arch; - char *savedir, *binfile, *lbinfile, *repoloc_trans; + const char *pkgver, *repoloc, *filename, *cachedir, *sha256; + char *binfile, *lbinfile; int rv = 0; + bool found_binpkg; + + cachedir = xbps_get_cachedir(); + if (cachedir == NULL) + return EINVAL; - printf("Downloading binary package file(s)...\n"); while ((obj = prop_object_iterator_next(iter)) != NULL) { + found_binpkg = false; if (!prop_dictionary_get_cstring_nocopy(obj, "repository", &repoloc)) return errno; - /* - * Skip packages in local repositories. - */ - if (!xbps_check_is_repo_string_remote(repoloc)) - continue; - if (!prop_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver)) return errno; @@ -141,65 +118,69 @@ download_package_list(prop_object_iterator_t iter) "filename", &filename)) return errno; if (!prop_dictionary_get_cstring_nocopy(obj, - "architecture", &arch)) + "filename-sha256", &sha256)) return errno; - repoloc_trans = xbps_get_remote_repo_string(repoloc); - if (repoloc_trans == NULL) + lbinfile = xbps_get_binpkg_local_path(obj); + if (lbinfile == NULL) return errno; - savedir = xbps_xasprintf("%s/%s/%s/%s", - xbps_get_rootdir(), XBPS_META_PATH, repoloc_trans, arch); - if (savedir == NULL) { - free(repoloc_trans); - return errno; - } - lbinfile = xbps_xasprintf("%s/%s", savedir, filename); - if (lbinfile == NULL) { - free(repoloc_trans); - free(savedir); - return errno; - } - if (access(lbinfile, R_OK) == 0) { - free(savedir); + /* + * If package is in a local repository, check its hash + * and pass no next one. + */ + if (!xbps_check_is_repo_string_remote(repoloc)) { + if (!check_binpkg_hash(lbinfile, filename, sha256)) { + free(lbinfile); + return errno; + } free(lbinfile); - goto change_repodir; + continue; } - free(lbinfile); - - binfile = xbps_xasprintf("%s/%s/%s", repoloc, arch, filename); + /* + * If downloaded package is in cachedir, check its hash + * and restart it again if doesn't match. + */ + if (access(lbinfile, R_OK) == 0) { + if (check_binpkg_hash(lbinfile, filename, sha256)) { + free(lbinfile); + continue; + } + if (errno && errno != ERANGE) { + free(lbinfile); + return errno; + } else if (errno == ERANGE) { + (void)remove(lbinfile); + printf("Refetching %s again...\n", + filename); + errno = 0; + } + } + if (xbps_mkpath(__UNCONST(cachedir), 0755) == -1) { + free(lbinfile); + return errno; + } + binfile = xbps_get_path_from_pkg_dict_repo(obj, repoloc); if (binfile == NULL) { - free(repoloc_trans); - free(savedir); + free(lbinfile); return errno; } printf("Downloading %s binary package ...\n", pkgver); - rv = xbps_fetch_file(binfile, savedir, false, NULL); - free(savedir); + rv = xbps_fetch_file(binfile, cachedir, false, NULL); free(binfile); if (rv == -1) { printf("Couldn't download %s from %s (%s)\n", filename, repoloc, xbps_fetch_error_string()); - free(repoloc_trans); + free(lbinfile); return errno; } - -change_repodir: - /* - * If it was downloaded successfully, override repository - * path in transaction dictionary. - */ - savedir = xbps_xasprintf("%s/%s/%s", - xbps_get_rootdir(), XBPS_META_PATH, repoloc_trans); - free(repoloc_trans); - if (savedir == NULL) - return errno; - - if (!prop_dictionary_set_cstring(obj, "repository", savedir)) { - free(savedir); + if (!check_binpkg_hash(lbinfile, filename, sha256)) { + printf("W: removing wrong %s file ...\n", filename); + (void)remove(lbinfile); + free(lbinfile); return errno; } - free(savedir); + free(lbinfile); } prop_object_iterator_reset(iter); @@ -250,10 +231,6 @@ show_transaction_sizes(prop_object_iterator_t iter) trans_inst = trans_up = trans_conf = false; - /* - * Iterate over the list of packages that are going to be - * installed and check the file hash. - */ while ((obj = prop_object_iterator_next(iter)) != NULL) { if (!prop_dictionary_get_uint64(obj, "filename-size", &tsize)) return errno; @@ -530,17 +507,12 @@ exec_transaction(struct transaction *trans) } /* - * Download binary packages if they are in a remote repository. + * Download binary packages (if they come from a remote repository) + * and check its SHA256 hash. */ if ((rv = download_package_list(trans->iter)) != 0) return rv; - /* - * Check the SHA256 hash for all required packages. - */ - if ((rv = check_pkg_hashes(trans->iter)) != 0) - return rv; - /* * Iterate over the transaction dictionary. */ diff --git a/bin/xbps-bin/main.c b/bin/xbps-bin/main.c index fefe4348..9433535c 100644 --- a/bin/xbps-bin/main.c +++ b/bin/xbps-bin/main.c @@ -58,12 +58,12 @@ usage(void) " show-revdeps\t\n" " update\t\t\n" " Options shared by all targets:\n" + " -c\t\t\n" " -r\t\t\n" " -v\t\tShows verbose messages\n" " -V\t\tPrints the xbps release version\n" " Options used by the (auto)remove and install target:\n" - " -f\t\tForce installation or removal of packages.\n" - " \t\tBeware with this option if you use autoremove!\n" + " -f\t\tBypasses the questions.\n" "\n"); exit(EXIT_FAILURE); } @@ -116,8 +116,11 @@ main(int argc, char **argv) force = verbose = false; - while ((c = getopt(argc, argv, "CVfr:v")) != -1) { + while ((c = getopt(argc, argv, "Vcfr:v")) != -1) { switch (c) { + case 'c': + xbps_set_cachedir(optarg); + break; case 'f': flags |= XBPS_FLAG_FORCE; force = true; diff --git a/bin/xbps-bin/xbps-bin.8.txt b/bin/xbps-bin/xbps-bin.8.txt index afbf798f..9ef6742d 100644 --- a/bin/xbps-bin/xbps-bin.8.txt +++ b/bin/xbps-bin/xbps-bin.8.txt @@ -23,6 +23,13 @@ be installed from local ('directory') or remote repositories ('http', OPTIONS ------- +*-c* 'cachedir':: + Sets the 'cache' directory to store downloaded binary packages + from remote repositories. + By default it's set to '/var/cache/xbps' and it's always relative + to the 'root' directory. So if you use a 'rootdir' of '/blah', + it will become '/blah/cachedir'. + *-f*:: By default while installing or removing packages, xbps-bin(1) will ask you if you are sure about the task that will be done. diff --git a/include/xbps_api.h b/include/xbps_api.h index 27e6c040..08d4acff 100644 --- a/include/xbps_api.h +++ b/include/xbps_api.h @@ -30,7 +30,9 @@ #include #include #include -#define NDEBUG +#ifndef DEBUG +# define NDEBUG +#endif #include #include @@ -38,11 +40,14 @@ #include /* Current release version */ -#define XBPS_RELVER "20091126" +#define XBPS_RELVER "20091128" /* Default root PATH for xbps to store metadata info. */ #define XBPS_META_PATH "/var/db/xbps" +/* Default cache PATH for xbps to store downloaded binpkgs. */ +#define XBPS_CACHE_PATH "/var/cache/xbps" + /* Filename for the repositories plist file. */ #define XBPS_REPOLIST "repositories.plist" @@ -59,7 +64,6 @@ /* Current version of the package index format. */ #define XBPS_PKGINDEX_VERSION "1.1" -/* Verbose messages */ #define XBPS_FLAG_VERBOSE 0x00000001 #define XBPS_FLAG_FORCE 0x00000002 @@ -119,6 +123,9 @@ prop_dictionary_t SYMEXPORT xbps_get_pkg_props(void); /* From lib/depends.c */ int SYMEXPORT xbps_find_deps_in_pkg(prop_dictionary_t, prop_dictionary_t); +/* From lib/mkpath.c */ +int SYMEXPORT xbps_mkpath(char *, mode_t); + /* From lib/orphans.c */ prop_array_t SYMEXPORT xbps_find_orphan_packages(void); @@ -233,6 +240,7 @@ int SYMEXPORT xbps_check_pkg_file_hash(prop_dictionary_t, int SYMEXPORT xbps_check_is_installed_pkg(const char *); bool SYMEXPORT xbps_check_is_installed_pkgname(const char *); bool SYMEXPORT xbps_check_is_repo_string_remote(const char *); +char SYMEXPORT *xbps_get_binpkg_local_path(prop_dictionary_t); char SYMEXPORT *xbps_get_pkg_index_plist(const char *); char SYMEXPORT *xbps_get_pkg_name(const char *); char SYMEXPORT *xbps_get_pkgdep_name(const char *); @@ -243,6 +251,8 @@ const char SYMEXPORT *xbps_get_pkgver_from_dict(prop_dictionary_t); bool SYMEXPORT xbps_pkg_has_rundeps(prop_dictionary_t); void SYMEXPORT xbps_set_rootdir(const char *); const char SYMEXPORT *xbps_get_rootdir(void); +void SYMEXPORT xbps_set_cachedir(const char *); +const char SYMEXPORT *xbps_get_cachedir(void); void SYMEXPORT xbps_set_flags(int); int SYMEXPORT xbps_get_flags(void); bool SYMEXPORT xbps_yesno(const char *, ...); diff --git a/lib/Makefile b/lib/Makefile index 9b92b6c0..6c6e28c2 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -17,7 +17,7 @@ LIBFETCH_OBJS = fetch/common.o fetch/fetch.o fetch/file.o fetch/ftp.o fetch/http OBJS += configure.o cmpver.o depends.o download.o fexec.o findpkg.o OBJS += humanize_number.o orphans.o plist.o purge.o register.o remove.o OBJS += repository.o requiredby.o sha256.o sortdeps.o state.o -OBJS += sync_remote_pkgidx.o unpack.o util.o pkgmatch.o +OBJS += sync_remote_pkgidx.o unpack.o util.o pkgmatch.o mkpath.o OBJS += regpkgs_dictionary.o repository_plist.o repository_pool.o .PHONY: all diff --git a/lib/mkpath.c b/lib/mkpath.c new file mode 100644 index 00000000..5774447a --- /dev/null +++ b/lib/mkpath.c @@ -0,0 +1,98 @@ +/* + * Copyright (c) 1983, 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * The following is a modified function from NetBSD's src/bin/mkdir/mkdir.c + */ +#include +#include +#include +#include +#include + +#include +/* + * mkpath -- create directories. + * path - path + * mode - file mode of terminal directory + */ +int +xbps_mkpath(char *path, mode_t mode) +{ + struct stat sb; + char *slash = path; + int done = 0, rv; + mode_t dir_mode; + + /* + * The default file mode is a=rwx (0777) with selected permissions + * removed in accordance with the file mode creation mask. For + * intermediate path name components, the mode is the default modified + * by u+wx so that the subdirectories can always be created. + */ + if (mode == 0) + mode = (S_IRWXU | S_IRWXG | S_IRWXO) & ~umask(0); + + dir_mode = mode | S_IWUSR | S_IXUSR; + + for (;;) { + slash += strspn(slash, "/"); + slash += strcspn(slash, "/"); + + done = (*slash == '\0'); + *slash = '\0'; + + rv = mkdir(path, done ? mode : dir_mode); + if (rv < 0) { + /* + * Can't create; path exists or no perms. + * stat() path to determine what's there now. + */ + int sverrno; + + sverrno = errno; + if (stat(path, &sb) < 0) { + /* Not there; use mkdir()s error */ + errno = sverrno; + return -1; + } + if (!S_ISDIR(sb.st_mode)) { + /* Is there, but isn't a directory */ + errno = ENOTDIR; + return -1; + } + } + if (done) + break; + + *slash = '/'; + } + + return 0; +} diff --git a/lib/sync_remote_pkgidx.c b/lib/sync_remote_pkgidx.c index 16bd0367..08fd18f4 100644 --- a/lib/sync_remote_pkgidx.c +++ b/lib/sync_remote_pkgidx.c @@ -32,8 +32,6 @@ #include #include "fetch.h" -static int mkpath(char *, mode_t); - char SYMEXPORT * xbps_get_remote_repo_string(const char *uri) { @@ -79,12 +77,12 @@ xbps_sync_repository_pkg_index(const char *uri) struct utsname un; struct stat st; const char *fetch_outputdir; - char *rpidx, *dir, *lrepodir, *uri_fixedp; + char *rpidx, *lrepodir, *uri_fixedp; char *metadir, *tmp_metafile, *lrepofile; int rv = 0; bool only_sync = false; - rpidx = dir = lrepodir = uri_fixedp = NULL; + rpidx = lrepodir = uri_fixedp = NULL; metadir = tmp_metafile = lrepofile = NULL; if (uname(&un) == -1) @@ -100,7 +98,7 @@ xbps_sync_repository_pkg_index(const char *uri) } /* - * Create metadir if it doesn't exist yet. + * Create metadir if necessary. */ metadir = xbps_xasprintf("%s/%s", xbps_get_rootdir(), XBPS_META_PATH); @@ -108,17 +106,8 @@ xbps_sync_repository_pkg_index(const char *uri) rv = -1; goto out; } - rv = stat(metadir, &st); - if (rv == -1 && errno == ENOENT) { - if (mkpath(metadir, 0755) == -1) { - rv = -1; - goto out; - } - } else if (rv == 0 && !S_ISDIR(st.st_mode)) { - errno = ENOTDIR; - rv = -1; + if ((rv = xbps_mkpath(metadir, 0755)) == -1) goto out; - } /* * Remote repository pkg-index.plist full URL. @@ -140,8 +129,8 @@ xbps_sync_repository_pkg_index(const char *uri) /* * Full path to machine arch local repository directory. */ - lrepodir = xbps_xasprintf("%s/%s/%s/%s", - xbps_get_rootdir(), XBPS_META_PATH, uri_fixedp, un.machine); + lrepodir = xbps_xasprintf("%s/%s/%s", + xbps_get_rootdir(), XBPS_META_PATH, uri_fixedp); if (lrepodir == NULL) { rv = -1; goto out; @@ -168,52 +157,17 @@ xbps_sync_repository_pkg_index(const char *uri) if (only_sync) goto out; - /* - * Create local arch repodir: - * - * /var/db/xbps/repo// - */ - rv = stat(lrepodir, &st); - if (rv == -1 && errno == ENOENT) { - if (mkpath(lrepodir, 0755) == -1) { - rv = -1; - goto out; - } - } else if (rv == 0 && !S_ISDIR(st.st_mode)) { - errno = ENOTDIR; - rv = -1; - goto out; - } - /* - * Create local noarch repodir: - * - * /var/db/xbps/repo//noarch - */ - dir = xbps_xasprintf("%s/%s/%s/noarch", - xbps_get_rootdir(), XBPS_META_PATH, uri_fixedp); - if (dir == NULL) { - rv = -1; - goto out; - } - rv = stat(dir, &st); - if (rv == -1 && errno == ENOENT) { - if (mkpath(dir, 0755) == -1) { - free(dir); - rv = -1; - goto out; - } - } else if (rv == 0 && !S_ISDIR(st.st_mode)) { - free(dir); - errno = ENOTDIR; - rv = -1; - goto out; - } - free(dir); lrepofile = xbps_xasprintf("%s/%s", lrepodir, XBPS_PKGINDEX); if (lrepofile == NULL) { rv = -1; goto out; } + /* + * Create local repodir to store pkg-index.plist file. + */ + if ((rv = xbps_mkpath(lrepodir, 0755)) == -1) + goto out; + /* * Rename to destination file now it has been fetched successfully. */ @@ -238,96 +192,3 @@ out: return rv; } - -/* - * The following is a modified function from NetBSD's src/bin/mkdir/mkdir.c - */ - -/* - * Copyright (c) 1983, 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/* - * mkpath -- create directories. - * path - path - * mode - file mode of terminal directory - */ -static int -mkpath(char *path, mode_t mode) -{ - struct stat sb; - char *slash = path; - int done = 0, rv; - mode_t dir_mode; - - /* - * The default file mode is a=rwx (0777) with selected permissions - * removed in accordance with the file mode creation mask. For - * intermediate path name components, the mode is the default modified - * by u+wx so that the subdirectories can always be created. - */ - if (mode == 0) - mode = (S_IRWXU | S_IRWXG | S_IRWXO) & ~umask(0); - - dir_mode = mode | S_IWUSR | S_IXUSR; - - for (;;) { - slash += strspn(slash, "/"); - slash += strcspn(slash, "/"); - - done = (*slash == '\0'); - *slash = '\0'; - - rv = mkdir(path, done ? mode : dir_mode); - if (rv < 0) { - /* - * Can't create; path exists or no perms. - * stat() path to determine what's there now. - */ - int sverrno; - - sverrno = errno; - if (stat(path, &sb) < 0) { - /* Not there; use mkdir()s error */ - errno = sverrno; - return -1; - } - if (!S_ISDIR(sb.st_mode)) { - /* Is there, but isn't a directory */ - errno = ENOTDIR; - return -1; - } - } - if (done) - break; - - *slash = '/'; - } - - return 0; -} diff --git a/lib/unpack.c b/lib/unpack.c index d52fa02e..751b25f3 100644 --- a/lib/unpack.c +++ b/lib/unpack.c @@ -39,30 +39,17 @@ static void set_extract_flags(int *); int SYMEXPORT xbps_unpack_binary_pkg(prop_dictionary_t pkg, bool essential) { - prop_string_t filename, repoloc, arch; - struct archive *ar = NULL; const char *pkgname; + struct archive *ar = NULL; char *binfile = NULL; int pkg_fd, rv = 0; assert(pkg != NULL); - /* - * Append filename to the full path for binary pkg. - */ if (!prop_dictionary_get_cstring_nocopy(pkg, "pkgname", &pkgname)) return errno; - filename = prop_dictionary_get(pkg, "filename"); - arch = prop_dictionary_get(pkg, "architecture"); - repoloc = prop_dictionary_get(pkg, "repository"); - if (filename == NULL || arch == NULL || repoloc == NULL) - return ENOTSUP; - - binfile = xbps_xasprintf("%s/%s/%s", - prop_string_cstring_nocopy(repoloc), - prop_string_cstring_nocopy(arch), - prop_string_cstring_nocopy(filename)); + binfile = xbps_get_binpkg_local_path(pkg); if (binfile == NULL) return EINVAL; diff --git a/lib/util.c b/lib/util.c index 12441cb1..0584bc37 100644 --- a/lib/util.c +++ b/lib/util.c @@ -41,6 +41,7 @@ static bool question(bool, const char *, va_list); static const char *rootdir; +static const char *cachedir; static int flags; char SYMEXPORT * @@ -298,7 +299,7 @@ xbps_get_pkgver_from_dict(prop_dictionary_t d) } static char * -get_pkg_index_remote_plist(const char *uri, const char *machine) +get_pkg_index_remote_plist(const char *uri) { char *uri_fixed, *repodir; @@ -306,9 +307,8 @@ get_pkg_index_remote_plist(const char *uri, const char *machine) if (uri_fixed == NULL) return NULL; - repodir = xbps_xasprintf("%s/%s/%s/%s/%s", - xbps_get_rootdir(), XBPS_META_PATH, uri_fixed, - machine, XBPS_PKGINDEX); + repodir = xbps_xasprintf("%s/%s/%s/%s", + xbps_get_rootdir(), XBPS_META_PATH, uri_fixed, XBPS_PKGINDEX); if (repodir == NULL) { free(uri_fixed); return NULL; @@ -328,11 +328,34 @@ xbps_get_pkg_index_plist(const char *uri) return NULL; if (xbps_check_is_repo_string_remote(uri)) - return get_pkg_index_remote_plist(uri, un.machine); + return get_pkg_index_remote_plist(uri); return xbps_xasprintf("%s/%s/%s", uri, un.machine, XBPS_PKGINDEX); } +char SYMEXPORT * +xbps_get_binpkg_local_path(prop_dictionary_t pkg) +{ + const char *repoloc, *filen, *arch, *cdir; + + if (!prop_dictionary_get_cstring_nocopy(pkg, "repository", &repoloc)) + return NULL; + if (!prop_dictionary_get_cstring_nocopy(pkg, "filename", &filen)) + return NULL; + if (!prop_dictionary_get_cstring_nocopy(pkg, "architecture", &arch)) + return NULL; + cdir = xbps_get_cachedir(); + if (cdir == NULL) + return NULL; + + if (!xbps_check_is_repo_string_remote(repoloc)) { + /* local repo */ + return xbps_xasprintf("%s/%s/%s", repoloc, arch, filen); + } + /* cachedir */ + return xbps_xasprintf("%s/%s", cdir, filen); +} + bool SYMEXPORT xbps_pkg_has_rundeps(prop_dictionary_t pkg) { @@ -362,6 +385,40 @@ xbps_get_rootdir(void) return rootdir; } +void SYMEXPORT +xbps_set_cachedir(const char *dir) +{ + static char res[PATH_MAX]; + int r = 0; + + assert(dir != NULL); + + r = snprintf(res, sizeof(res), "%s/%s", xbps_get_rootdir(), dir); + if (r == -1 || r >= (int)sizeof(res)) { + /* If error or truncated set to default */ + cachedir = XBPS_CACHE_PATH; + return; + } + cachedir = res; +} + +const char SYMEXPORT * +xbps_get_cachedir(void) +{ + static char res[PATH_MAX]; + int r = 0; + + if (cachedir == NULL) { + r = snprintf(res, sizeof(res), "%s/%s", + xbps_get_rootdir(), XBPS_CACHE_PATH); + if (r == -1 || r >= (int)sizeof(res)) + return NULL; + + cachedir = res; + } + return cachedir; +} + void SYMEXPORT xbps_set_flags(int lflags) {