diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2007-07-05 18:01:44 +0200 |
---|---|---|
committer | Sascha Hauer <sha@octopus.labnet.pengutronix.de> | 2007-07-05 18:01:44 +0200 |
commit | a8699cf6772fd67e8b5004bfd5e6bbe91c37e679 (patch) | |
tree | 04dfe1d173bdc2ae257859ad7821e74bd1a5da21 /common/environment.c | |
parent | 158c5812a64517dc3fc1f930e187f26f542e10bd (diff) | |
download | barebox-a8699cf6772fd67e8b5004bfd5e6bbe91c37e679.tar.gz barebox-a8699cf6772fd67e8b5004bfd5e6bbe91c37e679.tar.xz |
svn_rev_335
add envload/envsave functions
Diffstat (limited to 'common/environment.c')
-rw-r--r-- | common/environment.c | 210 |
1 files changed, 210 insertions, 0 deletions
diff --git a/common/environment.c b/common/environment.c new file mode 100644 index 0000000000..8dd7338a9a --- /dev/null +++ b/common/environment.c @@ -0,0 +1,210 @@ +#include <common.h> +#include <command.h> +#include <driver.h> +#include <malloc.h> +#include <errno.h> +#include <asm-generic/errno.h> +#include <fs.h> +#include <fcntl.h> +#include <linux/stat.h> +#include <envfs.h> +#include <xfuncs.h> + +int envfs_save(char *path, char *env_path) +{ + struct dir *dir; + struct dirent *d; + int malloc_size = 0; + struct stat s; + struct envfs_super super; + void *buf = NULL; + char tmp[PATH_MAX]; + int isize; + int envfd; + struct envfs_inode *inode = NULL; + int fd; + + envfd = open(path, O_WRONLY); + if (envfd < 0) { + perror("open"); + return -1; + } + + super.magic = ENVFS_MAGIC; + + write(envfd, &super, sizeof(struct envfs_super)); + + dir = opendir(env_path); + if (!dir) { + perror("opendir"); + close(envfd); + return errno; + } + + while ((d = readdir(dir))) { + sprintf(tmp, "%s/%s", env_path, d->name); + if (stat(tmp, &s)) { + perror("stat"); + goto out; + } + if (s.st_mode & S_IFDIR) + continue; + + isize = ((s.st_size + 3) & ~3) + sizeof(struct envfs_inode); + if (isize > malloc_size) { + if (buf) + free(buf); + inode = xmalloc(isize); + malloc_size = isize; + } + fd = open(tmp, O_RDONLY); + if (fd < 0) { + perror("open"); + goto out; + } + if (read(fd, inode->data, s.st_size) < s.st_size) { + perror("read"); + goto out; + } + + close(fd); + inode->magic = ENVFS_INODE_MAGIC; + inode->size = s.st_size; + strcpy(inode->name, d->name); /* FIXME: strncpy */ + /* calc crc */ + if (write(envfd, inode, isize) < isize) { + perror("write"); + goto out; + } + } + + *(unsigned long *)tmp = ENVFS_END_MAGIC; + if (write(envfd, &tmp, 4) < 4) { + perror("write"); + goto out; + } +out: + if (buf) + free(buf); + close(envfd); + closedir(dir); + return 0; +} + +int do_envsave(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + char *env, *envpath; + + printf("saving environment\n"); + if (argc < 3) + envpath = "/env"; + else + envpath = argv[2]; + if (argc < 2) + env = "/dev/env0"; + else + env = argv[1]; + + return envfs_save(env, envpath); +} + +U_BOOT_CMD( + envsave, 3, 0, do_envsave, + "saveenv - save environment variables to persistent storage\n", + NULL +); + +int envfs_load(char *path, char *env_path) +{ + int malloc_size = 0; + struct envfs_super super; + void *buf = NULL; + char tmp[PATH_MAX]; + int envfd; + struct envfs_inode inode; + int fd; + + envfd = open(path, O_RDONLY); + if (envfd < 0) { + perror("open"); + return -1; + } + + if (read(envfd, &super, sizeof(struct envfs_super)) < sizeof(struct envfs_super)) { + perror("read"); + goto out; + } + + while (1) { + if (read(envfd, &inode, sizeof(struct envfs_inode)) < sizeof(struct envfs_inode)) { + perror("read"); + goto out; + } + if (inode.magic == ENVFS_END_MAGIC) + break; + if (inode.magic != ENVFS_INODE_MAGIC) { + printf("envfs: wrong magic on %s\n", path); + goto out; + } + if (inode.size > malloc_size) { + if (buf) + free(buf); + buf = xmalloc(inode.size); + malloc_size = inode.size; + } + if (read(envfd, buf, inode.size) < inode.size) { + perror("read"); + goto out; + } + sprintf(tmp, "%s/%s", env_path, inode.name); + + fd = open(tmp, O_WRONLY | O_CREAT); + if (fd < 0) { + perror("open"); + goto out; + } + + if (write(fd, buf, inode.size) < inode.size) { + perror("write"); + close(fd); + goto out; + } + close(fd); + + if (inode.size & 0x3) { + if (read(envfd, buf, 4 - (inode.size & 0x3)) < 4 - (inode.size & 0x3)) { + perror("read"); + goto out; + } + } + } + +out: + close(envfd); + if (buf) + free(buf); + return errno; +} + +int do_envload(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + char *env, *envpath; + + if (argc < 3) + envpath = "/env"; + else + envpath = argv[2]; + if (argc < 2) + env = "/dev/env0"; + else + env = argv[1]; + printf("loading environment\n"); + return envfs_load(env, envpath); +} + +U_BOOT_CMD( + envload, 3, 0, do_envload, + "envload - bla\n", + NULL +); + |