2011-01-11 23:01:06 +00:00
|
|
|
/* radare - LGPL - Copyright 2011 pancake<nopcode.org> */
|
2011-01-07 17:22:02 +00:00
|
|
|
|
|
|
|
#include <r_fs.h>
|
2011-01-11 23:01:06 +00:00
|
|
|
#include "../config.h"
|
2011-01-07 17:22:02 +00:00
|
|
|
|
2011-01-14 00:02:20 +00:00
|
|
|
static RFSPlugin *fs_static_plugins[] = { R_FS_STATIC_PLUGINS };
|
2011-01-11 23:01:06 +00:00
|
|
|
|
|
|
|
/* lifecycle */
|
2011-01-07 17:22:02 +00:00
|
|
|
// TODO: needs much more love
|
|
|
|
R_API RFS *r_fs_new () {
|
2011-01-11 23:01:06 +00:00
|
|
|
int i;
|
|
|
|
RFSPlugin *static_plugin;
|
2011-01-07 17:22:02 +00:00
|
|
|
RFS *fs = R_NEW (RFS);
|
|
|
|
if (fs) {
|
2011-01-11 23:01:06 +00:00
|
|
|
fs->roots = r_list_new ();
|
|
|
|
fs->roots->free = (RListFree)r_fs_root_free;
|
2011-01-07 17:22:02 +00:00
|
|
|
fs->plugins = r_list_new ();
|
2011-01-11 23:01:06 +00:00
|
|
|
// XXX fs->roots->free = r_fs_plugin_free;
|
|
|
|
for (i=0; fs_static_plugins[i]; i++) {
|
|
|
|
static_plugin = R_NEW (RFSPlugin);
|
|
|
|
memcpy (static_plugin, fs_static_plugins[i], sizeof (RFSPlugin));
|
|
|
|
r_fs_add (fs, static_plugin);
|
|
|
|
}
|
2011-01-07 17:22:02 +00:00
|
|
|
}
|
|
|
|
return fs;
|
|
|
|
}
|
|
|
|
|
2011-01-11 23:01:06 +00:00
|
|
|
R_API RFSPlugin *r_fs_plugin_get (RFS *fs, const char *name) {
|
|
|
|
RListIter *iter;
|
|
|
|
RFSPlugin *p;
|
|
|
|
r_list_foreach (fs->plugins, iter, p) {
|
|
|
|
if (!strcmp (p->name, name))
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2011-01-07 17:22:02 +00:00
|
|
|
R_API void r_fs_free (RFS* fs) {
|
2011-01-11 23:01:06 +00:00
|
|
|
r_list_free (fs->plugins);
|
|
|
|
r_list_free (fs->roots);
|
2011-01-07 17:22:02 +00:00
|
|
|
free (fs);
|
|
|
|
}
|
|
|
|
|
2011-01-11 23:01:06 +00:00
|
|
|
/* plugins */
|
|
|
|
|
|
|
|
R_API void r_fs_add (RFS *fs, RFSPlugin *p) {
|
|
|
|
// find coliding plugin name
|
|
|
|
if (p) {
|
|
|
|
if (p->init)
|
|
|
|
p->init ();
|
|
|
|
}
|
|
|
|
r_list_append (fs->plugins, p);
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API void r_fs_del (RFS *fs, RFSPlugin *p) {
|
|
|
|
// TODO: implement
|
|
|
|
}
|
|
|
|
|
|
|
|
/* mountpoint */
|
|
|
|
|
2011-01-14 00:02:20 +00:00
|
|
|
R_API RFSRoot *r_fs_mount (RFS* fs, const char *fstype, const char *path, ut64 delta) {
|
2011-01-11 23:01:06 +00:00
|
|
|
RFSPlugin *p;
|
2011-01-14 00:02:20 +00:00
|
|
|
RFSRoot *root;
|
2011-01-11 23:01:06 +00:00
|
|
|
if (path[0] != '/') {
|
|
|
|
eprintf ("r_fs_mount: invalid mountpoint\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
p = r_fs_plugin_get (fs, fstype);
|
|
|
|
if (p != NULL) {
|
2011-01-14 00:02:20 +00:00
|
|
|
root = r_fs_root_new (path, delta);
|
|
|
|
root->p = p;
|
|
|
|
//memcpy (&root->iob, &fs->iob, sizeof (root->iob));
|
|
|
|
root->iob = fs->iob;
|
|
|
|
p->mount (root);
|
2011-01-11 23:01:06 +00:00
|
|
|
r_list_append (fs->roots, root);
|
|
|
|
eprintf ("Mounted %s on %s at 0x%llx\n", fstype, path, 0LL);
|
|
|
|
} else eprintf ("r_fs_mount: Invalid filesystem type\n");
|
|
|
|
return root;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int r_fs_match (const char *root, const char *path) {
|
|
|
|
return (!strncmp (path, root, strlen (path)));
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API int r_fs_umount (RFS* fs, const char *path) {
|
|
|
|
RFSRoot *root;
|
|
|
|
RListIter *iter;
|
|
|
|
r_list_foreach (fs->roots, iter, root) {
|
|
|
|
if (r_fs_match (path, root->path)) {
|
|
|
|
r_list_delete (fs->roots, iter);
|
|
|
|
return R_TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return R_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API RFSRoot *r_fs_root (RFS *fs, const char *path) {
|
|
|
|
RFSRoot *root;
|
|
|
|
RListIter *iter;
|
|
|
|
r_list_foreach (fs->roots, iter, root) {
|
|
|
|
if (r_fs_match (path, root->path))
|
|
|
|
return root;
|
|
|
|
}
|
2011-01-07 17:22:02 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2011-01-11 23:01:06 +00:00
|
|
|
/* filez */
|
|
|
|
|
|
|
|
R_API RFSFile *r_fs_open (RFS* fs, const char *path) {
|
|
|
|
RFSRoot *root = r_fs_root (fs, path);
|
2011-01-14 00:02:20 +00:00
|
|
|
if (root && root->p && root->p->open)
|
|
|
|
return root->p->open (root, path+strlen (root->path));
|
|
|
|
else eprintf ("r_fs_open: null root->p->open\n");
|
2011-01-11 23:01:06 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2011-01-14 00:02:20 +00:00
|
|
|
// TODO: close or free?
|
2011-01-11 23:01:06 +00:00
|
|
|
R_API void r_fs_close (RFS* fs, RFSFile *file) {
|
2011-01-14 00:02:20 +00:00
|
|
|
if (fs && file && file->p && file->p->close)
|
|
|
|
file->p->close (file);
|
2011-01-11 23:01:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
R_API int r_fs_read (RFS* fs, RFSFile *file, ut64 addr, int len) {
|
2011-01-14 00:02:20 +00:00
|
|
|
if (len<1) {
|
|
|
|
eprintf ("r_fs_read: too short read\n");
|
|
|
|
} else
|
2011-01-11 23:01:06 +00:00
|
|
|
if (fs && file) {
|
|
|
|
free (file->data);
|
2011-01-14 00:02:20 +00:00
|
|
|
file->data = malloc (len+1);
|
|
|
|
if (file->p && file->p->read) {
|
|
|
|
file->p->read (file, addr, len);
|
|
|
|
return R_TRUE;
|
|
|
|
} else eprintf ("r_fs_read: file->p->read is null\n");
|
2011-01-11 23:01:06 +00:00
|
|
|
}
|
|
|
|
return R_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API RList *r_fs_dir(RFS* fs, const char *path) {
|
|
|
|
if (fs) {
|
|
|
|
RFSRoot *root = r_fs_root (fs, path);
|
2011-01-20 23:21:32 +00:00
|
|
|
if (root) {
|
|
|
|
const char *dir = path + strlen (root->path);
|
|
|
|
if (!*dir) dir = "/";
|
|
|
|
if (root)
|
|
|
|
return root->p->dir (root, dir);
|
|
|
|
}
|
2011-01-11 23:01:06 +00:00
|
|
|
eprintf ("r_fs_dir: error, path %s is not mounted\n", path);
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
2011-01-14 00:02:20 +00:00
|
|
|
|
2011-01-14 00:05:23 +00:00
|
|
|
R_API RFSFile *r_fs_slurp(RFS* fs, const char *path) {
|
2011-01-14 00:02:20 +00:00
|
|
|
RFSFile *file = NULL;
|
|
|
|
RFSRoot *root = r_fs_root (fs, path);
|
|
|
|
if (root && root->p) {
|
|
|
|
if (root->p->open && root->p->read && root->p->close) {
|
|
|
|
file = root->p->open (root, path);
|
|
|
|
if (file) {
|
|
|
|
root->p->read (file, 0, file->size); //file->data, file->size);
|
2011-01-14 00:05:23 +00:00
|
|
|
} else eprintf ("r_fs_slurp: cannot open file\n");
|
2011-01-14 00:02:20 +00:00
|
|
|
} else {
|
2011-01-14 00:05:23 +00:00
|
|
|
if (root->p->slurp)
|
|
|
|
return root->p->slurp (root, path);
|
|
|
|
else eprintf ("r_fs_slurp: null root->p->slurp\n");
|
2011-01-14 00:02:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return file;
|
|
|
|
}
|
2011-01-14 13:41:56 +00:00
|
|
|
|
|
|
|
// TODO: move into grubfs
|
|
|
|
#include "p/grub/include/grubfs.h"
|
|
|
|
RList *list = NULL;
|
|
|
|
static int parhook (struct grub_disk *disk, struct grub_partition *par) {
|
|
|
|
RFSPartition *p = r_fs_partition_new (r_list_length (list), par->start*512, 512*par->len);
|
|
|
|
p->type = par->msdostype;
|
|
|
|
r_list_append (list, p);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API RList *r_fs_partitions(RFS *fs, const char *ptype, ut64 delta) {
|
|
|
|
list = r_list_new ();
|
|
|
|
list->free = r_fs_partition_free;
|
|
|
|
if (!strcmp (ptype, "msdos")) {
|
|
|
|
struct grub_disk *disk = grubfs_disk (&fs->iob);
|
|
|
|
struct grub_partition_map *gpm = &grub_msdos_partition_map;
|
|
|
|
gpm->iterate (disk, parhook);
|
|
|
|
} else {
|
|
|
|
eprintf ("Unknown partition type '%s'. Try 'msdos'", ptype);
|
|
|
|
r_list_free (list);
|
|
|
|
list = NULL;
|
|
|
|
}
|
|
|
|
return list;
|
|
|
|
}
|