Mountain/IPC/WindServiceHandlers/FileSystem/Native/
FileOpenFd.rs1
2use std::{
16 collections::HashMap,
17 sync::{
18 Mutex,
19 OnceLock,
20 atomic::{AtomicU32, Ordering},
21 },
22};
23
24use serde_json::{Value, json};
25use tokio::fs::File;
26
27use crate::{IPC::WindServiceHandlers::Utilities::PathExtraction::Fn as extract_path_from_arg, dev_log};
28
29static NEXT_FD:AtomicU32 = AtomicU32::new(1);
30
31pub struct FdTable {
32 pub Files:Mutex<HashMap<u32, File>>,
33}
34
35static FD_TABLE:OnceLock<FdTable> = OnceLock::new();
36
37pub(crate) fn GetFdTable() -> &'static FdTable { FD_TABLE.get_or_init(|| FdTable { Files:Mutex::new(HashMap::new()) }) }
38
39pub async fn Fn(Arguments:Vec<Value>) -> Result<Value, String> {
40 let ResourceArg = Arguments.first().ok_or("file:open: missing resource")?;
41
42 let Path = extract_path_from_arg(ResourceArg)?;
43
44 let Opts = Arguments.get(1).and_then(Value::as_object);
45
46 let Create = Opts.and_then(|O| O.get("create")).and_then(Value::as_bool).unwrap_or(false);
47
48 let Truncate = Opts.and_then(|O| O.get("truncate")).and_then(Value::as_bool).unwrap_or(false);
49
50 let F = if Create {
51 let mut OpenOpts = tokio::fs::OpenOptions::new();
52
53 OpenOpts.write(true).create(true);
54
55 if Truncate {
56 OpenOpts.truncate(true);
57 }
58
59 OpenOpts
60 .open(&Path)
61 .await
62 .map_err(|E| format!("file:open create '{}': {}", Path, E))?
63 } else {
64 tokio::fs::File::open(&Path)
65 .await
66 .map_err(|E| format!("file:open '{}': {}", Path, E))?
67 };
68
69 let Fd = NEXT_FD.fetch_add(1, Ordering::Relaxed);
70
71 if let Ok(mut Table) = GetFdTable().Files.lock() {
72 Table.insert(Fd, F);
73 }
74
75 dev_log!("vfs", "file:open fd={} path={} create={}", Fd, Path, Create);
76
77 Ok(json!(Fd))
78}