osdns 0.2.0

Safe, transactional control of operating-system DNS configuration
Documentation
use std::fs;
use std::io;
use std::path::Path;

use crate::error::{Error, Result};

pub(crate) fn ensure_private_dir(path: &Path) -> Result<()> {
    match fs::create_dir_all(path) {
        Ok(()) => {}
        Err(e) if e.kind() == io::ErrorKind::PermissionDenied => {
            return Err(Error::RequiresPrivilege(format!(
                "cannot create directory {}: {e}",
                path.display()
            )));
        }
        Err(e) => return Err(e.into()),
    }
    #[cfg(unix)]
    {
        use std::os::unix::fs::PermissionsExt;
        let meta = fs::metadata(path)?;
        if meta.permissions().mode() & 0o077 != 0 {
            match fs::set_permissions(path, fs::Permissions::from_mode(0o700)) {
                Ok(()) => {}
                Err(e) if e.kind() == io::ErrorKind::PermissionDenied => {
                    return Err(Error::RequiresPrivilege(format!(
                        "directory {} is accessible to other users and could not be restricted: {e}",
                        path.display()
                    )));
                }
                Err(e) => return Err(e.into()),
            }
            let meta = fs::metadata(path)?;
            if meta.permissions().mode() & 0o077 != 0 {
                return Err(Error::RequiresPrivilege(format!(
                    "directory {} is accessible to other users and could not be restricted",
                    path.display()
                )));
            }
        }
    }
    #[cfg(not(unix))]
    {
        let _ = path;
    }
    Ok(())
}

pub(crate) fn fsync_dir(path: &Path) -> io::Result<()> {
    #[cfg(unix)]
    {
        let file = fs::File::open(path)?;
        file.sync_all()
    }
    #[cfg(not(unix))]
    {
        let _ = path;
        Ok(())
    }
}