summaryrefslogtreecommitdiffstats
path: root/fs/ramfs.c
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2007-07-05 18:01:37 +0200
committerSascha Hauer <sha@octopus.labnet.pengutronix.de>2007-07-05 18:01:37 +0200
commit9db8ed3312a2137b12cb0cb15c4267ead96dbf8b (patch)
treeefa8cebc8db28bf6e7fafae2d920f15d66381047 /fs/ramfs.c
parent225b19227203911f9bda410746ef4e366a008852 (diff)
downloadbarebox-9db8ed3312a2137b12cb0cb15c4267ead96dbf8b.tar.gz
barebox-9db8ed3312a2137b12cb0cb15c4267ead96dbf8b.tar.xz
svn_rev_261
WIP Filesystem support
Diffstat (limited to 'fs/ramfs.c')
-rw-r--r--fs/ramfs.c282
1 files changed, 282 insertions, 0 deletions
diff --git a/fs/ramfs.c b/fs/ramfs.c
new file mode 100644
index 0000000000..7d3d2b6735
--- /dev/null
+++ b/fs/ramfs.c
@@ -0,0 +1,282 @@
+#include <common.h>
+#include <driver.h>
+#include <init.h>
+#include <malloc.h>
+#include <fs.h>
+#include <command.h>
+#include <errno.h>
+#include <asm-generic/errno.h>
+#include <linux/stat.h>
+
+struct handle_d {
+ int (*read)(struct handle_d *, ...);
+ int (*write)(struct handle_d *, ...);
+
+ struct device_d *dev;
+};
+
+struct data_d {
+ char *data;
+ ulong size;
+ struct data_d *next;
+};
+
+struct node_d {
+ char *name;
+ struct node_d *next;
+ struct node_d *child;
+ ulong mode;
+
+ struct handle_d *handle;
+
+ struct data_d *data;
+};
+
+struct filesystem_d {
+ int (*create)(struct device_d *dev, const char *pathname, mode_t mode);
+ struct handle_d *(*open)(struct device_d *dev, const char *pathname, mode_t mode);
+ int (*remove)(struct device_d *dev, const char *pathname);
+ int (*mknod)(struct device_d *dev, const char *pathname, struct handle_d *handle);
+ int (*ls)(struct device_d *dev, const char *pathname);
+};
+
+int create(const char *pathname, ulong mode);
+struct handle_d *open(const char *pathname, ulong type);
+int remove(const char *pathname);
+int mknod(const char *pathname, struct handle_d *handle);
+
+struct ramfs_priv {
+ struct node_d root;
+};
+
+/* ---------------------------------------------------------------*/
+struct node_d * __lookup(struct node_d *node, const char *name)
+{
+// printf("__lookup: %s in %p\n",name, node);
+ node = node->child;
+ if (!node || node->mode != S_IFDIR)
+ return NULL;
+
+ while (node) {
+ if (!strcmp(node->name, name))
+ return node;
+ node = node->next;
+ }
+ return NULL;
+}
+
+struct node_d* rlookup(struct node_d *node, const char *path)
+{
+ static char *buf;
+ char *part;
+//printf("rlookup %s in %p\n",path, node);
+ buf = strdup(path);
+
+ part = strtok(buf, "/");
+ if (!part)
+ goto out;
+
+ do {
+ node = __lookup(node, part);
+ if (!node)
+ goto out;
+ part = strtok(NULL, "/");
+ } while(part);
+
+out:
+ free(buf);
+ return node;
+}
+
+/*
+ * - Remove all multiple slashes
+ * - Remove trailing slashes (except path consists of only
+ * a single slash)
+ * - TODO: illegal characters?
+ */
+void normalise_path(char *path)
+{
+ char *out = path, *in = path;
+
+ while(*in) {
+ if(*in == '/') {
+ *out++ = *in++;
+ while(*in == '/')
+ in++;
+ } else {
+ *out++ = *in++;
+ }
+ }
+
+ /*
+ * Remove trailing slash, but only if
+ * we were given more than a single slash
+ */
+ if (out > path + 1 && *(out - 1) == '/')
+ *(out - 1) = 0;
+
+ *out = 0;
+}
+
+int node_add_child(struct node_d *node, const char *filename, ulong mode)
+{
+ struct node_d *new_node = malloc(sizeof(struct node_d));
+ memset(new_node, 0, sizeof(struct node_d));
+ new_node->name = strdup(filename);
+ new_node->mode = mode;
+
+// printf("node_add_child: %p -> %p\n", node, new_node);
+ if (!node->child) {
+ node->child = new_node;
+ return 0;
+ }
+
+ node = node->child;
+
+ while (node->next)
+ node = node->next;
+
+ node->next = new_node;
+ return 0;
+}
+
+/* ---------------------------------------------------------------*/
+
+int ramfs_create(struct device_d *dev, const char *pathname, ulong mode)
+{
+ struct ramfs_priv *priv = dev->priv;
+ char *path = strdup(pathname);
+ char *file;
+ struct node_d *node;
+
+ normalise_path(path);
+ if (*path == '/')
+ path++;
+
+// printf("after normalise: %s\n",path);
+
+ if ((file = strrchr(path, '/'))) {
+ *file = 0;
+ file++;
+ node = rlookup(&priv->root, path);
+ if (!node)
+ return -ENOENT;
+ } else {
+ file = path;
+ node = &priv->root;
+ }
+
+ if(__lookup(node, file))
+ return -EEXIST;
+
+ return node_add_child(node, file, mode);
+}
+
+int ramfs_mkdir(struct device_d *dev, const char *pathname)
+{
+ return ramfs_create(dev, pathname, S_IFDIR);
+}
+
+int ramfs_probe(struct device_d *dev)
+{
+ struct ramfs_priv *priv = malloc(sizeof(struct ramfs_priv));
+
+ printf("ramfs_probe\n");
+ memset(priv, 0, sizeof(struct ramfs_priv));
+
+ dev->priv = priv;
+
+ priv->root.name = "/";
+ priv->root.mode = S_IFDIR;
+
+ return 0;
+}
+
+static struct handle_d *ramfs_open(struct device_d *dev, const char *pathname)
+{
+ return NULL;
+}
+
+struct dir* ramfs_opendir(struct device_d *dev, const char *pathname)
+{
+ struct dir *dir;
+ struct ramfs_priv *priv = dev->priv;
+ struct node_d *node = rlookup(&priv->root, pathname);
+
+ if (!node)
+ return NULL;
+
+ if (node->mode != S_IFDIR)
+ return NULL;
+
+ dir = malloc(sizeof(struct dir));
+ if (!dir)
+ return NULL;
+
+ dir->node = node->child;
+
+ return dir;
+}
+
+struct dirent* ramfs_readdir(struct device_d *dev, struct dir *dir)
+{
+ if (dir->node) {
+ strcpy(dir->d.name, dir->node->name);
+ dir->d.mode = dir->node->mode;
+ dir->node = dir->node->next;
+ return &dir->d;
+ }
+ return NULL;
+}
+
+int ramfs_closedir(struct device_d *dev, struct dir *dir)
+{
+ free(dir);
+ return 0;
+}
+
+static struct fs_driver_d ramfs_driver = {
+ .type = FS_TYPE_RAMFS,
+ .create = ramfs_create,
+ .open = ramfs_open,
+
+ .mkdir = ramfs_mkdir,
+
+ .opendir = ramfs_opendir,
+ .readdir = ramfs_readdir,
+ .closedir = ramfs_closedir,
+
+ .flags = FS_DRIVER_NO_DEV,
+ .drv = {
+ .type = DEVICE_TYPE_FS,
+ .probe = ramfs_probe,
+ .name = "ramfs",
+ .type_data = &ramfs_driver,
+ }
+};
+
+int ramfs_init(void)
+{
+ return register_driver(&ramfs_driver.drv);
+}
+
+device_initcall(ramfs_init);
+
+/* --------- Testing --------- */
+
+static int do_create ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+// int ret;
+
+ printf("create %s\n",argv[1]);
+// ret = ramfs_create(&ramfs_device, argv[1], S_IFDIR);
+// perror("create", ret);
+ return 0;
+}
+
+U_BOOT_CMD(
+ create, 2, 0, do_create,
+ "ls - list a file or directory\n",
+ "<dev:path> list files on device"
+);
+