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
This commit is contained in:
Xin LI 2023-12-24 23:47:36 -08:00
parent ee5804da11
commit 61174ad88e
2 changed files with 99 additions and 21 deletions

View file

@ -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 @@ parse_file(FILE *cf, struct cflist *work_p, struct cflist *glob_p,
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 @@ parse_file(FILE *cf, struct cflist *work_p, struct cflist *glob_p,
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;

View file

@ -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