Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/libraries/core/ApplicationPaths.cc @ 11360

Last change on this file since 11360 was 11071, checked in by landauf, 9 years ago

merged branch cpp11_v3 back to trunk

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