X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;ds=sidebyside;f=source%2Ffs%2Fdir.cpp;fp=source%2Ffs%2Fdir.cpp;h=ad2e013085024fbbcfaf54d3cf154f0a256711a2;hb=af94bc926e301e9b871dc18662b4fa6e5614fdbf;hp=0000000000000000000000000000000000000000;hpb=fa77438b62207466c48620604c8cc34931080936;p=libs%2Fcore.git diff --git a/source/fs/dir.cpp b/source/fs/dir.cpp new file mode 100644 index 0000000..ad2e013 --- /dev/null +++ b/source/fs/dir.cpp @@ -0,0 +1,229 @@ +/* $Id$ + +This file is part of libmspfs +Copyright © 2006-2008 Mikko Rasa, Mikkosoft Productions +Distributed under the LGPL +*/ + +#include +#include +#include +#include +#ifdef WIN32 +#include +#endif +#include +#include +#include +#include "dir.h" +#include "path.h" +#include "stat.h" +#include "utils.h" + +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; +#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); +} + +void mkpath(const Path &path, int mode) +{ + Path p; + for(Path::Iterator i=path.begin(); i!=path.end(); ++i) + { + p /= *i; +#ifdef WIN32 + if(p.size()==1 && p.is_absolute()) + continue; +#endif + struct stat st; + int err = stat(p, st); + if(err==0) + { + if(!S_ISDIR(st.st_mode)) + throw Exception("A component exists and is not a directory"); + 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) +{ + list files = list_files(path); + for(list::iterator i=files.begin(); i!=files.end(); ++i) + { + Path p = path / *i; + struct stat st = stat(p.str().c_str()); + if(S_ISDIR(st.st_mode)) + rmdirs(p); + else + unlink(p); + } + + rmdir(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) + { + 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() +{ +#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 +} + +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; +} + +Path get_sys_lib_dir(const string &argv0, const string &appname) +{ + Path dir = get_bin_dir(argv0); + + if(dir[-1]=="bin" || dir[-1]=="sbin") + return dir/".."/"lib"/appname; + else + return dir; +} + +void chdir(const Path &path) +{ + if(::chdir(path.str().c_str())==-1) + throw SystemError("chdir failed", errno); +} + +} // namespace FS +} // namespace Msp