From ff68cb626cfac2bae419091a240bedcd1734ff59 Mon Sep 17 00:00:00 2001 From: vng Date: Wed, 29 May 2013 20:08:30 +0300 Subject: [PATCH] Handle file i/o errors according to manuals. --- coding/internal/file_data.cpp | 62 +++++++++++++++++++---------------- coding/internal/file_data.hpp | 3 +- 2 files changed, 36 insertions(+), 29 deletions(-) diff --git a/coding/internal/file_data.cpp b/coding/internal/file_data.cpp index 9c0f7ec864..64e82cacde 100644 --- a/coding/internal/file_data.cpp +++ b/coding/internal/file_data.cpp @@ -30,17 +30,14 @@ FileData::FileData(string const & fileName, Op op) return; #else m_File = fopen(fileName.c_str(), modes[op]); - if (m_File && ferror(m_File) == 0) + if (m_File) return; if (op == OP_WRITE_EXISTING) { // Special case, since "r+b" fails if file doesn't exist. - if (m_File) - fclose(m_File); - m_File = fopen(fileName.c_str(), "wb"); - if (m_File && ferror(m_File) == 0) + if (m_File) return; } #endif @@ -55,9 +52,10 @@ FileData::FileData(string const & fileName, Op op) FileData::~FileData() { #ifndef OMIM_OS_BADA - if (0 != fclose(m_File)) + if (m_File) { - LOG(LWARNING, ("Error closing file", GetErrorProlog())); + if (fclose(m_File)) + LOG(LWARNING, ("Error closing file", GetErrorProlog())); } #endif } @@ -76,6 +74,8 @@ string FileData::GetErrorProlog() const return m_FileName + "; " + s + "; " + strerror(errno); } +static int64_t const INVALID_POS = -1; + uint64_t FileData::Size() const { #ifdef OMIM_OS_BADA @@ -85,19 +85,22 @@ uint64_t FileData::Size() const MYTHROW(Reader::SizeException, (m_FileName, m_Op, error)); return attr.GetFileSize(); #else - uint64_t const pos = ftell64(m_File); - if (ferror(m_File)) + int64_t const pos = ftell64(m_File); + if (pos == INVALID_POS) MYTHROW(Reader::SizeException, (GetErrorProlog(), pos)); - fseek64(m_File, 0, SEEK_END); - if (ferror(m_File)) + + if (fseek64(m_File, 0, SEEK_END)) MYTHROW(Reader::SizeException, (GetErrorProlog())); - uint64_t const size = ftell64(m_File); - if (ferror(m_File)) + + int64_t const size = ftell64(m_File); + if (size == INVALID_POS) MYTHROW(Reader::SizeException, (GetErrorProlog(), size)); - fseek64(m_File, pos, SEEK_SET); - if (ferror(m_File)) + + if (fseek64(m_File, pos, SEEK_SET)) MYTHROW(Reader::SizeException, (GetErrorProlog(), pos)); - return size; + + ASSERT_GREATER_OR_EQUAL(size, 0, ()); + return static_cast(size); #endif } @@ -112,9 +115,9 @@ void FileData::Read(uint64_t pos, void * p, size_t size) if (static_cast(bytesRead) != size || IsFailed(error)) MYTHROW(Reader::ReadException, (m_FileName, m_Op, error, bytesRead, pos, size)); #else - fseek64(m_File, pos, SEEK_SET); - if (ferror(m_File)) + if (fseek64(m_File, pos, SEEK_SET)) 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)); @@ -130,10 +133,12 @@ uint64_t FileData::Pos() const MYTHROW(Writer::PosException, (m_FileName, m_Op, error, pos)); return pos; #else - uint64_t const result = ftell64(m_File); - if (ferror(m_File)) - MYTHROW(Writer::PosException, (GetErrorProlog(), result)); - return result; + int64_t const pos = ftell64(m_File); + if (pos == INVALID_POS) + MYTHROW(Writer::PosException, (GetErrorProlog(), pos)); + + ASSERT_GREATER_OR_EQUAL(pos, 0, ()); + return static_cast(pos); #endif } @@ -145,8 +150,7 @@ void FileData::Seek(uint64_t pos) if (IsFailed(error)) MYTHROW(Writer::SeekException, (m_FileName, m_Op, error, pos)); #else - fseek64(m_File, pos, SEEK_SET); - if (ferror(m_File)) + if (fseek64(m_File, pos, SEEK_SET)) MYTHROW(Writer::SeekException, (GetErrorProlog(), pos)); #endif } @@ -171,8 +175,7 @@ void FileData::Flush() if (IsFailed(error)) MYTHROW(Writer::WriteException, (m_FileName, m_Op, error)); #else - fflush(m_File); - if (ferror(m_File)) + if (fflush(m_File)) MYTHROW(Writer::WriteException, (GetErrorProlog())); #endif } @@ -180,10 +183,13 @@ void FileData::Flush() void FileData::Truncate(uint64_t sz) { #ifdef OMIM_OS_WINDOWS - _chsize(fileno(m_File), sz); + int const res = _chsize(fileno(m_File), sz); #else - ftruncate(fileno(m_File), sz); + int const res = ftruncate(fileno(m_File), sz); #endif + + if (res) + MYTHROW(Writer::WriteException, (GetErrorProlog(), sz)); } bool GetFileSize(string const & fName, uint64_t & sz) diff --git a/coding/internal/file_data.hpp b/coding/internal/file_data.hpp index 1b1cbfa1c1..8c6c3085f1 100644 --- a/coding/internal/file_data.hpp +++ b/coding/internal/file_data.hpp @@ -15,7 +15,8 @@ namespace my { class FileData { public: - enum Op { OP_READ = 0, OP_WRITE_TRUNCATE = 1, OP_WRITE_EXISTING = 2, OP_APPEND}; + /// @note Do not change order (@see FileData::FileData). + enum Op { OP_READ = 0, OP_WRITE_TRUNCATE, OP_WRITE_EXISTING, OP_APPEND }; FileData(string const & fileName, Op op); ~FileData();