diff options
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | obj-types.h | 30 | ||||
-rw-r--r-- | obj.h | 28 | ||||
-rwxr-xr-x | srUtils.c | 33 | ||||
-rwxr-xr-x | srUtils.h | 4 | ||||
-rw-r--r-- | stream.c | 49 | ||||
-rw-r--r-- | stream.h | 5 |
7 files changed, 118 insertions, 33 deletions
diff --git a/Makefile.am b/Makefile.am index 2cad2365..094a39f1 100644 --- a/Makefile.am +++ b/Makefile.am @@ -5,6 +5,7 @@ rfc3195d_SOURCES = rfc3195d.c rsyslog.h rsyslogd_SOURCES = \ syslogd.c \ syslogd.h \ + glbl.h \ pidfile.c \ pidfile.h \ template.c \ @@ -31,6 +32,7 @@ rsyslogd_SOURCES = \ net.h \ obj.c \ obj.h \ + obj-types.h \ msg.c \ msg.h \ expr.c \ diff --git a/obj-types.h b/obj-types.h index 005d6a4d..6da56db0 100644 --- a/obj-types.h +++ b/obj-types.h @@ -113,5 +113,35 @@ finalize_it: \ return iRet; \ } +/* this defines both the constructor and initializer + * rgerhards, 2008-01-10 + */ +#define BEGINobjConstruct(obj) \ + rsRetVal obj##Initialize(obj##_t *pThis) \ + { \ + DEFiRet; + +#define ENDobjConstruct(obj) \ + /* use finalize_it: before calling the macro (if you need it)! */ \ + return iRet; \ + } \ + rsRetVal obj##Construct(obj##_t **ppThis) \ + { \ + DEFiRet; \ + obj##_t *pThis; \ + \ + assert(ppThis != NULL); \ + \ + if((pThis = (obj##_t *)calloc(1, sizeof(obj##_t))) == NULL) { \ + ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); \ + } \ + \ + obj##Initialize(pThis); \ + \ + finalize_it: \ + OBJCONSTRUCT_CHECK_SUCCESS_AND_CLEANUP \ + return iRet; \ + } + #endif /* #ifndef OBJ_TYPES_H_INCLUDED */ @@ -47,6 +47,34 @@ #include "obj-types.h" #include "stream.h" +/* macros */ +/* the following one is a helper that prevents us from writing the + * ever-same code at the end of Construct() + */ +#define OBJCONSTRUCT_CHECK_SUCCESS_AND_CLEANUP \ + if(iRet == RS_RET_OK) { \ + *ppThis = pThis; \ + } else { \ + if(pThis != NULL) \ + free(pThis); \ + } + +#define objSerializeSCALAR(propName, propType) \ + CHKiRet(objSerializeProp(pCStr, (uchar*) #propName, PROPTYPE_##propType, (void*) &pThis->propName)); +#define objSerializePTR(propName, propType) \ + CHKiRet(objSerializeProp(pCStr, (uchar*) #propName, PROPTYPE_##propType, (void*) pThis->propName)); +#define DEFobjStaticHelpers static objInfo_t *pObjInfoOBJ = NULL; +#define objGetName(pThis) (((obj_t*) (pThis))->pObjInfo->pszName) +#define objGetObjID(pThis) (((obj_t*) (pThis))->pObjInfo->objID) +#define objGetVersion(pThis) (((obj_t*) (pThis))->pObjInfo->iObjVers) +/* must be called in Constructor: */ +#define objConstructSetObjInfo(pThis) ((obj_t*) (pThis))->pObjInfo = pObjInfoOBJ; +#define objDestruct(pThis) (((obj_t*) (pThis))->pObjInfo->objMethods[objMethod_DESTRUCT])(pThis) +#define objSerialize(pThis) (((obj_t*) (pThis))->pObjInfo->objMethods[objMethod_SERIALIZE]) + +#define OBJSetMethodHandler(methodID, pHdlr) \ + CHKiRet(objInfoSetMethod(pObjInfoOBJ, methodID, (rsRetVal (*)(void*)) pHdlr)) + /* prototypes */ rsRetVal objInfoConstruct(objInfo_t **ppThis, objID_t objID, uchar *pszName, int iObjVers, rsRetVal (*pConstruct)(void *), rsRetVal (*pDestruct)(void *)); rsRetVal objInfoSetMethod(objInfo_t *pThis, objMethod_t objMethod, rsRetVal (*pHandler)(void*)); @@ -243,25 +243,35 @@ void skipWhiteSpace(uchar **pp) * <directory name>/<name>.<number> * If number is negative, it is not used. If any of the strings is * NULL, an empty string is used instead. Length must be provided. + * lNumDigits is the minimum number of digits that lNum should have. This + * is to pretty-print the file name, e.g. lNum = 3, lNumDigits= 4 will + * result in "0003" being used inside the file name. Set lNumDigits to 0 + * to use as few space as possible. * rgerhards, 2008-01-03 */ -rsRetVal genFileName(uchar **ppName, uchar *pDirName, size_t lenDirName, uchar *pFName, size_t lenFName, long lNum) +rsRetVal genFileName(uchar **ppName, uchar *pDirName, size_t lenDirName, uchar *pFName, + size_t lenFName, long lNum, int lNumDigits) { DEFiRet; uchar *pName; uchar *pNameWork; size_t lenName; uchar szBuf[128]; /* buffer for number */ + char szFmtBuf[32]; /* buffer for snprintf format */ size_t lenBuf; if(lNum < 0) { szBuf[0] = '\0'; lenBuf = 0; } else { - lenBuf = snprintf((char*)szBuf, sizeof(szBuf), ".%ld", lNum); + if(lNumDigits > 0) { + snprintf(szFmtBuf, sizeof(szFmtBuf), ".%%0%dld", lNumDigits); + lenBuf = snprintf((char*)szBuf, sizeof(szBuf), szFmtBuf, lNum); + } else + lenBuf = snprintf((char*)szBuf, sizeof(szBuf), ".%ld", lNum); } - lenName = lenDirName + 1 + lenName + lenBuf + 1; /* last +1 for \0 char! */ + lenName = lenDirName + 1 + lenFName + lenBuf + 1; /* last +1 for \0 char! */ if((pName = malloc(sizeof(uchar) * lenName)) == NULL) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); @@ -283,6 +293,23 @@ finalize_it: return iRet; } +/* get the number of digits required to represent a given number. We use an + * iterative approach as we do not like to draw in the floating point + * library just for log(). -- rgerhards, 2008-01-10 + */ +int getNumberDigits(long lNum) +{ + int iDig; + + if(lNum == 0) + iDig = 1; + else + for(iDig = 0 ; lNum != 0 ; ++iDig) + lNum /= 10; + + return iDig; +} + /* * vi:set ai: @@ -64,5 +64,7 @@ int makeFileParentDirs(uchar *szFile, size_t lenFile, mode_t mode, uid_t uid, gi int execProg(uchar *program, int wait, uchar *arg); void skipWhiteSpace(uchar **pp); -rsRetVal genFileName(uchar **ppName, uchar *pDirName, size_t lenDirName, uchar *pName, size_t lenName, long lNum); +rsRetVal genFileName(uchar **ppName, uchar *pDirName, size_t lenDirName, uchar *pFName, + size_t lenFName, long lNum, int lNumDigits); +int getNumberDigits(long lNum); #endif @@ -72,8 +72,14 @@ rsRetVal strmOpenFile(strm_t *pThis, int flags, mode_t mode) if(pThis->pszFilePrefix == NULL) ABORT_FINALIZE(RS_RET_FILE_PREFIX_MISSING); + if(pThis->pIOBuf == NULL) { /* allocate our io buffer in case we have not yet */ + if((pThis->pIOBuf = (uchar*) malloc(sizeof(uchar) * pThis->sIOBufSize)) == NULL) + ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); + pThis->iBufPtrMax = 0; /* results in immediate read request */ + } + CHKiRet(genFileName(&pThis->pszCurrFName, pThis->pszDir, pThis->lenDir, - pThis->pszFilePrefix, pThis->lenFilePrefix, pThis->iCurrFNum)); + pThis->pszFilePrefix, pThis->lenFilePrefix, pThis->iCurrFNum, pThis->iFileNumDigits)); pThis->fd = open((char*)pThis->pszCurrFName, flags, mode); // TODO: open modes! pThis->iCurrOffs = 0; @@ -155,12 +161,6 @@ rsRetVal strmReadChar(strm_t *pThis, uchar *pC) assert(pC != NULL); /* DEV debug only: dbgprintf("strmRead index %d, max %d\n", pThis->iBufPtr, pThis->iBufPtrMax); */ - if(pThis->pIOBuf == NULL) { /* TODO: maybe we should move that to file open... */ - if((pThis->pIOBuf = (uchar*) malloc(sizeof(uchar) * STRM_IOBUF_SIZE )) == NULL) - ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); - pThis->iBufPtrMax = 0; /* results in immediate read request */ - } - if(pThis->iUngetC != -1) { /* do we have an "unread" char that we need to provide? */ *pC = pThis->iUngetC; pThis->iUngetC = -1; @@ -174,7 +174,7 @@ rsRetVal strmReadChar(strm_t *pThis, uchar *pC) while(bRun) { /* first check if we need to (re)open the file (we may have switched to a new one!) */ CHKiRet(strmOpenFile(pThis, O_RDONLY, 0600)); // TODO: open modes! - pThis->iBufPtrMax = read(pThis->fd, pThis->pIOBuf, STRM_IOBUF_SIZE); + pThis->iBufPtrMax = read(pThis->fd, pThis->pIOBuf, pThis->sIOBufSize); dbgprintf("strmReadChar read %d bytes from file %d\n", pThis->iBufPtrMax, pThis->fd); if(pThis->iBufPtrMax == 0) { if(pThis->iMaxFiles == 0) @@ -261,30 +261,15 @@ finalize_it: /* --------------- end type-specific handlers -------------------- */ -/* Constructor for the strm object +/* Standard-Constructor for the strm object */ -rsRetVal strmConstruct(strm_t **ppThis) -{ - DEFiRet; - strm_t *pThis; -dbgprintf("strmConstruct\n"); - - assert(ppThis != NULL); - - if((pThis = (strm_t *)calloc(1, sizeof(strm_t))) == NULL) { - ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); - } - - /* we have an object, so let's fill all properties that must not be 0 (we did calloc()!) */ +BEGINobjConstruct(strm) pThis->iCurrFNum = 1; pThis->fd = -1; pThis->iUngetC = -1; pThis->sType = STREAMTYPE_FILE; - -finalize_it: - OBJCONSTRUCT_CHECK_SUCCESS_AND_CLEANUP - return iRet; -} + pThis->sIOBufSize = glblGetIOBufSize(); +ENDobjConstruct(strm) /* ConstructionFinalizer - currently provided just to comply to the interface @@ -352,7 +337,15 @@ finalize_it: /* simple ones first */ DEFpropSetMeth(strm, bDeleteOnClose, int) DEFpropSetMeth(strm, iMaxFileSize, int) -DEFpropSetMeth(strm, iMaxFiles, int) +DEFpropSetMeth(strm, iFileNumDigits, int) + +rsRetVal strmSetiMaxFiles(strm_t *pThis, int iNewVal) +{ + pThis->iMaxFiles = iNewVal; + pThis->iFileNumDigits = getNumberDigits(iNewVal); + return RS_RET_OK; +} + /* set the stream's file prefix * The passed-in string is duplicated. So if the caller does not need @@ -44,6 +44,7 @@ #include <pthread.h> #include "obj-types.h" +#include "glbl.h" #include "stream.h" /* stream types */ @@ -72,8 +73,9 @@ typedef struct strm_s { size_t iMaxFileSize;/* maximum size a file may grow to */ int bDeleteOnClose; /* set to 1 to auto-delete on close -- be careful with that setting! */ int iMaxFiles; /* maximum number of files if a circular mode is in use */ + int iFileNumDigits;/* min number of digits to use in file number (only in circular mode) */ + size_t sIOBufSize;/* size of IO buffer */ } strm_t; -#define STRM_IOBUF_SIZE 4096 /* size of the IO buffer */ /* prototypes */ rsRetVal strmConstruct(strm_t **ppThis); @@ -92,5 +94,6 @@ PROTOTYPEObjClassInit(strm); PROTOTYPEpropSetMeth(strm, bDeleteOnClose, int); PROTOTYPEpropSetMeth(strm, iMaxFileSize, int); PROTOTYPEpropSetMeth(strm, iMaxFiles, int); +PROTOTYPEpropSetMeth(strm, iFileNumDigits, int); #endif /* #ifndef STREAM_H_INCLUDED */ |