Skip to content
4 changes: 2 additions & 2 deletions src/native/clr/host/assembly-store.cc
Original file line numberDiff line numberDiff line change
Expand Up@@ -312,8 +312,8 @@ namespace {
return;
}

std::string const& code_cache_dir = AndroidSystem::get_app_code_cache_dir ();
if (code_cache_dir.empty ()) {
const char *code_cache_dir = AndroidSystem::get_app_code_cache_dir ();
if (*code_cache_dir == '\0') {
return;
}

Expand Down
18 changes: 9 additions & 9 deletions src/native/clr/host/fastdev-assemblies.cc
Original file line numberDiff line numberDiff line change
Expand Up@@ -36,9 +36,9 @@ auto FastDevAssemblies::open_assembly (std::string_view const& name, int64_t &si
return nullptr;
}

std::string const& override_dir_path = AndroidSystem::get_primary_override_dir ();
const char *override_dir_path = AndroidSystem::get_primary_override_dir ();
if (!Util::dir_exists (override_dir_path)) [[unlikely]] {
log_debugf (LOG_ASSEMBLY, "Override directory '%s' does not exist", override_dir_path.c_str ());
log_debugf (LOG_ASSEMBLY, "Override directory '%s' does not exist", override_dir_path);
return nullptr;
}

Expand All@@ -47,9 +47,9 @@ auto FastDevAssemblies::open_assembly (std::string_view const& name, int64_t &si
if (override_dir_fd < 0) [[unlikely]] {
std::lock_guard dir_lock { override_dir_lock };
if (override_dir_fd < 0) [[likely]] {
override_dir = opendir (override_dir_path.c_str ());
override_dir = opendir (override_dir_path);
if (override_dir == nullptr) [[unlikely]] {
log_warnf (LOG_ASSEMBLY, "Failed to open override dir '%s'. %s", override_dir_path.c_str (), strerror (errno));
log_warnf (LOG_ASSEMBLY, "Failed to open override dir '%s'. %s", override_dir_path, strerror (errno));
return nullptr;
}
override_dir_fd = dirfd (override_dir);
Expand All@@ -60,7 +60,7 @@ auto FastDevAssemblies::open_assembly (std::string_view const& name, int64_t &si
LOG_ASSEMBLY,
"Attempting to load FastDev assembly '%.*s' from override directory '%s'",
static_cast<int>(name.length ()), name.data (),
override_dir_path.c_str ()
override_dir_path
);

if (!Util::file_exists (override_dir_fd, name)) {
Expand DownExpand Up@@ -133,14 +133,14 @@ auto FastDevAssemblies::build_tpa_list (std::string &tpa_list) noexcept -> bool
{
tpa_list.clear ();

std::string const& override_dir_path = AndroidSystem::get_primary_override_dir ();
const char *override_dir_path = AndroidSystem::get_primary_override_dir ();
if (!Util::dir_exists (override_dir_path)) {
return false;
}

DIR *dir = opendir (override_dir_path.c_str ());
DIR *dir = opendir (override_dir_path);
if (dir == nullptr) {
log_warnf (LOG_ASSEMBLY, "FastDev: failed to open override dir '%s'. %s", override_dir_path.c_str (), std::strerror (errno));
log_warnf (LOG_ASSEMBLY, "FastDev: failed to open override dir '%s'. %s", override_dir_path, std::strerror (errno));
return false;
}

Expand DownExpand Up@@ -183,7 +183,7 @@ auto FastDevAssemblies::build_tpa_list (std::string &tpa_list) noexcept -> bool
LOG_ASSEMBLY,
"FastDev: built TPA list with %zu assemblies from '%s' (corelib=%s, r2r=%s)",
count,
override_dir_path.c_str (),
override_dir_path,
found_corelib ? "true" : "false",
found_r2r ? "true" : "false"
);
Expand Down
16 changes: 8 additions & 8 deletions src/native/clr/host/host.cc
Original file line numberDiff line numberDiff line change
Expand Up@@ -91,16 +91,16 @@ bool Host::clr_external_assembly_probe (const char *path, void **data_start, int
[[gnu::always_inline]]
void Host::scan_filesystem_for_assemblies_and_libraries () noexcept
{
std::string const& native_lib_dir = AndroidSystem::get_native_libraries_dir ();
log_debugf (LOG_ASSEMBLY, "Looking for assemblies in '%s'", native_lib_dir.c_str ());
const char *native_lib_dir = AndroidSystem::get_native_libraries_dir ();
log_debugf (LOG_ASSEMBLY, "Looking for assemblies in '%s'", native_lib_dir);

DIR *lib_dir = opendir (native_lib_dir.c_str ());
DIR *lib_dir = opendir (native_lib_dir);
if (lib_dir == nullptr) [[unlikely]] {
Helpers::abort_applicationf (
LOG_ASSEMBLY,
std::source_location::current (),
"Unable to open native library directory '%s'. %s",
native_lib_dir.c_str (),
native_lib_dir,
std::strerror (errno)
);
}
Expand All@@ -111,7 +111,7 @@ void Host::scan_filesystem_for_assemblies_and_libraries () noexcept
LOG_ASSEMBLY,
std::source_location::current (),
"Unable to obtain file descriptor for opened directory '%s'. %s",
native_lib_dir.c_str (),
native_lib_dir,
std::strerror (errno)
);
}
Expand All@@ -121,7 +121,7 @@ void Host::scan_filesystem_for_assemblies_and_libraries () noexcept
dirent *cur = readdir (lib_dir);
if (cur == nullptr) {
if (errno != 0) {
log_warnf (LOG_ASSEMBLY, "Failed to open a directory entry from '%s': %s", native_lib_dir.c_str (), std::strerror (errno));
log_warnf (LOG_ASSEMBLY, "Failed to open a directory entry from '%s': %s", native_lib_dir, std::strerror (errno));
continue; // No harm, keep going
}
break; // we're done
Expand All@@ -138,7 +138,7 @@ void Host::scan_filesystem_for_assemblies_and_libraries () noexcept
continue;
}

log_debugf (LOG_ASSEMBLY, "Found assembly store in '%s/%s'", native_lib_dir.c_str (), Constants::assembly_store_file_name.data ());
log_debugf (LOG_ASSEMBLY, "Found assembly store in '%s/%s'", native_lib_dir, Constants::assembly_store_file_name.data ());

std::string store_path = native_lib_dir;
store_path.append ("/"sv);
Expand DownExpand Up@@ -339,7 +339,7 @@ void Host::Java_mono_android_Runtime_initInternal (
AndroidSystem::set_app_code_cache_dir (applicationDirs[Constants::APP_DIRS_CODE_CACHE_DIR_INDEX]);
AndroidSystem::create_update_dir (AndroidSystem::get_primary_override_dir ());
AndroidSystem::setup_environment ();
Logger::init_reference_logging (AndroidSystem::get_primary_override_dir ().c_str ());
Logger::init_reference_logging (AndroidSystem::get_primary_override_dir ());

jstring_array_wrapper runtimeApks (env, runtimeApksJava);
AndroidSystem::setup_app_library_directories (runtimeApks, applicationDirs, haveSplitApks);
Expand Down
2 changes: 1 addition & 1 deletion src/native/clr/include/host/host-environment.hh
Original file line numberDiff line numberDiff line change
Expand Up@@ -92,7 +92,7 @@ namespace xamarin::android {
[[gnu::flatten, gnu::always_inline]]
static void create_xdg_directory (jstring_wrapper &home, std::string_view const& relative_path, std::string_view const& environment_variable_name) noexcept
{
std::string_view home_path = home.get_string_view ();
const char *home_path = home.get_cstr ();
char stack_buffer [Util::LocalPathBufferSize];
ssize_t result = Util::format_joined_path (stack_buffer, sizeof (stack_buffer), home_path, relative_path);
abort_unless (result >= 0, "XDG directory path is too long");
Expand Down
87 changes: 34 additions & 53 deletions src/native/clr/include/runtime-base/android-system.hh
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,7 +4,6 @@
#include <cstdio>
#include <limits>
#include <span>
#include <string>
#include <string_view>

#include "../constants.hh"
Expand DownExpand Up@@ -32,11 +31,11 @@ namespace xamarin::android {
#if !defined (XA_HOST_NATIVEAOT)
// This optimizes things a little bit. The array is allocated at build time, so we pay no cost for its
// allocation and at run time it allows us to skip dynamic memory allocation.
inline static std::array<std::string, 1> single_app_lib_directory{};
inline static std::span<std::string> app_lib_directories;
inline static const char *single_app_lib_directory [1] { "" };
inline static std::span<const char*> app_lib_directories;

// TODO: override dirs not implemented
inline static std::array<std::string, 1> override_dirs{};
inline static const char *override_dirs [1] { "" };

static constexpr std::array<std::string_view, 7> android_abi_names {
std::string_view { "unknown" }, // CPU_KIND_UNKNOWN
Expand DownExpand Up@@ -73,45 +72,47 @@ namespace xamarin::android {
running_in_emulator = yesno;
}

#if defined (XA_HOST_NATIVEAOT)
static auto get_primary_override_dir () noexcept -> const char*
{
return primary_override_dir;
}
#else
static auto get_primary_override_dir () noexcept -> std::string const&
{
return primary_override_dir;
}
#endif

static void set_primary_override_dir (jstring_wrapper& home) noexcept
{
#if defined (XA_HOST_NATIVEAOT)
ssize_t result = format_primary_override_dir (home, primary_override_dir, sizeof (primary_override_dir));
abort_unless (result >= 0, "Primary override directory path is too long");
#else
primary_override_dir = determine_primary_override_dir (home);
#endif
char stack_buffer [Constants::SENSIBLE_PATH_MAX];
char *path = stack_buffer;
ssize_t result = format_primary_override_dir (home, path, sizeof (stack_buffer));
if (result < 0) {
size_t required_capacity = static_cast<size_t>(-result);
path = static_cast<char*> (std::malloc (required_capacity));
abort_unless (path != nullptr, "Failed to allocate primary override directory path");
result = format_primary_override_dir (home, path, required_capacity);
}
abort_unless (result >= 0, "Failed to format primary override directory path using the required capacity");

primary_override_dir = Util::duplicate_string (path);
if (path != stack_buffer) {
std::free (path);
}
}

#if !defined (XA_HOST_NATIVEAOT)
static auto get_app_code_cache_dir () noexcept -> std::string const&
static auto get_app_code_cache_dir () noexcept -> const char*
{
return app_code_cache_dir;
}

static void set_app_code_cache_dir (jstring_wrapper& code_cache_dir) noexcept
{
app_code_cache_dir.assign (code_cache_dir.get_cstr ());
app_code_cache_dir = Util::duplicate_string (code_cache_dir.get_cstr ());
}

static auto get_native_libraries_dir () noexcept -> std::string const&
static auto get_native_libraries_dir () noexcept -> const char*
{
return native_libraries_dir;
}

static void create_update_dir (std::string const& override_dir) noexcept
static void create_update_dir (const char *override_dir) noexcept
{
if constexpr (Constants::is_release_build) {
/*
Expand All@@ -129,8 +130,8 @@ namespace xamarin::android {
}
}

log_debugf (LOG_DEFAULT, "Creating public update directory: `%s`", override_dir.c_str ());
Util::create_public_directory (override_dir.c_str ());
log_debugf (LOG_DEFAULT, "Creating public update directory: `%s`", override_dir);
Util::create_public_directory (override_dir);
}
#endif

Expand DownExpand Up@@ -158,9 +159,9 @@ namespace xamarin::android {
static auto load_dso_from_any_directories (std::string_view const& name, int dl_flags, bool is_jni) noexcept -> void*;

private:
static auto format_full_dso_path (std::string const& base_dir, std::string_view const& dso_path, char *buffer, size_t buffer_size) noexcept -> ssize_t;
static auto format_full_dso_path (const char *base_dir, std::string_view const& dso_path, char *buffer, size_t buffer_size) noexcept -> ssize_t;

static auto get_full_dso_path (std::string const& base_dir, std::string_view const& dso_path, char *stack_buffer, size_t stack_buffer_size) noexcept -> char*
static auto get_full_dso_path (const char *base_dir, std::string_view const& dso_path, char *stack_buffer, size_t stack_buffer_size) noexcept -> char*
{
ssize_t result = format_full_dso_path (base_dir, dso_path, stack_buffer, stack_buffer_size);
if (result >= 0) {
Expand DownExpand Up@@ -226,38 +227,18 @@ namespace xamarin::android {
return static_cast<ssize_t>(length);
}

#if !defined (XA_HOST_NATIVEAOT)
static auto determine_primary_override_dir (jstring_wrapper &home) noexcept -> std::string
{
char stack_buffer [Constants::SENSIBLE_PATH_MAX];
size_t length;
char *name = Util::format_with_retry (
stack_buffer,
sizeof (stack_buffer),
[&home](char *buffer, size_t buffer_size) noexcept {
return format_primary_override_dir (home, buffer, buffer_size);
},
&length
);

std::string path { name, length };
if (name != stack_buffer) {
std::free (name);
}
return path;
}
#endif

private:
static inline long max_gref_count = 0;
static inline bool running_in_emulator = false;
static inline bool embedded_dso_mode_enabled = false;
#if defined (XA_HOST_NATIVEAOT)
static inline char primary_override_dir[Constants::SENSIBLE_PATH_MAX] {};
#else
static inline std::string primary_override_dir;
static inline std::string native_libraries_dir;
static inline std::string app_code_cache_dir;
// These are set once, early during startup, and are read for as long as the process lives.
// They are plain pointers so that they are constant-initialized: a `std::string` here would
// make the compiler emit a guard variable and an `atexit` registration in every translation
// unit which includes this header.
static inline const char *primary_override_dir = "";
#if !defined (XA_HOST_NATIVEAOT)
static inline const char *native_libraries_dir = "";
static inline const char *app_code_cache_dir = "";

#if defined (DEBUG)
static inline BundledProperty *bundled_properties = nullptr;
Expand Down
31 changes: 31 additions & 0 deletions src/native/clr/include/runtime-base/util.hh
Original file line numberDiff line numberDiff line change
Expand Up@@ -41,6 +41,21 @@ namespace xamarin::android {
public:
static constexpr size_t LocalPathBufferSize = Constants::SENSIBLE_PATH_MAX;

// Returns a copy of `str` allocated with `malloc`, aborting the application if the
// allocation fails. Used for values which are set once, early during startup, and which
// then live for as long as the process does - the copies are never freed.
static auto duplicate_string (const char *str) noexcept -> char*
{
abort_unless (str != nullptr, "String to duplicate must not be null");

char *ret = strdup (str);
Comment thread
simonrozsival marked this conversation as resolved.
if (ret == nullptr) [[unlikely]] {
Helpers::abort_application (LOG_DEFAULT, "Unable to allocate memory for a string copy");
}

return ret;
}

static int create_directory (const char *pathname, mode_t mode);

static auto create_directory (std::string_view const& dir, mode_t mode) noexcept -> int
Expand DownExpand Up@@ -310,6 +325,22 @@ namespace xamarin::android {
return !path.empty () && path.contains ('/');
}

[[gnu::flatten, gnu::always_inline]]
static auto ends_with (const char *value, const char *suffix) noexcept -> bool
{
if (value == nullptr || suffix == nullptr) {
return false;
}

size_t value_length = strlen (value);
size_t suffix_length = strlen (suffix);
if (suffix_length > value_length) {
return false;
}

return memcmp (value + value_length - suffix_length, suffix, suffix_length) == 0;
}

// Returns the path length excluding NUL, or the negative required capacity including NUL.
static auto format_joined_path (char *buffer, size_t buffer_size, std::string_view first, std::string_view second) noexcept -> ssize_t
{
Expand Down
Loading
Loading