mirror of
https://github.com/freebsd/freebsd-src.git
synced 2026-10-28 11:25:21 +01:00
Complete the native configuration trinity: sysctl(8) for live kernel state, sysrc(8) for rc.conf(5), and sysconf(8) for the remaining base configuration -- loader.conf(5), sysctl.conf(5), and the make.conf(5) family -- atop libbsdconf(3). libbsdconf resurrects figpar as a unified reader/writer. Callbacks own semantics; statements may span multiple lines via backslash continuation; non-seekable input is spooled; writes are atomic (mkstemp, fsync, rename) with mode/owner preservation. Format descriptors name each target, its files, and quoting rules without private parsers. Multi-file targets follow boot sourcing order; loader chases loader_conf_files as the boot loader does. sysconf(8) is the operator-facing tool: name / name=value on a required target, sysrc-style list edits, make append and list-strike where they belong, jail/altroot, and a capsicum sandbox for read-only use. Sysctl writes validate against the running kernel first -- unknown and read-only OIDs, CTLFLAG_TUN (pointing at the loader target), and CTLTYPE range checks -- so a typo or overflow does not land in sysctl.conf. Make and src treat WITH_/WITHOUT_ as presence knobs (as bsd.mkopt.mk / src.conf(5) do) and warn on the WITH_*=no form that does not disable the option, so a bad assignment is caught before an /usr/src build surfaces it. The rc target passes through to sysrc(8). Defaults querying (-d/-D/-A) mirrors sysrc for dumps and descriptions on targets that have a defaults file; named reads already see defaults, and -A only widens dump scope. Manuals are split pkg(8)-style (bsdconf/put/format; sysconf plus per-target pages). ATF coverage exercises the frontend. Co-authored-by: Faraz Vahedi <[email protected]> Reviewed by: fuz, kfv Differential Revision: https://reviews.freebsd.org/D58066
561 lines
15 KiB
Plaintext
561 lines
15 KiB
Plaintext
.\" Copyright (c) 2013-2026 Devin Teske <[email protected]>
|
|
.\" Copyright (c) 2021-2026 Faraz Vahedi <[email protected]>
|
|
.\"
|
|
.\" SPDX-License-Identifier: BSD-2-Clause
|
|
.\"
|
|
.Dd August 2, 2026
|
|
.Dt BSDCONF_FORMAT 3
|
|
.Os
|
|
.Sh NAME
|
|
.Nm bsdconf_format_derive ,
|
|
.Nm bsdconf_format_files ,
|
|
.Nm bsdconf_format_files_free ,
|
|
.Nm bsdconf_format_find ,
|
|
.Nm bsdconf_format_guess ,
|
|
.Nm bsdconf_format_lookup ,
|
|
.Nm bsdconf_format_path ,
|
|
.Nm bsdconf_format_processing ,
|
|
.Nm bsdconf_format_put ,
|
|
.Nm bsdconf_format_register
|
|
.Nd configuration format descriptors and discovery
|
|
.Sh LIBRARY
|
|
.Lb libbsdconf
|
|
.Sh SYNOPSIS
|
|
.In bsdconf.h
|
|
.Ft int
|
|
.Fo bsdconf_format_derive
|
|
.Fa "enum bsdconf_format base"
|
|
.Fa "struct bsdconf_format_def *def"
|
|
.Fc
|
|
.Ft int
|
|
.Fo bsdconf_format_files
|
|
.Fa "enum bsdconf_format format"
|
|
.Fa "const char *rootdir"
|
|
.Fa "const char *module"
|
|
.Fa "const char *defaults"
|
|
.Fa "char ***filesp"
|
|
.Fa "size_t *nfilesp"
|
|
.Fa "size_t *write_idxp"
|
|
.Fc
|
|
.Ft void
|
|
.Fo bsdconf_format_files_free
|
|
.Fa "char **files"
|
|
.Fa "size_t nfiles"
|
|
.Fc
|
|
.Ft int
|
|
.Fo bsdconf_format_find
|
|
.Fa "const char *keyword"
|
|
.Fa "enum bsdconf_format *format"
|
|
.Fc
|
|
.Ft "enum bsdconf_format"
|
|
.Fo bsdconf_format_guess
|
|
.Fa "const char *path"
|
|
.Fc
|
|
.Ft "const struct bsdconf_format_def *"
|
|
.Fo bsdconf_format_lookup
|
|
.Fa "enum bsdconf_format format"
|
|
.Fc
|
|
.Ft "const char *"
|
|
.Fo bsdconf_format_path
|
|
.Fa "enum bsdconf_format format"
|
|
.Fc
|
|
.Ft uint16_t
|
|
.Fo bsdconf_format_processing
|
|
.Fa "enum bsdconf_format format"
|
|
.Fc
|
|
.Ft uint16_t
|
|
.Fo bsdconf_format_put
|
|
.Fa "enum bsdconf_format format"
|
|
.Fc
|
|
.Ft int
|
|
.Fo bsdconf_format_register
|
|
.Fa "const struct bsdconf_format_def *def"
|
|
.Fa "enum bsdconf_format *format"
|
|
.Fc
|
|
.Sh DESCRIPTION
|
|
Every supported configuration file format is described by the same small
|
|
format descriptor
|
|
.Pq introduced in Xr bsdconf 3 :
|
|
.Bd -literal -offset indent
|
|
struct bsdconf_format_def {
|
|
const char *keyword; /* target keyword (or NULL) */
|
|
const char *path; /* default write path (or NULL) */
|
|
const struct bsdconf_source
|
|
*sources; /* ordered sources (or NULL) */
|
|
const char *defaults; /* defaults file (or NULL) */
|
|
const char *defaults_env; /* environment override */
|
|
const char *files_directive;
|
|
/* directive listing conf files */
|
|
const char *dirs_directive;
|
|
/* directive listing drop-in dirs */
|
|
const char *local_directive;
|
|
/* directive listing local files */
|
|
uint16_t processing; /* processing_options bitmask */
|
|
uint16_t put; /* put_options bitmask */
|
|
};
|
|
|
|
enum bsdconf_source_type {
|
|
BSDCONF_SOURCE_FILE = 0, /* a single file */
|
|
BSDCONF_SOURCE_DIR, /* each `*.conf' in a directory */
|
|
BSDCONF_SOURCE_MODDIR, /* `<module>.conf' in a directory */
|
|
};
|
|
|
|
struct bsdconf_source {
|
|
enum bsdconf_source_type type; /* how to interpret path */
|
|
const char *path; /* file or directory path */
|
|
};
|
|
.Ed
|
|
.Pp
|
|
There is exactly one parsing and writing engine;
|
|
a format descriptor merely parameterizes it.
|
|
The built-in formats,
|
|
with their target keywords and default write paths,
|
|
are:
|
|
.Bl -column "BSDCONF_FORMAT_GENERIC" "keyword" "/boot/loader.conf"
|
|
.It Sy format Ta Sy keyword Ta Sy "default write path"
|
|
.It Dv BSDCONF_FORMAT_GENERIC Ta generic Ta \&-
|
|
.It Dv BSDCONF_FORMAT_LOADER Ta loader Ta /boot/loader.conf
|
|
.It Dv BSDCONF_FORMAT_SYSCTL Ta sysctl Ta /etc/sysctl.conf
|
|
.It Dv BSDCONF_FORMAT_MAKE Ta make Ta /etc/make.conf
|
|
.It Dv BSDCONF_FORMAT_SRC Ta src Ta /etc/src.conf
|
|
.El
|
|
.Pp
|
|
The default write path
|
|
.Pq the Va path member
|
|
answers only the question of where a
|
|
.Em new
|
|
directive lands:
|
|
the file to which a directive not yet present anywhere is appended.
|
|
Which files are
|
|
.Em consulted
|
|
is a separate and potentially broader question,
|
|
answered by the
|
|
.Va sources
|
|
member.
|
|
When
|
|
.Va sources
|
|
is NULL
|
|
.Pq as for Dv BSDCONF_FORMAT_MAKE
|
|
the default write path is the format's one and only file and the two
|
|
questions collapse into one.
|
|
Otherwise
|
|
.Po
|
|
.Dv BSDCONF_FORMAT_LOADER ,
|
|
.Dv BSDCONF_FORMAT_SYSCTL ,
|
|
and
|
|
.Dv BSDCONF_FORMAT_SRC
|
|
.Pc
|
|
the format is backed by several files and
|
|
.Va sources
|
|
lists them:
|
|
an ordered,
|
|
NULL-path terminated array in which each entry contributes a single file
|
|
.Pq Dv BSDCONF_SOURCE_FILE ,
|
|
every
|
|
.Ql *.conf
|
|
found in a drop-in directory
|
|
.Pq Dv BSDCONF_SOURCE_DIR ,
|
|
or the file
|
|
.Ql <module>.conf
|
|
in a directory keyed by kernel module name
|
|
.Pq Dv BSDCONF_SOURCE_MODDIR .
|
|
The order matches the order in which the system sources the files at boot,
|
|
so a directive in a later file overrides the same directive in an earlier
|
|
one and the last file listing a directive is the authoritative source of
|
|
its value.
|
|
The built-in source lists are:
|
|
.Bl -tag -width BSDCONF_FORMAT_LOADER -offset indent
|
|
.It Dv BSDCONF_FORMAT_LOADER
|
|
discovered from
|
|
.Pa /boot/defaults/loader.conf
|
|
.Pq see below ;
|
|
on a stock system
|
|
.Pa /boot/device.hints ,
|
|
.Pa /boot/loader.conf ,
|
|
each
|
|
.Pa *.conf
|
|
in
|
|
.Pa /boot/loader.conf.d ,
|
|
then
|
|
.Pa /boot/loader.conf.local
|
|
.Pq see Xr loader.conf 5 ;
|
|
.It Dv BSDCONF_FORMAT_SYSCTL
|
|
.Pa /etc/sysctl.conf ,
|
|
.Pa /etc/sysctl.conf.local ,
|
|
then
|
|
.Pa /etc/sysctl.kld.d/<module>.conf
|
|
.Pq see Xr sysctl.conf 5 ;
|
|
.It Dv BSDCONF_FORMAT_MAKE
|
|
.Pa /etc/make.conf
|
|
alone;
|
|
.It Dv BSDCONF_FORMAT_SRC
|
|
.Pa /etc/src-env.conf ,
|
|
.Pa /etc/make.conf ,
|
|
then
|
|
.Pa /etc/src.conf
|
|
.Pq the /usr/src build triad; see Xr src.conf 5 ;
|
|
new writes prefer
|
|
.Pa src.conf .
|
|
.El
|
|
.Pp
|
|
A format whose backing files are themselves configuration data describes
|
|
that machinery with the descriptor's
|
|
.Va defaults
|
|
member quintet rather than a static list alone.
|
|
The boot loader hardcodes only
|
|
.Pa /boot/defaults/loader.conf
|
|
and discovers every other file from the
|
|
.Va loader_conf_files ,
|
|
.Va loader_conf_dirs ,
|
|
and
|
|
.Va local_loader_conf_files
|
|
directives it encounters along the way
|
|
.Pq see Xr loader.conf 5 ,
|
|
and
|
|
.Dv BSDCONF_FORMAT_LOADER
|
|
names that defaults file and those three directives so that
|
|
.Fn bsdconf_format_files
|
|
matches that discovery:
|
|
the defaults file is read,
|
|
.Va loader_conf_files
|
|
is chased
|
|
.Po
|
|
re-read after every file, as the loader does when a file queues
|
|
additional names
|
|
.Pc ,
|
|
and the drop-in directories and local files named by the final
|
|
.Va loader_conf_dirs
|
|
and
|
|
.Va local_loader_conf_files
|
|
values are appended
|
|
.Pq the loader likewise applies those only after the file-list walk .
|
|
The defaults file itself is deliberately excluded from the resolved list,
|
|
mirroring how
|
|
.Xr sysrc 8
|
|
excludes
|
|
.Pa /etc/defaults/rc.conf ;
|
|
the static
|
|
.Va sources
|
|
list serves as the fallback when the defaults file is missing.
|
|
.Pp
|
|
.Fn bsdconf_format_files
|
|
resolves the backing files of
|
|
.Fa format
|
|
into a newly allocated array of paths stored through
|
|
.Fa filesp
|
|
.Pq with the count stored through Fa nfilesp ,
|
|
each prefixed with
|
|
.Fa rootdir
|
|
unless NULL or empty.
|
|
When
|
|
.Fa defaults
|
|
is non-NULL,
|
|
it overrides the descriptor's defaults file for discovery and is used
|
|
verbatim
|
|
.Po
|
|
not prefixed with
|
|
.Fa rootdir ;
|
|
it is ignored for formats without one
|
|
.Pc .
|
|
When
|
|
.Fa write_idxp
|
|
is non-NULL,
|
|
the index of the file recommended for directives found in no file at all
|
|
is stored through it:
|
|
the format's default write path,
|
|
or the last regular
|
|
.Pq non-drop-in, non-local
|
|
configuration file when discovery is in play.
|
|
Sources of type
|
|
.Dv BSDCONF_SOURCE_FILE
|
|
.Pq and files named by a file-list directive
|
|
are always listed,
|
|
whether or not the file exists;
|
|
directory sources contribute only the entries present on disk
|
|
.Pq sorted ;
|
|
module sources contribute
|
|
.Ql <module>.conf
|
|
only when
|
|
.Fa module
|
|
is non-NULL.
|
|
The caller releases the result with
|
|
.Fn bsdconf_format_files_free .
|
|
.Pp
|
|
The formats also differ in quoting on output,
|
|
each honoring the full syntax its consumer accepts:
|
|
.Xr loader.conf 5
|
|
values are always written quoted
|
|
.Pq quoted or unquoted input is accepted when parsing
|
|
and no whitespace is permitted around the equals sign,
|
|
as demanded by the boot loader's reader;
|
|
.Xr sysctl.conf 5
|
|
follows the file parser of
|
|
.Xr sysctl 8 ,
|
|
which trims whitespace around the equals sign and strips one pair of quotes
|
|
around the value,
|
|
so values are written unquoted unless quoting is required
|
|
.Pq embedded whitespace or a comment character ;
|
|
.Pa make.conf
|
|
follows
|
|
.Xr make 1
|
|
syntax where values are never quoted
|
|
.Pq the value runs to the end of the line
|
|
and assignment modifiers such as
|
|
.Ql +=
|
|
are recognized.
|
|
The
|
|
.Dv BSDCONF_FORMAT_SRC
|
|
triad
|
|
.Po
|
|
.Pa src-env.conf ,
|
|
.Pa make.conf ,
|
|
.Pa src.conf
|
|
.Pc
|
|
shares that
|
|
.Pa make.conf
|
|
syntax exactly
|
|
.Pq all three are read by Xr make 1 when building /usr/src ,
|
|
including the empty value,
|
|
which for
|
|
.Pa src.conf
|
|
is the idiom for the value-less
|
|
.Ql WITH_*
|
|
and
|
|
.Ql WITHOUT_*
|
|
build knobs.
|
|
.Pp
|
|
.Fn bsdconf_format_find
|
|
maps a target keyword
|
|
.Pq e.g., Dq loader
|
|
to its format.
|
|
.Fn bsdconf_format_guess
|
|
guesses the format of an arbitrary file from the basename of
|
|
.Fa path ,
|
|
matching
|
|
.Ql <keyword>.conf
|
|
with an optional trailing suffix
|
|
.Pq e.g., Pa /etc/sysctl.conf.local .
|
|
The guess is advisory and offered for consumers that opt into it
|
|
.Pq an interactive picker suggesting a default, for example ;
|
|
where a wrong format silently misformats a file,
|
|
as when writing,
|
|
the caller should require the format to be stated explicitly instead,
|
|
as
|
|
.Xr sysconf 8
|
|
does with its
|
|
.Ar target
|
|
keyword.
|
|
.Fn bsdconf_format_lookup
|
|
returns the format descriptor for a format handle.
|
|
.Fn bsdconf_format_path ,
|
|
.Fn bsdconf_format_processing ,
|
|
and
|
|
.Fn bsdconf_format_put
|
|
return the default file path and the two option bitmasks,
|
|
respectively.
|
|
.Sh ADDING FORMATS
|
|
Before adding a format,
|
|
consider whether one is needed at all:
|
|
the parser hands each statement's raw directive and value to the caller's
|
|
callbacks and imposes no semantics of its own,
|
|
so a file whose directives mean something unusual
|
|
.Po
|
|
cumulative directives that legitimately repeat,
|
|
for example,
|
|
which a
|
|
.Fn parse
|
|
callback accumulates rather than overwrites;
|
|
see
|
|
.Xr bsdconf 3
|
|
.Pc
|
|
is read with the stock engine and bespoke callbacks;
|
|
no format descriptor,
|
|
flag,
|
|
or engine change is required.
|
|
A format descriptor parameterizes only tokenization and writing;
|
|
reach for one when a file needs a
|
|
.Xr sysconf 8
|
|
target keyword,
|
|
a source list,
|
|
or distinct quoting on output.
|
|
Rewriting files built from cumulative directives,
|
|
where a change is additive rather than a replacement,
|
|
is only partly covered by
|
|
.Va match_line
|
|
selection in
|
|
.Xr bsdconf_put 3 ;
|
|
higher-level additive policy remains the caller's concern
|
|
.Pq see that page's Sx LIMITATIONS .
|
|
.Pp
|
|
Beyond callbacks,
|
|
the format descriptor is the entire definition of a format;
|
|
no format has private parsing or writing code.
|
|
Support for a new configuration file format is therefore a data problem,
|
|
approached one of two ways.
|
|
.Pp
|
|
An application whose format is mostly like an existing one bolts it on at
|
|
runtime without duplicating any logic
|
|
.Pq see Sx EXAMPLES :
|
|
.Fn bsdconf_format_derive
|
|
copies the format descriptor of the nearest
|
|
.Fa base
|
|
format into
|
|
.Fa def ,
|
|
the caller adjusts only the members that differ
|
|
.Pq typically the keyword, the paths, and one or two bitmask flags ,
|
|
and
|
|
.Fn bsdconf_format_register
|
|
registers the result and returns a new format handle through
|
|
.Fa format .
|
|
The format descriptor is copied by value but the strings and arrays it
|
|
references
|
|
.Po
|
|
.Va keyword ,
|
|
.Va path ,
|
|
.Va sources ,
|
|
and the
|
|
.Va defaults
|
|
member quintet
|
|
.Pc
|
|
are not;
|
|
they must remain valid for the life of the registration.
|
|
Registered formats participate in keyword and basename resolution exactly
|
|
like built-ins,
|
|
including target resolution in
|
|
.Xr sysconf 8 Ns -style
|
|
consumers.
|
|
Registration is intended to occur during program initialization and is not
|
|
thread-safe.
|
|
.Pp
|
|
Within the library,
|
|
each built-in format is a self-contained translation unit
|
|
.Pa ( bsdconf_format_<keyword>.c )
|
|
that documents the format's syntax rules,
|
|
cites the authority for them
|
|
.Pq the consumer whose reader defines what is legal ,
|
|
and defines its format descriptor,
|
|
including its ordered source list.
|
|
Promoting a format into the library therefore touches no existing parsing
|
|
or writing code:
|
|
a new file of the same shape is dropped in,
|
|
its descriptor is declared alongside its siblings,
|
|
one
|
|
.Dv BSDCONF_FORMAT_*
|
|
constant is appended to
|
|
.Vt enum bsdconf_format ,
|
|
one pointer is appended to the registry table,
|
|
the file is listed in the Makefile,
|
|
and this manual's
|
|
.Sx DESCRIPTION
|
|
section grows one row and one quoting note.
|
|
The keyword becomes a
|
|
.Xr sysconf 8
|
|
target automatically.
|
|
.Pp
|
|
Many formats need no new engine capability at all.
|
|
Formats whose statements are a space-separated directive and value with no
|
|
equals sign
|
|
.Pq the Apache-style directive files the ancestral parser was raised on
|
|
parse today:
|
|
with
|
|
.Dv BSDCONF_BREAK_ON_EQUALS
|
|
omitted,
|
|
the first whitespace-delimited token is the directive and the remainder of
|
|
the line is the raw value
|
|
.Po which a
|
|
.Fn parse
|
|
callback may split further by its own rules
|
|
.Pc ,
|
|
and directive matching is case insensitive unless
|
|
.Dv BSDCONF_CASE_SENSITIVE
|
|
is set.
|
|
Likewise
|
|
.Dv BSDCONF_BREAK_ON_SEMICOLON
|
|
already covers formats that terminate or chain statements with a
|
|
semicolon.
|
|
.Pp
|
|
A candidate format whose syntax the existing option flags cannot express
|
|
.Pq brace-grouped statement blocks being the canonical example
|
|
is handled by teaching the shared engine
|
|
.Pq the scanners in the parsing and writing cores
|
|
one new
|
|
.Va processing
|
|
or
|
|
.Va put
|
|
flag that the new format's descriptor is the first to set.
|
|
The capability lands once,
|
|
composes with every existing flag,
|
|
and becomes available to every other format
|
|
.Pq built-in, derived, or registered
|
|
rather than living in a private parser;
|
|
the new format itself remains nothing more than a format descriptor in its
|
|
own translation unit.
|
|
.Sh RETURN VALUES
|
|
.Fn bsdconf_format_derive
|
|
and
|
|
.Fn bsdconf_format_register
|
|
return zero on success;
|
|
otherwise -1 with
|
|
.Va errno
|
|
set to
|
|
.Er EINVAL
|
|
or
|
|
.Er ENOSPC .
|
|
.Fn bsdconf_format_find
|
|
returns zero on success;
|
|
otherwise -1.
|
|
.Fn bsdconf_format_files
|
|
returns zero on success;
|
|
otherwise -1 with
|
|
.Va errno
|
|
set to indicate the error
|
|
.Pq Er EINVAL for a format with no backing files .
|
|
.Sh EXAMPLES
|
|
Bolt on a new format at runtime by deriving from the built-in it most
|
|
resembles,
|
|
then set a directive in its file with full resilient write semantics:
|
|
.Bd -literal -offset indent
|
|
struct bsdconf_format_def def;
|
|
enum bsdconf_format myfmt;
|
|
struct bsdconf_option set[] = {
|
|
{ .type = BSDCONF_TYPE_STR, .directive = "loglevel",
|
|
.value = { .str = "debug" },
|
|
.action = BSDCONF_ACTION_SET_VALUE },
|
|
{ .directive = NULL }
|
|
};
|
|
|
|
if (bsdconf_format_derive(BSDCONF_FORMAT_SYSCTL, &def) != 0)
|
|
err(1, "bsdconf_format_derive");
|
|
def.keyword = "myapp";
|
|
def.path = "/usr/local/etc/myapp.conf";
|
|
def.sources = NULL; /* one file; path is the sole source */
|
|
if (bsdconf_format_register(&def, &myfmt) != 0)
|
|
err(1, "bsdconf_format_register");
|
|
|
|
if (bsdconf_put(set, bsdconf_format_path(myfmt),
|
|
bsdconf_format_processing(myfmt),
|
|
bsdconf_format_put(myfmt)) != 0)
|
|
err(1, "%s", bsdconf_format_path(myfmt));
|
|
.Ed
|
|
.Pp
|
|
Promoting such a format into the library itself
|
|
.Pq a compiled-in sibling of the built-ins
|
|
is the same data expressed as a translation unit;
|
|
see
|
|
.Sx ADDING FORMATS .
|
|
.Sh SEE ALSO
|
|
.Xr bsdconf 3 ,
|
|
.Xr bsdconf_put 3 ,
|
|
.Xr loader.conf 5 ,
|
|
.Xr src.conf 5 ,
|
|
.Xr sysctl.conf 5 ,
|
|
.Xr sysconf 8
|
|
.Sh HISTORY
|
|
The format descriptor interface first appeared in
|
|
.Fx 16.0
|
|
as part of
|
|
.Xr bsdconf 3 .
|
|
.Sh AUTHORS
|
|
.An Devin Teske Aq Mt [email protected]
|
|
.An Faraz Vahedi Aq Mt [email protected]
|