3 This file is part of libmsppath
4 Copyright © 2006-2007 Mikko Rasa, Mikkosoft Productions
5 Distributed under the LGPL
11 #include <msp/core/except.h>
15 #include <msp/strings/glob.h>
17 #include <msp/strings/utils.h>
26 Fixes the case of the given path to match files / directories on the
27 filesystem. Intended to be used in programs that need to interact with
28 emulated Windows programs.
30 Path fix_case(const Path &path)
34 for(Path::Iterator i=path.begin(); i!=path.end(); ++i)
42 files=list_files(result);
44 files=list_files(".");
47 for(list<string>::iterator j=files.begin(); (j!=files.end() && !found); ++j)
48 if(!strcasecmp(*j,*i))
62 void mkdir(const Path &path, int mode)
66 // The win32 version of this function doesn't take the mode argument. Go figure.
68 err=::mkdir(path.str().c_str());
70 err=::mkdir(path.str().c_str(), mode);
74 throw SystemError("mkdir failed", errno);
78 Creates a directory and any parent directories if needed.
80 @param path The path to create
81 @param mode Access mode for new directories
83 @return 0 on success, -1 on error
85 void mkpath(const Path &path, int mode)
88 for(Path::Iterator i=path.begin(); i!=path.end(); ++i)
92 if(p.size()==1 && is_windows_drive(*i))
99 if(!S_ISDIR(st.st_mode))
100 throw Exception("A component exists and is not a directory");
103 else if(errno!=ENOENT)
104 throw SystemError("stat failed", errno);
110 void rmdir(const Path &path)
112 if(::rmdir(path.str().c_str())==-1)
113 throw SystemError("rmdir failed", errno);
116 void rmdirs(const Path &path)
118 list<string> files=list_files(path);
119 for(list<string>::iterator i=files.begin(); i!=files.end(); ++i)
122 struct stat st=stat(p.str().c_str());
123 if(S_ISDIR(st.st_mode))
132 void unlink(const Path &path)
134 if(::unlink(path.str().c_str())==-1)
135 throw SystemError("unlink failed", errno);
138 list<string> list_files(const Path &path)
141 DIR *dir=opendir(path.str().c_str());
144 while(dirent *de=readdir(dir))
146 const char *fn=de->d_name;
147 if(fn[0]=='.' && (fn[1]==0 || (fn[1]=='.' && fn[2]==0)))
149 result.push_back(fn);
157 bool exists(const Path &path)
159 return access(path.str().c_str(), F_OK)==0;
162 bool is_dir(const Path &path)
165 if(stat(path, st)==0)
166 return S_ISDIR(st.st_mode);
170 Filename splitext(const string &fn)
173 unsigned dot=fn.rfind('.');
174 result.base=fn.substr(0, dot);
175 if(dot!=string::npos)
176 result.ext=fn.substr(dot);
180 int fnmatch(const string &pat, const Path &fn)
183 return globcasematch(pat, fn.str());
185 return ::fnmatch(pat.c_str(), fn.str().c_str(), FNM_PATHNAME);
189 Path relative(const Path &path, const Path &base)
191 Path::Iterator i=path.begin();
192 Path::Iterator j=base.begin();
193 for(; (i!=path.end() && j!=base.end() && *i==*j); ++i, ++j) ;
196 for(; j!=base.end(); ++j)
198 for(; i!=path.end(); ++i)
205 Extracts the basename from the given path. Same thing as Path::Path(p)[-1],
208 string basename(const std::string &p)
210 unsigned slash=p.rfind(DIRCHAR);
211 if(slash==string::npos)
214 return p.substr(slash+1);
217 int stat(const Path &fn, struct stat &st)
219 return ::stat(fn.str().c_str(), &st);
222 struct stat stat(const Path &fn)
226 throw SystemError("stat failed", errno);
233 return ::getcwd(buf, sizeof(buf));
239 const char *home=getenv("HOME");
248 void chdir(const Path &path)
250 if(::chdir(path.str().c_str())==-1)
251 throw SystemError("chdir failed", errno);