X-Git-Url: https://git.verplant.org/?a=blobdiff_plain;f=src%2Ffile_system.cpp;h=266da812f6be7a712190976a22d4533e2507eaa7;hb=8ea989626785c9a386bf4aef1b44fd201b677a08;hp=af243f837187304e63008972d8bfb4773890335b;hpb=60908c905544776c376421b8d3e12eeb936c068f;p=supertux.git diff --git a/src/file_system.cpp b/src/file_system.cpp index af243f837..266da812f 100644 --- a/src/file_system.cpp +++ b/src/file_system.cpp @@ -1,222 +1,110 @@ -#include +// $Id$ +// +// SuperTux +// Copyright (C) 2006 Matthias Braun +// +// 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 -#include -#include -#ifndef WIN32 -#include -#endif +#include -#include "resources.h" +#include "log.hpp" +#include "file_system.hpp" -#ifdef WIN32 -#define mkdir(dir, mode) mkdir(dir) -#endif +#include +#include +#include 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 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 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 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 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 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 read_directory(const std::string& pathname) -{ - std::set 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::iterator i = path_stack.begin(); + i != path_stack.end(); ++i) { + result << '/' << *i; + } + if(path_stack.empty()) + result << '/'; + + return result.str(); } } -