osaf/libs/core/common/Makefile.am | 1 + osaf/libs/core/common/include/osaf_extended_name.h | 232 +++++++++++++++++++++ osaf/libs/core/common/osaf_extended_name.c | 184 ++++++++++++++++ osaf/libs/core/leap/sysf_def.c | 3 + 4 files changed, 420 insertions(+), 0 deletions(-)
These library functions are primarily intended to be used in agent libraries, to handle the old SAF APIs that still are using the SaNameT type. diff --git a/osaf/libs/core/common/Makefile.am b/osaf/libs/core/common/Makefile.am --- a/osaf/libs/core/common/Makefile.am +++ b/osaf/libs/core/common/Makefile.am @@ -34,6 +34,7 @@ libopensaf_common_la_SOURCES = \ osaf_utility.c \ osaf_poll.c \ osaf_time.c \ + osaf_extended_name.c \ nid_start_util.c \ saf_edu.c \ daemon.c \ diff --git a/osaf/libs/core/common/include/osaf_extended_name.h b/osaf/libs/core/common/include/osaf_extended_name.h new file mode 100644 --- /dev/null +++ b/osaf/libs/core/common/include/osaf_extended_name.h @@ -0,0 +1,232 @@ +/* -*- OpenSAF -*- + * + * (C) Copyright 2014 The OpenSAF Foundation + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed + * under the GNU Lesser General Public License Version 2.1, February 1999. + * The complete license can be accessed from the following location: + * http://opensource.org/licenses/lgpl-license.php + * See the Copying file included with the OpenSAF distribution for full + * licensing terms. + * + * Author(s): Ericsson AB + * + */ + +/** @file + * + * This file contains functions to support tunneling strings through the legacy + * SaNameT structure. The definitions in this file are for internal use within + * OpenSAF only, and are intended to be used by the agent libraries to support + * legacy SAF API functions that have SaNameT parameters. + */ + +#ifndef OPENSAF_OSAF_LIBS_CORE_COMMON_INCLUDE_OSAF_EXTENDED_NAME_H_ +#define OPENSAF_OSAF_LIBS_CORE_COMMON_INCLUDE_OSAF_EXTENDED_NAME_H_ + +#include <stddef.h> +#include <stdbool.h> +#include "saAis.h" + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + /** + * Magic number stored in the .length field (the first 16-bit word) of the + * legacy SaNameT type, to indicate that it contains a string longer than or + * equal to SA_MAX_UNEXTENDED_NAME_LENGTH bytes. A pointer to the string is + * stored immediately after the first 16-bit word (typically in the first + * four or eight bytes of the .value field of the legacy SaNameT type. + */ + kExtendedNameMagic = 0xcd2b, + + /** + * Maximum length of a distinguished name, not counting the terminating NUL + * character. + */ + kMaxDnLength = 2048 +}; + +/** + * @brief Initialize the extended SaNameT functionality. + * + * This function reads the environment variable SA_ENABLE_EXTENDED_NAMES to + * determine whether extended SaNameT shall be enabled or not. It shall be + * called by all top-level saXxxInitialize() functions, so that it is + * guaranteed to have been called before any other SAF API function. + */ +void osaf_extended_name_init(void); + +/** + * @brief Check whether extended SaNameT is enabled. + * + * This function returns true if extended SaNameT is enabled, and false + * otherwise. The function osaf_extended_name_init() must have been called + * prior to calling this function. + */ +static inline bool osaf_is_extended_names_enabled(void); + +/** + * @brief Set the string pointer in the legacy SaNameT type. + * + * This function sets the legacy SaNameT @a name to the NUL-terminated string + * @a value. If length of the string @a value is strictly less than + * SA_MAX_UNEXTENDED_NAME_LENGTH bytes, the contents of the string is copied + * into the legacy SaNameT type and can be read in a backwards compatible way + * by legacy applications. If length of the string @a value is greater than or + * equal to SA_MAX_UNEXTENDED_NAME_LENGTH, no copying is performed. Instead, a + * reference to the original string @a value is stored in @a name. In this + * case, it is important that @a value is not modified or freed until @a name + * is either overwritten or freed. + */ +void osaf_extended_name_lend(SaConstStringT value, SaNameT* name); + +/** + * @brief Get a pointer to the string in the legacy SaNameT type. + * + * This function returns a pointer to the string value in the legacy SaNameT @a + * name. If the .length field of the legacy SaNameT structure is not equal to + * the magic number @a kExtendedNameMagic, the returned pointer points to a + * copy of the string stored inside @a name. Otherwise, the returned pointer + * points to memory outside @a name. + * + * NOTE: This function is intended to be used in agent libraries to read + * SaNameT structures that may have been set by legacy application + * code. Therefore, the returned string pointer is not guaranteed to be NUL + * terminated. To get NUL-terminated string, you can do the following: use + * osaf_extended_name_length() to calculate the length of the string, call + * malloc() to allocate a memory area that is one byte larger than the string + * length, then use memcpy() to copy the string to the allocated memory, and + * finally add a NUL character at the end of the copied string. + */ +SaConstStringT osaf_extended_name_borrow(const SaNameT* name); + +/** + * @brief Check if an SaNameT is in using the extended (long) format. + * + * This function returns true if the SaNameT @a name is using the new extended + * (long) format where the SaNameT structure contains a pointer to the string, + * and false if @a name is using the legacy format where a copy of the string + * is stored inside the SaNameT structure. + */ +bool osaf_is_an_extended_name(const SaNameT* name); + +/** + * @brief Check if an SaNameT passes some sanity checks. + * + * This function returns true if the SaNameT @a name passes some sanity checks, + * e.g. that the length field is either equal to the magic number @a + * kExtendedNameMagic, or strictly less than SA_MAX_UNEXTENDED_NAME_LENGTH. It + * returns false if @a name failed some of the sanity checks. It may of course + * also crash the process if @a name is severly corrupted, e.g. if the pointer + * stored inside @a name points to inaccessible memory. + * + * NOTE: This function is intended to be used in agent libraries to read + * SaNameT structures that may have been set by legacy application + * code. Therefore, it does not require the string to be NUL terminated if it + * is stored in the legacy (short) format. + */ +bool osaf_is_extended_name_valid(const SaNameT* name); + +/** + * @brief Check if an SaNameT contains the empty string. + * + * This function works also with legacy SaNameT structures containing a string + * that is not NUL-terminated, and strings where there is a mismatch between + * the string length as indicated by the .length field an any NUL character + * contained in the string. It is equivalent to checking if the result of + * osaf_extended_name_length() is equal to zero, but may execute faster. + */ +bool osaf_is_extended_name_empty(const SaNameT* name); + +/** + * @brief Calculate the length of an SaNameT. + * + * This function returns the length of the SaNameT @a name. It may abort the + * process if @a name is not valid, but the sanity checks in this function are + * guaranteed to be no stricter than the checks in the + * osaf_is_extended_name_valid() function. + * + * This function works also with legacy SaNameT structures containing a string + * that is not NUL-terminated, and strings where there is a mismatch between + * the string length as indicated by the .length field an any NUL character + * contained in the string (in which case the shortest of the two string + * lengths is returned). + */ +size_t osaf_extended_name_length(const SaNameT* name); + +/** + * @brief Set an SaNameT to the empty string. + * + * This function sets @a name to the empty string, i.e. a string of length + * zero. + */ +void osaf_extended_name_clear(SaNameT* name); + +/** + * @brief Move a dynamically allocated string into an SaNameT structure. + * + * This function sets the SaNameT structure @a name to point to the dynamically + * allocated string @a value. The string @a value must have been dynamically + * allocated using malloc(), calloc(), strdup() or a similar function. When + * this function returns, the original string pointer @a value is no longer + * valid and must not be used. When the SaNameT structure @a name is no longer + * needed, the dynamically allocated memory must be freed by a call to + * osaf_extended_name_free(). + * + * This function works also in the case when @a value is a NULL pointer, in + * which case it simply calls osaf_extended_name_clear(). + */ +void osaf_extended_name_steal(SaStringT value, SaNameT* name); + +/** + * @brief Make a copy of a string and store it in an SaNameT structure. + * + * This function sets @a name to point to a newly allocated copy of the string + * @a value. When the SaNameT structure @a name is no longer needed, the + * dynamically allocated memory must be freed by a call to + * osaf_extended_name_free(). + * + * When the length of the string is strictly less than + * SA_MAX_UNEXTENDED_NAME_LENGTH, the SaNameT structure can be used in a + * backwards compatible way by legacy applications that do not understand the + * new extended SaNameT format. + * + * This function works also in the case when @a value is a NULL pointer, in + * which case it simply calls osaf_extended_name_clear(). + */ +void osaf_extended_name_alloc(SaConstStringT value, SaNameT* name); + +/** + * @brief Free dynamically allocated memory pointed to by an SaNameT. + * + * This function checks if the SaNameT @a name contains a pointer (i.e. is + * using the new extended format), and if so, it will call free() to release + * the dynamically allocated memory referenced by this SaNameT. When this + * function returns, @a name is no longer valid and must not be used (until it + * is re-initialized). + * + * When the length of the string is strictly less than + * SA_MAX_UNEXTENDED_NAME_LENGTH, the SaNameT structure can be used in a + * backwards compatible way by legacy applications that do not understand the + * new extended SaNameT format. + * + * This function works also in the case when @a name is a NULL pointer, in + * which case it does nothing. + */ +void osaf_extended_name_free(SaNameT* name); + +static inline bool osaf_is_extended_names_enabled(void) { + extern bool osaf_extended_names_enabled; + return osaf_extended_names_enabled; +} + +#ifdef __cplusplus +} +#endif + +#endif /* OPENSAF_OSAF_LIBS_CORE_COMMON_INCLUDE_OSAF_EXTENDED_NAME_H_ */ diff --git a/osaf/libs/core/common/osaf_extended_name.c b/osaf/libs/core/common/osaf_extended_name.c new file mode 100644 --- /dev/null +++ b/osaf/libs/core/common/osaf_extended_name.c @@ -0,0 +1,184 @@ +/* -*- OpenSAF -*- + * + * (C) Copyright 2014 The OpenSAF Foundation + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed + * under the GNU Lesser General Public License Version 2.1, February 1999. + * The complete license can be accessed from the following location: + * http://opensource.org/licenses/lgpl-license.php + * See the Copying file included with the OpenSAF distribution for full + * licensing terms. + * + * Author(s): Ericsson AB + * + */ + +#ifndef SA_EXTENDED_NAME_SOURCE +#define SA_EXTENDED_NAME_SOURCE +#endif +#define _GNU_SOURCE +#include <stdlib.h> +#include <string.h> +#include "osaf_extended_name.h" +#include "ncsgl_defs.h" + +static inline SaConstStringT get_ptr(const SaNameT* name); +static inline void set_ptr(SaConstStringT value, SaNameT* name); + +bool osaf_extended_names_enabled = false; +static bool extended_names_initialized = false; + +static inline SaConstStringT get_ptr(const SaNameT* name) +{ + union { + SaConstStringT pointer; + SaUint8T bytes[sizeof(SaConstStringT)]; + } tmp; + memcpy(tmp.bytes, name->_opaque + 1, sizeof(SaConstStringT)); + return tmp.pointer; +} + +static inline void set_ptr(SaConstStringT value, SaNameT* name) +{ + union { + SaConstStringT pointer; + SaUint8T bytes[sizeof(SaConstStringT)]; + } tmp; + tmp.pointer = value; + name->_opaque[0] = kExtendedNameMagic; + memcpy(name->_opaque + 1, tmp.bytes, sizeof(SaConstStringT)); +} + +void osaf_extended_name_init(void) +{ + if (!extended_names_initialized) { + char* enable = getenv("SA_ENABLE_EXTENDED_NAMES"); + if (enable != NULL && enable[0] == '1' && enable[1] == '\0') { + osaf_extended_names_enabled = true; + } else { + osaf_extended_names_enabled = false; + } + extended_names_initialized = true; + } +} + +void osaf_extended_name_lend(SaConstStringT value, SaNameT* name) +{ + size_t length = strlen(value); + if (length < SA_MAX_UNEXTENDED_NAME_LENGTH) { + name->_opaque[0] = length; + memcpy(name->_opaque + 1, value, length + 1); + } else { + set_ptr(value, name); + } +} + +SaConstStringT osaf_extended_name_borrow(const SaNameT* name) +{ + size_t length = name->_opaque[0]; + SaConstStringT value; + if (length != kExtendedNameMagic) { + value = (SaConstStringT) (name->_opaque + 1); + } else { + value = get_ptr(name); + } + return value; +} + +bool osaf_is_an_extended_name(const SaNameT* name) +{ + return name->_opaque[0] == kExtendedNameMagic; +} + +bool osaf_is_extended_name_valid(const SaNameT* name) +{ + size_t length = name->_opaque[0]; + bool is_valid; + if (length != kExtendedNameMagic) { + is_valid = length < SA_MAX_UNEXTENDED_NAME_LENGTH; + } else { + is_valid = osaf_extended_names_enabled && + strnlen(get_ptr(name), SA_MAX_UNEXTENDED_NAME_LENGTH) >= + SA_MAX_UNEXTENDED_NAME_LENGTH; + } + return is_valid; +} + +bool osaf_is_extended_name_empty(const SaNameT* name) +{ + size_t length = name->_opaque[0]; + bool is_empty; + if (length != kExtendedNameMagic) { + is_empty = length == 0; + } else { + is_empty = *get_ptr(name) == '\0'; + } + return is_empty; +} + +size_t osaf_extended_name_length(const SaNameT* name) +{ + size_t length = name->_opaque[0]; + if (length != kExtendedNameMagic) { + osafassert(length < SA_MAX_UNEXTENDED_NAME_LENGTH); + length = strnlen((const char*) (name->_opaque + 1), length); + } else { + length = strlen(get_ptr(name)); + osafassert(osaf_extended_names_enabled && + length >= SA_MAX_UNEXTENDED_NAME_LENGTH); + } + return length; +} + +void osaf_extended_name_clear(SaNameT* name) +{ + name->_opaque[0] = 0; + memset(name->_opaque + 1, 0, sizeof(SaConstStringT)); +} + +void osaf_extended_name_steal(SaStringT value, SaNameT* name) +{ + if (value != NULL) { + size_t length = strlen(value); + if (length < SA_MAX_UNEXTENDED_NAME_LENGTH) { + name->_opaque[0] = length; + memcpy(name->_opaque + 1, value, length + 1); + free(value); + } else { + set_ptr(value, name); + } + } else { + osaf_extended_name_clear(name); + } +} + +void osaf_extended_name_alloc(SaConstStringT value, SaNameT* name) +{ + if (value != NULL) { + size_t length = strlen(value); + void* pointer; + if (length < SA_MAX_UNEXTENDED_NAME_LENGTH) { + name->_opaque[0] = length; + pointer = name->_opaque + 1; + } else { + pointer = malloc(length + 1); + set_ptr(pointer, name); + } + memcpy(pointer, value, length + 1); + } else { + osaf_extended_name_clear(name); + } +} + +void osaf_extended_name_free(SaNameT* name) +{ + if (name != NULL) { + if (name->_opaque[0] == kExtendedNameMagic) { + free((SaStringT*) get_ptr(name)); + } + name->_opaque[0] = 0xffff; + memset(name->_opaque + 1, 0, sizeof(SaConstStringT)); + } +} diff --git a/osaf/libs/core/leap/sysf_def.c b/osaf/libs/core/leap/sysf_def.c --- a/osaf/libs/core/leap/sysf_def.c +++ b/osaf/libs/core/leap/sysf_def.c @@ -46,6 +46,7 @@ #include "ncssysfpool.h" #include "sysf_exc_scr.h" #include "usrbuf.h" +#include "osaf_extended_name.h" /** * File descriptor pointing to /proc/sysrq-trigger. If a process wants to be @@ -88,6 +89,8 @@ uint32_t leap_env_init(void) TRACE("INITIALIZING LEAP ENVIRONMENT"); + osaf_extended_name_init(); + ncs_os_atomic_init(); #if (NCSL_ENV_INIT_TMR == 1) ------------------------------------------------------------------------------ "Accelerate Dev Cycles with Automated Cross-Browser Testing - For FREE Instantly run your Selenium tests across 300+ browser/OS combos. Get unparalleled scalability from the best Selenium testing platform available. Simple to use. Nothing to install. Get started now for free." http://p.sf.net/sfu/SauceLabs _______________________________________________ Opensaf-devel mailing list Opensaf-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/opensaf-devel