模拟一个fat16文件系统,并创建4个文件,生成的映像可挂载。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h> //文件权限相关
#include <arpa/inet.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <capstone/capstone.h>
#include <elf.h>
#include <sys/queue.h>
typedef unsigned char u8;
typedef unsigned int u32;
typedef unsigned short u16;
typedef char s8;
typedef short s16;
typedef int s32;
typedef unsigned longULONG;
int macdbg_dmphex( const char* buff, int len );
unsigned int g_debug_buff[64];
int macdbg_dmphex( const char* buff, int len )
{
int retval = 0;
int x, y, tot, lineoff;
const char* curr;
lineoff = 0;
curr = buff;
tot = 0;
printf( "buff = %p\n", buff );
for( x = 0; len > x+16; ){
printf("0x%08x: ", lineoff);
for( y = 0; y < 16; y++ ){
printf("%02x ", (unsigned char)*(curr + y));
}
printf(" ");
for( y = 0; y < 16; y++ ){
char c;
c = *(curr + y);
if( c > 31 && c < 127 ){
printf("%c", c);
}else{
printf("%c", '.');
}
tot++;
}
curr += 16;
x += 16;
lineoff += 16;
printf("\n");
}
//do last line
if( tot < len ){
curr = (buff + tot);
printf("0x%08x: ", lineoff);
for( y = 0; y < (len - tot); y++ ){
printf("%02x ", (unsigned char)*(curr + y));
}
//padding with spaces
//Ser_Printf("(len - tot) %d.\r\n", (len - tot) );
if( (len - tot) < 16 ){
for( y = 0; y < (32 - ((len - tot)*2)); y++ ){
printf(" ");
}
}
for( y = 0; y < 16-(len - tot); y++ ){
printf(" ");
}
printf(" ");
//Ser_Printf("(len - tot) %d.\r\n", (len - tot) );
for( y = 0; y < (len - tot); y++ ){
char c;
c = *(curr + y);
if( c >31 && c < 127 ){
printf("%c", c);
}else{
printf("%c", '.');
}
}
}
printf("\n");
return retval;
}
//dd if=/dev/zero of=fat.img bs=1k count=64
//mkfs.vfat ./fat.img
//mkdir -p /mnt/fat
//mount -o loop fat.img /mnt/fat
//echo "Hello, FAT!" > /mnt/fat/testfile.txt
//sync
//umount /mnt/fat
// FAT16引导扇区结构
#pragma pack(push, 1)
typedef struct {
uint8_t jump_boot[3];
char oem_name[8];
uint16_t bytes_per_sector;
uint8_t sectors_per_cluster;
uint16_t reserved_sectors;
uint8_t fat_count;
uint16_t root_entries;
uint16_t total_sectors_16;
uint8_t media_type;
uint16_t sectors_per_fat;
uint16_t sectors_per_track;
uint16_t head_count;
uint32_t hidden_sectors;
uint32_t total_sectors_32;
uint8_t drive_number;
uint8_t reserved;
uint8_t boot_signature;
uint32_t volume_serial;
char volume_label[11];
char fs_type[8];
uint8_t boot_code[448];
uint16_t boot_sector_sig;
} BootSector;
#pragma pack(pop)
// FAT目录项结构
#pragma pack(push, 1)
typedef struct {
char name[11];
uint8_t attributes;
uint8_t reserved;
uint8_t creation_time_tenth;
uint16_t creation_time;
uint16_t creation_date;
uint16_t last_access_date;
uint16_t first_cluster_high;
uint16_t write_time;
uint16_t write_date;
uint16_t first_cluster_low;
uint32_t file_size;
} DirEntry;
#pragma pack(pop)
unsigned int g_bs_data_start = 0x00;
// 创建引导扇区
void create_boot_sector(BootSector* bs)
{
memset(bs, 0, sizeof(BootSector));
bs->jump_boot[0] = 0xEB;
bs->jump_boot[1] = 0x3C;
bs->jump_boot[2] = 0x90;
memcpy(bs->oem_name, "MSDOS5.0", 8);
bs->bytes_per_sector = 512;
bs->sectors_per_cluster = 1;
bs->reserved_sectors = 1;
bs->fat_count = 2;
bs->root_entries = 224;
bs->total_sectors_16 = 2880;
bs->media_type = 0xF0;
bs->sectors_per_fat = 9;
bs->sectors_per_track = 18;
bs->head_count = 2;
bs->hidden_sectors = 0;
bs->total_sectors_32 = 0;
bs->drive_number = 0x80;
bs->boot_signature = 0x29;
bs->volume_serial = 0x12345678;
memcpy(bs->volume_label, "MYDISK ", 11);
memcpy(bs->fs_type, "FAT16 ", 8);
bs->boot_sector_sig = 0xAA55;
}
// 创建FAT表
void create_fat_table(uint8_t* fat, int sectors_per_fat, int bytes_per_sector) {
memset(fat, 0, sectors_per_fat * bytes_per_sector);
uint16_t* fat16 = (uint16_t*)fat;
fat16[0] = 0xFFF0; // 簇0:介质类型
fat16[1] = 0xFFFF; // 簇1:保留
//fat16[2] = 0xFFFF; // 簇2:TEST目录
//fat16[3] = 0xFFFF; // 簇3:TEST1.TXT
}
// 创建根目录
void create_root_dir(DirEntry* root_dir, int root_entries) {
memset(root_dir, 0, root_entries * sizeof(DirEntry));
DirEntry* entry = &root_dir[0];
memcpy(entry->name, "mulu", 5); // 目录名
entry->attributes = 0x10; // 目录属性
entry->creation_time_tenth = 0;
entry->creation_time = 0x8000;
entry->creation_date = 0x4A21;
entry->last_access_date = 0x4A21;
entry->first_cluster_high = 0;
entry->write_time = 0x8000;
entry->write_date = 0x4A21;
entry->first_cluster_low = 2; // 起始簇2
entry->file_size = 0; // 目录大小为0
}
// 创建目录数据区
void create_directory_data(FILE* fp, BootSector* bs, int cluster_num, int parent_cluster) {
unsigned int data_start = g_bs_data_start + (cluster_num - 2) * bs->bytes_per_sector;
DirEntry* dir_entries = (DirEntry*)calloc(bs->bytes_per_sector, 1);
// 创建 "." 目录项
DirEntry* dot_entry = &dir_entries[0];
memcpy(dot_entry->name, ". ", 11);
dot_entry->attributes = 0x10;
dot_entry->first_cluster_low = cluster_num;
// 创建 ".." 目录项
DirEntry* dotdot_entry = &dir_entries[1];
memcpy(dotdot_entry->name, ".. ", 11);
dotdot_entry->attributes = 0x10;
dotdot_entry->first_cluster_low = parent_cluster;
fseek(fp, data_start, SEEK_SET);
fwrite(dir_entries, bs->bytes_per_sector, 1, fp);
free(dir_entries);
}
// 创建文件
void create_file(FILE* fp, BootSector* bs, const char* filename, const char* content, int cluster_num) {
DirEntry* root_dir = (DirEntry*)malloc(bs->root_entries * sizeof(DirEntry));
unsigned int root_dir_start = bs->reserved_sectors * bs->bytes_per_sector +
(bs->fat_count * bs->sectors_per_fat * bs->bytes_per_sector);
fseek(fp, root_dir_start, SEEK_SET);
fread(root_dir, sizeof(DirEntry), bs->root_entries, fp);
for (int i = 0; i < bs->root_entries; i++) {
if (root_dir[i].name[0] == 0x00) {
memcpy(root_dir[i].name, filename, 11);
root_dir[i].attributes = 0x20; // 文件属性
root_dir[i].first_cluster_low = cluster_num;
root_dir[i].file_size = strlen(content);
fseek(fp, root_dir_start + i * sizeof(DirEntry), SEEK_SET);
fwrite(&root_dir[i], sizeof(DirEntry), 1, fp);
break;
}
}
free(root_dir);
// 写入文件数据
unsigned int data_start = g_bs_data_start + (cluster_num - 2) * bs->bytes_per_sector;
uint8_t* file_data = (uint8_t*)malloc(bs->bytes_per_sector);
memcpy(file_data, content, strlen(content));
fseek(fp, data_start, SEEK_SET);
fwrite(file_data, bs->bytes_per_sector, 1, fp);
free(file_data);
}
// 修正后的 find_free_cluster 函数
int find_free_cluster(FILE* fp, BootSector* bs) {
int fat_size = bs->sectors_per_fat * bs->bytes_per_sector;
uint8_t* fat = (uint8_t*)malloc(fat_size);
fseek(fp, bs->reserved_sectors * bs->bytes_per_sector, SEEK_SET);
fread(fat, 1, fat_size, fp);
uint16_t* fat16 = (uint16_t*)fat;
int total_clusters = fat_size / 2;
for (int i = 2; i < total_clusters; i++) {
if (fat16[i] == 0x0000) { // 空闲簇
free(fat);
return i;
}
}
free(fat);
return -1;
}
int count_chars_before_dot(const char* s) {
const char* dot = strchr(s, '.');
if (dot == NULL) {
return strlen(s); // 无.返回总长度
}
return dot - s; // 返回.前字符数
}
void write_file( FILE* fp, BootSector* bs, const char* filename, const char* content )
{
unsigned int root_dir_start;
int n;
DirEntry* root_dir = (DirEntry*)malloc(bs->root_entries * sizeof(DirEntry));
uint8_t* fat = (uint8_t*)malloc(1 * bs->sectors_per_fat * bs->bytes_per_sector);
int fat_size = bs->sectors_per_fat * bs->bytes_per_sector;
fseek(fp, bs->reserved_sectors * bs->bytes_per_sector, SEEK_SET);
fread(fat, 1, fat_size, fp);
root_dir_start = bs->reserved_sectors * bs->bytes_per_sector +
(bs->fat_count * bs->sectors_per_fat * bs->bytes_per_sector);
fseek(fp, root_dir_start, SEEK_SET);
fread(root_dir, sizeof(DirEntry), bs->root_entries, fp);
// 2. 查找空闲簇
int cluster = find_free_cluster(fp, bs);
if (cluster == -1) {
printf("磁盘空间不足\n");
free(root_dir);
free(fat);
return;
}
printf("cluster = %d\n", cluster);
// 3. 创建目录项
int i;
for (i = 0; i < bs->root_entries; i++) {
if (root_dir[i].name[0] == 0x00) break;
}
if (i == bs->root_entries) {
printf("根目录已满\n");
free(root_dir);
free(fat);
return;
}
DirEntry* entry = &root_dir[i];
memset(entry->name, ' ', 11); // 初始化为空格
n = count_chars_before_dot(filename);
printf("n = %d\n", n);
memcpy(entry->name, filename, n > 8 ? 8 : n ); //限制8字节
memcpy(entry->name + 8, filename+n+1, strlen(filename)-n-1 );
entry->attributes = 0x20; // 普通文件
entry->first_cluster_low = cluster;
entry->file_size = strlen(content);
// 4. 写入根目录
fseek(fp, root_dir_start + i * sizeof(DirEntry), SEEK_SET);
fwrite(entry, sizeof(DirEntry), 1, fp);
// 5. 写入文件数据
unsigned int data_start = g_bs_data_start + (cluster - 2) * bs->bytes_per_sector;
int content_len = strlen(content);
int sectors = (content_len + bs->bytes_per_sector - 1) / bs->bytes_per_sector;
uint8_t* file_data = (uint8_t*)malloc(bs->bytes_per_sector);
printf("sectors = %d\n", sectors);
//return;
for (int j = 0; j < sectors; j++) {
int write_len = (j == sectors - 1) ? content_len % bs->bytes_per_sector : bs->bytes_per_sector;
printf("write_len = %d\n", write_len);
memcpy(file_data, content + j * bs->bytes_per_sector, write_len);
printf("data_start = %x\n", data_start);
fseek(fp, data_start + j * bs->bytes_per_sector, SEEK_SET);
fwrite(file_data, write_len, 1, fp);
// 更新FAT表
uint16_t* fat16 = (uint16_t*)fat;
if (j < sectors - 1) {
fat16[cluster] = cluster + 1; // 链接下一个簇
} else {
fat16[cluster] = 0xFFFF; // 文件结束
}
cluster++;
}
printf("bs->reserved_sectors * bs->bytes_per_sector = %x\n", bs->reserved_sectors * bs->bytes_per_sector);
// 6. 写回FAT表
fseek(fp, bs->reserved_sectors * bs->bytes_per_sector, SEEK_SET);
fwrite(fat, 1, 1 * bs->sectors_per_fat * bs->bytes_per_sector, fp);
fseek(fp, bs->reserved_sectors * bs->bytes_per_sector +
1 * bs->sectors_per_fat * bs->bytes_per_sector, SEEK_SET);
fwrite(fat, 1, 1 * bs->sectors_per_fat * bs->bytes_per_sector, fp);
// 7. 释放资源
free(root_dir);
free(fat);
free(file_data);
}
int main( void )
{
FILE* fp = fopen("fat.img", "wb+");
if (!fp) {
printf("can not to creat disk image.\n");
return 1;
}
unsigned int root_dir_start;
BootSector bs;
create_boot_sector(&bs);
fwrite(&bs, sizeof(BootSector), 1, fp);
printf( "sizeof(BootSector) = %d\n", sizeof(BootSector) );
printf( "bs.sectors_per_fat = %d\n", bs.sectors_per_fat );
printf( "bs.bytes_per_sector = %d\n", bs.bytes_per_sector );
int fat_size = bs.sectors_per_fat * bs.bytes_per_sector;
uint8_t* fat = (uint8_t*)calloc(fat_size, 1);
create_fat_table(fat, bs.sectors_per_fat, bs.bytes_per_sector);
//macdbg_dmphex( (const char *) fat, fat_size);
fwrite(fat, fat_size, 1, fp);
fwrite(fat, fat_size, 1, fp);
root_dir_start = bs.reserved_sectors * bs.bytes_per_sector +
(bs.fat_count * bs.sectors_per_fat * bs.bytes_per_sector);
g_bs_data_start = root_dir_start +
(bs.root_entries * sizeof(DirEntry));
printf( "bs.reserved_sectors = %d\n", bs.reserved_sectors );
printf( "bs.fat_count = %d\n", bs.fat_count );
printf( "bs.root_entries = %d\n", bs.root_entries );
printf( "sizeof(DirEntry) = %d\n", sizeof(DirEntry) );
printf( "root_dir_start = %#x\n", root_dir_start );
printf( "g_bs_data_start = %#x\n", g_bs_data_start );
//DirEntry* root_dir = (DirEntry*)calloc(bs.root_entries, sizeof(DirEntry));
//create_root_dir(root_dir, bs.root_entries);
//fwrite(root_dir, bs.root_entries * sizeof(DirEntry), 1, fp);
//uint8_t* file_data = (uint8_t*)calloc(bs.bytes_per_sector, 1);
// create_file_data(file_data, bs.bytes_per_sector);
//fwrite(file_data, bs.bytes_per_sector, 1, fp);
// 填充剩余空间
long current_pos = ftell(fp);
long total_size = 2880 * 512;
if (current_pos < total_size) {
uint8_t* padding = (uint8_t*)calloc(total_size - current_pos, 1);
fwrite(padding, total_size - current_pos, 1, fp);
free(padding);
}
fclose(fp);
free(fat);
//free(root_dir);
//free(file_data);
// 写入新文件
fp = fopen("fat.img", "r+b");
if (!fp) {
printf("无法打开磁盘镜像\n");
return 1;
}
//write_file(fp, &bs, "file1 txt", "file1 neirong888899999.\n");
write_file(fp, &bs, "file1.txt", "123\n");
write_file(fp, &bs, "file2.txt", "456\n");
write_file(fp, &bs, "file3.txt", "333\n");
write_file(fp, &bs, "file4.txt", "444\n");
fclose(fp);
printf("FAT16镜像已创建并写入新文件\n");
return 0;
}
// 主函数
int mainxxx(void) {
BootSector bs;
create_boot_sector(&bs);
FILE* fp = fopen("fat.img", "wb");
if (!fp) {
printf("无法创建磁盘镜像\n");
return 1;
}
// 写入引导扇区
fwrite(&bs, sizeof(BootSector), 1, fp);
// 写入两个FAT表
uint8_t* fat = (uint8_t*)malloc(bs.sectors_per_fat * bs.bytes_per_sector);
create_fat_table(fat, bs.sectors_per_fat, bs.bytes_per_sector);
fwrite(fat, bs.sectors_per_fat * bs.bytes_per_sector, 1, fp);
fwrite(fat, bs.sectors_per_fat * bs.bytes_per_sector, 1, fp);
free(fat);
// 创建根目录
DirEntry* root_dir = (DirEntry*)calloc(bs.root_entries, sizeof(DirEntry));
create_root_dir(root_dir, bs.root_entries);
fwrite(root_dir, bs.root_entries * sizeof(DirEntry), 1, fp);
free(root_dir);
// 创建TEST目录数据区(簇2)
create_directory_data(fp, &bs, 2, 0);
// 创建TEST1.TXT文件(簇3)
create_file(fp, &bs, "file", "Hello,FAT16!\n", 3);
// 填充剩余空间
unsigned int total_size = bs.total_sectors_16 * bs.bytes_per_sector;
unsigned int current_size = ftell(fp);
if (current_size < total_size) {
uint8_t* padding = (uint8_t*)calloc(total_size - current_size, 1);
fwrite(padding, 1, total_size - current_size, fp);
free(padding);
}
fclose(fp);
printf("FAT16镜像创建完成:fat16.img\n");
return 0;
}
mount -o loop fat.img /mnt/fat
root@ubuntu:/mnt/fat# ls -alh
总用量 13K
drwxr-xr-x 2 root root 7.0K Dec 31 1969 .
drwxr-xr-x 4 root root 4.0K Dec 25 02:20 ..
-rwxr-xr-x 1 root root 4 Dec 31 1979 file1.txt
-rwxr-xr-x 1 root root 4 Dec 31 1979 file2.txt
-rwxr-xr-x 1 root root 4 Dec 31 1979 file3.txt
-rwxr-xr-x 1 root root 4 Dec 31 1979 file4.txt