-#include <config.h>
+// $Id$
+//
+// SuperTux
+// Copyright (C) 2006 Matthias Braun <matze@braunis.de>
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-#include "file_system.h"
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <dirent.h>
-#ifndef WIN32
-#include <libgen.h>
-#endif
+#include <config.h>
-#include "resources.h"
+#include "log.hpp"
+#include "file_system.hpp"
-#ifdef WIN32
-#define mkdir(dir, mode) mkdir(dir)
-#endif
+#include <string>
+#include <vector>
+#include <sstream>
namespace FileSystem
{
-/* Does the given file exist and is it accessible? */
-bool faccessible(const std::string& filename)
+std::string dirname(const std::string& filename)
{
- FILE* f = fopen(filename.c_str(), "r");
- if(f == 0)
- return false;
+ std::string::size_type p = filename.find_last_of('/');
+ if(p == std::string::npos)
+ return "";
- fclose(f);
- return true;
+ return filename.substr(0, p+1);
}
-/* Can we write to this location? */
-bool fwriteable(const std::string& filename)
+std::string basename(const std::string& filename)
{
- FILE* f = fopen(filename.c_str(), "wa");
- if (f == 0)
- return false;
-
- fclose(f);
- return true;
-}
+ std::string::size_type p = filename.find_last_of('/');
+ if(p == std::string::npos)
+ return filename;
-/* Makes sure a directory is created in either the SuperTux home directory or the SuperTux base directory.*/
-bool fcreatedir(const std::string& relative_dir)
-{
- std::string path = user_dir + "/" + relative_dir + "/";
- if(mkdir(path.c_str(),0755) == 0)
- return true;
-
- path = datadir + "/" + relative_dir + "/";
- if(mkdir(path.c_str(),0755) == 0)
- return true;
-
- return false;
+ return filename.substr(p+1, filename.size()-p-1);
}
-/* Get all names of sub-directories in a certain directory. */
-/* Returns the number of sub-directories found. */
-/* Note: The user has to free the allocated space. */
-std::set<std::string> dsubdirs(const std::string &rel_path,
- const std::string& expected_file)
+std::string strip_extension(const std::string& filename)
{
- DIR *dirStructP;
- struct dirent *direntp;
- std::set<std::string> sdirs;
- std::string filename;
- std::string path = user_dir + "/" + rel_path;
-
- if((dirStructP = opendir(path.c_str())) != NULL)
- {
- while((direntp = readdir(dirStructP)) != NULL)
- {
- std::string absolute_filename;
- struct stat buf;
-
- absolute_filename = path + "/" + direntp->d_name;
-
- if (stat(absolute_filename.c_str(), &buf) == 0 && S_ISDIR(buf.st_mode))
- {
- if(!expected_file.empty())
- {
- filename = path + "/" + direntp->d_name + "/" + expected_file;
- if(!faccessible(filename))
- continue;
- }
-
- sdirs.insert(direntp->d_name);
- }
- }
- closedir(dirStructP);
- }
+ std::string::size_type p = filename.find_last_of('.');
+ if(p == std::string::npos)
+ return filename;
- path = datadir + "/" + rel_path;
- if((dirStructP = opendir(path.c_str())) != NULL)
- {
- while((direntp = readdir(dirStructP)) != NULL)
- {
- std::string absolute_filename;
- struct stat buf;
-
- absolute_filename = path + "/" + direntp->d_name;
-
- if (stat(absolute_filename.c_str(), &buf) == 0 && S_ISDIR(buf.st_mode))
- {
- if(!expected_file.empty())
- {
- filename = path + "/" + direntp->d_name + "/" + expected_file;
- if(!faccessible(filename.c_str()))
- {
- continue;
- }
- else
- {
- filename = user_dir + "/" + rel_path + "/" + direntp->d_name + "/" + expected_file;
- if(faccessible(filename.c_str()))
- continue;
- }
- }
-
- sdirs.insert(direntp->d_name);
- }
- }
- closedir(dirStructP);
- }
-
- return sdirs;
+ return filename.substr(0, p);
}
-std::set<std::string> dfiles(const std::string& rel_path,
- const std::string& glob, const std::string& exception_str)
+std::string normalize(const std::string& filename)
{
- DIR *dirStructP;
- struct dirent *direntp;
- std::set<std::string> sdirs;
- std::string path = user_dir + "/" + rel_path;
-
- if((dirStructP = opendir(path.c_str())) != NULL)
- {
- while((direntp = readdir(dirStructP)) != NULL)
- {
- std::string absolute_filename;
- struct stat buf;
-
- absolute_filename = path + "/" + direntp->d_name;
-
- if (stat(absolute_filename.c_str(), &buf) == 0 && S_ISREG(buf.st_mode))
- {
- if(!exception_str.empty())
- {
- if(strstr(direntp->d_name,exception_str.c_str()) != NULL)
- continue;
- }
- if(!glob.empty())
- if(strstr(direntp->d_name,glob.c_str()) == NULL)
- continue;
-
- sdirs.insert(direntp->d_name);
- }
- }
- closedir(dirStructP);
- }
+ std::vector<std::string> path_stack;
- path = datadir + "/" + rel_path;
- if((dirStructP = opendir(path.c_str())) != NULL)
- {
- while((direntp = readdir(dirStructP)) != NULL)
- {
- std::string absolute_filename;
- struct stat buf;
-
- absolute_filename = path + "/" + direntp->d_name;
-
- if (stat(absolute_filename.c_str(), &buf) == 0 && S_ISREG(buf.st_mode))
- {
- if(!exception_str.empty())
- {
- if(strstr(direntp->d_name,exception_str.c_str()) != NULL)
- continue;
- }
- if(!glob.empty())
- if(strstr(direntp->d_name,glob.c_str()) == NULL)
- continue;
-
- sdirs.insert(direntp->d_name);
- }
- }
- closedir(dirStructP);
- }
-
- return sdirs;
-}
+ const char* p = filename.c_str();
-std::string dirname(const std::string& filename)
-{
- std::string::size_type p = filename.find_last_of('/');
- if(p == std::string::npos)
- return "";
-
- return filename.substr(0, p+1);
-}
+ while(true) {
+ while(*p == '/') {
+ p++;
+ continue;
+ }
-std::set<std::string> read_directory(const std::string& pathname)
-{
- std::set<std::string> dirnames;
-
- DIR* dir = opendir(pathname.c_str());
- if (dir)
- {
- struct dirent *direntp;
-
- while((direntp = readdir(dir)))
- {
- dirnames.insert(direntp->d_name);
- }
-
- closedir(dir);
+ const char* pstart = p;
+ while(*p != '/' && *p != 0) {
+ ++p;
}
- return dirnames;
+ size_t len = p - pstart;
+ if(len == 0)
+ break;
+
+ std::string pathelem(pstart, p-pstart);
+ if(pathelem == ".")
+ continue;
+
+ if(pathelem == "..") {
+ if(path_stack.empty()) {
+
+ log_warning << "Invalid '..' in path '" << filename << "'" << std::endl;
+ // push it into the result path so that the users sees his error...
+ path_stack.push_back(pathelem);
+ } else {
+ path_stack.pop_back();
+ }
+ } else {
+ path_stack.push_back(pathelem);
+ }
+ }
+
+ // construct path
+ std::ostringstream result;
+ for(std::vector<std::string>::iterator i = path_stack.begin();
+ i != path_stack.end(); ++i) {
+ result << '/' << *i;
+ }
+ if(path_stack.empty())
+ result << '/';
+
+ return result.str();
}
}
-