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