summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafał Miłecki2019-08-16 14:14:27 +0000
committerRafał Miłecki2019-08-22 11:37:47 +0000
commit95580316bc2d37d9261691ea99dae518bde46836 (patch)
tree45ad898ff3f1b2c17295ab3463dfa51c76b953b0
parent832369078d818d19ab64051fdc8da9e06c90ad88 (diff)
downloadprocd-95580316bc2d37d9261691ea99dae518bde46836.tar.gz
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>
-rw-r--r--initd/preinit.c2
-rw-r--r--system.c5
-rw-r--r--sysupgrade.c56
-rw-r--r--sysupgrade.h4
4 files changed, 63 insertions, 4 deletions
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..a5bad9a 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,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 */
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