summaryrefslogtreecommitdiffstats
path: root/common/environment.c
diff options
context:
space:
mode:
authorJean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>2012-08-22 12:51:43 +0800
committerJean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>2012-09-05 03:22:14 +0800
commitacef08abb7b7826a7a4a50b65003bb1a3e25fb75 (patch)
treeb3c45b5ac94e96bf5c8aef1409174f30d837619f /common/environment.c
parentd3cbc615962c8e96f88d9e74645c5afb441431bb (diff)
downloadbarebox-acef08abb7b7826a7a4a50b65003bb1a3e25fb75.tar.gz
barebox-acef08abb7b7826a7a4a50b65003bb1a3e25fb75.tar.xz
envfs: add support of symlink
Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
Diffstat (limited to 'common/environment.c')
-rw-r--r--common/environment.c103
1 files changed, 73 insertions, 30 deletions
diff --git a/common/environment.c b/common/environment.c
index fc5c57e884..ce46f4a0e6 100644
--- a/common/environment.c
+++ b/common/environment.c
@@ -54,7 +54,20 @@ 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 += sizeof(struct envfs_inode_end);
- data->writep += PAD4(statbuf->st_size);
+ 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;
}
@@ -67,13 +80,9 @@ int file_save_action(const char *filename, struct stat *statbuf,
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->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));
@@ -83,19 +92,44 @@ int file_save_action(const char *filename, struct stat *statbuf,
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);
- data->writep += PAD4(statbuf->st_size);
+ 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));
+
+ 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;
@@ -277,22 +311,31 @@ int envfs_load(char *filename, char *dir)
goto out;
}
- 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;
+ 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_size);
size -= headerlen_full + PAD4(inode_size) +