Improve the RFS API to support write and unlink operations ##fs

* In fs_r2: /seek and /bsize and fix flags and config writes
* fs.shell supports echo and redirections '>'
This commit is contained in:
pancake 2019-05-10 10:13:54 +02:00 committed by radare
parent 23e906ea70
commit d8b283f8c6
12 changed files with 277 additions and 122 deletions

View File

@ -77,8 +77,8 @@ static void cmd_debug_reg(RCore *core, const char *str);
#include "cmd_hash.c"
#include "cmd_debug.c"
#include "cmd_log.c"
#include "cmd_zign.c"
#include "cmd_flag.c"
#include "cmd_zign.c"
#include "cmd_project.c"
#include "cmd_write.c"
#include "cmd_cmp.c"

View File

@ -109,6 +109,42 @@ static void cmd_flag_init(RCore *core) {
DEFINE_CMD_DESCRIPTOR (core, fz);
}
static void spaces_list(RSpaces *sp, int mode) {
RSpaceIter it;
RSpace *s;
const RSpace *cur = r_spaces_current (sp);
PJ *pj = NULL;
if (mode == 'j') {
pj = pj_new ();
pj_a (pj);
}
r_spaces_foreach (sp, it, s) {
int count = r_spaces_count (sp, s->name);
if (mode == 'j') {
pj_o (pj);
pj_ks (pj, "name", s->name);
pj_ki (pj, "count", count);
pj_kb (pj, "selected", cur == s);
pj_end (pj);
} else if (mode == 'q') {
r_cons_printf ("%s\n", s->name);
} else if (mode == '*') {
r_cons_printf ("%s %s\n", sp->name, s->name);
} else {
r_cons_printf ("%5d %c %s\n", count, (!cur || cur == s)? '*': '.',
s->name);
}
}
if (mode == '*' && r_spaces_current (sp)) {
r_cons_printf ("%s %s # current\n", sp->name, r_spaces_current_name (sp));
}
if (mode == 'j') {
pj_end (pj);
r_cons_printf ("%s\n", pj_string (pj));
pj_free (pj);
}
}
static void cmd_fz(RCore *core, const char *input) {
switch (*input) {
case '?': // "fz?"
@ -851,12 +887,6 @@ rep:
break;
}
break;
case 'j':
case '\0':
case '*':
case 'q':
spaces_list (&core->flags->spaces, input[1]);
break;
case ' ':
r_flag_space_set (core->flags, input+2);
break;
@ -874,6 +904,12 @@ rep:
}
}
break;
case 'j':
case '\0':
case '*':
case 'q':
spaces_list (&core->flags->spaces, input[1]);
break;
default:
spaces_list (&core->flags->spaces, 0);
break;

View File

