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