Browse Source

system: support passing "options" to the "sysupgrade" ubus method

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>
Rafał Miłecki 4 years ago
parent
commit
95580316bc
4 changed files with 63 additions and 4 deletions
  1. 1 1
      initd/preinit.c
  2. 4 1
      system.c
  3. 55 1
      sysupgrade.c
  4. 3 1
      sysupgrade.h

+ 1 - 1
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);

+ 4 - 1
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;

+ 55 - 1
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,55 @@ 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++) {
+			if (isalnum(*c) || *c == '_') {
+				*c = toupper(*c);
+			} else {
+				c = NULL;
+				break;
+			}
+		}
+
+		if (!c) {
+			fprintf(stderr, "Option \"%s\" contains invalid characters\n",
+				blobmsg_name(option));
+			free(name);
+			continue;
+		}
+
+		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 */

+ 3 - 1
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