X-Git-Url: http://git.localhorst.tv/?a=blobdiff_plain;f=src%2Fio%2Ffilesystem.cpp;h=5a4515e78dfab5629e5ce806b0622d9822829cc2;hb=ce10bfbe252d5598bbb559c6ce55aed1b9393227;hp=1fd94a0ae152a4313bc61d707ad012fc4f942c1a;hpb=1daba5b2fa044c1822d104fb65eeb88b6aeb5499;p=blank.git diff --git a/src/io/filesystem.cpp b/src/io/filesystem.cpp index 1fd94a0..5a4515e 100644 --- a/src/io/filesystem.cpp +++ b/src/io/filesystem.cpp @@ -1,11 +1,23 @@ #include "filesystem.hpp" #include +#include +#include +#include +#include +#include #ifdef _WIN32 +# include # include +# include +#else +# include +# include #endif #include +using namespace std; + namespace blank { @@ -33,7 +45,7 @@ namespace { return S_ISREG(info.st_mode); } #endif - std::time_t get_mtime(const Stat &info) { + time_t get_mtime(const Stat &info) { #ifdef __APPLE__ return info.st_mtimespec.tv_sec; #else @@ -58,7 +70,7 @@ bool is_file(const char *path) { return is_file(info); } -std::time_t file_mtime(const char *path) { +time_t file_mtime(const char *path) { Stat info; if (do_stat(path, info) != 0) { return 0; @@ -77,7 +89,7 @@ bool make_dir(const char *path) { } -bool make_dirs(const std::string &path) { +bool make_dirs(const string &path) { if (make_dir(path)) { return true; } @@ -92,7 +104,7 @@ bool make_dirs(const std::string &path) { #else auto pos = path.find_last_of('/'); #endif - if (pos == std::string::npos) { + if (pos == string::npos) { return false; } if (pos == path.length() - 1) { @@ -102,7 +114,7 @@ bool make_dirs(const std::string &path) { #else pos = path.find_last_of('/', pos - 1); #endif - if (pos == std::string::npos) { + if (pos == string::npos) { return false; } } @@ -124,4 +136,114 @@ bool make_dirs(const std::string &path) { } } + +bool remove_file(const string &path) { + return remove(path.c_str()) == 0; +} + + +bool remove_dir(const string &path) { +#ifdef _WIN32 + + // shamelessly stolen from http://www.codeguru.com/forum/showthread.php?t=239271 + const string pattern = path + "\\*.*"; + WIN32_FIND_DATA info; + HANDLE file = FindFirstFile(pattern.c_str(), &info); + if (file == INVALID_HANDLE_VALUE) { + // already non-existing + return true; + } + + do { + if ( + strncmp(info.cFileName, ".", 2) == 0 || + strncmp(info.cFileName, "..", 3) == 0 + ) { + continue; + } + const string sub_path = path + '\\' + info.cFileName; + if ((info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { + if (!remove_dir(sub_path)) { + return false; + } + } else { + if (!SetFileAttributes(sub_path.c_str(), FILE_ATTRIBUTE_NORMAL)) { + return false; + } + if (!remove_file(sub_path)) { + return false; + } + } + } while (FindNextFile(file, &info)); + FindClose(file); + + DWORD error = GetLastError(); + if (error != ERROR_NO_MORE_FILES) { + return false; + } + // is this (NORMAL vs DIRECTORY) really correct? + if (!SetFileAttributes(path.c_str(), FILE_ATTRIBUTE_NORMAL)) { + return false; + } + return RemoveDirectory(path.c_str()); + +#else + + DIR *dir = opendir(path.c_str()); + for (dirent *entry = readdir(dir); entry != nullptr; entry = readdir(dir)) { + if ( + strncmp(entry->d_name, ".", 2) == 0 || + strncmp(entry->d_name, "..", 3) == 0 + ) { + continue; + } + const string sub_path = path + '/' + entry->d_name; + if (is_dir(sub_path)) { + if (!remove_dir(sub_path)) { + return false; + } + } else { + if (!remove_file(sub_path)) { + return false; + } + } + } + return remove(path.c_str()) == 0; + +#endif +} + + +TempDir::TempDir() { +#if _DEFAULT_SOURCE || _BSD_SOURCE || _POSIX_C_SOURCE >= 200809L + char tmpl[] = "blank.XXXXXX"; + const char *name = mkdtemp(tmpl); + if (!name) { + throw runtime_error("unable to create temporary directory"); + } + path = name; +#else + char name[L_tmpnam]; + tmpnam(name); + constexpr int max_tries = 10; + int tries = 0; + while (!make_dirs(name) && tries < max_tries) { + tmpnam(name); + ++tries; + } + if (tries == max_tries) { + throw runtime_error("unable to create temporary directory"); + } +#endif + path = name; +} + +TempDir::~TempDir() { + try { + remove_dir(path); + } catch (...) { + cerr << "warning: could not remove temp dir " << path << endl; + } +} + }