3

Windows で xfs ファイルシステムを解析するための小さなユーティリティを作成しています。5GB 未満の小さなサイズのイメージの場合、ユーティリティは正常に動作します。すべてのファイルとディレクトリを一覧表示できます。しかし、30 GB を超える大きな xfs イメージを解析しようとすると、. それは間違った結果を与えています。特定のブロックを読み取るためにシークと fread に _fseeki64 と _ftelli64 を使用しています。私が気づいたことの 1 つは、_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 でグループ番号 = 2 をシークしたい場合。

私は currPrt = 2043982*4096*2 = 16744300544 (0x3E609C000) を期待していますが、_ftelli64 は (0xE609C000) を返しています。何が問題なのかを提案してください。また、Windows で大きなファイルを C++ で処理する最善の方法を教えてください。

アップデート::

__int64 を使用しているにもかかわらず、seekOffset が実際の値 16744300544 (0x3e609c000) ではなく 8154365952 (0x1e609c000) に制限されていることがわかりました。

そう。

_ int64 seekOff = ( _int64)(grpNum*m_fileSystemInfo.SizeOfBlockGroup*m_fileSystemInfo.BlockSize) = 2*2043982*4096 は、16744300544 ではなく 8154365952 を与えています。

すべてが__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 に答える