1#![no_std]
2
3extern crate alloc;
4
5#[cfg(feature = "building")]
6mod building;
7mod device_trait;
8mod error;
9mod read_data;
10mod standard;
11
12use alloc::string::String;
13#[cfg(feature = "building")]
14pub use building::*;
15pub use device_trait::*;
16pub use error::*;
17pub use read_data::*;
18pub use standard::*;
19
20use task::{JoinHandle, TaskIdentifier};
21use users::UserIdentifier;
22use virtual_file_system::File;
23
24use file_system::{Path, Statistics_type};
25
26async fn is_execute_allowed(statistics: &Statistics_type, user: UserIdentifier) -> bool {
27 if statistics.get_permissions().get_others().get_execute() {
29 return true;
30 }
31
32 if user == UserIdentifier::ROOT {
34 return true;
35 }
36 if (statistics.get_user() == user) && statistics.get_permissions().get_user().get_execute() {
37 return true;
38 }
39
40 let is_in_group = users::get_instance()
42 .is_in_group(user, statistics.get_group())
43 .await;
44
45 if (is_in_group) && statistics.get_permissions().get_group().get_execute() {
47 return true;
48 }
49
50 false
51}
52
53async fn get_overridden_user(
54 statistics: &Statistics_type,
55 task: TaskIdentifier,
56) -> Result<Option<UserIdentifier>> {
57 if !statistics
58 .get_permissions()
59 .get_special()
60 .get_set_user_identifier()
61 {
62 return Ok(None);
63 }
64
65 let current_user = task::get_instance().get_user(task).await?;
66
67 let new_user = statistics.get_user();
68
69 if current_user != users::UserIdentifier::ROOT || new_user != current_user {
70 return Err(Error::PermissionDenied);
71 }
72
73 Ok(Some(new_user))
74}
75
76pub async fn execute(
77 path: impl AsRef<Path>,
78 inputs: String,
79 standard: Standard,
80) -> Result<JoinHandle<isize>> {
81 let task_instance = task::get_instance();
82
83 let task = task_instance.get_current_task_identifier().await;
84
85 let file = File::open(
86 virtual_file_system::get_instance(),
87 &path,
88 file_system::Mode::READ_WRITE.into(),
89 )
90 .await?;
91
92 if !is_execute_allowed(
94 &file.get_statistics().await?,
95 task_instance.get_user(task).await?,
96 )
97 .await
98 {
99 return Err(Error::PermissionDenied);
100 }
101
102 let new_user = get_overridden_user(&file.get_statistics().await?, task).await?;
104
105 let file_name = path
106 .as_ref()
107 .get_file_name()
108 .ok_or(file_system::Error::InvalidPath)?;
109
110 let mut read_data = ReadData::new_default();
111 file.read(&mut read_data).await?;
112 let read_data: ReadData = read_data.try_into().unwrap();
113
114 let main = read_data.get_main().ok_or(Error::FailedToGetMainFunction)?;
115
116 let (join_handle, _) = task_instance
117 .spawn(task, file_name, None, async move |task| {
118 if let Some(new_user) = new_user {
119 task::get_instance().set_user(task, new_user).await.unwrap();
120 }
121
122 let standard = standard.transfert(task).await.unwrap();
123
124 match main(standard, inputs).await {
125 Ok(_) => 0_isize,
126 Err(error) => -(error.get() as isize),
127 }
128 })
129 .await?;
130
131 Ok(join_handle)
132}
133
134#[cfg(test)]
135mod tests {
136 extern crate std;
137
138 use file_system::Time;
139
140 use task::test;
141
142 use super::*;
143
144 #[test]
145 async fn is_user_allowed_test() {
146 let statistics = Statistics_type::new(
147 file_system::FileSystemIdentifier::new(0),
148 file_system::Inode::new(0),
149 1,
150 0_usize.into(),
151 Time::new(0),
152 Time::new(0),
153 Time::new(0),
154 file_system::Kind::File,
155 file_system::Permissions::from_octal(0o777).unwrap(),
156 users::UserIdentifier::ROOT,
157 users::GroupIdentifier::ROOT,
158 );
159
160 assert!(is_execute_allowed(&statistics, users::UserIdentifier::ROOT).await);
161 assert!(is_execute_allowed(&statistics, users::UserIdentifier::ROOT).await);
162 assert!(is_execute_allowed(&statistics, users::UserIdentifier::ROOT).await);
163 }
164}