summaryrefslogtreecommitdiffstats
path: root/drivers/unix
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/unix')
-rw-r--r--drivers/unix/dir_access_unix.cpp208
-rw-r--r--drivers/unix/dir_access_unix.h64
-rw-r--r--drivers/unix/file_access_unix.cpp100
-rw-r--r--drivers/unix/file_access_unix.h54
-rw-r--r--drivers/unix/ip_unix.cpp103
-rw-r--r--drivers/unix/ip_unix.h15
-rw-r--r--drivers/unix/net_socket_posix.cpp169
-rw-r--r--drivers/unix/net_socket_posix.h37
-rw-r--r--drivers/unix/os_unix.cpp265
-rw-r--r--drivers/unix/os_unix.h74
-rw-r--r--drivers/unix/rw_lock_posix.cpp93
-rw-r--r--drivers/unix/rw_lock_posix.h62
-rw-r--r--drivers/unix/syslog_logger.cpp8
-rw-r--r--drivers/unix/syslog_logger.h8
-rw-r--r--drivers/unix/thread_posix.cpp100
-rw-r--r--drivers/unix/thread_posix.h44
16 files changed, 648 insertions, 756 deletions
diff --git a/drivers/unix/dir_access_unix.cpp b/drivers/unix/dir_access_unix.cpp
index 5b99a2f53f..d894ceba59 100644
--- a/drivers/unix/dir_access_unix.cpp
+++ b/drivers/unix/dir_access_unix.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 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 */
@@ -30,29 +30,23 @@
#include "dir_access_unix.h"
-#if defined(UNIX_ENABLED) || defined(LIBC_FILEIO_ENABLED)
+#if defined(UNIX_ENABLED)
-#include "core/list.h"
#include "core/os/memory.h"
-#include "core/print_string.h"
+#include "core/os/os.h"
+#include "core/string/print_string.h"
+#include "core/templates/list.h"
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-
-#ifndef ANDROID_ENABLED
#include <sys/statvfs.h>
-#endif
#ifdef HAVE_MNTENT
#include <mntent.h>
#endif
-DirAccess *DirAccessUnix::create_fs() {
- return memnew(DirAccessUnix);
-}
-
Error DirAccessUnix::list_dir_begin() {
list_dir_end(); //close any previous dir opening!
@@ -71,13 +65,13 @@ Error DirAccessUnix::list_dir_begin() {
bool DirAccessUnix::file_exists(String p_file) {
GLOBAL_LOCK_FUNCTION
- if (p_file.is_rel_path()) {
- p_file = current_dir.plus_file(p_file);
+ if (p_file.is_relative_path()) {
+ p_file = current_dir.path_join(p_file);
}
p_file = fix_path(p_file);
- struct stat flags;
+ struct stat flags = {};
bool success = (stat(p_file.utf8().get_data(), &flags) == 0);
if (success && S_ISDIR(flags.st_mode)) {
@@ -90,35 +84,57 @@ bool DirAccessUnix::file_exists(String p_file) {
bool DirAccessUnix::dir_exists(String p_dir) {
GLOBAL_LOCK_FUNCTION
- if (p_dir.is_rel_path()) {
- p_dir = get_current_dir().plus_file(p_dir);
+ if (p_dir.is_relative_path()) {
+ p_dir = get_current_dir().path_join(p_dir);
}
p_dir = fix_path(p_dir);
- struct stat flags;
+ struct stat flags = {};
bool success = (stat(p_dir.utf8().get_data(), &flags) == 0);
return (success && S_ISDIR(flags.st_mode));
}
+bool DirAccessUnix::is_readable(String p_dir) {
+ GLOBAL_LOCK_FUNCTION
+
+ if (p_dir.is_relative_path()) {
+ p_dir = get_current_dir().path_join(p_dir);
+ }
+
+ p_dir = fix_path(p_dir);
+ return (access(p_dir.utf8().get_data(), R_OK) == 0);
+}
+
+bool DirAccessUnix::is_writable(String p_dir) {
+ GLOBAL_LOCK_FUNCTION
+
+ if (p_dir.is_relative_path()) {
+ p_dir = get_current_dir().path_join(p_dir);
+ }
+
+ p_dir = fix_path(p_dir);
+ return (access(p_dir.utf8().get_data(), W_OK) == 0);
+}
+
uint64_t DirAccessUnix::get_modified_time(String p_file) {
- if (p_file.is_rel_path()) {
- p_file = current_dir.plus_file(p_file);
+ if (p_file.is_relative_path()) {
+ p_file = current_dir.path_join(p_file);
}
p_file = fix_path(p_file);
- struct stat flags;
+ struct stat flags = {};
bool success = (stat(p_file.utf8().get_data(), &flags) == 0);
if (success) {
return flags.st_mtime;
} else {
ERR_FAIL_V(0);
- };
+ }
return 0;
-};
+}
String DirAccessUnix::get_next() {
if (!dir_stream) {
@@ -140,9 +156,9 @@ String DirAccessUnix::get_next() {
// known if it points to a directory. stat() will resolve the link
// for us.
if (entry->d_type == DT_UNKNOWN || entry->d_type == DT_LNK) {
- String f = current_dir.plus_file(fname);
+ String f = current_dir.path_join(fname);
- struct stat flags;
+ struct stat flags = {};
if (stat(f.utf8().get_data(), &flags) == 0) {
_cisdir = S_ISDIR(flags.st_mode);
} else {
@@ -194,8 +210,11 @@ static bool _filter_drive(struct mntent *mnt) {
#endif
static void _get_drives(List<String> *list) {
+ // Add root.
+ list->push_back("/");
+
#if defined(HAVE_MNTENT) && defined(X11_ENABLED)
- // Check /etc/mtab for the list of mounted partitions
+ // Check /etc/mtab for the list of mounted partitions.
FILE *mtab = setmntent("/etc/mtab", "r");
if (mtab) {
struct mntent mnt;
@@ -204,8 +223,9 @@ static void _get_drives(List<String> *list) {
while (getmntent_r(mtab, &mnt, strings, sizeof(strings))) {
if (mnt.mnt_dir != nullptr && _filter_drive(&mnt)) {
// Avoid duplicates
- if (!list->find(mnt.mnt_dir)) {
- list->push_back(mnt.mnt_dir);
+ String name = String::utf8(mnt.mnt_dir);
+ if (!list->find(name)) {
+ list->push_back(name);
}
}
}
@@ -214,15 +234,17 @@ static void _get_drives(List<String> *list) {
}
#endif
- // Add $HOME
+ // Add $HOME.
const char *home = getenv("HOME");
if (home) {
// Only add if it's not a duplicate
- if (!list->find(home)) {
- list->push_back(home);
+ String home_name = String::utf8(home);
+ if (!list->find(home_name)) {
+ list->push_back(home_name);
}
- // Check $HOME/.config/gtk-3.0/bookmarks
+ // Check GTK+3 bookmarks for both XDG locations (Documents, Downloads, etc.)
+ // and potential user-defined bookmarks.
char path[1024];
snprintf(path, 1024, "%s/.config/gtk-3.0/bookmarks", home);
FILE *fd = fopen(path, "r");
@@ -231,8 +253,8 @@ static void _get_drives(List<String> *list) {
while (fgets(string, 1024, fd)) {
// Parse only file:// links
if (strncmp(string, "file://", 7) == 0) {
- // Strip any unwanted edges on the strings and push_back if it's not a duplicate
- String fpath = String(string + 7).strip_edges().split_spaces()[0].percent_decode();
+ // Strip any unwanted edges on the strings and push_back if it's not a duplicate.
+ String fpath = String::utf8(string + 7).strip_edges().split_spaces()[0].uri_decode();
if (!list->find(fpath)) {
list->push_back(fpath);
}
@@ -241,6 +263,12 @@ static void _get_drives(List<String> *list) {
fclose(fd);
}
+
+ // Add Desktop dir.
+ String dpath = OS::get_singleton()->get_system_dir(OS::SystemDir::SYSTEM_DIR_DESKTOP);
+ if (dpath.length() > 0 && !list->find(dpath)) {
+ list->push_back(dpath);
+ }
}
list->sort();
@@ -262,6 +290,20 @@ String DirAccessUnix::get_drive(int p_drive) {
return list[p_drive];
}
+int DirAccessUnix::get_current_drive() {
+ int drive = 0;
+ int max_length = -1;
+ const String path = get_current_dir().to_lower();
+ for (int i = 0; i < get_drive_count(); i++) {
+ const String d = get_drive(i).to_lower();
+ if (max_length < d.length() && path.begins_with(d)) {
+ max_length = d.length();
+ drive = i;
+ }
+ }
+ return drive;
+}
+
bool DirAccessUnix::drives_are_shortcuts() {
return true;
}
@@ -269,8 +311,8 @@ bool DirAccessUnix::drives_are_shortcuts() {
Error DirAccessUnix::make_dir(String p_dir) {
GLOBAL_LOCK_FUNCTION
- if (p_dir.is_rel_path()) {
- p_dir = get_current_dir().plus_file(p_dir);
+ if (p_dir.is_relative_path()) {
+ p_dir = get_current_dir().path_join(p_dir);
}
p_dir = fix_path(p_dir);
@@ -280,11 +322,11 @@ Error DirAccessUnix::make_dir(String p_dir) {
if (success) {
return OK;
- };
+ }
if (err == EEXIST) {
return ERR_ALREADY_EXISTS;
- };
+ }
return ERR_CANT_CREATE;
}
@@ -298,14 +340,14 @@ Error DirAccessUnix::change_dir(String p_dir) {
String prev_dir;
char real_current_dir_name[2048];
ERR_FAIL_COND_V(getcwd(real_current_dir_name, 2048) == nullptr, ERR_BUG);
- if (prev_dir.parse_utf8(real_current_dir_name)) {
+ if (prev_dir.parse_utf8(real_current_dir_name) != OK) {
prev_dir = real_current_dir_name; //no utf8, maybe latin?
}
// try_dir is the directory we are trying to change into
String try_dir = "";
- if (p_dir.is_rel_path()) {
- String next_dir = current_dir.plus_file(p_dir);
+ if (p_dir.is_relative_path()) {
+ String next_dir = current_dir.path_join(p_dir);
next_dir = next_dir.simplify_path();
try_dir = next_dir;
} else {
@@ -318,7 +360,7 @@ Error DirAccessUnix::change_dir(String p_dir) {
}
String base = _get_root_path();
- if (base != String() && !try_dir.begins_with(base)) {
+ if (!base.is_empty() && !try_dir.begins_with(base)) {
ERR_FAIL_COND_V(getcwd(real_current_dir_name, 2048) == nullptr, ERR_BUG);
String new_dir;
new_dir.parse_utf8(real_current_dir_name);
@@ -334,9 +376,9 @@ Error DirAccessUnix::change_dir(String p_dir) {
return OK;
}
-String DirAccessUnix::get_current_dir(bool p_include_drive) {
+String DirAccessUnix::get_current_dir(bool p_include_drive) const {
String base = _get_root_path();
- if (base != "") {
+ if (!base.is_empty()) {
String bd = current_dir.replace_first(base, "");
if (bd.begins_with("/")) {
return _get_root_string() + bd.substr(1, bd.length());
@@ -348,14 +390,14 @@ String DirAccessUnix::get_current_dir(bool p_include_drive) {
}
Error DirAccessUnix::rename(String p_path, String p_new_path) {
- if (p_path.is_rel_path()) {
- p_path = get_current_dir().plus_file(p_path);
+ if (p_path.is_relative_path()) {
+ p_path = get_current_dir().path_join(p_path);
}
p_path = fix_path(p_path);
- if (p_new_path.is_rel_path()) {
- p_new_path = get_current_dir().plus_file(p_new_path);
+ if (p_new_path.is_relative_path()) {
+ p_new_path = get_current_dir().path_join(p_new_path);
}
p_new_path = fix_path(p_new_path);
@@ -364,13 +406,13 @@ Error DirAccessUnix::rename(String p_path, String p_new_path) {
}
Error DirAccessUnix::remove(String p_path) {
- if (p_path.is_rel_path()) {
- p_path = get_current_dir().plus_file(p_path);
+ if (p_path.is_relative_path()) {
+ p_path = get_current_dir().path_join(p_path);
}
p_path = fix_path(p_path);
- struct stat flags;
+ struct stat flags = {};
if ((stat(p_path.utf8().get_data(), &flags) != 0)) {
return FAILED;
}
@@ -382,19 +424,61 @@ Error DirAccessUnix::remove(String p_path) {
}
}
-size_t DirAccessUnix::get_space_left() {
-#ifndef NO_STATVFS
+bool DirAccessUnix::is_link(String p_file) {
+ if (p_file.is_relative_path()) {
+ p_file = get_current_dir().path_join(p_file);
+ }
+
+ p_file = fix_path(p_file);
+
+ struct stat flags = {};
+ if ((lstat(p_file.utf8().get_data(), &flags) != 0)) {
+ return FAILED;
+ }
+
+ return S_ISLNK(flags.st_mode);
+}
+
+String DirAccessUnix::read_link(String p_file) {
+ if (p_file.is_relative_path()) {
+ p_file = get_current_dir().path_join(p_file);
+ }
+
+ p_file = fix_path(p_file);
+
+ char buf[256];
+ memset(buf, 0, 256);
+ ssize_t len = readlink(p_file.utf8().get_data(), buf, sizeof(buf));
+ String link;
+ if (len > 0) {
+ link.parse_utf8(buf, len);
+ }
+ return link;
+}
+
+Error DirAccessUnix::create_link(String p_source, String p_target) {
+ if (p_target.is_relative_path()) {
+ p_target = get_current_dir().path_join(p_target);
+ }
+
+ p_source = fix_path(p_source);
+ p_target = fix_path(p_target);
+
+ if (symlink(p_source.utf8().get_data(), p_target.utf8().get_data()) == 0) {
+ return OK;
+ } else {
+ return FAILED;
+ }
+}
+
+uint64_t DirAccessUnix::get_space_left() {
struct statvfs vfs;
if (statvfs(current_dir.utf8().get_data(), &vfs) != 0) {
return 0;
- };
+ }
- return vfs.f_bfree * vfs.f_bsize;
-#else
- // FIXME: Implement this.
- return 0;
-#endif
-};
+ return (uint64_t)vfs.f_bavail * (uint64_t)vfs.f_frsize;
+}
String DirAccessUnix::get_filesystem_type() const {
return ""; //TODO this should be implemented
@@ -413,7 +497,7 @@ DirAccessUnix::DirAccessUnix() {
// set current directory to an absolute path of the current directory
char real_current_dir_name[2048];
ERR_FAIL_COND(getcwd(real_current_dir_name, 2048) == nullptr);
- if (current_dir.parse_utf8(real_current_dir_name)) {
+ if (current_dir.parse_utf8(real_current_dir_name) != OK) {
current_dir = real_current_dir_name;
}
@@ -424,4 +508,4 @@ DirAccessUnix::~DirAccessUnix() {
list_dir_end();
}
-#endif //posix_enabled
+#endif // UNIX_ENABLED
diff --git a/drivers/unix/dir_access_unix.h b/drivers/unix/dir_access_unix.h
index 90f98d4705..4db24a27b9 100644
--- a/drivers/unix/dir_access_unix.h
+++ b/drivers/unix/dir_access_unix.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 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 */
@@ -31,9 +31,9 @@
#ifndef DIR_ACCESS_UNIX_H
#define DIR_ACCESS_UNIX_H
-#if defined(UNIX_ENABLED) || defined(LIBC_FILEIO_ENABLED)
+#if defined(UNIX_ENABLED)
-#include "core/os/dir_access.h"
+#include "core/io/dir_access.h"
#include <dirent.h>
#include <sys/stat.h>
@@ -41,49 +41,55 @@
#include <unistd.h>
class DirAccessUnix : public DirAccess {
- DIR *dir_stream;
+ DIR *dir_stream = nullptr;
- static DirAccess *create_fs();
-
- String current_dir;
- bool _cisdir;
- bool _cishidden;
+ bool _cisdir = false;
+ bool _cishidden = false;
protected:
+ String current_dir;
virtual String fix_unicode_name(const char *p_name) const { return String::utf8(p_name); }
virtual bool is_hidden(const String &p_name);
public:
- virtual Error list_dir_begin(); ///< This starts dir listing
- virtual String get_next();
- virtual bool current_is_dir() const;
- virtual bool current_is_hidden() const;
+ virtual Error list_dir_begin() override; ///< This starts dir listing
+ virtual String get_next() override;
+ virtual bool current_is_dir() const override;
+ virtual bool current_is_hidden() const override;
- virtual void list_dir_end(); ///<
+ virtual void list_dir_end() override; ///<
- virtual int get_drive_count();
- virtual String get_drive(int p_drive);
- virtual bool drives_are_shortcuts();
+ virtual int get_drive_count() override;
+ virtual String get_drive(int p_drive) override;
+ virtual int get_current_drive() override;
+ virtual bool drives_are_shortcuts() override;
- virtual Error change_dir(String p_dir); ///< can be relative or absolute, return false on success
- virtual String get_current_dir(bool p_include_drive = true); ///< return current dir location
- virtual Error make_dir(String p_dir);
+ virtual Error change_dir(String p_dir) override; ///< can be relative or absolute, return false on success
+ virtual String get_current_dir(bool p_include_drive = true) const override; ///< return current dir location
+ virtual Error make_dir(String p_dir) override;
- virtual bool file_exists(String p_file);
- virtual bool dir_exists(String p_dir);
+ virtual bool file_exists(String p_file) override;
+ virtual bool dir_exists(String p_dir) override;
+ virtual bool is_readable(String p_dir) override;
+ virtual bool is_writable(String p_dir) override;
virtual uint64_t get_modified_time(String p_file);
- virtual Error rename(String p_path, String p_new_path);
- virtual Error remove(String p_path);
+ virtual Error rename(String p_path, String p_new_path) override;
+ virtual Error remove(String p_path) override;
- virtual size_t get_space_left();
+ virtual bool is_link(String p_file) override;
+ virtual String read_link(String p_file) override;
+ virtual Error create_link(String p_source, String p_target) override;
- virtual String get_filesystem_type() const;
+ virtual uint64_t get_space_left() override;
+
+ virtual String get_filesystem_type() const override;
DirAccessUnix();
~DirAccessUnix();
};
-#endif //UNIX ENABLED
-#endif
+#endif // UNIX_ENABLED
+
+#endif // DIR_ACCESS_UNIX_H
diff --git a/drivers/unix/file_access_unix.cpp b/drivers/unix/file_access_unix.cpp
index 51c657007c..0b80fb1491 100644
--- a/drivers/unix/file_access_unix.cpp
+++ b/drivers/unix/file_access_unix.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 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 */
@@ -30,24 +30,20 @@
#include "file_access_unix.h"
-#if defined(UNIX_ENABLED) || defined(LIBC_FILEIO_ENABLED)
+#if defined(UNIX_ENABLED)
#include "core/os/os.h"
-#include "core/print_string.h"
+#include "core/string/print_string.h"
+#include <errno.h>
+#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
-#include <errno.h>
-
#if defined(UNIX_ENABLED)
#include <unistd.h>
#endif
-#ifndef ANDROID_ENABLED
-#include <sys/statvfs.h>
-#endif
-
#ifdef MSVC
#define S_ISREG(m) ((m)&_S_IFREG)
#include <io.h>
@@ -56,12 +52,6 @@
#define S_ISREG(m) ((m)&S_IFREG)
#endif
-#ifndef NO_FCNTL
-#include <fcntl.h>
-#else
-#include <sys/ioctl.h>
-#endif
-
void FileAccessUnix::check_errors() const {
ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
@@ -70,11 +60,8 @@ void FileAccessUnix::check_errors() const {
}
}
-Error FileAccessUnix::_open(const String &p_path, int p_mode_flags) {
- if (f) {
- fclose(f);
- }
- f = nullptr;
+Error FileAccessUnix::open_internal(const String &p_path, int p_mode_flags) {
+ _close();
path_src = p_path;
path = fix_path(p_path);
@@ -99,7 +86,7 @@ Error FileAccessUnix::_open(const String &p_path, int p_mode_flags) {
backend (unix-compatible mostly) supports utf8 encoding */
//printf("opening %s as %s\n", p_path.utf8().get_data(), path.utf8().get_data());
- struct stat st;
+ struct stat st = {};
int err = stat(path.utf8().get_data(), &st);
if (!err) {
switch (st.st_mode & S_IFMT) {
@@ -111,7 +98,7 @@ Error FileAccessUnix::_open(const String &p_path, int p_mode_flags) {
}
}
- if (is_backup_save_enabled() && (p_mode_flags & WRITE) && !(p_mode_flags & READ)) {
+ if (is_backup_save_enabled() && (p_mode_flags == WRITE)) {
save_path = path;
path = path + ".tmp";
}
@@ -134,13 +121,8 @@ Error FileAccessUnix::_open(const String &p_path, int p_mode_flags) {
int fd = fileno(f);
if (fd != -1) {
-#if defined(NO_FCNTL)
- unsigned long par = 0;
- ioctl(fd, FIOCLEX, &par);
-#else
int opts = fcntl(fd, F_GETFD);
fcntl(fd, F_SETFD, opts | FD_CLOEXEC);
-#endif
}
last_error = OK;
@@ -148,7 +130,7 @@ Error FileAccessUnix::_open(const String &p_path, int p_mode_flags) {
return OK;
}
-void FileAccessUnix::close() {
+void FileAccessUnix::_close() {
if (!f) {
return;
}
@@ -160,7 +142,7 @@ void FileAccessUnix::close() {
close_notification_func(path, flags);
}
- if (save_path != "") {
+ if (!save_path.is_empty()) {
int rename_error = rename((save_path + ".tmp").utf8().get_data(), save_path.utf8().get_data());
if (rename_error && close_fail_notify) {
@@ -184,11 +166,11 @@ String FileAccessUnix::get_path_absolute() const {
return path;
}
-void FileAccessUnix::seek(size_t p_position) {
+void FileAccessUnix::seek(uint64_t p_position) {
ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
last_error = OK;
- if (fseek(f, p_position, SEEK_SET)) {
+ if (fseeko(f, p_position, SEEK_SET)) {
check_errors();
}
}
@@ -196,15 +178,15 @@ void FileAccessUnix::seek(size_t p_position) {
void FileAccessUnix::seek_end(int64_t p_position) {
ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
- if (fseek(f, p_position, SEEK_END)) {
+ if (fseeko(f, p_position, SEEK_END)) {
check_errors();
}
}
-size_t FileAccessUnix::get_position() const {
+uint64_t FileAccessUnix::get_position() const {
ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use.");
- long pos = ftell(f);
+ int64_t pos = ftello(f);
if (pos < 0) {
check_errors();
ERR_FAIL_V(0);
@@ -212,15 +194,15 @@ size_t FileAccessUnix::get_position() const {
return pos;
}
-size_t FileAccessUnix::get_len() const {
+uint64_t FileAccessUnix::get_length() const {
ERR_FAIL_COND_V_MSG(!f, 0, "File must be opened before use.");
- long pos = ftell(f);
+ int64_t pos = ftello(f);
ERR_FAIL_COND_V(pos < 0, 0);
- ERR_FAIL_COND_V(fseek(f, 0, SEEK_END), 0);
- long size = ftell(f);
+ ERR_FAIL_COND_V(fseeko(f, 0, SEEK_END), 0);
+ int64_t size = ftello(f);
ERR_FAIL_COND_V(size < 0, 0);
- ERR_FAIL_COND_V(fseek(f, pos, SEEK_SET), 0);
+ ERR_FAIL_COND_V(fseeko(f, pos, SEEK_SET), 0);
return size;
}
@@ -239,12 +221,14 @@ uint8_t FileAccessUnix::get_8() const {
return b;
}
-int FileAccessUnix::get_buffer(uint8_t *p_dst, int p_length) const {
+uint64_t FileAccessUnix::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
+ ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
ERR_FAIL_COND_V_MSG(!f, -1, "File must be opened before use.");
- int read = fread(p_dst, 1, p_length, f);
+
+ uint64_t read = fread(p_dst, 1, p_length, f);
check_errors();
return read;
-};
+}
Error FileAccessUnix::get_error() const {
return last_error;
@@ -260,15 +244,15 @@ void FileAccessUnix::store_8(uint8_t p_dest) {
ERR_FAIL_COND(fwrite(&p_dest, 1, 1, f) != 1);
}
-void FileAccessUnix::store_buffer(const uint8_t *p_src, int p_length) {
+void FileAccessUnix::store_buffer(const uint8_t *p_src, uint64_t p_length) {
ERR_FAIL_COND_MSG(!f, "File must be opened before use.");
- ERR_FAIL_COND(!p_src);
- ERR_FAIL_COND((int)fwrite(p_src, 1, p_length, f) != p_length);
+ ERR_FAIL_COND(!p_src && p_length > 0);
+ ERR_FAIL_COND(fwrite(p_src, 1, p_length, f) != p_length);
}
bool FileAccessUnix::file_exists(const String &p_path) {
int err;
- struct stat st;
+ struct stat st = {};
String filename = fix_path(p_path);
// Does the name exist at all?
@@ -283,8 +267,9 @@ bool FileAccessUnix::file_exists(const String &p_path) {
return false;
}
#else
- if (_access(filename.utf8().get_data(), 4) == -1)
+ if (_access(filename.utf8().get_data(), 4) == -1) {
return false;
+ }
#endif
// See if this is a regular file
@@ -299,26 +284,27 @@ bool FileAccessUnix::file_exists(const String &p_path) {
uint64_t FileAccessUnix::_get_modified_time(const String &p_file) {
String file = fix_path(p_file);
- struct stat flags;
+ struct stat flags = {};
int err = stat(file.utf8().get_data(), &flags);
if (!err) {
return flags.st_mtime;
} else {
- ERR_FAIL_V_MSG(0, "Failed to get modified time for: " + p_file + ".");
- };
+ print_verbose("Failed to get modified time for: " + p_file + "");
+ return 0;
+ }
}
uint32_t FileAccessUnix::_get_unix_permissions(const String &p_file) {
String file = fix_path(p_file);
- struct stat flags;
+ struct stat flags = {};
int err = stat(file.utf8().get_data(), &flags);
if (!err) {
return flags.st_mode & 0x7FF; //only permissions
} else {
ERR_FAIL_V_MSG(0, "Failed to get unix permissions for: " + p_file + ".");
- };
+ }
}
Error FileAccessUnix::_set_unix_permissions(const String &p_file, uint32_t p_permissions) {
@@ -332,14 +318,10 @@ Error FileAccessUnix::_set_unix_permissions(const String &p_file, uint32_t p_per
return FAILED;
}
-FileAccess *FileAccessUnix::create_libc() {
- return memnew(FileAccessUnix);
-}
-
CloseNotificationFunc FileAccessUnix::close_notification_func = nullptr;
FileAccessUnix::~FileAccessUnix() {
- close();
+ _close();
}
-#endif
+#endif // UNIX_ENABLED
diff --git a/drivers/unix/file_access_unix.h b/drivers/unix/file_access_unix.h
index 9fe43a2554..8c9afe75e7 100644
--- a/drivers/unix/file_access_unix.h
+++ b/drivers/unix/file_access_unix.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 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 */
@@ -31,12 +31,12 @@
#ifndef FILE_ACCESS_UNIX_H
#define FILE_ACCESS_UNIX_H
-#include "core/os/file_access.h"
+#include "core/io/file_access.h"
#include "core/os/memory.h"
#include <stdio.h>
-#if defined(UNIX_ENABLED) || defined(LIBC_FILEIO_ENABLED)
+#if defined(UNIX_ENABLED)
typedef void (*CloseNotificationFunc)(const String &p_file, int p_flags);
@@ -49,43 +49,43 @@ class FileAccessUnix : public FileAccess {
String path;
String path_src;
- static FileAccess *create_libc();
+ void _close();
public:
static CloseNotificationFunc close_notification_func;
- virtual Error _open(const String &p_path, int p_mode_flags); ///< open a file
- virtual void close(); ///< close a file
- virtual bool is_open() const; ///< true when file is open
+ virtual Error open_internal(const String &p_path, int p_mode_flags) override; ///< open a file
+ virtual bool is_open() const override; ///< true when file is open
- virtual String get_path() const; /// returns the path for the current open file
- virtual String get_path_absolute() const; /// returns the absolute path for the current open file
+ virtual String get_path() const override; /// returns the path for the current open file
+ virtual String get_path_absolute() const override; /// returns the absolute path for the current open file
- virtual void seek(size_t p_position); ///< seek to a given position
- virtual void seek_end(int64_t p_position = 0); ///< seek from the end of file
- virtual size_t get_position() const; ///< get position in the file
- virtual size_t get_len() const; ///< get size of the file
+ virtual void seek(uint64_t p_position) override; ///< seek to a given position
+ virtual void seek_end(int64_t p_position = 0) override; ///< seek from the end of file
+ virtual uint64_t get_position() const override; ///< get position in the file
+ virtual uint64_t get_length() const override; ///< get size of the file
- virtual bool eof_reached() const; ///< reading passed EOF
+ virtual bool eof_reached() const override; ///< reading passed EOF
- virtual uint8_t get_8() const; ///< get a byte
- virtual int get_buffer(uint8_t *p_dst, int p_length) const;
+ virtual uint8_t get_8() const override; ///< get a byte
+ virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const override;
- virtual Error get_error() const; ///< get last error
+ virtual Error get_error() const override; ///< get last error
- virtual void flush();
- virtual void store_8(uint8_t p_dest); ///< store a byte
- virtual void store_buffer(const uint8_t *p_src, int p_length); ///< store an array of bytes
+ virtual void flush() override;
+ virtual void store_8(uint8_t p_dest) override; ///< store a byte
+ virtual void store_buffer(const uint8_t *p_src, uint64_t p_length) override; ///< store an array of bytes
- virtual bool file_exists(const String &p_path); ///< return true if a file exists
+ virtual bool file_exists(const String &p_path) override; ///< return true if a file exists
- virtual uint64_t _get_modified_time(const String &p_file);
- virtual uint32_t _get_unix_permissions(const String &p_file);
- virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions);
+ virtual uint64_t _get_modified_time(const String &p_file) override;
+ virtual uint32_t _get_unix_permissions(const String &p_file) override;
+ virtual Error _set_unix_permissions(const String &p_file, uint32_t p_permissions) override;
FileAccessUnix() {}
virtual ~FileAccessUnix();
};
-#endif
-#endif
+#endif // UNIX_ENABLED
+
+#endif // FILE_ACCESS_UNIX_H
diff --git a/drivers/unix/ip_unix.cpp b/drivers/unix/ip_unix.cpp
index 05eedccc1d..0dc2efedc1 100644
--- a/drivers/unix/ip_unix.cpp
+++ b/drivers/unix/ip_unix.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 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 */
@@ -36,24 +36,12 @@
#ifdef WINDOWS_ENABLED
#include <stdio.h>
-#include <winsock2.h>
-// Needs to be included after winsocks2.h
+#define WIN32_LEAN_AND_MEAN
#include <windows.h>
+#include <winsock2.h>
#include <ws2tcpip.h>
#ifndef UWP_ENABLED
-#if defined(__MINGW32__) && (!defined(__MINGW64_VERSION_MAJOR) || __MINGW64_VERSION_MAJOR < 4)
-// MinGW-w64 on Ubuntu 12.04 (our Travis build env) has bugs in this code where
-// some includes are missing in dependencies of iphlpapi.h for WINVER >= 0x0600 (Vista).
-// We don't use this Vista code for now, so working it around by disabling it.
-// MinGW-w64 >= 4.0 seems to be better judging by its headers.
-#undef _WIN32_WINNT
-#define _WIN32_WINNT 0x0501 // Windows XP, disable Vista API
-#include <iphlpapi.h>
-#undef _WIN32_WINNT
-#define _WIN32_WINNT 0x0600 // Re-enable Vista API
-#else
#include <iphlpapi.h>
-#endif // MINGW hack
#endif
#else // UNIX
#include <netdb.h>
@@ -75,8 +63,8 @@
#include <net/if.h> // Order is important on OpenBSD, leave as last
#endif
-static IP_Address _sockaddr2ip(struct sockaddr *p_addr) {
- IP_Address ip;
+static IPAddress _sockaddr2ip(struct sockaddr *p_addr) {
+ IPAddress ip;
if (p_addr->sa_family == AF_INET) {
struct sockaddr_in *addr = (struct sockaddr_in *)p_addr;
@@ -84,14 +72,14 @@ static IP_Address _sockaddr2ip(struct sockaddr *p_addr) {
} else if (p_addr->sa_family == AF_INET6) {
struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)p_addr;
ip.set_ipv6(addr6->sin6_addr.s6_addr);
- };
+ }
return ip;
-};
+}
-IP_Address IP_Unix::_resolve_hostname(const String &p_hostname, Type p_type) {
+void IPUnix::_resolve_hostname(List<IPAddress> &r_addresses, const String &p_hostname, Type p_type) const {
struct addrinfo hints;
- struct addrinfo *result;
+ struct addrinfo *result = nullptr;
memset(&hints, 0, sizeof(struct addrinfo));
if (p_type == TYPE_IPV4) {
@@ -102,35 +90,45 @@ IP_Address IP_Unix::_resolve_hostname(const String &p_hostname, Type p_type) {
} else {
hints.ai_family = AF_UNSPEC;
hints.ai_flags = AI_ADDRCONFIG;
- };
+ }
hints.ai_flags &= ~AI_NUMERICHOST;
int s = getaddrinfo(p_hostname.utf8().get_data(), nullptr, &hints, &result);
if (s != 0) {
- ERR_PRINT("getaddrinfo failed! Cannot resolve hostname.");
- return IP_Address();
- };
+ print_verbose("getaddrinfo failed! Cannot resolve hostname.");
+ return;
+ }
if (result == nullptr || result->ai_addr == nullptr) {
- ERR_PRINT("Invalid response from getaddrinfo");
+ print_verbose("Invalid response from getaddrinfo");
if (result) {
freeaddrinfo(result);
}
- return IP_Address();
- };
+ return;
+ }
- IP_Address ip = _sockaddr2ip(result->ai_addr);
+ struct addrinfo *next = result;
- freeaddrinfo(result);
+ do {
+ if (next->ai_addr == nullptr) {
+ next = next->ai_next;
+ continue;
+ }
+ IPAddress ip = _sockaddr2ip(next->ai_addr);
+ if (ip.is_valid() && !r_addresses.find(ip)) {
+ r_addresses.push_back(ip);
+ }
+ next = next->ai_next;
+ } while (next);
- return ip;
+ freeaddrinfo(result);
}
#if defined(WINDOWS_ENABLED)
#if defined(UWP_ENABLED)
-void IP_Unix::get_local_interfaces(Map<String, Interface_Info> *r_interfaces) const {
+void IPUnix::get_local_interfaces(HashMap<String, Interface_Info> *r_interfaces) const {
using namespace Windows::Networking;
using namespace Windows::Networking::Connectivity;
@@ -140,11 +138,12 @@ void IP_Unix::get_local_interfaces(Map<String, Interface_Info> *r_interfaces) co
for (int i = 0; i < hostnames->Size; i++) {
auto hostname = hostnames->GetAt(i);
- if (hostname->Type != HostNameType::Ipv4 && hostname->Type != HostNameType::Ipv6)
+ if (hostname->Type != HostNameType::Ipv4 && hostname->Type != HostNameType::Ipv6) {
continue;
+ }
String name = hostname->RawName->Data();
- Map<String, Interface_Info>::Element *E = r_interfaces->find(name);
+ HashMap<String, Interface_Info>::Element *E = r_interfaces->find(name);
if (!E) {
Interface_Info info;
info.name = name;
@@ -156,14 +155,14 @@ void IP_Unix::get_local_interfaces(Map<String, Interface_Info> *r_interfaces) co
Interface_Info &info = E->get();
- IP_Address ip = IP_Address(hostname->CanonicalName->Data());
+ IPAddress ip = IPAddress(hostname->CanonicalName->Data());
info.ip_addresses.push_front(ip);
}
}
#else
-void IP_Unix::get_local_interfaces(Map<String, Interface_Info> *r_interfaces) const {
+void IPUnix::get_local_interfaces(HashMap<String, Interface_Info> *r_interfaces) const {
ULONG buf_size = 1024;
IP_ADAPTER_ADDRESSES *addrs;
@@ -173,14 +172,14 @@ void IP_Unix::get_local_interfaces(Map<String, Interface_Info> *r_interfaces) co
nullptr, addrs, &buf_size);
if (err == NO_ERROR) {
break;
- };
+ }
memfree(addrs);
if (err == ERROR_BUFFER_OVERFLOW) {
continue; // will go back and alloc the right size
- };
+ }
ERR_FAIL_MSG("Call to GetAdaptersAddresses failed with error " + itos(err) + ".");
- };
+ }
IP_ADAPTER_ADDRESSES *adapter = addrs;
@@ -193,25 +192,27 @@ void IP_Unix::get_local_interfaces(Map<String, Interface_Info> *r_interfaces) co
IP_ADAPTER_UNICAST_ADDRESS *address = adapter->FirstUnicastAddress;
while (address != nullptr) {
int family = address->Address.lpSockaddr->sa_family;
- if (family != AF_INET && family != AF_INET6)
+ if (family != AF_INET && family != AF_INET6) {
continue;
+ }
info.ip_addresses.push_front(_sockaddr2ip(address->Address.lpSockaddr));
address = address->Next;
}
adapter = adapter->Next;
// Only add interface if it has at least one IP
- if (info.ip_addresses.size() > 0)
+ if (info.ip_addresses.size() > 0) {
r_interfaces->insert(info.name, info);
- };
+ }
+ }
memfree(addrs);
-};
+}
#endif
#else // UNIX
-void IP_Unix::get_local_interfaces(Map<String, Interface_Info> *r_interfaces) const {
+void IPUnix::get_local_interfaces(HashMap<String, Interface_Info> *r_interfaces) const {
struct ifaddrs *ifAddrStruct = nullptr;
struct ifaddrs *ifa = nullptr;
int family;
@@ -229,7 +230,7 @@ void IP_Unix::get_local_interfaces(Map<String, Interface_Info> *r_interfaces) co
continue;
}
- Map<String, Interface_Info>::Element *E = r_interfaces->find(ifa->ifa_name);
+ HashMap<String, Interface_Info>::Iterator E = r_interfaces->find(ifa->ifa_name);
if (!E) {
Interface_Info info;
info.name = ifa->ifa_name;
@@ -239,7 +240,7 @@ void IP_Unix::get_local_interfaces(Map<String, Interface_Info> *r_interfaces) co
ERR_CONTINUE(!E);
}
- Interface_Info &info = E->get();
+ Interface_Info &info = E->value;
info.ip_addresses.push_front(_sockaddr2ip(ifa->ifa_addr));
}
@@ -249,15 +250,15 @@ void IP_Unix::get_local_interfaces(Map<String, Interface_Info> *r_interfaces) co
}
#endif
-void IP_Unix::make_default() {
+void IPUnix::make_default() {
_create = _create_unix;
}
-IP *IP_Unix::_create_unix() {
- return memnew(IP_Unix);
+IP *IPUnix::_create_unix() {
+ return memnew(IPUnix);
}
-IP_Unix::IP_Unix() {
+IPUnix::IPUnix() {
}
#endif
diff --git a/drivers/unix/ip_unix.h b/drivers/unix/ip_unix.h
index 7497f64a53..798d02095c 100644
--- a/drivers/unix/ip_unix.h
+++ b/drivers/unix/ip_unix.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 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 */
@@ -35,19 +35,20 @@
#if defined(UNIX_ENABLED) || defined(WINDOWS_ENABLED)
-class IP_Unix : public IP {
- GDCLASS(IP_Unix, IP);
+class IPUnix : public IP {
+ GDCLASS(IPUnix, IP);
- virtual IP_Address _resolve_hostname(const String &p_hostname, IP::Type p_type) override;
+ virtual void _resolve_hostname(List<IPAddress> &r_addresses, const String &p_hostname, Type p_type = TYPE_ANY) const override;
static IP *_create_unix();
public:
- virtual void get_local_interfaces(Map<String, Interface_Info> *r_interfaces) const override;
+ virtual void get_local_interfaces(HashMap<String, Interface_Info> *r_interfaces) const override;
static void make_default();
- IP_Unix();
+ IPUnix();
};
#endif
+
#endif // IP_UNIX_H
diff --git a/drivers/unix/net_socket_posix.cpp b/drivers/unix/net_socket_posix.cpp
index 186804dbb1..c6b327eeee 100644
--- a/drivers/unix/net_socket_posix.cpp
+++ b/drivers/unix/net_socket_posix.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 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 */
@@ -30,32 +30,30 @@
#include "net_socket_posix.h"
+// Some proprietary Unix-derived platforms don't expose Unix sockets
+// so this allows skipping this file to reimplement this API differently.
#ifndef UNIX_SOCKET_UNAVAILABLE
+
#if defined(UNIX_ENABLED)
#include <errno.h>
+#include <fcntl.h>
#include <netdb.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
#include <poll.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
+#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
-#ifndef NO_FCNTL
-#include <fcntl.h>
-#else
-#include <sys/ioctl.h>
-#endif
-#include <netinet/in.h>
-#include <sys/socket.h>
-#ifdef JAVASCRIPT_ENABLED
+#ifdef WEB_ENABLED
#include <arpa/inet.h>
#endif
-#include <netinet/tcp.h>
-
// BSD calls this flag IPV6_JOIN_GROUP
#if !defined(IPV6_ADD_MEMBERSHIP) && defined(IPV6_JOIN_GROUP)
#define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
@@ -93,9 +91,9 @@
#define SIO_UDP_NETRESET _WSAIOW(IOC_VENDOR, 15)
#endif
-#endif
+#endif // UNIX_ENABLED
-size_t NetSocketPosix::_set_addr_storage(struct sockaddr_storage *p_addr, const IP_Address &p_ip, uint16_t p_port, IP::Type p_ip_type) {
+size_t NetSocketPosix::_set_addr_storage(struct sockaddr_storage *p_addr, const IPAddress &p_ip, uint16_t p_port, IP::Type p_ip_type) {
memset(p_addr, 0, sizeof(struct sockaddr_storage));
if (p_ip_type == IP::TYPE_IPV6 || p_ip_type == IP::TYPE_ANY) { // IPv6 socket
@@ -106,7 +104,7 @@ size_t NetSocketPosix::_set_addr_storage(struct sockaddr_storage *p_addr, const
addr6->sin6_family = AF_INET6;
addr6->sin6_port = htons(p_port);
if (p_ip.is_valid()) {
- copymem(&addr6->sin6_addr.s6_addr, p_ip.get_ipv6(), 16);
+ memcpy(&addr6->sin6_addr.s6_addr, p_ip.get_ipv6(), 16);
} else {
addr6->sin6_addr = in6addr_any;
}
@@ -121,7 +119,7 @@ size_t NetSocketPosix::_set_addr_storage(struct sockaddr_storage *p_addr, const
addr4->sin_port = htons(p_port); // short, network byte order
if (p_ip.is_valid()) {
- copymem(&addr4->sin_addr.s_addr, p_ip.get_ipv4(), 4);
+ memcpy(&addr4->sin_addr.s_addr, p_ip.get_ipv4(), 4);
} else {
addr4->sin_addr.s_addr = INADDR_ANY;
}
@@ -130,19 +128,24 @@ size_t NetSocketPosix::_set_addr_storage(struct sockaddr_storage *p_addr, const
}
}
-void NetSocketPosix::_set_ip_port(struct sockaddr_storage *p_addr, IP_Address &r_ip, uint16_t &r_port) {
+void NetSocketPosix::_set_ip_port(struct sockaddr_storage *p_addr, IPAddress *r_ip, uint16_t *r_port) {
if (p_addr->ss_family == AF_INET) {
struct sockaddr_in *addr4 = (struct sockaddr_in *)p_addr;
- r_ip.set_ipv4((uint8_t *)&(addr4->sin_addr.s_addr));
-
- r_port = ntohs(addr4->sin_port);
-
+ if (r_ip) {
+ r_ip->set_ipv4((uint8_t *)&(addr4->sin_addr.s_addr));
+ }
+ if (r_port) {
+ *r_port = ntohs(addr4->sin_port);
+ }
} else if (p_addr->ss_family == AF_INET6) {
struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)p_addr;
- r_ip.set_ipv6(addr6->sin6_addr.s6_addr);
-
- r_port = ntohs(addr6->sin6_port);
- };
+ if (r_ip) {
+ r_ip->set_ipv6(addr6->sin6_addr.s6_addr);
+ }
+ if (r_port) {
+ *r_port = ntohs(addr6->sin6_port);
+ }
+ }
}
NetSocket *NetSocketPosix::_create_func() {
@@ -176,8 +179,8 @@ NetSocketPosix::~NetSocketPosix() {
close();
}
-// Silent a warning reported in #27594
-
+// Silence a warning reported in GH-27594.
+// EAGAIN and EWOULDBLOCK have the same value on most platforms, but it's not guaranteed.
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wlogical-op"
@@ -186,13 +189,21 @@ NetSocketPosix::~NetSocketPosix() {
NetSocketPosix::NetError NetSocketPosix::_get_socket_error() const {
#if defined(WINDOWS_ENABLED)
int err = WSAGetLastError();
-
- if (err == WSAEISCONN)
+ if (err == WSAEISCONN) {
return ERR_NET_IS_CONNECTED;
- if (err == WSAEINPROGRESS || err == WSAEALREADY)
+ }
+ if (err == WSAEINPROGRESS || err == WSAEALREADY) {
return ERR_NET_IN_PROGRESS;
- if (err == WSAEWOULDBLOCK)
+ }
+ if (err == WSAEWOULDBLOCK) {
return ERR_NET_WOULD_BLOCK;
+ }
+ if (err == WSAEADDRINUSE || err == WSAEADDRNOTAVAIL) {
+ return ERR_NET_ADDRESS_INVALID_OR_UNAVAILABLE;
+ }
+ if (err == WSAEACCES) {
+ return ERR_NET_UNAUTHORIZED;
+ }
print_verbose("Socket error: " + itos(err));
return ERR_NET_OTHER;
#else
@@ -205,6 +216,12 @@ NetSocketPosix::NetError NetSocketPosix::_get_socket_error() const {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
return ERR_NET_WOULD_BLOCK;
}
+ if (errno == EADDRINUSE || errno == EINVAL || errno == EADDRNOTAVAIL) {
+ return ERR_NET_ADDRESS_INVALID_OR_UNAVAILABLE;
+ }
+ if (errno == EACCES) {
+ return ERR_NET_UNAUTHORIZED;
+ }
print_verbose("Socket error: " + itos(errno));
return ERR_NET_OTHER;
#endif
@@ -214,7 +231,7 @@ NetSocketPosix::NetError NetSocketPosix::_get_socket_error() const {
#pragma GCC diagnostic pop
#endif
-bool NetSocketPosix::_can_use_ip(const IP_Address &p_ip, const bool p_for_bind) const {
+bool NetSocketPosix::_can_use_ip(const IPAddress &p_ip, const bool p_for_bind) const {
if (p_for_bind && !(p_ip.is_valid() || p_ip.is_wildcard())) {
return false;
} else if (!p_for_bind && !p_ip.is_valid()) {
@@ -225,7 +242,7 @@ bool NetSocketPosix::_can_use_ip(const IP_Address &p_ip, const bool p_for_bind)
return !(_ip_type != IP::TYPE_ANY && !p_ip.is_wildcard() && _ip_type != type);
}
-_FORCE_INLINE_ Error NetSocketPosix::_change_multicast_group(IP_Address p_ip, String p_if_name, bool p_add) {
+_FORCE_INLINE_ Error NetSocketPosix::_change_multicast_group(IPAddress p_ip, String p_if_name, bool p_add) {
ERR_FAIL_COND_V(!is_open(), ERR_UNCONFIGURED);
ERR_FAIL_COND_V(!_can_use_ip(p_ip, false), ERR_INVALID_PARAMETER);
@@ -235,12 +252,12 @@ _FORCE_INLINE_ Error NetSocketPosix::_change_multicast_group(IP_Address p_ip, St
int level = type == IP::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6;
int ret = -1;
- IP_Address if_ip;
+ IPAddress if_ip;
uint32_t if_v6id = 0;
- Map<String, IP::Interface_Info> if_info;
+ HashMap<String, IP::Interface_Info> if_info;
IP::get_singleton()->get_local_interfaces(&if_info);
- for (Map<String, IP::Interface_Info>::Element *E = if_info.front(); E; E = E->next()) {
- IP::Interface_Info &c = E->get();
+ for (KeyValue<String, IP::Interface_Info> &E : if_info) {
+ IP::Interface_Info &c = E.value;
if (c.name != p_if_name) {
continue;
}
@@ -250,11 +267,11 @@ _FORCE_INLINE_ Error NetSocketPosix::_change_multicast_group(IP_Address p_ip, St
break; // IPv6 uses index.
}
- for (List<IP_Address>::Element *F = c.ip_addresses.front(); F; F = F->next()) {
- if (!F->get().is_ipv4()) {
+ for (const IPAddress &F : c.ip_addresses) {
+ if (!F.is_ipv4()) {
continue; // Wrong IP type
}
- if_ip = F->get();
+ if_ip = F;
break;
}
break;
@@ -264,13 +281,13 @@ _FORCE_INLINE_ Error NetSocketPosix::_change_multicast_group(IP_Address p_ip, St
ERR_FAIL_COND_V(!if_ip.is_valid(), ERR_INVALID_PARAMETER);
struct ip_mreq greq;
int sock_opt = p_add ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP;
- copymem(&greq.imr_multiaddr, p_ip.get_ipv4(), 4);
- copymem(&greq.imr_interface, if_ip.get_ipv4(), 4);
+ memcpy(&greq.imr_multiaddr, p_ip.get_ipv4(), 4);
+ memcpy(&greq.imr_interface, if_ip.get_ipv4(), 4);
ret = setsockopt(_sock, level, sock_opt, (const char *)&greq, sizeof(greq));
} else {
struct ipv6_mreq greq;
int sock_opt = p_add ? IPV6_ADD_MEMBERSHIP : IPV6_DROP_MEMBERSHIP;
- copymem(&greq.ipv6mr_multiaddr, p_ip.get_ipv6(), 16);
+ memcpy(&greq.ipv6mr_multiaddr, p_ip.get_ipv6(), 16);
greq.ipv6mr_interface = if_v6id;
ret = setsockopt(_sock, level, sock_opt, (const char *)&greq, sizeof(greq));
}
@@ -290,14 +307,9 @@ void NetSocketPosix::_set_socket(SOCKET_TYPE p_sock, IP::Type p_ip_type, bool p_
void NetSocketPosix::_set_close_exec_enabled(bool p_enabled) {
#ifndef WINDOWS_ENABLED
// Enable close on exec to avoid sharing with subprocesses. Off by default on Windows.
-#if defined(NO_FCNTL)
- unsigned long par = p_enabled ? 1 : 0;
- SOCK_IOCTL(_sock, FIOCLEX, &par);
-#else
int opts = fcntl(_sock, F_GETFD);
fcntl(_sock, F_SETFD, opts | FD_CLOEXEC);
#endif
-#endif
}
Error NetSocketPosix::open(Type p_sock_type, IP::Type &ip_type) {
@@ -306,8 +318,9 @@ Error NetSocketPosix::open(Type p_sock_type, IP::Type &ip_type) {
#if defined(__OpenBSD__)
// OpenBSD does not support dual stacking, fallback to IPv4 only.
- if (ip_type == IP::TYPE_ANY)
+ if (ip_type == IP::TYPE_ANY) {
ip_type = IP::TYPE_IPV4;
+ }
#endif
int family = ip_type == IP::TYPE_IPV4 ? AF_INET : AF_INET6;
@@ -348,11 +361,11 @@ Error NetSocketPosix::open(Type p_sock_type, IP::Type &ip_type) {
// recv/recvfrom and an ICMP reply was received from a previous send/sendto.
unsigned long disable = 0;
if (ioctlsocket(_sock, SIO_UDP_CONNRESET, &disable) == SOCKET_ERROR) {
- print_verbose("Unable to turn off UDP WSAECONNRESET behaviour on Windows");
+ print_verbose("Unable to turn off UDP WSAECONNRESET behavior on Windows");
}
if (ioctlsocket(_sock, SIO_UDP_NETRESET, &disable) == SOCKET_ERROR) {
// This feature seems not to be supported on wine.
- print_verbose("Unable to turn off UDP WSAENETRESET behaviour on Windows");
+ print_verbose("Unable to turn off UDP WSAENETRESET behavior on Windows");
}
}
#endif
@@ -376,7 +389,7 @@ void NetSocketPosix::close() {
_is_stream = false;
}
-Error NetSocketPosix::bind(IP_Address p_addr, uint16_t p_port) {
+Error NetSocketPosix::bind(IPAddress p_addr, uint16_t p_port) {
ERR_FAIL_COND_V(!is_open(), ERR_UNCONFIGURED);
ERR_FAIL_COND_V(!_can_use_ip(p_addr, true), ERR_INVALID_PARAMETER);
@@ -384,8 +397,8 @@ Error NetSocketPosix::bind(IP_Address p_addr, uint16_t p_port) {
size_t addr_size = _set_addr_storage(&addr, p_addr, p_port, _ip_type);
if (::bind(_sock, (struct sockaddr *)&addr, addr_size) != 0) {
- _get_socket_error();
- print_verbose("Failed to bind socket.");
+ NetError err = _get_socket_error();
+ print_verbose("Failed to bind socket. Error: " + itos(err));
close();
return ERR_UNAVAILABLE;
}
@@ -401,12 +414,12 @@ Error NetSocketPosix::listen(int p_max_pending) {
print_verbose("Failed to listen from socket.");
close();
return FAILED;
- };
+ }
return OK;
}
-Error NetSocketPosix::connect_to_host(IP_Address p_host, uint16_t p_port) {
+Error NetSocketPosix::connect_to_host(IPAddress p_host, uint16_t p_port) {
ERR_FAIL_COND_V(!is_open(), ERR_UNCONFIGURED);
ERR_FAIL_COND_V(!_can_use_ip(p_host, false), ERR_INVALID_PARAMETER);
@@ -446,8 +459,8 @@ Error NetSocketPosix::poll(PollType p_type, int p_timeout) const {
FD_ZERO(&wr);
FD_ZERO(&ex);
FD_SET(_sock, &ex);
- struct timeval timeout = { p_timeout, 0 };
- // For blocking operation, pass nullptr timeout pointer to select.
+ struct timeval timeout = { p_timeout / 1000, (p_timeout % 1000) * 1000 };
+ // For blocking operation, pass nullptr timeout pointer to select.
struct timeval *tp = nullptr;
if (p_timeout >= 0) {
// If timeout is non-negative, we want to specify the timeout instead.
@@ -475,8 +488,9 @@ Error NetSocketPosix::poll(PollType p_type, int p_timeout) const {
return FAILED;
}
- if (ret == 0)
+ if (ret == 0) {
return ERR_BUSY;
+ }
if (FD_ISSET(_sock, &ex)) {
_get_socket_error();
@@ -484,10 +498,12 @@ Error NetSocketPosix::poll(PollType p_type, int p_timeout) const {
return FAILED;
}
- if (rdp && FD_ISSET(_sock, rdp))
+ if (rdp && FD_ISSET(_sock, rdp)) {
ready = true;
- if (wrp && FD_ISSET(_sock, wrp))
+ }
+ if (wrp && FD_ISSET(_sock, wrp)) {
ready = true;
+ }
return ready ? OK : ERR_BUSY;
#else
@@ -540,7 +556,7 @@ Error NetSocketPosix::recv(uint8_t *p_buffer, int p_len, int &r_read) {
return OK;
}
-Error NetSocketPosix::recvfrom(uint8_t *p_buffer, int p_len, int &r_read, IP_Address &r_ip, uint16_t &r_port, bool p_peek) {
+Error NetSocketPosix::recvfrom(uint8_t *p_buffer, int p_len, int &r_read, IPAddress &r_ip, uint16_t &r_port, bool p_peek) {
ERR_FAIL_COND_V(!is_open(), ERR_UNCONFIGURED);
struct sockaddr_storage from;
@@ -597,7 +613,7 @@ Error NetSocketPosix::send(const uint8_t *p_buffer, int p_len, int &r_sent) {
return OK;
}
-Error NetSocketPosix::sendto(const uint8_t *p_buffer, int p_len, int &r_sent, IP_Address p_ip, uint16_t p_port) {
+Error NetSocketPosix::sendto(const uint8_t *p_buffer, int p_len, int &r_sent, IPAddress p_ip, uint16_t p_port) {
ERR_FAIL_COND_V(!is_open(), ERR_UNCONFIGURED);
struct sockaddr_storage addr;
@@ -635,7 +651,7 @@ void NetSocketPosix::set_blocking_enabled(bool p_enabled) {
ERR_FAIL_COND(!is_open());
int ret = 0;
-#if defined(WINDOWS_ENABLED) || defined(NO_FCNTL)
+#if defined(WINDOWS_ENABLED)
unsigned long par = p_enabled ? 0 : 1;
ret = SOCK_IOCTL(_sock, FIONBIO, &par);
#else
@@ -716,7 +732,21 @@ int NetSocketPosix::get_available_bytes() const {
return len;
}
-Ref<NetSocket> NetSocketPosix::accept(IP_Address &r_ip, uint16_t &r_port) {
+Error NetSocketPosix::get_socket_address(IPAddress *r_ip, uint16_t *r_port) const {
+ ERR_FAIL_COND_V(!is_open(), FAILED);
+
+ struct sockaddr_storage saddr;
+ socklen_t len = sizeof(saddr);
+ if (getsockname(_sock, (struct sockaddr *)&saddr, &len) != 0) {
+ _get_socket_error();
+ print_verbose("Error when reading local socket address.");
+ return FAILED;
+ }
+ _set_ip_port(&saddr, r_ip, r_port);
+ return OK;
+}
+
+Ref<NetSocket> NetSocketPosix::accept(IPAddress &r_ip, uint16_t &r_port) {
Ref<NetSocket> out;
ERR_FAIL_COND_V(!is_open(), out);
@@ -729,7 +759,7 @@ Ref<NetSocket> NetSocketPosix::accept(IP_Address &r_ip, uint16_t &r_port) {
return out;
}
- _set_ip_port(&their_addr, r_ip, r_port);
+ _set_ip_port(&their_addr, &r_ip, &r_port);
NetSocketPosix *ns = memnew(NetSocketPosix);
ns->_set_socket(fd, _ip_type, _is_stream);
@@ -737,11 +767,12 @@ Ref<NetSocket> NetSocketPosix::accept(IP_Address &r_ip, uint16_t &r_port) {
return Ref<NetSocket>(ns);
}
-Error NetSocketPosix::join_multicast_group(const IP_Address &p_multi_address, String p_if_name) {
+Error NetSocketPosix::join_multicast_group(const IPAddress &p_multi_address, String p_if_name) {
return _change_multicast_group(p_multi_address, p_if_name, true);
}
-Error NetSocketPosix::leave_multicast_group(const IP_Address &p_multi_address, String p_if_name) {
+Error NetSocketPosix::leave_multicast_group(const IPAddress &p_multi_address, String p_if_name) {
return _change_multicast_group(p_multi_address, p_if_name, false);
}
-#endif
+
+#endif // UNIX_SOCKET_UNAVAILABLE
diff --git a/drivers/unix/net_socket_posix.h b/drivers/unix/net_socket_posix.h
index 8cefb6544e..5558114cb1 100644
--- a/drivers/unix/net_socket_posix.h
+++ b/drivers/unix/net_socket_posix.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 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 */
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef NET_SOCKET_UNIX_H
-#define NET_SOCKET_UNIX_H
+#ifndef NET_SOCKET_POSIX_H
+#define NET_SOCKET_POSIX_H
#include "core/io/net_socket.h"
@@ -54,39 +54,42 @@ private:
ERR_NET_WOULD_BLOCK,
ERR_NET_IS_CONNECTED,
ERR_NET_IN_PROGRESS,
- ERR_NET_OTHER
+ ERR_NET_ADDRESS_INVALID_OR_UNAVAILABLE,
+ ERR_NET_UNAUTHORIZED,
+ ERR_NET_OTHER,
};
NetError _get_socket_error() const;
void _set_socket(SOCKET_TYPE p_sock, IP::Type p_ip_type, bool p_is_stream);
- _FORCE_INLINE_ Error _change_multicast_group(IP_Address p_ip, String p_if_name, bool p_add);
+ _FORCE_INLINE_ Error _change_multicast_group(IPAddress p_ip, String p_if_name, bool p_add);
_FORCE_INLINE_ void _set_close_exec_enabled(bool p_enabled);
protected:
static NetSocket *_create_func();
- bool _can_use_ip(const IP_Address &p_ip, const bool p_for_bind) const;
+ bool _can_use_ip(const IPAddress &p_ip, const bool p_for_bind) const;
public:
static void make_default();
static void cleanup();
- static void _set_ip_port(struct sockaddr_storage *p_addr, IP_Address &r_ip, uint16_t &r_port);
- static size_t _set_addr_storage(struct sockaddr_storage *p_addr, const IP_Address &p_ip, uint16_t p_port, IP::Type p_ip_type);
+ static void _set_ip_port(struct sockaddr_storage *p_addr, IPAddress *r_ip, uint16_t *r_port);
+ static size_t _set_addr_storage(struct sockaddr_storage *p_addr, const IPAddress &p_ip, uint16_t p_port, IP::Type p_ip_type);
virtual Error open(Type p_sock_type, IP::Type &ip_type);
virtual void close();
- virtual Error bind(IP_Address p_addr, uint16_t p_port);
+ virtual Error bind(IPAddress p_addr, uint16_t p_port);
virtual Error listen(int p_max_pending);
- virtual Error connect_to_host(IP_Address p_host, uint16_t p_port);
+ virtual Error connect_to_host(IPAddress p_host, uint16_t p_port);
virtual Error poll(PollType p_type, int timeout) const;
virtual Error recv(uint8_t *p_buffer, int p_len, int &r_read);
- virtual Error recvfrom(uint8_t *p_buffer, int p_len, int &r_read, IP_Address &r_ip, uint16_t &r_port, bool p_peek = false);
+ virtual Error recvfrom(uint8_t *p_buffer, int p_len, int &r_read, IPAddress &r_ip, uint16_t &r_port, bool p_peek = false);
virtual Error send(const uint8_t *p_buffer, int p_len, int &r_sent);
- virtual Error sendto(const uint8_t *p_buffer, int p_len, int &r_sent, IP_Address p_ip, uint16_t p_port);
- virtual Ref<NetSocket> accept(IP_Address &r_ip, uint16_t &r_port);
+ virtual Error sendto(const uint8_t *p_buffer, int p_len, int &r_sent, IPAddress p_ip, uint16_t p_port);
+ virtual Ref<NetSocket> accept(IPAddress &r_ip, uint16_t &r_port);
virtual bool is_open() const;
virtual int get_available_bytes() const;
+ virtual Error get_socket_address(IPAddress *r_ip, uint16_t *r_port) const;
virtual Error set_broadcasting_enabled(bool p_enabled);
virtual void set_blocking_enabled(bool p_enabled);
@@ -94,11 +97,11 @@ public:
virtual void set_tcp_no_delay_enabled(bool p_enabled);
virtual void set_reuse_address_enabled(bool p_enabled);
virtual void set_reuse_port_enabled(bool p_enabled);
- virtual Error join_multicast_group(const IP_Address &p_multi_address, String p_if_name);
- virtual Error leave_multicast_group(const IP_Address &p_multi_address, String p_if_name);
+ virtual Error join_multicast_group(const IPAddress &p_multi_address, String p_if_name);
+ virtual Error leave_multicast_group(const IPAddress &p_multi_address, String p_if_name);
NetSocketPosix();
~NetSocketPosix();
};
-#endif
+#endif // NET_SOCKET_POSIX_H
diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp
index 96c338f86b..161706489f 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-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 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 */
@@ -32,14 +32,12 @@
#ifdef UNIX_ENABLED
+#include "core/config/project_settings.h"
#include "core/debugger/engine_debugger.h"
#include "core/debugger/script_debugger.h"
-#include "core/os/thread_dummy.h"
-#include "core/project_settings.h"
#include "drivers/unix/dir_access_unix.h"
#include "drivers/unix/file_access_unix.h"
#include "drivers/unix/net_socket_posix.h"
-#include "drivers/unix/rw_lock_posix.h"
#include "drivers/unix/thread_posix.h"
#include "servers/rendering_server.h"
@@ -53,7 +51,6 @@
#include <sys/sysctl.h>
#endif
-#include <assert.h>
#include <dlfcn.h>
#include <errno.h>
#include <poll.h>
@@ -64,8 +61,24 @@
#include <string.h>
#include <sys/time.h>
#include <sys/wait.h>
+#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__)
@@ -78,7 +91,7 @@ static void _setup_clock() {
_clock_start = mach_absolute_time() * _clock_scale;
}
#else
-#if defined(CLOCK_MONOTONIC_RAW) && !defined(JAVASCRIPT_ENABLED) // This is a better clock on Linux.
+#if defined(CLOCK_MONOTONIC_RAW) && !defined(WEB_ENABLED) // This is a better clock on Linux.
#define GODOT_CLOCK CLOCK_MONOTONIC_RAW
#else
#define GODOT_CLOCK CLOCK_MONOTONIC
@@ -90,10 +103,6 @@ static void _setup_clock() {
}
#endif
-void OS_Unix::debug_break() {
- assert(false);
-};
-
static void handle_interrupt(int sig) {
if (!EngineDebugger::is_active()) {
return;
@@ -117,25 +126,17 @@ int OS_Unix::unix_initialize_audio(int p_audio_driver) {
}
void OS_Unix::initialize_core() {
-#ifdef NO_THREADS
- ThreadDummy::make_default();
- RWLockDummy::make_default();
-#else
- ThreadPosix::make_default();
- RWLockPosix::make_default();
-#endif
+ init_thread_posix();
+
FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_RESOURCES);
FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_USERDATA);
FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_FILESYSTEM);
- //FileAccessBufferedFA<FileAccessUnix>::make_default();
DirAccess::make_default<DirAccessUnix>(DirAccess::ACCESS_RESOURCES);
DirAccess::make_default<DirAccessUnix>(DirAccess::ACCESS_USERDATA);
DirAccess::make_default<DirAccessUnix>(DirAccess::ACCESS_FILESYSTEM);
-#ifndef NO_NETWORK
NetSocketPosix::make_default();
- IP_Unix::make_default();
-#endif
+ IPUnix::make_default();
_setup_clock();
}
@@ -144,8 +145,8 @@ 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());
+Vector<String> OS_Unix::get_video_adapter_driver_info() const {
+ return Vector<String>();
}
String OS_Unix::get_stdin_string(bool p_block) {
@@ -159,25 +160,59 @@ 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);
+// Define this yourself if you don't want to fall back to /dev/urandom.
+#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";
}
+String OS_Unix::get_distribution_name() const {
+ return "";
+}
+
+String OS_Unix::get_version() const {
+ return "";
+}
+
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::DateTime OS_Unix::get_datetime(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);
}
- Date ret;
+ DateTime ret;
ret.year = 1900 + lt.tm_year;
// Index starting at 1 to match OS_Unix::get_date
// and Windows SYSTEMTIME and tm_mon follows the typical structure
@@ -185,27 +220,14 @@ OS::Date OS_Unix::get_date(bool utc) const {
ret.month = (Month)(lt.tm_mon + 1);
ret.day = lt.tm_mday;
ret.weekday = (Weekday)lt.tm_wday;
+ ret.hour = lt.tm_hour;
+ ret.minute = lt.tm_min;
+ ret.second = lt.tm_sec;
ret.dst = lt.tm_isdst;
return ret;
}
-OS::Time OS_Unix::get_time(bool utc) const {
- time_t t = time(nullptr);
- struct tm lt;
- if (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;
- get_time_zone_info();
- return ret;
-}
-
OS::TimeZoneInfo OS_Unix::get_time_zone_info() const {
time_t t = time(nullptr);
struct tm lt;
@@ -235,8 +257,11 @@ OS::TimeZoneInfo OS_Unix::get_time_zone_info() const {
}
void OS_Unix::delay_usec(uint32_t p_usec) const {
- struct timespec rem = { static_cast<time_t>(p_usec / 1000000), (static_cast<long>(p_usec) % 1000000) * 1000 };
- while (nanosleep(&rem, &rem) == EINTR) {
+ struct timespec requested = { static_cast<time_t>(p_usec / 1000000), (static_cast<long>(p_usec) % 1000000) * 1000 };
+ struct timespec remaining;
+ while (nanosleep(&requested, &remaining) == -1 && errno == EINTR) {
+ requested.tv_sec = remaining.tv_sec;
+ requested.tv_nsec = remaining.tv_nsec;
}
}
@@ -255,45 +280,45 @@ uint64_t OS_Unix::get_ticks_usec() const {
return longtime;
}
-Error OS_Unix::execute(const String &p_path, const List<String> &p_arguments, bool p_blocking, ProcessID *r_child_id, 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.
+ // Actual virtual call goes to OS_Web.
ERR_FAIL_V(ERR_BUG);
#else
- if (p_blocking && r_pipe) {
- String argss;
- argss = "\"" + p_path + "\"";
-
+ if (r_pipe) {
+ String command = "\"" + p_path + "\"";
for (int i = 0; i < p_arguments.size(); i++) {
- argss += String(" \"") + p_arguments[i] + "\"";
+ command += String(" \"") + p_arguments[i] + "\"";
}
-
if (read_stderr) {
- argss += " 2>&1"; // Read stderr too
+ command += " 2>&1"; // Include stderr
} else {
- argss += " 2>/dev/null"; //silence stderr
+ command += " 2>/dev/null"; // Silence stderr
}
- FILE *f = popen(argss.utf8().get_data(), "r");
-
- ERR_FAIL_COND_V_MSG(!f, ERR_CANT_OPEN, "Cannot pipe stream from process running with following arguments '" + argss + "'.");
+ FILE *f = popen(command.utf8().get_data(), "r");
+ ERR_FAIL_COND_V_MSG(!f, ERR_CANT_OPEN, "Cannot create pipe from command: " + command);
char buf[65535];
-
while (fgets(buf, 65535, f)) {
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();
}
}
int rv = pclose(f);
+
if (r_exitcode) {
*r_exitcode = WEXITSTATUS(rv);
}
-
return OK;
}
@@ -301,14 +326,7 @@ Error OS_Unix::execute(const String &p_path, const List<String> &p_arguments, bo
ERR_FAIL_COND_V(pid < 0, ERR_CANT_FORK);
if (pid == 0) {
- // is child
-
- if (!p_blocking) {
- // For non blocking calls, create a new session-ID so parent won't wait for it.
- // This ensures the process won't go zombie at end.
- setsid();
- }
-
+ // The child process
Vector<CharString> cs;
cs.push_back(p_path.utf8());
for (int i = 0; i < p_arguments.size(); i++) {
@@ -322,24 +340,56 @@ Error OS_Unix::execute(const String &p_path, const List<String> &p_arguments, bo
args.push_back(0);
execvp(p_path.utf8().get_data(), &args[0]);
- // still alive? something failed..
- fprintf(stderr, "**ERROR** OS_Unix::execute - Could not create child process while executing: %s\n", p_path.utf8().get_data());
+ // The execvp() function only returns if an error occurs.
+ ERR_PRINT("Could not create child process: " + p_path);
raise(SIGKILL);
}
- if (p_blocking) {
- int status;
- waitpid(pid, &status, 0);
- if (r_exitcode) {
- *r_exitcode = WEXITSTATUS(status);
+ int status;
+ waitpid(pid, &status, 0);
+ if (r_exitcode) {
+ *r_exitcode = WIFEXITED(status) ? WEXITSTATUS(status) : status;
+ }
+ return OK;
+#endif
+}
+
+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_Web.
+ ERR_FAIL_V(ERR_BUG);
+#else
+ pid_t pid = fork();
+ ERR_FAIL_COND_V(pid < 0, ERR_CANT_FORK);
+
+ if (pid == 0) {
+ // The new process
+ // Create a new session-ID so parent won't wait for it.
+ // This ensures the process won't go zombie at the end.
+ setsid();
+
+ Vector<CharString> cs;
+ cs.push_back(p_path.utf8());
+ for (int i = 0; i < p_arguments.size(); i++) {
+ cs.push_back(p_arguments[i].utf8());
}
- } else {
- if (r_child_id) {
- *r_child_id = pid;
+ Vector<char *> args;
+ for (int i = 0; i < cs.size(); i++) {
+ args.push_back((char *)cs[i].get_data());
}
+ args.push_back(0);
+
+ execvp(p_path.utf8().get_data(), &args[0]);
+ // The execvp() function only returns if an error occurs.
+ ERR_PRINT("Could not create child process: " + p_path);
+ raise(SIGKILL);
}
+ if (r_child_id) {
+ *r_child_id = pid;
+ }
return OK;
#endif
}
@@ -356,7 +406,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;
@@ -375,27 +434,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
- path = get_executable_path().get_base_dir().plus_file(p_path.get_file());
+ // This code exists so GDExtension can load .so files from within the executable path.
+ path = get_executable_path().get_base_dir().path_join(p_path.get_file());
}
if (!FileAccess::exists(path)) {
- //this code exists so gdnative 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());
+ // This code exists so GDExtension can load .so files from a standard unix location.
+ path = get_executable_path().get_base_dir().path_join("../lib").path_join(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;
}
@@ -440,26 +504,22 @@ bool OS_Unix::set_environment(const String &p_var, const String &p_value) const
return setenv(p_var.utf8().get_data(), p_value.utf8().get_data(), /* overwrite: */ true) == 0;
}
-int OS_Unix::get_processor_count() const {
- return sysconf(_SC_NPROCESSORS_CONF);
-}
-
String OS_Unix::get_user_data_dir() const {
- String appname = get_safe_dir_name(ProjectSettings::get_singleton()->get("application/config/name"));
- if (appname != "") {
- bool use_custom_dir = ProjectSettings::get_singleton()->get("application/config/use_custom_user_dir");
+ String appname = get_safe_dir_name(GLOBAL_GET("application/config/name"));
+ if (!appname.is_empty()) {
+ bool use_custom_dir = GLOBAL_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 == "") {
+ String custom_dir = get_safe_dir_name(GLOBAL_GET("application/config/custom_user_dir_name"), true);
+ if (custom_dir.is_empty()) {
custom_dir = appname;
}
- return get_data_path().plus_file(custom_dir);
+ return get_data_path().path_join(custom_dir);
} else {
- return get_data_path().plus_file(get_godot_dir_name()).plus_file("app_userdata").plus_file(appname);
+ return get_data_path().path_join(get_godot_dir_name()).path_join("app_userdata").path_join(appname);
}
}
- return ProjectSettings::get_singleton()->get_resource_path();
+ return get_data_path().path_join(get_godot_dir_name()).path_join("app_userdata").path_join("[unnamed project]");
}
String OS_Unix::get_executable_path() const {
@@ -472,7 +532,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();
}
@@ -501,8 +561,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;
@@ -514,7 +575,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;
}
diff --git a/drivers/unix/os_unix.h b/drivers/unix/os_unix.h
index 2982e0c55c..ce06a52a95 100644
--- a/drivers/unix/os_unix.h
+++ b/drivers/unix/os_unix.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 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 */
@@ -43,69 +43,61 @@ protected:
virtual void initialize_core();
virtual int unix_initialize_audio(int p_audio_driver);
- //virtual Error initialize(int p_video_driver,int p_audio_driver);
- virtual void finalize_core();
+ virtual void finalize_core() override;
String stdin_buf;
public:
OS_Unix();
- virtual void alert(const String &p_alert, const String &p_title = "ALERT!");
- virtual String get_stdin_string(bool p_block);
+ virtual Vector<String> get_video_adapter_driver_info() const override;
- //virtual void set_mouse_show(bool p_show);
- //virtual void set_mouse_grab(bool p_grab);
- //virtual bool is_mouse_grab_enabled() const = 0;
- //virtual void get_mouse_position(int &x, int &y) const;
- //virtual void set_window_title(const String& p_title);
+ virtual String get_stdin_string(bool p_block) override;
- //virtual void set_video_mode(const VideoMode& p_video_mode);
- //virtual VideoMode get_video_mode() const;
- //virtual void get_fullscreen_mode_list(List<VideoMode> *p_list) const;
+ virtual Error get_entropy(uint8_t *r_buffer, int p_bytes) override;
- virtual Error open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path = false);
- virtual Error close_dynamic_library(void *p_library_handle);
- virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle, bool p_optional = false);
+ virtual Error open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path = false, String *r_resolved_path = nullptr) override;
+ virtual Error close_dynamic_library(void *p_library_handle) override;
+ virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle, bool p_optional = false) override;
- virtual Error set_cwd(const String &p_cwd);
+ virtual Error set_cwd(const String &p_cwd) override;
- virtual String get_name() const;
+ virtual String get_name() const override;
+ virtual String get_distribution_name() const override;
+ virtual String get_version() const override;
- virtual Date get_date(bool utc) const;
- virtual Time get_time(bool utc) const;
- virtual TimeZoneInfo get_time_zone_info() const;
+ virtual DateTime get_datetime(bool p_utc) const override;
+ virtual TimeZoneInfo get_time_zone_info() const override;
- virtual double get_unix_time() const;
+ virtual double get_unix_time() const override;
- virtual void delay_usec(uint32_t p_usec) const;
- virtual uint64_t get_ticks_usec() const;
+ virtual void delay_usec(uint32_t p_usec) const override;
+ virtual uint64_t get_ticks_usec() const override;
- virtual Error execute(const String &p_path, const List<String> &p_arguments, bool p_blocking = true, ProcessID *r_child_id = nullptr, String *r_pipe = nullptr, int *r_exitcode = nullptr, bool read_stderr = false, Mutex *p_pipe_mutex = nullptr);
- virtual Error kill(const ProcessID &p_pid);
- virtual int get_process_id() const;
+ virtual Error execute(const String &p_path, const List<String> &p_arguments, String *r_pipe = nullptr, int *r_exitcode = nullptr, bool read_stderr = false, Mutex *p_pipe_mutex = nullptr, bool p_open_console = false) override;
+ virtual Error create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id = nullptr, bool p_open_console = false) override;
+ virtual Error kill(const ProcessID &p_pid) override;
+ virtual int get_process_id() const override;
+ virtual bool is_process_running(const ProcessID &p_pid) const override;
- virtual bool has_environment(const String &p_var) const;
- virtual String get_environment(const String &p_var) const;
- virtual bool set_environment(const String &p_var, const String &p_value) const;
- virtual String get_locale() const;
+ virtual bool has_environment(const String &p_var) const override;
+ virtual String get_environment(const String &p_var) const override;
+ virtual bool set_environment(const String &p_var, const String &p_value) const override;
+ virtual String get_locale() const override;
- virtual int get_processor_count() const;
+ virtual void initialize_debugging() override;
- virtual void debug_break();
- virtual void initialize_debugging();
-
- virtual String get_executable_path() const;
- virtual String get_user_data_dir() const;
+ virtual String get_executable_path() const override;
+ virtual String get_user_data_dir() const override;
};
class UnixTerminalLogger : public StdLogger {
public:
- virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type = ERR_ERROR);
+ virtual void 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 = false, ErrorType p_type = ERR_ERROR) override;
virtual ~UnixTerminalLogger();
};
-#endif
+#endif // UNIX_ENABLED
-#endif
+#endif // OS_UNIX_H
diff --git a/drivers/unix/rw_lock_posix.cpp b/drivers/unix/rw_lock_posix.cpp
deleted file mode 100644
index 50b74e84f7..0000000000
--- a/drivers/unix/rw_lock_posix.cpp
+++ /dev/null
@@ -1,93 +0,0 @@
-/*************************************************************************/
-/* rw_lock_posix.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 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 */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#if defined(UNIX_ENABLED) || defined(PTHREAD_ENABLED)
-
-#include "rw_lock_posix.h"
-
-#include "core/error_macros.h"
-#include "core/os/memory.h"
-#include <stdio.h>
-
-void RWLockPosix::read_lock() {
- int err = pthread_rwlock_rdlock(&rwlock);
- if (err != 0) {
- perror("Acquiring lock failed");
- }
- ERR_FAIL_COND(err != 0);
-}
-
-void RWLockPosix::read_unlock() {
- pthread_rwlock_unlock(&rwlock);
-}
-
-Error RWLockPosix::read_try_lock() {
- if (pthread_rwlock_tryrdlock(&rwlock) != 0) {
- return ERR_BUSY;
- } else {
- return OK;
- }
-}
-
-void RWLockPosix::write_lock() {
- int err = pthread_rwlock_wrlock(&rwlock);
- ERR_FAIL_COND(err != 0);
-}
-
-void RWLockPosix::write_unlock() {
- pthread_rwlock_unlock(&rwlock);
-}
-
-Error RWLockPosix::write_try_lock() {
- if (pthread_rwlock_trywrlock(&rwlock) != 0) {
- return ERR_BUSY;
- } else {
- return OK;
- }
-}
-
-RWLock *RWLockPosix::create_func_posix() {
- return memnew(RWLockPosix);
-}
-
-void RWLockPosix::make_default() {
- create_func = create_func_posix;
-}
-
-RWLockPosix::RWLockPosix() {
- //rwlock=PTHREAD_RWLOCK_INITIALIZER; fails on OSX
- pthread_rwlock_init(&rwlock, nullptr);
-}
-
-RWLockPosix::~RWLockPosix() {
- pthread_rwlock_destroy(&rwlock);
-}
-
-#endif
diff --git a/drivers/unix/rw_lock_posix.h b/drivers/unix/rw_lock_posix.h
deleted file mode 100644
index 056fcaea1c..0000000000
--- a/drivers/unix/rw_lock_posix.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*************************************************************************/
-/* rw_lock_posix.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 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 */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#ifndef RWLOCKPOSIX_H
-#define RWLOCKPOSIX_H
-
-#if defined(UNIX_ENABLED) || defined(PTHREAD_ENABLED)
-
-#include "core/os/rw_lock.h"
-#include <pthread.h>
-
-class RWLockPosix : public RWLock {
- pthread_rwlock_t rwlock;
-
- static RWLock *create_func_posix();
-
-public:
- virtual void read_lock();
- virtual void read_unlock();
- virtual Error read_try_lock();
-
- virtual void write_lock();
- virtual void write_unlock();
- virtual Error write_try_lock();
-
- static void make_default();
-
- RWLockPosix();
-
- ~RWLockPosix();
-};
-
-#endif
-
-#endif // RWLOCKPOSIX_H
diff --git a/drivers/unix/syslog_logger.cpp b/drivers/unix/syslog_logger.cpp
index a4c7070f0e..6189d645c6 100644
--- a/drivers/unix/syslog_logger.cpp
+++ b/drivers/unix/syslog_logger.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 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 */
@@ -31,7 +31,9 @@
#ifdef UNIX_ENABLED
#include "syslog_logger.h"
-#include "core/print_string.h"
+
+#include "core/string/print_string.h"
+
#include <syslog.h>
void SyslogLogger::logv(const char *p_format, va_list p_list, bool p_err) {
diff --git a/drivers/unix/syslog_logger.h b/drivers/unix/syslog_logger.h
index 52da12481f..cc6617eb25 100644
--- a/drivers/unix/syslog_logger.h
+++ b/drivers/unix/syslog_logger.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 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 */
@@ -43,6 +43,6 @@ public:
virtual ~SyslogLogger();
};
-#endif
+#endif // UNIX_ENABLED
-#endif
+#endif // SYSLOG_LOGGER_H
diff --git a/drivers/unix/thread_posix.cpp b/drivers/unix/thread_posix.cpp
index 285088342b..5154feb478 100644
--- a/drivers/unix/thread_posix.cpp
+++ b/drivers/unix/thread_posix.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 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 */
@@ -28,88 +28,18 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "thread_posix.h"
+#if defined(UNIX_ENABLED)
-#if (defined(UNIX_ENABLED) || defined(PTHREAD_ENABLED)) && !defined(NO_THREADS)
+#include "thread_posix.h"
-#include "core/os/memory.h"
-#include "core/safe_refcount.h"
-#include "core/script_language.h"
+#include "core/os/thread.h"
+#include "core/string/ustring.h"
#ifdef PTHREAD_BSD_SET_NAME
#include <pthread_np.h>
#endif
-static void _thread_id_key_destr_callback(void *p_value) {
- memdelete(static_cast<Thread::ID *>(p_value));
-}
-
-static pthread_key_t _create_thread_id_key() {
- pthread_key_t key;
- pthread_key_create(&key, &_thread_id_key_destr_callback);
- return key;
-}
-
-pthread_key_t ThreadPosix::thread_id_key = _create_thread_id_key();
-Thread::ID ThreadPosix::next_thread_id = 0;
-
-Thread::ID ThreadPosix::get_id() const {
- return id;
-}
-
-Thread *ThreadPosix::create_thread_posix() {
- return memnew(ThreadPosix);
-}
-
-void *ThreadPosix::thread_callback(void *userdata) {
- ThreadPosix *t = reinterpret_cast<ThreadPosix *>(userdata);
- t->id = atomic_increment(&next_thread_id);
- pthread_setspecific(thread_id_key, (void *)memnew(ID(t->id)));
-
- ScriptServer::thread_enter(); //scripts may need to attach a stack
-
- t->callback(t->user);
-
- ScriptServer::thread_exit();
-
- return nullptr;
-}
-
-Thread *ThreadPosix::create_func_posix(ThreadCreateCallback p_callback, void *p_user, const Settings &) {
- ThreadPosix *tr = memnew(ThreadPosix);
- tr->callback = p_callback;
- tr->user = p_user;
- pthread_attr_init(&tr->pthread_attr);
- pthread_attr_setdetachstate(&tr->pthread_attr, PTHREAD_CREATE_JOINABLE);
- pthread_attr_setstacksize(&tr->pthread_attr, 256 * 1024);
-
- pthread_create(&tr->pthread, &tr->pthread_attr, thread_callback, tr);
-
- return tr;
-}
-
-Thread::ID ThreadPosix::get_thread_id_func_posix() {
- void *value = pthread_getspecific(thread_id_key);
-
- if (value) {
- return *static_cast<ID *>(value);
- }
-
- ID new_id = atomic_increment(&next_thread_id);
- pthread_setspecific(thread_id_key, (void *)memnew(ID(new_id)));
- return new_id;
-}
-
-void ThreadPosix::wait_to_finish_func_posix(Thread *p_thread) {
- ThreadPosix *tp = static_cast<ThreadPosix *>(p_thread);
- ERR_FAIL_COND(!tp);
- ERR_FAIL_COND(tp->pthread == 0);
-
- pthread_join(tp->pthread, nullptr);
- tp->pthread = 0;
-}
-
-Error ThreadPosix::set_name_func_posix(const String &p_name) {
+static Error set_name(const String &p_name) {
#ifdef PTHREAD_NO_RENAME
return ERR_UNAVAILABLE;
@@ -137,20 +67,10 @@ Error ThreadPosix::set_name_func_posix(const String &p_name) {
return err == 0 ? OK : ERR_INVALID_PARAMETER;
#endif // PTHREAD_NO_RENAME
-};
-
-void ThreadPosix::make_default() {
- create_func = create_func_posix;
- get_thread_id_func = get_thread_id_func_posix;
- wait_to_finish_func = wait_to_finish_func_posix;
- set_name_func = set_name_func_posix;
-}
-
-ThreadPosix::ThreadPosix() {
- pthread = 0;
}
-ThreadPosix::~ThreadPosix() {
+void init_thread_posix() {
+ Thread::_set_platform_functions({ .set_name = set_name });
}
-#endif
+#endif // UNIX_ENABLED
diff --git a/drivers/unix/thread_posix.h b/drivers/unix/thread_posix.h
index 6607dbd111..87e42b3870 100644
--- a/drivers/unix/thread_posix.h
+++ b/drivers/unix/thread_posix.h
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2020 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 */
@@ -31,42 +31,6 @@
#ifndef THREAD_POSIX_H
#define THREAD_POSIX_H
-#if (defined(UNIX_ENABLED) || defined(PTHREAD_ENABLED)) && !defined(NO_THREADS)
+void init_thread_posix();
-#include "core/os/thread.h"
-#include <pthread.h>
-#include <sys/types.h>
-
-class ThreadPosix : public Thread {
- static pthread_key_t thread_id_key;
- static ID next_thread_id;
-
- pthread_t pthread;
- pthread_attr_t pthread_attr;
- ThreadCreateCallback callback;
- void *user;
- ID id;
-
- static Thread *create_thread_posix();
-
- static void *thread_callback(void *userdata);
-
- static Thread *create_func_posix(ThreadCreateCallback p_callback, void *, const Settings &);
- static ID get_thread_id_func_posix();
- static void wait_to_finish_func_posix(Thread *p_thread);
-
- static Error set_name_func_posix(const String &p_name);
-
- ThreadPosix();
-
-public:
- virtual ID get_id() const;
-
- static void make_default();
-
- ~ThreadPosix();
-};
-
-#endif
-
-#endif
+#endif // THREAD_POSIX_H