CoolPotOS/fs/fat16.c
2024-05-12 14:34:03 +08:00

327 lines
9.7 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/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);
}