From bbae14f187f70d1d73e60764383ac19e348c7ee3 Mon Sep 17 00:00:00 2001 From: Juan RP Date: Tue, 6 May 2014 12:17:18 +0200 Subject: [PATCH] xbps-remove(8): -O,--clean-cache is now multithreaded. --- NEWS | 3 + bin/xbps-remove/Makefile | 2 +- bin/xbps-remove/clean-cache.c | 142 ++++++++++++++++++++++++++++++++++ bin/xbps-remove/defs.h | 32 ++++++++ bin/xbps-remove/main.c | 92 +--------------------- 5 files changed, 180 insertions(+), 91 deletions(-) create mode 100644 bin/xbps-remove/clean-cache.c create mode 100644 bin/xbps-remove/defs.h diff --git a/NEWS b/NEWS index 77a54c3c..be8b6615 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,8 @@ xbps-0.37 (???): + * xbps-remove(8) -O, --clean-cache is now multithreaded. Gives a performance + boost as the number of threads increases. + * xbps.conf: the keyword "include" now supports file globbing, so that multiple small configuration files can be included directly, i.e: diff --git a/bin/xbps-remove/Makefile b/bin/xbps-remove/Makefile index bf3c3851..2781a3d5 100644 --- a/bin/xbps-remove/Makefile +++ b/bin/xbps-remove/Makefile @@ -2,7 +2,7 @@ TOPDIR = ../.. -include $(TOPDIR)/config.mk BIN = xbps-remove -OBJS = main.o +OBJS = main.o clean-cache.o OBJS += ../xbps-install/question.o OBJS += ../xbps-install/util.o OBJS += ../xbps-install/transaction.o diff --git a/bin/xbps-remove/clean-cache.c b/bin/xbps-remove/clean-cache.c new file mode 100644 index 00000000..650b5319 --- /dev/null +++ b/bin/xbps-remove/clean-cache.c @@ -0,0 +1,142 @@ +/*- + * Copyright (c) 2008-2014 Juan Romero Pardines. + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "defs.h" + +static int +cleaner_cb(struct xbps_handle *xhp, xbps_object_t obj, + const char *key _unused, void *arg _unused, + bool *done _unused) +{ + xbps_dictionary_t pkg_propsd, repo_pkgd; + const char *binpkg, *pkgver, *arch, *rsha256; + char *binpkgsig; + int rv; + + /* Internalize props.plist dictionary from binary pkg */ + binpkg = xbps_string_cstring_nocopy(obj); + pkg_propsd = xbps_get_pkg_plist_from_binpkg(binpkg, "./props.plist"); + if (pkg_propsd == NULL) { + rv = errno; + xbps_error_printf("Failed to read from %s: %s\n", binpkg, strerror(errno)); + return rv; + } + xbps_dictionary_get_cstring_nocopy(pkg_propsd, "architecture", &arch); + xbps_dictionary_get_cstring_nocopy(pkg_propsd, "pkgver", &pkgver); + if (!xbps_pkg_arch_match(xhp, arch, NULL)) { + xbps_dbg_printf(xhp, "%s: ignoring pkg with unmatched arch (%s)\n", pkgver, arch); + xbps_object_release(pkg_propsd); + return 0; + } + /* + * Remove binary pkg if it's not registered in any repository + * or if hash doesn't match. + */ + binpkgsig = xbps_xasprintf("%s.sig", binpkg); + repo_pkgd = xbps_rpool_get_pkg(xhp, pkgver); + if (repo_pkgd) { + xbps_dictionary_get_cstring_nocopy(repo_pkgd, + "filename-sha256", &rsha256); + if (xbps_file_hash_check(binpkg, rsha256) == ERANGE) { + if (unlink(binpkg) == -1) { + fprintf(stderr, "Failed to remove " + "`%s': %s\n", binpkg, strerror(errno)); + } else { + printf("Removed %s from cachedir (sha256 mismatch)\n", binpkg); + } + if ((access(binpkgsig, R_OK) == 0) && (unlink(binpkgsig) == -1)) { + fprintf(stderr, "Failed to remove " + "`%s': %s\n", binpkgsig, strerror(errno)); + } + } + xbps_object_release(pkg_propsd); + free(binpkgsig); + return 0; + } + if (unlink(binpkg) == -1) { + fprintf(stderr, "Failed to remove `%s': %s\n", + binpkg, strerror(errno)); + } else { + printf("Removed %s from cachedir (obsolete)\n", binpkg); + } + if ((access(binpkgsig, R_OK) == 0) && (unlink(binpkgsig) == -1)) { + fprintf(stderr, "Failed to remove `%s': %s\n", + binpkgsig, strerror(errno)); + } + xbps_object_release(pkg_propsd); + free(binpkgsig); + + return 0; +} + +int +clean_cachedir(struct xbps_handle *xhp) +{ + xbps_array_t array = NULL; + DIR *dirp; + struct dirent *dp; + char *ext; + int rv = 0; + + if (chdir(xhp->cachedir) == -1) + return -1; + + if ((dirp = opendir(xhp->cachedir)) == NULL) + return 0; + + while ((dp = readdir(dirp)) != NULL) { + if ((strcmp(dp->d_name, ".") == 0) || + (strcmp(dp->d_name, "..") == 0)) + continue; + + /* only process xbps binary packages, ignore something else */ + if ((ext = strrchr(dp->d_name, '.')) == NULL) + continue; + if (strcmp(ext, ".xbps")) { + xbps_dbg_printf(xhp, "ignoring unknown file: %s\n", dp->d_name); + continue; + } + if (array == NULL) + array = xbps_array_create(); + + xbps_array_add_cstring(array, dp->d_name); + } + (void)closedir(dirp); + + rv = xbps_array_foreach_cb_multi(xhp, array, NULL, cleaner_cb, NULL); + xbps_object_release(array); + return rv; +} diff --git a/bin/xbps-remove/defs.h b/bin/xbps-remove/defs.h new file mode 100644 index 00000000..512b4b82 --- /dev/null +++ b/bin/xbps-remove/defs.h @@ -0,0 +1,32 @@ +/*- + * Copyright (c) 2014 Juan Romero Pardines. + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + */ + +#ifndef _XBPS_REMOVE_DEFS_H_ +#define _XBPS_REMOVE_DEFS_H_ + +/* From clean-cache.c */ +int clean_cachedir(struct xbps_handle *); + +#endif /* !_XBPS_REMOVE_DEFS_H_ */ diff --git a/bin/xbps-remove/main.c b/bin/xbps-remove/main.c index bccf3a67..b1b433d2 100644 --- a/bin/xbps-remove/main.c +++ b/bin/xbps-remove/main.c @@ -33,11 +33,11 @@ #include #include #include -#include #include #include #include "../xbps-install/defs.h" +#include "defs.h" static void __attribute__((noreturn)) usage(bool fail) @@ -116,94 +116,6 @@ state_cb_rm(struct xbps_state_cb_data *xscd, void *cbdata _unused) return 0; } -static int -cachedir_clean(struct xbps_handle *xhp) -{ - xbps_dictionary_t pkg_propsd, repo_pkgd; - DIR *dirp; - struct dirent *dp; - const char *pkgver, *arch, *rsha256; - char *binpkg, *binpkgsig, *ext; - int rv = 0; - - if ((dirp = opendir(xhp->cachedir)) == NULL) - return 0; - - while ((dp = readdir(dirp)) != NULL) { - if ((strcmp(dp->d_name, ".") == 0) || - (strcmp(dp->d_name, "..") == 0)) - continue; - - /* only process xbps binary packages, ignore something else */ - if ((ext = strrchr(dp->d_name, '.')) == NULL) - continue; - if (strcmp(ext, ".xbps")) { - xbps_dbg_printf(xhp, "ignoring unknown file: %s\n", dp->d_name); - continue; - } - /* Internalize props.plist dictionary from binary pkg */ - binpkg = xbps_xasprintf("%s/%s", xhp->cachedir, dp->d_name); - pkg_propsd = xbps_get_pkg_plist_from_binpkg(binpkg, - "./props.plist"); - if (pkg_propsd == NULL) { - xbps_error_printf("Failed to read from %s: %s\n", - dp->d_name, strerror(errno)); - free(binpkg); - rv = errno; - break; - } - xbps_dictionary_get_cstring_nocopy(pkg_propsd, "architecture", &arch); - xbps_dictionary_get_cstring_nocopy(pkg_propsd, "pkgver", &pkgver); - if (!xbps_pkg_arch_match(xhp, arch, NULL)) { - xbps_dbg_printf(xhp, "%s: ignoring pkg with unmatched arch (%s)\n", pkgver, arch); - free(binpkg); - xbps_object_release(pkg_propsd); - continue; - } - /* - * Remove binary pkg if it's not registered in any repository - * or if hash doesn't match. - */ - binpkgsig = xbps_xasprintf("%s.sig", binpkg); - repo_pkgd = xbps_rpool_get_pkg(xhp, pkgver); - if (repo_pkgd) { - xbps_dictionary_get_cstring_nocopy(repo_pkgd, - "filename-sha256", &rsha256); - if (xbps_file_hash_check(binpkg, rsha256) == ERANGE) { - if (unlink(binpkg) == -1) { - fprintf(stderr, "Failed to remove " - "`%s': %s\n", binpkg, strerror(errno)); - } else { - printf("Removed %s from cachedir (sha256 mismatch)\n", dp->d_name); - } - if ((access(binpkgsig, R_OK) == 0) && (unlink(binpkgsig) == -1)) { - fprintf(stderr, "Failed to remove " - "`%s': %s\n", binpkgsig, strerror(errno)); - } - } - xbps_object_release(pkg_propsd); - free(binpkg); - free(binpkgsig); - continue; - } - if (unlink(binpkg) == -1) { - fprintf(stderr, "Failed to remove `%s': %s\n", - binpkg, strerror(errno)); - } else { - printf("Removed %s from cachedir (obsolete)\n", dp->d_name); - } - if ((access(binpkgsig, R_OK) == 0) && (unlink(binpkgsig) == -1)) { - fprintf(stderr, "Failed to remove `%s': %s\n", - binpkgsig, strerror(errno)); - } - xbps_object_release(pkg_propsd); - free(binpkg); - free(binpkgsig); - } - closedir(dirp); - return rv; -} - static int remove_pkg(struct xbps_handle *xhp, const char *pkgname, int cols, bool recursive) @@ -345,7 +257,7 @@ main(int argc, char **argv) maxcols = get_maxcols(); if (clean_cache) { - rv = cachedir_clean(&xh); + rv = clean_cachedir(&xh); if (rv != 0) exit(rv);; }