summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordubiousjim <dubiousjim@gmail.com>2020-03-10 15:11:27 -0400
committerGitHub <noreply@github.com>2020-03-10 15:11:27 -0400
commit8078d976d29aa12819e3f5a781c846d67868b0d6 (patch)
tree3ec7786dd9b7e787c27f58e2041110e6fca86e2b
parent6443e4aed16868c17111a56634aa733211430f46 (diff)
Add Deno.umask (#4290)
-rw-r--r--cli/js/deno.ts1
-rw-r--r--cli/js/lib.deno.ns.d.ts8
-rw-r--r--cli/js/ops/fs/umask.ts12
-rw-r--r--cli/js/tests/umask_test.ts16
-rw-r--r--cli/js/tests/unit_tests.ts1
-rw-r--r--cli/op_error.rs4
-rw-r--r--cli/ops/fs.rs38
7 files changed, 80 insertions, 0 deletions
diff --git a/cli/js/deno.ts b/cli/js/deno.ts
index 23fcfda5d..f0115f261 100644
--- a/cli/js/deno.ts
+++ b/cli/js/deno.ts
@@ -113,6 +113,7 @@ export { symlinkSync, symlink } from "./ops/fs/symlink.ts";
export { connectTLS, listenTLS } from "./tls.ts";
export { truncateSync, truncate } from "./ops/fs/truncate.ts";
export { isatty, setRaw } from "./ops/tty.ts";
+export { umask } from "./ops/fs/umask.ts";
export { utimeSync, utime } from "./ops/fs/utime.ts";
export { version } from "./version.ts";
export { writeFileSync, writeFile, WriteFileOptions } from "./write_file.ts";
diff --git a/cli/js/lib.deno.ns.d.ts b/cli/js/lib.deno.ns.d.ts
index 8eb2e1f4d..6950d9050 100644
--- a/cli/js/lib.deno.ns.d.ts
+++ b/cli/js/lib.deno.ns.d.ts
@@ -287,6 +287,14 @@ declare namespace Deno {
*/
export function chdir(directory: string): void;
+ /**
+ * **UNSTABLE**: New API. Maybe needs permissions.
+ *
+ * If `mask` is provided, sets the process umask. Always returns what the umask
+ * was before the call.
+ */
+ export function umask(mask?: number): number;
+
/** **UNSTABLE**: might move to `Deno.symbols`. */
export const EOF: unique symbol;
export type EOF = typeof EOF;
diff --git a/cli/js/ops/fs/umask.ts b/cli/js/ops/fs/umask.ts
new file mode 100644
index 000000000..ee56fecb5
--- /dev/null
+++ b/cli/js/ops/fs/umask.ts
@@ -0,0 +1,12 @@
+// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
+import { sendSync } from "../dispatch_json.ts";
+
+/**
+ * **UNSTABLE**: maybe needs `allow-env` permissions.
+ *
+ * If `mask` is provided, sets the process umask. Always returns what the umask
+ * was before the call.
+ */
+export function umask(mask?: number): number {
+ return sendSync("op_umask", { mask });
+}
diff --git a/cli/js/tests/umask_test.ts b/cli/js/tests/umask_test.ts
new file mode 100644
index 000000000..543372a46
--- /dev/null
+++ b/cli/js/tests/umask_test.ts
@@ -0,0 +1,16 @@
+// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
+import { unitTest, assertEquals } from "./test_util.ts";
+
+unitTest(
+ {
+ skip: Deno.build.os === "win"
+ },
+ function umaskSuccess(): void {
+ const prevMask = Deno.umask(0o020);
+ const newMask = Deno.umask(prevMask);
+ const finalMask = Deno.umask();
+ assertEquals(newMask, 0o020);
+ assertEquals(finalMask, prevMask);
+ assertEquals(prevMask, 0o022);
+ }
+);
diff --git a/cli/js/tests/unit_tests.ts b/cli/js/tests/unit_tests.ts
index cc51e6ade..9ae724d53 100644
--- a/cli/js/tests/unit_tests.ts
+++ b/cli/js/tests/unit_tests.ts
@@ -57,6 +57,7 @@ import "./timers_test.ts";
import "./tls_test.ts";
import "./truncate_test.ts";
import "./tty_test.ts";
+import "./umask_test.ts";
import "./url_test.ts";
import "./url_search_params_test.ts";
import "./utime_test.ts";
diff --git a/cli/op_error.rs b/cli/op_error.rs
index a2cf03a66..bebfd2e72 100644
--- a/cli/op_error.rs
+++ b/cli/op_error.rs
@@ -71,6 +71,10 @@ impl OpError {
Self::new(ErrorKind::NotFound, msg)
}
+ pub fn not_implemented() -> Self {
+ Self::other("not implemented".to_string())
+ }
+
pub fn other(msg: String) -> Self {
Self::new(ErrorKind::Other, msg)
}
diff --git a/cli/ops/fs.rs b/cli/ops/fs.rs
index ad1283c12..df5ad7bef 100644
--- a/cli/ops/fs.rs
+++ b/cli/ops/fs.rs
@@ -23,6 +23,7 @@ use std::os::unix::fs::{MetadataExt, PermissionsExt};
pub fn init(i: &mut Isolate, s: &State) {
i.register_op("op_open", s.stateful_json_op(op_open));
i.register_op("op_seek", s.stateful_json_op(op_seek));
+ i.register_op("op_umask", s.stateful_json_op(op_umask));
i.register_op("op_chdir", s.stateful_json_op(op_chdir));
i.register_op("op_mkdir", s.stateful_json_op(op_mkdir));
i.register_op("op_chmod", s.stateful_json_op(op_chmod));
@@ -222,6 +223,43 @@ fn op_seek(
}
#[derive(Deserialize)]
+struct UmaskArgs {
+ mask: Option<u32>,
+}
+
+fn op_umask(
+ _state: &State,
+ args: Value,
+ _zero_copy: Option<ZeroCopyBuf>,
+) -> Result<JsonOp, OpError> {
+ let args: UmaskArgs = serde_json::from_value(args)?;
+ // TODO implement umask for Windows
+ // see https://github.com/nodejs/node/blob/master/src/node_process_methods.cc
+ // and https://docs.microsoft.com/fr-fr/cpp/c-runtime-library/reference/umask?view=vs-2019
+ #[cfg(not(unix))]
+ {
+ let _ = args.mask; // avoid unused warning.
+ return Err(OpError::not_implemented());
+ }
+ #[cfg(unix)]
+ {
+ use nix::sys::stat::mode_t;
+ use nix::sys::stat::umask;
+ use nix::sys::stat::Mode;
+ let r = if let Some(mask) = args.mask {
+ // If mask provided, return previous.
+ umask(Mode::from_bits_truncate(mask as mode_t))
+ } else {
+ // If no mask provided, we query the current. Requires two syscalls.
+ let prev = umask(Mode::from_bits_truncate(0o777));
+ let _ = umask(prev);
+ prev
+ };
+ Ok(JsonOp::Sync(json!(r.bits() as u32)))
+ }
+}
+
+#[derive(Deserialize)]
struct ChdirArgs {
directory: String,
}