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