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