Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

implement wasi::path_rename #650

Merged
merged 1 commit into from
Aug 9, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Blocks of changes will separated by version increments.

Special thanks to @YaronWittenstein @penberg for their contributions.

- [#650](https://github.com/wasmerio/wasmer/issues/650) Implement `wasi::path_rename`, improve WASI FS public api, and allow open files to exist even when the underlying file is deleted
- [#643](https://github.com/wasmerio/wasmer/issues/643) Implement `wasi::path_symlink` and improve WASI FS public api IO error reporting
- [#608](https://github.com/wasmerio/wasmer/issues/608) Implement wasi syscalls `fd_allocate`, `fd_sync`, `fd_pread`, `path_link`, `path_filestat_set_times`; update WASI fs API in a WIP way; reduce coupling of WASI code to host filesystem; make debug messages from WASI more readable; improve rights-checking when calling syscalls; implement reference counting on inodes; misc bug fixes and improvements
- [#616](https://github.com/wasmerio/wasmer/issues/616) Create the import object separately from instance instantiation in `runtime-c-api`
Expand Down
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ generate-spectests:
generate-emtests:
WASM_EMSCRIPTEN_GENERATE_EMTESTS=1 cargo build -p wasmer-emscripten-tests --release

generate-wasitests:
generate-wasitests: wasitests-setup
WASM_WASI_GENERATE_WASITESTS=1 cargo build -p wasmer-wasi-tests --release -vv \
&& echo "formatting" \
&& cargo fmt
Expand Down
1 change: 1 addition & 0 deletions lib/wasi-tests/tests/wasitests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ mod fseek;
mod hello;
mod mapdir;
mod path_link;
mod path_rename;
mod path_symlink;
mod quine;
mod readlink;
Expand Down
14 changes: 14 additions & 0 deletions lib/wasi-tests/tests/wasitests/path_rename.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#[test]
fn test_path_rename() {
assert_wasi_output!(
"../../wasitests/path_rename.wasm",
"path_rename",
vec![],
vec![(
"temp".to_string(),
::std::path::PathBuf::from("wasitests/test_fs/temp")
),],
vec![],
"../../wasitests/path_rename.out"
);
}
2 changes: 2 additions & 0 deletions lib/wasi-tests/wasitests/path_rename.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
The original file does not still exist!
柴犬
56 changes: 56 additions & 0 deletions lib/wasi-tests/wasitests/path_rename.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// Args:
// mapdir: temp:wasitests/test_fs/temp

use std::fs;
use std::io::{Read, Write};
use std::path::PathBuf;

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

let file_to_create = base.join("temp/path_rename_file.txt");
let file_to_rename_to = base.join("temp/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つの説が代表的。";
let shiba_bytes: Vec<u8> = shiba_string.bytes().collect();
f.write_all(&shiba_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!");
}

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();
}
Binary file added lib/wasi-tests/wasitests/path_rename.wasm
Binary file not shown.
6 changes: 6 additions & 0 deletions lib/wasi/src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,9 @@ macro_rules! wasi_try {
wasi_try!(opt.ok_or($e))
}};
}

macro_rules! get_input_str {
($memory:expr, $data:expr, $len:expr) => {{
wasi_try!($data.get_utf8_string($memory, $len), __WASI_EINVAL)
}};
}
19 changes: 16 additions & 3 deletions lib/wasi/src/state/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ pub enum Kind {
},
}

#[derive(Clone, Debug)]
#[derive(Debug)]
pub struct Fd {
pub rights: __wasi_rights_t,
pub rights_inheriting: __wasi_rights_t,
Expand All @@ -126,6 +126,8 @@ pub struct WasiFs {
pub fd_map: HashMap<u32, Fd>,
pub next_fd: Cell<u32>,
inode_counter: Cell<u64>,
/// for fds still open after the file has been deleted
pub orphan_fds: HashMap<Inode, InodeVal>,

pub stdout: Box<dyn WasiFile>,
pub stderr: Box<dyn WasiFile>,
Expand All @@ -146,6 +148,7 @@ impl WasiFs {
fd_map: HashMap::new(),
next_fd: Cell::new(3),
inode_counter: Cell::new(1024),
orphan_fds: HashMap::new(),

stdin: Box::new(Stdin(io::stdin())),
stdout: Box::new(Stdout(io::stdout())),
Expand Down Expand Up @@ -683,6 +686,16 @@ impl WasiFs {
self.fd_map.get(&fd).ok_or(__WASI_EBADF)
}

/// gets either a normal inode or an orphaned inode
pub fn get_inodeval_mut(&mut self, fd: __wasi_fd_t) -> Result<&mut InodeVal, __wasi_errno_t> {
let inode = self.get_fd(fd)?.inode;
if let Some(iv) = self.inodes.get_mut(inode) {
Ok(iv)
} else {
self.orphan_fds.get_mut(&inode).ok_or(__WASI_EBADF)
}
}

pub fn filestat_fd(&self, fd: __wasi_fd_t) -> Result<__wasi_filestat_t, __wasi_errno_t> {
let fd = self.get_fd(fd)?;

Expand Down Expand Up @@ -818,8 +831,8 @@ impl WasiFs {
/// all refences to the given inode have been removed from the filesystem
///
/// returns true if the inode existed and was removed
pub unsafe fn remove_inode(&mut self, inode: Inode) -> bool {
self.inodes.remove(inode).is_some()
pub unsafe fn remove_inode(&mut self, inode: Inode) -> Option<InodeVal> {
self.inodes.remove(inode)
}

fn create_virtual_root(&mut self) -> Inode {
Expand Down
11 changes: 11 additions & 0 deletions lib/wasi/src/state/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,13 @@ pub trait WasiFile: std::fmt::Debug + Write + Read + Seek {
fn sync_to_disk(&self) -> Result<(), WasiFsError> {
panic!("Default implementation for compatibilty in the 0.6.X releases; this will be removed in 0.7.0. Please implement WasiFile::sync_to_disk for your type before then");
}

/// Moves the file to a new location
/// NOTE: the signature of this function will change before stabilization
// TODO: stablizie this in 0.7.0 or 0.8.0 by removing default impl
fn rename_file(&self, _new_name: &std::path::Path) -> Result<(), WasiFsError> {
panic!("Default implementation for compatibilty in the 0.6.X releases; this will be removed in 0.7.0 or 0.8.0. Please implement WasiFile::rename_file for your type before then");
}
}

pub trait WasiPath {}
Expand Down Expand Up @@ -271,6 +278,10 @@ impl WasiFile for HostFile {
fn sync_to_disk(&self) -> Result<(), WasiFsError> {
self.inner.sync_all().map_err(Into::into)
}

fn rename_file(&self, new_name: &std::path::Path) -> Result<(), WasiFsError> {
std::fs::rename(&self.host_path, new_name).map_err(Into::into)
}
}

impl From<io::Error> for WasiFsError {
Expand Down
Loading