1 |
commit: 10729f3630faaf79d2e4eaf77ea4bc957fa8c8aa |
2 |
Author: Fabian Groffen <grobian <AT> gentoo <DOT> org> |
3 |
AuthorDate: Sun Dec 29 12:27:21 2019 +0000 |
4 |
Commit: Fabian Groffen <grobian <AT> gentoo <DOT> org> |
5 |
CommitDate: Sun Dec 29 12:27:21 2019 +0000 |
6 |
URL: https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=10729f36 |
7 |
|
8 |
qlist: add support for listing contents from binpkgs |
9 |
|
10 |
Read CONTENTS straight out of the xpak archive to provide the same |
11 |
listing capabilities as for VDB. |
12 |
|
13 |
Signed-off-by: Fabian Groffen <grobian <AT> gentoo.org> |
14 |
|
15 |
configure.ac | 3 ++- |
16 |
qlist.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- |
17 |
2 files changed, 66 insertions(+), 5 deletions(-) |
18 |
|
19 |
diff --git a/configure.ac b/configure.ac |
20 |
index 0577d07..0efdf3e 100644 |
21 |
--- a/configure.ac |
22 |
+++ b/configure.ac |
23 |
@@ -19,7 +19,8 @@ LT_INIT |
24 |
AC_SUBST([LIBTOOL_DEPS]) |
25 |
|
26 |
AC_CHECK_FUNCS_ONCE(m4_flatten([ |
27 |
- scandirat |
28 |
+ fmemopen |
29 |
+ scandirat |
30 |
])) |
31 |
|
32 |
AC_ARG_WITH([eprefix], [AS_HELP_STRING([--with-eprefix], [path for Gentoo/Prefix project])]) |
33 |
|
34 |
diff --git a/qlist.c b/qlist.c |
35 |
index 30c0c6f..3f20ced 100644 |
36 |
--- a/qlist.c |
37 |
+++ b/qlist.c |
38 |
@@ -19,6 +19,7 @@ |
39 |
#include "atom.h" |
40 |
#include "contents.h" |
41 |
#include "tree.h" |
42 |
+#include "xpak.h" |
43 |
#include "xregex.h" |
44 |
|
45 |
#define QLIST_FLAGS "IkSRUcDedosF:" COMMON_FLAGS |
46 |
@@ -315,6 +316,7 @@ struct qlist_opt_state { |
47 |
depend_atom **atoms; |
48 |
bool exact:1; |
49 |
bool all:1; |
50 |
+ bool do_binpkgs:1; |
51 |
bool just_pkgname:1; |
52 |
bool show_dir:1; |
53 |
bool show_obj:1; |
54 |
@@ -327,6 +329,33 @@ struct qlist_opt_state { |
55 |
const char *fmt; |
56 |
}; |
57 |
|
58 |
+struct qlist_xpakcbctx { |
59 |
+ const char *key; |
60 |
+ char *retdata; |
61 |
+ size_t retlen; |
62 |
+}; |
63 |
+ |
64 |
+static void |
65 |
+_qlist_xpakcb( |
66 |
+ void *ctx, |
67 |
+ char *pathname, |
68 |
+ int pathname_len, |
69 |
+ int data_offset, |
70 |
+ int data_len, |
71 |
+ char *data) |
72 |
+{ |
73 |
+ struct qlist_xpakcbctx *xctx = ctx; |
74 |
+ (void)pathname_len; |
75 |
+ |
76 |
+ /* see if this path matches what we're looking for */ |
77 |
+ if (strcmp(pathname, xctx->key) != 0) |
78 |
+ return; |
79 |
+ |
80 |
+ xctx->retdata = xrealloc(xctx->retdata, data_len + 1); |
81 |
+ memcpy(xctx->retdata, data + data_offset, data_len + 1); |
82 |
+ xctx->retlen = data_len; |
83 |
+} |
84 |
+ |
85 |
static int |
86 |
qlist_cb(tree_pkg_ctx *pkg_ctx, void *priv) |
87 |
{ |
88 |
@@ -334,6 +363,11 @@ qlist_cb(tree_pkg_ctx *pkg_ctx, void *priv) |
89 |
int i; |
90 |
FILE *fp; |
91 |
depend_atom *atom; |
92 |
+ struct qlist_xpakcbctx cbctx = { |
93 |
+ .key = "CONTENTS", |
94 |
+ .retdata = NULL, |
95 |
+ .retlen = 0, |
96 |
+ }; |
97 |
|
98 |
/* see if this cat/pkg is requested */ |
99 |
if (!state->all) { |
100 |
@@ -358,7 +392,31 @@ qlist_cb(tree_pkg_ctx *pkg_ctx, void *priv) |
101 |
printf("%s %sCONTENTS%s:\n", |
102 |
atom_format(state->fmt, atom), DKBLUE, NORM); |
103 |
|
104 |
- fp = tree_pkg_vdb_fopenat_ro(pkg_ctx, "CONTENTS"); |
105 |
+ if (state->do_binpkgs) { |
106 |
+ char xpak[_Q_PATH_MAX]; |
107 |
+ int ret; |
108 |
+ snprintf(xpak, sizeof(xpak), "%s/%s/%s/%s-%s.tbz2", |
109 |
+ portroot, pkgdir, atom->CATEGORY, atom->PN, |
110 |
+ atom->PR_int > 0 ? atom->PVR : atom->PV); |
111 |
+ ret = xpak_extract(xpak, &cbctx, &_qlist_xpakcb); |
112 |
+ if (ret != 0 || cbctx.retdata == NULL) |
113 |
+ fp = NULL; |
114 |
+ else |
115 |
+#ifdef HAVE_FMEMOPEN |
116 |
+ fp = fmemopen(cbctx.retdata, cbctx.retlen, "r"); |
117 |
+#else |
118 |
+ { |
119 |
+ /* resort to writing a file in tmpspace */ |
120 |
+ fp = tmpfile(); |
121 |
+ if (fp != NULL) { |
122 |
+ fwrite(cbctx.retdata, 1, cbctx.retlen, fp); |
123 |
+ fseek(fp, 0, SEEK_SET); |
124 |
+ } |
125 |
+ } |
126 |
+#endif |
127 |
+ } else { |
128 |
+ fp = tree_pkg_vdb_fopenat_ro(pkg_ctx, "CONTENTS"); |
129 |
+ } |
130 |
if (fp == NULL) |
131 |
return 1; |
132 |
|
133 |
@@ -398,6 +456,8 @@ qlist_cb(tree_pkg_ctx *pkg_ctx, void *priv) |
134 |
} |
135 |
} |
136 |
fclose(fp); |
137 |
+ if (state->do_binpkgs && cbctx.retdata != NULL) |
138 |
+ free(cbctx.retdata); |
139 |
|
140 |
return 1; |
141 |
} |
142 |
@@ -410,13 +470,13 @@ int qlist_main(int argc, char **argv) |
143 |
int show_slots = 0; |
144 |
bool show_repo = false; |
145 |
bool do_columns = false; |
146 |
- bool do_binpkgs = false; |
147 |
char qfmt[128]; |
148 |
struct qlist_opt_state state = { |
149 |
.argc = argc, |
150 |
.argv = argv, |
151 |
.exact = false, |
152 |
.all = false, |
153 |
+ .do_binpkgs = false, |
154 |
.just_pkgname = false, |
155 |
.show_dir = false, |
156 |
.show_obj = false, |
157 |
@@ -432,7 +492,7 @@ int qlist_main(int argc, char **argv) |
158 |
switch (i) { |
159 |
COMMON_GETOPTS_CASES(qlist) |
160 |
case 'I': state.just_pkgname = true; break; |
161 |
- case 'k': do_binpkgs = true; break; |
162 |
+ case 'k': state.do_binpkgs = true; break; |
163 |
case 'S': state.just_pkgname = true; show_slots++; break; |
164 |
case 'R': state.just_pkgname = show_repo = true; break; |
165 |
case 'U': state.just_pkgname = state.show_umap = true; break; |
166 |
@@ -488,7 +548,7 @@ int qlist_main(int argc, char **argv) |
167 |
state.buf = xmalloc(state.buflen); |
168 |
state.atoms = xcalloc(argc - optind, sizeof(*state.atoms)); |
169 |
ret = 1; |
170 |
- if (do_binpkgs) |
171 |
+ if (state.do_binpkgs) |
172 |
vdb = tree_open_binpkg(portroot, pkgdir); |
173 |
else |
174 |
vdb = tree_open_vdb(portroot, portvdb); |