[OpenWrt-Devel,v2,opkg] alternatives: special-case busybox as alternatives provider
diff mbox series

Message ID 20190613163133.40306-1-zhouyousong@yunionyun.com
State Accepted, archived
Delegated to: Yousong Zhou
Headers show
Series
  • [OpenWrt-Devel,v2,opkg] alternatives: special-case busybox as alternatives provider
Related show

Commit Message

Yousong Zhou June 13, 2019, 4:31 p.m. UTC
From: Yousong Zhou <yszhou4tech@gmail.com>

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

Signed-off-by: Yousong Zhou <zhouyousong@yunionyun.com>
---
v2 <- v1 Make the code less busybox-specific by moving busybox into data section

 libopkg/pkg_alternatives.c | 49 +++++++++++++++++++++++++++++++++++---
 1 file changed, 46 insertions(+), 3 deletions(-)

Comments

Jo-Philipp Wich June 13, 2019, 4:50 p.m. UTC | #1
Hi Yousong,

> From: Yousong Zhou <yszhou4tech@gmail.com>
> 
> 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
> 
> Signed-off-by: Yousong Zhou <zhouyousong@yunionyun.com>

Acked-by: Jo-Philipp Wich <jo@mein.io>

Patch
diff mbox series

diff --git a/libopkg/pkg_alternatives.c b/libopkg/pkg_alternatives.c
index 50e9d12..7ea6b5b 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) {
+			return NULL;
+		}
+		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 {