Merge branch 'work/automount' into next
This commit is contained in:
commit
62f9b9d623
|
@ -181,6 +181,16 @@ config CMD_NANDTEST
|
|||
select PARTITION_NEED_MTD
|
||||
prompt "nandtest"
|
||||
|
||||
config CMD_AUTOMOUNT
|
||||
tristate
|
||||
select FS_AUTOMOUNT
|
||||
prompt "automount"
|
||||
help
|
||||
automount allows it to automatically execute a script when a certain
|
||||
directory is accessed for the first time. The script should then make
|
||||
this directory available (discover USB devices, bring network interface
|
||||
up and finally mount the filesystem).
|
||||
|
||||
endmenu
|
||||
|
||||
menu "console "
|
||||
|
|
|
@ -64,3 +64,4 @@ obj-$(CONFIG_CMD_OFTREE) += oftree.o
|
|||
obj-$(CONFIG_CMD_MAGICVAR) += magicvar.o
|
||||
obj-$(CONFIG_CMD_IOMEM) += iomem.o
|
||||
obj-$(CONFIG_CMD_LINUX_EXEC) += linux_exec.o
|
||||
obj-$(CONFIG_CMD_AUTOMOUNT) += automount.o
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* automount.c - automount devices
|
||||
*
|
||||
* Copyright (c) 2012 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <fs.h>
|
||||
#include <errno.h>
|
||||
#include <getopt.h>
|
||||
|
||||
static int do_automount(int argc, char *argv[])
|
||||
{
|
||||
int opt, ret;
|
||||
|
||||
while ((opt = getopt(argc, argv, "lr:")) > 0) {
|
||||
switch (opt) {
|
||||
case 'l':
|
||||
automount_print();
|
||||
return 0;
|
||||
case 'r':
|
||||
automount_remove(optarg);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (argc != 3)
|
||||
return COMMAND_ERROR_USAGE;
|
||||
|
||||
ret = automount_add(argv[1], argv[2]);
|
||||
if (ret)
|
||||
printf("adding automountpoint failed: %s\n",
|
||||
strerror(-ret));
|
||||
|
||||
return ret ? 1 : 0;
|
||||
}
|
||||
|
||||
BAREBOX_CMD_HELP_START(automount)
|
||||
BAREBOX_CMD_HELP_USAGE("automount [OPTIONS] <PATH> <cmd>\n")
|
||||
BAREBOX_CMD_HELP_SHORT("execute <cmd> when <PATH> is first accessed\n")
|
||||
BAREBOX_CMD_HELP_OPT("-l", "List currently registered automountpoints\n")
|
||||
BAREBOX_CMD_HELP_OPT("-r <PATH>", "remove an automountpoint\n")
|
||||
BAREBOX_CMD_HELP_END
|
||||
|
||||
BAREBOX_CMD_START(automount)
|
||||
.cmd = do_automount,
|
||||
.usage = "automount [OPTIONS] <PATH> <cmd>\n",
|
||||
BAREBOX_CMD_HELP(cmd_automount_help)
|
||||
BAREBOX_CMD_END
|
||||
|
|
@ -33,14 +33,14 @@
|
|||
static int do_mount(int argc, char *argv[])
|
||||
{
|
||||
int ret = 0;
|
||||
struct mtab_entry *entry;
|
||||
struct fs_device_d *fsdev;
|
||||
|
||||
if (argc == 1) {
|
||||
for_each_mtab_entry(entry) {
|
||||
for_each_fs_device(fsdev) {
|
||||
printf("%s on %s type %s\n",
|
||||
entry->parent_device ? dev_name(entry->parent_device) : "none",
|
||||
entry->path,
|
||||
entry->dev->name);
|
||||
fsdev->parent_device ? dev_name(fsdev->parent_device) : "none",
|
||||
fsdev->path,
|
||||
fsdev->dev.name);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -40,16 +40,19 @@
|
|||
#include <fs.h>
|
||||
#include <linux/stat.h>
|
||||
#include <libgen.h>
|
||||
#include <getopt.h>
|
||||
|
||||
#define SIZE_REMAINING ((ulong)-1)
|
||||
|
||||
#define PART_ADD_DEVNAME (1 << 0)
|
||||
|
||||
static int mtd_part_do_parse_one(char *devname, const char *partstr,
|
||||
char **endp, unsigned long *offset,
|
||||
off_t devsize, size_t *retsize)
|
||||
off_t devsize, size_t *retsize, unsigned int pflags)
|
||||
{
|
||||
ulong size;
|
||||
char *end;
|
||||
char buf[PATH_MAX];
|
||||
char buf[PATH_MAX] = {};
|
||||
unsigned long flags = 0;
|
||||
int ret;
|
||||
|
||||
|
@ -78,7 +81,8 @@ static int mtd_part_do_parse_one(char *devname, const char *partstr,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
sprintf(buf, "%s.", devname);
|
||||
if (pflags & PART_ADD_DEVNAME)
|
||||
sprintf(buf, "%s.", devname);
|
||||
memcpy(buf + strlen(buf), partstr, end - partstr);
|
||||
|
||||
end++;
|
||||
|
@ -114,24 +118,35 @@ static int do_addpart(int argc, char *argv[])
|
|||
unsigned long offset = 0;
|
||||
off_t devsize;
|
||||
struct stat s;
|
||||
int opt;
|
||||
unsigned int flags = PART_ADD_DEVNAME;
|
||||
|
||||
if (argc != 3)
|
||||
while ((opt = getopt(argc, argv, "n")) > 0) {
|
||||
switch (opt) {
|
||||
case 'n':
|
||||
flags &= ~PART_ADD_DEVNAME;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (argc != optind + 2)
|
||||
return COMMAND_ERROR_USAGE;
|
||||
|
||||
if (stat(argv[1], &s)) {
|
||||
if (stat(argv[optind], &s)) {
|
||||
perror("addpart");
|
||||
return 1;
|
||||
}
|
||||
devsize = s.st_size;
|
||||
|
||||
devname = basename(argv[1]);
|
||||
devname = basename(argv[optind]);
|
||||
|
||||
endp = argv[2];
|
||||
endp = argv[optind + 1];
|
||||
|
||||
while (1) {
|
||||
size_t size = 0;
|
||||
|
||||
if (mtd_part_do_parse_one(devname, endp, &endp, &offset, devsize, &size))
|
||||
if (mtd_part_do_parse_one(devname, endp, &endp, &offset,
|
||||
devsize, &size, flags))
|
||||
return 1;
|
||||
|
||||
offset += size;
|
||||
|
@ -152,6 +167,8 @@ static int do_addpart(int argc, char *argv[])
|
|||
BAREBOX_CMD_HELP_START(addpart)
|
||||
BAREBOX_CMD_HELP_USAGE("addpart <device> <part_desc>\n")
|
||||
BAREBOX_CMD_HELP_SHORT("Add a partition description to a device.\n")
|
||||
BAREBOX_CMD_HELP_OPT ("-n", "no prefix. Do not prepend the device name as prefix before the partition name\n")
|
||||
BAREBOX_CMD_HELP_OPT ("<device>", "device being worked on\n")
|
||||
BAREBOX_CMD_HELP_OPT ("<device>", "device being worked on\n")
|
||||
BAREBOX_CMD_HELP_OPT ("<part_desc>", "size1[@offset1](name1)[ro],size2[@offset2](name2)[ro],...\n")
|
||||
BAREBOX_CMD_HELP_END
|
||||
|
|
|
@ -22,17 +22,35 @@
|
|||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <usb/usb.h>
|
||||
#include <getopt.h>
|
||||
|
||||
static int scanned;
|
||||
|
||||
static int do_usb(int argc, char *argv[])
|
||||
{
|
||||
usb_rescan();
|
||||
int opt;
|
||||
|
||||
while ((opt = getopt(argc, argv, "f")) > 0) {
|
||||
switch (opt) {
|
||||
case 'f':
|
||||
scanned = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!scanned) {
|
||||
usb_rescan();
|
||||
scanned = 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const __maybe_unused char cmd_usb_help[] =
|
||||
"Usage: usb\n"
|
||||
"(re-)detect USB devices\n";
|
||||
BAREBOX_CMD_HELP_START(usb)
|
||||
BAREBOX_CMD_HELP_USAGE("usb [-f]\n")
|
||||
BAREBOX_CMD_HELP_SHORT("Scan for USB devices.\n")
|
||||
BAREBOX_CMD_HELP_OPT("-f", "force. Rescan if if if have scanned once\n")
|
||||
BAREBOX_CMD_HELP_END
|
||||
|
||||
BAREBOX_CMD_START(usb)
|
||||
.cmd = do_usb,
|
||||
|
|
|
@ -1678,10 +1678,25 @@ BAREBOX_CMD_END
|
|||
|
||||
static int do_source(int argc, char *argv[])
|
||||
{
|
||||
char *path;
|
||||
int ret;
|
||||
|
||||
if (argc < 2)
|
||||
return COMMAND_ERROR_USAGE;
|
||||
|
||||
return source_script(argv[1], argc - 1, argv + 1);
|
||||
if (strchr(argv[1], '/')) {
|
||||
path = xstrdup(argv[1]);
|
||||
} else {
|
||||
path = find_execable(argv[1]);
|
||||
if (!path)
|
||||
return 1;
|
||||
}
|
||||
|
||||
ret = source_script(path, argc - 1, argv + 1);
|
||||
|
||||
free(path);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const char *source_aliases[] = { ".", NULL};
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
|
||||
menu "Filesystem support "
|
||||
|
||||
config FS_AUTOMOUNT
|
||||
bool
|
||||
|
||||
config FS_CRAMFS
|
||||
bool
|
||||
select ZLIB
|
||||
|
|
18
fs/fat/fat.c
18
fs/fat/fat.c
|
@ -376,6 +376,7 @@ static int fat_probe(struct device_d *dev)
|
|||
struct fs_device_d *fsdev = dev_to_fs_device(dev);
|
||||
struct fat_priv *priv = xzalloc(sizeof(struct fat_priv));
|
||||
char *backingstore = fsdev->backingstore;
|
||||
int ret;
|
||||
|
||||
dev->priv = priv;
|
||||
|
||||
|
@ -383,13 +384,24 @@ static int fat_probe(struct device_d *dev)
|
|||
backingstore += 5;
|
||||
|
||||
priv->cdev = cdev_open(backingstore, O_RDWR);
|
||||
if (!priv->cdev)
|
||||
return -EINVAL;
|
||||
if (!priv->cdev) {
|
||||
ret = -ENOENT;
|
||||
goto err_open;
|
||||
}
|
||||
|
||||
priv->fat.userdata = priv;
|
||||
f_mount(&priv->fat);
|
||||
ret = f_mount(&priv->fat);
|
||||
if (ret)
|
||||
goto err_mount;
|
||||
|
||||
return 0;
|
||||
|
||||
err_mount:
|
||||
cdev_close(priv->cdev);
|
||||
err_open:
|
||||
free(priv);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void fat_remove(struct device_d *dev)
|
||||
|
|
|
@ -1699,9 +1699,7 @@ int f_mount (
|
|||
{
|
||||
fs->fs_type = 0; /* Clear new fs object */
|
||||
|
||||
chk_mounted(fs, 0);
|
||||
|
||||
return 0;
|
||||
return chk_mounted(fs, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
282
fs/fs.c
282
fs/fs.c
|
@ -167,21 +167,21 @@ char *normalise_path(const char *pathname)
|
|||
}
|
||||
EXPORT_SYMBOL(normalise_path);
|
||||
|
||||
LIST_HEAD(mtab_list);
|
||||
static struct mtab_entry *mtab_root;
|
||||
LIST_HEAD(fs_device_list);
|
||||
static struct fs_device_d *fs_dev_root;
|
||||
|
||||
static struct mtab_entry *get_mtab_entry_by_path(const char *path)
|
||||
static struct fs_device_d *get_fsdevice_by_path(const char *path)
|
||||
{
|
||||
struct mtab_entry *e = NULL;
|
||||
struct fs_device_d *fsdev = NULL;
|
||||
|
||||
for_each_mtab_entry(e) {
|
||||
int len = strlen(e->path);
|
||||
if (!strncmp(path, e->path, len) &&
|
||||
for_each_fs_device(fsdev) {
|
||||
int len = strlen(fsdev->path);
|
||||
if (!strncmp(path, fsdev->path, len) &&
|
||||
(path[len] == '/' || path[len] == 0))
|
||||
return e;
|
||||
return fsdev;
|
||||
}
|
||||
|
||||
return mtab_root;
|
||||
return fs_dev_root;
|
||||
}
|
||||
|
||||
static FILE files[MAX_FILES];
|
||||
|
@ -216,20 +216,134 @@ static int check_fd(int fd)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct device_d *get_fs_device_by_path(char **path)
|
||||
#ifdef CONFIG_FS_AUTOMOUNT
|
||||
|
||||
#define AUTOMOUNT_IS_FILE (1 << 0)
|
||||
|
||||
struct automount {
|
||||
char *path;
|
||||
char *cmd;
|
||||
struct list_head list;
|
||||
unsigned int flags;
|
||||
};
|
||||
|
||||
static LIST_HEAD(automount_list);
|
||||
|
||||
void automount_remove(const char *_path)
|
||||
{
|
||||
struct device_d *dev;
|
||||
struct mtab_entry *e;
|
||||
char *path = normalise_path(_path);
|
||||
struct automount *am;
|
||||
|
||||
e = get_mtab_entry_by_path(*path);
|
||||
if (!e)
|
||||
list_for_each_entry(am, &automount_list, list) {
|
||||
if (!strcmp(path, am->path))
|
||||
goto found;
|
||||
}
|
||||
|
||||
return;
|
||||
found:
|
||||
list_del(&am->list);
|
||||
free(am->path);
|
||||
free(am->cmd);
|
||||
free(am);
|
||||
}
|
||||
EXPORT_SYMBOL(automount_remove);
|
||||
|
||||
int automount_add(const char *path, const char *cmd)
|
||||
{
|
||||
struct automount *am = xzalloc(sizeof(*am));
|
||||
struct stat s;
|
||||
int ret;
|
||||
|
||||
am->path = normalise_path(path);
|
||||
am->cmd = xstrdup(cmd);
|
||||
|
||||
ret = stat(path, &s);
|
||||
if (!ret) {
|
||||
/*
|
||||
* If it exists it must be a directory
|
||||
*/
|
||||
if (!S_ISDIR(s.st_mode))
|
||||
return -ENOTDIR;
|
||||
} else {
|
||||
am->flags |= AUTOMOUNT_IS_FILE;
|
||||
}
|
||||
|
||||
list_add_tail(&am->list, &automount_list);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(automount_add);
|
||||
|
||||
void automount_print(void)
|
||||
{
|
||||
struct automount *am;
|
||||
|
||||
list_for_each_entry(am, &automount_list, list)
|
||||
printf("%-20s %s\n", am->path, am->cmd);
|
||||
}
|
||||
EXPORT_SYMBOL(automount_print);
|
||||
|
||||
static void automount_mount(const char *path, int instat)
|
||||
{
|
||||
struct automount *am;
|
||||
int ret;
|
||||
|
||||
list_for_each_entry(am, &automount_list, list) {
|
||||
char *cmd;
|
||||
int len_path = strlen(path);
|
||||
int len_am_path = strlen(am->path);
|
||||
|
||||
/*
|
||||
* stat is a bit special. We do not want to trigger
|
||||
* automount when someone calls stat() on the automount
|
||||
* directory itself.
|
||||
*/
|
||||
if (instat && !(am->flags & AUTOMOUNT_IS_FILE) &&
|
||||
len_path == len_am_path) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (len_path < len_am_path)
|
||||
continue;
|
||||
|
||||
if (strncmp(path, am->path, len_am_path))
|
||||
continue;
|
||||
|
||||
if (*(path + len_am_path) != 0 && *(path + len_am_path) != '/')
|
||||
continue;
|
||||
|
||||
cmd = asprintf("%s %s", am->cmd, am->path);
|
||||
ret = run_command(cmd, 0);
|
||||
free(cmd);
|
||||
|
||||
if (ret)
|
||||
printf("running automount command '%s' failed\n",
|
||||
am->cmd);
|
||||
else
|
||||
automount_remove(am->path);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
#else
|
||||
static void automount_mount(const char *path, int instat)
|
||||
{
|
||||
}
|
||||
#endif /* CONFIG_FS_AUTOMOUNT */
|
||||
|
||||
static struct fs_device_d *get_fs_device_and_root_path(char **path)
|
||||
{
|
||||
struct fs_device_d *fsdev;
|
||||
|
||||
automount_mount(*path, 0);
|
||||
|
||||
fsdev = get_fsdevice_by_path(*path);
|
||||
if (!fsdev)
|
||||
return NULL;
|
||||
if (e != mtab_root)
|
||||
*path += strlen(e->path);
|
||||
if (fsdev != fs_dev_root)
|
||||
*path += strlen(fsdev->path);
|
||||
|
||||
dev = e->dev;
|
||||
|
||||
return dev;
|
||||
return fsdev;
|
||||
}
|
||||
|
||||
static int dir_is_empty(const char *pathname)
|
||||
|
@ -336,7 +450,7 @@ EXPORT_SYMBOL(chdir);
|
|||
|
||||
int unlink(const char *pathname)
|
||||
{
|
||||
struct device_d *dev;
|
||||
struct fs_device_d *fsdev;
|
||||
struct fs_driver_d *fsdrv;
|
||||
char *p = normalise_path(pathname);
|
||||
char *freep = p;
|
||||
|
@ -344,17 +458,17 @@ int unlink(const char *pathname)
|
|||
if (path_check_prereq(pathname, S_IFREG))
|
||||
goto out;
|
||||
|
||||
dev = get_fs_device_by_path(&p);
|
||||
if (!dev)
|
||||
fsdev = get_fs_device_and_root_path(&p);
|
||||
if (!fsdev)
|
||||
goto out;
|
||||
fsdrv = dev_to_fs_driver(dev);
|
||||
fsdrv = fsdev->driver;
|
||||
|
||||
if (!fsdrv->unlink) {
|
||||
errno = -ENOSYS;
|
||||
goto out;
|
||||
}
|
||||
|
||||
errno = fsdrv->unlink(dev, p);
|
||||
errno = fsdrv->unlink(&fsdev->dev, p);
|
||||
out:
|
||||
free(freep);
|
||||
return errno;
|
||||
|
@ -363,23 +477,23 @@ EXPORT_SYMBOL(unlink);
|
|||
|
||||
int open(const char *pathname, int flags, ...)
|
||||
{
|
||||
struct device_d *dev;
|
||||
struct fs_device_d *fsdev;
|
||||
struct fs_driver_d *fsdrv;
|
||||
FILE *f;
|
||||
int exist;
|
||||
int exist_err;
|
||||
struct stat s;
|
||||
char *path = normalise_path(pathname);
|
||||
char *freep = path;
|
||||
|
||||
exist = (stat(path, &s) == 0) ? 1 : 0;
|
||||
exist_err = stat(path, &s);
|
||||
|
||||
if (exist && S_ISDIR(s.st_mode)) {
|
||||
if (!exist_err && S_ISDIR(s.st_mode)) {
|
||||
errno = -EISDIR;
|
||||
goto out1;
|
||||
}
|
||||
|
||||
if (!exist && !(flags & O_CREAT)) {
|
||||
errno = -ENOENT;
|
||||
if (exist_err && !(flags & O_CREAT)) {
|
||||
errno = exist_err;
|
||||
goto out1;
|
||||
}
|
||||
|
||||
|
@ -389,13 +503,13 @@ int open(const char *pathname, int flags, ...)
|
|||
goto out1;
|
||||
}
|
||||
|
||||
dev = get_fs_device_by_path(&path);
|
||||
if (!dev)
|
||||
fsdev = get_fs_device_and_root_path(&path);
|
||||
if (!fsdev)
|
||||
goto out;
|
||||
|
||||
fsdrv = dev_to_fs_driver(dev);
|
||||
fsdrv = fsdev->driver;
|
||||
|
||||
f->dev = dev;
|
||||
f->dev = &fsdev->dev;
|
||||
f->flags = flags;
|
||||
|
||||
if ((flags & O_ACCMODE) && !fsdrv->write) {
|
||||
|
@ -403,22 +517,22 @@ int open(const char *pathname, int flags, ...)
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (!exist) {
|
||||
if (exist_err) {
|
||||
if (NULL != fsdrv->create)
|
||||
errno = fsdrv->create(dev, path,
|
||||
errno = fsdrv->create(&fsdev->dev, path,
|
||||
S_IFREG | S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
else
|
||||
errno = -EROFS;
|
||||
if (errno)
|
||||
goto out;
|
||||
}
|
||||
errno = fsdrv->open(dev, f, path);
|
||||
errno = fsdrv->open(&fsdev->dev, f, path);
|
||||
if (errno)
|
||||
goto out;
|
||||
|
||||
|
||||
if (flags & O_TRUNC) {
|
||||
errno = fsdrv->truncate(dev, f, 0);
|
||||
errno = fsdrv->truncate(&fsdev->dev, f, 0);
|
||||
f->size = 0;
|
||||
if (errno)
|
||||
goto out;
|
||||
|
@ -705,7 +819,7 @@ static int fs_match(struct device_d *dev, struct driver_d *drv)
|
|||
static int fs_probe(struct device_d *dev)
|
||||
{
|
||||
struct fs_device_d *fsdev = dev_to_fs_device(dev);
|
||||
struct mtab_entry *entry = &fsdev->mtab;
|
||||
struct fs_driver_d *fsdrv = dev_to_fs_driver(dev);
|
||||
int ret;
|
||||
|
||||
ret = dev->driver->probe(dev);
|
||||
|
@ -714,15 +828,15 @@ static int fs_probe(struct device_d *dev)
|
|||
|
||||
if (fsdev->cdev) {
|
||||
dev_add_child(fsdev->cdev->dev, &fsdev->dev);
|
||||
entry->parent_device = fsdev->cdev->dev;
|
||||
fsdev->parent_device = fsdev->cdev->dev;
|
||||
}
|
||||
|
||||
entry->dev = &fsdev->dev;
|
||||
fsdev->driver = fsdrv;
|
||||
|
||||
list_add_tail(&entry->list, &mtab_list);
|
||||
list_add_tail(&fsdev->list, &fs_device_list);
|
||||
|
||||
if (!mtab_root)
|
||||
mtab_root = entry;
|
||||
if (!fs_dev_root)
|
||||
fs_dev_root = fsdev;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -730,17 +844,16 @@ static int fs_probe(struct device_d *dev)
|
|||
static void fs_remove(struct device_d *dev)
|
||||
{
|
||||
struct fs_device_d *fsdev = dev_to_fs_device(dev);
|
||||
struct mtab_entry *entry = &fsdev->mtab;
|
||||
|
||||
if (fsdev->dev.driver) {
|
||||
dev->driver->remove(dev);
|
||||
list_del(&entry->list);
|
||||
list_del(&fsdev->list);
|
||||
}
|
||||
|
||||
free(entry->path);
|
||||
free(fsdev->path);
|
||||
|
||||
if (entry == mtab_root)
|
||||
mtab_root = NULL;
|
||||
if (fsdev == fs_dev_root)
|
||||
fs_dev_root = NULL;
|
||||
|
||||
free(fsdev->backingstore);
|
||||
free(fsdev);
|
||||
|
@ -777,10 +890,9 @@ int mount(const char *device, const char *fsname, const char *_path)
|
|||
|
||||
debug("mount: %s on %s type %s\n", device, path, fsname);
|
||||
|
||||
if (mtab_root) {
|
||||
struct mtab_entry *entry;
|
||||
entry = get_mtab_entry_by_path(path);
|
||||
if (entry != mtab_root) {
|
||||
if (fs_dev_root) {
|
||||
fsdev = get_fsdevice_by_path(path);
|
||||
if (fsdev != fs_dev_root) {
|
||||
printf("sorry, no nested mounts\n");
|
||||
errno = -EBUSY;
|
||||
goto err_free_path;
|
||||
|
@ -799,7 +911,7 @@ int mount(const char *device, const char *fsname, const char *_path)
|
|||
fsdev->backingstore = xstrdup(device);
|
||||
safe_strncpy(fsdev->dev.name, fsname, MAX_DRIVER_NAME);
|
||||
fsdev->dev.id = get_free_deviceid(fsdev->dev.name);
|
||||
fsdev->mtab.path = xstrdup(path);
|
||||
fsdev->path = xstrdup(path);
|
||||
fsdev->dev.bus = &fs_bus;
|
||||
|
||||
if (!strncmp(device, "/dev/", 5))
|
||||
|
@ -836,29 +948,29 @@ EXPORT_SYMBOL(mount);
|
|||
|
||||
int umount(const char *pathname)
|
||||
{
|
||||
struct mtab_entry *entry = NULL, *e;
|
||||
struct fs_device_d *fsdev = NULL, *f;
|
||||
char *p = normalise_path(pathname);
|
||||
|
||||
for_each_mtab_entry(e) {
|
||||
if (!strcmp(p, e->path)) {
|
||||
entry = e;
|
||||
for_each_fs_device(f) {
|
||||
if (!strcmp(p, f->path)) {
|
||||
fsdev = f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free(p);
|
||||
|
||||
if (e == mtab_root && !list_is_singular(&mtab_list)) {
|
||||
if (f == fs_dev_root && !list_is_singular(&fs_device_list)) {
|
||||
errno = -EBUSY;
|
||||
return errno;
|
||||
}
|
||||
|
||||
if (!entry) {
|
||||
if (!fsdev) {
|
||||
errno = -EFAULT;
|
||||
return errno;
|
||||
}
|
||||
|
||||
unregister_device(entry->dev);
|
||||
unregister_device(&fsdev->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -867,7 +979,7 @@ EXPORT_SYMBOL(umount);
|
|||
DIR *opendir(const char *pathname)
|
||||
{
|
||||
DIR *dir = NULL;
|
||||
struct device_d *dev;
|
||||
struct fs_device_d *fsdev;
|
||||
struct fs_driver_d *fsdrv;
|
||||
char *p = normalise_path(pathname);
|
||||
char *freep = p;
|
||||
|
@ -875,16 +987,16 @@ DIR *opendir(const char *pathname)
|
|||
if (path_check_prereq(pathname, S_IFDIR))
|
||||
goto out;
|
||||
|
||||
dev = get_fs_device_by_path(&p);
|
||||
if (!dev)
|
||||
fsdev = get_fs_device_and_root_path(&p);
|
||||
if (!fsdev)
|
||||
goto out;
|
||||
fsdrv = dev_to_fs_driver(dev);
|
||||
fsdrv = fsdev->driver;
|
||||
|
||||
debug("opendir: fsdrv: %p\n",fsdrv);
|
||||
|
||||
dir = fsdrv->opendir(dev, p);
|
||||
dir = fsdrv->opendir(&fsdev->dev, p);
|
||||
if (dir) {
|
||||
dir->dev = dev;
|
||||
dir->dev = &fsdev->dev;
|
||||
dir->fsdrv = fsdrv;
|
||||
}
|
||||
|
||||
|
@ -918,23 +1030,25 @@ int stat(const char *filename, struct stat *s)
|
|||
{
|
||||
struct device_d *dev;
|
||||
struct fs_driver_d *fsdrv;
|
||||
struct mtab_entry *e;
|
||||
struct fs_device_d *fsdev;
|
||||
char *f = normalise_path(filename);
|
||||
char *freep = f;
|
||||
|
||||
automount_mount(f, 1);
|
||||
|
||||
memset(s, 0, sizeof(struct stat));
|
||||
|
||||
e = get_mtab_entry_by_path(f);
|
||||
if (!e) {
|
||||
fsdev = get_fsdevice_by_path(f);
|
||||
if (!fsdev) {
|
||||
errno = -ENOENT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (e != mtab_root && strcmp(f, e->path)) {
|
||||
f += strlen(e->path);
|
||||
dev = e->dev;
|
||||
if (fsdev != fs_dev_root && strcmp(f, fsdev->path)) {
|
||||
f += strlen(fsdev->path);
|
||||
dev = &fsdev->dev;
|
||||
} else
|
||||
dev = mtab_root->dev;
|
||||
dev = &fs_dev_root->dev;
|
||||
|
||||
fsdrv = dev_to_fs_driver(dev);
|
||||
|
||||
|
@ -951,20 +1065,20 @@ EXPORT_SYMBOL(stat);
|
|||
int mkdir (const char *pathname, mode_t mode)
|
||||
{
|
||||
struct fs_driver_d *fsdrv;
|
||||
struct device_d *dev;
|
||||
struct fs_device_d *fsdev;
|
||||
char *p = normalise_path(pathname);
|
||||
char *freep = p;
|
||||
|
||||
if (path_check_prereq(pathname, S_UB_DOES_NOT_EXIST))
|
||||
goto out;
|
||||
|
||||
dev = get_fs_device_by_path(&p);
|
||||
if (!dev)
|
||||
fsdev = get_fs_device_and_root_path(&p);
|
||||
if (!fsdev)
|
||||
goto out;
|
||||
fsdrv = dev_to_fs_driver(dev);
|
||||
fsdrv = fsdev->driver;
|
||||
|
||||
if (fsdrv->mkdir) {
|
||||
errno = fsdrv->mkdir(dev, p);
|
||||
errno = fsdrv->mkdir(&fsdev->dev, p);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -978,20 +1092,20 @@ EXPORT_SYMBOL(mkdir);
|
|||
int rmdir (const char *pathname)
|
||||
{
|
||||
struct fs_driver_d *fsdrv;
|
||||
struct device_d *dev;
|
||||
struct fs_device_d *fsdev;
|
||||
char *p = normalise_path(pathname);
|
||||
char *freep = p;
|
||||
|
||||
if (path_check_prereq(pathname, S_IFDIR | S_UB_IS_EMPTY))
|
||||
goto out;
|
||||
|
||||
dev = get_fs_device_by_path(&p);
|
||||
if (!dev)
|
||||
fsdev = get_fs_device_and_root_path(&p);
|
||||
if (!fsdev)
|
||||
goto out;
|
||||
fsdrv = dev_to_fs_driver(dev);
|
||||
fsdrv = fsdev->driver;
|
||||
|
||||
if (fsdrv->rmdir) {
|
||||
errno = fsdrv->rmdir(dev, p);
|
||||
errno = fsdrv->rmdir(&fsdev->dev, p);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
|
19
include/fs.h
19
include/fs.h
|
@ -77,15 +77,8 @@ struct fs_driver_d {
|
|||
#define dev_to_fs_driver(d) container_of(d->driver, struct fs_driver_d, drv)
|
||||
#define dev_to_fs_device(d) container_of(d, struct fs_device_d, dev)
|
||||
|
||||
struct mtab_entry {
|
||||
char *path;
|
||||
struct device_d *dev;
|
||||
struct device_d *parent_device;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
extern struct list_head mtab_list;
|
||||
#define for_each_mtab_entry(e) list_for_each_entry(e, &mtab_list, list)
|
||||
extern struct list_head fs_device_list;
|
||||
#define for_each_fs_device(f) list_for_each_entry(f, &fs_device_list, list)
|
||||
|
||||
struct fs_device_d {
|
||||
char *backingstore; /* the device we are associated with */
|
||||
|
@ -94,7 +87,9 @@ struct fs_device_d {
|
|||
struct fs_driver_d *driver;
|
||||
|
||||
struct cdev *cdev;
|
||||
struct mtab_entry mtab;
|
||||
char *path;
|
||||
struct device_d *parent_device;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -165,4 +160,8 @@ char *normalise_path(const char *path);
|
|||
/* Register a new filesystem driver */
|
||||
int register_fs_driver(struct fs_driver_d *fsdrv);
|
||||
|
||||
void automount_remove(const char *_path);
|
||||
int automount_add(const char *path, const char *cmd);
|
||||
void automount_print(void);
|
||||
|
||||
#endif /* __FS_H */
|
||||
|
|
Loading…
Reference in New Issue