]> git.ipfire.org Git - thirdparty/libsolv.git/commitdiff
Implement decompression in repo_add_apk_repo()
authorMichael Schroeder <mls@suse.de>
Tue, 17 Dec 2024 11:11:25 +0000 (12:11 +0100)
committerMichael Schroeder <mls@suse.de>
Tue, 17 Dec 2024 11:15:00 +0000 (12:15 +0100)
We need this to support apkv3 index files.

ext/repo_apk.c
ext/repo_apk.h
tools/apk2solv.c

index e2177cf937536df9f85d685bdb18f040f75e3736..481d63e1d4b9d468785a72b2dad7c76febde2e96 100644 (file)
 
 struct zstream {
   int fd;
+  FILE *fp;
   int eof;
   z_stream zs;
   unsigned char buf[65536];
   void (*readcb)(void *, const void *, int);
   void *readcb_data;
+  int doall;
 };
 
 static struct zstream *
@@ -59,6 +61,40 @@ apkz_close(void *cookie)
   return 0;
 }
 
+static inline ssize_t
+apkz_fillbuf(struct zstream *zstream)
+{
+  ssize_t rr;
+  if (zstream->fp)
+    {
+      rr = fread(zstream->buf, 1, sizeof(zstream->buf), zstream->fp);
+      if (rr <= 0 && ferror(zstream->fp))
+       rr = -1;
+    }
+  else
+    rr = read(zstream->fd, zstream->buf, sizeof(zstream->buf));
+  if (rr >= 0)
+    {
+      zstream->zs.avail_in = rr;
+      zstream->zs.next_in = zstream->buf;
+    }
+  return rr;
+}
+
+static int
+apkz_reset(struct zstream *zstream)
+{
+  zstream->eof = 0;
+  if (zstream->zs.avail_in == 0)
+    {
+      ssize_t rr = apkz_fillbuf(zstream);
+      if (rr <= 0)
+       return rr < 0 ? -1 : 0;
+    }
+  inflateReset(&zstream->zs);
+  return 1;
+}
+
 static ssize_t
 apkz_read(void *cookie, char *buf, size_t len)
 {
@@ -76,13 +112,11 @@ apkz_read(void *cookie, char *buf, size_t len)
     {
       if (zstream->zs.avail_in == 0)
        {
-         ssize_t rr = read(zstream->fd, zstream->buf, sizeof(zstream->buf));
+         ssize_t rr = apkz_fillbuf(zstream);
          if (rr < 0)
            return rr;
          if (rr == 0)
-             eof = 1;
-         zstream->zs.avail_in = rr;
-         zstream->zs.next_in = zstream->buf;
+           eof = 1;
        }
       old_avail_in = zstream->zs.avail_in;
       r = inflate(&zstream->zs, Z_NO_FLUSH);
@@ -96,6 +130,8 @@ apkz_read(void *cookie, char *buf, size_t len)
 
       if (r == Z_STREAM_END)
        {
+         if (zstream->doall && apkz_reset(zstream) > 0)
+           continue;
          zstream->eof = 1;
          return len - zstream->zs.avail_out;
        }
@@ -108,22 +144,6 @@ apkz_read(void *cookie, char *buf, size_t len)
     }
 }
 
-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)
 {
@@ -209,11 +229,12 @@ repo_add_apk_pkg(Repo *repo, const char *fn, int flags)
       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;
-  }
+  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)
@@ -464,15 +485,41 @@ apk_process_index(Repo *repo, Repodata *data, struct tarhead *th)
   solv_free(line);
 }
 
-Id
+int
 repo_add_apk_repo(Repo *repo, FILE *fp, int flags)
 {
   struct tarhead th;
   Repodata *data;
+  int c;
+  int close_fp = 0;
 
   data = repo_add_repodata(repo, flags);
 
+  /* peek into first byte to find out if this is a compressed file */
+  c = fgetc(fp);
+  if (c == EOF)
+    return -1;
+  ungetc(c, fp);
+
+  if (c == 0x1f)
+    {
+      struct zstream *zstream;
+      /* gzip compressed, setup decompression */
+      zstream = apkz_open(-1);
+      if (!zstream)
+       return -1;
+      zstream->fp = fp;
+      zstream->doall = 1;
+      if ((fp = solv_cookieopen(zstream, "r", apkz_read, 0, apkz_close)) == 0)
+       {
+         apkz_close(zstream);
+         return -1;
+        }
+      close_fp = 1;
+    }
+
   tarhead_init(&th, fp);
+  
   if ((flags & APK_ADD_INDEX) != 0)
     apk_process_index(repo, data, &th);
   else
@@ -486,6 +533,8 @@ repo_add_apk_repo(Repo *repo, FILE *fp, int flags)
        }
     }
   tarhead_free(&th);
+  if (close_fp)
+    fclose(fp);
   return 0;
 }
 
index 704899f4bd81b5a04616aa9eda2c2e3c1dd51166..8b3a7af3598e7a5ac6ab8b266216f856c170e234 100644 (file)
@@ -10,5 +10,5 @@
 #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);
+extern int repo_add_apk_repo(Repo *repo, FILE *fp, int flags);
 
index a6e5ee43c945c3f151582e8eefe2208746238059..93c7a1350e2c381f5499b76255fc16e94ff776ae 100644 (file)
@@ -132,21 +132,18 @@ main(int argc, char **argv)
        flags |= APK_ADD_INDEX;
       if (!npkgs)
        {
-         FILE *fp = islocaldb ? stdin : solv_xfopen_fd("stdin.tar.gz", 0, "r");;
-         if (repo_add_apk_repo(repo, fp, REPO_REUSE_REPODATA|REPO_NO_INTERNALIZE|flags) != 0)
+         if (repo_add_apk_repo(repo, stdin, REPO_REUSE_REPODATA|REPO_NO_INTERNALIZE|flags) != 0)
            {
              fprintf(stderr, "apk2solv: %s\n", pool_errstr(pool));
              res = 1;
            }
-         if (fp != stdin)
-           fclose(fp);
        }
       else 
        {
          for (i = 0; i < npkgs; i++)
            {
              FILE *fp;
-             if (!(fp = solv_xfopen(pkgs[i], "r")))
+             if (!(fp = fopen(pkgs[i], "r")))
                {
                  perror(pkgs[i]);
                  res = 1;