2014-01-04 01:06:36 +00:00
|
|
|
/* radare - LGPL - Copyright 2009-2014 - pancake */
|
2009-09-08 01:08:46 +00:00
|
|
|
|
2014-05-02 21:43:47 +00:00
|
|
|
#include <r_types.h>
|
|
|
|
#include <r_util.h>
|
|
|
|
#include <r_io.h>
|
2009-09-08 01:08:46 +00:00
|
|
|
|
2009-10-12 15:41:52 +00:00
|
|
|
#if 0
|
|
|
|
/* TODO: the basic object lifecycle must be simplified */
|
|
|
|
struct r_class_t {
|
|
|
|
// new/free are implicit
|
|
|
|
.init = &r_buf_init,
|
|
|
|
.fini = &r_buf_fini,
|
|
|
|
} r_buf_class;
|
|
|
|
|
|
|
|
#define r_buf_init(x) r_buf_class->init
|
|
|
|
#endif
|
|
|
|
|
2011-07-25 19:10:25 +00:00
|
|
|
R_API RBuffer *r_buf_new() {
|
2014-04-29 16:10:35 +00:00
|
|
|
RBuffer *b = R_NEW0 (RBuffer);
|
2009-10-12 15:41:52 +00:00
|
|
|
if (b) {
|
2010-01-23 12:42:44 +00:00
|
|
|
b->buf = NULL;
|
2009-10-12 15:41:52 +00:00
|
|
|
b->length = 0;
|
2010-01-23 12:42:44 +00:00
|
|
|
b->cur = 0;
|
2009-10-12 15:41:52 +00:00
|
|
|
b->base = 0LL;
|
2012-01-26 02:18:45 +00:00
|
|
|
b->mmap = NULL;
|
2009-10-12 15:41:52 +00:00
|
|
|
}
|
2009-09-08 01:08:46 +00:00
|
|
|
return b;
|
|
|
|
}
|
|
|
|
|
2014-05-08 17:27:50 +00:00
|
|
|
R_API const ut8 *r_buf_buffer (RBuffer *b) {
|
|
|
|
if (b) return b->buf;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2014-05-08 19:08:21 +00:00
|
|
|
R_API ut64 r_buf_size (RBuffer *b) {
|
2014-05-08 17:27:50 +00:00
|
|
|
if (b && b->empty) return 0;
|
|
|
|
else if (b) return b->length;
|
|
|
|
return UT64_MAX;
|
|
|
|
}
|
|
|
|
|
2014-05-02 21:43:47 +00:00
|
|
|
R_API RBuffer *r_buf_mmap (const char *file, int flags) {
|
|
|
|
int rw = flags&R_IO_WRITE ? R_TRUE : R_FALSE;
|
2012-01-26 02:18:45 +00:00
|
|
|
RBuffer *b = r_buf_new ();
|
2012-08-13 15:42:25 +00:00
|
|
|
if (!b) return NULL;
|
2013-03-12 00:50:55 +00:00
|
|
|
b->mmap = r_file_mmap (file, rw, 0);
|
2014-04-29 16:10:35 +00:00
|
|
|
if (b->mmap) {
|
2012-01-31 01:45:17 +00:00
|
|
|
b->buf = b->mmap->buf;
|
|
|
|
b->length = b->mmap->len;
|
2014-04-29 16:10:35 +00:00
|
|
|
if (b->length == 0) b->empty = 1;
|
2013-03-12 00:50:55 +00:00
|
|
|
return b;
|
2012-01-31 01:45:17 +00:00
|
|
|
}
|
2013-03-12 00:50:55 +00:00
|
|
|
r_buf_free (b);
|
|
|
|
return NULL; /* we just freed b, don't return it */
|
2012-01-26 02:18:45 +00:00
|
|
|
}
|
|
|
|
|
2013-01-23 17:38:08 +00:00
|
|
|
R_API RBuffer *r_buf_file (const char *file) {
|
|
|
|
RBuffer *b = r_buf_new ();
|
|
|
|
if (!b) return NULL;
|
|
|
|
b->buf = (ut8*)r_file_slurp (file, &b->length);
|
2013-03-12 00:50:55 +00:00
|
|
|
if (b->buf) return b;
|
|
|
|
r_buf_free (b);
|
|
|
|
return NULL; /* we just freed b, don't return it */
|
2013-01-23 17:38:08 +00:00
|
|
|
}
|
|
|
|
|
2010-03-03 01:41:41 +00:00
|
|
|
R_API int r_buf_set_bits(RBuffer *b, int bitoff, int bitsize, ut64 value) {
|
2009-10-12 15:41:52 +00:00
|
|
|
// TODO: implement r_buf_set_bits
|
|
|
|
// TODO: get the implementation from reg/value.c ?
|
2009-11-23 17:00:08 +00:00
|
|
|
return R_FALSE;
|
2009-10-12 15:41:52 +00:00
|
|
|
}
|
|
|
|
|
2011-11-13 03:47:56 +00:00
|
|
|
R_API int r_buf_set_bytes(RBuffer *b, const ut8 *buf, int length) {
|
2014-03-20 16:59:08 +00:00
|
|
|
if (length<=0 || !buf) return R_FALSE;
|
2014-05-09 15:40:28 +00:00
|
|
|
free (b->buf);
|
2014-03-20 16:59:08 +00:00
|
|
|
if (!(b->buf = malloc (length)))
|
2009-10-12 15:41:52 +00:00
|
|
|
return R_FALSE;
|
2010-03-03 01:41:41 +00:00
|
|
|
memcpy (b->buf, buf, length);
|
2009-09-08 01:08:46 +00:00
|
|
|
b->length = length;
|
2014-04-29 16:10:35 +00:00
|
|
|
b->empty = 0;
|
2009-10-12 15:41:52 +00:00
|
|
|
return R_TRUE;
|
2009-09-08 01:08:46 +00:00
|
|
|
}
|
|
|
|
|
2011-02-27 19:30:41 +00:00
|
|
|
R_API int r_buf_prepend_bytes(RBuffer *b, const ut8 *buf, int length) {
|
|
|
|
if (!(b->buf = realloc (b->buf, b->length+length)))
|
|
|
|
return R_FALSE;
|
|
|
|
memmove (b->buf+length, b->buf, b->length);
|
|
|
|
memcpy (b->buf, buf, length);
|
|
|
|
b->length += length;
|
2014-04-29 16:10:35 +00:00
|
|
|
b->empty = 0;
|
2011-02-27 19:30:41 +00:00
|
|
|
return R_TRUE;
|
|
|
|
}
|
|
|
|
|
2011-11-30 09:27:01 +00:00
|
|
|
// TODO: R_API void r_buf_insert_bytes() // with shift
|
|
|
|
// TODO: R_API void r_buf_write_bytes() // overwrite
|
|
|
|
|
2011-02-27 19:30:41 +00:00
|
|
|
R_API char *r_buf_to_string(RBuffer *b) {
|
2011-07-26 23:16:18 +00:00
|
|
|
char *s;
|
|
|
|
if (!b) return strdup ("");
|
|
|
|
s = malloc (b->length+1);
|
2011-02-27 19:30:41 +00:00
|
|
|
memcpy (s, b->buf, b->length);
|
|
|
|
s[b->length] = 0;
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API int r_buf_append_bytes(RBuffer *b, const ut8 *buf, int length) {
|
2014-04-29 16:10:35 +00:00
|
|
|
if (b->empty) b->length = b->empty = 0;
|
2010-10-02 15:21:51 +00:00
|
|
|
if (!(b->buf = realloc (b->buf, b->length+length)))
|
|
|
|
return R_FALSE;
|
|
|
|
memcpy (b->buf+b->length, buf, length);
|
|
|
|
b->length += length;
|
2014-04-29 16:10:35 +00:00
|
|
|
|
2010-10-02 15:21:51 +00:00
|
|
|
return R_TRUE;
|
|
|
|
}
|
|
|
|
|
2011-07-25 19:10:25 +00:00
|
|
|
R_API int r_buf_append_nbytes(RBuffer *b, int length) {
|
2014-04-29 16:10:35 +00:00
|
|
|
if (b->empty) b->length = b->empty = 0;
|
2011-07-25 19:10:25 +00:00
|
|
|
if (!(b->buf = realloc (b->buf, b->length+length)))
|
|
|
|
return R_FALSE;
|
|
|
|
memset (b->buf+b->length, 0, length);
|
|
|
|
b->length += length;
|
|
|
|
return R_TRUE;
|
|
|
|
}
|
|
|
|
|
2011-07-25 21:20:49 +00:00
|
|
|
R_API int r_buf_append_ut16(RBuffer *b, ut16 n) {
|
2014-04-29 16:10:35 +00:00
|
|
|
if (b->empty) b->length = b->empty = 0;
|
2011-07-25 21:20:49 +00:00
|
|
|
if (!(b->buf = realloc (b->buf, b->length+sizeof (n))))
|
|
|
|
return R_FALSE;
|
|
|
|
memcpy (b->buf+b->length, &n, sizeof (n));
|
|
|
|
b->length += sizeof (n);
|
|
|
|
return R_TRUE;
|
|
|
|
}
|
|
|
|
|
2011-07-25 19:10:25 +00:00
|
|
|
R_API int r_buf_append_ut32(RBuffer *b, ut32 n) {
|
2014-04-29 16:10:35 +00:00
|
|
|
if (b->empty) b->length = b->empty = 0;
|
2011-07-25 19:10:25 +00:00
|
|
|
if (!(b->buf = realloc (b->buf, b->length+sizeof (n))))
|
|
|
|
return R_FALSE;
|
|
|
|
memcpy (b->buf+b->length, &n, sizeof (n));
|
|
|
|
b->length += sizeof (n);
|
|
|
|
return R_TRUE;
|
|
|
|
}
|
|
|
|
|
2011-07-25 21:20:49 +00:00
|
|
|
R_API int r_buf_append_ut64(RBuffer *b, ut64 n) {
|
2014-04-29 16:10:35 +00:00
|
|
|
if (b->empty) b->length = b->empty = 0;
|
2011-07-25 21:20:49 +00:00
|
|
|
if (!(b->buf = realloc (b->buf, b->length+sizeof (n))))
|
|
|
|
return R_FALSE;
|
|
|
|
memcpy (b->buf+b->length, &n, sizeof (n));
|
|
|
|
b->length += sizeof (n);
|
|
|
|
return R_TRUE;
|
|
|
|
}
|
|
|
|
|
2011-12-01 02:28:12 +00:00
|
|
|
R_API int r_buf_append_buf(RBuffer *b, RBuffer *a) {
|
2014-04-29 16:10:35 +00:00
|
|
|
if (b->empty) {
|
|
|
|
b->length = 0;
|
|
|
|
b->empty = 0;
|
|
|
|
}
|
2011-12-01 02:28:12 +00:00
|
|
|
if (!(b->buf = realloc (b->buf, b->length+a->length)))
|
|
|
|
return R_FALSE;
|
|
|
|
memcpy (b->buf+b->length, a->buf, a->length);
|
|
|
|
b->length += a->length;
|
|
|
|
return R_TRUE;
|
|
|
|
}
|
|
|
|
|
2010-03-11 12:18:49 +00:00
|
|
|
static int r_buf_cpy(RBuffer *b, ut64 addr, ut8 *dst, const ut8 *src, int len, int write) {
|
2009-09-08 01:08:46 +00:00
|
|
|
int end;
|
2014-04-29 16:10:35 +00:00
|
|
|
if (!b || b->empty) return 0;
|
2011-07-18 22:12:36 +00:00
|
|
|
addr = (addr==R_BUF_CUR)? b->cur: addr-b->base;
|
2012-09-22 18:32:19 +00:00
|
|
|
if (len<1 || dst == NULL || addr > b->length)
|
2009-09-08 01:08:46 +00:00
|
|
|
return -1;
|
|
|
|
end = (int)(addr+len);
|
|
|
|
if (end > b->length)
|
|
|
|
len -= end-b->length;
|
2010-03-11 12:18:49 +00:00
|
|
|
if (write)
|
|
|
|
dst += addr;
|
|
|
|
else src += addr;
|
|
|
|
memcpy (dst, src, len);
|
2010-01-23 12:42:44 +00:00
|
|
|
b->cur = addr + len;
|
2009-09-08 01:08:46 +00:00
|
|
|
return len;
|
|
|
|
}
|
|
|
|
|
2010-03-18 23:36:28 +00:00
|
|
|
static int r_buf_fcpy_at (RBuffer *b, ut64 addr, ut8 *buf, const char *fmt, int n, int write) {
|
2010-01-19 21:41:45 +00:00
|
|
|
int i, j, k, len, tsize, endian, m = 1;
|
2014-04-29 16:10:35 +00:00
|
|
|
if (!b || b->empty) return 0;
|
2010-01-23 12:42:44 +00:00
|
|
|
if (addr == R_BUF_CUR)
|
|
|
|
addr = b->cur;
|
|
|
|
else addr -= b->base;
|
2013-09-15 21:57:22 +00:00
|
|
|
if (addr == UT64_MAX || addr > b->length)
|
2010-01-19 21:41:45 +00:00
|
|
|
return -1;
|
|
|
|
for (i = len = 0; i < n; i++)
|
|
|
|
for (j = 0; fmt[j]; j++) {
|
|
|
|
if (len > b->length)
|
|
|
|
return -1;
|
|
|
|
switch (fmt[j]) {
|
|
|
|
case '0'...'9':
|
|
|
|
if (m == 1)
|
2013-04-04 21:19:19 +00:00
|
|
|
m = r_num_get (NULL, &fmt[j]);
|
2010-01-19 21:41:45 +00:00
|
|
|
continue;
|
|
|
|
case 's': tsize = 2; endian = 1; break;
|
|
|
|
case 'S': tsize = 2; endian = 0; break;
|
|
|
|
case 'i': tsize = 4; endian = 1; break;
|
|
|
|
case 'I': tsize = 4; endian = 0; break;
|
|
|
|
case 'l': tsize = 8; endian = 1; break;
|
|
|
|
case 'L': tsize = 8; endian = 0; break;
|
|
|
|
case 'c': tsize = 1; endian = 1; break;
|
|
|
|
default: return -1;
|
|
|
|
}
|
2010-03-18 23:36:28 +00:00
|
|
|
for (k = 0; k < m; k++) {
|
2013-04-04 21:19:19 +00:00
|
|
|
if (write) r_mem_copyendian(
|
|
|
|
(ut8*)&buf[addr+len+k*tsize],
|
|
|
|
(ut8*)&b->buf[len+k*tsize], tsize, endian);
|
|
|
|
else r_mem_copyendian(
|
|
|
|
(ut8*)&buf[len+k*tsize],
|
|
|
|
(ut8*)&b->buf[addr+len+k*tsize], tsize, endian);
|
2010-03-18 23:36:28 +00:00
|
|
|
}
|
2010-01-19 21:41:45 +00:00
|
|
|
len += m*tsize; m = 1;
|
|
|
|
}
|
2010-01-23 12:42:44 +00:00
|
|
|
b->cur = addr + len;
|
2010-01-19 21:41:45 +00:00
|
|
|
return len;
|
|
|
|
}
|
|
|
|
|
2013-04-04 21:19:19 +00:00
|
|
|
R_API ut8 *r_buf_get_at (RBuffer *b, ut64 addr, int *left) {
|
2014-04-29 16:10:35 +00:00
|
|
|
if (b->empty) return 0;
|
2013-04-04 21:19:19 +00:00
|
|
|
if (addr == R_BUF_CUR)
|
|
|
|
addr = b->cur;
|
|
|
|
else addr -= b->base;
|
2013-09-15 21:57:22 +00:00
|
|
|
if (addr == UT64_MAX || addr > b->length)
|
2013-04-04 21:19:19 +00:00
|
|
|
return NULL;
|
|
|
|
if (left)
|
|
|
|
*left = b->length - addr;
|
|
|
|
return b->buf+addr;
|
|
|
|
}
|
|
|
|
|
2010-03-18 23:36:28 +00:00
|
|
|
R_API int r_buf_read_at(RBuffer *b, ut64 addr, ut8 *buf, int len) {
|
2012-11-27 13:09:53 +00:00
|
|
|
if (!b) return 0;
|
2010-03-18 23:36:28 +00:00
|
|
|
return r_buf_cpy (b, addr, buf, b->buf, len, R_FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API int r_buf_fread_at (RBuffer *b, ut64 addr, ut8 *buf, const char *fmt, int n) {
|
|
|
|
return r_buf_fcpy_at (b, addr, buf, fmt, n, R_FALSE);
|
|
|
|
}
|
|
|
|
|
2010-03-03 01:41:41 +00:00
|
|
|
R_API int r_buf_write_at(RBuffer *b, ut64 addr, const ut8 *buf, int len) {
|
2012-11-27 13:09:53 +00:00
|
|
|
if (!b) return 0;
|
2014-04-29 16:10:35 +00:00
|
|
|
if (b->empty) {
|
|
|
|
b->empty = 0;
|
|
|
|
free (b->buf);
|
|
|
|
b->buf = (ut8 *) malloc (addr + len);
|
|
|
|
}
|
2010-03-11 12:18:49 +00:00
|
|
|
return r_buf_cpy (b, addr, b->buf, buf, len, R_TRUE);
|
2009-09-08 01:08:46 +00:00
|
|
|
}
|
|
|
|
|
2010-03-18 23:36:28 +00:00
|
|
|
R_API int r_buf_fwrite_at (RBuffer *b, ut64 addr, ut8 *buf, const char *fmt, int n) {
|
|
|
|
return r_buf_fcpy_at (b, addr, buf, fmt, n, R_TRUE);
|
|
|
|
}
|
|
|
|
|
2012-01-26 02:18:45 +00:00
|
|
|
R_API void r_buf_deinit(RBuffer *b) {
|
|
|
|
if (b->mmap) {
|
|
|
|
r_file_mmap_free (b->mmap);
|
|
|
|
b->mmap = NULL;
|
2014-02-16 02:11:41 +00:00
|
|
|
} else free (b->buf);
|
2009-10-12 15:41:52 +00:00
|
|
|
}
|
|
|
|
|
2010-03-03 01:41:41 +00:00
|
|
|
R_API void r_buf_free(struct r_buf_t *b) {
|
2011-12-01 02:28:12 +00:00
|
|
|
if (!b) return;
|
2010-03-03 01:41:41 +00:00
|
|
|
r_buf_deinit (b);
|
|
|
|
free (b);
|
2009-09-08 01:08:46 +00:00
|
|
|
}
|
2014-01-04 00:59:23 +00:00
|
|
|
|
|
|
|
R_API int r_buf_append_string (RBuffer *b, const char *str) {
|
|
|
|
return r_buf_append_bytes (b, (const ut8*)str, strlen (str));
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API char *r_buf_free_to_string (RBuffer *b) {
|
|
|
|
char *p;
|
|
|
|
if (!b) return NULL;
|
|
|
|
if (b->mmap) {
|
|
|
|
p = r_buf_to_string (b);
|
|
|
|
} else {
|
|
|
|
r_buf_append_bytes (b, (const ut8*)"", 1);
|
|
|
|
p = (char *)b->buf;
|
|
|
|
}
|
|
|
|
free (b);
|
|
|
|
return p;
|
|
|
|
}
|