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