Added FileSystem class
[openstranded.git] / src / filesystem.cc
blob4cf042e885eafdb47fb98b51b80f9b5aa55c9deb
1 /*
2 * For information about this file see fsal.hh
4 * Copyright (C) 2009 David Kolossa
6 * This file is part of OpenStranded.
8 * OpenStranded is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
13 * OpenStranded is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with OpenStranded. If not, see <http://www.gnu.org/licenses/>.
22 #include <iostream>
23 #include <string>
24 #include <vector>
25 #include <map>
26 #include <cstdlib>
27 #include <cstring>
29 #ifndef WIN32
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <dirent.h>
33 #include <fcntl.h>
34 #include <errno.h>
35 #endif
37 #include "filesystem.hh"
38 #include "s2string.hh"
39 #include "eal/engine.hh"
44 // Class FileSystem
47 std::string FileSystem::modName = "";
49 void
50 FileSystem::setModName(std::string name)
52 modName = name;
55 std::vector<std::string> *
56 FileSystem::getDirectoryVector(std::string dirPath)
58 std::vector<std::string> *fileNames = new std::vector<std::string>();
59 #ifndef WIN32
60 DIR *dir = opendir(dirPath.c_str());
61 if(dir == NULL)
63 std::cerr << "Directory " << dirPath << "could not be opened";
64 return NULL;
66 dirent *file;
67 while((file = readdir(dir)) != NULL)
69 if(std::strcmp(file->d_name, ".") != 0 &&
70 std::strcmp(file->d_name, "..") != 0)
72 fileNames->push_back(std::string(file->d_name));
75 closedir(dir);
76 return fileNames;
78 #else
79 // TODO: Have fun, Windows porters!
80 return NULL;
81 #endif
84 std::string
85 FileSystem::getFileNameFromDirectoryVector(std::vector<std::string> *dirVector, const std::vector<std::string> &extensions, std::string name)
87 for(std::vector<std::string>::iterator f = dirVector->begin(); f != dirVector->end(); f++)
89 // Split filename into extension and actual filename
90 std::string extension = f->substr(f->find_last_of('.')+1);
91 std::string cutFileName = f->substr(0, f->find_last_of('.'));
93 // Check whether a file with a matching extension fits
94 for(std::vector<std::string>::const_iterator e = extensions.begin(); e != extensions.end(); e++)
96 #ifndef WIN32
97 // case-sensitive
98 if((cutFileName + "." + s2str::toLowercase(extension)) == (name + "." + *e))
99 #else
100 // case-insensitive
101 if((s2str::toLowercase(cutFileName) + "." + s2str::toLowercase(extension)) == (s2str::toLowercase(name) + "." + s2str::lowercase(*e)))
102 #endif
104 return *f;
108 return "";
115 // Directories
117 DirectoryInfo*
118 FileSystem::getUserDirectoryInfo()
120 std::string path = "";
122 #ifndef WIN32
123 path += std::getenv("HOME");
124 path += "/.openstranded/";
125 if(opendir(path.c_str()) == NULL)
127 int dirCreated = mkdir(path.c_str(), S_IRWXU);
128 if(dirCreated != 0)
130 // This might be called before the error stream
131 // is created, therefore no Out::error but
132 // std::cerr
133 std::cerr << "FATAL: OpenStranded user directory couldn't be created" << std::endl;
134 return NULL;
137 return new DirectoryInfo(path);
138 #else
139 // TODO: Windows stuff
140 return NULL;
141 #endif
144 DirectoryInfo*
145 FileSystem::getGameDirectoryInfo()
147 // FIXME: I don't want this hardcoded but I can't get CMake to
148 // deliver me the install path...
149 return new DirectoryInfo("/usr/share/games/openstranded/");
152 DirectoryInfo*
153 FileSystem::getModDirectoryInfo()
155 // FIXME: Same as in getGameDirectoryInfo()
156 return new DirectoryInfo("/usr/share/games/openstranded/mods/" + modName + "/");
162 // General Files
164 FileInfo*
165 FileSystem::getSaveFileInfo(std::string name)
167 std::string path;
169 path = getUserDirectoryInfo()->path + "saves/" + name;
171 FILE *f;
172 if((f = std::fopen((path+".sav").c_str(), "r+")) != NULL)
174 fclose(f);
175 return new FileInfo(path, 0);
177 else
179 return new FileInfo(path, errno);
186 // GFX files
188 FileInfo*
189 FileSystem::getTextureFileInfo(std::string name)
191 std::string path = "";
192 const std::vector<std::string> &allowedExtensions = eal::Engine::get()->getTextureExtensions();
195 // TODO: Map specific lookup
198 // Global lookup
199 DirectoryInfo* modDir = getModDirectoryInfo();
200 std::string dirPath = modDir->path + "gfx/textures/";
201 delete modDir;
202 modDir = NULL;
205 // Get file name
206 std::vector<std::string> *dirVector = getDirectoryVector(dirPath);
207 std::string fileName = getFileNameFromDirectoryVector(dirVector, allowedExtensions, name);
208 delete dirVector;
209 dirVector = NULL;
210 path = dirPath + fileName;
212 // Does our file actually exist?
213 if(fileName == "")
215 std::cerr << "WARNING: Texture " << fileName << " not found" << std::endl;
216 return new FileInfo(path, ENOENT);
219 // Do we have read access to the file?
220 FILE *f;
221 if((f = std::fopen(path.c_str(), "r+")) != NULL)
223 fclose(f);
224 return new FileInfo(path, 0);
226 else
228 return new FileInfo(path, errno);
235 // Class DirectoryInfo
237 DirectoryInfo::DirectoryInfo(std::string path)
238 : path(path)
244 // Class FileInfo
246 FileInfo::FileInfo(std::string path, int error)
247 : path(path), error(error)
250 bool
251 FileInfo::exists()
253 return this->error != ENOENT;