From 9b4dfd79953ffb79685a53a0821bd0a205e15088 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Thu, 5 Jul 2007 18:01:38 +0200 Subject: [PATCH] svn_rev_272 more FS work --- common/cmd_fs.c | 2 +- common/cmd_mem.c | 5 -- fs/cramfs/cramfs.c | 17 +++-- fs/fs.c | 78 ++++++++++++++------ fs/ramfs.c | 164 +++++++++++++++++++++++++++++-------------- include/fs.h | 9 ++- include/net.h | 4 ++ lib_generic/global.c | 2 +- 8 files changed, 191 insertions(+), 90 deletions(-) diff --git a/common/cmd_fs.c b/common/cmd_fs.c index 17a52e641..2bc2393e9 100644 --- a/common/cmd_fs.c +++ b/common/cmd_fs.c @@ -108,7 +108,7 @@ static int do_cat ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) while((ret = read(fd, buf, 1024)) > 0) { for(i = 0; i < ret; i++) { - if (isprint(buf[i])) + if (isprint(buf[i]) || buf[i] == '\n' || buf[i] == '\t') putc(buf[i]); else putc('.'); diff --git a/common/cmd_mem.c b/common/cmd_mem.c index 6ce292e42..0355d2ac2 100644 --- a/common/cmd_mem.c +++ b/common/cmd_mem.c @@ -340,11 +340,6 @@ int do_cp ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) return 1; } - if(creat(argv[2], 0)) { - perror("create"); - return 1; - } - dst = open(argv[2], O_WRONLY | O_CREAT); if ( dst < 0) { perror("open"); diff --git a/fs/cramfs/cramfs.c b/fs/cramfs/cramfs.c index c8ef7d7ff..8a5724135 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 b43a9e7b3..55bd2290a 100644 --- a/fs/fs.c +++ b/fs/fs.c @@ -5,6 +5,7 @@ #include #include #include +#include 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); - - dev = e->dev; - - fsdrv = (struct fs_driver_d *)dev->driver->type_data; - f->dev = dev; - - ret = fsdrv->open(dev, f, pathname); - if (ret) { - errno = ret; - goto out; - } + e = get_mtab_entry_by_path(pathname); + if (!e) { + /* This can only happen when nothing is mounted */ + errno = -ENOENT; + goto out; } -printf("open: %d\n",f->no); + + /* Adjust the pathname to the root of the device */ + if (e != mtab) + pathname += strlen(e->path); + + dev = e->dev; + + 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; + } + 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 a17315d6f..63338398c 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(); + /* 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); + size -= now; + pos += now; + buf += 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; + } + + /* 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; } - now = min(size, CHUNK_SIZE - ofs); - printf("now: %d data->data: %p buf: %p\n", now, data->data, buf); - memcpy(data->data, buf, now); - size -= now; - buf += now; - ofs += now; - outsize += now; + while (newchunks--) { + data->next = ramfs_get_chunk(); + data = data->next; + } } - return outsize; + 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, diff --git a/include/fs.h b/include/fs.h index 502a70d59..523d2f2c0 100644 --- a/include/fs.h +++ b/include/fs.h @@ -27,6 +27,7 @@ struct dir { typedef struct filep { struct device_d *dev; /* The device this FILE belongs to */ ulong pos; /* current position in stream */ + ulong size; /* The size of this inode */ void *inode; /* private to the filesystem driver */ @@ -43,8 +44,13 @@ struct fs_driver_d { int (*probe) (struct device_d *dev); int (*mkdir)(struct device_d *dev, const char *pathname); - int (*open)(struct device_d *dev, FILE *f, const char *pathname); + /* create a file. The file is guaranteed to not exist */ int (*create)(struct device_d *dev, const char *pathname, mode_t mode); + + /* Truncate a file to given size */ + int (*truncate)(struct device_d *dev, FILE *f, ulong size); + + int (*open)(struct device_d *dev, FILE *f, const char *pathname); int (*close)(struct device_d *dev, FILE *f); int (*read)(struct device_d *dev, FILE *f, void *buf, size_t size); int (*write)(struct device_d *dev, FILE *f, const void *buf, size_t size); @@ -69,6 +75,7 @@ struct fs_device_d { int open(const char *pathname, int flags); int creat(const char *pathname, mode_t mode); int close(int fd); +int stat(const char *filename, struct stat *s); int read(int fd, void *buf, size_t count); ssize_t write(int fd, const void *buf, size_t count); int ls(const char *path); diff --git a/include/net.h b/include/net.h index af1fb1030..e3e6319f7 100644 --- a/include/net.h +++ b/include/net.h @@ -376,7 +376,11 @@ extern int NetSendUDPPacket(uchar *ether, IPaddr_t dest, int dport, int sport, i extern void NetReceive(volatile uchar *, int); /* Print an IP address on the console */ +#ifdef CONFIG_NET extern void print_IPaddr (IPaddr_t); +#else +#define print_IPaddr(IPaddr_t); +#endif /* * The following functions are a bit ugly, but necessary to deal with diff --git a/lib_generic/global.c b/lib_generic/global.c index 7e817000a..2c0f6c493 100644 --- a/lib_generic/global.c +++ b/lib_generic/global.c @@ -92,7 +92,7 @@ static int do_set( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) val.val_ulong = simple_strtoul(argv[3], NULL, 0); break; case PARAM_TYPE_IPADDR: - val.val_ip = string_to_ip(argv[3]); +// val.val_ip = string_to_ip(argv[3]); break; }