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