]> git.tdb.fi Git - libs/core.git/blob - source/fs/dir.cpp
Add move semantics to Variant
[libs/core.git] / source / fs / dir.cpp
1 #include <msp/core/application.h>
2 #include <msp/core/environ.h>
3 #include <msp/core/except.h>
4 #include <msp/strings/utils.h>
5 #include "dir.h"
6 #include "path.h"
7 #include "stat.h"
8 #include "utils.h"
9
10 using namespace std;
11
12 namespace Msp {
13 namespace FS {
14
15 namespace
16 {
17
18 enum
19 {
20 #ifdef _WIN32
21         ITEMSEP = ';'
22 #else
23         ITEMSEP = ':'
24 #endif
25 };
26
27 /** Helper function to determine the location of the program's executable.
28 Caches the last result to cut down filesystem access with repeated calls. */
29 const Path &get_bin_dir(const string &argv0)
30 {
31         static string last_argv0;
32         static Path bin_dir;
33
34         if(!(argv0==last_argv0))
35         {
36                 Path exe;
37                 if(argv0.find(DIRSEP)==string::npos)
38                 {
39                         string path = getenv("PATH");
40                         if(!path.empty())
41                         {
42                                 for(const string &d: split(path, ITEMSEP))
43                                         if(exists(Path(d)/argv0))
44                                         {
45                                                 exe = realpath(Path(d)/argv0);
46                                                 break;
47                                         }
48                         }
49                 }
50
51                 if(exe.empty())
52                         exe = realpath(argv0);
53
54                 last_argv0 = argv0;
55                 bin_dir = dirname(exe);
56         }
57
58         return bin_dir;
59 }
60
61 }
62
63
64 not_a_directory::not_a_directory(const Path &p):
65         runtime_error(p.str())
66 { }
67
68
69 void mkpath(const Path &path, int mode)
70 {
71         Path p;
72         for(const string &c: path)
73         {
74                 p /= c;
75 #ifdef _WIN32
76                 if(p.size()==1 && p.is_absolute())
77                         continue;
78 #endif
79                 if(FS::Stat st = stat(p))
80                 {
81                         if(!st.is_directory())
82                                 throw not_a_directory(p);
83                         continue;
84                 }
85                 else
86                         mkdir(p, mode);
87         }
88 }
89
90 void rmpath(const Path &path)
91 {
92         for(const string &f: list_files(path))
93         {
94                 Path p = path/f;
95                 if(is_dir(p))
96                         rmpath(p);
97                 else
98                         unlink(p);
99         }
100
101         rmdir(path);
102 }
103
104 vector<string> list_files(const Path &path)
105 {
106         return list_filtered(path, string());
107 }
108
109 Path get_sys_conf_dir()
110 {
111         const char *argv0 = Application::get_argv0();
112         if(!argv0)
113                 throw invalid_state("no startup command");
114
115         Path dir = get_bin_dir(argv0);
116
117         if(dir[-1]=="bin" || dir[-1]=="sbin")
118         {
119                 dir /= "..";
120                 if(dir[-1]=="usr")
121                         dir /= "..";
122                 return dir/"etc";
123         }
124         else
125                 return dir;
126 }
127
128 Path get_sys_data_dir()
129 {
130         const char *argv0 = Application::get_argv0();
131         if(!argv0)
132                 throw invalid_state("no startup command");
133
134         Path dir = get_bin_dir(argv0);
135
136         if(dir[-1]=="bin" || dir[-1]=="sbin")
137                 return dir/".."/"share"/Application::get_name();
138         else if(dir[-1]=="MacOS")
139                 return dir/".."/"Resources";
140         else
141                 return dir;
142 }
143
144 Path get_sys_lib_dir()
145 {
146         const char *argv0 = Application::get_argv0();
147         if(!argv0)
148                 throw invalid_state("no startup command");
149
150         Path dir = get_bin_dir(argv0);
151
152         if(dir[-1]=="bin" || dir[-1]=="sbin")
153                 return dir/".."/"lib"/Application::get_name();
154         else
155                 return dir;
156 }
157
158 Path path_lookup(const string &name, const vector<Path> &paths)
159 {
160         for(const Path &p: paths)
161         {
162                 Path full = p/name;
163                 if(exists(full))
164                         return realpath(full);
165         }
166
167         return Path();
168 }
169
170 Path path_lookup(const string &name)
171 {
172         string path = getenv("PATH");
173         vector<string> dirs = split(path, ITEMSEP);
174         return path_lookup(name, vector<Path>(dirs.begin(), dirs.end()));
175 }
176
177 } // namespace FS
178 } // namespace Msp