summaryrefslogtreecommitdiffstats
path: root/common
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2014-02-20 08:16:01 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2014-02-20 14:45:48 +0100
commit0a2a8f7059e6cb11e5d4eb882538b37f99d09ee3 (patch)
tree28cc9dc1ea53e04ff5f7cb8c4b7670095af58a39 /common
parentc2428b2287a8377fd277c429be993a4b9babdf7e (diff)
downloadbarebox-0a2a8f7059e6cb11e5d4eb882538b37f99d09ee3.tar.gz
barebox-0a2a8f7059e6cb11e5d4eb882538b37f99d09ee3.tar.xz
environment: Add function to load envfs from buffer
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'common')
-rw-r--r--common/environment.c181
1 files changed, 116 insertions, 65 deletions
diff --git a/common/environment.c b/common/environment.c
index 695baf7456..19fb0273b3 100644
--- a/common/environment.c
+++ b/common/environment.c
@@ -218,78 +218,52 @@ out1:
}
EXPORT_SYMBOL(envfs_save);
-/**
- * Restore the last environment into the current one
- * @param[in] filename from where to restore
- * @param[in] dir where to store the last content
- * @return 0 on success, anything else in case of failure
- *
- * Note: This function will also be used on the host! See note in the header
- * of this file.
- */
-int envfs_load(const char *filename, const char *dir, unsigned flags)
+static int envfs_check_super(struct envfs_super *super, size_t *size)
{
- struct envfs_super super;
- void *buf = NULL, *buf_free = NULL;
- int envfd;
- int fd, ret = 0;
- char *str, *tmp;
- int headerlen_full;
- unsigned long size;
- /* for envfs < 1.0 */
- struct envfs_inode_end inode_end_dummy;
-
- inode_end_dummy.mode = ENVFS_32(S_IRWXU | S_IRWXG | S_IRWXO);
- inode_end_dummy.magic = ENVFS_32(ENVFS_INODE_END_MAGIC);
-
- envfd = open(filename, O_RDONLY);
- if (envfd < 0) {
- printf("Open %s %s\n", filename, errno_str());
- return -1;
+ if (ENVFS_32(super->magic) != ENVFS_MAGIC) {
+ printf("envfs: wrong magic\n");
+ return -EIO;
}
- /* read superblock */
- ret = read(envfd, &super, sizeof(struct envfs_super));
- if ( ret < sizeof(struct envfs_super)) {
- perror("read");
- ret = -errno;
- goto out;
+ if (crc32(0, super, sizeof(*super) - 4) != ENVFS_32(super->sb_crc)) {
+ printf("wrong crc on env superblock\n");
+ return -EIO;
}
- if ( ENVFS_32(super.magic) != ENVFS_MAGIC) {
- printf("envfs: wrong magic on %s\n", filename);
- ret = -EIO;
- goto out;
- }
+ if (super->major < ENVFS_MAJOR)
+ printf("envfs version %d.%d loaded into %d.%d\n",
+ super->major, super->minor,
+ ENVFS_MAJOR, ENVFS_MINOR);
- if (crc32(0, (unsigned char *)&super, sizeof(struct envfs_super) - 4)
- != ENVFS_32(super.sb_crc)) {
- printf("wrong crc on env superblock\n");
- ret = -EIO;
- goto out;
- }
+ *size = ENVFS_32(super->size);
- size = ENVFS_32(super.size);
- buf = xmalloc(size);
- buf_free = buf;
- ret = read(envfd, buf, size);
- if (ret < size) {
- perror("read");
- ret = -errno;
- goto out;
- }
+ return 0;
+}
- if (crc32(0, (unsigned char *)buf, size)
- != ENVFS_32(super.crc)) {
+static int envfs_check_data(struct envfs_super *super, void *buf, size_t size)
+{
+ uint32_t crc;
+
+ crc = crc32(0, buf, size);
+ if (crc != ENVFS_32(super->crc)) {
printf("wrong crc on env\n");
- ret = -EIO;
- goto out;
+ return -EIO;
}
- if (super.major < ENVFS_MAJOR)
- printf("envfs version %d.%d loaded into %d.%d\n",
- super.major, super.minor,
- ENVFS_MAJOR, ENVFS_MINOR);
+ return 0;
+}
+
+static int envfs_load_data(void *buf, size_t size, const char *dir, unsigned flags)
+{
+ struct envfs_super super;
+ int fd, ret = 0;
+ char *str, *tmp;
+ int headerlen_full;
+ /* for envfs < 1.0 */
+ struct envfs_inode_end inode_end_dummy;
+
+ inode_end_dummy.mode = ENVFS_32(S_IRWXU | S_IRWXG | S_IRWXO);
+ inode_end_dummy.magic = ENVFS_32(ENVFS_INODE_END_MAGIC);
while (size) {
struct envfs_inode *inode;
@@ -300,7 +274,7 @@ int envfs_load(const char *filename, const char *dir, unsigned flags)
buf += sizeof(struct envfs_inode);
if (ENVFS_32(inode->magic) != ENVFS_INODE_MAGIC) {
- printf("envfs: wrong magic on %s\n", filename);
+ printf("envfs: wrong magic\n");
ret = -EIO;
goto out;
}
@@ -324,7 +298,7 @@ int envfs_load(const char *filename, const char *dir, unsigned flags)
buf += headerlen_full;
if (ENVFS_32(inode_end->magic) != ENVFS_INODE_END_MAGIC) {
- printf("envfs: wrong inode_end_magic on %s\n", filename);
+ printf("envfs: wrong inode_end_magic\n");
ret = -EIO;
goto out;
}
@@ -370,9 +344,86 @@ skip:
ret = 0;
out:
+ return ret;
+}
+
+int envfs_load_from_buf(void *buf, int len, const char *dir, unsigned flags)
+{
+ int ret;
+ size_t size;
+ struct envfs_super *super = buf;
+
+ buf = super + 1;
+
+ ret = envfs_check_super(super, &size);
+ if (ret)
+ return ret;
+
+ ret = envfs_check_data(super, buf, size);
+ if (ret)
+ return ret;
+
+ ret = envfs_load_data(buf, size, dir, flags);
+
+ return ret;
+}
+
+/**
+ * Restore the last environment into the current one
+ * @param[in] filename from where to restore
+ * @param[in] dir where to store the last content
+ * @return 0 on success, anything else in case of failure
+ *
+ * Note: This function will also be used on the host! See note in the header
+ * of this file.
+ */
+int envfs_load(const char *filename, const char *dir, unsigned flags)
+{
+ struct envfs_super super;
+ void *buf = NULL;
+ int envfd;
+ int ret = 0;
+ size_t size;
+
+ envfd = open(filename, O_RDONLY);
+ if (envfd < 0) {
+ printf("Open %s %s\n", filename, errno_str());
+ return -1;
+ }
+
+ /* read superblock */
+ ret = read(envfd, &super, sizeof(struct envfs_super));
+ if ( ret < sizeof(struct envfs_super)) {
+ perror("read");
+ ret = -errno;
+ goto out;
+ }
+
+ ret = envfs_check_super(&super, &size);
+ if (ret)
+ goto out;
+
+ buf = xmalloc(size);
+ ret = read(envfd, buf, size);
+ if (ret < size) {
+ perror("read");
+ ret = -errno;
+ goto out;
+ }
+
+ ret = envfs_check_data(&super, buf, size);
+ if (ret)
+ goto out;
+
+ ret = envfs_load_data(buf, size, dir, flags);
+ if (ret)
+ goto out;
+
+ ret = 0;
+out:
close(envfd);
- if (buf_free)
- free(buf_free);
+ free(buf);
+
return ret;
}