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