diff --git a/js/mkdir_test.ts b/js/mkdir_test.ts index ed275bd363..4f82401dcc 100644 --- a/js/mkdir_test.ts +++ b/js/mkdir_test.ts @@ -9,6 +9,15 @@ testPerm({ write: true }, function mkdirSyncSuccess() { assert(pathInfo.isDirectory()); }); +testPerm({ write: true }, function mkdirSyncMode() { + const path = deno.makeTempDirSync() + "/dir/subdir"; + deno.mkdirSync(path, 0o755); // no perm for x + const pathInfo = deno.statSync(path); + if (pathInfo.mode !== null) { // Skip windows + assertEqual(pathInfo.mode & 0o777, 0o755); + } +}); + testPerm({ write: false }, function mkdirSyncPerm() { let err; try { diff --git a/js/stat.ts b/js/stat.ts index 3193794a5d..434841ec2e 100644 --- a/js/stat.ts +++ b/js/stat.ts @@ -51,7 +51,8 @@ export class FileInfo { this.modified = modified ? modified : null; this.accessed = accessed ? accessed : null; this.created = created ? created : null; - this.mode = mode >= 0 ? mode : null; // null if invalid mode (Windows) + // null if invalid mode (Windows) + this.mode = mode >= 0 ? mode & 0o7777 : null; } /** diff --git a/src/deno_dir.rs b/src/deno_dir.rs index a8379b9005..53fbf5ba8b 100644 --- a/src/deno_dir.rs +++ b/src/deno_dir.rs @@ -55,8 +55,8 @@ impl DenoDir { deps, reload, }; - deno_fs::mkdir(deno_dir.gen.as_ref())?; - deno_fs::mkdir(deno_dir.deps.as_ref())?; + deno_fs::mkdir(deno_dir.gen.as_ref(), 0o755)?; + deno_fs::mkdir(deno_dir.deps.as_ref(), 0o755)?; debug!("root {}", deno_dir.root.display()); debug!("gen {}", deno_dir.gen.display()); diff --git a/src/fs.rs b/src/fs.rs index e04675f66d..33323b87bf 100644 --- a/src/fs.rs +++ b/src/fs.rs @@ -1,5 +1,5 @@ use std; -use std::fs::{create_dir, File, OpenOptions}; +use std::fs::{create_dir, DirBuilder, File, OpenOptions}; use std::io::ErrorKind; use std::io::Write; use std::path::{Path, PathBuf}; @@ -7,6 +7,8 @@ use std::path::{Path, PathBuf}; use rand; use rand::Rng; +#[cfg(any(unix))] +use std::os::unix::fs::DirBuilderExt; #[cfg(any(unix))] use std::os::unix::fs::PermissionsExt; @@ -64,18 +66,28 @@ pub fn make_temp_dir( } } -pub fn mkdir(path: &Path) -> std::io::Result<()> { +pub fn mkdir(path: &Path, perm: u32) -> std::io::Result<()> { debug!("mkdir -p {}", path.display()); - assert!(path.has_root(), "non-has_root not yet implemented"); - std::fs::create_dir_all(path).or_else(|err| { - if err.kind() == std::io::ErrorKind::AlreadyExists { - Ok(()) - } else { - Err(err) - } + let mut builder = DirBuilder::new(); + builder.recursive(true); + set_dir_permission(&mut builder, perm); + builder.create(path).or_else(|err| match err.kind() { + std::io::ErrorKind::AlreadyExists => Ok(()), + _ => Err(err), }) } +#[cfg(any(unix))] +fn set_dir_permission(builder: &mut DirBuilder, perm: u32) { + debug!("set dir perm to {}", perm); + builder.mode(perm); +} + +#[cfg(not(any(unix)))] +fn set_dir_permission(_builder: &mut DirBuilder, _perm: u32) { + // NOOP on windows +} + pub fn normalize_path(path: &Path) -> String { let s = String::from(path.to_str().unwrap()); if cfg!(windows) { diff --git a/src/handlers.rs b/src/handlers.rs index 641bfd83c1..0917fd22ab 100644 --- a/src/handlers.rs +++ b/src/handlers.rs @@ -451,7 +451,7 @@ fn handle_make_temp_dir(d: *const DenoC, base: &msg::Base) -> Box { fn handle_mkdir(d: *const DenoC, base: &msg::Base) -> Box { let msg = base.msg_as_mkdir().unwrap(); - // TODO let mode = msg.mode(); + let mode = msg.mode(); let path = msg.path().unwrap(); let deno = from_c(d); if !deno.flags.allow_write { @@ -460,8 +460,7 @@ fn handle_mkdir(d: *const DenoC, base: &msg::Base) -> Box { // TODO Use tokio_threadpool. Box::new(futures::future::result(|| -> OpResult { debug!("handle_mkdir {}", path); - // TODO(ry) Use mode. - deno_fs::mkdir(Path::new(path))?; + deno_fs::mkdir(Path::new(path), mode)?; Ok(None) }())) }