?

最近在采用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))
??????美国高防vps? 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时,读取一个数据块就会出错。

?