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