/[gentoo-projects]/portage-utils/qlist.c
Gentoo

Contents of /portage-utils/qlist.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.75 - (show annotations) (download) (as text)
Mon Apr 29 05:10:35 2013 UTC (20 months ago) by vapier
Branch: MAIN
Changes since 1.74: +40 -6 lines
File MIME type: text/x-csrc
qlist: initial support for prefix/suffix operators #369225 by Christian Ruppert

1 /*
2 * Copyright 2005-2010 Gentoo Foundation
3 * Distributed under the terms of the GNU General Public License v2
4 * $Header: /var/cvsroot/gentoo-projects/portage-utils/qlist.c,v 1.74 2012/11/10 05:28:25 vapier Exp $
5 *
6 * Copyright 2005-2010 Ned Ludd - <solar@gentoo.org>
7 * Copyright 2005-2010 Mike Frysinger - <vapier@gentoo.org>
8 * Copyright 2005 Martin Schlemmer - <azarah@gentoo.org>
9 */
10
11 #ifdef APPLET_qlist
12
13 #define QLIST_FLAGS "ISULcDeados" COMMON_FLAGS
14 static struct option const qlist_long_opts[] = {
15 {"installed", no_argument, NULL, 'I'},
16 {"slots", no_argument, NULL, 'S'},
17 {"columns", no_argument, NULL, 'c'},
18 {"umap", no_argument, NULL, 'U'},
19 {"dups", no_argument, NULL, 'D'},
20 {"showdebug", no_argument, NULL, 128},
21 {"exact", no_argument, NULL, 'e'},
22 {"all", no_argument, NULL, 'a'},
23 {"dir", no_argument, NULL, 'd'},
24 {"obj", no_argument, NULL, 'o'},
25 {"sym", no_argument, NULL, 's'},
26 /* {"file", a_argument, NULL, 'f'}, */
27 COMMON_LONG_OPTS
28 };
29 static const char * const qlist_opts_help[] = {
30 "Just show installed packages",
31 "Display installed packages with slots",
32 "Display column view",
33 "Display installed packages with flags used",
34 "Only show package dups",
35 "Show /usr/lib/debug files",
36 "Exact match (only CAT/PN or PN without PV)",
37 "Show every installed package",
38 "Only show directories",
39 "Only show objects",
40 "Only show symlinks",
41 /* "query filename for pkgname", */
42 COMMON_OPTS_HELP
43 };
44 static const char qlist_rcsid[] = "$Id: qlist.c,v 1.74 2012/11/10 05:28:25 vapier Exp $";
45 #define qlist_usage(ret) usage(ret, QLIST_FLAGS, qlist_long_opts, qlist_opts_help, lookup_applet_idx("qlist"))
46
47 _q_static queue *filter_dups(queue *sets)
48 {
49 queue *ll = NULL;
50 queue *dups = NULL;
51 queue *list = NULL;
52
53 for (list = sets; list != NULL; list = list->next) {
54 for (ll = sets; ll != NULL; ll = ll->next) {
55 if ((strcmp(ll->name, list->name) == 0) && (strcmp(ll->item, list->item) != 0)) {
56 int ok = 0;
57 dups = del_set(ll->item, dups, &ok);
58 ok = 0;
59 dups = add_set(ll->item, ll->item, dups);
60 }
61 }
62 }
63 return dups;
64 }
65
66 _q_static char *q_vdb_pkg_eat(q_vdb_pkg_ctx *pkg_ctx, const char *item)
67 {
68 static char buf[_Q_PATH_MAX];
69
70 eat_file_at(pkg_ctx->fd, item, buf, sizeof(buf));
71 rmspace(buf);
72
73 return buf;
74 }
75
76 static char *grab_pkg_umap(const char *CAT, const char *PV)
77 {
78 static char umap[BUFSIZ];
79 char *use = NULL;
80 char *iuse = NULL;
81 int use_argc = 0, iuse_argc = 0;
82 char **use_argv = NULL, **iuse_argv = NULL;
83 queue *ll = NULL;
84 queue *sets = NULL;
85 int i, u;
86
87 if ((use = grab_vdb_item("USE", CAT, PV)) == NULL)
88 return NULL;
89
90 memset(umap, 0, sizeof(umap)); /* reset the buffer */
91
92 /* grab_vdb is a static function so save it to memory right away */
93 makeargv(use, &use_argc, &use_argv);
94 if ((iuse = grab_vdb_item("IUSE", CAT, PV)) != NULL) {
95 for (i = 0; i < (int)strlen(iuse); i++)
96 if (iuse[i] == '+' || iuse[i] == '-')
97 iuse[i] = ' ';
98 makeargv(iuse, &iuse_argc, &iuse_argv);
99 for (u = 1; u < use_argc; u++) {
100 for (i = 1; i < iuse_argc; i++) {
101 if (strcmp(use_argv[u], iuse_argv[i]) == 0) {
102 strncat(umap, use_argv[u], sizeof(umap)-strlen(umap)-1);
103 strncat(umap, " ", sizeof(umap)-strlen(umap)-1);
104 }
105 }
106 }
107 freeargv(iuse_argc, iuse_argv);
108 }
109 freeargv(use_argc, use_argv);
110
111 /* filter out the dup use flags */
112 use_argc = 0; use_argv = NULL;
113 makeargv(umap, &use_argc, &use_argv);
114 for (i = 1; i < use_argc; i++) {
115 int ok = 0;
116 sets = del_set(use_argv[i], sets, &ok);
117 sets = add_set(use_argv[i], use_argv[i], sets);
118 }
119 memset(umap, 0, sizeof(umap)); /* reset the buffer */
120 strcpy(umap, "");
121 for (ll = sets; ll != NULL; ll = ll->next) {
122 strncat(umap, ll->name, sizeof(umap)-strlen(umap)-1);
123 strncat(umap, " ", sizeof(umap)-strlen(umap)-1);
124 }
125 freeargv(use_argc, use_argv);
126 free_sets(sets);
127 /* end filter */
128
129 return umap;
130 }
131
132 static const char *umapstr(char display, const char *cat, const char *name)
133 {
134 static char buf[BUFSIZ];
135 char *umap = NULL;
136
137 buf[0] = '\0';
138 if (!display)
139 return buf;
140 if ((umap = grab_pkg_umap(cat, name)) == NULL)
141 return buf;
142 rmspace(umap);
143 if (!strlen(umap))
144 return buf;
145 snprintf(buf, sizeof(buf), " %s%s%s%s%s", quiet ? "": "(", RED, umap, NORM, quiet ? "": ")");
146 return buf;
147 }
148
149 _q_static bool
150 qlist_match(q_vdb_pkg_ctx *pkg_ctx, const char *name, depend_atom **name_atom, bool exact)
151 {
152 const char *catname = pkg_ctx->cat_ctx->name;
153 const char *pkgname = pkg_ctx->name;
154 char buf[_Q_PATH_MAX];
155 char swap[_Q_PATH_MAX];
156 const char *uslot;
157 depend_atom *atom;
158
159 uslot = strchr(name, ':');
160 if (uslot) {
161 ++uslot;
162 if (!pkg_ctx->slot)
163 pkg_ctx->slot = q_vdb_pkg_eat(pkg_ctx, "SLOT");
164 }
165
166 /* maybe they're using a version range */
167 switch (name[0]) {
168 case '=':
169 case '>':
170 case '<':
171 case '~':
172 snprintf(buf, sizeof(buf), "%s/%s%c%s", catname, pkgname,
173 pkg_ctx->slot ? ':' : '\0', pkg_ctx->slot ? : "");
174 if ((atom = atom_explode(buf)) == NULL) {
175 warn("invalid atom %s", buf);
176 return false;
177 }
178
179 depend_atom *_atom = NULL;
180 if (!name_atom)
181 name_atom = &_atom;
182 if (!*name_atom) {
183 if ((*name_atom = atom_explode(name)) == NULL) {
184 atom_implode(atom);
185 warn("invalid atom %s", name);
186 return false;
187 }
188 }
189
190 bool ret = atom_compare(atom, *name_atom) == EQUAL;
191 atom_implode(atom);
192 return ret;
193 }
194
195 if (uslot) {
196 /* require exact match on SLOTs */
197 if (strcmp(pkg_ctx->slot, uslot) != 0)
198 return false;
199 }
200
201 /* printf("buf=%s:%s\n", buf,grab_vdb_item("SLOT", catname, pkgname)); */
202 if (exact) {
203 snprintf(buf, sizeof(buf), "%s/%s:%s", catname, pkgname, pkg_ctx->slot);
204
205 /* exact match: CAT/PN-PVR[:SLOT] */
206 if (strcmp(name, buf) == 0)
207 return true;
208 /* exact match: PN-PVR[:SLOT] */
209 if (strcmp(name, strstr(buf, "/") + 1) == 0)
210 return true;
211
212 /* let's try exact matching w/out the PV */
213 if ((atom = atom_explode(buf)) == NULL) {
214 warn("invalid atom %s", buf);
215 return false;
216 }
217 if (uslot)
218 snprintf(swap, sizeof(swap), "%s/%s:%s",
219 atom->CATEGORY, atom->PN, atom->SLOT);
220 else
221 snprintf(swap, sizeof(swap), "%s/%s",
222 atom->CATEGORY, atom->PN);
223 atom_implode(atom);
224 /* exact match: CAT/PN[:SLOT] */
225 if (strcmp(name, swap) == 0)
226 return true;
227 /* exact match: PN[:SLOT] */
228 if (strcmp(name, strstr(swap, "/") + 1) == 0)
229 return true;
230 } else {
231 size_t ulen;
232 if (uslot)
233 ulen = uslot - name - 1;
234 else
235 ulen = strlen(name);
236 snprintf(buf, sizeof(buf), "%s/%s", catname, pkgname);
237 /* partial leading match: CAT/PN-PVR */
238 if (strncmp(name, buf, ulen) == 0)
239 return true;
240 /* partial leading match: PN-PVR */
241 if (strncmp(name, pkgname, ulen) == 0)
242 return true;
243 /* try again but with regexps */
244 if (rematch(name, buf, REG_EXTENDED) == 0)
245 return true;
246 if (rematch(name, pkgname, REG_EXTENDED) == 0)
247 return true;
248 }
249
250 return false;
251 }
252
253 struct qlist_opt_state {
254 int argc;
255 char **argv;
256 depend_atom **atoms;
257 bool exact;
258 bool all;
259 bool just_pkgname;
260 bool dups_only;
261 bool show_dir;
262 bool show_obj;
263 bool show_sym;
264 bool show_slots;
265 bool show_umap;
266 bool show_dbg;
267 bool columns;
268 queue *sets;
269 char *buf;
270 size_t buflen;
271 };
272
273 _q_static int qlist_cb(q_vdb_pkg_ctx *pkg_ctx, void *priv)
274 {
275 struct qlist_opt_state *state = priv;
276 int i;
277 FILE *fp;
278 const char *catname = pkg_ctx->cat_ctx->name;
279 const char *pkgname = pkg_ctx->name;
280
281 /* see if this cat/pkg is requested */
282 for (i = optind; i < state->argc; ++i)
283 if (qlist_match(pkg_ctx, state->argv[i], &state->atoms[i - optind], state->exact))
284 break;
285 if ((i == state->argc) && (state->argc != optind))
286 return 0;
287
288 if (state->just_pkgname) {
289 depend_atom *atom;
290 if (state->dups_only) {
291 char swap[_Q_PATH_MAX];
292 atom = atom_explode(pkgname);
293 snprintf(state->buf, state->buflen, "%s/%s", catname, atom->P);
294 snprintf(swap, sizeof(swap), "%s/%s", catname, atom->PN);
295 state->sets = add_set(swap, state->buf, state->sets);
296 atom_implode(atom);
297 return 0;
298 }
299 atom = (verbose ? NULL : atom_explode(pkgname));
300 if ((state->all + state->just_pkgname) < 2) {
301 if (state->show_slots && !pkg_ctx->slot)
302 pkg_ctx->slot = q_vdb_pkg_eat(pkg_ctx, "SLOT");
303 /* display it */
304 printf("%s%s/%s%s%s%s%s%s%s%s%s%s\n", BOLD, catname, BLUE,
305 (!state->columns ? (atom ? atom->PN : pkgname) : atom->PN),
306 (state->columns ? " " : ""), (state->columns ? atom->PV : ""),
307 NORM, YELLOW, state->show_slots ? ":" : "", state->show_slots ? pkg_ctx->slot : "", NORM,
308 umapstr(state->show_umap, catname, pkgname));
309 }
310 if (atom)
311 atom_implode(atom);
312
313 if (!state->all)
314 return 0;
315 }
316
317 if (verbose > 1)
318 printf("%s%s/%s%s%s\n%sCONTENTS%s:\n", BOLD, catname, BLUE, pkgname, NORM, DKBLUE, NORM);
319
320 fp = q_vdb_pkg_fopenat_ro(pkg_ctx, "CONTENTS");
321 if (fp == NULL)
322 return 0;
323
324 while (getline(&state->buf, &state->buflen, fp) != -1) {
325 contents_entry *e;
326
327 e = contents_parse_line(state->buf);
328 if (!e)
329 continue;
330
331 if (!state->show_dbg) {
332 if (!strncmp(e->name, "/usr/lib/debug", 14) &&
333 (e->name[14] == '/' || e->name[14] == '\0'))
334 continue;
335 }
336
337 switch (e->type) {
338 case CONTENTS_DIR:
339 if (state->show_dir)
340 printf("%s%s%s/\n", verbose > 1 ? YELLOW : "" , e->name, verbose > 1 ? NORM : "");
341 break;
342 case CONTENTS_OBJ:
343 if (state->show_obj)
344 printf("%s%s%s\n", verbose > 1 ? WHITE : "" , e->name, verbose > 1 ? NORM : "");
345 break;
346 case CONTENTS_SYM:
347 if (state->show_sym) {
348 if (verbose)
349 printf("%s%s -> %s%s\n", verbose > 1 ? CYAN : "", e->name, e->sym_target, NORM);
350 else
351 printf("%s\n", e->name);
352 }
353 break;
354 }
355 }
356 fclose(fp);
357
358 return 0;
359 }
360
361 int qlist_main(int argc, char **argv)
362 {
363 struct qlist_opt_state state = {
364 .argc = argc,
365 .argv = argv,
366 .exact = false,
367 .all = false,
368 .just_pkgname = false,
369 .dups_only = false,
370 .show_dir = false,
371 .show_obj = false,
372 .show_sym = false,
373 .show_slots = false,
374 .show_umap = false,
375 .show_dbg = false,
376 .columns = false,
377 .sets = NULL,
378 .buflen = _Q_PATH_MAX,
379 };
380 int i, ret;
381
382 DBG("argc=%d argv[0]=%s argv[1]=%s",
383 argc, argv[0], argc > 1 ? argv[1] : "NULL?");
384
385 while ((i = GETOPT_LONG(QLIST, qlist, "")) != -1) {
386 switch (i) {
387 COMMON_GETOPTS_CASES(qlist)
388 case 'a': state.all = true;
389 case 'I': state.just_pkgname = true; break;
390 case 'S': state.just_pkgname = state.show_slots = true; break;
391 case 'U': state.just_pkgname = state.show_umap = true; break;
392 case 'e': state.exact = true; break;
393 case 'd': state.show_dir = true; break;
394 case 128: state.show_dbg = true; break;
395 case 'o': state.show_obj = true; break;
396 case 's': state.show_sym = true; break;
397 case 'D': state.dups_only = state.exact = state.just_pkgname = true; break;
398 case 'c': state.columns = true; break;
399 case 'f': break;
400 }
401 }
402 if (state.columns) verbose = 0; /* if not set to zero; atom wont be exploded; segv */
403 /* default to showing syms and objs */
404 if (!state.show_dir && !state.show_obj && !state.show_sym)
405 state.show_obj = state.show_sym = true;
406 if (argc == optind && !state.just_pkgname)
407 qlist_usage(EXIT_FAILURE);
408
409 state.buf = xmalloc(state.buflen);
410 state.atoms = xcalloc(argc - optind, sizeof(*state.atoms));
411 ret = q_vdb_foreach_pkg_sorted(qlist_cb, &state);
412
413 if (state.dups_only) {
414 char last[126];
415 depend_atom *atom;
416 queue *ll, *dups = filter_dups(state.sets);
417 last[0] = 0;
418
419 for (ll = dups; ll != NULL; ll = ll->next) {
420 int ok = 1;
421 atom = atom_explode(ll->item);
422 if (strcmp(last, atom->PN) == 0)
423 if (!verbose)
424 ok = 0;
425 strncpy(last, atom->PN, sizeof(last));
426 if (ok) {
427 char *slot = NULL;
428 if (state.show_slots)
429 slot = grab_vdb_item("SLOT", atom->CATEGORY, atom->P);
430 printf("%s%s/%s%s%s%s%s%s%s%s%s", BOLD, atom->CATEGORY, BLUE,
431 (!state.columns ? (verbose ? atom->P : atom->PN) : atom->PN),
432 (state.columns ? " " : ""), (state.columns ? atom->PV : ""),
433 NORM, YELLOW, slot ? ":" : "", slot ? slot : "", NORM);
434 puts(umapstr(state.show_umap, atom->CATEGORY, atom->P));
435 }
436 atom_implode(atom);
437 }
438 free_sets(dups);
439 free_sets(state.sets);
440 }
441
442 return ret;
443 }
444
445 #else
446 DEFINE_APPLET_STUB(qlist)
447 #endif

  ViewVC Help
Powered by ViewVC 1.1.20