LCOV - code coverage report
Current view: top level - libpkg - pkgdb_query.c (source / functions) Hit Total Coverage
Test: cov.info Lines: 69 168 41.1 %
Date: 2015-08-15 Functions: 6 13 46.2 %

          Line data    Source code
       1             : /*-
       2             :  * Copyright (c) 2011-2012 Baptiste Daroussin <bapt@FreeBSD.org>
       3             :  * Copyright (c) 2011-2012 Julien Laffaye <jlaffaye@FreeBSD.org>
       4             :  * Copyright (c) 2011 Will Andrews <will@FreeBSD.org>
       5             :  * Copyright (c) 2011 Philippe Pepiot <phil@philpep.org>
       6             :  * Copyright (c) 2011-2012 Marin Atanasov Nikolov <dnaeon@gmail.com>
       7             :  * Copyright (c) 2012-2013 Matthew Seaman <matthew@FreeBSD.org>
       8             :  * Copyright (c) 2012 Bryan Drewery <bryan@shatow.net>
       9             :  * Copyright (c) 2013 Gerald Pfeifer <gerald@pfeifer.com>
      10             :  * Copyright (c) 2013-2014 Vsevolod Stakhov <vsevolod@FreeBSD.org>
      11             :  * All rights reserved.
      12             :  *
      13             :  * Redistribution and use in source and binary forms, with or without
      14             :  * modification, are permitted provided that the following conditions
      15             :  * are met:
      16             :  * 1. Redistributions of source code must retain the above copyright
      17             :  *    notice, this list of conditions and the following disclaimer
      18             :  *    in this position and unchanged.
      19             :  * 2. Redistributions in binary form must reproduce the above copyright
      20             :  *    notice, this list of conditions and the following disclaimer in the
      21             :  *    documentation and/or other materials provided with the distribution.
      22             :  *
      23             :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
      24             :  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
      25             :  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
      26             :  * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
      27             :  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
      28             :  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      29             :  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      30             :  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      31             :  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
      32             :  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      33             :  */
      34             : 
      35             : #ifdef HAVE_CONFIG_H
      36             : #include "pkg_config.h"
      37             : #endif
      38             : 
      39             : #include <assert.h>
      40             : #include <errno.h>
      41             : #include <regex.h>
      42             : #include <grp.h>
      43             : #ifdef HAVE_LIBUTIL_H
      44             : #include <libutil.h>
      45             : #endif
      46             : #include <stdlib.h>
      47             : #include <stdio.h>
      48             : #include <stdbool.h>
      49             : #include <string.h>
      50             : #include <unistd.h>
      51             : #include <signal.h>
      52             : 
      53             : #include <sqlite3.h>
      54             : 
      55             : #include "pkg.h"
      56             : #include "private/event.h"
      57             : #include "private/pkg.h"
      58             : #include "private/pkgdb.h"
      59             : #include "private/utils.h"
      60             : 
      61             : const char *
      62         208 : pkgdb_get_pattern_query(const char *pattern, match_t match)
      63             : {
      64         208 :         char            *checkorigin = NULL;
      65         208 :         char            *checkuid = NULL;
      66         208 :         const char      *comp = NULL;
      67             : 
      68         208 :         if (pattern != NULL) {
      69         176 :                 checkuid = strchr(pattern, '~');
      70         176 :                 if (checkuid == NULL)
      71         176 :                         checkorigin = strchr(pattern, '/');
      72             :         }
      73             : 
      74         208 :         switch (match) {
      75             :         case MATCH_ALL:
      76          32 :                 comp = "";
      77          32 :                 break;
      78             :         case MATCH_EXACT:
      79         141 :                 if (pkgdb_case_sensitive()) {
      80           0 :                         if (checkuid == NULL) {
      81           0 :                                 if (checkorigin == NULL)
      82           0 :                                         comp = " WHERE name = ?1 "
      83             :                                             "OR (name = SPLIT_VERSION('name', ?1) AND "
      84             :                                             " version = SPLIT_VERSION('version', ?1))";
      85             :                                 else
      86           0 :                                         comp = " WHERE origin = ?1";
      87             :                         } else {
      88           0 :                                 comp = " WHERE name = ?1";
      89             :                         }
      90             :                 } else {
      91         141 :                         if (checkuid == NULL) {
      92         141 :                                 if (checkorigin == NULL)
      93         140 :                                         comp = " WHERE name = ?1 COLLATE NOCASE "
      94             :                                                         "OR (name = SPLIT_VERSION('name', ?1) COLLATE NOCASE AND "
      95             :                                                         " version = SPLIT_VERSION('version', ?1))";
      96             :                                 else
      97           1 :                                         comp = " WHERE origin = ?1 COLLATE NOCASE";
      98             :                         } else {
      99           0 :                                 comp = " WHERE name = ?1 COLLATE NOCASE";
     100             :                         }
     101             :                 }
     102         141 :                 break;
     103             :         case MATCH_GLOB:
     104           5 :                 if (checkuid == NULL) {
     105           5 :                         if (checkorigin == NULL)
     106           5 :                                 comp = " WHERE name GLOB ?1 "
     107             :                                         "OR name || '-' || version GLOB ?1";
     108             :                         else
     109           0 :                                 comp = " WHERE origin GLOB ?1";
     110             :                 } else {
     111           0 :                         comp = " WHERE name = ?1";
     112             :                 }
     113           5 :                 break;
     114             :         case MATCH_REGEX:
     115           0 :                 if (checkuid == NULL) {
     116           0 :                         if (checkorigin == NULL)
     117           0 :                                 comp = " WHERE name REGEXP ?1 "
     118             :                                     "OR name || '-' || version REGEXP ?1";
     119             :                         else
     120           0 :                                 comp = " WHERE origin REGEXP ?1";
     121             :                 } else {
     122           0 :                         comp = " WHERE name = ?1";
     123             :                 }
     124           0 :                 break;
     125             :         case MATCH_CONDITION:
     126          30 :                 comp = pattern;
     127          30 :                 break;
     128             :         case MATCH_FTS:
     129           0 :                 if (checkorigin == NULL)
     130           0 :                         comp = " WHERE id IN (SELECT id FROM pkg_search WHERE name MATCH ?1)";
     131             :                 else
     132           0 :                         comp = " WHERE id IN (SELECT id FROM pkg_search WHERE origin MATCH ?1)";
     133           0 :                 break;
     134             :         }
     135             : 
     136         208 :         return (comp);
     137             : }
     138             : 
     139             : struct pkgdb_it *
     140         142 : pkgdb_query(struct pkgdb *db, const char *pattern, match_t match)
     141             : {
     142             :         char             sql[BUFSIZ];
     143             :         sqlite3_stmt    *stmt;
     144         142 :         const char      *comp = NULL;
     145             : 
     146         142 :         assert(db != NULL);
     147             : 
     148         142 :         if (match != MATCH_ALL && (pattern == NULL || pattern[0] == '\0'))
     149           0 :                 return (NULL);
     150             : 
     151         142 :         comp = pkgdb_get_pattern_query(pattern, match);
     152             : 
     153         142 :         sqlite3_snprintf(sizeof(sql), sql,
     154             :                         "SELECT id, origin, name, name as uniqueid, "
     155             :                                 "version, comment, desc, "
     156             :                                 "message, arch, maintainer, www, "
     157             :                                 "prefix, flatsize, licenselogic, automatic, "
     158             :                                 "locked, time, manifestdigest "
     159             :                         "FROM packages AS p%s "
     160             :                         "ORDER BY p.name;", comp);
     161             : 
     162         142 :         pkg_debug(4, "Pkgdb: running '%s'", sql);
     163         142 :         if (sqlite3_prepare_v2(db->sqlite, sql, -1, &stmt, NULL) != SQLITE_OK) {
     164           0 :                 ERROR_SQLITE(db->sqlite, sql);
     165           0 :                 return (NULL);
     166             :         }
     167             : 
     168         142 :         if (match != MATCH_ALL && match != MATCH_CONDITION)
     169          96 :                 sqlite3_bind_text(stmt, 1, pattern, -1, SQLITE_TRANSIENT);
     170             : 
     171         142 :         return (pkgdb_it_new_sqlite(db, stmt, PKG_INSTALLED, PKGDB_IT_FLAG_ONCE));
     172             : }
     173             : 
     174             : struct pkgdb_it *
     175           1 : pkgdb_query_which(struct pkgdb *db, const char *path, bool glob)
     176             : {
     177             :         sqlite3_stmt    *stmt;
     178             :         char    sql[BUFSIZ];
     179             : 
     180           1 :         assert(db != NULL);
     181             : 
     182           1 :         if (path == NULL)
     183           0 :                 return (NULL);
     184             : 
     185           1 :         sqlite3_snprintf(sizeof(sql), sql,
     186             :                         "SELECT p.id, p.origin, p.name, p.name as uniqueid, "
     187             :                         "p.version, p.comment, p.desc, "
     188             :                         "p.message, p.arch, p.maintainer, p.www, "
     189             :                         "p.prefix, p.flatsize, p.time "
     190             :                         "FROM packages AS p "
     191             :                         "LEFT JOIN files AS f ON p.id = f.package_id "
     192             :                         "WHERE f.path %s ?1 GROUP BY p.id;", glob ? "GLOB" : "=");
     193             : 
     194           1 :         pkg_debug(4, "Pkgdb: running '%s'", sql);
     195           1 :         if (sqlite3_prepare_v2(db->sqlite, sql, -1, &stmt, NULL) != SQLITE_OK) {
     196           0 :                 ERROR_SQLITE(db->sqlite, sql);
     197           0 :                 return (NULL);
     198             :         }
     199             : 
     200           1 :         sqlite3_bind_text(stmt, 1, path, -1, SQLITE_TRANSIENT);
     201             : 
     202           1 :         return (pkgdb_it_new_sqlite(db, stmt, PKG_INSTALLED, PKGDB_IT_FLAG_ONCE));
     203             : }
     204             : 
     205             : struct pkgdb_it *
     206           0 : pkgdb_query_shlib_require(struct pkgdb *db, const char *shlib)
     207             : {
     208             :         sqlite3_stmt    *stmt;
     209           0 :         const char       sql[] = ""
     210             :                 "SELECT p.id, p.origin, p.name, p.name as uniqueid, "
     211             :                         "p.version, p.comment, p.desc, "
     212             :                         "p.message, p.arch, p.maintainer, p.www, "
     213             :                         "p.prefix, p.flatsize, p.time "
     214             :                         "FROM packages AS p, pkg_shlibs_required AS ps, shlibs AS s "
     215             :                         "WHERE p.id = ps.package_id "
     216             :                                 "AND ps.shlib_id = s.id "
     217             :                                 "AND s.name = ?1;";
     218             : 
     219           0 :         assert(db != NULL);
     220             : 
     221           0 :         pkg_debug(4, "Pkgdb: running '%s'", sql);
     222           0 :         if (sqlite3_prepare_v2(db->sqlite, sql, -1, &stmt, NULL) != SQLITE_OK) {
     223           0 :                 ERROR_SQLITE(db->sqlite, sql);
     224           0 :                 return (NULL);
     225             :         }
     226             : 
     227           0 :         sqlite3_bind_text(stmt, 1, shlib, -1, SQLITE_TRANSIENT);
     228             : 
     229           0 :         return (pkgdb_it_new_sqlite(db, stmt, PKG_INSTALLED, PKGDB_IT_FLAG_ONCE));
     230             : }
     231             : 
     232             : struct pkgdb_it *
     233           0 : pkgdb_query_shlib_provide(struct pkgdb *db, const char *shlib)
     234             : {
     235             :         sqlite3_stmt    *stmt;
     236           0 :         const char       sql[] = ""
     237             :                 "SELECT p.id, p.origin, p.name, p.name as uniqueid, "
     238             :                         "p.version, p.comment, p.desc, "
     239             :                         "p.message, p.arch, p.maintainer, p.www, "
     240             :                         "p.prefix, p.flatsize, p.time "
     241             :                         "FROM packages AS p, pkg_shlibs_provided AS ps, shlibs AS s "
     242             :                         "WHERE p.id = ps.package_id "
     243             :                                 "AND ps.shlib_id = s.id "
     244             :                                 "AND s.name = ?1;";
     245             : 
     246           0 :         assert(db != NULL);
     247             : 
     248           0 :         pkg_debug(4, "Pkgdb: running '%s'", sql);
     249           0 :         if (sqlite3_prepare_v2(db->sqlite, sql, -1, &stmt, NULL) != SQLITE_OK) {
     250           0 :                 ERROR_SQLITE(db->sqlite, sql);
     251           0 :                 return (NULL);
     252             :         }
     253             : 
     254           0 :         sqlite3_bind_text(stmt, 1, shlib, -1, SQLITE_TRANSIENT);
     255             : 
     256           0 :         return (pkgdb_it_new_sqlite(db, stmt, PKG_INSTALLED, PKGDB_IT_FLAG_ONCE));
     257             : }
     258             : 
     259             : struct pkgdb_it *
     260           0 : pkgdb_query_require(struct pkgdb *db, const char *req)
     261             : {
     262             :         sqlite3_stmt    *stmt;
     263           0 :         const char       sql[] = ""
     264             :                 "SELECT p.id, p.origin, p.name, p.name as uniqueid, "
     265             :                         "p.version, p.comment, p.desc, "
     266             :                         "p.message, p.arch, p.maintainer, p.www, "
     267             :                         "p.prefix, p.flatsize, p.time "
     268             :                         "FROM packages AS p, pkg_requires AS ps, requires AS s "
     269             :                         "WHERE p.id = ps.package_id "
     270             :                                 "AND ps.require_id = s.id "
     271             :                                 "AND s.require = ?1;";
     272             : 
     273           0 :         assert(db != NULL);
     274             : 
     275           0 :         pkg_debug(4, "Pkgdb: running '%s'", sql);
     276           0 :         if (sqlite3_prepare_v2(db->sqlite, sql, -1, &stmt, NULL) != SQLITE_OK) {
     277           0 :                 ERROR_SQLITE(db->sqlite, sql);
     278           0 :                 return (NULL);
     279             :         }
     280             : 
     281           0 :         sqlite3_bind_text(stmt, 1, req, -1, SQLITE_TRANSIENT);
     282             : 
     283           0 :         return (pkgdb_it_new_sqlite(db, stmt, PKG_INSTALLED, PKGDB_IT_FLAG_ONCE));
     284             : }
     285             : 
     286             : struct pkgdb_it *
     287           5 : pkgdb_query_provide(struct pkgdb *db, const char *req)
     288             : {
     289             :         sqlite3_stmt    *stmt;
     290           5 :         const char       sql[] = ""
     291             :                 "SELECT p.id, p.origin, p.name, p.name as uniqueid, "
     292             :                         "p.version, p.comment, p.desc, "
     293             :                         "p.message, p.arch, p.maintainer, p.www, "
     294             :                         "p.prefix, p.flatsize, p.time "
     295             :                         "FROM packages AS p, pkg_provides AS ps, provides AS s "
     296             :                         "WHERE p.id = ps.package_id "
     297             :                                 "AND ps.provide_id = s.id "
     298             :                                 "AND s.provide = ?1;";
     299             : 
     300           5 :         assert(db != NULL);
     301             : 
     302           5 :         pkg_debug(4, "Pkgdb: running '%s'", sql);
     303           5 :         if (sqlite3_prepare_v2(db->sqlite, sql, -1, &stmt, NULL) != SQLITE_OK) {
     304           0 :                 ERROR_SQLITE(db->sqlite, sql);
     305           0 :                 return (NULL);
     306             :         }
     307             : 
     308           5 :         sqlite3_bind_text(stmt, 1, req, -1, SQLITE_TRANSIENT);
     309             : 
     310           5 :         return (pkgdb_it_new_sqlite(db, stmt, PKG_INSTALLED, PKGDB_IT_FLAG_ONCE));
     311             : }
     312             : 
     313             : struct pkgdb_it *
     314          50 : pkgdb_repo_query(struct pkgdb *db, const char *pattern, match_t match,
     315             :     const char *repo)
     316             : {
     317             :         struct pkgdb_it *it;
     318             :         struct pkg_repo_it *rit;
     319             :         struct _pkg_repo_list_item *cur;
     320             : 
     321          50 :         it = pkgdb_it_new_repo(db);
     322          50 :         if (it == NULL)
     323           0 :                 return (NULL);
     324             : 
     325         100 :         LL_FOREACH(db->repos, cur) {
     326          50 :                 if (repo == NULL || strcasecmp(cur->repo->name, repo) == 0) {
     327          50 :                         rit = cur->repo->ops->query(cur->repo, pattern, match);
     328          50 :                         if (rit != NULL)
     329          50 :                                 pkgdb_it_repo_attach(it, rit);
     330             :                 }
     331             :         }
     332             : 
     333          50 :         return (it);
     334             : }
     335             : 
     336             : struct pkgdb_it *
     337           0 : pkgdb_repo_shlib_require(struct pkgdb *db, const char *require, const char *repo)
     338             : {
     339             :         struct pkgdb_it *it;
     340             :         struct pkg_repo_it *rit;
     341             :         struct _pkg_repo_list_item *cur;
     342             : 
     343           0 :         it = pkgdb_it_new_repo(db);
     344           0 :         if (it == NULL)
     345           0 :                 return (NULL);
     346             : 
     347           0 :         LL_FOREACH(db->repos, cur) {
     348           0 :                 if (repo == NULL || strcasecmp(cur->repo->name, repo) == 0) {
     349           0 :                         if (cur->repo->ops->shlib_required != NULL) {
     350           0 :                                 rit = cur->repo->ops->shlib_required(cur->repo, require);
     351           0 :                                 if (rit != NULL)
     352           0 :                                         pkgdb_it_repo_attach(it, rit);
     353             :                         }
     354             :                 }
     355             :         }
     356             : 
     357           0 :         return (it);
     358             : }
     359             : 
     360             : struct pkgdb_it *
     361           0 : pkgdb_repo_shlib_provide(struct pkgdb *db, const char *require, const char *repo)
     362             : {
     363             :         struct pkgdb_it *it;
     364             :         struct pkg_repo_it *rit;
     365             :         struct _pkg_repo_list_item *cur;
     366             : 
     367           0 :         it = pkgdb_it_new_repo(db);
     368           0 :         if (it == NULL)
     369           0 :                 return (NULL);
     370             : 
     371           0 :         LL_FOREACH(db->repos, cur) {
     372           0 :                 if (repo == NULL || strcasecmp(cur->repo->name, repo) == 0) {
     373           0 :                         if (cur->repo->ops->shlib_required != NULL) {
     374           0 :                                 rit = cur->repo->ops->shlib_provided(cur->repo, require);
     375           0 :                                 if (rit != NULL)
     376           0 :                                         pkgdb_it_repo_attach(it, rit);
     377             :                         }
     378             :                 }
     379             :         }
     380             : 
     381           0 :         return (it);
     382             : }
     383             : 
     384             : struct pkgdb_it *
     385           0 : pkgdb_repo_require(struct pkgdb *db, const char *require, const char *repo)
     386             : {
     387             :         struct pkgdb_it *it;
     388             :         struct pkg_repo_it *rit;
     389             :         struct _pkg_repo_list_item *cur;
     390             : 
     391           0 :         it = pkgdb_it_new_repo(db);
     392           0 :         if (it == NULL)
     393           0 :                 return (NULL);
     394             : 
     395           0 :         LL_FOREACH(db->repos, cur) {
     396           0 :                 if (repo == NULL || strcasecmp(cur->repo->name, repo) == 0) {
     397           0 :                         if (cur->repo->ops->required != NULL) {
     398           0 :                                 rit = cur->repo->ops->required(cur->repo, require);
     399           0 :                                 if (rit != NULL)
     400           0 :                                         pkgdb_it_repo_attach(it, rit);
     401             :                         }
     402             :                 }
     403             :         }
     404             : 
     405           0 :         return (it);
     406             : }
     407             : 
     408             : struct pkgdb_it *
     409           5 : pkgdb_repo_provide(struct pkgdb *db, const char *require, const char *repo)
     410             : {
     411             :         struct pkgdb_it *it;
     412             :         struct pkg_repo_it *rit;
     413             :         struct _pkg_repo_list_item *cur;
     414             : 
     415           5 :         it = pkgdb_it_new_repo(db);
     416           5 :         if (it == NULL)
     417           0 :                 return (NULL);
     418             : 
     419          10 :         LL_FOREACH(db->repos, cur) {
     420           5 :                 if (repo == NULL || strcasecmp(cur->repo->name, repo) == 0) {
     421           5 :                         if (cur->repo->ops->required != NULL) {
     422           5 :                                 rit = cur->repo->ops->provided(cur->repo, require);
     423           5 :                                 if (rit != NULL)
     424           5 :                                         pkgdb_it_repo_attach(it, rit);
     425             :                         }
     426             :                 }
     427             :         }
     428             : 
     429           5 :         return (it);
     430             : }
     431             : struct pkgdb_it *
     432           0 : pkgdb_repo_search(struct pkgdb *db, const char *pattern, match_t match,
     433             :     pkgdb_field field, pkgdb_field sort, const char *repo)
     434             : {
     435             :         struct pkgdb_it *it;
     436             :         struct pkg_repo_it *rit;
     437             :         struct _pkg_repo_list_item *cur;
     438             : 
     439           0 :         it = pkgdb_it_new_repo(db);
     440           0 :         if (it == NULL)
     441           0 :                 return (NULL);
     442             : 
     443           0 :         LL_FOREACH(db->repos, cur) {
     444           0 :                 if (repo == NULL || strcasecmp(cur->repo->name, repo) == 0) {
     445           0 :                         if (cur->repo->ops->search != NULL) {
     446           0 :                                 rit = cur->repo->ops->search(cur->repo, pattern, match,
     447             :                                         field, sort);
     448           0 :                                 if (rit != NULL)
     449           0 :                                         pkgdb_it_repo_attach(it, rit);
     450             :                         }
     451             :                 }
     452             :         }
     453             : 
     454           0 :         return (it);
     455             : }

Generated by: LCOV version 1.10