* unify implementaions of stealing of dump directory from report-gtk and report-cli
Signed-off-by: Jakub Filak <[email protected]> --- src/cli/cli.c | 28 ++------- src/gui-wizard-gtk/wizard.c | 121 +++++++++++++++----------------------- src/include/internal_libreport.h | 11 ++++ src/lib/steal_directory.c | 42 +++++++++++++ 4 files changed, 106 insertions(+), 96 deletions(-) diff --git a/src/cli/cli.c b/src/cli/cli.c index 0f38734..66ebbe2 100644 --- a/src/cli/cli.c +++ b/src/cli/cli.c @@ -47,7 +47,6 @@ int main(int argc, char** argv) textdomain(PACKAGE); #endif - GList *D_list = NULL; const char *event_name = NULL; const char *pfx = ""; @@ -124,12 +123,6 @@ int main(int argc, char** argv) char *dump_dir_name = argv[0]; bool always = (opts & OPT_y); - if (!D_list) - { - D_list = g_list_append(D_list, concat_path_file(g_get_user_cache_dir(), "abrt/spool")); - D_list = g_list_append(D_list, (void*)DEBUG_DUMPS_DIR); - } - /* Get settings */ load_event_config_data(); @@ -191,26 +184,17 @@ int main(int argc, char** argv) } case OPT_report: { - struct dump_dir *dd = dd_opendir(dump_dir_name, DD_OPEN_READONLY); - if (!dd) - return 1; - int readonly = !dd->locked; - dd_close(dd); - if (readonly) + struct dump_dir *dd = open_directory_for_writing(dump_dir_name, NULL); + + if (dd) { - log("'%s' is not writable", dump_dir_name); - /* D_list can't be NULL here */ - struct dump_dir *dd_copy = steal_directory((char *)D_list->data, dump_dir_name); - if (dd_copy) - { - delete_dump_dir_possibly_using_abrtd(dump_dir_name); - dump_dir_name = xstrdup(dd_copy->dd_dirname); - dd_close(dd_copy); - } + dump_dir_name = xstrdup(dd->dd_dirname); + dd_close(dd); } exitcode = report(dump_dir_name, (always ? CLI_REPORT_BATCH : 0)); + if (exitcode == -1) error_msg_and_die("Crash '%s' not found", dump_dir_name); diff --git a/src/gui-wizard-gtk/wizard.c b/src/gui-wizard-gtk/wizard.c index a32aafa..cccf17f 100644 --- a/src/gui-wizard-gtk/wizard.c +++ b/src/gui-wizard-gtk/wizard.c @@ -311,72 +311,53 @@ static void on_toggle_ask_steal_cb(GtkToggleButton *tb, gpointer user_data) set_user_setting("ask_steal_dir", gtk_toggle_button_get_active(tb) ? "no" : "yes"); } -struct dump_dir *steal_if_needed(struct dump_dir *dd) +static bool ask_continue_before_steal(const char *base_dir, const char *dump_dir) { - if (!dd) - xfunc_die(); /* error msg was already logged */ - - if (dd->locked) - return dd; - - dd_close(dd); - - char *spooldir; - spooldir = concat_path_file(g_get_user_cache_dir(), "abrt/spool"); - const char *ask_steal_dir = get_user_setting("ask_steal_dir"); - if (!ask_steal_dir || strcmp(ask_steal_dir, "no")) - { - GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(g_wnd_assistant), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_QUESTION, - GTK_BUTTONS_OK_CANCEL, - _("Need writable directory, but '%s' is not writable." - " Move it to '%s' and operate on the moved data?"), - g_dump_dir_name, spooldir - ); - gint response = GTK_RESPONSE_CANCEL; - g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(save_dialog_response), &response); + if (ask_steal_dir && !strcmp(ask_steal_dir, "no")) + return true; - GtkWidget *ask_steal_cb = gtk_check_button_new_with_label(_("Don't ask me again")); - gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), - ask_steal_cb, TRUE, TRUE, 0); - g_signal_connect(ask_steal_cb, "toggled", G_CALLBACK(on_toggle_ask_steal_cb), NULL); + GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(g_wnd_assistant), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_QUESTION, + GTK_BUTTONS_OK_CANCEL, + _("Need writable directory, but '%s' is not writable." + " Move it to '%s' and operate on the moved data?"), + dump_dir, base_dir + ); - /* check it by default if it's shown for the first time */ - if (!ask_steal_dir) { - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ask_steal_cb), TRUE); - } + gint response = GTK_RESPONSE_CANCEL; + g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(save_dialog_response), &response); - gtk_widget_show(ask_steal_cb); - gtk_dialog_run(GTK_DIALOG(dialog)); - gtk_widget_destroy(dialog); + GtkWidget *ask_steal_cb = gtk_check_button_new_with_label(_("Don't ask me again")); + gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), + ask_steal_cb, TRUE, TRUE, 0); + g_signal_connect(ask_steal_cb, "toggled", G_CALLBACK(on_toggle_ask_steal_cb), NULL); - if (response != GTK_RESPONSE_OK) - return NULL; - } + /* check it by default if it's shown for the first time */ + if (!ask_steal_dir) + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ask_steal_cb), TRUE); - dd = steal_directory(spooldir, g_dump_dir_name); - g_free(spooldir); - if (!dd) - return NULL; /* Stealing failed. Error msg was already logged */ + gtk_widget_show(ask_steal_cb); + gtk_dialog_run(GTK_DIALOG(dialog)); + gtk_widget_destroy(dialog); - /* Delete old dir and switch to new one. - * Don't want to keep new dd open across deletion, - * therefore it's a bit more complicated. - */ - char *old_name = g_dump_dir_name; - g_dump_dir_name = xstrdup(dd->dd_dirname); - dd_close(dd); + return response == GTK_RESPONSE_OK; +} - update_window_title(); - delete_dump_dir_possibly_using_abrtd(old_name); //TODO: if (deletion_failed) error_msg("BAD")? - free(old_name); +struct dump_dir *wizard_open_directory_for_writing(const char *dump_dir_name) +{ + struct dump_dir *dd = open_directory_for_writing(dump_dir_name, + ask_continue_before_steal); - dd = dd_opendir(g_dump_dir_name, 0); - if (!dd) - xfunc_die(); /* error msg was already logged */ + if (dd && strcmp(g_dump_dir_name, dd->dd_dirname) != 0) + { + char *old_name = g_dump_dir_name; + g_dump_dir_name = xstrdup(dd->dd_dirname); + update_window_title(); + free(old_name); + } return dd; } @@ -439,12 +420,10 @@ static void save_text_if_changed(const char *name, const char *new_value) old_value = ""; if (strcmp(new_value, old_value) != 0) { - struct dump_dir *dd = dd_opendir(g_dump_dir_name, DD_OPEN_READONLY); - dd = steal_if_needed(dd); - if (dd && dd->locked) - { + struct dump_dir *dd = wizard_open_directory_for_writing(g_dump_dir_name); + if (dd) dd_save_text(dd, name, new_value); - } + //FIXME: else: what to do with still-unsaved data in the widget?? dd_close(dd); problem_data_reload_from_dump_dir(); @@ -1544,11 +1523,9 @@ static void start_event_run(const char *event_name, return; } - struct dump_dir *dd = dd_opendir(g_dump_dir_name, DD_OPEN_READONLY); - dd = steal_if_needed(dd); - int locked = (dd && dd->locked); + struct dump_dir *dd = wizard_open_directory_for_writing(g_dump_dir_name); dd_close(dd); - if (!locked) + if (!dd) { free_run_event_state(state); return; /* user refused to steal, or write error, etc... */ @@ -2142,9 +2119,8 @@ static void save_edited_one_liner(GtkCellRendererText *renderer, struct problem_item *item = problem_data_get_item_or_NULL(g_cd, item_name); if (item && (item->flags & CD_FLAG_ISEDITABLE)) { - struct dump_dir *dd = dd_opendir(g_dump_dir_name, DD_OPEN_READONLY); - dd = steal_if_needed(dd); - if (dd && dd->locked) + struct dump_dir *dd = wizard_open_directory_for_writing(g_dump_dir_name); + if (dd) { dd_save_text(dd, item_name, new_text); free(item->content); @@ -2193,11 +2169,8 @@ static void on_btn_add_file(GtkButton *button) struct problem_item *item = problem_data_get_item_or_NULL(g_cd, basename); if (!item || (item->flags & CD_FLAG_ISEDITABLE)) { - struct dump_dir *dd = dd_opendir(g_dump_dir_name, DD_OPEN_READONLY); - dd = steal_if_needed(dd); - bool writable = (dd && dd->locked); - dd_close(dd); - if (writable) + struct dump_dir *dd = wizard_open_directory_for_writing(g_dump_dir_name); + if (dd) { char *new_name = concat_path_file(g_dump_dir_name, basename); if (strcmp(filename, new_name) == 0) @@ -2222,6 +2195,7 @@ static void on_btn_add_file(GtkButton *button) } free(new_name); } + dd_close(dd); } else message = xasprintf(_("Item '%s' already exists and is not modifiable"), basename); @@ -2264,8 +2238,7 @@ static void delete_item(GtkTreeView *treeview) { // GtkTreePath *old_path = gtk_tree_model_get_path(store, &iter); - struct dump_dir *dd = dd_opendir(g_dump_dir_name, DD_OPEN_READONLY); - dd = steal_if_needed(dd); + struct dump_dir *dd = wizard_open_directory_for_writing(g_dump_dir_name); if (dd) { char *filename = concat_path_file(g_dump_dir_name, item_name); diff --git a/src/include/internal_libreport.h b/src/include/internal_libreport.h index 9d27a0d..e0cd7e6 100644 --- a/src/include/internal_libreport.h +++ b/src/include/internal_libreport.h @@ -634,6 +634,17 @@ int delete_dump_dir_possibly_using_abrtd(const char *dump_dir_name); #define steal_directory libreport_steal_directory struct dump_dir *steal_directory(const char *base_dir, const char *dump_dir_name); +/* Tries to open dump_dir_name with writing access. If function needs to steal + * directory calls ask_continue(new base dir, dump dir) callback to ask user + * for permission. If ask_continue param is NULL the function thinks that an + * answer is positive and steals directory. + * Returns NULL if opening failed or if stealing was dismissed. In this case, + * logs a message before returning. */ +#define open_directory_for_writing libreport_open_directory_for_writing +struct dump_dir *open_directory_for_writing( + const char *dump_dir_name, + bool (*ask_continue)(const char *, const char *)); + // Files bigger than this are never considered to be text. // // Started at 64k limit. But _some_ limit is necessary: diff --git a/src/lib/steal_directory.c b/src/lib/steal_directory.c index 1281872..ccfdd30 100644 --- a/src/lib/steal_directory.c +++ b/src/lib/steal_directory.c @@ -75,3 +75,45 @@ struct dump_dir *steal_directory(const char *base_dir, const char *dump_dir_name return dd_dst; } + +struct dump_dir *open_directory_for_writing( + const char *dump_dir_name, + bool (*ask)(const char *, const char *)) +{ + struct dump_dir *dd = dd_opendir(dump_dir_name, DD_OPEN_READONLY); + + if (!dd) + xfunc_die(); /* error msg was already logged */ + + if (dd->locked) + return dd; + + log("'%s' is not writable", dump_dir_name); + dd_close(dd); + + char *spooldir = concat_path_file(g_get_user_cache_dir(), "abrt/spool"); + + if (ask && !ask(spooldir, dump_dir_name)) + return NULL; + + dd = steal_directory(spooldir, dump_dir_name); + free(spooldir); + + if (!dd) + return NULL; + + /* Delete old dir and switch to new one. + * Don't want to keep new dd open across deletion, + * therefore it's a bit more complicated. + */ + delete_dump_dir_possibly_using_abrtd(dump_dir_name); + char *new_name = xstrdup(dd->dd_dirname); + dd_close(dd); + dd = dd_opendir(new_name, 0); + free(new_name); + + if (!dd) + xfunc_die(); /* error msg was already logged */ + + return dd; +} -- 1.7.10.4
