diff --git a/binr/radare2/radare2.c b/binr/radare2/radare2.c index 40fef1dfee..2483c04dcf 100644 --- a/binr/radare2/radare2.c +++ b/binr/radare2/radare2.c @@ -612,10 +612,18 @@ int main(int argc, char **argv, char **envp) { r.num->value = 0; if (patchfile) { - r_core_patch (&r, patchfile); - } else { + char *data = r_file_slurp (patchfile, NULL); + if (data) { + r_core_patch (&r, data); + r_core_seek (&r, 0, 1); + free (data); + } else eprintf ("Cannot open '%s'\n", patchfile); + } + if ((patchfile && !quiet) || !patchfile) { if (zerosep) r_cons_zero (); + if (seek != UT64_MAX) + r_core_seek (&r, seek, 1); for (;;) { r.zerosep = zerosep; #if USE_THREADS diff --git a/libr/core/cmd_write.c b/libr/core/cmd_write.c index cfc7896a73..daeac235e3 100644 --- a/libr/core/cmd_write.c +++ b/libr/core/cmd_write.c @@ -215,15 +215,16 @@ static int cmd_write(void *data, const char *input) { const char *tmpfile = ".tmp"; char *out = r_core_editor (core, NULL); if (out) { - // XXX hacky .. patch should support str, not only file - r_file_dump (tmpfile, (ut8*)out, strlen (out)); - r_core_patch (core, tmpfile); - r_file_rm (tmpfile); + r_core_patch (core, out); free (out); } } else { if (input[1]==' ' && input[2]) { - r_core_patch (core, input+2); + char *data = r_file_slurp (input+2, NULL); + if (data) { + r_core_patch (core, data); + free (data); + } } else { eprintf ("Usage: wp [-|r2patch-file]\n" "TODO: rapatch format documentation here\n"); diff --git a/libr/core/patch.c b/libr/core/patch.c index 8afd5dc1fd..36fe226b65 100644 --- a/libr/core/patch.c +++ b/libr/core/patch.c @@ -2,88 +2,110 @@ #include -R_API int r_core_patch (RCore *core, const char *patch) { - char *p, *p2, *q, str[200], tmp[64]; - ut64 noff = 0LL; - FILE *fd = r_sandbox_fopen (patch, "r"); - if (fd==NULL) { - eprintf ("Cannot open patch file\n"); - return 1; +R_API int r_core_patch_line (RCore *core, char *str) { + char *p, *q; + p = strchr (str+1, ' '); + if (!p) + return 0; + *p = 0; + for (++p; *p==' '; p++); // XXX: skipsspaces here + + switch (*p) { + case '"': + q = strchr (p+1,'"'); + if (q) *q = 0; + r_core_cmdf (core, "s %s", str); + r_core_cmdf (core, "\"w %s\"", p+1); + break; + case ':': + r_core_cmdf (core, "s %s", str); + r_core_cmdf (core, "wa %s", p); + break; + default: + r_core_cmdf (core, "s %s", str); + r_core_cmdf (core, "wx %s", p); + break; } + return 1; +} - while (!feof (fd)) { - fgets (str, sizeof (str), fd); - if (*str=='#' || *str=='\n' || *str=='\r') - continue; - if (*str==':') { - r_core_cmd0 (core, str+1); - continue; - } - if (*str=='.' || *str=='!') { - r_core_cmd0 (core, str); - continue; - } - p = strchr (str+1, ' '); - if (!p) - continue; - *p = 0; - for (++p; *p==' '; p++); // XXX: skipsspaces here - switch (*p) { - case '{': { - char *s, *off = strdup (str); - RBuffer *b = r_buf_new (); - - while (!feof (fd)) { - fgets (str, sizeof (str), fd); - if (*str=='}') - break; - if ((q=strstr (str, "${"))) { - char *end = strchr (q+2,'}'); - if (end) { - *q = *end = 0; - noff = r_num_math (core->num, q+2); - r_buf_append_bytes (b, (const ut8*)str, strlen (str)); - snprintf (tmp, sizeof (tmp), "0x%08"PFMT64x, noff); - r_buf_append_bytes (b, (const ut8*)tmp, strlen (tmp)); - r_buf_append_bytes (b, (const ut8*)end+1, strlen (end+1)); - } - } else r_buf_append_bytes (b, (const ut8*)str, strlen (str)); - } +R_API int r_core_patch (RCore *core, const char *patch) { + char *p, *p0, *str; + ut64 noff = 0LL; - s = r_buf_to_string (b); - r_egg_load (core->egg, s, 0); - free (s); - - r_egg_compile (core->egg); - r_egg_assemble (core->egg); + p = p0 = str = strdup (patch); + if (!p) + return 0; + for (; ; p++) { + /* read until newline */ + if (!*p || *p=='\n') *p++ = 0; else continue; - r_buf_free (b); - b = r_egg_get_bin (core->egg); - - if (strcmp (off, "+")) - noff = r_num_math (core->num, off); - r_core_write_at (core, noff, b->buf, b->length); - noff += b->length; - r_buf_free (b); - free (off); - } - break; - case '"': - p2 = strchr (p+1,'"'); - if (p2) *p2=0; - r_core_cmdf (core, "s %s", str); - r_core_cmdf (core, "\"w %s\"", p+1); + switch (*str) { + case '#': + case '\n': + case '\r': + case '\0': break; case ':': - r_core_cmdf (core, "s %s", str); - r_core_cmdf (core, "wa %s", p); + r_core_cmd0 (core, str+1); break; + case '.': + case '!': + r_core_cmd0 (core, str); + break; + case '{': { + char tmp[128]; + char *s, *q, *off = strdup (str); + RBuffer *b = r_buf_new (); + + str = p; + for (;;) { + if (*p=='\n') { + *p++ = 0; + } else continue; + if (*str=='}') + break; + if ((q=strstr (str, "${"))) { + char *end = strchr (q+2,'}'); + if (end) { + *q = *end = 0; + noff = r_num_math (core->num, q+2); + r_buf_append_bytes (b, (const ut8*)str, strlen (str)); + snprintf (tmp, sizeof (tmp), "0x%08"PFMT64x, noff); + r_buf_append_bytes (b, (const ut8*)tmp, strlen (tmp)); + r_buf_append_bytes (b, (const ut8*)end+1, strlen (end+1)); + } + } else r_buf_append_bytes (b, (const ut8*)str, strlen (str)); + str = p; + } + + s = r_buf_to_string (b); + r_egg_load (core->egg, s, 0); + free (s); + + r_egg_compile (core->egg); + r_egg_assemble (core->egg); + + r_buf_free (b); + b = r_egg_get_bin (core->egg); + + if (strcmp (off, "+")) + noff = r_num_math (core->num, off); + r_core_write_at (core, noff, b->buf, b->length); + noff += b->length; + r_buf_free (b); + free (off); + } + break; default: - r_core_cmdf (core, "s %s", str); - r_core_cmdf (core, "wx %s", p); + r_core_patch_line (core, str); break; } + if (!*p) break; + str = p; } - fclose (fd); +// eprintf ("%d\n", *p); +// eprintf ("Missing newline\n"); + free (p0); return 0; }