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