[ABRT EL6 PATCH 1/4] created problem_api - part of rhbz#961231
Jiri Moskovcak
jmoskovc at redhat.com
Fri May 10 10:43:52 UTC 2013
Signed-off-by: Jiri Moskovcak <jmoskovc at redhat.com>
---
po/POTFILES.in | 2 +
src/include/Makefile.am | 3 +-
src/include/problem_api.h | 55 +++++++++++
src/lib/Makefile.am | 3 +-
src/lib/problem_api.c | 240 ++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 301 insertions(+), 2 deletions(-)
create mode 100644 src/include/problem_api.h
create mode 100644 src/lib/problem_api.c
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 9cc76a1..250c1c5 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -11,6 +11,8 @@ src/daemon/abrt-handle-event.c
src/gui-gtk/abrt.desktop.in
src/gui-gtk/main.c
src/lib/abrt_conf.c
+src/lib/hooklib.c
+src/lib/problem_api.c
src/plugins/abrt-action-analyze-backtrace.c
src/plugins/abrt-action-analyze-c.c
src/plugins/abrt-action-analyze-oops.c
diff --git a/src/include/Makefile.am b/src/include/Makefile.am
index c3317d7..6b25ce4 100644
--- a/src/include/Makefile.am
+++ b/src/include/Makefile.am
@@ -2,4 +2,5 @@ libabrt_includedir = \
$(includedir)/abrt
libabrt_include_HEADERS = \
- libabrt.h
+ libabrt.h \
+ problem_api.h
diff --git a/src/include/problem_api.h b/src/include/problem_api.h
new file mode 100644
index 0000000..3b1dfd3
--- /dev/null
+++ b/src/include/problem_api.h
@@ -0,0 +1,55 @@
+/*
+ Copyright (C) ABRT Team
+ Copyright (C) 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 <glib.h>
+#include <libabrt.h>
+
+/*
+ * Structure for simple conditions based on problem fields
+ */
+struct problem_condition
+{
+ /* a name of filed required by evaluate function */
+ const char *field_name;
+ /* extra data passed to evaluate function */
+ const void *args;
+ /* evaluate function returning TRUE if condition was passed */
+ bool (*evaluate)(const char *, const void *);
+};
+
+/* Retrieves the list of directories currently used as a problem storage
+ * The result must be freed by caller
+ * @returns List of strings representing the full path to dirs
+*/
+GList *get_problem_storages();
+GList *get_problem_dirs_for_uid(uid_t uid, const char *dump_location);
+GList *get_problem_dirs_for_element_in_time(uid_t uid,
+ const char *element,
+ const char *value,
+ unsigned long timestamp_from,
+ unsigned long timestamp_to,
+ const char *dump_location);
+
+/* Counts all problems in given directories
+ *
+ * @paths[in] list of paths to scan (pass NULL to use the default problem directories)
+ * @since[in]
+ * @returns count of problems
+ */
+unsigned int get_problems_count(GList *paths, unsigned long since);
\ No newline at end of file
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
index afc106c..5ecb593 100644
--- a/src/lib/Makefile.am
+++ b/src/lib/Makefile.am
@@ -9,7 +9,8 @@ libabrt_la_SOURCES = \
hooklib.c \
daemon_is_ok.c \
kernel.c \
- check_recent_crash_file.c
+ check_recent_crash_file.c \
+ problem_api.c
libabrt_la_CPPFLAGS = \
-Wall -Wwrite-strings -Werror \
diff --git a/src/lib/problem_api.c b/src/lib/problem_api.c
new file mode 100644
index 0000000..b7dad47
--- /dev/null
+++ b/src/lib/problem_api.c
@@ -0,0 +1,240 @@
+/*
+ Copyright (C) ABRT Team
+ Copyright (C) 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 <glib.h>
+#include <sys/time.h>
+#include "problem_api.h"
+
+/*
+ * Evaluates a NULL-terminated list of problem conditions as a logical conjunction
+ */
+static bool problem_condition_evaluate_and(struct dump_dir *dd,
+ const struct problem_condition *const *condition)
+{
+ /* We stop on the first FALSE condition */
+ while (condition && *condition != NULL)
+ {
+ const struct problem_condition *c = *condition;
+ char *field_data = dd_load_text(dd, c->field_name);
+ bool value = c->evaluate(field_data, c->args);
+ free(field_data);
+ if (!value)
+ return false;
+ ++condition;
+ }
+
+ return true;
+}
+
+/*
+ * Goes through all problems and selects only problems accessible by caller_uid and
+ * problems for which an and_filter gets TRUE
+ *
+ * @param condition a NULL-terminated list of problem conditions evaluated
+ * as conjunction, can be NULL (means always TRUE)
+ */
+static GList* scan_directory(const char *path,
+ uid_t caller_uid,
+ const struct problem_condition *const *condition)
+{
+ GList *list = NULL;
+
+ DIR *dp = opendir(path);
+ if (!dp)
+ {
+ /* We don't want to yell if, say, $XDG_CACHE_DIR/abrt/spool doesn't exist */
+ //perror_msg("Can't open directory '%s'", path);
+ return list;
+ }
+
+ struct dirent *dent;
+ while ((dent = readdir(dp)) != NULL)
+ {
+ if (dot_or_dotdot(dent->d_name))
+ continue; /* skip "." and ".." */
+
+ char *full_name = concat_path_file(path, dent->d_name);
+ if (dump_dir_accessible_by_uid(full_name, caller_uid))
+ {
+ /* Silently ignore *any* errors, not only EACCES.
+ * We saw "lock file is locked by process PID" error
+ * when we raced with wizard.
+ */
+ int sv_logmode = logmode;
+ logmode = 0;
+ struct dump_dir *dd = dd_opendir(full_name, DD_OPEN_READONLY | DD_FAIL_QUIETLY_EACCES | DD_DONT_WAIT_FOR_LOCK);
+ logmode = sv_logmode;
+ /* or we could just setuid?
+ - but it would require locking, because we want to setuid back before we server another request..
+ */
+ if (dd)
+ {
+ if (!condition || problem_condition_evaluate_and(dd, condition))
+ {
+ list = g_list_prepend(list, full_name);
+ full_name = NULL;
+ }
+ dd_close(dd); //doesn't fail even if dd == NULL
+ }
+ }
+ free(full_name);
+ }
+ closedir(dp);
+
+ /* Why reverse?
+ * Because N*prepend+reverse is faster than N*append
+ */
+ return g_list_reverse(list);
+}
+
+/* Self explaining time interval structure */
+struct time_interval
+{
+ unsigned long from;
+ unsigned long to;
+};
+
+/*
+ * A problem condition evaluate function for checking of the TIME field against
+ * an allowed interval
+ *
+ * @param field_data a content from the PID field
+ * @param args a pointer to an instance of struct time_interval
+ * @return TRUE if a field value is in a specified interval; otherwise FALSE
+ */
+static bool time_interval_problem_condition(const char *field_data, const void *args)
+{
+ const struct time_interval *const interval = (const struct time_interval *)args;
+ const time_t timestamp = atol(field_data);
+
+ return interval->from <= timestamp && timestamp <= interval->to;
+}
+
+/*
+ * A problem condition evaluate function passed if strings are equal
+ *
+ * @param field_data a content of a field
+ * @param args a checked string
+ * @return TRUE if both strings are equal; otherwise FALSE
+ */
+static bool equal_string_problem_condition(const char *field_data, const void *args)
+{
+ return !strcmp(field_data, (const char *)args);
+}
+
+GList *get_problem_dirs_for_uid(uid_t uid, const char *dump_location)
+{
+ GList *dirs = scan_directory(dump_location, uid, NULL);
+ return dirs;
+}
+
+/*
+ * Finds problems which were created in the interval
+ */
+GList *get_problem_dirs_for_element_in_time(uid_t uid,
+ const char *element,
+ const char *value,
+ unsigned long timestamp_from,
+ unsigned long timestamp_to,
+ const char *dump_location)
+{
+ struct timeval tv;
+ /* use the current time if timestamp_to is 0 */
+ if (timestamp_to == 0) {
+ gettimeofday(&tv, NULL);
+ timestamp_to = tv.tv_sec;
+ }
+
+
+ const struct problem_condition elementc = {
+ .field_name = element,
+ .args = value,
+ .evaluate = equal_string_problem_condition,
+ };
+
+ const struct time_interval interval = {
+ .from = timestamp_from,
+ .to = timestamp_to,
+ };
+
+ const struct problem_condition timec = {
+ .field_name = FILENAME_TIME,
+ .args = &interval,
+ .evaluate = time_interval_problem_condition
+ };
+
+ const struct problem_condition *const condition[] = {
+ &timec,
+ element ? &elementc : NULL,
+ NULL
+ };
+ GList *dirs = scan_directory(dump_location, uid, condition);
+ return dirs;
+}
+
+GList *get_problem_storages()
+{
+ GList *pths = NULL;
+ load_abrt_conf();
+ pths = g_list_append(pths, xstrdup(g_settings_dump_location));
+ //no needed, we don't steal directories anymore
+ pths = g_list_append(pths, concat_path_file(g_get_user_cache_dir(), "abrt/spool"));
+ free_abrt_conf_data();
+
+ return pths;
+}
+
+
+typedef struct problem_count_info {
+ int problem_count;
+ unsigned long since;
+ unsigned long until;
+
+} problem_count_info_t;
+
+static void count_problems_in_dir(char *path, gpointer problem_counter)
+{
+ problem_count_info_t *pci = (problem_count_info_t *)problem_counter;
+ VERB2 log("scanning '%s' for problems since %lu", path, pci->since);
+ GList *problems = get_problem_dirs_for_element_in_time(getuid(), NULL /*don't filter by element*/, NULL, pci->since, pci->until, path);
+ pci->problem_count += g_list_length(problems);
+ list_free_with_free(problems);
+}
+
+unsigned int get_problems_count(GList *paths, unsigned long since)
+{
+ GList *pths = NULL;
+
+ if (paths == NULL)
+ {
+ pths = get_problem_storages();
+ }
+
+ problem_count_info_t pci;
+
+ pci.problem_count = 0;
+ pci.since = since;
+ pci.until = 0;
+
+ g_list_foreach(paths ? paths : pths, (GFunc)count_problems_in_dir, &pci);
+
+ list_free_with_free(pths);
+
+ return pci.problem_count;
+}
\ No newline at end of file
--
1.8.1.4
More information about the Crash-catcher
mailing list