From 7d6de2203e1e4865eda4881fd559b963f230bb26 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timo=20Ter=C3=A4s?= <timo.teras@iki.fi>
Date: Mon, 8 Nov 2021 14:19:24 +0200
Subject: [PATCH] database: support loading v3 indexes

---
 src/apk_blob.h    |  1 +
 src/apk_package.h |  2 +-
 src/blob.c        |  9 +++++++++
 src/database.c    | 25 +++++++++++++++++++++++++
 src/package.c     | 39 ++++++++++++++++++++-------------------
 5 files changed, 56 insertions(+), 20 deletions(-)

diff --git a/src/apk_blob.h b/src/apk_blob.h
index 97f55032..4286fbe9 100644
--- a/src/apk_blob.h
+++ b/src/apk_blob.h
@@ -87,6 +87,7 @@ static inline apk_blob_t apk_blob_trim(apk_blob_t blob)
 }
 
 char *apk_blob_cstr(apk_blob_t str);
+apk_blob_t apk_blob_dup(apk_blob_t blob);
 int apk_blob_spn(apk_blob_t blob, const apk_spn_match accept, apk_blob_t *l, apk_blob_t *r);
 int apk_blob_cspn(apk_blob_t blob, const apk_spn_match reject, apk_blob_t *l, apk_blob_t *r);
 int apk_blob_split(apk_blob_t blob, apk_blob_t split, apk_blob_t *l, apk_blob_t *r);
diff --git a/src/apk_package.h b/src/apk_package.h
index d94d73a6..d6f955b8 100644
--- a/src/apk_package.h
+++ b/src/apk_package.h
@@ -138,7 +138,7 @@ int apk_pkg_parse_name(apk_blob_t apkname, apk_blob_t *name, apk_blob_t *version
 
 int apk_pkg_add_info(struct apk_database *db, struct apk_package *pkg,
 		     char field, apk_blob_t value);
-void apk_pkg_from_adb(struct apk_database *db, struct apk_package *pkg, struct adb_obj *pkgo);
+void apk_pkg_from_adb(struct apk_database *db, struct apk_package *pkg, struct adb_obj *pkginfo);
 
 struct apk_installed_package *apk_pkg_install(struct apk_database *db, struct apk_package *pkg);
 void apk_pkg_uninstall(struct apk_database *db, struct apk_package *pkg);
diff --git a/src/blob.c b/src/blob.c
index 2052e8e7..d5159610 100644
--- a/src/blob.c
+++ b/src/blob.c
@@ -32,6 +32,15 @@ char *apk_blob_cstr(apk_blob_t blob)
 	return cstr;
 }
 
+apk_blob_t apk_blob_dup(apk_blob_t blob)
+{
+	char *ptr = malloc(blob.len);
+	if (!ptr) return APK_BLOB_NULL;
+	memcpy(ptr, blob.ptr, blob.len);
+	return APK_BLOB_PTR_LEN(ptr, blob.len);
+}
+
+
 #if defined(__i386__)
 static unsigned long inline memspn(
 		const unsigned char *ptr,
diff --git a/src/database.c b/src/database.c
index a3a5800d..4f0722bc 100644
--- a/src/database.c
+++ b/src/database.c
@@ -2176,8 +2176,33 @@ static int load_v2index(struct apk_extract_ctx *ectx, apk_blob_t *desc, struct a
 	return apk_db_index_read(ctx->db, is, ctx->repo);
 }
 
+static int load_v3index(struct apk_extract_ctx *ectx, struct adb_obj *ndx)
+{
+	struct apkindex_ctx *ctx = container_of(ectx, struct apkindex_ctx, ectx);
+	struct apk_database *db = ctx->db;
+	struct apk_repository *repo = &db->repos[ctx->repo];
+	struct apk_package *pkg;
+	struct adb_obj pkgs, pkginfo;
+	int i;
+
+	repo->description = apk_blob_dup(adb_ro_blob(ndx, ADBI_NDX_DESCRIPTION));
+	adb_ro_obj(ndx, ADBI_NDX_PACKAGES, &pkgs);
+
+	for (i = ADBI_FIRST; i <= adb_ra_num(&pkgs); i++) {
+		adb_ro_obj(&pkgs, i, &pkginfo);
+		pkg = apk_pkg_new();
+		if (!pkg) return -ENOMEM;
+		apk_pkg_from_adb(db, pkg, &pkginfo);
+		pkg->repos |= BIT(ctx->repo);
+		if (!apk_db_pkg_add(db, pkg)) return -APKE_ADB_SCHEMA;
+	}
+
+	return 0;
+}
+
 static const struct apk_extract_ops extract_index = {
 	.v2index = load_v2index,
+	.v3index = load_v3index,
 };
 
 static int load_index(struct apk_database *db, struct apk_istream *is, int repo)
diff --git a/src/package.c b/src/package.c
index f08101ff..3c042907 100644
--- a/src/package.c
+++ b/src/package.c
@@ -583,34 +583,32 @@ static char *commit_id(apk_blob_t b)
 	return apk_blob_cstr(to);
 }
 
