summaryrefslogtreecommitdiffstats
path: root/src/daemon
diff options
context:
space:
mode:
authorDenys Vlasenko <dvlasenk@redhat.com>2010-11-23 15:51:54 +0100
committerDenys Vlasenko <dvlasenk@redhat.com>2010-11-23 15:51:54 +0100
commit86fc61db75385d6fb452b4cf88aec1deffa3a5be (patch)
tree8b88bd46ef8fe05167f72b3d1f0bff034620b9a1 /src/daemon
parentd992b91c61b4da10e1f977038d85cd640f8d7ae5 (diff)
downloadabrt-86fc61db75385d6fb452b4cf88aec1deffa3a5be.tar.gz
abrt-86fc61db75385d6fb452b4cf88aec1deffa3a5be.tar.xz
abrt-86fc61db75385d6fb452b4cf88aec1deffa3a5be.zip
remove sqlite DB
This change removes sqlite database. Database was used to find dump dirs by [UID:]UUID. This patch uses more natural way: dump dirs are addressed by their directory names. DB was also used to produce a list of dump dirs. Now it is done by iterating over the /var/spool/abrt directory. And finally, DB was also used to find duplicate UUIDs. Now it is done by iterating over the /var/spool/abrt directory. Crash count, "inform all" and reporting result message are moved from DB field to a file in dump dir. "Reported" DB field is deleted - if message != "", then this dump was reported. Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
Diffstat (limited to 'src/daemon')
-rw-r--r--src/daemon/Daemon.cpp111
-rw-r--r--src/daemon/MiddleWare.cpp524
-rw-r--r--src/daemon/MiddleWare.h24
-rw-r--r--src/daemon/PluginManager.cpp14
-rw-r--r--src/daemon/PluginManager.h7
-rw-r--r--src/daemon/Settings.cpp15
-rw-r--r--src/daemon/Settings.h1
-rw-r--r--src/daemon/abrt-server.c2
-rw-r--r--src/daemon/abrt.conf4
-rw-r--r--src/daemon/abrt.conf.55
-rw-r--r--src/daemon/abrt_event.conf2
11 files changed, 268 insertions, 441 deletions
diff --git a/src/daemon/Daemon.cpp b/src/daemon/Daemon.cpp
index b25be6f9..225a7372 100644
--- a/src/daemon/Daemon.cpp
+++ b/src/daemon/Daemon.cpp
@@ -360,86 +360,6 @@ static int SetUpCron()
return 0;
}
-static void FindNewDumps(const char* pPath)
-{
- /* Get all debugdump directories in the pPath directory */
- GList *dirs = NULL;
- DIR *dp = opendir(pPath);
- if (dp == NULL)
- {
- perror_msg("Can't open directory '%s'", pPath);
- return;
- }
- struct dirent *ep;
- while ((ep = readdir(dp)))
- {
- if (dot_or_dotdot(ep->d_name))
- continue; /* skip "." and ".." */
- char *dname = concat_path_file(pPath, ep->d_name);
- struct stat stats;
- if (lstat(dname, &stats) == 0)
- {
- if (S_ISDIR(stats.st_mode))
- {
- VERB1 log("Will check directory '%s'", ep->d_name);
- dirs = g_list_append(dirs, dname);
- continue;
- }
- }
- free(dname);
- }
- closedir(dp);
-
- unsigned size = g_list_length(dirs);
- if (size == 0)
- return;
- log("Checking for unsaved crashes (dirs to check:%u)", size);
-
- /* Get potentially non-processed debugdumps */
- for (GList *li = dirs; li != NULL; li = g_list_next(li))
- {
- try
- {
- const char *dir_name = (char*)dirs->data;
- map_crash_data_t crashinfo;
- mw_result_t res = SaveDebugDump(dir_name, crashinfo);
- switch (res)
- {
- case MW_OK:
- /* Not VERB1: this is new, unprocessed crash dump.
- * Last abrtd somehow missed it - need to inform user */
- log("Non-processed crash in %s, saving into database", dir_name);
- break;
- case MW_IN_DB:
- /* This debugdump was found in DB, nothing else was done
- * by SaveDebugDump or needs to be done by us */
- VERB1 log("%s is already saved in database", dir_name);
- break;
- case MW_REPORTED: /* already reported dup */
- case MW_OCCURRED: /* not-yet-reported dup */
- VERB1 log("Duplicate crash %s, deleting", dir_name);
- delete_debug_dump_dir(dir_name);
- break;
- default:
- log("Corrupted or bad crash %s (res:%d), deleting", dir_name, (int)res);
- delete_debug_dump_dir(dir_name);
- break;
- }
- }
- catch (CABRTException& e)
- {
- error_msg("%s", e.what());
- }
- }
-
- for (GList *li = dirs; li != NULL; li = g_list_next(li))
- free(li->data);
-
- g_list_free(dirs);
-
- log("Done checking for unsaved crashes");
-}
-
static int CreatePidFile()
{
int fd;
@@ -616,7 +536,7 @@ static gboolean handle_inotify_cb(GIOChannel *gio, GIOCondition condition, gpoin
char *d = concat_path_file(DEBUG_DUMPS_DIR, worst_dir);
free(worst_dir);
worst_dir = NULL;
- DeleteDebugDump_by_dir(d);
+ delete_debug_dump_dir(d);
free(d);
}
}
@@ -625,38 +545,36 @@ static gboolean handle_inotify_cb(GIOChannel *gio, GIOCondition condition, gpoin
try
{
fullname = concat_path_file(DEBUG_DUMPS_DIR, name);
- /* Note: SaveDebugDump does not save crashinfo, it _fetches_ crashinfo */
map_crash_data_t crashinfo;
- mw_result_t res = SaveDebugDump(fullname, crashinfo);
+ mw_result_t res = LoadDebugDump(fullname, crashinfo);
switch (res)
{
case MW_OK:
log("New crash %s, processing", fullname);
/* Fall through */
- case MW_REPORTED: /* already reported dup */
- case MW_OCCURRED: /* not-yet-reported dup */
+ case MW_OCCURRED: /* dup */
{
if (res != MW_OK)
{
- const char *first = get_crash_data_item_content(crashinfo, CD_DUMPDIR).c_str();
+ const char *first = get_crash_data_item_content_or_NULL(crashinfo, CD_DUMPDIR);
log("Deleting crash %s (dup of %s), sending dbus signal",
strrchr(fullname, '/') + 1,
strrchr(first, '/') + 1);
delete_debug_dump_dir(fullname);
}
- const char *analyzer = get_crash_data_item_content(crashinfo, FILENAME_ANALYZER).c_str();
- const char *uid_str = get_crash_data_item_content(crashinfo, CD_UID).c_str();
+ const char *uid_str = get_crash_data_item_content_or_NULL(crashinfo, FILENAME_UID);
+ const char *inform_all = get_crash_data_item_content_or_NULL(crashinfo, FILENAME_INFORMALL);
- /* Send dbus signal */
- //if (analyzer_has_InformAllUsers(analyzer))
- // uid_str = NULL;
+ if (inform_all && string_to_bool(inform_all))
+ uid_str = NULL;
char *crash_id = xasprintf("%s:%s",
- get_crash_data_item_content(crashinfo, CD_UID).c_str(),
- get_crash_data_item_content(crashinfo, CD_UUID).c_str()
+ get_crash_data_item_content_or_NULL(crashinfo, FILENAME_UID),
+ get_crash_data_item_content_or_NULL(crashinfo, FILENAME_UUID)
);
- g_pCommLayer->Crash(get_crash_data_item_content(crashinfo, FILENAME_PACKAGE).c_str(),
+ /* Send dbus signal */
+ g_pCommLayer->Crash(get_crash_data_item_content_or_NULL(crashinfo, FILENAME_PACKAGE),
crash_id,
fullname,
uid_str
@@ -664,9 +582,6 @@ static gboolean handle_inotify_cb(GIOChannel *gio, GIOCondition condition, gpoin
free(crash_id);
break;
}
- case MW_IN_DB:
- log("Huh, this crash is already in db?! Nothing to do");
- break;
case MW_CORRUPTED:
case MW_GPG_ERROR:
default:
@@ -984,8 +899,6 @@ int main(int argc, char** argv)
/* Enter the event loop */
try
{
- /* This may take a while, therefore we don't do it in init section */
- FindNewDumps(DEBUG_DUMPS_DIR);
log("Init complete, entering main loop");
run_main_loop(pMainloop);
}
diff --git a/src/daemon/MiddleWare.cpp b/src/daemon/MiddleWare.cpp
index bd0e9689..43844d82 100644
--- a/src/daemon/MiddleWare.cpp
+++ b/src/daemon/MiddleWare.cpp
@@ -43,7 +43,7 @@ CPluginManager* g_pPluginManager;
* @param pCrashData A crash info.
* @return It return results of operation. See mw_result_t.
*/
-static mw_result_t FillCrashInfo(const char *crash_id,
+static mw_result_t FillCrashInfo(const char *dump_dir_name,
map_crash_data_t& pCrashData);
/**
@@ -79,6 +79,8 @@ static bool DebugDumpToCrashReport(const char *dump_dir_name, map_crash_data_t&
add_to_crash_data_ext(pCrashData, CD_EVENTS, CD_SYS, CD_ISNOTEDITABLE, events);
free(events);
+ add_to_crash_data_ext(pCrashData, CD_DUMPDIR, CD_SYS, CD_ISNOTEDITABLE, dump_dir_name);
+
return true;
}
@@ -94,43 +96,44 @@ static char *do_log_and_update_client(char *log_line, void *param)
* (1) by StartJob dbus call -> CreateReportThread(), in the thread
* (2) by CreateReport dbus call
*/
-mw_result_t CreateCrashReport(const char *crash_id,
+mw_result_t CreateCrashReport(const char *dump_dir_name,
long caller_uid,
int force,
map_crash_data_t& pCrashData)
{
- VERB2 log("CreateCrashReport('%s',%ld,result)", crash_id, caller_uid);
+ VERB2 log("CreateCrashReport('%s',%ld,result)", dump_dir_name, caller_uid);
- CDatabase* database = g_pPluginManager->GetDatabase(g_settings_sDatabase);
- database->Connect();
- struct db_row *row = database->GetRow(crash_id);
- database->DisConnect();
- if (!row)
- {
- error_msg("crash '%s' is not in database", crash_id);
- return MW_IN_DB_ERROR;
- }
+ struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
+ if (!dd)
+ return MW_NOENT_ERROR;
mw_result_t r = MW_OK;
- if (caller_uid != 0 /* not called by root */
- && row->db_inform_all[0] != '1'
- ) {
+ if (caller_uid != 0) /* not called by root */
+ {
char caller_uid_str[sizeof(long) * 3 + 2];
sprintf(caller_uid_str, "%ld", caller_uid);
- if (strcmp(caller_uid_str, row->db_uid) != 0)
+
+ char *uid = dd_load_text(dd, FILENAME_UID);
+ if (strcmp(uid, caller_uid_str) != 0)
{
- error_msg("crash '%s' can't be accessed by user with uid %ld", crash_id, caller_uid);
- r = MW_IN_DB_ERROR;
- goto ret;
+ char *inform_all = dd_load_text(dd, FILENAME_INFORMALL);
+ if (!string_to_bool(inform_all))
+ {
+ dd_close(dd);
+ error_msg("crash '%s' can't be accessed by user with uid %ld", dump_dir_name, caller_uid);
+ r = MW_PERM_ERROR;
+ goto ret;
+ }
}
}
+ dd_close(dd);
try
{
struct run_event_state *run_state = new_run_event_state();
run_state->logging_callback = do_log_and_update_client;
- int res = run_event(run_state, row->db_dump_dir, force ? "reanalyze" : "analyze");
+ int res = run_event(run_state, dump_dir_name, force ? "reanalyze" : "analyze");
free_run_event_state(run_state);
if (res != 0 && res != -1) /* -1 is "nothing was done", here it is ok */
{
@@ -141,7 +144,7 @@ mw_result_t CreateCrashReport(const char *crash_id,
/* Do a load_crash_data_from_debug_dump from (possibly updated)
* crash dump dir
*/
- if (!DebugDumpToCrashReport(row->db_dump_dir, pCrashData))
+ if (!DebugDumpToCrashReport(dump_dir_name, pCrashData))
{
error_msg("Error loading crash data");
r = MW_ERROR;
@@ -159,7 +162,6 @@ mw_result_t CreateCrashReport(const char *crash_id,
}
ret:
- db_row_free(row);
VERB3 log("CreateCrashReport() returns %d", r);
return r;
}
@@ -207,17 +209,16 @@ report_status_t Report(const map_crash_data_t& client_report,
long caller_uid)
{
// Get ID fields
- const char *UID = get_crash_data_item_content_or_NULL(client_report, CD_UID);
- const char *UUID = get_crash_data_item_content_or_NULL(client_report, CD_UUID);
- if (!UID || !UUID)
+ const char *UID = get_crash_data_item_content_or_NULL(client_report, FILENAME_UID);
+ const char *dump_dir_name = get_crash_data_item_content_or_NULL(client_report, CD_DUMPDIR);
+ if (!UID || !dump_dir_name)
{
- throw CABRTException(EXCEP_ERROR, "Report(): UID or UUID is missing in client's report data");
+ throw CABRTException(EXCEP_ERROR, "Report(): UID or DUMPDIR is missing in client's report data");
}
- string crash_id = ssprintf("%s:%s", UID, UUID);
// Retrieve corresponding stored record
map_crash_data_t stored_report;
- mw_result_t r = FillCrashInfo(crash_id.c_str(), stored_report);
+ mw_result_t r = FillCrashInfo(dump_dir_name, stored_report);
if (r != MW_OK)
{
return report_status_t();
@@ -225,15 +226,13 @@ report_status_t Report(const map_crash_data_t& client_report,
// Is it allowed for this user to report?
if (caller_uid != 0 // not called by root
- && get_crash_data_item_content(stored_report, CD_INFORMALL) != "1"
+ && get_crash_data_item_content(stored_report, FILENAME_INFORMALL) != "1"
&& strcmp(to_string(caller_uid).c_str(), UID) != 0
) {
throw CABRTException(EXCEP_ERROR, "Report(): user with uid %ld can't report crash %s",
- caller_uid, crash_id.c_str());
+ caller_uid, dump_dir_name);
}
- const char *dump_dir_name = get_crash_data_item_content_or_NULL(stored_report, CD_DUMPDIR);
-
// Save comment, "how to reproduce", backtrace
//TODO: we should iterate through stored_report and modify all
//modifiable fields which have new data in client_report
@@ -363,136 +362,102 @@ report_status_t Report(const map_crash_data_t& client_report,
}
g_list_free(env_list);
- // Save reporting results to database
+ // Save reporting results
if (at_least_one_reporter_succeeded)
{
- CDatabase* database = g_pPluginManager->GetDatabase(g_settings_sDatabase);
- database->Connect();
report_status_t::iterator ret_it = ret.begin();
while (ret_it != ret.end())
{
- const string &event = ret_it->first;
- const vector_string_t &v = ret_it->second;
- if (v[REPORT_STATUS_IDX_FLAG] == "1")
- {
- database->SetReportedPerReporter(crash_id.c_str(), event.c_str(), v[REPORT_STATUS_IDX_MSG].c_str());
- }
+// const string &event = ret_it->first;
+// const vector_string_t &v = ret_it->second;
+// if (v[REPORT_STATUS_IDX_FLAG] == "1")
+// {
+// TODO: append to a log of reports done
+// database->SetReportedPerReporter(dump_dir_name, event.c_str(), v[REPORT_STATUS_IDX_MSG].c_str());
+// }
ret_it++;
}
- database->SetReported(crash_id.c_str(), message.c_str());
- database->DisConnect();
+ /* Was: database->SetReported(dump_dir_name, message.c_str()); */
+ struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
+ if (dd)
+ {
+ dd_save_text(dd, FILENAME_MESSAGE, message.c_str());
+ dd_close(dd);
+ }
}
return ret;
#undef client_report
}
-/**
- * Check whether particular debugdump directory is saved in database.
- * @param debug_dump_dir
- * A debugdump dir containing all necessary data.
- * @return
- * It returns true if debugdump dir is already saved, otherwise
- * it returns false.
- */
-static bool is_debug_dump_saved(const char *debug_dump_dir)
-{
- CDatabase* database = g_pPluginManager->GetDatabase(g_settings_sDatabase);
- database->Connect();
- struct db_row *row = database->GetRow_by_dir(debug_dump_dir);
- database->DisConnect();
-
- db_row_free(row);
- return row != NULL;
-}
-
-/**
- * Save a debugdump into database. If saving is
- * successful, then crash info is filled. Otherwise the crash info is
- * not changed.
- * @param pUUID A local UUID of a crash.
- * @param pUID An UID of an user.
- * @param pTime Time when a crash occurs.
- * @param pDebugDumpPath A debugdump path.
- * @param pCrashData A filled crash info.
- * @return It return results of operation. See mw_result_t.
- */
-static mw_result_t SaveDebugDumpToDatabase(const char *crash_id,
- bool inform_all_users,
- const char *pTime,
- const char *pDebugDumpDir,
- map_crash_data_t& pCrashData)
-{
- CDatabase* database = g_pPluginManager->GetDatabase(g_settings_sDatabase);
- database->Connect();
- /* note: if [UUID,UID] record exists, pDebugDumpDir is not updated in the record */
- database->Insert_or_Update(crash_id, inform_all_users, pDebugDumpDir, pTime);
-
- struct db_row *row = database->GetRow(crash_id);
- database->DisConnect();
-
- mw_result_t res = FillCrashInfo(crash_id, pCrashData);
- if (res == MW_OK)
- {
- const char *first = get_crash_data_item_content(pCrashData, CD_DUMPDIR).c_str();
- if (row && row->db_reported[0] == '1')
- {
- log("Crash is in database already (dup of %s) and is reported", first);
- db_row_free(row);
- return MW_REPORTED;
- }
- if (row && xatou(row->db_count) > 1)
- {
- db_row_free(row);
- log("Crash is in database already (dup of %s)", first);
- return MW_OCCURRED;
- }
- }
- db_row_free(row);
- return res;
-}
-
-/* We need to share some data between SaveDebugDump and is_crash_id_in_db: */
+/* We need to share some data between LoadDebugDump and is_crash_a_dup: */
struct cdump_state {
- char *uid; /* filled by SaveDebugDump */
- char *crash_id; /* filled by is_crash_id_in_db */
- int crash_id_is_in_db; /* filled by is_crash_id_in_db */
+ 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_id_in_db(const char *dump_dir_name, void *param)
+static int is_crash_a_dup(const char *dump_dir_name, void *param)
{
struct cdump_state *state = (struct cdump_state *)param;
- if (state->crash_id)
+ 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) */
- char *uuid = dd_load_text_ext(dd, CD_UUID,
+ state->uuid = dd_load_text_ext(dd, FILENAME_UUID,
DD_FAIL_QUIETLY + DD_LOAD_TEXT_RETURN_NULL_ON_FAILURE
);
dd_close(dd);
- if (!uuid)
+ if (!state->uuid)
{
return 0; /* no uuid (yet), "run_event, please continue iterating" */
}
- state->crash_id = xasprintf("%s:%s", state->uid, uuid);
- free(uuid);
-
- CDatabase* database = g_pPluginManager->GetDatabase(g_settings_sDatabase);
- database->Connect();
- struct db_row *row = database->GetRow(state->crash_id);
- database->DisConnect();
-
- if (!row) /* Crash id is not in db - this crash wasn't seen before */
- return 0; /* "run_event, please continue iterating" */
-
- /* Crash id is in db */
- db_row_free(row);
- state->crash_id_is_in_db = 1;
- /* "run_event, please stop iterating": */
- return 1;
+
+ /* Scan crash dumps looking for a dup */
+//TODO: explain why this is safe wrt concurrent runs
+ DIR *dir = opendir(DEBUG_DUMPS_DIR);
+ 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(DEBUG_DUMPS_DIR, 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:*/ 0);
+ 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)
@@ -502,92 +467,110 @@ static char *do_log(char *log_line, void *param)
return log_line;
}
-mw_result_t SaveDebugDump(const char *dump_dir_name,
+mw_result_t LoadDebugDump(const char *dump_dir_name,
map_crash_data_t& pCrashData)
{
mw_result_t res;
- if (is_debug_dump_saved(dump_dir_name))
- return MW_IN_DB;
-
struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
if (!dd)
return MW_ERROR;
- struct cdump_state state = { NULL, NULL, false }; /* uid, crash_id, crash_id_is_in_db */
- state.uid = dd_load_text(dd, CD_UID);
- char *time = dd_load_text(dd, FILENAME_TIME);
+ 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_id_in_db;
+ 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(run_state, dump_dir_name, "post-create");
free_run_event_state(run_state);
- /* Is crash id in db? (In this case, is_crash_id_in_db() should have
+//TODO: consider this case:
+// new dump is created, post-create detects that it is a dup,
+// but then FillCrashInfo(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
- * such that uid:uuid (=crash_id) is in database, and set
- * the state.crash_id_is_in_db flag)
+ * and determined that there is another crash with same uuid.
+ * In this case it sets state.crash_dump_dup_name)
*/
- if (!state.crash_id_is_in_db)
+ 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_id_in_db()
- * should have fetched it and created state.crash_id)
+ /* Was uuid created after all? (In this case, is_crash_a_dup()
+ * should have fetched it and created state.uuid)
*/
- if (!state.crash_id)
+ 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;
+ }
/* Loads pCrashData (from the *first debugdump dir* if this one is a dup)
* Returns:
- * MW_REPORTED: "the crash is flagged as reported in DB" (which also means it's a dup)
* MW_OCCURRED: "crash count is != 1" (iow: it is > 1 - dup)
* MW_OK: "crash count is 1" (iow: this is a new crash, not a dup)
* else: an error code
*/
- res = SaveDebugDumpToDatabase(state.crash_id,
- true, /*analyzer_has_InformAllUsers(analyzer),*/
- time,
- dump_dir_name,
- pCrashData);
+ {
+ dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
+ if (!dd)
+ {
+ res = MW_ERROR;
+ goto ret;
+ }
+ char *count_str = dd_load_text_ext(dd, FILENAME_COUNT, DD_FAIL_QUIETLY);
+ unsigned long count = strtoul(count_str, NULL, 10);
+ count++;
+ char new_count_str[sizeof(long)*3 + 2];
+ sprintf(new_count_str, "%lu", count);
+ dd_save_text(dd, FILENAME_COUNT, new_count_str);
+ dd_close(dd);
+
+ res = FillCrashInfo(dump_dir_name, pCrashData);
+ if (res == MW_OK)
+ {
+ if (count > 1)
+ {
+ log("Crash dump is a duplicate of %s", dump_dir_name);
+ res = MW_OCCURRED;
+ }
+ }
+ }
+
ret:
- free(state.crash_id);
+ free(state.uuid);
free(state.uid);
- free(time);
+ free(state.crash_dump_dup_name);
free(analyzer);
return res;
}
-static mw_result_t FillCrashInfo(const char *crash_id,
+static mw_result_t FillCrashInfo(const char *dump_dir_name,
map_crash_data_t& pCrashData)
{
- CDatabase* database = g_pPluginManager->GetDatabase(g_settings_sDatabase);
- database->Connect();
- struct db_row *row = database->GetRow(crash_id);
- database->DisConnect();
-
- if (!row)
- return MW_ERROR;
-
- struct dump_dir *dd = dd_opendir(row->db_dump_dir, /*flags:*/ 0);
+ struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
if (!dd)
- {
- db_row_free(row);
return MW_ERROR;
- }
load_crash_data_from_debug_dump(dd, pCrashData);
char *events = list_possible_events(dd, NULL, "");
@@ -596,76 +579,85 @@ static mw_result_t FillCrashInfo(const char *crash_id,
add_to_crash_data_ext(pCrashData, CD_EVENTS, CD_SYS, CD_ISNOTEDITABLE, events);
free(events);
-//TODO: we _never_ use CD_SYS, perhaps we should use it here?
- add_to_crash_data(pCrashData, CD_UID , row->db_uid );
- add_to_crash_data(pCrashData, CD_UUID , row->db_uuid );
- add_to_crash_data(pCrashData, CD_INFORMALL , row->db_inform_all );
- add_to_crash_data(pCrashData, CD_COUNT , row->db_count );
- add_to_crash_data(pCrashData, CD_REPORTED , row->db_reported );
- add_to_crash_data(pCrashData, CD_MESSAGE , row->db_message );
- add_to_crash_data(pCrashData, CD_DUMPDIR , row->db_dump_dir );
- add_to_crash_data(pCrashData, FILENAME_TIME , row->db_time );
-
- db_row_free(row);
+ add_to_crash_data_ext(pCrashData, CD_DUMPDIR, CD_SYS, CD_ISNOTEDITABLE, dump_dir_name);
return MW_OK;
}
-static void GetUUIDsOfCrash(long caller_uid, vector_string_t &result)
-{
- CDatabase* database = g_pPluginManager->GetDatabase(g_settings_sDatabase);
- database->Connect();
- GList *rows = database->GetUIDData(caller_uid);
- database->DisConnect();
-
- for (GList *li = rows; li != NULL; li = g_list_next(li))
- {
- struct db_row *row = (struct db_row*)li->data;
- string crash_id = ssprintf("%s:%s", row->db_uid, row->db_uuid);
- result.push_back(crash_id);
- }
-
- // TODO: return GList
- db_list_free(rows);
-}
-
vector_map_crash_data_t GetCrashInfos(long caller_uid)
{
vector_map_crash_data_t retval;
log("Getting crash infos...");
- try
+
+ DIR *dir = opendir(DEBUG_DUMPS_DIR);
+ if (dir != NULL)
{
- vector_string_t crash_ids;
-//TODO: it looks strange that we select UUIDs
-//olny in order to find which directories to read!
-//Should we simply retrieve list of *directories*, not *uuids*?
- GetUUIDsOfCrash(caller_uid, crash_ids);
-
- unsigned int ii;
- for (ii = 0; ii < crash_ids.size(); ii++)
+ try
{
- const char *crash_id = crash_ids[ii].c_str();
-
- map_crash_data_t info;
- mw_result_t res = FillCrashInfo(crash_id, info);
- switch (res)
+ struct dirent *dent;
+ while ((dent = readdir(dir)) != NULL)
{
- case MW_OK:
- retval.push_back(info);
- break;
- case MW_ERROR:
- error_msg("Dump directory for crash_id %s doesn't exist or misses crucial files, deleting", crash_id);
- /* Deletes both DB record and dump dir */
- DeleteDebugDump(crash_id, /*caller_uid:*/ 0);
- break;
- default:
- break;
+ if (dot_or_dotdot(dent->d_name))
+ continue; /* skip "." and ".." */
+
+ char *dump_dir_name = concat_path_file(DEBUG_DUMPS_DIR, dent->d_name);
+
+ struct stat statbuf;
+ if (stat(dump_dir_name, &statbuf) != 0
+ || !S_ISDIR(statbuf.st_mode)
+ ) {
+ goto next; /* not a dir, skip */
+ }
+
+ /* Skip directories which are not for this uid */
+ if (caller_uid != 0) /* not called by root? */
+ {
+ char *uid;
+ char caller_uid_str[sizeof(long) * 3 + 2];
+
+ struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
+ if (!dd)
+ goto next;
+
+ sprintf(caller_uid_str, "%ld", caller_uid);
+ uid = dd_load_text(dd, FILENAME_UID);
+ if (strcmp(uid, caller_uid_str) != 0)
+ {
+ char *inform_all = dd_load_text(dd, FILENAME_INFORMALL);
+ if (!string_to_bool(inform_all))
+ {
+ dd_close(dd);
+ goto next;
+ }
+ }
+ dd_close(dd);
+ }
+
+ {
+ map_crash_data_t info;
+ mw_result_t res = FillCrashInfo(dump_dir_name, info);
+ switch (res)
+ {
+ case MW_OK:
+ retval.push_back(info);
+ break;
+ case MW_ERROR:
+ error_msg("Dump directory %s doesn't exist or misses crucial files, deleting", dump_dir_name);
+ delete_debug_dump_dir(dump_dir_name);
+ break;
+ default:
+ break;
+ }
+ }
+ next:
+ free(dump_dir_name);
}
}
- }
- catch (CABRTException& e)
- {
- error_msg("%s", e.what());
+ catch (CABRTException& e)
+ {
+ error_msg("%s", e.what());
+ }
+ closedir(dir);
}
return retval;
@@ -681,19 +673,18 @@ vector_map_crash_data_t GetCrashInfos(long caller_uid)
*/
void CreateReport(const char* crash_id, long caller_uid, int force, map_crash_data_t& crashReport)
{
- /* FIXME: starting from here, any shared data must be protected with a mutex.
- * For example, CreateCrashReport does:
- * g_pPluginManager->GetDatabase(g_settings_sDatabase);
- * which is unsafe wrt concurrent updates to g_pPluginManager state.
- */
+ /* FIXME: starting from here, any shared data must be protected with a mutex. */
mw_result_t res = CreateCrashReport(crash_id, caller_uid, force, crashReport);
switch (res)
{
case MW_OK:
VERB2 log_map_crash_data(crashReport, "crashReport");
break;
- case MW_IN_DB_ERROR:
- error_msg("Can't find crash with id %s in database", crash_id);
+ case MW_NOENT_ERROR:
+ error_msg("Can't find crash with id '%s'", crash_id);
+ break;
+ case MW_PERM_ERROR:
+ error_msg("Can't find crash with id '%s'", crash_id);
break;
case MW_PLUGIN_ERROR:
error_msg("Particular analyzer plugin isn't loaded or there is an error within plugin(s)");
@@ -770,63 +761,34 @@ int CreateReportThread(const char* crash_id, long caller_uid, int force, const c
}
-/* Remove dump dir and its DB record */
-int DeleteDebugDump(const char *crash_id, long caller_uid)
+/* Remove dump dir */
+int DeleteDebugDump(const char *dump_dir_name, long caller_uid)
{
- try
- {
- CDatabase* database = g_pPluginManager->GetDatabase(g_settings_sDatabase);
- database->Connect();
- struct db_row *row = database->GetRow(crash_id);
- if (!row)
- {
- database->DisConnect();
- return ENOENT;
- }
+ struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
+ if (!dd)
+ return MW_NOENT_ERROR;
+ if (caller_uid != 0) /* not called by root */
+ {
char caller_uid_str[sizeof(long) * 3 + 2];
- sprintf(caller_uid_str, "%li", caller_uid);
-
- if (caller_uid != 0 /* not called by root */
- && row->db_inform_all[0] != '1'
- && strcmp(caller_uid_str, row->db_uid) != 0
- ) {
- database->DisConnect();
- db_row_free(row);
- return EPERM;
- }
- database->DeleteRow(crash_id);
- database->DisConnect();
- if (row->db_dump_dir[0] != '\0')
+ sprintf(caller_uid_str, "%ld", caller_uid);
+
+ char *uid = dd_load_text(dd, FILENAME_UID);
+ if (strcmp(uid, caller_uid_str) != 0)
{
- delete_debug_dump_dir(row->db_dump_dir);
- db_row_free(row);
- return 0; /* success */
+ char *inform_all = dd_load_text(dd, FILENAME_INFORMALL);
+ if (!string_to_bool(inform_all))
+ {
+ dd_close(dd);
+ error_msg("crash '%s' can't be accessed by user with uid %ld", dump_dir_name, caller_uid);
+ return 1;
+ }
}
- db_row_free(row);
- }
- catch (CABRTException& e)
- {
- error_msg("%s", e.what());
}
- return EIO; /* generic failure code */
-}
-void DeleteDebugDump_by_dir(const char *dump_dir)
-{
- try
- {
- CDatabase* database = g_pPluginManager->GetDatabase(g_settings_sDatabase);
- database->Connect();
- database->DeleteRows_by_dir(dump_dir);
- database->DisConnect();
+ dd_delete(dd);
- delete_debug_dump_dir(dump_dir);
- }
- catch (CABRTException& e)
- {
- error_msg("%s", e.what());
- }
+ return 0; /* success */
}
void GetPluginsInfo(map_map_string_t &map_of_plugin_info)
diff --git a/src/daemon/MiddleWare.h b/src/daemon/MiddleWare.h
index 90386c03..808d7be4 100644
--- a/src/daemon/MiddleWare.h
+++ b/src/daemon/MiddleWare.h
@@ -30,13 +30,12 @@
*/
typedef enum {
MW_OK, /**< No error.*/
- MW_OCCURRED, /**< A not-yet-reported dup.*/
- MW_REPORTED, /**< A reported dup.*/
+ MW_OCCURRED, /**< No error, but thus dump is a dup.*/
MW_ERROR, /**< Common error.*/
+ MW_NOENT_ERROR,
+ MW_PERM_ERROR,
MW_CORRUPTED, /**< Debugdump directory is corrupted.*/
MW_GPG_ERROR, /**< Package is not signed properly.*/
- MW_IN_DB, /**< Debugdump directory is already saved in a database.*/
- MW_IN_DB_ERROR, /**< Error while working with a database.*/
MW_PLUGIN_ERROR, /**< plugin wasn't found or error within plugin*/
} mw_result_t;
@@ -56,7 +55,7 @@ typedef enum {
* @param pCrashData A filled crash report.
* @return It return results of operation. See mw_result_t.
*/
-mw_result_t CreateCrashReport(const char *crash_id,
+mw_result_t CreateCrashReport(const char *dump_dir_name,
long caller_uid,
int force,
map_crash_data_t& pCrashData);
@@ -91,23 +90,20 @@ report_status_t Report(const map_crash_data_t& crash_data,
const map_map_string_t& settings,
long caller_uid);
/**
- * Adds package name and description to debugdump dir.
- * Saves debugdump into database.
- * Detects whether it's a duplicate crash.
+ * Detects whether it's a duplicate crash dump.
* Fills crash info.
* Note that if it's a dup, loads _first crash_ info, not this one's.
- * @param pDebugDumpDir A debugdump directory.
+ * @param dump_dir_name A debugdump directory.
* @param pCrashData A crash info.
* @return It return results of operation. See mw_result_t.
*/
-mw_result_t SaveDebugDump(const char *pDebugDumpDir,
+mw_result_t LoadDebugDump(const char *dump_dir_name,
map_crash_data_t& pCrashData);
vector_map_crash_data_t GetCrashInfos(long caller_uid);
-int CreateReportThread(const char* crash_id, long caller_uid, int force, const char* pSender);
-void CreateReport(const char* crash_id, long caller_uid, int force, map_crash_data_t&);
-int DeleteDebugDump(const char *crash_id, long caller_uid);
-void DeleteDebugDump_by_dir(const char *dump_dir);
+int CreateReportThread(const char* dump_dir_name, long caller_uid, int force, const char* pSender);
+void CreateReport(const char* dump_dir_name, long caller_uid, int force, map_crash_data_t&);
+int DeleteDebugDump(const char *dump_dir_name, long caller_uid);
void GetPluginsInfo(map_map_string_t &map_of_plugin_info);
void GetPluginSettings(const char *plugin_name, map_plugin_settings_t &plugin_settings);
diff --git a/src/daemon/PluginManager.cpp b/src/daemon/PluginManager.cpp
index 0f7b983d..665a4625 100644
--- a/src/daemon/PluginManager.cpp
+++ b/src/daemon/PluginManager.cpp
@@ -247,20 +247,6 @@ CAction* CPluginManager::GetAction(const char *pName, bool silent)
return (CAction*)plugin;
}
-CDatabase* CPluginManager::GetDatabase(const char *pName)
-{
- CPlugin *plugin = LoadPlugin(pName);
- if (!plugin)
- {
- throw CABRTException(EXCEP_PLUGIN, "Plugin '%s' is not registered", pName);
- }
- if (m_mapLoadedModules[pName]->GetType() != DATABASE)
- {
- throw CABRTException(EXCEP_PLUGIN, "Plugin '%s' is not a database plugin", pName);
- }
- return (CDatabase*)plugin;
-}
-
plugin_type_t CPluginManager::GetPluginType(const char *pName)
{
CPlugin *plugin = LoadPlugin(pName);
diff --git a/src/daemon/PluginManager.h b/src/daemon/PluginManager.h
index 1d2b4bd3..c5036fbf 100644
--- a/src/daemon/PluginManager.h
+++ b/src/daemon/PluginManager.h
@@ -25,7 +25,6 @@
#include "abrt_types.h"
#include "plugin.h"
#include "analyzer.h"
-#include "database.h"
#include "action.h"
class CLoadedModule; /* opaque */
@@ -90,12 +89,6 @@ class CPluginManager
*/
CAction* GetAction(const char *pName, bool silent = false);
/**
- * A method, which returns instance of particular database plugin.
- * @param pName A plugin name.
- * @return A database plugin.
- */
- CDatabase* GetDatabase(const char *pName);
- /**
* A method, which returns type of particular plugin.
* @param pName A plugin name.
* @return A plugin type.
diff --git a/src/daemon/Settings.cpp b/src/daemon/Settings.cpp
index d0c44c20..5b9972ba 100644
--- a/src/daemon/Settings.cpp
+++ b/src/daemon/Settings.cpp
@@ -50,7 +50,6 @@ bool g_settings_bOpenGPGCheck = false;
GList *g_settings_setOpenGPGPublicKeys = NULL;
GList *g_settings_setBlackListedPkgs = NULL;
GList *g_settings_setBlackListedPaths = NULL;
-char *g_settings_sDatabase = NULL;
char *g_settings_sWatchCrashdumpArchiveDir = NULL;
unsigned int g_settings_nMaxCrashReportsSize = 1000;
bool g_settings_bProcessUnpackaged = false;
@@ -200,17 +199,6 @@ static int ParseCommon()
{
g_settings_setBlackListedPaths = parse_list(it->second.c_str());
}
- it = s_mapSectionCommon.find("Database");
- if (it != end)
- {
- if (it->second.empty())
- error_msg_and_die(_("Database plugin not specified. Please check abrtd settings."));
-
- g_settings_sDatabase = xstrdup(it->second.c_str());
- }
- else
- error_msg_and_die(_("Database plugin not specified. Please check abrtd settings."));
-
it = s_mapSectionCommon.find("WatchCrashdumpArchiveDir");
if (it != end)
{
@@ -466,9 +454,6 @@ void settings_free()
g_list_free(g_settings_setBlackListedPaths);
g_settings_setBlackListedPaths = NULL;
- free(g_settings_sDatabase);
- g_settings_sDatabase = NULL;
-
free(g_settings_sWatchCrashdumpArchiveDir);
g_settings_sWatchCrashdumpArchiveDir = NULL;
}
diff --git a/src/daemon/Settings.h b/src/daemon/Settings.h
index 7fe64fcf..71824c74 100644
--- a/src/daemon/Settings.h
+++ b/src/daemon/Settings.h
@@ -31,7 +31,6 @@ extern GList *g_settings_setBlackListedPaths;
extern unsigned int g_settings_nMaxCrashReportsSize;
extern bool g_settings_bOpenGPGCheck;
extern bool g_settings_bProcessUnpackaged;
-extern char *g_settings_sDatabase;
extern char *g_settings_sWatchCrashdumpArchiveDir;
extern map_cron_t g_settings_mapCron;
diff --git a/src/daemon/abrt-server.c b/src/daemon/abrt-server.c
index 67978561..db07fe94 100644
--- a/src/daemon/abrt-server.c
+++ b/src/daemon/abrt-server.c
@@ -134,7 +134,7 @@ static void create_debug_dump()
/* Store id of the user whose application crashed. */
char uid_str[sizeof(long) * 3 + 2];
sprintf(uid_str, "%lu", (long)client_uid);
- dd_save_text(dd, CD_UID, uid_str);
+ dd_save_text(dd, FILENAME_UID, uid_str);
dd_close(dd);
diff --git a/src/daemon/abrt.conf b/src/daemon/abrt.conf
index cd9a782e..07ea51a0 100644
--- a/src/daemon/abrt.conf
+++ b/src/daemon/abrt.conf
@@ -18,10 +18,6 @@ ProcessUnpackaged = no
#
BlackListedPaths = /usr/share/doc/*, */example*
-# Which database plugin to use
-#
-Database = SQLite3
-
# Enable this if you want abrtd to auto-unpack crashdump tarballs which appear
# in this directory (for example, uploaded via ftp, scp etc).
# Note: you must ensure that whatever directory you specify here exists
diff --git a/src/daemon/abrt.conf.5 b/src/daemon/abrt.conf.5
index 968b5ea8..3f9d8c39 100644
--- a/src/daemon/abrt.conf.5
+++ b/src/daemon/abrt.conf.5
@@ -35,11 +35,6 @@ will ignore packages in this list and will not handle their crashes.
will ignore crashes in executables whose absolute path matches
one of specified patterns.
.TP
-.B Database = \fIdatabasePlugin\fP
-This specifies which database plugin
-.I abrt
-uses to store metadata about the crash.
-.TP
.B MaxCrashReportsSize = \fInumber\fP
The maximum disk space (specified in megabytes) that
.I abrt
diff --git a/src/daemon/abrt_event.conf b/src/daemon/abrt_event.conf
index 6c1ac191..938a1de6 100644
--- a/src/daemon/abrt_event.conf
+++ b/src/daemon/abrt_event.conf
@@ -30,6 +30,8 @@ EVENT=post-create abrt-action-save-package-data
EVENT=post-create analyzer=CCpp abrt-action-analyze-c
EVENT=post-create analyzer=Python abrt-action-analyze-python
EVENT=post-create analyzer=Kerneloops abrt-action-analyze-oops
+# If you want all users (not just root) to be able to see oopses:
+#EVENT=post-create analyzer=Kerneloops echo 1 >inform_all_users
# If you want behavior similar to one provided by kerneloops daemon
# distributed by kerneloops.org - that is, if you want
# oopses to be reported automatically and immediately without