bless_plugins/wasi/
mod.rs

1use anyhow::{anyhow, bail, Result};
2use javy_plugin_api::javy::{
3    quickjs::{Ctx, Object as JObject, Value},
4    Args,
5};
6
7#[macro_use]
8mod macros;
9mod close;
10mod descriptor;
11mod error;
12mod link;
13mod mkdir;
14mod open;
15mod preview_1;
16mod rename;
17mod rmdir;
18mod stat;
19mod symlink;
20mod unlink;
21pub(crate) use close::wasi_preview1_close;
22pub use error::WasiError;
23pub(crate) use link::wasi_preview1_path_link;
24pub(crate) use mkdir::wasi_preview1_path_create_directory;
25pub(crate) use open::wasi_preview1_open;
26pub(crate) use rename::wasi_preview1_path_rename;
27pub(crate) use rmdir::wasi_preview1_path_remove_directory;
28pub(crate) use stat::wasi_preview1_path_filestat_get;
29pub(crate) use symlink::wasi_preview1_path_symlink;
30pub(crate) use unlink::wasi_preview1_path_unlink_file;
31
32#[inline]
33pub fn process_error(ctx: Ctx<'_>, rs: i32) -> Result<()> {
34    let obj = JObject::new(ctx.clone())?;
35    let error_messgae = if rs != 0 {
36        let error: WasiError = rs.into();
37        error.to_string()
38    } else {
39        "Success".to_string()
40    };
41    obj.set("errno", rs)?;
42    obj.set("error", error_messgae)?;
43    ctx.globals().set("lastErr", obj)?;
44    Ok(())
45}
46
47/// This function is used to get the directory name of a file descriptor.
48/// It is used to get the directory name of a file descriptor.
49/// The file descriptor must be a directory.
50pub fn wasi_preview1_fd_prestat_dir_name(args: Args<'_>) -> Result<Value<'_>> {
51    let (cx, args) = args.release();
52    let args_pat: &[Value<'_>] = &args.0;
53    let [fd, ..] = args_pat else {
54        bail!(
55            "fd_prestat_dir_name expects 1 parameters: the fd, path_ptr and path_len, Got: {} parameters.",
56            args.len()
57        );
58    };
59    let mut path_len_buf = [0u8; 8];
60    let fd = fd.as_int().ok_or_else(|| anyhow!("fd must be a number"))?;
61    let path_len_ptr: i32 = path_len_buf.as_mut_ptr() as i32;
62    let rs = unsafe { preview_1::fd_prestat_get(fd, path_len_ptr) };
63    let path_len_buf: [u8; 4] = path_len_buf[4..].try_into()?;
64    let path_len = i32::from_le_bytes(path_len_buf);
65    let obj = JObject::new(cx.clone())?;
66    if rs != 0 {
67        process_error(cx.clone(), rs)?;
68        return Ok(Value::from_object(obj));
69    }
70    let mut path_buf = vec![0u8; path_len as usize];
71    let rs = unsafe {
72        preview_1::fd_prestat_dir_name(
73            fd,
74            path_buf.as_mut_ptr() as *const i32 as i32,
75            path_len as _,
76        )
77    };
78    if rs == 0 {
79        let path = String::from_utf8(path_buf)?;
80        obj.set("dir_name", path)?;
81    }
82    obj.set("code", rs)?;
83    process_error(cx.clone(), rs)?;
84    Ok(Value::from_object(obj))
85}
86
87#[derive(Default, Debug)]
88#[repr(C)]
89pub struct Filestat {
90    pub device_id: u64,
91    pub inode: u64,
92    pub filetype: u8,
93    pub nlink: u64,
94    pub size: u64, // this is a read field, the rest are file fields
95    pub atim: u64,
96    pub mtim: u64,
97    pub ctim: u64,
98}
99
100pub struct FileType(u8);
101
102impl Into<&str> for FileType {
103    fn into(self) -> &'static str {
104        match self.0 {
105            0 => "unknown",
106            1 => "block device",
107            2 => "character device",
108            3 => "directory",
109            4 => "regular file",
110            5 => "socket dgram",
111            6 => "socket stream",
112            7 => "symbolic link",
113            _ => unimplemented!("FileType not implemented"),
114        }
115    }
116}
117
118pub enum Fstflags {
119    Atm = 1 << 0,
120    AtmNow = 1 << 1,
121    Mtim = 1 << 2,
122    MtimNow = 1 << 3,
123}