From: Michael Schroeder Date: Tue, 17 Dec 2024 11:11:25 +0000 (+0100) Subject: Implement decompression in repo_add_apk_repo() X-Git-Tag: 0.7.32~25 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e423f277a9eddb8953d25a3f46a44b762b94b1bd;p=thirdparty%2Flibsolv.git Implement decompression in repo_add_apk_repo() We need this to support apkv3 index files. --- diff --git a/ext/repo_apk.c b/ext/repo_apk.c index e2177cf9..481d63e1 100644 --- a/ext/repo_apk.c +++ b/ext/repo_apk.c @@ -28,11 +28,13 @@ 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; } diff --git a/ext/repo_apk.h b/ext/repo_apk.h index 704899f4..8b3a7af3 100644 --- a/ext/repo_apk.h +++ b/ext/repo_apk.h @@ -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); diff --git a/tools/apk2solv.c b/tools/apk2solv.c index a6e5ee43..93c7a135 100644 --- a/tools/apk2solv.c +++ b/tools/apk2solv.c @@ -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;