- More work on scripting interface
[supertux.git] / src / file_system.cpp
1 #include <config.h>
2
3 #include "file_system.h"
4 #include <sys/stat.h>
5 #include <sys/types.h>
6 #include <dirent.h>
7 #ifndef WIN32
8 #include <libgen.h>
9 #endif
10
11 #include "resources.h"
12
13 #ifdef WIN32
14 #define mkdir(dir, mode)    mkdir(dir)
15 #endif
16
17 namespace FileSystem
18 {
19
20 /* Does the given file exist and is it accessible? */
21 bool faccessible(const std::string& filename)
22 {
23   FILE* f = fopen(filename.c_str(), "r");
24   if(f == 0)
25     return false;
26
27   fclose(f);
28   return true;
29 }
30
31 /* Can we write to this location? */
32 bool fwriteable(const std::string& filename)
33 {
34   FILE* f = fopen(filename.c_str(), "wa");
35   if (f == 0)
36     return false;
37   
38   fclose(f);
39   return true;
40 }
41
42 /* Makes sure a directory is created in either the SuperTux home directory or the SuperTux base directory.*/
43 bool fcreatedir(const std::string& relative_dir)
44 {
45   std::string path = user_dir + "/" + relative_dir + "/";
46   if(mkdir(path.c_str(),0755) == 0)
47     return true;
48   
49   path = datadir + "/" + relative_dir + "/";
50   if(mkdir(path.c_str(),0755) == 0)
51     return true;
52     
53   return false;
54 }
55
56 /* Get all names of sub-directories in a certain directory. */
57 /* Returns the number of sub-directories found. */
58 /* Note: The user has to free the allocated space. */
59 std::set<std::string> dsubdirs(const std::string &rel_path,
60     const std::string& expected_file)
61 {
62   DIR *dirStructP;
63   struct dirent *direntp;
64   std::set<std::string> sdirs;
65   std::string filename;
66   std::string path = user_dir + "/" + rel_path;
67
68   if((dirStructP = opendir(path.c_str())) != NULL)
69     {
70       while((direntp = readdir(dirStructP)) != NULL)
71         {
72           std::string absolute_filename;
73           struct stat buf;
74
75           absolute_filename = path + "/" + direntp->d_name;
76
77           if (stat(absolute_filename.c_str(), &buf) == 0 && S_ISDIR(buf.st_mode))
78             {
79               if(!expected_file.empty())
80                 {
81                   filename = path + "/" + direntp->d_name + "/" + expected_file;
82                   if(!faccessible(filename))
83                     continue;
84                 }
85
86               sdirs.insert(direntp->d_name);
87             }
88         }
89       closedir(dirStructP);
90     }
91
92   path = datadir + "/" + rel_path;
93   if((dirStructP = opendir(path.c_str())) != NULL)
94     {
95       while((direntp = readdir(dirStructP)) != NULL)
96         {
97           std::string absolute_filename;
98           struct stat buf;
99
100           absolute_filename = path + "/" + direntp->d_name;
101
102           if (stat(absolute_filename.c_str(), &buf) == 0 && S_ISDIR(buf.st_mode))
103             {
104               if(!expected_file.empty())
105                 {
106                   filename = path + "/" + direntp->d_name + "/" + expected_file;
107                   if(!faccessible(filename.c_str()))
108                     {
109                       continue;
110                     }
111                   else
112                     {
113                       filename = user_dir + "/" + rel_path + "/" + direntp->d_name + "/" + expected_file;
114                       if(faccessible(filename.c_str()))
115                         continue;
116                     }
117                 }
118
119               sdirs.insert(direntp->d_name);
120             }
121         }
122       closedir(dirStructP);
123     }
124
125   return sdirs;
126 }
127
128 std::set<std::string> dfiles(const std::string& rel_path,
129     const std::string& glob, const std::string& exception_str)
130 {
131   DIR *dirStructP;
132   struct dirent *direntp;
133   std::set<std::string> sdirs;
134   std::string path = user_dir + "/" + rel_path;
135
136   if((dirStructP = opendir(path.c_str())) != NULL)
137     {
138       while((direntp = readdir(dirStructP)) != NULL)
139         {
140           std::string absolute_filename;
141           struct stat buf;
142
143           absolute_filename = path + "/" + direntp->d_name;
144
145           if (stat(absolute_filename.c_str(), &buf) == 0 && S_ISREG(buf.st_mode))
146             {
147               if(!exception_str.empty())
148                 {
149                   if(strstr(direntp->d_name,exception_str.c_str()) != NULL)
150                     continue;
151                 }
152               if(!glob.empty())
153                 if(strstr(direntp->d_name,glob.c_str()) == NULL)
154                   continue;
155
156               sdirs.insert(direntp->d_name);
157             }
158         }
159       closedir(dirStructP);
160     }
161
162   path = datadir + "/" + rel_path;
163   if((dirStructP = opendir(path.c_str())) != NULL)
164     {
165       while((direntp = readdir(dirStructP)) != NULL)
166         {
167           std::string absolute_filename;
168           struct stat buf;
169
170           absolute_filename = path + "/" + direntp->d_name;
171
172           if (stat(absolute_filename.c_str(), &buf) == 0 && S_ISREG(buf.st_mode))
173             {
174               if(!exception_str.empty())
175                 {
176                   if(strstr(direntp->d_name,exception_str.c_str()) != NULL)
177                     continue;
178                 }
179               if(!glob.empty())
180                 if(strstr(direntp->d_name,glob.c_str()) == NULL)
181                   continue;
182
183               sdirs.insert(direntp->d_name);
184             }
185         }
186       closedir(dirStructP);
187     }
188
189   return sdirs;
190 }
191
192 std::string dirname(const std::string& filename)
193 {
194   std::string::size_type p = filename.find_last_of('/');
195   if(p == std::string::npos)                              
196     return "";
197   
198   return filename.substr(0, p+1);
199 }
200
201 std::set<std::string> read_directory(const std::string& pathname)
202 {
203   std::set<std::string> dirnames;
204   
205   DIR* dir = opendir(pathname.c_str());
206   if (dir)
207     {
208       struct dirent *direntp;
209       
210       while((direntp = readdir(dir)))
211         {
212           dirnames.insert(direntp->d_name);
213         }
214       
215       closedir(dir);
216     }
217
218   return dirnames;
219 }
220
221 }
222