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