summaryrefslogtreecommitdiffstats
path: root/fs/ramfs.c
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2007-07-05 18:01:43 +0200
committerSascha Hauer <sha@octopus.labnet.pengutronix.de>2007-07-05 18:01:43 +0200
commit132c9b968dab5ffff3f989e22acdfc072d82e42d (patch)
tree088632187b34f778311d5466eef248af428f526b /fs/ramfs.c
parent57013a9864523d6ddfbe4c63a992c7534a793fad (diff)
downloadbarebox-132c9b968dab5ffff3f989e22acdfc072d82e42d.tar.gz
barebox-132c9b968dab5ffff3f989e22acdfc072d82e42d.tar.xz
svn_rev_325
implement . and .. entries
Diffstat (limited to 'fs/ramfs.c')
-rw-r--r--fs/ramfs.c239
1 files changed, 179 insertions, 60 deletions
diff --git a/fs/ramfs.c b/fs/ramfs.c
index 797b1ae474..e9d62f3f67 100644
--- a/fs/ramfs.c
+++ b/fs/ramfs.c
@@ -7,6 +7,7 @@
#include <errno.h>
#include <asm-generic/errno.h>
#include <linux/stat.h>
+#include <xfuncs.h>
#define CHUNK_SIZE 512
@@ -17,6 +18,7 @@ struct ramfs_chunk {
struct ramfs_inode {
char *name;
+ struct ramfs_inode *parent;
struct ramfs_inode *next;
struct ramfs_inode *child;
ulong mode;
@@ -32,9 +34,9 @@ struct ramfs_priv {
};
/* ---------------------------------------------------------------*/
-struct ramfs_inode * __lookup(struct ramfs_inode *node, const char *name)
+struct ramfs_inode * lookup(struct ramfs_inode *node, const char *name)
{
-// printf("__lookup: %s in %p\n",name, node);
+// printf("lookup: %s in %p\n",name, node);
if(node->mode != S_IFDIR)
return NULL;
@@ -43,15 +45,19 @@ struct ramfs_inode * __lookup(struct ramfs_inode *node, const char *name)
return NULL;
while (node) {
- if (!strcmp(node->name, name))
+// printf("lookup: %s\n", node->name);
+ if (!strcmp(node->name, name)) {
+// printf("lookup: found: 0x%p\n",node);
return node;
+ }
node = node->next;
}
return NULL;
}
-struct ramfs_inode* rlookup(struct ramfs_inode *node, const char *path)
+struct ramfs_inode* rlookup(struct ramfs_priv *priv, const char *path)
{
+ struct ramfs_inode *node = &priv->root;
static char *buf;
char *part;
//printf("rlookup %s in %p\n",path, node);
@@ -62,7 +68,7 @@ struct ramfs_inode* rlookup(struct ramfs_inode *node, const char *path)
goto out;
do {
- node = __lookup(node, part);
+ node = lookup(node, part);
if (!node)
goto out;
part = strtok(NULL, "/");
@@ -73,40 +79,102 @@ out:
return node;
}
+struct ramfs_inode* rlookup_parent(struct ramfs_priv *priv, const char *pathname, char **file)
+{
+ char *path;
+ struct ramfs_inode *node;
+
+ pathname++;
+ path = strdup(pathname);
+
+ if ((*file = strrchr(pathname, '/'))) {
+ char *tmp;
+ (*file)++;
+
+ tmp = strrchr(path, '/');
+ *tmp = 0;
+ node = rlookup(priv, path);
+ if (!node) {
+ errno = -ENOENT;
+ goto out;
+ }
+ } else {
+ *file = (char *)pathname;
+ node = &priv->root;
+ }
+
+out:
+ free(path);
+ return node;
+}
+
+static int chunks = 0;
+
struct ramfs_chunk *ramfs_get_chunk(void)
{
struct ramfs_chunk *data = malloc(sizeof(struct ramfs_chunk));
- printf("get chunk\n");
+// printf("get chunk\n");
data->data = malloc(CHUNK_SIZE);
data->next = NULL;
+ chunks++;
+// printf("chunks: %d\n", chunks);
return data;
}
void ramfs_put_chunk(struct ramfs_chunk *data)
{
- printf("put chunk\n");
+// printf("put chunk\n");
free(data->data);
free(data);
+ chunks--;
+// printf("chunks: %d\n", chunks);
}
-struct ramfs_inode* node_add_child(struct ramfs_inode *node, const char *filename, ulong mode)
+static struct ramfs_inode* ramfs_get_inode(void)
{
- struct ramfs_inode *new_node = malloc(sizeof(struct ramfs_inode));
- memset(new_node, 0, sizeof(struct ramfs_inode));
+ struct ramfs_inode *node = xzalloc(sizeof(struct ramfs_inode));
+ return node;
+}
+
+static void ramfs_put_inode(struct ramfs_inode *node)
+{
+ struct ramfs_chunk *data = node->data;
+
+ while (data) {
+ struct ramfs_chunk *tmp = data->next;
+ ramfs_put_chunk(data);
+ data = tmp;
+ }
+
+ free(node->name);
+ free(node);
+}
+
+struct ramfs_inode* node_insert(struct ramfs_inode *parent_node, const char *filename, ulong mode)
+{
+ struct ramfs_inode *node, *new_node = ramfs_get_inode();
new_node->name = strdup(filename);
new_node->mode = mode;
- if (!(mode & S_IFDIR))
+ node = parent_node->child;
+
+ if (mode & S_IFDIR) {
+ struct ramfs_inode *n = ramfs_get_inode();
+ n->name = strdup(".");
+ n->mode = S_IFDIR;
+ n->child = n;
+ n->parent = new_node;
+ new_node->child = n;
+ n = ramfs_get_inode();
+ n->name = strdup("..");
+ n->mode = S_IFDIR;
+ n->parent = new_node;
+ n->child = parent_node->child;
+ new_node->child->next = n;
+ } else {
new_node->data = ramfs_get_chunk();
-
- printf("node_add_child: %p -> %p\n", node, new_node);
- if (!node->child) {
- node->child = new_node;
- return new_node;
}
- node = node->child;
-
while (node->next)
node = node->next;
@@ -119,32 +187,37 @@ struct ramfs_inode* node_add_child(struct ramfs_inode *node, const char *filenam
int ramfs_create(struct device_d *dev, const char *pathname, mode_t mode)
{
struct ramfs_priv *priv = dev->priv;
- char *path = strdup(pathname);
- char *file;
struct ramfs_inode *node;
+ char *file;
+
+ node = rlookup_parent(priv, pathname, &file);
+ node_insert(node, file, mode);
+ return 0;
+}
- normalise_path(path);
- if (*path == '/')
- path++;
+int ramfs_unlink(struct device_d *dev, const char *pathname)
+{
+ struct ramfs_priv *priv = dev->priv;
+ struct ramfs_inode *node, *lastnode;
+ char *file;
- printf("ramfs create: %s\n",path);
+ node = rlookup_parent(priv, pathname, &file);
- if ((file = strrchr(path, '/'))) {
- *file = 0;
- file++;
- node = rlookup(&priv->root, path);
- if (!node)
- return -ENOENT;
- } else {
- file = path;
- node = &priv->root;
- }
+ lastnode = node->child->next;
+ node = lastnode->next;
- if(__lookup(node, file))
- return -EEXIST;
-printf("CREATE\n");
- node_add_child(node, file, mode);
- return 0;
+ while (node) {
+ if (!strcmp(node->name, file)) {
+ struct ramfs_inode *tmp;
+ tmp = node;
+ lastnode->next = node->next;
+ ramfs_put_inode(tmp);
+ return 0;
+ }
+ lastnode = node;
+ node = node->next;
+ };
+ return -ENOENT;
}
int ramfs_mkdir(struct device_d *dev, const char *pathname)
@@ -152,10 +225,37 @@ int ramfs_mkdir(struct device_d *dev, const char *pathname)
return ramfs_create(dev, pathname, S_IFDIR);
}
+int ramfs_rmdir(struct device_d *dev, const char *pathname)
+{
+ struct ramfs_priv *priv = dev->priv;
+ struct ramfs_inode *node, *lastnode;
+ char *file;
+
+ node = rlookup_parent(priv, pathname, &file);
+
+ lastnode = node->child->next;
+ node = lastnode->next;
+
+ while (node) {
+ if (!strcmp(node->name, file)) {
+ struct ramfs_inode *tmp;
+ tmp = node;
+ lastnode->next = node->next;
+ ramfs_put_inode(tmp->child->next);
+ ramfs_put_inode(tmp->child);
+ ramfs_put_inode(tmp);
+ return 0;
+ }
+ lastnode = node;
+ node = node->next;
+ };
+ return -ENOENT;
+}
+
static int ramfs_open(struct device_d *dev, FILE *file, const char *filename)
{
struct ramfs_priv *priv = dev->priv;
- struct ramfs_inode *node = rlookup(&priv->root, filename);
+ struct ramfs_inode *node = rlookup(priv, filename);
if (!node)
return -ENOENT;
@@ -181,7 +281,7 @@ static int ramfs_read(struct device_d *_dev, FILE *f, void *buf, size_t insize)
int size = insize;
chunk = f->pos / CHUNK_SIZE;
- printf("%s: reading from chunk %d\n", __FUNCTION__, chunk);
+// printf("%s: reading from chunk %d\n", __FUNCTION__, chunk);
/* Position ourself in stream */
data = node->data;
@@ -194,20 +294,21 @@ static int ramfs_read(struct device_d *_dev, FILE *f, void *buf, size_t insize)
/* Read till end of current chunk */
if (ofs) {
now = min(size, CHUNK_SIZE - ofs);
- printf("Reading till end of node. size: %d\n", size);
+// printf("Reading till end of node. size: %d\n", size);
memcpy(buf, data->data + ofs, now);
size -= now;
pos += now;
buf += now;
if (pos > node->size)
node->size = now;
+ data = data->next;
}
/* Do full chunks */
while (size >= CHUNK_SIZE) {
- printf("do full chunk. size: %d\n", size);
- data = data->next;
+// printf("do full chunk. size: %d\n", size);
memcpy(buf, data->data, CHUNK_SIZE);
+ data = data->next;
size -= CHUNK_SIZE;
pos += CHUNK_SIZE;
buf += CHUNK_SIZE;
@@ -215,8 +316,7 @@ static int ramfs_read(struct device_d *_dev, FILE *f, void *buf, size_t insize)
/* And the rest */
if (size) {
- printf("do rest. size: %d\n", size);
- data = data->next;
+// printf("do rest. size: %d\n", size);
memcpy(buf, data->data, size);
}
@@ -234,7 +334,7 @@ static int ramfs_write(struct device_d *_dev, FILE *f, const void *buf, size_t i
int size = insize;
chunk = f->pos / CHUNK_SIZE;
- printf("%s: writing to chunk %d\n", __FUNCTION__, chunk);
+// printf("%s: writing to chunk %d\n", __FUNCTION__, chunk);
/* Position ourself in stream */
data = node->data;
@@ -247,20 +347,21 @@ static int ramfs_write(struct device_d *_dev, FILE *f, const void *buf, size_t i
/* Write till end of current chunk */
if (ofs) {
now = min(size, CHUNK_SIZE - ofs);
- printf("writing till end of node. size: %d\n", size);
- memcpy(data->data, buf, now);
+// printf("writing till end of node. size: %d\n", size);
+ memcpy(data->data + ofs, buf, now);
size -= now;
pos += now;
buf += now;
if (pos > node->size)
node->size = now;
+ data = data->next;
}
/* Do full chunks */
while (size >= CHUNK_SIZE) {
- printf("do full chunk. size: %d\n", size);
- data = data->next;
+// printf("do full chunk. size: %d\n", size);
memcpy(data->data, buf, CHUNK_SIZE);
+ data = data->next;
size -= CHUNK_SIZE;
pos += CHUNK_SIZE;
buf += CHUNK_SIZE;
@@ -268,8 +369,7 @@ static int ramfs_write(struct device_d *_dev, FILE *f, const void *buf, size_t i
/* And the rest */
if (size) {
- printf("do rest. size: %d\n", size);
- data = data->next;
+// printf("do rest. size: %d\n", size);
memcpy(data->data, buf, size);
}
@@ -315,8 +415,11 @@ struct dir* ramfs_opendir(struct device_d *dev, const char *pathname)
{
struct dir *dir;
struct ramfs_priv *priv = dev->priv;
- struct ramfs_inode *node = rlookup(&priv->root, pathname);
+ struct ramfs_inode *node;
+// printf("opendir: %s\n", pathname);
+ node = rlookup(priv, pathname);
+//printf("opendir name: %s\n", node->name);
if (!node)
return NULL;
@@ -353,11 +456,12 @@ int ramfs_closedir(struct device_d *dev, struct dir *dir)
int ramfs_stat(struct device_d *dev, const char *filename, struct stat *s)
{
struct ramfs_priv *priv = dev->priv;
- struct ramfs_inode *node = rlookup(&priv->root, filename);
+ struct ramfs_inode *node = rlookup(priv, filename);
+// printf("ramfs_stat: %s\n", filename);
if (!node)
return -ENOENT;
-
+// printf("stat: %s\n", node->name);
s->st_size = node->size;
s->st_mode = node->mode;
@@ -366,29 +470,44 @@ int ramfs_stat(struct device_d *dev, const char *filename, struct stat *s)
int ramfs_probe(struct device_d *dev)
{
- struct ramfs_priv *priv = malloc(sizeof(struct ramfs_priv));
+ struct ramfs_inode *n;
+ struct ramfs_priv *priv = xzalloc(sizeof(struct ramfs_priv));
- printf("ramfs_probe\n");
- memset(priv, 0, sizeof(struct ramfs_priv));
+// printf("ramfs_probe\n");
dev->priv = priv;
priv->root.name = "/";
priv->root.mode = S_IFDIR;
+ priv->root.parent = &priv->root;
+ n = ramfs_get_inode();
+ n->name = strdup(".");
+ n->mode = S_IFDIR;
+ n->parent = &priv->root;
+ n->child = n;
+ priv->root.child = n;
+ n = ramfs_get_inode();
+ n->name = strdup("..");
+ n->mode = S_IFDIR;
+ n->parent = &priv->root;
+ n->child = priv->root.child;
+ priv->root.child->next = n;
+// printf("priv->root: 0x%p\n", priv->root);
- printf("root node: %p\n",&priv->root);
return 0;
}
static struct fs_driver_d ramfs_driver = {
.type = FS_TYPE_RAMFS,
.create = ramfs_create,
+ .unlink = ramfs_unlink,
.open = ramfs_open,
.close = ramfs_close,
.truncate = ramfs_truncate,
.read = ramfs_read,
.write = ramfs_write,
.mkdir = ramfs_mkdir,
+ .rmdir = ramfs_rmdir,
.opendir = ramfs_opendir,
.readdir = ramfs_readdir,
.closedir = ramfs_closedir,