#![forbid(unsafe_code)]
use std::{
os::fd::{AsRawFd, IntoRawFd},
sync::Arc,
};
use libc::c_uint;
use memchr::arch::all::memchr::One;
use nix::errno::Errno;
use crate::{
fd::{
closeall, AT_BADFD, PROC_FD, PROC_F_MODE, PROC_MNT_ID, ROOT_FD, ROOT_F_MODE, ROOT_MNT_ID,
},
hash::SydHashMap,
lookup::{FileMapEntry, FileType, MaybeFd},
path::XPath,
XPathBuf,
};
type InnerMap = SydHashMap<XPathBuf, FileMapEntry>;
pub struct FileMap(InnerMap);
impl FileMap {
pub(crate) fn find_descendant(&mut self, path: &XPath) -> Option<(MaybeFd, usize)> {
let path = path.as_bytes();
let mut result = None;
for (cpath, entry) in &self.0 {
let cpath = cpath.as_bytes();
if cpath.len() > path.len() && cpath.starts_with(path) {
let left = &cpath[path.len()..];
if left[0] == b'/' || path.last() == Some(&b'/') {
let my_depth = One::new(b'/').count(left);
match &result {
Some((_fd, depth)) if *depth <= my_depth => {}
_ => result = Some((entry.fd.clone(), my_depth)),
};
}
}
}
result
}
pub(crate) fn try_insert(
&mut self,
path: XPathBuf,
entry: FileMapEntry,
) -> Result<Option<FileMapEntry>, Errno> {
if path.is_root() || path.is_procfs() {
Ok(self.map_get(&path).cloned())
} else {
self.0.try_reserve(1).or(Err(Errno::ENOMEM))?;
Ok(self.0.insert(path, entry))
}
}
pub(crate) fn remove(&mut self, path: &XPath) -> Option<FileMapEntry> {
if path.is_root() || path.is_procfs() {
self.map_get(path).cloned()
} else {
self.map_remove(path)
}
}
pub(crate) fn get(&self, path: &XPath) -> Option<&FileMapEntry> {
self.map_get(path)
}
pub(crate) fn get_mut(&mut self, path: &XPath) -> Option<&mut FileMapEntry> {
self.map_get_mut(path)
}
fn map_get(&self, path: &XPath) -> Option<&FileMapEntry> {
self.0.get(path)
}
fn map_get_mut(&mut self, path: &XPath) -> Option<&mut FileMapEntry> {
self.0.get_mut(path)
}
fn map_remove(&mut self, path: &XPath) -> Option<FileMapEntry> {
self.0.remove(path)
}
fn try_insert_root(&mut self) -> Result<(), Errno> {
let mut path = XPathBuf::empty();
path.try_reserve(1).or(Err(Errno::ENOMEM))?;
path.append_byte(b'/');
let entry = FileMapEntry::new(
ROOT_FD().into(),
Some(FileType::Dir),
Some(ROOT_F_MODE()),
Some(ROOT_MNT_ID()),
Some(Err(Errno::EINVAL)),
);
self.0.try_reserve(1).or(Err(Errno::ENOMEM))?;
self.0.insert(path, entry);
Ok(())
}
fn try_insert_proc(&mut self) -> Result<(), Errno> {
let mut path = XPathBuf::empty();
path.try_reserve(5).or(Err(Errno::ENOMEM))?;
path.append_bytes(b"/proc");
let entry = FileMapEntry::new(
PROC_FD().into(),
Some(FileType::Dir),
Some(PROC_F_MODE()),
Some(PROC_MNT_ID()),
Some(Err(Errno::EINVAL)),
);
self.0.try_reserve(1).or(Err(Errno::ENOMEM))?;
self.0.insert(path, entry);
Ok(())
}
pub(crate) fn try_new() -> Result<Self, Errno> {
let mut map = Self(SydHashMap::default());
map.try_insert_root()?;
map.try_insert_proc()?;
Ok(map)
}
#[expect(clippy::disallowed_methods)]
pub(crate) fn reset(&mut self) {
let root_fd = ROOT_FD();
let proc_fd = PROC_FD();
let root_mnt_id = ROOT_MNT_ID();
let proc_mnt_id = PROC_MNT_ID();
let len = self.0.len().saturating_sub(2);
let mut close_fds = Vec::new();
close_fds.try_reserve_exact(len).unwrap();
self.0.iter_mut().for_each(|(_key, entry)| {
if matches!(entry.fd, MaybeFd::Owned(_)) {
let fd = std::mem::replace(&mut entry.fd, MaybeFd::RawFd(AT_BADFD.as_raw_fd()));
if let MaybeFd::Owned(fd) = fd {
if let Some(fd) = Arc::into_inner(fd) {
#[expect(clippy::cast_sign_loss)]
close_fds.push(fd.into_raw_fd() as c_uint);
}
}
}
});
self.0.retain(|_, entry| {
let fd = entry.fd.as_raw_fd();
let mnt_id = entry.mnt_id;
entry.f_type == Some(FileType::Dir)
&& ((fd == root_fd && mnt_id == Some(root_mnt_id))
|| (fd == proc_fd && mnt_id == Some(proc_mnt_id)))
});
if !close_fds.is_empty() {
close_fds.sort_unstable();
let _ = closeall(&close_fds);
}
}
}
#[cfg(test)]
mod tests {
use std::{os::fd::AsRawFd, sync::Once};
use nix::fcntl::OFlag;
use super::*;
use crate::{
fd::{open_static_files, ROOT_FD},
lookup::{FileMapEntry, FileType, MaybeFd},
path::{XPath, XPathBuf},
};
fn setup() {
static INIT: Once = Once::new();
INIT.call_once(|| {
open_static_files(OFlag::O_PATH).unwrap();
});
}
fn entry_raw(fd: i32) -> FileMapEntry {
FileMapEntry::new(
MaybeFd::RawFd(fd),
Some(FileType::Reg),
Some(0o644),
Some(1),
None,
)
}
fn entry_dir(fd: i32) -> FileMapEntry {
FileMapEntry::new(
MaybeFd::RawFd(fd),
Some(FileType::Dir),
Some(0o755),
Some(1),
None,
)
}
#[test]
fn test_filemap_1() {
setup();
let map = FileMap::try_new().unwrap();
let root = map.get(XPath::from_bytes(b"/"));
assert!(root.is_some());
let entry = root.unwrap();
assert_eq!(entry.fd.as_raw_fd(), ROOT_FD());
assert_eq!(entry.mnt_id, Some(ROOT_MNT_ID()));
}
#[test]
fn test_filemap_2() {
setup();
let map = FileMap::try_new().unwrap();
let proc = map.get(XPath::from_bytes(b"/proc"));
assert!(proc.is_some());
let entry = proc.unwrap();
assert_eq!(entry.fd.as_raw_fd(), PROC_FD());
assert_eq!(entry.mnt_id, Some(PROC_MNT_ID()));
}
#[test]
fn test_filemap_3() {
setup();
let mut map = FileMap::try_new().unwrap();
let path = XPathBuf::from("/home");
let old = map.try_insert(path, entry_dir(42)).unwrap();
assert!(old.is_none());
let got = map.get(XPath::from_bytes(b"/home"));
assert!(got.is_some());
assert_eq!(got.unwrap().fd.as_raw_fd(), 42);
}
#[test]
fn test_filemap_4() {
setup();
let mut map = FileMap::try_new().unwrap();
let path = XPathBuf::from("/etc");
map.try_insert(path.clone(), entry_dir(10)).unwrap();
let old = map.try_insert(path, entry_dir(20)).unwrap();
assert!(old.is_some());
assert_eq!(old.unwrap().fd.as_raw_fd(), 10);
let got = map.get(XPath::from_bytes(b"/etc"));
assert_eq!(got.unwrap().fd.as_raw_fd(), 20);
}
#[test]
fn test_filemap_5() {
setup();
let mut map = FileMap::try_new().unwrap();
let paths = ["/a", "/b", "/c", "/a/b", "/a/b/c"];
for (i, p) in paths.iter().enumerate() {
let fd = (100 + i) as i32;
map.try_insert(XPathBuf::from(*p), entry_raw(fd)).unwrap();
}
for (i, p) in paths.iter().enumerate() {
let fd = (100 + i) as i32;
let e = map.get(XPath::from_bytes(p.as_bytes()));
assert!(e.is_some(), "entry for {p} must exist");
assert_eq!(e.unwrap().fd.as_raw_fd(), fd);
}
}
#[test]
fn test_filemap_6() {
setup();
let map = FileMap::try_new().unwrap();
assert!(map.get(XPath::from_bytes(b"/no/such/path")).is_none());
}
#[test]
fn test_filemap_7() {
setup();
let mut map = FileMap::try_new().unwrap();
map.try_insert(XPathBuf::from("/mutable"), entry_raw(50))
.unwrap();
{
let e = map.get_mut(XPath::from_bytes(b"/mutable")).unwrap();
e.fd = MaybeFd::RawFd(99);
}
let e = map.get(XPath::from_bytes(b"/mutable")).unwrap();
assert_eq!(e.fd.as_raw_fd(), 99);
}
#[test]
fn test_filemap_8() {
setup();
let mut map = FileMap::try_new().unwrap();
assert!(map.get_mut(XPath::from_bytes(b"/ghost")).is_none());
}
#[test]
fn test_filemap_9() {
setup();
let mut map = FileMap::try_new().unwrap();
map.try_insert(XPathBuf::from("/tmp"), entry_dir(30))
.unwrap();
assert!(map.get(XPath::from_bytes(b"/tmp")).is_some());
let removed = map.remove(XPath::from_bytes(b"/tmp"));
assert!(removed.is_some());
assert_eq!(removed.unwrap().fd.as_raw_fd(), 30);
assert!(map.get(XPath::from_bytes(b"/tmp")).is_none());
}
#[test]
fn test_filemap_10() {
setup();
let mut map = FileMap::try_new().unwrap();
let removed = map.remove(XPath::from_bytes(b"/nonexistent"));
assert!(removed.is_none());
}
#[test]
fn test_filemap_11() {
setup();
let mut map = FileMap::try_new().unwrap();
let removed = map.remove(XPath::from_bytes(b"/"));
assert!(removed.is_some());
assert!(map.get(XPath::from_bytes(b"/")).is_some());
}
#[test]
fn test_filemap_12() {
setup();
let mut map = FileMap::try_new().unwrap();
map.try_insert(XPathBuf::from("/usr"), entry_dir(60))
.unwrap();
map.try_insert(XPathBuf::from("/usr/bin"), entry_dir(61))
.unwrap();
map.try_insert(XPathBuf::from("/usr/bin/foo"), entry_dir(62))
.unwrap();
map.try_insert(XPathBuf::from("/usr/bin/foo/bar"), entry_dir(63))
.unwrap();
let result = map.find_descendant(XPath::from_bytes(b"/usr"));
assert!(result.is_some());
let (fd, depth) = result.unwrap();
assert_eq!(fd.as_raw_fd(), 61);
assert_eq!(depth, 1);
}
#[test]
fn test_filemap_13() {
setup();
let mut map = FileMap::try_new().unwrap();
map.try_insert(XPathBuf::from("/a/b/c/d/e"), entry_raw(80))
.unwrap();
let result = map.find_descendant(XPath::from_bytes(b"/a"));
assert!(result.is_some());
let (fd, depth) = result.unwrap();
assert_eq!(fd.as_raw_fd(), 80);
assert_eq!(depth, 4);
}
#[test]
fn test_filemap_14() {
setup();
let mut map = FileMap::try_new().unwrap();
map.try_insert(XPathBuf::from("/opt/foo"), entry_raw(90))
.unwrap();
let result = map.find_descendant(XPath::from_bytes(b"/var"));
assert!(result.is_none());
}
#[test]
fn test_filemap_15() {
setup();
let mut map = FileMap::try_new().unwrap();
map.try_insert(XPathBuf::from("/usr"), entry_dir(60))
.unwrap();
map.try_insert(XPathBuf::from("/usrlocal"), entry_raw(61))
.unwrap();
map.try_insert(XPathBuf::from("/usr/local"), entry_raw(62))
.unwrap();
let result = map.find_descendant(XPath::from_bytes(b"/usr"));
assert!(result.is_some());
let (fd, depth) = result.unwrap();
assert_eq!(fd.as_raw_fd(), 62);
assert_eq!(depth, 1);
}
#[test]
fn test_filemap_16() {
setup();
let mut map = FileMap::try_new().unwrap();
map.try_insert(XPathBuf::from("/lib/a"), entry_raw(100))
.unwrap();
map.try_insert(XPathBuf::from("/lib/b"), entry_raw(101))
.unwrap();
map.try_insert(XPathBuf::from("/lib/c/d"), entry_raw(102))
.unwrap();
map.try_insert(XPathBuf::from("/lib/c/d/e"), entry_raw(103))
.unwrap();
map.try_insert(XPathBuf::from("/usr/bin"), entry_raw(104))
.unwrap();
map.try_insert(XPathBuf::from("/usr/lib"), entry_raw(105))
.unwrap();
let result = map.find_descendant(XPath::from_bytes(b"/lib"));
assert!(result.is_some());
let (fd, depth) = result.unwrap();
let fd = fd.as_raw_fd();
assert!(matches!(fd, 100 | 101), "FD:{fd}");
assert_eq!(depth, 1);
}
#[test]
fn test_filemap_17() {
setup();
let mut map = FileMap::try_new().unwrap();
map.try_insert(XPathBuf::from("/proc/self"), entry_raw(100))
.unwrap();
map.try_insert(XPathBuf::from("/proc/self/status"), entry_raw(1001))
.unwrap();
let result = map.find_descendant(XPath::from_bytes(b"/proc"));
assert!(result.is_some());
let (fd, depth) = result.unwrap();
assert_eq!(fd.as_raw_fd(), 100);
assert_eq!(depth, 1);
}
#[test]
fn test_filemap_18() {
setup();
let mut map = FileMap::try_new().unwrap();
let result = map.find_descendant(XPath::from_bytes(b"/"));
assert!(result.is_some());
let (fd, depth) = result.unwrap();
assert_eq!(fd.as_raw_fd(), PROC_FD());
assert_eq!(depth, 0);
}
#[test]
fn test_filemap_19() {
setup();
let mut map = FileMap::try_new().unwrap();
let mut inserted = 0usize;
for i in 0..10000 {
let path = format!("/large/{i}");
let fd = (1000i32 + i as i32) as i32;
match map.try_insert(XPathBuf::from(path), entry_raw(fd)) {
Ok(_) => inserted += 1,
Err(Errno::ENOMEM) => break,
Err(errno) => panic!("unexpected error: {errno}"),
}
}
for i in 0..inserted {
let path = format!("/large/{i}");
let fd = (1000i32 + i as i32) as i32;
let e = map.get(XPath::from_bytes(path.as_bytes()));
assert!(e.is_some(), "entry {path} must exist");
assert_eq!(e.unwrap().fd.as_raw_fd(), fd);
}
if inserted > 0 {
let result = map.find_descendant(XPath::from_bytes(b"/large"));
assert!(result.is_some());
}
}
#[test]
fn test_filemap_20() {
setup();
let mut map = FileMap::try_new().unwrap();
let path = XPathBuf::from("/cycle");
map.try_insert(path.clone(), entry_raw(200)).unwrap();
assert_eq!(
map.get(XPath::from_bytes(b"/cycle"))
.unwrap()
.fd
.as_raw_fd(),
200
);
let removed = map.remove(XPath::from_bytes(b"/cycle"));
assert!(removed.is_some());
assert!(map.get(XPath::from_bytes(b"/cycle")).is_none());
map.try_insert(path, entry_raw(300)).unwrap();
assert_eq!(
map.get(XPath::from_bytes(b"/cycle"))
.unwrap()
.fd
.as_raw_fd(),
300
);
}
#[test]
fn test_filemap_21() {
setup();
let mut map = FileMap::try_new().unwrap();
let deep = "/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p";
map.try_insert(XPathBuf::from(deep), entry_raw(400))
.unwrap();
let e = map.get(XPath::from_bytes(deep.as_bytes()));
assert!(e.is_some());
assert_eq!(e.unwrap().fd.as_raw_fd(), 400);
let result = map.find_descendant(XPath::from_bytes(b"/a"));
assert!(result.is_some());
let (_fd, depth) = result.unwrap();
assert_eq!(depth, 15);
}
#[test]
fn test_filemap_22() {
setup();
let mut map = FileMap::try_new().unwrap();
map.try_insert(XPathBuf::from("/usr/lib/lib.so.6"), entry_raw(500))
.unwrap();
let e = map.get(XPath::from_bytes(b"/usr/lib/lib.so.6"));
assert!(e.is_some());
assert_eq!(e.unwrap().fd.as_raw_fd(), 500);
}
#[test]
fn test_filemap_23() {
setup();
let mut map = FileMap::try_new().unwrap();
for i in 0..10 {
let fd = (9000 + i) as i32;
let path = format!("/drop_test/{i}");
map.try_insert(XPathBuf::from(path), entry_raw(fd)).unwrap();
}
}
#[test]
fn test_filemap_24() {
setup();
let mut map = FileMap::try_new().unwrap();
map.try_insert(XPathBuf::from("/data/file"), entry_raw(600))
.unwrap();
let result = map.find_descendant(XPath::from_bytes(b"/data/"));
assert!(result.is_some());
let (fd, depth) = result.unwrap();
assert_eq!(fd.as_raw_fd(), 600);
assert_eq!(depth, 0);
}
#[test]
fn test_filemap_25() {
setup();
let mut map = FileMap::try_new().unwrap();
map.try_insert(XPathBuf::from("/foobar"), entry_raw(700))
.unwrap();
let result = map.find_descendant(XPath::from_bytes(b"/foo"));
assert!(result.is_none());
}
#[test]
fn test_filemap_26() {
setup();
let mut map = FileMap::try_new().unwrap();
map.try_insert(XPathBuf::from("/foo/bar"), entry_raw(710))
.unwrap();
map.try_insert(XPathBuf::from("/foobar"), entry_raw(720))
.unwrap();
let result = map.find_descendant(XPath::from_bytes(b"/foo"));
assert!(result.is_some());
let (fd, depth) = result.unwrap();
assert_eq!(fd.as_raw_fd(), 710);
assert_eq!(depth, 1);
}
#[test]
fn test_filemap_27() {
setup();
let mut map = FileMap::try_new().unwrap();
map.try_insert(XPathBuf::from("/a/b"), entry_raw(800))
.unwrap();
map.try_insert(XPathBuf::from("/abc"), entry_raw(801))
.unwrap();
map.try_insert(XPathBuf::from("/ab/cd"), entry_raw(802))
.unwrap();
let result = map.find_descendant(XPath::from_bytes(b"/ab"));
assert!(result.is_some());
let (fd, depth) = result.unwrap();
assert_eq!(fd.as_raw_fd(), 802);
assert_eq!(depth, 1);
}
#[test]
fn test_filemap_28() {
setup();
let mut map = FileMap::try_new().unwrap();
map.try_insert(XPathBuf::from("/xyz1"), entry_raw(810))
.unwrap();
map.try_insert(XPathBuf::from("/xyz2"), entry_raw(811))
.unwrap();
let result = map.find_descendant(XPath::from_bytes(b"/xyz"));
assert!(result.is_none());
}
#[test]
fn test_filemap_29() {
setup();
let mut map = FileMap::try_new().unwrap();
let result = map.find_descendant(XPath::from_bytes(b"/zzz"));
assert!(result.is_none());
}
#[test]
fn test_filemap_30() {
setup();
let mut map = FileMap::try_new().unwrap();
map.try_insert(XPathBuf::from("/a"), entry_raw(820))
.unwrap();
map.try_insert(XPathBuf::from("/b"), entry_raw(821))
.unwrap();
let removed = map.remove(XPath::from_bytes(b"/a"));
assert!(removed.is_some());
assert_eq!(removed.unwrap().fd.as_raw_fd(), 820);
assert!(map.get(XPath::from_bytes(b"/a")).is_none());
assert!(map.get(XPath::from_bytes(b"/b")).is_some());
}
#[test]
fn test_filemap_31() {
setup();
let mut map = FileMap::try_new().unwrap();
let e1 = entry_dir(830);
let e2 = entry_dir(831);
map.try_insert(XPathBuf::from("/dup"), e1).unwrap();
let old = map.try_insert(XPathBuf::from("/dup"), e2).unwrap();
assert!(old.is_some());
assert_eq!(old.unwrap().fd.as_raw_fd(), 830);
}
#[test]
fn test_filemap_32() {
setup();
let mut map = FileMap::try_new().unwrap();
map.try_insert(XPathBuf::from("/tmp"), entry_dir(30))
.unwrap();
map.try_insert(XPathBuf::from("/var"), entry_dir(31))
.unwrap();
map.try_insert(XPathBuf::from("/home"), entry_dir(32))
.unwrap();
assert!(map.get(XPath::from_bytes(b"/tmp")).is_some());
assert!(map.get(XPath::from_bytes(b"/var")).is_some());
assert!(map.get(XPath::from_bytes(b"/home")).is_some());
map.reset();
assert!(map.get(XPath::from_bytes(b"/")).is_some());
assert_eq!(
map.get(XPath::from_bytes(b"/")).unwrap().fd.as_raw_fd(),
ROOT_FD()
);
assert!(map.get(XPath::from_bytes(b"/tmp")).is_none());
assert!(map.get(XPath::from_bytes(b"/var")).is_none());
assert!(map.get(XPath::from_bytes(b"/home")).is_none());
}
#[test]
fn test_filemap_33() {
setup();
let mut map = FileMap::try_new().unwrap();
map.try_insert(XPathBuf::from("/a"), entry_dir(10)).unwrap();
map.try_insert(XPathBuf::from("/a/b"), entry_dir(11))
.unwrap();
map.try_insert(XPathBuf::from("/a/b/c"), entry_dir(12))
.unwrap();
map.try_insert(XPathBuf::from("/x/y/z"), entry_dir(13))
.unwrap();
map.reset();
assert!(map.get(XPath::from_bytes(b"/")).is_some());
assert!(map.get(XPath::from_bytes(b"/proc")).is_some());
assert_eq!(map.0.len(), 2);
}
#[test]
fn test_filemap_34() {
setup();
let mut map = FileMap::try_new().unwrap();
map.try_insert(XPathBuf::from("/foo"), entry_dir(100))
.unwrap();
map.reset();
assert!(map.get(XPath::from_bytes(b"/foo")).is_none());
map.try_insert(XPathBuf::from("/bar"), entry_dir(200))
.unwrap();
map.reset();
assert!(map.get(XPath::from_bytes(b"/bar")).is_none());
map.try_insert(XPathBuf::from("/baz"), entry_dir(300))
.unwrap();
map.reset();
assert!(map.get(XPath::from_bytes(b"/baz")).is_none());
assert!(map.get(XPath::from_bytes(b"/")).is_some());
}
#[test]
fn test_filemap_35() {
setup();
let mut map = FileMap::try_new().unwrap();
map.reset();
assert!(map.get(XPath::from_bytes(b"/")).is_some());
assert!(map.get(XPath::from_bytes(b"/proc")).is_some());
assert_eq!(map.0.len(), 2);
}
#[test]
fn test_filemap_36() {
setup();
let mut map = FileMap::try_new().unwrap();
for i in 0..100 {
let path = format!("/test/{i}");
map.try_insert(XPathBuf::from(path), entry_raw(1000 + i))
.unwrap();
}
map.reset();
assert!(map.get(XPath::from_bytes(b"/")).is_some());
assert!(map.get(XPath::from_bytes(b"/proc")).is_some());
assert_eq!(map.0.len(), 2);
}
#[test]
fn test_filemap_37() {
setup();
let mut map = FileMap::try_new().unwrap();
map.try_insert(XPathBuf::from("/first"), entry_dir(1))
.unwrap();
map.reset();
assert!(map.get(XPath::from_bytes(b"/first")).is_none());
map.try_insert(XPathBuf::from("/second"), entry_dir(2))
.unwrap();
assert!(map.get(XPath::from_bytes(b"/second")).is_some());
map.reset();
assert!(map.get(XPath::from_bytes(b"/second")).is_none());
assert_eq!(map.0.len(), 2);
}
#[test]
fn test_filemap_38() {
setup();
let mut map = FileMap::try_new().unwrap();
map.try_insert(XPathBuf::from("/a"), entry_dir(1)).unwrap();
map.try_insert(XPathBuf::from("/b"), entry_dir(2)).unwrap();
map.try_insert(XPathBuf::from("/c"), entry_dir(3)).unwrap();
map.try_insert(XPathBuf::from("/d"), entry_dir(4)).unwrap();
map.try_insert(XPathBuf::from("/e"), entry_dir(5)).unwrap();
assert_eq!(map.0.len(), 7);
map.reset();
assert_eq!(map.0.len(), 2);
assert!(map.get(XPath::from_bytes(b"/")).is_some());
assert!(map.get(XPath::from_bytes(b"/proc")).is_some());
assert!(map.get(XPath::from_bytes(b"/a")).is_none());
assert!(map.get(XPath::from_bytes(b"/b")).is_none());
assert!(map.get(XPath::from_bytes(b"/c")).is_none());
assert!(map.get(XPath::from_bytes(b"/d")).is_none());
assert!(map.get(XPath::from_bytes(b"/e")).is_none());
}
#[test]
fn test_filemap_39() {
setup();
let mut map = FileMap::try_new().unwrap();
map.try_insert(XPathBuf::from("/z"), entry_dir(26)).unwrap();
map.try_insert(XPathBuf::from("/y"), entry_dir(25)).unwrap();
map.try_insert(XPathBuf::from("/x"), entry_dir(24)).unwrap();
map.try_insert(XPathBuf::from("/w"), entry_dir(23)).unwrap();
map.reset();
assert_eq!(map.0.len(), 2);
}
#[test]
fn test_filemap_40() {
setup();
let mut map = FileMap::try_new().unwrap();
map.try_insert(XPathBuf::from("/a1"), entry_dir(1)).unwrap();
map.try_insert(XPathBuf::from("/a2"), entry_dir(2)).unwrap();
map.try_insert(XPathBuf::from("/b1"), entry_dir(3)).unwrap();
map.try_insert(XPathBuf::from("/b2"), entry_dir(4)).unwrap();
map.try_insert(XPathBuf::from("/c1"), entry_dir(5)).unwrap();
map.try_insert(XPathBuf::from("/c2"), entry_dir(6)).unwrap();
map.reset();
assert_eq!(map.0.len(), 2);
}
#[test]
fn test_filemap_41() {
setup();
let mut map = FileMap::try_new().unwrap();
const PATH_MAX: usize = libc::PATH_MAX as usize;
let base_path = "/a";
let component = "/b";
let mut path = String::from(base_path);
while path.len() < PATH_MAX {
path.push_str(component);
}
for i in 0..5 {
let mut p = path.clone();
p.push_str(&format!("/c{i}"));
map.try_insert(XPathBuf::from(p), entry_raw((100 + i) as i32))
.unwrap();
}
map.reset();
assert_eq!(map.0.len(), 2);
}
#[test]
fn test_filemap_42() {
setup();
let mut map = FileMap::try_new().unwrap();
map.try_insert(XPathBuf::from("/usr"), entry_dir(1))
.unwrap();
map.try_insert(XPathBuf::from("/usr/bin"), entry_dir(2))
.unwrap();
map.try_insert(XPathBuf::from("/usr/local"), entry_dir(3))
.unwrap();
map.try_insert(XPathBuf::from("/usr/local/bin"), entry_dir(4))
.unwrap();
map.try_insert(XPathBuf::from("/usr/lib"), entry_dir(5))
.unwrap();
map.reset();
assert_eq!(map.0.len(), 2);
assert!(map.get(XPath::from_bytes(b"/")).is_some());
assert!(map.get(XPath::from_bytes(b"/proc")).is_some());
}
#[test]
fn test_filemap_43() {
setup();
let mut map = FileMap::try_new().unwrap();
map.try_insert(XPathBuf::from("/single"), entry_dir(999))
.unwrap();
assert_eq!(map.0.len(), 3);
map.reset();
assert_eq!(map.0.len(), 2);
assert!(map.get(XPath::from_bytes(b"/")).is_some());
assert!(map.get(XPath::from_bytes(b"/proc")).is_some());
}
#[test]
fn test_filemap_44() {
setup();
let mut map = FileMap::try_new().unwrap();
map.try_insert(XPathBuf::from("/tmp"), entry_dir(1))
.unwrap();
map.try_insert(XPathBuf::from("/var"), entry_dir(2))
.unwrap();
assert!(map.get(XPath::from_bytes(b"/")).is_some());
assert!(map.get(XPath::from_bytes(b"/proc")).is_some());
assert_eq!(map.0.len(), 4);
map.reset();
assert!(map.get(XPath::from_bytes(b"/")).is_some());
assert!(map.get(XPath::from_bytes(b"/proc")).is_some());
assert!(map.get(XPath::from_bytes(b"/tmp")).is_none());
assert!(map.get(XPath::from_bytes(b"/var")).is_none());
assert_eq!(map.0.len(), 2);
}
#[test]
fn test_filemap_45() {
setup();
let mut map = FileMap::try_new().unwrap();
for i in 0..50 {
let path = format!("/test/{}", i);
map.try_insert(XPathBuf::from(path), entry_raw(1000 + i))
.unwrap();
}
map.reset();
assert!(map.get(XPath::from_bytes(b"/")).is_some());
assert!(map.get(XPath::from_bytes(b"/proc")).is_some());
assert_eq!(map.0.len(), 2);
}
#[test]
fn test_filemap_46() {
setup();
let mut map = FileMap::try_new().unwrap();
let root_fd = ROOT_FD();
map.try_insert(XPathBuf::from("/test"), entry_dir(42))
.unwrap();
map.reset();
let root = map.get(XPath::from_bytes(b"/")).unwrap();
assert_eq!(root.fd.as_raw_fd(), root_fd);
}
}