1*004e86ffSlogin #![allow(dead_code)] 2*004e86ffSlogin use core::cmp::min; 3*004e86ffSlogin 4*004e86ffSlogin use alloc::{ 5*004e86ffSlogin string::{String, ToString}, 6*004e86ffSlogin sync::Arc, 7*004e86ffSlogin vec::Vec, 8*004e86ffSlogin }; 9*004e86ffSlogin 10*004e86ffSlogin use crate::{ 11*004e86ffSlogin include::bindings::bindings::{ 12*004e86ffSlogin EEXIST, EILSEQ, EINVAL, EISDIR, ENAMETOOLONG, ENOENT, ENOSPC, ENOTDIR, ENOTEMPTY, EPERM, 13*004e86ffSlogin EROFS, 14*004e86ffSlogin }, 15*004e86ffSlogin io::{device::LBA_SIZE, SeekFrom}, 16*004e86ffSlogin kwarn, 17*004e86ffSlogin libs::vec_cursor::VecCursor, 18*004e86ffSlogin }; 19*004e86ffSlogin 20*004e86ffSlogin use super::{ 21*004e86ffSlogin fs::{Cluster, FATFileSystem, MAX_FILE_SIZE}, 22*004e86ffSlogin utils::decode_u8_ascii, 23*004e86ffSlogin }; 24*004e86ffSlogin 25*004e86ffSlogin #[derive(Debug, Clone, Copy, Default)] 26*004e86ffSlogin pub struct FileAttributes { 27*004e86ffSlogin value: u8, 28*004e86ffSlogin } 29*004e86ffSlogin 30*004e86ffSlogin /// FAT表中,关于每个簇的信息 31*004e86ffSlogin #[derive(Debug, Eq, PartialEq)] 32*004e86ffSlogin pub enum FATEntry { 33*004e86ffSlogin /// 当前簇未使用 34*004e86ffSlogin Unused, 35*004e86ffSlogin /// 当前簇是坏簇 36*004e86ffSlogin Bad, 37*004e86ffSlogin /// 当前簇是整个FAT簇链的最后一个簇 38*004e86ffSlogin EndOfChain, 39*004e86ffSlogin /// 在整个链中,当前簇的下一个簇的值 40*004e86ffSlogin Next(Cluster), 41*004e86ffSlogin } 42*004e86ffSlogin 43*004e86ffSlogin /// FAT目录项的枚举类型 44*004e86ffSlogin #[derive(Debug, Clone)] 45*004e86ffSlogin pub enum FATDirEntry { 46*004e86ffSlogin File(FATFile), 47*004e86ffSlogin VolId(FATFile), 48*004e86ffSlogin Dir(FATDir), 49*004e86ffSlogin UnInit, 50*004e86ffSlogin } 51*004e86ffSlogin 52*004e86ffSlogin /// FAT文件系统中的文件 53*004e86ffSlogin #[derive(Debug, Default, Clone)] 54*004e86ffSlogin pub struct FATFile { 55*004e86ffSlogin /// 文件的第一个簇 56*004e86ffSlogin pub first_cluster: Cluster, 57*004e86ffSlogin /// 文件名 58*004e86ffSlogin pub file_name: String, 59*004e86ffSlogin /// 文件对应的短目录项 60*004e86ffSlogin pub short_dir_entry: ShortDirEntry, 61*004e86ffSlogin /// 文件目录项的起始、终止簇。格式:(簇,簇内偏移量) 62*004e86ffSlogin pub loc: ((Cluster, u64), (Cluster, u64)), 63*004e86ffSlogin } 64*004e86ffSlogin 65*004e86ffSlogin impl FATFile { 66*004e86ffSlogin /// @brief 获取文件大小 67*004e86ffSlogin #[inline] 68*004e86ffSlogin pub fn size(&self) -> u64 { 69*004e86ffSlogin return self.short_dir_entry.file_size as u64; 70*004e86ffSlogin } 71*004e86ffSlogin 72*004e86ffSlogin /// @brief 设置当前文件大小(仅仅更改short_dir_entry内的值) 73*004e86ffSlogin #[inline] 74*004e86ffSlogin pub fn set_size(&mut self, size: u32) { 75*004e86ffSlogin self.short_dir_entry.file_size = size; 76*004e86ffSlogin } 77*004e86ffSlogin 78*004e86ffSlogin /// @brief 从文件读取数据。读取的字节数与buf长度相等 79*004e86ffSlogin /// 80*004e86ffSlogin /// @param buf 输出缓冲区 81*004e86ffSlogin /// @param offset 起始位置在文件中的偏移量 82*004e86ffSlogin /// 83*004e86ffSlogin /// @return Ok(usize) 成功读取到的字节数 84*004e86ffSlogin /// @return Err(i32) 读取时出现错误,返回错误码 85*004e86ffSlogin pub fn read(&self, fs: &Arc<FATFileSystem>, buf: &mut [u8], offset: u64) -> Result<usize, i32> { 86*004e86ffSlogin if offset >= self.size() { 87*004e86ffSlogin return Ok(0); 88*004e86ffSlogin } 89*004e86ffSlogin 90*004e86ffSlogin // 文件内的簇偏移量 91*004e86ffSlogin let start_cluster_number: u64 = offset / fs.bytes_per_cluster(); 92*004e86ffSlogin // 计算对应在分区内的簇号 93*004e86ffSlogin let mut current_cluster = if let Some(c) = 94*004e86ffSlogin fs.get_cluster_by_relative(self.first_cluster, start_cluster_number as usize) 95*004e86ffSlogin { 96*004e86ffSlogin c 97*004e86ffSlogin } else { 98*004e86ffSlogin return Ok(0); 99*004e86ffSlogin }; 100*004e86ffSlogin 101*004e86ffSlogin let bytes_remain: u64 = self.size() - offset; 102*004e86ffSlogin 103*004e86ffSlogin // 计算簇内偏移量 104*004e86ffSlogin let mut in_cluster_offset: u64 = offset % fs.bytes_per_cluster(); 105*004e86ffSlogin let to_read_size: usize = min(buf.len(), bytes_remain as usize); 106*004e86ffSlogin 107*004e86ffSlogin let mut start = 0; 108*004e86ffSlogin let mut read_ok = 0; 109*004e86ffSlogin 110*004e86ffSlogin loop { 111*004e86ffSlogin // 当前簇已经读取完,尝试读取下一个簇 112*004e86ffSlogin if in_cluster_offset >= fs.bytes_per_cluster() { 113*004e86ffSlogin if let Some(FATEntry::Next(c)) = fs.get_fat_entry(current_cluster).ok() { 114*004e86ffSlogin current_cluster = c; 115*004e86ffSlogin in_cluster_offset %= fs.bytes_per_cluster(); 116*004e86ffSlogin } else { 117*004e86ffSlogin break; 118*004e86ffSlogin } 119*004e86ffSlogin } 120*004e86ffSlogin 121*004e86ffSlogin // 计算下一次读取,能够读多少字节 122*004e86ffSlogin let end_len: usize = min( 123*004e86ffSlogin to_read_size - read_ok, 124*004e86ffSlogin min( 125*004e86ffSlogin (fs.bytes_per_cluster() - in_cluster_offset) as usize, 126*004e86ffSlogin buf.len() - read_ok, 127*004e86ffSlogin ), 128*004e86ffSlogin ); 129*004e86ffSlogin 130*004e86ffSlogin // 从磁盘上读取数据 131*004e86ffSlogin let offset = fs.cluster_bytes_offset(current_cluster) + in_cluster_offset; 132*004e86ffSlogin let r = fs.partition.disk().device().read_at( 133*004e86ffSlogin offset as usize, 134*004e86ffSlogin end_len, 135*004e86ffSlogin &mut buf[start..start + end_len], 136*004e86ffSlogin )?; 137*004e86ffSlogin 138*004e86ffSlogin // 更新偏移量计数信息 139*004e86ffSlogin read_ok += r; 140*004e86ffSlogin start += r; 141*004e86ffSlogin in_cluster_offset += r as u64; 142*004e86ffSlogin if read_ok == to_read_size { 143*004e86ffSlogin break; 144*004e86ffSlogin } 145*004e86ffSlogin } 146*004e86ffSlogin // todo: 更新时间信息 147*004e86ffSlogin return Ok(read_ok); 148*004e86ffSlogin } 149*004e86ffSlogin 150*004e86ffSlogin /// @brief 向文件写入数据。写入的字节数与buf长度相等 151*004e86ffSlogin /// 152*004e86ffSlogin /// @param buf 输入缓冲区 153*004e86ffSlogin /// @param offset 起始位置在文件中的偏移量 154*004e86ffSlogin /// 155*004e86ffSlogin /// @return Ok(usize) 成功写入的字节数 156*004e86ffSlogin /// @return Err(i32) 写入时出现错误,返回错误码 157*004e86ffSlogin pub fn write( 158*004e86ffSlogin &mut self, 159*004e86ffSlogin fs: &Arc<FATFileSystem>, 160*004e86ffSlogin buf: &[u8], 161*004e86ffSlogin offset: u64, 162*004e86ffSlogin ) -> Result<usize, i32> { 163*004e86ffSlogin self.ensure_len(fs, offset, buf.len() as u64)?; 164*004e86ffSlogin 165*004e86ffSlogin // 要写入的第一个簇的簇号 166*004e86ffSlogin let start_cluster_num = offset / fs.bytes_per_cluster(); 167*004e86ffSlogin 168*004e86ffSlogin // 获取要写入的第一个簇 169*004e86ffSlogin let mut current_cluster: Cluster = if let Some(c) = 170*004e86ffSlogin fs.get_cluster_by_relative(self.first_cluster, start_cluster_num as usize) 171*004e86ffSlogin { 172*004e86ffSlogin c 173*004e86ffSlogin } else { 174*004e86ffSlogin return Ok(0); 175*004e86ffSlogin }; 176*004e86ffSlogin 177*004e86ffSlogin let mut in_cluster_bytes_offset: u64 = offset % fs.bytes_per_cluster(); 178*004e86ffSlogin 179*004e86ffSlogin let mut start: usize = 0; 180*004e86ffSlogin let mut write_ok: usize = 0; 181*004e86ffSlogin 182*004e86ffSlogin // 循环写入数据 183*004e86ffSlogin loop { 184*004e86ffSlogin if in_cluster_bytes_offset >= fs.bytes_per_cluster() { 185*004e86ffSlogin if let Some(FATEntry::Next(c)) = fs.get_fat_entry(current_cluster).ok() { 186*004e86ffSlogin current_cluster = c; 187*004e86ffSlogin in_cluster_bytes_offset = in_cluster_bytes_offset % fs.bytes_per_cluster(); 188*004e86ffSlogin } else { 189*004e86ffSlogin break; 190*004e86ffSlogin } 191*004e86ffSlogin } 192*004e86ffSlogin 193*004e86ffSlogin let end_len = min( 194*004e86ffSlogin (fs.bytes_per_cluster() - in_cluster_bytes_offset) as usize, 195*004e86ffSlogin buf.len() - write_ok, 196*004e86ffSlogin ); 197*004e86ffSlogin 198*004e86ffSlogin // 计算本次写入位置在磁盘上的偏移量 199*004e86ffSlogin let offset = fs.cluster_bytes_offset(current_cluster) + in_cluster_bytes_offset; 200*004e86ffSlogin // 写入磁盘 201*004e86ffSlogin let w: usize = fs.partition.disk().device().write_at( 202*004e86ffSlogin offset as usize, 203*004e86ffSlogin end_len, 204*004e86ffSlogin &buf[start..start + end_len], 205*004e86ffSlogin )?; 206*004e86ffSlogin 207*004e86ffSlogin // 更新偏移量数据 208*004e86ffSlogin write_ok += w; 209*004e86ffSlogin start += w; 210*004e86ffSlogin in_cluster_bytes_offset += w as u64; 211*004e86ffSlogin 212*004e86ffSlogin if write_ok == buf.len() { 213*004e86ffSlogin break; 214*004e86ffSlogin } 215*004e86ffSlogin } 216*004e86ffSlogin // todo: 更新时间信息 217*004e86ffSlogin return Ok(write_ok); 218*004e86ffSlogin } 219*004e86ffSlogin 220*004e86ffSlogin /// @brief 确保文件从指定偏移量开始,仍有长度为len的空间。 221*004e86ffSlogin /// 如果文件大小不够,就尝试分配更多的空间给这个文件。 222*004e86ffSlogin /// 223*004e86ffSlogin /// @param fs 当前文件所属的文件系统 224*004e86ffSlogin /// @param offset 起始位置在文件内的字节偏移量 225*004e86ffSlogin /// @param len 期待的空闲空间长度 226*004e86ffSlogin /// 227*004e86ffSlogin /// @return Ok(()) 经过操作后,offset后面具有长度至少为len的空闲空间 228*004e86ffSlogin /// @return Err(i32) 处理过程中出现了异常。 229*004e86ffSlogin fn ensure_len(&mut self, fs: &Arc<FATFileSystem>, offset: u64, len: u64) -> Result<(), i32> { 230*004e86ffSlogin // 文件内本身就还有空余的空间 231*004e86ffSlogin if offset + len <= self.size() { 232*004e86ffSlogin return Ok(()); 233*004e86ffSlogin } 234*004e86ffSlogin 235*004e86ffSlogin // 如果文件大小为0,证明它还没有分配簇,因此分配一个簇给它 236*004e86ffSlogin if self.size() == 0 { 237*004e86ffSlogin // first_cluster应当为0,否则将产生空间泄露的错误 238*004e86ffSlogin assert_eq!(self.first_cluster, Cluster::default()); 239*004e86ffSlogin self.first_cluster = fs.allocate_cluster(None)?; 240*004e86ffSlogin self.short_dir_entry.set_first_cluster(self.first_cluster); 241*004e86ffSlogin } 242*004e86ffSlogin 243*004e86ffSlogin // 计算文件的最后一个簇中有多少空闲空间 244*004e86ffSlogin 245*004e86ffSlogin let in_cluster_offset = self.size() % fs.bytes_per_cluster(); 246*004e86ffSlogin let bytes_remain_in_cluster = fs.bytes_per_cluster() - in_cluster_offset; 247*004e86ffSlogin 248*004e86ffSlogin // 计算还需要申请多少空间 249*004e86ffSlogin let extra_bytes = min((offset + len) - self.size(), MAX_FILE_SIZE - self.size()); 250*004e86ffSlogin 251*004e86ffSlogin // 如果还需要更多的簇 252*004e86ffSlogin if bytes_remain_in_cluster < extra_bytes { 253*004e86ffSlogin let clusters_to_allocate = 254*004e86ffSlogin (extra_bytes - bytes_remain_in_cluster + fs.bytes_per_cluster() - 1) 255*004e86ffSlogin / fs.bytes_per_cluster(); 256*004e86ffSlogin let last_cluster = if let Some(c) = fs.get_last_cluster(self.first_cluster) { 257*004e86ffSlogin c 258*004e86ffSlogin } else { 259*004e86ffSlogin kwarn!("FAT: last cluster not found, File = {self:?}"); 260*004e86ffSlogin return Err(-(EINVAL as i32)); 261*004e86ffSlogin }; 262*004e86ffSlogin // 申请簇 263*004e86ffSlogin let mut current_cluster: Cluster = last_cluster; 264*004e86ffSlogin for _ in 0..clusters_to_allocate { 265*004e86ffSlogin current_cluster = fs.allocate_cluster(Some(current_cluster))?; 266*004e86ffSlogin } 267*004e86ffSlogin } 268*004e86ffSlogin 269*004e86ffSlogin // 如果文件被扩展,则清空刚刚被扩展的部分的数据 270*004e86ffSlogin if offset > self.size() { 271*004e86ffSlogin // 文件内的簇偏移 272*004e86ffSlogin let start_cluster: u64 = self.size() / fs.bytes_per_cluster(); 273*004e86ffSlogin let start_cluster: Cluster = fs 274*004e86ffSlogin .get_cluster_by_relative(self.first_cluster, start_cluster as usize) 275*004e86ffSlogin .unwrap(); 276*004e86ffSlogin // 计算当前文件末尾在磁盘上的字节偏移量 277*004e86ffSlogin let start_offset: u64 = 278*004e86ffSlogin fs.cluster_bytes_offset(start_cluster) + self.size() % fs.bytes_per_cluster(); 279*004e86ffSlogin // 扩展之前,最后一个簇内还剩下多少字节的空间 280*004e86ffSlogin let bytes_remain: u64 = fs.bytes_per_cluster() - (self.size() % fs.bytes_per_cluster()); 281*004e86ffSlogin // 计算在扩展之后的最后一个簇内,文件的终止字节 282*004e86ffSlogin let cluster_offset_start = offset / fs.bytes_per_cluster(); 283*004e86ffSlogin // 扩展后,文件的最后 284*004e86ffSlogin let end_cluster: Cluster = fs 285*004e86ffSlogin .get_cluster_by_relative(self.first_cluster, cluster_offset_start as usize) 286*004e86ffSlogin .unwrap(); 287*004e86ffSlogin 288*004e86ffSlogin if start_cluster != end_cluster { 289*004e86ffSlogin self.zero_range(fs, start_offset, start_offset + bytes_remain)?; 290*004e86ffSlogin } else { 291*004e86ffSlogin self.zero_range(fs, start_offset, start_offset + offset - self.size())?; 292*004e86ffSlogin } 293*004e86ffSlogin } 294*004e86ffSlogin // 计算文件的新大小 295*004e86ffSlogin let new_size = self.size() + extra_bytes; 296*004e86ffSlogin self.set_size(new_size as u32); 297*004e86ffSlogin // 计算短目录项所在的位置,更新短目录项 298*004e86ffSlogin let short_entry_offset = fs.cluster_bytes_offset(self.loc.1 .0) + self.loc.1 .1; 299*004e86ffSlogin // todo: 更新时间信息 300*004e86ffSlogin // 把短目录项写入磁盘 301*004e86ffSlogin self.short_dir_entry.flush(fs, short_entry_offset)?; 302*004e86ffSlogin return Ok(()); 303*004e86ffSlogin } 304*004e86ffSlogin 305*004e86ffSlogin /// @brief 把磁盘上[range_start, range_end)范围的数据清零 306*004e86ffSlogin /// 307*004e86ffSlogin /// @param range_start 磁盘上起始位置(单位:字节) 308*004e86ffSlogin /// @param range_end 磁盘上终止位置(单位:字节) 309*004e86ffSlogin fn zero_range( 310*004e86ffSlogin &self, 311*004e86ffSlogin fs: &Arc<FATFileSystem>, 312*004e86ffSlogin range_start: u64, 313*004e86ffSlogin range_end: u64, 314*004e86ffSlogin ) -> Result<(), i32> { 315*004e86ffSlogin if range_end <= range_start { 316*004e86ffSlogin return Ok(()); 317*004e86ffSlogin } 318*004e86ffSlogin 319*004e86ffSlogin let zeroes: Vec<u8> = vec![0u8; (range_end - range_start) as usize]; 320*004e86ffSlogin fs.partition.disk().device().write_at( 321*004e86ffSlogin range_start as usize, 322*004e86ffSlogin zeroes.len(), 323*004e86ffSlogin zeroes.as_slice(), 324*004e86ffSlogin )?; 325*004e86ffSlogin return Ok(()); 326*004e86ffSlogin } 327*004e86ffSlogin 328*004e86ffSlogin /// @brief 截断文件的内容,并设置新的文件大小。如果new_size大于当前文件大小,则不做操作。 329*004e86ffSlogin /// 330*004e86ffSlogin /// @param new_size 新的文件大小,如果它大于当前文件大小,则不做操作。 331*004e86ffSlogin /// 332*004e86ffSlogin /// @return Ok(()) 操作成功 333*004e86ffSlogin /// @return Err(i32) 在操作时出现错误 334*004e86ffSlogin pub fn truncate(&mut self, fs: &Arc<FATFileSystem>, new_size: u64) -> Result<(), i32> { 335*004e86ffSlogin if new_size >= self.size() { 336*004e86ffSlogin return Ok(()); 337*004e86ffSlogin } 338*004e86ffSlogin 339*004e86ffSlogin let new_last_cluster = new_size / fs.bytes_per_cluster(); 340*004e86ffSlogin if let Some(begin_delete) = 341*004e86ffSlogin fs.get_cluster_by_relative(self.first_cluster, (new_last_cluster + 1) as usize) 342*004e86ffSlogin { 343*004e86ffSlogin fs.deallocate_cluster(begin_delete)?; 344*004e86ffSlogin }; 345*004e86ffSlogin 346*004e86ffSlogin self.set_size(new_size as u32); 347*004e86ffSlogin // 计算短目录项在磁盘内的字节偏移量 348*004e86ffSlogin let short_entry_offset = fs.cluster_bytes_offset((self.loc.1).0) + (self.loc.1).1; 349*004e86ffSlogin self.short_dir_entry.flush(fs, short_entry_offset)?; 350*004e86ffSlogin return Ok(()); 351*004e86ffSlogin } 352*004e86ffSlogin } 353*004e86ffSlogin 354*004e86ffSlogin /// FAT文件系统中的文件夹 355*004e86ffSlogin #[derive(Debug, Default, Clone)] 356*004e86ffSlogin pub struct FATDir { 357*004e86ffSlogin /// 目录的第一个簇 358*004e86ffSlogin pub first_cluster: Cluster, 359*004e86ffSlogin /// 该字段仅对FAT12、FAT16生效 360*004e86ffSlogin pub root_offset: Option<u64>, 361*004e86ffSlogin /// 文件夹名称 362*004e86ffSlogin pub dir_name: String, 363*004e86ffSlogin pub short_dir_entry: Option<ShortDirEntry>, 364*004e86ffSlogin /// 文件的起始、终止簇。格式:(簇,簇内偏移量) 365*004e86ffSlogin pub loc: Option<((Cluster, u64), (Cluster, u64))>, 366*004e86ffSlogin } 367*004e86ffSlogin 368*004e86ffSlogin impl FATDir { 369*004e86ffSlogin /// @brief 获得用于遍历当前目录的迭代器 370*004e86ffSlogin /// 371*004e86ffSlogin /// @param fs 当前目录所在的文件系统 372*004e86ffSlogin pub fn to_iter(&self, fs: Arc<FATFileSystem>) -> FATDirIter { 373*004e86ffSlogin return FATDirIter { 374*004e86ffSlogin current_cluster: self.first_cluster, 375*004e86ffSlogin offset: self.root_offset.unwrap_or(0), 376*004e86ffSlogin is_root: self.is_root(), 377*004e86ffSlogin fs: fs, 378*004e86ffSlogin }; 379*004e86ffSlogin } 380*004e86ffSlogin 381*004e86ffSlogin /// @brief 判断当前目录是否为根目录(仅对FAT12和FAT16生效) 382*004e86ffSlogin #[inline] 383*004e86ffSlogin pub fn is_root(&self) -> bool { 384*004e86ffSlogin return self.root_offset.is_some(); 385*004e86ffSlogin } 386*004e86ffSlogin 387*004e86ffSlogin /// @brief 获取当前目录所占用的大小 388*004e86ffSlogin pub fn size(&self, fs: &Arc<FATFileSystem>) -> u64 { 389*004e86ffSlogin return fs.num_clusters_chain(self.first_cluster) * fs.bytes_per_cluster(); 390*004e86ffSlogin } 391*004e86ffSlogin 392*004e86ffSlogin /// @brief 在目录项中,寻找num_free个连续空闲目录项 393*004e86ffSlogin /// 394*004e86ffSlogin /// @param num_free 需要的空闲目录项数目. 395*004e86ffSlogin /// @param fs 当前文件夹属于的文件系统 396*004e86ffSlogin /// 397*004e86ffSlogin /// @return Ok(Option<(第一个符合条件的空闲目录项所在的簇,簇内偏移量)) 398*004e86ffSlogin /// @return Err(错误码) 399*004e86ffSlogin pub fn find_free_entries( 400*004e86ffSlogin &self, 401*004e86ffSlogin num_free: u64, 402*004e86ffSlogin fs: Arc<FATFileSystem>, 403*004e86ffSlogin ) -> Result<Option<(Cluster, u64)>, i32> { 404*004e86ffSlogin let mut free = 0; 405*004e86ffSlogin let mut current_cluster: Cluster = self.first_cluster; 406*004e86ffSlogin let mut offset = self.root_offset.unwrap_or(0); 407*004e86ffSlogin // 第一个符合条件的空闲目录项 408*004e86ffSlogin let mut first_free: Option<(Cluster, u64)> = None; 409*004e86ffSlogin 410*004e86ffSlogin loop { 411*004e86ffSlogin // 如果当前簇没有空间了,并且当前不是FAT12和FAT16的根目录,那么就读取下一个簇。 412*004e86ffSlogin if offset >= fs.bytes_per_cluster() && !self.is_root() { 413*004e86ffSlogin // 成功读取下一个簇 414*004e86ffSlogin if let Some(FATEntry::Next(c)) = fs.get_fat_entry(current_cluster).ok() { 415*004e86ffSlogin current_cluster = c; 416*004e86ffSlogin // 计算簇内偏移量 417*004e86ffSlogin offset = offset % fs.bytes_per_cluster(); 418*004e86ffSlogin } else { 419*004e86ffSlogin // 读取失败,当前已经是最后一个簇,退出循环 420*004e86ffSlogin break; 421*004e86ffSlogin } 422*004e86ffSlogin } 423*004e86ffSlogin // 如果当前目录是FAT12和FAT16的根目录,且已经读取完,就直接返回。 424*004e86ffSlogin if self.is_root() && offset > fs.root_dir_end_bytes_offset().unwrap() { 425*004e86ffSlogin return Ok(None); 426*004e86ffSlogin } 427*004e86ffSlogin 428*004e86ffSlogin let e_offset = fs.cluster_bytes_offset(current_cluster) + offset; 429*004e86ffSlogin let entry: FATRawDirEntry = get_raw_dir_entry(&fs, e_offset)?; 430*004e86ffSlogin 431*004e86ffSlogin match entry { 432*004e86ffSlogin FATRawDirEntry::Free | FATRawDirEntry::FreeRest => { 433*004e86ffSlogin if free == 0 { 434*004e86ffSlogin first_free = Some((current_cluster, offset)); 435*004e86ffSlogin } 436*004e86ffSlogin 437*004e86ffSlogin free += 1; 438*004e86ffSlogin if free == num_free { 439*004e86ffSlogin // kdebug!("first_free = {first_free:?}, current_free = ({current_cluster:?}, {offset})"); 440*004e86ffSlogin return Ok(first_free); 441*004e86ffSlogin } 442*004e86ffSlogin } 443*004e86ffSlogin 444*004e86ffSlogin // 遇到一个不空闲的目录项,那么重新开始计算空闲目录项 445*004e86ffSlogin _ => { 446*004e86ffSlogin free = 0; 447*004e86ffSlogin } 448*004e86ffSlogin } 449*004e86ffSlogin offset += FATRawDirEntry::DIR_ENTRY_LEN; 450*004e86ffSlogin } 451*004e86ffSlogin 452*004e86ffSlogin // 剩余的需要获取的目录项 453*004e86ffSlogin let remain_entries = num_free - free; 454*004e86ffSlogin 455*004e86ffSlogin // 计算需要申请多少个簇 456*004e86ffSlogin let clusters_required = 457*004e86ffSlogin (remain_entries * FATRawDirEntry::DIR_ENTRY_LEN + fs.bytes_per_cluster() - 1) 458*004e86ffSlogin / fs.bytes_per_cluster(); 459*004e86ffSlogin let mut first_cluster = Cluster::default(); 460*004e86ffSlogin let mut prev_cluster = current_cluster; 461*004e86ffSlogin // kdebug!( 462*004e86ffSlogin // "clusters_required={clusters_required}, prev_cluster={prev_cluster:?}, free ={free}" 463*004e86ffSlogin // ); 464*004e86ffSlogin // 申请簇 465*004e86ffSlogin for i in 0..clusters_required { 466*004e86ffSlogin let c: Cluster = fs.allocate_cluster(Some(prev_cluster))?; 467*004e86ffSlogin if i == 0 { 468*004e86ffSlogin first_cluster = c; 469*004e86ffSlogin } 470*004e86ffSlogin 471*004e86ffSlogin prev_cluster = c; 472*004e86ffSlogin } 473*004e86ffSlogin 474*004e86ffSlogin if free > 0 { 475*004e86ffSlogin // 空闲目录项跨越了簇,返回第一个空闲目录项 476*004e86ffSlogin return Ok(first_free); 477*004e86ffSlogin } else { 478*004e86ffSlogin // 空闲目录项是在全新的簇开始的 479*004e86ffSlogin return Ok(Some((first_cluster, 0))); 480*004e86ffSlogin } 481*004e86ffSlogin } 482*004e86ffSlogin 483*004e86ffSlogin /// @brief 在当前目录中寻找目录项 484*004e86ffSlogin /// 485*004e86ffSlogin /// @param name 目录项的名字 486*004e86ffSlogin /// @param expect_dir 该值为Some时有效。如果期待目标目录项是文件夹,那么值为Some(true), 否则为Some(false). 487*004e86ffSlogin /// @param short_name_gen 短目录项名称生成器 488*004e86ffSlogin /// @param fs 当前目录所属的文件系统 489*004e86ffSlogin /// 490*004e86ffSlogin /// @return Ok(FATDirEntry) 找到期待的目录项 491*004e86ffSlogin /// @return Err(i32) 错误码 492*004e86ffSlogin pub fn find_entry( 493*004e86ffSlogin &self, 494*004e86ffSlogin name: &str, 495*004e86ffSlogin expect_dir: Option<bool>, 496*004e86ffSlogin mut short_name_gen: Option<&mut ShortNameGenerator>, 497*004e86ffSlogin fs: Arc<FATFileSystem>, 498*004e86ffSlogin ) -> Result<FATDirEntry, i32> { 499*004e86ffSlogin LongDirEntry::validate_long_name(name)?; 500*004e86ffSlogin // 迭代当前目录下的文件/文件夹 501*004e86ffSlogin for e in self.to_iter(fs) { 502*004e86ffSlogin if e.eq_name(name) { 503*004e86ffSlogin if expect_dir.is_some() && Some(e.is_dir()) != expect_dir { 504*004e86ffSlogin if e.is_dir() { 505*004e86ffSlogin // 期望得到文件,但是是文件夹 506*004e86ffSlogin return Err(-(EISDIR as i32)); 507*004e86ffSlogin } else { 508*004e86ffSlogin // 期望得到文件夹,但是是文件 509*004e86ffSlogin return Err(-(ENOTDIR as i32)); 510*004e86ffSlogin } 511*004e86ffSlogin } 512*004e86ffSlogin // 找到期望的目录项 513*004e86ffSlogin return Ok(e); 514*004e86ffSlogin } 515*004e86ffSlogin 516*004e86ffSlogin if let Some(ref mut sng) = short_name_gen { 517*004e86ffSlogin sng.add_name(&e.short_name_raw()) 518*004e86ffSlogin } 519*004e86ffSlogin } 520*004e86ffSlogin // 找不到文件/文件夹 521*004e86ffSlogin return Err(-(ENOENT as i32)); 522*004e86ffSlogin } 523*004e86ffSlogin 524*004e86ffSlogin /// @brief 在当前目录下打开文件,获取FATFile结构体 525*004e86ffSlogin pub fn open_file(&self, name: &str, fs: Arc<FATFileSystem>) -> Result<FATFile, i32> { 526*004e86ffSlogin let f: FATFile = self.find_entry(name, Some(false), None, fs)?.to_file()?; 527*004e86ffSlogin return Ok(f); 528*004e86ffSlogin } 529*004e86ffSlogin 530*004e86ffSlogin /// @brief 在当前目录下打开文件夹,获取FATDir结构体 531*004e86ffSlogin pub fn open_dir(&self, name: &str, fs: Arc<FATFileSystem>) -> Result<FATDir, i32> { 532*004e86ffSlogin let d: FATDir = self.find_entry(name, Some(true), None, fs)?.to_dir()?; 533*004e86ffSlogin return Ok(d); 534*004e86ffSlogin } 535*004e86ffSlogin 536*004e86ffSlogin /// @brief 在当前文件夹下创建文件。 537*004e86ffSlogin /// 538*004e86ffSlogin /// @param name 文件名 539*004e86ffSlogin /// @param fs 当前文件夹所属的文件系统 540*004e86ffSlogin pub fn create_file(&self, name: &str, fs: &Arc<FATFileSystem>) -> Result<FATFile, i32> { 541*004e86ffSlogin let r: Result<FATDirEntryOrShortName, i32> = 542*004e86ffSlogin self.check_existence(name, Some(false), fs.clone()); 543*004e86ffSlogin // 检查错误码,如果能够表明目录项已经存在,则返回-EEXIST 544*004e86ffSlogin if r.is_err() { 545*004e86ffSlogin let err_val = r.unwrap_err(); 546*004e86ffSlogin if err_val == (-(EISDIR as i32)) || err_val == (-(ENOTDIR as i32)) { 547*004e86ffSlogin return Err(-(EEXIST as i32)); 548*004e86ffSlogin } else { 549*004e86ffSlogin return Err(err_val); 550*004e86ffSlogin } 551*004e86ffSlogin } 552*004e86ffSlogin 553*004e86ffSlogin match r.unwrap() { 554*004e86ffSlogin FATDirEntryOrShortName::ShortName(short_name) => { 555*004e86ffSlogin // 确认名称是一个可行的长文件名 556*004e86ffSlogin LongDirEntry::validate_long_name(name)?; 557*004e86ffSlogin // 创建目录项 558*004e86ffSlogin let x: Result<FATFile, i32> = self 559*004e86ffSlogin .create_dir_entries( 560*004e86ffSlogin name.trim(), 561*004e86ffSlogin &short_name, 562*004e86ffSlogin None, 563*004e86ffSlogin FileAttributes { 564*004e86ffSlogin value: FileAttributes::ARCHIVE, 565*004e86ffSlogin }, 566*004e86ffSlogin fs.clone(), 567*004e86ffSlogin ) 568*004e86ffSlogin .map(|e| e.to_file())?; 569*004e86ffSlogin return x; 570*004e86ffSlogin } 571*004e86ffSlogin 572*004e86ffSlogin FATDirEntryOrShortName::DirEntry(_) => { 573*004e86ffSlogin // 已经存在这样的一个目录项了 574*004e86ffSlogin return Err(-(EEXIST as i32)); 575*004e86ffSlogin } 576*004e86ffSlogin } 577*004e86ffSlogin } 578*004e86ffSlogin 579*004e86ffSlogin pub fn create_dir(&self, name: &str, fs: &Arc<FATFileSystem>) -> Result<FATDir, i32> { 580*004e86ffSlogin let r: Result<FATDirEntryOrShortName, i32> = 581*004e86ffSlogin self.check_existence(name, Some(true), fs.clone()); 582*004e86ffSlogin // kdebug!("check existence ok"); 583*004e86ffSlogin // 检查错误码,如果能够表明目录项已经存在,则返回-EEXIST 584*004e86ffSlogin if r.is_err() { 585*004e86ffSlogin let err_val = r.unwrap_err(); 586*004e86ffSlogin if err_val == (-(EISDIR as i32)) || err_val == (-(ENOTDIR as i32)) { 587*004e86ffSlogin return Err(-(EEXIST as i32)); 588*004e86ffSlogin } else { 589*004e86ffSlogin return Err(err_val); 590*004e86ffSlogin } 591*004e86ffSlogin } 592*004e86ffSlogin 593*004e86ffSlogin match r.unwrap() { 594*004e86ffSlogin // 文件夹不存在,创建文件夹 595*004e86ffSlogin FATDirEntryOrShortName::ShortName(short_name) => { 596*004e86ffSlogin LongDirEntry::validate_long_name(name)?; 597*004e86ffSlogin // 目标目录项 598*004e86ffSlogin let mut short_entry = ShortDirEntry::default(); 599*004e86ffSlogin // kdebug!("to allocate cluster"); 600*004e86ffSlogin let first_cluster: Cluster = fs.allocate_cluster(None)?; 601*004e86ffSlogin short_entry.set_first_cluster(first_cluster); 602*004e86ffSlogin 603*004e86ffSlogin // kdebug!("to create dot"); 604*004e86ffSlogin // === 接下来在子目录中创建'.'目录项和'..'目录项 605*004e86ffSlogin let mut offset = 0; 606*004e86ffSlogin // '.'目录项 607*004e86ffSlogin let mut dot_entry = ShortDirEntry::default(); 608*004e86ffSlogin dot_entry.name = ShortNameGenerator::new(".").generate().unwrap(); 609*004e86ffSlogin dot_entry.attributes.value = FileAttributes::DIRECTORY; 610*004e86ffSlogin dot_entry.set_first_cluster(first_cluster); 611*004e86ffSlogin 612*004e86ffSlogin // todo: 设置创建、访问时间 613*004e86ffSlogin dot_entry.flush(&fs, fs.cluster_bytes_offset(first_cluster) + offset)?; 614*004e86ffSlogin 615*004e86ffSlogin drop(dot_entry); 616*004e86ffSlogin // 偏移量加上一个目录项的长度 617*004e86ffSlogin offset += FATRawDirEntry::DIR_ENTRY_LEN; 618*004e86ffSlogin 619*004e86ffSlogin // kdebug!("to create dot dot"); 620*004e86ffSlogin // '..'目录项 621*004e86ffSlogin let mut dot_dot_entry = ShortDirEntry::default(); 622*004e86ffSlogin dot_dot_entry.name = ShortNameGenerator::new("..").generate().unwrap(); 623*004e86ffSlogin dot_dot_entry.attributes.value = FileAttributes::DIRECTORY; 624*004e86ffSlogin dot_dot_entry.set_first_cluster(self.first_cluster); 625*004e86ffSlogin // todo: 设置创建、访问时间 626*004e86ffSlogin 627*004e86ffSlogin dot_dot_entry.flush(&fs, fs.cluster_bytes_offset(first_cluster) + offset)?; 628*004e86ffSlogin 629*004e86ffSlogin // kdebug!("to create dentries"); 630*004e86ffSlogin // 在当前目录下创建目标目录项 631*004e86ffSlogin let res = self 632*004e86ffSlogin .create_dir_entries( 633*004e86ffSlogin name.trim(), 634*004e86ffSlogin &short_name, 635*004e86ffSlogin Some(short_entry), 636*004e86ffSlogin FileAttributes { 637*004e86ffSlogin value: FileAttributes::DIRECTORY, 638*004e86ffSlogin }, 639*004e86ffSlogin fs.clone(), 640*004e86ffSlogin ) 641*004e86ffSlogin .map(|e| e.to_dir())?; 642*004e86ffSlogin // kdebug!("create dentries ok"); 643*004e86ffSlogin return res; 644*004e86ffSlogin } 645*004e86ffSlogin FATDirEntryOrShortName::DirEntry(_) => { 646*004e86ffSlogin // 已经存在这样的一个目录项了 647*004e86ffSlogin return Err(-(EEXIST as i32)); 648*004e86ffSlogin } 649*004e86ffSlogin } 650*004e86ffSlogin } 651*004e86ffSlogin /// @brief 检查目录项在当前文件夹下是否存在 652*004e86ffSlogin /// 653*004e86ffSlogin /// @param name 目录项的名字 654*004e86ffSlogin /// @param expect_dir 该值为Some时有效。如果期待目标目录项是文件夹,那么值为Some(true), 否则为Some(false). 655*004e86ffSlogin /// @param fs 当前目录所属的文件系统 656*004e86ffSlogin /// 657*004e86ffSlogin /// @return Ok(FATDirEntryOrShortName::DirEntry) 找到期待的目录项 658*004e86ffSlogin /// @return Ok(FATDirEntryOrShortName::ShortName) 当前文件夹下不存在指定的目录项,因此返回一个可行的短文件名 659*004e86ffSlogin /// @return Err(i32) 错误码 660*004e86ffSlogin pub fn check_existence( 661*004e86ffSlogin &self, 662*004e86ffSlogin name: &str, 663*004e86ffSlogin expect_dir: Option<bool>, 664*004e86ffSlogin fs: Arc<FATFileSystem>, 665*004e86ffSlogin ) -> Result<FATDirEntryOrShortName, i32> { 666*004e86ffSlogin let mut sng = ShortNameGenerator::new(name); 667*004e86ffSlogin 668*004e86ffSlogin loop { 669*004e86ffSlogin let e: Result<FATDirEntry, i32> = 670*004e86ffSlogin self.find_entry(name, expect_dir, Some(&mut sng), fs.clone()); 671*004e86ffSlogin match e { 672*004e86ffSlogin Ok(e) => { 673*004e86ffSlogin // 找到,返回目录项 674*004e86ffSlogin return Ok(FATDirEntryOrShortName::DirEntry(e)); 675*004e86ffSlogin } 676*004e86ffSlogin Err(e) => { 677*004e86ffSlogin // 如果没找到,则不返回错误 678*004e86ffSlogin if e == -(ENOENT as i32) { 679*004e86ffSlogin } else { 680*004e86ffSlogin // 其他错误,则返回 681*004e86ffSlogin return Err(e); 682*004e86ffSlogin } 683*004e86ffSlogin } 684*004e86ffSlogin } 685*004e86ffSlogin 686*004e86ffSlogin // 没找到文件,则生成短文件名 687*004e86ffSlogin if let Ok(name) = sng.generate() { 688*004e86ffSlogin return Ok(FATDirEntryOrShortName::ShortName(name)); 689*004e86ffSlogin } 690*004e86ffSlogin 691*004e86ffSlogin sng.next_iteration(); 692*004e86ffSlogin } 693*004e86ffSlogin } 694*004e86ffSlogin 695*004e86ffSlogin /// @brief 创建一系列的目录项 696*004e86ffSlogin /// 697*004e86ffSlogin /// @param long_name 长文件名 698*004e86ffSlogin /// @param short_name 短文件名 699*004e86ffSlogin /// @param short_dentry 可选的生成好的短目录项结构体 700*004e86ffSlogin /// @param attrs FAT目录项的属性 701*004e86ffSlogin /// @param fs 当前文件夹所属的文件系统 702*004e86ffSlogin /// 703*004e86ffSlogin /// @return Ok(FATDirEntry) FAT目录项的枚举类型(目录项链条的最后一个长目录项) 704*004e86ffSlogin fn create_dir_entries( 705*004e86ffSlogin &self, 706*004e86ffSlogin long_name: &str, 707*004e86ffSlogin short_name: &[u8; 11], 708*004e86ffSlogin short_dentry: Option<ShortDirEntry>, 709*004e86ffSlogin attrs: FileAttributes, 710*004e86ffSlogin fs: Arc<FATFileSystem>, 711*004e86ffSlogin ) -> Result<FATDirEntry, i32> { 712*004e86ffSlogin let mut short_dentry: ShortDirEntry = short_dentry.unwrap_or(ShortDirEntry::default()); 713*004e86ffSlogin short_dentry.name = short_name.clone(); 714*004e86ffSlogin short_dentry.attributes = attrs; 715*004e86ffSlogin 716*004e86ffSlogin // todo: 设置创建时间、修改时间 717*004e86ffSlogin 718*004e86ffSlogin let mut long_name_gen: LongNameEntryGenerator = 719*004e86ffSlogin LongNameEntryGenerator::new(long_name, short_dentry.checksum()); 720*004e86ffSlogin let num_entries = long_name_gen.num_entries() as u64; 721*004e86ffSlogin 722*004e86ffSlogin // kdebug!("to find free entries"); 723*004e86ffSlogin let free_entries: Option<(Cluster, u64)> = 724*004e86ffSlogin self.find_free_entries(num_entries, fs.clone())?; 725*004e86ffSlogin // 目录项开始位置 726*004e86ffSlogin let start_loc: (Cluster, u64) = match free_entries { 727*004e86ffSlogin Some(c) => c, 728*004e86ffSlogin None => return Err(-(ENOSPC as i32)), 729*004e86ffSlogin }; 730*004e86ffSlogin let offsets: Vec<(Cluster, u64)> = 731*004e86ffSlogin FATDirEntryOffsetIter::new(fs.clone(), start_loc, num_entries, None).collect(); 732*004e86ffSlogin 733*004e86ffSlogin // 迭代长目录项 734*004e86ffSlogin for off in &offsets.as_slice()[..offsets.len() - 1] { 735*004e86ffSlogin // 获取生成的下一个长目录项 736*004e86ffSlogin let long_entry: LongDirEntry = long_name_gen.next().unwrap(); 737*004e86ffSlogin // 获取这个长目录项在磁盘内的字节偏移量 738*004e86ffSlogin let bytes_offset = fs.cluster_bytes_offset(off.0) + off.1; 739*004e86ffSlogin long_entry.flush(fs.clone(), bytes_offset)?; 740*004e86ffSlogin } 741*004e86ffSlogin 742*004e86ffSlogin let start: (Cluster, u64) = offsets[0]; 743*004e86ffSlogin let end: (Cluster, u64) = *offsets.last().unwrap(); 744*004e86ffSlogin // 短目录项在磁盘上的字节偏移量 745*004e86ffSlogin let offset = fs.cluster_bytes_offset(end.0) + end.1; 746*004e86ffSlogin short_dentry.flush(&fs, offset)?; 747*004e86ffSlogin 748*004e86ffSlogin return Ok(short_dentry.to_dir_entry_with_long_name(long_name.to_string(), (start, end))); 749*004e86ffSlogin } 750*004e86ffSlogin 751*004e86ffSlogin /// @brief 判断当前目录是否为空 752*004e86ffSlogin /// 753*004e86ffSlogin /// @return true 当前目录为空 754*004e86ffSlogin /// @return false 当前目录不为空 755*004e86ffSlogin pub fn is_empty(&self, fs: Arc<FATFileSystem>) -> bool { 756*004e86ffSlogin for e in self.to_iter(fs) { 757*004e86ffSlogin let s = e.short_name(); 758*004e86ffSlogin if s == "." || s == ".." { 759*004e86ffSlogin continue; 760*004e86ffSlogin } else { 761*004e86ffSlogin return false; 762*004e86ffSlogin } 763*004e86ffSlogin } 764*004e86ffSlogin return true; 765*004e86ffSlogin } 766*004e86ffSlogin 767*004e86ffSlogin /// @brief 从当前文件夹中删除文件或者文件夹。如果目标文件夹不为空,则不能删除,返回-ENOTEMPTY. 768*004e86ffSlogin /// 769*004e86ffSlogin /// @param fs 当前FATDir所属的文件系统 770*004e86ffSlogin /// @param name 目录项的名字 771*004e86ffSlogin /// @param remove_clusters 是否删除与指定的目录项相关联的数据簇 772*004e86ffSlogin /// 773*004e86ffSlogin /// @return Ok() 成功时无返回值 774*004e86ffSlogin /// @return Err(i32) 如果目标文件夹不为空,则不能删除,返回-ENOTEMPTY. 或者返回底层传上来的错误 775*004e86ffSlogin pub fn remove( 776*004e86ffSlogin &self, 777*004e86ffSlogin fs: Arc<FATFileSystem>, 778*004e86ffSlogin name: &str, 779*004e86ffSlogin remove_clusters: bool, 780*004e86ffSlogin ) -> Result<(), i32> { 781*004e86ffSlogin let e: FATDirEntry = self.find_entry(name, None, None, fs.clone())?; 782*004e86ffSlogin 783*004e86ffSlogin // 判断文件夹是否为空,如果空,则不删除,报错。 784*004e86ffSlogin if e.is_dir() && !(e.to_dir().unwrap().is_empty(fs.clone())) { 785*004e86ffSlogin return Err(-(ENOTEMPTY as i32)); 786*004e86ffSlogin } 787*004e86ffSlogin 788*004e86ffSlogin if e.first_cluster().cluster_num >= 2 && remove_clusters { 789*004e86ffSlogin // 删除与指定的目录项相关联的数据簇 790*004e86ffSlogin fs.deallocate_cluster_chain(e.first_cluster())?; 791*004e86ffSlogin } 792*004e86ffSlogin 793*004e86ffSlogin if e.get_dir_range().is_some() { 794*004e86ffSlogin self.remove_dir_entries(fs, e.get_dir_range().unwrap())?; 795*004e86ffSlogin } 796*004e86ffSlogin 797*004e86ffSlogin return Ok(()); 798*004e86ffSlogin } 799*004e86ffSlogin 800*004e86ffSlogin /// @brief 在当前目录中删除多个目录项 801*004e86ffSlogin /// 802*004e86ffSlogin /// @param fs 当前目录所属的文件系统 803*004e86ffSlogin /// @param cluster_range 要删除的目录项的范围(以簇+簇内偏移量的形式表示) 804*004e86ffSlogin fn remove_dir_entries( 805*004e86ffSlogin &self, 806*004e86ffSlogin fs: Arc<FATFileSystem>, 807*004e86ffSlogin cluster_range: ((Cluster, u64), (Cluster, u64)), 808*004e86ffSlogin ) -> Result<(), i32> { 809*004e86ffSlogin // 收集所有的要移除的目录项 810*004e86ffSlogin let offsets: Vec<(Cluster, u64)> = 811*004e86ffSlogin FATDirEntryOffsetIter::new(fs.clone(), cluster_range.0, 15, Some(cluster_range.1)) 812*004e86ffSlogin .collect(); 813*004e86ffSlogin // 逐个设置这些目录项为“空闲”状态 814*004e86ffSlogin for off in offsets { 815*004e86ffSlogin let disk_bytes_offset = fs.cluster_bytes_offset(off.0) + off.1; 816*004e86ffSlogin let mut short_entry = ShortDirEntry::default(); 817*004e86ffSlogin short_entry.name[0] = 0xe5; 818*004e86ffSlogin short_entry.flush(&fs, disk_bytes_offset)?; 819*004e86ffSlogin } 820*004e86ffSlogin return Ok(()); 821*004e86ffSlogin } 822*004e86ffSlogin 823*004e86ffSlogin /// @brief 根据名字在当前文件夹下寻找目录项 824*004e86ffSlogin /// 825*004e86ffSlogin /// @return Ok(FATDirEntry) 目标目录项 826*004e86ffSlogin /// @return Err(i32) 底层传上来的错误码 827*004e86ffSlogin pub fn get_dir_entry(&self, fs: Arc<FATFileSystem>, name: &str) -> Result<FATDirEntry, i32> { 828*004e86ffSlogin if name == "." || name == "/" { 829*004e86ffSlogin return Ok(FATDirEntry::Dir(self.clone())); 830*004e86ffSlogin } 831*004e86ffSlogin 832*004e86ffSlogin LongDirEntry::validate_long_name(name)?; 833*004e86ffSlogin return self.find_entry(name, None, None, fs); 834*004e86ffSlogin } 835*004e86ffSlogin 836*004e86ffSlogin /// @brief 在当前目录内,重命名一个目录项 837*004e86ffSlogin /// 838*004e86ffSlogin pub fn rename( 839*004e86ffSlogin &self, 840*004e86ffSlogin fs: Arc<FATFileSystem>, 841*004e86ffSlogin old_name: &str, 842*004e86ffSlogin new_name: &str, 843*004e86ffSlogin ) -> Result<FATDirEntry, i32> { 844*004e86ffSlogin // 判断源目录项是否存在 845*004e86ffSlogin let old_dentry: FATDirEntry = if let FATDirEntryOrShortName::DirEntry(dentry) = 846*004e86ffSlogin self.check_existence(old_name, None, fs.clone())? 847*004e86ffSlogin { 848*004e86ffSlogin dentry 849*004e86ffSlogin } else { 850*004e86ffSlogin // 如果目标目录项不存在,则返回错误 851*004e86ffSlogin return Err(-(ENOENT as i32)); 852*004e86ffSlogin }; 853*004e86ffSlogin 854*004e86ffSlogin let short_name = if let FATDirEntryOrShortName::ShortName(s) = 855*004e86ffSlogin self.check_existence(new_name, None, fs.clone())? 856*004e86ffSlogin { 857*004e86ffSlogin s 858*004e86ffSlogin } else { 859*004e86ffSlogin // 如果目标目录项存在,那么就返回错误 860*004e86ffSlogin return Err(-(EEXIST as i32)); 861*004e86ffSlogin }; 862*004e86ffSlogin 863*004e86ffSlogin let old_short_dentry: Option<ShortDirEntry> = old_dentry.short_dir_entry(); 864*004e86ffSlogin if let Some(se) = old_short_dentry { 865*004e86ffSlogin // 删除原来的目录项 866*004e86ffSlogin self.remove(fs.clone(), old_dentry.name().as_str(), false)?; 867*004e86ffSlogin 868*004e86ffSlogin // 创建新的目录项 869*004e86ffSlogin let new_dentry: FATDirEntry = self.create_dir_entries( 870*004e86ffSlogin new_name, 871*004e86ffSlogin &short_name, 872*004e86ffSlogin Some(se), 873*004e86ffSlogin se.attributes, 874*004e86ffSlogin fs.clone(), 875*004e86ffSlogin )?; 876*004e86ffSlogin 877*004e86ffSlogin return Ok(new_dentry); 878*004e86ffSlogin } else { 879*004e86ffSlogin // 不允许对根目录项进行重命名 880*004e86ffSlogin return Err(-(EPERM as i32)); 881*004e86ffSlogin } 882*004e86ffSlogin } 883*004e86ffSlogin } 884*004e86ffSlogin 885*004e86ffSlogin impl FileAttributes { 886*004e86ffSlogin pub const READ_ONLY: u8 = 1 << 0; 887*004e86ffSlogin pub const HIDDEN: u8 = 1 << 1; 888*004e86ffSlogin pub const SYSTEM: u8 = 1 << 2; 889*004e86ffSlogin pub const VOLUME_ID: u8 = 1 << 3; 890*004e86ffSlogin pub const DIRECTORY: u8 = 1 << 4; 891*004e86ffSlogin pub const ARCHIVE: u8 = 1 << 5; 892*004e86ffSlogin pub const LONG_NAME: u8 = FileAttributes::READ_ONLY 893*004e86ffSlogin | FileAttributes::HIDDEN 894*004e86ffSlogin | FileAttributes::SYSTEM 895*004e86ffSlogin | FileAttributes::VOLUME_ID; 896*004e86ffSlogin 897*004e86ffSlogin /// @brief 判断属性是否存在 898*004e86ffSlogin #[inline] 899*004e86ffSlogin pub fn contains(&self, attr: u8) -> bool { 900*004e86ffSlogin return (self.value & attr) != 0; 901*004e86ffSlogin } 902*004e86ffSlogin 903*004e86ffSlogin pub fn new(attr: u8) -> Self { 904*004e86ffSlogin return Self { value: attr }; 905*004e86ffSlogin } 906*004e86ffSlogin } 907*004e86ffSlogin 908*004e86ffSlogin /// FAT32的短目录项 909*004e86ffSlogin #[derive(Debug, Clone, Copy, Default)] 910*004e86ffSlogin pub struct ShortDirEntry { 911*004e86ffSlogin /// short name 912*004e86ffSlogin name: [u8; 11], 913*004e86ffSlogin /// 目录项属性 (见 FileAttributes ) 914*004e86ffSlogin attributes: FileAttributes, 915*004e86ffSlogin 916*004e86ffSlogin /// Windows NT系统的保留字段。用来表示短目录项文件名。 917*004e86ffSlogin /// EXT|BASE => 8(BASE).3(EXT) 918*004e86ffSlogin /// BASE:LowerCase(8),UpperCase(0) 919*004e86ffSlogin /// EXT:LowerCase(16),UpperCase(0) 920*004e86ffSlogin nt_res: u8, 921*004e86ffSlogin 922*004e86ffSlogin /// 文件创建时间的毫秒级时间戳 923*004e86ffSlogin crt_time_tenth: u8, 924*004e86ffSlogin /// 创建时间 925*004e86ffSlogin crt_time: u16, 926*004e86ffSlogin /// 创建日期 927*004e86ffSlogin crt_date: u16, 928*004e86ffSlogin /// 最后一次访问日期 929*004e86ffSlogin lst_acc_date: u16, 930*004e86ffSlogin /// High word of first cluster(0 for FAT12 and FAT16) 931*004e86ffSlogin fst_clus_hi: u16, 932*004e86ffSlogin /// 最后写入时间 933*004e86ffSlogin wrt_time: u16, 934*004e86ffSlogin /// 最后写入日期 935*004e86ffSlogin wrt_date: u16, 936*004e86ffSlogin /// Low word of first cluster 937*004e86ffSlogin fst_clus_lo: u16, 938*004e86ffSlogin /// 文件大小 939*004e86ffSlogin file_size: u32, 940*004e86ffSlogin } 941*004e86ffSlogin 942*004e86ffSlogin /// FAT32的长目录项 943*004e86ffSlogin #[derive(Debug, Clone, Copy, Default)] 944*004e86ffSlogin pub struct LongDirEntry { 945*004e86ffSlogin /// 长目录项的序号 946*004e86ffSlogin ord: u8, 947*004e86ffSlogin /// 长文件名的第1-5个字符,每个字符占2bytes 948*004e86ffSlogin name1: [u16; 5], 949*004e86ffSlogin /// 目录项属性必须为ATTR_LONG_NAME 950*004e86ffSlogin file_attrs: FileAttributes, 951*004e86ffSlogin /// Entry Type: 如果为0,则说明这是长目录项的子项 952*004e86ffSlogin /// 非零值是保留的。 953*004e86ffSlogin dirent_type: u8, 954*004e86ffSlogin /// 短文件名的校验和 955*004e86ffSlogin checksum: u8, 956*004e86ffSlogin /// 长文件名的第6-11个字符,每个字符占2bytes 957*004e86ffSlogin name2: [u16; 6], 958*004e86ffSlogin /// 必须为0 959*004e86ffSlogin first_clus_low: u16, 960*004e86ffSlogin /// 长文件名的12-13个字符,每个字符占2bytes 961*004e86ffSlogin name3: [u16; 2], 962*004e86ffSlogin } 963*004e86ffSlogin 964*004e86ffSlogin impl LongDirEntry { 965*004e86ffSlogin /// 长目录项的字符串长度(单位:word) 966*004e86ffSlogin pub const LONG_NAME_STR_LEN: usize = 13; 967*004e86ffSlogin 968*004e86ffSlogin /// @brief 初始化一个新的长目录项 969*004e86ffSlogin /// 970*004e86ffSlogin /// @param ord 顺序 971*004e86ffSlogin /// @param name_part 长目录项名称的数组(长度必须为13) 972*004e86ffSlogin /// @param check_sum 短目录项的校验和 973*004e86ffSlogin /// 974*004e86ffSlogin /// @return Self 初始化好的长目录项对象 975*004e86ffSlogin fn new(ord: u8, name_part: &[u16], check_sum: u8) -> Self { 976*004e86ffSlogin let mut result = LongDirEntry::default(); 977*004e86ffSlogin result.ord = ord; 978*004e86ffSlogin result 979*004e86ffSlogin .insert_name(name_part) 980*004e86ffSlogin .expect("Name part's len should be equal to 13."); 981*004e86ffSlogin result.file_attrs.value = FileAttributes::LONG_NAME; 982*004e86ffSlogin result.dirent_type = 0; 983*004e86ffSlogin result.checksum = check_sum; 984*004e86ffSlogin // 该字段需要外层的代码手动赋值 985*004e86ffSlogin result.first_clus_low = 0; 986*004e86ffSlogin return result; 987*004e86ffSlogin } 988*004e86ffSlogin 989*004e86ffSlogin /// @brief 填写长目录项的名称字段。 990*004e86ffSlogin /// 991*004e86ffSlogin /// @param name_part 要被填入当前长目录项的名字(数组长度必须为13) 992*004e86ffSlogin /// 993*004e86ffSlogin /// @return Ok(()) 994*004e86ffSlogin /// @return Err(i32) 错误码 995*004e86ffSlogin fn insert_name(&mut self, name_part: &[u16]) -> Result<(), i32> { 996*004e86ffSlogin if name_part.len() != Self::LONG_NAME_STR_LEN { 997*004e86ffSlogin return Err(-(EINVAL as i32)); 998*004e86ffSlogin } 999*004e86ffSlogin self.name1.copy_from_slice(&name_part[0..5]); 1000*004e86ffSlogin self.name2.copy_from_slice(&name_part[5..11]); 1001*004e86ffSlogin self.name3.copy_from_slice(&name_part[11..13]); 1002*004e86ffSlogin return Ok(()); 1003*004e86ffSlogin } 1004*004e86ffSlogin 1005*004e86ffSlogin /// @brief 将当前长目录项的名称字段,原样地拷贝到一个长度为13的u16数组中。 1006*004e86ffSlogin /// @param dst 拷贝的目的地,一个[u16]数组,长度必须为13。 1007*004e86ffSlogin pub fn copy_name_to_slice(&self, dst: &mut [u16]) -> Result<(), i32> { 1008*004e86ffSlogin if dst.len() != Self::LONG_NAME_STR_LEN { 1009*004e86ffSlogin return Err(-(EINVAL as i32)); 1010*004e86ffSlogin } 1011*004e86ffSlogin dst[0..5].copy_from_slice(&self.name1); 1012*004e86ffSlogin dst[5..11].copy_from_slice(&self.name2); 1013*004e86ffSlogin dst[11..13].copy_from_slice(&self.name3); 1014*004e86ffSlogin return Ok(()); 1015*004e86ffSlogin } 1016*004e86ffSlogin 1017*004e86ffSlogin /// @brief 是否为最后一个长目录项 1018*004e86ffSlogin /// 1019*004e86ffSlogin /// @return true 是最后一个长目录项 1020*004e86ffSlogin /// @return false 不是最后一个长目录项 1021*004e86ffSlogin pub fn is_last(&self) -> bool { 1022*004e86ffSlogin return self.ord & 0x40 > 0; 1023*004e86ffSlogin } 1024*004e86ffSlogin 1025*004e86ffSlogin /// @brief 校验字符串是否符合长目录项的命名要求 1026*004e86ffSlogin /// 1027*004e86ffSlogin /// @return Ok(()) 名称合法 1028*004e86ffSlogin /// @return Err(i32) 名称不合法,返回错误码 1029*004e86ffSlogin pub fn validate_long_name(mut name: &str) -> Result<(), i32> { 1030*004e86ffSlogin // 去除首尾多余的空格 1031*004e86ffSlogin name = name.trim(); 1032*004e86ffSlogin 1033*004e86ffSlogin // 名称不能为0 1034*004e86ffSlogin if name.len() == 0 { 1035*004e86ffSlogin return Err(-(EINVAL as i32)); 1036*004e86ffSlogin } 1037*004e86ffSlogin 1038*004e86ffSlogin // 名称长度不能大于255 1039*004e86ffSlogin if name.len() > 255 { 1040*004e86ffSlogin return Err(-(ENAMETOOLONG as i32)); 1041*004e86ffSlogin } 1042*004e86ffSlogin 1043*004e86ffSlogin // 检查是否符合命名要求 1044*004e86ffSlogin for c in name.chars() { 1045*004e86ffSlogin match c { 1046*004e86ffSlogin 'a'..='z' | 'A'..='Z' | '0'..='9' => {} 1047*004e86ffSlogin '\u{80}'..='\u{ffff}' => {} 1048*004e86ffSlogin '$' | '%' | '\'' | '-' | '_' | '@' | '~' | '`' | '!' | '(' | ')' | '{' | '}' 1049*004e86ffSlogin | '^' | '#' | '&' => {} 1050*004e86ffSlogin '+' | ',' | ';' | '=' | '[' | ']' | '.' | ' ' => {} 1051*004e86ffSlogin _ => { 1052*004e86ffSlogin return Err(-(EILSEQ as i32)); 1053*004e86ffSlogin } 1054*004e86ffSlogin } 1055*004e86ffSlogin } 1056*004e86ffSlogin return Ok(()); 1057*004e86ffSlogin } 1058*004e86ffSlogin 1059*004e86ffSlogin /// @brief 把当前长目录项写入磁盘 1060*004e86ffSlogin /// 1061*004e86ffSlogin /// @param fs 对应的文件系统 1062*004e86ffSlogin /// @param disk_bytes_offset 长目录项所在位置对应的在磁盘上的字节偏移量 1063*004e86ffSlogin /// 1064*004e86ffSlogin /// @return Ok(()) 1065*004e86ffSlogin /// @return Err(i32) 错误码 1066*004e86ffSlogin pub fn flush(&self, fs: Arc<FATFileSystem>, disk_bytes_offset: u64) -> Result<(), i32> { 1067*004e86ffSlogin // 从磁盘读取数据 1068*004e86ffSlogin let blk_offset = fs.get_in_block_offset(disk_bytes_offset); 1069*004e86ffSlogin let lba = fs.get_lba_from_offset( 1070*004e86ffSlogin fs.bytes_to_sector(fs.get_in_partition_bytes_offset(disk_bytes_offset)), 1071*004e86ffSlogin ); 1072*004e86ffSlogin let mut v: Vec<u8> = Vec::new(); 1073*004e86ffSlogin v.resize(1 * fs.lba_per_sector() * LBA_SIZE, 0); 1074*004e86ffSlogin fs.partition 1075*004e86ffSlogin .disk() 1076*004e86ffSlogin .read_at(lba, 1 * fs.lba_per_sector(), &mut v)?; 1077*004e86ffSlogin 1078*004e86ffSlogin let mut cursor: VecCursor = VecCursor::new(v); 1079*004e86ffSlogin // 切换游标到对应位置 1080*004e86ffSlogin cursor.seek(SeekFrom::SeekSet(blk_offset as i64))?; 1081*004e86ffSlogin 1082*004e86ffSlogin // 写入数据 1083*004e86ffSlogin cursor.write_u8(self.ord)?; 1084*004e86ffSlogin for b in &self.name1 { 1085*004e86ffSlogin cursor.write_u16(*b)?; 1086*004e86ffSlogin } 1087*004e86ffSlogin 1088*004e86ffSlogin cursor.write_u8(self.file_attrs.value)?; 1089*004e86ffSlogin cursor.write_u8(self.dirent_type)?; 1090*004e86ffSlogin cursor.write_u8(self.checksum)?; 1091*004e86ffSlogin 1092*004e86ffSlogin for b in &self.name2 { 1093*004e86ffSlogin cursor.write_u16(*b)?; 1094*004e86ffSlogin } 1095*004e86ffSlogin 1096*004e86ffSlogin cursor.write_u16(self.first_clus_low)?; 1097*004e86ffSlogin 1098*004e86ffSlogin for b in &self.name3 { 1099*004e86ffSlogin cursor.write_u16(*b)?; 1100*004e86ffSlogin } 1101*004e86ffSlogin 1102*004e86ffSlogin // 把修改后的长目录项刷入磁盘 1103*004e86ffSlogin fs.partition 1104*004e86ffSlogin .disk() 1105*004e86ffSlogin .write_at(lba, 1 * fs.lba_per_sector(), cursor.as_slice())?; 1106*004e86ffSlogin fs.partition.disk().sync()?; 1107*004e86ffSlogin 1108*004e86ffSlogin return Ok(()); 1109*004e86ffSlogin } 1110*004e86ffSlogin } 1111*004e86ffSlogin 1112*004e86ffSlogin impl ShortDirEntry { 1113*004e86ffSlogin const PADDING: u8 = ' ' as u8; 1114*004e86ffSlogin 1115*004e86ffSlogin /// @brief 判断当前目录项是否为文件夹 1116*004e86ffSlogin /// 1117*004e86ffSlogin /// @return true 是文件夹 1118*004e86ffSlogin /// @return false 不是文件夹 1119*004e86ffSlogin pub fn is_dir(&self) -> bool { 1120*004e86ffSlogin return (self.attributes.contains(FileAttributes::DIRECTORY)) 1121*004e86ffSlogin && (!self.attributes.contains(FileAttributes::VOLUME_ID)); 1122*004e86ffSlogin } 1123*004e86ffSlogin 1124*004e86ffSlogin /// @brief 判断当前目录项是否为文件 1125*004e86ffSlogin /// 1126*004e86ffSlogin /// @return true 是文件 1127*004e86ffSlogin /// @return false 不是文件 1128*004e86ffSlogin pub fn is_file(&self) -> bool { 1129*004e86ffSlogin return (!self.attributes.contains(FileAttributes::DIRECTORY)) 1130*004e86ffSlogin && (!self.attributes.contains(FileAttributes::VOLUME_ID)); 1131*004e86ffSlogin } 1132*004e86ffSlogin 1133*004e86ffSlogin /// @brief 判断当前目录项是否为卷号 1134*004e86ffSlogin /// 1135*004e86ffSlogin /// @return true 是卷号 1136*004e86ffSlogin /// @return false 不是卷号 1137*004e86ffSlogin pub fn is_volume_id(&self) -> bool { 1138*004e86ffSlogin return (!self.attributes.contains(FileAttributes::DIRECTORY)) 1139*004e86ffSlogin && self.attributes.contains(FileAttributes::VOLUME_ID); 1140*004e86ffSlogin } 1141*004e86ffSlogin 1142*004e86ffSlogin /// @brief 将短目录项的名字转换为String 1143*004e86ffSlogin fn name_to_string(&self) -> String { 1144*004e86ffSlogin // 计算基础名的长度 1145*004e86ffSlogin let base_len = self.name[..8] 1146*004e86ffSlogin .iter() 1147*004e86ffSlogin .rposition(|x| *x != ShortDirEntry::PADDING) 1148*004e86ffSlogin .map(|len| len + 1) 1149*004e86ffSlogin .unwrap_or(0); 1150*004e86ffSlogin // 计算扩展名的长度 1151*004e86ffSlogin let ext_len = self.name[8..] 1152*004e86ffSlogin .iter() 1153*004e86ffSlogin .rposition(|x| *x != ShortDirEntry::PADDING) 1154*004e86ffSlogin .map(|len| len + 1) 1155*004e86ffSlogin .unwrap_or(0); 1156*004e86ffSlogin 1157*004e86ffSlogin // 声明存储完整名字的数组(包含“.”) 1158*004e86ffSlogin let mut name = [ShortDirEntry::PADDING; 12]; 1159*004e86ffSlogin // 拷贝基础名 1160*004e86ffSlogin name[..base_len].copy_from_slice(&self.name[..base_len]); 1161*004e86ffSlogin 1162*004e86ffSlogin // 拷贝扩展名,并计算总的长度 1163*004e86ffSlogin let total_len = if ext_len > 0 { 1164*004e86ffSlogin name[base_len] = '.' as u8; 1165*004e86ffSlogin name[base_len + 1..base_len + 1 + ext_len].copy_from_slice(&self.name[8..8 + ext_len]); 1166*004e86ffSlogin // 总长度为基础名长度+点号+扩展名长度 1167*004e86ffSlogin base_len + 1 + ext_len 1168*004e86ffSlogin } else { 1169*004e86ffSlogin base_len 1170*004e86ffSlogin }; 1171*004e86ffSlogin 1172*004e86ffSlogin if name[0] == 0x05 { 1173*004e86ffSlogin name[0] = 0xe5; 1174*004e86ffSlogin } 1175*004e86ffSlogin 1176*004e86ffSlogin let iter = name[..total_len].iter().map(|c| decode_u8_ascii(*c)); 1177*004e86ffSlogin // 返回最终的字符串 1178*004e86ffSlogin return String::from_iter(iter); 1179*004e86ffSlogin } 1180*004e86ffSlogin 1181*004e86ffSlogin /// @brief 将短目录项结构体,转换为FATDirEntry枚举类型 1182*004e86ffSlogin /// 1183*004e86ffSlogin /// @param loc 当前文件的起始、终止簇。格式:(簇,簇内偏移量) 1184*004e86ffSlogin /// @return 生成的FATDirENtry枚举类型 1185*004e86ffSlogin pub fn to_dir_entry(&self, loc: (Cluster, u64)) -> FATDirEntry { 1186*004e86ffSlogin // 当前文件的第一个簇 1187*004e86ffSlogin let first_cluster = 1188*004e86ffSlogin Cluster::new(((self.fst_clus_hi as u64) << 16) | (self.fst_clus_lo as u64)); 1189*004e86ffSlogin 1190*004e86ffSlogin // 当前是文件或卷号 1191*004e86ffSlogin if self.is_file() || self.is_volume_id() { 1192*004e86ffSlogin let mut file: FATFile = FATFile::default(); 1193*004e86ffSlogin 1194*004e86ffSlogin file.file_name = self.name_to_string(); 1195*004e86ffSlogin file.first_cluster = first_cluster; 1196*004e86ffSlogin file.short_dir_entry = self.clone(); 1197*004e86ffSlogin file.loc = (loc, loc); 1198*004e86ffSlogin 1199*004e86ffSlogin // 根据当前短目录项的类型的不同,返回对应的枚举类型。 1200*004e86ffSlogin if self.is_file() { 1201*004e86ffSlogin return FATDirEntry::File(file); 1202*004e86ffSlogin } else { 1203*004e86ffSlogin return FATDirEntry::VolId(file); 1204*004e86ffSlogin } 1205*004e86ffSlogin } else { 1206*004e86ffSlogin // 当前是文件夹 1207*004e86ffSlogin let mut dir = FATDir::default(); 1208*004e86ffSlogin dir.dir_name = self.name_to_string(); 1209*004e86ffSlogin dir.first_cluster = first_cluster; 1210*004e86ffSlogin dir.root_offset = None; 1211*004e86ffSlogin dir.short_dir_entry = Some(self.clone()); 1212*004e86ffSlogin dir.loc = Some((loc, loc)); 1213*004e86ffSlogin 1214*004e86ffSlogin return FATDirEntry::Dir(dir); 1215*004e86ffSlogin } 1216*004e86ffSlogin } 1217*004e86ffSlogin 1218*004e86ffSlogin /// @brief 将短目录项结构体,转换为FATDirEntry枚举类型. 并且,该短目录项具有对应的长目录项。 1219*004e86ffSlogin /// 因此,需要传入从长目录项获得的完整的文件名 1220*004e86ffSlogin /// 1221*004e86ffSlogin /// @param name 从长目录项获取的完整文件名 1222*004e86ffSlogin /// @param loc 当前文件的起始、终止簇。格式:(簇,簇内偏移量) 1223*004e86ffSlogin /// @return 生成的FATDirENtry枚举类型 1224*004e86ffSlogin pub fn to_dir_entry_with_long_name( 1225*004e86ffSlogin &self, 1226*004e86ffSlogin name: String, 1227*004e86ffSlogin loc: ((Cluster, u64), (Cluster, u64)), 1228*004e86ffSlogin ) -> FATDirEntry { 1229*004e86ffSlogin // 当前文件的第一个簇 1230*004e86ffSlogin let first_cluster = 1231*004e86ffSlogin Cluster::new(((self.fst_clus_hi as u64) << 16) | (self.fst_clus_lo as u64)); 1232*004e86ffSlogin 1233*004e86ffSlogin if self.is_file() || self.is_volume_id() { 1234*004e86ffSlogin let mut file = FATFile::default(); 1235*004e86ffSlogin 1236*004e86ffSlogin file.first_cluster = first_cluster; 1237*004e86ffSlogin file.file_name = name; 1238*004e86ffSlogin file.loc = loc; 1239*004e86ffSlogin file.short_dir_entry = self.clone(); 1240*004e86ffSlogin 1241*004e86ffSlogin if self.is_file() { 1242*004e86ffSlogin return FATDirEntry::File(file); 1243*004e86ffSlogin } else { 1244*004e86ffSlogin return FATDirEntry::VolId(file); 1245*004e86ffSlogin } 1246*004e86ffSlogin } else { 1247*004e86ffSlogin let mut dir = FATDir::default(); 1248*004e86ffSlogin 1249*004e86ffSlogin dir.first_cluster = first_cluster; 1250*004e86ffSlogin dir.dir_name = name; 1251*004e86ffSlogin dir.loc = Some(loc); 1252*004e86ffSlogin dir.short_dir_entry = Some(self.clone()); 1253*004e86ffSlogin dir.root_offset = None; 1254*004e86ffSlogin 1255*004e86ffSlogin return FATDirEntry::Dir(dir); 1256*004e86ffSlogin } 1257*004e86ffSlogin } 1258*004e86ffSlogin 1259*004e86ffSlogin /// @brief 计算短目录项的名称的校验和 1260*004e86ffSlogin fn checksum(&self) -> u8 { 1261*004e86ffSlogin let mut result = 0; 1262*004e86ffSlogin 1263*004e86ffSlogin for c in &self.name { 1264*004e86ffSlogin result = (result << 7) + (result >> 1) + *c; 1265*004e86ffSlogin } 1266*004e86ffSlogin return result; 1267*004e86ffSlogin } 1268*004e86ffSlogin 1269*004e86ffSlogin /// @brief 把当前短目录项写入磁盘 1270*004e86ffSlogin /// 1271*004e86ffSlogin /// @param fs 对应的文件系统 1272*004e86ffSlogin /// @param disk_bytes_offset 短目录项所在位置对应的在磁盘上的字节偏移量 1273*004e86ffSlogin /// 1274*004e86ffSlogin /// @return Ok(()) 1275*004e86ffSlogin /// @return Err(i32) 错误码 1276*004e86ffSlogin pub fn flush(&self, fs: &Arc<FATFileSystem>, disk_bytes_offset: u64) -> Result<(), i32> { 1277*004e86ffSlogin // 从磁盘读取数据 1278*004e86ffSlogin let blk_offset = fs.get_in_block_offset(disk_bytes_offset); 1279*004e86ffSlogin let lba = fs.get_lba_from_offset( 1280*004e86ffSlogin fs.bytes_to_sector(fs.get_in_partition_bytes_offset(disk_bytes_offset)), 1281*004e86ffSlogin ); 1282*004e86ffSlogin let mut v: Vec<u8> = Vec::new(); 1283*004e86ffSlogin v.resize(1 * fs.lba_per_sector() * LBA_SIZE, 0); 1284*004e86ffSlogin fs.partition 1285*004e86ffSlogin .disk() 1286*004e86ffSlogin .read_at(lba, 1 * fs.lba_per_sector(), &mut v)?; 1287*004e86ffSlogin 1288*004e86ffSlogin let mut cursor: VecCursor = VecCursor::new(v); 1289*004e86ffSlogin // 切换游标到对应位置 1290*004e86ffSlogin cursor.seek(SeekFrom::SeekSet(blk_offset as i64))?; 1291*004e86ffSlogin cursor.write_exact(&self.name)?; 1292*004e86ffSlogin cursor.write_u8(self.attributes.value)?; 1293*004e86ffSlogin cursor.write_u8(self.nt_res)?; 1294*004e86ffSlogin cursor.write_u8(self.crt_time_tenth)?; 1295*004e86ffSlogin cursor.write_u16(self.crt_time)?; 1296*004e86ffSlogin cursor.write_u16(self.crt_date)?; 1297*004e86ffSlogin cursor.write_u16(self.lst_acc_date)?; 1298*004e86ffSlogin cursor.write_u16(self.fst_clus_hi)?; 1299*004e86ffSlogin cursor.write_u16(self.wrt_time)?; 1300*004e86ffSlogin cursor.write_u16(self.wrt_date)?; 1301*004e86ffSlogin cursor.write_u16(self.fst_clus_lo)?; 1302*004e86ffSlogin cursor.write_u32(self.file_size)?; 1303*004e86ffSlogin 1304*004e86ffSlogin // 把修改后的长目录项刷入磁盘 1305*004e86ffSlogin fs.partition 1306*004e86ffSlogin .disk() 1307*004e86ffSlogin .write_at(lba, 1 * fs.lba_per_sector(), cursor.as_slice())?; 1308*004e86ffSlogin fs.partition.disk().sync()?; 1309*004e86ffSlogin 1310*004e86ffSlogin return Ok(()); 1311*004e86ffSlogin } 1312*004e86ffSlogin 1313*004e86ffSlogin /// @brief 设置短目录项的“第一个簇”字段的值 1314*004e86ffSlogin pub fn set_first_cluster(&mut self, cluster: Cluster) { 1315*004e86ffSlogin self.fst_clus_lo = (cluster.cluster_num & 0x0000ffff) as u16; 1316*004e86ffSlogin self.fst_clus_hi = ((cluster.cluster_num & 0xffff0000) >> 16) as u16; 1317*004e86ffSlogin } 1318*004e86ffSlogin } 1319*004e86ffSlogin 1320*004e86ffSlogin /// @brief FAT文件系统标准定义的目录项 1321*004e86ffSlogin #[derive(Debug, Clone)] 1322*004e86ffSlogin pub enum FATRawDirEntry { 1323*004e86ffSlogin /// 短目录项 1324*004e86ffSlogin Short(ShortDirEntry), 1325*004e86ffSlogin /// 长目录项 1326*004e86ffSlogin Long(LongDirEntry), 1327*004e86ffSlogin /// 当前目录项的Name[0]==0xe5, 是空闲目录项 1328*004e86ffSlogin Free, 1329*004e86ffSlogin /// 当前目录项的Name[0]==0xe5, 是空闲目录项,且在这之后没有被分配过的目录项了。 1330*004e86ffSlogin FreeRest, 1331*004e86ffSlogin } 1332*004e86ffSlogin 1333*004e86ffSlogin impl FATRawDirEntry { 1334*004e86ffSlogin /// 每个目录项的长度(单位:字节) 1335*004e86ffSlogin pub const DIR_ENTRY_LEN: u64 = 32; 1336*004e86ffSlogin 1337*004e86ffSlogin /// @brief 判断当前目录项是否为这个文件的最后一个目录项 1338*004e86ffSlogin fn is_last(&self) -> bool { 1339*004e86ffSlogin match self { 1340*004e86ffSlogin &Self::Short(_) => { 1341*004e86ffSlogin return true; 1342*004e86ffSlogin } 1343*004e86ffSlogin &Self::Long(l) => { 1344*004e86ffSlogin return l.is_last(); 1345*004e86ffSlogin } 1346*004e86ffSlogin _ => { 1347*004e86ffSlogin return false; 1348*004e86ffSlogin } 1349*004e86ffSlogin } 1350*004e86ffSlogin } 1351*004e86ffSlogin 1352*004e86ffSlogin /// @brief 判断当前目录项是否为长目录项 1353*004e86ffSlogin fn is_long(&self) -> bool { 1354*004e86ffSlogin if let Self::Long(_) = self { 1355*004e86ffSlogin return true; 1356*004e86ffSlogin } else { 1357*004e86ffSlogin return false; 1358*004e86ffSlogin } 1359*004e86ffSlogin } 1360*004e86ffSlogin 1361*004e86ffSlogin /// @brief 判断当前目录项是否为短目录项 1362*004e86ffSlogin fn is_short(&self) -> bool { 1363*004e86ffSlogin if let Self::Short(_) = self { 1364*004e86ffSlogin return true; 1365*004e86ffSlogin } else { 1366*004e86ffSlogin return false; 1367*004e86ffSlogin } 1368*004e86ffSlogin } 1369*004e86ffSlogin } 1370*004e86ffSlogin 1371*004e86ffSlogin /// @brief FAT文件系统的目录项迭代器 1372*004e86ffSlogin #[derive(Debug)] 1373*004e86ffSlogin pub struct FATDirIter { 1374*004e86ffSlogin /// 当前正在迭代的簇 1375*004e86ffSlogin current_cluster: Cluster, 1376*004e86ffSlogin /// 当前正在迭代的簇的簇内偏移量 1377*004e86ffSlogin offset: u64, 1378*004e86ffSlogin /// True for the root directories of FAT12 and FAT16 1379*004e86ffSlogin is_root: bool, 1380*004e86ffSlogin /// 指向当前文件系统的指针 1381*004e86ffSlogin fs: Arc<FATFileSystem>, 1382*004e86ffSlogin } 1383*004e86ffSlogin 1384*004e86ffSlogin impl FATDirIter { 1385*004e86ffSlogin /// @brief 迭代当前inode的目录项(获取下一个目录项) 1386*004e86ffSlogin /// 1387*004e86ffSlogin /// @return Ok(Cluster, u64, Option<FATDirEntry>) 1388*004e86ffSlogin /// Cluster: 下一个要读取的簇号 1389*004e86ffSlogin /// u64: 下一个要读取的簇内偏移量 1390*004e86ffSlogin /// Option<FATDirEntry>: 读取到的目录项(如果没有读取到,就返回失败) 1391*004e86ffSlogin /// @return Err(错误码) 可能出现了内部错误,或者是磁盘错误等。具体原因看错误码。 1392*004e86ffSlogin fn get_dir_entry(&mut self) -> Result<(Cluster, u64, Option<FATDirEntry>), i32> { 1393*004e86ffSlogin loop { 1394*004e86ffSlogin // 如果当前簇已经被读完,那么尝试获取下一个簇 1395*004e86ffSlogin if self.offset >= self.fs.bytes_per_cluster() && !self.is_root { 1396*004e86ffSlogin match self.fs.get_fat_entry(self.current_cluster)? { 1397*004e86ffSlogin FATEntry::Next(c) => { 1398*004e86ffSlogin // 获得下一个簇的信息 1399*004e86ffSlogin self.current_cluster = c; 1400*004e86ffSlogin self.offset %= self.fs.bytes_per_cluster(); 1401*004e86ffSlogin } 1402*004e86ffSlogin 1403*004e86ffSlogin _ => { 1404*004e86ffSlogin // 没有下一个簇了,返回None 1405*004e86ffSlogin return Ok((self.current_cluster, self.offset, None)); 1406*004e86ffSlogin } 1407*004e86ffSlogin } 1408*004e86ffSlogin } 1409*004e86ffSlogin 1410*004e86ffSlogin // 如果当前是FAT12/FAT16文件系统,并且当前inode是根目录项。 1411*004e86ffSlogin // 如果offset大于根目录项的最大大小(已经遍历完根目录),那么就返回None 1412*004e86ffSlogin if self.is_root && self.offset > self.fs.root_dir_end_bytes_offset().unwrap() { 1413*004e86ffSlogin return Ok((self.current_cluster, self.offset, None)); 1414*004e86ffSlogin } 1415*004e86ffSlogin 1416*004e86ffSlogin // 获取簇在磁盘内的字节偏移量 1417*004e86ffSlogin let offset: u64 = self.fs.cluster_bytes_offset(self.current_cluster) + self.offset; 1418*004e86ffSlogin 1419*004e86ffSlogin // 从磁盘读取原始的dentry 1420*004e86ffSlogin let raw_dentry: FATRawDirEntry = get_raw_dir_entry(&self.fs, offset)?; 1421*004e86ffSlogin 1422*004e86ffSlogin // 由于迭代顺序从前往后,因此: 1423*004e86ffSlogin // 如果找到1个短目录项,那么证明有一个完整的entry被找到,因此返回。 1424*004e86ffSlogin // 如果找到1个长目录项,那么,就依次往下迭代查找,直到找到一个短目录项,然后返回结果。这里找到的所有的目录项,都属于同一个文件/文件夹。 1425*004e86ffSlogin match raw_dentry { 1426*004e86ffSlogin FATRawDirEntry::Short(s) => { 1427*004e86ffSlogin // 当前找到一个短目录项,更新offset之后,直接返回 1428*004e86ffSlogin self.offset += FATRawDirEntry::DIR_ENTRY_LEN; 1429*004e86ffSlogin return Ok(( 1430*004e86ffSlogin self.current_cluster, 1431*004e86ffSlogin self.offset, 1432*004e86ffSlogin Some(s.to_dir_entry(( 1433*004e86ffSlogin self.current_cluster, 1434*004e86ffSlogin self.offset - FATRawDirEntry::DIR_ENTRY_LEN, 1435*004e86ffSlogin ))), 1436*004e86ffSlogin )); 1437*004e86ffSlogin } 1438*004e86ffSlogin FATRawDirEntry::Long(_) => { 1439*004e86ffSlogin // 当前找到一个长目录项 1440*004e86ffSlogin 1441*004e86ffSlogin // 声明一个数组,来容纳所有的entry。(先把最后一个entry放进去) 1442*004e86ffSlogin let mut long_name_entries: Vec<FATRawDirEntry> = vec![raw_dentry]; 1443*004e86ffSlogin let start_offset: u64 = self.offset; 1444*004e86ffSlogin let start_cluster: Cluster = self.current_cluster; 1445*004e86ffSlogin 1446*004e86ffSlogin self.offset += FATRawDirEntry::DIR_ENTRY_LEN; 1447*004e86ffSlogin 1448*004e86ffSlogin // 由于在FAT文件系统中,文件名最长为255字节,因此,最多有20个长目录项以及1个短目录项。 1449*004e86ffSlogin // 由于上面已经塞了1个长目录项,因此接下来最多需要迭代20次 1450*004e86ffSlogin // 循环查找目录项,直到遇到1个短目录项,或者是空闲目录项 1451*004e86ffSlogin for _ in 0..20 { 1452*004e86ffSlogin // 如果当前簇已经被读完,那么尝试获取下一个簇 1453*004e86ffSlogin if self.offset >= self.fs.bytes_per_cluster() && !self.is_root { 1454*004e86ffSlogin match self.fs.get_fat_entry(self.current_cluster)? { 1455*004e86ffSlogin FATEntry::Next(c) => { 1456*004e86ffSlogin // 获得下一个簇的信息 1457*004e86ffSlogin self.current_cluster = c; 1458*004e86ffSlogin self.offset %= self.fs.bytes_per_cluster(); 1459*004e86ffSlogin } 1460*004e86ffSlogin 1461*004e86ffSlogin _ => { 1462*004e86ffSlogin // 没有下一个簇了,退出迭代 1463*004e86ffSlogin break; 1464*004e86ffSlogin } 1465*004e86ffSlogin } 1466*004e86ffSlogin } 1467*004e86ffSlogin // 如果当前是FAT12/FAT16文件系统,并且当前inode是根目录项。 1468*004e86ffSlogin // 如果offset大于根目录项的最大大小(已经遍历完根目录),那么就退出迭代 1469*004e86ffSlogin if self.is_root 1470*004e86ffSlogin && self.offset > self.fs.root_dir_end_bytes_offset().unwrap() 1471*004e86ffSlogin { 1472*004e86ffSlogin break; 1473*004e86ffSlogin } 1474*004e86ffSlogin 1475*004e86ffSlogin // 获取簇在磁盘内的字节偏移量 1476*004e86ffSlogin let offset: u64 = 1477*004e86ffSlogin self.fs.cluster_bytes_offset(self.current_cluster) + self.offset; 1478*004e86ffSlogin // 从磁盘读取原始的dentry 1479*004e86ffSlogin let raw_dentry: FATRawDirEntry = get_raw_dir_entry(&self.fs, offset)?; 1480*004e86ffSlogin 1481*004e86ffSlogin match raw_dentry { 1482*004e86ffSlogin FATRawDirEntry::Short(_) => { 1483*004e86ffSlogin // 当前遇到1个短目录项,证明当前文件/文件夹的所有dentry都被读取完了,因此在将其加入数组后,退出迭代。 1484*004e86ffSlogin long_name_entries.push(raw_dentry); 1485*004e86ffSlogin break; 1486*004e86ffSlogin } 1487*004e86ffSlogin FATRawDirEntry::Long(_) => { 1488*004e86ffSlogin // 当前遇到1个长目录项,将其加入数组,然后更新offset,继续迭代。 1489*004e86ffSlogin long_name_entries.push(raw_dentry); 1490*004e86ffSlogin self.offset += FATRawDirEntry::DIR_ENTRY_LEN; 1491*004e86ffSlogin } 1492*004e86ffSlogin 1493*004e86ffSlogin _ => { 1494*004e86ffSlogin // 遇到了空闲簇,但没遇到短目录项,说明文件系统出错了,退出。 1495*004e86ffSlogin break; 1496*004e86ffSlogin } 1497*004e86ffSlogin } 1498*004e86ffSlogin } 1499*004e86ffSlogin // kdebug!("collect dentries done. long_name_entries={long_name_entries:?}"); 1500*004e86ffSlogin let dir_entry: Result<FATDirEntry, i32> = FATDirEntry::new( 1501*004e86ffSlogin long_name_entries, 1502*004e86ffSlogin ( 1503*004e86ffSlogin (start_cluster, start_offset), 1504*004e86ffSlogin (self.current_cluster, self.offset), 1505*004e86ffSlogin ), 1506*004e86ffSlogin ); 1507*004e86ffSlogin // kdebug!("dir_entry={:?}", dir_entry); 1508*004e86ffSlogin match dir_entry { 1509*004e86ffSlogin Ok(d) => { 1510*004e86ffSlogin // kdebug!("dir_entry ok"); 1511*004e86ffSlogin self.offset += FATRawDirEntry::DIR_ENTRY_LEN; 1512*004e86ffSlogin return Ok((self.current_cluster, self.offset, Some(d))); 1513*004e86ffSlogin } 1514*004e86ffSlogin 1515*004e86ffSlogin Err(_) => { 1516*004e86ffSlogin // kdebug!("dir_entry err, e={}", e); 1517*004e86ffSlogin self.offset += FATRawDirEntry::DIR_ENTRY_LEN; 1518*004e86ffSlogin } 1519*004e86ffSlogin } 1520*004e86ffSlogin } 1521*004e86ffSlogin FATRawDirEntry::Free => { 1522*004e86ffSlogin // 当前目录项是空的 1523*004e86ffSlogin self.offset += FATRawDirEntry::DIR_ENTRY_LEN; 1524*004e86ffSlogin } 1525*004e86ffSlogin FATRawDirEntry::FreeRest => { 1526*004e86ffSlogin // 当前目录项是空的,且之后都是空的,因此直接返回 1527*004e86ffSlogin return Ok((self.current_cluster, self.offset, None)); 1528*004e86ffSlogin } 1529*004e86ffSlogin } 1530*004e86ffSlogin } 1531*004e86ffSlogin } 1532*004e86ffSlogin } 1533*004e86ffSlogin 1534*004e86ffSlogin /// 为DirIter实现迭代器trait 1535*004e86ffSlogin impl Iterator for FATDirIter { 1536*004e86ffSlogin type Item = FATDirEntry; 1537*004e86ffSlogin 1538*004e86ffSlogin fn next(&mut self) -> Option<Self::Item> { 1539*004e86ffSlogin match self.get_dir_entry() { 1540*004e86ffSlogin Ok((cluster, offset, result)) => { 1541*004e86ffSlogin self.current_cluster = cluster; 1542*004e86ffSlogin self.offset = offset; 1543*004e86ffSlogin return result; 1544*004e86ffSlogin } 1545*004e86ffSlogin Err(_) => { 1546*004e86ffSlogin return None; 1547*004e86ffSlogin } 1548*004e86ffSlogin } 1549*004e86ffSlogin } 1550*004e86ffSlogin } 1551*004e86ffSlogin 1552*004e86ffSlogin impl FATDirEntry { 1553*004e86ffSlogin /// @brief 构建FATDirEntry枚举类型 1554*004e86ffSlogin /// 1555*004e86ffSlogin /// @param long_name_entries 长目录项的数组。 1556*004e86ffSlogin /// 格式:[第20个(或者是最大ord的那个), 19, 18, ..., 1, 短目录项] 1557*004e86ffSlogin /// 1558*004e86ffSlogin /// @return Ok(FATDirEntry) 构建好的FATDirEntry类型的对象 1559*004e86ffSlogin /// @return Err(i32) 错误码 1560*004e86ffSlogin pub fn new( 1561*004e86ffSlogin mut long_name_entries: Vec<FATRawDirEntry>, 1562*004e86ffSlogin loc: ((Cluster, u64), (Cluster, u64)), 1563*004e86ffSlogin ) -> Result<Self, i32> { 1564*004e86ffSlogin if long_name_entries.is_empty() { 1565*004e86ffSlogin return Err(-(EINVAL as i32)); 1566*004e86ffSlogin } 1567*004e86ffSlogin 1568*004e86ffSlogin if !long_name_entries[0].is_last() || !long_name_entries.last().unwrap().is_short() { 1569*004e86ffSlogin // 存在孤立的目录项,文件系统出现异常,因此返回错误,表明其只读。 1570*004e86ffSlogin // TODO: 标记整个FAT文件系统为只读的 1571*004e86ffSlogin return Err(-(EROFS as i32)); 1572*004e86ffSlogin } 1573*004e86ffSlogin 1574*004e86ffSlogin // 取出短目录项(位于vec的末尾) 1575*004e86ffSlogin let short_dentry: ShortDirEntry = match long_name_entries.pop().unwrap() { 1576*004e86ffSlogin FATRawDirEntry::Short(s) => s, 1577*004e86ffSlogin _ => unreachable!(), 1578*004e86ffSlogin }; 1579*004e86ffSlogin 1580*004e86ffSlogin let mut extractor = LongNameExtractor::new(); 1581*004e86ffSlogin for entry in &long_name_entries { 1582*004e86ffSlogin match entry { 1583*004e86ffSlogin &FATRawDirEntry::Long(l) => { 1584*004e86ffSlogin extractor.process(l)?; 1585*004e86ffSlogin } 1586*004e86ffSlogin 1587*004e86ffSlogin _ => { 1588*004e86ffSlogin return Err(-(EROFS as i32)); 1589*004e86ffSlogin } 1590*004e86ffSlogin } 1591*004e86ffSlogin } 1592*004e86ffSlogin // 检验校验和是否正确 1593*004e86ffSlogin if extractor.validate_checksum(&short_dentry) { 1594*004e86ffSlogin // 校验和正确,返回一个长目录项 1595*004e86ffSlogin return Ok(short_dentry.to_dir_entry_with_long_name(extractor.to_string(), loc)); 1596*004e86ffSlogin } else { 1597*004e86ffSlogin // 校验和不相同,认为文件系统出错 1598*004e86ffSlogin return Err(-(EROFS as i32)); 1599*004e86ffSlogin } 1600*004e86ffSlogin } 1601*004e86ffSlogin 1602*004e86ffSlogin /// @brief 获取短目录项的名字 1603*004e86ffSlogin pub fn short_name(&self) -> String { 1604*004e86ffSlogin match self { 1605*004e86ffSlogin FATDirEntry::File(f) | FATDirEntry::VolId(f) => { 1606*004e86ffSlogin return f.short_dir_entry.name_to_string(); 1607*004e86ffSlogin } 1608*004e86ffSlogin FATDirEntry::Dir(d) => match d.short_dir_entry { 1609*004e86ffSlogin Some(s) => { 1610*004e86ffSlogin return s.name_to_string(); 1611*004e86ffSlogin } 1612*004e86ffSlogin None => { 1613*004e86ffSlogin return String::from("/"); 1614*004e86ffSlogin } 1615*004e86ffSlogin }, 1616*004e86ffSlogin FATDirEntry::UnInit => unreachable!("FATFS: FATDirEntry uninitialized."), 1617*004e86ffSlogin } 1618*004e86ffSlogin } 1619*004e86ffSlogin 1620*004e86ffSlogin /// @brief 获取短目录项结构体 1621*004e86ffSlogin pub fn short_dir_entry(&self) -> Option<ShortDirEntry> { 1622*004e86ffSlogin match &self { 1623*004e86ffSlogin FATDirEntry::File(f) => { 1624*004e86ffSlogin return Some(f.short_dir_entry); 1625*004e86ffSlogin } 1626*004e86ffSlogin FATDirEntry::Dir(d) => { 1627*004e86ffSlogin return d.short_dir_entry; 1628*004e86ffSlogin } 1629*004e86ffSlogin FATDirEntry::VolId(s) => { 1630*004e86ffSlogin return Some(s.short_dir_entry); 1631*004e86ffSlogin } 1632*004e86ffSlogin FATDirEntry::UnInit => unreachable!("FATFS: FATDirEntry uninitialized."), 1633*004e86ffSlogin } 1634*004e86ffSlogin } 1635*004e86ffSlogin 1636*004e86ffSlogin /// @brief 获取目录项的第一个簇的簇号 1637*004e86ffSlogin pub fn first_cluster(&self) -> Cluster { 1638*004e86ffSlogin match self { 1639*004e86ffSlogin FATDirEntry::File(f) => { 1640*004e86ffSlogin return f.first_cluster; 1641*004e86ffSlogin } 1642*004e86ffSlogin FATDirEntry::Dir(d) => { 1643*004e86ffSlogin return d.first_cluster; 1644*004e86ffSlogin } 1645*004e86ffSlogin FATDirEntry::VolId(s) => { 1646*004e86ffSlogin return s.first_cluster; 1647*004e86ffSlogin } 1648*004e86ffSlogin FATDirEntry::UnInit => unreachable!("FATFS: FATDirEntry uninitialized."), 1649*004e86ffSlogin } 1650*004e86ffSlogin } 1651*004e86ffSlogin 1652*004e86ffSlogin /// @brief 获取当前目录项所占用的簇的范围 1653*004e86ffSlogin /// 1654*004e86ffSlogin /// @return (起始簇,簇内偏移量), (终止簇,簇内偏移量) 1655*004e86ffSlogin pub fn get_dir_range(&self) -> Option<((Cluster, u64), (Cluster, u64))> { 1656*004e86ffSlogin match self { 1657*004e86ffSlogin FATDirEntry::File(f) => Some(f.loc), 1658*004e86ffSlogin FATDirEntry::Dir(d) => d.loc, 1659*004e86ffSlogin FATDirEntry::VolId(s) => Some(s.loc), 1660*004e86ffSlogin FATDirEntry::UnInit => unreachable!("FATFS: FATDirEntry uninitialized."), 1661*004e86ffSlogin } 1662*004e86ffSlogin } 1663*004e86ffSlogin 1664*004e86ffSlogin /// @brief 获取原始的短目录项名(FAT标准规定的) 1665*004e86ffSlogin pub fn short_name_raw(&self) -> [u8; 11] { 1666*004e86ffSlogin match self { 1667*004e86ffSlogin FATDirEntry::File(f) => { 1668*004e86ffSlogin return f.short_dir_entry.name; 1669*004e86ffSlogin } 1670*004e86ffSlogin FATDirEntry::Dir(d) => match d.short_dir_entry { 1671*004e86ffSlogin // 存在短目录项,直接返回 1672*004e86ffSlogin Some(s) => { 1673*004e86ffSlogin return s.name; 1674*004e86ffSlogin } 1675*004e86ffSlogin // 是根目录项 1676*004e86ffSlogin None => { 1677*004e86ffSlogin let mut s = [0x20u8; 11]; 1678*004e86ffSlogin s[0] = '/' as u8; 1679*004e86ffSlogin return s; 1680*004e86ffSlogin } 1681*004e86ffSlogin }, 1682*004e86ffSlogin FATDirEntry::VolId(s) => { 1683*004e86ffSlogin return s.short_dir_entry.name; 1684*004e86ffSlogin } 1685*004e86ffSlogin 1686*004e86ffSlogin FATDirEntry::UnInit => unreachable!("FATFS: FATDirEntry uninitialized."), 1687*004e86ffSlogin } 1688*004e86ffSlogin } 1689*004e86ffSlogin 1690*004e86ffSlogin /// @brief 获取目录项的名字 1691*004e86ffSlogin pub fn name(&self) -> String { 1692*004e86ffSlogin match self { 1693*004e86ffSlogin FATDirEntry::File(f) => { 1694*004e86ffSlogin return f.file_name.clone(); 1695*004e86ffSlogin } 1696*004e86ffSlogin FATDirEntry::VolId(s) => { 1697*004e86ffSlogin return s.file_name.clone(); 1698*004e86ffSlogin } 1699*004e86ffSlogin FATDirEntry::Dir(d) => { 1700*004e86ffSlogin return d.dir_name.clone(); 1701*004e86ffSlogin } 1702*004e86ffSlogin FATDirEntry::UnInit => unreachable!("FATFS: FATDirEntry uninitialized."), 1703*004e86ffSlogin } 1704*004e86ffSlogin } 1705*004e86ffSlogin 1706*004e86ffSlogin /// @brief 判断目录项是否为文件 1707*004e86ffSlogin pub fn is_file(&self) -> bool { 1708*004e86ffSlogin match self { 1709*004e86ffSlogin &FATDirEntry::File(_) | &FATDirEntry::VolId(_) => true, 1710*004e86ffSlogin _ => false, 1711*004e86ffSlogin } 1712*004e86ffSlogin } 1713*004e86ffSlogin 1714*004e86ffSlogin /// @brief 判断目录项是否为文件夹 1715*004e86ffSlogin pub fn is_dir(&self) -> bool { 1716*004e86ffSlogin match &self { 1717*004e86ffSlogin &FATDirEntry::Dir(_) => true, 1718*004e86ffSlogin _ => false, 1719*004e86ffSlogin } 1720*004e86ffSlogin } 1721*004e86ffSlogin 1722*004e86ffSlogin /// @brief 判断目录项是否为Volume id 1723*004e86ffSlogin pub fn is_vol_id(&self) -> bool { 1724*004e86ffSlogin match self { 1725*004e86ffSlogin &FATDirEntry::VolId(_) => true, 1726*004e86ffSlogin _ => false, 1727*004e86ffSlogin } 1728*004e86ffSlogin } 1729*004e86ffSlogin 1730*004e86ffSlogin /// @brief 判断FAT目录项的名字与给定的是否相等 1731*004e86ffSlogin /// 1732*004e86ffSlogin /// 由于FAT32对大小写不敏感,因此将字符都转为大写,然后比较 1733*004e86ffSlogin /// 1734*004e86ffSlogin /// @return bool 相等 => true 1735*004e86ffSlogin /// 不相等 => false 1736*004e86ffSlogin pub fn eq_name(&self, name: &str) -> bool { 1737*004e86ffSlogin // 由于FAT32对大小写不敏感,因此将字符都转为大写,然后比较。 1738*004e86ffSlogin let binding = self.short_name(); 1739*004e86ffSlogin let short_name = binding.chars().flat_map(|c| c.to_uppercase()); 1740*004e86ffSlogin let binding = self.name(); 1741*004e86ffSlogin let long_name = binding.chars().flat_map(|c| c.to_uppercase()); 1742*004e86ffSlogin let name = name.chars().flat_map(|c| c.to_uppercase()); 1743*004e86ffSlogin 1744*004e86ffSlogin let long_name_matches: bool = long_name.eq(name.clone()); 1745*004e86ffSlogin let short_name_matches: bool = short_name.eq(name); 1746*004e86ffSlogin 1747*004e86ffSlogin return long_name_matches || short_name_matches; 1748*004e86ffSlogin } 1749*004e86ffSlogin 1750*004e86ffSlogin /// @brief 将FATDirEntry转换为FATFile对象 1751*004e86ffSlogin pub fn to_file(&self) -> Result<FATFile, i32> { 1752*004e86ffSlogin if self.is_file() == false { 1753*004e86ffSlogin return Err(-(EISDIR as i32)); 1754*004e86ffSlogin } 1755*004e86ffSlogin 1756*004e86ffSlogin match &self { 1757*004e86ffSlogin FATDirEntry::File(f) | FATDirEntry::VolId(f) => { 1758*004e86ffSlogin return Ok(f.clone()); 1759*004e86ffSlogin } 1760*004e86ffSlogin _ => unreachable!(), 1761*004e86ffSlogin } 1762*004e86ffSlogin } 1763*004e86ffSlogin 1764*004e86ffSlogin /// @brief 将FATDirEntry转换为FATDir对象 1765*004e86ffSlogin pub fn to_dir(&self) -> Result<FATDir, i32> { 1766*004e86ffSlogin if self.is_dir() == false { 1767*004e86ffSlogin return Err(-(ENOTDIR as i32)); 1768*004e86ffSlogin } 1769*004e86ffSlogin match &self { 1770*004e86ffSlogin FATDirEntry::Dir(d) => { 1771*004e86ffSlogin return Ok(d.clone()); 1772*004e86ffSlogin } 1773*004e86ffSlogin _ => unreachable!(), 1774*004e86ffSlogin } 1775*004e86ffSlogin } 1776*004e86ffSlogin } 1777*004e86ffSlogin 1778*004e86ffSlogin /// 用于生成短目录项文件名的生成器。 1779*004e86ffSlogin #[derive(Debug, Default)] 1780*004e86ffSlogin pub struct ShortNameGenerator { 1781*004e86ffSlogin /// 短目录项的名字 1782*004e86ffSlogin name: [u8; 11], 1783*004e86ffSlogin /// 生成器的标志位(使用impl里面的mask来解析) 1784*004e86ffSlogin flags: u8, 1785*004e86ffSlogin /// 基础名的长度 1786*004e86ffSlogin basename_len: u8, 1787*004e86ffSlogin /// 对于文件名形如(TE021F~1.TXT)的,短前缀+校验码的短目录项,该字段表示基础名末尾数字的对应位。 1788*004e86ffSlogin checksum_bitmask: u16, 1789*004e86ffSlogin /// Fletcher-16 Checksum(与填写到ShortDirEntry里面的不一样) 1790*004e86ffSlogin checksum: u16, 1791*004e86ffSlogin /// 对于形如(TEXTFI~1.TXT)的短目录项名称,其中的数字的bitmask(第0位置位则表示这个数字是0) 1792*004e86ffSlogin suffix_bitmask: u16, 1793*004e86ffSlogin } 1794*004e86ffSlogin 1795*004e86ffSlogin impl ShortNameGenerator { 1796*004e86ffSlogin /// 短目录项的名称的长度 1797*004e86ffSlogin const SHORT_NAME_LEN: usize = 8; 1798*004e86ffSlogin 1799*004e86ffSlogin // ===== flags标志位的含义 ===== 1800*004e86ffSlogin const IS_LOSSY: u8 = (1 << 0); 1801*004e86ffSlogin const IS_EXACT_MATCH: u8 = (1 << 1); 1802*004e86ffSlogin const IS_DOT: u8 = (1 << 2); 1803*004e86ffSlogin const IS_DOTDOT: u8 = (1 << 3); 1804*004e86ffSlogin /// 名称被完全拷贝 1805*004e86ffSlogin const NAME_FITS: u8 = (1 << 4); 1806*004e86ffSlogin 1807*004e86ffSlogin /// @brief 初始化一个短目录项名称生成器 1808*004e86ffSlogin pub fn new(mut name: &str) -> Self { 1809*004e86ffSlogin name = name.trim(); 1810*004e86ffSlogin 1811*004e86ffSlogin let mut short_name: [u8; 11] = [0x20u8; 11]; 1812*004e86ffSlogin if name == "." { 1813*004e86ffSlogin short_name[0] = '.' as u8; 1814*004e86ffSlogin } 1815*004e86ffSlogin 1816*004e86ffSlogin if name == ".." { 1817*004e86ffSlogin short_name[0] = '.' as u8; 1818*004e86ffSlogin short_name[1] = '.' as u8; 1819*004e86ffSlogin } 1820*004e86ffSlogin 1821*004e86ffSlogin // @name_fits: 名称是否被完全拷贝 1822*004e86ffSlogin // @basename_len: 基础名的长度 1823*004e86ffSlogin // @is_lossy: 是否存在不合法的字符 1824*004e86ffSlogin let (name_fits, basename_len, is_lossy) = match name.rfind('.') { 1825*004e86ffSlogin Some(index) => { 1826*004e86ffSlogin // 文件名里面有".", 且index为最右边的点号所在的下标(bytes index) 1827*004e86ffSlogin // 拷贝基础名 1828*004e86ffSlogin let (b_len, fits, b_lossy) = 1829*004e86ffSlogin Self::copy_part(&mut short_name[..Self::SHORT_NAME_LEN], &name[..index]); 1830*004e86ffSlogin 1831*004e86ffSlogin // 拷贝扩展名 1832*004e86ffSlogin let (_, ext_fits, ext_lossy) = Self::copy_part( 1833*004e86ffSlogin &mut short_name[Self::SHORT_NAME_LEN..Self::SHORT_NAME_LEN + 3], 1834*004e86ffSlogin &name[index + 1..], 1835*004e86ffSlogin ); 1836*004e86ffSlogin 1837*004e86ffSlogin (fits && ext_fits, b_len, b_lossy || ext_lossy) 1838*004e86ffSlogin } 1839*004e86ffSlogin None => { 1840*004e86ffSlogin // 文件名中,不存在"." 1841*004e86ffSlogin let (b_len, fits, b_lossy) = 1842*004e86ffSlogin Self::copy_part(&mut short_name[..Self::SHORT_NAME_LEN], &name); 1843*004e86ffSlogin (fits, b_len, b_lossy) 1844*004e86ffSlogin } 1845*004e86ffSlogin }; 1846*004e86ffSlogin 1847*004e86ffSlogin let mut flags: u8 = 0; 1848*004e86ffSlogin // 设置flags 1849*004e86ffSlogin if is_lossy { 1850*004e86ffSlogin flags |= Self::IS_LOSSY; 1851*004e86ffSlogin } 1852*004e86ffSlogin if name == "." { 1853*004e86ffSlogin flags |= Self::IS_DOT; 1854*004e86ffSlogin } 1855*004e86ffSlogin if name == ".." { 1856*004e86ffSlogin flags |= Self::IS_DOTDOT; 1857*004e86ffSlogin } 1858*004e86ffSlogin 1859*004e86ffSlogin if name_fits { 1860*004e86ffSlogin flags |= Self::NAME_FITS; 1861*004e86ffSlogin } 1862*004e86ffSlogin 1863*004e86ffSlogin return ShortNameGenerator { 1864*004e86ffSlogin name: short_name, 1865*004e86ffSlogin flags: flags, 1866*004e86ffSlogin basename_len: basename_len, 1867*004e86ffSlogin checksum: Self::fletcher_16_checksum(name), 1868*004e86ffSlogin ..Default::default() 1869*004e86ffSlogin }; 1870*004e86ffSlogin } 1871*004e86ffSlogin 1872*004e86ffSlogin /// @brief 拷贝字符串到一个u8数组 1873*004e86ffSlogin /// 1874*004e86ffSlogin /// @return (u8, bool, bool) 1875*004e86ffSlogin /// return.0: 拷贝了的字符串的长度 1876*004e86ffSlogin /// return.1: 是否完全拷贝完整个字符串 1877*004e86ffSlogin /// return.2: 拷贝过程中,是否出现了不合法字符 1878*004e86ffSlogin fn copy_part(dest: &mut [u8], src: &str) -> (u8, bool, bool) { 1879*004e86ffSlogin let mut dest_len: usize = 0; 1880*004e86ffSlogin let mut lossy_conv = false; 1881*004e86ffSlogin 1882*004e86ffSlogin for c in src.chars() { 1883*004e86ffSlogin // 如果src还有字符,而dest已经满了,那么表示没有完全拷贝完。 1884*004e86ffSlogin if dest_len == dest.len() { 1885*004e86ffSlogin return (dest_len as u8, false, lossy_conv); 1886*004e86ffSlogin } 1887*004e86ffSlogin 1888*004e86ffSlogin if c == ' ' || c == '.' { 1889*004e86ffSlogin lossy_conv = true; 1890*004e86ffSlogin continue; 1891*004e86ffSlogin } 1892*004e86ffSlogin 1893*004e86ffSlogin let cp: char = match c { 1894*004e86ffSlogin 'a'..='z' | 'A'..='Z' | '0'..='9' => c, 1895*004e86ffSlogin '$' | '%' | '\'' | '-' | '_' | '@' | '~' | '`' | '!' | '(' | ')' | '{' | '}' 1896*004e86ffSlogin | '^' | '#' | '&' => c, 1897*004e86ffSlogin _ => '_', 1898*004e86ffSlogin }; 1899*004e86ffSlogin 1900*004e86ffSlogin // 判断是否存在不符合条件的字符 1901*004e86ffSlogin lossy_conv = lossy_conv || c != cp; 1902*004e86ffSlogin 1903*004e86ffSlogin // 拷贝字符 1904*004e86ffSlogin dest[dest_len] = c.to_ascii_uppercase() as u8; 1905*004e86ffSlogin dest_len += 1; 1906*004e86ffSlogin } 1907*004e86ffSlogin 1908*004e86ffSlogin // 返回结果 1909*004e86ffSlogin return (dest_len as u8, true, lossy_conv); 1910*004e86ffSlogin } 1911*004e86ffSlogin 1912*004e86ffSlogin fn fletcher_16_checksum(name: &str) -> u16 { 1913*004e86ffSlogin let mut sum1: u16 = 0; 1914*004e86ffSlogin let mut sum2: u16 = 0; 1915*004e86ffSlogin for c in name.chars() { 1916*004e86ffSlogin sum1 = (sum1 + (c as u16)) % 0xff; 1917*004e86ffSlogin sum2 = (sum1 + sum2) & 0xff; 1918*004e86ffSlogin } 1919*004e86ffSlogin return (sum2 << 8) | sum1; 1920*004e86ffSlogin } 1921*004e86ffSlogin 1922*004e86ffSlogin /// @brief 更新生成器的状态 1923*004e86ffSlogin /// 当长目录项不存在的时候,需要调用这个函数来更新生成器的状态 1924*004e86ffSlogin pub fn add_name(&mut self, name: &[u8; 11]) { 1925*004e86ffSlogin // === 判断名称是否严格的完全匹配 1926*004e86ffSlogin if name == &self.name { 1927*004e86ffSlogin self.flags |= Self::IS_EXACT_MATCH; 1928*004e86ffSlogin } 1929*004e86ffSlogin 1930*004e86ffSlogin // === 检查是否存在长前缀的格式冲突。对于这样的短目录项名称:(TEXTFI~1.TXT) 1931*004e86ffSlogin // 获取名称前缀 1932*004e86ffSlogin let prefix_len = min(self.basename_len, 6) as usize; 1933*004e86ffSlogin // 获取后缀的那个数字 1934*004e86ffSlogin let num_suffix: Option<u32> = if name[prefix_len] as char == '~' { 1935*004e86ffSlogin (name[prefix_len + 1] as char).to_digit(10) 1936*004e86ffSlogin } else { 1937*004e86ffSlogin None 1938*004e86ffSlogin }; 1939*004e86ffSlogin 1940*004e86ffSlogin // 判断扩展名是否匹配 1941*004e86ffSlogin let ext_matches: bool = name[8..] == self.name[8..]; 1942*004e86ffSlogin 1943*004e86ffSlogin if name[..prefix_len] == self.name[..prefix_len] // 基础名前缀相同 1944*004e86ffSlogin && num_suffix.is_some() // 基础名具有数字后缀 1945*004e86ffSlogin && ext_matches 1946*004e86ffSlogin // 扩展名相匹配 1947*004e86ffSlogin { 1948*004e86ffSlogin let num = num_suffix.unwrap(); 1949*004e86ffSlogin self.suffix_bitmask |= 1 << num; 1950*004e86ffSlogin } 1951*004e86ffSlogin 1952*004e86ffSlogin // === 检查是否存在短前缀+校验和的冲突,文件名形如:(TE021F~1.TXT) 1953*004e86ffSlogin let prefix_len = min(self.basename_len, 2) as usize; 1954*004e86ffSlogin let num_suffix: Option<u32> = if name[prefix_len + 4] as char == '~' { 1955*004e86ffSlogin (name[prefix_len + 1] as char).to_digit(10) 1956*004e86ffSlogin } else { 1957*004e86ffSlogin None 1958*004e86ffSlogin }; 1959*004e86ffSlogin 1960*004e86ffSlogin if name[..prefix_len] == self.name[..prefix_len] && num_suffix.is_some() && ext_matches { 1961*004e86ffSlogin // 获取短文件名中的校验码字段 1962*004e86ffSlogin let checksum_result: Result< 1963*004e86ffSlogin Result<u16, core::num::ParseIntError>, 1964*004e86ffSlogin core::str::Utf8Error, 1965*004e86ffSlogin > = core::str::from_utf8(&name[prefix_len..prefix_len + 4]) 1966*004e86ffSlogin .map(|s| u16::from_str_radix(s, 16)); 1967*004e86ffSlogin // 如果校验码相同 1968*004e86ffSlogin if checksum_result == Ok(Ok(self.checksum)) { 1969*004e86ffSlogin let num = num_suffix.unwrap(); 1970*004e86ffSlogin // 置位checksum_bitmask中,基础名末尾数字的对应位 1971*004e86ffSlogin self.checksum_bitmask |= 1 << num; 1972*004e86ffSlogin } 1973*004e86ffSlogin } 1974*004e86ffSlogin } 1975*004e86ffSlogin 1976*004e86ffSlogin pub fn generate(&self) -> Result<[u8; 11], i32> { 1977*004e86ffSlogin if self.is_dot() || self.is_dotdot() { 1978*004e86ffSlogin return Ok(self.name); 1979*004e86ffSlogin } 1980*004e86ffSlogin 1981*004e86ffSlogin // 如果当前名字不存在不合法的字符,且名称被完整拷贝,但是exact match为false,可以认为名称没有冲突,直接返回 1982*004e86ffSlogin if !self.is_lossy() && self.name_fits() && !self.is_exact_match() { 1983*004e86ffSlogin return Ok(self.name); 1984*004e86ffSlogin } 1985*004e86ffSlogin 1986*004e86ffSlogin // 尝试使用长前缀(6字符) 1987*004e86ffSlogin for i in 1..5 { 1988*004e86ffSlogin if self.suffix_bitmask & (1 << i) == 0 { 1989*004e86ffSlogin return Ok(self.build_prefixed_name(i as u32, false)); 1990*004e86ffSlogin } 1991*004e86ffSlogin } 1992*004e86ffSlogin 1993*004e86ffSlogin // 尝试使用短前缀+校验码 1994*004e86ffSlogin for i in 1..10 { 1995*004e86ffSlogin if self.checksum_bitmask & (1 << i) == 0 { 1996*004e86ffSlogin return Ok(self.build_prefixed_name(i as u32, true)); 1997*004e86ffSlogin } 1998*004e86ffSlogin } 1999*004e86ffSlogin // 由于产生太多的冲突,因此返回错误(“短文件名已经存在”) 2000*004e86ffSlogin return Err(-(EEXIST as i32)); 2001*004e86ffSlogin } 2002*004e86ffSlogin 2003*004e86ffSlogin pub fn next_iteration(&mut self) { 2004*004e86ffSlogin // 在下一次迭代中,尝试一个不同的校验和 2005*004e86ffSlogin self.checksum = (core::num::Wrapping(self.checksum) + core::num::Wrapping(1)).0; 2006*004e86ffSlogin // 清空bitmask 2007*004e86ffSlogin self.suffix_bitmask = 0; 2008*004e86ffSlogin self.checksum_bitmask = 0; 2009*004e86ffSlogin } 2010*004e86ffSlogin 2011*004e86ffSlogin /// @brief 构造具有前缀的短目录项名称 2012*004e86ffSlogin /// 2013*004e86ffSlogin /// @param num 这是第几个重名的前缀名 2014*004e86ffSlogin /// @param with_checksum 前缀名中是否包含校验码 2015*004e86ffSlogin /// 2016*004e86ffSlogin /// @return 构造好的短目录项名称数组 2017*004e86ffSlogin fn build_prefixed_name(&self, num: u32, with_checksum: bool) -> [u8; 11] { 2018*004e86ffSlogin let mut buf: [u8; 11] = [0x20u8; 11]; 2019*004e86ffSlogin let prefix_len: usize = if with_checksum { 2020*004e86ffSlogin let prefix_len: usize = min(self.basename_len as usize, 2); 2021*004e86ffSlogin buf[..prefix_len].copy_from_slice(&self.name[..prefix_len]); 2022*004e86ffSlogin buf[prefix_len..prefix_len + 4].copy_from_slice(&Self::u16_to_u8_array(self.checksum)); 2023*004e86ffSlogin prefix_len + 4 2024*004e86ffSlogin } else { 2025*004e86ffSlogin let prefix_len = min(self.basename_len as usize, 6); 2026*004e86ffSlogin buf[..prefix_len].copy_from_slice(&self.name[..prefix_len]); 2027*004e86ffSlogin prefix_len 2028*004e86ffSlogin }; 2029*004e86ffSlogin 2030*004e86ffSlogin buf[prefix_len] = '~' as u8; 2031*004e86ffSlogin buf[prefix_len + 1] = char::from_digit(num, 10).unwrap() as u8; 2032*004e86ffSlogin buf[8..].copy_from_slice(&self.name[8..]); 2033*004e86ffSlogin return buf; 2034*004e86ffSlogin } 2035*004e86ffSlogin 2036*004e86ffSlogin /// @brief 将一个u16数字转换为十六进制大写字符串对应的ascii数组。 2037*004e86ffSlogin /// 举例:将x=12345转换为16进制字符串“3039”对应的ascii码数组:[51,48,51,57] 2038*004e86ffSlogin fn u16_to_u8_array(x: u16) -> [u8; 4] { 2039*004e86ffSlogin let c1 = char::from_digit((x as u32 >> 12) & 0xf, 16) 2040*004e86ffSlogin .unwrap() 2041*004e86ffSlogin .to_ascii_uppercase() as u8; 2042*004e86ffSlogin let c2 = char::from_digit((x as u32 >> 8) & 0xf, 16) 2043*004e86ffSlogin .unwrap() 2044*004e86ffSlogin .to_ascii_uppercase() as u8; 2045*004e86ffSlogin let c3 = char::from_digit((x as u32 >> 4) & 0xf, 16) 2046*004e86ffSlogin .unwrap() 2047*004e86ffSlogin .to_ascii_uppercase() as u8; 2048*004e86ffSlogin let c4 = char::from_digit((x as u32 >> 0) & 0xf, 16) 2049*004e86ffSlogin .unwrap() 2050*004e86ffSlogin .to_ascii_uppercase() as u8; 2051*004e86ffSlogin return [c1, c2, c3, c4]; 2052*004e86ffSlogin } 2053*004e86ffSlogin 2054*004e86ffSlogin #[inline] 2055*004e86ffSlogin fn is_lossy(&self) -> bool { 2056*004e86ffSlogin return (self.flags & Self::IS_LOSSY) > 0; 2057*004e86ffSlogin } 2058*004e86ffSlogin 2059*004e86ffSlogin #[inline] 2060*004e86ffSlogin fn is_exact_match(&self) -> bool { 2061*004e86ffSlogin return (self.flags & Self::IS_EXACT_MATCH) > 0; 2062*004e86ffSlogin } 2063*004e86ffSlogin 2064*004e86ffSlogin #[inline] 2065*004e86ffSlogin fn is_dot(&self) -> bool { 2066*004e86ffSlogin return (self.flags & Self::IS_DOT) > 0; 2067*004e86ffSlogin } 2068*004e86ffSlogin 2069*004e86ffSlogin #[inline] 2070*004e86ffSlogin fn is_dotdot(&self) -> bool { 2071*004e86ffSlogin return (self.flags & Self::IS_DOTDOT) > 0; 2072*004e86ffSlogin } 2073*004e86ffSlogin 2074*004e86ffSlogin #[inline] 2075*004e86ffSlogin fn name_fits(&self) -> bool { 2076*004e86ffSlogin return (self.flags & Self::NAME_FITS) > 0; 2077*004e86ffSlogin } 2078*004e86ffSlogin } 2079*004e86ffSlogin 2080*004e86ffSlogin /// 从多个LongName中提取完整文件名字段的提取器 2081*004e86ffSlogin struct LongNameExtractor { 2082*004e86ffSlogin name: Vec<u16>, 2083*004e86ffSlogin checksum: u8, 2084*004e86ffSlogin index: u8, 2085*004e86ffSlogin } 2086*004e86ffSlogin 2087*004e86ffSlogin impl LongNameExtractor { 2088*004e86ffSlogin fn new() -> Self { 2089*004e86ffSlogin return LongNameExtractor { 2090*004e86ffSlogin name: Vec::new(), 2091*004e86ffSlogin checksum: 0, 2092*004e86ffSlogin index: 0, 2093*004e86ffSlogin }; 2094*004e86ffSlogin } 2095*004e86ffSlogin 2096*004e86ffSlogin /// @brief 提取长目录项的名称 2097*004e86ffSlogin /// @param longname_dentry 长目录项 2098*004e86ffSlogin /// 请注意,必须倒序输入长目录项对象 2099*004e86ffSlogin fn process(&mut self, longname_dentry: LongDirEntry) -> Result<(), i32> { 2100*004e86ffSlogin let is_last: bool = longname_dentry.is_last(); 2101*004e86ffSlogin let index: u8 = longname_dentry.ord & 0x1f; 2102*004e86ffSlogin 2103*004e86ffSlogin if index == 0 { 2104*004e86ffSlogin self.name.clear(); 2105*004e86ffSlogin return Err(-(EROFS as i32)); 2106*004e86ffSlogin } 2107*004e86ffSlogin 2108*004e86ffSlogin // 如果是最后一个LongDirEntry,则初始化当前生成器 2109*004e86ffSlogin if is_last { 2110*004e86ffSlogin self.index = index; 2111*004e86ffSlogin self.checksum = longname_dentry.checksum; 2112*004e86ffSlogin self.name 2113*004e86ffSlogin .resize(index as usize * LongDirEntry::LONG_NAME_STR_LEN, 0); 2114*004e86ffSlogin } else if self.index == 0 2115*004e86ffSlogin || index != self.index - 1 2116*004e86ffSlogin || self.checksum != longname_dentry.checksum 2117*004e86ffSlogin { 2118*004e86ffSlogin // 如果当前index为0,或者index不连续,或者是校验和不同,那么认为文件系统损坏,清除生成器的名称字段 2119*004e86ffSlogin // TODO: 对文件系统的变为只读状态状况的拦截 2120*004e86ffSlogin self.name.clear(); 2121*004e86ffSlogin return Err(-(EROFS as i32)); 2122*004e86ffSlogin } else { 2123*004e86ffSlogin // 由于dentry倒序输入,因此index是每次减1的 2124*004e86ffSlogin self.index -= 1; 2125*004e86ffSlogin } 2126*004e86ffSlogin 2127*004e86ffSlogin let pos: usize = ((index - 1) as usize) * LongDirEntry::LONG_NAME_STR_LEN; 2128*004e86ffSlogin // 将当前目录项的值,拷贝到生成器的数组中 2129*004e86ffSlogin longname_dentry 2130*004e86ffSlogin .copy_name_to_slice(&mut self.name[pos..pos + LongDirEntry::LONG_NAME_STR_LEN])?; 2131*004e86ffSlogin return Ok(()); 2132*004e86ffSlogin } 2133*004e86ffSlogin 2134*004e86ffSlogin /// @brief 返回名称的长度 2135*004e86ffSlogin #[inline] 2136*004e86ffSlogin fn len(&self) -> usize { 2137*004e86ffSlogin return self.name.len(); 2138*004e86ffSlogin } 2139*004e86ffSlogin 2140*004e86ffSlogin /// @brief 返回抽取得到的名称字符串 2141*004e86ffSlogin fn to_string(&self) -> String { 2142*004e86ffSlogin let mut s = String::from_utf16_lossy(self.name.as_slice()); 2143*004e86ffSlogin // 计算字符串的长度。如果字符串中有\0,那么就截取字符串的前面部分 2144*004e86ffSlogin if let Some(len) = s.find('\u{0}') { 2145*004e86ffSlogin s.truncate(len); 2146*004e86ffSlogin } 2147*004e86ffSlogin return s; 2148*004e86ffSlogin } 2149*004e86ffSlogin 2150*004e86ffSlogin /// @brief 判断校验码是否与指定的短目录项的校验码相同 2151*004e86ffSlogin /// 2152*004e86ffSlogin /// @return bool 相同 => true 2153*004e86ffSlogin /// 不同 => false 2154*004e86ffSlogin fn validate_checksum(&self, short_dentry: &ShortDirEntry) -> bool { 2155*004e86ffSlogin return self.checksum == short_dentry.checksum(); 2156*004e86ffSlogin } 2157*004e86ffSlogin } 2158*004e86ffSlogin 2159*004e86ffSlogin /// @brief 长目录项生成器 2160*004e86ffSlogin #[derive(Debug)] 2161*004e86ffSlogin struct LongNameEntryGenerator { 2162*004e86ffSlogin name: Vec<u16>, 2163*004e86ffSlogin // 短目录项的校验和 2164*004e86ffSlogin checksum: u8, 2165*004e86ffSlogin // 当前迭代器的索引 2166*004e86ffSlogin idx: u8, 2167*004e86ffSlogin /// 最后一个目录项的索引 2168*004e86ffSlogin last_index: u8, 2169*004e86ffSlogin } 2170*004e86ffSlogin 2171*004e86ffSlogin impl LongNameEntryGenerator { 2172*004e86ffSlogin /// @brief 初始化长目录项生成器 2173*004e86ffSlogin /// 2174*004e86ffSlogin /// @param name 长文件名数组 2175*004e86ffSlogin /// @param checksum 短目录项的校验和 2176*004e86ffSlogin pub fn new(name: &str, checksum: u8) -> Self { 2177*004e86ffSlogin let mut name: Vec<u16> = name.chars().map(|c| c as u16).collect(); 2178*004e86ffSlogin 2179*004e86ffSlogin let padding_bytes: usize = (13 - (name.len() % 13)) % 13; 2180*004e86ffSlogin // 填充最后一个长目录项的文件名 2181*004e86ffSlogin for i in 0..padding_bytes { 2182*004e86ffSlogin if i == 0 { 2183*004e86ffSlogin name.push(0); 2184*004e86ffSlogin } else { 2185*004e86ffSlogin name.push(0xffff); 2186*004e86ffSlogin } 2187*004e86ffSlogin } 2188*004e86ffSlogin 2189*004e86ffSlogin // 先从最后一个长目录项开始生成 2190*004e86ffSlogin let start_index = (name.len() / 13) as u8; 2191*004e86ffSlogin return LongNameEntryGenerator { 2192*004e86ffSlogin name: name, 2193*004e86ffSlogin checksum: checksum, 2194*004e86ffSlogin idx: start_index, 2195*004e86ffSlogin last_index: start_index, 2196*004e86ffSlogin }; 2197*004e86ffSlogin } 2198*004e86ffSlogin 2199*004e86ffSlogin /// @brief 返回要生成的长目录项的总数 2200*004e86ffSlogin pub fn num_entries(&self) -> u8 { 2201*004e86ffSlogin return self.last_index + 1; 2202*004e86ffSlogin } 2203*004e86ffSlogin } 2204*004e86ffSlogin 2205*004e86ffSlogin impl Iterator for LongNameEntryGenerator { 2206*004e86ffSlogin type Item = LongDirEntry; 2207*004e86ffSlogin 2208*004e86ffSlogin fn next(&mut self) -> Option<Self::Item> { 2209*004e86ffSlogin match self.idx { 2210*004e86ffSlogin 0 => { 2211*004e86ffSlogin return None; 2212*004e86ffSlogin } 2213*004e86ffSlogin // 最后一个长目录项 2214*004e86ffSlogin n if n == self.last_index => { 2215*004e86ffSlogin // 最后一个长目录项的ord需要与0x40相或 2216*004e86ffSlogin let ord: u8 = n | 0x40; 2217*004e86ffSlogin let start_idx = ((n - 1) * 13) as usize; 2218*004e86ffSlogin self.idx -= 1; 2219*004e86ffSlogin return Some(LongDirEntry::new( 2220*004e86ffSlogin ord, 2221*004e86ffSlogin &self.name.as_slice()[start_idx..start_idx + 13], 2222*004e86ffSlogin self.checksum, 2223*004e86ffSlogin )); 2224*004e86ffSlogin } 2225*004e86ffSlogin n => { 2226*004e86ffSlogin // 其它的长目录项 2227*004e86ffSlogin let start_idx = ((n - 1) * 13) as usize; 2228*004e86ffSlogin self.idx -= 1; 2229*004e86ffSlogin return Some(LongDirEntry::new( 2230*004e86ffSlogin n, 2231*004e86ffSlogin &self.name.as_slice()[start_idx..start_idx + 13], 2232*004e86ffSlogin self.checksum, 2233*004e86ffSlogin )); 2234*004e86ffSlogin } 2235*004e86ffSlogin } 2236*004e86ffSlogin } 2237*004e86ffSlogin } 2238*004e86ffSlogin 2239*004e86ffSlogin #[derive(Debug)] 2240*004e86ffSlogin pub enum FATDirEntryOrShortName { 2241*004e86ffSlogin DirEntry(FATDirEntry), 2242*004e86ffSlogin ShortName([u8; 11]), 2243*004e86ffSlogin } 2244*004e86ffSlogin 2245*004e86ffSlogin /// @brief 对FAT目录项的迭代器(基于簇和簇内偏移量) 2246*004e86ffSlogin #[derive(Debug)] 2247*004e86ffSlogin struct FATDirEntryOffsetIter { 2248*004e86ffSlogin /// 当前迭代的偏移量(下一次迭代要返回的值) 2249*004e86ffSlogin current_offset: (Cluster, u64), 2250*004e86ffSlogin /// 截止迭代的位置(end_offset所在的位置也会被迭代器返回) 2251*004e86ffSlogin end_offset: Option<(Cluster, u64)>, 2252*004e86ffSlogin /// 属于的文件系统 2253*004e86ffSlogin fs: Arc<FATFileSystem>, 2254*004e86ffSlogin /// 当前已经迭代了多少次 2255*004e86ffSlogin index: u64, 2256*004e86ffSlogin /// 总共要迭代多少次 2257*004e86ffSlogin len: u64, 2258*004e86ffSlogin /// 如果end_offset不为None,该字段表示“是否已经到达了迭代终点” 2259*004e86ffSlogin fin: bool, 2260*004e86ffSlogin } 2261*004e86ffSlogin 2262*004e86ffSlogin impl FATDirEntryOffsetIter { 2263*004e86ffSlogin /// @brief 初始化FAT目录项的迭代器(基于簇和簇内偏移量) 2264*004e86ffSlogin /// 2265*004e86ffSlogin /// @param fs 属于的文件系统 2266*004e86ffSlogin /// @param start 起始偏移量 2267*004e86ffSlogin /// @param len 要迭代的次数 2268*004e86ffSlogin /// @param end_offset 截止迭代的位置(end_offset所在的位置也会被迭代器返回) 2269*004e86ffSlogin /// 2270*004e86ffSlogin /// @return 构建好的迭代器对象 2271*004e86ffSlogin pub fn new( 2272*004e86ffSlogin fs: Arc<FATFileSystem>, 2273*004e86ffSlogin start: (Cluster, u64), 2274*004e86ffSlogin len: u64, 2275*004e86ffSlogin end_offset: Option<(Cluster, u64)>, 2276*004e86ffSlogin ) -> Self { 2277*004e86ffSlogin return FATDirEntryOffsetIter { 2278*004e86ffSlogin current_offset: start, 2279*004e86ffSlogin end_offset, 2280*004e86ffSlogin fs, 2281*004e86ffSlogin index: 0, 2282*004e86ffSlogin len, 2283*004e86ffSlogin fin: false, 2284*004e86ffSlogin }; 2285*004e86ffSlogin } 2286*004e86ffSlogin } 2287*004e86ffSlogin 2288*004e86ffSlogin impl Iterator for FATDirEntryOffsetIter { 2289*004e86ffSlogin type Item = (Cluster, u64); 2290*004e86ffSlogin 2291*004e86ffSlogin fn next(&mut self) -> Option<Self::Item> { 2292*004e86ffSlogin if self.index == self.len || self.fin { 2293*004e86ffSlogin return None; 2294*004e86ffSlogin } 2295*004e86ffSlogin 2296*004e86ffSlogin let r: (Cluster, u64) = self.current_offset; 2297*004e86ffSlogin // 计算新的字节偏移量 2298*004e86ffSlogin let mut new_offset = r.1 + FATRawDirEntry::DIR_ENTRY_LEN; 2299*004e86ffSlogin let mut new_cluster: Cluster = r.0; 2300*004e86ffSlogin // 越过了当前簇,则获取下一个簇 2301*004e86ffSlogin if new_offset >= self.fs.bytes_per_cluster() { 2302*004e86ffSlogin new_offset %= self.fs.bytes_per_cluster(); 2303*004e86ffSlogin 2304*004e86ffSlogin match self.fs.get_fat_entry(new_cluster) { 2305*004e86ffSlogin Ok(FATEntry::Next(c)) => { 2306*004e86ffSlogin new_cluster = c; 2307*004e86ffSlogin } 2308*004e86ffSlogin // 没有下一个簇了 2309*004e86ffSlogin _ => { 2310*004e86ffSlogin self.fin = true; 2311*004e86ffSlogin } 2312*004e86ffSlogin } 2313*004e86ffSlogin } 2314*004e86ffSlogin 2315*004e86ffSlogin if let Some(off) = self.end_offset { 2316*004e86ffSlogin // 判断当前簇是否是要求停止搜索的最后一个位置 2317*004e86ffSlogin self.fin = off == self.current_offset; 2318*004e86ffSlogin } 2319*004e86ffSlogin // 更新当前迭代的偏移量 2320*004e86ffSlogin self.current_offset = (new_cluster, new_offset); 2321*004e86ffSlogin self.index += 1; 2322*004e86ffSlogin 2323*004e86ffSlogin return Some(r); 2324*004e86ffSlogin } 2325*004e86ffSlogin } 2326*004e86ffSlogin 2327*004e86ffSlogin /// @brief 根据磁盘内字节偏移量,读取磁盘,并生成一个FATRawDirEntry对象 2328*004e86ffSlogin pub fn get_raw_dir_entry( 2329*004e86ffSlogin fs: &Arc<FATFileSystem>, 2330*004e86ffSlogin in_disk_bytes_offset: u64, 2331*004e86ffSlogin ) -> Result<FATRawDirEntry, i32> { 2332*004e86ffSlogin // 块内偏移量 2333*004e86ffSlogin let blk_offset: u64 = fs.get_in_block_offset(in_disk_bytes_offset); 2334*004e86ffSlogin let lba = fs.get_lba_from_offset( 2335*004e86ffSlogin fs.bytes_to_sector(fs.get_in_partition_bytes_offset(in_disk_bytes_offset)), 2336*004e86ffSlogin ); 2337*004e86ffSlogin 2338*004e86ffSlogin // let step1 = fs.get_in_partition_bytes_offset(in_disk_bytes_offset); 2339*004e86ffSlogin // let step2 = fs.bytes_to_sector(step1); 2340*004e86ffSlogin // let lba = fs.get_lba_from_offset(step2); 2341*004e86ffSlogin // kdebug!("step1={step1}, step2={step2}, lba={lba}"); 2342*004e86ffSlogin let mut v: Vec<u8> = Vec::new(); 2343*004e86ffSlogin v.resize(1 * LBA_SIZE, 0); 2344*004e86ffSlogin 2345*004e86ffSlogin fs.partition.disk().read_at(lba, 1, &mut v)?; 2346*004e86ffSlogin 2347*004e86ffSlogin let mut cursor: VecCursor = VecCursor::new(v); 2348*004e86ffSlogin // 切换游标到对应位置 2349*004e86ffSlogin cursor.seek(SeekFrom::SeekSet(blk_offset as i64))?; 2350*004e86ffSlogin 2351*004e86ffSlogin let dir_0 = cursor.read_u8()?; 2352*004e86ffSlogin 2353*004e86ffSlogin match dir_0 { 2354*004e86ffSlogin 0x00 => { 2355*004e86ffSlogin return Ok(FATRawDirEntry::FreeRest); 2356*004e86ffSlogin } 2357*004e86ffSlogin 0xe5 => { 2358*004e86ffSlogin return Ok(FATRawDirEntry::Free); 2359*004e86ffSlogin } 2360*004e86ffSlogin _ => { 2361*004e86ffSlogin cursor.seek(SeekFrom::SeekCurrent(10))?; 2362*004e86ffSlogin let file_attr: FileAttributes = FileAttributes::new(cursor.read_u8()?); 2363*004e86ffSlogin 2364*004e86ffSlogin // 指针回到目录项的开始处 2365*004e86ffSlogin cursor.seek(SeekFrom::SeekSet(blk_offset as i64))?; 2366*004e86ffSlogin 2367*004e86ffSlogin if file_attr.contains(FileAttributes::LONG_NAME) { 2368*004e86ffSlogin // 当前目录项是一个长目录项 2369*004e86ffSlogin let mut long_dentry = LongDirEntry::default(); 2370*004e86ffSlogin 2371*004e86ffSlogin long_dentry.ord = cursor.read_u8()?; 2372*004e86ffSlogin cursor.read_u16_into(&mut long_dentry.name1)?; 2373*004e86ffSlogin long_dentry.file_attrs = FileAttributes::new(cursor.read_u8()?); 2374*004e86ffSlogin long_dentry.dirent_type = cursor.read_u8()?; 2375*004e86ffSlogin long_dentry.checksum = cursor.read_u8()?; 2376*004e86ffSlogin 2377*004e86ffSlogin cursor.read_u16_into(&mut long_dentry.name2)?; 2378*004e86ffSlogin long_dentry.first_clus_low = cursor.read_u16()?; 2379*004e86ffSlogin cursor.read_u16_into(&mut long_dentry.name3)?; 2380*004e86ffSlogin 2381*004e86ffSlogin return Ok(FATRawDirEntry::Long(long_dentry)); 2382*004e86ffSlogin } else { 2383*004e86ffSlogin // 当前目录项是一个短目录项 2384*004e86ffSlogin let mut short_dentry = ShortDirEntry::default(); 2385*004e86ffSlogin cursor.read_exact(&mut short_dentry.name)?; 2386*004e86ffSlogin 2387*004e86ffSlogin short_dentry.attributes = FileAttributes::new(cursor.read_u8()?); 2388*004e86ffSlogin 2389*004e86ffSlogin short_dentry.nt_res = cursor.read_u8()?; 2390*004e86ffSlogin short_dentry.crt_time_tenth = cursor.read_u8()?; 2391*004e86ffSlogin short_dentry.crt_time = cursor.read_u16()?; 2392*004e86ffSlogin short_dentry.crt_date = cursor.read_u16()?; 2393*004e86ffSlogin short_dentry.lst_acc_date = cursor.read_u16()?; 2394*004e86ffSlogin short_dentry.fst_clus_hi = cursor.read_u16()?; 2395*004e86ffSlogin short_dentry.wrt_time = cursor.read_u16()?; 2396*004e86ffSlogin short_dentry.wrt_date = cursor.read_u16()?; 2397*004e86ffSlogin short_dentry.fst_clus_lo = cursor.read_u16()?; 2398*004e86ffSlogin short_dentry.file_size = cursor.read_u32()?; 2399*004e86ffSlogin 2400*004e86ffSlogin return Ok(FATRawDirEntry::Short(short_dentry)); 2401*004e86ffSlogin } 2402*004e86ffSlogin } 2403*004e86ffSlogin } 2404*004e86ffSlogin } 2405