Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
filesystem.cpp
Go to the documentation of this file.
1//#define BOOST_NO_SCOPED_ENUMS
2#include <fc/filesystem.hpp>
4#include <fc/fwd_impl.hpp>
5#include <fc/utility.hpp>
6
7#include <fc/utf8.hpp>
8#include <fc/variant.hpp>
9
10#include <boost/config.hpp>
11#include <boost/filesystem.hpp>
12
13#include <fstream>
14
15#ifdef _WIN32
16# include <windows.h>
17# include <userenv.h>
18# include <shlobj.h>
19#else
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #include <pwd.h>
23# ifdef FC_HAS_SIMPLE_FILE_LOCK
24 #include <sys/file.h>
25 #include <fcntl.h>
26# endif
27#endif
28
29namespace fc {
30 // when converting to and from a variant, store utf-8 in the variant
31 void to_variant( const fc::path& path_to_convert, variant& variant_output )
32 {
33 std::wstring wide_string = path_to_convert.generic_wstring();
34 std::string utf8_string;
35 fc::encodeUtf8(wide_string, &utf8_string);
36 variant_output = utf8_string;
37
38 //std::string path = t.to_native_ansi_path();
39 //std::replace(path.begin(), path.end(), '\\', '/');
40 //v = path;
41 }
42
43 void from_variant( const fc::variant& variant_to_convert, fc::path& path_output )
44 {
45 std::wstring wide_string;
46 fc::decodeUtf8(variant_to_convert.as_string(), &wide_string);
47 path_output = path(wide_string);
48 }
49
50 // Note: we can do this cast because the separator should be an ASCII character
51 char path::separator_char = static_cast<char>(boost::filesystem::path("/").make_preferred().native()[0]);
52
55 path::path( const boost::filesystem::path& p )
56 :_p(p){}
57
58 path::path( const char* p )
59 :_p(p){}
61 :_p(p.c_str()){}
62
63 path::path(const std::wstring& p)
64 :_p(p) {}
65
66 path::path( const path& p )
67 :_p(p){}
68
70 :_p(std::move(p)){}
71
73 *_p = *p._p;
74 return *this;
75 }
77 *_p = fc::move( *p._p );
78 return *this;
79 }
80
81 bool operator <( const fc::path& l, const fc::path& r ) { return *l._p < *r._p; }
82 bool operator ==( const fc::path& l, const fc::path& r ) { return *l._p == *r._p; }
83 bool operator !=( const fc::path& l, const fc::path& r ) { return *l._p != *r._p; }
84
86 *_p /= *p._p;
87 return *this;
88 }
89 path operator /( const fc::path& p, const fc::path& o ) {
90 path tmp;
91 tmp = *p._p / *o._p;
92 return tmp;
93 }
94
95 path::operator boost::filesystem::path& () {
96 return *_p;
97 }
98 path::operator const boost::filesystem::path& ()const {
99 return *_p;
100 }
102 return _p->generic_string();
103 }
104
106 {
107 return boost::filesystem::path(*_p).make_preferred().string();
108 }
109
110 std::wstring path::wstring() const
111 {
112 return _p->wstring();
113 }
114
115 std::wstring path::generic_wstring() const
116 {
117 return _p->generic_wstring();
118 }
119
120 std::wstring path::preferred_wstring() const
121 {
122 return boost::filesystem::path(*_p).make_preferred().wstring();
123 }
124
125 std::string path::to_native_ansi_path() const
126 {
127 std::wstring path = generic_wstring();
128
129#ifdef WIN32
130 const size_t maxPath = 32*1024;
131 std::vector<wchar_t> short_path;
132 short_path.resize(maxPath + 1);
133
134 wchar_t* buffer = short_path.data();
135 DWORD res = GetShortPathNameW(path.c_str(), buffer, maxPath);
136 if(res != 0)
137 path = buffer;
138#endif
139 std::string filePath;
140 fc::encodeUtf8(path, &filePath);
141 return filePath;
142 }
143
149 std::string result = _p->generic_string();
150 std::replace(result.begin(), result.end(), '/', '\\');
151 return result;
152 }
153
155 return _p->string();
156 }
158 return _p->filename();
159 }
161 _p->replace_extension(e);
162 }
164 return _p->extension();
165 }
167 return _p->stem();
168 }
170 return _p->parent_path();
171 }
172 bool path::is_relative()const { return _p->is_relative(); }
173 bool path::is_absolute()const { return _p->is_absolute(); }
174
175 bool path::empty() const { return _p->empty(); }
176
179
182
183 fc::path directory_iterator::operator*()const { return boost::filesystem::path(*(*_p)); }
184 detail::path_wrapper directory_iterator::operator->() const { return detail::path_wrapper(boost::filesystem::path(*(*_p))); }
185 directory_iterator& directory_iterator::operator++(int) { (*_p)++; return *this; }
187
189 return *r._p == *l._p;
190 }
192 return *r._p != *l._p;
193 }
194
195
198
201
202 fc::path recursive_directory_iterator::operator*()const { return boost::filesystem::path(*(*_p)); }
205
207 int recursive_directory_iterator::level() { return _p->level(); }
208
210 return *r._p == *l._p;
211 }
213 return *r._p != *l._p;
214 }
215
216
217 bool exists( const path& p ) { return boost::filesystem::exists(p); }
218 void create_directories( const path& p ) {
219 try {
220 boost::filesystem::create_directories(p);
221 } catch ( ... ) {
222 FC_THROW( "Unable to create directories ${path}", ("path", p )("inner", fc::except_str() ) );
223 }
224 }
225 bool is_directory( const path& p ) { return boost::filesystem::is_directory(p); }
226 bool is_regular_file( const path& p ) { return boost::filesystem::is_regular_file(p); }
227 uint64_t file_size( const path& p ) { return boost::filesystem::file_size(p); }
228
230 {
231 try {
233
235 uint64_t size = 0;
236 for( recursive_directory_iterator itr( p ); itr != end; ++itr )
237 {
238 if( is_regular_file( *itr ) )
239 size += file_size( *itr );
240 }
241
242 return size;
243 } catch ( ... ) {
244 FC_THROW( "Unable to calculate size of directory ${path}", ("path", p )("inner", fc::except_str() ) );
245 }
246 }
247
248 void remove_all( const path& p ) { boost::filesystem::remove_all(p); }
249 void copy( const path& f, const path& t ) {
250 boost::system::error_code ec;
251 try {
252 #if BOOST_VERSION > 107300
253 if (exists(t)){
254 throw boost::system::system_error(boost::system::errc::make_error_code(boost::system::errc::errc_t::file_exists));
255 }
256 if ( boost::filesystem::is_directory( f ) ) {
257 boost::filesystem::copy(boost::filesystem::path(f),
258 boost::filesystem::path(t),
259 boost::filesystem::copy_options::directories_only,
260 ec );
261 } else {
262 boost::filesystem::copy(boost::filesystem::path(f),
263 boost::filesystem::path(t),
264 boost::filesystem::copy_options::none,
265 ec );
266 }
267 #else
268 boost::filesystem::copy( boost::filesystem::path(f), boost::filesystem::path(t), ec );
269 #endif
270 } catch ( boost::system::system_error& e ) {
271 FC_THROW( "Copy from ${srcfile} to ${dstfile} failed because ${reason}",
272 ("srcfile",f)("dstfile",t)("reason",e.what() ) );
273 } catch ( ... ) {
274 FC_THROW( "Copy from ${srcfile} to ${dstfile} failed",
275 ("srcfile",f)("dstfile",t)("inner", fc::except_str() ) );
276 }
277 if( ec ) {
278 FC_THROW( "Copy from ${srcfile} to ${dstfile} failed because ${reason}, category: ${cat}",
279 ("srcfile",f)("dstfile",t)("reason", ec.message())("cat", ec.category().name()) );
280 }
281 }
282 void resize_file( const path& f, size_t t )
283 {
284 try {
285 boost::filesystem::resize_file( f, t );
286 }
287 catch ( boost::system::system_error& e )
288 {
289 FC_THROW( "Resize file '${f}' to size ${s} failed: ${reason}",
290 ("f",f)("s",t)( "reason", e.what() ) );
291 }
292 catch ( ... )
293 {
294 FC_THROW( "Resize file '${f}' to size ${s} failed: ${reason}",
295 ("f",f)("s",t)( "reason", fc::except_str() ) );
296 }
297 }
298
299 // setuid, setgid not implemented.
300 // translates octal permission like 0755 to S_ stuff defined in sys/stat.h
301 // no-op on Windows.
302 void chmod( const path& p, int perm )
303 {
304#ifndef WIN32
305 mode_t actual_perm =
306 ((perm & 0400) ? S_IRUSR : 0)
307 | ((perm & 0200) ? S_IWUSR : 0)
308 | ((perm & 0100) ? S_IXUSR : 0)
309
310 | ((perm & 0040) ? S_IRGRP : 0)
311 | ((perm & 0020) ? S_IWGRP : 0)
312 | ((perm & 0010) ? S_IXGRP : 0)
313
314 | ((perm & 0004) ? S_IROTH : 0)
315 | ((perm & 0002) ? S_IWOTH : 0)
316 | ((perm & 0001) ? S_IXOTH : 0)
317 ;
318
319 int result = ::chmod( p.string().c_str(), actual_perm );
320 if( result != 0 )
321 FC_THROW( "chmod operation failed on ${p}", ("p",p) );
322#endif
323 return;
324 }
325
326 void rename( const path& f, const path& t ) {
327 try {
328 boost::filesystem::rename( boost::filesystem::path(f), boost::filesystem::path(t) );
329 } catch ( boost::system::system_error& ) {
330 try{
331 boost::filesystem::copy( boost::filesystem::path(f), boost::filesystem::path(t) );
332 boost::filesystem::remove( boost::filesystem::path(f));
333 } catch ( boost::system::system_error& e ) {
334 FC_THROW( "Rename from ${srcfile} to ${dstfile} failed because ${reason}",
335 ("srcfile",f)("dstfile",t)("reason",e.what() ) );
336 }
337 } catch ( ... ) {
338 FC_THROW( "Rename from ${srcfile} to ${dstfile} failed",
339 ("srcfile",f)("dstfile",t)("inner", fc::except_str() ) );
340 }
341 }
342 void create_hard_link( const path& f, const path& t ) {
343 try {
344 boost::filesystem::create_hard_link( f, t );
345 } catch ( ... ) {
346 FC_THROW( "Unable to create hard link from '${from}' to '${to}'",
347 ( "from", f )("to",t)("exception", fc::except_str() ) );
348 }
349 }
350 bool remove( const path& f ) {
351 try {
352 return boost::filesystem::remove( f );
353 } catch ( ... ) {
354 FC_THROW( "Unable to remove '${path}'", ( "path", f )("exception", fc::except_str() ) );
355 }
356 }
358 try {
359 return boost::filesystem::canonical(p);
360 } catch ( ... ) {
361 FC_THROW( "Unable to resolve path '${path}'", ( "path", p )("exception", fc::except_str() ) );
362 }
363 }
364 fc::path absolute( const fc::path& p ) { return boost::filesystem::absolute(p); }
365 path unique_path() { return boost::filesystem::unique_path(); }
366 path temp_directory_path() { return boost::filesystem::temp_directory_path(); }
367
368 // Return path when appended to a_From will resolve to same as a_To
369 fc::path make_relative(const fc::path& from, const fc::path& to) {
370 boost::filesystem::path a_From = boost::filesystem::absolute(from);
371 boost::filesystem::path a_To = boost::filesystem::absolute(to);
372 boost::filesystem::path ret;
373 boost::filesystem::path::const_iterator itrFrom(a_From.begin()), itrTo(a_To.begin());
374 // Find common base
375 for( boost::filesystem::path::const_iterator toEnd( a_To.end() ), fromEnd( a_From.end() ) ; itrFrom != fromEnd && itrTo != toEnd && *itrFrom == *itrTo; ++itrFrom, ++itrTo );
376 // Navigate backwards in directory to reach previously found base
377 for( boost::filesystem::path::const_iterator fromEnd( a_From.end() ); itrFrom != fromEnd; ++itrFrom ) {
378 if( (*itrFrom) != "." )
379 ret /= "..";
380 }
381 // Now navigate down the directory branch
382 for (; itrTo != a_To.end(); ++itrTo)
383 ret /= *itrTo;
384 return ret;
385 }
386
387 temp_file::temp_file(const fc::path& p, bool create)
389 {
390 if (fc::exists(*_path))
391 {
392 FC_THROW( "Name collision: ${path}", ("path", _path->string()) );
393 }
394 if (create)
395 {
396 std::ofstream ofs(_path->generic_string().c_str(), std::ofstream::out | std::ofstream::binary);
397 ofs.close();
398 }
399 }
400
402 : temp_file_base(std::move(other._path))
403 {
404 }
405
407 {
408 if (this != &other)
409 {
410 remove();
411 _path = std::move(other._path);
412 }
413 return *this;
414 }
415
418 {
419 if (fc::exists(*_path))
420 {
421 FC_THROW( "Name collision: ${path}", ("path", _path->string()) );
422 }
424 }
425
427 : temp_file_base(std::move(other._path))
428 {
429 }
430
432 {
433 if (this != &other)
434 {
435 remove();
436 _path = std::move(other._path);
437 }
438 return *this;
439 }
440
442 {
443 if (!_path)
444 {
445 FC_THROW( "Temporary directory has been released." );
446 }
447 return *_path;
448 }
449
451 {
452 if (_path)
453 {
454 try
455 {
457 }
458 catch (...)
459 {
460 // eat errors on cleanup
461 }
462 release();
463 }
464 }
465
467 {
468 _path = std::optional<fc::path>();
469 }
470
472 {
473 static fc::path p = []()
474 {
475#ifdef WIN32
476 HANDLE access_token;
477 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &access_token))
478 FC_ASSERT(false, "Unable to open an access token for the current process");
479 wchar_t user_profile_dir[MAX_PATH];
480 DWORD user_profile_dir_len = sizeof(user_profile_dir);
481 BOOL success = GetUserProfileDirectoryW(access_token, user_profile_dir, &user_profile_dir_len);
482 CloseHandle(access_token);
483 if (!success)
484 FC_ASSERT(false, "Unable to get the user profile directory");
485 return fc::path(std::wstring(user_profile_dir));
486#else
487 char* home = getenv( "HOME" );
488 if( nullptr == home )
489 {
490 struct passwd* pwd = getpwuid(getuid());
491 if( pwd )
492 {
493 return fc::path( std::string( pwd->pw_dir ) );
494 }
495 FC_ASSERT( home != nullptr, "The HOME environment variable is not set" );
496 }
497 return fc::path( std::string(home) );
498#endif
499 }();
500 return p;
501 }
502
504 {
505#ifdef __APPLE__
506 static fc::path appdir = [](){ return home_path() / "Library" / "Application Support"; }();
507#elif defined( WIN32 )
508 static fc::path appdir = [](){
509 wchar_t app_data_dir[MAX_PATH];
510
511 if (!SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, app_data_dir)))
512 FC_ASSERT(false, "Unable to get the current AppData directory");
513 return fc::path(std::wstring(app_data_dir));
514 }();
515#else
516 static fc::path appdir = home_path() / ".local/share";
517#endif
518 return appdir;
519 }
520
522 {
523 static fc::path appCurrentPath = boost::filesystem::current_path();
524 return appCurrentPath;
525 }
526
527
528#ifdef FC_HAS_SIMPLE_FILE_LOCK
529 class simple_lock_file::impl
530 {
531 public:
532#ifdef _WIN32
533 HANDLE file_handle;
534#else
535 int file_handle;
536#endif
537 bool is_locked;
538 path lock_file_path;
539
540 impl(const path& lock_file_path);
541 ~impl();
542
543 bool try_lock();
544 void unlock();
545 };
546
547 simple_lock_file::impl::impl(const path& lock_file_path) :
548#ifdef _WIN32
549 file_handle(INVALID_HANDLE_VALUE),
550#else
551 file_handle(-1),
552#endif
553 is_locked(false),
554 lock_file_path(lock_file_path)
555 {}
556
557 simple_lock_file::impl::~impl()
558 {
559 unlock();
560 }
561
562 bool simple_lock_file::impl::try_lock()
563 {
564#ifdef _WIN32
565 HANDLE fh = CreateFileA(lock_file_path.to_native_ansi_path().c_str(),
566 GENERIC_READ | GENERIC_WRITE,
567 0, 0,
568 OPEN_ALWAYS, 0, NULL);
569 if (fh == INVALID_HANDLE_VALUE)
570 return false;
571 is_locked = true;
572 file_handle = fh;
573 return true;
574#else
575 int fd = open(lock_file_path.string().c_str(), O_RDWR|O_CREAT, 0644);
576 if (fd < 0)
577 return false;
578 if (flock(fd, LOCK_EX|LOCK_NB) == -1)
579 {
580 close(fd);
581 return false;
582 }
583 is_locked = true;
584 file_handle = fd;
585 return true;
586#endif
587 }
588
589 void simple_lock_file::impl::unlock()
590 {
591#ifdef WIN32
592 CloseHandle(file_handle);
593 file_handle = INVALID_HANDLE_VALUE;
594 is_locked = false;
595#else
596 flock(file_handle, LOCK_UN);
597 close(file_handle);
598 file_handle = -1;
599 is_locked = false;
600#endif
601 }
602
603
604 simple_lock_file::simple_lock_file(const path& lock_file_path) :
605 my(new impl(lock_file_path))
606 {
607 }
608
609 simple_lock_file::~simple_lock_file()
610 {
611 }
612
613 bool simple_lock_file::try_lock()
614 {
615 return my->try_lock();
616 }
617
618 void simple_lock_file::unlock()
619 {
620 my->unlock();
621 }
622#endif // FC_HAS_SIMPLE_FILE_LOCK
623
624}
const mie::Vuint & p
Definition bn.cpp:27
const mie::Vuint & r
Definition bn.cpp:28
directory_iterator & operator++()
fc::path operator*() const
detail::path_wrapper operator->() const
wraps boost::filesystem::path to provide platform independent path manipulation.
std::wstring generic_wstring() const
std::wstring preferred_wstring() const
fc::path parent_path() const
std::string windows_string() const
replaces '/' with '\' in the result of generic_string()
fc::path filename() const
std::wstring wstring() const
bool empty() const
static char separator_char
fc::path stem() const
path & operator=(const path &)
std::string preferred_string() const
std::string to_native_ansi_path() const
std::string string() const
fc::path extension() const
std::string generic_string() const
path & operator/=(const fc::path &)
bool is_absolute() const
void replace_extension(const fc::path &e)
bool is_relative() const
recursive_directory_iterator & operator++()
temp_directory(temp_directory &&other)
temp_directory & operator=(temp_directory &&other)
const fc::path & path() const
temp_file(temp_file &&other)
temp_file & operator=(temp_file &&other)
stores null, int64, uint64, double, bool, string, std::vector<variant>, and variant_object's.
Definition variant.hpp:191
string as_string() const
Definition variant.cpp:469
Defines exception's used by fc.
#define FC_THROW( ...)
#define FC_ASSERT(TEST,...)
Checks a condition and throws an assert_exception if the test is FALSE.
void close(T *e, websocketpp::connection_hdl hdl)
namespace sysio::chain
Definition authority.cpp:3
void rename(const path &from, const path &to)
bool remove(const path &p)
std::string string
Definition string.hpp:10
bool operator<(const array< T, N > &a, const array< T, N > &b)
Definition array.hpp:94
std::string except_str()
const path & app_path()
bool exists(const path &p)
void decodeUtf8(const std::string &input, std::wstring *storage)
Definition utf8.cpp:71
void remove_all(const path &p)
bool operator!=(const array< T, N > &a, const array< T, N > &b)
Definition array.hpp:102
const path & home_path()
bool is_regular_file(const path &p)
const fc::path & current_path()
bool operator==(const array< T, N > &a, const array< T, N > &b)
Definition array.hpp:91
void create_directories(const path &p)
void copy(const path &from, const path &to)
path unique_path()
void encodeUtf8(const std::wstring &input, std::string *storage)
Definition utf8.cpp:78
void create_hard_link(const path &from, const path &to)
path make_relative(const path &from, const path &to)
uint64_t file_size(const path &p)
bool is_directory(const path &p)
void resize_file(const path &file, size_t s)
uint64_t directory_size(const path &p)
path absolute(const path &p)
fc::variant operator/(const fc::variant &a, const fc::variant &b)
Definition variant.cpp:1001
path canonical(const path &p)
void from_variant(const fc::variant &v, sysio::chain::chain_id_type &cid)
void chmod(const path &p, int perm)
void to_variant(const sysio::chain::shared_public_key &var, fc::variant &vo)
Definition authority.cpp:4
path temp_directory_path()
Definition name.hpp:106
unsigned __int64 uint64_t
Definition stdint.h:136
CK_RV ret
int l