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