Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: sandbox_light/src/libraries/core/PathConfig.cc @ 7121

Last change on this file since 7121 was 6040, checked in by rgrieder, 15 years ago

Also synchronised sandbox_light with current trunk.

  • Property svn:eol-style set to native
File size: 8.2 KB
RevLine 
[1505]1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
[2896]23 *      Reto Grieder
[1505]24 *   Co-authors:
[2896]25 *      ...
[1505]26 *
27 */
28
[5836]29#include "PathConfig.h"
[1505]30
[1756]31#include <cassert>
[2710]32#include <cstdlib>
33#include <cstdio>
[5836]34#include <vector>
[5693]35#include <boost/version.hpp>
[2710]36#include <boost/filesystem.hpp>
37
38#ifdef ORXONOX_PLATFORM_WINDOWS
[2896]39#  ifndef WIN32_LEAN_AND_MEAN
40#    define WIN32_LEAN_AND_MEAN
41#  endif
[2710]42#  include <windows.h>
[3214]43#  undef min
44#  undef max
[2710]45#elif defined(ORXONOX_PLATFORM_APPLE)
46#  include <sys/param.h>
47#  include <mach-o/dyld.h>
48#else /* Linux */
49#  include <sys/types.h>
50#  include <unistd.h>
51#endif
52
53#include "SpecialConfig.h"
[2896]54#include "util/Debug.h"
[2710]55#include "util/Exception.h"
[6021]56#include "CommandLineParser.h"
[1505]57
[5693]58// Boost 1.36 has some issues with deprecated functions that have been omitted
59#if (BOOST_VERSION == 103600)
60#  define BOOST_LEAF_FUNCTION filename
61#else
62#  define BOOST_LEAF_FUNCTION leaf
63#endif
64
[1505]65namespace orxonox
66{
[5836]67    namespace bf = boost::filesystem;
68
[3196]69    //! Static pointer to the singleton
[5836]70    PathConfig* PathConfig::singletonPtr_s  = 0;
[2662]71
[3280]72    SetCommandLineOnlyArgument(writingPathSuffix, "").information("Additional subfolder for config and log files");
[2710]73
[5836]74    PathConfig::PathConfig()
75        : rootPath_(*(new bf::path()))
76        , executablePath_(*(new bf::path()))
77        , dataPath_(*(new bf::path()))
78        , configPath_(*(new bf::path()))
79        , logPath_(*(new bf::path()))
[3370]80        , bDevRun_(false)
[3280]81    {
[5693]82        //////////////////////////
83        // FIND EXECUTABLE PATH //
84        //////////////////////////
85
[2710]86#ifdef ORXONOX_PLATFORM_WINDOWS
87        // get executable module
88        TCHAR buffer[1024];
89        if (GetModuleFileName(NULL, buffer, 1024) == 0)
90            ThrowException(General, "Could not retrieve executable path.");
91
92#elif defined(ORXONOX_PLATFORM_APPLE)
93        char buffer[1024];
94        unsigned long path_len = 1023;
95        if (_NSGetExecutablePath(buffer, &path_len))
96            ThrowException(General, "Could not retrieve executable path.");
97
98#else /* Linux */
99        /* written by Nicolai Haehnle <prefect_@gmx.net> */
100
101        /* Get our PID and build the name of the link in /proc */
102        char linkname[64]; /* /proc/<pid>/exe */
103        if (snprintf(linkname, sizeof(linkname), "/proc/%i/exe", getpid()) < 0)
104        {
105            /* This should only happen on large word systems. I'm not sure
106               what the proper response is here.
107               Since it really is an assert-like condition, aborting the
108               program seems to be in order. */
109            assert(false);
110        }
111
112        /* Now read the symbolic link */
113        char buffer[1024];
114        int ret;
115        ret = readlink(linkname, buffer, 1024);
116        /* In case of an error, leave the handling up to the caller */
117        if (ret == -1)
118            ThrowException(General, "Could not retrieve executable path.");
119
120        /* Ensure proper NUL termination */
121        buffer[ret] = 0;
122#endif
123
[5836]124        executablePath_ = bf::path(buffer);
[2710]125#ifndef ORXONOX_PLATFORM_APPLE
[5836]126        executablePath_ = executablePath_.branch_path(); // remove executable name
[2710]127#endif
128
[5693]129        /////////////////////
130        // SET MODULE PATH //
131        /////////////////////
132
[5836]133        if (bf::exists(executablePath_ / "orxonox_dev_build.keep_me"))
[2710]134        {
135            COUT(1) << "Running from the build tree." << std::endl;
[5836]136            PathConfig::bDevRun_ = true;
[2710]137        }
138        else
139        {
[5693]140
[2710]141#ifdef INSTALL_COPYABLE // --> relative paths
[5693]142
[2710]143            // Also set the root path
[5836]144            bf::path relativeExecutablePath(specialConfig::defaultRuntimePath);
145            rootPath_ = executablePath_;
146            while (!bf::equivalent(rootPath_ / relativeExecutablePath, executablePath_) && !rootPath_.empty())
147                rootPath_ = rootPath_.branch_path();
148            if (rootPath_.empty())
[2710]149                ThrowException(General, "Could not derive a root directory. Might the binary installation directory contain '..' when taken relative to the installation prefix path?");
150
[5693]151#else
152
153            // There is no root path, so don't set it at all
154
155#endif
156        }
157    }
158
[5836]159    PathConfig::~PathConfig()
[5693]160    {
[5836]161        delete &rootPath_;
162        delete &executablePath_;
163        delete &dataPath_;
164        delete &configPath_;
165        delete &logPath_;
166    }
167
168    void PathConfig::setConfigurablePaths()
169    {
170        if (bDevRun_)
[5693]171        {
[5836]172            dataPath_         = specialConfig::dataDevDirectory;
173            configPath_       = specialConfig::configDevDirectory;
174            logPath_          = specialConfig::logDevDirectory;
[5693]175        }
176        else
177        {
178
179#ifdef INSTALL_COPYABLE // --> relative paths
180
[2710]181            // Using paths relative to the install prefix, complete them
[5836]182            dataPath_   = rootPath_ / specialConfig::defaultDataPath;
183            configPath_ = rootPath_ / specialConfig::defaultConfigPath;
184            logPath_    = rootPath_ / specialConfig::defaultLogPath;
[5693]185
[2710]186#else
187
[5836]188            dataPath_  = specialConfig::dataInstallDirectory;
[2710]189
190            // Get user directory
191#  ifdef ORXONOX_PLATFORM_UNIX /* Apple? */
192            char* userDataPathPtr(getenv("HOME"));
193#  else
194            char* userDataPathPtr(getenv("APPDATA"));
195#  endif
196            if (userDataPathPtr == NULL)
197                ThrowException(General, "Could not retrieve user data path.");
[5836]198            bf::path userDataPath(userDataPathPtr);
[2710]199            userDataPath /= ".orxonox";
200
[5836]201            configPath_ = userDataPath / specialConfig::defaultConfigPath;
202            logPath_    = userDataPath / specialConfig::defaultLogPath;
[5693]203
[2710]204#endif
[5693]205
[2710]206        }
207
208        // Option to put all the config and log files in a separate folder
[6021]209        if (!CommandLineParser::getArgument("writingPathSuffix")->hasDefaultValue())
[2710]210        {
[6021]211            std::string directory(CommandLineParser::getValue("writingPathSuffix").getString());
[5836]212            configPath_ = configPath_ / directory;
213            logPath_    = logPath_    / directory;
[2710]214        }
215
[5693]216        // Create directories to avoid problems when opening files in non existent folders.
[5836]217        std::vector<std::pair<bf::path, std::string> > directories;
218        directories.push_back(std::make_pair(bf::path(configPath_), "config"));
219        directories.push_back(std::make_pair(bf::path(logPath_), "log"));
[2710]220
[5836]221        for (std::vector<std::pair<bf::path, std::string> >::iterator it = directories.begin();
[2710]222            it != directories.end(); ++it)
223        {
[5836]224            if (bf::exists(it->first) && !bf::is_directory(it->first))
[2710]225            {
226                ThrowException(General, std::string("The ") + it->second + " directory has been preoccupied by a file! \
[2759]227                                         Please remove " + it->first.string());
[2710]228            }
[5836]229            if (bf::create_directories(it->first)) // function may not return true at all (bug?)
[2710]230            {
231                COUT(4) << "Created " << it->second << " directory" << std::endl;
232            }
233        }
234    }
[2896]235
[5836]236    /*static*/ std::string PathConfig::getRootPathString()
[3370]237    {
[5836]238        return getInstance().rootPath_.string() + '/';
[3370]239    }
[5836]240
241    /*static*/ std::string PathConfig::getExecutablePathString()
242    {
243        return getInstance().executablePath_.string() + '/';
244    }
245
246    /*static*/ std::string PathConfig::getDataPathString()
247    {
248        return getInstance().dataPath_.string() + '/';
249    }
250
251    /*static*/ std::string PathConfig::getConfigPathString()
252    {
253        return getInstance().configPath_.string() + '/';
254    }
255
256    /*static*/ std::string PathConfig::getLogPathString()
257    {
258        return getInstance().logPath_.string() + '/';
259    }
[1505]260}
Note: See TracBrowser for help on using the repository browser.