parent
57013a9864
commit
132c9b968d
243
fs/ramfs.c
243
fs/ramfs.c
|
@ -7,6 +7,7 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <asm-generic/errno.h>
|
#include <asm-generic/errno.h>
|
||||||
#include <linux/stat.h>
|
#include <linux/stat.h>
|
||||||
|
#include <xfuncs.h>
|
||||||
|
|
||||||
#define CHUNK_SIZE 512
|
#define CHUNK_SIZE 512
|
||||||
|
|
||||||
|
@ -17,6 +18,7 @@ struct ramfs_chunk {
|
||||||
|
|
||||||
struct ramfs_inode {
|
struct ramfs_inode {
|
||||||
char *name;
|
char *name;
|
||||||
|
struct ramfs_inode *parent;
|
||||||
struct ramfs_inode *next;
|
struct ramfs_inode *next;
|
||||||
struct ramfs_inode *child;
|
struct ramfs_inode *child;
|
||||||
ulong mode;
|
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)
|
if(node->mode != S_IFDIR)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
@ -43,15 +45,19 @@ struct ramfs_inode * __lookup(struct ramfs_inode *node, const char *name)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
while (node) {
|
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;
|
return node;
|
||||||
|
}
|
||||||
node = node->next;
|
node = node->next;
|
||||||
}
|
}
|
||||||
return NULL;
|
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;
|
static char *buf;
|
||||||
char *part;
|
char *part;
|
||||||
//printf("rlookup %s in %p\n",path, node);
|
//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;
|
goto out;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
node = __lookup(node, part);
|
node = lookup(node, part);
|
||||||
if (!node)
|
if (!node)
|
||||||
goto out;
|
goto out;
|
||||||
part = strtok(NULL, "/");
|
part = strtok(NULL, "/");
|
||||||
|
@ -73,40 +79,102 @@ out:
|
||||||
return node;
|
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 *ramfs_get_chunk(void)
|
||||||
{
|
{
|
||||||
struct ramfs_chunk *data = malloc(sizeof(struct ramfs_chunk));
|
struct ramfs_chunk *data = malloc(sizeof(struct ramfs_chunk));
|
||||||
printf("get chunk\n");
|
// printf("get chunk\n");
|
||||||
data->data = malloc(CHUNK_SIZE);
|
data->data = malloc(CHUNK_SIZE);
|
||||||
data->next = NULL;
|
data->next = NULL;
|
||||||
|
chunks++;
|
||||||
|
// printf("chunks: %d\n", chunks);
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ramfs_put_chunk(struct ramfs_chunk *data)
|
void ramfs_put_chunk(struct ramfs_chunk *data)
|
||||||
{
|
{
|
||||||
printf("put chunk\n");
|
// printf("put chunk\n");
|
||||||
free(data->data);
|
free(data->data);
|
||||||
free(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));
|
struct ramfs_inode *node = xzalloc(sizeof(struct ramfs_inode));
|
||||||
memset(new_node, 0, 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->name = strdup(filename);
|
||||||
new_node->mode = mode;
|
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();
|
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)
|
while (node->next)
|
||||||
node = node->next;
|
node = node->next;
|
||||||
|
|
||||||
|
@ -119,43 +187,75 @@ 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)
|
int ramfs_create(struct device_d *dev, const char *pathname, mode_t mode)
|
||||||
{
|
{
|
||||||
struct ramfs_priv *priv = dev->priv;
|
struct ramfs_priv *priv = dev->priv;
|
||||||
char *path = strdup(pathname);
|
|
||||||
char *file;
|
|
||||||
struct ramfs_inode *node;
|
struct ramfs_inode *node;
|
||||||
|
char *file;
|
||||||
|
|
||||||
normalise_path(path);
|
node = rlookup_parent(priv, pathname, &file);
|
||||||
if (*path == '/')
|
node_insert(node, file, mode);
|
||||||
path++;
|
|
||||||
|
|
||||||
printf("ramfs create: %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;
|
|
||||||
printf("CREATE\n");
|
|
||||||
node_add_child(node, file, mode);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ramfs_unlink(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);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
lastnode = node;
|
||||||
|
node = node->next;
|
||||||
|
};
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
int ramfs_mkdir(struct device_d *dev, const char *pathname)
|
int ramfs_mkdir(struct device_d *dev, const char *pathname)
|
||||||
{
|
{
|
||||||
return ramfs_create(dev, pathname, S_IFDIR);
|
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)
|
static int ramfs_open(struct device_d *dev, FILE *file, const char *filename)
|
||||||
{
|
{
|
||||||
struct ramfs_priv *priv = dev->priv;
|
struct ramfs_priv *priv = dev->priv;
|
||||||
struct ramfs_inode *node = rlookup(&priv->root, filename);
|
struct ramfs_inode *node = rlookup(priv, filename);
|
||||||
|
|
||||||
if (!node)
|
if (!node)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
@ -181,7 +281,7 @@ static int ramfs_read(struct device_d *_dev, FILE *f, void *buf, size_t insize)
|
||||||
int size = insize;
|
int size = insize;
|
||||||
|
|
||||||
chunk = f->pos / CHUNK_SIZE;
|
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 */
|
/* Position ourself in stream */
|
||||||
data = node->data;
|
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 */
|
/* Read till end of current chunk */
|
||||||
if (ofs) {
|
if (ofs) {
|
||||||
now = min(size, CHUNK_SIZE - 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);
|
memcpy(buf, data->data + ofs, now);
|
||||||
size -= now;
|
size -= now;
|
||||||
pos += now;
|
pos += now;
|
||||||
buf += now;
|
buf += now;
|
||||||
if (pos > node->size)
|
if (pos > node->size)
|
||||||
node->size = now;
|
node->size = now;
|
||||||
|
data = data->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Do full chunks */
|
/* Do full chunks */
|
||||||
while (size >= CHUNK_SIZE) {
|
while (size >= CHUNK_SIZE) {
|
||||||
printf("do full chunk. size: %d\n", size);
|
// printf("do full chunk. size: %d\n", size);
|
||||||
data = data->next;
|
|
||||||
memcpy(buf, data->data, CHUNK_SIZE);
|
memcpy(buf, data->data, CHUNK_SIZE);
|
||||||
|
data = data->next;
|
||||||
size -= CHUNK_SIZE;
|
size -= CHUNK_SIZE;
|
||||||
pos += CHUNK_SIZE;
|
pos += CHUNK_SIZE;
|
||||||
buf += 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 */
|
/* And the rest */
|
||||||
if (size) {
|
if (size) {
|
||||||
printf("do rest. size: %d\n", size);
|
// printf("do rest. size: %d\n", size);
|
||||||
data = data->next;
|
|
||||||
memcpy(buf, data->data, 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;
|
int size = insize;
|
||||||
|
|
||||||
chunk = f->pos / CHUNK_SIZE;
|
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 */
|
/* Position ourself in stream */
|
||||||
data = node->data;
|
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 */
|
/* Write till end of current chunk */
|
||||||
if (ofs) {
|
if (ofs) {
|
||||||
now = min(size, CHUNK_SIZE - ofs);
|
now = min(size, CHUNK_SIZE - ofs);
|
||||||
printf("writing till end of node. size: %d\n", size);
|
// printf("writing till end of node. size: %d\n", size);
|
||||||
memcpy(data->data, buf, now);
|
memcpy(data->data + ofs, buf, now);
|
||||||
size -= now;
|
size -= now;
|
||||||
pos += now;
|
pos += now;
|
||||||
buf += now;
|
buf += now;
|
||||||
if (pos > node->size)
|
if (pos > node->size)
|
||||||
node->size = now;
|
node->size = now;
|
||||||
|
data = data->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Do full chunks */
|
/* Do full chunks */
|
||||||
while (size >= CHUNK_SIZE) {
|
while (size >= CHUNK_SIZE) {
|
||||||
printf("do full chunk. size: %d\n", size);
|
// printf("do full chunk. size: %d\n", size);
|
||||||
data = data->next;
|
|
||||||
memcpy(data->data, buf, CHUNK_SIZE);
|
memcpy(data->data, buf, CHUNK_SIZE);
|
||||||
|
data = data->next;
|
||||||
size -= CHUNK_SIZE;
|
size -= CHUNK_SIZE;
|
||||||
pos += CHUNK_SIZE;
|
pos += CHUNK_SIZE;
|
||||||
buf += 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 */
|
/* And the rest */
|
||||||
if (size) {
|
if (size) {
|
||||||
printf("do rest. size: %d\n", size);
|
// printf("do rest. size: %d\n", size);
|
||||||
data = data->next;
|
|
||||||
memcpy(data->data, buf, 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 dir *dir;
|
||||||
struct ramfs_priv *priv = dev->priv;
|
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)
|
if (!node)
|
||||||
return NULL;
|
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)
|
int ramfs_stat(struct device_d *dev, const char *filename, struct stat *s)
|
||||||
{
|
{
|
||||||
struct ramfs_priv *priv = dev->priv;
|
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)
|
if (!node)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
// printf("stat: %s\n", node->name);
|
||||||
s->st_size = node->size;
|
s->st_size = node->size;
|
||||||
s->st_mode = node->mode;
|
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)
|
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");
|
// printf("ramfs_probe\n");
|
||||||
memset(priv, 0, sizeof(struct ramfs_priv));
|
|
||||||
|
|
||||||
dev->priv = priv;
|
dev->priv = priv;
|
||||||
|
|
||||||
priv->root.name = "/";
|
priv->root.name = "/";
|
||||||
priv->root.mode = S_IFDIR;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct fs_driver_d ramfs_driver = {
|
static struct fs_driver_d ramfs_driver = {
|
||||||
.type = FS_TYPE_RAMFS,
|
.type = FS_TYPE_RAMFS,
|
||||||
.create = ramfs_create,
|
.create = ramfs_create,
|
||||||
|
.unlink = ramfs_unlink,
|
||||||
.open = ramfs_open,
|
.open = ramfs_open,
|
||||||
.close = ramfs_close,
|
.close = ramfs_close,
|
||||||
.truncate = ramfs_truncate,
|
.truncate = ramfs_truncate,
|
||||||
.read = ramfs_read,
|
.read = ramfs_read,
|
||||||
.write = ramfs_write,
|
.write = ramfs_write,
|
||||||
.mkdir = ramfs_mkdir,
|
.mkdir = ramfs_mkdir,
|
||||||
|
.rmdir = ramfs_rmdir,
|
||||||
.opendir = ramfs_opendir,
|
.opendir = ramfs_opendir,
|
||||||
.readdir = ramfs_readdir,
|
.readdir = ramfs_readdir,
|
||||||
.closedir = ramfs_closedir,
|
.closedir = ramfs_closedir,
|
||||||
|
|
Loading…
Reference in New Issue