Operating_Systems/Lab/Lab6/source/21281280-柯劲帆-第6次实验.md
2024-09-05 13:31:02 +08:00

493 lines
22 KiB
Markdown
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.

<h1><center>北京交通大学实验报告</center></h1>
<div style="text-align: center;">
<div><span style="display: inline-block; width: 65px; text-align: center;">课程名称</span><span style="display: inline-block; width: 25px;">:</span><span style="display: inline-block; width: 310px; font-weight: bold; text-align: left;">操作系统</span></div>
<div><span style="display: inline-block; width: 65px; text-align: center;">实验题目</span><span style="display: inline-block; width: 25px;">:</span><span style="display: inline-block; width: 310px; font-weight: bold; text-align: left;">FAT文件系统模拟与实现</span></div>
<div><span style="display: inline-block; width: 65px; text-align: center;">学号</span><span style="display: inline-block; width: 25px;">:</span><span style="display: inline-block; width: 310px; font-weight: bold; text-align: left;">21281280</span></div>
<div><span style="display: inline-block; width: 65px; text-align: center;">姓名</span><span style="display: inline-block; width: 25px;">:</span><span style="display: inline-block; width: 310px; font-weight: bold; text-align: left;">柯劲帆</span></div>
<div><span style="display: inline-block; width: 65px; text-align: center;">班级</span><span style="display: inline-block; width: 25px;">:</span><span style="display: inline-block; width: 310px; font-weight: bold; text-align: left;">物联网2101班</span></div>
<div><span style="display: inline-block; width: 65px; text-align: center;">指导老师</span><span style="display: inline-block; width: 25px;">:</span><span style="display: inline-block; width: 310px; font-weight: bold; text-align: left;">何永忠</span></div>
<div><span style="display: inline-block; width: 65px; text-align: center;">报告日期</span><span style="display: inline-block; width: 25px;">:</span><span style="display: inline-block; width: 310px; font-weight: bold; text-align: left;">2023年12月31日</span></div>
</div>
---
## 目录
[TOC]
---
# 1. 开发运行环境和工具
| 操作系统 | Linux内核版本 | 处理器 | GCC版本 |
| :---------: | :-----------------------: | :--------------------------------------: | :-------------------------------: |
| Deepin 20.9 | 5.18.17-amd64-desktop-hwe | Intel(R) Core(TM) i3-2330M CPU @ 2.20GHz | gcc (Uos 8.3.0.3-3+rebuild) 8.3.0 |
- **其他工具**
- **编辑**VSCode
- **编译和运行**Terminal
# 2. FAT磁盘格式化操作和映像文件生成
FAT的引导扇区各个字段的定义和说明如下
| 字节位移 | 字段长度(字节) | 字段名称 |
| -------- | -------------- | ---------------------------- |
| 0x00 | 3 | 跳转指令(Jump Instruction) |
| 0x03 | 8 | OEM ID |
| 0x0B | 25 | BPB |
| 0x24 | 26 | 扩展BPB |
| 0x3E | 448 | 引导程序代码(Bootstrap Code) |
| 0x01FE | 4 | 扇区结束标识符(0xAA55) |
FAT16分区的BPB字段为
| 字节位移 | 字段长度(字节) | 例值 | 名称、定义和描述 |
| -------- | -------------- | ----------- | ------------------------------------------------------------ |
| 0x0B | 2 | 0x0200 | 扇区字节数(Bytes Per Sector) 硬件扇区的大小。本字段合法的十进制值有512、1024、2048和4096。对大多数磁盘来说本字段的值为512 |
| 0x0D | 1 | 0x10 | 每簇扇区数(Sectors Per Cluster) 一个簇中的扇区数。由于FAT16文件系统只能跟踪有限个簇(最多为65536个)。因此,通过增加每簇的扇区数可以支持最大分区数。分区的缺省的簇的大小取决于该分区的大小。本字段合法的十进制值有 1、2、4、8、16、32、64和128。导致簇大于32KB(每扇区字节数*每簇扇区数)的值会引起磁盘错误和软件错误 |
| 0x0e | 2 | 0x0006 | 保留扇区数(Reserved Sector) 第一个FAT开始之前的扇区数包括引导扇区。 |
| 0x10 | 1 | 0x02 | FAT数(Number of FAT)该分区上FAT的副本数。本字段的值一般为2 |
| 0x11 | 2 | 0x0200 | 根目录项数(Root Entries) 能够保存在该分区的根目录文件夹中的32个字节长的文件和文件夹名称项的总数。在一个典型的硬盘上本字段的值为512。其中一个项常常被用作卷标号(Volume Label)长名称的文件和文件夹每个文件使用多个项。文件和文件夹项的最大数一般为511但是如果使用的长文件名往往都达不到这个数。 |
| 0x13 | 2 | 0x0000 | 小扇区数(Small Sector) 该分区上的扇区数表示为16位(<65536)。对大于65536个扇区的分区来说本字段的值为0而使用大扇区数来取代它 |
| 0x15 | 1 | 0xF8 | 媒体描述符( Media Descriptor)提供有关媒体被使用的信息值0xF8表示硬盘0xF0表示高密度的3.5寸软盘媒体描述符要用于MS-DOS FAT16磁盘在Windows 2000中未被使用 |
| 0x16 | 2 | 0x00F5 | 每FAT扇区数(Sectors Per FAT) 该分区上每个FAT所占用的扇区数计算机利用这个数和FAT数以及隐藏扇区数来决定根目录在哪里开始计算机还可以根据根目录中的项数(512)决定该分区的用户数据区从哪里开始 |
| 0x18 | 2 | 0x003F | 每道扇区数(Sectors Per Trark) |
| 0x1A | 2 | 0x00FF | 磁头数(Number of head) |
| 0x1C | 4 | 0x000000400 | 隐藏扇区数(Hidden Sector) 该分区上引导扇区之前的扇区数在引导序列计算到根目录和数据区的绝对位移的过程中使用了该值 |
| 0x20 | 4 | 0x000F4C00 | 大扇区数(Large Sector) 如果小扇区数字段的值为0本字段就包含该FAT16分区中的总扇区数如果小扇区数字段的值不为0那么本字段的值为0 |
FAT16分区的扩展BPB字段为
| 字节位移 | 字段长度(字节) | 图8对应取值 | 名称定义和描述 |
| -------- | -------------- | ----------- | ------------------------------------------------------------ |
| 0x24 | 1 | 0x80 | 物理驱动器号( Physical Drive Number) 与BIOS物理驱动器号有关软盘驱动器被标识为0x00物理硬盘被标识为0x80而与物理磁盘驱动器无关一般地在发出一个INT13h BIOS调用之前设置该值具体指定所访问的设备只有当该设备是一个引导设备时这个值才有意义 |
| 0x25 | 1 | 0x01 | 保留(Reserved) FAT16分区一般将本字段的值设置为1 |
| 0x26 | 1 | 0x29 | 扩展引导标签(Extended Boot Signature) 本字段必须要有能被Windows 2000所识别的值0x28或0x29 |
| 0x27 | 2 | 0xABA13358 | 卷序号(Volume Serial Number) 在格式化磁盘时所产生的一个随机序号它有助于区分磁盘 |
| 0x2B | 11 | "NO NAME" | 卷标(Volume Label) 本字段只能使用一次它被用来保存卷标号现在卷标被作为一个特殊文件保存在根目录中 |
| 0x36 | 8 | "FAT16" | 文件系统类型(File System Type) 根据该磁盘格式该字段的值可以为FATFAT12或FAT16 |
因此各参数初始化如下
```c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>
#define BS_jmpBoot_Offset 0x00 // 跳转指令偏移
#define BS_jmpBoot_Len 3 // 跳转指令长度
#define BS_OEMName_Offset 0x03 // 厂商名称偏移
#define BS_OEMName_Len 8 // 厂商名称长度
#define BPB_BytsPerSec_Offset 0x0B // 每扇区字节数偏移
#define BPB_BytsPerSec_Len 2 // 每扇区字节数长度
#define BPB_SecPerClus_Offset 0x0D // 每簇扇区数偏移
#define BPB_SecPerClus_Len 1 // 每簇扇区数长度
#define BPB_RsvdSecCnt_Offset 0x0E // 保留扇区数 (引导扇区的扇区数)偏移
#define BPB_RsvdSecCnt_Len 2 // 保留扇区数 (引导扇区的扇区数)长度
#define BPB_NumFATs_Offset 0x10 // FAT的份数偏移
#define BPB_NumFATs_Len 1 // FAT的份数长度
#define BPB_RootEntCnt_Offset 0x11 // 根目录可容纳的目录项数偏移
#define BPB_RootEntCnt_Len 2 // 根目录可容纳的目录项数长度
#define BPB_TotSec16_Offset 0x13 // 扇区总数偏移
#define BPB_TotSec16_Len 2 // 扇区总数长度
#define BPB_Media_Offset 0x15 // 介质描述符偏移
#define BPB_Media_Len 1 // 介质描述符长度
#define BPB_FATSz16_Offset 0x16 // 每个FAT表扇区数偏移
#define BPB_FATSz16_Len 2 // 每个FAT表扇区数长度
#define BPB_SecPerTrk_Offset 0x18 // 每磁道扇区数偏移
#define BPB_SecPerTrk_Len 2 // 每磁道扇区数长度
#define BPB_NumHeads_Offset 0x1A // 磁头数偏移
#define BPB_NumHeads_Len 2 // 磁头数长度
#define BPB_HiddSec_Offset 0x1C // 隐藏扇区数偏移
#define BPB_HiddSec_Len 4 // 隐藏扇区数长度
#define BPB_TotSec32_Offset 0x20 // 偏移 如果BPB_TotSec16是0由这个值记录扇区数
#define BPB_TotSec32_Len 4 // 长度 如果BPB_TotSec16是0由这个值记录扇区数
#define BS_DrvNum_Offset 0x24 // int 13h的驱动器号偏移
#define BS_DrvNum_Len 1 // int 13h的驱动器号长度
#define BS_Reservedl_Offset 0x25 // 偏移 未使用
#define BS_Reservedl_Len 1 // 长度 未使用
#define BS_BootSig_Offset 0x26 // 扩展引导标记偏移
#define BS_BootSig_Len 1 // 扩展引导标记长度
#define BS_VolID_Offset 0x27 // 卷序列号偏移
#define BS_VolID_Len 4 // 卷序列号长度
#define BS_VolLab_Offset 0x2B // 卷标偏移
#define BS_VolLab_Len 11 // 卷标长度
#define BS_FileSysType_Offset 0x36 // 文件系统类型偏移
#define BS_FileSysType_Len 8 // 文件系统类型长度
#define DBR_BootCode_Offset 0x3E // 引导代码及其他偏移
#define DBR_BootCode_Len 448 // 引导代码及其他长度
#define DBR_EndMark_Offset 0x1FE // 结束标志偏移
#define DBR_EndMark_Len 2 // 结束标志长度
#define DBR_EndMark 0xAA55 // 结束标志
typedef struct {
short BytsPerSec; // 每扇区字节数
char SecPerClus; // 每簇扇区数
short RsvdSecCnt; // 保留扇区数 (引导扇区的扇区数)
char NumFATs; // FAT的份数
short RootEntCnt; // 根目录可容纳的目录项数
short TotSec16; // 扇区总数
char Media; // 介质描述符
short FATSz16; // 每个FAT表扇区数
short SecPerTrk; // 每磁道扇区数
short NumHeads; // 磁头数
int HiddSec; // 隐藏扇区数
int TotSec32; // 替代扇区数
char DrvNum; // int 13h的驱动器号
char Reservedl; // 未使用
char BootSig; // 扩展引导标记
int VolID; // 卷序列号
int TotalSize; // 总磁盘大小
int current_dir; // 当前目录的首地址
} DISK;
DISK init_disk_attr() {
DISK disk;
disk.BytsPerSec = 0x0200;
disk.SecPerClus = 0x01;
disk.RsvdSecCnt = 0x0001;
disk.NumFATs = 0x01;
disk.RootEntCnt = 0x0200;
disk.TotSec16 = 0x2000;
disk.Media = 0xf8;
disk.FATSz16 = 0x0020;
disk.SecPerTrk = 0x0020;
disk.NumHeads = 0x0040;
disk.HiddSec = 0x00000000;
disk.TotSec32 = 0x00000000;
disk.DrvNum = 0x80;
disk.Reservedl = 0x00;
disk.BootSig = 0x29;
disk.VolID = 0x00000000;
disk.TotalSize = 0x400000;
disk.current_dir = 0x4200;
return disk;
}
```
初始化和格式化磁盘代码如下
```c
void init_file_system(char disk_name[13], DISK disk_attr) {
FILE* fp = fopen(disk_name, "wb");
// 跳转指令
fseek(fp, BS_jmpBoot_Offset, 0);
char jmpBoot[BS_jmpBoot_Len] = { 0xEB, 0x3C, 0x90 };
fwrite(jmpBoot, 1, BS_jmpBoot_Len, fp);
// 厂商名称
fseek(fp, BS_OEMName_Offset, 0);
char OEMName[BS_OEMName_Len] = { 'K', 'e', 'J', 'F', ' ', ' ', ' ', ' ' };
fwrite(OEMName, 1, BS_OEMName_Len, fp);
// 每扇区字节数
fseek(fp, BPB_BytsPerSec_Offset, 0);
fwrite(&disk_attr.BytsPerSec, BPB_BytsPerSec_Len, 1, fp);
// 每簇扇区数
fseek(fp, BPB_SecPerClus_Offset, 0);
fwrite(&disk_attr.SecPerClus, BPB_SecPerClus_Len, 1, fp);
// 保留扇区数 (引导扇区的扇区数)
fseek(fp, BPB_RsvdSecCnt_Offset, 0);
fwrite(&disk_attr.RsvdSecCnt, BPB_RsvdSecCnt_Len, 1, fp);
// FAT的份数
fseek(fp, BPB_NumFATs_Offset, 0);
fwrite(&disk_attr.NumFATs, BPB_NumFATs_Len, 1, fp);
// 根目录可容纳的目录项数
fseek(fp, BPB_RootEntCnt_Offset, 0);
fwrite(&disk_attr.RootEntCnt, BPB_RootEntCnt_Len, 1, fp);
// 扇区总数
fseek(fp, BPB_TotSec16_Offset, 0);
fwrite(&disk_attr.TotSec16, BPB_TotSec16_Len, 1, fp);
// 介质描述符
fseek(fp, BPB_Media_Offset, 0);
fwrite(&disk_attr.Media, BPB_Media_Len, 1, fp);
// 每个FAT表扇区数
fseek(fp, BPB_FATSz16_Offset, 0);
fwrite(&disk_attr.FATSz16, BPB_FATSz16_Len, 1, fp);
// 每磁道扇区数
fseek(fp, BPB_SecPerTrk_Offset, 0);
fwrite(&disk_attr.SecPerTrk, BPB_SecPerTrk_Len, 1, fp);
// 磁头数
fseek(fp, BPB_NumHeads_Offset, 0);
fwrite(&disk_attr.NumHeads, BPB_NumHeads_Len, 1, fp);
// 隐藏扇区数
fseek(fp, BPB_HiddSec_Offset, 0);
fwrite(&disk_attr.HiddSec, BPB_HiddSec_Len, 1, fp);
// 替代扇区数
fseek(fp, BPB_TotSec32_Offset, 0);
fwrite(&disk_attr.TotSec32, BPB_TotSec32_Len, 1, fp);
// int 13h的驱动器号
fseek(fp, BS_DrvNum_Offset, 0);
fwrite(&disk_attr.DrvNum, BS_DrvNum_Len, 1, fp);
// 未使用
fseek(fp, BS_Reservedl_Offset, 0);
fwrite(&disk_attr.Reservedl, BS_Reservedl_Len, 1, fp);
// 扩展引导标记
fseek(fp, BS_BootSig_Offset, 0);
fwrite(&disk_attr.BootSig, BS_BootSig_Len, 1, fp);
// 卷序列号
fseek(fp, BS_VolID_Offset, 0);
fwrite(&disk_attr.VolID, BS_VolID_Len, 1, fp);
// 卷标
fseek(fp, BS_VolLab_Offset, 0);
char VolLab[BS_VolLab_Len] = {'K', 'e', 'J', 'i', 'n', 'g', 'f', 'a', 'n', ' ', ' '};
fwrite(VolLab, 1, BS_VolLab_Len, fp);
// 文件系统类型
fseek(fp, BS_FileSysType_Offset, 0);
char FileSysType[BS_FileSysType_Len] = {'F', 'A', 'T', '1', '6', ' ', ' ', ' '};
fwrite(FileSysType, 1, BS_FileSysType_Len, fp);
// 引导代码等
fseek(fp, DBR_BootCode_Offset, 0);
char BootCode[DBR_BootCode_Len] = { 0 };
fwrite(BootCode, 1, DBR_BootCode_Len, fp);
// 结束标志
fseek(fp, DBR_EndMark_Offset, 0);
short EndMark = DBR_EndMark;
fwrite(&EndMark, DBR_EndMark_Len, 1, fp);
// FAT分区表
fseek(fp, 0x0200, 0);
int FAT_Len = disk_attr.FATSz16 * disk_attr.BytsPerSec * disk_attr.NumFATs; // 每个FAT表扇区数 * 扇区字节数 * FAT的份数
char* FAT_data = (char*)malloc(sizeof(char) * FAT_Len);
fwrite(FAT_data, 1, FAT_Len, fp);
// DATA段
fseek(fp, 0x0200 + FAT_Len, 0);
int DATA_Len = disk_attr.TotalSize - 0x0200 - FAT_Len;
char* DATA_data = (char*)malloc(sizeof(char) * DATA_Len);
fwrite(DATA_data, 1, DATA_Len, fp);
fclose(fp);
}
```
调用这个函数生成.img虚拟磁盘镜像挂载到linux上
```sh
> gcc ./main.c -o main
> ./main
> mkdir /media/cdrom
> sudo mount -o loop KJF_disk.img /media/cdrom
> cd /media/cdrom
```
发现可以正常认盘和使用
查看其二进制
```txt
> hexdump KJF_disk.img -C
00000000 eb 3c 90 4b 65 4a 46 20 20 20 20 00 02 01 01 00 |.<.KeJF .....|
00000010 01 00 02 00 20 f8 20 00 20 00 40 00 00 00 00 00 |.... . . .@.....|
00000020 00 00 00 00 80 00 29 00 00 00 00 4b 65 4a 69 6e |......)....KeJin|
00000030 67 66 61 6e 20 20 46 41 54 31 36 20 20 20 00 00 |gfan FAT16 ..|
00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
00000200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00400000
```
FAT文件格式正确
# 3. 目录
目录项字段定义
| 偏移地址 | 字节数 | 说明 | |
| --------- | ------ | ---------------- | ------------------------------------------------------------ |
| 0x00~0x07 | 8 | 文件名 | |
| 0x08~0x0A | 3 | 扩展名 | |
| 0x0B | 1 | | 00000000(读写) 00000001(只读) 00000010(隐藏) 00000100(系统) 00001000(卷标)00010000(目录) 00100000(归档) |
| 0x0C~0x15 | 10 | 保留 | |
| 0x16~0x17 | 2 | 文件最近修改时间 | |
| 0x18~0x19 | 2 | 文件最近修改日期 | |
| 0x1A~0x1B | 2 | 文件的首簇号 | |
| 0x1C~0x1F | 4 | 文件长度大小 | |
因此代码如下
```c
int mkdir(char dir_name[11], char disk_name[13], DISK disk_attr) {
FILE* fp = fopen(disk_name, "rb+");
unsigned short dir_firstBlockNum = find_free_blocks(disk_attr, fp);
if (dir_firstBlockNum == 0xFFFF) return -1;
fseek(fp, 0x200 + dir_firstBlockNum * 2, 0);
short new_index = 0xFFFF;
fwrite(&new_index, 2, 1, fp);
int start_byte = disk_attr.current_dir;
int byte_line_num = 0;
while (byte_line_num < disk_attr.BytsPerSec) {
fseek(fp, start_byte + byte_line_num, 0);
int byte_line[4] = { 0 };
fread(byte_line, 4, 3, fp);
if (!byte_line[0] && !byte_line[1] && !byte_line[2]) break;
byte_line_num += 0x20;
}
if (byte_line_num >= disk_attr.BytsPerSec) return -1;
fseek(fp, start_byte + byte_line_num, 0);
fwrite(dir_name, 1, 11, fp);
short dir_attr_byte = 0b00010000;
fwrite(&dir_attr_byte, 1, 1, fp);
short dir_reserved_byte[6] = { 0 };
fwrite(dir_reserved_byte, 2, 5, fp);
struct tm time = get_time();
short dir_time_byte = time.tm_hour * 2048 + time.tm_min * 32 + time.tm_sec / 2;
fwrite(&dir_time_byte, 2, 1, fp);
short dir_date_byte = (time.tm_year + 1900 - 1980) * 512 + time.tm_mon * 32 + time.tm_mday;
fwrite(&dir_date_byte, 2, 1, fp);
fwrite(&dir_firstBlockNum, 2, 1, fp);
short dir_size = disk_attr.BytsPerSec * disk_attr.SecPerClus;
fwrite(&dir_size, 2, 1, fp);
int new_block = 0x7800 + disk_attr.BytsPerSec * disk_attr.SecPerClus * dir_firstBlockNum;
fseek(fp, new_block, 0);
char dot[11] = { '.', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' };
fwrite(dot, 1, 11, fp);
fwrite(&dir_attr_byte, 1, 1, fp);
fwrite(dir_reserved_byte, 2, 5, fp);
fwrite(&dir_time_byte, 2, 1, fp);
fwrite(&dir_date_byte, 2, 1, fp);
short dir_oriBlock_byte = 0;
fwrite(&dir_oriBlock_byte, 2, 1, fp);
unsigned int dir_oriSize = 0;
fwrite(&dir_oriSize, 4, 1, fp);
fseek(fp, new_block + 0x20, 0);
char dotdot[11] = { '.', '.', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' };
fwrite(dotdot, 1, 11, fp);
fwrite(&dir_attr_byte, 1, 1, fp);
fwrite(dir_reserved_byte, 2, 5, fp);
short dir_oriTime_byte = 0;
fwrite(&dir_oriTime_byte, 2, 1, fp);
short dir_oriDate_byte = (1970 - 1980 + 1900) * 512 + 1 * 32 + 1;
fwrite(&dir_oriDate_byte, 2, 1, fp);
fwrite(&dir_oriBlock_byte, 2, 1, fp);
fwrite(&dir_oriSize, 4, 1, fp);
fclose(fp);
return 0;
}
struct tm get_time() {
struct timeval tv;
struct timezone tz;
struct tm *t;
gettimeofday(&tv, &tz);
t = localtime(&tv.tv_sec);
return *t;
}
```
# 4. 文件
```c
int touch(char file_name[11], char disk_name[13], DISK disk_attr) {
FILE* contentFile = fopen("./data.txt", "r");
char *content = (char*)malloc(2000 * sizeof(char));
fread(content, 1, 2000, contentFile);
fclose(contentFile);
FILE* fp = fopen(disk_name, "rb+");
int file_blockNum = strlen(content) / (disk_attr.BytsPerSec * disk_attr.SecPerClus) + 1;
unsigned short* index = (short*)malloc(sizeof(short) * file_blockNum);
for (int i = 0; i < file_blockNum; i++) {
index[i] = find_free_blocks(disk_attr, fp);
}
for (int i = 0; i < file_blockNum - 1; i++) {
fseek(fp, 0x200 + index[i] * 2, 0);
fwrite(&index[i + 1], 2, 1, fp);
}
fseek(fp, 0x200 + index[file_blockNum - 1] * 2, 0);
short last_index = 0xFFFF;
fwrite(&last_index, 2, 1, fp);
int start_byte = disk_attr.current_dir;
int byte_line_num = 0;
while (byte_line_num < disk_attr.BytsPerSec) {
fseek(fp, start_byte + byte_line_num, 0);
int byte_line[4] = { 0 };
fread(byte_line, 4, 3, fp);
if (!byte_line[0] && !byte_line[1] && !byte_line[2]) break;
byte_line_num += 0x20;
}
if (byte_line_num >= disk_attr.BytsPerSec) return -1;
fseek(fp, start_byte + byte_line_num, 0);
fwrite(file_name, 1, 11, fp);
short file_attr_byte = 0b00000000;
fwrite(&file_attr_byte, 1, 1, fp);
short file_reserved_byte[6] = { 0 };
fwrite(file_reserved_byte, 2, 5, fp);
struct tm time = get_time();
short file_time_byte = time.tm_hour * 2048 + time.tm_min * 32 + time.tm_sec / 2;
fwrite(&file_time_byte, 2, 1, fp);
short file_date_byte = (time.tm_year + 1900 - 1980) * 512 + time.tm_mon * 32 + time.tm_mday;
fwrite(&file_date_byte, 2, 1, fp);
fwrite(&index[0], 2, 1, fp);
unsigned int file_size = strlen(content);
fwrite(&file_size, 4, 1, fp);
for (int i = 0; i < file_blockNum; i++) {
int new_block = 0x7800 + disk_attr.BytsPerSec * disk_attr.SecPerClus * index[i];
fseek(fp, new_block, 0);
fwrite(content,
file_size > disk_attr.BytsPerSec * disk_attr.SecPerClus ? disk_attr.BytsPerSec * disk_attr.SecPerClus : file_size,
1,
fp
);
content += disk_attr.BytsPerSec * disk_attr.SecPerClus;
file_size -= disk_attr.BytsPerSec * disk_attr.SecPerClus;
}
fclose(fp);
return 0;
}
```