]> git.localhorst.tv Git - blank.git/blob - src/io/filesystem.cpp
1fd94a0ae152a4313bc61d707ad012fc4f942c1a
[blank.git] / src / io / filesystem.cpp
1 #include "filesystem.hpp"
2
3 #include <cerrno>
4 #ifdef _WIN32
5 #  include <direct.h>
6 #endif
7 #include <sys/stat.h>
8
9
10 namespace blank {
11
12 namespace {
13 #ifdef _WIN32
14         using Stat = struct _stat;
15         int do_stat(const char *path, Stat &info) {
16                 return _stat(path, &info);
17         }
18         bool is_dir(const Stat &info) {
19                 return (info.st_mode & _S_IFDIR) != 0;
20         }
21         bool is_file(const Stat &info) {
22                 return (info.st_mode & _S_IFEG) != 0;
23         }
24 #else
25         using Stat = struct stat;
26         int do_stat(const char *path, Stat &info) {
27                 return stat(path, &info);
28         }
29         bool is_dir(const Stat &info) {
30                 return S_ISDIR(info.st_mode);
31         }
32         bool is_file(const Stat &info) {
33                 return S_ISREG(info.st_mode);
34         }
35 #endif
36         std::time_t get_mtime(const Stat &info) {
37 #ifdef __APPLE__
38                 return info.st_mtimespec.tv_sec;
39 #else
40         return info.st_mtime;
41 #endif
42         }
43 }
44
45 bool is_dir(const char *path) {
46         Stat info;
47         if (do_stat(path, info) != 0) {
48                 return false;
49         }
50         return is_dir(info);
51 }
52
53 bool is_file(const char *path) {
54         Stat info;
55         if (do_stat(path, info) != 0) {
56                 return false;
57         }
58         return is_file(info);
59 }
60
61 std::time_t file_mtime(const char *path) {
62         Stat info;
63         if (do_stat(path, info) != 0) {
64                 return 0;
65         }
66         return get_mtime(info);
67 }
68
69
70 bool make_dir(const char *path) {
71 #ifdef _WIN32
72         int ret = _mkdir(path);
73 #else
74         int ret = mkdir(path, 0777);
75 #endif
76         return ret == 0;
77 }
78
79
80 bool make_dirs(const std::string &path) {
81         if (make_dir(path)) {
82                 return true;
83         }
84
85         switch (errno) {
86
87                 case ENOENT:
88                         // missing component
89                         {
90 #ifdef _WIN32
91                                 auto pos = path.find_last_of("\\/");
92 #else
93                                 auto pos = path.find_last_of('/');
94 #endif
95                                 if (pos == std::string::npos) {
96                                         return false;
97                                 }
98                                 if (pos == path.length() - 1) {
99                                         // trailing separator, would make final make_dir fail
100 #ifdef _WIN32
101                                          pos = path.find_last_of("\\/", pos - 1);
102 #else
103                                          pos = path.find_last_of('/', pos - 1);
104 #endif
105                                         if (pos == std::string::npos) {
106                                                 return false;
107                                         }
108                                 }
109                                 if (!make_dirs(path.substr(0, pos))) {
110                                         return false;
111                                 }
112                         }
113                         // try again
114                         return make_dir(path);
115
116                 case EEXIST:
117                         // something's there, check if it's a dir and we're good
118                         return is_dir(path);
119
120                 default:
121                         // whatever else went wrong, it can't be good
122                         return false;
123
124         }
125 }
126
127 }