summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cli/tests/unit/copy_file_test.ts27
-rw-r--r--runtime/ops/fs.rs21
2 files changed, 46 insertions, 2 deletions
diff --git a/cli/tests/unit/copy_file_test.ts b/cli/tests/unit/copy_file_test.ts
index c53f2601b..5e77b0dca 100644
--- a/cli/tests/unit/copy_file_test.ts
+++ b/cli/tests/unit/copy_file_test.ts
@@ -209,3 +209,30 @@ Deno.test(
}, Deno.errors.PermissionDenied);
},
);
+
+function copyFileSyncMode(content: string): void {
+ const tempDir = Deno.makeTempDirSync();
+ const fromFilename = tempDir + "/from.txt";
+ const toFilename = tempDir + "/to.txt";
+ Deno.writeTextFileSync(fromFilename, content);
+ Deno.chmodSync(fromFilename, 0o100755);
+
+ Deno.copyFileSync(fromFilename, toFilename);
+ const toStat = Deno.statSync(toFilename);
+ assertEquals(toStat.mode!, 0o100755);
+}
+
+Deno.test(
+ {
+ ignore: Deno.build.os === "windows",
+ permissions: { read: true, write: true },
+ },
+ function copyFileSyncChmod() {
+ // this Tests different optimization paths on MacOS:
+ //
+ // < 128 KB clonefile() w/ fallback to copyfile()
+ // > 128 KB
+ copyFileSyncMode("Hello world!");
+ copyFileSyncMode("Hello world!".repeat(128 * 1024));
+ },
+);
diff --git a/runtime/ops/fs.rs b/runtime/ops/fs.rs
index fe263d944..2f62e143b 100644
--- a/runtime/ops/fs.rs
+++ b/runtime/ops/fs.rs
@@ -881,6 +881,8 @@ fn op_copy_file_sync(
use libc::unlink;
use std::ffi::CString;
use std::io::Read;
+ use std::os::unix::fs::OpenOptionsExt;
+ use std::os::unix::fs::PermissionsExt;
let from = CString::new(from).unwrap();
let to = CString::new(to).unwrap();
@@ -909,8 +911,23 @@ fn op_copy_file_sync(
let mut buf = [0u8; 128 * 1024];
let mut from_file =
std::fs::File::open(&from_path).map_err(err_mapper)?;
- let mut to_file =
- std::fs::File::create(&to_path).map_err(err_mapper)?;
+ let perm = from_file.metadata().map_err(err_mapper)?.permissions();
+
+ let mut to_file = std::fs::OpenOptions::new()
+ // create the file with the correct mode right away
+ .mode(perm.mode())
+ .write(true)
+ .create(true)
+ .truncate(true)
+ .open(&to_path)
+ .map_err(err_mapper)?;
+ let writer_metadata = to_file.metadata()?;
+ if writer_metadata.is_file() {
+ // Set the correct file permissions, in case the file already existed.
+ // Don't set the permissions on already existing non-files like
+ // pipes/FIFOs or device nodes.
+ to_file.set_permissions(perm)?;
+ }
loop {
let nread = from_file.read(&mut buf).map_err(err_mapper)?;
if nread == 0 {