diff mbox series

[06/12] Implement IPC to set / get SWUpdate's vars

Message ID 20231016165740.1374614-6-stefano.babic@swupdate.org
State Changes Requested
Delegated to: Stefano Babic
Headers show
Series [01/12] Cleanup: use #pragma once in all headers | expand

Commit Message

Stefano Babic Oct. 16, 2023, 4:57 p.m. UTC
Access to SWUPdate's vars (namespace) is guaranteed for the core, but
other processes could need to store some values to store a state between
runs. This is not possible from subprocess because rights are not
guaranteed for the namespace's storage.

Add an IPC as done for bootloader environment to let subprocesses to
store persistently variables.

Signed-off-by: Stefano Babic <stefano.babic@swupdate.org>
---
 core/network_thread.c   | 17 +++++++++++
 core/swupdate_vars.c    | 68 +++++++++++++++++++++++++++++++++++++----
 include/swupdate_vars.h |  2 ++
 3 files changed, 81 insertions(+), 6 deletions(-)
diff mbox series

Patch

diff --git a/core/network_thread.c b/core/network_thread.c
index 916caf28..6b349784 100644
--- a/core/network_thread.c
+++ b/core/network_thread.c
@@ -33,6 +33,7 @@ 
 #include "pctl.h"
 #include "generated/autoconf.h"
 #include "state.h"
+#include "swupdate_vars.h"
 
 #ifdef CONFIG_SYSTEMD
 #include <systemd/sd-daemon.h>
@@ -451,6 +452,7 @@  void *network_thread (void *data)
 	struct subprocess_msg_elem *subprocess_msg;
 	bool should_close_socket;
 	struct swupdate_cfg *cfg;
+	char *varvalue;
 
 	if (!instp) {
 		TRACE("Fatal error: Network thread aborting...");
@@ -690,6 +692,21 @@  void *network_thread (void *data)
 				msg.data.msg[0] = get_state();
 				msg.type = ACK;
 				break;
+			case SET_SWUPDATE_VARS:
+				msg.type = swupdate_vars_set(msg.data.vars.varname,
+						  msg.data.vars.varvalue,
+						  msg.data.vars.varnamespace) == 0 ? ACK : NACK;
+				break;
+			case GET_SWUPDATE_VARS:
+				varvalue = swupdate_vars_get(msg.data.vars.varname,
+						  msg.data.vars.varnamespace);
+				memset(msg.data.vars.varvalue, 0, sizeof(msg.data.vars.varvalue));
+				if (varvalue) {
+					strlcpy(msg.data.vars.varvalue, varvalue, sizeof(msg.data.vars.varvalue));
+					msg.type = ACK;
+				} else
+					msg.type = NACK;
+				break;
 			default:
 				msg.type = NACK;
 			}
diff --git a/core/swupdate_vars.c b/core/swupdate_vars.c
index 4dd97ff7..f1e536a8 100644
--- a/core/swupdate_vars.c
+++ b/core/swupdate_vars.c
@@ -17,11 +17,13 @@ 
 #include <dirent.h>
 #include "generated/autoconf.h"
 #include "util.h"
-#include "dlfcn.h"
-#include "bootloader.h"
+#include "pctl.h"
+#include <network_ipc.h>
 
 #include "swupdate_vars.h"
 
