diff options
author | Denys Vlasenko <dvlasenk@redhat.com> | 2010-11-23 15:51:54 +0100 |
---|---|---|
committer | Denys Vlasenko <dvlasenk@redhat.com> | 2010-11-23 15:51:54 +0100 |
commit | 86fc61db75385d6fb452b4cf88aec1deffa3a5be (patch) | |
tree | 8b88bd46ef8fe05167f72b3d1f0bff034620b9a1 /src/daemon | |
parent | d992b91c61b4da10e1f977038d85cd640f8d7ae5 (diff) | |
download | abrt-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.cpp | 111 | ||||
-rw-r--r-- | src/daemon/MiddleWare.cpp | 524 | ||||
-rw-r--r-- | src/daemon/MiddleWare.h | 24 | ||||
-rw-r--r-- | src/daemon/PluginManager.cpp | 14 | ||||
-rw-r--r-- | src/daemon/PluginManager.h | 7 | ||||
-rw-r--r-- | src/daemon/Settings.cpp | 15 | ||||
-rw-r--r-- | src/daemon/Settings.h | 1 | ||||
-rw-r--r-- | src/daemon/abrt-server.c | 2 | ||||
-rw-r--r-- | src/daemon/abrt.conf | 4 | ||||
-rw-r--r-- | src/daemon/abrt.conf.5 | 5 | ||||
-rw-r--r-- | src/daemon/abrt_event.conf | 2 |
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 |