diff options
Diffstat (limited to 'src/pacman/query.c')
-rw-r--r-- | src/pacman/query.c | 545 |
1 files changed, 317 insertions, 228 deletions
diff --git a/src/pacman/query.c b/src/pacman/query.c index a6ebddb0..8a8765b6 100644 --- a/src/pacman/query.c +++ b/src/pacman/query.c @@ -1,8 +1,8 @@ /* * query.c - * - * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> - * + * + * Copyright (c) 2002-2007 by Judd Vinet <jvinet@zeroflux.org> + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -15,7 +15,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. */ @@ -26,7 +26,6 @@ #include <limits.h> #include <string.h> #include <sys/stat.h> -#include <libintl.h> #include <errno.h> #include <unistd.h> @@ -34,302 +33,392 @@ #include <alpm_list.h> /* pacman */ -#include "query.h" +#include "pacman.h" #include "package.h" -#include "log.h" #include "conf.h" -#include "sync.h" #include "util.h" -extern config_t *config; extern pmdb_t *db_local; static char *resolve_path(const char* file) { - char *copy, *p, *str = NULL; + char *str = NULL; - if(!(copy = strdup(file))) { + str = calloc(PATH_MAX+1, sizeof(char)); + if(!str) { return(NULL); } - if((p = strrchr(copy, '/')) == NULL) { - return(copy); - } else { - *p = '\0'; ++p; + if(!realpath(file, str)) { + free(str); + return(NULL); + } + + return(str); +} + +static int query_fileowner(alpm_list_t *targets) +{ + int ret = 0; + alpm_list_t *t; - str = calloc(PATH_MAX+1, sizeof(char)); - if(!str) { - /* null hmmm.... */ - return(NULL); + /* This code is here for safety only */ + if(targets == NULL) { + fprintf(stderr, _("error: no file was specified for --owns\n")); + return(1); + } + + for(t = targets; t; t = alpm_list_next(t)) { + int found = 0; + char *filename = alpm_list_getdata(t); + char *bname; + char *rpath; + struct stat buf; + alpm_list_t *i, *j; + + if(stat(filename, &buf) == -1) { + fprintf(stderr, _("error: failed to read file '%s': %s\n"), + filename, strerror(errno)); + ret++; + continue; } - if(!realpath(copy, str)) { - return(NULL); + if(S_ISDIR(buf.st_mode)) { + fprintf(stderr, _("error: cannot determine ownership of a directory\n")); + ret++; + continue; } - str[strlen(str)] = '/'; - strcat(str, p); + bname = mbasename(filename); + + if(!(rpath = resolve_path(filename))) { + fprintf(stderr, _("error: cannot determine real path for '%s': %s\n"), + filename, strerror(errno)); + ret++; + continue; + } + + for(i = alpm_db_getpkgcache(db_local); i && !found; i = alpm_list_next(i)) { + pmpkg_t *info = alpm_list_getdata(i); + + for(j = alpm_pkg_get_files(info); j && !found; j = alpm_list_next(j)) { + char path[PATH_MAX], *ppath; + snprintf(path, PATH_MAX, "%s%s", + alpm_option_get_root(), (const char *)alpm_list_getdata(j)); + + /* avoid the costly resolve_path usage if the basenames don't match */ + if(strcmp(mbasename(path), bname) != 0) { + continue; + } + + ppath = resolve_path(path); + + if(ppath && strcmp(ppath, rpath) == 0) { + printf(_("%s is owned by %s %s\n"), rpath, + alpm_pkg_get_name(info), alpm_pkg_get_version(info)); + found = 1; + } + free(ppath); + } + } + if(!found) { + fprintf(stderr, _("error: No package owns %s\n"), filename); + ret++; + } + free(rpath); } - free(copy); - return(str); + return ret; } - -static void query_fileowner(pmdb_t *db, char *filename) +/* search the local database for a matching package */ +static int query_search(alpm_list_t *targets) { - struct stat buf; - int gotcha = 0; - char *rpath; - alpm_list_t *i, *j; + alpm_list_t *i, *searchlist; + int freelist; - if(db == NULL) { - return; + /* if we have a targets list, search for packages matching it */ + if(targets) { + searchlist = alpm_db_search(db_local, targets); + freelist = 1; + } else { + searchlist = alpm_db_getpkgcache(db_local); + freelist = 0; } - if(filename == NULL || strlen(filename) == 0) { - ERR(NL, _("no file was specified for --owns\n")); - return; + if(searchlist == NULL) { + return(1); } - if(stat(filename, &buf) == -1) { - ERR(NL, _("failed to read file '%s': %s"), filename, strerror(errno)); - return; - } - - if(S_ISDIR(buf.st_mode)) { - ERR(NL, _("cannot determine ownership of a directory")); - return; - } + for(i = searchlist; i; i = alpm_list_next(i)) { + char *group = NULL; + alpm_list_t *grp; + pmpkg_t *pkg = alpm_list_getdata(i); - if(!(rpath = resolve_path(filename))) { - ERR(NL, _("cannot determine real path for '%s': %s"), filename, strerror(errno)); - return; - } + if (!config->quiet) { + printf("local/%s %s", alpm_pkg_get_name(pkg), alpm_pkg_get_version(pkg)); + } else { + printf("%s", alpm_pkg_get_name(pkg)); + } - for(i = alpm_db_getpkgcache(db); i && !gotcha; i = alpm_list_next(i)) { - pmpkg_t *info = alpm_list_getdata(i); + /* print the package size with the output if ShowSize option set */ + if(config->showsize) { + /* Convert byte size to MB */ + double mbsize = (double)alpm_pkg_get_size(pkg) / (1024.0 * 1024.0); - for(j = alpm_pkg_get_files(info); j && !gotcha; j = alpm_list_next(j)) { - char path[PATH_MAX], *ppath; - snprintf(path, PATH_MAX, "%s%s", alpm_option_get_root(), (const char *)alpm_list_getdata(j)); + printf(" [%.2f MB]", mbsize); + } - ppath = resolve_path(path); - if(ppath && strcmp(ppath, rpath) == 0) { - printf(_("%s is owned by %s %s\n"), filename, alpm_pkg_get_name(info), alpm_pkg_get_version(info)); - gotcha = 1; + if (!config->quiet) { + if((grp = alpm_pkg_get_groups(pkg)) != NULL) { + group = alpm_list_getdata(grp); + printf(" (%s)", (char *)alpm_list_getdata(grp)); } - free(ppath); + /* we need a newline and initial indent first */ + printf("\n "); + indentprint(alpm_pkg_get_desc(pkg), 4); } - } - if(!gotcha) { - ERR(NL, _("No package owns %s\n"), filename); + printf("\n"); } - free(rpath); + /* we only want to free if the list was a search list */ + if(freelist) { + alpm_list_free(searchlist); + } + return(0); } -int pacman_query(alpm_list_t *targets) +static int query_group(alpm_list_t *targets) { - alpm_list_t *sync_dbs = NULL, *i, *j, *k; - pmpkg_t *info = NULL; + alpm_list_t *i, *j; char *package = NULL; - int done = 0; - - if(config->op_q_search) { - alpm_list_t *ret = alpm_db_search(db_local, targets); - if(ret == NULL) { - return(0); + int ret = 0; + if(targets == NULL) { + for(j = alpm_db_getgrpcache(db_local); j; j = alpm_list_next(j)) { + pmgrp_t *grp = alpm_list_getdata(j); + const alpm_list_t *p, *pkgnames; + const char *grpname; + + grpname = alpm_grp_get_name(grp); + pkgnames = alpm_grp_get_pkgs(grp); + + for(p = pkgnames; p; p = alpm_list_next(p)) { + printf("%s %s\n", grpname, (char *)alpm_list_getdata(p)); + } } - for(i = ret; i; i = alpm_list_next(i)) { - char *group = NULL; - alpm_list_t *grp; - pmpkg_t *pkg = alpm_list_getdata(i); - - printf("local/%s %s", alpm_pkg_get_name(pkg), alpm_pkg_get_version(pkg)); - - if((grp = alpm_pkg_get_groups(pkg)) != NULL) { - group = alpm_list_getdata(grp); - printf(" (%s)\n ", (char *)alpm_list_getdata(grp)); + } else { + for(i = targets; i; i = alpm_list_next(i)) { + pmgrp_t *grp; + package = alpm_list_getdata(i); + grp = alpm_db_readgrp(db_local, package); + if(grp) { + const alpm_list_t *p, *pkgnames = alpm_grp_get_pkgs(grp); + for(p = pkgnames; p; p = alpm_list_next(p)) { + printf("%s %s\n", package, (char *)alpm_list_getdata(p)); + } } else { - printf("\n "); + fprintf(stderr, _("error: group \"%s\" was not found\n"), package); + ret++; } - - indentprint(alpm_pkg_get_desc(pkg), 4); - printf("\n"); } - alpm_list_free(ret); + } + return ret; +} + +static int query_upgrades(void) +{ + alpm_list_t *syncpkgs = NULL; + printf(_("Checking for package upgrades... \n")); + + alpm_list_t *syncdbs = alpm_option_get_syncdbs(); + if(alpm_sync_sysupgrade(db_local, syncdbs, &syncpkgs) == -1) { + return(-1); + } + if(syncpkgs) { + display_targets(syncpkgs, db_local); return(0); } - if(config->op_q_foreign) { - sync_dbs = alpm_option_get_syncdbs(); + printf(_("no upgrades found.\n")); + return(1); +} - if(sync_dbs == NULL || alpm_list_count(sync_dbs) == 0) { - ERR(NL, _("no usable package repositories configured.\n")); - return(1); +static int is_foreign(pmpkg_t *pkg) +{ + const char *pkgname = alpm_pkg_get_name(pkg); + alpm_list_t *j; + alpm_list_t *sync_dbs = alpm_option_get_syncdbs(); + + int match = 0; + for(j = sync_dbs; j; j = alpm_list_next(j)) { + pmdb_t *db = alpm_list_getdata(j); + pmpkg_t *findpkg = alpm_db_get_pkg(db, pkgname); + if(findpkg) { + match = 1; + break; } } + if(match == 0) { + return(1); + } + return(0); +} + +static int is_orphan(pmpkg_t *pkg) +{ + alpm_list_t *requiredby = alpm_pkg_compute_requiredby(pkg); + if(requiredby == NULL) { + return(1); + } + FREELIST(requiredby); + return(0); +} - if(config->op_q_upgrade) { - MSG(NL, _("Checking for package upgrades...")); - alpm_list_t *syncpkgs; +static int filter(pmpkg_t *pkg) +{ + /* check if this package was explicitly installed */ + if(config->op_q_explicit && + alpm_pkg_get_reason(pkg) != PM_PKG_REASON_EXPLICIT) { + return(0); + } + /* check if this package was installed as a dependency */ + if(config->op_q_deps && + alpm_pkg_get_reason(pkg) != PM_PKG_REASON_DEPEND) { + return(0); + } + /* check if this pkg isn't in a sync DB */ + if(config->op_q_foreign && !is_foreign(pkg)) { + return(0); + } + /* check if this pkg is orphaned */ + if(config->op_q_orphans && !is_orphan(pkg)) { + return(0); + } + return(1); +} - if((syncpkgs = alpm_get_upgrades()) != NULL) { - display_targets(syncpkgs); - return(0); +static void display(pmpkg_t *pkg) +{ + if(config->op_q_info) { + if(config->op_q_isfile) { + /* omit info that isn't applicable for a file package */ + dump_pkg_full(pkg, 0); } else { - MSG(NL, _("no upgrades found")); - return(1); + dump_pkg_full(pkg, config->op_q_info); } } - - for(i = targets; !done; i = (i ? alpm_list_next(i) : NULL)) { - if(targets == NULL) { - done = 1; + if(config->op_q_list) { + dump_pkg_files(pkg); + } + if(config->op_q_changelog) { + char changelog[PATH_MAX]; + /* TODO should be done in the backend- no raw DB stuff up front */ + snprintf(changelog, PATH_MAX, "%s/%s/%s-%s/changelog", + alpm_option_get_dbpath(), + alpm_db_get_name(db_local), + alpm_pkg_get_name(pkg), + alpm_pkg_get_version(pkg)); + dump_pkg_changelog(changelog, alpm_pkg_get_name(pkg)); + } + if(!config->op_q_info && !config->op_q_list && !config->op_q_changelog) { + if (!config->quiet) { + printf("%s %s\n", alpm_pkg_get_name(pkg), alpm_pkg_get_version(pkg)); } else { - if(alpm_list_next(i) == NULL) { - done = 1; - } - package = alpm_list_getdata(i); + printf("%s\n", alpm_pkg_get_name(pkg)); } + } +} + +int pacman_query(alpm_list_t *targets) +{ + int ret = 0; + alpm_list_t *i; - /* looking for groups */ - if(config->group) { - if(targets == NULL) { - for(j = alpm_db_getgrpcache(db_local); j; j = alpm_list_next(j)) { - pmgrp_t *grp = alpm_list_getdata(j); - alpm_list_t *p, *pkgnames; - const char *grpname; + /* First: operations that do not require targets */ - grpname = alpm_grp_get_name(grp); - pkgnames = alpm_grp_get_pkgs(grp); + /* search for a package */ + if(config->op_q_search) { + ret = query_search(targets); + return(ret); + } - for(p = pkgnames; p; p = alpm_list_next(p)) { - MSG(NL, "%s %s\n", grpname, (char *)alpm_list_getdata(p)); - } - } - } else { - pmgrp_t *grp = alpm_db_readgrp(db_local, package); - if(grp) { - alpm_list_t *p, *pkgnames = alpm_grp_get_pkgs(grp); - for(p = pkgnames; p; p = alpm_list_next(p)) { - MSG(NL, "%s %s\n", package, (char *)alpm_list_getdata(p)); - } - } else { - ERR(NL, _("group \"%s\" was not found\n"), package); - /* do not return on query operations - let's just carry on */ - /*return(2);*/ - } + /* check for package upgrades */ + if(config->op_q_upgrade) { + ret = query_upgrades(); + return(ret); + } + + /* looking for groups */ + if(config->group) { + ret = query_group(targets); + return(ret); + } + + if(config->op_q_foreign) { + /* ensure we have at least one valid sync db set up */ + alpm_list_t *sync_dbs = alpm_option_get_syncdbs(); + if(sync_dbs == NULL || alpm_list_count(sync_dbs) == 0) { + pm_printf(PM_LOG_ERROR, _("no usable package repositories configured.\n")); + return(-1); + } + } + + /* operations on all packages in the local DB + * valid: no-op (plain -Q), list, info + * invalid: isfile, owns */ + if(targets == NULL) { + if(config->op_q_isfile || config->op_q_owns) { + pm_printf(PM_LOG_ERROR, _("no targets specified (use -h for help)\n")); + return(1); + } + + for(i = alpm_db_getpkgcache(db_local); i; i = alpm_list_next(i)) { + pmpkg_t *pkg = alpm_list_getdata(i); + if(filter(pkg)) { + display(pkg); } - continue; } + return(0); + } + + /* Second: operations that require target(s) */ + + /* determine the owner of a file */ + if(config->op_q_owns) { + ret = query_fileowner(targets); + return(ret); + } + + /* operations on named packages in the local DB + * valid: no-op (plain -Q), list, info */ + for(i = targets; i; i = alpm_list_next(i)) { + char *strname = alpm_list_getdata(i); + pmpkg_t *pkg = NULL; - /* output info for a .tar.gz package */ if(config->op_q_isfile) { - if(package == NULL) { - ERR(NL, _("no package file was specified for --file\n")); - return(1); - } - if(alpm_pkg_load(package, &info) == -1) { - ERR(NL, _("failed to load package '%s' (%s)\n"), package, alpm_strerror(pm_errno)); - return(1); - } - if(config->op_q_info) { - dump_pkg_full(info, config->op_q_info); - } - if(config->op_q_list) { - dump_pkg_files(info); - } - if(!config->op_q_info && !config->op_q_list) { - MSG(NL, "%s %s\n", alpm_pkg_get_name(info), - alpm_pkg_get_version(info)); - } - FREEPKG(info); - continue; + alpm_pkg_load(strname, 1, &pkg); + } else { + pkg = alpm_db_get_pkg(db_local, strname); } - /* determine the owner of a file */ - if(config->op_q_owns) { - query_fileowner(db_local, package); + if(pkg == NULL) { + fprintf(stderr, _("error: package \"%s\" not found\n"), strname); + ret++; continue; } - /* find packages in the db */ - if(package == NULL) { - /* no target */ - for(i = alpm_db_getpkgcache(db_local); i; i = alpm_list_next(i)) { - pmpkg_t *tmpp = alpm_list_getdata(i); - const char *pkgname, *pkgver; - - pkgname = alpm_pkg_get_name(tmpp); - pkgver = alpm_pkg_get_version(tmpp); - - if(config->op_q_list || config->op_q_orphans || config->op_q_foreign) { - info = alpm_db_get_pkg(db_local, (char *)pkgname); - if(info == NULL) { - /* something weird happened */ - ERR(NL, _("package \"%s\" not found\n"), pkgname); - continue; - } - } - if(config->op_q_foreign) { - int match = 0; - for(j = sync_dbs; j; j = alpm_list_next(j)) { - pmdb_t *db = (pmdb_t *)alpm_list_getdata(j); - for(k = alpm_db_getpkgcache(db); k; k = alpm_list_next(k)) { - pmpkg_t *pkg = alpm_list_getdata(k); - if(strcmp(alpm_pkg_get_name(pkg), alpm_pkg_get_name(info)) == 0) { - match = 1; - } - } - } - if(match==0) { - MSG(NL, "%s %s\n", pkgname, pkgver); - } - } else if(config->op_q_list) { - dump_pkg_files(info); - } else if(config->op_q_orphans) { - if(alpm_pkg_get_requiredby(info) == NULL - && (long)alpm_pkg_get_reason(info) == PM_PKG_REASON_DEPEND) { - MSG(NL, "%s %s\n", pkgname, pkgver); - } - } else { - MSG(NL, "%s %s\n", pkgname, pkgver); - } - } - } else { - info = alpm_db_get_pkg(db_local, package); - if(info == NULL) { - ERR(NL, _("package \"%s\" not found\n"), package); - continue; - } + if(filter(pkg)) { + display(pkg); + } - /* find a target */ - if(config->op_q_info) { - dump_pkg_full(info, config->op_q_info); - } - if(config->op_q_list) { - dump_pkg_files(info); - } - if(!config->op_q_info && !config->op_q_list) { - MSG(NL, "%s %s\n", alpm_pkg_get_name(info), - alpm_pkg_get_version(info)); - } - if(config->op_q_changelog) { - char changelog[PATH_MAX]; - snprintf(changelog, PATH_MAX, "%s%s/%s/%s-%s/changelog", - alpm_option_get_root(), alpm_option_get_dbpath(), - alpm_db_get_name(db_local), - alpm_pkg_get_name(info), - alpm_pkg_get_version(info)); - dump_pkg_changelog(changelog, alpm_pkg_get_name(info)); - } + if(config->op_q_isfile) { + alpm_pkg_free(pkg); + pkg = NULL; } } - return(0); + return(ret); } /* vim: set ts=2 sw=2 noet: */ |