Correct errors handling in file's i/o operations.

This commit is contained in:
vng 2013-05-29 14:43:36 +03:00 committed by Alex Zolotarev
parent 13f6b4ab21
commit 3f7cb039a3
4 changed files with 68 additions and 38 deletions

View file

@ -10,13 +10,15 @@
#include "../../std/target_os.hpp"
#include "../../std/fstream.hpp"
#include "../../std/exception.hpp"
#include "../../std/cerrno.hpp"
#ifdef OMIM_OS_WINDOWS
#include <io.h>
#endif
namespace my {
namespace my
{
FileData::FileData(string const & fileName, Op op)
: m_FileName(fileName), m_Op(op)
@ -28,8 +30,7 @@ FileData::FileData(string const & fileName, Op op)
return;
#else
m_File = fopen(fileName.c_str(), modes[op]);
int error = m_File ? ferror(m_File) : 0;
if (m_File && error == 0)
if (m_File && ferror(m_File) == 0)
return;
if (op == OP_WRITE_EXISTING)
@ -37,49 +38,65 @@ FileData::FileData(string const & fileName, Op op)
// Special case, since "r+b" fails if file doesn't exist.
if (m_File)
fclose(m_File);
m_File = fopen(fileName.c_str(), "wb");
error = m_File ? ferror(m_File) : 0;
if (m_File && ferror(m_File) == 0)
return;
}
if (m_File && error == 0)
return;
#endif
// if we're here - something bad is happened
if (m_Op != OP_READ)
MYTHROW(Writer::OpenException, (fileName, error));
MYTHROW(Writer::OpenException, (GetErrorProlog()));
else
MYTHROW(Reader::OpenException, (fileName, error));
MYTHROW(Reader::OpenException, (GetErrorProlog()));
}
FileData::~FileData()
{
#ifndef OMIM_OS_BADA
if (int error = fclose(m_File))
if (0 != fclose(m_File))
{
LOG(LWARNING, ("Error closing file", m_FileName, m_Op, error));
LOG(LWARNING, ("Error closing file", GetErrorProlog()));
}
#endif
}
string FileData::GetErrorProlog() const
{
char const * s;
switch (m_Op)
{
case OP_READ: s = "Read"; break;
case OP_WRITE_TRUNCATE: s = "Write truncate"; break;
case OP_WRITE_EXISTING: s = "Write existing"; break;
case OP_APPEND: s = "Append"; break;
}
return m_FileName + "; " + s + "; " + strerror(errno);
}
uint64_t FileData::Size() const
{
#ifdef OMIM_OS_BADA
Osp::Io::FileAttributes attr;
result error = Osp::Io::File::GetAttributes(m_FileName.c_str(), attr);
if (IsFailed(error))
MYTHROW(Reader::OpenException, (m_FileName, m_Op, error));
MYTHROW(Reader::SizeException, (m_FileName, m_Op, error));
return attr.GetFileSize();
#else
uint64_t const pos = Pos();
uint64_t const pos = ftell64(m_File);
if (ferror(m_File))
MYTHROW(Reader::SizeException, (GetErrorProlog(), pos));
fseek64(m_File, 0, SEEK_END);
if (int error = ferror(m_File))
MYTHROW(Reader::OpenException, (m_FileName, m_Op, error));
uint64_t size = ftell64(m_File);
if (int error = ferror(m_File))
MYTHROW(Reader::OpenException, (m_FileName, m_Op, error));
if (ferror(m_File))
MYTHROW(Reader::SizeException, (GetErrorProlog()));
uint64_t const size = ftell64(m_File);
if (ferror(m_File))
MYTHROW(Reader::SizeException, (GetErrorProlog(), size));
fseek64(m_File, pos, SEEK_SET);
if (int error = ferror(m_File))
MYTHROW(Writer::SeekException, (m_FileName, m_Op, error, pos));
if (ferror(m_File))
MYTHROW(Reader::SizeException, (GetErrorProlog(), pos));
return size;
#endif
}
@ -90,33 +107,32 @@ void FileData::Read(uint64_t pos, void * p, size_t size)
result error = m_File.Seek(Osp::Io::FILESEEKPOSITION_BEGIN, pos);
if (IsFailed(error))
MYTHROW(Reader::ReadException, (error, pos));
int bytesRead = m_File.Read(p, size);
int const bytesRead = m_File.Read(p, size);
error = GetLastResult();
if (static_cast<size_t>(bytesRead) != size || IsFailed(error))
MYTHROW(Reader::ReadException, (m_FileName, m_Op, error, bytesRead, pos, size));
#else
fseek64(m_File, pos, SEEK_SET);
if (int error = ferror(m_File))
MYTHROW(Reader::ReadException, (error, pos));
size_t bytesRead = fread(p, 1, size, m_File);
int error = ferror(m_File);
if (bytesRead != size || error)
MYTHROW(Reader::ReadException, (m_FileName, m_Op, error, bytesRead, pos, size));
if (ferror(m_File))
MYTHROW(Reader::ReadException, (GetErrorProlog(), pos));
size_t const bytesRead = fread(p, 1, size, m_File);
if (bytesRead != size || ferror(m_File))
MYTHROW(Reader::ReadException, (GetErrorProlog(), bytesRead, pos, size));
#endif
}
uint64_t FileData::Pos() const
{
#ifdef OMIM_OS_BADA
int pos = m_File.Tell();
int const pos = m_File.Tell();
result error = GetLastResult();
if (IsFailed(error))
MYTHROW(Writer::PosException, (m_FileName, m_Op, error, pos));
return pos;
#else
uint64_t result = ftell64(m_File);
if (int error = ferror(m_File))
MYTHROW(Writer::PosException, (m_FileName, m_Op, error, result));
uint64_t const result = ftell64(m_File);
if (ferror(m_File))
MYTHROW(Writer::PosException, (GetErrorProlog(), result));
return result;
#endif
}
@ -130,8 +146,8 @@ void FileData::Seek(uint64_t pos)
MYTHROW(Writer::SeekException, (m_FileName, m_Op, error, pos));
#else
fseek64(m_File, pos, SEEK_SET);
if (int error = ferror(m_File))
MYTHROW(Writer::SeekException, (m_FileName, m_Op, error, pos));
if (ferror(m_File))
MYTHROW(Writer::SeekException, (GetErrorProlog(), pos));
#endif
}
@ -142,10 +158,9 @@ void FileData::Write(void const * p, size_t size)
if (IsFailed(error))
MYTHROW(Writer::WriteException, (m_FileName, m_Op, error, size));
#else
size_t bytesWritten = fwrite(p, 1, size, m_File);
int error = ferror(m_File);
if (bytesWritten != size || error)
MYTHROW(Writer::WriteException, (m_FileName, m_Op, error, bytesWritten, size));
size_t const bytesWritten = fwrite(p, 1, size, m_File);
if (bytesWritten != size || ferror(m_File))
MYTHROW(Writer::WriteException, (GetErrorProlog(), bytesWritten, size));
#endif
}
@ -157,8 +172,8 @@ void FileData::Flush()
MYTHROW(Writer::WriteException, (m_FileName, m_Op, error));
#else
fflush(m_File);
if (int error = ferror(m_File))
MYTHROW(Writer::WriteException, (m_FileName, m_Op, error));
if (ferror(m_File))
MYTHROW(Writer::WriteException, (GetErrorProlog()));
#endif
}

View file

@ -41,6 +41,8 @@ private:
#endif
string m_FileName;
Op m_Op;
string GetErrorProlog() const;
};
bool GetFileSize(string const & fName, uint64_t & sz);

View file

@ -18,6 +18,7 @@ class Reader
public:
DECLARE_EXCEPTION(Exception, RootException);
DECLARE_EXCEPTION(OpenException, Exception);
DECLARE_EXCEPTION(SizeException, Exception);
DECLARE_EXCEPTION(ReadException, Exception);
virtual ~Reader() {}

12
std/cerrno.hpp Normal file
View file

@ -0,0 +1,12 @@
#pragma once
#include "common_defines.hpp"
#ifdef new
#undef new
#endif
#include <cerrno>
#ifdef DEBUG_NEW
#define new DEBUG_NEW
#endif