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