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

Contents of /portage-utils/qlist.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.74 - (show annotations) (download) (as text)
Sat Nov 10 05:28:25 2012 UTC (17 months, 1 week ago) by vapier
Branch: MAIN
Changes since 1.73: +4 -3 lines
File MIME type: text/x-csrc
qlist: handle leading - in IUSE flags #437974 by Alexandr Tiurin

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.73 2012/10/28 06:27:59 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.73 2012/10/28 06:27:59 vapier Exp $";
45 #define qlist_usage(ret) usage(ret, QLIST_FLAGS, qlist_long_opts, qlist_opts_help, lookup_applet_idx("qlist"))
46
47 queue *filter_dups(queue *sets);
48 queue *filter_dups(queue *sets)
49 {
50 queue *ll = NULL;
51 queue *dups = NULL;
52 queue *list = NULL;
53
54 for (list = sets; list != NULL; list = list->next) {
55 for (ll = sets; ll != NULL; ll = ll->next) {
56 if ((strcmp(ll->name, list->name) == 0) && (strcmp(ll->item, list->item) != 0)) {
57 int ok = 0;
58 dups = del_set(ll->item, dups, &ok);
59 ok = 0;
60 dups = add_set(ll->item, ll->item, dups);
61 }
62 }
63 }
64 return dups;
65 }
66
67 _q_static char *q_vdb_pkg_eat(q_vdb_pkg_ctx *pkg_ctx, const char *item)
68 {
69 static char buf[_Q_PATH_MAX];
70
71 eat_file_at(pkg_ctx->fd, item, buf, sizeof(buf));
72 rmspace(buf);
73
74 return buf;
75 }
76
77 static char *grab_pkg_umap(const char *CAT, const char *PV)
78 {
79 static char umap[BUFSIZ];
80 char *use = NULL;
81 char *iuse = NULL;
82 int use_argc = 0, iuse_argc = 0;
83 char **use_argv = NULL, **iuse_argv = NULL;
84 queue *ll = NULL;
85 queue *sets = NULL;
86 int i, u;
87
88 if ((use = grab_vdb_item("USE", CAT, PV)) == NULL)
89 return NULL;
90
91 memset(umap, 0, sizeof(umap)); /* reset the buffer */
92
93 /* grab_vdb is a static function so save it to memory right away */
94 makeargv(use, &use_argc, &use_argv);
95 if ((iuse = grab_vdb_item("IUSE", CAT, PV)) != NULL) {
96 for (i = 0; i < (int)strlen(iuse); i++)
97 if (iuse[i] == '+' || iuse[i] == '-')
98 iuse[i] = ' ';
99 makeargv(iuse, &iuse_argc, &iuse_argv);
100 for (u = 1; u < use_argc; u++) {
101 for (i = 1; i < iuse_argc; i++) {
102 if (strcmp(use_argv[u], iuse_argv[i]) == 0) {
103 strncat(umap, use_argv[u], sizeof(umap)-strlen(umap)-1);
104 strncat(umap, " ", sizeof(umap)-strlen(umap)-1);
105 }
106 }
107 }
108 freeargv(iuse_argc, iuse_argv);
109 }
110 freeargv(use_argc, use_argv);
111
112 /* filter out the dup use flags */
113 use_argc = 0; use_argv = NULL;
114 makeargv(umap, &use_argc, &use_argv);
115 for (i = 1; i < use_argc; i++) {
116 int ok = 0;
117 sets = del_set(use_argv[i], sets, &ok);
118 sets = add_set(use_argv[i], use_argv[i], sets);
119 }
120 memset(umap, 0, sizeof(umap)); /* reset the buffer */
121 strcpy(umap, "");
122 for (ll = sets; ll != NULL; ll = ll->next) {
123 strncat(umap, ll->name, sizeof(umap)-strlen(umap)-1);
124 strncat(umap, " ", sizeof(umap)-strlen(umap)-1);
125 }
126 freeargv(use_argc, use_argv);
127 free_sets(sets);
128 /* end filter */
129
130 return umap;
131 }
132
133 static const char *umapstr(char display, const char *cat, const char *name)
134 {
135 static char buf[BUFSIZ];
136 char *umap = NULL;
137
138 buf[0] = '\0';
139 if (!display)
140 return buf;
141 if ((umap = grab_pkg_umap(cat, name)) == NULL)
142 return buf;
143 rmspace(umap);
144 if (!strlen(umap))
145 return buf;
146 snprintf(buf, sizeof(buf), " %s%s%s%s%s", quiet ? "": "(", RED, umap, NORM, quiet ? "": ")");
147 return buf;
148 }
149
150 _q_static bool qlist_match(q_vdb_pkg_ctx *pkg_ctx, const char *name, 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 /* require exact match on SLOTs */
165 if (strcmp(pkg_ctx->slot, uslot) != 0)
166 return false;
167 }
168
169 /* printf("buf=%s:%s\n", buf,grab_vdb_item("SLOT", catname, pkgname)); */
170 if (exact) {
171 snprintf(buf, sizeof(buf), "%s/%s:%s", catname, pkgname, pkg_ctx->slot);
172
173 /* exact match: CAT/PN-PVR[:SLOT] */
174 if (strcmp(name, buf) == 0)
175 return true;
176 /* exact match: PN-PVR[:SLOT] */
177 if (strcmp(name, strstr(buf, "/") + 1) == 0)
178 return true;
179
180 /* let's try exact matching w/out the PV */
181 if ((atom = atom_explode(buf)) == NULL) {
182 warn("invalid atom %s", buf);
183 return false;
184 }
185 if (uslot)
186 snprintf(swap, sizeof(swap), "%s/%s:%s",
187 atom->CATEGORY, atom->PN, atom->SLOT);
188 else
189 snprintf(swap, sizeof(swap), "%s/%s",
190 atom->CATEGORY, atom->PN);
191 atom_implode(atom);
192 /* exact match: CAT/PN[:SLOT] */
193 if (strcmp(name, swap) == 0)
194 return true;
195 /* exact match: PN[:SLOT] */
196 if (strcmp(name, strstr(swap, "/") + 1) == 0)
197 return true;
198 } else {
199 size_t ulen;
200 if (uslot)
201 ulen = uslot - name - 1;
202 else
203 ulen = strlen(name);
204 snprintf(buf, sizeof(buf), "%s/%s", catname, pkgname);
205 /* partial leading match: CAT/PN-PVR */
206 if (strncmp(name, buf, ulen) == 0)
207 return true;
208 /* partial leading match: PN-PVR */
209 if (strncmp(name, pkgname, ulen) == 0)
210 return true;
211 /* try again but with regexps */
212 if (rematch(name, buf, REG_EXTENDED) == 0)
213 return true;
214 if (rematch(name, pkgname, REG_EXTENDED) == 0)
215 return true;
216 }
217
218 return false;
219 }
220
221 struct qlist_opt_state {
222 int argc;
223 char **argv;
224 bool exact;
225 bool all;
226 bool just_pkgname;
227 bool dups_only;
228 bool show_dir;
229 bool show_obj;
230 bool show_sym;
231 bool show_slots;
232 bool show_umap;
233 bool show_dbg;
234 bool columns;
235 queue *sets;
236 char *buf;
237 size_t buflen;
238 };
239
240 _q_static int qlist_cb(q_vdb_pkg_ctx *pkg_ctx, void *priv)
241 {
242 struct qlist_opt_state *state = priv;
243 int i;
244 FILE *fp;
245 const char *catname = pkg_ctx->cat_ctx->name;
246 const char *pkgname = pkg_ctx->name;
247
248 /* see if this cat/pkg is requested */
249 for (i = optind; i < state->argc; ++i)
250 if (qlist_match(pkg_ctx, state->argv[i], state->exact))
251 break;
252 if ((i == state->argc) && (state->argc != optind))
253 return 0;
254
255 if (state->just_pkgname) {
256 depend_atom *atom;
257 if (state->dups_only) {
258 char swap[_Q_PATH_MAX];
259 atom = atom_explode(pkgname);
260 snprintf(state->buf, state->buflen, "%s/%s", catname, atom->P);
261 snprintf(swap, sizeof(swap), "%s/%s", catname, atom->PN);
262 state->sets = add_set(swap, state->buf, state->sets);
263 atom_implode(atom);
264 return 0;
265 }
266 atom = (verbose ? NULL : atom_explode(pkgname));
267 if ((state->all + state->just_pkgname) < 2) {
268 if (state->show_slots && !pkg_ctx->slot)
269 pkg_ctx->slot = q_vdb_pkg_eat(pkg_ctx, "SLOT");
270 /* display it */
271 printf("%s%s/%s%s%s%s%s%s%s%s%s%s\n", BOLD, catname, BLUE,
272 (!state->columns ? (atom ? atom->PN : pkgname) : atom->PN),
273 (state->columns ? " " : ""), (state->columns ? atom->PV : ""),
274 NORM, YELLOW, state->show_slots ? ":" : "", state->show_slots ? pkg_ctx->slot : "", NORM,
275 umapstr(state->show_umap, catname, pkgname));
276 }
277 if (atom)
278 atom_implode(atom);
279
280 if (!state->all)
281 return 0;
282 }
283
284 if (verbose > 1)
285 printf("%s%s/%s%s%s\n%sCONTENTS%s:\n", BOLD, catname, BLUE, pkgname, NORM, DKBLUE, NORM);
286
287 fp = q_vdb_pkg_fopenat_ro(pkg_ctx, "CONTENTS");
288 if (fp == NULL)
289 return 0;
290
291 while (getline(&state->buf, &state->buflen, fp) != -1) {
292 contents_entry *e;
293
294 e = contents_parse_line(state->buf);
295 if (!e)
296 continue;
297
298 if (!state->show_dbg) {
299 if (!strncmp(e->name, "/usr/lib/debug", 14) &&
300 (e->name[14] == '/' || e->name[14] == '\0'))
301 continue;
302 }
303
304 switch (e->type) {
305 case CONTENTS_DIR:
306 if (state->show_dir)
307 printf("%s%s%s/\n", verbose > 1 ? YELLOW : "" , e->name, verbose > 1 ? NORM : "");
308 break;
309 case CONTENTS_OBJ:
310 if (state->show_obj)
311 printf("%s%s%s\n", verbose > 1 ? WHITE : "" , e->name, verbose > 1 ? NORM : "");
312 break;
313 case CONTENTS_SYM:
314 if (state->show_sym) {
315 if (verbose)
316 printf("%s%s -> %s%s\n", verbose > 1 ? CYAN : "", e->name, e->sym_target, NORM);
317 else
318 printf("%s\n", e->name);
319 }
320 break;
321 }
322 }
323 fclose(fp);
324
325 return 0;
326 }
327
328 int qlist_main(int argc, char **argv)
329 {
330 struct qlist_opt_state state = {
331 .argc = argc,
332 .argv = argv,
333 .exact = false,
334 .all = false,
335 .just_pkgname = false,
336 .dups_only = false,
337 .show_dir = false,
338 .show_obj = false,
339 .show_sym = false,
340 .show_slots = false,
341 .show_umap = false,
342 .show_dbg = false,
343 .columns = false,
344 .sets = NULL,
345 .buflen = _Q_PATH_MAX,
346 };
347 int i, ret;
348
349 DBG("argc=%d argv[0]=%s argv[1]=%s",
350 argc, argv[0], argc > 1 ? argv[1] : "NULL?");
351
352 while ((i = GETOPT_LONG(QLIST, qlist, "")) != -1) {
353 switch (i) {
354 COMMON_GETOPTS_CASES(qlist)
355 case 'a': state.all = true;
356 case 'I': state.just_pkgname = true; break;
357 case 'S': state.just_pkgname = state.show_slots = true; break;
358 case 'U': state.just_pkgname = state.show_umap = true; break;
359 case 'e': state.exact = true; break;
360 case 'd': state.show_dir = true; break;
361 case 128: state.show_dbg = true; break;
362 case 'o': state.show_obj = true; break;
363 case 's': state.show_sym = true; break;
364 case 'D': state.dups_only = state.exact = state.just_pkgname = true; break;
365 case 'c': state.columns = true; break;
366 case 'f': break;
367 }
368 }
369 if (state.columns) verbose = 0; /* if not set to zero; atom wont be exploded; segv */
370 /* default to showing syms and objs */
371 if (!state.show_dir && !state.show_obj && !state.show_sym)
372 state.show_obj = state.show_sym = true;
373 if (argc == optind && !state.just_pkgname)
374 qlist_usage(EXIT_FAILURE);
375
376 state.buf = xmalloc(state.buflen);
377 ret = q_vdb_foreach_pkg_sorted(qlist_cb, &state);
378
379 if (state.dups_only) {
380 char last[126];
381 depend_atom *atom;
382 queue *ll, *dups = filter_dups(state.sets);
383 last[0] = 0;
384
385 for (ll = dups; ll != NULL; ll = ll->next) {
386 int ok = 1;
387 atom = atom_explode(ll->item);
388 if (strcmp(last, atom->PN) == 0)
389 if (!verbose)
390 ok = 0;
391 strncpy(last, atom->PN, sizeof(last));
392 if (ok) {
393 char *slot = NULL;
394 if (state.show_slots)
395 slot = grab_vdb_item("SLOT", atom->CATEGORY, atom->P);
396 printf("%s%s/%s%s%s%s%s%s%s%s%s", BOLD, atom->CATEGORY, BLUE,
397 (!state.columns ? (verbose ? atom->P : atom->PN) : atom->PN),
398 (state.columns ? " " : ""), (state.columns ? atom->PV : ""),
399 NORM, YELLOW, slot ? ":" : "", slot ? slot : "", NORM);
400 puts(umapstr(state.show_umap, atom->CATEGORY, atom->P));
401 }
402 atom_implode(atom);
403 }
404 free_sets(dups);
405 free_sets(state.sets);
406 }
407
408 return ret;
409 }
410
411 #else
412 DEFINE_APPLET_STUB(qlist)
413 #endif

  ViewVC Help
Powered by ViewVC 1.1.20