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

Fix wasi-fyi tests #4740

Merged
merged 3 commits into from
May 31, 2024
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
8 changes: 7 additions & 1 deletion lib/wasix/src/syscalls/wasi/path_create_directory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ pub(crate) fn path_create_directory_internal(
}

let mut cur_dir_inode = working_dir.inode;
let mut created_directory = false;
for comp in &path_vec {
let processing_cur_dir_inode = cur_dir_inode.clone();
let mut guard = processing_cur_dir_inode.write();
Expand Down Expand Up @@ -125,6 +126,7 @@ pub(crate) fn path_create_directory_internal(
return Err(Errno::Notdir);
}
} else {
created_directory = true;
state.fs_create_dir(&adjusted_path)?;
}
let kind = Kind::Dir {
Expand Down Expand Up @@ -160,5 +162,9 @@ pub(crate) fn path_create_directory_internal(
}
}

Ok(())
if created_directory {
Ok(())
} else {
Err(Errno::Exist)
}
}
149 changes: 108 additions & 41 deletions lib/wasix/src/syscalls/wasi/path_remove_directory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,58 +47,125 @@ pub(crate) fn path_remove_directory_internal(
path: &str,
) -> Result<(), Errno> {
let env = ctx.data();
let (memory, mut state, inodes) = unsafe { env.get_memory_and_wasi_state_and_inodes(&ctx, 0) };
let (memory, state, inodes) = unsafe { env.get_memory_and_wasi_state_and_inodes(&ctx, 0) };
let working_dir = state.fs.get_fd(fd)?;

let inode = state.fs.get_inode_at_path(inodes, fd, path, false)?;
let (parent_inode, childs_name) =
state
.fs
.get_parent_inode_at_path(inodes, fd, std::path::Path::new(&path), false)?;

let host_path_to_remove = {
let guard = inode.read();
match guard.deref() {
Kind::Dir { entries, path, .. } => {
if !entries.is_empty() || state.fs_read_dir(path)?.count() != 0 {
return Err(Errno::Notempty);
}
path.clone()
}
Kind::Root { .. } => return Err(Errno::Access),
_ => return Err(Errno::Notdir),
}
};
let path = std::path::PathBuf::from(path);
let path_vec = path
.components()
.map(|comp| {
comp.as_os_str()
.to_str()
.map(|inner_str| inner_str.to_string())
.ok_or(Errno::Inval)
})
.collect::<Result<Vec<String>, Errno>>()?;
if path_vec.is_empty() {
trace!("path vector is invalid (its empty)");
return Err(Errno::Inval);
}

{
let mut guard = parent_inode.write();
let (child, parent) = path_vec.split_last().unwrap();

// if path only contains one component (the root), operation is not permitted
if child.is_empty() {
return Err(Errno::Access);
}

let mut cur_dir_inode = working_dir.inode;
for comp in path_vec.iter() {
let processing_cur_dir_inode = cur_dir_inode.clone();
let mut guard = processing_cur_dir_inode.write();
match guard.deref_mut() {
Kind::Dir {
ref mut entries, ..
ref mut entries,
path,
parent,
} => {
let removed_inode = entries.remove(&childs_name).ok_or(Errno::Inval)?;
match comp.borrow() {
".." => {
if let Some(p) = parent.upgrade() {
cur_dir_inode = p;
continue;
}
}
"." => continue,
_ => (),
}
if let Some(child) = entries.get(comp) {
cur_dir_inode = child.clone();
} else {
let parent_path = path.clone();
let mut adjusted_path = path.clone();
drop(guard);

// TODO: double check this doesn't risk breaking the sandbox
adjusted_path.push(comp);
if let Ok(adjusted_path_stat) = path_filestat_get_internal(
&memory,
state,
inodes,
fd,
0,
&adjusted_path.to_string_lossy(),
) {
if adjusted_path_stat.st_filetype != Filetype::Directory {
trace!("path is not a directory");
return Err(Errno::Notdir);
}
} else {
return Err(Errno::Noent);
}
let kind = Kind::Dir {
parent: cur_dir_inode.downgrade(),
path: adjusted_path,
entries: Default::default(),
};
let new_inode = state
.fs
.create_inode(inodes, kind, false, comp.to_string())?;

// TODO: make this a debug assert in the future
assert!(inode.ino() == removed_inode.ino());
// reborrow to insert
{
let mut guard = cur_dir_inode.write();
if let Kind::Dir {
ref mut entries, ..
} = guard.deref_mut()
{
entries.insert(comp.to_string(), new_inode.clone());
}
}
cur_dir_inode = new_inode;
}
}
Kind::Root { .. } => {
trace!("the root node can no create a directory");
return Err(Errno::Access);
}
_ => {
trace!("path is not a directory");
return Err(Errno::Notdir);
}
Kind::Root { .. } => return Err(Errno::Access),
_ => unreachable!(
"Internal logic error in wasi::path_remove_directory, parent is not a directory"
),
}
}

let env = ctx.data();
let (memory, mut state, inodes) = unsafe { env.get_memory_and_wasi_state_and_inodes(&ctx, 0) };
if let Err(err) = state.fs_remove_dir(host_path_to_remove) {
// reinsert to prevent FS from being in bad state
let mut guard = parent_inode.write();
if let Kind::Dir {
ref mut entries, ..
} = guard.deref_mut()
{
entries.insert(childs_name, inode);
if let Kind::Dir {
parent,
path: child_path,
entries,
} = cur_dir_inode.write().deref_mut()
{
let parent = parent.upgrade().ok_or(Errno::Noent)?;

if let Kind::Dir { entries, .. } = parent.write().deref_mut() {
let child_inode = entries.remove(child).ok_or(Errno::Noent)?;

if let Err(e) = state.fs_remove_dir(&child_path) {
tracing::warn!(path = ?child_path, error = ?e, "failed to remove directory");
}
}
return Err(err);

drop(parent)
}

Ok(())
Expand Down
Binary file added tests/integration/cli/resources/php/db/.ht.sqlite
Binary file not shown.
16 changes: 16 additions & 0 deletions tests/integration/cli/resources/php/test.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php
for ($i = 0; $i < 5; $i++) {
$sqlite = new SQLite3('/db/.ht.sqlite');

$result = @$sqlite->query("SELECT name FROM sqlite_master WHERE type='table'");

if ($result) {
$sqlite->close();
} else {
echo "1";
exit(1);
};
}

echo "0"
?>
10 changes: 10 additions & 0 deletions tests/integration/cli/src/fixtures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,16 @@ use std::path::{Path, PathBuf};

use crate::{asset_path, c_asset_path};

pub fn php() -> (PathBuf, PathBuf, PathBuf) {
let root = Path::new(env!("CARGO_MANIFEST_DIR"));
let resources = root.join("resources").join("php");
(
root.join("tests").join("wasm").join("php.wasm"),
resources.clone(),
resources.join("db"),
)
}

/// A WEBC file containing the Python interpreter, compiled to WASI.
pub fn python() -> PathBuf {
c_asset_path().join("python-0.1.0.wasmer")
Expand Down
26 changes: 25 additions & 1 deletion tests/integration/cli/tests/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@ use predicates::str::contains;
use rand::Rng;
use reqwest::{blocking::Client, IntoUrl};
use tempfile::TempDir;
use wasmer_integration_tests_cli::{asset_path, fixtures, get_wasmer_path};
use wasmer_integration_tests_cli::{
asset_path,
fixtures::{self, php},
get_wasmer_path,
};

const HTTP_GET_TIMEOUT: Duration = Duration::from_secs(5);

Expand Down Expand Up @@ -43,6 +47,26 @@ static CACHE_RUST_LOG: Lazy<String> = Lazy::new(|| {
.join(",")
});

#[test]
fn run_php_with_sqlite() {
let (php_wasm, app_dir, db) = php();

let output = Command::new(get_wasmer_path())
.arg("-q")
.arg("run")
.arg(php_wasm)
.arg("--mapdir")
.arg(format!("/db:{}", db.display()))
.arg("--mapdir")
.arg(format!("/app:{}", app_dir.display()))
.arg("--")
.arg("/app/test.php")
.output()
.unwrap();

assert_eq!(output.stdout, "0".as_bytes().to_vec());
}

/// Ignored on Windows because running vendored packages does not work
/// since Windows does not allow `::` characters in filenames (every other OS does)
///
Expand Down
Binary file added tests/integration/cli/tests/wasm/php.wasm
Binary file not shown.
2 changes: 1 addition & 1 deletion tests/wasi-fyi/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ bash build.sh
status=0

# Define skip list as an array
SKIP_LIST=("fs_create_dir-existing-directory.wasm")
SKIP_LIST=()

# List and process .foo files
for file in *.wasm; do
Expand Down
Loading