summaryrefslogtreecommitdiff
path: root/shared/fileIO.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'shared/fileIO.cpp')
-rw-r--r--shared/fileIO.cpp157
1 files changed, 157 insertions, 0 deletions
diff --git a/shared/fileIO.cpp b/shared/fileIO.cpp
new file mode 100644
index 00000000..c4825e04
--- /dev/null
+++ b/shared/fileIO.cpp
@@ -0,0 +1,157 @@
+// **************************************************************************
+// * This file is part of the FreeFileSync project. It is distributed under *
+// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
+// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) *
+// **************************************************************************
+//
+#include "fileIO.h"
+#include <wx/intl.h>
+#include "stringConv.h"
+#include "systemFunctions.h"
+
+#ifdef FFS_WIN
+#include "longPathPrefix.h"
+#endif
+
+using namespace FreeFileSync;
+
+
+FileInput::FileInput(const Zstring& filename) : //throw FileError()
+#ifdef FFS_WIN
+ eofReached(false),
+#endif
+ filename_(filename)
+{
+#ifdef FFS_WIN
+ fileHandle = ::CreateFile(FreeFileSync::applyLongPathPrefix(filename).c_str(),
+ GENERIC_READ,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, //all shared modes are required to read files that are open in other applications
+ NULL,
+ OPEN_EXISTING,
+ FILE_FLAG_SEQUENTIAL_SCAN,
+ NULL);
+ if (fileHandle == INVALID_HANDLE_VALUE)
+ throw FileError(wxString(_("Error opening file:")) + wxT("\n\"") + zToWx(filename_) + wxT("\"") +
+ wxT("\n\n") + FreeFileSync::getLastErrorFormatted());
+#elif defined FFS_LINUX
+ fileHandle = ::fopen(filename.c_str(), "rb,type=record,noseek"); //utilize UTF-8 filename
+ if (!fileHandle)
+ throw FileError(wxString(_("Error opening file:")) + wxT("\n\"") + zToWx(filename_) + wxT("\"") +
+ wxT("\n\n") + FreeFileSync::getLastErrorFormatted());
+#endif
+}
+
+
+FileInput::~FileInput()
+{
+#ifdef FFS_WIN
+ ::CloseHandle(fileHandle);
+#elif defined FFS_LINUX
+ ::fclose(fileHandle); //NEVER allow passing NULL to fclose! -> crash!; fileHandle != NULL in this context!
+#endif
+}
+
+
+size_t FileInput::read(void* buffer, size_t bytesToRead) //returns actual number of bytes read; throw FileError()
+{
+#ifdef FFS_WIN
+ DWORD bytesRead = 0;
+
+ if (!::ReadFile(
+ fileHandle, //__in HANDLE hFile,
+ buffer, //__out LPVOID lpBuffer,
+ static_cast<DWORD>(bytesToRead), //__in DWORD nNumberOfBytesToRead,
+ &bytesRead, //__out_opt LPDWORD lpNumberOfBytesRead,
+ NULL) //__inout_opt LPOVERLAPPED lpOverlapped
+ || bytesRead > bytesToRead) //must be fulfilled
+ throw FileError(wxString(_("Error reading file:")) + wxT("\n\"") + zToWx(filename_) + wxT("\"") +
+ wxT("\n\n") + FreeFileSync::getLastErrorFormatted());
+
+ if (bytesRead < bytesToRead)
+ eofReached = true;
+
+ return bytesRead;
+#elif defined FFS_LINUX
+ const size_t bytesRead = ::fread(buffer, 1, bytesToRead, fileHandle);
+ if (::ferror(fileHandle) != 0)
+ throw FileError(wxString(_("Error reading file:")) + wxT("\n\"") + zToWx(filename_) + wxT("\"") +
+ wxT("\n\n") + FreeFileSync::getLastErrorFormatted());
+ return bytesRead;
+#endif
+}
+
+
+bool FileInput::eof() //end of file reached
+{
+#ifdef FFS_WIN
+ return eofReached;
+#elif defined FFS_LINUX
+ return ::feof(fileHandle) != 0;
+#endif
+}
+
+
+FileOutput::FileOutput(const Zstring& filename) : //throw FileError()
+ filename_(filename)
+{
+#ifdef FFS_WIN
+ fileHandle = ::CreateFile(FreeFileSync::applyLongPathPrefix(filename).c_str(),
+ GENERIC_WRITE,
+ FILE_SHARE_READ,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
+ NULL);
+ if (fileHandle == INVALID_HANDLE_VALUE)
+ throw FileError(wxString(_("Error writing file:")) + wxT("\n\"") + zToWx(filename_) + wxT("\"") +
+ wxT("\n\n") + FreeFileSync::getLastErrorFormatted());
+#elif defined FFS_LINUX
+ fileHandle = ::fopen(filename.c_str(), "wb,type=record,noseek"); //utilize UTF-8 filename
+ if (!fileHandle)
+ throw FileError(wxString(_("Error writing file:")) + wxT("\n\"") + zToWx(filename_) + wxT("\"") +
+ wxT("\n\n") + FreeFileSync::getLastErrorFormatted());
+#endif
+}
+
+
+FileOutput::~FileOutput()
+{
+ close(); //may be called more than once
+}
+
+
+void FileOutput::write(const void* buffer, size_t bytesToWrite) //throw FileError()
+{
+#ifdef FFS_WIN
+ DWORD bytesWritten = 0;
+
+ if (!::WriteFile(
+ fileHandle, //__in HANDLE hFile,
+ buffer, //__out LPVOID lpBuffer,
+ static_cast<DWORD>(bytesToWrite), //__in DWORD nNumberOfBytesToRead,
+ &bytesWritten, //__out_opt LPDWORD lpNumberOfBytesWritten,
+ NULL) //__inout_opt LPOVERLAPPED lpOverlapped
+ || bytesWritten != bytesToWrite) //must be fulfilled for synchronous writes!
+ throw FileError(wxString(_("Error writing file:")) + wxT("\n\"") + zToWx(filename_) + wxT("\"") +
+ wxT("\n\n") + FreeFileSync::getLastErrorFormatted());
+#elif defined FFS_LINUX
+ const size_t bytesWritten = ::fwrite(buffer, 1, bytesToWrite, fileHandle);
+ if (::ferror(fileHandle) != 0 || bytesWritten != bytesToWrite)
+ throw FileError(wxString(_("Error writing file:")) + wxT("\n\"") + zToWx(filename_) + wxT("\"") +
+ wxT("\n\n") + FreeFileSync::getLastErrorFormatted() + wxT(" (w)")); //w -> distinguish from fopen error message!
+#endif
+}
+
+
+void FileOutput::close() //close file stream
+{
+ if (fileHandle != NULL) //NEVER allow passing NULL to fclose! -> crash!
+ {
+#ifdef FFS_WIN
+ ::CloseHandle(fileHandle);
+#elif defined FFS_LINUX
+ ::fclose(fileHandle);
+#endif
+ fileHandle = NULL;
+ }
+}
bgstack15