[OpenWrt-Devel,procd,V2] system: support passing "options" to the "sysupgrade" ubus method
diff mbox series

Message ID 20190816154455.1152-1-zajec5@gmail.com
State Accepted
Delegated to: Rafał Miłecki
Headers show
Series
  • [OpenWrt-Devel,procd,V2] system: support passing "options" to the "sysupgrade" ubus method
Related show

Commit Message

Rafał Miłecki Aug. 16, 2019, 3:44 p.m. UTC
From: Rafał Miłecki <rafal@milecki.pl>

Object passed as "options" gets translated into environment variables
UPGRADE_OPT_*. E.g.
"options": { "foo": 5 }
will result in setting UPGRADE_OPT_FOO=5.

This allows stage2 sysupgrade to get options explicitly. So far it was
guessing what to do by checking for existence of some files (e.g.
sysupgrade.tgz).

Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
---
V2: Use asprintf() & drop some braces
---
 initd/preinit.c |  2 +-
 system.c        |  5 ++++-
 sysupgrade.c    | 43 ++++++++++++++++++++++++++++++++++++++++++-
 sysupgrade.h    |  4 +++-
 4 files changed, 50 insertions(+), 4 deletions(-)

Patch
diff mbox series

diff --git a/initd/preinit.c b/initd/preinit.c
index fbb36df..2b4df4b 100644
--- a/initd/preinit.c
+++ b/initd/preinit.c
@@ -75,7 +75,7 @@  check_sysupgrade(void)
 
 	fclose(sysupgrade);
 
-	sysupgrade_exec_upgraded(prefix, path, command);
+	sysupgrade_exec_upgraded(prefix, path, command, NULL);
 
 	while (true)
 		sleep(1);
diff --git a/system.c b/system.c
index 8ed3f93..738f327 100644
--- a/system.c
+++ b/system.c
@@ -380,6 +380,7 @@  enum {
 	SYSUPGRADE_PATH,
 	SYSUPGRADE_PREFIX,
 	SYSUPGRADE_COMMAND,
+	SYSUPGRADE_OPTIONS,
 	__SYSUPGRADE_MAX
 };
 
@@ -387,6 +388,7 @@  static const struct blobmsg_policy sysupgrade_policy[__SYSUPGRADE_MAX] = {
 	[SYSUPGRADE_PATH] = { .name = "path", .type = BLOBMSG_TYPE_STRING },
 	[SYSUPGRADE_PREFIX] = { .name = "prefix", .type = BLOBMSG_TYPE_STRING },
 	[SYSUPGRADE_COMMAND] = { .name = "command", .type = BLOBMSG_TYPE_STRING },
+	[SYSUPGRADE_OPTIONS] = { .name = "options", .type = BLOBMSG_TYPE_TABLE },
 };
 
 static int sysupgrade(struct ubus_context *ctx, struct ubus_object *obj,
@@ -404,7 +406,8 @@  static int sysupgrade(struct ubus_context *ctx, struct ubus_object *obj,
 
 	sysupgrade_exec_upgraded(blobmsg_get_string(tb[SYSUPGRADE_PREFIX]),
 				 blobmsg_get_string(tb[SYSUPGRADE_PATH]),
-				 tb[SYSUPGRADE_COMMAND] ? blobmsg_get_string(tb[SYSUPGRADE_COMMAND]) : NULL);
+				 tb[SYSUPGRADE_COMMAND] ? blobmsg_get_string(tb[SYSUPGRADE_COMMAND]) : NULL,
+				 tb[SYSUPGRADE_OPTIONS]);
 
 	/* sysupgrade_exec_upgraded() will never return unless something has gone wrong */
 	return UBUS_STATUS_UNKNOWN_ERROR;
diff --git a/sysupgrade.c b/sysupgrade.c
index 07e33f7..29c4c9b 100644
--- a/sysupgrade.c
+++ b/sysupgrade.c
@@ -17,15 +17,20 @@ 
 #include "watchdog.h"
 #include "sysupgrade.h"
 
+#include <ctype.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 
+#include <libubox/blobmsg.h>
 
-void sysupgrade_exec_upgraded(const char *prefix, char *path, char *command)
+void sysupgrade_exec_upgraded(const char *prefix, char *path, char *command,
+			      struct blob_attr *options)
 {
 	char *wdt_fd = watchdog_fd();
 	char *argv[] = { "/sbin/upgraded", NULL, NULL, NULL};
+	struct blob_attr *option;
+	int rem;
 	int ret;
 
 	ret = chroot(prefix);
@@ -41,6 +46,42 @@  void sysupgrade_exec_upgraded(const char *prefix, char *path, char *command)
 		watchdog_set_cloexec(false);
 		setenv("WDTFD", wdt_fd, 1);
 	}
+
+	blobmsg_for_each_attr(option, options, rem) {
+		const char *prefix = "UPGRADE_OPT_";
+		char value[11];
+		char *name;
+		char *c;
+		int tmp;
+
+		if (asprintf(&name, "%s%s", prefix, blobmsg_name(option)) < 0)
+			continue;
+		for (c = name + strlen(prefix); *c; c++)
+			*c = toupper(*c);
+
+		switch (blobmsg_type(option)) {
+		case BLOBMSG_TYPE_INT32:
+			tmp = blobmsg_get_u32(option);
+			break;
+		case BLOBMSG_TYPE_INT16:
+			tmp = blobmsg_get_u16(option);
+			break;
+		case BLOBMSG_TYPE_INT8:
+			tmp = blobmsg_get_u8(option);
+			break;
+		default:
+			fprintf(stderr, "Option \"%s\" has unsupported type: %d\n",
+				blobmsg_name(option), blobmsg_type(option));
+			free(name);
+			continue;
+		}
+		snprintf(value, sizeof(value), "%u", tmp);
+
+		setenv(name, value, 1);
+
+		free(name);
+	}
+
 	execvp(argv[0], argv);
 
 	/* Cleanup on failure */
diff --git a/sysupgrade.h b/sysupgrade.h
index 8c09fc9..c84e494 100644
--- a/sysupgrade.h
+++ b/sysupgrade.h
@@ -14,8 +14,10 @@ 
 #ifndef __PROCD_SYSUPGRADE_H
 #define __PROCD_SYSUPGRADE_H
 
+struct blob_attr;
 
-void sysupgrade_exec_upgraded(const char *prefix, char *path, char *command);
+void sysupgrade_exec_upgraded(const char *prefix, char *path, char *command,
+			      struct blob_attr *options);
 
 
 #endif