* 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

Reply via email to