aboutsummaryrefslogtreecommitdiffstats
path: root/src/apk_adbschema.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/apk_adbschema.c')
-rw-r--r--src/apk_adbschema.c270
1 files changed, 270 insertions, 0 deletions
diff --git a/src/apk_adbschema.c b/src/apk_adbschema.c
new file mode 100644
index 0000000000..1c3a08cf82
--- /dev/null
+++ b/src/apk_adbschema.c
@@ -0,0 +1,270 @@
+#include "adb.h"
+#include "apk_adb.h"
+#include "apk_print.h"
+#include "apk_version.h"
+
+#define APK_VERSION_CONFLICT 16
+
+static apk_blob_t string_tostring(struct adb *db, adb_val_t val, char *buf, size_t bufsz)
+{
+ return adb_r_blob(db, val);
+}
+
+static struct adb_scalar_schema scalar_string = {
+ .kind = ADB_KIND_BLOB,
+ .tostring = string_tostring,
+};
+
+static apk_blob_t hexblob_tostring(struct adb *db, adb_val_t val, char *buf, size_t bufsz)
+{
+ apk_blob_t b = adb_r_blob(db, val), to = APK_BLOB_PTR_LEN(buf, bufsz);
+
+ if (APK_BLOB_IS_NULL(b)) return b;
+
+ apk_blob_push_hexdump(&to, b);
+ if (!APK_BLOB_IS_NULL(to))
+ return APK_BLOB_PTR_PTR(buf, to.ptr-1);
+
+ return APK_BLOB_PTR_LEN(buf, snprintf(buf, bufsz, "(%ld bytes)", b.len));
+}
+
+static struct adb_scalar_schema scalar_hexblob = {
+ .kind = ADB_KIND_BLOB,
+ .tostring = hexblob_tostring,
+};
+
+static apk_blob_t int_tostring(struct adb *db, adb_val_t val, char *buf, size_t bufsz)
+{
+ return APK_BLOB_PTR_LEN(buf, snprintf(buf, bufsz, "%u", adb_r_int(db, val)));
+}
+
+static struct adb_scalar_schema scalar_int = {
+ .kind = ADB_KIND_INT,
+ .tostring = int_tostring,
+};
+
+static apk_blob_t oct_tostring(struct adb *db, adb_val_t val, char *buf, size_t bufsz)
+{
+ return APK_BLOB_PTR_LEN(buf, snprintf(buf, bufsz, "%o", adb_r_int(db, val)));
+}
+
+static struct adb_scalar_schema scalar_oct = {
+ .kind = ADB_KIND_INT,
+ .tostring = oct_tostring,
+};
+
+static apk_blob_t hsize_tostring(struct adb *db, adb_val_t val, char *buf, size_t bufsz)
+{
+ off_t v = adb_r_int(db, val);
+ const char *unit = apk_get_human_size(v, &v);
+
+ return APK_BLOB_PTR_LEN(buf, snprintf(buf, bufsz, "%jd %s", (intmax_t)v, unit));
+}
+
+static struct adb_scalar_schema scalar_hsize = {
+ .kind = ADB_KIND_INT,
+ .tostring = hsize_tostring,
+};
+
+static apk_blob_t dependency_tostring(struct adb *db, adb_val_t val, char *buf, size_t bufsz)
+{
+ struct adb_obj o;
+ apk_blob_t name, ver;
+ unsigned int mask;
+
+ adb_r_obj(db, val, &o, &schema_dependency);
+ name = adb_ro_blob(&o, ADBI_DEP_NAME);
+ ver = adb_ro_blob(&o, ADBI_DEP_VERSION);
+
+ if (APK_BLOB_IS_NULL(name)) return APK_BLOB_NULL;
+ if (APK_BLOB_IS_NULL(ver)) return name;
+
+ mask = adb_ro_int(&o, ADBI_DEP_MATCH) ?: APK_VERSION_EQUAL;
+ return APK_BLOB_PTR_LEN(buf,
+ snprintf(buf, bufsz, "%s"BLOB_FMT"%s"BLOB_FMT,
+ (mask & APK_VERSION_CONFLICT) ? "!" : "",
+ BLOB_PRINTF(name),
+ apk_version_op_string(mask & ~APK_VERSION_CONFLICT),
+ BLOB_PRINTF(ver)));
+}
+
+const struct adb_object_schema schema_dependency = {
+ .kind = ADB_KIND_OBJECT,
+ .num_fields = ADBI_DEP_MAX,
+ .tostring = dependency_tostring,
+ .fields = {
+ ADB_FIELD(ADBI_DEP_NAME, "name", scalar_string),
+ ADB_FIELD(ADBI_DEP_VERSION, "version", scalar_string),
+ ADB_FIELD(ADBI_DEP_MATCH, "match", scalar_int),
+ },
+};
+
+const struct adb_object_schema schema_dependency_array = {
+ .kind = ADB_KIND_ARRAY,
+ .num_fields = APK_MAX_PKG_DEPENDENCIES,
+ .fields = ADB_ARRAY_ITEM(schema_dependency),
+};
+
+static int pkginfo_cmp(struct adb_obj *o1, struct adb_obj *o2)
+{
+ int r;
+ r = apk_blob_sort(
+ adb_ro_blob(o1, ADBI_PI_NAME),
+ adb_ro_blob(o2, ADBI_PI_NAME));
+ if (r) return r;
+
+ r = apk_version_compare_blob(
+ adb_ro_blob(o1, ADBI_PI_VERSION),
+ adb_ro_blob(o2, ADBI_PI_VERSION));
+ switch (r) {
+ case APK_VERSION_LESS: return -1;
+ case APK_VERSION_GREATER: return 1;
+ }
+ return 0;
+}
+
+const struct adb_object_schema schema_pkginfo = {
+ .kind = ADB_KIND_OBJECT,
+ .num_fields = ADBI_PI_MAX,
+ .compare = pkginfo_cmp,
+ .fields = {
+ ADB_FIELD(ADBI_PI_NAME, "name", scalar_string),
+ ADB_FIELD(ADBI_PI_VERSION, "version", scalar_string),
+ ADB_FIELD(ADBI_PI_UNIQUE_ID, "unique-id", scalar_int),
+ ADB_FIELD(ADBI_PI_DESCRIPTION, "description", scalar_string),
+ ADB_FIELD(ADBI_PI_ARCH, "arch", scalar_string),
+ ADB_FIELD(ADBI_PI_LICENSE, "license", scalar_string),
+ ADB_FIELD(ADBI_PI_ORIGIN, "origin", scalar_string),
+ ADB_FIELD(ADBI_PI_MAINTAINER, "maintainer", scalar_string),
+ ADB_FIELD(ADBI_PI_URL, "url", scalar_string),
+ ADB_FIELD(ADBI_PI_REPO_COMMIT, "repo-commit", scalar_hexblob),
+ ADB_FIELD(ADBI_PI_BUILD_TIME, "build-time", scalar_int),
+ ADB_FIELD(ADBI_PI_INSTALLED_SIZE,"installed-size",scalar_hsize),
+ ADB_FIELD(ADBI_PI_FILE_SIZE, "file-size", scalar_hsize),
+ ADB_FIELD(ADBI_PI_PRIORITY, "priority", scalar_int),
+ ADB_FIELD(ADBI_PI_DEPENDS, "depends", schema_dependency_array),
+ ADB_FIELD(ADBI_PI_PROVIDES, "provides", schema_dependency_array),
+ ADB_FIELD(ADBI_PI_REPLACES, "replaces", schema_dependency_array),
+ ADB_FIELD(ADBI_PI_INSTALL_IF, "install-if", schema_dependency_array),
+ ADB_FIELD(ADBI_PI_RECOMMENDS, "recommends", schema_dependency_array),
+ },
+};
+
+const struct adb_object_schema schema_pkginfo_array = {
+ .kind = ADB_KIND_ARRAY,
+ .num_fields = APK_MAX_INDEX_PACKAGES,
+ .pre_commit = adb_wa_sort,
+ .fields = ADB_ARRAY_ITEM(schema_pkginfo),
+};
+
+const struct adb_object_schema schema_index = {
+ .kind = ADB_KIND_OBJECT,
+ .num_fields = ADBI_NDX_MAX,
+ .fields = {
+ ADB_FIELD(ADBI_NDX_DESCRIPTION, "description", scalar_string),
+ ADB_FIELD(ADBI_NDX_PACKAGES, "packages", schema_pkginfo_array),
+ },
+};
+
+static uint32_t file_get_default_int(unsigned i)
+{
+ switch (i) {
+ case ADBI_FI_UID:
+ case ADBI_FI_GID:
+ return 0;
+ case ADBI_FI_MODE:
+ return 0644;
+ }
+ return -1;
+}
+
+static int file_cmp(struct adb_obj *o1, struct adb_obj *o2)
+{
+ return apk_blob_sort(
+ adb_ro_blob(o1, ADBI_FI_NAME),
+ adb_ro_blob(o2, ADBI_FI_NAME));
+}
+
+const struct adb_object_schema schema_file = {
+ .kind = ADB_KIND_OBJECT,
+ .num_fields = ADBI_FI_MAX,
+ .get_default_int = file_get_default_int,
+ .compare = file_cmp,
+ .fields = {
+ ADB_FIELD(ADBI_FI_NAME, "name", scalar_string),
+ ADB_FIELD(ADBI_FI_HASHES, "hash", scalar_hexblob),
+ ADB_FIELD(ADBI_FI_UID, "uid", scalar_int),
+ ADB_FIELD(ADBI_FI_GID, "gid", scalar_int),
+ ADB_FIELD(ADBI_FI_MODE, "mode", scalar_oct),
+ ADB_FIELD(ADBI_FI_XATTRS, "xattr", scalar_hexblob),
+ },
+};
+
+const struct adb_object_schema schema_file_array = {
+ .kind = ADB_KIND_ARRAY,
+ .pre_commit = adb_wa_sort,
+ .num_fields = APK_MAX_MANIFEST_FILES,
+ .fields = ADB_ARRAY_ITEM(schema_file),
+};
+
+static uint32_t path_get_default_int(unsigned i)
+{
+ switch (i) {
+ case ADBI_FI_UID:
+ case ADBI_FI_GID:
+ return 0;
+ case ADBI_FI_MODE:
+ return 0755;
+ }
+ return -1;
+}
+
+const struct adb_object_schema schema_path = {
+ .kind = ADB_KIND_OBJECT,
+ .num_fields = ADBI_FI_MAX,
+ .get_default_int = path_get_default_int,
+ .compare = file_cmp,
+ .fields = {
+ ADB_FIELD(ADBI_FI_NAME, "name", scalar_string),
+ ADB_FIELD(ADBI_FI_FILES, "files", schema_file_array),
+ ADB_FIELD(ADBI_FI_UID, "uid", scalar_int),
+ ADB_FIELD(ADBI_FI_GID, "gid", scalar_int),
+ ADB_FIELD(ADBI_FI_MODE, "mode", scalar_oct),
+ ADB_FIELD(ADBI_FI_XATTRS, "xattr", scalar_hexblob),
+ },
+};
+
+const struct adb_object_schema schema_path_array = {
+ .kind = ADB_KIND_ARRAY,
+ .pre_commit = adb_wa_sort,
+ .num_fields = APK_MAX_MANIFEST_PATHS,
+ .fields = ADB_ARRAY_ITEM(schema_path),
+};
+
+const struct adb_object_schema schema_package = {
+ .kind = ADB_KIND_OBJECT,
+ .num_fields = ADBI_PKG_MAX,
+ .fields = {
+ ADB_FIELD(ADBI_PKG_PKGINFO, "info", schema_pkginfo),
+ ADB_FIELD(ADBI_PKG_PATHS, "paths", schema_path_array),
+ },
+};
+
+const struct adb_adb_schema schema_package_adb = {
+ .kind = ADB_KIND_ADB,
+ .schema_id = ADB_SCHEMA_PACKAGE,
+};
+
+const struct adb_object_schema schema_package_adb_array = {
+ .kind = ADB_KIND_ARRAY,
+ .num_fields = APK_MAX_INDEX_PACKAGES,
+ .fields = ADB_ARRAY_ITEM(schema_package_adb),
+};
+
+const struct adb_object_schema schema_idb = {
+ .kind = ADB_KIND_OBJECT,
+ .num_fields = ADBI_IDB_MAX,
+ .fields = {
+ ADB_FIELD(ADBI_IDB_PACKAGES, "packages", schema_package_adb_array),
+ },
+};