Blame SOURCES/rsyslog-8.2102.0-rhbz2064318-errfile-maxsize.patch

6e9fa2
--- rsyslog-8.2102.0-ori/action.c	2021-02-15 12:06:16.000000000 +0100
6e9fa2
+++ rsyslog-8.2102.0-changes/action.c	2022-03-10 11:00:11.027242300 +0100
6e9fa2
@@ -198,6 +198,7 @@
6e9fa2
 	{ "name", eCmdHdlrGetWord, 0 }, /* legacy: actionname */
6e9fa2
 	{ "type", eCmdHdlrString, CNFPARAM_REQUIRED }, /* legacy: actionname */
6e9fa2
 	{ "action.errorfile", eCmdHdlrString, 0 },
6e9fa2
+	{ "action.errorfile.maxsize", eCmdHdlrInt, 0 },
6e9fa2
 	{ "action.writeallmarkmessages", eCmdHdlrBinary, 0 }, /* legacy: actionwriteallmarkmessages */
6e9fa2
 	{ "action.execonlyeverynthtime", eCmdHdlrInt, 0 }, /* legacy: actionexeconlyeverynthtime */
6e9fa2
 	{ "action.execonlyeverynthtimetimeout", eCmdHdlrInt, 0 }, /* legacy: actionexeconlyeverynthtimetimeout */
6e9fa2
@@ -400,6 +401,8 @@
6e9fa2
 	pThis->iResumeRetryCount = 0;
6e9fa2
 	pThis->pszName = NULL;
6e9fa2
 	pThis->pszErrFile = NULL;
6e9fa2
+	pThis->maxErrFileSize = 0;
6e9fa2
+	pThis->errFileWritten = 0;
6e9fa2
 	pThis->pszExternalStateFile = NULL;
6e9fa2
 	pThis->fdErrFile = -1;
6e9fa2
 	pThis->bWriteAllMarkMsgs = 1;
6e9fa2
@@ -1436,6 +1439,14 @@
6e9fa2
 				pThis->pszName, pThis->pszErrFile);
6e9fa2
 			goto done;
6e9fa2
 		}
6e9fa2
+		if (pThis->maxErrFileSize > 0) {
6e9fa2
+			struct stat statbuf;
6e9fa2
+			if (fstat(pThis->fdErrFile, &statbuf) == -1) {
6e9fa2
+				LogError(errno, RS_RET_ERR, "failed to fstat %s", pThis->pszErrFile);
6e9fa2
+				goto done;
6e9fa2
+			}
6e9fa2
+			pThis->errFileWritten += statbuf.st_size;
6e9fa2
+		}
6e9fa2
 	}
6e9fa2
 
