~ubuntu-branches/ubuntu/oneiric/rsyslog/oneiric

« back to all changes in this revision

Viewing changes to tools/omfile.c

  • Committer: Dave Walker (Daviey)
  • Author(s): Scott Moser
  • Date: 2011-06-17 20:59:38 UTC
  • mfrom: (36.1.8 oneiric.merge)
  • Revision ID: davewalker@ubuntu.com-20110617205938-pfkizxz2wsgzi2ot
Tags: 5.8.1-1ubuntu1
* Resynchronise with Debian (LP: #794230).  Remaining changes:
  - Run as rsyslog:rsyslog, set $FileOwner to syslog
  - Replace init script with debian/rsyslog.upstart.
  - debian/rsyslog.logrotate: Use reload command to restart rsyslog
  - debian/rsyslog.conf: enable $RepeatedMsgReduction 
    to avoid bloating the syslog file (LP #453444)
  - Add debian/rsyslog.dmesg.upstart to save initial dmesg into a file.
    Install it in debian/rules.
  - debian/50-default.conf: set of default rules for syslog (forwarded to
    Debian #603160). remove file in postrm on purge. manage with ucf.
  - debian/rules: build with LDFLAGS=""
* Dropped:
  - debian/control: Bump build-dependency on debhelper
    debian now depends on dh >= 8
* New upstream release.
* Bump Standards-Version to 3.9.2. No further changes.
* Enable and install impstats module. (Closes: #620114)
* Update logcheck rule. (Closes: #616659)
* debian/rsyslog.init: Set correct compat level (5).
* The way rsyslog processes SIGHUP has changed. It no longer does a reload
  of its configuration, but simply closes all open files. To apply a changed
  configuration, rsyslogd needs to be restarted now.
  - Drop "reload" action from debian/rsyslog.init, map "force-reload" to
    "restart". (Closes: #580897)
  - Add "rotate" action to debian/rsyslog.init which sends SIGHUP to
    rsyslogd. Use that in debian/rsyslog.logrotate. (Closes: #626365)
  - Update debian/rsyslog-mysql.postinst and rsyslog-pgsql.postinst to use
    restart instead of reload.
  - Add a NEWS file explaining the changed SIGHUP handling.
* New upstream stable release.
* New upstream release.
  - Properly handle ANSI SQL strings in ompgsql. (Closes: #600479)
* New upstream release.
* debian/patches/02-pmaixforwardedfrom_type_nokeep.patch
  - Remove, merged upstream.
* debian/patches/03-epoll_create1-fallback.patch
  - Remove, merged upstream.
* debian/patches/03-epoll_create1-fallback.patch
  - If epoll_create1() is not available during runtime, fall back to
    epoll_create(). This fixes remote syslog when runnig rsyslog on a
    lenny kernel. (Closes: #617996)
* New upstream release.
* debian/rsyslog.links
  - Create symlink for rsyslog.service in multi-user.target.wants so rsyslog
    is enabled by default when using systemd.
* debian/patches/02-pmaixforwardedfrom_type_nokeep.patch
  - Fix build failure in aixforwardedfrom parser module by setting the
    module type to NOKEEP.
* debian/rsyslog.preinst
  - Remove old rsyslog.socket symlink from sockets.target.wants on upgrades
    as rsyslog uses syslog.socket now which is provided by systemd.
* debian/rsyslog.install
  - Stop installing rsyslog.socket.
* New upstream release.
* New upstream release.
  - Fix regression in imuxsock plugin which did no longer sanitize received
    messages. This makes 02-cleanup-trailing-lf.patch obsolete and also
    fixes the SQL syntax errors in the mysql output if the input contained
    NUL bytes. Closes: #614061
* Enable and install omprog output plugin. Closes: #552095
* Improve package description. Closes: #612948
  Thanks to Justin B Rye for the patch.
* debian/patches/02-cleanup-trailing-lf.patch
  - Fix regression in imuxsock plugin which did not remove a trailing LF
    anymore. Patch cherry-picked from upstream Git. Closes: #612829
* New upstream release.
* Enable and install parser modules.
* New upstream release.
* Upload to unstable.
* debian/patches/02-typo_fix_equation_sign.patch
  - Removed, merged upstream.
* debian/patches/03-atomic_operations.patch
  - Removed, merged upstream.
* debian/patches/03-atomic_operations.patch
  - Fix build failures on platforms which don't have 64 bit atomic
    operations. Patch cherry-picked from upstream Git. Closes: #600930
* New upstream development release.
* Remove patches, merged upstream
  - debian/patches/02-install_also_rsyslog_socket.patch
  - debian/patches/02-tls_loop_fix.patch
* debian/patches/02-typo_fix_equation_sign.patch
  - Fix small typo ("equation sign"). Closes: #575589
* debian/rsyslog.postinst
  - Remove pre-lenny migration code to rotate old log files from sysklogd.
* New upstream development release.
* debian/rsyslog.install
  - Install omruleset.so plugin: http://www.rsyslog.com/doc/omruleset.html
* debian/rsyslog.default
  - Start rsyslogd with native -c5 mode.
* Install systemd unit files which allow to run rsyslog in socket activation
  mode when systemd is used.
* debian/patches/02-install_also_rsyslog_socket.patch
  - When enabling rsyslog.service also enable rsyslog.socket. Patch
    cherry-picked from upstream Git.
* Bump debhelper compatibility level to 8. Update Build-Depends accordingly.

Show diffs side-by-side

added added

removed removed

Lines of Context:
48
48
#include <libgen.h>
49
49
#include <unistd.h>
50
50
#include <sys/file.h>
51
 
 
52
51
#ifdef OS_SOLARIS
53
52
#       include <fcntl.h>
54
53
#endif
 
54
#ifdef HAVE_ATOMIC_BUILTINS
 
55
#       include <pthread.h>
 
56
#endif
 
57
 
55
58
 
56
59
#include "conf.h"
57
60
#include "syslogd-types.h"
67
70
#include "atomic.h"
68
71
 
69
72
MODULE_TYPE_OUTPUT
 
73
MODULE_TYPE_NOKEEP
70
74
 
71
75
/* internal structures
72
76
 */
74
78
DEFobjCurrIf(errmsg)
75
79
DEFobjCurrIf(strm)
76
80
 
 
81
/* for our current LRU mechanism, we need a monotonically increasing counters. We use
 
82
 * it much like a "Lamport logical clock": we do not need the actual time, we just need
 
83
 * to know the sequence in which files were accessed. So we use a simple counter to
 
84
 * create that sequence. We use an unsigned 64 bit value which is extremely unlike to
 
85
 * wrap within the lifetime of a process. If we process 1,000,000 file writes per
 
86
 * second, the process could still exist over 500,000 years before a wrap to 0 happens.
 
87
 * That should be sufficient (and even than, there would no really bad effect ;)).
 
88
 * The variable below is the global counter/clock.
 
89
 */
 
90
#if HAVE_ATOMIC_BUILTINS_64BIT
 
91
static uint64 clockFileAccess = 0;
 
92
#else
 
93
static unsigned clockFileAccess = 0;
 
94
#endif
 
95
/* and the "tick" function */
 
96
#ifndef HAVE_ATOMIC_BUILTINS
 
97
static pthread_mutex_t mutClock;
 
98
#endif
 
99
static inline uint64
 
100
getClockFileAccess(void)
 
101
{
 
102
#if HAVE_ATOMIC_BUILTINS_64BIT
 
103
        return ATOMIC_INC_AND_FETCH_uint64(&clockFileAccess, &mutClock);
 
104
#else
 
105
        return ATOMIC_INC_AND_FETCH_unsigned(&clockFileAccess, &mutClock);
 
106
#endif
 
107
}
 
108
 
 
109
 
77
110
/* The following structure is a dynafile name cache entry.
78
111
 */
79
112
struct s_dynaFileCacheEntry {
80
113
        uchar *pName;           /* name currently open, if dynamic name */
81
114
        strm_t  *pStrm;         /* our output stream */
82
 
        time_t  lastUsed;       /* for LRU - last access */
 
115
        uint64  clkTickAccessed;/* for LRU - based on clockFileAccess */
83
116
};
84
117
typedef struct s_dynaFileCacheEntry dynaFileCacheEntry;
85
118
 
89
122
#define USE_ASYNCWRITER_DFLT 0  /* default buffer use async writer */
90
123
#define FLUSHONTX_DFLT 1        /* default for flush on TX end */
91
124
 
 
125
#define DFLT_bForceChown 0
92
126
/* globals for default values */
93
127
static int iDynaFileCacheSize = 10; /* max cache for dynamic files */
94
128
static int fCreateMode = 0644; /* mode to use when creating files */
95
129
static int fDirCreateMode = 0700; /* mode to use when creating files */
96
130
static int      bFailOnChown;   /* fail if chown fails? */
 
131
static int      bForceChown = DFLT_bForceChown; /* Force chown() on existing files? */
97
132
static uid_t    fileUID;        /* UID to be used for newly created files */
98
133
static uid_t    fileGID;        /* GID to be used for newly created files */
99
134
static uid_t    dirUID;         /* UID to be used for newly created directories */
101
136
static int      bCreateDirs = 1;/* auto-create directories for dynaFiles: 0 - no, 1 - yes */
102
137
static int      bEnableSync = 0;/* enable syncing of files (no dash in front of pathname in conf): 0 - no, 1 - yes */
103
138
static int      iZipLevel = 0;  /* zip compression mode (0..9 as usual) */
104
 
static bool     bFlushOnTXEnd = FLUSHONTX_DFLT;/* flush write buffers when transaction has ended? */
 
139
static sbool    bFlushOnTXEnd = FLUSHONTX_DFLT;/* flush write buffers when transaction has ended? */
105
140
static int64    iIOBufSize = IOBUF_DFLT_SIZE;   /* size of an io buffer */
106
141
static int      iFlushInterval = FLUSH_INTRVL_DFLT;     /* how often flush the output buffer on inactivity? */
107
142
static int      bUseAsyncWriter = USE_ASYNCWRITER_DFLT; /* should we enable asynchronous writing? */
118
153
        int     fDirCreateMode; /* creation mode for mkdir() */
119
154
        int     bCreateDirs;    /* auto-create directories? */
120
155
        int     bSyncFile;      /* should the file by sync()'ed? 1- yes, 0- no */
 
156
        sbool   bForceChown;    /* force chown() on existing files? */
121
157
        uid_t   fileUID;        /* IDs for creation */
122
158
        uid_t   dirUID;
123
159
        gid_t   fileGID;
136
172
        int     iZipLevel;              /* zip mode to use for this selector */
137
173
        int     iIOBufSize;             /* size of associated io buffer */
138
174
        int     iFlushInterval;         /* how fast flush buffer on inactivity? */
139
 
        bool    bFlushOnTXEnd;          /* flush write buffers when transaction has ended? */
140
 
        bool    bUseAsyncWriter;        /* use async stream writer? */
 
175
        sbool   bFlushOnTXEnd;          /* flush write buffers when transaction has ended? */
 
176
        sbool   bUseAsyncWriter;        /* use async stream writer? */
141
177
} instanceData;
142
178
 
143
179
 
163
199
        dbgprintf("\tflush interval=%d\n", pData->iFlushInterval);
164
200
        dbgprintf("\tfile cache size=%d\n", pData->iDynaFileCacheSize);
165
201
        dbgprintf("\tcreate directories: %s\n", pData->bCreateDirs ? "yes" : "no");
166
 
        dbgprintf("\tfile owner %d, group %d\n", pData->fileUID, pData->fileGID);
167
 
        dbgprintf("\tdirectory owner %d, group %d\n", pData->dirUID, pData->dirGID);
 
202
        dbgprintf("\tfile owner %d, group %d\n", (int) pData->fileUID, (int) pData->fileGID);
 
203
        dbgprintf("\tforce chown() for all files: %s\n", pData->bForceChown ? "yes" : "no"); 
 
204
        dbgprintf("\tdirectory owner %d, group %d\n", (int) pData->dirUID, (int) pData->dirGID);
168
205
        dbgprintf("\tdir create mode 0%3.3o, file create mode 0%3.3o\n",
169
206
                  pData->fDirCreateMode, pData->fCreateMode);
170
207
        dbgprintf("\tfail if owner/group can not be set: %s\n", pData->bFailOnChown ? "yes" : "no");
351
388
        int fd;
352
389
        DEFiRet;
353
390
 
354
 
        if(access((char*)newFileName, F_OK) != 0) {
 
391
        if(access((char*)newFileName, F_OK) == 0) {
 
392
                if(pData->bForceChown) {
 
393
                        /* Try to fix wrong ownership set by someone else. Note that this code
 
394
                         * will no longer work once we have made the $PrivDrop code fully secure.
 
395
                         * This change is based on an idea of Michael Terry, provided as part of
 
396
                         * the effort to make rsyslogd the Ubuntu default syslogd.
 
397
                         * rgerhards, 2009-09-11
 
398
                         */
 
399
                        if(chown((char*)newFileName, pData->fileUID, pData->fileGID) != 0) {
 
400
                                if(pData->bFailOnChown) {
 
401
                                        int eSave = errno;
 
402
                                        errno = eSave;
 
403
                                }
 
404
                        }
 
405
                }
 
406
        } else {
355
407
                /* file does not exist, create it (and eventually parent directories */
356
 
                fd = -1;
357
408
                if(pData->bCreateDirs) {
358
409
                        /* We first need to create parent dirs if they are missing.
359
410
                         * We do not report any errors here ourselfs but let the code
372
423
                                pData->fCreateMode);
373
424
                if(fd != -1) {
374
425
                        /* check and set uid/gid */
375
 
                        if(pData->fileUID != (uid_t)-1 || pData->fileGID != (gid_t) -1) {
 
426
                        if(pData->bForceChown || pData->fileUID != (uid_t)-1 || pData->fileGID != (gid_t) -1) {
376
427
                                /* we need to set owner/group */
377
428
                                if(fchown(fd, pData->fileUID, pData->fileGID) != 0) {
378
429
                                        if(pData->bFailOnChown) {
437
488
static inline rsRetVal
438
489
prepareDynFile(instanceData *pData, uchar *newFileName, unsigned iMsgOpts)
439
490
{
440
 
        time_t ttOldest; /* timestamp of oldest element */
 
491
        uint64 ctOldest; /* "timestamp" of oldest element */
441
492
        int iOldest;
442
493
        int i;
443
494
        int iFirstFree;
456
507
        if(   (pData->iCurrElt != -1)
457
508
           && !ustrcmp(newFileName, pCache[pData->iCurrElt]->pName)) {
458
509
                /* great, we are all set */
459
 
                pCache[pData->iCurrElt]->lastUsed = time(NULL); /* update timestamp for LRU */ // TODO: optimize time call!
 
510
                pCache[pData->iCurrElt]->clkTickAccessed = getClockFileAccess();
460
511
                // LRU needs only a strictly monotonically increasing counter, so such a one could do
461
512
                FINALIZE;
462
513
        }
467
518
        pData->iCurrElt = -1;   /* invalid current element pointer */
468
519
        iFirstFree = -1; /* not yet found */
469
520
        iOldest = 0; /* we assume the first element to be the oldest - that will change as we loop */
470
 
        ttOldest = time(NULL) + 1; /* there must always be an older one */
 
521
        ctOldest = getClockFileAccess(); /* there must always be an older one */
471
522
        for(i = 0 ; i < pData->iCurrCacheSize ; ++i) {
472
523
                if(pCache[i] == NULL || pCache[i]->pName == NULL) {
473
524
                        if(iFirstFree == -1)
477
528
                                /* we found our element! */
478
529
                                pData->pStrm = pCache[i]->pStrm;
479
530
                                pData->iCurrElt = i;
480
 
                                pCache[i]->lastUsed = time(NULL); /* update timestamp for LRU */
 
531
                                pCache[i]->clkTickAccessed = getClockFileAccess(); /* update "timestamp" for LRU */
481
532
                                FINALIZE;
482
533
                        }
483
534
                        /* did not find it - so lets keep track of the counters for LRU */
484
 
                        if(pCache[i]->lastUsed < ttOldest) {
485
 
                                ttOldest = pCache[i]->lastUsed;
 
535
                        if(pCache[i]->clkTickAccessed < ctOldest) {
 
536
                                ctOldest = pCache[i]->clkTickAccessed;
486
537
                                iOldest = i;
487
538
                                }
488
539
                }
508
559
                iFirstFree = pData->iCurrCacheSize++;
509
560
        }
510
561
 
511
 
// RG: this is the begin of a potential problem area
512
562
        /* Note that the following code sequence does not work with the cache entry itself,
513
563
         * but rather with pData->pStrm, the (sole) stream pointer in the non-dynafile case.
514
564
         * The cache array is only updated after the open was successful. -- rgerhards, 2010-03-21
546
596
                ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
547
597
        }
548
598
        pCache[iFirstFree]->pStrm = pData->pStrm;
549
 
        pCache[iFirstFree]->lastUsed = time(NULL);
 
599
        pCache[iFirstFree]->clkTickAccessed = getClockFileAccess();
550
600
        pData->iCurrElt = iFirstFree;
551
601
        DBGPRINTF("Added new entry %d for file cache, file '%s'.\n", iFirstFree, newFileName);
552
602
 
567
617
        ASSERT(pData != NULL);
568
618
        ASSERT(pszBuf != NULL);
569
619
 
570
 
dbgprintf("doWrite, pData->pStrm %p, lenBuf %d\n", pData->pStrm, lenBuf);
 
620
dbgprintf("write to stream, pData->pStrm %p, lenBuf %d\n", pData->pStrm, lenBuf);
571
621
        if(pData->pStrm != NULL){
572
622
                CHKiRet(strm.Write(pData->pStrm, pszBuf, lenBuf));
573
623
                FINALIZE;
633
683
CODESTARTtryResume
634
684
ENDtryResume
635
685
 
 
686
BEGINbeginTransaction
 
687
CODESTARTbeginTransaction
 
688
        /* we have nothing to do to begin a transaction */
 
689
ENDbeginTransaction
 
690
 
 
691
 
 
692
BEGINendTransaction
 
693
CODESTARTendTransaction
 
694
        if(pData->bFlushOnTXEnd) {
 
695
                CHKiRet(strm.Flush(pData->pStrm));
 
696
        }
 
697
finalize_it:
 
698
ENDendTransaction
 
699
 
 
700
 
636
701
BEGINdoAction
637
702
CODESTARTdoAction
638
703
        DBGPRINTF("file to log to: %s\n", pData->f_fname);
639
704
        CHKiRet(writeFile(ppString, iMsgOpts, pData));
640
 
        if(pData->bFlushOnTXEnd) {
641
 
                /* TODO v5: do this in endTransaction only! */
 
705
        if(!bCoreSupportsBatching && pData->bFlushOnTXEnd) {
642
706
                CHKiRet(strm.Flush(pData->pStrm));
643
707
        }
644
708
finalize_it:
 
709
        if(iRet == RS_RET_OK)
 
710
                iRet = RS_RET_DEFER_COMMIT;
645
711
ENDdoAction
646
712
 
647
713
 
724
790
        pData->fDirCreateMode = fDirCreateMode;
725
791
        pData->bCreateDirs = bCreateDirs;
726
792
        pData->bFailOnChown = bFailOnChown;
 
793
        pData->bForceChown = bForceChown;
727
794
        pData->fileUID = fileUID;
728
795
        pData->fileGID = fileGID;
729
796
        pData->dirUID = dirUID;
759
826
        dirUID = -1;
760
827
        dirGID = -1;
761
828
        bFailOnChown = 1;
 
829
        bForceChown = DFLT_bForceChown;
762
830
        iDynaFileCacheSize = 10;
763
831
        fCreateMode = 0644;
764
832
        fDirCreateMode = 0700;
796
864
        objRelease(errmsg, CORE_COMPONENT);
797
865
        objRelease(strm, CORE_COMPONENT);
798
866
        free(pszFileDfltTplName);
 
867
        DESTROY_ATOMIC_HELPER_MUT(mutClock);
799
868
ENDmodExit
800
869
 
801
870
 
802
871
BEGINqueryEtryPt
803
872
CODESTARTqueryEtryPt
804
873
CODEqueryEtryPt_STD_OMOD_QUERIES
 
874
CODEqueryEtryPt_TXIF_OMOD_QUERIES /* we support the transactional interface! */
805
875
CODEqueryEtryPt_doHUP
806
876
ENDqueryEtryPt
807
877
 
812
882
CODEmodInit_QueryRegCFSLineHdlr
813
883
        CHKiRet(objUse(errmsg, CORE_COMPONENT));
814
884
        CHKiRet(objUse(strm, CORE_COMPONENT));
 
885
 
 
886
        INIT_ATOMIC_HELPER_MUT(mutClock);
 
887
 
 
888
        INITChkCoreFeature(bCoreSupportsBatching, CORE_FEATURE_BATCHING);
 
889
        DBGPRINTF("omfile: %susing transactional output interface.\n", bCoreSupportsBatching ? "" : "not ");
815
890
        CHKiRet(omsdRegCFSLineHdlr((uchar *)"dynafilecachesize", 0, eCmdHdlrInt, (void*) setDynaFileCacheSize, NULL, STD_LOADABLE_MODULE_ID));
816
891
        CHKiRet(omsdRegCFSLineHdlr((uchar *)"omfileziplevel", 0, eCmdHdlrInt, NULL, &iZipLevel, STD_LOADABLE_MODULE_ID));
817
892
        CHKiRet(omsdRegCFSLineHdlr((uchar *)"omfileflushinterval", 0, eCmdHdlrInt, NULL, &iFlushInterval, STD_LOADABLE_MODULE_ID));
826
901
        CHKiRet(omsdRegCFSLineHdlr((uchar *)"filecreatemode", 0, eCmdHdlrFileCreateMode, NULL, &fCreateMode, STD_LOADABLE_MODULE_ID));
827
902
        CHKiRet(omsdRegCFSLineHdlr((uchar *)"createdirs", 0, eCmdHdlrBinary, NULL, &bCreateDirs, STD_LOADABLE_MODULE_ID));
828
903
        CHKiRet(omsdRegCFSLineHdlr((uchar *)"failonchownfailure", 0, eCmdHdlrBinary, NULL, &bFailOnChown, STD_LOADABLE_MODULE_ID));
 
904
        CHKiRet(omsdRegCFSLineHdlr((uchar *)"omfileForceChown", 0, eCmdHdlrBinary, NULL, &bForceChown, STD_LOADABLE_MODULE_ID));
829
905
        CHKiRet(omsdRegCFSLineHdlr((uchar *)"actionfileenablesync", 0, eCmdHdlrBinary, NULL, &bEnableSync, STD_LOADABLE_MODULE_ID));
830
906
        CHKiRet(regCfSysLineHdlr((uchar *)"actionfiledefaulttemplate", 0, eCmdHdlrGetWord, NULL, &pszFileDfltTplName, NULL));
831
907
        CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID));