]> git.ipfire.org Git - thirdparty/libsolv.git/commitdiff
Add a package/repo parser for apk
authorMichael Schroeder <mls@suse.de>
Thu, 28 Nov 2024 12:47:31 +0000 (13:47 +0100)
committerMichael Schroeder <mls@suse.de>
Thu, 28 Nov 2024 12:52:43 +0000 (13:52 +0100)
You need to configure with ENABLE_APK to get them.

Note that we currently only support the v2 format. We'll add
v3 support if somebody uses it in the future.

CMakeLists.txt
README
ext/CMakeLists.txt
ext/libsolvext.ver
ext/repo_apk.c [new file with mode: 0644]
ext/repo_apk.h [new file with mode: 0644]
ext/solv_xfopen.c
ext/solv_xfopen.h
tools/CMakeLists.txt

index e352d220a3d36667271e56275d49d14cec6ccd8f..30125cc9c32194f5c01fdeaafa61b7d91835fc5a 100644 (file)
@@ -24,9 +24,10 @@ OPTION (ENABLE_RPMMD "Build with rpmmd repository support?" OFF)
 OPTION (ENABLE_SUSEREPO "Build with suse repository support?" OFF)
 OPTION (ENABLE_COMPS "Build with fedora comps support?" OFF)
 OPTION (ENABLE_HELIXREPO "Build with helix repository support?" OFF)
-OPTION (ENABLE_DEBIAN "Build with debian database/repository support?" OFF)
+OPTION (ENABLE_DEBIAN "Build with debian package/repository support?" OFF)
 OPTION (ENABLE_MDKREPO "Build with mandriva/mageia repository support?" OFF)
 OPTION (ENABLE_ARCHREPO "Build with archlinux repository support?" OFF)
+OPTION (ENABLE_APK "Build with apk package/repository support?" OFF)
 OPTION (ENABLE_CUDFREPO "Build with cudf repository support?" OFF)
 OPTION (ENABLE_HAIKU "Build with Haiku package support?" OFF)
 OPTION (ENABLE_CONDA "Build with conda dependency support?" OFF)
@@ -314,6 +315,7 @@ FOREACH (VAR
   ENABLE_HELIXREPO ENABLE_MDKREPO ENABLE_ARCHREPO ENABLE_DEBIAN ENABLE_HAIKU
   ENABLE_ZLIB_COMPRESSION ENABLE_LZMA_COMPRESSION ENABLE_BZIP2_COMPRESSION
   ENABLE_ZSTD_COMPRESSION ENABLE_ZCHUNK_COMPRESSION ENABLE_PGPVRFY ENABLE_APPDATA
+  ENABLE_APK
   WITH_SYSTEM_ZCHUNK)
   IF(${VAR})
     ADD_DEFINITIONS (-D${VAR}=1)
diff --git a/README b/README
index 41fe16842a4550739e960e4853dffc6a8079f6c0..c704be32a673c5c511dd7bcdef2cc8e7eaf6d6be 100644 (file)
--- a/README
+++ b/README
@@ -24,6 +24,7 @@ Supported package formats:
   - deb
   - arch linux
   - haiku
+  - apk 
 
 Supported repository formats:
 
@@ -33,6 +34,7 @@ Supported repository formats:
   - arch linux
   - red carpet helix format
   - haiku
+  - apk 
 
 Build instructions
 ==================
index 2cf62423aa56127f59d25c8b2a324a859409367b..4b36934a89a7739c5694513656973d5c8f10d6e8 100644 (file)
@@ -74,6 +74,13 @@ IF (ENABLE_DEBIAN)
        repo_deb.h)
 ENDIF (ENABLE_DEBIAN)
 
+IF (ENABLE_APK)
+    SET (libsolvext_SRCS ${libsolvext_SRCS}
+       repo_apk.c)
+    SET (libsolvext_HEADERS ${libsolvext_HEADERS}
+       repo_apk.h)
+ENDIF (ENABLE_APK)
+
 IF (ENABLE_HELIXREPO)
     SET (libsolvext_SRCS ${libsolvext_SRCS}
        repo_helix.c)
