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-11-21 22:18:42 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             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #include "cpl_port.h"
      14             : #include "cpl_conv.h"
      15             : 
      16             : #if HAVE_UNISTD_H
      17             : #include <unistd.h>
      18             : #endif
      19             : 
      20             : #include "cpl_multiproc.h"
      21             : #include "cpl_string.h"
      22             : 
      23             : #if defined(_WIN32)
      24             : #include <windows.h>
      25             : #elif defined(__MACH__) && defined(__APPLE__)
      26             : #include <mach-o/dyld.h>
      27             : #elif defined(__FreeBSD__)
      28             : #include <sys/sysctl.h>
      29             : #include <sys/types.h>
      30             : #endif
      31             : 
      32             : /************************************************************************/
      33             : /*                           CPLGetExecPath()                           */
      34             : /************************************************************************/
      35             : 
      36             : /**
      37             :  * Fetch path of executable.
      38             :  *
      39             :  * The path to the executable currently running is returned.  This path
      40             :  * includes the name of the executable. Currently this only works on
      41             :  * Windows, Linux, MacOS and FreeBSD platforms.  The returned path is UTF-8
      42             :  * encoded, and will be nul-terminated if success is reported.
      43             :  *
      44             :  * @param pszPathBuf the buffer into which the path is placed.
      45             :  * @param nMaxLength the buffer size (including the nul-terminating character).
      46             :  * MAX_PATH+1 is suggested.
      47             :  *
      48             :  * @return FALSE on failure or TRUE on success.
      49             :  */
      50             : 
      51         129 : int CPLGetExecPath(char *pszPathBuf, int nMaxLength)
      52             : {
      53         129 :     if (nMaxLength == 0)
      54           0 :         return FALSE;
      55         129 :     pszPathBuf[0] = '\0';
      56             : 
      57             : #if defined(_WIN32)
      58             :     if (CPLTestBool(CPLGetConfigOption("GDAL_FILENAME_IS_UTF8", "YES")))
      59             :     {
      60             :         wchar_t *pwszPathBuf =
      61             :             static_cast<wchar_t *>(CPLCalloc(nMaxLength + 1, sizeof(wchar_t)));
      62             : 
      63             :         if (GetModuleFileNameW(nullptr, pwszPathBuf, nMaxLength) == 0)
      64             :         {
      65             :             CPLFree(pwszPathBuf);
      66             :             return FALSE;
      67             :         }
      68             :         else
      69             :         {
      70             :             char *pszDecoded =
      71             :                 CPLRecodeFromWChar(pwszPathBuf, CPL_ENC_UCS2, CPL_ENC_UTF8);
      72             : 
      73             :             const size_t nStrlenDecoded = strlen(pszDecoded);
      74             :             strncpy(pszPathBuf, pszDecoded, nMaxLength);
      75             :             int bOK = TRUE;
      76             :             if (nStrlenDecoded >= static_cast<size_t>(nMaxLength) - 1)
      77             :             {
      78             :                 pszPathBuf[nMaxLength - 1] = '\0';
      79             :                 // There is no easy way to detect if the string has been
      80             :                 // truncated other than testing the existence of the file.
      81             :                 VSIStatBufL sStat;
      82             :                 bOK = (VSIStatL(pszPathBuf, &sStat) == 0);
      83             :             }
      84             :             CPLFree(pszDecoded);
      85             :             CPLFree(pwszPathBuf);
      86             :             return bOK;
      87             :         }
      88             :     }
      89             :     else
      90             :     {
      91             :         if (GetModuleFileNameA(nullptr, pszPathBuf, nMaxLength) == 0)
      92             :             return FALSE;
      93             :         else
      94             :         {
      95             :             const size_t nStrlenDecoded = strlen(pszPathBuf);
      96             :             int bOK = TRUE;
      97             :             if (nStrlenDecoded >= static_cast<size_t>(nMaxLength) - 1)
      98             :             {
      99             :                 pszPathBuf[nMaxLength - 1] = '\0';
     100             :                 // There is no easy way to detect if the string has been
     101             :                 // truncated other than testing the existence of the file.
     102             :                 VSIStatBufL sStat;
     103             :                 bOK = (VSIStatL(pszPathBuf, &sStat) == 0);
     104             :             }
     105             :             return bOK;
     106             :         }
     107             :     }
     108             : #elif defined(__linux)
     109         129 :     long nPID = getpid();
     110         129 :     CPLString osExeLink;
     111             : 
     112         129 :     osExeLink.Printf("/proc/%ld/exe", nPID);
     113         129 :     ssize_t nResultLen = readlink(osExeLink, pszPathBuf, nMaxLength);
     114         129 :     if (nResultLen == nMaxLength)
     115           1 :         pszPathBuf[nMaxLength - 1] = '\0';
     116         128 :     else if (nResultLen >= 0)
     117         128 :         pszPathBuf[nResultLen] = '\0';
     118             : 
     119         129 :     return nResultLen > 0 && nResultLen < nMaxLength;
     120             : #elif defined(__MACH__) && defined(__APPLE__)
     121             :     uint32_t size = static_cast<uint32_t>(nMaxLength);
     122             :     if (_NSGetExecutablePath(pszPathBuf, &size) == 0)
     123             :     {
     124             :         return TRUE;
     125             :     }
     126             :     return FALSE;
     127             : #elif defined(__FreeBSD__)
     128             :     int mib[4];
     129             :     mib[0] = CTL_KERN;
     130             :     mib[1] = KERN_PROC;
     131             :     mib[2] = KERN_PROC_PATHNAME;
     132             :     mib[3] = -1;
     133             :     size_t size = static_cast<size_t>(nMaxLength);
     134             :     if (sysctl(mib, 4, pszPathBuf, &size, nullptr, 0) == 0)
     135             :     {
     136             :         return TRUE;
     137             :     }
     138             :     return FALSE;
     139             : #else
     140             :     return FALSE;
     141             : #endif
     142             : }

Generated by: LCOV version 1.14