* 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
|
||||
|
||||
<{include libr/TODO}>
|
||||
|
||||
|
||||
* correct result (R_TRUFAE), but with warnings (implement r_errno and r_errstr in r_util?)
|
||||
- Quantic computation ftw \o/
|
||||
* r_cmd must provide a nesting char table indexing for commands
|
||||
|
|
|
@ -4,18 +4,14 @@
|
|||
#include "r_types.h"
|
||||
#include "list.h"
|
||||
|
||||
#define R_IO_READ 0
|
||||
#define R_IO_WRITE 1
|
||||
#define R_IO_EXEC 4
|
||||
#define R_IO_READ 4
|
||||
#define R_IO_WRITE 2
|
||||
#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
|
||||
// DEPRECATE ??
|
||||
#define R_IO_RW R_IO_READ|R_IO_WRITE
|
||||
|
@ -26,9 +22,6 @@ enum {
|
|||
|
||||
#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
|
||||
struct r_io_map_t {
|
||||
|
@ -43,13 +36,25 @@ struct r_io_map_t {
|
|||
/* stores write and seek changes */
|
||||
#define R_IO_UNDOS 64
|
||||
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_lock;
|
||||
/* seek stuff */
|
||||
ut64 seek[R_IO_UNDOS];
|
||||
int fd[R_IO_UNDOS];
|
||||
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 {
|
||||
|
@ -65,6 +70,7 @@ struct r_io_t {
|
|||
ut8 *write_mask_buf;
|
||||
int write_mask_len;
|
||||
struct r_io_handle_t *plugin;
|
||||
struct r_io_undo_t undo;
|
||||
struct list_head io_list;
|
||||
ut64 last_align;
|
||||
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 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);
|
||||
|
||||
/* 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
|
||||
#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)
|
||||
|
|
|
@ -9,7 +9,7 @@ STATIC_OBJS=
|
|||
include ../config.mk
|
||||
include ${STATIC_IO_PLUGINS}
|
||||
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:
|
||||
@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;
|
||||
}
|
||||
|
||||
#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
|
||||
|
||||
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)
|
||||
{
|
||||
io->cached = 0; // IO cached
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
#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 <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)
|
||||
{
|
||||
io->write_mask_fd = -1;
|
||||
io->last_align = 0;
|
||||
io->redirect = NULL;
|
||||
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_map_init(io);
|
||||
r_io_section_init(io);
|
||||
r_io_handle_init(io);
|
||||
r_io_desc_init(io);
|
||||
r_io_undo_init(&io->undo);
|
||||
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)
|
||||
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) {
|
||||
r_io_set_fd(io, fd);
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
R_API int r_io_read(struct r_io_t *io, ut8 *buf, int len)
|
||||
{
|
||||
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
|
||||
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)
|
||||
{
|
||||
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));
|
||||
}
|
||||
|
||||
|
|
205
libr/io/undo.c
205
libr/io/undo.c
|
@ -1,170 +1,138 @@
|
|||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
/* radare - LGPL - Copyright 2007-2009 pancake<nopcode.org> */
|
||||
|
||||
#include "main.h"
|
||||
#include "radare.h"
|
||||
#include "list.h"
|
||||
#include "undo.h"
|
||||
#include <r_io.h>
|
||||
|
||||
#define cons_printf printf
|
||||
#define cons_newline() printf("\n");
|
||||
|
||||
#if 0
|
||||
* Handle changes in write and seeks
|
||||
* Per-fd history log
|
||||
* TODO:
|
||||
* - make path of indirections shortr (io->undo.foo is slow) */
|
||||
* - Handle changes in write and seeks
|
||||
* - Per-fd history log
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
/* 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)
|
||||
R_API int r_io_undo_init(struct r_io_t *io)
|
||||
{
|
||||
u->undo_w_init = 0;
|
||||
u->undo_w_lock = 0;
|
||||
u->undos_idx = 0;
|
||||
u->undos_lim = 0;
|
||||
io->undo.w_init = 0;
|
||||
io->undo.w_lock = 0;
|
||||
io->undo.idx = 0;
|
||||
io->undo.limit = 0;
|
||||
io->undo.enable = 0;
|
||||
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 config.seek;
|
||||
return undos[undos_idx-2];
|
||||
return (io->undo.idx)?
|
||||
io->undo.seek[io->undo.idx-2] : io->seek;
|
||||
}
|
||||
|
||||
void undo_seek()
|
||||
R_API void r_io_undo_seek(struct r_io_t *io)
|
||||
{
|
||||
if (--undos_idx<0)
|
||||
undos_idx = 0;
|
||||
else config.seek = undos[undos_idx-1];
|
||||
if (--io->undo.idx<0)
|
||||
io->undo.idx = 0;
|
||||
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) {
|
||||
undos_idx+=2;
|
||||
undo_seek();
|
||||
if (io->undo.idx<io->undo.limit) {
|
||||
io->undo.idx += 2;
|
||||
r_io_undo_seek(io);
|
||||
}
|
||||
}
|
||||
|
||||
void undo_push()
|
||||
R_API void r_io_undo_push(struct r_io_t *io)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (undos[undos_idx-1] == config.seek)
|
||||
if (io->undo.seek[io->undo.idx-1] == io->seek)
|
||||
return;
|
||||
|
||||
undos[undos_idx] = config.seek;
|
||||
if (undos_idx==UNDOS-1) {
|
||||
for(i=1;i<UNDOS;i++)
|
||||
undos[i-1] = undos[i];
|
||||
} else
|
||||
undos_idx++;
|
||||
io->undo.seek[io->undo.idx] = io->seek;
|
||||
if (io->undo.idx==R_IO_UNDOS-1) {
|
||||
for(i=1;i<R_IO_UNDOS;i++)
|
||||
io->undo.seek[i-1] = io->undo.seek[i];
|
||||
} else io->undo.idx++;
|
||||
|
||||
if (undos_lim<undos_idx)
|
||||
undos_lim = undos_idx;
|
||||
if (io->undo.limit<io->undo.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;
|
||||
if (undos_idx<1)
|
||||
eprintf("-no seeks done-\n");
|
||||
else {
|
||||
cons_printf("f undo_idx @ %d\n", undos_idx);
|
||||
for(i=undos_idx-1;i!=0;i--)
|
||||
cons_printf("f undo_%d @ 0x%llx\n", undos_idx-1-i, undos[i-1]);
|
||||
}
|
||||
if (io->undo.idx>0) {
|
||||
cons_printf("f undo_idx @ %d\n", io->undo.idx);
|
||||
for(i=io->undo.idx-1;i!=0;i--)
|
||||
cons_printf("f undo_%d @ 0x%llx\n",
|
||||
io->undo.idx-1-i, io->undo.seek[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;
|
||||
|
||||
if (undo_w_lock)
|
||||
return;
|
||||
|
||||
if (!undo_w_init) {
|
||||
undo_w_init = 1;
|
||||
INIT_LIST_HEAD(&(undo_w_list));
|
||||
if (!io->undo.w_init) {
|
||||
io->undo.w_init = 1;
|
||||
INIT_LIST_HEAD(&(io->undo.w_list));
|
||||
}
|
||||
|
||||
/* undo changes */
|
||||
uw->set = UNDO_WRITE_SET;
|
||||
uw->set = R_TRUE;
|
||||
uw->off = off;
|
||||
uw->len = len;
|
||||
uw->n = (ut8*) malloc(len);
|
||||
memcpy(uw->n, data, len);
|
||||
uw->o = (ut8*) malloc(len);
|
||||
radare_read_at(off, uw->o, len);
|
||||
list_add_tail(&(uw->list), &(undo_w_list));
|
||||
r_io_read_at(io, off, uw->o, len);
|
||||
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
|
||||
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;
|
||||
int i = 0;
|
||||
|
||||
if (undo_w_init)
|
||||
list_for_each_prev(p, &(undo_w_list)) {
|
||||
if (io->undo.w_init)
|
||||
list_for_each_prev(p, &(io->undo.w_list)) {
|
||||
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 */
|
||||
struct list_head *p;
|
||||
int i = 0, j, len;
|
||||
|
||||
if (undo_w_init)
|
||||
list_for_each_prev(p, &(undo_w_list)) {
|
||||
struct undow_t *u = list_entry(p, struct undow_t, list);
|
||||
if (io->undo.w_init)
|
||||
list_for_each_prev(p, &(io->undo.w_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);
|
||||
len = (u->len>BW)?BW:u->len;
|
||||
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) {
|
||||
radare_write_at(u->off, u->n, u->len);
|
||||
u->set = UNDO_WRITE_SET;
|
||||
r_io_write_at(io, u->off, u->n, u->len);
|
||||
u->set = R_TRUE;
|
||||
} else {
|
||||
radare_write_at(u->off, u->o, u->len);
|
||||
u->set = UNDO_WRITE_UNSET;
|
||||
r_io_write_at(io, u->off, u->o, u->len);
|
||||
u->set = R_FALSE;
|
||||
}
|
||||
undo_w_lock = 0;
|
||||
io->undo.w_lock = 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;
|
||||
|
||||
if (undo_w_init)
|
||||
list_for_each_prev(p, &(undo_w_list)) {
|
||||
struct undow_t *u = list_entry(p, struct undow_t, list);
|
||||
undo_write_set_t(u, set); //UNDO_WRITE_UNSET);
|
||||
if (io->undo.w_init)
|
||||
list_for_each_prev(p, &(io->undo.w_list)) {
|
||||
struct r_io_undo_w_t *u = list_entry(p, struct r_io_undo_w_t, list);
|
||||
r_io_undo_write_set_t(io, u, set); //UNDO_WRITE_UNSET);
|
||||
eprintf("%s 0x%08llx\n", set?"redo":"undo", u->off);
|
||||
}
|
||||
}
|
||||
|
||||
/* sets or unsets the writes done */
|
||||
/* 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;
|
||||
int i = 0;
|
||||
|
||||
if (undo_w_init) {
|
||||
list_for_each_prev(p, &(undo_w_list)) {
|
||||
if (io->undo.w_init) {
|
||||
list_for_each_prev(p, &(io->undo.w_list)) {
|
||||
if (i++ == n) {
|
||||
u = list_entry(p, struct undow_t, list);
|
||||
u = list_entry(p, struct r_io_undo_w_t, list);
|
||||
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("no writes done\n");
|
||||
|
||||
} else eprintf("no writes done\n");
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ namespace Radare
|
|||
CUR = 1,
|
||||
END = 2,
|
||||
}
|
||||
|
||||
/**
|
||||
* Do the io! :D
|
||||
*/
|
||||
|
@ -41,6 +42,12 @@ namespace Radare
|
|||
public int close(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 */
|
||||
public struct Handle {
|
||||
string name;
|
||||
|
|
Loading…
Reference in New Issue