@@ -144,10 +151,10 @@ IF (ENABLE_ZCHUNK_COMPRESSION)
        solv_zchunk.c)
 ENDIF (ENABLE_ZCHUNK_COMPRESSION)
 
-IF (ENABLE_ARCHREPO)
+IF (ENABLE_ARCHREPO OR ENABLE_APK)
     SET (libsolvext_SRCS ${libsolvext_SRCS}
        tarhead.c)
-ENDIF (ENABLE_ARCHREPO)
+ENDIF (ENABLE_ARCHREPO OR ENABLE_APK)
 
 IF (NOT MSVC)
 SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
index a2e8628b2b0385617d1d32afe06de263d20f5ef9..de39b203ef7769394bb5bba9114219a23c882c0b 100644 (file)
@@ -3,6 +3,8 @@ SOLV_1.0 {
                pool_deb_get_autoinstalled;
                pool_findfileconflicts;
                pool_parserpmrichdep;
+               repo_add_apk_pkg;
+               repo_add_apk_repo;
                repo_add_appdata;
                repo_add_appdata_dir;
                repo_add_arch_local;
diff --git a/ext/repo_apk.c b/ext/repo_apk.c
new file mode 100644 (file)
index 0000000..e2177cf
--- /dev/null
@@ -0,0 +1,491 @@
+/*
+ * Copyright (c) 2024, SUSE LLC
+ *
+ * This program is licensed under the BSD license, read LICENSE.BSD
+ * for further information
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include <zlib.h>
+
+
+#include "pool.h"
+#include "repo.h"
+#include "util.h"
+#include "chksum.h"
+#include "solv_xfopen.h"
+#include "tarhead.h"
+#include "repo_apk.h"
+
+
+struct zstream {
+  int fd;
+  int eof;
+  z_stream zs;
+  unsigned char buf[65536];
+  void (*readcb)(void *, const void *, int);
+  void *readcb_data;
+};
+
+static struct zstream *
+apkz_open(int fd)
+{
+  struct zstream *zstream = solv_calloc(1, sizeof(*zstream));
+  zstream->fd = fd;
+  if (inflateInit2(&zstream->zs, 15 + 32) != Z_OK)     /* 32: enable gzip */
+    {
+      solv_free(&zstream->zs);
+      return 0;
+    }
+  return zstream;
+}
+
+static int
+apkz_close(void *cookie)
+{
+  struct zstream *zstream = cookie;
+  inflateEnd(&zstream->zs);
+  if (zstream->fd != -1)
+    close(zstream->fd);
+  solv_free(zstream);
+  return 0;
+}
+
+static ssize_t
+apkz_read(void *cookie, char *buf, size_t len)
+{
+  struct zstream *zstream = cookie;
+  int r, eof = 0;
+  ssize_t old_avail_in;
+
+  if (!zstream)
+    return -1;
+  if (zstream->eof)
+    return 0;
+  zstream->zs.avail_out = len;
+  zstream->zs.next_out = (unsigned char *)buf;
+  for (;;)
+    {
+      if (zstream->zs.avail_in == 0)
+       {
+         ssize_t rr = read(zstream->fd, zstream->buf, sizeof(zstream->buf));
+         if (rr < 0)
+           return rr;
+         if (rr == 0)
+             eof = 1;
+         zstream->zs.avail_in = rr;
+         zstream->zs.next_in = zstream->buf;
+       }
+      old_avail_in = zstream->zs.avail_in;
+      r = inflate(&zstream->zs, Z_NO_FLUSH);
+
+      if ((r == Z_OK || r == Z_STREAM_END) && zstream->readcb)
+       if (zstream->zs.avail_in < old_avail_in)
+         {
+           int l = old_avail_in - zstream->zs.avail_in;
+           zstream->readcb(zstream->readcb_data, (const void *)(zstream->zs.next_in - l), l);
+         }
+
+      if (r == Z_STREAM_END)
+       {
+         zstream->eof = 1;
+         return len - zstream->zs.avail_out;
+       }
+      if (r != Z_OK)
+       return -1;
+      if (zstream->zs.avail_out == 0)
+       return len;
+      if (eof)
+       return -1;
+    }
+}
+
+static int
+apkz_reset(struct zstream *zstream)
+{
+  zstream->eof = 0;
+  if (zstream->zs.avail_in == 0)
+    {
+      ssize_t rr = read(zstream->fd, zstream->buf, sizeof(zstream->buf));
+      if (rr <= 0)
+       return rr < 0 ? -1 : 0;
+      zstream->zs.avail_in = rr;
+      zstream->zs.next_in = zstream->buf;
+    }
+  inflateReset(&zstream->zs);
+  return 1;
+}
+
+static void
+add_deps(Repo *repo, Solvable *s, Id what, char *p)
+{
+  Pool *pool = repo->pool;
+  Id oldwhat = what;
+  Id supplements = 0;
+  while (*p)
+    {
+      char *pn, *pv;
+      int flags = 0;
+      Id id;
+      while (*p == ' ' || *p == '\t')
+       p++;
+      what = oldwhat;
+      if (what == SOLVABLE_REQUIRES && *p == '!')
+       {
+         what = SOLVABLE_CONFLICTS;
+         p++;
+       }
+      pn = p;
+      while (*p && *p != ' ' && *p != '\t' && *p != '<' && *p != '>' && *p != '=' && *p != '~')
+       p++;
+      id =  pool_strn2id(pool, pn, p - pn, 1);
+      for (; *p; p++)
+       {
+         if (*p == '<')
+           flags |= REL_LT;
+         else if (*p == '>')
+           flags |= REL_GT;
+         else if (*p == '=')
+           flags |= REL_EQ;
+         else
+           break;
+       }
+      if (*p == '~')
+       flags |= REL_EQ;
+      if (flags)
+       {
+         pv = p;
+         while (*p && *p != ' ' && *p != '\t')
+           p++;
+         id = pool_rel2id(pool, id, pool_strn2id(pool, pv, p - pv, 1), flags, 1);
+       }
+      if (what == SOLVABLE_PROVIDES)
+        s->provides = repo_addid_dep(repo, s->provides, id, 0);
+      else if (what == SOLVABLE_REQUIRES)
+        s->requires = repo_addid_dep(repo, s->requires, id, 0);
+      else if (what == SOLVABLE_CONFLICTS)
+        s->conflicts = repo_addid_dep(repo, s->conflicts, id, 0);
+      else if (what == SOLVABLE_SUPPLEMENTS)
+       supplements = supplements ? pool_rel2id(pool, id, supplements, REL_AND, 1) : id;
+    }
+  if (supplements)
+    s->supplements = repo_addid_dep(repo, s->supplements, supplements, 0);
+}
+
+Id
+repo_add_apk_pkg(Repo *repo, const char *fn, int flags)
+{
+  Pool *pool = repo->pool;
+  Repodata *data;
+  int fd;
+  FILE *fp;
+  struct zstream *zstream;
+  struct tarhead th;
+  Solvable *s = 0;
+  Chksum *pkgidchk = 0;
+  Chksum *q1chk = 0;
+  char *line = 0;
+  size_t l, line_alloc = 0;
+  int haveorigin = 0;
+
+  data = repo_add_repodata(repo, flags);
+  if ((fd = open(flags & REPO_USE_ROOTDIR ? pool_prepend_rootdir_tmp(pool, fn) : fn, O_RDONLY)) == -1)
+    {
+      pool_error(pool, -1, "%s: %s", fn, strerror(errno));
+      return 0;
+    }
+  zstream = apkz_open(fd);
+  if (!zstream)
+    {
+      pool_error(pool, -1, "%s: %s", fn, strerror(errno));
+      close(fd);
+      return 0;
+    }
+  if ((fp = solv_cookieopen(zstream, "r", apkz_read, 0, apkz_close)) == 0) {
+    pool_error(pool, -1, "%s: %s", fn, strerror(errno));
+    apkz_close(zstream);
+    return 0;
+  }
+
+  /* skip signatures */
+  while (getc(fp) != EOF)
+    ;
+  if (apkz_reset(zstream) != 1)
+    {
+      pool_error(pool, -1, "%s: unexpected EOF", fn);
+      fclose(fp);
+      return 0;
+    }
+  if (flags & APK_ADD_WITH_HDRID)
+    {
+      q1chk = solv_chksum_create(REPOKEY_TYPE_SHA1);
+      zstream->readcb_data = q1chk;
+      zstream->readcb = (void *)solv_chksum_add;
+    }
+  clearerr(fp);
+  tarhead_init(&th, fp);
+  while (tarhead_next(&th) > 0)
+    {
+      if (th.type != 1 || strcmp(th.path, ".PKGINFO") != 0 || s)
+       {
+         tarhead_skip(&th);
+         continue;
+       }
+      if (th.length > 10 * 1024 * 1024)
+       {
+         pool_error(pool, -1, "%s: oversized .PKGINFO", fn);
+         break;
+       }
+      s = pool_id2solvable(pool, repo_add_solvable(repo));
+      if (flags & APK_ADD_WITH_PKGID)
+        pkgidchk = solv_chksum_create(REPOKEY_TYPE_MD5);
+      while ((l = tarhead_gets(&th, &line, &line_alloc)) > 0)
+       {
+         if (pkgidchk)
+           solv_chksum_add(pkgidchk, line, l);
+         l = strlen(line);
+         if (l && line[l - 1] == '\n')
+           line[--l] = 0;
+         if (l == 0 || line[0] == '#')
+           continue;
+         if (!strncmp(line, "pkgname = ", 10))
+           s->name = pool_str2id(pool, line + 10, 1);
+         else if (!strncmp(line, "pkgver = ", 9))
+           s->evr = pool_str2id(pool, line + 9, 1);
+         else if (!strncmp(line, "pkgdesc = ", 10))
+           {
+             repodata_set_str(data, s - pool->solvables, SOLVABLE_SUMMARY, line + 10);
+             repodata_set_str(data, s - pool->solvables, SOLVABLE_DESCRIPTION, line + 10);
+           }
+         else if (!strncmp(line, "url = ", 6))
+           repodata_set_str(data, s - pool->solvables, SOLVABLE_URL, line + 6);
+         else if (!strncmp(line, "builddate = ", 12))
+           repodata_set_num(data, s - pool->solvables, SOLVABLE_BUILDTIME, strtoull(line + 12, 0, 10));
+         else if (!strncmp(line, "packager = ", 11))
+           repodata_set_poolstr(data, s - pool->solvables, SOLVABLE_PACKAGER, line + 11);
+         else if (!strncmp(line, "size = ", 7))
+           repodata_set_num(data, s - pool->solvables, SOLVABLE_INSTALLSIZE, strtoull(line + 7, 0, 10));
+         else if (!strncmp(line, "arch = ", 7))
+           s->arch = pool_str2id(pool, line + 7, 1);
+         else if (!strncmp(line, "license = ", 10))
+           repodata_add_poolstr_array(data, s - pool->solvables, SOLVABLE_LICENSE, line + 10);
+         else if (!strncmp(line, "origin = ", 9))
+           {
+             if (s->name && !strcmp(line + 9,  pool_id2str(pool, s->name)))
+               repodata_set_void(data, s - pool->solvables, SOLVABLE_SOURCENAME);
+             else
+               repodata_set_id(data, s - pool->solvables, SOLVABLE_SOURCENAME, pool_str2id(pool, line + 9, 1));
+             haveorigin = 1;
+           }
+         else if (!strncmp(line, "depend = ", 9))
+           add_deps(repo, s, SOLVABLE_REQUIRES, line + 9);
+         else if (!strncmp(line, "provides = ", 11))
+           add_deps(repo, s, SOLVABLE_PROVIDES, line + 11);
+         else if (!strncmp(line, "install_if = ", 13))
+           add_deps(repo, s, SOLVABLE_SUPPLEMENTS, line + 13);
+       }
+    }
+  solv_free(line);
+  tarhead_free(&th);
+  fclose(fp);
+  if (s && !s->name)
+    {
+      pool_error(pool, -1, "%s: package has no name", fn);
+      s = solvable_free(s, 1);
+    }
+  if (s)
+    {
+      if (!s->arch)
+       s->arch = ARCH_NOARCH;
+      if (!s->evr)
+       s->evr = ID_EMPTY;
+      if (s->name)
+       s->provides = repo_addid_dep(repo, s->provides, pool_rel2id(pool, s->name, s->evr, REL_EQ, 1), 0);
+      if (s->name && !haveorigin)
+       repodata_set_void(data, s - pool->solvables, SOLVABLE_SOURCENAME);
+      if (pkgidchk)
+       {
+         unsigned char pkgid[16];
+         solv_chksum_free(pkgidchk, pkgid);
+         repodata_set_bin_checksum(data, s - pool->solvables, SOLVABLE_PKGID, REPOKEY_TYPE_MD5, pkgid);
+         pkgidchk = 0;
+       }
+      if (q1chk)
+       {
+         unsigned char hdrid[20];
+         solv_chksum_free(q1chk, hdrid);
+         repodata_set_bin_checksum(data, s - pool->solvables, SOLVABLE_HDRID, REPOKEY_TYPE_SHA1, hdrid);
+         q1chk = 0;
+       }
+      if (!(flags & REPO_NO_LOCATION))
+       repodata_set_location(data, s - pool->solvables, 0, 0, fn);
+    }
+  if (q1chk)
+    solv_chksum_free(q1chk, 0);
+  if (pkgidchk)
+    solv_chksum_free(pkgidchk, 0);
+  if (!(flags & REPO_NO_INTERNALIZE))
+    repodata_internalize(data);
+  return s ? s - pool->solvables : 0;
+}
+
+static void
+apk_add_hdrid(Repodata *data, Id p, char *idstr)
+{
+  size_t l = strlen(idstr);
+  unsigned char chksum[33], *cp = chksum;
+
+  if (((l == 30 || l == 46) && idstr[0] == 'Q' && idstr[1] == '1') || (idstr[1] == '2' && l == 46))
+    {
+      int xpos = idstr[1] == '2' ? 43 : 27;
+      int i, v;
+
+      l -= 2;
+      idstr += 2;
+      for (i = v = 0; i < l; i++)
+       {
+         int x = idstr[i];
+         if (x >= 'A' && x <= 'Z')
+           x -= 'A';
+         else if (x >= 'a' && x <= 'z') 
+           x -= 'a' - 26;
+         else if (x >= '0' && x <= '9') 
+           x -= '0' - 52;
+         else if (x == '+') 
+           x = 62;
+         else if (x == '/') 
+           x = 63;
+         else if (x == '=' && i == xpos) 
+           x = 0;
+         else
+           return;
+         v = v << 6 | x;
+         if ((i & 3) == 3)
+           {
+             *cp++ = v >> 16;
+             *cp++ = v >> 8;
+             if (i != xpos)
+                 *cp++ = v;
+             v = 0;
+           }
+       }
+      repodata_set_bin_checksum(data, p, SOLVABLE_HDRID, l == 28 ? REPOKEY_TYPE_SHA1 : REPOKEY_TYPE_SHA256, chksum);
+    }
+}
+
+static void
+apk_process_index(Repo *repo, Repodata *data, struct tarhead *th)
+{
+  Pool *pool = repo->pool;
+  Solvable *s = 0;
+  char *line = 0;
+  size_t l, line_alloc = 0;
+  int haveorigin = 0;
+
+  for (;;)
+    {
+      l = tarhead_gets(th, &line, &line_alloc);
+      if (s && (l == 0 || (l == 1 && line[0] == '\n')))
+       {
+         /* finish old solvable */
+         if (!s->name)
+           repo_free_solvable(repo, s - pool->solvables, 1);
+         else
+           {
+             if (!s->arch)
+               s->arch = ARCH_NOARCH;
+             if (!s->evr)
+               s->evr = ID_EMPTY;
+             if (s->name)
+               s->provides = repo_addid_dep(repo, s->provides, pool_rel2id(pool, s->name, s->evr, REL_EQ, 1), 0);
+             if (s->name && !haveorigin)
+               repodata_set_void(data, s - pool->solvables, SOLVABLE_SOURCENAME);
+           }
+         s = 0;
+       }
+
+      if (l == 0)
+       break;
+
+      l = strlen(line);
+      if (l && line[l - 1] == '\n')
+       line[--l] = 0;
+      if (l < 2 || line[1] != ':')
+       continue;
+      if (!s)
+       {
+         s = pool_id2solvable(pool, repo_add_solvable(repo));
+         haveorigin = 0;
+       }
+      if (line[0] == 'P')
+       s->name = pool_str2id(pool, line + 2, 1);
+      else if (line[0] == 'V')
+       s->evr = pool_str2id(pool, line + 2, 1);
+      else if (line[0] == 'T')
+       {
+         repodata_set_str(data, s - pool->solvables, SOLVABLE_SUMMARY, line + 2);
+         repodata_set_str(data, s - pool->solvables, SOLVABLE_DESCRIPTION, line + 2);
+       }
+      else if (line[0] == 'U')
+       repodata_set_str(data, s - pool->solvables, SOLVABLE_URL, line + 2);
+      else if (line[0] == 't')
+       repodata_set_num(data, s - pool->solvables, SOLVABLE_BUILDTIME, strtoull(line + 2, 0, 10));
+      else if (line[0] == 'I')
+       repodata_set_num(data, s - pool->solvables, SOLVABLE_INSTALLSIZE, strtoull(line + 2, 0, 10));
+      else if (line[0] == 'A')
+       s->arch = pool_str2id(pool, line + 2, 1);
+      else if (line[0] == 'L')
+       repodata_add_poolstr_array(data, s - pool->solvables, SOLVABLE_LICENSE, line + 2);
+      else if (line[0] == 'o')
+       {
+         if (s->name && !strcmp(line + 2,  pool_id2str(pool, s->name)))
+           repodata_set_void(data, s - pool->solvables, SOLVABLE_SOURCENAME);
+         else
+           repodata_set_id(data, s - pool->solvables, SOLVABLE_SOURCENAME, pool_str2id(pool, line + 2, 1));
+         haveorigin = 1;
+       }
+      else if (line[0] == 'D')
+       add_deps(repo, s, SOLVABLE_REQUIRES, line + 2);
+      else if (line[0] == 'p')
+       add_deps(repo, s, SOLVABLE_PROVIDES, line + 2);
+      else if (line[0] == 'i')
+       add_deps(repo, s, SOLVABLE_SUPPLEMENTS, line + 2);
+      else if (line[0] == 'C')
+       apk_add_hdrid(data, s - pool->solvables, line + 2);
+    }
+  solv_free(line);
+}
+
+Id
+repo_add_apk_repo(Repo *repo, FILE *fp, int flags)
+{
+  struct tarhead th;
+  Repodata *data;
+
+  data = repo_add_repodata(repo, flags);
+
+  tarhead_init(&th, fp);
+  if ((flags & APK_ADD_INDEX) != 0)
+    apk_process_index(repo, data, &th);
+  else
+    {
+      while (tarhead_next(&th) > 0)
+       {
+         if (th.type != 1 || strcmp(th.path, "APKINDEX") != 0)
+           tarhead_skip(&th);
+         else
+           apk_process_index(repo, data, &th);
+       }
+    }
+  tarhead_free(&th);
+  return 0;
+}
+
diff --git a/ext/repo_apk.h b/ext/repo_apk.h
new file mode 100644 (file)
index 0000000..704899f
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2024, SUSE LLC
+ *
+ * This program is licensed under the BSD license, read LICENSE.BSD
+ * for further information
+ */
+
+#define APK_ADD_INDEX                  (1 << 8)
+#define APK_ADD_WITH_PKGID             (1 << 9)
+#define APK_ADD_WITH_HDRID             (1 << 10)
+
+extern Id repo_add_apk_pkg(Repo *repo, const char *fn, int flags);
+extern Id repo_add_apk_repo(Repo *repo, FILE *fp, int flags);
+
index 398a7d43a9a7e2ddcc43182e7ca89717704dfc11..a117a5822e81dd73ecfaf3cf31a6974f942c36c6 100644 (file)
@@ -22,7 +22,7 @@
 
 #ifndef WITHOUT_COOKIEOPEN
 
