selinux-configfile
100% safe Rust parser and writer for /etc/selinux/config with format-preserving writes, type-safe API, and atomic file updates. Zero dependencies beyond std (serde optional).
Features
- Type-safe API —
SelinuxModeenum (Enforcing/Permissive/Disabled) instead of raw strings; typed getters and setters for all 5 standard keys - Format preservation — comments, blank lines, indentation, spacing around
=, and inline comments survive all read-modify-write cycles intact - Atomic writes — write to temp file +
fsync+renameensures the config file is never left in a corrupt state - Zero unsafe —
#![forbid(unsafe_code)]ready; verified withgrep -r "unsafe" src/ - Thread-safe — all public types implement
SendandSync - Generic key-value API — supports unknown/custom keys beyond the standard SELinux set
- Validation — validates values against SELinux rules (
enforcing/permissive/disabled, boolean keys, SELINUXTYPE restrictions)
Quick Start
use ;
// Parse an in-memory string
let mut cfg = parse.unwrap;
assert_eq!;
assert_eq!;
// Modify values with type-safe setters
cfg.set_selinux;
cfg.set_selinuxtype.unwrap;
// Serialize — comments and formatting preserved
let output = cfg.to_string;
// Read, modify, and write the system config file
use ;
let mut cfg = read_default.unwrap;
cfg.set_selinux;
cfg.write_default.unwrap;
API Overview
Reading
| Method | Returns |
|---|---|
selinux() |
Option<SelinuxMode> |
selinuxtype() |
Option<&str> |
require_seusers() |
Option<bool> |
autorelabel() |
Option<bool> |
setlocaldefs() |
Option<bool> |
get(key) |
Option<&str> — any key, case-insensitive |
get_bool(key) |
Option<bool> — parses 0/1/true/false |
contains(key) |
bool |
keys() |
Vec<&str> — all unique keys |
is_empty() |
bool |
lines() |
&[Line] — all lines including comments |
validate() |
Vec<ValueError> — empty = valid |
Writing
| Method | Description |
|---|---|
set_selinux(mode) |
Set SELinux mode (type-safe) |
set_selinuxtype(s) |
Set policy type (validated) |
set_require_seusers(b) |
Set REQUIRESEUSERS |
set_autorelabel(b) |
Set AUTORELABEL |
set_setlocaldefs(b) |
Set SETLOCALDEFS |
set(key, value) |
Set any key (generic, case-insensitive) |
remove(key) |
Remove all entries for a key |
disable(key) |
Comment out all entries for a key |
add_comment_line(s) |
Append a # comment line |
add_blank_line() |
Append a blank line |
File I/O
| Method | Description |
|---|---|
read_from(path) |
Read and parse any path |
read_default() |
Read /etc/selinux/config |
write_to(path) |
Atomic write to any path |
write_default() |
Atomic write to /etc/selinux/config |
Format Preservation
The library represents each config file as a sequence of lines:
Comment(String)—#comment lines (preserved verbatim)Blank(String)— empty or whitespace-only linesRaw(String)— unrecognized lines (no=)Entry { key_raw, value, raw_leading, raw_separator, raw_suffix }— key=value with formatting metadata
When a value is modified, only the value field changes. All other fields — leading whitespace, separator style (= vs = vs = ), trailing content (inline comments, whitespace) — are written back exactly as parsed.
let input = "SELINUX = enforcing # production\n";
let mut cfg = parse.unwrap;
cfg.set_selinux;
assert_eq!;
Standard SELinux Config Keys
| Key | Required | Valid Values |
|---|---|---|
SELINUX |
Yes | enforcing, permissive, disabled |
SELINUXTYPE |
Yes | Policy name (e.g., targeted, mls, minimum) |
REQUIRESEUSERS |
No | 0 / 1 |
AUTORELABEL |
No | 0 / 1 |
SETLOCALDEFS |
No (deprecated) | 0 / 1 |
Based on selinux_config(5) and libselinux source.
Installation
License
MIT