[PATCH][TESTS] Abrt testsuite
by Richard Marko
Hi,
patch adding beaker testsuite for abrt and its utils (proposed a month
ago by Michal Nowak).
To run the testsuite cd to tests/runtests/, edit your email in
abrt-testing-defs.sh and run abrt-nightly-test.sh.
Note:
* tests are supposed to run under root account in fresh F15
installation (most of the tests should run properly without these
requirements but build/install tests won't);
* email will soon be changed to target this mailing list (when we have
automated beaker reservation solved) and testing will be done on regular
basis.
Richard Marko
12 years, 7 months
[PATCH] new bodhi plugin
by Nikola Pajkovsky
for now bodhi plugin has only two possibilities how to search updates.
1) give bodhi bugzilla id and if bz id is associate to any updates it returns
them, otherwise json-c dies on sigsegv (bug filled, but maybe I'll have to fix it)
2) give bodhi name of the package
Working on: -r, --release (f14, f15, ...); -s, --status (stable, update, pending)
Signed-off-by: Nikola Pajkovsky <npajkovs(a)redhat.com>
---
.gitignore | 1 +
abrt.spec.in | 26 ++++-
configure.ac | 11 ++
src/plugins/Makefile.am | 57 +++++++---
src/plugins/abrt-action-bodhi.c | 241 +++++++++++++++++++++++++++++++++++++++
5 files changed, 319 insertions(+), 17 deletions(-)
create mode 100644 src/plugins/abrt-action-bodhi.c
diff --git a/.gitignore b/.gitignore
index a0c88d8..08df83f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -18,6 +18,7 @@ src/plugins/abrt-action-generate-backtrace
src/plugins/abrt-action-upload
src/plugins/abrt-action-mailx
src/plugins/abrt-action-print
+src/plugins/abrt-action-bodhi
src/plugins/abrt-dump-oops
src/plugins/abrt-action-install-debuginfo-to-abrt-cache
src/plugins/abrt-retrace-client
diff --git a/abrt.spec.in b/abrt.spec.in
index d36a4d3..d8c05de 100644
--- a/abrt.spec.in
+++ b/abrt.spec.in
@@ -38,7 +38,7 @@ BuildRequires: asciidoc
BuildRequires: xmlto
# for rhel6
-%if 0%{?rhel} >= 6
+%if 0%{?rhel}
BuildRequires: gnome-keyring-devel
%else
BuildRequires: libgnome-keyring-devel
@@ -170,6 +170,18 @@ Requires: mailx
The simple reporter plugin which sends a report via mailx to a specified
email address.
+%if 0%{?fedora}
+%package plugin-bodhi
+Summary: %{name}'s bodhi plugin
+BuildRequires: json-c-devel
+Group: System Environment/Libraries
+Requires: %{name} = %{version}-%{release}
+
+%description plugin-bodhi
+Search for a new updates in bodhi
+%endif
+
+
%package plugin-bugzilla
Summary: %{name}'s bugzilla plugin
Group: System Environment/Libraries
@@ -264,7 +276,13 @@ generation service over a network using HTTP protocol.
%build
autoconf
+
+%if 0%{?rhel}
+%configure --disable-bodhi
+%else
%configure
+%endif
+
sed -i 's|^hardcode_libdir_flag_spec=.*|hardcode_libdir_flag_spec=""|g' libtool
sed -i 's|^runpath_var=LD_RUN_PATH|runpath_var=DIE_RPATH_DIE|g' libtool
CFLAGS="-fno-strict-aliasing"
@@ -549,6 +567,12 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || :
%{_bindir}/abrt-action-print
%{_mandir}/man*/abrt-action-print.*
+%if 0%{?fedora}
+%files plugin-bodhi
+%defattr(-,root,root,-)
+%{_bindir}/abrt-action-bodhi
+%endif
+
%files plugin-mailx
%defattr(-,root,root,-)
%{_sysconfdir}/%{name}/events/report_Mailx.xml
diff --git a/configure.ac b/configure.ac
index c568c43..71cff83 100644
--- a/configure.ac
+++ b/configure.ac
@@ -20,6 +20,9 @@ AC_ARG_ENABLE(debug,
[Enable debug information])],
[CFLAGS="$CFLAGS -DDEBUG -ggdb -g"])
+AC_ARG_ENABLE([bodhi],
+ AC_HELP_STRING([--disable-bodhi], [do not use bodhi plugin]))
+
dnl ****** INTERNATIONALIZATION **********************
GETTEXT_PACKAGE=abrt
AC_SUBST(GETTEXT_PACKAGE)
@@ -67,6 +70,14 @@ PKG_CHECK_MODULES([NSS], [nss])
PKG_CHECK_MODULES([XMLRPC], [xmlrpc])
PKG_CHECK_MODULES([XMLRPC_CLIENT], [xmlrpc_client])
PKG_CHECK_MODULES([GNOME_KEYRING], [gnome-keyring-1])
+
+AS_IF([test "x$enable_bodhi" != "xno"], [
+ dnl Do the stuff needed for enabling the feature
+ AC_DEFINE([HAVE_BODHI], [1], [Define if you have bodhi])
+ PKG_CHECK_MODULES([JSON_C], [json])
+])
+AM_CONDITIONAL(HAVE_BODHI, [test "x$enable_bodhi" != "xno"])
+
# Just PKG_CHECK_MODULES([PYTHON], [python]) works only with python2.7+
# Below, if python is not found, we set up for python2.6 w/o checking:
PKG_CHECK_MODULES([PYTHON], [python],,[
diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am
index e3dbcff..903311f 100644
--- a/src/plugins/Makefile.am
+++ b/src/plugins/Makefile.am
@@ -7,22 +7,30 @@ bin_SCRIPTS = \
abrt-action-analyze-core.py \
abrt-action-list-dsos.py
-bin_PROGRAMS = \
- abrt-dump-oops \
- abrt-action-analyze-c \
- abrt-action-analyze-python \
- abrt-action-analyze-oops \
- abrt-action-trim-files \
- abrt-action-generate-backtrace \
- abrt-action-analyze-backtrace \
- abrt-action-bugzilla \
- abrt-action-rhtsupport \
- abrt-action-kerneloops \
- abrt-action-upload \
- abrt-action-mailx \
- abrt-action-print \
- abrt-action-install-debuginfo-to-abrt-cache \
- abrt-retrace-client
+BIN =
+
+BIN += abrt-dump-oops
+BIN += abrt-action-analyze-c
+BIN += abrt-action-analyze-python
+BIN += abrt-action-analyze-oops
+BIN += abrt-action-trim-files
+BIN += abrt-action-generate-backtrace
+BIN += abrt-action-analyze-backtrace
+BIN += abrt-action-bugzilla
+BIN += abrt-action-rhtsupport
+BIN += abrt-action-kerneloops
+BIN += abrt-action-upload
+BIN += abrt-action-mailx
+BIN += abrt-action-print
+
+if HAVE_BODHI
+BIN += abrt-action-bodhi
+endif
+
+BIN += abrt-action-install-debuginfo-to-abrt-cache
+BIN += abrt-retrace-client
+
+bin_PROGRAMS = $(BIN)
pluginsconfdir = $(PLUGINS_CONF_DIR)
@@ -260,6 +268,23 @@ abrt_action_bugzilla_LDADD = \
../lib/libabrt_web.la \
../lib/libreport.la
+if HAVE_BODHI
+abrt_action_bodhi_SOURCES = \
+ abrt-action-bodhi.c
+abrt_action_bodhi_CPPFLAGS = \
+ -I$(srcdir)/../include/report -I$(srcdir)/../include \
+ -I$(srcdir)/../lib \
+ $(GLIB_CFLAGS) \
+ $(JSON_C_CFLAGS) \
+ -D_GNU_SOURCE \
+ -Wall -Wwrite-strings
+abrt_action_bodhi_LDADD = \
+ $(GLIB_LIBS) \
+ $(JSON_C_LIBS) \
+ ../lib/libabrt_web.la \
+ ../lib/libreport.la
+endif
+
abrt_action_rhtsupport_SOURCES = \
abrt_rh_support.h abrt_rh_support.c \
abrt-action-rhtsupport.c
diff --git a/src/plugins/abrt-action-bodhi.c b/src/plugins/abrt-action-bodhi.c
new file mode 100644
index 0000000..0133da7
--- /dev/null
+++ b/src/plugins/abrt-action-bodhi.c
@@ -0,0 +1,241 @@
+/*
+ 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 <json/json.h>
+
+#include "abrtlib.h"
+#include "abrt_curl.h"
+#include "parse_options.h"
+
+//699198,705037,705036
+
+static const char *bodhi_url = "https://admin.fedoraproject.org/updates/%s";
+
+struct bodhi {
+ const char *package_name;
+ const char *date_pushed;
+ int karma;
+
+ GList *bz_ids;
+};
+
+enum bodhi_flags {
+ BODHI_READ_STR,
+ BODHI_READ_INT,
+};
+
+static void free_bodhi_list(GList *bodhi_list)
+{
+ if (!bodhi_list)
+ return;
+
+ for (GList *li = bodhi_list; li; li = li->next)
+ {
+ struct bodhi *b = (struct bodhi *) li->data;
+ list_free_with_free(b->bz_ids);
+ free(b);
+ }
+
+ g_list_free(bodhi_list);
+}
+
+#define bodhi_read_value_int(item, bodhi, json) \
+ do { \
+ json_object *j; \
+ j = json_object_object_get((json), (item)); \
+ if (!j) \
+ error_msg_and_die("'%s' section is not available", (item)); \
+ bodhi = json_object_get_int(j); \
+ break; \
+ } while(0)
+
+#define bodhi_read_value_str(item, bodhi, json) \
+ do { \
+ json_object *j; \
+ j = json_object_object_get((json), (item)); \
+ if (!j) \
+ error_msg_and_die("'%s' section is not available", (item)); \
+ bodhi = json_object_to_json_string(j); \
+ } while(0)
+
+static void print_bodhi(struct bodhi *b)
+{
+ if (b->package_name)
+ printf("'%s'", b->package_name);
+ if (b->date_pushed)
+ printf(" '%s'", b->date_pushed);
+
+ printf(" %i", b->karma);
+
+ for (GList *li = b->bz_ids; li; li = li->next)
+ printf(" %i", *(int*) li->data);
+
+ puts("");
+}
+
+static GList *bodhi_parse_json(json_object *json)
+{
+ json_object *json_num_items = json_object_object_get(json, "num_items");
+ if (!json_num_items)
+ {
+ error_msg("'num_items' is not available");
+ return NULL;
+ }
+
+ int num_items = json_object_get_int(json_num_items);
+ if (num_items <= 0)
+ return NULL;
+
+ json_object *updates = json_object_object_get(json, "updates");
+ if (!updates)
+ {
+ error_msg("'update' section is not available");
+ return NULL;
+ }
+
+ int updates_len = json_object_array_length(updates);
+ VERB1 log("%i updates", updates_len);
+
+ GList *bodhi_list = NULL;
+ for (int i = 0; i < updates_len; ++i)
+ {
+ json_object *updates_item = json_object_array_get_idx(updates, i);
+
+ /* some of item are null */
+ if (!updates_item)
+ continue;
+
+ struct bodhi *b = xzalloc(sizeof(struct bodhi));
+ bodhi_read_value_str("title", b->package_name, updates_item);
+ bodhi_read_value_str("date_pushed", b->date_pushed, updates_item);
+ bodhi_read_value_int("karma", b->karma, updates_item);
+
+ json_object *bugs = json_object_object_get(updates_item, "bugs");
+ if (bugs)
+ {
+ for (int j = 0; j < json_object_array_length(bugs); ++j)
+ {
+ int *bz_id = xmalloc(sizeof(int));
+ json_object *bug_item = json_object_array_get_idx(bugs, j);
+ bodhi_read_value_int("bz_id", *bz_id, bug_item);
+ b->bz_ids = g_list_append(b->bz_ids, bz_id);
+ }
+ }
+
+ bodhi_list = g_list_append(bodhi_list, b);
+
+ VERB1 print_bodhi(b);
+ }
+
+ return bodhi_list;
+}
+
+static int bodhi_query_list(const char *query, const char *package)
+{
+ if (!query && !package)
+ return -1;
+
+ char *bodhi_url_bugs = xasprintf(bodhi_url, "list");
+
+ abrt_post_state_t *post_state = new_abrt_post_state(
+ ABRT_POST_WANT_BODY|ABRT_POST_WANT_SSL_VERIFY);
+
+ const char *headers[] = {
+ "Accept: application/json",
+ NULL
+ };
+
+ struct strbuf *data = strbuf_new();
+
+ if (query)
+ strbuf_append_str(data, query);
+
+ if (package && query)
+ strbuf_append_strf(data, "&package=%s", package);
+ if (package && !query)
+ strbuf_append_strf(data, "package=%s", package);
+
+ VERB1 log("data: %s", data->buf);
+
+ abrt_post_string(post_state, bodhi_url_bugs, "application/x-www-form-urlencoded",
+ headers, data->buf);
+ free(bodhi_url_bugs);
+ strbuf_free(data);
+
+ VERB3 log("%s", post_state->body);
+
+ /* when you try to search in bodhi server bug with number 'ss' (some invalid
+ * number or not associate to any updates, bodhi returns not json answer, but
+ * some html page. Bug filled here https://fedorahosted.org/bodhi/ticket/611
+ *
+ * What is worst is that json_tokener_parse() does not return NULL when
+ * invalid input is passed to function, but returns some rubbish pointer
+ * 0xfffffffffffffffc. Bug filled https://bugzilla.redhat.com/show_bug.cgi?id=709804
+ */
+ json_object *json = json_tokener_parse(post_state->body);
+ if (!json)
+ error_msg_and_die("unable parse response from bodhi server");
+
+ GList *bodhi_list = bodhi_parse_json(json);
+ free_bodhi_list(bodhi_list);
+ json_object_put(json);
+ free_abrt_post_state(post_state);
+
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ abrt_init(argv);
+ enum {
+ OPT_v = 1 << 0,
+ OPT_b = 1 << 1,
+ };
+
+ char *bugs = NULL;
+ /* Keep enum above and order of options below in sync! */
+ struct options program_options[] = {
+ OPT__VERBOSE(&g_verbose),
+ OPT_STRING('b', "bugs", &bugs, "id1[,id2,...]" , _("List of bug ids")),
+ OPT_END()
+ };
+
+ const char *program_usage_string = _(
+ "\b bodhi [-v] [-b] package-name package-name ...\n"
+ "\n"
+ "Search for a new updates in bodhi"
+ );
+
+ unsigned opts = parse_opts(argc, argv, program_options, program_usage_string);
+
+ int status = 0;
+
+ char *query = NULL;
+ if (opts & OPT_b)
+ query = xasprintf("bugs=%s", bugs);
+
+ if (optind < argc)
+ while (optind < argc)
+ status = bodhi_query_list(query, argv[optind++]);
+ else
+ status = bodhi_query_list(query, NULL);
+
+ free(query);
+ return 0;
+}
--
1.7.1
12 years, 7 months
[PATCH] teach bz to attach binary files; bump text file limit from 200k to 500k
by Denys Vlasenko
Compile-tested only.
Please guys, both take a look at this patch.
It should help with this problem:
https://bugzilla.redhat.com/show_bug.cgi?id=733448
--
vda
diff -d -urpN libreport.8/src/lib/problem_data.c libreport.9/src/lib/problem_data.c
--- libreport.8/src/lib/problem_data.c 2011-08-30 13:16:19.778174262 +0200
+++ libreport.9/src/lib/problem_data.c 2011-08-30 16:33:39.447460724 +0200
@@ -236,9 +236,10 @@ static char* is_text_file(const char *na
* So, don't remove this. If you really need to, raise the limit.
*
* Bumped up to 200k: saw 124740 byte /proc/PID/smaps file
+ * Bumped up to 500k: saw 375252 byte anaconda traceback file
*/
off_t size = lseek(fd, 0, SEEK_END);
- if (size < 0 || size > 200*1024)
+ if (size < 0 || size > 500*1024)
{
close(fd);
return NULL; /* it's not a SMALL text */
diff -d -urpN libreport.8/src/plugins/report_Bugzilla.xml.in libreport.9/src/plugins/report_Bugzilla.xml.in
--- libreport.8/src/plugins/report_Bugzilla.xml.in 2011-08-24 15:06:29.000000000 +0200
+++ libreport.9/src/plugins/report_Bugzilla.xml.in 2011-08-30 16:32:03.459040895 +0200
@@ -6,7 +6,7 @@
<requires-items>component,duphash,os_release</requires-items>
<exclude-items-by-default>coredump,count,event_log,reported_to,vmcore</exclude-items-by-default>
<exclude-items-always></exclude-items-always>
- <exclude-binary-items>yes</exclude-binary-items>
+ <exclude-binary-items>no</exclude-binary-items>
<include-items-by-default></include-items-by-default>
<minimal-rating>3</minimal-rating>
diff -d -urpN libreport.8/src/plugins/reporter-bugzilla.c libreport.9/src/plugins/reporter-bugzilla.c
--- libreport.8/src/plugins/reporter-bugzilla.c 2011-08-30 12:48:10.557751346 +0200
+++ libreport.9/src/plugins/reporter-bugzilla.c 2011-08-30 16:27:25.875934263 +0200
@@ -113,7 +113,7 @@ static void report_to_bugzilla(const cha
char bug_id_str[sizeof(int)*3 + 2];
sprintf(bug_id_str, "%i", bug_id);
- rhbz_attachments(client, bug_id_str, problem_data, RHBZ_NOMAIL_NOTIFY);
+ rhbz_attach_big_files(client, bug_id_str, problem_data, RHBZ_NOMAIL_NOTIFY);
bz = new_bug_info();
bz->bi_status = xstrdup("NEW");
@@ -354,29 +354,8 @@ int main(int argc, char **argv)
continue;
}
- off_t size = lseek(fd, 0, SEEK_END);
- if (size < 0)
- {
- perror_msg("Can't lseek '%s'", filename);
- close(fd);
- continue;
- }
- lseek(fd, 0, SEEK_SET);
-
- /* FIXME: what if the file is tens of gigabytes? */
- char *data = xmalloc(size + 1);
- ssize_t r = full_read(fd, data, size);
- if (r < 0)
- {
- free(data);
- perror_msg("Can't read '%s'", filename);
- close(fd);
- continue;
- }
+ rhbz_attach_fd(client, filename, ticket_no, fd, /*flags*/ 0);
close(fd);
-
- rhbz_attachment(client, filename, ticket_no, data, r, /*flags*/ 0);
- free(data);
}
log(_("Logging out"));
diff -d -urpN libreport.8/src/plugins/rhbz.c libreport.9/src/plugins/rhbz.c
--- libreport.8/src/plugins/rhbz.c 2011-08-30 12:51:35.665963066 +0200
+++ libreport.9/src/plugins/rhbz.c 2011-08-30 16:37:58.825900264 +0200
@@ -380,7 +380,7 @@ int rhbz_new_bug(struct abrt_xmlrpc *ax,
}
/* suppress mail notify by {s:i} (nomail:1) (driven by flag) */
-int rhbz_attachment(struct abrt_xmlrpc *ax, const char *filename,
+int rhbz_attach_blob(struct abrt_xmlrpc *ax, const char *filename,
const char *bug_id, const char *data, int data_len, int flags)
{
char *encoded64 = encode_base64(data, data_len);
@@ -406,8 +406,38 @@ int rhbz_attachment(struct abrt_xmlrpc *
return 0;
}
+int rhbz_attach_fd(struct abrt_xmlrpc *ax, const char *filename,
+ const char *bug_id, int fd, int flags)
+{
+ off_t size = lseek(fd, 0, SEEK_END);
+ if (size < 0)
+ {
+ perror_msg("Can't lseek '%s'", filename);
+ return -1;
+ }
+ if (size > INT_MAX / 2)
+ {
+ error_msg("Can't upload '%s', it's too large (%llu bytes)", filename, (long long)size);
+ return -1;
+ }
+ lseek(fd, 0, SEEK_SET);
+
+ char *data = xmalloc(size + 1);
+ ssize_t r = full_read(fd, data, size);
+ if (r < 0)
+ {
+ free(data);
+ perror_msg("Can't read '%s'", filename);
+ return -1;
+ }
+
+ int res = rhbz_attach_blob(ax, filename, bug_id, data, size, flags);
+ free(data);
+ return res;
+}
+
/* suppress mail notify by {s:i} (nomail:1) (driven by flag) */
-int rhbz_attachments(struct abrt_xmlrpc *ax, const char *bug_id,
+int rhbz_attach_big_files(struct abrt_xmlrpc *ax, const char *bug_id,
problem_data_t *problem_data, int flags)
{
GHashTableIter iter;
@@ -427,9 +457,27 @@ int rhbz_attachments(struct abrt_xmlrpc
/* This text item wasn't added in comments, it is too big
* for that. Attach it as a file.
*/
- rhbz_attachment(ax, name, bug_id, content, len, flags);
+ rhbz_attach_blob(ax, name, bug_id, content, len, flags);
}
}
+ if (value->flags & CD_FLAG_BIN)
+ {
+ int fd = open(value->content, O_RDONLY);
+ if (fd < 0)
+ {
+ perror_msg("Can't open '%s'", value->content);
+ continue;
+ }
+ struct stat st;
+ if (fstat(fd, &st) != 0 || !S_ISREG(st.st_mode))
+ {
+ error_msg("'%s': not a regular file", value->content);
+ close(fd);
+ continue;
+ }
+ rhbz_attach_fd(ax, name, bug_id, fd, flags);
+ close(fd);
+ }
}
return 0;
diff -d -urpN libreport.8/src/plugins/rhbz.h libreport.9/src/plugins/rhbz.h
--- libreport.8/src/plugins/rhbz.h 2011-08-30 12:48:17.626745937 +0200
+++ libreport.9/src/plugins/rhbz.h 2011-08-30 16:23:00.450020115 +0200
@@ -82,12 +82,15 @@ int rhbz_bug_id(xmlrpc_value *xml);
int rhbz_new_bug(struct abrt_xmlrpc *ax, problem_data_t *problem_data,
int depend_on_bug);
-int rhbz_attachments(struct abrt_xmlrpc *ax, const char *bug_id,
+int rhbz_attach_big_files(struct abrt_xmlrpc *ax, const char *bug_id,
problem_data_t *problem_data, int flags);
-int rhbz_attachment(struct abrt_xmlrpc *ax, const char *filename,
+int rhbz_attach_blob(struct abrt_xmlrpc *ax, const char *filename,
const char *bug_id, const char *data, int data_len, int flags);
+int rhbz_attach_fd(struct abrt_xmlrpc *ax, const char *filename,
+ const char *bug_id, int fd, int flags);
+
GList *rhbz_bug_cc(xmlrpc_value *result_xml);
struct bug_info *rhbz_bug_info(struct abrt_xmlrpc *ax, int bug_id);
12 years, 8 months
[PATCH] support shell glob patterns in .xml item selectors
by Denys Vlasenko
We used to support "*" only. Example:
<requires-items>backtrace</requires-items>
<exclude-items-by-default/>
<exclude-items-always>*</exclude-items-always>
<exclude-binary-items>yes</exclude-binary-items>
<include-items-by-default/>
<minimal-rating>0</minimal-rating>
The patch below adds support for patterns like *.txt, abc*
As a consequence, special-casing code is removed.
Please review.
--
vda
diff -d -urpN libreport.7/src/gui-wizard-gtk/wizard.c libreport.8/src/gui-wizard-gtk/wizard.c
--- libreport.7/src/gui-wizard-gtk/wizard.c 2011-08-24 15:06:29.000000000 +0200
+++ libreport.8/src/gui-wizard-gtk/wizard.c 2011-08-30 13:58:49.400468290 +0200
@@ -1846,18 +1846,6 @@ static void on_page_prepare(GtkAssistant
/* Based on selected reporter, update item checkboxes */
event_config_t *cfg = get_event_config(g_reporter_events_selected ? g_reporter_events_selected : "");
//log("%s: event:'%s', cfg:'%p'", __func__, g_reporter_events_selected, cfg);
- int allowed_by_reporter = 1;
- int default_by_reporter = 1;
- if (cfg)
- {
- /* Default settings are... */
- if (cfg->ec_exclude_items_always && strcmp(cfg->ec_exclude_items_always, "*") == 0)
- allowed_by_reporter = 0;
- default_by_reporter = allowed_by_reporter;
- if (cfg->ec_exclude_items_by_default && strcmp(cfg->ec_exclude_items_by_default, "*") == 0)
- default_by_reporter = 0;
- }
-
GHashTableIter iter;
char *name;
struct problem_item *item;
@@ -1865,28 +1853,28 @@ static void on_page_prepare(GtkAssistant
while (g_hash_table_iter_next(&iter, (void**)&name, (void**)&item))
{
/* Decide whether item is allowed, required, and what's the default */
- item->allowed_by_reporter = allowed_by_reporter;
+ item->allowed_by_reporter = 1;
if (cfg)
{
- if (is_in_comma_separated_list(name, cfg->ec_exclude_items_always))
+ if (is_in_comma_separated_list_of_glob_patterns(name, cfg->ec_exclude_items_always))
item->allowed_by_reporter = 0;
if ((item->flags & CD_FLAG_BIN) && cfg->ec_exclude_binary_items)
item->allowed_by_reporter = 0;
}
- item->default_by_reporter = item->allowed_by_reporter ? default_by_reporter : 0;
+ item->default_by_reporter = item->allowed_by_reporter;
if (cfg)
{
- if (is_in_comma_separated_list(name, cfg->ec_exclude_items_by_default))
+ if (is_in_comma_separated_list_of_glob_patterns(name, cfg->ec_exclude_items_by_default))
item->default_by_reporter = 0;
- if (is_in_comma_separated_list(name, cfg->ec_include_items_by_default))
+ if (is_in_comma_separated_list_of_glob_patterns(name, cfg->ec_include_items_by_default))
item->allowed_by_reporter = item->default_by_reporter = 1;
}
item->required_by_reporter = 0;
if (cfg)
{
- if (is_in_comma_separated_list(name, cfg->ec_requires_items))
+ if (is_in_comma_separated_list_of_glob_patterns(name, cfg->ec_requires_items))
item->default_by_reporter = item->allowed_by_reporter = item->required_by_reporter = 1;
}
diff -d -urpN libreport.7/src/include/internal_libreport.h libreport.8/src/include/internal_libreport.h
--- libreport.7/src/include/internal_libreport.h 2011-08-24 15:06:29.000000000 +0200
+++ libreport.8/src/include/internal_libreport.h 2011-08-30 13:53:57.868782976 +0200
@@ -236,6 +236,8 @@ bool is_in_string_list(const char *name,
#define is_in_comma_separated_list libreport_is_in_comma_separated_list
bool is_in_comma_separated_list(const char *value, const char *list);
+#define is_in_comma_separated_list_of_glob_patterns libreport_is_in_comma_separated_list_of_glob_patterns
+bool is_in_comma_separated_list_of_glob_patterns(const char *value, const char *list);
/* Frees every element'd data using free(),
* then frees list itself using g_list_free(list):
diff -d -urpN libreport.7/src/lib/is_in_comma_separated_list.c libreport.8/src/lib/is_in_comma_separated_list.c
--- libreport.7/src/lib/is_in_comma_separated_list.c 2011-08-24 15:06:29.000000000 +0200
+++ libreport.8/src/lib/is_in_comma_separated_list.c 2011-08-30 14:01:43.781111205 +0200
@@ -16,6 +16,7 @@
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
+#include <fnmatch.h>
#include "internal_libreport.h"
bool is_in_comma_separated_list(const char *value, const char *list)
@@ -34,3 +35,22 @@ bool is_in_comma_separated_list(const ch
}
return false;
}
+
+bool is_in_comma_separated_list_of_glob_patterns(const char *value, const char *list)
+{
+ if (!list)
+ return false;
+ while (*list)
+ {
+ const char *comma = strchrnul(list, ',');
+ char *pattern = xstrndup(list, comma - list);
+ int match = !fnmatch(pattern, value, /*flags:*/ 0);
+ free(pattern);
+ if (match)
+ return true;
+ if (!*comma)
+ break;
+ list = comma + 1;
+ }
+ return false;
+}
diff -d -urpN libreport.7/src/lib/problem_data.c libreport.8/src/lib/problem_data.c
--- libreport.7/src/lib/problem_data.c 2011-08-24 15:06:29.000000000 +0200
+++ libreport.8/src/lib/problem_data.c 2011-08-30 13:16:19.778174262 +0200
@@ -433,10 +433,10 @@ static char **build_exclude_vector(const
problem_data_t *create_problem_data_for_reporting(const char *dump_dir_name)
{
- char **exclude_items = build_exclude_vector(getenv("EXCLUDE_FROM_REPORT"));
struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
if (!dd)
return NULL; /* dd_opendir already emitted error msg */
+ char **exclude_items = build_exclude_vector(getenv("EXCLUDE_FROM_REPORT"));
problem_data_t *problem_data = new_problem_data();
load_problem_data_from_dump_dir(problem_data, dd, exclude_items);
dd_close(dd);
12 years, 8 months
[PATCH] retrace-client: handle supported_formats and supported_releases
by Michal Toman
Retrace server's /settings action outputs following:
running_tasks 0
max_running_tasks 5
max_packed_size 50
max_unpacked_size 1024
supported_formats application/x-tar application/x-xz-compressed-tar
application/x-gzip
supported_releases fedora-16-i386 fedora-15-x86_64 fedora-15-i386
fedora-16-x86_64
but the current retrace-client only handles numeric values. This patch
enables format and release verification.
Please review
M.
12 years, 8 months
[PATCH] intermediate helper for executing shell code
by Nikola Pajkovsky
Signed-off-by: Nikola Pajkovsky <npajkovs(a)redhat.com>
---
abrt.spec.in | 1 +
src/daemon/Makefile.am | 15 +++
src/daemon/abrt-handle-event.c | 176 +++++++++++++++++++++++++++++++++++
src/daemon/abrtd.c | 198 ++++++++++------------------------------
4 files changed, 240 insertions(+), 150 deletions(-)
create mode 100644 src/daemon/abrt-handle-event.c
diff --git a/abrt.spec.in b/abrt.spec.in
index f7f2971..709715b 100644
--- a/abrt.spec.in
+++ b/abrt.spec.in
@@ -372,6 +372,7 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || :
%endif
%{_sbindir}/abrtd
%{_sbindir}/abrt-server
+%{_libexecdir}/abrt-handle-event
%{_bindir}/abrt-handle-upload
%{_bindir}/abrt-action-save-package-data
%config(noreplace) %{_sysconfdir}/%{name}/abrt.conf
diff --git a/src/daemon/Makefile.am b/src/daemon/Makefile.am
index 5e02936..391b547 100644
--- a/src/daemon/Makefile.am
+++ b/src/daemon/Makefile.am
@@ -13,6 +13,8 @@ sbin_PROGRAMS = \
abrtd \
abrt-server
+libexec_PROGRAMS = abrt-handle-event
+
abrtd_SOURCES = \
CommLayerServerDBus.h CommLayerServerDBus.c \
comm_layer_inner.h comm_layer_inner.c \
@@ -57,6 +59,19 @@ abrt_server_LDADD = \
../lib/libabrt.la \
$(LIBREPORT_LIBS)
+abrt_handle_event_SOURCES = \
+ abrt-handle-event.c
+abrt_handle_event_CPPFLAGS = \
+ -I$(srcdir)/../include \
+ -I$(srcdir)/../lib \
+ $(GLIB_CFLAGS) \
+ $(LIBREPORT_CFLAGS) \
+ -D_GNU_SOURCE \
+ -Wall -Wwrite-strings -Werror
+abrt_handle_event_LDADD = \
+ ../lib/libabrt.la \
+ $(LIBREPORT_LIBS)
+
abrt_action_save_package_data_SOURCES = \
rpm.h rpm.c \
abrt-action-save-package-data.c
diff --git a/src/daemon/abrt-handle-event.c b/src/daemon/abrt-handle-event.c
new file mode 100644
index 0000000..5ba3d95
--- /dev/null
+++ b/src/daemon/abrt-handle-event.c
@@ -0,0 +1,176 @@
+/*
+ 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"
+#include "run_event.h"
+
+static char *uid = NULL;
+static char *uuid = NULL;
+static char *crash_dump_dup_name = NULL;
+
+static int is_crash_a_dup(const char *dump_dir_name, void *param)
+{
+ if (uuid)
+ return 0; /* we already checked it, don't do it again */
+
+ struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
+ if (!dd)
+ return 0; /* wtf? (error, but will be handled elsewhere later) */
+ uuid = dd_load_text_ext(dd, FILENAME_UUID,
+ DD_FAIL_QUIETLY_ENOENT + DD_LOAD_TEXT_RETURN_NULL_ON_FAILURE
+ );
+ dd_close(dd);
+ if (!uuid)
+ return 0; /* no uuid (yet), "run_event, please continue iterating" */
+
+ /* Scan crash dumps looking for a dup */
+//TODO: explain why this is safe wrt concurrent runs
+ DIR *dir = opendir(g_settings_dump_location);
+ if (dir != NULL)
+ {
+ struct dirent *dent;
+ while ((dent = readdir(dir)) != NULL)
+ {
+ if (dot_or_dotdot(dent->d_name))
+ continue; /* skip "." and ".." */
+
+ int different;
+ char *dd_uid, *dd_uuid;
+ char *dump_dir_name2 = concat_path_file(g_settings_dump_location, dent->d_name);
+
+ if (strcmp(dump_dir_name, dump_dir_name2) == 0)
+ goto next; /* we are never a dup of ourself */
+
+ dd = dd_opendir(dump_dir_name2, /*flags:*/ DD_FAIL_QUIETLY_ENOENT);
+ if (!dd)
+ goto next;
+ dd_uid = dd_load_text(dd, FILENAME_UID);
+ dd_uuid = dd_load_text(dd, FILENAME_UUID);
+ dd_close(dd);
+ different = strcmp(uid, dd_uid) || strcmp(uuid, dd_uuid);
+ free(dd_uid);
+ free(dd_uuid);
+ if (different)
+ goto next;
+
+ crash_dump_dup_name = dump_dir_name2;
+ /* "run_event, please stop iterating": */
+ return 1;
+
+ next:
+ free(dump_dir_name2);
+ }
+ closedir(dir);
+ }
+
+ /* No dup found */
+ return 0; /* "run_event, please continue iterating" */
+}
+
+static char *do_log(char *log_line, void *param)
+{
+ /* We pipe output of post-create events to our log (which usually
+ * includes syslog). Otherwise, errors on post-create result in
+ * "Corrupted or bad dump DIR, deleting" without adequate explanation why.
+ */
+ log("%s", log_line);
+ return log_line;
+}
+
+int main(int argc, char **argv)
+{
+ abrt_init(argv);
+
+ const char *program_usage_string = _(
+ "\b [-v] -e|--event EVENT DUMP_DIR [DUMP_DIR]..."
+ );
+
+ char *event_name = NULL;
+ struct options program_options[] = {
+ OPT__VERBOSE(&g_verbose),
+ OPT_GROUP(""),
+ OPT_STRING('e', "event" , &event_name, "EVENT", _("Run EVENT on DUMP_DIR")),
+ OPT_END()
+ };
+
+ parse_opts(argc, argv, program_options, program_usage_string);
+ if (!argv[optind] || !event_name)
+ show_usage_and_die(program_usage_string, program_options);
+
+ load_abrt_conf();
+
+ const char *dump_dir_name = NULL;
+ while (argv[optind])
+ {
+ dump_dir_name = argv[optind++];
+
+ struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
+ if (!dd)
+ return 1;
+
+ uid = dd_load_text(dd, FILENAME_UID);
+ dd_close(dd);
+
+ struct run_event_state *run_state = new_run_event_state();
+ if (strcmp(event_name, "post-create") == 0)
+ run_state->post_run_callback = is_crash_a_dup;
+ run_state->logging_callback = do_log;
+ int r = run_event_on_dir_name(run_state, dump_dir_name, event_name);
+ if (r == 0 && run_state->children_count == 0)
+ error_msg_and_die("No actions are found for event '%s'", event_name);
+ free_run_event_state(run_state);
+
+//TODO: consider this case:
+// new dump is created, post-create detects that it is a dup,
+// but then load_crash_info(dup_name) *FAILS*.
+// In this case, we later delete damaged dup_name (right?)
+// but new dump never gets its FILENAME_COUNT set!
+
+ /* Is crash a dup? (In this case, is_crash_a_dup() should have
+ * aborted "post-create" event processing as soon as it saw uuid
+ * and determined that there is another crash with same uuid.
+ * In this case it sets state.crash_dump_dup_name)
+ */
+ if (!crash_dump_dup_name)
+ {
+ /* No. Was there error on one of processing steps in run_event? */
+ if (r != 0)
+ return r; /* yes */
+
+ /* Was uuid created after all? (In this case, is_crash_a_dup()
+ * should have fetched it and created uuid)
+ */
+ if (!uuid)
+ {
+ /* no */
+ printf("Dump directory '%s' has no UUID element\n", dump_dir_name);
+ return 1;
+ }
+ }
+ else
+ {
+ printf("DUP_OF_DIR: %s\n", crash_dump_dup_name);
+ free(crash_dump_dup_name);
+ return 1;
+ }
+ }
+
+ /* exit 0 means, that there is no duplicate of dump-dir*/
+ return 0;
+}
diff --git a/src/daemon/abrtd.c b/src/daemon/abrtd.c
index 6d77f18..48dd93e 100644
--- a/src/daemon/abrtd.c
+++ b/src/daemon/abrtd.c
@@ -245,103 +245,6 @@ static gboolean handle_signal_cb(GIOChannel *gio, GIOCondition condition, gpoint
/* Inotify handler */
-/* helpers first */
-
-struct logging_state {
- char *last_line;
-};
-
-static char *do_log_and_save_line(char *log_line, void *param)
-{
- struct logging_state *l_state = (struct logging_state *)param;
-
- VERB1 log("%s", log_line);
- update_client("%s", log_line);
- free(l_state->last_line);
- l_state->last_line = log_line;
- return NULL;
-}
-
-/* We need to share some data between LoadDebugDump and is_crash_a_dup: */
-struct cdump_state {
- char *uid; /* filled by LoadDebugDump */
- char *uuid; /* filled by is_crash_a_dup */
- char *crash_dump_dup_name; /* filled by is_crash_a_dup */
-};
-
-static int is_crash_a_dup(const char *dump_dir_name, void *param)
-{
- struct cdump_state *state = (struct cdump_state *)param;
-
- if (state->uuid)
- return 0; /* we already checked it, don't do it again */
-
- struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
- if (!dd)
- return 0; /* wtf? (error, but will be handled elsewhere later) */
- state->uuid = dd_load_text_ext(dd, FILENAME_UUID,
- DD_FAIL_QUIETLY_ENOENT + DD_LOAD_TEXT_RETURN_NULL_ON_FAILURE
- );
- dd_close(dd);
- if (!state->uuid)
- {
- return 0; /* no uuid (yet), "run_event, please continue iterating" */
- }
-
- /* Scan crash dumps looking for a dup */
-//TODO: explain why this is safe wrt concurrent runs
- DIR *dir = opendir(g_settings_dump_location);
- if (dir != NULL)
- {
- struct dirent *dent;
- while ((dent = readdir(dir)) != NULL)
- {
- if (dot_or_dotdot(dent->d_name))
- continue; /* skip "." and ".." */
-
- int different;
- char *uid, *uuid;
- char *dump_dir_name2 = concat_path_file(g_settings_dump_location, dent->d_name);
-
- if (strcmp(dump_dir_name, dump_dir_name2) == 0)
- goto next; /* we are never a dup of ourself */
-
- dd = dd_opendir(dump_dir_name2, /*flags:*/ DD_FAIL_QUIETLY_ENOENT);
- if (!dd)
- goto next;
- uid = dd_load_text(dd, FILENAME_UID);
- uuid = dd_load_text(dd, FILENAME_UUID);
- dd_close(dd);
- different = strcmp(state->uid, uid) || strcmp(state->uuid, uuid);
- free(uid);
- free(uuid);
- if (different)
- goto next;
-
- state->crash_dump_dup_name = dump_dir_name2;
- /* "run_event, please stop iterating": */
- return 1;
-
- next:
- free(dump_dir_name2);
- }
- closedir(dir);
- }
-
- /* No dup found */
- return 0; /* "run_event, please continue iterating" */
-}
-
-static char *do_log(char *log_line, void *param)
-{
- /* We pipe output of post-create events to our log (which usually
- * includes syslog). Otherwise, errors on post-create result in
- * "Corrupted or bad dump DIR, deleting" without adequate explanation why.
- */
- log("%s", log_line);
- return log_line;
-}
-
static problem_data_t *load_crash_info(const char *dump_dir_name)
{
struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
@@ -365,58 +268,57 @@ typedef enum {
static mw_result_t LoadDebugDump(const char *dump_dir_name, problem_data_t **problem_data)
{
- mw_result_t res;
-
- struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
- if (!dd)
- return MW_ERROR;
- struct cdump_state state;
- state.uid = dd_load_text(dd, FILENAME_UID);
- state.uuid = NULL;
- state.crash_dump_dup_name = NULL;
- char *analyzer = dd_load_text(dd, FILENAME_ANALYZER);
- dd_close(dd);
-
- res = MW_ERROR;
-
- /* Run post-create event handler(s) */
- struct run_event_state *run_state = new_run_event_state();
- run_state->post_run_callback = is_crash_a_dup;
- run_state->post_run_param = &state;
- run_state->logging_callback = do_log;
- int r = run_event_on_dir_name(run_state, dump_dir_name, "post-create");
- free_run_event_state(run_state);
-
-//TODO: consider this case:
-// new dump is created, post-create detects that it is a dup,
-// but then load_crash_info(dup_name) *FAILS*.
-// In this case, we later delete damaged dup_name (right?)
-// but new dump never gets its FILENAME_COUNT set!
-
- /* Is crash a dup? (In this case, is_crash_a_dup() should have
- * aborted "post-create" event processing as soon as it saw uuid
- * and determined that there is another crash with same uuid.
- * In this case it sets state.crash_dump_dup_name)
- */
- if (!state.crash_dump_dup_name)
+ mw_result_t res = MW_ERROR;
+
+ char *args[6];
+ args[0] = (char *) "/usr/libexec/abrt-handle-event";
+ args[1] = (char *) "-e";
+ args[2] = (char *) "post-create";
+ args[3] = (char *) "--";
+ args[4] = (char *) dump_dir_name;
+ args[5] = NULL;
+
+ int pipeout[2];
+ int flags = EXECFLG_INPUT_NUL | EXECFLG_OUTPUT | EXECFLG_QUIET | EXECFLG_ERR2OUT;
+ VERB1 flags &= ~EXECFLG_QUIET;
+
+ pid_t child = fork_execv_on_steroids(flags, args, pipeout,
+ /*env_vec:*/ NULL, /*dir:*/ NULL, 0);
+
+ FILE *fp = fdopen(pipeout[0], "r");
+ if (!fp)
+ die_out_of_memory();
+
+ char *buf;
+ struct strbuf *dup_of_dir = strbuf_new();
+ while ((buf = xmalloc_fgetline(fp)) != NULL)
{
- /* No. Was there error on one of processing steps in run_event? */
- if (r != 0)
- goto ret; /* yes */
-
- /* Was uuid created after all? (In this case, is_crash_a_dup()
- * should have fetched it and created state.uuid)
- */
- if (!state.uuid)
+ log("%s", buf);
+
+ if (strncmp("DUP_OF_DIR: ", buf, strlen("DUP_OF_DIR: ")) == 0)
{
- /* no */
- log("Dump directory '%s' has no UUID element", dump_dir_name);
- goto ret;
+ strbuf_append_str(dup_of_dir, buf + strlen("DUP_OF_DIR: "));
+ while (dup_of_dir->len != 0 && dup_of_dir->buf[dup_of_dir->len - 1] == '\n')
+ dup_of_dir->buf[--dup_of_dir->len] = '\0';
}
+
+ free(buf);
}
- else
+ fclose(fp);
+ close(pipeout[0]);
+
+ /* Prevent having zombie child process */
+ int status;
+ waitpid(child, &status, 0);
+ status = WEXITSTATUS(status);
+
+ /* exit 0 means, this is a good, non-dup dir */
+ if (status != 0)
{
- dump_dir_name = state.crash_dump_dup_name;
+ if (dup_of_dir->len)
+ dump_dir_name = dup_of_dir->buf;
+ else
+ return MW_ERROR;
}
/* Loads problem_data (from the *first debugdump dir* if this one is a dup)
@@ -426,7 +328,7 @@ static mw_result_t LoadDebugDump(const char *dump_dir_name, problem_data_t **pro
* else: an error code
*/
{
- dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
+ struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
if (!dd)
{
res = MW_ERROR;
@@ -458,11 +360,7 @@ static mw_result_t LoadDebugDump(const char *dump_dir_name, problem_data_t **pro
}
ret:
- free(state.uuid);
- free(state.uid);
- free(state.crash_dump_dup_name);
- free(analyzer);
-
+ strbuf_free(dup_of_dir);
return res;
}
--
1.7.6.557.gcee4
12 years, 8 months
[PATCH] intermediate helper for executing shell code
by Nikola Pajkovsky
Signed-off-by: Nikola Pajkovsky <npajkovs(a)redhat.com>
---
abrt.spec.in | 1 +
src/daemon/Makefile.am | 15 +++
src/daemon/abrt-handle-event.c | 176 +++++++++++++++++++++++++++++++++++
src/daemon/abrtd.c | 200 ++++++++++------------------------------
4 files changed, 241 insertions(+), 151 deletions(-)
create mode 100644 src/daemon/abrt-handle-event.c
diff --git a/abrt.spec.in b/abrt.spec.in
index f7f2971..709715b 100644
--- a/abrt.spec.in
+++ b/abrt.spec.in
@@ -372,6 +372,7 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || :
%endif
%{_sbindir}/abrtd
%{_sbindir}/abrt-server
+%{_libexecdir}/abrt-handle-event
%{_bindir}/abrt-handle-upload
%{_bindir}/abrt-action-save-package-data
%config(noreplace) %{_sysconfdir}/%{name}/abrt.conf
diff --git a/src/daemon/Makefile.am b/src/daemon/Makefile.am
index 5e02936..391b547 100644
--- a/src/daemon/Makefile.am
+++ b/src/daemon/Makefile.am
@@ -13,6 +13,8 @@ sbin_PROGRAMS = \
abrtd \
abrt-server
+libexec_PROGRAMS = abrt-handle-event
+
abrtd_SOURCES = \
CommLayerServerDBus.h CommLayerServerDBus.c \
comm_layer_inner.h comm_layer_inner.c \
@@ -57,6 +59,19 @@ abrt_server_LDADD = \
../lib/libabrt.la \
$(LIBREPORT_LIBS)
+abrt_handle_event_SOURCES = \
+ abrt-handle-event.c
+abrt_handle_event_CPPFLAGS = \
+ -I$(srcdir)/../include \
+ -I$(srcdir)/../lib \
+ $(GLIB_CFLAGS) \
+ $(LIBREPORT_CFLAGS) \
+ -D_GNU_SOURCE \
+ -Wall -Wwrite-strings -Werror
+abrt_handle_event_LDADD = \
+ ../lib/libabrt.la \
+ $(LIBREPORT_LIBS)
+
abrt_action_save_package_data_SOURCES = \
rpm.h rpm.c \
abrt-action-save-package-data.c
diff --git a/src/daemon/abrt-handle-event.c b/src/daemon/abrt-handle-event.c
new file mode 100644
index 0000000..d258ec7
--- /dev/null
+++ b/src/daemon/abrt-handle-event.c
@@ -0,0 +1,176 @@
+/*
+ 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"
+#include "run_event.h"
+
+static char *uid = NULL;
+static char *uuid = NULL;
+static char *crash_dump_dup_name = NULL;
+
+static int is_crash_a_dup(const char *dump_dir_name, void *param)
+{
+ if (uuid)
+ return 0; /* we already checked it, don't do it again */
+
+ struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
+ if (!dd)
+ return 0; /* wtf? (error, but will be handled elsewhere later) */
+ uuid = dd_load_text_ext(dd, FILENAME_UUID,
+ DD_FAIL_QUIETLY_ENOENT + DD_LOAD_TEXT_RETURN_NULL_ON_FAILURE
+ );
+ dd_close(dd);
+ if (!uuid)
+ return 0; /* no uuid (yet), "run_event, please continue iterating" */
+
+ /* Scan crash dumps looking for a dup */
+//TODO: explain why this is safe wrt concurrent runs
+ DIR *dir = opendir(g_settings_dump_location);
+ if (dir != NULL)
+ {
+ struct dirent *dent;
+ while ((dent = readdir(dir)) != NULL)
+ {
+ if (dot_or_dotdot(dent->d_name))
+ continue; /* skip "." and ".." */
+
+ int different;
+ char *dd_uid, *dd_uuid;
+ char *dump_dir_name2 = concat_path_file(g_settings_dump_location, dent->d_name);
+
+ if (strcmp(dump_dir_name, dump_dir_name2) == 0)
+ goto next; /* we are never a dup of ourself */
+
+ dd = dd_opendir(dump_dir_name2, /*flags:*/ DD_FAIL_QUIETLY_ENOENT);
+ if (!dd)
+ goto next;
+ dd_uid = dd_load_text(dd, FILENAME_UID);
+ dd_uuid = dd_load_text(dd, FILENAME_UUID);
+ dd_close(dd);
+ different = strcmp(uid, dd_uid) || strcmp(uuid, dd_uuid);
+ free(dd_uid);
+ free(dd_uuid);
+ if (different)
+ goto next;
+
+ crash_dump_dup_name = dump_dir_name2;
+ /* "run_event, please stop iterating": */
+ return 1;
+
+ next:
+ free(dump_dir_name2);
+ }
+ closedir(dir);
+ }
+
+ /* No dup found */
+ return 0; /* "run_event, please continue iterating" */
+}
+
+static char *do_log(char *log_line, void *param)
+{
+ /* We pipe output of post-create events to our log (which usually
+ * includes syslog). Otherwise, errors on post-create result in
+ * "Corrupted or bad dump DIR, deleting" without adequate explanation why.
+ */
+ log("%s", log_line);
+ return log_line;
+}
+
+int main(int argc, const char **argv)
+{
+ abrt_init((char **)argv);
+
+ const char *program_usage_string = _(
+ "\b [-v] -e|--event EVENT DUMP_DIR [DUMP_DIR]..."
+ );
+
+ char *event_name = NULL;
+ struct options program_options[] = {
+ OPT__VERBOSE(&g_verbose),
+ OPT_GROUP(""),
+ OPT_STRING('e', "event" , &event_name, "EVENT", _("Run EVENT on DUMP_DIR")),
+ OPT_END()
+ };
+
+ parse_opts(argc, (char **)argv, program_options, program_usage_string);
+ if (!argv[optind] || !event_name)
+ show_usage_and_die(program_usage_string, program_options);
+
+ load_abrt_conf();
+
+ const char *dump_dir_name = NULL;
+ while (argv[optind])
+ {
+ dump_dir_name = argv[optind++];
+
+ struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
+ if (!dd)
+ return 1;
+
+ uid = dd_load_text(dd, FILENAME_UID);
+ dd_close(dd);
+
+ struct run_event_state *run_state = new_run_event_state();
+ if (strcmp(event_name, "post-create") == 0)
+ run_state->post_run_callback = is_crash_a_dup;
+ run_state->logging_callback = do_log;
+ int r = run_event_on_dir_name(run_state, dump_dir_name, event_name);
+ if (r == 0 && run_state->children_count == 0)
+ error_msg_and_die("No actions are found for event '%s'", event_name);
+ free_run_event_state(run_state);
+
+//TODO: consider this case:
+// new dump is created, post-create detects that it is a dup,
+// but then load_crash_info(dup_name) *FAILS*.
+// In this case, we later delete damaged dup_name (right?)
+// but new dump never gets its FILENAME_COUNT set!
+
+ /* Is crash a dup? (In this case, is_crash_a_dup() should have
+ * aborted "post-create" event processing as soon as it saw uuid
+ * and determined that there is another crash with same uuid.
+ * In this case it sets state.crash_dump_dup_name)
+ */
+ if (!crash_dump_dup_name)
+ {
+ /* No. Was there error on one of processing steps in run_event? */
+ if (r != 0)
+ return r; /* yes */
+
+ /* Was uuid created after all? (In this case, is_crash_a_dup()
+ * should have fetched it and created uuid)
+ */
+ if (!uuid)
+ {
+ /* no */
+ printf("Dump directory '%s' has no UUID element\n", dump_dir_name);
+ return 1;
+ }
+ }
+ else
+ {
+ printf("DUP_OF_DIR: %s\n", crash_dump_dup_name);
+ free(crash_dump_dup_name);
+ return 1;
+ }
+ }
+
+ /* exit 0 means, that there is no duplicate of dump-dir*/
+ return 0;
+}
diff --git a/src/daemon/abrtd.c b/src/daemon/abrtd.c
index 6d77f18..bb034c6 100644
--- a/src/daemon/abrtd.c
+++ b/src/daemon/abrtd.c
@@ -245,103 +245,6 @@ static gboolean handle_signal_cb(GIOChannel *gio, GIOCondition condition, gpoint
/* Inotify handler */
-/* helpers first */
-
-struct logging_state {
- char *last_line;
-};
-
-static char *do_log_and_save_line(char *log_line, void *param)
-{
- struct logging_state *l_state = (struct logging_state *)param;
-
- VERB1 log("%s", log_line);
- update_client("%s", log_line);
- free(l_state->last_line);
- l_state->last_line = log_line;
- return NULL;
-}
-
-/* We need to share some data between LoadDebugDump and is_crash_a_dup: */
-struct cdump_state {
- char *uid; /* filled by LoadDebugDump */
- char *uuid; /* filled by is_crash_a_dup */
- char *crash_dump_dup_name; /* filled by is_crash_a_dup */
-};
-
-static int is_crash_a_dup(const char *dump_dir_name, void *param)
-{
- struct cdump_state *state = (struct cdump_state *)param;
-
- if (state->uuid)
- return 0; /* we already checked it, don't do it again */
-
- struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
- if (!dd)
- return 0; /* wtf? (error, but will be handled elsewhere later) */
- state->uuid = dd_load_text_ext(dd, FILENAME_UUID,
- DD_FAIL_QUIETLY_ENOENT + DD_LOAD_TEXT_RETURN_NULL_ON_FAILURE
- );
- dd_close(dd);
- if (!state->uuid)
- {
- return 0; /* no uuid (yet), "run_event, please continue iterating" */
- }
-
- /* Scan crash dumps looking for a dup */
-//TODO: explain why this is safe wrt concurrent runs
- DIR *dir = opendir(g_settings_dump_location);
- if (dir != NULL)
- {
- struct dirent *dent;
- while ((dent = readdir(dir)) != NULL)
- {
- if (dot_or_dotdot(dent->d_name))
- continue; /* skip "." and ".." */
-
- int different;
- char *uid, *uuid;
- char *dump_dir_name2 = concat_path_file(g_settings_dump_location, dent->d_name);
-
- if (strcmp(dump_dir_name, dump_dir_name2) == 0)
- goto next; /* we are never a dup of ourself */
-
- dd = dd_opendir(dump_dir_name2, /*flags:*/ DD_FAIL_QUIETLY_ENOENT);
- if (!dd)
- goto next;
- uid = dd_load_text(dd, FILENAME_UID);
- uuid = dd_load_text(dd, FILENAME_UUID);
- dd_close(dd);
- different = strcmp(state->uid, uid) || strcmp(state->uuid, uuid);
- free(uid);
- free(uuid);
- if (different)
- goto next;
-
- state->crash_dump_dup_name = dump_dir_name2;
- /* "run_event, please stop iterating": */
- return 1;
-
- next:
- free(dump_dir_name2);
- }
- closedir(dir);
- }
-
- /* No dup found */
- return 0; /* "run_event, please continue iterating" */
-}
-
-static char *do_log(char *log_line, void *param)
-{
- /* We pipe output of post-create events to our log (which usually
- * includes syslog). Otherwise, errors on post-create result in
- * "Corrupted or bad dump DIR, deleting" without adequate explanation why.
- */
- log("%s", log_line);
- return log_line;
-}
-
static problem_data_t *load_crash_info(const char *dump_dir_name)
{
struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
@@ -365,60 +268,59 @@ typedef enum {
static mw_result_t LoadDebugDump(const char *dump_dir_name, problem_data_t **problem_data)
{
- mw_result_t res;
+ mw_result_t res = MW_ERROR;
- struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
- if (!dd)
- return MW_ERROR;
- struct cdump_state state;
- state.uid = dd_load_text(dd, FILENAME_UID);
- state.uuid = NULL;
- state.crash_dump_dup_name = NULL;
- char *analyzer = dd_load_text(dd, FILENAME_ANALYZER);
- dd_close(dd);
+ char *args[5];
+ args[0] = (char *) "/usr/libexec/abrt-handle-event";
+ args[1] = (char *) "-e";
+ args[2] = (char *) "post-create";
+ args[3] = (char *) dump_dir_name;
+ args[4] = NULL;
- res = MW_ERROR;
-
- /* Run post-create event handler(s) */
- struct run_event_state *run_state = new_run_event_state();
- run_state->post_run_callback = is_crash_a_dup;
- run_state->post_run_param = &state;
- run_state->logging_callback = do_log;
- int r = run_event_on_dir_name(run_state, dump_dir_name, "post-create");
- free_run_event_state(run_state);
-
-//TODO: consider this case:
-// new dump is created, post-create detects that it is a dup,
-// but then load_crash_info(dup_name) *FAILS*.
-// In this case, we later delete damaged dup_name (right?)
-// but new dump never gets its FILENAME_COUNT set!
-
- /* Is crash a dup? (In this case, is_crash_a_dup() should have
- * aborted "post-create" event processing as soon as it saw uuid
- * and determined that there is another crash with same uuid.
- * In this case it sets state.crash_dump_dup_name)
- */
- if (!state.crash_dump_dup_name)
+ int pipeout[2];
+ int flags = EXECFLG_INPUT_NUL | EXECFLG_OUTPUT | EXECFLG_QUIET;
+ VERB1 flags &= ~EXECFLG_QUIET;
+
+ pid_t child = fork_execv_on_steroids(flags, args, pipeout,
+ /*env_vec:*/ NULL, /*dir:*/ NULL, 0);
+
+ struct strbuf *buf_out = strbuf_new();
+ while (1)
{
- /* No. Was there error on one of processing steps in run_event? */
- if (r != 0)
- goto ret; /* yes */
-
- /* Was uuid created after all? (In this case, is_crash_a_dup()
- * should have fetched it and created state.uuid)
- */
- if (!state.uuid)
- {
- /* no */
- log("Dump directory '%s' has no UUID element", dump_dir_name);
- goto ret;
- }
+ char buff[1024];
+ int r = read(pipeout[0], buff, sizeof(buff) - 1);
+ if (r <= 0)
+ break;
+ buff[r] = '\0';
+ strbuf_append_str(buf_out, buff);
}
- else
+ close(pipeout[0]);
+
+ /* Prevent having zombie child process */
+ int status;
+ waitpid(child, &status, 0);
+ status = WEXITSTATUS(status);
+
+ /* exit 0 means, this is a good, non-dup dir */
+ if (status != 0)
{
- dump_dir_name = state.crash_dump_dup_name;
- }
+ while (buf_out->len != 0 && buf_out->buf[buf_out->len - 1] == '\n')
+ buf_out->buf[--buf_out->len] = '\0';
+
+ char *last_line = strrchr(buf_out->buf, '\n');
+ if (!last_line)
+ last_line = buf_out->buf;
+ if (strncmp("DUP_OF_DIR: ", last_line, strlen("DUP_OF_DIR: ")) == 0)
+ {
+ dump_dir_name = last_line + strlen("DUP_OF_DIR: ");
+ }
+ else /* no DUP_OF_DIR */
+ {
+ strbuf_free(buf_out);
+ return MW_ERROR;
+ }
+ }
/* Loads problem_data (from the *first debugdump dir* if this one is a dup)
* Returns:
* MW_OCCURRED: "crash count is != 1" (iow: it is > 1 - dup)
@@ -426,7 +328,7 @@ static mw_result_t LoadDebugDump(const char *dump_dir_name, problem_data_t **pro
* else: an error code
*/
{
- dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
+ struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
if (!dd)
{
res = MW_ERROR;
@@ -458,11 +360,7 @@ static mw_result_t LoadDebugDump(const char *dump_dir_name, problem_data_t **pro
}
ret:
- free(state.uuid);
- free(state.uid);
- free(state.crash_dump_dup_name);
- free(analyzer);
-
+ strbuf_free(buf_out);
return res;
}
--
1.7.6.345.g5c2f8
12 years, 8 months
[PATCH-abrt] intermediate helper for executing shell code
by Nikola Pajkovsky
Signed-off-by: Nikola Pajkovsky <npajkovs(a)redhat.com>
---
abrt.spec.in | 1 +
src/daemon/Makefile.am | 15 +++
src/daemon/abrt-handle-event.c | 176 ++++++++++++++++++++++++++++++++++
src/daemon/abrtd.c | 207 +++++++++++-----------------------------
4 files changed, 248 insertions(+), 151 deletions(-)
create mode 100644 src/daemon/abrt-handle-event.c
diff --git a/abrt.spec.in b/abrt.spec.in
index e605dea..5b4f23f 100644
--- a/abrt.spec.in
+++ b/abrt.spec.in
@@ -372,6 +372,7 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || :
%endif
%{_sbindir}/abrtd
%{_sbindir}/abrt-server
+%{_libexecdir}/abrt-handle-event
%{_bindir}/abrt-handle-upload
%{_bindir}/abrt-action-save-package-data
%config(noreplace) %{_sysconfdir}/%{name}/abrt.conf
diff --git a/src/daemon/Makefile.am b/src/daemon/Makefile.am
index 9770e56..faaccdd 100644
--- a/src/daemon/Makefile.am
+++ b/src/daemon/Makefile.am
@@ -13,6 +13,8 @@ sbin_PROGRAMS = \
abrtd \
abrt-server
+libexec_PROGRAMS = abrt-handle-event
+
abrtd_SOURCES = \
CommLayerServerDBus.h CommLayerServerDBus.c \
comm_layer_inner.h comm_layer_inner.c \
@@ -57,6 +59,19 @@ abrt_server_LDADD = \
../lib/libabrt.la \
$(LIBREPORT_LIBS)
+abrt_handle_event_SOURCES = \
+ abrt-handle-event.c
+abrt_handle_event_CPPFLAGS = \
+ -I$(srcdir)/../include \
+ -I$(srcdir)/../lib \
+ $(GLIB_CFLAGS) \
+ $(LIBREPORT_CFLAGS) \
+ -D_GNU_SOURCE \
+ -Wall -Wwrite-strings -Werror
+abrt_handle_event_LDADD = \
+ ../lib/libabrt.la \
+ $(LIBREPORT_LIBS)
+
abrt_action_save_package_data_SOURCES = \
rpm.h rpm.c \
abrt-action-save-package-data.c
diff --git a/src/daemon/abrt-handle-event.c b/src/daemon/abrt-handle-event.c
new file mode 100644
index 0000000..809e0e9
--- /dev/null
+++ b/src/daemon/abrt-handle-event.c
@@ -0,0 +1,176 @@
+/*
+ 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"
+#include "run_event.h"
+
+static char *uid = NULL;
+static char *uuid = NULL;
+static char *crash_dump_dup_name = NULL;
+
+static int is_crash_a_dup(const char *dump_dir_name, void *param)
+{
+ if (uuid)
+ return 0; /* we already checked it, don't do it again */
+
+ struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
+ if (!dd)
+ return 0; /* wtf? (error, but will be handled elsewhere later) */
+ uuid = dd_load_text_ext(dd, FILENAME_UUID,
+ DD_FAIL_QUIETLY_ENOENT + DD_LOAD_TEXT_RETURN_NULL_ON_FAILURE
+ );
+ dd_close(dd);
+ if (!uuid)
+ return 0; /* no uuid (yet), "run_event, please continue iterating" */
+
+ /* Scan crash dumps looking for a dup */
+//TODO: explain why this is safe wrt concurrent runs
+ DIR *dir = opendir(g_settings_dump_location);
+ if (dir != NULL)
+ {
+ struct dirent *dent;
+ while ((dent = readdir(dir)) != NULL)
+ {
+ if (dot_or_dotdot(dent->d_name))
+ continue; /* skip "." and ".." */
+
+ int different;
+ char *dd_uid, *dd_uuid;
+ char *dump_dir_name2 = concat_path_file(g_settings_dump_location, dent->d_name);
+
+ if (strcmp(dump_dir_name, dump_dir_name2) == 0)
+ goto next; /* we are never a dup of ourself */
+
+ dd = dd_opendir(dump_dir_name2, /*flags:*/ DD_FAIL_QUIETLY_ENOENT);
+ if (!dd)
+ goto next;
+ dd_uid = dd_load_text(dd, FILENAME_UID);
+ dd_uuid = dd_load_text(dd, FILENAME_UUID);
+ dd_close(dd);
+ different = strcmp(uid, dd_uid) || strcmp(uuid, dd_uuid);
+ free(dd_uid);
+ free(dd_uuid);
+ if (different)
+ goto next;
+
+ crash_dump_dup_name = dump_dir_name2;
+ /* "run_event, please stop iterating": */
+ return 1;
+
+ next:
+ free(dump_dir_name2);
+ }
+ closedir(dir);
+ }
+
+ /* No dup found */
+ return 0; /* "run_event, please continue iterating" */
+}
+
+static char *do_log(char *log_line, void *param)
+{
+ /* We pipe output of post-create events to our log (which usually
+ * includes syslog). Otherwise, errors on post-create result in
+ * "Corrupted or bad dump DIR, deleting" without adequate explanation why.
+ */
+ log("%s", log_line);
+ return log_line;
+}
+
+int main(int argc, const char **argv)
+{
+ abrt_init((char **)argv);
+
+ const char *program_usage_string = _(
+ "\b [-v] -e|--event EVENT DUMP_DIR [DUMP_DIR]..."
+ );
+
+ char *event_name = NULL;
+ struct options program_options[] = {
+ OPT__VERBOSE(&g_verbose),
+ OPT_GROUP(""),
+ OPT_STRING('e', "event" , &event_name, "EVENT", _("Run EVENT on DUMP_DIR")),
+ OPT_END()
+ };
+
+ parse_opts(argc, (char **)argv, program_options, program_usage_string);
+ if (!argv[optind] || !event_name)
+ show_usage_and_die(program_usage_string, program_options);
+
+ load_abrt_conf();
+
+ const char *dump_dir_name = NULL;
+ while (argv[optind])
+ {
+ dump_dir_name = argv[optind++];
+
+ struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
+ if (!dd)
+ return 1;
+
+ uid = dd_load_text(dd, FILENAME_UID);
+ dd_close(dd);
+
+ struct run_event_state *run_state = new_run_event_state();
+ if (strcmp(event_name, "post-create") == 0)
+ run_state->post_run_callback = is_crash_a_dup;
+ run_state->logging_callback = do_log;
+ int r = run_event_on_dir_name(run_state, dump_dir_name, event_name);
+ if (r == 0 && run_state->children_count == 0)
+ error_msg_and_die("No actions are found for event '%s'", event_name);
+ free_run_event_state(run_state);
+
+//TODO: consider this case:
+// new dump is created, post-create detects that it is a dup,
+// but then load_crash_info(dup_name) *FAILS*.
+// In this case, we later delete damaged dup_name (right?)
+// but new dump never gets its FILENAME_COUNT set!
+
+ /* Is crash a dup? (In this case, is_crash_a_dup() should have
+ * aborted "post-create" event processing as soon as it saw uuid
+ * and determined that there is another crash with same uuid.
+ * In this case it sets state.crash_dump_dup_name)
+ */
+ if (!crash_dump_dup_name)
+ {
+ /* No. Was there error on one of processing steps in run_event? */
+ if (r != 0)
+ return r; /* yes */
+
+ /* Was uuid created after all? (In this case, is_crash_a_dup()
+ * should have fetched it and created uuid)
+ */
+ if (!uuid)
+ {
+ /* no */
+ fprintf(stdout, "Dump directory '%s' has no UUID element", dump_dir_name);
+ return 1;
+ }
+ }
+ else
+ {
+ fprintf(stdout, "DUP_OF_DIR: %s", crash_dump_dup_name);
+ free(crash_dump_dup_name);
+ return 1;
+ }
+ }
+
+ /* exit 0 means, that there is no duplicate of dump-dir*/
+ return 0;
+}
diff --git a/src/daemon/abrtd.c b/src/daemon/abrtd.c
index 5d93426..1badfe1 100644
--- a/src/daemon/abrtd.c
+++ b/src/daemon/abrtd.c
@@ -245,103 +245,6 @@ static gboolean handle_signal_cb(GIOChannel *gio, GIOCondition condition, gpoint
/* Inotify handler */
-/* helpers first */
-
-struct logging_state {
- char *last_line;
-};
-
-static char *do_log_and_save_line(char *log_line, void *param)
-{
- struct logging_state *l_state = (struct logging_state *)param;
-
- VERB1 log("%s", log_line);
- update_client("%s", log_line);
- free(l_state->last_line);
- l_state->last_line = log_line;
- return NULL;
-}
-
-/* We need to share some data between LoadDebugDump and is_crash_a_dup: */
-struct cdump_state {
- char *uid; /* filled by LoadDebugDump */
- char *uuid; /* filled by is_crash_a_dup */
- char *crash_dump_dup_name; /* filled by is_crash_a_dup */
-};
-
-static int is_crash_a_dup(const char *dump_dir_name, void *param)
-{
- struct cdump_state *state = (struct cdump_state *)param;
-
- if (state->uuid)
- return 0; /* we already checked it, don't do it again */
-
- struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
- if (!dd)
- return 0; /* wtf? (error, but will be handled elsewhere later) */
- state->uuid = dd_load_text_ext(dd, FILENAME_UUID,
- DD_FAIL_QUIETLY_ENOENT + DD_LOAD_TEXT_RETURN_NULL_ON_FAILURE
- );
- dd_close(dd);
- if (!state->uuid)
- {
- return 0; /* no uuid (yet), "run_event, please continue iterating" */
- }
-
- /* Scan crash dumps looking for a dup */
-//TODO: explain why this is safe wrt concurrent runs
- DIR *dir = opendir(g_settings_dump_location);
- if (dir != NULL)
- {
- struct dirent *dent;
- while ((dent = readdir(dir)) != NULL)
- {
- if (dot_or_dotdot(dent->d_name))
- continue; /* skip "." and ".." */
-
- int different;
- char *uid, *uuid;
- char *dump_dir_name2 = concat_path_file(g_settings_dump_location, dent->d_name);
-
- if (strcmp(dump_dir_name, dump_dir_name2) == 0)
- goto next; /* we are never a dup of ourself */
-
- dd = dd_opendir(dump_dir_name2, /*flags:*/ DD_FAIL_QUIETLY_ENOENT);
- if (!dd)
- goto next;
- uid = dd_load_text(dd, FILENAME_UID);
- uuid = dd_load_text(dd, FILENAME_UUID);
- dd_close(dd);
- different = strcmp(state->uid, uid) || strcmp(state->uuid, uuid);
- free(uid);
- free(uuid);
- if (different)
- goto next;
-
- state->crash_dump_dup_name = dump_dir_name2;
- /* "run_event, please stop iterating": */
- return 1;
-
- next:
- free(dump_dir_name2);
- }
- closedir(dir);
- }
-
- /* No dup found */
- return 0; /* "run_event, please continue iterating" */
-}
-
-static char *do_log(char *log_line, void *param)
-{
- /* We pipe output of post-create events to our log (which usually
- * includes syslog). Otherwise, errors on post-create result in
- * "Corrupted or bad dump DIR, deleting" without adequate explanation why.
- */
- log("%s", log_line);
- return log_line;
-}
-
static problem_data_t *load_crash_info(const char *dump_dir_name)
{
struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
@@ -365,60 +268,66 @@ typedef enum {
static mw_result_t LoadDebugDump(const char *dump_dir_name, problem_data_t **problem_data)
{
- mw_result_t res;
+ mw_result_t res = MW_ERROR;
- struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
- if (!dd)
- return MW_ERROR;
- struct cdump_state state;
- state.uid = dd_load_text(dd, FILENAME_UID);
- state.uuid = NULL;
- state.crash_dump_dup_name = NULL;
- char *analyzer = dd_load_text(dd, FILENAME_ANALYZER);
- dd_close(dd);
+ char *args[5];
+ args[0] = (char *) "/usr/libexec/abrt-handle-event";
+ args[1] = (char *) "-e";
+ args[2] = (char *) "post-create";
+ args[3] = (char *) dump_dir_name;
+ args[4] = NULL;
- res = MW_ERROR;
-
- /* Run post-create event handler(s) */
- struct run_event_state *run_state = new_run_event_state();
- run_state->post_run_callback = is_crash_a_dup;
- run_state->post_run_param = &state;
- run_state->logging_callback = do_log;
- int r = run_event_on_dir_name(run_state, dump_dir_name, "post-create");
- free_run_event_state(run_state);
-
-//TODO: consider this case:
-// new dump is created, post-create detects that it is a dup,
-// but then load_crash_info(dup_name) *FAILS*.
-// In this case, we later delete damaged dup_name (right?)
-// but new dump never gets its FILENAME_COUNT set!
-
- /* Is crash a dup? (In this case, is_crash_a_dup() should have
- * aborted "post-create" event processing as soon as it saw uuid
- * and determined that there is another crash with same uuid.
- * In this case it sets state.crash_dump_dup_name)
- */
- if (!state.crash_dump_dup_name)
+ int pipeout[2];
+ int flags = EXECFLG_INPUT_NUL | EXECFLG_OUTPUT | EXECFLG_QUIET;
+ VERB1 flags &= ~EXECFLG_QUIET;
+
+ pid_t child = fork_execv_on_steroids(flags, args, pipeout,
+ /*env_vec:*/ NULL, /*dir:*/ NULL, 0);
+
+ struct strbuf *buf_out = strbuf_new();
+ while (1)
{
- /* No. Was there error on one of processing steps in run_event? */
- if (r != 0)
- goto ret; /* yes */
-
- /* Was uuid created after all? (In this case, is_crash_a_dup()
- * should have fetched it and created state.uuid)
- */
- if (!state.uuid)
- {
- /* no */
- log("Dump directory '%s' has no UUID element", dump_dir_name);
- goto ret;
- }
+ char buff[1024];
+ int r = read(pipeout[0], buff, sizeof(buff) - 1);
+ if (r <= 0)
+ break;
+ buff[r] = '\0';
+ strbuf_append_str(buf_out, buff);
}
- else
+ close(pipeout[0]);
+
+ /* Prevent having zombie child process */
+ int status;
+ waitpid(child, &status, 0);
+ status = WEXITSTATUS(status);
+
+ /* exit 0 means, this is a good, non-dup dir */
+ if (status != 0)
{
- dump_dir_name = state.crash_dump_dup_name;
- }
+ /* exit != 0 and empty buffer means error processing in run_event */
+ if (buf_out->len == 0)
+ {
+ strbuf_free(buf_out);
+ return MW_ERROR;
+ }
+
+ if (buf_out->buf[buf_out->len - 1] == '\n')
+ buf_out->buf[buf_out->len - 1] = '\0';
+
+ char *last_line = strrchr(buf_out->buf, '\n');
+ if (!last_line)
+ last_line = buf_out->buf;
+ if (strncmp("DUP_OF_DIR: ", last_line, strlen("DUP_OF_DIR")) == 0)
+ {
+ dump_dir_name = last_line + strlen("DUP_OF_DIR: ");
+ }
+ else /* no DUP_OF_DIR */
+ {
+ strbuf_free(buf_out);
+ return MW_ERROR;
+ }
+ }
/* Loads problem_data (from the *first debugdump dir* if this one is a dup)
* Returns:
* MW_OCCURRED: "crash count is != 1" (iow: it is > 1 - dup)
@@ -426,7 +335,7 @@ static mw_result_t LoadDebugDump(const char *dump_dir_name, problem_data_t **pro
* else: an error code
*/
{
- dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
+ struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
if (!dd)
{
res = MW_ERROR;
@@ -458,11 +367,7 @@ static mw_result_t LoadDebugDump(const char *dump_dir_name, problem_data_t **pro
}
ret:
- free(state.uuid);
- free(state.uid);
- free(state.crash_dump_dup_name);
- free(analyzer);
-
+ strbuf_free(buf_out);
return res;
}
--
1.7.6.345.g5c2f8
12 years, 8 months