Merge branch 'for-next/link'
This commit is contained in:
commit
e5a927883e
|
@ -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 "
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 <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;
|
||||
|
|
|
@ -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_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";
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
229
fs/fs.c
|
@ -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;
|
||||
|
|
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;
|
||||
}
|
||||
|
||||
#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,
|
||||
|
|
61
fs/ramfs.c
61
fs/ramfs.c
|
@ -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,
|
||||
|
|
|
@ -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 */
|
||||
};
|
||||
|
||||
|
|
12
include/fs.h
12
include/fs.h
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
};
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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 */
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue