From fed69cc7ac1bccb7012a68d954b58c6de9ad75e7 Mon Sep 17 00:00:00 2001
From: Tomas Heinrich <theinric@redhat.com>
Date: Sun, 10 Jul 2016 23:46:42 +0200
Subject: [PATCH] Make state file handling in imjournal more robust
---
plugins/imjournal/imjournal.c | 98 ++++++++++++++++++++++++++++++-------------
1 file changed, 70 insertions(+), 28 deletions(-)
diff --git a/plugins/imjournal/imjournal.c b/plugins/imjournal/imjournal.c
index f97b745..1ebbd1c 100755
--- a/plugins/imjournal/imjournal.c
+++ b/plugins/imjournal/imjournal.c
@@ -70,6 +70,7 @@ static struct configSettings_s {
int ratelimitInterval;
int ratelimitBurst;
int bIgnorePrevious;
+ int bIgnoreNonValidStatefile;
int iDfltSeverity;
int iDfltFacility;
char *dfltTag;
@@ -84,6 +85,7 @@ static struct cnfparamdescr modpdescr[] = {
{ "ratelimit.burst", eCmdHdlrInt, 0 },
{ "persiststateinterval", eCmdHdlrInt, 0 },
{ "ignorepreviousmessages", eCmdHdlrBinary, 0 },
+ { "ignorenonvalidstatefile", eCmdHdlrBinary, 0 },
{ "defaultseverity", eCmdHdlrSeverity, 0 },
{ "defaultfacility", eCmdHdlrString, 0 },
{ "defaulttag", eCmdHdlrGetWord, 0 },
@@ -441,23 +443,36 @@ static rsRetVal
persistJournalState () {
DEFiRet;
FILE *sf; /* state file */
+ char tmp_sf[MAXFNAME];
char *cursor;
int ret = 0;
/* On success, sd_journal_get_cursor() returns 1 in systemd
197 or older and 0 in systemd 198 or newer */
if ((ret = sd_journal_get_cursor(j, &cursor)) >= 0) {
- if ((sf = fopen(cs.stateFile, "wb")) != NULL) {
+ /* we create a temporary name by adding a ".tmp"
+ * suffix to the end of our state file's name
+ */
+ snprintf(tmp_sf, sizeof(tmp_sf), "%s.tmp", cs.stateFile);
+ if ((sf = fopen(tmp_sf, "wb")) != NULL) {
if (fprintf(sf, "%s", cursor) < 0) {
iRet = RS_RET_IO_ERROR;
}
fclose(sf);
free(cursor);
+ /* change the name of the file to the configured one */
+ if (iRet == RS_RET_OK && rename(tmp_sf, cs.stateFile) == -1) {
+ char errStr[256];
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ iRet = RS_RET_IO_ERROR;
+ errmsg.LogError(0, iRet, "rename() failed: "
+ "'%s', new path: '%s'\n", errStr, cs.stateFile);
+ }
} else {
char errStr[256];
rs_strerror_r(errno, errStr, sizeof(errStr));
errmsg.LogError(0, RS_RET_FOPEN_FAILURE, "fopen() failed: "
- "'%s', path: '%s'\n", errStr, cs.stateFile);
+ "'%s', path: '%s'\n", errStr, tmp_sf);
iRet = RS_RET_FOPEN_FAILURE;
}
} else {
@@ -515,6 +530,35 @@ finalize_it:
RETiRet;
}
+/* Seek to the very end of the journal and ignore all older
+ * messages.
+ */
+static rsRetVal
+skipOldMessages(void)
+{
+ DEFiRet;
+
+ if (sd_journal_seek_tail(j) < 0) {
+ char errStr[256];
+
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ errmsg.LogError(0, RS_RET_ERR,
+ "sd_journal_seek_tail() failed: '%s'", errStr);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ if (sd_journal_previous(j) < 0) {
+ char errStr[256];
+
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ errmsg.LogError(0, RS_RET_ERR,
+ "sd_journal_previous() failed: '%s'", errStr);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+finalize_it:
+ RETiRet;
+
+}
/* This function loads a journal cursor from the state file.
*/
@@ -546,41 +590,32 @@ loadJournalState()
errmsg.LogError(0, RS_RET_ERR, "imjournal: "
"couldn't seek to cursor `%s'\n", readCursor);
iRet = RS_RET_ERR;
- goto finalize_it;
+ } else {
+ sd_journal_next(j);
}
- sd_journal_next(j);
} else {
errmsg.LogError(0, RS_RET_IO_ERROR, "imjournal: "
"fscanf on state file `%s' failed\n", cs.stateFile);
iRet = RS_RET_IO_ERROR;
- goto finalize_it;
}
+
fclose(r_sf);
+
+ if (iRet != RS_RET_OK && cs.bIgnoreNonValidStatefile) {
+ /* ignore state file errors */
+ iRet = RS_RET_OK;
+ errmsg.LogError(0, NO_ERRCODE,
+ "imjournal: ignoring invalid state file");
+ if (cs.bIgnorePrevious) {
+ skipOldMessages();
+ }
+ }
} else {
errmsg.LogError(0, RS_RET_FOPEN_FAILURE, "imjournal: "
"open on state file `%s' failed\n", cs.stateFile);
}
- } else {
- /* when IgnorePrevious, seek to the end of journal */
- if (cs.bIgnorePrevious) {
- if (sd_journal_seek_tail(j) < 0) {
- char errStr[256];
-
- rs_strerror_r(errno, errStr, sizeof(errStr));
- errmsg.LogError(0, RS_RET_ERR,
- "sd_journal_seek_tail() failed: '%s'", errStr);
- ABORT_FINALIZE(RS_RET_ERR);
- }
-
- if (sd_journal_previous(j) < 0) {
- char errStr[256];
-
- rs_strerror_r(errno, errStr, sizeof(errStr));
- errmsg.LogError(0, RS_RET_ERR,
- "sd_journal_previous() failed: '%s'", errStr);
- ABORT_FINALIZE(RS_RET_ERR);
- }
- }
+ } else if (cs.bIgnorePrevious) {
+ skipOldMessages();
}
finalize_it:
@@ -598,6 +633,8 @@ CODESTARTrunInput
if (cs.stateFile) {
CHKiRet(loadJournalState());
+ } else if (cs.bIgnorePrevious) {
+ skipOldMessages();
}
/* this is an endless loop - it is terminated when the thread is
@@ -641,6 +678,7 @@ BEGINbeginCnfLoad
CODESTARTbeginCnfLoad
bLegacyCnfModGlobalsPermitted = 1;
+ cs.bIgnoreNonValidStatefile = 1;
cs.iPersistStateInterval = DFLT_persiststateinterval;
cs.stateFile = NULL;
cs.ratelimitBurst = 20000;
@@ -739,7 +777,9 @@ CODESTARTsetModCnf
} else if(!strcmp(modpblk.descr[i].name, "ratelimit.interval")) {
cs.ratelimitInterval = (int) pvals[i].val.d.n;
} else if (!strcmp(modpblk.descr[i].name, "ignorepreviousmessages")) {
- cs.bIgnorePrevious = (int) pvals[i].val.d.n;
+ cs.bIgnorePrevious = (int) pvals[i].val.d.n;
+ } else if (!strcmp(modpblk.descr[i].name, "ignorenonvalidstatefile")) {
+ cs.bIgnoreNonValidStatefile = (int) pvals[i].val.d.n;
} else if (!strcmp(modpblk.descr[i].name, "defaultseverity")) {
cs.iDfltSeverity = (int) pvals[i].val.d.n;
} else if (!strcmp(modpblk.descr[i].name, "defaultfacility")) {
@@ -806,7 +846,9 @@ CODEmodInit_QueryRegCFSLineHdlr
CHKiRet(omsdRegCFSLineHdlr((uchar *)"imjournalstatefile", 0, eCmdHdlrGetWord,
NULL, &cs.stateFile, STD_LOADABLE_MODULE_ID));
CHKiRet(omsdRegCFSLineHdlr((uchar *)"imjournalignorepreviousmessages", 0, eCmdHdlrBinary,
- NULL, &cs.bIgnorePrevious, STD_LOADABLE_MODULE_ID));
+ NULL, &cs.bIgnorePrevious, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"imjournalignorenonvalidstatefile", 0, eCmdHdlrBinary,
+ NULL, &cs.bIgnoreNonValidStatefile, STD_LOADABLE_MODULE_ID));
CHKiRet(omsdRegCFSLineHdlr((uchar *)"imjournaldefaultseverity", 0, eCmdHdlrSeverity,
NULL, &cs.iDfltSeverity, STD_LOADABLE_MODULE_ID));
CHKiRet(omsdRegCFSLineHdlr((uchar *)"imjournaldefaultfacility", 0, eCmdHdlrCustomHandler,
--
2.5.5