diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2007-07-05 18:01:38 +0200 |
---|---|---|
committer | Sascha Hauer <sha@octopus.labnet.pengutronix.de> | 2007-07-05 18:01:38 +0200 |
commit | 9b4dfd79953ffb79685a53a0821bd0a205e15088 (patch) | |
tree | ddb8b85bc241fa46df900d8262f299e2455674b4 /fs | |
parent | 189579188bf79e176cc57a3b6d68f8306cfc7c60 (diff) | |
download | barebox-9b4dfd79953ffb79685a53a0821bd0a205e15088.tar.gz barebox-9b4dfd79953ffb79685a53a0821bd0a205e15088.tar.xz |
svn_rev_272
more FS work
Diffstat (limited to 'fs')
-rw-r--r-- | fs/cramfs/cramfs.c | 17 | ||||
-rw-r--r-- | fs/fs.c | 70 | ||||
-rw-r--r-- | fs/ramfs.c | 162 |
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; @@ -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, |