X-Git-Url: http://git.tdb.fi/?p=libs%2Fcore.git;a=blobdiff_plain;f=source%2Fdir.cpp;h=29c24c188fa96b7d76763b9b1ab5ad4a8aa3de53;hp=c402ec99ee2d61e95e930b07552a0437cbc2e77d;hb=9c48f72f02e3112f4193cc8b3f12b135aa483de1;hpb=f91f1df3e0b00b3a270e571d4b2c8251da4d1226 diff --git a/source/dir.cpp b/source/dir.cpp index c402ec9..29c24c1 100644 --- a/source/dir.cpp +++ b/source/dir.cpp @@ -9,7 +9,12 @@ Distributed under the LGPL #include #include #include +#ifdef WIN32 +#include +#endif #include +#include +#include #include "dir.h" #include "path.h" #include "stat.h" @@ -20,6 +25,44 @@ using namespace std; namespace Msp { 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. +*/ +const Path &get_bin_dir(const string &argv0) +{ + static string last_argv0; + static Path bin_dir; + + if(!(argv0==last_argv0)) + { + Path exe; + if(argv0.find('/')==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; + } + } + else + exe=realpath(argv0); + + last_argv0=argv0; + bin_dir=dirname(exe); + } + + return bin_dir; +} + +} + void mkdir(const Path &path, int mode) { int err; @@ -35,14 +78,6 @@ void mkdir(const Path &path, int mode) throw SystemError("mkdir failed", errno); } -/** -Creates a directory and any parent directories if needed. - -@param path The path to create -@param mode Access mode for new directories - -@return 0 on success, -1 on error -*/ void mkpath(const Path &path, int mode) { Path p; @@ -50,7 +85,7 @@ void mkpath(const Path &path, int mode) { p/=*i; #ifdef WIN32 - if(p.size()==1 && is_windows_drive(*i)) + if(p.size()==1 && p.is_absolute()) continue; #endif struct stat st; @@ -92,6 +127,13 @@ void rmdirs(const Path &path) list 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) @@ -101,7 +143,8 @@ list list_files(const Path &path) const char *fn=de->d_name; if(fn[0]=='.' && (fn[1]==0 || (fn[1]=='.' && fn[2]==0))) continue; - result.push_back(fn); + if(r_filter.match(fn)) + result.push_back(fn); } closedir(dir); } @@ -117,16 +160,55 @@ Path getcwd() Path get_home_dir() { -#ifndef WIN32 +#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 "."; -#else +} + +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 } +Path get_sys_conf_dir(const string &argv0) +{ + Path dir=get_bin_dir(argv0); + + if(dir[-1]=="bin" || dir[-1]=="sbin") + { + dir/=".."; + if(dir[-1]=="usr") + dir/=".."; + return dir/"etc"; + } + else + return dir; +} + +Path get_sys_data_dir(const string &argv0, const string &appname) +{ + Path dir=get_bin_dir(argv0); + + if(dir[-1]=="bin" || dir[-1]=="sbin") + return dir/".."/"share"/appname; + else + return dir; +} + void chdir(const Path &path) { if(::chdir(path.str().c_str())==-1)