+/* $Id$
+
+This file is part of libmspfs
+Copyright © 2006-2008 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#include <cstdlib>
+#include <cerrno>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <msp/core/except.h>
+#include "dir.h"
+#include "path.h"
+#include "stat.h"
+#include "utils.h"
+
+using namespace std;
+
+namespace Msp {
+namespace FS {
+
+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);
+}
+
+/**
+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;
+ for(Path::Iterator i=path.begin(); i!=path.end(); ++i)
+ {
+ p/=*i;
+#ifdef WIN32
+ if(p.size()==1 && is_windows_drive(*i))
+ 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<string> files=list_files(path);
+ for(list<string>::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<string> list_files(const Path &path)
+{
+ list<string> 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;
+ result.push_back(fn);
+ }
+ closedir(dir);
+ }
+
+ return result;
+}
+
+Path getcwd()
+{
+ char buf[1024];
+ return ::getcwd(buf, sizeof(buf));
+}
+
+Path get_home_dir()
+{
+#ifndef WIN32
+ const char *home=getenv("HOME");
+ if(home)
+ return home;
+ return ".";
+#else
+ return ".";
+#endif
+}
+
+void chdir(const Path &path)
+{
+ if(::chdir(path.str().c_str())==-1)
+ throw SystemError("chdir failed", errno);
+}
+
+} // namespace FS
+} // namespace Msp