diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2017-06-14 09:29:53 +0200 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2017-06-14 09:29:53 +0200 |
commit | 253412624e0fa60a309c6691b0cd99b6c341df87 (patch) | |
tree | d261ea96f8b29388beb93ec1b05b7b972aa548c1 /fs | |
parent | 6191ef93b25edbd75caec9213db3665f486ee433 (diff) | |
parent | c35624d1946a4756c93bdb489f4790176b6e2dcc (diff) | |
download | barebox-253412624e0fa60a309c6691b0cd99b6c341df87.tar.gz barebox-253412624e0fa60a309c6691b0cd99b6c341df87.tar.xz |
Merge branch 'for-next/misc'
Diffstat (limited to 'fs')
-rw-r--r-- | fs/devfs-core.c | 92 | ||||
-rw-r--r-- | fs/fs.c | 36 | ||||
-rw-r--r-- | fs/parseopt.c | 26 | ||||
-rw-r--r-- | fs/parseopt.h | 1 |
4 files changed, 151 insertions, 4 deletions
diff --git a/fs/devfs-core.c b/fs/devfs-core.c index 382606f1cf..3368d3ed68 100644 --- a/fs/devfs-core.c +++ b/fs/devfs-core.c @@ -20,11 +20,14 @@ #include <complete.h> #include <driver.h> #include <errno.h> +#include <fcntl.h> #include <malloc.h> #include <ioctl.h> #include <nand.h> #include <linux/err.h> +#include <linux/fs.h> #include <linux/mtd/mtd.h> +#include <unistd.h> LIST_HEAD(cdev_list); @@ -332,6 +335,8 @@ static struct cdev *__devfs_add_partition(struct cdev *cdev, devfs_create(new); + cdev_create_default_automount(new); + return new; } @@ -407,3 +412,90 @@ int devfs_create_partitions(const char *devname, return 0; } + +struct loop_priv { + int fd; +}; + +static ssize_t loop_read(struct cdev *cdev, void *buf, size_t count, + loff_t offset, ulong flags) +{ + struct loop_priv *priv = cdev->priv; + loff_t ofs; + + ofs = lseek(priv->fd, offset, SEEK_SET); + if (ofs < 0) + return ofs; + + return read(priv->fd, buf, count); +} + +static ssize_t loop_write(struct cdev *cdev, const void *buf, size_t count, + loff_t offset, ulong flags) +{ + struct loop_priv *priv = cdev->priv; + loff_t ofs; + + ofs = lseek(priv->fd, offset, SEEK_SET); + if (ofs < 0) + return ofs; + + return write(priv->fd, buf, count); +} + +static const struct file_operations loop_ops = { + .read = loop_read, + .write = loop_write, + .memmap = generic_memmap_rw, + .lseek = dev_lseek_default, +}; + +struct cdev *cdev_create_loop(const char *path, ulong flags) +{ + struct cdev *new; + struct loop_priv *priv; + static int loopno; + loff_t ofs; + + priv = xzalloc(sizeof(*priv)); + + priv->fd = open(path, flags); + if (priv->fd < 0) { + free(priv); + return NULL; + } + + new = xzalloc(sizeof(*new)); + + new->ops = &loop_ops; + new->name = basprintf("loop%u", loopno++); + new->priv = priv; + + ofs = lseek(priv->fd, 0, SEEK_END); + if (ofs < 0) { + free(new); + free(priv); + return NULL; + } + lseek(priv->fd, 0, SEEK_SET); + + new->size = ofs; + new->offset = 0; + new->dev = NULL; + new->flags = 0; + + devfs_create(new); + + return new; +} + +void cdev_remove_loop(struct cdev *cdev) +{ + struct loop_priv *priv = cdev->priv; + + devfs_remove(cdev); + close(priv->fd); + free(priv); + free(cdev->name); + free(cdev); +} @@ -36,6 +36,8 @@ #include <block.h> #include <libfile.h> +#include "parseopt.h" + char *mkmodestr(unsigned long mode, char *str) { static const char *l = "xwr"; @@ -404,6 +406,20 @@ int automount_add(const char *path, const char *cmd) } EXPORT_SYMBOL(automount_add); +void cdev_create_default_automount(struct cdev *cdev) +{ + char *path, *cmd; + + path = basprintf("/mnt/%s", cdev->name); + cmd = basprintf("mount %s", cdev->name); + + make_directory(path); + automount_add(path, cmd); + + free(cmd); + free(path); +} + void automount_print(void) { struct automount *am; @@ -1193,6 +1209,9 @@ static void fs_remove(struct device_d *dev) if (fsdev->cdev) cdev_close(fsdev->cdev); + if (fsdev->loop) + cdev_remove_loop(fsdev->cdev); + free(fsdev->backingstore); free(fsdev); } @@ -1219,13 +1238,18 @@ int register_fs_driver(struct fs_driver_d *fsdrv) } EXPORT_SYMBOL(register_fs_driver); -static const char *detect_fs(const char *filename) +static const char *detect_fs(const char *filename, const char *fsoptions) { enum filetype type; struct driver_d *drv; struct fs_driver_d *fdrv; + bool loop; - type = cdev_detect_type(filename); + parseopt_b(fsoptions, "loop", &loop); + if (loop) + type = file_name_detect_type(filename); + else + type = cdev_detect_type(filename); if (type == filetype_unknown) return NULL; @@ -1242,7 +1266,11 @@ static const char *detect_fs(const char *filename) int fsdev_open_cdev(struct fs_device_d *fsdev) { - fsdev->cdev = cdev_open(fsdev->backingstore, O_RDWR); + parseopt_b(fsdev->options, "loop", &fsdev->loop); + if (fsdev->loop) + fsdev->cdev = cdev_create_loop(fsdev->backingstore, O_RDWR); + else + fsdev->cdev = cdev_open(fsdev->backingstore, O_RDWR); if (!fsdev->cdev) return -EINVAL; @@ -1295,7 +1323,7 @@ int mount(const char *device, const char *fsname, const char *_path, } if (!fsname) - fsname = detect_fs(device); + fsname = detect_fs(device, fsoptions); if (!fsname) return -ENOENT; diff --git a/fs/parseopt.c b/fs/parseopt.c index 12dbe1813c..8ff83019a7 100644 --- a/fs/parseopt.c +++ b/fs/parseopt.c @@ -2,6 +2,32 @@ #include "parseopt.h" +void parseopt_b(const char *options, const char *opt, bool *val) +{ + const char *start; + size_t optlen = strlen(opt); + +again: + start = strstr(options, opt); + + if (!start) { + *val = false; + return; + } + + if (start > options && start[-1] != ',') { + options = start; + goto again; + } + + if (start[optlen] != ',' && start[optlen] != '\0') { + options = start; + goto again; + } + + *val = true; +} + void parseopt_hu(const char *options, const char *opt, unsigned short *val) { const char *start; diff --git a/fs/parseopt.h b/fs/parseopt.h index a8523b6a10..abf3be3f35 100644 --- a/fs/parseopt.h +++ b/fs/parseopt.h @@ -1 +1,2 @@ +void parseopt_b(const char *options, const char *opt, bool *val); void parseopt_hu(const char *options, const char *opt, unsigned short *val); |