Extend the mountd with the ability to apply sysupgrades from mounted devices.
Upgrade files are identified by filename and executed through the
commandline sysupgrade utility of LEDE.

Option List:

config mountd 'sysupgrade'
        option  check_filename  firmware.bin (required)
        option  save_config     1       (optional, default disabled)
        option  delay           10      (optional, default disabled)
        option  preserve_part   1       (optional, default disabled)
        option  enabled         1

The so called "filesearch" is done only in the root of a mounted
devices.

Signed-off-by: Philipp Deppenwiese <zao...@das-labor.org>
---
 CMakeLists.txt    |   2 +-
 autofs.c          |  19 ++++++-
 include/upgrade.h |   6 ++
 mount.c           |   2 +
 upgrade.c         | 162 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 189 insertions(+), 2 deletions(-)
 create mode 100644 include/upgrade.h
 create mode 100644 upgrade.c

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2e712cd..ed3602e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -5,7 +5,7 @@ ADD_DEFINITIONS(-Os -ggdb -Wall -Werror --std=gnu99 
-Wmissing-declarations)
 
 SET(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
 
-ADD_EXECUTABLE(mountd main.c log.c sys.c autofs.c mount.c timer.c signal.c 
ucix.c led.c fs.c ucix.c)
+ADD_EXECUTABLE(mountd main.c log.c sys.c autofs.c mount.c timer.c signal.c 
ucix.c led.c fs.c ucix.c upgrade.c)
 TARGET_LINK_LIBRARIES(mountd uci ubox)
 
 INSTALL(TARGETS mountd
diff --git a/autofs.c b/autofs.c
index 4ad782d..79a3e97 100644
--- a/autofs.c
+++ b/autofs.c
@@ -37,6 +37,13 @@ dev_t dev;
 time_t uci_timeout;
 char uci_path[32];
 
+// Sysupgrade uci options
+char uci_upgrade_filename[255];
+int uci_upgrade_backup;
+int uci_upgrade_delay;
+int uci_upgrade_enabled;
+int uci_upgrade_preserve_partition;
+
 static void umount_autofs(void)
 {
        system_printf("umount %s 2> /dev/null", "/tmp/run/mountd/");
@@ -186,18 +193,28 @@ static void autofs_cleanup_handler(void)
 static void autofs_init(void)
 {
        int kproto_version;
-       char *p;
+       char *p, *filename = NULL;
        struct uci_context *ctx;
        signal_init(autofs_cleanup_handler);
        ctx = ucix_init("mountd");
        uci_timeout = ucix_get_option_int(ctx, "mountd", "mountd", "timeout", 
60);
        p = ucix_get_option(ctx, "mountd", "mountd", "path");
+       filename = ucix_get_option(ctx, "mountd", "sysupgrade", 
"check_filename");
+       uci_upgrade_backup = ucix_get_option_int(ctx, "mountd", "sysupgrade", 
"save_config", 0);
+       uci_upgrade_delay = ucix_get_option_int(ctx, "mountd", "sysupgrade", 
"delay", 0);
+       uci_upgrade_enabled = ucix_get_option_int(ctx, "mountd", "sysupgrade", 
"enabled", 0);
+       uci_upgrade_preserve_partition = ucix_get_option_int(ctx, "mountd", 
"sysupgrade", "preserve_part", 0);
        ucix_cleanup(ctx);
        if(p)
                snprintf(uci_path, 31, "%s", p);
        else
                snprintf(uci_path, 31, "/tmp/mounts/");
        uci_path[31] = '\0';
+
+       if(filename) {
+               snprintf(uci_upgrade_filename, 255, "%s", filename);
+       }
+
        mkdir("/tmp/run/", 0555);
        mkdir("/tmp/mounts", 0555);
        system_printf("rm -rf %s*", uci_path);
diff --git a/include/upgrade.h b/include/upgrade.h
new file mode 100644
index 0000000..6b5ace9
--- /dev/null
+++ b/include/upgrade.h
@@ -0,0 +1,6 @@
+#ifndef _UPGRADE_H__
+#define _UPGRADE_H__
+
+int sysupgrade_scan(const char *mount_path);
+
+#endif
diff --git a/mount.c b/mount.c
index 7cbb8ff..0bec25e 100644
--- a/mount.c
+++ b/mount.c
@@ -28,6 +28,7 @@
 #include "include/ucix.h"
 #include "include/fs.h"
 #include "include/mount.h"
+#include "include/upgrade.h"
 
 int mount_new(char *path, char *dev);
 
@@ -300,6 +301,7 @@ int mount_new(char *path, char *dev)
        {
                mount->mounted = 1;
                mount_dump_uci_state();
+               sysupgrade_scan(tmp);
        } else return -1;
        return 0;
 }
diff --git a/upgrade.c b/upgrade.c
new file mode 100644
index 0000000..6992e65
--- /dev/null
+++ b/upgrade.c
@@ -0,0 +1,162 @@
+/*
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   Provided by 9elements GmbH
+ *   Copyright (C) 2016 Philipp Deppenwiese <philipp.deppenwi...@9elements.com>
+ */
+
+#include <errno.h>
+#include <linux/limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include "include/upgrade.h"
+#include "include/log.h"
+
+#define SYSUPGRADE_CMD "/sbin/sysupgrade"
+
+extern char uci_upgrade_filename[255];
+extern int uci_upgrade_backup;
+extern int uci_upgrade_delay;
+extern int uci_upgrade_enabled;
+extern int uci_upgrade_preserve_partition;
+
+static unsigned option_index = 0;
+static char **parameters = NULL;
+
+static int execute_sysupgrade()
+{
+       pid_t pid;
+       int status;
+       char * const envp[] = { NULL };
+
+       if (!parameters) {
+               return 1;
+       }
+
+       if ((pid = fork()) < 0) {
+               perror("Can't fork child process for command invocation!");
+               return 1;
+       } else if (pid == 0) {
+               if (execve(SYSUPGRADE_CMD, parameters, envp) < 0) {
+                       log_printf("Error was reported on sysupgrade: %s\n", 
strerror(errno));
+                       return 1;
+               }
+       } else {
+               waitpid(pid, &status, 0);
+       }
+       return 0;
+}
+
+static int find_upgrade_filepath(const char *mount_path, char *update_file)
+{
+       struct stat file;
+
+       if (snprintf(update_file, PATH_MAX, "%s/%s", mount_path,
+                    uci_upgrade_filename) < 0) {
+               perror(NULL);
+               return 1;
+       }
+
+       if (stat(update_file, &file) < 0) {
+               log_printf("No upgrade file found for device path: %s! \n", 
mount_path);
+               return 1;
+       }
+       return 0;
+}
+
+static void add_sysupgrade_option(const char *parameter, ...)
+{
+       va_list arguments;
+       char *option = NULL;
+
+       parameters = realloc(parameters, ++option_index * sizeof(char*));
+
+       if (parameter) {
+               option = (char*)calloc(PATH_MAX, sizeof(char));
+
+               va_start(arguments, parameter);
+               vsnprintf(option, PATH_MAX, parameter, arguments);
+               va_end(arguments);
+       }
+
+       parameters[option_index - 1] = option;
+}
+
+static void free_all()
+{
+       unsigned i;
+
+       if (!parameters) {
+               return;
+       }
+
+       for (i = 0; i < option_index; i++) {
+               if (parameters[i]) {
+                       free(parameters[i]);
+               }
+       }
+
+       free(parameters);
+       parameters = NULL;
+       option_index = 0;
+}
+
+int sysupgrade_scan(const char *mount_path)
+{
+       char update_file[PATH_MAX];
+
+       if (!uci_upgrade_enabled) {
+               log_printf("Sysupgrade via usb device is disabled..\n");
+               return 0;
+       }
+
+       if (find_upgrade_filepath(mount_path, update_file)) {
+               log_printf("No upgrade file could be found..\n");
+               return 0;
+       }
+
+       log_printf("Starting sysupgrade routine..\n");
+
+       add_sysupgrade_option("%s", SYSUPGRADE_CMD);
+
+       if (uci_upgrade_delay) {
+               add_sysupgrade_option("-d %i", uci_upgrade_delay);
+       }
+
+       if (uci_upgrade_backup) {
+               add_sysupgrade_option("-c");
+       } else {
+               add_sysupgrade_option("-n");
+       }
+
+       if (uci_upgrade_preserve_partition) {
+               add_sysupgrade_option("-p");
+       }
+
+       add_sysupgrade_option("%s", update_file);
+       add_sysupgrade_option(NULL);
+
+       if (execute_sysupgrade()) {
+               free_all();
+               log_printf("Try to start sysupgrade but it failed! \n");
+               return 1;
+       }
+
+       free_all();
+       return 0;
+}
-- 
2.9.0


_______________________________________________
Lede-dev mailing list
Lede-dev@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/lede-dev

Reply via email to