最近在采用ext2read读取读硬盘里ext2文件系统分区文件的数据,该开源库是读取MBR分区下的各分区数据,对ext2read库里面的主要接口大概整理下:
1.int Ext2Read::scan_partitions(char *path, int diskno)
scanMBR分区分区头及4个分区表,获取各分区数据(分区起始扇区,分区总的扇区数,如果是GPT分区,需根据情况分析。
2. Ext2Partition::Ext2Partition(lloff_t size, lloff_t offset, int ssize, FileHandle phandle, LogicalVolume *vol)
size:分区末尾扇区号
offset:分区起始扇区号
phandle:文件句柄
LogicalVolume :这个我没有用到(NULL),应该是有无逻辑分区。。。
该构造函数可以获取root节点的inode表中数据(Ext2File)
GPT分区只要确定了分区起始扇区和分区扇区数(该数值貌似库里面并没有用到),就可调用此接口,如果分区的镜像文件直接读取的分区数据,offset置为0即可。
3. bool Ext2CopyProcess::copy_file(QString &destfile, Ext2File *srcfile)
该接口为拷贝文件到自己设定的路径,不过它实现的是从当前目录下拷贝文件,而不是从根目录搜索文件,再保存。其中srcfile为当前文件的inode表项
4.bool Ext2CopyProcess::copy_folder(QString &path, Ext2File *parent)
同样,从当前目录下拷贝目录中的文件夹。parent为当前目录的的inode表项。
如若从root开始搜索文件
Ext2File *Ext2Partition::read_dir(EXT2DIRENT *dirent)读取目录文件的数据块数据,并获取一个文件/目录的项的inode表项
if(!dirent->dirbuf)
{
dirent->dirbuf = (EXT2_DIR_ENTRY *) new char[blocksize]; //new出一个数组
if(!dirent->dirbuf)
return NULL;
ret = read_data_block(&dirent->parent->inode, dirent->next_block, dirent->dirbuf);
if(ret < 0)
return NULL;
dirent->next_block++;
}
again:
if(!dirent->next)
dirent->next = dirent->dirbuf;
else
{
pos = (char *) dirent->next;
dirent->next = (EXT2_DIR_ENTRY *)(pos + dirent->next->rec_len);
if(IS_BUFFER_END(dirent->next, dirent->dirbuf, blocksize))
{
dirent->next = NULL;
if(dirent->read_bytes < dirent->parent->file_size)
{
//LOG("DIR: Reading next block %d parent %s\n", dirent->next_block, dirent->parent->file_name.c_str());
ret = read_data_block(&dirent->parent->inode, dirent->next_block, dirent->dirbuf);
if(ret < 0)
return NULL;
dirent->next_block++;
goto again;
}
return NULL;
}
}
dirent->read_bytes += dirent->next->rec_len;
filename.assign(dirent->next->name, dirent->next->name_len);
if((filename.compare(".") == 0) ||
(filename.compare("..") == 0))
goto again; //以上,读取目录文件中的一个文件夹/文件夹项,保存在dirent->next中
newEntry = read_inode(dirent->next->inode); //读取该文件夹/文件项的inode表项内容
if(!newEntry)
{
LOG("Error reading Inode %d parent inode %d.\n", dirent->next->inode, dirent->parent->inode_num);
return NULL;
}
newEntry->file_type = dirent->next->filetype;
newEntry->file_name = filename;
return newEntry; //返回inode表项的内容(Ext2File )
如若需要从根目录下查找一个文件,需要多次调用read_dir,并判断是否是所要查找的文件夹/文件。 目录文件里面含有文件夹/文件标识,并通过判断文件夹/文件名称来判断就可以。
调试过程中遇到的问题:
读取数据块中的数据时,存放数据的内存区域必须要大于等于blocksize,否则保存数据时会出错。
即int Ext2Partition::read_data_block(EXT2_INODE *ino, lloff_t lbn, void *buf)中buf new出来的空间必须大于等于blocksize,其实blocksize就可以了,如果读一次即存储的话。如果new char[filesize],在数据边读边存情况下没有问题,当文件大小低于blocksize时,读取一个数据块就会出错。