diff options
author | Denys Vlasenko <dvlasenk@redhat.com> | 2011-04-28 22:02:46 +0200 |
---|---|---|
committer | Denys Vlasenko <dvlasenk@redhat.com> | 2011-04-28 22:02:46 +0200 |
commit | 1912a7c3980713ccc81e9fd2895873e29dc519a2 (patch) | |
tree | b621e0f468ad43cdf408d18f9bd82cb7e80a4132 /src/lib | |
parent | c6971f6de60e441c8edfe38e192c84a179d173b1 (diff) | |
download | abrt-1912a7c3980713ccc81e9fd2895873e29dc519a2.tar.gz abrt-1912a7c3980713ccc81e9fd2895873e29dc519a2.tar.xz abrt-1912a7c3980713ccc81e9fd2895873e29dc519a2.zip |
Logger: output "END:" line to delimit appended reports. closes bz#698458
Also changes Bugzilla and abrt-cli output format.
Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/Makefile.am | 1 | ||||
-rw-r--r-- | src/lib/is_in_string_list.c | 30 | ||||
-rw-r--r-- | src/lib/make_descr.c | 343 | ||||
-rw-r--r-- | src/lib/problem_data.c | 17 |
4 files changed, 210 insertions, 181 deletions
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index f2b97749..88671f54 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -12,6 +12,7 @@ lib_LTLIBRARIES = \ libreport_la_SOURCES = \ xfuncs.c \ + is_in_string_list.c \ encbase64.c \ binhex.c \ stdio_helpers.c \ diff --git a/src/lib/is_in_string_list.c b/src/lib/is_in_string_list.c new file mode 100644 index 00000000..2eda61dd --- /dev/null +++ b/src/lib/is_in_string_list.c @@ -0,0 +1,30 @@ +/* + Copyright (C) 2011 ABRT team + Copyright (C) 2011 RedHat Inc + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +#include "abrtlib.h" + +bool is_in_string_list(const char *name, char **v) +{ + while (*v) + { + if (strcmp(*v, name) == 0) + return true; + v++; + } + return false; +} diff --git a/src/lib/make_descr.c b/src/lib/make_descr.c index 35f4e9dc..fe629d2b 100644 --- a/src/lib/make_descr.c +++ b/src/lib/make_descr.c @@ -18,55 +18,171 @@ */ #include "abrtlib.h" -// caller is responsible for freeing **dsc -static void add_content(bool *was_multiline, char **dsc, const char *header, const char *content) + +char *make_description(problem_data_t *problem_data, char **names_to_skip, unsigned max_text_size, unsigned desc_flags) { - struct strbuf *buf_description = strbuf_new(); - if (*was_multiline) - strbuf_append_char(buf_description, '\n'); + struct strbuf *buf_dsc = strbuf_new(); - while (content[0] == '\n') - content++; + GList *list = g_hash_table_get_keys(problem_data); + list = g_list_sort(list, (GCompareFunc)strcmp); + GList *l; + + /* Print one-liners. Format: + * NAME1: <maybe more spaces>VALUE1 + * NAME2: <maybe more spaces>VALUE2 + */ + bool empty = true; + l = list; + while (l) + { + const char *key = l->data; + l = l->next; + + /* Skip items we are not interested in */ +//TODO: optimize by doing this once, not 3 times: + if (names_to_skip && is_in_string_list(key, names_to_skip)) + continue; + + struct problem_item *item = g_hash_table_lookup(problem_data, key); + if (!item) + continue; + + if ((desc_flags & MAKEDESC_SHOW_ONLY_LIST) && !(item->flags & CD_FLAG_LIST)) + continue; + + if ((item->flags & CD_FLAG_TXT) + && strlen(item->content) <= max_text_size + ) { + char *formatted = format_problem_item(item); + char *output = formatted ? formatted : item->content; + char *eol = strchr(output, '\n'); + if (!eol) + { + int pad = 16 - (strlen(key) + 2); + if (pad < 0) pad = 0; + strbuf_append_strf(buf_dsc, "%s: %*s%s\n", key, pad, "", output); + empty = false; + } + free(formatted); + } + } - if (strchr(content, '\n') == NULL) + bool append_empty_line = !empty; + if (desc_flags & MAKEDESC_SHOW_FILES) { - if (skip_whitespace(content)[0] == '\0') + /* Print file info. Format: + * <empty line if needed> + * NAME1: <maybe more spaces>Binary file, NNN bytes + * NAME2: <maybe more spaces>Text file, NNN bytes + * + * In many cases, it is useful to know how big binary files are + * (for example, helps with diagnosing bug upload problems) + */ + l = list; + while (l) { - /* empty, dont report at all */ - *dsc = strbuf_free_nobuf(buf_description); - return; + const char *key = l->data; + l = l->next; + + /* Skip items we are not interested in */ + if (names_to_skip && is_in_string_list(key, names_to_skip)) + continue; + + struct problem_item *item = g_hash_table_lookup(problem_data, key); + if (!item) + continue; + + if ((desc_flags & MAKEDESC_SHOW_ONLY_LIST) && !(item->flags & CD_FLAG_LIST)) + continue; + + if ((item->flags & CD_FLAG_BIN) + || ((item->flags & CD_FLAG_TXT) && strlen(item->content) > max_text_size) + ) { + if (append_empty_line) + strbuf_append_char(buf_dsc, '\n'); + append_empty_line = false; + + struct stat statbuf; + int stat_err = 0; + if (item->flags & CD_FLAG_BIN) + stat_err = stat(item->content, &statbuf); + else + statbuf.st_size = strlen(item->content); + + /* We don't print item->content for CD_FLAG_BIN, as it is + * always "/path/to/dump/dir/KEY" - not informative. + */ + int pad = 16 - (strlen(key) + 2); + if (pad < 0) pad = 0; + strbuf_append_strf(buf_dsc, + (!stat_err ? "%s: %*s%s file, %llu bytes\n" : "%s: %*s%s file\n"), + key, + pad, "", + ((item->flags & CD_FLAG_BIN) ? "Binary" : "Text"), + (long long)statbuf.st_size + ); + empty = false; + } } - /* one string value, like OS release */ - strbuf_append_strf(buf_description, "%s: %s\n", header, content); - *was_multiline = 0; } - else + + if (desc_flags & MAKEDESC_SHOW_MULTILINE) { - /* multi-string value, like backtrace */ - if (!*was_multiline && (buf_description->len != 0)) /* if wasn't yet separated */ - strbuf_append_char(buf_description, '\n'); + /* Print multi-liners. Format: + * <empty line if needed> + * NAME: + * :LINE1 + * :LINE2 + * :LINE3 + */ + l = list; + while (l) + { + const char *key = l->data; + l = l->next; - strbuf_append_strf(buf_description, "%s\n-----\n%s", header, content); - if (content[strlen(content) - 1] != '\n') - strbuf_append_char(buf_description, '\n'); + /* Skip items we are not interested in */ + if (names_to_skip && is_in_string_list(key, names_to_skip)) + continue; - *was_multiline = 1; + struct problem_item *item = g_hash_table_lookup(problem_data, key); + if (!item) + continue; + + if ((desc_flags & MAKEDESC_SHOW_ONLY_LIST) && !(item->flags & CD_FLAG_LIST)) + continue; + + if ((item->flags & CD_FLAG_TXT) + && strlen(item->content) <= max_text_size + ) { + char *formatted = format_problem_item(item); + char *output = formatted ? formatted : item->content; + char *eol = strchr(output, '\n'); + if (eol) + { + if (!empty) + strbuf_append_char(buf_dsc, '\n'); + strbuf_append_str(buf_dsc, key); + strbuf_append_str(buf_dsc, ":\n"); + for (;;) + { + eol = strchrnul(output, '\n'); + strbuf_append_strf(buf_dsc, ":%.*s\n", (int)(eol - output), output); + if (*eol == '\0' || eol[1] == '\0') + break; + output = eol + 1; + } + empty = false; + } + free(formatted); + } + } } - *dsc = strbuf_free_nobuf(buf_description); -} + g_list_free(list); -/* Items we don't want to include */ -static const char *const blacklisted_items[] = { - FILENAME_ANALYZER , - FILENAME_COREDUMP , - FILENAME_HOSTNAME , - FILENAME_DUPHASH , - FILENAME_UUID , - CD_DUMPDIR , - FILENAME_COUNT , - NULL -}; + return strbuf_free_nobuf(buf_dsc); +} char* make_description_mailx(problem_data_t *problem_data) { @@ -112,143 +228,36 @@ char* make_description_mailx(problem_data_t *problem_data) return strbuf_free_nobuf(buf_dsc); } +/* Items we don't want to include to bz / logger */ +static const char *const blacklisted_items[] = { + CD_DUMPDIR , + FILENAME_ANALYZER , + FILENAME_COREDUMP , + FILENAME_HOSTNAME , + FILENAME_DUPHASH , + FILENAME_UUID , + FILENAME_COUNT , + NULL +}; + char* make_description_bz(problem_data_t *problem_data) { - struct strbuf *buf_dsc = strbuf_new(); - struct strbuf *buf_big_dsc = strbuf_new(); - struct strbuf *buf_long_dsc = strbuf_new(); - - 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)) - { - struct stat statbuf; - int stat_err = 0; - unsigned flags = value->flags; - const char *content = value->content; - if (flags & CD_FLAG_TXT) - { - /* Skip items we are not interested in */ - const char *const *bl = blacklisted_items; - while (*bl) - { - if (strcmp(name, *bl) == 0) - break; - bl++; - } - if (*bl) - continue; /* blacklisted */ - - if (strlen(content) <= CD_TEXT_ATT_SIZE) - { - /* Add small (less than few kb) text items inline */ - bool was_multiline = 0; - char *tmp = NULL; - add_content(&was_multiline, &tmp, name, content); - - if (was_multiline) - { - /* Not one-liner */ - if (buf_long_dsc->len != 0) - strbuf_append_char(buf_long_dsc, '\n'); - strbuf_append_str(buf_long_dsc, tmp); - } - else - strbuf_append_str(buf_dsc, tmp); - - free(tmp); - } - else - { - statbuf.st_size = strlen(content); - goto add_big_file_info; - } - } - if (flags & CD_FLAG_BIN) - { - /* In many cases, it is useful to know how big binary files are - * (for example, helps with diagnosing bug upload problems) - */ - stat_err = stat(content, &statbuf); - add_big_file_info: - strbuf_append_strf(buf_big_dsc, - (stat_err ? "%s file: %s\n" : "%s file: %s, %llu bytes\n"), - ((flags & CD_FLAG_BIN) ? "Binary" : "Text"), - name, - (long long)statbuf.st_size - ); - } - } - - /* One-liners go first, then big files, then multi-line items */ - if (buf_dsc->len != 0 && (buf_big_dsc->len != 0 || buf_long_dsc->len != 0)) - strbuf_append_char(buf_dsc, '\n'); /* add empty line */ - - if (buf_big_dsc->len != 0 && buf_long_dsc->len != 0) - strbuf_append_char(buf_big_dsc, '\n'); /* add empty line */ - - char *big_dsc = strbuf_free_nobuf(buf_big_dsc); - strbuf_append_str(buf_dsc, big_dsc); - free(big_dsc); - - char *long_dsc = strbuf_free_nobuf(buf_long_dsc); - strbuf_append_str(buf_dsc, long_dsc); - free(long_dsc); - - return strbuf_free_nobuf(buf_dsc); + return make_description( + problem_data, + (char**)blacklisted_items, + /*max_text_size:*/ CD_TEXT_ATT_SIZE, + MAKEDESC_SHOW_FILES | MAKEDESC_SHOW_MULTILINE + ); } char* make_description_logger(problem_data_t *problem_data) { - struct strbuf *buf_dsc = strbuf_new(); - struct strbuf *buf_long_dsc = strbuf_new(); - - 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)) - { - const char *content = value->content; - if (value->flags & (CD_FLAG_TXT|CD_FLAG_BIN)) - { - /* Skip items we are not interested in */ - const char *const *bl = blacklisted_items; - while (*bl) - { - if (name == *bl) - break; - bl++; - } - if (*bl) - continue; /* blacklisted */ - - bool was_multiline = 0; - char *tmp = NULL; - add_content(&was_multiline, &tmp, name, content); - - if (was_multiline) - { - if (buf_long_dsc->len != 0) - strbuf_append_char(buf_long_dsc, '\n'); - - strbuf_append_str(buf_long_dsc, tmp); - } - else - strbuf_append_str(buf_dsc, tmp); - } - } - - if (buf_dsc->len != 0 && buf_long_dsc->len != 0) - strbuf_append_char(buf_dsc, '\n'); - - char *long_dsc = strbuf_free_nobuf(buf_long_dsc); - strbuf_append_str(buf_dsc, long_dsc); - free(long_dsc); - - return strbuf_free_nobuf(buf_dsc); + return make_description( + problem_data, + (char**)blacklisted_items, + /*max_text_size:*/ CD_TEXT_ATT_SIZE, + MAKEDESC_SHOW_FILES | MAKEDESC_SHOW_MULTILINE + ); } char* make_description_comment(problem_data_t *problem_data) diff --git a/src/lib/problem_data.c b/src/lib/problem_data.c index 63db70db..42dc770d 100644 --- a/src/lib/problem_data.c +++ b/src/lib/problem_data.c @@ -107,17 +107,6 @@ vector_of_problem_data_t *new_vector_of_problem_data(void) /* Miscellaneous helpers */ -static bool is_in_list(const char *name, const char *const *v) -{ - while (*v) - { - if (strcmp(*v, name) == 0) - return true; - v++; - } - return false; -} - static const char *const editable_files[] = { FILENAME_COMMENT , FILENAME_BACKTRACE, @@ -125,7 +114,7 @@ static const char *const editable_files[] = { }; static bool is_editable_file(const char *file_name) { - return is_in_list(file_name, editable_files); + return is_in_string_list(file_name, (char**)editable_files); } static const char *const always_text_files[] = { @@ -176,7 +165,7 @@ static char* is_text_file(const char *name, ssize_t *sz) if (base) { base++; - if (is_in_list(base, always_text_files)) + if (is_in_string_list(base, (char**)always_text_files)) return buf; } @@ -268,7 +257,7 @@ void load_problem_data_from_dump_dir(problem_data_t *problem_data, struct dump_d FILENAME_COUNT , NULL }; - if (is_in_list(short_name, list_files)) + if (is_in_string_list(short_name, (char**)list_files)) flags |= CD_FLAG_LIST; if (strcmp(short_name, FILENAME_TIME) == 0) |