| 1 | /* | 
|---|
| 2 |    orxonox - the future of 3D-vertical-scrollers | 
|---|
| 3 |  | 
|---|
| 4 |    Copyright (C) 2004 orx | 
|---|
| 5 |  | 
|---|
| 6 |    This program is free software; you can redistribute it and/or modify | 
|---|
| 7 |    it under the terms of the GNU General Public License as published by | 
|---|
| 8 |    the Free Software Foundation; either version 2, or (at your option) | 
|---|
| 9 |    any later version. | 
|---|
| 10 |  | 
|---|
| 11 | ### File Specific: | 
|---|
| 12 |    main-programmer: Benjamin Grauer | 
|---|
| 13 |    co-programmer: ... | 
|---|
| 14 | */ | 
|---|
| 15 |  | 
|---|
| 16 | #include "file.h" | 
|---|
| 17 |  | 
|---|
| 18 | #include <sys/types.h> | 
|---|
| 19 | #include <sys/stat.h> | 
|---|
| 20 | #include <stdio.h> | 
|---|
| 21 |  | 
|---|
| 22 | #include <iostream> | 
|---|
| 23 | #include <fstream> | 
|---|
| 24 |  | 
|---|
| 25 | #ifdef __unix__ | 
|---|
| 26 | #include <unistd.h> | 
|---|
| 27 | #elif __WIN32__ || _MS_DOS_ | 
|---|
| 28 | #include <dir.h> | 
|---|
| 29 | #else | 
|---|
| 30 | #include <direct.h> | 
|---|
| 31 | #endif | 
|---|
| 32 |  | 
|---|
| 33 | #include <cassert> | 
|---|
| 34 |  | 
|---|
| 35 | File::File() | 
|---|
| 36 | { | 
|---|
| 37 |   this->init(); | 
|---|
| 38 | } | 
|---|
| 39 |  | 
|---|
| 40 | File::File(const std::string& fileName) | 
|---|
| 41 | { | 
|---|
| 42 |   this->init(); | 
|---|
| 43 |   this->setFileName(fileName); | 
|---|
| 44 | } | 
|---|
| 45 |  | 
|---|
| 46 | File::File(const File& file) | 
|---|
| 47 | { | 
|---|
| 48 |   this->init(); | 
|---|
| 49 |   this->setFileName(file.name()); | 
|---|
| 50 | } | 
|---|
| 51 |  | 
|---|
| 52 | File::~File() | 
|---|
| 53 | { | 
|---|
| 54 |   this->close(); | 
|---|
| 55 |  | 
|---|
| 56 |   if (this->_status) | 
|---|
| 57 |     delete this->_status; | 
|---|
| 58 | } | 
|---|
| 59 |  | 
|---|
| 60 |  | 
|---|
| 61 | /** | 
|---|
| 62 |  * @brief initializes the File | 
|---|
| 63 |  * | 
|---|
| 64 |  * Stats the File, looks if it exists and sets the hadle to 0 | 
|---|
| 65 |  */ | 
|---|
| 66 | void File::init() | 
|---|
| 67 | { | 
|---|
| 68 |   this->_handle = 0; | 
|---|
| 69 |   this->_status = NULL; | 
|---|
| 70 | } | 
|---|
| 71 |  | 
|---|
| 72 |  | 
|---|
| 73 | /** | 
|---|
| 74 |  * @brief sets a new File to apply to this File. | 
|---|
| 75 |  * @param fileName the Filename of the File to access. | 
|---|
| 76 |  */ | 
|---|
| 77 | void File::setFileName(const std::string& fileName) | 
|---|
| 78 | { | 
|---|
| 79 |   this->close(); | 
|---|
| 80 |   this->_name = fileName; | 
|---|
| 81 |   File::homeDirCheck(this->_name); | 
|---|
| 82 |   this->statFile(); | 
|---|
| 83 | } | 
|---|
| 84 |  | 
|---|
| 85 | /** | 
|---|
| 86 |  * @brief sets the file to the new File. | 
|---|
| 87 |  * @param fileName the FileName to set the File to. | 
|---|
| 88 |  * @returns this File. | 
|---|
| 89 |  */ | 
|---|
| 90 | File& File::operator=(const std::string& fileName) | 
|---|
| 91 | { | 
|---|
| 92 |   this->setFileName(fileName); | 
|---|
| 93 |   return *this; | 
|---|
| 94 | } | 
|---|
| 95 |  | 
|---|
| 96 | /** | 
|---|
| 97 |  * @brief sets the file to the new File. | 
|---|
| 98 |  * @param file the File to set the File to. | 
|---|
| 99 |  * @returns this File. | 
|---|
| 100 |  */ | 
|---|
| 101 | File& File::operator=(const File& file) | 
|---|
| 102 | { | 
|---|
| 103 |   this->setFileName(file.name()); | 
|---|
| 104 |   return *this; | 
|---|
| 105 | } | 
|---|
| 106 |  | 
|---|
| 107 | /** | 
|---|
| 108 |  * @brief compares two files. | 
|---|
| 109 |  * @param fileName the File to compare against the stored one. | 
|---|
| 110 |  * @returns true if the filenames match. | 
|---|
| 111 |  */ | 
|---|
| 112 | bool File::operator==(const std::string& fileName) const | 
|---|
| 113 | { | 
|---|
| 114 |   return (this->_name == fileName); | 
|---|
| 115 | } | 
|---|
| 116 |  | 
|---|
| 117 | /** | 
|---|
| 118 |  * @brief compares two files. | 
|---|
| 119 |  * @param file the File to compare against the stored one. | 
|---|
| 120 |  * @returns true if the filenames match. | 
|---|
| 121 |  */ | 
|---|
| 122 | bool File::operator==(const File& file) const | 
|---|
| 123 | { | 
|---|
| 124 |   return (this->_name == file.name()); | 
|---|
| 125 | } | 
|---|
| 126 |  | 
|---|
| 127 |  | 
|---|
| 128 |  | 
|---|
| 129 | /** | 
|---|
| 130 |  * @brief stats a File. | 
|---|
| 131 |  * Gathers information about the File, like permissions, and if it exists. | 
|---|
| 132 |  */ | 
|---|
| 133 | void File::statFile() | 
|---|
| 134 | { | 
|---|
| 135 |   if (this->_status == NULL) | 
|---|
| 136 |     this->_status = new struct stat; | 
|---|
| 137 |   // Check the End of the FileName and chop away any \ and // | 
|---|
| 138 |   /*  std::string name = this->_name; | 
|---|
| 139 |     if (this->_name[this->_name.size()-1] == '/' || | 
|---|
| 140 |         this->_name[this->_name.size()-1] == '\\') | 
|---|
| 141 |          name.resize(name.size()-1);*/ | 
|---|
| 142 |   if (stat(this->_name.c_str(), this->_status)) | 
|---|
| 143 |   { | 
|---|
| 144 |     delete this->_status; | 
|---|
| 145 |     this->_status = NULL; | 
|---|
| 146 |   } | 
|---|
| 147 | } | 
|---|
| 148 |  | 
|---|
| 149 | bool File::open(OpenMode mode) | 
|---|
| 150 | { | 
|---|
| 151 | #warning implement | 
|---|
| 152 | } | 
|---|
| 153 |  | 
|---|
| 154 | bool File::close() | 
|---|
| 155 | { | 
|---|
| 156 | #warning implement | 
|---|
| 157 | } | 
|---|
| 158 |  | 
|---|
| 159 | bool File::exists() const | 
|---|
| 160 | { | 
|---|
| 161 |   return (this->_status != NULL); | 
|---|
| 162 | } | 
|---|
| 163 |  | 
|---|
| 164 | /** | 
|---|
| 165 |  * @brief checks if the file is a Link (symlink/hardlink on UNIX) | 
|---|
| 166 |  * @returns true if the File is a Link, false otherwise (on windows always false) | 
|---|
| 167 |  */ | 
|---|
| 168 | bool File::isLink() const | 
|---|
| 169 | { | 
|---|
| 170 | #ifndef __WIN32__ | 
|---|
| 171 |   return (this->_status != NULL && this->_status->st_mode & (S_IFLNK)); | 
|---|
| 172 | #else | 
|---|
| 173 |   return false; | 
|---|
| 174 | #endif | 
|---|
| 175 | } | 
|---|
| 176 |  | 
|---|
| 177 | /** | 
|---|
| 178 |  * @brief checks if the File is a regular File | 
|---|
| 179 |  * @returns true if the File is a Regular file. | 
|---|
| 180 |  */ | 
|---|
| 181 | bool File::isFile() const | 
|---|
| 182 | { | 
|---|
| 183 |   return (this->_status != NULL && this->_status->st_mode & (S_IFREG)); | 
|---|
| 184 | } | 
|---|
| 185 |  | 
|---|
| 186 | /** | 
|---|
| 187 |  * @brief Checks if the File is a Directory | 
|---|
| 188 |  * @returns true if it is a directory/symlink false otherwise | 
|---|
| 189 |  */ | 
|---|
| 190 | bool File::isDirectory() const | 
|---|
| 191 | { | 
|---|
| 192 |   // checking for the termination of the string given. If there is a "/" at the end cut it away | 
|---|
| 193 |   //if (this->_name[this->_name.size()-1] == '/' || | 
|---|
| 194 |   //    this->_name[this->_name.size()-1] == '\\') | 
|---|
| 195 |   //{ | 
|---|
| 196 |   //  tmpDirName.erase(tmpDirName.size()-1); | 
|---|
| 197 |   //} | 
|---|
| 198 |   return (this->_status != NULL && this->_status->st_mode & (S_IFDIR)); | 
|---|
| 199 | } | 
|---|
| 200 |  | 
|---|
| 201 |  | 
|---|
| 202 | /// FIXME NEXT THREE FUNCTIONS | 
|---|
| 203 | bool File::isReadeable() const | 
|---|
| 204 | { | 
|---|
| 205 | #ifndef __WIN32__ | 
|---|
| 206 |   return (this->_status != NULL && this->_status->st_mode & (S_IRUSR)); | 
|---|
| 207 | #else | 
|---|
| 208 |   return (this->_status != NULL); | 
|---|
| 209 | #endif | 
|---|
| 210 | } | 
|---|
| 211 | bool File::isWriteable() const | 
|---|
| 212 | { | 
|---|
| 213 | #ifndef __WIN32__ | 
|---|
| 214 |   return (this->_status != NULL && this->_status->st_mode & (S_IWUSR)); | 
|---|
| 215 | #else | 
|---|
| 216 |   return (this->_status != NULL); | 
|---|
| 217 | #endif | 
|---|
| 218 | } | 
|---|
| 219 | bool File::isExecutable() const | 
|---|
| 220 | { | 
|---|
| 221 | #ifndef __WIN32__ | 
|---|
| 222 |   return (this->_status != NULL && this->_status->st_mode & (S_IXUSR)); | 
|---|
| 223 | #else | 
|---|
| 224 |   return (this->_status != NULL); | 
|---|
| 225 | #endif | 
|---|
| 226 | } | 
|---|
| 227 |  | 
|---|
| 228 | /** | 
|---|
| 229 |  * @brief copies the File to another File. | 
|---|
| 230 |  * @param destination the Destination File. | 
|---|
| 231 |  * @returns true on success, false otherwise. | 
|---|
| 232 |  */ | 
|---|
| 233 | bool File::copy(const File& destination) | 
|---|
| 234 | { | 
|---|
| 235 |   char ch; | 
|---|
| 236 |   std::ifstream iFile(this->_name.c_str()); | 
|---|
| 237 |   std::ofstream oFile(destination.name().c_str()); | 
|---|
| 238 |   while (iFile.get(ch)) | 
|---|
| 239 |   { | 
|---|
| 240 |     oFile.put(ch); | 
|---|
| 241 |   } | 
|---|
| 242 | } | 
|---|
| 243 |  | 
|---|
| 244 | /** | 
|---|
| 245 |  * @brief renames the File (move) | 
|---|
| 246 |  * @param destination the Destination to move this file to. | 
|---|
| 247 |  * @returns true on success, false otherwise. | 
|---|
| 248 |  * | 
|---|
| 249 |  * if the File was opened, it will be closed throuh this function. | 
|---|
| 250 |  */ | 
|---|
| 251 | bool File::rename(const File& destination) | 
|---|
| 252 | { | 
|---|
| 253 |   if (!std::rename(this->_name.c_str(), destination.name().c_str())) | 
|---|
| 254 |   { | 
|---|
| 255 |     this->close(); | 
|---|
| 256 |     this->_name = destination.name(); | 
|---|
| 257 |     this->statFile(); | 
|---|
| 258 |  | 
|---|
| 259 |     return true; | 
|---|
| 260 |   } | 
|---|
| 261 |   return false; | 
|---|
| 262 | } | 
|---|
| 263 |  | 
|---|
| 264 | /** | 
|---|
| 265 |  * @brief touches the File. | 
|---|
| 266 |  * @returns true if the file could have been touched. false otherwise. | 
|---|
| 267 |  * | 
|---|
| 268 |  * Touching a File means creating it. | 
|---|
| 269 |  */ | 
|---|
| 270 | bool File::touch() | 
|---|
| 271 | { | 
|---|
| 272 |   FILE* stream; | 
|---|
| 273 |   if( (stream = fopen (this->_name.c_str(), "w")) == NULL) | 
|---|
| 274 |   { | 
|---|
| 275 |     std::cout << "could not touch '" << this->_name << "' for writing\n"; | 
|---|
| 276 |     return false; | 
|---|
| 277 |   } | 
|---|
| 278 |   fclose(stream); | 
|---|
| 279 |   return true; | 
|---|
| 280 | } | 
|---|
| 281 |  | 
|---|
| 282 | /** | 
|---|
| 283 |  * @brief delete the File on the Disk | 
|---|
| 284 |  * @returns true on success, false otherwise. | 
|---|
| 285 |  */ | 
|---|
| 286 | bool File::remove() | 
|---|
| 287 | { | 
|---|
| 288 |   unlink(this->_name.c_str()); | 
|---|
| 289 |   delete this->_status; | 
|---|
| 290 |   this->_status = NULL; | 
|---|
| 291 |   /// FIXME HANDLE | 
|---|
| 292 | } | 
|---|
| 293 |  | 
|---|
| 294 | /** | 
|---|
| 295 |  * @brief transforms a Relative path to an absolute one. | 
|---|
| 296 |  * @param fileName the Absolute Path. | 
|---|
| 297 |  */ | 
|---|
| 298 | void File::relToAbs(std::string& relFileName) | 
|---|
| 299 | { | 
|---|
| 300 |   if (relFileName.empty()) | 
|---|
| 301 |     return ; | 
|---|
| 302 |   if (relFileName[0] !=  '/') | 
|---|
| 303 |   { | 
|---|
| 304 |     if (relFileName[0] == '.' && relFileName[1] != '.') | 
|---|
| 305 |       relFileName.erase(0); | 
|---|
| 306 |     relFileName = File::cwd() + relFileName; | 
|---|
| 307 |   } | 
|---|
| 308 | } | 
|---|
| 309 |  | 
|---|
| 310 | void File::absToRel(std::string& absFileName) | 
|---|
| 311 | { | 
|---|
| 312 |   if (absFileName.find(cwd()) == 0) | 
|---|
| 313 |     absFileName.replace(0, File::cwd().size(), "."); | 
|---|
| 314 | } | 
|---|
| 315 |  | 
|---|
| 316 |  | 
|---|
| 317 | std::string File::_cwd = ""; | 
|---|
| 318 |  | 
|---|
| 319 | /** | 
|---|
| 320 |  * @returns the Current Woring Directory | 
|---|
| 321 |  */ | 
|---|
| 322 | const std::string& File::cwd() | 
|---|
| 323 | { | 
|---|
| 324 |   if (File::_cwd.empty()) | 
|---|
| 325 |   { | 
|---|
| 326 |     char cwd[1024]; | 
|---|
| 327 |     char* errorCode = getcwd(cwd, 1024); | 
|---|
| 328 |     if (errorCode == 0) | 
|---|
| 329 |       return File::_cwd; | 
|---|
| 330 |  | 
|---|
| 331 |     File::_cwd = cwd; | 
|---|
| 332 |   } | 
|---|
| 333 |   return File::_cwd; | 
|---|
| 334 | } | 
|---|
| 335 |  | 
|---|
| 336 | /** | 
|---|
| 337 |  * @brief check if fileName has the '~/` prepended. | 
|---|
| 338 |  * @returns the fileName in absolute coordinate. | 
|---|
| 339 |  */ | 
|---|
| 340 | void File::homeDirCheck(std::string& fileName) | 
|---|
| 341 | { | 
|---|
| 342 |   if (fileName.size() < 2 || fileName[0] != '~' || fileName[1] != '/') | 
|---|
| 343 |     return; | 
|---|
| 344 |   std::string homeDir; | 
|---|
| 345 | #ifdef __WIN32__ | 
|---|
| 346 |   homeDir = getenv("USERPROFILE"); | 
|---|
| 347 | #else | 
|---|
| 348 |   homeDir = getenv("HOME"); | 
|---|
| 349 | #endif | 
|---|
| 350 |   fileName = homeDir + fileName.substr(1); | 
|---|
| 351 | } | 
|---|
| 352 |  | 
|---|
| 353 |  | 
|---|
| 354 | #include "file.h" | 
|---|
| 355 |  | 
|---|
| 356 |  | 
|---|