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