Kill download process in abrt-action-install-debuginfo-to-abrt-cache
by Chris Meek
Hi,
Is there a way to kill abrt-action-install-debuginfo-to-abrt-cache
once a download has started? Ctrl-c does not appear to work. It goes
back to the command prompt, but then continues on the next line. Is
there a timeout feature to stop the download if it takes longer than
a specified period of time?
Thanks,
Chris
12 years, 8 months
[PATCH] Rename report to report1 in RHEL6
by Michal Toman
A huge patch that just renames report (binary and python module) to
report1. I tested some features (CLI, Newt, localsave, ftp) and
everything seems to work fine.
M.
12 years, 8 months
[PATCH] reporting from Anaconda textui rhbz#729566
by Jiri Moskovcak
Can't test it with anaconda right now, but I wrote 2 small tests
(located in test/) which anyone willing to test this can use.
Please review (test) asap - this is F16 alpha blocker.
Thank you,
Jirka
12 years, 8 months
[PATCH] rename old report to report1
by Michal Toman
With this patch there are no more file conflicts between libreport and
old report package.
"rpm -ivh report-*" works even with libreport installed, but yum does
not allow installing report and libreport together because of obsoleting
(which is probably correct, just keep this in mind and in documentation
:)).
M.
12 years, 9 months
[PATCH] simple check if directory belongs to abrt
by Nikola Pajkovsky
Signed-off-by: Nikola Pajkovsky <npajkovs(a)redhat.com>
---
src/include/dump_dir.h | 2 ++
src/lib/copy_file_recursive.c | 5 +++++
src/lib/dirsize.c | 12 ++++++++++++
src/lib/dump_dir.c | 32 ++++++++++++++++++++++++++++++++
4 files changed, 51 insertions(+), 0 deletions(-)
diff --git a/src/include/dump_dir.h b/src/include/dump_dir.h
index 6d77a49..e2a4ea8 100644
--- a/src/include/dump_dir.h
+++ b/src/include/dump_dir.h
@@ -92,6 +92,8 @@ report_result_t *find_in_reported_to(struct dump_dir *dd, const char *prefix);
void delete_dump_dir(const char *dirname);
+int is_abrt_dump_dir(const char *path);
+
#ifdef __cplusplus
}
#endif
diff --git a/src/lib/copy_file_recursive.c b/src/lib/copy_file_recursive.c
index 6bad978..54655fd 100644
--- a/src/lib/copy_file_recursive.c
+++ b/src/lib/copy_file_recursive.c
@@ -85,6 +85,11 @@ int copy_file_recursive(const char *source, const char *dest)
if (dot_or_dotdot(d->d_name))
continue;
new_source = concat_path_file(source, d->d_name);
+ if (!is_abrt_dump_dir(new_source))
+ {
+ free(new_source);
+ continue;
+ }
new_dest = concat_path_file(dest, d->d_name);
if (copy_file_recursive(new_source, new_dest) < 0)
retval = -1;
diff --git a/src/lib/dirsize.c b/src/lib/dirsize.c
index 77dc443..67874c5 100644
--- a/src/lib/dirsize.c
+++ b/src/lib/dirsize.c
@@ -32,6 +32,12 @@ double get_dirsize(const char *pPath)
if (dot_or_dotdot(ep->d_name))
continue;
char *dname = concat_path_file(pPath, ep->d_name);
+ if (!is_abrt_dump_dir(dname))
+ {
+ free(dname);
+ continue;
+ }
+
if (lstat(dname, &statbuf) != 0)
{
free(dname);
@@ -72,6 +78,12 @@ double get_dirsize_find_largest_dir(
if (dot_or_dotdot(ep->d_name))
continue;
char *dname = concat_path_file(pPath, ep->d_name);
+ if (!is_abrt_dump_dir(dname))
+ {
+ free(dname);
+ continue;
+ }
+
if (lstat(dname, &statbuf) != 0)
{
free(dname);
diff --git a/src/lib/dump_dir.c b/src/lib/dump_dir.c
index 1f03043..c228fa1 100644
--- a/src/lib/dump_dir.c
+++ b/src/lib/dump_dir.c
@@ -539,6 +539,11 @@ void dd_sanitize_mode_and_owner(struct dump_dir *dd)
if (dent->d_name[0] == '.') /* ".lock", ".", ".."? skip */
continue;
char *full_path = concat_path_file(dd->dd_dirname, dent->d_name);
+ if (!is_abrt_dump_dir(full_path))
+ {
+ free(full_path);
+ continue;
+ }
struct stat statbuf;
if (lstat(full_path, &statbuf) == 0 && S_ISREG(statbuf.st_mode))
{
@@ -587,6 +592,11 @@ static int delete_file_dir(const char *dir, bool skip_lock_file)
continue;
}
char *full_path = concat_path_file(dir, dent->d_name);
+ if (!is_abrt_dump_dir(full_path))
+ {
+ free(full_path);
+ continue;
+ }
if (unlink(full_path) == -1 && errno != ENOENT)
{
int err = 0;
@@ -927,3 +937,25 @@ void delete_dump_dir(const char *dirname)
dd_delete(dd);
}
}
+
+int is_abrt_dump_dir(const char *path)
+{
+ char *analyzer_path = concat_path_file(path, FILENAME_ANALYZER);
+ int fd = open(analyzer_path, O_RDONLY);
+ if (fd < 0)
+ {
+ VERB3 perror_msg("Can't open '%s'", analyzer_path);
+ return 0;
+ }
+
+ struct stat st;
+ if (fstat(fd, &st) != 0 || !S_ISREG(st.st_mode))
+ {
+ VERB3 error_msg("'%s': not a regular file", analyzer_path);
+ close(fd);
+ return 0;
+ }
+
+ free(analyzer_path);
+ return -1;
+}
--
1.7.6.345.g5c2f8
12 years, 9 months
[PATCH] intermediate helper for executing shell code
by Nikola Pajkovsky
Signed-off-by: Nikola Pajkovsky <npajkovs(a)redhat.com>
---
src/daemon/Makefile.am | 16 +++-
src/daemon/abrt-handle-event.c | 186 ++++++++++++++++++++++++++++++++++++
src/daemon/abrtd.c | 207 +++++++++++----------------------------
src/include/abrtlib.h | 13 +++
4 files changed, 273 insertions(+), 149 deletions(-)
create mode 100644 src/daemon/abrt-handle-event.c
diff --git a/src/daemon/Makefile.am b/src/daemon/Makefile.am
index 9770e56..a79669b 100644
--- a/src/daemon/Makefile.am
+++ b/src/daemon/Makefile.am
@@ -11,7 +11,8 @@ bin_PROGRAMS = \
sbin_PROGRAMS = \
abrtd \
- abrt-server
+ abrt-server \
+ abrt-handle-event
abrtd_SOURCES = \
CommLayerServerDBus.h CommLayerServerDBus.c \
@@ -57,6 +58,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..2688740
--- /dev/null
+++ b/src/daemon/abrt-handle-event.c
@@ -0,0 +1,186 @@
+/*
+ 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 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;
+}
+
+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();
+ struct cdump_state state;
+ mw_result_t res = MW_ERROR;
+ const char *dump_dir_name = NULL;
+ while (argv[optind])
+ {
+ res = MW_ERROR;
+ dump_dir_name = argv[optind++];
+
+ struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
+ if (!dd)
+ return MW_ERROR;
+
+ state.uid = dd_load_text(dd, FILENAME_UID);
+ state.uuid = NULL;
+ state.crash_dump_dup_name = NULL;
+ dd_close(dd);
+
+ 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, 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 (!state.crash_dump_dup_name)
+ {
+ /* 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;
+ }
+ }
+ else
+ {
+ dump_dir_name = state.crash_dump_dup_name;
+ }
+
+ log("STATUS: %s", dump_dir_name);
+ }
+
+ return MW_OK;
+
+ret:
+ log("STATUS: %s", dump_dir_name);
+ free(state.uuid);
+ free(state.uid);
+ free(state.crash_dump_dup_name);
+ return res;
+}
diff --git a/src/daemon/abrtd.c b/src/daemon/abrtd.c
index d7b3f0e..9026aab 100644
--- a/src/daemon/abrtd.c
+++ b/src/daemon/abrtd.c
@@ -60,6 +60,7 @@ static GIOChannel *socket_channel = NULL;
static guint socket_channel_cb_id = 0;
static int socket_client_count = 0;
+static int timeout_sec = 60;
/* Helpers */
@@ -242,106 +243,6 @@ static gboolean handle_signal_cb(GIOChannel *gio, GIOCondition condition, gpoint
return TRUE; /* "please don't remove this event" */
}
-
-/* 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);
@@ -357,66 +258,79 @@ static problem_data_t *load_crash_info(const char *dump_dir_name)
return problem_data;
}
-typedef enum {
- MW_OK, /**< No error.*/
- MW_OCCURRED, /**< No error, but thus dump is a dup.*/
- MW_ERROR, /**< Common error.*/
-} mw_result_t;
-
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);
- 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)
+ uid_t uid = xatoi_positive(state.uid);
+
+ char *args[5];
+ args[0] = (char *) "abrt-handle-event";
+ args[1] = (char *) "-e";
+ args[2] = (char *) "post-create";
+ args[3] = (char *) dump_dir_name;
+ args[4] = NULL;
+
+ int pipeout[2];
+ int flags = EXECFLG_INPUT_NUL | EXECFLG_OUTPUT | EXECFLG_QUIET;
+ flags |= EXECFLG_ERR2OUT;
+ VERB1 flags &= ~EXECFLG_QUIET;
+
+ pid_t child = fork_execv_on_steroids(flags, args, pipeout,
+ /*env_vec:*/ NULL, /*dir:*/ NULL, uid);
+
+ int t = time(NULL); /* int is enough, no need to use time_t */
+ int endtime = t + timeout_sec;
+ 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)
+ int timeout = endtime - t;
+ if (timeout < 0)
{
- /* no */
- log("Dump directory '%s' has no UUID element", dump_dir_name);
- goto ret;
+ kill(child, SIGKILL);
+ strbuf_append_strf(buf_out, "\nTimeout exceeded: %u seconds, killing %s\n", timeout_sec, args[0]);
+ break;
}
+
+ /* We don't check poll result - checking read result is enough */
+ struct pollfd pfd;
+ pfd.fd = pipeout[0];
+ pfd.events = POLLIN;
+ poll(&pfd, 1, timeout * 1000);
+
+ 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);
+ t = time(NULL);
+ }
+ close(pipeout[0]);
+
+ /* Prevent having zombie child process */
+ waitpid(child, NULL, 0);
+
+ 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)
+ {
+ if (prefixcmp("STATUS: ", buf_out->buf))
+ dump_dir_name = buf_out->buf + sizeof("STATUS: ");
}
else
{
- dump_dir_name = state.crash_dump_dup_name;
+ if (prefixcmp("STATUS: ", buf_out->buf))
+ dump_dir_name = last_line + sizeof("STATUS: ");
}
/* Loads problem_data (from the *first debugdump dir* if this one is a dup)
@@ -458,11 +372,8 @@ 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;
}
diff --git a/src/include/abrtlib.h b/src/include/abrtlib.h
index 40d88f3..684ae38 100644
--- a/src/include/abrtlib.h
+++ b/src/include/abrtlib.h
@@ -9,6 +9,19 @@
/* libreport's internal functions we use: */
#include <internal_libreport.h>
+typedef enum {
+ MW_OK, /**< No error.*/
+ MW_OCCURRED, /**< No error, but thus dump is a dup.*/
+ MW_ERROR, /**< Common error.*/
+} mw_result_t;
+
+/* We need to share some data between LoadDebugDump and is_crash_a_dup: */
+struct cdump_state {
+ char *uid;
+ char *uuid;
+ char *crash_dump_dup_name;
+};
+
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
--
1.7.6.345.g5c2f8
12 years, 9 months
ABRT1 -> ABRT2 dump conversion tool rhbz#727619
by Jiri Moskovcak
This script converts the data from abrt-db from ABRT1 to equivalent
ABRT2 dump_dir files. It saves following columns:
UUID -> uuid
MESSAGE -> reported_to
COUNT -> count
I will hook it to posttrans in spec file to make it update old abrt dump
dir when user installs abrt2. This should fix 727619. To test it
manually, just install abrt1, crash and report few apps (not from
coreutils ;)) then install abrt2, run this tool and check if everything
reported from ABRT1 is still marked as reported and files reported_to,
uuid and count are created in the old dump_dirs.
Thank you,
Jirka
12 years, 9 months
[PATCH] intermediate helper for executing shell code
by Nikola Pajkovsky
Signed-off-by: Nikola Pajkovsky <npajkovs(a)redhat.com>
---
src/daemon/Makefile.am | 16 +++-
src/daemon/abrt-handle-event.c | 175 ++++++++++++++++++++++++++++++++++
src/daemon/abrtd.c | 202 ++++++++++------------------------------
3 files changed, 240 insertions(+), 153 deletions(-)
create mode 100644 src/daemon/abrt-handle-event.c
diff --git a/src/daemon/Makefile.am b/src/daemon/Makefile.am
index 9770e56..a79669b 100644
--- a/src/daemon/Makefile.am
+++ b/src/daemon/Makefile.am
@@ -11,7 +11,8 @@ bin_PROGRAMS = \
sbin_PROGRAMS = \
abrtd \
- abrt-server
+ abrt-server \
+ abrt-handle-event
abrtd_SOURCES = \
CommLayerServerDBus.h CommLayerServerDBus.c \
@@ -57,6 +58,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..e94e9b3
--- /dev/null
+++ b/src/daemon/abrt-handle-event.c
@@ -0,0 +1,175 @@
+/*
+ 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 state.uuid)
+ */
+ if (!uuid)
+ {
+ /* no */
+ log("Dump directory '%s' has no UUID element", dump_dir_name);
+ return 1;
+ }
+ }
+ else
+ {
+ dump_dir_name = crash_dump_dup_name;
+ }
+
+ log("STATUS: %s", dump_dir_name);
+ }
+
+ return 0;
+}
diff --git a/src/daemon/abrtd.c b/src/daemon/abrtd.c
index d7b3f0e..0033c97 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,59 +268,58 @@ 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 *) "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)
- {
- /* 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;
- }
- }
- else
+ int pipeout[2];
+ int flags = EXECFLG_INPUT_NUL | EXECFLG_OUTPUT | EXECFLG_QUIET | EXECFLG_SETGUID;
+ flags |= EXECFLG_ERR2OUT;
+ 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)
{
- dump_dir_name = state.crash_dump_dup_name;
+ /* We don't check poll result - checking read result is enough */
+ struct pollfd pfd;
+ pfd.fd = pipeout[0];
+ pfd.events = POLLIN;
+ poll(&pfd, 1, -1);
+
+ 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);
}
+ close(pipeout[0]);
+
+ /* Prevent having zombie child process */
+ int status;
+ waitpid(child, &status, 0);
+ status = WEXITSTATUS(status);
+
+ if (buf_out->len == 0 || status != 0)
+ 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 (prefixcmp("STATUS: ", last_line))
+ dump_dir_name = last_line + sizeof("STATUS: ");
/* Loads problem_data (from the *first debugdump dir* if this one is a dup)
* Returns:
@@ -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, 9 months
[PATCH] [abrt] simple check if directory belongs to abrt
by Nikola Pajkovsky
Signed-off-by: Nikola Pajkovsky <npajkovs(a)redhat.com>
---
src/applet/applet.c | 4 ++++
src/cli/abrt-cli-core.c | 4 +++-
src/daemon/abrtd.c | 3 +++
src/gui-gtk/main.c | 3 +++
src/plugins/abrt-action-trim-files.c | 3 +++
5 files changed, 16 insertions(+), 1 deletions(-)
diff --git a/src/applet/applet.c b/src/applet/applet.c
index 75723a1..16214f0 100644
--- a/src/applet/applet.c
+++ b/src/applet/applet.c
@@ -657,6 +657,10 @@ static GList *add_dirs_to_dirlist(GList *dirlist, const char *dirname)
{
if (dot_or_dotdot(dent->d_name))
continue;
+
+ if (!is_abrt_dump_dir(dent->d_name))
+ continue;
+
char *full_name = concat_path_file(dirname, dent->d_name);
struct stat statbuf;
if (lstat(full_name, &statbuf) == 0 && S_ISDIR(statbuf.st_mode))
diff --git a/src/cli/abrt-cli-core.c b/src/cli/abrt-cli-core.c
index 0221f03..e73aa8f 100644
--- a/src/cli/abrt-cli-core.c
+++ b/src/cli/abrt-cli-core.c
@@ -74,8 +74,10 @@ vector_of_problem_data_t *fetch_crash_infos(GList *dir_list)
if (dot_or_dotdot(dent->d_name))
continue; /* skip "." and ".." */
- char *dump_dir_name = concat_path_file(dir_name, dent->d_name);
+ if (!is_abrt_dump_dir(dent->d_name))
+ continue;
+ char *dump_dir_name = concat_path_file(dir_name, dent->d_name);
struct stat statbuf;
if (stat(dump_dir_name, &statbuf) == 0
&& S_ISDIR(statbuf.st_mode))
diff --git a/src/daemon/abrtd.c b/src/daemon/abrtd.c
index d7b3f0e..45f35e0 100644
--- a/src/daemon/abrtd.c
+++ b/src/daemon/abrtd.c
@@ -299,6 +299,9 @@ static int is_crash_a_dup(const char *dump_dir_name, void *param)
if (dot_or_dotdot(dent->d_name))
continue; /* skip "." and ".." */
+ if (!is_abrt_dump_dir(dent->d_name))
+ continue;
+
int different;
char *uid, *uuid;
char *dump_dir_name2 = concat_path_file(g_settings_dump_location, dent->d_name);
diff --git a/src/gui-gtk/main.c b/src/gui-gtk/main.c
index e3b250f..41f1f0f 100644
--- a/src/gui-gtk/main.c
+++ b/src/gui-gtk/main.c
@@ -823,6 +823,9 @@ static void scan_directory_and_add_to_dirlist(const char *path)
if (dot_or_dotdot(dent->d_name))
continue; /* skip "." and ".." */
+ if (!is_abrt_dump_dir(dent->d_name))
+ continue;
+
char *full_name = concat_path_file(path, dent->d_name);
struct stat statbuf;
if (stat(full_name, &statbuf) == 0 && S_ISDIR(statbuf.st_mode))
diff --git a/src/plugins/abrt-action-trim-files.c b/src/plugins/abrt-action-trim-files.c
index 2de0e17..c7c18d9 100644
--- a/src/plugins/abrt-action-trim-files.c
+++ b/src/plugins/abrt-action-trim-files.c
@@ -36,6 +36,9 @@ static double get_dir_size(const char *dirname,
if (dot_or_dotdot(dent->d_name))
continue;
+ if (!is_abrt_dump_dir(dent->d_name))
+ continue;
+
char *fullname = concat_path_file(dirname, dent->d_name);
if (lstat(fullname, &stats) != 0)
{
--
1.7.6.345.g5c2f8
12 years, 9 months