1 #include "fat32.h"
2 #include "fat_ent.h"
3 #include "internal.h"
4 #include <common/errno.h>
5 #include <common/kprint.h>
6 #include <common/spinlock.h>
7 #include <common/stdio.h>
8 #include <common/string.h>
9 #include <driver/disk/ahci/ahci.h>
10 #include <filesystem/MBR.h>
11 #include <mm/slab.h>
12
13 struct vfs_super_block_operations_t fat32_sb_ops;
14 struct vfs_dir_entry_operations_t fat32_dEntry_ops;
15 struct vfs_file_operations_t fat32_file_ops;
16 struct vfs_inode_operations_t fat32_inode_ops;
17 extern struct blk_gendisk ahci_gendisk0;
18
19 static unsigned int vfat_striptail_len(unsigned int len, const char *name);
20 static int vfat_find(struct vfs_index_node_t *dir, const char *name, struct fat32_slot_info *slot_info);
21 static int __fat32_search_long_short(struct vfs_index_node_t *parent_inode, const char *name, int name_len,
22 struct fat32_slot_info *sinfo);
23 static int fat32_detach_inode(struct vfs_index_node_t *inode);
24
25 /**
26 * @brief 注册指定磁盘上的指定分区的fat32文件系统
27 *
28 * @param blk_dev 块设备结构体
29 * @param part_num 磁盘分区编号
30 *
31 * @return struct vfs_super_block_t * 文件系统的超级块
32 */
fat32_register_partition(struct block_device * blk_dev,uint8_t part_num)33 struct vfs_superblock_t *fat32_register_partition(struct block_device *blk_dev, uint8_t part_num)
34 {
35 // 挂载文件系统到vfs
36 return vfs_mount_fs("/", "FAT32", blk_dev);
37 }
38
39 /**
40 * @brief 计算短目录项文件名的校验和
41 *
42 * @param name 短目录项文件名字符串(长度为11)
43 * @return uint8_t 校验和
44 */
fat32_ChkSum(uint8_t * name)45 static uint8_t fat32_ChkSum(uint8_t *name)
46 {
47 uint8_t chksum = 0;
48 for (uint8_t i = 0; i < 11; ++i)
49 {
50 chksum = ((chksum & 1) ? 0x80 : 0) + (chksum >> 1) + *name;
51 ++name;
52 }
53 return chksum;
54 }
55
__fat32_search_long_short(struct vfs_index_node_t * parent_inode,const char * name,int name_len,struct fat32_slot_info * sinfo)56 static int __fat32_search_long_short(struct vfs_index_node_t *parent_inode, const char *name, int name_len,
57 struct fat32_slot_info *sinfo)
58 {
59 struct fat32_inode_info_t *finode = (struct fat32_inode_info_t *)parent_inode->private_inode_info;
60 fat32_sb_info_t *fsbi = (fat32_sb_info_t *)parent_inode->sb->private_sb_info;
61 struct block_device *blk = parent_inode->sb->blk_device;
62
63 uint8_t *buf = kzalloc(fsbi->bytes_per_clus, 0);
64
65 // 计算父目录项的起始簇号
66 uint32_t cluster = finode->first_clus;
67
68 struct fat32_Directory_t *tmp_dEntry = NULL;
69 int cnt_long_dir = 0; // 最终结果中,长目录项的数量
70
71 while (true)
72 {
73
74 // 计算父目录项的起始LBA扇区号
75 uint64_t sector = __fat32_calculate_LBA(fsbi->first_data_sector, fsbi->sec_per_clus, cluster);
76 // kdebug("fat32_part_info[part_id].bootsector.BPB_SecPerClus=%d",fat32_part_info[part_id].bootsector.BPB_SecPerClus);
77 // kdebug("sector=%d",sector);
78
79 // 读取父目录项的起始簇数据
80 blk->bd_disk->fops->transfer(blk->bd_disk, AHCI_CMD_READ_DMA_EXT, sector, fsbi->sec_per_clus, (uint64_t)buf);
81
82 tmp_dEntry = (struct fat32_Directory_t *)buf;
83
84 // 查找每个文件的短目录项
85 for (int i = 0; i < fsbi->bytes_per_clus; i += 32, ++tmp_dEntry)
86 {
87 // 跳过长目录项
88 if (tmp_dEntry->DIR_Attr == ATTR_LONG_NAME)
89 continue;
90
91 // 跳过无效目录项、空闲目录项
92 if (tmp_dEntry->DIR_Name[0] == 0xe5 || tmp_dEntry->DIR_Name[0] == 0x00 || tmp_dEntry->DIR_Name[0] == 0x05)
93 continue;
94 // kdebug("short name [%d] %s\n 33333==[%#02x]", i / 32, tmp_dEntry->DIR_Name, tmp_dEntry->DIR_Name[3]);
95 // 找到长目录项,位于短目录项之前
96 struct fat32_LongDirectory_t *tmp_ldEntry = (struct fat32_LongDirectory_t *)tmp_dEntry - 1;
97 cnt_long_dir = 0;
98 int js = 0;
99 // 遍历每个长目录项
100 while (tmp_ldEntry->LDIR_Attr == ATTR_LONG_NAME && tmp_ldEntry->LDIR_Ord != 0xe5)
101 {
102 // 比较name1
103 for (int x = 0; x < 5; ++x)
104 {
105 if (js >= name_len && (tmp_ldEntry->LDIR_Name1[x] == 0xffff))
106 continue;
107 else if (js > name_len ||
108 tmp_ldEntry->LDIR_Name1[x] != (uint16_t)(name[js++])) // 文件名不匹配,检索下一个短目录项
109 goto continue_cmp_fail;
110 }
111
112 // 比较name2
113 for (int x = 0; x < 6; ++x)
114 {
115 if (js >= name_len && (tmp_ldEntry->LDIR_Name2[x] == 0xffff))
116 continue;
117 else if (js > name_len ||
118 tmp_ldEntry->LDIR_Name2[x] != (uint16_t)(name[js++])) // 文件名不匹配,检索下一个短目录项
119 goto continue_cmp_fail;
120 }
121
122 // 比较name3
123 for (int x = 0; x < 2; ++x)
124 {
125 if (js >= name_len && (tmp_ldEntry->LDIR_Name3[x] == 0xffff))
126 continue;
127 else if (js > name_len ||
128 tmp_ldEntry->LDIR_Name3[x] != (uint16_t)(name[js++])) // 文件名不匹配,检索下一个短目录项
129 goto continue_cmp_fail;
130 }
131
132 if (js >= name_len) // 找到需要的目录项,返回
133 {
134 // kdebug("found target long name.");
135 cnt_long_dir = tmp_dEntry - (struct fat32_Directory_t *)tmp_ldEntry;
136 goto success;
137 }
138
139 --tmp_ldEntry; // 检索下一个长目录项
140 }
141
142 // 不存在长目录项,匹配短目录项的基础名
143 js = 0;
144 for (int x = 0; x < 8; ++x)
145 {
146 // kdebug("no long name, comparing short name");
147 // kdebug("value = %#02x", tmp_dEntry->DIR_Name[x]);
148 switch (tmp_dEntry->DIR_Name[x])
149 {
150 case ' ':
151 if (!(tmp_dEntry->DIR_Attr & ATTR_DIRECTORY)) // 不是文件夹(是文件)
152 {
153 if (name[js] == '.')
154 continue;
155 else if (tmp_dEntry->DIR_Name[x] == name[js])
156 {
157 ++js;
158 break;
159 }
160 else
161 goto continue_cmp_fail;
162 }
163 else // 是文件夹
164 {
165 if (js < name_len && tmp_dEntry->DIR_Name[x] == name[js]) // 当前位正确匹配
166 {
167 ++js;
168 break; // 进行下一位的匹配
169 }
170 else if (js == name_len)
171 continue;
172 else
173 goto continue_cmp_fail;
174 }
175 break;
176
177 // 当前位是字母
178 case 'A' ... 'Z':
179 case 'a' ... 'z':
180 if (tmp_dEntry->DIR_NTRes & LOWERCASE_BASE) // 为兼容windows系统,检测DIR_NTRes字段
181 {
182 if (js < name_len && (tmp_dEntry->DIR_Name[x] + 32 == name[js]))
183 {
184 ++js;
185 break;
186 }
187 else
188 goto continue_cmp_fail;
189 }
190 else
191 {
192 if (js < name_len && tmp_dEntry->DIR_Name[x] == name[js])
193 {
194 ++js;
195 break;
196 }
197 else
198 goto continue_cmp_fail;
199 }
200 break;
201 case '0' ... '9':
202 if (js < name_len && tmp_dEntry->DIR_Name[x] == name[js])
203 {
204 ++js;
205 break;
206 }
207 else
208 goto continue_cmp_fail;
209
210 break;
211 default:
212 // ++js;
213 goto continue_cmp_fail;
214 break;
215 }
216 }
217 if (js > name_len)
218 {
219 // kdebug("js > namelen");
220 goto continue_cmp_fail;
221 }
222 // 若短目录项为文件,则匹配扩展名
223 if (!(tmp_dEntry->DIR_Attr & ATTR_DIRECTORY))
224 {
225 ++js;
226 for (int x = 8; x < 11; ++x)
227 {
228 switch (tmp_dEntry->DIR_Name[x])
229 {
230 // 当前位是字母
231 case 'A' ... 'Z':
232 case 'a' ... 'z':
233 if (tmp_dEntry->DIR_NTRes & LOWERCASE_EXT) // 为兼容windows系统,检测DIR_NTRes字段
234 {
235 if ((tmp_dEntry->DIR_Name[x] + 32 == name[js]))
236 {
237 ++js;
238 break;
239 }
240 else
241 goto continue_cmp_fail;
242 }
243 else
244 {
245 if (tmp_dEntry->DIR_Name[x] == name[js])
246 {
247 ++js;
248 break;
249 }
250 else
251 goto continue_cmp_fail;
252 }
253 break;
254 case '0' ... '9':
255 case ' ':
256 if (tmp_dEntry->DIR_Name[x] == name[js])
257 {
258 ++js;
259 break;
260 }
261 else
262 goto continue_cmp_fail;
263
264 break;
265
266 default:
267 goto continue_cmp_fail;
268 break;
269 }
270 }
271 }
272 if (js > name_len)
273 {
274 // kdebug("js > namelen");
275 goto continue_cmp_fail;
276 }
277 cnt_long_dir = 0;
278 goto success;
279 continue_cmp_fail:;
280 }
281
282 // 当前簇没有发现目标文件名,寻找下一个簇
283 cluster = fat32_read_FAT_entry(blk, fsbi, cluster);
284
285 if (cluster >= 0x0ffffff7) // 寻找完父目录的所有簇,都没有找到目标文件名
286 {
287 kfree(buf);
288 return -ENOENT;
289 }
290 }
291 if (unlikely(tmp_dEntry == NULL))
292 {
293 BUG_ON(1);
294 kfree(buf);
295 return -ENOENT;
296 }
297 success:;
298
299 // 填充sinfo
300 sinfo->buffer = buf;
301 sinfo->de = tmp_dEntry;
302 sinfo->i_pos = __fat32_calculate_LBA(fsbi->first_data_sector, fsbi->sec_per_clus, cluster);
303 sinfo->num_slots = cnt_long_dir + 1;
304 sinfo->slot_off = tmp_dEntry - (struct fat32_Directory_t *)buf;
305 // kdebug("successfully found:%s", name);
306 return 0;
307 }
308
309 /**
310 * @brief 在父目录中寻找指定的目录项
311 *
312 * @param parent_inode 父目录项的inode
313 * @param dest_dentry 搜索目标目录项
314 * @return struct vfs_dir_entry_t* 目标目录项
315 */
fat32_lookup(struct vfs_index_node_t * parent_inode,struct vfs_dir_entry_t * dest_dentry)316 struct vfs_dir_entry_t *fat32_lookup(struct vfs_index_node_t *parent_inode, struct vfs_dir_entry_t *dest_dentry)
317 {
318 int errcode = 0;
319 fat32_sb_info_t *fsbi = (fat32_sb_info_t *)parent_inode->sb->private_sb_info;
320 struct fat32_inode_info_t *finode = NULL;
321
322 struct fat32_slot_info sinfo = {0};
323 errcode = vfat_find(parent_inode, dest_dentry->name, &sinfo);
324
325 if (unlikely(errcode != 0))
326 return NULL;
327
328 find_lookup_success:; // 找到目标dentry
329 struct vfs_index_node_t *p = vfs_alloc_inode();
330
331 p->file_size = sinfo.de->DIR_FileSize;
332 // 计算文件占用的扇区数, 由于最小存储单位是簇,因此需要按照簇的大小来对齐扇区
333 p->blocks = (p->file_size + fsbi->bytes_per_clus - 1) / fsbi->bytes_per_sec;
334 p->attribute = (sinfo.de->DIR_Attr & ATTR_DIRECTORY) ? VFS_IF_DIR : VFS_IF_FILE;
335 p->sb = parent_inode->sb;
336 p->file_ops = &fat32_file_ops;
337 p->inode_ops = &fat32_inode_ops;
338
339 // 为inode的与文件系统相关的信息结构体分配空间
340 p->private_inode_info = (void *)kzalloc(sizeof(fat32_inode_info_t), 0);
341 finode = (fat32_inode_info_t *)p->private_inode_info;
342
343 finode->first_clus = ((sinfo.de->DIR_FstClusHI << 16) | sinfo.de->DIR_FstClusLO) & 0x0fffffff;
344 finode->dEntry_location_clus = __fat32_LBA_to_cluster(fsbi->first_data_sector, fsbi->sec_per_clus, sinfo.i_pos);
345 finode->dEntry_location_clus_offset = sinfo.slot_off; // 计算dentry的偏移量
346 // kdebug("finode->dEntry_location_clus=%#018lx", finode->dEntry_location_clus);
347 // kdebug("finode->dEntry_location_clus_offset=%#018lx", finode->dEntry_location_clus_offset);
348 finode->create_date = sinfo.de->DIR_CrtDate;
349 finode->create_time = sinfo.de->DIR_CrtTime;
350 finode->write_date = sinfo.de->DIR_WrtDate;
351 finode->write_time = sinfo.de->DIR_WrtTime;
352
353 // 暂时使用fat32的高4bit来标志设备文件
354 // todo: 引入devfs后删除这段代码
355 if ((sinfo.de->DIR_FstClusHI >> 12) && (p->attribute & VFS_IF_FILE))
356 p->attribute |= VFS_IF_DEVICE;
357
358 dest_dentry->dir_inode = p;
359 dest_dentry->dir_ops = &fat32_dEntry_ops;
360 list_init(&dest_dentry->child_node_list);
361 list_init(&dest_dentry->subdirs_list);
362
363 kfree(sinfo.buffer);
364 return dest_dentry;
365 }
366
367 /**
368 * @brief 创建fat32文件系统的超级块
369 *
370 * @param blk 块设备结构体
371 * @return struct vfs_superblock_t* 创建好的超级块
372 */
fat32_read_superblock(struct block_device * blk)373 struct vfs_superblock_t *fat32_read_superblock(struct block_device *blk)
374 {
375 // 读取文件系统的boot扇区
376 uint8_t buf[512] = {0};
377 blk->bd_disk->fops->transfer(blk->bd_disk, AHCI_CMD_READ_DMA_EXT, blk->bd_start_LBA, 1, (uint64_t)&buf);
378
379 // 分配超级块的空间
380 struct vfs_superblock_t *sb_ptr = (struct vfs_superblock_t *)kzalloc(sizeof(struct vfs_superblock_t), 0);
381 blk->bd_superblock = sb_ptr;
382 sb_ptr->sb_ops = &fat32_sb_ops;
383 sb_ptr->dir_ops = &fat32_dEntry_ops;
384 sb_ptr->private_sb_info = kzalloc(sizeof(fat32_sb_info_t), 0);
385 sb_ptr->blk_device = blk;
386
387 struct fat32_BootSector_t *fbs = (struct fat32_BootSector_t *)buf;
388
389 fat32_sb_info_t *fsbi = (fat32_sb_info_t *)(sb_ptr->private_sb_info);
390
391 fsbi->starting_sector = blk->bd_start_LBA;
392 fsbi->sector_count = blk->bd_sectors_num;
393 fsbi->sec_per_clus = fbs->BPB_SecPerClus;
394 fsbi->bytes_per_clus = fbs->BPB_SecPerClus * fbs->BPB_BytesPerSec;
395 fsbi->bytes_per_sec = fbs->BPB_BytesPerSec;
396 fsbi->first_data_sector = blk->bd_start_LBA + fbs->BPB_RsvdSecCnt + fbs->BPB_FATSz32 * fbs->BPB_NumFATs;
397 fsbi->FAT1_base_sector = blk->bd_start_LBA + fbs->BPB_RsvdSecCnt;
398 fsbi->FAT2_base_sector = fsbi->FAT1_base_sector + fbs->BPB_FATSz32;
399 fsbi->sec_per_FAT = fbs->BPB_FATSz32;
400 fsbi->NumFATs = fbs->BPB_NumFATs;
401 fsbi->fsinfo_sector_addr_infat = fbs->BPB_FSInfo;
402 fsbi->bootsector_bak_sector_addr_infat = fbs->BPB_BkBootSec;
403
404 printk_color(ORANGE, BLACK,
405 "FAT32 Boot Sector\n\tBPB_FSInfo:%#018lx\n\tBPB_BkBootSec:%#018lx\n\tBPB_TotSec32:%#018lx\n",
406 fbs->BPB_FSInfo, fbs->BPB_BkBootSec, fbs->BPB_TotSec32);
407
408 // fsinfo扇区的信息
409 memset(&fsbi->fsinfo, 0, sizeof(struct fat32_FSInfo_t));
410 blk->bd_disk->fops->transfer(blk->bd_disk, AHCI_CMD_READ_DMA_EXT,
411 blk->bd_start_LBA + fsbi->fsinfo_sector_addr_infat, 1, (uint64_t)&fsbi->fsinfo);
412
413 printk_color(BLUE, BLACK, "FAT32 FSInfo\n\tFSI_LeadSig:%#018lx\n\tFSI_StrucSig:%#018lx\n\tFSI_Free_Count:%#018lx\n",
414 fsbi->fsinfo.FSI_LeadSig, fsbi->fsinfo.FSI_StrucSig, fsbi->fsinfo.FSI_Free_Count);
415
416 // 初始化超级块的dir entry
417 sb_ptr->root = vfs_alloc_dentry(2);
418
419 sb_ptr->root->parent = sb_ptr->root;
420 sb_ptr->root->dir_ops = &fat32_dEntry_ops;
421 // 分配2个字节的name
422 sb_ptr->root->name[0] = '/';
423 sb_ptr->root->name_length = 1;
424
425 // 为root目录项分配index node
426 sb_ptr->root->dir_inode = vfs_alloc_inode();
427 sb_ptr->root->dir_inode->inode_ops = &fat32_inode_ops;
428 sb_ptr->root->dir_inode->file_ops = &fat32_file_ops;
429 sb_ptr->root->dir_inode->file_size = 0;
430 // 计算文件占用的扇区数, 由于最小存储单位是簇,因此需要按照簇的大小来对齐扇区
431 sb_ptr->root->dir_inode->blocks =
432 (sb_ptr->root->dir_inode->file_size + fsbi->bytes_per_clus - 1) / fsbi->bytes_per_sec;
433 sb_ptr->root->dir_inode->attribute = VFS_IF_DIR;
434 sb_ptr->root->dir_inode->sb = sb_ptr; // 反向绑定对应的超级块
435
436 // 初始化inode信息
437 sb_ptr->root->dir_inode->private_inode_info = kmalloc(sizeof(struct fat32_inode_info_t), 0);
438 memset(sb_ptr->root->dir_inode->private_inode_info, 0, sizeof(struct fat32_inode_info_t));
439 struct fat32_inode_info_t *finode = (struct fat32_inode_info_t *)sb_ptr->root->dir_inode->private_inode_info;
440
441 finode->first_clus = fbs->BPB_RootClus;
442 finode->dEntry_location_clus = 0;
443 finode->dEntry_location_clus_offset = 0;
444 finode->create_time = 0;
445 finode->create_date = 0;
446 finode->write_date = 0;
447 finode->write_time;
448
449 return sb_ptr;
450 }
451
452 /**
453 * @brief todo: 写入superblock
454 *
455 * @param sb
456 */
fat32_write_superblock(struct vfs_superblock_t * sb)457 void fat32_write_superblock(struct vfs_superblock_t *sb)
458 {
459 }
460
461 /**
462 * @brief 释放superblock的内存空间
463 *
464 * @param sb 要被释放的superblock
465 */
fat32_put_superblock(struct vfs_superblock_t * sb)466 void fat32_put_superblock(struct vfs_superblock_t *sb)
467 {
468 kfree(sb->private_sb_info);
469 kfree(sb->root->dir_inode->private_inode_info);
470 kfree(sb->root->dir_inode);
471 kfree(sb->root);
472 kfree(sb);
473 }
474
475 /**
476 * @brief 写入inode到硬盘上
477 *
478 * @param inode
479 */
fat32_write_inode(struct vfs_index_node_t * inode)480 void fat32_write_inode(struct vfs_index_node_t *inode)
481 {
482 fat32_inode_info_t *finode = inode->private_inode_info;
483
484 if (finode->dEntry_location_clus == 0)
485 {
486 kerror("FAT32 error: Attempt to write the root inode");
487 return;
488 }
489
490 fat32_sb_info_t *fsbi = (fat32_sb_info_t *)inode->sb->private_sb_info;
491
492 // 计算目标inode对应数据区的LBA地址
493 uint64_t fLBA = fsbi->first_data_sector + (finode->dEntry_location_clus - 2) * fsbi->sec_per_clus;
494
495 struct fat32_Directory_t *buf = (struct fat32_Directory_t *)kmalloc(fsbi->bytes_per_clus, 0);
496 memset(buf, 0, fsbi->bytes_per_clus);
497
498 inode->sb->blk_device->bd_disk->fops->transfer(inode->sb->blk_device->bd_disk, AHCI_CMD_READ_DMA_EXT, fLBA,
499 fsbi->sec_per_clus, (uint64_t)buf);
500 // 计算目标dEntry所在的位置
501 struct fat32_Directory_t *fdEntry = buf + finode->dEntry_location_clus_offset;
502
503 // 写入fat32文件系统的dir_entry
504 fdEntry->DIR_FileSize = inode->file_size;
505 fdEntry->DIR_FstClusLO = finode->first_clus & 0xffff;
506 fdEntry->DIR_FstClusHI = (finode->first_clus >> 16) | (fdEntry->DIR_FstClusHI & 0xf000);
507
508 // 将dir entry写回磁盘
509 inode->sb->blk_device->bd_disk->fops->transfer(inode->sb->blk_device->bd_disk, AHCI_CMD_WRITE_DMA_EXT, fLBA,
510 fsbi->sec_per_clus, (uint64_t)buf);
511 kfree(buf);
512 }
513
514 struct vfs_super_block_operations_t fat32_sb_ops = {
515 .write_superblock = fat32_write_superblock,
516 .put_superblock = fat32_put_superblock,
517 .write_inode = fat32_write_inode,
518 };
519
520 // todo: compare
fat32_compare(struct vfs_dir_entry_t * parent_dEntry,char * source_filename,char * dest_filename)521 long fat32_compare(struct vfs_dir_entry_t *parent_dEntry, char *source_filename, char *dest_filename)
522 {
523 return 0;
524 }
525 // todo: hash
fat32_hash(struct vfs_dir_entry_t * dEntry,char * filename)526 long fat32_hash(struct vfs_dir_entry_t *dEntry, char *filename)
527 {
528 return 0;
529 }
530 // todo: release
fat32_release(struct vfs_dir_entry_t * dEntry)531 long fat32_release(struct vfs_dir_entry_t *dEntry)
532 {
533 return 0;
534 }
535 // todo: iput
fat32_iput(struct vfs_dir_entry_t * dEntry,struct vfs_index_node_t * inode)536 long fat32_iput(struct vfs_dir_entry_t *dEntry, struct vfs_index_node_t *inode)
537 {
538 return 0;
539 }
540
541 /**
542 * @brief fat32文件系统对于dEntry的操作
543 *
544 */
545 struct vfs_dir_entry_operations_t fat32_dEntry_ops = {
546 .compare = fat32_compare,
547 .hash = fat32_hash,
548 .release = fat32_release,
549 .iput = fat32_iput,
550 };
551
552 // todo: open
fat32_open(struct vfs_index_node_t * inode,struct vfs_file_t * file_ptr)553 long fat32_open(struct vfs_index_node_t *inode, struct vfs_file_t *file_ptr)
554 {
555 return 0;
556 }
557
558 // todo: close
fat32_close(struct vfs_index_node_t * inode,struct vfs_file_t * file_ptr)559 long fat32_close(struct vfs_index_node_t *inode, struct vfs_file_t *file_ptr)
560 {
561 return 0;
562 }
563
564 /**
565 * @brief 从fat32文件系统读取数据
566 *
567 * @param file_ptr 文件描述符
568 * @param buf 输出缓冲区
569 * @param count 要读取的字节数
570 * @param position 文件指针位置
571 * @return long 执行成功:传输的字节数量 执行失败:错误码(小于0)
572 */
fat32_read(struct vfs_file_t * file_ptr,char * buf,int64_t count,long * position)573 long fat32_read(struct vfs_file_t *file_ptr, char *buf, int64_t count, long *position)
574 {
575
576 struct fat32_inode_info_t *finode = (struct fat32_inode_info_t *)(file_ptr->dEntry->dir_inode->private_inode_info);
577 fat32_sb_info_t *fsbi = (fat32_sb_info_t *)(file_ptr->dEntry->dir_inode->sb->private_sb_info);
578 struct block_device *blk = file_ptr->dEntry->dir_inode->sb->blk_device;
579
580 // First cluster num of the file
581 uint64_t cluster = finode->first_clus;
582 // kdebug("fsbi->bytes_per_clus=%d fsbi->sec_per_clus=%d finode->first_clus=%d cluster=%d", fsbi->bytes_per_clus,
583 // fsbi->sec_per_clus, finode->first_clus, cluster);
584
585 // kdebug("fsbi->bytes_per_clus=%d", fsbi->bytes_per_clus);
586
587 // clus offset in file
588 uint64_t clus_offset_in_file = (*position) / fsbi->bytes_per_clus;
589 // bytes offset in clus
590 uint64_t bytes_offset = (*position) % fsbi->bytes_per_clus;
591
592 if (!cluster)
593 return -EFAULT;
594
595 // find the actual cluster on disk of the specified position
596 for (int i = 0; i < clus_offset_in_file; ++i)
597 cluster = fat32_read_FAT_entry(blk, fsbi, cluster);
598
599 // 如果需要读取的数据边界大于文件大小
600 if (*position + count > file_ptr->dEntry->dir_inode->file_size)
601 count = file_ptr->dEntry->dir_inode->file_size - *position;
602
603 // 剩余还需要传输的字节数量
604 int64_t bytes_remain = count;
605
606 // alloc buffer memory space for ahci transfer
607 void *tmp_buffer = kmalloc(fsbi->bytes_per_clus, 0);
608
609 int64_t retval = 0;
610 do
611 {
612
613 memset(tmp_buffer, 0, fsbi->bytes_per_clus);
614 uint64_t sector = fsbi->first_data_sector + (cluster - 2) * fsbi->sec_per_clus;
615
616 // 读取一个簇的数据
617 int errno = blk->bd_disk->fops->transfer(blk->bd_disk, AHCI_CMD_READ_DMA_EXT, sector, fsbi->sec_per_clus,
618 (uint64_t)tmp_buffer);
619 if (errno != AHCI_SUCCESS)
620 {
621 kerror("FAT32 FS(read) error!");
622 retval = -EIO;
623 break;
624 }
625
626 int64_t step_trans_len = 0; // 当前循环传输的字节数
627 if (bytes_remain > (fsbi->bytes_per_clus - bytes_offset))
628 step_trans_len = (fsbi->bytes_per_clus - bytes_offset);
629 else
630 step_trans_len = bytes_remain;
631
632 if (((uint64_t)buf) < USER_MAX_LINEAR_ADDR)
633 copy_to_user(buf, tmp_buffer + bytes_offset, step_trans_len);
634 else
635 memcpy(buf, tmp_buffer + bytes_offset, step_trans_len);
636
637 bytes_remain -= step_trans_len;
638 buf += step_trans_len;
639 bytes_offset -= bytes_offset;
640
641 *position += step_trans_len; // 更新文件指针
642
643 cluster = fat32_read_FAT_entry(blk, fsbi, cluster);
644 } while (bytes_remain && (cluster < 0x0ffffff8) && cluster != 0);
645
646 kfree(tmp_buffer);
647
648 if (!bytes_remain)
649 retval = count;
650
651 return retval;
652 }
653
654 /**
655 * @brief 向fat32文件系统写入数据
656 *
657 * @param file_ptr 文件描述符
658 * @param buf 输入写入的字节数
659 * @param position 文件指针位置
660 * @return long 执行成功:传输的字节数量 执行失败:错误码(小于0)
661 */
fat32_write(struct vfs_file_t * file_ptr,char * buf,int64_t count,long * position)662 long fat32_write(struct vfs_file_t *file_ptr, char *buf, int64_t count, long *position)
663 {
664 struct fat32_inode_info_t *finode = (struct fat32_inode_info_t *)file_ptr->dEntry->dir_inode->private_inode_info;
665 fat32_sb_info_t *fsbi = (fat32_sb_info_t *)(file_ptr->dEntry->dir_inode->sb->private_sb_info);
666 struct block_device *blk = file_ptr->dEntry->dir_inode->sb->blk_device;
667
668 // First cluster num of the file
669 uint32_t cluster = finode->first_clus;
670 int64_t flags = 0;
671
672 // clus offset in file
673 uint64_t clus_offset_in_file = (*position) / fsbi->bytes_per_clus;
674 // bytes offset in clus
675 uint64_t bytes_offset = (*position) % fsbi->bytes_per_clus;
676
677 if (!cluster) // 起始簇号为0,说明是空文件
678 {
679 // 分配空闲簇
680 if (fat32_alloc_clusters(file_ptr->dEntry->dir_inode, &cluster, 1) != 0)
681 return -ENOSPC;
682 }
683 else
684 {
685 // 跳转到position所在的簇
686 for (uint64_t i = 0; i < clus_offset_in_file; ++i)
687 cluster = fat32_read_FAT_entry(blk, fsbi, cluster);
688 }
689 // kdebug("cluster(start)=%d", cluster);
690 // 没有可用的磁盘空间
691 if (!cluster)
692 return -ENOSPC;
693
694 int64_t bytes_remain = count;
695
696 if (count < 0) // 要写入的字节数小于0
697 return -EINVAL;
698
699 uint64_t sector;
700 int64_t retval = 0;
701
702 void *tmp_buffer = kmalloc(fsbi->bytes_per_clus, 0);
703 do
704 {
705 memset(tmp_buffer, 0, fsbi->bytes_per_clus);
706 sector = fsbi->first_data_sector + (cluster - 2) * fsbi->sec_per_clus; // 计算对应的扇区
707 if (!flags) // 当前簇已分配
708 {
709 // kdebug("read existed sec=%ld", sector);
710 // 读取一个簇的数据
711 int errno = blk->bd_disk->fops->transfer(blk->bd_disk, AHCI_CMD_READ_DMA_EXT, sector, fsbi->sec_per_clus,
712 (uint64_t)tmp_buffer);
713 if (errno != 0)
714 {
715 // kerror("FAT32 FS(write) read disk error!");
716 retval = -EIO;
717 break;
718 }
719 }
720
721 int64_t step_trans_len = 0; // 当前循环传输的字节数
722 if (bytes_remain > (fsbi->bytes_per_clus - bytes_offset))
723 step_trans_len = (fsbi->bytes_per_clus - bytes_offset);
724 else
725 step_trans_len = bytes_remain;
726
727 // kdebug("step_trans_len=%d, bytes_offset=%d", step_trans_len, bytes_offset);
728 if (((uint64_t)buf) < USER_MAX_LINEAR_ADDR)
729 copy_from_user(tmp_buffer + bytes_offset, buf, step_trans_len);
730 else
731 memcpy(tmp_buffer + bytes_offset, buf, step_trans_len);
732
733 // 写入数据到对应的簇
734 int errno = blk->bd_disk->fops->transfer(blk->bd_disk, AHCI_CMD_WRITE_DMA_EXT, sector, fsbi->sec_per_clus,
735 (uint64_t)tmp_buffer);
736 if (errno != AHCI_SUCCESS)
737 {
738 kerror("FAT32 FS(write) write disk error!");
739 retval = -EIO;
740 break;
741 }
742
743 bytes_remain -= step_trans_len;
744 buf += step_trans_len;
745 bytes_offset -= bytes_offset;
746
747 *position += step_trans_len; // 更新文件指针
748 // kdebug("step_trans_len=%d", step_trans_len);
749
750 int next_clus = 0;
751 if (bytes_remain)
752 next_clus = fat32_read_FAT_entry(blk, fsbi, cluster);
753 else
754 break;
755 if (next_clus >= 0x0ffffff8) // 已经到达了最后一个簇,需要分配新簇
756 {
757 if (fat32_alloc_clusters(file_ptr->dEntry->dir_inode, &next_clus, 1) != 0)
758 {
759 // 没有空闲簇
760 kfree(tmp_buffer);
761 return -ENOSPC;
762 }
763
764 cluster = next_clus; // 切换当前簇
765 flags = 1; // 标记当前簇是新分配的簇
766 }
767
768 } while (bytes_remain);
769
770 // 文件大小有增长
771 if (*position > (file_ptr->dEntry->dir_inode->file_size))
772 {
773 file_ptr->dEntry->dir_inode->file_size = *position;
774 file_ptr->dEntry->dir_inode->sb->sb_ops->write_inode(file_ptr->dEntry->dir_inode);
775 // kdebug("new file size=%ld", *position);
776 }
777
778 kfree(tmp_buffer);
779 if (!bytes_remain)
780 retval = count;
781 // kdebug("retval=%lld", retval);
782 return retval;
783 }
784
785 /**
786 * @brief 调整文件的当前访问位置
787 *
788 * @param file_ptr vfs文件指针
789 * @param offset 调整的偏移量
790 * @param whence 调整方法
791 * @return long 更新后的指针位置
792 */
fat32_lseek(struct vfs_file_t * file_ptr,long offset,long whence)793 long fat32_lseek(struct vfs_file_t *file_ptr, long offset, long whence)
794 {
795 struct vfs_index_node_t *inode = file_ptr->dEntry->dir_inode;
796
797 long pos = 0;
798 switch (whence)
799 {
800 case SEEK_SET: // 相对于文件头
801 pos = offset;
802 break;
803 case SEEK_CUR: // 相对于当前位置
804 pos = file_ptr->position + offset;
805 break;
806 case SEEK_END: // 相对于文件末尾
807 pos = file_ptr->dEntry->dir_inode->file_size + offset;
808 break;
809
810 default:
811 return -EINVAL;
812 break;
813 }
814
815 if (pos < 0 || pos > file_ptr->dEntry->dir_inode->file_size)
816 return -EOVERFLOW;
817 file_ptr->position = pos;
818
819 // kdebug("fat32 lseek -> position=%d", file_ptr->position);
820 return pos;
821 }
822 // todo: ioctl
fat32_ioctl(struct vfs_index_node_t * inode,struct vfs_file_t * file_ptr,uint64_t cmd,uint64_t arg)823 long fat32_ioctl(struct vfs_index_node_t *inode, struct vfs_file_t *file_ptr, uint64_t cmd, uint64_t arg)
824 {
825 return 0;
826 }
827
828 /**
829 * @brief fat32文件系统,关于文件的操作
830 *
831 */
832 struct vfs_file_operations_t fat32_file_ops = {
833 .open = fat32_open,
834 .close = fat32_close,
835 .read = fat32_read,
836 .write = fat32_write,
837 .lseek = fat32_lseek,
838 .ioctl = fat32_ioctl,
839 .readdir = fat32_readdir,
840 };
841
842 /**
843 * @brief 创建新的文件
844 * @param parent_inode 父目录的inode结构体
845 * @param dest_dEntry 新文件的dentry
846 * @param mode 创建模式
847 */
fat32_create(struct vfs_index_node_t * parent_inode,struct vfs_dir_entry_t * dest_dEntry,int mode)848 long fat32_create(struct vfs_index_node_t *parent_inode, struct vfs_dir_entry_t *dest_dEntry, int mode)
849 {
850 // 文件系统超级块信息
851 fat32_sb_info_t *fsbi = (fat32_sb_info_t *)parent_inode->sb->private_sb_info;
852 // 父目录项的inode的私有信息
853 struct fat32_inode_info_t *parent_inode_info = (struct fat32_inode_info_t *)parent_inode->private_inode_info;
854
855 int64_t retval = 0;
856
857 // ======== 检验名称的合法性
858 retval = fat32_check_name_available(dest_dEntry->name, dest_dEntry->name_length, 0);
859
860 if (retval != 0)
861 return retval;
862
863 if (dest_dEntry->dir_inode != NULL)
864 return -EEXIST;
865
866 struct vfs_index_node_t *inode = vfs_alloc_inode();
867 dest_dEntry->dir_inode = inode;
868 dest_dEntry->dir_ops = &fat32_dEntry_ops;
869
870 struct fat32_inode_info_t *finode = (struct fat32_inode_info_t *)kzalloc(sizeof(struct fat32_inode_info_t), 0);
871 inode->attribute = VFS_IF_FILE;
872 inode->file_ops = &fat32_file_ops;
873 inode->file_size = 0;
874 inode->sb = parent_inode->sb;
875 inode->inode_ops = &fat32_inode_ops;
876 inode->private_inode_info = (void *)finode;
877 inode->blocks = fsbi->sec_per_clus;
878
879 struct block_device *blk = inode->sb->blk_device;
880
881 // 计算总共需要多少个目录项
882 uint32_t cnt_longname = (dest_dEntry->name_length + 25) / 26;
883 // 默认都是创建长目录项来存储
884 if (cnt_longname == 0)
885 cnt_longname = 1;
886
887 // 空闲dentry所在的扇区号
888 uint32_t tmp_dentry_sector = 0;
889 // 空闲dentry所在的缓冲区的基地址
890 uint64_t tmp_dentry_clus_buf_addr = 0;
891 uint64_t tmp_parent_dentry_clus = 0;
892 // 寻找空闲目录项
893 struct fat32_Directory_t *empty_fat32_dentry = fat32_find_empty_dentry(
894 parent_inode, cnt_longname + 1, 0, &tmp_dentry_sector, &tmp_parent_dentry_clus, &tmp_dentry_clus_buf_addr);
895 // kdebug("found empty dentry, cnt_longname=%ld", cnt_longname);
896
897 finode->first_clus = 0;
898 finode->dEntry_location_clus = tmp_parent_dentry_clus;
899 finode->dEntry_location_clus_offset = empty_fat32_dentry - (struct fat32_Directory_t *)tmp_dentry_clus_buf_addr;
900
901 // ====== 为新的文件分配一个簇 =======
902 uint32_t new_dir_clus;
903 if (fat32_alloc_clusters(inode, &new_dir_clus, 1) != 0)
904 {
905 retval = -ENOSPC;
906 goto fail;
907 }
908 // kdebug("new dir clus=%ld", new_dir_clus);
909 // kdebug("dest_dEntry->name=%s", dest_dEntry->name);
910
911 // ====== 填写短目录项
912 fat32_fill_shortname(dest_dEntry, empty_fat32_dentry, new_dir_clus);
913 // kdebug("dest_dEntry->name=%s",dest_dEntry->name);
914
915 // 计算校验和
916 uint8_t short_dentry_ChkSum = fat32_ChkSum(empty_fat32_dentry->DIR_Name);
917
918 // kdebug("dest_dEntry->name=%s", dest_dEntry->name);
919 // ======== 填写长目录项
920 fat32_fill_longname(dest_dEntry, (struct fat32_LongDirectory_t *)(empty_fat32_dentry - 1), short_dentry_ChkSum,
921 cnt_longname);
922
923 // ====== 将目录项写回磁盘
924 // kdebug("tmp_dentry_sector=%ld", tmp_dentry_sector);
925 blk->bd_disk->fops->transfer(blk->bd_disk, AHCI_CMD_WRITE_DMA_EXT, tmp_dentry_sector, fsbi->sec_per_clus,
926 tmp_dentry_clus_buf_addr);
927
928 // 注意:parent字段需要在调用函数的地方进行设置
929
930 // 释放在find empty dentry中动态申请的缓冲区
931 kfree((void *)tmp_dentry_clus_buf_addr);
932 return 0;
933 fail:;
934 // 释放在find empty dentry中动态申请的缓冲区
935 kfree((void *)tmp_dentry_clus_buf_addr);
936 dest_dEntry->dir_inode = NULL;
937 dest_dEntry->dir_ops = NULL;
938 kfree(finode);
939 kfree(inode);
940 return retval;
941 }
942
943 /**
944 * @brief 创建文件夹
945 * @param inode 父目录的inode
946 * @param dEntry 新的文件夹的dentry
947 * @param mode 创建文件夹的mode
948 * @return long 错误码
949 */
fat32_mkdir(struct vfs_index_node_t * parent_inode,struct vfs_dir_entry_t * dEntry,int mode)950 int64_t fat32_mkdir(struct vfs_index_node_t *parent_inode, struct vfs_dir_entry_t *dEntry, int mode)
951 {
952 int64_t retval = 0;
953
954 // 文件系统超级块信息
955 fat32_sb_info_t *fsbi = (fat32_sb_info_t *)parent_inode->sb->private_sb_info;
956 // 父目录项的inode私有信息
957 struct fat32_inode_info_t *parent_inode_info = (struct fat32_inode_info_t *)parent_inode->private_inode_info;
958 // ======== 检验名称的合法性
959 retval = fat32_check_name_available(dEntry->name, dEntry->name_length, 0);
960 if (retval != 0)
961 return retval;
962 // ====== 找一块连续的区域放置新的目录项 =====
963
964 // 计算总共需要多少个目录项
965 uint32_t cnt_longname = (dEntry->name_length + 25) / 26;
966 // 默认都是创建长目录项来存储
967 if (cnt_longname == 0)
968 cnt_longname = 1;
969
970 // 空闲dentry所在的扇区号
971 uint32_t tmp_dentry_sector = 0;
972 // 空闲dentry所在的缓冲区的基地址
973 uint64_t tmp_dentry_clus_buf_addr = 0;
974 uint64_t tmp_parent_dentry_clus = 0;
975 // 寻找空闲目录项
976 struct fat32_Directory_t *empty_fat32_dentry = fat32_find_empty_dentry(
977 parent_inode, cnt_longname + 1, 0, &tmp_dentry_sector, &tmp_parent_dentry_clus, &tmp_dentry_clus_buf_addr);
978
979 // ====== 初始化inode =======
980 struct vfs_index_node_t *inode = vfs_alloc_inode();
981 inode->attribute = VFS_IF_DIR;
982 inode->blocks = fsbi->sec_per_clus;
983 inode->file_ops = &fat32_file_ops;
984 inode->file_size = 0;
985 inode->inode_ops = &fat32_inode_ops;
986 inode->sb = parent_inode->sb;
987
988 struct block_device *blk = inode->sb->blk_device;
989
990 // ===== 初始化inode的文件系统私有信息 ====
991
992 inode->private_inode_info = (fat32_inode_info_t *)kmalloc(sizeof(fat32_inode_info_t), 0);
993 memset(inode->private_inode_info, 0, sizeof(fat32_inode_info_t));
994 fat32_inode_info_t *p = (fat32_inode_info_t *)inode->private_inode_info;
995 p->first_clus = 0;
996 p->dEntry_location_clus = tmp_parent_dentry_clus;
997 p->dEntry_location_clus_offset = empty_fat32_dentry - (struct fat32_Directory_t *)tmp_dentry_clus_buf_addr;
998 // kdebug(" p->dEntry_location_clus_offset=%d", p->dEntry_location_clus_offset);
999 // todo: 填写完全fat32_inode_info的信息
1000
1001 // 初始化dentry信息
1002 dEntry->dir_ops = &fat32_dEntry_ops;
1003 dEntry->dir_inode = inode;
1004
1005 // ====== 为新的文件夹分配一个簇 =======
1006 uint32_t new_dir_clus;
1007 if (fat32_alloc_clusters(inode, &new_dir_clus, 1) != 0)
1008 {
1009 retval = -ENOSPC;
1010 goto fail;
1011 }
1012
1013 // kdebug("new dir clus=%ld", new_dir_clus);
1014
1015 // ====== 填写短目录项
1016 fat32_fill_shortname(dEntry, empty_fat32_dentry, new_dir_clus);
1017
1018 // 计算校验和
1019 uint8_t short_dentry_ChkSum = fat32_ChkSum(empty_fat32_dentry->DIR_Name);
1020
1021 // ======== 填写长目录项
1022 fat32_fill_longname(dEntry, (struct fat32_LongDirectory_t *)(empty_fat32_dentry - 1), short_dentry_ChkSum,
1023 cnt_longname);
1024
1025 // ====== 将目录项写回磁盘
1026 // kdebug("tmp_dentry_sector=%ld", tmp_dentry_sector);
1027 blk->bd_disk->fops->transfer(blk->bd_disk, AHCI_CMD_WRITE_DMA_EXT, tmp_dentry_sector, fsbi->sec_per_clus,
1028 tmp_dentry_clus_buf_addr);
1029 // ====== 初始化新的文件夹的目录项 =====
1030 {
1031 // kdebug("to create dot and dot dot.");
1032 void *buf = kmalloc(fsbi->bytes_per_clus, 0);
1033 struct fat32_Directory_t *new_dir_dentries = (struct fat32_Directory_t *)buf;
1034 memset((void *)new_dir_dentries, 0, fsbi->bytes_per_clus);
1035
1036 // 新增 . 目录项
1037 new_dir_dentries->DIR_Attr = ATTR_DIRECTORY;
1038 new_dir_dentries->DIR_FileSize = 0;
1039 new_dir_dentries->DIR_Name[0] = '.';
1040 for (int i = 1; i < 11; ++i)
1041 new_dir_dentries->DIR_Name[i] = 0x20;
1042
1043 new_dir_dentries->DIR_FstClusHI = empty_fat32_dentry->DIR_FstClusHI;
1044 new_dir_dentries->DIR_FstClusLO = empty_fat32_dentry->DIR_FstClusLO;
1045
1046 // 新增 .. 目录项
1047 ++new_dir_dentries;
1048 new_dir_dentries->DIR_Attr = ATTR_DIRECTORY;
1049 new_dir_dentries->DIR_FileSize = 0;
1050 new_dir_dentries->DIR_Name[0] = '.';
1051 new_dir_dentries->DIR_Name[1] = '.';
1052 for (int i = 2; i < 11; ++i)
1053 new_dir_dentries->DIR_Name[i] = 0x20;
1054 new_dir_dentries->DIR_FstClusHI = (unsigned short)(parent_inode_info->first_clus >> 16) & 0x0fff;
1055 new_dir_dentries->DIR_FstClusLO = (unsigned short)(parent_inode_info->first_clus) & 0xffff;
1056
1057 // 写入磁盘
1058
1059 uint64_t sector = fsbi->first_data_sector + (new_dir_clus - 2) * fsbi->sec_per_clus;
1060 // kdebug("add dot and dot dot: sector=%ld", sector);
1061 blk->bd_disk->fops->transfer(blk->bd_disk, AHCI_CMD_WRITE_DMA_EXT, sector, fsbi->sec_per_clus, (uint64_t)buf);
1062 }
1063
1064 // 注意:parent字段需要在调用函数的地方进行设置
1065 // 注意:需要将当前dentry加入父目录的subdirs_list
1066
1067 // 释放在find empty dentry中动态申请的缓冲区
1068 kfree((void *)tmp_dentry_clus_buf_addr);
1069
1070 return 0;
1071 fail:;
1072 // 释放在find empty dentry中动态申请的缓冲区
1073 kfree((void *)tmp_dentry_clus_buf_addr);
1074 return retval;
1075 }
1076
1077 // todo: rmdir
fat32_rmdir(struct vfs_index_node_t * inode,struct vfs_dir_entry_t * dEntry)1078 int64_t fat32_rmdir(struct vfs_index_node_t *inode, struct vfs_dir_entry_t *dEntry)
1079 {
1080 return 0;
1081 }
1082
1083 // todo: rename
fat32_rename(struct vfs_index_node_t * old_inode,struct vfs_dir_entry_t * old_dEntry,struct vfs_index_node_t * new_inode,struct vfs_dir_entry_t * new_dEntry)1084 int64_t fat32_rename(struct vfs_index_node_t *old_inode, struct vfs_dir_entry_t *old_dEntry,
1085 struct vfs_index_node_t *new_inode, struct vfs_dir_entry_t *new_dEntry)
1086 {
1087 return 0;
1088 }
1089
1090 // todo: getAttr
fat32_getAttr(struct vfs_dir_entry_t * dEntry,uint64_t * attr)1091 int64_t fat32_getAttr(struct vfs_dir_entry_t *dEntry, uint64_t *attr)
1092 {
1093 return 0;
1094 }
1095
1096 // todo: setAttr
fat32_setAttr(struct vfs_dir_entry_t * dEntry,uint64_t * attr)1097 int64_t fat32_setAttr(struct vfs_dir_entry_t *dEntry, uint64_t *attr)
1098 {
1099 return 0;
1100 }
1101
1102 /**
1103 * @brief 从fat32中卸载inode
1104 *
1105 * @param inode 要被卸载的inode
1106 * @return int 错误码
1107 */
fat32_detach_inode(struct vfs_index_node_t * inode)1108 static int fat32_detach_inode(struct vfs_index_node_t *inode)
1109 {
1110 // todo: 当引入哈希表管理inode之后,这个函数负责将inode从哈希表中删除
1111 // 参考Linux的fat_detach
1112 return 0;
1113 }
1114
1115 /**
1116 * @brief 取消inode和dentry之间的链接关系(删除文件)
1117 *
1118 * @param inode 要被取消关联关系的目录项的【父目录项】
1119 * @param dentry 要被取消关联关系的子目录项
1120 */
fat32_unlink(struct vfs_index_node_t * dir,struct vfs_dir_entry_t * dentry)1121 int64_t fat32_unlink(struct vfs_index_node_t *dir, struct vfs_dir_entry_t *dentry)
1122 {
1123 int retval = 0;
1124 struct vfs_superblock_t *sb = dir->sb;
1125 struct vfs_index_node_t *inode_to_remove = dentry->dir_inode;
1126 fat32_sb_info_t *fsbi = (fat32_sb_info_t *)sb->private_sb_info;
1127 struct fat32_slot_info sinfo = {0};
1128 // todo: 对fat32的超级块加锁
1129
1130 retval = vfat_find(dir, dentry->name, &sinfo);
1131
1132 if (unlikely(retval != 0))
1133 goto out;
1134
1135 // 从fat表删除目录项
1136 retval = fat32_remove_entries(dir, &sinfo);
1137 if (unlikely(retval != 0))
1138 goto out;
1139 retval = fat32_detach_inode(dentry->dir_inode);
1140 if (unlikely(retval != 0))
1141 goto out;
1142 out:;
1143 if (sinfo.buffer != NULL)
1144 kfree(sinfo.buffer);
1145 // todo: 对fat32的超级块放锁
1146 return retval;
1147 }
1148
1149 /**
1150 * @brief 读取文件夹(在指定目录中找出有效目录项)
1151 *
1152 * @param file_ptr 文件结构体指针
1153 * @param dirent 返回的dirent
1154 * @param filler 填充dirent的函数
1155 * @return uint64_t dirent的总大小
1156 */
fat32_readdir(struct vfs_file_t * file_ptr,void * dirent,vfs_filldir_t filler)1157 int64_t fat32_readdir(struct vfs_file_t *file_ptr, void *dirent, vfs_filldir_t filler)
1158 {
1159 struct fat32_inode_info_t *finode = (struct fat32_inode_info_t *)file_ptr->dEntry->dir_inode->private_inode_info;
1160 fat32_sb_info_t *fsbi = (fat32_sb_info_t *)file_ptr->dEntry->dir_inode->sb->private_sb_info;
1161 struct block_device *blk = file_ptr->dEntry->dir_inode->sb->blk_device;
1162
1163 unsigned char *buf = (unsigned char *)kzalloc(fsbi->bytes_per_clus, 0);
1164 uint32_t cluster = finode->first_clus;
1165
1166 // 当前文件指针所在位置的簇号(文件内偏移量)
1167 int clus_num = file_ptr->position / fsbi->bytes_per_clus;
1168
1169 // 循环读取fat entry,直到读取到文件当前位置的所在簇号
1170 for (int i = 0; i < clus_num; ++i)
1171 {
1172 cluster = fat32_read_FAT_entry(blk, fsbi, cluster);
1173 if (cluster > 0x0ffffff7) // 文件结尾
1174 {
1175 kerror("file position out of range! (cluster not exists)");
1176 return NULL;
1177 }
1178 }
1179
1180 uint64_t dentry_type = 0; // 传递给filler的dentry类型数据
1181
1182 char *dir_name = NULL;
1183 int name_len = 0;
1184 // ==== 此时已经将文件夹的目录项起始簇的簇号读取到cluster变量中 ===
1185 while (cluster <= 0x0ffffff7) // cluster在循环末尾更新(如果当前簇已经没有短目录项的话)
1186 {
1187 // 计算文件夹当前位置所在簇的起始扇区号
1188 uint64_t sector = fsbi->first_data_sector + (cluster - 2) * fsbi->sec_per_clus;
1189 // 读取文件夹目录项当前位置起始扇区的数据
1190
1191 if (AHCI_SUCCESS != blk->bd_disk->fops->transfer(blk->bd_disk, AHCI_CMD_READ_DMA_EXT, sector,
1192 fsbi->sec_per_clus, (uint64_t)buf))
1193 {
1194 // 读取失败
1195 kerror("Failed to read the file's first sector.");
1196 kfree(buf);
1197 return NULL;
1198 }
1199
1200 struct fat32_Directory_t *dentry = NULL;
1201 struct fat32_LongDirectory_t *long_dentry = NULL;
1202
1203 // 找到当前短目录项
1204 dentry = (struct fat32_Directory_t *)(buf + file_ptr->position % fsbi->bytes_per_clus);
1205
1206 name_len = 0;
1207 // 逐个查找短目录项
1208 for (int i = file_ptr->position % fsbi->bytes_per_clus; i < fsbi->bytes_per_clus;
1209 i += 32, file_ptr->position += 32, ++dentry)
1210 {
1211 // 若是长目录项则跳过
1212 if (dentry->DIR_Attr == ATTR_LONG_NAME)
1213 continue;
1214 // 跳过无效表项、空闲表项
1215 if (dentry->DIR_Name[0] == 0xe5 || dentry->DIR_Name[0] == 0x00 || dentry->DIR_Name[0] == 0x05)
1216 continue;
1217
1218 // 找到短目录项
1219 // 该短目录项对应的第一个长目录项
1220 long_dentry = (struct fat32_LongDirectory_t *)(dentry - 1);
1221
1222 // 如果长目录项有效,则读取长目录项
1223 if (long_dentry->LDIR_Attr == ATTR_LONG_NAME && long_dentry->LDIR_Ord != 0xe5 &&
1224 long_dentry->LDIR_Ord != 0x00 && long_dentry->LDIR_Ord != 0x05)
1225 {
1226 int count_long_dentry = 0;
1227 // 统计长目录项的个数
1228 while (long_dentry->LDIR_Attr == ATTR_LONG_NAME && long_dentry->LDIR_Ord != 0xe5 &&
1229 long_dentry->LDIR_Ord != 0x00 && long_dentry->LDIR_Ord != 0x05)
1230 {
1231 ++count_long_dentry;
1232 if (long_dentry->LDIR_Ord & 0x40) // 最后一个长目录项
1233 break;
1234 --long_dentry;
1235 }
1236 // 为目录名分配空间
1237 dir_name = (char *)kmalloc(count_long_dentry * 26 + 1, 0);
1238 memset(dir_name, 0, count_long_dentry * 26 + 1);
1239
1240 // 重新将长目录项指针指向第一个长目录项
1241 long_dentry = (struct fat32_LongDirectory_t *)(dentry - 1);
1242 name_len = 0;
1243 // 逐个存储文件名
1244 for (int j = 0; j < count_long_dentry; ++j, --long_dentry)
1245 {
1246 // 存储name1
1247 for (int k = 0; k < 5; ++k)
1248 {
1249 if (long_dentry->LDIR_Name1[k] != 0xffff && long_dentry->LDIR_Name1[k] != 0x0000)
1250 dir_name[name_len++] = (char)long_dentry->LDIR_Name1[k];
1251 }
1252
1253 // 存储name2
1254 for (int k = 0; k < 6; ++k)
1255 {
1256 if (long_dentry->LDIR_Name2[k] != 0xffff && long_dentry->LDIR_Name2[k] != 0x0000)
1257 dir_name[name_len++] = (char)long_dentry->LDIR_Name2[k];
1258 }
1259
1260 // 存储name3
1261 for (int k = 0; k < 2; ++k)
1262 {
1263 if (long_dentry->LDIR_Name3[k] != 0xffff && long_dentry->LDIR_Name3[k] != 0x0000)
1264 dir_name[name_len++] = (char)long_dentry->LDIR_Name3[k];
1265 }
1266 }
1267
1268 // 读取目录项成功,返回
1269 dentry_type = dentry->DIR_Attr;
1270 goto find_dir_success;
1271 }
1272 else // 不存在长目录项
1273 {
1274 dir_name = (char *)kmalloc(15, 0);
1275 memset(dir_name, 0, 15);
1276
1277 name_len = 0;
1278 int total_len = 0;
1279 // 读取基础名
1280 for (int j = 0; j < 8; ++j, ++total_len)
1281 {
1282 if (dentry->DIR_Name[j] == ' ')
1283 break;
1284
1285 if (dentry->DIR_NTRes & LOWERCASE_BASE) // 如果标记了文件名小写,则转换为小写字符
1286 dir_name[name_len++] = dentry->DIR_Name[j] + 32;
1287 else
1288 dir_name[name_len++] = dentry->DIR_Name[j];
1289 }
1290
1291 // 如果当前短目录项为文件夹,则直接返回,不需要读取扩展名
1292 if (dentry->DIR_Attr & ATTR_DIRECTORY)
1293 {
1294 dentry_type = dentry->DIR_Attr;
1295 goto find_dir_success;
1296 }
1297
1298 // 是文件,增加 .
1299 dir_name[name_len++] = '.';
1300
1301 // 读取扩展名
1302 // 读取基础名
1303 for (int j = 0; j < 3; ++j, ++total_len)
1304 {
1305 if (dentry->DIR_Name[j] == ' ')
1306 break;
1307
1308 if (dentry->DIR_NTRes & LOWERCASE_BASE) // 如果标记了文件名小写,则转换为小写字符
1309 dir_name[name_len++] = dentry->DIR_Name[j] + 32;
1310 else
1311 dir_name[name_len++] = dentry->DIR_Name[j];
1312 }
1313
1314 if (total_len == 8) // 没有扩展名
1315 dir_name[--name_len] = '\0';
1316
1317 dentry_type = dentry->DIR_Attr;
1318 goto find_dir_success;
1319 }
1320 }
1321
1322 // 当前簇不存在目录项
1323 cluster = fat32_read_FAT_entry(blk, fsbi, cluster);
1324 }
1325
1326 kfree(buf);
1327 // 在上面的循环中读取到目录项结尾了,仍没有找到
1328 return NULL;
1329
1330 find_dir_success:;
1331 // 将文件夹位置坐标加32(即指向下一个目录项)
1332 file_ptr->position += 32;
1333 // todo: 计算ino_t
1334 if (dentry_type & ATTR_DIRECTORY)
1335 dentry_type = VFS_IF_DIR;
1336 else
1337 dentry_type = VFS_IF_FILE;
1338
1339 return filler(dirent, 0, dir_name, name_len, dentry_type, 0);
1340 }
1341
1342 struct vfs_inode_operations_t fat32_inode_ops = {
1343 .create = fat32_create,
1344 .mkdir = fat32_mkdir,
1345 .rmdir = fat32_rmdir,
1346 .lookup = fat32_lookup,
1347 .rename = fat32_rename,
1348 .getAttr = fat32_getAttr,
1349 .setAttr = fat32_setAttr,
1350 .unlink = fat32_unlink,
1351
1352 };
1353
1354 /**
1355 * @brief 给定字符串长度,计算去除字符串尾部的'.'后,剩余部分的长度
1356 *
1357 * @param len 字符串长度(不包括\0)
1358 * @param name 名称字符串
1359 * @return unsigned int 去除'.'后的
1360 */
vfat_striptail_len(unsigned int len,const char * name)1361 static unsigned int vfat_striptail_len(unsigned int len, const char *name)
1362 {
1363 while (len && name[len - 1] == '.')
1364 --len;
1365 return len;
1366 }
1367
1368 /**
1369 * @brief 在指定inode的长目录项中搜索目标子目录项
1370 *
1371 * @param dir 父目录项inode
1372 * @param name 要查找的子目录项的名称
1373 * @param len 子目录项名称长度
1374 * @param slot_info 返回的对应的子目录项的短目录项。
1375 * @return int 错误码
1376 */
fat_search_long(struct vfs_index_node_t * dir,const char * name,int len,struct fat32_slot_info * slot_info)1377 static int fat_search_long(struct vfs_index_node_t *dir, const char *name, int len, struct fat32_slot_info *slot_info)
1378 {
1379 int retval = 0;
1380 retval = __fat32_search_long_short(dir, name, len, slot_info);
1381 return retval;
1382 }
1383 /**
1384 * @brief 在fat32中,根据父inode,寻找给定名称的子inode
1385 *
1386 * @param dir 父目录项的inode
1387 * @param name 子目录项名称
1388 * @param slot_info 找到的slot的信息
1389 * @return int 错误码
1390 */
vfat_find(struct vfs_index_node_t * dir,const char * name,struct fat32_slot_info * slot_info)1391 static int vfat_find(struct vfs_index_node_t *dir, const char *name, struct fat32_slot_info *slot_info)
1392 {
1393 uint32_t len = vfat_striptail_len(strnlen(name, PAGE_4K_SIZE - 1), name);
1394
1395 if (len == 0)
1396 return -ENOENT;
1397
1398 return fat_search_long(dir, name, len, slot_info);
1399 }
1400
1401 struct vfs_filesystem_type_t fat32_fs_type = {
1402 .name = "FAT32",
1403 .fs_flags = 0,
1404 .read_superblock = fat32_read_superblock,
1405 .next = NULL,
1406 };
fat32_init()1407 void fat32_init()
1408 {
1409
1410 kinfo("Initializing FAT32...");
1411
1412 // 在VFS中注册fat32文件系统
1413 vfs_register_filesystem(&fat32_fs_type);
1414
1415 // 挂载根文件系统
1416 fat32_register_partition(ahci_gendisk0.partition + 0, 0);
1417 kinfo("FAT32 initialized.");
1418 }