LCOV - code coverage report
Current view: top level - port - cpl_getexecpath.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 12 13 92.3 %
Date: 2024-04-29 01:40:10 Functions: 1 1 100.0 %

          Line data    Source code
       1             : /**********************************************************************
       2             :  *
       3             :  * Project:  CPL - Common Portability Library
       4             :  * Purpose:  Implement CPLGetExecPath().
       5             :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       6             :  *
       7             :  **********************************************************************
       8             :  * Copyright (c) 2005, Frank Warmerdam
       9             :  *
      10             :  * Permission is hereby granted, free of charge, to any person obtaining a
      11             :  * copy of this software and associated documentation files (the "Software"),
      12             :  * to deal in the Software without restriction, including without limitation
      13             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      14             :  * and/or sell copies of the Software, and to permit persons to whom the
      15             :  * Software is furnished to do so, subject to the following conditions:
      16             :  *
      17             :  * The above copyright notice and this permission notice shall be included
      18             :  * in all copies or substantial portions of the Software.
      19             :  *
      20             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      21             :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      22             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
      23             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      24             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      25             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      26             :  * DEALINGS IN THE SOFTWARE.
      27             :  ****************************************************************************/
      28             : 
      29             : #include "cpl_port.h"
      30             : #include "cpl_conv.h"
      31             : 
      32             : #if HAVE_UNISTD_H
      33             : #include <unistd.h>
      34             : #endif
      35             : 
      36             : #include "cpl_multiproc.h"
      37             : #include "cpl_string.h"
      38             : 
      39             : #if defined(_WIN32)
      40             : #include <windows.h>
      41             : #elif defined(__MACH__) && defined(__APPLE__)
      42             : #include <mach-o/dyld.h>
      43             : #elif defined(__FreeBSD__)
      44             : #include <sys/sysctl.h>
      45             : #include <sys/types.h>
      46             : #endif
      47             : 
      48             : /************************************************************************/
      49             : /*                           CPLGetExecPath()                           */
      50             : /************************************************************************/
      51             : 
      52             : /**
      53             :  * Fetch path of executable.
      54             :  *
      55             :  * The path to the executable currently running is returned.  This path
      56             :  * includes the name of the executable. Currently this only works on
      57             :  * Windows, Linux, MacOS and FreeBSD platforms.  The returned path is UTF-8
      58             :  * encoded, and will be nul-terminated if success is reported.
      59             :  *
      60             :  * @param pszPathBuf the buffer into which the path is placed.
      61             :  * @param nMaxLength the buffer size (including the nul-terminating character).
      62             :  * MAX_PATH+1 is suggested.
      63             :  *
      64             :  * @return FALSE on failure or TRUE on success.
      65             :  */
      66             : 
      67         135 : int CPLGetExecPath(char *pszPathBuf, int nMaxLength)
      68             : {
      69         135 :     if (nMaxLength == 0)
      70           0 :         return FALSE;
      71         135 :     pszPathBuf[0] = '\0';
      72             : 
      73             : #if defined(_WIN32)
      74             :     if (CPLTestBool(CPLGetConfigOption("GDAL_FILENAME_IS_UTF8", "YES")))
      75             :     {
      76             :         wchar_t *pwszPathBuf =
      77             :             static_cast<wchar_t *>(CPLCalloc(nMaxLength + 1, sizeof(wchar_t)));
      78             : 
      79             :         if (GetModuleFileNameW(nullptr, pwszPathBuf, nMaxLength) == 0)
      80             :         {
      81             :             CPLFree(pwszPathBuf);
      82             :             return FALSE;
      83             :         }
      84             :         else
      85             :         {
      86             :             char *pszDecoded =
      87             :                 CPLRecodeFromWChar(pwszPathBuf, CPL_ENC_UCS2, CPL_ENC_UTF8);
      88             : 
      89             :             const size_t nStrlenDecoded = strlen(pszDecoded);
      90             :             strncpy(pszPathBuf, pszDecoded, nMaxLength);
      91             :             int bOK = TRUE;
      92             :             if (nStrlenDecoded >= static_cast<size_t>(nMaxLength) - 1)
      93             :             {
      94             :                 pszPathBuf[nMaxLength - 1] = '\0';
      95             :                 // There is no easy way to detect if the string has been
      96             :                 // truncated other than testing the existence of the file.
      97             :                 VSIStatBufL sStat;
      98             :                 bOK = (VSIStatL(pszPathBuf, &sStat) == 0);
      99             :             }
     100             :             CPLFree(pszDecoded);
     101             :             CPLFree(pwszPathBuf);
     102             :             return bOK;
     103             :         }
     104             :     }
     105             :     else
     106             :     {
     107             :         if (GetModuleFileNameA(nullptr, pszPathBuf, nMaxLength) == 0)
     108             :             return FALSE;
     109             :         else
     110             :         {
     111             :             const size_t nStrlenDecoded = strlen(pszPathBuf);
     112             :             int bOK = TRUE;
     113             :             if (nStrlenDecoded >= static_cast<size_t>(nMaxLength) - 1)
     114             :             {
     115             :                 pszPathBuf[nMaxLength - 1] = '\0';
     116             :                 // There is no easy way to detect if the string has been
     117             :                 // truncated other than testing the existence of the file.
     118             :                 VSIStatBufL sStat;
     119             :                 bOK = (VSIStatL(pszPathBuf, &sStat) == 0);
     120             :             }
     121             :             return bOK;
     122             :         }
     123             :     }
     124             : #elif defined(__linux)
     125         135 :     long nPID = getpid();
     126         135 :     CPLString osExeLink;
     127             : 
     128         135 :     osExeLink.Printf("/proc/%ld/exe", nPID);
     129         135 :     ssize_t nResultLen = readlink(osExeLink, pszPathBuf, nMaxLength);
     130         135 :     if (nResultLen == nMaxLength)
     131           1 :         pszPathBuf[nMaxLength - 1] = '\0';
     132         134 :     else if (nResultLen >= 0)
     133         134 :         pszPathBuf[nResultLen] = '\0';
     134             : 
     135         135 :     return nResultLen > 0 && nResultLen < nMaxLength;
     136             : #elif defined(__MACH__) && defined(__APPLE__)
     137             :     uint32_t size = static_cast<uint32_t>(nMaxLength);
     138             :     if (_NSGetExecutablePath(pszPathBuf, &size) == 0)
     139             :     {
     140             :         return TRUE;
     141             :     }
     142             :     return FALSE;
     143             : #elif defined(__FreeBSD__)
     144             :     int mib[4];
     145             :     mib[0] = CTL_KERN;
     146             :     mib[1] = KERN_PROC;
     147             :     mib[2] = KERN_PROC_PATHNAME;
     148             :     mib[3] = -1;
     149             :     size_t size = static_cast<size_t>(nMaxLength);
     150             :     if (sysctl(mib, 4, pszPathBuf, &size, nullptr, 0) == 0)
     151             :     {
     152             :         return TRUE;
     153             :     }
     154             :     return FALSE;
     155             : #else
     156             :     return FALSE;
     157             : #endif
     158             : }

Generated by: LCOV version 1.14