-static FILE *cookieopen(void *cookie, const char *mode,
+FILE *solv_cookieopen(void *cookie, const char *mode,
        ssize_t (*cread)(void *, char *, size_t),
        ssize_t (*cwrite)(void *, const char *, size_t),
        int (*cclose)(void *))
@@ -86,13 +86,13 @@ static int cookie_gzclose(void *cookie)
 static inline FILE *mygzfopen(const char *fn, const char *mode)
 {
   gzFile gzf = gzopen(fn, mode);
-  return cookieopen(gzf, mode, cookie_gzread, cookie_gzwrite, cookie_gzclose);
+  return solv_cookieopen(gzf, mode, cookie_gzread, cookie_gzwrite, cookie_gzclose);
 }
 
 static inline FILE *mygzfdopen(int fd, const char *mode)
 {
   gzFile gzf = gzdopen(fd, mode);
-  return cookieopen(gzf, mode, cookie_gzread, cookie_gzwrite, cookie_gzclose);
+  return solv_cookieopen(gzf, mode, cookie_gzread, cookie_gzwrite, cookie_gzclose);
 }
 
 #endif
@@ -123,13 +123,13 @@ static int cookie_bzclose(void *cookie)
 static inline FILE *mybzfopen(const char *fn, const char *mode)
 {
   BZFILE *bzf = BZ2_bzopen(fn, mode);
-  return cookieopen(bzf, mode, cookie_bzread, cookie_bzwrite, cookie_bzclose);
+  return solv_cookieopen(bzf, mode, cookie_bzread, cookie_bzwrite, cookie_bzclose);
 }
 
 static inline FILE *mybzfdopen(int fd, const char *mode)
 {
   BZFILE *bzf = BZ2_bzdopen(fd, mode);
-  return cookieopen(bzf, mode, cookie_bzread, cookie_bzwrite, cookie_bzclose);
+  return solv_cookieopen(bzf, mode, cookie_bzread, cookie_bzwrite, cookie_bzclose);
 }
 
 #endif
@@ -305,25 +305,25 @@ static ssize_t lzwrite(void *cookie, const char *buf, size_t len)
 static inline FILE *myxzfopen(const char *fn, const char *mode)
 {
   LZFILE *lzf = lzopen(fn, mode, -1, 1);
-  return cookieopen(lzf, mode, lzread, lzwrite, lzclose);
+  return solv_cookieopen(lzf, mode, lzread, lzwrite, lzclose);
 }
 
 static inline FILE *myxzfdopen(int fd, const char *mode)
 {
   LZFILE *lzf = lzopen(0, mode, fd, 1);
-  return cookieopen(lzf, mode, lzread, lzwrite, lzclose);
+  return solv_cookieopen(lzf, mode, lzread, lzwrite, lzclose);
 }
 
 static inline FILE *mylzfopen(const char *fn, const char *mode)
 {
   LZFILE *lzf = lzopen(fn, mode, -1, 0);
-  return cookieopen(lzf, mode, lzread, lzwrite, lzclose);
+  return solv_cookieopen(lzf, mode, lzread, lzwrite, lzclose);
 }
 
 static inline FILE *mylzfdopen(int fd, const char *mode)
 {
   LZFILE *lzf = lzopen(0, mode, fd, 0);
-  return cookieopen(lzf, mode, lzread, lzwrite, lzclose);
+  return solv_cookieopen(lzf, mode, lzread, lzwrite, lzclose);
 }
 
 #endif /* ENABLE_LZMA_COMPRESSION */
@@ -507,13 +507,13 @@ static ssize_t zstdwrite(void *cookie, const char *buf, size_t len)
 static inline FILE *myzstdfopen(const char *fn, const char *mode)
 {
   ZSTDFILE *zstdfile = zstdopen(fn, mode, -1);
-  return cookieopen(zstdfile, mode, zstdread, zstdwrite, zstdclose);
+  return solv_cookieopen(zstdfile, mode, zstdread, zstdwrite, zstdclose);
 }
 
 static inline FILE *myzstdfdopen(int fd, const char *mode)
 {
   ZSTDFILE *zstdfile = zstdopen(0, mode, fd);
-  return cookieopen(zstdfile, mode, zstdread, zstdwrite, zstdclose);
+  return solv_cookieopen(zstdfile, mode, zstdread, zstdwrite, zstdclose);
 }
 
 #endif
@@ -587,7 +587,7 @@ static void *zchunkopen(const char *path, const char *mode, int fd)
          return 0;
        }
     }
