/* orxonox - the future of 3D-vertical-scrollers Copyright (C) 2004 orx 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, or (at your option) any later version. ### File Specific: main-programmer: Benjamin Grauer co-programmer: ... */ #include "file.h" #include #include #include #include #include #ifdef __unix__ #include #elif __WIN32__ || _MS_DOS_ #include #else //#include #endif /** * @brief default constructor. */ File::File() { this->init(); } /** * @brief A File will be constructed and stated from a given FileName. * @param fileName the FileName to load and stat. */ File::File(const std::string& fileName) { this->init(); this->setFileName(fileName); } /** * @brief A File will be constructed and stated from a given other File. * @param file the File to get the Name from. */ File::File(const File& file) { this->init(); this->setFileName(file.name()); } File::~File() { this->close(); if (this->_status) delete this->_status; } /** * @brief initializes the File * * Stats the File, looks if it exists and sets the hadle to 0 */ void File::init() { this->_handle = 0; this->_status = NULL; } /** * @brief sets a new File to apply to this File. * @param fileName the Filename of the File to access. */ void File::setFileName(const std::string& fileName) { this->close(); this->_name = fileName; File::homeDirCheck(this->_name); this->statFile(); } /** * @brief sets the file to the new File. * @param fileName the FileName to set the File to. * @returns this File. */ File& File::operator=(const std::string& fileName) { this->setFileName(fileName); return *this; } /** * @brief sets the file to the new File. * @param file the File to set the File to. * @returns this File. */ File& File::operator=(const File& file) { this->setFileName(file.name()); return *this; } /** * @brief compares two files. * @param fileName the File to compare against the stored one. * @returns true if the filenames match. */ bool File::operator==(const std::string& fileName) const { return (this->_name == fileName); } /** * @brief compares two files. * @param file the File to compare against the stored one. * @returns true if the filenames match. */ bool File::operator==(const File& file) const { return (this->_name == file.name()); } /** * @brief stats a File. * Gathers information about the File, like permissions, and if it exists. */ void File::statFile() { if (this->_status == NULL) this->_status = new struct stat; // Check the End of the FileName and chop away any \ and // std::string name = this->_name; while (name[name.size()-1] == '/' || name[name.size()-1] == '\\') name.resize(name.size()-1); if (stat(name.c_str(), this->_status)) { delete this->_status; this->_status = NULL; } } bool File::open( OpenMode mode ) { static const char* openModeStrings[] = { "r", "w", "r+", "a+" }; _mode = mode; _handle = fopen( name().c_str(), openModeStrings[mode] ); return ( _handle != NULL ); } bool File::close() { if ( _handle != NULL ) { int success = fclose( _handle ); _handle = NULL; return ( success == 0 ); } return false; } bool File::exists() const { return (this->_status != NULL); } /** * @brief checks if the file is a Link (symlink/hardlink on UNIX) * @returns true if the File is a Link, false otherwise (on windows always false) */ bool File::isLink() const { #ifndef __WIN32__ return (this->_status != NULL && this->_status->st_mode & (S_IFLNK)); #else return false; #endif } /** * @brief checks if the File is a regular File * @returns true if the File is a Regular file. */ bool File::isFile() const { return (this->_status != NULL && this->_status->st_mode & (S_IFREG)); } /** * @brief Checks if the File is a Directory * @returns true if it is a directory/symlink false otherwise */ bool File::isDirectory() const { return (this->_status != NULL && this->_status->st_mode & (S_IFDIR)); } /// FIXME NEXT THREE FUNCTIONS bool File::isReadable() const { #ifndef __WIN32__ return (this->_status != NULL && this->_status->st_mode & (S_IRUSR)); #else return (this->_status != NULL); #endif } bool File::isWriteable() const { #ifndef __WIN32__ return (this->_status != NULL && this->_status->st_mode & (S_IWUSR)); #else return (this->_status != NULL); #endif } bool File::isExecutable() const { #ifndef __WIN32__ return (this->_status != NULL && this->_status->st_mode & (S_IXUSR)); #else return (this->_status != NULL); #endif } /** * @brief copies the File to another File. * @param destination the Destination File. * @returns true on success, false otherwise. */ bool File::copy(const File& destination) { if (*this == destination) { std::cout << "files are the Same '" << this->_name << "'\n"; return false; } char ch; std::ifstream iFile(this->_name.c_str()); std::ofstream oFile(destination.name().c_str()); while (iFile.get(ch)) { oFile.put(ch); } return true; } /** * @brief renames the File (move) * @param destination the Destination to move this file to. * @returns true on success, false otherwise. * * if the File was opened, it will be closed throuh this function. * The File will also be closed, if the File was not renamed. */ bool File::rename(const File& destination) { this->close(); if (!std::rename(this->_name.c_str(), destination.name().c_str())) { this->_name = destination.name(); this->statFile(); return true; } return false; } /** * @brief touches the File. * @returns true if the file could have been touched. false otherwise. * * Touching a File means creating it. */ bool File::touch() { FILE* stream; if( (stream = fopen (this->_name.c_str(), "w")) == NULL) { std::cout << "could not touch '" << this->_name << "' for writing\n"; return false; } fclose(stream); this->statFile(); return true; } /** * @brief delete the File on the Disk * @returns true on success, false otherwise. */ bool File::remove() { if (!this->exists()) return false; this->close(); unlink(this->_name.c_str()); delete this->_status; this->_status = NULL; return true; } /** * @brief transforms a Relative path to an absolute one. * @param fileName the Absolute Path. */ void File::relToAbs(std::string& relFileName) { if (relFileName.empty()) return ; if (relFileName[0] != '/') { if (relFileName[0] == '.' && relFileName[1] != '.') relFileName.erase(0); relFileName = File::cwd() + relFileName; } } void File::absToRel(std::string& absFileName) { if (absFileName.find(cwd()) == 0) absFileName.replace(0, File::cwd().size(), "."); } std::string File::_cwd = ""; /** * @returns the Current Woring Directory */ const std::string& File::cwd() { if (File::_cwd.empty()) { char cwd[1024]; char* errorCode = getcwd(cwd, 1024); if (errorCode == 0) return File::_cwd; File::_cwd = cwd; } return File::_cwd; } /** * @brief check if fileName has the '~/` prepended. * @returns the fileName in absolute coordinate. */ void File::homeDirCheck(std::string& fileName) { if (fileName.size() < 2 || fileName[0] != '~' || fileName[1] != '/') return; std::string homeDir; #ifdef __WIN32__ homeDir = getenv("USERPROFILE"); #else homeDir = getenv("HOME"); #endif fileName = homeDir + fileName.substr(1); }