commit:     7905d33dbdf0e0b40ed28fbbf5f92cf45aee3c70
Author:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
AuthorDate: Sat Jan 24 19:36:21 2026 +0000
Commit:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
CommitDate: Sat Jan 24 19:36:21 2026 +0000
URL:        https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=7905d33d

libq/tree: fix atom parsing from Packages file via PATH

Signed-off-by: Fabian Groffen <grobian <AT> gentoo.org>

 libq/tree.c | 127 ++++++++++++++++++++++++++++++++++++++++++------------------
 1 file changed, 89 insertions(+), 38 deletions(-)

diff --git a/libq/tree.c b/libq/tree.c
index 11872d7..7e2833f 100644
--- a/libq/tree.c
+++ b/libq/tree.c
@@ -954,7 +954,7 @@ static void tree_pkg_xpak_read_cb
   case 'B':
 #define keycmp(P,K) \
     if (pathname_len == sizeof(#K) - 1 && \
-        strcmp(&P[1], &(#K)[1]) == 0) \
+        memcmp(&P[1], &(#K)[1], pathname_len - 1) == 0) \
     { \
       key = &pkg->meta[Q_##K]; \
       break; \
@@ -1041,7 +1041,7 @@ static bool tree_pkg_binpkg_read
     archive_read_support_format_all(a);
     archive_read_support_filter_all(a);
 
-    fd = openat(pkg->cat->tree->portroot_fd, pkg->cat->tree->path, O_RDONLY);
+    fd = openat(pkg->cat->tree->portroot_fd, pkg->path, O_RDONLY);
     if (fd < 0)
       return false;
 
@@ -1250,10 +1250,8 @@ char *tree_pkg_meta
       break; /* }}} */
     case TREE_BINPKGS:
     case TREE_PACKAGES:
-      {
-        if (tree_pkg_binpkg_read(pkg))
-          pkg->meta_complete = true;
-      }
+      if (tree_pkg_binpkg_read(pkg))
+        pkg->meta_complete = true;
       break;
     default:
       break;
@@ -2166,38 +2164,77 @@ int tree_foreach_pkg
           /* don't attempt to do anything, this is the header which we
            * ignore/not store anything of currently */
         }
-        else if (strcmp(k, "CPV") == 0)
+        else
         {
-          cpv = v;
+          switch (k[0])
+          {
+          case 'B':
+#define keycmp(P,K) \
+            if (strcmp(&P[1], &(#K)[1]) == 0) \
+            { \
+              if (pkg->meta[Q_##K] == NULL) \
+                pkg->meta[Q_##K] = xstrdup(v); \
+              break; \
+            }
+            keycmp(k, BDEPEND);
+            keycmp(k, BUILD_ID);
+            break;
+          case 'C':
+            if (strcmp(&k[1], "PV") == 0)
+              cpv = v;
+            break;
+          case 'D':
+            keycmp(k, DEFINED_PHASES);
+            keycmp(k, DEPEND);
+            if (strcmp(&k[1], "ESC") == 0)
+            {
+              if (pkg->meta[Q_DESCRIPTION] == NULL)
+                pkg->meta[Q_DESCRIPTION] = xstrdup(v);
+              break;
+            }
+            break;
+          case 'E':
+            keycmp(k, EAPI);
+            break;
+          case 'I':
+            keycmp(k, IDEPEND);
+            keycmp(k, IUSE);
+            break;
+          case 'K':
+            keycmp(k, KEYWORDS);
+            break;
+          case 'L':
+            keycmp(k, LICENSE);
+            break;
+          case 'M':
+            keycmp(k, MD5);
+            break;
+          case 'P':
+            keycmp(k, PATH);
+            keycmp(k, PDEPEND);
+            break;
+          case 'R':
+            keycmp(k, RDEPEND);
+            if (strcmp(&k[1], "EPO") == 0)
+            {
+              if (pkg->meta[Q_repository] == NULL)
+                pkg->meta[Q_repository] = xstrdup(v);
+              break;
+            }
+            break;
+          case 'S':
+            keycmp(k, SHA1);
+            keycmp(k, SIZE);
+            keycmp(k, SLOT);
+            break;
+          case 'U':
+            keycmp(k, USE);
+            break;
+          default:
+            /* don't care/ignored */
+            break;
+          }
         }
-#define match_key(X) match_key2(X,X)
-#define match_key2(X,Y) \
-        else if (strcmp(k, #X) == 0) \
-          do { \
-            if (pkg->meta[Q_##Y] == NULL) \
-              pkg->meta[Q_##Y] = xstrdup(v); \
-          } while (false)
-        match_key(DEFINED_PHASES);
-        match_key(DEPEND);
-        match_key2(DESC, DESCRIPTION);
-        match_key(EAPI);
-        match_key(IUSE);
-        match_key(KEYWORDS);
-        match_key(LICENSE);
-        match_key(MD5);
-        match_key(SHA1);
-        match_key(RDEPEND);
-        match_key(SLOT);
-        match_key(USE);
-        match_key(PDEPEND);
-        match_key2(REPO, repository);
-        match_key(SIZE);
-        match_key(BDEPEND);
-        match_key(IDEPEND);
-        match_key(PATH);
-        match_key(BUILD_ID);
-#undef match_key
-#undef match_key2
 
         if (*nexttok == '\n')
         {
@@ -2208,12 +2245,26 @@ int tree_foreach_pkg
             /* create atom from the path if we have it, else use cpv */
             if (pkg->meta[Q_PATH] != NULL)
             {
+              char *pn     = strrchr(pkg->meta[Q_PATH], '/');
+              char *catend = strchr(pkg->meta[Q_PATH], '/');
+
+              if (pn == NULL) /* implies catend == NULL */
+              {
+                /* have no version or anything, skip this */
+                tree_pkg_close(pkg);
+                cpv = NULL;
+                pkg = xzalloc(sizeof(*pkg));
+                continue;
+              }
+
               /* construct full path */
               snprintf(pth, sizeof(pth), "%.*s/%s",
                        (int)rootlen, tree->path, pkg->meta[Q_PATH]);
-
               pkg->path = xstrdup(pth);
-              pkg->atom = atom_explode(pkg->meta[Q_PATH]);
+
+              snprintf(pth, sizeof(pth), "%.*s",
+                       (int)(catend - pkg->meta[Q_PATH]), pkg->meta[Q_PATH]);
+              pkg->atom = atom_explode_cat(pn + 1, pth);
 
               len = strlen(pkg->meta[Q_PATH]);
               if (len > sizeof(".gpkg.tar") - 1 &&

Reply via email to