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

Reply via email to