LCOV - code coverage report
Current view: top level - source/ps/GameSetup - Paths.cpp (source / functions) Hit Total Coverage
Test: 0 A.D. test coverage report Lines: 1 45 2.2 %
Date: 2023-01-19 00:18:29 Functions: 2 6 33.3 %

          Line data    Source code
       1             : /* Copyright (C) 2012 Wildfire Games.
       2             :  * This file is part of 0 A.D.
       3             :  *
       4             :  * 0 A.D. is free software: you can redistribute it and/or modify
       5             :  * it under the terms of the GNU General Public License as published by
       6             :  * the Free Software Foundation, either version 2 of the License, or
       7             :  * (at your option) any later version.
       8             :  *
       9             :  * 0 A.D. is distributed in the hope that it will be useful,
      10             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12             :  * GNU General Public License for more details.
      13             :  *
      14             :  * You should have received a copy of the GNU General Public License
      15             :  * along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
      16             :  */
      17             : 
      18             : #include "precompiled.h"
      19             : #include "Paths.h"
      20             : 
      21             : #include "lib/file/file_system.h"
      22             : #include "lib/sysdep/sysdep.h"    // sys_get_executable_name
      23             : #include "lib/sysdep/filesystem.h"    // wrealpath
      24             : #if OS_WIN
      25             : # include "lib/sysdep/os/win/wutil.h" // wutil_*Path
      26             : #elif OS_MACOSX
      27             : # include "lib/sysdep/os/osx/osx_paths.h"
      28             : # include "lib/sysdep/os/osx/osx_bundle.h"
      29             : #endif
      30             : #include "ps/CLogger.h"
      31             : 
      32             : 
      33           0 : Paths::Paths(const CmdLineArgs& args)
      34             : {
      35           0 :     m_root = Root(args.GetArg0());
      36             : 
      37           0 :     m_rdata = RootData(args.GetArg0());
      38             : 
      39           0 :     const char* subdirectoryName = args.Has("writableRoot")? 0 : "0ad";
      40             : 
      41           0 :     if(!subdirectoryName)
      42             :     {
      43             :         // Note: if writableRoot option is passed to the game, then
      44             :         //  all the data is a subdirectory of the root
      45           0 :         m_gameData = m_rdata;
      46           0 :         m_userData = m_gameData;
      47           0 :         m_config = m_gameData / "config"/"";
      48           0 :         m_cache = m_gameData / "cache"/"";
      49           0 :         m_logs = m_root / "logs"/"";
      50             :     }
      51             :     else // OS-specific path handling
      52             :     {
      53             : 
      54             : #if OS_ANDROID
      55             : 
      56             :         const OsPath appdata = OsPath("/sdcard/0ad/appdata");
      57             : 
      58             :         // We don't make the game vs. user data distinction on Android
      59             :         m_gameData = appdata/"data"/"";
      60             :         m_userData = m_gameData;
      61             :         m_config = appdata/"config"/"";
      62             :         m_cache = appdata/"cache"/"";
      63             :         m_logs = appdata/"logs"/"";
      64             : 
      65             : #elif OS_WIN
      66             : 
      67             :         /* For reasoning behind our Windows paths, see the discussion here:
      68             :          * http://www.wildfiregames.com/forum/index.php?showtopic=14759
      69             :          *
      70             :          * Summary:
      71             :          *  1. Local appdata: for bulky unfriendly data like the cache,
      72             :          *      which can be recreated if deleted; doesn't need backing up.
      73             :          *  2. Roaming appdata: for slightly less unfriendly data like config
      74             :          *      files that might theoretically be shared between different
      75             :          *      machines on a domain.
      76             :          *  3. Personal / My Documents: for data explicitly created by the user,
      77             :          *      and which should be visible and easily accessed. We use a non-
      78             :          *      localized My Games subfolder for improved organization.
      79             :          */
      80             : 
      81             :         // %localappdata%/0ad/
      82             :         const OsPath localAppdata = wutil_LocalAppdataPath() / subdirectoryName/"";
      83             :         // %appdata%/0ad/
      84             :         const OsPath roamingAppData = wutil_RoamingAppdataPath() / subdirectoryName/"";
      85             :         // My Documents/My Games/0ad/
      86             :         const OsPath personalData = wutil_PersonalPath() / "My Games" / subdirectoryName/"";
      87             : 
      88             :         m_cache = localAppdata / "cache"/"";
      89             :         m_gameData = roamingAppData / "data"/"";
      90             :         m_userData = personalData/"";
      91             :         m_config = roamingAppData / "config"/"";
      92             :         m_logs = localAppdata / "logs"/"";
      93             : 
      94             : #elif OS_MACOSX
      95             : 
      96             :         /* For reasoning behind our OS X paths, see the discussion here:
      97             :          * http://www.wildfiregames.com/forum/index.php?showtopic=15511
      98             :          *
      99             :          * Summary:
     100             :          *  1. Application Support: most data associated with the app
     101             :          *      should be stored here, with few exceptions (e.g. temporary
     102             :          *      data, cached data, and managed media files).
     103             :          *  2. Caches: used for non-critial app data that can be easily
     104             :          *      regenerated if this directory is deleted. It is not
     105             :          *      included in backups by default.
     106             :          *
     107             :          * Note: the paths returned by osx_Get*Path are not guaranteed to exist,
     108             :          *     but that's OK since we always create them on demand.
     109             :          */
     110             : 
     111             :         // We probably want to use the same subdirectoryName regardless
     112             :         //  of whether running a bundle or from SVN. Apple recommends using
     113             :         //  company name, bundle name or bundle identifier.
     114             :         OsPath appSupportPath;  // ~/Library/Application Support/0ad
     115             :         OsPath cachePath;       // ~/Library/Caches/0ad
     116             : 
     117             :         {
     118             :             std::string path = osx_GetAppSupportPath();
     119             :             ENSURE(!path.empty());
     120             :             appSupportPath = OsPath(path) / subdirectoryName;
     121             :         }
     122             :         {
     123             :             std::string path = osx_GetCachesPath();
     124             :             ENSURE(!path.empty());
     125             :             cachePath = OsPath(path) / subdirectoryName;
     126             :         }
     127             : 
     128             :         // We don't make the game vs. user data distinction on OS X
     129             :         m_gameData = appSupportPath /"";
     130             :         m_userData = m_gameData;
     131             :         m_cache = cachePath/"";
     132             :         m_config = appSupportPath / "config"/"";
     133             :         m_logs = appSupportPath / "logs"/"";
     134             : 
     135             : #else // OS_UNIX
     136             : 
     137           0 :         const char* envHome = getenv("HOME");
     138           0 :         ENSURE(envHome);
     139           0 :         const OsPath home(envHome);
     140           0 :         const OsPath xdgData   = XDG_Path("XDG_DATA_HOME",   home, home/".local/share/") / subdirectoryName;
     141           0 :         const OsPath xdgConfig = XDG_Path("XDG_CONFIG_HOME", home, home/".config/"     ) / subdirectoryName;
     142           0 :         const OsPath xdgCache  = XDG_Path("XDG_CACHE_HOME",  home, home/".cache/"      ) / subdirectoryName;
     143             : 
     144             :         // We don't make the game vs. user data distinction on Unix
     145           0 :         m_gameData = xdgData/"";
     146           0 :         m_userData = m_gameData;
     147           0 :         m_cache  = xdgCache/"";
     148           0 :         m_config = xdgConfig / "config"/"";
     149           0 :         m_logs   = xdgConfig / "logs"/"";
     150             : 
     151             : #endif
     152             :     }
     153           0 : }
     154             : 
     155             : 
     156           0 : /*static*/ OsPath Paths::Root(const OsPath& argv0)
     157             : {
     158             : #if OS_ANDROID
     159             :     return OsPath("/sdcard/0ad"); // TODO: this is kind of bogus
     160             : #else
     161             : 
     162             :     // get full path to executable
     163           0 :     OsPath pathname = sys_ExecutablePathname(); // safe, but requires OS-specific implementation
     164           0 :     if(pathname.empty())    // failed, use argv[0] instead
     165             :     {
     166           0 :         errno = 0;
     167           0 :         pathname = wrealpath(argv0);
     168           0 :         if(pathname.empty())
     169           0 :             WARN_IF_ERR(StatusFromErrno());
     170             :     }
     171             : 
     172             :     // make sure it's valid
     173           0 :     if(!FileExists(pathname))
     174             :     {
     175           0 :         LOGERROR("Cannot find executable (expected at '%s')", pathname.string8());
     176           0 :         WARN_IF_ERR(StatusFromErrno());
     177             :     }
     178             : 
     179           0 :     for(size_t i = 0; i < 2; i++)    // remove "system/name.exe"
     180           0 :         pathname = pathname.Parent();
     181           0 :     return pathname;
     182             : 
     183             : #endif
     184             : }
     185             : 
     186           0 : /*static*/ OsPath Paths::RootData(const OsPath& argv0)
     187             : {
     188             : 
     189             : #ifdef INSTALLED_DATADIR
     190             :     UNUSED2(argv0);
     191             :     return OsPath(STRINGIZE(INSTALLED_DATADIR))/"";
     192             : #else
     193             : 
     194             : # if OS_MACOSX
     195             :     if (osx_IsAppBundleValid())
     196             :     {
     197             :         debug_printf("Valid app bundle detected\n");
     198             : 
     199             :         std::string resourcesPath = osx_GetBundleResourcesPath();
     200             :         // Ensure we have a valid resources path
     201             :         ENSURE(!resourcesPath.empty());
     202             : 
     203             :         return OsPath(resourcesPath)/"data"/"";
     204             :     }
     205             : # endif // OS_MACOSX
     206             : 
     207           0 :     return Root(argv0)/"data"/"";
     208             : 
     209             : #endif // INSTALLED_DATADIR
     210             : }
     211             : 
     212           0 : /*static*/ OsPath Paths::XDG_Path(const char* envname, const OsPath& home, const OsPath& defaultPath)
     213             : {
     214           0 :     const char* path = getenv(envname);
     215             :     // Use if set and non-empty
     216           0 :     if(path && path[0] != '\0')
     217             :     {
     218           0 :         if(path[0] != '/')  // relative to $HOME
     219           0 :             return home / path/"";
     220           0 :         return OsPath(path)/"";
     221             :     }
     222           0 :     return defaultPath/"";
     223           3 : }

Generated by: LCOV version 1.13