Branch data Line data Source code
1 : : #pragma once
2 : :
3 : : /*
4 : : MIT License
5 : :
6 : : Copyright (c) 2014-2024 Stephane Cuillerdier (aka aiekick)
7 : :
8 : : Permission is hereby granted, free of charge, to any person obtaining a copy
9 : : of this software and associated documentation files (the "Software"), to deal
10 : : in the Software without restriction, including without limitation the rights
11 : : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 : : copies of the Software, and to permit persons to whom the Software is
13 : : furnished to do so, subject to the following conditions:
14 : :
15 : : The above copyright notice and this permission notice shall be included in all
16 : : copies or substantial portions of the Software.
17 : :
18 : : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 : : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 : : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 : : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 : : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 : : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 : : SOFTWARE.
25 : : */
26 : :
27 : : // ezApp is part of the ezLibs project : https://github.com/aiekick/ezLibs.git
28 : :
29 : : #include "ezOS.hpp"
30 : :
31 : : #ifdef WINDOWS_OS
32 : : // includes
33 : : #include <Windows.h>
34 : : #include <shellapi.h>
35 : : #pragma comment(lib, "shlwapi.lib")
36 : : #include <direct.h> // _chdir
37 : : // defines
38 : : #define S_IFDIR _S_IFDIR
39 : : #define GetCurrentDir _getcwd
40 : : #define SetCurrentDir _chdir
41 : : #define SLASH_CHAR "\\"
42 : : #elif defined(LINUX_OS) || defined(APPLE_OS)
43 : : // includes
44 : : #include <unistd.h>
45 : : #include <sys/param.h>
46 : : #include <sys/file.h>
47 : : #include <sys/wait.h>
48 : : #include <ctype.h>
49 : : #include <pwd.h>
50 : : #include <time.h>
51 : : #include <signal.h>
52 : : #include <errno.h>
53 : : #include <fcntl.h>
54 : : #include <dirent.h>
55 : : #include <cstdlib>
56 : : #include <stdio.h>
57 : : #ifdef APPLE_OS
58 : : #include <dlfcn.h>
59 : : #include <sys/syslimits.h> // PATH_MAX
60 : : #endif // APPLE_OS
61 : : #ifdef STDC_HEADERS
62 : : #include <stdlib.h>
63 : : #include <stddef.h>
64 : : #else // STDC_HEADERS
65 : : #ifdef HAVE_STDLIB_H
66 : : #include <stdlib.h>
67 : : #endif // HAVE_STDLIB_H
68 : : #endif /* STDC_HEADERS */
69 : : #ifdef HAVE_STRING_H
70 : : #include <string.h>
71 : : #endif /* HAVE_STRING_H */
72 : : // defines
73 : : #define GetCurrentDir getcwd
74 : : #define SetCurrentDir chdir
75 : : #ifndef S_IFDIR
76 : : #define S_IFDIR __S_IFDIR
77 : : #endif // S_IFDIR
78 : : #ifndef MAX_PATH
79 : 4 : #define MAX_PATH PATH_MAX
80 : : #endif // MAX_PATH
81 : : #ifndef PATH_MAX
82 : : #define PATH_MAX MAX_PATH
83 : : #endif // PATH_MAX
84 : : #define SLASH_CHAR "/"
85 : : #endif
86 : :
87 : : #include "ezStr.hpp" // ez::str::replaceString
88 : :
89 : : #include <map>
90 : : #include <vector>
91 : : #include <string>
92 : : #include <cstdio> // FILENAME_MAX
93 : : #include <cstdint> // int32_t
94 : : #include <iostream>
95 : :
96 : : namespace ez {
97 : :
98 : : class App {
99 : : private:
100 : : std::string m_AppPath;
101 : :
102 : : public:
103 : 2 : App() = default;
104 : 0 : App(int32_t /*vArgc*/, char** vArgv) {
105 : 0 : #ifdef _MSC_VER
106 : 0 : SetConsoleOutputCP(CP_UTF8);
107 : 0 : #endif
108 : 0 : setAppPath(vArgv[0]);
109 : 0 : setCurDirectory(getAppPath());
110 : 0 : }
111 : :
112 : 0 : void setAppPath(const std::string& vPath) {
113 : 0 : if (!vPath.empty()) {
114 : 0 : auto pos = vPath.find_last_of("\\/");
115 : 0 : if (pos != std::string::npos) {
116 : 0 : m_AppPath = vPath.substr(0, pos);
117 : 0 : }
118 : 0 : }
119 : 0 : }
120 : :
121 : : template <typename T>
122 : 2 : inline T mini(T a, T b) {
123 [ + - ]: 2 : return a < b ? a : b;
124 : 2 : }
125 : :
126 : 2 : std::string getAppPath() {
127 [ + - ]: 2 : if (m_AppPath.empty()) {
128 : 2 : char buffer[MAX_PATH] = {};
129 : : #ifdef WINDOWS_OS
130 : : GetModuleFileName(nullptr, buffer, MAX_PATH);
131 : : #elif defined(LINUX_OS)
132 : : char szTmp[32];
133 : 2 : sprintf(szTmp, "/proc/%d/exe", getpid());
134 : 2 : auto bytes = mini<int>(readlink(szTmp, buffer, MAX_PATH), MAX_PATH - 1);
135 [ + - ]: 2 : if (bytes >= 0) {
136 : 2 : buffer[bytes] = '\0';
137 : 2 : }
138 : : #elif defined(APPLE_OS)
139 : : auto path = m_getMacOsAppPath();
140 : : auto pos = path.find_last_of("\\/");
141 : : m_AppPath = path.substr(0, pos);
142 : : #endif
143 : 2 : #if defined(WINDOWS_OS) || defined(LINUX_OS)
144 : 2 : auto pos = std::string(buffer).find_last_of("\\/");
145 : 2 : m_AppPath = std::string(buffer).substr(0, pos);
146 : 2 : #endif
147 : 2 : }
148 : 2 : return m_AppPath;
149 : 2 : }
150 : :
151 : 0 : std::string getAppPath() const { return m_AppPath; }
152 : :
153 : 0 : static std::string getCurDirectory() {
154 : 0 : char cCurrentPath[FILENAME_MAX];
155 : 0 : if (GetCurrentDir(cCurrentPath, FILENAME_MAX)) {
156 : 0 : return std::string(cCurrentPath) + SLASH_CHAR;
157 : 0 : }
158 : 0 : return "";
159 : 0 : }
160 : :
161 : 0 : static bool setCurDirectory(const std::string& vPath) {
162 : 0 : auto path = vPath;
163 : 0 : m_correctSlashForPath(path);
164 : 0 : return (SetCurrentDir(path.c_str()) == 0);
165 : 0 : }
166 : :
167 : : private:
168 : : /* correct file path between os and different slash type between window and unix */
169 : 0 : static void m_correctSlashForPath(std::string& vPath) {
170 : 0 : str::replaceString(vPath, "\\", SLASH_CHAR);
171 : 0 : str::replaceString(vPath, "/", SLASH_CHAR);
172 : 0 : }
173 : :
174 : : #if defined(APPLE_OS)
175 : : static std::string m_getMacOsAppPath() {
176 : : Dl_info module_info;
177 : : if (dladdr((void*)getCurDirectory, &module_info)) { // use of getCurDirectory who is a static function
178 : : return std::string(module_info.dli_fname);
179 : : }
180 : : return "";
181 : : }
182 : : #endif
183 : : };
184 : :
185 : : } // namespace ez
|