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

Philipp Deppenwiese zaolin at das-labor.org
Mon Jul 4 09:56:38 PDT 2016


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;
+}
-- 
2.9.0




More information about the Lede-dev mailing list