本节根据前面几讲介绍的 ext2 的数据结构,建立了几个结构体,用于存储 ext2 的各种表和位图信息。
为了读写方便,在 MFile 模块添加了如下几个函数。
unsigned char MFileReadByte(off_t liFrom)
{
unsigned char rtn = 0;
if(-1 == MFileRead(&rtn, 1, liFrom)){
printf("%s read error, Message: %s\n", __FUNCTION__, strerror(errno));
return MFILE_READ;
}
return rtn;
}
int MFileWriteByte(off_t liFrom, unsigned char ucWriteData)
{
if(-1 == MFileWrite(liFrom, &ucWriteData, 1)){
printf("%s write error, Message: %s\n", __FUNCTION__, strerror(errno));
return MFILE_WRITE;
}
return MFILE_OK;
}
// 将 2 字节的整数拆分成 2 个 1字节的整数,并且按照小端顺序写入地址 liFrom
int MFileWriteUint16InByte(off_t liFrom, uint16 data)
{
uint8 tmp = 0;
tmp = (uint8)(data&0xff);
MFileWriteByte(liFrom, tmp);
tmp = (uint8)(data>>8);
MFileWriteByte(liFrom+1, tmp);
return MFILE_OK;
}
// 将 4 字节的整数拆分成 4 个 1字节的整数,并且按照小端顺序写入地址 liFrom
int MFileWriteUint32InByte(off_t liFrom, uint32 data)
{
uint8 tmp = 0;
tmp = (uint8)(data&0xff);
MFileWriteByte(liFrom, tmp);
tmp = (uint8)((data>>8)&0xff);
MFileWriteByte(liFrom+1, tmp);
tmp = (uint8)((data>>16)&0xff);
MFileWriteByte(liFrom+2, tmp);
tmp = (uint8)((data>>24)&0xff);
MFileWriteByte(liFrom+3, tmp);
return MFILE_OK;
}
int MFileWriteStringInByte(off_t liFrom, char* str)
{
uint32 i = 0;
while('\0' != *(str+i)){
MFileWriteByte(liFrom+i, *(str+i));
i++;
}
return MFILE_OK;
}
// 读 4 字节,因为读到的是小端,所以要转换下
uint32 MFileRead4Byte(off_t liFrom)
{
uint32 tmp = 0;
uint32 rtn = 0;
tmp = (uint32)MFileReadByte(liFrom);
rtn |= tmp;
tmp = (uint32)MFileReadByte(liFrom+1);
rtn |= tmp<<8;
tmp = (uint32)MFileReadByte(liFrom+2);
rtn |= tmp<<16;
tmp = (uint32)MFileReadByte(liFrom+3);
rtn |= tmp<<24;
return rtn;
}
// 读 2 字节,因为读到的是小端,所以要转换下
uint16 MFileRead2Byte(off_t liFrom)
{
uint16 tmp = 0;
uint16 rtn = 0;
tmp = (uint16)MFileReadByte(liFrom);
rtn |= tmp;
tmp = (uint16)MFileReadByte(liFrom+1);
rtn |= tmp<<8;
return rtn;
}
新建 MExt2 模块
MExt2.h
#include "../include/MFile.h"
// Bm -> Bitmap
// Loc -> Location
// dir -> directories
#define MEXT2_OK 0
#define MEXT2_INIT -1
#define MEXT2_INFO -2
#define MEXT2_IDLEBITMAP -3
#define MEXT2_IDLEINODEBLOCK -4
// 块组描述符表
typedef struct{
uint32 blockBmLoc;
uint32 inodeBmLoc;
uint32 inodeTable;
uint16 freeBlocks;
uint16 freeInodes;
uint16 directories;
} sGroupDescriptor;
// inode 表
typedef struct{
uint16 st_mode;
uint16 user;
uint32 size;
uint32 atime;
uint32 ctime;
uint32 mtime;
uint32 dtime;
uint16 group;
uint16 links;
uint32 ocupiedBlocks;
uint32 flags;
uint32 osInfo;
uint32 blocks[15];
} sInode;
// 数据块
typedef struct{
uint32 inodeIndex;
uint16 recordLen;
uint8 fileNameLen;
uint8 fileType;
uint8 fileName[256]; // malloc 根据 fileNameLen
}sDataBlock;
// super block
typedef struct
{
uint32 inodes;
uint32 blocks;
uint32 reservedBlocks;
uint32 freeBlocks;
uint32 freeInodes;
uint32 firstBlock;
uint32 blockSize; // 1024<<blockSize = 实际块大小(Bytes)
uint32 log; // 给 0 就成
uint32 blocksPerGroup;
uint32 framsPerGroup;
uint32 inodesPerGroup;
uint32 lastMountTime;
uint32 lastWriteTime;
uint16 mountNum;
uint16 maxMountNum;
uint16 magic;
uint16 fsState;
uint16 errBehav;
uint16 minorRev;
uint32 lastCheck;
uint32 checkIntvl;
uint32 osType;
uint32 majorRev;
uint16 reserverdBlocksUid;
uint16 reserverdBlocksGid;
uint32 firstInode;
uint16 inodeSize;
uint16 blockGroupIndex;
uint8 compatibleFeatures[12];
uint8 uuid[16];
uint8 volmName[16];
// 余下的填充零
} sSuperBlock;
MExt2.c
#include "../include/MExt2.h"
static char m_fileName[255] = {0};
static sSuperBlock s_sprBlk;
static sGroupDescriptor s_grpDescrpt;
static int sGetSuperBlockInfo(sSuperBlock* pSuperBlock);
static int sGetGroupDescriptorInfo(sGroupDescriptor* pGrpDescrpt);
int InitMExt2(char* cpFileName)
{
if(0 > MFileOpen(cpFileName)){
printf("InitMExt2 error, MFileOpen failed\n");
return MEXT2_INIT;
}
sGetSuperBlockInfo(&s_sprBlk);
sGetGroupDescriptorInfo(&s_grpDescrpt);
return MEXT2_OK;
}
// 未加错误判断
// 超级块,占一个块
static int sGetSuperBlockInfo(sSuperBlock* pSuperBlock)
{
pSuperBlock->inodes = MFileRead4Byte(0x400);
pSuperBlock->blocks = MFileRead4Byte(0x400 + 4);
pSuperBlock->reservedBlocks = MFileRead4Byte(0x400 + 4*2);
pSuperBlock->freeBlocks = MFileRead4Byte(0x400 + 4*3);
pSuperBlock->freeInodes = MFileRead4Byte(0x400 + 4*4);
pSuperBlock->firstBlock = MFileRead4Byte(0x400 + 4*5);
pSuperBlock->blockSize = 1024<<MFileRead4Byte(0x400 + 4*6);
pSuperBlock->blocksPerGroup = MFileRead4Byte(0x420);
pSuperBlock->framsPerGroup = MFileRead4Byte(0x420 + 4);
pSuperBlock->inodesPerGroup = MFileRead4Byte(0x420 + 4*2);
pSuperBlock->inodeSize = MFileRead2Byte(0x458);
pSuperBlock->blockGroupIndex = MFileRead2Byte(0x458 + 2);
return MEXT2_OK;
}
int GetSuperBlockInfo(sSuperBlock* pSuperBlock)
{
*pSuperBlock = s_sprBlk;
return MEXT2_OK;
}
// 未完美错误判断
// 块组
static int sGetGroupDescriptorInfo(sGroupDescriptor* pGrpDescrpt)
{
uint32 start = 0;
// 首先获取起点,即超级块结束的位置
start = 0x400 + 1024;
pGrpDescrpt->blockBmLoc = MFileRead4Byte(start);
pGrpDescrpt->inodeBmLoc = MFileRead4Byte(start + 4);
pGrpDescrpt->inodeTable = MFileRead4Byte(start + 4*2);
pGrpDescrpt->freeBlocks = MFileRead2Byte(start + 4*3);
pGrpDescrpt->freeInodes = MFileRead2Byte(start + 4*3 + 2);
pGrpDescrpt->directories = MFileRead4Byte(start + 4*3 + 2*2);
return MEXT2_OK;
}
int GetGroupDescriptorInfo(sGroupDescriptor* pGrpDescrpt)
{
*pGrpDescrpt = s_grpDescrpt;
return MEXT2_OK;
}
// 获取 inode
int sGetInodeInfo(off_t addr, sInode* pSInode)
{
int i = 0;
pSInode->st_mode = MFileRead2Byte(addr);
pSInode->user = MFileRead2Byte(addr + 2*1);
pSInode->size = MFileRead4Byte(addr + 2*2);
pSInode->group = MFileRead2Byte(addr + 24);
pSInode->links = MFileRead2Byte(addr + 24 + 2);
pSInode->ocupiedBlocks = MFileRead4Byte(addr + 24 + 2*2 );
for(i=0; i<15; i++){
pSInode->blocks[i] = MFileRead4Byte(addr + 40 + 4*i);
}
return MEXT2_OK;
}
这里有函数名字前面有个 s,是因为计划将这些函数作为静态函数使用。目前为了开发调试方便,有的未加 static 关键字。
main.c
#include "../include/MExt2.h"
char fileName[] = "../../tmp/disk";
sSuperBlock sb;
sGroupDescriptor sg;
int main()
{
InitMExt2(fileName);
printf("GetSuperBlockInfo: ----------------------\n");
GetSuperBlockInfo(&sb);
printf("inodes: %ld\n", sb.inodes);
printf("blocks: %ld\n", sb.blocks);
printf("blockSize: %d\n", sb.blockSize);
printf("reservedBlocks: %ld\n", sb.reservedBlocks);
printf("freeBlocks: %ld\n", sb.freeBlocks);
printf("freeInodes: %ld\n", sb.freeInodes);
printf("firstBlock: %ld\n", sb.firstBlock);
printf("blocksPerGroup: %ld\n", sb.blocksPerGroup);
printf("framsPerGroup: %ld\n", sb.framsPerGroup);
printf("inodesPerGroup: %ld\n", sb.inodesPerGroup);
printf("inodeSize: %d\n", sb.inodeSize);
printf("blockGroupIndex: %d\n", sb.blockGroupIndex);
printf("GetGroupDescriptorInfo: ----------------------\n");
GetGroupDescriptorInfo(&sg);
printf("blockBmLoc: %d\n", sg.blockBmLoc);
printf("inodeBmLoc: %d\n", sg.inodeBmLoc);
printf("inodeTable: %d\n", sg.inodeTable);
printf("freeBlocks: %d\n", sg.freeBlocks);
printf("freeInodes: %d\n", sg.freeInodes);
printf("directories: %d\n", sg.directories);
return 0;
}
$ ./main.out
GetSuperBlockInfo: ----------------------
inodes: 128
blocks: 1024
blockSize: 1024
reservedBlocks: 51
freeBlocks: 986
freeInodes: 117
firstBlock: 1
blocksPerGroup: 8192
framsPerGroup: 8192
inodesPerGroup: 128
inodeSize: 128
blockGroupIndex: 0
GetGroupDescriptorInfo: ----------------------
blockBmLoc: 6
inodeBmLoc: 7
inodeTable: 8
freeBlocks: 986
freeInodes: 117
directories: 2
- 这里以获取 超级块信息 和 块组描述符 为例,其他的表信息获取类似。