diff --git a/js/deno.ts b/js/deno.ts
index 21c93c5d3b..869314d2cd 100644
--- a/js/deno.ts
+++ b/js/deno.ts
@@ -4,7 +4,17 @@
///
export { env, exit } from "./os";
export { chdir, cwd } from "./dir";
-export { File, open, stdin, stdout, stderr, read, write, close } from "./files";
+export {
+ File,
+ open,
+ stdin,
+ stdout,
+ stderr,
+ read,
+ write,
+ close,
+ OpenMode
+} from "./files";
export {
copy,
toAsyncIterator,
diff --git a/js/files.ts b/js/files.ts
index 4392eadf7b..e23d19cfe5 100644
--- a/js/files.ts
+++ b/js/files.ts
@@ -29,7 +29,7 @@ export const stdout = new File(1);
/** An instance of `File` for stderr. */
export const stderr = new File(2);
-type OpenMode =
+export type OpenMode =
/** Read-only. Default. Starts at beginning of file. */
| "r"
/** Read-write. Start at beginning of file. */
diff --git a/js/files_test.ts b/js/files_test.ts
index d46a469060..03ad7a7cd8 100644
--- a/js/files_test.ts
+++ b/js/files_test.ts
@@ -30,10 +30,26 @@ test(async function filesToAsyncIterator() {
assertEqual(totalSize, 12);
});
+testPerm({ write: false }, async function writePermFailure() {
+ const filename = "tests/hello.txt";
+ const writeModes: deno.OpenMode[] = ["r+", "w", "w+", "a", "a+", "x", "x+"];
+ for (const mode of writeModes) {
+ let err;
+ try {
+ await deno.open(filename, mode);
+ } catch (e) {
+ err = e;
+ }
+ assert(!!err);
+ assertEqual(err.kind, deno.ErrorKind.PermissionDenied);
+ assertEqual(err.name, "PermissionDenied");
+ }
+});
+
testPerm({ write: true }, async function createFile() {
const tempDir = await deno.makeTempDir();
const filename = tempDir + "/test.txt";
- let f = await deno.open(filename, "w");
+ const f = await deno.open(filename, "w");
let fileInfo = deno.statSync(filename);
assert(fileInfo.isFile());
assert(fileInfo.len === 0);
@@ -88,7 +104,7 @@ testPerm({ write: true }, async function openModeWriteRead() {
const filename = tempDir + "hello.txt";
const data = encoder.encode("Hello world!\n");
- let file = await deno.open(filename, "w+");
+ const file = await deno.open(filename, "w+");
// assert file was created
let fileInfo = deno.statSync(filename);
assert(fileInfo.isFile());
diff --git a/src/ops.rs b/src/ops.rs
index 3cf466d0d5..3dc457aa64 100644
--- a/src/ops.rs
+++ b/src/ops.rs
@@ -576,15 +576,15 @@ fn op_chmod(
}
fn op_open(
- _state: &IsolateState,
+ state: &IsolateState,
base: &msg::Base,
data: libdeno::deno_buf,
) -> Box {
assert_eq!(data.len(), 0);
let cmd_id = base.cmd_id();
let inner = base.inner_as_open().unwrap();
- let filename = PathBuf::from(inner.filename().unwrap());
- // let perm = inner.perm();
+ let filename_str = inner.filename().unwrap();
+ let filename = PathBuf::from(&filename_str);
let mode = inner.mode().unwrap();
let mut open_options = tokio::fs::OpenOptions::new();
@@ -594,12 +594,21 @@ fn op_open(
open_options.read(true);
}
"r+" => {
+ if let Err(e) = state.check_write(&filename_str) {
+ return odd_future(e);
+ }
open_options.read(true).write(true);
}
"w" => {
+ if let Err(e) = state.check_write(&filename_str) {
+ return odd_future(e);
+ }
open_options.create(true).write(true).truncate(true);
}
"w+" => {
+ if let Err(e) = state.check_write(&filename_str) {
+ return odd_future(e);
+ }
open_options
.read(true)
.create(true)
@@ -607,15 +616,27 @@ fn op_open(
.truncate(true);
}
"a" => {
+ if let Err(e) = state.check_write(&filename_str) {
+ return odd_future(e);
+ }
open_options.create(true).append(true);
}
"a+" => {
+ if let Err(e) = state.check_write(&filename_str) {
+ return odd_future(e);
+ }
open_options.read(true).create(true).append(true);
}
"x" => {
+ if let Err(e) = state.check_write(&filename_str) {
+ return odd_future(e);
+ }
open_options.create_new(true).write(true);
}
"x+" => {
+ if let Err(e) = state.check_write(&filename_str) {
+ return odd_future(e);
+ }
open_options.create_new(true).read(true).write(true);
}
&_ => {