2017-08-22 07:42:16 +00:00
|
|
|
/* radare2 - LGPL - Copyright 2008-2017 - condret, pancake, alvaro_fe */
|
2009-02-05 21:08:46 +00:00
|
|
|
|
2017-08-22 07:42:16 +00:00
|
|
|
#include <r_io.h>
|
|
|
|
#include <sdb.h>
|
|
|
|
#include <config.h>
|
2017-05-09 12:25:57 +00:00
|
|
|
|
2014-01-21 14:40:10 +00:00
|
|
|
R_LIB_VERSION (r_io);
|
2013-06-14 00:51:33 +00:00
|
|
|
|
2017-09-07 15:47:39 +00:00
|
|
|
static void fd_read_at_wrap (RIO *io, int fd, ut64 addr, ut8 *buf, int len, RIOMap *map, void *user) {
|
|
|
|
bool *ret = (bool *)user;
|
|
|
|
*ret &= (r_io_fd_read_at (io, fd, addr, buf, len) == len);
|
2017-08-24 18:12:02 +00:00
|
|
|
}
|
|
|
|
|
2017-09-07 15:47:39 +00:00
|
|
|
static void fd_write_at_wrap (RIO *io, int fd, ut64 addr, ut8 *buf, int len, RIOMap *map, void *user) {
|
|
|
|
bool *ret = (bool *)user;
|
|
|
|
*ret &= (r_io_fd_write_at (io, fd, addr, buf, len) == len);
|
2017-08-24 18:12:02 +00:00
|
|
|
}
|
|
|
|
|
2017-09-07 15:47:39 +00:00
|
|
|
static void al_fd_read_at_wrap (RIO *io, int fd, ut64 addr, ut8 *buf, int len, RIOMap *map, void *user) {
|
2017-08-24 18:12:02 +00:00
|
|
|
RIOAccessLog *log = (RIOAccessLog *)user;
|
|
|
|
RIOAccessLogElement *ale = R_NEW0(RIOAccessLogElement);
|
|
|
|
int rlen = r_io_fd_read_at (io, fd, addr, buf, len);
|
|
|
|
if (ale) {
|
|
|
|
ale->expect_len = len;
|
|
|
|
ale->len = rlen;
|
|
|
|
ale->buf_idx = (int)(size_t)(buf - log->buf);
|
|
|
|
ale->flags = map->flags;
|
|
|
|
ale->fd = fd;
|
|
|
|
ale->mapid = map->id;
|
|
|
|
ale->paddr = addr;
|
|
|
|
ale->vaddr = map->from + (addr - map->delta);
|
|
|
|
r_list_append (log->log, ale);
|
|
|
|
} else {
|
|
|
|
log->allocation_failed = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-07 15:47:39 +00:00
|
|
|
static void al_fd_write_at_wrap (RIO *io, int fd, ut64 addr, ut8 *buf, int len, RIOMap *map, void *user) {
|
2017-08-24 18:12:02 +00:00
|
|
|
RIOAccessLog *log = (RIOAccessLog *)user;
|
|
|
|
RIOAccessLogElement *ale = R_NEW0(RIOAccessLogElement);
|
|
|
|
int rlen = r_io_fd_write_at (io, fd, addr, buf, len);
|
|
|
|
if (ale) {
|
|
|
|
ale->expect_len = len;
|
|
|
|
ale->len = rlen;
|
|
|
|
ale->buf_idx = (int)(size_t)(buf - log->buf);
|
|
|
|
ale->flags = map->flags;
|
|
|
|
ale->fd = fd;
|
|
|
|
ale->mapid = map->id;
|
|
|
|
ale->paddr = addr;
|
|
|
|
ale->vaddr = map->from + (addr - map->delta);
|
|
|
|
r_list_append (log->log, ale);
|
|
|
|
} else {
|
|
|
|
log->allocation_failed = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-07 15:47:39 +00:00
|
|
|
typedef void (*cbOnIterMap) (RIO *io, int fd, ut64 addr, ut8 *buf, int len, RIOMap *map, void *user);
|
2017-08-23 14:45:05 +00:00
|
|
|
|
2017-09-07 15:47:39 +00:00
|
|
|
static void onIterMap(SdbListIter* iter, RIO* io, ut64 vaddr, ut8* buf,
|
|
|
|
int len, int match_flg, cbOnIterMap op, void *user) {
|
|
|
|
ut64 vendaddr = UT64_MAX;
|
|
|
|
if (!io || !iter || !buf || len < 1) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// this block is not that much elegant
|
|
|
|
if (UT64_ADD_OVFCHK (len - 1, vaddr)) {
|
|
|
|
int nlen = (int) (UT64_MAX - vaddr + 1);
|
|
|
|
onIterMap (iter->p, io, 0LL, buf + nlen, len - nlen, match_flg, op, user);
|
|
|
|
} else {
|
|
|
|
vendaddr = vaddr + len - 1;
|
|
|
|
}
|
|
|
|
RIOMap *map = (RIOMap*) iter->data;
|
|
|
|
// search for next map or end of list
|
|
|
|
while (!r_io_map_is_in_range (map, vaddr, vendaddr)) {
|
|
|
|
iter = iter->p;
|
|
|
|
// end of list
|
2017-09-13 10:13:20 +00:00
|
|
|
if (!iter) {
|
2017-09-07 15:47:39 +00:00
|
|
|
// pread/pwrite
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
map = (RIOMap*) iter->data;
|
|
|
|
}
|
|
|
|
if (map->from >= vaddr) {
|
|
|
|
onIterMap (iter->p, io, vaddr, buf, (int) (map->from - vaddr), match_flg, op, user);
|
|
|
|
buf = buf + (map->from - vaddr);
|
|
|
|
vaddr = map->from;
|
|
|
|
len = (int) (vendaddr - vaddr + 1);
|
|
|
|
if (vendaddr <= map->to) {
|
|
|
|
if (((map->flags & match_flg) == match_flg) || io->p_cache) {
|
|
|
|
op (io, map->fd, map->delta, buf, len, map, user);
|
2017-08-23 13:48:35 +00:00
|
|
|
}
|
2017-09-07 15:47:39 +00:00
|
|
|
} else {
|
|
|
|
if (((map->flags & match_flg) == match_flg) || io->p_cache) {
|
|
|
|
int nlen = len - (int) (vendaddr - map->to);
|
|
|
|
op (io, map->fd, map->delta, buf, nlen, map, user);
|
2017-08-23 13:48:35 +00:00
|
|
|
}
|
2017-09-07 15:47:39 +00:00
|
|
|
vaddr = map->to + 1;
|
|
|
|
buf = buf + (len - (int) (vendaddr - map->to));
|
|
|
|
len = (int) (vendaddr - map->to);
|
|
|
|
onIterMap (iter->p, io, vaddr, buf, len, match_flg, op, user);
|
2017-08-27 15:59:11 +00:00
|
|
|
}
|
2017-09-07 15:47:39 +00:00
|
|
|
} else {
|
|
|
|
if (vendaddr <= map->to) {
|
|
|
|
if (((map->flags & match_flg) == match_flg) || io->p_cache) {
|
|
|
|
//can it overflow
|
|
|
|
op (io, map->fd, map->delta + (vaddr - map->from), buf, len, map, user);
|
2017-08-23 13:48:35 +00:00
|
|
|
}
|
2017-09-07 15:47:39 +00:00
|
|
|
} else {
|
|
|
|
if (((map->flags & match_flg) == match_flg) || io->p_cache) {
|
|
|
|
int nlen = len - (int) (vendaddr - map->to);
|
|
|
|
op (io, map->fd, map->delta + (vaddr - map->from), buf, nlen, map, user);
|
|
|
|
}
|
|
|
|
vaddr = map->to + 1;
|
|
|
|
buf = buf + (len - (int) (vendaddr - map->to));
|
|
|
|
len = (int) (vendaddr - map->to);
|
|
|
|
onIterMap (iter->p, io, vaddr, buf, len, match_flg, op, user);
|
2017-08-23 13:48:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-08-18 18:03:29 +00:00
|
|
|
|
2017-08-22 07:42:16 +00:00
|
|
|
R_API RIO* r_io_new() {
|
|
|
|
return r_io_init (R_NEW0 (RIO));
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API RIO* r_io_init(RIO* io) {
|
2016-11-04 00:30:35 +00:00
|
|
|
if (!io) {
|
|
|
|
return NULL;
|
|
|
|
}
|
2017-09-04 19:41:09 +00:00
|
|
|
io->addrbytes = 1;
|
2011-04-18 22:59:16 +00:00
|
|
|
r_io_desc_init (io);
|
2017-08-22 07:42:16 +00:00
|
|
|
r_io_map_init (io);
|
|
|
|
r_io_section_init (io);
|
2014-01-21 14:40:10 +00:00
|
|
|
r_io_cache_init (io);
|
|
|
|
r_io_plugin_init (io);
|
2017-08-22 07:42:16 +00:00
|
|
|
r_io_undo_init (io);
|
2010-05-20 15:40:58 +00:00
|
|
|
return io;
|
2009-08-22 01:54:24 +00:00
|
|
|
}
|
|
|
|
|
2014-01-21 14:40:10 +00:00
|
|
|
R_API RBuffer *r_io_read_buf(RIO *io, ut64 addr, int len) {
|
2014-07-11 20:56:21 +00:00
|
|
|
RBuffer *b = R_NEW0 (RBuffer);
|
2015-12-08 13:59:30 +00:00
|
|
|
if (!b) return NULL;
|
2010-03-23 22:26:59 +00:00
|
|
|
b->buf = malloc (len);
|
2015-12-08 13:59:30 +00:00
|
|
|
if (!b->buf) {
|
|
|
|
free (b);
|
|
|
|
return NULL;
|
|
|
|
}
|
2010-03-23 22:26:59 +00:00
|
|
|
len = r_io_read_at (io, addr, b->buf, len);
|
2015-12-08 21:35:39 +00:00
|
|
|
b->length = (len < 0)? 0: len;
|
2009-09-08 01:08:46 +00:00
|
|
|
return b;
|
|
|
|
}
|
|
|
|
|
2014-01-21 14:40:10 +00:00
|
|
|
R_API int r_io_write_buf(RIO *io, struct r_buf_t *b) {
|
2013-11-14 12:52:03 +00:00
|
|
|
return r_io_write_at (io, b->base, b->buf, b->length);
|
2009-09-08 01:08:46 +00:00
|
|
|
}
|
|
|
|
|
2017-08-22 07:42:16 +00:00
|
|
|
R_API void r_io_free(RIO *io) {
|
2016-12-15 09:22:40 +00:00
|
|
|
if (!io) {
|
2017-08-22 07:42:16 +00:00
|
|
|
return;
|
2016-12-15 09:22:40 +00:00
|
|
|
}
|
2017-08-22 07:42:16 +00:00
|
|
|
r_io_fini (io);
|
2013-01-12 03:29:45 +00:00
|
|
|
r_cache_free (io->buffer);
|
2010-01-31 01:30:59 +00:00
|
|
|
free (io);
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
|
|
|
|
2013-06-08 22:10:16 +00:00
|
|
|
R_API RIODesc *r_io_open_as(RIO *io, const char *urihandler, const char *file, int flags, int mode) {
|
2017-08-25 23:05:22 +00:00
|
|
|
char *uri = (urihandler && *urihandler)
|
|
|
|
? r_str_newf ("%s://%s", urihandler, file)
|
|
|
|
: strdup (file);
|
|
|
|
RIODesc *ret = r_io_open_nomap (io, uri, flags, mode);
|
2010-01-31 01:30:59 +00:00
|
|
|
free (uri);
|
2009-09-07 20:01:34 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2017-05-03 15:19:49 +00:00
|
|
|
R_API RIODesc *r_io_open_nomap(RIO *io, const char *uri, int flags, int mode) {
|
2017-08-19 02:23:51 +00:00
|
|
|
RIODesc *desc;
|
|
|
|
if (!io) {
|
2017-05-03 15:19:49 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2017-08-19 02:23:51 +00:00
|
|
|
desc = r_io_desc_open (io, uri, flags, mode);
|
|
|
|
if ((io->autofd || !io->desc) && desc) {
|
2017-05-03 15:19:49 +00:00
|
|
|
io->desc = desc;
|
|
|
|
}
|
2017-08-19 02:23:51 +00:00
|
|
|
//set desc as current if autofd or io->desc==NULL
|
2011-01-20 21:52:16 +00:00
|
|
|
return desc;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
|
|
|
|
2017-08-22 07:42:16 +00:00
|
|
|
/* opens a file and maps it to 0x0 */
|
|
|
|
R_API RIODesc* r_io_open(RIO* io, const char* uri, int flags, int mode) {
|
|
|
|
RIODesc* desc;
|
|
|
|
if (!io || !io->maps) {
|
2014-09-05 22:30:52 +00:00
|
|
|
return NULL;
|
2014-09-05 14:53:08 +00:00
|
|
|
}
|
2017-08-22 07:42:16 +00:00
|
|
|
desc = r_io_open_nomap (io, uri, flags, mode);
|
|
|
|
if (!desc) {
|
|
|
|
return NULL;
|
2016-07-03 20:36:42 +00:00
|
|
|
}
|
2017-08-27 23:27:28 +00:00
|
|
|
r_io_map_new (io, desc->fd, desc->flags, 0LL, 0LL, r_io_desc_size (desc), true);
|
2014-09-05 14:53:08 +00:00
|
|
|
return desc;
|
|
|
|
}
|
|
|
|
|
2017-08-22 07:42:16 +00:00
|
|
|
/* opens a file and maps it to an offset specified by the "at"-parameter */
|
|
|
|
R_API RIODesc* r_io_open_at(RIO* io, const char* uri, int flags, int mode, ut64 at) {
|
|
|
|
RIODesc* desc;
|
|
|
|
ut64 size;
|
|
|
|
if (!io || !io->maps) {
|
2014-09-05 22:30:52 +00:00
|
|
|
return NULL;
|
2017-08-22 07:42:16 +00:00
|
|
|
}
|
|
|
|
desc = r_io_open_nomap (io, uri, flags, mode);
|
|
|
|
if (!desc) {
|
2014-09-05 22:30:52 +00:00
|
|
|
return NULL;
|
2014-01-24 03:05:35 +00:00
|
|
|
}
|
2017-08-22 07:42:16 +00:00
|
|
|
size = r_io_desc_size (desc);
|
|
|
|
// second map
|
2017-08-24 05:39:12 +00:00
|
|
|
if (size && ((UT64_MAX - size + 1) < at)) {
|
2017-08-22 07:42:16 +00:00
|
|
|
// split map into 2 maps if only 1 big map results into interger overflow
|
2017-08-27 23:27:28 +00:00
|
|
|
r_io_map_new (io, desc->fd, desc->flags, UT64_MAX - at + 1, 0LL, size - (UT64_MAX - at) - 1, true);
|
2017-08-22 07:42:16 +00:00
|
|
|
// someone pls take a look at this confusing stuff
|
2017-08-24 05:39:12 +00:00
|
|
|
size = UT64_MAX - at + 1;
|
2014-10-20 08:29:32 +00:00
|
|
|
}
|
2017-08-27 23:27:28 +00:00
|
|
|
r_io_map_new (io, desc->fd, desc->flags, 0LL, at, size, true); // first map
|
2017-08-22 07:42:16 +00:00
|
|
|
return desc;
|
2014-10-20 08:29:32 +00:00
|
|
|
}
|
|
|
|
|
2017-08-22 07:42:16 +00:00
|
|
|
/* opens many files, without mapping them. This should be discussed */
|
|
|
|
R_API RList* r_io_open_many(RIO* io, const char* uri, int flags, int mode) {
|
|
|
|
RList* desc_list;
|
|
|
|
RListIter* iter;
|
|
|
|
RIODesc* desc;
|
|
|
|
if (!io || !io->files || !uri) {
|
|
|
|
return NULL;
|
2009-08-22 04:54:41 +00:00
|
|
|
}
|
2017-08-22 07:42:16 +00:00
|
|
|
RIOPlugin* plugin = r_io_plugin_resolve (io, uri, 1);
|
|
|
|
if (!plugin || !plugin->open_many || !plugin->close) {
|
|
|
|
return NULL;
|
2017-05-03 15:19:49 +00:00
|
|
|
}
|
2017-08-22 07:42:16 +00:00
|
|
|
if (!(desc_list = plugin->open_many (io, uri, flags, mode))) {
|
|
|
|
return NULL;
|
2017-05-03 15:19:49 +00:00
|
|
|
}
|
2017-08-22 07:42:16 +00:00
|
|
|
r_list_foreach (desc_list, iter, desc) {
|
|
|
|
if (desc) {
|
|
|
|
if (!desc->plugin) {
|
|
|
|
desc->plugin = plugin;
|
|
|
|
}
|
|
|
|
if (!desc->uri) {
|
|
|
|
desc->uri = strdup (uri);
|
|
|
|
}
|
|
|
|
//should autofd be honored here?
|
|
|
|
r_io_desc_add (io, desc);
|
2017-08-24 05:39:12 +00:00
|
|
|
if (!io->desc) {
|
2017-08-22 07:42:16 +00:00
|
|
|
io->desc = desc;
|
|
|
|
}
|
2017-05-03 15:19:49 +00:00
|
|
|
}
|
|
|
|
}
|
2017-08-22 07:42:16 +00:00
|
|
|
return desc_list;
|
2009-08-22 04:54:41 +00:00
|
|
|
}
|
|
|
|
|
2017-08-22 07:42:16 +00:00
|
|
|
R_API bool r_io_reopen(RIO* io, int fd, int flags, int mode) {
|
|
|
|
RIODesc *old, *new;
|
|
|
|
char *uri;
|
|
|
|
if (!(old = r_io_desc_get (io, fd))) {
|
|
|
|
return false;
|
2014-04-23 23:04:25 +00:00
|
|
|
}
|
2017-08-22 07:42:16 +00:00
|
|
|
//does this really work, or do we have to handler debuggers ugly
|
|
|
|
uri = old->referer? old->referer: old->uri;
|
|
|
|
if (!(new = r_io_open_nomap (io, uri, flags, mode))) {
|
|
|
|
return false;
|
2014-04-05 05:39:17 +00:00
|
|
|
}
|
2017-08-22 07:42:16 +00:00
|
|
|
r_io_desc_exchange (io, old->fd, new->fd);
|
|
|
|
return r_io_desc_close (old); // magic
|
2011-10-25 18:30:05 +00:00
|
|
|
}
|
|
|
|
|
2017-08-22 07:42:16 +00:00
|
|
|
R_API int r_io_close_all(RIO* io) { // what about undo?
|
|
|
|
if (!io) {
|
|
|
|
return false;
|
2017-01-30 08:57:07 +00:00
|
|
|
}
|
2017-08-22 07:42:16 +00:00
|
|
|
r_io_desc_fini (io);
|
|
|
|
r_io_map_fini (io);
|
|
|
|
r_io_section_fini (io);
|
|
|
|
ls_free (io->plugins);
|
|
|
|
r_list_free (io->cache);
|
|
|
|
r_io_desc_init (io);
|
|
|
|
r_io_map_init (io);
|
|
|
|
r_io_section_init (io);
|
|
|
|
r_io_cache_init (io);
|
|
|
|
r_io_plugin_init (io);
|
|
|
|
return true;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
2013-03-17 23:38:04 +00:00
|
|
|
|
2017-08-22 07:42:16 +00:00
|
|
|
R_API int r_io_pread_at(RIO* io, ut64 paddr, ut8* buf, int len) {
|
2017-05-03 15:19:49 +00:00
|
|
|
if (!io || !buf || len < 1) {
|
|
|
|
return 0;
|
2017-04-24 19:45:33 +00:00
|
|
|
}
|
2017-05-03 15:19:49 +00:00
|
|
|
if (io->ff) {
|
|
|
|
memset (buf, 0xff, len);
|
2017-04-24 19:45:33 +00:00
|
|
|
}
|
2017-08-22 07:42:16 +00:00
|
|
|
return r_io_desc_read_at (io->desc, paddr, buf, len);
|
2017-05-03 15:19:49 +00:00
|
|
|
}
|
|
|
|
|
2017-08-22 07:42:16 +00:00
|
|
|
R_API int r_io_pwrite_at(RIO* io, ut64 paddr, const ut8* buf, int len) {
|
|
|
|
if (!io) {
|
2017-08-14 00:55:47 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2017-08-22 07:42:16 +00:00
|
|
|
return r_io_desc_write_at (io->desc, paddr, buf, len);
|
2009-09-02 00:10:51 +00:00
|
|
|
}
|
|
|
|
|
2017-08-22 14:52:40 +00:00
|
|
|
R_API bool r_io_vread_at(RIO* io, ut64 vaddr, ut8* buf, int len) {
|
2017-09-07 15:47:39 +00:00
|
|
|
bool ret = true;
|
2017-08-22 14:52:40 +00:00
|
|
|
if (!io || !buf || (len < 1)) {
|
|
|
|
return false;
|
2016-12-21 21:13:16 +00:00
|
|
|
}
|
2017-08-22 07:42:16 +00:00
|
|
|
if (io->ff) {
|
|
|
|
memset (buf, 0xff, len);
|
2016-12-21 21:13:16 +00:00
|
|
|
}
|
2017-08-22 07:42:16 +00:00
|
|
|
r_io_map_cleanup (io);
|
|
|
|
if (!io->maps) {
|
2017-08-24 14:25:19 +00:00
|
|
|
return false;
|
2014-05-19 00:52:51 +00:00
|
|
|
}
|
2017-09-07 15:47:39 +00:00
|
|
|
onIterMap (io->maps->tail, io, vaddr, buf, len, R_IO_READ, fd_read_at_wrap, &ret);
|
|
|
|
return ret;
|
2017-08-22 14:52:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
R_API bool r_io_vwrite_at(RIO* io, ut64 vaddr, const ut8* buf, int len) {
|
2017-09-07 15:47:39 +00:00
|
|
|
bool ret = true;
|
2017-08-22 14:52:40 +00:00
|
|
|
if (!io || !buf || (len < 1)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
r_io_map_cleanup (io);
|
|
|
|
if (!io->maps) {
|
2017-08-24 14:25:19 +00:00
|
|
|
return false;
|
2017-08-22 08:46:48 +00:00
|
|
|
}
|
2017-09-07 15:47:39 +00:00
|
|
|
onIterMap (io->maps->tail, io, vaddr, (ut8*)buf, len, R_IO_WRITE, fd_write_at_wrap, &ret);
|
|
|
|
return ret;
|
2014-03-25 03:00:26 +00:00
|
|
|
}
|
2017-08-22 21:55:18 +00:00
|
|
|
|
2017-08-24 18:12:02 +00:00
|
|
|
R_API RIOAccessLog *r_io_al_vread_at(RIO* io, ut64 vaddr, ut8* buf, int len) {
|
|
|
|
RIOAccessLog *log;
|
|
|
|
if (!io || !buf || (len < 1)) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
r_io_map_cleanup (io);
|
|
|
|
if (!io->maps || !(log = r_io_accesslog_new ())) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
if (io->ff) {
|
|
|
|
memset (buf, 0xff, len);
|
|
|
|
}
|
|
|
|
log->buf = buf;
|
2017-09-07 15:47:39 +00:00
|
|
|
onIterMap (io->maps->tail, io, vaddr, buf, len, R_IO_READ, al_fd_read_at_wrap, log);
|
2017-08-24 18:12:02 +00:00
|
|
|
return log;
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API RIOAccessLog *r_io_al_vwrite_at(RIO* io, ut64 vaddr, const ut8* buf, int len) {
|
|
|
|
RIOAccessLog *log;
|
|
|
|
if (!io || !buf || (len < 1)) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
r_io_map_cleanup (io);
|
|
|
|
if (!io->maps || !(log = r_io_accesslog_new ())) {
|
|
|
|
return NULL;
|
|
|
|
}
|
2017-08-25 16:56:29 +00:00
|
|
|
log->buf = (ut8*)buf;
|
2017-09-07 15:47:39 +00:00
|
|
|
onIterMap (io->maps->tail, io, vaddr, (ut8*)buf, len, R_IO_WRITE, al_fd_write_at_wrap, log);
|
2017-08-24 18:12:02 +00:00
|
|
|
return log;
|
|
|
|
}
|
|
|
|
|
2017-08-22 14:52:40 +00:00
|
|
|
R_API bool r_io_read_at(RIO* io, ut64 addr, ut8* buf, int len) {
|
|
|
|
bool ret;
|
|
|
|
if (!io || !buf || len < 1) {
|
|
|
|
return false;
|
2015-12-07 21:35:34 +00:00
|
|
|
}
|
2017-08-22 07:42:16 +00:00
|
|
|
if (io->buffer_enabled) {
|
2017-08-22 14:52:40 +00:00
|
|
|
return !!r_io_buffer_read (io, addr, buf, len);
|
|
|
|
}
|
|
|
|
if (io->va) {
|
|
|
|
ret = r_io_vread_at (io, addr, buf, len);
|
|
|
|
} else {
|
2017-08-24 18:12:02 +00:00
|
|
|
ret = (r_io_pread_at (io, addr, buf, len) > 0);
|
2014-05-22 06:58:03 +00:00
|
|
|
}
|
2017-08-22 07:42:16 +00:00
|
|
|
if (io->cached_read) {
|
2017-08-22 23:09:45 +00:00
|
|
|
(void)r_io_cache_read (io, addr, buf, len);
|
2016-12-19 03:56:27 +00:00
|
|
|
}
|
2009-02-05 21:08:46 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2017-08-26 19:25:40 +00:00
|
|
|
R_API RIOAccessLog *r_io_al_read_at(RIO* io, ut64 addr, ut8* buf, int len) {
|
|
|
|
RIOAccessLog *log;
|
2017-08-29 10:39:04 +00:00
|
|
|
RIOAccessLogElement *ale = NULL;
|
2017-08-26 19:25:40 +00:00
|
|
|
int rlen;
|
|
|
|
if (!io || !buf || (len < 1)) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
if (io->va) {
|
|
|
|
return r_io_al_vread_at (io, addr, buf, len);
|
|
|
|
}
|
|
|
|
if (!(log = r_io_accesslog_new ())) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
log->buf = buf;
|
|
|
|
if (io->ff) {
|
|
|
|
memset (buf, 0xff, len);
|
|
|
|
}
|
|
|
|
rlen = r_io_pread_at (io, addr, buf, len);
|
|
|
|
if (io->cached_read) {
|
|
|
|
(void)r_io_cache_read (io, addr, buf, len);
|
|
|
|
}
|
|
|
|
if (!(ale = R_NEW0 (RIOAccessLogElement))) {
|
|
|
|
log->allocation_failed = true;
|
|
|
|
} else {
|
|
|
|
ale->paddr = ale->vaddr = addr;
|
|
|
|
ale->len = rlen;
|
|
|
|
ale->expect_len = len;
|
|
|
|
ale->flags = io->desc ? io->desc->flags : 0;
|
|
|
|
ale->fd = io->desc ? io->desc->fd : 0; //xxx
|
|
|
|
r_list_append (log->log, ale);
|
|
|
|
}
|
|
|
|
return log;
|
|
|
|
}
|
|
|
|
|
2017-08-22 14:52:40 +00:00
|
|
|
R_API bool r_io_write_at(RIO* io, ut64 addr, const ut8* buf, int len) {
|
|
|
|
int i;
|
2017-09-07 15:47:39 +00:00
|
|
|
bool ret = false;
|
2017-08-14 00:55:47 +00:00
|
|
|
ut8 *mybuf = (ut8*)buf;
|
2017-08-22 14:52:40 +00:00
|
|
|
if (!io || !buf || len < 1) {
|
|
|
|
return false;
|
2017-08-14 00:55:47 +00:00
|
|
|
}
|
2017-08-22 07:42:16 +00:00
|
|
|
if (io->write_mask) {
|
2017-08-14 00:55:47 +00:00
|
|
|
mybuf = r_mem_dup ((void*)buf, len);
|
|
|
|
for (i = 0; i < len; i++) {
|
|
|
|
//this sucks
|
2017-08-22 23:09:45 +00:00
|
|
|
mybuf[i] &= io->write_mask[i % io->write_mask_len];
|
2017-08-14 00:55:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (io->cached) {
|
2017-09-07 15:47:39 +00:00
|
|
|
r_io_cache_write (io, addr, mybuf, len); //can be ignored for the return
|
2017-08-14 00:55:47 +00:00
|
|
|
} else if (io->va) {
|
|
|
|
ret = r_io_vwrite_at (io, addr, mybuf, len);
|
|
|
|
} else {
|
2017-08-24 18:12:02 +00:00
|
|
|
ret = (r_io_pwrite_at (io, addr, mybuf, len) > 0);
|
2017-08-14 00:55:47 +00:00
|
|
|
}
|
|
|
|
if (buf != mybuf) {
|
|
|
|
free (mybuf);
|
|
|
|
}
|
|
|
|
return ret;
|
2009-09-02 00:10:51 +00:00
|
|
|
}
|
2009-08-22 04:54:41 +00:00
|
|
|
|
2017-08-22 14:52:40 +00:00
|
|
|
R_API bool r_io_read(RIO* io, ut8* buf, int len) {
|
2016-06-20 07:12:44 +00:00
|
|
|
if (!io) {
|
2017-08-22 14:52:40 +00:00
|
|
|
return false;
|
2011-10-25 18:30:05 +00:00
|
|
|
}
|
2017-08-22 14:52:40 +00:00
|
|
|
if (r_io_read_at (io, io->off, buf, len)) {
|
|
|
|
io->off += len;
|
|
|
|
return true;
|
2016-06-20 07:12:44 +00:00
|
|
|
}
|
2017-08-22 14:52:40 +00:00
|
|
|
return false;
|
2017-08-22 07:42:16 +00:00
|
|
|
}
|
|
|
|
|
2017-08-22 14:52:40 +00:00
|
|
|
R_API bool r_io_write(RIO* io, ut8* buf, int len) {
|
|
|
|
if (!io || !buf || len < 1) {
|
|
|
|
return false;
|
2016-06-20 07:12:44 +00:00
|
|
|
}
|
2017-08-22 14:52:40 +00:00
|
|
|
if (r_io_write_at (io, io->off, buf, len)) {
|
|
|
|
io->off += len;
|
|
|
|
return true;
|
2016-06-20 09:08:21 +00:00
|
|
|
}
|
2017-08-22 14:52:40 +00:00
|
|
|
return false;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
|
|
|
|
2017-08-22 07:42:16 +00:00
|
|
|
R_API ut64 r_io_size(RIO* io) {
|
2017-08-24 05:39:12 +00:00
|
|
|
// TODO: rethink this, maybe not needed
|
2017-05-03 15:19:49 +00:00
|
|
|
return io? r_io_desc_size (io->desc): 0LL;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
|
|
|
|
2017-08-22 07:42:16 +00:00
|
|
|
R_API bool r_io_is_listener(RIO* io) {
|
|
|
|
if (io && io->desc && io->desc->plugin && io->desc->plugin->listener) {
|
|
|
|
return io->desc->plugin->listener (io->desc);
|
2016-10-09 21:56:52 +00:00
|
|
|
}
|
2017-08-22 07:42:16 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API int r_io_system(RIO* io, const char* cmd) {
|
|
|
|
if (io && io->desc && io->desc->plugin && io->desc->plugin->system) {
|
|
|
|
return io->desc->plugin->system (io, io->desc, cmd);
|
|
|
|
}
|
|
|
|
return -1;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
|
|
|
|
2017-08-22 07:42:16 +00:00
|
|
|
R_API bool r_io_resize(RIO* io, ut64 newsize) {
|
2017-08-31 15:23:31 +00:00
|
|
|
if (io) {
|
|
|
|
return r_io_desc_resize (io->desc, newsize);
|
2016-06-19 22:29:41 +00:00
|
|
|
}
|
2017-08-22 07:42:16 +00:00
|
|
|
return false;
|
2016-06-19 22:29:41 +00:00
|
|
|
}
|
|
|
|
|
2017-08-22 07:42:16 +00:00
|
|
|
R_API bool r_io_close(RIO *io) {
|
|
|
|
return io ? r_io_desc_close (io->desc) : false;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
2009-09-10 20:51:34 +00:00
|
|
|
|
2017-08-22 07:42:16 +00:00
|
|
|
R_API int r_io_extend_at(RIO* io, ut64 addr, ut64 size) {
|
|
|
|
ut64 cur_size, tmp_size;
|
|
|
|
ut8* buffer;
|
|
|
|
if (!io || !io->desc || !io->desc->plugin || !size) {
|
|
|
|
return false;
|
2017-03-02 21:47:59 +00:00
|
|
|
}
|
2017-08-22 07:42:16 +00:00
|
|
|
if (io->desc->plugin->extend) {
|
|
|
|
int ret;
|
|
|
|
ut64 cur_off = io->off;
|
|
|
|
r_io_seek (io, addr, R_IO_SEEK_SET);
|
2017-09-01 15:09:17 +00:00
|
|
|
ret = r_io_desc_extend (io->desc, size);
|
2017-08-22 07:42:16 +00:00
|
|
|
//no need to seek here
|
2017-08-24 05:39:12 +00:00
|
|
|
io->off = cur_off;
|
2017-08-22 07:42:16 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
if ((io->desc->flags & R_IO_RW) != R_IO_RW) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
cur_size = r_io_desc_size (io->desc);
|
|
|
|
if (addr > cur_size) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if ((UT64_MAX - size) < cur_size) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (!r_io_resize (io, cur_size + size)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if ((tmp_size = cur_size - addr) == 0LL) {
|
|
|
|
return true;
|
|
|
|
}
|
2017-08-22 23:33:36 +00:00
|
|
|
if (!(buffer = calloc (1, (size_t) tmp_size + 1))) {
|
2017-08-22 07:42:16 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
r_io_pread_at (io, addr, buffer, (int) tmp_size);
|
2017-08-22 23:33:36 +00:00
|
|
|
/* fill with null bytes */
|
|
|
|
ut8 *empty = calloc (1, size);
|
|
|
|
if (empty) {
|
|
|
|
r_io_pwrite_at (io, addr, empty, size);
|
|
|
|
free (empty);
|
|
|
|
}
|
2017-08-22 07:42:16 +00:00
|
|
|
r_io_pwrite_at (io, addr + size, buffer, (int) tmp_size);
|
|
|
|
free (buffer);
|
|
|
|
return true;
|
2015-01-22 01:22:29 +00:00
|
|
|
}
|
|
|
|
|
2017-08-22 07:42:16 +00:00
|
|
|
R_API bool r_io_set_write_mask(RIO* io, const ut8* mask, int len) {
|
|
|
|
if (!io || len < 1) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
free (io->write_mask);
|
|
|
|
if (!mask) {
|
|
|
|
io->write_mask = NULL;
|
|
|
|
io->write_mask_len = 0;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
io->write_mask = (ut8*) malloc (len);
|
|
|
|
memcpy (io->write_mask, mask, len);
|
|
|
|
io->write_mask_len = len;
|
|
|
|
return true;
|
2017-05-03 15:19:49 +00:00
|
|
|
}
|
|
|
|
|
2017-08-22 07:42:16 +00:00
|
|
|
R_API int r_io_bind(RIO* io, RIOBind* bnd) {
|
2017-05-03 15:19:49 +00:00
|
|
|
if (!io || !bnd) {
|
|
|
|
return false;
|
|
|
|
}
|
2009-09-10 20:51:34 +00:00
|
|
|
bnd->io = io;
|
2015-09-14 00:08:31 +00:00
|
|
|
bnd->init = true;
|
2017-05-03 15:19:49 +00:00
|
|
|
bnd->desc_use = r_io_use_fd;
|
|
|
|
bnd->desc_get = r_io_desc_get;
|
|
|
|
bnd->desc_size = r_io_desc_size;
|
|
|
|
bnd->open = r_io_open_nomap;
|
|
|
|
bnd->open_at = r_io_open_at;
|
2017-08-22 07:42:16 +00:00
|
|
|
bnd->close = r_io_fd_close;
|
2009-09-10 20:51:34 +00:00
|
|
|
bnd->read_at = r_io_read_at;
|
2017-08-26 19:25:40 +00:00
|
|
|
bnd->al_read_at = r_io_al_read_at;
|
2009-09-10 20:51:34 +00:00
|
|
|
bnd->write_at = r_io_write_at;
|
2016-10-08 00:39:50 +00:00
|
|
|
bnd->system = r_io_system;
|
2017-08-22 21:07:35 +00:00
|
|
|
bnd->fd_open = r_io_fd_open;
|
|
|
|
bnd->fd_close = r_io_fd_close;
|
|
|
|
bnd->fd_seek = r_io_fd_seek;
|
|
|
|
bnd->fd_size = r_io_fd_size;
|
|
|
|
bnd->fd_read = r_io_fd_read;
|
|
|
|
bnd->fd_write = r_io_fd_write;
|
|
|
|
bnd->fd_read_at = r_io_fd_read_at;
|
|
|
|
bnd->fd_write_at = r_io_fd_write_at;
|
2017-08-23 00:04:47 +00:00
|
|
|
bnd->fd_is_dbg = r_io_fd_is_dbg;
|
|
|
|
bnd->fd_get_name = r_io_fd_get_name;
|
2017-08-26 19:25:40 +00:00
|
|
|
bnd->al_sort = r_io_accesslog_sort;
|
|
|
|
bnd->al_free = r_io_accesslog_free;
|
|
|
|
bnd->al_buf_byflags = r_io_accesslog_getf_buf_byflags;
|
2017-08-23 22:19:57 +00:00
|
|
|
bnd->is_valid_offset = r_io_is_valid_offset;
|
2017-08-22 07:42:16 +00:00
|
|
|
bnd->sections_vget = r_io_sections_vget;
|
2017-05-03 15:19:49 +00:00
|
|
|
bnd->section_add = r_io_section_add;
|
2017-08-23 20:28:49 +00:00
|
|
|
bnd->sect_vget = r_io_section_vget;
|
2015-09-14 00:08:31 +00:00
|
|
|
return true;
|
2009-09-10 20:51:34 +00:00
|
|
|
}
|
2011-02-04 23:20:28 +00:00
|
|
|
|
2011-02-05 11:51:37 +00:00
|
|
|
/* moves bytes up (+) or down (-) within the specified range */
|
2017-08-22 07:42:16 +00:00
|
|
|
R_API int r_io_shift(RIO* io, ut64 start, ut64 end, st64 move) {
|
|
|
|
ut8* buf;
|
2011-02-07 08:46:01 +00:00
|
|
|
ut64 chunksize = 0x10000;
|
2017-08-22 07:42:16 +00:00
|
|
|
ut64 src, shiftsize = r_num_abs (move);
|
|
|
|
if (!shiftsize || (end - start) <= shiftsize) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
ut64 rest = (end - start) - shiftsize;
|
|
|
|
if (!(buf = calloc (1, chunksize + 1))) {
|
2016-09-25 22:45:28 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (move > 0) {
|
2015-12-08 21:35:39 +00:00
|
|
|
src = end - shiftsize;
|
2016-09-25 22:45:28 +00:00
|
|
|
} else {
|
|
|
|
src = start + shiftsize;
|
|
|
|
}
|
2015-12-08 21:35:39 +00:00
|
|
|
while (rest > 0) {
|
2016-10-09 21:56:52 +00:00
|
|
|
if (chunksize > rest) {
|
|
|
|
chunksize = rest;
|
|
|
|
}
|
|
|
|
if (move > 0) {
|
|
|
|
src -= chunksize;
|
|
|
|
}
|
2011-02-05 11:51:37 +00:00
|
|
|
r_io_read_at (io, src, buf, chunksize);
|
2015-12-08 21:35:39 +00:00
|
|
|
r_io_write_at (io, src + move, buf, chunksize);
|
2016-10-09 21:56:52 +00:00
|
|
|
if (move < 0) {
|
|
|
|
src += chunksize;
|
|
|
|
}
|
2011-02-05 11:51:37 +00:00
|
|
|
rest -= chunksize;
|
|
|
|
}
|
|
|
|
free (buf);
|
2015-09-14 00:08:31 +00:00
|
|
|
return true;
|
2011-02-05 11:51:37 +00:00
|
|
|
}
|
2012-07-06 00:17:44 +00:00
|
|
|
|
2017-08-22 07:42:16 +00:00
|
|
|
R_API int r_io_create(RIO* io, const char* file, int mode, int type) {
|
|
|
|
if (io && io->desc && io->desc->plugin && io->desc->plugin->create) {
|
|
|
|
return io->desc->plugin->create (io, file, mode, type);
|
2016-09-25 22:45:28 +00:00
|
|
|
}
|
|
|
|
if (type == 'd' || type == 1) {
|
2012-08-10 09:35:38 +00:00
|
|
|
return r_sys_mkdir (file);
|
2016-09-25 22:45:28 +00:00
|
|
|
}
|
2016-01-19 12:16:24 +00:00
|
|
|
return r_sandbox_creat (file, mode);
|
2012-07-06 00:17:44 +00:00
|
|
|
}
|
2014-01-26 00:06:17 +00:00
|
|
|
|
2017-08-22 07:42:16 +00:00
|
|
|
R_API ut64 r_io_seek(RIO* io, ut64 offset, int whence) {
|
2014-09-18 19:27:06 +00:00
|
|
|
if (!io) {
|
2017-08-22 14:52:40 +00:00
|
|
|
return 0LL;
|
2017-04-05 08:59:37 +00:00
|
|
|
}
|
2017-08-22 07:42:16 +00:00
|
|
|
switch (whence) {
|
|
|
|
case R_IO_SEEK_SET:
|
|
|
|
io->off = offset;
|
|
|
|
break;
|
|
|
|
case R_IO_SEEK_CUR:
|
|
|
|
io->off += offset;
|
|
|
|
break;
|
|
|
|
case R_IO_SEEK_END:
|
|
|
|
default:
|
2017-08-26 09:03:46 +00:00
|
|
|
io->off = r_io_desc_seek (io->desc, offset, whence);
|
2017-08-22 07:42:16 +00:00
|
|
|
break;
|
2016-08-07 12:07:52 +00:00
|
|
|
}
|
2017-08-22 07:42:16 +00:00
|
|
|
return io->off;
|
2017-05-03 15:19:49 +00:00
|
|
|
}
|
|
|
|
|
2017-08-22 07:42:16 +00:00
|
|
|
//remove all descs and maps
|
|
|
|
R_API int r_io_fini(RIO* io) {
|
|
|
|
if (!io) {
|
|
|
|
return false;
|
2017-05-03 15:19:49 +00:00
|
|
|
}
|
2017-08-22 07:42:16 +00:00
|
|
|
r_io_desc_cache_fini_all (io);
|
|
|
|
r_io_desc_fini (io);
|
|
|
|
r_io_map_fini (io);
|
|
|
|
r_io_section_fini (io);
|
|
|
|
ls_free (io->plugins);
|
|
|
|
r_list_free (io->cache);
|
|
|
|
r_list_free (io->undo.w_list);
|
|
|
|
if (io->runprofile) {
|
|
|
|
R_FREE (io->runprofile);
|
2017-05-03 15:19:49 +00:00
|
|
|
}
|
2017-08-22 07:42:16 +00:00
|
|
|
return true;
|
2014-09-18 19:27:06 +00:00
|
|
|
}
|