parent
225b192272
commit
9db8ed3312
|
@ -209,11 +209,11 @@ int cramfs_load (char *loadoffset, struct device_d *dev, const char *filename)
|
|||
(unsigned long) loadoffset);
|
||||
}
|
||||
|
||||
static int cramfs_list_inode (struct device_d *dev, unsigned long offset)
|
||||
static int cramfs_fill_dirent (struct device_d *dev, unsigned long offset, struct dirent *d)
|
||||
{
|
||||
struct cramfs_inode *inode = (struct cramfs_inode *)
|
||||
(dev->map_base + offset);
|
||||
char *name, str[20];
|
||||
char *name;
|
||||
int namelen, nextoff;
|
||||
|
||||
/*
|
||||
|
@ -233,80 +233,89 @@ static int cramfs_list_inode (struct device_d *dev, unsigned long offset)
|
|||
namelen--;
|
||||
}
|
||||
|
||||
printf (" %s %8d %*.*s", mkmodestr (CRAMFS_16 (inode->mode), str),
|
||||
CRAMFS_24 (inode->size), namelen, namelen, name);
|
||||
|
||||
if ((CRAMFS_16 (inode->mode) & S_IFMT) == S_IFLNK) {
|
||||
/* symbolic link.
|
||||
* Unpack the link target, trusting in the inode's size field.
|
||||
*/
|
||||
unsigned long size = CRAMFS_24 (inode->size);
|
||||
char *link = malloc (size);
|
||||
|
||||
if (link != NULL && cramfs_uncompress (dev->map_base, offset,
|
||||
(unsigned long) link)
|
||||
== size)
|
||||
printf (" -> %*.*s\n", (int) size, (int) size, link);
|
||||
else
|
||||
printf (" [Error reading link]\n");
|
||||
if (link)
|
||||
free (link);
|
||||
} else
|
||||
printf ("\n");
|
||||
d->mode = CRAMFS_16 (inode->mode);
|
||||
d->size = CRAMFS_24 (inode->size);
|
||||
memset(d->name, 0, 256);
|
||||
strncpy(d->name, name, namelen);
|
||||
|
||||
return nextoff;
|
||||
}
|
||||
|
||||
int cramfs_ls (struct device_d *dev, const char *filename)
|
||||
{
|
||||
struct cramfs_dir {
|
||||
struct cramfs_inode *inode;
|
||||
unsigned long inodeoffset = 0, nextoffset;
|
||||
unsigned long offset, size;
|
||||
unsigned long inodeoffset;
|
||||
struct dir dir;
|
||||
};
|
||||
|
||||
struct dir* cramfs_opendir(struct device_d *_dev, const char *filename)
|
||||
{
|
||||
char *f;
|
||||
struct fs_device_d *fsdev = _dev->type_data;
|
||||
struct device_d *dev = fsdev->parent;
|
||||
|
||||
printf("cramfs_ls: %s\n", filename);
|
||||
|
||||
if (cramfs_read_super (dev))
|
||||
return -1;
|
||||
struct cramfs_dir *dir = malloc(sizeof(struct cramfs_dir));
|
||||
memset(dir, 0, sizeof(struct cramfs_dir));
|
||||
dir->dir.priv = dir;
|
||||
|
||||
if (strlen (filename) == 0 || !strcmp (filename, "/")) {
|
||||
/* Root directory. Use root inode in super block */
|
||||
offset = CRAMFS_GET_OFFSET (&(super.root)) << 2;
|
||||
size = CRAMFS_24 (super.root.size);
|
||||
dir->offset = CRAMFS_GET_OFFSET (&(super.root)) << 2;
|
||||
dir->size = CRAMFS_24 (super.root.size);
|
||||
} else {
|
||||
f = strdup(filename);
|
||||
/* Resolve the path */
|
||||
offset = cramfs_resolve (dev->map_base,
|
||||
dir->offset = cramfs_resolve (dev->map_base,
|
||||
CRAMFS_GET_OFFSET (&(super.root)) <<
|
||||
2, CRAMFS_24 (super.root.size), 1,
|
||||
strtok (f, "/"));
|
||||
free(f);
|
||||
if (offset <= 0)
|
||||
return offset;
|
||||
if (dir->offset <= 0)
|
||||
goto err_free;
|
||||
|
||||
/* Resolving was successful. Examine the inode */
|
||||
inode = (struct cramfs_inode *) (dev->map_base + offset);
|
||||
if (!S_ISDIR (CRAMFS_16 (inode->mode))) {
|
||||
/* It's not a directory - list it, and that's that */
|
||||
return (cramfs_list_inode (dev, offset) > 0);
|
||||
dir->inode = (struct cramfs_inode *) (dev->map_base + dir->offset);
|
||||
if (!S_ISDIR (CRAMFS_16 (dir->inode->mode))) {
|
||||
/* It's not a directory */
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
/* It's a directory. List files within */
|
||||
offset = CRAMFS_GET_OFFSET (inode) << 2;
|
||||
size = CRAMFS_24 (inode->size);
|
||||
dir->offset = CRAMFS_GET_OFFSET (dir->inode) << 2;
|
||||
dir->size = CRAMFS_24 (dir->inode->size);
|
||||
}
|
||||
|
||||
return &dir->dir;
|
||||
|
||||
err_free:
|
||||
free(dir);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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;
|
||||
struct cramfs_dir *dir = _dir->priv;
|
||||
unsigned long nextoffset;
|
||||
|
||||
/* List the given directory */
|
||||
while (inodeoffset < size) {
|
||||
inode = (struct cramfs_inode *) (dev->map_base + offset +
|
||||
inodeoffset);
|
||||
if (dir->inodeoffset < dir->size) {
|
||||
dir->inode = (struct cramfs_inode *) (dev->map_base + dir->offset +
|
||||
dir->inodeoffset);
|
||||
|
||||
nextoffset = cramfs_list_inode (dev, offset + inodeoffset);
|
||||
if (nextoffset == 0)
|
||||
break;
|
||||
inodeoffset += sizeof (struct cramfs_inode) + nextoffset;
|
||||
nextoffset = cramfs_fill_dirent (dev, dir->offset + dir->inodeoffset, &_dir->d);
|
||||
|
||||
dir->inodeoffset += sizeof (struct cramfs_inode) + nextoffset;
|
||||
return &_dir->d;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int cramfs_closedir(struct device_d *dev, struct dir *_dir)
|
||||
{
|
||||
struct cramfs_dir *dir = _dir->priv;
|
||||
free(dir);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -338,7 +347,14 @@ int cramfs_info (struct device_d *dev)
|
|||
|
||||
int cramfs_probe(struct device_d *dev)
|
||||
{
|
||||
if (cramfs_read_super (dev)) {
|
||||
struct fs_device_d *fsdev;
|
||||
|
||||
printf("%s: dev: %p\n",__FUNCTION__, dev);
|
||||
|
||||
fsdev = dev->type_data;
|
||||
printf("%s: fsdev: %p\n",__FUNCTION__, fsdev);
|
||||
|
||||
if (cramfs_read_super (fsdev->parent)) {
|
||||
printf("no valid cramfs found on %s\n",dev->id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -347,19 +363,21 @@ int cramfs_probe(struct device_d *dev)
|
|||
}
|
||||
|
||||
static struct fs_driver_d cramfs_driver = {
|
||||
.type = FS_TYPE_CRAMFS,
|
||||
.probe = cramfs_probe,
|
||||
.ls = cramfs_ls,
|
||||
.type = FS_TYPE_CRAMFS,
|
||||
.opendir = cramfs_opendir,
|
||||
.readdir = cramfs_readdir,
|
||||
.closedir = cramfs_closedir,
|
||||
.drv = {
|
||||
.type = DEVICE_TYPE_FS,
|
||||
.probe = cramfs_probe,
|
||||
.name = "cramfs",
|
||||
.driver_data = &cramfs_driver,
|
||||
.type_data = &cramfs_driver,
|
||||
}
|
||||
};
|
||||
|
||||
int cramfs_init(void)
|
||||
{
|
||||
return register_fs_driver(&cramfs_driver);
|
||||
return register_driver(&cramfs_driver.drv);
|
||||
}
|
||||
|
||||
device_initcall(cramfs_init);
|
||||
|
|
250
fs/fs.c
250
fs/fs.c
|
@ -37,26 +37,48 @@ char *mkmodestr(unsigned long mode, char *str)
|
|||
return str;
|
||||
}
|
||||
|
||||
static int fs_probe(struct device_d *dev)
|
||||
{
|
||||
struct fs_device_d *fs_dev = dev->platform_data;
|
||||
struct mtab_entry {
|
||||
char path[PATH_MAX];
|
||||
struct mtab_entry *next;
|
||||
struct device_d *dev;
|
||||
};
|
||||
|
||||
return fs_dev->driver->probe(fs_dev->parent);
|
||||
static struct mtab_entry *mtab;
|
||||
|
||||
struct mtab_entry *get_mtab_entry_by_path(const char *_path)
|
||||
{
|
||||
struct mtab_entry *match = NULL, *e = mtab;
|
||||
char *path, *tok;
|
||||
|
||||
if (*_path != '/')
|
||||
return NULL;
|
||||
|
||||
path = strdup(_path);
|
||||
|
||||
tok = strchr(path + 1, '/');
|
||||
if (tok)
|
||||
*tok = 0;
|
||||
|
||||
while (e) {
|
||||
if (!strcmp(path, e->path)) {
|
||||
match = e;
|
||||
break;
|
||||
}
|
||||
e = e->next;
|
||||
}
|
||||
|
||||
free(path);
|
||||
|
||||
return match ? match : mtab;
|
||||
}
|
||||
|
||||
int register_fs_driver(struct fs_driver_d *new_fs_drv)
|
||||
int mount (struct device_d *dev, char *fsname, char *path)
|
||||
{
|
||||
new_fs_drv->drv.probe = fs_probe;
|
||||
new_fs_drv->drv.driver_data = new_fs_drv;
|
||||
|
||||
return register_driver(&new_fs_drv->drv);
|
||||
}
|
||||
|
||||
int register_filesystem(struct device_d *dev, char *fsname)
|
||||
{
|
||||
struct fs_device_d *new_fs_dev;
|
||||
struct driver_d *drv;
|
||||
struct fs_driver_d *fs_drv;
|
||||
struct mtab_entry *entry;
|
||||
struct fs_device_d *fsdev;
|
||||
int ret;
|
||||
|
||||
drv = get_driver_by_name(fsname);
|
||||
if (!drv) {
|
||||
|
@ -69,72 +91,146 @@ int register_filesystem(struct device_d *dev, char *fsname)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
new_fs_dev = malloc(sizeof(struct fs_device_d));
|
||||
/* check if path exists */
|
||||
/* TODO */
|
||||
|
||||
fs_drv = drv->driver_data;
|
||||
fs_drv = drv->type_data;
|
||||
printf("mount: fs_drv: %p\n", fs_drv);
|
||||
|
||||
new_fs_dev->driver = fs_drv;
|
||||
new_fs_dev->parent = dev;
|
||||
new_fs_dev->dev.platform_data = new_fs_dev;
|
||||
new_fs_dev->dev.type = DEVICE_TYPE_FS;
|
||||
sprintf(new_fs_dev->dev.name, "%s", fsname);
|
||||
sprintf(new_fs_dev->dev.id, "%s", "fs0");
|
||||
|
||||
register_device(&new_fs_dev->dev);
|
||||
|
||||
if (!new_fs_dev->dev.driver) {
|
||||
unregister_device(&new_fs_dev->dev);
|
||||
return -ENODEV;
|
||||
if (fs_drv->flags & FS_DRIVER_NO_DEV) {
|
||||
dev = malloc(sizeof(struct device_d));
|
||||
memset(dev, 0, sizeof(struct device_d));
|
||||
sprintf(dev->name, "%s", fsname);
|
||||
dev->type = DEVICE_TYPE_FS;
|
||||
if ((ret = register_device(dev))) {
|
||||
free(dev);
|
||||
return ret;
|
||||
}
|
||||
if (!dev->driver) {
|
||||
/* driver didn't accept the device. Bail out */
|
||||
free(dev);
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
fsdev = malloc(sizeof(struct fs_device_d));
|
||||
memset(fsdev, 0, sizeof(struct fs_device_d));
|
||||
fsdev->parent = dev;
|
||||
sprintf(fsdev->dev.name, "%s", fsname);
|
||||
fsdev->dev.type = DEVICE_TYPE_FS;
|
||||
fsdev->dev.type_data = fsdev;
|
||||
if ((ret = register_device(&fsdev->dev))) {
|
||||
free(fsdev);
|
||||
return ret;
|
||||
}
|
||||
if (!fsdev->dev.driver) {
|
||||
/* driver didn't accept the device. Bail out */
|
||||
free(fsdev);
|
||||
return -EINVAL;
|
||||
}
|
||||
dev = &fsdev->dev;
|
||||
}
|
||||
|
||||
/* add mtab entry */
|
||||
entry = malloc(sizeof(struct mtab_entry));
|
||||
sprintf(entry->path, "%s", path);
|
||||
entry->dev = dev;
|
||||
entry->next = NULL;
|
||||
|
||||
if (!mtab)
|
||||
mtab = entry;
|
||||
else {
|
||||
struct mtab_entry *e = mtab;
|
||||
while (e->next)
|
||||
e = e->next;
|
||||
e->next = entry;
|
||||
}
|
||||
|
||||
printf("mount: mtab->dev: %p\n", mtab->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ls(struct device_d *dev, const char *filename)
|
||||
{
|
||||
struct fs_device_d *fs_dev;
|
||||
|
||||
if (!dev || dev->type != DEVICE_TYPE_FS || !dev->driver)
|
||||
return -ENODEV;
|
||||
|
||||
fs_dev = dev->platform_data;
|
||||
|
||||
return fs_dev->driver->ls(fs_dev->parent, filename);
|
||||
}
|
||||
|
||||
/* addfs <device> <fstype> */
|
||||
int do_addfs ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
int do_mount (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
struct device_d *dev;
|
||||
int ret = 0;
|
||||
|
||||
if (argc != 3) {
|
||||
if (argc != 4) {
|
||||
printf ("Usage:\n%s\n", cmdtp->usage);
|
||||
return 1;
|
||||
}
|
||||
|
||||
dev = get_device_by_id(argv[1]);
|
||||
if (!dev) {
|
||||
printf("no such device: %s\n", argv[1]);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if ((ret = register_filesystem(dev, argv[2]))) {
|
||||
perror("register_device", ret);
|
||||
if ((ret = mount(dev, argv[2], argv[3]))) {
|
||||
perror("mount", ret);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int do_ls ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
struct dir *opendir(const char *pathname)
|
||||
{
|
||||
struct device_d *dev;
|
||||
char *endp;
|
||||
struct fs_driver_d *fsdrv;
|
||||
struct dir *dir;
|
||||
struct mtab_entry *e;
|
||||
|
||||
e = get_mtab_entry_by_path(pathname);
|
||||
if (e != mtab)
|
||||
pathname += strlen(e->path);
|
||||
|
||||
dev = e->dev;
|
||||
// printf("opendir: dev: %p\n",dev);
|
||||
|
||||
fsdrv = (struct fs_driver_d *)dev->driver->type_data;
|
||||
// printf("opendir: fsdrv: %p\n",fsdrv);
|
||||
|
||||
dir = fsdrv->opendir(dev, pathname);
|
||||
if (dir) {
|
||||
dir->dev = dev;
|
||||
dir->fsdrv = fsdrv;
|
||||
}
|
||||
|
||||
return dir;
|
||||
}
|
||||
|
||||
struct dirent *readdir(struct dir *dir)
|
||||
{
|
||||
return dir->fsdrv->readdir(dir->dev, dir);
|
||||
}
|
||||
|
||||
int closedir(struct dir *dir)
|
||||
{
|
||||
return dir->fsdrv->closedir(dir->dev, dir);
|
||||
}
|
||||
|
||||
static int ls(const char *path)
|
||||
{
|
||||
struct dir *dir;
|
||||
struct dirent *d;
|
||||
char modestr[11];
|
||||
|
||||
dir = opendir(path);
|
||||
if (!dir)
|
||||
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);
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int do_ls (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
||||
{
|
||||
int ret;
|
||||
|
||||
dev = device_from_spec_str(argv[1], &endp);
|
||||
|
||||
ret = ls(dev, endp);
|
||||
ret = ls(argv[1]);
|
||||
if (ret) {
|
||||
perror("ls", ret);
|
||||
return 1;
|
||||
|
@ -146,13 +242,51 @@ int do_ls ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
|
|||
U_BOOT_CMD(
|
||||
ls, 2, 0, do_ls,
|
||||
"ls - list a file or directory\n",
|
||||
"<dev:path> list files on device"
|
||||
"<path> list files on path"
|
||||
);
|
||||
|
||||
int mkdir (const char *pathname)
|
||||
{
|
||||
struct fs_driver_d *fsdrv;
|
||||
struct device_d *dev;
|
||||
struct mtab_entry *e;
|
||||
|
||||
e = get_mtab_entry_by_path(pathname);
|
||||
if (e != mtab)
|
||||
pathname += strlen(e->path);
|
||||
|
||||
dev = e->dev;
|
||||
|
||||
fsdrv = (struct fs_driver_d *)dev->driver->type_data;
|
||||
|
||||
if (fsdrv->mkdir)
|
||||
return fsdrv->mkdir(dev, pathname);
|
||||
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(
|
||||
addfs, 3, 0, do_addfs,
|
||||
"addfs - add a filesystem to a device\n",
|
||||
" <device> <type> add a filesystem of type 'type' on the given device"
|
||||
mount, 4, 0, do_mount,
|
||||
"mount - mount a filesystem to a device\n",
|
||||
" <device> <type> <path> add a filesystem of type 'type' on the given device"
|
||||
);
|
||||
#if 0
|
||||
U_BOOT_CMD(
|
||||
|
|
|
@ -0,0 +1,282 @@
|
|||
#include <common.h>
|
||||
#include <driver.h>
|
||||
#include <init.h>
|
||||
#include <malloc.h>
|
||||
#include <fs.h>
|
||||
#include <command.h>
|
||||
#include <errno.h>
|
||||
#include <asm-generic/errno.h>
|
||||
#include <linux/stat.h>
|
||||
|
||||
struct handle_d {
|
||||
int (*read)(struct handle_d *, ...);
|
||||
int (*write)(struct handle_d *, ...);
|
||||
|
||||
struct device_d *dev;
|
||||
};
|
||||
|
||||
struct data_d {
|
||||
char *data;
|
||||
ulong size;
|
||||
struct data_d *next;
|
||||
};
|
||||
|
||||
struct node_d {
|
||||
char *name;
|
||||
struct node_d *next;
|
||||
struct node_d *child;
|
||||
ulong mode;
|
||||
|
||||
struct handle_d *handle;
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
/* ---------------------------------------------------------------*/
|
||||
struct node_d * __lookup(struct node_d *node, const char *name)
|
||||
{
|
||||
// printf("__lookup: %s in %p\n",name, node);
|
||||
node = node->child;
|
||||
if (!node || node->mode != S_IFDIR)
|
||||
return NULL;
|
||||
|
||||
while (node) {
|
||||
if (!strcmp(node->name, name))
|
||||
return node;
|
||||
node = node->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct node_d* rlookup(struct node_d *node, const char *path)
|
||||
{
|
||||
static char *buf;
|
||||
char *part;
|
||||
//printf("rlookup %s in %p\n",path, node);
|
||||
buf = strdup(path);
|
||||
|
||||
part = strtok(buf, "/");
|
||||
if (!part)
|
||||
goto out;
|
||||
|
||||
do {
|
||||
node = __lookup(node, part);
|
||||
if (!node)
|
||||
goto out;
|
||||
part = strtok(NULL, "/");
|
||||
} while(part);
|
||||
|
||||
out:
|
||||
free(buf);
|
||||
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));
|
||||
memset(new_node, 0, sizeof(struct node_d));
|
||||
new_node->name = strdup(filename);
|
||||
new_node->mode = mode;
|
||||
|
||||
// printf("node_add_child: %p -> %p\n", node, new_node);
|
||||
if (!node->child) {
|
||||
node->child = new_node;
|
||||
return 0;
|
||||
}
|
||||
|
||||
node = node->child;
|
||||
|
||||
while (node->next)
|
||||
node = node->next;
|
||||
|
||||
node->next = new_node;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------*/
|
||||
|
||||
int ramfs_create(struct device_d *dev, const char *pathname, ulong mode)
|
||||
{
|
||||
struct ramfs_priv *priv = dev->priv;
|
||||
char *path = strdup(pathname);
|
||||
char *file;
|
||||
struct node_d *node;
|
||||
|
||||
normalise_path(path);
|
||||
if (*path == '/')
|
||||
path++;
|
||||
|
||||
// printf("after normalise: %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;
|
||||
|
||||
return node_add_child(node, file, mode);
|
||||
}
|
||||
|
||||
int ramfs_mkdir(struct device_d *dev, const char *pathname)
|
||||
{
|
||||
return ramfs_create(dev, pathname, S_IFDIR);
|
||||
}
|
||||
|
||||
int ramfs_probe(struct device_d *dev)
|
||||
{
|
||||
struct ramfs_priv *priv = malloc(sizeof(struct ramfs_priv));
|
||||
|
||||
printf("ramfs_probe\n");
|
||||
memset(priv, 0, sizeof(struct ramfs_priv));
|
||||
|
||||
dev->priv = priv;
|
||||
|
||||
priv->root.name = "/";
|
||||
priv->root.mode = S_IFDIR;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct handle_d *ramfs_open(struct device_d *dev, const char *pathname)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct dir* ramfs_opendir(struct device_d *dev, const char *pathname)
|
||||
{
|
||||
struct dir *dir;
|
||||
struct ramfs_priv *priv = dev->priv;
|
||||
struct node_d *node = rlookup(&priv->root, pathname);
|
||||
|
||||
if (!node)
|
||||
return NULL;
|
||||
|
||||
if (node->mode != S_IFDIR)
|
||||
return NULL;
|
||||
|
||||
dir = malloc(sizeof(struct dir));
|
||||
if (!dir)
|
||||
return NULL;
|
||||
|
||||
dir->node = node->child;
|
||||
|
||||
return dir;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int ramfs_closedir(struct device_d *dev, struct dir *dir)
|
||||
{
|
||||
free(dir);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct fs_driver_d ramfs_driver = {
|
||||
.type = FS_TYPE_RAMFS,
|
||||
.create = ramfs_create,
|
||||
.open = ramfs_open,
|
||||
|
||||
.mkdir = ramfs_mkdir,
|
||||
|
||||
.opendir = ramfs_opendir,
|
||||
.readdir = ramfs_readdir,
|
||||
.closedir = ramfs_closedir,
|
||||
|
||||
.flags = FS_DRIVER_NO_DEV,
|
||||
.drv = {
|
||||
.type = DEVICE_TYPE_FS,
|
||||
.probe = ramfs_probe,
|
||||
.name = "ramfs",
|
||||
.type_data = &ramfs_driver,
|
||||
}
|
||||
};
|
||||
|
||||
int ramfs_init(void)
|
||||
{
|
||||
return register_driver(&ramfs_driver.drv);
|
||||
}
|
||||
|
||||
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",
|
||||
"<dev:path> list files on device"
|
||||
);
|
||||
|
|
@ -26,8 +26,11 @@ struct device_d {
|
|||
*/
|
||||
unsigned long map_base;
|
||||
|
||||
void *platform_data;
|
||||
void *priv;
|
||||
void *platform_data; /* board specific information about this device */
|
||||
void *priv; /* data private to the driver */
|
||||
void *type_data; /* In case this device is a specific device, this pointer
|
||||
* points to the type specific device, i.e. eth_device
|
||||
*/
|
||||
|
||||
/* The driver for this device */
|
||||
struct driver_d *driver;
|
||||
|
@ -55,9 +58,10 @@ struct driver_d {
|
|||
int (*get) (struct device_d*, struct param_d *);
|
||||
int (*set) (struct device_d*, struct param_d *, value_t val);
|
||||
|
||||
void *driver_data;
|
||||
unsigned long type;
|
||||
void *type_data;
|
||||
void *type_data; /* In case this driver is of a specific type, i.e. a filesystem
|
||||
* driver, this pointer points to the corresponding data struct
|
||||
*/
|
||||
};
|
||||
|
||||
#define RW_SIZE(x) (x)
|
||||
|
|
31
include/fs.h
31
include/fs.h
|
@ -6,23 +6,46 @@
|
|||
#define FS_TYPE_CRAMFS 1
|
||||
#define FS_TYPE_RAMFS 2
|
||||
|
||||
#define PATH_MAX 1024 /* include/linux/limits.h */
|
||||
|
||||
struct partition;
|
||||
struct node_d;
|
||||
|
||||
struct dirent {
|
||||
unsigned long mode;
|
||||
unsigned long size;
|
||||
char name[256];
|
||||
};
|
||||
|
||||
struct dir {
|
||||
struct device_d *dev;
|
||||
struct fs_driver_d *fsdrv;
|
||||
struct node_d *node;
|
||||
struct dirent d;
|
||||
void *priv; /* private data for the fs driver */
|
||||
};
|
||||
|
||||
#define FS_DRIVER_NO_DEV 1
|
||||
|
||||
struct fs_driver_d {
|
||||
ulong type;
|
||||
char *name;
|
||||
int (*ls) (struct device_d *dev, const char *filename);
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
struct driver_d drv;
|
||||
|
||||
unsigned long flags;
|
||||
};
|
||||
|
||||
struct fs_device_d {
|
||||
ulong type;
|
||||
char *name;
|
||||
struct device_d *parent; /* the device we are associated with */
|
||||
struct device_d dev; /* our own device */
|
||||
|
||||
|
@ -34,4 +57,6 @@ int register_filesystem(struct device_d *dev, char *fsname);
|
|||
|
||||
int register_fs_driver(struct fs_driver_d *new_fs_drv);
|
||||
|
||||
char *mkmodestr(unsigned long mode, char *str);
|
||||
|
||||
#endif /* __FS_H */
|
||||
|
|
|
@ -68,7 +68,7 @@ int register_device(struct device_d *new_device)
|
|||
|
||||
dev = first_device;
|
||||
|
||||
if(get_device_by_id(new_device->id)) {
|
||||
if(*new_device->id && get_device_by_id(new_device->id)) {
|
||||
printf("device %s already exists\n", new_device->id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue