Gentoo Archives: gentoo-commits

From: Fabian Groffen <grobian@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/portage-utils:master commit in: libq/
Date: Sun, 17 Nov 2019 15:12:42
Message-Id: 1574002860.b811b9afd740e8f4cc73f096e8c162d5d332aed2.grobian@gentoo
1 commit: b811b9afd740e8f4cc73f096e8c162d5d332aed2
2 Author: Fabian Groffen <grobian <AT> gentoo <DOT> org>
3 AuthorDate: Sun Nov 17 15:01:00 2019 +0000
4 Commit: Fabian Groffen <grobian <AT> gentoo <DOT> org>
5 CommitDate: Sun Nov 17 15:01:00 2019 +0000
6 URL: https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=b811b9af
7
8 libq/tree: add support for binpgks and Packages file
9
10 This allows to foreach binpkgs (without Packages file index) as well as
11 use the Packages file to loop over them.
12
13 Signed-off-by: Fabian Groffen <grobian <AT> gentoo.org>
14
15 libq/tree.c | 254 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
16 libq/tree.h | 13 +++-
17 2 files changed, 251 insertions(+), 16 deletions(-)
18
19 diff --git a/libq/tree.c b/libq/tree.c
20 index b0d0b5b..427281f 100644
21 --- a/libq/tree.c
22 +++ b/libq/tree.c
23 @@ -21,6 +21,7 @@
24 #include "scandirat.h"
25 #include "set.h"
26 #include "tree.h"
27 +#include "xpak.h"
28
29 #include <ctype.h>
30 #include <xalloc.h>
31 @@ -30,7 +31,7 @@ static int tree_pkg_compar(const void *l, const void *r);
32 static tree_ctx *
33 tree_open_int(const char *sroot, const char *tdir, bool quiet)
34 {
35 - tree_ctx *ctx = xmalloc(sizeof(*ctx));
36 + tree_ctx *ctx = xzalloc(sizeof(*ctx));
37
38 ctx->portroot_fd = open(sroot, O_RDONLY | O_CLOEXEC | O_PATH);
39 if (ctx->portroot_fd == -1) {
40 @@ -56,12 +57,8 @@ tree_open_int(const char *sroot, const char *tdir, bool quiet)
41 goto cv_error;
42
43 ctx->do_sort = false;
44 - ctx->cat_de = NULL;
45 ctx->catsortfunc = alphasort;
46 ctx->pkgsortfunc = tree_pkg_compar;
47 - ctx->repo = NULL;
48 - ctx->ebuilddir_ctx = NULL;
49 - ctx->ebuilddir_pkg_ctx = NULL;
50 return ctx;
51
52 cv_error:
53 @@ -130,6 +127,24 @@ tree_open_vdb(const char *sroot, const char *svdb)
54 return ret;
55 }
56
57 +static const char binpkg_packages[] = "Packages";
58 +tree_ctx *
59 +tree_open_binpkg(const char *sroot, const char *spkg)
60 +{
61 + tree_ctx *ret = tree_open_int(sroot, spkg, true);
62 + char buf[_Q_PATH_MAX];
63 +
64 + if (ret != NULL) {
65 + ret->cachetype = CACHE_BINPKGS;
66 +
67 + snprintf(buf, sizeof(buf), "%s%s/%s", sroot, spkg, binpkg_packages);
68 + if (eat_file(buf, &ret->pkgs, &ret->pkgslen))
69 + ret->cachetype = CACHE_PACKAGES;
70 + }
71 +
72 + return ret;
73 +}
74 +
75 void
76 tree_close(tree_ctx *ctx)
77 {
78 @@ -141,6 +156,8 @@ tree_close(tree_ctx *ctx)
79 scandir_free(ctx->cat_de, ctx->cat_cnt);
80 if (ctx->repo != NULL)
81 free(ctx->repo);
82 + if (ctx->pkgs != NULL)
83 + free(ctx->pkgs);
84 if (ctx->ebuilddir_ctx != NULL)
85 free(ctx->ebuilddir_ctx);
86 free(ctx);
87 @@ -443,6 +460,13 @@ tree_next_pkg(tree_cat_ctx *cat_ctx)
88 }
89 }
90 } while (ret == NULL);
91 + } else if (ctx->cachetype == CACHE_BINPKGS) {
92 + char *p = NULL;
93 + do {
94 + ret = tree_next_pkg_int(cat_ctx);
95 + } while (ret != NULL && (p = strstr(ret->name, ".tbz2")) == NULL);
96 + if (p != NULL)
97 + *p = '\0';
98 } else {
99 ret = tree_next_pkg_int(cat_ctx);
100 }
101 @@ -805,22 +829,96 @@ err:
102 return NULL;
103 }
104
105 +static void
106 +tree_read_file_binpkg_xpak_cb(
107 + void *ctx,
108 + char *pathname,
109 + int pathname_len,
110 + int data_offset,
111 + int data_len,
112 + char *data)
113 +{
114 + tree_pkg_meta *m = (tree_pkg_meta *)ctx;
115 + char **key;
116 + size_t pos;
117 + size_t len;
118 +
119 +#define match_path(K) \
120 + else if (pathname_len == (sizeof(#K) - 1) && strcmp(pathname, #K) == 0) \
121 + key = &m->K
122 + if (1 == 0); /* dummy for syntax */
123 + match_path(DEPEND);
124 + match_path(RDEPEND);
125 + match_path(SLOT);
126 + match_path(SRC_URI);
127 + match_path(RESTRICT);
128 + match_path(HOMEPAGE);
129 + match_path(DESCRIPTION);
130 + match_path(KEYWORDS);
131 + match_path(INHERITED);
132 + match_path(IUSE);
133 + match_path(CDEPEND);
134 + match_path(PDEPEND);
135 + match_path(PROVIDE);
136 + match_path(EAPI);
137 + match_path(PROPERTIES);
138 + match_path(DEFINED_PHASES);
139 + match_path(REQUIRED_USE);
140 + match_path(BDEPEND);
141 + match_path(CONTENTS);
142 + match_path(USE);
143 + match_path(repository);
144 + else
145 + return;
146 +#undef match_path
147 +
148 + /* hijack unused members */
149 + pos = (size_t)m->_eclasses_;
150 + len = (size_t)m->_md5_;
151 +
152 + /* trim whitespace (mostly trailing newline) */
153 + while (isspace((int)data[data_offset + data_len - 1]))
154 + data_len--;
155 +
156 + if (len - pos < (size_t)data_len) {
157 + len += (((data_len + 1) / BUFSIZ) + 1) * BUFSIZ;
158 + m->_data = xrealloc(m->_data, len);
159 + m->_md5_ = (char *)len;
160 + }
161 +
162 + *key = m->_data + pos;
163 + snprintf(*key, len - pos, "%.*s", data_len, data + data_offset);
164 + pos += data_len + 1;
165 + m->_eclasses_ = (char *)pos;
166 +}
167 +
168 +static tree_pkg_meta *
169 +tree_read_file_binpkg(tree_pkg_ctx *pkg_ctx)
170 +{
171 + tree_pkg_meta *m = xzalloc(sizeof(tree_pkg_meta));
172 +
173 + xpak_process_fd(pkg_ctx->fd, true, m, tree_read_file_binpkg_xpak_cb);
174 + pkg_ctx->fd = -1; /* closed by xpak_process_fd */
175 +
176 + return m;
177 +}
178 +
179 tree_pkg_meta *
180 tree_pkg_read(tree_pkg_ctx *pkg_ctx)
181 {
182 tree_ctx *ctx = pkg_ctx->cat_ctx->ctx;
183
184 if (pkg_ctx->fd == -1) {
185 - if (ctx->cachetype != CACHE_EBUILD) {
186 - pkg_ctx->fd = openat(pkg_ctx->cat_ctx->fd, pkg_ctx->name,
187 - O_RDONLY | O_CLOEXEC);
188 - } else {
189 + if (ctx->cachetype == CACHE_EBUILD || ctx->cachetype == CACHE_BINPKGS) {
190 char *p = (char *)pkg_ctx->name;
191 p += strlen(p);
192 *p = '.';
193 pkg_ctx->fd = openat(pkg_ctx->cat_ctx->fd, pkg_ctx->name,
194 O_RDONLY | O_CLOEXEC);
195 *p = '\0';
196 + } else {
197 + pkg_ctx->fd = openat(pkg_ctx->cat_ctx->fd, pkg_ctx->name,
198 + O_RDONLY | O_CLOEXEC);
199 }
200 if (pkg_ctx->fd == -1)
201 return NULL;
202 @@ -832,6 +930,10 @@ tree_pkg_read(tree_pkg_ctx *pkg_ctx)
203 return tree_read_file_pms(pkg_ctx);
204 } else if (ctx->cachetype == CACHE_EBUILD) {
205 return tree_read_file_ebuild(pkg_ctx);
206 + } else if (ctx->cachetype == CACHE_BINPKGS) {
207 + return tree_read_file_binpkg(pkg_ctx);
208 + } else if (ctx->cachetype == CACHE_PACKAGES) {
209 + return (tree_pkg_meta *)pkg_ctx->cat_ctx->ctx->pkgs;
210 }
211
212 warn("Unknown metadata cache type!");
213 @@ -841,8 +943,10 @@ tree_pkg_read(tree_pkg_ctx *pkg_ctx)
214 void
215 tree_close_meta(tree_pkg_meta *cache)
216 {
217 - if (!cache)
218 + if (cache == NULL)
219 errf("Cache is empty !");
220 + if (cache->_data != NULL)
221 + free(cache->_data);
222 free(cache);
223 }
224
225 @@ -952,6 +1056,112 @@ tree_close_pkg(tree_pkg_ctx *pkg_ctx)
226 free(pkg_ctx);
227 }
228
229 +static int
230 +tree_foreach_packages(tree_ctx *ctx, tree_pkg_cb callback, void *priv)
231 +{
232 + char *p = ctx->pkgs;
233 + char *q;
234 + char *c;
235 + size_t len = ctx->pkgslen;
236 + int ret = 0;
237 +
238 + /* reused for every entry */
239 + tree_cat_ctx *cat = xzalloc(sizeof(tree_cat_ctx));
240 + tree_pkg_ctx *pkg = xzalloc(sizeof(tree_pkg_ctx));
241 + tree_pkg_meta *meta = xzalloc(sizeof(tree_pkg_meta));
242 + depend_atom *atom = NULL;
243 +
244 + cat->ctx = ctx;
245 + pkg->cat_ctx = cat;
246 +
247 + do {
248 + /* find next line */
249 + c = NULL;
250 + for (q = p; len > 0 && *q != '\n'; q++, len--)
251 + if (c == NULL && *q == ':')
252 + c = q;
253 +
254 + if (len == 0)
255 + break;
256 +
257 + /* empty line, end of a block */
258 + if (p == q) {
259 + /* make callback with populated atom */
260 + if (atom != NULL) {
261 + /* store meta ptr in repo->pkgs, such that get_pkg_meta
262 + * can grab it from there (for free) */
263 + ctx->pkgs = (char *)meta;
264 +
265 + cat->name = atom->CATEGORY;
266 + pkg->name = atom->PN;
267 + pkg->slot = meta->SLOT == NULL ? "0" : meta->SLOT;
268 + pkg->repo = ctx->repo;
269 + pkg->atom = atom;
270 +
271 + /* do call callback with pkg_atom (populate cat and pkg) */
272 + ret |= callback(pkg, priv);
273 +
274 + atom_implode(atom);
275 + }
276 +
277 + memset(meta, 0, sizeof(meta[0]));
278 + atom = NULL;
279 + if (len > 0) { /* hop over \n */
280 + p++;
281 + len--;
282 + }
283 + continue;
284 + }
285 +
286 + /* skip invalid lines */
287 + if (c == NULL || q - c < 3 || c[1] != ' ')
288 + continue;
289 +
290 + /* NULL-terminate p and c, file should end with \n */
291 + *q = '\0';
292 + *c = '\0';
293 + c += 2; /* hop over ": " */
294 + if (len > 0) { /* hop over \n */
295 + q++;
296 + len--;
297 + }
298 +
299 + if (strcmp(p, "REPO") == 0) { /* from global section in older files */
300 + ctx->repo = c;
301 + } else if (strcmp(p, "CPV") == 0) {
302 + if (atom != NULL)
303 + atom_implode(atom);
304 + atom = atom_explode(c);
305 +#define match_key(X) match_key2(X,X)
306 +#define match_key2(X,Y) \
307 + } else if (strcmp(p, #X) == 0) { \
308 + meta->Y = c
309 + match_key(DEFINED_PHASES);
310 + match_key(DEPEND);
311 + match_key2(DESC, DESCRIPTION);
312 + match_key(EAPI);
313 + match_key(IUSE);
314 + match_key(KEYWORDS);
315 + match_key(LICENSE);
316 + match_key2(MD5, _md5_);
317 + match_key2(SHA1, _eclasses_);
318 + match_key(RDEPEND);
319 + match_key(SLOT);
320 + match_key(USE);
321 + match_key(PDEPEND);
322 +#undef match_key
323 +#undef match_key2
324 + }
325 +
326 + p = q;
327 + } while (len > 0);
328 +
329 + /* ensure we don't free a garbage pointer */
330 + ctx->repo = NULL;
331 +
332 + return ret;
333 +}
334 +
335 int
336 tree_foreach_pkg(tree_ctx *ctx,
337 tree_pkg_cb callback, void *priv, tree_cat_filter filter,
338 @@ -964,6 +1174,10 @@ tree_foreach_pkg(tree_ctx *ctx,
339 if (ctx == NULL)
340 return EXIT_FAILURE;
341
342 + /* handle Packages (binpkgs index) file separately */
343 + if (ctx->cachetype == CACHE_PACKAGES)
344 + return tree_foreach_packages(ctx, callback, priv);
345 +
346 ctx->do_sort = sort;
347 if (catsortfunc != NULL)
348 ctx->catsortfunc = catsortfunc;
349 @@ -1009,23 +1223,35 @@ tree_get_atom(tree_pkg_ctx *pkg_ctx, bool complete)
350 &pkg_ctx->repo, &pkg_ctx->repo_len);
351 pkg_ctx->atom->REPO = pkg_ctx->repo;
352 }
353 - } else { /* metadata or ebuild */
354 + } else { /* metadata, ebuild, binpkg or Packages */
355 + tree_pkg_meta *meta = NULL;
356 if (pkg_ctx->atom->SLOT == NULL) {
357 if (pkg_ctx->slot == NULL) {
358 - tree_pkg_meta *meta = tree_pkg_read(pkg_ctx);
359 + meta = tree_pkg_read(pkg_ctx);
360 if (meta != NULL) {
361 if (meta->SLOT != NULL) {
362 pkg_ctx->slot = xstrdup(meta->SLOT);
363 pkg_ctx->slot_len = strlen(pkg_ctx->slot);
364 }
365 - tree_close_meta(meta);
366 }
367 }
368 pkg_ctx->atom->SLOT = pkg_ctx->slot;
369 }
370 /* repo is set from the tree, when found */
371 - if (pkg_ctx->atom->REPO == NULL)
372 + if (pkg_ctx->atom->REPO == NULL) {
373 + if (pkg_ctx->repo == NULL && ctx->cachetype == CACHE_BINPKGS) {
374 + if (meta == NULL)
375 + meta = tree_pkg_read(pkg_ctx);
376 + if (meta != NULL && meta->repository != NULL) {
377 + pkg_ctx->repo = xstrdup(meta->repository);
378 + pkg_ctx->repo_len = strlen(pkg_ctx->repo);
379 + }
380 + }
381 pkg_ctx->atom->REPO = pkg_ctx->repo;
382 + }
383 +
384 + if (meta != NULL)
385 + tree_close_meta(meta);
386 }
387
388 /* this is a bit atom territory, but since we pulled in SLOT we
389
390 diff --git a/libq/tree.h b/libq/tree.h
391 index c2a30f1..d769b7b 100644
392 --- a/libq/tree.h
393 +++ b/libq/tree.h
394 @@ -18,7 +18,7 @@ typedef struct tree_pkg_ctx tree_pkg_ctx;
395 typedef struct tree_pkg_meta tree_pkg_meta;
396 typedef struct tree_metadata_xml tree_metadata_xml;
397
398 -/* VDB context */
399 +/* tree context */
400 struct tree_ctx {
401 int portroot_fd;
402 int tree_fd;
403 @@ -35,11 +35,15 @@ struct tree_ctx {
404 CACHE_METADATA_PMS,
405 CACHE_EBUILD,
406 CACHE_VDB,
407 + CACHE_PACKAGES,
408 + CACHE_BINPKGS,
409 } cachetype:3;
410 tree_pkg_ctx *ebuilddir_pkg_ctx;
411 tree_cat_ctx *ebuilddir_cat_ctx;
412 tree_ctx *ebuilddir_ctx;
413 char *repo;
414 + char *pkgs;
415 + size_t pkgslen;
416 };
417
418 /* Category context */
419 @@ -90,6 +94,10 @@ struct tree_pkg_meta {
420 char *BDEPEND;
421 char *_eclasses_;
422 char *_md5_;
423 + /* binpkgs/vdb */
424 + char *CONTENTS;
425 + char *USE;
426 + char *repository;
427 };
428
429 /* Metadata.xml */
430 @@ -104,8 +112,9 @@ struct tree_metadata_xml {
431 typedef int (tree_pkg_cb)(tree_pkg_ctx *, void *priv);
432 typedef int (tree_cat_filter)(tree_cat_ctx *, void *priv);
433
434 -tree_ctx *tree_open_vdb(const char *sroot, const char *svdb);
435 tree_ctx *tree_open(const char *sroot, const char *portdir);
436 +tree_ctx *tree_open_vdb(const char *sroot, const char *svdb);
437 +tree_ctx *tree_open_binpkg(const char *sroot, const char *spkg);
438 void tree_close(tree_ctx *ctx);
439 int tree_filter_cat(const struct dirent *de);
440 tree_cat_ctx *tree_open_cat(tree_ctx *ctx, const char *name);