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