environment: Only save changes to the defaultenv
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@pengutronix.de>
This commit is contained in:
parent
eb3ef18c8c
commit
70e718baa1
|
@ -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;
|
||||
|
|
|
@ -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)) {
|
||||
|
|
Loading…
Reference in New Issue