From 944700a386a3df3353588c3e9a939b901fb480e2 Mon Sep 17 00:00:00 2001 From: Pablo Garrido Date: Fri, 14 Jul 2023 08:25:45 +0200 Subject: [PATCH] micro-ROS Rolling patch * micro-ROS changes over dashing Feature/add security directory (#1) * Added security directory * Updated security directory Feature/avoid filesystem and allocation (#2) * Included RCUTILS_NO_FILESYSTEM and RCUTILS_AVOID_DYNAMIC_ALLOCATION * Added no filesystem options * Default allocators write access * Avoid dynamic allocation and no filesytem on error handling * Typo * New flags for filesystem and avoid dynamic * Error handling template * New allocator approach Add test_security_directory test from rcl. (#3) Merge pull request #4 from micro-ROS/feature/zephyr_fixes Feature/zephyr fixes CMake refactor (#5) Update approach (#6) * Update approach * Remove target_compile_definitions and refactor flags install * Added RCUTILS_NO_FILESYSTEM on new functions * Added RCUTILS_NO_FILESYSTEM on new functions Co-authored-by: Pablo Garrido Updates 17092020 Fix atomics 64bits (#9) * micro-ROS changes over dashing Feature/add security directory (#1) * Added security directory * Updated security directory Feature/avoid filesystem and allocation (#2) * Included RCUTILS_NO_FILESYSTEM and RCUTILS_AVOID_DYNAMIC_ALLOCATION * Added no filesystem options * Default allocators write access * Avoid dynamic allocation and no filesytem on error handling * Typo * New flags for filesystem and avoid dynamic * Error handling template * New allocator approach Add test_security_directory test from rcl. (#3) Merge pull request #4 from micro-ROS/feature/zephyr_fixes Feature/zephyr fixes CMake refactor (#5) Update approach (#6) * Update approach * Remove target_compile_definitions and refactor flags install * Added RCUTILS_NO_FILESYSTEM on new functions * Added RCUTILS_NO_FILESYSTEM on new functions Co-authored-by: Pablo Garrido * Initial changes * Add hashing and lock pool * Updates Co-authored-by: Jose Antonio Moral Fix atomics 64bits (#9) Updates 09102020 * Release micro-ROS Foxy (#8) Update Cleaning Update Update filesystem Updates Adjust logger level Remove build warning (#10) * Avoid not used warnings * Update Reduce error handling static size (#14) (#15) This reverts commit befc608e21c653404f2fd876986969286125a527. Reduce error handling static size (#14) (#15) Signed-off-by: Pablo Garrido (cherry picked from commit 1176652124c12b23cb58f052077901d2c24dbf39) Co-authored-by: Pablo Garrido Revert "Revert "Install headers to include\${PROJECT_NAME} (#351)"" This reverts commit 4546892d5b3b4ef0d6e906c55e4b898c4c6d965a. Fix atomic 64 b description (#17) (#18) (cherry picked from commit 85efa4ad786fb6920ae92156ab439dec0315299b) Co-authored-by: Pablo Garrido Add fork checker for humble Signed-off-by: Pablo Garrido --- .github/workflows/fork_checker.yml | 36 +++++++ CMakeLists.txt | 13 ++- include/rcutils/allocator.h | 15 +++ include/rcutils/configuration_flags.h.in | 18 ++++ include/rcutils/error_handling.h | 32 +++++- include/rcutils/logging.h | 2 +- include/rcutils/macros.h | 6 +- include/rcutils/security_directory.h | 67 +++++++++++++ include/rcutils/testing/fault_injection.h | 13 +++ resource/logging_macros.h.em | 2 +- src/allocator.c | 23 ++++- src/atomic_64bits.c | 92 +++++++++++++++++ src/error_handling_helpers.h | 4 + src/filesystem.c | 116 ++++++++++++++++++++++ src/process.c | 8 +- src/shared_library.c | 40 ++++++++ src/time_unix.c | 2 +- 17 files changed, 475 insertions(+), 14 deletions(-) create mode 100644 .github/workflows/fork_checker.yml create mode 100644 include/rcutils/configuration_flags.h.in create mode 100644 include/rcutils/security_directory.h create mode 100644 src/atomic_64bits.c diff --git a/.github/workflows/fork_checker.yml b/.github/workflows/fork_checker.yml new file mode 100644 index 00000000..2d247eff --- /dev/null +++ b/.github/workflows/fork_checker.yml @@ -0,0 +1,36 @@ +name: micro-ROS fork Update Checker +on: + workflow_dispatch: + inputs: + name: + description: "Manual trigger" + schedule: + - cron: '0 4 * * *' + +jobs: + micro_ros_fork_update_check: + runs-on: ubuntu-latest + container: ubuntu:20.04 + strategy: + fail-fast: false + matrix: + branches: [foxy, galactic, humble, master] + steps: + - name: Check + id: check + shell: bash + run: | + apt update; apt install -y git + REPO=$(echo ${{ github.repository }} | awk '{split($0,a,"/"); print a[2]}') + git clone -b ${{ matrix.branches }} https://github.com/micro-ros/$REPO + cd $REPO + git remote add ros2 https://github.com/ros2/$REPO + git fetch ros2 + git fetch origin + echo "::set-output name=merge_required::true" + CMP=$(git rev-list --left-right --count ros2/${{ matrix.branches }}...origin/${{ matrix.branches }} | awk '{print $1}') + if [ $CMP = "0" ]; then echo "::set-output name=merge_required::false"; fi + + - name: Alert + if: ${{ steps.check.outputs.merge_required == 'true' }} + run: exit 1 diff --git a/CMakeLists.txt b/CMakeLists.txt index 35d4df0c..33242e52 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,6 +2,12 @@ cmake_minimum_required(VERSION 3.12) project(rcutils) +option(RCUTILS_NO_THREAD_SUPPORT "Disable thread support." OFF) +option(RCUTILS_NO_FILESYSTEM "Disable filesystem usage." OFF) +option(RCUTILS_AVOID_DYNAMIC_ALLOCATION "Disable dynamic allocations." OFF) +option(RCUTILS_NO_64_ATOMIC "Enable alternative support for 64 bits atomic operations in platforms with no native support." OFF) +option(RCUTILS_MICROROS "Flag for building micro-ROS." ON) + # Default to C11 if(NOT CMAKE_C_STANDARD) set(CMAKE_C_STANDARD 11) @@ -30,7 +36,7 @@ if(UNIX AND NOT APPLE) endif() endif() -if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") +if(NOT RCUTILS_MICROROS AND (CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")) # enables building a static library but later link it into a dynamic library add_compile_options(-fPIC) endif() @@ -76,6 +82,7 @@ set(rcutils_sources src/time.c ${time_impl_c} src/uint8_array.c + $<$:src/atomic_64bits.c> ) set_source_files_properties( ${rcutils_sources} @@ -130,6 +137,10 @@ target_compile_definitions(${PROJECT_NAME} PRIVATE "RCUTILS_BUILDING_DLL") if(BUILD_TESTING AND NOT RCUTILS_DISABLE_FAULT_INJECTION) target_compile_definitions(${PROJECT_NAME} PUBLIC RCUTILS_ENABLE_FAULT_INJECTION) endif() +configure_file( + "${PROJECT_SOURCE_DIR}/include/rcutils/configuration_flags.h.in" + "${PROJECT_BINARY_DIR}/include/rcutils/configuration_flags.h" +) target_link_libraries(${PROJECT_NAME} ${CMAKE_DL_LIBS}) diff --git a/include/rcutils/allocator.h b/include/rcutils/allocator.h index b6c76ba6..5547db28 100644 --- a/include/rcutils/allocator.h +++ b/include/rcutils/allocator.h @@ -85,6 +85,21 @@ RCUTILS_WARN_UNUSED rcutils_allocator_t rcutils_get_zero_initialized_allocator(void); +/// Set rcutils default allocators. +/** + *
+ * Attribute | Adherence + * ------------------ | ------------- + * Allocates Memory | No + * Thread-Safe | Yes + * Uses Atomics | No + * Lock-Free | Yes + */ +RCUTILS_PUBLIC +RCUTILS_WARN_UNUSED +bool +rcutils_set_default_allocator(rcutils_allocator_t * allocator); + /// Return a properly initialized rcutils_allocator_t with default values. /** * This defaults to: diff --git a/include/rcutils/configuration_flags.h.in b/include/rcutils/configuration_flags.h.in new file mode 100644 index 00000000..346c6a33 --- /dev/null +++ b/include/rcutils/configuration_flags.h.in @@ -0,0 +1,18 @@ + +#ifndef RCUTILS__CONFIGURATION_FLAGS_H_ +#define RCUTILS__CONFIGURATION_FLAGS_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#cmakedefine RCUTILS_NO_FILESYSTEM +#cmakedefine RCUTILS_AVOID_DYNAMIC_ALLOCATION +#cmakedefine RCUTILS_NO_THREAD_SUPPORT + +#ifdef __cplusplus +} +#endif + +#endif // RCUTILS__CONFIGURATION_FLAGS_H_ \ No newline at end of file diff --git a/include/rcutils/error_handling.h b/include/rcutils/error_handling.h index ee5667aa..2c7075e3 100644 --- a/include/rcutils/error_handling.h +++ b/include/rcutils/error_handling.h @@ -39,8 +39,9 @@ extern "C" #include "rcutils/testing/fault_injection.h" #include "rcutils/types/rcutils_ret.h" #include "rcutils/visibility_control.h" +#include "rcutils/configuration_flags.h" -#ifdef __STDC_LIB_EXT1__ +#if defined(__STDC_LIB_EXT1__) && !defined(RCUTILS_NO_FILESYSTEM) /// Write the given msg out to stderr, limiting the buffer size in the `fwrite`. /** * This ensures that there is an upper bound to a buffer overrun if `msg` is @@ -48,10 +49,11 @@ extern "C" */ #define RCUTILS_SAFE_FWRITE_TO_STDERR(msg) \ do {fwrite(msg, sizeof(char), strnlen_s(msg, 4096), stderr);} while (0) -#else -/// Write the given msg out to stderr. +#elif !defined(RCUTILS_NO_FILESYSTEM) #define RCUTILS_SAFE_FWRITE_TO_STDERR(msg) \ do {fwrite(msg, sizeof(char), strlen(msg), stderr);} while (0) +#else + #define RCUTILS_SAFE_FWRITE_TO_STDERR(msg) #endif /// Set the error message to stderr using a format string and format arguments. @@ -63,6 +65,8 @@ extern "C" * \param[in] format_string The string to be used as the format of the error message. * \param[in] ... Arguments for the format string. */ + +#if !defined(RCUTILS_AVOID_DYNAMIC_ALLOCATION) #define RCUTILS_SAFE_FWRITE_TO_STDERR_WITH_FORMAT_STRING(format_string, ...) \ do { \ char output_msg[RCUTILS_ERROR_MESSAGE_MAX_LENGTH]; \ @@ -73,7 +77,11 @@ extern "C" RCUTILS_SAFE_FWRITE_TO_STDERR(output_msg); \ } \ } while (0) +#else +#define RCUTILS_SAFE_FWRITE_TO_STDERR_WITH_FORMAT_STRING(format_string, ...) +#endif +#if !defined(RCUTILS_AVOID_DYNAMIC_ALLOCATION) /// The maximum length a formatted number is allowed to have. #define RCUTILS_ERROR_STATE_LINE_NUMBER_STR_MAX_LENGTH 20 // "18446744073709551615" @@ -100,6 +108,13 @@ extern "C" RCUTILS_ERROR_STATE_LINE_NUMBER_STR_MAX_LENGTH - \ RCUTILS_ERROR_FORMATTING_CHARACTERS - \ 1) +#else +#define RCUTILS_ERROR_STATE_LINE_NUMBER_STR_MAX_LENGTH 1 +#define RCUTILS_ERROR_FORMATTING_CHARACTERS 1 +#define RCUTILS_ERROR_MESSAGE_MAX_LENGTH 1 +#define RCUTILS_ERROR_STATE_MESSAGE_MAX_LENGTH 1 +#define RCUTILS_ERROR_STATE_FILE_MAX_LENGTH 1 +#endif // RCUTILS_AVOID_DYNAMIC_ALLOCATION /// Struct wrapping a fixed-size c string used for returning the formatted error string. typedef struct rcutils_error_string_s @@ -121,7 +136,7 @@ typedef struct rcutils_error_state_s } rcutils_error_state_t; // make sure our math is right... -#if __STDC_VERSION__ >= 201112L +#if __STDC_VERSION__ >= 201112L && !defined(RCUTILS_AVOID_DYNAMIC_ALLOCATION) static_assert( sizeof(rcutils_error_string_t) == ( RCUTILS_ERROR_STATE_MESSAGE_MAX_LENGTH + @@ -233,8 +248,12 @@ rcutils_set_error_state(const char * error_string, const char * file, size_t lin * * \param[in] msg The error message to be set. */ +#ifdef RCUTILS_AVOID_DYNAMIC_ALLOCATION + #define RCUTILS_SET_ERROR_MSG(msg) +#else #define RCUTILS_SET_ERROR_MSG(msg) \ do {rcutils_set_error_state(msg, __FILE__, __LINE__);} while (0) +#endif // RCUTILS_AVOID_DYNAMIC_ALLOCATION /// Set the error message using a format string and format arguments. /** @@ -245,6 +264,9 @@ rcutils_set_error_state(const char * error_string, const char * file, size_t lin * \param[in] format_string The string to be used as the format of the error message. * \param[in] ... Arguments for the format string. */ +#ifdef RCUTILS_AVOID_DYNAMIC_ALLOCATION + #define RCUTILS_SET_ERROR_MSG_WITH_FORMAT_STRING(format_string, ...) +#else #define RCUTILS_SET_ERROR_MSG_WITH_FORMAT_STRING(format_string, ...) \ do { \ char output_msg[RCUTILS_ERROR_MESSAGE_MAX_LENGTH]; \ @@ -255,6 +277,8 @@ rcutils_set_error_state(const char * error_string, const char * file, size_t lin RCUTILS_SET_ERROR_MSG(output_msg); \ } \ } while (0) +#endif // RCUTILS_AVOID_DYNAMIC_ALLOCATION + /// Indicate that the function intends to set an error message and return an error value. /** diff --git a/include/rcutils/logging.h b/include/rcutils/logging.h index 42eb2406..646d79bc 100644 --- a/include/rcutils/logging.h +++ b/include/rcutils/logging.h @@ -40,7 +40,7 @@ extern "C" * \def RCUTILS_DEFAULT_LOGGER_DEFAULT_LEVEL * \brief The default severity level of the default logger. */ -#define RCUTILS_DEFAULT_LOGGER_DEFAULT_LEVEL RCUTILS_LOG_SEVERITY_INFO +#define RCUTILS_DEFAULT_LOGGER_DEFAULT_LEVEL RCUTILS_LOG_SEVERITY_UNSET /// The flag if the logging system has been initialized. RCUTILS_PUBLIC diff --git a/include/rcutils/macros.h b/include/rcutils/macros.h index c18d36ea..b6d435f6 100644 --- a/include/rcutils/macros.h +++ b/include/rcutils/macros.h @@ -22,6 +22,8 @@ extern "C" { #endif +#include "rcutils/configuration_flags.h" + #ifndef _WIN32 /// A macro to make the compiler warn when the return value of a function is not used. #define RCUTILS_WARN_UNUSED __attribute__((warn_unused_result)) @@ -32,7 +34,9 @@ extern "C" /// \cond Doxygen_Suppress // This block either sets RCUTILS_THREAD_LOCAL or RCUTILS_THREAD_LOCAL_PTHREAD. -#if defined _WIN32 || defined __CYGWIN__ +#if defined(RCUTILS_NO_THREAD_SUPPORT) + #define RCUTILS_THREAD_LOCAL +#elif defined _WIN32 || defined __CYGWIN__ // Windows or Cygwin #define RCUTILS_THREAD_LOCAL __declspec(thread) #elif defined __APPLE__ diff --git a/include/rcutils/security_directory.h b/include/rcutils/security_directory.h new file mode 100644 index 00000000..9d2c6806 --- /dev/null +++ b/include/rcutils/security_directory.h @@ -0,0 +1,67 @@ +// Copyright 2018 Open Source Robotics Foundation, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef RCUTILS__SECURITY_DIRECTORY_H_ +#define RCUTILS__SECURITY_DIRECTORY_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "rcutils/allocator.h" +#include "rcutils/visibility_control.h" + +#ifndef ROS_SECURITY_NODE_DIRECTORY_VAR_NAME + #define ROS_SECURITY_NODE_DIRECTORY_VAR_NAME "ROS_SECURITY_NODE_DIRECTORY" +#endif + +#ifndef ROS_SECURITY_ROOT_DIRECTORY_VAR_NAME + #define ROS_SECURITY_ROOT_DIRECTORY_VAR_NAME "ROS_SECURITY_ROOT_DIRECTORY" +#endif + +#ifndef ROS_SECURITY_LOOKUP_TYPE_VAR_NAME + #define ROS_SECURITY_LOOKUP_TYPE_VAR_NAME "ROS_SECURITY_LOOKUP_TYPE" +#endif + +/// Return the secure root directory associated with a node given its validated name and namespace. +/** + * E.g. for a node named "c" in namespace "/a/b", the secure root path will be + * "a/b/c", where the delimiter "/" is native for target file system (e.g. "\\" for _WIN32). + * If no exact match is found for the node name, a best match would be used instead + * (by performing longest-prefix matching). + * + * However, this expansion can be overridden by setting the secure node directory environment + * variable, allowing users to explicitly specify the exact secure root directory to be utilized. + * Such an override is useful for where the FQN of a node is non-deterministic before runtime, + * or when testing and using additional tools that may not otherwise be easily provisioned. + * + * \param[in] node_name validated node name (a single token) + * \param[in] node_namespace validated, absolute namespace (starting with "/") + * \param[in] allocator the allocator to use for allocation + * \returns machine specific (absolute) node secure root path or NULL on failure + * returned pointer must be deallocated by the caller of this function + */ +RCUTILS_PUBLIC +char * rcutils_get_secure_root( + const char * node_name, + const char * node_namespace, + const rcutils_allocator_t * allocator +); + +#ifdef __cplusplus +} +#endif + +#endif // RCUTILS__SECURITY_DIRECTORY_H_ diff --git a/include/rcutils/testing/fault_injection.h b/include/rcutils/testing/fault_injection.h index d397fd74..d74a49bf 100644 --- a/include/rcutils/testing/fault_injection.h +++ b/include/rcutils/testing/fault_injection.h @@ -83,6 +83,8 @@ RCUTILS_WARN_UNUSED int_least64_t _rcutils_fault_injection_maybe_fail(void); +#ifdef RCUTILS_ENABLE_FAULT_INJECTION + /** * \def RCUTILS_FAULT_INJECTION_MAYBE_RETURN_ERROR * \brief This macro checks and decrements a static global variable atomic counter and returns @@ -199,6 +201,17 @@ _rcutils_fault_injection_maybe_fail(void); rcutils_fault_injection_set_count(no_fault_injection_count); \ } while (0) +#else + +// Mocks for micro-ROS when fault injection not enabled + +#define RCUTILS_FAULT_INJECTION_MAYBE_RETURN_ERROR(return_value_on_error) +#define RCUTILS_FAULT_INJECTION_MAYBE_FAIL(failure_code) +#define RCUTILS_FAULT_INJECTION_TEST(code) +#define RCUTILS_NO_FAULT_INJECTION(code) + +#endif + #ifdef __cplusplus } #endif diff --git a/resource/logging_macros.h.em b/resource/logging_macros.h.em index 1b87e496..6f8d7f5e 100644 --- a/resource/logging_macros.h.em +++ b/resource/logging_macros.h.em @@ -51,7 +51,7 @@ extern "C" * Use RCUTILS_LOG_MIN_SEVERITY_NONE to compile out all macros. */ #ifndef RCUTILS_LOG_MIN_SEVERITY -#define RCUTILS_LOG_MIN_SEVERITY RCUTILS_LOG_MIN_SEVERITY_DEBUG +#define RCUTILS_LOG_MIN_SEVERITY RCUTILS_LOG_MIN_SEVERITY_NONE #endif // TODO(dhood): optimise severity check via notifyLoggerLevelsChanged concept or similar. diff --git a/src/allocator.c b/src/allocator.c index 0309da95..886aee72 100644 --- a/src/allocator.c +++ b/src/allocator.c @@ -75,16 +75,31 @@ rcutils_get_zero_initialized_allocator(void) return zero_allocator; } -rcutils_allocator_t -rcutils_get_default_allocator() -{ - static rcutils_allocator_t default_allocator = { +static rcutils_allocator_t default_allocator = { .allocate = __default_allocate, .deallocate = __default_deallocate, .reallocate = __default_reallocate, .zero_allocate = __default_zero_allocate, .state = NULL, }; + +bool +rcutils_set_default_allocator(rcutils_allocator_t * allocator){ + if (rcutils_allocator_is_valid(allocator)) + { + default_allocator.allocate = allocator->allocate; + default_allocator.deallocate = allocator->deallocate; + default_allocator.reallocate = allocator->reallocate; + default_allocator.zero_allocate = allocator->zero_allocate; + default_allocator.state = NULL; + return true; + } + return false; +} + +rcutils_allocator_t +rcutils_get_default_allocator() +{ return default_allocator; } diff --git a/src/atomic_64bits.c b/src/atomic_64bits.c new file mode 100644 index 00000000..f11a39da --- /dev/null +++ b/src/atomic_64bits.c @@ -0,0 +1,92 @@ +// Copyright 2020 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include +#include + +#define FLAGS_LEN 23 + +static bool * get_memory_lock(void *address) +{ + static bool memory_locks[FLAGS_LEN] = { 0 }; + uintptr_t a = (uintptr_t)(address); + + // Public domain hash function taken from http://burtleburtle.net/bob/hash/integer.html + a = (a ^ 61) ^ (a >> 16); + a = a + (a << 3); + a = a ^ (a >> 4); + a = a * 0x27d4eb2d; + a = a ^ (a >> 15); + + a = a % FLAGS_LEN; + return memory_locks + a; +} + +void lock_memory(uint64_t *address){ + bool * memory_lock = get_memory_lock(address); + + while (__atomic_test_and_set(memory_lock, __ATOMIC_ACQUIRE) == 1); +} + +void unlock_memory(uint64_t *address){ + bool * memory_lock = get_memory_lock(address); + + __atomic_clear(memory_lock, __ATOMIC_RELEASE); +} + +uint64_t __atomic_load_8(uint64_t *mem, int model) { + (void) model; + + lock_memory(mem); + uint64_t ret = *mem; + unlock_memory(mem); + return ret; +} + +void __atomic_store_8(uint64_t *mem, uint64_t val, int model) { + (void) model; + + lock_memory(mem); + *mem = val; + unlock_memory(mem); +} + +uint64_t __atomic_exchange_8(uint64_t *mem, uint64_t val, int model) { + (void) model; + + lock_memory(mem); + uint64_t ret = *mem; + *mem = val; + unlock_memory(mem); + return ret; +} + +uint64_t __atomic_fetch_add_8(uint64_t *mem, uint64_t val, int model) { + (void) model; + + lock_memory(mem); + uint64_t ret = *mem; + *mem += val; + unlock_memory(mem); + return ret; +} + +#ifdef __cplusplus +} +#endif diff --git a/src/error_handling_helpers.h b/src/error_handling_helpers.h index 4914c4fe..b6a1dc67 100644 --- a/src/error_handling_helpers.h +++ b/src/error_handling_helpers.h @@ -108,6 +108,7 @@ static void __rcutils_convert_uint64_t_into_c_str(uint64_t number, char * buffer, size_t buffer_size) { +#if !defined(RCUTILS_AVOID_DYNAMIC_ALLOCATION) assert(buffer != NULL); assert(buffer_size >= 21); (void)buffer_size; // prevent warning in release builds where there is no assert(...) @@ -131,6 +132,7 @@ __rcutils_convert_uint64_t_into_c_str(uint64_t number, char * buffer, size_t buf // reverse the string in place __rcutils_reverse_str(buffer, strnlen(buffer, 21)); +#endif } // do not use externally, internal function which is only to be used by error_handling.c @@ -140,6 +142,7 @@ __rcutils_format_error_string( rcutils_error_string_t * error_string, const rcutils_error_state_t * error_state) { +#if !defined(RCUTILS_AVOID_DYNAMIC_ALLOCATION) assert(error_string != NULL); assert(error_state != NULL); static const char format_1[] = ", at "; @@ -173,6 +176,7 @@ __rcutils_format_error_string( written = __rcutils_copy_string(offset, bytes_left, line_number_buffer); offset += written; offset[0] = '\0'; +#endif } #ifdef __cplusplus diff --git a/src/filesystem.c b/src/filesystem.c index c88e74ae..604118ae 100644 --- a/src/filesystem.c +++ b/src/filesystem.c @@ -22,9 +22,13 @@ extern "C" #include #include #include +#ifndef RCUTILS_NO_FILESYSTEM #include +#endif #ifndef _WIN32 +#ifndef RCUTILS_NO_FILESYSTEM #include +#endif #include #else // When building with MSVC 19.28.29333.0 on Windows 10 (as of 2020-11-11), @@ -54,6 +58,9 @@ extern "C" # define RCUTILS_PATH_DELIMITER "/" #endif // _WIN32 +#ifdef RCUTILS_NO_FILESYSTEM +typedef int DIR; +#endif // _RCUTILS_NO_FILESYSTEM typedef struct rcutils_dir_iter_state_t { #ifdef _WIN32 @@ -67,6 +74,12 @@ typedef struct rcutils_dir_iter_state_t bool rcutils_get_cwd(char * buffer, size_t max_length) { +#ifdef RCUTILS_NO_FILESYSTEM + (void) buffer; + (void) max_length; + RCUTILS_SET_ERROR_MSG("not available filesystem"); + return false; +#else if (NULL == buffer || max_length == 0) { return false; } @@ -80,11 +93,17 @@ rcutils_get_cwd(char * buffer, size_t max_length) } #endif // _WIN32 return true; +#endif // _RCUTILS_NO_FILESYSTEM } bool rcutils_is_directory(const char * abs_path) { +#ifdef RCUTILS_NO_FILESYSTEM + (void) abs_path; + RCUTILS_SET_ERROR_MSG("not available filesystem"); + return false; +#else struct stat buf; if (stat(abs_path, &buf) < 0) { return false; @@ -94,11 +113,17 @@ rcutils_is_directory(const char * abs_path) #else return S_ISDIR(buf.st_mode); #endif // _WIN32 +#endif // _RCUTILS_NO_FILESYSTEM } bool rcutils_is_file(const char * abs_path) { +#ifdef RCUTILS_NO_FILESYSTEM + (void) abs_path; + RCUTILS_SET_ERROR_MSG("not available filesystem"); + return false; +#else struct stat buf; if (stat(abs_path, &buf) < 0) { return false; @@ -108,21 +133,33 @@ rcutils_is_file(const char * abs_path) #else return S_ISREG(buf.st_mode); #endif // _WIN32 +#endif // _RCUTILS_NO_FILESYSTEM } bool rcutils_exists(const char * abs_path) { +#ifdef RCUTILS_NO_FILESYSTEM + (void) abs_path; + RCUTILS_SET_ERROR_MSG("not available filesystem"); + return false; +#else struct stat buf; if (stat(abs_path, &buf) < 0) { return false; } return true; +#endif // _RCUTILS_NO_FILESYSTEM } bool rcutils_is_readable(const char * abs_path) { +#ifdef RCUTILS_NO_FILESYSTEM + (void) abs_path; + RCUTILS_SET_ERROR_MSG("not available filesystem"); + return false; +#else struct stat buf; if (stat(abs_path, &buf) < 0) { return false; @@ -135,11 +172,17 @@ rcutils_is_readable(const char * abs_path) return false; } return true; +#endif // _RCUTILS_NO_FILESYSTEM } bool rcutils_is_writable(const char * abs_path) { +#ifdef RCUTILS_NO_FILESYSTEM + (void) abs_path; + RCUTILS_SET_ERROR_MSG("not available filesystem"); + return false; +#else struct stat buf; if (stat(abs_path, &buf) < 0) { return false; @@ -152,11 +195,17 @@ rcutils_is_writable(const char * abs_path) return false; } return true; +#endif // _RCUTILS_NO_FILESYSTEM } bool rcutils_is_readable_and_writable(const char * abs_path) { +#ifdef RCUTILS_NO_FILESYSTEM + (void) abs_path; + RCUTILS_SET_ERROR_MSG("not available filesystem"); + return false; +#else struct stat buf; if (stat(abs_path, &buf) < 0) { return false; @@ -171,6 +220,7 @@ rcutils_is_readable_and_writable(const char * abs_path) return false; } return true; +#endif // _RCUTILS_NO_FILESYSTEM } char * @@ -179,6 +229,13 @@ rcutils_join_path( const char * right_hand_path, rcutils_allocator_t allocator) { +#ifdef RCUTILS_NO_FILESYSTEM + (void) left_hand_path; + (void) right_hand_path; + (void) allocator; + RCUTILS_SET_ERROR_MSG("not available filesystem"); + return NULL; +#else if (NULL == left_hand_path) { return NULL; } @@ -190,6 +247,7 @@ rcutils_join_path( allocator, "%s%s%s", left_hand_path, RCUTILS_PATH_DELIMITER, right_hand_path); +#endif // _RCUTILS_NO_FILESYSTEM } char * @@ -197,16 +255,29 @@ rcutils_to_native_path( const char * path, rcutils_allocator_t allocator) { +#ifdef RCUTILS_NO_FILESYSTEM + (void) path; + (void) allocator; + RCUTILS_SET_ERROR_MSG("not available filesystem"); + return NULL; +#else if (NULL == path) { return NULL; } return rcutils_repl_str(path, "/", RCUTILS_PATH_DELIMITER, &allocator); +#endif // _RCUTILS_NO_FILESYSTEM } char * rcutils_expand_user(const char * path, rcutils_allocator_t allocator) { +#ifdef RCUTILS_NO_FILESYSTEM + (void) path; + (void) allocator; + RCUTILS_SET_ERROR_MSG("not available filesystem"); + return NULL; +#else if (NULL == path) { return NULL; } @@ -225,11 +296,17 @@ rcutils_expand_user(const char * path, rcutils_allocator_t allocator) "%s%s", homedir, path + 1); +#endif // _RCUTILS_NO_FILESYSTEM } bool rcutils_mkdir(const char * abs_path) { +#ifdef RCUTILS_NO_FILESYSTEM + (void) abs_path; + RCUTILS_SET_ERROR_MSG("not available filesystem"); + return false; +#else if (NULL == abs_path) { return false; } @@ -257,6 +334,7 @@ rcutils_mkdir(const char * abs_path) } return success; +#endif // _RCUTILS_NO_FILESYSTEM } rcutils_ret_t @@ -275,6 +353,7 @@ typedef struct dir_list_t struct dir_list_t * next; } dir_list_t; +#ifndef RCUTILS_NO_FILESYSTEM static void free_dir_list(dir_list_t * dir_list, rcutils_allocator_t allocator) { dir_list_t * next_dir; @@ -337,6 +416,7 @@ static rcutils_ret_t check_and_calculate_size( return RCUTILS_RET_OK; } +#endif // _RCUTILS_NO_FILESYSTEM rcutils_ret_t rcutils_calculate_directory_size_with_recursion( @@ -345,6 +425,14 @@ rcutils_calculate_directory_size_with_recursion( uint64_t * size, rcutils_allocator_t allocator) { +#ifdef RCUTILS_NO_FILESYSTEM + (void) directory_path; + (void) max_depth; + (void) size; + (void) allocator; + RCUTILS_SET_ERROR_MSG("not available filesystem"); + return RCUTILS_RET_ERROR; +#else dir_list_t * dir_list = NULL; rcutils_ret_t ret = RCUTILS_RET_OK; rcutils_dir_iter_t * iter = NULL; @@ -359,6 +447,8 @@ rcutils_calculate_directory_size_with_recursion( return RCUTILS_RET_INVALID_ARGUMENT; } + size_t dir_size = 0; + if (!rcutils_is_directory(directory_path)) { RCUTILS_SAFE_FWRITE_TO_STDERR_WITH_FORMAT_STRING( "Path is not a directory: %s\n", directory_path); @@ -407,11 +497,18 @@ rcutils_calculate_directory_size_with_recursion( rcutils_dir_iter_end(iter); free_dir_list(dir_list, allocator); return ret; +#endif // _RCUTILS_NO_FILESYSTEM } rcutils_dir_iter_t * rcutils_dir_iter_start(const char * directory_path, const rcutils_allocator_t allocator) { +#ifdef RCUTILS_NO_FILESYSTEM + (void) directory_path; + (void) allocator; + RCUTILS_SET_ERROR_MSG("not available filesystem"); + return NULL; +#else RCUTILS_CHECK_ARGUMENT_FOR_NULL(directory_path, NULL); RCUTILS_CHECK_ALLOCATOR_WITH_MSG( &allocator, "allocator is invalid", return NULL); @@ -473,11 +570,17 @@ rcutils_dir_iter_start(const char * directory_path, const rcutils_allocator_t al rcutils_dir_iter_start_fail: rcutils_dir_iter_end(iter); return NULL; +#endif // _RCUTILS_NO_FILESYSTEM } bool rcutils_dir_iter_next(rcutils_dir_iter_t * iter) { +#ifdef RCUTILS_NO_FILESYSTEM + (void) iter; + RCUTILS_SET_ERROR_MSG("not available filesystem"); + return false; +#else RCUTILS_CHECK_ARGUMENT_FOR_NULL(iter, false); rcutils_dir_iter_state_t * state = (rcutils_dir_iter_state_t *)iter->state; RCUTILS_CHECK_FOR_NULL_WITH_MSG(state, "iter is invalid", false); @@ -498,11 +601,16 @@ rcutils_dir_iter_next(rcutils_dir_iter_t * iter) iter->entry_name = NULL; return false; +#endif // _RCUTILS_NO_FILESYSTEM } void rcutils_dir_iter_end(rcutils_dir_iter_t * iter) { +#ifdef RCUTILS_NO_FILESYSTEM + (void) iter; + RCUTILS_SET_ERROR_MSG("not available filesystem"); +#else if (NULL == iter) { return; } @@ -522,11 +630,18 @@ rcutils_dir_iter_end(rcutils_dir_iter_t * iter) } allocator.deallocate(iter, allocator.state); +#endif // _RCUTILS_NO_FILESYSTEM } size_t rcutils_get_file_size(const char * file_path) { + +#ifdef RCUTILS_NO_FILESYSTEM + (void) file_path; + RCUTILS_SET_ERROR_MSG("not available filesystem"); + return 0; +#else if (!rcutils_is_file(file_path)) { RCUTILS_SAFE_FWRITE_TO_STDERR_WITH_FORMAT_STRING( "Path is not a file: %s\n", file_path); @@ -536,6 +651,7 @@ rcutils_get_file_size(const char * file_path) struct stat stat_buffer; int rc = stat(file_path, &stat_buffer); return rc == 0 ? (size_t)(stat_buffer.st_size) : 0; +#endif // _RCUTILS_NO_FILESYSTEM } #ifdef __cplusplus diff --git a/src/process.c b/src/process.c index 9f21bbf7..e3f7755b 100644 --- a/src/process.c +++ b/src/process.c @@ -61,7 +61,13 @@ char * rcutils_get_executable_name(rcutils_allocator_t allocator) #if defined __APPLE__ || defined __FreeBSD__ || (defined __ANDROID__ && __ANDROID_API__ >= 21) const char * appname = getprogname(); #elif defined __GNUC__ && !defined(__QNXNTO__) && !defined(__OHOS__) - const char * appname = program_invocation_name; + #if defined __linux__ || defined __linux || defined __gnu_linux__ || defined linux + const char * appname = program_invocation_name; + #else + // Some embedded OS compile with __GNUC__ but are not quite conformant with GNU-specific extensions. + // They may fake to have a GLIBC in their custom C library implementation. + const char * appname = ""; + #endif #elif defined _WIN32 || defined __CYGWIN__ char appname[MAX_PATH]; int32_t size = GetModuleFileNameA(NULL, appname, MAX_PATH); diff --git a/src/shared_library.c b/src/shared_library.c index f26d6b15..4d73f0e3 100644 --- a/src/shared_library.c +++ b/src/shared_library.c @@ -19,6 +19,10 @@ extern "C" #include #include +#include "rcutils/configuration_flags.h" + +#ifndef RCUTILS_NO_FILESYSTEM + #ifndef _WIN32 #if defined(__APPLE__) #include @@ -48,6 +52,8 @@ C_ASSERT(sizeof(void *) == sizeof(HINSTANCE)); C_ASSERT(sizeof(char) == sizeof(TCHAR)); #endif // _WIN32 +#endif //RCUTILS_NO_FILESYSTEM + #include "rcutils/error_handling.h" #include "rcutils/macros.h" #include "rcutils/shared_library.h" @@ -69,6 +75,7 @@ rcutils_load_shared_library( const char * library_path, rcutils_allocator_t allocator) { +#ifndef RCUTILS_NO_FILESYSTEM RCUTILS_CAN_RETURN_WITH_ERROR_OF(RCUTILS_RET_INVALID_ARGUMENT); RCUTILS_CAN_RETURN_WITH_ERROR_OF(RCUTILS_RET_BAD_ALLOC); RCUTILS_CAN_RETURN_WITH_ERROR_OF(RCUTILS_RET_ERROR); @@ -195,11 +202,20 @@ rcutils_load_shared_library( } return ret; #endif // _WIN32 + +#else + (void) lib; + (void) library_path; + (void) allocator; + return RCUTILS_RET_ERROR; +#endif //RCUTILS_NO_FILESYSTEM + } void * rcutils_get_symbol(const rcutils_shared_library_t * lib, const char * symbol_name) { +#ifndef RCUTILS_NO_FILESYSTEM if (!lib || !lib->lib_pointer || (symbol_name == NULL)) { RCUTILS_SET_ERROR_MSG("invalid inputs arguments"); return NULL; @@ -230,11 +246,17 @@ rcutils_get_symbol(const rcutils_shared_library_t * lib, const char * symbol_nam return NULL; } return lib_symbol; +#else + (void) lib; + (void) symbol_name; + return NULL; +#endif //RCUTILS_NO_FILESYSTEM } bool rcutils_has_symbol(const rcutils_shared_library_t * lib, const char * symbol_name) { +#ifndef RCUTILS_NO_FILESYSTEM if (!lib || !lib->lib_pointer || symbol_name == NULL) { return false; } @@ -250,11 +272,17 @@ rcutils_has_symbol(const rcutils_shared_library_t * lib, const char * symbol_nam void * lib_symbol = GetProcAddress((HINSTANCE)(lib->lib_pointer), symbol_name); return lib_symbol != NULL; #endif // _WIN32 +#else + (void) lib; + (void) symbol_name; + return false; +#endif //RCUTILS_NO_FILESYSTEM } rcutils_ret_t rcutils_unload_shared_library(rcutils_shared_library_t * lib) { +#ifndef RCUTILS_NO_FILESYSTEM RCUTILS_CHECK_ARGUMENT_FOR_NULL(lib, RCUTILS_RET_INVALID_ARGUMENT); RCUTILS_CHECK_ARGUMENT_FOR_NULL(lib->lib_pointer, RCUTILS_RET_INVALID_ARGUMENT); RCUTILS_CHECK_ARGUMENT_FOR_NULL(lib->library_path, RCUTILS_RET_INVALID_ARGUMENT); @@ -280,6 +308,10 @@ rcutils_unload_shared_library(rcutils_shared_library_t * lib) lib->lib_pointer = NULL; lib->allocator = rcutils_get_zero_initialized_allocator(); return ret; +#else + (void) lib; + return RCUTILS_RET_ERROR; +#endif //RCUTILS_NO_FILESYSTEM } rcutils_ret_t @@ -289,6 +321,7 @@ rcutils_get_platform_library_name( unsigned int buffer_size, bool debug) { +#ifndef RCUTILS_NO_FILESYSTEM RCUTILS_CHECK_ARGUMENT_FOR_NULL(library_name, RCUTILS_RET_INVALID_ARGUMENT); RCUTILS_CHECK_ARGUMENT_FOR_NULL(library_name_platform, RCUTILS_RET_INVALID_ARGUMENT); @@ -338,6 +371,13 @@ rcutils_get_platform_library_name( return RCUTILS_RET_ERROR; } return RCUTILS_RET_OK; +#else + (void) library_name; + (void) library_name_platform; + (void) buffer_size; + (void) debug; + return RCUTILS_RET_ERROR; +#endif //RCUTILS_NO_FILESYSTEM } bool diff --git a/src/time_unix.c b/src/time_unix.c index 27ea623a..92ada574 100644 --- a/src/time_unix.c +++ b/src/time_unix.c @@ -45,7 +45,7 @@ // This is an appropriate check for clock_gettime() according to: // http://man7.org/linux/man-pages/man2/clock_gettime.2.html # if !defined(_POSIX_TIMERS) || !_POSIX_TIMERS -# error no monotonic clock function available +# warning no monotonic clock function available # endif // !defined(_POSIX_TIMERS) || !_POSIX_TIMERS #endif // !defined(__MACH__) && !defined(__APPLE__)