|
|
c16178 |
From f85ef7aabcec84497a5eaf9670616b3402c79d9c Mon Sep 17 00:00:00 2001
|
|
|
c16178 |
From: Rainer Gerhards <rgerhards@adiscon.com>
|
|
|
c16178 |
Date: Sun, 23 Sep 2018 13:19:31 +0200
|
|
|
c16178 |
Subject: File rotation with imfile broken
|
|
|
c16178 |
|
|
|
c16178 |
Previously, truncation was only detected at end of file. Especially with
|
|
|
c16178 |
busy files that could cause loss of data and possibly also stall imfile
|
|
|
c16178 |
reading. The new code now also checks during each read. Obviously, there
|
|
|
c16178 |
is some additional overhead associated with that, but this is unavoidable.
|
|
|
c16178 |
|
|
|
c16178 |
It still is highly recommended NOT to turn on "reopenOnTruncate" in imfile.
|
|
|
c16178 |
Note that there are also inherant reliability issues. There is no way to
|
|
|
c16178 |
"fix" these, as they are caused by races between the process(es) who truncate
|
|
|
c16178 |
and rsyslog reading the file. But with the new code, the "problem window"
|
|
|
c16178 |
should be much smaller and, more importantly, imfile should not stall.
|
|
|
c16178 |
|
|
|
c16178 |
A change in the inode was not detected under all circumstances,
|
|
|
c16178 |
most importantly not in some logrotate cases.
|
|
|
c16178 |
|
|
|
c16178 |
Includes new tests made by Andre Lorbach. They now use the
|
|
|
c16178 |
logrotate tool natively to reproduce the issue.
|
|
|
c16178 |
---
|
|
|
c16178 |
runtime/rsyslog.h | 6 ++--
|
|
|
c16178 |
plugins/imfile/imfile.c | 17 +++-
|
|
|
c16178 |
runtime/stream.c | 122 ++++++++----
|
|
|
c16178 |
runtime/stream.h | 7 ++
|
|
|
c16178 |
4 files changed, 126 insertions(+), 36 deletions(-)
|
|
|
c16178 |
|
|
|
c16178 |
diff --git a/runtime/rsyslog.h b/runtime/rsyslog.h
|
|
|
c16178 |
index 61d0af623..22a1c46d1 100644
|
|
|
c16178 |
--- a/runtime/rsyslog.h
|
|
|
c16178 |
+++ b/runtime/rsyslog.h
|
|
|
c16178 |
@@ -221,9 +221,9 @@ enum rsRetVal_ /** return value. All methods return this if not specified oth
|
|
|
c16178 |
/* begin regular error codes */
|
|
|
c16178 |
RS_RET_NOT_IMPLEMENTED = -7, /**< implementation is missing (probably internal error or lazyness ;)) */
|
|
|
c16178 |
RS_RET_OUT_OF_MEMORY = -6, /**< memory allocation failed */
|
|
|
c16178 |
- RS_RET_PROVIDED_BUFFER_TOO_SMALL = -50,
|
|
|
c16178 |
-/*< the caller provided a buffer, but the called function sees the size of this buffer is too small -
|
|
|
c16178 |
-operation not carried out */
|
|
|
c16178 |
+ RS_RET_PROVIDED_BUFFER_TOO_SMALL = -50, /*< the caller provided a buffer, but the called function sees
|
|
|
c16178 |
+ the size of this buffer is too small - operation not carried out */
|
|
|
c16178 |
+ RS_RET_FILE_TRUNCATED = -51, /**< (input) file was truncated, not an error but a status */
|
|
|
c16178 |
RS_RET_TRUE = -3, /**< to indicate a true state (can be used as TRUE, legacy) */
|
|
|
c16178 |
RS_RET_FALSE = -2, /**< to indicate a false state (can be used as FALSE, legacy) */
|
|
|
c16178 |
RS_RET_NO_IRET = -8, /**< This is a trick for the debuging system - it means no iRet is provided */
|
|
|
c16178 |
diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c
|
|
|
c16178 |
index f4a4ef9b7..6be8b2999 100644
|
|
|
c16178 |
--- a/plugins/imfile/imfile.c
|
|
|
c16178 |
+++ b/plugins/imfile/imfile.c
|
|
|
c16178 |
@@ -740,8 +740,19 @@ detect_updates(fs_edge_t *const edge)
|
|
|
c16178 |
act_obj_unlink(act);
|
|
|
c16178 |
restart = 1;
|
|
|
c16178 |
break;
|
|
|
c16178 |
+ } else if(fileInfo.st_ino != act->ino) {
|
|
|
c16178 |
+ DBGPRINTF("file '%s' inode changed from %llu to %llu, unlinking from "
|
|
|
c16178 |
+ "internal lists\n", act->name, (long long unsigned) act->ino,
|
|
|
c16178 |
+ (long long unsigned) fileInfo.st_ino);
|
|
|
c16178 |
+ if(act->pStrm != NULL) {
|
|
|
c16178 |
+ /* we do no need to re-set later, as act_obj_unlink
|
|
|
c16178 |
+ * will destroy the strm obj */
|
|
|
c16178 |
+ strmSet_checkRotation(act->pStrm, STRM_ROTATION_DO_NOT_CHECK);
|
|
|
c16178 |
+ }
|
|
|
c16178 |
+ act_obj_unlink(act);
|
|
|
c16178 |
+ restart = 1;
|
|
|
c16178 |
+ break;
|
|
|
c16178 |
}
|
|
|
c16178 |
- // TODO: add inode check for change notification!
|
|
|
c16178 |
|
|
|
c16178 |
}
|
|
|
c16178 |
|
|
|
c16178 |
@@ -993,10 +1004,10 @@ chk_active(const act_obj_t *act, const act_obj_t *const deleted)
|
|
|
c16178 |
/* unlink act object from linked list and then
|
|
|
c16178 |
* destruct it.
|
|
|
c16178 |
*/
|
|
|
c16178 |
-static void //ATTR_NONNULL()
|
|
|
c16178 |
+static void ATTR_NONNULL()
|
|
|
c16178 |
act_obj_unlink(act_obj_t *act)
|
|
|
c16178 |
{
|
|
|
c16178 |
- DBGPRINTF("act_obj_unlink %p: %s\n", act, act->name);
|
|
|
c16178 |
+ DBGPRINTF("act_obj_unlink %p: %s, pStrm %p\n", act, act->name, act->pStrm);
|
|
|
c16178 |
if(act->prev == NULL) {
|
|
|
c16178 |
act->edge->active = act->next;
|
|
|
c16178 |
} else {
|
|
|
c16178 |
diff --git a/runtime/stream.c b/runtime/stream.c
|
|
|
c16178 |
index 0f4197103..32a12b256 100644
|
|
|
c16178 |
--- a/runtime/stream.c
|
|
|
c16178 |
+++ b/runtime/stream.c
|
|
|
c16178 |
@@ -400,6 +400,7 @@ static rsRetVal strmOpenFile(strm_t *pThis)
|
|
|
c16178 |
CHKiRet(doPhysOpen(pThis));
|
|
|
c16178 |
|
|
|
c16178 |
pThis->iCurrOffs = 0;
|
|
|
c16178 |
+ pThis->iBufPtrMax = 0;
|
|
|
c16178 |
CHKiRet(getFileSize(pThis->pszCurrFName, &offset));
|
|
|
c16178 |
if(pThis->tOperationsMode == STREAMMODE_WRITE_APPEND) {
|
|
|
c16178 |
pThis->iCurrOffs = offset;
|
|
|
c16178 |
@@ -636,6 +637,78 @@ strmHandleEOF(strm_t *pThis)
|
|
|
c16178 |
RETiRet;
|
|
|
c16178 |
}
|
|
|
c16178 |
|
|
|
c16178 |
+
|
|
|
c16178 |
+/* helper to checkTruncation */
|
|
|
c16178 |
+static rsRetVal ATTR_NONNULL()
|
|
|
c16178 |
+rereadTruncated(strm_t *const pThis, const char *const reason)
|
|
|
c16178 |
+{
|
|
|
c16178 |
+ DEFiRet;
|
|
|
c16178 |
+
|
|
|
c16178 |
+ LogMsg(errno, RS_RET_FILE_TRUNCATED, LOG_WARNING, "file '%s': truncation detected, "
|
|
|
c16178 |
+ "(%s) - re-start reading from beginning",
|
|
|
c16178 |
+ pThis->pszCurrFName, reason);
|
|
|
c16178 |
+ DBGPRINTF("checkTruncation, file %s last buffer CHANGED\n", pThis->pszCurrFName);
|
|
|
c16178 |
+ CHKiRet(strmCloseFile(pThis));
|
|
|
c16178 |
+ CHKiRet(strmOpenFile(pThis));
|
|
|
c16178 |
+ iRet = RS_RET_FILE_TRUNCATED;
|
|
|
c16178 |
+
|
|
|
c16178 |
+finalize_it:
|
|
|
c16178 |
+ RETiRet;
|
|
|
c16178 |
+}
|
|
|
c16178 |
+/* helper to read:
|
|
|
c16178 |
+ * Check if file has been truncated since last read and, if so, re-set reading
|
|
|
c16178 |
+ * to begin of file. To detect truncation, we try to re-read the last block.
|
|
|
c16178 |
+ * If that does not succeed or different data than from the original read is
|
|
|
c16178 |
+ * returned, truncation is assumed.
|
|
|
c16178 |
+ * NOTE: this function must be called only if truncation is enabled AND
|
|
|
c16178 |
+ * when the previous read buffer still is valid (aka "before the next read").
|
|
|
c16178 |
+ * It is ok to call with a 0-size buffer, which we than assume as begin of
|
|
|
c16178 |
+ * reading. In that case, no truncation will be detected.
|
|
|
c16178 |
+ * rgerhards, 2018-09-20
|
|
|
c16178 |
+ */
|
|
|
c16178 |
+static rsRetVal ATTR_NONNULL()
|
|
|
c16178 |
+checkTruncation(strm_t *const pThis)
|
|
|
c16178 |
+{
|
|
|
c16178 |
+ DEFiRet;
|
|
|
c16178 |
+ int ret;
|
|
|
c16178 |
+ off64_t backseek;
|
|
|
c16178 |
+ assert(pThis->bReopenOnTruncate);
|
|
|
c16178 |
+
|
|
|
c16178 |
+ DBGPRINTF("checkTruncation, file %s, iBufPtrMax %zd\n", pThis->pszCurrFName, pThis->iBufPtrMax);
|
|
|
c16178 |
+ if(pThis->iBufPtrMax == 0) {
|
|
|
c16178 |
+ FINALIZE;
|
|
|
c16178 |
+ }
|
|
|
c16178 |
+
|
|
|
c16178 |
+ int currpos = lseek64(pThis->fd, 0, SEEK_CUR);
|
|
|
c16178 |
+ backseek = -1 * (off64_t) pThis->iBufPtrMax;
|
|
|
c16178 |
+ dbgprintf("checkTruncation in actual processing, currpos %d, backseek is %d\n", (int)currpos, (int) backseek);
|
|
|
c16178 |
+ ret = lseek64(pThis->fd, backseek, SEEK_CUR);
|
|
|
c16178 |
+ if(ret < 0) {
|
|
|
c16178 |
+ iRet = rereadTruncated(pThis, "cannot seek backward to begin of last block");
|
|
|
c16178 |
+ FINALIZE;
|
|
|
c16178 |
+ }
|
|
|
c16178 |
+dbgprintf("checkTruncation seek backwrds: %d\n", ret);
|
|
|
c16178 |
+currpos = lseek64(pThis->fd, 0, SEEK_CUR);
|
|
|
c16178 |
+dbgprintf("checkTruncation in actual processing, NEW currpos %d, backseek is %d\n", (int)currpos, (int) backseek);
|
|
|
c16178 |
+
|
|
|
c16178 |
+ const ssize_t lenRead = read(pThis->fd, pThis->pIOBuf_truncation, pThis->iBufPtrMax);
|
|
|
c16178 |
+ dbgprintf("checkTruncation proof-read: %d bytes\n", (int) lenRead);
|
|
|
c16178 |
+ if(lenRead < 0) {
|
|
|
c16178 |
+ iRet = rereadTruncated(pThis, "last block could not be re-read");
|
|
|
c16178 |
+ FINALIZE;
|
|
|
c16178 |
+ }
|
|
|
c16178 |
+
|
|
|
c16178 |
+ if(!memcmp(pThis->pIOBuf_truncation, pThis->pIOBuf, pThis->iBufPtrMax)) {
|
|
|
c16178 |
+ DBGPRINTF("checkTruncation, file %s last buffer unchanged\n", pThis->pszCurrFName);
|
|
|
c16178 |
+ } else {
|
|
|
c16178 |
+ iRet = rereadTruncated(pThis, "last block data different");
|
|
|
c16178 |
+ }
|
|
|
c16178 |
+
|
|
|
c16178 |
+finalize_it:
|
|
|
c16178 |
+ RETiRet;
|
|
|
c16178 |
+}
|
|
|
c16178 |
+
|
|
|
c16178 |
+
|
|
|
c16178 |
/* read the next buffer from disk
|
|
|
c16178 |
* rgerhards, 2008-02-13
|
|
|
c16178 |
*/
|
|
|
c16178 |
@@ -668,6 +741,13 @@ strmReadBuf(strm_t *pThis, int *padBytes)
|
|
|
c16178 |
toRead = (size_t) bytesLeft;
|
|
|
c16178 |
}
|
|
|
c16178 |
}
|
|
|
c16178 |
+ if(pThis->bReopenOnTruncate) {
|
|
|
c16178 |
+ rsRetVal localRet = checkTruncation(pThis);
|
|
|
c16178 |
+ if(localRet == RS_RET_FILE_TRUNCATED) {
|
|
|
c16178 |
+ continue;
|
|
|
c16178 |
+ }
|
|
|
c16178 |
+ CHKiRet(localRet);
|
|
|
c16178 |
+ }
|
|
|
c16178 |
iLenRead = read(pThis->fd, pThis->pIOBuf, toRead);
|
|
|
c16178 |
DBGOPRINT((obj_t*) pThis, "file %d read %ld bytes\n", pThis->fd, iLenRead);
|
|
|
c16178 |
/* end crypto */
|
|
|
c16178 |
@@ -1184,6 +1264,7 @@ static rsRetVal strmConstructFinalize(strm_t *pThis)
|
|
|
c16178 |
} else {
|
|
|
c16178 |
/* we work synchronously, so we need to alloc a fixed pIOBuf */
|
|
|
c16178 |
CHKmalloc(pThis->pIOBuf = (uchar*) MALLOC(pThis->sIOBufSize));
|
|
|
c16178 |
+ CHKmalloc(pThis->pIOBuf_truncation = (char*) MALLOC(pThis->sIOBufSize));
|
|
|
c16178 |
}
|
|
|
c16178 |
|
|
|
c16178 |
finalize_it:
|
|
|
c16178 |
@@ -1231,6 +1312,7 @@ CODESTARTobjDestruct(strm)
|
|
|
c16178 |
}
|
|
|
c16178 |
} else {
|
|
|
c16178 |
free(pThis->pIOBuf);
|
|
|
c16178 |
+ free(pThis->pIOBuf_truncation);
|
|
|
c16178 |
}
|
|
|
c16178 |
|
|
|
c16178 |
/* Finally, we can free the resources.
|
|
|
c16178 |
diff --git a/runtime/stream.c b/runtime/stream.c
|
|
|
c16178 |
index 2d494c612..5b52591ef 100644
|
|
|
c16178 |
--- a/runtime/stream.c
|
|
|
c16178 |
+++ b/runtime/stream.c
|
|
|
c16178 |
@@ -360,8 +360,8 @@ CheckFileChange(strm_t *pThis)
|
|
|
c16178 |
CHKiRet(strmSetCurrFName(pThis));
|
|
|
c16178 |
if(stat((char*) pThis->pszCurrFName, &statName) == -1)
|
|
|
c16178 |
ABORT_FINALIZE(RS_RET_IO_ERROR);
|
|
|
c16178 |
- DBGPRINTF("stream/after deserialize checking for file change on '%s', "
|
|
|
c16178 |
- "inode %u/%u, size/currOffs %llu/%llu\n",
|
|
|
c16178 |
+ DBGPRINTF("CheckFileChange: stream/after deserialize checking for file change "
|
|
|
c16178 |
+ "on '%s', inode %u/%u, size/currOffs %llu/%llu\n",
|
|
|
c16178 |
pThis->pszCurrFName, (unsigned) pThis->inode,
|
|
|
c16178 |
(unsigned) statName.st_ino,
|
|
|
c16178 |
(long long unsigned) statName.st_size,
|
|
|
c16178 |
@@ -574,8 +574,8 @@ strmNextFile(strm_t *pThis)
|
|
|
c16178 |
* circumstances). So starting as of now, we only check the inode number and
|
|
|
c16178 |
* a file change is detected only if the inode changes. -- rgerhards, 2011-01-10
|
|
|
c16178 |
*/
|
|
|
c16178 |
-static rsRetVal
|
|
|
c16178 |
-strmHandleEOFMonitor(strm_t *pThis)
|
|
|
c16178 |
+static rsRetVal ATTR_NONNULL()
|
|
|
c16178 |
+strmHandleEOFMonitor(strm_t *const pThis)
|
|
|
c16178 |
{
|
|
|
c16178 |
DEFiRet;
|
|
|
c16178 |
struct stat statName;
|
|
|
c16178 |
@@ -611,8 +611,8 @@ strmHandleEOFMonitor(strm_t *pThis)
|
|
|
c16178 |
* try to open the next one.
|
|
|
c16178 |
* rgerhards, 2008-02-13
|
|
|
c16178 |
*/
|
|
|
c16178 |
-static rsRetVal
|
|
|
c16178 |
-strmHandleEOF(strm_t *pThis)
|
|
|
c16178 |
+static rsRetVal ATTR_NONNULL()
|
|
|
c16178 |
+strmHandleEOF(strm_t *const pThis)
|
|
|
c16178 |
{
|
|
|
c16178 |
DEFiRet;
|
|
|
c16178 |
|
|
|
c16178 |
@@ -629,7 +629,13 @@ strmHandleEOF(strm_t *pThis)
|
|
|
c16178 |
CHKiRet(strmNextFile(pThis));
|
|
|
c16178 |
break;
|
|
|
c16178 |
case STREAMTYPE_FILE_MONITOR:
|
|
|
c16178 |
- CHKiRet(strmHandleEOFMonitor(pThis));
|
|
|
c16178 |
+ DBGOPRINT((obj_t*) pThis, "file '%s' (%d) EOF, rotationCheck %d\n",
|
|
|
c16178 |
+ pThis->pszCurrFName, pThis->fd, pThis->rotationCheck);
|
|
|
c16178 |
+ if(pThis->rotationCheck == STRM_ROTATION_DO_CHECK) {
|
|
|
c16178 |
+ CHKiRet(strmHandleEOFMonitor(pThis));
|
|
|
c16178 |
+ } else {
|
|
|
c16178 |
+ ABORT_FINALIZE(RS_RET_EOF);
|
|
|
c16178 |
+ }
|
|
|
c16178 |
break;
|
|
|
c16178 |
}
|
|
|
c16178 |
|
|
|
c16178 |
@@ -687,9 +693,6 @@ checkTruncation(strm_t *const pThis)
|
|
|
c16178 |
iRet = rereadTruncated(pThis, "cannot seek backward to begin of last block");
|
|
|
c16178 |
FINALIZE;
|
|
|
c16178 |
}
|
|
|
c16178 |
-dbgprintf("checkTruncation seek backwrds: %d\n", ret);
|
|
|
c16178 |
-currpos = lseek64(pThis->fd, 0, SEEK_CUR);
|
|
|
c16178 |
-dbgprintf("checkTruncation in actual processing, NEW currpos %d, backseek is %d\n", (int)currpos, (int) backseek);
|
|
|
c16178 |
|
|
|
c16178 |
const ssize_t lenRead = read(pThis->fd, pThis->pIOBuf_truncation, pThis->iBufPtrMax);
|
|
|
c16178 |
dbgprintf("checkTruncation proof-read: %d bytes\n", (int) lenRead);
|
|
|
c16178 |
@@ -861,7 +864,7 @@ static rsRetVal strmUnreadChar(strm_t *pThis, uchar c)
|
|
|
c16178 |
* a line, but following lines that are indented are part of the same log entry
|
|
|
c16178 |
*/
|
|
|
c16178 |
static rsRetVal
|
|
|
c16178 |
-strmReadLine(strm_t *pThis, cstr_t **ppCStr, uint8_t mode, sbool bEscapeLF,
|
|
|
c16178 |
+strmReadLine(strm_t *const pThis, cstr_t **ppCStr, uint8_t mode, sbool bEscapeLF,
|
|
|
c16178 |
uint32_t trimLineOverBytes, int64 *const strtOffs)
|
|
|
c16178 |
{
|
|
|
c16178 |
uchar c;
|
|
|
c16178 |
@@ -2147,14 +2150,25 @@ DEFpropSetMeth(strm, cryprov, cryprov_if_t*)
|
|
|
c16178 |
DEFpropSetMeth(strm, cryprovData, void*)
|
|
|
c16178 |
|
|
|
c16178 |
/* sets timeout in seconds */
|
|
|
c16178 |
-void
|
|
|
c16178 |
+void ATTR_NONNULL()
|
|
|
c16178 |
strmSetReadTimeout(strm_t *const __restrict__ pThis, const int val)
|
|
|
c16178 |
{
|
|
|
c16178 |
+ ISOBJ_TYPE_assert(pThis, strm);
|
|
|
c16178 |
pThis->readTimeout = val;
|
|
|
c16178 |
}
|
|
|
c16178 |
|
|
|
c16178 |
-static rsRetVal strmSetbDeleteOnClose(strm_t *pThis, int val)
|
|
|
c16178 |
+void ATTR_NONNULL()
|
|
|
c16178 |
+strmSet_checkRotation(strm_t *const pThis, const int val) {
|
|
|
c16178 |
+ ISOBJ_TYPE_assert(pThis, strm);
|
|
|
c16178 |
+ assert(val == STRM_ROTATION_DO_CHECK || val == STRM_ROTATION_DO_NOT_CHECK);
|
|
|
c16178 |
+ pThis->rotationCheck = val;
|
|
|
c16178 |
+}
|
|
|
c16178 |
+
|
|
|
c16178 |
+
|
|
|
c16178 |
+static rsRetVal ATTR_NONNULL()
|
|
|
c16178 |
+strmSetbDeleteOnClose(strm_t *const pThis, const int val)
|
|
|
c16178 |
{
|
|
|
c16178 |
+ ISOBJ_TYPE_assert(pThis, strm);
|
|
|
c16178 |
pThis->bDeleteOnClose = val;
|
|
|
c16178 |
if(pThis->cryprov != NULL) {
|
|
|
c16178 |
pThis->cryprov->SetDeleteOnClose(pThis->cryprovFileData, pThis->bDeleteOnClose);
|
|
|
c16178 |
@@ -2162,15 +2176,19 @@ static rsRetVal strmSetbDeleteOnClose(strm_t *pThis, int val)
|
|
|
c16178 |
return RS_RET_OK;
|
|
|
c16178 |
}
|
|
|
c16178 |
|
|
|
c16178 |
-static rsRetVal strmSetiMaxFiles(strm_t *pThis, int iNewVal)
|
|
|
c16178 |
+static rsRetVal ATTR_NONNULL()
|
|
|
c16178 |
+strmSetiMaxFiles(strm_t *const pThis, const int iNewVal)
|
|
|
c16178 |
{
|
|
|
c16178 |
+ ISOBJ_TYPE_assert(pThis, strm);
|
|
|
c16178 |
pThis->iMaxFiles = iNewVal;
|
|
|
c16178 |
pThis->iFileNumDigits = getNumberDigits(iNewVal);
|
|
|
c16178 |
return RS_RET_OK;
|
|
|
c16178 |
}
|
|
|
c16178 |
|
|
|
c16178 |
-static rsRetVal strmSetFileNotFoundError(strm_t *pThis, int pFileNotFoundError)
|
|
|
c16178 |
+static rsRetVal ATTR_NONNULL()
|
|
|
c16178 |
+strmSetFileNotFoundError(strm_t *const pThis, const int pFileNotFoundError)
|
|
|
c16178 |
{
|
|
|
c16178 |
+ ISOBJ_TYPE_assert(pThis, strm);
|
|
|
c16178 |
pThis->fileNotFoundError = pFileNotFoundError;
|
|
|
c16178 |
return RS_RET_OK;
|
|
|
c16178 |
}
|
|
|
c16178 |
diff --git a/runtime/stream.h b/runtime/stream.h
|
|
|
c16178 |
index 7dc597ff5..e3d6c2372 100644
|
|
|
c16178 |
--- a/runtime/stream.h
|
|
|
c16178 |
+++ b/runtime/stream.h
|
|
|
c16178 |
@@ -124,6 +124,7 @@ typedef struct strm_s {
|
|
|
c16178 |
ino_t inode; /* current inode for files being monitored (undefined else) */
|
|
|
c16178 |
uchar *pszCurrFName; /* name of current file (if open) */
|
|
|
c16178 |
uchar *pIOBuf; /* the iobuffer currently in use to gather data */
|
|
|
c16178 |
+ char *pIOBuf_truncation; /* iobuffer used during trucation detection block re-reads */
|
|
|
c16178 |
size_t iBufPtrMax; /* current max Ptr in Buffer (if partial read!) */
|
|
|
c16178 |
size_t iBufPtr; /* pointer into current buffer */
|
|
|
c16178 |
int iUngetC; /* char set via UngetChar() call or -1 if none set */
|
|
|
c16178 |
|
|
|
c16178 |
diff --git a/runtime/stream.h b/runtime/stream.h
|
|
|
c16178 |
index e3d6c2372..f6f48378a 100644
|
|
|
c16178 |
--- a/runtime/stream.h
|
|
|
c16178 |
+++ b/runtime/stream.h
|
|
|
c16178 |
@@ -91,6 +91,10 @@ typedef enum { /* when extending, do NOT change existing modes! */
|
|
|
c16178 |
STREAMMODE_WRITE_APPEND = 4
|
|
|
c16178 |
} strmMode_t;
|
|
|
c16178 |
|
|
|
c16178 |
+/* settings for stream rotation (applies not to all processing modes!) */
|
|
|
c16178 |
+#define STRM_ROTATION_DO_CHECK 0
|
|
|
c16178 |
+#define STRM_ROTATION_DO_NOT_CHECK 1
|
|
|
c16178 |
+
|
|
|
c16178 |
#define STREAM_ASYNC_NUMBUFS 2 /* must be a power of 2 -- TODO: make configurable */
|
|
|
c16178 |
/* The strm_t data structure */
|
|
|
c16178 |
typedef struct strm_s {
|
|
|
c16178 |
@@ -114,6 +118,7 @@ typedef struct strm_s {
|
|
|
c16178 |
sbool bDisabled; /* should file no longer be written to? (currently set only if omfile file size limit fails) */
|
|
|
c16178 |
sbool bSync; /* sync this file after every write? */
|
|
|
c16178 |
sbool bReopenOnTruncate;
|
|
|
c16178 |
+ int rotationCheck; /* rotation check mode */
|
|
|
c16178 |
size_t sIOBufSize;/* size of IO buffer */
|
|
|
c16178 |
uchar *pszDir; /* Directory */
|
|
|
c16178 |
int lenDir;
|
|
|
c16178 |
@@ -234,5 +239,6 @@ void strmSetReadTimeout(strm_t *const __restrict__ pThis, const int val);
|
|
|
c16178 |
const uchar * ATTR_NONNULL() strmGetPrevLineSegment(strm_t *const pThis);
|
|
|
c16178 |
const uchar * ATTR_NONNULL() strmGetPrevMsgSegment(strm_t *const pThis);
|
|
|
c16178 |
int ATTR_NONNULL() strmGetPrevWasNL(const strm_t *const pThis);
|
|
|
c16178 |
+void ATTR_NONNULL() strmSet_checkRotation(strm_t *const pThis, const int val);
|
|
|
c16178 |
|
|
|
c16178 |
#endif /* #ifndef STREAM_H_INCLUDED */
|