#include <KM_fileio.h>
#include <KM_log.h>
#include <fcntl.h>
+#include <sstream>
+#include <iomanip>
#include <assert.h>
typedef struct _stati64 fstat_t;
#define S_IFLNK 0
-
// win32 has WriteFileGather() and ReadFileScatter() but they
// demand page alignment and page sizing, making them unsuitable
// for use with arbitrary buffer sizes.
#ifdef KM_WIN32
UINT prev = ::SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX);
- if ( _stati64(path, stat_info) == (__int64)-1 )
+ int const wn = MultiByteToWideChar (CP_UTF8, 0, path, -1, 0, 0);
+ wchar_t* buffer = new wchar_t[wn];
+ if (MultiByteToWideChar (CP_UTF8, 0, path, -1, buffer, wn) == 0) {
+ delete[] buffer;
+ return Kumu::RESULT_FAIL;
+ }
+
+ if ( _wstati64(buffer, stat_info) == (__int64)-1 )
result = Kumu::RESULT_FILEOPEN;
+ delete[] buffer;
+
::SetErrorMode( prev );
#else
if ( stat(path, stat_info) == -1L )
// these are declared here instead of in the header file
// because we have a mem_ptr that is managing a hidden class
-Kumu::FileWriter::FileWriter() {}
+Kumu::FileWriter::FileWriter()
+ : m_Hashing (false)
+{}
+
Kumu::FileWriter::~FileWriter() {}
//
return RESULT_OK;
}
+void
+Kumu::FileWriter::StartHashing()
+{
+ m_Hashing = true;
+ MD5_Init (&m_MD5Context);
+}
+
+void
+Kumu::FileWriter::MaybeHash(void const * data, int size)
+{
+ if (m_Hashing) {
+ MD5_Update (&m_MD5Context, data, size);
+ }
+}
+
+std::string
+Kumu::FileWriter::StopHashing()
+{
+ m_Hashing = false;
+
+ unsigned char digest[MD5_DIGEST_LENGTH];
+ MD5_Final (digest, &m_MD5Context);
+
+ std::stringstream s;
+ for (int i = 0; i < MD5_DIGEST_LENGTH; ++i) {
+ s << std::hex << std::setfill('0') << std::setw(2) << ((int) digest[i]);
+ }
+
+ return s.str ();
+}
+
#ifdef KM_WIN32
//------------------------------------------------------------------------------------------
//
+/** @param filename File name (UTF-8 encoded) */
Kumu::Result_t
Kumu::FileReader::OpenRead(const char* filename) const
{
// suppress popup window on error
UINT prev = ::SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX);
- const_cast<FileReader*>(this)->m_Handle = ::CreateFileA(filename,
+ int const wn = MultiByteToWideChar (CP_UTF8, 0, filename, -1, 0, 0);
+ wchar_t* buffer = new wchar_t[wn];
+ if (MultiByteToWideChar (CP_UTF8, 0, filename, -1, buffer, wn) == 0) {
+ delete[] buffer;
+ return Kumu::RESULT_FAIL;
+ }
+ const_cast<FileReader*>(this)->m_Handle = ::CreateFileW(buffer,
(GENERIC_READ), // open for reading
FILE_SHARE_READ, // share for reading
NULL, // no security
NULL // no template file
);
+ delete[] buffer;
+
::SetErrorMode(prev);
return ( m_Handle == INVALID_HANDLE_VALUE ) ?
//------------------------------------------------------------------------------------------
//
-//
+/** @param filename File name (UTF-8 encoded) */
Kumu::Result_t
Kumu::FileWriter::OpenWrite(const char* filename)
{
// suppress popup window on error
UINT prev = ::SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX);
- m_Handle = ::CreateFileA(filename,
+ int const wn = MultiByteToWideChar (CP_UTF8, 0, filename, -1, 0, 0);
+ wchar_t* buffer = new wchar_t[wn];
+ if (MultiByteToWideChar (CP_UTF8, 0, filename, -1, buffer, wn) == 0) {
+ delete[] buffer;
+ return Kumu::RESULT_FAIL;
+ }
+
+ m_Handle = ::CreateFileW(buffer,
(GENERIC_WRITE|GENERIC_READ), // open for reading
FILE_SHARE_READ, // share for reading
NULL, // no security
NULL // no template file
);
+ delete[] buffer;
+
+ ::SetErrorMode(prev);
+
+ if ( m_Handle == INVALID_HANDLE_VALUE )
+ return Kumu::RESULT_FILEOPEN;
+
+ m_IOVec = new h__iovec;
+ return Kumu::RESULT_OK;
+}
+
+/** @param filename File name (UTF-8 encoded) */
+Kumu::Result_t
+Kumu::FileWriter::OpenModify(const char* filename)
+{
+ KM_TEST_NULL_STR_L(filename);
+ m_Filename = filename;
+
+ // suppress popup window on error
+ UINT prev = ::SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX);
+
+ int const wn = MultiByteToWideChar (CP_UTF8, 0, filename, -1, 0, 0);
+ wchar_t* buffer = new wchar_t[wn];
+ if (MultiByteToWideChar (CP_UTF8, 0, filename, -1, buffer, wn) == 0) {
+ delete[] buffer;
+ return Kumu::RESULT_FAIL;
+ }
+
+ m_Handle = ::CreateFileW(buffer,
+ (GENERIC_WRITE|GENERIC_READ), // open for reading
+ FILE_SHARE_READ, // share for reading
+ NULL, // no security
+ OPEN_ALWAYS, // don't truncate existing
+ FILE_ATTRIBUTE_NORMAL, // normal file
+ NULL // no template file
+ );
+
+ delete[] buffer;
+
::SetErrorMode(prev);
if ( m_Handle == INVALID_HANDLE_VALUE )
break;
}
+ MaybeHash (iov->m_iovec[i].iov_base, iov->m_iovec[i].iov_len);
*bytes_written += tmp_count;
}
if ( result == 0 || *bytes_written != buf_len )
return Kumu::RESULT_WRITEFAIL;
+ MaybeHash (buf, buf_len);
+
return Kumu::RESULT_OK;
}
if ( write_size == -1L || write_size != total_size )
return RESULT_WRITEFAIL;
+ for (int i = 0; i < iov->m_Count; ++i) {
+ MaybeHash (iov->m_iovec[i].iov_base, iov->m_iovec[i].iov_len);
+ }
+
iov->m_Count = 0;
*bytes_written = write_size;
return RESULT_OK;
return RESULT_STATE;
int write_size = write(m_Handle, buf, buf_len);
+ MaybeHash (buf, buf_len);
if ( write_size == -1L || (ui32_t)write_size != buf_len )
return RESULT_WRITEFAIL;
}
-#endif // KM_WIN32
+#endif
//------------------------------------------------------------------------------------------
if (_iterator == boost::filesystem::directory_iterator()) {
return RESULT_ENDOFFILE;
}
-
- strncpy (filename, boost::filesystem::path(*_iterator).filename().generic_string().c_str(), MaxFilePath);
+
+#if BOOST_FILESYSTEM_VERSION == 3
+ std::string f = boost::filesystem::path(*_iterator).filename().generic_string();
+#else
+ std::string f = boost::filesystem::path(*_iterator).filename();
+#endif
+ strncpy (filename, f.c_str(), MaxFilePath);
++_iterator;
return RESULT_OK;
}