2012-09-07 01:26:38 +00:00
|
|
|
/* radare - LGPL - Copyright 2008-2012 - pancake */
|
2009-02-05 21:08:46 +00:00
|
|
|
|
|
|
|
#include "r_io.h"
|
|
|
|
#include "r_util.h"
|
|
|
|
#include <stdio.h>
|
|
|
|
|
2009-09-08 18:16:52 +00:00
|
|
|
// TODO: R_API int r_io_fetch(struct r_io_t *io, ut8 *buf, int len)
|
|
|
|
// --- check for EXEC perms in section (use cached read to accelerate)
|
|
|
|
|
2010-01-19 10:25:17 +00:00
|
|
|
R_API struct r_io_t *r_io_new() {
|
2011-06-04 01:14:04 +00:00
|
|
|
RIO *io = R_NEW (RIO);
|
2011-04-18 22:59:16 +00:00
|
|
|
if (!io) return NULL;
|
|
|
|
io->fd = NULL;
|
|
|
|
io->write_mask_fd = -1;
|
|
|
|
io->redirect = NULL;
|
|
|
|
io->printf = (void*) printf;
|
2012-05-29 23:35:41 +00:00
|
|
|
io->bits = (sizeof(void*) == 8)? 64: 32;
|
2012-02-01 10:49:46 +00:00
|
|
|
io->va = -1;
|
2011-04-18 22:59:16 +00:00
|
|
|
io->plugin = NULL;
|
|
|
|
io->raised = -1;
|
2012-02-04 22:25:10 +00:00
|
|
|
io->off = 0;
|
2011-04-18 22:59:16 +00:00
|
|
|
r_io_cache_init (io);
|
|
|
|
r_io_map_init (io);
|
|
|
|
r_io_section_init (io);
|
|
|
|
r_io_plugin_init (io);
|
|
|
|
r_io_desc_init (io);
|
|
|
|
r_io_undo_init (io);
|
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)
|
2011-01-20 21:52:16 +00:00
|
|
|
return io->plugin->listener (io->fd);
|
2010-08-22 19:42:08 +00:00
|
|
|
return R_FALSE;
|
|
|
|
}
|
|
|
|
|
2010-03-23 22:26:59 +00:00
|
|
|
R_API RBuffer *r_io_read_buf(struct r_io_t *io, ut64 addr, int len) {
|
|
|
|
RBuffer *b = R_NEW (RBuffer);
|
|
|
|
b->buf = malloc (len);
|
|
|
|
len = r_io_read_at (io, addr, b->buf, len);
|
2011-02-12 00:52:41 +00:00
|
|
|
b->length = (len<0)?0:len;
|
2009-09-08 01:08:46 +00:00
|
|
|
return b;
|
|
|
|
}
|
|
|
|
|
2010-01-19 10:25:17 +00:00
|
|
|
R_API int r_io_write_buf(struct r_io_t *io, struct r_buf_t *b) {
|
2009-09-08 01:08:46 +00:00
|
|
|
return r_io_write_at(io, b->base, b->buf, b->length);
|
|
|
|
}
|
|
|
|
|
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;
|
2009-09-05 23:58:02 +00:00
|
|
|
/* TODO: properly free inner nfo */
|
2011-12-16 15:33:06 +00:00
|
|
|
/* TODO: memory leaks */
|
2012-01-26 02:18:45 +00:00
|
|
|
r_list_free (io->sections);
|
|
|
|
r_list_free (io->maps);
|
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 */
|
2010-03-23 22:26:59 +00:00
|
|
|
R_API int r_io_redirect(struct r_io_t *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;
|
|
|
|
}
|
|
|
|
|
2011-01-20 21:52:16 +00:00
|
|
|
R_API RIODesc *r_io_open_as(struct r_io_t *io, const char *urihandler, const char *file, int flags, int mode) {
|
|
|
|
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);
|
|
|
|
urilen = hlen + strlen (file)+5;
|
|
|
|
uri = malloc (urilen);
|
2010-01-31 01:30:59 +00:00
|
|
|
if (uri == NULL)
|
2011-01-20 21:52:16 +00:00
|
|
|
return NULL;
|
2011-07-06 01:01:21 +00:00
|
|
|
if (hlen>0) snprintf (uri, urilen, "%s://%s", urihandler, file);
|
|
|
|
else strncpy (uri, file, urilen);
|
2010-01-31 01:30:59 +00:00
|
|
|
ret = r_io_open (io, uri, flags, mode);
|
|
|
|
free (uri);
|
2009-09-07 20:01:34 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2012-09-07 01:26:38 +00:00
|
|
|
R_API RIODesc *r_io_open(RIO *io, const char *file, int flags, int mode) {
|
2012-09-22 18:32:19 +00:00
|
|
|
struct r_io_plugin_t *plugin;
|
2011-01-20 21:52:16 +00:00
|
|
|
RIODesc *desc = NULL;
|
2009-09-02 00:10:51 +00:00
|
|
|
int fd = -2;
|
2012-09-22 18:32:19 +00:00
|
|
|
char *uri;
|
2011-11-14 21:46:23 +00:00
|
|
|
if (!io) return NULL;
|
2012-09-22 18:32:19 +00:00
|
|
|
uri = strdup (file);
|
2011-11-14 21:46:23 +00:00
|
|
|
for (;;) {
|
|
|
|
plugin = r_io_plugin_resolve (io, uri);
|
|
|
|
if (plugin && plugin->open) {
|
|
|
|
desc = plugin->open (io, uri, flags, mode);
|
|
|
|
if (io->redirect) {
|
2012-09-12 17:35:27 +00:00
|
|
|
// TODO: free desc if not null
|
2011-11-14 21:46:23 +00:00
|
|
|
free ((void *)uri);
|
|
|
|
uri = strdup (io->redirect);
|
|
|
|
r_io_redirect (io, NULL);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (desc != NULL) {
|
|
|
|
r_io_desc_add (io, desc);
|
|
|
|
fd = desc->fd;
|
|
|
|
if (fd != -1)
|
|
|
|
r_io_plugin_open (io, fd, plugin);
|
|
|
|
if (desc != io->fd)
|
|
|
|
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
|
|
|
}
|
2010-01-15 12:02:54 +00:00
|
|
|
if (fd == -2) {
|
|
|
|
#if __WINDOWS__
|
2011-01-06 23:42:27 +00:00
|
|
|
if (flags & R_IO_WRITE) {
|
2012-09-07 01:26:38 +00:00
|
|
|
fd = open (uri, O_BINARY | 1);
|
2011-01-06 23:42:27 +00:00
|
|
|
if (fd == -1)
|
2012-09-07 01:26:38 +00:00
|
|
|
creat (uri, O_BINARY);
|
|
|
|
fd = open (uri, O_BINARY | 1);
|
|
|
|
} else fd = open (uri, O_BINARY);
|
2010-01-15 12:02:54 +00:00
|
|
|
#else
|
2012-09-07 01:26:38 +00:00
|
|
|
fd = open (uri, (flags&R_IO_WRITE)?O_RDWR:O_RDONLY, mode);
|
2010-01-15 12:02:54 +00:00
|
|
|
#endif
|
|
|
|
}
|
2009-09-05 23:58:02 +00:00
|
|
|
if (fd >= 0) {
|
2011-01-20 23:21:32 +00:00
|
|
|
if (desc == NULL)
|
2012-09-07 01:26:38 +00:00
|
|
|
desc = r_io_desc_new (io->plugin,
|
|
|
|
fd, uri, flags, mode, NULL);
|
2011-01-20 21:52:16 +00:00
|
|
|
r_io_desc_add (io, desc);
|
|
|
|
r_io_set_fd (io, desc);
|
|
|
|
}
|
2010-04-14 21:56:27 +00:00
|
|
|
free ((void *)uri);
|
2011-01-20 21:52:16 +00:00
|
|
|
return desc;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
|
|
|
|
2011-01-20 21:52:16 +00:00
|
|
|
R_API int r_io_set_fd(RIO *io, RIODesc *fd) {
|
|
|
|
if (fd != NULL) {
|
2009-08-22 04:54:41 +00:00
|
|
|
io->fd = fd;
|
2011-01-20 21:52:16 +00:00
|
|
|
io->plugin = fd->plugin;
|
|
|
|
return R_TRUE;
|
2009-08-22 04:54:41 +00:00
|
|
|
}
|
2011-01-20 21:52:16 +00:00
|
|
|
return R_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API int r_io_set_fdn(RIO *io, int fd) {
|
|
|
|
if (fd != -1 && io->fd != NULL && fd != io->fd->fd) {
|
|
|
|
RIODesc *desc = r_io_desc_get (io, fd);
|
2012-08-13 23:25:50 +00:00
|
|
|
if (!desc) return R_FALSE;
|
|
|
|
io->fd = desc;
|
|
|
|
io->plugin = desc->plugin;
|
|
|
|
return R_TRUE;
|
2011-01-20 21:52:16 +00:00
|
|
|
}
|
|
|
|
return R_FALSE;
|
2009-08-22 04:54:41 +00:00
|
|
|
}
|
|
|
|
|
2011-10-25 18:30:05 +00:00
|
|
|
static inline int r_io_read_internal(RIO *io, ut8 *buf, int len) {
|
|
|
|
if (io->plugin && io->plugin->read)
|
|
|
|
return io->plugin->read (io, io->fd, buf, len);
|
|
|
|
return read (io->fd->fd, buf, len);
|
|
|
|
}
|
|
|
|
|
2011-02-12 00:52:41 +00:00
|
|
|
R_API int r_io_read(RIO *io, ut8 *buf, int len) {
|
2011-01-20 21:52:16 +00:00
|
|
|
if (io==NULL || io->fd == NULL)
|
2011-01-14 00:02:20 +00:00
|
|
|
return -1;
|
2011-10-25 18:30:05 +00:00
|
|
|
/* IGNORE check section permissions
|
2010-03-23 22:26:59 +00:00
|
|
|
if (io->enforce_rwx && !(r_io_section_get_rwx (io, io->off) & R_IO_READ))
|
2009-09-08 02:14:19 +00:00
|
|
|
return -1;
|
2011-10-25 18:30:05 +00:00
|
|
|
*/
|
2011-11-29 03:25:18 +00:00
|
|
|
return r_io_read_at (io, io->off, buf, len);
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
|
|
|
|
2012-09-07 02:12:24 +00:00
|
|
|
// XXX: this is buggy. must use seek+read
|
2011-10-25 18:30:05 +00:00
|
|
|
R_API int r_io_read_at(RIO *io, ut64 addr, ut8 *buf, int len) {
|
|
|
|
int ret, l, olen = len;
|
|
|
|
int w = 0;
|
2012-09-21 00:25:44 +00:00
|
|
|
int eof = 0;
|
2012-02-07 23:45:06 +00:00
|
|
|
|
2012-09-07 08:07:41 +00:00
|
|
|
r_io_seek (io, addr, R_IO_SEEK_SET);
|
2012-08-13 02:33:01 +00:00
|
|
|
#if 0
|
2011-11-25 03:32:32 +00:00
|
|
|
// HACK?: if io->va == 0 -> call seek+read without checking sections ?
|
|
|
|
if (!io->va) {
|
2012-02-06 23:44:46 +00:00
|
|
|
// r_io_seek (io, addr, R_IO_SEEK_SET);
|
2012-02-07 23:45:06 +00:00
|
|
|
r_io_map_select (io, addr);
|
2012-02-05 00:14:09 +00:00
|
|
|
ret = r_io_read_internal (io, buf, len);
|
|
|
|
if (io->cached) {
|
|
|
|
r_io_cache_read (io, addr, buf, len);
|
|
|
|
}
|
|
|
|
return ret;
|
2011-11-25 03:32:32 +00:00
|
|
|
}
|
2011-11-25 08:40:28 +00:00
|
|
|
#endif
|
2012-08-13 02:33:01 +00:00
|
|
|
// XXX: this is buggy!
|
2012-09-21 00:25:44 +00:00
|
|
|
memset (buf, 0xff, len);
|
|
|
|
#if 0
|
|
|
|
ret = r_io_read_internal (io, buf, len);
|
|
|
|
return len;
|
|
|
|
#endif
|
|
|
|
|
2011-10-25 18:30:05 +00:00
|
|
|
while (len>0) {
|
2012-08-13 02:33:01 +00:00
|
|
|
int ms;
|
2011-10-25 18:30:05 +00:00
|
|
|
ut64 last = r_io_section_next (io, addr);
|
|
|
|
l = (len > (last-addr))? (last-addr): len;
|
|
|
|
if (l<1) l = len;
|
|
|
|
// ignore seek errors
|
|
|
|
// eprintf ("0x%llx %llx\n", addr+w,
|
2012-02-06 23:44:46 +00:00
|
|
|
//r_io_seek (io, addr+w, R_IO_SEEK_SET);
|
2012-08-13 02:33:01 +00:00
|
|
|
if (r_io_seek (io, addr+w, R_IO_SEEK_SET)==UT64_MAX) {
|
|
|
|
memset (buf+w, 0xff, l);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
ms = r_io_map_select (io, addr+w);
|
2011-10-25 18:30:05 +00:00
|
|
|
ret = r_io_read_internal (io, buf+w, l);
|
2012-08-13 02:33:01 +00:00
|
|
|
if (ret<1) {
|
2011-10-25 18:30:05 +00:00
|
|
|
memset (buf+w, 0xff, l); // reading out of file
|
|
|
|
ret = 1;
|
2012-02-05 00:14:09 +00:00
|
|
|
} else if (ret<l) {
|
2011-10-25 18:30:05 +00:00
|
|
|
// eprintf ("FOUND EOF AT %llx\n", addr+ret);
|
2012-09-21 00:25:44 +00:00
|
|
|
eof = 1;
|
2011-10-25 18:30:05 +00:00
|
|
|
l = ret;
|
2012-09-21 00:25:44 +00:00
|
|
|
} else {
|
|
|
|
//eprintf ("L = %d\n", len-w);
|
|
|
|
eof = 1;
|
2011-10-25 18:30:05 +00:00
|
|
|
}
|
2012-02-05 00:14:09 +00:00
|
|
|
if (io->cached) {
|
2012-09-21 00:25:44 +00:00
|
|
|
r_io_cache_read (io, addr+w, buf+w, len-w);
|
2012-08-20 08:07:21 +00:00
|
|
|
} else
|
2012-08-13 02:33:01 +00:00
|
|
|
// hide non-mapped files here
|
|
|
|
// do not allow reading on real addresses if mapped != 0
|
2012-09-21 00:25:44 +00:00
|
|
|
if (r_list_length (io->maps) >1)
|
2012-08-14 01:21:31 +00:00
|
|
|
if (!io->debug && ms>0) {
|
2012-08-13 02:33:01 +00:00
|
|
|
//eprintf ("FAIL MS=%d l=%d d=%d\n", ms, l, d);
|
2012-08-13 11:16:06 +00:00
|
|
|
/* check if address is vaddred in sections */
|
|
|
|
ut64 o = r_io_section_offset_to_vaddr (io, addr);
|
|
|
|
if (o == UT64_MAX) {
|
|
|
|
ut64 o = r_io_section_vaddr_to_offset (io, addr);
|
|
|
|
if (o == UT64_MAX)
|
|
|
|
memset (buf+w, 0xff, l);
|
|
|
|
}
|
2012-08-13 02:33:01 +00:00
|
|
|
break;
|
|
|
|
}
|
2012-09-21 00:25:44 +00:00
|
|
|
////if (eof) break;
|
2011-10-25 18:30:05 +00:00
|
|
|
w += l;
|
|
|
|
len -= l;
|
2012-09-21 00:25:44 +00:00
|
|
|
break;
|
2011-10-25 18:30:05 +00:00
|
|
|
}
|
|
|
|
return olen;
|
2009-09-02 00:10:51 +00:00
|
|
|
}
|
|
|
|
|
2011-10-25 18:30:05 +00:00
|
|
|
R_API ut64 r_io_read_i(RIO *io, ut64 addr, int sz, int endian) {
|
2009-08-22 04:54:41 +00:00
|
|
|
ut64 ret = 0LL;
|
|
|
|
int err;
|
2009-09-02 00:10:51 +00:00
|
|
|
ut8 buf[8];
|
2009-08-22 04:54:41 +00:00
|
|
|
if (sz > 8) sz = 8;
|
|
|
|
if (sz < 0) sz = 1;
|
2010-03-23 22:26:59 +00:00
|
|
|
err = r_io_read_at (io, addr, buf, sz);
|
|
|
|
if (err == sz) r_mem_copyendian ((ut8*)&ret, buf, sz, endian);
|
2010-08-19 00:30:12 +00:00
|
|
|
else return -1;
|
|
|
|
//else perror("Cannot read");
|
2009-08-22 04:54:41 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2012-09-21 00:25:44 +00:00
|
|
|
R_API int r_io_resize(RIO *io, ut64 newsize) {
|
2011-01-17 14:28:40 +00:00
|
|
|
if (io->plugin && io->plugin->resize)
|
|
|
|
return io->plugin->resize (io, io->fd, newsize);
|
2011-01-20 21:52:16 +00:00
|
|
|
else ftruncate (io->fd->fd, newsize);
|
2011-01-17 14:28:40 +00:00
|
|
|
return R_FALSE;
|
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) {
|
2009-09-02 00:10:51 +00:00
|
|
|
int ret = R_FALSE;
|
2009-02-05 21:08:46 +00:00
|
|
|
if (len) {
|
2011-01-20 21:52:16 +00:00
|
|
|
io->write_mask_fd = io->fd->fd;
|
2010-03-23 22:26:59 +00:00
|
|
|
io->write_mask_buf = (ut8 *)malloc (len);
|
|
|
|
memcpy (io->write_mask_buf, buf, len);
|
2009-02-05 21:08:46 +00:00
|
|
|
io->write_mask_len = len;
|
|
|
|
ret = R_TRUE;
|
2009-09-02 00:10:51 +00:00
|
|
|
} else io->write_mask_fd = -1;
|
2009-02-05 21:08:46 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2010-03-23 22:26:59 +00:00
|
|
|
R_API int r_io_write(struct r_io_t *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 */
|
2010-03-23 22:26:59 +00:00
|
|
|
if (io->enforce_rwx && !(r_io_section_get_rwx (io, io->off) & R_IO_WRITE))
|
2009-09-08 02:14:19 +00:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (io->cached) {
|
2010-03-23 22:26:59 +00:00
|
|
|
ret = r_io_cache_write (io, io->off, buf, len);
|
2009-09-08 02:14:19 +00:00
|
|
|
if (ret == len)
|
|
|
|
return len;
|
|
|
|
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) {
|
2010-06-28 12:12:34 +00:00
|
|
|
data = malloc (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);
|
2010-06-28 12:12:34 +00:00
|
|
|
for (i=0; i<len; i++)
|
2009-02-05 21:08:46 +00:00
|
|
|
data[i] = buf[i] & \
|
|
|
|
io->write_mask_buf[i%io->write_mask_len];
|
|
|
|
buf = data;
|
|
|
|
}
|
2011-04-07 07:35:03 +00:00
|
|
|
|
2012-02-06 23:44:46 +00:00
|
|
|
r_io_map_select (io, io->off);
|
2011-04-07 07:35:03 +00:00
|
|
|
|
|
|
|
if (io->plugin) {
|
|
|
|
if (io->plugin->write)
|
|
|
|
ret = io->plugin->write (io, io->fd, buf, len);
|
|
|
|
else eprintf ("r_io_write: io handler with no write callback\n");
|
|
|
|
} else ret = write (io->fd->fd, buf, len);
|
|
|
|
|
|
|
|
if (ret == -1)
|
|
|
|
eprintf ("r_io_write: cannot write on fd %d\n", io->fd->fd);
|
2010-06-28 12:12:34 +00:00
|
|
|
if (data)
|
|
|
|
free (data);
|
2009-02-05 21:08:46 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2010-03-23 22:26:59 +00:00
|
|
|
R_API int r_io_write_at(struct r_io_t *io, ut64 addr, const ut8 *buf, int len) {
|
|
|
|
if (r_io_seek (io, addr, R_IO_SEEK_SET)<0)
|
2009-09-02 00:10:51 +00:00
|
|
|
return -1;
|
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
|
|
|
|
2010-03-23 22:26:59 +00:00
|
|
|
R_API ut64 r_io_seek(struct r_io_t *io, ut64 offset, int whence) {
|
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;
|
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;
|
2011-04-18 22:59:16 +00:00
|
|
|
ret = offset;
|
2009-02-05 21:08:46 +00:00
|
|
|
break;
|
|
|
|
case R_IO_SEEK_CUR:
|
2011-01-20 21:52:16 +00:00
|
|
|
// offset += io->off;
|
2009-02-05 21:08:46 +00:00
|
|
|
posix_whence = SEEK_CUR;
|
2011-02-12 00:52:41 +00:00
|
|
|
ret = offset+io->off;
|
2009-02-05 21:08:46 +00:00
|
|
|
break;
|
|
|
|
case R_IO_SEEK_END:
|
2010-05-20 23:34:35 +00:00
|
|
|
//offset = UT64_MAX; // XXX: depending on io bits?
|
2011-01-20 23:21:32 +00:00
|
|
|
ret = UT64_MAX;
|
2009-02-05 21:08:46 +00:00
|
|
|
posix_whence = SEEK_END;
|
|
|
|
break;
|
|
|
|
}
|
2011-01-20 22:28:20 +00:00
|
|
|
if (io == NULL)
|
|
|
|
return ret;
|
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);
|
|
|
|
if (!io->debug && io->va && !r_list_empty (io->sections)) {
|
|
|
|
ut64 o = r_io_section_vaddr_to_offset (io, offset);
|
|
|
|
if (o != UT64_MAX)
|
|
|
|
offset = o;
|
|
|
|
// eprintf ("-(vadd)-> 0x%08llx\n", offset);
|
|
|
|
}
|
2011-04-18 22:59:16 +00:00
|
|
|
// if resolution fails... just return as invalid address
|
|
|
|
if (offset==UT64_MAX)
|
|
|
|
return UT64_MAX;
|
2009-09-08 02:14:19 +00:00
|
|
|
// TODO: implement io->enforce_seek here!
|
2011-01-20 21:52:16 +00:00
|
|
|
if (io->fd != NULL) {
|
2011-10-25 18:30:05 +00:00
|
|
|
// lseek_internal
|
2011-01-20 21:52:16 +00:00
|
|
|
if (io->plugin && io->plugin->lseek)
|
|
|
|
ret = io->plugin->lseek (io, io->fd, offset, whence);
|
|
|
|
// XXX can be problematic on w32..so no 64 bit offset?
|
2011-06-28 22:36:52 +00:00
|
|
|
else ret = (ut64)lseek (io->fd->fd, offset, posix_whence);
|
2011-06-04 01:14:04 +00:00
|
|
|
if (ret != UT64_MAX) {
|
2011-01-20 21:52:16 +00:00
|
|
|
io->off = ret;
|
2011-04-19 12:43:48 +00:00
|
|
|
// XXX this can be tricky.. better not to use this .. must be deprecated
|
2011-01-20 21:52:16 +00:00
|
|
|
// r_io_sundo_push (io);
|
2011-04-19 12:43:48 +00:00
|
|
|
ret = (!io->debug && io->va && !r_list_empty (io->sections))?
|
2011-01-20 21:52:16 +00:00
|
|
|
r_io_section_offset_to_vaddr (io, io->off) : io->off;
|
2011-01-23 17:19:03 +00:00
|
|
|
} //else eprintf ("r_io_seek: cannot seek to %"PFMT64x"\n", offset);
|
|
|
|
} //else { eprintf ("r_io_seek: null fd\n"); }
|
2010-04-08 12:04:34 +00:00
|
|
|
return ret;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
|
|
|
|
2011-01-20 23:21:32 +00:00
|
|
|
R_API ut64 r_io_size(RIO *io) {
|
2012-08-08 15:19:48 +00:00
|
|
|
int iova;
|
2009-08-22 04:54:41 +00:00
|
|
|
ut64 size, here;
|
2012-08-08 15:19:48 +00:00
|
|
|
if (!io) return 0LL;
|
|
|
|
iova = io->va;
|
2011-02-04 23:20:28 +00:00
|
|
|
if (r_io_is_listener (io))
|
|
|
|
return UT64_MAX;
|
2011-11-12 03:51:45 +00:00
|
|
|
// XXX. problematic when io.va = 1
|
|
|
|
io->va = 0;
|
2011-01-20 23:21:32 +00:00
|
|
|
//r_io_set_fdn (io, fd);
|
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);
|
2011-11-12 03:51:45 +00:00
|
|
|
io->va = iova;
|
2010-03-23 22:26:59 +00:00
|
|
|
r_io_seek (io, here, R_IO_SEEK_SET);
|
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)
|
2010-03-23 22:26:59 +00:00
|
|
|
ret = io->plugin->system (io, io->fd, cmd);
|
2009-09-05 23:58:02 +00:00
|
|
|
return ret;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
|
|
|
|
2009-09-02 00:10:51 +00:00
|
|
|
// TODO: remove int fd here???
|
2011-01-20 21:52:16 +00:00
|
|
|
R_API int r_io_close(struct r_io_t *io, RIODesc *fd) {
|
|
|
|
if (io == NULL || fd == NULL)
|
|
|
|
return -1;
|
|
|
|
int nfd = fd->fd;
|
|
|
|
if (r_io_set_fd (io, fd)) {
|
|
|
|
RIODesc *desc = r_io_desc_get (io, fd->fd);
|
2011-02-07 08:46:01 +00:00
|
|
|
if (desc) {
|
|
|
|
r_io_map_del (io, fd->fd);
|
|
|
|
r_io_plugin_close (io, fd->fd, io->plugin);
|
|
|
|
if (io->plugin && io->plugin->close)
|
|
|
|
return io->plugin->close (desc);
|
|
|
|
r_io_desc_del (io, desc->fd);
|
|
|
|
}
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
2011-01-20 21:52:16 +00:00
|
|
|
io->fd = NULL; // unset current fd
|
|
|
|
return close (nfd);
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
2009-09-10 20:51:34 +00:00
|
|
|
|
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;
|
|
|
|
bnd->init = R_TRUE;
|
|
|
|
bnd->read_at = r_io_read_at;
|
|
|
|
bnd->write_at = r_io_write_at;
|
|
|
|
//bnd->fd = io->fd;// do we need to store ptr to fd??
|
|
|
|
return R_TRUE;
|
|
|
|
}
|
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)
|
2011-02-05 11:51:37 +00:00
|
|
|
return io->plugin->accept (io, io->fd, fd);
|
2011-02-04 23:20:28 +00:00
|
|
|
return R_FALSE;
|
|
|
|
}
|
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);
|
|
|
|
if (!shiftsize || (end-start) <= shiftsize) return R_FALSE;
|
|
|
|
rest = (end-start) - shiftsize;
|
|
|
|
|
|
|
|
if (!(buf = malloc (chunksize))) return R_FALSE;
|
|
|
|
|
|
|
|
if (move>0) src = end-shiftsize;
|
|
|
|
else src = start+shiftsize;
|
|
|
|
|
|
|
|
while (rest>0) {
|
|
|
|
if (chunksize>rest) chunksize=rest;
|
|
|
|
if (move>0) src -= chunksize;
|
|
|
|
|
|
|
|
r_io_read_at (io, src, buf, chunksize);
|
|
|
|
r_io_write_at (io, src+move, buf, chunksize);
|
|
|
|
|
|
|
|
if (move<0) src += chunksize;
|
|
|
|
rest -= chunksize;
|
|
|
|
}
|
|
|
|
free (buf);
|
|
|
|
return R_TRUE;
|
|
|
|
}
|
2012-07-06 00:17:44 +00:00
|
|
|
|
|
|
|
R_API int r_io_create (RIO *io, const char *file, int mode, int type) {
|
|
|
|
if (io->plugin && io->plugin->create)
|
|
|
|
return io->plugin->create (io, file, mode, type);
|
2012-08-08 15:19:48 +00:00
|
|
|
if (type == 'd'|| type == 1)
|
2012-08-10 09:35:38 +00:00
|
|
|
return r_sys_mkdir (file);
|
2012-08-08 15:19:48 +00:00
|
|
|
return creat (file, mode)? R_FALSE: R_TRUE;
|
2012-07-06 00:17:44 +00:00
|
|
|
}
|