Hi Philipp

the thing that i am worried about is this process

1) plug a stick
2) mountd detects the upgrade file
3) mountd triggers sysupgrade
4) system reboots
5) goto 1)

there is no way to know at what point between 3 and 4 we need to unplug
the usb stick

        John

On 04/07/2016 18:56, Philipp Deppenwiese wrote:
> 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;
> +}
> 

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

Reply via email to