On 06/07/16 06:58, John Crispin wrote:
> 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

One possible solution is to write a file, something like
".sysupgrade-applied" or remove the upgrade file before actually doing
the upgrade, or during first boot.

bruno

>       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
> 


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

Reply via email to