[PATCH 04/11] environment: Only save changes to the defaultenv

Sascha Hauer s.hauer at pengutronix.de
Thu Nov 6 04:59:31 PST 2014


Instead of storing the complete files with a 'saveenv' command
only store the files that have changes to the default environment.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 common/environment.c | 111 ++++++++++++++++++++++++++++++++++++++++++++++++---
 common/startup.c     |  11 ++---
 2 files changed, 108 insertions(+), 14 deletions(-)

diff --git a/common/environment.c b/common/environment.c
index 985adc1..a04b1fa 100644
--- a/common/environment.c
+++ b/common/environment.c
@@ -36,6 +36,8 @@
 #include <libbb.h>
 #include <libgen.h>
 #include <environment.h>
+#include <globalvar.h>
+#include <libfile.h>
 #else
 # define errno_str(x) ("void")
 #define EXPORT_SYMBOL(x)
@@ -57,6 +59,9 @@ struct action_data {
 #define PAD4(x) ((x + 3) & ~3)
 
 #ifdef __BAREBOX__
+
+#define TMPDIR "/.defaultenv"
+
 static char *default_environment_path = "/dev/env0";
 
 void default_environment_path_set(char *path)
@@ -68,6 +73,21 @@ char *default_environment_path_get(void)
 {
 	return default_environment_path;
 }
+
+static int do_compare_file(const char *filename, const char *base)
+{
+	int ret;
+	char *cmp;
+	const char *relname = filename + strlen(base) + 1;
+
+	cmp = asprintf("%s/%s", TMPDIR, relname);
+	ret = compare_file(cmp, filename);
+
+	free(cmp);
+
+	return ret;
+}
+
 #else
 static inline int protect(int fd, size_t count, unsigned long offset, int prot)
 {
@@ -78,6 +98,11 @@ static inline int erase(int fd, size_t count, unsigned long offset)
 {
 	return 0;
 }
+
+static int do_compare_file(const char *filename, const char *base)
+{
+	return 1;
+}
 #endif
 
 static int file_action(const char *filename, struct stat *statbuf,
@@ -87,6 +112,9 @@ static int file_action(const char *filename, struct stat *statbuf,
 	struct envfs_entry *env;
 	int fd, ret;
 
+	if (!do_compare_file(filename, data->base))
+		return 1;
+
 	env = xzalloc(sizeof(*env));
 	env->name = strdup(filename + strlen(data->base));
 	env->size = statbuf->st_size;
@@ -153,6 +181,60 @@ static void envfs_save_inode(struct action_data *data, struct envfs_entry *env)
 	data->writep += PAD4(env->size);
 }
 
+#ifdef __BAREBOX__
+static int file_remove_action(const char *filename, struct stat *statbuf,
+		void *userdata, int depth)
+{
+	struct action_data *data = userdata;
+	char *envname;
+	struct stat s;
+	int ret;
+	struct envfs_entry *env;
+
+	filename += sizeof(TMPDIR) - 1;
+
+	envname = asprintf("%s/%s", data->base, filename);
+
+	ret = stat(envname, &s);
+	if (ret) {
+		char *base;
+
+		base = basename(envname);
+
+		env = xzalloc(sizeof(*env));
+		env->name = strdup(filename);
+		env->size = strlen(base) + 1;
+
+		env->buf = strdup(base);
+		if (!env->buf)
+			goto out;
+
+		env->mode = S_IRWXU | S_IRWXG | S_IRWXO | S_IFLNK;
+
+		env->next = data->env;
+		data->env = env;
+	}
+out:
+	free(envname);
+
+	return 1;
+}
+#else
+static int file_remove_action(const char *filename, struct stat *statbuf,
+		void *userdata, int depth)
+{
+	return 0;
+}
+#endif
+
+static int dir_remove_action(const char *filename, struct stat *statbuf,
+		void *userdata, int depth)
+{
+	rmdir(filename);
+
+	return 1;
+}
+
 /**
  * Make the current environment persistent
  * @param[in] filename where to store
@@ -174,12 +256,18 @@ int envfs_save(const char *filename, const char *dirname, unsigned flags)
 	data.writep = NULL;
 	data.base = dirname;
 
+#ifdef __BAREBOX__
+	defaultenv_load(TMPDIR, 0);
+#endif
+
 	if (flags & ENVFS_FLAGS_FORCE_BUILT_IN) {
 		size = 0; /* force no content */
 	} else {
 		/* first pass: calculate size */
 		recursive_action(dirname, ACTION_RECURSE, file_action,
 				NULL, &data, 0);
+		recursive_action("/.defaultenv", ACTION_RECURSE,
+				file_remove_action, NULL, &data, 0);
 		size = 0;
 
 		for (env = data.env; env; env = env->next) {
@@ -270,6 +358,9 @@ out:
 	close(envfd);
 out1:
 	free(buf);
+#ifdef __BAREBOX__
+	unlink_recursive(TMPDIR, NULL);
+#endif
 	return ret;
 }
 EXPORT_SYMBOL(envfs_save);
@@ -346,9 +437,6 @@ static int envfs_load_data(struct envfs_super *super, void *buf, size_t size,
 			inode_size, namelen, inode_headerlen);
 
 		str = concat_path_file(dir, inode->data);
-		tmp = strdup(str);
-		make_directory(dirname(tmp));
-		free(tmp);
 
 		headerlen_full = PAD4(inode_headerlen);
 		buf += headerlen_full;
@@ -359,11 +447,19 @@ static int envfs_load_data(struct envfs_super *super, void *buf, size_t size,
 			goto out;
 		}
 
+		tmp = strdup(str);
+		make_directory(dirname(tmp));
+		free(tmp);
+
 		if (S_ISLNK(ENVFS_32(inode_end->mode))) {
 			debug("symlink: %s -> %s\n", str, (char*)buf);
-			if (symlink(buf, str) < 0) {
-				printf("symlink: %s -> %s :", str, (char*)buf);
-				perror("");
+			if (!strcmp(buf, basename(str))) {
+				unlink(str);
+			} else {
+				ret = symlink(buf, str);
+				if (ret < 0)
+					printf("symlink: %s -> %s : %s\n",
+							str, (char*)buf, strerror(-errno));
 			}
 			free(str);
 		} else {
@@ -398,6 +494,9 @@ skip:
 				sizeof(struct envfs_inode);
 	}
 
+	recursive_action(dir, ACTION_RECURSE | ACTION_DEPTHFIRST, NULL,
+			dir_remove_action, NULL, 0);
+
 	ret = 0;
 out:
 	return ret;
diff --git a/common/startup.c b/common/startup.c
index ceb597b..f164142 100644
--- a/common/startup.c
+++ b/common/startup.c
@@ -78,17 +78,12 @@ void __noreturn start_barebox(void)
 	pr_debug("initcalls done\n");
 
 	if (IS_ENABLED(CONFIG_ENV_HANDLING)) {
-		int ret;
 		char *default_environment_path = default_environment_path_get();
 
-		ret = envfs_load(default_environment_path, "/env", 0);
-
-		if (ret && IS_ENABLED(CONFIG_DEFAULT_ENVIRONMENT)) {
-			pr_err("no valid environment found on %s. "
-				"Using default environment\n",
-				default_environment_path);
+		if (IS_ENABLED(CONFIG_DEFAULT_ENVIRONMENT))
 			defaultenv_load("/env", 0);
-		}
+
+		envfs_load(default_environment_path, "/env", 0);
 	}
 
 	if (IS_ENABLED(CONFIG_COMMAND_SUPPORT)) {
-- 
2.1.1




More information about the barebox mailing list