diff options
| author | Denys Vlasenko <dvlasenk@redhat.com> | 2010-12-06 16:56:50 +0100 |
|---|---|---|
| committer | Denys Vlasenko <dvlasenk@redhat.com> | 2010-12-06 16:56:50 +0100 |
| commit | 47728cc3c70c2b6d3a645e5760b39b20bd946e39 (patch) | |
| tree | 6fd64dc8d124d5a10dd4efddd69a71f921f4a1d1 /src/cli | |
| parent | 300a498bdc7b2912f8aaebeb87a7b4cc0a9970a5 (diff) | |
This patch changes crash data to use C structures.
The smallest data element is:
struct crash_item { char *content; unsigned flags; };
where content is, eh, content, and flags is a bit flag field.
crash_data_t is a map of crash_item's, implemented as a pointer
to heap-allocated GHashTable.
vector_of_crash_data_t is a vector of crash_data_t's, implemented
as a pointer to heap-allocated GPtrArray.
Most operations have light wrappers around them to hide the nature
of the containers. For example, to free vector_of_crash_data,
you need to use free_vector_of_crash_data(ptr) instead of
open-coding g_ptr_array_free. The wrapper is thin.
The goal is not so much to hide the implementation, but more
to make it easier to use the correct function.
dbus (un)marshalling functions convert crash_item to three-element
array of strings, in order to keep compatibility with abrt-gui (python).
This can be changed later to use native representation.
crash_data_t and vector_of_crash_data_t are represented in
"natural" way, no funny stuff there.
Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
Diffstat (limited to 'src/cli')
| -rw-r--r-- | src/cli/CLI.cpp | 91 | ||||
| -rw-r--r-- | src/cli/dbus.cpp | 16 | ||||
| -rw-r--r-- | src/cli/dbus.h | 6 | ||||
| -rw-r--r-- | src/cli/report.cpp | 77 |
4 files changed, 101 insertions, 89 deletions
diff --git a/src/cli/CLI.cpp b/src/cli/CLI.cpp index 64d629b8..fd8ec4f0 100644 --- a/src/cli/CLI.cpp +++ b/src/cli/CLI.cpp @@ -38,10 +38,10 @@ static char *localize_crash_time(const char *timestr) } /** Prints basic information about a crash to stdout. */ -static void print_crash(const map_crash_data_t &crash) +static void print_crash(crash_data_t *crash_data) { /* Create a localized string from crash time. */ - const char *timestr = get_crash_data_item_content(crash, FILENAME_TIME).c_str(); + const char *timestr = get_crash_item_content_or_die(crash_data, FILENAME_TIME); const char *timeloc = localize_crash_time(timestr); printf(_("\tCrash dump : %s\n" @@ -50,17 +50,18 @@ static void print_crash(const map_crash_data_t &crash) "\tExecutable : %s\n" "\tCrash Time : %s\n" "\tCrash Count: %s\n"), - get_crash_data_item_content(crash, CD_DUMPDIR).c_str(), - get_crash_data_item_content(crash, FILENAME_UID).c_str(), - get_crash_data_item_content(crash, FILENAME_PACKAGE).c_str(), - get_crash_data_item_content(crash, FILENAME_EXECUTABLE).c_str(), + get_crash_item_content_or_NULL(crash_data, CD_DUMPDIR), + get_crash_item_content_or_NULL(crash_data, FILENAME_UID), + get_crash_item_content_or_NULL(crash_data, FILENAME_PACKAGE), + get_crash_item_content_or_NULL(crash_data, FILENAME_EXECUTABLE), timeloc, - get_crash_data_item_content(crash, FILENAME_COUNT).c_str()); + get_crash_item_content_or_NULL(crash_data, FILENAME_COUNT) + ); free((void *)timeloc); /* Print the hostname if it's available. */ - const char *hostname = get_crash_data_item_content_or_NULL(crash, FILENAME_HOSTNAME); + const char *hostname = get_crash_item_content_or_NULL(crash_data, FILENAME_HOSTNAME); if (hostname) printf(_("\tHostname : %s\n"), hostname); } @@ -70,14 +71,14 @@ static void print_crash(const map_crash_data_t &crash) * @param include_reported * Do not skip entries marked as already reported. */ -static void print_crash_list(const vector_map_crash_data_t& crash_list, bool include_reported) +static void print_crash_list(vector_of_crash_data_t *crash_list, bool include_reported) { - for (unsigned i = 0; i < crash_list.size(); ++i) + for (unsigned i = 0; i < crash_list->len; ++i) { - const map_crash_data_t& crash = crash_list[i]; + crash_data_t *crash = get_crash_data(crash_list, i); if (!include_reported) { - const char *msg = get_crash_data_item_content_or_NULL(crash, FILENAME_MESSAGE); + const char *msg = get_crash_item_content_or_NULL(crash, FILENAME_MESSAGE); if (!msg || !msg[0]) continue; } @@ -90,9 +91,9 @@ static void print_crash_list(const vector_map_crash_data_t& crash_list, bool inc /** * Prints full information about a crash */ -static void print_crash_info(const map_crash_data_t& crash, bool show_backtrace) +static void print_crash_info(crash_data_t *crash_data, bool show_backtrace) { - const char *timestr = get_crash_data_item_content(crash, FILENAME_TIME).c_str(); + const char *timestr = get_crash_item_content_or_die(crash_data, FILENAME_TIME); const char *timeloc = localize_crash_time(timestr); printf(_("Dump directory: %s\n" @@ -104,50 +105,51 @@ static void print_crash_info(const map_crash_data_t& crash, bool show_backtrace) "Executable: %s\n" "System: %s, kernel %s\n" "Reason: %s\n"), - get_crash_data_item_content(crash, CD_DUMPDIR).c_str(), + get_crash_item_content_or_die(crash_data, CD_DUMPDIR), timeloc, - get_crash_data_item_content(crash, FILENAME_ANALYZER).c_str(), - get_crash_data_item_content(crash, FILENAME_COMPONENT).c_str(), - get_crash_data_item_content(crash, FILENAME_PACKAGE).c_str(), - get_crash_data_item_content(crash, FILENAME_CMDLINE).c_str(), - get_crash_data_item_content(crash, FILENAME_EXECUTABLE).c_str(), - get_crash_data_item_content(crash, FILENAME_RELEASE).c_str(), - get_crash_data_item_content(crash, FILENAME_KERNEL).c_str(), - get_crash_data_item_content(crash, FILENAME_REASON).c_str()); + get_crash_item_content_or_die(crash_data, FILENAME_ANALYZER), + get_crash_item_content_or_die(crash_data, FILENAME_COMPONENT), + get_crash_item_content_or_die(crash_data, FILENAME_PACKAGE), + get_crash_item_content_or_die(crash_data, FILENAME_CMDLINE), + get_crash_item_content_or_die(crash_data, FILENAME_EXECUTABLE), + get_crash_item_content_or_die(crash_data, FILENAME_RELEASE), + get_crash_item_content_or_die(crash_data, FILENAME_KERNEL), + get_crash_item_content_or_die(crash_data, FILENAME_REASON) + ); free((void *)timeloc); /* Print optional fields only if they are available */ /* Coredump is not present in kerneloopses and Python exceptions. */ - const char *coredump = get_crash_data_item_content_or_NULL(crash, FILENAME_COREDUMP); + const char *coredump = get_crash_item_content_or_NULL(crash_data, FILENAME_COREDUMP); if (coredump) printf(_("Coredump file: %s\n"), coredump); - const char *rating = get_crash_data_item_content_or_NULL(crash, FILENAME_RATING); + const char *rating = get_crash_item_content_or_NULL(crash_data, FILENAME_RATING); if (rating) printf(_("Rating: %s\n"), rating); /* Crash function is not present in kerneloopses, and before the full report is created.*/ - const char *crash_function = get_crash_data_item_content_or_NULL(crash, FILENAME_CRASH_FUNCTION); + const char *crash_function = get_crash_item_content_or_NULL(crash_data, FILENAME_CRASH_FUNCTION); if (crash_function) printf(_("Crash function: %s\n"), crash_function); - const char *hostname = get_crash_data_item_content_or_NULL(crash, FILENAME_HOSTNAME); + const char *hostname = get_crash_item_content_or_NULL(crash_data, FILENAME_HOSTNAME); if (hostname) printf(_("Hostname: %s\n"), hostname); - const char *reproduce = get_crash_data_item_content_or_NULL(crash, FILENAME_REPRODUCE); + const char *reproduce = get_crash_item_content_or_NULL(crash_data, FILENAME_REPRODUCE); if (reproduce) printf(_("\nHow to reproduce:\n%s\n"), reproduce); - const char *comment = get_crash_data_item_content_or_NULL(crash, FILENAME_COMMENT); + const char *comment = get_crash_item_content_or_NULL(crash_data, FILENAME_COMMENT); if (comment) printf(_("\nComment:\n%s\n"), comment); if (show_backtrace) { - const char *backtrace = get_crash_data_item_content_or_NULL(crash, FILENAME_BACKTRACE); + const char *backtrace = get_crash_item_content_or_NULL(crash_data, FILENAME_BACKTRACE); if (backtrace) printf(_("\nBacktrace:\n%s\n"), backtrace); } @@ -159,15 +161,17 @@ static void print_crash_info(const map_crash_data_t& crash, bool show_backtrace) */ static char *guess_crash_id(const char *str) { - vector_map_crash_data_t ci = call_GetCrashInfos(); - unsigned num_crashinfos = ci.size(); + vector_of_crash_data_t *ci = call_GetCrashInfos(); + unsigned num_crashinfos = ci->len; if (str[0] == '@') /* "--report @N" syntax */ { unsigned position = xatoi_u(str + 1); if (position >= num_crashinfos) error_msg_and_die("There are only %u crash infos", num_crashinfos); - map_crash_data_t& info = ci[position]; - return xstrdup(get_crash_data_item_content(info, CD_DUMPDIR).c_str()); + crash_data_t *info = get_crash_data(ci, position); + char *res = xstrdup(get_crash_item_content_or_die(info, CD_DUMPDIR)); + free_vector_of_crash_data(ci); + return res; } unsigned len = strlen(str); @@ -175,8 +179,8 @@ static char *guess_crash_id(const char *str) char *result = NULL; for (ii = 0; ii < num_crashinfos; ii++) { - map_crash_data_t& info = ci[ii]; - const char *this_dir = get_crash_data_item_content(info, CD_DUMPDIR).c_str(); + crash_data_t *info = get_crash_data(ci, ii); + const char *this_dir = get_crash_item_content_or_die(info, CD_DUMPDIR); if (strncmp(str, this_dir, len) == 0) { if (result) @@ -184,6 +188,7 @@ static char *guess_crash_id(const char *str) result = xstrdup(this_dir); } } + free_vector_of_crash_data(ci); if (!result) error_msg_and_die("Crash dump directory '%s' not found", str); return result; @@ -353,8 +358,9 @@ int main(int argc, char** argv) { case OPT_GET_LIST: { - vector_map_crash_data_t ci = call_GetCrashInfos(); + vector_of_crash_data_t *ci = call_GetCrashInfos(); print_crash_list(ci, full); + free_vector_of_crash_data(ci); break; } case OPT_REPORT: @@ -403,12 +409,12 @@ int main(int argc, char** argv) int old_logmode = logmode; logmode = 0; - map_crash_data_t crashData = call_CreateReport(crash_id); - if (crashData.empty()) /* no such crash_id */ + crash_data_t *crash_data = call_CreateReport(crash_id); + if (!crash_data) /* no such crash_id */ { crash_id = guess_crash_id(crash_id); - crashData = call_CreateReport(crash_id); - if (crashData.empty()) + crash_data = call_CreateReport(crash_id); + if (!crash_data) { error_msg("Crash '%s' not found", crash_id); free((void *)crash_id); @@ -420,7 +426,8 @@ int main(int argc, char** argv) logmode = old_logmode; - print_crash_info(crashData, backtrace); + print_crash_info(crash_data, backtrace); + free_crash_data(crash_data); break; } diff --git a/src/cli/dbus.cpp b/src/cli/dbus.cpp index f9271b85..6c98ec4e 100644 --- a/src/cli/dbus.cpp +++ b/src/cli/dbus.cpp @@ -121,7 +121,7 @@ static DBusMessage* send_get_reply_and_unref(DBusMessage* msg) } } -vector_map_crash_data_t call_GetCrashInfos() +vector_of_crash_data_t *call_GetCrashInfos() { DBusMessage* msg = new_call_msg(__func__ + 5); DBusMessage *reply = send_get_reply_and_unref(msg); @@ -129,8 +129,8 @@ vector_map_crash_data_t call_GetCrashInfos() DBusMessageIter in_iter; dbus_message_iter_init(reply, &in_iter); - vector_map_crash_data_t argout; - int r = load_val(&in_iter, argout); + vector_of_crash_data_t *argout = NULL; + int r = load_vector_of_crash_data(&in_iter, &argout); if (r != ABRT_DBUS_LAST_FIELD) /* more values present, or bad type */ error_msg_and_die("dbus call %s: return type mismatch", __func__ + 5); @@ -138,7 +138,7 @@ vector_map_crash_data_t call_GetCrashInfos() return argout; } -map_crash_data_t call_CreateReport(const char* crash_id) +crash_data_t *call_CreateReport(const char* crash_id) { DBusMessage* msg = new_call_msg(__func__ + 5); dbus_message_append_args(msg, @@ -150,8 +150,8 @@ map_crash_data_t call_CreateReport(const char* crash_id) DBusMessageIter in_iter; dbus_message_iter_init(reply, &in_iter); - map_crash_data_t argout; - int r = load_val(&in_iter, argout); + crash_data_t *argout = NULL; + int r = load_crash_data(&in_iter, &argout); if (r != ABRT_DBUS_LAST_FIELD) /* more values present, or bad type */ error_msg_and_die("dbus call %s: return type mismatch", __func__ + 5); @@ -159,7 +159,7 @@ map_crash_data_t call_CreateReport(const char* crash_id) return argout; } -report_status_t call_Report(const map_crash_data_t& report, +report_status_t call_Report(crash_data_t *report, const vector_string_t& reporters, GHashTable *plugins) { @@ -168,7 +168,7 @@ report_status_t call_Report(const map_crash_data_t& report, dbus_message_iter_init_append(msg, &out_iter); /* parameter #1: report data */ - store_val(&out_iter, report); + store_crash_data(&out_iter, report); /* parameter #2: reporters to use */ store_val(&out_iter, reporters); /* parameter #3 (opt): plugin config */ diff --git a/src/cli/dbus.h b/src/cli/dbus.h index b837869d..0d338d27 100644 --- a/src/cli/dbus.h +++ b/src/cli/dbus.h @@ -24,9 +24,9 @@ extern DBusConnection* s_dbus_conn; -vector_map_crash_data_t call_GetCrashInfos(); +vector_of_crash_data_t *call_GetCrashInfos(); -map_crash_data_t call_CreateReport(const char *crash_id); +crash_data_t *call_CreateReport(const char *crash_id); /** Sends report using enabled Reporter plugins. * @param report @@ -40,7 +40,7 @@ map_crash_data_t call_CreateReport(const char *crash_id); * obtained by call_GetPluginSettings, otherwise the plugin might ignore * the settings. */ -report_status_t call_Report(const map_crash_data_t& report, +report_status_t call_Report(crash_data_t *report, const vector_string_t& reporters, GHashTable *plugins); diff --git a/src/cli/report.cpp b/src/cli/report.cpp index 88154d53..9ee37576 100644 --- a/src/cli/report.cpp +++ b/src/cli/report.cpp @@ -142,30 +142,30 @@ static void remove_comments_and_unescape(char *str) * Writes a field of crash report to a file. * Field must be writable. */ -static void write_crash_report_field(FILE *fp, const map_crash_data_t &report, +static void write_crash_report_field(FILE *fp, crash_data_t *crash_data, const char *field, const char *description) { - const map_crash_data_t::const_iterator it = report.find(field); - if (it == report.end()) + const struct crash_item *value = get_crash_data_item_or_NULL(crash_data, field); + if (!value) { // exit silently, all fields are optional for now //error_msg("Field %s not found", field); return; } - if (it->second[CD_TYPE] == CD_SYS) + if (value->flags & CD_FLAG_SYS) { error_msg("Cannot update field %s because it is a system value", field); return; } - fprintf(fp, "%s%s\n", FIELD_SEP, it->first.c_str()); + fprintf(fp, "%s%s\n", FIELD_SEP, field); fprintf(fp, "%s\n", description); - if (it->second[CD_EDITABLE] != CD_ISEDITABLE) + if (!(value->flags & CD_FLAG_ISEDITABLE)) fprintf(fp, _("# This field is read only\n")); - char *escaped_content = escape(it->second[CD_CONTENT].c_str()); + char *escaped_content = escape(value->content); fprintf(fp, "%s\n", escaped_content); free(escaped_content); } @@ -177,7 +177,7 @@ static void write_crash_report_field(FILE *fp, const map_crash_data_t &report, * If the report is successfully stored to the file, a zero value is returned. * On failure, nonzero value is returned. */ -static void write_crash_report(const map_crash_data_t &report, FILE *fp) +static void write_crash_report(crash_data_t *report, FILE *fp) { fprintf(fp, "# Please check this report. Lines starting with '#' will be ignored.\n" "# Lines starting with '%%----' separate fields, please do not delete them.\n\n"); @@ -208,7 +208,7 @@ static void write_crash_report(const map_crash_data_t &report, FILE *fp) * 1 if the field was changed. * Changes to read-only fields are ignored. */ -static int read_crash_report_field(const char *text, map_crash_data_t &report, +static int read_crash_report_field(const char *text, crash_data_t *report, const char *field) { char separator[sizeof("\n" FIELD_SEP)-1 + strlen(field) + 2]; // 2 = '\n\0' @@ -225,21 +225,21 @@ static int read_crash_report_field(const char *text, map_crash_data_t &report, else length = end - textfield; - const map_crash_data_t::iterator it = report.find(field); - if (it == report.end()) + struct crash_item *value = get_crash_data_item_or_NULL(report, field); + if (!value) { error_msg("Field %s not found", field); return 0; } - if (it->second[CD_TYPE] == CD_SYS) + if (value->flags & CD_FLAG_SYS) { error_msg("Cannot update field %s because it is a system value", field); return 0; } // Do not change noneditable fields. - if (it->second[CD_EDITABLE] != CD_ISEDITABLE) + if (!(value->flags & CD_FLAG_ISEDITABLE)) return 0; // Compare the old field contents with the new field contents. @@ -248,16 +248,16 @@ static int read_crash_report_field(const char *text, map_crash_data_t &report, newvalue[length] = '\0'; trim(newvalue); - char oldvalue[it->second[CD_CONTENT].length() + 1]; - strcpy(oldvalue, it->second[CD_CONTENT].c_str()); + char oldvalue[strlen(value->content) + 1]; + strcpy(oldvalue, value->content); trim(oldvalue); // Return if no change in the contents detected. - int cmp = strcmp(newvalue, oldvalue); - if (!cmp) + if (strcmp(newvalue, oldvalue) == 0) return 0; - it->second[CD_CONTENT].assign(newvalue); + free(value->content); + value->content = xstrdup(newvalue); return 1; } @@ -269,7 +269,7 @@ static int read_crash_report_field(const char *text, map_crash_data_t &report, * 1 if any field was changed. * Changes to read-only fields are ignored. */ -static int read_crash_report(map_crash_data_t &report, const char *text) +static int read_crash_report(crash_data_t *report, const char *text) { int result = 0; result |= read_crash_report_field(text, report, FILENAME_COMMENT); @@ -292,13 +292,13 @@ static int read_crash_report(map_crash_data_t &report, const char *text) * Ensures that the fields needed for editor are present in the crash data. * Fields: comments, how to reproduce. */ -static void create_fields_for_editor(map_crash_data_t &crash_data) +static void create_fields_for_editor(crash_data_t *crash_data) { - if (crash_data.find(FILENAME_COMMENT) == crash_data.end()) - add_to_crash_data_ext(crash_data, FILENAME_COMMENT, CD_TXT, CD_ISEDITABLE, ""); + if (!get_crash_data_item_or_NULL(crash_data, FILENAME_COMMENT)) + add_to_crash_data_ext(crash_data, FILENAME_COMMENT, "", CD_FLAG_TXT + CD_FLAG_ISEDITABLE); - if (crash_data.find(FILENAME_REPRODUCE) == crash_data.end()) - add_to_crash_data_ext(crash_data, FILENAME_REPRODUCE, CD_TXT, CD_ISEDITABLE, "1. \n2. \n3. \n"); + if (!get_crash_data_item_or_NULL(crash_data, FILENAME_REPRODUCE)) + add_to_crash_data_ext(crash_data, FILENAME_REPRODUCE, "1. \n2. \n3. \n", CD_FLAG_TXT + CD_FLAG_ISEDITABLE); } /** @@ -342,7 +342,7 @@ static int launch_editor(const char *path) * 2 on failure, unable to create, open, or close temporary file * 3 on failure, cannot launch text editor */ -static int run_report_editor(map_crash_data_t &cr) +static int run_report_editor(crash_data_t *crash_data) { /* Open a temporary file and write the crash report to it. */ char filename[] = "/tmp/abrt-report.XXXXXX"; @@ -360,7 +360,7 @@ static int run_report_editor(map_crash_data_t &cr) return 2; } - write_crash_report(cr, fp); + write_crash_report(crash_data, fp); if (fclose(fp)) /* errno is set */ { @@ -405,7 +405,7 @@ static int run_report_editor(map_crash_data_t &cr) remove_comments_and_unescape(text); // Updates the crash report from the file text. - int report_changed = read_crash_report(cr, text); + int report_changed = read_crash_report(crash_data, text); free(text); if (report_changed) puts(_("\nThe report has been updated")); @@ -587,27 +587,31 @@ int report(const char *crash_id, int flags) if (flags & CLI_REPORT_SILENT_IF_NOT_FOUND) logmode = 0; // Ask for an initial report. - map_crash_data_t cr = call_CreateReport(crash_id); + crash_data_t *crash_data = call_CreateReport(crash_id); logmode = old_logmode; - if (cr.size() == 0) + if (!crash_data || g_hash_table_size(crash_data) == 0) { + free_crash_data(crash_data); return -1; } - const char *rating_str = get_crash_data_item_content_or_NULL(cr, FILENAME_RATING); + const char *rating_str = get_crash_item_content_or_NULL(crash_data, FILENAME_RATING); unsigned rating = rating_str ? xatou(rating_str) : 4; /* Open text editor and give a chance to review the backtrace etc. */ if (!(flags & CLI_REPORT_BATCH)) { - create_fields_for_editor(cr); - int result = run_report_editor(cr); + create_fields_for_editor(crash_data); + int result = run_report_editor(crash_data); if (result != 0) + { + free_crash_data(crash_data); return result; + } } /* Get possible reporters associated with this particular crash. */ - const char *events = get_crash_data_item_content_or_NULL(cr, CD_EVENTS); + const char *events = get_crash_item_content_or_NULL(crash_data, CD_EVENTS); vector_string_t reporters; if (events) while (*events) { @@ -633,7 +637,7 @@ int report(const char *crash_id, int flags) if (flags & CLI_REPORT_BATCH) { puts(_("Reporting...")); - report_status_t r = call_Report(cr, reporters, reporters_settings); + report_status_t r = call_Report(crash_data, reporters, reporters_settings); report_status_t::iterator it = r.begin(); while (it != r.end()) { @@ -668,7 +672,7 @@ int report(const char *crash_id, int flags) { puts(_("Reporting disabled because the backtrace is unusable")); - const char *package = get_crash_data_item_content_or_NULL(cr, FILENAME_PACKAGE); + const char *package = get_crash_item_content_or_NULL(crash_data, FILENAME_PACKAGE); if (package && package[0]) printf(_("Please try to install debuginfo manually using the command: \"debuginfo-install %s\" and try again\n"), package); @@ -688,7 +692,7 @@ int report(const char *crash_id, int flags) ask_for_missing_settings(it->c_str(), *settings); vector_string_t cur_reporter(1, *it); - report_status_t r = call_Report(cr, cur_reporter, reporters_settings); + report_status_t r = call_Report(crash_data, cur_reporter, reporters_settings); assert(r.size() == 1); /* one reporter --> one report status */ vector_string_t &v = r.begin()->second; printf("%s: %s\n", r.begin()->first.c_str(), v[REPORT_STATUS_IDX_MSG].c_str()); @@ -699,6 +703,7 @@ int report(const char *crash_id, int flags) } g_hash_table_destroy(reporters_settings); + free_crash_data(crash_data); printf(_("Crash reported via %d report events (%d errors)\n"), plugins, errors); return errors != 0; } |
