diff options
-rw-r--r-- | inc/crash_types.h | 2 | ||||
-rw-r--r-- | lib/utils/CrashTypes.cpp | 123 | ||||
-rw-r--r-- | src/daemon/MiddleWare.cpp | 123 |
3 files changed, 125 insertions, 123 deletions
diff --git a/inc/crash_types.h b/inc/crash_types.h index d978071a..c89c9a78 100644 --- a/inc/crash_types.h +++ b/inc/crash_types.h @@ -118,6 +118,8 @@ void add_to_crash_data(map_crash_data_t& pCrashData, const char *pItem, const char *pContent); +void load_crash_data_from_debug_dump(struct dump_dir *dd, map_crash_data_t& data); + const char *get_crash_data_item_content_or_NULL(const map_crash_data_t& crash_data, const char *key); // Aborts if key is not found: const std::string& get_crash_data_item_content(const map_crash_data_t& crash_data, const char *key); 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); diff --git a/src/daemon/MiddleWare.cpp b/src/daemon/MiddleWare.cpp index 0bb24634..f499f3b7 100644 --- a/src/daemon/MiddleWare.cpp +++ b/src/daemon/MiddleWare.cpp @@ -54,129 +54,6 @@ static vector_pair_string_string_t s_vectorActionsAndReporters; static void RunAnalyzerActions(const char *pAnalyzer, const char* pPackageName, const char *pDebugDumpDir, int force); -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 */ -} - -static 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); - } -} - /** * Transforms a debugdump directory to inner crash * report form. This form is used for later reporting. |