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