1 #include "filesystem.hpp"
12 # include <sys/types.h>
22 using Stat = struct _stat;
23 int do_stat(const char *path, Stat &info) {
24 return _stat(path, &info);
26 bool is_dir(const Stat &info) {
27 return (info.st_mode & _S_IFDIR) != 0;
29 bool is_file(const Stat &info) {
30 return (info.st_mode & _S_IFEG) != 0;
33 using Stat = struct stat;
34 int do_stat(const char *path, Stat &info) {
35 return stat(path, &info);
37 bool is_dir(const Stat &info) {
38 return S_ISDIR(info.st_mode);
40 bool is_file(const Stat &info) {
41 return S_ISREG(info.st_mode);
44 std::time_t get_mtime(const Stat &info) {
46 return info.st_mtimespec.tv_sec;
53 bool is_dir(const char *path) {
55 if (do_stat(path, info) != 0) {
61 bool is_file(const char *path) {
63 if (do_stat(path, info) != 0) {
69 std::time_t file_mtime(const char *path) {
71 if (do_stat(path, info) != 0) {
74 return get_mtime(info);
78 bool make_dir(const char *path) {
80 int ret = _mkdir(path);
82 int ret = mkdir(path, 0777);
88 bool make_dirs(const std::string &path) {
99 auto pos = path.find_last_of("\\/");
101 auto pos = path.find_last_of('/');
103 if (pos == std::string::npos) {
106 if (pos == path.length() - 1) {
107 // trailing separator, would make final make_dir fail
109 pos = path.find_last_of("\\/", pos - 1);
111 pos = path.find_last_of('/', pos - 1);
113 if (pos == std::string::npos) {
117 if (!make_dirs(path.substr(0, pos))) {
122 return make_dir(path);
125 // something's there, check if it's a dir and we're good
129 // whatever else went wrong, it can't be good
136 bool remove_file(const std::string &path) {
137 return remove(path.c_str()) == 0;
141 bool remove_dir(const std::string &path) {
144 // shamelessly stolen from http://www.codeguru.com/forum/showthread.php?t=239271
145 const std::string pattern = path + "\\*.*";
146 WIN32_FIND_DATA info;
147 HANDLE file = FindFirstFile(pattern.c_str(), &info);
148 if (file == INVALID_HANDLE_VALUE) {
149 // already non-existing
155 strncmp(info.cFileName, ".", 2) == 0 ||
156 strncmp(info.cFileName, "..", 3) == 0
160 const std::string sub_path = path + '\\' + info.cFileName;
161 if ((info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) {
162 if (!remove_dir(sub_path)) {
166 if (!SetFileAttributes(sub_path.c_str(), FILE_ATTRIBUTE_NORMAL)) {
169 if (!remove_file(sub_path)) {
173 } while (FindNextFile(file, &info));
176 DWORD error = GetLastError();
177 if (error != ERROR_NO_MORE_FILES) {
180 // is this (NORMAL vs DIRECTORY) really correct?
181 if (!SetFileAttributes(path.c_str(), FILE_ATTRIBUTE_NORMAL)) {
184 return RemoveDirectory(path.c_str());
188 DIR *dir = opendir(path.c_str());
189 for (dirent *entry = readdir(dir); entry != nullptr; entry = readdir(dir)) {
191 strncmp(entry->d_name, ".", 2) == 0 ||
192 strncmp(entry->d_name, "..", 3) == 0
196 const std::string sub_path = path + '/' + entry->d_name;
197 if (is_dir(sub_path)) {
198 if (!remove_dir(sub_path)) {
202 if (!remove_file(sub_path)) {
207 return remove(path.c_str()) == 0;