PageRenderTime 34ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/libpkg/pkgdb_query.c

https://gitlab.com/tunixman/pkg
C | 455 lines | 356 code | 66 blank | 33 comment | 117 complexity | 5e116abe26ee71ce1362fbf366a67d01 MD5 | raw file
  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. #ifdef HAVE_CONFIG_H
  35. #include "pkg_config.h"
  36. #endif
  37. #include <assert.h>
  38. #include <errno.h>
  39. #include <regex.h>
  40. #include <grp.h>
  41. #ifdef HAVE_LIBUTIL_H
  42. #include <libutil.h>
  43. #endif
  44. #include <stdlib.h>
  45. #include <stdio.h>
  46. #include <stdbool.h>
  47. #include <string.h>
  48. #include <unistd.h>
  49. #include <signal.h>
  50. #include <sqlite3.h>
  51. #include "pkg.h"
  52. #include "private/event.h"
  53. #include "private/pkg.h"
  54. #include "private/pkgdb.h"
  55. #include "private/utils.h"
  56. const char *
  57. pkgdb_get_pattern_query(const char *pattern, match_t match)
  58. {
  59. char *checkorigin = NULL;
  60. char *checkuid = NULL;
  61. const char *comp = NULL;
  62. if (pattern != NULL) {
  63. checkuid = strchr(pattern, '~');
  64. if (checkuid == NULL)
  65. checkorigin = strchr(pattern, '/');
  66. }
  67. switch (match) {
  68. case MATCH_ALL:
  69. comp = "";
  70. break;
  71. case MATCH_EXACT:
  72. if (pkgdb_case_sensitive()) {
  73. if (checkuid == NULL) {
  74. if (checkorigin == NULL)
  75. comp = " WHERE name = ?1 "
  76. "OR (name = SPLIT_VERSION('name', ?1) AND "
  77. " version = SPLIT_VERSION('version', ?1))";
  78. else
  79. comp = " WHERE origin = ?1";
  80. } else {
  81. comp = " WHERE name = ?1";
  82. }
  83. } else {
  84. if (checkuid == NULL) {
  85. if (checkorigin == NULL)
  86. comp = " WHERE name = ?1 COLLATE NOCASE "
  87. "OR (name = SPLIT_VERSION('name', ?1) COLLATE NOCASE AND "
  88. " version = SPLIT_VERSION('version', ?1))";
  89. else
  90. comp = " WHERE origin = ?1 COLLATE NOCASE";
  91. } else {
  92. comp = " WHERE name = ?1 COLLATE NOCASE";
  93. }
  94. }
  95. break;
  96. case MATCH_GLOB:
  97. if (checkuid == NULL) {
  98. if (checkorigin == NULL)
  99. comp = " WHERE name GLOB ?1 "
  100. "OR name || '-' || version GLOB ?1";
  101. else
  102. comp = " WHERE origin GLOB ?1";
  103. } else {
  104. comp = " WHERE name = ?1";
  105. }
  106. break;
  107. case MATCH_REGEX:
  108. if (checkuid == NULL) {
  109. if (checkorigin == NULL)
  110. comp = " WHERE name REGEXP ?1 "
  111. "OR name || '-' || version REGEXP ?1";
  112. else
  113. comp = " WHERE origin REGEXP ?1";
  114. } else {
  115. comp = " WHERE name = ?1";
  116. }
  117. break;
  118. case MATCH_CONDITION:
  119. comp = pattern;
  120. break;
  121. case MATCH_FTS:
  122. if (checkorigin == NULL)
  123. comp = " WHERE id IN (SELECT id FROM pkg_search WHERE name MATCH ?1)";
  124. else
  125. comp = " WHERE id IN (SELECT id FROM pkg_search WHERE origin MATCH ?1)";
  126. break;
  127. }
  128. return (comp);
  129. }
  130. struct pkgdb_it *
  131. pkgdb_query(struct pkgdb *db, const char *pattern, match_t match)
  132. {
  133. char sql[BUFSIZ];
  134. sqlite3_stmt *stmt;
  135. const char *comp = NULL;
  136. assert(db != NULL);
  137. if (match != MATCH_ALL && (pattern == NULL || pattern[0] == '\0'))
  138. return (NULL);
  139. comp = pkgdb_get_pattern_query(pattern, match);
  140. sqlite3_snprintf(sizeof(sql), sql,
  141. "SELECT id, origin, name, name as uniqueid, "
  142. "version, comment, desc, "
  143. "message, arch, maintainer, www, "
  144. "prefix, flatsize, licenselogic, automatic, "
  145. "locked, time, manifestdigest, vital "
  146. "FROM packages AS p%s "
  147. "ORDER BY p.name;", comp);
  148. pkg_debug(4, "Pkgdb: running '%s'", sql);
  149. if (sqlite3_prepare_v2(db->sqlite, sql, -1, &stmt, NULL) != SQLITE_OK) {
  150. ERROR_SQLITE(db->sqlite, sql);
  151. return (NULL);
  152. }
  153. if (match != MATCH_ALL && match != MATCH_CONDITION)
  154. sqlite3_bind_text(stmt, 1, pattern, -1, SQLITE_TRANSIENT);
  155. return (pkgdb_it_new_sqlite(db, stmt, PKG_INSTALLED, PKGDB_IT_FLAG_ONCE));
  156. }
  157. struct pkgdb_it *
  158. pkgdb_query_which(struct pkgdb *db, const char *path, bool glob)
  159. {
  160. sqlite3_stmt *stmt;
  161. char sql[BUFSIZ];
  162. assert(db != NULL);
  163. if (path == NULL)
  164. return (NULL);
  165. sqlite3_snprintf(sizeof(sql), sql,
  166. "SELECT p.id, p.origin, p.name, p.name as uniqueid, "
  167. "p.version, p.comment, p.desc, "
  168. "p.message, p.arch, p.maintainer, p.www, "
  169. "p.prefix, p.flatsize, p.time "
  170. "FROM packages AS p "
  171. "LEFT JOIN files AS f ON p.id = f.package_id "
  172. "WHERE f.path %s ?1 GROUP BY p.id;", glob ? "GLOB" : "=");
  173. pkg_debug(4, "Pkgdb: running '%s'", sql);
  174. if (sqlite3_prepare_v2(db->sqlite, sql, -1, &stmt, NULL) != SQLITE_OK) {
  175. ERROR_SQLITE(db->sqlite, sql);
  176. return (NULL);
  177. }
  178. sqlite3_bind_text(stmt, 1, path, -1, SQLITE_TRANSIENT);
  179. return (pkgdb_it_new_sqlite(db, stmt, PKG_INSTALLED, PKGDB_IT_FLAG_ONCE));
  180. }
  181. struct pkgdb_it *
  182. pkgdb_query_shlib_require(struct pkgdb *db, const char *shlib)
  183. {
  184. sqlite3_stmt *stmt;
  185. const char 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, pkg_shlibs_required AS ps, shlibs AS s "
  191. "WHERE p.id = ps.package_id "
  192. "AND ps.shlib_id = s.id "
  193. "AND s.name = ?1;";
  194. assert(db != NULL);
  195. pkg_debug(4, "Pkgdb: running '%s'", sql);
  196. if (sqlite3_prepare_v2(db->sqlite, sql, -1, &stmt, NULL) != SQLITE_OK) {
  197. ERROR_SQLITE(db->sqlite, sql);
  198. return (NULL);
  199. }
  200. sqlite3_bind_text(stmt, 1, shlib, -1, SQLITE_TRANSIENT);
  201. return (pkgdb_it_new_sqlite(db, stmt, PKG_INSTALLED, PKGDB_IT_FLAG_ONCE));
  202. }
  203. struct pkgdb_it *
  204. pkgdb_query_shlib_provide(struct pkgdb *db, const char *shlib)
  205. {
  206. sqlite3_stmt *stmt;
  207. const char sql[] = ""
  208. "SELECT p.id, p.origin, p.name, p.name as uniqueid, "
  209. "p.version, p.comment, p.desc, "
  210. "p.message, p.arch, p.maintainer, p.www, "
  211. "p.prefix, p.flatsize, p.manifestdigest, p.time "
  212. "FROM packages AS p, pkg_shlibs_provided AS ps, shlibs AS s "
  213. "WHERE p.id = ps.package_id "
  214. "AND ps.shlib_id = s.id "
  215. "AND s.name = ?1;";
  216. assert(db != NULL);
  217. pkg_debug(4, "Pkgdb: running '%s'", sql);
  218. if (sqlite3_prepare_v2(db->sqlite, sql, -1, &stmt, NULL) != SQLITE_OK) {
  219. ERROR_SQLITE(db->sqlite, sql);
  220. return (NULL);
  221. }
  222. sqlite3_bind_text(stmt, 1, shlib, -1, SQLITE_TRANSIENT);
  223. return (pkgdb_it_new_sqlite(db, stmt, PKG_INSTALLED, PKGDB_IT_FLAG_ONCE));
  224. }
  225. struct pkgdb_it *
  226. pkgdb_query_require(struct pkgdb *db, const char *req)
  227. {
  228. sqlite3_stmt *stmt;
  229. const char sql[] = ""
  230. "SELECT p.id, p.origin, p.name, p.name as uniqueid, "
  231. "p.version, p.comment, p.desc, "
  232. "p.message, p.arch, p.maintainer, p.www, "
  233. "p.prefix, p.flatsize, p.time "
  234. "FROM packages AS p, pkg_requires AS ps, requires AS s "
  235. "WHERE p.id = ps.package_id "
  236. "AND ps.require_id = s.id "
  237. "AND s.require = ?1;";
  238. assert(db != NULL);
  239. pkg_debug(4, "Pkgdb: running '%s'", sql);
  240. if (sqlite3_prepare_v2(db->sqlite, sql, -1, &stmt, NULL) != SQLITE_OK) {
  241. ERROR_SQLITE(db->sqlite, sql);
  242. return (NULL);
  243. }
  244. sqlite3_bind_text(stmt, 1, req, -1, SQLITE_TRANSIENT);
  245. return (pkgdb_it_new_sqlite(db, stmt, PKG_INSTALLED, PKGDB_IT_FLAG_ONCE));
  246. }
  247. struct pkgdb_it *
  248. pkgdb_query_provide(struct pkgdb *db, const char *req)
  249. {
  250. sqlite3_stmt *stmt;
  251. const char sql[] = ""
  252. "SELECT p.id, p.origin, p.name, p.name as uniqueid, "
  253. "p.version, p.comment, p.desc, "
  254. "p.message, p.arch, p.maintainer, p.www, "
  255. "p.prefix, p.flatsize, p.time "
  256. "FROM packages AS p, pkg_provides AS ps, provides AS s "
  257. "WHERE p.id = ps.package_id "
  258. "AND ps.provide_id = s.id "
  259. "AND s.provide = ?1;";
  260. assert(db != NULL);
  261. pkg_debug(4, "Pkgdb: running '%s'", sql);
  262. if (sqlite3_prepare_v2(db->sqlite, sql, -1, &stmt, NULL) != SQLITE_OK) {
  263. ERROR_SQLITE(db->sqlite, sql);
  264. return (NULL);
  265. }
  266. sqlite3_bind_text(stmt, 1, req, -1, SQLITE_TRANSIENT);
  267. return (pkgdb_it_new_sqlite(db, stmt, PKG_INSTALLED, PKGDB_IT_FLAG_ONCE));
  268. }
  269. struct pkgdb_it *
  270. pkgdb_repo_query(struct pkgdb *db, const char *pattern, match_t match,
  271. const char *repo)
  272. {
  273. struct pkgdb_it *it;
  274. struct pkg_repo_it *rit;
  275. struct _pkg_repo_list_item *cur;
  276. it = pkgdb_it_new_repo(db);
  277. if (it == NULL)
  278. return (NULL);
  279. LL_FOREACH(db->repos, cur) {
  280. if (repo == NULL || strcasecmp(cur->repo->name, repo) == 0) {
  281. rit = cur->repo->ops->query(cur->repo, pattern, match);
  282. if (rit != NULL)
  283. pkgdb_it_repo_attach(it, rit);
  284. }
  285. }
  286. return (it);
  287. }
  288. struct pkgdb_it *
  289. pkgdb_repo_shlib_require(struct pkgdb *db, const char *require, const char *repo)
  290. {
  291. struct pkgdb_it *it;
  292. struct pkg_repo_it *rit;
  293. struct _pkg_repo_list_item *cur;
  294. it = pkgdb_it_new_repo(db);
  295. if (it == NULL)
  296. return (NULL);
  297. LL_FOREACH(db->repos, cur) {
  298. if (repo == NULL || strcasecmp(cur->repo->name, repo) == 0) {
  299. if (cur->repo->ops->shlib_required != NULL) {
  300. rit = cur->repo->ops->shlib_required(cur->repo, require);
  301. if (rit != NULL)
  302. pkgdb_it_repo_attach(it, rit);
  303. }
  304. }
  305. }
  306. return (it);
  307. }
  308. struct pkgdb_it *
  309. pkgdb_repo_shlib_provide(struct pkgdb *db, const char *require, const char *repo)
  310. {
  311. struct pkgdb_it *it;
  312. struct pkg_repo_it *rit;
  313. struct _pkg_repo_list_item *cur;
  314. it = pkgdb_it_new_repo(db);
  315. if (it == NULL)
  316. return (NULL);
  317. LL_FOREACH(db->repos, cur) {
  318. if (repo == NULL || strcasecmp(cur->repo->name, repo) == 0) {
  319. if (cur->repo->ops->shlib_required != NULL) {
  320. rit = cur->repo->ops->shlib_provided(cur->repo, require);
  321. if (rit != NULL)
  322. pkgdb_it_repo_attach(it, rit);
  323. }
  324. }
  325. }
  326. return (it);
  327. }
  328. struct pkgdb_it *
  329. pkgdb_repo_require(struct pkgdb *db, const char *require, const char *repo)
  330. {
  331. struct pkgdb_it *it;
  332. struct pkg_repo_it *rit;
  333. struct _pkg_repo_list_item *cur;
  334. it = pkgdb_it_new_repo(db);
  335. if (it == NULL)
  336. return (NULL);
  337. LL_FOREACH(db->repos, cur) {
  338. if (repo == NULL || strcasecmp(cur->repo->name, repo) == 0) {
  339. if (cur->repo->ops->required != NULL) {
  340. rit = cur->repo->ops->required(cur->repo, require);
  341. if (rit != NULL)
  342. pkgdb_it_repo_attach(it, rit);
  343. }
  344. }
  345. }
  346. return (it);
  347. }
  348. struct pkgdb_it *
  349. pkgdb_repo_provide(struct pkgdb *db, const char *require, const char *repo)
  350. {
  351. struct pkgdb_it *it;
  352. struct pkg_repo_it *rit;
  353. struct _pkg_repo_list_item *cur;
  354. it = pkgdb_it_new_repo(db);
  355. if (it == NULL)
  356. return (NULL);
  357. LL_FOREACH(db->repos, cur) {
  358. if (repo == NULL || strcasecmp(cur->repo->name, repo) == 0) {
  359. if (cur->repo->ops->required != NULL) {
  360. rit = cur->repo->ops->provided(cur->repo, require);
  361. if (rit != NULL)
  362. pkgdb_it_repo_attach(it, rit);
  363. }
  364. }
  365. }
  366. return (it);
  367. }
  368. struct pkgdb_it *
  369. pkgdb_repo_search(struct pkgdb *db, const char *pattern, match_t match,
  370. pkgdb_field field, pkgdb_field sort, const char *repo)
  371. {
  372. struct pkgdb_it *it;
  373. struct pkg_repo_it *rit;
  374. struct _pkg_repo_list_item *cur;
  375. it = pkgdb_it_new_repo(db);
  376. if (it == NULL)
  377. return (NULL);
  378. LL_FOREACH(db->repos, cur) {
  379. if (repo == NULL || strcasecmp(cur->repo->name, repo) == 0) {
  380. if (cur->repo->ops->search != NULL) {
  381. rit = cur->repo->ops->search(cur->repo, pattern, match,
  382. field, sort);
  383. if (rit != NULL)
  384. pkgdb_it_repo_attach(it, rit);
  385. }
  386. }
  387. }
  388. return (it);
  389. }