praks411
praks411

Reputation: 1992

Seeking large file in c++ on windows

I'm writing a small utility to parse xfs filesystem on windows. For small size image <5GB my utility is working fine: I'm able to list all files and directories. But when I try to parse large xfs image > 30GB. It is giving wrong results. I'm using _fseeki64 and _ftelli64 for seeking and fread for reading particular block. One of thing I've notice is that _fseeki64 is not wroking properly. Below is my seek function which seek to particular group number and block number.

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;
    }

However the above function is taking me to wrong postion. For example when I want to seek to group number = 2 with m_fileSystemInfo.SizeOfBlockGroup = 2043982 and m_fileSystemInfo.BlockSize = 4096.

I'm expecting currPrt = 2043982*4096*2 = 16744300544 (0x3E609C000), But _ftelli64 is returning (0xE609C000). Please suggest what could be going wrong. Also please advice what is the best way to deal with large files on windows in c++.

Update::

I found that the seekOffset is getting limited to 8154365952 (0x1e609c000) instead of actual value of 16744300544 (0x3e609c000) inspite of me using __int64.

So.

_int64 seekOff = (_int64)(grpNum*m_fileSystemInfo.SizeOfBlockGroup*m_fileSystemInfo.BlockSize) = 2*2043982*4096 is giving 8154365952 instead of 16744300544.

I'm not sure what could the reason as everything is in __int64.

Upvotes: 3

Views: 1395

Answers (2)

praks411
praks411

Reputation: 1992

Apparently the problem was with calculation of seek offset. It was generating integer overflow. Hence I have to convert everything to __int64 even-though I'm working on 64 bits application. I was thinking compiler might be able to do this for me.

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

which works fine with _fseeki64 and __ftelli64.

Upvotes: 4

shoosh
shoosh

Reputation: 78914

Your best bet is to use Win32 API directly and not go through the C RunTime.

Use CreateFile to open the file and SetFilePointerEx to seek

The functions you're calling will end up calling these APIs anyway. In Visual studio you have the CRT code so you can step into _fseeki64 and possibly see where it goes wrong.

Upvotes: 2

Related Questions