summaryrefslogtreecommitdiffstats
path: root/platform/linuxbsd/os_linuxbsd.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'platform/linuxbsd/os_linuxbsd.cpp')
-rw-r--r--platform/linuxbsd/os_linuxbsd.cpp305
1 files changed, 197 insertions, 108 deletions
diff --git a/platform/linuxbsd/os_linuxbsd.cpp b/platform/linuxbsd/os_linuxbsd.cpp
index 41d1f1d050..310778388b 100644
--- a/platform/linuxbsd/os_linuxbsd.cpp
+++ b/platform/linuxbsd/os_linuxbsd.cpp
@@ -30,21 +30,18 @@
#include "os_linuxbsd.h"
+#include "core/io/certs_compressed.gen.h"
#include "core/io/dir_access.h"
#include "main/main.h"
#include "servers/display_server.h"
-#include "modules/modules_enabled.gen.h" // For regex.
-#ifdef MODULE_REGEX_ENABLED
-#include "modules/regex/regex.h"
-#endif
-
#ifdef X11_ENABLED
#include "x11/display_server_x11.h"
#endif
-#ifdef HAVE_MNTENT
-#include <mntent.h>
+#include "modules/modules_enabled.gen.h" // For regex.
+#ifdef MODULE_REGEX_ENABLED
+#include "modules/regex/regex.h"
#endif
#include <dlfcn.h>
@@ -56,6 +53,10 @@
#include <sys/utsname.h>
#include <unistd.h>
+#ifdef HAVE_MNTENT
+#include <mntent.h>
+#endif
+
void OS_LinuxBSD::alert(const String &p_alert, const String &p_title) {
const char *message_programs[] = { "zenity", "kdialog", "Xdialog", "xmessage" };
@@ -195,6 +196,10 @@ void OS_LinuxBSD::set_main_loop(MainLoop *p_main_loop) {
main_loop = p_main_loop;
}
+String OS_LinuxBSD::get_identifier() const {
+ return "linuxbsd";
+}
+
String OS_LinuxBSD::get_name() const {
#ifdef __linux__
return "Linux";
@@ -210,48 +215,54 @@ String OS_LinuxBSD::get_name() const {
}
String OS_LinuxBSD::get_systemd_os_release_info_value(const String &key) const {
- static String info;
- if (info.is_empty()) {
- Ref<FileAccess> f = FileAccess::open("/etc/os-release", FileAccess::READ);
- if (f.is_valid()) {
- while (!f->eof_reached()) {
- const String line = f->get_line();
- if (line.find(key) != -1) {
- return line.split("=")[1].strip_edges();
- }
+ Ref<FileAccess> f = FileAccess::open("/etc/os-release", FileAccess::READ);
+ if (f.is_valid()) {
+ while (!f->eof_reached()) {
+ const String line = f->get_line();
+ if (line.find(key) != -1) {
+ String value = line.split("=")[1].strip_edges();
+ value = value.trim_prefix("\"");
+ return value.trim_suffix("\"");
}
}
}
- return info;
+ return "";
}
String OS_LinuxBSD::get_distribution_name() const {
- static String systemd_name = get_systemd_os_release_info_value("NAME"); // returns a value for systemd users, otherwise an empty string.
- if (!systemd_name.is_empty()) {
- return systemd_name;
+ static String distribution_name = get_systemd_os_release_info_value("NAME"); // returns a value for systemd users, otherwise an empty string.
+ if (!distribution_name.is_empty()) {
+ return distribution_name;
}
struct utsname uts; // returns a decent value for BSD family.
uname(&uts);
- return uts.sysname;
+ distribution_name = uts.sysname;
+ return distribution_name;
}
String OS_LinuxBSD::get_version() const {
- static String systemd_version = get_systemd_os_release_info_value("VERSION"); // returns a value for systemd users, otherwise an empty string.
- if (!systemd_version.is_empty()) {
- return systemd_version;
+ static String release_version = get_systemd_os_release_info_value("VERSION"); // returns a value for systemd users, otherwise an empty string.
+ if (!release_version.is_empty()) {
+ return release_version;
}
struct utsname uts; // returns a decent value for BSD family.
uname(&uts);
- return uts.version;
+ release_version = uts.version;
+ return release_version;
}
Vector<String> OS_LinuxBSD::get_video_adapter_driver_info() const {
- if (RenderingServer::get_singleton()->get_rendering_device() == nullptr) {
+ if (RenderingServer::get_singleton() == nullptr) {
return Vector<String>();
}
- const String rendering_device_name = RenderingServer::get_singleton()->get_rendering_device()->get_device_name(); // e.g. `NVIDIA GeForce GTX 970`
- const String rendering_device_vendor = RenderingServer::get_singleton()->get_rendering_device()->get_device_vendor_name(); // e.g. `NVIDIA`
+ static Vector<String> info;
+ if (!info.is_empty()) {
+ return info;
+ }
+
+ const String rendering_device_name = RenderingServer::get_singleton()->get_video_adapter_name(); // e.g. `NVIDIA GeForce GTX 970`
+ const String rendering_device_vendor = RenderingServer::get_singleton()->get_video_adapter_vendor(); // e.g. `NVIDIA`
const String card_name = rendering_device_name.trim_prefix(rendering_device_vendor).strip_edges(); // -> `GeForce GTX 970`
String vendor_device_id_mappings;
@@ -315,8 +326,8 @@ Vector<String> OS_LinuxBSD::get_video_adapter_driver_info() const {
Vector<String> class_display_device_drivers = OS_LinuxBSD::lspci_get_device_value(class_display_device_candidates, kernel_lit, dummys);
Vector<String> class_3d_device_drivers = OS_LinuxBSD::lspci_get_device_value(class_3d_device_candidates, kernel_lit, dummys);
- static String driver_name;
- static String driver_version;
+ String driver_name;
+ String driver_version;
// Use first valid value:
for (const String &driver : class_3d_device_drivers) {
@@ -336,7 +347,6 @@ Vector<String> OS_LinuxBSD::get_video_adapter_driver_info() const {
}
}
- Vector<String> info;
info.push_back(driver_name);
String modinfo;
@@ -486,10 +496,23 @@ bool OS_LinuxBSD::_check_internal_feature_support(const String &p_feature) {
return font_config_initialized;
}
#endif
+
+#ifndef __linux__
+ // `bsd` includes **all** BSD, not only "other BSD" (see `get_name()`).
+ if (p_feature == "bsd") {
+ return true;
+ }
+#endif
+
if (p_feature == "pc") {
return true;
}
+ // Match against the specific OS (`linux`, `freebsd`, `netbsd`, `openbsd`).
+ if (p_feature == get_name().to_lower()) {
+ return true;
+ }
+
return false;
}
@@ -677,40 +700,45 @@ Vector<String> OS_LinuxBSD::get_system_font_path_for_text(const String &p_font_n
}
Vector<String> ret;
- FcPattern *pattern = FcPatternCreate();
- if (pattern) {
- FcPatternAddString(pattern, FC_FAMILY, reinterpret_cast<const FcChar8 *>(p_font_name.utf8().get_data()));
- FcPatternAddInteger(pattern, FC_WEIGHT, _weight_to_fc(p_weight));
- FcPatternAddInteger(pattern, FC_WIDTH, _stretch_to_fc(p_stretch));
- FcPatternAddInteger(pattern, FC_SLANT, p_italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN);
-
- FcCharSet *char_set = FcCharSetCreate();
- for (int i = 0; i < p_text.size(); i++) {
- FcCharSetAddChar(char_set, p_text[i]);
- }
- FcPatternAddCharSet(pattern, FC_CHARSET, char_set);
-
- FcLangSet *lang_set = FcLangSetCreate();
- FcLangSetAdd(lang_set, reinterpret_cast<const FcChar8 *>(p_locale.utf8().get_data()));
- FcPatternAddLangSet(pattern, FC_LANG, lang_set);
-
- FcConfigSubstitute(0, pattern, FcMatchPattern);
- FcDefaultSubstitute(pattern);
-
- FcResult result;
- FcPattern *match = FcFontMatch(0, pattern, &result);
- if (match) {
- char *file_name = nullptr;
- if (FcPatternGetString(match, FC_FILE, 0, reinterpret_cast<FcChar8 **>(&file_name)) == FcResultMatch) {
- if (file_name) {
- ret.push_back(String::utf8(file_name));
+ static const char *allowed_formats[] = { "TrueType", "CFF" };
+ for (size_t i = 0; i < sizeof(allowed_formats) / sizeof(const char *); i++) {
+ FcPattern *pattern = FcPatternCreate();
+ if (pattern) {
+ FcPatternAddBool(pattern, FC_SCALABLE, FcTrue);
+ FcPatternAddString(pattern, FC_FONTFORMAT, reinterpret_cast<const FcChar8 *>(allowed_formats[i]));
+ FcPatternAddString(pattern, FC_FAMILY, reinterpret_cast<const FcChar8 *>(p_font_name.utf8().get_data()));
+ FcPatternAddInteger(pattern, FC_WEIGHT, _weight_to_fc(p_weight));
+ FcPatternAddInteger(pattern, FC_WIDTH, _stretch_to_fc(p_stretch));
+ FcPatternAddInteger(pattern, FC_SLANT, p_italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN);
+
+ FcCharSet *char_set = FcCharSetCreate();
+ for (int j = 0; j < p_text.size(); j++) {
+ FcCharSetAddChar(char_set, p_text[j]);
+ }
+ FcPatternAddCharSet(pattern, FC_CHARSET, char_set);
+
+ FcLangSet *lang_set = FcLangSetCreate();
+ FcLangSetAdd(lang_set, reinterpret_cast<const FcChar8 *>(p_locale.utf8().get_data()));
+ FcPatternAddLangSet(pattern, FC_LANG, lang_set);
+
+ FcConfigSubstitute(0, pattern, FcMatchPattern);
+ FcDefaultSubstitute(pattern);
+
+ FcResult result;
+ FcPattern *match = FcFontMatch(0, pattern, &result);
+ if (match) {
+ char *file_name = nullptr;
+ if (FcPatternGetString(match, FC_FILE, 0, reinterpret_cast<FcChar8 **>(&file_name)) == FcResultMatch) {
+ if (file_name) {
+ ret.push_back(String::utf8(file_name));
+ }
}
+ FcPatternDestroy(match);
}
- FcPatternDestroy(match);
+ FcPatternDestroy(pattern);
+ FcCharSetDestroy(char_set);
+ FcLangSetDestroy(lang_set);
}
- FcPatternDestroy(pattern);
- FcCharSetDestroy(char_set);
- FcLangSetDestroy(lang_set);
}
return ret;
@@ -725,47 +753,51 @@ String OS_LinuxBSD::get_system_font_path(const String &p_font_name, int p_weight
ERR_FAIL_V_MSG(String(), "Unable to load fontconfig, system font support is disabled.");
}
- String ret;
- FcPattern *pattern = FcPatternCreate();
- if (pattern) {
- bool allow_substitutes = (p_font_name.to_lower() == "sans-serif") || (p_font_name.to_lower() == "serif") || (p_font_name.to_lower() == "monospace") || (p_font_name.to_lower() == "cursive") || (p_font_name.to_lower() == "fantasy");
-
- FcPatternAddBool(pattern, FC_SCALABLE, FcTrue);
- FcPatternAddString(pattern, FC_FAMILY, reinterpret_cast<const FcChar8 *>(p_font_name.utf8().get_data()));
- FcPatternAddInteger(pattern, FC_WEIGHT, _weight_to_fc(p_weight));
- FcPatternAddInteger(pattern, FC_WIDTH, _stretch_to_fc(p_stretch));
- FcPatternAddInteger(pattern, FC_SLANT, p_italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN);
-
- FcConfigSubstitute(0, pattern, FcMatchPattern);
- FcDefaultSubstitute(pattern);
-
- FcResult result;
- FcPattern *match = FcFontMatch(0, pattern, &result);
- if (match) {
- if (!allow_substitutes) {
- char *family_name = nullptr;
- if (FcPatternGetString(match, FC_FAMILY, 0, reinterpret_cast<FcChar8 **>(&family_name)) == FcResultMatch) {
- if (family_name && String::utf8(family_name).to_lower() != p_font_name.to_lower()) {
+ static const char *allowed_formats[] = { "TrueType", "CFF" };
+ for (size_t i = 0; i < sizeof(allowed_formats) / sizeof(const char *); i++) {
+ FcPattern *pattern = FcPatternCreate();
+ if (pattern) {
+ bool allow_substitutes = (p_font_name.to_lower() == "sans-serif") || (p_font_name.to_lower() == "serif") || (p_font_name.to_lower() == "monospace") || (p_font_name.to_lower() == "cursive") || (p_font_name.to_lower() == "fantasy");
+
+ FcPatternAddBool(pattern, FC_SCALABLE, FcTrue);
+ FcPatternAddString(pattern, FC_FONTFORMAT, reinterpret_cast<const FcChar8 *>(allowed_formats[i]));
+ FcPatternAddString(pattern, FC_FAMILY, reinterpret_cast<const FcChar8 *>(p_font_name.utf8().get_data()));
+ FcPatternAddInteger(pattern, FC_WEIGHT, _weight_to_fc(p_weight));
+ FcPatternAddInteger(pattern, FC_WIDTH, _stretch_to_fc(p_stretch));
+ FcPatternAddInteger(pattern, FC_SLANT, p_italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN);
+
+ FcConfigSubstitute(0, pattern, FcMatchPattern);
+ FcDefaultSubstitute(pattern);
+
+ FcResult result;
+ FcPattern *match = FcFontMatch(0, pattern, &result);
+ if (match) {
+ if (!allow_substitutes) {
+ char *family_name = nullptr;
+ if (FcPatternGetString(match, FC_FAMILY, 0, reinterpret_cast<FcChar8 **>(&family_name)) == FcResultMatch) {
+ if (family_name && String::utf8(family_name).to_lower() != p_font_name.to_lower()) {
+ FcPatternDestroy(match);
+ FcPatternDestroy(pattern);
+ continue;
+ }
+ }
+ }
+ char *file_name = nullptr;
+ if (FcPatternGetString(match, FC_FILE, 0, reinterpret_cast<FcChar8 **>(&file_name)) == FcResultMatch) {
+ if (file_name) {
+ String ret = String::utf8(file_name);
FcPatternDestroy(match);
FcPatternDestroy(pattern);
-
- return String();
+ return ret;
}
}
+ FcPatternDestroy(match);
}
- char *file_name = nullptr;
- if (FcPatternGetString(match, FC_FILE, 0, reinterpret_cast<FcChar8 **>(&file_name)) == FcResultMatch) {
- if (file_name) {
- ret = String::utf8(file_name);
- }
- }
-
- FcPatternDestroy(match);
+ FcPatternDestroy(pattern);
}
- FcPatternDestroy(pattern);
}
- return ret;
+ return String();
#else
ERR_FAIL_V_MSG(String(), "Godot was compiled without fontconfig, system font support is disabled.");
#endif
@@ -929,32 +961,41 @@ Error OS_LinuxBSD::move_to_trash(const String &p_path) {
args.push_back(path);
args.push_front("trash"); // The command is `gio trash <file_name>` so we need to add it to args.
Error result = execute("gio", args, nullptr, &err_code); // For GNOME based machines.
- if (result == OK && !err_code) {
- return OK;
- } else if (err_code == 2) {
- return ERR_FILE_NOT_FOUND;
+ if (result == OK) { // The `execute` function has done its job without errors.
+ if (!err_code) { // The shell command has been executed without errors.
+ return OK;
+ } else if (err_code == 1) {
+ ERR_PRINT("move_to_trash: No such file or directory as " + path + ".");
+ return ERR_FILE_NOT_FOUND;
+ }
}
args.pop_front();
args.push_front("move");
args.push_back("trash:/"); // The command is `kioclient5 move <file_name> trash:/`.
result = execute("kioclient5", args, nullptr, &err_code); // For KDE based machines.
- if (result == OK && !err_code) {
- return OK;
- } else if (err_code == 2) {
- return ERR_FILE_NOT_FOUND;
+ if (result == OK) { // The `execute` function has done its job without errors.
+ if (!err_code) { // The shell command has been executed without errors.
+ return OK;
+ } else if (err_code == 1) {
+ ERR_PRINT("move_to_trash: No such file or directory as " + path + ".");
+ return ERR_FILE_NOT_FOUND;
+ }
}
args.pop_front();
args.pop_back();
result = execute("gvfs-trash", args, nullptr, &err_code); // For older Linux machines.
- if (result == OK && !err_code) {
- return OK;
- } else if (err_code == 2) {
- return ERR_FILE_NOT_FOUND;
+ if (result == OK) { // The `execute` function has done its job without errors.
+ if (!err_code) { // The shell command has been executed without errors.
+ return OK;
+ } else if (err_code == 1) {
+ ERR_PRINT("move_to_trash: No such file or directory as " + path + ".");
+ return ERR_FILE_NOT_FOUND;
+ }
}
- // If the commands `kioclient5`, `gio` or `gvfs-trash` don't exist on the system we do it manually.
+ // If the commands `kioclient5`, `gio` or `gvfs-trash` don't work on the system we do it manually.
String trash_path = "";
String mnt = get_mountpoint(path);
@@ -1067,6 +1108,40 @@ Error OS_LinuxBSD::move_to_trash(const String &p_path) {
return OK;
}
+String OS_LinuxBSD::get_system_ca_certificates() {
+ String certfile;
+ Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+
+ // Compile time preferred certificates path.
+ if (!String(_SYSTEM_CERTS_PATH).is_empty() && da->file_exists(_SYSTEM_CERTS_PATH)) {
+ certfile = _SYSTEM_CERTS_PATH;
+ } else if (da->file_exists("/etc/ssl/certs/ca-certificates.crt")) {
+ // Debian/Ubuntu
+ certfile = "/etc/ssl/certs/ca-certificates.crt";
+ } else if (da->file_exists("/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem")) {
+ // Fedora
+ certfile = "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem";
+ } else if (da->file_exists("/etc/ca-certificates/extracted/tls-ca-bundle.pem")) {
+ // Arch Linux
+ certfile = "/etc/ca-certificates/extracted/tls-ca-bundle.pem";
+ } else if (da->file_exists("/var/lib/ca-certificates/ca-bundle.pem")) {
+ // openSUSE
+ certfile = "/var/lib/ca-certificates/ca-bundle.pem";
+ } else if (da->file_exists("/etc/ssl/cert.pem")) {
+ // FreeBSD/OpenBSD
+ certfile = "/etc/ssl/cert.pem";
+ }
+
+ if (certfile.is_empty()) {
+ return "";
+ }
+
+ Ref<FileAccess> f = FileAccess::open(certfile, FileAccess::READ);
+ ERR_FAIL_COND_V_MSG(f.is_null(), "", vformat("Failed to open system CA certificates file: '%s'", certfile));
+
+ return f->get_as_text();
+}
+
OS_LinuxBSD::OS_LinuxBSD() {
main_loop = nullptr;
@@ -1083,12 +1158,26 @@ OS_LinuxBSD::OS_LinuxBSD() {
#endif
#ifdef FONTCONFIG_ENABLED
+#ifdef SOWRAP_ENABLED
#ifdef DEBUG_ENABLED
int dylibloader_verbose = 1;
#else
int dylibloader_verbose = 0;
#endif
font_config_initialized = (initialize_fontconfig(dylibloader_verbose) == 0);
+#else
+ font_config_initialized = true;
+#endif
+ if (font_config_initialized) {
+ bool ver_ok = false;
+ int version = FcGetVersion();
+ ver_ok = ((version / 100 / 100) == 2 && (version / 100 % 100) >= 11) || ((version / 100 / 100) > 2); // 2.11.0
+ print_verbose(vformat("FontConfig %d.%d.%d detected.", version / 100 / 100, version / 100 % 100, version % 100));
+ if (!ver_ok) {
+ font_config_initialized = false;
+ }
+ }
+
if (font_config_initialized) {
config = FcInitLoadConfigAndFonts();
if (!config) {