Skip to content

Commit

Permalink
🔧 Support <includedir>
Browse files Browse the repository at this point in the history
A little less efficient than @elmarco 's implementation over in dbus2#23
  • Loading branch information
jokeyrhyme committed Nov 19, 2024
1 parent 97c2b77 commit d3faefd
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 18 deletions.
7 changes: 6 additions & 1 deletion src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,12 @@ impl TryFrom<Document> for Config {
bc.auth.insert(s);
}
Element::Fork => bc.fork = true,
Element::Include(_) => { /* no-op */ }
Element::Include(_) => {
// NO-OP: removed during `Document::resolve_includes`
}
Element::Includedir(_) => {
// NO-OP: removed during `Document::resolve_includedirs`
}
Element::KeepUmask => bc.keep_umask = true,
Element::Limit => {
warn!("busd does not implement `<limit>`");
Expand Down
85 changes: 69 additions & 16 deletions src/config/xml.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::{
env::current_dir,
fs::read_to_string,
ffi::OsString,
fs::{read_dir, read_to_string},
path::{Path, PathBuf},
str::FromStr,
};
Expand Down Expand Up @@ -36,7 +37,64 @@ impl Document {

let mut doc = Document::from_str(&text)?;
doc.file_path = Some(file_path.as_ref().to_path_buf());
doc.resolve_includes()
doc.resolve_includedirs()?.resolve_includes()
}

fn resolve_includedirs(self) -> Result<Document> {
let base_path = self.base_path()?;
let Document {
busconfig,
file_path,
} = self;

let mut doc = Document {
busconfig: vec![],
file_path: None,
};

for el in busconfig {
match el {
Element::Includedir(dir_path) => {
let dir_path = resolve_include_path(&base_path, &dir_path);
let dir_path = match dir_path.canonicalize() {
Ok(ok) => ok,
// we treat `<includedir>` as though it has `ignore_missing="yes"`
Err(err) => {
warn!(
"should canonicalize directory path '{}': {:?}",
&dir_path.display(),
err
);
continue;
}
};
match read_dir(&dir_path) {
Ok(ok) => {
for entry in ok {
let path = entry?.path();
if path.extension() == Some(&OsString::from("conf"))
&& path.is_file()
{
doc.busconfig.push(Element::Include(IncludeElement {
file_path: path,
..Default::default()
}));
}
}
}
// we treat `<includedir>` as though it has `ignore_missing="yes"`
Err(err) => {
warn!("should read directory '{}': {:?}", &dir_path.display(), err);
continue;
}
}
}
_ => doc.busconfig.push(el),
}
}

doc.file_path = file_path;
Ok(doc)
}

fn resolve_includes(self) -> Result<Document> {
Expand All @@ -56,12 +114,14 @@ impl Document {
match el {
Element::Include(include) => {
let ignore_missing = include.ignore_missing == IncludeOption::Yes;
let file_path = match resolve_include_path(&base_path, &include.file_path) {
let file_path = resolve_include_path(&base_path, &include.file_path);
let file_path = match file_path.canonicalize().map_err(Error::msg) {
Ok(ok) => ok,
Err(err) => {
let msg = format!(
"'{}' should be a valid file path",
include.file_path.display()
"should canonicalize file path '{}': {:?}",
&file_path.display(),
err
);
if ignore_missing {
warn!(msg);
Expand Down Expand Up @@ -117,7 +177,7 @@ pub enum Element {
Auth(String),
Fork,
Include(IncludeElement),
// TODO: support `<includedir>`
Includedir(PathBuf),
KeepUmask,
Listen(String),
Limit,
Expand Down Expand Up @@ -255,13 +315,10 @@ pub struct TypeElement {
pub r#type: BusType,
}

fn resolve_include_path(
base_path: impl AsRef<Path>,
include_path: impl AsRef<Path>,
) -> Result<PathBuf> {
fn resolve_include_path(base_path: impl AsRef<Path>, include_path: impl AsRef<Path>) -> PathBuf {
let p = include_path.as_ref();
if p.is_absolute() {
return p.canonicalize().map_err(Error::msg);
return p.to_path_buf();
}

error!(
Expand All @@ -270,9 +327,5 @@ fn resolve_include_path(
&include_path.as_ref().display()
);

base_path
.as_ref()
.join(p)
.canonicalize()
.map_err(Error::msg)
base_path.as_ref().join(p)
}
5 changes: 4 additions & 1 deletion tests/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,11 @@ fn config_read_file_with_includes_ok() {
Config {
auth: HashSet::from_iter(vec![String::from("ANONYMOUS"), String::from("EXTERNAL"),]),
listen: HashSet::from_iter(vec![
String::from("unix:path=/tmp/a"), // via <includedir>
String::from("unix:path=/tmp/b"), // via <includedir>
// should be no "unix:path=/tmp/not_included" as that file ends in .xml
String::from("unix:path=/tmp/foo"),
String::from("tcp:host=localhost,port=1234"),
String::from("tcp:host=localhost,port=1234"), // via <include>
]),
policies: vec![
Policy::DefaultContext(vec![
Expand Down
5 changes: 5 additions & 0 deletions tests/fixtures/includedir/a.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-Bus Bus Configuration 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>
<listen>unix:path=/tmp/a</listen>
</busconfig>
5 changes: 5 additions & 0 deletions tests/fixtures/includedir/b.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-Bus Bus Configuration 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>
<listen>unix:path=/tmp/b</listen>
</busconfig>
5 changes: 5 additions & 0 deletions tests/fixtures/includedir/not_included.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-Bus Bus Configuration 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>
<listen>unix:path=/tmp/not_included</listen>
</busconfig>
1 change: 1 addition & 0 deletions tests/fixtures/valid.conf
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@
</policy>
<include>./valid_included.conf</include>
<include ignore_missing="yes">./valid_missing.conf</include>
<includedir>./includedir</includedir>
</busconfig>

0 comments on commit d3faefd

Please sign in to comment.