]> git.tdb.fi Git - libs/core.git/blob - source/dir.cpp
9d23a1388015a89acf8e9ce36cf257c4fd8941a7
[libs/core.git] / source / dir.cpp
1 /* $Id$
2
3 This file is part of libmspfs
4 Copyright © 2006-2008  Mikko Rasa, Mikkosoft Productions
5 Distributed under the LGPL
6 */
7
8 #include <cstdlib>
9 #include <cerrno>
10 #include <dirent.h>
11 #include <sys/stat.h>
12 #ifdef WIN32
13 #include <shlobj.h>
14 #endif
15 #include <msp/core/except.h>
16 #include <msp/strings/regex.h>
17 #include "dir.h"
18 #include "path.h"
19 #include "stat.h"
20 #include "utils.h"
21
22 using namespace std;
23
24 namespace Msp {
25 namespace FS {
26
27 void mkdir(const Path &path, int mode)
28 {
29         int err;
30 #ifdef WIN32
31         // The win32 version of this function doesn't take the mode argument.  Go figure.
32         (void)mode;
33         err=::mkdir(path.str().c_str());
34 #else
35         err=::mkdir(path.str().c_str(), mode);
36 #endif
37
38         if(err==-1)
39                 throw SystemError("mkdir failed", errno);
40 }
41
42 void mkpath(const Path &path, int mode)
43 {
44         Path p;
45         for(Path::Iterator i=path.begin(); i!=path.end(); ++i)
46         {
47                 p/=*i;
48 #ifdef WIN32
49                 if(p.size()==1 && is_windows_drive(*i))
50                         continue;
51 #endif
52                 struct stat st;
53                 int err=stat(p, st);
54                 if(err==0)
55                 {
56                         if(!S_ISDIR(st.st_mode))
57                                 throw Exception("A component exists and is not a directory");
58                         continue;
59                 }
60                 else if(errno!=ENOENT)
61                         throw SystemError("stat failed", errno);
62                 else
63                         mkdir(p, mode);
64         }
65 }
66
67 void rmdir(const Path &path)
68 {
69         if(::rmdir(path.str().c_str())==-1)
70                 throw SystemError("rmdir failed", errno);
71 }
72
73 void rmdirs(const Path &path)
74 {
75         list<string> files=list_files(path);
76         for(list<string>::iterator i=files.begin(); i!=files.end(); ++i)
77         {
78                 Path p=path / *i;
79                 struct stat st=stat(p.str().c_str());
80                 if(S_ISDIR(st.st_mode))
81                         rmdirs(p);
82                 else
83                         unlink(p);
84         }
85
86         rmdir(path);
87 }
88
89 list<string> list_files(const Path &path)
90 {
91         return list_filtered(path, string());
92 }
93
94 list<string> list_filtered(const Path &path, const string &filter)
95 {
96         Regex r_filter(filter);
97
98         list<string> result;
99         DIR *dir=opendir(path.str().c_str());
100         if(dir)
101         {
102                 while(dirent *de=readdir(dir))
103                 {
104                         const char *fn=de->d_name;
105                         if(fn[0]=='.' && (fn[1]==0 || (fn[1]=='.' && fn[2]==0))) 
106                                 continue;
107                         if(r_filter.match(fn))
108                                 result.push_back(fn);
109                 }
110                 closedir(dir);
111         }
112
113         return result;
114 }
115
116 Path getcwd()
117 {
118         char buf[1024];
119         return ::getcwd(buf, sizeof(buf));
120 }
121
122 Path get_home_dir()
123 {
124 #ifdef WIN32
125         char home[MAX_PATH];
126         if(SHGetFolderPath(0, CSIDL_PERSONAL, 0, 0, home)==S_OK)
127                 return home;
128 #else
129         const char *home=getenv("HOME");
130         if(home)
131                 return home;
132 #endif
133         return ".";
134 }
135
136 Path get_user_data_dir(const string &appname)
137 {
138 #ifdef WIN32
139         char datadir[MAX_PATH];
140         if(SHGetFolderPath(0, CSIDL_LOCAL_APPDATA, 0, 0, datadir)==S_OK)
141                 return Path(datadir)/appname;
142         return ".";
143 #else
144         return get_home_dir()/("+"+appname);
145 #endif
146 }
147
148 void chdir(const Path &path)
149 {
150         if(::chdir(path.str().c_str())==-1)
151                 throw SystemError("chdir failed", errno);
152 }
153
154 } // namespace FS
155 } // namespace Msp