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) {
|
2011-02-22 23:54:40 +00:00
|
|
|
// TODO: find coliding plugin name
|
|
|
|
if (p && p->init)
|
|
|
|
p->init ();
|
2011-01-11 23:01:06 +00:00
|
|
|
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-02-18 00:43:31 +00:00
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2011-02-25 02:17:20 +00:00
|
|
|
static inline int r_fs_match (const char *root, const char *path, int len, int olen) {
|
|
|
|
return ((len>olen) && (!strncmp (path, root, len)));
|
2011-01-11 23:01:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
R_API int r_fs_umount (RFS* fs, const char *path) {
|
2011-02-25 02:17:20 +00:00
|
|
|
int olen = 0;
|
2011-01-11 23:01:06 +00:00
|
|
|
RFSRoot *root;
|
2011-02-25 02:17:20 +00:00
|
|
|
RListIter *iter, *riter = NULL;
|
2011-01-11 23:01:06 +00:00
|
|
|
r_list_foreach (fs->roots, iter, root) {
|
2011-02-25 02:17:20 +00:00
|
|
|
int len = strlen (root->path);
|
|
|
|
if (r_fs_match (path, root->path, len, olen)) {
|
|
|
|
olen = len;
|
|
|
|
riter = iter;
|
2011-01-11 23:01:06 +00:00
|
|
|
}
|
|
|
|
}
|
2011-02-25 02:17:20 +00:00
|
|
|
if (riter) {
|
|
|
|
r_list_delete (fs->roots, riter);
|
|
|
|
return R_TRUE;
|
|
|
|
}
|
2011-01-11 23:01:06 +00:00
|
|
|
return R_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API RFSRoot *r_fs_root (RFS *fs, const char *path) {
|
2011-02-25 02:17:20 +00:00
|
|
|
int olen = 0;
|
2011-01-11 23:01:06 +00:00
|
|
|
RListIter *iter;
|
2011-02-25 02:17:20 +00:00
|
|
|
RFSRoot *root, *oroot = NULL;
|
2011-01-11 23:01:06 +00:00
|
|
|
r_list_foreach (fs->roots, iter, root) {
|
2011-02-25 02:17:20 +00:00
|
|
|
int len = strlen (root->path);
|
|
|
|
if (r_fs_match (path, root->path, len, olen)) {
|
|
|
|
olen = len;
|
|
|
|
oroot = root;
|
|
|
|
}
|
2011-01-11 23:01:06 +00:00
|
|
|
}
|
2011-02-25 02:17:20 +00:00
|
|
|
return oroot;
|
2011-01-07 17:22:02 +00:00
|
|
|
}
|
|
|
|
|
2011-01-11 23:01:06 +00:00
|
|
|
/* filez */
|
2011-02-21 08:26:32 +00:00
|
|
|
R_API RFSFile *r_fs_open (RFS* fs, const char *p) {
|
2011-02-22 23:54:40 +00:00
|
|
|
RFSRoot *root;
|
2011-02-21 08:26:32 +00:00
|
|
|
char *path = strdup (p);
|
2011-02-25 02:17:20 +00:00
|
|
|
//r_str_chop_path (path);
|
2011-02-22 23:54:40 +00:00
|
|
|
root = r_fs_root (fs, path);
|
2011-02-21 08:26:32 +00:00
|
|
|
if (root && root->p && root->p->open) {
|
|
|
|
RFSFile *f = root->p->open (root, path+strlen (root->path));
|
|
|
|
free (path);
|
|
|
|
return f;
|
|
|
|
} else eprintf ("r_fs_open: null root->p->open\n");
|
|
|
|
free (path);
|
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");
|
2011-02-22 23:54:40 +00:00
|
|
|
return R_FALSE;
|
|
|
|
}
|
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;
|
|
|
|
}
|
|
|
|
|
2011-02-21 08:26:32 +00:00
|
|
|
R_API RList *r_fs_dir(RFS* fs, const char *p) {
|
2011-01-11 23:01:06 +00:00
|
|
|
if (fs) {
|
2011-02-21 08:26:32 +00:00
|
|
|
char *path = strdup (p);
|
2011-02-25 02:17:20 +00:00
|
|
|
r_str_chop (path);
|
2011-01-11 23:01:06 +00:00
|
|
|
RFSRoot *root = r_fs_root (fs, path);
|
2011-01-20 23:21:32 +00:00
|
|
|
if (root) {
|
2011-02-25 02:17:20 +00:00
|
|
|
const char *dir = path + strlen (root->path)-1;
|
2011-01-20 23:21:32 +00:00
|
|
|
if (!*dir) dir = "/";
|
2011-02-21 08:26:32 +00:00
|
|
|
if (root) {
|
2011-02-25 02:17:20 +00:00
|
|
|
RList *ret = root->p->dir (root, dir);
|
2011-02-21 08:26:32 +00:00
|
|
|
free (path);
|
2011-02-25 02:17:20 +00:00
|
|
|
return ret;
|
2011-02-21 08:26:32 +00:00
|
|
|
}
|
2011-01-20 23:21:32 +00:00
|
|
|
}
|
2011-02-21 17:10:22 +00:00
|
|
|
eprintf ("r_fs_dir: not mounted '%s'\n", path);
|
2011-02-25 02:17:20 +00:00
|
|
|
free (path);
|
2011-01-11 23:01:06 +00:00
|
|
|
}
|
|
|
|
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);
|
2011-02-22 23:54:40 +00:00
|
|
|
if (file) root->p->read (file, 0, file->size); //file->data
|
|
|
|
else eprintf ("r_fs_slurp: cannot open file\n");
|
2011-01-14 00:02:20 +00:00
|
|
|
} else {
|
2011-02-22 23:54:40 +00:00
|
|
|
if (root->p->slurp) return root->p->slurp (root, path);
|
2011-01-14 00:05:23 +00:00
|
|
|
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;
|
2011-02-21 14:20:33 +00:00
|
|
|
static int parhook (struct grub_disk *disk, struct grub_partition *par, void *closure) {
|
2011-01-14 13:41:56 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2011-02-18 17:22:51 +00:00
|
|
|
R_API RList *r_fs_partitions (RFS *fs, const char *ptype, ut64 delta) {
|
2011-01-23 20:54:18 +00:00
|
|
|
struct grub_partition_map *gpm = NULL;
|
|
|
|
if (!strcmp (ptype, "msdos"))
|
|
|
|
gpm = &grub_msdos_partition_map;
|
|
|
|
else if (!strcmp (ptype, "apple"))
|
|
|
|
gpm = &grub_apple_partition_map;
|
|
|
|
else if (!strcmp (ptype, "sun"))
|
|
|
|
gpm = &grub_sun_partition_map;
|
|
|
|
else if (!strcmp (ptype, "sunpc"))
|
2011-01-23 22:58:46 +00:00
|
|
|
gpm = &grub_sun_pc_partition_map;
|
2011-01-23 20:54:18 +00:00
|
|
|
else if (!strcmp (ptype, "amiga"))
|
|
|
|
gpm = &grub_amiga_partition_map;
|
|
|
|
else if (!strcmp (ptype, "bsdlabel"))
|
|
|
|
gpm = &grub_bsdlabel_partition_map;
|
2011-02-21 08:26:32 +00:00
|
|
|
// XXX: In BURG all bsd partition map are in bsdlabel
|
|
|
|
// else if (!strcmp (ptype, "openbsdlabel"))
|
|
|
|
// gpm = &grub_openbsdlabel_partition_map;
|
|
|
|
// else if (!strcmp (ptype, "netbsdlabel"))
|
|
|
|
// gpm = &grub_netbsdlabel_partition_map;
|
2011-01-23 22:58:46 +00:00
|
|
|
// else if (!strcmp (ptype, "acorn"))
|
|
|
|
// gpm = &grub_acorn_partition_map;
|
2011-01-23 20:54:18 +00:00
|
|
|
else if (!strcmp (ptype, "gpt"))
|
|
|
|
gpm = &grub_gpt_partition_map;
|
|
|
|
|
|
|
|
if (gpm) {
|
|
|
|
list = r_list_new ();
|
|
|
|
list->free = (RListFree)r_fs_partition_free;
|
2011-01-14 13:41:56 +00:00
|
|
|
struct grub_disk *disk = grubfs_disk (&fs->iob);
|
2011-02-21 08:26:32 +00:00
|
|
|
gpm->iterate (disk, parhook, 0);
|
2011-01-23 20:54:18 +00:00
|
|
|
return list;
|
2011-01-14 13:41:56 +00:00
|
|
|
}
|
2011-02-22 23:54:40 +00:00
|
|
|
if (ptype&&*ptype)
|
|
|
|
eprintf ("Unknown partition type '%s'.\n", ptype);
|
|
|
|
eprintf ("Supported types:\n"
|
2011-02-25 02:17:20 +00:00
|
|
|
" msdos, apple, sun, sunpc, amiga, bsdlabel, acorn, gpt\n");
|
2011-01-23 20:54:18 +00:00
|
|
|
return NULL;
|
2011-01-14 13:41:56 +00:00
|
|
|
}
|
2011-02-18 17:22:51 +00:00
|
|
|
|
|
|
|
R_API int r_fs_prompt (RFS *fs, char *root) {
|
|
|
|
char buf[1024];
|
|
|
|
char path[1024];
|
|
|
|
char str[2048];
|
|
|
|
char *input;
|
|
|
|
RList *list;
|
|
|
|
RListIter *iter;
|
|
|
|
RFSFile *file;
|
|
|
|
|
2011-02-21 17:10:22 +00:00
|
|
|
if (root && *root) {
|
|
|
|
r_str_chop_path (root);
|
2011-02-23 02:01:26 +00:00
|
|
|
if (!r_fs_root (fs, root)) {
|
|
|
|
printf ("Unknown root\n");
|
|
|
|
return R_FALSE;
|
|
|
|
}
|
2011-02-21 17:10:22 +00:00
|
|
|
strncpy (path, root, sizeof (path)-1);
|
|
|
|
} else strcpy (path, "/");
|
2011-02-18 17:22:51 +00:00
|
|
|
|
|
|
|
for (;;) {
|
2011-02-25 03:19:30 +00:00
|
|
|
printf ("[%s]> ", path);
|
2011-02-18 17:22:51 +00:00
|
|
|
fflush (stdout);
|
|
|
|
fgets (buf, sizeof (buf)-1, stdin);
|
|
|
|
if (feof (stdin)) break;
|
|
|
|
buf[strlen (buf)-1] = '\0';
|
|
|
|
if (!strcmp (buf, "q") || !strcmp (buf, "exit"))
|
|
|
|
return R_TRUE;
|
2011-02-21 17:10:22 +00:00
|
|
|
if (buf[0]=='!') {
|
|
|
|
system (buf+1);
|
|
|
|
} else
|
2011-02-25 02:17:20 +00:00
|
|
|
if (!memcmp (buf, "ls", 2)) {
|
|
|
|
if (buf[2]==' ') {
|
|
|
|
list = r_fs_dir (fs, buf+3);
|
|
|
|
} else list = r_fs_dir (fs, path);
|
2011-02-18 17:22:51 +00:00
|
|
|
if (list) {
|
|
|
|
r_list_foreach (list, iter, file)
|
|
|
|
printf ("%c %s\n", file->type, file->name);
|
|
|
|
r_list_free (list);
|
2011-02-25 02:17:20 +00:00
|
|
|
} else eprintf ("Unknown path: %s\n", path);
|
2011-02-21 17:10:22 +00:00
|
|
|
} else if (!strncmp (buf, "pwd", 3)) {
|
|
|
|
eprintf ("%s\n", path);
|
|
|
|
} else if (!memcmp (buf, "cd ", 3)) {
|
2011-02-25 02:17:20 +00:00
|
|
|
char opath[4096];
|
|
|
|
strcpy (opath, path);
|
2011-02-18 17:22:51 +00:00
|
|
|
input = buf+3;
|
2011-02-25 02:17:20 +00:00
|
|
|
while (*input == ' ')
|
2011-02-18 17:22:51 +00:00
|
|
|
input++;
|
2011-02-25 02:17:20 +00:00
|
|
|
if (!strcmp (input, "..")) {
|
|
|
|
char *p = r_str_lchr (path, '/');
|
|
|
|
if (p) p[(p==path)?1:0]=0;
|
|
|
|
} else {
|
|
|
|
if (*input=='/')
|
|
|
|
strcpy (path, input);
|
|
|
|
else strcat (path, input);
|
2011-02-18 17:22:51 +00:00
|
|
|
}
|
2011-02-25 02:17:20 +00:00
|
|
|
list = r_fs_dir (fs, path);
|
|
|
|
if (r_list_empty (list)) {
|
|
|
|
strcpy (path, opath);
|
|
|
|
eprintf ("cd: unknown path: %s\n", path);
|
|
|
|
} else r_list_free (list);
|
2011-02-21 17:10:22 +00:00
|
|
|
} else if (!memcmp (buf, "cat ", 4)) {
|
2011-02-18 17:22:51 +00:00
|
|
|
input = buf+3;
|
|
|
|
while (input[0] == ' ')
|
|
|
|
input++;
|
|
|
|
if (input[0] == '/')
|
|
|
|
strncpy (str, root, sizeof (str)-1);
|
2011-02-21 17:10:22 +00:00
|
|
|
else strncpy (str, path, sizeof (str)-1);
|
2011-02-18 17:22:51 +00:00
|
|
|
strcat (str, "/");
|
|
|
|
strcat (str, input);
|
|
|
|
file = r_fs_open (fs, str);
|
|
|
|
if (file) {
|
|
|
|
r_fs_read (fs, file, 0, file->size);
|
|
|
|
write (1, file->data, file->size);
|
|
|
|
r_fs_close (fs, file);
|
2011-02-21 17:10:22 +00:00
|
|
|
} else eprintf ("Cannot open file\n");
|
|
|
|
} else if (!memcmp (buf, "mount", 5)) {
|
|
|
|
RFSRoot *root;
|
|
|
|
r_list_foreach (fs->roots, iter, root) {
|
|
|
|
eprintf ("%s %s\n", root->path, root->p->name);
|
|
|
|
}
|
2011-02-25 03:19:30 +00:00
|
|
|
} else if (!memcmp (buf, "get ", 4)) {
|
2011-02-18 17:22:51 +00:00
|
|
|
input = buf+3;
|
|
|
|
while (input[0] == ' ')
|
|
|
|
input++;
|
|
|
|
if (input[0] == '/')
|
|
|
|
strncpy (str, root, sizeof (str)-1);
|
2011-02-21 17:10:22 +00:00
|
|
|
else strncpy (str, path, sizeof (str)-1);
|
2011-02-18 17:22:51 +00:00
|
|
|
strcat (str, "/");
|
|
|
|
strcat (str, input);
|
|
|
|
file = r_fs_open (fs, str);
|
|
|
|
if (file) {
|
|
|
|
r_fs_read (fs, file, 0, file->size);
|
|
|
|
r_file_dump (input, file->data, file->size);
|
|
|
|
r_fs_close (fs, file);
|
|
|
|
} else printf ("Cannot open file\n");
|
2011-02-21 17:10:22 +00:00
|
|
|
} else if (!memcmp (buf, "help", 4) || !strcmp (buf, "?")) {
|
2011-02-25 03:19:30 +00:00
|
|
|
eprintf (
|
2011-02-18 17:22:51 +00:00
|
|
|
"Commands:\n"
|
2011-02-21 17:10:22 +00:00
|
|
|
" !cmd ; escape to system\n"
|
2011-02-25 03:19:30 +00:00
|
|
|
" ls [path] ; list current directory\n"
|
2011-02-18 17:22:51 +00:00
|
|
|
" cd path ; change current directory\n"
|
|
|
|
" cat file ; print contents of file\n"
|
2011-02-21 17:10:22 +00:00
|
|
|
" get file ; dump file to disk\n"
|
|
|
|
" mount ; list mount points\n"
|
2011-02-18 17:22:51 +00:00
|
|
|
" q/exit ; leave prompt mode\n"
|
|
|
|
" ?/help ; show this help\n"
|
|
|
|
);
|
2011-02-25 03:19:30 +00:00
|
|
|
} else eprintf ("Unknown command %s\n", buf);
|
2011-02-18 17:22:51 +00:00
|
|
|
}
|
|
|
|
clearerr (stdin);
|
|
|
|
printf ("\n");
|
|
|
|
return R_TRUE;
|
|
|
|
}
|