1004e86ffSlogin #![allow(dead_code)] 26d81180bSLoGin use core::{cmp::min, intrinsics::unlikely}; 391e9d4abSLoGin use system_error::SystemError; 4004e86ffSlogin 5004e86ffSlogin use crate::{ 6b087521eSChiichen driver::base::block::{block_device::LBA_SIZE, SeekFrom}, 7004e86ffSlogin kwarn, 8004e86ffSlogin libs::vec_cursor::VecCursor, 9004e86ffSlogin }; 106d81180bSLoGin use alloc::{ 116d81180bSLoGin string::{String, ToString}, 126d81180bSLoGin sync::Arc, 136d81180bSLoGin vec::Vec, 146d81180bSLoGin }; 15004e86ffSlogin 16004e86ffSlogin use super::{ 17004e86ffSlogin fs::{Cluster, FATFileSystem, MAX_FILE_SIZE}, 18004e86ffSlogin utils::decode_u8_ascii, 19004e86ffSlogin }; 20004e86ffSlogin 21004e86ffSlogin #[derive(Debug, Clone, Copy, Default)] 22004e86ffSlogin pub struct FileAttributes { 23004e86ffSlogin value: u8, 24004e86ffSlogin } 25004e86ffSlogin 26004e86ffSlogin /// FAT表中,关于每个簇的信息 27004e86ffSlogin #[derive(Debug, Eq, PartialEq)] 28004e86ffSlogin pub enum FATEntry { 29004e86ffSlogin /// 当前簇未使用 30004e86ffSlogin Unused, 31004e86ffSlogin /// 当前簇是坏簇 32004e86ffSlogin Bad, 33004e86ffSlogin /// 当前簇是整个FAT簇链的最后一个簇 34004e86ffSlogin EndOfChain, 35004e86ffSlogin /// 在整个链中,当前簇的下一个簇的值 36004e86ffSlogin Next(Cluster), 37004e86ffSlogin } 38004e86ffSlogin 39004e86ffSlogin /// FAT目录项的枚举类型 40004e86ffSlogin #[derive(Debug, Clone)] 41004e86ffSlogin pub enum FATDirEntry { 42004e86ffSlogin File(FATFile), 43004e86ffSlogin VolId(FATFile), 44004e86ffSlogin Dir(FATDir), 45004e86ffSlogin UnInit, 46004e86ffSlogin } 47004e86ffSlogin 48004e86ffSlogin /// FAT文件系统中的文件 49004e86ffSlogin #[derive(Debug, Default, Clone)] 50004e86ffSlogin pub struct FATFile { 51004e86ffSlogin /// 文件的第一个簇 52004e86ffSlogin pub first_cluster: Cluster, 53004e86ffSlogin /// 文件名 54004e86ffSlogin pub file_name: String, 55004e86ffSlogin /// 文件对应的短目录项 56004e86ffSlogin pub short_dir_entry: ShortDirEntry, 57004e86ffSlogin /// 文件目录项的起始、终止簇。格式:(簇,簇内偏移量) 58004e86ffSlogin pub loc: ((Cluster, u64), (Cluster, u64)), 59004e86ffSlogin } 60004e86ffSlogin 61004e86ffSlogin impl FATFile { 62004e86ffSlogin /// @brief 获取文件大小 63004e86ffSlogin #[inline] 64004e86ffSlogin pub fn size(&self) -> u64 { 65004e86ffSlogin return self.short_dir_entry.file_size as u64; 66004e86ffSlogin } 67004e86ffSlogin 68004e86ffSlogin /// @brief 设置当前文件大小(仅仅更改short_dir_entry内的值) 69004e86ffSlogin #[inline] 70004e86ffSlogin pub fn set_size(&mut self, size: u32) { 71004e86ffSlogin self.short_dir_entry.file_size = size; 72004e86ffSlogin } 73004e86ffSlogin 74004e86ffSlogin /// @brief 从文件读取数据。读取的字节数与buf长度相等 75004e86ffSlogin /// 76004e86ffSlogin /// @param buf 输出缓冲区 77004e86ffSlogin /// @param offset 起始位置在文件中的偏移量 78004e86ffSlogin /// 79004e86ffSlogin /// @return Ok(usize) 成功读取到的字节数 80676b8ef6SMork /// @return Err(SystemError) 读取时出现错误,返回错误码 8178bf93f0SYJwu2023 pub fn read( 8278bf93f0SYJwu2023 &self, 8378bf93f0SYJwu2023 fs: &Arc<FATFileSystem>, 8478bf93f0SYJwu2023 buf: &mut [u8], 8578bf93f0SYJwu2023 offset: u64, 8678bf93f0SYJwu2023 ) -> Result<usize, SystemError> { 87004e86ffSlogin if offset >= self.size() { 88004e86ffSlogin return Ok(0); 89004e86ffSlogin } 90004e86ffSlogin 91004e86ffSlogin // 文件内的簇偏移量 92004e86ffSlogin let start_cluster_number: u64 = offset / fs.bytes_per_cluster(); 93004e86ffSlogin // 计算对应在分区内的簇号 94004e86ffSlogin let mut current_cluster = if let Some(c) = 95004e86ffSlogin fs.get_cluster_by_relative(self.first_cluster, start_cluster_number as usize) 96004e86ffSlogin { 97004e86ffSlogin c 98004e86ffSlogin } else { 99004e86ffSlogin return Ok(0); 100004e86ffSlogin }; 101004e86ffSlogin 102004e86ffSlogin let bytes_remain: u64 = self.size() - offset; 103004e86ffSlogin 104004e86ffSlogin // 计算簇内偏移量 105004e86ffSlogin let mut in_cluster_offset: u64 = offset % fs.bytes_per_cluster(); 106004e86ffSlogin let to_read_size: usize = min(buf.len(), bytes_remain as usize); 107004e86ffSlogin 108004e86ffSlogin let mut start = 0; 109004e86ffSlogin let mut read_ok = 0; 110004e86ffSlogin 111004e86ffSlogin loop { 112004e86ffSlogin // 当前簇已经读取完,尝试读取下一个簇 113004e86ffSlogin if in_cluster_offset >= fs.bytes_per_cluster() { 114004e86ffSlogin if let Some(FATEntry::Next(c)) = fs.get_fat_entry(current_cluster).ok() { 115004e86ffSlogin current_cluster = c; 116004e86ffSlogin in_cluster_offset %= fs.bytes_per_cluster(); 117004e86ffSlogin } else { 118004e86ffSlogin break; 119004e86ffSlogin } 120004e86ffSlogin } 121004e86ffSlogin 122004e86ffSlogin // 计算下一次读取,能够读多少字节 123004e86ffSlogin let end_len: usize = min( 124004e86ffSlogin to_read_size - read_ok, 125004e86ffSlogin min( 126004e86ffSlogin (fs.bytes_per_cluster() - in_cluster_offset) as usize, 127004e86ffSlogin buf.len() - read_ok, 128004e86ffSlogin ), 129004e86ffSlogin ); 130004e86ffSlogin 131004e86ffSlogin // 从磁盘上读取数据 132004e86ffSlogin let offset = fs.cluster_bytes_offset(current_cluster) + in_cluster_offset; 133b087521eSChiichen let r = fs.partition.disk().read_at_bytes( 134004e86ffSlogin offset as usize, 135004e86ffSlogin end_len, 136004e86ffSlogin &mut buf[start..start + end_len], 137004e86ffSlogin )?; 138004e86ffSlogin 139004e86ffSlogin // 更新偏移量计数信息 140004e86ffSlogin read_ok += r; 141004e86ffSlogin start += r; 142004e86ffSlogin in_cluster_offset += r as u64; 143004e86ffSlogin if read_ok == to_read_size { 144004e86ffSlogin break; 145004e86ffSlogin } 146004e86ffSlogin } 147004e86ffSlogin // todo: 更新时间信息 148004e86ffSlogin return Ok(read_ok); 149004e86ffSlogin } 150004e86ffSlogin 151004e86ffSlogin /// @brief 向文件写入数据。写入的字节数与buf长度相等 152004e86ffSlogin /// 153004e86ffSlogin /// @param buf 输入缓冲区 154004e86ffSlogin /// @param offset 起始位置在文件中的偏移量 155004e86ffSlogin /// 156004e86ffSlogin /// @return Ok(usize) 成功写入的字节数 157676b8ef6SMork /// @return Err(SystemError) 写入时出现错误,返回错误码 158004e86ffSlogin pub fn write( 159004e86ffSlogin &mut self, 160004e86ffSlogin fs: &Arc<FATFileSystem>, 161004e86ffSlogin buf: &[u8], 162004e86ffSlogin offset: u64, 163676b8ef6SMork ) -> Result<usize, SystemError> { 164004e86ffSlogin self.ensure_len(fs, offset, buf.len() as u64)?; 165004e86ffSlogin 166004e86ffSlogin // 要写入的第一个簇的簇号 167004e86ffSlogin let start_cluster_num = offset / fs.bytes_per_cluster(); 168004e86ffSlogin // 获取要写入的第一个簇 169004e86ffSlogin let mut current_cluster: Cluster = if let Some(c) = 170004e86ffSlogin fs.get_cluster_by_relative(self.first_cluster, start_cluster_num as usize) 171004e86ffSlogin { 172004e86ffSlogin c 173004e86ffSlogin } else { 174004e86ffSlogin return Ok(0); 175004e86ffSlogin }; 176004e86ffSlogin 177004e86ffSlogin let mut in_cluster_bytes_offset: u64 = offset % fs.bytes_per_cluster(); 178004e86ffSlogin 179004e86ffSlogin let mut start: usize = 0; 180004e86ffSlogin let mut write_ok: usize = 0; 181004e86ffSlogin 182004e86ffSlogin // 循环写入数据 183004e86ffSlogin loop { 184004e86ffSlogin if in_cluster_bytes_offset >= fs.bytes_per_cluster() { 185004e86ffSlogin if let Some(FATEntry::Next(c)) = fs.get_fat_entry(current_cluster).ok() { 186004e86ffSlogin current_cluster = c; 187004e86ffSlogin in_cluster_bytes_offset = in_cluster_bytes_offset % fs.bytes_per_cluster(); 188004e86ffSlogin } else { 189004e86ffSlogin break; 190004e86ffSlogin } 191004e86ffSlogin } 192004e86ffSlogin 193004e86ffSlogin let end_len = min( 194004e86ffSlogin (fs.bytes_per_cluster() - in_cluster_bytes_offset) as usize, 195004e86ffSlogin buf.len() - write_ok, 196004e86ffSlogin ); 197004e86ffSlogin 198004e86ffSlogin // 计算本次写入位置在磁盘上的偏移量 199004e86ffSlogin let offset = fs.cluster_bytes_offset(current_cluster) + in_cluster_bytes_offset; 200004e86ffSlogin // 写入磁盘 2010facf623SLoGin let w: usize = fs.partition.disk().write_at_bytes( 202004e86ffSlogin offset as usize, 203004e86ffSlogin end_len, 204004e86ffSlogin &buf[start..start + end_len], 205004e86ffSlogin )?; 206004e86ffSlogin 207004e86ffSlogin // 更新偏移量数据 208004e86ffSlogin write_ok += w; 209004e86ffSlogin start += w; 210004e86ffSlogin in_cluster_bytes_offset += w as u64; 211004e86ffSlogin 212004e86ffSlogin if write_ok == buf.len() { 213004e86ffSlogin break; 214004e86ffSlogin } 215004e86ffSlogin } 216004e86ffSlogin // todo: 更新时间信息 217004e86ffSlogin return Ok(write_ok); 218004e86ffSlogin } 219004e86ffSlogin 220004e86ffSlogin /// @brief 确保文件从指定偏移量开始,仍有长度为len的空间。 221004e86ffSlogin /// 如果文件大小不够,就尝试分配更多的空间给这个文件。 222004e86ffSlogin /// 223004e86ffSlogin /// @param fs 当前文件所属的文件系统 224004e86ffSlogin /// @param offset 起始位置在文件内的字节偏移量 225004e86ffSlogin /// @param len 期待的空闲空间长度 226004e86ffSlogin /// 227004e86ffSlogin /// @return Ok(()) 经过操作后,offset后面具有长度至少为len的空闲空间 228676b8ef6SMork /// @return Err(SystemError) 处理过程中出现了异常。 22978bf93f0SYJwu2023 fn ensure_len( 23078bf93f0SYJwu2023 &mut self, 23178bf93f0SYJwu2023 fs: &Arc<FATFileSystem>, 23278bf93f0SYJwu2023 offset: u64, 23378bf93f0SYJwu2023 len: u64, 23478bf93f0SYJwu2023 ) -> Result<(), SystemError> { 235004e86ffSlogin // 文件内本身就还有空余的空间 236004e86ffSlogin if offset + len <= self.size() { 237004e86ffSlogin return Ok(()); 238004e86ffSlogin } 239004e86ffSlogin 2406d81180bSLoGin // 计算文件的最后一个簇中有多少空闲空间 2416d81180bSLoGin let in_cluster_offset = self.size() % fs.bytes_per_cluster(); 2426d81180bSLoGin let mut bytes_remain_in_cluster = if in_cluster_offset == 0 { 2436d81180bSLoGin 0 2446d81180bSLoGin } else { 2456d81180bSLoGin fs.bytes_per_cluster() - in_cluster_offset 2466d81180bSLoGin }; 2476d81180bSLoGin 2486d81180bSLoGin // 计算还需要申请多少空间 2496d81180bSLoGin let extra_bytes = min((offset + len) - self.size(), MAX_FILE_SIZE - self.size()); 2506d81180bSLoGin 251004e86ffSlogin // 如果文件大小为0,证明它还没有分配簇,因此分配一个簇给它 252004e86ffSlogin if self.size() == 0 { 253004e86ffSlogin // first_cluster应当为0,否则将产生空间泄露的错误 254004e86ffSlogin assert_eq!(self.first_cluster, Cluster::default()); 255004e86ffSlogin self.first_cluster = fs.allocate_cluster(None)?; 256004e86ffSlogin self.short_dir_entry.set_first_cluster(self.first_cluster); 2576d81180bSLoGin bytes_remain_in_cluster = fs.bytes_per_cluster(); 258004e86ffSlogin } 259004e86ffSlogin 260004e86ffSlogin // 如果还需要更多的簇 261004e86ffSlogin if bytes_remain_in_cluster < extra_bytes { 262004e86ffSlogin let clusters_to_allocate = 263004e86ffSlogin (extra_bytes - bytes_remain_in_cluster + fs.bytes_per_cluster() - 1) 264004e86ffSlogin / fs.bytes_per_cluster(); 265004e86ffSlogin let last_cluster = if let Some(c) = fs.get_last_cluster(self.first_cluster) { 266004e86ffSlogin c 267004e86ffSlogin } else { 268004e86ffSlogin kwarn!("FAT: last cluster not found, File = {self:?}"); 269676b8ef6SMork return Err(SystemError::EINVAL); 270004e86ffSlogin }; 271004e86ffSlogin // 申请簇 272004e86ffSlogin let mut current_cluster: Cluster = last_cluster; 273004e86ffSlogin for _ in 0..clusters_to_allocate { 274004e86ffSlogin current_cluster = fs.allocate_cluster(Some(current_cluster))?; 275004e86ffSlogin } 276004e86ffSlogin } 277004e86ffSlogin 278004e86ffSlogin // 如果文件被扩展,则清空刚刚被扩展的部分的数据 279004e86ffSlogin if offset > self.size() { 280004e86ffSlogin // 文件内的簇偏移 281004e86ffSlogin let start_cluster: u64 = self.size() / fs.bytes_per_cluster(); 282004e86ffSlogin let start_cluster: Cluster = fs 283004e86ffSlogin .get_cluster_by_relative(self.first_cluster, start_cluster as usize) 284004e86ffSlogin .unwrap(); 285004e86ffSlogin // 计算当前文件末尾在磁盘上的字节偏移量 286004e86ffSlogin let start_offset: u64 = 287004e86ffSlogin fs.cluster_bytes_offset(start_cluster) + self.size() % fs.bytes_per_cluster(); 288004e86ffSlogin // 扩展之前,最后一个簇内还剩下多少字节的空间 289004e86ffSlogin let bytes_remain: u64 = fs.bytes_per_cluster() - (self.size() % fs.bytes_per_cluster()); 290004e86ffSlogin // 计算在扩展之后的最后一个簇内,文件的终止字节 291004e86ffSlogin let cluster_offset_start = offset / fs.bytes_per_cluster(); 292004e86ffSlogin // 扩展后,文件的最后 293004e86ffSlogin let end_cluster: Cluster = fs 294004e86ffSlogin .get_cluster_by_relative(self.first_cluster, cluster_offset_start as usize) 295004e86ffSlogin .unwrap(); 296004e86ffSlogin 297004e86ffSlogin if start_cluster != end_cluster { 298004e86ffSlogin self.zero_range(fs, start_offset, start_offset + bytes_remain)?; 299004e86ffSlogin } else { 300004e86ffSlogin self.zero_range(fs, start_offset, start_offset + offset - self.size())?; 301004e86ffSlogin } 302004e86ffSlogin } 303004e86ffSlogin // 计算文件的新大小 304004e86ffSlogin let new_size = self.size() + extra_bytes; 305004e86ffSlogin self.set_size(new_size as u32); 306004e86ffSlogin // 计算短目录项所在的位置,更新短目录项 307004e86ffSlogin let short_entry_offset = fs.cluster_bytes_offset(self.loc.1 .0) + self.loc.1 .1; 308004e86ffSlogin // todo: 更新时间信息 309004e86ffSlogin // 把短目录项写入磁盘 310004e86ffSlogin self.short_dir_entry.flush(fs, short_entry_offset)?; 311004e86ffSlogin return Ok(()); 312004e86ffSlogin } 313004e86ffSlogin 314004e86ffSlogin /// @brief 把磁盘上[range_start, range_end)范围的数据清零 315004e86ffSlogin /// 316004e86ffSlogin /// @param range_start 磁盘上起始位置(单位:字节) 317004e86ffSlogin /// @param range_end 磁盘上终止位置(单位:字节) 318004e86ffSlogin fn zero_range( 319004e86ffSlogin &self, 320004e86ffSlogin fs: &Arc<FATFileSystem>, 321004e86ffSlogin range_start: u64, 322004e86ffSlogin range_end: u64, 323676b8ef6SMork ) -> Result<(), SystemError> { 324004e86ffSlogin if range_end <= range_start { 325004e86ffSlogin return Ok(()); 326004e86ffSlogin } 327004e86ffSlogin 328004e86ffSlogin let zeroes: Vec<u8> = vec![0u8; (range_end - range_start) as usize]; 329b087521eSChiichen fs.partition 330b087521eSChiichen .disk() 331b087521eSChiichen .write_at(range_start as usize, zeroes.len(), zeroes.as_slice())?; 332004e86ffSlogin return Ok(()); 333004e86ffSlogin } 334004e86ffSlogin 335004e86ffSlogin /// @brief 截断文件的内容,并设置新的文件大小。如果new_size大于当前文件大小,则不做操作。 336004e86ffSlogin /// 337004e86ffSlogin /// @param new_size 新的文件大小,如果它大于当前文件大小,则不做操作。 338004e86ffSlogin /// 339004e86ffSlogin /// @return Ok(()) 操作成功 340676b8ef6SMork /// @return Err(SystemError) 在操作时出现错误 341676b8ef6SMork pub fn truncate(&mut self, fs: &Arc<FATFileSystem>, new_size: u64) -> Result<(), SystemError> { 342004e86ffSlogin if new_size >= self.size() { 343004e86ffSlogin return Ok(()); 344004e86ffSlogin } 345004e86ffSlogin 3466d81180bSLoGin let new_last_cluster = (new_size + fs.bytes_per_cluster() - 1) / fs.bytes_per_cluster(); 347004e86ffSlogin if let Some(begin_delete) = 3486d81180bSLoGin fs.get_cluster_by_relative(self.first_cluster, new_last_cluster as usize) 349004e86ffSlogin { 3506d81180bSLoGin fs.deallocate_cluster_chain(begin_delete)?; 351004e86ffSlogin }; 352004e86ffSlogin 3536d81180bSLoGin if new_size == 0 { 3546d81180bSLoGin assert!(new_last_cluster == 0); 3556d81180bSLoGin self.short_dir_entry.set_first_cluster(Cluster::new(0)); 3566d81180bSLoGin self.first_cluster = Cluster::new(0); 3576d81180bSLoGin } 3586d81180bSLoGin 359004e86ffSlogin self.set_size(new_size as u32); 360004e86ffSlogin // 计算短目录项在磁盘内的字节偏移量 361004e86ffSlogin let short_entry_offset = fs.cluster_bytes_offset((self.loc.1).0) + (self.loc.1).1; 362004e86ffSlogin self.short_dir_entry.flush(fs, short_entry_offset)?; 3636d81180bSLoGin 364004e86ffSlogin return Ok(()); 365004e86ffSlogin } 366004e86ffSlogin } 367004e86ffSlogin 368004e86ffSlogin /// FAT文件系统中的文件夹 369004e86ffSlogin #[derive(Debug, Default, Clone)] 370004e86ffSlogin pub struct FATDir { 371004e86ffSlogin /// 目录的第一个簇 372004e86ffSlogin pub first_cluster: Cluster, 373004e86ffSlogin /// 该字段仅对FAT12、FAT16生效 374004e86ffSlogin pub root_offset: Option<u64>, 375004e86ffSlogin /// 文件夹名称 376004e86ffSlogin pub dir_name: String, 377004e86ffSlogin pub short_dir_entry: Option<ShortDirEntry>, 378004e86ffSlogin /// 文件的起始、终止簇。格式:(簇,簇内偏移量) 379004e86ffSlogin pub loc: Option<((Cluster, u64), (Cluster, u64))>, 380004e86ffSlogin } 381004e86ffSlogin 382004e86ffSlogin impl FATDir { 383004e86ffSlogin /// @brief 获得用于遍历当前目录的迭代器 384004e86ffSlogin /// 385004e86ffSlogin /// @param fs 当前目录所在的文件系统 386004e86ffSlogin pub fn to_iter(&self, fs: Arc<FATFileSystem>) -> FATDirIter { 387004e86ffSlogin return FATDirIter { 388004e86ffSlogin current_cluster: self.first_cluster, 389004e86ffSlogin offset: self.root_offset.unwrap_or(0), 390004e86ffSlogin is_root: self.is_root(), 391004e86ffSlogin fs: fs, 392004e86ffSlogin }; 393004e86ffSlogin } 394004e86ffSlogin 395004e86ffSlogin /// @brief 判断当前目录是否为根目录(仅对FAT12和FAT16生效) 396004e86ffSlogin #[inline] 397004e86ffSlogin pub fn is_root(&self) -> bool { 398004e86ffSlogin return self.root_offset.is_some(); 399004e86ffSlogin } 400004e86ffSlogin 401004e86ffSlogin /// @brief 获取当前目录所占用的大小 402004e86ffSlogin pub fn size(&self, fs: &Arc<FATFileSystem>) -> u64 { 403004e86ffSlogin return fs.num_clusters_chain(self.first_cluster) * fs.bytes_per_cluster(); 404004e86ffSlogin } 405004e86ffSlogin 406004e86ffSlogin /// @brief 在目录项中,寻找num_free个连续空闲目录项 407004e86ffSlogin /// 408004e86ffSlogin /// @param num_free 需要的空闲目录项数目. 409004e86ffSlogin /// @param fs 当前文件夹属于的文件系统 410004e86ffSlogin /// 411004e86ffSlogin /// @return Ok(Option<(第一个符合条件的空闲目录项所在的簇,簇内偏移量)) 412004e86ffSlogin /// @return Err(错误码) 413004e86ffSlogin pub fn find_free_entries( 414004e86ffSlogin &self, 415004e86ffSlogin num_free: u64, 416004e86ffSlogin fs: Arc<FATFileSystem>, 417676b8ef6SMork ) -> Result<Option<(Cluster, u64)>, SystemError> { 418004e86ffSlogin let mut free = 0; 419004e86ffSlogin let mut current_cluster: Cluster = self.first_cluster; 420004e86ffSlogin let mut offset = self.root_offset.unwrap_or(0); 421004e86ffSlogin // 第一个符合条件的空闲目录项 422004e86ffSlogin let mut first_free: Option<(Cluster, u64)> = None; 423004e86ffSlogin 424004e86ffSlogin loop { 425004e86ffSlogin // 如果当前簇没有空间了,并且当前不是FAT12和FAT16的根目录,那么就读取下一个簇。 426004e86ffSlogin if offset >= fs.bytes_per_cluster() && !self.is_root() { 427004e86ffSlogin // 成功读取下一个簇 428004e86ffSlogin if let Some(FATEntry::Next(c)) = fs.get_fat_entry(current_cluster).ok() { 429004e86ffSlogin current_cluster = c; 430004e86ffSlogin // 计算簇内偏移量 431004e86ffSlogin offset = offset % fs.bytes_per_cluster(); 432004e86ffSlogin } else { 433004e86ffSlogin // 读取失败,当前已经是最后一个簇,退出循环 434004e86ffSlogin break; 435004e86ffSlogin } 436004e86ffSlogin } 437004e86ffSlogin // 如果当前目录是FAT12和FAT16的根目录,且已经读取完,就直接返回。 438004e86ffSlogin if self.is_root() && offset > fs.root_dir_end_bytes_offset().unwrap() { 439004e86ffSlogin return Ok(None); 440004e86ffSlogin } 441004e86ffSlogin 442004e86ffSlogin let e_offset = fs.cluster_bytes_offset(current_cluster) + offset; 443004e86ffSlogin let entry: FATRawDirEntry = get_raw_dir_entry(&fs, e_offset)?; 444004e86ffSlogin 445004e86ffSlogin match entry { 446004e86ffSlogin FATRawDirEntry::Free | FATRawDirEntry::FreeRest => { 447004e86ffSlogin if free == 0 { 448004e86ffSlogin first_free = Some((current_cluster, offset)); 449004e86ffSlogin } 450004e86ffSlogin 451004e86ffSlogin free += 1; 452004e86ffSlogin if free == num_free { 453004e86ffSlogin // kdebug!("first_free = {first_free:?}, current_free = ({current_cluster:?}, {offset})"); 454004e86ffSlogin return Ok(first_free); 455004e86ffSlogin } 456004e86ffSlogin } 457004e86ffSlogin 458004e86ffSlogin // 遇到一个不空闲的目录项,那么重新开始计算空闲目录项 459004e86ffSlogin _ => { 460004e86ffSlogin free = 0; 461004e86ffSlogin } 462004e86ffSlogin } 463004e86ffSlogin offset += FATRawDirEntry::DIR_ENTRY_LEN; 464004e86ffSlogin } 465004e86ffSlogin 466004e86ffSlogin // 剩余的需要获取的目录项 467004e86ffSlogin let remain_entries = num_free - free; 468004e86ffSlogin 469004e86ffSlogin // 计算需要申请多少个簇 470004e86ffSlogin let clusters_required = 471004e86ffSlogin (remain_entries * FATRawDirEntry::DIR_ENTRY_LEN + fs.bytes_per_cluster() - 1) 472004e86ffSlogin / fs.bytes_per_cluster(); 473004e86ffSlogin let mut first_cluster = Cluster::default(); 474004e86ffSlogin let mut prev_cluster = current_cluster; 475004e86ffSlogin // kdebug!( 476004e86ffSlogin // "clusters_required={clusters_required}, prev_cluster={prev_cluster:?}, free ={free}" 477004e86ffSlogin // ); 478004e86ffSlogin // 申请簇 479004e86ffSlogin for i in 0..clusters_required { 480004e86ffSlogin let c: Cluster = fs.allocate_cluster(Some(prev_cluster))?; 481004e86ffSlogin if i == 0 { 482004e86ffSlogin first_cluster = c; 483004e86ffSlogin } 484004e86ffSlogin 485004e86ffSlogin prev_cluster = c; 486004e86ffSlogin } 487004e86ffSlogin 488004e86ffSlogin if free > 0 { 489004e86ffSlogin // 空闲目录项跨越了簇,返回第一个空闲目录项 490004e86ffSlogin return Ok(first_free); 491004e86ffSlogin } else { 492004e86ffSlogin // 空闲目录项是在全新的簇开始的 493004e86ffSlogin return Ok(Some((first_cluster, 0))); 494004e86ffSlogin } 495004e86ffSlogin } 496004e86ffSlogin 497004e86ffSlogin /// @brief 在当前目录中寻找目录项 498004e86ffSlogin /// 499004e86ffSlogin /// @param name 目录项的名字 500004e86ffSlogin /// @param expect_dir 该值为Some时有效。如果期待目标目录项是文件夹,那么值为Some(true), 否则为Some(false). 501004e86ffSlogin /// @param short_name_gen 短目录项名称生成器 502004e86ffSlogin /// @param fs 当前目录所属的文件系统 503004e86ffSlogin /// 504004e86ffSlogin /// @return Ok(FATDirEntry) 找到期待的目录项 505676b8ef6SMork /// @return Err(SystemError) 错误码 506004e86ffSlogin pub fn find_entry( 507004e86ffSlogin &self, 508004e86ffSlogin name: &str, 509004e86ffSlogin expect_dir: Option<bool>, 510004e86ffSlogin mut short_name_gen: Option<&mut ShortNameGenerator>, 511004e86ffSlogin fs: Arc<FATFileSystem>, 512676b8ef6SMork ) -> Result<FATDirEntry, SystemError> { 513004e86ffSlogin LongDirEntry::validate_long_name(name)?; 514004e86ffSlogin // 迭代当前目录下的文件/文件夹 515004e86ffSlogin for e in self.to_iter(fs) { 516004e86ffSlogin if e.eq_name(name) { 517004e86ffSlogin if expect_dir.is_some() && Some(e.is_dir()) != expect_dir { 518004e86ffSlogin if e.is_dir() { 519004e86ffSlogin // 期望得到文件,但是是文件夹 520676b8ef6SMork return Err(SystemError::EISDIR); 521004e86ffSlogin } else { 522004e86ffSlogin // 期望得到文件夹,但是是文件 523676b8ef6SMork return Err(SystemError::ENOTDIR); 524004e86ffSlogin } 525004e86ffSlogin } 526004e86ffSlogin // 找到期望的目录项 527004e86ffSlogin return Ok(e); 528004e86ffSlogin } 529004e86ffSlogin 530004e86ffSlogin if let Some(ref mut sng) = short_name_gen { 531004e86ffSlogin sng.add_name(&e.short_name_raw()) 532004e86ffSlogin } 533004e86ffSlogin } 534004e86ffSlogin // 找不到文件/文件夹 535676b8ef6SMork return Err(SystemError::ENOENT); 536004e86ffSlogin } 537004e86ffSlogin 538004e86ffSlogin /// @brief 在当前目录下打开文件,获取FATFile结构体 539676b8ef6SMork pub fn open_file(&self, name: &str, fs: Arc<FATFileSystem>) -> Result<FATFile, SystemError> { 540004e86ffSlogin let f: FATFile = self.find_entry(name, Some(false), None, fs)?.to_file()?; 541004e86ffSlogin return Ok(f); 542004e86ffSlogin } 543004e86ffSlogin 544004e86ffSlogin /// @brief 在当前目录下打开文件夹,获取FATDir结构体 545676b8ef6SMork pub fn open_dir(&self, name: &str, fs: Arc<FATFileSystem>) -> Result<FATDir, SystemError> { 546004e86ffSlogin let d: FATDir = self.find_entry(name, Some(true), None, fs)?.to_dir()?; 547004e86ffSlogin return Ok(d); 548004e86ffSlogin } 549004e86ffSlogin 550004e86ffSlogin /// @brief 在当前文件夹下创建文件。 551004e86ffSlogin /// 552004e86ffSlogin /// @param name 文件名 553004e86ffSlogin /// @param fs 当前文件夹所属的文件系统 554676b8ef6SMork pub fn create_file(&self, name: &str, fs: &Arc<FATFileSystem>) -> Result<FATFile, SystemError> { 555676b8ef6SMork let r: Result<FATDirEntryOrShortName, SystemError> = 556004e86ffSlogin self.check_existence(name, Some(false), fs.clone()); 557004e86ffSlogin // 检查错误码,如果能够表明目录项已经存在,则返回-EEXIST 558004e86ffSlogin if r.is_err() { 559004e86ffSlogin let err_val = r.unwrap_err(); 560676b8ef6SMork if err_val == (SystemError::EISDIR) || err_val == (SystemError::ENOTDIR) { 561676b8ef6SMork return Err(SystemError::EEXIST); 562004e86ffSlogin } else { 563004e86ffSlogin return Err(err_val); 564004e86ffSlogin } 565004e86ffSlogin } 566004e86ffSlogin 567004e86ffSlogin match r.unwrap() { 568004e86ffSlogin FATDirEntryOrShortName::ShortName(short_name) => { 569004e86ffSlogin // 确认名称是一个可行的长文件名 570004e86ffSlogin LongDirEntry::validate_long_name(name)?; 571004e86ffSlogin // 创建目录项 572676b8ef6SMork let x: Result<FATFile, SystemError> = self 573004e86ffSlogin .create_dir_entries( 574004e86ffSlogin name.trim(), 575004e86ffSlogin &short_name, 576004e86ffSlogin None, 577004e86ffSlogin FileAttributes { 578004e86ffSlogin value: FileAttributes::ARCHIVE, 579004e86ffSlogin }, 580004e86ffSlogin fs.clone(), 581004e86ffSlogin ) 582004e86ffSlogin .map(|e| e.to_file())?; 583004e86ffSlogin return x; 584004e86ffSlogin } 585004e86ffSlogin 586004e86ffSlogin FATDirEntryOrShortName::DirEntry(_) => { 587004e86ffSlogin // 已经存在这样的一个目录项了 588676b8ef6SMork return Err(SystemError::EEXIST); 589004e86ffSlogin } 590004e86ffSlogin } 591004e86ffSlogin } 592004e86ffSlogin 593676b8ef6SMork pub fn create_dir(&self, name: &str, fs: &Arc<FATFileSystem>) -> Result<FATDir, SystemError> { 594676b8ef6SMork let r: Result<FATDirEntryOrShortName, SystemError> = 595004e86ffSlogin self.check_existence(name, Some(true), fs.clone()); 596004e86ffSlogin // kdebug!("check existence ok"); 597004e86ffSlogin // 检查错误码,如果能够表明目录项已经存在,则返回-EEXIST 598004e86ffSlogin if r.is_err() { 599004e86ffSlogin let err_val = r.unwrap_err(); 600676b8ef6SMork if err_val == (SystemError::EISDIR) || err_val == (SystemError::ENOTDIR) { 601676b8ef6SMork return Err(SystemError::EEXIST); 602004e86ffSlogin } else { 603004e86ffSlogin return Err(err_val); 604004e86ffSlogin } 605004e86ffSlogin } 606004e86ffSlogin 607004e86ffSlogin match r.unwrap() { 608004e86ffSlogin // 文件夹不存在,创建文件夹 609004e86ffSlogin FATDirEntryOrShortName::ShortName(short_name) => { 610004e86ffSlogin LongDirEntry::validate_long_name(name)?; 611004e86ffSlogin // 目标目录项 612004e86ffSlogin let mut short_entry = ShortDirEntry::default(); 613b087521eSChiichen 614004e86ffSlogin let first_cluster: Cluster = fs.allocate_cluster(None)?; 615004e86ffSlogin short_entry.set_first_cluster(first_cluster); 616004e86ffSlogin 617004e86ffSlogin // === 接下来在子目录中创建'.'目录项和'..'目录项 618004e86ffSlogin let mut offset = 0; 619004e86ffSlogin // '.'目录项 620004e86ffSlogin let mut dot_entry = ShortDirEntry::default(); 621004e86ffSlogin dot_entry.name = ShortNameGenerator::new(".").generate().unwrap(); 622004e86ffSlogin dot_entry.attributes.value = FileAttributes::DIRECTORY; 623004e86ffSlogin dot_entry.set_first_cluster(first_cluster); 624004e86ffSlogin 625004e86ffSlogin // todo: 设置创建、访问时间 626004e86ffSlogin dot_entry.flush(&fs, fs.cluster_bytes_offset(first_cluster) + offset)?; 627004e86ffSlogin 628004e86ffSlogin // 偏移量加上一个目录项的长度 629004e86ffSlogin offset += FATRawDirEntry::DIR_ENTRY_LEN; 630004e86ffSlogin 631004e86ffSlogin // '..'目录项 632004e86ffSlogin let mut dot_dot_entry = ShortDirEntry::default(); 633004e86ffSlogin dot_dot_entry.name = ShortNameGenerator::new("..").generate().unwrap(); 634004e86ffSlogin dot_dot_entry.attributes.value = FileAttributes::DIRECTORY; 635004e86ffSlogin dot_dot_entry.set_first_cluster(self.first_cluster); 636004e86ffSlogin // todo: 设置创建、访问时间 637004e86ffSlogin 638004e86ffSlogin dot_dot_entry.flush(&fs, fs.cluster_bytes_offset(first_cluster) + offset)?; 639004e86ffSlogin 640004e86ffSlogin // kdebug!("to create dentries"); 641004e86ffSlogin // 在当前目录下创建目标目录项 642004e86ffSlogin let res = self 643004e86ffSlogin .create_dir_entries( 644004e86ffSlogin name.trim(), 645004e86ffSlogin &short_name, 646004e86ffSlogin Some(short_entry), 647004e86ffSlogin FileAttributes { 648004e86ffSlogin value: FileAttributes::DIRECTORY, 649004e86ffSlogin }, 650004e86ffSlogin fs.clone(), 651004e86ffSlogin ) 652004e86ffSlogin .map(|e| e.to_dir())?; 653004e86ffSlogin // kdebug!("create dentries ok"); 654004e86ffSlogin return res; 655004e86ffSlogin } 656004e86ffSlogin FATDirEntryOrShortName::DirEntry(_) => { 657004e86ffSlogin // 已经存在这样的一个目录项了 658676b8ef6SMork return Err(SystemError::EEXIST); 659004e86ffSlogin } 660004e86ffSlogin } 661004e86ffSlogin } 662004e86ffSlogin /// @brief 检查目录项在当前文件夹下是否存在 663004e86ffSlogin /// 664004e86ffSlogin /// @param name 目录项的名字 665004e86ffSlogin /// @param expect_dir 该值为Some时有效。如果期待目标目录项是文件夹,那么值为Some(true), 否则为Some(false). 666004e86ffSlogin /// @param fs 当前目录所属的文件系统 667004e86ffSlogin /// 668004e86ffSlogin /// @return Ok(FATDirEntryOrShortName::DirEntry) 找到期待的目录项 669004e86ffSlogin /// @return Ok(FATDirEntryOrShortName::ShortName) 当前文件夹下不存在指定的目录项,因此返回一个可行的短文件名 670676b8ef6SMork /// @return Err(SystemError) 错误码 671004e86ffSlogin pub fn check_existence( 672004e86ffSlogin &self, 673004e86ffSlogin name: &str, 674004e86ffSlogin expect_dir: Option<bool>, 675004e86ffSlogin fs: Arc<FATFileSystem>, 676676b8ef6SMork ) -> Result<FATDirEntryOrShortName, SystemError> { 677004e86ffSlogin let mut sng = ShortNameGenerator::new(name); 678004e86ffSlogin 679004e86ffSlogin loop { 680676b8ef6SMork let e: Result<FATDirEntry, SystemError> = 681004e86ffSlogin self.find_entry(name, expect_dir, Some(&mut sng), fs.clone()); 682004e86ffSlogin match e { 683004e86ffSlogin Ok(e) => { 684004e86ffSlogin // 找到,返回目录项 685004e86ffSlogin return Ok(FATDirEntryOrShortName::DirEntry(e)); 686004e86ffSlogin } 687004e86ffSlogin Err(e) => { 688004e86ffSlogin // 如果没找到,则不返回错误 689676b8ef6SMork if e == SystemError::ENOENT { 690004e86ffSlogin } else { 691004e86ffSlogin // 其他错误,则返回 692004e86ffSlogin return Err(e); 693004e86ffSlogin } 694004e86ffSlogin } 695004e86ffSlogin } 696004e86ffSlogin 697004e86ffSlogin // 没找到文件,则生成短文件名 698004e86ffSlogin if let Ok(name) = sng.generate() { 699004e86ffSlogin return Ok(FATDirEntryOrShortName::ShortName(name)); 700004e86ffSlogin } 701004e86ffSlogin 702004e86ffSlogin sng.next_iteration(); 703004e86ffSlogin } 704004e86ffSlogin } 705004e86ffSlogin 706004e86ffSlogin /// @brief 创建一系列的目录项 707004e86ffSlogin /// 708004e86ffSlogin /// @param long_name 长文件名 709004e86ffSlogin /// @param short_name 短文件名 710004e86ffSlogin /// @param short_dentry 可选的生成好的短目录项结构体 711004e86ffSlogin /// @param attrs FAT目录项的属性 712004e86ffSlogin /// @param fs 当前文件夹所属的文件系统 713004e86ffSlogin /// 714004e86ffSlogin /// @return Ok(FATDirEntry) FAT目录项的枚举类型(目录项链条的最后一个长目录项) 715004e86ffSlogin fn create_dir_entries( 716004e86ffSlogin &self, 717004e86ffSlogin long_name: &str, 718004e86ffSlogin short_name: &[u8; 11], 719004e86ffSlogin short_dentry: Option<ShortDirEntry>, 720004e86ffSlogin attrs: FileAttributes, 721004e86ffSlogin fs: Arc<FATFileSystem>, 722676b8ef6SMork ) -> Result<FATDirEntry, SystemError> { 723004e86ffSlogin let mut short_dentry: ShortDirEntry = short_dentry.unwrap_or(ShortDirEntry::default()); 724004e86ffSlogin short_dentry.name = short_name.clone(); 725004e86ffSlogin short_dentry.attributes = attrs; 726004e86ffSlogin 727004e86ffSlogin // todo: 设置创建时间、修改时间 728004e86ffSlogin 729004e86ffSlogin let mut long_name_gen: LongNameEntryGenerator = 730004e86ffSlogin LongNameEntryGenerator::new(long_name, short_dentry.checksum()); 731004e86ffSlogin let num_entries = long_name_gen.num_entries() as u64; 732004e86ffSlogin 733004e86ffSlogin // kdebug!("to find free entries"); 734004e86ffSlogin let free_entries: Option<(Cluster, u64)> = 735004e86ffSlogin self.find_free_entries(num_entries, fs.clone())?; 736004e86ffSlogin // 目录项开始位置 737004e86ffSlogin let start_loc: (Cluster, u64) = match free_entries { 738004e86ffSlogin Some(c) => c, 739676b8ef6SMork None => return Err(SystemError::ENOSPC), 740004e86ffSlogin }; 741004e86ffSlogin let offsets: Vec<(Cluster, u64)> = 742004e86ffSlogin FATDirEntryOffsetIter::new(fs.clone(), start_loc, num_entries, None).collect(); 743004e86ffSlogin 744004e86ffSlogin // 迭代长目录项 745004e86ffSlogin for off in &offsets.as_slice()[..offsets.len() - 1] { 746004e86ffSlogin // 获取生成的下一个长目录项 747004e86ffSlogin let long_entry: LongDirEntry = long_name_gen.next().unwrap(); 748004e86ffSlogin // 获取这个长目录项在磁盘内的字节偏移量 749004e86ffSlogin let bytes_offset = fs.cluster_bytes_offset(off.0) + off.1; 750004e86ffSlogin long_entry.flush(fs.clone(), bytes_offset)?; 751004e86ffSlogin } 752004e86ffSlogin 753004e86ffSlogin let start: (Cluster, u64) = offsets[0]; 754004e86ffSlogin let end: (Cluster, u64) = *offsets.last().unwrap(); 755004e86ffSlogin // 短目录项在磁盘上的字节偏移量 756004e86ffSlogin let offset = fs.cluster_bytes_offset(end.0) + end.1; 757004e86ffSlogin short_dentry.flush(&fs, offset)?; 758004e86ffSlogin 759004e86ffSlogin return Ok(short_dentry.to_dir_entry_with_long_name(long_name.to_string(), (start, end))); 760004e86ffSlogin } 761004e86ffSlogin 762004e86ffSlogin /// @brief 判断当前目录是否为空 763004e86ffSlogin /// 764004e86ffSlogin /// @return true 当前目录为空 765004e86ffSlogin /// @return false 当前目录不为空 766004e86ffSlogin pub fn is_empty(&self, fs: Arc<FATFileSystem>) -> bool { 767004e86ffSlogin for e in self.to_iter(fs) { 768004e86ffSlogin let s = e.short_name(); 769004e86ffSlogin if s == "." || s == ".." { 770004e86ffSlogin continue; 771004e86ffSlogin } else { 772004e86ffSlogin return false; 773004e86ffSlogin } 774004e86ffSlogin } 775004e86ffSlogin return true; 776004e86ffSlogin } 777004e86ffSlogin 778004e86ffSlogin /// @brief 从当前文件夹中删除文件或者文件夹。如果目标文件夹不为空,则不能删除,返回-ENOTEMPTY. 779004e86ffSlogin /// 780004e86ffSlogin /// @param fs 当前FATDir所属的文件系统 781004e86ffSlogin /// @param name 目录项的名字 782004e86ffSlogin /// @param remove_clusters 是否删除与指定的目录项相关联的数据簇 783004e86ffSlogin /// 784004e86ffSlogin /// @return Ok() 成功时无返回值 785676b8ef6SMork /// @return Err(SystemError) 如果目标文件夹不为空,则不能删除,返回-ENOTEMPTY. 或者返回底层传上来的错误 786004e86ffSlogin pub fn remove( 787004e86ffSlogin &self, 788004e86ffSlogin fs: Arc<FATFileSystem>, 789004e86ffSlogin name: &str, 790004e86ffSlogin remove_clusters: bool, 791676b8ef6SMork ) -> Result<(), SystemError> { 792004e86ffSlogin let e: FATDirEntry = self.find_entry(name, None, None, fs.clone())?; 793004e86ffSlogin 794004e86ffSlogin // 判断文件夹是否为空,如果空,则不删除,报错。 795004e86ffSlogin if e.is_dir() && !(e.to_dir().unwrap().is_empty(fs.clone())) { 796676b8ef6SMork return Err(SystemError::ENOTEMPTY); 797004e86ffSlogin } 798004e86ffSlogin 799004e86ffSlogin if e.first_cluster().cluster_num >= 2 && remove_clusters { 800004e86ffSlogin // 删除与指定的目录项相关联的数据簇 801004e86ffSlogin fs.deallocate_cluster_chain(e.first_cluster())?; 802004e86ffSlogin } 803004e86ffSlogin 804004e86ffSlogin if e.get_dir_range().is_some() { 805004e86ffSlogin self.remove_dir_entries(fs, e.get_dir_range().unwrap())?; 806004e86ffSlogin } 807004e86ffSlogin 808004e86ffSlogin return Ok(()); 809004e86ffSlogin } 810004e86ffSlogin 811004e86ffSlogin /// @brief 在当前目录中删除多个目录项 812004e86ffSlogin /// 813004e86ffSlogin /// @param fs 当前目录所属的文件系统 814004e86ffSlogin /// @param cluster_range 要删除的目录项的范围(以簇+簇内偏移量的形式表示) 815004e86ffSlogin fn remove_dir_entries( 816004e86ffSlogin &self, 817004e86ffSlogin fs: Arc<FATFileSystem>, 818004e86ffSlogin cluster_range: ((Cluster, u64), (Cluster, u64)), 819676b8ef6SMork ) -> Result<(), SystemError> { 820004e86ffSlogin // 收集所有的要移除的目录项 821004e86ffSlogin let offsets: Vec<(Cluster, u64)> = 822004e86ffSlogin FATDirEntryOffsetIter::new(fs.clone(), cluster_range.0, 15, Some(cluster_range.1)) 823004e86ffSlogin .collect(); 824004e86ffSlogin // 逐个设置这些目录项为“空闲”状态 825004e86ffSlogin for off in offsets { 826004e86ffSlogin let disk_bytes_offset = fs.cluster_bytes_offset(off.0) + off.1; 827004e86ffSlogin let mut short_entry = ShortDirEntry::default(); 828004e86ffSlogin short_entry.name[0] = 0xe5; 829004e86ffSlogin short_entry.flush(&fs, disk_bytes_offset)?; 830004e86ffSlogin } 831004e86ffSlogin return Ok(()); 832004e86ffSlogin } 833004e86ffSlogin 834004e86ffSlogin /// @brief 根据名字在当前文件夹下寻找目录项 835004e86ffSlogin /// 836004e86ffSlogin /// @return Ok(FATDirEntry) 目标目录项 837676b8ef6SMork /// @return Err(SystemError) 底层传上来的错误码 83878bf93f0SYJwu2023 pub fn get_dir_entry( 83978bf93f0SYJwu2023 &self, 84078bf93f0SYJwu2023 fs: Arc<FATFileSystem>, 84178bf93f0SYJwu2023 name: &str, 84278bf93f0SYJwu2023 ) -> Result<FATDirEntry, SystemError> { 843004e86ffSlogin if name == "." || name == "/" { 844004e86ffSlogin return Ok(FATDirEntry::Dir(self.clone())); 845004e86ffSlogin } 846004e86ffSlogin 847004e86ffSlogin LongDirEntry::validate_long_name(name)?; 848004e86ffSlogin return self.find_entry(name, None, None, fs); 849004e86ffSlogin } 850004e86ffSlogin 851004e86ffSlogin /// @brief 在当前目录内,重命名一个目录项 852004e86ffSlogin /// 853004e86ffSlogin pub fn rename( 854004e86ffSlogin &self, 855004e86ffSlogin fs: Arc<FATFileSystem>, 856004e86ffSlogin old_name: &str, 857004e86ffSlogin new_name: &str, 858676b8ef6SMork ) -> Result<FATDirEntry, SystemError> { 859004e86ffSlogin // 判断源目录项是否存在 860004e86ffSlogin let old_dentry: FATDirEntry = if let FATDirEntryOrShortName::DirEntry(dentry) = 861004e86ffSlogin self.check_existence(old_name, None, fs.clone())? 862004e86ffSlogin { 863004e86ffSlogin dentry 864004e86ffSlogin } else { 865004e86ffSlogin // 如果目标目录项不存在,则返回错误 866676b8ef6SMork return Err(SystemError::ENOENT); 867004e86ffSlogin }; 868004e86ffSlogin 869004e86ffSlogin let short_name = if let FATDirEntryOrShortName::ShortName(s) = 870004e86ffSlogin self.check_existence(new_name, None, fs.clone())? 871004e86ffSlogin { 872004e86ffSlogin s 873004e86ffSlogin } else { 874004e86ffSlogin // 如果目标目录项存在,那么就返回错误 875676b8ef6SMork return Err(SystemError::EEXIST); 876004e86ffSlogin }; 877004e86ffSlogin 878004e86ffSlogin let old_short_dentry: Option<ShortDirEntry> = old_dentry.short_dir_entry(); 879004e86ffSlogin if let Some(se) = old_short_dentry { 880004e86ffSlogin // 删除原来的目录项 881004e86ffSlogin self.remove(fs.clone(), old_dentry.name().as_str(), false)?; 882004e86ffSlogin 883004e86ffSlogin // 创建新的目录项 884004e86ffSlogin let new_dentry: FATDirEntry = self.create_dir_entries( 885004e86ffSlogin new_name, 886004e86ffSlogin &short_name, 887004e86ffSlogin Some(se), 888004e86ffSlogin se.attributes, 889004e86ffSlogin fs.clone(), 890004e86ffSlogin )?; 891004e86ffSlogin 892004e86ffSlogin return Ok(new_dentry); 893004e86ffSlogin } else { 894004e86ffSlogin // 不允许对根目录项进行重命名 895676b8ef6SMork return Err(SystemError::EPERM); 896004e86ffSlogin } 897004e86ffSlogin } 898*9e481b3bSTTaq 899*9e481b3bSTTaq /// @brief 跨目录,重命名一个目录项 900*9e481b3bSTTaq /// 901*9e481b3bSTTaq pub fn rename_across( 902*9e481b3bSTTaq &self, 903*9e481b3bSTTaq fs: Arc<FATFileSystem>, 904*9e481b3bSTTaq target: &FATDir, 905*9e481b3bSTTaq old_name: &str, 906*9e481b3bSTTaq new_name: &str, 907*9e481b3bSTTaq ) -> Result<FATDirEntry, SystemError> { 908*9e481b3bSTTaq // 判断源目录项是否存在 909*9e481b3bSTTaq let old_dentry: FATDirEntry = if let FATDirEntryOrShortName::DirEntry(dentry) = 910*9e481b3bSTTaq self.check_existence(old_name, None, fs.clone())? 911*9e481b3bSTTaq { 912*9e481b3bSTTaq dentry 913*9e481b3bSTTaq } else { 914*9e481b3bSTTaq // 如果目标目录项不存在,则返回错误 915*9e481b3bSTTaq return Err(SystemError::ENOENT); 916*9e481b3bSTTaq }; 917*9e481b3bSTTaq 918*9e481b3bSTTaq let short_name = if let FATDirEntryOrShortName::ShortName(s) = 919*9e481b3bSTTaq target.check_existence(new_name, None, fs.clone())? 920*9e481b3bSTTaq { 921*9e481b3bSTTaq s 922*9e481b3bSTTaq } else { 923*9e481b3bSTTaq // 如果目标目录项存在,那么就返回错误 924*9e481b3bSTTaq return Err(SystemError::EEXIST); 925*9e481b3bSTTaq }; 926*9e481b3bSTTaq 927*9e481b3bSTTaq let old_short_dentry: Option<ShortDirEntry> = old_dentry.short_dir_entry(); 928*9e481b3bSTTaq if let Some(se) = old_short_dentry { 929*9e481b3bSTTaq // 删除原来的目录项 930*9e481b3bSTTaq self.remove(fs.clone(), old_dentry.name().as_str(), false)?; 931*9e481b3bSTTaq 932*9e481b3bSTTaq // 创建新的目录项 933*9e481b3bSTTaq let new_dentry: FATDirEntry = target.create_dir_entries( 934*9e481b3bSTTaq new_name, 935*9e481b3bSTTaq &short_name, 936*9e481b3bSTTaq Some(se), 937*9e481b3bSTTaq se.attributes, 938*9e481b3bSTTaq fs.clone(), 939*9e481b3bSTTaq )?; 940*9e481b3bSTTaq 941*9e481b3bSTTaq return Ok(new_dentry); 942*9e481b3bSTTaq } else { 943*9e481b3bSTTaq // 不允许对根目录项进行重命名 944*9e481b3bSTTaq return Err(SystemError::EPERM); 945*9e481b3bSTTaq } 946*9e481b3bSTTaq } 947004e86ffSlogin } 948004e86ffSlogin 949004e86ffSlogin impl FileAttributes { 950004e86ffSlogin pub const READ_ONLY: u8 = 1 << 0; 951004e86ffSlogin pub const HIDDEN: u8 = 1 << 1; 952004e86ffSlogin pub const SYSTEM: u8 = 1 << 2; 953004e86ffSlogin pub const VOLUME_ID: u8 = 1 << 3; 954004e86ffSlogin pub const DIRECTORY: u8 = 1 << 4; 955004e86ffSlogin pub const ARCHIVE: u8 = 1 << 5; 956004e86ffSlogin pub const LONG_NAME: u8 = FileAttributes::READ_ONLY 957004e86ffSlogin | FileAttributes::HIDDEN 958004e86ffSlogin | FileAttributes::SYSTEM 959004e86ffSlogin | FileAttributes::VOLUME_ID; 960004e86ffSlogin 961004e86ffSlogin /// @brief 判断属性是否存在 962004e86ffSlogin #[inline] 963004e86ffSlogin pub fn contains(&self, attr: u8) -> bool { 964004e86ffSlogin return (self.value & attr) != 0; 965004e86ffSlogin } 966004e86ffSlogin 967004e86ffSlogin pub fn new(attr: u8) -> Self { 968004e86ffSlogin return Self { value: attr }; 969004e86ffSlogin } 970004e86ffSlogin } 971004e86ffSlogin 972004e86ffSlogin /// FAT32的短目录项 973004e86ffSlogin #[derive(Debug, Clone, Copy, Default)] 974004e86ffSlogin pub struct ShortDirEntry { 975004e86ffSlogin /// short name 976004e86ffSlogin name: [u8; 11], 977004e86ffSlogin /// 目录项属性 (见 FileAttributes ) 978004e86ffSlogin attributes: FileAttributes, 979004e86ffSlogin 980004e86ffSlogin /// Windows NT系统的保留字段。用来表示短目录项文件名。 981004e86ffSlogin /// EXT|BASE => 8(BASE).3(EXT) 982004e86ffSlogin /// BASE:LowerCase(8),UpperCase(0) 983004e86ffSlogin /// EXT:LowerCase(16),UpperCase(0) 984004e86ffSlogin nt_res: u8, 985004e86ffSlogin 986004e86ffSlogin /// 文件创建时间的毫秒级时间戳 987004e86ffSlogin crt_time_tenth: u8, 988004e86ffSlogin /// 创建时间 989004e86ffSlogin crt_time: u16, 990004e86ffSlogin /// 创建日期 991004e86ffSlogin crt_date: u16, 992004e86ffSlogin /// 最后一次访问日期 993004e86ffSlogin lst_acc_date: u16, 994004e86ffSlogin /// High word of first cluster(0 for FAT12 and FAT16) 995004e86ffSlogin fst_clus_hi: u16, 996004e86ffSlogin /// 最后写入时间 997004e86ffSlogin wrt_time: u16, 998004e86ffSlogin /// 最后写入日期 999004e86ffSlogin wrt_date: u16, 1000004e86ffSlogin /// Low word of first cluster 1001004e86ffSlogin fst_clus_lo: u16, 1002004e86ffSlogin /// 文件大小 1003004e86ffSlogin file_size: u32, 1004004e86ffSlogin } 1005004e86ffSlogin 1006004e86ffSlogin /// FAT32的长目录项 1007004e86ffSlogin #[derive(Debug, Clone, Copy, Default)] 1008004e86ffSlogin pub struct LongDirEntry { 1009004e86ffSlogin /// 长目录项的序号 1010004e86ffSlogin ord: u8, 1011004e86ffSlogin /// 长文件名的第1-5个字符,每个字符占2bytes 1012004e86ffSlogin name1: [u16; 5], 1013004e86ffSlogin /// 目录项属性必须为ATTR_LONG_NAME 1014004e86ffSlogin file_attrs: FileAttributes, 1015004e86ffSlogin /// Entry Type: 如果为0,则说明这是长目录项的子项 1016004e86ffSlogin /// 非零值是保留的。 1017004e86ffSlogin dirent_type: u8, 1018004e86ffSlogin /// 短文件名的校验和 1019004e86ffSlogin checksum: u8, 1020004e86ffSlogin /// 长文件名的第6-11个字符,每个字符占2bytes 1021004e86ffSlogin name2: [u16; 6], 1022004e86ffSlogin /// 必须为0 1023004e86ffSlogin first_clus_low: u16, 1024004e86ffSlogin /// 长文件名的12-13个字符,每个字符占2bytes 1025004e86ffSlogin name3: [u16; 2], 1026004e86ffSlogin } 1027004e86ffSlogin 1028004e86ffSlogin impl LongDirEntry { 1029004e86ffSlogin /// 长目录项的字符串长度(单位:word) 1030004e86ffSlogin pub const LONG_NAME_STR_LEN: usize = 13; 1031004e86ffSlogin 1032004e86ffSlogin /// @brief 初始化一个新的长目录项 1033004e86ffSlogin /// 1034004e86ffSlogin /// @param ord 顺序 1035004e86ffSlogin /// @param name_part 长目录项名称的数组(长度必须为13) 1036004e86ffSlogin /// @param check_sum 短目录项的校验和 1037004e86ffSlogin /// 1038004e86ffSlogin /// @return Self 初始化好的长目录项对象 1039004e86ffSlogin fn new(ord: u8, name_part: &[u16], check_sum: u8) -> Self { 1040004e86ffSlogin let mut result = LongDirEntry::default(); 1041004e86ffSlogin result.ord = ord; 1042004e86ffSlogin result 1043004e86ffSlogin .insert_name(name_part) 1044004e86ffSlogin .expect("Name part's len should be equal to 13."); 1045004e86ffSlogin result.file_attrs.value = FileAttributes::LONG_NAME; 1046004e86ffSlogin result.dirent_type = 0; 1047004e86ffSlogin result.checksum = check_sum; 1048004e86ffSlogin // 该字段需要外层的代码手动赋值 1049004e86ffSlogin result.first_clus_low = 0; 1050004e86ffSlogin return result; 1051004e86ffSlogin } 1052004e86ffSlogin 1053004e86ffSlogin /// @brief 填写长目录项的名称字段。 1054004e86ffSlogin /// 1055004e86ffSlogin /// @param name_part 要被填入当前长目录项的名字(数组长度必须为13) 1056004e86ffSlogin /// 1057004e86ffSlogin /// @return Ok(()) 1058676b8ef6SMork /// @return Err(SystemError) 错误码 1059676b8ef6SMork fn insert_name(&mut self, name_part: &[u16]) -> Result<(), SystemError> { 1060004e86ffSlogin if name_part.len() != Self::LONG_NAME_STR_LEN { 1061676b8ef6SMork return Err(SystemError::EINVAL); 1062004e86ffSlogin } 1063004e86ffSlogin self.name1.copy_from_slice(&name_part[0..5]); 1064004e86ffSlogin self.name2.copy_from_slice(&name_part[5..11]); 1065004e86ffSlogin self.name3.copy_from_slice(&name_part[11..13]); 1066004e86ffSlogin return Ok(()); 1067004e86ffSlogin } 1068004e86ffSlogin 1069004e86ffSlogin /// @brief 将当前长目录项的名称字段,原样地拷贝到一个长度为13的u16数组中。 1070004e86ffSlogin /// @param dst 拷贝的目的地,一个[u16]数组,长度必须为13。 1071676b8ef6SMork pub fn copy_name_to_slice(&self, dst: &mut [u16]) -> Result<(), SystemError> { 1072004e86ffSlogin if dst.len() != Self::LONG_NAME_STR_LEN { 1073676b8ef6SMork return Err(SystemError::EINVAL); 1074004e86ffSlogin } 1075004e86ffSlogin dst[0..5].copy_from_slice(&self.name1); 1076004e86ffSlogin dst[5..11].copy_from_slice(&self.name2); 1077004e86ffSlogin dst[11..13].copy_from_slice(&self.name3); 1078004e86ffSlogin return Ok(()); 1079004e86ffSlogin } 1080004e86ffSlogin 1081004e86ffSlogin /// @brief 是否为最后一个长目录项 1082004e86ffSlogin /// 1083004e86ffSlogin /// @return true 是最后一个长目录项 1084004e86ffSlogin /// @return false 不是最后一个长目录项 1085004e86ffSlogin pub fn is_last(&self) -> bool { 1086004e86ffSlogin return self.ord & 0x40 > 0; 1087004e86ffSlogin } 1088004e86ffSlogin 1089004e86ffSlogin /// @brief 校验字符串是否符合长目录项的命名要求 1090004e86ffSlogin /// 1091004e86ffSlogin /// @return Ok(()) 名称合法 1092676b8ef6SMork /// @return Err(SystemError) 名称不合法,返回错误码 1093676b8ef6SMork pub fn validate_long_name(mut name: &str) -> Result<(), SystemError> { 1094004e86ffSlogin // 去除首尾多余的空格 1095004e86ffSlogin name = name.trim(); 1096004e86ffSlogin 1097004e86ffSlogin // 名称不能为0 1098004e86ffSlogin if name.len() == 0 { 1099676b8ef6SMork return Err(SystemError::EINVAL); 1100004e86ffSlogin } 1101004e86ffSlogin 1102004e86ffSlogin // 名称长度不能大于255 1103004e86ffSlogin if name.len() > 255 { 1104676b8ef6SMork return Err(SystemError::ENAMETOOLONG); 1105004e86ffSlogin } 1106004e86ffSlogin 1107004e86ffSlogin // 检查是否符合命名要求 1108004e86ffSlogin for c in name.chars() { 1109004e86ffSlogin match c { 1110004e86ffSlogin 'a'..='z' | 'A'..='Z' | '0'..='9' => {} 1111004e86ffSlogin '\u{80}'..='\u{ffff}' => {} 1112004e86ffSlogin '$' | '%' | '\'' | '-' | '_' | '@' | '~' | '`' | '!' | '(' | ')' | '{' | '}' 1113004e86ffSlogin | '^' | '#' | '&' => {} 1114004e86ffSlogin '+' | ',' | ';' | '=' | '[' | ']' | '.' | ' ' => {} 1115004e86ffSlogin _ => { 1116676b8ef6SMork return Err(SystemError::EILSEQ); 1117004e86ffSlogin } 1118004e86ffSlogin } 1119004e86ffSlogin } 1120004e86ffSlogin return Ok(()); 1121004e86ffSlogin } 1122004e86ffSlogin 1123004e86ffSlogin /// @brief 把当前长目录项写入磁盘 1124004e86ffSlogin /// 1125004e86ffSlogin /// @param fs 对应的文件系统 1126004e86ffSlogin /// @param disk_bytes_offset 长目录项所在位置对应的在磁盘上的字节偏移量 1127004e86ffSlogin /// 1128004e86ffSlogin /// @return Ok(()) 1129676b8ef6SMork /// @return Err(SystemError) 错误码 1130676b8ef6SMork pub fn flush(&self, fs: Arc<FATFileSystem>, disk_bytes_offset: u64) -> Result<(), SystemError> { 1131004e86ffSlogin // 从磁盘读取数据 1132004e86ffSlogin let blk_offset = fs.get_in_block_offset(disk_bytes_offset); 1133004e86ffSlogin let lba = fs.get_lba_from_offset( 1134004e86ffSlogin fs.bytes_to_sector(fs.get_in_partition_bytes_offset(disk_bytes_offset)), 1135004e86ffSlogin ); 1136004e86ffSlogin let mut v: Vec<u8> = Vec::new(); 1137004e86ffSlogin v.resize(1 * fs.lba_per_sector() * LBA_SIZE, 0); 1138004e86ffSlogin fs.partition 1139004e86ffSlogin .disk() 1140004e86ffSlogin .read_at(lba, 1 * fs.lba_per_sector(), &mut v)?; 1141004e86ffSlogin 1142004e86ffSlogin let mut cursor: VecCursor = VecCursor::new(v); 1143004e86ffSlogin // 切换游标到对应位置 1144004e86ffSlogin cursor.seek(SeekFrom::SeekSet(blk_offset as i64))?; 1145004e86ffSlogin 1146004e86ffSlogin // 写入数据 1147004e86ffSlogin cursor.write_u8(self.ord)?; 1148004e86ffSlogin for b in &self.name1 { 1149004e86ffSlogin cursor.write_u16(*b)?; 1150004e86ffSlogin } 1151004e86ffSlogin 1152004e86ffSlogin cursor.write_u8(self.file_attrs.value)?; 1153004e86ffSlogin cursor.write_u8(self.dirent_type)?; 1154004e86ffSlogin cursor.write_u8(self.checksum)?; 1155004e86ffSlogin 1156004e86ffSlogin for b in &self.name2 { 1157004e86ffSlogin cursor.write_u16(*b)?; 1158004e86ffSlogin } 1159004e86ffSlogin 1160004e86ffSlogin cursor.write_u16(self.first_clus_low)?; 1161004e86ffSlogin 1162004e86ffSlogin for b in &self.name3 { 1163004e86ffSlogin cursor.write_u16(*b)?; 1164004e86ffSlogin } 1165004e86ffSlogin 1166004e86ffSlogin // 把修改后的长目录项刷入磁盘 1167004e86ffSlogin fs.partition 1168004e86ffSlogin .disk() 1169004e86ffSlogin .write_at(lba, 1 * fs.lba_per_sector(), cursor.as_slice())?; 1170004e86ffSlogin fs.partition.disk().sync()?; 1171004e86ffSlogin 1172004e86ffSlogin return Ok(()); 1173004e86ffSlogin } 1174004e86ffSlogin } 1175004e86ffSlogin 1176004e86ffSlogin impl ShortDirEntry { 1177004e86ffSlogin const PADDING: u8 = ' ' as u8; 1178004e86ffSlogin 1179004e86ffSlogin /// @brief 判断当前目录项是否为文件夹 1180004e86ffSlogin /// 1181004e86ffSlogin /// @return true 是文件夹 1182004e86ffSlogin /// @return false 不是文件夹 1183004e86ffSlogin pub fn is_dir(&self) -> bool { 1184004e86ffSlogin return (self.attributes.contains(FileAttributes::DIRECTORY)) 1185004e86ffSlogin && (!self.attributes.contains(FileAttributes::VOLUME_ID)); 1186004e86ffSlogin } 1187004e86ffSlogin 1188004e86ffSlogin /// @brief 判断当前目录项是否为文件 1189004e86ffSlogin /// 1190004e86ffSlogin /// @return true 是文件 1191004e86ffSlogin /// @return false 不是文件 1192004e86ffSlogin pub fn is_file(&self) -> bool { 1193004e86ffSlogin return (!self.attributes.contains(FileAttributes::DIRECTORY)) 1194004e86ffSlogin && (!self.attributes.contains(FileAttributes::VOLUME_ID)); 1195004e86ffSlogin } 1196004e86ffSlogin 1197004e86ffSlogin /// @brief 判断当前目录项是否为卷号 1198004e86ffSlogin /// 1199004e86ffSlogin /// @return true 是卷号 1200004e86ffSlogin /// @return false 不是卷号 1201004e86ffSlogin pub fn is_volume_id(&self) -> bool { 1202004e86ffSlogin return (!self.attributes.contains(FileAttributes::DIRECTORY)) 1203004e86ffSlogin && self.attributes.contains(FileAttributes::VOLUME_ID); 1204004e86ffSlogin } 1205004e86ffSlogin 1206004e86ffSlogin /// @brief 将短目录项的名字转换为String 1207004e86ffSlogin fn name_to_string(&self) -> String { 1208004e86ffSlogin // 计算基础名的长度 1209004e86ffSlogin let base_len = self.name[..8] 1210004e86ffSlogin .iter() 1211004e86ffSlogin .rposition(|x| *x != ShortDirEntry::PADDING) 1212004e86ffSlogin .map(|len| len + 1) 1213004e86ffSlogin .unwrap_or(0); 1214004e86ffSlogin // 计算扩展名的长度 1215004e86ffSlogin let ext_len = self.name[8..] 1216004e86ffSlogin .iter() 1217004e86ffSlogin .rposition(|x| *x != ShortDirEntry::PADDING) 1218004e86ffSlogin .map(|len| len + 1) 1219004e86ffSlogin .unwrap_or(0); 1220004e86ffSlogin 1221004e86ffSlogin // 声明存储完整名字的数组(包含“.”) 1222004e86ffSlogin let mut name = [ShortDirEntry::PADDING; 12]; 1223004e86ffSlogin // 拷贝基础名 1224004e86ffSlogin name[..base_len].copy_from_slice(&self.name[..base_len]); 1225004e86ffSlogin 1226004e86ffSlogin // 拷贝扩展名,并计算总的长度 1227004e86ffSlogin let total_len = if ext_len > 0 { 1228004e86ffSlogin name[base_len] = '.' as u8; 1229004e86ffSlogin name[base_len + 1..base_len + 1 + ext_len].copy_from_slice(&self.name[8..8 + ext_len]); 1230004e86ffSlogin // 总长度为基础名长度+点号+扩展名长度 1231004e86ffSlogin base_len + 1 + ext_len 1232004e86ffSlogin } else { 1233004e86ffSlogin base_len 1234004e86ffSlogin }; 1235004e86ffSlogin 1236004e86ffSlogin if name[0] == 0x05 { 1237004e86ffSlogin name[0] = 0xe5; 1238004e86ffSlogin } 1239004e86ffSlogin 1240004e86ffSlogin let iter = name[..total_len].iter().map(|c| decode_u8_ascii(*c)); 1241004e86ffSlogin // 返回最终的字符串 1242004e86ffSlogin return String::from_iter(iter); 1243004e86ffSlogin } 1244004e86ffSlogin 1245004e86ffSlogin /// @brief 将短目录项结构体,转换为FATDirEntry枚举类型 1246004e86ffSlogin /// 1247004e86ffSlogin /// @param loc 当前文件的起始、终止簇。格式:(簇,簇内偏移量) 1248004e86ffSlogin /// @return 生成的FATDirENtry枚举类型 1249004e86ffSlogin pub fn to_dir_entry(&self, loc: (Cluster, u64)) -> FATDirEntry { 1250004e86ffSlogin // 当前文件的第一个簇 1251004e86ffSlogin let first_cluster = 1252004e86ffSlogin Cluster::new(((self.fst_clus_hi as u64) << 16) | (self.fst_clus_lo as u64)); 1253004e86ffSlogin 1254004e86ffSlogin // 当前是文件或卷号 1255004e86ffSlogin if self.is_file() || self.is_volume_id() { 1256004e86ffSlogin let mut file: FATFile = FATFile::default(); 1257004e86ffSlogin 1258004e86ffSlogin file.file_name = self.name_to_string(); 1259004e86ffSlogin file.first_cluster = first_cluster; 1260004e86ffSlogin file.short_dir_entry = self.clone(); 1261004e86ffSlogin file.loc = (loc, loc); 1262004e86ffSlogin 1263004e86ffSlogin // 根据当前短目录项的类型的不同,返回对应的枚举类型。 1264004e86ffSlogin if self.is_file() { 1265004e86ffSlogin return FATDirEntry::File(file); 1266004e86ffSlogin } else { 1267004e86ffSlogin return FATDirEntry::VolId(file); 1268004e86ffSlogin } 1269004e86ffSlogin } else { 1270004e86ffSlogin // 当前是文件夹 1271004e86ffSlogin let mut dir = FATDir::default(); 1272004e86ffSlogin dir.dir_name = self.name_to_string(); 1273004e86ffSlogin dir.first_cluster = first_cluster; 1274004e86ffSlogin dir.root_offset = None; 1275004e86ffSlogin dir.short_dir_entry = Some(self.clone()); 1276004e86ffSlogin dir.loc = Some((loc, loc)); 1277004e86ffSlogin 1278004e86ffSlogin return FATDirEntry::Dir(dir); 1279004e86ffSlogin } 1280004e86ffSlogin } 1281004e86ffSlogin 1282004e86ffSlogin /// @brief 将短目录项结构体,转换为FATDirEntry枚举类型. 并且,该短目录项具有对应的长目录项。 1283004e86ffSlogin /// 因此,需要传入从长目录项获得的完整的文件名 1284004e86ffSlogin /// 1285004e86ffSlogin /// @param name 从长目录项获取的完整文件名 1286004e86ffSlogin /// @param loc 当前文件的起始、终止簇。格式:(簇,簇内偏移量) 1287004e86ffSlogin /// @return 生成的FATDirENtry枚举类型 1288004e86ffSlogin pub fn to_dir_entry_with_long_name( 1289004e86ffSlogin &self, 1290004e86ffSlogin name: String, 1291004e86ffSlogin loc: ((Cluster, u64), (Cluster, u64)), 1292004e86ffSlogin ) -> FATDirEntry { 1293004e86ffSlogin // 当前文件的第一个簇 1294004e86ffSlogin let first_cluster = 1295004e86ffSlogin Cluster::new(((self.fst_clus_hi as u64) << 16) | (self.fst_clus_lo as u64)); 1296004e86ffSlogin 1297004e86ffSlogin if self.is_file() || self.is_volume_id() { 1298004e86ffSlogin let mut file = FATFile::default(); 1299004e86ffSlogin 1300004e86ffSlogin file.first_cluster = first_cluster; 1301004e86ffSlogin file.file_name = name; 1302004e86ffSlogin file.loc = loc; 1303004e86ffSlogin file.short_dir_entry = self.clone(); 1304004e86ffSlogin 1305004e86ffSlogin if self.is_file() { 1306004e86ffSlogin return FATDirEntry::File(file); 1307004e86ffSlogin } else { 1308004e86ffSlogin return FATDirEntry::VolId(file); 1309004e86ffSlogin } 1310004e86ffSlogin } else { 1311004e86ffSlogin let mut dir = FATDir::default(); 1312004e86ffSlogin 1313004e86ffSlogin dir.first_cluster = first_cluster; 1314004e86ffSlogin dir.dir_name = name; 1315004e86ffSlogin dir.loc = Some(loc); 1316004e86ffSlogin dir.short_dir_entry = Some(self.clone()); 1317004e86ffSlogin dir.root_offset = None; 1318004e86ffSlogin 1319004e86ffSlogin return FATDirEntry::Dir(dir); 1320004e86ffSlogin } 1321004e86ffSlogin } 1322004e86ffSlogin 1323004e86ffSlogin /// @brief 计算短目录项的名称的校验和 1324004e86ffSlogin fn checksum(&self) -> u8 { 1325004e86ffSlogin let mut result = 0; 1326004e86ffSlogin 1327004e86ffSlogin for c in &self.name { 1328004e86ffSlogin result = (result << 7) + (result >> 1) + *c; 1329004e86ffSlogin } 1330004e86ffSlogin return result; 1331004e86ffSlogin } 1332004e86ffSlogin 1333004e86ffSlogin /// @brief 把当前短目录项写入磁盘 1334004e86ffSlogin /// 1335004e86ffSlogin /// @param fs 对应的文件系统 1336004e86ffSlogin /// @param disk_bytes_offset 短目录项所在位置对应的在磁盘上的字节偏移量 1337004e86ffSlogin /// 1338004e86ffSlogin /// @return Ok(()) 1339676b8ef6SMork /// @return Err(SystemError) 错误码 134078bf93f0SYJwu2023 pub fn flush( 134178bf93f0SYJwu2023 &self, 134278bf93f0SYJwu2023 fs: &Arc<FATFileSystem>, 134378bf93f0SYJwu2023 disk_bytes_offset: u64, 134478bf93f0SYJwu2023 ) -> Result<(), SystemError> { 1345004e86ffSlogin // 从磁盘读取数据 1346004e86ffSlogin let blk_offset = fs.get_in_block_offset(disk_bytes_offset); 1347004e86ffSlogin let lba = fs.get_lba_from_offset( 1348004e86ffSlogin fs.bytes_to_sector(fs.get_in_partition_bytes_offset(disk_bytes_offset)), 1349004e86ffSlogin ); 1350004e86ffSlogin let mut v: Vec<u8> = Vec::new(); 1351004e86ffSlogin v.resize(1 * fs.lba_per_sector() * LBA_SIZE, 0); 1352004e86ffSlogin fs.partition 1353004e86ffSlogin .disk() 1354004e86ffSlogin .read_at(lba, 1 * fs.lba_per_sector(), &mut v)?; 1355004e86ffSlogin 1356004e86ffSlogin let mut cursor: VecCursor = VecCursor::new(v); 1357004e86ffSlogin // 切换游标到对应位置 1358004e86ffSlogin cursor.seek(SeekFrom::SeekSet(blk_offset as i64))?; 1359004e86ffSlogin cursor.write_exact(&self.name)?; 1360004e86ffSlogin cursor.write_u8(self.attributes.value)?; 1361004e86ffSlogin cursor.write_u8(self.nt_res)?; 1362004e86ffSlogin cursor.write_u8(self.crt_time_tenth)?; 1363004e86ffSlogin cursor.write_u16(self.crt_time)?; 1364004e86ffSlogin cursor.write_u16(self.crt_date)?; 1365004e86ffSlogin cursor.write_u16(self.lst_acc_date)?; 1366004e86ffSlogin cursor.write_u16(self.fst_clus_hi)?; 1367004e86ffSlogin cursor.write_u16(self.wrt_time)?; 1368004e86ffSlogin cursor.write_u16(self.wrt_date)?; 1369004e86ffSlogin cursor.write_u16(self.fst_clus_lo)?; 1370004e86ffSlogin cursor.write_u32(self.file_size)?; 1371004e86ffSlogin 1372004e86ffSlogin // 把修改后的长目录项刷入磁盘 1373004e86ffSlogin fs.partition 1374004e86ffSlogin .disk() 1375004e86ffSlogin .write_at(lba, 1 * fs.lba_per_sector(), cursor.as_slice())?; 1376004e86ffSlogin fs.partition.disk().sync()?; 1377004e86ffSlogin 1378004e86ffSlogin return Ok(()); 1379004e86ffSlogin } 1380004e86ffSlogin 1381004e86ffSlogin /// @brief 设置短目录项的“第一个簇”字段的值 1382004e86ffSlogin pub fn set_first_cluster(&mut self, cluster: Cluster) { 1383004e86ffSlogin self.fst_clus_lo = (cluster.cluster_num & 0x0000ffff) as u16; 1384004e86ffSlogin self.fst_clus_hi = ((cluster.cluster_num & 0xffff0000) >> 16) as u16; 1385004e86ffSlogin } 1386004e86ffSlogin } 1387004e86ffSlogin 1388004e86ffSlogin /// @brief FAT文件系统标准定义的目录项 1389004e86ffSlogin #[derive(Debug, Clone)] 1390004e86ffSlogin pub enum FATRawDirEntry { 1391004e86ffSlogin /// 短目录项 1392004e86ffSlogin Short(ShortDirEntry), 1393004e86ffSlogin /// 长目录项 1394004e86ffSlogin Long(LongDirEntry), 1395004e86ffSlogin /// 当前目录项的Name[0]==0xe5, 是空闲目录项 1396004e86ffSlogin Free, 1397004e86ffSlogin /// 当前目录项的Name[0]==0xe5, 是空闲目录项,且在这之后没有被分配过的目录项了。 1398004e86ffSlogin FreeRest, 1399004e86ffSlogin } 1400004e86ffSlogin 1401004e86ffSlogin impl FATRawDirEntry { 1402004e86ffSlogin /// 每个目录项的长度(单位:字节) 1403004e86ffSlogin pub const DIR_ENTRY_LEN: u64 = 32; 1404004e86ffSlogin 1405004e86ffSlogin /// @brief 判断当前目录项是否为这个文件的最后一个目录项 1406004e86ffSlogin fn is_last(&self) -> bool { 1407004e86ffSlogin match self { 1408004e86ffSlogin &Self::Short(_) => { 1409004e86ffSlogin return true; 1410004e86ffSlogin } 1411004e86ffSlogin &Self::Long(l) => { 1412004e86ffSlogin return l.is_last(); 1413004e86ffSlogin } 1414004e86ffSlogin _ => { 1415004e86ffSlogin return false; 1416004e86ffSlogin } 1417004e86ffSlogin } 1418004e86ffSlogin } 1419004e86ffSlogin 1420004e86ffSlogin /// @brief 判断当前目录项是否为长目录项 1421004e86ffSlogin fn is_long(&self) -> bool { 1422004e86ffSlogin if let Self::Long(_) = self { 1423004e86ffSlogin return true; 1424004e86ffSlogin } else { 1425004e86ffSlogin return false; 1426004e86ffSlogin } 1427004e86ffSlogin } 1428004e86ffSlogin 1429004e86ffSlogin /// @brief 判断当前目录项是否为短目录项 1430004e86ffSlogin fn is_short(&self) -> bool { 1431004e86ffSlogin if let Self::Short(_) = self { 1432004e86ffSlogin return true; 1433004e86ffSlogin } else { 1434004e86ffSlogin return false; 1435004e86ffSlogin } 1436004e86ffSlogin } 1437004e86ffSlogin } 1438004e86ffSlogin 1439004e86ffSlogin /// @brief FAT文件系统的目录项迭代器 1440004e86ffSlogin #[derive(Debug)] 1441004e86ffSlogin pub struct FATDirIter { 1442004e86ffSlogin /// 当前正在迭代的簇 1443004e86ffSlogin current_cluster: Cluster, 1444004e86ffSlogin /// 当前正在迭代的簇的簇内偏移量 1445004e86ffSlogin offset: u64, 1446004e86ffSlogin /// True for the root directories of FAT12 and FAT16 1447004e86ffSlogin is_root: bool, 1448004e86ffSlogin /// 指向当前文件系统的指针 1449004e86ffSlogin fs: Arc<FATFileSystem>, 1450004e86ffSlogin } 1451004e86ffSlogin 1452004e86ffSlogin impl FATDirIter { 1453004e86ffSlogin /// @brief 迭代当前inode的目录项(获取下一个目录项) 1454004e86ffSlogin /// 1455004e86ffSlogin /// @return Ok(Cluster, u64, Option<FATDirEntry>) 1456004e86ffSlogin /// Cluster: 下一个要读取的簇号 1457004e86ffSlogin /// u64: 下一个要读取的簇内偏移量 1458004e86ffSlogin /// Option<FATDirEntry>: 读取到的目录项(如果没有读取到,就返回失败) 1459004e86ffSlogin /// @return Err(错误码) 可能出现了内部错误,或者是磁盘错误等。具体原因看错误码。 1460676b8ef6SMork fn get_dir_entry(&mut self) -> Result<(Cluster, u64, Option<FATDirEntry>), SystemError> { 1461004e86ffSlogin loop { 14626d81180bSLoGin if unlikely(self.current_cluster.cluster_num < 2) { 14636d81180bSLoGin return Ok((self.current_cluster, self.offset, None)); 14646d81180bSLoGin } 14656d81180bSLoGin 1466004e86ffSlogin // 如果当前簇已经被读完,那么尝试获取下一个簇 1467004e86ffSlogin if self.offset >= self.fs.bytes_per_cluster() && !self.is_root { 1468004e86ffSlogin match self.fs.get_fat_entry(self.current_cluster)? { 1469004e86ffSlogin FATEntry::Next(c) => { 1470004e86ffSlogin // 获得下一个簇的信息 1471004e86ffSlogin self.current_cluster = c; 1472004e86ffSlogin self.offset %= self.fs.bytes_per_cluster(); 1473004e86ffSlogin } 1474004e86ffSlogin 1475004e86ffSlogin _ => { 1476004e86ffSlogin // 没有下一个簇了,返回None 1477004e86ffSlogin return Ok((self.current_cluster, self.offset, None)); 1478004e86ffSlogin } 1479004e86ffSlogin } 1480004e86ffSlogin } 1481004e86ffSlogin 1482004e86ffSlogin // 如果当前是FAT12/FAT16文件系统,并且当前inode是根目录项。 1483004e86ffSlogin // 如果offset大于根目录项的最大大小(已经遍历完根目录),那么就返回None 1484004e86ffSlogin if self.is_root && self.offset > self.fs.root_dir_end_bytes_offset().unwrap() { 1485004e86ffSlogin return Ok((self.current_cluster, self.offset, None)); 1486004e86ffSlogin } 1487004e86ffSlogin 1488004e86ffSlogin // 获取簇在磁盘内的字节偏移量 1489004e86ffSlogin let offset: u64 = self.fs.cluster_bytes_offset(self.current_cluster) + self.offset; 1490004e86ffSlogin 1491004e86ffSlogin // 从磁盘读取原始的dentry 1492004e86ffSlogin let raw_dentry: FATRawDirEntry = get_raw_dir_entry(&self.fs, offset)?; 1493004e86ffSlogin 1494004e86ffSlogin // 由于迭代顺序从前往后,因此: 1495004e86ffSlogin // 如果找到1个短目录项,那么证明有一个完整的entry被找到,因此返回。 1496004e86ffSlogin // 如果找到1个长目录项,那么,就依次往下迭代查找,直到找到一个短目录项,然后返回结果。这里找到的所有的目录项,都属于同一个文件/文件夹。 1497004e86ffSlogin match raw_dentry { 1498004e86ffSlogin FATRawDirEntry::Short(s) => { 1499004e86ffSlogin // 当前找到一个短目录项,更新offset之后,直接返回 1500004e86ffSlogin self.offset += FATRawDirEntry::DIR_ENTRY_LEN; 1501004e86ffSlogin return Ok(( 1502004e86ffSlogin self.current_cluster, 1503004e86ffSlogin self.offset, 1504004e86ffSlogin Some(s.to_dir_entry(( 1505004e86ffSlogin self.current_cluster, 1506004e86ffSlogin self.offset - FATRawDirEntry::DIR_ENTRY_LEN, 1507004e86ffSlogin ))), 1508004e86ffSlogin )); 1509004e86ffSlogin } 1510004e86ffSlogin FATRawDirEntry::Long(_) => { 1511004e86ffSlogin // 当前找到一个长目录项 1512004e86ffSlogin 1513004e86ffSlogin // 声明一个数组,来容纳所有的entry。(先把最后一个entry放进去) 1514004e86ffSlogin let mut long_name_entries: Vec<FATRawDirEntry> = vec![raw_dentry]; 1515004e86ffSlogin let start_offset: u64 = self.offset; 1516004e86ffSlogin let start_cluster: Cluster = self.current_cluster; 1517004e86ffSlogin 1518004e86ffSlogin self.offset += FATRawDirEntry::DIR_ENTRY_LEN; 1519004e86ffSlogin 1520004e86ffSlogin // 由于在FAT文件系统中,文件名最长为255字节,因此,最多有20个长目录项以及1个短目录项。 1521004e86ffSlogin // 由于上面已经塞了1个长目录项,因此接下来最多需要迭代20次 1522004e86ffSlogin // 循环查找目录项,直到遇到1个短目录项,或者是空闲目录项 1523004e86ffSlogin for _ in 0..20 { 1524004e86ffSlogin // 如果当前簇已经被读完,那么尝试获取下一个簇 1525004e86ffSlogin if self.offset >= self.fs.bytes_per_cluster() && !self.is_root { 1526004e86ffSlogin match self.fs.get_fat_entry(self.current_cluster)? { 1527004e86ffSlogin FATEntry::Next(c) => { 1528004e86ffSlogin // 获得下一个簇的信息 1529004e86ffSlogin self.current_cluster = c; 1530004e86ffSlogin self.offset %= self.fs.bytes_per_cluster(); 1531004e86ffSlogin } 1532004e86ffSlogin 1533004e86ffSlogin _ => { 1534004e86ffSlogin // 没有下一个簇了,退出迭代 1535004e86ffSlogin break; 1536004e86ffSlogin } 1537004e86ffSlogin } 1538004e86ffSlogin } 1539004e86ffSlogin // 如果当前是FAT12/FAT16文件系统,并且当前inode是根目录项。 1540004e86ffSlogin // 如果offset大于根目录项的最大大小(已经遍历完根目录),那么就退出迭代 1541004e86ffSlogin if self.is_root 1542004e86ffSlogin && self.offset > self.fs.root_dir_end_bytes_offset().unwrap() 1543004e86ffSlogin { 1544004e86ffSlogin break; 1545004e86ffSlogin } 1546004e86ffSlogin 1547004e86ffSlogin // 获取簇在磁盘内的字节偏移量 1548004e86ffSlogin let offset: u64 = 1549004e86ffSlogin self.fs.cluster_bytes_offset(self.current_cluster) + self.offset; 1550004e86ffSlogin // 从磁盘读取原始的dentry 1551004e86ffSlogin let raw_dentry: FATRawDirEntry = get_raw_dir_entry(&self.fs, offset)?; 1552004e86ffSlogin 1553004e86ffSlogin match raw_dentry { 1554004e86ffSlogin FATRawDirEntry::Short(_) => { 1555004e86ffSlogin // 当前遇到1个短目录项,证明当前文件/文件夹的所有dentry都被读取完了,因此在将其加入数组后,退出迭代。 1556004e86ffSlogin long_name_entries.push(raw_dentry); 1557004e86ffSlogin break; 1558004e86ffSlogin } 1559004e86ffSlogin FATRawDirEntry::Long(_) => { 1560004e86ffSlogin // 当前遇到1个长目录项,将其加入数组,然后更新offset,继续迭代。 1561004e86ffSlogin long_name_entries.push(raw_dentry); 1562004e86ffSlogin self.offset += FATRawDirEntry::DIR_ENTRY_LEN; 1563004e86ffSlogin } 1564004e86ffSlogin 1565004e86ffSlogin _ => { 1566004e86ffSlogin // 遇到了空闲簇,但没遇到短目录项,说明文件系统出错了,退出。 1567004e86ffSlogin break; 1568004e86ffSlogin } 1569004e86ffSlogin } 1570004e86ffSlogin } 1571004e86ffSlogin // kdebug!("collect dentries done. long_name_entries={long_name_entries:?}"); 1572676b8ef6SMork let dir_entry: Result<FATDirEntry, SystemError> = FATDirEntry::new( 1573004e86ffSlogin long_name_entries, 1574004e86ffSlogin ( 1575004e86ffSlogin (start_cluster, start_offset), 1576004e86ffSlogin (self.current_cluster, self.offset), 1577004e86ffSlogin ), 1578004e86ffSlogin ); 1579004e86ffSlogin // kdebug!("dir_entry={:?}", dir_entry); 1580004e86ffSlogin match dir_entry { 1581004e86ffSlogin Ok(d) => { 1582004e86ffSlogin // kdebug!("dir_entry ok"); 1583004e86ffSlogin self.offset += FATRawDirEntry::DIR_ENTRY_LEN; 1584004e86ffSlogin return Ok((self.current_cluster, self.offset, Some(d))); 1585004e86ffSlogin } 1586004e86ffSlogin 1587004e86ffSlogin Err(_) => { 1588004e86ffSlogin // kdebug!("dir_entry err, e={}", e); 1589004e86ffSlogin self.offset += FATRawDirEntry::DIR_ENTRY_LEN; 1590004e86ffSlogin } 1591004e86ffSlogin } 1592004e86ffSlogin } 1593004e86ffSlogin FATRawDirEntry::Free => { 1594004e86ffSlogin // 当前目录项是空的 1595004e86ffSlogin self.offset += FATRawDirEntry::DIR_ENTRY_LEN; 1596004e86ffSlogin } 1597004e86ffSlogin FATRawDirEntry::FreeRest => { 1598004e86ffSlogin // 当前目录项是空的,且之后都是空的,因此直接返回 1599004e86ffSlogin return Ok((self.current_cluster, self.offset, None)); 1600004e86ffSlogin } 1601004e86ffSlogin } 1602004e86ffSlogin } 1603004e86ffSlogin } 1604004e86ffSlogin } 1605004e86ffSlogin 1606004e86ffSlogin /// 为DirIter实现迭代器trait 1607004e86ffSlogin impl Iterator for FATDirIter { 1608004e86ffSlogin type Item = FATDirEntry; 1609004e86ffSlogin 1610004e86ffSlogin fn next(&mut self) -> Option<Self::Item> { 1611004e86ffSlogin match self.get_dir_entry() { 1612004e86ffSlogin Ok((cluster, offset, result)) => { 1613004e86ffSlogin self.current_cluster = cluster; 1614004e86ffSlogin self.offset = offset; 1615004e86ffSlogin return result; 1616004e86ffSlogin } 1617004e86ffSlogin Err(_) => { 1618004e86ffSlogin return None; 1619004e86ffSlogin } 1620004e86ffSlogin } 1621004e86ffSlogin } 1622004e86ffSlogin } 1623004e86ffSlogin 1624004e86ffSlogin impl FATDirEntry { 1625004e86ffSlogin /// @brief 构建FATDirEntry枚举类型 1626004e86ffSlogin /// 1627004e86ffSlogin /// @param long_name_entries 长目录项的数组。 1628004e86ffSlogin /// 格式:[第20个(或者是最大ord的那个), 19, 18, ..., 1, 短目录项] 1629004e86ffSlogin /// 1630004e86ffSlogin /// @return Ok(FATDirEntry) 构建好的FATDirEntry类型的对象 1631676b8ef6SMork /// @return Err(SystemError) 错误码 1632004e86ffSlogin pub fn new( 1633004e86ffSlogin mut long_name_entries: Vec<FATRawDirEntry>, 1634004e86ffSlogin loc: ((Cluster, u64), (Cluster, u64)), 1635676b8ef6SMork ) -> Result<Self, SystemError> { 1636004e86ffSlogin if long_name_entries.is_empty() { 1637676b8ef6SMork return Err(SystemError::EINVAL); 1638004e86ffSlogin } 1639004e86ffSlogin 1640004e86ffSlogin if !long_name_entries[0].is_last() || !long_name_entries.last().unwrap().is_short() { 1641004e86ffSlogin // 存在孤立的目录项,文件系统出现异常,因此返回错误,表明其只读。 1642004e86ffSlogin // TODO: 标记整个FAT文件系统为只读的 1643676b8ef6SMork return Err(SystemError::EROFS); 1644004e86ffSlogin } 1645004e86ffSlogin 1646004e86ffSlogin // 取出短目录项(位于vec的末尾) 1647004e86ffSlogin let short_dentry: ShortDirEntry = match long_name_entries.pop().unwrap() { 1648004e86ffSlogin FATRawDirEntry::Short(s) => s, 1649004e86ffSlogin _ => unreachable!(), 1650004e86ffSlogin }; 1651004e86ffSlogin 1652004e86ffSlogin let mut extractor = LongNameExtractor::new(); 1653004e86ffSlogin for entry in &long_name_entries { 1654004e86ffSlogin match entry { 1655004e86ffSlogin &FATRawDirEntry::Long(l) => { 1656004e86ffSlogin extractor.process(l)?; 1657004e86ffSlogin } 1658004e86ffSlogin 1659004e86ffSlogin _ => { 1660676b8ef6SMork return Err(SystemError::EROFS); 1661004e86ffSlogin } 1662004e86ffSlogin } 1663004e86ffSlogin } 1664004e86ffSlogin // 检验校验和是否正确 1665004e86ffSlogin if extractor.validate_checksum(&short_dentry) { 1666004e86ffSlogin // 校验和正确,返回一个长目录项 1667004e86ffSlogin return Ok(short_dentry.to_dir_entry_with_long_name(extractor.to_string(), loc)); 1668004e86ffSlogin } else { 1669004e86ffSlogin // 校验和不相同,认为文件系统出错 1670676b8ef6SMork return Err(SystemError::EROFS); 1671004e86ffSlogin } 1672004e86ffSlogin } 1673004e86ffSlogin 1674004e86ffSlogin /// @brief 获取短目录项的名字 1675004e86ffSlogin pub fn short_name(&self) -> String { 1676004e86ffSlogin match self { 1677004e86ffSlogin FATDirEntry::File(f) | FATDirEntry::VolId(f) => { 1678004e86ffSlogin return f.short_dir_entry.name_to_string(); 1679004e86ffSlogin } 1680004e86ffSlogin FATDirEntry::Dir(d) => match d.short_dir_entry { 1681004e86ffSlogin Some(s) => { 1682004e86ffSlogin return s.name_to_string(); 1683004e86ffSlogin } 1684004e86ffSlogin None => { 1685004e86ffSlogin return String::from("/"); 1686004e86ffSlogin } 1687004e86ffSlogin }, 1688004e86ffSlogin FATDirEntry::UnInit => unreachable!("FATFS: FATDirEntry uninitialized."), 1689004e86ffSlogin } 1690004e86ffSlogin } 1691004e86ffSlogin 1692004e86ffSlogin /// @brief 获取短目录项结构体 1693004e86ffSlogin pub fn short_dir_entry(&self) -> Option<ShortDirEntry> { 1694004e86ffSlogin match &self { 1695004e86ffSlogin FATDirEntry::File(f) => { 1696004e86ffSlogin return Some(f.short_dir_entry); 1697004e86ffSlogin } 1698004e86ffSlogin FATDirEntry::Dir(d) => { 1699004e86ffSlogin return d.short_dir_entry; 1700004e86ffSlogin } 1701004e86ffSlogin FATDirEntry::VolId(s) => { 1702004e86ffSlogin return Some(s.short_dir_entry); 1703004e86ffSlogin } 1704004e86ffSlogin FATDirEntry::UnInit => unreachable!("FATFS: FATDirEntry uninitialized."), 1705004e86ffSlogin } 1706004e86ffSlogin } 1707004e86ffSlogin 1708004e86ffSlogin /// @brief 获取目录项的第一个簇的簇号 1709004e86ffSlogin pub fn first_cluster(&self) -> Cluster { 1710004e86ffSlogin match self { 1711004e86ffSlogin FATDirEntry::File(f) => { 1712004e86ffSlogin return f.first_cluster; 1713004e86ffSlogin } 1714004e86ffSlogin FATDirEntry::Dir(d) => { 1715004e86ffSlogin return d.first_cluster; 1716004e86ffSlogin } 1717004e86ffSlogin FATDirEntry::VolId(s) => { 1718004e86ffSlogin return s.first_cluster; 1719004e86ffSlogin } 1720004e86ffSlogin FATDirEntry::UnInit => unreachable!("FATFS: FATDirEntry uninitialized."), 1721004e86ffSlogin } 1722004e86ffSlogin } 1723004e86ffSlogin 1724004e86ffSlogin /// @brief 获取当前目录项所占用的簇的范围 1725004e86ffSlogin /// 1726004e86ffSlogin /// @return (起始簇,簇内偏移量), (终止簇,簇内偏移量) 1727004e86ffSlogin pub fn get_dir_range(&self) -> Option<((Cluster, u64), (Cluster, u64))> { 1728004e86ffSlogin match self { 1729004e86ffSlogin FATDirEntry::File(f) => Some(f.loc), 1730004e86ffSlogin FATDirEntry::Dir(d) => d.loc, 1731004e86ffSlogin FATDirEntry::VolId(s) => Some(s.loc), 1732004e86ffSlogin FATDirEntry::UnInit => unreachable!("FATFS: FATDirEntry uninitialized."), 1733004e86ffSlogin } 1734004e86ffSlogin } 1735004e86ffSlogin 1736004e86ffSlogin /// @brief 获取原始的短目录项名(FAT标准规定的) 1737004e86ffSlogin pub fn short_name_raw(&self) -> [u8; 11] { 1738004e86ffSlogin match self { 1739004e86ffSlogin FATDirEntry::File(f) => { 1740004e86ffSlogin return f.short_dir_entry.name; 1741004e86ffSlogin } 1742004e86ffSlogin FATDirEntry::Dir(d) => match d.short_dir_entry { 1743004e86ffSlogin // 存在短目录项,直接返回 1744004e86ffSlogin Some(s) => { 1745004e86ffSlogin return s.name; 1746004e86ffSlogin } 1747004e86ffSlogin // 是根目录项 1748004e86ffSlogin None => { 1749004e86ffSlogin let mut s = [0x20u8; 11]; 1750004e86ffSlogin s[0] = '/' as u8; 1751004e86ffSlogin return s; 1752004e86ffSlogin } 1753004e86ffSlogin }, 1754004e86ffSlogin FATDirEntry::VolId(s) => { 1755004e86ffSlogin return s.short_dir_entry.name; 1756004e86ffSlogin } 1757004e86ffSlogin 1758004e86ffSlogin FATDirEntry::UnInit => unreachable!("FATFS: FATDirEntry uninitialized."), 1759004e86ffSlogin } 1760004e86ffSlogin } 1761004e86ffSlogin 1762004e86ffSlogin /// @brief 获取目录项的名字 1763004e86ffSlogin pub fn name(&self) -> String { 1764004e86ffSlogin match self { 1765004e86ffSlogin FATDirEntry::File(f) => { 1766004e86ffSlogin return f.file_name.clone(); 1767004e86ffSlogin } 1768004e86ffSlogin FATDirEntry::VolId(s) => { 1769004e86ffSlogin return s.file_name.clone(); 1770004e86ffSlogin } 1771004e86ffSlogin FATDirEntry::Dir(d) => { 1772004e86ffSlogin return d.dir_name.clone(); 1773004e86ffSlogin } 1774004e86ffSlogin FATDirEntry::UnInit => unreachable!("FATFS: FATDirEntry uninitialized."), 1775004e86ffSlogin } 1776004e86ffSlogin } 1777004e86ffSlogin 1778004e86ffSlogin /// @brief 判断目录项是否为文件 1779004e86ffSlogin pub fn is_file(&self) -> bool { 1780004e86ffSlogin match self { 1781004e86ffSlogin &FATDirEntry::File(_) | &FATDirEntry::VolId(_) => true, 1782004e86ffSlogin _ => false, 1783004e86ffSlogin } 1784004e86ffSlogin } 1785004e86ffSlogin 1786004e86ffSlogin /// @brief 判断目录项是否为文件夹 1787004e86ffSlogin pub fn is_dir(&self) -> bool { 1788004e86ffSlogin match &self { 1789004e86ffSlogin &FATDirEntry::Dir(_) => true, 1790004e86ffSlogin _ => false, 1791004e86ffSlogin } 1792004e86ffSlogin } 1793004e86ffSlogin 1794004e86ffSlogin /// @brief 判断目录项是否为Volume id 1795004e86ffSlogin pub fn is_vol_id(&self) -> bool { 1796004e86ffSlogin match self { 1797004e86ffSlogin &FATDirEntry::VolId(_) => true, 1798004e86ffSlogin _ => false, 1799004e86ffSlogin } 1800004e86ffSlogin } 1801004e86ffSlogin 1802004e86ffSlogin /// @brief 判断FAT目录项的名字与给定的是否相等 1803004e86ffSlogin /// 1804004e86ffSlogin /// 由于FAT32对大小写不敏感,因此将字符都转为大写,然后比较 1805004e86ffSlogin /// 1806004e86ffSlogin /// @return bool 相等 => true 1807004e86ffSlogin /// 不相等 => false 1808004e86ffSlogin pub fn eq_name(&self, name: &str) -> bool { 1809004e86ffSlogin // 由于FAT32对大小写不敏感,因此将字符都转为大写,然后比较。 1810004e86ffSlogin let binding = self.short_name(); 1811004e86ffSlogin let short_name = binding.chars().flat_map(|c| c.to_uppercase()); 1812004e86ffSlogin let binding = self.name(); 1813004e86ffSlogin let long_name = binding.chars().flat_map(|c| c.to_uppercase()); 1814004e86ffSlogin let name = name.chars().flat_map(|c| c.to_uppercase()); 1815004e86ffSlogin 1816004e86ffSlogin let long_name_matches: bool = long_name.eq(name.clone()); 1817004e86ffSlogin let short_name_matches: bool = short_name.eq(name); 1818004e86ffSlogin 1819004e86ffSlogin return long_name_matches || short_name_matches; 1820004e86ffSlogin } 1821004e86ffSlogin 1822004e86ffSlogin /// @brief 将FATDirEntry转换为FATFile对象 1823676b8ef6SMork pub fn to_file(&self) -> Result<FATFile, SystemError> { 1824004e86ffSlogin if self.is_file() == false { 1825676b8ef6SMork return Err(SystemError::EISDIR); 1826004e86ffSlogin } 1827004e86ffSlogin 1828004e86ffSlogin match &self { 1829004e86ffSlogin FATDirEntry::File(f) | FATDirEntry::VolId(f) => { 1830004e86ffSlogin return Ok(f.clone()); 1831004e86ffSlogin } 1832004e86ffSlogin _ => unreachable!(), 1833004e86ffSlogin } 1834004e86ffSlogin } 1835004e86ffSlogin 1836004e86ffSlogin /// @brief 将FATDirEntry转换为FATDir对象 1837676b8ef6SMork pub fn to_dir(&self) -> Result<FATDir, SystemError> { 1838004e86ffSlogin if self.is_dir() == false { 1839676b8ef6SMork return Err(SystemError::ENOTDIR); 1840004e86ffSlogin } 1841004e86ffSlogin match &self { 1842004e86ffSlogin FATDirEntry::Dir(d) => { 1843004e86ffSlogin return Ok(d.clone()); 1844004e86ffSlogin } 1845004e86ffSlogin _ => unreachable!(), 1846004e86ffSlogin } 1847004e86ffSlogin } 1848004e86ffSlogin } 1849004e86ffSlogin 1850004e86ffSlogin /// 用于生成短目录项文件名的生成器。 1851004e86ffSlogin #[derive(Debug, Default)] 1852004e86ffSlogin pub struct ShortNameGenerator { 1853004e86ffSlogin /// 短目录项的名字 1854004e86ffSlogin name: [u8; 11], 1855004e86ffSlogin /// 生成器的标志位(使用impl里面的mask来解析) 1856004e86ffSlogin flags: u8, 1857004e86ffSlogin /// 基础名的长度 1858004e86ffSlogin basename_len: u8, 1859004e86ffSlogin /// 对于文件名形如(TE021F~1.TXT)的,短前缀+校验码的短目录项,该字段表示基础名末尾数字的对应位。 1860004e86ffSlogin checksum_bitmask: u16, 1861004e86ffSlogin /// Fletcher-16 Checksum(与填写到ShortDirEntry里面的不一样) 1862004e86ffSlogin checksum: u16, 1863004e86ffSlogin /// 对于形如(TEXTFI~1.TXT)的短目录项名称,其中的数字的bitmask(第0位置位则表示这个数字是0) 1864004e86ffSlogin suffix_bitmask: u16, 1865004e86ffSlogin } 1866004e86ffSlogin 1867004e86ffSlogin impl ShortNameGenerator { 1868004e86ffSlogin /// 短目录项的名称的长度 1869004e86ffSlogin const SHORT_NAME_LEN: usize = 8; 1870004e86ffSlogin 1871004e86ffSlogin // ===== flags标志位的含义 ===== 1872004e86ffSlogin const IS_LOSSY: u8 = (1 << 0); 1873004e86ffSlogin const IS_EXACT_MATCH: u8 = (1 << 1); 1874004e86ffSlogin const IS_DOT: u8 = (1 << 2); 1875004e86ffSlogin const IS_DOTDOT: u8 = (1 << 3); 1876004e86ffSlogin /// 名称被完全拷贝 1877004e86ffSlogin const NAME_FITS: u8 = (1 << 4); 1878004e86ffSlogin 1879004e86ffSlogin /// @brief 初始化一个短目录项名称生成器 1880004e86ffSlogin pub fn new(mut name: &str) -> Self { 1881004e86ffSlogin name = name.trim(); 1882004e86ffSlogin 1883004e86ffSlogin let mut short_name: [u8; 11] = [0x20u8; 11]; 1884004e86ffSlogin if name == "." { 1885004e86ffSlogin short_name[0] = '.' as u8; 1886004e86ffSlogin } 1887004e86ffSlogin 1888004e86ffSlogin if name == ".." { 1889004e86ffSlogin short_name[0] = '.' as u8; 1890004e86ffSlogin short_name[1] = '.' as u8; 1891004e86ffSlogin } 1892004e86ffSlogin 1893004e86ffSlogin // @name_fits: 名称是否被完全拷贝 1894004e86ffSlogin // @basename_len: 基础名的长度 1895004e86ffSlogin // @is_lossy: 是否存在不合法的字符 1896004e86ffSlogin let (name_fits, basename_len, is_lossy) = match name.rfind('.') { 1897004e86ffSlogin Some(index) => { 1898004e86ffSlogin // 文件名里面有".", 且index为最右边的点号所在的下标(bytes index) 1899004e86ffSlogin // 拷贝基础名 1900004e86ffSlogin let (b_len, fits, b_lossy) = 1901004e86ffSlogin Self::copy_part(&mut short_name[..Self::SHORT_NAME_LEN], &name[..index]); 1902004e86ffSlogin 1903004e86ffSlogin // 拷贝扩展名 1904004e86ffSlogin let (_, ext_fits, ext_lossy) = Self::copy_part( 1905004e86ffSlogin &mut short_name[Self::SHORT_NAME_LEN..Self::SHORT_NAME_LEN + 3], 1906004e86ffSlogin &name[index + 1..], 1907004e86ffSlogin ); 1908004e86ffSlogin 1909004e86ffSlogin (fits && ext_fits, b_len, b_lossy || ext_lossy) 1910004e86ffSlogin } 1911004e86ffSlogin None => { 1912004e86ffSlogin // 文件名中,不存在"." 1913004e86ffSlogin let (b_len, fits, b_lossy) = 1914004e86ffSlogin Self::copy_part(&mut short_name[..Self::SHORT_NAME_LEN], &name); 1915004e86ffSlogin (fits, b_len, b_lossy) 1916004e86ffSlogin } 1917004e86ffSlogin }; 1918004e86ffSlogin 1919004e86ffSlogin let mut flags: u8 = 0; 1920004e86ffSlogin // 设置flags 1921004e86ffSlogin if is_lossy { 1922004e86ffSlogin flags |= Self::IS_LOSSY; 1923004e86ffSlogin } 1924004e86ffSlogin if name == "." { 1925004e86ffSlogin flags |= Self::IS_DOT; 1926004e86ffSlogin } 1927004e86ffSlogin if name == ".." { 1928004e86ffSlogin flags |= Self::IS_DOTDOT; 1929004e86ffSlogin } 1930004e86ffSlogin 1931004e86ffSlogin if name_fits { 1932004e86ffSlogin flags |= Self::NAME_FITS; 1933004e86ffSlogin } 1934004e86ffSlogin 1935004e86ffSlogin return ShortNameGenerator { 1936004e86ffSlogin name: short_name, 1937004e86ffSlogin flags: flags, 1938004e86ffSlogin basename_len: basename_len, 1939004e86ffSlogin checksum: Self::fletcher_16_checksum(name), 1940004e86ffSlogin ..Default::default() 1941004e86ffSlogin }; 1942004e86ffSlogin } 1943004e86ffSlogin 1944004e86ffSlogin /// @brief 拷贝字符串到一个u8数组 1945004e86ffSlogin /// 1946004e86ffSlogin /// @return (u8, bool, bool) 1947004e86ffSlogin /// return.0: 拷贝了的字符串的长度 1948004e86ffSlogin /// return.1: 是否完全拷贝完整个字符串 1949004e86ffSlogin /// return.2: 拷贝过程中,是否出现了不合法字符 1950004e86ffSlogin fn copy_part(dest: &mut [u8], src: &str) -> (u8, bool, bool) { 1951004e86ffSlogin let mut dest_len: usize = 0; 1952004e86ffSlogin let mut lossy_conv = false; 1953004e86ffSlogin 1954004e86ffSlogin for c in src.chars() { 1955004e86ffSlogin // 如果src还有字符,而dest已经满了,那么表示没有完全拷贝完。 1956004e86ffSlogin if dest_len == dest.len() { 1957004e86ffSlogin return (dest_len as u8, false, lossy_conv); 1958004e86ffSlogin } 1959004e86ffSlogin 1960004e86ffSlogin if c == ' ' || c == '.' { 1961004e86ffSlogin lossy_conv = true; 1962004e86ffSlogin continue; 1963004e86ffSlogin } 1964004e86ffSlogin 1965004e86ffSlogin let cp: char = match c { 1966004e86ffSlogin 'a'..='z' | 'A'..='Z' | '0'..='9' => c, 1967004e86ffSlogin '$' | '%' | '\'' | '-' | '_' | '@' | '~' | '`' | '!' | '(' | ')' | '{' | '}' 1968004e86ffSlogin | '^' | '#' | '&' => c, 1969004e86ffSlogin _ => '_', 1970004e86ffSlogin }; 1971004e86ffSlogin 1972004e86ffSlogin // 判断是否存在不符合条件的字符 1973004e86ffSlogin lossy_conv = lossy_conv || c != cp; 1974004e86ffSlogin 1975004e86ffSlogin // 拷贝字符 1976004e86ffSlogin dest[dest_len] = c.to_ascii_uppercase() as u8; 1977004e86ffSlogin dest_len += 1; 1978004e86ffSlogin } 1979004e86ffSlogin 1980004e86ffSlogin // 返回结果 1981004e86ffSlogin return (dest_len as u8, true, lossy_conv); 1982004e86ffSlogin } 1983004e86ffSlogin 1984004e86ffSlogin fn fletcher_16_checksum(name: &str) -> u16 { 1985004e86ffSlogin let mut sum1: u16 = 0; 1986004e86ffSlogin let mut sum2: u16 = 0; 1987004e86ffSlogin for c in name.chars() { 1988004e86ffSlogin sum1 = (sum1 + (c as u16)) % 0xff; 1989004e86ffSlogin sum2 = (sum1 + sum2) & 0xff; 1990004e86ffSlogin } 1991004e86ffSlogin return (sum2 << 8) | sum1; 1992004e86ffSlogin } 1993004e86ffSlogin 1994004e86ffSlogin /// @brief 更新生成器的状态 1995004e86ffSlogin /// 当长目录项不存在的时候,需要调用这个函数来更新生成器的状态 1996004e86ffSlogin pub fn add_name(&mut self, name: &[u8; 11]) { 1997004e86ffSlogin // === 判断名称是否严格的完全匹配 1998004e86ffSlogin if name == &self.name { 1999004e86ffSlogin self.flags |= Self::IS_EXACT_MATCH; 2000004e86ffSlogin } 2001004e86ffSlogin 2002004e86ffSlogin // === 检查是否存在长前缀的格式冲突。对于这样的短目录项名称:(TEXTFI~1.TXT) 2003004e86ffSlogin // 获取名称前缀 2004004e86ffSlogin let prefix_len = min(self.basename_len, 6) as usize; 2005004e86ffSlogin // 获取后缀的那个数字 2006004e86ffSlogin let num_suffix: Option<u32> = if name[prefix_len] as char == '~' { 2007004e86ffSlogin (name[prefix_len + 1] as char).to_digit(10) 2008004e86ffSlogin } else { 2009004e86ffSlogin None 2010004e86ffSlogin }; 2011004e86ffSlogin 2012004e86ffSlogin // 判断扩展名是否匹配 2013004e86ffSlogin let ext_matches: bool = name[8..] == self.name[8..]; 2014004e86ffSlogin 2015004e86ffSlogin if name[..prefix_len] == self.name[..prefix_len] // 基础名前缀相同 2016004e86ffSlogin && num_suffix.is_some() // 基础名具有数字后缀 2017004e86ffSlogin && ext_matches 2018004e86ffSlogin // 扩展名相匹配 2019004e86ffSlogin { 2020004e86ffSlogin let num = num_suffix.unwrap(); 2021004e86ffSlogin self.suffix_bitmask |= 1 << num; 2022004e86ffSlogin } 2023004e86ffSlogin 2024004e86ffSlogin // === 检查是否存在短前缀+校验和的冲突,文件名形如:(TE021F~1.TXT) 2025004e86ffSlogin let prefix_len = min(self.basename_len, 2) as usize; 2026004e86ffSlogin let num_suffix: Option<u32> = if name[prefix_len + 4] as char == '~' { 2027004e86ffSlogin (name[prefix_len + 1] as char).to_digit(10) 2028004e86ffSlogin } else { 2029004e86ffSlogin None 2030004e86ffSlogin }; 2031004e86ffSlogin 2032004e86ffSlogin if name[..prefix_len] == self.name[..prefix_len] && num_suffix.is_some() && ext_matches { 2033004e86ffSlogin // 获取短文件名中的校验码字段 2034004e86ffSlogin let checksum_result: Result< 2035004e86ffSlogin Result<u16, core::num::ParseIntError>, 2036004e86ffSlogin core::str::Utf8Error, 2037004e86ffSlogin > = core::str::from_utf8(&name[prefix_len..prefix_len + 4]) 2038004e86ffSlogin .map(|s| u16::from_str_radix(s, 16)); 2039004e86ffSlogin // 如果校验码相同 2040004e86ffSlogin if checksum_result == Ok(Ok(self.checksum)) { 2041004e86ffSlogin let num = num_suffix.unwrap(); 2042004e86ffSlogin // 置位checksum_bitmask中,基础名末尾数字的对应位 2043004e86ffSlogin self.checksum_bitmask |= 1 << num; 2044004e86ffSlogin } 2045004e86ffSlogin } 2046004e86ffSlogin } 2047004e86ffSlogin 2048676b8ef6SMork pub fn generate(&self) -> Result<[u8; 11], SystemError> { 2049004e86ffSlogin if self.is_dot() || self.is_dotdot() { 2050004e86ffSlogin return Ok(self.name); 2051004e86ffSlogin } 2052004e86ffSlogin 2053004e86ffSlogin // 如果当前名字不存在不合法的字符,且名称被完整拷贝,但是exact match为false,可以认为名称没有冲突,直接返回 2054004e86ffSlogin if !self.is_lossy() && self.name_fits() && !self.is_exact_match() { 2055004e86ffSlogin return Ok(self.name); 2056004e86ffSlogin } 2057004e86ffSlogin 2058004e86ffSlogin // 尝试使用长前缀(6字符) 2059004e86ffSlogin for i in 1..5 { 2060004e86ffSlogin if self.suffix_bitmask & (1 << i) == 0 { 2061004e86ffSlogin return Ok(self.build_prefixed_name(i as u32, false)); 2062004e86ffSlogin } 2063004e86ffSlogin } 2064004e86ffSlogin 2065004e86ffSlogin // 尝试使用短前缀+校验码 2066004e86ffSlogin for i in 1..10 { 2067004e86ffSlogin if self.checksum_bitmask & (1 << i) == 0 { 2068004e86ffSlogin return Ok(self.build_prefixed_name(i as u32, true)); 2069004e86ffSlogin } 2070004e86ffSlogin } 2071004e86ffSlogin // 由于产生太多的冲突,因此返回错误(“短文件名已经存在”) 2072676b8ef6SMork return Err(SystemError::EEXIST); 2073004e86ffSlogin } 2074004e86ffSlogin 2075004e86ffSlogin pub fn next_iteration(&mut self) { 2076004e86ffSlogin // 在下一次迭代中,尝试一个不同的校验和 2077004e86ffSlogin self.checksum = (core::num::Wrapping(self.checksum) + core::num::Wrapping(1)).0; 2078004e86ffSlogin // 清空bitmask 2079004e86ffSlogin self.suffix_bitmask = 0; 2080004e86ffSlogin self.checksum_bitmask = 0; 2081004e86ffSlogin } 2082004e86ffSlogin 2083004e86ffSlogin /// @brief 构造具有前缀的短目录项名称 2084004e86ffSlogin /// 2085004e86ffSlogin /// @param num 这是第几个重名的前缀名 2086004e86ffSlogin /// @param with_checksum 前缀名中是否包含校验码 2087004e86ffSlogin /// 2088004e86ffSlogin /// @return 构造好的短目录项名称数组 2089004e86ffSlogin fn build_prefixed_name(&self, num: u32, with_checksum: bool) -> [u8; 11] { 2090004e86ffSlogin let mut buf: [u8; 11] = [0x20u8; 11]; 2091004e86ffSlogin let prefix_len: usize = if with_checksum { 2092004e86ffSlogin let prefix_len: usize = min(self.basename_len as usize, 2); 2093004e86ffSlogin buf[..prefix_len].copy_from_slice(&self.name[..prefix_len]); 2094004e86ffSlogin buf[prefix_len..prefix_len + 4].copy_from_slice(&Self::u16_to_u8_array(self.checksum)); 2095004e86ffSlogin prefix_len + 4 2096004e86ffSlogin } else { 2097004e86ffSlogin let prefix_len = min(self.basename_len as usize, 6); 2098004e86ffSlogin buf[..prefix_len].copy_from_slice(&self.name[..prefix_len]); 2099004e86ffSlogin prefix_len 2100004e86ffSlogin }; 2101004e86ffSlogin 2102004e86ffSlogin buf[prefix_len] = '~' as u8; 2103004e86ffSlogin buf[prefix_len + 1] = char::from_digit(num, 10).unwrap() as u8; 2104004e86ffSlogin buf[8..].copy_from_slice(&self.name[8..]); 2105004e86ffSlogin return buf; 2106004e86ffSlogin } 2107004e86ffSlogin 2108004e86ffSlogin /// @brief 将一个u16数字转换为十六进制大写字符串对应的ascii数组。 2109004e86ffSlogin /// 举例:将x=12345转换为16进制字符串“3039”对应的ascii码数组:[51,48,51,57] 2110004e86ffSlogin fn u16_to_u8_array(x: u16) -> [u8; 4] { 2111004e86ffSlogin let c1 = char::from_digit((x as u32 >> 12) & 0xf, 16) 2112004e86ffSlogin .unwrap() 2113004e86ffSlogin .to_ascii_uppercase() as u8; 2114004e86ffSlogin let c2 = char::from_digit((x as u32 >> 8) & 0xf, 16) 2115004e86ffSlogin .unwrap() 2116004e86ffSlogin .to_ascii_uppercase() as u8; 2117004e86ffSlogin let c3 = char::from_digit((x as u32 >> 4) & 0xf, 16) 2118004e86ffSlogin .unwrap() 2119004e86ffSlogin .to_ascii_uppercase() as u8; 2120004e86ffSlogin let c4 = char::from_digit((x as u32 >> 0) & 0xf, 16) 2121004e86ffSlogin .unwrap() 2122004e86ffSlogin .to_ascii_uppercase() as u8; 2123004e86ffSlogin return [c1, c2, c3, c4]; 2124004e86ffSlogin } 2125004e86ffSlogin 2126004e86ffSlogin #[inline] 2127004e86ffSlogin fn is_lossy(&self) -> bool { 2128004e86ffSlogin return (self.flags & Self::IS_LOSSY) > 0; 2129004e86ffSlogin } 2130004e86ffSlogin 2131004e86ffSlogin #[inline] 2132004e86ffSlogin fn is_exact_match(&self) -> bool { 2133004e86ffSlogin return (self.flags & Self::IS_EXACT_MATCH) > 0; 2134004e86ffSlogin } 2135004e86ffSlogin 2136004e86ffSlogin #[inline] 2137004e86ffSlogin fn is_dot(&self) -> bool { 2138004e86ffSlogin return (self.flags & Self::IS_DOT) > 0; 2139004e86ffSlogin } 2140004e86ffSlogin 2141004e86ffSlogin #[inline] 2142004e86ffSlogin fn is_dotdot(&self) -> bool { 2143004e86ffSlogin return (self.flags & Self::IS_DOTDOT) > 0; 2144004e86ffSlogin } 2145004e86ffSlogin 2146004e86ffSlogin #[inline] 2147004e86ffSlogin fn name_fits(&self) -> bool { 2148004e86ffSlogin return (self.flags & Self::NAME_FITS) > 0; 2149004e86ffSlogin } 2150004e86ffSlogin } 2151004e86ffSlogin 2152004e86ffSlogin /// 从多个LongName中提取完整文件名字段的提取器 2153004e86ffSlogin struct LongNameExtractor { 2154004e86ffSlogin name: Vec<u16>, 2155004e86ffSlogin checksum: u8, 2156004e86ffSlogin index: u8, 2157004e86ffSlogin } 2158004e86ffSlogin 2159004e86ffSlogin impl LongNameExtractor { 2160004e86ffSlogin fn new() -> Self { 2161004e86ffSlogin return LongNameExtractor { 2162004e86ffSlogin name: Vec::new(), 2163004e86ffSlogin checksum: 0, 2164004e86ffSlogin index: 0, 2165004e86ffSlogin }; 2166004e86ffSlogin } 2167004e86ffSlogin 2168004e86ffSlogin /// @brief 提取长目录项的名称 2169004e86ffSlogin /// @param longname_dentry 长目录项 2170004e86ffSlogin /// 请注意,必须倒序输入长目录项对象 2171676b8ef6SMork fn process(&mut self, longname_dentry: LongDirEntry) -> Result<(), SystemError> { 2172004e86ffSlogin let is_last: bool = longname_dentry.is_last(); 2173004e86ffSlogin let index: u8 = longname_dentry.ord & 0x1f; 2174004e86ffSlogin 2175004e86ffSlogin if index == 0 { 2176004e86ffSlogin self.name.clear(); 2177676b8ef6SMork return Err(SystemError::EROFS); 2178004e86ffSlogin } 2179004e86ffSlogin 2180004e86ffSlogin // 如果是最后一个LongDirEntry,则初始化当前生成器 2181004e86ffSlogin if is_last { 2182004e86ffSlogin self.index = index; 2183004e86ffSlogin self.checksum = longname_dentry.checksum; 2184004e86ffSlogin self.name 2185004e86ffSlogin .resize(index as usize * LongDirEntry::LONG_NAME_STR_LEN, 0); 2186004e86ffSlogin } else if self.index == 0 2187004e86ffSlogin || index != self.index - 1 2188004e86ffSlogin || self.checksum != longname_dentry.checksum 2189004e86ffSlogin { 2190004e86ffSlogin // 如果当前index为0,或者index不连续,或者是校验和不同,那么认为文件系统损坏,清除生成器的名称字段 2191004e86ffSlogin // TODO: 对文件系统的变为只读状态状况的拦截 2192004e86ffSlogin self.name.clear(); 2193676b8ef6SMork return Err(SystemError::EROFS); 2194004e86ffSlogin } else { 2195004e86ffSlogin // 由于dentry倒序输入,因此index是每次减1的 2196004e86ffSlogin self.index -= 1; 2197004e86ffSlogin } 2198004e86ffSlogin 2199004e86ffSlogin let pos: usize = ((index - 1) as usize) * LongDirEntry::LONG_NAME_STR_LEN; 2200004e86ffSlogin // 将当前目录项的值,拷贝到生成器的数组中 2201004e86ffSlogin longname_dentry 2202004e86ffSlogin .copy_name_to_slice(&mut self.name[pos..pos + LongDirEntry::LONG_NAME_STR_LEN])?; 2203004e86ffSlogin return Ok(()); 2204004e86ffSlogin } 2205004e86ffSlogin 2206004e86ffSlogin /// @brief 返回名称的长度 2207004e86ffSlogin #[inline] 2208004e86ffSlogin fn len(&self) -> usize { 2209004e86ffSlogin return self.name.len(); 2210004e86ffSlogin } 2211004e86ffSlogin 2212004e86ffSlogin /// @brief 返回抽取得到的名称字符串 2213004e86ffSlogin fn to_string(&self) -> String { 2214004e86ffSlogin let mut s = String::from_utf16_lossy(self.name.as_slice()); 2215004e86ffSlogin // 计算字符串的长度。如果字符串中有\0,那么就截取字符串的前面部分 2216004e86ffSlogin if let Some(len) = s.find('\u{0}') { 2217004e86ffSlogin s.truncate(len); 2218004e86ffSlogin } 2219004e86ffSlogin return s; 2220004e86ffSlogin } 2221004e86ffSlogin 2222004e86ffSlogin /// @brief 判断校验码是否与指定的短目录项的校验码相同 2223004e86ffSlogin /// 2224004e86ffSlogin /// @return bool 相同 => true 2225004e86ffSlogin /// 不同 => false 2226004e86ffSlogin fn validate_checksum(&self, short_dentry: &ShortDirEntry) -> bool { 2227004e86ffSlogin return self.checksum == short_dentry.checksum(); 2228004e86ffSlogin } 2229004e86ffSlogin } 2230004e86ffSlogin 2231004e86ffSlogin /// @brief 长目录项生成器 2232004e86ffSlogin #[derive(Debug)] 2233004e86ffSlogin struct LongNameEntryGenerator { 2234004e86ffSlogin name: Vec<u16>, 2235004e86ffSlogin // 短目录项的校验和 2236004e86ffSlogin checksum: u8, 2237004e86ffSlogin // 当前迭代器的索引 2238004e86ffSlogin idx: u8, 2239004e86ffSlogin /// 最后一个目录项的索引 2240004e86ffSlogin last_index: u8, 2241004e86ffSlogin } 2242004e86ffSlogin 2243004e86ffSlogin impl LongNameEntryGenerator { 2244004e86ffSlogin /// @brief 初始化长目录项生成器 2245004e86ffSlogin /// 2246004e86ffSlogin /// @param name 长文件名数组 2247004e86ffSlogin /// @param checksum 短目录项的校验和 2248004e86ffSlogin pub fn new(name: &str, checksum: u8) -> Self { 2249004e86ffSlogin let mut name: Vec<u16> = name.chars().map(|c| c as u16).collect(); 2250004e86ffSlogin 2251004e86ffSlogin let padding_bytes: usize = (13 - (name.len() % 13)) % 13; 2252004e86ffSlogin // 填充最后一个长目录项的文件名 2253004e86ffSlogin for i in 0..padding_bytes { 2254004e86ffSlogin if i == 0 { 2255004e86ffSlogin name.push(0); 2256004e86ffSlogin } else { 2257004e86ffSlogin name.push(0xffff); 2258004e86ffSlogin } 2259004e86ffSlogin } 2260004e86ffSlogin 2261004e86ffSlogin // 先从最后一个长目录项开始生成 2262004e86ffSlogin let start_index = (name.len() / 13) as u8; 2263004e86ffSlogin return LongNameEntryGenerator { 2264004e86ffSlogin name: name, 2265004e86ffSlogin checksum: checksum, 2266004e86ffSlogin idx: start_index, 2267004e86ffSlogin last_index: start_index, 2268004e86ffSlogin }; 2269004e86ffSlogin } 2270004e86ffSlogin 2271004e86ffSlogin /// @brief 返回要生成的长目录项的总数 2272004e86ffSlogin pub fn num_entries(&self) -> u8 { 2273004e86ffSlogin return self.last_index + 1; 2274004e86ffSlogin } 2275004e86ffSlogin } 2276004e86ffSlogin 2277004e86ffSlogin impl Iterator for LongNameEntryGenerator { 2278004e86ffSlogin type Item = LongDirEntry; 2279004e86ffSlogin 2280004e86ffSlogin fn next(&mut self) -> Option<Self::Item> { 2281004e86ffSlogin match self.idx { 2282004e86ffSlogin 0 => { 2283004e86ffSlogin return None; 2284004e86ffSlogin } 2285004e86ffSlogin // 最后一个长目录项 2286004e86ffSlogin n if n == self.last_index => { 2287004e86ffSlogin // 最后一个长目录项的ord需要与0x40相或 2288004e86ffSlogin let ord: u8 = n | 0x40; 2289004e86ffSlogin let start_idx = ((n - 1) * 13) as usize; 2290004e86ffSlogin self.idx -= 1; 2291004e86ffSlogin return Some(LongDirEntry::new( 2292004e86ffSlogin ord, 2293004e86ffSlogin &self.name.as_slice()[start_idx..start_idx + 13], 2294004e86ffSlogin self.checksum, 2295004e86ffSlogin )); 2296004e86ffSlogin } 2297004e86ffSlogin n => { 2298004e86ffSlogin // 其它的长目录项 2299004e86ffSlogin let start_idx = ((n - 1) * 13) as usize; 2300004e86ffSlogin self.idx -= 1; 2301004e86ffSlogin return Some(LongDirEntry::new( 2302004e86ffSlogin n, 2303004e86ffSlogin &self.name.as_slice()[start_idx..start_idx + 13], 2304004e86ffSlogin self.checksum, 2305004e86ffSlogin )); 2306004e86ffSlogin } 2307004e86ffSlogin } 2308004e86ffSlogin } 2309004e86ffSlogin } 2310004e86ffSlogin 2311004e86ffSlogin #[derive(Debug)] 2312004e86ffSlogin pub enum FATDirEntryOrShortName { 2313004e86ffSlogin DirEntry(FATDirEntry), 2314004e86ffSlogin ShortName([u8; 11]), 2315004e86ffSlogin } 2316004e86ffSlogin 2317004e86ffSlogin /// @brief 对FAT目录项的迭代器(基于簇和簇内偏移量) 2318004e86ffSlogin #[derive(Debug)] 2319004e86ffSlogin struct FATDirEntryOffsetIter { 2320004e86ffSlogin /// 当前迭代的偏移量(下一次迭代要返回的值) 2321004e86ffSlogin current_offset: (Cluster, u64), 2322004e86ffSlogin /// 截止迭代的位置(end_offset所在的位置也会被迭代器返回) 2323004e86ffSlogin end_offset: Option<(Cluster, u64)>, 2324004e86ffSlogin /// 属于的文件系统 2325004e86ffSlogin fs: Arc<FATFileSystem>, 2326004e86ffSlogin /// 当前已经迭代了多少次 2327004e86ffSlogin index: u64, 2328004e86ffSlogin /// 总共要迭代多少次 2329004e86ffSlogin len: u64, 2330004e86ffSlogin /// 如果end_offset不为None,该字段表示“是否已经到达了迭代终点” 2331004e86ffSlogin fin: bool, 2332004e86ffSlogin } 2333004e86ffSlogin 2334004e86ffSlogin impl FATDirEntryOffsetIter { 2335004e86ffSlogin /// @brief 初始化FAT目录项的迭代器(基于簇和簇内偏移量) 2336004e86ffSlogin /// 2337004e86ffSlogin /// @param fs 属于的文件系统 2338004e86ffSlogin /// @param start 起始偏移量 2339004e86ffSlogin /// @param len 要迭代的次数 2340004e86ffSlogin /// @param end_offset 截止迭代的位置(end_offset所在的位置也会被迭代器返回) 2341004e86ffSlogin /// 2342004e86ffSlogin /// @return 构建好的迭代器对象 2343004e86ffSlogin pub fn new( 2344004e86ffSlogin fs: Arc<FATFileSystem>, 2345004e86ffSlogin start: (Cluster, u64), 2346004e86ffSlogin len: u64, 2347004e86ffSlogin end_offset: Option<(Cluster, u64)>, 2348004e86ffSlogin ) -> Self { 2349004e86ffSlogin return FATDirEntryOffsetIter { 2350004e86ffSlogin current_offset: start, 2351004e86ffSlogin end_offset, 2352004e86ffSlogin fs, 2353004e86ffSlogin index: 0, 2354004e86ffSlogin len, 2355004e86ffSlogin fin: false, 2356004e86ffSlogin }; 2357004e86ffSlogin } 2358004e86ffSlogin } 2359004e86ffSlogin 2360004e86ffSlogin impl Iterator for FATDirEntryOffsetIter { 2361004e86ffSlogin type Item = (Cluster, u64); 2362004e86ffSlogin 2363004e86ffSlogin fn next(&mut self) -> Option<Self::Item> { 2364004e86ffSlogin if self.index == self.len || self.fin { 2365004e86ffSlogin return None; 2366004e86ffSlogin } 2367004e86ffSlogin 2368004e86ffSlogin let r: (Cluster, u64) = self.current_offset; 2369004e86ffSlogin // 计算新的字节偏移量 2370004e86ffSlogin let mut new_offset = r.1 + FATRawDirEntry::DIR_ENTRY_LEN; 2371004e86ffSlogin let mut new_cluster: Cluster = r.0; 2372004e86ffSlogin // 越过了当前簇,则获取下一个簇 2373004e86ffSlogin if new_offset >= self.fs.bytes_per_cluster() { 2374004e86ffSlogin new_offset %= self.fs.bytes_per_cluster(); 2375004e86ffSlogin 2376004e86ffSlogin match self.fs.get_fat_entry(new_cluster) { 2377004e86ffSlogin Ok(FATEntry::Next(c)) => { 2378004e86ffSlogin new_cluster = c; 2379004e86ffSlogin } 2380004e86ffSlogin // 没有下一个簇了 2381004e86ffSlogin _ => { 2382004e86ffSlogin self.fin = true; 2383004e86ffSlogin } 2384004e86ffSlogin } 2385004e86ffSlogin } 2386004e86ffSlogin 2387004e86ffSlogin if let Some(off) = self.end_offset { 2388004e86ffSlogin // 判断当前簇是否是要求停止搜索的最后一个位置 2389004e86ffSlogin self.fin = off == self.current_offset; 2390004e86ffSlogin } 2391004e86ffSlogin // 更新当前迭代的偏移量 2392004e86ffSlogin self.current_offset = (new_cluster, new_offset); 2393004e86ffSlogin self.index += 1; 2394004e86ffSlogin 2395004e86ffSlogin return Some(r); 2396004e86ffSlogin } 2397004e86ffSlogin } 2398004e86ffSlogin 2399004e86ffSlogin /// @brief 根据磁盘内字节偏移量,读取磁盘,并生成一个FATRawDirEntry对象 2400004e86ffSlogin pub fn get_raw_dir_entry( 2401004e86ffSlogin fs: &Arc<FATFileSystem>, 2402004e86ffSlogin in_disk_bytes_offset: u64, 2403676b8ef6SMork ) -> Result<FATRawDirEntry, SystemError> { 2404004e86ffSlogin // 块内偏移量 2405004e86ffSlogin let blk_offset: u64 = fs.get_in_block_offset(in_disk_bytes_offset); 2406004e86ffSlogin let lba = fs.get_lba_from_offset( 2407004e86ffSlogin fs.bytes_to_sector(fs.get_in_partition_bytes_offset(in_disk_bytes_offset)), 2408004e86ffSlogin ); 2409004e86ffSlogin 2410004e86ffSlogin // let step1 = fs.get_in_partition_bytes_offset(in_disk_bytes_offset); 2411004e86ffSlogin // let step2 = fs.bytes_to_sector(step1); 2412004e86ffSlogin // let lba = fs.get_lba_from_offset(step2); 2413004e86ffSlogin // kdebug!("step1={step1}, step2={step2}, lba={lba}"); 2414004e86ffSlogin let mut v: Vec<u8> = Vec::new(); 2415004e86ffSlogin v.resize(1 * LBA_SIZE, 0); 2416004e86ffSlogin 2417004e86ffSlogin fs.partition.disk().read_at(lba, 1, &mut v)?; 2418004e86ffSlogin 2419004e86ffSlogin let mut cursor: VecCursor = VecCursor::new(v); 2420004e86ffSlogin // 切换游标到对应位置 2421004e86ffSlogin cursor.seek(SeekFrom::SeekSet(blk_offset as i64))?; 2422004e86ffSlogin 2423004e86ffSlogin let dir_0 = cursor.read_u8()?; 2424004e86ffSlogin 2425004e86ffSlogin match dir_0 { 2426004e86ffSlogin 0x00 => { 2427004e86ffSlogin return Ok(FATRawDirEntry::FreeRest); 2428004e86ffSlogin } 2429004e86ffSlogin 0xe5 => { 2430004e86ffSlogin return Ok(FATRawDirEntry::Free); 2431004e86ffSlogin } 2432004e86ffSlogin _ => { 2433004e86ffSlogin cursor.seek(SeekFrom::SeekCurrent(10))?; 2434004e86ffSlogin let file_attr: FileAttributes = FileAttributes::new(cursor.read_u8()?); 2435004e86ffSlogin 2436004e86ffSlogin // 指针回到目录项的开始处 2437004e86ffSlogin cursor.seek(SeekFrom::SeekSet(blk_offset as i64))?; 2438004e86ffSlogin 2439004e86ffSlogin if file_attr.contains(FileAttributes::LONG_NAME) { 2440004e86ffSlogin // 当前目录项是一个长目录项 2441004e86ffSlogin let mut long_dentry = LongDirEntry::default(); 2442004e86ffSlogin 2443004e86ffSlogin long_dentry.ord = cursor.read_u8()?; 2444004e86ffSlogin cursor.read_u16_into(&mut long_dentry.name1)?; 2445004e86ffSlogin long_dentry.file_attrs = FileAttributes::new(cursor.read_u8()?); 2446004e86ffSlogin long_dentry.dirent_type = cursor.read_u8()?; 2447004e86ffSlogin long_dentry.checksum = cursor.read_u8()?; 2448004e86ffSlogin 2449004e86ffSlogin cursor.read_u16_into(&mut long_dentry.name2)?; 2450004e86ffSlogin long_dentry.first_clus_low = cursor.read_u16()?; 2451004e86ffSlogin cursor.read_u16_into(&mut long_dentry.name3)?; 2452004e86ffSlogin 2453004e86ffSlogin return Ok(FATRawDirEntry::Long(long_dentry)); 2454004e86ffSlogin } else { 2455004e86ffSlogin // 当前目录项是一个短目录项 2456004e86ffSlogin let mut short_dentry = ShortDirEntry::default(); 2457004e86ffSlogin cursor.read_exact(&mut short_dentry.name)?; 2458004e86ffSlogin 2459004e86ffSlogin short_dentry.attributes = FileAttributes::new(cursor.read_u8()?); 2460004e86ffSlogin 2461004e86ffSlogin short_dentry.nt_res = cursor.read_u8()?; 2462004e86ffSlogin short_dentry.crt_time_tenth = cursor.read_u8()?; 2463004e86ffSlogin short_dentry.crt_time = cursor.read_u16()?; 2464004e86ffSlogin short_dentry.crt_date = cursor.read_u16()?; 2465004e86ffSlogin short_dentry.lst_acc_date = cursor.read_u16()?; 2466004e86ffSlogin short_dentry.fst_clus_hi = cursor.read_u16()?; 2467004e86ffSlogin short_dentry.wrt_time = cursor.read_u16()?; 2468004e86ffSlogin short_dentry.wrt_date = cursor.read_u16()?; 2469004e86ffSlogin short_dentry.fst_clus_lo = cursor.read_u16()?; 2470004e86ffSlogin short_dentry.file_size = cursor.read_u32()?; 2471004e86ffSlogin 2472004e86ffSlogin return Ok(FATRawDirEntry::Short(short_dentry)); 2473004e86ffSlogin } 2474004e86ffSlogin } 2475004e86ffSlogin } 2476004e86ffSlogin } 2477