-  return cookieopen(f, mode, cookie_zckread, cookie_zckwrite, cookie_zckclose);
+  return solv_cookieopen(f, mode, cookie_zckread, cookie_zckwrite, cookie_zckclose);
 }
 
 #else
@@ -627,7 +627,7 @@ static void *zchunkopen(const char *path, const char *mode, int fd)
          fclose(fp);
        }
     }
-  return cookieopen(f, mode, (ssize_t (*)(void *, char *, size_t))solv_zchunk_read, 0, (int (*)(void *))solv_zchunk_close);
+  return solv_cookieopen(f, mode, (ssize_t (*)(void *, char *, size_t))solv_zchunk_read, 0, (int (*)(void *))solv_zchunk_close);
 }
 
 #endif
@@ -924,7 +924,7 @@ solv_xfopen_buf(const char *fn, char **bufp, size_t *buflp, const char *mode)
       (*bc->bufp)[0] = 0;
       *bc->buflp = 0;
     }
-  fp = cookieopen(bc, mode, cookie_bufread, cookie_bufwrite, cookie_bufclose);
+  fp = solv_cookieopen(bc, mode, cookie_bufread, cookie_bufwrite, cookie_bufclose);
   if (!strcmp(mode, "rf"))     /* auto-free */
     bc->freemem = *bufp;
   if (!fp)
