Electroneum
Loading...
Searching...
No Matches
file_io_utils.h
Go to the documentation of this file.
1// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are met:
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above copyright
9// notice, this list of conditions and the following disclaimer in the
10// documentation and/or other materials provided with the distribution.
11// * Neither the name of the Andrey N. Sabelnikov nor the
12// names of its contributors may be used to endorse or promote products
13// derived from this software without specific prior written permission.
14//
15// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY
19// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25//
26
27
28#ifndef _FILE_IO_UTILS_H_
29#define _FILE_IO_UTILS_H_
30
31#include <fstream>
32#include <boost/filesystem/path.hpp>
33#include <boost/filesystem/operations.hpp>
34#ifdef WIN32
35#include <windows.h>
36#include "string_tools.h"
37#endif
38
39// On Windows there is a problem with non-ASCII characters in path and file names
40// as far as support by the standard components used is concerned:
41
42// The various file stream classes, e.g. std::ifstream and std::ofstream, are
43// part of the GNU C++ Library / libstdc++. On the most basic level they use the
44// fopen() call as defined / made accessible to programs compiled within MSYS2
45// by the stdio.h header file maintained by the MinGW project.
46
47// The critical point: The implementation of fopen() is part of MSVCRT, the
48// Microsoft Visual C/C++ Runtime Library, and this method does NOT offer any
49// Unicode support.
50
51// Electroneum code that would want to continue to use the normal file stream classes
52// but WITH Unicode support could therefore not solve this problem on its own,
53// but 2 different projects from 2 different maintaining groups would need changes
54// in this particular direction - something probably difficult to achieve and
55// with a long time to wait until all new versions / releases arrive.
56
57// Implemented solution approach: Circumvent the problem by stopping to use std
58// file stream classes on Windows and directly use Unicode-capable WIN32 API
59// calls. Most of the code doing so is concentrated in this header file here.
60
61namespace epee
62{
64{
65 inline
66 bool is_file_exist(const std::string& path)
67 {
68 boost::filesystem::path p(path);
69 return boost::filesystem::exists(p);
70 }
71
72 inline
73 bool save_string_to_file(const std::string& path_to_file, const std::string& str)
74 {
75#ifdef WIN32
76 std::wstring wide_path;
77 try { wide_path = string_tools::utf8_to_utf16(path_to_file); } catch (...) { return false; }
78 HANDLE file_handle = CreateFileW(wide_path.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
79 if (file_handle == INVALID_HANDLE_VALUE)
80 return false;
81 DWORD bytes_written;
82 DWORD bytes_to_write = (DWORD)str.size();
83 BOOL result = WriteFile(file_handle, str.data(), bytes_to_write, &bytes_written, NULL);
84 CloseHandle(file_handle);
85 if (bytes_written != bytes_to_write)
86 result = FALSE;
87 return result;
88#else
89 try
90 {
91 std::ofstream fstream;
92 fstream.exceptions(std::ifstream::failbit | std::ifstream::badbit);
93 fstream.open(path_to_file, std::ios_base::binary | std::ios_base::out | std::ios_base::trunc);
94 fstream << str;
95 fstream.close();
96 return true;
97 }
98
99 catch(...)
100 {
101 return false;
102 }
103#endif
104 }
105
106 inline
107 bool get_file_time(const std::string& path_to_file, time_t& ft)
108 {
109 boost::system::error_code ec;
110 ft = boost::filesystem::last_write_time(boost::filesystem::path(path_to_file), ec);
111 if(!ec)
112 return true;
113 else
114 return false;
115 }
116
117 inline
118 bool set_file_time(const std::string& path_to_file, const time_t& ft)
119 {
120 boost::system::error_code ec;
121 boost::filesystem::last_write_time(boost::filesystem::path(path_to_file), ft, ec);
122 if(!ec)
123 return true;
124 else
125 return false;
126 }
127
128
129 inline
130 bool load_file_to_string(const std::string& path_to_file, std::string& target_str, size_t max_size = 1000000000)
131 {
132#ifdef WIN32
133 std::wstring wide_path;
134 try { wide_path = string_tools::utf8_to_utf16(path_to_file); } catch (...) { return false; }
135 HANDLE file_handle = CreateFileW(wide_path.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
136 if (file_handle == INVALID_HANDLE_VALUE)
137 return false;
138 DWORD file_size = GetFileSize(file_handle, NULL);
139 if ((file_size == INVALID_FILE_SIZE) || (uint64_t)file_size > (uint64_t)max_size) {
140 CloseHandle(file_handle);
141 return false;
142 }
143 target_str.resize(file_size);
144 DWORD bytes_read;
145 BOOL result = ReadFile(file_handle, &target_str[0], file_size, &bytes_read, NULL);
146 CloseHandle(file_handle);
147 if (bytes_read != file_size)
148 result = FALSE;
149 return result;
150#else
151 try
152 {
153 std::ifstream fstream;
154 fstream.exceptions(std::ifstream::failbit | std::ifstream::badbit);
155 fstream.open(path_to_file, std::ios_base::binary | std::ios_base::in | std::ios::ate);
156
157 std::ifstream::pos_type file_size = fstream.tellg();
158
159 if((uint64_t)file_size > (uint64_t)max_size) // ensure a large domain for comparison, and negative -> too large
160 return false;//don't go crazy
161 size_t file_size_t = static_cast<size_t>(file_size);
162
163 target_str.resize(file_size_t);
164
165 fstream.seekg (0, std::ios::beg);
166 fstream.read((char*)target_str.data(), target_str.size());
167 fstream.close();
168 return true;
169 }
170
171 catch(...)
172 {
173 return false;
174 }
175#endif
176 }
177
178 inline
179 bool append_string_to_file(const std::string& path_to_file, const std::string& str)
180 {
181 // No special Windows implementation because so far not used in Electroneum code
182 try
183 {
184 std::ofstream fstream;
185 fstream.exceptions(std::ifstream::failbit | std::ifstream::badbit);
186 fstream.open(path_to_file.c_str(), std::ios_base::binary | std::ios_base::out | std::ios_base::app);
187 fstream << str;
188 fstream.close();
189 return true;
190 }
191
192 catch(...)
193 {
194 return false;
195 }
196 }
197
198 inline
199 bool get_file_size(const std::string& path_to_file, uint64_t &size)
200 {
201#ifdef WIN32
202 std::wstring wide_path;
203 try { wide_path = string_tools::utf8_to_utf16(path_to_file); } catch (...) { return false; }
204 HANDLE file_handle = CreateFileW(wide_path.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
205 if (file_handle == INVALID_HANDLE_VALUE)
206 return false;
207 LARGE_INTEGER file_size;
208 BOOL result = GetFileSizeEx(file_handle, &file_size);
209 CloseHandle(file_handle);
210 if (result) {
211 size = file_size.QuadPart;
212 }
213 return size;
214#else
215 try
216 {
217 std::ifstream fstream;
218 fstream.exceptions(std::ifstream::failbit | std::ifstream::badbit);
219 fstream.open(path_to_file, std::ios_base::binary | std::ios_base::in | std::ios::ate);
220 size = fstream.tellg();
221 fstream.close();
222 return true;
223 }
224
225 catch(...)
226 {
227 return false;
228 }
229#endif
230 }
231
232}
233}
234
235#endif //_FILE_IO_UTILS_H_
bool set_file_time(const std::string &path_to_file, const time_t &ft)
bool get_file_size(const std::string &path_to_file, uint64_t &size)
bool load_file_to_string(const std::string &path_to_file, std::string &target_str, size_t max_size=1000000000)
bool append_string_to_file(const std::string &path_to_file, const std::string &str)
bool get_file_time(const std::string &path_to_file, time_t &ft)
bool save_string_to_file(const std::string &path_to_file, const std::string &str)
bool is_file_exist(const std::string &path)
unsigned __int64 uint64_t
Definition stdint.h:136