diff options
Diffstat (limited to 'src/apk_adbschema.c')
-rw-r--r-- | src/apk_adbschema.c | 270 |
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), + }, +}; |