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