-void apk_pkg_from_adb(struct apk_database *db, struct apk_package *pkg, struct adb_obj *pkgo)
+void apk_pkg_from_adb(struct apk_database *db, struct apk_package *pkg, struct adb_obj *pkginfo)
 {
-	struct adb_obj pkginfo, obj;
+	struct adb_obj obj;
 	apk_blob_t uid;
 
-	adb_ro_obj(pkgo, ADBI_PKG_PKGINFO, &pkginfo);
-
-	uid = adb_ro_blob(&pkginfo, ADBI_PI_UNIQUE_ID);
+	uid = adb_ro_blob(pkginfo, ADBI_PI_UNIQUE_ID);
 	if (uid.len >= APK_CHECKSUM_SHA1) {
 		pkg->csum.type = APK_CHECKSUM_SHA1;
 		memcpy(pkg->csum.data, uid.ptr, uid.len);
 	}
 
-	pkg->name = apk_db_get_name(db, adb_ro_blob(&pkginfo, ADBI_PI_NAME));
-	pkg->version = apk_atomize_dup(&db->atoms, adb_ro_blob(&pkginfo, ADBI_PI_VERSION));
-	pkg->description = apk_blob_cstr(adb_ro_blob(&pkginfo, ADBI_PI_DESCRIPTION));
-	pkg->url = apk_blob_cstr(adb_ro_blob(&pkginfo, ADBI_PI_URL));
-	pkg->license = apk_atomize_dup(&db->atoms, adb_ro_blob(&pkginfo, ADBI_PI_LICENSE));
-	pkg->arch = apk_atomize_dup(&db->atoms, adb_ro_blob(&pkginfo, ADBI_PI_ARCH));
-	pkg->installed_size = adb_ro_int(&pkginfo, ADBI_PI_INSTALLED_SIZE);
-	pkg->origin = apk_atomize_dup(&db->atoms, adb_ro_blob(&pkginfo, ADBI_PI_ORIGIN));
-	pkg->maintainer = apk_atomize_dup(&db->atoms, adb_ro_blob(&pkginfo, ADBI_PI_MAINTAINER));
-	pkg->build_time = adb_ro_int(&pkginfo, ADBI_PI_BUILD_TIME);
-	pkg->commit = commit_id(adb_ro_blob(&pkginfo, ADBI_PI_REPO_COMMIT));
+	pkg->name = apk_db_get_name(db, adb_ro_blob(pkginfo, ADBI_PI_NAME));
+	pkg->version = apk_atomize_dup(&db->atoms, adb_ro_blob(pkginfo, ADBI_PI_VERSION));
+	pkg->description = apk_blob_cstr(adb_ro_blob(pkginfo, ADBI_PI_DESCRIPTION));
+	pkg->url = apk_blob_cstr(adb_ro_blob(pkginfo, ADBI_PI_URL));
+	pkg->license = apk_atomize_dup(&db->atoms, adb_ro_blob(pkginfo, ADBI_PI_LICENSE));
+	pkg->arch = apk_atomize_dup(&db->atoms, adb_ro_blob(pkginfo, ADBI_PI_ARCH));
+	pkg->installed_size = adb_ro_int(pkginfo, ADBI_PI_INSTALLED_SIZE);
+	pkg->origin = apk_atomize_dup(&db->atoms, adb_ro_blob(pkginfo, ADBI_PI_ORIGIN));
+	pkg->maintainer = apk_atomize_dup(&db->atoms, adb_ro_blob(pkginfo, ADBI_PI_MAINTAINER));
+	pkg->build_time = adb_ro_int(pkginfo, ADBI_PI_BUILD_TIME);
+	pkg->commit = commit_id(adb_ro_blob(pkginfo, ADBI_PI_REPO_COMMIT));
 
-	apk_deps_from_adb(&pkg->depends, db, adb_ro_obj(&pkginfo, ADBI_PI_DEPENDS, &obj));
-	apk_deps_from_adb(&pkg->provides, db, adb_ro_obj(&pkginfo, ADBI_PI_PROVIDES, &obj));
-	apk_deps_from_adb(&pkg->install_if, db, adb_ro_obj(&pkginfo, ADBI_PI_INSTALL_IF, &obj));
+	apk_deps_from_adb(&pkg->depends, db, adb_ro_obj(pkginfo, ADBI_PI_DEPENDS, &obj));
+	apk_deps_from_adb(&pkg->provides, db, adb_ro_obj(pkginfo, ADBI_PI_PROVIDES, &obj));
+	apk_deps_from_adb(&pkg->install_if, db, adb_ro_obj(pkginfo, ADBI_PI_INSTALL_IF, &obj));
 }
 
 static int read_info_line(struct read_info_ctx *ri, apk_blob_t line)
@@ -668,10 +666,13 @@ static int apk_pkg_v2meta(struct apk_extract_ctx *ectx, struct apk_istream *is)
 static int apk_pkg_v3meta(struct apk_extract_ctx *ectx, struct adb_obj *pkg)
 {
 	struct read_info_ctx *ri = container_of(ectx, struct read_info_ctx, ectx);
+	struct adb_obj pkginfo;
 
 	if (!ri->v3ok) return -APKE_FORMAT_NOT_SUPPORTED;
 
+	adb_ro_obj(pkg, ADBI_PKG_PKGINFO, &pkginfo);
 	apk_pkg_from_adb(ri->db, ri->pkg, pkg);
+
 	return -ECANCELED;
 }
 
-- 
GitLab