diff options
| author | Carl Hetherington <cth@carlh.net> | 2016-01-14 23:54:53 +0000 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2016-01-14 23:54:53 +0000 |
| commit | a2374eb06a0f6d391d1d5ae04f50ce5e8076173a (patch) | |
| tree | a3b83b31e739e7b5312a3a99e9a1c1446ff29bbb /asdcplib/src/KM_fileio.cpp | |
| parent | 38ff2954f40131a12aa8a037b9fc6c4abd3894b9 (diff) | |
Use out-of-tree asdcplib-cth
Diffstat (limited to 'asdcplib/src/KM_fileio.cpp')
| -rw-r--r-- | asdcplib/src/KM_fileio.cpp | 1546 |
1 files changed, 0 insertions, 1546 deletions
diff --git a/asdcplib/src/KM_fileio.cpp b/asdcplib/src/KM_fileio.cpp deleted file mode 100644 index b20ff7f7..00000000 --- a/asdcplib/src/KM_fileio.cpp +++ /dev/null @@ -1,1546 +0,0 @@ -/* -Copyright (c) 2004-2011, John Hurst -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. -3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - /*! \file KM_fileio.cpp - \version $Id: KM_fileio.cpp,v 1.31 2011/03/08 19:03:47 jhurst Exp $ - \brief portable file i/o - */ - -#include <KM_fileio.h> -#include <KM_log.h> -#include <fcntl.h> -#include <sstream> -#include <iomanip> - -#include <assert.h> - -#ifdef KM_WIN32 -#include <direct.h> -#else -#define _getcwd getcwd -#define _unlink unlink -#define _rmdir rmdir -#endif - -using namespace Kumu; - -#ifdef KM_WIN32 -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. -struct iovec { - char* iov_base; // stupid iovec uses char* - int iov_len; -}; -#else -# if defined(__linux__) -# include <sys/statfs.h> -# else -# include <sys/param.h> -# include <sys/mount.h> -# endif - -#include <sys/stat.h> -#include <sys/uio.h> -typedef struct stat fstat_t; -#endif - -// -static void -split(const std::string& str, char separator, std::list<std::string>& components) -{ - const char* pstr = str.c_str(); - const char* r = strchr(pstr, separator); - - while ( r != 0 ) - { - assert(r >= pstr); - if ( r > pstr ) - { - std::string tmp_str; - tmp_str.assign(pstr, (r - pstr)); - components.push_back(tmp_str); - } - - pstr = r + 1; - r = strchr(pstr, separator); - } - - if( strlen(pstr) > 0 ) - components.push_back(std::string(pstr)); -} - - -// -static Kumu::Result_t -do_stat(const char* path, fstat_t* stat_info) -{ - KM_TEST_NULL_STR_L(path); - KM_TEST_NULL_L(stat_info); - - Kumu::Result_t result = Kumu::RESULT_OK; - -#ifdef KM_WIN32 - UINT prev = ::SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX); - - 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 ) - result = Kumu::RESULT_FILEOPEN; - - if ( (stat_info->st_mode & (S_IFREG|S_IFLNK|S_IFDIR)) == 0 ) - result = Kumu::RESULT_FILEOPEN; -#endif - - return result; -} - -#ifndef KM_WIN32 - -// -static Kumu::Result_t -do_fstat(FileHandle handle, fstat_t* stat_info) -{ - KM_TEST_NULL_L(stat_info); - - Kumu::Result_t result = Kumu::RESULT_OK; - - if ( fstat(handle, stat_info) == -1L ) - result = Kumu::RESULT_FILEOPEN; - - if ( (stat_info->st_mode & (S_IFREG|S_IFLNK|S_IFDIR)) == 0 ) - result = Kumu::RESULT_FILEOPEN; - - return result; -} - -#endif - - -// -bool -Kumu::PathExists(const std::string& pathname) -{ - if ( pathname.empty() ) - return false; - - fstat_t info; - - if ( KM_SUCCESS(do_stat(pathname.c_str(), &info)) ) - return true; - - return false; -} - -// -bool -Kumu::PathIsFile(const std::string& pathname) -{ - if ( pathname.empty() ) - return false; - - fstat_t info; - - if ( KM_SUCCESS(do_stat(pathname.c_str(), &info)) ) - { - if ( info.st_mode & ( S_IFREG|S_IFLNK ) ) - return true; - } - - return false; -} - - -// -bool -Kumu::PathIsDirectory(const std::string& pathname) -{ - if ( pathname.empty() ) - return false; - - fstat_t info; - - if ( KM_SUCCESS(do_stat(pathname.c_str(), &info)) ) - { - if ( info.st_mode & S_IFDIR ) - return true; - } - - return false; -} - -// -Kumu::fsize_t -Kumu::FileSize(const std::string& pathname) -{ - if ( pathname.empty() ) - return 0; - - fstat_t info; - - if ( KM_SUCCESS(do_stat(pathname.c_str(), &info)) ) - { - if ( info.st_mode & ( S_IFREG|S_IFLNK ) ) - return(info.st_size); - } - - return 0; -} - -// -static PathCompList_t& -s_PathMakeCanonical(PathCompList_t& CList, bool is_absolute) -{ - PathCompList_t::iterator ci, ri; // component and removal iterators - - for ( ci = CList.begin(); ci != CList.end(); ci++ ) - { - if ( *ci == "." && ( CList.size() > 1 || is_absolute ) ) - { - ri = ci++; - CList.erase(ri); - } - else if ( *ci == ".." && ci != CList.begin() ) - { - ri = ci; - ri--; - - if ( *ri != ".." ) - { - CList.erase(ri); - ri = ci++; - CList.erase(ri); - } - } - } - - return CList; -} - -// -std::string -Kumu::PathMakeCanonical(const std::string& Path, char separator) -{ - PathCompList_t CList; - bool is_absolute = PathIsAbsolute(Path, separator); - s_PathMakeCanonical(PathToComponents(Path, CList, separator), is_absolute); - - if ( is_absolute ) - return ComponentsToAbsolutePath(CList, separator); - - return ComponentsToPath(CList, separator); -} - -// -bool -Kumu::PathsAreEquivalent(const std::string& lhs, const std::string& rhs) -{ - return PathMakeCanonical(lhs) == PathMakeCanonical(rhs); -} - -// -Kumu::PathCompList_t& -Kumu::PathToComponents(const std::string& Path, PathCompList_t& CList, char separator) -{ - split(Path, separator, CList); - return CList; -} - -// -std::string -Kumu::ComponentsToPath(const PathCompList_t& CList, char separator) -{ - if ( CList.empty() ) - return ""; - - PathCompList_t::const_iterator ci = CList.begin(); - std::string out_path = *ci; - - for ( ci++; ci != CList.end(); ci++ ) - out_path += separator + *ci; - - return out_path; -} - -// -std::string -Kumu::ComponentsToAbsolutePath(const PathCompList_t& CList, char separator) -{ - std::string out_path; - - if ( CList.empty() ) - out_path = separator; - else - { - PathCompList_t::const_iterator ci; - - for ( ci = CList.begin(); ci != CList.end(); ci++ ) - out_path += separator + *ci; - } - - return out_path; -} - -// -bool -Kumu::PathHasComponents(const std::string& Path, char separator) -{ - if ( strchr(Path.c_str(), separator) == 0 ) - return false; - - return true; -} - -// -bool -Kumu::PathIsAbsolute(const std::string& Path, char separator) -{ - if ( Path.empty() ) - return false; - - if ( Path[0] == separator) - return true; - - return false; -} - -// -std::string -Kumu::PathMakeAbsolute(const std::string& Path, char separator) -{ - if ( Path.empty() ) - { - std::string out_path; - out_path = separator; - return out_path; - } - - if ( PathIsAbsolute(Path, separator) ) - return Path; - - char cwd_buf [MaxFilePath]; - if ( _getcwd(cwd_buf, MaxFilePath) == 0 ) - { - DefaultLogSink().Error("Error retrieving current working directory."); - return ""; - } - - PathCompList_t CList; - PathToComponents(cwd_buf, CList); - CList.push_back(Path); - - return ComponentsToAbsolutePath(s_PathMakeCanonical(CList, true), separator); -} - -// -std::string -Kumu::PathMakeLocal(const std::string& Path, const std::string& Parent) -{ - size_t pos = Path.find(Parent); - - if ( pos == 0 ) // Parent found at offset 0 - return Path.substr(Parent.size()+1); - - return Path; -} - -// -std::string -Kumu::PathBasename(const std::string& Path, char separator) -{ - PathCompList_t CList; - PathToComponents(Path, CList, separator); - - if ( CList.empty() ) - return ""; - - return CList.back(); -} - -// -std::string -Kumu::PathDirname(const std::string& Path, char separator) -{ - PathCompList_t CList; - bool is_absolute = PathIsAbsolute(Path, separator); - PathToComponents(Path, CList, separator); - - if ( CList.empty() ) - return is_absolute ? "/" : ""; - - CList.pop_back(); - - if ( is_absolute ) - return ComponentsToAbsolutePath(CList, separator); - - return ComponentsToPath(CList, separator); -} - -// -std::string -Kumu::PathGetExtension(const std::string& Path) -{ - std::string Basename = PathBasename(Path); - const char* p = strrchr(Basename.c_str(), '.'); - - if ( p++ == 0 ) - return ""; - - return p; -} - -// -std::string -Kumu::PathSetExtension(const std::string& Path, const std::string& Extension) // empty extension removes -{ - std::string Basename = PathBasename(Path); - const char* p = strrchr(Basename.c_str(), '.'); - - if ( p != 0 ) - Basename = Basename.substr(0, p - Basename.c_str()); - - if ( Extension.empty() ) - return Basename; - - return Basename + "." + Extension; -} - -// -std::string -Kumu::PathJoin(const std::string& Path1, const std::string& Path2, char separator) -{ - return Path1 + separator + Path2; -} - -// -std::string -Kumu::PathJoin(const std::string& Path1, const std::string& Path2, const std::string& Path3, char separator) -{ - return Path1 + separator + Path2 + separator + Path3; -} - -// -std::string -Kumu::PathJoin(const std::string& Path1, const std::string& Path2, - const std::string& Path3, const std::string& Path4, char separator) -{ - return Path1 + separator + Path2 + separator + Path3 + separator + Path4; -} - -// -Kumu::PathList_t& -Kumu::FindInPaths(const IPathMatch& Pattern, const Kumu::PathList_t& SearchPaths, - Kumu::PathList_t& FoundPaths, bool one_shot, char separator) -{ - PathList_t::const_iterator si; - for ( si = SearchPaths.begin(); si != SearchPaths.end(); si++ ) - { - FindInPath(Pattern, *si, FoundPaths, one_shot, separator); - - if ( one_shot && ! FoundPaths.empty() ) - break; - } - - return FoundPaths; -} - -// -Kumu::PathList_t& -Kumu::FindInPath(const IPathMatch& Pattern, const std::string& SearchDir, - Kumu::PathList_t& FoundPaths, bool one_shot, char separator) -{ - char name_buf[MaxFilePath]; - DirScanner Dir; - - if ( KM_SUCCESS(Dir.Open(SearchDir.c_str())) ) - { - while ( KM_SUCCESS(Dir.GetNext(name_buf)) ) - { - if ( name_buf[0] == '.' ) continue; // no hidden files - std::string tmp_path = SearchDir + separator + name_buf; - - if ( PathIsDirectory(tmp_path.c_str()) ) - FindInPath(Pattern, tmp_path, FoundPaths, one_shot, separator); - - else if ( Pattern.Match(name_buf) ) - { - FoundPaths.push_back(SearchDir + separator + name_buf); - if ( one_shot ) - break; - } - } - } - - return FoundPaths; -} - - -#ifndef KM_WIN32 - -// -Kumu::PathMatchRegex::PathMatchRegex(const std::string& s) -{ - int result = regcomp(&m_regex, s.c_str(), REG_NOSUB); // (REG_EXTENDED|REG_NOSUB|REG_NEWLINE)); - - if ( result ) - { - char buf[128]; - regerror(result, &m_regex, buf, 128); - DefaultLogSink().Error("PathMatchRegex: %s\n", buf); - regfree(&m_regex); - } -} - -Kumu::PathMatchRegex::PathMatchRegex(const PathMatchRegex& rhs) : IPathMatch() { - m_regex = rhs.m_regex; -} - -Kumu::PathMatchRegex::~PathMatchRegex() { - regfree(&m_regex); -} - -bool -Kumu::PathMatchRegex::Match(const std::string& s) const { - return ( regexec(&m_regex, s.c_str(), 0, 0, 0) == 0 ); -} - - - -// -Kumu::PathMatchGlob::PathMatchGlob(const std::string& glob) -{ - std::string regex; // convert glob to regex - - for ( const char* p = glob.c_str(); *p != 0; p++ ) - { - switch (*p) - { - case '.': regex += "\\."; break; - case '*': regex += ".*"; break; - case '?': regex += ".?"; break; - default: regex += *p; - } - } - regex += '$'; - - int result = regcomp(&m_regex, regex.c_str(), REG_NOSUB); - - if ( result ) - { - char buf[128]; - regerror(result, &m_regex, buf, 128); - DefaultLogSink().Error("PathMatchRegex: %s\n", buf); - regfree(&m_regex); - } -} - -Kumu::PathMatchGlob::PathMatchGlob(const PathMatchGlob& rhs) : IPathMatch() { - m_regex = rhs.m_regex; -} - -Kumu::PathMatchGlob::~PathMatchGlob() { - regfree(&m_regex); -} - -bool -Kumu::PathMatchGlob::Match(const std::string& s) const { - return ( regexec(&m_regex, s.c_str(), 0, 0, 0) == 0 ); -} - -#endif - -//------------------------------------------------------------------------------------------ -// portable aspects of the file classes - -const int IOVecMaxEntries = 32; // we never use more that 3, but that number seems somehow small... - -// -class Kumu::FileWriter::h__iovec -{ -public: - int m_Count; - struct iovec m_iovec[IOVecMaxEntries]; - h__iovec() : m_Count(0) {} -}; - - - -// -Kumu::fsize_t -Kumu::FileReader::Size() const -{ -#ifdef KM_WIN32 - return FileSize(m_Filename.c_str()); -#else - fstat_t info; - - if ( KM_SUCCESS(do_fstat(m_Handle, &info)) ) - { - if ( info.st_mode & ( S_IFREG|S_IFLNK ) ) - return(info.st_size); - } -#endif - - return 0; -} - -// 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() - : m_Hashing (false) -{} - -Kumu::FileWriter::~FileWriter() {} - -// -Kumu::Result_t -Kumu::FileWriter::Writev(const byte_t* buf, ui32_t buf_len) -{ - assert( ! m_IOVec.empty() ); - register h__iovec* iov = m_IOVec; - KM_TEST_NULL_L(buf); - - if ( iov->m_Count >= IOVecMaxEntries ) - { - DefaultLogSink().Error("The iovec is full! Only %u entries allowed before a flush.\n", - IOVecMaxEntries); - return RESULT_WRITEFAIL; - } - - iov->m_iovec[iov->m_Count].iov_base = (char*)buf; // stupid iovec uses char* - iov->m_iovec[iov->m_Count].iov_len = buf_len; - iov->m_Count++; - - 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 -{ - KM_TEST_NULL_STR_L(filename); - const_cast<FileReader*>(this)->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; - } - const_cast<FileReader*>(this)->m_Handle = ::CreateFileW(buffer, - (GENERIC_READ), // open for reading - FILE_SHARE_READ, // share for reading - NULL, // no security - OPEN_EXISTING, // read - FILE_ATTRIBUTE_NORMAL, // normal file - NULL // no template file - ); - - delete[] buffer; - - ::SetErrorMode(prev); - - return ( m_Handle == INVALID_HANDLE_VALUE ) ? - Kumu::RESULT_FILEOPEN : Kumu::RESULT_OK; -} - -// -Kumu::Result_t -Kumu::FileReader::Close() const -{ - if ( m_Handle == INVALID_HANDLE_VALUE ) - return Kumu::RESULT_FILEOPEN; - - // suppress popup window on error - UINT prev = ::SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX); - BOOL result = ::CloseHandle(m_Handle); - ::SetErrorMode(prev); - const_cast<FileReader*>(this)->m_Handle = INVALID_HANDLE_VALUE; - - return ( result == 0 ) ? Kumu::RESULT_FAIL : Kumu::RESULT_OK; -} - -// -Kumu::Result_t -Kumu::FileReader::Seek(Kumu::fpos_t position, SeekPos_t whence) const -{ - if ( m_Handle == INVALID_HANDLE_VALUE ) - return Kumu::RESULT_STATE; - - LARGE_INTEGER in; - UINT prev = ::SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX); - in.QuadPart = position; - in.LowPart = ::SetFilePointer(m_Handle, in.LowPart, &in.HighPart, whence); - HRESULT LastError = GetLastError(); - ::SetErrorMode(prev); - - if ( (LastError != NO_ERROR - && (in.LowPart == INVALID_SET_FILE_POINTER - || in.LowPart == ERROR_NEGATIVE_SEEK )) ) - return Kumu::RESULT_READFAIL; - - return Kumu::RESULT_OK; -} - -// -Kumu::Result_t -Kumu::FileReader::Tell(Kumu::fpos_t* pos) const -{ - KM_TEST_NULL_L(pos); - - if ( m_Handle == INVALID_HANDLE_VALUE ) - return Kumu::RESULT_FILEOPEN; - - LARGE_INTEGER in; - UINT prev = ::SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX); - in.QuadPart = (__int64)0; - in.LowPart = ::SetFilePointer(m_Handle, in.LowPart, &in.HighPart, FILE_CURRENT); - HRESULT LastError = GetLastError(); - ::SetErrorMode(prev); - - if ( (LastError != NO_ERROR - && (in.LowPart == INVALID_SET_FILE_POINTER - || in.LowPart == ERROR_NEGATIVE_SEEK )) ) - return Kumu::RESULT_READFAIL; - - *pos = (Kumu::fpos_t)in.QuadPart; - return Kumu::RESULT_OK; -} - -// -Kumu::Result_t -Kumu::FileReader::Read(byte_t* buf, ui32_t buf_len, ui32_t* read_count) const -{ - KM_TEST_NULL_L(buf); - Result_t result = Kumu::RESULT_OK; - DWORD tmp_count; - ui32_t tmp_int; - - if ( read_count == 0 ) - read_count = &tmp_int; - - *read_count = 0; - - if ( m_Handle == INVALID_HANDLE_VALUE ) - return Kumu::RESULT_FILEOPEN; - - UINT prev = ::SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX); - if ( ::ReadFile(m_Handle, buf, buf_len, &tmp_count, NULL) == 0 ) - result = Kumu::RESULT_READFAIL; - - ::SetErrorMode(prev); - - if ( tmp_count == 0 ) /* EOF */ - result = Kumu::RESULT_ENDOFFILE; - - if ( KM_SUCCESS(result) ) - *read_count = tmp_count; - - return result; -} - - - -//------------------------------------------------------------------------------------------ -// - -/** @param filename File name (UTF-8 encoded) */ -Kumu::Result_t -Kumu::FileWriter::OpenWrite(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 - CREATE_ALWAYS, // overwrite (beware!) - FILE_ATTRIBUTE_NORMAL, // normal file - 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 ) - return Kumu::RESULT_FILEOPEN; - - m_IOVec = new h__iovec; - return Kumu::RESULT_OK; -} - -// -Kumu::Result_t -Kumu::FileWriter::Writev(ui32_t* bytes_written) -{ - assert( ! m_IOVec.empty() ); - register h__iovec* iov = m_IOVec; - ui32_t tmp_int; - - if ( bytes_written == 0 ) - bytes_written = &tmp_int; - - if ( m_Handle == INVALID_HANDLE_VALUE ) - return Kumu::RESULT_STATE; - - *bytes_written = 0; - UINT prev = ::SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX); - Result_t result = Kumu::RESULT_OK; - - // AFAIK, there is no writev() equivalent in the win32 API - for ( register int i = 0; i < iov->m_Count; i++ ) - { - ui32_t tmp_count = 0; - BOOL wr_result = ::WriteFile(m_Handle, - iov->m_iovec[i].iov_base, - iov->m_iovec[i].iov_len, - (DWORD*)&tmp_count, - NULL); - - if ( wr_result == 0 || tmp_count != iov->m_iovec[i].iov_len) - { - result = Kumu::RESULT_WRITEFAIL; - break; - } - - MaybeHash (iov->m_iovec[i].iov_base, iov->m_iovec[i].iov_len); - *bytes_written += tmp_count; - } - - ::SetErrorMode(prev); - iov->m_Count = 0; // error nor not, all is lost - - return result; -} - -// -Kumu::Result_t -Kumu::FileWriter::Write(const byte_t* buf, ui32_t buf_len, ui32_t* bytes_written) -{ - KM_TEST_NULL_L(buf); - ui32_t tmp_int; - - if ( bytes_written == 0 ) - bytes_written = &tmp_int; - - if ( m_Handle == INVALID_HANDLE_VALUE ) - return Kumu::RESULT_STATE; - - // suppress popup window on error - UINT prev = ::SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX); - BOOL result = ::WriteFile(m_Handle, buf, buf_len, (DWORD*)bytes_written, NULL); - ::SetErrorMode(prev); - - if ( result == 0 || *bytes_written != buf_len ) - return Kumu::RESULT_WRITEFAIL; - - MaybeHash (buf, buf_len); - - return Kumu::RESULT_OK; -} - -#else // KM_WIN32 -//------------------------------------------------------------------------------------------ -// POSIX - -// -Kumu::Result_t -Kumu::FileReader::OpenRead(const char* filename) const -{ - KM_TEST_NULL_STR_L(filename); - const_cast<FileReader*>(this)->m_Filename = filename; - const_cast<FileReader*>(this)->m_Handle = open(filename, O_RDONLY, 0); - return ( m_Handle == -1L ) ? RESULT_FILEOPEN : RESULT_OK; -} - -// -Kumu::Result_t -Kumu::FileReader::Close() const -{ - if ( m_Handle == -1L ) - return RESULT_FILEOPEN; - - close(m_Handle); - const_cast<FileReader*>(this)->m_Handle = -1L; - return RESULT_OK; -} - -// -Kumu::Result_t -Kumu::FileReader::Seek(Kumu::fpos_t position, SeekPos_t whence) const -{ - if ( m_Handle == -1L ) - return RESULT_FILEOPEN; - - if ( lseek(m_Handle, position, whence) == -1L ) - return RESULT_BADSEEK; - - return RESULT_OK; -} - -// -Kumu::Result_t -Kumu::FileReader::Tell(Kumu::fpos_t* pos) const -{ - KM_TEST_NULL_L(pos); - - if ( m_Handle == -1L ) - return RESULT_FILEOPEN; - - Kumu::fpos_t tmp_pos; - - if ( (tmp_pos = lseek(m_Handle, 0, SEEK_CUR)) == -1 ) - return RESULT_READFAIL; - - *pos = tmp_pos; - return RESULT_OK; -} - -// -Kumu::Result_t -Kumu::FileReader::Read(byte_t* buf, ui32_t buf_len, ui32_t* read_count) const -{ - KM_TEST_NULL_L(buf); - i32_t tmp_count = 0; - ui32_t tmp_int = 0; - - if ( read_count == 0 ) - read_count = &tmp_int; - - *read_count = 0; - - if ( m_Handle == -1L ) - return RESULT_FILEOPEN; - - if ( (tmp_count = read(m_Handle, buf, buf_len)) == -1L ) - return RESULT_READFAIL; - - *read_count = tmp_count; - return (tmp_count == 0 ? RESULT_ENDOFFILE : RESULT_OK); -} - - -//------------------------------------------------------------------------------------------ -// - -// -Kumu::Result_t -Kumu::FileWriter::OpenWrite(const char* filename) -{ - KM_TEST_NULL_STR_L(filename); - m_Filename = filename; - m_Handle = open(filename, O_RDWR|O_CREAT|O_TRUNC, 0664); - - if ( m_Handle == -1L ) - { - DefaultLogSink().Error("Error opening file %s: %s\n", filename, strerror(errno)); - return RESULT_FILEOPEN; - } - - m_IOVec = new h__iovec; - return RESULT_OK; -} - -// -Kumu::Result_t -Kumu::FileWriter::OpenModify(const char* filename) -{ - KM_TEST_NULL_STR_L(filename); - m_Filename = filename; - m_Handle = open(filename, O_RDWR|O_CREAT, 0664); - - if ( m_Handle == -1L ) - { - DefaultLogSink().Error("Error opening file %s: %s\n", filename, strerror(errno)); - return RESULT_FILEOPEN; - } - - m_IOVec = new h__iovec; - return RESULT_OK; -} - -// -Kumu::Result_t -Kumu::FileWriter::Writev(ui32_t* bytes_written) -{ - assert( ! m_IOVec.empty() ); - register h__iovec* iov = m_IOVec; - ui32_t tmp_int; - - if ( bytes_written == 0 ) - bytes_written = &tmp_int; - - if ( m_Handle == -1L ) - return RESULT_STATE; - - int total_size = 0; - for ( int i = 0; i < iov->m_Count; i++ ) - total_size += iov->m_iovec[i].iov_len; - - int write_size = writev(m_Handle, iov->m_iovec, iov->m_Count); - - 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; -} - -// -Kumu::Result_t -Kumu::FileWriter::Write(const byte_t* buf, ui32_t buf_len, ui32_t* bytes_written) -{ - KM_TEST_NULL_L(buf); - ui32_t tmp_int; - - if ( bytes_written == 0 ) - bytes_written = &tmp_int; - - if ( m_Handle == -1L ) - 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; - - *bytes_written = write_size; - return RESULT_OK; -} - - -#endif - -//------------------------------------------------------------------------------------------ - - -// -Kumu::Result_t -Kumu::ReadFileIntoString(const char* filename, std::string& outString, ui32_t max_size) -{ - fsize_t fsize = 0; - ui32_t read_size = 0; - FileReader File; - ByteString ReadBuf; - - KM_TEST_NULL_STR_L(filename); - - Result_t result = File.OpenRead(filename); - - if ( KM_SUCCESS(result) ) - { - fsize = File.Size(); - - if ( fsize > (Kumu::fpos_t)max_size ) - { - DefaultLogSink().Error("%s: exceeds available buffer size (%u)\n", filename, max_size); - return RESULT_ALLOC; - } - - if ( fsize == 0 ) - { - DefaultLogSink().Error("%s: zero file size\n", filename); - return RESULT_READFAIL; - } - - result = ReadBuf.Capacity((ui32_t)fsize); - } - - if ( KM_SUCCESS(result) ) - result = File.Read(ReadBuf.Data(), ReadBuf.Capacity(), &read_size); - - if ( KM_SUCCESS(result) ) - outString.assign((const char*)ReadBuf.RoData(), read_size); - - return result; -} - - -// -Kumu::Result_t -Kumu::WriteStringIntoFile(const char* filename, const std::string& inString) -{ - FileWriter File; - ui32_t write_count = 0; - KM_TEST_NULL_STR_L(filename); - - Result_t result = File.OpenWrite(filename); - - if ( KM_SUCCESS(result) ) - result = File.Write((byte_t*)inString.c_str(), inString.length(), &write_count); - - return result; -} - -//------------------------------------------------------------------------------------------ - - -// -Kumu::Result_t -Kumu::ReadFileIntoObject(const std::string& Filename, Kumu::IArchive& Object, ui32_t) -{ - ByteString Buffer; - ui32_t file_size = static_cast<ui32_t>(FileSize(Filename)); - Result_t result = Buffer.Capacity(file_size); - - if ( KM_SUCCESS(result) ) - { - ui32_t read_count = 0; - FileWriter Reader; - - result = Reader.OpenRead(Filename.c_str()); - - if ( KM_SUCCESS(result) ) - result = Reader.Read(Buffer.Data(), file_size, &read_count); - - if ( KM_SUCCESS(result) ) - { - assert(file_size == read_count); - Buffer.Length(read_count); - MemIOReader MemReader(&Buffer); - result = Object.Unarchive(&MemReader) ? RESULT_OK : RESULT_READFAIL; - } - } - - return result; -} - -// -Kumu::Result_t -Kumu::WriteObjectIntoFile(const Kumu::IArchive& Object, const std::string& Filename) -{ - ByteString Buffer; - Result_t result = Buffer.Capacity(Object.ArchiveLength()); - - if ( KM_SUCCESS(result) ) - { - ui32_t write_count = 0; - FileWriter Writer; - MemIOWriter MemWriter(&Buffer); - - result = Object.Archive(&MemWriter) ? RESULT_OK : RESULT_WRITEFAIL; - - if ( KM_SUCCESS(result) ) - { - Buffer.Length(MemWriter.Length()); - result = Writer.OpenWrite(Filename.c_str()); - } - - if ( KM_SUCCESS(result) ) - result = Writer.Write(Buffer.RoData(), Buffer.Length(), &write_count); - } - - return result; -} - -//------------------------------------------------------------------------------------------ -// - -// -Result_t -Kumu::ReadFileIntoBuffer(const std::string& Filename, Kumu::ByteString& Buffer, ui32_t) -{ - ui32_t file_size = FileSize(Filename); - Result_t result = Buffer.Capacity(file_size); - - if ( KM_SUCCESS(result) ) - { - ui32_t read_count = 0; - FileWriter Reader; - - result = Reader.OpenRead(Filename.c_str()); - - if ( KM_SUCCESS(result) ) - result = Reader.Read(Buffer.Data(), file_size, &read_count); - - if ( KM_SUCCESS(result) ) - { - if ( file_size != read_count) - return RESULT_READFAIL; - - Buffer.Length(read_count); - } - } - - return result; -} - -// -Result_t -Kumu::WriteBufferIntoFile(const Kumu::ByteString& Buffer, const std::string& Filename) -{ - ui32_t write_count = 0; - FileWriter Writer; - - Result_t result = Writer.OpenWrite(Filename.c_str()); - - if ( KM_SUCCESS(result) ) - result = Writer.Write(Buffer.RoData(), Buffer.Length(), &write_count); - - if ( KM_SUCCESS(result) && Buffer.Length() != write_count) - return RESULT_WRITEFAIL; - - return result; -} - -//------------------------------------------------------------------------------------------ -// - -Kumu::DirScanner::DirScanner() -{ - -} - -Result_t -Kumu::DirScanner::Open (const char* filename) -{ - KM_TEST_NULL_L (filename); - - if (!boost::filesystem::is_directory(filename)) { - return RESULT_NOT_FOUND; - } - - _iterator = boost::filesystem::directory_iterator (filename); - return RESULT_OK; -} - -Result_t -Kumu::DirScanner::GetNext (char* filename) -{ - KM_TEST_NULL_L (filename); - - if (_iterator == boost::filesystem::directory_iterator()) { - return RESULT_ENDOFFILE; - } - -#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; -} - -//------------------------------------------------------------------------------------------ - -// -// Attention Windows users: make sure to use the proper separator character -// with these functions. -// - -// given a path string, create any missing directories so that PathIsDirectory(Path) is true. -// -Result_t -Kumu::CreateDirectoriesInPath(const std::string& Path) -{ - bool abs = PathIsAbsolute(Path); - PathCompList_t PathComps, TmpPathComps; - - PathToComponents(Path, PathComps); - - while ( ! PathComps.empty() ) - { - TmpPathComps.push_back(PathComps.front()); - PathComps.pop_front(); - std::string tmp_path = abs ? ComponentsToAbsolutePath(TmpPathComps) : ComponentsToPath(TmpPathComps); - - if ( ! PathIsDirectory(tmp_path) ) - { -#ifdef KM_WIN32 - if ( _mkdir(tmp_path.c_str()) != 0 ) -#else // KM_WIN32 - if ( mkdir(tmp_path.c_str(), 0775) != 0 ) -#endif // KM_WIN32 - { - DefaultLogSink().Error("CreateDirectoriesInPath mkdir %s: %s\n", - tmp_path.c_str(), strerror(errno)); - return RESULT_DIR_CREATE; - } - } - } - - return RESULT_OK; -} - - -// -Result_t -Kumu::DeleteFile(const std::string& filename) -{ - if ( _unlink(filename.c_str()) == 0 ) - return RESULT_OK; - - switch ( errno ) - { - case ENOENT: - case ENOTDIR: return RESULT_NOTAFILE; - - case EROFS: - case EBUSY: - case EACCES: - case EPERM: return RESULT_NO_PERM; - } - - DefaultLogSink().Error("DeleteFile %s: %s\n", filename.c_str(), strerror(errno)); - return RESULT_FAIL; -} - -// -Result_t -h__DeletePath(const std::string& pathname) -{ - if ( pathname.empty() ) - return RESULT_NULL_STR; - - Result_t result = RESULT_OK; - - if ( ! PathIsDirectory(pathname) ) - { - result = DeleteFile(pathname); - } - else - { - { - DirScanner TestDir; - char next_file[Kumu::MaxFilePath]; - result = TestDir.Open(pathname.c_str()); - - while ( KM_SUCCESS(result) && KM_SUCCESS(TestDir.GetNext(next_file)) ) - { - if ( next_file[0] == '.' ) - { - if ( next_file[1] == 0 ) - continue; // don't delete 'this' - - if ( next_file[1] == '.' && next_file[2] == 0 ) - continue; // don't delete 'this' parent - } - - result = h__DeletePath(pathname + std::string("/") + next_file); - } - } - - if ( _rmdir(pathname.c_str()) != 0 ) - { - switch ( errno ) - { - case ENOENT: - case ENOTDIR: - result = RESULT_NOTAFILE; - break; - - case EROFS: - case EBUSY: - case EACCES: - case EPERM: - result = RESULT_NO_PERM; - break; - - default: - DefaultLogSink().Error("DeletePath %s: %s\n", pathname.c_str(), strerror(errno)); - result = RESULT_FAIL; - } - } - } - - return result; -} - -// -Result_t -Kumu::DeletePath(const std::string& pathname) -{ - std::string c_pathname = PathMakeAbsolute(PathMakeCanonical(pathname)); - DefaultLogSink().Debug("DeletePath (%s) c(%s)\n", pathname.c_str(), c_pathname.c_str()); - return h__DeletePath(c_pathname); -} - - -//------------------------------------------------------------------------------------------ -// - - -Result_t -Kumu::FreeSpaceForPath(const std::string& path, Kumu::fsize_t& free_space, Kumu::fsize_t& total_space) -{ -#ifdef KM_WIN32 - ULARGE_INTEGER lTotalNumberOfBytes; - ULARGE_INTEGER lTotalNumberOfFreeBytes; - - BOOL fResult = ::GetDiskFreeSpaceExA(path.c_str(), NULL, &lTotalNumberOfBytes, &lTotalNumberOfFreeBytes); - if (fResult) { - free_space = static_cast<Kumu::fsize_t>(lTotalNumberOfFreeBytes.QuadPart); - total_space = static_cast<Kumu::fsize_t>(lTotalNumberOfBytes.QuadPart); - return RESULT_OK; - } - HRESULT LastError = ::GetLastError(); - - DefaultLogSink().Error("FreeSpaceForPath GetDiskFreeSpaceEx %s: %lu\n", path.c_str(), ::GetLastError()); - return RESULT_FAIL; -#else // KM_WIN32 - struct statfs s; - - if ( statfs(path.c_str(), &s) == 0 ) - { - if ( s.f_blocks < 1 ) - { - DefaultLogSink().Error("File system %s has impossible size: %ld\n", - path.c_str(), s.f_blocks); - return RESULT_FAIL; - } - - free_space = (Kumu::fsize_t)s.f_bsize * (Kumu::fsize_t)s.f_bavail; - total_space = (Kumu::fsize_t)s.f_bsize * (Kumu::fsize_t)s.f_blocks; - return RESULT_OK; - } - - switch ( errno ) - { - case ENOENT: - case ENOTDIR: return RESULT_NOTAFILE; - case EACCES: return RESULT_NO_PERM; - } - - DefaultLogSink().Error("FreeSpaceForPath statfs %s: %s\n", path.c_str(), strerror(errno)); - return RESULT_FAIL; -#endif // KM_WIN32 -} - - -// -// end KM_fileio.cpp -// |
