summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/add.c5
-rw-r--r--src/apk_package.h14
-rw-r--r--src/database.c43
-rw-r--r--src/info.c37
-rw-r--r--src/package.c75
-rw-r--r--src/test.c4
6 files changed, 119 insertions, 59 deletions
diff --git a/src/add.c b/src/add.c
index 5e1b2bb..a31c9e2 100644
--- a/src/add.c
+++ b/src/add.c
@@ -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) {
diff --git a/src/info.c b/src/info.c
index 2cbadf0..b45eba5 100644
--- a/src/info.c
+++ b/src/info.c
@@ -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:
diff --git a/src/test.c b/src/test.c
index dec5bb0..9fc3e1f 100644
--- a/src/test.c
+++ b/src/test.c
@@ -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);