CoolPotOS/kernel/fat16.c

327 lines
9.7 KiB
C
Raw Normal View History

2024-04-09 23:46:56 +08:00
#include "../include/fat16.h"
#include "../include/memory.h"
#include "../include/disk.h"
void read_root_dir_sector1(struct File *root_entries) {
read_disk(SECTOR_NUM_OF_ROOT_DIR_START, 1, (unsigned int) root_entries);
}
void save_root_dir_sector1(struct File *root_entries) {
write_disk(SECTOR_NUM_OF_ROOT_DIR_START, 1, (unsigned int) root_entries);
}
void read_one_cluster(unsigned short clustno, unsigned int memory_addrress) {
read_disk(clustno + SECTOR_CLUSTER_BALANCE, 1, memory_addrress);
}
int read_root_dir(struct File *file_infos) {
struct File *root_entries = (struct File *) kmalloc(SECTOR_SIZE);
read_root_dir_sector1(root_entries);
int n = 0; // 记录文件数
for (int i = 0; i < MAX_FILE_NUM; i++) {
if (root_entries[i].name[0] == 0) {
break;
}
if (root_entries[i].name[0] != 0xe5) {
file_infos[n] = root_entries[i];
n++;
}
}
kfree(root_entries);
return n;
}
void get_fat1(unsigned short *fat1) {
read_disk(SECTOR_NUM_OF_FAT1_START, FAT1_SECTORS, (unsigned int) fat1); // 将FAT1全部读取到内存中。
}
void save_fat1(unsigned short *fat1) {
write_disk(SECTOR_NUM_OF_FAT1_START, FAT1_SECTORS, (unsigned int) fat1); // 将FAT1全部写回到内存中。
}
void get_file_all_clustnos(unsigned short first_clustno, unsigned short *clustnos) {
unsigned short *fat1 = kmalloc(FAT1_SECTORS * SECTOR_SIZE);
get_fat1(fat1);
*clustnos = first_clustno;
while (1) {
unsigned short clustno = *(fat1 + *clustnos);
clustnos++;
*clustnos = clustno;
if (clustno >= 0xfff8) // 大于等于0xfff8表示文件的最后一个簇
{
break;
}
}
kfree(fat1);
}
void read_file(struct File *file, void *file_addr) {
if (file->size == 0) {
return;
}
int cluster_count = (file->size + 511) / 512;
unsigned short *clustnos = kmalloc(cluster_count * 2);
get_file_all_clustnos(file->clustno, clustnos);
for (int i = 0; i < cluster_count; i++) {
read_one_cluster(clustnos[i], (unsigned int) file_addr);
file_addr += 512;
}
kfree(clustnos);
}
void check_name_or_ext(char *str, int len) {
for (int i = 0; i < len; i++) {
if (str[i] == 0) {
str[i] = ' ';
} else if ('a' <= str[i] && str[i] <= 'z') {
str[i] -= 0x20;
}
}
}
void check_name_and_ext(char *name, char *ext) {
check_name_or_ext(name, 8);
check_name_or_ext(ext, 3);
}
void analyse_fullname(char *fullname, char *name, char *ext) {
int ext_dot_index = -1;
for (int i = 11; i >= 0; i--) {
if (fullname[i] == '.') {
ext_dot_index = i;
}
}
if (ext_dot_index == -1) // 没有后缀名的情况
{
memcpy(name, fullname, 8);
memset(ext, ' ', 3);
} else if (ext_dot_index == 0) // 没有文件名的情况
{
memset(name, ' ', 8);
memcpy(ext, fullname + 1, 3);
} else {
memcpy(name, fullname, ext_dot_index);
memcpy(ext, fullname + ext_dot_index + 1, 3);
}
check_name_and_ext(name, ext);
}
int find_file(char *name, char *ext, struct File *const file) {
struct File *root_entries = kmalloc(SECTOR_SIZE);
read_root_dir_sector1(root_entries);
int isfind = 0;
for (int i = 0; i < MAX_FILE_NUM; i++) {
if (memcmp(root_entries[i].name, name, 8) == 0 && memcmp(root_entries[i].ext, ext, 3) == 0) {
if (file != 0) {
*file = root_entries[i];
}
isfind = 1;
}
}
kfree(root_entries);
return isfind;
}
struct File *create_dir(char *fullname) {
char name[8] = {0};
char ext[3] = {0};
analyse_fullname(fullname, name, ext);
int isfind = find_file(name, ext, 0);
if (isfind) {
return 0; //文件已存在。
}
struct File *file = (struct File *) kmalloc(32);
memcpy(file->name, name, 8);
memcpy(file->ext, " ", 3);
file->type = 0x10;
file->time = 0;
file->date = 0;
file->clustno = 0;
file->size = 0;
struct File *root_entries = kmalloc(SECTOR_SIZE);
read_root_dir_sector1(root_entries);
for (int i = 0; i < MAX_FILE_NUM; i++) {
if (root_entries[i].name[0] == 0 || root_entries[i].name[0] == 0xe5) { //找一个空闲的文件项存放。
root_entries[i] = *file;
break;
}
}
save_root_dir_sector1(root_entries);
kfree(root_entries);
return file;
}
struct File *create_file(char *fullname) {
char name[8] = {0};
char ext[3] = {0};
analyse_fullname(fullname, name, ext);
int isfind = find_file(name, ext, 0);
if (isfind) {
return 0; //文件已存在。
}
struct File *file = (struct File *) kmalloc(32);
memcpy(file->name, name, 8);
memcpy(file->ext, ext, 3);
file->type = 0x20;
file->time = 0;
file->date = 0;
file->clustno = 0;
file->size = 0;
struct File *root_entries = kmalloc(SECTOR_SIZE);
read_root_dir_sector1(root_entries);
for (int i = 0; i < MAX_FILE_NUM; i++) {
if (root_entries[i].name[0] == 0 || root_entries[i].name[0] == 0xe5) { //找一个空闲的文件项存放。
root_entries[i] = *file;
break;
}
}
save_root_dir_sector1(root_entries);
kfree(root_entries);
//open_file_task(file);
kfree(name);
kfree(ext);
return file;
}
struct File *open_file(char *fullname) {
char name[8] = {0};
char ext[3] = {0};
analyse_fullname(fullname, name, ext);
struct File *file = (struct File *) kmalloc(32);
int isfind = find_file(name, ext, file);
if (!isfind) {
kfree(file);
file = 0;
} else {
//set_opened_file(file);
}
return file;
}
void alter_file_name(struct File *file, char *new_fullname) {
char new_name[8] = {0};
char new_ext[3] = {0};
analyse_fullname(new_fullname, new_name, new_ext);
struct File *root_entries = kmalloc(SECTOR_SIZE);
read_root_dir_sector1(root_entries);
for (int i = 0; i < MAX_FILE_NUM; i++) {
if (memcmp(root_entries[i].name, file->name, 8) == 0 && memcmp(root_entries[i].ext, file->ext, 3) == 0) {
memcpy(root_entries[i].name, new_name, 8);
memcpy(root_entries[i].ext, new_ext, 3);
}
}
save_root_dir_sector1(root_entries);
kfree(root_entries);
}
void alter_dir_entry(struct File *file) {
struct File *root_entries = kmalloc(SECTOR_SIZE);
read_root_dir_sector1(root_entries);
for (int i = 0; i < MAX_FILE_NUM; i++) {
if (memcmp(root_entries[i].name, file->name, 8) == 0 && memcmp(root_entries[i].ext, file->ext, 3) == 0) {
root_entries[i] = *file;
}
}
save_root_dir_sector1(root_entries);
kfree(root_entries);
}
void save_file(struct File *file, char *content) {
unsigned int file_size = strlen(content); //内容大小
if (file_size == 0 && file->size == 0) {
return;
}
file->size = file_size;
int sector_num = (file_size + 511) / 512; //将要占用的扇区数
unsigned short *fat1 = kmalloc(FAT1_SECTORS * SECTOR_SIZE);
get_fat1(fat1);
unsigned short clustno = file->clustno;
unsigned short next_clustno;
if (file->clustno == 0) //第一次写入
{
clustno = 2; //可用簇号从2开始
while (1) {
if (*(fat1 + clustno) == 0) //空闲簇号
{
file->clustno = clustno; //分配起始簇号
break;
} else {
clustno++;
}
}
}
int i = 0;
while (1) {
write_disk(SECTOR_CLUSTER_BALANCE + clustno, 1, (unsigned int) content);
if (i == sector_num - 1) { //已写完最后一扇区。
break;
}
i++;
content += 512;
next_clustno = *(fat1 + clustno);
if (next_clustno == 0 || next_clustno >= 0xfff8) { //寻找下一个可用簇号
next_clustno = clustno + 1;
while (1) {
if (*(fat1 + next_clustno) == 0) {
*(fat1 + clustno) = next_clustno;
break;
} else {
next_clustno++;
}
}
}
clustno = next_clustno;
}
next_clustno = *(fat1 + clustno);
*(fat1 + clustno) = 0xffff; //0xfff8~0xffff表示文件结束没有下一个簇了。
//如果本次写入的内容比上次的少,上次用过的簇号本次用不完,以下将剩下的簇号清零处理。
if (1 < next_clustno && next_clustno < 0xfff0) {
while (1) {
clustno = next_clustno;
next_clustno = *(fat1 + clustno);
*(fat1 + clustno) = 0;
if (next_clustno >= 0xfff8) {
break;
}
}
}
alter_dir_entry(file);
save_fat1(fat1);
kfree(fat1);
}
void delete_file(struct File *file) {
//1.标记目录项为已删除。
struct File *root_entries = kmalloc(SECTOR_SIZE);
read_root_dir_sector1(root_entries);
for (int i = 0; i < MAX_FILE_NUM; i++) {
if (memcmp(root_entries[i].name, file->name, 8) == 0 && memcmp(root_entries[i].ext, file->ext, 3) == 0) {
root_entries[i].name[0] = 0xe5;
break;
}
}
save_root_dir_sector1(root_entries);
kfree(root_entries);
if (file->clustno == 0) {
return;
}
unsigned short *fat1 = kmalloc(FAT1_SECTORS * SECTOR_SIZE);
get_fat1(fat1);
unsigned short clustno = file->clustno;
unsigned short next_clustno = 0;
while (1) {
next_clustno = *(fat1 + clustno);
*(fat1 + clustno) = 0;
if (next_clustno >= 0xfff8) {
break;
}
clustno = next_clustno;
}
save_fat1(fat1);
kfree(fat1);
}