mirror of
https://github.com/radareorg/radare2.git
synced 2025-02-03 12:12:06 +00:00
A better way to check if a project has been saved ##projects
* Add a dirty var to RFlag, RAnal and RConfig * Add prj.alwaysprompt * Add R_DIRTY() and R_IS_DIRTY()
This commit is contained in:
parent
6b45040a4b
commit
785e500a7e
@ -139,6 +139,7 @@ R_API RAnal *r_anal_new(void) {
|
||||
r_anal_add (anal, anal_static_plugins[i]);
|
||||
}
|
||||
}
|
||||
R_DIRTY (anal);
|
||||
return anal;
|
||||
}
|
||||
|
||||
@ -380,7 +381,6 @@ R_API ut8 *r_anal_mask(RAnal *anal, int size, const ut8 *data, ut64 at) {
|
||||
}
|
||||
|
||||
r_anal_op_free (op);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -397,6 +397,7 @@ R_API void r_anal_trace_bb(RAnal *anal, ut64 addr) {
|
||||
}
|
||||
}
|
||||
}
|
||||
R_DIRTY (anal);
|
||||
}
|
||||
|
||||
R_API RList* r_anal_get_fcns(RAnal *anal) {
|
||||
@ -553,7 +554,10 @@ R_API bool r_anal_noreturn_add(RAnal *anal, const char *name, ut64 addr) {
|
||||
}
|
||||
tmp_name = fcn ? fcn->name: fi->name;
|
||||
if (fcn) {
|
||||
fcn->is_noreturn = true;
|
||||
if (!fcn->is_noreturn) {
|
||||
fcn->is_noreturn = true;
|
||||
R_DIRTY (anal);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (r_type_func_exist (TDB, tmp_name)) {
|
||||
@ -745,6 +749,7 @@ R_API void r_anal_add_import(RAnal *anal, const char *imp) {
|
||||
if (!cimp) {
|
||||
return;
|
||||
}
|
||||
R_DIRTY (anal);
|
||||
r_list_push (anal->imports, cimp);
|
||||
}
|
||||
|
||||
@ -753,6 +758,7 @@ R_API void r_anal_remove_import(RAnal *anal, const char *imp) {
|
||||
const char *eimp;
|
||||
r_list_foreach (anal->imports, it, eimp) {
|
||||
if (!strcmp (eimp, imp)) {
|
||||
R_DIRTY (anal);
|
||||
r_list_delete (anal->imports, it);
|
||||
return;
|
||||
}
|
||||
@ -760,5 +766,6 @@ R_API void r_anal_remove_import(RAnal *anal, const char *imp) {
|
||||
}
|
||||
|
||||
R_API void r_anal_purge_imports(RAnal *anal) {
|
||||
R_DIRTY(anal);
|
||||
r_list_purge (anal->imports);
|
||||
}
|
||||
|
@ -175,6 +175,7 @@ R_API RAnalVar *r_anal_function_set_var(RAnalFunction *fcn, int delta, char kind
|
||||
free (var->regname);
|
||||
free (var->type);
|
||||
}
|
||||
R_DIRTY (fcn->anal);
|
||||
var->name = strdup (name);
|
||||
var->regname = reg? strdup (reg->name): NULL; // TODO: no strdup here? pool? or not keep regname at all?
|
||||
var->type = strdup (type);
|
||||
@ -193,6 +194,7 @@ R_API bool r_anal_function_set_var_prot(RAnalFunction *fcn, RList *l) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
R_DIRTY (fcn->anal);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -680,6 +682,7 @@ R_API void r_anal_var_remove_access_at(RAnalVar *var, ut64 address) {
|
||||
RPVector *inst_accesses = ht_up_find (var->fcn->inst_vars, (ut64)offset, NULL);
|
||||
r_pvector_remove_data (inst_accesses, var);
|
||||
}
|
||||
R_DIRTY (var->fcn->anal);
|
||||
}
|
||||
|
||||
R_API void r_anal_var_clear_accesses(RAnalVar *var) {
|
||||
@ -697,6 +700,7 @@ R_API void r_anal_var_clear_accesses(RAnalVar *var) {
|
||||
}
|
||||
}
|
||||
r_vector_clear (&var->accesses);
|
||||
R_DIRTY (var->fcn->anal);
|
||||
}
|
||||
|
||||
R_API RAnalVarAccess *r_anal_var_get_access_at(RAnalVar *var, ut64 addr) {
|
||||
|
@ -111,6 +111,7 @@ R_API bool r_anal_xrefs_set(RAnal *anal, ut64 from, ut64 to, const RAnalRefType
|
||||
}
|
||||
setxref (anal->dict_xrefs, to, from, type);
|
||||
setxref (anal->dict_refs, from, to, type);
|
||||
R_DIRTY (anal);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -129,6 +130,7 @@ R_API bool r_anal_xrefs_deln(RAnal *anal, ut64 from, ut64 to, const RAnalRefType
|
||||
ht_up_delete (d, from);
|
||||
}
|
||||
#endif
|
||||
R_DIRTY (anal);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -140,6 +142,7 @@ R_API bool r_anal_xref_del(RAnal *anal, ut64 from, ut64 to) {
|
||||
res |= r_anal_xrefs_deln (anal, from, to, R_ANAL_REF_TYPE_CALL);
|
||||
res |= r_anal_xrefs_deln (anal, from, to, R_ANAL_REF_TYPE_DATA);
|
||||
res |= r_anal_xrefs_deln (anal, from, to, R_ANAL_REF_TYPE_STRING);
|
||||
R_DIRTY (anal);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -397,7 +397,6 @@ R_API RConfigNode* r_config_set(RConfig *cfg, const char *name, const char *valu
|
||||
RConfigNode *node = NULL;
|
||||
char *ov = NULL;
|
||||
ut64 oi;
|
||||
|
||||
r_return_val_if_fail (cfg && cfg->ht, NULL);
|
||||
r_return_val_if_fail (!IS_NULLSTR (name), NULL);
|
||||
|
||||
@ -416,6 +415,7 @@ R_API RConfigNode* r_config_set(RConfig *cfg, const char *name, const char *valu
|
||||
} else {
|
||||
node->value = strdup ("");
|
||||
}
|
||||
R_DIRTY (cfg);
|
||||
if (r_config_node_is_bool (node)) {
|
||||
bool b = r_str_is_true (value);
|
||||
node->i_value = b;
|
||||
@ -504,6 +504,7 @@ R_API RConfigNode* r_config_node_desc(RConfigNode *node, const char *desc) {
|
||||
R_API bool r_config_rm(RConfig *cfg, const char *name) {
|
||||
RConfigNode *node = r_config_node_get (cfg, name);
|
||||
if (node) {
|
||||
R_DIRTY (cfg);
|
||||
ht_pp_delete (cfg->ht, node->name);
|
||||
r_list_delete_data (cfg->nodes, node);
|
||||
return true;
|
||||
@ -535,6 +536,7 @@ R_API RConfigNode* r_config_set_i(RConfig *cfg, const char *name, const ut64 i)
|
||||
char buf[128], *ov = NULL;
|
||||
r_return_val_if_fail (cfg && name, NULL);
|
||||
RConfigNode *node = r_config_node_get (cfg, name);
|
||||
R_DIRTY (cfg);
|
||||
if (node) {
|
||||
if (r_config_node_is_ro (node)) {
|
||||
node = NULL;
|
||||
@ -674,6 +676,7 @@ R_API RConfig* r_config_new(void *user) {
|
||||
cfg->num = NULL;
|
||||
cfg->lock = false;
|
||||
cfg->cb_printf = (void *) printf;
|
||||
R_DIRTY (cfg);
|
||||
return cfg;
|
||||
}
|
||||
|
||||
@ -691,6 +694,7 @@ R_API RConfig* r_config_clone(RConfig *cfg) {
|
||||
}
|
||||
c->lock = cfg->lock;
|
||||
c->cb_printf = cfg->cb_printf;
|
||||
R_DIRTY (c);
|
||||
return c;
|
||||
}
|
||||
|
||||
|
@ -3658,6 +3658,8 @@ R_API int r_core_config_init(RCore *core) {
|
||||
SETBPREF ("prj.zip", "false", "Use ZIP format for project files");
|
||||
SETBPREF ("prj.gpg", "false", "TODO: Encrypt project with GnuPGv2");
|
||||
SETBPREF ("prj.sandbox", "false", "Sandbox r2 while loading project files");
|
||||
SETBPREF ("prj.alwasyprompt", "false", "Even when the project is already\
|
||||
saved, ask the user to save the project when qutting");
|
||||
|
||||
/* cfg */
|
||||
n = SETCB ("cfg.charset", "", &cb_cfgcharset, "Specify encoding to use when printing strings");
|
||||
|
@ -139,6 +139,12 @@ R_API int r_core_project_list(RCore *core, int mode) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
R_API void r_core_project_undirty(RCore *core) {
|
||||
core->config->is_dirty = false;
|
||||
core->anal->is_dirty = false;
|
||||
core->flags->is_dirty = false;
|
||||
}
|
||||
|
||||
R_API int r_core_project_delete(RCore *core, const char *prjfile) {
|
||||
if (r_sandbox_enable (0)) {
|
||||
eprintf ("Cannot delete project in sandbox mode\n");
|
||||
@ -377,6 +383,9 @@ R_API bool r_core_project_open(RCore *core, const char *prj_path) {
|
||||
ret = r_core_project_load (core, prj_name, prj_script);
|
||||
free (prj_name);
|
||||
free (prj_script);
|
||||
if (ret) {
|
||||
r_core_project_undirty(core);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -697,6 +706,7 @@ R_API bool r_core_project_save(RCore *core, const char *prj_name) {
|
||||
}
|
||||
free (script_path);
|
||||
r_config_set (core->config, "prj.name", prj_name);
|
||||
r_core_project_undirty(core);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -709,42 +719,7 @@ R_API char *r_core_project_notes_file(RCore *core, const char *prj_name) {
|
||||
}
|
||||
|
||||
R_API bool r_core_project_is_saved(RCore *core) {
|
||||
bool ret;
|
||||
char *saved_dat, *tmp_dat;
|
||||
char *pd = r_str_newf ("%s" R_SYS_DIR "%s",
|
||||
r_config_get (core->config, "dir.projects"),
|
||||
r_config_get (core->config, "prj.name"));
|
||||
if (!pd) {
|
||||
return false;
|
||||
}
|
||||
char *sp = r_str_newf ("%s" R_SYS_DIR "%s", pd, "rc.r2");
|
||||
if (!sp) {
|
||||
free (pd);
|
||||
return false;
|
||||
}
|
||||
char *tsp = r_str_newf ("%s" R_SYS_DIR "tmp", pd);
|
||||
//horrible code follows:
|
||||
free (pd);
|
||||
if (!tsp) {
|
||||
free (sp);
|
||||
return false;
|
||||
}
|
||||
r_core_project_save_script (core, tsp, R_CORE_PRJ_ALL);
|
||||
saved_dat = r_file_slurp (sp, 0);
|
||||
free (sp);
|
||||
if (!saved_dat) {
|
||||
free (tsp);
|
||||
return false;
|
||||
}
|
||||
//Would be better if I knew how to map files in mem in windows
|
||||
tmp_dat = r_file_slurp (tsp, 0);
|
||||
r_file_rm (tsp);
|
||||
free (tsp);
|
||||
if (!tmp_dat) {
|
||||
return false;
|
||||
}
|
||||
ret = !strcmp (tmp_dat, saved_dat);
|
||||
free (tmp_dat);
|
||||
free (saved_dat);
|
||||
return ret;
|
||||
return !R_IS_DIRTY (core->config)
|
||||
&& !R_IS_DIRTY (core->anal)
|
||||
&& !R_IS_DIRTY (core->flags);
|
||||
}
|
||||
|
@ -94,6 +94,7 @@ static void remove_offsetmap(RFlag *f, RFlagItem *item) {
|
||||
if (r_list_empty (flags->flags)) {
|
||||
r_skiplist_delete (f->by_off, flags);
|
||||
}
|
||||
R_DIRTY (f);
|
||||
}
|
||||
}
|
||||
|
||||
@ -154,6 +155,7 @@ static bool update_flag_item_offset(RFlag *f, RFlagItem *item, ut64 newoff, bool
|
||||
}
|
||||
|
||||
r_list_append (flagsAtOffset->flags, item);
|
||||
R_DIRTY (f);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -176,6 +178,7 @@ static bool update_flag_item_name(RFlag *f, RFlagItem *item, const char *newname
|
||||
: ht_pp_insert (f->ht_name, fname, item);
|
||||
if (res) {
|
||||
set_name (item, fname);
|
||||
R_DIRTY (f);
|
||||
return true;
|
||||
}
|
||||
free (fname);
|
||||
@ -235,6 +238,7 @@ R_API RFlag *r_flag_new(void) {
|
||||
f->ht_name = ht_pp_new (NULL, ht_free_flag, NULL);
|
||||
f->by_off = r_skiplist_new (flag_skiplist_free, flag_skiplist_cmp);
|
||||
new_spaces (f);
|
||||
R_DIRTY (f);
|
||||
return f;
|
||||
}
|
||||
|
||||
@ -719,6 +723,7 @@ R_API RFlagItem *r_flag_set_next(RFlag *f, const char *name, ut64 off, ut32 size
|
||||
RFlagItem *fi = r_flag_set (f, newName, off, size);
|
||||
if (fi) {
|
||||
free (newName);
|
||||
R_DIRTY (f);
|
||||
return fi;
|
||||
}
|
||||
}
|
||||
@ -734,6 +739,7 @@ R_API RFlagItem *r_flag_set_inspace(RFlag *f, const char *space, const char *nam
|
||||
if (space) {
|
||||
r_flag_space_pop (f);
|
||||
}
|
||||
R_DIRTY (f);
|
||||
return fi;
|
||||
}
|
||||
|
||||
@ -833,6 +839,7 @@ R_API bool r_flag_unset(RFlag *f, RFlagItem *item) {
|
||||
r_return_val_if_fail (f && item, false);
|
||||
remove_offsetmap (f, item);
|
||||
ht_pp_delete (f->ht_name, item->name);
|
||||
R_DIRTY (f);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -870,6 +877,7 @@ R_API int r_flag_unset_glob(RFlag *f, const char *glob) {
|
||||
|
||||
struct unset_foreach_t u = { .f = f, .n = 0 };
|
||||
r_flag_foreach_glob (f, glob, unset_foreach, &u);
|
||||
R_DIRTY (f);
|
||||
return u.n;
|
||||
}
|
||||
|
||||
@ -878,6 +886,7 @@ R_API int r_flag_unset_glob(RFlag *f, const char *glob) {
|
||||
R_API bool r_flag_unset_name(RFlag *f, const char *name) {
|
||||
r_return_val_if_fail (f, false);
|
||||
RFlagItem *item = ht_pp_find (f->ht_name, name, NULL);
|
||||
R_DIRTY (f);
|
||||
return item && r_flag_unset (f, item);
|
||||
}
|
||||
|
||||
@ -889,6 +898,7 @@ R_API void r_flag_unset_all(RFlag *f) {
|
||||
r_skiplist_purge (f->by_off);
|
||||
r_spaces_fini (&f->spaces);
|
||||
new_spaces (f);
|
||||
R_DIRTY (f);
|
||||
}
|
||||
|
||||
struct flag_relocate_t {
|
||||
@ -923,7 +933,6 @@ R_API int r_flag_relocate(RFlag *f, ut64 off, ut64 off_mask, ut64 to) {
|
||||
.to = to,
|
||||
.n = 0
|
||||
};
|
||||
|
||||
r_flag_foreach (f, flag_relocate_foreach, &u);
|
||||
return u.n;
|
||||
}
|
||||
|
@ -684,6 +684,7 @@ typedef struct r_anal_t {
|
||||
RStrConstPool constpool;
|
||||
RList *leaddrs;
|
||||
char *pincmd;
|
||||
R_DIRTY_VAR;
|
||||
} RAnal;
|
||||
|
||||
typedef enum r_anal_addr_hint_type_t {
|
||||
@ -2187,7 +2188,8 @@ R_API bool r_anal_global_del(RAnal *anal, ut64 addr);
|
||||
R_API bool r_anal_global_retype(RAnal *anal, ut64 addr, const char *new_type);
|
||||
R_API bool r_anal_global_rename(RAnal *anal, ut64 addr, const char *new_name);
|
||||
R_API const char *r_anal_global_get_type(RAnal *anal, ut64 addr);
|
||||
|
||||
/*return anal->is_dirty and sets it to false*/
|
||||
R_API bool r_anal_is_dirty(RAnal *anal);
|
||||
/* plugin pointers */
|
||||
extern RAnalPlugin r_anal_plugin_null;
|
||||
extern RAnalPlugin r_anal_plugin_6502;
|
||||
|
@ -50,6 +50,8 @@ typedef struct r_config_t {
|
||||
RList *nodes;
|
||||
HtPP *ht;
|
||||
bool lock;
|
||||
/*was the struct modified after the last project save*/
|
||||
R_DIRTY_VAR;
|
||||
} RConfig;
|
||||
|
||||
typedef struct r_config_hold_t {
|
||||
|
@ -714,7 +714,7 @@ R_API bool r_core_project_save_script(RCore *core, const char *file, int opts);
|
||||
R_API bool r_core_project_save(RCore *core, const char *file);
|
||||
R_API char *r_core_project_name(RCore *core, const char *file);
|
||||
R_API char *r_core_project_notes_file(RCore *core, const char *file);
|
||||
|
||||
R_API void r_core_project_undirty(RCore *core);
|
||||
R_API char *r_core_sysenv_begin(RCore *core, const char *cmd);
|
||||
R_API void r_core_sysenv_end(RCore *core, const char *cmd);
|
||||
|
||||
|
@ -59,6 +59,7 @@ typedef struct r_flag_t {
|
||||
PrintfCallback cb_printf;
|
||||
RList *zones;
|
||||
ut64 mask;
|
||||
R_DIRTY_VAR;
|
||||
} RFlag;
|
||||
|
||||
/* compile time dependency */
|
||||
|
@ -86,9 +86,10 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
R_LIB_VERSION_HEADER(r_util);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#define R_DIRTY(x) (x)->is_dirty = true
|
||||
#define R_IS_DIRTY(x) (x)->is_dirty
|
||||
#define R_DIRTY_VAR bool is_dirty
|
||||
#endif
|
||||
|
@ -1458,6 +1458,7 @@ R_API int r_main_radare2(int argc, const char **argv) {
|
||||
r_core_cmd0 (r, "aeip");
|
||||
}
|
||||
}
|
||||
r_core_project_undirty (r);
|
||||
for (;;) {
|
||||
if (!r_core_prompt_loop (r)) {
|
||||
quietLeak = true;
|
||||
@ -1501,7 +1502,7 @@ R_API int r_main_radare2(int argc, const char **argv) {
|
||||
|
||||
const char *prj = r_config_get (r->config, "prj.name");
|
||||
if (R_STR_ISNOTEMPTY (prj)) {
|
||||
if (r_core_project_is_saved (r)) {
|
||||
if (r_core_project_is_saved (r) && !r_config_get_b (r->config, "prj.alwaysprompt")) {
|
||||
break;
|
||||
}
|
||||
if (no_question_save) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user