* Add 'r_io_undo'
* Added deinitializators for r_io_cache
This commit is contained in:
parent
780e424cbe
commit
fdf164e229
2
TODO
2
TODO
|
@ -7,7 +7,7 @@
|
||||||
----------------------------------------[ todo
|
----------------------------------------[ todo
|
||||||
|
|
||||||
<{include libr/TODO}>
|
<{include libr/TODO}>
|
||||||
|
|
||||||
* correct result (R_TRUFAE), but with warnings (implement r_errno and r_errstr in r_util?)
|
* correct result (R_TRUFAE), but with warnings (implement r_errno and r_errstr in r_util?)
|
||||||
- Quantic computation ftw \o/
|
- Quantic computation ftw \o/
|
||||||
* r_cmd must provide a nesting char table indexing for commands
|
* r_cmd must provide a nesting char table indexing for commands
|
||||||
|
|
|
@ -4,18 +4,14 @@
|
||||||
#include "r_types.h"
|
#include "r_types.h"
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
|
|
||||||
#define R_IO_READ 0
|
#define R_IO_READ 4
|
||||||
#define R_IO_WRITE 1
|
#define R_IO_WRITE 2
|
||||||
#define R_IO_EXEC 4
|
#define R_IO_EXEC 1
|
||||||
|
|
||||||
|
#define R_IO_SEEK_SET 0
|
||||||
|
#define R_IO_SEEK_CUR 1
|
||||||
|
#define R_IO_SEEK_END 2
|
||||||
|
|
||||||
#if 0
|
|
||||||
// TODO: rename SECTION to PERMISION or so
|
|
||||||
enum {
|
|
||||||
R_IO_SECTION_R = 4,
|
|
||||||
R_IO_SECTION_W = 2,
|
|
||||||
R_IO_SECTION_X = 1,
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
#if 0
|
#if 0
|
||||||
// DEPRECATE ??
|
// DEPRECATE ??
|
||||||
#define R_IO_RW R_IO_READ|R_IO_WRITE
|
#define R_IO_RW R_IO_READ|R_IO_WRITE
|
||||||
|
@ -26,9 +22,6 @@ enum {
|
||||||
|
|
||||||
#define R_IO_NFDS 32
|
#define R_IO_NFDS 32
|
||||||
|
|
||||||
#define R_IO_SEEK_SET 0
|
|
||||||
#define R_IO_SEEK_CUR 1
|
|
||||||
#define R_IO_SEEK_END 2
|
|
||||||
|
|
||||||
#define IO_MAP_N 128
|
#define IO_MAP_N 128
|
||||||
struct r_io_map_t {
|
struct r_io_map_t {
|
||||||
|
@ -43,13 +36,25 @@ struct r_io_map_t {
|
||||||
/* stores write and seek changes */
|
/* stores write and seek changes */
|
||||||
#define R_IO_UNDOS 64
|
#define R_IO_UNDOS 64
|
||||||
struct r_io_undo_t {
|
struct r_io_undo_t {
|
||||||
struct list_head undo_w_list;
|
int enable;
|
||||||
|
/* write stuff */
|
||||||
|
struct list_head w_list;
|
||||||
int w_init;
|
int w_init;
|
||||||
int w_lock;
|
int w_lock;
|
||||||
|
/* seek stuff */
|
||||||
ut64 seek[R_IO_UNDOS];
|
ut64 seek[R_IO_UNDOS];
|
||||||
int fd[R_IO_UNDOS];
|
int fd[R_IO_UNDOS];
|
||||||
int idx;
|
int idx;
|
||||||
int lim;
|
int limit;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct r_io_undo_w_t {
|
||||||
|
int set;
|
||||||
|
ut64 off;
|
||||||
|
ut8 *o; /* old data */
|
||||||
|
ut8 *n; /* new data */
|
||||||
|
int len; /* length */
|
||||||
|
struct list_head list;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct r_io_t {
|
struct r_io_t {
|
||||||
|
@ -65,6 +70,7 @@ struct r_io_t {
|
||||||
ut8 *write_mask_buf;
|
ut8 *write_mask_buf;
|
||||||
int write_mask_len;
|
int write_mask_len;
|
||||||
struct r_io_handle_t *plugin;
|
struct r_io_handle_t *plugin;
|
||||||
|
struct r_io_undo_t undo;
|
||||||
struct list_head io_list;
|
struct list_head io_list;
|
||||||
ut64 last_align;
|
ut64 last_align;
|
||||||
struct list_head sections;
|
struct list_head sections;
|
||||||
|
@ -205,6 +211,26 @@ R_API int r_io_desc_add(struct r_io_t *io, int fd, const char *file, int flags,
|
||||||
R_API int r_io_desc_del(struct r_io_t *io, int fd);
|
R_API int r_io_desc_del(struct r_io_t *io, int fd);
|
||||||
R_API struct r_io_desc_t *r_io_desc_get(struct r_io_t *io, int fd);
|
R_API struct r_io_desc_t *r_io_desc_get(struct r_io_t *io, int fd);
|
||||||
R_API int r_io_desc_generate(struct r_io_t *io);
|
R_API int r_io_desc_generate(struct r_io_t *io);
|
||||||
|
|
||||||
|
/* undo api */
|
||||||
|
// track seeks and writes
|
||||||
|
// TODO: needs cleanup..kinda big?
|
||||||
|
R_API int r_io_undo_init(struct r_io_t *io);
|
||||||
|
R_API void r_io_undo_enable(struct r_io_t *io, int set);
|
||||||
|
R_API ut64 r_io_undo_get_last_seek(struct r_io_t *io);
|
||||||
|
R_API void r_io_undo_seek(struct r_io_t *io);
|
||||||
|
R_API void r_io_undo_redo(struct r_io_t *io);
|
||||||
|
R_API void r_io_undo_push(struct r_io_t *io);
|
||||||
|
R_API void r_io_undo_reset(struct r_io_t *io);
|
||||||
|
R_API void r_io_undo_list(struct r_io_t *io);
|
||||||
|
R_API void r_io_undo_write_new(struct r_io_t *io, ut64 off, const ut8 *data, int len);
|
||||||
|
R_API void r_io_undo_write_clear(struct r_io_t *io);
|
||||||
|
R_API int r_io_undo_write_size(struct r_io_t *io);
|
||||||
|
R_API void r_io_undo_write_list(struct r_io_t *io);
|
||||||
|
R_API int r_io_undo_write_set_t(struct r_io_t *io, struct r_io_undo_w_t *u, int set) ;
|
||||||
|
R_API void r_io_undo_write_set_all(struct r_io_t *io, int set);
|
||||||
|
R_API int r_io_undo_write_set(struct r_io_t *io, int n, int set);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
#define CB_READ int (*cb_read)(struct r_io_t *user, int pid, ut64 addr, ut8 *buf, int len)
|
#define CB_READ int (*cb_read)(struct r_io_t *user, int pid, ut64 addr, ut8 *buf, int len)
|
||||||
#define CB_WRITE int (*cb_write)(struct r_io_t *user, int pid, ut64 addr, const ut8 *buf, int len)
|
#define CB_WRITE int (*cb_write)(struct r_io_t *user, int pid, ut64 addr, const ut8 *buf, int len)
|
||||||
|
|
|
@ -9,7 +9,7 @@ STATIC_OBJS=
|
||||||
include ../config.mk
|
include ../config.mk
|
||||||
include ${STATIC_IO_PLUGINS}
|
include ${STATIC_IO_PLUGINS}
|
||||||
STATIC_OBJS=$(subst ..,p/..,$(subst io_,p/io_,$(STATIC_OBJ)))
|
STATIC_OBJS=$(subst ..,p/..,$(subst io_,p/io_,$(STATIC_OBJ)))
|
||||||
OBJ=${STATIC_OBJS} io.o handle.o map.o section.o desc.o bind.o cache.o
|
OBJ=${STATIC_OBJS} io.o handle.o map.o section.o desc.o bind.o cache.o undo.o
|
||||||
|
|
||||||
pre:
|
pre:
|
||||||
@echo STATICOBJS: ${STATIC_OBJS}
|
@echo STATICOBJS: ${STATIC_OBJS}
|
||||||
|
|
|
@ -8,6 +8,22 @@ R_API int r_io_bind(struct r_io_t *io, struct r_io_bind_t *bnd)
|
||||||
return R_TRUE;
|
return R_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// define callback for other APIs to use with current io
|
||||||
|
static int _cb_read(struct r_io_t *io, int pid, ut64 addr, ut8 *buf, int len)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _cb_write(struct r_io_t *io, int pid, ut64 addr, const ut8 *buf, int len)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
R_API int r_io_hook(struct r_io_t *io, CB_IO)
|
||||||
|
{
|
||||||
|
return cb_io(user, _cb_read, _cb_write
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
|
||||||
this api must be used from r_vm, r_bin ...
|
this api must be used from r_vm, r_bin ...
|
||||||
|
|
|
@ -8,9 +8,30 @@
|
||||||
|
|
||||||
R_API void r_io_cache_init(struct r_io_t *io)
|
R_API void r_io_cache_init(struct r_io_t *io)
|
||||||
{
|
{
|
||||||
|
io->cached = 0; // IO cached
|
||||||
INIT_LIST_HEAD(&io->cache);
|
INIT_LIST_HEAD(&io->cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
R_API void r_io_cache_enable(struct r_io_t *io, int set)
|
||||||
|
{
|
||||||
|
io->cached = set;
|
||||||
|
}
|
||||||
|
|
||||||
|
R_API void r_io_cache_free(struct r_io_t *io, int set)
|
||||||
|
{
|
||||||
|
io->cached = set;
|
||||||
|
struct r_io_cache_t *c;
|
||||||
|
struct list_head *pos, *n;
|
||||||
|
|
||||||
|
list_for_each_safe(pos, n, &io->cache) {
|
||||||
|
c = list_entry(pos, struct r_io_cache_t, list);
|
||||||
|
free(c->data);
|
||||||
|
free(c);
|
||||||
|
}
|
||||||
|
// is this necessary at all?
|
||||||
|
INIT_LIST_HEAD(&io->cache);
|
||||||
|
}
|
||||||
|
|
||||||
R_API int r_io_cache_write(struct r_io_t *io, ut64 addr, const ut8 *buf, int len)
|
R_API int r_io_cache_write(struct r_io_t *io, ut64 addr, const ut8 *buf, int len)
|
||||||
{
|
{
|
||||||
struct r_io_cache_t *ch = MALLOC_STRUCT(struct r_io_cache_t);
|
struct r_io_cache_t *ch = MALLOC_STRUCT(struct r_io_cache_t);
|
||||||
|
@ -57,8 +78,3 @@ R_API int r_io_cache_write(struct r_io_t *io, ut64 off, ut8 *data, int len)
|
||||||
return r_io_write_at(io, off, data, len);
|
return r_io_write_at(io, off, data, len);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
R_API void r_io_cache_enable(struct r_io_t *io, int set)
|
|
||||||
{
|
|
||||||
io->cached = set;
|
|
||||||
}
|
|
||||||
|
|
29
libr/io/io.c
29
libr/io/io.c
|
@ -4,22 +4,21 @@
|
||||||
#include "r_util.h"
|
#include "r_util.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
|
||||||
R_API struct r_io_t *r_io_init(struct r_io_t *io)
|
R_API struct r_io_t *r_io_init(struct r_io_t *io)
|
||||||
{
|
{
|
||||||
io->write_mask_fd = -1;
|
io->write_mask_fd = -1;
|
||||||
io->last_align = 0;
|
io->last_align = 0;
|
||||||
io->redirect = NULL;
|
io->redirect = NULL;
|
||||||
io->printf = printf;
|
io->printf = printf;
|
||||||
io->enforce_rwx = 0; // do not enforce RWX section permissions by default
|
|
||||||
io->enforce_seek = 0; // do not limit seeks out of the file by default
|
|
||||||
io->enforce_rwx = 0;
|
|
||||||
io->enforce_seek = 0;
|
|
||||||
io->cached = 0; // IO cached
|
|
||||||
r_io_cache_init(io);
|
r_io_cache_init(io);
|
||||||
r_io_map_init(io);
|
r_io_map_init(io);
|
||||||
r_io_section_init(io);
|
r_io_section_init(io);
|
||||||
r_io_handle_init(io);
|
r_io_handle_init(io);
|
||||||
r_io_desc_init(io);
|
r_io_desc_init(io);
|
||||||
|
r_io_undo_init(&io->undo);
|
||||||
return io;
|
return io;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,7 +96,8 @@ R_API int r_io_open(struct r_io_t *io, const char *file, int flags, int mode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (fd == -2)
|
if (fd == -2)
|
||||||
fd = open(file, flags, mode);
|
// XXX RDONLY; READ; WRITE AND MORE SOO...
|
||||||
|
fd = open(file, O_RDONLY, mode); // XXX drop posix depz here
|
||||||
if (fd >= 0) {
|
if (fd >= 0) {
|
||||||
r_io_set_fd(io, fd);
|
r_io_set_fd(io, fd);
|
||||||
r_io_desc_add(io, fd, file, flags, io->plugin);
|
r_io_desc_add(io, fd, file, flags, io->plugin);
|
||||||
|
@ -116,6 +116,7 @@ R_API int r_io_set_fd(struct r_io_t *io, int fd)
|
||||||
return io->fd;
|
return io->fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
R_API int r_io_read(struct r_io_t *io, ut8 *buf, int len)
|
R_API int r_io_read(struct r_io_t *io, ut8 *buf, int len)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -312,19 +313,3 @@ R_API int r_io_close(struct r_io_t *io, int fd)
|
||||||
io->fd = -1; // unset current fd
|
io->fd = -1; // unset current fd
|
||||||
return close(fd);
|
return close(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
// define callback for other APIs to use with current io
|
|
||||||
static int _cb_read(struct r_io_t *io, int pid, ut64 addr, ut8 *buf, int len)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _cb_write(struct r_io_t *io, int pid, ut64 addr, const ut8 *buf, int len)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
R_API int r_io_hook(struct r_io_t *io, CB_IO)
|
|
||||||
{
|
|
||||||
return cb_io(user, _cb_read, _cb_write
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
|
|
||||||
R_API void r_io_section_init(struct r_io_t *io)
|
R_API void r_io_section_init(struct r_io_t *io)
|
||||||
{
|
{
|
||||||
|
io->enforce_rwx = 0; // do not enforce RWX section permissions by default
|
||||||
|
io->enforce_seek = 0; // do not limit seeks out of the file by default
|
||||||
INIT_LIST_HEAD(&(io->sections));
|
INIT_LIST_HEAD(&(io->sections));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
205
libr/io/undo.c
205
libr/io/undo.c
|
@ -1,170 +1,138 @@
|
||||||
/*
|
/* radare - LGPL - Copyright 2007-2009 pancake<nopcode.org> */
|
||||||
* Copyright (C) 2007, 2008, 2009
|
|
||||||
* pancake <@youterm.com>
|
|
||||||
*
|
|
||||||
* radare is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* radare is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with radare; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "main.h"
|
#include <r_io.h>
|
||||||
#include "radare.h"
|
|
||||||
#include "list.h"
|
#define cons_printf printf
|
||||||
#include "undo.h"
|
#define cons_newline() printf("\n");
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
* Handle changes in write and seeks
|
* TODO:
|
||||||
* Per-fd history log
|
* - make path of indirections shortr (io->undo.foo is slow) */
|
||||||
|
* - Handle changes in write and seeks
|
||||||
|
* - Per-fd history log
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if 0
|
R_API int r_io_undo_init(struct r_io_t *io)
|
||||||
/* History for writes support indexing and undo/redo with state flags */
|
|
||||||
static struct list_head undo_w_list;
|
|
||||||
static int undo_w_init = 0;
|
|
||||||
static int undo_w_lock = 0;
|
|
||||||
|
|
||||||
/* History for the N last seeks, stack-like access */
|
|
||||||
#define UNDOS 64
|
|
||||||
static ut64 undos[UNDOS];
|
|
||||||
static int undos_idx = 0;
|
|
||||||
static int undos_lim = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
int r_io_undo_init(struct r_io_undo_t *undo)
|
|
||||||
{
|
{
|
||||||
u->undo_w_init = 0;
|
io->undo.w_init = 0;
|
||||||
u->undo_w_lock = 0;
|
io->undo.w_lock = 0;
|
||||||
u->undos_idx = 0;
|
io->undo.idx = 0;
|
||||||
u->undos_lim = 0;
|
io->undo.limit = 0;
|
||||||
|
io->undo.enable = 0;
|
||||||
return R_TRUE;
|
return R_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ut64 r_io_undo_get_last()
|
R_API void r_io_undo_enable(struct r_io_t *io, int set)
|
||||||
{
|
{
|
||||||
|
io->undo.enable = set;
|
||||||
}
|
}
|
||||||
|
|
||||||
ut64 undo_get_last_seek()
|
R_API ut64 r_io_undo_get_last_seek(struct r_io_t *io)
|
||||||
{
|
{
|
||||||
if (undos_idx==0)
|
return (io->undo.idx)?
|
||||||
return config.seek;
|
io->undo.seek[io->undo.idx-2] : io->seek;
|
||||||
return undos[undos_idx-2];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void undo_seek()
|
R_API void r_io_undo_seek(struct r_io_t *io)
|
||||||
{
|
{
|
||||||
if (--undos_idx<0)
|
if (--io->undo.idx<0)
|
||||||
undos_idx = 0;
|
io->undo.idx = 0;
|
||||||
else config.seek = undos[undos_idx-1];
|
else io->seek = io->undo.seek[io->undo.idx-1];
|
||||||
}
|
}
|
||||||
|
|
||||||
void undo_redo()
|
R_API void r_io_undo_redo(struct r_io_t *io)
|
||||||
{
|
{
|
||||||
if (undos_idx<undos_lim) {
|
if (io->undo.idx<io->undo.limit) {
|
||||||
undos_idx+=2;
|
io->undo.idx += 2;
|
||||||
undo_seek();
|
r_io_undo_seek(io);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void undo_push()
|
R_API void r_io_undo_push(struct r_io_t *io)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (undos[undos_idx-1] == config.seek)
|
if (io->undo.seek[io->undo.idx-1] == io->seek)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
undos[undos_idx] = config.seek;
|
io->undo.seek[io->undo.idx] = io->seek;
|
||||||
if (undos_idx==UNDOS-1) {
|
if (io->undo.idx==R_IO_UNDOS-1) {
|
||||||
for(i=1;i<UNDOS;i++)
|
for(i=1;i<R_IO_UNDOS;i++)
|
||||||
undos[i-1] = undos[i];
|
io->undo.seek[i-1] = io->undo.seek[i];
|
||||||
} else
|
} else io->undo.idx++;
|
||||||
undos_idx++;
|
|
||||||
|
|
||||||
if (undos_lim<undos_idx)
|
if (io->undo.limit<io->undo.idx)
|
||||||
undos_lim = undos_idx;
|
io->undo.limit = io->undo.idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
void undo_reset()
|
R_API void r_io_undo_reset(struct r_io_t *io)
|
||||||
{
|
{
|
||||||
undos_idx = 0;
|
io->undo.idx = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void undo_list()
|
R_API void r_io_undo_list(struct r_io_t *io)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
if (undos_idx<1)
|
if (io->undo.idx>0) {
|
||||||
eprintf("-no seeks done-\n");
|
cons_printf("f undo_idx @ %d\n", io->undo.idx);
|
||||||
else {
|
for(i=io->undo.idx-1;i!=0;i--)
|
||||||
cons_printf("f undo_idx @ %d\n", undos_idx);
|
cons_printf("f undo_%d @ 0x%llx\n",
|
||||||
for(i=undos_idx-1;i!=0;i--)
|
io->undo.idx-1-i, io->undo.seek[i-1]);
|
||||||
cons_printf("f undo_%d @ 0x%llx\n", undos_idx-1-i, undos[i-1]);
|
} else eprintf("-no seeks done-\n");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void undo_write_new(ut64 off, const ut8 *data, int len)
|
R_API void r_io_undo_write_new(struct r_io_t *io, ut64 off, const ut8 *data, int len)
|
||||||
{
|
{
|
||||||
struct undow_t *uw = (struct undow_t *)malloc(sizeof(struct undow_t));
|
struct r_io_undo_w_t *uw = MALLOC_STRUCT(struct r_io_undo_w_t);
|
||||||
|
|
||||||
if (!config_get_i("file.undowrite"))
|
if (io->undo.w_lock)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (undo_w_lock)
|
if (!io->undo.w_init) {
|
||||||
return;
|
io->undo.w_init = 1;
|
||||||
|
INIT_LIST_HEAD(&(io->undo.w_list));
|
||||||
if (!undo_w_init) {
|
|
||||||
undo_w_init = 1;
|
|
||||||
INIT_LIST_HEAD(&(undo_w_list));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* undo changes */
|
/* undo changes */
|
||||||
uw->set = UNDO_WRITE_SET;
|
uw->set = R_TRUE;
|
||||||
uw->off = off;
|
uw->off = off;
|
||||||
uw->len = len;
|
uw->len = len;
|
||||||
uw->n = (ut8*) malloc(len);
|
uw->n = (ut8*) malloc(len);
|
||||||
memcpy(uw->n, data, len);
|
memcpy(uw->n, data, len);
|
||||||
uw->o = (ut8*) malloc(len);
|
uw->o = (ut8*) malloc(len);
|
||||||
radare_read_at(off, uw->o, len);
|
r_io_read_at(io, off, uw->o, len);
|
||||||
list_add_tail(&(uw->list), &(undo_w_list));
|
list_add_tail(&(uw->list), &(io->undo.w_list));
|
||||||
}
|
}
|
||||||
|
|
||||||
void undo_write_clear()
|
R_API void r_io_undo_write_clear(struct r_io_t *io)
|
||||||
{
|
{
|
||||||
// XXX memory leak
|
// XXX memory leak
|
||||||
INIT_LIST_HEAD(&(undo_w_list));
|
INIT_LIST_HEAD(&(io->undo.w_list));
|
||||||
}
|
}
|
||||||
|
|
||||||
int undo_write_size()
|
// rename to r_io_undo_length
|
||||||
|
R_API int r_io_undo_write_size(struct r_io_t *io)
|
||||||
{
|
{
|
||||||
struct list_head *p;
|
struct list_head *p;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
if (undo_w_init)
|
if (io->undo.w_init)
|
||||||
list_for_each_prev(p, &(undo_w_list)) {
|
list_for_each_prev(p, &(io->undo.w_list)) {
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
void undo_write_list()
|
// TODO: Deprecate or so? iterators must be language-wide, but helpers are useful
|
||||||
|
R_API void r_io_undo_write_list(struct r_io_t *io)
|
||||||
{
|
{
|
||||||
#define BW 8 /* byte wrap */
|
#define BW 8 /* byte wrap */
|
||||||
struct list_head *p;
|
struct list_head *p;
|
||||||
int i = 0, j, len;
|
int i = 0, j, len;
|
||||||
|
|
||||||
if (undo_w_init)
|
if (io->undo.w_init)
|
||||||
list_for_each_prev(p, &(undo_w_list)) {
|
list_for_each_prev(p, &(io->undo.w_list)) {
|
||||||
struct undow_t *u = list_entry(p, struct undow_t, list);
|
struct r_io_undo_w_t *u = list_entry(p, struct r_io_undo_w_t, list);
|
||||||
cons_printf("%02d %c %d %08llx: ", i, u->set?'+':'-', u->len, u->off);
|
cons_printf("%02d %c %d %08llx: ", i, u->set?'+':'-', u->len, u->off);
|
||||||
len = (u->len>BW)?BW:u->len;
|
len = (u->len>BW)?BW:u->len;
|
||||||
for(j=0;j<len;j++) cons_printf("%02x ", u->o[j]);
|
for(j=0;j<len;j++) cons_printf("%02x ", u->o[j]);
|
||||||
|
@ -177,52 +145,49 @@ void undo_write_list()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int undo_write_set_t(struct undow_t *u, int set)
|
R_API int r_io_undo_write_set_t(struct r_io_t *io, struct r_io_undo_w_t *u, int set)
|
||||||
{
|
{
|
||||||
undo_w_lock = 1;
|
io->undo.w_lock = 1;
|
||||||
if (set) {
|
if (set) {
|
||||||
radare_write_at(u->off, u->n, u->len);
|
r_io_write_at(io, u->off, u->n, u->len);
|
||||||
u->set = UNDO_WRITE_SET;
|
u->set = R_TRUE;
|
||||||
} else {
|
} else {
|
||||||
radare_write_at(u->off, u->o, u->len);
|
r_io_write_at(io, u->off, u->o, u->len);
|
||||||
u->set = UNDO_WRITE_UNSET;
|
u->set = R_FALSE;
|
||||||
}
|
}
|
||||||
undo_w_lock = 0;
|
io->undo.w_lock = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void undo_write_set_all(int set)
|
R_API void r_io_undo_write_set_all(struct r_io_t *io, int set)
|
||||||
{
|
{
|
||||||
struct list_head *p;
|
struct list_head *p;
|
||||||
|
|
||||||
if (undo_w_init)
|
if (io->undo.w_init)
|
||||||
list_for_each_prev(p, &(undo_w_list)) {
|
list_for_each_prev(p, &(io->undo.w_list)) {
|
||||||
struct undow_t *u = list_entry(p, struct undow_t, list);
|
struct r_io_undo_w_t *u = list_entry(p, struct r_io_undo_w_t, list);
|
||||||
undo_write_set_t(u, set); //UNDO_WRITE_UNSET);
|
r_io_undo_write_set_t(io, u, set); //UNDO_WRITE_UNSET);
|
||||||
eprintf("%s 0x%08llx\n", set?"redo":"undo", u->off);
|
eprintf("%s 0x%08llx\n", set?"redo":"undo", u->off);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* sets or unsets the writes done */
|
/* sets or unsets the writes done */
|
||||||
/* if ( set == 0 ) unset(n) */
|
/* if ( set == 0 ) unset(n) */
|
||||||
int undo_write_set(int n, int set)
|
R_API int r_io_undo_write_set(struct r_io_t *io, int n, int set)
|
||||||
{
|
{
|
||||||
struct undow_t *u = NULL;
|
struct r_io_undo_w_t *u = NULL;
|
||||||
struct list_head *p;
|
struct list_head *p;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
if (io->undo.w_init) {
|
||||||
if (undo_w_init) {
|
list_for_each_prev(p, &(io->undo.w_list)) {
|
||||||
list_for_each_prev(p, &(undo_w_list)) {
|
|
||||||
if (i++ == n) {
|
if (i++ == n) {
|
||||||
u = list_entry(p, struct undow_t, list);
|
u = list_entry(p, struct r_io_undo_w_t, list);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (u) undo_write_set_t(u, set);
|
if (u) r_io_undo_write_set_t(io, u, set);
|
||||||
else eprintf("invalid undo-write index\n");
|
else eprintf("invalid undo-write index\n");
|
||||||
} else
|
} else eprintf("no writes done\n");
|
||||||
eprintf("no writes done\n");
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ namespace Radare
|
||||||
CUR = 1,
|
CUR = 1,
|
||||||
END = 2,
|
END = 2,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Do the io! :D
|
* Do the io! :D
|
||||||
*/
|
*/
|
||||||
|
@ -41,6 +42,12 @@ namespace Radare
|
||||||
public int close(int fd);
|
public int close(int fd);
|
||||||
public uint64 size(int fd);
|
public uint64 size(int fd);
|
||||||
|
|
||||||
|
/* undo */
|
||||||
|
public void undo_enable(int set);
|
||||||
|
public uint64 undo_seek();
|
||||||
|
public void undo_redo();
|
||||||
|
public void undo_push();
|
||||||
|
|
||||||
/* handle */
|
/* handle */
|
||||||
public struct Handle {
|
public struct Handle {
|
||||||
string name;
|
string name;
|
||||||
|
|
Loading…
Reference in New Issue