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