summaryrefslogtreecommitdiff
path: root/library/binary.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'library/binary.cpp')
-rw-r--r--library/binary.cpp122
1 files changed, 122 insertions, 0 deletions
diff --git a/library/binary.cpp b/library/binary.cpp
new file mode 100644
index 00000000..bc5ba814
--- /dev/null
+++ b/library/binary.cpp
@@ -0,0 +1,122 @@
+// **************************************************************************
+// * 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 "binary.h"
+#include <boost/scoped_array.hpp>
+#include <wx/intl.h>
+#include "../shared/stringConv.h"
+
+#ifdef FFS_WIN
+#include "../shared/longPathPrefix.h"
+#include <wx/msw/wrapwin.h> //includes "windows.h"
+#include <boost/shared_ptr.hpp>
+
+#elif defined FFS_LINUX
+#include <wx/ffile.h>
+#endif
+
+
+bool FreeFileSync::filesHaveSameContent(const Zstring& filename1, const Zstring& filename2, CompareCallback* callback)
+{
+ const size_t BUFFER_SIZE = 512 * 1024; //512 kb seems to be the perfect buffer size
+ static boost::scoped_array<unsigned char> memory1(new unsigned char[BUFFER_SIZE]);
+ static boost::scoped_array<unsigned char> memory2(new unsigned char[BUFFER_SIZE]);
+
+#ifdef FFS_WIN
+ const HANDLE hFile1 = ::CreateFile(FreeFileSync::applyLongPathPrefix(filename1).c_str(),
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL,
+ OPEN_EXISTING,
+ FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_SEQUENTIAL_SCAN,
+ NULL);
+ if (hFile1 == INVALID_HANDLE_VALUE)
+ throw FileError(wxString(_("Error opening file:")) + wxT(" \"") + zToWx(filename1) + wxT("\""));
+
+ boost::shared_ptr<void> dummy1(hFile1, &::CloseHandle);
+
+ const HANDLE hFile2 = ::CreateFile(FreeFileSync::applyLongPathPrefix(filename2).c_str(),
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL,
+ OPEN_EXISTING,
+ FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_SEQUENTIAL_SCAN,
+ NULL);
+ if (hFile2 == INVALID_HANDLE_VALUE)
+ throw FileError(wxString(_("Error opening file:")) + wxT(" \"") + zToWx(filename2) + wxT("\""));
+
+ boost::shared_ptr<void> dummy2(hFile2, &::CloseHandle);
+
+ wxLongLong bytesCompared;
+ DWORD length1 = 0;
+ do
+ {
+ if (!::ReadFile(
+ hFile1, //__in HANDLE hFile,
+ memory1.get(), //__out LPVOID lpBuffer,
+ BUFFER_SIZE, //__in DWORD nNumberOfBytesToRead,
+ &length1, //__out_opt LPDWORD lpNumberOfBytesRead,
+ NULL)) //__inout_opt LPOVERLAPPED lpOverlapped
+ throw FileError(wxString(_("Error reading file:")) + wxT(" \"") + zToWx(filename1) + wxT("\""));
+
+ DWORD length2 = 0;
+ if (!::ReadFile(
+ hFile2, //__in HANDLE hFile,
+ memory2.get(), //__out LPVOID lpBuffer,
+ BUFFER_SIZE, //__in DWORD nNumberOfBytesToRead,
+ &length2, //__out_opt LPDWORD lpNumberOfBytesRead,
+ NULL)) //__inout_opt LPOVERLAPPED lpOverlapped
+ throw FileError(wxString(_("Error reading file:")) + wxT(" \"") + zToWx(filename2) + wxT("\""));
+
+ if (length1 != length2 || ::memcmp(memory1.get(), memory2.get(), length1) != 0)
+ return false;
+
+ bytesCompared += length1 * 2;
+
+ //send progress updates
+ callback->updateCompareStatus(bytesCompared);
+ }
+ while (length1 == BUFFER_SIZE);
+
+ return true;
+
+
+#elif defined FFS_LINUX
+ wxFFile file1(::fopen(filename1.c_str(), DefaultStr("rb,type=record,noseek"))); //utilize UTF-8 filename
+ if (!file1.IsOpened())
+ throw FileError(wxString(_("Error opening file:")) + wxT(" \"") + zToWx(filename1) + wxT("\""));
+
+ wxFFile file2(::fopen(filename2.c_str(), DefaultStr("rb,type=record,noseek"))); //utilize UTF-8 filename
+ if (!file2.IsOpened())
+ throw FileError(wxString(_("Error opening file:")) + wxT(" \"") + zToWx(filename2) + wxT("\""));
+
+ wxLongLong bytesCompared;
+ do
+ {
+ const size_t length1 = file1.Read(memory1.get(), BUFFER_SIZE);
+ if (file1.Error())
+ throw FileError(wxString(_("Error reading file:")) + wxT(" \"") + zToWx(filename1) + wxT("\""));
+
+ const size_t length2 = file2.Read(memory2.get(), BUFFER_SIZE);
+ if (file2.Error())
+ throw FileError(wxString(_("Error reading file:")) + wxT(" \"") + zToWx(filename2) + wxT("\""));
+
+ if (length1 != length2 || ::memcmp(memory1.get(), memory2.get(), length1) != 0)
+ return false;
+
+ bytesCompared += length1 * 2;
+
+ //send progress updates
+ callback->updateCompareStatus(bytesCompared);
+ }
+ while (!file1.Eof());
+
+ if (!file2.Eof()) //highly unlikely, but theoretically possible! (but then again, not in this context where both files have same size...)
+ return false;
+
+ return true;
+#endif
+}
bgstack15