diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/add.c | 5 | ||||
-rw-r--r-- | src/apk_package.h | 14 | ||||
-rw-r--r-- | src/database.c | 43 | ||||
-rw-r--r-- | src/info.c | 37 | ||||
-rw-r--r-- | src/package.c | 75 | ||||
-rw-r--r-- | src/test.c | 4 |
6 files changed, 119 insertions, 59 deletions
@@ -107,8 +107,9 @@ static int add_main(void *ctx, struct apk_database *db, int argc, char **argv) } apk_dep_from_pkg(&dep, db, pkg); } else { - r = apk_dep_from_blob(&dep, db, APK_BLOB_STR(argv[i])); - if (r != 0) + apk_blob_t b = APK_BLOB_STR(argv[i]); + apk_blob_pull_dep(&b, db, &dep); + if (APK_BLOB_IS_NULL(b)) return -1; } diff --git a/src/apk_package.h b/src/apk_package.h index b6bcffd..f58954f 100644 --- a/src/apk_package.h +++ b/src/apk_package.h @@ -74,6 +74,7 @@ struct apk_installed_package { apk_blob_t script[APK_SCRIPT_MAX]; struct apk_string_array *triggers; struct apk_string_array *pending_triggers; + struct apk_dependency_array *replaces; }; #define APK_PKG_UNINSTALLABLE ((char*) -1) @@ -115,22 +116,21 @@ int apk_sign_ctx_verify_tar(void *ctx, const struct apk_file_info *fi, struct apk_istream *is); int apk_sign_ctx_mpart_cb(void *ctx, int part, apk_blob_t blob); -int apk_dep_from_blob(struct apk_dependency *dep, struct apk_database *db, - apk_blob_t blob); void apk_dep_from_pkg(struct apk_dependency *dep, struct apk_database *db, struct apk_package *pkg); int apk_dep_is_satisfied(struct apk_dependency *dep, struct apk_package *pkg); + void apk_blob_push_dep(apk_blob_t *to, struct apk_dependency *dep); +void apk_blob_push_deps(apk_blob_t *to, struct apk_dependency_array *deps); +void apk_blob_pull_dep(apk_blob_t *from, struct apk_database *, struct apk_dependency *); +void apk_blob_pull_deps(apk_blob_t *from, struct apk_database *, struct apk_dependency_array **); + +int apk_deps_write(struct apk_dependency_array *deps, struct apk_ostream *os); int 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); -void apk_deps_parse(struct apk_database *db, - struct apk_dependency_array **depends, - apk_blob_t blob); - -int apk_deps_write(struct apk_dependency_array *deps, struct apk_ostream *os); int apk_script_type(const char *name); void apk_pkg_format_plain(struct apk_package *pkg, apk_blob_t to); diff --git a/src/database.c b/src/database.c index 135f6b4..5662f7a 100644 --- a/src/database.c +++ b/src/database.c @@ -75,7 +75,6 @@ struct install_ctx { struct apk_db_dir_instance *diri; struct apk_checksum data_csum; struct apk_sign_ctx sctx; - struct apk_name_array *replaces; apk_progress_cb cb; void *cb_ctx; @@ -668,6 +667,10 @@ int apk_db_index_read(struct apk_database *db, struct apk_bstream *bs, int repo) } apk_blob_pull_csum(&l, &file->csum); break; + case 'r': + if (ipkg != NULL) + apk_blob_pull_deps(&l, db, &ipkg->replaces); + break; default: if (r != 0 && !(apk_flags & APK_FORCE)) { /* Installed db should not have unsupported fields */ @@ -704,6 +707,12 @@ static int apk_db_write_fdb(struct apk_database *db, struct apk_ostream *os) if (r < 0) return r; + if (ipkg->replaces->num) { + apk_blob_push_blob(&bbuf, APK_BLOB_STR("r:")); + apk_blob_push_deps(&bbuf, ipkg->replaces); + apk_blob_push_blob(&bbuf, APK_BLOB_STR("\n")); + } + hlist_for_each_entry(diri, c1, &ipkg->owned_dirs, pkg_dirs_list) { apk_blob_push_blob(&bbuf, APK_BLOB_STR("F:")); apk_blob_push_blob(&bbuf, APK_BLOB_PTR_LEN(diri->dir->name, diri->dir->namelen)); @@ -897,7 +906,7 @@ static int apk_db_read_state(struct apk_database *db, int flags) blob = apk_blob_from_file(db->root_fd, apk_world_file); if (APK_BLOB_IS_NULL(blob)) return -ENOENT; - apk_deps_parse(db, &db->world, blob); + apk_blob_pull_deps(&blob, db, &db->world); free(blob.ptr); } @@ -1757,17 +1766,6 @@ static int apk_db_run_pending_script(struct install_ctx *ctx) return r; } -static int parse_replaces(void *_ctx, apk_blob_t blob) -{ - struct install_ctx *ctx = (struct install_ctx *) _ctx; - - if (blob.len == 0) - return 0; - - *apk_name_array_add(&ctx->replaces) = apk_db_get_name(ctx->db, blob); - return 0; -} - static int read_info_line(void *_ctx, apk_blob_t line) { struct install_ctx *ctx = (struct install_ctx *) _ctx; @@ -1782,7 +1780,7 @@ static int read_info_line(void *_ctx, apk_blob_t line) return 0; if (apk_blob_compare(APK_BLOB_STR("replaces"), l) == 0) { - apk_blob_for_each_segment(r, " ", parse_replaces, ctx); + apk_blob_pull_deps(&r, db, &ctx->ipkg->replaces); } else if (apk_blob_compare(APK_BLOB_STR("triggers"), l) == 0) { apk_string_array_resize(&ipkg->triggers, 0); apk_blob_for_each_segment(r, " ", parse_triggers, ctx->ipkg); @@ -1878,11 +1876,20 @@ static int apk_db_install_archive_entry(void *_ctx, /* Upgrading package? */ if (opkg->name == pkg->name) break; + /* If we have been replaced, skip file silently. */ + for (i = 0; i < opkg->ipkg->replaces->num; i++) { + if (apk_dep_is_satisfied(&opkg->ipkg->replaces->item[i], pkg)) { + apk_warning("%s: Dropping silently %s owned by %s.", + pkg->name->name, ae->name, + opkg->name->name); + return 0; + } + } /* Overwriting with permission? */ - for (i = 0; i < ctx->replaces->num; i++) - if (opkg->name == ctx->replaces->item[i]) + for (i = 0; i < ctx->ipkg->replaces->num; i++) + if (apk_dep_is_satisfied(&ctx->ipkg->replaces->item[i], opkg)) break; - if (i < ctx->replaces->num) + if (i < ctx->ipkg->replaces->num) break; if (!(apk_flags & APK_FORCE)) { @@ -2159,12 +2166,10 @@ static int apk_db_unpack_pkg(struct apk_database *db, .cb = cb, .cb_ctx = cb_ctx, }; - apk_name_array_init(&ctx.replaces); apk_sign_ctx_init(&ctx.sctx, APK_SIGN_VERIFY_IDENTITY, &pkg->csum, db->keys_fd); tar = apk_bstream_gunzip_mpart(bs, apk_sign_ctx_mpart_cb, &ctx.sctx); r = apk_tar_parse(tar, apk_db_install_archive_entry, &ctx, TRUE, &db->id_cache); apk_sign_ctx_free(&ctx.sctx); - apk_name_array_free(&ctx.replaces); tar->close(tar); if (need_copy) { @@ -34,6 +34,7 @@ struct info_ctx { #define APK_INFO_TRIGGERS 0x40 #define APK_INFO_INSTALL_IF 0x80 #define APK_INFO_RINSTALL_IF 0x100 +#define APK_INFO_REPLACES 0x200 static void verbose_print_pkg(struct apk_package *pkg, int minimal_verbosity) { @@ -69,14 +70,15 @@ static int info_exists(struct info_ctx *ctx, struct apk_database *db, struct apk_name *name; struct apk_package *pkg = NULL; struct apk_dependency dep; - int r, i, j, ok = 0; + int i, j, ok = 0; for (i = 0; i < argc; i++) { - r = apk_dep_from_blob(&dep, db, APK_BLOB_STR(argv[i])); - if (r != 0) + apk_blob_t b = APK_BLOB_STR(argv[i]); + apk_blob_pull_dep(&b, db, &dep); + name = dep.name; + if (name == NULL) continue; - name = dep.name; for (j = 0; j < name->pkgs->num; j++) { pkg = name->pkgs->item[j]; if (pkg->ipkg != NULL) @@ -309,6 +311,26 @@ static void info_print_triggers(struct apk_package *pkg) } } +static void info_print_replaces(struct apk_package *pkg) +{ + apk_blob_t separator = APK_BLOB_STR(apk_verbosity > 1 ? " " : "\n"); + char dep[256]; + int i; + + if (apk_verbosity == 1) + printf(PKG_VER_FMT " replaces:\n", + PKG_VER_PRINTF(pkg)); + if (apk_verbosity > 1) + printf("%s: ", pkg->name->name); + for (i = 0; i < pkg->ipkg->replaces->num; i++) { + apk_blob_t b = APK_BLOB_BUF(dep); + apk_blob_push_dep(&b, &pkg->ipkg->replaces->item[i]); + apk_blob_push_blob(&b, separator); + b = apk_blob_pushed(APK_BLOB_BUF(dep), b); + fwrite(b.ptr, b.len, 1, stdout); + } +} + static void info_subaction(struct info_ctx *ctx, struct apk_package *pkg) { typedef void (*subaction_t)(struct apk_package *); @@ -322,10 +344,11 @@ static void info_subaction(struct info_ctx *ctx, struct apk_package *pkg) info_print_triggers, info_print_install_if, info_print_rinstall_if, + info_print_replaces, }; const int requireipkg = APK_INFO_CONTENTS | APK_INFO_TRIGGERS | APK_INFO_RDEPENDS | - APK_INFO_RINSTALL_IF; + APK_INFO_RINSTALL_IF | APK_INFO_REPLACES; int i; for (i = 0; i < ARRAY_SIZE(subactions); i++) { @@ -398,6 +421,9 @@ static int info_parse(void *ctx, struct apk_db_options *dbopts, case 't': ictx->subaction_mask |= APK_INFO_TRIGGERS; break; + case 0x10000: + ictx->subaction_mask |= APK_INFO_REPLACES; + break; case 'a': ictx->subaction_mask = 0xffffffff; break; @@ -423,6 +449,7 @@ static struct apk_option info_options[] = { { 'W', "who-owns", "Print the package owning the specified file" }, { 'R', "depends", "List packages that the PACKAGE depends on" }, { 'r', "rdepends", "List all packages depending on PACKAGE" }, + { 0x10000, "replaces", "List packages whom files PACKAGE might replace" }, { 'i', "install-if", "List the PACKAGE's install-if rule" }, { 'I', "rinstall-if", "List all packages having install-if referencing PACKAGE" }, { 'w', "webpage", "Show URL for more information about PACKAGE" }, diff --git a/src/package.c b/src/package.c index 0f882e2..76b6550 100644 --- a/src/package.c +++ b/src/package.c @@ -77,6 +77,7 @@ struct apk_installed_package *apk_pkg_install(struct apk_database *db, ipkg->pkg = pkg; apk_string_array_init(&ipkg->triggers); apk_string_array_init(&ipkg->pending_triggers); + apk_dependency_array_init(&ipkg->replaces); /* Overlay override information resides in a nameless package */ if (pkg->name != NULL) { @@ -109,6 +110,7 @@ void apk_pkg_uninstall(struct apk_database *db, struct apk_package *pkg) } apk_string_array_free(&ipkg->triggers); apk_string_array_free(&ipkg->pending_triggers); + apk_dependency_array_free(&ipkg->replaces); for (i = 0; i < APK_SCRIPT_MAX; i++) if (ipkg->script[i].ptr != NULL) @@ -189,26 +191,28 @@ struct parse_depend_ctx { struct apk_dependency_array **depends; }; -int apk_dep_from_blob(struct apk_dependency *dep, struct apk_database *db, - apk_blob_t blob) +void apk_blob_pull_dep(apk_blob_t *b, struct apk_database *db, struct apk_dependency *dep) { struct apk_name *name; apk_blob_t bname, bop, bver = APK_BLOB_NULL; int mask = APK_DEPMASK_REQUIRE; + size_t len; /* [!]name[<,<=,=,>=,>]ver */ - if (blob.ptr[0] == '!') { + if (APK_BLOB_IS_NULL(*b)) + goto fail; + if (b->ptr[0] == '!') { mask = 0; - blob.ptr++; - blob.len--; + b->ptr++; + b->len--; } - if (apk_blob_cspn(blob, "<>=", &bname, &bop)) { + if (apk_blob_cspn(*b, "<>= ", &bname, &bop)) { int i; if (mask == 0) - return -EINVAL; + goto fail; if (!apk_blob_spn(bop, "<>=", &bop, &bver)) - return -EINVAL; + goto fail; mask = 0; for (i = 0; i < bop.len; i++) { switch (bop.ptr[i]) { @@ -225,21 +229,29 @@ int apk_dep_from_blob(struct apk_dependency *dep, struct apk_database *db, } if ((mask & APK_DEPMASK_CHECKSUM) != APK_DEPMASK_CHECKSUM && !apk_version_validate(bver)) - return -EINVAL; - - blob = bname; + goto fail; + } else { + bname = *b; + bop = APK_BLOB_NULL; + bver = APK_BLOB_NULL; } + len = bname.len + bop.len + bver.len; + b->ptr += len; + b->len -= len; - name = apk_db_get_name(db, blob); + name = apk_db_get_name(db, bname); if (name == NULL) - return -ENOENT; + goto fail; *dep = (struct apk_dependency){ .name = name, .version = apk_blob_atomize_dup(bver), .result_mask = mask, }; - return 0; + return; +fail: + *dep = (struct apk_dependency){ .name = NULL }; + *b = APK_BLOB_NULL; } void apk_dep_from_pkg(struct apk_dependency *dep, struct apk_database *db, @@ -266,7 +278,8 @@ static int parse_depend(void *ctx, apk_blob_t blob) if (blob.len == 0) return 0; - if (apk_dep_from_blob(&p, pctx->db, blob) < 0) + apk_blob_pull_dep(&blob, pctx->db, &p); + if (p.name == NULL || blob.len != 0) return -1; dep = apk_dependency_array_add(pctx->depends); @@ -301,16 +314,14 @@ int apk_dep_is_satisfied(struct apk_dependency *dep, struct apk_package *pkg) return 0; } -void apk_deps_parse(struct apk_database *db, - struct apk_dependency_array **depends, - apk_blob_t blob) +void apk_blob_pull_deps(apk_blob_t *b, struct apk_database *db, struct apk_dependency_array **deps) { - struct parse_depend_ctx ctx = { db, depends }; + struct parse_depend_ctx ctx = { db, deps }; - if (blob.len > 0 && blob.ptr[blob.len-1] == '\n') - blob.len--; + if (b->len > 0 && b->ptr[b->len-1] == '\n') + b->len--; - apk_blob_for_each_segment(blob, " ", parse_depend, &ctx); + apk_blob_for_each_segment(*b, " ", parse_depend, &ctx); } void apk_blob_push_dep(apk_blob_t *to, struct apk_dependency *dep) @@ -327,6 +338,20 @@ void apk_blob_push_dep(apk_blob_t *to, struct apk_dependency *dep) } } +void apk_blob_push_deps(apk_blob_t *to, struct apk_dependency_array *deps) +{ + int i; + + if (deps == NULL) + return; + + for (i = 0; i < deps->num; i++) { + if (i) + apk_blob_push_blob(to, APK_BLOB_PTR_LEN(" ", 1)); + apk_blob_push_dep(to, &deps->item[i]); + } +} + int apk_deps_write(struct apk_dependency_array *deps, struct apk_ostream *os) { apk_blob_t blob; @@ -657,7 +682,7 @@ int apk_pkg_add_info(struct apk_database *db, struct apk_package *pkg, pkg->arch = apk_blob_atomize_dup(value); break; case 'D': - apk_deps_parse(db, &pkg->depends, value); + apk_blob_pull_deps(&value, db, &pkg->depends); break; case 'C': apk_blob_pull_csum(&value, &pkg->csum); @@ -669,7 +694,7 @@ int apk_pkg_add_info(struct apk_database *db, struct apk_package *pkg, pkg->installed_size = apk_blob_pull_uint(&value, 10); break; case 'i': - apk_deps_parse(db, &pkg->install_if, value); + apk_blob_pull_deps(&value, db, &pkg->install_if); break; case 'o': pkg->origin = apk_blob_atomize_dup(value); @@ -683,7 +708,7 @@ int apk_pkg_add_info(struct apk_database *db, struct apk_package *pkg, case 'c': pkg->commit = apk_blob_cstr(value); break; - case 'F': case 'M': case 'R': case 'Z': + case 'F': case 'M': case 'R': case 'Z': case 'r': /* installed db entries which are handled in database.c */ return 1; default: @@ -147,6 +147,7 @@ static int test_main(void *pctx, struct apk_database *db, int argc, char **argv) struct apk_bstream *bs; struct apk_package_array *solution = NULL; struct apk_changeset changeset = {}; + apk_blob_t b; int i, r; if (argc != 1) @@ -173,7 +174,8 @@ static int test_main(void *pctx, struct apk_database *db, int argc, char **argv) } /* construct new world */ - apk_deps_parse(db, &db->world, APK_BLOB_STR(argv[0])); + b = APK_BLOB_STR(argv[0]); + apk_blob_pull_deps(&b, db, &db->world); /* run solver */ r = apk_solver_solve(db, ctx->solver_flags, db->world, &solution, &changeset); |