summaryrefslogtreecommitdiff
path: root/drivers/unix/os_unix.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/unix/os_unix.cpp')
-rw-r--r--drivers/unix/os_unix.cpp114
1 files changed, 85 insertions, 29 deletions
diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp
index b9bd773c2e..5bf14056ab 100644
--- a/drivers/unix/os_unix.cpp
+++ b/drivers/unix/os_unix.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -65,6 +65,21 @@
#include <time.h>
#include <unistd.h>
+#if defined(MACOS_ENABLED) || (defined(__ANDROID_API__) && __ANDROID_API__ >= 28)
+// Random location for getentropy. Fitting.
+#include <sys/random.h>
+#define UNIX_GET_ENTROPY
+#elif defined(__FreeBSD__) || defined(__OpenBSD__) || (defined(__GLIBC_MINOR__) && (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 26))
+// In <unistd.h>.
+// One day... (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 700)
+// https://publications.opengroup.org/standards/unix/c211
+#define UNIX_GET_ENTROPY
+#endif
+
+#if !defined(UNIX_GET_ENTROPY) && !defined(NO_URANDOM)
+#include <fcntl.h>
+#endif
+
/// Clock Setup function (used by get_ticks_usec)
static uint64_t _clock_start = 0;
#if defined(__APPLE__)
@@ -91,7 +106,7 @@ static void _setup_clock() {
void OS_Unix::debug_break() {
assert(false);
-};
+}
static void handle_interrupt(int sig) {
if (!EngineDebugger::is_active()) {
@@ -129,7 +144,7 @@ void OS_Unix::initialize_core() {
#ifndef NO_NETWORK
NetSocketPosix::make_default();
- IP_Unix::make_default();
+ IPUnix::make_default();
#endif
_setup_clock();
@@ -139,10 +154,6 @@ void OS_Unix::finalize_core() {
NetSocketPosix::cleanup();
}
-void OS_Unix::alert(const String &p_alert, const String &p_title) {
- fprintf(stderr, "ERROR: %s\n", p_alert.utf8().get_data());
-}
-
String OS_Unix::get_stdin_string(bool p_block) {
if (p_block) {
char buff[1024];
@@ -154,6 +165,31 @@ String OS_Unix::get_stdin_string(bool p_block) {
return "";
}
+Error OS_Unix::get_entropy(uint8_t *r_buffer, int p_bytes) {
+#if defined(UNIX_GET_ENTROPY)
+ int left = p_bytes;
+ int ofs = 0;
+ do {
+ int chunk = MIN(left, 256);
+ ERR_FAIL_COND_V(getentropy(r_buffer + ofs, chunk), FAILED);
+ left -= chunk;
+ ofs += chunk;
+ } while (left > 0);
+#elif !defined(NO_URANDOM)
+ int r = open("/dev/urandom", O_RDONLY);
+ ERR_FAIL_COND_V(r < 0, FAILED);
+ int left = p_bytes;
+ do {
+ ssize_t ret = read(r, r_buffer, p_bytes);
+ ERR_FAIL_COND_V(ret <= 0, FAILED);
+ left -= ret;
+ } while (left > 0);
+#else
+ return ERR_UNAVAILABLE;
+#endif
+ return OK;
+}
+
String OS_Unix::get_name() const {
return "Unix";
}
@@ -162,12 +198,12 @@ double OS_Unix::get_unix_time() const {
struct timeval tv_now;
gettimeofday(&tv_now, nullptr);
return (double)tv_now.tv_sec + double(tv_now.tv_usec) / 1000000;
-};
+}
-OS::Date OS_Unix::get_date(bool utc) const {
+OS::Date OS_Unix::get_date(bool p_utc) const {
time_t t = time(nullptr);
struct tm lt;
- if (utc) {
+ if (p_utc) {
gmtime_r(&t, &lt);
} else {
localtime_r(&t, &lt);
@@ -185,18 +221,18 @@ OS::Date OS_Unix::get_date(bool utc) const {
return ret;
}
-OS::Time OS_Unix::get_time(bool utc) const {
+OS::Time OS_Unix::get_time(bool p_utc) const {
time_t t = time(nullptr);
struct tm lt;
- if (utc) {
+ if (p_utc) {
gmtime_r(&t, &lt);
} else {
localtime_r(&t, &lt);
}
Time ret;
ret.hour = lt.tm_hour;
- ret.min = lt.tm_min;
- ret.sec = lt.tm_sec;
+ ret.minute = lt.tm_min;
+ ret.second = lt.tm_sec;
get_time_zone_info();
return ret;
}
@@ -253,7 +289,7 @@ uint64_t OS_Unix::get_ticks_usec() const {
return longtime;
}
-Error OS_Unix::execute(const String &p_path, const List<String> &p_arguments, String *r_pipe, int *r_exitcode, bool read_stderr, Mutex *p_pipe_mutex) {
+Error OS_Unix::execute(const String &p_path, const List<String> &p_arguments, String *r_pipe, int *r_exitcode, bool read_stderr, Mutex *p_pipe_mutex, bool p_open_console) {
#ifdef __EMSCRIPTEN__
// Don't compile this code at all to avoid undefined references.
// Actual virtual call goes to OS_JavaScript.
@@ -277,7 +313,12 @@ Error OS_Unix::execute(const String &p_path, const List<String> &p_arguments, St
if (p_pipe_mutex) {
p_pipe_mutex->lock();
}
- (*r_pipe) += String::utf8(buf);
+ String pipe_out;
+ if (pipe_out.parse_utf8(buf) == OK) {
+ (*r_pipe) += pipe_out;
+ } else {
+ (*r_pipe) += String(buf); // If not valid UTF-8 try decode as Latin-1
+ }
if (p_pipe_mutex) {
p_pipe_mutex->unlock();
}
@@ -322,7 +363,7 @@ Error OS_Unix::execute(const String &p_path, const List<String> &p_arguments, St
#endif
}
-Error OS_Unix::create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id) {
+Error OS_Unix::create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id, bool p_open_console) {
#ifdef __EMSCRIPTEN__
// Don't compile this code at all to avoid undefined references.
// Actual virtual call goes to OS_JavaScript.
@@ -374,7 +415,16 @@ Error OS_Unix::kill(const ProcessID &p_pid) {
int OS_Unix::get_process_id() const {
return getpid();
-};
+}
+
+bool OS_Unix::is_process_running(const ProcessID &p_pid) const {
+ int status = 0;
+ if (waitpid(p_pid, &status, WNOHANG) != 0) {
+ return false;
+ }
+
+ return true;
+}
bool OS_Unix::has_environment(const String &p_var) const {
return getenv(p_var.utf8().get_data()) != nullptr;
@@ -393,27 +443,32 @@ String OS_Unix::get_locale() const {
return locale;
}
-Error OS_Unix::open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path) {
+Error OS_Unix::open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path, String *r_resolved_path) {
String path = p_path;
- if (FileAccess::exists(path) && path.is_rel_path()) {
+ if (FileAccess::exists(path) && path.is_relative_path()) {
// dlopen expects a slash, in this case a leading ./ for it to be interpreted as a relative path,
// otherwise it will end up searching various system directories for the lib instead and finally failing.
path = "./" + path;
}
if (!FileAccess::exists(path)) {
- //this code exists so gdnative can load .so files from within the executable path
+ // This code exists so GDExtension can load .so files from within the executable path.
path = get_executable_path().get_base_dir().plus_file(p_path.get_file());
}
if (!FileAccess::exists(path)) {
- //this code exists so gdnative can load .so files from a standard unix location
+ // This code exists so GDExtension can load .so files from a standard unix location.
path = get_executable_path().get_base_dir().plus_file("../lib").plus_file(p_path.get_file());
}
p_library_handle = dlopen(path.utf8().get_data(), RTLD_NOW);
ERR_FAIL_COND_V_MSG(!p_library_handle, ERR_CANT_OPEN, "Can't open dynamic library: " + p_path + ". Error: " + dlerror());
+
+ if (r_resolved_path != nullptr) {
+ *r_resolved_path = path;
+ }
+
return OK;
}
@@ -464,11 +519,11 @@ int OS_Unix::get_processor_count() const {
String OS_Unix::get_user_data_dir() const {
String appname = get_safe_dir_name(ProjectSettings::get_singleton()->get("application/config/name"));
- if (appname != "") {
+ if (!appname.is_empty()) {
bool use_custom_dir = ProjectSettings::get_singleton()->get("application/config/use_custom_user_dir");
if (use_custom_dir) {
String custom_dir = get_safe_dir_name(ProjectSettings::get_singleton()->get("application/config/custom_user_dir_name"), true);
- if (custom_dir == "") {
+ if (custom_dir.is_empty()) {
custom_dir = appname;
}
return get_data_path().plus_file(custom_dir);
@@ -477,7 +532,7 @@ String OS_Unix::get_user_data_dir() const {
}
}
- return ProjectSettings::get_singleton()->get_resource_path();
+ return get_data_path().plus_file(get_godot_dir_name()).plus_file("app_userdata").plus_file("[unnamed project]");
}
String OS_Unix::get_executable_path() const {
@@ -490,7 +545,7 @@ String OS_Unix::get_executable_path() const {
if (len > 0) {
b.parse_utf8(buf, len);
}
- if (b == "") {
+ if (b.is_empty()) {
WARN_PRINT("Couldn't get executable path from /proc/self/exe, using argv[0]");
return OS::get_executable_path();
}
@@ -519,8 +574,9 @@ String OS_Unix::get_executable_path() const {
char *resolved_path = new char[buff_size + 1];
- if (_NSGetExecutablePath(resolved_path, &buff_size) == 1)
+ if (_NSGetExecutablePath(resolved_path, &buff_size) == 1) {
WARN_PRINT("MAXPATHLEN is too small");
+ }
String path(resolved_path);
delete[] resolved_path;
@@ -532,7 +588,7 @@ String OS_Unix::get_executable_path() const {
#endif
}
-void UnixTerminalLogger::log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type) {
+void UnixTerminalLogger::log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify, ErrorType p_type) {
if (!should_log(true)) {
return;
}