2019-07-23 23:05:20 +01:00
|
|
|
#include "../file.h"
|
|
|
|
#include "../directory.h"
|
|
|
|
|
|
|
|
#include <sstream>
|
|
|
|
#include <io.h>
|
|
|
|
#include <windows.h>
|
|
|
|
|
|
|
|
|
|
|
|
void throwFileError()
|
|
|
|
{
|
|
|
|
char msgBuf[32*1024];
|
|
|
|
memset( msgBuf, 0, sizeof(msgBuf) );
|
|
|
|
DWORD dw = GetLastError();
|
|
|
|
FormatMessage(
|
|
|
|
FORMAT_MESSAGE_FROM_SYSTEM,
|
|
|
|
NULL,
|
|
|
|
dw,
|
|
|
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
|
|
|
(LPTSTR) &msgBuf,
|
|
|
|
sizeof(msgBuf),
|
|
|
|
NULL );
|
|
|
|
throw std::runtime_error( msgBuf );
|
|
|
|
}
|
|
|
|
|
|
|
|
void makeWin32OpenFlags(
|
|
|
|
unsigned int oflag,
|
|
|
|
DWORD* const dwDesiredAccess,
|
|
|
|
DWORD* const dwCreationDisposition,
|
|
|
|
DWORD* const dwShareMode )
|
|
|
|
{
|
|
|
|
*dwDesiredAccess = 0;
|
|
|
|
*dwCreationDisposition = CREATE_ALWAYS;
|
|
|
|
if( oflag & File::ofRead )
|
|
|
|
{
|
|
|
|
*dwDesiredAccess = GENERIC_READ & ~SYNCHRONIZE;
|
|
|
|
*dwCreationDisposition = OPEN_EXISTING;
|
|
|
|
*dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
|
|
|
|
}
|
|
|
|
if( oflag & File::ofWrite )
|
|
|
|
{
|
|
|
|
*dwDesiredAccess |= GENERIC_WRITE & ~SYNCHRONIZE;
|
|
|
|
*dwCreationDisposition = CREATE_ALWAYS;
|
|
|
|
*dwShareMode = FILE_SHARE_READ;
|
|
|
|
}
|
|
|
|
if( oflag & File::ofAppend )
|
|
|
|
*dwCreationDisposition = OPEN_ALWAYS;
|
|
|
|
if( oflag & File::ofNoTruncate)
|
|
|
|
*dwCreationDisposition = OPEN_ALWAYS;
|
|
|
|
if( oflag & File::ofOpenExisting )
|
|
|
|
*dwCreationDisposition = OPEN_EXISTING;
|
|
|
|
if( oflag & File::ofCreateNew )
|
|
|
|
*dwCreationDisposition = CREATE_NEW;
|
|
|
|
}
|
|
|
|
|
|
|
|
File::File():
|
|
|
|
AbstractOutputStream(),
|
|
|
|
m_impl( INVALID_HANDLE_VALUE ),
|
|
|
|
m_name ( "" ),
|
|
|
|
m_pos(0)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2019-08-16 19:36:20 +01:00
|
|
|
File::File( const char* fName, unsigned int oflag, unsigned int systemDependentFlags ) /* throw ( std::runtime_error ) */:
|
2019-07-23 23:05:20 +01:00
|
|
|
AbstractOutputStream(),
|
|
|
|
m_impl( INVALID_HANDLE_VALUE ),
|
|
|
|
m_name ( fName ),
|
|
|
|
m_pos(0)
|
|
|
|
{
|
|
|
|
DWORD dwDesiredAccess = 0;
|
|
|
|
DWORD dwCreationDisposition = CREATE_ALWAYS;
|
|
|
|
DWORD dwShareMode = 0;
|
|
|
|
makeWin32OpenFlags( oflag, &dwDesiredAccess, &dwCreationDisposition, &dwShareMode );
|
|
|
|
if( !systemDependentFlags )
|
|
|
|
{
|
|
|
|
if( (oflag & ofRead) && !(oflag & ofWrite) )
|
|
|
|
systemDependentFlags = FILE_FLAG_SEQUENTIAL_SCAN;
|
|
|
|
else
|
|
|
|
systemDependentFlags = FILE_FLAG_RANDOM_ACCESS;
|
|
|
|
}
|
|
|
|
m_impl = CreateFile(
|
|
|
|
fName,
|
|
|
|
dwDesiredAccess,
|
|
|
|
dwShareMode,
|
|
|
|
NULL,
|
|
|
|
dwCreationDisposition,
|
|
|
|
systemDependentFlags,
|
|
|
|
NULL );
|
|
|
|
if( m_impl == INVALID_HANDLE_VALUE )
|
|
|
|
{
|
|
|
|
throwFileError();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if( oflag & File::ofAppend ) {
|
|
|
|
long hiword = 0;
|
|
|
|
DWORD newPointerLow = SetFilePointer( m_impl, 0, &hiword, FILE_END );
|
|
|
|
if( newPointerLow == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR )
|
|
|
|
throwFileError();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
File::~File()
|
|
|
|
{
|
|
|
|
if( isOpen() )
|
|
|
|
close();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool File::open( const char* fName, unsigned int oflag, unsigned int systemDependentFlags )
|
|
|
|
{
|
|
|
|
m_name = fName;
|
|
|
|
m_pos = 0;
|
|
|
|
|
|
|
|
DWORD dwDesiredAccess = 0;
|
|
|
|
DWORD dwCreationDisposition = CREATE_ALWAYS;
|
|
|
|
DWORD dwShareMode = 0;
|
|
|
|
makeWin32OpenFlags( oflag, &dwDesiredAccess, &dwCreationDisposition, &dwShareMode );
|
|
|
|
if( !systemDependentFlags )
|
|
|
|
{
|
|
|
|
if( (oflag & ofRead) && !(oflag & ofWrite) )
|
|
|
|
systemDependentFlags = FILE_FLAG_SEQUENTIAL_SCAN;
|
|
|
|
else
|
|
|
|
systemDependentFlags = FILE_FLAG_RANDOM_ACCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
createDir ( extractFileDir ( fName ), true );
|
|
|
|
|
|
|
|
m_impl = CreateFile(
|
|
|
|
fName,
|
|
|
|
dwDesiredAccess,
|
|
|
|
dwShareMode,
|
|
|
|
NULL,
|
|
|
|
dwCreationDisposition,
|
|
|
|
systemDependentFlags,
|
|
|
|
NULL );
|
|
|
|
if( m_impl == INVALID_HANDLE_VALUE )
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if( oflag & File::ofAppend ) {
|
|
|
|
long hiword = 0;
|
|
|
|
DWORD newPointerLow = SetFilePointer( m_impl, 0, &hiword, FILE_END );
|
|
|
|
if( newPointerLow == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR )
|
|
|
|
throwFileError();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool File::close()
|
|
|
|
{
|
|
|
|
//sync();
|
|
|
|
BOOL res = CloseHandle( m_impl );
|
|
|
|
m_impl = INVALID_HANDLE_VALUE;
|
|
|
|
return res != 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int File::read( void* buffer, uint32_t count ) const
|
|
|
|
{
|
|
|
|
if( !isOpen() )
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
DWORD bytesRead = 0;
|
|
|
|
BOOL res = ReadFile( m_impl, buffer, count, &bytesRead, NULL );
|
|
|
|
if( !res )
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
m_pos += bytesRead;
|
|
|
|
|
|
|
|
return (int)bytesRead;
|
|
|
|
}
|
|
|
|
|
|
|
|
int File::write( const void* buffer, uint32_t count )
|
|
|
|
{
|
|
|
|
if( !isOpen() )
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
DWORD bytesWritten = 0;
|
|
|
|
BOOL res = WriteFile( m_impl, buffer, count, &bytesWritten, NULL );
|
|
|
|
if( !res )
|
|
|
|
{
|
|
|
|
throwFileError();
|
|
|
|
}
|
|
|
|
if( !res )
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
m_pos += bytesWritten;
|
|
|
|
|
|
|
|
return (int)bytesWritten;
|
|
|
|
}
|
|
|
|
|
|
|
|
void File::sync()
|
|
|
|
{
|
|
|
|
FlushFileBuffers( m_impl );
|
|
|
|
}
|
|
|
|
|
|
|
|
bool File::isOpen() const
|
|
|
|
{
|
|
|
|
return m_impl != INVALID_HANDLE_VALUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool File::size( uint64_t* const fileSize ) const
|
|
|
|
{
|
|
|
|
DWORD highDw;
|
|
|
|
DWORD lowDw = GetFileSize( m_impl, &highDw );
|
|
|
|
if( (lowDw == INVALID_FILE_SIZE) && (GetLastError() != NO_ERROR) )
|
|
|
|
return false;
|
|
|
|
*fileSize = highDw;
|
|
|
|
*fileSize <<= 32;
|
|
|
|
*fileSize |= lowDw;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t File::seek( int64_t offset, SeekMethod whence )
|
|
|
|
{
|
|
|
|
if( !isOpen() )
|
|
|
|
return (uint64_t)-1;
|
|
|
|
|
|
|
|
DWORD moveMethod = 0;
|
|
|
|
switch( whence )
|
|
|
|
{
|
|
|
|
case smBegin:
|
|
|
|
moveMethod = FILE_BEGIN;
|
|
|
|
break;
|
|
|
|
case smCurrent:
|
|
|
|
moveMethod = FILE_CURRENT;
|
|
|
|
break;
|
|
|
|
case smEnd:
|
|
|
|
moveMethod = FILE_END;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
LONG distanceToMoveLow = (uint32_t)(offset & 0xffffffff);
|
|
|
|
LONG distanceToMoveHigh = (uint32_t)((offset & 0xffffffff00000000ull) >> 32);
|
|
|
|
|
|
|
|
DWORD newPointerLow = SetFilePointer( m_impl, distanceToMoveLow, &distanceToMoveHigh, moveMethod );
|
|
|
|
if( newPointerLow == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR )
|
|
|
|
return (uint64_t)-1;
|
|
|
|
|
|
|
|
m_pos = newPointerLow | ((uint64_t)distanceToMoveHigh << 32);
|
|
|
|
|
|
|
|
return m_pos;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool File::truncate( uint64_t newFileSize)
|
|
|
|
{
|
|
|
|
LONG distanceToMoveLow = (uint32_t)(newFileSize & 0xffffffff);
|
|
|
|
LONG distanceToMoveHigh = (uint32_t)((newFileSize & 0xffffffff00000000ull) >> 32);
|
|
|
|
DWORD newPointerLow = SetFilePointer(
|
|
|
|
m_impl,
|
|
|
|
distanceToMoveLow,
|
|
|
|
&distanceToMoveHigh,
|
|
|
|
FILE_BEGIN );
|
|
|
|
int errCode = GetLastError();
|
|
|
|
if( (newPointerLow == INVALID_SET_FILE_POINTER) && (errCode != NO_ERROR) )
|
|
|
|
//return false;
|
|
|
|
throwFileError();
|
|
|
|
|
|
|
|
return SetEndOfFile( m_impl ) > 0;
|
|
|
|
}
|