3 This file is part of libmsppath
4 Copyright © 2006-2007 Mikko Rasa, Mikkosoft Productions
5 Distributed under the LGPL
10 #include <msp/core/except.h>
14 #include <msp/strings/glob.h>
16 #include <msp/strings/utils.h>
25 Fixes the case of the given path to match files / directories on the
26 filesystem. Intended to be used in programs that need to interact with
27 emulated Windows programs.
29 Path fix_case(const Path &path)
33 for(Path::Iterator i=path.begin(); i!=path.end(); ++i)
41 files=list_files(result);
43 files=list_files(".");
46 for(list<string>::iterator j=files.begin(); (j!=files.end() && !found); ++j)
47 if(!strcasecmp(*j,*i))
61 void mkdir(const Path &path, int mode)
65 // The win32 version of this function doesn't take the mode argument. Go figure.
67 err=::mkdir(path.str().c_str());
69 err=::mkdir(path.str().c_str(), mode);
73 throw SystemError("mkdir failed", errno);
77 Creates a directory and any parent directories if needed.
79 @param path The path to create
80 @param mode Access mode for new directories
82 @return 0 on success, -1 on error
84 void mkpath(const Path &path, int mode)
87 for(Path::Iterator i=path.begin(); i!=path.end(); ++i)
91 if(p.size()==1 && is_windows_drive(*i))
98 if(!S_ISDIR(st.st_mode))
99 throw Exception("A component exists and is not a directory");
102 else if(errno!=ENOENT)
103 throw SystemError("stat failed", errno);
109 void rmdir(const Path &path)
111 if(::rmdir(path.str().c_str())==-1)
112 throw SystemError("rmdir failed", errno);
115 void rmdirs(const Path &path)
117 list<string> files=list_files(path);
118 for(list<string>::iterator i=files.begin(); i!=files.end(); ++i)
121 struct stat st=stat(p.str().c_str());
122 if(S_ISDIR(st.st_mode))
131 void unlink(const Path &path)
133 if(::unlink(path.str().c_str())==-1)
134 throw SystemError("unlink failed", errno);
137 list<string> list_files(const Path &path)
140 DIR *dir=opendir(path.str().c_str());
143 while(dirent *de=readdir(dir))
145 const char *fn=de->d_name;
146 if(fn[0]=='.' && (fn[1]==0 || (fn[1]=='.' && fn[2]==0)))
148 result.push_back(fn);
156 bool exists(const Path &path)
158 return access(path.str().c_str(), F_OK)==0;
161 Filename splitext(const string &fn)
164 unsigned dot=fn.rfind('.');
165 result.base=fn.substr(0, dot);
166 if(dot!=string::npos)
167 result.ext=fn.substr(dot);
171 int fnmatch(const string &pat, const Path &fn)
174 return globcasematch(pat, fn.str());
176 return ::fnmatch(pat.c_str(), fn.str().c_str(), FNM_PATHNAME);
180 Path relative(const Path &path, const Path &base)
182 Path::Iterator i=path.begin();
183 Path::Iterator j=base.begin();
184 for(; (i!=path.end() && j!=base.end() && *i==*j); ++i,++j);
187 for(; j!=base.end(); ++j)
189 for(; i!=path.end(); ++i)
196 Extracts the basename from the given path. Same thing as Path::Path(p)[-1],
199 string basename(const std::string &p)
201 unsigned slash=p.rfind(DIRCHAR);
202 if(slash==string::npos)
205 return p.substr(slash+1);
208 int stat(const Path &fn, struct stat &st)
210 return ::stat(fn.str().c_str(), &st);
213 struct stat stat(const Path &fn)
217 throw SystemError("stat failed", errno);
224 return ::getcwd(buf, sizeof(buf));