starnix_core/vfs/
xattr.rs

1// Copyright 2022 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use crate::vfs::{FsStr, FsString, XattrOp, XattrStorage};
6use starnix_rcu::rcu_hash_map::Entry;
7use starnix_rcu::{RcuHashMap, RcuReadScope};
8use starnix_sync::{FileOpsCore, Locked};
9use starnix_uapi::errors::Errno;
10use starnix_uapi::{errno, error};
11
12#[derive(Default)]
13pub struct MemoryXattrStorage {
14    xattrs: RcuHashMap<FsString, FsString>,
15}
16
17impl XattrStorage for MemoryXattrStorage {
18    fn get_xattr(
19        &self,
20        _locked: &mut Locked<FileOpsCore>,
21        name: &FsStr,
22    ) -> Result<FsString, Errno> {
23        self.xattrs.get(&RcuReadScope::new(), name).cloned().ok_or_else(|| errno!(ENODATA))
24    }
25
26    fn set_xattr(
27        &self,
28        _locked: &mut Locked<FileOpsCore>,
29        name: &FsStr,
30        value: &FsStr,
31        op: XattrOp,
32    ) -> Result<(), Errno> {
33        let mut xattrs = self.xattrs.lock();
34        match xattrs.entry(name.to_owned()) {
35            Entry::Vacant(_) if op == XattrOp::Replace => return error!(ENODATA),
36            Entry::Occupied(_) if op == XattrOp::Create => return error!(EEXIST),
37            Entry::Vacant(v) => {
38                v.insert(value.to_owned());
39            }
40            Entry::Occupied(mut o) => {
41                o.insert(value.to_owned());
42            }
43        };
44        Ok(())
45    }
46
47    fn remove_xattr(&self, _locked: &mut Locked<FileOpsCore>, name: &FsStr) -> Result<(), Errno> {
48        let mut xattrs = self.xattrs.lock();
49        if xattrs.remove(name).is_none() {
50            return error!(ENODATA);
51        }
52        Ok(())
53    }
54
55    fn list_xattrs(&self, _locked: &mut Locked<FileOpsCore>) -> Result<Vec<FsString>, Errno> {
56        Ok(self.xattrs.keys(&RcuReadScope::new()).cloned().collect())
57    }
58}