scripts/bareboxenv: skip file creation to allow reading the destination
file, when existing.

Signed-off-by: Jonas Licht <jonas.li...@gmail.com>
Fixes #29
---
 common/environment.c | 62 +++++++++++++++++++++++++++++++++++++++-----
 scripts/bareboxenv.c | 11 +-------
 2 files changed, 57 insertions(+), 16 deletions(-)

diff --git a/common/environment.c b/common/environment.c
index 37adb5d678..dee746a6b2 100644
--- a/common/environment.c
+++ b/common/environment.c
@@ -305,9 +305,10 @@ int envfs_save(const char *filename, const char *dirname, 
unsigned flags)
        struct envfs_super *super;
        int envfd, size, ret;
        struct action_data data = {};
-       void *buf = NULL, *wbuf;
+       void *buf = NULL, *wbuf, *bufWithEfi;
        struct envfs_entry *env;
        const char *defenv_path = default_environment_path_get();
+       uint32_t magic;
 
        if (!filename)
                filename = defenv_path;
@@ -342,7 +343,9 @@ int envfs_save(const char *filename, const char *dirname, 
unsigned flags)
                }
        }
 
-       buf = xzalloc(size + sizeof(struct envfs_super));
+       bufWithEfi = xzalloc(size + sizeof(struct envfs_super) +
+                            4); // four byte efi attributes
+       buf = bufWithEfi + 4;
        data.writep = buf + sizeof(struct envfs_super);
 
        super = buf;
@@ -370,7 +373,7 @@ int envfs_save(const char *filename, const char *dirname, 
unsigned flags)
        super->crc = ENVFS_32(crc32(0, buf + sizeof(struct envfs_super), size));
        super->sb_crc = ENVFS_32(crc32(0, buf, sizeof(struct envfs_super) - 4));
 
-       envfd = open(filename, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
+       envfd = open(filename, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
        if (envfd < 0) {
                printf("could not open %s: %m\n", filename);
                ret = -errno;
@@ -385,6 +388,34 @@ int envfs_save(const char *filename, const char *dirname, 
unsigned flags)
                goto out;
        }
 
+       wbuf = buf;
+
+       /* check if we writing efi vars */
+       ret = pread(envfd, &magic, sizeof(uint32_t),
+                   4); // four byte efi var attributes
+       if (ret == -1 && errno == ENOENT) {
+               // skip as file don't exist
+               goto skip_efi_read;
+       }
+       if (ret < sizeof(u_int32_t)) {
+               perror("read of destination file failed");
+               ret = -errno;
+               goto skip_efi_read;
+       }
+
+       if (ENVFS_32(magic) == ENVFS_MAGIC) {
+               pr_info("looks like we writing efi vars, keep attributes\n");
+               ret = pread(envfd, bufWithEfi, sizeof(uint32_t), 0);
+               if (ret < sizeof(uint32_t)) {
+                       perror("read of efi attributes failed");
+                       ret = -errno;
+                       goto out;
+               }
+               size += sizeof(uint32_t);
+               wbuf = bufWithEfi;
+       }
+
+skip_efi_read:
        ret = erase(envfd, ERASE_SIZE_ALL, 0, ERASE_TO_WRITE);
 
        /* ENOSYS and EOPNOTSUPP aren't errors here, many devices don't need it 
*/
@@ -395,8 +426,6 @@ int envfs_save(const char *filename, const char *dirname, 
unsigned flags)
 
        size += sizeof(struct envfs_super);
 
-       wbuf = buf;
-
        while (size) {
                ssize_t now = write(envfd, wbuf, size);
                if (now < 0) {
@@ -425,7 +454,7 @@ int envfs_save(const char *filename, const char *dirname, 
unsigned flags)
 out:
        close(envfd);
 out1:
-       free(buf);
+       free(bufWithEfi);
 #ifdef __BAREBOX__
        unlink_recursive(TMPDIR, NULL);
 #endif
@@ -449,6 +478,7 @@ int envfs_load(const char *filename, const char *dir, 
unsigned flags)
        int envfd;
        int ret = 0;
        size_t size, rsize;
+       uint32_t magic;
 
        if (!filename)
                filename = default_environment_path_get();
@@ -466,6 +496,26 @@ int envfs_load(const char *filename, const char *dir, 
unsigned flags)
                return -1;
        }
 
+       /* check if we reading efi vars */
+       ret = pread(envfd, &magic, sizeof(uint32_t),
+                   4); // four byte efi var attributes
+       if (ret < sizeof(u_int32_t)) {
+               perror("read");
+               ret = -errno;
+               goto out;
+       }
+
+       if (ENVFS_32(magic) == ENVFS_MAGIC) {
+               pr_info("looks like we reading efi vars, skip attributes\n");
+               ret = read(envfd, &magic,
+                          sizeof(uint32_t)); // simply reuse the memory
+               if (ret < sizeof(uint32_t)) {
+                       perror("read");
+                       ret = -errno;
+                       goto out;
+               }
+       }
+
        /* read superblock */
        ret = read(envfd, &super, sizeof(struct envfs_super));
        if ( ret < sizeof(struct envfs_super)) {
diff --git a/scripts/bareboxenv.c b/scripts/bareboxenv.c
index e954447015..6b9b8d90c4 100644
--- a/scripts/bareboxenv.c
+++ b/scripts/bareboxenv.c
@@ -117,7 +117,7 @@ static void usage(char *prgname)
 int main(int argc, char *argv[])
 {
        int opt;
-       int save = 0, load = 0, pad = 0, err = 0, fd;
+       int save = 0, load = 0, pad = 0, err = 0;
        char *filename = NULL, *dirname = NULL;
        unsigned envfs_flags = 0;
        int verbose = 0;
@@ -156,15 +156,6 @@ int main(int argc, char *argv[])
                exit(1);
        }
 
-       if (save) {
-               fd = open(filename, O_CREAT | O_TRUNC | O_WRONLY, 0644);
-               if (fd < 0) {
-                       perror("open");
-                       exit(1);
-               }
-               close(fd);
-       }
-
        if (save && pad) {
                if (truncate(filename, pad)) {
                        perror("truncate");
-- 
2.45.3


Reply via email to