From 40f08663679246edaa578d87e9f153adaad62a87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Fri, 3 Sep 2021 16:29:55 +0300 Subject: [PATCH] db, add: support adding v3 package files --- src/adb.c | 4 +-- src/apk_crypto.h | 8 +++-- src/apk_extract.h | 2 ++ src/apk_package.h | 7 +++- src/app_add.c | 2 +- src/app_index.c | 2 +- src/database.c | 40 ++++++++++++++++++++- src/extract_v3.c | 3 ++ src/package.c | 90 +++++++++++++++++++++++++++++++++++++++++++---- 9 files changed, 144 insertions(+), 14 deletions(-) diff --git a/src/adb.c b/src/adb.c index f1a4937..ee992cf 100644 --- a/src/adb.c +++ b/src/adb.c @@ -253,11 +253,11 @@ static int __adb_m_stream(struct adb *db, struct apk_istream *is, uint32_t expec } while (1); err: if (r > 0) r = -APKE_ADB_BLOCK; - if (r == 0) { + if (r == 0 || r == -ECANCELED) { if (!trusted) r = -APKE_SIGNATURE_UNTRUSTED; else if (!db->adb.ptr) r = -APKE_ADB_BLOCK; } - if (r != 0) { + if (r != 0 && r != -ECANCELED) { free(db->adb.ptr); db->adb = APK_BLOB_NULL; } diff --git a/src/apk_crypto.h b/src/apk_crypto.h index 4eab130..43b4bd2 100644 --- a/src/apk_crypto.h +++ b/src/apk_crypto.h @@ -120,8 +120,12 @@ static inline int apk_digest_cmp_csum(const struct apk_digest *d, const struct a } static inline void apk_checksum_from_digest(struct apk_checksum *csum, const struct apk_digest *d) { - csum->type = d->len; - memcpy(csum->data, d->data, d->len); + if (d->len > sizeof csum->data) { + csum->type = APK_CHECKSUM_NONE; + } else { + csum->type = d->len; + memcpy(csum->data, d->data, d->len); + } } // Asymmetric keys diff --git a/src/apk_extract.h b/src/apk_extract.h index c44ed87..2a25638 100644 --- a/src/apk_extract.h +++ b/src/apk_extract.h @@ -18,6 +18,8 @@ struct adb_obj; struct apk_ctx; struct apk_extract_ctx; +#define APK_EXTRACT_SKIP_FILE 0x111 + #define APK_EXTRACTF_NO_CHOWN 0x0001 #define APK_EXTRACTF_NO_OVERWRITE 0x0002 diff --git a/src/apk_package.h b/src/apk_package.h index c6545c2..246b2ae 100644 --- a/src/apk_package.h +++ b/src/apk_package.h @@ -15,6 +15,7 @@ #include "apk_io.h" #include "apk_solver_data.h" +struct adb_obj; struct apk_database; struct apk_name; struct apk_provider; @@ -119,6 +120,9 @@ void apk_blob_pull_deps(apk_blob_t *from, struct apk_database *, struct apk_depe int apk_deps_write(struct apk_database *db, struct apk_dependency_array *deps, struct apk_ostream *os, apk_blob_t separator); +void apk_dep_from_adb(struct apk_dependency *dep, struct apk_database *db, struct adb_obj *d); +void apk_deps_from_adb(struct apk_dependency_array **deps, struct apk_database *db, struct adb_obj *da); + void apk_deps_add(struct apk_dependency_array **depends, struct apk_dependency *dep); void apk_deps_del(struct apk_dependency_array **deps, struct apk_name *name); int apk_script_type(const char *name); @@ -126,13 +130,14 @@ int apk_script_type(const char *name); struct apk_package *apk_pkg_get_installed(struct apk_name *name); struct apk_package *apk_pkg_new(void); -int apk_pkg_read(struct apk_database *db, const char *name, struct apk_package **pkg); +int apk_pkg_read(struct apk_database *db, const char *name, struct apk_package **pkg, int v3ok); void apk_pkg_free(struct apk_package *pkg); 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); 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/app_add.c b/src/app_add.c index 214bf67..1d20e81 100644 --- a/src/app_add.c +++ b/src/app_add.c @@ -160,7 +160,7 @@ static int add_main(void *ctx, struct apk_ctx *ac, struct apk_string_array *args if (non_repository_check(db)) return -1; - r = apk_pkg_read(db, *parg, &pkg); + r = apk_pkg_read(db, *parg, &pkg, TRUE); if (r != 0) { apk_err(out, "%s: %s", *parg, apk_error_str(r)); return -1; diff --git a/src/app_index.c b/src/app_index.c index 741bcf9..f38af63 100644 --- a/src/app_index.c +++ b/src/app_index.c @@ -182,7 +182,7 @@ static int index_main(void *ctx, struct apk_ctx *ac, struct apk_string_array *ar } while (0); if (!found) { - r = apk_pkg_read(db, *parg, &pkg); + r = apk_pkg_read(db, *parg, &pkg, FALSE); if (r < 0) { apk_err(out, "%s: %s", *parg, apk_error_str(r)); errors++; diff --git a/src/database.c b/src/database.c index f64d706..144dd34 100644 --- a/src/database.c +++ b/src/database.c @@ -36,6 +36,7 @@ #include "apk_print.h" #include "apk_openssl.h" #include "apk_tar.h" +#include "apk_adb.h" static const apk_spn_match_def apk_spn_repo_separators = { [1] = (1<<1) /* tab */, @@ -2374,6 +2375,29 @@ static int apk_db_install_v2meta(struct apk_extract_ctx *ectx, struct apk_istrea return 0; } +static int apk_db_install_v3meta(struct apk_extract_ctx *ectx, struct adb_obj *pkg) +{ + struct install_ctx *ctx = container_of(ectx, struct install_ctx, ectx); + struct apk_database *db = ctx->db; + struct apk_installed_package *ipkg = ctx->ipkg; + struct adb_obj triggers, pkginfo, obj; + int i; + + apk_pkg_from_adb(db, ctx->pkg, pkg); + adb_ro_obj(pkg, ADBI_PKG_PKGINFO, &pkginfo); + apk_deps_from_adb(&ipkg->replaces, db, adb_ro_obj(&pkginfo, ADBI_PI_REPLACES, &obj)); + ipkg->replaces_priority = adb_ro_int(&pkginfo, ADBI_PI_PRIORITY); + + apk_string_array_resize(&ipkg->triggers, 0); + adb_ro_obj(pkg, ADBI_PKG_TRIGGERS, &triggers); + for (i = ADBI_FIRST; i <= adb_ra_num(&triggers); i++) + *apk_string_array_add(&ipkg->triggers) = apk_blob_cstr(adb_ro_blob(&triggers, i)); + if (ctx->ipkg->triggers->num != 0 && !list_hashed(&ipkg->trigger_pkgs_list)) + list_add_tail(&ipkg->trigger_pkgs_list, &db->installed.triggers); + + return 0; +} + static int apk_db_install_script(struct apk_extract_ctx *ectx, unsigned int type, size_t size, struct apk_istream *is) { struct install_ctx *ctx = container_of(ectx, struct install_ctx, ectx); @@ -2412,6 +2436,13 @@ static int apk_db_install_file(struct apk_extract_ctx *ectx, const struct apk_fi return 0; } + if (ae->uvol_name) { + apk_warn(out, PKG_VER_FMT": %s: uvol not supported yet", + PKG_VER_PRINTF(pkg), ae->name); + ipkg->broken_files = 1; + return APK_EXTRACT_SKIP_FILE; + } + /* Installable entry */ ctx->current_file_size = apk_calc_installed_size(ae->size); if (!S_ISDIR(ae->mode)) { @@ -2542,13 +2573,19 @@ static int apk_db_install_file(struct apk_extract_ctx *ectx, const struct apk_fi else apk_checksum_from_digest(&file->csum, &ae->digest); /* only warn once per package */ - if (file->csum.type == APK_CHECKSUM_NONE && !ctx->missing_checksum) { + if (ae->digest.alg == APK_DIGEST_NONE && !ctx->missing_checksum) { apk_warn(out, PKG_VER_FMT": support for packages without embedded " "checksums will be dropped in apk-tools 3.", PKG_VER_PRINTF(pkg)); ipkg->broken_files = 1; ctx->missing_checksum = 1; + } else if (file->csum.type == APK_CHECKSUM_NONE && !ctx->missing_checksum) { + apk_warn(out, + PKG_VER_FMT": v3 checksums ignored", + PKG_VER_PRINTF(pkg)); + ipkg->broken_files = 1; + ctx->missing_checksum = 1; } break; case -ENOTSUP: @@ -2580,6 +2617,7 @@ static int apk_db_install_file(struct apk_extract_ctx *ectx, const struct apk_fi static const struct apk_extract_ops extract_installer = { .v2meta = apk_db_install_v2meta, + .v3meta = apk_db_install_v3meta, .script = apk_db_install_script, .file = apk_db_install_file, }; diff --git a/src/extract_v3.c b/src/extract_v3.c index a5a1459..dcc5c24 100644 --- a/src/extract_v3.c +++ b/src/extract_v3.c @@ -93,6 +93,8 @@ static int apk_extract_v3_file(struct apk_extract_ctx *ectx, off_t sz, struct ap fi.mode |= S_IFREG; r = ectx->ops->file(ectx, &fi, apk_istream_verify(&dis, is, &fi.digest)); + if (r == APK_EXTRACT_SKIP_FILE) + return 0; return apk_istream_close_error(&dis.is, r); } @@ -255,6 +257,7 @@ int apk_extract_v3(struct apk_extract_ctx *ectx, struct apk_istream *is) } } if (r == -ECANCELED) r = 0; + if (r == 0 && !ctx.db.adb.len) r = -APKE_ADB_BLOCK; adb_free(&ctx.db); apk_extract_reset(ectx); diff --git a/src/package.c b/src/package.c index 3b634d6..cba999f 100644 --- a/src/package.c +++ b/src/package.c @@ -27,6 +27,7 @@ #include "apk_database.h" #include "apk_print.h" #include "apk_extract.h" +#include "apk_adb.h" const apk_spn_match_def apk_spn_dependency_comparer = { [7] = (1<<4) /*<*/ | (1<<5) /*=*/ | (1<<6) /*<*/, @@ -448,6 +449,27 @@ int apk_deps_write(struct apk_database *db, struct apk_dependency_array *deps, s return n; } +void apk_dep_from_adb(struct apk_dependency *dep, struct apk_database *db, struct adb_obj *d) +{ + *dep = (struct apk_dependency) { + .name = apk_db_get_name(db, adb_ro_blob(d, ADBI_DEP_NAME)), + .version = apk_atomize_dup(&db->atoms, adb_ro_blob(d, ADBI_DEP_VERSION)), + .result_mask = adb_ro_int(d, ADBI_DEP_MATCH) ?: APK_VERSION_EQUAL, + }; +} + +void apk_deps_from_adb(struct apk_dependency_array **deps, struct apk_database *db, struct adb_obj *da) +{ + struct adb_obj obj; + int i; + + for (i = ADBI_FIRST; i <= adb_ra_num(da); i++) { + struct apk_dependency *d = apk_dependency_array_add(deps); + adb_ro_obj(da, i, &obj); + apk_dep_from_adb(d, db, &obj); + } +} + const char *apk_script_types[] = { [APK_SCRIPT_PRE_INSTALL] = "pre-install", [APK_SCRIPT_POST_INSTALL] = "post-install", @@ -474,6 +496,7 @@ struct read_info_ctx { struct apk_database *db; struct apk_package *pkg; struct apk_extract_ctx ectx; + int v3ok; }; int apk_pkg_add_info(struct apk_database *db, struct apk_package *pkg, @@ -549,6 +572,47 @@ int apk_pkg_add_info(struct apk_database *db, struct apk_package *pkg, return 0; } +static char *commit_id(apk_blob_t b) +{ + char buf[80]; + apk_blob_t to = APK_BLOB_BUF(buf); + + apk_blob_push_hexdump(&to, b); + to = apk_blob_pushed(APK_BLOB_BUF(buf), to); + if (APK_BLOB_IS_NULL(to)) return NULL; + return apk_blob_cstr(to); +} + +void apk_pkg_from_adb(struct apk_database *db, struct apk_package *pkg, struct adb_obj *pkgo) +{ + struct adb_obj pkginfo, obj; + apk_blob_t uid; + + adb_ro_obj(pkgo, ADBI_PKG_PKGINFO, &pkginfo); + + 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)); + + 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) { static struct { @@ -601,13 +665,27 @@ static int apk_pkg_v2meta(struct apk_extract_ctx *ectx, struct apk_istream *is) return 0; } +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); + + if (!ri->v3ok) return -APKE_FORMAT_NOT_SUPPORTED; + + apk_pkg_from_adb(ri->db, ri->pkg, pkg); + return -ECANCELED; +} + static const struct apk_extract_ops extract_pkgmeta_ops = { .v2meta = apk_pkg_v2meta, + .v3meta = apk_pkg_v3meta, }; -int apk_pkg_read(struct apk_database *db, const char *file, struct apk_package **pkg) +int apk_pkg_read(struct apk_database *db, const char *file, struct apk_package **pkg, int v3ok) { - struct read_info_ctx ctx; + struct read_info_ctx ctx = { + .db = db, + .v3ok = v3ok, + }; struct apk_file_info fi; int r; @@ -615,8 +693,6 @@ int apk_pkg_read(struct apk_database *db, const char *file, struct apk_package * if (r != 0) return r; - memset(&ctx, 0, sizeof(ctx)); - ctx.db = db; ctx.pkg = apk_pkg_new(); r = -ENOMEM; if (ctx.pkg == NULL) @@ -628,8 +704,10 @@ int apk_pkg_read(struct apk_database *db, const char *file, struct apk_package * r = apk_extract(&ctx.ectx, apk_istream_from_file(AT_FDCWD, file)); if (r < 0) goto err; - if (ctx.pkg->name == NULL || ctx.pkg->uninstallable) { - r = -ENOTSUP; + if (ctx.pkg->csum.type == APK_CHECKSUM_NONE || + ctx.pkg->name == NULL || + ctx.pkg->uninstallable) { + r = -APKE_FORMAT_NOT_SUPPORTED; goto err; } ctx.pkg->filename = strdup(file);