summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2007-07-05 18:01:38 +0200
committerSascha Hauer <sha@octopus.labnet.pengutronix.de>2007-07-05 18:01:38 +0200
commit9b4dfd79953ffb79685a53a0821bd0a205e15088 (patch)
treeddb8b85bc241fa46df900d8262f299e2455674b4 /fs
parent189579188bf79e176cc57a3b6d68f8306cfc7c60 (diff)
downloadbarebox-9b4dfd79953ffb79685a53a0821bd0a205e15088.tar.gz
barebox-9b4dfd79953ffb79685a53a0821bd0a205e15088.tar.xz
svn_rev_272
more FS work
Diffstat (limited to 'fs')
-rw-r--r--fs/cramfs/cramfs.c17
-rw-r--r--fs/fs.c70
-rw-r--r--fs/ramfs.c162
3 files changed, 172 insertions, 77 deletions
diff --git a/fs/cramfs/cramfs.c b/fs/cramfs/cramfs.c
index c8ef7d7ff0..8a57241350 100644
--- a/fs/cramfs/cramfs.c
+++ b/fs/cramfs/cramfs.c
@@ -293,8 +293,7 @@ static int cramfs_open(struct device_d *_dev, FILE *file, const char *filename)
if (offset <= 0)
return -ENOENT;
- file->pos = 0;
- file->inode = dev->map_base + offset;
+ file->inode = (void*)dev->map_base + offset;
return 0;
}
@@ -323,7 +322,7 @@ static int cramfs_read(struct device_d *_dev, FILE *f, void *buf, size_t size)
unsigned long base;
int copy;
- blocknr = f->pos >> 12;
+ blocknr = (f->pos + outsize) >> 12;
if (blocknr != priv->curr_block || priv->inode != inode) {
if (blocknr)
base = CRAMFS_32 (block_ptrs[blocknr - 1]);
@@ -346,7 +345,6 @@ static int cramfs_read(struct device_d *_dev, FILE *f, void *buf, size_t size)
memcpy(buf, priv->buf + ofs, copy);
ofs = 0;
- f->pos += copy;
outsize += copy;
size -= copy;
buf += copy;
@@ -364,13 +362,18 @@ static int cramfs_stat(struct device_d *_dev, const char *filename, struct stat
char *f;
unsigned long offset;
- f = strdup(filename);
- offset = cramfs_resolve (dev->map_base,
+ if (strlen (filename) == 0 || !strcmp (filename, "/")) {
+ /* Root directory. Use root inode in super block */
+ offset = CRAMFS_GET_OFFSET (&(priv->super.root)) << 2;
+ } else {
+ f = strdup(filename);
+ offset = cramfs_resolve (dev->map_base,
CRAMFS_GET_OFFSET (&(priv->super.root)) << 2,
CRAMFS_24 (priv->super.root.size), 1,
strtok (f, "/"));
- free(f);
+ free(f);
+ }
if (offset < 0)
return -ENOENT;
diff --git a/fs/fs.c b/fs/fs.c
index b43a9e7b38..55bd2290a1 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -5,6 +5,7 @@
#include <asm-generic/errno.h>
#include <malloc.h>
#include <linux/stat.h>
+#include <fcntl.h>
char *mkmodestr(unsigned long mode, char *str)
{
@@ -152,7 +153,7 @@ int creat(const char *pathname, mode_t mode)
dev = e->dev;
fsdrv = (struct fs_driver_d *)dev->driver->type_data;
- errno = fsdrv->create(dev, pathname, mode);
+ errno = fsdrv->create(dev, pathname, S_IFREG);
return errno;
}
@@ -163,32 +164,58 @@ int open(const char *pathname, int flags)
struct fs_driver_d *fsdrv;
struct mtab_entry *e;
FILE *f;
- int ret;
+ int exist;
+ struct stat s;
+
+ exist = stat(pathname, &s) == 0 ? 1 : 0;
+
+ if (!exist && !(flags & O_CREAT))
+ return -EEXIST;
f = get_file_by_pathname(pathname);
- if (!f->dev) {
- e = get_mtab_entry_by_path(pathname);
- if (!e) {
- errno = -ENOENT;
- goto out;
- }
+ if (f->dev)
+ return f->no;
- if (e != mtab)
- pathname += strlen(e->path);
+ e = get_mtab_entry_by_path(pathname);
+ if (!e) {
+ /* This can only happen when nothing is mounted */
+ errno = -ENOENT;
+ goto out;
+ }
- dev = e->dev;
+ /* Adjust the pathname to the root of the device */
+ if (e != mtab)
+ pathname += strlen(e->path);
- fsdrv = (struct fs_driver_d *)dev->driver->type_data;
- f->dev = dev;
+ dev = e->dev;
- ret = fsdrv->open(dev, f, pathname);
- if (ret) {
- errno = ret;
+ fsdrv = (struct fs_driver_d *)dev->driver->type_data;
+ f->dev = dev;
+
+ if ((flags & O_ACCMODE) && !fsdrv->write) {
+ errno = -EROFS;
+ goto out;
+ }
+
+ if (!exist) {
+ errno = fsdrv->create(dev, pathname, S_IFREG);
+ if (errno)
goto out;
- }
}
-printf("open: %d\n",f->no);
+ errno = fsdrv->open(dev, f, pathname);
+ if (errno)
+ goto out;
+
+ if (flags & O_APPEND)
+ f->pos = f->size;
+
+ if (flags & O_TRUNC) {
+ errno = fsdrv->truncate(dev, f, 0);
+ if (errno)
+ goto out;
+ }
+
return f->no;
out:
@@ -206,6 +233,7 @@ int read(int fd, void *buf, size_t count)
printf("READ: dev: %p\n",dev);
if (dev->type == DEVICE_TYPE_FS) {
fsdrv = (struct fs_driver_d *)dev->driver->type_data;
+ printf("\nreading %d bytes at %d\n",count, f->pos);
errno = fsdrv->read(dev, f, buf, count);
} else {
errno = dev->driver->read(dev, buf, count, f->pos, 0); /* FIXME: flags */
@@ -225,6 +253,12 @@ ssize_t write(int fd, const void *buf, size_t count)
printf("WRITE: dev: %p\n",dev);
if (dev->type == DEVICE_TYPE_FS) {
fsdrv = (struct fs_driver_d *)dev->driver->type_data;
+ if (f->pos + count > f->size) {
+ errno = fsdrv->truncate(dev, f, f->pos + count);
+ if (errno)
+ return errno;
+ f->size = f->pos + count;
+ }
errno = fsdrv->write(dev, f, buf, count);
} else {
errno = dev->driver->write(dev, buf, count, f->pos, 0); /* FIXME: flags */
diff --git a/fs/ramfs.c b/fs/ramfs.c
index a17315d6f2..63338398c6 100644
--- a/fs/ramfs.c
+++ b/fs/ramfs.c
@@ -10,9 +10,9 @@
#define CHUNK_SIZE 512
-struct data_d {
+struct ramfs_chunk {
char *data;
- struct data_d *next;
+ struct ramfs_chunk *next;
};
struct ramfs_inode {
@@ -24,7 +24,7 @@ struct ramfs_inode {
struct handle_d *handle;
ulong size;
- struct data_d *data;
+ struct ramfs_chunk *data;
};
struct ramfs_priv {
@@ -73,17 +73,36 @@ out:
return node;
}
-int node_add_child(struct ramfs_inode *node, const char *filename, ulong mode)
+struct ramfs_chunk *ramfs_get_chunk(void)
+{
+ struct ramfs_chunk *data = malloc(sizeof(struct ramfs_chunk));
+ printf("get chunk\n");
+ data->data = malloc(CHUNK_SIZE);
+ data->next = NULL;
+ return data;
+}
+
+void ramfs_put_chunk(struct ramfs_chunk *data)
+{
+ printf("put chunk\n");
+ free(data->data);
+ free(data);
+}
+
+struct ramfs_inode* node_add_child(struct ramfs_inode *node, const char *filename, ulong mode)
{
struct ramfs_inode *new_node = malloc(sizeof(struct ramfs_inode));
memset(new_node, 0, sizeof(struct ramfs_inode));
new_node->name = strdup(filename);
new_node->mode = mode;
+ if (!(mode & S_IFDIR))
+ new_node->data = ramfs_get_chunk();
+
printf("node_add_child: %p -> %p\n", node, new_node);
if (!node->child) {
node->child = new_node;
- return 0;
+ return new_node;
}
node = node->child;
@@ -92,7 +111,7 @@ int node_add_child(struct ramfs_inode *node, const char *filename, ulong mode)
node = node->next;
node->next = new_node;
- return 0;
+ return new_node;
}
/* ---------------------------------------------------------------*/
@@ -124,7 +143,8 @@ int ramfs_create(struct device_d *dev, const char *pathname, mode_t mode)
if(__lookup(node, file))
return -EEXIST;
printf("CREATE\n");
- return node_add_child(node, file, mode);
+ node_add_child(node, file, mode);
+ return 0;
}
int ramfs_mkdir(struct device_d *dev, const char *pathname)
@@ -156,7 +176,7 @@ static int ramfs_open(struct device_d *dev, FILE *file, const char *filename)
if (!node)
return -ENOENT;
- file->pos = 0;
+ file->size = node->size;
file->inode = node;
return 0;
}
@@ -171,52 +191,92 @@ static int ramfs_read(struct device_d *_dev, FILE *f, void *buf, size_t size)
return 0;
}
-struct data_d *ramfs_get_chunk(void)
-{
- struct data_d *data = malloc(sizeof(struct data_d));
- data->data = malloc(CHUNK_SIZE);
- data->next = NULL;
- return data;
-}
-
-static int ramfs_write(struct device_d *_dev, FILE *f, const void *buf, size_t size)
+static int ramfs_write(struct device_d *_dev, FILE *f, const void *buf, size_t insize)
{
struct ramfs_inode *node = (struct ramfs_inode *)f->inode;
int chunk;
- struct data_d *data = node->data;
+ struct ramfs_chunk *data;
int ofs;
- int outsize = 0;
int now;
+ int pos = f->pos;
+ int size = insize;
chunk = f->pos / CHUNK_SIZE;
- printf("%s: wrinting to chunk %d\n", __FUNCTION__, chunk);
-
- if (!node->data)
- node->data = ramfs_get_chunk();
+ printf("%s: writing to chunk %d\n", __FUNCTION__, chunk);
+ /* Position ourself in stream */
+ data = node->data;
while (chunk) {
data = data->next;
chunk--;
}
-
ofs = f->pos % CHUNK_SIZE;
- while (size) {
- if (ofs == CHUNK_SIZE) {
- printf("get new chunk\n");
- data->next = ramfs_get_chunk();
- data = data->next;
- }
-
+ /* Write till end of current chunk */
+ if (ofs) {
now = min(size, CHUNK_SIZE - ofs);
- printf("now: %d data->data: %p buf: %p\n", now, data->data, buf);
+ printf("writing till end of node. size: %d\n", size);
memcpy(data->data, buf, now);
size -= now;
+ pos += now;
buf += now;
- ofs += now;
- outsize += now;
+ if (pos > node->size)
+ node->size = now;
+ }
+
+ /* Do full chunks */
+ while (size >= CHUNK_SIZE) {
+ printf("do full chunk. size: %d\n", size);
+ data = data->next;
+ memcpy(data->data, buf, CHUNK_SIZE);
+ size -= CHUNK_SIZE;
+ pos += CHUNK_SIZE;
+ buf += CHUNK_SIZE;
}
- return outsize;
+
+ /* And the rest */
+ if (size) {
+ printf("do rest. size: %d\n", size);
+ data = data->next;
+ memcpy(data->data, buf, size);
+ }
+
+ return insize;
+}
+
+int ramfs_truncate(struct device_d *dev, FILE *f, ulong size)
+{
+ struct ramfs_inode *node = (struct ramfs_inode *)f->inode;
+ int oldchunks, newchunks;
+ struct ramfs_chunk *data = node->data;
+
+ newchunks = (size + CHUNK_SIZE - 1) / CHUNK_SIZE;
+ oldchunks = (node->size + CHUNK_SIZE - 1) / CHUNK_SIZE;
+
+ if (newchunks < oldchunks) {
+ while (newchunks--)
+ data = data->next;
+ while (data->next) {
+ struct ramfs_chunk *tmp;
+ tmp = data->next;
+ ramfs_put_chunk(data);
+ data = tmp;
+ }
+ }
+
+ if (newchunks > oldchunks) {
+ while (data->next) {
+ newchunks--;
+ data = data->next;
+ }
+
+ while (newchunks--) {
+ data->next = ramfs_get_chunk();
+ data = data->next;
+ }
+ }
+ node->size = size;
+ return 0;
}
struct dir* ramfs_opendir(struct device_d *dev, const char *pathname)
@@ -262,34 +322,32 @@ 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);
-printf("%s: %s node: %p\n",__FUNCTION__, filename, node);
+
if (!node) {
errno = -ENOENT;
return -ENOENT;
}
+ s->st_size = node->size;
s->st_mode = node->mode;
return 0;
}
static struct fs_driver_d ramfs_driver = {
- .type = FS_TYPE_RAMFS,
- .create = ramfs_create,
- .open = ramfs_open,
- .close = ramfs_close,
-
- .read = ramfs_read,
- .write = ramfs_write,
-
- .mkdir = ramfs_mkdir,
-
- .opendir = ramfs_opendir,
- .readdir = ramfs_readdir,
- .closedir = ramfs_closedir,
- .stat = ramfs_stat,
-
- .flags = FS_DRIVER_NO_DEV,
+ .type = FS_TYPE_RAMFS,
+ .create = ramfs_create,
+ .open = ramfs_open,
+ .close = ramfs_close,
+ .truncate = ramfs_truncate,
+ .read = ramfs_read,
+ .write = ramfs_write,
+ .mkdir = ramfs_mkdir,
+ .opendir = ramfs_opendir,
+ .readdir = ramfs_readdir,
+ .closedir = ramfs_closedir,
+ .stat = ramfs_stat,
+ .flags = FS_DRIVER_NO_DEV,
.drv = {
.type = DEVICE_TYPE_FS,
.probe = ramfs_probe,