Skip to content

Commit

Permalink
Merge pull request #3230 from wasmerio/fix_wasi_path_rename
Browse files Browse the repository at this point in the history
Remove test if dest file exist on path_rename wasi syscall (for #3228)
  • Loading branch information
syrusakbary authored Oct 18, 2022
2 parents 3670b2e + 42afe0a commit 497cedf
Show file tree
Hide file tree
Showing 31 changed files with 118 additions and 19 deletions.
19 changes: 18 additions & 1 deletion lib/vfs/src/mem_fs/filesystem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,11 @@ impl crate::FileSystem for FileSystem {
}

fn rename(&self, from: &Path, to: &Path) -> Result<()> {
let ((position_of_from, inode, inode_of_from_parent), (inode_of_to_parent, name_of_to)) = {
let (
(position_of_from, inode, inode_of_from_parent),
(inode_of_to_parent, name_of_to),
inode_dest,
) = {
// Read lock.
let fs = self.inner.try_read().map_err(|_| FsError::Lock)?;

Expand All @@ -180,6 +184,10 @@ impl crate::FileSystem for FileSystem {
let inode_of_from_parent = fs.inode_of_parent(parent_of_from)?;
let inode_of_to_parent = fs.inode_of_parent(parent_of_to)?;

// Find the inode of the dest file if it exists
let maybe_position_and_inode_of_file =
fs.as_parent_get_position_and_inode_of_file(inode_of_to_parent, &name_of_to)?;

// Get the child indexes to update in the parent nodes, in
// addition to the inode of the directory to update.
let (position_of_from, inode) = fs
Expand All @@ -189,13 +197,22 @@ impl crate::FileSystem for FileSystem {
(
(position_of_from, inode, inode_of_from_parent),
(inode_of_to_parent, name_of_to),
maybe_position_and_inode_of_file,
)
};

{
// Write lock.
let mut fs = self.inner.try_write().map_err(|_| FsError::Lock)?;

if let Some((position, inode_of_file)) = inode_dest {
// Remove the file from the storage.
fs.storage.remove(inode_of_file);

// Remove the child from the parent directory.
fs.remove_child_from_node(inode_of_to_parent, position)?;
}

// Update the file name, and update the modified time.
fs.update_node_name(inode, name_of_to)?;

Expand Down
35 changes: 18 additions & 17 deletions lib/wasi/src/syscalls/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2659,18 +2659,13 @@ pub fn path_rename<M: MemorySize>(
source_path.to_str().as_ref().unwrap(),
true
));
if state
.fs
.get_inode_at_path(
inodes.deref_mut(),
new_fd,
target_path.to_str().as_ref().unwrap(),
true,
)
.is_ok()
{
return Errno::Exist;
}
// Create the destination inode if the file exists.
let _ = state.fs.get_inode_at_path(
inodes.deref_mut(),
new_fd,
target_path.to_str().as_ref().unwrap(),
true,
);
let (source_parent_inode, source_entry_name) =
wasi_try!(state
.fs
Expand All @@ -2679,13 +2674,14 @@ pub fn path_rename<M: MemorySize>(
wasi_try!(state
.fs
.get_parent_inode_at_path(inodes.deref_mut(), new_fd, target_path, true));
let mut need_create = true;
let host_adjusted_target_path = {
let guard = inodes.arena[target_parent_inode].read();
let deref = guard.deref();
match deref {
Kind::Dir { entries, path, .. } => {
if entries.contains_key(&target_entry_name) {
return Errno::Exist;
need_create = false;
}
let mut out_path = path.clone();
out_path.push(std::path::Path::new(&target_entry_name));
Expand Down Expand Up @@ -2778,7 +2774,7 @@ pub fn path_rename<M: MemorySize>(
}
}

{
if need_create {
let mut guard = inodes.arena[target_parent_inode].write();
if let Kind::Dir { entries, .. } = guard.deref_mut() {
let result = entries.insert(target_entry_name, source_entry);
Expand Down Expand Up @@ -2829,10 +2825,15 @@ pub fn path_symlink<M: MemorySize>(
wasi_try!(state
.fs
.get_parent_inode_at_path(inodes.deref_mut(), fd, old_path_path, true));
let depth = wasi_try!(state
let depth = state
.fs
.path_depth_from_fd(inodes.deref(), fd, source_inode))
- 1;
.path_depth_from_fd(inodes.deref(), fd, source_inode);

// depth == -1 means folder is not relative. See issue #3233.
let depth = match depth {
Ok(depth) => depth as i32 - 1,
Err(_) => -1,
};

let new_path_path = std::path::Path::new(&new_path_str);
let (target_parent_inode, entry_name) =
Expand Down
Binary file modified tests/wasi-wast/wasi/snapshot1/close_preopen_fd.wasm
Binary file not shown.
Binary file modified tests/wasi-wast/wasi/snapshot1/create_dir.wasm
Binary file not shown.
Binary file modified tests/wasi-wast/wasi/snapshot1/envvar.wasm
Binary file not shown.
Binary file modified tests/wasi-wast/wasi/snapshot1/fd_allocate.wasm
Binary file not shown.
Binary file modified tests/wasi-wast/wasi/snapshot1/fd_append.wasm
Binary file not shown.
Binary file modified tests/wasi-wast/wasi/snapshot1/fd_close.wasm
Binary file not shown.
Binary file modified tests/wasi-wast/wasi/snapshot1/fd_pread.wasm
Binary file not shown.
Binary file modified tests/wasi-wast/wasi/snapshot1/fd_read.wasm
Binary file not shown.
Binary file modified tests/wasi-wast/wasi/snapshot1/fd_rename_path.wasm
Binary file not shown.
Binary file modified tests/wasi-wast/wasi/snapshot1/fd_sync.wasm
Binary file not shown.
Binary file modified tests/wasi-wast/wasi/snapshot1/file_metadata.wasm
Binary file not shown.
Binary file modified tests/wasi-wast/wasi/snapshot1/fs_sandbox_test.wasm
Binary file not shown.
Binary file modified tests/wasi-wast/wasi/snapshot1/fseek.wasm
Binary file not shown.
Binary file modified tests/wasi-wast/wasi/snapshot1/hello.wasm
Binary file not shown.
Binary file modified tests/wasi-wast/wasi/snapshot1/isatty.wasm
Binary file not shown.
Binary file modified tests/wasi-wast/wasi/snapshot1/mapdir.wasm
Binary file not shown.
Binary file modified tests/wasi-wast/wasi/snapshot1/mapdir_with_leading_slash.wasm
100644 → 100755
Binary file not shown.
Binary file modified tests/wasi-wast/wasi/snapshot1/path_link.wasm
Binary file not shown.
Binary file modified tests/wasi-wast/wasi/snapshot1/path_rename.wasm
Binary file not shown.
2 changes: 1 addition & 1 deletion tests/wasi-wast/wasi/snapshot1/path_rename.wast
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
(wasi_test "path_rename.wasm"
(temp_dirs "temp")
(assert_return (i64.const 0))
(assert_stdout "The original file does not still exist!\nFound item: path_renamed_file.txt\n柴犬\nrun_with_sub_dir: The original file does not still exist!\nrun_with_different_sub_dirs: The original file does not still exist!\n")
(assert_stdout "The original file does not still exist!\nFound item: path_renamed_file.txt\n柴犬\nThe original file does not still exist!\nFound item: path_renamed_file.txt\n柴犬\nrun_with_sub_dir: The original file does not still exist!\nrun_with_different_sub_dirs: The original file does not still exist!\n")
)
Binary file modified tests/wasi-wast/wasi/snapshot1/path_symlink.wasm
Binary file not shown.
Binary file modified tests/wasi-wast/wasi/snapshot1/pipe_reverse.wasm
Binary file not shown.
Binary file modified tests/wasi-wast/wasi/snapshot1/poll_oneoff.wasm
Binary file not shown.
Binary file modified tests/wasi-wast/wasi/snapshot1/quine.wasm
Binary file not shown.
Binary file modified tests/wasi-wast/wasi/snapshot1/readlink.wasm
Binary file not shown.
Binary file modified tests/wasi-wast/wasi/snapshot1/unix_open_special_files.wasm
Binary file not shown.
Binary file modified tests/wasi-wast/wasi/snapshot1/wasi_sees_virtual_root.wasm
Binary file not shown.
Binary file modified tests/wasi-wast/wasi/snapshot1/writing.wasm
Binary file not shown.
81 changes: 81 additions & 0 deletions tests/wasi-wast/wasi/tests/path_rename.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,86 @@ fn run_with_toplevel_dir() {
std::fs::remove_file(file_to_rename_to).unwrap();
}

fn run_with_toplevel_dir_overwrite() {
#[cfg(not(target_os = "wasi"))]
let mut base = PathBuf::from("test_fs");
#[cfg(target_os = "wasi")]
let mut base = PathBuf::from("temp");

let file_to_create = base.join("path_rename_file.txt");
let file_to_rename_to = base.join("path_renamed_file.txt");

{
let mut f = std::fs::OpenOptions::new()
.create_new(true)
.write(true)
.open(&file_to_create)
.unwrap();

// text from https://ja.wikipedia.org/wiki/柴犬
let shiba_string = "「柴犬」という名前は中央高地で使われていたもので、文献上では、昭和初期の日本犬保存会の会誌「日本犬」で用いられている。一般的には、「柴」は小ぶりな雑木を指す。
由来には諸説があり、
柴藪を巧みにくぐり抜けて猟を助けることから
赤褐色の毛色が枯れ柴に似ている(柴赤)ことから
小さなものを表す古語の「柴」から
の3つの説が代表的。";
f.write_all(shiba_string.as_bytes()).unwrap();
}

{
let mut f = std::fs::OpenOptions::new()
.create_new(true)
.write(true)
.open(&file_to_rename_to)
.unwrap();

let lorem_string = "lorem ispum";
f.write_all(lorem_string.as_bytes()).unwrap();
}

std::fs::rename(&file_to_create, &file_to_rename_to).unwrap();
let mut file = fs::File::open(&file_to_rename_to).expect("Could not open file");
if file_to_create.exists() {
println!("The original file still exists!");
return;
} else {
println!("The original file does not still exist!");
}


if !file_to_rename_to.exists() {
println!("The moved file does not exist!");
return;
}

// TODO: add temp directory suport for native execution...
// until then, don't actually inspect the directory when running native code.
#[cfg(target_os = "wasi")]
for item in fs::read_dir(&base).unwrap() {
println!(
"Found item: {}",
item.unwrap().path().file_name().unwrap().to_str().unwrap()
);
}
#[cfg(not(target_os = "wasi"))]
{
println!("Found item: path_renamed_file.txt");
}

let mut out_str = String::new();
file.read_to_string(&mut out_str).unwrap();
let mut test_str = String::new();
let mut out_chars = out_str.chars();
out_chars.next().unwrap();
test_str.push(out_chars.next().unwrap());
test_str.push(out_chars.next().unwrap());

println!("{}", test_str);
std::fs::remove_file(file_to_rename_to).unwrap();
}

fn run_with_sub_dir() {
#[cfg(not(target_os = "wasi"))]
let base = PathBuf::from("test_fs");
Expand Down Expand Up @@ -162,6 +242,7 @@ fn run_with_different_sub_dirs() {

fn main() {
run_with_toplevel_dir();
run_with_toplevel_dir_overwrite();
run_with_sub_dir();
run_with_different_sub_dirs();
}

0 comments on commit 497cedf

Please sign in to comment.