3

我正在编写一个小实用程序来解析 Windows 上的 xfs 文件系统。对于 <5GB 的小尺寸图像,我的实用程序运行良好:我能够列出所有文件和目录。但是当我尝试解析 > 30GB 的大型 xfs 图像时。它给出了错误的结果。我正在使用 _fseeki64 和 _ftelli64 来寻找和 fread 来阅读特定的块。我注意到的一件事是 _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 和 m_fileSystemInfo.BlockSize = 4096 对 number = 2 进行分组时。

我期待 currPrt = 2043982*4096*2 = 16744300544 (0x3E609C000),但 _ftelli64 正在返回 (0xE609C000)。请提出可能出了什么问题。还请建议在 c++ 中处理 Windows 上的大文件的最佳方法是什么。

更新::

尽管我使用 __int64,但我发现 seekOffset 被限制为 8154365952 (0x1e609c000) 而不是实际值 16744300544 (0x3e609c000)。

所以。

_ int64 seekOff = ( _int64)(grpNum*m_fileSystemInfo.SizeOfBlockGroup*m_fileSystemInfo.BlockSize) = 2*2043982*4096 给出 8154365952 而不是 16744300544。

我不确定原因是什么,因为一切都在 __int64 中。

4

2 回答 2

4

显然问题出在寻找偏移量的计算上。它正在产生整数溢出。因此,即使我正在开发 64 位应用程序,我也必须将所有内容都转换为 __int64。我在想编译器也许可以为我做这件事。

__int64 grpNum = 2;
__int64 sizeOfBlockGroup = 2043982;
__int64 blockSize = 4096;
__int64 seekOffSet = grpNum*sizeOfBlockGroup*blockSize;

这适用于 _fseeki64 和 __ftelli64。

于 2013-11-15T13:15:13.350 回答
2

您最好的选择是直接使用 Win32 API,而不是通过 C RunTime。

用于CreateFile打开文件并SetFilePointerEx查找

无论如何,您调用的函数最终都会调用这些 API。在 Visual Studio 中,您拥有 CRT 代码,因此您可以进入_fseeki64并可能查看哪里出错了。

于 2013-11-15T11:20:09.023 回答