@ -445,7 +445,7 @@ static int cmd_mount(void *data, const char *_input) {
break;
}
break;
case 's':
case 's': // "ms"
if (core->http_up) {
free (oinput);
return false;

View File

@ -6,7 +6,6 @@
#include <r_list.h>
#include <r_cons.h>
#include <r_util.h>
#include "i/private.h"
static const char *help_msg_z[] = {
"Usage:", "z[*j-aof/cs] [args] ", "# Manage zignatures",

View File

@ -7,7 +7,6 @@
#if __UNIX__
#include <signal.h>
#endif
#include "i/private.h"
#define DB core->sdb
@ -2256,40 +2255,6 @@ static char *get_comments_cb(void *user, ut64 addr) {
return r_core_anal_get_comments ((RCore *)user, addr);
}
R_IPI void spaces_list(RSpaces *sp, int mode) {
RSpaceIter it;
RSpace *s;
const RSpace *cur = r_spaces_current (sp);
PJ *pj = NULL;
if (mode == 'j') {
pj = pj_new ();
pj_a (pj);
}
r_spaces_foreach (sp, it, s) {
int count = r_spaces_count (sp, s->name);
if (mode == 'j') {
pj_o (pj);
pj_ks (pj, "name", s->name);
pj_ki (pj, "count", count);
pj_kb (pj, "selected", cur == s);
pj_end (pj);
} else if (mode == '*') {
r_cons_printf ("%s %s\n", sp->name, s->name);
} else {
r_cons_printf ("%5d %c %s\n", count, (!cur || cur == s)? '*': '.',
s->name);
}
}
if (mode == '*' && r_spaces_current (sp)) {
r_cons_printf ("%s %s # current\n", sp->name, r_spaces_current_name (sp));
}
if (mode == 'j') {
pj_end (pj);
r_cons_printf ("%s\n", pj_string (pj));
pj_free (pj);
}
}
static void cb_event_handler(REvent *ev, int event_type, void *user, void *data) {
RCore *core = (RCore *)ev->user;
if (!core->log_events) {

View File

@ -1,10 +0,0 @@
#ifndef R_CORE_PRIVATE_H_
#define R_CORE_PRIVATE_H_
#include <r_core.h>
#include <r_util.h>
#include <r_types.h>
R_IPI void spaces_list(RSpaces *sp, int mode);
#endif

View File

@ -1,4 +1,4 @@
/* radare - LGPL - Copyright 2011 pancake<nopcode.org> */
/* radare - LGPL - Copyright 2011-2019 - pancake */
#include <r_fs.h>
@ -8,15 +8,26 @@ R_API RFSFile* r_fs_file_new(RFSRoot* root, const char* path) {
return NULL;
}
file->root = root;
file->name = strdup (path);
// TODO: concat path?
if (root) {
file->p = file->root->p; // XXX dupe
}
file->path = strdup (path);
char *last = (char *)r_str_rchr (file->path, NULL, '/');
if (last) {
*last++ = 0;
file->name = strdup (last);
} else {
file->name = strdup (path);
}
return file;
}
R_API void r_fs_file_free(RFSFile* file) {
free (file->name);
free (file->data);
free (file);
if (file) {
free (file->name);
free (file->data);
free (file);
}
}
// TODO: Use RFSRoot and pass it in the stack instead of heap? problematic with bindings

View File

@ -1,4 +1,4 @@
/* radare2 - LGPL - Copyright 2011-2018 - pancake */
/* radare2 - LGPL - Copyright 2011-2019 - pancake */
#include <r_fs.h>
#include "config.h"
@ -147,7 +147,7 @@ R_API RFSRoot* r_fs_mount(RFS* fs, const char* fstype, const char* path, ut64 de
return NULL;
}
}
file = r_fs_open (fs, str);
file = r_fs_open (fs, str, false);
if (file) {
r_fs_close (fs, file);
eprintf ("r_fs_mount: Invalid mount point\n");
@ -234,24 +234,29 @@ R_API RList* r_fs_root(RFS* fs, const char* p) {
}
/* filez */
R_API RFSFile* r_fs_open(RFS* fs, const char* p) {
R_API RFSFile* r_fs_open(RFS* fs, const char* p, bool create) {
RFSRoot* root;
RList* roots;
RListIter* iter;
RFSFile* f = NULL;
const char* dir;
char* path = strdup (p);
//r_str_trim_path (path);
roots = r_fs_root (fs, path);
char* path = r_str_trim (strdup (p));
RList *roots = r_fs_root (fs, path);
if (!r_list_empty (roots)) {
r_list_foreach (roots, iter, root) {
if (create) {
if (root && root->p && root->p->write) {
f = r_fs_file_new (root, path + strlen (root->path));
break;
}
continue;
}
if (root && root->p && root->p->open) {
if (strlen (root->path) == 1) {
dir = path;
} else {
dir = path + strlen (root->path);
}
f = root->p->open (root, dir);
f = root->p->open (root, dir, false);
if (f) {
break;
}
@ -263,7 +268,7 @@ R_API RFSFile* r_fs_open(RFS* fs, const char* p) {
return f;
}
// TODO: close or free?
// NOTE: close doesnt free
R_API void r_fs_close(RFS* fs, RFSFile* file) {
if (fs && file) {
R_FREE (file->data);
@ -273,16 +278,33 @@ R_API void r_fs_close(RFS* fs, RFSFile* file) {
}
}
R_API int r_fs_write(RFS* fs, RFSFile* file, ut64 addr, const ut8 *data, int len) {
if (len < 1) {
return false;
}
if (fs && file) {
// TODO: fill file->data ? looks like dupe of rbuffer
if (file->p && file->p->write) {
file->p->write (file, addr, data, len);
return true;
}
eprintf ("r_fs_write: file->p->write is null\n");
}
return false;
}
R_API int r_fs_read(RFS* fs, RFSFile* file, ut64 addr, int len) {
if (len < 1) {
eprintf ("r_fs_read: too short read\n");
return false;
}
if (fs && file) {
#if 0
free (file->data);
file->data = calloc (1, len + 1);
#endif
// file->data_len = len;
if (file->p && file->data && file->p->read) {
if (file->p && file->p->read) {
file->p->read (file, addr, len);
return true;
} else {
@ -293,13 +315,13 @@ R_API int r_fs_read(RFS* fs, RFSFile* file, ut64 addr, int len) {
}
R_API RList* r_fs_dir(RFS* fs, const char* p) {
RList* roots, * ret = NULL;
RList *ret = NULL;
RFSRoot* root;
RListIter* iter;
const char* dir;
char* path = strdup (p);
r_str_trim_path (path);
roots = r_fs_root (fs, path);
RList *roots = r_fs_root (fs, path);
r_list_foreach (roots, iter, root) {
if (root) {
if (strlen (root->path) == 1) {
@ -366,7 +388,7 @@ R_API int r_fs_dir_dump(RFS* fs, const char* path, const char* name) {
}
break;
case R_FS_FILE_TYPE_REGULAR:
item = r_fs_open (fs, npath);
item = r_fs_open (fs, npath, false);
if (item) {
r_fs_read (fs, item, 0, item->size);
if (!r_file_dump (str, item->data, item->size, 0)) {
@ -407,7 +429,7 @@ static void r_fs_find_off_aux(RFS* fs, const char* name, ut64 offset, RList* lis
if (item->type == R_FS_FILE_TYPE_DIRECTORY) {
r_fs_find_off_aux (fs, found, offset, list);
} else {
file = r_fs_open (fs, found);
file = r_fs_open (fs, found, false);
if (file) {
r_fs_read (fs, file, 0, file->size);
if (file->off == offset) {
@ -467,10 +489,9 @@ static void r_fs_find_name_aux(RFS* fs, const char* name, const char* glob, RLis
R_API RList* r_fs_find_name(RFS* fs, const char* name, const char* glob) {
RList* list = r_list_newf (free);
if (!list) {
return NULL;
if (list) {
r_fs_find_name_aux (fs, name, glob, list);
}
r_fs_find_name_aux (fs, name, glob, list);
return list;
}
@ -484,7 +505,7 @@ R_API RFSFile* r_fs_slurp(RFS* fs, const char* path) {
continue;
}
if (root->p->open && root->p->read && root->p->close) {
file = root->p->open (root, path);
file = root->p->open (root, path, false);
if (file) {
root->p->read (file, 0, file->size); //file->data
}else {

View File

@ -3,7 +3,7 @@
#include <r_fs.h>
#include "grubfs.h"
static RFSFile* FSP(_open)(RFSRoot *root, const char *path) {
static RFSFile* FSP(_open)(RFSRoot *root, const char *path, bool create) {
RFSFile *file = r_fs_file_new (root, path);
GrubFS *gfs = grubfs_new (&FSIPTR, &root->iob);
file->ptr = gfs;

View File

@ -1,4 +1,4 @@
/* radare - LGPL - Copyright 2017 - pancake */
/* radare - LGPL - Copyright 2017-2019 - pancake */
#include <r_fs.h>
#include <r_lib.h>
@ -6,24 +6,34 @@
typedef RList *(*DirHandler)(RFSRoot *root, const char *path);
typedef RFSFile *(*CatHandler)(RFSRoot *root, const char *path, RFSFile *file);
typedef RFSFile *(*CatHandler)(RFSRoot *root, RFSFile *file, const char *path);
typedef bool (*WriteHandler)(RFSFile *file, ut64 addr, const ut8 *data, int len);
typedef struct {
const char *path;
DirHandler dir;
CatHandler cat;
WriteHandler write;
} Routes;
static RFSFile *__cfg_cat(RFSRoot *root, const char *path, RFSFile *file);
static RFSFile *__version(RFSRoot *root, const char *path, RFSFile *file);
static RFSFile *__flags_cat(RFSRoot *root, RFSFile *file, const char *path);
static RFSFile *__cfg_cat(RFSRoot *root, RFSFile *file, const char *path);
static RFSFile *__seek_cat(RFSRoot *root, RFSFile *file, const char *path);
static RFSFile *__bsize_cat(RFSRoot *root, RFSFile *file, const char *path);
static bool __cfg_write(RFSFile *file, ut64 addr, const ut8 *data, int len);
static bool __seek_write(RFSFile *file, ut64 addr, const ut8 *data, int len);
static bool __bsize_write(RFSFile *file, ut64 addr, const ut8 *data, int len);
static RFSFile *__version(RFSRoot *root, RFSFile *file, const char *path);
static RList *__root(RFSRoot *root, const char *path);
static RList *__cfg(RFSRoot *root, const char *path);
static RList *__flags(RFSRoot *root, const char *path);
static Routes routes[] = {
{"/cfg", &__cfg, &__cfg_cat},
{"/flags", &__flags},
{"/version", NULL, &__version},
{"/cfg", &__cfg, &__cfg_cat, &__cfg_write },
{"/flags", &__flags, &__flags_cat, NULL},
{"/version", NULL, &__version, NULL},
{"/seek", NULL, &__seek_cat, &__seek_write },
{"/bsize", NULL, &__bsize_cat, &__bsize_write },
{"/", &__root},
{NULL, NULL}
};
@ -64,22 +74,40 @@ static RList *fscmd(RFSRoot *root, const char *cmd, int type) {
return NULL;
}
static RFSFile* fs_r2_open(RFSRoot *root, const char *path) {
static RFSFile* fs_r2_open(RFSRoot *root, const char *path, bool create) {
int i;
for (i = 0; routes[i].path; i++) {
if (routes[i].cat && !strncmp (path, routes[i].path, strlen (routes[i].path))) {
return routes[i].cat (root, path, NULL);
const char *cwd = routes[i].path;
if (routes[i].cat && !strncmp (path, cwd, strlen (cwd))) {
return routes[i].cat (root, NULL, path);
}
}
return NULL;
}
static bool fs_r2_write(RFSFile *file, ut64 addr, const ut8 *data, int len) {
int i;
const char *path = file->path;
const char *name = file->name;
for (i = 0; routes[i].path; i++) {
if (routes[i].write) {
if (!strncmp (name, routes[i].path + 1, strlen (routes[i].path) - 1)) {
return routes[i].write (file, addr, data, len);
}
if (!strncmp (path, routes[i].path, strlen (routes[i].path))) {
return routes[i].write (file, addr, data, len);
}
}
}
return false;
}
static bool fs_r2_read(RFSFile *file, ut64 addr, int len) {
int i;
const char *path = file->name;
for (i = 0; routes[i].path; i++) {
if (routes[i].cat && !strncmp (path, routes[i].path, strlen (routes[i].path))) {
return routes[i].cat (file->root, path, file);
return routes[i].cat (file->root, file, path);
}
}
return false;
@ -90,34 +118,93 @@ static void fs_r2_close(RFSFile *file) {
//fclose (file->ptr);
}
static RFSFile *__version(RFSRoot *root, const char *path, RFSFile *file) {
if (strlen (path) < 6) {
return NULL;
}
char *a = strdup (path + 5);
r_str_replace_char (a, '/', '.');
static RFSFile *__version(RFSRoot *root, RFSFile *file, const char *path) {
char *res = root->cob.cmdstrf (root->cob.core, "?V");
/// root->iob.io->cb_printf ("%s\n", res);
// eprintf ("%s", res);
// RFSFile *
if (!file) {
file = r_fs_file_new (root, path);
}
file->ptr = NULL;
free (file->data);
file->data = (ut8*)res;
file->p = root->p;
file->size = strlen (res);
return file;
}
static RFSFile *__flags_cat(RFSRoot *root, RFSFile *file, const char *path) {
r_return_val_if_fail (root && path, NULL);
const char *last = r_str_rchr (path, NULL, '/');
if (last) {
last++;
} else {
last = path;
}
char *res = root->cob.cmdstrf (root->cob.core, "?v %s", last);
if (file) {
file->ptr = NULL;
file->data = (ut8*)res;
file->p = root->p;
file->size = strlen (res);
free (res);
} else {
file = r_fs_file_new (root, path);
file->ptr = NULL;
file->data = NULL;
file->data = (ut8*)res;
file->p = root->p;
file->size = strlen (res);
}
free (a);
return file;
}
static RFSFile *__cfg_cat(RFSRoot *root, const char *path, RFSFile *file) {
static bool __bsize_write(RFSFile *file, ut64 addr, const ut8 *data, int len) {
void *core = file->root->cob.core;
char *res = file->root->cob.cmdstrf (core, "b %s", data);
free (res);
return true;
}
static RFSFile *__bsize_cat(RFSRoot *root, RFSFile *file, const char *path) {
char *res = root->cob.cmdstrf (root->cob.core, "b");
if (!file) {
file = r_fs_file_new (root, path);
}
file->ptr = NULL;
file->data = (ut8*)res;
file->p = root->p;
file->size = strlen (res);
return file;
}
static bool __seek_write(RFSFile *file, ut64 addr, const ut8 *data, int len) {
void *core = file->root->cob.core;
char *res = file->root->cob.cmdstrf (core, "s %s", data);
free (res);
return true;
}
static RFSFile *__seek_cat(RFSRoot *root, RFSFile *file, const char *path) {
char *res = root->cob.cmdstrf (root->cob.core, "s");
if (!file) {
file = r_fs_file_new (root, path);
}
file->ptr = NULL;
file->data = (ut8*)res;
file->p = root->p;
file->size = strlen (res);
return file;
}
static bool __cfg_write(RFSFile *file, ut64 addr, const ut8 *data, int len) {
const char *a = file->name;
void *core = file->root->cob.core;
char *prefix = strdup (file->path + strlen ("/cfg/"));
char *res = file->root->cob.cmdstrf (core, "e %s.%s=%s", prefix, a, data);
free (prefix);
free (res);
return true;
}
static RFSFile *__cfg_cat(RFSRoot *root, RFSFile *file, const char *path) {
if (strlen (path) < 6) {
return NULL;
}
@ -126,19 +213,13 @@ static RFSFile *__cfg_cat(RFSRoot *root, const char *path, RFSFile *file) {
char *res = root->cob.cmdstrf (root->cob.core, "e %s", a);
// root->iob.io->cb_printf ("%s\n", res);
// eprintf ("%s", res);
if (file) {
file->ptr = NULL;
file->data = (ut8*)res;
file->p = root->p;
file->size = strlen (res);
free (res);
} else {
if (!file) {
file = r_fs_file_new (root, path);
file->ptr = NULL;
file->data = NULL;
file->p = root->p;
file->size = strlen (res);
}
file->ptr = NULL;
file->data = (ut8*)res;
file->p = root->p;
file->size = strlen (res);
return file;
}
@ -222,8 +303,9 @@ RFSPlugin r_fs_plugin_r2 = {
.name = "r2",
.desc = "r2-based filesystem",
.license = "MIT",
.open = fs_r2_open,
.read = fs_r2_read,
.open = fs_r2_open, // open == read
.read = fs_r2_read, // read == open
.write = fs_r2_write,
.close = fs_r2_close,
.dir = &fs_r2_dir,
.mount = fs_r2_mount,

View File

@ -1,9 +1,32 @@
/* radare2 - LGPL - Copyright 2018 - pancake */
/* radare2 - LGPL - Copyright 2018-2019 - pancake */
#include <r_fs.h>
#define PROMPT_PATH_BUFSIZE 1024
static bool handlePipes(RFS *fs, char *msg, const char *cwd) {
char *red = strchr (msg, '>');
if (red) {
*red++ = 0;
r_str_trim (msg);
red = strdup (r_str_trim (red));
if (*red != '/') {
char *blu = r_str_newf ("%s/%s", cwd, red);
free (red);
red = blu;
} else {
}
RFSFile *f = r_fs_open (fs, red, true);
r_fs_write (fs, f, 0, (const ut8 *)msg, strlen (msg));
free (red);
r_fs_close (fs, f);
r_fs_file_free (f);
return true;
}
return false;
}
R_API int r_fs_shell_prompt(RFSShell* shell, RFS* fs, const char* root) {
char buf[PROMPT_PATH_BUFSIZE];
char path[PROMPT_PATH_BUFSIZE];
@ -73,8 +96,21 @@ R_API int r_fs_shell_prompt(RFSShell* shell, RFS* fs, const char* root) {
r_list_free (list);
return true;
}
if (buf[0] == '!') {
if (buf[0] == '#') {
// comment
continue;
} else if (buf[0] == ':') {
char *msg = fs->cob.cmdstr (fs->cob.core, buf+1);
printf ("%s\n", msg);
free (msg);
} else if (buf[0] == '!') {
r_sandbox_system (buf + 1, 1);
} else if (!strncmp (buf, "echo", 4)) {
char *msg = r_str_trim (strdup (buf + 4));
if (!handlePipes (fs, msg, path)) {
printf ("%s\n", msg);
}
free (msg);
} else if (!strncmp (buf, "ls", 2)) {
char *ptr = str;
r_list_free (list);
@ -155,9 +191,11 @@ R_API int r_fs_shell_prompt(RFSShell* shell, RFS* fs, const char* root) {
found = true;
}
}
#if 0
if (!found) {
strcpy (path, opath);
}
#endif
}
} else if (!memcmp (buf, "cat ", 4)) {
input = buf + 3;
@ -175,10 +213,20 @@ R_API int r_fs_shell_prompt(RFSShell* shell, RFS* fs, const char* root) {
}
strncat (str, "/", sizeof (str) - strlen (str) - 1);
strncat (str, input, sizeof (str) - strlen (str) - 1);
file = r_fs_open (fs, str);
char *p = strchr (str, '>');
if (p) {
*p = 0;
}
file = r_fs_open (fs, str, false);
if (file) {
if (p) {
*p = '>';
}
r_fs_read (fs, file, 0, file->size);
write (1, file->data, file->size);
if (!handlePipes (fs, (char *)file->data, path)) {
write (1, file->data, file->size);
}
write (1, "\n", 1);
r_fs_close (fs, file);
} else {
eprintf ("Cannot open file\n");
@ -217,7 +265,7 @@ R_API int r_fs_shell_prompt(RFSShell* shell, RFS* fs, const char* root) {
}
strcat (s, "/");
strcat (s, input);
file = r_fs_open (fs, s);
file = r_fs_open (fs, s, false);
if (file) {
r_fs_read (fs, file, 0, file->size);
r_file_dump (input, file->data, file->size, 0);

View File

@ -58,7 +58,9 @@ typedef struct r_fs_plugin_t {
const char *desc;
const char *license;
RFSFile* (*slurp)(RFSRoot *root, const char *path);
RFSFile* (*open)(RFSRoot *root, const char *path);
RFSFile* (*open)(RFSRoot *root, const char *path, bool create);
bool (*unlink)(RFSRoot *root, const char *path);
bool (*write)(RFSFile *fs, ut64 addr, const ut8 *data, int len);
bool (*read)(RFSFile *fs, ut64 addr, int len);
void (*close)(RFSFile *fs);
RList *(*dir)(RFSRoot *root, const char *path, int view);
@ -115,9 +117,10 @@ R_API void r_fs_del(RFS *fs, RFSPlugin *p);
R_API RFSRoot *r_fs_mount(RFS* fs, const char *fstype, const char *path, ut64 delta);
R_API bool r_fs_umount(RFS* fs, const char *path);
R_API RList *r_fs_root(RFS *fs, const char *path);
R_API RFSFile *r_fs_open(RFS* fs, const char *path);
R_API RFSFile *r_fs_open(RFS* fs, const char *path, bool create);
R_API void r_fs_close(RFS* fs, RFSFile *file);
R_API int r_fs_read(RFS* fs, RFSFile *file, ut64 addr, int len);
R_API int r_fs_write(RFS* fs, RFSFile* file, ut64 addr, const ut8 *data, int len);
R_API RFSFile *r_fs_slurp(RFS* fs, const char *path);
R_API RList *r_fs_dir(RFS* fs, const char *path);
R_API int r_fs_dir_dump(RFS* fs, const char *path, const char *name);