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