建立一个mulu的目录,然后在此目录下创建一个文本文件
前面那个只能创建普通文本文件。
root@ubuntu:/mnt/fat# ls
mulu
root@ubuntu:/mnt/fat# ls -alh mulu/
总用量 8.0K
drwxr-xr-x 2 root root 512 Jan 1 2017 .
drwxr-xr-x 3 root root 7.0K Dec 31 1969 ..
-rwxr-xr-x 1 root root 6 Jan 1 2017 FILE1.TXT
root@ubuntu:/mnt/fat#
#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;
}
// 修正后的 create_fat_table
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:mulu目录
fat16[3] = 0xFFFF; // 簇3:file1.txt文件
}
//创建根目录
void create_root_dir(DirEntry* root_dir, int root_entries) {
memset(root_dir, 0, root_entries * sizeof(DirEntry));
// 创建mulu目录项
DirEntry* entry = &root_dir[0];
memset(entry->name, ' ', 11);
memcpy(entry->name, "mulu", 4); // 目录名(大写)
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);
if (dir_entries == NULL) {
printf("内存分配失败\n");
return;
}
// 创建 "." 目录项
DirEntry* dot_entry = &dir_entries[0];
memset(dot_entry->name, ' ', 11);
memcpy(dot_entry->name, ".", 1);
dot_entry->attributes = 0x10;
dot_entry->first_cluster_low = cluster_num;
dot_entry->file_size = 0;
// 创建 ".." 目录项
DirEntry* dotdot_entry = &dir_entries[1];
memset(dotdot_entry->name, ' ', 11);
memcpy(dotdot_entry->name, "..", 2);
dotdot_entry->attributes = 0x10;
dotdot_entry->first_cluster_low = parent_cluster; // 根目录的父目录为0
dotdot_entry->file_size = 0;
fseek(fp, data_start, SEEK_SET);
fwrite(dir_entries, bs->bytes_per_sector, 1, fp);
free(dir_entries);
}
// 在指定目录中创建文件
void create_file_in_directory(FILE* fp, BootSector* bs, int dir_cluster,
const char* filename, const char* content, int file_cluster) {
// 读取目录数据区
unsigned int dir_start = g_bs_data_start + (dir_cluster - 2) * bs->bytes_per_sector;
DirEntry* dir_entries = (DirEntry*)malloc(bs->bytes_per_sector);
if (dir_entries == NULL) {
printf("内存分配失败\n");
return;
}
fseek(fp, dir_start, SEEK_SET);
fread(dir_entries, 1, bs->bytes_per_sector, fp);
// 查找空闲目录项(从第2个开始,因为前两个是.和..)
int i;
for (i = 2; i < bs->bytes_per_sector / sizeof(DirEntry); i++) {
if (dir_entries[i].name[0] == 0x00 || dir_entries[i].name[0] == 0xE5) {
break;
}
}
if (i >= bs->bytes_per_sector / sizeof(DirEntry)) {
printf("目录已满\n");
free(dir_entries);
return;
}
// 创建文件目录项
DirEntry* entry = &dir_entries[i];
memset(entry->name, ' ', 11);
// 处理文件名(8.3格式)
const char* dot = strchr(filename, '.');
if (dot) {
// 有扩展名
int name_len = dot - filename;
int ext_len = strlen(dot + 1);
// 文件名部分(最多8个字符)
memcpy(entry->name, filename, name_len > 8 ? 8 : name_len);
// 扩展名部分(最多3个字符)
if (ext_len > 0) {
memcpy(entry->name + 8, dot + 1, ext_len > 3 ? 3 : ext_len);
}
} else {
// 无扩展名
memcpy(entry->name, filename, strlen(filename) > 8 ? 8 : strlen(filename));
}
// 转换为大写(FAT标准要求)
for (int j = 0; j < 11; j++) {
if (entry->name[j] >= 'a' && entry->name[j] <= 'z') {
entry->name[j] = entry->name[j] - 'a' + 'A';
}
}
entry->attributes = 0x20; // 普通文件属性
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 = file_cluster;
entry->file_size = strlen(content);
// 写回目录数据区
fseek(fp, dir_start, SEEK_SET);
fwrite(dir_entries, bs->bytes_per_sector, 1, fp);
free(dir_entries);
// 写入文件数据
unsigned int file_start = g_bs_data_start + (file_cluster - 2) * bs->bytes_per_sector;
uint8_t* file_data = (uint8_t*)malloc(bs->bytes_per_sector);
if (file_data == NULL) {
printf("内存分配失败\n");
return;
}
memset(file_data, 0, bs->bytes_per_sector);
memcpy(file_data, content, strlen(content));
fseek(fp, file_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 );
// 4. 创建根目录
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);
// 5. 创建mulu目录的数据区(簇2)
create_directory_data(fp, &bs, 2, 0);
// 6. 在mulu目录中创建file1.txt文件(簇3)
create_file_in_directory(fp, &bs, 2, "file1.txt", "88888\n", 3);
// 填充剩余空间
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");
fclose(fp);
printf("FAT16镜像已创建并写入新文件\n");
return 0;
}