Page MenuHomeFreeBSD

D20764.diff
No OneTemporary

D20764.diff

Index: usr.sbin/syslogd/syslog.conf.5
===================================================================
--- usr.sbin/syslogd/syslog.conf.5
+++ usr.sbin/syslogd/syslog.conf.5
@@ -28,7 +28,7 @@
.\" @(#)syslog.conf.5 8.1 (Berkeley) 6/9/93
.\" $FreeBSD$
.\"
-.Dd November 1, 2016
+.Dd June 25, 2019
.Dt SYSLOG.CONF 5
.Os
.Sh NAME
@@ -342,6 +342,21 @@
.Dq -
option may improve performance,
especially if the kernel is logging many messages.
+.Pp
+Options may be specified after the pathname.
+The options, delimited by whitespace, take the form of a letter,
+potentially followed by an associated value.
+The available options are:
+.Bl -tag -indent
+.It Ar R size
+Limit the growth of the file to the given size.
+If the file exceeds that size, enter
+.Dq recycle
+mode, in which the last 32 KBytes of the file become a circular buffer
+which is continually overwritten, preserving the bulk of the original file.
+The size is specified in bytes, with the usual power-of-two suffixes
+recognized.
+.El
.It
A hostname (preceded by an at
.Pq Dq @
Index: usr.sbin/syslogd/syslogd.c
===================================================================
--- usr.sbin/syslogd/syslogd.c
+++ usr.sbin/syslogd/syslogd.c
@@ -199,6 +199,24 @@
static STAILQ_HEAD(, socklist) shead = STAILQ_HEAD_INITIALIZER(shead);
/*
+ * If a file has a size limit specified, and that limit is exceeded, we treat
+ * the last few kbytes of the file as a circular buffer and repeatedly overwrite
+ * it. When that happens we write a msg to the file saying that we're doing so.
+ * This effectively turns the end of the file into a small circular buffer but
+ * preserves the bulk of the file (and thus hopefully preserves some clue as to
+ * what began spewing to the log to create this condition).
+ *
+ */
+#define LIMIT_CIRCBUF_SIZE (32 * 1024)
+#define LIMIT_CIRCBUF_MESSAGE \
+"\n" \
+"\n*******************************************************************************" \
+"\nsyslogd: Configured file size limit has been exceeded; data has been lost." \
+"\nsyslogd: From here down the file is being recycled in circular-buffer mode." \
+"\n*******************************************************************************" \
+"\n"
+
+/*
* Flags to logmsg().
*/
@@ -242,8 +260,11 @@
struct addrinfo *f_addr;
} f_forw; /* forwarding address */
- char f_fname[MAXPATHLEN];
struct {
+ char f_fname[MAXPATHLEN];
+ off_t f_fsizelimit;
+ } f_logfile;
+ struct {
char f_pname[MAXPATHLEN];
pid_t f_pid;
} f_pipe;
@@ -251,7 +272,8 @@
#define fu_uname f_un.f_uname
#define fu_forw_hname f_un.f_forw.f_hname
#define fu_forw_addr f_un.f_forw.f_addr
-#define fu_fname f_un.f_fname
+#define fu_fname f_un.f_logfile.f_fname
+#define fu_fsizelimit f_un.f_logfile.f_fsizelimit
#define fu_pipe_pname f_un.f_pipe.f_pname
#define fu_pipe_pid f_un.f_pipe.f_pid
char f_prevline[MAXSVLINE]; /* last message logged */
@@ -1727,6 +1749,18 @@
case F_FILE:
dprintf(" %s\n", f->fu_fname);
iovlist_append(il, "\n");
+ /*
+ * If this file has a size limit, and we're about to write to a
+ * location beyond that limit, seek to limit-CIRCBUF_SIZE before
+ * writing and drop a message into the file to say we lost data.
+ */
+ if (f->fu_fsizelimit != 0 && f->fu_fsizelimit <
+ lseek(f->f_file, 0, SEEK_CUR)) {
+ lseek(f->f_file, f->fu_fsizelimit - LIMIT_CIRCBUF_SIZE,
+ SEEK_SET);
+ write(f->f_file, LIMIT_CIRCBUF_MESSAGE,
+ sizeof(LIMIT_CIRCBUF_MESSAGE) - 1);
+ }
if (writev(f->f_file, il->iov, il->iovcnt) < 0) {
/*
* If writev(2) fails for potentially transient errors
@@ -2529,6 +2563,42 @@
}
/*
+ * Parse a filename config line to extract the filename and any options that may
+ * follow it on the line, storing the values into f->f_un.logfile.
+ */
+static void
+parse_fline(const char *p, struct filed *f)
+{
+ char *q, *r, *s;
+ uint64_t sizelimit;
+
+ (void)strlcpy(f->fu_fname, p, sizeof(f->fu_fname));
+
+ /* If there are no spaces on the line, no options follow the name. */
+ if ((q = strpbrk(f->fu_fname, "\t ")) == NULL)
+ return;
+
+ /* The only option we support right now is 'R' for recycle. */
+ r = q + strspn(q, "\t ");
+ if (*r++ != 'R')
+ return;
+
+ /* The thing following the R must be numeric. */
+ s = r + strspn(r, "\t ");
+ if (expand_number(s, &sizelimit) == -1)
+ return;
+
+ /*
+ * Looks like a valid R <size> option is present. Terminate fu_name at
+ * the first space and store the limit associated with the file.
+ */
+ *q = 0;
+ f->fu_fsizelimit = sizelimit;
+ if (f->fu_fsizelimit < LIMIT_CIRCBUF_SIZE)
+ f->fu_fsizelimit = LIMIT_CIRCBUF_SIZE;
+}
+
+/*
* Crack a configuration file line
*/
static struct filed *
@@ -2746,9 +2816,14 @@
break;
case '/':
- if ((f->f_file = open(p, logflags, 0600)) < 0) {
+ /* Parse the filename and any options into f->f_un.f_logfile. */
+ parse_fline(p, f);
+ if (f->fu_fsizelimit != 0) {
+ logflags &= ~O_APPEND;
+ }
+ if ((f->f_file = open(f->fu_fname, logflags, 0600)) < 0) {
f->f_type = F_UNUSED;
- logerror(p);
+ logerror(f->fu_fname);
break;
}
if (syncfile)
@@ -2761,7 +2836,12 @@
(void)strlcpy(f->fu_fname, p + sizeof(_PATH_DEV) - 1,
sizeof(f->fu_fname));
} else {
- (void)strlcpy(f->fu_fname, p, sizeof(f->fu_fname));
+ /*
+ * O_APPEND isn't used when limiting file size; limiting
+ * requires seeking. Start by seeking to end of file.
+ */
+ if (f->fu_fsizelimit != 0)
+ lseek(f->f_file, 0, SEEK_END);
f->f_type = F_FILE;
}
break;

File Metadata

Mime Type
text/plain
Expires
Thu, Sep 3, 5:10 PM (20 h, 22 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
37710754
Default Alt Text
D20764.diff (5 KB)

Event Timeline