Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/core7/src/libraries/core/ApplicationPaths.cc @ 10509

Last change on this file since 10509 was 10509, checked in by landauf, 10 years ago

moved static application paths (root, executable, modules) into new class named ApplicationPaths
moved configurable data paths (data, log, config) into new class named ConfigurablePaths
removed PathConfig

  • Property svn:eol-style set to native
File size: 6.8 KB
Line 
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:
23 *      Reto Grieder
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29#include "ApplicationPaths.h"
30
31#include <cassert>
32#include <cstdlib>
33#include <cstdio>
34#include <vector>
35#include <boost/filesystem.hpp>
36
37#ifdef ORXONOX_PLATFORM_WINDOWS
38#  ifndef WIN32_LEAN_AND_MEAN
39#    define WIN32_LEAN_AND_MEAN
40#  endif
41#  include <windows.h>
42#  undef min
43#  undef max
44#elif defined(ORXONOX_PLATFORM_APPLE)
45#  include <sys/param.h>
46#  include <mach-o/dyld.h>
47#else /* Linux */
48#  include <sys/types.h>
49#  include <unistd.h>
50#endif
51
52#include "SpecialConfig.h"
53#include "util/Output.h"
54#include "util/Exception.h"
55
56// Differentiate Boost Filesystem v2 and v3
57#if (BOOST_FILESYSTEM_VERSION < 3)
58#  define BF_LEAF leaf
59#  define BF_GENERIC_STRING string
60#else
61#  define BF_LEAF path().filename().string
62#  define BF_GENERIC_STRING generic_string
63#endif
64
65namespace orxonox
66{
67    namespace bf = boost::filesystem;
68
69    //! Static pointer to the singleton
70    ApplicationPaths* ApplicationPaths::singletonPtr_s  = 0;
71
72    ApplicationPaths::ApplicationPaths()
73        : rootPath_(*(new bf::path()))
74        , executablePath_(*(new bf::path()))
75        , modulePath_(*(new bf::path()))
76        , bBuildDirectoryRun_(false)
77    {
78        //////////////////////////
79        // FIND EXECUTABLE PATH //
80        //////////////////////////
81
82#ifdef ORXONOX_PLATFORM_WINDOWS
83        // get executable module
84        TCHAR buffer[1024];
85        if (GetModuleFileName(NULL, buffer, 1024) == 0)
86            ThrowException(General, "Could not retrieve executable path.");
87
88#elif defined(ORXONOX_PLATFORM_APPLE)
89        char buffer[1024];
90        uint32_t path_len = 1023;
91        if (_NSGetExecutablePath(buffer, &path_len))
92            ThrowException(General, "Could not retrieve executable path.");
93
94#else /* Linux */
95        /* written by Nicolai Haehnle <prefect_@gmx.net> */
96
97        /* Get our PID and build the name of the link in /proc */
98        char linkname[64]; /* /proc/<pid>/exe */
99        if (snprintf(linkname, sizeof(linkname), "/proc/%i/exe", getpid()) < 0)
100        {
101            /* This should only happen on large word systems. I'm not sure
102               what the proper response is here.
103               Since it really is an assert-like condition, aborting the
104               program seems to be in order. */
105            assert(false);
106        }
107
108        /* Now read the symbolic link */
109        char buffer[1024];
110        int ret;
111        ret = readlink(linkname, buffer, 1024);
112        /* In case of an error, leave the handling up to the caller */
113        if (ret == -1)
114            ThrowException(General, "Could not retrieve executable path.");
115
116        /* Ensure proper NUL termination */
117        buffer[ret] = 0;
118#endif
119
120        // Remove executable filename
121        executablePath_ = bf::path(buffer).branch_path();
122
123        /////////////////////
124        // SET MODULE PATH //
125        /////////////////////
126
127        if (bf::exists(executablePath_ / "orxonox_dev_build.keep_me"))
128        {
129            orxout(internal_info) << "Running from the build tree." << endl;
130            ApplicationPaths::bBuildDirectoryRun_ = true;
131            modulePath_ = specialConfig::moduleDevDirectory;
132        }
133        else
134        {
135
136#ifdef INSTALL_COPYABLE // --> relative paths
137
138            // Also set the root path
139            bf::path relativeExecutablePath(specialConfig::defaultRuntimePath);
140            rootPath_ = executablePath_;
141            while (!bf::equivalent(rootPath_ / relativeExecutablePath, executablePath_) && !rootPath_.empty())
142                rootPath_ = rootPath_.branch_path();
143            if (rootPath_.empty())
144                ThrowException(General, "Could not derive a root directory. Might the binary installation directory contain '..' when taken relative to the installation prefix path?");
145
146            // Module path is fixed as well
147            modulePath_ = rootPath_ / specialConfig::defaultModulePath;
148
149#else
150
151            // There is no root path, so don't set it at all
152            // Module path is fixed as well
153            modulePath_ = specialConfig::moduleInstallDirectory;
154
155#endif
156        }
157    }
158
159    ApplicationPaths::~ApplicationPaths()
160    {
161        delete &rootPath_;
162        delete &executablePath_;
163        delete &modulePath_;
164    }
165
166    std::vector<std::string> ApplicationPaths::getModulePaths()
167    {
168        std::vector<std::string> modulePaths;
169
170        // We search for helper files with the following extension
171        const std::string& moduleextension = specialConfig::moduleExtension;
172        size_t moduleextensionlength = moduleextension.size();
173
174        // Make sure the path exists, otherwise don't load modules
175        if (!boost::filesystem::exists(modulePath_))
176            return modulePaths;
177
178        boost::filesystem::directory_iterator file(modulePath_);
179        boost::filesystem::directory_iterator end;
180
181        // Iterate through all files
182        while (file != end)
183        {
184            std::string filename = file->BF_LEAF();
185
186            // Check if the file ends with the extension in question
187            if (filename.size() > moduleextensionlength)
188            {
189                if (filename.substr(filename.size() - moduleextensionlength) == moduleextension)
190                {
191                    // We've found a helper file
192                    const std::string& library = filename.substr(0, filename.size() - moduleextensionlength);
193                    modulePaths.push_back(getModulePathString() + library);
194                }
195            }
196            ++file;
197        }
198
199        return modulePaths;
200    }
201
202    /*static*/ std::string ApplicationPaths::getRootPathString()
203    {
204        return getInstance().rootPath_.BF_GENERIC_STRING() + '/';
205    }
206
207    /*static*/ std::string ApplicationPaths::getExecutablePathString()
208    {
209        return getInstance().executablePath_.BF_GENERIC_STRING() + '/';
210    }
211
212    /*static*/ std::string ApplicationPaths::getModulePathString()
213    {
214        return getInstance().modulePath_.BF_GENERIC_STRING() + '/';
215    }
216}
Note: See TracBrowser for help on using the repository browser.