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