diff --git a/common/Makefile b/common/Makefile index bbbf8ad0c..e0e4cd044 100644 --- a/common/Makefile +++ b/common/Makefile @@ -90,3 +90,6 @@ obj-y += mtdpart.o obj-y += env.o obj-y += startup.o obj-y += misc.o + +obj-y += cmd_fs.o + diff --git a/common/cmd_flash.c b/common/cmd_flash.c index 4395ca930..43c44f281 100644 --- a/common/cmd_flash.c +++ b/common/cmd_flash.c @@ -51,7 +51,7 @@ int do_flerase (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) return 1; } - erase(mem.device, mem.size, mem.start); + dev_erase(mem.device, mem.size, mem.start); return 0; } diff --git a/common/cmd_mem.c b/common/cmd_mem.c index 1da58d22b..0a026f6b2 100644 --- a/common/cmd_mem.c +++ b/common/cmd_mem.c @@ -131,9 +131,9 @@ int do_mem_md ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) do { now = min(RW_BUF_SIZE, nbytes); - r = read(mem.device, rw_buf, now, offs, RW_SIZE(size)); + r = dev_read(mem.device, rw_buf, now, offs, RW_SIZE(size)); if (r <= 0) { - perror("read", r); + perror("read"); return r; } @@ -184,7 +184,7 @@ int do_mem_mw ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) count = size; if (count == size) { - return write(mem.device, (uchar *)&writeval, count, mem.start, RW_SIZE(size)); + return dev_write(mem.device, (uchar *)&writeval, count, mem.start, RW_SIZE(size)); } else { printf("write multiple not yet implemented\n"); } @@ -300,11 +300,11 @@ int do_mem_cp ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) while (count > 0) { now = min(RW_BUF_SIZE, count); - ret = read(src.device, rw_buf, now, src.start + offset, RW_SIZE(size)); + ret = dev_read(src.device, rw_buf, now, src.start + offset, RW_SIZE(size)); if (ret <= 0) return ret; - ret = write(dst.device, rw_buf, ret, dst.start + offset, RW_SIZE(size)); + ret = dev_write(dst.device, rw_buf, ret, dst.start + offset, RW_SIZE(size)); if (ret <= 0) return ret; if (ret < now) @@ -432,14 +432,19 @@ static void memcpy_sz(void *_dst, void *_src, ulong count, ulong rwsize) ssize_t mem_read(struct device_d *dev, void *buf, size_t count, ulong offset, ulong rwflags) { - memcpy_sz(buf, (void *)(dev->map_base + offset), count, rwflags & RW_SIZE_MASK); - return count; + ulong size; + size = min(count, dev->size - offset); + printf("mem_read: dev->map_base: %p size: %d offset: %d\n",dev->map_base, size, offset); + memcpy_sz(buf, (void *)(dev->map_base + offset), size, rwflags & RW_SIZE_MASK); + return size; } ssize_t mem_write(struct device_d *dev, void *buf, size_t count, ulong offset, ulong rwflags) { - memcpy_sz((void *)(dev->map_base + offset), buf, count, rwflags & RW_SIZE_MASK); - return count; + ulong size; + size = min(count, dev->size - offset); + memcpy_sz((void *)(dev->map_base + offset), buf, size, rwflags & RW_SIZE_MASK); + return size; } static struct device_d mem_dev = { diff --git a/common/env.c b/common/env.c index d8fb86795..8a6901721 100644 --- a/common/env.c +++ b/common/env.c @@ -123,7 +123,7 @@ int add_env_spec(char *spec) env_list->next = NULL; - err = read(info.device, env, env_size, info.start, 0); + err = dev_read(info.device, env, env_size, info.start, 0); if (err != env_size) goto err_out; @@ -206,13 +206,13 @@ int saveenv(void) *(ulong *)env = crc32(0, env + sizeof(ulong), env_size - sizeof(ulong)); - ret = erase(info.device, info.size, info.start); + ret = dev_erase(info.device, info.size, info.start); if (ret) { printf("unable to erase\n"); goto err_out; } - ret = write(info.device, env, info.size, info.start, 0); + ret = dev_write(info.device, env, info.size, info.start, 0); if (ret < 0) { printf("unable to write\n"); goto err_out; diff --git a/common/mtdpart.c b/common/mtdpart.c index 788aeda06..3b4cc7f71 100644 --- a/common/mtdpart.c +++ b/common/mtdpart.c @@ -196,14 +196,14 @@ ssize_t part_read(struct device_d *dev, void *buf, size_t count, unsigned long o { struct partition *part = dev->platform_data; - return read(part->parent, buf, count, offset + part->offset, flags); + return dev_read(part->parent, buf, count, offset + part->offset, flags); } ssize_t part_write(struct device_d *dev, void *buf, size_t count, unsigned long offset, ulong flags) { struct partition *part = dev->platform_data; - return write(part->parent, buf, count, offset + part->offset, flags); + return dev_write(part->parent, buf, count, offset + part->offset, flags); } struct driver_d part_driver = { diff --git a/fs/cramfs/cramfs.c b/fs/cramfs/cramfs.c index 95dfad97a..25631a6b7 100644 --- a/fs/cramfs/cramfs.c +++ b/fs/cramfs/cramfs.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -42,49 +43,56 @@ #define CRAMINO(x) (CRAMFS_GET_OFFSET(x) ? CRAMFS_GET_OFFSET(x)<<2 : 1) #define OFFSET(x) ((x)->i_ino) -struct cramfs_super super; +struct cramfs_priv { + struct cramfs_super super; + int curr_block; + struct cramfs_inode *inode; + char buf[4096]; + int curr_block_len; +}; -static int cramfs_read_super (struct device_d *dev) +static int cramfs_read_super (struct device_d *dev, struct cramfs_priv *priv) { unsigned long root_offset; + struct cramfs_super *super = &priv->super; - if (read(dev, &super, sizeof (super), 0, 0) < sizeof (super)) { + if (dev_read(dev, super, sizeof (struct cramfs_super), 0, 0) < sizeof (struct cramfs_super)) { printf("read superblock failed\n"); return -EINVAL; } /* Do sanity checks on the superblock */ - if (super.magic != CRAMFS_32 (CRAMFS_MAGIC)) { + if (super->magic != CRAMFS_32 (CRAMFS_MAGIC)) { /* check at 512 byte offset */ - if (read(dev, &super, sizeof (super), 512, 0) < sizeof (super)) { + if (dev_read(dev, super, sizeof (struct cramfs_super), 512, 0) < sizeof (struct cramfs_super)) { printf("read superblock failed\n"); return -EINVAL; } - if (super.magic != CRAMFS_32 (CRAMFS_MAGIC)) { + if (super->magic != CRAMFS_32 (CRAMFS_MAGIC)) { printf ("cramfs: wrong magic\n"); return -1; } } /* flags is reused several times, so swab it once */ - super.flags = CRAMFS_32 (super.flags); - super.size = CRAMFS_32 (super.size); + super->flags = CRAMFS_32 (super->flags); + super->size = CRAMFS_32 (super->size); /* get feature flags first */ - if (super.flags & ~CRAMFS_SUPPORTED_FLAGS) { + if (super->flags & ~CRAMFS_SUPPORTED_FLAGS) { printf ("cramfs: unsupported filesystem features\n"); return -1; } /* Check that the root inode is in a sane state */ - if (!S_ISDIR (CRAMFS_16 (super.root.mode))) { + if (!S_ISDIR (CRAMFS_16 (super->root.mode))) { printf ("cramfs: root is not a directory\n"); return -1; } - root_offset = CRAMFS_GET_OFFSET (&(super.root)) << 2; + root_offset = CRAMFS_GET_OFFSET (&(super->root)) << 2; if (root_offset == 0) { printf ("cramfs: empty filesystem"); - } else if (!(super.flags & CRAMFS_FLAG_SHIFTED_ROOT_OFFSET) && + } else if (!(super->flags & CRAMFS_FLAG_SHIFTED_ROOT_OFFSET) && ((root_offset != sizeof (struct cramfs_super)) && (root_offset != 512 + sizeof (struct cramfs_super)))) { printf ("cramfs: bad root offset %lu\n", root_offset); @@ -153,61 +161,10 @@ static unsigned long cramfs_resolve (unsigned long begin, unsigned long offset, inodeoffset = nextoffset; } + printf ("can't find corresponding entry\n"); return 0; } -static int cramfs_uncompress (unsigned long begin, unsigned long offset, - unsigned long loadoffset) -{ - struct cramfs_inode *inode = (struct cramfs_inode *) (begin + offset); - unsigned long *block_ptrs = (unsigned long *) - (begin + (CRAMFS_GET_OFFSET (inode) << 2)); - unsigned long curr_block = (CRAMFS_GET_OFFSET (inode) + - (((CRAMFS_24 (inode->size)) + - 4095) >> 12)) << 2; - int size, total_size = 0; - int i; - - cramfs_uncompress_init (); - - for (i = 0; i < ((CRAMFS_24 (inode->size) + 4095) >> 12); i++) { - size = cramfs_uncompress_block ((void *) loadoffset, - (void *) (begin + curr_block), - (CRAMFS_32 (block_ptrs[i]) - - curr_block)); - if (size < 0) - return size; - loadoffset += size; - total_size += size; - curr_block = CRAMFS_32 (block_ptrs[i]); - } - - cramfs_uncompress_exit (); - return total_size; -} - -int cramfs_load (char *loadoffset, struct device_d *dev, const char *filename) -{ - unsigned long offset; - char *f; - if (cramfs_read_super (dev)) - return -1; - - f = strdup(filename); - offset = cramfs_resolve (dev->map_base, - CRAMFS_GET_OFFSET (&(super.root)) << 2, - CRAMFS_24 (super.root.size), 0, - strtok (f, "/")); - - free(f); - - if (offset <= 0) - return offset; - - return cramfs_uncompress (dev->map_base, offset, - (unsigned long) loadoffset); -} - static int cramfs_fill_dirent (struct device_d *dev, unsigned long offset, struct dirent *d) { struct cramfs_inode *inode = (struct cramfs_inode *) @@ -232,8 +189,6 @@ static int cramfs_fill_dirent (struct device_d *dev, unsigned long offset, struc namelen--; } - d->mode = CRAMFS_16 (inode->mode); - d->size = CRAMFS_24 (inode->size); memset(d->name, 0, 256); strncpy(d->name, name, namelen); @@ -250,6 +205,7 @@ struct cramfs_dir { struct dir* cramfs_opendir(struct device_d *_dev, const char *filename) { char *f; + struct cramfs_priv *priv = _dev->priv; struct fs_device_d *fsdev = _dev->type_data; struct device_d *dev = fsdev->parent; @@ -259,14 +215,14 @@ struct dir* cramfs_opendir(struct device_d *_dev, const char *filename) if (strlen (filename) == 0 || !strcmp (filename, "/")) { /* Root directory. Use root inode in super block */ - dir->offset = CRAMFS_GET_OFFSET (&(super.root)) << 2; - dir->size = CRAMFS_24 (super.root.size); + dir->offset = CRAMFS_GET_OFFSET (&(priv->super.root)) << 2; + dir->size = CRAMFS_24 (priv->super.root.size); } else { f = strdup(filename); /* Resolve the path */ dir->offset = cramfs_resolve (dev->map_base, - CRAMFS_GET_OFFSET (&(super.root)) << - 2, CRAMFS_24 (super.root.size), 1, + CRAMFS_GET_OFFSET (&(priv->super.root)) << + 2, CRAMFS_24 (priv->super.root.size), 1, strtok (f, "/")); free(f); if (dir->offset <= 0) @@ -291,7 +247,7 @@ err_free: return NULL; } -struct dirent* cramfs_readdir(struct device_d *_dev, struct dir *_dir) +static struct dirent* cramfs_readdir(struct device_d *_dev, struct dir *_dir) { struct fs_device_d *fsdev = _dev->type_data; struct device_d *dev = fsdev->parent; @@ -311,14 +267,123 @@ struct dirent* cramfs_readdir(struct device_d *_dev, struct dir *_dir) return NULL; } -int cramfs_closedir(struct device_d *dev, struct dir *_dir) +static int cramfs_closedir(struct device_d *dev, struct dir *_dir) { struct cramfs_dir *dir = _dir->priv; free(dir); return 0; } -int cramfs_info (struct device_d *dev) +static int cramfs_open(struct device_d *_dev, FILE *file, const char *filename) +{ + struct cramfs_priv *priv = _dev->priv; + struct fs_device_d *fsdev = _dev->type_data; + struct device_d *dev = fsdev->parent; + char *f; + unsigned long offset; + + f = strdup(filename); + offset = cramfs_resolve (dev->map_base, + CRAMFS_GET_OFFSET (&(priv->super.root)) << 2, + CRAMFS_24 (priv->super.root.size), 0, + strtok (f, "/")); + + free(f); + + if (offset <= 0) + return -ENOENT; + + file->pos = 0; + file->inode = (struct cramfs_inode *)(dev->map_base + offset); + + return 0; +} + +static int cramfs_close(struct device_d *dev, FILE *f) +{ + return 0; +} + +static int cramfs_read(struct device_d *_dev, FILE *f, void *buf, size_t size) +{ + struct cramfs_priv *priv = _dev->priv; + struct fs_device_d *fsdev = _dev->type_data; + struct device_d *dev = fsdev->parent; + struct cramfs_inode *inode = (struct cramfs_inode *)f->inode; + unsigned int blocknr; + int outsize = 0; + unsigned long *block_ptrs = (unsigned long *) + (dev->map_base + (CRAMFS_GET_OFFSET (inode) << 2)); + int ofs = f->pos % 4096; + + if (f->pos + size > inode->size) + size = inode->size - f->pos; + + while (size) { + unsigned long base; + int copy; + + blocknr = f->pos >> 12; + if (blocknr != priv->curr_block || priv->inode != inode) { + if (blocknr) + base = CRAMFS_32 (block_ptrs[blocknr - 1]); + else + base = (CRAMFS_GET_OFFSET(inode) + (((CRAMFS_24 (inode->size)) + 4095) >> 12)) << 2; + + priv->curr_block_len = cramfs_uncompress_block (priv->buf, + (void *)(dev->map_base + base), 4096); + +// printf("READ blocknr: %d len %d\n",blocknr,priv->curr_block_len ); + if (priv->curr_block_len <= 0) + break; + + priv->curr_block = blocknr; + priv->inode = inode; + } + + copy = min(priv->curr_block_len, size); + + memcpy(buf, priv->buf + ofs, copy); + ofs = 0; + + f->pos += copy; + outsize += copy; + size -= copy; + buf += copy; + } + + return outsize; +} + +static int cramfs_stat(struct device_d *_dev, const char *filename, struct stat *stat) +{ + struct cramfs_priv *priv = _dev->priv; + struct fs_device_d *fsdev = _dev->type_data; + struct device_d *dev = fsdev->parent; + struct cramfs_inode *inode; + char *f; + unsigned long offset; + + 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); + + if (offset < 0) + return -ENOENT; + + inode = (struct cramfs_inode *) (dev->map_base + offset); + + stat->st_mode = CRAMFS_16 (inode->mode); + stat->st_size = CRAMFS_24 (inode->size); + + return 0; +} +#if 0 +static int cramfs_info (struct device_d *dev) { if (cramfs_read_super (dev)) return 0; @@ -343,32 +408,53 @@ int cramfs_info (struct device_d *dev) return 1; } +#endif int cramfs_probe(struct device_d *dev) { struct fs_device_d *fsdev; - - printf("%s: dev: %p\n",__FUNCTION__, dev); + struct cramfs_priv *priv; fsdev = dev->type_data; - printf("%s: fsdev: %p\n",__FUNCTION__, fsdev); - if (cramfs_read_super (fsdev->parent)) { + priv = malloc(sizeof(struct cramfs_priv)); + dev->priv = priv; + + if (cramfs_read_super (fsdev->parent, priv)) { printf("no valid cramfs found on %s\n",dev->id); + free(priv); return -EINVAL; } + priv->curr_block = -1; + + cramfs_uncompress_init (); + return 0; +} + +int cramfs_remove(struct device_d *dev) +{ + struct cramfs_priv *priv = dev->priv; + + cramfs_uncompress_exit (); + free(priv); + return 0; } static struct fs_driver_d cramfs_driver = { .type = FS_TYPE_CRAMFS, + .open = cramfs_open, + .close = cramfs_close, + .read = cramfs_read, .opendir = cramfs_opendir, .readdir = cramfs_readdir, .closedir = cramfs_closedir, + .stat = cramfs_stat, .drv = { .type = DEVICE_TYPE_FS, .probe = cramfs_probe, + .remove = cramfs_remove, .name = "cramfs", .type_data = &cramfs_driver, } diff --git a/fs/fs.c b/fs/fs.c index 0bc9d200f..4ed3e39f4 100644 --- a/fs/fs.c +++ b/fs/fs.c @@ -1,5 +1,4 @@ #include -#include #include #include #include @@ -37,11 +36,35 @@ char *mkmodestr(unsigned long mode, char *str) return str; } -struct mtab_entry { - char path[PATH_MAX]; - struct mtab_entry *next; - struct device_d *dev; -}; +/* + * - Remove all multiple slashes + * - Remove trailing slashes (except path consists of only + * a single slash) + * - TODO: illegal characters? + */ +void normalise_path(char *path) +{ + char *out = path, *in = path; + + while(*in) { + if(*in == '/') { + *out++ = *in++; + while(*in == '/') + in++; + } else { + *out++ = *in++; + } + } + + /* + * Remove trailing slash, but only if + * we were given more than a single slash + */ + if (out > path + 1 && *(out - 1) == '/') + *(out - 1) = 0; + + *out = 0; +} static struct mtab_entry *mtab; @@ -72,30 +95,149 @@ struct mtab_entry *get_mtab_entry_by_path(const char *_path) return match ? match : mtab; } +FILE files[MAX_FILES]; + +FILE *get_file(void) +{ + int i; + + for (i = 3; i < MAX_FILES; i++) { + if (!files[i].used) { + files[i].used = 1; + files[i].no = i; + memset(&files[i], 0, sizeof(FILE)); + return &files[i]; + } + } + return NULL; +} + +void put_file(FILE *f) +{ + files[f->no].used = 0; +} + +int open(const char *pathname, int flags) +{ + struct device_d *dev; + struct fs_driver_d *fsdrv; + struct mtab_entry *e; + FILE *f; + int ret; + + f = get_file(); + if (!f) { + errno = -EMFILE; + return errno; + } + + if (!strncmp(pathname, "/dev/", 5)) { + dev = get_device_by_id(pathname + 5); + f->dev = dev; + } else { + e = get_mtab_entry_by_path(pathname); + if (!e) { + errno = -ENOENT; + goto out; + } + + 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; + } + } + + return f->no; + +out: + put_file(f); + return errno; +} + +int read(int fd, void *buf, size_t count) +{ + struct device_d *dev; + struct fs_driver_d *fsdrv; + FILE *f = &files[fd]; + + dev = f->dev; + if (dev->type == DEVICE_TYPE_FS) { + fsdrv = (struct fs_driver_d *)dev->driver->type_data; + errno = fsdrv->read(dev, f, buf, count); + return errno; + } else { + errno = dev->driver->read(dev, buf, count, f->pos, 0); /* FIXME: flags */ + if (errno > 0) + f->pos += errno; + return errno; + } +} + +ssize_t write(int fd, const void *buf, size_t count) +{ + return -EROFS; +} + +int close(int fd) +{ + struct device_d *dev; + struct fs_driver_d *fsdrv; + FILE *f = &files[fd]; + + dev = f->dev; + fsdrv = (struct fs_driver_d *)dev->driver->type_data; + + put_file(f); + return fsdrv->close(dev, f); +} + int mount (struct device_d *dev, char *fsname, char *path) { struct driver_d *drv; struct fs_driver_d *fs_drv; struct mtab_entry *entry; struct fs_device_d *fsdev; + struct dir *dir; int ret; + errno = 0; + drv = get_driver_by_name(fsname); if (!drv) { - printf("no driver for fstype %s\n", fsname); - return -EINVAL; + errno = -ENODEV; + goto out; } if (drv->type != DEVICE_TYPE_FS) { - printf("driver %s is no filesystem driver\n"); - return -EINVAL; + errno = -EINVAL; + goto out; } - /* check if path exists */ - /* TODO */ + if (mtab) { + /* check if path exists and is a directory */ + if (!(dir = opendir(path))) { + errno = -ENOTDIR; + goto out; + } + closedir(dir); + } else { + /* no mtab, so we only allow to mount on '/' */ + if (*path != '/' || *(path + 1)) { + errno = -ENOTDIR; + goto out; + } + } fs_drv = drv->type_data; - printf("mount: fs_drv: %p\n", fs_drv); if (fs_drv->flags & FS_DRIVER_NO_DEV) { dev = malloc(sizeof(struct device_d)); @@ -104,12 +246,14 @@ int mount (struct device_d *dev, char *fsname, char *path) dev->type = DEVICE_TYPE_FS; if ((ret = register_device(dev))) { free(dev); - return ret; + errno = ret; + goto out; } if (!dev->driver) { /* driver didn't accept the device. Bail out */ free(dev); - return -EINVAL; + errno = -EINVAL; + goto out; } } else { fsdev = malloc(sizeof(struct fs_device_d)); @@ -120,12 +264,14 @@ int mount (struct device_d *dev, char *fsname, char *path) fsdev->dev.type_data = fsdev; if ((ret = register_device(&fsdev->dev))) { free(fsdev); - return ret; + errno = ret; + goto out; } if (!fsdev->dev.driver) { /* driver didn't accept the device. Bail out */ free(fsdev); - return -EINVAL; + errno = -EINVAL; + goto out; } dev = &fsdev->dev; } @@ -144,28 +290,38 @@ int mount (struct device_d *dev, char *fsname, char *path) e = e->next; e->next = entry; } - - printf("mount: mtab->dev: %p\n", mtab->dev); - - return 0; +out: + return errno; } -int do_mount (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +int umount(const char *pathname) { - struct device_d *dev; - int ret = 0; + struct mtab_entry *entry = mtab; + struct mtab_entry *last = mtab; + char *p = strdup(pathname); - if (argc != 4) { - printf ("Usage:\n%s\n", cmdtp->usage); - return 1; + normalise_path(p); + + while(entry && strcmp(p, entry->path)) { + last = entry; + entry = entry->next; } - dev = get_device_by_id(argv[1]); + free(p); - if ((ret = mount(dev, argv[2], argv[3]))) { - perror("mount", ret); - return 1; + if (!entry) { + errno = -EFAULT; + return errno; } + + if (entry == mtab) + mtab = mtab->next; + else + last->next = entry->next; + + unregister_device(entry->dev); + free(entry); + return 0; } @@ -207,20 +363,59 @@ int closedir(struct dir *dir) return dir->fsdrv->closedir(dir->dev, dir); } -static int ls(const char *path) +int stat(const char *filename, struct stat *s) +{ + struct device_d *dev; + struct fs_driver_d *fsdrv; + struct mtab_entry *e; + char *f = strdup(filename); + + memset(s, 0, sizeof(struct stat)); + + normalise_path(f); + + e = get_mtab_entry_by_path(f); + if (!e) { + errno = -ENOENT; + goto out; + } + if (e != mtab) + f += strlen(e->path); + + dev = e->dev; + + fsdrv = (struct fs_driver_d *)dev->driver->type_data; + + errno = fsdrv->stat(dev, f, s); +out: + free(f); + return errno; +} + +int ls(const char *path) { struct dir *dir; struct dirent *d; char modestr[11]; + char tmp[PATH_MAX]; + struct stat s; dir = opendir(path); - if (!dir) + if (!dir) { + errno = -ENOENT; return -ENOENT; + } while ((d = readdir(dir))) { unsigned long namelen = strlen(d->name); - mkmodestr(d->mode, modestr); - printf("%s %8d %*.*s\n",modestr, d->size, namelen, namelen, d->name); + sprintf(tmp, "%s/%s", path, d->name); + if (stat(tmp, &s)) { + perror("stat"); + return errno; + } + + mkmodestr(s.st_mode, modestr); + printf("%s %8d %*.*s\n",modestr, s.st_size, namelen, namelen, d->name); } closedir(dir); @@ -228,25 +423,6 @@ static int ls(const char *path) return 0; } -int do_ls (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) -{ - int ret; - - ret = ls(argv[1]); - if (ret) { - perror("ls", ret); - return 1; - } - - return 0; -} - -U_BOOT_CMD( - ls, 2, 0, do_ls, - "ls - list a file or directory\n", - " list files on path" -); - int mkdir (const char *pathname) { struct fs_driver_d *fsdrv; @@ -254,8 +430,11 @@ int mkdir (const char *pathname) struct mtab_entry *e; e = get_mtab_entry_by_path(pathname); - if (!e) - return NULL; + if (!e) { + errno = -ENOENT; + return -ENOENT; + } + if (e != mtab) pathname += strlen(e->path); @@ -265,37 +444,8 @@ int mkdir (const char *pathname) if (fsdrv->mkdir) return fsdrv->mkdir(dev, pathname); + + errno = -EROFS; return -EROFS; } -int do_mkdir (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) -{ - int ret; - - ret = mkdir(argv[1]); - if (ret) { - perror("ls", ret); - return 1; - } - - return 0; -} - -U_BOOT_CMD( - mkdir, 2, 0, do_mkdir, - "mkdir - create a new directory\n", - "" -); - -U_BOOT_CMD( - mount, 4, 0, do_mount, - "mount - mount a filesystem to a device\n", - " add a filesystem of type 'type' on the given device" -); -#if 0 -U_BOOT_CMD( - delfs, 2, 0, do_delfs, - "delfs - delete a filesystem from a device\n", - "" -); -#endif diff --git a/fs/ramfs.c b/fs/ramfs.c index 7d3d2b673..d271b27bf 100644 --- a/fs/ramfs.c +++ b/fs/ramfs.c @@ -8,13 +8,6 @@ #include #include -struct handle_d { - int (*read)(struct handle_d *, ...); - int (*write)(struct handle_d *, ...); - - struct device_d *dev; -}; - struct data_d { char *data; ulong size; @@ -32,19 +25,6 @@ struct node_d { struct data_d *data; }; -struct filesystem_d { - int (*create)(struct device_d *dev, const char *pathname, mode_t mode); - struct handle_d *(*open)(struct device_d *dev, const char *pathname, mode_t mode); - int (*remove)(struct device_d *dev, const char *pathname); - int (*mknod)(struct device_d *dev, const char *pathname, struct handle_d *handle); - int (*ls)(struct device_d *dev, const char *pathname); -}; - -int create(const char *pathname, ulong mode); -struct handle_d *open(const char *pathname, ulong type); -int remove(const char *pathname); -int mknod(const char *pathname, struct handle_d *handle); - struct ramfs_priv { struct node_d root; }; @@ -88,36 +68,6 @@ out: return node; } -/* - * - Remove all multiple slashes - * - Remove trailing slashes (except path consists of only - * a single slash) - * - TODO: illegal characters? - */ -void normalise_path(char *path) -{ - char *out = path, *in = path; - - while(*in) { - if(*in == '/') { - *out++ = *in++; - while(*in == '/') - in++; - } else { - *out++ = *in++; - } - } - - /* - * Remove trailing slash, but only if - * we were given more than a single slash - */ - if (out > path + 1 && *(out - 1) == '/') - *(out - 1) = 0; - - *out = 0; -} - int node_add_child(struct node_d *node, const char *filename, ulong mode) { struct node_d *new_node = malloc(sizeof(struct node_d)); @@ -192,9 +142,9 @@ int ramfs_probe(struct device_d *dev) return 0; } -static struct handle_d *ramfs_open(struct device_d *dev, const char *pathname) +static int ramfs_open(struct device_d *_dev, FILE *file, const char *filename) { - return NULL; + return -ENOENT; } struct dir* ramfs_opendir(struct device_d *dev, const char *pathname) @@ -222,7 +172,6 @@ struct dirent* ramfs_readdir(struct device_d *dev, struct dir *dir) { if (dir->node) { strcpy(dir->d.name, dir->node->name); - dir->d.mode = dir->node->mode; dir->node = dir->node->next; return &dir->d; } @@ -235,6 +184,21 @@ int ramfs_closedir(struct device_d *dev, struct dir *dir) return 0; } +int ramfs_stat(struct device_d *dev, const char *filename, struct stat *s) +{ + struct ramfs_priv *priv = dev->priv; + struct node_d *node = rlookup(&priv->root, filename); + + if (!node) { + errno = -ENOENT; + return -ENOENT; + } + + s->st_mode = node->mode; + + return 0; +} + static struct fs_driver_d ramfs_driver = { .type = FS_TYPE_RAMFS, .create = ramfs_create, @@ -245,6 +209,7 @@ static struct fs_driver_d ramfs_driver = { .opendir = ramfs_opendir, .readdir = ramfs_readdir, .closedir = ramfs_closedir, + .stat = ramfs_stat, .flags = FS_DRIVER_NO_DEV, .drv = { @@ -262,21 +227,3 @@ int ramfs_init(void) device_initcall(ramfs_init); -/* --------- Testing --------- */ - -static int do_create ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) -{ -// int ret; - - printf("create %s\n",argv[1]); -// ret = ramfs_create(&ramfs_device, argv[1], S_IFDIR); -// perror("create", ret); - return 0; -} - -U_BOOT_CMD( - create, 2, 0, do_create, - "ls - list a file or directory\n", - " list files on device" -); - diff --git a/include/common.h b/include/common.h index c45850169..d1f9cdc29 100644 --- a/include/common.h +++ b/include/common.h @@ -593,7 +593,7 @@ void vprintf(const char *fmt, va_list args); #define stdin 0 #define stdout 1 #define stderr 2 -#define MAX_FILES 3 +#define MAX_FILES 16 void fprintf(int file, const char *fmt, ...); void fputs(int file, const char *s); diff --git a/include/driver.h b/include/driver.h index c7ede1acc..a37a7cd0b 100644 --- a/include/driver.h +++ b/include/driver.h @@ -48,6 +48,7 @@ struct driver_d { struct driver_d *next; int (*probe) (struct device_d *); + int (*remove)(struct device_d *); ssize_t (*read) (struct device_d*, void* buf, size_t count, ulong offset, ulong flags); ssize_t (*write) (struct device_d*, void* buf, size_t count, ulong offset, ulong flags); ssize_t (*erase) (struct device_d*, size_t count, unsigned long offset); @@ -74,13 +75,13 @@ void unregister_device(struct device_d *); struct device_d *device_from_spec_str(const char *str, char **endp); struct device_d *get_device_by_name(char *name); struct device_d *get_device_by_type(ulong type, struct device_d *last); -struct device_d *get_device_by_id(char *id); +struct device_d *get_device_by_id(const char *id); struct driver_d *get_driver_by_name(char *name); -ssize_t read(struct device_d *dev, void *buf, size_t count, ulong offset, ulong flags); -ssize_t write(struct device_d *dev, void *buf, size_t count, ulong offset, ulong flags); -ssize_t erase(struct device_d *dev, size_t count, unsigned long offset); +ssize_t dev_read(struct device_d *dev, void *buf, size_t count, ulong offset, ulong flags); +ssize_t dev_write(struct device_d *dev, void *buf, size_t count, ulong offset, ulong flags); +ssize_t dev_erase(struct device_d *dev, size_t count, unsigned long offset); ssize_t mem_read(struct device_d *dev, void *buf, size_t count, ulong offset, ulong flags); ssize_t mem_write(struct device_d *dev, void *buf, size_t count, ulong offset, ulong flags); diff --git a/include/errno.h b/include/errno.h index aee5c78ff..56ed0ed9d 100644 --- a/include/errno.h +++ b/include/errno.h @@ -1,6 +1,8 @@ #ifndef __ERRNO_H #define __ERRNO_H -void perror(const char *s, int errno); +extern int errno; + +void perror(const char *s); #endif /* __ERRNO_H */ diff --git a/include/fs.h b/include/fs.h index c600a9dd9..22e5fcf07 100644 --- a/include/fs.h +++ b/include/fs.h @@ -10,10 +10,9 @@ struct partition; struct node_d; +struct stat; struct dirent { - unsigned long mode; - unsigned long size; char name[256]; }; @@ -25,20 +24,32 @@ struct dir { void *priv; /* private data for the fs driver */ }; +typedef struct filep { + struct device_d *dev; + ulong pos; + char used; + int no; + void *inode; /* private to the filesystem driver */ +} FILE; + #define FS_DRIVER_NO_DEV 1 struct fs_driver_d { ulong type; char *name; - int (*load) (char *dst, struct device_d *dev, const char *filename); int (*probe) (struct device_d *dev); int (*create)(struct device_d *dev, const char *pathname, ulong type); int (*mkdir)(struct device_d *dev, const char *pathname); - struct handle_d *(*open)(struct device_d *dev, const char *pathname); + + 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, void *buf, size_t size); struct dir* (*opendir)(struct device_d *dev, const char *pathname); struct dirent* (*readdir)(struct device_d *dev, struct dir *dir); int (*closedir)(struct device_d *dev, struct dir *dir); + int (*stat)(struct device_d *dev, const char *file, struct stat *stat); struct driver_d drv; @@ -52,11 +63,29 @@ struct fs_device_d { struct fs_driver_d *driver; }; -int register_filesystem(struct device_d *dev, char *fsname); -//int unregister_filesystem(struct device_d *dev); +int open(const char *pathname, int flags); +int close(int fd); +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); +int mkdir (const char *pathname); +int mount (struct device_d *dev, char *fsname, char *path); +int umount(const char *pathname); -int register_fs_driver(struct fs_driver_d *new_fs_drv); +struct dir *opendir(const char *pathname); +struct dirent *readdir(struct dir *dir); +int closedir(struct dir *dir); char *mkmodestr(unsigned long mode, char *str); +struct mtab_entry *get_mtab_entry_by_path(const char *path); + +struct mtab_entry { + char path[PATH_MAX]; + struct mtab_entry *next; + struct device_d *dev; +}; + +void normalise_path(char *path); + #endif /* __FS_H */ diff --git a/lib_generic/misc.c b/lib_generic/misc.c index 6df4f5c15..92a8374a1 100644 --- a/lib_generic/misc.c +++ b/lib_generic/misc.c @@ -5,6 +5,7 @@ #include #include #include +#include #include int cmd_get_data_size(char* arg, int default_size) @@ -32,7 +33,7 @@ int cmd_get_data_size(char* arg, int default_size) static struct device_d *first_device = NULL; static struct driver_d *first_driver = NULL; -struct device_d *get_device_by_id(char *id) +struct device_d *get_device_by_id(const char *id) { struct device_d *d; @@ -357,25 +358,28 @@ out: return 0; } -ssize_t read(struct device_d *dev, void *buf, size_t count, unsigned long offset, ulong flags) +ssize_t dev_read(struct device_d *dev, void *buf, size_t count, unsigned long offset, ulong flags) { if (dev->driver->read) return dev->driver->read(dev, buf, count, offset, flags); - return -1; + errno = -ENOSYS; + return -ENOSYS; } -ssize_t write(struct device_d *dev, void *buf, size_t count, unsigned long offset, ulong flags) +ssize_t dev_write(struct device_d *dev, void *buf, size_t count, unsigned long offset, ulong flags) { if (dev->driver->write) return dev->driver->write(dev, buf, count, offset, flags); - return -1; + errno = -ENOSYS; + return -ENOSYS; } -ssize_t erase(struct device_d *dev, size_t count, unsigned long offset) +ssize_t dev_erase(struct device_d *dev, size_t count, unsigned long offset) { if (dev->driver->erase) return dev->driver->erase(dev, count, offset); - return -1; + errno = -ENOSYS; + return -ENOSYS; } int dummy_probe(struct device_d *dev) @@ -414,7 +418,12 @@ struct param_d* dev_get_param(struct device_d *dev, char *name) { struct param_d *param = get_param_by_name(dev, name); - if (param && param->get) + if (!param) { + errno = -EINVAL; + return NULL; + } + + if (param->get) return param->get(dev, param); return param; @@ -424,8 +433,10 @@ IPaddr_t dev_get_param_ip(struct device_d *dev, char *name) { struct param_d *param = dev_get_param(dev, name); - if (!param || param->type != PARAM_TYPE_IPADDR) - return -1; + if (!param || param->type != PARAM_TYPE_IPADDR) { + errno = -EINVAL; + return 0; + } return param->value.val_ip; } @@ -443,11 +454,15 @@ int dev_set_param(struct device_d *dev, char *name, value_t val) { struct param_d *param = get_param_by_name(dev, name); - if (!param) + if (!param) { + errno = -EINVAL; return -EINVAL; + } - if (param->flags & PARAM_FLAG_RO) + if (param->flags & PARAM_FLAG_RO) { + errno = -EACCES; return -EACCES; + } if (param->set) return param->set(dev, param, val); diff --git a/net/tftp.c b/net/tftp.c index ba1ececc0..e58b38030 100644 --- a/net/tftp.c +++ b/net/tftp.c @@ -65,7 +65,7 @@ store_block (unsigned block, uchar * src, unsigned len) ulong offset = block * TFTP_BLOCK_SIZE + TftpBlockWrapOffset; ulong newsize = offset + len; - write(net_store_mem.device, src, len, net_store_mem.start + offset, 0); + dev_write(net_store_mem.device, src, len, net_store_mem.start + offset, 0); if (NetBootFileXferSize < newsize) NetBootFileXferSize = newsize;