9
0
Fork 0

Merge branch 'for-next/link'

This commit is contained in:
Sascha Hauer 2012-09-05 12:59:29 +02:00
commit e5a927883e
18 changed files with 677 additions and 101 deletions

View File

@ -264,3 +264,4 @@ then
else
do_build_target ${ARCH} $1
fi
exit $nb_errors

View File

@ -57,6 +57,10 @@ config CMD_READLINE
tristate
prompt "readline"
config CMD_LN
tristate
prompt "ln"
config CMD_TRUE
tristate
default y
@ -220,6 +224,12 @@ config CMD_DIRNAME
Strip last component of file name and store the result in a
environment variable
config CMD_READLINK
tristate
prompt "readlink"
help
read value of a symbolic link
endmenu
menu "console "

View File

@ -72,3 +72,5 @@ obj-$(CONFIG_CMD_AUTOMOUNT) += automount.o
obj-$(CONFIG_CMD_GLOBAL) += global.o
obj-$(CONFIG_CMD_BASENAME) += basename.o
obj-$(CONFIG_CMD_DIRNAME) += dirname.o
obj-$(CONFIG_CMD_READLINK) += readlink.o
obj-$(CONFIG_CMD_LN) += ln.o

View File

@ -24,20 +24,38 @@
#include <command.h>
#include <libgen.h>
#include <environment.h>
#include <fs.h>
#include <getopt.h>
static int do_dirname(int argc, char *argv[])
{
if (argc != 3)
int opt;
int path_fs = 0;
int len = 0;
while ((opt = getopt(argc, argv, "V")) > 0) {
switch (opt) {
case 'V':
path_fs = 1;
break;
}
}
if (argc < optind + 2)
return COMMAND_ERROR_USAGE;
setenv(argv[2], dirname(argv[1]));
if (path_fs)
len = strlen(get_mounted_path(argv[optind]));
setenv(argv[optind + 1], dirname(argv[optind]) + len);
return 0;
}
BAREBOX_CMD_HELP_START(dirname)
BAREBOX_CMD_HELP_USAGE("dirname NAME DIRNAME\n")
BAREBOX_CMD_HELP_USAGE("dirname [-V] NAME DIRNAME\n")
BAREBOX_CMD_HELP_SHORT("strip last componext of NAME and store into $DIRNAME\n")
BAREBOX_CMD_HELP_SHORT("-V return the path relative to the mountpoint.\n")
BAREBOX_CMD_HELP_END
BAREBOX_CMD_START(dirname)

51
commands/ln.c Normal file
View File

