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