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