- should be used in call from hook api,
  maybe it can even replace the former
  create_dump_dir_from_problem_data
---
 po/POTFILES.in             |    1 +
 src/include/problem_data.h |    2 +
 src/include/report.h       |    8 ++++
 src/lib/create_dump_dir.c  |   94 ++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 105 insertions(+)

diff --git a/po/POTFILES.in b/po/POTFILES.in
index 3203183..09ff83e 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -9,6 +9,7 @@ src/gtk-helpers/event_config_dialog.c
 src/gui-wizard-gtk/main.c
 src/gui-wizard-gtk/wizard.c
 src/gui-wizard-gtk/wizard.glade
+src/lib/create_dump_dir.c
 src/lib/event_config.c
 src/lib/parse_options.c
 src/lib/curl.c
diff --git a/src/include/problem_data.h b/src/include/problem_data.h
index 9bf46f5..c90f4a1 100644
--- a/src/include/problem_data.h
+++ b/src/include/problem_data.h
@@ -35,6 +35,7 @@ enum {
     /* Show this element in "short" info (report-cli -l) */
     CD_FLAG_LIST          = (1 << 4),
     CD_FLAG_UNIXTIME      = (1 << 5),
+    CD_FLAG_FILE          = (1 << 6),
 };
 
 struct problem_item {
@@ -61,6 +62,7 @@ void add_basics_to_problem_data(problem_data_t *pd);
 
 static inline void free_problem_data(problem_data_t *problem_data)
 {
+    //TODO: leaks problem item;
     if (problem_data)
         g_hash_table_destroy(problem_data);
 }
diff --git a/src/include/report.h b/src/include/report.h
index 3735ef6..21557ac 100644
--- a/src/include/report.h
+++ b/src/include/report.h
@@ -39,6 +39,12 @@ enum {
     LIBREPORT_RUN_NEWT    = (1 << 8), /* run 'report-newt' */
 };
 
+typedef enum {
+    LR_OK = 0,
+    LR_MISSING_ITEM = (1 << 1),
+    LR_ERROR        = (1 << 2),
+} LibreportError;
+
 int report_problem_in_dir(const char *dirname, int flags);
 
 /* Reports a problem stored in problem_data_t.
@@ -49,6 +55,8 @@ int report_problem_in_memory(problem_data_t *pd, int flags);
 /* Simple wrapper for trivial uses */
 int report_problem(problem_data_t *pd);
 
+LibreportError save_dump_dir_from_problem_data(problem_data_t *problem_data, 
char **problem_id, const char *base_dir_name);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/lib/create_dump_dir.c b/src/lib/create_dump_dir.c
index 137da12..a089a3b 100644
--- a/src/lib/create_dump_dir.c
+++ b/src/lib/create_dump_dir.c
@@ -19,6 +19,8 @@
 
 #include "internal_libreport.h"
 
+#define NEW_PD_SUFFIX ".new"
+
 static struct dump_dir *try_dd_create(const char *base_dir_name, const char 
*dir_name)
 {
     char *path = concat_path_file(base_dir_name, dir_name);
@@ -88,3 +90,95 @@ struct dump_dir 
*create_dump_dir_from_problem_data(problem_data_t *problem_data,
 
     return dd;
 }
+
+LibreportError save_dump_dir_from_problem_data(problem_data_t *problem_data, 
char **problem_id, const char *base_dir_name)
+{
+    char *type = get_problem_item_content_or_NULL(problem_data, "type");
+
+    if(!type)
+    {
+        error_msg(_("Missing required item: 'type'"));
+        return LR_MISSING_ITEM;
+    }
+
+    char *time_s = get_problem_item_content_or_NULL(problem_data, "time");
+    if(!time_s)
+    {
+        /* 64 is a randomly picked constant which should be
+         * enough to hold the time in seconds for a long time..
+         */
+        char buf[64];
+        time_t t = time(NULL);
+        /* time is a required field, so if it's not provided add a default one 
*/
+        snprintf(buf, sizeof(buf), "%lu", (long unsigned)t);
+        add_to_problem_data_ext(problem_data, "time", buf, CD_FLAG_TXT);
+    }
+
+    char dir_name[strlen(type) + 
sizeof("-"LIBREPORT_ISO_DATE_STRING_SAMPLE"-%lu") + sizeof(long)*3];
+    *problem_id = (char *)xmalloc(sizeof(dir_name));
+    snprintf(*problem_id, sizeof(dir_name), "%s-%s-%lu"NEW_PD_SUFFIX, type, 
iso_date_string(NULL), (long)getpid());
+    strncpy(dir_name, *problem_id, sizeof(dir_name));
+
+    VERB2 log("Saving to %s/%s", base_dir_name, *problem_id);
+    struct dump_dir *dd = try_dd_create(base_dir_name, dir_name);
+    if (!dd)
+    {
+        perror_msg("Can't create problem directory");
+        *problem_id = NULL;
+        return LR_ERROR;
+    }
+
+    GHashTableIter iter;
+    char *name;
+    struct problem_item *value;
+    g_hash_table_iter_init(&iter, problem_data);
+    while (g_hash_table_iter_next(&iter, (void**)&name, (void**)&value))
+    {
+        if (value->flags & CD_FLAG_FILE)
+        {
+            char dest[PATH_MAX+1];
+            snprintf(dest, sizeof(dest), "%s/%s", dd->dd_dirname, name);
+            VERB2 log("copying '%s' to '%s'", value->content, dest);
+            off_t copied = copy_file(value->content, dest, 0644);
+            if (copied < 0)
+                error_msg("Can't copy %s to %s", value->content, dest);
+
+            VERB2 log("copied %li bytes", (unsigned long)copied);
+
+            continue;
+        }
+
+        /* only files should contain '/' and those are handled earlier */
+        if (name[0] == '.' || strchr(name, '/'))
+        {
+            error_msg("Problem data field name contains disallowed chars: 
'%s'", name);
+            continue;
+        }
+
+//FIXME: what to do with CD_FLAG_BINs??
+        if (value->flags & CD_FLAG_BIN)
+            continue;
+
+        dd_save_text(dd, name, value->content);
+    }
+
+
+
+    char *suffix = strstr(*problem_id, NEW_PD_SUFFIX);
+    if (suffix)
+        *suffix = '\0';
+
+    char* new_path = concat_path_file(base_dir_name, *problem_id);
+
+    VERB2 log("Renaming from'%s' to '%s'", dd->dd_dirname, new_path);
+    if (dd_rename(dd, new_path) != 0)
+    {
+        *problem_id = NULL;
+        return LR_ERROR;
+    }
+    free(new_path);
+
+    dd_close(dd);
+
+    return LR_OK;
+}
-- 
1.7.10.2

Reply via email to