CoolPotOS/fs/fat.c
2024-05-18 23:44:25 +08:00

1303 lines
47 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "../include/fat.h"
#include "../include/vdisk.h"
#include "../include/memory.h"
#include "../include/vfs.h"
#include "../include/printf.h"
#include "../include/cmos.h"
#define get_dm(vfs) ((fat_cache *)(vfs->cache))->dm
#define get_now_dir(vfs) ((fat_cache *)(vfs->cache))->dir
#define get_clustno(high, low) (high << 16) | (low & 0xffff)
#define clustno_end(type) 0xfffffff & ((((1 << (type - 1)) - 1) << 1) + 1)
static inline int get_fat_date(unsigned short year, unsigned short month,
unsigned short day) {
year -= 1980;
unsigned short date = 0;
date |= (year & 0x7f) << 9;
date |= (month & 0x0f) << 5;
date |= (day & 0x1f);
return date;
}
static inline int get_fat_time(unsigned short hour, unsigned short minute) {
unsigned short time = 0;
time |= (hour & 0x1f) << 11;
time |= (minute & 0x3f) << 5;
return time;
}
void read_fat(unsigned char *img, int *fat, unsigned char *ff, int max,
int type) {
if (type == 12) {
for (int i = 0, j = 0; i < max; i += 2) {
fat[i + 0] = (img[j + 0] | img[j + 1] << 8) & 0xfff;
fat[i + 1] = (img[j + 1] >> 4 | img[j + 2] << 4) & 0xfff;
j += 3;
}
// 保留簇
ff[0] = true;
ff[1] = true;
for (int i = 1; i < max; i++) {
if (fat[i] > 0 && fat[i] < 0xff0) {
ff[fat[i]] = true;
} else if (fat[i] >= 0xff0 && fat[i] <= 0xfff) {
ff[i + 1] = true;
}
}
} else if (type == 16) {
unsigned short *p = (unsigned short *)img;
for (int i = 0; i != max; i++) {
fat[i] = p[i];
}
ff[0] = true;
ff[1] = true;
for (int i = 1; i < max; i++) {
if (fat[i] > 0 && fat[i] < 0xfff0) {
ff[fat[i]] = true;
} else if (fat[i] >= 0xfff0 && fat[i] <= 0xffff) {
ff[i + 1] = true;
}
}
} else if (type == 32) {
unsigned int *p = (unsigned int *)img;
for (int i = 0; i != max; i++) {
fat[i] = p[i];
}
ff[0] = true;
ff[1] = true;
for (int i = 1; i < max; i++) {
if (fat[i] > 0 && fat[i] < 0xffffff0) {
ff[fat[i]] = true;
} else if (fat[i] >= 0xffffff0 && fat[i] <= 0xfffffff) {
ff[i + 1] = true;
}
}
}
return;
}
int get_directory_max(struct FAT_FILEINFO *directory, vfs_t *vfs) {
if (directory == get_dm(vfs).root_directory) {
return get_dm(vfs).RootMaxFiles;
}
for (int i = 1; FindForCount(i, get_dm(vfs).directory_list) != NULL; i++) {
struct List *l = FindForCount(i, get_dm(vfs).directory_list);
if ((struct FAT_FILEINFO *)l->val == directory) {
return (int)FindForCount(i, get_dm(vfs).directory_max_list)->val;
}
}
}
void file_loadfile(int clustno, int size, char *buf, int *fat, vfs_t *vfs) {
if (!size) {
return;
}
int s =
((size - 1) / get_dm(vfs).ClustnoBytes + 1) * get_dm(vfs).ClustnoBytes;
void *img = kmalloc(s);
int flag = 0, a, num = 0, sec_start = 0;
for (int i = 0; i != (size - 1) / get_dm(vfs).ClustnoBytes + 1; i++) {
uint32_t sec = (get_dm(vfs).FileDataAddress +
(clustno - 2) * get_dm(vfs).ClustnoBytes) /
get_dm(vfs).SectorBytes;
if (!flag) {
a = sec;
num = 1;
} else {
if (a + num == sec) {
num++;
} else {
Disk_Read(a, num * get_dm(vfs).ClustnoBytes / get_dm(vfs).SectorBytes,
img + sec_start * get_dm(vfs).ClustnoBytes, vfs->disk_number);
sec_start += num;
a = sec;
num = 1;
clustno = fat[clustno];
continue;
}
}
// Disk_Read(sec, get_dm(vfs).ClustnoBytes / get_dm(vfs).SectorBytes,
// img + i * get_dm(vfs).ClustnoBytes, vfs->disk_number);
flag = 1;
clustno = fat[clustno];
}
if (num) {
Disk_Read(a, num * get_dm(vfs).ClustnoBytes / get_dm(vfs).SectorBytes,
img + sec_start * get_dm(vfs).ClustnoBytes, vfs->disk_number);
}
memcpy((void *)buf, img, size);
kfree(img);
return;
}
void file_savefile(int clustno, int size, char *buf, int *fat,
unsigned char *ff, vfs_t *vfs) {
uint32_t clustall = 0;
int tmp = clustno;
int end = clustno_end(get_dm(vfs).type);
while (fat[clustno] != end) { // 计算文件占多少Fat项 Fat项 = 大小 / 簇大小 + 1
clustno = fat[clustno];
clustall++;
}
int old_clustno = clustno;
clustno = tmp;
int alloc_size;
if (size >
(clustall + 1) *
get_dm(vfs).ClustnoBytes) { // 新大小 > (旧大小 / 簇大小 + 1) * 簇大小
// 请求内存大小 = (新大小 / 簇大小 + 1) * 簇大小
alloc_size =
((size - 1) / get_dm(vfs).ClustnoBytes + 1) * get_dm(vfs).ClustnoBytes;
// 分配Fat这里需要在写盘前分配
for (int size1 = size; size1 > ((clustall + 1) * get_dm(vfs).ClustnoBytes);
size1 -= get_dm(vfs).ClustnoBytes) {
for (int i = 0; i != get_dm(vfs).FatMaxTerms; i++) {
if (!ff[i]) {
fat[old_clustno] = i;
old_clustno = i;
ff[i] = true;
break;
}
}
}
fat[old_clustno] = end; // 结尾Fat
ff[old_clustno] = true;
} else if (size <=
(clustall + 1) *
get_dm(vfs).ClustnoBytes) { // 新大小 <= (旧大小 / 簇大小
// + 1) * 簇大小
// 请求内存大小 = (旧大小 / 簇大小 + 1) * 簇大小
alloc_size = (clustall + 1) * get_dm(vfs).ClustnoBytes;
// 这里不分配Fat的原因是要清空更改后多余的数据
}
void *img = kmalloc(alloc_size);
memclean((char *)img, alloc_size);
memcpy(img, buf, size); // 把要写入的数据复制到新请求的内存地址
// for (int i = 0; i != (alloc_size / get_dm(vfs).ClustnoBytes); i++) {
// uint32_t sec = (get_dm(vfs).FileDataAddress +
// (clustno - 2) * get_dm(vfs).ClustnoBytes) /
// get_dm(vfs).SectorBytes;
// Disk_Write(sec, get_dm(vfs).ClustnoBytes / get_dm(vfs).SectorBytes,
// img + i * get_dm(vfs).ClustnoBytes, vfs->disk_number);
// clustno = fat[clustno];
// }
int flag = 0, a, num = 0, sec_start = 0;
for (int i = 0; i != (alloc_size / get_dm(vfs).ClustnoBytes); i++) {
uint32_t sec = (get_dm(vfs).FileDataAddress +
(clustno - 2) * get_dm(vfs).ClustnoBytes) /
get_dm(vfs).SectorBytes;
if (!flag) {
a = sec;
num = 1;
} else {
if (a + num == sec) {
num++;
} else {
Disk_Write(a, num * get_dm(vfs).ClustnoBytes / get_dm(vfs).SectorBytes,
img + sec_start * get_dm(vfs).ClustnoBytes,
vfs->disk_number);
sec_start += num;
a = sec;
num = 1;
clustno = fat[clustno];
continue;
}
}
// Disk_Read(sec, get_dm(vfs).ClustnoBytes / get_dm(vfs).SectorBytes,
// img + i * get_dm(vfs).ClustnoBytes, vfs->disk_number);
flag = 1;
clustno = fat[clustno];
}
if (num) {
Disk_Write(a, num * get_dm(vfs).ClustnoBytes / get_dm(vfs).SectorBytes,
img + sec_start * get_dm(vfs).ClustnoBytes, vfs->disk_number);
}
kfree(img);
if (size <
clustall *
get_dm(vfs).ClustnoBytes) { // 新大小 < (旧大小 / 簇大小) * 簇大小
// 分配Fat中间情况没必要分配
int i = old_clustno;
for (int size1 = clustall * get_dm(vfs).ClustnoBytes; size1 > size;
size1 -= get_dm(vfs).ClustnoBytes) {
fat[i] = 0;
ff[i] = false;
for (int j = 0; j != get_dm(vfs).FatMaxTerms; j++) {
if (fat[j] == i) {
i = j;
}
}
}
old_clustno = i;
fat[old_clustno] = end;
ff[old_clustno] = true;
}
file_savefat(fat, 0, get_dm(vfs).FatMaxTerms, vfs);
}
void file_saveinfo(struct FAT_FILEINFO *directory, vfs_t *vfs) {
if (directory == get_dm(vfs).root_directory) {
Disk_Write(get_dm(vfs).RootDictAddress / get_dm(vfs).SectorBytes,
get_dm(vfs).RootMaxFiles * 32 / get_dm(vfs).SectorBytes,
(void *)directory, vfs->disk_number);
} else {
for (int i = 1; FindForCount(i, get_dm(vfs).directory_list) != NULL; i++) {
struct List *list = FindForCount(i, get_dm(vfs).directory_list);
if (list->val == directory) {
list = FindForCount(i, get_dm(vfs).directory_clustno_list);
int k = (int)FindForCount(i, get_dm(vfs).directory_max_list)->val * 32 /
get_dm(vfs).ClustnoBytes;
for (int j = list->val, l = 0; l != k; l++) {
Disk_Write((get_dm(vfs).FileDataAddress +
(j - 2) * get_dm(vfs).ClustnoBytes) /
get_dm(vfs).SectorBytes,
get_dm(vfs).ClustnoBytes / get_dm(vfs).SectorBytes,
(char *)directory + l * get_dm(vfs).SectorBytes,
vfs->disk_number);
j = get_dm(vfs).fat[j];
}
break;
}
}
}
}
void file_savefat(int *fat, int clustno, int length, vfs_t *vfs) {
unsigned char *img = get_dm(vfs).ADR_DISKIMG + get_dm(vfs).Fat1Address;
int size, sec;
if (get_dm(vfs).type == 12) {
for (int i = 0; i <= length; i++) {
if ((clustno + i) % 2 == 0) {
img[(clustno + i) * 3 / 2 + 0] = fat[clustno + i] & 0xff;
img[(clustno + i) * 3 / 2 + 1] =
(fat[clustno + i] >> 8 | (img[(clustno + i) * 3 / 2 + 1] & 0xf0)) &
0xff;
} else if ((clustno + i) % 2 != 0) {
img[(clustno + i - 1) * 3 / 2 + 1] =
((img[(clustno + i - 1) * 3 / 2 + 1] & 0x0f) | fat[clustno + i]
<< 4) &
0xff;
img[(clustno + i - 1) * 3 / 2 + 2] = (fat[clustno + i] >> 4) & 0xff;
}
}
size = length * 3 / 2 - 1;
sec = clustno * 3 / 2;
} else if (get_dm(vfs).type == 16) {
for (int i = 0; i <= length; i++) {
img[(clustno + i) * 2 + 0] = fat[clustno + i] & 0xff;
img[(clustno + i) * 2 + 1] = (fat[clustno + i] >> 8) & 0xff;
}
size = length * 2 - 1;
sec = clustno * 2;
} else if (get_dm(vfs).type == 32) {
for (int i = 0; i <= length; i++) {
img[(clustno + i) * 4 + 0] = fat[clustno + i] & 0xff;
img[(clustno + i) * 4 + 1] = (fat[clustno + i] >> 8) & 0xff;
img[(clustno + i) * 4 + 2] = (fat[clustno + i] >> 16) & 0xff;
img[(clustno + i) * 4 + 3] = fat[clustno + i] >> 24;
}
size = length * 4 - 1;
sec = clustno * 4;
}
Disk_Write((get_dm(vfs).Fat1Address + sec) / get_dm(vfs).SectorBytes,
size / get_dm(vfs).SectorBytes + 1,
get_dm(vfs).ADR_DISKIMG + get_dm(vfs).Fat1Address,
vfs->disk_number);
Disk_Write((get_dm(vfs).Fat2Address + sec) / get_dm(vfs).SectorBytes,
size / get_dm(vfs).SectorBytes + 1,
get_dm(vfs).ADR_DISKIMG + get_dm(vfs).Fat2Address,
vfs->disk_number);
}
struct FAT_FILEINFO *file_search(char *name, struct FAT_FILEINFO *finfo,
int max) {
int i, j;
char s[12];
for (j = 0; j < 11; j++) {
s[j] = ' ';
}
j = 0;
for (i = 0; name[i] != 0; i++) {
if (j >= 11) {
return 0; /*没有找到*/
}
if (name[i] == '.' && j <= 8) {
j = 8;
} else {
s[j] = name[i];
if ('a' <= s[j] && s[j] <= 'z') {
/*将小写字母转换为大写字母*/
s[j] -= 0x20;
}
j++;
}
}
for (i = 0; i < max;) {
if (finfo[i].name[0] == 0x00) {
break;
}
if ((finfo[i].type & 0x18) == 0) {
for (j = 0; j < 11; j++) {
if (finfo[i].name[j] != s[j]) {
goto next;
}
}
return finfo + i; /*找到文件*/
}
next:
i++;
}
return 0; /*没有找到*/
}
struct FAT_FILEINFO *dict_search(char *name, struct FAT_FILEINFO *finfo,
int max) {
int i, j;
char s[12];
for (j = 0; j < 11; j++) {
s[j] = ' ';
}
j = 0;
for (i = 0; name[i] != 0; i++) {
if (j >= 11) {
return 0; /*没有找到*/
} else {
s[j] = name[i];
if ('a' <= s[j] && s[j] <= 'z') {
/*将小写字母转换为大写字母*/
s[j] -= 0x20;
}
j++;
}
}
for (i = 0; i < max;) {
if (finfo[i].name[0] == 0x00) {
break;
}
if (finfo[i].type == 0x10) {
for (j = 0; j < 11; j++) {
if (finfo[i].name[j] != s[j]) {
goto next;
}
}
return finfo + i; /* 找到文件 */
}
next:
i++;
}
return 0; /*没有找到*/
}
struct FAT_FILEINFO *Get_File_Address(char *path1, vfs_t *vfs) {
// TODO: Modifly it
struct FAT_FILEINFO *bmpDict = get_now_dir(vfs);
int drive_number = vfs->disk_number;
char *path = (char *)kmalloc(strlen(path1) + 1);
char *bmp = path;
strcpy(path, path1);
strtoupper(path);
if (strncmp("/", path, 1) == 0) {
path += 1;
bmpDict = get_dm(vfs).root_directory;
}
if (path[0] == '\\' || path[0] == '/') {
// 跳过反斜杠和正斜杠
for (int i = 0; i < strlen(path); i++) {
if (path[i] != '\\' && path[i] != '/') {
path += i;
break;
}
}
}
char *temp_name = (char *)kmalloc(128);
memclean(temp_name,128);
struct FAT_FILEINFO *finfo = get_dm(vfs).root_directory;
int i = 0;
while (1) {
int j;
for (j = 0; i < strlen(path); i++, j++) {
if (path[i] == '\\' || path[i] == '/') {
temp_name[j] = '\0';
i++;
break;
}
temp_name[j] = path[i];
}
finfo = dict_search(temp_name, bmpDict, get_directory_max(bmpDict, vfs));
if (finfo == 0) {
if (path[i] != '\0') {
kfree((void *)temp_name);
kfree((void *)bmp);
return 0;
}
finfo = file_search(temp_name, bmpDict, get_directory_max(bmpDict, vfs));
if (finfo == 0) {
kfree((void *)temp_name);
kfree((void *)bmp);
return 0;
} else {
goto END;
}
} else {
if (get_clustno(finfo->clustno_high, finfo->clustno_low) != 0) {
for (int count = 1;
FindForCount(count, get_dm(vfs).directory_clustno_list) != NULL;
count++) {
struct List *list =
FindForCount(count, get_dm(vfs).directory_clustno_list);
if (get_clustno(finfo->clustno_high, finfo->clustno_low) ==
list->val) {
list = FindForCount(count, get_dm(vfs).directory_list);
bmpDict = (struct FAT_FILEINFO *)list->val;
break;
}
}
} else {
bmpDict = get_dm(vfs).root_directory;
}
memclean(temp_name, 128);
}
}
END:
kfree((void *)temp_name);
kfree((void *)bmp);
return finfo;
}
struct FAT_FILEINFO *Get_dictaddr(char *path1, vfs_t *vfs) {
// TODO: Modifly it
struct FAT_FILEINFO *bmpDict = get_now_dir(vfs);
int drive_number = vfs->disk_number;
char *path = (char *)kmalloc(strlen(path1) + 1);
char *bmp = path;
strcpy(path, path1);
strtoupper(path);
if (strncmp("/", path, 1) == 0) {
path += 1;
bmpDict = get_dm(vfs).root_directory;
}
if (path[0] == '\\' || path[0] == '/') {
// 跳过反斜杠和正斜杠
for (int i = 0; i < strlen(path); i++) {
if (path[i] != '\\' && path[i] != '/') {
path += i;
break;
}
}
}
char *temp_name = (char *)kmalloc(128);
struct FAT_FILEINFO *finfo;
int i = 0;
while (1) {
int j;
for (j = 0; i < strlen(path); i++, j++) {
if (path[i] == '\\' || path[i] == '/') {
temp_name[j] = '\0';
i++;
break;
}
temp_name[j] = path[i];
}
finfo = dict_search(temp_name, bmpDict, get_directory_max(bmpDict, vfs));
if (finfo == 0) {
if (path[i] != 0) {
bmpDict = NULL;
}
goto END;
} else {
if (get_clustno(finfo->clustno_high, finfo->clustno_low) != 0) {
for (int count = 1;
FindForCount(count, get_dm(vfs).directory_clustno_list) != NULL;
count++) {
struct List *list =
FindForCount(count, get_dm(vfs).directory_clustno_list);
if (get_clustno(finfo->clustno_high, finfo->clustno_low) ==
list->val) {
list = FindForCount(count, get_dm(vfs).directory_list);
bmpDict = (struct FAT_FILEINFO *)list->val;
break;
}
}
} else {
bmpDict = get_dm(vfs).root_directory;
}
memclean(temp_name, 128);
if (path[i] == '\0') {
goto END;
}
}
}
END:
kfree((void *)temp_name);
kfree(((void *)bmp));
return bmpDict;
}
int mkdir(char *dictname, int last_clust, vfs_t *vfs) {
/*
dictname:目录名
last_clust:上一级目录的簇号
*/
int r = mkfile(dictname, vfs);
if (!r)
return 0;
// 三个目录项(模板)
static struct FAT_FILEINFO model[3];
// .目录项,指向自己
// ..目录项,指向上一级目录
// 空目录项为mkfile函数提供指引
model[0].reserve = 0;
model[1].reserve = 0;
model[2].reserve = 0;
memcpy(model[2].name, "NULL ", 11);
model[2].type = 0x20; // 文件的type属性是0x20
// 将size date time这类属性全部设置为0
model[2].size = 0;
model[2].update_date =
get_fat_date(get_year(), get_mon(), get_day_of_month());
model[2].update_time = get_fat_time(get_hour(), get_min());
for (int i = 0; i != get_dm(vfs).FatMaxTerms; i++) {
if (!get_dm(vfs).fat[i]) {
model[2].clustno_low = i;
int end = clustno_end(get_dm(vfs).type);
get_dm(vfs).fat[i] = end;
get_dm(vfs).FatClustnoFlags[i] = true;
break;
}
}
model[0].name[0] = '.';
for (int i = 1; i != 8; i++) {
model[0].name[i] = ' ';
}
for (int i = 0; i != 3; i++) {
model[0].ext[i] = ' ';
}
struct FAT_FILEINFO *finfo1 = Get_File_Address(dictname, vfs);
model[0].type = 0x10;
model[0].clustno_low = finfo1->clustno_low; // 指向自己
model[0].clustno_high = finfo1->clustno_high;
model[0].size = 0;
model[0].update_date =
get_fat_date(get_year(), get_mon(), get_day_of_month());
model[0].update_time = get_fat_time(get_hour(), get_min());
model[1].name[0] = '.';
model[1].name[1] = '.';
for (int i = 2; i != 8; i++) {
model[1].name[i] = ' ';
}
for (int i = 0; i != 3; i++) {
model[1].ext[i] = ' ';
}
model[1].clustno_low = last_clust;
model[1].size = 0;
model[1].update_date =
get_fat_date(get_year(), get_mon(), get_day_of_month());
model[1].update_time = get_fat_time(get_hour(), get_min());
model[1].type = 0x10;
Fat_WriteFile(vfs, dictname, (char *)&model[0], 32 * 3);
struct FAT_FILEINFO *finfo = Get_File_Address(dictname, vfs);
finfo->type = 0x10; // 是目录文件夹的type属性是0x10
finfo->size = 0;
int drive_number = vfs->disk_number;
AddVal(get_clustno(finfo->clustno_high, finfo->clustno_low),
get_dm(vfs).directory_clustno_list);
if (last_clust == 0) {
file_saveinfo(get_dm(vfs).root_directory, vfs);
} else {
for (int i = 1; FindForCount(i, get_dm(vfs).directory_clustno_list) != NULL;
i++) {
struct List *list = FindForCount(i, get_dm(vfs).directory_clustno_list);
if (list->val == last_clust) {
list = FindForCount(i, get_dm(vfs).directory_list);
struct FAT_FILEINFO *d_finfo = (struct FAT_FILEINFO *)list->val;
file_saveinfo(d_finfo, vfs);
}
}
}
file_savefat(get_dm(vfs).fat,
get_clustno(model[2].clustno_high, model[2].clustno_low), 1,
vfs);
void *directory_alloc = kmalloc(get_dm(vfs).ClustnoBytes);
Disk_Read((get_dm(vfs).FileDataAddress +
(get_clustno(finfo->clustno_high, finfo->clustno_low) - 2) *
get_dm(vfs).ClustnoBytes) /
get_dm(vfs).SectorBytes,
get_dm(vfs).ClustnoBytes / get_dm(vfs).SectorBytes, directory_alloc,
vfs->disk_number);
AddVal(directory_alloc, get_dm(vfs).directory_list);
AddVal(get_dm(vfs).ClustnoBytes / 32, get_dm(vfs).directory_max_list);
return 1;
}
struct FAT_FILEINFO *clust_sech(int clustno, struct FAT_FILEINFO *finfo,
int max) {
// 通过簇号找到文件信息
int i, j;
j = 0;
for (i = 0; i < max; i++) {
if (finfo[i].clustno_low == clustno) {
return finfo + i;
}
}
return 0; /*没找到*/
}
int del(char *cmdline, vfs_t *vfs) {
// 删除某个文件
char *name = cmdline;
int i;
struct FAT_FILEINFO *finfo;
finfo = Get_File_Address(name, vfs);
if (finfo == 0 || finfo->type == 0x01 || finfo->type == 0x04) {
return 0;
}
file_savefile(get_clustno(finfo->clustno_high, finfo->clustno_low), 0, NULL,
get_dm(vfs).fat, get_dm(vfs).FatClustnoFlags, vfs);
finfo->name[0] = 0xe5;
get_dm(vfs).fat[get_clustno(finfo->clustno_high, finfo->clustno_low)] = 0;
get_dm(vfs)
.FatClustnoFlags[get_clustno(finfo->clustno_high, finfo->clustno_low)] =
false;
file_saveinfo(Get_dictaddr(name, vfs), vfs);
file_savefat(get_dm(vfs).fat,
get_clustno(finfo->clustno_high, finfo->clustno_low), 1, vfs);
return 1;
}
int deldir(char *path, vfs_t *vfs) {
struct FAT_FILEINFO *finfo = Get_dictaddr(path, vfs);
if (finfo == Get_dictaddr(".", vfs)) {
return 0;
}
struct FAT_FILEINFO *f = get_now_dir(vfs);
get_now_dir(vfs) = finfo;
for (int i = 2; finfo[i].name[0] != '\0'; i++) {
if (finfo[i].type == 0x10 && finfo[i].name[0] != 0xe5) {
char s[30];
int j = 0;
for (; finfo[i].name[j] != ' '; j++) {
s[j] = finfo[i].name[j];
}
s[j] = '\0';
// printk("(CALL)DEL DIR:%s\n", s);
if (deldir(s, vfs) == -1) {
return 0;
}
// return -1;
}
}
for (int i = 2; finfo[i].name[0] != '\0'; i++) {
if (finfo[i].name[0] != 0xe5 && finfo[i].type != 0x10) {
char s[30];
int p = 0;
for (int j = 0; finfo[i].name[j] != ' '; j++, p++) {
s[p] = finfo[i].name[j];
}
if (finfo[i].ext[0] != ' ') {
s[p++] = '.';
for (int j = 0; finfo[i].ext[j] != ' ' || j != 3; j++, p++) {
s[p] = finfo[i].ext[j];
}
}
s[p] = '\0';
// printk("(IN)DEL FILE:%s\n", s);
if (del(s, vfs) == -1) {
return 0;
}
}
}
get_now_dir(vfs) = f;
// printk("(IN)DEL SELF\n");
struct FAT_FILEINFO *root_finfo;
if (finfo[1].clustno_low == 0) {
root_finfo = get_dm(vfs).root_directory;
} else {
for (int i = 1; FindForCount(i, get_dm(vfs).directory_clustno_list) != NULL;
i++) {
if (FindForCount(i, get_dm(vfs).directory_clustno_list)->val ==
finfo[1].clustno_low) {
root_finfo =
(struct FAT_FILEINFO *)FindForCount(i, get_dm(vfs).directory_list)
->val;
// printk("FIND ROOT %08x\n", root_finfo);
}
}
}
for (int i = 0; root_finfo[i].name[0] != '\0'; i++) {
// printk("ROOT FILE:%s\n", root_finfo[i].name);
if (root_finfo[i].clustno_low == finfo[0].clustno_low) {
root_finfo[i].name[0] = 0xe5;
break;
}
}
get_dm(vfs).fat[get_clustno(finfo->clustno_high, finfo->clustno_low)] = 0;
get_dm(vfs)
.FatClustnoFlags[get_clustno(finfo->clustno_high, finfo->clustno_low)] =
false;
file_saveinfo(Get_dictaddr(path, vfs), vfs);
file_savefat(get_dm(vfs).fat,
get_clustno(finfo->clustno_high, finfo->clustno_low), 1, vfs);
return 1;
}
int mkfile(char *name, vfs_t *vfs) {
// logk("mkfile : %s\n", name);
char s[12];
int i, j;
struct FAT_FILEINFO *finfo = Get_dictaddr(name, vfs);
// logk("finfo = %08x\n", finfo);
if (finfo == NULL) {
return 0;
}
int max = get_directory_max(finfo, vfs);
char *path = name;
for (i = strlen(name); i >= 0; i--) {
if (name[i] == '/' || name[i] == '\\') {
name += i + 1;
break;
}
}
for (j = 0; j != 12; j++) {
s[j] = ' ';
}
j = 0;
for (i = 0; name[i] != 0; i++) {
if (j >= 11) {
return;
}
if (name[i] == '.' && j <= 8) {
j = 8;
} else {
s[j] = name[i];
if ('a' <= s[j] && s[j] <= 'z') {
s[j] -= 0x20;
}
j++;
}
}
for (i = 0;; i++) {
if (finfo[i].name[0] == 0x00 || finfo[i].name[0] == 0xe5) {
finfo = finfo + i;
break;
}
if (i >= max && finfo != get_dm(vfs).root_directory) {
for (int j = 1; FindForCount(j, get_dm(vfs).directory_list) != NULL;
j++) {
struct List *l = FindForCount(j, get_dm(vfs).directory_list);
if ((struct FAT_FILEINFO *)l->val == finfo) {
max += get_dm(vfs).ClustnoBytes / 32;
FindForCount(j, get_dm(vfs).directory_max_list)->val = max;
struct FAT_FILEINFO *finfo_ =
(struct FAT_FILEINFO *)realloc((void *)finfo, max * 32);
if (get_now_dir(vfs) == finfo) {
get_now_dir(vfs) = finfo_;
}
finfo = finfo_;
l->val = finfo;
break;
}
}
int end = clustno_end(get_dm(vfs).type), last;
for (int j = get_clustno(finfo->clustno_high, finfo->clustno_low);;
j = get_dm(vfs).fat[j]) {
if (get_dm(vfs).fat[j] == end) {
last = j;
break;
}
}
for (int j = 0; j != get_dm(vfs).FatMaxTerms; j++) {
if (!get_dm(vfs).fat[j]) {
get_dm(vfs).fat[last] = j;
get_dm(vfs).fat[j] = end;
get_dm(vfs).FatClustnoFlags[j] = true;
break;
}
}
i--;
}
}
for (i = 0; i != 8; i++) {
finfo->name[i] = s[i];
}
for (i = 8; i != 11; i++) {
finfo->ext[i - 8] = s[i];
}
finfo->type = 0x20;
for (int i = 0; i != get_dm(vfs).FatMaxTerms; i++) {
if (!get_dm(vfs).fat[i]) {
finfo->clustno_low = i & 0xffff;
finfo->clustno_high = i >> 16;
int end = clustno_end(get_dm(vfs).type);
get_dm(vfs).fat[i] = end;
get_dm(vfs).FatClustnoFlags[i] = true;
break;
}
}
finfo->reserve = 0;
finfo->update_time = get_fat_time(get_hour(), get_min());
finfo->update_date =
get_fat_date(get_year(), get_mon(), get_day_of_month());
finfo->size = 0;
file_saveinfo(Get_dictaddr(path, vfs), vfs);
file_savefat(get_dm(vfs).fat,
get_clustno(finfo->clustno_high, finfo->clustno_low), 1, vfs);
return 1;
}
int changedict(char *dictname, vfs_t *vfs) {
// cd命令的依赖函数
strtoupper(dictname);
printf("%s\n",dictname);
if (strcmp(dictname, "/") == 0) {
while (vfs->path->ctl->all != 0) {
kfree((FindForCount(vfs->path->ctl->all, vfs->path)->val));
DeleteVal(vfs->path->ctl->all, vfs->path);
}
get_now_dir(vfs) = get_dm(vfs).root_directory;
return 1;
}
struct FAT_FILEINFO *finfo = dict_search(
dictname, get_now_dir(vfs), get_directory_max(get_now_dir(vfs), vfs));
// 找文件夹
if (finfo == 0) {
// 没找到
return 0;
}
if (get_clustno(finfo->clustno_high, finfo->clustno_low) == 0) {
// 根目录
while (vfs->path->ctl->all != 0) {
kfree((FindForCount(vfs->path->ctl->all, vfs->path)->val));
DeleteVal(vfs->path->ctl->all, vfs->path);
}
get_now_dir(vfs) = get_dm(vfs).root_directory;
return 1;
}
//..进行特殊的处理
//.不进行处理
// 其他按照下面的方式处理
if (strcmp(dictname, "..") != 0 && strcmp(dictname, ".") != 0) {
char *dict = kmalloc(255);
strcpy(dict, dictname);
AddVal(dict, vfs->path);
}
if (strcmp(dictname, "..") == 0) {
kfree((FindForCount(vfs->path->ctl->all, vfs->path)->val));
DeleteVal(vfs->path->ctl->all, vfs->path);
}
for (int count = 1;
FindForCount(count, get_dm(vfs).directory_clustno_list) != NULL;
count++) {
struct List *list = FindForCount(count, get_dm(vfs).directory_clustno_list);
if (get_clustno(finfo->clustno_high, finfo->clustno_low) == list->val) {
list = FindForCount(count, get_dm(vfs).directory_list);
get_now_dir(vfs) = (struct FAT_FILEINFO *)list->val;
break;
}
}
return 1;
}
int rename(char *src_name, char *dst_name, vfs_t *vfs) {
strtoupper(src_name);
strtoupper(dst_name);
char name[9], ext[4];
int i;
memclean(name, 9);
memclean(ext, 4);
for (i = 0; dst_name[i] != '.'; i++) {
name[i] = dst_name[i];
}
i++;
for (int j = 0; i != strlen(dst_name); i++, j++) {
ext[j] = dst_name[i];
}
struct FAT_FILEINFO *finfo = Get_File_Address(src_name, vfs);
if (finfo == 0 || finfo->type == 0x01 || finfo->type == 0x04) {
return 0;
}
memset((void *)finfo->name, ' ', 11);
for (i = 0; i != strlen(name); i++) {
finfo->name[i] = name[i];
}
for (i = 0; i != strlen(ext); i++) {
finfo->ext[i] = ext[i];
}
file_saveinfo(Get_dictaddr(src_name, vfs), vfs);
return 1;
}
int format(char drive) {
}
int attrib(char *filename, ftype type, struct vfs_t *vfs) {
struct FAT_FILEINFO *finfo = Get_File_Address(filename, vfs);
if (finfo == 0) {
return 0;
}
if (type == FLE)
finfo->type = 0x20;
else if (type == RDO)
finfo->type = 0x01;
else if (type == HID)
finfo->type = 0x02;
else if (type == SYS)
finfo->type = 0x04;
else
return 0;
file_saveinfo(Get_dictaddr(filename, vfs), vfs);
return 1;
}
void fat_InitFS(struct vfs_t *vfs, uint8_t disk_number) {
vfs->cache = kmalloc(sizeof(fat_cache));
void *boot_sector = kmalloc(512);
Disk_Read(0, 1, boot_sector, disk_number);
if (memcmp(boot_sector + BS_FileSysType, "FAT12 ", 8) == 0) {
get_dm(vfs).type = 12;
} else if (memcmp(boot_sector + BS_FileSysType, "FAT16 ", 8) == 0) {
get_dm(vfs).type = 16;
} else if (memcmp(boot_sector + BS_FileSysType + BPB_Fat32ExtByts, "FAT32 ",
8) == 0) {
get_dm(vfs).type = 32;
}
get_dm(vfs).SectorBytes = *(unsigned short *)(boot_sector + BPB_BytsPerSec);
get_dm(vfs).RootMaxFiles = *(unsigned short *)(boot_sector + BPB_RootEntCnt);
get_dm(vfs).ClustnoBytes = get_dm(vfs).SectorBytes *
*(unsigned char *)(boot_sector + BPB_SecPerClus);
get_dm(vfs).Fat1Address = *(unsigned short *)(boot_sector + BPB_RsvdSecCnt) *
get_dm(vfs).SectorBytes;
if (get_dm(vfs).type != 32) {
get_dm(vfs).RootDictAddress =
(*(unsigned char *)(boot_sector + BPB_NumFATs) *
*(unsigned short *)(boot_sector + BPB_FATSz16) +
*(unsigned short *)(boot_sector + BPB_RsvdSecCnt)) *
get_dm(vfs).SectorBytes;
get_dm(vfs).FileDataAddress =
get_dm(vfs).RootDictAddress + get_dm(vfs).RootMaxFiles * 32;
if (*(unsigned short *)(boot_sector + BPB_TotSec16) != 0) {
get_dm(vfs).imgTotalSize =
*(unsigned short *)(boot_sector + BPB_TotSec16) *
get_dm(vfs).SectorBytes;
} else {
get_dm(vfs).imgTotalSize = *(unsigned int *)(boot_sector + BPB_TotSec32) *
get_dm(vfs).SectorBytes;
}
get_dm(vfs).Fat2Address = get_dm(vfs).Fat1Address +
*(unsigned short *)(boot_sector + BPB_FATSz16) *
get_dm(vfs).SectorBytes;
} else {
get_dm(vfs).FileDataAddress =
(*(unsigned char *)(boot_sector + BPB_NumFATs) *
*(unsigned int *)(boot_sector + BPB_FATSz32) +
*(unsigned short *)(boot_sector + BPB_RsvdSecCnt)) *
get_dm(vfs).SectorBytes;
get_dm(vfs).RootDictAddress =
get_dm(vfs).FileDataAddress +
(*(unsigned int *)(boot_sector + BPB_RootClus) - 2) *
get_dm(vfs).ClustnoBytes;
get_dm(vfs).imgTotalSize =
*(unsigned int *)(boot_sector + BPB_TotSec32) * get_dm(vfs).SectorBytes;
get_dm(vfs).Fat2Address =
get_dm(vfs).Fat1Address +
*(unsigned int *)(boot_sector + BPB_FATSz32) * get_dm(vfs).SectorBytes;
get_dm(vfs).RootMaxFiles = get_dm(vfs).ClustnoBytes / 32;
}
get_dm(vfs).FatMaxTerms =
(get_dm(vfs).Fat2Address - get_dm(vfs).Fat1Address) * 8 /
get_dm(vfs).type;
uint32_t sec = (get_dm(vfs).RootDictAddress + get_dm(vfs).RootMaxFiles * 32) /
get_dm(vfs).SectorBytes;
get_dm(vfs).ADR_DISKIMG = (unsigned int)kmalloc(get_dm(vfs).RootDictAddress +
get_dm(vfs).RootMaxFiles * 32);
printf("DISK NUMBER :%x %d\n",disk_number,sec);
Disk_Read(0, sec, (void *)get_dm(vfs).ADR_DISKIMG, disk_number);
get_dm(vfs).fat = kmalloc(get_dm(vfs).FatMaxTerms * sizeof(int));
get_dm(vfs).FatClustnoFlags = kmalloc(get_dm(vfs).FatMaxTerms * sizeof(char));
read_fat((unsigned char *)(get_dm(vfs).ADR_DISKIMG +
(unsigned int)get_dm(vfs).Fat1Address),
get_dm(vfs).fat, get_dm(vfs).FatClustnoFlags,
get_dm(vfs).FatMaxTerms, get_dm(vfs).type);
get_dm(vfs).root_directory =
(struct FAT_FILEINFO *)kmalloc(get_dm(vfs).RootMaxFiles * 32);
memcpy((void *)get_dm(vfs).root_directory,
(void *)get_dm(vfs).ADR_DISKIMG + get_dm(vfs).RootDictAddress,
get_dm(vfs).RootMaxFiles * 32);
get_dm(vfs).directory_list = (struct List *)NewList();
get_dm(vfs).directory_clustno_list = (struct List *)NewList();
get_dm(vfs).directory_max_list = (struct List *)NewList();
struct FAT_FILEINFO *finfo = get_dm(vfs).root_directory;
for (int i = 0; i != get_dm(vfs).RootMaxFiles; i++) {
if (finfo[i].type == 0x10 && finfo[i].name[0] != 0xe5) {
AddVal(get_clustno(finfo[i].clustno_high, finfo[i].clustno_low),
(struct List *)get_dm(vfs).directory_clustno_list);
int end = clustno_end(get_dm(vfs).type), k = 1;
for (int j = get_clustno(finfo[i].clustno_high, finfo[i].clustno_low);
get_dm(vfs).fat[j] != end; j = get_dm(vfs).fat[j], k++)
;
void *directory_alloc = kmalloc(k * get_dm(vfs).ClustnoBytes);
for (int j = get_clustno(finfo[i].clustno_high, finfo[i].clustno_low),
l = 0;
l != k; l++) {
uint32_t sec1 =
(get_dm(vfs).FileDataAddress + (j - 2) * get_dm(vfs).ClustnoBytes) /
get_dm(vfs).SectorBytes;
Disk_Read(sec1, get_dm(vfs).ClustnoBytes / get_dm(vfs).SectorBytes,
(char *)directory_alloc + l * get_dm(vfs).SectorBytes,
disk_number);
j = get_dm(vfs).fat[j];
}
AddVal((int)directory_alloc, (struct List *)get_dm(vfs).directory_list);
AddVal(k * get_dm(vfs).ClustnoBytes / 32,
(struct List *)get_dm(vfs).directory_max_list);
}
if (finfo[i].name[0] == 0) {
break;
}
}
for (int i = 1;
FindForCount(i, (struct List *)get_dm(vfs).directory_list) != NULL;
i++) {
struct List *list =
FindForCount(i, (struct List *)get_dm(vfs).directory_list);
finfo = (struct FAT_FILEINFO *)list->val;
for (int j = 0; j != get_directory_max(finfo, vfs); j++) {
if (finfo[j].type == 0x10 && finfo[j].name[0] != 0xe5 &&
strncmp(".", (char *)finfo[j].name, 1) != 0 &&
strncmp("..", (char *)finfo[j].name, 2) != 0) {
AddVal(get_clustno(finfo[j].clustno_high, finfo[j].clustno_low),
(struct List *)get_dm(vfs).directory_clustno_list);
int end = clustno_end(get_dm(vfs).type), k = 1;
for (int m = get_clustno(finfo[j].clustno_high, finfo[j].clustno_low);
get_dm(vfs).fat[m] != end; m = get_dm(vfs).fat[m], k++)
;
void *directory_alloc = kmalloc(k * get_dm(vfs).ClustnoBytes);
for (int m = get_clustno(finfo[j].clustno_high, finfo[j].clustno_low),
l = 0;
l != k; l++) {
uint32_t sec1 = (get_dm(vfs).FileDataAddress +
(m - 2) * get_dm(vfs).ClustnoBytes) /
get_dm(vfs).SectorBytes;
Disk_Read(sec1, get_dm(vfs).ClustnoBytes / get_dm(vfs).SectorBytes,
(char *)directory_alloc + l * get_dm(vfs).SectorBytes,
disk_number);
m = get_dm(vfs).fat[m];
}
AddVal((int)directory_alloc, (struct List *)get_dm(vfs).directory_list);
AddVal(k * get_dm(vfs).ClustnoBytes / 32,
(struct List *)get_dm(vfs).directory_max_list);
}
if (finfo[j].name[0] == 0) {
break;
}
}
}
kfree((boot_sector));
}
void Fat_CopyCache(struct vfs_t *dest, struct vfs_t *src) {
dest->cache = kmalloc(sizeof(fat_cache));
memcpy(dest->cache, src->cache, sizeof(fat_cache));
}
bool Fat_cd(struct vfs_t *vfs, char *dictName) {
return changedict(dictName, vfs);
}
bool Fat_ReadFile(struct vfs_t *vfs, char *path, char *buffer) {
struct FAT_FILEINFO *finfo;
finfo = Get_File_Address(path, vfs);
if (finfo == 0) {
return 0;
} else {
file_loadfile(get_clustno(finfo->clustno_high, finfo->clustno_low),
finfo->size, buffer, get_dm(vfs).fat, vfs);
return 1;
}
}
bool Fat_WriteFile(struct vfs_t *vfs, char *path, char *buffer, int size) {
struct FAT_FILEINFO *finfo = Get_File_Address(path, vfs);
file_savefile(get_clustno(finfo->clustno_high, finfo->clustno_low), size,
buffer, get_dm(vfs).fat, get_dm(vfs).FatClustnoFlags, vfs);
finfo->size = size;
file_saveinfo(Get_dictaddr(path, vfs), vfs);
}
List *Fat_ListFile(struct vfs_t *vfs, char *dictpath) {
struct FAT_FILEINFO *finfo = Get_dictaddr(dictpath, vfs);
if(finfo == NULL) {
return NULL;
}
List *result = NewList();
char s[30];
for (int i = 0; i != 30; i++) {
s[i] = 0;
}
for (int i = 0; i < get_directory_max(finfo, vfs); i++) {
if (finfo[i].name[0] == 0x00) {
break;
}
if (finfo[i].name[0] != 0xe5) {
if ((finfo[i].type & 0x18) == 0 || finfo[i].type == 0x10) {
for (int j = 0; j < 8; j++) {
s[j] = finfo[i].name[j];
}
s[8] = '.';
if (finfo[i].ext[0] == ' ') {
s[8] = 0;
} else {
s[9] = finfo[i].ext[0];
s[10] = finfo[i].ext[1];
s[11] = finfo[i].ext[2];
}
if (s[0] != '+') {
vfs_file *d = kmalloc(sizeof(vfs_file));
if (finfo[i].type == 0x10) {
d->type = DIR;
} else if (finfo[i].type == 0x20) {
d->type = FLE;
} else if (finfo[i].type == 0x01) {
d->type = RDO;
} else if (finfo[i].type == 0x02) {
d->type = HID;
} else if (finfo[i].type == 0x04) {
d->type = SYS;
}
d->year = (finfo[i].update_date & 65024) >> 9;
d->year += 1980;
d->month = (finfo[i].update_date & 480) >> 5;
d->day = finfo[i].update_date & 31;
d->hour = (finfo[i].update_time & 63488) >> 11;
d->minute = (finfo[i].update_time & 2016) >> 5;
d->size = finfo[i].size;
int q = 0;
for (int k = 0; k < 12 && s[k] != 0; ++k) {
if (s[k] != ' ') {
d->name[q++] = s[k];
}
}
d->name[q] = 0;
// printk("d->name = %s\n", d->name);
AddVal(d, result);
}
}
}
}
return result;
}
bool Fat_RenameFile(struct vfs_t *vfs, char *filename, char *filename_of_new) {
return rename(filename, filename_of_new, vfs);
}
bool Fat_CreateFile(struct vfs_t *vfs, char *filename) {
return mkfile(filename, vfs);
}
void Fat_DeleteFs(struct vfs_t *vfs) {
kfree((void *)get_dm(vfs).ADR_DISKIMG);
kfree(get_dm(vfs).fat);
kfree(get_dm(vfs).FatClustnoFlags);
kfree(get_dm(vfs).root_directory);
DeleteList(get_dm(vfs).directory_clustno_list);
DeleteList(get_dm(vfs).directory_list);
}
bool Fat_Check(uint8_t disk_number) {
uint8_t *boot_sec = kmalloc(512);
Disk_Read(0, 1, boot_sec, disk_number);
// logk("disk number = %02x\n", disk_number);
for(int i = 0;i<0x200;i++) printf("%02x ",boot_sec[i]);
if (memcmp(boot_sec + BS_FileSysType, "FAT12 ", 8) == 0 ||
memcmp(boot_sec + BS_FileSysType, "FAT16 ", 8) == 0 ||
memcmp(boot_sec + BS_FileSysType + BPB_Fat32ExtByts, "FAT32 ", 8) ==
0) {
kfree((boot_sec));
return true;
}
kfree((boot_sec));
return false;
}
bool Fat_DelFile(struct vfs_t *vfs, char *path) { return del(path, vfs); }
bool Fat_DelDict(struct vfs_t *vfs, char *path) { return deldir(path, vfs); }
int Fat_FileSize(struct vfs_t *vfs, char *filename) {
if (Get_File_Address(filename, vfs) == NULL) {
return -1;
}
return Get_File_Address(filename, vfs)->size;
}
bool Fat_Format(uint8_t disk_number) { return format(disk_number); }
bool Fat_CreateDict(struct vfs_t *vfs, char *filename) {
struct FAT_FILEINFO *finfo = Get_dictaddr(filename, vfs);
int last_clustno = finfo[0].clustno_low;
if (finfo == get_dm(vfs).root_directory) {
last_clustno = 0;
}
return mkdir(filename, last_clustno, vfs);
}
bool Fat_Attrib(struct vfs_t *vfs, char *filename, ftype type) {
return attrib(filename, type, vfs);
}
vfs_file *Fat_FileInfo(struct vfs_t *vfs, char *filename) {
struct FAT_FILEINFO *finfo = Get_File_Address(filename, vfs);
if (finfo == NULL) {
return NULL;
}
vfs_file *result = (vfs_file *)kmalloc(sizeof(vfs_file));
char s[30];
for (int i = 0; i != 30; i++) {
s[i] = 0;
}
for (int i = 0; i < 8; i++) {
s[i] = finfo->name[i];
}
s[8] = '.';
if (finfo->ext[0] == ' ') {
s[8] = 0;
} else {
s[9] = finfo->ext[0];
s[10] = finfo->ext[1];
s[11] = finfo->ext[2];
}
int i = 0;
for (int j = 0; i < 12 && s[i] != 0; i++) {
if (s[i] != ' ') {
result->name[j++] = s[i];
}
}
s[i] = '\0';
if (finfo->type == 0x10) {
result->type = DIR;
} else if (finfo->type == 0x20) {
result->type = FLE;
} else if (finfo->type == 0x01) {
result->type = RDO;
} else if (finfo->type == 0x02) {
result->type = HID;
} else if (finfo->type == 0x04) {
result->type = SYS;
}
result->year = (finfo->update_date & 65024) >> 9;
result->year += 1980;
result->month = (finfo->update_date & 480) >> 5;
result->day = finfo->update_date & 31;
result->hour = (finfo->update_time & 63488) >> 11;
result->minute = (finfo->update_time & 2016) >> 5;
result->size = finfo->size;
return result;
}
void Register_fat_fileSys() {
vfs_t fs;
fs.flag = 1;
fs.cache = NULL;
strcpy(fs.FSName, "FAT");
fs.CopyCache = Fat_CopyCache;
fs.Format = Fat_Format;
fs.CreateFile = Fat_CreateFile;
fs.CreateDict = Fat_CreateDict;
fs.DelDict = Fat_DelDict;
fs.DelFile = Fat_DelFile;
fs.ReadFile = Fat_ReadFile;
fs.WriteFile = Fat_WriteFile;
fs.DeleteFs = Fat_DeleteFs;
fs.cd = Fat_cd;
fs.FileSize = Fat_FileSize;
fs.Check = Fat_Check;
fs.ListFile = Fat_ListFile;
fs.InitFs = fat_InitFS;
fs.RenameFile = Fat_RenameFile;
fs.Attrib = Fat_Attrib;
fs.FileInfo = Fat_FileInfo;
vfs_register_fs(fs);
}