49 #if defined(_WIN32) || defined(_WIN64)
52 #define access _access_s
76 #if defined(_WIN32) || defined(_WIN64)
79 auto const lpath =
"\\\\?\\" +
path;
80 return GetFileAttributesW( lpath.c_str() ) != INVALID_FILE_ATTRIBUTES;
86 return ( stat(
path.c_str(), &info ) == 0 );
117 std::ifstream instream( filename );
118 instream.seekg( 0, std::ios::end );
119 auto const result = instream.good() && !
is_dir( filename );
121 err_str = std::string( strerror( errno ));
126 std::string
file_read( std::string
const& filename,
bool detect_compression )
136 if( !instream.good() ) {
137 throw std::runtime_error(
138 "Cannot read from file '" + filename +
"': " + std::string( strerror( errno ))
144 std::istreambuf_iterator<char>(instream),
145 std::istreambuf_iterator<char>()
151 std::ifstream instream(filename);
152 if( !instream.good() ) {
153 throw std::runtime_error(
154 "Cannot read from file '" + filename +
"': " + std::string( strerror( errno ))
159 instream.seekg(0, std::ios::end);
160 str.reserve(instream.tellg());
161 instream.seekg(0, std::ios::beg);
165 std::istreambuf_iterator<char>(instream),
166 std::istreambuf_iterator<char>()
171 std::vector<std::string>
file_read_lines( std::string
const& filename,
bool detect_compression )
173 std::vector<std::string> result;
177 assert( !it || *it ==
'\n' );
183 void file_write( std::string
const& content, std::string
const& filename,
bool create_dirs )
190 void file_append( std::string
const& content, std::string
const& filename,
bool create_dirs )
200 std::ofstream out_stream( filename, std::ofstream::app );
201 if( out_stream.fail() ) {
202 throw std::runtime_error(
203 "Cannot append to file '" + filename +
"': " + std::string( strerror( errno ))
206 out_stream << content;
221 if (stat (dir.c_str(), &info) != 0) {
224 return static_cast<bool>( info.st_mode & S_IFDIR );
243 if( path_no_bs.empty() ) {
249 if( !
dir_exists( path_no_bs ) && path_no_bs.size() > 0 ) {
256 if( stat(
path.c_str(), &info ) != 0 ) {
257 if( mkdir(
path.c_str(), mode ) != 0 && errno != EEXIST ) {
258 throw std::runtime_error(
259 "Cannot create directory '" +
path +
"': " + std::string( strerror( errno ))
262 }
else if( !S_ISDIR( info.st_mode )) {
263 throw std::runtime_error(
264 "Cannot create directory '" +
path +
"': Path already exists, but is not a directory"
275 std::string
const& dir,
277 std::string
const& regex,
278 std::function<
bool( std::string
const& )> condition
280 std::vector<std::string> list;
282 std::regex pattern( regex );
288 if(( dp = opendir( dir.c_str() )) ==
nullptr ) {
289 throw std::runtime_error(
290 "Cannot open directory '" + dir +
"': " + std::string( strerror( errno ))
293 while(( dirp = readdir(dp) ) !=
nullptr ) {
294 auto const fn = std::string( dirp->d_name );
296 if (fn ==
"." || fn ==
"..") {
299 if( ! regex.empty() && ! regex_match( fn, pattern ) ) {
302 if( ! condition( dir_path + fn ) ) {
307 list.push_back( dir_path + fn );
309 list.push_back( fn );
319 std::string
const& dir,
321 std::string
const& regex
324 dir, full_path, regex,
325 []( std::string
const& ){
return true; }
330 std::string
const& dir,
332 std::string
const& regex
338 auto is_file_ = []( std::string
const& file_name ){
343 dir, full_path, regex, is_file_
348 std::string
const& dir,
350 std::string
const& regex
353 dir, full_path, regex,
is_dir
367 char temp[ PATH_MAX ];
369 if( getcwd( temp, PATH_MAX ) !=
nullptr ) {
376 throw std::runtime_error(
"Cannot read current directory: Access denied." );
379 throw std::runtime_error(
"Cannot read current directory: Insufficient storage." );
382 std::ostringstream str;
383 str <<
"Cannot read current directory: " << std::string( strerror( errno ));
384 throw std::runtime_error( str.str() );
398 typedef std::pair<dev_t, ino_t> file_id;
402 int start_fd = open(
".", O_RDONLY);
403 if( start_fd == -1 ) {
404 throw std::runtime_error(
405 "Cannot read current directory: " + std::string( strerror( errno ))
410 if( fstat(start_fd, &sb) ) {
411 throw std::runtime_error(
412 "Cannot read current directory: " + std::string( strerror( errno ))
417 file_id current_id(sb.st_dev, sb.st_ino);
418 if( stat(
"/", &sb )) {
419 throw std::runtime_error(
420 "Cannot read current directory: " + std::string( strerror( errno ))
424 std::vector<std::string> path_components;
425 file_id root_id(sb.st_dev, sb.st_ino);
428 while( current_id != root_id ) {
432 if( ! chdir(
"..") ) {
433 DIR *dir = opendir(
".");
438 while(( entry = readdir(dir) )) {
440 strcmp(entry->d_name,
".")
441 && strcmp(entry->d_name,
"..")
442 && !lstat(entry->d_name, &sb)
444 file_id child_id(sb.st_dev, sb.st_ino);
447 if( child_id == current_id ) {
448 path_components.push_back(entry->d_name);
457 if( pushed && !stat(
".", &sb) ) {
458 current_id = file_id(sb.st_dev, sb.st_ino);
471 if( current_id == root_id ) {
475 for(
auto i = path_components.rbegin(); i != path_components.rend(); ++i ) {
480 throw std::runtime_error(
481 "Cannot read current directory: " + std::string( strerror( errno ))
484 throw std::runtime_error(
"Cannot read current directory." );
488 if( fchdir(start_fd) ) {
490 throw std::runtime_error(
491 "Cannot change directory: " + std::string( strerror( errno ))
494 throw std::runtime_error(
"Cannot change directory." );
505 #if defined( _WIN32 ) || defined( _WIN64 )
523 auto slash_pos =
path.rfind(
"/");
526 if (slash_pos != std::string::npos) {
530 dir =
path.substr(0, slash_pos);
533 base =
path.substr(slash_pos);
545 int start_fd = open(
".", O_RDONLY);
546 if (start_fd == -1) {
547 throw std::runtime_error(
548 "Cannot open current directory: " + std::string( strerror( errno ))
553 if( chdir(dir.c_str()) ) {
554 throw std::runtime_error(
555 "Cannot change directory: " + std::string( strerror( errno ))
563 if( fchdir(start_fd) ) {
564 throw std::runtime_error(
565 "Cannot change directory: " + std::string( strerror( errno ))
581 return resolved_path + base;
586 bool success =
false;
589 char *buf =
new(std::nothrow)
char[
length+1];
593 ssize_t amount = ::readlink(
path.c_str(), buf,
length+1);
596 if ((amount > 0) && (amount <=
length)) {
615 path = dir + newbase;
623 typedef std::pair<dev_t, ino_t> file_id;
625 bool success =
false;
628 std::string
path = start;
630 std::set<file_id> seen_links;
635 resolved_link =
false;
636 if (!lstat(
path.c_str(), &sb)) {
637 file_id current_id(sb.st_dev, sb.st_ino);
639 if (seen_links.find(current_id) == seen_links.end()) {
641 seen_links.insert(current_id);
644 if (S_ISLNK(sb.st_mode)) {
648 if (newpath[0] ==
'/') {
654 resolved_link =
true;
667 }
while (resolved_link);
685 if( stat(
path.c_str(), &sb) ) {
686 throw std::runtime_error(
687 "Cannot read path '" +
path +
"': " + std::string( strerror( errno ))
691 if( S_ISDIR( sb.st_mode )) {
697 throw std::runtime_error(
698 "Cannot determine real path to '" +
path +
"': " +
699 std::string( strerror( errno ))
721 char resolved_path[PATH_MAX];
722 auto ptr = realpath(
path.c_str(), resolved_path );
724 throw std::runtime_error(
725 "Cannot determine real path to '" +
path +
"': " + std::string( strerror( errno ))
728 return std::string( ptr );
734 #if defined( _WIN32 ) || defined( _WIN64 )
749 std::unordered_map<std::string, std::string>
file_info( std::string
const& filename )
752 std::unordered_map<std::string, std::string> res;
755 res[
"basename"] = basename;
765 auto result = filename;
766 std::ifstream in(result, std::ifstream::ate | std::ifstream::binary);
768 throw std::runtime_error(
769 "Cannot determine file size of file '" + filename +
"': " +
770 std::string( strerror( errno ))
773 return static_cast<size_t>(in.tellg());
778 auto result = filename;
779 const size_t idx = result.find_last_of(
"\\/");
780 if( idx == std::string::npos ) {
790 auto result = filename;
791 const size_t idx = result.find_last_of(
"\\/");
792 if( idx != std::string::npos ) {
793 result.erase(0, idx + 1);
799 std::string
const& filename,
800 std::vector<std::string>
const& remove_extensions
803 for(
auto const& ext : remove_extensions ) {
805 bn.erase( bn.size() - ext.size() );
813 auto result = filename;
814 const size_t idx = result.rfind(
'.');
815 if( idx != 0 && idx != std::string::npos ) {
823 auto result = filename;
824 const size_t idx = result.rfind(
'.');
825 if( idx != 0 && idx != std::string::npos ) {
826 result.erase(0, idx + 1);
838 if(
trim( filename ) ==
"" ) {
848 if( filename.find_first_of(
"<>:\"\\/|?*" ) != std::string::npos ) {
854 for(
auto c : filename ) {
855 if( ! isprint( c ) ) {
866 std::string result =
"";
867 result.reserve( filename.size() );
870 for(
auto c : filename ) {
877 result =
trim( result );
882 throw std::runtime_error(
"Invalid filename '" + filename +
"'" );