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