@ -0,0 +1,51 @@
/*
* ln.c - make links between files
*
* Copyright (c) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <common.h>
#include <command.h>
#include <libgen.h>
#include <environment.h>
#include <fs.h>
#include <errno.h>
static int do_ln(int argc, char *argv[])
{
if (argc != 3)
return COMMAND_ERROR_USAGE;
if (symlink(argv[1], argv[2]) < 0) {
perror("ln");
return 1;
}
return 0;
}
BAREBOX_CMD_HELP_START(ln)
BAREBOX_CMD_HELP_USAGE("ln SRC DEST\n")
BAREBOX_CMD_HELP_SHORT("symlink - make a new name for a file\n")
BAREBOX_CMD_HELP_END
BAREBOX_CMD_START(ln)
.cmd = do_ln,
.usage = "symlink - make a new name for a file",
BAREBOX_CMD_HELP(cmd_ln_help)
BAREBOX_CMD_END

View File

@ -29,13 +29,24 @@
#include <getopt.h>
#include <stringlist.h>
static void ls_one(const char *path, struct stat *s)
static void ls_one(const char *path, const char* fullname, struct stat *s)
{
char modestr[11];
unsigned int namelen = strlen(path);
mkmodestr(s->st_mode, modestr);
printf("%s %10llu %*.*s\n", modestr, s->st_size, namelen, namelen, path);
printf("%s %10llu %*.*s", modestr, s->st_size, namelen, namelen, path);
if (S_ISLNK(s->st_mode)) {
char realname[PATH_MAX];
memset(realname, 0, PATH_MAX);
if (readlink(fullname, realname, PATH_MAX - 1) >= 0)
printf(" -> %s", realname);
}
puts("\n");
}
int ls(const char *path, ulong flags)
@ -48,14 +59,14 @@ int ls(const char *path, ulong flags)
string_list_init(&sl);
if (stat(path, &s))
if (lstat(path, &s))
return -errno;
if (flags & LS_SHOWARG && s.st_mode & S_IFDIR)
printf("%s:\n", path);
if (!(s.st_mode & S_IFDIR)) {
ls_one(path, &s);
ls_one(path, path, &s);
return 0;
}
@ -65,12 +76,12 @@ int ls(const char *path, ulong flags)
while ((d = readdir(dir))) {
sprintf(tmp, "%s/%s", path, d->d_name);
if (stat(tmp, &s))
if (lstat(tmp, &s))
goto out;
if (flags & LS_COLUMN)
string_list_add_sorted(&sl, d->d_name);
else
ls_one(d->d_name, &s);
ls_one(d->d_name, tmp, &s);
}
closedir(dir);
@ -97,7 +108,7 @@ int ls(const char *path, ulong flags)
continue;
sprintf(tmp, "%s/%s", path, d->d_name);
if (stat(tmp, &s))
if (lstat(tmp, &s))
goto out;
if (s.st_mode & S_IFDIR) {
char *norm = normalise_path(tmp);
@ -146,7 +157,7 @@ static int do_ls(int argc, char *argv[])
/* first pass: all files */
while (o < argc) {
ret = stat(argv[o], &s);
ret = lstat(argv[o], &s);
if (ret) {
printf("%s: %s: %s\n", argv[0],
argv[o], errno_str());
@ -158,7 +169,7 @@ static int do_ls(int argc, char *argv[])
if (flags & LS_COLUMN)
string_list_add_sorted(&sl, argv[o]);
else
ls_one(argv[o], &s);
ls_one(argv[o], argv[o], &s);
}
o++;
@ -173,7 +184,7 @@ static int do_ls(int argc, char *argv[])
/* second pass: directories */
while (o < argc) {
ret = stat(argv[o], &s);
ret = lstat(argv[o], &s);
if (ret) {
o++;
continue;

80
commands/readlink.c Normal file
View File

@ -0,0 +1,80 @@
/*
* readlink.c - read value of a symbolic link
*
* Copyright (c) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <common.h>
#include <command.h>
#include <libgen.h>
#include <environment.h>
#include <fs.h>
#include <malloc.h>
#include <getopt.h>
static int do_readlink(int argc, char *argv[])
{
char realname[PATH_MAX];
int canonicalize = 0;
int opt;
memset(realname, 0, PATH_MAX);
while ((opt = getopt(argc, argv, "f")) > 0) {
switch (opt) {
case 'f':
canonicalize = 1;
break;
}
}
if (argc < optind + 2)
return COMMAND_ERROR_USAGE;
if (readlink(argv[optind], realname, PATH_MAX - 1) < 0)
goto err;
if (canonicalize) {
char *buf = normalise_link(argv[optind], realname);
if (!buf)
goto err;
setenv(argv[optind + 1], buf);
free(buf);
} else {
setenv(argv[optind + 1], realname);
}
return 0;
err:
setenv(argv[optind + 1], "");
return 1;
}
BAREBOX_CMD_HELP_START(readlink)
BAREBOX_CMD_HELP_USAGE("readlink [-f] FILE REALNAME\n")
BAREBOX_CMD_HELP_SHORT("read value of a symbolic link and store into $REALNAME\n")
BAREBOX_CMD_HELP_SHORT("-f canonicalize by following first symlink");
BAREBOX_CMD_HELP_END
BAREBOX_CMD_START(readlink)
.cmd = do_readlink,
.usage = "read value of a symbolic link",
BAREBOX_CMD_HELP(cmd_readlink_help)
BAREBOX_CMD_END

View File

@ -43,6 +43,7 @@ typedef enum {
OPT_DIRECTORY,
OPT_FILE,
OPT_EXISTS,
OPT_SYMBOLIC_LINK,
OPT_MAX,
} test_opts;
@ -62,6 +63,7 @@ static char *test_options[] = {
[OPT_FILE] = "-f",
[OPT_DIRECTORY] = "-d",
[OPT_EXISTS] = "-e",
[OPT_SYMBOLIC_LINK] = "-L",
};
static int parse_opt(const char *opt)
@ -140,9 +142,10 @@ static int do_test(int argc, char *argv[])
case OPT_FILE:
case OPT_DIRECTORY:
case OPT_EXISTS:
case OPT_SYMBOLIC_LINK:
adv = 2;
if (ap[1] && *ap[1] != ']' && strlen(ap[1])) {
expr = stat(ap[1], &statbuf);
expr = (opt == OPT_SYMBOLIC_LINK ? lstat : stat)(ap[1], &statbuf);
if (expr < 0) {
expr = 0;
break;
@ -160,6 +163,10 @@ static int do_test(int argc, char *argv[])
expr = 1;
break;
}
if (opt == OPT_SYMBOLIC_LINK && S_ISLNK(statbuf.st_mode)) {
expr = 1;
break;
}
}
break;
@ -224,7 +231,7 @@ static const char *test_aliases[] = { "[", NULL};
static const __maybe_unused char cmd_test_help[] =
"Usage: test [OPTIONS]\n"
"options: !, =, !=, -eq, -ne, -ge, -gt, -le, -lt, -o, -a, -z, -n, -d, -e, -f\n"
"options: !, =, !=, -eq, -ne, -ge, -gt, -le, -lt, -o, -a, -z, -n, -d, -e, -f, -L\n"
"see 'man test' on your PC for more information.\n";
static const __maybe_unused char cmd_test_usage[] = "minimal test like /bin/sh";

View File

@ -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

View File

@ -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,35 +76,61 @@ 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;
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));
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);
}
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);
}

229
fs/fs.c
View File

@ -26,6 +26,7 @@
#include <errno.h>
#include <malloc.h>
#include <linux/stat.h>
#include <linux/err.h>
#include <fcntl.h>
#include <xfuncs.h>
#include <init.h>
@ -111,6 +112,61 @@ static int init_cwd(void)
postcore_initcall(init_cwd);
char *normalise_link(const char *pathname, const char *symlink)
{
const char *buf = symlink;
char *path_free, *path;
char *absolute_path;
int point = 0;
int dir = 1;
int len;
if (symlink[0] == '/')
return strdup(symlink);
while (*buf == '.' || *buf == '/') {
if (*buf == '.') {
point++;
} else if (*buf == '/') {
point = 0;
dir++;
}
if (point > 2) {
buf -= 2;
break;
}
buf++;
}
path = path_free = strdup(pathname);
if (!path)
return NULL;
while(dir) {
path = dirname(path);
dir--;
}
len = strlen(buf) + strlen(path) + 1;
if (buf[0] != '/')
len++;
absolute_path = calloc(sizeof(char), len);
if (!absolute_path)
goto out;
strcat(absolute_path, path);
if (buf[0] != '/')
strcat(absolute_path, "/");
strcat(absolute_path, buf);
out:
free(path_free);
return absolute_path;
}
char *normalise_path(const char *pathname)
{
char *path = xzalloc(strlen(pathname) + strlen(cwd) + 2);
@ -187,6 +243,15 @@ static struct fs_device_d *get_fsdevice_by_path(const char *path)
return fs_dev_root;
}
char *get_mounted_path(const char *path)
{
struct fs_device_d *fdev;
fdev = get_fsdevice_by_path(path);
return fdev->path;
}
static FILE files[MAX_FILES];
static FILE *get_file(void)
@ -392,7 +457,7 @@ static int path_check_prereq(const char *path, unsigned int flags)
unsigned int m;
int ret = 0;
if (stat(path, &s)) {
if (lstat(path, &s)) {
if (flags & S_UB_DOES_NOT_EXIST)
goto out;
ret = -ENOENT;
@ -434,7 +499,7 @@ static int parent_check_directory(const char *path)
int ret;
char *dir = dirname(xstrdup(path));
ret = stat(dir, &s);
ret = lstat(dir, &s);
free(dir);
@ -512,18 +577,61 @@ out:
}
EXPORT_SYMBOL(unlink);
static char *realfile(const char *pathname, struct stat *s)
{
char *path = normalise_path(pathname);
int ret;
ret = lstat(path, s);
if (ret)
goto out;
if (S_ISLNK(s->st_mode)) {
char tmp[PATH_MAX];
char *new_path;
memset(tmp, 0, PATH_MAX);
ret = readlink(path, tmp, PATH_MAX - 1);
if (ret < 0)
goto out;
new_path = normalise_link(path, tmp);
free(path);
if (!new_path)
return ERR_PTR(-ENOMEM);
path = new_path;
ret = lstat(path, s);
}
if (!ret)
return path;
out:
free(path);
return ERR_PTR(ret);
}
int open(const char *pathname, int flags, ...)
{
struct fs_device_d *fsdev;
struct fs_driver_d *fsdrv;
FILE *f;
int exist_err;
int exist_err = 0;
struct stat s;
char *path = normalise_path(pathname);
char *freep = path;
char *path;
char *freep;
int ret;
exist_err = stat(path, &s);
path = realfile(pathname, &s);
if (IS_ERR(path)) {
exist_err = PTR_ERR(path);
path = normalise_path(pathname);
}
freep = path;
if (!exist_err && S_ISDIR(s.st_mode)) {
ret = -EISDIR;
@ -890,6 +998,94 @@ int close(int fd)
}
EXPORT_SYMBOL(close);
int readlink(const char *pathname, char *buf, size_t bufsiz)
{
struct fs_driver_d *fsdrv;
struct fs_device_d *fsdev;
char *p = normalise_path(pathname);
char *freep = p;
int ret;
ret = path_check_prereq(pathname, S_IFLNK);
if (ret)
goto out;
fsdev = get_fs_device_and_root_path(&p);
if (!fsdev) {
ret = -ENODEV;
goto out;
}
fsdrv = fsdev->driver;
if (fsdrv->readlink)
ret = fsdrv->readlink(&fsdev->dev, p, buf, bufsiz);
else
ret = -ENOSYS;
if (ret)
goto out;
out:
free(freep);
if (ret)
errno = -ret;
return ret;
}
EXPORT_SYMBOL(readlink);
int symlink(const char *pathname, const char *newpath)
{
struct fs_driver_d *fsdrv;
struct fs_device_d *fsdev;
char *p;
char *freep = normalise_path(pathname);
int ret;
struct stat s;
if (!freep)
return -ENOMEM;
if (!stat(freep, &s) && S_ISDIR(s.st_mode)) {
ret = -ENOSYS;
goto out;
}
free(freep);
freep = p = normalise_path(newpath);
if (!p)
return -ENOMEM;
ret = lstat(p, &s);
if (!ret) {
ret = -EEXIST;
goto out;
}
fsdev = get_fs_device_and_root_path(&p);
if (!fsdev) {
ret = -ENODEV;
goto out;
}
fsdrv = fsdev->driver;
if (fsdrv->symlink) {
ret = fsdrv->symlink(&fsdev->dev, pathname, p);
} else {
ret = -EPERM;
}
out:
free(freep);
if (ret)
errno = -ret;
return ret;
}
EXPORT_SYMBOL(symlink);
static int fs_match(struct device_d *dev, struct driver_d *drv)
{
return strcmp(dev->name, drv->name) ? -1 : 0;
@ -1159,6 +1355,19 @@ int closedir(DIR *dir)
EXPORT_SYMBOL(closedir);
int stat(const char *filename, struct stat *s)
{
char *f;
f = realfile(filename, s);
if (IS_ERR(f))
return PTR_ERR(f);
free(f);
return 0;
}
EXPORT_SYMBOL(stat);
int lstat(const char *filename, struct stat *s)
{
struct device_d *dev;
struct fs_driver_d *fsdrv;
@ -1197,7 +1406,7 @@ out:
return ret;
}
EXPORT_SYMBOL(stat);
EXPORT_SYMBOL(lstat);
int mkdir (const char *pathname, mode_t mode)
{
@ -1244,6 +1453,12 @@ int rmdir (const char *pathname)
char *freep = p;
int ret;
ret = path_check_prereq(pathname, S_IFLNK);
if (!ret) {
ret = -ENOTDIR;
goto out;
}
ret = path_check_prereq(pathname, S_IFDIR | S_UB_IS_EMPTY);
if (ret)
goto out;

View File

@ -605,34 +605,6 @@ static int nfs_read_req(struct file_priv *priv, int offset, int readlen)
return 0;
}
#if 0
static int nfs_readlink_reply(unsigned char *pkt, unsigned len)
{
uint32_t *data;
char *path;
int rlen;
// int ret;
data = (uint32_t *)(pkt + sizeof(struct rpc_reply));
data++;
rlen = ntohl(net_read_uint32(data)); /* new path length */
data++;
path = (char *)data;
if (*path != '/') {
strcat(nfs_path, "/");
strncat(nfs_path, path, rlen);
} else {
memcpy(nfs_path, path, rlen);
nfs_path[rlen] = 0;
}
return 0;
}
#endif
static void nfs_handler(void *ctx, char *packet, unsigned len)
{
char *pkt = net_eth_to_udp_payload(packet);
@ -742,6 +714,63 @@ static struct file_priv *nfs_do_stat(struct device_d *dev, const char *filename,
return priv;
}
static int nfs_readlink_req(struct file_priv *priv, char* buf, size_t size)
{
uint32_t data[1024];
uint32_t *p;
int len;
int ret;
char *path;
uint32_t *filedata;
p = &(data[0]);
p = rpc_add_credentials(p);
memcpy(p, priv->filefh, NFS_FHSIZE);
p += (NFS_FHSIZE / 4);
len = p - &(data[0]);
ret = rpc_req(priv->npriv, PROG_NFS, NFS_READLINK, data, len);
if (ret)
return ret;
filedata = nfs_packet + sizeof(struct rpc_reply);
filedata++;
len = ntohl(net_read_uint32(filedata)); /* new path length */
filedata++;
path = (char *)filedata;
if (len > size)
len = size;
memcpy(buf, path, len);
return 0;
}
static int nfs_readlink(struct device_d *dev, const char *filename,
char *realname, size_t size)
{
struct file_priv *priv;
int ret;
struct stat s;
priv = nfs_do_stat(dev, filename, &s);
if (IS_ERR(priv))
return PTR_ERR(priv);
ret = nfs_readlink_req(priv, realname, size);
if (ret) {
nfs_do_close(priv);
return ret;
}
return 0;
}
static int nfs_open(struct device_d *dev, FILE *file, const char *filename)
{
struct file_priv *priv;
@ -1039,6 +1068,7 @@ static struct fs_driver_d nfs_driver = {
.rmdir = nfs_rmdir,
.write = nfs_write,
.truncate = nfs_truncate,
.readlink = nfs_readlink,
.flags = 0,
.drv = {
.probe = nfs_probe,

View File

@ -42,6 +42,7 @@ struct ramfs_inode {
struct ramfs_inode *parent;
struct ramfs_inode *next;
struct ramfs_inode *child;
char *symlink;
ulong mode;
struct handle_d *handle;
@ -176,6 +177,7 @@ static void ramfs_put_inode(struct ramfs_inode *node)
data = tmp;
}
free(node->symlink);
free(node->name);
free(node);
}
@ -212,18 +214,38 @@ static struct ramfs_inode* node_insert(struct ramfs_inode *parent_node, const ch
/* ---------------------------------------------------------------*/
static int ramfs_create(struct device_d *dev, const char *pathname, mode_t mode)
static int __ramfs_create(struct device_d *dev, const char *pathname,
mode_t mode, const char *symlink)
{
struct ramfs_priv *priv = dev->priv;
struct ramfs_inode *node;
char *file;
char *__symlink = NULL;
node = rlookup_parent(priv, pathname, &file);
if (node) {
node_insert(node, file, mode);
return 0;
if (!node)
return -ENOENT;
if (symlink) {
__symlink = strdup(symlink);
if (!__symlink)
return -ENOMEM;
}
return -ENOENT;
node = node_insert(node, file, mode);
if (!node) {
free(__symlink);
return -ENOMEM;
}
node->symlink = __symlink;
return 0;
}
static int ramfs_create(struct device_d *dev, const char *pathname, mode_t mode)
{
return __ramfs_create(dev, pathname, mode, NULL);
}
static int ramfs_unlink(struct device_d *dev, const char *pathname)
@ -532,12 +554,37 @@ static int ramfs_stat(struct device_d *dev, const char *filename, struct stat *s
if (!node)
return -ENOENT;
s->st_size = node->size;
s->st_size = node->symlink ? strlen(node->symlink) : node->size;
s->st_mode = node->mode;
return 0;
}
static int ramfs_symlink(struct device_d *dev, const char *pathname,
const char *newpath)
{
mode_t mode = S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO;
return __ramfs_create(dev, newpath, mode, pathname);
}
static int ramfs_readlink(struct device_d *dev, const char *pathname,
char *buf, size_t bufsiz)
{
struct ramfs_priv *priv = dev->priv;
struct ramfs_inode *node = rlookup(priv, pathname);
int len;
if (!node || !node->symlink)
return -ENOENT;
len = min(bufsiz, strlen(node->symlink));
memcpy(buf, node->symlink, len);
return 0;
}
static int ramfs_probe(struct device_d *dev)
{
struct ramfs_inode *n;
@ -584,6 +631,8 @@ static struct fs_driver_d ramfs_driver = {
.readdir = ramfs_readdir,
.closedir = ramfs_closedir,
.stat = ramfs_stat,
.symlink = ramfs_symlink,
.readlink = ramfs_readlink,
.flags = FS_DRIVER_NO_DEV,
.drv = {
.probe = ramfs_probe,

View File

@ -5,15 +5,19 @@
#include <asm/byteorder.h>
#endif
#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
@ -21,6 +25,11 @@ struct envfs_inode {
*/
};
struct envfs_inode_end {
uint32_t magic; /* ENVFS_INODE_END_MAGIC */
uint32_t mode; /* file mode */
};
/*
* Superblock information at the beginning of the FS.
*/
@ -29,8 +38,10 @@ struct envfs_super {
uint32_t priority;
uint32_t crc; /* crc for the data */
uint32_t size; /* size of data */
uint8_t major; /* major */
uint8_t minor; /* minor */
uint16_t future; /* reserved for future use */
uint32_t flags; /* feature flags */
uint32_t future; /* reserved for future use */
uint32_t sb_crc; /* crc for the superblock */
};

View File

@ -51,6 +51,11 @@ struct fs_driver_d {
/* Truncate a file to given size */
int (*truncate)(struct device_d *dev, FILE *f, ulong size);
int (*symlink)(struct device_d *dev, const char *pathname,
const char *newpath);
int (*readlink)(struct device_d *dev, const char *pathname, char *name,
size_t size);
int (*open)(struct device_d *dev, FILE *f, const char *pathname);
int (*close)(struct device_d *dev, FILE *f);
int (*read)(struct device_d *dev, FILE *f, void *buf, size_t size);
@ -106,6 +111,7 @@ int creat(const char *pathname, mode_t mode);
int unlink(const char *pathname);
int close(int fd);
int flush(int fd);
int lstat(const char *filename, struct stat *s);
int stat(const char *filename, struct stat *s);
int read(int fd, void *buf, size_t count);
int ioctl(int fd, int request, void *buf);
@ -129,6 +135,9 @@ DIR *opendir(const char *pathname);
struct dirent *readdir(DIR *dir);
int closedir(DIR *dir);
int symlink(const char *pathname, const char *newpath);
int readlink(const char *path, char *buf, size_t bufsiz);
int mount (const char *device, const char *fsname, const char *path);
int umount(const char *pathname);
@ -162,6 +171,9 @@ void *read_file(const char *filename, size_t *size);
* of "..", "." and double slashes. The returned string must be freed wit free().
*/
char *normalise_path(const char *path);
char *normalise_link(const char *pathname, const char* symlink);
char *get_mounted_path(const char *path);
/* Register a new filesystem driver */
int register_fs_driver(struct fs_driver_d *fsdrv);

View File

@ -14,7 +14,7 @@ char* last_char_is(const char *s, int c);
enum {
ACTION_RECURSE = (1 << 0),
/* ACTION_FOLLOWLINKS = (1 << 1), - unused */
ACTION_FOLLOWLINKS = (1 << 1),
ACTION_DEPTHFIRST = (1 << 2),
/*ACTION_REVERSE = (1 << 3), - unused */
};

View File

@ -54,14 +54,19 @@ int recursive_action(const char *fileName,
const unsigned depth)
{
struct stat statbuf;
unsigned follow;
int status;
DIR *dir;
struct dirent *next;
if (!fileAction) fileAction = true_action;
if (!dirAction) dirAction = true_action;
status = stat(fileName, &statbuf);
follow = ACTION_FOLLOWLINKS;
if (depth == 0)
follow = ACTION_FOLLOWLINKS;
follow &= flags;
status = (follow ? stat : lstat)(fileName, &statbuf);
if (status < 0) {
#ifdef DEBUG_RECURS_ACTION
bb_error_msg("status=%d followLinks=%d TRUE=%d",

View File

@ -73,7 +73,7 @@ char* last_char_is(const char *s, int c)
enum {
ACTION_RECURSE = (1 << 0),
/* ACTION_FOLLOWLINKS = (1 << 1), - unused */
ACTION_FOLLOWLINKS = (1 << 1),
ACTION_DEPTHFIRST = (1 << 2),
/*ACTION_REVERSE = (1 << 3), - unused */
};