summaryrefslogtreecommitdiffstats
path: root/common
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2012-09-05 12:59:29 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2012-09-05 12:59:29 +0200
commite5a927883ea8f85e2258d5e15ac6ede8f44aeaab (patch)
tree1798a5dc8008c29d688093783e6bece1094cedbc /common
parent62b665b6442c493eb2537d1c5f6c8925a2ce73bf (diff)
parent42d3d24c7152462f7bb40056255ebcfffa8dbd9f (diff)
downloadbarebox-e5a927883ea8f85e2258d5e15ac6ede8f44aeaab.tar.gz
barebox-e5a927883ea8f85e2258d5e15ac6ede8f44aeaab.tar.xz
Merge branch 'for-next/link'
Diffstat (limited to 'common')
-rw-r--r--common/Makefile2
-rw-r--r--common/environment.c150
2 files changed, 113 insertions, 39 deletions
diff --git a/common/Makefile b/common/Makefile
index d74dffb916..df9f301234 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -58,7 +58,7 @@ ifneq ($(CONFIG_DEFAULT_ENVIRONMENT_PATH),"")
DEFAULT_ENVIRONMENT_PATH += $(CONFIG_DEFAULT_ENVIRONMENT_PATH)
endif
-ENV_FILES := $(shell cd $(srctree); for i in $(DEFAULT_ENVIRONMENT_PATH); do find $${i} -type f -exec readlink -f '{}' \;; done)
+ENV_FILES := $(shell cd $(srctree); for i in $(DEFAULT_ENVIRONMENT_PATH); do find $${i} -type f ; done)
endif # ifdef CONFIG_DEFAULT_ENVIRONMENT
diff --git a/common/environment.c b/common/environment.c
index 52ce0de1da..ce46f4a0e6 100644
--- a/common/environment.c
+++ b/common/environment.c
@@ -53,7 +53,21 @@ int file_size_action(const char *filename, struct stat *statbuf,
data->writep += sizeof(struct envfs_inode);
data->writep += PAD4(strlen(filename) + 1 - strlen(data->base));
- data->writep += PAD4(statbuf->st_size);
+ data->writep += sizeof(struct envfs_inode_end);
+ if (S_ISLNK(statbuf->st_mode)) {
+ char path[PATH_MAX];
+
+ memset(path, 0, PATH_MAX);
+
+ if (readlink(filename, path, PATH_MAX - 1) < 0) {
+ perror("read");
+ return 0;
+ }
+ data->writep += PAD4(strlen(path) + 1);
+ } else {
+ data->writep += PAD4(statbuf->st_size);
+ }
+
return 1;
}
@@ -62,34 +76,60 @@ int file_save_action(const char *filename, struct stat *statbuf,
{
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);
- debug("handling file %s size %ld namelen %d\n", filename + strlen(data->base),
- statbuf->st_size, namelen);
-
inode = (struct envfs_inode*)data->writep;
inode->magic = ENVFS_32(ENVFS_INODE_MAGIC);
- inode->namelen = ENVFS_32(namelen);
- inode->size = ENVFS_32(statbuf->st_size);
+ inode->headerlen = ENVFS_32(PAD4(namelen + sizeof(struct envfs_inode_end)));
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) {
- printf("Open %s %s\n", filename, errno_str());
- goto out;
- }
+ if (S_ISLNK(statbuf->st_mode)) {
+ char path[PATH_MAX];
+ int len;
- if (read(fd, data->writep, statbuf->st_size) < statbuf->st_size) {
- perror("read");
- goto out;
- }
- close(fd);
+ memset(path, 0, PATH_MAX);
+
+ if (readlink(filename, path, PATH_MAX - 1) < 0) {
+ perror("read");
+ goto out;
+ }
+ len = strlen(path) + 1;
+
+ inode_end->mode |= ENVFS_32(S_IFLNK);
+
+ memcpy(data->writep, path, len);
+ inode->size = ENVFS_32(len);
+ data->writep += PAD4(len);
+ debug("handling symlink %s size %ld namelen %d headerlen %d\n", filename + strlen(data->base),
+ len, namelen, ENVFS_32(inode->headerlen));
+ } else {
+ debug("handling file %s size %ld namelen %d headerlen %d\n", filename + strlen(data->base),
+ statbuf->st_size, namelen, ENVFS_32(inode->headerlen));
- data->writep += PAD4(statbuf->st_size);
+ inode->size = ENVFS_32(statbuf->st_size);
+ fd = open(filename, O_RDONLY);
+ if (fd < 0) {
+ printf("Open %s %s\n", filename, errno_str());
+ goto out;
+ }
+
+ if (read(fd, data->writep, statbuf->st_size) < statbuf->st_size) {
+ perror("read");
+ goto out;
+ }
+ close(fd);
+
+ data->writep += PAD4(statbuf->st_size);
+ }
out:
return 1;
@@ -125,6 +165,8 @@ int envfs_save(char *filename, char *dirname)
super = (struct envfs_super *)buf;
super->magic = ENVFS_32(ENVFS_MAGIC);
+ super->major = ENVFS_MAJOR;
+ super->minor = ENVFS_MINOR;
super->size = ENVFS_32(size);
/* second pass: copy files to buffer */
@@ -174,8 +216,13 @@ int envfs_load(char *filename, char *dir)
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) {
@@ -221,11 +268,18 @@ int envfs_load(char *filename, char *dir)
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);
@@ -233,38 +287,58 @@ int envfs_load(char *filename, char *dir)
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);
- fd = open(str, O_WRONLY | O_CREAT | O_TRUNC, 0644);
- free(str);
- if (fd < 0) {
- printf("Open %s\n", errno_str());
- ret = fd;
+ 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;
}
- namelen_full = PAD4(inode_namelen);
- ret = write(fd, buf + namelen_full + sizeof(struct envfs_inode),
- inode_size);
- if (ret < inode_size) {
- perror("write");
- ret = -errno;
+ if (S_ISLNK(ENVFS_32(inode_end->mode))) {
+ debug("symlink: %s -> %s\n", str, (char*)buf);
+ if (symlink((char*)buf, str) < 0) {
+ printf("symlink: %s -> %s :", str, (char*)buf);
+ perror("");
+ }
+ free(str);
+ } else {
+ fd = open(str, O_WRONLY | O_CREAT | O_TRUNC, 0644);
+ free(str);
+ if (fd < 0) {
+ printf("Open %s\n", errno_str());
+ ret = fd;
+ goto out;
+ }
+
+ ret = write(fd, buf, inode_size);
+ if (ret < inode_size) {
+ perror("write");
+ ret = -errno;
+ close(fd);
+ goto out;
+ }
close(fd);
- goto out;
}
- 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);
}