in IORequestGenerator/IORequestGenerator.cpp [1735:1878]
bool IORequestGenerator::_CreateFile(UINT64 ullFileSize, const char *pszFilename, bool fZeroBuffers, bool fVerbose) const
{
bool fSlowWrites = false;
PrintVerbose(fVerbose, "Creating file '%s' of size %I64u.\n", pszFilename, ullFileSize);
//enable SE_MANAGE_VOLUME_NAME privilege, required to set valid size of a file
if (!SetPrivilege(SE_MANAGE_VOLUME_NAME, "WARNING:"))
{
PrintError("WARNING: Could not set privileges for setting valid file size; will use a slower method of preparing the file\n", GetLastError());
fSlowWrites = true;
}
// there are various forms of paths we do not support creating subdir hierarchies
// for - relative and unc paths specifically. this is fine, and not neccesary to
// warn about. we can add support in the future.
DWORD dwError = _CreateDirectoryPath(pszFilename);
if (dwError != ERROR_SUCCESS && dwError != ERROR_NOT_SUPPORTED)
{
PrintError("WARNING: Could not create intermediate directory (error code: %u)\n", dwError);
}
// create handle to the file
HANDLE hFile = CreateFile(pszFilename,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
nullptr,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
nullptr);
if (INVALID_HANDLE_VALUE == hFile)
{
PrintError("Could not create the file (error code: %u)\n", GetLastError());
return false;
}
if (ullFileSize > 0)
{
LARGE_INTEGER li;
li.QuadPart = ullFileSize;
LARGE_INTEGER liNewFilePointer;
if (!SetFilePointerEx(hFile, li, &liNewFilePointer, FILE_BEGIN))
{
PrintError("Could not set file pointer during file creation when extending file (error code: %u)\n", GetLastError());
CloseHandle(hFile);
return false;
}
if (liNewFilePointer.QuadPart != li.QuadPart)
{
PrintError("File pointer improperly moved during file creation when extending file\n");
CloseHandle(hFile);
return false;
}
//extends file (warning! this is a kind of "reservation" of space; valid size of the file is still 0!)
if (!SetEndOfFile(hFile))
{
PrintError("Error setting end of file (error code: %u)\n", GetLastError());
CloseHandle(hFile);
return false;
}
//try setting valid size of the file (privileges for that are enabled before CreateFile)
if (!fSlowWrites && !SetFileValidData(hFile, ullFileSize))
{
PrintError("WARNING: Could not set valid file size (error code: %u); trying a slower method of filling the file"
" (this does not affect performance, just makes the test preparation longer)\n",
GetLastError());
fSlowWrites = true;
}
//if setting valid size couldn't be performed, fill in the file by simply writing to it (slower)
if (fSlowWrites)
{
li.QuadPart = 0;
if (!SetFilePointerEx(hFile, li, &liNewFilePointer, FILE_BEGIN))
{
PrintError("Could not set file pointer during file creation (error code: %u)\n", GetLastError());
CloseHandle(hFile);
return false;
}
if (liNewFilePointer.QuadPart != li.QuadPart)
{
PrintError("File pointer improperly moved during file creation\n");
CloseHandle(hFile);
return false;
}
UINT32 ulBufSize;
UINT64 ullRemainSize;
ulBufSize = 1024*1024;
if (ullFileSize < (UINT64)ulBufSize)
{
ulBufSize = (UINT32)ullFileSize;
}
vector<BYTE> vBuf(ulBufSize);
for (UINT32 i=0; i<ulBufSize; ++i)
{
vBuf[i] = fZeroBuffers ? 0 : (BYTE)(i&0xFF);
}
ullRemainSize = ullFileSize;
while (ullRemainSize > 0)
{
DWORD dwBytesWritten;
if ((UINT64)ulBufSize > ullRemainSize)
{
ulBufSize = (UINT32)ullRemainSize;
}
if (!WriteFile(hFile, &vBuf[0], ulBufSize, &dwBytesWritten, NULL))
{
PrintError("Error while writng during file creation (error code: %u)\n", GetLastError());
CloseHandle(hFile);
return false;
}
if (dwBytesWritten != ulBufSize)
{
PrintError("Improperly written data during file creation\n");
CloseHandle(hFile);
return false;
}
ullRemainSize -= ulBufSize;
}
}
}
//if compiled with debug support, check file size
#ifndef NDEBUG
LARGE_INTEGER li;
if( GetFileSizeEx(hFile, &li) )
{
assert(li.QuadPart == (LONGLONG)ullFileSize);
}
#endif
CloseHandle(hFile);
return true;
}