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