summaryrefslogtreecommitdiffstats
path: root/runtime
diff options
context:
space:
mode:
authorRainer Gerhards <rgerhards@adiscon.com>2009-06-12 09:47:44 +0200
committerRainer Gerhards <rgerhards@adiscon.com>2009-06-12 09:47:44 +0200
commit0917edf26da9055c6dc160aafca97896daea3e6c (patch)
treecaeee5f141e982597cd70070eb753ea1154d6720 /runtime
parent1c8fe77b78a64d69138b30ec28b430677b197601 (diff)
downloadrsyslog-0917edf26da9055c6dc160aafca97896daea3e6c.tar.gz
rsyslog-0917edf26da9055c6dc160aafca97896daea3e6c.tar.xz
rsyslog-0917edf26da9055c6dc160aafca97896daea3e6c.zip
re-enabled outchannel functionality
Diffstat (limited to 'runtime')
-rw-r--r--runtime/rsyslog.h3
-rw-r--r--runtime/srUtils.h1
-rw-r--r--runtime/srutils.c27
-rw-r--r--runtime/stream.c130
-rw-r--r--runtime/stream.h7
-rw-r--r--runtime/unicode-helper.h27
6 files changed, 179 insertions, 16 deletions
diff --git a/runtime/rsyslog.h b/runtime/rsyslog.h
index b587554e..92942c70 100644
--- a/runtime/rsyslog.h
+++ b/runtime/rsyslog.h
@@ -289,6 +289,9 @@ enum rsRetVal_ /** return value. All methods return this if not specified oth
RS_RET_PREVIOUS_COMMITTED = -2122, /**< output plugin status: previous record was committed (an OK state!) */
RS_RET_ACTION_FAILED = -2123, /**< action failed and is now suspended (consider this permanent for the time being) */
RS_RET_NONFATAL_CONFIG_ERR = -2124, /**< non-fatal error during config processing */
+ RS_RET_NON_SIZELIMITCMD = -2125, /**< size limit for file defined, but no size limit command given */
+ RS_RET_SIZELIMITCMD_DIDNT_RESOLVE = -2126, /**< size limit command did not resolve situation */
+ RS_RET_STREAM_DISABLED = -2127, /**< a file has been disabled (e.g. by size limit restriction) */
RS_RET_FILENAME_INVALID = -2140, /**< filename invalid, not found, no access, ... */
RS_RET_ZLIB_ERR = -2141, /**< error during zlib call */
diff --git a/runtime/srUtils.h b/runtime/srUtils.h
index bfce4cbb..699f8527 100644
--- a/runtime/srUtils.h
+++ b/runtime/srUtils.h
@@ -92,6 +92,7 @@ void srSleep(int iSeconds, int iuSeconds);
char *rs_strerror_r(int errnum, char *buf, size_t buflen);
int decodeSyslogName(uchar *name, syslogName_t *codetab);
int getSubString(uchar **ppSrc, char *pDst, size_t DstSize, char cSep);
+rsRetVal getFileSize(uchar *pszName, off_t *pSize);
/* mutex operations */
/* some macros to cancel-safe lock a mutex (it will automatically be released
diff --git a/runtime/srutils.c b/runtime/srutils.c
index d01ca20d..5407531f 100644
--- a/runtime/srutils.c
+++ b/runtime/srutils.c
@@ -553,6 +553,33 @@ int getSubString(uchar **ppSrc, char *pDst, size_t DstSize, char cSep)
}
+/* get the size of a file or return appropriate error code. If an error is returned,
+ * *pSize content is undefined.
+ * rgerhards, 2009-06-12
+ */
+rsRetVal
+getFileSize(uchar *pszName, off_t *pSize)
+{
+ int ret;
+ struct stat statBuf;
+ DEFiRet;
+
+ ret = stat((char*) pszName, &statBuf);
+ if(ret == -1) {
+ switch(errno) {
+ case EACCES: ABORT_FINALIZE(RS_RET_NO_FILE_ACCESS);
+ case ENOTDIR:
+ case ENOENT: ABORT_FINALIZE(RS_RET_FILE_NOT_FOUND);
+ default: ABORT_FINALIZE(RS_RET_FILE_NO_STAT);
+ }
+ }
+
+ *pSize = statBuf.st_size;
+
+finalize_it:
+ RETiRet;
+}
+
/* vim:set ai:
*/
diff --git a/runtime/stream.c b/runtime/stream.c
index 49d29e0e..5355a1a5 100644
--- a/runtime/stream.c
+++ b/runtime/stream.c
@@ -6,8 +6,9 @@
* "driver").
*
* File begun on 2008-01-09 by RGerhards
+ * Large modifications in 2009-06 to support using it with omfile, including zip writer.
*
- * Copyright 2008 Rainer Gerhards and Adiscon GmbH.
+ * Copyright 2008, 2009 Rainer Gerhards and Adiscon GmbH.
*
* This file is part of the rsyslog runtime library.
*
@@ -54,11 +55,112 @@ DEFobjCurrIf(zlibw)
/* forward definitions */
static rsRetVal strmFlush(strm_t *pThis);
static rsRetVal strmWrite(strm_t *pThis, uchar *pBuf, size_t lenBuf);
+static rsRetVal strmCloseFile(strm_t *pThis);
/* methods */
-/* first, we define type-specific handlers. The provide a generic functionality,
+
+/* Try to resolve a size limit situation. This is used to support custom-file size handlers
+ * for omfile. It first runs the command, and then checks if we are still above the size
+ * treshold. Note that this works only with single file names, NOT with circular names.
+ * Note that pszCurrFName can NOT be taken from pThis, because the stream is closed when
+ * we are called (and that destroys pszCurrFName, as there is NO CURRENT file name!). So
+ * we need to receive the name as a parameter.
+ * initially wirtten 2005-06-21, moved to this class & updates 2009-06-01, both rgerhards
+ */
+static rsRetVal
+resolveFileSizeLimit(strm_t *pThis, uchar *pszCurrFName)
+{
+ uchar *pParams;
+ uchar *pCmd;
+ uchar *p;
+ off_t actualFileSize;
+ rsRetVal localRet;
+ DEFiRet;
+ ISOBJ_TYPE_assert(pThis, strm);
+ assert(pszCurrFName != NULL);
+
+ if(pThis->pszSizeLimitCmd == NULL) {
+ ABORT_FINALIZE(RS_RET_NON_SIZELIMITCMD); /* nothing we can do in this case... */
+ }
+
+ /* we first check if we have command line parameters. We assume this,
+ * when we have a space in the program name. If we find it, everything after
+ * the space is treated as a single argument.
+ */
+ CHKmalloc(pCmd = ustrdup(pThis->pszSizeLimitCmd));
+
+ for(p = pCmd ; *p && *p != ' ' ; ++p) {
+ /* JUST SKIP */
+ }
+
+ if(*p == ' ') {
+ *p = '\0'; /* pretend string-end */
+ pParams = p+1;
+ } else
+ pParams = NULL;
+
+ /* the execProg() below is probably not great, but at least is is
+ * fairly secure now. Once we change the way file size limits are
+ * handled, we should also revisit how this command is run (and
+ * with which parameters). rgerhards, 2007-07-20
+ */
+ execProg(pCmd, 1, pParams);
+
+ free(pCmd);
+
+ localRet = getFileSize(pszCurrFName, &actualFileSize);
+
+ if(localRet == RS_RET_OK && actualFileSize >= pThis->iSizeLimit) {
+ ABORT_FINALIZE(RS_RET_SIZELIMITCMD_DIDNT_RESOLVE); /* OK, it didn't work out... */
+ } else if(localRet != RS_RET_FILE_NOT_FOUND) {
+ /* file not found is OK, the command may have moved away the file */
+ ABORT_FINALIZE(localRet);
+ }
+
+finalize_it:
+ if(iRet != RS_RET_OK) {
+ if(iRet == RS_RET_SIZELIMITCMD_DIDNT_RESOLVE)
+ dbgprintf("file size limit cmd for file '%s' did no resolve situation\n", pszCurrFName);
+ else
+ dbgprintf("file size limit cmd for file '%s' failed with code %d.\n", pszCurrFName, iRet);
+ pThis->bDisabled = 1;
+ }
+
+ RETiRet;
+}
+
+
+/* Check if the file has grown beyond the configured omfile iSizeLimit
+ * and, if so, initiate processing.
+ */
+static rsRetVal
+doSizeLimitProcessing(strm_t *pThis)
+{
+ uchar *pszCurrFName = NULL;
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pThis, strm);
+ ASSERT(pThis->iSizeLimit != 0);
+ ASSERT(pThis->fd != -1);
+
+ if(pThis->iCurrOffs >= pThis->iSizeLimit) {
+ /* strmClosefile() destroys the current file name, so we
+ * need to preserve it.
+ */
+ CHKmalloc(pszCurrFName = ustrdup(pThis->pszCurrFName));
+ CHKiRet(strmCloseFile(pThis));
+ CHKiRet(resolveFileSizeLimit(pThis, pszCurrFName));
+ }
+
+finalize_it:
+ free(pszCurrFName);
+ RETiRet;
+}
+
+
+/* now, we define type-specific handlers. The provide a generic functionality,
* but for this specific type of strm. The mapping to these handlers happens during
* strm construction. Later on, handlers are called by pointers present in the
* strm instance object.
@@ -123,6 +225,12 @@ static rsRetVal strmOpenFile(strm_t *pThis)
}
pThis->iCurrOffs = 0;
+ if(pThis->tOperationsMode == STREAMMODE_WRITE_APPEND) {
+ /* we need to obtain the current offset */
+ off_t offset;
+ CHKiRet(getFileSize(pThis->pszCurrFName, &offset));
+ pThis->iCurrOffs = offset;
+ }
dbgoprint((obj_t*) pThis, "opened file '%s' for %s (0x%x) as %d\n", pThis->pszCurrFName,
(pThis->tOperationsMode == STREAMMODE_READ) ? "READ" : "WRITE", iFlags, pThis->fd);
@@ -527,7 +635,7 @@ doWriteCall(int fd, uchar *pBuf, size_t *pLenBuf)
if(err == EINTR) {
/*NO ERROR, just continue */;
} else {
- ABORT_FINALIZE(RS_RET_ERR);
+ ABORT_FINALIZE(RS_RET_IO_ERROR);
// TODO: cover more error cases!
}
}
@@ -538,7 +646,7 @@ doWriteCall(int fd, uchar *pBuf, size_t *pLenBuf)
} while(lenBuf > 0); /* Warning: do..while()! */
finalize_it:
- *pLenBuf -= iTotalWritten;
+ *pLenBuf = iTotalWritten;
RETiRet;
}
@@ -610,8 +718,11 @@ strmPhysWrite(strm_t *pThis, uchar *pBuf, size_t lenBuf)
CHKiRet(syncFile(pThis));
}
- if(pThis->sType == STREAMTYPE_FILE_CIRCULAR)
+ if(pThis->sType == STREAMTYPE_FILE_CIRCULAR) {
CHKiRet(strmCheckNextOutputFile(pThis));
+ } else if(pThis->iSizeLimit != 0) {
+ CHKiRet(doSizeLimitProcessing(pThis));
+ }
finalize_it:
pThis->iBufPtr = 0; /* see comment above */
@@ -812,7 +923,10 @@ strmWrite(strm_t *pThis, uchar *pBuf, size_t lenBuf)
ASSERT(pThis != NULL);
ASSERT(pBuf != NULL);
-dbgprintf("strmWrite(%p, '%s', %ld);\n", pThis, pBuf,lenBuf);
+dbgprintf("strmWrite(%p, '%65.65s', %ld);, disabled %d, sizelim %ld, size %lld\n", pThis, pBuf,lenBuf, pThis->bDisabled, pThis->iSizeLimit, pThis->iCurrOffs);
+ if(pThis->bDisabled)
+ ABORT_FINALIZE(RS_RET_STREAM_DISABLED);
+
/* check if the to-be-written data is larger than our buffer size */
if(lenBuf >= pThis->sIOBufSize) {
/* it is - so we do a direct write, that is most efficient.
@@ -857,6 +971,8 @@ DEFpropSetMeth(strm, sType, strmType_t)
DEFpropSetMeth(strm, iZipLevel, int)
DEFpropSetMeth(strm, bSync, int)
DEFpropSetMeth(strm, sIOBufSize, size_t)
+DEFpropSetMeth(strm, iSizeLimit, off_t)
+DEFpropSetMeth(strm, pszSizeLimitCmd, uchar*)
static rsRetVal strmSetiMaxFiles(strm_t *pThis, int iNewVal)
{
@@ -1139,6 +1255,8 @@ CODESTARTobjQueryInterface(strm)
pIf->SetiZipLevel = strmSetiZipLevel;
pIf->SetbSync = strmSetbSync;
pIf->SetsIOBufSize = strmSetsIOBufSize;
+ pIf->SetiSizeLimit = strmSetiSizeLimit;
+ pIf->SetpszSizeLimitCmd = strmSetpszSizeLimitCmd;
finalize_it:
ENDobjQueryInterface(strm)
diff --git a/runtime/stream.h b/runtime/stream.h
index a66108b7..a06e089f 100644
--- a/runtime/stream.h
+++ b/runtime/stream.h
@@ -103,6 +103,7 @@ typedef struct strm_s {
int64 iCurrOffs;/* current offset */
int64 *pUsrWCntr; /* NULL or a user-provided counter that receives the nbr of bytes written since the last CntrSet() */
/* dynamic properties, valid only during file open, not to be persistet */
+ int bDisabled; /* should file no longer be written to? (currently set only if omfile file size limit fails) */
int bSync; /* sync this file after every write? */
size_t sIOBufSize;/* size of IO buffer */
uchar *pszDir; /* Directory */
@@ -117,7 +118,9 @@ typedef struct strm_s {
int bInRecord; /* if 1, indicates that we are currently writing a not-yet complete record */
int iZipLevel; /* zip level (0..9). If 0, zip is completely disabled */
Bytef *pZipBuf;
-
+ /* support for omfile size-limiting commands, special counters, NOT persisted! */
+ off_t iSizeLimit; /* file size limit, 0 = no limit */
+ uchar *pszSizeLimitCmd; /* command to carry out when size limit is reached */
} strm_t;
/* interfaces */
@@ -152,6 +155,8 @@ BEGINinterface(strm) /* name must also be changed in ENDinterface macro! */
INTERFACEpropSetMeth(strm, iZipLevel, int);
INTERFACEpropSetMeth(strm, bSync, int);
INTERFACEpropSetMeth(strm, sIOBufSize, size_t);
+ INTERFACEpropSetMeth(strm, iSizeLimit, off_t);
+ INTERFACEpropSetMeth(strm, pszSizeLimitCmd, uchar*);
ENDinterface(strm)
#define strmCURR_IF_VERSION 1 /* increment whenever you change the interface structure! */
diff --git a/runtime/unicode-helper.h b/runtime/unicode-helper.h
index 5289da3f..8216e992 100644
--- a/runtime/unicode-helper.h
+++ b/runtime/unicode-helper.h
@@ -4,6 +4,9 @@
* The following functions are wrappers which hopefully enable us to move
* from 8-bit chars to unicode with relative ease when we finally attack this
*
+ * Note: while we prefer inline functions, this leads to invalid references in
+ * core dumps. So in a debug build, we use macros where appropriate...
+ *
* Begun 2009-05-21 RGerhards
*
* Copyright (C) 2009 by Rainer Gerhards and Adiscon GmbH
@@ -31,10 +34,21 @@
#include <string.h>
-static inline char* ustrncpy(uchar *psz1, uchar *psz2, size_t len)
-{
- return strncpy((char*) psz1, (char*) psz2, len);
-}
+#ifdef DEBUG
+# define ustrncpy(psz1, psz2, len) strncpy((char*)(psz1), (char*)(psz2), (len))
+# define ustrdup(psz) (uchar*)strdup((char*)(psz))
+#else
+ static inline uchar* ustrncpy(uchar *psz1, uchar *psz2, size_t len)
+ {
+ return strncpy((char*) psz1, (char*) psz2, len);
+ }
+
+ static inline uchar* ustrdup(uchar *psz)
+ {
+ return (uchar*) strdup((char*)psz);
+ }
+
+#endif /* #ifdef DEBUG */
static inline int ustrcmp(uchar *psz1, uchar *psz2)
{
@@ -46,11 +60,6 @@ static inline int ustrlen(uchar *psz)
return strlen((char*) psz);
}
-static inline uchar* ustrdup(uchar *psz)
-{
- return (uchar*) strdup((char*)psz);
-}
-
#define UCHAR_CONSTANT(x) ((uchar*) (x))
#define CHAR_CONVERT(x) ((char*) (x))