diff --git a/common/environment.c b/common/environment.c index 8efed97..fc5c57e 100644 --- a/common/environment.c +++ b/common/environment.c @@ -53,6 +53,7 @@ data->writep += sizeof(struct envfs_inode); data->writep += PAD4(strlen(filename) + 1 - strlen(data->base)); + data->writep += sizeof(struct envfs_inode_end); data->writep += PAD4(statbuf->st_size); return 1; } @@ -62,6 +63,7 @@ { struct action_data *data = userdata; struct envfs_inode *inode; + struct envfs_inode_end *inode_end; int fd; int namelen = strlen(filename) + 1 - strlen(data->base); @@ -70,12 +72,16 @@ inode = (struct envfs_inode*)data->writep; inode->magic = ENVFS_32(ENVFS_INODE_MAGIC); - inode->namelen = ENVFS_32(namelen); + inode->headerlen = ENVFS_32(PAD4(namelen + sizeof(struct envfs_inode_end))); inode->size = ENVFS_32(statbuf->st_size); data->writep += sizeof(struct envfs_inode); strcpy(data->writep, filename + strlen(data->base)); data->writep += PAD4(namelen); + inode_end = (struct envfs_inode_end*)data->writep; + data->writep += sizeof(struct envfs_inode_end); + inode_end->magic = ENVFS_32(ENVFS_INODE_END_MAGIC); + inode_end->mode = ENVFS_32(S_IRWXU | S_IRWXG | S_IRWXO); fd = open(filename, O_RDONLY); if (fd < 0) { @@ -176,8 +182,13 @@ int envfd; int fd, ret = 0; char *str, *tmp; - int namelen_full; + 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) { @@ -223,11 +234,18 @@ 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); + while (size) { struct envfs_inode *inode; - uint32_t inode_size, inode_namelen; + struct envfs_inode_end *inode_end; + uint32_t inode_size, inode_headerlen, namelen; inode = (struct envfs_inode *)buf; + buf += sizeof(struct envfs_inode); if (ENVFS_32(inode->magic) != ENVFS_INODE_MAGIC) { printf("envfs: wrong magic on %s\n", filename); @@ -235,16 +253,30 @@ goto out; } inode_size = ENVFS_32(inode->size); - inode_namelen = ENVFS_32(inode->namelen); + inode_headerlen = ENVFS_32(inode->headerlen); + namelen = strlen(inode->data) + 1; + if (super.major < 1) + inode_end = &inode_end_dummy; + else + inode_end = (struct envfs_inode_end *)(buf + PAD4(namelen)); - debug("loading %s size %d namelen %d\n", inode->data, - inode_size, inode_namelen); + debug("loading %s size %d namelen %d headerlen %d\n", inode->data, + 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; + + if (ENVFS_32(inode_end->magic) != ENVFS_INODE_END_MAGIC) { + printf("envfs: wrong inode_end_magic on %s\n", filename); + ret = -EIO; + goto out; + } + fd = open(str, O_WRONLY | O_CREAT | O_TRUNC, 0644); free(str); if (fd < 0) { @@ -253,9 +285,7 @@ goto out; } - namelen_full = PAD4(inode_namelen); - ret = write(fd, buf + namelen_full + sizeof(struct envfs_inode), - inode_size); + ret = write(fd, buf, inode_size); if (ret < inode_size) { perror("write"); ret = -errno; @@ -264,9 +294,8 @@ } close(fd); - buf += PAD4(inode_namelen) + PAD4(inode_size) + - sizeof(struct envfs_inode); - size -= PAD4(inode_namelen) + PAD4(inode_size) + + buf += PAD4(inode_size); + size -= headerlen_full + PAD4(inode_size) + sizeof(struct envfs_inode); } diff --git a/include/envfs.h b/include/envfs.h index c6df8c5..3d14fcb 100644 --- a/include/envfs.h +++ b/include/envfs.h @@ -5,18 +5,19 @@ #include #endif -#define ENVFS_MAJOR 0 -#define ENVFS_MINOR 1 +#define ENVFS_MAJOR 1 +#define ENVFS_MINOR 0 #define ENVFS_MAGIC 0x798fba79 /* some random number */ #define ENVFS_INODE_MAGIC 0x67a8c78d +#define ENVFS_INODE_END_MAGIC 0x68a8c78d #define ENVFS_END_MAGIC 0x6a87d6cd #define ENVFS_SIGNATURE "barebox envfs" struct envfs_inode { uint32_t magic; /* ENVFS_INODE_MAGIC */ uint32_t size; /* data size in bytes */ - uint32_t namelen; /* The length of the filename _including_ a trailing 0 */ + uint32_t headerlen; /* The length of the filename _including_ a trailing 0 */ char data[0]; /* The filename (zero terminated) + padding to 4 byte boundary * followed by the data for this inode. * The next inode follows after the data + padding to 4 byte @@ -24,6 +25,11 @@ */ }; +struct envfs_inode_end { + uint32_t magic; /* ENVFS_INODE_END_MAGIC */ + uint32_t mode; /* file mode */ +}; + /* * Superblock information at the beginning of the FS. */