OpenTTD Source 20250612-master-gb012d9e3dc
unix.cpp
Go to the documentation of this file.
1/*
2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
6 */
7
10#include "../../stdafx.h"
11#include "../../textbuf_gui.h"
12#include "../../debug.h"
13#include "../../string_func.h"
14#include "../../fios.h"
15#include "../../thread.h"
16
17
18#include <dirent.h>
19#include <unistd.h>
20#include <sys/stat.h>
21#include <time.h>
22#include <signal.h>
23#include <pthread.h>
24
25#ifdef WITH_SDL2
26#include <SDL.h>
27#endif
28
29#ifdef __EMSCRIPTEN__
30# include <emscripten.h>
31#endif
32
33#ifdef __APPLE__
34# include <sys/mount.h>
35#elif (defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L) || defined(__GLIBC__)
36# define HAS_STATVFS
37#endif
38
39#if defined(OPENBSD) || defined(__NetBSD__) || defined(__FreeBSD__)
40# define HAS_SYSCTL
41#endif
42
43#ifdef HAS_STATVFS
44#include <sys/statvfs.h>
45#endif
46
47#ifdef HAS_SYSCTL
48#include <sys/sysctl.h>
49#endif
50
51#if defined(__APPLE__)
52# include "../macosx/macos.h"
53#endif
54
55#include "../../safeguards.h"
56
57bool FiosIsRoot(const std::string &path)
58{
59 return path == PATHSEP;
60}
61
62void FiosGetDrives(FileList &)
63{
64 return;
65}
66
67std::optional<uint64_t> FiosGetDiskFreeSpace(const std::string &path)
68{
69#ifdef __APPLE__
70 struct statfs s;
71
72 if (statfs(path.c_str(), &s) == 0) return static_cast<uint64_t>(s.f_bsize) * s.f_bavail;
73#elif defined(HAS_STATVFS)
74 struct statvfs s;
75
76 if (statvfs(path.c_str(), &s) == 0) return static_cast<uint64_t>(s.f_frsize) * s.f_bavail;
77#endif
78 return std::nullopt;
79}
80
81bool FiosIsHiddenFile(const std::filesystem::path &path)
82{
83 return path.filename().string().starts_with(".");
84}
85
86#ifdef WITH_ICONV
87
88#include <iconv.h>
89#include "../../debug.h"
90#include "../../string_func.h"
91
92std::optional<std::string> GetCurrentLocale(const char *param);
93
94#define INTERNALCODE "UTF-8"
95
101static std::string GetLocalCode()
102{
103#if defined(__APPLE__)
104 return "UTF-8-MAC";
105#else
106 /* Strip locale (eg en_US.UTF-8) to only have UTF-8 */
107 auto locale = GetCurrentLocale("LC_CTYPE");
108 if (!locale.has_value()) return "";
109 auto pos = locale->find('.');
110 if (pos == std::string_view::npos) return "";
111 locale.erase(0, pos + 1);
112 return locale;
113#endif
114}
115
120static std::string convert_tofrom_fs(iconv_t convd, std::string_view name)
121{
122 /* There are different implementations of iconv. The older ones,
123 * e.g. SUSv2, pass a const pointer, whereas the newer ones, e.g.
124 * IEEE 1003.1 (2004), pass a non-const pointer. */
125#ifdef HAVE_NON_CONST_ICONV
126 char *inbuf = const_cast<char *>(name.data());
127#else
128 const char *inbuf = name.data();
129#endif
130
131 /* If the output is UTF-32, then 1 ASCII character becomes 4 bytes. */
132 size_t inlen = name.size();
133 std::string buf(inlen * 4, '\0');
134
135 size_t outlen = buf.size();
136 char *outbuf = buf.data();
137 iconv(convd, nullptr, nullptr, nullptr, nullptr);
138 if (iconv(convd, &inbuf, &inlen, &outbuf, &outlen) == SIZE_MAX) {
139 Debug(misc, 0, "[iconv] error converting '{}'. Errno {}", name, errno);
140 return std::string{name};
141 }
142
143 buf.resize(outbuf - buf.data());
144 return buf;
145}
146
150static std::optional<iconv_t> OpenIconv(std::string from, std::string to)
151{
152 iconv_t convd = iconv_open(from.c_str(), to.c_str());
153 if (convd == reinterpret_cast<iconv_t>(-1)) {
154 Debug(misc, 0, "[iconv] conversion from codeset '{}' to '{}' unsupported", from, to);
155 return std::nullopt;
156 }
157 return convd;
158}
159
165std::string OTTD2FS(std::string_view name)
166{
167 static const auto convd = OpenIconv(GetLocalCode(), INTERNALCODE);
168 if (!convd.has_value()) return std::string{name};
169
170 return convert_tofrom_fs(*convd, name);
171}
172
178std::string FS2OTTD(std::string_view name)
179{
180 static const auto convd = OpenIconv(INTERNALCODE, GetLocalCode());
181 if (!convd.has_value()) return std::string{name};
182
183 return convert_tofrom_fs(*convd, name);
184}
185
186#endif /* WITH_ICONV */
187
188void ShowInfoI(std::string_view str)
189{
190 fmt::print(stderr, "{}\n", str);
191}
192
193#if !defined(__APPLE__)
194void ShowOSErrorBox(std::string_view buf, bool)
195{
196 /* All unix systems, except OSX. Only use escape codes on a TTY. */
197 if (isatty(fileno(stderr))) {
198 fmt::print(stderr, "\033[1;31mError: {}\033[0;39m\n", buf);
199 } else {
200 fmt::print(stderr, "Error: {}\n", buf);
201 }
202}
203#endif
204
205#ifndef WITH_COCOA
206std::optional<std::string> GetClipboardContents()
207{
208#ifdef WITH_SDL2
209 if (SDL_HasClipboardText() == SDL_FALSE) return std::nullopt;
210
211 char *clip = SDL_GetClipboardText();
212 if (clip != nullptr) {
213 std::string result = clip;
214 SDL_free(clip);
215 return result;
216 }
217#endif
218
219 return std::nullopt;
220}
221#endif
222
223
224#if defined(__EMSCRIPTEN__)
225void OSOpenBrowser(const std::string &url)
226{
227 /* Implementation in pre.js */
228 EM_ASM({ if (window["openttd_open_url"]) window.openttd_open_url($0, $1) }, url.data(), url.size());
229}
230#elif !defined( __APPLE__)
231void OSOpenBrowser(const std::string &url)
232{
233 pid_t child_pid = fork();
234 if (child_pid != 0) return;
235
236 const char *args[3];
237 args[0] = "xdg-open";
238 args[1] = url.c_str();
239 args[2] = nullptr;
240 execvp(args[0], const_cast<char * const *>(args));
241 Debug(misc, 0, "Failed to open url: {}", url);
242 exit(0);
243}
244#endif /* __APPLE__ */
245
246void SetCurrentThreadName([[maybe_unused]] const std::string &thread_name)
247{
248#if defined(__GLIBC__)
249 pthread_setname_np(pthread_self(), thread_name.c_str());
250#endif /* defined(__GLIBC__) */
251#if defined(__APPLE__)
252 MacOSSetThreadName(thread_name);
253#endif /* defined(__APPLE__) */
254}
List of file information.
Definition fios.h:87
#define Debug(category, level, format_string,...)
Output a line of debugging information.
Definition debug.h:37
std::optional< std::string > GetClipboardContents()
Try to retrieve the current clipboard contents.
Definition unix.cpp:206
void SetCurrentThreadName(const std::string &thread_name)
Name the thread this function is called on for the debugger.
Definition unix.cpp:246
std::wstring OTTD2FS(std::string_view name)
Convert from OpenTTD's encoding to a wide string.
Definition win32.cpp:354
std::string FS2OTTD(std::wstring_view name)
Convert to OpenTTD's encoding from a wide string.
Definition win32.cpp:337
std::optional< std::string > GetCurrentLocale(const char *)
Determine the current user's locale.
Definition win32.cpp:398