summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYousong Zhou2019-06-12 04:19:02 +0000
committerYousong Zhou2019-06-14 01:08:23 +0000
commit21b7bd73ae88ba2ce9a5bfeedf67bc204d10fd08 (patch)
treeff4f1d8a5b4a9c3e710d3c6d3b4e8e1a27ce8329
parentd4ba162bb3f931bd5a019154270a548cf1f0853b (diff)
downloadopkg-lede-21b7bd73ae88ba2ce9a5bfeedf67bc204d10fd08.tar.gz
alternatives: special-case busybox as alternatives provider
Almost all busybox applets are alternatives to some other existing "full" utilities. To lift the maintenance burden of enumerating CONFIG symbols, symlink path of each applet, we special case busybox here as a known alternatives provider. All file pathes provided by busybox will serve as fallback alternatives with -inf priority. Packages intending to switch to using alternatives mechanism will also not need to depend on the same kind of change be applied on busybox in base system v3 <- v2 continue to next when fetching provider pkg failed v2 <- v1 Move busybox-specific part into data section Signed-off-by: Yousong Zhou <zhouyousong@yunionyun.com> Acked-by: Jo-Philipp Wich <jo@mein.io>
-rw-r--r--libopkg/pkg_alternatives.c49
1 files changed, 46 insertions, 3 deletions
diff --git a/libopkg/pkg_alternatives.c b/libopkg/pkg_alternatives.c
index 50e9d12..5891616 100644
--- a/libopkg/pkg_alternatives.c
+++ b/libopkg/pkg_alternatives.c
@@ -27,6 +27,42 @@
#include "pkg_alternatives.h"
#include "sprintf_alloc.h"
+struct alternative_provider {
+ char *name;
+ char *altpath;
+};
+
+static const struct alternative_provider const providers[] = {
+ {
+ .name = "busybox",
+ .altpath = "/bin/busybox",
+ },
+};
+
+static const char *pkg_alternatives_check_providers(const char *path)
+{
+ pkg_t *pkg;
+ str_list_t *files;
+ str_list_elt_t *iter;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(providers); i++) {
+ pkg = pkg_hash_fetch_installed_by_name(providers[i].name);
+ if (!pkg) {
+ continue;
+ }
+ files = pkg_get_installed_files(pkg);
+ for (iter = str_list_first(files); iter; iter = str_list_next(files, iter)) {
+ if (!strcmp(path, (char *)(iter->data))) {
+ pkg_free_installed_files(pkg);
+ return providers[i].altpath;
+ }
+ }
+ pkg_free_installed_files(pkg);
+ }
+ return NULL;
+}
+
static int pkg_alternatives_update_path(pkg_t *pkg, const pkg_vec_t *installed, const char *path)
{
struct pkg_alternatives *pkg_alts;
@@ -35,6 +71,7 @@ static int pkg_alternatives_update_path(pkg_t *pkg, const pkg_vec_t *installed,
int i, j;
int r;
char *path_in_dest;
+ const char *target_path = NULL;
for (i = 0; i < installed->len; i++) {
pkg_t *pkg = installed->pkgs[i];
@@ -60,6 +97,12 @@ static int pkg_alternatives_update_path(pkg_t *pkg, const pkg_vec_t *installed,
return -1;
if (the_alt) {
+ target_path = the_alt->altpath;
+ } else {
+ target_path = pkg_alternatives_check_providers(path);
+ }
+
+ if (target_path) {
struct stat sb;
r = lstat(path_in_dest, &sb);
@@ -72,7 +115,7 @@ static int pkg_alternatives_update_path(pkg_t *pkg, const pkg_vec_t *installed,
goto out;
}
realpath = xreadlink(path_in_dest);
- if (realpath && strcmp(realpath, the_alt->altpath))
+ if (realpath && strcmp(realpath, target_path))
unlink(path_in_dest);
free(realpath);
} else if (errno != ENOENT) {
@@ -87,7 +130,7 @@ static int pkg_alternatives_update_path(pkg_t *pkg, const pkg_vec_t *installed,
if (r) {
goto out;
}
- r = symlink(the_alt->altpath, path_in_dest);
+ r = symlink(target_path, path_in_dest);
if (r && errno == EEXIST) {
/*
* the strcmp & unlink check above will make sure that if EEXIST
@@ -96,7 +139,7 @@ static int pkg_alternatives_update_path(pkg_t *pkg, const pkg_vec_t *installed,
r = 0;
}
if (r) {
- opkg_perror(ERROR, "failed symlinking %s -> %s", path_in_dest, the_alt->altpath);
+ opkg_perror(ERROR, "failed symlinking %s -> %s", path_in_dest, target_path);
}
}
} else {