system: support passing "options" to the "sysupgrade" ubus method
authorRafał Miłecki <rafal@milecki.pl>
Fri, 16 Aug 2019 14:14:27 +0000 (16:14 +0200)
committerRafał Miłecki <rafal@milecki.pl>
Thu, 22 Aug 2019 11:37:47 +0000 (13:37 +0200)
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>
initd/preinit.c
system.c
sysupgrade.c
sysupgrade.h

index fbb36df9e5adb2e668f0b033bbc2fda0f1e20ee0..2b4df4ba218a359c8c3275ddcdbcde0bad71d47c 100644 (file)
@@ -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);
index 8ed3f93af481a544b48e5173158f446360499ab6..738f32744f5b1e64ba168179bdc374d9cab9db5d 100644 (file)
--- 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;
index 07e33f752d0c3be57962771cdf42f02576d42e7f..a5bad9a8e4264e3cfc1caf4f0a2a4edec70043bb 100644 (file)
 #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 */
index 8c09fc99d191182a4f26333569a8adad2728070a..c84e4945c226678b46d3547c17800fe49d8272f0 100644 (file)
 #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