6e9fa2
 	for(int i = 0 ; i < nparams ; ++i) {
6e9fa2
@@ -1454,16 +1465,26 @@
6e9fa2
 		char *const rendered = strdup((char*)fjson_object_to_json_string(etry));
6e9fa2
 		if(rendered == NULL)
6e9fa2
 			goto done;
6e9fa2
-		const size_t toWrite = strlen(rendered) + 1;
6e9fa2
-		/* note: we use the '\0' inside the string to store a LF - we do not
6e9fa2
-		 * otherwise need it and it safes us a copy/realloc.
6e9fa2
-		 */
6e9fa2
-		rendered[toWrite-1] = '\n'; /* NO LONGER A STRING! */
6e9fa2
-		const ssize_t wrRet = write(pThis->fdErrFile, rendered, toWrite);
6e9fa2
-		if(wrRet != (ssize_t) toWrite) {
6e9fa2
-			LogError(errno, RS_RET_IO_ERROR,
6e9fa2
-				"action %s: error writing errorFile %s, write returned %lld",
6e9fa2
-				pThis->pszName, pThis->pszErrFile, (long long) wrRet);
6e9fa2
+		size_t toWrite = strlen(rendered) + 1;
6e9fa2
+		// Check if need to truncate the amount of bytes to write
6e9fa2
+		if (pThis->maxErrFileSize > 0) {
6e9fa2
+			if (pThis->errFileWritten + toWrite > pThis->maxErrFileSize) {
6e9fa2
+				// Truncate to the pending available
6e9fa2
+				toWrite = pThis->maxErrFileSize - pThis->errFileWritten;
6e9fa2
+			}
6e9fa2
+			pThis->errFileWritten += toWrite;
6e9fa2
+		}
6e9fa2
+		if(toWrite > 0) {
6e9fa2
+			/* note: we use the '\0' inside the string to store a LF - we do not
6e9fa2
+			 * otherwise need it and it safes us a copy/realloc.
6e9fa2
+			 */
6e9fa2
+			rendered[toWrite-1] = '\n'; /* NO LONGER A STRING! */
6e9fa2
+			const ssize_t wrRet = write(pThis->fdErrFile, rendered, toWrite);
6e9fa2
+			if(wrRet != (ssize_t) toWrite) {
6e9fa2
+				LogError(errno, RS_RET_IO_ERROR,
6e9fa2
+					"action %s: error writing errorFile %s, write returned %lld",
6e9fa2
+					pThis->pszName, pThis->pszErrFile, (long long) wrRet);
6e9fa2
+			}
6e9fa2
 		}
6e9fa2
 		free(rendered);
6e9fa2
 
6e9fa2
@@ -2048,6 +2069,8 @@
6e9fa2
 			continue; /* this is handled seperately during module select! */
6e9fa2
 		} else if(!strcmp(pblk.descr[i].name, "action.errorfile")) {
6e9fa2
 			pAction->pszErrFile = es_str2cstr(pvals[i].val.d.estr, NULL);
6e9fa2
+		} else if(!strcmp(pblk.descr[i].name, "action.errorfile.maxsize")) {
6e9fa2
+			pAction->maxErrFileSize = pvals[i].val.d.n;
6e9fa2
 		} else if(!strcmp(pblk.descr[i].name, "action.externalstate.file")) {
6e9fa2
 			pAction->pszExternalStateFile = es_str2cstr(pvals[i].val.d.estr, NULL);
6e9fa2
 		} else if(!strcmp(pblk.descr[i].name, "action.writeallmarkmessages")) {
6e9fa2
--- rsyslog-8.2102.0-ori/action.h	2020-10-03 19:06:47.000000000 +0200
6e9fa2
+++ rsyslog-8.2102.0-changes/action.h	2022-03-04 11:36:47.024588972 +0100
6e9fa2
@@ -77,6 +77,8 @@
6e9fa2
 	/* error file */
6e9fa2
 	const char *pszErrFile;
6e9fa2
 	int fdErrFile;
6e9fa2
+	size_t maxErrFileSize;
6e9fa2
+	size_t errFileWritten;
6e9fa2
 	pthread_mutex_t mutErrFile;
6e9fa2
 	/* external stat file system */
6e9fa2
 	const char *pszExternalStateFile;
6e9fa2
--- rsyslog-8.2102.0-ori/tests/Makefile.am	2021-02-15 12:06:16.000000000 +0100
6e9fa2
+++ rsyslog-8.2102.0-changes/tests/Makefile.am	2022-03-04 11:38:01.625095709 +0100
6e9fa2
@@ -695,7 +695,8 @@
6e9fa2
 	mysql-actq-mt.sh \
6e9fa2
 	mysql-actq-mt-withpause.sh \
6e9fa2
 	action-tx-single-processing.sh \
6e9fa2
-	action-tx-errfile.sh
6e9fa2
+	action-tx-errfile.sh \
6e9fa2
+	action-tx-errfile-maxsize.sh
6e9fa2
 
6e9fa2
 mysql-basic.log: mysqld-start.log
6e9fa2
 mysql-basic-cnf6.log: mysqld-start.log
6e9fa2
@@ -2156,6 +2157,8 @@
6e9fa2
 	sndrcv_omudpspoof_nonstdpt.sh \
6e9fa2
 	sndrcv_gzip.sh \
6e9fa2
 	action-tx-single-processing.sh \
6e9fa2
+	omfwd-errfile-maxsize.sh \
6e9fa2
+	action-tx-errfile-maxsize.sh \
6e9fa2
 	action-tx-errfile.sh \
6e9fa2
 	testsuites/action-tx-errfile.result \
6e9fa2
 	pipeaction.sh \
6e9fa2
--- rsyslog-8.2102.0-ori/tests/omfwd-errfile-maxsize.sh	1970-01-01 01:00:00.000000000 +0100
6e9fa2
+++ rsyslog-8.2102.0-changes/tests/omfwd-errfile-maxsize.sh	2022-03-04 11:39:02.060506234 +0100
6e9fa2
@@ -0,0 +1,17 @@
6e9fa2
+#!/bin/bash
6e9fa2
+# part of the rsyslog project, released under ASL 2.0
6e9fa2
+. ${srcdir:=.}/diag.sh init
6e9fa2
+
6e9fa2
+export MAX_ERROR_SIZE=1999
6e9fa2
+
6e9fa2
+generate_conf
6e9fa2
+add_conf '
6e9fa2
+action(type="omfwd" target="1.2.3.4" port="1234" Protocol="tcp" NetworkNamespace="doesNotExist"
6e9fa2
+       action.errorfile="'$RSYSLOG2_OUT_LOG'" action.errorfile.maxsize="'$MAX_ERROR_SIZE'")
6e9fa2
+'
6e9fa2
+startup
6e9fa2
+shutdown_when_empty
6e9fa2
+wait_shutdown
6e9fa2
+check_file_exists ${RSYSLOG2_OUT_LOG}
6e9fa2
+file_size_check ${RSYSLOG2_OUT_LOG} ${MAX_ERROR_SIZE}
6e9fa2
+exit_test
6e9fa2
--- rsyslog-8.2102.0-ori/tests/action-tx-errfile-maxsize.sh	1970-01-01 01:00:00.000000000 +0100
6e9fa2
+++ rsyslog-8.2102.0-changes/tests/action-tx-errfile-maxsize.sh	2022-03-04 11:59:22.592796989 +0100
6e9fa2
@@ -0,0 +1,35 @@
6e9fa2
+#!/bin/bash
6e9fa2
+# part of the rsyslog project, released under ASL 2.0
6e9fa2
+
6e9fa2
+. ${srcdir:=.}/diag.sh init
6e9fa2
+
6e9fa2
+export NUMMESSAGES=50 # enough to generate big file
6e9fa2
+export MAX_ERROR_SIZE=100
6e9fa2
+
6e9fa2
+generate_conf
6e9fa2
+add_conf '
6e9fa2
+$ModLoad ../plugins/ommysql/.libs/ommysql
6e9fa2
+global(errormessagestostderr.maxnumber="5")
6e9fa2
+
6e9fa2
+template(type="string" name="tpl" string="insert into SystemEvents (Message, Facility) values (\"%msg%\", %$!facility%)" option.sql="on")
6e9fa2
+
6e9fa2
+if((not($msg contains "error")) and ($msg contains "msgnum:")) then {
6e9fa2
+	set $.num = field($msg, 58, 2);
6e9fa2
+	if $.num % 2 == 0 then {
6e9fa2
+		set $!facility = $syslogfacility;
6e9fa2
+	} else {
6e9fa2
+		set $/cntr = 0;
6e9fa2
+	}
6e9fa2
+	action(type="ommysql" name="mysql_action_errfile_maxsize" server="127.0.0.1" template="tpl"
6e9fa2
+	       db="'$RSYSLOG_DYNNAME'" uid="rsyslog" pwd="testbench" action.errorfile="'$RSYSLOG2_OUT_LOG'" action.errorfile.maxsize="'$MAX_ERROR_SIZE'")
6e9fa2
+}
6e9fa2
+'
6e9fa2
+mysql_prep_for_test
6e9fa2
+startup
6e9fa2
+injectmsg
6e9fa2
+shutdown_when_empty
6e9fa2
+wait_shutdown
6e9fa2
+mysql_get_data
6e9fa2
+check_file_exists ${RSYSLOG2_OUT_LOG}
6e9fa2
+file_size_check ${RSYSLOG2_OUT_LOG} ${MAX_ERROR_SIZE}
6e9fa2
+exit_test
6e9fa2
--- rsyslog-8.2102.0/tests/omfwd-errfile-maxsize-filled.sh	1970-01-01 01:00:00.000000000 +0100
6e9fa2
+++ rsyslog-8.2102.0-changes/tests/omfwd-errfile-maxsize-filled.sh	2022-03-08 16:24:01.174365289 +0100
6e9fa2
@@ -0,0 +1,19 @@
6e9fa2
+#!/bin/bash
6e9fa2
+# part of the rsyslog project, released under ASL 2.0
6e9fa2
+. ${srcdir:=.}/diag.sh init
6e9fa2
+ERRFILE=$(mktemp)
6e9fa2
+export MAX_ERROR_SIZE=1999
6e9fa2
+export INITIAL_FILE_SIZE=$((MAX_ERROR_SIZE - 100))
6e9fa2
+dd if=/dev/urandom of=${ERRFILE}  bs=1 count=${INITIAL_FILE_SIZE}
6e9fa2
+generate_conf
6e9fa2
+add_conf '
6e9fa2
+action(type="omfwd" target="1.2.3.4" port="1234" Protocol="tcp" NetworkNamespace="doesNotExist"
6e9fa2
+       action.errorfile="'$ERRFILE'" action.errorfile.maxsize="'$MAX_ERROR_SIZE'")
6e9fa2
+'
6e9fa2
+startup
6e9fa2
+shutdown_when_empty
6e9fa2
+wait_shutdown
6e9fa2
+check_file_exists ${ERRFILE}
6e9fa2
+file_size_check ${ERRFILE} ${MAX_ERROR_SIZE}
6e9fa2
+exit_test
6e9fa2
+rm ${ERRFILE}