[LEDE-DEV] [PATCH] Mountd: Add sysupgrade functionality.

Wang Linetkux chinawrj at gmail.com
Wed Jul 6 03:34:11 PDT 2016


Another possible solution is to record the HASH of system image after
system upgrade is done. Next time when we try to do the system
upgrade, we can compare the recorded HASH value and the compute value
from system upgrade file?

2016-07-06 18:18 GMT+08:00 Bruno Randolf <br1 at einfach.org>:
> 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 <zaolin at 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.deppenwiese at 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 at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/lede-dev
>>
>
>
> _______________________________________________
> Lede-dev mailing list
> Lede-dev at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/lede-dev



More information about the Lede-dev mailing list