summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorDenys Vlasenko <dvlasenk@redhat.com>2010-10-11 19:31:27 +0200
committerDenys Vlasenko <dvlasenk@redhat.com>2010-10-11 19:31:27 +0200
commit86cfa357aae945eac2e11ef1379c94e5ef27ccd6 (patch)
tree0b4c20cf2b90f33e2a7d34826e015f85780cf545 /lib
parent6c09581696b33bd6f8b96fdb61b4971369f21220 (diff)
downloadabrt-86cfa357aae945eac2e11ef1379c94e5ef27ccd6.tar.gz
abrt-86cfa357aae945eac2e11ef1379c94e5ef27ccd6.tar.xz
abrt-86cfa357aae945eac2e11ef1379c94e5ef27ccd6.zip
move load_crash_data_from_debug_dump from MiddleWare to CrashTypes
Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/utils/CrashTypes.cpp123
1 files changed, 123 insertions, 0 deletions
diff --git a/lib/utils/CrashTypes.cpp b/lib/utils/CrashTypes.cpp
index a31f2c00..acacda5e 100644
--- a/lib/utils/CrashTypes.cpp
+++ b/lib/utils/CrashTypes.cpp
@@ -82,6 +82,129 @@ void add_to_crash_data(map_crash_data_t& pCrashData,
add_to_crash_data_ext(pCrashData, pItem, CD_TXT, CD_ISNOTEDITABLE, pContent);
}
+static char* is_text_file(const char *name, ssize_t *sz)
+{
+ /* We were using magic.h API to check for file being text, but it thinks
+ * that file containing just "0" is not text (!!)
+ * So, we do it ourself.
+ */
+
+ int fd = open(name, O_RDONLY);
+ if (fd < 0)
+ return NULL; /* it's not text (because it does not exist! :) */
+
+ /* Maybe 64k limit is small. But _some_ limit is necessary:
+ * fields declared "text" may end up in editing fields and such.
+ * We don't want to accidentally end up with 100meg text in a textbox!
+ * So, don't remove this. If you really need to, raise the limit.
+ */
+ off_t size = lseek(fd, 0, SEEK_END);
+ if (size < 0 || size > 64*1024)
+ {
+ close(fd);
+ return NULL; /* it's not a SMALL text */
+ }
+ lseek(fd, 0, SEEK_SET);
+
+ char *buf = (char*)xmalloc(*sz);
+ ssize_t r = *sz = full_read(fd, buf, *sz);
+ close(fd);
+ if (r < 0)
+ {
+ free(buf);
+ return NULL; /* it's not text (because we can't read it) */
+ }
+
+ /* Some files in our dump directories are known to always be textual */
+ const char *base = strrchr(name, '/');
+ if (base)
+ {
+ base++;
+ if (strcmp(base, FILENAME_BACKTRACE) == 0
+ || strcmp(base, FILENAME_CMDLINE) == 0
+ ) {
+ return buf;
+ }
+ }
+
+ /* Every once in a while, even a text file contains a few garbled
+ * or unexpected non-ASCII chars. We should not declare it "binary".
+ */
+ const unsigned RATIO = 50;
+ unsigned total_chars = r + RATIO;
+ unsigned bad_chars = 1; /* 1 prevents division by 0 later */
+ while (--r >= 0)
+ {
+ if (buf[r] >= 0x7f
+ /* among control chars, only '\t','\n' etc are allowed */
+ || (buf[r] < ' ' && !isspace(buf[r]))
+ ) {
+ if (buf[r] == '\0')
+ {
+ /* We don't like NULs very much. Not text for sure! */
+ free(buf);
+ return NULL;
+ }
+ bad_chars++;
+ }
+ }
+
+ if ((total_chars / bad_chars) >= RATIO)
+ return buf; /* looks like text to me */
+
+ free(buf);
+ return NULL; /* it's binary */
+}
+
+void load_crash_data_from_debug_dump(struct dump_dir *dd, map_crash_data_t& data)
+{
+ char *short_name;
+ char *full_name;
+
+ dd_init_next_file(dd);
+ while (dd_get_next_file(dd, &short_name, &full_name))
+ {
+ ssize_t sz = 4*1024;
+ char *text = NULL;
+ bool editable = is_editable_file(short_name);
+
+ if (!editable)
+ {
+ text = is_text_file(full_name, &sz);
+ if (!text)
+ {
+ add_to_crash_data_ext(data,
+ short_name,
+ CD_BIN,
+ CD_ISNOTEDITABLE,
+ full_name
+ );
+
+ free(short_name);
+ free(full_name);
+ continue;
+ }
+ }
+
+ char *content;
+ if (sz < 4*1024) /* is_text_file did read entire file */
+ content = xstrndup(text, sz); //TODO: can avoid this copying if is_text_file() adds NUL
+ else /* no, need to read it all */
+ content = dd_load_text(dd, short_name);
+ free(text);
+
+ add_to_crash_data_ext(data,
+ short_name,
+ CD_TXT,
+ editable ? CD_ISEDITABLE : CD_ISNOTEDITABLE,
+ content
+ );
+ free(short_name);
+ free(full_name);
+ free(content);
+ }
+}
+
static const std::string* helper_get_crash_data_item_content(const map_crash_data_t& crash_data, const char *key)
{
map_crash_data_t::const_iterator it = crash_data.find(key);