4362c17a3990406ed0fbdfd7c72c8de0078db220
[supertux.git] / lib / app / setup.cpp
1 //  $Id$
2 //
3 //  SuperTux -  A Jump'n Run
4 //  Copyright (C) 2000 Bill Kendrick <bill@newbreedsoftware.com>
5 //
6 //  This program is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU General Public License
8 //  as published by the Free Software Foundation; either version 2
9 //  of the License, or (at your option) any later version.
10 //
11 //  This program is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 //  GNU General Public License for more details.
15 //
16 //  You should have received a copy of the GNU General Public License
17 //  along with this program; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19 #include <config.h>
20
21 #include <cassert>
22 #include <cstdio>
23 #include <iostream>
24 #include <cstdio>
25 #include <cstdlib>
26 #include <cstring>
27 #include <cerrno>
28 #include <unistd.h>
29
30 #include <sys/stat.h>
31 #include <sys/types.h>
32 #include <dirent.h>
33 #ifndef WIN32
34 #include <libgen.h>
35 #endif
36
37 #include <cctype>
38
39 #include "globals.h"
40 #include "setup.h"
41
42 using namespace SuperTux;
43
44 #ifdef WIN32
45 #define mkdir(dir, mode)    mkdir(dir)
46 #endif
47
48 /* Does the given file exist and is it accessible? */
49 bool FileSystem::faccessible(const std::string& filename)
50 {
51   struct stat filestat;
52   if (stat(filename.c_str(), &filestat) == -1)
53     {
54       return false;
55     }
56   else
57     {
58       if(S_ISREG(filestat.st_mode))
59         return true;
60       else
61         return false;
62     }
63 }
64
65 /* Can we write to this location? */
66 bool FileSystem::fwriteable(const std::string& filename)
67 {
68   FILE* fi;
69   fi = fopen(filename.c_str(), "wa");
70   if (fi == NULL)
71     {
72       return false;
73     }
74   fclose(fi);
75   return true;
76 }
77
78 /* Makes sure a directory is created in either the SuperTux home directory or the SuperTux base directory.*/
79 bool FileSystem::fcreatedir(const std::string& relative_dir)
80 {
81   std::string path = user_dir + "/" + relative_dir + "/";
82   if(mkdir(path.c_str(),0755) != 0)
83     {
84       path = datadir + "/" + relative_dir + "/";
85       if(mkdir(path.c_str(),0755) != 0)
86         {
87           return false;
88         }
89       else
90         {
91           return true;
92         }
93     }
94   else
95     {
96       return true;
97     }
98 }
99
100 /* Get all names of sub-directories in a certain directory. */
101 /* Returns the number of sub-directories found. */
102 /* Note: The user has to free the allocated space. */
103 std::set<std::string> FileSystem::dsubdirs(const std::string &rel_path,const  std::string& expected_file)
104 {
105   DIR *dirStructP;
106   struct dirent *direntp;
107   std::set<std::string> sdirs;
108   std::string filename;
109   std::string path = user_dir + "/" + rel_path;
110
111   if((dirStructP = opendir(path.c_str())) != NULL)
112     {
113       while((direntp = readdir(dirStructP)) != NULL)
114         {
115           std::string absolute_filename;
116           struct stat buf;
117
118           absolute_filename = path + "/" + direntp->d_name;
119
120           if (stat(absolute_filename.c_str(), &buf) == 0 && S_ISDIR(buf.st_mode))
121             {
122               if(!expected_file.empty())
123                 {
124                   filename = path + "/" + direntp->d_name + "/" + expected_file;
125                   if(!faccessible(filename))
126                     continue;
127                 }
128
129               sdirs.insert(direntp->d_name);
130             }
131         }
132       closedir(dirStructP);
133     }
134
135   path = datadir + "/" + rel_path;
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_ISDIR(buf.st_mode))
146             {
147               if(!expected_file.empty())
148                 {
149                   filename = path + "/" + direntp->d_name + "/" + expected_file;
150                   if(!faccessible(filename.c_str()))
151                     {
152                       continue;
153                     }
154                   else
155                     {
156                       filename = user_dir + "/" + rel_path + "/" + direntp->d_name + "/" + expected_file;
157                       if(faccessible(filename.c_str()))
158                         continue;
159                     }
160                 }
161
162               sdirs.insert(direntp->d_name);
163             }
164         }
165       closedir(dirStructP);
166     }
167
168   return sdirs;
169 }
170
171 std::set<std::string> FileSystem::dfiles(const std::string& rel_path, const  std::string& glob, const  std::string& exception_str)
172 {
173   DIR *dirStructP;
174   struct dirent *direntp;
175   std::set<std::string> sdirs;
176   std::string path = user_dir + "/" + rel_path;
177
178   if((dirStructP = opendir(path.c_str())) != NULL)
179     {
180       while((direntp = readdir(dirStructP)) != NULL)
181         {
182           std::string absolute_filename;
183           struct stat buf;
184
185           absolute_filename = path + "/" + direntp->d_name;
186
187           if (stat(absolute_filename.c_str(), &buf) == 0 && S_ISREG(buf.st_mode))
188             {
189               if(!exception_str.empty())
190                 {
191                   if(strstr(direntp->d_name,exception_str.c_str()) != NULL)
192                     continue;
193                 }
194               if(!glob.empty())
195                 if(strstr(direntp->d_name,glob.c_str()) == NULL)
196                   continue;
197
198               sdirs.insert(direntp->d_name);
199             }
200         }
201       closedir(dirStructP);
202     }
203
204   path = datadir + "/" + rel_path;
205   if((dirStructP = opendir(path.c_str())) != NULL)
206     {
207       while((direntp = readdir(dirStructP)) != NULL)
208         {
209           std::string absolute_filename;
210           struct stat buf;
211
212           absolute_filename = path + "/" + direntp->d_name;
213
214           if (stat(absolute_filename.c_str(), &buf) == 0 && S_ISREG(buf.st_mode))
215             {
216               if(!exception_str.empty())
217                 {
218                   if(strstr(direntp->d_name,exception_str.c_str()) != NULL)
219                     continue;
220                 }
221               if(!glob.empty())
222                 if(strstr(direntp->d_name,glob.c_str()) == NULL)
223                   continue;
224
225               sdirs.insert(direntp->d_name);
226             }
227         }
228       closedir(dirStructP);
229     }
230
231   return sdirs;
232 }
233
234 std::string FileSystem::dirname(const std::string& filename)
235 {
236   std::string::size_type p = filename.find_last_of('/');
237   if(p == std::string::npos)                              
238     return "";
239   
240   return filename.substr(0, p+1);
241 }
242
243 std::set<std::string> FileSystem::read_directory(const std::string& pathname)
244 {
245   std::set<std::string> dirnames;
246   
247   DIR* dir = opendir(pathname.c_str());
248   if (dir)
249     {
250       struct dirent *direntp;
251       
252       while((direntp = readdir(dir)))
253         {
254           dirnames.insert(direntp->d_name);
255         }
256       
257       closedir(dir);
258     }
259
260   return dirnames;
261 }