4 #include <msp/core/application.h>
5 #include <msp/core/systemerror.h>
6 #include <msp/strings/regex.h>
7 #include <msp/strings/utils.h>
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)
34 static string last_argv0;
37 if(!(argv0==last_argv0))
40 if(argv0.find('/')==string::npos)
42 const char *path = getenv("PATH");
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))
47 exe = realpath(Path(*i)/argv0);
53 exe = realpath(argv0);
56 bin_dir = dirname(exe);
65 not_a_directory::not_a_directory(const Path &p):
66 runtime_error(p.str())
70 void mkpath(const Path &path, int mode)
73 for(Path::Iterator i=path.begin(); i!=path.end(); ++i)
77 if(p.size()==1 && p.is_absolute())
80 if(FS::Stat st = stat(p))
82 if(!st.is_directory())
83 throw not_a_directory(p);
91 void rmpath(const Path &path)
93 list<string> files = list_files(path);
94 for(list<string>::iterator i=files.begin(); i!=files.end(); ++i)
106 list<string> list_files(const Path &path)
108 return list_filtered(path, string());
111 list<string> list_filtered(const Path &path, const string &filter)
113 Regex r_filter(filter);
116 DIR *dir = opendir(path.str().c_str());
118 throw system_error("opendir");
120 while(dirent *de = readdir(dir))
122 const char *fn = de->d_name;
123 if(fn[0]=='.' && (fn[1]==0 || (fn[1]=='.' && fn[2]==0)))
125 if(r_filter.match(fn))
126 result.push_back(fn);
133 Path get_user_data_dir()
135 const string &name = Application::get_name();
137 throw logic_error("application name not known");
138 return get_user_data_dir(name);
141 Path get_sys_conf_dir(const string &argv0)
144 throw invalid_argument("get_sys_conf_dir");
146 Path dir = get_bin_dir(argv0);
148 if(dir[-1]=="bin" || dir[-1]=="sbin")
159 Path get_sys_conf_dir()
161 const char *argv0 = Application::get_argv0();
163 throw logic_error("no startup command");
164 return get_sys_conf_dir(argv0);
167 Path get_sys_data_dir(const string &argv0, const string &appname)
169 if(argv0.empty() || appname.empty())
170 throw invalid_argument("get_sys_data_dir");
172 Path dir = get_bin_dir(argv0);
174 if(dir[-1]=="bin" || dir[-1]=="sbin")
175 return dir/".."/"share"/appname;
176 else if(dir[-1]=="MacOS")
177 return dir/".."/"Resources";
182 Path get_sys_data_dir()
184 const char *argv0 = Application::get_argv0();
186 throw logic_error("no startup command");
187 return get_sys_data_dir(argv0, Application::get_name());
190 Path get_sys_lib_dir(const string &argv0, const string &appname)
192 if(argv0.empty() || appname.empty())
193 throw invalid_argument("get_sys_data_dir");
195 Path dir = get_bin_dir(argv0);
197 if(dir[-1]=="bin" || dir[-1]=="sbin")
198 return dir/".."/"lib"/appname;
203 Path get_sys_lib_dir()
205 const char *argv0 = Application::get_argv0();
207 throw logic_error("no startup command");
208 return get_sys_lib_dir(argv0, Application::get_name());
211 Path path_lookup(const string &name, const list<Path> &paths)
213 for(list<Path>::const_iterator i=paths.begin(); i!=paths.end(); ++i)
217 return realpath(full);
223 Path path_lookup(const string &name)
225 const char *path = getenv("PATH");
226 vector<string> dirs = split(path, ITEMSEP);
227 return path_lookup(name, list<Path>(dirs.begin(), dirs.end()));