2011-05-12 18:28:44 +00:00
|
|
|
/* radare - LGPL - Copyright 2007-2011 pancake<nopcode.org> */
|
2009-02-05 21:08:46 +00:00
|
|
|
|
2009-09-08 18:16:52 +00:00
|
|
|
#include <r_io.h>
|
|
|
|
|
2009-02-16 23:09:40 +00:00
|
|
|
#if 0
|
2009-09-08 18:16:52 +00:00
|
|
|
* TODO:
|
|
|
|
* - make path of indirections shortr (io->undo.foo is slow) */
|
2010-05-25 23:42:22 +00:00
|
|
|
* - Plugin changes in write and seeks
|
2009-09-08 18:16:52 +00:00
|
|
|
* - Per-fd history log
|
2009-02-16 23:09:40 +00:00
|
|
|
#endif
|
|
|
|
|
2011-11-16 09:06:34 +00:00
|
|
|
R_API int r_io_undo_init(RIO *io) {
|
2009-09-08 18:16:52 +00:00
|
|
|
io->undo.w_init = 0;
|
2009-09-09 00:35:00 +00:00
|
|
|
io->undo.w_enable = 0;
|
2009-09-08 18:16:52 +00:00
|
|
|
io->undo.idx = 0;
|
|
|
|
io->undo.limit = 0;
|
2009-09-09 00:35:00 +00:00
|
|
|
io->undo.s_enable = 0;
|
|
|
|
io->undo.w_enable = 0;
|
2011-11-15 22:26:45 +00:00
|
|
|
io->undo.w_list = r_list_new ();
|
2009-02-16 23:09:40 +00:00
|
|
|
return R_TRUE;
|
|
|
|
}
|
|
|
|
|
2011-11-16 09:06:34 +00:00
|
|
|
R_API void r_io_undo_enable(RIO *io, int s, int w) {
|
2009-09-09 00:35:00 +00:00
|
|
|
io->undo.s_enable = s;
|
|
|
|
io->undo.w_enable = w;
|
2009-02-16 23:09:40 +00:00
|
|
|
}
|
2009-02-05 21:08:46 +00:00
|
|
|
|
2011-11-16 09:06:34 +00:00
|
|
|
R_API ut64 r_io_sundo_last(RIO *io) {
|
2009-09-09 00:35:00 +00:00
|
|
|
return (io->undo.idx>0)?
|
2010-02-15 21:59:26 +00:00
|
|
|
io->undo.seek[io->undo.idx-2] : io->off;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
|
|
|
|
2011-11-16 09:06:34 +00:00
|
|
|
R_API int r_io_sundo(RIO *io) {
|
2011-06-05 18:36:22 +00:00
|
|
|
if (io->undo.idx == io->undo.limit)
|
|
|
|
r_io_sundo_push (io);
|
2010-05-19 00:39:01 +00:00
|
|
|
io->undo.idx--;
|
|
|
|
if (io->undo.idx<0)
|
|
|
|
return io->undo.idx = 0;
|
|
|
|
io->off = io->undo.seek[io->undo.idx-1];
|
|
|
|
return R_TRUE;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
|
|
|
|
2011-11-16 09:06:34 +00:00
|
|
|
R_API int r_io_sundo_redo(RIO *io) {
|
2009-09-08 18:16:52 +00:00
|
|
|
if (io->undo.idx<io->undo.limit) {
|
2011-06-05 18:36:22 +00:00
|
|
|
io->undo.idx += 1;
|
2011-11-16 09:06:34 +00:00
|
|
|
if (io->undo.idx<R_IO_UNDOS) {
|
|
|
|
io->off = io->undo.seek[io->undo.idx-1];
|
|
|
|
return R_TRUE;
|
|
|
|
r_io_sundo (io);
|
|
|
|
}
|
|
|
|
io->undo.idx -= 1;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
2010-05-19 00:39:01 +00:00
|
|
|
return R_FALSE;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
|
|
|
|
2010-07-12 23:00:36 +00:00
|
|
|
R_API void r_io_sundo_push(RIO *io) {
|
2011-11-16 09:06:34 +00:00
|
|
|
ut64 off = io->off;
|
2009-09-09 00:35:00 +00:00
|
|
|
if (!io->undo.s_enable)
|
|
|
|
return;
|
2011-11-16 09:06:34 +00:00
|
|
|
//if (io->undo.seek[io->undo.idx-1] == off) return;
|
2010-07-12 23:00:36 +00:00
|
|
|
io->undo.seek[io->undo.idx] = off;
|
2011-05-21 23:16:12 +00:00
|
|
|
io->undo.idx++;
|
|
|
|
if (io->undo.idx==R_IO_UNDOS-1) {
|
2010-05-19 00:39:01 +00:00
|
|
|
io->undo.idx--;
|
2011-07-15 16:13:00 +00:00
|
|
|
//eprintf ("undo limit reached\n");
|
2011-05-21 23:16:12 +00:00
|
|
|
}
|
2011-06-05 18:36:22 +00:00
|
|
|
//if (io->undo.limit<io->undo.idx)
|
2009-09-08 18:16:52 +00:00
|
|
|
io->undo.limit = io->undo.idx;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
|
|
|
|
2011-11-16 09:06:34 +00:00
|
|
|
R_API void r_io_sundo_reset(RIO *io) {
|
2009-09-08 18:16:52 +00:00
|
|
|
io->undo.idx = 0;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
|
|
|
|
2011-11-16 09:06:34 +00:00
|
|
|
R_API void r_io_sundo_list(RIO *io) {
|
2009-02-05 21:08:46 +00:00
|
|
|
int i;
|
2009-09-08 18:16:52 +00:00
|
|
|
if (io->undo.idx>0) {
|
2010-05-19 00:39:01 +00:00
|
|
|
io->printf ("f undo_idx @ %d\n", io->undo.idx);
|
2011-11-16 09:06:34 +00:00
|
|
|
for (i=io->undo.idx; i!=0; i--)
|
2010-05-19 00:39:01 +00:00
|
|
|
io->printf ("f undo_%d @ 0x%"PFMT64x"\n",
|
2011-05-21 23:16:12 +00:00
|
|
|
io->undo.idx-i, io->undo.seek[i-1]);
|
2009-09-08 18:16:52 +00:00
|
|
|
} else eprintf("-no seeks done-\n");
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
|
|
|
|
2009-09-09 00:35:00 +00:00
|
|
|
/* undo writez */
|
|
|
|
|
2011-11-16 09:06:34 +00:00
|
|
|
R_API void r_io_wundo_new(RIO *io, ut64 off, const ut8 *data, int len) {
|
2009-09-09 00:35:00 +00:00
|
|
|
struct r_io_undo_w_t *uw;
|
|
|
|
if (!io->undo.w_enable)
|
2009-02-05 21:08:46 +00:00
|
|
|
return;
|
2009-09-09 00:35:00 +00:00
|
|
|
/* undo write changes */
|
2011-11-16 09:06:34 +00:00
|
|
|
uw = R_NEW (RIOUndoWrite);
|
2011-05-21 23:16:12 +00:00
|
|
|
if (!uw) return;
|
2009-09-08 18:16:52 +00:00
|
|
|
uw->set = R_TRUE;
|
2009-02-05 21:08:46 +00:00
|
|
|
uw->off = off;
|
|
|
|
uw->len = len;
|
2011-11-16 09:06:34 +00:00
|
|
|
uw->n = (ut8*) malloc (len);
|
2009-02-05 21:08:46 +00:00
|
|
|
memcpy(uw->n, data, len);
|
2011-11-16 09:06:34 +00:00
|
|
|
uw->o = (ut8*) malloc (len);
|
2009-09-08 18:16:52 +00:00
|
|
|
r_io_read_at(io, off, uw->o, len);
|
2011-11-15 22:26:45 +00:00
|
|
|
r_list_append (io->undo.w_list, uw);
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
|
|
|
|
2011-11-16 09:06:34 +00:00
|
|
|
R_API void r_io_wundo_clear(RIO *io) {
|
2009-02-05 21:08:46 +00:00
|
|
|
// XXX memory leak
|
2011-11-15 22:26:45 +00:00
|
|
|
io->undo.w_list = r_list_new ();
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
|
|
|
|
2009-09-09 00:35:00 +00:00
|
|
|
// rename to r_io_undo_length ?
|
2011-11-16 09:06:34 +00:00
|
|
|
R_API int r_io_wundo_size(RIO *io) {
|
2011-11-15 22:26:45 +00:00
|
|
|
RListIter *iter;
|
2011-11-16 09:06:34 +00:00
|
|
|
RIOUndoWrite *uw;
|
2009-02-05 21:08:46 +00:00
|
|
|
int i = 0;
|
2011-11-15 22:26:45 +00:00
|
|
|
|
2009-09-08 18:16:52 +00:00
|
|
|
if (io->undo.w_init)
|
2011-11-15 22:26:45 +00:00
|
|
|
r_list_foreach (io->undo.w_list, iter, uw)
|
2009-09-09 00:35:00 +00:00
|
|
|
i++;
|
2009-02-05 21:08:46 +00:00
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
2009-09-08 18:16:52 +00:00
|
|
|
// TODO: Deprecate or so? iterators must be language-wide, but helpers are useful
|
2011-11-16 09:06:34 +00:00
|
|
|
R_API void r_io_wundo_list(RIO *io) {
|
2009-02-05 21:08:46 +00:00
|
|
|
#define BW 8 /* byte wrap */
|
2011-11-15 22:26:45 +00:00
|
|
|
RListIter *iter;
|
2011-11-16 09:06:34 +00:00
|
|
|
RIOUndoWrite *u;
|
2009-02-05 21:08:46 +00:00
|
|
|
int i = 0, j, len;
|
|
|
|
|
2009-09-08 18:16:52 +00:00
|
|
|
if (io->undo.w_init)
|
2011-11-16 09:06:34 +00:00
|
|
|
r_list_foreach (io->undo.w_list, iter, u) {
|
2010-05-19 00:39:01 +00:00
|
|
|
io->printf ("%02d %c %d %08"PFMT64x": ", i, u->set?'+':'-', u->len, u->off);
|
2009-02-05 21:08:46 +00:00
|
|
|
len = (u->len>BW)?BW:u->len;
|
2011-11-16 09:06:34 +00:00
|
|
|
for (j=0;j<len;j++) io->printf ("%02x ", u->o[j]);
|
2010-05-19 00:39:01 +00:00
|
|
|
if (len == BW) io->printf (".. ");
|
|
|
|
io->printf ("=> ");
|
2011-11-16 09:06:34 +00:00
|
|
|
for (j=0;j<len;j++) io->printf ("%02x ", u->n[j]);
|
2010-05-19 00:39:01 +00:00
|
|
|
if (len == BW) io->printf (".. ");
|
|
|
|
io->printf ("\n");
|
2009-02-05 21:08:46 +00:00
|
|
|
i++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-11-16 09:06:34 +00:00
|
|
|
R_API int r_io_wundo_apply(RIO *io, struct r_io_undo_w_t *u, int set) {
|
2009-09-09 00:35:00 +00:00
|
|
|
int orig = io->undo.w_enable;
|
|
|
|
io->undo.w_enable = 0;
|
2009-02-05 21:08:46 +00:00
|
|
|
if (set) {
|
2011-11-16 09:06:34 +00:00
|
|
|
r_io_write_at (io, u->off, u->n, u->len);
|
2009-09-08 18:16:52 +00:00
|
|
|
u->set = R_TRUE;
|
2009-02-05 21:08:46 +00:00
|
|
|
} else {
|
2011-11-16 09:06:34 +00:00
|
|
|
r_io_write_at (io, u->off, u->o, u->len);
|
2009-09-08 18:16:52 +00:00
|
|
|
u->set = R_FALSE;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
2009-09-09 00:35:00 +00:00
|
|
|
io->undo.w_enable = orig;
|
2009-02-05 21:08:46 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-11-16 09:06:34 +00:00
|
|
|
R_API void r_io_wundo_apply_all(RIO *io, int set) {
|
2011-11-15 22:26:45 +00:00
|
|
|
RListIter *iter;
|
2011-11-16 09:06:34 +00:00
|
|
|
RIOUndoWrite *u;
|
2009-02-05 21:08:46 +00:00
|
|
|
|
2011-11-15 22:26:45 +00:00
|
|
|
r_list_foreach_prev (io->undo.w_list, iter, u) {
|
2010-05-19 00:39:01 +00:00
|
|
|
r_io_wundo_apply (io, u, set); //UNDO_WRITE_UNSET);
|
|
|
|
eprintf ("%s 0x%08"PFMT64x"\n", set?"redo":"undo", u->off);
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* sets or unsets the writes done */
|
|
|
|
/* if ( set == 0 ) unset(n) */
|
2011-11-16 09:06:34 +00:00
|
|
|
R_API int r_io_wundo_set(RIO *io, int n, int set) {
|
2011-11-15 22:26:45 +00:00
|
|
|
RListIter *iter;
|
2011-11-16 09:06:34 +00:00
|
|
|
RIOUndoWrite *u = NULL;
|
2009-02-05 21:08:46 +00:00
|
|
|
int i = 0;
|
2009-09-08 18:16:52 +00:00
|
|
|
if (io->undo.w_init) {
|
2011-11-16 09:06:34 +00:00
|
|
|
r_list_foreach_prev (io->undo.w_list, iter, u)
|
|
|
|
if (i++ == n)
|
2009-02-05 21:08:46 +00:00
|
|
|
break;
|
2011-11-16 09:06:34 +00:00
|
|
|
if (u) { // wtf?
|
|
|
|
r_io_wundo_apply (io, u, set);
|
2010-05-19 00:39:01 +00:00
|
|
|
return R_TRUE;
|
2011-11-16 09:06:34 +00:00
|
|
|
}
|
|
|
|
eprintf ("invalid undo-write index\n");
|
2010-05-19 00:39:01 +00:00
|
|
|
} else eprintf ("no writes done\n");
|
|
|
|
return R_FALSE;
|
2009-02-05 21:08:46 +00:00
|
|
|
}
|