starnix_core/vfs/
xattr.rs1use crate::vfs::{FsStr, FsString, XattrOp, XattrStorage};
6use starnix_rcu::rcu_hash_map::Entry;
7use starnix_rcu::{RcuHashMap, RcuReadScope};
8use starnix_sync::RcuHashMapLock;
9use starnix_uapi::errors::Errno;
10use starnix_uapi::{errno, error};
11
12pub struct MemoryXattrStorage {
13 xattrs:
15 RcuHashMap<FsString, Box<[u8]>, RcuHashMapLock, std::collections::hash_map::RandomState>,
16}
17
18impl Default for MemoryXattrStorage {
19 fn default() -> Self {
20 Self { xattrs: RcuHashMap::with_hasher(std::collections::hash_map::RandomState::new()) }
21 }
22}
23
24impl XattrStorage for MemoryXattrStorage {
25 fn get_xattr(&self, name: &FsStr) -> Result<Box<[u8]>, Errno> {
26 self.xattrs.get(&RcuReadScope::new(), name).cloned().ok_or_else(|| errno!(ENODATA))
27 }
28
29 fn set_xattr(&self, name: &FsStr, value: &[u8], op: XattrOp) -> Result<(), Errno> {
30 let mut xattrs = self.xattrs.lock();
31 match xattrs.entry(name.to_owned()) {
32 Entry::Vacant(_) if op == XattrOp::Replace => return error!(ENODATA),
33 Entry::Occupied(_) if op == XattrOp::Create => return error!(EEXIST),
34 Entry::Vacant(v) => {
35 v.insert(value.into());
36 }
37 Entry::Occupied(mut o) => {
38 o.insert(value.into());
39 }
40 };
41 Ok(())
42 }
43
44 fn remove_xattr(&self, name: &FsStr) -> Result<(), Errno> {
45 let mut xattrs = self.xattrs.lock();
46 if xattrs.remove(name).is_none() {
47 return error!(ENODATA);
48 }
49 Ok(())
50 }
51
52 fn list_xattrs(&self) -> Result<Vec<FsString>, Errno> {
53 Ok(self.xattrs.keys(&RcuReadScope::new()).cloned().collect())
54 }
55}