Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/pkg
Path: blob/main/src/rquery.c
2065 views
1
/*-
2
* Copyright (c) 2011-2012 Baptiste Daroussin <[email protected]>
3
* Copyright (c) 2011-2012 Marin Atanasov Nikolov <[email protected]>
4
* Copyright (c) 2012-2013 Bryan Drewery <[email protected]>
5
* Copyright (c) 2013-2014 Matthew Seaman <[email protected]>
6
* All rights reserved.
7
*
8
* Redistribution and use in source and binary forms, with or without
9
* modification, are permitted provided that the following conditions
10
* are met:
11
* 1. Redistributions of source code must retain the above copyright
12
* notice, this list of conditions and the following disclaimer
13
* in this position and unchanged.
14
* 2. Redistributions in binary form must reproduce the above copyright
15
* notice, this list of conditions and the following disclaimer in the
16
* documentation and/or other materials provided with the distribution.
17
*
18
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
19
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
22
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
*/
29
30
#include <sys/types.h>
31
32
#include <ctype.h>
33
#include <err.h>
34
#include <getopt.h>
35
#include <inttypes.h>
36
#include <pkg.h>
37
#include <stdio.h>
38
#include <stdlib.h>
39
#include <string.h>
40
#include <unistd.h>
41
42
#include "pkgcli.h"
43
44
static struct query_flags accepted_rquery_flags[] = {
45
{ 'd', "nov", 1, PKG_LOAD_DEPS },
46
{ 'r', "nov", 1, PKG_LOAD_RDEPS },
47
{ 'C', "", 1, PKG_LOAD_CATEGORIES },
48
{ 'O', "kvdD", 1, PKG_LOAD_OPTIONS },
49
{ 'L', "", 1, PKG_LOAD_LICENSES },
50
{ 'B', "", 1, PKG_LOAD_SHLIBS_REQUIRED },
51
{ 'b', "", 1, PKG_LOAD_SHLIBS_PROVIDED },
52
{ 'A', "tv", 1, PKG_LOAD_ANNOTATIONS },
53
{ '?', "drCOLBbA", 1, PKG_LOAD_BASIC }, /* dbflags handled in analyse_query_string() */
54
{ '#', "drCOLBbA", 1, PKG_LOAD_BASIC }, /* dbflags handled in analyse_query_string() */
55
{ 's', "hb", 0, PKG_LOAD_BASIC },
56
{ 'n', "", 0, PKG_LOAD_BASIC },
57
{ 'e', "", 0, PKG_LOAD_BASIC },
58
{ 'v', "", 0, PKG_LOAD_BASIC },
59
{ 'o', "", 0, PKG_LOAD_BASIC },
60
{ 'R', "", 0, PKG_LOAD_BASIC },
61
{ 'p', "", 0, PKG_LOAD_BASIC },
62
{ 'm', "", 0, PKG_LOAD_BASIC },
63
{ 'c', "", 0, PKG_LOAD_BASIC },
64
{ 'w', "", 0, PKG_LOAD_BASIC },
65
{ 'l', "", 0, PKG_LOAD_BASIC },
66
{ 'q', "", 0, PKG_LOAD_BASIC },
67
{ 'M', "", 0, PKG_LOAD_BASIC }
68
};
69
70
void
71
usage_rquery(void)
72
{
73
fprintf(stderr, "Usage: pkg rquery [-r reponame] [-I|<query-format>] <pkg-name>\n");
74
fprintf(stderr, " pkg rquery [-a] [-r reponame] [-I|<query-format>]\n");
75
fprintf(stderr, " pkg rquery -e <evaluation> [-r reponame] <query-format>\n");
76
fprintf(stderr, " pkg rquery [-Cgix] [-r reponame] [-I|<query-format>] <pattern> <...>\n\n");
77
fprintf(stderr, "For more information see 'pkg help rquery.'\n");
78
}
79
80
static void
81
print_index(struct pkg *pkg, const char *portsdir)
82
{
83
84
pkg_printf(
85
"%n-%v|" /* PKGNAME */
86
"%S/%o|" /* PORTDIR */
87
"%p|" /* PREFIX */
88
"%c|" /* COMMENT */
89
"%S/%o/pkg-descr|" /* _DESCR */
90
"%m|" /* MAINTAINER */
91
"%C%{%Cn%| %}|" /* CATEGORIES */
92
"|" /* BUILD_DEPENDS */
93
"%d%{%dn-%dv%| %}|" /* RUN_DEPENDS */
94
"%w|" /* WWW */
95
"|" /* EXTRACT_DEPENDS */
96
"|" /* PATCH_DEPENDS */
97
"\n", /* FETCH_DEPENDS */
98
pkg, pkg, portsdir, pkg, pkg, pkg, portsdir, pkg, pkg, pkg, pkg,
99
pkg);
100
}
101
102
int
103
exec_rquery(int argc, char **argv)
104
{
105
struct pkgdb *db = NULL;
106
struct pkgdb_it *it = NULL;
107
struct pkg *pkg = NULL;
108
char *pkgname = NULL;
109
int query_flags = PKG_LOAD_BASIC;
110
match_t match = MATCH_EXACT;
111
int ch;
112
int ret = EPKG_OK;
113
int retcode = EXIT_SUCCESS;
114
int i;
115
char multiline = 0;
116
char *condition = NULL;
117
const char *condition_sql = NULL;
118
const char *portsdir;
119
xstring *sqlcond = NULL;
120
const unsigned int q_flags_len = NELEM(accepted_rquery_flags);
121
bool onematched = false;
122
bool old_quiet;
123
bool index_output = false;
124
c_charv_t reponames = vec_init();
125
126
struct option longopts[] = {
127
{ "all", no_argument, NULL, 'a' },
128
{ "case-sensitive", no_argument, NULL, 'C' },
129
{ "evaluate", required_argument, NULL, 'e' },
130
{ "glob", no_argument, NULL, 'g' },
131
{ "case-insensitive", no_argument, NULL, 'i' },
132
{ "index-line", no_argument, NULL, 'I' },
133
{ "repository", required_argument, NULL, 'r' },
134
{ "no-repo-update", no_argument, NULL, 'U' },
135
{ "regex", no_argument, NULL, 'x' },
136
{ NULL, 0, NULL, 0 },
137
};
138
139
portsdir = pkg_object_string(pkg_config_get("PORTSDIR"));
140
141
while ((ch = getopt_long(argc, argv, "+aCgiIxe:r:U", longopts, NULL)) != -1) {
142
switch (ch) {
143
case 'a':
144
match = MATCH_ALL;
145
break;
146
case 'C':
147
pkgdb_set_case_sensitivity(true);
148
break;
149
case 'e':
150
condition = optarg;
151
break;
152
case 'g':
153
match = MATCH_GLOB;
154
break;
155
case 'i':
156
pkgdb_set_case_sensitivity(false);
157
break;
158
case 'I':
159
index_output = true;
160
break;
161
case 'r':
162
vec_push(&reponames, optarg);
163
break;
164
case 'U':
165
auto_update = false;
166
break;
167
case 'x':
168
match = MATCH_REGEX;
169
break;
170
default:
171
usage_rquery();
172
return (EXIT_FAILURE);
173
}
174
}
175
176
argc -= optind;
177
argv += optind;
178
179
if (argc == 0 && !index_output) {
180
usage_rquery();
181
return (EXIT_FAILURE);
182
}
183
184
/* Default to all packages if no pkg provided */
185
if (!index_output) {
186
if (argc == 1 && match == MATCH_EXACT) {
187
match = MATCH_ALL;
188
} else if (((argc == 1) ^ (match == MATCH_ALL )) && condition == NULL) {
189
usage_rquery();
190
return (EXIT_FAILURE);
191
}
192
} else {
193
if (argc == 0)
194
match = MATCH_ALL;
195
}
196
197
if (!index_output && analyse_query_string(argv[0], accepted_rquery_flags, q_flags_len, &query_flags, &multiline) != EPKG_OK)
198
return (EXIT_FAILURE);
199
200
if (condition != NULL) {
201
sqlcond = xstring_new();
202
if (format_sql_condition(condition, sqlcond, true) != EPKG_OK) {
203
xstring_free(sqlcond);
204
return (EXIT_FAILURE);
205
}
206
}
207
208
ret = pkgdb_access2(PKGDB_MODE_READ, PKGDB_DB_REPO, &reponames);
209
if (ret == EPKG_ENOACCESS) {
210
warnx("Insufficient privileges to query the package database");
211
xstring_free(sqlcond);
212
return (EXIT_FAILURE);
213
} else if (ret != EPKG_OK) {
214
xstring_free(sqlcond);
215
return (EXIT_FAILURE);
216
}
217
218
/* first update the remote repositories if needed */
219
old_quiet = quiet;
220
quiet = true;
221
if (auto_update && (ret = pkgcli_update(false, false, &reponames)) != EPKG_OK) {
222
xstring_free(sqlcond);
223
return (ret);
224
}
225
quiet = old_quiet;
226
227
ret = pkgdb_open_all2(&db, PKGDB_REMOTE, &reponames);
228
if (ret != EPKG_OK) {
229
xstring_free(sqlcond);
230
return (EXIT_FAILURE);
231
}
232
pkg_drop_privileges();
233
234
if (index_output)
235
query_flags = PKG_LOAD_BASIC|PKG_LOAD_CATEGORIES|PKG_LOAD_DEPS;
236
237
if (sqlcond) {
238
fflush(sqlcond->fp);
239
condition_sql = sqlcond->buf;
240
}
241
if (match == MATCH_ALL) {
242
if ((it = pkgdb_repo_query_cond2(db, condition_sql, NULL, match, &reponames)) == NULL) {
243
xstring_free(sqlcond);
244
return (EXIT_FAILURE);
245
}
246
247
while ((ret = pkgdb_it_next(it, &pkg, query_flags)) == EPKG_OK) {
248
if (index_output)
249
print_index(pkg, portsdir);
250
else
251
print_query(pkg, argv[0], multiline);
252
}
253
254
if (ret != EPKG_END)
255
retcode = EXIT_FAILURE;
256
257
pkgdb_it_free(it);
258
} else {
259
for (i = (index_output ? 0 : 1); i < argc; i++) {
260
pkgname = argv[i];
261
262
if ((it = pkgdb_repo_query_cond2(db, condition_sql, pkgname, match, &reponames)) == NULL) {
263
xstring_free(sqlcond);
264
return (EXIT_FAILURE);
265
}
266
267
while ((ret = pkgdb_it_next(it, &pkg, query_flags)) == EPKG_OK) {
268
onematched = true;
269
if (index_output)
270
print_index(pkg, portsdir);
271
else
272
print_query(pkg, argv[0], multiline);
273
}
274
275
if (ret != EPKG_END) {
276
retcode = EXIT_FAILURE;
277
break;
278
}
279
280
pkgdb_it_free(it);
281
}
282
if (!onematched && retcode == EXIT_SUCCESS)
283
retcode = EXIT_FAILURE;
284
}
285
286
xstring_free(sqlcond);
287
pkg_free(pkg);
288
pkgdb_close(db);
289
290
return (retcode);
291
}
292
293