1use core::mem;
30use kernel::hil::kv;
31use kernel::storage_permissions::StoragePermissions;
32use kernel::utilities::cells::{MapCell, OptionalCell, TakeCell};
33use kernel::utilities::leasable_buffer::SubSliceMut;
34use kernel::ErrorCode;
35
36#[derive(Clone, Copy, PartialEq, Debug)]
37enum Operation {
38 Get,
39 Set,
40 Add,
41 Update,
42 Delete,
43 GarbageCollect,
44}
45
46const HEADER_VERSION: u8 = 0;
48pub const HEADER_LENGTH: usize = mem::size_of::<KeyHeader>();
49
50#[repr(C, packed)]
52struct KeyHeader {
53 version: u8,
54 length: u32,
55 write_id: u32,
56}
57
58impl KeyHeader {
59 fn new_from_buf(buf: &[u8]) -> Self {
61 Self {
62 version: buf[0],
63 length: u32::from_le_bytes(buf[1..5].try_into().unwrap_or([0; 4])),
64 write_id: u32::from_le_bytes(buf[5..9].try_into().unwrap_or([0; 4])),
65 }
66 }
67
68 fn copy_to_buf(&self, buf: &mut [u8]) {
70 buf[0] = self.version;
71 buf[1..5].copy_from_slice(&self.length.to_le_bytes());
72 buf[5..9].copy_from_slice(&self.write_id.to_le_bytes());
73 }
74}
75
76pub struct KVStorePermissions<'a, K: kv::KV<'a>> {
81 kv: &'a K,
82 header_value: TakeCell<'static, [u8]>,
83
84 client: OptionalCell<&'a dyn kv::KVClient>,
85 operation: OptionalCell<Operation>,
86
87 value: MapCell<SubSliceMut<'static, u8>>,
88 valid_ids: OptionalCell<StoragePermissions>,
89}
90
91impl<'a, K: kv::KV<'a>> KVStorePermissions<'a, K> {
92 pub fn new(
93 kv: &'a K,
94 header_value: &'static mut [u8; HEADER_LENGTH],
95 ) -> KVStorePermissions<'a, K> {
96 Self {
97 kv,
98 header_value: TakeCell::new(header_value),
99 client: OptionalCell::empty(),
100 operation: OptionalCell::empty(),
101 value: MapCell::empty(),
102 valid_ids: OptionalCell::empty(),
103 }
104 }
105
106 fn insert(
107 &self,
108 key: SubSliceMut<'static, u8>,
109 mut value: SubSliceMut<'static, u8>,
110 permissions: StoragePermissions,
111 operation: Operation,
112 ) -> Result<
113 (),
114 (
115 SubSliceMut<'static, u8>,
116 SubSliceMut<'static, u8>,
117 ErrorCode,
118 ),
119 > {
120 let write_id = match permissions.get_write_id() {
121 Some(write_id) => write_id,
122 None => return Err((key, value, ErrorCode::INVAL)),
123 };
124
125 if self.operation.is_some() {
126 return Err((key, value, ErrorCode::BUSY));
127 }
128
129 if value.len() < HEADER_LENGTH {
131 return Err((key, value, ErrorCode::SIZE));
132 }
133
134 let header = KeyHeader {
136 version: HEADER_VERSION,
137 length: (value.len() - HEADER_LENGTH) as u32,
138 write_id,
139 };
140
141 header.copy_to_buf(value.as_slice());
143
144 self.operation.set(operation);
145
146 match operation {
147 Operation::Set | Operation::Update => {
148 self.valid_ids.set(permissions);
149
150 match self.header_value.take() {
152 Some(header_value) => match self.kv.get(key, SubSliceMut::new(header_value)) {
153 Ok(()) => {
154 self.value.replace(value);
155 Ok(())
156 }
157 Err((key, hvalue, e)) => {
158 self.header_value.replace(hvalue.take());
159 self.operation.clear();
160 Err((key, value, e))
161 }
162 },
163 None => Err((key, value, ErrorCode::FAIL)),
164 }
165 }
166
167 Operation::Add => {
168 match self.kv.add(key, value) {
172 Ok(()) => Ok(()),
173 Err((key, val, e)) => {
174 self.operation.clear();
175 Err((key, val, e))
176 }
177 }
178 }
179
180 _ => Err((key, value, ErrorCode::FAIL)),
181 }
182 }
183}
184
185impl<'a, K: kv::KV<'a>> kv::KVPermissions<'a> for KVStorePermissions<'a, K> {
186 fn set_client(&self, client: &'a dyn kv::KVClient) {
187 self.client.set(client);
188 }
189
190 fn get(
191 &self,
192 key: SubSliceMut<'static, u8>,
193 value: SubSliceMut<'static, u8>,
194 permissions: StoragePermissions,
195 ) -> Result<
196 (),
197 (
198 SubSliceMut<'static, u8>,
199 SubSliceMut<'static, u8>,
200 ErrorCode,
201 ),
202 > {
203 if self.operation.is_some() {
204 return Err((key, value, ErrorCode::BUSY));
205 }
206
207 self.operation.set(Operation::Get);
208 self.valid_ids.set(permissions);
209
210 match self.kv.get(key, value) {
211 Ok(()) => Ok(()),
212 Err((key, val, e)) => {
213 self.operation.clear();
214 Err((key, val, e))
215 }
216 }
217 }
218
219 fn set(
220 &self,
221 key: SubSliceMut<'static, u8>,
222 value: SubSliceMut<'static, u8>,
223 permissions: StoragePermissions,
224 ) -> Result<
225 (),
226 (
227 SubSliceMut<'static, u8>,
228 SubSliceMut<'static, u8>,
229 ErrorCode,
230 ),
231 > {
232 self.insert(key, value, permissions, Operation::Set)
233 }
234
235 fn add(
236 &self,
237 key: SubSliceMut<'static, u8>,
238 value: SubSliceMut<'static, u8>,
239 permissions: StoragePermissions,
240 ) -> Result<
241 (),
242 (
243 SubSliceMut<'static, u8>,
244 SubSliceMut<'static, u8>,
245 ErrorCode,
246 ),
247 > {
248 self.insert(key, value, permissions, Operation::Add)
249 }
250
251 fn update(
252 &self,
253 key: SubSliceMut<'static, u8>,
254 value: SubSliceMut<'static, u8>,
255 permissions: StoragePermissions,
256 ) -> Result<
257 (),
258 (
259 SubSliceMut<'static, u8>,
260 SubSliceMut<'static, u8>,
261 ErrorCode,
262 ),
263 > {
264 self.insert(key, value, permissions, Operation::Update)
265 }
266
267 fn delete(
268 &self,
269 key: SubSliceMut<'static, u8>,
270 permissions: StoragePermissions,
271 ) -> Result<(), (SubSliceMut<'static, u8>, ErrorCode)> {
272 if self.operation.is_some() {
273 return Err((key, ErrorCode::BUSY));
274 }
275
276 self.operation.set(Operation::Delete);
277 self.valid_ids.set(permissions);
278
279 match self.header_value.take() {
280 Some(header_value) => match self.kv.get(key, SubSliceMut::new(header_value)) {
281 Ok(()) => Ok(()),
282 Err((key, hvalue, e)) => {
283 self.header_value.replace(hvalue.take());
284 self.operation.clear();
285 Err((key, e))
286 }
287 },
288 None => Err((key, ErrorCode::FAIL)),
289 }
290 }
291
292 fn garbage_collect(&self) -> Result<(), ErrorCode> {
293 if self.operation.is_some() {
294 return Err(ErrorCode::BUSY);
295 }
296
297 self.operation.set(Operation::GarbageCollect);
298
299 self.kv.garbage_collect()
300 }
301
302 fn header_size(&self) -> usize {
303 HEADER_LENGTH
304 }
305}
306
307impl<'a, K: kv::KV<'a>> kv::KVClient for KVStorePermissions<'a, K> {
308 fn get_complete(
309 &self,
310 result: Result<(), ErrorCode>,
311 key: SubSliceMut<'static, u8>,
312 mut value: SubSliceMut<'static, u8>,
313 ) {
314 self.operation.map(|op| {
315 match op {
316 Operation::Set => {
317 let mut access_allowed = false;
319
320 if result.is_ok() || result.err() == Some(ErrorCode::SIZE) {
321 let header = KeyHeader::new_from_buf(value.as_slice());
322
323 if header.version == HEADER_VERSION {
324 self.valid_ids.map(|perms| {
325 access_allowed = perms.check_modify_permission(header.write_id);
326 });
327 }
328 } else if result.err() == Some(ErrorCode::NOSUPPORT) {
329 access_allowed = true;
331 }
332
333 self.header_value.replace(value.take());
334
335 if access_allowed {
336 self.value
337 .take()
338 .map(|set_value| match self.kv.set(key, set_value) {
339 Ok(()) => {}
340
341 Err((key, set_value, e)) => {
342 self.operation.clear();
343 self.client.map(move |cb| {
344 cb.set_complete(Err(e), key, set_value);
345 });
346 }
347 });
348 } else {
349 self.operation.clear();
350 self.value.take().map(|set_value| {
351 self.client.map(move |cb| {
352 cb.set_complete(Err(ErrorCode::NOSUPPORT), key, set_value);
353 });
354 });
355 }
356 }
357 Operation::Update => {
358 let mut access_allowed = false;
360
361 if result.is_ok() || result.err() == Some(ErrorCode::SIZE) {
362 let header = KeyHeader::new_from_buf(value.as_slice());
363
364 if header.version == HEADER_VERSION {
365 self.valid_ids.map(|perms| {
366 access_allowed = perms.check_modify_permission(header.write_id);
367 });
368 }
369 }
370
371 self.header_value.replace(value.take());
372
373 if access_allowed {
374 self.value
375 .take()
376 .map(|set_value| match self.kv.update(key, set_value) {
377 Ok(()) => {}
378
379 Err((key, set_value, e)) => {
380 self.operation.clear();
381 self.client.map(move |cb| {
382 cb.update_complete(Err(e), key, set_value);
383 });
384 }
385 });
386 } else {
387 self.operation.clear();
388 self.value.take().map(|set_value| {
389 self.client.map(move |cb| {
390 cb.update_complete(Err(ErrorCode::NOSUPPORT), key, set_value);
391 });
392 });
393 }
394 }
395 Operation::Delete => {
396 let mut access_allowed = false;
402
403 if result.is_ok() || result.err() == Some(ErrorCode::SIZE) {
404 let header = KeyHeader::new_from_buf(value.as_slice());
405
406 if header.version == HEADER_VERSION {
407 self.valid_ids.map(|perms| {
408 access_allowed = perms.check_modify_permission(header.write_id);
409 });
410 }
411 }
412
413 self.header_value.replace(value.take());
414
415 if access_allowed {
416 match self.kv.delete(key) {
417 Ok(()) => {}
418
419 Err((key, e)) => {
420 self.operation.clear();
421 self.client.map(move |cb| {
422 cb.delete_complete(Err(e), key);
423 });
424 }
425 }
426 } else {
427 self.operation.clear();
428 self.client.map(move |cb| {
429 cb.delete_complete(Err(ErrorCode::NOSUPPORT), key);
430 });
431 }
432 }
433 Operation::Get => {
434 self.operation.clear();
435
436 let mut read_allowed = false;
437
438 if result.is_ok() || result.err() == Some(ErrorCode::SIZE) {
439 let header = KeyHeader::new_from_buf(value.as_slice());
440
441 if header.version == HEADER_VERSION {
442 self.valid_ids.map(|perms| {
443 read_allowed = perms.check_read_permission(header.write_id);
444 });
445
446 if read_allowed {
447 value.slice(HEADER_LENGTH..);
450 }
451 }
452 }
453
454 if !read_allowed {
455 value.as_slice().iter_mut().for_each(|m| *m = 0)
457 }
458
459 self.client.map(move |cb| {
460 if read_allowed {
461 cb.get_complete(result, key, value);
462 } else {
463 cb.get_complete(Err(ErrorCode::NOSUPPORT), key, value);
467 }
468 });
469 }
470 _ => {}
471 }
472 });
473 }
474
475 fn set_complete(
476 &self,
477 result: Result<(), ErrorCode>,
478 key: SubSliceMut<'static, u8>,
479 value: SubSliceMut<'static, u8>,
480 ) {
481 self.operation.clear();
482 self.client.map(move |cb| {
483 cb.set_complete(result, key, value);
484 });
485 }
486
487 fn add_complete(
488 &self,
489 result: Result<(), ErrorCode>,
490 key: SubSliceMut<'static, u8>,
491 value: SubSliceMut<'static, u8>,
492 ) {
493 self.operation.clear();
494 self.client.map(move |cb| {
495 cb.add_complete(result, key, value);
496 });
497 }
498
499 fn update_complete(
500 &self,
501 result: Result<(), ErrorCode>,
502 key: SubSliceMut<'static, u8>,
503 value: SubSliceMut<'static, u8>,
504 ) {
505 self.operation.clear();
506 self.client.map(move |cb| {
507 cb.update_complete(result, key, value);
508 });
509 }
510
511 fn delete_complete(&self, result: Result<(), ErrorCode>, key: SubSliceMut<'static, u8>) {
512 self.operation.clear();
513 self.client.map(move |cb| {
514 cb.delete_complete(result, key);
515 });
516 }
517
518 fn garbage_collection_complete(&self, result: Result<(), ErrorCode>) {
519 self.operation.clear();
520 self.client.map(move |cb| {
521 cb.garbage_collection_complete(result);
522 });
523 }
524}