git: 61174ad88e33 - main - newsyslog(8): Add support of specifying compression method in configuration file.

From: Xin LI <delphij_at_FreeBSD.org>
Date: Fri, 29 Dec 2023 08:33:13 UTC
The branch main has been updated by delphij:

URL: https://cgit.FreeBSD.org/src/commit/?id=61174ad88e33b6162fa1c9ee37d7f227e0bbf931

commit 61174ad88e33b6162fa1c9ee37d7f227e0bbf931
Author:     Xin LI <delphij@FreeBSD.org>
AuthorDate: 2023-12-25 07:47:36 +0000
Commit:     Xin LI <delphij@FreeBSD.org>
CommitDate: 2023-12-29 08:32:26 +0000

    newsyslog(8): Add support of specifying compression method in configuration file.
    
    Administrators can now specify a global compression method directly
    at the beginning of the newsyslog.conf file, for example:
    
            <compress> none
    
    Relnotes:       yes
    Reviewed by:    dvl
    MFC after:      1 week
    Differential Revision: https://reviews.freebsd.org/D43174
---
 usr.sbin/newsyslog/newsyslog.c      | 97 +++++++++++++++++++++++++++++++------
 usr.sbin/newsyslog/newsyslog.conf.5 | 23 +++++++--
 2 files changed, 99 insertions(+), 21 deletions(-)

diff --git a/usr.sbin/newsyslog/newsyslog.c b/usr.sbin/newsyslog/newsyslog.c
index a08e7b903707..9f9185c1ad20 100644
--- a/usr.sbin/newsyslog/newsyslog.c
+++ b/usr.sbin/newsyslog/newsyslog.c
@@ -74,6 +74,7 @@
 #include <paths.h>
 #include <pwd.h>
 #include <signal.h>
+#include <stdbool.h>
 #include <stdio.h>
 #include <libgen.h>
 #include <stdlib.h>
@@ -124,6 +125,7 @@ enum compress_types_enum {
 #define	DEFAULT_MARKER	"<default>"
 #define	DEBUG_MARKER	"<debug>"
 #define	INCLUDE_MARKER	"<include>"
+#define	COMPRESS_MARKER	"<compress>"
 #define	DEFAULT_TIMEFNAME_FMT	"%Y%m%dT%H%M%S"
 
 #define	MAX_OLDLOGS 65536	/* Default maximum number of old logfiles */
@@ -248,6 +250,8 @@ static char *archdirname;	/* Directory path to old logfiles archive */
 static char *destdir = NULL;	/* Directory to treat at root for logs */
 static const char *conf;	/* Configuration file to use */
 static enum compress_types_enum compress_type_override = COMPRESS_LEGACY;	/* Compression type */
+static bool compress_type_set = false;
+static bool compress_type_seen = false;
 
 struct ptime_data *dbg_timenow;	/* A "timenow" value set via -D option */
 static struct ptime_data *timenow; /* The time to use for checking at-fields */
@@ -505,6 +509,37 @@ free_clist(struct cflist *list)
 	list = NULL;
 }
 
