Index: src/libchcore/TFakeFilesystemFile.cpp =================================================================== diff -u -N --- src/libchcore/TFakeFilesystemFile.cpp (revision a13bee8e2ecd1e8f61be0aa9b51d99acdc43a5d0) +++ src/libchcore/TFakeFilesystemFile.cpp (revision 0) @@ -1,294 +0,0 @@ -// ============================================================================ -// Copyright (C) 2001-2015 by Jozef Starosczyk -// ixen@copyhandler.com -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU Library General Public License -// (version 2) as published by the Free Software Foundation; -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU Library General Public -// License along with this program; if not, write to the -// Free Software Foundation, Inc., -// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// ============================================================================ -#include "stdafx.h" -#include "TFakeFilesystemFile.h" -#include "TCoreException.h" -#include "ErrorCodes.h" -#include "TFakeFilesystem.h" -#include -#include "RoundingFunctions.h" -#include "TFileException.h" - -namespace -{ - struct APCINFO - { - OVERLAPPED* pOverlapped; - DWORD dwError; - DWORD dwNumberOfBytesTransfered; - }; - - enum EStatus : DWORD - { - STATUS_OK = 0, - STATUS_END_OF_FILE = 0xc0000011 - }; -} - -namespace chcore -{ - VOID CALLBACK ReadCompleted(ULONG_PTR dwParam) - { - APCINFO* pApcInfo = (APCINFO*)dwParam; - OverlappedReadCompleted(pApcInfo->dwError, pApcInfo->dwNumberOfBytesTransfered, pApcInfo->pOverlapped); - - delete pApcInfo; - } - - VOID CALLBACK WriteCompleted(ULONG_PTR dwParam) - { - APCINFO* pApcInfo = (APCINFO*)dwParam; - OverlappedWriteCompleted(pApcInfo->dwError, pApcInfo->dwNumberOfBytesTransfered, pApcInfo->pOverlapped); - - delete pApcInfo; - } - - TFakeFilesystemFile::TFakeFilesystemFile(const TSmartPath& pathFile, bool bNoBuffering, TFakeFilesystem* pFilesystem) : - m_pathFile(pathFile), - m_pFilesystem(pFilesystem), - m_bIsOpen(false), - m_bNoBuffering(bNoBuffering), - m_bModeReading(true) - { - if (!pFilesystem || pathFile.IsEmpty()) - THROW_CORE_EXCEPTION(eErr_InvalidArgument); - } - - TFakeFilesystemFile::~TFakeFilesystemFile() - { - } - - void TFakeFilesystemFile::Close() - { - m_bIsOpen = false; - } - - TSmartPath TFakeFilesystemFile::GetFilePath() const - { - return m_pathFile; - } - - unsigned long long TFakeFilesystemFile::GetFileSize() const - { - TFakeFileDescriptionPtr spFileDesc = m_pFilesystem->FindFileByLocation(m_pathFile); - if (!spFileDesc) - THROW_FILE_EXCEPTION(eErr_CannotGetFileInfo, ERROR_FILE_INVALID, m_pathFile, L"Cannot retrieve file info - file does not exist"); - - return spFileDesc->GetFileInfo().GetLength64(); - } - - bool TFakeFilesystemFile::IsOpen() const - { - return m_bIsOpen; - } - - void TFakeFilesystemFile::FinalizeFile(TOverlappedDataBuffer& /*rBuffer*/) - { - // does nothing - } - - void TFakeFilesystemFile::WriteFile(TOverlappedDataBuffer& rBuffer) - { - if (!IsOpen()) - THROW_FILE_EXCEPTION(eErr_FileNotOpen, ERROR_INVALID_HANDLE, m_pathFile, L"Cannot write to closed file"); - - // file should have been created already by create for write functions - TFakeFileDescriptionPtr spFileDesc = m_pFilesystem->FindFileByLocation(m_pathFile); - if (!spFileDesc) - THROW_FILE_EXCEPTION(eErr_CannotWriteFile, ERROR_FILE_INVALID, m_pathFile, L"Cannot write to non-existent file"); - - APCINFO* pInfo = new APCINFO; - unsigned long long ullNewSize = 0; - //unsigned long long ullGrow = 0; - if (rBuffer.GetFilePosition() >= spFileDesc->GetFileInfo().GetLength64()) - { - ullNewSize = rBuffer.GetFilePosition() + rBuffer.GetRealDataSize(); - //ullGrow = ullNewSize - spFileDesc->GetFileInfo().GetLength64(); - } - else - { - ullNewSize = std::max(rBuffer.GetFilePosition() + rBuffer.GetRealDataSize(), spFileDesc->GetFileInfo().GetLength64()); - //ullGrow = ullNewSize - spFileDesc->GetFileInfo().GetLength64(); - } - - spFileDesc->GetFileInfo().SetLength64(ullNewSize); - - rBuffer.SetStatusCode(STATUS_OK); - rBuffer.SetBytesTransferred(rBuffer.GetRealDataSize()); - pInfo->dwError = ERROR_SUCCESS; - pInfo->dwNumberOfBytesTransfered = rBuffer.GetRealDataSize(); - pInfo->pOverlapped = &rBuffer; - - if (QueueUserAPC(WriteCompleted, GetCurrentThread(), (ULONG_PTR)pInfo) == 0) - THROW_CORE_EXCEPTION(eErr_InternalProblem); - } - - void TFakeFilesystemFile::ReadFile(TOverlappedDataBuffer& rBuffer) - { - if (!IsOpen()) - THROW_FILE_EXCEPTION(eErr_FileNotOpen, ERROR_INVALID_HANDLE, m_pathFile, L"Cannot read from closed file"); - - // check if we're reading the undamaged data - TFakeFileDescriptionPtr spFileDesc = m_pFilesystem->FindFileByLocation(m_pathFile); - if (!spFileDesc) - THROW_FILE_EXCEPTION(eErr_CannotReadFile, ERROR_FILE_INVALID, m_pathFile, L"Cannot read from non-existent file"); - - const TSparseRangeMap& rmapDamage = spFileDesc->GetDamageMap(); - if (rmapDamage.OverlapsRange(rBuffer.GetFilePosition(), rBuffer.GetRequestedDataSize())) - { - APCINFO* pInfo = new APCINFO; - pInfo->dwError = ERROR_READ_FAULT; - pInfo->dwNumberOfBytesTransfered = 0; - pInfo->pOverlapped = &rBuffer; - - if (QueueUserAPC(ReadCompleted, GetCurrentThread(), (ULONG_PTR)pInfo) == 0) - THROW_CORE_EXCEPTION(eErr_InternalProblem); - } - else - { - APCINFO* pInfo = new APCINFO; - - if (rBuffer.GetFilePosition() >= spFileDesc->GetFileInfo().GetLength64()) - { - rBuffer.SetStatusCode(STATUS_END_OF_FILE); - rBuffer.SetBytesTransferred(0); - pInfo->dwError = ERROR_HANDLE_EOF; - pInfo->dwNumberOfBytesTransfered = 0; - pInfo->pOverlapped = &rBuffer; - } - else if (rBuffer.GetFilePosition() + rBuffer.GetRequestedDataSize() > spFileDesc->GetFileInfo().GetLength64()) - { - file_size_t fsRemaining = spFileDesc->GetFileInfo().GetLength64() - rBuffer.GetFilePosition(); - - rBuffer.SetStatusCode(STATUS_OK); - rBuffer.SetBytesTransferred(boost::numeric_cast(fsRemaining)); - pInfo->dwError = ERROR_SUCCESS; - pInfo->dwNumberOfBytesTransfered = boost::numeric_cast(fsRemaining); - pInfo->pOverlapped = &rBuffer; - } - else - { - rBuffer.SetStatusCode(STATUS_OK); - rBuffer.SetBytesTransferred(rBuffer.GetRequestedDataSize()); - pInfo->dwError = ERROR_SUCCESS; - pInfo->dwNumberOfBytesTransfered = rBuffer.GetRequestedDataSize(); - pInfo->pOverlapped = &rBuffer; - } - - GenerateBufferContent(rBuffer); - - if (QueueUserAPC(ReadCompleted, GetCurrentThread(), (ULONG_PTR)pInfo) == 0) - THROW_CORE_EXCEPTION(eErr_InternalProblem); - } - } - - file_size_t TFakeFilesystemFile::GetSeekPositionForResume(file_size_t fsLastAvailablePosition) - { - file_size_t fsMove = (m_bNoBuffering ? RoundDown(fsLastAvailablePosition, MaxSectorSize) : fsLastAvailablePosition); - return fsMove; - } - - void TFakeFilesystemFile::Truncate(file_size_t fsNewSize) - { - if (!IsOpen()) - THROW_FILE_EXCEPTION(eErr_FileNotOpen, ERROR_INVALID_HANDLE, m_pathFile, L"Cannot truncate closed file"); - - // check if we're reading the undamaged data - TFakeFileDescriptionPtr spFileDesc = m_pFilesystem->FindFileByLocation(m_pathFile); - if (!spFileDesc) - THROW_FILE_EXCEPTION(eErr_CannotTruncate, ERROR_FILE_INVALID, m_pathFile, L"Cannot truncate non-existent file"); - - spFileDesc->GetFileInfo().SetLength64(fsNewSize); - } - - void TFakeFilesystemFile::OpenExistingForWriting() - { - TFakeFileDescriptionPtr spFileDesc = m_pFilesystem->FindFileByLocation(m_pathFile); - if (!spFileDesc) - THROW_FILE_EXCEPTION(eErr_CannotOpenFile, ERROR_FILE_INVALID, m_pathFile, L"Cannot open existing for writing"); - - Close(); - - m_bIsOpen = true; - m_bModeReading = false; - } - - void TFakeFilesystemFile::CreateNewForWriting() - { - TFakeFileDescriptionPtr spFileDesc = m_pFilesystem->FindFileByLocation(m_pathFile); - if(!spFileDesc) - { - TFakeFileDescriptionPtr parentDesc = m_pFilesystem->FindFileByLocation(m_pathFile.GetParent()); - if (!parentDesc) - THROW_FILE_EXCEPTION(eErr_CannotOpenFile, ERROR_FUNCTION_FAILED, m_pathFile, L"Cannot open existing for writing"); - - FILETIME ftCurrent = m_pFilesystem->GetCurrentFileTime(); - TFakeFileDescriptionPtr spNewFile(std::make_shared( - TFileInfo(nullptr, m_pathFile, FILE_ATTRIBUTE_NORMAL, 0, ftCurrent, ftCurrent, ftCurrent, 0), - TSparseRangeMap() - )); - - m_pFilesystem->m_listFilesystemContent.push_back(spNewFile); - } - - Close(); - - m_bIsOpen = true; - m_bModeReading = false; - } - - void TFakeFilesystemFile::OpenExistingForReading() - { - TFakeFileDescriptionPtr spFileDesc = m_pFilesystem->FindFileByLocation(m_pathFile); - if (!spFileDesc) - THROW_FILE_EXCEPTION(eErr_CannotOpenFile, ERROR_FILE_INVALID, m_pathFile, L"Cannot find file"); - - Close(); - - m_bIsOpen = true; - m_bModeReading = true; - } - - void TFakeFilesystemFile::GenerateBufferContent(TOverlappedDataBuffer &rBuffer) - { - if(rBuffer.GetBytesTransferred() > 0) - { - ZeroMemory(rBuffer.GetBufferPtr(), rBuffer.GetBufferSize()); - - size_t stCount = rBuffer.GetBytesTransferred() / sizeof(file_size_t); - if (stCount > 0) - { - file_size_t* pBuffer = (file_size_t*)rBuffer.GetBufferPtr(); - for (size_t stIndex = 0; stIndex != stCount; ++stIndex) - { - pBuffer[stIndex] = rBuffer.GetFilePosition() + stIndex * sizeof(file_size_t); - } - } - } - } - - void TFakeFilesystemFile::GetFileInfo(TFileInfo& tFileInfo) const - { - TFakeFileDescriptionPtr spFileDesc = m_pFilesystem->FindFileByLocation(m_pathFile); - if (!spFileDesc) - THROW_FILE_EXCEPTION(eErr_CannotGetFileInfo, ERROR_FILE_INVALID, m_pathFile, L"Cannot retrieve file info - file does not exist"); - - tFileInfo = spFileDesc->GetFileInfo(); - } -}