@@ -948,7 +948,7 @@ solv_fmemopen(const char *buf, size_t bufl, const char *mode)
   bc->bufl_int = bufl;
   bc->bufp = &bc->buf_int;
   bc->buflp = &bc->bufl_int;
-  fp = cookieopen(bc, mode, cookie_bufread, cookie_bufwrite, cookie_bufclose);
+  fp = solv_cookieopen(bc, mode, cookie_bufread, cookie_bufwrite, cookie_bufclose);
   if (!strcmp(mode, "rf"))     /* auto-free */
     bc->freemem = bc->buf_int;
   if (!fp)
index 613f33178f14079fd7c79c91a943f3a11f095a75..b79e00936321ebcce8729b9b8c8a66b04375790c 100644 (file)
@@ -14,4 +14,6 @@ extern FILE *solv_xfopen_buf(const char *fn, char **bufp, size_t *buflp, const c
 extern int   solv_xfopen_iscompressed(const char *fn);
 extern FILE *solv_fmemopen(const char *buf, size_t bufl, const char *mode);
 
+FILE *solv_cookieopen(void *cookie, const char *mode, ssize_t (*cread)(void *, char *, size_t), ssize_t (*cwrite)(void *, const char *, size_t), int (*cclose)(void *));       /* internal */
+
 #endif
index f19030eb8c4a337a09a5d11dba9e4f184450983d..dd0477a578b25382d1482ee1a022d9e5285f2172 100644 (file)
@@ -87,6 +87,13 @@ TARGET_LINK_LIBRARIES (archrepo2solv toolstuff libsolvext libsolv ${SYSTEM_LIBRA
 SET (tools_list ${tools_list} archpkgs2solv archrepo2solv)
 ENDIF (ENABLE_ARCHREPO)
 
+IF (ENABLE_APK)
+ADD_EXECUTABLE (apk2solv apk2solv.c)
+TARGET_LINK_LIBRARIES (apk2solv toolstuff libsolvext libsolv ${SYSTEM_LIBRARIES})
+
+SET (tools_list ${tools_list} apk2solv)
+ENDIF (ENABLE_APK)
+
 IF (ENABLE_CUDFREPO)
 ADD_EXECUTABLE (cudftest cudftest.c)
 TARGET_LINK_LIBRARIES (cudftest libsolvext libsolv ${SYSTEM_LIBRARIES})