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