diff options
Diffstat (limited to 'src/journald')
-rw-r--r-- | src/journald/LMI_JournalLogRecordProvider.c | 112 | ||||
-rw-r--r-- | src/journald/instutil.c | 29 | ||||
-rw-r--r-- | src/journald/instutil.h | 2 |
3 files changed, 142 insertions, 1 deletions
diff --git a/src/journald/LMI_JournalLogRecordProvider.c b/src/journald/LMI_JournalLogRecordProvider.c index 34a8f93..03493b3 100644 --- a/src/journald/LMI_JournalLogRecordProvider.c +++ b/src/journald/LMI_JournalLogRecordProvider.c @@ -21,6 +21,7 @@ #include <konkret/konkret.h> #include <cmpi/cmpimacs.h> #include "LMI_JournalLogRecord.h" +#include "LMI_JournalMessageLog.h" #include <errno.h> #include <glib.h> @@ -31,6 +32,9 @@ #include "instutil.h" +#define WRITE_RECORD_TIMEOUT 5000 /* ms */ + + static const CMPIBroker* _cb = NULL; static sd_journal *journal_iter = NULL; @@ -161,6 +165,25 @@ static CMPIStatus LMI_JournalLogRecordGetInstance( KReturn(OK); } +static const char * +get_string_property(const char *property_name, const CMPIInstance* ci) +{ + CMPIData d; + CMPIStatus rc = { CMPI_RC_OK, NULL }; + + d = CMGetProperty(ci, property_name, &rc); + if (rc.rc != CMPI_RC_OK || (d.state & CMPI_nullValue) == CMPI_nullValue || + (d.state & CMPI_notFound) == CMPI_notFound || d.value.string == NULL) + return NULL; + return CMGetCharPtr(d.value.string); +} + +#define J_RESULT_CHECK(r,j,msg) \ + if (r < 0) { \ + sd_journal_close(j); \ + KReturn2(_cb, ERR_FAILED, msg ": %s\n", strerror(-r)); \ + } + static CMPIStatus LMI_JournalLogRecordCreateInstance( CMPIInstanceMI* mi, const CMPIContext* cc, @@ -168,7 +191,94 @@ static CMPIStatus LMI_JournalLogRecordCreateInstance( const CMPIObjectPath* cop, const CMPIInstance* ci) { - CMReturn(CMPI_RC_ERR_NOT_SUPPORTED); + const char *cr_cl_n; + const char *log_cr_cl_n; + const char *log_name; + const char *data_format; + sd_journal *journal; + int r; + CMPIrc rc; + bool found; + + cr_cl_n = get_string_property("CreationClassName", ci); + log_cr_cl_n = get_string_property("LogCreationClassName", ci); + log_name = get_string_property("LogName", ci); + data_format = get_string_property("DataFormat", ci); + + if (cr_cl_n == NULL || log_cr_cl_n == NULL || log_name == NULL || data_format == NULL) + KReturn(ERR_INVALID_PARAMETER); + if (strcmp(cr_cl_n, LMI_JournalLogRecord_ClassName) != 0 || + strcmp(log_cr_cl_n, LMI_JournalMessageLog_ClassName) != 0 || + strcmp(log_name, JOURNAL_MESSAGE_LOG_NAME) != 0) { + KReturn(ERR_INVALID_PARAMETER); + } + + r = sd_journal_open(&journal, 0); + if (r < 0) { + KReturn2(_cb, ERR_FAILED, "Error opening journal: %s\n", strerror(-r)); + } + + r = sd_journal_seek_tail(journal); + J_RESULT_CHECK(r, journal, "Error seeking to the end of the journal"); + + /* Need to call at least one of the _previous()/_next() functions to make the iterator set */ + r = sd_journal_previous(journal); + if (r > 0) + while ((r = sd_journal_next(journal)) > 0) + ; + J_RESULT_CHECK(r, journal, "Error seeking to the end of the journal"); + + /* Queue send new record */ + r = sd_journal_send("MESSAGE=%s", data_format, + NULL); + J_RESULT_CHECK(r, journal, "Error writing new record to the journal"); + + r = sd_journal_wait(journal, WRITE_RECORD_TIMEOUT * 1000 /* usec */); + /* First wait call will likely return INVALIDATE, try again */ + if (r == SD_JOURNAL_INVALIDATE) + r = sd_journal_wait(journal, WRITE_RECORD_TIMEOUT * 1000 /* usec */); + J_RESULT_CHECK(r, journal, "Error checking the journal for new records"); + + found = false; + while (sd_journal_next(journal) > 0) { + /* TODO: alternatively, we can use custom property and an unique identifier + * but let's not bloat the journal with unneccessary data for now */ + r = match_journal_record(journal, data_format, __func__); + if (r == 1) { + const char *ns = KNameSpace(cop); + LMI_JournalLogRecord log_record; + char *cursor; + + LMI_JournalLogRecord_InitFromObjectPath(&log_record, _cb, cop); + LMI_JournalLogRecord_Set_DataFormat(&log_record, data_format); + LMI_JournalLogRecord_Set_CreationClassName(&log_record, LMI_JournalLogRecord_ClassName); + LMI_JournalLogRecord_Set_LogCreationClassName(&log_record, LMI_JournalMessageLog_ClassName); + LMI_JournalLogRecord_Set_LogName(&log_record, JOURNAL_MESSAGE_LOG_NAME); + + /* Get stable cursor string */ + r = sd_journal_get_cursor(journal, &cursor); + J_RESULT_CHECK(r, journal, "Failed to get cursor position"); + LMI_JournalLogRecord_Set_RecordID(&log_record, cursor); + free(cursor); + + r = create_LMI_JournalLogRecord(journal, &log_record, _cb); + if (r <= 0) { + sd_journal_close(journal); + KReturn2(_cb, ERR_FAILED, "Failed to create instance: %s\n", strerror(-r)); + } + + CMReturnObjectPath(cr, LMI_JournalLogRecord_ToObjectPath(&log_record, NULL)); + CMReturnDone(cr); + found = true; + break; + } + J_RESULT_CHECK(r, journal, "Failed to find newly written record"); + } + sd_journal_close(journal); + + if (! found) + KReturn2(_cb, ERR_FAILED, "Failed to find newly written record\n"); + CMReturn(CMPI_RC_OK); } static CMPIStatus LMI_JournalLogRecordModifyInstance( diff --git a/src/journald/instutil.c b/src/journald/instutil.c index a38202a..e664621 100644 --- a/src/journald/instutil.c +++ b/src/journald/instutil.c @@ -20,6 +20,7 @@ #include <errno.h> #include <syslog.h> +#include <unistd.h> #include <glib.h> #include <konkret/konkret.h> @@ -239,6 +240,34 @@ int create_LMI_JournalLogRecord(sd_journal *j, return 1; } +int match_journal_record(sd_journal *j, const char *message, const char *code_func) +{ + gchar *msg = NULL; + gchar *pid = NULL; + gchar *cfunc = NULL; + char *conv_err = NULL; + long int pid_n; + int r; + + r = dup_journal_data(j, "MESSAGE", &msg); + if (r < 0) + return r; + dup_journal_data(j, "_PID", &pid); + dup_journal_data(j, "CODE_FUNC", &cfunc); + + if (pid) + pid_n = strtol(pid, &conv_err, 10); + + r = msg && pid && cfunc && + (strcmp(message, msg) == 0) && (strcmp(code_func, cfunc) == 0) && + (conv_err == NULL || *conv_err == '\0') && (pid_n == getpid()); + + g_free(msg); + g_free(pid); + g_free(cfunc); + + return r; +} void ind_init() { diff --git a/src/journald/instutil.h b/src/journald/instutil.h index 0ba7ff1..1ea96a2 100644 --- a/src/journald/instutil.h +++ b/src/journald/instutil.h @@ -31,6 +31,8 @@ int create_LMI_JournalLogRecordRef(sd_journal *j, LMI_JournalLogRecordRef *ref, const CMPIBroker *_cb); int create_LMI_JournalLogRecord(sd_journal *j, LMI_JournalLogRecord *rec, const CMPIBroker *_cb); +int match_journal_record(sd_journal *j, const char *message, const char *code_func); + void ind_init(); bool ind_watcher(void **data); bool ind_filter_cb(const CMPISelectExp *filter); |