我正在编写一个小工具来解析Windows上的xfs文件系统。对于小尺寸图像<5GB,我的实用程序工作正常:我能够列出所有文件和目录。但是当我尝试解析 30GB>的大型 xfs 图像时。它给出了错误的结果。我正在使用_fseeki64和_ftelli64来寻找和恐惧来阅读特定的块。我注意到的一件事是_fseeki64无法正常工作。下面是我的搜索函数,它寻求特定的组号和块号。
int FileSystemReadXFS::SeekToGroupBlock(uint16_t grpNum, uint64_t blockNum)
{
int error = -1;
//Seek to beginning
if(_fseeki64(m_fileSystemInfo.fp, (__int64)0, SEEK_SET) != 0)
{
PRINT_SEEK_ERROR;
goto BAILOUT;
}
__int64 currPtr = 0;
//Seek to destination group
if(grpNum > 0)
{
if(_fseeki64(m_fileSystemInfo.fp, (__int64)(grpNum*m_fileSystemInfo.SizeOfBlockGroup*m_fileSystemInfo.BlockSize), SEEK_SET))
{
PRINT_SEEK_ERROR;
goto BAILOUT;
}
currPtr = _ftelli64(m_fileSystemInfo.fp);
}
//Seek to destination block in group
if(blockNum > 0)
{
if(_fseeki64(m_fileSystemInfo.fp, (__int64)(blockNum*m_fileSystemInfo.BlockSize), SEEK_CUR))
{
PRINT_SEEK_ERROR;
goto BAILOUT;
}
currPtr = _ftelli64(m_fileSystemInfo.fp);
}
error = 0;
BAILOUT:
return error;
}
但是,上述功能将我带到了错误的位置。例如,当我想使用 m_fileSystemInfo.SizeOfBlockGroup = 2043982 寻求分组编号 = 2和 m_fileSystemInfo.块大小 = 4096。
我期待 currPrt = 2043982*4096*2 = 16744300544 (0x3E609C000),但_ftelli64正在返回 (0xE609C000)。请建议可能出现的问题。另外,请告知在 c++ 中处理 Windows 上的大文件的最佳方法是什么。
更新::
我发现 seekOffset 被限制为8154365952 (0x1e609c000) 而不是实际16744300544的价值(0x3e609c000)尽管我使用__int64。
所以。
_int64 seekOff = (_int64)(grpNum*m_fileSystemInfo.SizeOfBlockGroup*m_fileSystemInfo.BlockSize) = 2*2043982*4096 是给予8154365952而不是16744300544。
我不确定是什么原因,因为一切都在__int64。
显然,问题在于寻道偏移量的计算。它正在生成整数溢出。因此,我必须将所有内容转换为__int64即使我正在处理 64 位应用程序。我在想编译器也许可以为我做到这一点。
__int64 grpNum = 2;
__int64 sizeOfBlockGroup = 2043982;
__int64 blockSize = 4096;
__int64 seekOffSet = grpNum*sizeOfBlockGroup*blockSize;
适用于_fseeki64和__ftelli64。
最好的办法是直接使用 Win32 API,而不是通过 C 运行时。
使用CreateFile
打开文件并SetFilePointerEx
查找
无论如何,您正在调用的函数最终都会调用这些 API。在Visual Studio中,您有CRT代码,因此您可以进入_fseeki64
并可能查看出错的地方。