+char *namespace_default = NULL;
+
 static inline void libuboot_cleanup(struct uboot_ctx *ctx)
 {
 	libuboot_close(ctx);
@@ -32,8 +34,11 @@  int swupdate_vars_initialize(struct uboot_ctx **ctx, const char *namespace)
 {
 	int ret;
 
-	if (!namespace)
-		return -EINVAL;
+	if (!namespace || !strlen(namespace)) {
+		if(!namespace_default)
+			return -EINVAL;
+		namespace = namespace_default;
+	}
 
 	ret = libuboot_read_config_ext(ctx, get_fwenv_config());
 	if (ret) {
@@ -50,7 +55,7 @@  int swupdate_vars_initialize(struct uboot_ctx **ctx, const char *namespace)
 	return 0;
 }
 
-char *swupdate_vars_get(const char *name, const char *namespace)
+static char *__swupdate_vars_get(const char *name, const char *namespace)
 {
 	int ret;
 	struct uboot_ctx *ctx = NULL;
@@ -65,7 +70,32 @@  char *swupdate_vars_get(const char *name, const char *namespace)
 	return value;
 }
 
-int swupdate_vars_set(const char *name, const char *value, const char *namespace)
+char *swupdate_vars_get(const char *name, const char *namespace)
+{
+	if (!name)
+		return NULL;
+
+	if (pid == getpid())
+	{
+		ipc_message msg;
+		memset(&msg, 0, sizeof(msg));
+
+		msg.type = GET_SWUPDATE_VARS;
+		if (namespace)
+			strlcpy(msg.data.vars.varnamespace, namespace, sizeof(msg.data.vars.varnamespace));
+		strlcpy(msg.data.vars.varname, name, sizeof(msg.data.vars.varname));
+
+		if (ipc_send_cmd(&msg) || msg.type == NACK) {
+			ERROR("Failed to get variable %s", name);
+			return NULL;
+		}
+		return strdup (msg.data.vars.varvalue);
+	}
+
+	return __swupdate_vars_get(name, namespace);
+}
+
+static int __swupdate_vars_set(const char *name, const char *value, const char *namespace)
 {
 	int ret;
 	struct uboot_ctx *ctx = NULL;
@@ -81,6 +111,28 @@  int swupdate_vars_set(const char *name, const char *value, const char *namespace
 	return ret;
 }
 
+int swupdate_vars_set(const char *name, const char *value, const char *namespace)
+{
+	ipc_message msg;
+
+	if (!name)
+		return -EINVAL;
+
+	if (pid == getpid()) {
+		memset(&msg, 0, sizeof(msg));
+		msg.magic = IPC_MAGIC;
+		msg.type = SET_SWUPDATE_VARS;
+		if (namespace)
+			strlcpy(msg.data.vars.varnamespace, namespace, sizeof(msg.data.vars.varnamespace));
+		strlcpy(msg.data.vars.varname, name, sizeof(msg.data.vars.varname));
+		if (value)
+			strlcpy(msg.data.vars.varvalue, value, sizeof(msg.data.vars.varvalue));
+		return !(ipc_send_cmd(&msg) == 0 && msg.type == ACK);
+	}
+
+	return __swupdate_vars_set(name, value, namespace);
+}
+
 int swupdate_vars_unset(const char *name, const char *namespace)
 {
 	return swupdate_vars_set(name, NULL, namespace);
@@ -91,6 +143,10 @@  int swupdate_vars_apply_list(const char *filename, const char *namespace)
 	int ret;
 	struct uboot_ctx *ctx = NULL;
 
+	if (pid == getpid()) {
+		ERROR("This function can be called only by core !");
+		return -EINVAL;
+	}
 	ret = swupdate_vars_initialize(&ctx, namespace);
 	if (!ret) {
 		libuboot_load_file(ctx, filename);
diff --git a/include/swupdate_vars.h b/include/swupdate_vars.h
index cbff84e5..1dcab972 100644
--- a/include/swupdate_vars.h
+++ b/include/swupdate_vars.h
@@ -8,9 +8,11 @@ 
 #pragma once
 
 #include <libuboot.h>
+#include <stdbool.h>
 
 int swupdate_vars_initialize(struct uboot_ctx **ctx, const char *namespace);
 int swupdate_vars_apply_list(const char *filename, const char *namespace);
 char *swupdate_vars_get(const char *name, const char *namespace);
 int swupdate_vars_set(const char *name, const char *value, const char *namespace);
 int swupdate_vars_unset(const char *name, const char *namespace);
+bool swupdate_set_default_namespace(const char *namespace);