src/tools/tDirectories.cpp

Go to the documentation of this file.
00001 /*
00002 
00003 *************************************************************************
00004 
00005 ArmageTron -- Just another Tron Lightcycle Game in 3D.
00006 Copyright (C) 2000  Manuel Moos (manuel@moosnet.de)
00007 Copyright (C) 2004  Armagetron Advanced Team (http://sourceforge.net/projects/armagetronad/)
00008 
00009 **************************************************************************
00010 
00011 This program is free software; you can redistribute it and/or
00012 modify it under the terms of the GNU General Public License
00013 as published by the Free Software Foundation; either version 2
00014 of the License, or (at your option) any later version.
00015 
00016 This program is distributed in the hope that it will be useful,
00017 but WITHOUT ANY WARRANTY; without even the implied warranty of
00018 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019 GNU General Public License for more details.
00020 
00021 You should have received a copy of the GNU General Public License
00022 along with this program; if not, write to the Free Software
00023 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00024 
00025 ***************************************************************************
00026 
00027 */
00028 
00029 #include "aa_config.h"
00030 
00031 #include <errno.h>
00032 #include <sys/types.h>
00033 #ifndef WIN32
00034 #include <sys/stat.h>
00035 #endif
00036 #include <stdio.h>
00037 #include <stdlib.h>
00038 
00039 #include "tLocale.h"
00040 #include "tDirectories.h"
00041 #include "tString.h"
00042 #include "tConfiguration.h"
00043 #include "tCommandLine.h"
00044 #include "tMemManager.h"
00045 
00046 #if HAVE_UNISTD_H
00047 #include <unistd.h>
00048 #endif
00049 
00050 // include definition for top source directory
00051 #ifndef MACOSX_XCODE
00052 #ifdef TOP_SOURCE_DIR
00053 static const char * s_topSourceDir = TOP_SOURCE_DIR;
00054 #else
00055 static const char * s_topSourceDir = ".";
00056 #endif
00057 #endif // !MACOSX_XCODE
00058 
00059 // program name definition
00060 #ifndef PROGNAME
00061 #ifdef DEDICATED
00062 #define PROGNAME "armagetronad-dedicated"
00063 #else
00064 #define PROGNAME "armagetronad"
00065 #endif
00066 #endif
00067 
00068 #ifndef PROGNAMEBASE
00069 #define PROGNAMEBASE "armagetronad"
00070 #endif
00071 
00072 #ifndef PROGDIR_SUFFIX
00073 #define PROGDIR_SUFFIX ""
00074 #endif
00075 
00076 #ifdef WIN32
00077 // activate used function from shlobj.h (z-man does not know if this is a bad hack)
00078 #ifdef __MINGW32__
00079 #define _WIN32_IE 0x400
00080 #endif
00081 
00082 #include <direct.h>
00083 #include <windows.h>
00084 #include <shlobj.h>
00085 #define mkdir(x, y)   _mkdir(x)
00086 #ifndef strdup
00087 #define strdup        _strdup
00088 #endif
00089 #ifndef _stat
00090 #define _stat stat
00091 #endif
00092 #else
00093 #include <pwd.h>
00094 #endif
00095 
00096 #ifdef TOP_SOURCE_DIR
00097 // #include "tPaths.h"
00098 #include "tUniversalVariables.h"
00099 #endif
00100 
00101 #ifndef PREFIX
00102 #define PREFIX "/usr/local"
00103 #endif
00104 
00105 #ifndef BINDIR
00106 #define BINDIR "/usr/local/bin"
00107 #endif
00108 
00109 // move variables out of binrelocs macros way
00110 static tString st_prefixCompiled(PREFIX);
00111 static tString st_bindirCompiled(BINDIR);
00112 
00113 // Paths from root to binaries, data and config ( so we can do search&replace to get
00114 // from the binary path to the data and config )
00115 #ifndef SYSBINDIR
00116 #define SYSBINDIR "/does/not/exist"
00117 #endif
00118 
00119 #ifndef DATASUFFIX
00120 #define DATASUFFIX ""
00121 #endif
00122 
00123 #ifndef CONFIGSUFFIX
00124 #define CONFIGSUFFIX ""
00125 #endif
00126 
00127 #define PROGDIR PROGNAME PROGDIR_SUFFIX
00128 
00129 #ifdef WIN32
00130 // activate used function from shlobj.h (z-man does not know if this is a bad hack)
00131 #ifdef __MINGW32__
00132 #define _WIN32_IE 0x400
00133 #endif
00134 
00135 #undef DATADIR
00136 #include <direct.h>
00137 #include <windows.h>
00138 #include <shlobj.h>
00139 #define mkdir(x, y)   _mkdir(x)
00140 #ifndef strdup
00141 #define strdup        _strdup
00142 #endif
00143 #ifndef _stat
00144 #define _stat stat
00145 #endif
00146 #else
00147 #include <pwd.h>
00148 #endif
00149 
00150 #ifdef DEBUG
00151 // define this if you want file search debug output
00152 //#define PRINTSEARCH
00153 //#define DEBUG_PATH
00154 #endif
00155 
00156 #include <dirent.h>
00157 #include <sys/types.h>
00158 #include <sys/stat.h>
00159 
00160 #ifdef ENABLE_BINRELOC
00161 #include "thirdparty/binreloc/prefix.h"
00162 #endif
00163 
00164 tString expand_home(const tString & pathname);
00165 
00166 #define expand_home_c(c) expand_home(tString(c))
00167 
00168 #ifdef DATA_DIR
00169 static tString st_DataDir(expand_home_c(DATA_DIR));    // directory for game data
00170 #else
00171 static tString st_DataDir(".");    // directory for game data
00172 #endif
00173 
00174 #ifdef MUSIC_DIR
00175 static tString st_MusicDir(expand_home_c(DATA_DIR));    // directory for game music
00176 #else
00177 static tString st_MusicDir(".");    // directory for game music
00178 #endif
00179 
00180 #ifdef USER_DATA_DIR
00181 static tString st_UserDataDir(expand_home_c(USER_DATA_DIR));    // directory for game data
00182 #else
00183 static tString st_UserDataDir(expand_home_c("~/." PROGDIR));    // directory for game data
00184 #endif
00185 
00186 #ifdef CONFIG_DIR
00187 static tString st_ConfigDir(expand_home_c(CONFIG_DIR));  // directory for static configuration files
00188 #else
00189 static tString st_ConfigDir("");  // directory for static configuration files
00190 #endif
00191 
00192 #ifdef SCRIPT_DIR
00193 static tString st_ScriptDir(expand_home_c(SCRIPT_DIR));  // directory for scripts
00194 #else
00195 static tString st_ScriptDir("");  // directory for scripts
00196 #endif
00197 
00198 #ifdef USER_CONFIG_DIR
00199 static tString st_UserConfigDir(expand_home_c(USER_CONFIG_DIR));  // directory for static configuration files
00200 #else
00201 static tString st_UserConfigDir("");  // directory for static configuration files
00202 #endif
00203 
00204 #ifdef VAR_DIR
00205 static tString st_VarDir(expand_home_c(VAR_DIR));     // directory for dynamic logs and highscores
00206 #else
00207 static tString st_VarDir("");     // directory for dynamic logs and highscores
00208 #endif
00209 
00210 #ifdef DEDICATED
00211 #ifdef WWWROOTDIR
00212 static tString st_WwwDir(expand_home_c(WWWROOTDIR));     // directory for dynamic logs and highscores
00213 #else
00214 static tString st_WwwDir("");     // directory for dynamic logs and highscores
00215 #endif
00216 #endif
00217 
00218 #ifdef RESOURCE_DIR
00219 static tString st_ResourceDir(expand_home_c(RESOURCE_DIR));
00220 #else
00221 static tString st_ResourceDir("");
00222 #endif
00223 
00224 #ifdef AUTORESOURCE_DIR
00225 static tString st_AutoResourceDir(expand_home_c(AUTORESOURCE_DIR));
00226 #else
00227 static tString st_AutoResourceDir("");
00228 #endif
00229 
00230 #ifdef INCLUDEDRESOURCE_DIR
00231 static tString st_IncludedResourceDir(expand_home_c(INCLUDEDRESOURCE_DIR));
00232 #else
00233 static tString st_IncludedResourceDir("");
00234 #endif
00235 
00236 #ifdef SCREENSHOT_DIR
00237 static tString st_ScreenshotDir(expand_home_c(SCREENSHOT_DIR));
00238 #else
00239 static tString st_ScreenshotDir("");
00240 #endif
00241 
00242 // checks whether a character is a path delimiter
00243 static bool st_IsPathDelimiter( char c )
00244 {
00245     return  ( c == '/' || c == '\\' );
00246 }
00247 
00248 /*
00249 Recursively creates directories.
00250 Parameters:
00251 pathname: The path to create. Must have aat least one / and last directory must be suffix'd with a /
00252 safe_path: The number of characters to assume safe for usage. Checking for .* is disabled for these.
00253         Returns true if successful. Returns false if unsuccessful or in hidden-file circumstances!
00254                 */
00255 static bool mkdir_recurse(char *pathname, size_t safe_path) {
00256     // method: strip path segments from the end, try to make the directory up to there.
00257     // once this succeeded, rebuild the path, making all the subdirectories as you go.
00258 
00259     size_t i;
00260     bool fs = false; // forward search flag. if set, start rebuilding the path
00261     bool e  = false; // error flag.
00262 
00263     size_t len = strlen(pathname); // the total length of the path
00264 
00265     for (i = len - 1; i < len && !e; fs ? ++i : --i) {
00266         if ( st_IsPathDelimiter( pathname[i] ) ) {
00267             if (pathname[i + 1] == '.' && i + 2 > safe_path)
00268                 return false; // abort; we have a hidden file/dir!
00269             char delimiter = pathname[i];
00270             pathname[i] = '\0';
00271 
00272 #ifdef DEBUG_PATH
00273             static bool first = true;
00274             if (fs || first )
00275             {
00276                 first = false;
00277                 con << "Making directory " << pathname << "\n";
00278             }
00279 #endif
00280 
00281             if (!mkdir(pathname, 0777) || errno == EEXIST)
00282                 fs = true;
00283             else if (fs)
00284                 e = true;
00285             pathname[i] = delimiter;
00286         }
00287         if (i == 0 && !fs)
00288             e = true;
00289     }
00290     return !e;
00291 }
00292 
00293 static bool st_checkPathAbsolute = true; // check for absolute paths
00294 static bool st_checkPathRelative = true; // check for relative paths
00295 static bool st_checkPathHidden   = true; // check for hidden files/directories in paths
00296 
00297 // *******************************************************************************************
00298 // *
00299 // *   IsValidPath
00300 // *
00301 // *******************************************************************************************
00314 // *******************************************************************************************
00315 
00316 bool tPath::IsValidPath( char const * filename )
00317 {
00318     // always check for empty paths
00319     if ( !filename || filename[0] == 0 )
00320     {
00321         con << tOutput( "$directory_path_null" );
00322         return false;
00323     }
00324 
00325     // check for absolute paths (the system would not make them absolute, so no real
00326     // danger comes from them, but we check anyway)
00327     if ( st_checkPathAbsolute && ( st_IsPathDelimiter( filename[0] ) || strstr(filename,":") ) )
00328     {
00329         con << tOutput( "$directory_path_absolute", filename );
00330         return false;
00331     }
00332 
00333     // check for relative paths. Those are the real danger. Search for .. and see
00334     // if it surrounded by path delimiters or string ends.
00335     if ( st_checkPathRelative )
00336     {
00337         // traverse through occurences of ..
00338         char const * run = filename;
00339         while ( run && *run )
00340         {
00341             // find next ..
00342             run = strstr(run,"..");
00343 
00344             // check if before and after that come no path delimiters
00345             if ( run )
00346             {
00347                 if ( ( run == filename || st_IsPathDelimiter( run[-1] ) ) &&
00348                         ( run[2] == 0 || st_IsPathDelimiter( run[2] ) ) )
00349                 {
00350                     con << tOutput( "$directory_path_relative", filename );
00351                     return false;
00352                 }
00353 
00354                 // go on searching
00355                 run ++;
00356             }
00357         }
00358     }
00359 
00360     // hidden paths are a path delimiter followed by a ., but not ..<delimiter>.
00361     if ( st_checkPathHidden )
00362     {
00363         // iterate path segments
00364         char const * run = filename;
00365         while ( run && *run )
00366         {
00367             // check if it is a hidden file
00368             if ( run[0] == '.' )
00369             {
00370                 // don't give false alarm for relative paths
00371                 if ( run[1] != '.' || ( !st_IsPathDelimiter( run[2] ) && run[2] != 0 ) )
00372                 {
00373                     con << tOutput( "$directory_path_hidden", filename );
00374                     return false;
00375                 }
00376             }
00377 
00378             // proceed to next path segments: find next path delimiter
00379             while ( *run && !st_IsPathDelimiter( *run ) )
00380                 ++run;
00381 
00382             // go to next character after that
00383             if ( *run )
00384                 ++run;
00385         }
00386     }
00387 
00388     return true;
00389 }
00390 
00391 /*
00392 Parses "~", "~username", "${HOME}", "${HOME:username}", etc
00393 */
00394 char *eh_getdir(const char *da, size_t *len) {
00395     const char *s, *r, *d;
00396     char *type = 0, *user = 0, *ret = 0;
00397     size_t l;
00398 
00399     // Step 1: Extract type, user, and *len
00400     if (da[0] == '~') {
00401         type = strdup("HOME");
00402         {
00403             // find first occurence of slash or backslash
00404             char const * slash = strchr(da, '/');
00405             char const * backslash = strchr(da, '\\');
00406             if ( slash && backslash )
00407                 d = slash < backslash ? slash : backslash;
00408             else
00409                 d = slash ? slash : backslash;
00410         }
00411         l = ((d ? d : strchr(da, '\0')) - da - 1) * sizeof(char);
00412         user = (char *)memcpy(malloc(l + sizeof(char)), da + 1, l); user[l] = '\0';
00413         *len = l + 1;
00414     } else if (!strncmp(da, "${", 2)) {
00415         s = strchr(da, '}');
00416         if (!s) {
00417             // Invalid structure
00418             return 0;
00419         }
00420         if ((r = strchr(da, ':'))) {
00421             l = (s - r - 1) * sizeof(char);
00422             user = (char *)memcpy(malloc(l + sizeof(char)), r + 1, l); user[l] = '\0';
00423         } else {
00424             r = s;
00425             user = (char *)malloc(sizeof(char));
00426             user[0] = '\0';
00427         }
00428         l = (r - da - 2) * sizeof(char);
00429         type = (char *)memcpy(malloc(l + sizeof(char)), da + 2, l); type[l] = '\0';
00430         *len = s - da + 1;
00431     }
00432 
00433     // Step 2: Resolve type/user into ret
00434 #ifdef WIN32
00435     if (!strcmp(type, "HOME")) {
00436         free(type);
00437         type = strdup("HOMEPATH");
00438     }
00439 #endif
00440     if ((ret = getenv(type)))
00441         ret = strdup(ret);
00442     else {
00443 # ifdef WIN32
00444         {
00445             char path[MAX_PATH];
00446             int ssf = 0;
00447 
00448             // Bug! This assumes user == current user! (who cares, but... yeah)
00449             if (!strcmp(type, "HOME"))   ssf = 0x28;
00450             if (!strcmp(type, "APPDATA"))  ssf = 0x1a;
00451             if (!strcmp(type, "COMMONAPPDATA")) ssf = 0x23;
00452             if (!strcmp(type, "DESKTOP"))  ssf = 0x10;
00453             if (!strcmp(type, "LOCALAPPDATA")) ssf = 0x1c;
00454             if (!strcmp(type, "MYPICTURES")) ssf = 0x27;
00455             if (!strcmp(type, "PERSONAL"))  ssf = 0x05;
00456             if (!strcmp(type, "PROFILE"))  ssf = 0x28;
00457             if (!strcmp(type, "SYSTEM"))  ssf = 0x25;
00458             if (!strcmp(type, "WINDOWS"))  ssf = 0x24;
00459 
00460             //if (ssf && SUCCEEDED(SHGetFolderPath(NULL, ssf, NULL, 0, path)))
00461             if (ssf && SHGetSpecialFolderPath(NULL, path, ssf, 1))
00462                 ret = strdup(path);
00463         }
00464 # else
00465         // fall back to default for HOME
00466         if (!strcmp(type, "HOME")) {
00467             struct passwd *pw;
00468 
00469             if (user[0] == '\0') // Current user
00470                 pw = getpwuid(getuid());
00471             else
00472                 pw = getpwnam(user);
00473             if (pw)
00474                 ret = strdup(pw->pw_dir);
00475             // struct passwd seems to do some really freaky stuff and doesn't like freeing? can someone confirm this?
00476         }
00477 # endif
00478         // TODO: fall back to hardcoded stuff in some cases?
00479     }
00480 
00481 #ifdef DEBUG_PATH
00482     std::cout << "Changing " << type << " to " << ret << "\n";
00483 #endif
00484 
00485     // Step 3: Cleanup
00486     free(type);
00487     free(user);
00488     if (!ret && da[0] != '~') {
00489         // Valid, but undefined
00490         free(ret);
00491         ret = (char *)malloc(sizeof(char));
00492         ret[0] = '\0';
00493     }
00494 
00495     return ret;
00496 }
00497 
00498 tString expand_home(tString const & pathname) {
00499     const char *pn = (const char *)pathname;
00500     char *s;
00501     size_t len;
00502     tString r;
00503 
00504     if ((pn[0] == '~' || !strncmp(pn, "${", 2)) && (s = eh_getdir(pn, &len))) {
00505         tString sStr(s);
00506         r = sStr << (pn + len);
00507         free(s);
00508     }
00509     else
00510         r = pathname;
00511 
00512 #ifdef DEBUG
00513     printf("changed %s to %s\n", (const char *)pathname, (const char *)r);
00514 #endif
00515     return r;
00516 }
00517 
00518 class tPathConfig: public tPath
00519 {
00520 public:
00521 private:
00522     void Paths ( tArray< tString >& paths ) const
00523     {
00524         paths.SetLen( 0 );
00525         int pos = 0;
00526 
00527         paths[ pos++ ] = st_DataDir + "/config";
00528 
00529         if ( st_ConfigDir.Len() > 1 )
00530         {
00531             paths[ pos++ ] = st_ConfigDir;
00532         }
00533 
00534         if ( st_UserDataDir.Len() > 1 )
00535         {
00536             paths[ pos++ ] = st_UserDataDir + "/config";
00537         }
00538 
00539         if ( st_UserConfigDir.Len() > 1 )
00540         {
00541             paths[ pos++ ] = st_UserConfigDir;
00542         }
00543     }
00544 };
00545 
00546 static const tPathConfig st_Config;
00547 
00548 class tPathData: public tPath
00549 {
00550 public:
00551 private:
00552     void Paths ( tArray< tString >& paths ) const
00553     {
00554         paths.SetLen( 0 );
00555         int pos = 0;
00556 
00557         paths[ pos++ ] = st_DataDir;
00558 
00559         if ( st_UserDataDir.Len() > 1 )
00560         {
00561             paths[ pos++ ] = st_UserDataDir;
00562         }
00563     }
00564 };
00565 
00566 static const tPathData st_Data;
00567 
00568 // This doesn't work because I don't understand this stuff at all :(  --Lucifer
00569 class tPathMusic: public tPath
00570 {
00571 public:
00572 private:
00573     void Paths ( tArray< tString >& paths ) const
00574     {
00575         paths.SetLen( 0 );
00576         int pos = 0;
00577 
00578         paths[ pos++ ] = st_MusicDir;
00579     }
00580 };
00581 
00582 static const tPathMusic st_Music;
00583 
00584 #ifdef DEDICATED
00585 void tPathWebroot::Paths ( tArray< tString >& paths ) const
00586 {
00587     paths.SetLen( 0 );
00588     int pos = 0;
00589 
00590     paths[ pos++ ] = st_WwwDir;
00591 }
00592 
00593 tString tPathWebroot::GetDirPath() {
00594     //std::cout << st_WwwDir;
00595     return st_WwwDir;
00596 }
00597 
00598 static const tPathWebroot st_Webroot;
00599 
00600 const tPathWebroot& tDirectories::Webroot()
00601 {
00602     return st_Webroot;
00603 }
00604 
00605 #endif
00606 
00607 class tPathVar: public tPath
00608 {
00609 public:
00610 private:
00611     void Paths ( tArray< tString >& paths ) const
00612     {
00613         paths.SetLen( 0 );
00614         int pos = 0;
00615 
00616         paths[ pos++ ] = st_DataDir + "/var";
00617 
00618         if ( st_UserDataDir.Len() > 1 )
00619         {
00620             paths[ pos++ ] = st_UserDataDir + "/var";
00621         }
00622 
00623         if ( st_VarDir.Len() > 1 )
00624         {
00625             paths[ pos++ ] = st_VarDir;
00626         }
00627     }
00628 };
00629 
00630 static const tPathVar st_Var;
00631 
00632 
00633 class tPathScreenshot: public tPath
00634 {
00635 public:
00636 private:
00637     void Paths ( tArray< tString >& paths ) const
00638     {
00639         paths.SetLen( 0 );
00640         int pos = 0;
00641 
00642         paths[ pos++ ] = st_DataDir + "/screenshot";
00643 
00644         if ( st_UserDataDir.Len() > 1 )
00645             paths[ pos++ ] = st_UserDataDir + "/screenshot";
00646 
00647         if ( st_ScreenshotDir.Len() > 1 )
00648             paths[ pos++ ] = st_ScreenshotDir;
00649     }
00650 };
00651 
00652 static const tPathScreenshot st_Screenshot;
00653 
00654 
00655 tString tPathResource::GetWritePath(const char *filename) const {
00656     if ( !tPath::IsValidPath( filename ) )
00657         return tString();
00658 
00659     tArray< tString > paths;
00660     Paths( paths );
00661 
00662     tString fullname;
00663     fullname << paths(0) << "/" << filename;
00664 
00665     {
00666         bool s;
00667 
00668         char *fpmr = strdup( static_cast< char const * >( fullname ) );
00669         s = mkdir_recurse(fpmr, paths(0).Len());
00670         free(fpmr);
00671 
00672         if (!s)
00673         {
00674             tERR_WARN( tOutput( "$directory_path_nonwritable",  fullname  ) );
00675             return tString();
00676         }
00677     }
00678 
00679     return fullname;
00680 }
00681 
00682 tString tPathResource::GetDirPath()
00683 {
00684     if ( st_IncludedResourceDir.Len() > 2 )
00685         return st_IncludedResourceDir;
00686     else
00687         return st_DataDir + "/resource/included";
00688 }
00689 
00690 void tPathResource::Paths(tArray< tString >& paths) const {
00691     paths.SetLen( 0 );
00692     int pos = 0;
00693 
00694     if ( st_AutoResourceDir.Len() > 1 )
00695         paths[ pos++ ] = st_AutoResourceDir;
00696     else if ( st_ResourceDir.Len() > 1 )
00697         paths[ pos++ ] = st_ResourceDir + "/automatic";
00698     else if ( st_UserDataDir.Len() > 1 )
00699         paths[ pos++ ] = st_UserDataDir + "/resource/automatic";
00700     else
00701         paths[ pos++ ] = st_DataDir + "/resource/automatic";
00702 
00703     paths[ pos++ ] = st_DataDir + "/resource/included";
00704     if ( st_IncludedResourceDir.Len() > 1 )
00705         paths[ pos++ ] = st_IncludedResourceDir;
00706 
00707     paths[ pos++ ] = st_DataDir + "/resource";
00708     if ( st_UserDataDir.Len() > 1 )
00709         paths[ pos++ ] = st_UserDataDir + "/resource";
00710     if ( st_ResourceDir.Len() > 1 )
00711         paths[ pos++ ] = st_ResourceDir;
00712 }
00713 
00714 
00715 static const tPathResource st_Resource;
00716 
00717 tString tPathScripts::GetDirPath()
00718 {
00719     return st_DataDir + "/scripts";
00720 }
00721 
00722 void tPathScripts::Paths(tArray< tString >& paths) const {
00723     paths.SetLen(0);
00724     paths[0] = GetDirPath();
00725 }
00726 
00727 static const tPathScripts st_Scripts;
00728 
00729 bool tPath::Open    ( std::ifstream& f,
00730                       const char* filename   ) const
00731 {
00732     if ( !tPath::IsValidPath( filename ) )
00733         return false;
00734 
00735     tArray< tString > paths;
00736     Paths( paths );
00737 
00738     for ( int prio = paths.Len() - 1; prio>=0; --prio )
00739     {
00740         //  std::ifstream test;
00741 
00742         tString fullname;
00743         fullname << paths( prio ) << "/" << filename;
00744 
00745 #ifdef PRINTSEARCH
00746 #endif
00747 
00748         //  test.open( fullname );
00749         f.clear();
00750         f.open( fullname );
00751 
00752         //  if ( test )
00753         if ( f && f.good() )
00754         {
00755 #ifdef PRINTSEARCH
00756             std::cout << "Trying to open " << fullname << " succeeded.";
00757 #endif
00758             //   f.open( fullname );
00759 
00760             //   return f;
00761             return true;
00762         }
00763 
00764 #ifdef PRINTSEARCH
00765         std::cout << "Trying to open " << fullname << " succeeded.";
00766 #endif
00767     }
00768 
00769     return false;
00770 }
00771 
00772 static bool st_protectFiles = true;
00773 tSettingItem<bool> st_protectFilesConf("PROTECT_SENSITIVE_FILES", st_protectFiles);
00774 
00775 bool tPath::Open    ( std::ofstream& f,
00776                       const char* filename,
00777                       std::ios::openmode mode,
00778                       bool sensitive) const
00779 {
00780     if ( !tPath::IsValidPath( filename ) )
00781         return false;
00782 
00783     // tArray< tString > paths;
00784     // Paths( paths );
00785 
00786     tString fullname = GetWritePath(filename);
00787 
00788 #ifndef WIN32
00789     mode_t oldmask=0;
00790     if(sensitive && st_protectFiles)
00791     {
00792         oldmask = umask(0600);
00793     }
00794 #endif
00795     f.open( fullname, mode );
00796 #ifndef WIN32
00797     if(sensitive && st_protectFiles)
00798     {
00799         chmod( &fullname(0), 0600 );
00800         umask(oldmask);
00801     }
00802 #endif
00803 
00804     return ( f && f.good() );
00805 }
00806 
00807 bool tPath::Open(std::fstream& f, const char* filename) const
00808 {
00809     //  std::cout << "open\n";
00810 
00811     tString fullname = GetWritePath(filename);
00812     f.open(fullname, std::ios::in | std::ios::out);
00813 
00814     return ( f.good() );
00815 }
00816 
00817 tString tPath::GetReadPath   ( const char* filename   ) const
00818 {
00819     if ( !tPath::IsValidPath( filename ) )
00820         return tString();
00821 
00822     tArray< tString > paths;
00823     Paths( paths );
00824 
00825     for ( int prio = paths.Len() - 1; prio>=0; --prio )
00826     {
00827         tString fullname;
00828         fullname << paths( prio ) << "/" << filename;
00829         std::ifstream f;
00830 
00831         //if (fullname != "./moviepack/sky.png")
00832 #ifdef PRINTSEARCH
00833         printf("Searching %s...", (const char *)fullname);
00834 #endif
00835         f.open( fullname );
00836 
00837         if ( f && f.good() )
00838         {
00839             //if (fullname != "./moviepack/sky.png")
00840 #ifdef PRINTSEARCH
00841             printf("OK\n");
00842 #endif
00843             return fullname;
00844         }
00845         //if (fullname != "./moviepack/sky.png")
00846 #ifdef PRINTSEARCH
00847         printf("nope\n");
00848 #endif
00849     }
00850 
00851     return tString();
00852 }
00853 
00854 tString tPath::GetWritePath  ( const char* filename   ) const
00855 {
00856     if ( !tPath::IsValidPath( filename ) )
00857         return tString();
00858 
00859     tArray< tString > paths;
00860     Paths( paths );
00861 
00862     tString fullname;
00863     fullname << paths( paths.Len() -1 ) << "/" << filename;
00864 
00865     {
00866         bool s;
00867 
00868         char *fpmr = strdup( static_cast< char const * > ( fullname ) );
00869         s = mkdir_recurse(fpmr, paths( paths.Len() -1 ).Len());
00870         free(fpmr);
00871 
00872         if (!s)
00873         {
00874             tERR_WARN( "Could not create path to " << fullname << ". Check your user's rights." );
00875             return tString();
00876         }
00877     }
00878 
00879     return fullname;
00880 }
00881 
00882 const tPath& tDirectories::Data()
00883 {
00884     return st_Data;
00885 }
00886 
00887 const tPath& tDirectories::Music()
00888 {
00889     return st_Music;
00890 }
00891 
00892 const tPath& tDirectories::Config()
00893 {
00894     return st_Config;
00895 }
00896 
00897 const tPath& tDirectories::Scripts()
00898 {
00899     return st_Scripts;
00900 }
00901 
00902 const tPath& tDirectories::Var()
00903 {
00904     return st_Var;
00905 }
00906 
00907 const tPath& tDirectories::Screenshot()
00908 {
00909     return st_Screenshot;
00910 }
00911 
00912 const tPathResource& tDirectories::Resource()
00913 {
00914     return st_Resource;
00915 }
00916 
00917 // set location of data directory
00918 void tDirectories::SetData( const tString& dir )
00919 {
00920     st_DataDir = dir;
00921 }
00922 
00923 // set location of user data directory
00924 void tDirectories::SetUserData( const tString& dir )
00925 {
00926     st_UserDataDir = dir;
00927 }
00928 
00929 // set location of config directory
00930 void tDirectories::SetConfig( const tString& dir )
00931 {
00932     st_ConfigDir = dir;
00933 }
00934 
00935 // set location of user config directory
00936 void tDirectories::SetUserConfig( const tString& dir )
00937 {
00938     st_UserConfigDir = dir;
00939 }
00940 
00941 // set location of var directory
00942 void tDirectories::SetVar( const tString& dir )
00943 {
00944     st_VarDir = dir;
00945 }
00946 
00947 // set location of screenshot directory
00948 void tDirectories::SetScreenshot( const tString& dir ) {
00949     st_ScreenshotDir = dir;
00950 }
00951 
00952 void tDirectories::SetResource( const tString& dir ) {
00953     st_ResourceDir = dir;
00954 }
00955 
00956 void tDirectories::SetAutoResource( const tString& dir ) {
00957     st_AutoResourceDir = dir;
00958 }
00959 
00960 void tDirectories::SetIncludedResource( const tString& dir ) {
00961     st_IncludedResourceDir = dir;
00962 }
00963 
00964 /*
00965  * robust glob pattern matcher
00966  * ozan s. yigit/dec 1994
00967  * public domain
00968  * http://www.cs.yorku.ca/~oz/glob.bun
00969  *
00970  * glob patterns:
00971  * * matches zero or more characters
00972  * ? matches any single character
00973  *
00974  * char matches itself except where char is '*' or '?' or '['
00975  * \char matches char, including any pattern character
00976  *
00977  * examples:
00978  * a*c  ac abc abbc ...
00979  * a?c  acc abc aXc ...
00980  *
00981  * Revision 1.5  2004/08/24  12:24:23  k
00982  * added case sensitive/insensitive option
00983  *
00984  * Revision 1.4  2004/08/17  12:24:23  k
00985  * removed [a-z] checking to match Windows wildcard parsing
00986  */
00987 // check if a file name matches a wildcard (* and ? are valid wild cards)
00988 bool tDirectories::FileMatchesWildcard(const char *str, const char *pattern,
00989                                        bool ignoreCase /* = true */)
00990 {
00991     int c;
00992 
00993     while (*pattern)
00994     {
00995         if (!*str && *pattern != '*')
00996             return false;
00997 
00998         switch (c = *pattern++)
00999         {
01000 
01001         case '*':
01002             while (*pattern == '*')
01003                 pattern++;
01004 
01005             if (!*pattern)
01006                 return true;
01007 
01008             if (*pattern != '?' && *pattern != '\\')
01009             {
01010                 if (ignoreCase)
01011                 {
01012                     while (*str && tolower(*pattern) != tolower(*str) )
01013                         str++;
01014                 }
01015                 else
01016                 {
01017                     while (*str && *pattern != *str )
01018                         str++;
01019                 }
01020             }
01021 
01022             while (*str)
01023             {
01024                 if (FileMatchesWildcard(str, pattern, ignoreCase))
01025                     return true;
01026                 str++;
01027             }
01028             return false;
01029 
01030         case '?':
01031             if (*str)
01032                 break;
01033             return false;
01034 
01035         case '\\':
01036             if (*pattern)
01037                 c = *pattern++;
01038 
01039         default:
01040             if (ignoreCase)
01041             {
01042                 if (tolower(c) != tolower(*str))
01043                     return false;
01044             }
01045             else
01046             {
01047                 if (c != *str)
01048                     return false;
01049             }
01050             break;
01051 
01052         }
01053         str++;
01054     }
01055 
01056     return !*str;
01057 }
01058 
01059 // get a list of files for a directory
01060 // flag: 0=files+dirs, 1=files, 2=dirs
01061 void tDirectories::GetFiles( const tString& dir, const tString& fileSpec,
01062                              tArray< tString >& files, int flag /* = eGetFilesAllFiles */ )
01063 {
01064     tArray<tString> specList;
01065     long pos = 0;
01066     struct stat statbuf;
01067     tString temp;
01068     bool bDir = false;
01069 
01070     files.SetLen( 0 );
01071 
01072     // Check for multiple file specs
01073     GetSpecList( fileSpec, specList );
01074 
01075     DIR *dirp;
01076     struct dirent *entry;
01077 
01078     dirp = opendir( dir );
01079 
01080     if ( dirp != NULL )
01081     {
01082         while ( ( entry = readdir( dirp ) ) != NULL )
01083         {
01084             // Ignore "." and ".." entries
01085             if ( entry->d_name[0] != '.' )
01086             {
01087                 // Build path.  Make sure dir ends with a '/' or '\'.
01088                 temp = dir;
01089                 if ( ( dir.Len() > 1 ) && ( dir[ dir.Len() - 2 ] != '/' && dir[ dir.Len() - 2 ] != '\\' ) )
01090                 {
01091                     temp += "/";
01092                 }
01093                 temp += entry->d_name;
01094 
01095                 // Is the entry a directory?
01096                 bDir = false;
01097                 if ( stat( temp, &statbuf ) == 0 )
01098                 {
01099                     if( statbuf.st_mode & S_IFDIR )
01100                     {
01101                         bDir = true;
01102                         // Don't add directories when flag = 1
01103                         if ( flag == eGetFilesFilesOnly )
01104                             continue;
01105                     }
01106                     else
01107                     {
01108                         // Don't add files when flag = 2
01109                         if ( flag == eGetFilesDirsOnly )
01110                             continue;
01111                     }
01112                 }
01113 
01114                 // If the entry matches a file spec add it to the list
01115                 for ( int i = 0; i < specList.Len(); i++ )
01116                 {
01117                     if ( FileMatchesWildcard( entry->d_name, specList( i ), true ) )
01118                     {
01119                         files[ pos ] = entry->d_name;
01120                         if ( bDir )
01121                             files[ pos ] += "/";
01122                         pos++;
01123                         break;
01124                     }
01125                 }
01126             }
01127         }
01128 
01129         closedir( dirp );
01130     }
01131 
01132     // Sort the list of files
01133     SortFiles( files );
01134 }
01135 
01136 // Convert a file name to a menu name (strip extension, replace '_' with ' ')
01137 tString& tDirectories::FileNameToMenuName(const char* fileName, tString& menuName)
01138 {
01139     char szBuf[256];
01140     int i = 0;
01141 
01142     // copy string to buffer for manipulation
01143     memset( szBuf, 0, sizeof( szBuf ) );
01144     strncpy( szBuf, fileName, sizeof( szBuf ) - 1 );
01145 
01146     // skip translation strings
01147     if ( szBuf[0] != '$' )
01148     {
01149         // strip extension
01150         for ( i = strlen(szBuf); i >= 0; i-- )
01151         {
01152             if ( szBuf[i] == '.' )
01153             {
01154                 szBuf[i] = '\0';
01155             }
01156         }
01157 
01158         // replace underscores with spaces
01159         for ( i = 0; (unsigned)i < strlen(szBuf); i++ )
01160         {
01161             if ( szBuf[i] == '_' )
01162             {
01163                 szBuf[i] = ' ';
01164             }
01165         }
01166     }
01167 
01168     menuName = szBuf;
01169 
01170     return menuName;
01171 }
01172 
01173 // split the file spec into a list
01174 void tDirectories::GetSpecList( const tString& fileSpec, tArray< tString >& specList )
01175 {
01176     char szBuf[256];
01177     char szSep[] = ";";
01178     char *token = NULL;
01179     long pos = 0;
01180 
01181     specList.SetLen( 0 );
01182 
01183     // Check for multiple file specs
01184     memset( szBuf, 0, sizeof( szBuf ) );
01185     strncpy( szBuf, (const char *) fileSpec, sizeof( szBuf ) - 1 );
01186     token = strtok( szBuf, szSep );
01187     while( token != NULL )
01188     {
01189         specList[ pos++ ] = token;
01190         token = strtok( NULL, szSep );
01191     }
01192 }
01193 
01194 // Helper function to see if tString s1 is less than s2 ignoring case
01195 static bool tStringLessThan(const tString &s1, const tString &s2)
01196 {
01197     for (int i = 0; i < s1.Len() - 1; i++)
01198     {
01199         if ( tolower( s2( i ) ) >= tolower( s1( i ) ) )
01200         {
01201             return false;
01202         }
01203     }
01204     return true;
01205 }
01206 
01207 // Sort the list of files
01208 void tDirectories::SortFiles( tArray< tString >& files )
01209 {
01210     tString temp;
01211     long pos = 0;
01212 
01213     // bubble sort for now
01214     for ( pos = 0; pos < files.Len() - 1; pos ++ )
01215     {
01216         for ( long pos2 = pos + 1; pos2 < files.Len(); pos2++ )
01217         {
01218             //if ( strcmp( (const char *) files( pos2 ), (const char *) files( pos ) ) < 0 )
01219             if ( tStringLessThan( files( pos2 ), files( pos ) ) )
01220             {
01221                 temp = files( pos );
01222                 files( pos ) = files( pos2 );
01223                 files( pos2 ) = temp;
01224             }
01225         }
01226     }
01227 }
01228 
01229 /*
01230 static void quitWithMessage( const char* message )
01231 {
01232 #ifdef WIN32
01233 #ifndef DEDICATED
01234 #define USEBOX
01235 #endif
01236 #endif
01237 
01238 #ifdef USEBOX
01239     int result = MessageBox (NULL, message , "Message", MB_OK);
01240 #else
01241     std::cout << message;
01242 #endif
01243 
01244     tLocale::Clear();
01245 }
01246 */
01247 
01248 //#define QUIT(x) { std::ostringstream s; s << x; quitWithMessage(s.str().c_str()); name_.Clear(); } exit(0)
01249 #define QUIT(x) { std::ostringstream s; s << x; quitWithMessage(s.str().c_str()); name_.Clear(); } return false
01250 
01251 /*
01252 // reads a command line option
01253 bool ReadOption( int& i, int argc, char **argv, const char* argument, tString& target )
01254 {
01255     if ( !strcmp(argv[i],argument ) )
01256     {
01257         if ( i < argc - 1 )
01258         {
01259             i++;
01260             target = argv[i];
01261 
01262             return true;
01263         }
01264         else
01265         {
01266             tString name_;
01267             QUIT( "\n\n" << argument << " needs another argument.\n\n" );
01268         }
01269     }
01270 
01271     return false;
01272 }
01273 */
01274 
01275 void ReplacePath( tString & path, char const * replacement )
01276 {
01277     // don't do a thing if the path is already set
01278     if ( path.Len() < 3 )
01279     {
01280         path = replacement;
01281     }
01282 }
01283 
01284 // tests whether <file> can be found in path <path>
01285 bool TestPath( char const * path, char const * file )
01286 {
01287     std::string testData( path );
01288     testData += "/";
01289     testData += file;
01290     std::ifstream f(testData.c_str());
01291 
01292 
01293 #ifdef DEBUG_PATH
01294     con << "Testing existence of file " << testData << ( f.good() ? " : good.\n" : " : bad!\n" );
01295 #endif
01296 
01297     return ( f.good() );
01298 }
01299 
01300 // tests whether the given path is a valid configuration path
01301 bool TestConfigurationPath( char const * path )
01302 {
01303     if ( TestPath( path, "settings.cfg" ) )
01304     {
01305 #ifdef DEBUG_PATH
01306         con << "Configuration path " << path << " is good.\n";
01307 #endif
01308         // replace data paths
01309         ReplacePath( st_ConfigDir, path );
01310 
01311         return true;
01312     }
01313 
01314 #ifdef DEBUG_PATH
01315     con << "Configuration path " << path << " is bad!\n";
01316 #endif
01317 
01318     return false;
01319 }
01320 
01321 // tests whether the given path is a valid data path
01322 bool TestDataPath( char const * path )
01323 {
01324     if ( TestPath( path, "language/english_base.txt") )
01325     {
01326 #ifdef DEBUG_PATH
01327         con << "Data path " << path << " is good.\n";
01328 #endif
01329         // replace data paths
01330         ReplacePath( st_DataDir, path );
01331 
01332         return true;
01333     }
01334 
01335 #ifdef DEBUG_PATH
01336     con << "Data path " << path << " is bad!\n";
01337 #endif
01338 
01339     return false;
01340 }
01341 
01342 // generates parent directories of the passed path
01343 static tString GetParent( char const * child, int levels )
01344 {
01345     tString ret( child );
01346 
01347     // strip last two path segments
01348     int toStrip = levels;
01349     int stripCurrent = ret.Size()-1;
01350     while (stripCurrent >= 0 && toStrip > 0)
01351     {
01352         char & c = ret[ stripCurrent ];
01353         // count separators
01354         if (c == '/' || c == '\\' || c == ':')
01355             --toStrip;
01356         c=0;
01357         --stripCurrent;
01358     }
01359 
01360 #ifdef DEBUG_PATH
01361     std::cout << "Parent: " << ret << "\n";
01362 #endif
01363 
01364     return tString(static_cast<char const *>(ret));
01365 }
01366 
01368 class tPathToExecutable
01369 {
01370 public:
01372     void Set( char const * defaultPath )
01373     {
01374 #ifndef WIN32
01375 #ifdef ENABLE_BINRELOC
01376         // get path of executable
01377         char const * bestGuess = SELFPATH;
01378 #else // binreloc
01379         char const * bestGuess = BINDIR "/" PROGNAME;
01380 #endif// binreloc
01381 #else // win32
01382         char const * bestGuess = "./" PROGNAME;
01383 #endif// win32
01384 
01385 #ifndef ENABLE_BINRELOC
01386         // if the passed default path is a real path, let it override the best guess
01387         if ( strstr( defaultPath, "/" ) || strstr( defaultPath, "\\" ) )
01388             bestGuess = defaultPath;
01389         //            bestGuess = "./armagetronad-dedicated";
01390 #endif
01391 
01392         path_ = bestGuess;
01393 
01394 #ifdef DEBUG_PATH
01395         con << "path to executable: " << path_ << "\n";
01396 #endif
01397     }
01398 
01399     // returns the best bet
01400     char const * Get() const
01401     {
01402         tASSERT( path_.Len() > 2 );
01403         return path_;
01404     }
01405 private:
01406     tString path_;
01407 };
01408 
01409 static tPathToExecutable st_pathToExecutable;
01410 
01411 static tString GenerateParentOfExecutable( int levels = 2 )
01412 {
01413     return GetParent( st_pathToExecutable.Get(), levels );
01414 }
01415 
01416 // exception to throw if the game is running from the build directory
01417 struct tRunningInBuildDirectory
01418 {
01419 };
01420 
01421 // generates real prefix from executable position and compiled in prefix and
01422 // binary path
01423 static tString GeneratePrefix()
01424 {
01425     // fetch prefix as it was compiled in
01426     tString const & prefixCompiled = st_prefixCompiled;
01427     // the binary path as it was compiled in
01428     tString const & bindirCompiled = st_bindirCompiled;
01429     // and the current binary path
01430     tString bindirNow(GenerateParentOfExecutable(1));
01431 
01432     // the length of the bindir suffix, the part that is added below prefix
01433     int bindirSuffixLength=bindirCompiled.Len() - prefixCompiled.Len();
01434 
01435     // the end of the prefix part in binDirNow according to that
01436     int bindirNowPrefixEnd=bindirNow.Len() - 1 - bindirSuffixLength;
01437     if ( bindirNowPrefixEnd < 0 )
01438         bindirNowPrefixEnd = 0;
01439 
01440     // check that the binary path now ends the same way
01441     tString suffixNow      = bindirNow.SubStr( bindirNowPrefixEnd + 1 );
01442     tString suffixCompiled = bindirCompiled.SubStr( prefixCompiled.Len() );
01443 
01444 #ifdef DEBUG_PATH
01445     con << "suffices: " << suffixNow << ", " << suffixCompiled << "\n";
01446 #endif
01447 
01448     if ( suffixNow != suffixCompiled )
01449     {
01450         // may we be running inside the build directory?
01451         int bindirEndStart = bindirNow.Len() - 5;
01452         if ( bindirEndStart < 0 )
01453             bindirEndStart = 0;
01454 
01455         tString bindirEnd = bindirNow.SubStr( bindirEndStart );
01456 
01457 #ifdef DEBUG_PATH
01458         con << "bindirEnd: " << bindirEnd << "\n";
01459 #endif
01460 
01461         if ( TestPath( bindirNow, "Makefile" ) )
01462             throw tRunningInBuildDirectory();
01463 
01464         tERR_ERROR("Relocation error. The binary was supposed to be installed into " << bindirCompiled << " and found itself in " << bindirNow << " and could not find out what this means for the prefix " << prefixCompiled << "." );
01465     }
01466 
01467     // generate prefix
01468     tString prefixNow = bindirNow.SubStr( 0, bindirNowPrefixEnd );
01469 
01470 #ifdef DEBUG_PATH
01471     con << "prefix: " << prefixNow << "\n";
01472 #endif
01473 
01474     return prefixNow;
01475 }
01476 
01477 // returns the complete prefix the game was installed in (defaults to /usr/local)
01478 static char const * GetPrefix()
01479 {
01480     static tString ret( GeneratePrefix() );
01481     return ret;
01482 }
01483 
01484 /*
01485 // appends the given suffix to the prefix and returns the result
01486 static tString AddPrefix( const char * suffix )
01487 {
01488     tString ret(GetPrefix());
01489     ret += suffix;
01490 
01491     return ret;
01492 }
01493 */
01494 
01495 #ifndef WIN32
01496 static tString st_RelocatePath( tString const & original )
01497 {
01498     // fetch prefix as it was compiled in
01499     tString const & prefixCompiled = st_prefixCompiled;
01500     // and as it is now
01501     static tString prefixNow(GetPrefix());
01502 
01503     // see if the passed string starts with it
01504     if ( original.StartsWith( prefixCompiled ) )
01505     {
01506         // replace the prefix with the real prefix and return the result
01507         return prefixNow + original.SubStr( prefixCompiled.Len()-1 );
01508     }
01509     else
01510     {
01511         // don't relocate and hope it works
01512         return original;
01513     }
01514 }
01515 #endif
01516 
01517 // tries to find the path to the data files, given the location of the executable
01518 static void FindDataPath()
01519 {
01520 #ifndef MACOSX_XCODE
01521 #ifdef WIN32
01522     // look for data in the same directory as the executable
01523     if ( TestDataPath(GetParent(st_pathToExecutable.Get(), 1) ) ) return;
01524 #else
01525     // try to use path substitution
01526     if ( TestDataPath( st_RelocatePath( tString(AA_DATADIR ) ) ) ) return;
01527     // if ( TestDataPath( AddPrefix( DATASUFFIX ) ) ) return;
01528 #endif
01529 
01530 #ifdef DEBUG_PATH
01531     con << "Data sarch failed, trying debug fallback.\n";
01532 #endif
01533 
01534 #ifdef DEBUG_PATH
01535     tERR_MESSAGE("Could not determine path to data files. Using defaults or command line arguments.\n");
01536 #endif
01537 #endif // !MACOSX_XCODE
01538 }
01539 
01540 // tries to find the path to the configuration files, given the location of the executable
01541 static void FindConfigurationPath()
01542 {
01543 #ifndef MACOSX_XCODE
01544 #ifndef WIN32
01545     if ( TestConfigurationPath( st_RelocatePath( tString( AA_SYSCONFDIR ) ) ) ) return;
01546 #endif
01547 
01548     // look for configuration where the data is
01549     if ( TestConfigurationPath(st_DataDir + "/config") ) return;
01550 
01551     tERR_WARN("Could not determine path to configuration files. Using defaults or command line arguments.\n");
01552 #endif // !MACOSX_XCODE
01553 }
01554 
01555 // tries to read a direcory type argument from the command line parser; result is written
01556 // into target, argument is the required switch ("--userdatadir")
01557 static bool ReadDir( tCommandLineParser & parser, tString & target, const char* argument )
01558 {
01559     if ( parser.GetOption( target, argument ) )
01560     {
01561         target = expand_home_c( target );
01562 
01563         return true;
01564     }
01565 
01566     return false;
01567 }
01568 
01569 class tDirectoriesCommandLineAnalyzer: public tCommandLineAnalyzer
01570 {
01571 private:
01572     virtual void DoInitialize( tCommandLineParser & parser )
01573     {
01574         // Puts the data files in the executable's bundle
01575 #ifndef MACOSX_XCODE
01576         try
01577         {
01578             st_pathToExecutable.Set( parser.Executable() );
01579             FindDataPath();
01580             FindConfigurationPath();
01581         }
01582         catch( tRunningInBuildDirectory )
01583         {
01584             // last fallback for debugging (activated only if there is data in the current directory)
01585             if ( TestPath( ".", "language/languages.txt") && TestDataPath(s_topSourceDir) && TestConfigurationPath(st_DataDir + "/config") )
01586             {
01587                 // we must be running the game in debug mode; set user data dir to current directory.
01588                 st_UserDataDir = ".";
01589 
01590                 // the included resources are scrambled and put into the current directory as well.
01591                 st_IncludedResourceDir = "./resource/included";
01592                 return;
01593             }
01594         }
01595 #endif // !MACOSX_XCODE
01596 
01597 
01598     }
01599 
01600     virtual bool DoAnalyze( tCommandLineParser & parser )
01601     {
01602         if( ReadDir( parser, st_DataDir, "--datadir" ) ) return true;
01603         if( ReadDir( parser, st_UserDataDir, "--userdatadir" ) ) return true;
01604         if( ReadDir( parser, st_ConfigDir, "--configdir" ) ) return true;
01605         if( ReadDir( parser, st_UserConfigDir, "--userconfigdir" ) ) return true;
01606         if( ReadDir( parser, st_VarDir, "--vardir" ) ) return true;
01607         if( ReadDir( parser, st_ResourceDir, "--resourcedir" ) ) return true;
01608         if( ReadDir( parser, st_AutoResourceDir, "--autoresourcedir" ) ) return true;
01609 
01610         if ( parser.GetSwitch( "--path-no-absolutecheck" ) )
01611         {
01612             st_checkPathAbsolute = false;
01613             return true;
01614         }
01615 
01616         if ( parser.GetSwitch( "--path-no-relativecheck" ) )
01617         {
01618             st_checkPathRelative = false;
01619             return true;
01620         }
01621 
01622         if ( parser.GetSwitch( "--path-no-hiddencheck" ) )
01623         {
01624             st_checkPathHidden = false;
01625             return true;
01626         }
01627 
01628         if ( parser.GetSwitch( "--prefix" ) )
01629         {
01630             std::cout << GetPrefix() << '\n';
01631             throw 1;
01632             return true;
01633         }
01634 
01635         return false;
01636     }
01637 
01638     virtual void DoHelp( std::ostream & s )
01639     {                                      //
01640         s << "--datadir <Directory>        : read game data (textures, sounds and texts)\n"
01641         <<   "                               from this directory\n";
01642         s << "--userdatadir <Directory>    : read customized game data from this directory\n";
01643         s << "--configdir <Directory>      : read game configuration (.cfg-files)\n"
01644         <<   "                               from this directory\n";
01645         s << "--userconfigdir <Directory>  : read user game configuration from this directory\n";
01646         s << "--vardir <Directory>         : save game logs and highscores in this directory\n\n";
01647         s << "--resourcedir <Directory>    : look for resources in this directory\n\n";
01648         s << "--autoresourcedir <Directory>: download missing resources into this directory\n\n";
01649         s << "--path-no-absolutecheck      : disables security check against absolute paths\n";
01650         s << "--path-no-hiddencheck        : disables security check against hidden paths\n";
01651         s << "--path-no-relativecheck      : disables security check against relative paths.\n"
01652         <<   "                               Not recommended, this check is really important.\n\n";
01653         s << "--prefix                     : prints the prefix the game was installed to\n";
01654     }
01655 };
01656 
01657 static tDirectoriesCommandLineAnalyzer analyzer;
01658 
01659 tString tPath::GetPaths(void) const {
01660     tString ret;
01661     tArray<tString> paths;
01662     Paths(paths);
01663     for (int i = 0; i < paths.Len(); ++i) {
01664         if(i > 0 && paths[i - 1] == paths[i]) continue;
01665         ret << " - " << paths[i] << "\n";
01666     }
01667     return ret;
01668 }
01669 
01670 extern char *st_userConfigs[];
01671 void st_PrintPathInfo(tOutput &buf) {
01672     tString const hcol("0xff8888");
01673     buf << hcol << "$path_info_user_cfg"   << "0xRESETT\n   " << tDirectories::Var().GetReadPath("user.cfg") << "\n"
01674     << hcol << "$path_info_config"     << "0xRESETT\n" << tDirectories::Config().GetPaths()
01675     << hcol << "$path_info_resource"   << "0xRESETT\n" << tDirectories::Resource().GetPaths()
01676     << hcol << "$path_info_data"       << "0xRESETT\n" << tDirectories::Data().GetPaths()
01677     << hcol << "$path_info_screenshot" << "0xRESETT\n" << tDirectories::Screenshot().GetPaths()
01678     << hcol << "$path_info_var"        << "0xRESETT\n" << tDirectories::Var().GetPaths();
01679 }

Generated on Sat Mar 15 22:55:59 2008 for Armagetron Advanced by  doxygen 1.5.4