Here's what I've got so far. I've tested the different usages on some
small files of random data (and the multibyte text I was working with
originally), but far from extensively.
I've added a function r_slide to perform the shifting up or down after
the inserted/deleted region. My intention is that this could then be
used by file.insert, when implemented, or another "resize" option that
only moves the bytes around between seek and end-of-block (where the
blocks might be memory pages, or file sections).
Those are something I might look into next, but I thought I'd check I'm
not going about this all the wrong way.
Some of my concerns with the attached patch:
* should the adjustment to core->file->size, and reloading the buffer
(where appropriate) be moved inside a file/io-specific resize() method?
* have I hooked the command up correctly? The way the other commands
use r_cmd_add looks quite straightforward and it seems to work for me,
but there are other bits I don't know if I should touch, such as the
radare_argv array.
Glyn
diff -r bb5eb361dd42 libr/core/cmd.c
--- a/libr/core/cmd.c Tue Jan 25 16:29:59 2011 +0100
+++ b/libr/core/cmd.c Tue Jan 25 19:09:40 2011 +0000
@@ -1417,6 +1417,7 @@
" p?[len] ; print current block with format and
length\n"
" V[vcmds] ; enter visual mode (vcmds=visualvisual
keystrokes)\n"
" w[mode] [arg] ; multiple write operations\n"
+ " r[+- ][len] ; resize file\n"
" x [len] ; alias for 'px' (print hexadecimal)\n"
" y [len] [off] ; yank/paste bytes from/to memory\n"
" ? [expr] ; help or evaluate math expression\n"
@@ -2764,6 +2765,80 @@
return 0;
}
+/* moves bytes up (+) or down (-) within the specified range */
+R_API int r_slide(RCore *core, ut64 start, ut64 end, st64 move)
+{
+ ut64 rest,size;
+ ut8 *buf;
+
+ size=r_num_abs(move);
+ if ((end-start) < size ) return R_FALSE;
+
+ rest=(end-start) - size;
+ buf = malloc (rest);
+ if (!buf) return R_FALSE;
+
+ if (move<0) {
+ r_core_read_at(core, end-rest, buf, rest);
+ r_core_write_at(core, start, buf, rest);
+ } else {
+ r_core_read_at(core, start, buf, rest);
+ r_core_write_at(core, end-rest, buf, rest);
+ }
+
+ free(buf);
+ return R_TRUE;
+}
+
+static int cmd_resize(void *data, const char *input) {
+ RCore *core = (RCore *)data;
+ st64 delta=0;
+ int grow;
+ ut64 oldsize,newsize;
+
+ oldsize = core->file->size;
+
+ switch (input[0]) {
+ case ' ':
+ newsize = r_num_math(core->num, input+1);
+ break;
+ case '+':
+ case '-':
+ delta = (st64)r_num_math(NULL, input);
+ newsize = oldsize + delta;
+ break;
+ case '?':
+ default:
+ r_cons_printf (
+ "Usage: r[ size|+insert|-remove]\n"
+ " r size set filesize to size, extending or
truncating\n"
+ " r-num remove num bytes, move following data down\n"
+ " r+num insert num bytes, move following data up\n");
+ return R_TRUE;
+ }
+
+ grow = (newsize > oldsize);
+
+ if (grow) {
+ r_io_resize (core->io, newsize);
+ core->file->size = newsize;
+ }
+
+ if (delta && core->offset < newsize)
+ r_slide (core, core->offset, grow?newsize:oldsize, delta);
+
+ if (!grow) {
+ r_io_resize (core->io, newsize);
+ core->file->size = newsize;
+ }
+
+ if (newsize < core->offset+core->blocksize ||
+ oldsize < core->offset+core->blocksize)
+ r_core_block_read (core, 0);
+
+ return R_TRUE;
+}
+
static const char *cmdhit = NULL;
static int __cb_hit(RSearchKeyword *kw, void *user, ut64 addr) {
RCore *core = (RCore *)user;
@@ -4296,6 +4371,7 @@
r_cmd_add (core->cmd, "Code", "code metadata", &cmd_meta);
r_cmd_add (core->cmd, "Project", "project", &cmd_project);
r_cmd_add (core->cmd, "open", "open or map file", &cmd_open);
+ r_cmd_add (core->cmd, "resize", "change file size", &cmd_resize);
r_cmd_add (core->cmd, "yank", "yank bytes", &cmd_yank);
r_cmd_add (core->cmd, "Visual", "enter visual mode", &cmd_visual);
r_cmd_add (core->cmd, "!", "run system command", &cmd_system);
_______________________________________________
radare mailing list
[email protected]
http://lists.nopcode.org/listinfo.cgi/radare-nopcode.org