xref: /DragonOS/kernel/src/filesystem/fat/entry.rs (revision 7c28051e8c601312d3d0fd7bcb71bc71450d10c0)
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