6

c读取ext2表和位图信息

 3 years ago
source link: https://blog.popkx.com/c-read-ext2-tables-and-bitmap-information/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
    本节根据前面几讲介绍的 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
  • 这里以获取 超级块信息 和 块组描述符 为例,其他的表信息获取类似。

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK