Simplify logging and remove unwanted functions from abstraction layer
Signed-off-by: Jeroen Koekkoek <jeroen@koekkoek.nl>
This commit is contained in:
parent
ac020f62f7
commit
1cf03332ca
97 changed files with 2819 additions and 5361 deletions
|
@ -11,7 +11,6 @@
|
|||
#
|
||||
string(TOLOWER ${CMAKE_SYSTEM_NAME} platform)
|
||||
|
||||
# For posix platforms include the files in the posix/ directory.
|
||||
set (posix_platforms darwin linux sunos)
|
||||
IF(${platform} IN_LIST posix_platforms)
|
||||
set(platform posix)
|
||||
|
@ -21,7 +20,8 @@ ENDIF()
|
|||
PREPEND(srcs_platform ${platform} os_platform_errno.c os_platform_heap.c os_platform_init.c os_platform_process.c os_platform_ifaddrs.c os_platform_socket.c os_platform_stdlib.c os_platform_sync.c os_platform_thread.c os_platform_time.c)
|
||||
|
||||
include (GenerateExportHeader)
|
||||
PREPEND(srcs_os "${CMAKE_CURRENT_SOURCE_DIR}/src" os_atomics.c os_init.c os_report.c os_ifaddrs.c os_socket.c os_thread.c os_time.c os_errno.c os_iter.c ${srcs_platform})
|
||||
PREPEND(srcs_os "${CMAKE_CURRENT_SOURCE_DIR}/src" os_atomics.c os_init.c os_log.c os_ifaddrs.c os_socket.c os_thread.c os_time.c os_errno.c os_iter.c ${srcs_platform})
|
||||
|
||||
add_library(OSAPI ${srcs_os})
|
||||
|
||||
configure_file(
|
||||
|
|
|
@ -49,12 +49,11 @@
|
|||
#include "os_socket.h"
|
||||
#include "os_heap.h"
|
||||
#include "os_stdlib.h"
|
||||
#include "os_report.h"
|
||||
#include "os_init.h"
|
||||
#include "os_process.h"
|
||||
#include "os_errno.h"
|
||||
#include "os_iter.h"
|
||||
|
||||
#include "os_log.h"
|
||||
|
||||
#define OSPL_VERSION_STR "aap"
|
||||
#define OSPL_HOST_STR "noot"
|
||||
|
|
234
src/os/include/os/os_log.h
Normal file
234
src/os/include/os/os_log.h
Normal file
|
@ -0,0 +1,234 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
|
||||
/** @file
|
||||
*
|
||||
* @brief DDS C Logging API
|
||||
*
|
||||
* This header file defines the public API for logging and controlling logging
|
||||
* in the DDS C language binding.
|
||||
*/
|
||||
#ifndef DDS_LOG_H
|
||||
#define DDS_LOG_H
|
||||
|
||||
#include "os/os_defs.h"
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @defgroup log_categories Convenience log category definitions.
|
||||
*
|
||||
* These defines expand into numeric values that can be ORed together to
|
||||
* specify messages of which categories must be passed to the respective sinks.
|
||||
*
|
||||
* Every category other than DDS_LC_FATAL, DDS_LC_ERROR, DDS_LC_WARNING and
|
||||
* DDS_LC_INFO automatically falls into the trace category.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
/** Fatal error condition. Immediate abort on sink return. */
|
||||
#define DDS_LC_FATAL (1u)
|
||||
/** Error condition. */
|
||||
#define DDS_LC_ERROR (2u)
|
||||
/** Warning condition. */
|
||||
#define DDS_LC_WARNING (4u)
|
||||
/** Informational message. */
|
||||
#define DDS_LC_INFO (8u)
|
||||
/** Debug/trace messages related to configuration settings. */
|
||||
#define DDS_LC_CONFIG (16u)
|
||||
/** Debug/trace messages related to node discovery. */
|
||||
#define DDS_LC_DISCOVERY (32u)
|
||||
/** Currently unused. */
|
||||
#define DDS_LC_DATA (64u)
|
||||
/** Debug/trace messages for which no specialized category exists (yet). */
|
||||
#define DDS_LC_TRACE (128u)
|
||||
/** Debug/trace messages related to receive administration. */
|
||||
#define DDS_LC_RADMIN (256u)
|
||||
/** Debug/trace messages related to timing. */
|
||||
#define DDS_LC_TIMING (512u)
|
||||
/** Debug/trace messages related to send administration. */
|
||||
#define DDS_LC_TRAFFIC (1024u)
|
||||
/** Currently unused. */
|
||||
#define DDS_LC_TOPIC (2048u)
|
||||
/** Debug/trace messages related to TCP communication. */
|
||||
#define DDS_LC_TCP (4096u)
|
||||
/** Debug/trace messages related to parameter list processing. */
|
||||
#define DDS_LC_PLIST (8192u)
|
||||
/** Debug/trace messages related to the writer history cache. */
|
||||
#define DDS_LC_WHC (16384u)
|
||||
/** Debug/trace messages related to throttling. */
|
||||
#define DDS_LC_THROTTLE (32768u)
|
||||
/** All common trace categories. */
|
||||
#define DDS_LC_ALL \
|
||||
(DDS_LC_FATAL | DDS_LC_ERROR | DDS_LC_WARNING | DDS_LC_INFO | \
|
||||
DDS_LC_CONFIG | DDS_LC_DISCOVERY | DDS_LC_DATA | DDS_LC_TRACE | \
|
||||
DDS_LC_TIMING | DDS_LC_TRAFFIC | DDS_LC_TCP | DDS_LC_THROTTLE)
|
||||
/** @}*/
|
||||
|
||||
#define DDS_LOG_MASK \
|
||||
(DDS_LC_FATAL | DDS_LC_ERROR | DDS_LC_WARNING | DDS_LC_INFO)
|
||||
|
||||
#define DDS_TRACE_MASK \
|
||||
(~DDS_LOG_MASK)
|
||||
|
||||
/** Structure with log message and meta data passed to callbacks. */
|
||||
typedef struct {
|
||||
/** Log category the message falls into. */
|
||||
uint32_t priority;
|
||||
/** Filename where message was generated. */
|
||||
const char *file;
|
||||
/** Line number in file where message was generated. */
|
||||
uint32_t line;
|
||||
/** Name of function message where message was generated. */
|
||||
const char *function;
|
||||
/** Log message. */
|
||||
const char *message;
|
||||
/** Size of log message. */
|
||||
size_t size;
|
||||
} dds_log_data_t;
|
||||
|
||||
/** Function signature that log and trace callbacks must adhere too. */
|
||||
typedef void(*dds_log_write_fn_t)(void *, const dds_log_data_t *);
|
||||
|
||||
extern uint32_t *const dds_log_mask;
|
||||
|
||||
/**
|
||||
* @brief Get currently enabled log and trace categories.
|
||||
*
|
||||
* @returns A uint32_t with enabled categories set.
|
||||
*/
|
||||
inline uint32_t
|
||||
dds_get_log_mask(void)
|
||||
{
|
||||
return *dds_log_mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set enabled log and trace categories.
|
||||
*
|
||||
* @param[in] cats Log and trace categories to enable.
|
||||
*/
|
||||
OSAPI_EXPORT void
|
||||
dds_set_log_mask(
|
||||
_In_ uint32_t cats);
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
OSAPI_EXPORT void
|
||||
dds_set_log_file(
|
||||
_In_ FILE *file);
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
OSAPI_EXPORT void
|
||||
dds_set_trace_file(
|
||||
_In_ FILE *file);
|
||||
|
||||
/**
|
||||
* @brief Register callback to receive log messages
|
||||
*
|
||||
* Callbacks registered to handle log messages will receive messages of type
|
||||
* info, warning, error and fatal. Messages that fall into the trace category
|
||||
* will never be delivered to the callback.
|
||||
*
|
||||
* This operation is synchronous and only returns once the operation is
|
||||
* registered with all threads. Meaning that neither callback or userdata will
|
||||
* be referenced by the DDS stack on return.
|
||||
*
|
||||
* @param[in] callback Function pointer matching dds_log_write_fn signature
|
||||
* or a null pointer to restore the default sink.
|
||||
* @param[in] userdata User specified data passed along with each invocation
|
||||
* of callback.
|
||||
*/
|
||||
OSAPI_EXPORT void
|
||||
dds_set_log_sink(
|
||||
_In_opt_ dds_log_write_fn_t callback,
|
||||
_In_opt_ void *userdata);
|
||||
|
||||
/**
|
||||
* @brief Register callback to receive trace messages
|
||||
*
|
||||
* Callbacks registered to handle trace messages will receive messages of type
|
||||
* info, warning, error and fatal as well as all message types that fall into
|
||||
* the trace category depending on the log mask.
|
||||
*
|
||||
* This operation is synchronous and only returns once the operation is
|
||||
* registered with all threads. Meaning that neither callback or
|
||||
* userdata will be referenced by the DDS stack on return.
|
||||
*
|
||||
* @param[in] callback Function pointer matching dds_log_write_fn_t signature
|
||||
* or a null pointer to restore the default sink.
|
||||
* @param[in] userdata User specified data passed along with each invocation
|
||||
* of callback.
|
||||
*/
|
||||
OSAPI_EXPORT void
|
||||
dds_set_trace_sink(
|
||||
_In_opt_ dds_log_write_fn_t callback,
|
||||
_In_opt_ void *userdata);
|
||||
|
||||
/**
|
||||
* @brief Write a log or trace message.
|
||||
*
|
||||
* Write a log or trace message to one (or both) of the currently active sinks.
|
||||
*
|
||||
* Direct use of #dds_log is discouraged. Use #DDS_INFO, #DDS_WARNING,
|
||||
* #DDS_ERROR, #DDS_FATAL or #DDS_LOG instead.
|
||||
*/
|
||||
OSAPI_EXPORT int
|
||||
dds_log(
|
||||
_In_ uint32_t prio,
|
||||
_In_z_ const char *file,
|
||||
_In_ uint32_t line,
|
||||
_In_z_ const char *func,
|
||||
_In_z_ _Printf_format_string_ const char *fmt,
|
||||
...) __attribute_format__((printf,5,6));
|
||||
|
||||
/**
|
||||
* @brief Write a log message.
|
||||
*
|
||||
* Write a log or trace message to the currently active log and/or trace sinks
|
||||
* if the log category is enabled. Whether or not the category is enabled is
|
||||
* checked before any dds_log-related activities to save a couple of % CPU.
|
||||
*
|
||||
* Only messages that fall into one of the log categories are passed onto
|
||||
* dds_log. While messages that fall into a trace category could have been
|
||||
* passed just as easily, they are rejected so that tracing is kept entirely
|
||||
* separate from logging, if only cosmetic.
|
||||
*/
|
||||
#define DDS_LOG(cat, ...) \
|
||||
((dds_get_log_mask() & (cat)) ? \
|
||||
dds_log(cat, __FILE__, __LINE__, OS_FUNCTION, __VA_ARGS__) : 0)
|
||||
|
||||
/** Write a log message of type #DDS_LC_INFO. */
|
||||
#define DDS_INFO(...) \
|
||||
DDS_LOG(DDS_LC_INFO, __VA_ARGS__)
|
||||
/** Write a log message of type #DDS_LC_WARNING. */
|
||||
#define DDS_WARNING(...) \
|
||||
DDS_LOG(DDS_LC_WARNING, __VA_ARGS__)
|
||||
/** Write a log message of type #DDS_LC_ERROR. */
|
||||
#define DDS_ERROR(...) \
|
||||
DDS_LOG(DDS_LC_ERROR, __VA_ARGS__)
|
||||
/** Write a log message of type #DDS_LC_ERROR and abort. */
|
||||
#define DDS_FATAL(...) \
|
||||
dds_log(DDS_LC_FATAL, __FILE__, __LINE__, OS_FUNCTION, __VA_ARGS__)
|
||||
/** Write a #DDS_LC_TRACE message. */
|
||||
#define DDS_TRACE(...) \
|
||||
DDS_LOG(DDS_LC_TRACE, __VA_ARGS__)
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* DDS_LOG_H */
|
|
@ -1,137 +0,0 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#ifndef OS_REPORT_H
|
||||
#define OS_REPORT_H
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* !!!!!!!!NOTE From here no more includes are allowed!!!!!!! */
|
||||
|
||||
/* Subcomponents might need to alter the report before actually handing it over
|
||||
* to os_report. Since os_report truncates messages, those components can get
|
||||
* away with fixed size buffers as well, but the maximum size must known at
|
||||
* that point.
|
||||
*/
|
||||
#define OS_REPORT_BUFLEN 1024
|
||||
|
||||
/*
|
||||
Note - in the below the check of reportType against os_reportVerbosity is also present
|
||||
in os_report. By duplicating it we avoid putting the call onto the stack and evaluating
|
||||
args if not necessary.
|
||||
*/
|
||||
|
||||
#define OS_REPORT(type,context,code,message,...) \
|
||||
(((type) >= os_reportVerbosity) ? os_report((type),(context),__FILE__,__LINE__,(code),(message),##__VA_ARGS__) : (void)0)
|
||||
|
||||
|
||||
#define OS_DEBUG(context,code,message,...) OS_REPORT(OS_REPORT_DEBUG,(context),(code),(message),##__VA_ARGS__)
|
||||
#define OS_INFO(context,code,message,...) OS_REPORT(OS_REPORT_INFO,(context),(code),(message),##__VA_ARGS__)
|
||||
#define OS_WARNING(context,code,message,...) OS_REPORT(OS_REPORT_WARNING,(context),(code),(message),##__VA_ARGS__)
|
||||
#define OS_ERROR(context,code,message,...) OS_REPORT(OS_REPORT_ERROR,(context),(code),(message),##__VA_ARGS__)
|
||||
#define OS_CRITICAL(context,code,message,...) OS_REPORT(OS_REPORT_CRITICAL,(context),(code),(message),##__VA_ARGS__)
|
||||
#define OS_FATAL(context,code,message,...) OS_REPORT(OS_REPORT_FATAL,(context),(code),(message),##__VA_ARGS__)
|
||||
|
||||
#define OS_REPORT_STACK() \
|
||||
os_report_stack()
|
||||
|
||||
#define OS_REPORT_FLUSH(condition) \
|
||||
os_report_flush((condition), OS_FUNCTION, __FILE__, __LINE__)
|
||||
|
||||
/**
|
||||
* These types are an ordered series of incremental 'importance' (to the user)
|
||||
* levels.
|
||||
* @see os_reportVerbosity
|
||||
*/
|
||||
typedef enum os_reportType {
|
||||
OS_REPORT_DEBUG,
|
||||
OS_REPORT_INFO,
|
||||
OS_REPORT_WARNING,
|
||||
OS_REPORT_ERROR,
|
||||
OS_REPORT_FATAL,
|
||||
OS_REPORT_CRITICAL,
|
||||
OS_REPORT_NONE
|
||||
} os_reportType;
|
||||
|
||||
OSAPI_EXPORT extern os_reportType os_reportVerbosity;
|
||||
|
||||
OSAPI_EXPORT void
|
||||
os_reportInit(_In_ bool forceReInit);
|
||||
|
||||
OSAPI_EXPORT void
|
||||
os_reportExit(void);
|
||||
|
||||
/** \brief Report message
|
||||
*
|
||||
* Consider this function private. It should be invoked by reporting functions
|
||||
* specified in the language bindings only.
|
||||
*
|
||||
* @param type type of report
|
||||
* @param context context in which report was generated, often function name
|
||||
* from which function was invoked
|
||||
* @param path path of file from which function was invoked
|
||||
* @param line line of file from which function was invoked
|
||||
* @param code error code associated with the report
|
||||
* @param format message to log
|
||||
* @param ... Parameter to log
|
||||
*/
|
||||
|
||||
OSAPI_EXPORT void
|
||||
os_report(
|
||||
_In_ os_reportType type,
|
||||
_In_z_ const char *context,
|
||||
_In_z_ const char *path,
|
||||
_In_ int32_t line,
|
||||
_In_ int32_t code,
|
||||
_In_z_ _Printf_format_string_ const char *format,
|
||||
...) __attribute_format__((printf,6,7));
|
||||
|
||||
/*****************************************
|
||||
* Report stack related functions
|
||||
*****************************************/
|
||||
|
||||
/**
|
||||
* The os_report_stack operation enables a report stack for the current thread.
|
||||
* The stack will be disabled again by the os_report_flush operation.
|
||||
*/
|
||||
OSAPI_EXPORT void
|
||||
os_report_stack(
|
||||
void);
|
||||
|
||||
/**
|
||||
* The os_report_stack_free operation frees all memory allocated by the current
|
||||
* thread for the report stack.
|
||||
*/
|
||||
OSAPI_EXPORT void
|
||||
os_report_stack_free(
|
||||
void);
|
||||
|
||||
/**
|
||||
* The os_report_flush operation removes the report message from the stack,
|
||||
* and if valid is TRUE also writes them into the report device.
|
||||
* This operation additionally disables the stack.
|
||||
*/
|
||||
OSAPI_EXPORT void
|
||||
os_report_flush(
|
||||
_In_ bool valid,
|
||||
_In_z_ const char *context,
|
||||
_In_z_ const char *file,
|
||||
_In_ int line);
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* OS_REPORT_H */
|
|
@ -82,127 +82,6 @@ extern "C" {
|
|||
os_putenv(
|
||||
char *variable_definition);
|
||||
|
||||
/** \brief Get file seperator
|
||||
*
|
||||
* Possible Results:
|
||||
* - "<file-seperator-character>"
|
||||
*/
|
||||
OSAPI_EXPORT const char *
|
||||
os_fileSep(void);
|
||||
|
||||
/** \brief Get path seperator
|
||||
*
|
||||
* Possible Results:
|
||||
* - "<file-seperator-character>"
|
||||
*/
|
||||
OSAPI_EXPORT const char *
|
||||
os_pathSep(void);
|
||||
|
||||
#define OS_PATHSEPCHAR OS_OS_PATHSEPCHAR
|
||||
#define OS_EXESUFFIX OS_OS_EXESUFFIX
|
||||
#define OS_BATSUFFIX OS_OS_BATSUFFIX
|
||||
#define OS_LIB_LOAD_PATH_VAR OS_OS_LIB_LOAD_PATH_VAR
|
||||
|
||||
/** \brief Check user's permissions for a file
|
||||
*
|
||||
* Precondition:
|
||||
* - permission is a mask of:
|
||||
* OS_ROK check for read access
|
||||
* OS_WOK check for write access
|
||||
* OS_XOK check for execution access
|
||||
* OS_FOK check for existence of the file
|
||||
*
|
||||
* Possible results:
|
||||
* - return os_resultSuccess if
|
||||
* requested file access is granted
|
||||
* - return os_resultFail if
|
||||
* requested file access is not granted
|
||||
*/
|
||||
OSAPI_EXPORT os_result
|
||||
os_access(
|
||||
const char *file_path,
|
||||
int32_t permission);
|
||||
|
||||
/** \brief Locate an executable file in the path
|
||||
*
|
||||
* Precondition:
|
||||
* - permission is a mask of:
|
||||
* OS_ROK check for read access
|
||||
* OS_WOK check for write access
|
||||
* OS_XOK check for execution access
|
||||
* OS_FOK check for existence of the file
|
||||
*
|
||||
* Possible results:
|
||||
* - return an os_malloc-ed string if a file with
|
||||
* the given permission mask was found in
|
||||
* PATH. The return value contains the full
|
||||
* path name of the file found.
|
||||
* If the name of the file contains an
|
||||
* absolute or relative path, then no
|
||||
* search is done in the PATH.
|
||||
* - return NULL if no file was found in PATH
|
||||
*/
|
||||
OSAPI_EXPORT char *
|
||||
os_locate(
|
||||
const char *name,
|
||||
int32_t permission);
|
||||
|
||||
/** \brief mkdir wrapper
|
||||
*
|
||||
* because operating systems has different
|
||||
* interfaces to mkdir a wrapper is made
|
||||
*
|
||||
* Precondition:
|
||||
* None
|
||||
*
|
||||
* Possible results:
|
||||
* - return 0 if
|
||||
* requested dir is created
|
||||
* - return -1 if
|
||||
* requested dir could not be created
|
||||
*/
|
||||
OSAPI_EXPORT int32_t
|
||||
os_mkdir(
|
||||
const char *path,
|
||||
os_mode_t mode);
|
||||
|
||||
/** \brief Create a path including parent dirs
|
||||
*
|
||||
* Alternative to os_mkdir that creates all path elements instead
|
||||
* of only the top-level directory
|
||||
*
|
||||
* Preconditions:
|
||||
* None
|
||||
*
|
||||
* Possible results:
|
||||
* - return os_resultSuccess if
|
||||
* requested path is created
|
||||
* - return os_resultFail if
|
||||
* requested path could not be created
|
||||
*
|
||||
* When path creation fails an appropriate error message is reported
|
||||
*/
|
||||
OSAPI_EXPORT os_result
|
||||
os_mkpath(
|
||||
const char *path,
|
||||
os_mode_t mode);
|
||||
|
||||
/** \brief dirname wrapper
|
||||
*
|
||||
* because not all operating systems have
|
||||
* interfaces to dirname a wrapper is made
|
||||
*
|
||||
* Precondition:
|
||||
* None
|
||||
*
|
||||
* Possible results:
|
||||
* - return '.' if
|
||||
* path is a null pointer
|
||||
* - return char *
|
||||
* to a string that is the parent directory of path
|
||||
*/
|
||||
OSAPI_EXPORT char * os_dirname_r(char *path);
|
||||
|
||||
/** \brief rindex wrapper
|
||||
*
|
||||
* because not all operating systems have
|
||||
|
@ -576,91 +455,6 @@ extern "C" {
|
|||
OSAPI_EXPORT char *
|
||||
os_strtok_r(char *str, const char *delim, char **saveptr);
|
||||
|
||||
struct os_stat {
|
||||
/* The mode_t macro's (like OS_ISDIR) are defined in the platform specific header files! */
|
||||
/* NEVER name these fields identical to the POSIX standard! Since e.g. the Linux implementation
|
||||
has defined it as follows:
|
||||
struct stat {
|
||||
...
|
||||
struct timespec st_mtim;
|
||||
#define st_mtime st_mtim.tvsec
|
||||
...
|
||||
};
|
||||
This results in the fact that our definition is also changed, causing compilation errors!
|
||||
*/
|
||||
os_mode_t stat_mode;
|
||||
size_t stat_size;
|
||||
os_time stat_mtime;
|
||||
};
|
||||
|
||||
OSAPI_EXPORT os_result
|
||||
os_stat(
|
||||
const char *path,
|
||||
struct os_stat *buf);
|
||||
|
||||
/** \brief Removes the file or directory given by name.
|
||||
*
|
||||
* This function is equivalent to POSIX remove(3)
|
||||
*
|
||||
*/
|
||||
|
||||
OSAPI_EXPORT os_result os_remove (const char *name);
|
||||
|
||||
/** \brief Renames a file or directory
|
||||
*
|
||||
* This function is equivalent to POSIX rename(3)
|
||||
*
|
||||
*/
|
||||
|
||||
OSAPI_EXPORT os_result os_rename (const char *oldpath, const char *newpath);
|
||||
|
||||
/** \brief Transforms the given filepath into a platform specific filepath.
|
||||
*
|
||||
* This translation function will replace any platform file seperator into
|
||||
* the fileseperator of the current platform.
|
||||
*
|
||||
* Precondition:
|
||||
* none
|
||||
*
|
||||
* Possible results:
|
||||
* - returns normalized filepath conform current platform
|
||||
* - return NULL if out of memory.
|
||||
*/
|
||||
_Ret_z_
|
||||
_Must_inspect_result_
|
||||
OSAPI_EXPORT char *
|
||||
os_fileNormalize(
|
||||
_In_z_ const char *filepath);
|
||||
|
||||
/**
|
||||
* \brief Flushes the internal buffers associated with the file handle to disk
|
||||
*
|
||||
* Precondition:
|
||||
* The file should be open.
|
||||
*
|
||||
* Possible results:
|
||||
* - os_resultSuccess if function succeeded
|
||||
* - os_resultFail if function failed
|
||||
*/
|
||||
OSAPI_EXPORT os_result
|
||||
os_fsync(
|
||||
FILE *fHandle);
|
||||
|
||||
/**
|
||||
* \brief returns the location of the temporary files used by OpenSplice.
|
||||
* This may be the key file describing the shared memory or the shared
|
||||
* file itself depending on the operating system
|
||||
*
|
||||
* Precondition:
|
||||
* none
|
||||
*
|
||||
* Possible results:
|
||||
* - char * of the absolute path of the temporary location. This will return
|
||||
* always return a valid value, using a default if necessary
|
||||
*/
|
||||
OSAPI_EXPORT _Ret_opt_z_ const char *
|
||||
os_getTempDir(void);
|
||||
|
||||
/**
|
||||
* \brief writes up to count bytes from the buffer pointed buf to the file referred to by the file descriptor fd.
|
||||
*
|
||||
|
@ -678,42 +472,6 @@ extern "C" {
|
|||
_In_reads_bytes_(count) void const* buf,
|
||||
_In_ size_t count);
|
||||
|
||||
/**
|
||||
* \brief the os_flockfile() function waits for *filehandle to be
|
||||
* no longer locked by a different thread, then makes the current
|
||||
* thread owner of *filehandle, and increments the lockcount.
|
||||
* (not effective on VxWorks DKM platform)
|
||||
*
|
||||
* Precondition:
|
||||
* none
|
||||
*
|
||||
* Possible results:
|
||||
* - No error information is returned.
|
||||
* The thread will block until the lock is acquired.
|
||||
* An explicit call to os_funlockfile has to be used to release the lock.
|
||||
*
|
||||
*/
|
||||
OSAPI_EXPORT void os_flockfile(
|
||||
FILE *file);
|
||||
|
||||
/**
|
||||
* \brief the os_funlockfile function decrements the lock count and releases
|
||||
* the internal locking object of the *filehandle. The *filehandle must
|
||||
* have been locked before by a call to os_flockfile.
|
||||
* (not effective on VxWorks DKM platform)
|
||||
*
|
||||
* Precondition:
|
||||
* none
|
||||
*
|
||||
* Possible results:
|
||||
* - No error information is returned.
|
||||
* The behaviour is undefined if a thread other than the current owner calls
|
||||
* the os_funlockfile() function.
|
||||
*
|
||||
*/
|
||||
OSAPI_EXPORT void os_funlockfile(
|
||||
FILE *file);
|
||||
|
||||
/**
|
||||
* \brief binary search algorithm on an already sorted list.
|
||||
*
|
||||
|
|
|
@ -37,7 +37,6 @@ extern "C" {
|
|||
OS_THREAD_WARNING,
|
||||
OS_THREAD_ALLOCATOR_STATE,
|
||||
OS_THREAD_NAME,
|
||||
OS_THREAD_REPORT_STACK,
|
||||
OS_THREAD_PROCESS_INFO,
|
||||
OS_THREAD_STATE, /* Used for monitoring thread progress */
|
||||
OS_THREAD_STR_ERROR,
|
||||
|
|
298
src/os/src/os_log.c
Normal file
298
src/os/src/os_log.c
Normal file
|
@ -0,0 +1,298 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "os/os.h"
|
||||
|
||||
#define MAX_TIMESTAMP_LEN (10 + 1 + 6)
|
||||
#define MAX_TID_LEN (10)
|
||||
#define HDR_LEN (MAX_TIMESTAMP_LEN + 1 + MAX_TID_LEN + 2)
|
||||
|
||||
#define BUF_OFFSET HDR_LEN
|
||||
|
||||
typedef struct {
|
||||
char buf[2048];
|
||||
size_t bufsz;
|
||||
size_t pos;
|
||||
} log_buffer_t;
|
||||
|
||||
typedef struct {
|
||||
dds_log_write_fn_t funcs[2];
|
||||
void *ptr;
|
||||
FILE *out;
|
||||
} log_sink_t;
|
||||
|
||||
static os_threadLocal log_buffer_t log_buffer;
|
||||
|
||||
static os_once_t lock_inited = OS_ONCE_T_STATIC_INIT;
|
||||
static os_rwlock lock;
|
||||
|
||||
static uint32_t log_mask = DDS_LC_ERROR | DDS_LC_WARNING;
|
||||
|
||||
static void default_sink(void *ptr, const dds_log_data_t *data)
|
||||
{
|
||||
fwrite(data->message - HDR_LEN, 1, HDR_LEN + data->size + 1, (FILE *)ptr);
|
||||
fflush((FILE *)ptr);
|
||||
}
|
||||
|
||||
static void nop_sink(void *ptr, const dds_log_data_t *data)
|
||||
{
|
||||
(void)ptr;
|
||||
(void)data;
|
||||
return;
|
||||
}
|
||||
|
||||
#define LOG (0)
|
||||
#define TRACE (1)
|
||||
#define USE (0)
|
||||
#define SET (1)
|
||||
|
||||
static log_sink_t sinks[] = {
|
||||
/* Log */
|
||||
{ .funcs = { default_sink, default_sink }, .ptr = NULL, .out = NULL },
|
||||
/* Trace */
|
||||
{ .funcs = { nop_sink, default_sink }, .ptr = NULL, .out = NULL }
|
||||
};
|
||||
|
||||
uint32_t *const dds_log_mask = &log_mask;
|
||||
|
||||
#define RDLOCK (1)
|
||||
#define WRLOCK (2)
|
||||
|
||||
static void init_lock(void)
|
||||
{
|
||||
os_rwlockInit(&lock);
|
||||
sinks[LOG].ptr = sinks[TRACE].ptr = stderr;
|
||||
sinks[LOG].out = sinks[TRACE].out = stderr;
|
||||
}
|
||||
|
||||
static void lock_sink(int type)
|
||||
{
|
||||
assert(type == RDLOCK || type == WRLOCK);
|
||||
os_once(&lock_inited, &init_lock);
|
||||
|
||||
if (type == RDLOCK) {
|
||||
os_rwlockRead(&lock);
|
||||
} else {
|
||||
os_rwlockWrite(&lock);
|
||||
}
|
||||
}
|
||||
|
||||
static void unlock_sink(void)
|
||||
{
|
||||
os_rwlockUnlock(&lock);
|
||||
}
|
||||
|
||||
static void set_active_log_sinks(void)
|
||||
{
|
||||
if (dds_get_log_mask() & DDS_LOG_MASK) {
|
||||
sinks[LOG].funcs[USE] = sinks[LOG].funcs[SET];
|
||||
} else {
|
||||
sinks[LOG].funcs[USE] = nop_sink;
|
||||
}
|
||||
if (dds_get_log_mask() & DDS_TRACE_MASK) {
|
||||
sinks[TRACE].funcs[USE] = sinks[TRACE].funcs[SET];
|
||||
} else {
|
||||
sinks[TRACE].funcs[USE] = nop_sink;
|
||||
}
|
||||
if (sinks[LOG].funcs[USE] == sinks[TRACE].funcs[USE] &&
|
||||
sinks[LOG].ptr == sinks[TRACE].ptr)
|
||||
{
|
||||
sinks[LOG].funcs[USE] = nop_sink;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
set_log_sink(
|
||||
_In_ log_sink_t *sink,
|
||||
_In_opt_ dds_log_write_fn_t func,
|
||||
_In_opt_ void *ptr)
|
||||
{
|
||||
assert(sink != NULL);
|
||||
|
||||
/* No life cycle management is done for log sinks, the caller is
|
||||
responsible for that. Ensure this operation is deterministic and that on
|
||||
return, no thread in the DDS stack still uses the deprecated sink. */
|
||||
lock_sink(WRLOCK);
|
||||
|
||||
if (func == 0) {
|
||||
sink->funcs[SET] = default_sink;
|
||||
sink->ptr = sink->out;
|
||||
} else {
|
||||
sink->funcs[SET] = func;
|
||||
sink->ptr = ptr;
|
||||
}
|
||||
|
||||
set_active_log_sinks();
|
||||
unlock_sink();
|
||||
}
|
||||
|
||||
/* dds_set_log_file must be considered private. */
|
||||
void dds_set_log_file(_In_ FILE *file)
|
||||
{
|
||||
lock_sink(WRLOCK);
|
||||
sinks[LOG].out = file;
|
||||
if (sinks[LOG].funcs[SET] == default_sink) {
|
||||
sinks[LOG].ptr = sinks[LOG].out;
|
||||
}
|
||||
unlock_sink();
|
||||
}
|
||||
|
||||
void dds_set_trace_file(_In_ FILE *file)
|
||||
{
|
||||
lock_sink(WRLOCK);
|
||||
sinks[TRACE].out = file;
|
||||
if (sinks[TRACE].funcs[SET] == default_sink) {
|
||||
sinks[TRACE].ptr = sinks[TRACE].out;
|
||||
}
|
||||
unlock_sink();
|
||||
}
|
||||
|
||||
void dds_set_log_sink(
|
||||
_In_opt_ dds_log_write_fn_t callback,
|
||||
_In_opt_ void *userdata)
|
||||
{
|
||||
set_log_sink(&sinks[LOG], callback, userdata);
|
||||
}
|
||||
|
||||
void dds_set_trace_sink(
|
||||
_In_opt_ dds_log_write_fn_t callback,
|
||||
_In_opt_ void *userdata)
|
||||
{
|
||||
set_log_sink(&sinks[TRACE], callback, userdata);
|
||||
}
|
||||
|
||||
extern inline uint32_t
|
||||
dds_get_log_mask(void);
|
||||
|
||||
void
|
||||
dds_set_log_mask(_In_ uint32_t cats)
|
||||
{
|
||||
lock_sink(WRLOCK);
|
||||
*dds_log_mask = (cats & (DDS_LOG_MASK | DDS_TRACE_MASK));
|
||||
set_active_log_sinks();
|
||||
unlock_sink();
|
||||
}
|
||||
|
||||
static void print_header(char *str)
|
||||
{
|
||||
int cnt;
|
||||
char *tid, buf[MAX_TID_LEN] = { 0 };
|
||||
static const char fmt[] = "%10u.%06d/%*.*s:";
|
||||
os_time tv;
|
||||
unsigned sec;
|
||||
int usec;
|
||||
|
||||
(void)os_threadGetThreadName(buf, sizeof(buf));
|
||||
tid = (buf[0] == '\0' ? "(anon)" : buf);
|
||||
tv = os_timeGet();
|
||||
sec = (unsigned)tv.tv_sec;
|
||||
usec = (int)(tv.tv_nsec / 1000);
|
||||
|
||||
cnt = snprintf(
|
||||
str, HDR_LEN, fmt, sec, usec, MAX_TID_LEN, MAX_TID_LEN, tid);
|
||||
assert(cnt == (HDR_LEN - 1));
|
||||
str[cnt] = ' '; /* Replace snprintf null byte by space. */
|
||||
}
|
||||
|
||||
static void vlog(
|
||||
_In_ uint32_t cat,
|
||||
_In_z_ const char *file,
|
||||
_In_ uint32_t line,
|
||||
_In_z_ const char *func,
|
||||
_In_z_ const char *fmt,
|
||||
va_list ap)
|
||||
{
|
||||
int n, trunc = 0;
|
||||
size_t nrem;
|
||||
log_buffer_t *lb;
|
||||
dds_log_data_t data;
|
||||
|
||||
if (*fmt == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
lock_sink(RDLOCK);
|
||||
lb = &log_buffer;
|
||||
|
||||
/* Thread-local buffer is always initialized with all zeroes. The pos
|
||||
member must always be greater or equal to BUF_OFFSET. */
|
||||
if (lb->pos < BUF_OFFSET) {
|
||||
lb->pos = BUF_OFFSET;
|
||||
lb->buf[lb->pos] = 0;
|
||||
}
|
||||
nrem = lb->bufsz - lb->pos;
|
||||
if (nrem > 0) {
|
||||
n = os_vsnprintf(lb->buf + lb->pos, nrem, fmt, ap);
|
||||
if (n >= 0 && (size_t) n < nrem) {
|
||||
lb->pos += (size_t) n;
|
||||
} else {
|
||||
lb->pos += nrem;
|
||||
trunc = 1;
|
||||
}
|
||||
if (trunc) {
|
||||
static const char msg[] = "(trunc)\n";
|
||||
const size_t msglen = sizeof (msg) - 1;
|
||||
assert(lb->pos <= lb->bufsz);
|
||||
assert(lb->pos >= msglen);
|
||||
memcpy(lb->buf + lb->pos - msglen, msg, msglen);
|
||||
}
|
||||
}
|
||||
|
||||
if (fmt[strlen (fmt) - 1] == '\n') {
|
||||
print_header(lb->buf);
|
||||
|
||||
data.priority = cat;
|
||||
data.file = file;
|
||||
data.function = func;
|
||||
data.line = line;
|
||||
data.message = lb->buf + BUF_OFFSET;
|
||||
data.size = strlen(data.message) - 1;
|
||||
|
||||
for (size_t i = (cat & DDS_LOG_MASK) ? LOG : TRACE;
|
||||
i < sizeof(sinks) / sizeof(sinks[0]);
|
||||
i++)
|
||||
{
|
||||
sinks[i].funcs[USE](sinks[i].ptr, &data);
|
||||
}
|
||||
|
||||
lb->pos = BUF_OFFSET;
|
||||
lb->buf[lb->pos] = 0;
|
||||
}
|
||||
|
||||
unlock_sink();
|
||||
}
|
||||
|
||||
int
|
||||
dds_log(
|
||||
_In_ uint32_t cat,
|
||||
_In_z_ const char *file,
|
||||
_In_ uint32_t line,
|
||||
_In_z_ const char *func,
|
||||
_In_z_ _Printf_format_string_ const char *fmt,
|
||||
...)
|
||||
{
|
||||
if ((dds_get_log_mask() & cat) || (cat & DDS_LC_FATAL)) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vlog(cat, file, line, func, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
if (cat & DDS_LC_FATAL) {
|
||||
abort();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,909 +0,0 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#ifdef PIKEOS_POSIX
|
||||
#include <lwip_config.h>
|
||||
#endif
|
||||
|
||||
#include "os/os.h"
|
||||
#include "os/os_project.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define OS_REPORT_TYPE_DEBUG (1u)
|
||||
#define OS_REPORT_TYPE_WARNING (1u<<OS_REPORT_WARNING)
|
||||
#define OS_REPORT_TYPE_ERROR (1u<<OS_REPORT_ERROR)
|
||||
#define OS_REPORT_TYPE_CRITICAL (1u<<OS_REPORT_CRITICAL)
|
||||
#define OS_REPORT_TYPE_FATAL (1u<<OS_REPORT_FATAL)
|
||||
#define OS_REPORT_TYPE_INFO (1u<<OS_REPORT_INFO)
|
||||
|
||||
#define OS_REPORT_TYPE_FLAG(x) (1u<<(x))
|
||||
#define OS_REPORT_IS_ALWAYS(x) ((x) & (OS_REPORT_TYPE_CRITICAL | OS_REPORT_TYPE_FATAL))
|
||||
#define OS_REPORT_IS_WARNING(x) ((x) & OS_REPORT_TYPE_WARNING)
|
||||
#define OS_REPORT_IS_ERROR(x) ((x) & (OS_REPORT_TYPE_ERROR | OS_REPORT_TYPE_CRITICAL | OS_REPORT_TYPE_FATAL))
|
||||
|
||||
#define OS_REPORT_FLAG_TYPE(x) (((x) & OS_REPORT_TYPE_FATAL) ? OS_REPORT_FATAL : \
|
||||
((x) & OS_REPORT_TYPE_CRITICAL) ? OS_REPORT_CRITICAL : \
|
||||
((x) & OS_REPORT_TYPE_ERROR) ? OS_REPORT_ERROR : \
|
||||
((x) & OS_REPORT_TYPE_WARNING) ? OS_REPORT_WARNING : \
|
||||
((x) & OS_REPORT_TYPE_INFO) ? OS_REPORT_INFO : \
|
||||
((x) & OS_REPORT_TYPE_DEBUG) ? OS_REPORT_DEBUG : \
|
||||
OS_REPORT_NONE)
|
||||
|
||||
#define MAX_FILE_PATH 2048
|
||||
|
||||
typedef struct os_reportStack_s {
|
||||
int count;
|
||||
unsigned typeset;
|
||||
const char *file;
|
||||
int lineno;
|
||||
const char *signature;
|
||||
os_iter *reports; /* os_reportEventV1 */
|
||||
} *os_reportStack;
|
||||
|
||||
|
||||
/**
|
||||
* The information that is made available to a plugged in logger
|
||||
* via its TypedReport symbol.
|
||||
*/
|
||||
struct os_reportEventV1_s
|
||||
{
|
||||
/** The version of this struct i.e. 1. */
|
||||
uint32_t version;
|
||||
/** The type / level of this report.
|
||||
* @see os_reportType */
|
||||
os_reportType reportType;
|
||||
/** Context information relating to where the even was generated.
|
||||
* May contain a function or compnent name or a stacktrace */
|
||||
char* reportContext;
|
||||
/** The source file name where the report even was generated */
|
||||
char* fileName;
|
||||
/** The source file line number where the report was generated */
|
||||
int32_t lineNo;
|
||||
/** An integer code associated with the event. */
|
||||
int32_t code;
|
||||
/** A description of the reported event */
|
||||
char *description;
|
||||
/** A string identifying the thread the event occurred in */
|
||||
char* threadDesc;
|
||||
/** A string identifying the process the event occurred in */
|
||||
char* processDesc;
|
||||
};
|
||||
|
||||
#define OS_REPORT_EVENT_V1 1
|
||||
|
||||
|
||||
typedef struct os_reportEventV1_s* os_reportEventV1;
|
||||
|
||||
static void os__report_append(_Inout_ os_reportStack _this, _In_ const os_reportEventV1 report);
|
||||
|
||||
static void os__report_fprintf(_Inout_ FILE *file, _In_z_ _Printf_format_string_ const char *format, ...);
|
||||
|
||||
static void os__report_free(_In_ _Post_invalid_ os_reportEventV1 report);
|
||||
|
||||
static void os__report_dumpStack(_In_z_ const char *context, _In_z_ const char *path, _In_ int line);
|
||||
|
||||
static FILE* error_log = NULL;
|
||||
static FILE* info_log = NULL;
|
||||
|
||||
static os_mutex reportMutex;
|
||||
static os_mutex infologcreateMutex;
|
||||
static os_mutex errorlogcreateMutex;
|
||||
static bool inited = false;
|
||||
static bool StaleLogsRemoved = false;
|
||||
|
||||
/**
|
||||
* Process global verbosity level for OS_REPORT output. os_reportType
|
||||
* values >= this value will be written.
|
||||
* This value defaults to OS_REPORT_INFO, meaning that all types 'above' (i.e.
|
||||
* other than) OS_REPORT_DEBUG will be written and OS_REPORT_DEBUG will not be.
|
||||
*/
|
||||
os_reportType os_reportVerbosity = OS_REPORT_INFO;
|
||||
|
||||
/**
|
||||
* Labels corresponding to os_reportType values.
|
||||
* @see os_reportType
|
||||
*/
|
||||
const char *os_reportTypeText [] = {
|
||||
"DEBUG",
|
||||
"INFO",
|
||||
"WARNING",
|
||||
"ERROR",
|
||||
"CRITICAL",
|
||||
"FATAL",
|
||||
"NONE"
|
||||
};
|
||||
|
||||
enum os_report_logType {
|
||||
OS_REPORT_INFO_LOG,
|
||||
OS_REPORT_ERROR_LOG
|
||||
};
|
||||
|
||||
static char * os_report_defaultInfoFileName = OS_PROJECT_NAME_NOSPACE_SMALL"-info.log";
|
||||
static char * os_report_defaultErrorFileName = OS_PROJECT_NAME_NOSPACE_SMALL"-error.log";
|
||||
static const char os_env_logdir[] = OS_PROJECT_NAME_NOSPACE_CAPS"_LOGPATH";
|
||||
static const char os_env_infofile[] = OS_PROJECT_NAME_NOSPACE_CAPS"_INFOFILE";
|
||||
static const char os_env_errorfile[] = OS_PROJECT_NAME_NOSPACE_CAPS"_ERRORFILE";
|
||||
static const char os_env_verbosity[] = OS_PROJECT_NAME_NOSPACE_CAPS"_VERBOSITY";
|
||||
static const char os_env_append[] = OS_PROJECT_NAME_NOSPACE_CAPS"_LOGAPPEND";
|
||||
#if defined _WRS_KERNEL
|
||||
static const char os_default_logdir[] = "/tgtsvr";
|
||||
#else
|
||||
static const char os_default_logdir[] = ".";
|
||||
#endif
|
||||
|
||||
static _Ret_maybenull_ FILE *
|
||||
os__open_file (
|
||||
_In_z_ const char * file_name)
|
||||
{
|
||||
FILE *logfile=NULL;
|
||||
const char *dir = os_getenv (os_env_logdir);
|
||||
char * nomalized_dir;
|
||||
char *str;
|
||||
size_t len;
|
||||
os_result res = os_resultSuccess;
|
||||
|
||||
if (dir == NULL) {
|
||||
dir = os_default_logdir;
|
||||
}
|
||||
|
||||
len = strlen (dir) + 2; /* '/' + '\0' */
|
||||
str = os_malloc (len);
|
||||
if (str != NULL) {
|
||||
(void)snprintf (str, len, "%s/", dir);
|
||||
nomalized_dir = os_fileNormalize (str);
|
||||
os_free (str);
|
||||
if (nomalized_dir == NULL) {
|
||||
res = os_resultFail;
|
||||
}
|
||||
os_free(nomalized_dir);
|
||||
} else {
|
||||
res = os_resultFail;
|
||||
}
|
||||
|
||||
if (res == os_resultSuccess) {
|
||||
logfile = fopen (file_name, "a");
|
||||
}
|
||||
|
||||
return logfile;
|
||||
}
|
||||
|
||||
static void
|
||||
os__close_file (
|
||||
_In_z_ const char * file_name,
|
||||
_In_ _Post_invalid_ FILE *file)
|
||||
{
|
||||
if (strcmp(file_name, "<stderr>") != 0 && strcmp(file_name, "<stdout>") != 0)
|
||||
{
|
||||
fclose(file);
|
||||
}
|
||||
}
|
||||
|
||||
_Check_return_ _Ret_z_
|
||||
static char *os__report_createFileNormalize(
|
||||
_In_z_ const char *file_dir,
|
||||
_In_z_ const char *file_name)
|
||||
{
|
||||
char file_path[MAX_FILE_PATH];
|
||||
int len;
|
||||
|
||||
len = snprintf(file_path, MAX_FILE_PATH, "%s/%s", file_dir, file_name);
|
||||
/* Note bug in glibc < 2.0.6 returns -1 for output truncated */
|
||||
if ( len < MAX_FILE_PATH && len > -1 ) {
|
||||
return (os_fileNormalize(file_path));
|
||||
} else {
|
||||
return os_strdup(file_name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return either a log file path string or a pseudo file name/path value
|
||||
* like <stdout> or <stderr>.
|
||||
* The result of os_report_file_path must be freed with os_free
|
||||
* @param override_variable An environment variable name that may hold a filename
|
||||
* or pseudo filename. If this var is set, and is not a pseudo filename,
|
||||
* the value of this var will be added to the value of env variable
|
||||
* {OS_PROJECT_NAME_NOSPACE_CAPS}_LOGPATH (if set or './' if not) to create the
|
||||
* log file path.
|
||||
* @param default_file If override_variable is not defined in the environment
|
||||
* this is the filename used.
|
||||
*/
|
||||
_Ret_z_
|
||||
_Check_return_
|
||||
static char *
|
||||
os__report_file_path(
|
||||
_In_z_ const char * default_file,
|
||||
_In_opt_z_ const char * override_variable,
|
||||
_In_ enum os_report_logType type)
|
||||
{
|
||||
const char *file_dir;
|
||||
const char *file_name = NULL;
|
||||
|
||||
if (override_variable != NULL)
|
||||
{
|
||||
file_name = os_getenv(override_variable);
|
||||
}
|
||||
if (!file_name)
|
||||
{
|
||||
file_name = default_file;
|
||||
}
|
||||
|
||||
file_dir = os_getenv(os_env_logdir);
|
||||
if (!file_dir)
|
||||
{
|
||||
file_dir = os_default_logdir;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We just need to check if a file can be written to the directory, we just use the
|
||||
* default info file as there will always be one created, if we used the variables
|
||||
* passed in we would create an empty error log (which is bad for testing) and we
|
||||
* cannot delete it as we open the file with append
|
||||
*/
|
||||
if (type == OS_REPORT_INFO_LOG)
|
||||
{
|
||||
FILE *logfile;
|
||||
char *full_file_path;
|
||||
|
||||
full_file_path = os_malloc(strlen(file_dir) + 1 + strlen(file_name) + 1);
|
||||
strcpy(full_file_path, file_dir);
|
||||
strcat(full_file_path, "/");
|
||||
strcat(full_file_path, file_name);
|
||||
logfile = fopen (full_file_path, "a");
|
||||
if (logfile)
|
||||
{
|
||||
fclose(logfile);
|
||||
}
|
||||
os_free (full_file_path);
|
||||
}
|
||||
}
|
||||
if (strcmp(file_name, "<stderr>") != 0 && strcmp(file_name, "<stdout>") != 0)
|
||||
{
|
||||
return (os__report_createFileNormalize(file_dir, file_name));
|
||||
}
|
||||
return os_strdup (file_name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides the current minimum output level to be reported from
|
||||
* this process.
|
||||
* @param newVerbosity String holding either an integer value corresponding
|
||||
* to an acceptable (in range) log verbosity or a string verbosity 'name'
|
||||
* like 'ERROR' or 'warning' or 'DEBUG' or somesuch.
|
||||
* @return os_resultFail if the string contains neither of the above;
|
||||
* os_resultSuccess otherwise.
|
||||
*/
|
||||
static os_result
|
||||
os__determine_verbosity(
|
||||
_In_z_ const char* newVerbosity)
|
||||
{
|
||||
long verbosityInt;
|
||||
os_result result = os_resultFail;
|
||||
verbosityInt = strtol(newVerbosity, NULL, 0);
|
||||
|
||||
if (verbosityInt == 0 && strcmp("0", newVerbosity)) {
|
||||
/* Conversion from int failed. See if it's one of the string forms. */
|
||||
while (verbosityInt < (long) (sizeof(os_reportTypeText) / sizeof(os_reportTypeText[0]))) {
|
||||
if (os_strcasecmp(newVerbosity, os_reportTypeText[verbosityInt]) == 0) {
|
||||
break;
|
||||
}
|
||||
++verbosityInt;
|
||||
}
|
||||
}
|
||||
if (verbosityInt >= 0 && verbosityInt < (long) (sizeof(os_reportTypeText) / sizeof(os_reportTypeText[0]))) {
|
||||
/* OS_API_INFO label is kept for backwards compatibility. */
|
||||
os_reportVerbosity = (os_reportType)verbosityInt;
|
||||
result = os_resultSuccess;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void os__set_verbosity(void)
|
||||
{
|
||||
const char * envValue = os_getenv(os_env_verbosity);
|
||||
if (envValue != NULL)
|
||||
{
|
||||
if (os__determine_verbosity(envValue) == os_resultFail)
|
||||
{
|
||||
OS_WARNING("os_reportInit", 0,
|
||||
"Cannot parse report verbosity %s value \"%s\","
|
||||
" reporting verbosity remains %s", os_env_verbosity, envValue, os_reportTypeText[os_reportVerbosity]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the destination for logging error reports. Env property {OS_PROJECT_NAME_NOSPACE_CAPS}_INFOFILE and
|
||||
* {OS_PROJECT_NAME_NOSPACE_CAPS}_LOGPATH controls this value.
|
||||
* If {OS_PROJECT_NAME_NOSPACE_CAPS}_INFOFILE is not set & this process is a service, default
|
||||
* to logging to a file named {OS_PROJECT_NAME_NOSPACE_SMALL}-info.log, otherwise
|
||||
* use standard out.
|
||||
* @see os_report_file_path
|
||||
*/
|
||||
_Ret_z_
|
||||
_Check_return_
|
||||
static char *
|
||||
os__get_info_file_name(void)
|
||||
{
|
||||
char * file_name;
|
||||
os_mutexLock(&infologcreateMutex);
|
||||
file_name = os__report_file_path (os_report_defaultInfoFileName, os_env_infofile, OS_REPORT_INFO_LOG);
|
||||
os_mutexUnlock(&infologcreateMutex);
|
||||
return file_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the destination for logging error reports. Env property {OS_PROJECT_NAME_NOSPACE_CAPS}_ERRORFILE and
|
||||
* {OS_PROJECT_NAME_NOSPACE_CAPS}_LOGPATH controls this value.
|
||||
* If {OS_PROJECT_NAME_NOSPACE_CAPS}_ERRORFILE is not set & this process is a service, default
|
||||
* to logging to a file named {OS_PROJECT_NAME_NOSPACE_SMALL}-error.log, otherwise
|
||||
* use standard error.
|
||||
* @see os_report_file_path
|
||||
*/
|
||||
_Ret_z_
|
||||
_Check_return_
|
||||
static char *
|
||||
os__get_error_file_name(void)
|
||||
{
|
||||
char * file_name;
|
||||
os_mutexLock(&errorlogcreateMutex);
|
||||
file_name = os__report_file_path (os_report_defaultErrorFileName, os_env_errorfile, OS_REPORT_ERROR_LOG);
|
||||
os_mutexUnlock(&errorlogcreateMutex);
|
||||
return file_name;
|
||||
}
|
||||
|
||||
static void os__remove_stale_logs(void)
|
||||
{
|
||||
if (!StaleLogsRemoved) {
|
||||
/* TODO: Only a single process or spliced (as 1st process) is allowed to
|
||||
* delete the log files. */
|
||||
/* Remove ospl-info.log and ospl-error.log.
|
||||
* Ignore the result because it is possible that they don't exist yet. */
|
||||
char * log_file_name;
|
||||
|
||||
log_file_name = os__get_error_file_name();
|
||||
(void)os_remove(log_file_name);
|
||||
os_free(log_file_name);
|
||||
|
||||
log_file_name = os__get_info_file_name();
|
||||
(void)os_remove(log_file_name);
|
||||
os_free(log_file_name);
|
||||
|
||||
StaleLogsRemoved = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void os__check_removal_stale_logs(void)
|
||||
{
|
||||
const char * envValue = os_getenv(os_env_append);
|
||||
if (envValue != NULL)
|
||||
{
|
||||
if (os_strcasecmp(envValue, "FALSE") == 0 ||
|
||||
os_strcasecmp(envValue, "0") == 0 ||
|
||||
- os_strcasecmp(envValue, "NO") == 0) {
|
||||
os__remove_stale_logs();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read environment properties. In particular ones that can't be left until
|
||||
* there is a requirement to log.
|
||||
*/
|
||||
void os_reportInit(
|
||||
_In_ bool forceReInit)
|
||||
{
|
||||
if (forceReInit) {
|
||||
inited = false;
|
||||
}
|
||||
|
||||
if (!inited)
|
||||
{
|
||||
os_mutexInit(&reportMutex);
|
||||
os_mutexInit(&errorlogcreateMutex);
|
||||
os_mutexInit(&infologcreateMutex);
|
||||
|
||||
os__check_removal_stale_logs();
|
||||
os__set_verbosity();
|
||||
}
|
||||
inited = true;
|
||||
}
|
||||
|
||||
void os_reportExit(void)
|
||||
{
|
||||
char *name;
|
||||
os_reportStack reports;
|
||||
if (!inited) {
|
||||
return;
|
||||
}
|
||||
|
||||
reports = os_threadMemGet(OS_THREAD_REPORT_STACK);
|
||||
if (reports) {
|
||||
os__report_dumpStack(OS_FUNCTION, __FILE__, __LINE__);
|
||||
os_iterFree(reports->reports, NULL);
|
||||
os_threadMemFree(OS_THREAD_REPORT_STACK);
|
||||
}
|
||||
inited = false;
|
||||
os_mutexDestroy(&reportMutex);
|
||||
|
||||
if (error_log)
|
||||
{
|
||||
name = os__get_error_file_name();
|
||||
os__close_file(name, error_log);
|
||||
os_free (name);
|
||||
error_log = NULL;
|
||||
}
|
||||
|
||||
if (info_log)
|
||||
{
|
||||
name = os__get_info_file_name();
|
||||
os__close_file(name, info_log);
|
||||
os_free (name);
|
||||
info_log = NULL;
|
||||
}
|
||||
os_mutexDestroy(&errorlogcreateMutex);
|
||||
os_mutexDestroy(&infologcreateMutex);
|
||||
}
|
||||
|
||||
static void os__report_fprintf(
|
||||
_Inout_ FILE *file,
|
||||
_In_z_ _Printf_format_string_ const char *format, ...)
|
||||
{
|
||||
int BytesWritten = 0;
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
BytesWritten = os_vfprintfnosigpipe(file, format, args);
|
||||
va_end(args);
|
||||
if (BytesWritten == -1) {
|
||||
/* error occurred ?, try to write to stdout. (also with no sigpipe,
|
||||
* stdout can also give broken pipe)
|
||||
*/
|
||||
va_start(args, format);
|
||||
(void) os_vfprintfnosigpipe(stdout, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
}
|
||||
|
||||
static _Ret_notnull_ FILE* os__get_info_file (void)
|
||||
{
|
||||
if (info_log == NULL) {
|
||||
char * name = os__get_info_file_name();
|
||||
info_log = os__open_file(name);
|
||||
if (!info_log)
|
||||
{
|
||||
info_log = stdout;
|
||||
}
|
||||
os_free (name);
|
||||
}
|
||||
return info_log;
|
||||
}
|
||||
|
||||
static _Ret_notnull_ FILE* os__get_error_file (void)
|
||||
{
|
||||
if (error_log == NULL) {
|
||||
char * name = os__get_error_file_name();
|
||||
error_log = os__open_file(name);
|
||||
if (!error_log)
|
||||
{
|
||||
error_log = stderr;
|
||||
}
|
||||
os_free (name);
|
||||
}
|
||||
return error_log;
|
||||
}
|
||||
|
||||
static void os__sectionReport(
|
||||
_Pre_notnull_ _Post_notnull_ os_reportEventV1 event,
|
||||
_In_ bool useErrorLog)
|
||||
{
|
||||
os_time ostime;
|
||||
FILE *log = useErrorLog ? os__get_error_file() : os__get_info_file();
|
||||
|
||||
ostime = os_timeGet();
|
||||
os_mutexLock(&reportMutex);
|
||||
os__report_fprintf(log,
|
||||
"----------------------------------------------------------------------------------------\n"
|
||||
"Report : %s\n"
|
||||
"Internals : %s/%s/%d/%d/%d.%09d\n",
|
||||
event->description,
|
||||
event->reportContext,
|
||||
event->fileName,
|
||||
event->lineNo,
|
||||
event->code,
|
||||
ostime.tv_sec,
|
||||
ostime.tv_nsec);
|
||||
fflush (log);
|
||||
os_mutexUnlock(&reportMutex);
|
||||
}
|
||||
|
||||
static void os__headerReport(
|
||||
_Pre_notnull_ _Post_notnull_ os_reportEventV1 event,
|
||||
_In_ bool useErrorLog)
|
||||
{
|
||||
os_time ostime;
|
||||
char node[64];
|
||||
char date_time[128];
|
||||
FILE *log = NULL;
|
||||
if (useErrorLog)
|
||||
log = os__get_error_file();
|
||||
else log = os__get_info_file();
|
||||
|
||||
ostime = os_timeGet();
|
||||
os_ctime_r(&ostime, date_time, sizeof(date_time));
|
||||
|
||||
if (os_gethostname(node, sizeof(node)-1) == os_resultSuccess)
|
||||
{
|
||||
node[sizeof(node)-1] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(node, "UnkownNode");
|
||||
}
|
||||
|
||||
os_mutexLock(&reportMutex);
|
||||
|
||||
os__report_fprintf(log,
|
||||
"========================================================================================\n"
|
||||
"ReportType : %s\n"
|
||||
"Context : %s\n"
|
||||
"Date : %s\n"
|
||||
"Node : %s\n"
|
||||
"Process : %s\n"
|
||||
"Thread : %s\n"
|
||||
"Internals : %s/%d/%s/%s/%s\n",
|
||||
os_reportTypeText[event->reportType],
|
||||
event->description,
|
||||
date_time,
|
||||
node,
|
||||
event->processDesc,
|
||||
event->threadDesc,
|
||||
event->fileName,
|
||||
event->lineNo,
|
||||
OSPL_VERSION_STR,
|
||||
OSPL_INNER_REV_STR,
|
||||
OSPL_OUTER_REV_STR);
|
||||
|
||||
fflush (log);
|
||||
|
||||
os_mutexUnlock(&reportMutex);
|
||||
}
|
||||
|
||||
static void os__defaultReport(
|
||||
_Pre_notnull_ _Post_notnull_ os_reportEventV1 event)
|
||||
{
|
||||
os_time ostime;
|
||||
char node[64];
|
||||
char date_time[128];
|
||||
FILE *log;
|
||||
|
||||
switch (event->reportType) {
|
||||
case OS_REPORT_DEBUG:
|
||||
case OS_REPORT_INFO:
|
||||
case OS_REPORT_WARNING:
|
||||
log = os__get_info_file();
|
||||
break;
|
||||
case OS_REPORT_ERROR:
|
||||
case OS_REPORT_CRITICAL:
|
||||
case OS_REPORT_FATAL:
|
||||
default:
|
||||
log = os__get_error_file();
|
||||
break;
|
||||
}
|
||||
|
||||
ostime = os_timeGet();
|
||||
os_ctime_r(&ostime, date_time, sizeof(date_time));
|
||||
|
||||
if (os_gethostname(node, sizeof(node)-1) == os_resultSuccess)
|
||||
{
|
||||
node[sizeof(node)-1] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(node, "UnkownNode");
|
||||
}
|
||||
|
||||
os_mutexLock(&reportMutex);
|
||||
os__report_fprintf (log,
|
||||
"========================================================================================\n"
|
||||
"Report : %s\n"
|
||||
"Date : %s\n"
|
||||
"Description : %s\n"
|
||||
"Node : %s\n"
|
||||
"Process : %s\n"
|
||||
"Thread : %s\n"
|
||||
"Internals : %s/%s/%s/%s/%s/%d/%d/%d.%09d\n",
|
||||
os_reportTypeText[event->reportType],
|
||||
date_time,
|
||||
event->description,
|
||||
node,
|
||||
event->processDesc,
|
||||
event->threadDesc,
|
||||
OSPL_VERSION_STR,
|
||||
OSPL_INNER_REV_STR,
|
||||
OSPL_OUTER_REV_STR,
|
||||
event->reportContext,
|
||||
event->fileName,
|
||||
event->lineNo,
|
||||
event->code,
|
||||
ostime.tv_sec,
|
||||
ostime.tv_nsec);
|
||||
fflush (log);
|
||||
os_mutexUnlock(&reportMutex);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void os_report_message(
|
||||
_In_ os_reportType type,
|
||||
_In_z_ const char *context,
|
||||
_In_z_ const char *path,
|
||||
_In_ int32_t line,
|
||||
_In_ int32_t code,
|
||||
_In_z_ const char *message)
|
||||
{
|
||||
char *file;
|
||||
char procid[256], thrid[64];
|
||||
os_reportStack stack;
|
||||
|
||||
struct os_reportEventV1_s report = { OS_REPORT_EVENT_V1, /* version */
|
||||
OS_REPORT_NONE, /* reportType */
|
||||
NULL, /* reportContext */
|
||||
NULL, /* fileName */
|
||||
0, /* lineNo */
|
||||
0, /* code */
|
||||
NULL, /* description */
|
||||
NULL, /* threadDesc */
|
||||
NULL /* processDesc */
|
||||
};
|
||||
|
||||
file = (char *)path;
|
||||
|
||||
/* Only figure out process and thread identities if the user requested an
|
||||
entry in the default log file or registered a typed report plugin. */
|
||||
os_procNamePid (procid, sizeof (procid));
|
||||
os_threadFigureIdentity (thrid, sizeof (thrid));
|
||||
|
||||
report.reportType = type;
|
||||
report.reportContext = (char *)context;
|
||||
report.fileName = (char *)file;
|
||||
report.lineNo = line;
|
||||
report.code = code;
|
||||
report.description = (char *)message;
|
||||
report.threadDesc = thrid;
|
||||
report.processDesc = procid;
|
||||
|
||||
stack = (os_reportStack)os_threadMemGet(OS_THREAD_REPORT_STACK);
|
||||
if (stack && stack->count) {
|
||||
if (report.reportType != OS_REPORT_NONE) {
|
||||
os__report_append (stack, &report);
|
||||
}
|
||||
} else {
|
||||
os__defaultReport (&report);
|
||||
}
|
||||
}
|
||||
|
||||
void os_report(
|
||||
_In_ os_reportType type,
|
||||
_In_z_ const char *context,
|
||||
_In_z_ const char *path,
|
||||
_In_ int32_t line,
|
||||
_In_ int32_t code,
|
||||
_In_z_ _Printf_format_string_ const char *format,
|
||||
...)
|
||||
{
|
||||
char buf[OS_REPORT_BUFLEN];
|
||||
va_list args;
|
||||
|
||||
if (!inited) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (type < os_reportVerbosity) {
|
||||
return;
|
||||
}
|
||||
|
||||
va_start (args, format);
|
||||
(void)os_vsnprintf (buf, sizeof(buf), format, args);
|
||||
va_end (args);
|
||||
|
||||
os_report_message(type, context, path, line, code, buf);
|
||||
}
|
||||
|
||||
/*****************************************
|
||||
* Report-stack related functions
|
||||
*****************************************/
|
||||
void os_report_stack(void)
|
||||
{
|
||||
os_reportStack _this;
|
||||
|
||||
if (inited == false) {
|
||||
return;
|
||||
}
|
||||
_this = (os_reportStack)os_threadMemGet(OS_THREAD_REPORT_STACK);
|
||||
if (!_this) {
|
||||
/* Report stack does not exist yet, so create it */
|
||||
_this = os_threadMemMalloc(OS_THREAD_REPORT_STACK, sizeof(struct os_reportStack_s));
|
||||
if (_this) {
|
||||
_this->count = 1;
|
||||
_this->typeset = 0;
|
||||
_this->file = NULL;
|
||||
_this->lineno = 0;
|
||||
_this->signature = NULL;
|
||||
_this->reports = os_iterNew();
|
||||
} else {
|
||||
OS_ERROR("os_report_stack", 0,
|
||||
"Failed to initialize report stack (could not allocate thread-specific memory)");
|
||||
}
|
||||
} else {
|
||||
/* Use previously created report stack */
|
||||
if (_this->count == 0) {
|
||||
_this->file = NULL;
|
||||
_this->lineno = 0;
|
||||
_this->signature = NULL;
|
||||
}
|
||||
_this->count++;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void os_report_stack_free(void)
|
||||
{
|
||||
os_reportStack _this;
|
||||
os_reportEventV1 report;
|
||||
|
||||
_this = (os_reportStack)os_threadMemGet(OS_THREAD_REPORT_STACK);
|
||||
if (_this) {
|
||||
while((report = os_iterTake(_this->reports, -1))) {
|
||||
os__report_free(report);
|
||||
}
|
||||
os_iterFree(_this->reports, NULL);
|
||||
os_threadMemFree(OS_THREAD_REPORT_STACK);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
os__report_stack_unwind(
|
||||
_Inout_ os_reportStack _this,
|
||||
_In_ bool valid,
|
||||
_In_z_ const char *context,
|
||||
_In_z_ const char *path,
|
||||
_In_ int line)
|
||||
{
|
||||
struct os_reportEventV1_s header;
|
||||
os_reportEventV1 report;
|
||||
char *file;
|
||||
bool useErrorLog;
|
||||
os_reportType reportType = OS_REPORT_ERROR;
|
||||
|
||||
if (!valid) {
|
||||
if (OS_REPORT_IS_ALWAYS(_this->typeset)) {
|
||||
valid = true;
|
||||
}
|
||||
} else {
|
||||
reportType = OS_REPORT_FLAG_TYPE(_this->typeset);
|
||||
}
|
||||
|
||||
useErrorLog = OS_REPORT_IS_ERROR(_this->typeset);
|
||||
|
||||
/* Typeset will be set when a report was appended. */
|
||||
if (valid && (_this->typeset != 0)) {
|
||||
char proc[256], procid[256];
|
||||
char thr[64], thrid[64];
|
||||
|
||||
assert (context != NULL);
|
||||
assert (path != NULL);
|
||||
|
||||
file = (char *)path;
|
||||
|
||||
os_procNamePid (procid, sizeof (procid));
|
||||
os_procName (proc, sizeof (proc));
|
||||
os_threadFigureIdentity (thrid, sizeof (thrid));
|
||||
os_threadGetThreadName (thr, sizeof (thr));
|
||||
|
||||
header.reportType = reportType;
|
||||
header.description = (char *)context;
|
||||
header.processDesc = procid;
|
||||
header.threadDesc = thrid;
|
||||
header.fileName = file;
|
||||
header.lineNo = line;
|
||||
|
||||
os__headerReport (&header, useErrorLog);
|
||||
}
|
||||
|
||||
while ((report = os_iterTake(_this->reports, -1))) {
|
||||
if (valid) {
|
||||
os__sectionReport (report, useErrorLog);
|
||||
}
|
||||
os__report_free(report);
|
||||
}
|
||||
|
||||
_this->typeset = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
os__report_dumpStack(
|
||||
_In_z_ const char *context,
|
||||
_In_z_ const char *path,
|
||||
_In_ int line)
|
||||
{
|
||||
os_reportStack _this;
|
||||
|
||||
if (inited == false) {
|
||||
return;
|
||||
}
|
||||
_this = os_threadMemGet(OS_THREAD_REPORT_STACK);
|
||||
if ((_this) && (_this->count > 0)) {
|
||||
os__report_stack_unwind(_this, true, context, path, line);
|
||||
}
|
||||
}
|
||||
|
||||
void os_report_flush(
|
||||
_In_ bool valid,
|
||||
_In_z_ const char *context,
|
||||
_In_z_ const char *path,
|
||||
_In_ int line)
|
||||
{
|
||||
os_reportStack _this;
|
||||
|
||||
if (inited == false) {
|
||||
return;
|
||||
}
|
||||
_this = os_threadMemGet(OS_THREAD_REPORT_STACK);
|
||||
if ((_this) && (_this->count)) {
|
||||
if (_this->count == 1) {
|
||||
os__report_stack_unwind(_this, valid, context, path, line);
|
||||
_this->file = NULL;
|
||||
_this->signature = NULL;
|
||||
_this->lineno = 0;
|
||||
}
|
||||
_this->count--;
|
||||
}
|
||||
}
|
||||
|
||||
#define OS__STRDUP(str) (str != NULL ? os_strdup(str) : os_strdup("NULL"))
|
||||
|
||||
static void
|
||||
os__report_append(
|
||||
_Inout_ os_reportStack _this,
|
||||
_In_ const os_reportEventV1 report)
|
||||
{
|
||||
os_reportEventV1 copy;
|
||||
|
||||
copy = os_malloc(sizeof(*copy));
|
||||
copy->code = report->code;
|
||||
copy->description = OS__STRDUP(report->description);
|
||||
copy->fileName = OS__STRDUP(report->fileName);
|
||||
copy->lineNo = report->lineNo;
|
||||
copy->processDesc = OS__STRDUP(report->processDesc);
|
||||
copy->reportContext = OS__STRDUP(report->reportContext);
|
||||
copy->reportType = report->reportType;
|
||||
copy->threadDesc = OS__STRDUP(report->threadDesc);
|
||||
copy->version = report->version;
|
||||
_this->typeset |= OS_REPORT_TYPE_FLAG(report->reportType);
|
||||
os_iterAppend(_this->reports, copy);
|
||||
}
|
||||
|
||||
static void
|
||||
os__report_free(
|
||||
_In_ _Post_invalid_ os_reportEventV1 report)
|
||||
{
|
||||
os_free(report->description);
|
||||
os_free(report->fileName);
|
||||
os_free(report->processDesc);
|
||||
os_free(report->reportContext);
|
||||
os_free(report->threadDesc);
|
||||
os_free(report);
|
||||
}
|
|
@ -256,13 +256,13 @@ os_sockaddrStringToAddress(
|
|||
ret = getaddrinfo(addressString, NULL, &hints, &res);
|
||||
if (ret != 0) {
|
||||
fmt = "getaddrinfo(\"%s\") failed: %s";
|
||||
OS_DEBUG(OS_FUNCTION, 0, fmt, addressString, os_gai_strerror(ret));
|
||||
DDS_TRACE(fmt, addressString, os_gai_strerror(ret));
|
||||
} else if (res != NULL) {
|
||||
memcpy(addressOut, res->ai_addr, res->ai_addrlen);
|
||||
freeaddrinfo(res);
|
||||
} else {
|
||||
fmt = "getaddrinfo(\"%s\") did not return any results";
|
||||
OS_DEBUG(OS_FUNCTION, 0, fmt, addressString);
|
||||
DDS_TRACE(fmt, addressString);
|
||||
}
|
||||
|
||||
return (ret == 0 && res != NULL);
|
||||
|
|
|
@ -37,3 +37,32 @@ os_threadAttrInit (
|
|||
threadAttr->schedPriority = 0;
|
||||
threadAttr->stackSize = 0;
|
||||
}
|
||||
|
||||
int32_t
|
||||
os_threadFigureIdentity(char *str, uint32_t size)
|
||||
{
|
||||
int32_t cnt;
|
||||
uintmax_t id;
|
||||
char *fmt, *ptr, buf[1] = { '\0' };
|
||||
uint32_t sz;
|
||||
|
||||
assert(str != NULL);
|
||||
assert(size >= 1);
|
||||
|
||||
id = os_threadIdToInteger(os_threadIdSelf());
|
||||
cnt = os_threadGetThreadName(str, size);
|
||||
if (cnt >= 0) {
|
||||
fmt = (cnt > 0 ? " 0x%"PRIxMAX : "0x%"PRIxMAX);
|
||||
if ((uint32_t)cnt < size) {
|
||||
ptr = str + (uint32_t)cnt;
|
||||
sz = size - (uint32_t)cnt;
|
||||
} else {
|
||||
ptr = buf;
|
||||
sz = sizeof(buf);
|
||||
}
|
||||
|
||||
cnt += snprintf(ptr, sz, fmt, id);
|
||||
}
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
|
|
@ -32,14 +32,12 @@ void os_osPlatformInit (void)
|
|||
os_syncModuleInit();
|
||||
os_threadModuleInit();
|
||||
os_processModuleInit();
|
||||
os_reportInit(false);
|
||||
}
|
||||
|
||||
/** \brief OS layer deinitialization
|
||||
*/
|
||||
void os_osPlatformExit (void)
|
||||
{
|
||||
os_reportExit();
|
||||
os_processModuleExit();
|
||||
os_threadModuleExit();
|
||||
os_syncModuleExit();
|
||||
|
|
|
@ -309,6 +309,7 @@ void os_rwlockRead(os_rwlock *rwlock)
|
|||
|
||||
err = pthread_rwlock_rdlock(&rwlock->rwlock);
|
||||
assert(err == 0);
|
||||
(void)err;
|
||||
}
|
||||
|
||||
void os_rwlockWrite(os_rwlock *rwlock)
|
||||
|
@ -319,6 +320,7 @@ void os_rwlockWrite(os_rwlock *rwlock)
|
|||
|
||||
err = pthread_rwlock_wrlock(&rwlock->rwlock);
|
||||
assert(err == 0);
|
||||
(void)err;
|
||||
}
|
||||
|
||||
os_result os_rwlockTryRead(os_rwlock *rwlock)
|
||||
|
@ -353,6 +355,7 @@ void os_rwlockUnlock(os_rwlock *rwlock)
|
|||
|
||||
err = pthread_rwlock_unlock(&rwlock->rwlock);
|
||||
assert(err == 0);
|
||||
(void)err;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -65,13 +65,12 @@ os_threadMemInit (
|
|||
if (pthreadMemArray != NULL) {
|
||||
memset (pthreadMemArray, 0, sizeof(void *) * OS_THREAD_MEM_ARRAY_SIZE);
|
||||
if (pthread_setspecific (os_threadMemKey, pthreadMemArray) == EINVAL) {
|
||||
OS_ERROR("os_threadMemInit", 4,
|
||||
"pthread_setspecific failed with error EINVAL (%d), "
|
||||
"invalid threadMemKey value", EINVAL);
|
||||
DDS_ERROR("pthread_setspecific failed with error EINVAL (%d), "
|
||||
"invalid threadMemKey value\n", EINVAL);
|
||||
os_free(pthreadMemArray);
|
||||
}
|
||||
} else {
|
||||
OS_ERROR("os_threadMemInit", 3, "Out of heap memory");
|
||||
DDS_ERROR("Out of heap memory\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -106,7 +105,7 @@ os_threadMemExit(
|
|||
os_free (pthreadMemArray);
|
||||
pthreadMemArray = NULL;
|
||||
if (pthread_setspecific (os_threadMemKey, pthreadMemArray) == EINVAL) {
|
||||
OS_ERROR("os_threadMemExit", 4, "pthread_setspecific failed with error %d", EINVAL);
|
||||
DDS_ERROR("pthread_setspecific failed with error %d\n", EINVAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -164,9 +163,8 @@ os_startRoutineWrapper (
|
|||
|
||||
/* store the thread name with the thread via thread specific data; failure isn't */
|
||||
if (pthread_setspecific (os_threadNameKey, context->threadName) == EINVAL) {
|
||||
OS_WARNING("os_startRoutineWrapper", 0,
|
||||
"pthread_setspecific failed with error EINVAL (%d), "
|
||||
"invalid os_threadNameKey value", EINVAL);
|
||||
DDS_WARNING("pthread_setspecific failed with error EINVAL (%d), "
|
||||
"invalid os_threadNameKey value\n", EINVAL);
|
||||
}
|
||||
|
||||
/* allocate an array to store thread private memory references */
|
||||
|
@ -175,12 +173,10 @@ os_startRoutineWrapper (
|
|||
/* Call the user routine */
|
||||
resultValue = context->startRoutine (context->arguments);
|
||||
|
||||
os_report_stack_free();
|
||||
|
||||
/* Free the thread context resources, arguments is responsibility */
|
||||
/* for the caller of os_procCreate */
|
||||
os_free (context->threadName);
|
||||
os_free (context);
|
||||
os_free(context->threadName);
|
||||
os_free(context);
|
||||
|
||||
/* deallocate the array to store thread private memory references */
|
||||
os_threadMemExit ();
|
||||
|
@ -276,32 +272,28 @@ os_threadCreate (
|
|||
if (result != 0) {
|
||||
char errmsg[64];
|
||||
(void)os_strerror_r(result, errmsg, sizeof(errmsg));
|
||||
OS_WARNING("os_threadCreate", 2,
|
||||
"pthread_attr_setschedpolicy failed for SCHED_FIFO with "\
|
||||
"error %d (%s) for thread '%s', reverting to SCHED_OTHER.",
|
||||
result, errmsg, name);
|
||||
DDS_WARNING("pthread_attr_setschedpolicy failed for SCHED_FIFO with "
|
||||
"error %d (%s) for thread '%s', reverting to SCHED_OTHER\n",
|
||||
result, errmsg, name);
|
||||
|
||||
result = pthread_attr_setschedpolicy (&attr, SCHED_OTHER);
|
||||
if (result != 0) {
|
||||
OS_WARNING("os_threadCreate", 2, "pthread_attr_setschedpolicy failed with error %d (%s)", result, name);
|
||||
DDS_WARNING("pthread_attr_setschedpolicy failed with error %d (%s)\n", result, name);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
result = pthread_attr_setschedpolicy (&attr, SCHED_OTHER);
|
||||
|
||||
if (result != 0) {
|
||||
OS_WARNING("os_threadCreate", 2,
|
||||
"pthread_attr_setschedpolicy failed with error %d (%s)",
|
||||
result, name);
|
||||
DDS_WARNING("pthread_attr_setschedpolicy failed with error %d (%s)\n", result, name);
|
||||
}
|
||||
}
|
||||
pthread_attr_getschedpolicy(&attr, &policy);
|
||||
|
||||
if ((tattr.schedPriority < sched_get_priority_min(policy)) ||
|
||||
(tattr.schedPriority > sched_get_priority_max(policy))) {
|
||||
OS_WARNING("os_threadCreate", 2,
|
||||
"scheduling priority outside valid range for the policy "\
|
||||
"reverted to valid value (%s)", name);
|
||||
DDS_WARNING("scheduling priority outside valid range for the policy "
|
||||
"reverted to valid value (%s)\n", name);
|
||||
sched_param.sched_priority = (sched_get_priority_min(policy) +
|
||||
sched_get_priority_max(policy)) / 2;
|
||||
} else {
|
||||
|
@ -317,9 +309,8 @@ os_threadCreate (
|
|||
/* start the thread */
|
||||
result = pthread_attr_setschedparam (&attr, &sched_param);
|
||||
if (result != 0) {
|
||||
OS_WARNING("os_threadCreate", 2,
|
||||
"pthread_attr_setschedparam failed with error %d (%s)",
|
||||
result, name);
|
||||
DDS_WARNING("pthread_attr_setschedparam failed with error %d (%s)\n",
|
||||
result, name);
|
||||
}
|
||||
|
||||
create_ret = pthread_create(&threadId->v, &attr, os_startRoutineWrapper,
|
||||
|
@ -330,19 +321,17 @@ os_threadCreate (
|
|||
*/
|
||||
if((create_ret == EPERM) && (tattr.schedClass == OS_SCHED_REALTIME))
|
||||
{
|
||||
OS_WARNING("os_threadCreate", 2,
|
||||
"pthread_create failed with SCHED_FIFO " \
|
||||
"for thread '%s', reverting to SCHED_OTHER.",
|
||||
name);
|
||||
DDS_WARNING("pthread_create failed with SCHED_FIFO "
|
||||
"for thread '%s', reverting to SCHED_OTHER\n",
|
||||
name);
|
||||
(void) pthread_attr_setschedpolicy (&attr, SCHED_OTHER); /* SCHED_OTHER is always supported */
|
||||
pthread_attr_getschedpolicy(&attr, &policy);
|
||||
|
||||
if ((tattr.schedPriority < sched_get_priority_min(policy)) ||
|
||||
(tattr.schedPriority > sched_get_priority_max(policy)))
|
||||
{
|
||||
OS_WARNING("os_threadCreate", 2,
|
||||
"scheduling priority outside valid range for the " \
|
||||
"policy reverted to valid value (%s)", name);
|
||||
DDS_WARNING("scheduling priority outside valid range for the "
|
||||
"policy reverted to valid value (%s)\n", name);
|
||||
sched_param.sched_priority =
|
||||
(sched_get_priority_min(policy) +
|
||||
sched_get_priority_max(policy)) / 2;
|
||||
|
@ -352,9 +341,8 @@ os_threadCreate (
|
|||
|
||||
result = pthread_attr_setschedparam (&attr, &sched_param);
|
||||
if (result != 0) {
|
||||
OS_WARNING("os_threadCreate", 2,
|
||||
"pthread_attr_setschedparam failed " \
|
||||
"with error %d (%s)", result, name);
|
||||
DDS_WARNING("pthread_attr_setschedparam failed "
|
||||
"with error %d (%s)", result, name);
|
||||
} else {
|
||||
create_ret = pthread_create(&threadId->v, &attr,
|
||||
os_startRoutineWrapper, threadContext);
|
||||
|
@ -366,7 +354,7 @@ os_threadCreate (
|
|||
if(create_ret != 0){
|
||||
os_free (threadContext->threadName);
|
||||
os_free (threadContext);
|
||||
OS_WARNING("os_threadCreate", 2, "pthread_create failed with error %d (%s)", create_ret, name);
|
||||
DDS_WARNING("pthread_create failed with error %d (%s)\n", create_ret, name);
|
||||
rv = os_resultFail;
|
||||
}
|
||||
}
|
||||
|
@ -398,29 +386,6 @@ os_threadIdSelf (void)
|
|||
return id;
|
||||
}
|
||||
|
||||
/** \brief Figure out the identity of the current thread
|
||||
*
|
||||
* \b os_threadFigureIdentity determines the numeric identity
|
||||
* of a thread. POSIX does not identify threads by name,
|
||||
* therefore only the numeric identification is returned,
|
||||
*/
|
||||
int32_t
|
||||
os_threadFigureIdentity (
|
||||
char *threadIdentity,
|
||||
uint32_t threadIdentitySize)
|
||||
{
|
||||
int size;
|
||||
char *threadName;
|
||||
|
||||
threadName = pthread_getspecific (os_threadNameKey);
|
||||
if (threadName != NULL) {
|
||||
size = snprintf (threadIdentity, threadIdentitySize, "%s 0x%"PRIxMAX, threadName, (uintmax_t)pthread_self ());
|
||||
} else {
|
||||
size = snprintf (threadIdentity, threadIdentitySize, "0x%"PRIxMAX, (uintmax_t)pthread_self ());
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
int32_t
|
||||
os_threadGetThreadName (
|
||||
char *buffer,
|
||||
|
@ -486,7 +451,7 @@ os_threadWaitExit (
|
|||
if (result != 0) {
|
||||
/* NOTE: The below report actually is a debug output; makes no sense from
|
||||
* a customer perspective. Made OS_INFO for now. */
|
||||
OS_INFO("os_threadWaitExit", 2, "pthread_join(0x%"PRIxMAX") failed with error %d", os_threadIdToInteger(threadId), result);
|
||||
DDS_INFO("pthread_join(0x%"PRIxMAX") failed with error %d\n", os_threadIdToInteger(threadId), result);
|
||||
rv = os_resultFail;
|
||||
} else {
|
||||
rv = os_resultSuccess;
|
||||
|
@ -652,7 +617,7 @@ os_threadCleanupPush(
|
|||
itr = os_iterNew();
|
||||
assert(itr != NULL);
|
||||
if (pthread_setspecific(cleanup_key, itr) == EINVAL) {
|
||||
OS_WARNING(OS_FUNCTION, 0, "pthread_setspecific failed with error EINVAL (%d)", EINVAL);
|
||||
DDS_WARNING("pthread_setspecific failed with error EINVAL (%d)\n", EINVAL);
|
||||
os_iterFree(itr, NULL);
|
||||
itr = NULL;
|
||||
}
|
||||
|
|
|
@ -62,28 +62,6 @@ os_pathSep(void)
|
|||
return ":";
|
||||
}
|
||||
|
||||
os_result
|
||||
os_access(
|
||||
const char *file_path,
|
||||
int32_t permission)
|
||||
{
|
||||
os_result result;
|
||||
#ifdef VXWORKS_RTP
|
||||
/* The access function is broken for vxworks RTP for some filesystems
|
||||
so best ignore the result, and assume the user has correct permissions */
|
||||
(void) file_path;
|
||||
(void) permission;
|
||||
result = os_resultSuccess;
|
||||
#else
|
||||
if (access (file_path, permission) == 0) {
|
||||
result = os_resultSuccess;
|
||||
} else {
|
||||
result = os_resultFail;
|
||||
}
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
int
|
||||
os_vsnprintf(
|
||||
char *str,
|
||||
|
@ -130,125 +108,11 @@ os_vfprintfnosigpipe(
|
|||
return result;
|
||||
}
|
||||
|
||||
os_result
|
||||
os_stat(
|
||||
const char *path,
|
||||
struct os_stat *buf)
|
||||
{
|
||||
os_result result;
|
||||
struct stat _buf;
|
||||
int r;
|
||||
|
||||
r = stat(path, &_buf);
|
||||
if (r == 0) {
|
||||
buf->stat_mode = _buf.st_mode;
|
||||
buf->stat_size = (size_t) _buf.st_size;
|
||||
buf->stat_mtime.tv_sec = (os_timeSec) _buf.st_mtime;
|
||||
buf->stat_mtime.tv_nsec = 0;
|
||||
result = os_resultSuccess;
|
||||
} else {
|
||||
result = os_resultFail;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
os_result os_remove (const char *pathname)
|
||||
{
|
||||
return (remove (pathname) == 0) ? os_resultSuccess : os_resultFail;
|
||||
}
|
||||
|
||||
os_result os_rename (const char *oldpath, const char *newpath)
|
||||
{
|
||||
return (rename (oldpath, newpath) == 0) ? os_resultSuccess : os_resultFail;
|
||||
}
|
||||
|
||||
/* The result of os_fileNormalize should be freed with os_free */
|
||||
char *
|
||||
os_fileNormalize(
|
||||
const char *filepath)
|
||||
{
|
||||
char *norm;
|
||||
const char *fpPtr;
|
||||
char *normPtr;
|
||||
|
||||
norm = NULL;
|
||||
if ((filepath != NULL) && (*filepath != '\0')) {
|
||||
norm = os_malloc(strlen(filepath) + 1);
|
||||
/* replace any / or \ by OS_FILESEPCHAR */
|
||||
fpPtr = (char *) filepath;
|
||||
normPtr = norm;
|
||||
while (*fpPtr != '\0') {
|
||||
*normPtr = *fpPtr;
|
||||
if ((*fpPtr == '/') || (*fpPtr == '\\')) {
|
||||
*normPtr = OS_FILESEPCHAR;
|
||||
normPtr++;
|
||||
} else {
|
||||
if (*fpPtr != '\"') {
|
||||
normPtr++;
|
||||
}
|
||||
}
|
||||
fpPtr++;
|
||||
}
|
||||
*normPtr = '\0';
|
||||
}
|
||||
|
||||
return norm;
|
||||
}
|
||||
|
||||
os_result
|
||||
os_fsync(
|
||||
FILE *fHandle)
|
||||
{
|
||||
os_result r;
|
||||
|
||||
if (fsync(fileno(fHandle)) == 0) {
|
||||
r = os_resultSuccess;
|
||||
} else {
|
||||
r = os_resultFail;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
_Ret_opt_z_ const char *
|
||||
os_getTempDir(void)
|
||||
{
|
||||
const char * dir_name = NULL;
|
||||
|
||||
dir_name = os_getenv("OSPL_TEMP");
|
||||
|
||||
/* if OSPL_TEMP is not defined the default is /tmp */
|
||||
if (dir_name == NULL || (strcmp (dir_name, "") == 0)) {
|
||||
dir_name = "/tmp";
|
||||
}
|
||||
|
||||
return dir_name;
|
||||
}
|
||||
|
||||
ssize_t os_write(int fd, const void *buf, size_t count)
|
||||
{
|
||||
return write(fd, buf, count);
|
||||
}
|
||||
|
||||
void os_flockfile(FILE *file)
|
||||
{
|
||||
/* flockfile is not supported on the VxWorks DKM platform.
|
||||
* Therefore, this function block is empty on the VxWorks platform. */
|
||||
#ifndef _WRS_KERNEL
|
||||
flockfile (file);
|
||||
#endif
|
||||
}
|
||||
|
||||
void os_funlockfile(FILE *file)
|
||||
{
|
||||
/* funlockfile is not supported on the VxWorks DKM platform.
|
||||
* Therefore, this function block is empty on the VxWorks platform. */
|
||||
#ifndef _WRS_KERNEL
|
||||
funlockfile (file);
|
||||
#endif
|
||||
}
|
||||
|
||||
int os_getopt(int argc, char **argv, const char *opts)
|
||||
{
|
||||
return getopt(argc, argv, opts);
|
||||
|
|
|
@ -23,8 +23,6 @@
|
|||
* independent conversions.
|
||||
*/
|
||||
|
||||
#include "os/os_report.h"
|
||||
|
||||
/*
|
||||
* Determine the maximum size that a string should have to be
|
||||
* able to contain a double.
|
||||
|
@ -76,9 +74,8 @@ os_lcNumericGet(void)
|
|||
(void) snprintf(num, 4, "%3.1f", 2.2);
|
||||
lcNumeric = num [1];
|
||||
if (lcNumeric != '.') {
|
||||
OS_WARNING("os_stdlib", 0,
|
||||
"Locale with LC_NUMERIC \'%c\' detected, which is not '.'. This can decrease performance.",
|
||||
lcNumeric);
|
||||
DDS_WARNING("Locale with LC_NUMERIC \'%c\' detected, which is not '.'. "
|
||||
"This can decrease performance.", lcNumeric);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -84,7 +84,7 @@ void os_osExit (void)
|
|||
uint32_t initCount;
|
||||
|
||||
#if defined(OS_USE_ALLIGNED_MALLOC) && !defined(NDEBUG)
|
||||
OS_INFO("os__reallocdoublecopycount", 0, "count=%d", vxAtomicGet(&os__reallocdoublecopycount));
|
||||
DDS_INFO("count=%d\n", vxAtomicGet(&os__reallocdoublecopycount));
|
||||
#endif
|
||||
initCount = os_atomic_dec32_nv(&_ospl_osInitCount);
|
||||
|
||||
|
@ -96,7 +96,7 @@ void os_osExit (void)
|
|||
/* The 0 boundary is passed, so os_osExit is called more often than
|
||||
* os_osInit. Therefore undo decrement as nothing happened and warn. */
|
||||
initCount = os_atomic_inc32_nv(&_ospl_osInitCount);
|
||||
OS_WARNING("os_osExit", 1, "OS-layer not initialized");
|
||||
DDS_WARNING("OS-layer not initialized\n");
|
||||
/* Fail in case of DEV, as it is incorrect API usage */
|
||||
assert(0);
|
||||
}
|
||||
|
|
|
@ -26,14 +26,12 @@ void os_osPlatformInit (void)
|
|||
os_processModuleInit();
|
||||
os_threadModuleInit();
|
||||
os_timeModuleInit();
|
||||
os_reportInit(false);
|
||||
os_socketModuleInit();
|
||||
}
|
||||
|
||||
void os_osPlatformExit (void)
|
||||
{
|
||||
os_socketModuleExit();
|
||||
os_reportExit();
|
||||
os_timeModuleExit();
|
||||
os_threadModuleExit();
|
||||
os_processModuleExit();
|
||||
|
|
|
@ -58,7 +58,7 @@ os_socketModuleInit()
|
|||
|
||||
err = WSAStartup (wVersionRequested, &wsaData);
|
||||
if (err != 0) {
|
||||
OS_FATAL("os_socketModuleInit", 0, "WSAStartup failed, no compatible socket implementation available");
|
||||
DDS_FATAL("WSAStartup failed, no compatible socket implementation available\n");
|
||||
/* Tell the user that we could not find a usable */
|
||||
/* WinSock DLL. */
|
||||
return;
|
||||
|
@ -74,14 +74,14 @@ os_socketModuleInit()
|
|||
(HIBYTE(wsaData.wVersion) != OS_SOCK_REVISION)) {
|
||||
/* Tell the user that we could not find a usable */
|
||||
/* WinSock DLL. */
|
||||
OS_FATAL("os_socketModuleInit", 1, "WSAStartup failed, no compatible socket implementation available");
|
||||
DDS_FATAL("WSAStartup failed, no compatible socket implementation available\n");
|
||||
WSACleanup();
|
||||
return;
|
||||
}
|
||||
|
||||
qwaveDLLModuleLock = CreateMutex(NULL, FALSE, NULL);
|
||||
if (qwaveDLLModuleLock == NULL) {
|
||||
OS_ERROR("os_socketModuleInit", 0, "Failed to create mutex");
|
||||
DDS_ERROR("Failed to create mutex\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -232,7 +232,7 @@ os_sockSetDscpValueWithTos(
|
|||
char errmsg[1024];
|
||||
int errNo = os_getErrno();
|
||||
(void) os_strerror_r(errNo, errmsg, sizeof errmsg);
|
||||
OS_WARNING("os_sockSetDscpValue", 0, "Failed to set diffserv value to %lu: %d %s", value, errNo, errmsg);
|
||||
DDS_WARNING("Failed to set diffserv value to %lu: %d %s\n", value, errNo, errmsg);
|
||||
result = os_resultFail;
|
||||
}
|
||||
|
||||
|
@ -244,16 +244,14 @@ static os_result
|
|||
os_sockLoadQwaveLibrary(void)
|
||||
{
|
||||
if (qwaveDLLModuleLock == NULL) {
|
||||
OS_WARNING("os_sockLoadQwaveLibrary", 0,
|
||||
"Failed to load QWAVE.DLL for using diffserv on outgoing IP packets");
|
||||
DDS_WARNING("Failed to load QWAVE.DLL for using diffserv on outgoing IP packets\n");
|
||||
goto err_lock;
|
||||
}
|
||||
|
||||
WaitForSingleObject(qwaveDLLModuleLock, INFINITE);
|
||||
if (qwaveDLLModuleHandle == NULL) {
|
||||
if ((qwaveDLLModuleHandle = LoadLibrary("QWAVE.DLL")) == NULL) {
|
||||
OS_WARNING("os_sockLoadQwaveLibrary", 0,
|
||||
"Failed to load QWAVE.DLL for using diffserv on outgoing IP packets");
|
||||
DDS_WARNING("Failed to load QWAVE.DLL for using diffserv on outgoing IP packets\n");
|
||||
goto err_load_lib;
|
||||
}
|
||||
|
||||
|
@ -264,8 +262,7 @@ os_sockLoadQwaveLibrary(void)
|
|||
|
||||
if ((qwaveQOSCreateHandleFunc == 0) || (qwaveQOSCloseHandleFunc == 0) ||
|
||||
(qwaveQOSAddSocketToFlowFunc == 0) || (qwaveQOSSetFlowFunc == 0)) {
|
||||
OS_WARNING("os_sockLoadQwaveLibrary", 0,
|
||||
"Failed to resolve entry points for using diffserv on outgoing IP packets");
|
||||
DDS_WARNING("Failed to resolve entry points for using diffserv on outgoing IP packets\n");
|
||||
goto err_find_func;
|
||||
}
|
||||
}
|
||||
|
@ -277,7 +274,6 @@ err_find_func:
|
|||
err_load_lib:
|
||||
ReleaseMutex(qwaveDLLModuleLock);
|
||||
err_lock:
|
||||
|
||||
return os_resultFail;
|
||||
}
|
||||
|
||||
|
@ -384,7 +380,7 @@ os_sockSetDscpValueWithQos(
|
|||
char errmsg[1024];
|
||||
errNo = os_getErrno();
|
||||
(void)os_strerror_r(errNo, errmsg, sizeof errmsg);
|
||||
OS_ERROR("os_sockSetDscpValue", 0, "QOSCreateHandle failed: %d %s", errNo, errmsg);
|
||||
DDS_ERROR("QOSCreateHandle failed: %d %s\n", errNo, errmsg);
|
||||
goto err_create_handle;
|
||||
}
|
||||
|
||||
|
@ -397,7 +393,7 @@ os_sockSetDscpValueWithQos(
|
|||
char errmsg[1024];
|
||||
errNo = os_getErrno();
|
||||
(void)os_strerror_r(errNo, errmsg, sizeof errmsg);
|
||||
OS_ERROR("os_sockSetDscpValue", 0, "QOSAddSocketToFlow failed: %d %s", errNo, errmsg);
|
||||
DDS_ERROR("QOSAddSocketToFlow failed: %d %s\n", errNo, errmsg);
|
||||
qwaveQOSCloseHandleFunc(qosHandle);
|
||||
goto err_add_flow;
|
||||
}
|
||||
|
@ -405,9 +401,8 @@ os_sockSetDscpValueWithQos(
|
|||
if (value != defaultDscp) {
|
||||
|
||||
if (!setDscpSupported) {
|
||||
OS_WARNING("os_sockSetDscpValue", 0,
|
||||
"Failed to set diffserv value to %lu value used is %d, not supported on this platform",
|
||||
value, defaultDscp);
|
||||
DDS_WARNING("Failed to set diffserv value to %lu value used is %d, not supported on this platform\n",
|
||||
value, defaultDscp);
|
||||
goto err_set_flow;
|
||||
}
|
||||
|
||||
|
@ -417,14 +412,13 @@ os_sockSetDscpValueWithQos(
|
|||
if (!qosResult) {
|
||||
errNo = os_getErrno();
|
||||
if ((errNo == ERROR_ACCESS_DENIED) || (errNo == ERROR_ACCESS_DISABLED_BY_POLICY)) {
|
||||
OS_WARNING("os_sockSetDscpValue", 0,
|
||||
"Failed to set diffserv value to %lu value used is %d, not enough privileges",
|
||||
value, defaultDscp);
|
||||
DDS_WARNING("Failed to set diffserv value to %lu value used is %d, not enough privileges\n",
|
||||
value, defaultDscp);
|
||||
} else {
|
||||
char errmsg[1024];
|
||||
errNo = os_getErrno();
|
||||
(void)os_strerror_r(errNo, errmsg, sizeof errmsg);
|
||||
OS_ERROR("os_sockSetDscpValue", 0, "QOSSetFlow failed: %d %s", errNo, errmsg);
|
||||
DDS_ERROR("QOSSetFlow failed: %d %s\n", errNo, errmsg);
|
||||
}
|
||||
goto err_set_flow;
|
||||
}
|
||||
|
@ -435,7 +429,6 @@ os_sockSetDscpValueWithQos(
|
|||
err_set_flow:
|
||||
err_add_flow:
|
||||
err_create_handle:
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -447,11 +440,11 @@ os_sockSetDscpValue(
|
|||
{
|
||||
os_result result;
|
||||
|
||||
if (IsWindowsVistaOrGreater() && (os_sockLoadQwaveLibrary() == os_resultSuccess)) {
|
||||
result = os_sockSetDscpValueWithQos(sock, value, IsWindows7OrGreater());
|
||||
} else {
|
||||
result = os_sockSetDscpValueWithTos(sock, value);
|
||||
}
|
||||
if (IsWindowsVistaOrGreater() && (os_sockLoadQwaveLibrary() == os_resultSuccess)) {
|
||||
result = os_sockSetDscpValueWithQos(sock, value, IsWindows7OrGreater());
|
||||
} else {
|
||||
result = os_sockSetDscpValueWithTos(sock, value);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -516,7 +509,7 @@ os_sockSetNonBlocking(
|
|||
r = os_resultInvalid;
|
||||
break;
|
||||
case WSANOTINITIALISED:
|
||||
OS_FATAL("os_sockSetNonBlocking", 0, "Socket-module not initialised; ensure os_socketModuleInit is performed before using the socket module.");
|
||||
DDS_FATAL("Socket-module not initialised; ensure os_socketModuleInit is performed before using the socket module\n");
|
||||
default:
|
||||
r = os_resultFail;
|
||||
break;
|
||||
|
|
|
@ -26,32 +26,6 @@
|
|||
#include "../snippets/code/os_stdlib_strcasecmp.c"
|
||||
#include "../snippets/code/os_stdlib_strncasecmp.c"
|
||||
|
||||
static int32_t
|
||||
os__ensurePathExists(
|
||||
_In_z_ const char* dir_name);
|
||||
|
||||
/**
|
||||
* \brief create a directory with default
|
||||
* security descriptor. The mode parameter
|
||||
* is ignored for this Operating System.
|
||||
*
|
||||
*/
|
||||
int32_t
|
||||
os_mkdir(
|
||||
const char *path,
|
||||
os_mode_t mode)
|
||||
{
|
||||
int32_t result = 0;
|
||||
|
||||
if (CreateDirectory(path, NULL)) {
|
||||
result = 0;
|
||||
}
|
||||
else {
|
||||
result = -1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
os_result
|
||||
os_gethostname(
|
||||
char *hostname,
|
||||
|
@ -67,7 +41,7 @@ os_gethostname(
|
|||
|
||||
err = WSAStartup(wVersionRequested, &wsaData);
|
||||
if (err != 0) {
|
||||
OS_FATAL("os_gethostname", 0, "WSAStartup failed, no compatible socket implementation available");
|
||||
DDS_FATAL("WSAStartup failed, no compatible socket implementation available\n");
|
||||
/* Tell the user that we could not find a usable */
|
||||
/* WinSock DLL. */
|
||||
return os_resultFail;
|
||||
|
@ -114,38 +88,6 @@ os_putenv(
|
|||
return result;
|
||||
}
|
||||
|
||||
const char *
|
||||
os_fileSep(void)
|
||||
{
|
||||
return "\\";
|
||||
}
|
||||
|
||||
const char *
|
||||
os_pathSep(void)
|
||||
{
|
||||
return ";";
|
||||
}
|
||||
|
||||
os_result
|
||||
os_access(
|
||||
const char *file_path,
|
||||
int32_t permission)
|
||||
{
|
||||
struct _stat statbuf;
|
||||
os_result result;
|
||||
|
||||
result = os_resultFail;
|
||||
if (file_path) {
|
||||
if (_stat(file_path, &statbuf) == 0) {
|
||||
if ((statbuf.st_mode & permission) == permission) {
|
||||
result = os_resultSuccess;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#pragma warning( disable : 4996 )
|
||||
int
|
||||
os_vfprintfnosigpipe(
|
||||
|
@ -156,184 +98,6 @@ os_vfprintfnosigpipe(
|
|||
return vfprintf(file, format, args);
|
||||
}
|
||||
|
||||
os_result
|
||||
os_stat(
|
||||
const char *path,
|
||||
struct os_stat *buf)
|
||||
{
|
||||
os_result result;
|
||||
struct _stat32 _buf;
|
||||
int r;
|
||||
|
||||
r = _stat32(path, &_buf);
|
||||
if (r == 0) {
|
||||
buf->stat_mode = _buf.st_mode;
|
||||
buf->stat_size = _buf.st_size;
|
||||
buf->stat_mtime.tv_sec = _buf.st_mtime;
|
||||
buf->stat_mtime.tv_nsec = 0;
|
||||
result = os_resultSuccess;
|
||||
}
|
||||
else {
|
||||
result = os_resultFail;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
os_result os_remove(const char *pathname)
|
||||
{
|
||||
return (remove(pathname) == 0) ? os_resultSuccess : os_resultFail;
|
||||
}
|
||||
|
||||
os_result os_rename(const char *oldpath, const char *newpath)
|
||||
{
|
||||
(void)os_remove(newpath);
|
||||
return (rename(oldpath, newpath) == 0) ? os_resultSuccess : os_resultFail;
|
||||
}
|
||||
|
||||
/* The result of os_fileNormalize should be freed with os_free */
|
||||
_Ret_z_
|
||||
_Must_inspect_result_
|
||||
char *
|
||||
os_fileNormalize(
|
||||
_In_z_ const char *filepath)
|
||||
{
|
||||
char *norm;
|
||||
const char *fpPtr;
|
||||
char *normPtr;
|
||||
|
||||
norm = os_malloc(strlen(filepath) + 1);
|
||||
fpPtr = filepath;
|
||||
normPtr = norm;
|
||||
while (*fpPtr != '\0') {
|
||||
*normPtr = *fpPtr;
|
||||
if ((*fpPtr == '/') || (*fpPtr == '\\')) {
|
||||
*normPtr = OS_FILESEPCHAR;
|
||||
normPtr++;
|
||||
} else {
|
||||
if (*fpPtr != '\"') {
|
||||
normPtr++;
|
||||
}
|
||||
}
|
||||
fpPtr++;
|
||||
}
|
||||
*normPtr = '\0';
|
||||
|
||||
return norm;
|
||||
}
|
||||
|
||||
os_result
|
||||
os_fsync(
|
||||
FILE *fHandle)
|
||||
{
|
||||
os_result r;
|
||||
|
||||
if (FlushFileBuffers((HANDLE)fHandle)) {
|
||||
r = os_resultSuccess;
|
||||
}
|
||||
else {
|
||||
r = os_resultFail;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
_Ret_opt_z_ const char *
|
||||
os_getTempDir(void)
|
||||
{
|
||||
const char * dir_name = NULL;
|
||||
|
||||
dir_name = os_getenv("OSPL_TEMP");
|
||||
|
||||
/* if OSPL_TEMP is not defined use the TEMP variable */
|
||||
if (dir_name == NULL || (strcmp(dir_name, "") == 0)) {
|
||||
dir_name = os_getenv("TEMP");
|
||||
}
|
||||
|
||||
/* if TEMP is not defined use the TMP variable */
|
||||
if (dir_name == NULL || (strcmp(dir_name, "") == 0)) {
|
||||
dir_name = os_getenv("TMP");
|
||||
}
|
||||
|
||||
/* Now we need to verify if we found a temp directory path, and if we did
|
||||
* we have to make sure all the (sub)directories in the path exist.
|
||||
* This is needed to prevent any other operations from using the directory
|
||||
* path while it doesn't exist and therefore running into errors.
|
||||
*/
|
||||
if (dir_name == NULL || (strcmp(dir_name, "") == 0)) {
|
||||
OS_ERROR("os_getTempDir", 0,
|
||||
"Could not retrieve temporary directory path - "
|
||||
"neither of environment variables TEMP, TMP, OSPL_TEMP were set");
|
||||
}
|
||||
else if (os__ensurePathExists(dir_name) != 0)
|
||||
{
|
||||
OS_ERROR("os_getTempDir", 0,
|
||||
"Could not ensure all (sub)directories of the temporary directory\n"
|
||||
"path '%s' exist.\n"
|
||||
"This has consequences for the ability of OpenSpliceDDS to run\n"
|
||||
"properly, as the directory path must be accessible to create\n"
|
||||
"database and key files in. Without this ability OpenSpliceDDS can\n"
|
||||
"not start.\n",
|
||||
dir_name);
|
||||
}
|
||||
|
||||
return dir_name;
|
||||
}
|
||||
|
||||
int32_t
|
||||
os__ensurePathExists(
|
||||
_In_z_ const char* dir_name)
|
||||
{
|
||||
char* tmp;
|
||||
char* ptr;
|
||||
char ptrTmp;
|
||||
struct os_stat statBuf;
|
||||
os_result status;
|
||||
int32_t result = 0;
|
||||
int32_t cont = 1;
|
||||
|
||||
tmp = os_strdup(dir_name);
|
||||
|
||||
for (ptr = tmp; cont; ptr++)
|
||||
{
|
||||
if (*ptr == '\\' || *ptr == '/' || *ptr == '\0')
|
||||
{
|
||||
ptrTmp = ptr[0];
|
||||
ptr[0] = '\0';
|
||||
status = os_stat(tmp, &statBuf);
|
||||
|
||||
if (status != os_resultSuccess)
|
||||
{
|
||||
os_mkdir(tmp, 0);
|
||||
status = os_stat(tmp, &statBuf);
|
||||
}
|
||||
|
||||
if (!OS_ISDIR(statBuf.stat_mode))
|
||||
{
|
||||
if ((strlen(tmp) == 2) && (tmp[1] == ':')) {
|
||||
/*This is a device like for instance: 'C:'*/
|
||||
}
|
||||
else
|
||||
{
|
||||
OS_ERROR("os_ensurePathExists", 0,
|
||||
"Unable to create directory '%s' within path '%s'. Errorcode: %d",
|
||||
tmp,
|
||||
dir_name,
|
||||
os_getErrno());
|
||||
result = -1;
|
||||
}
|
||||
}
|
||||
ptr[0] = ptrTmp;
|
||||
}
|
||||
if (*ptr == '\0' || result == -1)
|
||||
{
|
||||
cont = 0;
|
||||
}
|
||||
}
|
||||
os_free(tmp);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#pragma warning( disable : 4996 )
|
||||
int
|
||||
os_vsnprintf(
|
||||
|
@ -404,16 +168,6 @@ ssize_t os_write(
|
|||
return _write(fd, buf, (unsigned int)count); /* Type casting is done for the warning of conversion from 'size_t' to 'unsigned int', which may cause possible loss of data */
|
||||
}
|
||||
|
||||
void os_flockfile(FILE *file)
|
||||
{
|
||||
_lock_file (file);
|
||||
}
|
||||
|
||||
void os_funlockfile(FILE *file)
|
||||
{
|
||||
_unlock_file (file);
|
||||
}
|
||||
|
||||
int os_getopt(
|
||||
_In_range_(0, INT_MAX) int argc,
|
||||
_In_reads_z_(argc) char **argv,
|
||||
|
|
|
@ -188,8 +188,6 @@ os_startRoutineWrapper(
|
|||
/* Call the user routine */
|
||||
resultValue = context->startRoutine(context->arguments);
|
||||
|
||||
os_report_stack_free();
|
||||
|
||||
/* Free the thread context resources, arguments is responsibility */
|
||||
/* for the caller of os_threadCreate */
|
||||
os_free (context->threadName);
|
||||
|
@ -236,7 +234,7 @@ os_threadCreate(
|
|||
(LPVOID)threadContext,
|
||||
(DWORD)0, &threadIdent);
|
||||
if (threadHandle == 0) {
|
||||
OS_WARNING("os_threadCreate", os_getErrno(), "Failed with System Error Code: %i\n", os_getErrno ());
|
||||
DDS_WARNING("Failed with System Error Code: %i\n", os_getErrno ());
|
||||
return os_resultFail;
|
||||
}
|
||||
|
||||
|
@ -277,7 +275,7 @@ os_threadCreate(
|
|||
}
|
||||
}
|
||||
if (SetThreadPriority (threadHandle, effective_priority) == 0) {
|
||||
OS_INFO("os_threadCreate", os_getErrno(), "SetThreadPriority failed with %i", os_getErrno());
|
||||
DDS_INFO("SetThreadPriority failed with %i\n", os_getErrno());
|
||||
}
|
||||
|
||||
/* ES: dds2086: Close handle should not be performed here. Instead the handle
|
||||
|
@ -358,29 +356,6 @@ os_threadWaitExit(
|
|||
return os_resultSuccess;
|
||||
}
|
||||
|
||||
/** \brief Figure out the identity of the current thread
|
||||
*
|
||||
* Possible Results:
|
||||
* - returns the actual length of threadIdentity
|
||||
*/
|
||||
int
|
||||
os_threadFigureIdentity(
|
||||
char *threadIdentity,
|
||||
uint32_t threadIdentitySize)
|
||||
{
|
||||
int size;
|
||||
char* threadName;
|
||||
|
||||
threadName = (char *)os_threadMemGet(OS_THREAD_NAME);
|
||||
if (threadName != NULL) {
|
||||
size = snprintf (threadIdentity, threadIdentitySize, "%s 0x%"PRIx32, threadName, GetCurrentThreadId());
|
||||
} else {
|
||||
size = snprintf (threadIdentity, threadIdentitySize, "0x%"PRIx32, GetCurrentThreadId());
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
int
|
||||
os_threadGetThreadName(
|
||||
char *buffer,
|
||||
|
|
|
@ -19,7 +19,6 @@ set(sources
|
|||
"iter.c"
|
||||
"mutex.c"
|
||||
"once.c"
|
||||
"report.c"
|
||||
"rwlock.c"
|
||||
"stdlib.c"
|
||||
"strtoll.c"
|
||||
|
|
|
@ -1,404 +0,0 @@
|
|||
/*
|
||||
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||
* v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||
*/
|
||||
#include "CUnit/Test.h"
|
||||
#include "os/os.h"
|
||||
#include "os/os_project.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
CU_Init(os_report)
|
||||
{
|
||||
os_putenv(OS_PROJECT_NAME_NOSPACE_CAPS"_ERRORFILE=vdds_test_error");
|
||||
os_putenv(OS_PROJECT_NAME_NOSPACE_CAPS"_INFOFILE=vdds_test_info");
|
||||
os_putenv(OS_PROJECT_NAME_NOSPACE_CAPS"_LOGAPPEND=TRUE");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void remove_logs()
|
||||
{
|
||||
const char * error_file_name = os_getenv(OS_PROJECT_NAME_NOSPACE_CAPS"_ERRORFILE");
|
||||
const char * info_file_name = os_getenv(OS_PROJECT_NAME_NOSPACE_CAPS"_INFOFILE");
|
||||
|
||||
os_remove(error_file_name);
|
||||
os_remove(info_file_name);
|
||||
}
|
||||
|
||||
void check_existence(os_result error_log_existence, os_result info_log_existence)
|
||||
{
|
||||
const char * error_file_name = os_getenv(OS_PROJECT_NAME_NOSPACE_CAPS"_ERRORFILE");
|
||||
const char * info_file_name = os_getenv(OS_PROJECT_NAME_NOSPACE_CAPS"_INFOFILE");
|
||||
|
||||
CU_ASSERT(os_access(error_file_name, OS_ROK) == error_log_existence);
|
||||
CU_ASSERT(os_access(info_file_name, OS_ROK) == info_log_existence);
|
||||
}
|
||||
|
||||
CU_Clean(os_report)
|
||||
{
|
||||
remove_logs();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
CU_Test(os_report, re_init)
|
||||
{
|
||||
os_reportInit(true);
|
||||
|
||||
OS_INFO(OS_FUNCTION, 0, "os_report-info-test %d", __LINE__);
|
||||
OS_ERROR(OS_FUNCTION, 0, "os_report-error-test %d", __LINE__);
|
||||
|
||||
check_existence(os_resultSuccess, os_resultSuccess);
|
||||
|
||||
os_reportExit();
|
||||
|
||||
os_reportInit(true);
|
||||
check_existence(os_resultSuccess, os_resultSuccess);
|
||||
|
||||
OS_INFO(OS_FUNCTION, 0, "os_report-info-test %d", __LINE__);
|
||||
|
||||
os_reportExit();
|
||||
|
||||
remove_logs();
|
||||
}
|
||||
|
||||
|
||||
CU_Test(os_report, stack_critical)
|
||||
{
|
||||
os_reportInit(true);
|
||||
|
||||
OS_REPORT_STACK();
|
||||
|
||||
OS_CRITICAL(OS_FUNCTION, 0, "os_report-error-test %d", __LINE__);
|
||||
|
||||
check_existence(os_resultFail, os_resultFail);
|
||||
|
||||
OS_REPORT_FLUSH(false);
|
||||
|
||||
// Since a critical is logged, the error log should be created
|
||||
check_existence(os_resultSuccess, os_resultFail);
|
||||
|
||||
os_reportExit();
|
||||
|
||||
remove_logs();
|
||||
}
|
||||
|
||||
|
||||
CU_Test(os_report, stack_non_critical)
|
||||
{
|
||||
os_reportInit(true);
|
||||
|
||||
OS_REPORT_STACK();
|
||||
|
||||
OS_ERROR(OS_FUNCTION, 0, "os_report-error-test %d", __LINE__);
|
||||
|
||||
check_existence(os_resultFail, os_resultFail);
|
||||
|
||||
OS_REPORT_FLUSH(false);
|
||||
|
||||
// Since a non critical is logged, the error log should not be created
|
||||
check_existence(os_resultFail, os_resultFail);
|
||||
|
||||
os_reportExit();
|
||||
|
||||
remove_logs();
|
||||
}
|
||||
|
||||
|
||||
CU_Test(os_report, error_file_creation_critical)
|
||||
{
|
||||
os_reportInit(true);
|
||||
|
||||
OS_CRITICAL(OS_FUNCTION, 0, "os_report-critical-test %d", __LINE__);
|
||||
|
||||
check_existence(os_resultSuccess, os_resultFail);
|
||||
|
||||
os_reportExit();
|
||||
|
||||
remove_logs();
|
||||
}
|
||||
|
||||
|
||||
CU_Test(os_report, error_file_creation_fatal)
|
||||
{
|
||||
os_reportInit(true);
|
||||
|
||||
OS_FATAL(OS_FUNCTION, 0, "os_report-fatal-test %d", __LINE__);
|
||||
|
||||
check_existence(os_resultSuccess, os_resultFail);
|
||||
|
||||
os_reportExit();
|
||||
|
||||
remove_logs();
|
||||
}
|
||||
|
||||
|
||||
CU_Test(os_report, info_file_creation_warning)
|
||||
{
|
||||
os_reportInit(true);
|
||||
|
||||
OS_WARNING(OS_FUNCTION, 0, "os_report-warning-test %d", __LINE__);
|
||||
|
||||
check_existence(os_resultFail, os_resultSuccess);
|
||||
|
||||
os_reportExit();
|
||||
|
||||
remove_logs();
|
||||
}
|
||||
|
||||
|
||||
CU_Test(os_report, info_file_creation_info)
|
||||
{
|
||||
os_reportInit(true);
|
||||
|
||||
OS_INFO(OS_FUNCTION, 0, "os_report-info-test %d", __LINE__);
|
||||
|
||||
check_existence(os_resultFail, os_resultSuccess);
|
||||
|
||||
os_reportExit();
|
||||
|
||||
remove_logs();
|
||||
}
|
||||
|
||||
|
||||
CU_Test(os_report, verbosity_low)
|
||||
{
|
||||
os_reportInit(true);
|
||||
check_existence(os_resultFail, os_resultFail);
|
||||
|
||||
os_reportVerbosity = OS_REPORT_ERROR;
|
||||
|
||||
OS_WARNING(OS_FUNCTION, 0, "os_report-info-test %d", __LINE__);
|
||||
|
||||
check_existence(os_resultFail, os_resultFail);
|
||||
|
||||
os_reportExit();
|
||||
|
||||
remove_logs();
|
||||
}
|
||||
|
||||
|
||||
CU_Test(os_report, verbosity_high)
|
||||
{
|
||||
os_reportInit(true);
|
||||
check_existence(os_resultFail, os_resultFail);
|
||||
|
||||
os_reportVerbosity = OS_REPORT_DEBUG;
|
||||
|
||||
OS_WARNING(OS_FUNCTION, 0, "os_report-info-test %d", __LINE__);
|
||||
|
||||
check_existence(os_resultFail, os_resultSuccess);
|
||||
|
||||
os_reportExit();
|
||||
|
||||
remove_logs();
|
||||
}
|
||||
|
||||
|
||||
|
||||
CU_Test(os_report, verbosity_equal)
|
||||
{
|
||||
os_reportInit(true);
|
||||
check_existence(os_resultFail, os_resultFail);
|
||||
|
||||
os_reportVerbosity = OS_REPORT_WARNING;
|
||||
|
||||
OS_WARNING(OS_FUNCTION, 0, "os_report-info-test %d", __LINE__);
|
||||
|
||||
check_existence(os_resultFail, os_resultSuccess);
|
||||
|
||||
os_reportExit();
|
||||
|
||||
remove_logs();
|
||||
}
|
||||
|
||||
|
||||
CU_Test(os_report, stack_verbosity_low)
|
||||
{
|
||||
os_reportInit(true);
|
||||
check_existence(os_resultFail, os_resultFail);
|
||||
|
||||
os_reportVerbosity = OS_REPORT_ERROR;
|
||||
|
||||
OS_REPORT_STACK();
|
||||
OS_WARNING(OS_FUNCTION, 0, "os_report-info-test %d", __LINE__);
|
||||
OS_REPORT_FLUSH(true);
|
||||
|
||||
check_existence(os_resultFail, os_resultFail);
|
||||
|
||||
os_reportExit();
|
||||
|
||||
remove_logs();
|
||||
}
|
||||
|
||||
|
||||
CU_Test(os_report, stack_verbosity_high)
|
||||
{
|
||||
os_reportInit(true);
|
||||
check_existence(os_resultFail, os_resultFail);
|
||||
|
||||
os_reportVerbosity = OS_REPORT_DEBUG;
|
||||
|
||||
OS_REPORT_STACK();
|
||||
OS_WARNING(OS_FUNCTION, 0, "os_report-info-test %d", __LINE__);
|
||||
OS_REPORT_FLUSH(true);
|
||||
|
||||
check_existence(os_resultFail, os_resultSuccess);
|
||||
|
||||
os_reportExit();
|
||||
|
||||
remove_logs();
|
||||
}
|
||||
|
||||
|
||||
|
||||
CU_Test(os_report, stack_verbosity_equal)
|
||||
{
|
||||
os_reportInit(true);
|
||||
check_existence(os_resultFail, os_resultFail);
|
||||
|
||||
os_reportVerbosity = OS_REPORT_WARNING;
|
||||
|
||||
OS_REPORT_STACK();
|
||||
OS_WARNING(OS_FUNCTION, 0, "os_report-info-test %d", __LINE__);
|
||||
OS_REPORT_FLUSH(true);
|
||||
|
||||
check_existence(os_resultFail, os_resultSuccess);
|
||||
|
||||
os_reportExit();
|
||||
|
||||
remove_logs();
|
||||
}
|
||||
|
||||
|
||||
CU_Test(os_report, no_log_append)
|
||||
{
|
||||
os_reportInit(true);
|
||||
check_existence(os_resultFail, os_resultFail);
|
||||
|
||||
OS_ERROR(OS_FUNCTION, 0, "os_report-error-test %d", __LINE__);
|
||||
OS_INFO(OS_FUNCTION, 0, "os_report-info-test %d", __LINE__);
|
||||
|
||||
check_existence(os_resultSuccess, os_resultSuccess);
|
||||
|
||||
os_reportExit();
|
||||
|
||||
os_putenv(OS_PROJECT_NAME_NOSPACE_CAPS"_LOGAPPEND=FALSE");
|
||||
|
||||
os_reportInit(true);
|
||||
|
||||
// Both logs should be deleted
|
||||
check_existence(os_resultFail, os_resultFail);
|
||||
|
||||
os_reportExit();
|
||||
|
||||
remove_logs();
|
||||
}
|
||||
|
||||
|
||||
CU_Test(os_report, log_dir)
|
||||
{
|
||||
os_putenv(OS_PROJECT_NAME_NOSPACE_CAPS"_LOGPATH=.");
|
||||
|
||||
os_reportInit(true);
|
||||
|
||||
check_existence(os_resultFail, os_resultFail);
|
||||
|
||||
OS_ERROR(OS_FUNCTION, 0, "os_report-error-test %d", __LINE__);
|
||||
OS_INFO(OS_FUNCTION, 0, "os_report-info-test %d", __LINE__);
|
||||
|
||||
check_existence(os_resultSuccess, os_resultSuccess);
|
||||
|
||||
os_reportExit();
|
||||
|
||||
remove_logs();
|
||||
}
|
||||
|
||||
|
||||
CU_Test(os_report, verbosity_env_value_info)
|
||||
{
|
||||
os_putenv(OS_PROJECT_NAME_NOSPACE_CAPS"_VERBOSITY=0");
|
||||
os_reportInit(true);
|
||||
check_existence(os_resultFail, os_resultFail);
|
||||
|
||||
OS_ERROR(OS_FUNCTION, 0, "os_report-error-test %d", __LINE__);
|
||||
OS_INFO(OS_FUNCTION, 0, "os_report-info-test %d", __LINE__);
|
||||
|
||||
check_existence(os_resultSuccess, os_resultSuccess);
|
||||
|
||||
os_reportExit();
|
||||
|
||||
remove_logs();
|
||||
|
||||
//reset for other tests.
|
||||
os_putenv(OS_PROJECT_NAME_NOSPACE_CAPS"_VERBOSITY=");
|
||||
}
|
||||
|
||||
|
||||
CU_Test(os_report, verbosity_env_value_error)
|
||||
{
|
||||
os_putenv(OS_PROJECT_NAME_NOSPACE_CAPS"_VERBOSITY=3");
|
||||
os_reportInit(true);
|
||||
check_existence(os_resultFail, os_resultFail);
|
||||
|
||||
OS_ERROR(OS_FUNCTION, 0, "os_report-error-test %d", __LINE__);
|
||||
OS_INFO(OS_FUNCTION, 0, "os_report-info-test %d", __LINE__);
|
||||
|
||||
check_existence(os_resultSuccess, os_resultFail);
|
||||
|
||||
os_reportExit();
|
||||
|
||||
remove_logs();
|
||||
|
||||
//reset for other tests.
|
||||
os_putenv(OS_PROJECT_NAME_NOSPACE_CAPS"_VERBOSITY=");
|
||||
}
|
||||
|
||||
|
||||
CU_Test(os_report, verbosity_env_value_error_as_string)
|
||||
{
|
||||
os_putenv(OS_PROJECT_NAME_NOSPACE_CAPS"_VERBOSITY=ERROR");
|
||||
os_reportInit(true);
|
||||
check_existence(os_resultFail, os_resultFail);
|
||||
|
||||
OS_ERROR(OS_FUNCTION, 0, "os_report-error-test %d", __LINE__);
|
||||
OS_DEBUG(OS_FUNCTION, 0, "os_report-info-test %d", __LINE__);
|
||||
|
||||
check_existence(os_resultSuccess, os_resultFail);
|
||||
|
||||
os_reportExit();
|
||||
|
||||
remove_logs();
|
||||
|
||||
//reset for other tests.
|
||||
os_putenv(OS_PROJECT_NAME_NOSPACE_CAPS"_VERBOSITY=");
|
||||
}
|
||||
|
||||
|
||||
CU_Test(os_report, verbosity_wrong_env_value)
|
||||
{
|
||||
os_putenv(OS_PROJECT_NAME_NOSPACE_CAPS"_VERBOSITY=WRONG");
|
||||
os_reportInit(true);
|
||||
check_existence(os_resultFail, os_resultFail);
|
||||
|
||||
OS_ERROR(OS_FUNCTION, 0, "os_report-error-test %d", __LINE__);
|
||||
OS_DEBUG(OS_FUNCTION, 0, "os_report-error-test %d", __LINE__);
|
||||
|
||||
check_existence(os_resultSuccess, os_resultFail);
|
||||
|
||||
os_reportExit();
|
||||
|
||||
remove_logs();
|
||||
|
||||
//reset for other tests.
|
||||
os_putenv(OS_PROJECT_NAME_NOSPACE_CAPS"_VERBOSITY=");
|
||||
}
|
|
@ -12,261 +12,8 @@
|
|||
#include "CUnit/Test.h"
|
||||
#include "os/os.h"
|
||||
|
||||
#ifndef WINCE
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
#if (defined WIN32 || defined WIN64)
|
||||
#include <direct.h>
|
||||
#include <Windows.h>
|
||||
#endif
|
||||
|
||||
static const os_time wait_time_out = { 1, 0 };
|
||||
static FILE *file;
|
||||
|
||||
#define ENABLE_TRACING 0
|
||||
|
||||
#define FLOCKFILE_THREAD1_INPUT1 "thread1_flockfile_proc: *** input 1 ***"
|
||||
#define FLOCKFILE_THREAD1_INPUT3 "thread1_flockfile_proc: *** input 3 ***"
|
||||
#define FLOCKFILE_THREAD2_INPUT2 "thread2_flockfile_proc: *** input 2 ***"
|
||||
|
||||
#define defSignal(signal) \
|
||||
static os_cond signal;\
|
||||
static bool signal##_set = false;
|
||||
|
||||
#define initSignal(signal, mutex) \
|
||||
os_condInit(&signal, &mutex);\
|
||||
signal##_set = false;
|
||||
|
||||
#define sendSignal(signal, mutex) \
|
||||
os_mutexLock(&mutex);\
|
||||
/* signaling */ \
|
||||
signal##_set = true; \
|
||||
os_condSignal(&signal);\
|
||||
os_mutexUnlock(&mutex);
|
||||
|
||||
#define waitForSignal(signal, mutex) \
|
||||
os_mutexLock(&mutex);\
|
||||
while(!signal##_set) { \
|
||||
/* waiting for signal */ \
|
||||
os_condWait(&signal, &mutex);\
|
||||
/* received */ \
|
||||
} /* else already signal received */ \
|
||||
os_mutexUnlock(&mutex);
|
||||
|
||||
#define timedWaitSignal(signal, mutex, time) \
|
||||
{ \
|
||||
os_time duration = time; \
|
||||
os_time startTime, currentTime; \
|
||||
os_result rc; \
|
||||
os_mutexLock(&mutex); \
|
||||
startTime = os_timeGetElapsed(); \
|
||||
while(!signal##_set) { \
|
||||
/* waiting for signal */ \
|
||||
rc = os_condTimedWait(&signal, &mutex, &duration); \
|
||||
/* signal received or timeout */ \
|
||||
if(rc == os_resultTimeout) { \
|
||||
break; \
|
||||
} else { \
|
||||
currentTime = os_timeGetElapsed(); \
|
||||
if(os_timeCompare(os_timeSub(currentTime, startTime), wait_time_out) >= 0) { \
|
||||
break; \
|
||||
} \
|
||||
duration = os_timeSub(wait_time_out, os_timeSub(currentTime, startTime)); \
|
||||
} \
|
||||
} /* else already signal received */ \
|
||||
os_mutexUnlock(&mutex);\
|
||||
}
|
||||
|
||||
static os_mutex mutex;
|
||||
static bool do_locking;
|
||||
|
||||
/* signals set by threads */
|
||||
defSignal(thread1_started);
|
||||
defSignal(thread2_started);
|
||||
defSignal(action1_done);
|
||||
defSignal(action2_done);
|
||||
|
||||
/* signals set by the test orchestrator (doFlockfileTest) */
|
||||
defSignal(do_action1);
|
||||
defSignal(do_action2);
|
||||
defSignal(do_action3);
|
||||
|
||||
static uint32_t thread1_flockfile_proc(void* args) {
|
||||
int result = 0;
|
||||
(void)args;
|
||||
|
||||
/* thread1: start */
|
||||
sendSignal(thread1_started, mutex);
|
||||
|
||||
waitForSignal(do_action1, mutex);
|
||||
if(do_locking) os_flockfile(file);
|
||||
/* Thread1: writing input 1 to the file */
|
||||
result = fputs(FLOCKFILE_THREAD1_INPUT1, file);
|
||||
CU_ASSERT(result >= 0);
|
||||
|
||||
sendSignal(action1_done, mutex);
|
||||
|
||||
waitForSignal(do_action3, mutex);
|
||||
/* Thread1: writing input 3 to the file */
|
||||
result = fputs(FLOCKFILE_THREAD1_INPUT3, file);
|
||||
CU_ASSERT(result >= 0);
|
||||
if(do_locking) os_funlockfile(file);
|
||||
/* thread1: end */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t thread2_flockfile_proc(void* args) {
|
||||
int result = 0;
|
||||
(void)args;
|
||||
|
||||
/* thread2: start */
|
||||
sendSignal(thread2_started, mutex);
|
||||
|
||||
waitForSignal(do_action2, mutex);
|
||||
/* Thread2: writing input 2 to the file */
|
||||
result = fputs(FLOCKFILE_THREAD2_INPUT2, file);
|
||||
CU_ASSERT(result >= 0);
|
||||
|
||||
sendSignal(action2_done, mutex);
|
||||
/* thread2: end */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool doFlockfileTest(bool lock) {
|
||||
bool testPassed = true;
|
||||
bool strcmpResult = true;
|
||||
os_result result;
|
||||
os_threadAttr threadAttr;
|
||||
os_threadId thread1;
|
||||
os_threadId thread2;
|
||||
int FLOCKFILE_INPUT_MAX = sizeof(FLOCKFILE_THREAD1_INPUT1);
|
||||
|
||||
do_locking = lock;
|
||||
|
||||
char *buffer = os_malloc(sizeof(char) * (unsigned)FLOCKFILE_INPUT_MAX);
|
||||
|
||||
file = tmpfile();
|
||||
|
||||
os_mutexInit(&mutex);
|
||||
|
||||
/* initialize all signal conditions */
|
||||
os_mutexLock(&mutex);
|
||||
initSignal(thread1_started, mutex);
|
||||
initSignal(thread2_started, mutex);
|
||||
initSignal(action1_done, mutex);
|
||||
initSignal(action2_done, mutex);
|
||||
|
||||
initSignal(do_action1, mutex);
|
||||
initSignal(do_action2, mutex);
|
||||
initSignal(do_action3, mutex);
|
||||
os_mutexUnlock(&mutex);
|
||||
|
||||
/* create threads... */
|
||||
os_threadAttrInit(&threadAttr);
|
||||
|
||||
result = os_threadCreate(
|
||||
&thread1,
|
||||
"thread 1",
|
||||
&threadAttr,
|
||||
thread1_flockfile_proc,
|
||||
NULL);
|
||||
CU_ASSERT(result == os_resultSuccess);
|
||||
|
||||
result = os_threadCreate(
|
||||
&thread2,
|
||||
"thread 2",
|
||||
&threadAttr,
|
||||
thread2_flockfile_proc,
|
||||
NULL);
|
||||
CU_ASSERT(result == os_resultSuccess);
|
||||
|
||||
/* wait for threads to start */
|
||||
waitForSignal(thread1_started, mutex);
|
||||
waitForSignal(thread2_started, mutex);
|
||||
|
||||
/* get thread one to do its first thing */
|
||||
sendSignal(do_action1, mutex);
|
||||
|
||||
/* wait for thread 1 to acknowledge */
|
||||
timedWaitSignal(action1_done, mutex, wait_time_out);
|
||||
|
||||
/* kick thead 2 */
|
||||
sendSignal(do_action2, mutex);
|
||||
|
||||
/* wait for thread 2 to acknowledge */
|
||||
timedWaitSignal(action2_done, mutex, wait_time_out);
|
||||
|
||||
/* kick thread 1, again */
|
||||
sendSignal(do_action3, mutex);
|
||||
|
||||
/* wait for threads to shutdown */
|
||||
result = os_threadWaitExit(thread1,NULL);
|
||||
CU_ASSERT(result == os_resultSuccess);
|
||||
|
||||
result = os_threadWaitExit(thread2,NULL);
|
||||
CU_ASSERT(result == os_resultSuccess);
|
||||
|
||||
/* if lock then Expected action order: 1 3 2
|
||||
* else Expected action order: 1 2 3 */
|
||||
|
||||
rewind(file);
|
||||
|
||||
if(lock) {
|
||||
if(fgets(buffer, FLOCKFILE_INPUT_MAX, file) > (char*)0) {
|
||||
strcmpResult = (strcmp(buffer, FLOCKFILE_THREAD1_INPUT1) == 0);
|
||||
CU_ASSERT(strcmpResult);
|
||||
testPassed = testPassed && strcmpResult; /* update flag indicating overall test state */
|
||||
}
|
||||
if(fgets(buffer, FLOCKFILE_INPUT_MAX, file) > (char*)0) {
|
||||
strcmpResult = (strcmp(buffer, FLOCKFILE_THREAD1_INPUT3) == 0);
|
||||
CU_ASSERT(strcmpResult);
|
||||
testPassed = testPassed && strcmpResult; /* update flag indicating overall test state */
|
||||
}
|
||||
if(fgets(buffer, FLOCKFILE_INPUT_MAX, file) > (char*)0) {
|
||||
strcmpResult = (strcmp(buffer, FLOCKFILE_THREAD2_INPUT2) == 0);
|
||||
CU_ASSERT(strcmpResult);
|
||||
testPassed = testPassed && strcmpResult; /* update flag indicating overall test state */
|
||||
}
|
||||
} else {
|
||||
if(fgets(buffer, FLOCKFILE_INPUT_MAX, file) > (char*)0) {
|
||||
strcmpResult = (strcmp(buffer, FLOCKFILE_THREAD1_INPUT1) == 0);
|
||||
CU_ASSERT(strcmpResult);
|
||||
testPassed = testPassed && strcmpResult; /* update flag indicating overall test state */
|
||||
}
|
||||
if(fgets(buffer, FLOCKFILE_INPUT_MAX, file) > (char*)0) {
|
||||
strcmpResult = (strcmp(buffer, FLOCKFILE_THREAD2_INPUT2) == 0);
|
||||
CU_ASSERT(strcmpResult);
|
||||
testPassed = testPassed && strcmpResult; /* update flag indicating overall test state */
|
||||
}
|
||||
if(fgets(buffer, FLOCKFILE_INPUT_MAX, file) > (char*)0) {
|
||||
strcmpResult = (strcmp(buffer, FLOCKFILE_THREAD1_INPUT3) == 0);
|
||||
CU_ASSERT(strcmpResult);
|
||||
testPassed = testPassed && strcmpResult; /* update flag indicating overall test state */
|
||||
}
|
||||
}
|
||||
|
||||
/* cleanup */
|
||||
os_free(buffer);
|
||||
fclose(file);
|
||||
|
||||
os_mutexLock(&mutex);
|
||||
os_condDestroy(&do_action1);
|
||||
os_condDestroy(&do_action2);
|
||||
os_condDestroy(&do_action3);
|
||||
|
||||
os_condDestroy(&thread1_started);
|
||||
os_condDestroy(&thread2_started);
|
||||
os_condDestroy(&action1_done);
|
||||
os_condDestroy(&action2_done);
|
||||
os_mutexUnlock(&mutex);
|
||||
os_mutexDestroy(&mutex);
|
||||
/* doFlockfileTest */
|
||||
return testPassed;
|
||||
}
|
||||
|
||||
static int
|
||||
vsnprintfTest(
|
||||
const char *format,
|
||||
|
@ -292,15 +39,8 @@ CU_Init(os_stdlib)
|
|||
|
||||
CU_Clean(os_stdlib)
|
||||
{
|
||||
/* Remove files used to test permissions */
|
||||
remove ("exec_only");
|
||||
remove ("read_exec");
|
||||
remove ("read_only");
|
||||
remove ("read_write_exec");
|
||||
remove ("write_only");
|
||||
remove ("existing_file");
|
||||
os_osExit();
|
||||
return 0;
|
||||
os_osExit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
CU_Test(os_stdlib, gethostname)
|
||||
|
@ -356,254 +96,6 @@ CU_Test(os_stdlib, getenv)
|
|||
printf ("Ending os_stdlib_getenv\n");
|
||||
}
|
||||
|
||||
CU_Test(os_stdlib, fileSep)
|
||||
{
|
||||
#if defined WIN32
|
||||
const char *wanted= "\\";
|
||||
#else
|
||||
const char *wanted= "/";
|
||||
#endif
|
||||
printf ("Starting os_stdlib_fileSep_001\n");
|
||||
CU_ASSERT (strcmp(os_fileSep(), wanted) == 0);
|
||||
printf ("Ending os_stdlib_fileSep\n");
|
||||
}
|
||||
|
||||
CU_Test(os_stdlib, access)
|
||||
{
|
||||
os_result os_res;
|
||||
os_result wanted;
|
||||
int fh;
|
||||
|
||||
/* Check correct functioning of os_access, non existing file read access */
|
||||
printf ("Starting os_stdlib_access_001\n");
|
||||
#if defined VXWORKS_RTP || defined _WRS_KERNEL
|
||||
printf ("N.A - Not tested for vxworks.\n");
|
||||
#else
|
||||
os_res = os_access("non_existing_file", OS_ROK);
|
||||
CU_ASSERT (os_res == os_resultFail);
|
||||
|
||||
/* Check correct functioning of os_access, non existing file write access */
|
||||
printf ("Starting os_stdlib_access_002\n");
|
||||
os_res = os_access("non_existing_file", OS_WOK);
|
||||
CU_ASSERT (os_res == os_resultFail);
|
||||
|
||||
/* Check correct functioning of os_access, non existing file execute access */
|
||||
printf ("Starting os_stdlib_access_003\n");
|
||||
os_res = os_access("non_existing_file", OS_XOK);
|
||||
CU_ASSERT (os_res == os_resultFail);
|
||||
|
||||
/* Check correct functioning of os_access, non existing file existence */
|
||||
printf ("Starting os_stdlib_access_004\n");
|
||||
os_res = os_access("non_existing_file", OS_FOK);
|
||||
CU_ASSERT (os_res == os_resultFail);
|
||||
|
||||
/* Check correct functioning of os_access, existing file with no
|
||||
permissions read access */
|
||||
printf ("Starting os_stdlib_access_005\n");
|
||||
#ifdef WIN32
|
||||
fh= _creat("existing_file", 0000); /* Note always has read & execute */
|
||||
if (fh != -1)
|
||||
_close(fh);
|
||||
wanted = os_resultSuccess;
|
||||
#else
|
||||
fh= creat("existing_file", 0000);
|
||||
if (fh != -1)
|
||||
close(fh);
|
||||
wanted = os_resultFail;
|
||||
#endif /* WIN32 */
|
||||
os_res = os_access("existing_file", OS_ROK);
|
||||
CU_ASSERT (os_res == wanted);
|
||||
|
||||
/* Check correct functioning of os_access, existing file with no
|
||||
permissions write access */
|
||||
printf ("Starting os_stdlib_access_006\n");
|
||||
os_res = os_access("existing_file", OS_WOK);
|
||||
CU_ASSERT (os_res == os_resultFail);
|
||||
|
||||
/* Check correct functioning of os_access, existing file with no
|
||||
permissions execute access */
|
||||
printf ("Starting os_stdlib_access_007\n");
|
||||
os_res = os_access("existing_file", OS_XOK);
|
||||
CU_ASSERT (os_res == os_resultFail);
|
||||
|
||||
/* Check correct functioning of os_access, existing file with no permissions existence */
|
||||
printf ("Starting os_stdlib_access_008\n");
|
||||
os_res = os_access("existing_file", OS_FOK);
|
||||
CU_ASSERT (os_res == os_resultSuccess);
|
||||
|
||||
/* Check correct functioning of os_access,
|
||||
existing file with read permissions read access */
|
||||
printf ("Starting os_stdlib_access_009\n");
|
||||
#ifdef WIN32
|
||||
fh= _creat("read_only", _S_IREAD); /* Note always has read & execute */
|
||||
if (fh != -1)
|
||||
_close(fh);
|
||||
#else
|
||||
fh= creat("read_only", S_IRUSR);
|
||||
if (fh != -1)
|
||||
close(fh);
|
||||
#endif /* WIN32 */
|
||||
os_res = os_access("read_only", OS_ROK);
|
||||
CU_ASSERT (os_res == os_resultSuccess);
|
||||
|
||||
/* Check correct functioning of os_access,
|
||||
existing file with read permissions write access */
|
||||
printf ("Starting os_stdlib_access_010\n");
|
||||
os_res = os_access("read_only", OS_WOK);
|
||||
CU_ASSERT (os_res == os_resultFail);
|
||||
|
||||
/* Check correct functioning of os_access,
|
||||
existing file with read permissions execute access */
|
||||
printf ("Starting os_stdlib_access_011\n");
|
||||
os_res = os_access("read_only", OS_XOK);
|
||||
CU_ASSERT (os_res == os_resultFail);
|
||||
|
||||
/* Check correct functioning of os_access,
|
||||
existing file with read permissions existence */
|
||||
printf ("Starting os_stdlib_access_012\n");
|
||||
os_res = os_access("read_only", OS_FOK);
|
||||
CU_ASSERT (os_res == os_resultSuccess);
|
||||
|
||||
/* Check correct functioning of os_access,
|
||||
existing file with write permissions read access */
|
||||
printf ("Starting os_stdlib_access_013\n");
|
||||
#ifdef WIN32
|
||||
fh= _creat("write_only", _S_IWRITE); /* Note windows automatically has read access can't have write only */
|
||||
if (fh != -1)
|
||||
_close(fh);
|
||||
wanted = os_resultSuccess;
|
||||
#else
|
||||
fh= creat("write_only", S_IWUSR);
|
||||
if (fh != -1)
|
||||
close(fh);
|
||||
wanted = os_resultFail;
|
||||
#endif /* WIN32 */
|
||||
os_res = os_access("write_only", OS_ROK);
|
||||
CU_ASSERT (os_res == wanted);
|
||||
|
||||
/* Check correct functioning of os_access,
|
||||
existing file with write permissions write access */
|
||||
printf ("Starting os_stdlib_access_014\n");
|
||||
os_res = os_access("write_only", OS_WOK);
|
||||
CU_ASSERT (os_res == os_resultSuccess);
|
||||
|
||||
/* Check correct functioning of os_access,
|
||||
existing file with write permissions execute access */
|
||||
printf ("Starting os_stdlib_access_015\n");
|
||||
os_res = os_access("write_only", OS_XOK);
|
||||
CU_ASSERT (os_res == os_resultFail);
|
||||
|
||||
/* Check correct functioning of os_access,
|
||||
existing file with write permissions existence */
|
||||
printf ("Starting os_stdlib_access_016\n");
|
||||
os_res = os_access("write_only", OS_FOK);
|
||||
CU_ASSERT (os_res == os_resultSuccess);
|
||||
|
||||
/* Check correct functioning of os_access,
|
||||
existing file with exec permissions read access */
|
||||
printf ("Starting os_stdlib_access_017\n");
|
||||
#ifdef WIN32
|
||||
fh= _creat("exec_only" OS_OS_EXESUFFIX, _S_IREAD); /* Windows always has read and can't do execute (that's based upon filename ext only) */
|
||||
if (fh != -1)
|
||||
_close(fh);
|
||||
wanted = os_resultSuccess;
|
||||
#else
|
||||
fh= creat("exec_only" OS_OS_EXESUFFIX, S_IXUSR);
|
||||
if (fh != -1)
|
||||
close(fh);
|
||||
wanted = os_resultFail;
|
||||
#endif /* WIN32 */
|
||||
os_res = os_access("exec_only" OS_OS_EXESUFFIX, OS_ROK);
|
||||
CU_ASSERT (os_res == wanted);
|
||||
|
||||
/* Check correct functioning of os_access,
|
||||
existing file with exec permissions write access */
|
||||
printf ("Starting os_stdlib_access_018\n");
|
||||
os_res = os_access("exec_only" OS_OS_EXESUFFIX, OS_WOK);
|
||||
CU_ASSERT (os_res == os_resultFail);
|
||||
|
||||
/* Check correct functioning of os_access,
|
||||
existing file with exec permissions execute access */
|
||||
printf ("Starting os_stdlib_access_019\n");
|
||||
os_res = os_access("exec_only" OS_OS_EXESUFFIX, OS_XOK);
|
||||
CU_ASSERT (os_res == os_resultSuccess);
|
||||
|
||||
/* Check correct functioning of os_access,
|
||||
existing file with exec permissions existence */
|
||||
printf ("Starting os_stdlib_access_020\n");
|
||||
os_res = os_access("exec_only" OS_OS_EXESUFFIX, OS_FOK);
|
||||
CU_ASSERT (os_res == os_resultSuccess);
|
||||
|
||||
/* Check correct functioning of os_access,
|
||||
existing file with read/write/exec permissions read access */
|
||||
printf ("Starting os_stdlib_access_021\n");
|
||||
#ifdef WIN32
|
||||
fh= _creat("read_write_exec" OS_OS_EXESUFFIX, _S_IREAD | _S_IWRITE); /* Windows always has read and can't do execute (that's based upon filename ext only) */
|
||||
if (fh != -1)
|
||||
_close(fh);
|
||||
#else
|
||||
fh= creat("read_write_exec" OS_OS_EXESUFFIX, S_IRUSR | S_IWUSR | S_IXUSR);
|
||||
if (fh != -1)
|
||||
close(fh);
|
||||
#endif /* WIN32 */
|
||||
os_res = os_access("read_write_exec" OS_OS_EXESUFFIX, OS_ROK);
|
||||
CU_ASSERT (os_res == os_resultSuccess);
|
||||
|
||||
/* Check correct functioning of os_access,
|
||||
existing file with read/write/exec permissions write access */
|
||||
printf ("Starting os_stdlib_access_022\n");
|
||||
os_res = os_access("read_write_exec" OS_OS_EXESUFFIX, OS_WOK);
|
||||
CU_ASSERT (os_res == os_resultSuccess);
|
||||
|
||||
/* Check correct functioning of os_access,
|
||||
existing file with read/write/exec permissions execute access */
|
||||
printf ("Starting os_stdlib_access_023\n");
|
||||
os_res = os_access("read_write_exec" OS_OS_EXESUFFIX, OS_XOK);
|
||||
CU_ASSERT (os_res == os_resultSuccess);
|
||||
|
||||
/* Check correct functioning of os_access,
|
||||
existing file with read/write/exec permissions existence */
|
||||
printf ("Starting os_stdlib_access_024\n");
|
||||
os_res = os_access("read_write_exec" OS_OS_EXESUFFIX, OS_FOK);
|
||||
CU_ASSERT (os_res == os_resultSuccess);
|
||||
|
||||
/* Check correct functioning of os_access,
|
||||
existing file with read/exec permissions read+write access */
|
||||
printf ("Starting os_stdlib_access_025\n");
|
||||
#ifdef WIN32
|
||||
fh= _creat("read_exec" OS_OS_EXESUFFIX, _S_IREAD); /* Windows always has read and can't do execute (that's based upon filename ext only) */
|
||||
if (fh != -1)
|
||||
_close(fh);
|
||||
#else
|
||||
fh= creat("read_exec" OS_OS_EXESUFFIX, S_IRUSR | S_IXUSR);
|
||||
if (fh != -1)
|
||||
close(fh);
|
||||
#endif /* WIN32 */
|
||||
os_res = os_access("read_exec" OS_OS_EXESUFFIX, OS_ROK|OS_WOK);
|
||||
CU_ASSERT (os_res == os_resultFail);
|
||||
|
||||
/* Check correct functioning of os_access,
|
||||
existing file with read/exec permissions write+exec access */
|
||||
printf ("Starting os_stdlib_access_026\n");
|
||||
os_res = os_access("read_exec" OS_OS_EXESUFFIX, OS_WOK|OS_XOK);
|
||||
CU_ASSERT (os_res == os_resultFail);
|
||||
|
||||
/* Check correct functioning of os_access,
|
||||
existing file with read/exec permissions read+exec access */
|
||||
printf ("Starting os_stdlib_access_027\n");
|
||||
os_res = os_access("read_exec" OS_OS_EXESUFFIX, OS_ROK|OS_XOK);
|
||||
CU_ASSERT (os_res == os_resultSuccess);
|
||||
|
||||
/* Check correct functioning of os_access,
|
||||
existing file with read/exec permissions read+exec+existence */
|
||||
printf ("Starting os_stdlib_access_028\n");
|
||||
os_res = os_access("read_exec" OS_OS_EXESUFFIX, OS_ROK|OS_XOK|OS_FOK);
|
||||
CU_ASSERT (os_res == os_resultSuccess);
|
||||
#endif /* VXWORKS */
|
||||
|
||||
printf ("Ending stdlib_os_access\n");
|
||||
}
|
||||
|
||||
CU_Test(os_stdlib, vsnprintf)
|
||||
{
|
||||
printf ("Starting os_stdlib_vsnprintf_001\n");
|
||||
|
@ -694,27 +186,6 @@ CU_Test(os_stdlib, index)
|
|||
printf ("Ending os_stdlib_index\n");
|
||||
}
|
||||
|
||||
CU_Test(os_stdlib, flockfile)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
os_osInit();
|
||||
|
||||
/* Check writing in a FILE from multiple threads without using os_flockfile. */
|
||||
printf ("Starting os_stdlib_flockfile_001\n");
|
||||
result = doFlockfileTest(false);
|
||||
CU_ASSERT (result);
|
||||
|
||||
/* Check writing in a FILE from multiple threads using os_flockfile in the first thread. */
|
||||
printf ("Starting os_stdlib_flockfile_002\n");
|
||||
result = doFlockfileTest(true);
|
||||
CU_ASSERT (result);
|
||||
|
||||
printf ("Ending os_stdlib_flockfile\n");
|
||||
|
||||
os_osExit();
|
||||
}
|
||||
|
||||
CU_Test(os_stdlib, getopt)
|
||||
{
|
||||
int c = 0;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue