2016-05-03 21:09:00 +00:00
|
|
|
/* radare - LGPL - Copyright 2008-2016 - pancake */
|
2009-02-05 21:08:46 +00:00
|
|
|
|
|
|
|
#include "r_io.h"
|
|
|
|
#include "r_util.h"
|
|
|
|
#include <stdio.h>
|
|
|
|
|
2014-01-21 14:40:10 +00:00
|
|
|
R_LIB_VERSION (r_io);
|
2013-06-14 00:51:33 +00:00
|
|
|
|
2015-07-08 19:41:17 +00:00
|
|
|
/* allocate 128 MB */
|
2015-12-08 21:35:39 +00:00
|
|
|
#define R_IO_MAX_ALLOC (1024 * 1024 * 128)
|
2015-07-08 19:41:17 +00:00
|
|
|
|
2014-05-28 02:34:12 +00:00
|
|
|
// XXX: this is buggy. must use seek+read
|
|
|
|
#define USE_CACHE 1
|
2015-02-09 22:13:49 +00:00
|
|
|
// the new io is buggy //liar
|
2014-06-13 15:48:33 +00:00
|
|
|
#define USE_NEW_IO 0
|
2014-04-23 23:04:25 +00:00
|
|
|
#define DO_THE_IO_DBG 0
|
|
|
|
#define IO_IFDBG if (DO_THE_IO_DBG == 1)
|
2014-03-25 03:00:26 +00:00
|
|
|
|
2015-12-08 21:35:39 +00:00
|
|
|
static ut8 *r_io_desc_read(RIO *io, RIODesc *desc, ut64 *out_sz);
|
|
|
|
static RIO *r_io_bind_get_io(RIOBind *bnd);
|
2014-04-29 16:10:35 +00:00
|
|
|
|
2012-10-22 08:12:13 +00:00
|
|
|
R_API RIO *r_io_new() {
|
2014-07-11 20:56:21 +00:00
|
|
|
RIO *io = R_NEW0 (RIO);
|
2011-04-18 22:59:16 +00:00
|
|
|
if (!io) return NULL;
|
2014-06-04 23:50:56 +00:00
|
|
|
io->buffer = r_cache_new (); // RCache is a list of ranged buffers. maybe rename?
|
2011-04-18 22:59:16 +00:00
|
|
|
io->write_mask_fd = -1;
|
2015-12-08 21:35:39 +00:00
|
|
|
io->cb_printf = (void *)printf;
|
|
|
|
io->bits = (sizeof (void *) == 8)? 64: 32;
|
2016-05-03 21:09:00 +00:00
|
|
|
io->ff = true;
|
|
|
|
io->Oxff = 0xff;
|
2015-08-16 15:45:23 +00:00
|
|
|
io->aslr = 0;
|
2011-04-18 22:59:16 +00:00
|
|
|
io->raised = -1;
|
2015-09-14 00:08:31 +00:00
|
|
|
io->autofd = true;
|
2011-04-18 22:59:16 +00:00
|
|
|
r_io_map_init (io);
|
|
|
|
r_io_desc_init (io);
|
|
|
|
r_io_undo_init (io);
|
2014-01-21 14:40:10 +00:00
|
|
|
r_io_cache_init (io);
|
|
|
|
r_io_plugin_init (io);
|
|
|
|
r_io_section_init (io);
|
2016-01-26 22:36:02 +00:00
|
|
|
{
|
|
|
|
char *env = r_sys_getenv ("R_IO_MAX_ALLOC");
|
|
|
|
if (env) {
|
|
|
|
io->maxalloc = r_num_get (NULL, env);
|
|
|
|
free (env);
|
|
|
|
}
|
|
|
|
}
|
2010-05-20 15:40:58 +00:00
|
|
|
return io;
|
2009-08-22 01:54:24 +00:00
|
|
|
}
|
|
|
|
|
2011-02-16 08:29:09 +00:00
|
|
|
R_API void r_io_raise(RIO *io, int fd) {
|
|
|
|
io->raised = fd;
|
|
|
|
}
|
|
|
|
|
2010-08-22 19:42:08 +00:00
|
|
|
R_API int r_io_is_listener(RIO *io) {
|
2010-08-22 22:48:44 +00:00
|
|
|
if (io && io->plugin && io->plugin->listener)
|
2014-05-28 02:34:12 +00:00
|
|
|
return io->plugin->listener (io->desc);
|
2015-09-14 00:08:31 +00:00
|
|
|
return false;
|
2010-08-22 19:42:08 +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
|
|
|
}
|
|
|
|
|
2012-01-26 02:18:45 +00:00
|
|
|
R_API RIO *r_io_free(RIO *io) {
|
2011-12-16 15:33:06 +00:00
|
|
|
if (!io) return NULL;
|
2016-06-19 22:29:41 +00:00
|
|
|
r_list_free (io->plugins);
|
2012-01-26 02:18:45 +00:00
|
|
|
r_list_free (io->sections);
|
|
|
|
r_list_free (io->maps);
|
2013-11-17 10:25:45 +00:00
|
|
|
r_list_free (io->undo.w_list);
|
2013-01-12 03:29:45 +00:00
|
|
|
r_cache_free (io->buffer);
|
2013-11-17 10:25:45 +00:00
|
|
|
r_list_free (io->cache);
|
2012-02-05 00:14:09 +00:00
|
|
|
r_io_desc_fini (io);
|
2010-01-31 01:30:59 +00:00
|
|
|
free (io);
|
2009-08-22 03:11:33 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2009-09-05 23:58:02 +00:00
|
|
|
/* used by uri handler plugins */
|
2013-06-08 22:08:17 +00:00
|
|
|
R_API int r_io_redirect(RIO *io, const char *file) {
|
2010-01-31 01:30:59 +00:00
|
|
|
free (io->redirect);
|
2012-02-09 00:38:16 +00:00
|
|
|
io->redirect = file? strdup (file): NULL;
|
2009-02-05 21:08:46 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
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) {
|
2011-01-20 21:52:16 +00:00
|
|
|
RIODesc *ret;
|
2010-01-31 01:30:59 +00:00
|
|
|
char *uri;
|
2011-07-06 01:01:21 +00:00
|
|
|
int urilen, hlen = strlen (urihandler);
|
2015-12-08 21:35:39 +00:00
|
|
|
urilen = hlen + strlen (file) + 5;
|
2011-07-06 01:01:21 +00:00
|
|
|
uri = malloc (urilen);
|
2016-09-19 12:44:47 +00:00
|
|
|
if (!uri)
|
2011-01-20 21:52:16 +00:00
|
|
|
return NULL;
|
2015-12-08 21:35:39 +00:00
|
|
|
if (hlen > 0)
|
|
|
|
snprintf (uri, urilen, "%s://%s", urihandler, file);
|
2011-07-06 01:01:21 +00:00
|
|
|
else strncpy (uri, file, urilen);
|
2014-09-06 21:05:59 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2013-06-08 22:08:17 +00:00
|
|
|
static inline RIODesc *__getioplugin(RIO *io, const char *_uri, int flags, int mode) {
|
2014-04-29 16:10:35 +00:00
|
|
|
RIOPlugin *plugin;
|
2011-01-20 21:52:16 +00:00
|
|
|
RIODesc *desc = NULL;
|
2015-11-24 09:17:24 +00:00
|
|
|
char *uri = strdup (_uri? _uri: "");
|
2014-11-03 10:47:51 +00:00
|
|
|
char *redir = NULL;
|
2011-11-14 21:46:23 +00:00
|
|
|
for (;;) {
|
2014-01-24 03:05:35 +00:00
|
|
|
plugin = r_io_plugin_resolve (io, uri, 0);
|
2011-11-14 21:46:23 +00:00
|
|
|
if (plugin && plugin->open) {
|
|
|
|
desc = plugin->open (io, uri, flags, mode);
|
|
|
|
if (io->redirect) {
|
2014-11-03 10:47:51 +00:00
|
|
|
redir = uri;
|
2013-06-08 22:08:17 +00:00
|
|
|
uri = strdup (io->redirect);
|
2011-11-14 21:46:23 +00:00
|
|
|
r_io_redirect (io, NULL);
|
|
|
|
continue;
|
|
|
|
}
|
2014-04-29 16:10:35 +00:00
|
|
|
if (desc) {
|
2014-09-25 16:04:07 +00:00
|
|
|
desc->uri = uri;
|
2014-11-03 10:47:51 +00:00
|
|
|
desc->referer = redir;
|
2016-06-20 07:30:29 +00:00
|
|
|
io->plugin = plugin;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
2009-09-02 00:10:51 +00:00
|
|
|
}
|
2011-11-14 21:46:23 +00:00
|
|
|
break;
|
2009-09-02 00:10:51 +00:00
|
|
|
}
|
2014-04-29 16:10:35 +00:00
|
|
|
if (!desc) {
|
|
|
|
plugin = r_io_plugin_get_default (io, uri, 0);
|
2016-06-20 07:30:29 +00:00
|
|
|
desc = (plugin && plugin->open)
|
|
|
|
? plugin->open (io, uri, flags, mode)
|
|
|
|
: NULL;
|
2014-04-29 16:10:35 +00:00
|
|
|
if (desc) {
|
2014-09-25 16:04:07 +00:00
|
|
|
desc->uri = uri;
|
2016-06-20 07:30:29 +00:00
|
|
|
io->plugin = plugin;
|
2014-04-29 16:10:35 +00:00
|
|
|
}
|
|
|
|
}
|
2014-10-16 22:04:52 +00:00
|
|
|
if (!desc) {
|
2014-09-25 16:04:07 +00:00
|
|
|
free (uri);
|
2014-10-16 22:04:52 +00:00
|
|
|
io->plugin = NULL;
|
|
|
|
}
|
2013-05-31 00:09:45 +00:00
|
|
|
return desc;
|
|
|
|
}
|
|
|
|
|
2014-01-24 03:05:35 +00:00
|
|
|
static inline RList *__getioplugin_many(RIO *io, const char *_uri, int flags, int mode) {
|
|
|
|
RIOPlugin *plugin, *iop = NULL;
|
|
|
|
RList *list_fds = NULL;
|
|
|
|
RListIter *iter;
|
|
|
|
RIODesc *desc;
|
|
|
|
char *uri = strdup (_uri);
|
|
|
|
for (;;) {
|
|
|
|
// resolve
|
|
|
|
plugin = r_io_plugin_resolve (io, uri, 1);
|
|
|
|
if (plugin && plugin->open_many) {
|
|
|
|
// open
|
|
|
|
list_fds = plugin->open_many (io, uri, flags, mode);
|
|
|
|
if (io->redirect) {
|
|
|
|
free (uri);
|
|
|
|
uri = strdup (io->redirect);
|
|
|
|
r_io_redirect (io, NULL);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2014-09-25 16:04:07 +00:00
|
|
|
if (!list_fds) {
|
|
|
|
free (uri);
|
|
|
|
return NULL;
|
|
|
|
}
|
2014-01-24 03:05:35 +00:00
|
|
|
|
|
|
|
r_list_foreach (list_fds, iter, desc) {
|
2016-06-19 22:29:41 +00:00
|
|
|
desc->uri = strdup (uri);
|
2014-01-24 03:05:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
io->plugin = iop;
|
|
|
|
free (uri);
|
|
|
|
return list_fds;
|
|
|
|
}
|
|
|
|
|
2014-09-06 21:05:59 +00:00
|
|
|
R_API RIODesc *r_io_open_nomap(RIO *io, const char *file, int flags, int mode) {
|
2014-09-05 22:30:52 +00:00
|
|
|
RIODesc *desc;
|
2016-06-20 07:30:29 +00:00
|
|
|
if (!io || !file || io->redirect) {
|
2014-09-05 22:30:52 +00:00
|
|
|
return NULL;
|
2014-04-23 23:04:25 +00:00
|
|
|
}
|
2016-06-20 07:30:29 +00:00
|
|
|
desc = __getioplugin (io, file, flags, mode);
|
2014-04-29 16:10:35 +00:00
|
|
|
if (desc) {
|
2011-01-20 21:52:16 +00:00
|
|
|
r_io_desc_add (io, desc);
|
2014-06-03 15:10:38 +00:00
|
|
|
if (io->autofd || !io->desc)
|
2014-06-03 13:55:56 +00:00
|
|
|
r_io_use_desc (io, desc);
|
2015-12-08 21:35:39 +00:00
|
|
|
} // else eprintf ("r_io_open_nomap: Unable to open file: %s\n", file);
|
2011-01-20 21:52:16 +00:00
|
|
|
return desc;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
|
|
|
|
2015-12-08 21:35:39 +00:00
|
|
|
R_API RIODesc *r_io_open_at(RIO *io, const char *file, int flags, int mode, ut64 maddr) {
|
2014-09-05 22:30:52 +00:00
|
|
|
RIODesc *desc;
|
2014-09-05 14:53:08 +00:00
|
|
|
ut64 size;
|
2016-06-20 07:12:44 +00:00
|
|
|
if (!io || !file || io->redirect) {
|
2014-09-05 22:30:52 +00:00
|
|
|
return NULL;
|
2014-09-05 14:53:08 +00:00
|
|
|
}
|
2016-06-20 07:12:44 +00:00
|
|
|
desc = __getioplugin (io, file, flags, mode);
|
2014-09-05 14:53:08 +00:00
|
|
|
if (desc) {
|
|
|
|
r_io_desc_add (io, desc);
|
|
|
|
size = r_io_desc_size (io, desc);
|
2016-06-20 07:30:29 +00:00
|
|
|
if (io->autofd || !io->desc) {
|
2014-09-05 14:53:08 +00:00
|
|
|
r_io_use_desc (io, desc);
|
2016-06-20 07:30:29 +00:00
|
|
|
}
|
2014-09-05 14:53:08 +00:00
|
|
|
r_io_map_new (io, desc->fd, mode, 0, maddr, size);
|
2016-07-03 20:36:42 +00:00
|
|
|
} else {
|
|
|
|
eprintf ("r_io_open_at: Unable to open file: %s\n", file);
|
|
|
|
}
|
2014-09-05 14:53:08 +00:00
|
|
|
return desc;
|
|
|
|
}
|
|
|
|
|
2015-12-08 21:35:39 +00:00
|
|
|
R_API RIODesc *r_io_open(RIO *io, const char *file, int flags, int mode) {
|
2014-09-06 21:05:59 +00:00
|
|
|
return r_io_open_at (io, file, flags, mode, 0LL);
|
|
|
|
}
|
|
|
|
|
2014-01-24 03:05:35 +00:00
|
|
|
R_API RList *r_io_open_many(RIO *io, const char *file, int flags, int mode) {
|
|
|
|
RIODesc *desc;
|
|
|
|
RListIter *desc_iter = NULL;
|
|
|
|
int fd;
|
2014-09-05 22:30:52 +00:00
|
|
|
RList *list_fds;
|
2015-12-08 21:35:39 +00:00
|
|
|
if (!io || !file || io->redirect)
|
2014-09-05 22:30:52 +00:00
|
|
|
return NULL;
|
|
|
|
list_fds = __getioplugin_many (io, file, flags, mode);
|
2014-01-24 03:05:35 +00:00
|
|
|
|
2014-09-05 22:30:52 +00:00
|
|
|
if (!list_fds)
|
|
|
|
return NULL;
|
2014-01-24 03:05:35 +00:00
|
|
|
|
|
|
|
r_list_foreach (list_fds, desc_iter, desc) {
|
|
|
|
fd = -1;
|
|
|
|
if (desc) fd = desc->fd;
|
|
|
|
if (fd >= 0) r_io_desc_add (io, desc);
|
|
|
|
}
|
|
|
|
return list_fds;
|
|
|
|
}
|
|
|
|
|
2015-12-08 21:35:39 +00:00
|
|
|
R_API int r_io_reopen(RIO *io, RIODesc *desc, int flags, int mode) {
|
2014-10-20 08:29:32 +00:00
|
|
|
RIODesc *n = NULL;
|
|
|
|
RListIter *iter;
|
|
|
|
RIOMap *map;
|
|
|
|
if (desc && desc->uri && io && io->files && (desc == r_io_desc_get (io, desc->fd))) {
|
|
|
|
n = __getioplugin (io, desc->uri, flags, mode);
|
2016-06-20 07:30:29 +00:00
|
|
|
if (!n) {
|
2015-09-14 00:08:31 +00:00
|
|
|
return false;
|
2016-06-20 07:30:29 +00:00
|
|
|
}
|
2014-10-20 08:29:32 +00:00
|
|
|
r_io_section_rm_all (io, desc->fd);
|
|
|
|
if (io->maps) {
|
|
|
|
r_list_foreach (io->maps, iter, map) {
|
2014-10-22 18:23:34 +00:00
|
|
|
if (map->fd == desc->fd) {
|
2014-10-20 08:29:32 +00:00
|
|
|
map->fd = n->fd;
|
2014-10-22 18:23:34 +00:00
|
|
|
map->flags &= n->flags;
|
|
|
|
}
|
2014-10-20 08:29:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (desc->plugin && desc->plugin->close)
|
2015-12-08 21:35:39 +00:00
|
|
|
desc->plugin->close (desc); //free desc->data
|
2014-10-20 08:29:32 +00:00
|
|
|
free (desc->name);
|
|
|
|
free (desc->uri);
|
|
|
|
*desc = *n;
|
|
|
|
free (n);
|
2015-09-14 00:08:31 +00:00
|
|
|
return true;
|
2014-10-20 08:29:32 +00:00
|
|
|
}
|
2015-09-14 00:08:31 +00:00
|
|
|
return false;
|
2014-10-20 08:29:32 +00:00
|
|
|
}
|
|
|
|
|
2015-12-08 21:35:39 +00:00
|
|
|
R_API int r_io_use_desc(RIO *io, RIODesc *d) {
|
2014-05-29 13:27:18 +00:00
|
|
|
if (d) {
|
2014-05-28 02:34:12 +00:00
|
|
|
io->desc = d;
|
|
|
|
io->plugin = d->plugin;
|
2015-09-14 00:08:31 +00:00
|
|
|
return true;
|
2009-08-22 04:54:41 +00:00
|
|
|
}
|
2015-09-14 00:08:31 +00:00
|
|
|
return false;
|
2011-01-20 21:52:16 +00:00
|
|
|
}
|
|
|
|
|
2015-12-08 21:35:39 +00:00
|
|
|
R_API RIODesc *r_io_use_fd(RIO *io, int fd) {
|
2014-04-23 23:04:25 +00:00
|
|
|
RIODesc *desc = r_io_desc_get (io, fd);
|
2014-05-28 02:34:12 +00:00
|
|
|
if (!desc) return NULL;
|
|
|
|
io->desc = desc;
|
2014-04-23 23:04:25 +00:00
|
|
|
io->plugin = desc->plugin;
|
2014-05-28 02:34:12 +00:00
|
|
|
return desc;
|
2009-08-22 04:54:41 +00:00
|
|
|
}
|
|
|
|
|
2015-12-08 13:59:30 +00:00
|
|
|
static bool readcache = false;
|
|
|
|
|
2014-11-23 21:44:38 +00:00
|
|
|
R_API int r_io_read_internal(RIO *io, ut8 *buf, int len) {
|
2014-04-23 23:04:25 +00:00
|
|
|
int bytes_read = 0;
|
2015-12-08 13:59:30 +00:00
|
|
|
const char *source = NULL;
|
|
|
|
if (io->desc && io->desc->plugin && io->desc->plugin->read) {
|
|
|
|
source = io->desc->plugin->name;
|
2014-05-28 02:34:12 +00:00
|
|
|
bytes_read = io->desc->plugin->read (io, io->desc, buf, len);
|
2015-12-08 13:59:30 +00:00
|
|
|
#if 1
|
|
|
|
if (readcache) {
|
2015-12-08 21:35:39 +00:00
|
|
|
if (bytes_read > 0) {
|
|
|
|
readcache = false;
|
2015-12-08 13:59:30 +00:00
|
|
|
bytes_read = r_io_cache_write (io, io->off, buf, len);
|
2015-12-08 21:35:39 +00:00
|
|
|
readcache = true;
|
2015-12-08 13:59:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
2014-05-28 02:34:12 +00:00
|
|
|
} else if (!io->desc) {
|
2015-04-29 16:35:13 +00:00
|
|
|
if (io->files && r_list_length (io->files) != 0) {
|
2014-09-20 17:30:14 +00:00
|
|
|
eprintf ("Something really bad has happened, and r2 is going to die soon. sorry! :-(\n");
|
2015-04-29 16:35:13 +00:00
|
|
|
}
|
2015-12-08 13:59:30 +00:00
|
|
|
source = "FAILED";
|
2014-04-23 23:04:25 +00:00
|
|
|
bytes_read = 0;
|
|
|
|
} else {
|
2015-12-08 13:59:30 +00:00
|
|
|
source = "File";
|
2014-05-28 02:34:12 +00:00
|
|
|
bytes_read = read (io->desc->fd, buf, len);
|
2014-04-23 23:04:25 +00:00
|
|
|
}
|
|
|
|
IO_IFDBG {
|
2014-05-28 02:34:12 +00:00
|
|
|
if (io->desc) eprintf ("Data source: %s\n", io->desc->name);
|
2014-05-26 09:33:39 +00:00
|
|
|
eprintf ("Asked for %d bytes, provided %d from %s\n",
|
2015-12-08 13:59:30 +00:00
|
|
|
len, bytes_read, source);
|
2014-04-05 05:39:17 +00:00
|
|
|
}
|
2014-04-23 23:04:25 +00:00
|
|
|
return bytes_read;
|
2011-10-25 18:30:05 +00:00
|
|
|
}
|
|
|
|
|
2011-02-12 00:52:41 +00:00
|
|
|
R_API int r_io_read(RIO *io, ut8 *buf, int len) {
|
2013-06-04 21:49:28 +00:00
|
|
|
int ret;
|
2015-12-08 21:35:39 +00:00
|
|
|
if (!io || !io->desc || !buf || io->off == UT64_MAX)
|
2014-05-26 01:52:46 +00:00
|
|
|
return -1;
|
2014-05-18 00:19:11 +00:00
|
|
|
/* IGNORE check section permissions */
|
|
|
|
if (io->enforce_rwx & R_IO_READ)
|
|
|
|
if (!(r_io_section_get_rwx (io, io->off) & R_IO_READ))
|
|
|
|
return -1;
|
2015-12-09 20:17:49 +00:00
|
|
|
/* io->off is in maddr, but r_io_read_at works in vaddr
|
|
|
|
* FIXME: in some cases, r_io_seek sets io->off in vaddr */
|
|
|
|
ut64 vaddr = r_io_section_maddr_to_vaddr(io, io->off);
|
|
|
|
vaddr = (vaddr == UT64_MAX) ? io->off : vaddr;
|
|
|
|
ret = r_io_read_at (io, vaddr, buf, len);
|
2015-12-08 21:35:39 +00:00
|
|
|
if (ret > 0) io->off += ret;
|
2013-06-04 21:49:28 +00:00
|
|
|
return ret;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
2013-03-17 23:38:04 +00:00
|
|
|
|
2014-06-13 15:48:33 +00:00
|
|
|
int r_io_read_cr (RIO *io, ut64 addr, ut8 *buf, int len) {
|
|
|
|
RList *maps;
|
|
|
|
RListIter *iter;
|
|
|
|
RIOMap *map;
|
|
|
|
if (!io)
|
|
|
|
return R_FAIL;
|
|
|
|
if (io->ff)
|
2016-05-03 21:09:00 +00:00
|
|
|
memset (buf, io->Oxff, len);
|
2014-06-13 15:48:33 +00:00
|
|
|
if (io->raw) {
|
|
|
|
r_io_seek (io, addr, R_IO_SEEK_SET);
|
|
|
|
return r_io_read_internal (io, buf, len);
|
|
|
|
}
|
|
|
|
if (io->va) {
|
2015-12-08 21:35:39 +00:00
|
|
|
r_io_vread (io, addr, buf, len); //must check return-stat
|
2014-06-13 15:48:33 +00:00
|
|
|
if (io->cached)
|
|
|
|
r_io_cache_read (io, addr, buf, len);
|
|
|
|
return len;
|
|
|
|
}
|
2015-12-08 21:35:39 +00:00
|
|
|
maps = r_io_map_get_maps_in_range (io, addr, addr + len);
|
2014-06-13 15:48:33 +00:00
|
|
|
r_list_foreach (maps, iter, map) {
|
2015-12-08 21:35:39 +00:00
|
|
|
r_io_mread (io, map->fd, addr, buf, len); //must check return-stat
|
2014-06-13 15:48:33 +00:00
|
|
|
}
|
2015-12-08 21:35:39 +00:00
|
|
|
r_io_mread (io, io->desc->fd, addr, buf, len); //must check return-stat
|
2014-06-13 15:48:33 +00:00
|
|
|
if (io->cached)
|
|
|
|
r_io_cache_read (io, addr, buf, len);
|
2015-12-08 21:35:39 +00:00
|
|
|
r_list_free (maps);
|
2014-06-13 15:48:33 +00:00
|
|
|
return len;
|
|
|
|
}
|
2014-05-28 02:34:12 +00:00
|
|
|
|
2011-10-25 18:30:05 +00:00
|
|
|
R_API int r_io_read_at(RIO *io, ut64 addr, ut8 *buf, int len) {
|
2014-10-16 22:04:52 +00:00
|
|
|
ut64 paddr, last, last2;
|
|
|
|
int ms, ret, l = 0, olen = len, w = 0;
|
|
|
|
|
2015-10-05 12:43:17 +00:00
|
|
|
if (!io || !buf || len < 0) return 0;
|
|
|
|
if (io->vio) return r_io_read_cr (io, addr, buf, len);
|
2014-11-23 23:41:20 +00:00
|
|
|
if (io->sectonly && !r_list_empty (io->sections)) {
|
2015-07-04 23:44:45 +00:00
|
|
|
if (!r_io_section_exists_for_vaddr (io, addr, 0)) {
|
2014-11-23 23:41:20 +00:00
|
|
|
// find next sec
|
2016-05-03 21:09:00 +00:00
|
|
|
memset (buf, io->Oxff, len);
|
2014-11-23 23:41:20 +00:00
|
|
|
ut64 next = r_io_section_next (io, addr);
|
2015-12-08 21:35:39 +00:00
|
|
|
if (next < (addr + len)) {
|
|
|
|
int delta = (next - addr);
|
2014-11-23 23:41:20 +00:00
|
|
|
addr = next;
|
|
|
|
len -= delta;
|
|
|
|
buf += delta;
|
2015-10-05 12:43:17 +00:00
|
|
|
} else {
|
|
|
|
next = 0;
|
|
|
|
}
|
|
|
|
if (!next) return 0;
|
2014-11-23 23:41:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-04 23:32:05 +00:00
|
|
|
if (io->raw) {
|
2016-06-19 22:29:41 +00:00
|
|
|
if (r_io_seek (io, addr, R_IO_SEEK_SET) == UT64_MAX) {
|
2016-05-03 21:09:00 +00:00
|
|
|
memset (buf, io->Oxff, len);
|
2016-06-19 22:29:41 +00:00
|
|
|
}
|
2014-06-04 23:32:05 +00:00
|
|
|
return r_io_read_internal (io, buf, len);
|
|
|
|
}
|
2012-02-07 23:45:06 +00:00
|
|
|
|
2013-03-19 09:27:57 +00:00
|
|
|
io->off = addr;
|
2016-05-03 21:09:00 +00:00
|
|
|
memset (buf, io->Oxff, len); // probably unnecessary
|
2013-01-12 03:29:45 +00:00
|
|
|
|
2015-08-24 02:45:04 +00:00
|
|
|
if (io->buffer_enabled) {
|
2013-01-12 03:29:45 +00:00
|
|
|
return r_io_buffer_read (io, addr, buf, len);
|
2015-08-24 02:45:04 +00:00
|
|
|
}
|
2015-10-05 12:43:17 +00:00
|
|
|
while (len > 0) {
|
|
|
|
if ((addr + w) < ((addr + w) + len)) {
|
2015-08-24 02:45:04 +00:00
|
|
|
// this code assumes that the IO backend knows
|
|
|
|
// 1) the size of a loaded file and its offset into the r2 data space
|
|
|
|
// 2) the sections with physical (offsets) and virtual addresses in r2 data space
|
|
|
|
// Currently debuggers may not support registering these data spaces in r2 and this
|
|
|
|
// may prevent "raw" access to locations in the data space for entities like debuggers.
|
|
|
|
// Until that issue is resolved this code will be disabled.
|
|
|
|
// step one does a section exist for the offset
|
2015-12-08 21:35:39 +00:00
|
|
|
int exists = r_io_section_exists_for_paddr (io, addr + w, 0) ||
|
|
|
|
r_io_section_exists_for_vaddr (io, addr + w, 0) ||
|
|
|
|
r_io_map_exists_for_offset (io, addr + w);
|
2015-08-24 02:45:04 +00:00
|
|
|
|
|
|
|
// XXX this is a break b/c external IO caller do not need to create
|
|
|
|
// an IO Map (yet.), so the "checking existence of" only works if r_core_file
|
|
|
|
// APIs are used to load files.
|
|
|
|
if (!exists && r_io_map_count (io) > 0) {
|
|
|
|
// XXX this will break if there is actually data at this location
|
|
|
|
// or within UT64_MAX - len
|
2015-10-05 12:43:17 +00:00
|
|
|
ut64 next_map_addr = UT64_MAX;
|
|
|
|
ut64 next_sec_addr = UT64_MAX;
|
2015-08-24 02:45:04 +00:00
|
|
|
|
|
|
|
RIOMap *next_map = NULL;
|
2015-12-08 21:35:39 +00:00
|
|
|
RIOSection *next_sec = NULL;
|
2015-08-24 02:45:04 +00:00
|
|
|
// is there a map somewhere within the next range for
|
|
|
|
// us to read from
|
2015-12-08 21:35:39 +00:00
|
|
|
next_sec = r_io_section_get_first_in_vaddr_range (io, addr + w, addr + len + w);
|
|
|
|
next_sec_addr = next_sec? next_sec->offset: UT64_MAX;
|
2015-08-24 02:45:04 +00:00
|
|
|
|
|
|
|
if (!next_sec) {
|
2015-12-08 21:35:39 +00:00
|
|
|
next_map = r_io_map_get_first_map_in_range (io, addr + w, addr + len + w);
|
|
|
|
next_map_addr = next_map? next_map->from: UT64_MAX;
|
|
|
|
if (len <= next_map_addr - addr)
|
|
|
|
next_map_addr = UT64_MAX;
|
|
|
|
else l = next_map_addr - addr;
|
2015-08-24 02:45:04 +00:00
|
|
|
|
2015-12-08 21:35:39 +00:00
|
|
|
} else if (len <= next_map_addr - addr) {
|
2015-08-24 02:45:04 +00:00
|
|
|
next_sec_addr = UT64_MAX;
|
|
|
|
} else {
|
|
|
|
if (addr > next_sec_addr) {
|
|
|
|
/* avoid negative deltas */
|
|
|
|
return olen;
|
|
|
|
}
|
2015-12-08 21:35:39 +00:00
|
|
|
l = next_sec_addr - addr;
|
2015-08-24 02:45:04 +00:00
|
|
|
}
|
2014-06-05 01:29:11 +00:00
|
|
|
|
2015-08-24 02:45:04 +00:00
|
|
|
if (!next_sec && !next_map) {
|
|
|
|
// done
|
2014-12-04 12:02:11 +00:00
|
|
|
return olen;
|
|
|
|
}
|
2015-08-24 02:45:04 +00:00
|
|
|
// want to capture monotonicity even when maps are 0 in length
|
2015-12-08 21:35:39 +00:00
|
|
|
if (l == 0) l++;
|
|
|
|
w += l;
|
2015-08-24 02:45:04 +00:00
|
|
|
len -= l;
|
|
|
|
continue;
|
2014-06-04 23:32:05 +00:00
|
|
|
}
|
2014-05-22 06:58:03 +00:00
|
|
|
|
2015-12-08 21:35:39 +00:00
|
|
|
last = r_io_section_next (io, addr + w);
|
|
|
|
last2 = r_io_map_next (io, addr + w); // XXX: must use physical address
|
|
|
|
if (last == (addr + w)) last = last2;
|
2015-08-24 02:45:04 +00:00
|
|
|
//else if (last2<last) last = last2;
|
2015-12-08 21:35:39 +00:00
|
|
|
l = (len > (last - addr + w))? (last - addr + w): len;
|
2015-08-24 02:45:04 +00:00
|
|
|
} else {
|
|
|
|
// overflow //
|
|
|
|
l = UT64_MAX - addr + 1;
|
|
|
|
}
|
2015-10-05 12:43:17 +00:00
|
|
|
if (l < 1) l = len;
|
2015-08-24 02:45:04 +00:00
|
|
|
if (addr != UT64_MAX) {
|
2015-12-08 21:35:39 +00:00
|
|
|
paddr = w? r_io_section_vaddr_to_maddr_try (io, addr + w): addr;
|
2015-10-05 12:43:17 +00:00
|
|
|
} else {
|
|
|
|
paddr = 0;
|
|
|
|
}
|
2015-08-24 02:45:04 +00:00
|
|
|
//if (!paddr || paddr==UT64_MAX)
|
2015-10-05 12:43:17 +00:00
|
|
|
if (paddr == UT64_MAX) {
|
2015-08-24 02:45:04 +00:00
|
|
|
paddr = r_io_map_select (io, addr); // XXX
|
|
|
|
}
|
|
|
|
if (paddr == UT64_MAX) {
|
2015-12-08 21:35:39 +00:00
|
|
|
w += l;
|
2014-06-04 23:32:05 +00:00
|
|
|
len -= l;
|
|
|
|
continue;
|
2014-05-22 06:58:03 +00:00
|
|
|
}
|
2015-08-24 02:45:04 +00:00
|
|
|
r_io_map_select (io, addr); // XXX
|
2015-12-08 21:35:39 +00:00
|
|
|
if (len > 0 && l > len) l = len;
|
|
|
|
addr = paddr - w;
|
|
|
|
if (r_io_seek (io, paddr, R_IO_SEEK_SET) == UT64_MAX) {
|
2016-05-03 21:09:00 +00:00
|
|
|
memset (buf + w, io->Oxff, l);
|
2015-08-24 02:45:04 +00:00
|
|
|
}
|
2013-01-03 00:43:23 +00:00
|
|
|
// XXX is this necessary?
|
2015-12-08 21:35:39 +00:00
|
|
|
ms = r_io_map_select (io, addr + w);
|
2015-12-08 13:59:30 +00:00
|
|
|
if (readcache) {
|
2015-12-08 21:35:39 +00:00
|
|
|
if (r_io_cache_read (io, io->off, buf + w, l) == l) {
|
2015-12-08 13:59:30 +00:00
|
|
|
eprintf ("CACHED\n");
|
|
|
|
w += l;
|
|
|
|
len -= l;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
2015-12-08 21:35:39 +00:00
|
|
|
ret = r_io_read_internal (io, buf + w, l);
|
2015-10-05 12:43:17 +00:00
|
|
|
if (ret < 1) {
|
2016-05-03 21:09:00 +00:00
|
|
|
memset (buf + w, io->Oxff, l); // reading out of file
|
2014-06-05 01:29:11 +00:00
|
|
|
ret = l;
|
2015-10-05 12:43:17 +00:00
|
|
|
} else if (ret < l) {
|
2011-10-25 18:30:05 +00:00
|
|
|
l = ret;
|
2014-06-05 01:29:11 +00:00
|
|
|
}
|
2015-12-08 13:59:30 +00:00
|
|
|
if (readcache) {
|
2015-12-08 21:35:39 +00:00
|
|
|
r_io_cache_write (io, io->off, buf + w, len);
|
2015-12-08 13:59:30 +00:00
|
|
|
}
|
2013-03-17 23:38:04 +00:00
|
|
|
#if USE_CACHE
|
2012-02-05 00:14:09 +00:00
|
|
|
if (io->cached) {
|
2015-12-08 21:35:39 +00:00
|
|
|
r_io_cache_read (io, addr + w, buf + w, len); //-w);
|
|
|
|
#if 0
|
2015-12-08 13:59:30 +00:00
|
|
|
int cov = r_io_cache_write (io, addr+w, buf+w, len); //-w);
|
|
|
|
if (cov != len) {
|
|
|
|
}
|
2015-12-08 21:35:39 +00:00
|
|
|
#endif
|
|
|
|
} else if (r_list_length (io->maps) > 1) {
|
|
|
|
if (!io->debug && ms > 0) {
|
2012-10-25 10:55:28 +00:00
|
|
|
//eprintf ("FAIL MS=%d l=%d d=%d\n", ms, l, d);
|
|
|
|
/* check if address is vaddred in sections */
|
2015-12-08 21:35:39 +00:00
|
|
|
ut64 o = r_io_section_maddr_to_vaddr (io, addr + w);
|
2012-10-25 10:55:28 +00:00
|
|
|
if (o == UT64_MAX) {
|
2015-12-08 21:35:39 +00:00
|
|
|
ut64 o = r_io_section_vaddr_to_maddr_try (io, addr + w);
|
2012-10-25 10:55:28 +00:00
|
|
|
if (o == UT64_MAX)
|
2016-05-03 21:09:00 +00:00
|
|
|
memset (buf + w, io->Oxff, l);
|
2012-10-25 10:55:28 +00:00
|
|
|
}
|
|
|
|
break;
|
2012-08-13 11:16:06 +00:00
|
|
|
}
|
2015-12-08 23:27:31 +00:00
|
|
|
// } else {
|
2015-08-24 02:45:04 +00:00
|
|
|
//eprintf ("ONT USING CACH\n");
|
2012-08-13 02:33:01 +00:00
|
|
|
}
|
2013-03-17 23:38:04 +00:00
|
|
|
#endif
|
2011-10-25 18:30:05 +00:00
|
|
|
w += l;
|
|
|
|
len -= l;
|
2014-05-18 00:37:34 +00:00
|
|
|
/* Fix famous io/f bug */
|
|
|
|
#if 0
|
|
|
|
this is not a real fix, because it just avoids reading again , even if the seek returns error.
|
|
|
|
bear in mind that we need to fix that loop and honor lseek sections and sio maps fine
|
|
|
|
#endif
|
2015-12-08 21:35:39 +00:00
|
|
|
if (len > 0) {
|
2016-05-03 21:09:00 +00:00
|
|
|
memset (buf + w, io->Oxff, len);
|
2015-08-24 02:45:04 +00:00
|
|
|
}
|
2015-12-08 21:35:39 +00:00
|
|
|
//break;
|
2011-10-25 18:30:05 +00:00
|
|
|
}
|
|
|
|
return olen;
|
2009-09-02 00:10:51 +00:00
|
|
|
}
|
|
|
|
|
2016-04-26 09:09:15 +00:00
|
|
|
R_API ut64 r_io_read_i(RIO *io, ut64 addr, int sz) {
|
2009-08-22 04:54:41 +00:00
|
|
|
ut64 ret = 0LL;
|
2009-09-02 00:10:51 +00:00
|
|
|
ut8 buf[8];
|
2013-06-04 21:49:28 +00:00
|
|
|
sz = R_DIM (sz, 1, 8);
|
|
|
|
if (sz != r_io_read_at (io, addr, buf, sz))
|
|
|
|
return UT64_MAX;
|
2016-04-26 09:09:15 +00:00
|
|
|
memcpy ((ut8 *)&ret, buf, sz);
|
2009-08-22 04:54:41 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2014-05-28 02:34:12 +00:00
|
|
|
// TODO. this is a physical resize
|
2016-06-29 09:35:16 +00:00
|
|
|
R_API bool r_io_resize(RIO *io, ut64 newsize) {
|
2014-05-19 00:52:51 +00:00
|
|
|
if (io->plugin) {
|
2015-04-16 15:57:36 +00:00
|
|
|
if (io->plugin->resize && io->desc) {
|
2016-06-29 09:35:16 +00:00
|
|
|
bool res = io->plugin->resize (io, io->desc, newsize);
|
|
|
|
if (res) {
|
2014-05-28 02:34:12 +00:00
|
|
|
r_io_map_truncate_update (io, io->desc->fd, newsize);
|
2016-06-29 09:35:16 +00:00
|
|
|
}
|
2014-05-22 06:58:03 +00:00
|
|
|
return res;
|
|
|
|
}
|
2015-09-14 00:08:31 +00:00
|
|
|
return false;
|
2014-05-19 00:52:51 +00:00
|
|
|
}
|
2015-09-14 00:08:31 +00:00
|
|
|
return true;
|
2014-03-25 03:00:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
R_API int r_io_extend(RIO *io, ut64 size) {
|
|
|
|
ut64 curr_off = io->off;
|
2015-12-08 21:35:39 +00:00
|
|
|
ut64 cur_size = r_io_size (io), tmp_size = cur_size - size;
|
2014-03-25 03:00:26 +00:00
|
|
|
ut8 *buffer = NULL;
|
|
|
|
|
2015-09-14 00:08:31 +00:00
|
|
|
if (!size) return false;
|
2014-03-25 03:00:26 +00:00
|
|
|
|
|
|
|
if (io->plugin && io->plugin->extend)
|
2014-05-28 02:34:12 +00:00
|
|
|
return io->plugin->extend (io, io->desc, size);
|
2014-03-28 17:04:57 +00:00
|
|
|
|
2015-12-08 21:35:39 +00:00
|
|
|
if (!r_io_resize (io, size + cur_size)) return false;
|
2014-03-25 03:00:26 +00:00
|
|
|
|
2014-04-08 22:47:26 +00:00
|
|
|
if (cur_size < size) {
|
|
|
|
tmp_size = size - cur_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
buffer = malloc (tmp_size);
|
2014-03-25 03:00:26 +00:00
|
|
|
// shift the bytes over by size
|
|
|
|
r_io_seek (io, curr_off, R_IO_SEEK_SET);
|
2014-04-08 22:47:26 +00:00
|
|
|
r_io_read (io, buffer, tmp_size);
|
2014-03-25 03:00:26 +00:00
|
|
|
// move/write the bytes
|
2015-12-08 21:35:39 +00:00
|
|
|
r_io_seek (io, curr_off + size, R_IO_SEEK_SET);
|
2014-04-08 22:47:26 +00:00
|
|
|
r_io_write (io, buffer, tmp_size);
|
2014-03-25 03:00:26 +00:00
|
|
|
// zero out new bytes
|
|
|
|
if (cur_size < size) {
|
|
|
|
free (buffer);
|
|
|
|
buffer = malloc (size);
|
|
|
|
}
|
|
|
|
memset (buffer, 0, size);
|
|
|
|
r_io_seek (io, curr_off, R_IO_SEEK_SET);
|
|
|
|
r_io_write (io, buffer, size);
|
|
|
|
// reset the cursor
|
|
|
|
r_io_seek (io, curr_off, R_IO_SEEK_SET);
|
|
|
|
free (buffer);
|
2015-09-14 00:08:31 +00:00
|
|
|
return true;
|
2014-03-25 03:00:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
R_API int r_io_extend_at(RIO *io, ut64 addr, ut64 size) {
|
2015-09-14 00:08:31 +00:00
|
|
|
if (!size) return false;
|
2014-03-25 03:00:26 +00:00
|
|
|
r_io_seek (io, addr, R_IO_SEEK_SET);
|
2015-12-08 21:35:39 +00:00
|
|
|
return r_io_extend (io, size);
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
|
|
|
|
2012-09-21 00:25:44 +00:00
|
|
|
R_API int r_io_set_write_mask(RIO *io, const ut8 *buf, int len) {
|
2015-12-08 21:35:39 +00:00
|
|
|
if (len > 0) {
|
2014-05-28 02:34:12 +00:00
|
|
|
io->write_mask_fd = io->desc->fd;
|
2010-03-23 22:26:59 +00:00
|
|
|
io->write_mask_buf = (ut8 *)malloc (len);
|
2016-06-20 07:12:44 +00:00
|
|
|
if (io->write_mask_buf) {
|
|
|
|
memcpy (io->write_mask_buf, buf, len);
|
|
|
|
io->write_mask_len = len;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
io->write_mask_fd = -1;
|
|
|
|
return false;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
|
|
|
|
2014-06-06 20:37:18 +00:00
|
|
|
R_API int r_io_write(RIO *io, const ut8 *buf, int len) {
|
2009-02-05 21:08:46 +00:00
|
|
|
int i, ret = -1;
|
2010-06-28 12:12:34 +00:00
|
|
|
ut8 *data = NULL;
|
2009-02-05 21:08:46 +00:00
|
|
|
|
2009-09-08 02:14:19 +00:00
|
|
|
/* check section permissions */
|
2016-06-20 07:12:44 +00:00
|
|
|
if (io->enforce_rwx & R_IO_WRITE) {
|
|
|
|
if (!(r_io_section_get_rwx (io, io->off) & R_IO_WRITE)) {
|
2014-05-18 00:19:11 +00:00
|
|
|
return -1;
|
2016-06-20 07:12:44 +00:00
|
|
|
}
|
|
|
|
}
|
2009-09-08 02:14:19 +00:00
|
|
|
|
|
|
|
if (io->cached) {
|
2010-03-23 22:26:59 +00:00
|
|
|
ret = r_io_cache_write (io, io->off, buf, len);
|
2016-06-20 07:12:44 +00:00
|
|
|
if (ret == len) {
|
2009-09-08 02:14:19 +00:00
|
|
|
return len;
|
2016-06-20 07:12:44 +00:00
|
|
|
}
|
2009-09-08 02:14:19 +00:00
|
|
|
if (ret > 0) {
|
|
|
|
len -= ret;
|
|
|
|
buf += ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* TODO: implement IO cache here. to avoid dupping work on vm for example */
|
|
|
|
|
2009-02-05 21:08:46 +00:00
|
|
|
/* apply write binary mask */
|
|
|
|
if (io->write_mask_fd != -1) {
|
2015-12-08 21:35:39 +00:00
|
|
|
data = (len > 0)? malloc (len): NULL;
|
2015-12-07 21:35:34 +00:00
|
|
|
if (!data) {
|
|
|
|
eprintf ("malloc failed in write_mask_fd");
|
|
|
|
return -1;
|
|
|
|
}
|
2016-05-03 21:09:00 +00:00
|
|
|
// memset (data, io->Oxff, len);
|
2010-03-23 22:26:59 +00:00
|
|
|
r_io_seek (io, io->off, R_IO_SEEK_SET);
|
|
|
|
r_io_read (io, data, len);
|
|
|
|
r_io_seek (io, io->off, R_IO_SEEK_SET);
|
2016-06-20 07:12:44 +00:00
|
|
|
for (i = 0; i < len; i++) {
|
2015-12-08 21:35:39 +00:00
|
|
|
data[i] = buf[i] &
|
|
|
|
io->write_mask_buf[i % io->write_mask_len];
|
2016-06-20 07:12:44 +00:00
|
|
|
}
|
2009-02-05 21:08:46 +00:00
|
|
|
buf = data;
|
|
|
|
}
|
2014-03-28 17:04:57 +00:00
|
|
|
|
2015-01-17 01:57:19 +00:00
|
|
|
// this makes a double sub, so we restore the io->off
|
|
|
|
{
|
|
|
|
ut64 addr = io->off;
|
|
|
|
r_io_map_select (io, io->off);
|
|
|
|
io->off = addr;
|
|
|
|
}
|
2015-12-07 21:35:34 +00:00
|
|
|
{
|
|
|
|
RIOMap *map = r_io_map_get (io, io->off);
|
|
|
|
if (map) {
|
|
|
|
io->off -= map->from;
|
|
|
|
}
|
|
|
|
}
|
2011-04-07 07:35:03 +00:00
|
|
|
|
|
|
|
if (io->plugin) {
|
2014-10-07 00:52:47 +00:00
|
|
|
if (io->plugin->write) {
|
2014-05-28 02:34:12 +00:00
|
|
|
ret = io->plugin->write (io, io->desc, buf, len);
|
2015-09-29 14:17:36 +00:00
|
|
|
} else {
|
2014-10-07 00:52:47 +00:00
|
|
|
eprintf ("r_io_write: io handler with no write callback\n");
|
|
|
|
ret = -1;
|
|
|
|
}
|
2012-10-22 08:12:13 +00:00
|
|
|
} else {
|
2015-09-29 14:17:36 +00:00
|
|
|
ret = io->desc? write (io->desc->fd, buf, len): -1;
|
2012-10-22 08:12:13 +00:00
|
|
|
}
|
2014-10-07 00:52:47 +00:00
|
|
|
if (ret == -1) {
|
2014-10-08 23:47:03 +00:00
|
|
|
if (io->cached != 2) {
|
2015-09-29 14:17:36 +00:00
|
|
|
eprintf ("r_io_write: cannot write %d bytes "
|
2015-12-08 21:35:39 +00:00
|
|
|
"at 0x%" PFMT64x " (file=%s, fd=%d)\n",
|
2015-09-29 14:17:36 +00:00
|
|
|
len, io->off,
|
2015-12-08 21:35:39 +00:00
|
|
|
io->desc? io->desc->uri: "unknown",
|
|
|
|
io->desc? io->desc->fd: -1);
|
2015-09-29 14:17:36 +00:00
|
|
|
eprintf ("hint: try oo+ or e io.cache=true\n");
|
2015-12-08 21:35:39 +00:00
|
|
|
r_io_cache_invalidate (io, io->off, io->off + 1);
|
2014-10-08 23:47:03 +00:00
|
|
|
}
|
2014-10-07 00:52:47 +00:00
|
|
|
} else {
|
2015-12-08 13:59:30 +00:00
|
|
|
if (readcache) {
|
|
|
|
//r_io_cache_invalidate (io, io->off, io->off + len);
|
|
|
|
r_io_cache_write (io, io->off, buf, len);
|
|
|
|
}
|
2015-03-17 19:27:59 +00:00
|
|
|
if (io->desc) {
|
|
|
|
r_io_map_write_update (io, io->desc->fd, io->off, ret);
|
|
|
|
io->off += ret;
|
|
|
|
}
|
2014-05-22 06:58:03 +00:00
|
|
|
}
|
2014-10-07 00:52:47 +00:00
|
|
|
free (data);
|
2009-02-05 21:08:46 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2013-01-12 03:29:45 +00:00
|
|
|
R_API int r_io_write_at(RIO *io, ut64 addr, const ut8 *buf, int len) {
|
2016-06-20 07:12:44 +00:00
|
|
|
if (io->cached) {
|
2015-02-12 21:46:51 +00:00
|
|
|
return r_io_cache_write (io, addr, buf, len);
|
2016-06-20 07:12:44 +00:00
|
|
|
}
|
2014-06-06 20:37:18 +00:00
|
|
|
(void)r_io_seek (io, addr, R_IO_SEEK_SET);
|
|
|
|
// errors on seek are checked and ignored here //
|
2010-03-23 22:26:59 +00:00
|
|
|
return r_io_write (io, buf, len);
|
2009-09-02 00:10:51 +00:00
|
|
|
}
|
2009-08-22 04:54:41 +00:00
|
|
|
|
2013-01-12 03:29:45 +00:00
|
|
|
R_API ut64 r_io_seek(RIO *io, ut64 offset, int whence) {
|
2014-06-06 20:37:18 +00:00
|
|
|
// TODO: review the offset/vaddr/paddr/maddr thing here
|
|
|
|
// now, io-seek always works with vaddr, because it depends on read/write ops that use it
|
2010-05-26 23:18:30 +00:00
|
|
|
int posix_whence = SEEK_SET;
|
2011-06-04 01:14:04 +00:00
|
|
|
ut64 ret = UT64_MAX;
|
2016-06-20 07:12:44 +00:00
|
|
|
if (!io) {
|
2014-05-19 21:47:13 +00:00
|
|
|
return ret;
|
2016-06-20 07:12:44 +00:00
|
|
|
}
|
2013-01-12 03:29:45 +00:00
|
|
|
if (io->buffer_enabled) {
|
|
|
|
io->off = offset;
|
|
|
|
return offset;
|
|
|
|
}
|
2011-02-12 00:52:41 +00:00
|
|
|
switch (whence) {
|
2009-02-05 21:08:46 +00:00
|
|
|
case R_IO_SEEK_SET:
|
|
|
|
posix_whence = SEEK_SET;
|
|
|
|
break;
|
|
|
|
case R_IO_SEEK_CUR:
|
2015-12-08 21:35:39 +00:00
|
|
|
// offset += io->off;
|
2009-02-05 21:08:46 +00:00
|
|
|
posix_whence = SEEK_CUR;
|
|
|
|
break;
|
|
|
|
case R_IO_SEEK_END:
|
2010-05-20 23:34:35 +00:00
|
|
|
//offset = UT64_MAX; // XXX: depending on io bits?
|
2009-02-05 21:08:46 +00:00
|
|
|
posix_whence = SEEK_END;
|
|
|
|
break;
|
|
|
|
}
|
2010-06-27 22:43:07 +00:00
|
|
|
// XXX: list_empty trick must be done in r_io_set_va();
|
2011-10-25 18:30:05 +00:00
|
|
|
//eprintf ("-(seek)-> 0x%08llx\n", offset);
|
2015-08-24 02:45:04 +00:00
|
|
|
//if (!io->debug && io->va && !r_list_empty (io->sections)) {
|
2015-12-08 23:41:44 +00:00
|
|
|
if (!io->debug || !io->raw) { //
|
2015-08-24 14:44:09 +00:00
|
|
|
if (io->va && !r_list_empty (io->sections)) {
|
2015-09-09 20:01:29 +00:00
|
|
|
ut64 o = r_io_section_vaddr_to_maddr_try (io, offset);
|
2016-06-20 07:12:44 +00:00
|
|
|
if (o != UT64_MAX) {
|
2015-08-24 14:44:09 +00:00
|
|
|
offset = o;
|
2016-06-20 07:12:44 +00:00
|
|
|
}
|
2015-08-24 14:44:09 +00:00
|
|
|
// eprintf ("-(vadd)-> 0x%08llx\n", offset);
|
|
|
|
}
|
2011-10-25 18:30:05 +00:00
|
|
|
}
|
2011-04-18 22:59:16 +00:00
|
|
|
// if resolution fails... just return as invalid address
|
2016-06-20 07:12:44 +00:00
|
|
|
if (offset == UT64_MAX || !io->desc) {
|
2011-04-18 22:59:16 +00:00
|
|
|
return UT64_MAX;
|
2016-06-20 07:12:44 +00:00
|
|
|
}
|
|
|
|
if (io->plugin && io->plugin->lseek) {
|
|
|
|
ret = io->plugin->lseek (io, io->desc, offset, whence);
|
|
|
|
} else {
|
|
|
|
ret = (ut64)lseek (io->desc->fd, offset, posix_whence);
|
|
|
|
}
|
2016-06-20 09:08:21 +00:00
|
|
|
if (whence == R_IO_SEEK_SET) {
|
|
|
|
io->off = offset;
|
|
|
|
}
|
2016-06-20 07:22:34 +00:00
|
|
|
#if 0
|
|
|
|
// XXX can be problematic on w32..so no 64 bit offset?
|
2016-06-20 07:12:44 +00:00
|
|
|
if (ret != UT64_MAX) {
|
|
|
|
io->off = (whence == R_IO_SEEK_SET)
|
|
|
|
? offset // HACKY FIX linux-arm-32-bs at 0x10000
|
|
|
|
: ret;
|
|
|
|
io->off = offset;
|
|
|
|
ret = (!io->debug && io->va && !r_list_empty (io->sections))
|
|
|
|
? r_io_section_maddr_to_vaddr (io, io->off)
|
|
|
|
: io->off;
|
|
|
|
}
|
2016-06-20 07:22:34 +00:00
|
|
|
#endif
|
2010-04-08 12:04:34 +00:00
|
|
|
return ret;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
|
|
|
|
2015-12-08 21:35:39 +00:00
|
|
|
R_API ut64 r_io_fd_size(RIO *io, int fd) {
|
2013-11-14 12:52:03 +00:00
|
|
|
RIODesc *desc = r_io_desc_get (io, fd);
|
|
|
|
return r_io_desc_size (io, desc);
|
2013-11-09 23:15:30 +00:00
|
|
|
}
|
|
|
|
|
2015-12-08 21:35:39 +00:00
|
|
|
R_API int r_io_is_blockdevice(RIO *io) {
|
2014-07-01 12:42:50 +00:00
|
|
|
#if __UNIX__
|
2014-07-01 12:37:21 +00:00
|
|
|
if (io && io->desc && io->desc->fd) {
|
|
|
|
struct stat buf;
|
2015-02-16 21:40:05 +00:00
|
|
|
if (io->desc->obsz) {
|
|
|
|
return 1;
|
|
|
|
}
|
2015-12-08 21:35:39 +00:00
|
|
|
if (fstat (io->desc->fd, &buf) == -1)
|
2014-07-03 07:45:38 +00:00
|
|
|
return 0;
|
2014-07-01 12:37:21 +00:00
|
|
|
if (io->plugin == &r_io_plugin_default) {
|
|
|
|
// TODO: optimal blocksize = 2048 for disk, 4096 for files
|
2015-02-16 21:40:05 +00:00
|
|
|
// usually is 128K
|
2015-12-08 21:35:39 +00:00
|
|
|
// eprintf ("OPtimal blocksize: %d\n", buf.st_blksize);
|
2015-02-16 21:40:05 +00:00
|
|
|
if ((buf.st_mode & S_IFCHR) == S_IFCHR) {
|
|
|
|
io->desc->obsz = buf.st_blksize;
|
|
|
|
return 1;
|
|
|
|
}
|
2014-07-01 12:37:21 +00:00
|
|
|
return ((buf.st_mode & S_IFBLK) == S_IFBLK);
|
|
|
|
}
|
|
|
|
}
|
2014-07-01 12:42:50 +00:00
|
|
|
#endif
|
2014-07-01 12:37:21 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-01-20 23:21:32 +00:00
|
|
|
R_API ut64 r_io_size(RIO *io) {
|
2014-07-30 19:05:19 +00:00
|
|
|
int oldva;
|
2009-08-22 04:54:41 +00:00
|
|
|
ut64 size, here;
|
2012-08-08 15:19:48 +00:00
|
|
|
if (!io) return 0LL;
|
2014-07-30 19:05:19 +00:00
|
|
|
oldva = io->va;
|
2016-06-20 07:12:44 +00:00
|
|
|
if (r_io_is_listener (io)) {
|
2011-02-04 23:20:28 +00:00
|
|
|
return UT64_MAX;
|
2016-06-20 07:12:44 +00:00
|
|
|
}
|
2015-09-14 00:08:31 +00:00
|
|
|
io->va = false;
|
2010-03-23 22:26:59 +00:00
|
|
|
here = r_io_seek (io, 0, R_IO_SEEK_CUR);
|
|
|
|
size = r_io_seek (io, 0, R_IO_SEEK_END);
|
2014-07-30 19:05:19 +00:00
|
|
|
if (r_io_seek (io, here, R_IO_SEEK_SET) != here) {
|
2015-12-08 21:35:39 +00:00
|
|
|
eprintf ("Failed to reset the file position\n");
|
2014-07-30 19:05:19 +00:00
|
|
|
}
|
|
|
|
io->va = oldva;
|
2015-08-19 18:56:41 +00:00
|
|
|
if (r_io_is_blockdevice (io)) {
|
2014-07-01 12:37:21 +00:00
|
|
|
io->va = 0;
|
|
|
|
size = UT64_MAX;
|
|
|
|
}
|
2009-02-05 21:08:46 +00:00
|
|
|
return size;
|
|
|
|
}
|
|
|
|
|
2010-05-19 22:59:42 +00:00
|
|
|
R_API int r_io_system(RIO *io, const char *cmd) {
|
2009-09-05 23:58:02 +00:00
|
|
|
int ret = -1;
|
2009-09-02 00:10:51 +00:00
|
|
|
if (io->plugin && io->plugin->system)
|
2014-05-28 02:34:12 +00:00
|
|
|
ret = io->plugin->system (io, io->desc, cmd);
|
2009-09-05 23:58:02 +00:00
|
|
|
return ret;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
|
|
|
|
2016-06-19 22:29:41 +00:00
|
|
|
R_API int r_io_plugin_close(RIO *io, RIODesc *desc) {
|
|
|
|
if (io->plugin && io->plugin->close) {
|
|
|
|
int ret = io->plugin->close (desc);
|
|
|
|
if (desc == io->desc) {
|
|
|
|
io->desc = NULL;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2014-05-28 02:34:12 +00:00
|
|
|
R_API int r_io_close(RIO *io, RIODesc *d) {
|
2014-09-16 21:07:28 +00:00
|
|
|
RIODesc *cur = NULL;
|
2016-09-19 12:44:47 +00:00
|
|
|
if (!io || !d) {
|
2011-01-20 21:52:16 +00:00
|
|
|
return -1;
|
2016-06-26 02:51:44 +00:00
|
|
|
}
|
|
|
|
if (d != io->desc) {
|
2014-09-16 21:07:28 +00:00
|
|
|
cur = io->desc;
|
2016-06-26 02:51:44 +00:00
|
|
|
}
|
2014-05-28 02:34:12 +00:00
|
|
|
if (r_io_use_desc (io, d)) {
|
|
|
|
int nfd = d->fd;
|
2014-05-07 23:32:06 +00:00
|
|
|
RIODesc *desc = r_io_desc_get (io, nfd);
|
2011-02-07 08:46:01 +00:00
|
|
|
if (desc) {
|
2015-04-17 16:26:49 +00:00
|
|
|
if (desc == io->desc) {
|
|
|
|
cur = NULL;
|
|
|
|
}
|
2015-03-12 19:49:30 +00:00
|
|
|
r_io_map_del (io, nfd);
|
2014-09-16 21:07:28 +00:00
|
|
|
r_io_section_rm_all (io, nfd);
|
2016-06-19 22:29:41 +00:00
|
|
|
r_io_plugin_close (io, io->desc);
|
2016-06-10 08:58:10 +00:00
|
|
|
//r_io_desc_del (io, desc->fd);
|
2011-02-07 08:46:01 +00:00
|
|
|
}
|
2016-06-26 02:51:44 +00:00
|
|
|
if (nfd == io->raised) {
|
|
|
|
io->raised = -1;
|
|
|
|
}
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
2014-09-16 21:07:28 +00:00
|
|
|
io->desc = cur;
|
2015-09-14 00:08:31 +00:00
|
|
|
return false;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
2009-09-10 20:51:34 +00:00
|
|
|
|
2015-12-08 21:35:39 +00:00
|
|
|
R_API int r_io_close_all(RIO *io) {
|
2015-01-22 01:22:29 +00:00
|
|
|
// LOT OF MEMLEAKS HERE
|
|
|
|
if (!io) return 0;
|
|
|
|
r_cache_free (io->buffer);
|
|
|
|
io->buffer = r_cache_new (); // RCache is a list of ranged buffers. maybe rename?
|
|
|
|
io->write_mask_fd = -1;
|
|
|
|
io->ff = 1;
|
|
|
|
io->raised = -1;
|
2015-09-14 00:08:31 +00:00
|
|
|
io->autofd = true;
|
2015-01-22 01:22:29 +00:00
|
|
|
r_io_map_del (io, -1);
|
|
|
|
r_io_desc_del (io, -1);
|
|
|
|
r_io_section_rm_all (io, -1);
|
|
|
|
r_io_undo_init (io);
|
|
|
|
r_io_cache_reset (io, 0);
|
2015-12-08 21:35:39 +00:00
|
|
|
// r_io_plugin_init (io);
|
2015-01-22 01:22:29 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2010-03-30 21:12:19 +00:00
|
|
|
R_API int r_io_bind(RIO *io, RIOBind *bnd) {
|
2009-09-10 20:51:34 +00:00
|
|
|
bnd->io = io;
|
2015-09-14 00:08:31 +00:00
|
|
|
bnd->init = true;
|
2014-04-29 16:10:35 +00:00
|
|
|
bnd->get_io = r_io_bind_get_io;
|
2009-09-10 20:51:34 +00:00
|
|
|
bnd->read_at = r_io_read_at;
|
|
|
|
bnd->write_at = r_io_write_at;
|
2014-01-02 05:09:46 +00:00
|
|
|
bnd->size = r_io_size;
|
|
|
|
bnd->seek = r_io_seek;
|
2014-09-21 23:39:24 +00:00
|
|
|
bnd->is_valid_offset = r_io_is_valid_offset;
|
2014-04-29 16:10:35 +00:00
|
|
|
|
2014-09-06 21:05:59 +00:00
|
|
|
bnd->desc_open = r_io_open_nomap;
|
2015-03-12 19:49:30 +00:00
|
|
|
bnd->desc_open_at = r_io_open_at;
|
2014-04-29 16:10:35 +00:00
|
|
|
bnd->desc_close = r_io_close;
|
|
|
|
bnd->desc_read = r_io_desc_read;
|
|
|
|
bnd->desc_size = r_io_desc_size;
|
|
|
|
bnd->desc_seek = r_io_desc_seek;
|
|
|
|
bnd->desc_get_by_fd = r_io_desc_get;
|
2014-05-08 23:35:04 +00:00
|
|
|
|
|
|
|
bnd->section_add = r_io_section_add;
|
2015-07-28 00:55:26 +00:00
|
|
|
bnd->section_vget = r_io_section_vget;
|
2014-09-21 23:39:24 +00:00
|
|
|
|
2014-05-08 23:35:04 +00:00
|
|
|
bnd->section_set_arch = r_io_section_set_archbits;
|
|
|
|
bnd->section_set_arch_bin_id = r_io_section_set_archbits_bin_id;
|
|
|
|
|
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
|
|
|
|
|
|
|
R_API int r_io_accept(RIO *io, int fd) {
|
2012-09-22 18:32:19 +00:00
|
|
|
if (r_io_is_listener (io) && io->plugin && io->plugin->accept)
|
2014-05-28 02:34:12 +00:00
|
|
|
return io->plugin->accept (io, io->desc, fd);
|
2015-09-14 00:08:31 +00:00
|
|
|
return false;
|
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 */
|
|
|
|
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;
|
2011-02-05 11:51:37 +00:00
|
|
|
ut64 rest, src, shiftsize = r_num_abs (move);
|
2015-12-08 21:35:39 +00:00
|
|
|
if (!shiftsize || (end - start) <= shiftsize) return false;
|
|
|
|
rest = (end - start) - shiftsize;
|
2011-02-05 11:51:37 +00:00
|
|
|
|
2015-09-14 00:08:31 +00:00
|
|
|
if (!(buf = malloc (chunksize))) return false;
|
2011-02-05 11:51:37 +00:00
|
|
|
|
2015-12-08 21:35:39 +00:00
|
|
|
if (move > 0)
|
|
|
|
src = end - shiftsize;
|
|
|
|
else src = start + shiftsize;
|
2011-02-05 11:51:37 +00:00
|
|
|
|
2015-12-08 21:35:39 +00:00
|
|
|
while (rest > 0) {
|
|
|
|
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);
|
2011-02-05 11:51:37 +00:00
|
|
|
|
2015-12-08 21:35:39 +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
|
|
|
|
2015-12-08 21:35:39 +00:00
|
|
|
R_API int r_io_create(RIO *io, const char *file, int mode, int type) {
|
2012-07-06 00:17:44 +00:00
|
|
|
if (io->plugin && io->plugin->create)
|
|
|
|
return io->plugin->create (io, file, mode, type);
|
2015-12-08 21:35:39 +00:00
|
|
|
if (type == 'd' || type == 1)
|
2012-08-10 09:35:38 +00:00
|
|
|
return r_sys_mkdir (file);
|
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
|
|
|
|
2015-12-08 21:35:39 +00:00
|
|
|
R_API void r_io_sort_maps(RIO *io) {
|
|
|
|
r_list_sort (io->maps, (RListComparator)r_io_map_sort);
|
2014-01-26 00:06:17 +00:00
|
|
|
}
|
|
|
|
|
2014-05-28 02:34:12 +00:00
|
|
|
// THIS IS pread.. a weird one
|
2015-12-08 21:35:39 +00:00
|
|
|
static ut8 *r_io_desc_read(RIO *io, RIODesc *desc, ut64 *out_sz) {
|
2016-01-26 22:36:02 +00:00
|
|
|
ut8 *buf = NULL;
|
2014-05-19 01:31:07 +00:00
|
|
|
ut64 off = 0;
|
2014-04-29 16:10:35 +00:00
|
|
|
|
2015-07-08 19:41:17 +00:00
|
|
|
if (!io || !desc || !out_sz) {
|
2014-05-18 00:19:11 +00:00
|
|
|
return NULL;
|
2015-07-08 19:41:17 +00:00
|
|
|
}
|
2016-06-20 07:12:44 +00:00
|
|
|
if (*out_sz == UT64_MAX) {
|
2014-05-21 16:58:36 +00:00
|
|
|
*out_sz = r_io_desc_size (io, desc);
|
2016-06-20 07:12:44 +00:00
|
|
|
}
|
2015-01-29 00:45:39 +00:00
|
|
|
if (*out_sz == 0x8000000) {
|
|
|
|
*out_sz = 1024 * 1024 * 1; // 2MB
|
|
|
|
}
|
2014-05-19 01:31:07 +00:00
|
|
|
off = io->off;
|
2014-05-21 16:58:36 +00:00
|
|
|
|
2016-01-26 22:36:02 +00:00
|
|
|
if (*out_sz == UT64_MAX) {
|
2016-03-31 19:43:58 +00:00
|
|
|
return NULL;
|
2016-01-26 22:36:02 +00:00
|
|
|
}
|
|
|
|
if (io->maxalloc && *out_sz > io->maxalloc) {
|
2016-07-05 10:46:28 +00:00
|
|
|
eprintf ("WARNING: File is greater than 0x%"PFMT64x" bytes.\n"
|
|
|
|
"Allocating R_IO_MAX_ALLOC set as the environment variable.\n", io->maxalloc);
|
|
|
|
*out_sz = io->maxalloc;
|
2015-06-08 23:45:39 +00:00
|
|
|
}
|
2014-04-29 16:10:35 +00:00
|
|
|
|
2015-01-29 00:45:39 +00:00
|
|
|
buf = malloc (*out_sz);
|
2015-07-08 19:41:17 +00:00
|
|
|
if (!buf) {
|
2016-07-05 10:46:28 +00:00
|
|
|
if (*out_sz > R_IO_MAX_ALLOC) {
|
|
|
|
char *num_unit = r_num_units (NULL, *out_sz);
|
|
|
|
eprintf ("Failed to allocate %s bytes.\n"
|
|
|
|
"Allocating %"PFMT64u" bytes.\n", num_unit, (ut64)R_IO_MAX_ALLOC);
|
|
|
|
free (num_unit);
|
|
|
|
*out_sz = R_IO_MAX_ALLOC;
|
|
|
|
buf = malloc (*out_sz);
|
|
|
|
}
|
|
|
|
if (!buf) {
|
|
|
|
char *num_unit = r_num_units (NULL, *out_sz);
|
|
|
|
eprintf ("Failed to allocate %s bytes.\n", num_unit);
|
|
|
|
free (num_unit);
|
|
|
|
return NULL;
|
|
|
|
}
|
2015-07-08 19:41:17 +00:00
|
|
|
}
|
|
|
|
if (buf && desc->plugin && desc->plugin->read) {
|
2015-01-29 00:45:39 +00:00
|
|
|
if (!buf || !desc->plugin->read (io, desc, buf, *out_sz)) {
|
|
|
|
free (buf);
|
2014-05-19 01:31:07 +00:00
|
|
|
io->off = off;
|
2015-06-08 23:45:39 +00:00
|
|
|
return NULL;
|
2014-05-19 01:31:07 +00:00
|
|
|
}
|
2014-04-29 16:10:35 +00:00
|
|
|
}
|
|
|
|
io->off = off;
|
2015-01-29 00:45:39 +00:00
|
|
|
return buf;
|
2014-04-29 16:10:35 +00:00
|
|
|
}
|
|
|
|
|
2015-12-08 21:35:39 +00:00
|
|
|
static RIO *r_io_bind_get_io(RIOBind *bnd) {
|
|
|
|
return bnd? bnd->io: NULL;
|
2014-04-29 16:10:35 +00:00
|
|
|
}
|
2014-05-25 00:23:33 +00:00
|
|
|
|
|
|
|
R_API void r_io_set_raw(RIO *io, int raw) {
|
2015-12-08 21:35:39 +00:00
|
|
|
io->raw = raw? 1: 0;
|
2014-05-25 00:23:33 +00:00
|
|
|
}
|
2014-09-18 19:27:06 +00:00
|
|
|
|
2015-07-04 23:44:45 +00:00
|
|
|
// check if reading at offset or writting to offset is reasonable
|
2015-12-08 21:35:39 +00:00
|
|
|
R_API int r_io_is_valid_offset(RIO *io, ut64 offset, int hasperm) {
|
2016-08-07 12:07:52 +00:00
|
|
|
bool io_sectonly = io->sectonly;
|
|
|
|
bool io_va = io->va;
|
|
|
|
//io_va=true;
|
|
|
|
// io_sectonly = true;
|
2014-09-18 19:27:06 +00:00
|
|
|
if (!io) {
|
|
|
|
eprintf ("r_io_is_valid_offset: io is NULL\n");
|
|
|
|
r_sys_backtrace ();
|
|
|
|
return R_FAIL;
|
|
|
|
}
|
2014-09-20 17:30:14 +00:00
|
|
|
if (!io->files) {
|
|
|
|
eprintf ("r_io_is_valid_offset: io->files is NULL\n");
|
|
|
|
r_sys_backtrace ();
|
|
|
|
return R_FAIL;
|
|
|
|
}
|
2015-07-21 11:38:34 +00:00
|
|
|
if (r_list_empty (io->files)) {
|
2015-09-14 00:08:31 +00:00
|
|
|
return false;
|
2015-07-21 11:38:34 +00:00
|
|
|
}
|
2014-09-18 19:27:06 +00:00
|
|
|
if (!io->desc) {
|
|
|
|
eprintf ("r_io_is_valid_offset: io->desc is NULL\n");
|
|
|
|
r_sys_backtrace ();
|
|
|
|
return R_FAIL;
|
|
|
|
}
|
2015-07-04 23:44:45 +00:00
|
|
|
#if 0
|
|
|
|
if (hasperm) {
|
|
|
|
int ret = (r_io_map_exists_for_offset (io, offset) ||
|
|
|
|
r_io_section_exists_for_vaddr (io, offset, hasperm));
|
|
|
|
}
|
|
|
|
#endif
|
2016-08-07 12:07:52 +00:00
|
|
|
if (!io_va) {
|
2015-12-08 21:35:39 +00:00
|
|
|
if ((r_io_map_exists_for_offset (io, offset))) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return (offset < r_io_size (io));
|
2016-08-07 12:07:52 +00:00
|
|
|
}
|
|
|
|
if (io->debug) {
|
|
|
|
// TODO check debug maps here
|
|
|
|
return 1;
|
|
|
|
} else {
|
|
|
|
if (io_sectonly) {
|
|
|
|
if (r_list_empty (io->sections)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return (r_io_map_exists_for_offset (io, offset) ||
|
|
|
|
r_io_section_exists_for_vaddr (io, offset, hasperm));
|
2015-12-08 21:35:39 +00:00
|
|
|
} else {
|
2016-08-07 12:07:52 +00:00
|
|
|
if (!io_va) {
|
|
|
|
if (!io_va && r_io_map_exists_for_offset (io, offset)) {
|
2015-12-08 21:35:39 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
2016-08-07 12:07:52 +00:00
|
|
|
return r_io_section_exists_for_vaddr (io, offset, hasperm);
|
|
|
|
//return (offset < r_io_size (io));
|
2015-12-08 21:35:39 +00:00
|
|
|
}
|
2016-08-07 12:07:52 +00:00
|
|
|
}
|
2014-09-18 19:27:06 +00:00
|
|
|
eprintf ("r_io_is_valid_offset: io->va is %i\n", io->va);
|
|
|
|
r_sys_backtrace ();
|
|
|
|
return R_FAIL;
|
|
|
|
}
|