Codex Handbook
config/src/loader/layer_io.rs 183 lines
#[cfg(target_os = "macos")]use super::macos::ManagedAdminConfigLayer;#[cfg(target_os = "macos")]use super::macos::load_managed_admin_config_layer;use crate::config_toml::ConfigToml;use crate::diagnostics::config_error_from_toml;use crate::diagnostics::io_error_from_config_error;use crate::state::LoaderOverrides;use crate::strict_config::config_error_from_ignored_toml_value_fields;use codex_file_system::ExecutorFileSystem;use codex_utils_absolute_path::AbsolutePathBuf;use codex_utils_absolute_path::AbsolutePathBufGuard;use codex_utils_path_uri::PathUri;use std::io;use std::path::Path;use std::path::PathBuf;use toml::Value as TomlValue;#[cfg(unix)]const CODEX_MANAGED_CONFIG_SYSTEM_PATH: &str = "/etc/codex/managed_config.toml";#[derive(Debug, Clone)]pub(super) struct MangedConfigFromFile {    pub managed_config: TomlValue,    pub file: AbsolutePathBuf,}#[derive(Debug, Clone)]pub(super) struct ManagedConfigFromMdm {    pub managed_config: TomlValue,    pub raw_toml: String,}#[derive(Debug, Clone)]pub(super) struct LoadedConfigLayers {    /// If present, data read from a file such as `/etc/codex/managed_config.toml`.    pub managed_config: Option<MangedConfigFromFile>,    /// If present, data read from managed preferences (macOS only).    pub managed_config_from_mdm: Option<ManagedConfigFromMdm>,}pub(super) async fn load_config_layers_internal(    fs: &dyn ExecutorFileSystem,    codex_home: &Path,    overrides: LoaderOverrides,    strict_config: bool,) -> io::Result<LoadedConfigLayers> {    #[cfg(target_os = "macos")]    let LoaderOverrides {        managed_config_path,        managed_preferences_base64,        ..    } = overrides;    #[cfg(not(target_os = "macos"))]    let LoaderOverrides {        managed_config_path,        ..    } = overrides;    let managed_config_path = AbsolutePathBuf::from_absolute_path(        managed_config_path.unwrap_or_else(|| managed_config_default_path(codex_home)),    )?;    let managed_config = read_config_from_path(        fs,        &managed_config_path,        /*log_missing_as_info*/ false,        strict_config,    )    .await?    .map(|loaded| MangedConfigFromFile {        managed_config: loaded,        file: managed_config_path.clone(),    });    #[cfg(target_os = "macos")]    let managed_preferences = load_managed_admin_config_layer(        managed_preferences_base64.as_deref(),        strict_config,        codex_home,    )    .await?    .map(map_managed_admin_layer);    #[cfg(not(target_os = "macos"))]    let managed_preferences = None;    Ok(LoadedConfigLayers {        managed_config,        managed_config_from_mdm: managed_preferences,    })}#[cfg(target_os = "macos")]fn map_managed_admin_layer(layer: ManagedAdminConfigLayer) -> ManagedConfigFromMdm {    let ManagedAdminConfigLayer { config, raw_toml } = layer;    ManagedConfigFromMdm {        managed_config: config,        raw_toml,    }}pub(super) async fn read_config_from_path(    fs: &dyn ExecutorFileSystem,    path: &AbsolutePathBuf,    log_missing_as_info: bool,    strict_config: bool,) -> io::Result<Option<TomlValue>> {    let path_uri = PathUri::from_abs_path(path);    match fs.read_file_text(&path_uri, /*sandbox*/ None).await {        Ok(contents) => match toml::from_str::<TomlValue>(&contents) {            Ok(value) => {                if strict_config {                    validate_config_toml_strictly(path, &contents, &value)?;                }                Ok(Some(value))            }            Err(err) => {                tracing::error!("Failed to parse {}: {err}", path.as_path().display());                let config_error = config_error_from_toml(path.as_path(), &contents, err.clone());                Err(io_error_from_config_error(                    io::ErrorKind::InvalidData,                    config_error,                    Some(err),                ))            }        },        Err(err) if err.kind() == io::ErrorKind::NotFound => {            if log_missing_as_info {                tracing::info!("{} not found, using defaults", path.as_path().display());            } else {                tracing::debug!("{} not found", path.as_path().display());            }            Ok(None)        }        Err(err) => {            tracing::error!("Failed to read {}: {err}", path.as_path().display());            Err(err)        }    }}fn validate_config_toml_strictly(    path: &AbsolutePathBuf,    contents: &str,    value: &TomlValue,) -> io::Result<()> {    let Some(base_dir) = path.as_path().parent() else {        return Err(io::Error::new(            io::ErrorKind::InvalidData,            format!("Config file {} has no parent directory", path.display()),        ));    };    let _guard = AbsolutePathBufGuard::new(base_dir);    if let Some(config_error) = config_error_from_ignored_toml_value_fields::<ConfigToml>(        path.as_path(),        contents,        value.clone(),    ) {        return Err(io_error_from_config_error(            io::ErrorKind::InvalidData,            config_error,            /*source*/ None,        ));    }    Ok(())}/// Return the default managed config path.pub(super) fn managed_config_default_path(codex_home: &Path) -> PathBuf {    #[cfg(unix)]    {        let _ = codex_home;        PathBuf::from(CODEX_MANAGED_CONFIG_SYSTEM_PATH)    }    #[cfg(not(unix))]    {        codex_home.join("managed_config.toml")    }}