query.c

Go to the documentation of this file.
00001 /*
00002  *  query.c
00003  *
00004  *  Copyright (c) 2002-2007 by Judd Vinet <jvinet@zeroflux.org>
00005  *
00006  *  This program is free software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License as published by
00008  *  the Free Software Foundation; either version 2 of the License, or
00009  *  (at your option) any later version.
00010  *
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU General Public License
00017  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00018  */
00019 
00020 #include "config.h"
00021 
00022 #include <stdlib.h>
00023 #include <stdio.h>
00024 #include <limits.h>
00025 #include <string.h>
00026 #include <sys/stat.h>
00027 #include <errno.h>
00028 #include <unistd.h>
00029 
00030 #include <alpm.h>
00031 #include <alpm_list.h>
00032 
00033 /* pacman */
00034 #include "pacman.h"
00035 #include "package.h"
00036 #include "conf.h"
00037 #include "util.h"
00038 
00039 extern pmdb_t *db_local;
00040 
00041 static char *resolve_path(const char* file)
00042 {
00043     char *str = NULL;
00044 
00045     str = calloc(PATH_MAX+1, sizeof(char));
00046     if(!str) {
00047         return(NULL);
00048     }
00049 
00050     if(!realpath(file, str)) {
00051         free(str);
00052         return(NULL);
00053     }
00054 
00055     return(str);
00056 }
00057 
00058 static int query_fileowner(alpm_list_t *targets)
00059 {
00060     int ret = 0;
00061     alpm_list_t *t;
00062 
00063     /* This code is here for safety only */
00064     if(targets == NULL) {
00065         fprintf(stderr, _("error: no file was specified for --owns\n"));
00066         return(1);
00067     }
00068 
00069     for(t = targets; t; t = alpm_list_next(t)) {
00070         int found = 0;
00071         char *filename = alpm_list_getdata(t);
00072         char *bname;
00073         char *rpath;
00074         struct stat buf;
00075         alpm_list_t *i, *j;
00076 
00077         if(stat(filename, &buf) == -1) {
00078             fprintf(stderr, _("error: failed to read file '%s': %s\n"),
00079                     filename, strerror(errno));
00080             ret++;
00081             continue;
00082         }
00083 
00084         if(S_ISDIR(buf.st_mode)) {
00085             fprintf(stderr, _("error: cannot determine ownership of a directory\n"));
00086             ret++;
00087             continue;
00088         }
00089 
00090         bname = mbasename(filename);
00091 
00092         if(!(rpath = resolve_path(filename))) {
00093             fprintf(stderr, _("error: cannot determine real path for '%s': %s\n"),
00094                     filename, strerror(errno));
00095             ret++;
00096             continue;
00097         }
00098 
00099         for(i = alpm_db_getpkgcache(db_local); i && !found; i = alpm_list_next(i)) {
00100             pmpkg_t *info = alpm_list_getdata(i);
00101 
00102             for(j = alpm_pkg_get_files(info); j && !found; j = alpm_list_next(j)) {
00103                 char path[PATH_MAX], *ppath;
00104                 snprintf(path, PATH_MAX, "%s%s",
00105                          alpm_option_get_root(), (const char *)alpm_list_getdata(j));
00106 
00107                 /* avoid the costly resolve_path usage if the basenames don't match */
00108                 if(strcmp(mbasename(path), bname) != 0) {
00109                     continue;
00110                 }
00111 
00112                 ppath = resolve_path(path);
00113 
00114                 if(ppath && strcmp(ppath, rpath) == 0) {
00115                     printf(_("%s is owned by %s %s\n"), rpath,
00116                            alpm_pkg_get_name(info), alpm_pkg_get_version(info));
00117                     found = 1;
00118                 }
00119                 free(ppath);
00120             }
00121         }
00122         if(!found) {
00123             fprintf(stderr, _("error: No package owns %s\n"), filename);
00124             ret++;
00125         }
00126         free(rpath);
00127     }
00128 
00129     return ret;
00130 }
00131 
00132 /* search the local database for a matching package */
00133 static int query_search(alpm_list_t *targets)
00134 {
00135     alpm_list_t *i, *searchlist;
00136     int freelist;
00137 
00138     /* if we have a targets list, search for packages matching it */
00139     if(targets) {
00140         searchlist = alpm_db_search(db_local, targets);
00141         freelist = 1;
00142     } else {
00143         searchlist = alpm_db_getpkgcache(db_local);
00144         freelist = 0;
00145     }
00146     if(searchlist == NULL) {
00147         return(1);
00148     }
00149 
00150     for(i = searchlist; i; i = alpm_list_next(i)) {
00151         char *group = NULL;
00152         alpm_list_t *grp;
00153         pmpkg_t *pkg = alpm_list_getdata(i);
00154 
00155         if (!config->quiet) {
00156             printf("local/%s %s", alpm_pkg_get_name(pkg), alpm_pkg_get_version(pkg));
00157         } else {
00158             printf("%s", alpm_pkg_get_name(pkg));
00159         }
00160 
00161         /* print the package size with the output if ShowSize option set */
00162         if(config->showsize) {
00163             /* Convert byte size to MB */
00164             double mbsize = (double)alpm_pkg_get_size(pkg) / (1024.0 * 1024.0);
00165 
00166             printf(" [%.2f MB]", mbsize);
00167         }
00168 
00169 
00170         if (!config->quiet) {
00171             if((grp = alpm_pkg_get_groups(pkg)) != NULL) {
00172                 group = alpm_list_getdata(grp);
00173                 printf(" (%s)", (char *)alpm_list_getdata(grp));
00174             }
00175 
00176             /* we need a newline and initial indent first */
00177             printf("\n    ");
00178             indentprint(alpm_pkg_get_desc(pkg), 4);
00179         }
00180         printf("\n");
00181     }
00182 
00183     /* we only want to free if the list was a search list */
00184     if(freelist) {
00185         alpm_list_free(searchlist);
00186     }
00187     return(0);
00188 }
00189 
00190 static int query_group(alpm_list_t *targets)
00191 {
00192     alpm_list_t *i, *j;
00193     char *package = NULL;
00194     int ret = 0;
00195     if(targets == NULL) {
00196         for(j = alpm_db_getgrpcache(db_local); j; j = alpm_list_next(j)) {
00197             pmgrp_t *grp = alpm_list_getdata(j);
00198             const alpm_list_t *p, *pkgnames;
00199             const char *grpname;
00200 
00201             grpname = alpm_grp_get_name(grp);
00202             pkgnames = alpm_grp_get_pkgs(grp);
00203 
00204             for(p = pkgnames; p; p = alpm_list_next(p)) {
00205                 printf("%s %s\n", grpname, (char *)alpm_list_getdata(p));
00206             }
00207         }
00208     } else {
00209         for(i = targets; i; i = alpm_list_next(i)) {
00210             pmgrp_t *grp;
00211             package = alpm_list_getdata(i);
00212             grp = alpm_db_readgrp(db_local, package);
00213             if(grp) {
00214                 const alpm_list_t *p, *pkgnames = alpm_grp_get_pkgs(grp);
00215                 for(p = pkgnames; p; p = alpm_list_next(p)) {
00216                     printf("%s %s\n", package, (char *)alpm_list_getdata(p));
00217                 }
00218             } else {
00219                 fprintf(stderr, _("error: group \"%s\" was not found\n"), package);
00220                 ret++;
00221             }
00222         }
00223     }
00224     return ret;
00225 }
00226 
00227 static int query_upgrades(void)
00228 {
00229     alpm_list_t *syncpkgs = NULL;
00230     printf(_("Checking for package upgrades... \n"));
00231 
00232     alpm_list_t *syncdbs = alpm_option_get_syncdbs();
00233     if(alpm_sync_sysupgrade(db_local, syncdbs, &syncpkgs) == -1) {
00234         return(-1);
00235     }
00236     if(syncpkgs) {
00237         display_targets(syncpkgs, db_local);
00238         return(0);
00239     }
00240 
00241     printf(_("no upgrades found.\n"));
00242     return(1);
00243 }
00244 
00245 static int is_foreign(pmpkg_t *pkg)
00246 {
00247     const char *pkgname = alpm_pkg_get_name(pkg);
00248     alpm_list_t *j;
00249     alpm_list_t *sync_dbs = alpm_option_get_syncdbs();
00250 
00251     int match = 0;
00252     for(j = sync_dbs; j; j = alpm_list_next(j)) {
00253         pmdb_t *db = alpm_list_getdata(j);
00254         pmpkg_t *findpkg = alpm_db_get_pkg(db, pkgname);
00255         if(findpkg) {
00256             match = 1;
00257             break;
00258         }
00259     }
00260     if(match == 0) {
00261         return(1);
00262     }
00263     return(0);
00264 }
00265 
00266 static int is_unrequired(pmpkg_t *pkg)
00267 {
00268     alpm_list_t *requiredby = alpm_pkg_compute_requiredby(pkg);
00269     if(requiredby == NULL) {
00270         return(1);
00271     }
00272     FREELIST(requiredby);
00273     return(0);
00274 }
00275 
00276 static int filter(pmpkg_t *pkg)
00277 {
00278     /* check if this package was explicitly installed */
00279     if(config->op_q_explicit &&
00280             alpm_pkg_get_reason(pkg) != PM_PKG_REASON_EXPLICIT) {
00281         return(0);
00282     }
00283     /* check if this package was installed as a dependency */
00284     if(config->op_q_deps &&
00285             alpm_pkg_get_reason(pkg) != PM_PKG_REASON_DEPEND) {
00286         return(0);
00287     }
00288     /* check if this pkg isn't in a sync DB */
00289     if(config->op_q_foreign && !is_foreign(pkg)) {
00290         return(0);
00291     }
00292     /* check if this pkg is unrequired */
00293     if(config->op_q_unrequired && !is_unrequired(pkg)) {
00294         return(0);
00295     }
00296     return(1);
00297 }
00298 
00299 static void display(pmpkg_t *pkg)
00300 {
00301     if(config->op_q_info) {
00302         if(config->op_q_isfile) {
00303             /* omit info that isn't applicable for a file package */
00304             dump_pkg_full(pkg, 0);
00305         } else {
00306             dump_pkg_full(pkg, config->op_q_info);
00307         }
00308     }
00309     if(config->op_q_list) {
00310         dump_pkg_files(pkg);
00311     }
00312     if(config->op_q_changelog) {
00313         dump_pkg_changelog(pkg);
00314     }
00315     if(!config->op_q_info && !config->op_q_list && !config->op_q_changelog) {
00316         if (!config->quiet) {
00317             printf("%s %s\n", alpm_pkg_get_name(pkg), alpm_pkg_get_version(pkg));
00318         } else {
00319             printf("%s\n", alpm_pkg_get_name(pkg));
00320         }
00321     }
00322 }
00323 
00324 int pacman_query(alpm_list_t *targets)
00325 {
00326     int ret = 0;
00327     alpm_list_t *i;
00328 
00329     /* First: operations that do not require targets */
00330 
00331     /* search for a package */
00332     if(config->op_q_search) {
00333         ret = query_search(targets);
00334         return(ret);
00335     }
00336 
00337     /* check for package upgrades */
00338     if(config->op_q_upgrade) {
00339         ret = query_upgrades();
00340         return(ret);
00341     }
00342 
00343     /* looking for groups */
00344     if(config->group) {
00345         ret = query_group(targets);
00346         return(ret);
00347     }
00348 
00349     if(config->op_q_foreign) {
00350         /* ensure we have at least one valid sync db set up */
00351         alpm_list_t *sync_dbs = alpm_option_get_syncdbs();
00352         if(sync_dbs == NULL || alpm_list_count(sync_dbs) == 0) {
00353             pm_printf(PM_LOG_ERROR, _("no usable package repositories configured.\n"));
00354             return(-1);
00355         }
00356     }
00357 
00358     /* operations on all packages in the local DB
00359      * valid: no-op (plain -Q), list, info
00360      * invalid: isfile, owns */
00361     if(targets == NULL) {
00362         if(config->op_q_isfile || config->op_q_owns) {
00363             pm_printf(PM_LOG_ERROR, _("no targets specified (use -h for help)\n"));
00364             return(1);
00365         }
00366 
00367         for(i = alpm_db_getpkgcache(db_local); i; i = alpm_list_next(i)) {
00368             pmpkg_t *pkg = alpm_list_getdata(i);
00369             if(filter(pkg)) {
00370                 display(pkg);
00371             }
00372         }
00373         return(0);
00374     }
00375 
00376     /* Second: operations that require target(s) */
00377 
00378     /* determine the owner of a file */
00379     if(config->op_q_owns) {
00380         ret = query_fileowner(targets);
00381         return(ret);
00382     }
00383 
00384     /* operations on named packages in the local DB
00385      * valid: no-op (plain -Q), list, info */
00386     for(i = targets; i; i = alpm_list_next(i)) {
00387         char *strname = alpm_list_getdata(i);
00388         pmpkg_t *pkg = NULL;
00389 
00390         if(config->op_q_isfile) {
00391             alpm_pkg_load(strname, 1, &pkg);
00392         } else {
00393             pkg = alpm_db_get_pkg(db_local, strname);
00394         }
00395 
00396         if(pkg == NULL) {
00397             fprintf(stderr, _("error: package \"%s\" not found\n"), strname);
00398             ret++;
00399             continue;
00400         }
00401 
00402         if(filter(pkg)) {
00403             display(pkg);
00404         }
00405 
00406         if(config->op_q_isfile) {
00407             alpm_pkg_free(pkg);
00408             pkg = NULL;
00409         }
00410     }
00411 
00412     return(ret);
00413 }
00414 
00415 /* vim: set ts=2 sw=2 noet: */

Generated on Mon Jan 14 23:53:40 2008 for libalpm by  doxygen 1.5.4