Merge branch 'for-next/link'
This commit is contained in:
commit
e5a927883e
1
MAKEALL
1
MAKEALL
|
@ -264,3 +264,4 @@ then
|
||||||
else
|
else
|
||||||
do_build_target ${ARCH} $1
|
do_build_target ${ARCH} $1
|
||||||
fi
|
fi
|
||||||
|
exit $nb_errors
|
||||||
|
|
|
@ -57,6 +57,10 @@ config CMD_READLINE
|
||||||
tristate
|
tristate
|
||||||
prompt "readline"
|
prompt "readline"
|
||||||
|
|
||||||
|
config CMD_LN
|
||||||
|
tristate
|
||||||
|
prompt "ln"
|
||||||
|
|
||||||
config CMD_TRUE
|
config CMD_TRUE
|
||||||
tristate
|
tristate
|
||||||
default y
|
default y
|
||||||
|
@ -220,6 +224,12 @@ config CMD_DIRNAME
|
||||||
Strip last component of file name and store the result in a
|
Strip last component of file name and store the result in a
|
||||||
environment variable
|
environment variable
|
||||||
|
|
||||||
|
config CMD_READLINK
|
||||||
|
tristate
|
||||||
|
prompt "readlink"
|
||||||
|
help
|
||||||
|
read value of a symbolic link
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
|
||||||
menu "console "
|
menu "console "
|
||||||
|
|
|
@ -72,3 +72,5 @@ obj-$(CONFIG_CMD_AUTOMOUNT) += automount.o
|
||||||
obj-$(CONFIG_CMD_GLOBAL) += global.o
|
obj-$(CONFIG_CMD_GLOBAL) += global.o
|
||||||
obj-$(CONFIG_CMD_BASENAME) += basename.o
|
obj-$(CONFIG_CMD_BASENAME) += basename.o
|
||||||
obj-$(CONFIG_CMD_DIRNAME) += dirname.o
|
obj-$(CONFIG_CMD_DIRNAME) += dirname.o
|
||||||
|
obj-$(CONFIG_CMD_READLINK) += readlink.o
|
||||||
|
obj-$(CONFIG_CMD_LN) += ln.o
|
||||||
|
|
|
@ -24,20 +24,38 @@
|
||||||
#include <command.h>
|
#include <command.h>
|
||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
#include <environment.h>
|
#include <environment.h>
|
||||||
|
#include <fs.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
|
||||||
static int do_dirname(int argc, char *argv[])
|
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;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
BAREBOX_CMD_HELP_START(dirname)
|
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("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_HELP_END
|
||||||
|
|
||||||
BAREBOX_CMD_START(dirname)
|
BAREBOX_CMD_START(dirname)
|
||||||
|
|
|
@ -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
|
|
@ -29,13 +29,24 @@
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <stringlist.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];
|
char modestr[11];
|
||||||
unsigned int namelen = strlen(path);
|
unsigned int namelen = strlen(path);
|
||||||
|
|
||||||
mkmodestr(s->st_mode, modestr);
|
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)
|
int ls(const char *path, ulong flags)
|
||||||
|
@ -48,14 +59,14 @@ int ls(const char *path, ulong flags)
|
||||||
|
|
||||||
string_list_init(&sl);
|
string_list_init(&sl);
|
||||||
|
|
||||||
if (stat(path, &s))
|
if (lstat(path, &s))
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
if (flags & LS_SHOWARG && s.st_mode & S_IFDIR)
|
if (flags & LS_SHOWARG && s.st_mode & S_IFDIR)
|
||||||
printf("%s:\n", path);
|
printf("%s:\n", path);
|
||||||
|
|
||||||
if (!(s.st_mode & S_IFDIR)) {
|
if (!(s.st_mode & S_IFDIR)) {
|
||||||
ls_one(path, &s);
|
ls_one(path, path, &s);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,12 +76,12 @@ int ls(const char *path, ulong flags)
|
||||||
|
|
||||||
while ((d = readdir(dir))) {
|
while ((d = readdir(dir))) {
|
||||||
sprintf(tmp, "%s/%s", path, d->d_name);
|
sprintf(tmp, "%s/%s", path, d->d_name);
|
||||||
if (stat(tmp, &s))
|
if (lstat(tmp, &s))
|
||||||
goto out;
|
goto out;
|
||||||
if (flags & LS_COLUMN)
|
if (flags & LS_COLUMN)
|
||||||
string_list_add_sorted(&sl, d->d_name);
|
string_list_add_sorted(&sl, d->d_name);
|
||||||
else
|
else
|
||||||
ls_one(d->d_name, &s);
|
ls_one(d->d_name, tmp, &s);
|
||||||
}
|
}
|
||||||
|
|
||||||
closedir(dir);
|
closedir(dir);
|
||||||
|
@ -97,7 +108,7 @@ int ls(const char *path, ulong flags)
|
||||||
continue;
|
continue;
|
||||||
sprintf(tmp, "%s/%s", path, d->d_name);
|
sprintf(tmp, "%s/%s", path, d->d_name);
|
||||||
|
|
||||||
if (stat(tmp, &s))
|
if (lstat(tmp, &s))
|
||||||
goto out;
|
goto out;
|
||||||
if (s.st_mode & S_IFDIR) {
|
if (s.st_mode & S_IFDIR) {
|
||||||
char *norm = normalise_path(tmp);
|
char *norm = normalise_path(tmp);
|
||||||
|
@ -146,7 +157,7 @@ static int do_ls(int argc, char *argv[])
|
||||||
|
|
||||||
/* first pass: all files */
|
/* first pass: all files */
|
||||||
while (o < argc) {
|
while (o < argc) {
|
||||||
ret = stat(argv[o], &s);
|
ret = lstat(argv[o], &s);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
printf("%s: %s: %s\n", argv[0],
|
printf("%s: %s: %s\n", argv[0],
|
||||||
argv[o], errno_str());
|
argv[o], errno_str());
|
||||||
|
@ -158,7 +169,7 @@ static int do_ls(int argc, char *argv[])
|
||||||
if (flags & LS_COLUMN)
|
if (flags & LS_COLUMN)
|
||||||
string_list_add_sorted(&sl, argv[o]);
|
string_list_add_sorted(&sl, argv[o]);
|
||||||
else
|
else
|
||||||
ls_one(argv[o], &s);
|
ls_one(argv[o], argv[o], &s);
|
||||||
}
|
}
|
||||||
|
|
||||||
o++;
|
o++;
|
||||||
|
@ -173,7 +184,7 @@ static int do_ls(int argc, char *argv[])
|
||||||
|
|
||||||
/* second pass: directories */
|
/* second pass: directories */
|
||||||
while (o < argc) {
|
while (o < argc) {
|
||||||
ret = stat(argv[o], &s);
|
ret = lstat(argv[o], &s);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
o++;
|
o++;
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -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
|
|
@ -43,6 +43,7 @@ typedef enum {
|
||||||
OPT_DIRECTORY,
|
OPT_DIRECTORY,
|
||||||
OPT_FILE,
|
OPT_FILE,
|
||||||
OPT_EXISTS,
|
OPT_EXISTS,
|
||||||
|
OPT_SYMBOLIC_LINK,
|
||||||
OPT_MAX,
|
OPT_MAX,
|
||||||
} test_opts;
|
} test_opts;
|
||||||
|
|
||||||
|
@ -62,6 +63,7 @@ static char *test_options[] = {
|
||||||
[OPT_FILE] = "-f",
|
[OPT_FILE] = "-f",
|
||||||
[OPT_DIRECTORY] = "-d",
|
[OPT_DIRECTORY] = "-d",
|
||||||
[OPT_EXISTS] = "-e",
|
[OPT_EXISTS] = "-e",
|
||||||
|
[OPT_SYMBOLIC_LINK] = "-L",
|
||||||
};
|
};
|
||||||
|
|
||||||
static int parse_opt(const char *opt)
|
static int parse_opt(const char *opt)
|
||||||
|
@ -140,9 +142,10 @@ static int do_test(int argc, char *argv[])
|
||||||
case OPT_FILE:
|
case OPT_FILE:
|
||||||
case OPT_DIRECTORY:
|
case OPT_DIRECTORY:
|
||||||
case OPT_EXISTS:
|
case OPT_EXISTS:
|
||||||
|
case OPT_SYMBOLIC_LINK:
|
||||||
adv = 2;
|
adv = 2;
|
||||||
if (ap[1] && *ap[1] != ']' && strlen(ap[1])) {
|
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) {
|
if (expr < 0) {
|
||||||
expr = 0;
|
expr = 0;
|
||||||
break;
|
break;
|
||||||
|
@ -160,6 +163,10 @@ static int do_test(int argc, char *argv[])
|
||||||
expr = 1;
|
expr = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (opt == OPT_SYMBOLIC_LINK && S_ISLNK(statbuf.st_mode)) {
|
||||||
|
expr = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -224,7 +231,7 @@ static const char *test_aliases[] = { "[", NULL};
|
||||||
|
|
||||||
static const __maybe_unused char cmd_test_help[] =
|
static const __maybe_unused char cmd_test_help[] =
|
||||||
"Usage: test [OPTIONS]\n"
|
"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";
|
"see 'man test' on your PC for more information.\n";
|
||||||
|
|
||||||
static const __maybe_unused char cmd_test_usage[] = "minimal test like /bin/sh";
|
static const __maybe_unused char cmd_test_usage[] = "minimal test like /bin/sh";
|
||||||
|
|
|
@ -58,7 +58,7 @@ ifneq ($(CONFIG_DEFAULT_ENVIRONMENT_PATH),"")
|
||||||
DEFAULT_ENVIRONMENT_PATH += $(CONFIG_DEFAULT_ENVIRONMENT_PATH)
|
DEFAULT_ENVIRONMENT_PATH += $(CONFIG_DEFAULT_ENVIRONMENT_PATH)
|
||||||
endif
|
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
|
endif # ifdef CONFIG_DEFAULT_ENVIRONMENT
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,21 @@ int file_size_action(const char *filename, struct stat *statbuf,
|
||||||
|
|
||||||
data->writep += sizeof(struct envfs_inode);
|
data->writep += sizeof(struct envfs_inode);
|
||||||
data->writep += PAD4(strlen(filename) + 1 - strlen(data->base));
|
data->writep += PAD4(strlen(filename) + 1 - strlen(data->base));
|
||||||
|
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);
|
data->writep += PAD4(statbuf->st_size);
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,21 +76,46 @@ int file_save_action(const char *filename, struct stat *statbuf,
|
||||||
{
|
{
|
||||||
struct action_data *data = userdata;
|
struct action_data *data = userdata;
|
||||||
struct envfs_inode *inode;
|
struct envfs_inode *inode;
|
||||||
|
struct envfs_inode_end *inode_end;
|
||||||
int fd;
|
int fd;
|
||||||
int namelen = strlen(filename) + 1 - strlen(data->base);
|
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 = (struct envfs_inode*)data->writep;
|
||||||
inode->magic = ENVFS_32(ENVFS_INODE_MAGIC);
|
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);
|
data->writep += sizeof(struct envfs_inode);
|
||||||
|
|
||||||
strcpy(data->writep, filename + strlen(data->base));
|
strcpy(data->writep, filename + strlen(data->base));
|
||||||
data->writep += PAD4(namelen);
|
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);
|
||||||
|
|
||||||
|
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);
|
fd = open(filename, O_RDONLY);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
printf("Open %s %s\n", filename, errno_str());
|
printf("Open %s %s\n", filename, errno_str());
|
||||||
|
@ -90,6 +129,7 @@ int file_save_action(const char *filename, struct stat *statbuf,
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
data->writep += PAD4(statbuf->st_size);
|
data->writep += PAD4(statbuf->st_size);
|
||||||
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -125,6 +165,8 @@ int envfs_save(char *filename, char *dirname)
|
||||||
|
|
||||||
super = (struct envfs_super *)buf;
|
super = (struct envfs_super *)buf;
|
||||||
super->magic = ENVFS_32(ENVFS_MAGIC);
|
super->magic = ENVFS_32(ENVFS_MAGIC);
|
||||||
|
super->major = ENVFS_MAJOR;
|
||||||
|
super->minor = ENVFS_MINOR;
|
||||||
super->size = ENVFS_32(size);
|
super->size = ENVFS_32(size);
|
||||||
|
|
||||||
/* second pass: copy files to buffer */
|
/* second pass: copy files to buffer */
|
||||||
|
@ -174,8 +216,13 @@ int envfs_load(char *filename, char *dir)
|
||||||
int envfd;
|
int envfd;
|
||||||
int fd, ret = 0;
|
int fd, ret = 0;
|
||||||
char *str, *tmp;
|
char *str, *tmp;
|
||||||
int namelen_full;
|
int headerlen_full;
|
||||||
unsigned long size;
|
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);
|
envfd = open(filename, O_RDONLY);
|
||||||
if (envfd < 0) {
|
if (envfd < 0) {
|
||||||
|
@ -221,11 +268,18 @@ int envfs_load(char *filename, char *dir)
|
||||||
goto out;
|
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) {
|
while (size) {
|
||||||
struct envfs_inode *inode;
|
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;
|
inode = (struct envfs_inode *)buf;
|
||||||
|
buf += sizeof(struct envfs_inode);
|
||||||
|
|
||||||
if (ENVFS_32(inode->magic) != ENVFS_INODE_MAGIC) {
|
if (ENVFS_32(inode->magic) != ENVFS_INODE_MAGIC) {
|
||||||
printf("envfs: wrong magic on %s\n", filename);
|
printf("envfs: wrong magic on %s\n", filename);
|
||||||
|
@ -233,16 +287,38 @@ int envfs_load(char *filename, char *dir)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
inode_size = ENVFS_32(inode->size);
|
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,
|
debug("loading %s size %d namelen %d headerlen %d\n", inode->data,
|
||||||
inode_size, inode_namelen);
|
inode_size, namelen, inode_headerlen);
|
||||||
|
|
||||||
str = concat_path_file(dir, inode->data);
|
str = concat_path_file(dir, inode->data);
|
||||||
tmp = strdup(str);
|
tmp = strdup(str);
|
||||||
make_directory(dirname(tmp));
|
make_directory(dirname(tmp));
|
||||||
free(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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
fd = open(str, O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
||||||
free(str);
|
free(str);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
|
@ -251,9 +327,7 @@ int envfs_load(char *filename, char *dir)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
namelen_full = PAD4(inode_namelen);
|
ret = write(fd, buf, inode_size);
|
||||||
ret = write(fd, buf + namelen_full + sizeof(struct envfs_inode),
|
|
||||||
inode_size);
|
|
||||||
if (ret < inode_size) {
|
if (ret < inode_size) {
|
||||||
perror("write");
|
perror("write");
|
||||||
ret = -errno;
|
ret = -errno;
|
||||||
|
@ -261,10 +335,10 @@ int envfs_load(char *filename, char *dir)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
close(fd);
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
buf += PAD4(inode_namelen) + PAD4(inode_size) +
|
buf += PAD4(inode_size);
|
||||||
sizeof(struct envfs_inode);
|
size -= headerlen_full + PAD4(inode_size) +
|
||||||
size -= PAD4(inode_namelen) + PAD4(inode_size) +
|
|
||||||
sizeof(struct envfs_inode);
|
sizeof(struct envfs_inode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
229
fs/fs.c
229
fs/fs.c
|
@ -26,6 +26,7 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include <linux/stat.h>
|
#include <linux/stat.h>
|
||||||
|
#include <linux/err.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <xfuncs.h>
|
#include <xfuncs.h>
|
||||||
#include <init.h>
|
#include <init.h>
|
||||||
|
@ -111,6 +112,61 @@ static int init_cwd(void)
|
||||||
|
|
||||||
postcore_initcall(init_cwd);
|
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 *normalise_path(const char *pathname)
|
||||||
{
|
{
|
||||||
char *path = xzalloc(strlen(pathname) + strlen(cwd) + 2);
|
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;
|
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 files[MAX_FILES];
|
||||||
|
|
||||||
static FILE *get_file(void)
|
static FILE *get_file(void)
|
||||||
|
@ -392,7 +457,7 @@ static int path_check_prereq(const char *path, unsigned int flags)
|
||||||
unsigned int m;
|
unsigned int m;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (stat(path, &s)) {
|
if (lstat(path, &s)) {
|
||||||
if (flags & S_UB_DOES_NOT_EXIST)
|
if (flags & S_UB_DOES_NOT_EXIST)
|
||||||
goto out;
|
goto out;
|
||||||
ret = -ENOENT;
|
ret = -ENOENT;
|
||||||
|
@ -434,7 +499,7 @@ static int parent_check_directory(const char *path)
|
||||||
int ret;
|
int ret;
|
||||||
char *dir = dirname(xstrdup(path));
|
char *dir = dirname(xstrdup(path));
|
||||||
|
|
||||||
ret = stat(dir, &s);
|
ret = lstat(dir, &s);
|
||||||
|
|
||||||
free(dir);
|
free(dir);
|
||||||
|
|
||||||
|
@ -512,18 +577,61 @@ out:
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(unlink);
|
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, ...)
|
int open(const char *pathname, int flags, ...)
|
||||||
{
|
{
|
||||||
struct fs_device_d *fsdev;
|
struct fs_device_d *fsdev;
|
||||||
struct fs_driver_d *fsdrv;
|
struct fs_driver_d *fsdrv;
|
||||||
FILE *f;
|
FILE *f;
|
||||||
int exist_err;
|
int exist_err = 0;
|
||||||
struct stat s;
|
struct stat s;
|
||||||
char *path = normalise_path(pathname);
|
char *path;
|
||||||
char *freep = path;
|
char *freep;
|
||||||
int ret;
|
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)) {
|
if (!exist_err && S_ISDIR(s.st_mode)) {
|
||||||
ret = -EISDIR;
|
ret = -EISDIR;
|
||||||
|
@ -890,6 +998,94 @@ int close(int fd)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(close);
|
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)
|
static int fs_match(struct device_d *dev, struct driver_d *drv)
|
||||||
{
|
{
|
||||||
return strcmp(dev->name, drv->name) ? -1 : 0;
|
return strcmp(dev->name, drv->name) ? -1 : 0;
|
||||||
|
@ -1159,6 +1355,19 @@ int closedir(DIR *dir)
|
||||||
EXPORT_SYMBOL(closedir);
|
EXPORT_SYMBOL(closedir);
|
||||||
|
|
||||||
int stat(const char *filename, struct stat *s)
|
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 device_d *dev;
|
||||||
struct fs_driver_d *fsdrv;
|
struct fs_driver_d *fsdrv;
|
||||||
|
@ -1197,7 +1406,7 @@ out:
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(stat);
|
EXPORT_SYMBOL(lstat);
|
||||||
|
|
||||||
int mkdir (const char *pathname, mode_t mode)
|
int mkdir (const char *pathname, mode_t mode)
|
||||||
{
|
{
|
||||||
|
@ -1244,6 +1453,12 @@ int rmdir (const char *pathname)
|
||||||
char *freep = p;
|
char *freep = p;
|
||||||
int ret;
|
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);
|
ret = path_check_prereq(pathname, S_IFDIR | S_UB_IS_EMPTY);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
86
fs/nfs.c
86
fs/nfs.c
|
@ -605,34 +605,6 @@ static int nfs_read_req(struct file_priv *priv, int offset, int readlen)
|
||||||
return 0;
|
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)
|
static void nfs_handler(void *ctx, char *packet, unsigned len)
|
||||||
{
|
{
|
||||||
char *pkt = net_eth_to_udp_payload(packet);
|
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;
|
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)
|
static int nfs_open(struct device_d *dev, FILE *file, const char *filename)
|
||||||
{
|
{
|
||||||
struct file_priv *priv;
|
struct file_priv *priv;
|
||||||
|
@ -1039,6 +1068,7 @@ static struct fs_driver_d nfs_driver = {
|
||||||
.rmdir = nfs_rmdir,
|
.rmdir = nfs_rmdir,
|
||||||
.write = nfs_write,
|
.write = nfs_write,
|
||||||
.truncate = nfs_truncate,
|
.truncate = nfs_truncate,
|
||||||
|
.readlink = nfs_readlink,
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.drv = {
|
.drv = {
|
||||||
.probe = nfs_probe,
|
.probe = nfs_probe,
|
||||||
|
|
59
fs/ramfs.c
59
fs/ramfs.c
|
@ -42,6 +42,7 @@ struct ramfs_inode {
|
||||||
struct ramfs_inode *parent;
|
struct ramfs_inode *parent;
|
||||||
struct ramfs_inode *next;
|
struct ramfs_inode *next;
|
||||||
struct ramfs_inode *child;
|
struct ramfs_inode *child;
|
||||||
|
char *symlink;
|
||||||
ulong mode;
|
ulong mode;
|
||||||
|
|
||||||
struct handle_d *handle;
|
struct handle_d *handle;
|
||||||
|
@ -176,6 +177,7 @@ static void ramfs_put_inode(struct ramfs_inode *node)
|
||||||
data = tmp;
|
data = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(node->symlink);
|
||||||
free(node->name);
|
free(node->name);
|
||||||
free(node);
|
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_priv *priv = dev->priv;
|
||||||
struct ramfs_inode *node;
|
struct ramfs_inode *node;
|
||||||
char *file;
|
char *file;
|
||||||
|
char *__symlink = NULL;
|
||||||
|
|
||||||
node = rlookup_parent(priv, pathname, &file);
|
node = rlookup_parent(priv, pathname, &file);
|
||||||
if (node) {
|
if (!node)
|
||||||
node_insert(node, file, mode);
|
return -ENOENT;
|
||||||
|
|
||||||
|
if (symlink) {
|
||||||
|
__symlink = strdup(symlink);
|
||||||
|
if (!__symlink)
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
node = node_insert(node, file, mode);
|
||||||
|
if (!node) {
|
||||||
|
free(__symlink);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
node->symlink = __symlink;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return -ENOENT;
|
|
||||||
|
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)
|
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)
|
if (!node)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
||||||
s->st_size = node->size;
|
s->st_size = node->symlink ? strlen(node->symlink) : node->size;
|
||||||
s->st_mode = node->mode;
|
s->st_mode = node->mode;
|
||||||
|
|
||||||
return 0;
|
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)
|
static int ramfs_probe(struct device_d *dev)
|
||||||
{
|
{
|
||||||
struct ramfs_inode *n;
|
struct ramfs_inode *n;
|
||||||
|
@ -584,6 +631,8 @@ static struct fs_driver_d ramfs_driver = {
|
||||||
.readdir = ramfs_readdir,
|
.readdir = ramfs_readdir,
|
||||||
.closedir = ramfs_closedir,
|
.closedir = ramfs_closedir,
|
||||||
.stat = ramfs_stat,
|
.stat = ramfs_stat,
|
||||||
|
.symlink = ramfs_symlink,
|
||||||
|
.readlink = ramfs_readlink,
|
||||||
.flags = FS_DRIVER_NO_DEV,
|
.flags = FS_DRIVER_NO_DEV,
|
||||||
.drv = {
|
.drv = {
|
||||||
.probe = ramfs_probe,
|
.probe = ramfs_probe,
|
||||||
|
|
|
@ -5,15 +5,19 @@
|
||||||
#include <asm/byteorder.h>
|
#include <asm/byteorder.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define ENVFS_MAJOR 1
|
||||||
|
#define ENVFS_MINOR 0
|
||||||
|
|
||||||
#define ENVFS_MAGIC 0x798fba79 /* some random number */
|
#define ENVFS_MAGIC 0x798fba79 /* some random number */
|
||||||
#define ENVFS_INODE_MAGIC 0x67a8c78d
|
#define ENVFS_INODE_MAGIC 0x67a8c78d
|
||||||
|
#define ENVFS_INODE_END_MAGIC 0x68a8c78d
|
||||||
#define ENVFS_END_MAGIC 0x6a87d6cd
|
#define ENVFS_END_MAGIC 0x6a87d6cd
|
||||||
#define ENVFS_SIGNATURE "barebox envfs"
|
#define ENVFS_SIGNATURE "barebox envfs"
|
||||||
|
|
||||||
struct envfs_inode {
|
struct envfs_inode {
|
||||||
uint32_t magic; /* ENVFS_INODE_MAGIC */
|
uint32_t magic; /* ENVFS_INODE_MAGIC */
|
||||||
uint32_t size; /* data size in bytes */
|
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
|
char data[0]; /* The filename (zero terminated) + padding to 4 byte boundary
|
||||||
* followed by the data for this inode.
|
* followed by the data for this inode.
|
||||||
* The next inode follows after the data + padding to 4 byte
|
* 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.
|
* Superblock information at the beginning of the FS.
|
||||||
*/
|
*/
|
||||||
|
@ -29,8 +38,10 @@ struct envfs_super {
|
||||||
uint32_t priority;
|
uint32_t priority;
|
||||||
uint32_t crc; /* crc for the data */
|
uint32_t crc; /* crc for the data */
|
||||||
uint32_t size; /* size of 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 flags; /* feature flags */
|
||||||
uint32_t future; /* reserved for future use */
|
|
||||||
uint32_t sb_crc; /* crc for the superblock */
|
uint32_t sb_crc; /* crc for the superblock */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
12
include/fs.h
12
include/fs.h
|
@ -51,6 +51,11 @@ struct fs_driver_d {
|
||||||
/* Truncate a file to given size */
|
/* Truncate a file to given size */
|
||||||
int (*truncate)(struct device_d *dev, FILE *f, ulong 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 (*open)(struct device_d *dev, FILE *f, const char *pathname);
|
||||||
int (*close)(struct device_d *dev, FILE *f);
|
int (*close)(struct device_d *dev, FILE *f);
|
||||||
int (*read)(struct device_d *dev, FILE *f, void *buf, size_t size);
|
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 unlink(const char *pathname);
|
||||||
int close(int fd);
|
int close(int fd);
|
||||||
int flush(int fd);
|
int flush(int fd);
|
||||||
|
int lstat(const char *filename, struct stat *s);
|
||||||
int stat(const char *filename, struct stat *s);
|
int stat(const char *filename, struct stat *s);
|
||||||
int read(int fd, void *buf, size_t count);
|
int read(int fd, void *buf, size_t count);
|
||||||
int ioctl(int fd, int request, void *buf);
|
int ioctl(int fd, int request, void *buf);
|
||||||
|
@ -129,6 +135,9 @@ DIR *opendir(const char *pathname);
|
||||||
struct dirent *readdir(DIR *dir);
|
struct dirent *readdir(DIR *dir);
|
||||||
int closedir(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 mount (const char *device, const char *fsname, const char *path);
|
||||||
int umount(const char *pathname);
|
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().
|
* of "..", "." and double slashes. The returned string must be freed wit free().
|
||||||
*/
|
*/
|
||||||
char *normalise_path(const char *path);
|
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 */
|
/* Register a new filesystem driver */
|
||||||
int register_fs_driver(struct fs_driver_d *fsdrv);
|
int register_fs_driver(struct fs_driver_d *fsdrv);
|
||||||
|
|
|
@ -14,7 +14,7 @@ char* last_char_is(const char *s, int c);
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
ACTION_RECURSE = (1 << 0),
|
ACTION_RECURSE = (1 << 0),
|
||||||
/* ACTION_FOLLOWLINKS = (1 << 1), - unused */
|
ACTION_FOLLOWLINKS = (1 << 1),
|
||||||
ACTION_DEPTHFIRST = (1 << 2),
|
ACTION_DEPTHFIRST = (1 << 2),
|
||||||
/*ACTION_REVERSE = (1 << 3), - unused */
|
/*ACTION_REVERSE = (1 << 3), - unused */
|
||||||
};
|
};
|
||||||
|
|
|
@ -54,14 +54,19 @@ int recursive_action(const char *fileName,
|
||||||
const unsigned depth)
|
const unsigned depth)
|
||||||
{
|
{
|
||||||
struct stat statbuf;
|
struct stat statbuf;
|
||||||
|
unsigned follow;
|
||||||
int status;
|
int status;
|
||||||
DIR *dir;
|
DIR *dir;
|
||||||
struct dirent *next;
|
struct dirent *next;
|
||||||
|
|
||||||
if (!fileAction) fileAction = true_action;
|
if (!fileAction) fileAction = true_action;
|
||||||
if (!dirAction) dirAction = 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) {
|
if (status < 0) {
|
||||||
#ifdef DEBUG_RECURS_ACTION
|
#ifdef DEBUG_RECURS_ACTION
|
||||||
bb_error_msg("status=%d followLinks=%d TRUE=%d",
|
bb_error_msg("status=%d followLinks=%d TRUE=%d",
|
||||||
|
|
|
@ -73,7 +73,7 @@ char* last_char_is(const char *s, int c)
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
ACTION_RECURSE = (1 << 0),
|
ACTION_RECURSE = (1 << 0),
|
||||||
/* ACTION_FOLLOWLINKS = (1 << 1), - unused */
|
ACTION_FOLLOWLINKS = (1 << 1),
|
||||||
ACTION_DEPTHFIRST = (1 << 2),
|
ACTION_DEPTHFIRST = (1 << 2),
|
||||||
/*ACTION_REVERSE = (1 << 3), - unused */
|
/*ACTION_REVERSE = (1 << 3), - unused */
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue