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:
RHL120 2022-01-25 09:39:15 +00:00 committed by GitHub
parent 6b45040a4b
commit 785e500a7e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 58 additions and 47 deletions

View File

@ -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);
}

View File

@ -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) {

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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");

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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 {

View File

@ -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);

View File

@ -59,6 +59,7 @@ typedef struct r_flag_t {
PrintfCallback cb_printf;
RList *zones;
ut64 mask;
R_DIRTY_VAR;
} RFlag;
/* compile time dependency */

View File

@ -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

View File

@ -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) {