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