From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from lists.gentoo.org (pigeon.gentoo.org [208.92.234.80]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by finch.gentoo.org (Postfix) with ESMTPS id CD37D138336 for ; Sun, 17 Nov 2019 15:12:42 +0000 (UTC) Received: from pigeon.gentoo.org (localhost [127.0.0.1]) by pigeon.gentoo.org (Postfix) with SMTP id 2847AE08EF; Sun, 17 Nov 2019 15:12:42 +0000 (UTC) Received: from smtp.gentoo.org (smtp.gentoo.org [140.211.166.183]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by pigeon.gentoo.org (Postfix) with ESMTPS id EE25CE08F0 for ; Sun, 17 Nov 2019 15:12:41 +0000 (UTC) Received: from oystercatcher.gentoo.org (unknown [IPv6:2a01:4f8:202:4333:225:90ff:fed9:fc84]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.gentoo.org (Postfix) with ESMTPS id E037334CF1E for ; Sun, 17 Nov 2019 15:12:40 +0000 (UTC) Received: from localhost.localdomain (localhost [IPv6:::1]) by oystercatcher.gentoo.org (Postfix) with ESMTP id C0BC38D1 for ; Sun, 17 Nov 2019 15:12:35 +0000 (UTC) From: "Fabian Groffen" To: gentoo-commits@lists.gentoo.org Content-Transfer-Encoding: 8bit Content-type: text/plain; charset=UTF-8 Reply-To: gentoo-dev@lists.gentoo.org, "Fabian Groffen" Message-ID: <1574002860.b811b9afd740e8f4cc73f096e8c162d5d332aed2.grobian@gentoo> Subject: [gentoo-commits] proj/portage-utils:master commit in: libq/ X-VCS-Repository: proj/portage-utils X-VCS-Files: libq/tree.c libq/tree.h X-VCS-Directories: libq/ X-VCS-Committer: grobian X-VCS-Committer-Name: Fabian Groffen X-VCS-Revision: b811b9afd740e8f4cc73f096e8c162d5d332aed2 X-VCS-Branch: master Date: Sun, 17 Nov 2019 15:12:35 +0000 (UTC) Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-Id: Gentoo Linux mail X-BeenThere: gentoo-commits@lists.gentoo.org X-Auto-Response-Suppress: DR, RN, NRN, OOF, AutoReply X-Archives-Salt: 66c7bdad-8149-4210-af46-8ebb104a188f X-Archives-Hash: 8e47b1544b12ef31cc07f7e1ac1fa9c6 commit: b811b9afd740e8f4cc73f096e8c162d5d332aed2 Author: Fabian Groffen gentoo org> AuthorDate: Sun Nov 17 15:01:00 2019 +0000 Commit: Fabian Groffen gentoo org> CommitDate: Sun Nov 17 15:01:00 2019 +0000 URL: https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=b811b9af libq/tree: add support for binpgks and Packages file This allows to foreach binpkgs (without Packages file index) as well as use the Packages file to loop over them. Signed-off-by: Fabian Groffen gentoo.org> libq/tree.c | 254 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- libq/tree.h | 13 +++- 2 files changed, 251 insertions(+), 16 deletions(-) diff --git a/libq/tree.c b/libq/tree.c index b0d0b5b..427281f 100644 --- a/libq/tree.c +++ b/libq/tree.c @@ -21,6 +21,7 @@ #include "scandirat.h" #include "set.h" #include "tree.h" +#include "xpak.h" #include #include @@ -30,7 +31,7 @@ static int tree_pkg_compar(const void *l, const void *r); static tree_ctx * tree_open_int(const char *sroot, const char *tdir, bool quiet) { - tree_ctx *ctx = xmalloc(sizeof(*ctx)); + tree_ctx *ctx = xzalloc(sizeof(*ctx)); ctx->portroot_fd = open(sroot, O_RDONLY | O_CLOEXEC | O_PATH); if (ctx->portroot_fd == -1) { @@ -56,12 +57,8 @@ tree_open_int(const char *sroot, const char *tdir, bool quiet) goto cv_error; ctx->do_sort = false; - ctx->cat_de = NULL; ctx->catsortfunc = alphasort; ctx->pkgsortfunc = tree_pkg_compar; - ctx->repo = NULL; - ctx->ebuilddir_ctx = NULL; - ctx->ebuilddir_pkg_ctx = NULL; return ctx; cv_error: @@ -130,6 +127,24 @@ tree_open_vdb(const char *sroot, const char *svdb) return ret; } +static const char binpkg_packages[] = "Packages"; +tree_ctx * +tree_open_binpkg(const char *sroot, const char *spkg) +{ + tree_ctx *ret = tree_open_int(sroot, spkg, true); + char buf[_Q_PATH_MAX]; + + if (ret != NULL) { + ret->cachetype = CACHE_BINPKGS; + + snprintf(buf, sizeof(buf), "%s%s/%s", sroot, spkg, binpkg_packages); + if (eat_file(buf, &ret->pkgs, &ret->pkgslen)) + ret->cachetype = CACHE_PACKAGES; + } + + return ret; +} + void tree_close(tree_ctx *ctx) { @@ -141,6 +156,8 @@ tree_close(tree_ctx *ctx) scandir_free(ctx->cat_de, ctx->cat_cnt); if (ctx->repo != NULL) free(ctx->repo); + if (ctx->pkgs != NULL) + free(ctx->pkgs); if (ctx->ebuilddir_ctx != NULL) free(ctx->ebuilddir_ctx); free(ctx); @@ -443,6 +460,13 @@ tree_next_pkg(tree_cat_ctx *cat_ctx) } } } while (ret == NULL); + } else if (ctx->cachetype == CACHE_BINPKGS) { + char *p = NULL; + do { + ret = tree_next_pkg_int(cat_ctx); + } while (ret != NULL && (p = strstr(ret->name, ".tbz2")) == NULL); + if (p != NULL) + *p = '\0'; } else { ret = tree_next_pkg_int(cat_ctx); } @@ -805,22 +829,96 @@ err: return NULL; } +static void +tree_read_file_binpkg_xpak_cb( + void *ctx, + char *pathname, + int pathname_len, + int data_offset, + int data_len, + char *data) +{ + tree_pkg_meta *m = (tree_pkg_meta *)ctx; + char **key; + size_t pos; + size_t len; + +#define match_path(K) \ + else if (pathname_len == (sizeof(#K) - 1) && strcmp(pathname, #K) == 0) \ + key = &m->K + if (1 == 0); /* dummy for syntax */ + match_path(DEPEND); + match_path(RDEPEND); + match_path(SLOT); + match_path(SRC_URI); + match_path(RESTRICT); + match_path(HOMEPAGE); + match_path(DESCRIPTION); + match_path(KEYWORDS); + match_path(INHERITED); + match_path(IUSE); + match_path(CDEPEND); + match_path(PDEPEND); + match_path(PROVIDE); + match_path(EAPI); + match_path(PROPERTIES); + match_path(DEFINED_PHASES); + match_path(REQUIRED_USE); + match_path(BDEPEND); + match_path(CONTENTS); + match_path(USE); + match_path(repository); + else + return; +#undef match_path + + /* hijack unused members */ + pos = (size_t)m->_eclasses_; + len = (size_t)m->_md5_; + + /* trim whitespace (mostly trailing newline) */ + while (isspace((int)data[data_offset + data_len - 1])) + data_len--; + + if (len - pos < (size_t)data_len) { + len += (((data_len + 1) / BUFSIZ) + 1) * BUFSIZ; + m->_data = xrealloc(m->_data, len); + m->_md5_ = (char *)len; + } + + *key = m->_data + pos; + snprintf(*key, len - pos, "%.*s", data_len, data + data_offset); + pos += data_len + 1; + m->_eclasses_ = (char *)pos; +} + +static tree_pkg_meta * +tree_read_file_binpkg(tree_pkg_ctx *pkg_ctx) +{ + tree_pkg_meta *m = xzalloc(sizeof(tree_pkg_meta)); + + xpak_process_fd(pkg_ctx->fd, true, m, tree_read_file_binpkg_xpak_cb); + pkg_ctx->fd = -1; /* closed by xpak_process_fd */ + + return m; +} + tree_pkg_meta * tree_pkg_read(tree_pkg_ctx *pkg_ctx) { tree_ctx *ctx = pkg_ctx->cat_ctx->ctx; if (pkg_ctx->fd == -1) { - if (ctx->cachetype != CACHE_EBUILD) { - pkg_ctx->fd = openat(pkg_ctx->cat_ctx->fd, pkg_ctx->name, - O_RDONLY | O_CLOEXEC); - } else { + if (ctx->cachetype == CACHE_EBUILD || ctx->cachetype == CACHE_BINPKGS) { char *p = (char *)pkg_ctx->name; p += strlen(p); *p = '.'; pkg_ctx->fd = openat(pkg_ctx->cat_ctx->fd, pkg_ctx->name, O_RDONLY | O_CLOEXEC); *p = '\0'; + } else { + pkg_ctx->fd = openat(pkg_ctx->cat_ctx->fd, pkg_ctx->name, + O_RDONLY | O_CLOEXEC); } if (pkg_ctx->fd == -1) return NULL; @@ -832,6 +930,10 @@ tree_pkg_read(tree_pkg_ctx *pkg_ctx) return tree_read_file_pms(pkg_ctx); } else if (ctx->cachetype == CACHE_EBUILD) { return tree_read_file_ebuild(pkg_ctx); + } else if (ctx->cachetype == CACHE_BINPKGS) { + return tree_read_file_binpkg(pkg_ctx); + } else if (ctx->cachetype == CACHE_PACKAGES) { + return (tree_pkg_meta *)pkg_ctx->cat_ctx->ctx->pkgs; } warn("Unknown metadata cache type!"); @@ -841,8 +943,10 @@ tree_pkg_read(tree_pkg_ctx *pkg_ctx) void tree_close_meta(tree_pkg_meta *cache) { - if (!cache) + if (cache == NULL) errf("Cache is empty !"); + if (cache->_data != NULL) + free(cache->_data); free(cache); } @@ -952,6 +1056,112 @@ tree_close_pkg(tree_pkg_ctx *pkg_ctx) free(pkg_ctx); } +static int +tree_foreach_packages(tree_ctx *ctx, tree_pkg_cb callback, void *priv) +{ + char *p = ctx->pkgs; + char *q; + char *c; + size_t len = ctx->pkgslen; + int ret = 0; + + /* reused for every entry */ + tree_cat_ctx *cat = xzalloc(sizeof(tree_cat_ctx)); + tree_pkg_ctx *pkg = xzalloc(sizeof(tree_pkg_ctx)); + tree_pkg_meta *meta = xzalloc(sizeof(tree_pkg_meta)); + depend_atom *atom = NULL; + + cat->ctx = ctx; + pkg->cat_ctx = cat; + + do { + /* find next line */ + c = NULL; + for (q = p; len > 0 && *q != '\n'; q++, len--) + if (c == NULL && *q == ':') + c = q; + + if (len == 0) + break; + + /* empty line, end of a block */ + if (p == q) { + /* make callback with populated atom */ + if (atom != NULL) { + /* store meta ptr in repo->pkgs, such that get_pkg_meta + * can grab it from there (for free) */ + ctx->pkgs = (char *)meta; + + cat->name = atom->CATEGORY; + pkg->name = atom->PN; + pkg->slot = meta->SLOT == NULL ? "0" : meta->SLOT; + pkg->repo = ctx->repo; + pkg->atom = atom; + + /* do call callback with pkg_atom (populate cat and pkg) */ + ret |= callback(pkg, priv); + + atom_implode(atom); + } + + memset(meta, 0, sizeof(meta[0])); + atom = NULL; + if (len > 0) { /* hop over \n */ + p++; + len--; + } + continue; + } + + /* skip invalid lines */ + if (c == NULL || q - c < 3 || c[1] != ' ') + continue; + + /* NULL-terminate p and c, file should end with \n */ + *q = '\0'; + *c = '\0'; + c += 2; /* hop over ": " */ + if (len > 0) { /* hop over \n */ + q++; + len--; + } + + if (strcmp(p, "REPO") == 0) { /* from global section in older files */ + ctx->repo = c; + } else if (strcmp(p, "CPV") == 0) { + if (atom != NULL) + atom_implode(atom); + atom = atom_explode(c); +#define match_key(X) match_key2(X,X) +#define match_key2(X,Y) \ + } else if (strcmp(p, #X) == 0) { \ + meta->Y = c + match_key(DEFINED_PHASES); + match_key(DEPEND); + match_key2(DESC, DESCRIPTION); + match_key(EAPI); + match_key(IUSE); + match_key(KEYWORDS); + match_key(LICENSE); + match_key2(MD5, _md5_); + match_key2(SHA1, _eclasses_); + match_key(RDEPEND); + match_key(SLOT); + match_key(USE); + match_key(PDEPEND); +#undef match_key +#undef match_key2 + } + + p = q; + } while (len > 0); + + /* ensure we don't free a garbage pointer */ + ctx->repo = NULL; + + return ret; +} + int tree_foreach_pkg(tree_ctx *ctx, tree_pkg_cb callback, void *priv, tree_cat_filter filter, @@ -964,6 +1174,10 @@ tree_foreach_pkg(tree_ctx *ctx, if (ctx == NULL) return EXIT_FAILURE; + /* handle Packages (binpkgs index) file separately */ + if (ctx->cachetype == CACHE_PACKAGES) + return tree_foreach_packages(ctx, callback, priv); + ctx->do_sort = sort; if (catsortfunc != NULL) ctx->catsortfunc = catsortfunc; @@ -1009,23 +1223,35 @@ tree_get_atom(tree_pkg_ctx *pkg_ctx, bool complete) &pkg_ctx->repo, &pkg_ctx->repo_len); pkg_ctx->atom->REPO = pkg_ctx->repo; } - } else { /* metadata or ebuild */ + } else { /* metadata, ebuild, binpkg or Packages */ + tree_pkg_meta *meta = NULL; if (pkg_ctx->atom->SLOT == NULL) { if (pkg_ctx->slot == NULL) { - tree_pkg_meta *meta = tree_pkg_read(pkg_ctx); + meta = tree_pkg_read(pkg_ctx); if (meta != NULL) { if (meta->SLOT != NULL) { pkg_ctx->slot = xstrdup(meta->SLOT); pkg_ctx->slot_len = strlen(pkg_ctx->slot); } - tree_close_meta(meta); } } pkg_ctx->atom->SLOT = pkg_ctx->slot; } /* repo is set from the tree, when found */ - if (pkg_ctx->atom->REPO == NULL) + if (pkg_ctx->atom->REPO == NULL) { + if (pkg_ctx->repo == NULL && ctx->cachetype == CACHE_BINPKGS) { + if (meta == NULL) + meta = tree_pkg_read(pkg_ctx); + if (meta != NULL && meta->repository != NULL) { + pkg_ctx->repo = xstrdup(meta->repository); + pkg_ctx->repo_len = strlen(pkg_ctx->repo); + } + } pkg_ctx->atom->REPO = pkg_ctx->repo; + } + + if (meta != NULL) + tree_close_meta(meta); } /* this is a bit atom territory, but since we pulled in SLOT we diff --git a/libq/tree.h b/libq/tree.h index c2a30f1..d769b7b 100644 --- a/libq/tree.h +++ b/libq/tree.h @@ -18,7 +18,7 @@ typedef struct tree_pkg_ctx tree_pkg_ctx; typedef struct tree_pkg_meta tree_pkg_meta; typedef struct tree_metadata_xml tree_metadata_xml; -/* VDB context */ +/* tree context */ struct tree_ctx { int portroot_fd; int tree_fd; @@ -35,11 +35,15 @@ struct tree_ctx { CACHE_METADATA_PMS, CACHE_EBUILD, CACHE_VDB, + CACHE_PACKAGES, + CACHE_BINPKGS, } cachetype:3; tree_pkg_ctx *ebuilddir_pkg_ctx; tree_cat_ctx *ebuilddir_cat_ctx; tree_ctx *ebuilddir_ctx; char *repo; + char *pkgs; + size_t pkgslen; }; /* Category context */ @@ -90,6 +94,10 @@ struct tree_pkg_meta { char *BDEPEND; char *_eclasses_; char *_md5_; + /* binpkgs/vdb */ + char *CONTENTS; + char *USE; + char *repository; }; /* Metadata.xml */ @@ -104,8 +112,9 @@ struct tree_metadata_xml { typedef int (tree_pkg_cb)(tree_pkg_ctx *, void *priv); typedef int (tree_cat_filter)(tree_cat_ctx *, void *priv); -tree_ctx *tree_open_vdb(const char *sroot, const char *svdb); tree_ctx *tree_open(const char *sroot, const char *portdir); +tree_ctx *tree_open_vdb(const char *sroot, const char *svdb); +tree_ctx *tree_open_binpkg(const char *sroot, const char *spkg); void tree_close(tree_ctx *ctx); int tree_filter_cat(const struct dirent *de); tree_cat_ctx *tree_open_cat(tree_ctx *ctx, const char *name);