8 #include <msp/core/except.h>
9 #include <msp/strings/regex.h>
10 #include <msp/strings/utils.h>
24 /** Helper function to determine the location of the program's executable.
25 Caches the last result to cut down filesystem access with repeated calls. */
26 const Path &get_bin_dir(const string &argv0)
28 static string last_argv0;
31 if(!(argv0==last_argv0))
34 if(argv0.find('/')==string::npos)
36 const char *path = getenv("PATH");
37 vector<string> dirs = split(path, ':');
38 for(vector<string>::const_iterator i=dirs.begin(); i!=dirs.end(); ++i)
39 if(exists(Path(*i)/argv0))
41 exe = realpath(Path(*i)/argv0);
46 exe = realpath(argv0);
49 bin_dir = dirname(exe);
57 void mkdir(const Path &path, int mode)
61 // The win32 version of this function doesn't take the mode argument. Go figure.
63 err = ::mkdir(path.str().c_str());
65 err = ::mkdir(path.str().c_str(), mode);
69 throw SystemError("mkdir failed", errno);
72 void mkpath(const Path &path, int mode)
75 for(Path::Iterator i=path.begin(); i!=path.end(); ++i)
79 if(p.size()==1 && p.is_absolute())
83 int err = stat(p, st);
86 if(!S_ISDIR(st.st_mode))
87 throw Exception("A component exists and is not a directory");
90 else if(errno!=ENOENT)
91 throw SystemError("stat failed", errno);
97 void rmdir(const Path &path)
99 if(::rmdir(path.str().c_str())==-1)
100 throw SystemError("rmdir failed", errno);
103 void rmdirs(const Path &path)
105 list<string> files = list_files(path);
106 for(list<string>::iterator i=files.begin(); i!=files.end(); ++i)
109 struct stat st = stat(p.str().c_str());
110 if(S_ISDIR(st.st_mode))
119 list<string> list_files(const Path &path)
121 return list_filtered(path, string());
124 list<string> list_filtered(const Path &path, const string &filter)
126 Regex r_filter(filter);
129 DIR *dir = opendir(path.str().c_str());
132 while(dirent *de = readdir(dir))
134 const char *fn = de->d_name;
135 if(fn[0]=='.' && (fn[1]==0 || (fn[1]=='.' && fn[2]==0)))
137 if(r_filter.match(fn))
138 result.push_back(fn);
149 return ::getcwd(buf, sizeof(buf));
156 if(SHGetFolderPath(0, CSIDL_PERSONAL, 0, 0, home)==S_OK)
159 const char *home = getenv("HOME");
166 Path get_user_data_dir(const string &appname)
169 char datadir[MAX_PATH];
170 if(SHGetFolderPath(0, CSIDL_LOCAL_APPDATA, 0, 0, datadir)==S_OK)
171 return Path(datadir)/appname;
174 return get_home_dir()/("."+appname);
178 Path get_sys_conf_dir(const string &argv0)
180 Path dir = get_bin_dir(argv0);
182 if(dir[-1]=="bin" || dir[-1]=="sbin")
193 Path get_sys_data_dir(const string &argv0, const string &appname)
195 Path dir = get_bin_dir(argv0);
197 if(dir[-1]=="bin" || dir[-1]=="sbin")
198 return dir/".."/"share"/appname;
203 Path get_sys_lib_dir(const string &argv0, const string &appname)
205 Path dir = get_bin_dir(argv0);
207 if(dir[-1]=="bin" || dir[-1]=="sbin")
208 return dir/".."/"lib"/appname;
213 void chdir(const Path &path)
215 if(::chdir(path.str().c_str())==-1)
216 throw SystemError("chdir failed", errno);