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