+static bool
+parse_compression_type(const char *str, enum compress_types_enum *type)
+{
+	int i;
+
+	for (i = 0; i < COMPRESS_TYPES; i++) {
+		if (strcasecmp(str, compress_type[i].name) == 0) {
+			*type = i;
+			break;
+		}
+	}
+	if (i == COMPRESS_TYPES) {
+		if (strcasecmp(str, "legacy") == 0)
+			compress_type_override = COMPRESS_LEGACY;
+		else {
+			return (false);
+		}
+	}
+	return (true);
+}
+
+static const char *
+compression_type_name(enum compress_types_enum type)
+{
+
+	if (type == COMPRESS_LEGACY)
+		return ("legacy");
+	else
+		return (compress_type[type].name);
+}
+
 static fk_entry
 do_entry(struct conf_entry * ent)
 {
@@ -628,8 +663,13 @@ do_entry(struct conf_entry * ent)
 		if (ent->rotate && !norotate) {
 			if (temp_reason[0] != '\0')
 				ent->r_reason = strdup(temp_reason);
-			if (verbose)
-				printf("--> trimming log....\n");
+			if (verbose) {
+				if (ent->compress == COMPRESS_NONE)
+					printf("--> trimming log....\n");
+				else
+					printf("--> trimming log and compressing with %s....\n",
+					    compression_type_name(ent->compress));
+			}
 			if (noaction && !verbose)
 				printf("%s <%d%s>: trimming\n", ent->log,
 				    ent->numlogs,
@@ -647,7 +687,7 @@ do_entry(struct conf_entry * ent)
 static void
 parse_args(int argc, char **argv)
 {
-	int ch, i;
+	int ch;
 	char *p;
 
 	timenow = ptime_init(NULL);
@@ -667,20 +707,11 @@ parse_args(int argc, char **argv)
 			archdirname = optarg;
 			break;
 		case 'c':
-			for (i = 0; i < COMPRESS_TYPES; i++) {
-				if (strcmp(optarg, compress_type[i].name) == 0) {
-					compress_type_override = i;
-					break;
-				}
-			}
-			if (i == COMPRESS_TYPES) {
-				if (strcmp(optarg, "legacy") == 0)
-					compress_type_override = COMPRESS_LEGACY;
-				else {
-					warnx("Unrecognized compression method '%s'.", optarg);
-					usage();
-				}
+			if (!parse_compression_type(optarg, &compress_type_override)) {
+				warnx("Unrecognized compression method '%s'.", optarg);
+				usage();
 			}
+			compress_type_set = true;
 			break;
 		case 'd':
 			destdir = optarg;
@@ -1187,6 +1218,36 @@ parse_file(FILE *cf, struct cflist *work_p, struct cflist *glob_p,
 			} else
 				add_to_queue(q, inclist);
 			continue;
+		} else if (strcasecmp(COMPRESS_MARKER, q) == 0) {
+			enum compress_types_enum result;
+
+			if (verbose)
+				printf("Found: %s", errline);
+			q = parse = missing_field(sob(parse + 1), errline);
+			parse = son(parse);
+			if (!*parse)
+				warnx("compress line specifies no option:\n%s",
+				    errline);
+			else {
+				*parse = '\0';
+				if (parse_compression_type(q, &result)) {
+					if (compress_type_set) {
+						warnx("Ignoring compress line "
+						    "option '%s', using '%s' instead",
+						    q,
+						    compression_type_name(compress_type_override));
+					} else {
+						if (compress_type_seen)
+							warnx("Compress type should appear before all log files:\n%s",
+							    errline);
+						compress_type_override = result;
+						compress_type_set = true;
+					}
+				} else {
+					warnx("Bad compress option '%s'", q);
+				};
+			}
+			continue;
 		}
 
 #define badline(msg, ...) do {		\
@@ -1357,6 +1418,7 @@ no_trimat:
 					working->compress = COMPRESS_BZIP2;
 				else
 					working->compress = compress_type_override;
+				compress_type_seen = true;
 				break;
 			case 'n':
 				working->flags |= CE_NOSIGNAL;
@@ -1381,18 +1443,21 @@ no_trimat:
 					working->compress = COMPRESS_XZ;
 				else
 					working->compress = compress_type_override;
+				compress_type_seen = true;
 				break;
 			case 'y':
 				if (compress_type_override == COMPRESS_LEGACY)
 					working->compress = COMPRESS_ZSTD;
 				else
 					working->compress = compress_type_override;
+				compress_type_seen = true;
 				break;
 			case 'z':
 				if (compress_type_override == COMPRESS_LEGACY)
 					working->compress = COMPRESS_GZIP;
 				else
 					working->compress = compress_type_override;
+				compress_type_seen = true;
 				break;
 			case '-':
 				break;
diff --git a/usr.sbin/newsyslog/newsyslog.conf.5 b/usr.sbin/newsyslog/newsyslog.conf.5
index a53af5b38319..120c5a0cb7cc 100644
--- a/usr.sbin/newsyslog/newsyslog.conf.5
+++ b/usr.sbin/newsyslog/newsyslog.conf.5
@@ -18,7 +18,7 @@
 .\" the suitability of this software for any purpose.  It is
 .\" provided "as is" without express or implied warranty.
 .\"
-.Dd December 22, 2023
+.Dd December 25, 2023
 .Dt NEWSYSLOG.CONF 5
 .Os
 .Sh NAME
@@ -67,11 +67,24 @@ The fields of the configuration file are as follows:
 .Bl -tag -width indent
 .It Ar logfile_name
 Name of the system log file to be archived,
-or one of the literal strings
-.Dq Aq Li default ,
+or one of the special strings
+.Dq Li <compress> ,
+.Dq Li <default> ,
 or
-.Dq Aq Li include .
-The special default entry will only be used if a log file
+.Dq Li <include> .
+The <compress> entry,
+which should be placed at the beginning of the
+.Nm
+configuration file,
+sets the global compress method.
+This method is applied when a log file is flagged as
+compressible,
+which has the same effect of passing a compress method to the
+.Fl c
+option on the
+.Xr newsyslog 8
+command line.
+The special <default> entry will only be used if a log file
 name is given as a command line argument to
 .Xr newsyslog 8 ,
 and if that log file name is not matched by any other