459 lines
11 KiB
C++
459 lines
11 KiB
C++
// Copyright (c) 2014, The Monero Project
|
|
//
|
|
// 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. Neither the name of the copyright holder nor the names of its contributors may be
|
|
// used to endorse or promote products derived from this software without specific
|
|
// prior written permission.
|
|
//
|
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER OR CONTRIBUTORS 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.
|
|
//
|
|
// Parts of this file are originally copyright (c) 2006-2013, Andrey N. Sabelnikov
|
|
|
|
#ifndef _FILE_IO_UTILS_H_
|
|
#define _FILE_IO_UTILS_H_
|
|
|
|
|
|
//#include <sys/types.h>
|
|
//#include <sys/stat.h>
|
|
|
|
#include <iostream>
|
|
#include <boost/filesystem.hpp>
|
|
|
|
|
|
#ifndef MAKE64
|
|
#define MAKE64(low,high) ((__int64)(((DWORD)(low)) | ((__int64)((DWORD)(high))) << 32))
|
|
#endif
|
|
|
|
#ifdef WINDOWS_PLATFORM
|
|
#include <psapi.h>
|
|
#include <strsafe.h>
|
|
#include <string.h>
|
|
#include <mbstring.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
namespace epee
|
|
{
|
|
namespace file_io_utils
|
|
{
|
|
#ifdef WINDOWS_PLATFORM
|
|
|
|
inline
|
|
std::string get_temp_file_name_a()
|
|
{
|
|
std::string str_result;
|
|
char sz_temp[MAX_PATH*2] = {0};
|
|
if(!::GetTempPathA( sizeof( sz_temp ), sz_temp ))
|
|
return str_result;
|
|
|
|
char sz_temp_file[MAX_PATH*2] = {0};
|
|
if(!::GetTempFileNameA( sz_temp, "mail", 0, sz_temp_file))
|
|
return str_result;
|
|
sz_temp_file[sizeof(sz_temp_file)-1] = 0; //be happy!
|
|
str_result = sz_temp_file;
|
|
return str_result;
|
|
}
|
|
|
|
|
|
#ifdef BOOST_LEXICAL_CAST_INCLUDED
|
|
inline
|
|
bool get_not_used_filename(const std::string& folder, OUT std::string& result_name)
|
|
{
|
|
DWORD folder_attr = ::GetFileAttributesA(folder.c_str());
|
|
if(folder_attr == INVALID_FILE_ATTRIBUTES)
|
|
return false;
|
|
if(!(folder_attr&FILE_ATTRIBUTE_DIRECTORY))
|
|
return false;
|
|
|
|
|
|
std::string base_name = folder + "\\tmp";
|
|
std::string tmp_name;
|
|
bool name_found = false;
|
|
int current_index = 0;
|
|
tmp_name = base_name + boost::lexical_cast<std::string>(current_index) + ".tmp";
|
|
while(!name_found)
|
|
{
|
|
if(INVALID_FILE_ATTRIBUTES == ::GetFileAttributesA(tmp_name.c_str()))
|
|
name_found = true;
|
|
else
|
|
{
|
|
current_index++;
|
|
tmp_name = base_name + boost::lexical_cast<std::string>(current_index) + ".tmp";
|
|
}
|
|
}
|
|
result_name = tmp_name;
|
|
return true;
|
|
}
|
|
#endif
|
|
|
|
inline
|
|
std::string get_temp_folder_a()
|
|
{
|
|
std::string str_result;
|
|
char sz_temp[MAX_PATH*2] = {0};
|
|
if(!::GetTempPathA( sizeof( sz_temp ), sz_temp ))
|
|
return str_result;
|
|
sz_temp[(sizeof(sz_temp)/sizeof(sz_temp[0])) -1] = 0;
|
|
str_result = sz_temp;
|
|
return str_result;
|
|
}
|
|
|
|
std::string convert_from_device_path_to_standart(const std::string& path)
|
|
{
|
|
|
|
|
|
STRSAFE_LPSTR pszFilename = (STRSAFE_LPSTR)path.c_str();
|
|
|
|
// Translate path with device name to drive letters.
|
|
char szTemp[4000] = {0};
|
|
|
|
if (::GetLogicalDriveStringsA(sizeof(szTemp)-1, szTemp))
|
|
{
|
|
char szName[MAX_PATH];
|
|
char szDrive[3] = " :";
|
|
BOOL bFound = FALSE;
|
|
char* p = szTemp;
|
|
|
|
do
|
|
{
|
|
// Copy the drive letter to the template string
|
|
*szDrive = *p;
|
|
|
|
// Look up each device name
|
|
if (::QueryDosDeviceA(szDrive, szName, sizeof(szName)))
|
|
{
|
|
UINT uNameLen = strlen(szName);
|
|
|
|
if (uNameLen < MAX_PATH)
|
|
{
|
|
bFound = _mbsnbicmp((const unsigned char*)pszFilename, (const unsigned char*)szName,
|
|
uNameLen) == 0;
|
|
|
|
if (bFound)
|
|
{
|
|
// Reconstruct pszFilename using szTempFile
|
|
// Replace device path with DOS path
|
|
char szTempFile[MAX_PATH] = {0};
|
|
StringCchPrintfA(szTempFile,
|
|
MAX_PATH,
|
|
"%s%s",
|
|
szDrive,
|
|
pszFilename+uNameLen);
|
|
return szTempFile;
|
|
//::StringCchCopyNA(pszFilename, MAX_PATH+1, szTempFile, strlen(szTempFile));
|
|
}
|
|
}
|
|
}
|
|
|
|
// Go to the next NULL character.
|
|
while (*p++);
|
|
} while (!bFound && *p); // end of string
|
|
}
|
|
|
|
return "";
|
|
}
|
|
|
|
inline
|
|
std::string get_process_path_by_pid(DWORD pid)
|
|
{
|
|
std::string res;
|
|
|
|
HANDLE hprocess = 0;
|
|
if( hprocess = ::OpenProcess( PROCESS_QUERY_INFORMATION|PROCESS_VM_READ, FALSE, pid) )
|
|
{
|
|
char buff[MAX_PATH]= {0};
|
|
if(!::GetModuleFileNameExA( hprocess, 0, buff, MAX_PATH - 1 ))
|
|
res = "Unknown_b";
|
|
else
|
|
{
|
|
buff[MAX_PATH - 1]=0; //be happy!
|
|
res = buff;
|
|
std::string::size_type a = res.rfind( '\\' );
|
|
if ( a != std::string::npos )
|
|
res.erase( 0, a+1);
|
|
|
|
}
|
|
::CloseHandle( hprocess );
|
|
}else
|
|
res = "Unknown_a";
|
|
|
|
return res;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
inline
|
|
std::wstring get_temp_file_name_w()
|
|
{
|
|
std::wstring str_result;
|
|
wchar_t sz_temp[MAX_PATH*2] = {0};
|
|
if(!::GetTempPathW( sizeof(sz_temp)/sizeof(sz_temp[0]), sz_temp ))
|
|
return str_result;
|
|
|
|
wchar_t sz_temp_file[MAX_PATH+1] = {0};
|
|
if(!::GetTempFileNameW( sz_temp, L"mail", 0, sz_temp_file))
|
|
return str_result;
|
|
|
|
sz_temp_file[(sizeof(sz_temp_file)/sizeof(sz_temp_file[0]))-1] = 0; //be happy!
|
|
str_result = sz_temp_file;
|
|
return str_result;
|
|
}
|
|
#endif
|
|
inline
|
|
bool is_file_exist(const std::string& path)
|
|
{
|
|
boost::filesystem::path p(path);
|
|
return boost::filesystem::exists(p);
|
|
}
|
|
|
|
/*
|
|
inline
|
|
bool save_string_to_handle(HANDLE hfile, const std::string& str)
|
|
{
|
|
|
|
|
|
|
|
if( INVALID_HANDLE_VALUE != hfile )
|
|
{
|
|
DWORD dw;
|
|
if( !::WriteFile( hfile, str.data(), (DWORD) str.size(), &dw, NULL) )
|
|
{
|
|
int err_code = GetLastError();
|
|
//LOG_PRINT("Failed to write to file handle: " << hfile<< " Last error code:" << err_code << " : " << log_space::get_win32_err_descr(err_code), LOG_LEVEL_2);
|
|
return false;
|
|
}
|
|
::CloseHandle(hfile);
|
|
return true;
|
|
}else
|
|
{
|
|
//LOG_WIN32_ERROR(::GetLastError());
|
|
return false;
|
|
}
|
|
|
|
return false;
|
|
}*/
|
|
|
|
|
|
|
|
inline
|
|
bool save_string_to_file(const std::string& path_to_file, const std::string& str)
|
|
{
|
|
|
|
try
|
|
{
|
|
std::ofstream fstream;
|
|
fstream.exceptions(std::ifstream::failbit | std::ifstream::badbit);
|
|
fstream.open(path_to_file, std::ios_base::binary | std::ios_base::out | std::ios_base::trunc);
|
|
fstream << str;
|
|
fstream.close();
|
|
return true;
|
|
}
|
|
|
|
catch(...)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/*
|
|
inline
|
|
bool load_form_handle(HANDLE hfile, std::string& str)
|
|
{
|
|
if( INVALID_HANDLE_VALUE != hfile )
|
|
{
|
|
bool res = true;
|
|
DWORD dw = 0;
|
|
DWORD fsize = ::GetFileSize(hfile, &dw);
|
|
if(fsize > 300000000)
|
|
{
|
|
::CloseHandle(hfile);
|
|
return false;
|
|
}
|
|
if(fsize)
|
|
{
|
|
str.resize(fsize);
|
|
if(!::ReadFile( hfile, (LPVOID)str.data(), (DWORD)str.size(), &dw, NULL))
|
|
res = false;
|
|
}
|
|
::CloseHandle(hfile);
|
|
return res;
|
|
}
|
|
return false;
|
|
}
|
|
*/
|
|
inline
|
|
bool get_file_time(const std::string& path_to_file, OUT time_t& ft)
|
|
{
|
|
boost::system::error_code ec;
|
|
ft = boost::filesystem::last_write_time(boost::filesystem::path(path_to_file), ec);
|
|
if(!ec)
|
|
return true;
|
|
else
|
|
return false;
|
|
}
|
|
|
|
inline
|
|
bool set_file_time(const std::string& path_to_file, const time_t& ft)
|
|
{
|
|
boost::system::error_code ec;
|
|
boost::filesystem::last_write_time(boost::filesystem::path(path_to_file), ft, ec);
|
|
if(!ec)
|
|
return true;
|
|
else
|
|
return false;
|
|
}
|
|
|
|
|
|
inline
|
|
bool load_file_to_string(const std::string& path_to_file, std::string& target_str)
|
|
{
|
|
try
|
|
{
|
|
std::ifstream fstream;
|
|
fstream.exceptions(std::ifstream::failbit | std::ifstream::badbit);
|
|
fstream.open(path_to_file, std::ios_base::binary | std::ios_base::in | std::ios::ate);
|
|
|
|
std::ifstream::pos_type file_size = fstream.tellg();
|
|
|
|
if(file_size > 1000000000)
|
|
return false;//don't go crazy
|
|
size_t file_size_t = static_cast<size_t>(file_size);
|
|
|
|
target_str.resize(file_size_t);
|
|
|
|
fstream.seekg (0, std::ios::beg);
|
|
fstream.read((char*)target_str.data(), target_str.size());
|
|
fstream.close();
|
|
return true;
|
|
}
|
|
|
|
catch(...)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
inline
|
|
bool append_string_to_file(const std::string& path_to_file, const std::string& str)
|
|
{
|
|
try
|
|
{
|
|
std::ofstream fstream;
|
|
fstream.exceptions(std::ifstream::failbit | std::ifstream::badbit);
|
|
fstream.open(path_to_file.c_str(), std::ios_base::binary | std::ios_base::out | std::ios_base::app);
|
|
fstream << str;
|
|
fstream.close();
|
|
return true;
|
|
}
|
|
|
|
catch(...)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/*
|
|
bool remove_dir_and_subirs(const char* path_to_dir);
|
|
|
|
inline
|
|
bool clean_dir(const char* path_to_dir)
|
|
{
|
|
if(!path_to_dir)
|
|
return false;
|
|
|
|
std::string folder = path_to_dir;
|
|
WIN32_FIND_DATAA find_data = {0};
|
|
HANDLE hfind = ::FindFirstFileA((folder + "\\*.*").c_str(), &find_data);
|
|
if(INVALID_HANDLE_VALUE == hfind)
|
|
return false;
|
|
do{
|
|
if(!strcmp("..", find_data.cFileName) || (!strcmp(".", find_data.cFileName)))
|
|
continue;
|
|
|
|
if(find_data.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
|
|
{
|
|
if(!remove_dir_and_subirs((folder + "\\" + find_data.cFileName).c_str()))
|
|
return false;
|
|
}else
|
|
{
|
|
if(!::DeleteFileA((folder + "\\" + find_data.cFileName).c_str()))
|
|
return false;
|
|
}
|
|
|
|
|
|
}while(::FindNextFileA(hfind, &find_data));
|
|
::FindClose(hfind);
|
|
|
|
return true;
|
|
}
|
|
*/
|
|
#ifdef WINDOWS_PLATFORM
|
|
inline bool get_folder_content(const std::string& path, std::list<WIN32_FIND_DATAA>& OUT target_list)
|
|
{
|
|
WIN32_FIND_DATAA find_data = {0};
|
|
HANDLE hfind = ::FindFirstFileA((path + "\\*.*").c_str(), &find_data);
|
|
if(INVALID_HANDLE_VALUE == hfind)
|
|
return false;
|
|
do{
|
|
if(!strcmp("..", find_data.cFileName) || (!strcmp(".", find_data.cFileName)))
|
|
continue;
|
|
|
|
target_list.push_back(find_data);
|
|
|
|
}while(::FindNextFileA(hfind, &find_data));
|
|
::FindClose(hfind);
|
|
|
|
return true;
|
|
}
|
|
#endif
|
|
inline bool get_folder_content(const std::string& path, std::list<std::string>& OUT target_list, bool only_files = false)
|
|
{
|
|
try
|
|
{
|
|
|
|
boost::filesystem::directory_iterator end_itr; // default construction yields past-the-end
|
|
for ( boost::filesystem::directory_iterator itr( path ); itr != end_itr; ++itr )
|
|
{
|
|
if ( only_files && boost::filesystem::is_directory(itr->status()) )
|
|
{
|
|
continue;
|
|
}
|
|
target_list.push_back(itr->path().filename().string());
|
|
}
|
|
|
|
}
|
|
|
|
catch(...)
|
|
{
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif //_FILE_IO_UTILS_H_
|