Skip to main content

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
12pub struct MemoryXattrStorage {
13    // Arbitrary userspace programs can define xattr keys so we use a collision-resistant hasher.
14    xattrs: RcuHashMap<FsString, FsString, std::collections::hash_map::RandomState>,
15}
16
17impl Default for MemoryXattrStorage {
18    fn default() -> Self {
19        Self { xattrs: RcuHashMap::with_hasher(std::collections::hash_map::RandomState::new()) }
20    }
21}
22
23impl XattrStorage for MemoryXattrStorage {
24    fn get_xattr(
25        &self,
26        _locked: &mut Locked<FileOpsCore>,
27        name: &FsStr,
28    ) -> Result<FsString, Errno> {
29        self.xattrs.get(&RcuReadScope::new(), name).cloned().ok_or_else(|| errno!(ENODATA))
30    }
31
32    fn set_xattr(
33        &self,
34        _locked: &mut Locked<FileOpsCore>,
35        name: &FsStr,
36        value: &FsStr,
37        op: XattrOp,
38    ) -> Result<(), Errno> {
39        let mut xattrs = self.xattrs.lock();
40        match xattrs.entry(name.to_owned()) {
41            Entry::Vacant(_) if op == XattrOp::Replace => return error!(ENODATA),
42            Entry::Occupied(_) if op == XattrOp::Create => return error!(EEXIST),
43            Entry::Vacant(v) => {
44                v.insert(value.to_owned());
45            }
46            Entry::Occupied(mut o) => {
47                o.insert(value.to_owned());
48            }
49        };
50        Ok(())
51    }
52
53    fn remove_xattr(&self, _locked: &mut Locked<FileOpsCore>, name: &FsStr) -> Result<(), Errno> {
54        let mut xattrs = self.xattrs.lock();
55        if xattrs.remove(name).is_none() {
56            return error!(ENODATA);
57        }
58        Ok(())
59    }
60
61    fn list_xattrs(&self, _locked: &mut Locked<FileOpsCore>) -> Result<Vec<FsString>, Errno> {
62        Ok(self.xattrs.keys(&RcuReadScope::new()).cloned().collect())
63    }
64}