diff --git a/src/path.rs b/src/path.rs index c8ad89458..b9185680f 100644 --- a/src/path.rs +++ b/src/path.rs @@ -667,7 +667,7 @@ fn make_base_directory(xdg_var: &wstr, non_xdg_homepath: &wstr) -> BaseDirectory let mut remoteness = DirRemoteness::unknown; if path.is_empty() { err = ENOENT; - } else if let Err(io_error) = std::fs::create_dir_all(wcs2osstring(&path)) { + } else if let Err(io_error) = create_dir_all_with_mode(wcs2osstring(&path), 0o700) { err = io_error.raw_os_error().unwrap_or_default(); } else { err = 0; @@ -685,6 +685,15 @@ fn make_base_directory(xdg_var: &wstr, non_xdg_homepath: &wstr) -> BaseDirectory } } +// Like std::fs::create_dir_all, but new directories are created using the given mode (e.g. 0o700). +fn create_dir_all_with_mode>(path: P, mode: u32) -> std::io::Result<()> { + use std::os::unix::fs::DirBuilderExt; + std::fs::DirBuilder::new() + .recursive(true) + .mode(mode) + .create(path.as_ref()) +} + /// Return whether the given path is on a remote filesystem. fn path_remoteness(path: &wstr) -> DirRemoteness { let narrow = wcs2zstring(path); diff --git a/tests/checks/create-base-directories.fish b/tests/checks/create-base-directories.fish new file mode 100644 index 000000000..1dc97891d --- /dev/null +++ b/tests/checks/create-base-directories.fish @@ -0,0 +1,16 @@ +#RUN: %fish -C 'set -l fish %fish' %s + +# Set a XDG_CONFIG_HOME with both pre-existing and non-existing directories. +set -l dir (mktemp -d) +mkdir -m 0755 $dir/old +set -gx XDG_CONFIG_HOME $dir/old/new + +# Launch fish so it will create all missing directories. +$fish -c '' + +# Check that existing directories kept their permissions, and new directories +# have the right permissions according to the XDG Base Directory Specification. +ls -ld $dir/old $dir/old/new $dir/old/new/fish | awk '{print $1}' +# CHECK: drwxr-xr-x +# CHECK: drwx------ +# CHECK: drwx------