X-Git-Url: http://git.tdb.fi/?p=libs%2Fcore.git;a=blobdiff_plain;f=source%2Ffs%2Fdir.cpp;h=066d88bc1fd2c461bae39b5e3700d756f2aaa5b6;hp=bc7a8fec1b7fd9374c51dfa69165637341aad758;hb=HEAD;hpb=7563bb650aa11207a7c128ba44468cf5ad2897c7 diff --git a/source/fs/dir.cpp b/source/fs/dir.cpp index bc7a8fe..0f617e5 100644 --- a/source/fs/dir.cpp +++ b/source/fs/dir.cpp @@ -1,12 +1,6 @@ -#include -#include -#include -#include -#ifdef WIN32 -#include -#endif +#include +#include #include -#include #include #include "dir.h" #include "path.h" @@ -21,10 +15,17 @@ namespace FS { namespace { -/** -Helper function to determine the location of the program's executable. Caches -the last result to cut down filesystem access with repeated calls. -*/ +enum +{ +#ifdef _WIN32 + ITEMSEP = ';' +#else + ITEMSEP = ':' +#endif +}; + +/** Helper function to determine the location of the program's executable. +Caches the last result to cut down filesystem access with repeated calls. */ const Path &get_bin_dir(const string &argv0) { static string last_argv0; @@ -33,18 +34,21 @@ const Path &get_bin_dir(const string &argv0) if(!(argv0==last_argv0)) { Path exe; - if(argv0.find('/')==string::npos) + if(argv0.find(DIRSEP)==string::npos) { - const char *path = getenv("PATH"); - vector dirs = split(path, ':'); - for(vector::const_iterator i=dirs.begin(); i!=dirs.end(); ++i) - if(exists(Path(*i)/argv0)) - { - exe = realpath(Path(*i)/argv0); - break; - } + string path = getenv("PATH"); + if(!path.empty()) + { + for(const string &d: split(path, ITEMSEP)) + if(exists(Path(d)/argv0)) + { + exe = realpath(Path(d)/argv0); + break; + } + } } - else + + if(exe.empty()) exe = realpath(argv0); last_argv0 = argv0; @@ -56,61 +60,40 @@ const Path &get_bin_dir(const string &argv0) } -void mkdir(const Path &path, int mode) -{ - int err; -#ifdef WIN32 - // The win32 version of this function doesn't take the mode argument. Go figure. - (void)mode; - err = ::mkdir(path.str().c_str()); -#else - err = ::mkdir(path.str().c_str(), mode); -#endif - if(err==-1) - throw SystemError("mkdir failed", errno); -} +not_a_directory::not_a_directory(const Path &p): + runtime_error(p.str()) +{ } + void mkpath(const Path &path, int mode) { Path p; - for(Path::Iterator i=path.begin(); i!=path.end(); ++i) + for(const string &c: path) { - p /= *i; -#ifdef WIN32 + p /= c; +#ifdef _WIN32 if(p.size()==1 && p.is_absolute()) continue; #endif - struct stat st; - int err = stat(p, st); - if(err==0) + if(FS::Stat st = stat(p)) { - if(!S_ISDIR(st.st_mode)) - throw Exception("A component exists and is not a directory"); + if(!st.is_directory()) + throw not_a_directory(p); continue; } - else if(errno!=ENOENT) - throw SystemError("stat failed", errno); else mkdir(p, mode); } } -void rmdir(const Path &path) -{ - if(::rmdir(path.str().c_str())==-1) - throw SystemError("rmdir failed", errno); -} - -void rmdirs(const Path &path) +void rmpath(const Path &path) { - list files = list_files(path); - for(list::iterator i=files.begin(); i!=files.end(); ++i) + for(const string &f: list_files(path)) { - Path p = path / *i; - struct stat st = stat(p.str().c_str()); - if(S_ISDIR(st.st_mode)) - rmdirs(p); + Path p = path/f; + if(is_dir(p)) + rmpath(p); else unlink(p); } @@ -118,67 +101,17 @@ void rmdirs(const Path &path) rmdir(path); } -list list_files(const Path &path) +vector list_files(const Path &path) { return list_filtered(path, string()); } -list list_filtered(const Path &path, const string &filter) -{ - Regex r_filter(filter); - - list result; - DIR *dir = opendir(path.str().c_str()); - if(dir) - { - while(dirent *de = readdir(dir)) - { - const char *fn = de->d_name; - if(fn[0]=='.' && (fn[1]==0 || (fn[1]=='.' && fn[2]==0))) - continue; - if(r_filter.match(fn)) - result.push_back(fn); - } - closedir(dir); - } - - return result; -} - -Path getcwd() -{ - char buf[1024]; - return ::getcwd(buf, sizeof(buf)); -} - -Path get_home_dir() +Path get_sys_conf_dir() { -#ifdef WIN32 - char home[MAX_PATH]; - if(SHGetFolderPath(0, CSIDL_PERSONAL, 0, 0, home)==S_OK) - return home; -#else - const char *home = getenv("HOME"); - if(home) - return home; -#endif - return "."; -} - -Path get_user_data_dir(const string &appname) -{ -#ifdef WIN32 - char datadir[MAX_PATH]; - if(SHGetFolderPath(0, CSIDL_LOCAL_APPDATA, 0, 0, datadir)==S_OK) - return Path(datadir)/appname; - return "."; -#else - return get_home_dir()/("."+appname); -#endif -} + const char *argv0 = Application::get_argv0(); + if(!argv0) + throw invalid_state("no startup command"); -Path get_sys_conf_dir(const string &argv0) -{ Path dir = get_bin_dir(argv0); if(dir[-1]=="bin" || dir[-1]=="sbin") @@ -192,30 +125,53 @@ Path get_sys_conf_dir(const string &argv0) return dir; } -Path get_sys_data_dir(const string &argv0, const string &appname) +Path get_sys_data_dir() { + const char *argv0 = Application::get_argv0(); + if(!argv0) + throw invalid_state("no startup command"); + Path dir = get_bin_dir(argv0); if(dir[-1]=="bin" || dir[-1]=="sbin") - return dir/".."/"share"/appname; + return dir/".."/"share"/Application::get_name(); + else if(dir[-1]=="MacOS") + return dir/".."/"Resources"; else return dir; } -Path get_sys_lib_dir(const string &argv0, const string &appname) +Path get_sys_lib_dir() { + const char *argv0 = Application::get_argv0(); + if(!argv0) + throw invalid_state("no startup command"); + Path dir = get_bin_dir(argv0); if(dir[-1]=="bin" || dir[-1]=="sbin") - return dir/".."/"lib"/appname; + return dir/".."/"lib"/Application::get_name(); else return dir; } -void chdir(const Path &path) +Path path_lookup(const string &name, const vector &paths) +{ + for(const Path &p: paths) + { + Path full = p/name; + if(exists(full)) + return realpath(full); + } + + return Path(); +} + +Path path_lookup(const string &name) { - if(::chdir(path.str().c_str())==-1) - throw SystemError("chdir failed", errno); + string path = getenv("PATH"); + vector dirs = split(path, ITEMSEP); + return path_lookup(name, vector(dirs.begin(), dirs.end())); } } // namespace FS