From 7dabb65d28e0174a6814d706095692f57ab9a635 Mon Sep 17 00:00:00 2001 From: codebase7 Date: Sat, 16 May 2015 02:38:45 -0400 Subject: [PATCH 001/325] Add Fatal Error Handler, rewrite Error Handler as. This commit adds a Fatal Error Notification Subsystem implementation and rewrites the pre-existing error handler code to be C code with C++ bindings. Do note that the transition to C code means that an API change cannot be avoided. Although attempts have been made to make the transition as easy as possible. Also the error table API version numbers have been updated. In addition to adding an API call to check what those version numbers are. --- CMakeLists.txt | 2 + src/Common/Src/Error_Handler/CMakeLists.txt | 59 ++- .../Src/Error_Handler/Common_Error_Handler.c | 370 ++++++++++++++++++ .../Error_Handler/Common_Error_Handler.cpp | 136 ------- .../Src/Error_Handler/Common_Error_Handler.h | 226 ++++++++++- .../Common_Error_Handler_CPP_Bindings.cpp | 118 ++++++ .../Common_Error_Handler_Internal.h | 12 +- .../Common_Error_Handler_Structures.c | 148 +++++++ .../Common_Error_Handler_Structures.h | 247 +++++++----- ..._Error_Handler_Structures_CPP_Bindings.cpp | 41 ++ src/Common/Src/Error_Handler/Error_Struct.h | 25 +- ...le.cpp => Posix_Error_Translation_Table.c} | 37 +- .../Posix_Error_Translation_Table.h | 162 ++++++-- ...x_Error_Translation_Table_CPP_Bindings.cpp | 45 +++ 14 files changed, 1302 insertions(+), 326 deletions(-) create mode 100644 src/Common/Src/Error_Handler/Common_Error_Handler.c delete mode 100644 src/Common/Src/Error_Handler/Common_Error_Handler.cpp create mode 100644 src/Common/Src/Error_Handler/Common_Error_Handler_CPP_Bindings.cpp create mode 100644 src/Common/Src/Error_Handler/Common_Error_Handler_Structures.c create mode 100644 src/Common/Src/Error_Handler/Common_Error_Handler_Structures_CPP_Bindings.cpp rename src/Common/Src/Error_Handler/{Posix_Error_Translation_Table.cpp => Posix_Error_Translation_Table.c} (60%) create mode 100644 src/Common/Src/Error_Handler/Posix_Error_Translation_Table_CPP_Bindings.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index e083325..7b86078 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,6 +20,8 @@ endif() # Option Defaults. option (BUILD_DYNAMIC_LIBRARY_SUBSYSTEM "Whether or not to build the Dynamic Library Subsystem. (Defaults to yes.)" ON) +option (BUILD_COMMON_ERROR_HANDLER "Whether or not to build the Common Error Handler. (Defaults to yes.)" ON) +option (BUILD_FATAL_ERROR_NOTIFY_SUPPORT "Whether or not to build the Common Error Handler's fatal error notification support. (Defaults to yes.)" ON) option (BUILD_INTERNAL_MUTEX_SUPPORT "Whether or not to build the internal mutex support library. (Defaults to yes.)" ON) option (BUILD_INTERNAL_MUTEX_THREAD_SUBSYS_WRAPPER "Whether or not the Threading Subsystem library will have Internal Mutex Support built in. (Defaults to yes, but is disabled currently due to changes to Thread_Utils that have not been commited yet.)" OFF) option (BUILD_INTERNAL_MUTEX_THREAD_SUBSYS_WRAPPER_PLUGIN "Whether or not to build the Threading Subsystem plugin for Internal Mutex Support. (Defaults to yes, but is disabled currently due to changes to Thread_Utils that have not been commited yet.)" OFF) diff --git a/src/Common/Src/Error_Handler/CMakeLists.txt b/src/Common/Src/Error_Handler/CMakeLists.txt index 44119e0..ed2b7e5 100644 --- a/src/Common/Src/Error_Handler/CMakeLists.txt +++ b/src/Common/Src/Error_Handler/CMakeLists.txt @@ -2,8 +2,59 @@ set(LIBRARY_OUTPUT_PATH ${L_OUTPUT_DIR}) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${O_OUTPUT_DIR}) -# Create the error handler. -set (COMMON_ERROR_HANDLER_INCLUDES Common_Error_Handler.cpp -Posix_Error_Translation_Table.cpp) +# Build the error handler if needed. +if (BUILD_COMMON_ERROR_HANDLER) + # Check for internal mutex support as the error handler uses it. + if (BUILD_FATAL_ERROR_NOTIFY_SUPPORT) + if (BUILD_INTERNAL_MUTEX_SUPPORT) + # Enable the needed flags. + set (COMMON_ERROR_HANDLER_DEFINES MSYS_BUILD_FATAL_ERROR_SUPPORT) -add_library(Common_Error_Handler_Multiverse_Engine SHARED ${COMMON_ERROR_HANDLER_INCLUDES}) + # Define the link libraries. + set(COMMON_ERROR_HANDLER_LINK_LIBS Common_Mutexes_Multiverse_Engine) + else(BUILD_INTERNAL_MUTEX_SUPPORT) + # No internal mutex support, so skip building the error handler's fatal error notification support. + message(SEND_ERROR "ERROR: Internal mutex support is disabled, and is REQUIRED to build the Common Error Handler's fatal error notification support. Skipping.") + endif(BUILD_INTERNAL_MUTEX_SUPPORT) + endif (BUILD_FATAL_ERROR_NOTIFY_SUPPORT) + + # Create the error handler. (Nasty hack to avoid a warning from GCC about invalid -std:gnu99 flag below....) + set (COMMON_ERROR_HANDLER_C_INCLUDES Common_Error_Handler.c + Posix_Error_Translation_Table.c + ) + set (COMMON_ERROR_HANDLER_CXX_INCLUDES Common_Error_Handler_Structures_CPP_Bindings.cpp + Common_Error_Handler_CPP_Bindings.cpp + Posix_Error_Translation_Table_CPP_Bindings.cpp + ) + + # Because we broke up the object code build from the shared library linking, we need to break up the flags and arguments too. + set (COMMON_ERROR_HANDLER_COMPILER_FLAGS -fPIC) + set (COMMON_ERROR_HANDLER_C_FLAGS ${COMMON_ERROR_HANDLER_COMPILER_FLAGS}) + set (COMMON_ERROR_HANDLER_CXX_FLAGS ${COMMON_ERROR_HANDLER_COMPILER_FLAGS}) + set (COMMON_ERROR_HANDLER_LINK_FLAGS -fPIC) + + # Check for gcc and enable gnu99 extensions if needed. + if (${CMAKE_COMPILER_IS_GNUCC}) + message (STATUS "GCC compiler detected, enabling gnu99 extensions for Common Error Handler.") + set (COMMON_ERROR_HANDLER_C_FLAGS ${COMMON_ERROR_HANDLER_C_FLAGS} -std=gnu99) + endif(${CMAKE_COMPILER_IS_GNUCC}) + + # First add the static C object library... + add_library(Common_Error_Handler_Multiverse_Engine_C OBJECT ${COMMON_ERROR_HANDLER_C_INCLUDES}) + set_property(TARGET Common_Error_Handler_Multiverse_Engine_C APPEND PROPERTY COMPILE_DEFINITIONS ${COMMON_ERROR_HANDLER_DEFINES}) + target_compile_options (Common_Error_Handler_Multiverse_Engine_C BEFORE PRIVATE ${COMMON_ERROR_HANDLER_C_FLAGS}) # Allows us to put the args to the compiler in the correct order. + + # Now add the C++ Bindings object library. + add_library(Common_Error_Handler_Multiverse_Engine_CXX OBJECT ${COMMON_ERROR_HANDLER_CXX_INCLUDES}) + set_property(TARGET Common_Error_Handler_Multiverse_Engine_CXX APPEND PROPERTY COMPILE_DEFINITIONS ${COMMON_ERROR_HANDLER_DEFINES}) + target_compile_options (Common_Error_Handler_Multiverse_Engine_CXX BEFORE PRIVATE ${COMMON_ERROR_HANDLER_CXX_FLAGS}) # Allows us to put the args to the compiler in the correct order. + + # Now the final shared library. (What we really want.) + add_library(Common_Error_Handler_Multiverse_Engine SHARED $ + $ + ) + target_link_libraries(Common_Error_Handler_Multiverse_Engine ${COMMON_ERROR_HANDLER_LINK_LIBS}) + set_property(TARGET Common_Error_Handler_Multiverse_Engine APPEND PROPERTY COMPILE_DEFINITIONS ${COMMON_ERROR_HANDLER_DEFINES}) + set_property(TARGET Common_Error_Handler_Multiverse_Engine APPEND PROPERTY LINK_FLAGS ${COMMON_ERROR_HANDLER_LINK_FLAGS}) + +endif(BUILD_COMMON_ERROR_HANDLER) diff --git a/src/Common/Src/Error_Handler/Common_Error_Handler.c b/src/Common/Src/Error_Handler/Common_Error_Handler.c new file mode 100644 index 0000000..eb462fe --- /dev/null +++ b/src/Common/Src/Error_Handler/Common_Error_Handler.c @@ -0,0 +1,370 @@ +/*! + Multiverse Engine Project 23/6/2014 Common Common_Error_Handler.c + + Copyright (C) 2014 Multiverse Engine Project + + This program is free software; + you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this program; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Official source repository and project information can be found at + https://github.com/codebase7/mengine +*/ + +// Internal includes. +#include "Common_Error_Handler.h" // Main header. +#include "Common_Error_Handler_Internal.h" // Private internal header that defines the structure used for error logging. + +// Only include the mutex header if needed by the fatal error handler. +#ifdef MSYS_BUILD_FATAL_ERROR_SUPPORT +#ifdef __win32__ +#include "..\Mutexes\MSYS_Mutexes.h" // Internal mutex support. +#else +#include "../Mutexes/MSYS_Mutexes.h" // Internal mutex support. +#endif // __win32__ +#endif // MSYS_BUILD_FATAL_ERROR_SUPPORT + +// Enable C linkage if needed. +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +/*! + * static int Common_commonLastErrorCode + * + * Contains the last error code encountered by a Common namespace function. + * + * Note: Calling Common_GetErrorMessage() or Common_GetErrorTableSize() + * will NOT clear this variable. + * Calling any other Common namespace function WILL clear this variable. + */ +static int Common_commonLastErrorCode = COMMON_ERROR_SUCCESS; + +void Common_Set_Error_Log_Level(const unsigned int logLevel) +{ + // Set the log level. + commonErrorLoggingData.errorLogLevel = logLevel; + + // Exit function. + return; +} + +unsigned int Common_Get_Error_Log_Level() +{ + // Return the current log level. + return commonErrorLoggingData.errorLogLevel; +} + +void Common_Register_Error_Log_Callback(void (*loggingFunction)(const unsigned int logLevel, const char * errorMsg)) +{ + // Check and see if the pointer is NULL. + if (loggingFunction == NULL) + { + // Set the log level to ERROR_DISABLE. + commonErrorLoggingData.errorLogLevel = ERROR_DISABLE; + commonErrorLoggingData.loggingFunct = NULL; + } + else + { + // Set the pointer. + commonErrorLoggingData.loggingFunct = loggingFunction; + } + + // Exit function. + return; +} + +// Build the Fatal Error Handler if needed. +#ifdef MSYS_BUILD_FATAL_ERROR_SUPPORT +/*! + * static unsigned int registeredFatalErrorCallbackFunctionsSize + * + * This unsigned int is used to remember the allocated size of the registeredFatalErrorCallbackFunctions array. + */ +static unsigned int registeredFatalErrorCallbackFunctionsSize = 0; + +/* + * static Common_pErrorCallBackFunction * registeredFatalErrorCallbackFunctions + * + * This pointer to an array contains the callback functions (registered with Common::Register_Fatal_Error_Callback()) + * used to notify the engine's subsystems and the application that a fatal error has occured and the engine's + * process is about to be terminated by the host system. + */ +static Common_pErrorCallBackFunction * registeredFatalErrorCallbackFunctions = NULL; + +/*! + * static MSYS_Mutex * fatalErrorHandlerMutex + * + * This pointer is to an MSYS_Mutex object that is used to control access to the registered fatal error handler + * function pointer list and it's size value. + */ +static MSYS_Mutex * fatalErrorHandlerMutex = NULL; + +bool Common_Register_Fatal_Error_Callback(const Common_pErrorCallBackFunction fatalErrorNotifyFunction) +{ + // Init vars. + bool ret = false; // The result of this function. + size_t previousErrorListSize = registeredFatalErrorCallbackFunctionsSize; // The size of the previous error list. + size_t newErrorListSize = 0; // The size of the new error list we are creating. + Common_pErrorCallBackFunction * previousErrorList = registeredFatalErrorCallbackFunctions; // The previous error list. + Common_pErrorCallBackFunction * newErrorList = NULL; // The new error list we are creating. + MSYS_Mutex * retFromLockMutex = NULL; // The result from the call to MSYS_Lock_Mutex(). + + // Check for a valid mutex. + if (fatalErrorHandlerMutex == NULL) + { + // Allocate the mutex. + fatalErrorHandlerMutex = MSYS_Create_Mutex(); + } + + // Lock the error handler mutex. + retFromLockMutex = MSYS_Lock_Mutex(fatalErrorHandlerMutex); + if ((retFromLockMutex != NULL) && (retFromLockMutex == fatalErrorHandlerMutex)) + { + // Check for valid function pointer. + if (fatalErrorNotifyFunction != NULL) + { + // Check for a error function list. + if ((previousErrorList != NULL) && (previousErrorListSize > 0)) + { + // Re-allocate the error list. + newErrorList = (Common_pErrorCallBackFunction *)malloc((sizeof(Common_pErrorCallBackFunction) * (previousErrorListSize + 1))); + if (newErrorList != NULL) + { + // Update the size info. + newErrorListSize = (previousErrorListSize + 1); + + // Copy the data. + for (size_t x = 0; x < previousErrorListSize; x++) + { + newErrorList[x] = previousErrorList[x]; + } + } + } + else + { + // Allocate the error list. + newErrorList = (Common_pErrorCallBackFunction *)malloc(sizeof(Common_pErrorCallBackFunction)); + if (newErrorList != NULL) + { + // Update the size info. + newErrorListSize = 1; + } + } + + // Check for a valid list. + if ((previousErrorListSize + 1) == newErrorListSize) + { + // Register the function. + newErrorList[(previousErrorListSize)] = fatalErrorNotifyFunction; + + // Copy the new list pointer, and size info. + registeredFatalErrorCallbackFunctions = newErrorList; + registeredFatalErrorCallbackFunctionsSize = newErrorListSize; + + // Check and see if we need to deallocate the previousErrorList. + if ((previousErrorList != NULL) && (previousErrorList != newErrorList) && (previousErrorListSize > 0)) + { + // Null out the old pointer list. + for (size_t x = 0; x < previousErrorListSize; x++) + { + previousErrorList[x] = NULL; + } + + // Deallocate the old array. + free(previousErrorList); + previousErrorList = NULL; + previousErrorListSize = 0; + } + + // We are done. + ret = true; + } + } + + // Release the error handler mutex. + MSYS_Unlock_Mutex(fatalErrorHandlerMutex); + } + + // Return the result. + return ret; +} + +bool Common_Unregister_Fatal_Error_Callback(const Common_pErrorCallBackFunction fatalErrorNotifyFunction) +{ + // Init vars. + bool ret = false; // The result of this function. + size_t previousErrorListSize = registeredFatalErrorCallbackFunctionsSize; // The size of the previous error list. + size_t newErrorListSize = 0; // The size of the new error list we are creating. + Common_pErrorCallBackFunction * previousErrorList = registeredFatalErrorCallbackFunctions; // The previous error list. + Common_pErrorCallBackFunction * newErrorList = NULL; // The new error list we are creating. + MSYS_Mutex * retFromLockMutex = NULL; // The result from the call to MSYS_Lock_Mutex(). + + // Lock the error handler mutex. + retFromLockMutex = MSYS_Lock_Mutex(fatalErrorHandlerMutex); + if ((retFromLockMutex != NULL) && (retFromLockMutex == fatalErrorHandlerMutex)) + { + // Check for valid function pointer. + if (fatalErrorNotifyFunction != NULL) + { + // Check for a error function list. + if ((previousErrorList != NULL) && (previousErrorListSize > 0)) + { + // Check the existing list for that function. + for (size_t x = 0; ((newErrorList == NULL) && (x < previousErrorListSize)); x++) + { + // Check for the correct function, to see if the function was registered previously. + if (previousErrorList[x] == fatalErrorNotifyFunction) + { + // Found the function, so re-allocate the error list so we can remove it. + newErrorList = (Common_pErrorCallBackFunction *)malloc((sizeof(Common_pErrorCallBackFunction) * (previousErrorListSize - 1))); + if (newErrorList != NULL) + { + // Update the size info. + newErrorListSize = (previousErrorListSize - 1); + } + } + } + + // Only continue if the list was reallocated due to us finding the function to remove. + if ((newErrorList != NULL) && (newErrorListSize == (previousErrorListSize - 1))) + { + // Copy the data. + for (size_t x = 0, y = 0; ((x < previousErrorListSize) && (y < newErrorListSize)); x++) + { + // Make sure we don't copy the pointer we are removing. + if (previousErrorList[x] != fatalErrorNotifyFunction) + { + // Copy the pointer, and increment y. (Yes, y can be different than x, because it will not contain every pointer.) + newErrorList[y] = previousErrorList[x]; + y++; + } + } + + // Now that the data is copied, copy the pointers. + registeredFatalErrorCallbackFunctions = newErrorList; + registeredFatalErrorCallbackFunctionsSize = newErrorListSize; + + // Deallocate the old list. + if ((previousErrorList != NULL) && (previousErrorList != newErrorList) && (previousErrorListSize > 0)) + { + // Null out the old pointer list. + for (size_t x = 0; x < previousErrorListSize; x++) + { + previousErrorList[x] = NULL; + } + + free(previousErrorList); + previousErrorList = NULL; + previousErrorListSize = 0; + } + + // Done. + ret = true; + } + } + } + + // Release the error handler mutex. + MSYS_Unlock_Mutex(fatalErrorHandlerMutex); + } + + // Return the result. + return ret; +} + +void Common_Fatal_Error_Notify() +{ + // Init vars. + MSYS_Mutex * retFromLockMutex = NULL; // The result from the call to MSYS_Lock_Mutex(). + + // Lock the error handler mutex. + retFromLockMutex = MSYS_Lock_Mutex(fatalErrorHandlerMutex); + if ((retFromLockMutex != NULL) && (retFromLockMutex == fatalErrorHandlerMutex)) + { + // Check for registered fatal error callbacks. + if (registeredFatalErrorCallbackFunctionsSize > 0) + { + // Begin vector iteration loop. + for (size_t x = 0; (x < registeredFatalErrorCallbackFunctionsSize); x++) + { + // Trigger each function. + if (registeredFatalErrorCallbackFunctions[x] != NULL) + { + registeredFatalErrorCallbackFunctions[x](); + } + } + } + + // Release the error handler mutex. + MSYS_Unlock_Mutex(fatalErrorHandlerMutex); + } + + // Exit function. + return; +} + +#endif // MSYS_BUILD_FATAL_ERROR_SUPPORT + +void COMMON_LOG_ERROR(const unsigned int loggingLevel, const char * errorMsg) +{ + /* + * Only do something if the log is enabled, + * the error is at or below our current log level, + * and the logging callback function is defined. + * + * Note: The lower the log level, the higher severity of the error. + */ + if ((commonErrorLoggingData.errorLogLevel != ERROR_DISABLE) && + (commonErrorLoggingData.loggingFunct != NULL) && + (loggingLevel <= commonErrorLoggingData.errorLogLevel)) + { + // Call the callback. (Hope it returns....) + commonErrorLoggingData.loggingFunct(loggingLevel, errorMsg); + } + + // Exit function. + return; +} + +void COMMON_LOG_CRITICAL(const char * errorMsg) +{ + COMMON_LOG_ERROR(ERROR_CRITICAL, errorMsg); + return; +} + +void COMMON_LOG_WARNING(const char * errorMsg) +{ + COMMON_LOG_ERROR(ERROR_WARNING, errorMsg); + return; +} + +void COMMON_LOG_INFO(const char * errorMsg) +{ + COMMON_LOG_ERROR(ERROR_INFO, errorMsg); + return; +} + +void COMMON_LOG_DEBUG(const char * errorMsg) +{ + COMMON_LOG_ERROR(ERROR_DEBUG, errorMsg); + return; +} + +void COMMON_LOG_VERBOSE(const char * errorMsg) +{ + COMMON_LOG_ERROR(ERROR_VERBOSE, errorMsg); + return; +} + +// End C Linkage if needed. +#ifdef __cplusplus +} +#endif // __cplusplus diff --git a/src/Common/Src/Error_Handler/Common_Error_Handler.cpp b/src/Common/Src/Error_Handler/Common_Error_Handler.cpp deleted file mode 100644 index 1ea3719..0000000 --- a/src/Common/Src/Error_Handler/Common_Error_Handler.cpp +++ /dev/null @@ -1,136 +0,0 @@ -/*! - Multiverse Engine Project 23/6/2014 Common Common_Error_Handler.cpp - - Copyright (C) 2014 Multiverse Engine Project - - This program is free software; - you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; - either version 2 of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with this program; - if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - Official source repository and project information can be found at - https://github.com/codebase7/mengine -*/ - -#include "Common_Error_Handler.h" // Main header. -#include "Common_Error_Handler_Internal.h" // Private internal header that defines the structure used for error logging. - -const unsigned int Common::Get_Error_Table_Size() -{ - return (sizeof(Common::commonErrorTable) / sizeof(Common_Error_Object)); -} - -const char * Common::Get_Error_Message(const int & errorCode) -{ - // Init vars. - const char * result = NULL; // Result of this function. - const size_t errorTableSize = Common::Get_Error_Table_Size(); // Size of the Common error lookup table. - - // Begin lookup loop. - for (size_t x = 0; ((x < errorTableSize) && (result == NULL)); x++) - { - // Check for the correct error code. - if (Common::commonErrorTable[x].errorCode == errorCode) - { - // Found the correct error code. - result = Common::commonErrorTable[x].error; - } - } - - // If we still can't find the error message to return, use COMMON_UNKNOWN_ERROR - if (result == NULL) - { - result = Common::UNKNOWN_ERROR_MSG; - } - - // Return the result. - return result; -} - -void Common::Set_Error_Log_Level(const unsigned int & logLevel) -{ - // Set the log level. - commonErrorLoggingData.errorLogLevel = logLevel; - - // Exit function. - return; -} - -unsigned int Common::Get_Error_Log_Level() -{ - // Return the current log level. - return commonErrorLoggingData.errorLogLevel; -} - -void Common::Register_Error_Log_Callback(void (*loggingFunction)(const unsigned int logLevel, const char * errorMsg)) -{ - // Check and see if the pointer is NULL. - if (loggingFunction == NULL) - { - // Set the log level to ERROR_DISABLE. - commonErrorLoggingData.errorLogLevel = ERROR_DISABLE; - } - - // Set the pointer. - commonErrorLoggingData.loggingFunct = loggingFunction; - - // Exit function. - return; -} - -void COMMON_LOG_ERROR(const unsigned int loggingLevel, const char * errorMsg) -{ - /* - * Only do something if the log is enabled, - * the error is at or below our current log level, - * and the logging callback function is defined. - * - * Note: The lower the log level, the higher severity of the error. - */ - if ((commonErrorLoggingData.errorLogLevel != ERROR_DISABLE) && - (commonErrorLoggingData.loggingFunct != NULL) && - (loggingLevel <= commonErrorLoggingData.errorLogLevel)) - { - // Call the callback. (Hope it returns....) - commonErrorLoggingData.loggingFunct(loggingLevel, errorMsg); - } - - // Exit function. - return; -} - -void COMMON_LOG_CRITICAL(const char * errorMsg) -{ - COMMON_LOG_ERROR(ERROR_CRITICAL, errorMsg); - return; -} - -void COMMON_LOG_WARNING(const char * errorMsg) -{ - COMMON_LOG_ERROR(ERROR_WARNING, errorMsg); - return; -} - -void COMMON_LOG_INFO(const char * errorMsg) -{ - COMMON_LOG_ERROR(ERROR_INFO, errorMsg); - return; -} - -void COMMON_LOG_DEBUG(const char * errorMsg) -{ - COMMON_LOG_ERROR(ERROR_DEBUG, errorMsg); - return; -} - -void COMMON_LOG_VERBOSE(const char * errorMsg) -{ - COMMON_LOG_ERROR(ERROR_VERBOSE, errorMsg); - return; -} diff --git a/src/Common/Src/Error_Handler/Common_Error_Handler.h b/src/Common/Src/Error_Handler/Common_Error_Handler.h index 9292da7..cefe259 100644 --- a/src/Common/Src/Error_Handler/Common_Error_Handler.h +++ b/src/Common/Src/Error_Handler/Common_Error_Handler.h @@ -24,6 +24,9 @@ // External includes. #include // Defines NULL. +#ifndef __cplusplus +#include // Defines bool data type. (For C compilers.) +#endif // __cplusplus // Project includes. #ifdef __win32 // Needed for different path seperator in Windows. @@ -35,30 +38,137 @@ #include "Common_Error_Handler_Structures.h" // Defines the error codes, error lookup table error lookup table version number, and Common::commonLastErrorCode. #include "Posix_Error_Translation_Table.h" // Defines the POSIX errno to Common namespace error translation table and functions. +// Enable C linkage if needed. +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +// Define the C bindings for the error handler. + +/*! + * void Common_Set_Error_Log_Level(const unsigned int & logLevel) + * + * Sets the error logging level for the Common namespace functions. + * + * By default it sets the error logging level to ERROR_DISABLE. + * (Disables all logging. See Core/Src/Panic.h for a list of + * valid logging levels.) + */ +void Common_Set_Error_Log_Level(const unsigned int logLevel); + +/*! + * unsigned int Common_Get_Error_Log_Level() + * + * Returns the current error logging level for the Common namespace functions. + * + * See Core/Src/Panic.h for a list of valid logging levels. + */ +unsigned int Common_Get_Error_Log_Level(); + +/*! + * void Common_Register_Error_Log_Callback(void (*loggingFunction)(const unsigned int logLevel, const char * errorMsg)) + * + * WARNING: The callback function MUST return control back to + * the caller, as the caller will be blocked until the callback + * function returns. + * + * Sets the logging function to call when an error is generated + * by a Common namespace function. + * + * For example, this function can be used to send the generated + * errors to the console in a multi-threaded enviroment. + * + * Passing a NULL pointer to this function (the default) will + * disable calling another function when an error is generated. + * In addition the logging level will be reset to ERROR_DISABLE. + */ +void Common_Register_Error_Log_Callback(void (*loggingFunction)(const unsigned int logLevel, const char * errorMsg)); +#ifdef MSYS_BUILD_FATAL_ERROR_SUPPORT + +/*! + * typedef void(*Common_pErrorCallBackFunction)(void) + * + * Defines the function pointer type for use as arguments by the Common fatal error handler functions. + */ +typedef void(*Common_pErrorCallBackFunction)(void); + +/*! + * bool Common_Register_Fatal_Error_Callback(const Common_pErrorCallBackFunction fatalErrorNotifyFunction) + * + * WARNING: The callback function MUST return control back to + * the caller, as the caller will be blocked until the callback + * function returns. This means any other registered callbacks + * will not be triggered, which may lead to data loss. The only exception + * to this is if the host system will kill the engine's process after a set + * amount of time. In this one specific instance, nothing can be done to + * prevent the host system from killing the engine. As such the function + * registered with this call should attempt to clean up and return as + * fast as possible. + * + * Registers a callback function for notification of an engine subsystem + * triggering the host system to kill the engine's process. + * + * Note: The registered callback is not guaranteed to be called at all prior to + * the engine process being terminated. (The host system reserves the right to + * kill the engine without warning it of the impending termination.) + * As such this should be considered an informal notification and not something + * to be relied on if data preservation / security or proper cleanup is required + * prior to engine shutdown. + * + * Returns true if the regisration completed successfully. + * Returns false otherwise. + */ +bool Common_Register_Fatal_Error_Callback(const Common_pErrorCallBackFunction fatalErrorNotifyFunction); + +/*! + * bool Common_Unregister_Fatal_Error_Callback(const Common_pErrorCallBackFunction fatalErrorNotifyFunction) + * + * Unregisters the given fatal error callback function from the list of fatal error + * callback functions to be triggered in the event of a fatal error being generated. + * + * (I.e. If unregistered, a given callback function will not be called if a fatal + * error occurs.) + * + * The callback function pointer given to this function must match a function pointer + * given to Common_Register_Fatal_Error_Callback() (Or Common::Register_Fatal_Error_Callback()) previously, + * otherwise this function will fail. + * + * Returns true if the unregisration completed successfully. + * Returns false otherwise. + */ +bool Common_Unregister_Fatal_Error_Callback(const Common_pErrorCallBackFunction fatalErrorNotifyFunction); + +/*! + * void Common_Fatal_Error_Notify() + * + * This function triggers the registered fatal error callback functions + * registered with Common_Register_Fatal_Error_Callback() (Or Common::Register_Fatal_Error_Callback()), + * in an attempt to notify all need to know sections of the engine, and application, that the engine is + * about to be terminated. + * + * When this function returns to it's caller, it is expected that the caller + * will terminate the engine's process if it does not happen automaticly. + * + * This function does not return any data to it's caller. + */ +void Common_Fatal_Error_Notify(); +#endif // MSYS_BUILD_FATAL_ERROR_SUPPORT + +// End C Linkage if needed. +#ifdef __cplusplus +} +#endif // __cplusplus + +// Define C++ Bindings. +#ifdef __cplusplus // Define namespaces. namespace Common { - /*! - * const unsigned int Common::Get_Error_Table_Size() - * - * Returns the size of the common error table. - */ - const unsigned int Get_Error_Table_Size(); - - /*! - * const char * Common::Get_Error_Message(const int & errorCode) - * - * This function takes the given error code and returns a pointer to a human - * readable string describing the meaning of the given error code. - * - * Returns a valid pointer if the given error code is in the common error table. - * Returns the message for Common::COMMON_UNKNOWN_ERROR otherwise. - */ - const char * Get_Error_Message(const int & errorCode); - /*! * void Common::Set_Error_Log_Level(const unsigned int & logLevel) - * + * + * (C++ Binding) + * * Sets the error logging level for the Common namespace functions. * * By default it sets the error logging level to ERROR_DISABLE. @@ -69,7 +179,9 @@ namespace Common /*! * unsigned int Common::Get_Error_Log_Level() - * + * + * (C++ Binding) + * * Returns the current error logging level for the Common namespace functions. * * See Core/Src/Panic.h for a list of valid logging levels. @@ -78,7 +190,9 @@ namespace Common /*! * void Common::Register_Error_Log_Callback(void (*loggingFunction)(const unsigned int logLevel, const char * errorMsg)) - * + * + * (C++ Binding) + * * WARNING: The callback function MUST return control back to * the caller, as the caller will be blocked until the callback * function returns. @@ -94,7 +208,77 @@ namespace Common * In addition the logging level will be reset to ERROR_DISABLE. */ void Register_Error_Log_Callback(void (*loggingFunction)(const unsigned int logLevel, const char * errorMsg) = NULL); + +#ifdef MSYS_BUILD_FATAL_ERROR_SUPPORT + /*! + * bool Common::Register_Fatal_Error_Callback(const Common_pErrorCallBackFunction fatalErrorNotifyFunction) + * + * (C++ Binding) + * + * WARNING: The callback function MUST return control back to + * the caller, as the caller will be blocked until the callback + * function returns. This means any other registered callbacks + * will not be triggered, which may lead to data loss. The only exception + * to this is if the host system will kill the engine's process after a set + * amount of time. In this one specific instance, nothing can be done to + * prevent the host system from killing the engine. As such the function + * registered with this call should attempt to clean up and return as + * fast as possible. + * + * Registers a callback function for notification of an engine subsystem + * triggering the host system to kill the engine's process. + * + * Note: The registered callback is not guaranteed to be called at all prior to + * the engine process being terminated. (The host system reserves the right to + * kill the engine without warning it of the impending termination.) + * As such this should be considered an informal notification and not something + * to be relied on if data preservation / security or proper cleanup is required + * prior to engine shutdown. + * + * Returns true if the regisration completed successfully. + * Returns false otherwise. + */ + bool Register_Fatal_Error_Callback(const Common_pErrorCallBackFunction fatalErrorNotifyFunction); + + /*! + * bool Common::Unregister_Fatal_Error_Callback(const Common_pErrorCallBackFunction fatalErrorNotifyFunction) + * + * (C++ Binding) + * + * Unregisters the given fatal error callback function from the list of fatal error + * callback functions to be triggered in the event of a fatal error being generated. + * + * (I.e. If unregistered, a given callback function will not be called if a fatal + * error occurs.) + * + * The callback function pointer given to this function must match a function pointer + * given to Common_Register_Fatal_Error_Callback() (Or Common::Register_Fatal_Error_Callback()) previously, + * otherwise this function will fail. + * + * Returns true if the unregisration completed successfully. + * Returns false otherwise. + */ + bool Unregister_Fatal_Error_Callback(const Common_pErrorCallBackFunction fatalErrorNotifyFunction); + + /*! + * void Common::Fatal_Error_Notify() + * + * (C++ Binding) + * + * This function triggers the registered fatal error callback functions + * registered with Or Common_Register_Fatal_Error_Callback() (Common::Register_Fatal_Error_Callback()), + * in an attempt to notify all need to know sections of the engine, and application, that the engine is + * about to be terminated. + * + * When this function returns to it's caller, it is expected that the caller + * will terminate the engine's process if it does not happen automaticly. + * + * This function does not return any data to it's caller. + */ + void Fatal_Error_Notify(); +#endif // MSYS_BUILD_FATAL_ERROR_SUPPORT }; +#endif // __cplusplus #endif // COMMON_ERROR_HANDLER_H diff --git a/src/Common/Src/Error_Handler/Common_Error_Handler_CPP_Bindings.cpp b/src/Common/Src/Error_Handler/Common_Error_Handler_CPP_Bindings.cpp new file mode 100644 index 0000000..f880379 --- /dev/null +++ b/src/Common/Src/Error_Handler/Common_Error_Handler_CPP_Bindings.cpp @@ -0,0 +1,118 @@ +/*! + Multiverse Engine Project 13/5/2015 Common Common_Error_Handler_CPP_Bindings.cpp + + Copyright (C) 2014 Multiverse Engine Project + + This program is free software; + you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this program; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Official source repository and project information can be found at + https://github.com/codebase7/mengine +*/ + +// Define C++ Bindings. +#ifdef __cplusplus + +// Internal includes. +#include "Common_Error_Handler.h" // Main header. +#include "Common_Error_Handler_Internal.h" // Private internal header that defines the structure used for error logging. + +// External includes. +#include + +void Common::Set_Error_Log_Level(const unsigned int & logLevel) +{ + Common_Set_Error_Log_Level(logLevel); +} + +unsigned int Common::Get_Error_Log_Level() +{ + return Common_Get_Error_Log_Level(); +} + +void Common::Register_Error_Log_Callback(void (*loggingFunction)(const unsigned int logLevel, const char * errorMsg)) +{ + Common_Register_Error_Log_Callback(loggingFunction); +} + +// Build the Fatal Error Handler if needed. +#ifdef MSYS_BUILD_FATAL_ERROR_SUPPORT + +bool Common::Register_Fatal_Error_Callback(const Common_pErrorCallBackFunction fatalErrorNotifyFunction) +{ + // Init vars. + bool ret = false; // The result of this function. + + // Begin try block. + try { + // Call real function. + ret = Common_Register_Fatal_Error_Callback(fatalErrorNotifyFunction); + } + catch (...) + { + /* + * Great probably a memory allocation error, if so, we don't do anything as the original list is not modifyed + * unless the operations succeed. + * + * If not, well we just destroyed the list of functions we needed to call when a fatal error happened, + * so maybe we should call terminate() here? + */ + ret = false; + } + + // Return the result. + return ret; +} + +bool Common::Unregister_Fatal_Error_Callback(const Common_pErrorCallBackFunction fatalErrorNotifyFunction) +{ + // Init vars. + bool ret = false; // The result of this function. + + // Begin try block. + try { + // Call real function. + ret = Common_Unregister_Fatal_Error_Callback(fatalErrorNotifyFunction); + } + catch (...) + { + /* + * Great probably a memory allocation error, if so, we don't do anything as the original list is not modifyed + * unless the operations succeed. + * + * If not, well we just destroyed the list of functions we needed to call when a fatal error happened, + * so maybe we should call terminate() here? + */ + ret = false; + } + + // Return the result. + return ret; +} + +void Common::Fatal_Error_Notify() +{ + // Begin try block. + try { + // Call real function. + Common_Fatal_Error_Notify(); + } + catch (std::exception & ex) + { + // Well, not much to do here, we are terminating anyway. + COMMON_LOG_CRITICAL("Common::Fatal_Error_Notify(): Exception occured while notifying engine subsystems / application that a fatal error occured."); + } +} + +#endif // MSYS_BUILD_FATAL_ERROR_SUPPORT + +#endif // __cplusplus + diff --git a/src/Common/Src/Error_Handler/Common_Error_Handler_Internal.h b/src/Common/Src/Error_Handler/Common_Error_Handler_Internal.h index 1847783..a1db502 100644 --- a/src/Common/Src/Error_Handler/Common_Error_Handler_Internal.h +++ b/src/Common/Src/Error_Handler/Common_Error_Handler_Internal.h @@ -34,6 +34,11 @@ //#error "This header is for internal engine use only. It should not be linked against, as it is NOT a part of the public API." //#endif // COMMON_ERROR_HANDLER_H +// Enable C linkage if needed. +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + /* * struct CommonErrorLogData * @@ -57,7 +62,7 @@ struct CommonErrorLogData { * * The actual data structure that contains the error * logging data for the Common namespace functions. - * + * * Once again, DO NOT USE THIS STRUCTURE DIRECTLY! * This structure is NOT a part of the public API, and * is subject to change at anytime. @@ -137,6 +142,11 @@ void COMMON_LOG_DEBUG(const char * errorMsg); */ void COMMON_LOG_VERBOSE(const char * errorMsg); +// End C Linkage if needed. +#ifdef __cplusplus +} +#endif // __cplusplus + #endif // COMMON_ERROR_HANDLER_INTERNAL_H // End of Common_Error_Handler_Internal.h diff --git a/src/Common/Src/Error_Handler/Common_Error_Handler_Structures.c b/src/Common/Src/Error_Handler/Common_Error_Handler_Structures.c new file mode 100644 index 0000000..0c682f4 --- /dev/null +++ b/src/Common/Src/Error_Handler/Common_Error_Handler_Structures.c @@ -0,0 +1,148 @@ +/*! + Multiverse Engine Project 16/5/2015 Common Common_Error_Handler_Structures.c + + Copyright (C) 2015 Multiverse Engine Project + + This program is free software; + you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this program; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Official source repository and project information can be found at + https://github.com/codebase7/mengine +*/ + +// Internal Includes. +#include "Common_Error_Handler.h" + +// Enable C linkage if needed. +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +/*! + * const char * COMMON_ERROR_UNKNOWN_ERROR_MSG + * + * This is the definition for the generic unknown error + * code. + * + * It is defined here to allow Common_Get_Error_Message() + * to reference it without needing to use another for loop + * to locate it's offset in the error message table. + */ +const char COMMON_ERROR_UNKNOWN_ERROR_MSG[] = COMMON_UNKNOWN_ERROR_MSG_DEF; + +/*! + * const Common_Error_Object Common_commonErrorTable[] + * + * This array contains all of the error codes that a Common namespace + * function may return, in addition to a human readable string describing + * the error code's meaning. (This is a work in progress, some error codes + * conflict with error codes in other functions, as such these are slowly + * being corrected.) + * + * The easiest way of fetching the human readable string from this table + * is to call Common::GetErrorMessage(). + * + * Do not reuse an existing error code. (If the error is generic then use a + * generic error code.) + * + * Do not change an existing error code. (This is to keep the API stable + * between revisions.) + */ +const Common_Error_Object Common_commonErrorTable[] = { + // Define the initilizers for the lookup table. + {COMMON_ERROR_UNKNOWN_ERROR, COMMON_ERROR_UNKNOWN_ERROR_MSG}, + {COMMON_ERROR_SYSTEM_SPECIFIC, "System specific error code. Check log."}, + {COMMON_ERROR_SUCCESS, "Success."}, + {COMMON_ERROR_INVALID_ARGUMENT, "Invalid argument."}, + {COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED, "Function not implemented."}, + {COMMON_ERROR_ACCESS_DENIED, "Access Denied."}, + {COMMON_ERROR_EXCEPTION_THROWN, "Execption thrown."}, + {COMMON_ERROR_INTERNAL_ERROR, "Internal error."}, + {COMMON_ERROR_IO_ERROR, "Input / Output error. (Normally this is a hardware issue.)"}, + {COMMON_ERROR_RANGE_ERROR, "Given range is invalid."}, + {COMMON_ERROR_MEMORY_ERROR, "Memory error (Could not allocate memory / Control loop out of bounds.)"}, + {COMMON_ERROR_INVALID_LIBRARY_ID, "Given LibraryID does not match a supported library or a loaded plugin."}, + {COMMON_ERROR_PEBKAC_INVALID_OPERATION_ORDER, "Caller is attempting to do something that requires another call / process to be completed first. (Check the order in which you are doing things.)"}, + {COMMON_ERROR_CANNOT_GET_SYSTEM_TIME, "Could not get the system's current time."}, + {COMMON_ERROR_SUBSYSTEM_OBJECT_NOT_INITED, "Given object has not been inited yet."}, + {COMMON_ERROR_SUBSYSTEM_OBJECT_ALREADY_INITED, "Given object has already been inited."}, + // Rendering Subsystem error codes. + {RENDERER_ERROR_UNABLE_TO_ALLOC_OI_BUF, "Could not allocate memory for overlay image buffer."}, + {RENDERER_ERROR_UNABLE_TO_ALLOC_TD_BUF, "Could not allocate memory for transparency data buffer."}, + {RENDERER_ERROR_MEM_BUF_ALLOC_EXCEPTION, "Exception thrown while attempting to allocate memory buffer(s)."}, + {RENDERER_ERROR_DUPE_OVERLAY_EXCEPTION, "Exception thrown while duplicating overlay, clearing dest overlay."}, + {RENDERER_ERROR_INVAL_OVERLAY_SELF_OVERWRITE, "Given overlays are the same. Cannot overwrite an overlay with itself."}, + {RENDERER_ERROR_TRANSPARENCY_DISABLED, "Transparency is disabled on given overlay."}, + // Threading Subsystem (Thread_Utils) error codes. + {THREAD_UTILS_ERROR_EXCEPTION_THROWN, "Exception thrown in threading subsystem."}, + {THREAD_UTILS_ERROR_PLUGIN_LOAD_FAILURE, "Unable to load plugin(s). Internal error."}, + {THREAD_UTILS_ERROR_THREAD_COULD_NOT_START, "Could not start new thread."}, + {THREAD_UTILS_ERROR_THREAD_COULD_NOT_DETACH, "Could not detach thread."}, + {THREAD_UTILS_ERROR_THREAD_COULD_NOT_JOIN, "Could not join thread."}, + {THREAD_UTILS_ERROR_MUTEX_ALREADY_LOCKED, "The given mutex is already locked."}, + {THREAD_UTILS_ERROR_CONDITION_WAIT_TIMEOUT_REACHED, "Given timeout period was exceeded while waiting for the condition variable to signal."}, + {THREAD_UTILS_ERROR_CONDITION_CANNOT_LOCK_MUTEX, "Could not lock internal mutex in condition variable object."}, + // FileUtills. + {FILEUTILLS_ERROR_EXISTANT, "The path exists."}, + {FILEUTILLS_ERROR_NON_EXISTANT, "The path (or a component of the path) does not exist."}, + {FILEUTILLS_ERROR_READ_ONLY, "The path is read only."}, + {FILEUTILLS_ERROR_PATH_LENGTH_INVALID, "The path's length is beyond the filesystem's maximum length."}, + {FILEUTILLS_ERROR_PATH_FILE_AS_DIRECTORY, "The path has a file in it that is being treated as a directory."}, + {FILEUTILLS_ERROR_PATH_IS_A_FILE, "Given path is a file."}, + {FILEUTILLS_ERROR_PATH_IS_A_DIRECTORY, "Given path is a directory."}, + {FILEUTILLS_ERROR_FILESYSTEM_FULL, "Given filesystem is full."}, + {FILEUTILLS_ERROR_FILESYSTEM_QUOTA_REACHED, "User's disk usage quota for the given filesystem has been reached."}, + {FILEUTILLS_ERROR_EMPTY_DIRECTORY, "The given path is an empty directory."}, + {FILEUTILLS_ERROR_NON_EMPTY_DIRECTORY, "The given path is a non-empty directory."}, + // UI Subsystem/ + {UI_SUBSYSTEM_ERROR_EXCEPTION_THROWN, "An exception was thrown in the UI Subsystem."}, + // TODO: Need to add the error codes from all common namespace functions. +}; + +const unsigned int Common_Get_Error_Table_API_Version() +{ + return COMMON_ERROR_TABLE_ABI_VER; +} + +const unsigned int Common_Get_Error_Table_Size() +{ + return (sizeof(Common_commonErrorTable) / sizeof(Common_Error_Object)); +} + +const char * Common_Get_Error_Message(const int errorCode) +{ + // Init vars. + const char * result = COMMON_ERROR_UNKNOWN_ERROR_MSG; // Result of this function. + const size_t errorTableSize = Common_Get_Error_Table_Size(); // Size of the Common error lookup table. + + // Check for COMMON_UNKNOWN_ERROR. + if (errorCode != COMMON_ERROR_UNKNOWN_ERROR) + { + // Begin lookup loop. + for (size_t x = 0; ((x < errorTableSize) && (result == COMMON_ERROR_UNKNOWN_ERROR_MSG)); x++) + { + // Check for the correct error code. + if (Common_commonErrorTable[x].errorCode == errorCode) + { + // Found the correct error code. + result = Common_commonErrorTable[x].error; + } + } + } + + // Return the result. + return result; +} + +// End C Linkage if needed. +#ifdef __cplusplus +} +#endif // __cplusplus diff --git a/src/Common/Src/Error_Handler/Common_Error_Handler_Structures.h b/src/Common/Src/Error_Handler/Common_Error_Handler_Structures.h index 24fefa6..ad6bf04 100644 --- a/src/Common/Src/Error_Handler/Common_Error_Handler_Structures.h +++ b/src/Common/Src/Error_Handler/Common_Error_Handler_Structures.h @@ -1,128 +1,161 @@ +/*! + Multiverse Engine Project 04/7/2014 Common Common_Error_Handler_Structures.h + Copyright (C) 2014 Multiverse Engine Project + This program is free software; + you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this program; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Official source repository and project information can be found at + https://github.com/codebase7/mengine +*/ + +// Include guard. +#ifndef COMMON_ERROR_ERROR_HANDLER_STRUCTURES_H +#define COMMON_ERROR_ERROR_HANDLER_STRUCTURES_H + +// Internal includes. #include "Error_Struct.h" // Structure used to create error lookup table. -namespace Common { - // Common namespace error code definitions. - // Error code table ABI version. - const unsigned int COMMON_ERROR_ABI_VER = 1; // Increment this if you alter the table. +// Define the Common unknown error message. (It has to be replicated in two places, once for the C code and once for the C++ bindings.) +#define COMMON_UNKNOWN_ERROR_MSG_DEF "Unknown error code." - /*! - * const static char * Common::UNKNOWN_ERROR_MSG - * - * This is the definition for the generic unknown error - * code. - * - * It is defined here to allow Common::Get_Error_Message() - * to reference it without needing to use another for loop - * to locate it's offset in the error message table. - */ - const static char * UNKNOWN_ERROR_MSG = "Unknown error code."; +// Error code table ABI version. +#define COMMON_ERROR_TABLE_ABI_VER 2 // Increment this if you alter the table. - // Error code table. +// Enable C linkage if needed. +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +// Common namespace error code definitions. (Human-readable error message translation table is located in Common_Error_Handler_Structures.c) enum { // Generic error codes. - COMMON_SYSTEM_SPECIFIC = 99, - COMMON_SUCCESS = 0, - COMMON_UNKNOWN_ERROR = -1, - COMMON_INVALID_ARGUMENT = -2, - COMMON_FUNCTION_NOT_IMPLEMENTED = -3, - COMMON_ACCESS_DENIED = -4, - COMMON_EXCEPTION_THROWN = -5, - COMMON_INTERNAL_ERROR = -6, - COMMON_IO_ERROR = -7, - COMMON_RANGE_ERROR = -8, - COMMON_MEMORY_ERROR = -9, + COMMON_ERROR_SYSTEM_SPECIFIC = 99, + COMMON_ERROR_SUCCESS = 0, + COMMON_ERROR_UNKNOWN_ERROR = -1, + COMMON_ERROR_INVALID_ARGUMENT = -2, + COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED = -3, + COMMON_ERROR_ACCESS_DENIED = -4, + COMMON_ERROR_EXCEPTION_THROWN = -5, + COMMON_ERROR_INTERNAL_ERROR = -6, + COMMON_ERROR_IO_ERROR = -7, + COMMON_ERROR_RANGE_ERROR = -8, + COMMON_ERROR_MEMORY_ERROR = -9, + COMMON_ERROR_INVALID_LIBRARY_ID = -10, // Formerly THREAD_UTILS_INVALID_LIBRARY_ID. + COMMON_ERROR_PEBKAC_INVALID_OPERATION_ORDER = -11, + COMMON_ERROR_CANNOT_GET_SYSTEM_TIME = -12, + COMMON_ERROR_SUBSYSTEM_OBJECT_NOT_INITED = -13, + COMMON_ERROR_SUBSYSTEM_OBJECT_ALREADY_INITED = -14, + // Rendering Subsystem error codes. - RENDERER_UNABLE_TO_ALLOC_OI_BUF = -12, // Overlay image buffer. - RENDERER_UNABLE_TO_ALLOC_TD_BUF = -13, // Transparency data buffer. - RENDERER_MEM_BUF_ALLOC_EXCEPTION = -14, - RENDERER_DUPE_OVERLAY_EXCEPTION = -15, - RENDERER_INVAL_OVERLAY_SELF_OVERWRITE = -16, - RENDERER_TRANSPARENCY_DISABLED = -17, + RENDERER_ERROR_UNABLE_TO_ALLOC_OI_BUF = -21, // Overlay image buffer. + RENDERER_ERROR_UNABLE_TO_ALLOC_TD_BUF = -22, // Transparency data buffer. + RENDERER_ERROR_MEM_BUF_ALLOC_EXCEPTION = -23, + RENDERER_ERROR_DUPE_OVERLAY_EXCEPTION = -24, + RENDERER_ERROR_INVAL_OVERLAY_SELF_OVERWRITE = -25, + RENDERER_ERROR_TRANSPARENCY_DISABLED = -26, // Threading Subsystem error codes. - THREAD_UTILS_EXCEPTION_THROWN = -31, - THREAD_UTILS_INVALID_LIBRARY_ID = -32, - THREAD_UTILS_PLUGIN_LOAD_FAILURE = -33, + THREAD_UTILS_ERROR_EXCEPTION_THROWN = -31, + THREAD_UTILS_ERROR_PLUGIN_LOAD_FAILURE = -32, + THREAD_UTILS_ERROR_THREAD_COULD_NOT_START = -33, + THREAD_UTILS_ERROR_THREAD_COULD_NOT_DETACH = -34, + THREAD_UTILS_ERROR_THREAD_COULD_NOT_JOIN = -35, + THREAD_UTILS_ERROR_MUTEX_ALREADY_LOCKED = -36, + THREAD_UTILS_ERROR_CONDITION_CANNOT_LOCK_MUTEX = -37, + THREAD_UTILS_ERROR_CONDITION_WAIT_TIMEOUT_REACHED = -38, // FileUtills error codes. - FILEUTILLS_EXISTANT = -60, - FILEUTILLS_NON_EXISTANT = -61, - FILEUTILLS_READ_ONLY = -62, - FILEUTILLS_PATH_LENGTH_INVALID = -63, - FILEUTILLS_PATH_FILE_AS_DIRECTORY = -64, - FILEUTILLS_PATH_IS_A_FILE = -65, - FILEUTILLS_PATH_IS_A_DIRECTORY = -66, - FILEUTILLS_FILESYSTEM_FULL = -67, - FILEUTILLS_FILESYSTEM_QUOTA_REACHED = -68, - FILEUTILLS_EMPTY_DIRECTORY = -69, - FILEUTILLS_NON_EMPTY_DIRECTORY = -70, + FILEUTILLS_ERROR_EXISTANT = -60, + FILEUTILLS_ERROR_NON_EXISTANT = -61, + FILEUTILLS_ERROR_READ_ONLY = -62, + FILEUTILLS_ERROR_PATH_LENGTH_INVALID = -63, + FILEUTILLS_ERROR_PATH_FILE_AS_DIRECTORY = -64, + FILEUTILLS_ERROR_PATH_IS_A_FILE = -65, + FILEUTILLS_ERROR_PATH_IS_A_DIRECTORY = -66, + FILEUTILLS_ERROR_FILESYSTEM_FULL = -67, + FILEUTILLS_ERROR_FILESYSTEM_QUOTA_REACHED = -68, + FILEUTILLS_ERROR_EMPTY_DIRECTORY = -69, + FILEUTILLS_ERROR_NON_EMPTY_DIRECTORY = -70, + // UI Subsystem. + UI_SUBSYSTEM_ERROR_EXCEPTION_THROWN = -90, }; +/*! + * const unsigned int Common_Get_Error_Table_API_Version() + * + * Returns the API version number of the common error table. + */ +const unsigned int Common_Get_Error_Table_API_Version(); + +/*! + * const unsigned int Common_Get_Error_Table_Size() + * + * Returns the size of the common error table. + */ +const unsigned int Common_Get_Error_Table_Size(); + +/*! + * const char * Common_Get_Error_Message(const int & errorCode) + * + * This function takes the given error code and returns a pointer to a human + * readable string describing the meaning of the given error code. + * + * Returns a valid pointer if the given error code is in the common error table. + * Returns the message for Common_COMMON_UNKNOWN_ERROR otherwise. + */ +const char * Common_Get_Error_Message(const int errorCode); + +// Define C++ Bindings. +#ifdef __cplusplus +// Define namespaces. +namespace Common +{ /*! - * const Common_Error_Object Common::commonErrorTable[] - * - * This array contains all of the error codes that a Common namespace - * function may return, in addition to a human readable string describing - * the error code's meaning. (This is a work in progress, some error codes - * conflict with error codes in other functions, as such these are slowly - * being corrected.) - * - * The easiest way of fetching the human readable string from this table - * is to call Common::GetErrorMessage(). - * - * Do not reuse an existing error code. (If the error is generic then use a - * generic error code.) - * - * Do not change an existing error code. (This is to keep the API stable - * between revisions.) + * const unsigned int Common::Get_Error_Table_API_Version() + * + * (C++ Binding) + * + * Returns the API version number of the common error table. */ - const Common_Error_Object commonErrorTable[] = { - {COMMON_UNKNOWN_ERROR, UNKNOWN_ERROR_MSG}, - {COMMON_SYSTEM_SPECIFIC, "System specific error code. Check log."}, - {COMMON_SUCCESS, "Success."}, - {COMMON_INVALID_ARGUMENT, "Invalid argument."}, - {COMMON_FUNCTION_NOT_IMPLEMENTED, "Function not implemented."}, - {COMMON_ACCESS_DENIED, "Access Denied."}, - {COMMON_EXCEPTION_THROWN, "Execption thrown."}, - {COMMON_INTERNAL_ERROR, "Internal error."}, - {COMMON_IO_ERROR, "Input / Output error. (Normally this is a hardware issue.)"}, - {COMMON_RANGE_ERROR, "Given range is invalid."}, - {COMMON_MEMORY_ERROR, "Memory error (Could not allocate memory / Control loop out of bounds.)"}, - // Rendering Subsystem error codes. - {RENDERER_UNABLE_TO_ALLOC_OI_BUF, "Could not allocate memory for overlay image buffer."}, - {RENDERER_UNABLE_TO_ALLOC_TD_BUF, "Could not allocate memory for transparency data buffer."}, - {RENDERER_MEM_BUF_ALLOC_EXCEPTION, "Exception thrown while attempting to allocate memory buffer(s)."}, - {RENDERER_DUPE_OVERLAY_EXCEPTION, "Exception thrown while duplicating overlay, clearing dest overlay."}, - {RENDERER_INVAL_OVERLAY_SELF_OVERWRITE, "Given overlays are the same. Cannot overwrite an overlay with itself."}, - {RENDERER_TRANSPARENCY_DISABLED, "Transparency is disabled on given overlay."}, - // Threading Subsystem (Thread_Utils) error codes. - {THREAD_UTILS_EXCEPTION_THROWN, "Exception thrown in threading subsystem."}, - {THREAD_UTILS_INVALID_LIBRARY_ID, "Given LibraryID does not match a supported library or a loaded plugin."}, - {THREAD_UTILS_PLUGIN_LOAD_FAILURE, "Unable to load plugin(s). Internal error."}, - // FileUtills. - {FILEUTILLS_EXISTANT, "The path exists."}, - {FILEUTILLS_NON_EXISTANT, "The path (or a component of the path) does not exist."}, - {FILEUTILLS_READ_ONLY, "The path is read only."}, - {FILEUTILLS_PATH_LENGTH_INVALID, "The path's length is beyond the filesystem's maximum length."}, - {FILEUTILLS_PATH_FILE_AS_DIRECTORY, "The path has a file in it that is being treated as a directory."}, - {FILEUTILLS_PATH_IS_A_FILE, "Given path is a file."}, - {FILEUTILLS_PATH_IS_A_DIRECTORY, "Given path is a directory."}, - {FILEUTILLS_FILESYSTEM_FULL, "Given filesystem is full."}, - {FILEUTILLS_FILESYSTEM_QUOTA_REACHED, "User's disk usage quota for the given filesystem has been reached."}, - {FILEUTILLS_EMPTY_DIRECTORY, "The given path is an empty directory."}, - {FILEUTILLS_NON_EMPTY_DIRECTORY, "The given path is a non-empty directory."}, - // TODO: Need to add the error codes from all common namespace functions. - }; + const unsigned int Get_Error_Table_API_Version(); + + /*! + * const unsigned int Common::Get_Error_Table_Size() + * + * (C++ Binding) + * + * Returns the size of the common error table. + */ + const unsigned int Get_Error_Table_Size(); /*! - * static int Common::commonLastErrorCode + * const char * Common::Get_Error_Message(const int & errorCode) + * + * (C++ Binding) * - * Contains the last error code encountered by a Common namespace function. + * This function takes the given error code and returns a pointer to a human + * readable string describing the meaning of the given error code. * - * Note: Calling Common::GetErrorMessage() or Common::GetErrorTableSize() - * will NOT clear this variable. - * Calling any other Common namespace function WILL clear this variable. + * Returns a valid pointer if the given error code is in the common error table. + * Returns the message for Common_COMMON_UNKNOWN_ERROR otherwise. */ - static int commonLastErrorCode = COMMON_SUCCESS; -}; + const char * Get_Error_Message(const int & errorCode); +} +#endif // __cplusplus + +// End C Linkage if needed. +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif // COMMON_ERROR_ERROR_HANDLER_STRUCTURES_H + +// End of Common_Error_Handler_Structures.h diff --git a/src/Common/Src/Error_Handler/Common_Error_Handler_Structures_CPP_Bindings.cpp b/src/Common/Src/Error_Handler/Common_Error_Handler_Structures_CPP_Bindings.cpp new file mode 100644 index 0000000..0fd7237 --- /dev/null +++ b/src/Common/Src/Error_Handler/Common_Error_Handler_Structures_CPP_Bindings.cpp @@ -0,0 +1,41 @@ +/*! + Multiverse Engine Project 16/5/2015 Common Common_Error_Handler_Structures_CPP_Bindings.cpp + + Copyright (C) 2015 Multiverse Engine Project + + This program is free software; + you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this program; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Official source repository and project information can be found at + https://github.com/codebase7/mengine +*/ + +// Internal Includes. +#include "Common_Error_Handler.h" + +// Define C++ Bindings. +#ifdef __cplusplus + +const unsigned int Common::Get_Error_Table_API_Version() +{ + return Common_Get_Error_Table_API_Version(); +} + +const unsigned int Common::Get_Error_Table_Size() +{ + return Common_Get_Error_Table_Size(); +} + +const char * Common::Get_Error_Message(const int & errorCode) +{ + return Common_Get_Error_Message(errorCode); +} +#endif // __cplusplus diff --git a/src/Common/Src/Error_Handler/Error_Struct.h b/src/Common/Src/Error_Handler/Error_Struct.h index d551a0a..e08b1b0 100644 --- a/src/Common/Src/Error_Handler/Error_Struct.h +++ b/src/Common/Src/Error_Handler/Error_Struct.h @@ -18,14 +18,31 @@ https://github.com/codebase7/mengine */ +// Include guard. #ifndef ERROR_STRUCT_H #define ERROR_STRUCT_H -struct Common_Error_Object { +// Enable C linkage if needed. +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +/*! + * typedef struct Common_Error_Object_T + * + * Defines the data structure used by the Common Error Handler functions + * to look up human-readable strings and their assoicated error codes. + */ +typedef struct Common_Error_Object_T { short errorCode; const char * error; -}; +} Common_Error_Object; + +// End C Linkage if needed. +#ifdef __cplusplus +} +#endif // __cplusplus -#endif +#endif // ERROR_STRUCT_H -// End of Error_Struct.h \ No newline at end of file +// End of Error_Struct.h diff --git a/src/Common/Src/Error_Handler/Posix_Error_Translation_Table.cpp b/src/Common/Src/Error_Handler/Posix_Error_Translation_Table.c similarity index 60% rename from src/Common/Src/Error_Handler/Posix_Error_Translation_Table.cpp rename to src/Common/Src/Error_Handler/Posix_Error_Translation_Table.c index edfe8c1..e33fe41 100644 --- a/src/Common/Src/Error_Handler/Posix_Error_Translation_Table.cpp +++ b/src/Common/Src/Error_Handler/Posix_Error_Translation_Table.c @@ -1,5 +1,5 @@ /*! - Multiverse Engine Project 05/7/2014 Common Posix_Error_Translation_Table.cpp + Multiverse Engine Project 05/7/2014 Common Posix_Error_Translation_Table.c Copyright (C) 2014 Multiverse Engine Project @@ -22,33 +22,48 @@ #include "Common_Error_Handler_Structures.h" #include "Posix_Error_Translation_Table.h" -unsigned int Common::Get_Posix_Error_Translation_Table_Size() +// Include Extern C if needed. +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +const unsigned int Common_Get_Posix_Error_Translation_Table_API_Version() +{ + return COMMON_POSIX_ERROR_TRANSLATION_TABLE_API_VERSION; +} + +const unsigned int Common_Get_Posix_Error_Translation_Table_Size() { - return (sizeof(Common::posixErrorTranslationTable) / sizeof(Common::posixErrnoTableEntry)); + return (sizeof(Common_posixErrorTranslationTable) / sizeof(Common_posixErrnoTableEntry)); } -int Common::Translate_Posix_Errno_To_Common_Error_Code(const int & err) +int Common_Translate_Posix_Errno_To_Common_Error_Code(const int err) { // Init result. - int ret = COMMON_SYSTEM_SPECIFIC; /* - * Default is COMMON_SYSTEM_SPECIFIC, as + int ret = COMMON_ERROR_SYSTEM_SPECIFIC; /* + * Default is COMMON_ERROR_SYSTEM_SPECIFIC, as * not all POSIX errno(s) are / can be * reperesented in the Common namespace * error code table. */ // Run loop. - for (unsigned int x = 0; ((x < Common::Get_Posix_Error_Translation_Table_Size()) && - (ret == COMMON_SYSTEM_SPECIFIC)); x++) + for (unsigned int x = 0; ((x < Common_Get_Posix_Error_Translation_Table_Size()) && + (ret == COMMON_ERROR_SYSTEM_SPECIFIC)); x++) { // Check for a match in the error code translation table. - if (Common::posixErrorTranslationTable[x].posixErrorNo == err) + if (Common_posixErrorTranslationTable[x].posixErrorNo == err) { // Match found, return the Common namespace error code. - ret = Common::posixErrorTranslationTable[x].commonErrorCode; + ret = Common_posixErrorTranslationTable[x].commonErrorCode; } } // Return the result. return ret; -} \ No newline at end of file +} + +// Terminate C linkage if needed. +#ifdef __cplusplus +} +#endif // __cplusplus diff --git a/src/Common/Src/Error_Handler/Posix_Error_Translation_Table.h b/src/Common/Src/Error_Handler/Posix_Error_Translation_Table.h index 25d3ab6..671704b 100644 --- a/src/Common/Src/Error_Handler/Posix_Error_Translation_Table.h +++ b/src/Common/Src/Error_Handler/Posix_Error_Translation_Table.h @@ -25,66 +25,143 @@ // Include POSIX errno header. #include +// Enable C linkage if needed. +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +/*! + * #define COMMON_POSIX_ERROR_TRANSLATION_TABLE_API_VERSION + * + * Defines the API version of the posix errno to + * common namespace error code translation table. + * + * If you change the table increment the version + * number. + */ +#define COMMON_POSIX_ERROR_TRANSLATION_TABLE_API_VERSION 1 + +/*! + * typedef struct Common_posixErrnoTableEntry_T Common_posixErrnoTableEntry + * + * (C Binding.) + * + * Used to construct the errno translation table. + * for POSIX compliant systems. + */ +typedef struct Common_posixErrnoTableEntry_T { + int posixErrorNo; + int commonErrorCode; +} Common_posixErrnoTableEntry; + +/*! + * const static Common_posixErrnoTableEntry Common_posixErrorTranslationTable[] + * + * A table that contains (some) POSIX errno codes and their + * Common namespace error code equilivants. + * + * Not all POSIX errno(s) are present in this table, as + * some POSIX errno(s) are specific to POSIX compliant + * systems. As such there is no Common namespace error + * code (beyond COMMON_SYSTEM_SPECIFIC) to represent them. + */ +const static Common_posixErrnoTableEntry Common_posixErrorTranslationTable[] = { + {EACCES, COMMON_ERROR_ACCESS_DENIED}, + {ENOENT, FILEUTILLS_ERROR_NON_EXISTANT}, + {EEXIST, FILEUTILLS_ERROR_EXISTANT}, + {EROFS, FILEUTILLS_ERROR_READ_ONLY}, + {EINVAL, COMMON_ERROR_INVALID_ARGUMENT}, + {ENAMETOOLONG, FILEUTILLS_ERROR_PATH_LENGTH_INVALID}, + {ENOTDIR, FILEUTILLS_ERROR_PATH_FILE_AS_DIRECTORY}, + {ENOMEM, COMMON_ERROR_MEMORY_ERROR}, + {EFAULT, COMMON_ERROR_INVALID_ARGUMENT}, + {ENOSPC, FILEUTILLS_ERROR_FILESYSTEM_FULL}, + {EDQUOT, FILEUTILLS_ERROR_FILESYSTEM_QUOTA_REACHED}, + {ENOTEMPTY, FILEUTILLS_ERROR_NON_EMPTY_DIRECTORY}, +}; + +/*! + * const unsigned int Common_Get_Posix_Error_Translation_Table_API_Version() + * + * Returns the API Version number of the Common_posixErrorTranslationTable + * array. + */ +const unsigned int Common_Get_Posix_Error_Translation_Table_API_Version(); + +/*! + * const unsigned int Common_Get_Posix_Error_Translation_Table_Size() + * + * Returns the size of the Common::posixErrorTranslationTable + * array. + */ +const unsigned int Common_Get_Posix_Error_Translation_Table_Size(); + +/*! + * int Common_Translate_Posix_Errno_To_Common_Error_Code(const int err) + * + * Translates the given POSIX errno to it's Common namespace + * error code equilivant. (If applicable.) + * + * WARNING: Because the POSIX errno variable is global, you + * should never call this function passing errno directly. + * + * Instead, copy the errno to a temporary variable and then + * pass the temporary variable to this function. + * + * (Otherwise just calling this function could change errno + * before it is checked.) + * + * @pram const int err, the POSIX error code to translate. + * + * Returns the translated Common namespace error code if applicable. + * + * Returns COMMON_SYSTEM_SPECIFIC if the POSIX errno does not have a + * Common namespace error code translation. + */ +int Common_Translate_Posix_Errno_To_Common_Error_Code(const int err); + +// End C Linkage if needed. +#ifdef __cplusplus +} +#endif // __cplusplus + +// Check for a C compiler. +#ifdef __cplusplus namespace Common { /*! - * struct Common::posixErrnoTableEntry - * + * typedef Common_posixErrnoTableEntry Common::posixErrnoTableEntry + * + * (C++ Binding.) + * * Used to construct the errno translation table. * for POSIX compliant systems. */ - struct posixErrnoTableEntry{ - int posixErrorNo; - int commonErrorCode; - }; + typedef Common_posixErrnoTableEntry posixErrnoTableEntry; /*! - * const int posixErrorTranslationTableAPIVersion - * - * Defines the API version of the posix errno to - * common namespace error code translation table. - * - * If you change the table increment the version - * number. - */ - const int posixErrorTranslationTableAPIVersion = 1; - - /*! - * const Common::posixErrnoTableEntry Common::posixErrorTranslationTable[] - * - * A table that contains (some) POSIX errno codes and their - * Common namespace error code equilivants. + * const unsigned int Common::Get_Posix_Error_Translation_Table_API_Version() * - * Not all POSIX errno(s) are present in this table, as - * some POSIX errno(s) are specific to POSIX compliant - * systems. As such there is no Common namespace error - * code (beyond COMMON_SYSTEM_SPECIFIC) to represent them. + * Returns the API Version number of the Common_posixErrorTranslationTable + * array. */ - const posixErrnoTableEntry posixErrorTranslationTable[] = { - {EACCES, Common::COMMON_ACCESS_DENIED}, - {ENOENT, Common::FILEUTILLS_NON_EXISTANT}, - {EEXIST, Common::FILEUTILLS_EXISTANT}, - {EROFS, Common::FILEUTILLS_READ_ONLY}, - {EINVAL, Common::COMMON_INVALID_ARGUMENT}, - {ENAMETOOLONG, Common::FILEUTILLS_PATH_LENGTH_INVALID}, - {ENOTDIR, Common::FILEUTILLS_PATH_FILE_AS_DIRECTORY}, - {ENOMEM, Common::COMMON_MEMORY_ERROR}, - {EFAULT, Common::COMMON_INVALID_ARGUMENT}, - {ENOSPC, Common::FILEUTILLS_FILESYSTEM_FULL}, - {EDQUOT, Common::FILEUTILLS_FILESYSTEM_QUOTA_REACHED}, - }; + const unsigned int Get_Posix_Error_Translation_Table_API_Version(); /*! - * unsigned int Common::Get_Posix_Error_Translation_Table_Size() - * + * const unsigned int Common::Get_Posix_Error_Translation_Table_Size() + * + * (C++ Binding) + * * Returns the size of the Common::posixErrorTranslationTable * array. */ - unsigned int Get_Posix_Error_Translation_Table_Size(); + const unsigned int Get_Posix_Error_Translation_Table_Size(); /*! * int Common::Translate_Posix_Errno_To_Common_Error_Code(const int & err) - * + * + * (C++ Binding) + * * Translates the given POSIX errno to it's Common namespace * error code equilivant. (If applicable.) * @@ -106,6 +183,7 @@ namespace Common */ int Translate_Posix_Errno_To_Common_Error_Code(const int & err); }; +#endif // __cplusplus #endif // POSIX_ERROR_TRANSLATION_TABLE_H diff --git a/src/Common/Src/Error_Handler/Posix_Error_Translation_Table_CPP_Bindings.cpp b/src/Common/Src/Error_Handler/Posix_Error_Translation_Table_CPP_Bindings.cpp new file mode 100644 index 0000000..96c7adb --- /dev/null +++ b/src/Common/Src/Error_Handler/Posix_Error_Translation_Table_CPP_Bindings.cpp @@ -0,0 +1,45 @@ +/*! + Multiverse Engine Project 15/5/2015 Common Posix_Error_Translation_Table_CPP_Bindings.cpp + + Copyright (C) 2015 Multiverse Engine Project + + This program is free software; + you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this program; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Official source repository and project information can be found at + https://github.com/codebase7/mengine +*/ + +// C++ Bindings. +#ifdef __cplusplus + +// Internal includes. +#include "Common_Error_Handler_Structures.h" +#include "Posix_Error_Translation_Table.h" + +// External includes. +#include + +const unsigned int Common::Get_Posix_Error_Translation_Table_API_Version() +{ + return Common_Get_Posix_Error_Translation_Table_API_Version(); +} + +const unsigned int Common::Get_Posix_Error_Translation_Table_Size() +{ + return Common_Get_Posix_Error_Translation_Table_Size(); +} + +int Common::Translate_Posix_Errno_To_Common_Error_Code(const int & err) +{ + return Common_Translate_Posix_Errno_To_Common_Error_Code(err); +} +#endif // __cplusplus From 4464d65bccf2f2eb72fff47213634cfbd2707bc5 Mon Sep 17 00:00:00 2001 From: codebase7 Date: Sun, 24 May 2015 19:17:31 -0400 Subject: [PATCH 002/325] Inital rewrite commit. This commit is all over the place as it contains a lot of rewriten functions, new API calls, code path restructuring, and even some new error codes. In addition most of this code was written over the course of the last year, but was not completed, due to other work. Probably a benifit as the original rewrite was "finalized" as far as it's code path restructuring and API calls were concerned, but looking at it now, there is some other modifications that need to be made that I was not considering at the time. Currently work is being done to port the code to C, as well as fix the API calls to make all functions return Common error codes. (Any other data that needs to be returned, will be moved to the arguments list as pointers.) We are also elimiating the Common::commonLastErrorCode global variable to make the API thread safe. In addition to makeing the API more thread safe in general. --- .../Common_Error_Handler_Structures.c | 4 + .../Common_Error_Handler_Structures.h | 12 +- .../File_Management_Subsystem/CMakeLists.txt | 18 +- .../File_Management_Subsystem/FileUtills.cpp | 4557 ++++++++--------- .../File_Management_Subsystem/FileUtills.h | 1060 ++-- ...tills_Emulated_Symbolic_Link_Functions.cpp | 307 ++ ...eUtills_Emulated_Symbolic_Link_Functions.h | 146 + .../FileUtills_Private_API.cpp | 1602 ++++++ .../FileUtills_Private_API.h | 884 ++++ .../FileUtills_Private_API_Posix_Syscall.cpp | 1326 +++++ .../FileUtills_Private_API_Posix_Syscall.h | 30 + 11 files changed, 6970 insertions(+), 2976 deletions(-) create mode 100644 src/Common/Src/File_Management_Subsystem/FileUtills_Emulated_Symbolic_Link_Functions.cpp create mode 100644 src/Common/Src/File_Management_Subsystem/FileUtills_Emulated_Symbolic_Link_Functions.h create mode 100644 src/Common/Src/File_Management_Subsystem/FileUtills_Private_API.cpp create mode 100644 src/Common/Src/File_Management_Subsystem/FileUtills_Private_API.h create mode 100644 src/Common/Src/File_Management_Subsystem/FileUtills_Private_API_Posix_Syscall.cpp create mode 100644 src/Common/Src/File_Management_Subsystem/FileUtills_Private_API_Posix_Syscall.h diff --git a/src/Common/Src/Error_Handler/Common_Error_Handler_Structures.c b/src/Common/Src/Error_Handler/Common_Error_Handler_Structures.c index 0c682f4..1887943 100644 --- a/src/Common/Src/Error_Handler/Common_Error_Handler_Structures.c +++ b/src/Common/Src/Error_Handler/Common_Error_Handler_Structures.c @@ -98,10 +98,14 @@ const Common_Error_Object Common_commonErrorTable[] = { {FILEUTILLS_ERROR_PATH_FILE_AS_DIRECTORY, "The path has a file in it that is being treated as a directory."}, {FILEUTILLS_ERROR_PATH_IS_A_FILE, "Given path is a file."}, {FILEUTILLS_ERROR_PATH_IS_A_DIRECTORY, "Given path is a directory."}, + {FILEUTILLS_ERROR_PATH_IS_A_SYMLINK, "Given path is a symbolic link."}, + {FILEUTILLS_ERROR_PATH_IS_ABSOLUTE, "Given path is in absolute format (Fully resolved)."}, + {FILEUTILLS_ERROR_PATH_IS_RELATIVE, "Given path is in relative format (Needs resolving)."}, {FILEUTILLS_ERROR_FILESYSTEM_FULL, "Given filesystem is full."}, {FILEUTILLS_ERROR_FILESYSTEM_QUOTA_REACHED, "User's disk usage quota for the given filesystem has been reached."}, {FILEUTILLS_ERROR_EMPTY_DIRECTORY, "The given path is an empty directory."}, {FILEUTILLS_ERROR_NON_EMPTY_DIRECTORY, "The given path is a non-empty directory."}, + {FILEUTILLS_ERROR_SYMLINK_CHAIN_TOO_DEEP, "While parsing a host-defined symbolic link chain, the host system indicated the link chain was longer than what it supports."}, // UI Subsystem/ {UI_SUBSYSTEM_ERROR_EXCEPTION_THROWN, "An exception was thrown in the UI Subsystem."}, // TODO: Need to add the error codes from all common namespace functions. diff --git a/src/Common/Src/Error_Handler/Common_Error_Handler_Structures.h b/src/Common/Src/Error_Handler/Common_Error_Handler_Structures.h index ad6bf04..3e22a73 100644 --- a/src/Common/Src/Error_Handler/Common_Error_Handler_Structures.h +++ b/src/Common/Src/Error_Handler/Common_Error_Handler_Structures.h @@ -80,10 +80,14 @@ extern "C" { FILEUTILLS_ERROR_PATH_FILE_AS_DIRECTORY = -64, FILEUTILLS_ERROR_PATH_IS_A_FILE = -65, FILEUTILLS_ERROR_PATH_IS_A_DIRECTORY = -66, - FILEUTILLS_ERROR_FILESYSTEM_FULL = -67, - FILEUTILLS_ERROR_FILESYSTEM_QUOTA_REACHED = -68, - FILEUTILLS_ERROR_EMPTY_DIRECTORY = -69, - FILEUTILLS_ERROR_NON_EMPTY_DIRECTORY = -70, + FILEUTILLS_ERROR_PATH_IS_A_SYMLINK = -67, + FILEUTILLS_ERROR_PATH_IS_ABSOLUTE = -68, + FILEUTILLS_ERROR_PATH_IS_RELATIVE = -69, + FILEUTILLS_ERROR_FILESYSTEM_FULL = -70, + FILEUTILLS_ERROR_FILESYSTEM_QUOTA_REACHED = -71, + FILEUTILLS_ERROR_EMPTY_DIRECTORY = -72, + FILEUTILLS_ERROR_NON_EMPTY_DIRECTORY = -73, + FILEUTILLS_ERROR_SYMLINK_CHAIN_TOO_DEEP = -74, // UI Subsystem. UI_SUBSYSTEM_ERROR_EXCEPTION_THROWN = -90, }; diff --git a/src/Common/Src/File_Management_Subsystem/CMakeLists.txt b/src/Common/Src/File_Management_Subsystem/CMakeLists.txt index d8dd7dd..e276211 100644 --- a/src/Common/Src/File_Management_Subsystem/CMakeLists.txt +++ b/src/Common/Src/File_Management_Subsystem/CMakeLists.txt @@ -2,7 +2,23 @@ set(LIBRARY_OUTPUT_PATH ${L_OUTPUT_DIR}) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${O_OUTPUT_DIR}) -set(FILEUTILLS_INCLUDES FileUtills.cpp) +# Set default includes. +set(FILEUTILLS_INCLUDES FileUtills.cpp FileUtills_Private_API.cpp) + +# Set system specific includes. +IF(${CMAKE_SYSTEM_NAME} MATCHES "Windows") + # Building on windows. + set(FILEUTILLS_INCLUDES ${FILEUTILLS_INCLUDES} FileUtills_Private_API_Windows_Syscall.cpp) + + ELSEIF(${CMAKE_SYSTEM_NAME} MATCHES "Linux") + # Building on Linux. + set(FILEUTILLS_INCLUDES ${FILEUTILLS_INCLUDES} FileUtills_Private_API_Posix_Syscall.cpp) + + ELSE(${CMAKE_SYSTEM_NAME} MATCHES "Windows") + # We don't have a match against a known system. + message(FATAL_ERROR "Attempting to build the File Management Subsystem with an unrecognized OS / System / Arch. Aborting build.") + +ENDIF(${CMAKE_SYSTEM_NAME} MATCHES "Windows") add_library(File_Management_Multiverse_Engine SHARED ${FILEUTILLS_INCLUDES}) target_link_libraries(File_Management_Multiverse_Engine Common_Error_Handler_Multiverse_Engine) diff --git a/src/Common/Src/File_Management_Subsystem/FileUtills.cpp b/src/Common/Src/File_Management_Subsystem/FileUtills.cpp index c7e28fa..a8ebee5 100644 --- a/src/Common/Src/File_Management_Subsystem/FileUtills.cpp +++ b/src/Common/Src/File_Management_Subsystem/FileUtills.cpp @@ -1,7 +1,7 @@ /*! Multiverse Engine Project 04/12/2011 FileUtills FileUtills.cpp - Copyright (C) 2013 Multiverse Engine Project + Copyright (C) 2014 Multiverse Engine Project This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; @@ -18,8 +18,9 @@ https://github.com/codebase7/mengine */ - +// Internal includes. #include "FileUtills.h" +#include "FileUtills_Private_API.h" /*! std::string RemoveTrailingSlash(const std::string & path) @@ -30,642 +31,801 @@ */ std::string RemoveTrailingSlash(const std::string & path) { - //init vars + // Init vars. size_t size = 0; std::string buffer = ""; // Get size of the Directory string. size = path.size(); - // Check the length of the string see if it is only 1 charater - if (size == 1) + // Check the length of the string see if it is only 1 charater. + if (size <= 1) { - // We can't remove anything, if we do the return would be empty. - return path; + // We can't remove anything, if we do the return would be empty. + return path; } // Copy the directory string to buffer buffer = path; // Check and see if a directory seperator is on the end of the string. - if ((path.find_last_of(DIR_SEP)) == (size-1)) + if ((path.find_last_of(DIR_SEP)) == (size - 1)) { - // Remove the trailing Directory seperator so we don't screw up the next check. - // Note substr CAN throw an exception so we must put it in a try catch block - try{ - buffer = path.substr(0, (size-1)); - } - catch(exception ex) - { - // We can't return an error so we will silently fail. - return path; - } + // Remove the trailing Directory seperator so we don't screw up the next check. + // Note: substr CAN throw an exception so we must put it in a try catch block. + try{ + buffer = path.substr(0, (size - 1)); + } + catch(exception ex) + { + // We can't return an error so we will silently fail. + return path; + } } // Return new path. return buffer; } -int FileUtills::GetUserProfileDirectoryPath(std::string & path) +int CheckPathType(const std::string & path, bool & bIsDosStylePath) { - // Reset Common::commonLastErrorCode. - Common::commonLastErrorCode = Common::COMMON_FUNCTION_NOT_IMPLEMENTED; -#ifdef __linux__ // Init vars. - int errorg = 0; // Used to hold the original state of errno so it can be restored after we finish. - int errcpy = 0; // Used to store errno if needed. - char * pHD = NULL; // Used to fetch the path from the system. - - // Backup and clear errno. - errorg = errno; - errno = 0; - - // Blank out the path value. - path.clear(); + short ret = COMMON_ERROR_INTERNAL_ERROR; // Result of this function. - // Get the path to the user's profile directory. - try { - pHD = getenv("HOME"); - if ((errno == 0) && (pHD != NULL)) + // Check for valid path string. + if (path.size() > 0) + { + // Check for a DOS style absolute path reference. + if ((path.size() > 3) && (path[1] == ':') && (path[2] == '\\')) { - // Copy the variable to the path. - path = pHD; - - // Set success code. - Common::commonLastErrorCode = Common::COMMON_SUCCESS; + // This is DOS style absolute path. + bIsDosStylePath = true; } else { - // Could not get user profile directory path variable. - errcpy = errno; - Common::commonLastErrorCode = Common::Translate_Posix_Errno_To_Common_Error_Code(errcpy); - COMMON_LOG_VERBOSE("FileUtills::GetUserProfileDirectoryPath(): "); - COMMON_LOG_VERBOSE(Common::Get_Error_Message(Common::commonLastErrorCode)); - COMMON_LOG_VERBOSE(" Could not get user profile directory path from enviorment.\n"); - - // Reset path. - path.clear(); + // Set bIsDosStylePath. + bIsDosStylePath = true; + + /* + * We are assuming that if a '/' character is found + * in the path, it is a POSIX style path. + * + * (Probably a dangerous assumption, but there is not + * much of a way to determine the path type short of + * determining the OS in use. (And even then it's a + * problem if the target is different than the host.)) + * + * Hopefully the target OS will complain if it gets an + * invalid path...... + */ + for (size_t x = 0; ((x < path.size()) && (bIsDosStylePath)); x++) + { + // Check for a '/' character. + if (path[x] == '/') + { + // OK this is a reserved character on windows, so assume the path is a POSIX style path. + bIsDosStylePath = false; + } + } } + + // Done. + ret = COMMON_ERROR_SUCCESS; } - catch (exception &ex) + else { - // Exception thown. - Common::commonLastErrorCode = Common::COMMON_EXCEPTION_THROWN; - COMMON_LOG_VERBOSE("FileUtills::GetUserProfileDirectoryPath(): "); - COMMON_LOG_VERBOSE(Common::Get_Error_Message(Common::commonLastErrorCode)); - COMMON_LOG_VERBOSE(" "); - COMMON_LOG_VERBOSE(ex.what()); - COMMON_LOG_VERBOSE("\n"); - - // Reset path. - path.clear(); + // Invalid path. + ret = COMMON_ERROR_INVALID_ARGUMENT; } - // Check for an allocated buffer. - if (pHD != NULL) + // Return the result. + return ret; +} + +int FileUtills::GetUserProfileDirectoryPath(std::string & path) +{ + // Init vars. + int ret = COMMON_ERROR_UNKNOWN_ERROR; + + // Call the syscall. + ret = FileUtills::GetUserProfileDirectoryPath_Syscall(path); + if (ret != COMMON_ERROR_SUCCESS) { - // Release the buffer. - free(pHD); - pHD = NULL; - } + // Blank path. + path.clear(); - // Restore errno. - errno = errorg; -#endif // __linux__ + // Check for a INVALID_ARGUMENT. + if (ret == COMMON_ERROR_INVALID_ARGUMENT) + { + // This is an internal error. + ret = COMMON_ERROR_INTERNAL_ERROR; - // Exit function. - return Common::commonLastErrorCode; + // Log this error. + COMMON_LOG_WARNING("FileUtills::GetUserProfileDirectoryPath(): Syscall returned an invalid argument error. Please report this bug.\n"); + } + else + { + // Log the error. + COMMON_LOG_DEBUG("FileUtills::GetUserProfileDirectoryPath(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(ret)); + COMMON_LOG_DEBUG("\n"); + } + } + else + { + // Check for success without result. + if (path.size() <= 0) + { + // Internal error. + ret = COMMON_ERROR_INTERNAL_ERROR; + COMMON_LOG_WARNING("FileUtills::GetUserProfileDirectoryPath(): Syscall returned an invalid path, but indicated success. Please report this bug.\n"); + } + } + + // Return the result. + return ret; } int FileUtills::GetCurrentWorkingDirectoryPath(std::string & path) { - // Reset Common::commonLastErrorCode. - Common::commonLastErrorCode = Common::COMMON_FUNCTION_NOT_IMPLEMENTED; -#ifdef __linux__ // Init vars. - int errorg = 0; // Used to hold the original state of errno so it can be restored after we finish. - int errcpy = 0; // Used to store errno if needed. - char * pCWD = NULL; // Used to fetch path from system. + int ret = COMMON_ERROR_UNKNOWN_ERROR; - // Backup and clear errno. - errorg = errno; - errno = 0; - - // Blank out the path value. - path.clear(); + // Call the syscall. + ret = FileUtills::GetCurrentWorkingDirectoryPath_Syscall(path); + if (ret != COMMON_ERROR_SUCCESS) + { + // Blank path. + path.clear(); - // Get current directory. - try { - /* - * NOTE: The call below is linux (libc5, libc6, and glibc) specific. - * (The standard requires a preallocated buffer.) - * - * I dislike the idea of a preallocated buffer as we cannot reliably - * determine the needed length. (Plus it could change between calls.) - * - * This really should be checked for and an error thrown if the OS / - * libc in use does not support this usage. - */ - pCWD = getcwd(NULL, 0); - if ((errno == 0) && (pCWD != NULL)) + // Check for a INVALID_ARGUMENT. + if (ret == COMMON_ERROR_INVALID_ARGUMENT) { - // Copy the path. - path = pCWD; + // This is an internal error. + ret = COMMON_ERROR_INTERNAL_ERROR; - // Set commonLastErrorCode. - Common::commonLastErrorCode = Common::COMMON_SUCCESS; + // Log this error. + COMMON_LOG_WARNING("FileUtills::GetCurrentWorkingDirectoryPath(): Syscall returned an invalid argument error. Please report this bug.\n"); } else { - // Could not get current working directory path variable. - errcpy = errno; - Common::commonLastErrorCode = Common::Translate_Posix_Errno_To_Common_Error_Code(errcpy); - COMMON_LOG_VERBOSE("FileUtills::GetCurrentWorkingDirectoryPath(): "); - COMMON_LOG_VERBOSE(Common::Get_Error_Message(Common::commonLastErrorCode)); - COMMON_LOG_VERBOSE(" Could not get current working directory path from enviorment.\n"); - - // Reset path. - path.clear(); + // Log the error. + COMMON_LOG_DEBUG("FileUtills::GetCurrentWorkingDirectoryPath(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(ret)); + COMMON_LOG_DEBUG("\n"); } } - catch(exception &ex) + else { - // Exception thown. - Common::commonLastErrorCode = Common::COMMON_EXCEPTION_THROWN; - COMMON_LOG_VERBOSE("FileUtills::GetCurrentWorkingDirectoryPath(): "); - COMMON_LOG_VERBOSE(Common::Get_Error_Message(Common::commonLastErrorCode)); - COMMON_LOG_VERBOSE(" "); - COMMON_LOG_VERBOSE(ex.what()); - COMMON_LOG_VERBOSE("\n"); - - // Reset path. - path.clear(); + // Check for success without result. + if (path.size() <= 0) + { + // Internal error. + ret = COMMON_ERROR_INTERNAL_ERROR; + COMMON_LOG_WARNING("FileUtills::GetCurrentWorkingDirectoryPath(): Syscall returned an invalid path, but indicated success. Please report this bug.\n"); + } } - // Check for an allocated buffer. - if (pCWD != NULL) + // Return the result. + return ret; +} + +int FileUtills::GetExecDirectory(std::string & retStr) +{ + // Init vars. + int ret = COMMON_ERROR_UNKNOWN_ERROR; // The result code of this function. + std::string result = ""; // The result string from GetExecDirectory_Syscall(). + + // Call the syscall. + ret = FileUtills::GetExecDirectory_Syscall(result); + if (ret == COMMON_ERROR_SUCCESS) + { + // Copy result to retStr. + retStr = result; + } + else { - // Release the buffer. - free(pCWD); - pCWD = NULL; + // Check for a INVALID_ARGUMENT. + if (ret == COMMON_ERROR_INVALID_ARGUMENT) + { + // This is an internal error. + ret = COMMON_ERROR_INTERNAL_ERROR; + + // Log this error. + COMMON_LOG_WARNING("FileUtills::GetExecDirectory(): Syscall returned an invalid argument error. Please report this bug.\n"); + } + else + { + // Log the error. + COMMON_LOG_DEBUG("FileUtills::GetExecDirectory(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(ret)); + COMMON_LOG_DEBUG("\n"); + } } - // Restore errno. - errno = errorg; -#endif // __linux__ + // Blank result. + result.clear(); - // Exit function. - return Common::commonLastErrorCode; + // Return ret. + return ret; } -std::string FileUtills::GetExecDirectory() +/*! + * int FileUtills_Reallocate_CString_Buffer(char ** buf, const size_t bufSize, const size_t newSize) + * + * Allocates a new C-String buffer of newSize length, Reallocates a given buffer + * to be the given newSize length, or deallocates the given buffer if it is + * allocated and newSize is equal to zero. + * + * WARNING: If this function returns COMMON_ERROR_SUCCESS, then the original + * pointer will be deallocated (free()'d) prior to the function's return. + * DO NOT ATTEMPT TO REUSE THE ORIGINAL POINTER AFTERWARDS. + * + * Note about buffer reallocations: + * If the original buffer is allocated and a valid size is provided, + * (bufSize must be greater than zero), then X amount of data from the original + * buffer will be sequentially copied to the new buffer. Where X is the amount of + * data that will fit within the new buffer. Any remaining space will be filled + * with NULL characters. Any data that does not fit will be truncated. + * + * Examples of buffer reallocations: + * Original Buffer (bufSize) Reallocated buffer(newSize): + * "Foo"(3) "Foo"(3) + * "Foo"(3) "Foo\0\0\0"(6) + * "Foo"(3) "F"(1) + * + * Returns COMMON_ERROR_SUCCESS if successful. The original pointer will have + * been deallocated and replaced with the newly allocated buffer. The newly + * allocated buffer will be of newSize length. + * + * Otherwise returns the appropriate error. In this case the original buffer is + * guaranteed to be left intact and unaltered. + */ +int FileUtills_Reallocate_CString_Buffer(char ** buf, const size_t bufSize, const size_t newSize) { // Init vars. - std::string result = ""; // The string returned from this function. -#ifdef __linux__ - /* - * Short version: - * This is a cluster. - * - * Long version: - * The only reliable (guarrenteed to work) method for getting the executable - * path in linux, is by using readlink() on /proc/self/exe. - * - * However, this has several issues. - * - * First issue: readlink() expects a preallocated buffer to store the result. - * If the preallocated buffer is too small for the full path, then readlink() - * will silently truncate the remaining data and not tell us how much was - * left over. - * - * Second issue: The proc filesystem misbehaves and does not fill in the - * st_size field of the stat structure. So as a result we can't easilly - * tell how much memory to allocate for our buffer. - * - * Third issue: Because some filesystems allow paths of unlimited size, - * (i.e. the only restriction is having the space to store the path), - * we can't use PATH_MAX (as it's possibly wrong), and we can't set a - * limit on our memory allocation. - * - * Because of these issues, the glibc MANUAL actually gives an indefinite - * loop of memory allocation->readlink()->if(!got entire link)->Deallocate memory->Allocate memory. - * for reading a symlink from the filesystem. - * - * This loop is reimplimented here, but with two differences. - * - * - The loop will end once a certian amount of relocations (defined by GET_EXE_PATH_REALLOC) - * is reached. (This is to prevent some of the above issues.) - * - * - The loop will also check to make sure that the returned string has not been altered. - * (via memcmp). - */ + int ret = COMMON_ERROR_UNKNOWN_ERROR; // The result of this function. + char * tempBuf = NULL; // A temp pointer used to copy data. - // Init vars. - int errcpy = 0; // Used to copy errno if needed. - const size_t MAX_GET_EXE_PATH_REALLOC = 4; // Maximum number of times to run the memory reallocation loop. - const size_t BASE_SIZE = 1000; // Inital number of bytes to allocate. (This number is multiplied by the loop iteration value (x) after each loop iteration.) - size_t realBufferLength = 0; // Unsigned value of how big the buffer is. (Used for accessing and allocating the buffer.) - ssize_t firstBufferLength = 0; // Signed return value of the number of bytes written to the buffer by readlink(). (Just so they could return that -1 error code....) - ssize_t secondBufferLength = 0; // Signed return value of the number of bytes written to the checkBuffer by readlink(). (Just so they could return that -1 error code....) - char * buffer = NULL; // First buffer. - char * checkBuffer = NULL; // Second buffer. (Both buffers must match exactly (memcmp) for this function to return a valid path.) - struct stat st; // Used to make sure that PROC_PATH is actually a symlink. - const char * const PROC_PATH = "/proc/self/exe";// The actual path to the symlink that represents the executable in the /proc filesystem. - - // Set Common::commonLastErrorCode to COMMON_UNKNOWN_ERROR. - Common::commonLastErrorCode = Common::COMMON_UNKNOWN_ERROR; - - // OK this is dumb, but check it anyway.... - errcpy = lstat(PROC_PATH, &st); - if (errcpy == 0) + // Check for a zero new size. + if (newSize > 0) { - // Make sure that PROC_PATH is a symlink. - if ((st.st_mode & S_IFMT) == S_IFLNK) // S_IFMT is a bit mask for extracting the file type from st_mode. S_IFLNK is the file type for a symlink. + // Allocate the buffer. + tempBuf = (char*)malloc(newSize); + if (tempBuf != NULL) { - // Begin the devil's loop. - try { - for (size_t x = 0; ((x < MAX_GET_EXE_PATH_REALLOC) && - ((buffer == NULL) && (checkBuffer == NULL)) && - (Common::commonLastErrorCode == Common::COMMON_UNKNOWN_ERROR)); x++) + // Fill the buffer with NULL characters. + for (size_t x = 0; (x < newSize); x++) + { + tempBuf[x] = '\0'; + } + + // Check and see if the original buffer size is greater than zero, and if that buffer is allocated. + if ((bufSize > 0) && (buf != NULL)) + { + // OK, copy as much of the original data from the original buffer as possible. + for (size_t x = 0; ((x < bufSize) && (x < newSize)); x++) { - // Recalculate bufferLength. - realBufferLength = (BASE_SIZE * (x + 1)); + tempBuf[x] = (*buf)[x]; + } + } + + // Deallocate the original buffer if it is allocated. + if ((*buf) != NULL) + { + free((*buf)); + (*buf) = NULL; + } + + // Copy the tempBuf pointer to buf. + (*buf) = tempBuf; + + // Done. + ret = COMMON_ERROR_SUCCESS; + } + else + { + // Could not allocate memory. + ret = COMMON_ERROR_MEMORY_ERROR; + } + } + else + { + // Deallocate the original buffer if it is allocated. + if ((*buf) != NULL) + { + free((*buf)); + (*buf) = NULL; + } + + // Done. + ret = COMMON_ERROR_SUCCESS; + } - // Allocate the memory. - buffer = (char*)malloc(realBufferLength); - checkBuffer = (char*)malloc(realBufferLength); + // Return the result. + return ret; +} - // Make sure it was allocated. - if ((buffer != NULL) && (checkBuffer != NULL)) +int FileUtills::ResolvePath(const char * path, const size_t pathSize, char * retStr, size_t * retStrSize, const bool disableSymLinkResolution) +{ + // Init vars. + int ret = COMMON_ERROR_UNKNOWN_ERROR; // The result of this function. + size_t numOfResolveAttempts = 0; // The number of times we have attempted to resolve a symbolic link. + size_t outputStrSize = 0; // The current size of the output string. + size_t tempLinkBufSize = 0; // The current size of the tempLinkBuf. + char * outputStr = NULL; // The resolved path. + char * tempLinkBuf = NULL; // Used to hold the result of FileUtills::ResolveSystemSymoblicLink_Syscall(). + + // Check for valid path. + if ((path != NULL) && (pathSize > 0)) + { + // Allocate buffer for outputStr. + outputStr = (char*)malloc(pathSize); + if (outputStr != NULL) + { + // Copy path to outputStr. + for (outputStrSize = 0; ((ret == COMMON_ERROR_UNKNOWN_ERROR) && (outputStrSize < pathSize)); outputStrSize++) + { + // Check for a NULL that's before the end of the buffer. + if ((path[outputStrSize] == '\0') && ((outputStrSize + 1) != pathSize)) + { + // Invalid path string. (NULL should be at the end of the buffer.) + ret = COMMON_ERROR_INVALID_ARGUMENT; + COMMON_LOG_DEBUG("FileUtills_ResolvePath(): "); + COMMON_LOG_DEBUG(Common_Get_Error_Message(COMMON_ERROR_INVALID_ARGUMENT)); + COMMON_LOG_DEBUG(" given path argument has a NULL character before the end of the buffer."); + } + else { - // Blank out the allocated memory. - memset(buffer, '\0', realBufferLength); - memset(checkBuffer, '\0', realBufferLength); + // Copy the data. + outputStr[outputStrSize] = path[outputStrSize]; + } + } - // Call readlink() for the first buffer. - firstBufferLength = readlink(PROC_PATH, buffer, realBufferLength); + // Check for success. + if ((pathSize == outputStrSize) && (ret == COMMON_ERROR_UNKNOWN_ERROR)) + { + // Begin resolution loop. + for (numOfResolveAttempts = 0; ((ret == FILEUTILLS_ERROR_PATH_IS_A_SYMLINK) && (numOfResolveAttempts < (FileUtills::Get_Max_Symlink_Depth()))); numOfResolveAttempts++) + { + // Resolve the given path. + ret = FileUtills::ResolvePath_Helper(outputStr, &outputStrSize); - // Check bufferLength. - if (firstBufferLength >= 0) + // Check for error. + if (ret == COMMON_ERROR_SUCCESS) { - // Check to see if we got the entire path. - if (firstBufferLength < realBufferLength) + // Check for valid result. + if ((outputStr != NULL) && (outputStrSize > 0)) { - // Call readlink() for the second buffer. - secondBufferLength = readlink(PROC_PATH, checkBuffer, realBufferLength); + // Check to see if the path is a symbolic link. + ret = FileUtills::IsFileOrDirectory_Helper(outputStr, outputStrSize); - // Check secondBufferLength. - if (secondBufferLength >= 0) + // Check the result. + switch (ret) { - // Check to see if we got the entire path. - if (secondBufferLength == firstBufferLength) - { - // Call memcmp(). - if (memcmp(buffer, checkBuffer, realBufferLength) == 0) + case COMMON_ERROR_SUCCESS: // System specific (unchecked) filesystem entry type. + case FILEUTILLS_ERROR_PATH_IS_A_DIRECTORY: + case FILEUTILLS_ERROR_PATH_IS_A_FILE: + // Success. + ret = COMMON_ERROR_SUCCESS; + break; + case FILEUTILLS_ERROR_PATH_IS_A_SYMLINK: + // Check and see if we are resolving symbolic links. + if (!disableSymLinkResolution) { - // Paths match, deallocate the second buffer. - if (checkBuffer != NULL) + // OK, Resolve the symbolic link. + ret = FileUtills::ResolveSystemSymoblicLink_Syscall(outputStr, outputStrSize, &tempLinkBuf, &tempLinkBufSize); + if (ret == COMMON_ERROR_SUCCESS) { - free(checkBuffer); - checkBuffer = NULL; - } + // Check for success without result. + if ((tempLinkBuf != NULL) && (tempLinkBufSize > 0)) + { + // OK, we need to determine if the resolved symbolic link is a relative path or an absolute path. + ret = FileUtills::IsAbsolutePathReference(tempLinkBuf, tempLinkBufSize); - // Copy the first buffer to the result. - result = buffer; + // Check for absolute path result. + if (ret == FILEUTILLS_ERROR_PATH_IS_ABSOLUTE) + { + // Replace the result with the absolute path. + free(outputStr); + outputStr = tempLinkBuf; + outputStrSize = tempLinkBufSize; + } + else + { + // Check for relative path. + if (ret == FILEUTILLS_ERROR_PATH_IS_RELATIVE) + { + // Remove the symlink from the outputStr. + ret = FileUtills::RemoveLastPathSegment(outputStr, outputStrSize); + if (ret == COMMON_ERROR_SUCCESS) + { + // Reallocate the buffer to store the relative path. + ret = FileUtills_Reallocate_CString_Buffer(outputStr, outputStrSize, (outputStrSize + tempLinkBufSize)); + if (ret == COMMON_ERROR_SUCCESS) + { + // Reset ret. + ret = COMMON_ERROR_UNKNOWN_ERROR; + + // Append the relative path to the result. + for (size_t x = outputStrSize; ((x < (outputStrSize + tempLinkBufSize)) && (ret == COMMON_ERROR_UNKNOWN_ERROR)); x++) + { + // Check for NULL. + if ((tempLinkBuf[x] == '\0') && ((x + 1) != (outputStrSize + tempLinkBufSize))) + { + // Alright, the tempLinkBuf should NOT have a NULL character in the middle of the buffer. + ret = COMMON_ERROR_INTERNAL_ERROR; + COMMON_LOG_DEBUG("FileUtills_ResolvePath(): "); + COMMON_LOG_DEBUG(Common_Get_Error_Message(COMMON_ERROR_INTERNAL_ERROR)); + COMMON_LOG_DEBUG(" invalid NULL character found in the middle of a resolved symbolic link's buffer."); + } + else + { + // Copy the data. + outputStr[x] = tempLinkBuf[x]; + } + } + } + else + { + // An error occured while reallocating the buffer. + if (ret == COMMON_ERROR_MEMORY_ERROR) + { + // Unable to allocate memory for buffer reallocation. + COMMON_LOG_DEBUG("FileUtills_ResolvePath(): "); + COMMON_LOG_DEBUG(Common_Get_Error_Message(COMMON_ERROR_MEMORY_ERROR)); + COMMON_LOG_DEBUG(" out of usable memory. Cannot reallocate buffer for addition of relative path."); + } + else + { + // All other errors. + COMMON_LOG_DEBUG("FileUtills_ResolvePath(): "); + COMMON_LOG_DEBUG(Common_Get_Error_Message(ret)); + COMMON_LOG_DEBUG(" unable to reallocate output buffer for addition of relative path. Please report this bug."); + ret = COMMON_ERROR_INTERNAL_ERROR; + } + } + } + else + { + // Unable to remove the last path segment. + COMMON_LOG_DEBUG("FileUtills::ResolvePath(): "); + COMMON_LOG_DEBUG(Common_Get_Error_Message(COMMON_ERROR_INTERNAL_ERROR)); + COMMON_LOG_DEBUG(" Call to path segment removal function failed. Please report this bug."); + ret = COMMON_ERROR_INTERNAL_ERROR; + } + } + else + { + // This is any other error. + COMMON_LOG_DEBUG("FileUtills::ResolvePath(): "); + COMMON_LOG_DEBUG(Common_Get_Error_Message(ret)); + COMMON_LOG_DEBUG(" Unable to resolve the given path ( "); + COMMON_LOG_DEBUG(path); + COMMON_LOG_DEBUG(" ) Unable to determine the type of the symbolic link."); + ret = COMMON_ERROR_INTERNAL_ERROR; + } + } + } + else + { + // Success without result. + ret = COMMON_ERROR_INTERNAL_ERROR; - // Because the returned link is the actual executable, call GetParent(). - result = FileUtills::GetParent(result); - if (result.size() > 0) - { - // Clear Common::commonLastErrorCode. - Common::commonLastErrorCode = Common::COMMON_SUCCESS; + // Log the error. + COMMON_LOG_WARNING("FileUtills::ResolvePath(): "); + COMMON_LOG_WARNING(Common_Get_Error_Message(COMMON_ERROR_INTERNAL_ERROR)); + COMMON_LOG_WARNING(" Call to system symbolic link resolution function indicated success but did not give a result. Please report this bug."); + } } else { - // GetParent() failed. - Common::commonLastErrorCode = Common::COMMON_INTERNAL_ERROR; - COMMON_LOG_DEBUG("FileUtills::GetExecDirectory(): "); - COMMON_LOG_DEBUG(Common::Get_Error_Message(Common::commonLastErrorCode)); - COMMON_LOG_DEBUG(" Call to GetParent() failed.\n"); - result = ""; + // OK an error occured report and log it. + if (ret == COMMON_ERROR_INVALID_ARGUMENT) + { + // This is an internal engine error. + ret = COMMON_ERROR_INTERNAL_ERROR; + COMMON_LOG_WARNING("FileUtills_ResolvePath(): "); + COMMON_LOG_WARNING(Common_Get_Error_Message(COMMON_ERROR_INTERNAL_ERROR)); + COMMON_LOG_WARNING(" Call to system symbolic link resolution function failed with the given path ( "); + COMMON_LOG_WARNING(outputStr); + COMMON_LOG_WARNING(" ) Please report this bug."); + } + else + { + // This is any other error. + COMMON_LOG_DEBUG("FileUtills_ResolvePath(): Unable to resolve the given path ( "); + COMMON_LOG_DEBUG(outputStr); + COMMON_LOG_DEBUG(" ) Unable to resolve system defined symbolic link."); + } } } - } - } - else - { - // Error. - errcpy = errno; - Common::commonLastErrorCode = Common::Translate_Posix_Errno_To_Common_Error_Code(errcpy); - COMMON_LOG_DEBUG("FileUtills::GetExecDirectory(): readlink() system call returned: "); - COMMON_LOG_DEBUG(Common::Get_Error_Message(Common::commonLastErrorCode)); - COMMON_LOG_DEBUG("\n"); - result = ""; - } + break; + default: + // OK an error occured report and log it. + if (ret == COMMON_ERROR_INVALID_ARGUMENT) + { + // This is an internal engine error. + ret = COMMON_ERROR_INTERNAL_ERROR; + COMMON_LOG_WARNING("FileUtills_ResolvePath(): "); + COMMON_LOG_WARNING(Common_Get_Error_Message(COMMON_ERROR_INTERNAL_ERROR)); + COMMON_LOG_WARNING(" Call to FileUtills_IsFileOrDirectory() failed with the given path ( "); + COMMON_LOG_WARNING(path); + COMMON_LOG_WARNING(" ) Please report this bug.\n"); + } + else + { + // This is any other error. + COMMON_LOG_DEBUG("FileUtills_ResolvePath(): Unable to resolve the given path ( "); + COMMON_LOG_DEBUG(path); + COMMON_LOG_DEBUG(" ) Unable to determine final path type.\n"); + } + break; + }; } - } - else - { - // Error. - errcpy = errno; - Common::commonLastErrorCode = Common::Translate_Posix_Errno_To_Common_Error_Code(errcpy); - COMMON_LOG_DEBUG("FileUtills::GetExecDirectory(): readlink() system call returned: "); - COMMON_LOG_DEBUG(Common::Get_Error_Message(Common::commonLastErrorCode)); - COMMON_LOG_DEBUG("\n"); - result = ""; - } - } + else + { + // Success without result. + ret = COMMON_ERROR_INTERNAL_ERROR; - // Deallocate any remaining buffers. - if (buffer != NULL) - { - free(buffer); - buffer = NULL; + // Log the error. + COMMON_LOG_WARNING("FileUtills_ResolvePath(): "); + COMMON_LOG_WARNING(Common_Get_Error_Message(COMMON_ERROR_INTERNAL_ERROR)); + COMMON_LOG_WARNING(" Call to helper function indicated success but did not give a result. Please report this bug.\n"); + } + } } - if (checkBuffer != NULL) + + // Check and see if the loop exited because we hit the resolution attempt limit. + if (numOfResolveAttempts >= FileUtills::Get_Max_Symlink_Depth()) { - free(checkBuffer); - checkBuffer = NULL; + // Resolve attempt limit reached. + ret = FILEUTILLS_ERROR_SYMLINK_CHAIN_TOO_DEEP; + + // Log the error. + COMMON_LOG_INFO("FileUtills_ResolvePath(): Unable to resolve the given path ( "); + COMMON_LOG_INFO(path); + COMMON_LOG_INFO(" ) "); + COMMON_LOG_INFO(Common_Get_Error_Message(FILEUTILLS_ERROR_SYMLINK_CHAIN_TOO_DEEP)); + COMMON_LOG_INFO("\n"); } } - - /* - * If we reach here, and Common::commonLastErrorCode == Common::COMMON_UNKNOWN_ERROR, - * then we have failed. (Most likely we ran out of reallocation attempts...) - */ - if (Common::commonLastErrorCode == Common::COMMON_UNKNOWN_ERROR) - { - /* - * Set COMMON_INTERNAL_ERROR. - * - * (The system most likely can fetch the link, - * but we need to limit the reallocation attempts - * to prevent issues. So it's not appropriate to use - * FILEUTILLS_PATH_LENGTH_INVALID.) - */ - Common::commonLastErrorCode = Common::COMMON_INTERNAL_ERROR; - COMMON_LOG_INFO("FileUtills::GetExecDirectory(): "); - COMMON_LOG_INFO(Common::Get_Error_Message(Common::commonLastErrorCode)); - COMMON_LOG_INFO(" executable path is too long to retrive due to engine limitation.\n"); - result = ""; - } } - catch(...) - { - // Exception thrown. - Common::commonLastErrorCode = Common::COMMON_EXCEPTION_THROWN; - COMMON_LOG_DEBUG("FileUtills::GetExecDirectory(): "); - COMMON_LOG_DEBUG(Common::Get_Error_Message(Common::commonLastErrorCode)); - COMMON_LOG_DEBUG("\n"); - result = ""; - } - } - else - { - // Internal error. (PROC_PATH is NOT a symbolic link.) - Common::commonLastErrorCode = Common::COMMON_INTERNAL_ERROR; - COMMON_LOG_DEBUG("FileUtills::GetExecDirectory(): "); - COMMON_LOG_DEBUG(Common::Get_Error_Message(Common::commonLastErrorCode)); - COMMON_LOG_DEBUG(" PROC_PATH is NOT a symbolic link.\n"); - } } else { - // lstat() Error. - errcpy = errno; - Common::commonLastErrorCode = Common::Translate_Posix_Errno_To_Common_Error_Code(errcpy); - COMMON_LOG_DEBUG("FileUtills::GetExecDirectory(): lstat() system call returned: "); - COMMON_LOG_DEBUG(Common::Get_Error_Message(Common::commonLastErrorCode)); - COMMON_LOG_DEBUG("\n"); - } -#endif - // Return result. - return result; -} - -std::string FileUtills::CheckPathType(const std::string & path) -{ - // Init vars. - std::string output = ""; - char charArray[1000]; // Used for the cwd function. - char * pCWD; // Used to store result of the getCWD function. - long int size = 0; // Size of path string. - - // Set size. - size = path.size(); - - // Check and see if a directory seperator is in the path. - if (path.find(DIR_SEP) == string::npos) - { - // Going with realtive path. - pCWD = getcwd(charArray, sizeof(charArray)); - output = pCWD; - output += DIR_SEP; - output += path; - return output; - } - - // Look for home '~'. - if (path.find_first_of('~') == 0) - { - // Get the home path. - pCWD = getenv("HOME"); - output = pCWD; - output += path.substr(1, size); + // Given path is invalid. + ret = COMMON_ERROR_INVALID_ARGUMENT; - // Remove the slash if it was added back. - output = RemoveTrailingSlash(output); - - // Return output. - return output; - } - - // Look for "./" (Relative) - if(path.find("./") == 0) - { - // Get current directory. - pCWD = getcwd(charArray, sizeof(charArray)); - output = pCWD; - - // Add a DIR_SEP to the string or we will mess up the directory name. - output += DIR_SEP; - - // Add data from the Directory string. - output += path.substr(2, size); - - // Remove the slash if it was added back. - output = RemoveTrailingSlash(output); - - // Return the output. - return output; - } + // Log the error. + COMMON_LOG_DEBUG("FileUtills::ResolvePath(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(COMMON_ERROR_INVALID_ARGUMENT)); + COMMON_LOG_DEBUG(" Given path is invalid.\n"); + } - // Look for absolute path. - if (path.find(DIR_SEP) == 0) - { - // Path is absolute. - return path; - } - else // If all else fails it must be relative. - { - // Assuming relative path. - pCWD = getcwd(charArray, sizeof(charArray)); - output = pCWD; - output += DIR_SEP; - output += path; - return output; - } + // If we do not have success, we need to deallocate the outputStr buffer. + if (ret != COMMON_ERROR_SUCCESS) + { + if (outputStr != NULL) + { + free(outputStr); + outputStr = NULL; + } + } - // Default return - return ""; + // Return the result. + return ret; } FileUtills::dirlist * FileUtills::getDirectory(const std::string & path, const bool & cleanList) { -#ifdef POSIX_COMMON_H - // Dumb check. - if (path.size() <= 0) - { - // Invalid path. - return NULL; - } - // Init vars. - FileUtills::dirlist * buffer; - struct dirent * dir; // '' - DIR * dp; // Directory stream to hold directory name..... (Why can't it just take a c string?) - std::string tempname = ""; // Used to store the filename / subdirectory name for the addToArray function. - - // Allocate the dirlist. - try{ - buffer = new FileUtills::dirlist; - } - catch(bad_alloc) - { - // Could not allocate struct. - return NULL; - } - - // Set the path. - buffer->path = path; + FileUtills::dirlist * ret = NULL; // Result of this function. + std::string absPath = ""; // Absolute version of the given path. - // Dump the path as a c string into the Directory stream object......(Overly complicated POS......) - - // Check and make sure we can open the directory first. - if ((dp = (opendir(path.c_str()))) == NULL) + // Resolve the given path. + absPath = FileUtills::ResolvePath(path); + if ((Common_commonLastErrorCode == COMMON_ERROR_SUCCESS) && (absPath.size() > 0)) { - // An error occured. - if (buffer != NULL) + // Call helper. + ret = FileUtills::getDirectory_Helper(absPath, cleanList); + if (Common_commonLastErrorCode != COMMON_ERROR_SUCCESS) { - delete buffer; - buffer = NULL; - } - - // Exit function. - return NULL; - } + // Check for a list. + if (ret != NULL) + { + delete ret; + ret = NULL; + } - // Start filesystem fetch loop. - while ((dir = readdir(dp))) // Call Host OS function. - { - // Check and see if the cleanList flag is set. - if (cleanList) + // Check for a INVALID_ARGUMENT error. + if (Common_commonLastErrorCode == COMMON_ERROR_INVALID_ARGUMENT) + { + // Set this to internal error. (The caller does not need to see the invalid argument error.) + Common_commonLastErrorCode = COMMON_ERROR_INTERNAL_ERROR; + } + } + else { - // Check to see if d_name is a POSIX directory shortcut. - if ((strcmp(dir->d_name, ".") == 0) || (strcmp(dir->d_name, "..") == 0)) + // Check for a success without result. + if (ret == NULL) { - // d_name is a directory shortcut, do not add it to the list. - continue; + // Set this to internal error. (The caller does not need to see the success without result error.) + Common_commonLastErrorCode = COMMON_ERROR_INTERNAL_ERROR; } } - - // Cast d_name to a string. - tempname = dir->d_name; - - // Add the data to the array. - buffer->list.push_back(tempname); } - - // Close the directory stream and reset it. - closedir(dp); - - // If we are cleaning the list, call DataProcess::DecrementingSort(). - if (DataProcess::DecrementingSort(buffer->list) != 0) + else { - // An exception was thrown in the DecrementingSort() function, bail out. - if (buffer != NULL) + // Log the error if needed. + COMMON_LOG_VERBOSE("FileUtills::getDirectory(): "); + COMMON_LOG_VERBOSE(Common::Get_Error_Message(Common_commonLastErrorCode)); + COMMON_LOG_VERBOSE("Unable to resolve the given path, aborting.\n"); + + /* + * Just in case for some reason Common_commonLastErrorCode + * was COMMON_ERROR_SUCCESS, and we got here because absPath.size() + * was less than or equal to (MINIMAL_VALID_ABSOLUTE_PATH_LENGTH + 1), + * make sure we set the correct error code. + */ + if ((Common_commonLastErrorCode == COMMON_ERROR_SUCCESS) && (absPath.size() <= 0)) { - delete buffer; - buffer = NULL; + // The error is an internal error. + Common_commonLastErrorCode = COMMON_ERROR_INTERNAL_ERROR; + COMMON_LOG_WARNING("FileUtills::getDirectory(): ResolvePath() returned an invalid path string, but indicated success. Please report this bug.\n"); } - - // Exit function. - return NULL; } - // Set the number of entries. - buffer->numOfEntries = buffer->list.size(); - - // Return the buffer. - return buffer; -#endif - // Default return for unimplemted function. - return NULL; + // Return the result. + return ret; } int FileUtills::GetGigaFreespace(const std::string & path, size_t & result) { - // Init ret. - int ret = Common::COMMON_FUNCTION_NOT_IMPLEMENTED; // The result of this function. - - // Call GetByteFreespace(). - ret = FileUtills::GetByteFreespace(path, result); + // Init vars. + int ret = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; // Result of this function. + std::string absPath = ""; // Absolute version of the given path. - // Check for success. - if (ret == Common::COMMON_SUCCESS) + // Resolve the given path. + absPath = FileUtills::ResolvePath(path); + if ((Common_commonLastErrorCode == COMMON_ERROR_SUCCESS) && (absPath.size() > 0)) { - // Byte conversion. - result = (result / ((double)1000000000)); + // Call helper. + ret = FileUtills::GetGigaFreespace_Helper(absPath, result); + if (ret != COMMON_ERROR_SUCCESS) + { + // Check for a INVALID_ARGUMENT error. + if (ret == COMMON_ERROR_INVALID_ARGUMENT) + { + // Set this to internal error. (The caller does not need to see the invalid argument error.) + ret = COMMON_ERROR_INTERNAL_ERROR; + } + } } + else + { + // Log the error if needed. + COMMON_LOG_VERBOSE("FileUtills::GetGigaFreespace(): "); + COMMON_LOG_VERBOSE(Common::Get_Error_Message(ret)); + COMMON_LOG_VERBOSE("Unable to resolve the given path, aborting.\n"); - // Return ret. + /* + * Just in case for some reason result + * was COMMON_SUCCESS, and we got here because absPath.size() + * was less than or equal to (MINIMAL_VALID_ABSOLUTE_PATH_LENGTH + 1), + * make sure we set the correct error code. + */ + if ((Common_commonLastErrorCode == COMMON_ERROR_SUCCESS) && (absPath.size() <= 0)) + { + // The error is an internal error. + result = COMMON_ERROR_INTERNAL_ERROR; + COMMON_LOG_WARNING("FileUtills::GetGigaFreespace(): ResolvePath() returned an invalid path string, but indicated success. Please report this bug.\n"); + } + } + + // Copy ret to Common_commonLastErrorCode. + Common_commonLastErrorCode = ret; + + // Return ret. return ret; } int FileUtills::GetFreespace(const std::string & path, size_t & result) { - // Init ret. - int ret = Common::COMMON_FUNCTION_NOT_IMPLEMENTED; // The result of this function. - - // Call GetByteFreespace(). - ret = FileUtills::GetByteFreespace(path, result); + // Init vars. + int ret = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; // Result of this function. + std::string absPath = ""; // Absolute version of the given path. - // Check for success. - if (ret == Common::COMMON_SUCCESS) + // Resolve the given path. + absPath = FileUtills::ResolvePath(path); + if ((Common_commonLastErrorCode == COMMON_ERROR_SUCCESS) && (absPath.size() > 0)) + { + // Call helper. + ret = FileUtills::GetFreespace_Helper(absPath, result); + if (ret != COMMON_ERROR_SUCCESS) + { + // Check for a INVALID_ARGUMENT error. + if (ret == COMMON_ERROR_INVALID_ARGUMENT) + { + // Set this to internal error. (The caller does not need to see the invalid argument error.) + ret = COMMON_ERROR_INTERNAL_ERROR; + } + } + } + else { - // Byte conversion. - result = (result / ((double)1000000)); + // Log the error if needed. + COMMON_LOG_VERBOSE("FileUtills::GetFreespace(): "); + COMMON_LOG_VERBOSE(Common::Get_Error_Message(ret)); + COMMON_LOG_VERBOSE("Unable to resolve the given path, aborting.\n"); + + /* + * Just in case for some reason result + * was COMMON_SUCCESS, and we got here because absPath.size() + * was less than or equal to (MINIMAL_VALID_ABSOLUTE_PATH_LENGTH + 1), + * make sure we set the correct error code. + */ + if ((Common_commonLastErrorCode == COMMON_ERROR_SUCCESS) && (absPath.size() <= 0)) + { + // The error is an internal error. + result = COMMON_ERROR_INTERNAL_ERROR; + COMMON_LOG_WARNING("FileUtills::GetFreespace(): ResolvePath() returned an invalid path string, but indicated success. Please report this bug.\n"); + } } + // Copy ret to Common_commonLastErrorCode. + Common_commonLastErrorCode = ret; + // Return ret. return ret; } int FileUtills::GetKiloFreespace(const std::string & path, size_t & result) { - // Init ret. - int ret = Common::COMMON_FUNCTION_NOT_IMPLEMENTED; // The result of this function. - - // Call GetByteFreespace(). - ret = FileUtills::GetByteFreespace(path, result); + // Init vars. + int ret = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; // Result of this function. + std::string absPath = ""; // Absolute version of the given path. - // Check for success. - if (ret == Common::COMMON_SUCCESS) + // Resolve the given path. + absPath = FileUtills::ResolvePath(path); + if ((Common_commonLastErrorCode == COMMON_ERROR_SUCCESS) && (absPath.size() > 0)) + { + // Call helper. + ret = FileUtills::GetKiloFreespace_Helper(absPath, result); + if (ret != COMMON_ERROR_SUCCESS) + { + // Check for a INVALID_ARGUMENT error. + if (ret == COMMON_ERROR_INVALID_ARGUMENT) + { + // Set this to internal error. (The caller does not need to see the invalid argument error.) + ret = COMMON_ERROR_INTERNAL_ERROR; + } + } + } + else { - // Byte conversion. - result = (result / ((double)1000)); + // Log the error if needed. + COMMON_LOG_VERBOSE("FileUtills::GetKiloFreespace(): "); + COMMON_LOG_VERBOSE(Common::Get_Error_Message(ret)); + COMMON_LOG_VERBOSE("Unable to resolve the given path, aborting.\n"); + + /* + * Just in case for some reason result + * was COMMON_SUCCESS, and we got here because absPath.size() + * was less than or equal to (MINIMAL_VALID_ABSOLUTE_PATH_LENGTH + 1), + * make sure we set the correct error code. + */ + if ((Common_commonLastErrorCode == COMMON_ERROR_SUCCESS) && (absPath.size() <= 0)) + { + // The error is an internal error. + result = COMMON_ERROR_INTERNAL_ERROR; + COMMON_LOG_WARNING("FileUtills::GetKiloFreespace(): ResolvePath() returned an invalid path string, but indicated success. Please report this bug.\n"); + } } + // Copy ret to Common_commonLastErrorCode. + Common_commonLastErrorCode = ret; + // Return ret. return ret; } @@ -673,1947 +833,1467 @@ int FileUtills::GetKiloFreespace(const std::string & path, size_t & result) int FileUtills::GetByteFreespace(const std::string & path, size_t & result) { // Init vars. - int ret = Common::COMMON_FUNCTION_NOT_IMPLEMENTED; // Result of this function. -#ifdef POSIX_COMMON_H - struct statvfs * buffer = NULL; // Buffer used to get filesystem info from the OS. - - // Reset result. - result = 0; + int ret = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; // Result of this function. + std::string absPath = ""; // Absolute version of the given path. - // Begin try block. - try { - // Create buffer. - buffer = new struct statvfs; - if (buffer != NULL) + // Resolve the given path. + absPath = FileUtills::ResolvePath(path); + if ((Common_commonLastErrorCode == COMMON_ERROR_SUCCESS) && (absPath.size() > 0)) + { + // Call helper. + ret = FileUtills::GetByteFreespace_Helper(absPath, result); + if (ret != COMMON_ERROR_SUCCESS) { - // Call host's function, and check for error. - if (statvfs(path.c_str(), buffer) == 0) - { - // Determine number of free bytes. (Number of avaiable blocks * block size) - result = (buffer->f_bavail * buffer->f_bsize); - - // Set success. - ret = Common::COMMON_SUCCESS; - } - else + // Check for a INVALID_ARGUMENT error. + if (ret == COMMON_ERROR_INVALID_ARGUMENT) { - // Figure out what the error we got back was. - ret = errno; - ret = Common::Translate_Posix_Errno_To_Common_Error_Code(ret); - - // Log the error. - COMMON_LOG_DEBUG("FileUtills::GetByteFreespace(): "); - COMMON_LOG_DEBUG(Common::Get_Error_Message(ret)); - COMMON_LOG_DEBUG("\n"); + // Set this to internal error. (The caller does not need to see the invalid argument error.) + ret = COMMON_ERROR_INTERNAL_ERROR; } - - // Delete the buffer - delete buffer; - buffer = NULL; - } - else - { - // Could not allocate memory. - ret = Common::COMMON_MEMORY_ERROR; - - // Log the error. - COMMON_LOG_DEBUG("FileUtills::GetByteFreespace(): "); - COMMON_LOG_DEBUG(Common::Get_Error_Message(ret)); - COMMON_LOG_DEBUG("\n"); } } - catch (exception &ex) + else { - // Exception thrown. - ret = Common::COMMON_EXCEPTION_THROWN; + // Log the error if needed. + COMMON_LOG_VERBOSE("FileUtills::GetByteFreespace(): "); + COMMON_LOG_VERBOSE(Common::Get_Error_Message(ret)); + COMMON_LOG_VERBOSE("Unable to resolve the given path, aborting.\n"); - // Check for allocated buffer. - if (buffer != NULL) + /* + * Just in case for some reason result + * was COMMON_SUCCESS, and we got here because absPath.size() + * was less than or equal to (MINIMAL_VALID_ABSOLUTE_PATH_LENGTH + 1), + * make sure we set the correct error code. + */ + if ((Common_commonLastErrorCode == COMMON_ERROR_SUCCESS) && (absPath.size() <= 0)) { - delete buffer; - buffer = NULL; + // The error is an internal error. + result = COMMON_ERROR_INTERNAL_ERROR; + COMMON_LOG_WARNING("FileUtills::GetByteFreespace(): ResolvePath() returned an invalid path string, but indicated success. Please report this bug.\n"); } - - // Log the error. - COMMON_LOG_VERBOSE("FileUtills::GetByteFreespace(): "); - COMMON_LOG_VERBOSE(Common::Get_Error_Message(ret)); - COMMON_LOG_VERBOSE(" "); - COMMON_LOG_VERBOSE(ex.what()); - COMMON_LOG_VERBOSE("\n"); } -#endif - // Copy ret to Common::commonLastErrorCode. - Common::commonLastErrorCode = ret; + + // Copy ret to Common_commonLastErrorCode. + Common_commonLastErrorCode = ret; // Return ret. return ret; } -short FileUtills::CreateDirectory(const std::string & directory, Panic::ERROR & error, const bool & createRecursive) +int FileUtills::CreateDirectory(const std::string & directory, const bool & createRecursive) { -#ifdef POSIX_COMMON_H // Init vars. - std::string buffer = ""; // Used to store the current directory path. - std::string parentbuffer = ""; // Used to store the parent directory's path. - std::string realpath = ""; // Used to store the real directory path if a relative path or a user path is given instead of an absolute path. - int errorcode = 0; // Used to store return error codes. - size_t position = 0; // Used to store current search position in buffer. - size_t size = 0; // Used to store the size of the path string - int permission = 0; // Used to store return code from FileUtills::CheckPermissions(). - bool skiploop = false; // Used to control the recursive directory creation loop. - bool isrelative = false; // Used to tell if the path is relative or abosulute. - bool isHome = false; // Used to tell if the path is in a user's home directory. - char charArray[1000]; // Used for the cwd function. - char * pCWD; // Used to store result of the getCWD function. - - // Check to see if the full directory path already exists. - if (FileUtills::DoesExist(directory, error) == true) - { - // Directory already exists thus return true. - return -3; - } - - // Check for a directory seperator on the end of the path and remove it if it is found. - buffer = RemoveTrailingSlash(directory); - - // Get the size of the buffer string. - size = buffer.size(); - - // Determine if we have a relative path or a absolute one. - if (buffer.find_first_of(DIR_SEP) == 0) - { - isrelative = false; - } + int result = COMMON_ERROR_UNKNOWN_ERROR; // Used to hold the result of this function. + std::string absPath = ""; // Used to store the current directory path. - if (buffer.find("./") == 0) // BUG: this should not be called when string != "./". + // Check to see if the full directory path already exists. + if (FileUtills::DoesExist(directory) != true) { - // Ok relative path get the full path - isrelative = true; - pCWD = getcwd(charArray, sizeof(charArray)); - buffer = pCWD; - - buffer += directory.substr(1, size); - - // Remove the slash if it was added back. - buffer = RemoveTrailingSlash(buffer); + // Check for a directory seperator on the end of the path and remove it if it is found. + absPath = RemoveTrailingSlash(directory); - // Copy it to the realpath. - realpath = buffer; + // Get the absolute version of the path to create. + absPath = FileUtills::ResolvePath(absPath); + // Check the result. + if ((Common_commonLastErrorCode == COMMON_ERROR_SUCCESS) && (absPath.size() > (MINIMAL_VALID_ABSOLUTE_PATH_LENGTH + 1))) + { + // Call helper. + result = FileUtills::CreateDirectory_Helper(absPath, createRecursive); + if (result != COMMON_ERROR_SUCCESS) + { + // Check for a INVALID_ARGUMENT error. + if (result == COMMON_ERROR_INVALID_ARGUMENT) + { + // Set this to internal error. (The caller does not need to see the invalid argument error.) + result = COMMON_ERROR_INTERNAL_ERROR; + } + } + } + else + { + // Could not get absolute path to create. + COMMON_LOG_VERBOSE("FileUtills::CreateDirectory(): Could not get absolute path to create, aborting.\n"); + + /* + * Just in case for some reason result + * was COMMON_SUCCESS, and we got here because absPath.size() + * was less than or equal to (MINIMAL_VALID_ABSOLUTE_PATH_LENGTH + 1), + * make sure we set the correct error code. + */ + if ((Common_commonLastErrorCode == COMMON_ERROR_SUCCESS) && (absPath.size() <= (MINIMAL_VALID_ABSOLUTE_PATH_LENGTH + 1))) + { + // The error is an internal error. + result = COMMON_ERROR_INTERNAL_ERROR; + COMMON_LOG_WARNING("FileUtills::CreateDirectory(): ResolvePath() returned an invalid path string, but indicated success. Please report this bug.\n"); + } + } } - - // Also check if it's in a user's home subdirectory. - if (buffer.find_first_of('~') == 0) + else { - // Ok user path, get the full path. - isHome = true; - pCWD = getenv("HOME"); - buffer = pCWD; - buffer += directory.substr(1, size); - - // remove the slash if it was added back. - buffer = RemoveTrailingSlash(buffer); - - // Copy it to the real path. - realpath = buffer; + // Directory already exists thus return true. + result = FILEUTILLS_ERROR_EXISTANT; } - // Assume relative if we have something else here. - if (buffer.find_first_of(DIR_SEP) != 0 && isHome == false && isrelative == false) // BUG: This does not get called. - { - // Set isrelative to true and retrive the current working directory. - isrelative = true; - pCWD = getcwd(charArray, sizeof(charArray)); - buffer = pCWD; - - // Add a DIR_SEP to the string or we will mess up the directory name. - buffer += DIR_SEP; - - // Add all data from the Directory string because the string does not have a DIR_SEP at position zero. - buffer += directory.substr(0, size); - - // Remove the slash if it was added back. - buffer = RemoveTrailingSlash(buffer); - - // Copy it to the realpath. - realpath = buffer; - } + // Copy result to commonLastErrorCode. + Common_commonLastErrorCode = result; - // Get the parent directory out of the buffer and store it for later. - position = buffer.find_last_of(DIR_SEP); - parentbuffer = buffer.substr(0, position); - - // Check and see if the parent directory exists. - errorcode = FileUtills::CheckParent(directory); // Switch - - switch (errorcode) { - case -1: // Can't write to the parent directory exit the function. - error.PanicHandler("FileUtills::CreateDirectory : Parent Directory not writable. will not create directory."); - return -1; - permission = 0; - break; - case -2: // Parent Directory does not exist, - if (createRecursive == false) - { - // Don't create the directory structure. - error.PanicHandler("FileUtills::CreateDirectory : Parent Directory does not exist. createRecursive is false, will not create directory."); - return -2; - } - break; - - case 0: // Parent Directory does exist and is writeable. - // since we can write to the directory skip the loop. - skiploop = true; - break; - default: // Ether there was an unknown error or this Arch / OS is not supported. ether way return -4. - return -4; - errorcode = 0; - break; - } + // Return the result. + return result; +} - // Clear the vars for the recursive directory creation loop. - permission = 0; - position = 0; - errorcode = 0; +int FileUtills::CheckPermissions(const std::string & path, const bool & read, const bool & write, const bool & exec) +{ + // Init vars. + int ret = COMMON_ERROR_SUCCESS; // The result of this function. + std::string absPath = ""; // The absolute path of the given path. - // Set buffer so we can check the path correctly. - // If we have a relative or user path use the real path. - if (isHome == true || isrelative == true) + // Call ResolvePath(). + absPath = FileUtills::ResolvePath(path); + if ((Common_commonLastErrorCode == COMMON_ERROR_SUCCESS) && (absPath.size() > 0)) { - buffer = realpath.substr(0, (realpath.find_first_of( DIR_SEP , 1))); - - // Also set the size of the string correctly. - size = realpath.size(); + // Call helper function. + ret = FileUtills::CheckPermissions_Helper(absPath, read, write, exec); + if (ret != COMMON_ERROR_SUCCESS) + { + // Check for a INVALID_ARGUMENT error. + if (ret == COMMON_ERROR_INVALID_ARGUMENT) + { + // Set this to internal error. (The caller does not need to see the invalid argument error.) + ret = COMMON_ERROR_INTERNAL_ERROR; + } + } } else { - // Otherwise use the directory string. - buffer = directory.substr(0, (directory.find_first_of( DIR_SEP, 1))); - - // Also set the size of the string correctly. - size = directory.size(); - } + // Call to ResolvePath() failed. + COMMON_LOG_VERBOSE("FileUtils::CheckPermissions(): Unable to resolve the given path, aborting.\n"); - // If the parent directory does not exist and createRecursive is true then begin main loop. - while (skiploop != true) - { - // If we are at position 0 and there is a DIR_SEP there incremnt position by one. - if (position == 0 && buffer.find_first_of(DIR_SEP) == 0) + // Make sure Common_commonLastErrorCode is set to something. + if (absPath.size() <= 0) { - // Incremnt the position by one. - position++; + ret = COMMON_ERROR_INTERNAL_ERROR; + COMMON_LOG_WARNING("FileUtills::CheckPermissions(): ResolvePath() returned an invalid path string, but indicated success. Please report this bug.\n"); } + } - // Start with root directory and run though the following until we reach the requested directory. + // Copy ret to Common_commonLastErrorCode. + Common_commonLastErrorCode = ret; - if (isHome == true || isrelative == true) // If true use realpath - { - if ((position = realpath.find_first_of(DIR_SEP, position)) == string::npos) - { - // This is the requested directory so exit the loop. - skiploop = true; - break; - } - } - else // Otherwise use directory. + // Return the result. + return ret; +} + +int FileUtills::DoesExist(const std::string & path) +{ + // Declare some vars. + int ret = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; // Holds common namepspace error code. + std::string absPath = ""; // Holds the abosolute value of the given path. + + // Call ResolvePath(). + absPath = FileUtills::ResolvePath(path); + if ((Common_commonLastErrorCode == COMMON_ERROR_SUCCESS) && (absPath.size() > 0)) + { + // Call helper function. + ret = FileUtills::DoesExist_Helper(absPath); + if (ret != COMMON_ERROR_SUCCESS) { - if ((position = directory.find_first_of(DIR_SEP, position)) == string::npos) + // Check for a INVALID_ARGUMENT error. + if (ret == COMMON_ERROR_INVALID_ARGUMENT) { - // This is the requested directory so exit the loop. - skiploop = true; - break; + // Set this to internal error. (The caller does not need to see the invalid argument error.) + ret = COMMON_ERROR_INTERNAL_ERROR; } } + } + else + { + // Call to ResolvePath() failed. + COMMON_LOG_VERBOSE("FileUtils::DoesExist(): Call to FileUtills::ResolvePath() failed, aborting.\n"); - // Do a sanity check for the size of the string. - if (position < 0 || position > size) + // Make sure Common_commonLastErrorCode is set to something. + if (absPath.size() <= 0) { - // Ok something went wrong. - return -4; + ret = COMMON_ERROR_INTERNAL_ERROR; + COMMON_LOG_WARNING("FileUtills::DoesExist(): ResolvePath() returned an invalid path string, but indicated success. Please report this bug.\n"); } + } + + // Copy ret to Common_commonLastErrorCode. + Common_commonLastErrorCode = ret; + + // Default return. + return ret; +} - // Dump the last buffer into the parentdirectory buffer. - parentbuffer = buffer; +int FileUtills::IsFileOrDirectory(const std::string & path) +{ + // Init result. + int result = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; // Result of this function. (Defaults to function not implemetated.) + std::string absPath = ""; // The absolute path of the given path argument. - // Cut up the directory string so we can check for it. + // Make sure that the path is not empty. + if (path.size() > 0) + { + // Get the absolute path of the given path argument. + absPath = FileUtills::ResolvePath(path); - if (isHome == true || isrelative == true) + // Check for success. + if ((Common_commonLastErrorCode == COMMON_ERROR_SUCCESS) && (absPath.size() > 0)) { - buffer = realpath.substr(0, position); + // Call Helper function. + result = FileUtills::IsFileOrDirectory_Helper(absPath); + if (result != COMMON_ERROR_SUCCESS) + { + // Check for a INVALID_ARGUMENT error. + if (result == COMMON_ERROR_INVALID_ARGUMENT) + { + // Set this to internal error. (The caller does not need to see the invalid argument error.) + result = COMMON_ERROR_INTERNAL_ERROR; + } + } } else { - buffer = directory.substr(0, position); - } - - // Do Check. - errorcode = FileUtills::DoesExist(buffer, error); + // Unable to generate absolute path. + COMMON_LOG_DEBUG("FileUtills::IsFileOrDirectory(): Unable to get absolute path, aborting.\n"); - switch (errorcode){ - case -1: // Directory does not exist on system. - // Check and see if we can create it. - permission = FileUtills::CheckPermissions(parentbuffer, error); + // Make sure Common_commonLastErrorCode is set to a valid error code. + if (absPath.size() <= 0) + { + result = COMMON_ERROR_INTERNAL_ERROR; + COMMON_LOG_WARNING("FileUtills::IsFileOrDirectory(): ResolvePath() returned an invalid path string, but indicated success. Please report this bug.\n"); + } + } + } + else + { + // Empty path. + result = COMMON_ERROR_INVALID_ARGUMENT; - switch (permission){ - case -1: - // Permission Check Failed. - return false; - break; + // Log the error. + COMMON_LOG_DEBUG("FileUtills::IsFileOrDirectory(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(result)); + COMMON_LOG_DEBUG(" given path argument is invalid."); + } - case 0: - // Ok try and create the directory. - if ((errorcode = (mkdir(buffer.c_str(), S_IRWXU))) != 0) - { - // An error ocurred find out what. + // Copy result to commonLastErrorCode. + Common_commonLastErrorCode = result; - switch (errno) { - case EACCES: // Permission error. - return -1; - break; - case EEXIST: // Path exists on system. - return -3; - break; - case ENOSPC: // Out of disk space. - return -2; - break; - default: // We really don't care about the other errors. - return -4; - break; - } - } + // Exit function. + return result; +} - // Update the position counter. - position++; +int FileUtills::CheckParent(const std::string & path, const bool & read, const bool & write, const bool & exec) +{ + // Init vars. + int result = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; // Result of this function. + std::string absPath = path; // Absolute version of the given path. - // Check and see if that was the last directory to create. - if (isHome == true || isrelative == true) + // Check and see if the length is zero. + if (absPath.size() > 0) + { + // Get the absolute path. + absPath = FileUtills::ResolvePath(absPath); + if (Common_commonLastErrorCode == COMMON_ERROR_SUCCESS) + { + // Call helper. + result = FileUtills::CheckParent_Helper(absPath, read, write, exec); + if (result != COMMON_ERROR_SUCCESS) { - // Check realpath. - if (buffer == realpath) + // Check for a INVALID_ARGUMENT error. + if (result == COMMON_ERROR_INVALID_ARGUMENT) { - skiploop = true; - return 0; + // Set this to internal error. (The caller does not need to see the invalid argument error.) + result = COMMON_ERROR_INTERNAL_ERROR; } } - // Otherwise check the directory buffer. - if (buffer == directory) - { - skiploop = true; - return 0; - } - break; - - default: - // Bad errorcode exit function. - return -4; - break; - } - permission = 0; - errorcode = 0; - break; - - case 0: // Ok directory does exist. - position++; - break; - - default: - // Bad error code exit function. - return -4; } + else + { + // Call to ResolvePath() failed. + COMMON_LOG_VERBOSE("FileUtills::CheckParent(): Could not resolve the parent path. Unable to check parent's existance / permissions.\n"); + } + } + else + { + // Invalid path. + result = COMMON_ERROR_INVALID_ARGUMENT; + COMMON_LOG_VERBOSE("FileUtills::CheckParent(): "); + COMMON_LOG_VERBOSE(Common::Get_Error_Message(result)); + COMMON_LOG_VERBOSE(" Given path is invalid, aborting.\n"); + } + // Copy result to commonLastErrorCode. + Common_commonLastErrorCode = result; + // Return the result. + return result; +} - // If the next directory does exist then skip the remaining portion of the checks and restart with the next directory. - - // If the next directory does not exist the check the permissions of this one. +std::string FileUtills::GetParent(const std::string & path) +{ + // Init vars. + std::string parentbuffer = ""; + size_t length = 0; + size_t location = 0; - // If we can write to this directory then create the directory. +#ifdef POSIX_COMMON_H + // Remove the trailing slash if present. + parentbuffer = RemoveTrailingSlash(path); - // If the directory creation was successful then check and see what to do next. + // Check the Path for absolute path. + parentbuffer = FileUtills::ResolvePath(parentbuffer); - // If we have created the requested directory exit the function - //return true. + // Check the length of the path. + length = parentbuffer.length(); - // If we have not created the requested directory contiune loop with the next - // directory. + // Check and see if the length is zero. + if (length == 0) + { + // Nothing to do so return that the path does not exist. (It clearly does not exist.) + parentbuffer = ""; + return parentbuffer; + } - // If we encountered a fatal error exit the function return false. + // Locate the path seperator before the last directory / file name. + location = parentbuffer.find_last_of(DIR_SEP); - // If we can't write to this directory exit the function, return false. + // Check and make sure that the location of the dir sep is inside the string + if (location > length || length < 0 || location < 0) + { + // Memory error or someone is fucking with us. + // Either way kill the function + parentbuffer = ""; + return parentbuffer; + } - // If the permission check fails with a fatal error exit the function return false. + // Check and see if the parentbuffer is a root directory + if (length > 1) + { + // Get the parent directory path. + // Note substr CAN throw an exception. so we need to put this in a try catch block. + try{ + parentbuffer = parentbuffer.substr(0, location); + } + catch(exception &ex) + { + // If we end up here we're in trouble. + // Kill the function to be safe. + parentbuffer = ""; + return parentbuffer; + } - // If the existance check fails exit the function, return false. - } + // Now rerun the check for a dir sep on the end. + parentbuffer = RemoveTrailingSlash(parentbuffer); + // Exit function. + return parentbuffer; + } +#endif + // arch / OS not supported. + parentbuffer = ""; + return parentbuffer; - //If we have a relative or user path use realpath. - if (isHome == true || isrelative == true) - { - buffer = realpath; - } - else // Otherwise use the directory string. - { +} - buffer = directory; - } +int FileUtills::DeletePath(const std::string & path, const bool & recursive) +{ + // Init vars. + int result = COMMON_ERROR_UNKNOWN_ERROR; // Used to store results from calls to other functions. + std::string absPath = ""; // Used to contain the top level absolute path. - // Ok try and create the directory. - if ((errorcode = (mkdir(buffer.c_str(), S_IRWXU))) != 0) + // Avoid running ResolvePath() if the given path argument is empty. + if (path.size() > 0) { - // An error ocurred find out what. - - switch (errno) { - case EACCES: // Permission error. - return -1; - break; - case EEXIST: // Path exists on system. - return -5; - break; - case ENOSPC: // Out of disk space. - return -4; - break; - default: // We really don't care about the other errors. - return -6; - break; + // Get the absolute path. + absPath = FileUtills::ResolvePath(path); + + // Make sure we got the path. + if ((Common_commonLastErrorCode == COMMON_ERROR_SUCCESS) && (absPath.size() > 0)) + { + // Call helper. + result = FileUtills::DeletePath_Helper(path, recursive); + if (result != COMMON_ERROR_SUCCESS) + { + // Check for a INVALID_ARGUMENT error. + if (result == COMMON_ERROR_INVALID_ARGUMENT) + { + // Set this to internal error. (The caller does not need to see the invalid argument error.) + result = COMMON_ERROR_INTERNAL_ERROR; + } + } + } + else + { + // Log the error. + COMMON_LOG_INFO("FileUtills::DeletePath(): Unable to delete ( "); + COMMON_LOG_INFO(absPath.c_str()); + COMMON_LOG_INFO(" ) Path resolution failed with error: "); + if ((Common_commonLastErrorCode == COMMON_ERROR_SUCCESS) && (absPath.size() <= 0)) + { + // Internal error. + result = COMMON_ERROR_INTERNAL_ERROR; + COMMON_LOG_INFO(Common::Get_Error_Message(result)); + COMMON_LOG_INFO("\n"); + COMMON_LOG_WARNING("FileUtills::DeletePath(): ResolvePath() returned an empty / invalid absolute path while indicating success, Please report this bug."); + } + else + { + // Preserve the error code from ResolvePath(). + result = Common_commonLastErrorCode; + COMMON_LOG_INFO(Common::Get_Error_Message(result)); + } + COMMON_LOG_INFO("\n"); } } - if (errorcode == 0) + else { - return 0; + // Invalid path argument. + result = COMMON_ERROR_INVALID_ARGUMENT; + COMMON_LOG_DEBUG("FileUtills::DeletePath(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(result)); + COMMON_LOG_DEBUG(" Given path argument is empty.\n"); } -#endif - // If an implemetation does not exist for this platform then exit the function, return false. - return -3; + + // Copy result to Common_commonLastErrorCode. + Common_commonLastErrorCode = result; + + // Return the result. + return result; } -short FileUtills::CreateDirectory(const std::string & directory, const bool & createRecursive) +int FileUtills::CopyFile(const std::string & src, const std::string & dest, const bool & append, const streamsize & begOffset, const streamsize & endOffset) { -#ifdef POSIX_COMMON_H // Init vars. - std::string buffer = ""; // Used to store the current directory path. - std::string parentbuffer = ""; // Used to store the parent directory's path. - std::string realpath = ""; // Used to store the real directory path if a relative path or a user path is given instead of an absolute path. - int errorcode = 0; // Used to store return error codes. - size_t position = 0; // Used to store current search position in buffer. - size_t size = 0; // Used to store the size of the path string - int permission = 0; // Used to store return code from FileUtills::CheckPermissions(). - bool skiploop = false; // Used to control the recursive directory creation loop. - bool isrelative = false; // Used to tell if the path is relative or abosulute. - bool isHome = false; // Used to tell if the path is in a user's home directory. - char charArray[1000]; // Used for the cwd function. - char * pCWD; // Used to store result of the getCWD function. - - // Check to see if the full directory path already exists. - if (FileUtills::DoesExist(directory) == true) - { - // Directory already exists thus return true. - return -3; - } - - // Check for a directory seperator on the end of the path and remove it if it is found. - buffer = RemoveTrailingSlash(directory); - - // Get the size of the buffer string. - size = buffer.size(); - - // Determine if we have a relative path or a absolute one. - if (buffer.find_first_of(DIR_SEP) == 0) - { - isrelative = false; - } - - if (buffer.find("./") == 0) // BUG: this should not be called when string != "./". + int result = COMMON_ERROR_UNKNOWN_ERROR; // The result of this function. + size_t amountOfBytesToCopy = 0; // Used to hold the amount of bytes to copy from the source file. + size_t x = 0; // Used to control the outer copy loop. + size_t y = 0; // Used to control the inner input copy loop. + size_t z = 0; // Used to control the inner output copy loop. + const size_t bufferSize = 512; // Size of the buffer to allocate. + char * ioBuffer = NULL; // Used to hold data in a buffer while it is being copied. + std::string absPathSrc = ""; // Used to fetch the absolute path of src. + std::string absPathDest = ""; // Used to fetch the absolute path of dest. + std::fstream input; // File stream for the input (source) file. + std::fstream output; // File stream for the output (destionation) file. + + // Check Arguments. + if (src.size() > 0) { - // Ok relative path get the full path - isrelative = true; - pCWD = getcwd(charArray, sizeof(charArray)); - buffer = pCWD; - - buffer += directory.substr(1, size); - - // Remove the slash if it was added back. - buffer = RemoveTrailingSlash(buffer); + if (dest.size() > 0) + { + if (begOffset >= 0) + { + if (endOffset >= 0) + { + // Check and see if the offsets are valid. + if (((begOffset == 0) && (endOffset == 0)) || + ((begOffset == 0) && (endOffset > 0)) || + ((begOffset > 0) && (endOffset == 0)) || + ((begOffset > 0) && (endOffset > 0) && (endOffset > begOffset))) + { + // Set the amountOfBytesToCopy if we know the total amount. + if ((begOffset == 0) && (endOffset > 0)) + { + amountOfBytesToCopy = endOffset; + } + else + { + if ((begOffset > 0) && (endOffset > 0) && (endOffset > begOffset)) + { + amountOfBytesToCopy = (endOffset - begOffset); + } + } - // Copy it to the realpath. - realpath = buffer; + // Get absolute path for src. + absPathSrc = FileUtills::ResolvePath(src); - } + // Check for error. + if ((Common_commonLastErrorCode == COMMON_ERROR_SUCCESS) && (absPathSrc.size() > 0)) + { + // Get absolute path for dest. + absPathDest = FileUtills::ResolvePath(dest); - // Also check if it's in a user's home subdirectory. - if (buffer.find_first_of('~') == 0) - { - // Ok user path, get the full path. - isHome = true; - pCWD = getenv("HOME"); - buffer = pCWD; - buffer += directory.substr(1, size); + // Check for error. + if ((Common_commonLastErrorCode == COMMON_ERROR_SUCCESS) && (absPathDest.size() > 0)) + { + // Check and see if src is a regular file. + if (FileUtills::IsFileOrDirectory(absPathSrc) == FILEUTILLS_ERROR_PATH_IS_A_FILE) + { + // Check and see if dest exists. + FileUtills::IsFileOrDirectory(absPathDest); + if ((Common_commonLastErrorCode == FILEUTILLS_ERROR_NON_EXISTANT) || + (Common_commonLastErrorCode == FILEUTILLS_ERROR_PATH_IS_A_FILE)) + { + // Check to see if the parent directory exists. + result = FileUtills::CheckParent(absPathDest); + if (result == COMMON_ERROR_SUCCESS) + { + // Open the dest file first. + if ((Common_commonLastErrorCode == FILEUTILLS_ERROR_PATH_IS_A_FILE) && + (append)) + { + // Open in append mode. + output.open(absPathDest.c_str(), std::ios::out | std::ios::binary | std::ios::app); + } + else + { + // Open in truncate mode. + output.open(absPathDest.c_str(), std::ios::out | std::ios::binary | std::ios::trunc); + } - // remove the slash if it was added back. - buffer = RemoveTrailingSlash(buffer); + // Check and see if the dest file opened. + if (output.is_open()) + { + // If we are appending data jump to the end. + if (append) + { + output.seekp(0, std::ios::end); + } - // Copy it to the real path. - realpath = buffer; - } + // Open the input file. + input.open(absPathSrc.c_str(), std::ios::in | std::ios::binary); - // Assume relative if we have something else here. - if (buffer.find_first_of(DIR_SEP) != 0 && isHome == false && isrelative == false) // BUG: This does not get called. - { - // Set isrelative to true and retrive the current working directory. - isrelative = true; - pCWD = getcwd(charArray, sizeof(charArray)); - buffer = pCWD; + // Check and see if the input file opened. + if (input.is_open()) + { + // Calculate the size of the input file, and determine if we need to take into account an offset. (amountOfBytesToCopy will be greater than zero if we do.) + input.seekg(0, std::ios::end); + if (amountOfBytesToCopy > 0) + { + // Check and see if we have a file big enough to have that many bytes. + if (input.tellg() >= (begOffset + amountOfBytesToCopy)) + { + // Jump to the correct beginning offset in the input file. + input.seekg(begOffset, std::ios::beg); + } + else + { + // File is not big enough to copy the requested byte range. + result = COMMON_ERROR_RANGE_ERROR; + + // Log the error. + COMMON_LOG_DEBUG("FileUtills::CopyFile(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(result)); + COMMON_LOG_DEBUG(" The given source file ( "); + COMMON_LOG_DEBUG(absPathSrc.c_str()); + COMMON_LOG_DEBUG(" ) is too small. Either the beginning offset itself, or the beginning offset plus the range of bytes to copy, is beyond the end of the source file. Aborting.\n"); + + // Reset amountOfBytesToCopy. + amountOfBytesToCopy = 0; + } + } + else + { + // Copy the entire file. (Only if both offsets are equal to zero.) + amountOfBytesToCopy = input.tellg(); - // Add a DIR_SEP to the string or we will mess up the directory name. - buffer += DIR_SEP; + // Seek back to the beginning og the source file. + input.seekg(0, std::ios::beg); + } - // Add all data from the Directory string because the string does not have a DIR_SEP at position zero. - buffer += directory.substr(0, size); + // Allocate our memory buffer. + try { + ioBuffer = (char*)malloc(bufferSize); + + // Check for an allocated buffer. + if (ioBuffer != NULL) + { + // Begin copy loop. + for (x = 0; ((x < amountOfBytesToCopy) && (result == COMMON_ERROR_SUCCESS));) + { + // Start internal buffer loop. + for (y = 0; ((y < bufferSize) && ((x + y) < amountOfBytesToCopy) && (result == COMMON_ERROR_SUCCESS)); y++) + { + // Copy the data. + ioBuffer[(x + y)] = input.get(); + + // Check the input stream. + if (!input.good()) + { + // I/O error. + result = COMMON_ERROR_IO_ERROR; + + // Log the error. + COMMON_LOG_VERBOSE("FileUtills::CopyFile(): "); + COMMON_LOG_VERBOSE(Common::Get_Error_Message(result)); + COMMON_LOG_VERBOSE(" Input file stream failed."); + COMMON_LOG_VERBOSE("\n"); + } + } - // Remove the slash if it was added back. - buffer = RemoveTrailingSlash(buffer); + // Output the data. + for (z = 0; ((z < y) && (result == COMMON_ERROR_SUCCESS)); z++) + { + output.put(ioBuffer[z]); + + // Check the output stream. + if (!output.good()) + { + // I/O error. + result = COMMON_ERROR_IO_ERROR; + + // Log the error. + COMMON_LOG_DEBUG("FileUtills::CopyFile(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(result)); + COMMON_LOG_VERBOSE(" Output file stream failed."); + COMMON_LOG_DEBUG("\n"); + } + } - // Copy it to the realpath. - realpath = buffer; - } + // Flush the output buffer. + if (output.good()) + { + output.flush(); + } + + // Increment x. + x += y; + } + } + else + { + // Could not allocate memory buffer. + result = COMMON_ERROR_MEMORY_ERROR; - // Get the parent directory out of the buffer and store it for later. - position = buffer.find_last_of(DIR_SEP); - parentbuffer = buffer.substr(0, position); - - // Check and see if the parent directory exists. - errorcode = FileUtills::CheckParent(directory); // Switch - - switch (errorcode) { - case -1: // Can't write to the parent directory exit the function. - return -1; - permission = 0; - break; - case -2: // Parent Directory does not exist, - if (createRecursive == false) - { - // Don't create the directory structure. - return -2; - } - break; - - case 0: // Parent Directory does exist and is writeable. - // since we can write to the directory skip the loop. - skiploop = true; - break; - default: // Ether there was an unknown error or this Arch / OS is not supported. ether way return -4. - return -4; - errorcode = 0; - break; - } + // Log the error. + COMMON_LOG_VERBOSE("FileUtills::CopyFile(): "); + COMMON_LOG_VERBOSE(Common::Get_Error_Message(result)); + COMMON_LOG_VERBOSE("\n"); + } + } + catch(exception &ex) + { + // Exception thrown. + result = COMMON_ERROR_EXCEPTION_THROWN; + + // Log the error. + COMMON_LOG_VERBOSE("FileUtills::CopyFile(): "); + COMMON_LOG_VERBOSE(Common::Get_Error_Message(result)); + COMMON_LOG_VERBOSE(" "); + COMMON_LOG_VERBOSE(ex.what()); + COMMON_LOG_VERBOSE("\n"); + } - // Clear the vars for the recursive directory creation loop. - permission = 0; - position = 0; - errorcode = 0; + // Free the buffer if needed. + if (ioBuffer != NULL) + { + free(ioBuffer); + ioBuffer = NULL; + } - // Set buffer so we can check the path correctly. - // If we have a relative or user path use the real path. - if (isHome == true || isrelative == true) - { - buffer = realpath.substr(0, (realpath.find_first_of( DIR_SEP , 1))); + // Close the input and output files. + if (input.is_open()) + { + input.close(); + } + if (output.is_open()) + { + output.close(); + } - // Also set the size of the string correctly. - size = realpath.size(); - } - else - { - // Otherwise use the directory string. - buffer = directory.substr(0, (directory.find_first_of( DIR_SEP, 1))); + // Log file creation. + if (result == COMMON_ERROR_SUCCESS) + { + COMMON_LOG_INFO("FileUtills::CopyFile(): Copied file ( "); + COMMON_LOG_INFO(absPathDest.c_str()); + COMMON_LOG_INFO(" ) successfully.\n"); + } + else + { + COMMON_LOG_INFO("FileUtills::CopyFile(): File ( "); + COMMON_LOG_INFO(absPathDest.c_str()); + COMMON_LOG_INFO(" ) created, but coping was unsuccessful.\n"); + } + } + else + { + // Could not open the source file for reading. + result = COMMON_ERROR_IO_ERROR; + + // Log error. + COMMON_LOG_DEBUG("FileUtills::CopyFile(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(result)); + COMMON_LOG_DEBUG(" Unable to open ( "); + COMMON_LOG_DEBUG(absPathSrc.c_str()); + COMMON_LOG_DEBUG(" ) for reading.\n"); + + // Close the output file. + output.close(); + } + } + else + { + // Could not open the destionation file for writing. + result = COMMON_ERROR_IO_ERROR; + + // Log error. + COMMON_LOG_DEBUG("FileUtills::CopyFile(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(result)); + COMMON_LOG_DEBUG(" Unable to open ( "); + COMMON_LOG_DEBUG(absPathDest.c_str()); + COMMON_LOG_DEBUG(" ) for writing.\n"); + } + } + else + { + // Check for non-existant parent directory. + if (result == FILEUTILLS_ERROR_NON_EXISTANT) + { + COMMON_LOG_INFO("FileUtills::CopyFile(): Destionation directory (or a path componet leading up to it) does not exist, CopyFile() does not create non-existant directories, call CopyPath() instead. Aborting.\n"); + } + else + { + COMMON_LOG_INFO("FileUtills::CopyFile(): Error while checking destionation parent directory, aborting.\n"); + } + } + } + else + { + // Check for a directory. + if (Common_commonLastErrorCode == FILEUTILLS_ERROR_PATH_IS_A_DIRECTORY) + { + // Cannot overwrite a directory with a file. + COMMON_LOG_INFO("FileUtills::CopyFile(): Cannot overwrite a directory with a file, aborting.\n"); + } + else + { + // Other error, abort. + COMMON_LOG_INFO("FileUtills::CopyFile(): Unable to determine the destionation path's type / existance, aborting.\n"); + } + } + } + else + { + // Check error. + if ((Common_commonLastErrorCode == FILEUTILLS_ERROR_PATH_IS_A_DIRECTORY) || + (Common_commonLastErrorCode == COMMON_ERROR_SUCCESS)) + { + // Unable to copy a directory or special file. (COMMON_ERROR_SUCCESS is used to indicate path existance when it is not a regular file or directory.) + COMMON_LOG_DEBUG("FileUtills::CopyFile(): Unable to copy non-regular files or directories, aborting.\n"); + } + else + { + // Got an error, abort. + COMMON_LOG_VERBOSE("FileUtills::CopyFile(): Unable to determine the source path's type / existance, aborting.\n"); + } + } + } + else + { + // Unable to get destionation absolute path. + COMMON_LOG_VERBOSE("Unable to get destionation absolute path, aborting.\n"); - // Also set the size of the string correctly. - size = directory.size(); - } + // Make sure Common_commonLastErrorCode is set to something. + if (absPathDest.size() <= 0) + { + result = COMMON_ERROR_INTERNAL_ERROR; + } + } + } + else + { + // Unable to get source absolute path. + COMMON_LOG_VERBOSE("Unable to get source absolute path, aborting.\n"); - // If the parent directory does not exist and createRecursive is true then begin main loop. - while (skiploop != true) - { - // If we are at position 0 and there is a DIR_SEP there incremnt position by one. - if (position == 0 && buffer.find_first_of(DIR_SEP) == 0) - { - // Incremnt the position by one. - position++; - } + // Make sure Common_commonLastErrorCode is set to something. + if (absPathSrc.size() <= 0) + { + result = COMMON_ERROR_INTERNAL_ERROR; + } + } + } + else + { + // Offsets are switched. + result = COMMON_ERROR_INVALID_ARGUMENT; - // Start with root directory and run though the following until we reach the requested directory. + // Log error. + COMMON_LOG_DEBUG("FileUtills::CopyFile(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(result)); + COMMON_LOG_DEBUG(" Your offsets are invalid. (Really the only way this is possible is if you either reverse the beginning and ending offsets, or if you have an offset that is less than zero.) Aborting.\n"); + } + } + else + { + // endOffset is invalid. + result = COMMON_ERROR_INVALID_ARGUMENT; - if (isHome == true || isrelative == true) // If true use realpath - { - if ((position = realpath.find_first_of(DIR_SEP, position)) == string::npos) - { - // This is the requested directory so exit the loop. - skiploop = true; - break; + // Log error. + COMMON_LOG_DEBUG("FileUtills::CopyFile(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(result)); + COMMON_LOG_DEBUG(" ending offset argument is invalid.\n"); + } } - } - else // Otherwise use directory. - { - if ((position = directory.find_first_of(DIR_SEP, position)) == string::npos) + else { - // This is the requested directory so exit the loop. - skiploop = true; - break; - } - } - - // Do a sanity check for the size of the string. - if (position < 0 || position > size) - { - // Ok something went wrong. - return -4; - } + // begOffset is invalid. + result = COMMON_ERROR_INVALID_ARGUMENT; - // Dump the last buffer into the parentdirectory buffer. - parentbuffer = buffer; - - // Cut up the directory string so we can check for it. - - if (isHome == true || isrelative == true) - { - buffer = realpath.substr(0, position); + // Log error. + COMMON_LOG_DEBUG("FileUtills::CopyFile(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(result)); + COMMON_LOG_DEBUG(" beginning offset argument is invalid.\n"); + } } else { - buffer = directory.substr(0, position); - } - - // Do Check. - errorcode = FileUtills::DoesExist(buffer); - - switch (errorcode){ - case -1: // Directory does not exist on system. - // Check and see if we can create it. - permission = FileUtills::CheckPermissions(parentbuffer); + // dest is invalid. + result = COMMON_ERROR_INVALID_ARGUMENT; - switch (permission){ - case -1: - // Permission Check Failed. - return false; - break; - - case 0: - // Ok try and create the directory. - if ((errorcode = (mkdir(buffer.c_str(), S_IRWXU))) != 0) - { - // An error ocurred find out what. - - switch (errno) { - case EACCES: // Permission error. - return -1; - break; - case EEXIST: // Path exists on system. - return -3; - break; - case ENOSPC: // Out of disk space. - return -2; - break; - default: // We really don't care about the other errors. - return -4; - break; - } - } - - // Update the position counter. - position++; - - // Check and see if that was the last directory to create. - if (isHome == true || isrelative == true) - { - // Check realpath. - if (buffer == realpath) - { - skiploop = true; - return 0; - } - } - // Otherwise check the directory buffer. - if (buffer == directory) - { - skiploop = true; - return 0; - } - break; - - default: - // Bad errorcode exit function. - return -4; - break; - } - permission = 0; - errorcode = 0; - break; - - case 0: // Ok directory does exist. - position++; - break; - - default: - // Bad error code exit function. - return -4; + // Log error. + COMMON_LOG_DEBUG("FileUtills::CopyFile(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(result)); + COMMON_LOG_DEBUG(" destionation path argument is invalid.\n"); } - - - - // If the next directory does exist then skip the remaining portion of the checks and restart with the next directory. - - // If the next directory does not exist the check the permissions of this one. - - // If we can write to this directory then create the directory. - - // If the directory creation was successful then check and see what to do next. - - // If we have created the requested directory exit the function - //return true. - - // If we have not created the requested directory contiune loop with the next - // directory. - - // If we encountered a fatal error exit the function return false. - - // If we can't write to this directory exit the function, return false. - - // If the permission check fails with a fatal error exit the function return false. - - // If the existance check fails exit the function, return false. - } - - - - //If we have a relative or user path use realpath. - if (isHome == true || isrelative == true) - { - buffer = realpath; } - else // Otherwise use the directory string. + else { + // Src is invalid. + result = COMMON_ERROR_INVALID_ARGUMENT; - buffer = directory; + // Log error. + COMMON_LOG_DEBUG("FileUtills::CopyFile(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(result)); + COMMON_LOG_DEBUG(" source path argument is invalid.\n"); } - // Ok try and create the directory. - if ((errorcode = (mkdir(buffer.c_str(), S_IRWXU))) != 0) - { - // An error ocurred find out what. - - switch (errno) { - case EACCES: // Permission error. - return -1; - break; - case EEXIST: // Path exists on system. - return -5; - break; - case ENOSPC: // Out of disk space. - return -4; - break; - default: // We really don't care about the other errors. - return -6; - break; - } - } - if (errorcode == 0) - { - return 0; - } -#endif - // If an implemetation does not exist for this platform then exit the function, return false. - return -3; + // Copy result to Common_commonLastErrorCode. + Common_commonLastErrorCode = result; + + // Return the result. + return result; } -int FileUtills::CheckPermissions(const std::string & Filename, Panic::ERROR & error, bool read, bool write) +int FileUtills::CopyPathData(const std::string & src, const std::string & dest, const bool & recursive, + const bool & rename, const bool & abort_on_failure, + const bool & append, const streamsize & begOffset, const streamsize & endOffset) { - // Double check and make sure we have something to do. - if (read == false && write == false) - { - // Ok what? Call PanicHandler. - error.PanicHandler("FileUtills::CheckPermissions : CheckPermissions called but no permissions to check due to args. Returning -3"); - - // Return -3 - return -3; - } - -#ifdef POSIX_COMMON_H - //init vars - int errorcode = 0; - - // Find out if file or directory exists - if ((errorcode = DoesExist(Filename, error)) == -1) - { - // File does not exist return -2. - return -2; - } + // Init vars. + int ret = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; - // Also check and make sure no other error occured. - if (errorcode == -2) - { - // Something went wrong with DoesExist return -3. - return -3; - } + // LOG INCOMPLETE FUNCTION. + COMMON_LOG_WARNING("FileUtills::CopyPathData(): "); + COMMON_LOG_WARNING(Common::Get_Error_Message(ret)); + COMMON_LOG_WARNING("\n"); - // Reset errorcode - errorcode = 0; + // Copy result to Common_commonLastErrorCode. + Common_commonLastErrorCode = ret; - // DoesExist returned ok, Begin check - if (read == true && write == false) - { - // Check for read only permission. - errorcode = access(Filename.c_str(), R_OK); - if (errorcode != 0) - { - // File or Directory is not readable return -1 - return -1; - } - if (errorcode == 0) - { - // File or directory is readable return 0. - return 0; - } + // Return the result. + return ret; +} - // Unknown error call Panic Handler - error.PanicHandler("FileUtills::CheckPermissions : Unknown Error occured during read permission check. Returning -3"); - return -3; - } +int FileUtills::CopyPath(const std::string & src, const std::string & dest, const bool & recursive, + const bool & useSyscall, const bool & useRename) +{ + // Init vars. + int ret = COMMON_ERROR_UNKNOWN_ERROR; // The result of this function. + std::string absPathSrc = ""; // The absolute version of the given source path. + std::string absPathDest = ""; // The absolute version of the given destionation path. - if (read == false && write == true) + // Call FileUtills::ResolvePath() for the source path. + absPathSrc = FileUtills::ResolvePath(src); + if (Common_commonLastErrorCode == COMMON_ERROR_SUCCESS) { - // Check for write only permission. (odd but for rundundantcy.) - errorcode = access(Filename.c_str(), W_OK); - - if (errorcode != 0) - { - // File or Directory is not writeable return -1 - return -1; - } - if (errorcode == 0) + // Check for valid result. + if (absPathSrc.size() > 0) { - // File or directory is writeable return 0. - return 0; - } - - // Unknown error call Panic Handler - error.PanicHandler("FileUtills::CheckPermissions : Unknown Error occured during write permission check. Returning -3"); - return -3; - } + // Resolve the destionation path. + absPathDest = FileUtills::ResolvePath(dest); + if (Common_commonLastErrorCode == COMMON_ERROR_SUCCESS) + { + // Check for valid result. + if (absPathDest.size() > 0) + { + // Call helper function. + ret = FileUtills::CopyPath_Helper(absPathSrc, absPathDest, recursive, useSyscall, useRename); + if (ret == COMMON_ERROR_SUCCESS) + { + // Log success. + COMMON_LOG_INFO("FileUtills::CopyPath(): Copied ( "); + COMMON_LOG_INFO(absPathSrc.c_str()); + COMMON_LOG_INFO(" ) to ( "); + COMMON_LOG_INFO(absPathDest.c_str()); + COMMON_LOG_INFO(" ) successfully.\n"); + } + else + { + // Check for invalid argument. + if (ret == COMMON_ERROR_INVALID_ARGUMENT) + { + // Set this to internal error. (The caller does not need to see the invalid argument error.) + ret = COMMON_ERROR_INTERNAL_ERROR; + } - if (read == true && write == true) - { - // Check for read and write permissions. - errorcode = access(Filename.c_str(), R_OK); - if (errorcode != 0) - { - // File or directory is not readable. it has failed one critera for check, return -1. - return -1; - } - if (errorcode == 0) - { - // File or directory is readable check for write permission. - errorcode = access(Filename.c_str(), W_OK); + // Log the error. + COMMON_LOG_INFO("FileUtills::CopyPath(): Unable to copy ( "); + COMMON_LOG_INFO(absPathSrc.c_str()); + COMMON_LOG_INFO(" ) to ( "); + COMMON_LOG_INFO(absPathDest.c_str()); + COMMON_LOG_INFO(" ) successfully. Some files / directories may have been copied. Please double check manually.\n"); + } + } + else + { + // Could not resolve the destionation path. (Success without result.) + ret = COMMON_ERROR_INTERNAL_ERROR; - if (errorcode != 0) - { - // File or Directory is not writeable return -1 - return -1; - } - if (errorcode == 0) - { - // File or directory is writeable return 0. - return 0; + // Log the error. + COMMON_LOG_WARNING("FileUtills::CopyPath(): "); + COMMON_LOG_WARNING(Common::Get_Error_Message(ret)); + COMMON_LOG_WARNING(" Could not resolve the destionation path, FileUtills::ResolvePath() returned an invalid path but indicated success, Please report this bug.\n"); + } } else { - // Unknown error call panic handler. - error.PanicHandler("FileUtills::CheckPermissions : Unknown Error occured during write permission check. Returning -3"); - return -3; + // Log the error. + COMMON_LOG_DEBUG("FileUtills::CopyPath(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(ret)); + COMMON_LOG_DEBUG(" Could not resolve the destionation path, aborting.\n"); } } else { - // Unknown error call panic handler. - error.PanicHandler("FileUtills::CheckPermissions : Unknown Error occured during read permission check. Returning -3"); - return -3; - } - } - -#endif - // Call Panic Handler there is no OS / arch impilmentation. - error.PanicHandler("FileUtills::CheckPermissions : OS / arch not supported. No Implementation found. Returning -3."); + // Could not resolve the source path. (Success without result.) + ret = COMMON_ERROR_INTERNAL_ERROR; - // Default Return - return -3; -} - - -int FileUtills::CheckPermissions(const std::string & path, bool read, bool write) -{ - // Double check and make sure we have something to do. - if (read == false && write == false) - { - // Return -3 - return -3; - } - -#ifdef POSIX_COMMON_H - //init vars - int errorcode = 0; - - // Find out if file or directory exists - if ((errorcode = DoesExist(path)) == -1) - { - // File does not exist return -2. - return -2; - } - - // Also check and make sure no other error occured. - if (errorcode == -2) - { - // Something went wrong with DoesExist return -3. - return -3; - } - - // Reset errorcode - errorcode = 0; - - // DoesExist returned ok, Begin check - if (read == true && write == false) - { - // Check for read only permission. - errorcode = access(path.c_str(), R_OK); - if (errorcode != 0) - { - // File or Directory is not readable return -1 - return -1; - } - if (errorcode == 0) - { - // File or directory is readable return 0. - return 0; - } - // Unknown error - return -3; - } - - if (read == false && write == true) - { - // Check for write only permission. (odd but for rundundantcy.) - errorcode = access(path.c_str(), W_OK); - - if (errorcode != 0) - { - // File or Directory is not writeable return -1 - return -1; - } - if (errorcode == 0) - { - // File or directory is writeable return 0. - return 0; + // Log the error. + COMMON_LOG_WARNING("FileUtills::CopyPath(): "); + COMMON_LOG_WARNING(Common::Get_Error_Message(ret)); + COMMON_LOG_WARNING(" Could not resolve the source path, FileUtills::ResolvePath() returned an invalid path but indicated success, Please report this bug.\n"); } - - // Unknown error - return -3; } - - if (read == true && write == true) + else { - // Check for read and write permissions. - errorcode = access(path.c_str(), R_OK); - if (errorcode != 0) - { - // File or directory is not readable. it has failed one critera for check, return -1. - return -1; - } - if (errorcode == 0) - { - // File or directory is readable check for write permission. - errorcode = access(path.c_str(), W_OK); - - if (errorcode != 0) - { - // File or Directory is not writeable return -1 - return -1; - } - if (errorcode == 0) - { - // File or directory is writeable return 0. - return 0; - } - else - { - // Unknown error - return -3; - } - } - else - { - // Unknown error - return -3; - } + // Log the error. + COMMON_LOG_DEBUG("FileUtills::CopyPath(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(ret)); + COMMON_LOG_DEBUG(" Could not resolve the destionation path, aborting.\n"); } -#endif - // there is no OS / arch impilmentation return default. - // Default Return - return -3; -} - - -int FileUtills::DoesExist(const std::string & Filename, Panic::ERROR & error) -{ -#ifdef POSIX_COMMON_H - - // Declare some vars. - int errorcode = 0; // Holds error number. - - // Check and see if the file exists. - errorcode = access(Filename.c_str(), F_OK); - - // Get error code. - if (errorcode == 0) - { - // File exists return ok - return 0; - } - if (errorcode == -1) - { - // File does not exist return false. - return -1; - } - else - { - // Ok What happened? Call PanicHandler - error.PanicHandler("FileUtills::DoesExist : Unknown Error, returning false on file exist check."); - } -#endif - // Call Panic Handler arch / OS not supported. - error.PanicHandler("FileUtils::DoesExist : OS / arch not supported. No Implementation found. Returning -2."); - - // Default return. - return -2; -} - -int FileUtills::DoesExist(const std::string & Filename) -{ -#ifdef POSIX_COMMON_H - - // Declare some vars. - int errorcode = 0; // Holds error number. - - // Check and see if the file exists. - errorcode = access(Filename.c_str(), F_OK); - - // Get error code. - if (errorcode == 0) - { - // File exists return ok - return 0; - } - if (errorcode == -1) - { - // File does not exist return false. - return -1; - } - else - { - // Unknown error return false. - return -1; - } -#endif - // arch / OS not supported. - - // Default return. - return -2; -} + // Copy ret to Common_commonLastErrorCode. + Common_commonLastErrorCode = ret; -int FileUtills::IsFileOrDirectory(const std::string & path) + // Return the result. + return ret; +} + // Below is the Helper function for CopyPath(). + + rewrite directory parser loop with the one from DeletePath(). + +int FileUtills::CopyPath_Helper(const std::string & absPathSrc, const std::string & absPathDest, const bool & recursive, const bool & useSyscall, const bool & useRename) { - // Make sure that the path is not empty. - if (path.size() <= 0) - { - // Empty path. - return -5; - } - -#ifdef POSIX_COMMON_H - // Init vars. - int result = 0; - int call_result = 0; - struct stat * buf = NULL; - - // Init stat buffer. - buf = new struct stat; - - // Ask the OS to stat() the path. - call_result = stat(path.c_str(), buf); + // Init vars. + int ret = COMMON_ERROR_SUCCESS; // Used to hold the result of this function. + char * pCurrentPathSegment = NULL; // Used to allocate memory for a substring that contains the current path segment. + std::string absPathDestFixedFileName = ""; // Used to copy a source path with a different destionation name. - // Check the result. - if (call_result == 0) - { - // Check the stat structure. - if (S_ISREG((buf->st_mode))) - { - // Path is a regular file. - result = 1; - } - else - { - if (S_ISDIR((buf->st_mode))) - { - // Path is a directory. - result = 2; - } - } - } - else + // Check for valid absPathSrc. + if (absPathSrc.size() > 0) { - // Error, see if it was a permissions error. - switch (errno) + // Check for valid absPathDest. + if (absPathDest.size() > 0) { - case EACCES: - // Permissions error. - result = -4; - break; - case ENOENT: - // A path componet does not exist. - result = -6; - break; - case ENOTDIR: - // Path has a file in it, and is not the final componet. - result = -7; - break; - default: - // Some other error. - result = -9; - break; - }; - } - - // Delete stat buffer. - delete buf; - buf = NULL; - - // Exit function. - return result; -#endif - - // System unsupported, why not add support for it? :) - return -3; -} - -int FileUtills::CheckParent(const std::string & path, bool read, bool write) -{ -#ifdef POSIX_COMMON_H - // Init vars - std::string parentbuffer = ""; - long int length = 0; - long int location = 0; - int result = 0; - - // Remove the trailing slash if present. - parentbuffer = RemoveTrailingSlash(path); - - // Check the Path for absolute path. - parentbuffer = FileUtills::CheckPathType(parentbuffer); - - // Check the length of the path. - length = parentbuffer.length(); - - // Check and see if the length is zero. - if (length == 0) - { - // Nothing to do so return that the path does not exist. (It clearly does not exist.) - return -2; - } - - // Locate the path seperator before the last directory / file name. - location = parentbuffer.find_last_of(DIR_SEP); - - // Check and make sure that the location of the dir sep is inside the string - if (location > length || length < 0 || location < 0) - { - // Memory error or someone is fucking with us. - // Either way kill the function - return -5; - } - - // Check and see if the parentbuffer is a root directory - if (length > 1) - { - - // Get the parent directory path. - // Note substr CAN throw an exception. so we need to put this in a try catch block. - try{ - parentbuffer = parentbuffer.substr(0, location); - } - catch(exception &ex) - { - // If we end up here we're in trouble. - // Kill the function to be safe. - return -5; - } - - // Now rerun the check for a dir sep on the end. - parentbuffer = RemoveTrailingSlash(parentbuffer); - } - - // Call the other functions - result = FileUtills::CheckPermissions(parentbuffer, read, write); - - // Check the result - switch (result) - { - // Successful - case 0: - return 0; - break; - // Permission error - case -1: - return -1; - break; - // Parent Does not exist - case -2: - return -2; - break; - // Unknown error (Probabliy a memory error) - default: - return -5; - break; - }; -#endif - // arch / OS not supported. - return -3; -} - -std::string FileUtills::GetParent(const std::string & path) -{ - // Init vars. - std::string parentbuffer = ""; - long int length = 0; - long int location = 0; - -#ifdef POSIX_COMMON_H - // Remove the trailing slash if present. - parentbuffer = RemoveTrailingSlash(path); - - // Check the Path for absolute path. - parentbuffer = FileUtills::CheckPathType(parentbuffer); - - // Check the length of the path. - length = parentbuffer.length(); + // Determine the type of source. (File or directory.) + ret = FileUtills::IsFileOrDirectory_Helper(absPathSrc); + if ((ret == FILEUTILLS_ERROR_PATH_IS_A_FILE) || (ret == COMMON_ERROR_SUCCESS)) + { + // Check and see if the source is a non-regular file, and if the copy syscall use is disabled. + if ((ret == COMMON_ERROR_SUCCESS) && (!useSyscall)) + { + // We cannot copy a non-regular file, without using a syscall. + COMMON_LOG_INFO("FileUtills::CopyPath(): Cannot copy source ( "); + COMMON_LOG_INFO(absPathSrc.c_str()); + COMMON_LOG_INFO(" ) to destionation ( "); + COMMON_LOG_INFO(absPathDest.c_str()); + COMMON_LOG_INFO(" ) Cannot copy a non-regular file without using a host's syscall. Caller has disabled use of a host's syscall. Aborting.\n"); + } + else + { + // Check and see if the destionation path exists. + ret = FileUtills::IsFileOrDirectory_Helper(absPathDest); + if (ret == FILEUTILLS_ERROR_NON_EXISTANT) + { + // Destionation path does not exist. Assume the last path segment in the destionation path is the file name of the copied file. + // OK, check and see if the parent exists. + ret = FileUtills::CheckParent_Helper(absPathDest, true, true, true); + if (ret == COMMON_ERROR_SUCCESS) + { + // OK Copy the source file to the destionation directory. + // Using the given last path segment in the destionation path as the copied file's name. + if (useSyscall && useRename) + { + // Use the rename syscall. + ret = FileUtills::RenameFile_Syscall(absPathSrc, absPathDest); + if (ret == COMMON_ERROR_SUCCESS) + { + // Log the copied file. + COMMON_LOG_INFO("FileUtills::CopyPath(): Copied ( "); + COMMON_LOG_INFO(absPathSrc.c_str()); + COMMON_LOG_INFO(" ) to destionation ( "); + COMMON_LOG_INFO(absPathDest.c_str()); + COMMON_LOG_INFO(" ) successfully.\n"); + } + else + { + // An error occured. + COMMON_LOG_DEBUG("FileUtills::CopyPath(): Error ( "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(ret)); + COMMON_LOG_DEBUG(" ) was returned from the RenameFile syscall. Unable to copy ( "); + COMMON_LOG_DEBUG(absPathSrc.c_str()); + COMMON_LOG_DEBUG(" ) to destionation ( "); + COMMON_LOG_DEBUG(absPathDest.c_str()); + COMMON_LOG_DEBUG(" ).\n"); + + // If ret was invalid argument change it to internal error. + if (ret == COMMON_ERROR_INVALID_ARGUMENT) + { + ret = COMMON_ERROR_INTERNAL_ERROR; + } + } + } + else + { + // Check to see if we are using the syscall. + if (useSyscall) + { + // Copy using the host's copy syscall. + ret = FileUtills::CopyPath_Syscall(absPathSrc, absPathDest); + if (ret == COMMON_ERROR_SUCCESS) + { + // Log the copied file. + COMMON_LOG_INFO("FileUtills::CopyPath(): Copied ( "); + COMMON_LOG_INFO(absPathSrc.c_str()); + COMMON_LOG_INFO(" ) to destionation ( "); + COMMON_LOG_INFO(absPathDest.c_str()); + COMMON_LOG_INFO(" ) successfully.\n"); + } + else + { + // An error occured. + COMMON_LOG_DEBUG("FileUtills::CopyPath(): Error ( "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(ret)); + COMMON_LOG_DEBUG(" ) was returned from the CopyFile syscall. Unable to copy ( "); + COMMON_LOG_DEBUG(absPathSrc.c_str()); + COMMON_LOG_DEBUG(" ) to destionation ( "); + COMMON_LOG_DEBUG(absPathDest.c_str()); + COMMON_LOG_DEBUG(" ).\n"); + + // If ret was invalid argument change it to internal error. + if (ret == COMMON_ERROR_INVALID_ARGUMENT) + { + ret = COMMON_ERROR_INTERNAL_ERROR; + } + } + } + else + { + // Copy using the CopyPathData() function. + } + } + } + else + { + // An error occured. + } + } + else + { + // Check and see if the destionation path is a directory. + if (ret == FILEUTILLS_ERROR_PATH_IS_A_DIRECTORY) + { + // The last path segment in the destionation path is a directory, + // assume the copied file's name is the same as the source file. - // Check and see if the length is zero. - if (length == 0) - { - // Nothing to do so return that the path does not exist. (It clearly does not exist.) - parentbuffer = ""; - return parentbuffer; - } + // Copy absPathDest to absPathDestFixedFileName and add a DIR_SEP. + absPathDestFixedFileName = absPathDest; + absPathDestFixedFileName += DIR_SEP; - // Locate the path seperator before the last directory / file name. - location = parentbuffer.find_last_of(DIR_SEP); + // We need to copy the last path segment of the source to the destionation. + // (So the copied file will have the same name as the source file.) + ret = FileUtills::GetLastPathSegment(absPathSrc, absPathDestFixedFileName, false); + if (ret == COMMON_ERROR_SUCCESS) + { + // Check for success without result. + if (absPathDestFixedFileName.size() > (absPathDest.size() + sizeof(DIR_SEP))) + { + // Check and see if we are using the syscalls. + if (useSyscall && useRename) + { + // Use the rename syscall. + ret = FileUtills::RenameFile_Syscall(absPathSrc, absPathDestFixedFileName); + if (ret == COMMON_ERROR_SUCCESS) + { + // Log the copied file. + COMMON_LOG_INFO("FileUtills::CopyPath(): Copied ( "); + COMMON_LOG_INFO(absPathSrc.c_str()); + COMMON_LOG_INFO(" ) to destionation ( "); + COMMON_LOG_INFO(absPathDestFixedFileName.c_str()); + COMMON_LOG_INFO(" ) successfully.\n"); + } + else + { + // An error occured. + COMMON_LOG_DEBUG("FileUtills::CopyPath(): Error ( "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(ret)); + COMMON_LOG_DEBUG(" ) was returned from the CopyFile syscall. Unable to copy ( "); + COMMON_LOG_DEBUG(absPathSrc.c_str()); + COMMON_LOG_DEBUG(" ) to destionation ( "); + COMMON_LOG_DEBUG(absPathDestFixedFileName.c_str()); + COMMON_LOG_DEBUG(" ).\n"); + + // If ret was invalid argument change it to internal error. + if (ret == COMMON_ERROR_INVALID_ARGUMENT) + { + ret = COMMON_ERROR_INTERNAL_ERROR; + } + } + } + else + { + // Check and see if we are using the host's copy syscall. + if (useSyscall) + { + // OK, copy the source file to the destionation directory, using the syscall. + ret = FileUtills::CopyPath_Syscall(absPathSrc, absPathDestFixedFileName); + if (ret == COMMON_ERROR_SUCCESS) + { + // Log the copied file. + COMMON_LOG_INFO("FileUtills::CopyPath(): Copied ( "); + COMMON_LOG_INFO(absPathSrc.c_str()); + COMMON_LOG_INFO(" ) to destionation ( "); + COMMON_LOG_INFO(absPathDestFixedFileName.c_str()); + COMMON_LOG_INFO(" ) successfully.\n"); + } + else + { + // An error occured. + COMMON_LOG_DEBUG("FileUtills::CopyPath(): Error ( "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(ret)); + COMMON_LOG_DEBUG(" ) was returned from the CopyFile syscall. Unable to copy ( "); + COMMON_LOG_DEBUG(absPathSrc.c_str()); + COMMON_LOG_DEBUG(" ) to destionation ( "); + COMMON_LOG_DEBUG(absPathDestFixedFileName.c_str()); + COMMON_LOG_DEBUG(" ).\n"); + + // If ret was invalid argument change it to internal error. + if (ret == COMMON_ERROR_INVALID_ARGUMENT) + { + ret = COMMON_ERROR_INTERNAL_ERROR; + } + } + } + else + { + // Copy using the CopyPathData() function. + } + } + else + { + // We got success without a result. + ret = COMMON_ERROR_INTERNAL_ERROR; + COMMON_LOG_WARNING("FileUtills::CopyPath(): "); + COMMON_LOG_WARNING(Common::Get_Error_Message(ret)); + COMMON_LOG_WARNING(" FileUtills::GetLastPathSegment() returned an invalid path while indicating success. Please report this bug.\n"); + } + } + else + { + // Log the error. + - // Check and make sure that the location of the dir sep is inside the string - if (location > length || length < 0 || location < 0) - { - // Memory error or someone is fucking with us. - // Either way kill the function - parentbuffer = ""; - return parentbuffer; - } + // Could not copy the file name. + if (ret == COMMON_ERROR_INVALID_ARGUMENT) + { + // Set this to internal error. + ret = COMMON_ERROR_INTERNAL_ERROR; + } + } + } + else + { + // An error occured. + } + } + } + } + else + { + // Check and see if the source is a directory. + if (ret == FILEUTILLS_ERROR_PATH_IS_A_DIRECTORY) + { + // Check and see if copy recursive is false. + if (recursive) + { + // Check and see if the destionation exists. + ret = FileUtills::IsFileOrDirectory_Helper(absPathDest); + if (ret == FILEUTILLS_ERROR_NON_EXISTANT) + { + // Destionation path does not exist, assume that the destionation path's + // last path segment is the name to use for the copied directory. - // Check and see if the parentbuffer is a root directory - if (length > 1) - { - // Get the parent directory path. - // Note substr CAN throw an exception. so we need to put this in a try catch block. - try{ - parentbuffer = parentbuffer.substr(0, location); - } - catch(exception &ex) - { - // If we end up here we're in trouble. - // Kill the function to be safe. - parentbuffer = ""; - return parentbuffer; - } + // Check and see if the parent exists. + ret = FileUtills::CheckParent_Helper(absPathDest, true, true, true); + if (ret == COMMON_ERROR_SUCCESS) + { + // Ok, create the destionation path. + ret = FileUtills::CreateDirectory_Helper(absPathDest); + if (ret != COMMON_ERROR_SUCCESS) + { + // We cannot create the destionation directory. + COMMON_LOG_INFO("FileUtills::CopyPath(): Cannot copy source ( "); + COMMON_LOG_INFO(absPathSrc.c_str()); + COMMON_LOG_INFO(" ) to destionation ( "); + COMMON_LOG_INFO(absPathDest.c_str()); + COMMON_LOG_INFO(" ) unable to create destionation directory. Aborting.\n"); + } + } + else + { + // An error occured. + } + } + else + { + // Check and see if the destionation is a pre-existing directory. + // If the destionation is a pre-existing directory, assume we need + // to merge the source directory's contents with the destionation's + // contents. + if (ret != FILEUTILLS_ERROR_PATH_IS_A_DIRECTORY) + { + // Check and see if the destionation path is a file. + if ((ret == COMMON_ERROR_SUCCESS) || (ret == FILEUTILLS_ERROR_PATH_IS_A_FILE)) + { + // Indicate failure. + ret = FILEUTILLS_ERROR_PATH_IS_A_FILE; + + // Cannot overwrite a file with a directory. + COMMON_LOG_INFO("FileUtills::CopyPath(): Cannot copy source ( "); + COMMON_LOG_INFO(absPathSrc.c_str()); + COMMON_LOG_INFO(" ) to destionation ( "); + COMMON_LOG_INFO(absPathDest.c_str()); + COMMON_LOG_INFO(" ) Cannot overwrite a pre-existing file with a directory. Aborting.\n"); + } + else + { + // An error occured. + } + } + } + + // Check and see if we can continue. (If the destionation path was non-existant then ret would be COMMON_ERROR_SUCCESS if the directory was created.) + if ((ret == FILEUTILLS_ERROR_PATH_IS_A_DIRECTORY) || (ret == COMMON_ERROR_SUCCESS)) + { + // Begin try block. + try { + // Begin recursion loop. + } + catch (exception &ex) + { + // Exception thrown. + ret = COMMON_ERROR_EXCEPTION_THROWN; + + // Log the error. + COMMON_LOG_DEBUG("FileUtills::CopyPath(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(ret)); + COMMON_LOG_DEBUG(" "); + COMMON_LOG_DEBUG(ex.what()); + COMMON_LOG_DEBUG("\n"); + } + } + } + else + { + // Cannot copy a directory if recursion is disabled by the caller. + COMMON_LOG_DEBUG("FileUtills::CopyPath(): Cannot copy source ( "); + COMMON_LOG_DEBUG(absPathSrc.c_str()); + COMMON_LOG_DEBUG(" ) to destionation ( "); + COMMON_LOG_DEBUG(absPathDest.c_str()); + COMMON_LOG_DEBUG(" ) because recursion is disabled by the caller. Aborting.\n"); + } + } + else + { + // An error occured. + } + } + + + // Run copy loop. + for (size_t x = (MINIMAL_VALID_ABSOLUTE_PATH_LENGTH + 1); ((x < absPath.size()) && (result == COMMON_ERROR_SUCCESS)); x++) + { + // Search for the next DIR_SEP, or the end of the given path string. + if ((absPath[x] == DIR_SEP) || ((x + 1) == absPath.size())) + { + // This is the end of the next path segment, create the needed substring and create the directory. + try { + // Allocate memory buffer. + if (absPath[x] != DIR_SEP) + { + // Allocate an extra character only if we are before a directory seperator. + pCurrentPathSegment = (char*)malloc((x + 1)); + } + else + { + // If the current char is a directory seperator, then we need to allocate only the current x value. + pCurrentPathSegment = (char*)malloc(x); + } - // Now rerun the check for a dir sep on the end. - parentbuffer = RemoveTrailingSlash(parentbuffer); + // Check and make sure we got the memory allocated. + if (pCurrentPathSegment != NULL) + { + // Check and see if the current char is a DIR_SEP. (Controls how much of the source buffer we need to copy.) + if (absPath[x] != DIR_SEP) + { + // Copy the data. + for (size_t y = 0; (y < (x + 1)); y++) + { + pCurrentPathSegment[y] = absPath[y]; + } - // Exit function. - return parentbuffer; + // Terminate the string. (Arrays start at zero, x is the last valid character in the string.) + pCurrentPathSegment[x] = '\0'; + } + else + { + // Copy the data. + for (size_t y = 0; (y < x); y++) + { + pCurrentPathSegment[y] = absPath[y]; + } - } -#endif - // arch / OS not supported. - parentbuffer = ""; - return parentbuffer; + // Terminate the string. (Arrays start at zero, (x - 1) is the last valid character in the string.) + pCurrentPathSegment[(x - 1)] = '\0'; + } -} + // Now create the path. (Issue system call.) + if ((FileUtills::CreateDirectory_Syscall(pCurrentPathSegment) != COMMON_ERROR_SUCCESS) || (Common_commonLastErrorCode != COMMON_ERROR_SUCCESS)) + { + // Check and see if the error code is FILEUTILLS_ERROR_EXISTANT. (This is only an error if the final directory segment cannot be created.) + if ((Common_commonLastErrorCode != FILEUTILLS_ERROR_EXISTANT) || ((Common_commonLastErrorCode == FILEUTILLS_ERROR_EXISTANT) && ((x + 1) >= absPath.size()))) + { + // Copy the error. + result = Common_commonLastErrorCode; + + // Log the error if needed. + COMMON_LOG_INFO("FileUtills::CreateDirectory(): "); + COMMON_LOG_INFO(Common::Get_Error_Message(result)); + COMMON_LOG_INFO(" Unable to create directory ( "); + COMMON_LOG_INFO(pCurrentPathSegment); + COMMON_LOG_INFO(" ), aborting.\n"); + + // Force the loop to exit. + x = absPath.size(); + } + } + else + { + // Report success. + COMMON_LOG_INFO("FileUtills::CreateDirectory(): Created directory ( "); + COMMON_LOG_INFO(pCurrentPathSegment); + COMMON_LOG_INFO(" )\n"); + } -short FileUtills::DeletePath(const std::string & path, const bool & recursive) -{ -#ifdef POSIX_COMMON_H - // Init vars. - bool done = false; // Used to know when to exit the recursive iterator loop. - bool resetIterLoop = false; // Used to control resetting the recursive iterator loop. - bool unableToDeleteAll = false; // Used to tell if we could not delete something while deleting recursively. - int result = 0; // Used to store results from calls to other functions. - size_t x = 0; // Used by the recursion loop, for accessing the directory list. - std::string currentabspath = ""; // Used to contain the current absolute path. - std::string dummy = ""; // Used to construct temporary paths. - FileUtills::dirlist * plist = NULL; // Used to store paths for recursive deletions. - std::vector::iterator iter; // plist->list (Directory Listing). - std::vector directory_offsets; // Used to store the offsets in the directory listings. - - // Check and see if the file can be erased. - result = FileUtills::CheckPermissions(path); - - // Attempt to delete the path if the OS permissions allow it. - if (result == 0) - { - // Call removal function. - if (remove(path.c_str()) != 0) - { - // Check the error. - if (errno == EACCES) - { - // Permissions error. - return -1; - } - if (errno == EPERM) - { - // Permissions error. - return -1; - } - if (errno == ENOTEMPTY) // Path is a non empty directory. - { - // If we have recursive set to true we can delete the path, else return an error. - if (recursive) - { - // Copy the src path to the currentabspath var. - currentabspath = path; - - // Begin recursion loop. - do - { - // OK we need to get the paths of every file in the directory and any other directories. - plist = NULL; - plist = FileUtills::getDirectory(currentabspath, true); - if (plist == NULL) - { - // Could not get directory list. - if (plist != NULL) - { - delete plist; - plist = NULL; - } - return -4; - } - - // Reset the iter just to be safe. - iter = plist->list.begin(); - - // Check and see if the directory offset list has anything in it. - if ((!resetIterLoop) && (directory_offsets.size() > 0)) - { - // We have an offset, so init x to that offset. - x = directory_offsets[(directory_offsets.size() - 1)]; // size() returns the number of valid elements in the vector. - - // Fix the iterator. - iter = iter + x; - - // Erase the offset from the vector. - directory_offsets.erase((directory_offsets.end() - 1)); // end() returns the position after the last valid element in the vector. - } - else - { - // We don't have any offsets, (or we just switched to a subdirectory) so init x to zero. - x = 0; - - // Unset resetIterLoop. - resetIterLoop = false; - } - - // Begin loop to check for more subdirectories. - for (; x < plist->list.size(); x++) - { - // Create temp path. - dummy.clear(); - dummy = currentabspath + DIR_SEP + (plist->list[x]); - dummy = RemoveTrailingSlash(dummy); // If we got a DIR_SEP at the end of the string get rid of it. - - // Check to see if the current entry in the list is a directory. - switch (FileUtills::IsFileOrDirectory(dummy)) - { - case 0: // Not a file or directory. (Try to remove anyway.) - case 1: // File. - // Attempt to delete file. - if (remove(dummy.c_str()) != 0) - { - // Set unableToDeleteAll. - unableToDeleteAll = true; - - /* - Note: We need someway of keeping track of what - files we've already attempted to delete, - Otherwise we'll end up in an indefinte loop. - - The easist way to to have the list generated the same - way each time and store the offsets. (I.e each call to - FileUtills::getDirectory() returns the same list. As - opposed to just the way the OS spits out the directory - listing.) - - Then when the subdirectory is removed, (or after the failed removal - attempt) find where that subdirectory was in the list and continue. - */ - } - break; - case 2: // Directory. - // Set currentabspath to this path. - currentabspath = dummy; - - // Set the current directory list offset (x) in to the vector. - directory_offsets.push_back(x); - - // Set reset flag. - resetIterLoop = true; - - // Get out of this loop. - break; - case -3: // OS not supported. - if (plist != NULL) - { - delete plist; - plist = NULL; - } - return -3; - case -4: // Permission error. - case -5: // Arg error. - case -6: // Path componet does not exist. - case -7: // Part of path is a file. - case -9: // Memory error. - default: - // Set unableToDeleteAll. - unableToDeleteAll = true; - break; - }; - - // Check to see if reset flag is set. - if (resetIterLoop) - { - // Get out of this loop. - break; - } - } - - // Check to see how the previous loop exited. - if (!resetIterLoop) - { - // Remove the directory. - if (remove(currentabspath.c_str()) != 0) - { - // Check and see if unableToDeleteAll was set. If it was set, we ignore this error. - if (!unableToDeleteAll) - { - // Check the error. - if (errno == EACCES) - { - // Permissions error. - if (plist != NULL) - { - delete plist; - plist = NULL; - } - return -1; - } - else - { - if (errno == EPERM) - { - // Permissions error. - if (plist != NULL) - { - delete plist; - plist = NULL; - } - return -1; - } - else - { - // Some other error. - if (plist != NULL) - { - delete plist; - plist = NULL; - } - return -5; - } - } - } - else - { - // Increment the offset in the vector. (We have dealt with this subdirectory.) - if (directory_offsets.size() > 0) - { - directory_offsets[(directory_offsets.size() - 1)] = (directory_offsets[(directory_offsets.size() - 1)] + 1); - } - } - } - - // Check to see if we removed the source dir. - if (currentabspath != path) - { - // Get the parent directory of currentabspath. - currentabspath = FileUtills::GetParent(currentabspath); - if (currentabspath.size() <= 0) - { - // Could not get parent directory. - if (plist != NULL) - { - delete plist; - plist = NULL; - } - return -7; - } - - // Delete the old plist. - if (plist != NULL) - { - delete plist; - plist = NULL; - } - } - else - { - // Delete the old plist. - if (plist != NULL) - { - delete plist; - plist = NULL; - } - - // All directories have been deleted. - done = true; - } - } - else - { - // Delete the old plist. - if (plist != NULL) - { - delete plist; - plist = NULL; - } - } - }while (!done); - - // Delete the plist. - if (plist != NULL) - { - delete plist; - plist = NULL; - } - - // Clear dummy and currentabspath. - dummy.clear(); - currentabspath.clear(); - - // Flush the directory_offsets vector. - directory_offsets.clear(); - - // Check and see if the unableToDeleteAll flag is set. - if (unableToDeleteAll) - { - // We can't delete some things so return an error. - return -8; - } - } - else - { - // Path is not empty and we are not deleting recursively. - return -6; - } - } - else - { - // Some other error. - return -5; - } - } - } - else - { - // Determine the error. - switch (result) - { - // Permission BAD - case -1: - return -1; - break; - // Path does not exist - case -2: - return -2; - break; - // Either an unknown error or function is not supported - case -3: - return -3; - break; - // Possible memory error - default: - return -4; - break; - }; - } + // Deallocate the buffer. + if (pCurrentPathSegment != NULL) + { + free(pCurrentPathSegment); + pCurrentPathSegment = NULL; + } + } + else + { + // Could not allocate memory. + result = COMMON_ERROR_MEMORY_ERROR; + COMMON_LOG_DEBUG("FileUtills::CreateDirectory(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(result)); + COMMON_LOG_DEBUG("\n"); + + // Force loop to exit. + x = absPath.size(); + } + } + catch(exception &ex) + { + // Exception thrown. + result = COMMON_ERROR_EXCEPTION_THROWN; + COMMON_LOG_DEBUG("FileUtills::CreateDirectory(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(result)); + COMMON_LOG_DEBUG(" "); + COMMON_LOG_DEBUG(ex.what()); + COMMON_LOG_DEBUG("\n"); - // Exit function. - return 0; -#endif - // System not supported. - return -3; -} + // Force loop to exit. + x = absPath.size(); + } + } + } + } + } + else + { + // Invalid destionation path. + ret = COMMON_ERROR_INVALID_ARGUMENT; + COMMON_LOG_DEBUG("FileUtills::CopyPath(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(ret)); + COMMON_LOG_DEBUG(" Given destionation path is invalid.\n"); + } + } + else + { + // Invalid source path. + ret = COMMON_ERROR_INVALID_ARGUMENT; + COMMON_LOG_DEBUG("FileUtills::CopyPath(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(ret)); + COMMON_LOG_DEBUG(" Given source path is invalid.\n"); + } -short FileUtills::CopyFile(const std::string & src, const std::string & dest, const bool & append, const streamsize & begOffset, const streamsize & endOffset) -{ - // Init vars. - const short buffer_size = 512; // Constant used to determine the size of the file copy buffer. - streamsize result = 0; // Used to hold the returned result of this function to the caller. - streamsize count = 0; // Used while copying data to count the number of copied bytes. - streamsize total_bytes_copied = 0; // Holds the total amount of copied bytes. - streamsize input_size = 0; // Holds the size of the input file. - streamsize bytes_to_copy = 0; // Holds the total amount of bytes to copy from the input file. - char * pBuffer = NULL; // Used as a buffer for copying data. - fstream input; // File stream for input file. - fstream output; // File stream for output file. - - // Check for invalid offsets. - if ((begOffset < 0) || (endOffset < 0)) - { - // Error, An offset is negative. - result = -1; - } - else - { - // Check and make sure that the beginning offset is smaller than the ending offset. - if (begOffset > endOffset) - { - // Offsets are out of order. - result = -5; - } - else - { - // Check the source file name length. - if (src.size() <= 0) - { - // Invalid source file name. - result = -10; - } - else - { - // Check to see if src is a directory. - result = FileUtills::IsFileOrDirectory(src); - if (result == 2) - { - // Src is a directory, do not continue. - result = -17; - } - else - { - // Check for negative return code. - if (result < 0) - { - // IsFileOrDirectory() returned an error. - switch (result) - { - case -3: - // IsFileOrDirectory() is not supported on this system. - result = -33; - break; - case -4: - // A permissions error occured. - result = -34; - break; - case -5: - // The given path is empty. - result = -35; - break; - case -6: - // A path componet does not exist. - result = -36; - break; - case -7: - // The path has a file in it and is not at the end. (I.e you are treating a file as a directory.) - result = -37; - break; - default: - // All other errors. - result = -39; - break; - }; - } - else - { - // Attempt to open the file. - input.open(src.c_str(), ios::in | ios::binary); - if (!input.is_open()) - { - // Could not open file. - result = -11; - } - else - { - // Get file size. - input.seekg(0, ios::end); - input_size = input.tellg(); - input.seekg(0, ios::beg); - - // Determine if the input file has the needed amount of bytes to copy. - if (input_size < begOffset) - { - // Input file is smaller than the beginning offset. - result = -12; - } - else - { - if (input_size < endOffset) - { - // Input file is smaller than the ending offset. - result = -13; - } - else - { - // Check to see if we are copying the entire file. - if ((begOffset == 0) && (endOffset == 0)) // Shortcut so the caller does not need to know the size of the file. - { - // We are copying the entire file. - bytes_to_copy = input_size; - } - else - { - // Calculate the total amount of bytes to copy. - bytes_to_copy = endOffset - begOffset; - - // Seek to the beginning offset in the source file. - input.seekg(begOffset, ios::beg); - } - - // Check the length of the dest. - if (dest.size() <= 0) - { - // Invalid dest path. - result = -20; - } - else - { - // Check and see if dest is a directory. - result = FileUtills::IsFileOrDirectory(dest); - if (result == 2) - { - // Dest is a directory, abort. - result = -27; - } - else - { - // Check for negative return code. (That is NOT the non existant file error.) - if ((result != -6) && (result < 0)) - { - // IsFileOrDirectory() returned an error. - switch (result) - { - case -3: - // IsFileOrDirectory() is not supported on this system. - result = -33; - break; - case -4: - // A permissions error occured. - result = -34; - break; - case -5: - // The given path is empty. - result = -35; - break; - case -6: - // A path componet does not exist. - result = -36; - break; - case -7: - // The path has a file in it and is not at the end. (I.e you are treating a file as a directory.) - result = -37; - break; - default: - // All other errors. - result = -39; - break; - }; - } - else - { - // Check and see if we got the non existant file error from IsFileOrDirectory(). - if (result == -6) - { - // Reset result. - result = 0; - } - - // Open output file. - if (append) - { - output.open(dest.c_str(), ios::in | ios::out | ios::binary | ios::app); - output.seekg(0, ios::end); - output.seekp(0, ios::end); - } - else - { - output.open(dest.c_str(), ios::in | ios::out | ios::binary | ios::trunc); - } - - // Check to see if the file is open. - if (!output.is_open()) - { - // Could not open output file. - result = -21; - } - else - { - // Begin try block. - try{ - // Allocate memory buffer. - pBuffer = (char*)malloc(buffer_size); - if (pBuffer == NULL) - { - // Could not allocate memory buffer. - result = -9; - } - else - { - // Blank the buffer. - memset(pBuffer, '\0', buffer_size); - - // Start copy loop. - while (total_bytes_copied < bytes_to_copy) - { - // Check the state of the file streams. - if (input.fail()) - { - // Input file stream error. - if (input.bad()) - { - // Read IO error. - result = -14; - } - else - { - // Logical IO error. - result = -15; - } - - // Get out of the loop. - break; - } - if (input.eof()) - { - // ??? We should not have hit eof.... - result = -16; - - // Get out of the loop. - break; - } - if (output.fail()) - { - // Output file stream error. - if (output.bad()) - { - // Write IO error. - result = -24; - } - else - { - // Logical IO error. - result = -25; - } - - // Get out of the loop. - break; - } - - // Check and see if the data remaining to copy is less than the buffer size. - if ((bytes_to_copy - total_bytes_copied) < buffer_size) - { - // OK we only need to copy the remaining data. - input.read(pBuffer, (bytes_to_copy - total_bytes_copied)); - } - else - { - // Fill up the buffer. - input.read(pBuffer, buffer_size); - } - - // Get the number of read bytes. - count = input.gcount(); - - // Write out the bytes to the output file. - output.write(pBuffer, count); - - // Add the bytes copied to the total. - total_bytes_copied += count; - } - - // Deallocate memory buffer. - memset(pBuffer, '\0', buffer_size); - if (pBuffer != NULL) - { - free(pBuffer); - pBuffer = NULL; - } - } - } - catch(...) - { - // Exception thrown during copy loop. - result = -99; - } - - // Close output file. - if (output.is_open()) - { - output.close(); - } - } - } - } - } - } - } - - // Close input file. - if (input.is_open()) - { - input.close(); - } - } - } - } - } - } - } + // Copy ret to Common_commonLastErrorCode. + Common_commonLastErrorCode = ret; - // Exit function. - return result; + // Return the result. + return ret; } - -short FileUtills::CopyPath(const std::string & src, const std::string & dest, const bool & recursive, - const bool & rename, const bool & abort_on_failure, - const bool & append, const streamsize & begOffset, const streamsize & endOffset) -{ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + // Init vars. bool done = false; // Used to know when to exit the recursive iterator loop. bool resetIterLoop = false; // Used to control resetting the recursive iterator loop. bool unableToCopyAll = false; // Used to know if a file copy failed while recursively copying files. - short result = 0; // Used to store results from calls to other functions. + int result = COMMON_ERROR_UNKNOWN_ERROR; // Used to store results from calls to other functions. std::string currentabspath_src = ""; // Used to contain the current absolute source path. std::string currentabspath_dest = ""; // Used to contain the current absolute destionation path. std::string src_path = ""; // Used to construct temporary source paths. @@ -2625,7 +2305,7 @@ short FileUtills::CopyPath(const std::string & src, const std::string & dest, co // Check and see if the src is a file or a directory. result = FileUtills::IsFileOrDirectory(src); - if (result == 2) // Directory. + if (result == FILEUTILLS_ERROR_PATH_IS_A_DIRECTORY) // Directory. { // Copy the src path to the currentabspath_src and the dest path to the currentabspath_dest var. currentabspath_src = src; @@ -2633,66 +2313,42 @@ short FileUtills::CopyPath(const std::string & src, const std::string & dest, co // OK, check and see if the dest directory exists. result = FileUtills::IsFileOrDirectory(currentabspath_dest); - if (result == -6) // Directory does not exist. + if (result == FILEUTILLS_ERROR_NON_EXISTANT) // Directory does not exist. { - // Create the dest directory. - result = FileUtills::CreateDirectory(currentabspath_dest); - if (result != 0) - { - // OK, we can't create the dest directory. - result = -1; - } + // Create the dest directory. + result = FileUtills::CreateDirectory(currentabspath_dest); + if (result == COMMON_ERROR_SUCCESS) + { + // Set result to FILEUTILLS_ERROR_NON_EXISTANT, so that we know we can continue. + result = FILEUTILLS_ERROR_NON_EXISTANT; + } + else + { + // OK, we can't create the dest directory. + COMMON_LOG_DEBUG("FileUtills::CopyPath(): Could not create destionation directory, aborting.\n"); + } } else { - if (result == 2) // Dest Directory exists. + if (result != FILEUTILLS_ERROR_EXISTANT) // Dest Directory exists. + { + if (result == COMMON_ERROR_SUCCESS) { - // Set result to zero. (0) - result = 0; + // This is some special file, so we can't overwrite it. + COMMON_LOG_DEBUG("FileUtills::CopyPath(): Destionation is a special file, will not overwrite it, aborting.\n"); } else { - if (result >= 0) - { - // OK, dest is some file or other filesystem entry, so we can't copy a directory to it. - result = -2; - } - else - { - // IsFileOrDirectory() returned an error. - switch (result) - { - case -3: - // IsFileOrDirectory() is not supported on this system. - result = -13; - break; - case -4: - // A permissions error occured. - result = -14; - break; - case -5: - // The given path is empty. - result = -15; - break; - case -6: - // A path componet does not exist. - result = -16; - break; - case -7: - // The path has a file in it and is not at the end. (I.e you are treating a file as a directory.) - result = -17; - break; - default: - // All other errors. - result = -19; - break; - }; - } + // Some other error. + COMMON_LOG_DEBUG("FileUtills::CopyPath(): Unable to check destionation, returned error was: "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(result)); + COMMON_LOG_DEBUG("\n"); } + } } // Make sure that result == 0. (I.e. that we can continue.) - if (result == 0) + if ((result == FILEUTILLS_ERROR_NON_EXISTANT) || (result == FILEUTILLS_ERROR_EXISTANT)) { // Begin recursion loop. do @@ -2708,7 +2364,7 @@ short FileUtills::CopyPath(const std::string & src, const std::string & dest, co delete plist; plist = NULL; } - result = -4; + result = Common_commonLastErrorCode; // Exit loop. done = true; @@ -2753,13 +2409,13 @@ short FileUtills::CopyPath(const std::string & src, const std::string & dest, co // Check to see if the current entry in the list is a directory. switch (FileUtills::IsFileOrDirectory(src_path)) { - case 0: // Not a file or directory. (Try to copy anyway.) - case 1: // File. + case COMMON_ERROR_SUCCESS: // Not a file or directory. (Try to copy anyway.) + case FILEUTILLS_ERROR_PATH_IS_A_FILE: // File. // Attempt to copy file. result = FileUtills::CopyFile(src_path, dest_path, false, 0, 0); - if (result != 0) + if (result != COMMON_ERROR_SUCCESS) { - if ((result != -3) || (result == -33)) // If result does = -3 (CopyFile), or -33 (IsFileOrDirectory) it means the OS / Arch is unsupported by CopyFile(). + if (result == COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED) // If result does = -3 (CopyFile), or -33 (IsFileOrDirectory) it means the OS / Arch is unsupported by CopyFile(). { // Set unableToCopyAll. unableToCopyAll = true; @@ -2781,7 +2437,7 @@ short FileUtills::CopyPath(const std::string & src, const std::string & dest, co } } break; - case 2: // Directory. + case FILEUTILLS_ERROR_PATH_IS_A_DIRECTORY: // Directory. // Check recursive flag. if (recursive) { @@ -2798,19 +2454,18 @@ short FileUtills::CopyPath(const std::string & src, const std::string & dest, co // Get out of this loop. } // Ignore otherwise. break; - case -3: // OS not supported. + case COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED: // OS not supported. if (plist != NULL) { delete plist; plist = NULL; } - result = -3; break; - case -4: // Permission error. - case -5: // Arg error. - case -6: // Path componet does not exist. - case -7: // Part of path is a file. - case -9: // Memory error. + case COMMON_ERROR_ACCESS_DENIED: // Permission error. + case COMMON_ERROR_INVALID_ARGUMENT: // Arg error. + case FILEUTILLS_ERROR_NON_EXISTANT: // Path componet does not exist. + case FILEUTILLS_ERROR_PATH_FILE_AS_DIRECTORY: // Part of path is a file. + case COMMON_ERROR_MEMORY_ERROR: // Memory error. default: // Set unableToCopyAll. unableToCopyAll = true; @@ -2818,7 +2473,7 @@ short FileUtills::CopyPath(const std::string & src, const std::string & dest, co }; // Check to see if reset flag is set, if we hit OS / Arch unsupported, or if we failed and the user requested abort on failure. - if ((resetIterLoop) || (result == -3) || ((unableToCopyAll) && (abort_on_failure))) + if ((resetIterLoop) || (result == COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED) || ((unableToCopyAll) && (abort_on_failure))) { // Get out of this loop. break; @@ -2826,7 +2481,7 @@ short FileUtills::CopyPath(const std::string & src, const std::string & dest, co } // Check to see how the previous loop exited. - if ((result == -3) || (result == -33) || ((abort_on_failure) && (unableToCopyAll))) + if ((result == COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED) || ((abort_on_failure) && (unableToCopyAll))) { /* OS / Arch not supported, or * we failed to copy something and the user requested abort on failure. @@ -2847,13 +2502,13 @@ short FileUtills::CopyPath(const std::string & src, const std::string & dest, co // Check and see if the dest directory exists. result = FileUtills::IsFileOrDirectory(currentabspath_dest); - if (result == -6) // Directory does NOT exist. + if (result == FILEUTILLS_ERROR_NON_EXISTANT) // Directory does NOT exist. { // Create subdirectory. result = FileUtills::CreateDirectory(currentabspath_dest); - if (result != 0) + if (result != COMMON_ERROR_SUCCESS) { - if (result == -3) // -3 means OS / Arch not supported. + if (result == COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED) // -3 means OS / Arch not supported. { // Exit loop. done = true; @@ -2871,14 +2526,14 @@ short FileUtills::CopyPath(const std::string & src, const std::string & dest, co else { // Check to see if currentabspath_dest is a some sort of filesystem entry. - if (result >= 0) + if (result != FILEUTILLS_ERROR_PATH_IS_A_DIRECTORY) { // OK, we can't create a directory where a file (or some other filesystem entry) exists. unableToCopyAll = true; } else { - if (result == -3) // OS / Arch not supported. + if (result == COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED) // OS / Arch not supported. { // Exit loop. done = true; @@ -2912,14 +2567,14 @@ short FileUtills::CopyPath(const std::string & src, const std::string & dest, co if (currentabspath_src.size() <= 0) { // Could not get parent directory. - result = -5; + result = COMMON_ERROR_INTERNAL_ERROR; done = true; } currentabspath_dest = FileUtills::GetParent(currentabspath_dest); if (currentabspath_dest.size() <= 0) { // Could not get parent directory. - result = -5; + result = COMMON_ERROR_INTERNAL_ERROR; done = true; } @@ -2968,136 +2623,120 @@ short FileUtills::CopyPath(const std::string & src, const std::string & dest, co // We can't copy some things so return an error. result = -6; } - - // Check and see if IsFileOrDirectory() returned -3. - if (result == -33) - { - // IsFileOrDirectory() is not supported. - result = -13; - } } } else // Treat as single file. { - if ((result == 0) || (result == 1)) - { - // Call CopyFile. - result = FileUtills::CopyFile(src, dest, append, begOffset, endOffset); - } - else - { - // IsFileOrDirectory() returned an error. - switch (result) - { - case -3: - // IsFileOrDirectory() is not supported on this system. - result = -13; - break; - case -4: - // A permissions error occured. - result = -14; - break; - case -5: - // The given path is empty. - result = -15; - break; - case -6: - // A path componet does not exist. - result = -16; - break; - case -7: - // The path has a file in it and is not at the end. (I.e you are treating a file as a directory.) - result = -17; - break; - default: - // All other errors. - result = -19; - break; - }; - } + if ((result == COMMON_ERROR_SUCCESS) || (result == FILEUTILLS_ERROR_PATH_IS_A_FILE)) + { + // Call CopyFile. + result = FileUtills::CopyFile(src, dest, append, begOffset, endOffset); + } + else + { + // IsFileOrDirectory() returned an error. + COMMON_LOG_INFO("FileUtills::CopyPath(): Unable to determine the type of the source path, aborting.\n"); + } } + // Copy result to Common_commonLastErrorCode. + Common_commonLastErrorCode = result; + // Return result. return result; } -short FileUtills::MovePath(const std::string & src, const std::string & dest, const bool & overwrite) +int FileUtills::MovePath(const std::string & src, const std::string & dest, const bool & overwrite) { - // Dumb check. - if ((src.size() <= 0) || (dest.size() <= 0)) - { - // Bad src or dest. - return -5; - } + // Init vars. + int result = 0; // Used for return codes. - // Init vars. - short result = 0; // Used for return codes. + // Dumb check. + if (src.size() > 0) + { + if (dest.size() > 0) + { + // Check and see if dest already exists. + result = FileUtills::DoesExist(dest); + switch (result) + { + case FILEUTILLS_ERROR_EXISTANT: // Path exists. + if (overwrite == true) + { + // Attempt to delete dest path. + result = FileUtills::DeletePath(dest, true); + switch (result) + { + case COMMON_ERROR_SUCCESS: // Delete OK. + break; + default: // Unable to delete path. + COMMON_LOG_INFO("FileUtills::MovePath(): Unable to delete destionation path, aborting.\n"); + break; + }; + } + else + { + // Can't delete existing path bail out. + COMMON_LOG_INFO("FileUtills::MovePath(): Destionation path already exists. Caller has disabled overwriting pre-existing paths, aborting.\n"); + break; + } + break; + case FILEUTILLS_ERROR_NON_EXISTANT: // Path does not exist. + break; + default: // Some error. + COMMON_LOG_VERBOSE("FileUtills::MovePath(): Unable to determine if the destionation path already exists. Aborting.\n"); + break; + }; - // Check and see if dest already exists. - result = FileUtills::DoesExist(dest); - switch (result) - { - case 0: // Path exists. - if (overwrite == true) - { - // Attempt to delete dest path. - result = FileUtills::DeletePath(dest, true); - switch (result) - { - case 0: // Delete OK. - break; - default: // Unable to delete path. - result = -21; - break; - }; - } - else - { - // Can't delete existing path bail out. - result = -20; - break; - } - break; - case -1: // Path does not exist. - break; - default: // Some error. - result = -22; - break; - }; - - // Check to see if we can continue. - if ((result == -1) || (result == 0)) - { - // Copy entire path to the dest. - result = FileUtills::CopyPath(src, dest); - switch (result) - { - case 0: // Copy ok. - break; - case -1: // Source Permission error. - result = -10; - case -2: // Source Does not exist. - result = -10; - default: // Some error. - result = -4; - break; - }; - - // Check to see if the copy was successful. - if (result == 0) - { - // Delete original path. - result = FileUtills::DeletePath(src, true); - switch (result) - { - case 0: // Delete ok. - break; - default: // Some error. - result = -4; - break; - }; - } - } + // Check to see if we can continue. + if ((result == FILEUTILLS_ERROR_NON_EXISTANT) || (result == COMMON_ERROR_SUCCESS)) + { + // Copy entire path to the dest. + result = FileUtills::CopyPath(src, dest); + switch (result) + { + case COMMON_ERROR_SUCCESS: // Copy ok. + break; + default: // Some error. + COMMON_LOG_INFO("FileUtills::MovePath(): Unable to copy data from source to destionation, aborting.\n"); + break; + }; + + // Check to see if the copy was successful. + if (result == COMMON_ERROR_SUCCESS) + { + // Delete original path. + result = FileUtills::DeletePath(src, true); + switch (result) + { + case COMMON_ERROR_SUCCESS: // Delete ok. + COMMON_LOG_INFO("FileUtills::MovePath(): Source path moved to destionation path successfully.\n"); + break; + default: // Some error. + COMMON_LOG_WARNING("FileUtills::MovePath(): Source path copied to destionation path successfully, but we were unable to delete the source path. Returning error: "); + COMMON_LOG_WARNING(Common::Get_Error_Message(result)); + COMMON_LOG_WARNING("\n"); + break; + }; + } + } + } + else + { + // Dest is invalid. + result = COMMON_ERROR_INVALID_ARGUMENT; + COMMON_LOG_INFO("FileUtills::MovePath(): Invalid destionation path, aborting.\n"); + } + } + else + { + // Invalid source path. + result = COMMON_ERROR_INVALID_ARGUMENT; + COMMON_LOG_INFO("FileUtills::MovePath(): Invalid source path, aborting.\n"); + } + + // Copy result to Common_commonLastErrorCode. + Common_commonLastErrorCode = result; // Default return. return result; diff --git a/src/Common/Src/File_Management_Subsystem/FileUtills.h b/src/Common/Src/File_Management_Subsystem/FileUtills.h index c6ba89b..8903ec7 100644 --- a/src/Common/Src/File_Management_Subsystem/FileUtills.h +++ b/src/Common/Src/File_Management_Subsystem/FileUtills.h @@ -1,512 +1,548 @@ -/*! - Multiverse Engine Project 04/12/2011 FileUtills FileUtills.h - Yes we are reinventing the wheel here, go with it. - - Copyright (C) 2014 Multiverse Engine Project - - This program is free software; - you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; - either version 2 of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with this program; - if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - Official source repository and project information can be found at - https://github.com/codebase7/mengine -*/ - -#ifndef FILEUTILLS -#define FILEUTILLS - -// Engine Includes -#ifdef __win32 -#include "..\BaseHeader.h" -#include "..\Error_Handler\Common_Error_Handler.h" -#include "..\Error_Handler\Common_Error_Handler_Internal.h" -#else -#include "../BaseHeader.h" -#include "../Error_Handler/Common_Error_Handler.h" -#include "../Error_Handler/Common_Error_Handler_Internal.h" -#endif - -namespace FileUtills{ - -#ifdef _WIN32 -// Define the Windows Directory seperator -#define DIR_SEP = '\\' -#else -// Define the Posix Directory Seperator. -#ifndef DIR_SEP -#define DIR_SEP '/' -#define Relative_Symbol "./" -#endif -#endif - -// Define the directory list structure -struct dirlist{ - long int numOfEntries; // Used to store the number of entries in the list array. - std::vector list; // Used to store the directory's entry data. - std::string path; // Used to store the path of the directory that the entry list is about. - Panic::ERROR error; // Used to store an errorcode if one occurs. -}; - -/*! - * int FileUtills::GetUserProfileDirectoryPath(std::string & path) - * - * Fetches the user's profile directory from the enviorment, and stores - * it in the given path argument. (Note: The given path argument will be - * erased when this function is called. So take care not to leave something - * in it you need.) - * - * If the function fails for any reason, path will be an empty string, - * and Common::commonLastErrorCode will be set to the approiate error. - */ -int GetUserProfileDirectoryPath(std::string & path); - -/*! - * int FileUtills::GetCurrentWorkingDirectoryPath(std::string & path) - * - * Fetches the current working directory from the enviorment, and stores - * it in the given path argument. (Note: The given path argument will be - * erased when this function is called. So take care not to leave something - * in it you need.) - * - * If the function fails for any reason, path will be an empty string, - * and Common::commonLastErrorCode will be set to the approiate error. - */ -int GetCurrentWorkingDirectoryPath(std::string & path); - -/*! - * std::string FileUtills::GetExecDirectory() - * - * Returns a NULL terminated std::string the path to the directory where the - * executable is stored. - * - * If the function fails for any reason, the returned std::string will be empty, - * and Common::commonLastErrorCode will be set to the error. - */ -std::string GetExecDirectory(); - -/*! - FileUtills::dirlist * getDirectory(const std::string & path, const bool & cleanList) - - Lists the given directory's contents. - - Pram: path, path of directory to check. - - Pram: cleanList, If this is true then, the generated list will be sorted - (via decrementing sort), and the list will have the entries for the current - and parent directories removed. - (Default is to do nothing, and return the list as the OS generated it.) - - Returns a pointer to a dirlist if successfull. - Returns NULL if an error occurs. -*/ -dirlist * getDirectory(const std::string & path, const bool & cleanList = false); - -/*! - int FileUtills::DoesExist(const std::string & Filename, Panic::ERROR & error) - Prams: @std::string Filename - - Checks to see if given file or directory exists. - - This function is called by FileUtills::CheckPermissions() before runing permission checks. - - This function uses the Panic::ERROR class. - - Returns 0 if file or directory exists on the system. - Returns -1 if file or directory does not exist on the system. - Returns -2 if an error occurs, call ReturnLastError() on the error instance to get details. - Note it will also return -2 if the function does not have an implementation for your OS / arch. -*/ -int DoesExist(const std::string & Filename, Panic::ERROR & error); - -/*! - int FileUtills::DoesExist(const std::string & Filename) - Prams: @std::string Filename - - Checks to see if given file or directory exists. - - This function is called by FileUtills::CheckPermissions() before runing permission checks. - - Returns 0 if file or directory exists on the system. - Returns -1 if file or directory does not exist on the system. - Returns -2 if an error occurs. - Note it will also return -2 if the function does not have an implementation for your OS / arch. -*/ -int DoesExist(const std::string & Filename); - -/*! - FileUtills::IsFileOrDirectory(const std::string & path) - - Checks to see if a given path is a file or directory. - - Returns 0 if the path exists but it is not a file or directory. - Returns 1 if the path is a file. - Returns 2 if the path is a directory. - Returns -3 if the given system is unsupported. - Returns -4 if a permissions error occurs. - Returns -5 if the given path is empty. - Returns -6 if a path componet does not exist. - Returns -7 if the path has a file in it and is not at the end. (I.e you are treating a file as a directory.) - Returns -9 on all other errors. -*/ -int IsFileOrDirectory(const std::string & path); - -/*! - int FileUtills::CheckParent(const std::string & path, bool read, bool write) - - Acts as a wrapper to DoesExist and CheckPermissions - Checks for the parent directory's existance in the path given. - Also Checks to see if it is accessible. By default it checks for Read and Write access. - - Ex. This path is given "/home/user/Homework.txt" this function will check and see if the "/home/user" parent - directory exists, and if it is accessable. - - Returns 0 if the directory exists and is accessible with the requested permissions. - Returns -1 if A permission error occurs - Returns -2 if the parent directory does not exist. - Returns -3 if the OS / Arch is not supported. - Returns -5 if an unknown error occurs. -*/ -int CheckParent(const std::string & path, bool read = true, bool write = true); - -/*! - std::string FileUtills::GetParent(const std::string & path) - - Returns the parent directory for the given file. - - Gets the path exactly like FileUtills::CheckParent(). - - Returns std::string with parent directory path if successful. - Returns an empty string otherwise. -*/ -std::string GetParent(const std::string & path); - -/*! - std::string FileUtills::CheckPathType(const std::string & path) - - Checks the path given, and converts it to a absolute path. - - Returns absoulte path on success. - Returns a zero length string otherwise. -*/ -std::string CheckPathType(const std::string & path); - -/*! - short FileUtills::CreateDirectory(const std::string & directory, Panic::ERROR & error, const bool & createRecursive) - @pram : directory, path to create. - @pram : error, error handler for a human readable error message. - @pram : createRecursive, if this is set to true, then this function will try to create the - parent directories of the given directory if they do not exist. - - Creates given directory on the filesystem. - - This function uses the Panic::ERROR class. - - Returns 0 if directory creation was successful. - Returns -1 if permission is denied. - Returbs -2 if the parent directory does not exist and createRecursive is false. - Returns -3 if this function is unsupported. - Returns -4 if the disk is full. - Returns -5 if the directory already exists. - Returns -6 if another error is encountered. -*/ -short CreateDirectory(const std::string & directory, Panic::ERROR & error, const bool & createRecursive = false); - -/*! - short FileUtills::CreateDirectory(const std::string & directory, const bool & createRecursive) - @pram : directory, path to create. - @pram : createRecursive, if this is set to true, then this function will try to create the - parent directories of the given directory if they do not exist. - - Creates given directory on the filesystem. - - Returns 0 if directory creation was successful. - Returns -1 if permission is denied. - Returbs -2 if the parent directory does not exist and createRecursive is false. - Returns -3 if this function is unsupported. - Returns -4 if the disk is full. - Returns -5 if the directory already exists. - Returns -6 if another error is encountered. -*/ -short CreateDirectory(const std::string & directory, const bool & createRecursive = false); - -/*! - int FileUtills::CheckPermissions(const std::string & path, Panic::ERROR & error, bool read, bool write) - - Checks Permissions on the given file or directory. Also checks if the given file or directory - actully exists first before checking other permissions. By default it will check for both read and - write permissions. - - This function uses the Panic::ERROR class. - - Pram: path to directory or file to check. - Pram: error handler instance. - Pram: check for read permission. default is true. - Pram: check for wrtie permission. default is true. - - Return: 0 if all permission checks pass. - Return: -1 if permission check fails. - Return: -2 if the file does not exist. - Return: -3 if a diffrent error occurs. Call ReturnLastError for details. -*/ -int CheckPermissions(const std::string & path, Panic::ERROR & error, bool read = true, bool write = true); - -/*! - int FileUtills::CheckPermissions(const std::string & path, bool read, bool write) - Checks Permissions on the given file or directory. Also checks if the given file or directory - actully exists first before checking other permissions. By default it will check for both read and - write permissions. - - Pram: path to directory or file to check. - Pram: check for read permission. default is true. - Pram: check for wrtie permission. default is true. - - Return: 0 if all permission checks pass. - Return: -1 if permission check fails. - Return: -2 if the file does not exist. - Return: -3 if a diffrent error occurs. -*/ -int CheckPermissions(const std::string & path, bool read = true, bool write = true); - -/*! - int FileUtills::GetGigaFreespace(const std::string & path, size_t & result) - - Returns the remaining disk space in Gigabytes (SI Unit) on the given disk. - - Note if an error occurs, result will be set to zero, and an error code will be returned. - (Although result can also be set to zero if there really is no remaining disk space.) - - @pram const std::string & path : volume / path to check. - @pram size_t & result : The remaining space on the filesystem. - - Returns Common::COMMON_SUCCESS if successfull, result will contain the remaining space. - Returns a Common namespace error if an error occurs. Size will be equal to zero in this - case. To obtain more detailed info register an error hander before calling this function. -*/ -int GetGigaFreespace(const std::string & path, size_t & result); - -/*! - int FileUtills::GetFreespace(const std::string & path, size_t & result) - - Returns the remaining disk space in Megabytes (SI Unit) on the given disk. - - Note if an error occurs, result will be set to zero, and an error code will be returned. - (Although result can also be set to zero if there really is no remaining disk space.) - - @pram const std::string & path : volume / path to check. - @pram size_t & result : The remaining space on the filesystem. - - Returns Common::COMMON_SUCCESS if successfull, result will contain the remaining space. - Returns a Common namespace error if an error occurs. Size will be equal to zero in this - case. To obtain more detailed info register an error hander before calling this function. -*/ -int GetFreespace(const std::string & path, size_t & result); - -/*! - int FileUtills::GetKiloFreespace(const std::string & path, size_t & result) - - Returns the remaining disk space in Kilobytes (SI Unit) on the given disk. - - Note if an error occurs, result will be set to zero, and an error code will be returned. - (Although result can also be set to zero if there really is no remaining disk space.) - - @pram const std::string & path : volume / path to check. - @pram size_t & result : The remaining space on the filesystem. - - Returns Common::COMMON_SUCCESS if successfull, result will contain the remaining space. - Returns a Common namespace error if an error occurs. Size will be equal to zero in this - case. To obtain more detailed info register an error hander before calling this function. -*/ -int GetKiloFreespace(const std::string & path, size_t & result); - -/*! - int FileUtills::GetByteFreespace(const std::string & path, size_t & result) - - Returns the remaining disk space in Bytes (SI Unit) on the given disk. - - Note if an error occurs, result will be set to zero, and an error code will be returned. - (Although result can also be set to zero if there really is no remaining disk space.) - - @pram const std::string & path : volume / path to check. - @pram size_t & result : The remaining space on the filesystem. - - Returns Common::COMMON_SUCCESS if successfull, result will contain the remaining space. - Returns a Common namespace error if an error occurs. Size will be equal to zero in this - case. To obtain more detailed info register an error hander before calling this function. -*/ -int GetByteFreespace(const std::string & path, size_t & result); - -/*! - short FileUtills::DeletePath(const std::string & path, const bool & recursive) - - Deletes the file or directory given by path. - - By default this function will NOT delete recursively. - If the given path is a non-empty directory, by default this function will throw an error. - If the given path is an empty directory, however by default this function WILL delete it. - - Note: If while deleting rescursively, a file or subdirectory can't be deleted, this function will try to continue - deleting any other files and subdirectories that can be deleted, but it will throw an error apon exit. - - Returns 0 if successful. - -1 if the user lacks permission to delete the path. (Or if recursively deleting a directory, a file or subdirectory could not be deleted.) - -2 if the path does not exist. (Or if recursively deleting a directory, a file or subdirectory does not exist.) - -3 if the function is not supported. - -4 if a memory error occurs. - -5 if an unknown error occurs. (An error other than a permissions error occured while deleting something.) - -6 if the path is a non empty directory and recursive is set to false. - -7 if while deleting recursively, the parent directory of a deleted directory could not be obtained. (I.e could not "go up a level in the directory tree.") - -8 if while deleting recursively, there were files and or subdirectories that could not be deleted. (Some files may have been deleted however.) -*/ -short DeletePath(const std::string & path, const bool & recursive = false); - -/*! - short FileUtills::CopyFile(const std::string & src, const std::string & dest, const bool & append, - const streamsize & begOffset, const streamsize & endOffset) - - Copies endOffset bytes starting at begOffset, from source file to dest file. - - Offset rules: - If offsets are used, they must be positive. (If one of the given offsets is negative an error is returned.) - If zeros are used for both offsets, then the entire file will be copied. - If endOffset is greater than begOffset an error will be returned. - - This function only works on FILES. Not directories. To copy a directory, call FileUtills::CopyPath(). - - @pram src, absolute path to the source file. - @pram dest, absolute path to the dest file. - @pram append, Whether or not to append data to the dest file. (Note only applies if the dest file exists. - If append is false, then the dest file will be overwritten.) - @pram begOffset, Location in the source file to start copying data from. - @pram endOffset, Location in the source file to stop copying data when it is reached. - - By default the entire file is copied and the dest file is overwritten. - - Note: This function expects that both given paths are absolute. (I.e Complete paths to both files.) - (If the paths are not absolute, then the source and dest files must be relative to the current working directory.) - - Returns 0 on success. - Returns -1 if a given offset is negative. - Returns -5 if the given begOffset is bigger than the given endOffset. (I.e you reversed the offsets.) - Returns -9 if the memory buffer could not be allocated. - Returns -10 if the source file was not given. - Returns -11 if the source file could not be opened. - Returns -12 if the beginning offset given is larger than the source file. - Returns -13 if the ending offset given is larger than the source file. - Returns -14 if an I/O error occured while reading the source file. - Returns -15 if a logical error occured while reading the source file. - Returns -16 if end of file was encountered unexpectedly. (I.e It was expected that the source file had more data in it.) - Returns -17 if the given source file was a directory. - Returns -20 if the dest file was not given. - Returns -21 if dest file could not be opened. - Returns -24 if an I/O error occured while writing to the dest file. - Returns -25 if a logical error occured while writing to the dest file. - Returns -27 if the given dest file was a directory. - Returns -33 if FileUtills::IsFileOrDirectory() returns -3. (OS / Arch not supported.) - Returns -34 if FileUtills::IsFileOrDirectory() returns -4. (A permissions error occured.) - Returns -35 if FileUtills::IsFileOrDirectory() returns -5. (The given path is empty.) - Returns -36 if FileUtills::IsFileOrDirectory() returns -6. (A path componet does not exist.) - Returns -37 if FileUtills::IsFileOrDirectory() returns -7. (The path has a file in it and is not at the end. (I.e you are treating a file as a directory.)) - Returns -39 if FileUtills::IsFileOrDirectory() returns -9. (All other errors.) - Returns -99 if an exception is thrown while copying data. -*/ -short CopyFile(const std::string & src, const std::string & dest, const bool & append = false, - const streamsize & begOffset = 0, const streamsize & endOffset = 0); - -/*! - short FileUtills::CopyPath(const std::string & src, const std::string & dest, const bool & recursive, - const bool & rename, const bool & abort_on_failure, - const bool & append, const streamsize & begOffset, - const streamsize & endOffset) - - This function takes a given source path and copies it to the given dest path. - - This function supports files and directories. - (Do note that while copying files, you must give ABS (absolute) paths to the src and dest. - If you give a file as src and a directory as dest, the function WILL return an error.) - - If the given src is a file, then this function acts as a wrapper to FileUtills::CopyFile(), and returns all of it's - error codes. - - If the given src is a directory, then this function will copy the entire directory to the given dest, creating dest if - nessacarry. If recursive is set to true, then the entire directory AND it's subdirectories will be copied. - (The subdirectories will be created as needed, if a subdirectory already exists, then the data from src will be merged.) - - @pram recursive, if this is true, then this function will recursively copy all subdirectories from src. Merging / creating - subdirectories as needed. Otherwise this function will only copy the top level directory. (Default) - If src is a file, then this pram has no effect. - - @pram rename, if this is set to true, then this function will try to rename the file rather than copy it. - otherwise a copy will be performed (Default). - It should be noted that a rename is equivelent to calling CopyFile(), and then DeletePath() on the same source. - (Minus the overhead and extra disk space use of actually copying the source first.) And that renaming a - src will only work if the dest is on the same filesystem. - In the event that rename fails, then a copy will be performed UNLESS abort_on_failure is set to true. In that case - the function will abort imeadently. - NOTE: Currently rename does nothing, as the RenamePath() function does not exist. - - @pram abort_on_failure, if this is set to true then this function will abort when the first failure is encountered. - otherwise this function will try to continue with the remaining list of files and subdirectories. (Default) - - @pram append, this is only used if src is a file. (As this function acts as a wrapper to CopyFile() in that case, - see FileUtills::CopyFile() for it's description. This function provides the same default value for this pram as CopyFile().) - If src is a directory, this pram has no effect. - - @pram begOffset, this is only used if src is a file. (As this function acts as a wrapper to CopyFile() in that case, - see FileUtills::CopyFile() for it's description. This function provides the same default value for this pram as CopyFile().) - If src is a directory, this pram has no effect. - - @pram endOffset, this is only used if src is a file. (As this function acts as a wrapper to CopyFile() in that case, - see FileUtills::CopyFile() for it's description. This function provides the same default value for this pram as CopyFile().) - If src is a directory, this pram has no effect. - - Below are return codes for when src is a directory, if src is a file, then the return codes for this function are identical to - FileUtills::CopyFile(). Please see FileUtills::CopyFile() for it's return codes. - - Returns 0 on success. - Returns -1 if the function was unable to create top level dest path and top level dest path does not exist. - Returns -2 if the top level dest path exists and is a file or some other filesystem entry. - Returns -3 if the host OS / Arch is unsupported. - Returns -4 if the function could not get a directory listing. - Returns -5 if the function could not get parent directory string. - Returns -6 if the function was unable to copy all files. (Some files may have been copied however.) - Returns -13 if FileUtills::IsFileOrDirectory() returns -3. (OS / Arch not supported.) - Returns -14 if FileUtills::IsFileOrDirectory() returns -4. (A permissions error occured.) - Returns -15 if FileUtills::IsFileOrDirectory() returns -5. (The given path is empty.) - Returns -16 if FileUtills::IsFileOrDirectory() returns -6. (A path componet does not exist.) - Returns -17 if FileUtills::IsFileOrDirectory() returns -7. (The path has a file in it and is not at the end. (I.e you are treating a file as a directory.)) - Returns -19 if FileUtills::IsFileOrDirectory() returns -9. (All other errors.) -*/ -short CopyPath(const std::string & src, const std::string & dest, const bool & recursive = false, - const bool & rename = false, const bool & abort_on_failure = false, - const bool & append = false, const streamsize & begOffset = 0, const streamsize & endOffset = 0); - -/*! - short FileUtills::MovePath(const std::string & src, const std::string & dest, const bool & overwrite) - - Acts as a wrapper for a call to CopyPath and DeletePath. - The src file is copied to the dest file and then the src file is deleted. - - Returns 0 on success. - Returns -10 If an error occurs while accessing the src file. - Returns -20 If dest already exists and overwriting is disabled. - Returns -21 If dest already exists and can't be deleted. (overwrite = true) - Returns -22 If an error occurs while accessing the dest file. - Returns -3 If an Implementation does not exist for your system. - Returns -4 If an error occurs while moving data. - Returns -5 If an argument to the function is bad. -*/ -short MovePath(const std::string & src, const std::string & dest, const bool & overwrite = false); - -} - - -#endif - -// End of FileUtills.h +/*! + Multiverse Engine Project 04/12/2011 FileUtills FileUtills.h + Yes we are reinventing the wheel here, go with it. + + Copyright (C) 2014 Multiverse Engine Project + + This program is free software; + you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this program; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Official source repository and project information can be found at + https://github.com/codebase7/mengine +*/ + +#ifndef FILEUTILLS +#define FILEUTILLS + +// Engine Includes +#ifdef __win32 +#include "..\BaseHeader.h" +#include "..\Error_Handler\Common_Error_Handler.h" +#include "..\Error_Handler\Common_Error_Handler_Internal.h" +#else +#include "../BaseHeader.h" +#include "../Error_Handler/Common_Error_Handler.h" +#include "../Error_Handler/Common_Error_Handler_Internal.h" +#endif + +namespace FileUtills{ + +#ifdef _WIN32 +// Define the Windows Directory seperator +#define DIR_SEP '\\' +#define HOME_DIR_SYMBOL '~' +// Define the minimal valid absolute directory path length. +/* + * MINIMAL_VALID_ABSOLUTE_PATH_LENGTH is supposed to include the needed DIR_SEP for the root directory. + * In addition it is supposed to be the minimal number of char(s) needed to represent a valid absolute path + * to a root directory. + * + * In windows ":" is minimal for an absolute path. (Root of given drive.) + */ +#define MINIMAL_VALID_ABSOLUTE_PATH_LENGTH 3 +#else +// Define the Posix Directory Seperator. +#ifndef DIR_SEP +#define DIR_SEP '/' +#define HOME_DIR_SYMBOL '~' +#define Relative_Symbol "./" +/* + * MINIMAL_VALID_ABSOLUTE_PATH_LENGTH is supposed to include the needed DIR_SEP for the root directory. + * In addition it is supposed to be the minimal number of char(s) needed to represent a valid absolute path + * to a root directory. + * + * In linux "" is minimal for an absolute path. (Root of the entire filesystem / chroot.) + */ +#define MINIMAL_VALID_ABSOLUTE_PATH_LENGTH 1 +#endif +#endif + +// Define the directory list structure +struct dirlist{ + size_t numOfEntries; // Used to store the number of entries in the list array. + std::vector list; // Used to store the directory's entry data. + std::string path; // Used to store the path of the directory that the entry list is about. +}; + +/*! + * int FileUtills::GetUserProfileDirectoryPath(std::string & path) + * + * Fetches the user's profile directory from the enviorment, and stores + * it in the given path argument. (Note: The given path argument will be + * erased when this function is called. So take care not to leave something + * in it you need.) + * + * If the function fails for any reason, path will be an empty string, + * the returned error code and Common::commonLastErrorCode will be set + * to the approiate error. + */ +int GetUserProfileDirectoryPath(std::string & path); + +/*! + * int FileUtills::GetCurrentWorkingDirectoryPath(std::string & path) + * + * Fetches the current working directory from the enviorment, and stores + * it in the given path argument. (Note: The given path argument will be + * erased when this function is called. So take care not to leave something + * in it you need.) + * + * If the function fails for any reason, path will be an empty string, + * the returned error code and Common::commonLastErrorCode will be set + * to the approiate error. + */ +int GetCurrentWorkingDirectoryPath(std::string & path); + +/*! + * int FileUtills::GetExecDirectory(std::string & retStr) + * + * Replaces the contents of the given retStr argument with a NULL + * terminated std::string that contains the path to the directory where the + * executable is stored. + * + * If the function fails for any reason, the retStr argument will NOT be altered, + * and the appropriate error will be returned to the caller. + */ +int GetExecDirectory(std::string & retStr); + +/*! + int getDirectory(const std::string & path, FileUtills::dirlist ** dirTree, const bool & cleanList) + + Lists the given directory's contents. + + Pram: path, path of directory to check. + + Pram: FileUtills::dirlist ** dirTree, pointer to a pointer to a + FileUtills::dirlist structure that will contain the resulting + directory listing if successful. If the structure is already + allocated when passed to this function and this function succeeds, + the pre-existing structure will be deallocated. + + Pram: cleanList, If this is true then, the generated list will be sorted + (via decrementing sort), and the list will have the entries for the current + and parent directories removed. + Default is to do nothing, and return the list as the OS generated it. + + WARNING: The OS generated list has no guarantee that it will always show up + in the same order, as that depends on the underlying OS and filesystem. + + If you need a predictable list, (I.e. a list that always shows up in the same + order (excluding ANY modifications to the filesystem)) then you should always + set cleanList to true when calling this function. + + Returns COMMON_ERROR_SUCCESS if successfull, dirTree's pointer will point to a valid + FileUtills::dirlist structure with the given path's contents in this case. + (Any previous structure pointed to by the dirTree pointer will be deallocated.) + + Otherwise this function will return the appropriate error, and dirTree's pointer will + not be modified. +*/ +int getDirectory(const std::string & path, dirlist ** dirTree, const bool & cleanList = false); + +/*! + int FileUtills::DoesExist(const std::string & path) + + Prams: @std::string path, path to check for existance on the filesystem. + + This function checks to see if given file or directory exists. + + This function is called by FileUtills::CheckPermissions() before runing permission checks. + + The returned error code is always copied to Common::commonLastErrorCode. + + Returns FILEUTILLS_ERROR_EXISTANT if file or directory exists on the system. + Returns FILEUTILLS_ERROR_NON_EXISTANT if file or directory does not exist on the system. + Returns COMMON_ERROR_INVALID_ARGUMENT if the given path is empty. + Returns COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED if the given system is unsupported. + Returns the approiate error in all other instances. +*/ +int DoesExist(const std::string & path); + +/*! + FileUtills::IsFileOrDirectory(const std::string & path) + + Checks to see if a given path is a file or directory. + + The returned error code is always copied to Common::commonLastErrorCode. + + Returns COMMON_ERROR_SUCCESS if the path exists but it is not a file or directory. + Returns FILEUTILLS_ERROR_PATH_IS_A_FILE if the path is a file. + Returns FILEUTILLS_ERROR_PATH_IS_A_DIRECTORY if the path is a directory. + Returns COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED if the given system is unsupported. + Returns COMMON_ERROR_ACCESS_DENIED if a permissions error occurs. + Returns COMMON_ERROR_INVALID_ARGUMENT if the given path is empty. + Returns FILEUTILLS_ERROR_NON_EXISTANT if a path componet does not exist. + Returns FILEUTILLS_ERROR_ if the path has a file in it and is not at the end. (I.e you are treating a file as a directory.) + Returns the approiate error in all other instances. +*/ +int IsFileOrDirectory(const std::string & path); + +/*! + int FileUtills::CheckParent(const std::string & path, const bool & read, const bool & write, const bool & exec) + + Acts as a wrapper to DoesExist and CheckPermissions + Checks for the parent directory's existance in the path given. + Also Checks to see if it is accessible. By default it checks for Read and Write access. + (Optionaly it can check for execute permissions, and any combonation of the three. This + function will return a COMMON_ERROR_INVALID_ARGUMENT error however if all of the permissions to check + are false.) + + Ex. If this path is given: "/home/user/Homework.txt", this function will check and see if the "/home/user" parent + directory exists, and if it is accessable. + + The returned error code is always copied to Common::commonLastErrorCode. + + Returns COMMON_ERROR_SUCCESS if the directory exists and is accessible with the requested permissions. + Returns COMMON_ERROR_ACCESS_DENIED if A permission error occurs. + Returns FILEUTILLS_ERROR_NON_EXISTANT if the parent directory does not exist. + Returns COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED if the OS / Arch is not supported. + Returns COMMON_ERROR_SYSTEM_SPECIFIC if a system specific / untranslated error occurs. + Returns COMMON_ERROR_INTERNAL_ERROR if an engine error occurs. + Returns COMMON_ERROR_UNKNOWN_ERROR if an unknown error occurs. + Returns COMMON_ERROR_EXCEPTION_THROWN if an exception is thrown. + Returns the approiate error in all other cases. +*/ +int CheckParent(const std::string & path, const bool & read = true, const bool & write = true, const bool & exec = false); + +/*! + std::string FileUtills::GetParent(const std::string & path) + + Returns the parent directory for the given file. + + Gets the path exactly like FileUtills::CheckParent(). + + Returns std::string with parent directory path if successful. + Returns an empty string otherwise, and sets + Common::commonLastErrorCode to the approiate error code. +*/ +std::string GetParent(const std::string & path); + +/*! + int FileUtills::ResolvePath(const char * path, const size_t pathSize, char * retStr, size_t * retStrSize, const bool disableSymLinkResolution) + + Checks the path given, and converts it to a absolute path. + + Setting disableSymLinkResolution to true will disable resolving any symbolic link(s) if a + symbolic link is encountered while resolving the given path(s). Setting + disableSymLinkResolution to false will make this function resolve any + symbolic link(s) that are encountered while resolving the given path(s). + + Returns COMMON_ERROR_SUCCESS if successfull, retStr and retStrSize will be altered in this + case. (Any pre-existing c-string given to this function as retStr will be deallocated.) + + Otherwise the approiate error code is returned. (retStr and retStrSize will be unaltered in + this instance.) +*/ +int ResolvePath(const char * path, const size_t pathSize, char * retStr, size_t * retStrSize, const bool disableSymLinkResolution); + +/*! + int FileUtills::CreateDirectory(const std::string & directory, const bool & createRecursive) + @pram : directory, path to create. + @pram : createRecursive, if this is set to true, then this function will try to create the + parent directories of the given directory if they do not exist. + + This function attempts to create the given directory on the filesystem. + + The returned error code is always copied to Common::commonLastErrorCode. + + Returns COMMON_ERROR_SUCCESS if directory creation was successful. + Returns COMMON_ERROR_ACCESS_DENIED if permission is denied. + Returns COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED if this function is unsupported. + Returns FILEUTILLS_ERROR_FILESYSTEM_FULL if the disk is full. + Returns FILEUTILLS_ERROR_EXISTANT if the directory already exists. + Returns the approiate error or COMMON_ERROR_UNKNOWN_ERROR if another error is encountered. +*/ +int CreateDirectory(const std::string & directory, const bool & createRecursive = false); + +/*! + int FileUtills::CheckPermissions(const std::string & path, const bool & read, const bool & write, const bool & exec) + + Checks Permissions on the given file or directory. Also checks if the given file or directory + actully exists first before checking other permissions. By default it will check for both read and + write permissions. (Optionaly it can check for execute permissions, and any combonation of the three. This + function will return a COMMON_ERROR_INVALID_ARGUMENT error however if all of the permissions to check + are false.) + + Pram: path to directory or file to check. + Pram: check for read permission. default is true. + Pram: check for wrtie permission. default is true. + Pram: check for execute permission. default is false. + + The returned error code is always copied to Common::commonLastErrorCode. + + Returns COMMON_ERROR_SUCCESS if the directory exists and is accessible with the requested permissions. + Returns COMMON_ERROR_ACCESS_DENIED if A permission error occurs. + Returns FILEUTILLS_ERROR_NON_EXISTANT if the parent directory does not exist. + Returns COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED if the OS / Arch is not supported. + Returns COMMON_ERROR_SYSTEM_SPECIFIC if a system specific / untranslated error occurs. + Returns COMMON_ERROR_INTERNAL_ERROR if an engine error occurs. + Returns COMMON_ERROR_UNKNOWN_ERROR if an unknown error occurs. + Returns COMMON_ERROR_EXCEPTION_THROWN if an exception is thrown. + Returns the approiate error in all other cases. +*/ +int CheckPermissions(const std::string & path, const bool & read = true, const bool & write = true, const bool & exec = false); + +/*! + int FileUtills::GetGigaFreespace(const std::string & path, size_t & result) + + Returns the remaining disk space in Gigabytes (SI Unit) on the given disk. + + Note if an error occurs, result will be set to zero, and an error code will be returned. + (Although result can also be set to zero if there really is no remaining disk space.) + + @pram const std::string & path : volume / path to check. + @pram size_t & result : The remaining space on the filesystem. + + The returned error code is always copied to Common::commonLastErrorCode. + + Returns COMMON_ERROR_SUCCESS if successfull, result will contain the remaining space. + Returns a Common namespace error if an error occurs. Size will be equal to zero in this + case. To obtain more detailed info register an error hander before calling this function. +*/ +int GetGigaFreespace(const std::string & path, size_t & result); + +/*! + int FileUtills::GetFreespace(const std::string & path, size_t & result) + + Returns the remaining disk space in Megabytes (SI Unit) on the given disk. + + Note if an error occurs, result will be set to zero, and an error code will be returned. + (Although result can also be set to zero if there really is no remaining disk space.) + + @pram const std::string & path : volume / path to check. + @pram size_t & result : The remaining space on the filesystem. + + The returned error code is always copied to Common::commonLastErrorCode. + + Returns COMMON_ERROR_SUCCESS if successfull, result will contain the remaining space. + Returns a Common namespace error if an error occurs. Size will be equal to zero in this + case. To obtain more detailed info register an error hander before calling this function. +*/ +int GetFreespace(const std::string & path, size_t & result); + +/*! + int FileUtills::GetKiloFreespace(const std::string & path, size_t & result) + + Returns the remaining disk space in Kilobytes (SI Unit) on the given disk. + + Note if an error occurs, result will be set to zero, and an error code will be returned. + (Although result can also be set to zero if there really is no remaining disk space.) + + @pram const std::string & path : volume / path to check. + @pram size_t & result : The remaining space on the filesystem. + + The returned error code is always copied to Common::commonLastErrorCode. + + Returns COMMON_ERROR_SUCCESS if successfull, result will contain the remaining space. + Returns a Common namespace error if an error occurs. Size will be equal to zero in this + case. To obtain more detailed info register an error hander before calling this function. +*/ +int GetKiloFreespace(const std::string & path, size_t & result); + +/*! + int FileUtills::GetByteFreespace(const std::string & path, size_t & result) + + Returns the remaining disk space in Bytes (SI Unit) on the given disk. + + Note if an error occurs, result will be set to zero, and an error code will be returned. + (Although result can also be set to zero if there really is no remaining disk space.) + + @pram const std::string & path : volume / path to check. + @pram size_t & result : The remaining space on the filesystem. + + The returned error code is always copied to Common::commonLastErrorCode. + + Returns COMMON_ERROR_SUCCESS if successfull, result will contain the remaining space. + Returns a Common namespace error if an error occurs. Size will be equal to zero in this + case. To obtain more detailed info register an error hander before calling this function. +*/ +int GetByteFreespace(const std::string & path, size_t & result); + +/*! + int FileUtills::DeletePath(const std::string & path, const bool & recursive) + + This function attempts to delete the given file or directory from the filesystem. + + By default this function will NOT delete recursively. + If the given path is a non-empty directory, by default this function will throw an error. + If the given path is an empty directory, however by default this function WILL delete it. + + Note: If while deleting rescursively, a file or subdirectory can't be deleted, this function will try to continue + deleting any other files and subdirectories that can be deleted, but it will throw an error apon exit. + + The returned error code is always copied to Common::commonLastErrorCode. + + Returns 0 if successful. + -1 if the user lacks permission to delete the path. (Or if recursively deleting a directory, a file or subdirectory could not be deleted.) + -2 if the path does not exist. (Or if recursively deleting a directory, a file or subdirectory does not exist.) + -3 if the function is not supported. + -4 if a memory error occurs. + -5 if an unknown error occurs. (An error other than a permissions error occured while deleting something.) + -6 if the path is a non empty directory and recursive is set to false. + -7 if while deleting recursively, the parent directory of a deleted directory could not be obtained. (I.e could not "go up a level in the directory tree.") + -8 if while deleting recursively, there were files and or subdirectories that could not be deleted. (Some files may have been deleted however.) +*/ +int DeletePath(const std::string & path, const bool & recursive = false); + +/*! + int FileUtills::CopyFile(const std::string & src, const std::string & dest, const bool & append, + const streamsize & begOffset, const streamsize & endOffset) + + Copies endOffset bytes starting at begOffset, from source file to dest file. + + Offset rules: + - If offsets are used, they must be positive. (If one or both of the given offsets is negative, + then COMMON_ERROR_INVALID_ARGUMENT will be returned.) + + - If zeros are used for both offsets, then the entire file will be copied. + + - If endOffset is greater than begOffset then the given range of bytes + from the file will be copied. + + - If begOffset is equal to zero and endOffset is greater than zero, then + the file will be copied from the start of the file to endOffset. + + - If begOffset is greater than zero and endOffset is equal to zero, then + the file will be copied from begOffset to the end of the file. + + - If any offset is not zero, then ONLY IF the file has enough bytes in it + to copy the given range of bytes from the given beginning offset, will the + copy take place. + (This allows for some insurance if the source file's size is known before + calling this function.) + + This function only works on FILES. Not directories. To copy a directory, call FileUtills::CopyPath(). + + @pram src, path to the source file. + @pram dest, path to the dest file. + + @pram append, Whether or not to append data to the dest file. + (Note only applies if the dest file exists. If append is false, then the dest file will be overwritten.) + + @pram begOffset, Location in the source file to start copying data from. + @pram endOffset, Location in the source file to stop copying data when it is reached. + + By default the entire file is copied and the dest file is overwritten. + + Note: This function does NOT make any attempt to preserve the destionation file if it already exists. + + Note: This function can return ANY error in the Common namespace error list, below is only an example + of what errors this function itself may generate. (I.e. This function calls other FileUtills functions + and as such can return the errors generated by them.) If you need a more detailed error message, you + should register a callback function for the Common error handler (via Common::Register_Error_Log_Callback()) + before calling this function. + + Returns COMMON_ERROR_SUCCESS on success. + Returns COMMON_ERROR_INVALID_ARGUMENT if a given offset is negative. + Returns COMMON_ERROR_INVALID_ARGUMENT if the given begOffset is bigger than the given endOffset. (I.e you reversed the offsets.) + Returns COMMON_ERROR_MEMORY_ERROR if the memory buffer could not be allocated. + Returns COMMON_ERROR_INVALID_ARGUMENT if the source file was not given. + Returns COMMON_ERROR_IO_ERROR if the source file could not be opened. + Returns COMMON_ERROR_IO_ERROR if an I/O error occured while reading the source file. + Returns COMMON::FILEUTILLS_PATH_IS_A_DIRECTORY if the given source file was a directory. + Returns COMMON_ERROR_INVALID_ARGUMENT if the dest file was not given. + Returns COMMON_ERROR_IO_ERROR if dest file could not be opened. + Returns COMMON_ERROR_IO_ERROR if an I/O error occured while writing to the dest file. + Returns FILEUTILLS_ERROR_PATH_IS_A_DIRECTORY if the given dest file was a directory. + Returns COMMON_ERROR_EXCEPTION_THROWN if an exception is thrown while copying data. +*/ +int CopyFile(const std::string & src, const std::string & dest, const bool & append = false, + const streamsize & begOffset = 0, const streamsize & endOffset = 0); + +/*! + int FileUtills::CopyPath(const std::string & src, const std::string & dest, const bool & recursive, + const bool & rename, const bool & abort_on_failure, + const bool & append, const streamsize & begOffset, + const streamsize & endOffset) + + This function takes a given source path and copies it to the given dest path. + + This function supports files and directories. + If you give a file as src and a directory as dest, the function WILL return an error. + + If the given src is a file, then this function acts as a wrapper to FileUtills::CopyFile(), and returns all of it's + error codes. + + If the given src is a directory, then this function will copy the entire directory to the given dest, creating dest if + nessacarry. If recursive is set to true, then the entire directory AND it's subdirectories will be copied. + (The subdirectories will be created as needed, if a subdirectory already exists, then the data from src will be merged.) + + @pram recursive, if this is true, then this function will recursively copy all subdirectories from src. Merging / creating + subdirectories as needed. Otherwise this function will only copy the top level directory. (Default) + If src is a file, then this pram has no effect. + + @pram rename, if this is set to true, then this function will try to rename the file rather than copy it. + otherwise a copy will be performed (Default). + It should be noted that a rename is equivelent to calling CopyFile(), and then DeletePath() on the same source. + (Minus the overhead and extra disk space use of actually copying the source first.) And that renaming a + src will only work if the dest is on the same filesystem. + In the event that rename fails, then a copy will be performed UNLESS abort_on_failure is set to true. In that case + the function will abort imeadently. + NOTE: Currently rename does nothing, as the RenamePath() function does not exist. + + @pram abort_on_failure, if this is set to true then this function will abort when the first failure is encountered. + otherwise this function will try to continue with the remaining list of files and subdirectories. (Default) + + @pram append, this is only used if src is a file. (As this function acts as a wrapper to CopyFile() in that case, + see FileUtills::CopyFile() for it's description. This function provides the same default value for this pram as CopyFile().) + If src is a directory, this pram has no effect. + + @pram begOffset, this is only used if src is a file. (As this function acts as a wrapper to CopyFile() in that case, + see FileUtills::CopyFile() for it's description. This function provides the same default value for this pram as CopyFile().) + If src is a directory, this pram has no effect. + + @pram endOffset, this is only used if src is a file. (As this function acts as a wrapper to CopyFile() in that case, + see FileUtills::CopyFile() for it's description. This function provides the same default value for this pram as CopyFile().) + If src is a directory, this pram has no effect. + + Below are return codes for when src is a directory, if src is a file, then the return codes for this function are identical to + FileUtills::CopyFile(). Please see FileUtills::CopyFile() for it's return codes. + + Returns 0 on success. + Returns -1 if the function was unable to create top level dest path and top level dest path does not exist. + Returns -2 if the top level dest path exists and is a file or some other filesystem entry. + Returns -3 if the host OS / Arch is unsupported. + Returns -4 if the function could not get a directory listing. + Returns -5 if the function could not get parent directory string. + Returns -6 if the function was unable to copy all files. (Some files may have been copied however.) + Returns -13 if FileUtills::IsFileOrDirectory() returns -3. (OS / Arch not supported.) + Returns -14 if FileUtills::IsFileOrDirectory() returns -4. (A permissions error occured.) + Returns -15 if FileUtills::IsFileOrDirectory() returns -5. (The given path is empty.) + Returns -16 if FileUtills::IsFileOrDirectory() returns -6. (A path componet does not exist.) + Returns -17 if FileUtills::IsFileOrDirectory() returns -7. (The path has a file in it and is not at the end. (I.e you are treating a file as a directory.)) + Returns -19 if FileUtills::IsFileOrDirectory() returns -9. (All other errors.) +*/ +int CopyPath(const std::string & src, const std::string & dest, const bool & recursive = false, + const bool & rename = false, const bool & abort_on_failure = false, + const bool & append = false, const streamsize & begOffset = 0, const streamsize & endOffset = 0); + +/*! + int FileUtills::MovePath(const std::string & src, const std::string & dest, const bool & overwrite) + + Acts as a wrapper for a call to CopyPath and DeletePath. + The src file is copied to the dest file and then the src file is deleted. + + Returns 0 on success. + Returns -10 If an error occurs while accessing the src file. + Returns -20 If dest already exists and overwriting is disabled. + Returns -21 If dest already exists and can't be deleted. (overwrite = true) + Returns -22 If an error occurs while accessing the dest file. + Returns -3 If an Implementation does not exist for your system. + Returns -4 If an error occurs while moving data. + Returns -5 If an argument to the function is bad. +*/ +int MovePath(const std::string & src, const std::string & dest, const bool & overwrite = false); + +} + + +#endif + +// End of FileUtills.h diff --git a/src/Common/Src/File_Management_Subsystem/FileUtills_Emulated_Symbolic_Link_Functions.cpp b/src/Common/Src/File_Management_Subsystem/FileUtills_Emulated_Symbolic_Link_Functions.cpp new file mode 100644 index 0000000..440e352 --- /dev/null +++ b/src/Common/Src/File_Management_Subsystem/FileUtills_Emulated_Symbolic_Link_Functions.cpp @@ -0,0 +1,307 @@ +/*! + Multiverse Engine Project 21/8/2014 FileUtills FileUtills_Emulated_Symbolic_Link_Functions.cpp + Yes we are reinventing the wheel here, go with it. + + Copyright (C) 2014 Multiverse Engine Project + + This program is free software; + you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this program; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Official source repository and project information can be found at + https://github.com/codebase7/mengine +*/ + +// Include header file. +#include "FileUtills_Emulated_Symbolic_Link_Functions.h" + +int FileUtills::Create_MSYS_Emulated_Symbolic_Link(const std::string & linkDestionation, const std::string & pathToLinkFile) +{ + // Init vars. + int ret = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; // The result of this function. + size_t linkSize = linkDestionation.size(); // The size of the link destionation. + fstream outputFile; // The fstream for the emulated link file. + + // Check for valid arguments. + if (linkSize > 0) + { + if (pathToLinkFile.size() > 0) + { + // Begin try block. + try { + // Open the link file in append mode. + outputFile.open(pathToLinkFile.c_str(), std::ios::out | std::ios::binary | std::ios::append); + if (outputFile.is_open()) + { + // OK, Check to see if the file is blank. + outputFile.seekg(0, std::ios::end); + if (outputFile.tellg() == 0) + { + // OK, seek back to the beginning. + outputFile.seekg(0, std::ios::beg); + + // Now output the magic string. + outputFile << MSYS_EMU_SYMLINK_MAGIC; + + // Determine if we need to swap the byte order of the integers. (size of length and the length itself are supposed to be little-endian encoded.) + if (DataProcess::) + { + // Now we need to output the number of bytes for the destionationLink string's length. (ie. sizeof(size_t)). (This is in little-endianess format.) + outputFile << + + // Now we need to output the length of the destionationLink string. (This is in little-endianess format.) + outputFile << + } + else + { + // Now we need to output the number of bytes for the destionationLink string's length. (ie. sizeof(size_t)). (This is in little-endianess format.) + outputFile << + + // Now we need to output the length of the destionationLink string. (This is in little-endianess format.) + outputFile << + } + + // Output the destionationLink string. + outputFile << destionationLink; + + // Flush the output buffer. + outputFile.flush(); + + // Check for good output buffer. + if (outputFile.good()) + { + // Success. + ret = COMMON_ERROR_SUCCESS; + } + else + { + // IO Error. + ret = COMMON_ERROR_IO_ERROR; + + // Log the error. + COMMON_LOG_DEBUG("FileUtills::Create_MSYS_Emulated_Symbolic_Link(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(ret)); + COMMON_LOG_DEBUG(" Unable to create emulated symbolic link file ( "); + COMMON_LOG_DEBUG(pathToLinkFile.c_str()); + COMMON_LOG_DEBUG(" )\n"); + + // Invalidate link file. + outputFile.clear(); + outputFile.seekp(0, std::ios::beg); + outputFile.seekg(0, std::ios::beg); + outputFile.put('\0'); + } + + // Close the file. + outputFile.close(); + } + else + { + // File is not empty, abort. + ret = FILEUTILLS_ERROR_EXISTANT; + + // Log the error. + COMMON_LOG_INFO("FileUtills::Create_MSYS_Emulated_Symbolic_Link(): "); + COMMON_LOG_INFO(Common::Get_Error_Message(ret)); + COMMON_LOG_INFO(" The given path ( "); + COMMON_LOG_INFO(pathToLinkFile.c_str()); + COMMON_LOG_INFO(" ) already exists.\n"); + } + } + else + { + // Could not open output file for writing. + ret = COMMON_ERROR_IO_ERROR; + + // Log the error. + COMMON_LOG_INFO("FileUtills::Create_MSYS_Emulated_Symbolic_Link(): "); + COMMON_LOG_INFO(Common::Get_Error_Message(ret)); + COMMON_LOG_INFO(" Unable to open ( "); + COMMON_LOG_INFO(pathToLinkFile.c_str()); + COMMON_LOG_INFO(" ) for writing.\n"); + } + } + catch(exception &ex) + { + // Exception thown. + ret = COMMON_ERROR_EXCEPTION_THROWN; + COMMON_LOG_VERBOSE("FileUtills::Create_MSYS_Emulated_Symbolic_Link(): "); + COMMON_LOG_VERBOSE(Common::Get_Error_Message(ret)); + COMMON_LOG_VERBOSE(" "); + COMMON_LOG_VERBOSE(ex.what()); + COMMON_LOG_VERBOSE("\n"); + } + } + else + { + // Invalid path. + ret = COMMON_ERROR_INVALID_ARGUMENT; + + // Log the error. + COMMON_LOG_DEBUG("FileUtills::Create_MSYS_Emulated_Symbolic_Link(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(COMMON_ERROR_INVALID_ARGUMENT)); + COMMON_LOG_DEBUG(" Given path to the emulated link file is invalid.\n"); + } + } + else + { + // Invalid destionationLink. + ret = COMMON_ERROR_INVALID_ARGUMENT; + + // Log the error. + COMMON_LOG_DEBUG("FileUtills::Create_MSYS_Emulated_Symbolic_Link(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(COMMON_ERROR_INVALID_ARGUMENT)); + COMMON_LOG_DEBUG(" Given destionation link string is invalid.\n"); + } + + // Close the file if it's still open. + if (outputFile.is_open()) + { + outputFile.close(); + } + + // Copy the result to Common::commonLastErrorCode. + Common::commonLastErrorCode = ret; + + // Return the result. + return ret; +} + +int FileUtills::Read_MSYS_Emulated_Symbolic_Link(std::string & link, const std::string & pathToLinkFile) +{ + // Init vars. + int ret = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; // The result of this function. + std::string tempLinkBuf = ""; // Temporary buffer for constructing the link string. + fstream inputFile; // The fstream for the emulated link file. + + // Blank the link string. + link.clear(); + + // Check for valid argument. + if (pathToLinkFile.size() > 0) + { + // Begin try block. + try { + + + } + catch(exception &ex) + { + // Exception thown. + ret = COMMON_ERROR_EXCEPTION_THROWN; + COMMON_LOG_VERBOSE("FileUtills::Read_MSYS_Emulated_Symbolic_Link(): "); + COMMON_LOG_VERBOSE(Common::Get_Error_Message(ret)); + COMMON_LOG_VERBOSE(" "); + COMMON_LOG_VERBOSE(ex.what()); + COMMON_LOG_VERBOSE("\n"); + } + } + else + { + // Invalid path. + ret = COMMON_ERROR_INVALID_ARGUMENT; + + // Log the error. + COMMON_LOG_DEBUG("FileUtills::Read_MSYS_Emulated_Symbolic_Link(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(COMMON_ERROR_INVALID_ARGUMENT)); + COMMON_LOG_DEBUG(" Given path to the emulated link file is invalid.\n"); + } + + // Close the file if it's still open. + if (inputFile.is_open()) + { + inputFile.close(); + } + + // If we failed, blank the link string. + if (ret != COMMON_ERROR_SUCCESS) + { + tempLinkBuf.clear(); + link.clear(); + } + + // Copy the result to Common::commonLastErrorCode. + Common::commonLastErrorCode = ret; + + // Return the result. + return ret; +} + +int FileUtills::Update_MSYS_Emulated_Symbolic_Link(const std::string & linkDestionation, const std::string & pathToLinkFile) +{ + // Init vars. + int ret = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; // The result of this function. + size_t linkSize = linkDestionation.size(); // The size of the link destionation. + std::string tempLinkBuf = ""; // Temporary buffer for constructing the link string. + fstream linkFile; // The fstream for the emulated link file. + + // Check for valid arguments. + if (linkSize > 0) + { + if (pathToLinkFile.size() > 0) + { + // Begin try block. + try { + + + } + catch(exception &ex) + { + // Exception thown. + ret = COMMON_ERROR_EXCEPTION_THROWN; + COMMON_LOG_VERBOSE("FileUtills::Update_MSYS_Emulated_Symbolic_Link(): "); + COMMON_LOG_VERBOSE(Common::Get_Error_Message(ret)); + COMMON_LOG_VERBOSE(" "); + COMMON_LOG_VERBOSE(ex.what()); + COMMON_LOG_VERBOSE("\n"); + } + } + else + { + // Invalid path. + ret = COMMON_ERROR_INVALID_ARGUMENT; + + // Log the error. + COMMON_LOG_DEBUG("FileUtills::Update_MSYS_Emulated_Symbolic_Link(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(COMMON_ERROR_INVALID_ARGUMENT)); + COMMON_LOG_DEBUG(" Given path to the emulated link file is invalid.\n"); + } + } + else + { + // Invalid destionationLink. + ret = COMMON_ERROR_INVALID_ARGUMENT; + + // Log the error. + COMMON_LOG_DEBUG("FileUtills::Update_MSYS_Emulated_Symbolic_Link(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(COMMON_ERROR_INVALID_ARGUMENT)); + COMMON_LOG_DEBUG(" Given destionation link string is invalid.\n"); + } + + // Close the file if it's still open. + if (linkFile.is_open()) + { + linkFile.close(); + } + + // If we failed, blank the link string. + if (ret != COMMON_ERROR_SUCCESS) + { + tempLinkBuf.clear(); + } + + // Copy the result to Common::commonLastErrorCode. + Common::commonLastErrorCode = ret; + + // Return the result. + return ret; +} + +// End of FileUtills_Emulated_Symbolic_Link_Functions.cpp diff --git a/src/Common/Src/File_Management_Subsystem/FileUtills_Emulated_Symbolic_Link_Functions.h b/src/Common/Src/File_Management_Subsystem/FileUtills_Emulated_Symbolic_Link_Functions.h new file mode 100644 index 0000000..702c3d4 --- /dev/null +++ b/src/Common/Src/File_Management_Subsystem/FileUtills_Emulated_Symbolic_Link_Functions.h @@ -0,0 +1,146 @@ +/*! + Multiverse Engine Project 21/8/2014 FileUtills FileUtills_Emulated_Symbolic_Link_Functions.h + Yes we are reinventing the wheel here, go with it. + + Copyright (C) 2014 Multiverse Engine Project + + This program is free software; + you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this program; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Official source repository and project information can be found at + https://github.com/codebase7/mengine +*/ + +// Include guard. +#ifndef FILEUTILLS_EMULATED_SYMBOLIC_LINK_FUNCTIONS_H +#define FILEUTILLS_EMULATED_SYMBOLIC_LINK_FUNCTIONS_H + +// Internal includes. +#include "../Error_Handler/Common_Error_Handler.h" +#include "../Error_Handler/Common_Error_Handler_Internal.h" + +// External includes. +#include +#include +#include +#include + + +/*! + * Description of the emulated symbolic link file format: + * + * Offset 0: Magic string. (E.g. "MSYS_EMU_SYMLINK") + * + * Offset (0 + sizeof()): uint (4 bytes, little endian) size of the length value. (I.e. sizeof(size_t)). + * + * Offset (0 + sizeof() + 4): length of the link. (Length is the same as the read size variable.) + * + * Offset (0 + sizeof() + 4 + (size of the length value)): Start of link. + * + * Offset (0 + sizeof() + 4 + (size of the length value) + ): End of the link, and enf of file. + */ + + +// Define namespace. +namespace FileUtills +{ + // Define magic string for the emulated symbolic link file. + #define MSYS_EMU_SYMLINK_MAGIC "MSYS_EMU_SYMLINK" + + // Define file extension for the emulated symbolic link file. + #define MSYS_EMU_SYMLINK_FILE_EXT "msl" + + // Define functions. + + /*! + * int FileUtills::Create_MSYS_Emulated_Symbolic_Link(const std::string & linkDestionation, const std::string & pathToLinkFile) + * + * Takes the given linkDestionation string and creates an emulated symbolic link file with the string's + * contents at the given path on the filesystem. + * + * NOTE: This function expects that the given path is invalid. (I.e. That no file / directory / some other + * filesystem entry exists at the given path.) In addition this function expects that the given path's + * parent directory exists at the time that this function is called. (I.e. That this function does not + * need to create the directory tree leading up to the file to create.) If either of these assumptions + * are false, this function will abort and return an error. + * + * If successfull this function will return COMMON_ERROR_SUCCESS, and the emulated symbolic link file + * will be present at the given location on the filesystem. + * + * If an error occurs, the approperite Common namespace error code will be returned. In addition, the + * emulated link file will be rendered invalid on the filesystem. (It will still be present on the + * filesystem however, as such it will need to be deleted manually.) + * + * In all instances the returned error code will be copied to Common::commonLastErrorCode. (In addition, + * depending on the configured log level, a human readable error message will be outputted to the logging + * function to better describe the error that occured.) + */ + int Create_MSYS_Emulated_Symbolic_Link(const std::string & linkDestionation, const std::string & pathToLinkFile); + + /*! + * int FileUtills::Read_MSYS_Emulated_Symbolic_Link(std::string & link, const std::string & pathToLinkFile) + * + * Erases the given link argument string, then reads the file from the given path for a symbolic link + * string, and writes it to the given link argument string. + * + * NOTE: This function does NOT resolve the read symbolic link, and will return it as is on the filesystem. + * To resolve the link, either call your own resolver function, or call FileUtills::ResolvePath(). + * + * NOTE: This function is called automaticly by FileUtills::ResolvePath() if symbolic link resolution is + * enabled by the caller (it is by default), and an emulated link file is found during path resolution. + * As such it's not nessacarry to call this function directly before FileUtills::ResolvePath(). + * + * (Sidenote: This function returns read links as is, if the read link is relative to the directory it is in, + * then the link string will need to have the path to the directory that the emulated link file is stored + * in prepended to the link string before calling FileUtills::ResolvePath(). If you fail to do this, + * FileUtills::ResolvePath() will assume that the given emulated link string is relative to the + * calling program's current working directory. (Along with all of the issues that come with that + * assumption.)) + * + * If successfull, the given link argument string will have it's contents replaced with the read link + * string, and COMMON_ERROR_SUCCESS will be returned. + * + * If an error occurs then the given link argument string will be blank / empty, and the approperite + * Common namespace error code will be returned. + * + * In all instances the returned error code will be copied to Common::commonLastErrorCode. (In addition, + * depending on the configured log level, a human readable error message will be outputted to the logging + * function to better describe the error that occured.) + */ + int Read_MSYS_Emulated_Symbolic_Link(std::string & link, const std::string & pathToLinkFile); + + /*! + * int FileUtills::Update_MSYS_Emulated_Symbolic_Link(const std::string & linkDestionation, const std::string & pathToLinkFile) + * + * This function updates a pre-existing emulated link file at the given path on the filesystem, with the contents + * of the given linkDestionation argument string. + * + * NOTE: This function expects that the emulated link file already exists on the filesystem at the given path. It also + * expects that the emulated link file will be valid. If either of these two conditions are not true, then this function + * will abort and return an error. + * + * If successfull, the given emulated link file will contain the contents of the given linkDestionation argument string, and + * the returned error code will be COMMON_ERROR_SUCCESS. + * + * If an error occurs, the approperite Common namespace error code will be returned. In addition, the + * emulated link file will be rendered invalid on the filesystem. (It will still be present on the + * filesystem however, as such it will need to be deleted manually.) + * + * In all instances the returned error code will be copied to Common::commonLastErrorCode. (In addition, + * depending on the configured log level, a human readable error message will be outputted to the logging + * function to better describe the error that occured.) + */ + int Update_MSYS_Emulated_Symbolic_Link(const std::string & linkDestionation, const std::string & pathToLinkFile); +}; + +#endif + +// End of FileUtills_Emulated_Symbolic_Link_Functions.h diff --git a/src/Common/Src/File_Management_Subsystem/FileUtills_Private_API.cpp b/src/Common/Src/File_Management_Subsystem/FileUtills_Private_API.cpp new file mode 100644 index 0000000..39a0177 --- /dev/null +++ b/src/Common/Src/File_Management_Subsystem/FileUtills_Private_API.cpp @@ -0,0 +1,1602 @@ +/*! + Multiverse Engine Project 04/8/2014 FileUtills FileUtills_Private_API.cpp + + Copyright (C) 2014 Multiverse Engine Project + + This program is free software; + you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this program; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Official source repository and project information can be found at + https://github.com/codebase7/mengine +*/ + +#include "FileUtills.h" +#include "FileUtills_Private_API.h" + +int FileUtills::IsAbsolutePathReference(const char * path, const size_t pathSize) +{ + // Init vars. + int ret = COMMON_ERROR_UNKNOWN_ERROR; // Result of this function. + + // Check for a valid arguments. + if ((path != NULL) && (pathSize > 0)) + { + // Check for a valid string. + if (path[0] == '/') // Posix style path. + { + // Valid Posix style path. + ret = FILEUTILLS_ERROR_PATH_IS_ABSOLUTE; + } + else + { + // Check for a Windows / DOS style path. + if ((pathSize > 2) && (path[0] != '\0') && (path[1] == ':') && (path[2] == '\\')) + { + // Valid Windows / DOS style path. + ret = FILEUTILLS_ERROR_PATH_IS_ABSOLUTE; + } + else + { + // Path is not absolute. + ret = FILEUTILLS_ERROR_PATH_IS_RELATIVE; + } + } + } + else + { + // Invalid pointer. + ret = COMMON_ERROR_INVALID_ARGUMENT; + COMMON_LOG_VERBOSE("FileUtills_IsAbsolutePathReference(): "); + COMMON_LOG_VERBOSE(Common_Get_Error_Message(COMMON_ERROR_INVALID_ARGUMENT)); + } + + // Return the result. + return ret; +} + +int FileUtills::IsAbsolutePathReference(const char * path, const size_t pathSize, char ** absRef, size_t * absRefSize) +{ + // Init vars. + int ret = COMMON_ERROR_UNKNOWN_ERROR; // Result of this function. + char * tempAbsRef = NULL; // Temporary variable for construction of absRef. + + // Check for a valid arguments. + if ((path != NULL) && (pathSize > 0) && (absRefSize != NULL)) + { + // Check for a valid string. + if (path[0] == '/') // Posix style path. + { + // Valid Posix style path. + ret = FILEUTILLS_ERROR_PATH_IS_ABSOLUTE; + + // Allocate memory for absRef. + tempAbsRef = (char*)malloc((sizeof(char) * 2)); + if (tempAbsRef != NULL) + { + // Write the data. + tempAbsRef[0] = '/'; + tempAbsRef[1] = '\0'; + + // Copy the pointer. + (*absRef) = tempAbsRef; + + // Update the absRefSize. + absRefSize = (sizeof(char) * 2); + } + else + { + // Could not allocate memory. + ret = COMMON_ERROR_MEMORY_ERROR; + } + } + else + { + // Check for a Windows / DOS style path. + if ((pathSize > 2) && (path[0] != '\0') && (path[1] == ':') && (path[2] == '\\')) + { + // Valid Windows / DOS style path. + ret = FILEUTILLS_ERROR_PATH_IS_ABSOLUTE; + + // Allocate memory for absRef. + tempAbsRef = (char*)malloc((sizeof(char) * 4)); + if (tempAbsRef != NULL) + { + // Write the data. + tempAbsRef[0] = path[0]; + tempAbsRef[1] = path[1]; + tempAbsRef[2] = path[2]; + tempAbsRef[3] = '\0'; + + // Copy the pointer. + (*absRef) = tempAbsRef; + + // Update the absRefSize. + absRefSize = (sizeof(char) * 4); + } + else + { + // Could not allocate memory. + ret = COMMON_ERROR_MEMORY_ERROR; + } + } + else + { + // Path is not absolute. + ret = FILEUTILLS_ERROR_PATH_IS_RELATIVE; + } + } + } + else + { + // Invalid pointer. + ret = COMMON_ERROR_INVALID_ARGUMENT; + COMMON_LOG_VERBOSE("FileUtills_IsAbsolutePathReference(): "); + COMMON_LOG_VERBOSE(Common_Get_Error_Message(COMMON_ERROR_INVALID_ARGUMENT)); + } + + // Return the result. + return ret; +} + +int FileUtills::GetPathSegment(const std::string & path, const size_t & currentPathPos, std::string & pathSegment, const bool & blankPathSegment) +{ + // Init vars. + int ret = COMMON_ERROR_UNKNOWN_ERROR; // The result of this function. + + // Blank pathSegment if needed. + if (blankPathSegment) + { + pathSegment.clear(); + } + + // Check for valid path. + if (path.capacity > 0) + { + // Check for a valid path position. + if (currentPathPos > 0) + { + // Make sure the path position is within the path buffer. + if (currentPathPos < path.capacity()) + { + // Copy the path segment from output. (Search from the given currentPathPos offset.) + for (size_t y = 0; ((y < path.capacity()) && (result == COMMON_ERROR_UNKNOWN_ERROR)); y++) + { + // Look for the DIR_SEP. + if (path[(currentPathPos - y)] == DIR_SEP) + { + // Decrement y, as we don't want to copy the directory seperator. + y--; + + // This position is the start of the directory segment. + for (size_t z = 0; ((z < y) && (((currentPathPos - y) + z) < path.capacity())); z++) + { + // Blank the value. + pathSegment += path[((currentPathPos - y) + z)]; + } + + // Set result. + result = COMMON_ERROR_SUCCESS; + } + } + + // If we get here and result is still COMMON_UNKNOWN_ERROR, then the path did not have a directory seperator in it. + if (result == COMMON_ERROR_UNKNOWN_ERROR) + { + result = COMMON_ERROR_SUCCESS; + } + } + else + { + // currentPathPos is beyond the end of the path buffer. + result = COMMON_ERROR_INVALID_ARGUMENT; + COMMON_LOG_VERBOSE("FileUtills::GetPathSegment(): "); + COMMON_LOG_VERBOSE(Common::Get_Error_Message(result)); + COMMON_LOG_VERBOSE(" current path position is beyond the end of the path buffer. (Nice try.)\n"); + } + } + else + { + // Invalid currentPathPos. + result = COMMON_ERROR_INVALID_ARGUMENT; + COMMON_LOG_VERBOSE("FileUtills::GetPathSegment(): "); + COMMON_LOG_VERBOSE(Common::Get_Error_Message(result)); + COMMON_LOG_VERBOSE(" current path position is invalid.\n"); + } + } + else + { + // Invalid path. + ret = COMMON_ERROR_INVALID_ARGUMENT; + + // Log the error. + COMMON_LOG_DEBUG("FileUtills::GetPathSegment(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(ret)); + COMMON_LOG_DEBUG(" Given path is invalid.\n"); + } + + // Copy ret to Common::commonLastErrorCode. + Common::commonLastErrorCode = ret; + + // Return the result. + return ret; +} + +int FileUtills::GetLastPathSegment(const std::string & path, std::string & pathSegment, const bool & blankPathSegment) +{ + // Init fake currentPathPos. + size_t currentPathPos = path.size(); + + // Check for valid path size. (No need to check for false here. If this is false, then the real function will return COMMON_ERROR_INVALID_ARGUMENT. (It does it's own check.)) + if (currentPathPos > 0) + { + // Make sure currentPathPos is less than it's size. + currentPathPos--; + } + + // Call the GetPathSegment() function. + return (FileUtills::GetPathSegment(path, currentPathPos, pathSegment)); +} + +int FileUtills::RemoveLastPathSegment(std::string & path, size_t & currentPathPos) +{ + // Init vars. + int result = COMMON_ERROR_UNKNOWN_ERROR; // Result of this function. + + // Check for valid path. + if (path.capacity() > 0) + { + // Check for a valid path position. + if (currentPathPos > 0) + { + // Make sure the path position is within the path buffer. + if (currentPathPos < path.capacity()) + { + // Remove last path segment from output. (Search from the end of the output string.) + for (size_t y = 0; ((y < path.capacity()) && (result == COMMON_ERROR_UNKNOWN_ERROR)); y++) + { + // Look for the DIR_SEP. + if (path[(currentPathPos - y)] == DIR_SEP) + { + // Check to see if we have hit the first directory seperator. + if ((currentPathPos - y) == MINIMAL_VALID_ABSOLUTE_PATH_LENGTH) + { + // Decrement y, as we need this directory seperator. + y--; + } + + // This position is the start of the last directory segment. + for (size_t z = 0; z < (path.capacity() - (currentPathPos - y)); z++) + { + // Blank the value. + path[((currentPathPos - y) + z)] = '\0'; + } + + // Reset the path position. + currentPathPos = (currentPathPos - y); + + // Set result. + result = COMMON_ERROR_SUCCESS; + } + } + + // If we get here and result is still COMMON_UNKNOWN_ERROR, then the path did not have a directory seperator in it. + if (result == COMMON_ERROR_UNKNOWN_ERROR) + { + result = COMMON_ERROR_SUCCESS; + } + } + else + { + // currentPathPos is beyond the end of the path buffer. + result = COMMON_ERROR_INVALID_ARGUMENT; + COMMON_LOG_VERBOSE("FileUtills::RemoveLastPathSegment(): "); + COMMON_LOG_VERBOSE(Common::Get_Error_Message(result)); + COMMON_LOG_VERBOSE(" current path position is beyond the end of the path buffer. (Nice try.)\n"); + } + } + else + { + // Invalid currentPathPos. + result = COMMON_ERROR_INVALID_ARGUMENT; + COMMON_LOG_VERBOSE("FileUtills::RemoveLastPathSegment(): "); + COMMON_LOG_VERBOSE(Common::Get_Error_Message(result)); + COMMON_LOG_VERBOSE(" current path position is invalid.\n"); + } + } + else + { + // No path given. + result = COMMON_ERROR_INVALID_ARGUMENT; + COMMON_LOG_VERBOSE("FileUtills::RemoveLastPathSegment(): "); + COMMON_LOG_VERBOSE(Common::Get_Error_Message(result)); + COMMON_LOG_VERBOSE(" No path given.\n"); + } + + // Copy result to commonLastErrorCode. + Common::commonLastErrorCode = result; + + // Return the result. + return result; +} + +int FileUtills::RemoveLastPathSegment(std::string & path) +{ + // Init fake currentPathPos. + size_t currentPathPos = path.size(); + + // Check for valid path size. (No need to check for false here. If this is false, then the real function will return COMMON_ERROR_INVALID_ARGUMENT. (It does it's own check.)) + if (currentPathPos > 0) + { + // Make sure currentPathPos is less than it's size. + currentPathPos--; + } + + // Call the real RemoveLastPathSegment() function. + return (FileUtills::RemoveLastPathSegment(path, currentPathPos)); +} + +int FileUtills::ResolvePath_Helper(char * retStr, size_t * retStrSize) +{ + // Init vars. + bool eraseLoopDone = false; // Used to tell when the loop for erasing the current directory segment from the output is done. + int ret = COMMON_ERROR_UNKNOWN_ERROR; // The result code from this function. + const char * pCurrentPos = NULL; // Used to access the path string. + size_t size = 0; // Size of path string. + size_t initalOffset = 0; // Used to start parsing at the correct offset if the given path starts with a resolveable identifier. + size_t currentOutputPos = 0; /* Used to store the current position in the output string. + (Reasoning for this is that I can't determine if any of + the insertion operators consider NULL characters to not + be a valid part of the string's value. + (E.x. for the given string: "some\0\0\0" is the current + insertion point 4 or is it 7? Also does the C++ standard + define this, or is the result implimentation defined, or + is this possibly undefined behavour?)) + */ + std::string output = ""; // Result of this function. + std::string homeDir = ""; // Used if we need to get the home (User profile) directory. + std::string currentDir = ""; // Used if we need to get the current working directory. + + // Set size. + size = path.size(); + + /* Results: + * + * Does nothing but copy the path string to the output + * string if the path is already absolute. + * + * If the path is not absolute, then the path is made + * absolute before being returned. + * + * Default is to assume the path is Relative. + * + * This function does NOT filter invalid characters in + * the given path. (Valid characters are filesystem + * specific. The OS in use may not allow the user to + * access that information without special privileges. + * In addition it's not practical for us to maintain a + * list of valid characters for each filesystem type in + * existance. (Some OSes may not have an easy mechinism + * for determining what characters are valid vs. invalid + * short of attempting to actually use them.)) As such + * any given invalid character will be retained in the + * output string if this function succeeds. + * + * Notes: About linux behavior. + * /foo/bar/../fee translates to /foo/fee. (../ nulls out bar.) + * /foo/./bar translates to /foo/bar. (./ is ignored or translates to the current path without it.) + * /foo/./bar/../ translates to /foo. (./ is ignored like above, ../ nulls out bar.) + * /foo/./bar/../.././ translates to /. (the first ./ is ignored like above, the first ../ nulls out bar, the second ../ nulls out foo, and the last ./ is ignored like above.) + * /foo/./bar/../../~ results in a no such file or directory error. (Apperently ~ only has a special meaning if it is located at the beginning of the given path string. Also not all shells resolve it.) + * /foo/./bar/../../$HOME translates to $HOME. (./ is ignored like above, the first ../ nulls out bar, the second ../ nulls out foo, and $ is treated as the start of an enviorment variable. the enviorment variable's name is HOME (the space is the delimiter.)) + * ./foo translates to /foo. + * ../foo translates to /foo. + * foo translates to /foo. + */ + + // Check to see if the path needs anything done to it. + if (size > 0) + { + // Get a pointer to the path string. + pCurrentPos = path.c_str(); + + // Make sure we got the pointer. + if (pCurrentPos != NULL) + { + // First allocate enough memory in the string object for the current path string. + output.reserve(size); + + // Make sure we allocated the memory. + if (output.capacity() == size) + { + /* + * Check to see if the path is a user profile directory path. + * + * This only has a special meaning if there is a DIR_SEP as the next character, + * or if it is the only character in the given path string. + * + * If this is not the case, then the HOME_DIR_SYMBOL looses it's special meaning, + * and is assumed to be a part of the current path segment. + */ + if ((pCurrentPos[0] == HOME_DIR_SYMBOL) && ((size == 1) || ((size > 1) && (pCurrentPos[1] == DIR_SEP)))) + { + // Get the user profile directory path. + ret = FileUtills::GetUserProfileDirectoryPath(homeDir); + if (ret == COMMON_ERROR_SUCCESS) + { + // Set the user profile directory. + output = homeDir; + + // Update currentOutputPos. + currentOutputPos = homeDir.size(); + + // Set the initial offset. + initalOffset = 1; + } + else + { + // Unable to get user profile directory. + COMMON_LOG_VERBOSE("FileUtills::ResolvePath(): Unable to get needed user profile directory path, aborting.\n"); + + // Clear output. + output.clear(); + + // Force the function to exit by setting size to zero. + size = 0; + } + } + else + { + // Check for an absolute path reference. + // We need to check for a abosolute reference here. (If it is an absolute reference we do nothing.) + ret = FileUtills::IsAbsolutePathReference(pCurrentPos); + if (ret == COMMON_ERROR_SUCCESS) + { + // The default is to assume that the path is relative to the current working directory. + // Get the current working directory. + ret = FileUtills::GetCurrentWorkingDirectoryPath(currentDir); + if (ret == COMMON_ERROR_SUCCESS) + { + // Set the current working directory. + output = currentDir; + + // Update currentOutputPos. + currentOutputPos = currentDir.size(); + + /* + * Continue parsing looking for another dot as we may not be done yet. + * + * If this is not the case, then we assume that the given path is a path + * segment that starts in the given working directory. + */ + if (pCurrentPos[0] == '.') + { + // Check and see if there is something else to parse after the dot. + if (size > 1) + { + // Check for another dot. + if (pCurrentPos[1] == '.') // ".." (Parent directory of the current working directory.) + { + /* + * Check for the end of the path or that there is another directory seperator present. + * + * If this is not the case then the first two dots loose their special meaning, and we + * assume that the first two dots are part of the current path segment. + * (That or the caller made a typo....) + */ + if ((size == 2) || ((size > 2) && (pCurrentPos[2] == DIR_SEP)) || ((size == 3) && (pCurrentPos[2] == '\0'))) + { + // Erase the last directory segment from the output. + ret = FileUtills::RemoveLastPathSegment(output, currentOutputPos); + if ((ret == COMMON_ERROR_SUCCESS) && (currentOutputPos < output.capacity())) + { + // Skip the first two dots. + initalOffset = 2; + } + else + { + // FileUtills::RemoveLastPathSegment() failed. + COMMON_LOG_VERBOSE("FileUtills::ResolvePath(): Call to FileUtills::RemoveLastPathSegment() failed, unable to get needed parent directory. Aborting.\n"); + + // Clear output. + output.clear(); + + // Force the function to exit by setting size to zero. + size = 0; + } + } + } + } + else + { + /* + * The dot is by itself, assumed to be a reference to the + * current working directory. + * + * (Rather than a reference to a file in the current working + * directory whose filename is a dot.) + */ + initalOffset = 1; + } + } + else + { + // This is the start of a directory entry, so add a DIR_SEP to output and increment currentOutputPos. + output += DIR_SEP; + currentOutputPos++; + } + } + else + { + // Could not get current working directory. + COMMON_LOG_VERBOSE("FileUtills::ResolvePath(): Unable to get needed current working directory path, aborting.\n"); + + // Clear output. + output.clear(); + + // Force the function to exit by setting size to zero. + size = 0; + } + } + else + { + // Check for COMMON_ERROR_SUCCESS. + if (ret != COMMON_ERROR_SUCCESS) + { + // Call to FileUtills::IsAbsolutePathReference() failed. + ret = COMMON_ERROR_INTERNAL_ERROR; + + // Log the error. + COMMON_LOG_DEBUG("FileUtills::ResolvePath(): Could not determing if the given path was an absolute path reference, aborting.\n"); + + // Clear output. + output.clear(); + + // Make sure the processing loop does not execute. + size = 0; + } + } + } + + // Start processing loop. + for (size_t x = initalOffset; ((x < size) && (ret == COMMON_ERROR_SUCCESS)); x++) + { + // Selection switch. + switch (pCurrentPos[x]) + { + case '.': /* Dot ('.') character. Normally used for indicating + the current or parent directory. + + For the dot character to have a special meaning, + one of the following conditions must be true: + + - There must be a DIR_SEP at either the + (x + 1) or (x + 2) position (but not both) in + the given path string. (In the case of the + latter, position (x + 1) must have another + dot character for (x + 2) to have a meaning.) + + - The dot characters (either "." or "..") must + be at the end of the given path string, and + have nothing after them. (The terminating NULL + byte for c-style strings is permitted however.) + + If both of these conditions are false, then the + dot character is assumed to be part of the + current path segment, and therefore loses it's + special meaning. + */ + + // Check and see if we have at least one character left after the current position. + if ((x + 1) < size) + { + // Check for "." current working directory variant. + if (pCurrentPos[(x + 1)] == DIR_SEP) + { + // Increment x to skip checking the directory seperator on the next loop iteration. + x++; + } + else + { + // Check for ".." variant. (Parent directory.) + if (pCurrentPos[(x + 1)] == '.') + { + /* + * Determine if we can continue. + * + * /foo/bar/.. is a valid path. + * (Yes, ".." only has a special meaning if it's at the end of a path. + * Otherwise it's considered part of a filesystem entry. + * Ex. "/foo/bar/..my_filename_begins_with_two_dots" is a valid filename.) + */ + if (((x + 2) >= size) || + (((x + 2) < size) && ((pCurrentPos[(x + 2)] == DIR_SEP) || (((x + 3) >= size) && (pCurrentPos[(x + 2)] == '\0'))))) + { + // Referening the parent directory. Check to see if we are at the root directory. (No parent path reference can pass beyond the filesystem's root directory.) + if (currentOutputPos > MINIMAL_VALID_ABSOLUTE_PATH_LENGTH) + { + // Reset eraseLoopDone. + eraseLoopDone = false; + + // Remove last path segment from output. (Search from the end of the output string.) + ret = FileUtills::RemoveLastPathSegment(output, currentOutputPos); + if ((ret == COMMON_ERROR_SUCCESS) && (currentOutputPos < output.capacity())) + { + // Set eraseLoopDone. + eraseLoopDone = true; + } + else + { + // FileUtills::RemoveLastPathSegment() failed. + COMMON_LOG_VERBOSE("FileUtills::ResolvePath(): Call to FileUtills::RemoveLastPathSegment() failed. Unable to remove current path segment. Aborting.\n"); + + // Abort the parsing loop. + x = size; + } + } + + // Check to see if there are at least two characters after the current position. + if (((x + 2) < size) && (pCurrentPos[(x + 2)] == DIR_SEP)) + { + // Increment x by 2 to skip the dots and the directory seperator. + x += 2; + } + else + { + // Increment x to skip the dots. + x++; + } + } + else + { + // Copy the dot. + output.insert(currentOutputPos, 1, pCurrentPos[x]); + currentOutputPos++; + } + } + else + { + // Copy the dot. + output.insert(currentOutputPos, 1, pCurrentPos[x]); + currentOutputPos++; + } + } + } + break; + default: + // Check and see if the current character is a DIR_SEP and it is the last character in the string. + if (((x + 1) < size) || (((x + 1) == size) && (pCurrentPos[x] != DIR_SEP))) + { + // We don't do anything here, except copy the data to the output buffer. + output.insert(currentOutputPos, 1, pCurrentPos[x]); + currentOutputPos++; + } + break; + }; + } + + // Copy output to retStr. + retStr = output; + + // Set Common::commonLastErrorCode. + ret = COMMON_ERROR_SUCCESS; + + // Log result. + COMMON_LOG_VERBOSE("FileUtills::ResolvePath(): Path ( "); + COMMON_LOG_VERBOSE(path.c_str()); + COMMON_LOG_VERBOSE(" ) resolved to ( "); + COMMON_LOG_VERBOSE(output.c_str()); + COMMON_LOG_VERBOSE(").\n"); + } + else + { + // Could not allocate memory for output. + ret = COMMON_ERROR_MEMORY_ERROR; + } + } + else + { + // Could not get pointer for given path. + ret = COMMON_ERROR_INTERNAL_ERROR; + COMMON_LOG_WARNING("FileUtills::ResolvePath(): "); + COMMON_LOG_WARNING(Common::Get_Error_Message(COMMON_ERROR_INTERNAL_ERROR)); + COMMON_LOG_WARNING(" Unable to get pointer to given path argument.\n"); + } + } + else + { + // No given path. + ret = COMMON_ERROR_INVALID_ARGUMENT; + COMMON_LOG_VERBOSE("FileUtills::ResolvePath(): "); + COMMON_LOG_VERBOSE(Common::Get_Error_Message(COMMON_ERROR_INVALID_ARGUMENT)); + COMMON_LOG_VERBOSE(" No path given.\n"); + } + + // Clear output. + output.clear(); + + // Return the result. + return ret; +} + + +FileUtills::dirlist * FileUtills::getDirectory_Helper(const std::string & absPath, const bool & cleanList) +{ + // Init vars. + int errcode_SortFunct = 0; // The returned error code from DataProcess::DecrementingSort(). + FileUtills::dirlist * ret = NULL; // The constructed directory list. + + // Dumb check. + if (absPath.size() > 0) + { + // Call syscall. + ret = FileUtills::getDirectory_Syscall(absPath, cleanList); + if ((Common::commonLastErrorCode == COMMON_ERROR_SUCCESS) && (ret != NULL)) + { + // If we are cleaning the list, call DataProcess::DecrementingSort(). + if (cleanList) + { + errcode_SortFunct = DataProcess::DecrementingSort(ret->list); + if (errcode_SortFunct != 0) + { + // An exception was thrown in the DecrementingSort() function, bail out. + if (ret != NULL) + { + delete ret; + ret = NULL; + } + + // Internal error. + Common::commonLastErrorCode = COMMON_ERROR_INTERNAL_ERROR; + + // Log the error. + COMMON_LOG_VERBOSE("FileUtills::getDirectory(): The call to DataProcess::DecrementingSort() failed, Aborting.\n"); + } + } + } + else + { + // Check for SUCCESS but no list. + if ((Common::commonLastErrorCode == COMMON_ERROR_SUCCESS) && (ret == NULL)) + { + // Bug in the syscall. + Common::commonLastErrorCode = COMMON_ERROR_INTERNAL_ERROR; + COMMON_LOG_WARNING("FileUtills::getDirectory(): "); + COMMON_LOG_WARNING(Common::Get_Error_Message(Common::commonLastErrorCode)); + COMMON_LOG_WARNING(" The syscall returned an invalid directory list, but indicated success. Please report this bug.\n"); + } + else + { + // An error occured in the syscall. + if (ret != NULL) + { + delete ret; + ret = NULL; + } + + // Check for invalid argument. + if (Common::commonLastErrorCode == COMMON_ERROR_INVALID_ARGUMENT) + { + // OK the syscall is bugged. + Common::commonLastErrorCode = COMMON_ERROR_INTERNAL_ERROR; + COMMON_LOG_WARNING("FileUtills::getDirectory(): "); + COMMON_LOG_WARNING(Common::Get_Error_Message(Common::commonLastErrorCode)); + COMMON_LOG_WARNING(" Syscall returned invalid argument, please report this bug.\n"); + } + } + } + } + else + { + // Invalid path. + Common::commonLastErrorCode = COMMON_ERROR_INVALID_ARGUMENT; + COMMON_LOG_DEBUG("FileUtills::getDirectory(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(Common::commonLastErrorCode)); + COMMON_LOG_DEBUG(" Given path is invalid.\n"); + } + + // Return the result. + return ret; +} + +int FileUtills::GetGigaFreespace_Helper(const std::string & absPath, size_t & result) +{ + // Init vars. + int ret = COMMON_ERROR_UNKNOWN_ERROR; // Result of this function. + + // Issue syscall. + ret = FileUtills::GetByteFreespace_Syscall(absPath, result); + + // Check for success. + if (ret == COMMON_ERROR_SUCCESS) + { + // Byte conversion. + result = (result / ((double)1000000000)); + } + + // Copy ret to Common::commonLastErrorCode. + Common::commonLastErrorCode = ret; + + // Return the result. + return ret; +} + +int FileUtills::GetFreespace_Helper(const std::string & absPath, size_t & result) +{ + // Init vars. + int ret = COMMON_ERROR_UNKNOWN_ERROR; // Result of this function. + + // Issue syscall. + ret = FileUtills::GetByteFreespace_Syscall(absPath, result); + + // Check for success. + if (ret == COMMON_ERROR_SUCCESS) + { + // Byte conversion. + result = (result / ((double)1000000)); + } + + // Copy ret to Common::commonLastErrorCode. + Common::commonLastErrorCode = ret; + + // Return the result. + return ret; +} + +int FileUtills::GetKiloFreespace_Helper(const std::string & absPath, size_t & result) +{ + // Init vars. + int ret = COMMON_ERROR_UNKNOWN_ERROR; // Result of this function. + + // Issue syscall. + ret = FileUtills::GetByteFreespace_Syscall(absPath, result); + + // Check for success. + if (ret == COMMON_ERROR_SUCCESS) + { + // Byte conversion. + result = (result / ((double)1000)); + } + + // Copy ret to Common::commonLastErrorCode. + Common::commonLastErrorCode = ret; + + // Return the result. + return ret; +} + +int FileUtills::GetByteFreespace_Helper(const std::string & absPath, size_t & result) +{ + // Init vars. + int ret = COMMON_ERROR_UNKNOWN_ERROR; // Result of this function. + + // Issue syscall. + ret = FileUtills::GetByteFreespace_Syscall(absPath, result); + + // Copy ret to Common::commonLastErrorCode. + Common::commonLastErrorCode = ret; + + // Return the result. + return ret; +} + +int FileUtills::CreateDirectory_Helper(const std::string & absPath, const bool & createRecursive) +{ + // Init vars. + int result = COMMON_ERROR_SUCCESS; // Used to hold the result of this function. + char * pCurrentPathSegment = NULL; // Used to allocate memory for a substring that contains the current path segment. + + // Check for valid absPath. + if (absPath.size() > 0) + { + // Check and see if create recursive is false. + if (!createRecursive) + { + // Check and see if the parent directory exists. + result = FileUtills::CheckParent(absPath); + if (result == COMMON_ERROR_SUCCESS) + { + // Attempt to create the directory path. (Issue syscall.) + result = FileUtills::CreateDirectory_Syscall(absPath.c_str()); + if ((result != COMMON_ERROR_SUCCESS) || (Common::commonLastErrorCode != COMMON_ERROR_SUCCESS)) + { + // Log the error if needed. + COMMON_LOG_INFO("FileUtills::CreateDirectory(): Error returned while attempting to create directory ( "); + COMMON_LOG_INFO(absPath.c_str()); + COMMON_LOG_INFO(" ) "); + COMMON_LOG_INFO(Common::Get_Error_Message(result)); + COMMON_LOG_INFO(" Aborting.\n"); + } + else + { + COMMON_LOG_INFO("FileUtills::CreateDirectory(): Created directory ( "); + COMMON_LOG_INFO(absPath.c_str()); + COMMON_LOG_INFO(" )\n"); + } + } + else + { + // Unable to create directory. + COMMON_LOG_INFO("FileUtills::CreateDirectory(): Unable to create directory ( "); + COMMON_LOG_INFO(absPath.c_str()); + COMMON_LOG_INFO(" ) as the parent directory does not exist or is inaccessable, and recursive directory creation is disabled by the caller. Aborting.\n"); + } + } + else + { + // Run directory creation loop. + for (size_t x = (MINIMAL_VALID_ABSOLUTE_PATH_LENGTH + 1); ((x < absPath.size()) && (result == COMMON_ERROR_SUCCESS)); x++) + { + // Search for the next DIR_SEP, or the end of the given path string. + if ((absPath[x] == DIR_SEP) || ((x + 1) == absPath.size())) + { + // This is the end of the next path segment, create the needed substring and create the directory. + try { + // Allocate memory buffer. + if (absPath[x] != DIR_SEP) + { + // Allocate an extra character only if we are before a directory seperator. + pCurrentPathSegment = (char*)malloc((x + 1)); + } + else + { + // If the current char is a directory seperator, then we need to allocate only the current x value. + pCurrentPathSegment = (char*)malloc(x); + } + + // Check and make sure we got the memory allocated. + if (pCurrentPathSegment != NULL) + { + // Check and see if the current char is a DIR_SEP. (Controls how much of the source buffer we need to copy.) + if (absPath[x] != DIR_SEP) + { + // Copy the data. + for (size_t y = 0; (y < (x + 1)); y++) + { + pCurrentPathSegment[y] = absPath[y]; + } + + // Terminate the string. (Arrays start at zero, x is the last valid character in the string.) + pCurrentPathSegment[x] = '\0'; + } + else + { + // Copy the data. + for (size_t y = 0; (y < x); y++) + { + pCurrentPathSegment[y] = absPath[y]; + } + + // Terminate the string. (Arrays start at zero, (x - 1) is the last valid character in the string.) + pCurrentPathSegment[(x - 1)] = '\0'; + } + + // Now create the path. (Issue system call.) + if ((FileUtills::CreateDirectory_Syscall(pCurrentPathSegment) != COMMON_ERROR_SUCCESS) || (Common::commonLastErrorCode != COMMON_ERROR_SUCCESS)) + { + // Check and see if the error code is FILEUTILLS_ERROR_EXISTANT. (This is only an error if the final directory segment cannot be created.) + if ((Common::commonLastErrorCode != FILEUTILLS_ERROR_EXISTANT) || ((Common::commonLastErrorCode == FILEUTILLS_ERROR_EXISTANT) && ((x + 1) >= absPath.size()))) + { + // Copy the error. + result = Common::commonLastErrorCode; + + // Log the error if needed. + COMMON_LOG_INFO("FileUtills::CreateDirectory(): "); + COMMON_LOG_INFO(Common::Get_Error_Message(result)); + COMMON_LOG_INFO(" Unable to create directory ( "); + COMMON_LOG_INFO(pCurrentPathSegment); + COMMON_LOG_INFO(" ), aborting.\n"); + + // Force the loop to exit. + x = absPath.size(); + } + } + else + { + // Report success. + COMMON_LOG_INFO("FileUtills::CreateDirectory(): Created directory ( "); + COMMON_LOG_INFO(pCurrentPathSegment); + COMMON_LOG_INFO(" )\n"); + } + + // Deallocate the buffer. + if (pCurrentPathSegment != NULL) + { + free(pCurrentPathSegment); + pCurrentPathSegment = NULL; + } + } + else + { + // Could not allocate memory. + result = COMMON_ERROR_MEMORY_ERROR; + COMMON_LOG_DEBUG("FileUtills::CreateDirectory(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(result)); + COMMON_LOG_DEBUG("\n"); + + // Force loop to exit. + x = absPath.size(); + } + } + catch(exception &ex) + { + // Exception thrown. + result = COMMON_ERROR_EXCEPTION_THROWN; + COMMON_LOG_DEBUG("FileUtills::CreateDirectory(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(result)); + COMMON_LOG_DEBUG(" "); + COMMON_LOG_DEBUG(ex.what()); + COMMON_LOG_DEBUG("\n"); + + // Force loop to exit. + x = absPath.size(); + } + } + } + } + } + else + { + // Invalid path. + result = COMMON_ERROR_INVALID_ARGUMENT; + COMMON_LOG_DEBUG("FileUtills::CreateDirectory(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(result)); + COMMON_LOG_DEBUG(" Given path is invalid.\n"); + } + + // Copy result to Common::commonLastErrorCode. + Common::commonLastErrorCode = result; + + // Return the result. + return result; +} + +int FileUtills::CheckPermissions_Helper(const std::string & absPath, const bool & read, const bool & write, const bool & exec) +{ + // Init vars. + int ret = COMMON_ERROR_UNKNOWN_ERROR; // The result of this function. + + // Call syscall. + ret = FileUtills::CheckPermissions_Syscall(absPath, read, write, exec); + if (ret != COMMON_ERROR_SUCCESS) + { + // Check for INVALID_ARGUMENT. + if (ret == COMMON_ERROR_INVALID_ARGUMENT) + { + // This is an internal error. (The caller does not need to see the invalid argument error.) + ret = COMMON_ERROR_INTERNAL_ERROR; + + // Log the error. + COMMON_LOG_WARNING("FileUtills::CheckPermissions(): "); + COMMON_LOG_WARNING(Common::Get_Error_Message(ret)); + COMMON_LOG_WARNING(" Misbehaving syscall, returned invalid argument. Please report this bug.\n"); + } + } + + // Copy ret to Common::commonLastErrorCode. + Common::commonLastErrorCode = ret; + + // Return the result. + return ret; +} + +int FileUtills::CheckParent_Helper(const std::string & path, const bool & read, const bool & write, const bool & exec) +{ + // Init vars. + int result = COMMON_ERROR_UNKNOWN_ERROR; // Result of this function. + std::string absPath = path; // Absolute version of the given path. + + // Check for valid path. + if (absPath.size() > 0) + { + // Get the parent path. + result = FileUtills::RemoveLastPathSegment(absPath); + if (result == COMMON_ERROR_SUCCESS) + { + // Call the other functions + result = FileUtills::CheckPermissions_Helper(absPath, read, write, exec); + + // Log the result. + COMMON_LOG_INFO("FileUtills::CheckParent(): Path ( "); + COMMON_LOG_INFO(absPath.c_str()); + COMMON_LOG_INFO(" ) "); + + // Check the result + switch (result) + { + // Successful. + case COMMON_ERROR_SUCCESS: + COMMON_LOG_INFO("exists and is accessable with the requested permissions.\n"); + break; + // Permission error. + case COMMON_ERROR_ACCESS_DENIED: + COMMON_LOG_INFO("Status unknown. A permissions error was encountered while performing the needed checks.\n"); + break; + // Parent Does not exist. + case FILEUTILLS_ERROR_NON_EXISTANT: + COMMON_LOG_INFO("does not exist.\n"); + break; + // Unknown error. + default: + COMMON_LOG_INFO("Call to CheckPermissions() failed, unable to check parent's permissions or existance.\n"); + break; + }; + } + else + { + // Log the error. + COMMON_LOG_VERBOSE("FileUtills::CheckParent(): Unable to get absolute path of parent directory, aborting.\n"); + + // Set result to COMMON_ERROR_INTERNAL_ERROR. (Caller should not see the invalid argument error.) + result = COMMON_ERROR_INTERNAL_ERROR; + } + } + else + { + // Invalid path. + result = COMMON_ERROR_INVALID_ARGUMENT; + COMMON_LOG_DEBUG("FileUtills::CheckParent(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(result)); + COMMON_LOG_DEBUG(" Given path is invalid.\n"); + } + + // Copy result to Common::commonLastErrorCode. + Common::commonLastErrorCode = result; + + // Return the result. + return result; +} + +int FileUtills::DoesExist_Helper(const std::string & absPath) +{ + // Init vars. + int ret = COMMON_ERROR_UNKNOWN_ERROR; // The result of this function. + + // Check for invalid absPath. + if (absPath.size() > 0) + { + // Call the syscall. + ret = FileUtills::DoesExist_Syscall(absPath); + + // Get error code. + switch (ret) { + case FILEUTILLS_ERROR_EXISTANT: // Path exists. + // Log existance if needed. + COMMON_LOG_INFO("FileUtills::DoesExist(): Path ( "); + COMMON_LOG_INFO(absPath.c_str()); + COMMON_LOG_INFO(" ) exists.\n"); + break; + default: // Error occured. + // Check for non-existing path error. + if (ret == FILEUTILLS_ERROR_NON_EXISTANT) + { + // Path does not exist. + COMMON_LOG_INFO("FileUtills::DoesExist(): Path ( "); + COMMON_LOG_INFO(absPath.c_str()); + COMMON_LOG_INFO(" ) does not exist.\n"); + } + else + { + // Log the error. + COMMON_LOG_DEBUG("FileUtills::DoesExist(): An error occured while checking existance of path: "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(ret)); + COMMON_LOG_DEBUG("\n"); + } + break; + }; + } + else + { + // Invalid absPath. + ret = COMMON_ERROR_INVALID_ARGUMENT; + + // Log the error. + COMMON_LOG_DEBUG("FileUtills::DoesExist(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(ret)); + COMMON_LOG_DEBUG(" Given path is invalid.\n"); + } + + // Copy ret to Common::commonLastErrorCode. + Common::commonLastErrorCode = ret; + + // Return the result. + return ret; +} + +int FileUtills::IsFileOrDirectory_Helper(const char * absPath, const size_t absPathSize) +{ + // Init vars. + int ret = COMMON_ERROR_UNKNOWN_ERROR; // The result of this function. + + // Call syscall function. + ret = IsFileOrDirectory_Syscall(absPath, absPathSize); + + // Check return. + switch (ret) + { + // VALID ERROR CODES: + FILEUTILLS_ERROR_PATH_IS_A_FILE: + FILEUTILLS_ERROR_PATH_IS_A_DIRECTORY: + FILEUTILLS_ERROR_PATH_IS_A_SIMLINK: + COMMON_ERROR_SUCCESS: + break; + default: // Called function returned an invalid error code. + ret = COMMON_ERROR_UNKNOWN_ERROR; + COMMON_LOG_DEBUG("FileUtills_IsFileOrDirectoryHelper(): Called IsFileOrDirectory_Syscall() function returned an invalid error code, and needs to be rewritten to conform to the error code definitions."); + break; + }; + + // Return the result. + return ret; +} + +int FileUtills::DeletePath_Helper(const std::string & absPath, const bool & recursive) +{ + // Init vars. + bool unableToDeleteAll = false; // Used to tell if we could not delete something while deleting recursively. + int result = COMMON_ERROR_UNKNOWN_ERROR; // Used to store results from calls to other functions. + size_t currentEntry = 0; // Used by the recursion loop to indicate the current entry in the directory listing that it is working on. + std::string currentAbsPath = ""; // Used to contain the current absolute path. + std::string tempPath = ""; // Used to construct temporary paths. + FileUtills::dirlist * pList = NULL; // Used to store paths for recursive deletions. + + // Check path string. + if (absPath.size() > 0) + { + // Determine the type of path given. + result = FileUtills::IsFileOrDirectory_Helper(absPath); + switch (result) + { + case COMMON_ERROR_SUCCESS: + case FILEUTILLS_ERROR_PATH_IS_A_FILE: + // Attempt to delete the file. + result = FileUtills::DeletePath_Syscall(absPath); + if (result == COMMON_ERROR_SUCCESS) + { + // Log the success. + COMMON_LOG_INFO("FileUtills::DeletePath(): Deleted ( "); + COMMON_LOG_INFO(absPath.c_str()); + COMMON_LOG_INFO(" ) from the filesystem.\n"); + } + else + { + // Log the failure. + COMMON_LOG_INFO("FileUtills::DeletePath(): Unable to delete ( "); + COMMON_LOG_INFO(absPath.c_str()); + COMMON_LOG_INFO(" ) from the filesystem. The returned error was: "); + COMMON_LOG_INFO(Common::Get_Error_Message(result)); + COMMON_LOG_INFO("\n"); + } + break; + case FILEUTILLS_ERROR_PATH_IS_A_DIRECTORY: + // If we have recursive set to true we can delete the path, else return an error. + if (recursive) + { + // Copy the top level path. + currentAbsPath = absPath; + + // Blank tempPath. + tempPath.clear(); + + // Begin recursive deletion loop. + do + { + // Delete the current directory list. + if (pList != NULL) + { + delete pList; + pList = NULL; + } + + // OK we need to get the paths of every file in the directory and any other directories. + pList = FileUtills::getDirectory(currentAbsPath, true); + if ((Common::commonLastErrorCode == COMMON_ERROR_SUCCESS) && (pList != NULL)) + { + // Set currentEntry to zero. + currentEntry = 0; + + // Check to see if tempPath is defined. + if (tempPath.size() > 0) + { + // Ok, we just swapped out of a subdirectory, so we need to skip to it in the list and delete it. + for (size_t x = 0; (x < pList->list.size()); x++) + { + // Check for the subdirectory we just finished parsing. + if (((currentAbsPath + DIR_SEP) + pList->list[x]) == tempPath) + { + // Subdirectory entry found, attempt to delete it. + result = FileUtills::DeletePath_Syscall(tempPath); + if (result != COMMON_ERROR_SUCCESS) + { + // Set unableToDeleteAll. + unableToDeleteAll = true; + } + + // Set currentEntry to the next entry in the list. (The reason this works is because the Directory listing is sorted in desending order. Anything in the list prior to this position, we were unable to delete.) + currentEntry = (x + 1); + + // Clear tempPath. + tempPath.clear(); + } + } + } + + // Begin inner path loop. (Should exit early if we hit a subdirectory, or if we hit a critical error.) + for (; ((pList != NULL) && (currentEntry < (pList->list.size())) && (result != FILEUTILLS_ERROR_NON_EMPTY_DIRECTORY)); currentEntry++) + { + // Construct the path to be deleted. + tempPath = ((currentAbsPath + DIR_SEP) + pList->list[currentEntry]); + + // Attempt to delete the entry. + result = FileUtills::DeletePath_Syscall(tempPath); + if (result != COMMON_ERROR_SUCCESS) + { + // Check and see if it's a directory. + if (result == FILEUTILLS_ERROR_NON_EMPTY_DIRECTORY) + { + // Update currentAbsPath to add the new subdirectory. + currentAbsPath = ((currentAbsPath + DIR_SEP) + pList->list[currentEntry]); + } + else + { + // Skip the entry and continue. + unableToDeleteAll = true; + } + } + } + + // Blank tempPath. + tempPath.clear(); + + // Check to see if the directory list we just finished parsing is for the given path from the caller. + if ((currentAbsPath != absPath) && (result != FILEUTILLS_ERROR_NON_EMPTY_DIRECTORY)) + { + // OK, copy currentAbsPath to tempPath so that the next loop will check the parent directory for currentAbsPath's entry in the list. + tempPath = currentAbsPath; + + // Now call FileUtills::RemoveLastPathSegment() on the currentAbsPath, so we can get the parent directory's entry list on the next loop. + if (FileUtills::RemoveLastPathSegment(currentAbsPath) != COMMON_ERROR_SUCCESS) + { + // Could not remove path segment. + result = COMMON_ERROR_INTERNAL_ERROR; + COMMON_LOG_INFO("FileUtills::DeletePath(): FileUtills::RemoveLastPathSegment() returned: "); + COMMON_LOG_INFO(Common::Get_Error_Message(Common::commonLastErrorCode)); + COMMON_LOG_INFO(" Please report this bug, Aborting.\n"); + } + } + } + else + { + // Unable to get directory listing, check to see if pList is NULL and Common::commonLastErrorCode is COMMON_ERROR_SUCCESS. + if ((pList == NULL) && (Common::commonLastErrorCode == COMMON_ERROR_SUCCESS)) + { + // Internal bug in getDirectory(). (This should never happen.) + result = COMMON_ERROR_INTERNAL_ERROR; + COMMON_LOG_WARNING("FileUtills::DeletePath(): "); + COMMON_LOG_WARNING(" FileUtills::getDirectory() returned an invalid directory listing while indicating success, please report this bug.\n"); + } + else + { + // Preserve the returned error code from getDirectory(). + result = Common::commonLastErrorCode; + } + } + } + while ((currentAbsPath != absPath) && ((result == COMMON_ERROR_SUCCESS) || (result == FILEUTILLS_ERROR_NON_EMPTY_DIRECTORY))); + + // Reattempt to delete the given top level directory if unableToDeleteAll is not set. + if (!unableToDeleteAll) + { + // Attempt to delete the given top level directory. + result = FileUtills::DeletePath_Syscall(absPath); + if (result == COMMON_ERROR_SUCCESS) + { + // Success. + COMMON_LOG_INFO("FileUtills::DeletePath(): Deleted ( "); + COMMON_LOG_INFO(absPath.c_str()); + COMMON_LOG_INFO(" ) from the filesystem.\n"); + } + else + { + // Unsuccessfull. + COMMON_LOG_INFO("FileUtills::DeletePath(): Unable to completely delete ( "); + COMMON_LOG_INFO(absPath.c_str()); + COMMON_LOG_INFO(" ) from the filesystem. The the directory should be empty however. The returned error was: "); + COMMON_LOG_INFO(Common::Get_Error_Message(result)); + COMMON_LOG_INFO("\n"); + } + } + else + { + // We were unable to delete the requested path. + COMMON_LOG_INFO("FileUtills::DeletePath(): Unable to completely delete ( "); + COMMON_LOG_INFO(absPath.c_str()); + COMMON_LOG_INFO(" ) from the filesystem.\n"); + } + } + else + { + // Unable to delete a directory if recursive is set to false. + COMMON_LOG_INFO("FileUtills::DeletePath(): Unable to delete ( "); + COMMON_LOG_INFO(absPath.c_str()); + COMMON_LOG_INFO(" ) as it's a directory, and recursive deletion was disabled by the caller.\n"); + } + break; + default: + // Log the error. + COMMON_LOG_INFO("FileUtills::DeletePath(): Unable to delete ( "); + COMMON_LOG_INFO(absPath.c_str()); + COMMON_LOG_INFO(" ) from the filesystem.\n"); + break; + }; + } + else + { + // Invalid path argument. + result = COMMON_ERROR_INVALID_ARGUMENT; + + // Log the error. + COMMON_LOG_DEBUG("FileUtills::DeletePath(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(result)); + COMMON_LOG_DEBUG(" Given path is invalid.\n"); + } + + // Copy result to Common::commonLastErrorCode. + Common::commonLastErrorCode = result; + + // Return the result. + return result; +} + +int FileUtills::CopyPath_Helper(const std::string & absPathSrc, const std::string & absPathDest, const bool & recursive, + const bool & rename, const bool & abort_on_failure, + const bool & append, const streamsize & begOffset, const streamsize & endOffset) +{ + // Init vars. + int ret = COMMON_ERROR_UNKNOWN_ERROR; // The result of this function. + + // Check for valid absPathSrc. + if (absPathSrc.size() > 0) + { + // Check for valid absPathDest. + if (absPathDest.size() > 0) + { + // Ok, Check and see what the source path is. + ret = FileUtills::IsFileOrDirectory_Helper(absPathSrc); + if ((ret == FILEUTILLS_ERROR_PATH_IS_A_FILE) || (ret == COMMON_ERROR_SUCCESS)) + { + // Path is either a regular file or a special file. + COMMON_LOG_WARNING("FileUtills::CopyPath(): TODO: We can only copy a special file if the system's copy syscall is used. Impliment the copy syscall functions.\n"); + + // Check to see if the dest is a file or a directory. + ret = FileUtills::IsFileOrDirectory_Helper(absPathDest); + if (ret == FILEUTILLS_ERROR_PATH_IS_A_FILE) + { + // Overwrite pre-existing file? + } + else + { + // Check and see if dest is a directory. + if (ret == FILEUTILLS_ERROR_PATH_IS_A_DIRECTORY) + { + // Copy source file to pre-existing directory. + } + else + { + // Check for non-existant path. + if (ret == FILEUTILLS_ERROR_NON_EXISTANT) + { + // Check for the parent path's existance. + ret = FileUtills::CheckParent_Helper(absPathDest); + if (ret == COMMON_ERROR_SUCCESS) + { + // Copy the source file to the destionation path with the given filename instead of it's original filename. + + } + else + { + // Check for non-existant error. + if (ret == FILEUTILLS_ERROR_NON_EXISTANT) + { + // We cannot copy something to a non-existant destionation directory. + COMMON_LOG_DEBUG("FileUtills::CopyPath(): Cannot copy to non-existant destionation directory ( "); + COMMON_LOG_DEBUG(absPathDest.c_str()); + COMMON_LOG_DEBUG(" ). Please create the destionation directory and try to copy the source again.\n"); + } + else + { + // An error has occured. + if () + } + } + } + else + { + // An error occured. + + } + } + } + } + else + { + // Check and see if the source path is a directory. + if (ret == FILEUTILLS_ERROR_PATH_IS_A_DIRECTORY) + { + // Check to see if recursion is enabled. + if (recursive) + { + // OK, begin try block. + try { + // Begin directory recursion loop. + + + } + catch (execption &ex) + { + // Exception thrown. + ret = COMMON_ERROR_EXCEPTION_THROWN; + + // Log the error. + COMMON_LOG_DEBUG("FileUtills::CopyPath(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(ret)); + COMMON_LOG_DEBUG(" "); + COMMON_LOG_DEBUG(ex.what()); + COMMON_LOG_DEBUG("\n"); + } + } + else + { + // Cannot copy a directory if recursion is disabled. + ret = COMMON_ERROR_INVALID_ARGUMENT; + + // Log the error. + COMMON_LOG_DEBUG("FileUtills::CopyPath(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(ret)); + COMMON_LOG_DEBUG(" Unable to copy a directory because the caller has disabled recursion, aborting.\n"); + } + } + else + { + // Log the error. + COMMON_LOG_DEBUG("FileUtills::CopyPath(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(ret)); + COMMON_LOG_DEBUG(" was returned while checking the source path's filesystem type, aborting.\n"); + } + } + } + else + { + // Invalid destionation path argument. + ret = COMMON_ERROR_INVALID_ARGUMENT; + + // Log the error. + COMMON_LOG_DEBUG("FileUtills::CopyPath(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(ret)); + COMMON_LOG_DEBUG(" Given destionation path is invalid.\n"); + } + } + else + { + // Invalid source path argument. + ret = COMMON_ERROR_INVALID_ARGUMENT; + + // Log the error. + COMMON_LOG_DEBUG("FileUtills::CopyPath(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(ret)); + COMMON_LOG_DEBUG(" Given source path is invalid.\n"); + } + + // Copy ret to Common::commonLastErrorCode. + Common::commonLastErrorCode = ret; + + // Return the result. + return ret; +} diff --git a/src/Common/Src/File_Management_Subsystem/FileUtills_Private_API.h b/src/Common/Src/File_Management_Subsystem/FileUtills_Private_API.h new file mode 100644 index 0000000..37a30b3 --- /dev/null +++ b/src/Common/Src/File_Management_Subsystem/FileUtills_Private_API.h @@ -0,0 +1,884 @@ +/*! + Multiverse Engine Project 04/12/2011 FileUtills FileUtills_Private_API.h + + Copyright (C) 2014 Multiverse Engine Project + + This program is free software; + you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this program; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Official source repository and project information can be found at + https://github.com/codebase7/mengine +*/ + +// Include guard. +#ifndef FILEUTILLS_PRIVATE_API_H +#define FILEUTILLS_PRIVATE_API_H + +// External includes. +#include + +// Namespace definition. +namespace FileUtills{ + +/*! + * int FileUtills::IsAbsolutePathReference(const char * path, const size_t pathSize) + * + * This function checks the given path to see if it's beginning is in + * absolute path reference form. + * + * Absolute path reference form is defined as: + * - On DOS / Windows systems: Having the drive letter the colon + * and directory seperator as the first three (3) characters in + * the given path. E.x. "C:\Windows" or "D:\Setup.exe" + * + * - On all other systems: Having the directory seperator as the + * first character in the given path. E.x. "/usr" or "/home" + * or "/foo" or "/bar" + * + * If the given path is in absolute path reference form as defined above, + * then the function will return FILEUTILLS_ERROR_PATH_IS_ABSOLUTE. + * + * If the given path is NOT in absolute path reference form as defined + * above, then this function will return FILEUTILLS_ERROR_PATH_IS_RELATIVE. + * + * If any error occurs then, this function will return the appropriate error code. + */ +int IsAbsolutePathReference(const char * path, const size_t pathSize); + +/*! + * int FileUtills::IsAbsolutePathReference(const char * path, const size_t pathSize, char ** absRef, size_t * absRefSize) + * + * This function checks the given path to see if it's beginning is in + * absolute path reference form. This version also copies the found + * absolute path reference to the given absRef argument if applicable. + * + * Note: This function expects absRefSize to point to a valid size_t + * variable when it is called. (This function will NOT allocate it.) + * absRef will be allocated by this function, but will NOT deallocate + * any pre-existing pointer. (As such you should deallocate it yourself + * or copy the pointer somewhere else if you need to save it for later use.) + * + * Absolute path reference form is defined as: + * - On DOS / Windows systems: Having the drive letter the colon + * and directory seperator as the first three (3) characters in + * the given path. E.x. "C:\Windows" or "D:\Setup.exe" + * + * - On all other systems: Having the directory seperator as the + * first character in the given path. E.x. "/usr" or "/home" + * or "/foo" or "/bar" + * + * If the given path is in absolute path reference form as defined above, + * then the function will return FILEUTILLS_ERROR_PATH_IS_ABSOLUTE, + * absRef will be set to the absolute path reference (Only the part that is + * checked is stored in absRef as per above. + * E.x. On DOS / Windows systems: ":\" on all + * other systems this will be set to "/".) + * absRefSize will be set to the length of the absRef string. + * + * If the given path is NOT in absolute path reference form as defined + * above, then this function will return FILEUTILLS_ERROR_PATH_IS_RELATIVE, + * the absRef string and absRefSize variables will NOT BE ALTERED. + * + * If any error occurs then, this function will return the appropriate error code, + * the absRef string and absRefSize variables will NOT BE ALTERED. + */ +bool IsAbsolutePathReference(const char * path, std::string & absRef); + +/*! + * int FileUtills::GetPathSegment(const std::string & path, const size_t & currentPathPos, std::string & pathSegment, const bool & blankPathSegment) + * + * This function looks for the last path segment from the given path + * and copies it to the given pathSegment string argument. + * + * WARNING: If the given blankPathSegment boolean is true (default), + * pathSegment is cleared (by calling std::string.clear().) even if the + * function fails with an error. (So make sure pathSegment does not have + * something in it you need to keep when you call this function.) + * + * (This function is mostly a slightly altered version of FileUtills::RemoveLastPathSegment() + * that copies the last path segment rather than remove it from the given path string.) + * + * The path segment to copy is determined by the given currentPathPos + * variable. currentPathPos is checked to make sure it is within the capacity + * of the given string and if it is, iterates backwards in the string until a + * directory seperator (defined by DIR_SEP) is found. If the currentPathPos + * check fails, then this function will return the COMMON_ERROR_INVALID_ARGUMENT + * error code. + * + * The path segment is then copied from the directory seperator (but NOT including the directory + * seperator) to pathSegment until it reaches the given currentPathPos offset in the path string. + * (Or the end of the path string is reached which ever comes first.) + * + * If a path segment to copy cannot be found, then pathSegment will be cleared (if blankPathSegment is true (default)) + * or pathSegment will have it's original contents (if blankPathSegment is false), and + * the function will return the COMMON_ERROR_SUCCESS error code. + * + * If a path segment to copy is found, then pathSegment will have a copy of the + * path segment appended to it (if blankPathSegment is true (default) then only the copied path segment will + * be in pathSegment, otherwise pathSegment will have it's original contents appended with the copied path + * segment.), and the function will return the COMMON_ERROR_SUCCESS error code. + * + * In any case, the returned error code will also be written to Common::commonLastErrorCode. + */ +int GetPathSegment(const std::string & path, const size_t & currentPathPos, std::string & pathSegment, const bool & blankPathSegment = true); + +/*! + * int FileUtills::GetLastPathSegment(const std::string & path, std::string & pathSegment, const bool & blankPathSegment) + * + * This function acts as a wrapper to FileUtills::GetPathSegment(const std::string &, const size_t &, std::string &) + * with the assumption that the path segment you want to copy is at the end of the + * string. (end of the given string is determined by the string's size.) + * + * By default the given path segment argument will be cleared. To not clear the argument, set blankPathSegment to false. + */ +int GetLastPathSegment(const std::string & path, std::string & pathSegment, const bool & blankPathSegment = true); + +/*! + * int FileUtills::RemoveLastPathSegment(std::string & path, size_t & currentPathPos) + * + * This function removes a path segment from the given path, and updates the + * given currentPathPos variable to point to the location in the string + * where the removed path segment began. + * + * Long description: + * The given path argument is checked to see if is is big enough to have more + * than just the filesystem root directory reference. If this is not the case + * then this function will return the COMMON_ERROR_INVALID_ARGUMENT error + * code, and the given path and position arguments will NOT be modified. + * + * The given path argument is copied to a temporary variable. + * + * The path segment to remove is determined by the given currentPathPos + * variable. currentPathPos is checked to make sure it is within the capacity + * of the given string and if it is, iterates backwards in the string until a + * directory seperator (defined by DIR_SEP) is found. If the currentPathPos + * check fails, then this function will return the COMMON_ERROR_INVALID_ARGUMENT + * error code, and the given path and position arguments will NOT be modified. + * + * Once the path segment to remove is identfied, a check is performed to make sure + * the function is not removing the filesystem root directory reference. + * + * If the path segment to be removed is within the filesystem root directory, then the + * path segment is removed by replacing all of the bytes from the start of the path + * segment to be removed (while preserving the DIR_SEP as required for the filesystem + * root directory reference) to the end of the string with NULL character bytes. + * + * If removal of the path segment will not result in the removal of the filesystem root + * directory reference, then the path segment is removed by replacing all of the bytes + * from the start of the path segment to be removed (including the DIR_SEP) to the end + * of the string with NULL character bytes. + * + * If the path segment is removed, then currentPathPos will be updated to indicate where + * the next path segment's entry name (file or directory name) would start in the altered + * string. + * + * If a path segment to remove cannot be found, then the given path and position arguments will + * NOT be altered, and the function will return the COMMON_ERROR_SUCCESS error code. + * + * In any case, the returned error code will also be written to Common::commonLastErrorCode. + * + * Short description: + * This function will return the COMMON_ERROR_SUCCESS error code if it is successfull, + * the results will be stored in the given arguments. + * + * If an error occurs, the error will be returned, and the given arguments will NOT + * be altered. + * + * In any case, the returned error code will also be written to Common::commonLastErrorCode. + */ +int RemoveLastPathSegment(std::string & path, size_t & currentPathPos); + +/*! + * int FileUtills::RemoveLastPathSegment(std::string & path) + * + * This function acts as a wrapper to FileUtills::RemoveLastPathSegment(std::string &, size_t &) + * with the assumption that the path segment you want to remove is at the end of the + * string. (end of the given string is determined by the string's size.) + */ +int RemoveLastPathSegment(std::string & path); + +/*! + * size_t FileUtills::Get_Max_Symlink_Depth() + * + * Returns the maximum supported symbolic link depth. + */ +size_t Get_Max_Symlink_Depth() +{ + return 0; +} + +/*! + * int FileUtills::ResolvePath_Helper(char * retStr, size_t * retStrSize) + * + * WARNING: NEVER CALL THIS FUNCTION DIRECTLY OUTSIDE OF THE + * FILEUTILLS NAMESPACE. THIS FUNCTION EXPECTS ANY AND ALL OTHER + * SAFETY CHECKS HAVE PASSED BEFORE IT IS CALLED. + * + * Helper function that resolves the given path and returns the result. + * + * WARNING: This function does NOT resolve any symbolic link(s) if a + * symbolic link is encountered. If you need to resolve symbolic links, + * use the public API version of this function: FileUtills::ResolvePath(). + * + * The path resolution method is described below: + * + * First the path is checked for a user profile directory reference. + * If one is found, then the profile directory path for the currently + * effective user is prepended to the result and parsing continues as + * if the remaining path segment(s) are relative to that profile + * directory path. (The check below for a relative or absolute path + * reference is skipped.) + * + * The given path is checked to determine whether it is an absolute path + * reference or a relative (to the current working directory) path reference + * by running it through FileUtills::IsAbsolutePathReference(). + * + * If the path is considered a relative reference, the current working + * directory is fetched from the host system and prepended to the result. + * Parsing then continues on the remaining path segments. + * + * If the path is considered an absolute path reference, then the absolute + * path reference is copied to the result, and parsing continues. + * + * The parsing loop starts which checks each given path segment to see if it + * contains references to the current path segment or the parent of the current + * path segment. + * + * If a reference to the current path segment is found, then the found reference + * is ignored, and parsing continues with the next path segment. + * + * If a reference to the parent of the current path segment is found, then + * the result is checked to see if removing the last path segment in the + * result would cause going past the boundry of a root directory. + * This check is defined below: + * If the target system uses the DOS / Windows style path scheme, + * then the check will indicate passing a root directory boundry + * if the removal of the path segment would remove the drive letter + * reference. (I.e. It would remove the + * ":" portion. + * (For Example: "C:\", "D:\", "Z:\", etc.)) + * + * Otherwise the check will indicate passing a root directory + * boundry if the removal of the path segment would remove the + * initial directory seperator. (I.e. The first directory + * seperator. A.K.A '/'.) + * + * If the check described above indicates that removal of the last path + * segment in the result would pass the root directory boundry this function + * will abort and return an error. + * + * If the check described above indicates that removal of the last path + * segment would NOT result in passing the root directory boundry, then + * the last segment will be removed from the result and parsing will + * continue. + * + * Once the last path segment in the given path is reached, the result + * will replace the contents of the retStr argument and COMMON_ERROR_SUCCESS + * will be returned. + * + * If at any time an exception is thrown, the retStr argument will NOT be altered, + * and COMMON_ERROR_EXCEPTION_THROWN will be returned to the caller. + * (Depending on the set Common namespace logging level, a human readable + * error message will be logged to describe the exception encountered more + * throughly.) + * + * If an error is encountered at any point, the retStr argument will NOT be altered, + * and the appropriate error will be returned to the caller. + * (Depending on the set Common namespace logging level, a human readable + * error message will be logged to describe the error encountered more + * throughly.) + */ +int ResolvePath_Helper(char * retStr, size_t * retStrSize); + +/*! + * int FileUtills::ResolveSystemSymoblicLink_Syscall(const char * path, const size_t pathSize, char ** resolvedPath, size_t * resolvedPathSize) + * + * WARNING: NEVER CALL THIS FUNCTION DIRECTLY OUTSIDE OF THE + * FILEUTILLS NAMESPACE. THIS FUNCTION EXPECTS ANY AND ALL OTHER + * SAFETY CHECKS HAVE PASSED BEFORE IT IS CALLED. + * + * Helper function that calls the host's syscall(s) to resolve a given symbolic link. + * (Note: This only works if the given symbolic link is in the format that the host system + * expects / supports.) + * + * WARNING: This function verifies that the given path is a symbolic link using the host system's syscalls + * for doing so. Depending on your views / requirements of secure programming, this function may not be + * considered safe to call from certain contexts. + * + * All public FileUtills functions will wind up calling this function (directly or indirectly), as a side + * effect of FileUtills::ResolvePath() encountering a symbolic link during path resolution. (Unless the + * called public FileUtills function had it's disableSymLinkResolution boolean argument set to true + * explisitly.) + * + * Returns COMMON_ERROR_SUCCESS if successful. (resolvedPath with have it's contents reset and the resolved + * path stored in it.) + * + * Returns COMMON_ERROR_INVALID_ARGUMENT if the given path argument is empty, or if the given path string is + * not a symbolic link as defined by the host system. + * + * Returns all other errors where appropriate. + * + * This function is required to translate any error that + * may be returned by the syscall into a Common namespace + * error code. + * + * The result of this function is returned to the caller, (The requested path will be stored in + * given path argument.) + * + * This function is permitted to perform any nessacarry allocations or + * modifications needed by the host's syscall to perform the task, however + * these modifications and or allocations must be undone prior to the + * function's return. In addition this function must catch any thrown + * exception created by itself or the host's syscall. (In that instance + * COMMON_ERROR_EXCEPTION_THROWN must be returned, regardless of result.) + */ +int ResolveSystemSymoblicLink_Syscall(const char * path, const size_t pathSize, char ** resolvedPath, size_t * resolvedPathSize); + +/*! + * int FileUtills::GetUserProfileDirectoryPath_Syscall(std::string & path) + * + * WARNING: NEVER CALL THIS FUNCTION DIRECTLY OUTSIDE OF THE + * FILEUTILLS NAMESPACE. THIS FUNCTION EXPECTS ANY AND ALL OTHER + * SAFETY CHECKS HAVE PASSED BEFORE IT IS CALLED. + * + * Helper function that calls the host's syscall for + * getting the user profile directory's location on + * the filesystem for the current user. + * + * This function is required to translate any error that + * may be returned by the syscall into a Common namespace + * error code. + * + * The result of this function is stored in Common::commonLastErrorCode, + * in addition to being returned. (The requested path will be stored in + * given path argument.) + * + * This function is permitted to perform any nessacarry allocations or + * modifications needed by the host's syscall to perform the task, however + * these modifications and or allocations must be undone prior to the + * function's return. In addition this function must catch any thrown + * exception created by itself or the host's syscall. (In that instance + * COMMON_ERROR_EXCEPTION_THROWN must be returned, regardless of result.) + */ +int GetUserProfileDirectoryPath_Syscall(std::string & path); + +/*! + * int FileUtills::GetCurrentWorkingDirectoryPath_Syscall(std::string & path) + * + * WARNING: NEVER CALL THIS FUNCTION DIRECTLY OUTSIDE OF THE + * FILEUTILLS NAMESPACE. THIS FUNCTION EXPECTS ANY AND ALL OTHER + * SAFETY CHECKS HAVE PASSED BEFORE IT IS CALLED. + * + * Helper function that calls the host's syscall for + * getting the current working directory's location on + * the filesystem. + * + * This function is required to translate any error that + * may be returned by the syscall into a Common namespace + * error code. + * + * The result of this function is stored in Common::commonLastErrorCode, + * in addition to being returned. (The requested path will be stored in + * given path argument.) + * + * This function is permitted to perform any nessacarry allocations or + * modifications needed by the host's syscall to perform the task, however + * these modifications and or allocations must be undone prior to the + * function's return. In addition this function must catch any thrown + * exception created by itself or the host's syscall. (In that instance + * COMMON_ERROR_EXCEPTION_THROWN must be returned, regardless of result.) + */ +int GetCurrentWorkingDirectoryPath_Syscall(std::string & path); + +/*! + * int FileUtills::GetExecDirectory_Syscall(std::string & retStr) + * + * WARNING: NEVER CALL THIS FUNCTION DIRECTLY OUTSIDE OF THE + * FILEUTILLS NAMESPACE. THIS FUNCTION EXPECTS ANY AND ALL OTHER + * SAFETY CHECKS HAVE PASSED BEFORE IT IS CALLED. + * + * Helper function that calls the host's syscall for + * getting the main executable's location on the filesystem. + * + * This function is required to translate any error that + * may be returned by the syscall into a Common namespace + * error code. + * + * The result of this function is returned to the caller, + * and the std::string argument retStr is altered with the result. + * (In case of error the std::string argument is NOT altered.) + * + * This function is permitted to perform any nessacarry allocations or + * modifications needed by the host's syscall to perform the task, however + * these modifications and or allocations must be undone prior to the + * function's return. In addition this function must catch any thrown + * exception created by itself or the host's syscall. (In that instance + * COMMON_ERROR_EXCEPTION_THROWN must be returned, regardless of result.) + */ +int GetExecDirectory_Syscall(std::string & retStr); + +/*! + * FileUtills::dirlist * FileUtills::getDirectory_Helper(const std::string & absPath, const bool & cleanList) + * + * Helper function that calls FileUtills::getDirectory_Syscall() for + * generating a list of the given path's directory contents. If cleanList + * is set to true, then the list will have the references to the + * given path's current directory and parent directory removed from the + * generated list, as well as having the list sorted by + * DataProcess::DecrementingSort(). + * + * This is used internally by other FileUtills functions to + * prevent calling FileUtills::ResolvePath() multiple times. + * + * WARNING: This function expects that the given path has + * already been resolved by FileUtills::ResolvePath(). + * If the path needs to be resolved (if you are unsure then + * it does) use the public API version of this function, + * which will resolve the path. + */ +FileUtills::dirlist * getDirectory_Helper(const std::string & absPath, const bool & cleanList); + +/*! + * FileUtills::dirlist * FileUtills::getDirectory_Syscall(const std::string & absPath, const bool & cleanList) + * + * WARNING: NEVER CALL THIS FUNCTION DIRECTLY OUTSIDE OF THE + * FILEUTILLS NAMESPACE. THIS FUNCTION EXPECTS ANY AND ALL OTHER + * SAFETY CHECKS HAVE PASSED BEFORE IT IS CALLED. + * + * Helper function that calls the host's syscall for + * getting a listing of the given path's directory contents + * from the filesystem. If cleanList is set to true, then the + * list will have the references to the given path's current + * directory and parent directory removed from the generated + * list. (The sorting is done by the Helper function.) + * + * This function is required to translate any error that + * may be returned by the syscall into a Common namespace + * error code. + * + * The result of this function is stored in Common::commonLastErrorCode, + * and a pointer to a FileUtills::dirlist is returned. (In case of error + * the returned pointer will be NULL.) + * + * This function is permitted to perform any nessacarry allocations or + * modifications needed by the host's syscall to perform the task, however + * these modifications and or allocations must be undone prior to the + * function's return. In addition this function must catch any thrown + * exception created by itself or the host's syscall. (In that instance + * COMMON_ERROR_EXCEPTION_THROWN must be returned, regardless of result.) + */ +FileUtills::dirlist * getDirectory_Syscall(const std::string & absPath, const bool & cleanList); + +/*! + * int FileUtills::GetGigaFreespace_Helper(const std::string & absPath, size_t & result) + * + * Helper function that calls FileUtills::GetByteFreespace_Syscall() for + * getting the number of remaining free bytes on the given filesystem, + * then performs the conversion of the remaining bytes to the SI unit + * gigabyte (GB) representation. + * + * This is used internally by other FileUtills functions to + * prevent calling FileUtills::ResolvePath() multiple times. + * + * WARNING: This function expects that the given path has + * already been resolved by FileUtills::ResolvePath(). + * If the path needs to be resolved (if you are unsure then + * it does) use the public API version of this function, + * which will resolve the path. + */ +int GetGigaFreespace_Helper(const std::string & absPath, size_t & result); + +/*! + * int FileUtills::GetFreespace_Helper(const std::string & absPath, size_t & result) + * + * Helper function that calls FileUtills::GetByteFreespace_Syscall() for + * getting the number of remaining free bytes on the given filesystem, + * then performs the conversion of the remaining bytes to the SI unit + * megabyte (MB) representation. + * + * This is used internally by other FileUtills functions to + * prevent calling FileUtills::ResolvePath() multiple times. + * + * WARNING: This function expects that the given path has + * already been resolved by FileUtills::ResolvePath(). + * If the path needs to be resolved (if you are unsure then + * it does) use the public API version of this function, + * which will resolve the path. + */ +int GetFreespace_Helper(const std::string & absPath, size_t & result); + +/*! + * int FileUtills::GetKiloFreespace_Helper(const std::string & absPath, size_t & result) + * + * Helper function that calls FileUtills::GetByteFreespace_Syscall() for + * getting the number of remaining free bytes on the given filesystem, + * then performs the conversion of the remaining bytes to the SI unit + * kilobyte (kB) representation. + * + * This is used internally by other FileUtills functions to + * prevent calling FileUtills::ResolvePath() multiple times. + * + * WARNING: This function expects that the given path has + * already been resolved by FileUtills::ResolvePath(). + * If the path needs to be resolved (if you are unsure then + * it does) use the public API version of this function, + * which will resolve the path. + */ +int GetKiloFreespace_Helper(const std::string & absPath, size_t & result); + +/*! + * int FileUtills::GetByteFreespace_Helper(const std::string & absPath, size_t & result) + * + * Helper function that calls FileUtills::GetByteFreespace_Syscall() for + * getting the number of remaining free bytes on the given filesystem. + * + * This is used internally by other FileUtills functions to + * prevent calling FileUtills::ResolvePath() multiple times. + * + * WARNING: This function expects that the given path has + * already been resolved by FileUtills::ResolvePath(). + * If the path needs to be resolved (if you are unsure then + * it does) use the public API version of this function, + * which will resolve the path. + */ +int GetByteFreespace_Helper(const std::string & absPath, size_t & result); + +/*! + * int FileUtills::GetByteFreespace_Syscall(const std::string & absPath, size_t & result) + * + * WARNING: NEVER CALL THIS FUNCTION DIRECTLY OUTSIDE OF THE + * FILEUTILLS NAMESPACE. THIS FUNCTION EXPECTS ANY AND ALL OTHER + * SAFETY CHECKS HAVE PASSED BEFORE IT IS CALLED. + * + * Helper function that calls the host's syscall for + * getting the number of remaining free bytes on the given filesystem. + * + * This function is required to translate any error that + * may be returned by the syscall into a Common namespace + * error code. + * + * The result of this function is stored in Common::commonLastErrorCode + * in addition to being returned. + * + * This function is permitted to perform any nessacarry allocations or + * modifications needed by the host's syscall to perform the task, however + * these modifications and or allocations must be undone prior to the + * function's return. In addition this function must catch any thrown + * exception created by itself or the host's syscall. (In that instance + * COMMON_ERROR_EXCEPTION_THROWN must be returned, regardless of result.) + */ +int GetByteFreespace_Syscall(const std::string & absPath, size_t & result); + +/*! + * int FileUtills::CreateDirectory_Helper(const std::string & absPath, const bool & createRecursive) + * + * Helper function that calls FileUtills::CreateDirectory_Syscall() for + * creating a directory on the filesystem. + * + * This is used internally by other FileUtills functions to + * prevent calling FileUtills::ResolvePath() multiple times. + * + * WARNING: This function expects that the given path has + * already been resolved by FileUtills::ResolvePath(). + * If the path needs to be resolved (if you are unsure then + * it does) use the public API version of this function, + * which will resolve the path. + */ +int CreateDirectory_Helper(const std::string & absPath, const bool & createRecursive); + +/*! + * int FileUtills::CreateDirectory_Syscall(const char * absPath) + * + * WARNING: NEVER CALL THIS FUNCTION DIRECTLY OUTSIDE OF THE + * FILEUTILLS NAMESPACE. THIS FUNCTION EXPECTS ANY AND ALL OTHER + * SAFETY CHECKS HAVE PASSED BEFORE IT IS CALLED. + * + * Helper function that calls the host's syscall for + * creating a directory on the filesystem. + * + * This function is required to translate any error that + * may be returned by the syscall into a Common namespace + * error code. + * + * The result of this function is stored in Common::commonLastErrorCode + * in addition to being returned. + * + * This function is permitted to perform any nessacarry allocations or + * modifications needed by the host's syscall to perform the task, however + * these modifications and or allocations must be undone prior to the + * function's return. In addition this function must catch any thrown + * exception created by itself or the host's syscall. (In that instance + * COMMON_ERROR_EXCEPTION_THROWN must be returned, regardless of result.) + */ +int CreateDirectory_Syscall(const char * absPath); + +/*! + * int FileUtills::CheckPermissions_Helper(const std::string & absPath, const bool & read, const bool & write, const bool & exec) + * + * Helper function that calls FileUtills::CheckPermissions_Syscall() for + * checking the permissions of a given file or directory on the filesystem. + * + * This is used internally by other FileUtills functions to + * prevent calling FileUtills::ResolvePath() multiple times. + * + * WARNING: This function expects that the given path has + * already been resolved by FileUtills::ResolvePath(). + * If the path needs to be resolved (if you are unsure then + * it does) use the public API version of this function, + * which will resolve the path. + * + * WARNING: This function expects that the path given to it + * is a filesystem entry within the directory to check. (I.e. + * The given path is a file or directory whose parent directory + * needs to be checked.) As such it will remove the last path + * component from the given path before performing the checks. + */ +int CheckPermissions_Helper(const std::string & absPath, const bool & read, const bool & write, const bool & exec); + +/*! + * int FileUtills::CheckPermissions_Syscall(const std::string & absPath, const bool & read, const bool & write, const bool & exec) + * + * WARNING: NEVER CALL THIS FUNCTION DIRECTLY OUTSIDE OF THE + * FILEUTILLS NAMESPACE. THIS FUNCTION EXPECTS ANY AND ALL OTHER + * SAFETY CHECKS HAVE PASSED BEFORE IT IS CALLED. + * + * Helper function that calls the host's syscall for + * checking the permissions of a given file or directory on the filesystem. + * + * This function is required to translate any error that + * may be returned by the syscall into a Common namespace + * error code. + * + * The result of this function is stored in Common::commonLastErrorCode + * in addition to being returned. + * + * This function is permitted to perform any nessacarry allocations or + * modifications needed by the host's syscall to perform the task, however + * these modifications and or allocations must be undone prior to the + * function's return. In addition this function must catch any thrown + * exception created by itself or the host's syscall. (In that instance + * COMMON_ERROR_EXCEPTION_THROWN must be returned, regardless of result.) + */ +int CheckPermissions_Syscall(const std::string & absPath, const bool & read, const bool & write, const bool & exec); + +/*! + * int FileUtills::CheckParent_Helper(const std::string & path, const bool & read, const bool & write, const bool & exec) + * + * Helper function that calls FileUtills::CheckPermissions_Helper() for + * determining whether or not a given path's parent directory + * exists and is accessable with the given permissions. + * + * This is used internally by other FileUtills functions to + * prevent calling FileUtills::ResolvePath() multiple times. + * + * WARNING: This function expects that the given path has + * already been resolved by FileUtills::ResolvePath(). + * If the path needs to be resolved (if you are unsure then + * it does) use the public API version of this function, + * which will resolve the path. + * + * WARNING: This function expects that the path given to it + * is a filesystem entry within the directory to check. (I.e. + * The given path is a file or directory whose parent directory + * needs to be checked.) As such it will remove the last path + * component from the given path before performing the checks. + */ +int CheckParent_Helper(const std::string & path, const bool & read, const bool & write, const bool & exec); + +/*! + * int FileUtills::DoesExist_Helper(const std::string & absPath) + * + * Helper function that calls FileUtills::DoesExist_Syscall() for + * determining whether or not a given path exists on the given filesystem. + * + * This is used internally by other FileUtills functions to + * prevent calling FileUtills::ResolvePath() multiple times. + * + * WARNING: This function expects that the given path has + * already been resolved by FileUtills::ResolvePath(). + * If the path needs to be resolved (if you are unsure then + * it does) use the public API version of this function, + * which will resolve the path. + */ +int DoesExist_Helper(const std::string & absPath); + +/*! + * int FileUtills::DoesExist_Syscall(const std::string & absPath) + * + * WARNING: NEVER CALL THIS FUNCTION DIRECTLY OUTSIDE OF THE + * FILEUTILLS NAMESPACE. THIS FUNCTION EXPECTS ANY AND ALL OTHER + * SAFETY CHECKS HAVE PASSED BEFORE IT IS CALLED. + * + * Helper function that calls the host's syscall for + * determining whether or not a given path exists on the given filesystem. + * + * This function is required to translate any error that + * may be returned by the syscall into a Common namespace + * error code. + * + * The result of this function is stored in Common::commonLastErrorCode + * in addition to being returned. + * + * This function is permitted to perform any nessacarry allocations or + * modifications needed by the host's syscall to perform the task, however + * these modifications and or allocations must be undone prior to the + * function's return. In addition this function must catch any thrown + * exception created by itself or the host's syscall. (In that instance + * COMMON_ERROR_EXCEPTION_THROWN must be returned, regardless of result.) + */ +int DoesExist_Syscall(const std::string & absPath); + +/*! + * int FileUtills::IsFileOrDirectory_Helper(const char * absPath, const size_t absPathSize) + * + * Helper function that calls FileUtills::IsFileOrDirectory_Syscall() for + * determining whether or not a given path is a file or + * directory on a filesystem. + * + * This is used internally by other FileUtills functions to + * prevent calling FileUtills::ResolvePath() multiple times. + * + * WARNING: This function expects that the given path has + * already been resolved by FileUtills::ResolvePath(). + * If the path needs to be resolved (if you are unsure then + * it does) use the public API version of this function, + * which will resolve the path. + * + * Returns FILEUTILLS_ERROR_PATH_IS_A_FILE if the given absPath is a file + * in the filesystem. + * + * Returns FILEUTILLS_PATH_IS_A_DIRECTORY if the given absPath is a + * directory on the file system. + * + * Returns FILEUTILLS_ERROR_PATH_IS_A_SYMLINK if the given absPath is a + * symbolic link in the file system. + * + * Returns COMMON_ERROR_SUCCESS if the given absPath is a valid (but unrecognised) + * entry in the filesystem. + * + * Otherwise the appropriate error is returned to the caller. + */ +int IsFileOrDirectory_Helper(const char * absPath, const size_t absPathSize); + +/*! + * int FileUtills::IsFileOrDirectory_Syscall(const std::string & absPath) + * + * WARNING: NEVER CALL THIS FUNCTION DIRECTLY OUTSIDE OF THE + * FILEUTILLS NAMESPACE. THIS FUNCTION EXPECTS ANY AND ALL OTHER + * SAFETY CHECKS HAVE PASSED BEFORE IT IS CALLED. + * + * Helper function that calls the host's syscall for + * determining whether or not a given path is a file or + * directory on a filesystem. + * + * This function is required to translate any error that + * may be returned by the syscall into a Common namespace + * error code. + * + * The result of this function is stored in Common::commonLastErrorCode + * in addition to being returned. + * + * This function is permitted to perform any nessacarry allocations or + * modifications needed by the host's syscall to perform the task, however + * these modifications and or allocations must be undone prior to the + * function's return. In addition this function must catch any thrown + * exception created by itself or the host's syscall. (In that instance + * COMMON_ERROR_EXCEPTION_THROWN must be returned, regardless of result.) + */ +int IsFileOrDirectory_Syscall(const std::string & absPath); + +/*! + * int FileUtills::DeletePath_Helper(const std::string & absPath, const bool & recursive) + * + * Helper function that calls FileUtills::DeletePath_Syscall() for + * removing (unlinking / deleting) a given file or directory on a + * filesystem. + * + * This is used internally by other FileUtills functions to + * prevent calling FileUtills::ResolvePath() multiple times. + * + * WARNING: This function expects that the given path has + * already been resolved by FileUtills::ResolvePath(). + * If the path needs to be resolved (if you are unsure then + * it does) use the public API version of this function, + * which will resolve the path. + */ +int DeletePath_Helper(const std::string & absPath, const bool & recursive); + +/*! + * int FileUtills::DeletePath_Syscall(const std::string & absPath) + * + * WARNING: NEVER CALL THIS FUNCTION DIRECTLY OUTSIDE OF THE + * FILEUTILLS NAMESPACE. THIS FUNCTION EXPECTS ANY AND ALL OTHER + * SAFETY CHECKS HAVE PASSED BEFORE IT IS CALLED. + * + * Helper function that calls the host's syscall for + * removing (unlinking / deleting) a given file or + * directory on a filesystem. + * + * This function is required to translate any error that + * may be returned by the syscall into a Common namespace + * error code. + * + * The result of this function is stored in Common::commonLastErrorCode + * in addition to being returned. + * + * This function is permitted to perform any nessacarry allocations or + * modifications needed by the host's syscall to perform the task, however + * these modifications and or allocations must be undone prior to the + * function's return. In addition this function must catch any thrown + * exception created by itself or the host's syscall. (In that instance + * COMMON_ERROR_EXCEPTION_THROWN must be returned, regardless of result.) + */ +int DeletePath_Syscall(const std::string & absPath); + +/*! + * int FileUtills::RenamePath_Syscall(const std::string & absPathSrc, const std::string & absPathDest, const bool & dereferenceSymLinks) + * + * WARNING: NEVER CALL THIS FUNCTION DIRECTLY OUTSIDE OF THE + * FILEUTILLS NAMESPACE. THIS FUNCTION EXPECTS ANY AND ALL OTHER + * SAFETY CHECKS HAVE PASSED BEFORE IT IS CALLED. + * + * Helper function that calls the host's syscall for + * renaming a given file or directory on the same filesystem. + * + * This function is NOT permitted to issue a call to CopyFile_Syscall() + * (or actually use the host's copy syscall) under any circumstance. + * (Even if the filesystems are the same.) + * + * In addition, this function is NOT permitted to move / copy files across + * filesystem boundries under any circumstance. + * + * This function MUST resolve any symbolic links (symlinks) passed to it before + * performing it's task, if the host's syscall for that task does not resolve them + * automaticly. The ONLY exception is if the given dereferenceSymLinks argument is + * set to false. The default for dereferenceSymLinks is true. + * + * This function is required to translate any error that + * may be returned by the syscall into a Common namespace + * error code. + * + * The result of this function is stored in Common::commonLastErrorCode + * in addition to being returned. + * + * This function is permitted to perform any nessacarry allocations or + * modifications needed by the host's syscall to perform the task, however + * these modifications and or allocations must be undone prior to the + * function's return. In addition this function must catch any thrown + * exception created by itself or the host's syscall. (In that instance + * COMMON_ERROR_EXCEPTION_THROWN must be returned, regardless of result.) + */ +int RenamePath_Syscall(const std::string & absPathSrc, const std::string & absPathDest, const bool & dereferenceSymLinks = true); +}; + +#endif // FILEUTILLS_PRIVATE_API_H + +// End of FileUtills_Private_API.h diff --git a/src/Common/Src/File_Management_Subsystem/FileUtills_Private_API_Posix_Syscall.cpp b/src/Common/Src/File_Management_Subsystem/FileUtills_Private_API_Posix_Syscall.cpp new file mode 100644 index 0000000..f8910ad --- /dev/null +++ b/src/Common/Src/File_Management_Subsystem/FileUtills_Private_API_Posix_Syscall.cpp @@ -0,0 +1,1326 @@ +/*! + Multiverse Engine Project 04/8/2014 FileUtills FileUtills_Private_API_Posix_Syscall.cpp + + Copyright (C) 2014 Multiverse Engine Project + + This program is free software; + you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this program; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Official source repository and project information can be found at + https://github.com/codebase7/mengine +*/ + +#include "FileUtills.h" +#include "FileUtills_Private_API.h" +#include "FileUtills_Private_API_Posix_Syscall.h" + +int FileUtills::ResolveSystemSymoblicLink_Syscall(const char * path, const size_t pathSize, char ** resolvedPath, size_t * resolvedPathSize) +{ + // Init vars. + int ret = COMMON_ERROR_UNKNOWN_ERROR; // The result of this function. + int errcpy = 0; // Used to copy errno for translation if needed. + char * readLinkBuf = NULL; // Pointer to a buffer for readlink(). + char * checkBuffer = NULL; // A second buffer for readlink() that is used to verifiy the contents of readLinkBuf during the "devil's loop". + ssize_t firstBufferLength = 0; // Signed return value of the number of bytes written to the buffer by readlink(). (Just so they could return that -1 error code....) + ssize_t secondBufferLength = 0; // Signed return value of the number of bytes written to the checkBuffer by readlink(). (Just so they could return that -1 error code....) + size_t realBufferLength = 0; // Unsigned value of how big the buffer is. (Used for accessing and allocating the buffer.) + const size_t MAX_GET_EXE_PATH_REALLOC = 4; // Maximum number of times to run the memory reallocation loop. + const size_t BASE_SIZE = 1000; // Inital number of bytes to allocate. (This number is multiplied by the loop iteration value (x) after each loop iteration.) + struct stat st; // POSIX Stat structure for retriving the status of the given path. (Whether or not it's a symlink and it's length.) + + // Make sure we got a valid path. + if (pathSize > 0) + { + // Call lstat. + if (lstat(path, &st) == 0) + { + // Check and see if the given path is a symbolic link. + if (S_ISLNK((st.st_mode))) + { + // Check the size of the given link. (Just in case we get a non-conforming system that actually fills in st_size for the proc fs. (See below rant.)) + if (st.st_size > 0) + { + // OK, allocate a buffer for the given length. (Plus one so we can add a NULL character to it as readlink() does not.) + readLinkBuf = malloc((st.st_size + 1)); + if (readLinkBuf != NULL) + { + // Call readlink. + firstBufferLength = readlink(path, readLinkBuf, st.st_size); + + // Check and see if the result from readlink is not -1 and if it equals st.st_size. + if (firstBufferLength != -1) + { + if (firstBufferLength == st.st_size) + { + // Insert a NULL character after the end of the string. + readLinkBuf[st.st_size] = '\0'; + + // Copy the result to the resolvedPath buffer. + resolvedPath = readLinkBuf; + + // Set success. + ret = COMMON_ERROR_SUCCESS; + } + else + { + // OK, we got screwed with. The result should be the same size as the original lstat() call returned. + ret = COMMON_ERROR_INTERNAL_ERROR; + + // Log the error. + COMMON_LOG_VERBOSE("FileUtills_ResolveSystemSymoblicLink(): Size of the read symbolic link is not the same as the size returned from the OS."); + } + } + else + { + // Copy the error code. + errcpy = errno; + + // Translate the error code. + ret = Common_Translate_Posix_Errno_To_Common_Error_Code(errcpy); + + // Log the error. + COMMON_LOG_DEBUG("FileUtills_ResolveSystemSymoblicLink(): An error was returned while reading the symbolic link: "); + COMMON_LOG_DEBUG(Common_Get_Error_Message(ret)); + } + } + else + { + // Could not allocate buffer. + ret = COMMON_ERROR_MEMORY_ERROR; + + // Log the error. + COMMON_LOG_INFO("FileUtills_ResolveSystemSymoblicLink(): "); + COMMON_LOG_INFO(Common_Get_Error_Message(ret)); + } + } + else + { + /* + * OK, run the hard limited implemetation. + * (Copied from the original FileUtills::GetExecDirectory_Syscall() implemetation for POSIX.) + * + * We do this to avoid a runaway reallocation loop which could be considered a resource starvation + * issue. (See below for the original rant....) + * + * (Begin original rant.) + * + * Short version: + * This is a cluster. + * + * Long version: + * The only reliable (guarrenteed to work) method for getting the executable + * path in linux, is by using readlink() on /proc/self/exe. + * + * However, this has several issues. + * + * First issue: readlink() expects a preallocated buffer to store the result. + * If the preallocated buffer is too small for the full path, then readlink() + * will silently truncate the remaining data and not tell us how much was + * left over. + * + * Second issue: The proc filesystem misbehaves and does not fill in the + * st_size field of the stat structure. So as a result we can't easilly + * tell how much memory to allocate for our buffer. + * + * Third issue: Because some filesystems allow paths of unlimited size, + * (i.e. the only restriction is having the space to store the path), + * we can't use PATH_MAX (as it's possibly wrong), and we can't set a + * limit on our memory allocation. + * + * Because of these issues, the glibc MANUAL actually gives an indefinite + * loop of memory allocation->readlink()->if(!got entire link)->Deallocate memory->Allocate memory. + * for reading a symlink from the filesystem. + * + * This loop is reimplimented here, but with two differences. + * + * - The loop will end once a certian amount of reallocations (defined by MAX_GET_EXE_PATH_REALLOC) + * is reached. (This is to prevent some of the above issues.) + * + * - The loop will also check to make sure that the returned string has not been altered. + * (via memcmp). (Attempt to prevent a compromised system from mallissously changing the + * symlink's destionation as a result of our multiple accesses to /proc/self/path.) + * + * (End of original rant.) + */ + // Begin the devil's loop. + for (size_t x = 0; ((x < MAX_GET_EXE_PATH_REALLOC) && + ((readLinkBuf == NULL) && (checkBuffer == NULL)) && + (ret == COMMON_ERROR_UNKNOWN_ERROR)); x++) + { + // Recalculate bufferLength. + realBufferLength = (BASE_SIZE * (x + 1)); + + // Allocate the memory. + readLinkBuf = (char*)malloc(realBufferLength); + checkBuffer = (char*)malloc(realBufferLength); + + // Make sure it was allocated. + if ((readLinkBuf != NULL) && (checkBuffer != NULL)) + { + // Blank out the allocated memory. + memset(readLinkBuf, '\0', realBufferLength); + memset(checkBuffer, '\0', realBufferLength); + + // Call readlink() for the first buffer. + firstBufferLength = readlink(PROC_PATH, readLinkBuf, realBufferLength); + + // Check bufferLength. + if (firstBufferLength >= 0) + { + // Check to see if we got the entire path. + if (firstBufferLength < realBufferLength) + { + // Call readlink() for the second buffer. + secondBufferLength = readlink(PROC_PATH, checkBuffer, realBufferLength); + + // Check secondBufferLength. + if (secondBufferLength >= 0) + { + // Check to see if we got the entire path. + if (secondBufferLength == firstBufferLength) + { + // Call memcmp(). + if (memcmp(readLinkBuf, checkBuffer, realBufferLength) == 0) + { + // Paths match, deallocate the second buffer. + if (checkBuffer != NULL) + { + free(checkBuffer); + checkBuffer = NULL; + } + + // Copy the first buffer to the resolvedPath buffer. + resolvedPath = readLinkBuf; + + // Because the returned link is the actual executable, call GetParent(). + resolvedPath = FileUtills::GetParent(resolvedPath); + if (resolvedPath.size() > 0) + { + // Clear Common::commonLastErrorCode. + ret = COMMON_ERROR_SUCCESS; + } + else + { + // GetParent() failed. + ret = COMMON_ERROR_INTERNAL_ERROR; + COMMON_LOG_DEBUG("FileUtills_ResolveSystemSymoblicLink(): "); + COMMON_LOG_DEBUG(Common_Get_Error_Message(COMMON_ERROR_INTERNAL_ERROR)); + COMMON_LOG_DEBUG(" Call to FileUtills_GetParent() failed."); + } + } + } + } + else + { + // Error. + errcpy = errno; + ret = Common_Translate_Posix_Errno_To_Common_Error_Code(errcpy); + COMMON_LOG_DEBUG("FileUtills_ResolveSystemSymoblicLink(): readlink() system call returned: "); + COMMON_LOG_DEBUG(Common_Get_Error_Message(ret)); + } + } + } + else + { + // Error. + errcpy = errno; + ret = Common_Translate_Posix_Errno_To_Common_Error_Code(errcpy); + COMMON_LOG_DEBUG("FileUtills_ResolveSystemSymoblicLink(): readlink() system call returned: "); + COMMON_LOG_DEBUG(Common_Get_Error_Message(ret)); + } + } + } + + /* + * If we reach here, and ret == COMMON_ERROR_UNKNOWN_ERROR, + * then we have failed. (Most likely we ran out of reallocation attempts...) + */ + if (ret == COMMON_ERROR_UNKNOWN_ERROR) + { + /* + * Set COMMON_INTERNAL_ERROR. + * + * (The system most likely can fetch the link, + * but we need to limit the reallocation attempts + * to prevent issues. So it's not appropriate to use + * FILEUTILLS_PATH_LENGTH_INVALID.) + */ + ret = COMMON_ERROR_INTERNAL_ERROR; + COMMON_LOG_INFO("FileUtills_ResolveSystemSymoblicLink(): "); + COMMON_LOG_INFO(Common_Get_Error_Message(COMMON_ERROR_INTERNAL_ERROR)); + COMMON_LOG_INFO(" Unable to resolve the symbolic link due to engine limitation. (Length of the resolved path is too long.)"); + } + } + } + else + { + // This is not a symbolic link. + ret = COMMON_ERROR_INVALID_ARGUMENT; + + // Log the error. + COMMON_LOG_INFO("FileUtills_ResolveSystemSymoblicLink(): The given path ( "); + COMMON_LOG_INFO(path); + COMMON_LOG_INFO(" ) is not a symbolic link created by the system."); + } + } + else + { + // Copy errno. + errcpy = errno; + + // Translate the error. + ret = Common_Translate_Posix_Errno_To_Common_Error_Code(errcpy); + + // Log the error. + COMMON_LOG_DEBUG("FileUtills_ResolveSystemSymoblicLink(): An error was returned while accessing the given path: "); + COMMON_LOG_DEBUG(Common_Get_Error_Message(ret)); + } + } + else + { + // Invalid path. + ret = COMMON_ERROR_INVALID_ARGUMENT; + + // Log the error. + COMMON_LOG_DEBUG("FileUtills_ResolveSystemSymoblicLink(): "); + COMMON_LOG_DEBUG(Common_Get_Error_Message(COMMON_ERROR_INVALID_ARGUMENT)); + COMMON_LOG_DEBUG(" Given path argument is invalid."); + } + + // Deallocate the used memory if needed. + if (readLinkBuf != NULL) + { + // Deallocate the memory. + free(readLinkBuf); + readLinkBuf = NULL; + } + if (checkBuffer != NULL) + { + // Deallocate the memory. + free(checkBuffer); + checkBuffer = NULL; + } + + // Reset resolvedPath if needed. + if (ret != COMMON_ERROR_SUCCESS) + { + // Reset resolvedPath. + resolvedPath.clear(); + } + + // Return the result. + return ret; +} + +int FileUtills::GetUserProfileDirectoryPath_Syscall(std::string & path) +{ + // Init vars. + int ret = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; // The result of this function. +#ifdef __linux__ + // Init vars. + int errorg = 0; // Used to hold the original state of errno so it can be restored after we finish. + int errcpy = 0; // Used to store errno if needed. + char * pHD = NULL; // Used to fetch the path from the system. + + // Backup and clear errno. + errorg = errno; + errno = 0; + + // Blank out the path value. + path.clear(); + + // Get the path to the user's profile directory. + try { + pHD = getenv("HOME"); + if ((errno == 0) && (pHD != NULL)) + { + // Copy the variable to the path. + path = pHD; + + // Set success code. + ret = COMMON_ERROR_SUCCESS; + } + else + { + // Could not get user profile directory path variable. + errcpy = errno; + ret = Common::Translate_Posix_Errno_To_Common_Error_Code(errcpy); + COMMON_LOG_VERBOSE("FileUtills::GetUserProfileDirectoryPath(): "); + COMMON_LOG_VERBOSE(Common::Get_Error_Message(ret)); + COMMON_LOG_VERBOSE(" Could not get user profile directory path from enviorment.\n"); + + // Reset path. + path.clear(); + } + } + catch (exception &ex) + { + // Exception thown. + ret = COMMON_ERROR_EXCEPTION_THROWN; + COMMON_LOG_VERBOSE("FileUtills::GetUserProfileDirectoryPath(): "); + COMMON_LOG_VERBOSE(Common::Get_Error_Message(ret)); + COMMON_LOG_VERBOSE(" "); + COMMON_LOG_VERBOSE(ex.what()); + COMMON_LOG_VERBOSE("\n"); + + // Reset path. + path.clear(); + } + + // Check for an allocated buffer. + if (pHD != NULL) + { + // Release the buffer. + free(pHD); + pHD = NULL; + } + + // Restore errno. + errno = errorg; +#endif // __linux__ + + // Copy ret to Common::commonLastErrorCode. + Common::commonLastErrorCode = ret; + + // Return the result. + return ret; +} + +int FileUtills::GetCurrentWorkingDirectoryPath_Syscall(std::string & path) +{ + // Init vars. + int ret = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; // The result of this function. +#ifdef __linux__ + int errorg = 0; // Used to hold the original state of errno so it can be restored after we finish. + int errcpy = 0; // Used to store errno if needed. + char * pCWD = NULL; // Used to fetch path from system. + + // Backup and clear errno. + errorg = errno; + errno = 0; + + // Blank out the path value. + path.clear(); + + // Get current directory. + try { + /* + * NOTE: The call below is linux (libc5, libc6, and glibc) specific. + * (The standard requires a preallocated buffer.) + * + * I dislike the idea of a preallocated buffer as we cannot reliably + * determine the needed length. (Plus it could change between calls.) + * + * This really should be checked for and an error thrown if the OS / + * libc in use does not support this usage. + */ + pCWD = getcwd(NULL, 0); + if ((errno == 0) && (pCWD != NULL)) + { + // Copy the path. + path = pCWD; + + // Set ret. + ret = COMMON_ERROR_SUCCESS; + } + else + { + // Could not get current working directory path variable. + errcpy = errno; + ret = Common::Translate_Posix_Errno_To_Common_Error_Code(errcpy); + COMMON_LOG_VERBOSE("FileUtills::GetCurrentWorkingDirectoryPath(): "); + COMMON_LOG_VERBOSE(Common::Get_Error_Message(ret)); + COMMON_LOG_VERBOSE(" Could not get current working directory path from enviorment.\n"); + + // Reset path. + path.clear(); + } + } + catch(exception &ex) + { + // Exception thown. + ret = COMMON_ERROR_EXCEPTION_THROWN; + COMMON_LOG_VERBOSE("FileUtills::GetCurrentWorkingDirectoryPath(): "); + COMMON_LOG_VERBOSE(Common::Get_Error_Message(ret)); + COMMON_LOG_VERBOSE(" "); + COMMON_LOG_VERBOSE(ex.what()); + COMMON_LOG_VERBOSE("\n"); + + // Reset path. + path.clear(); + } + + // Check for an allocated buffer. + if (pCWD != NULL) + { + // Release the buffer. + free(pCWD); + pCWD = NULL; + } + + // Restore errno. + errno = errorg; +#endif // __linux__ + + // Copy ret to Common::commonLastErrorCode. + Common::commonLastErrorCode = ret; + + // Return the result. + return ret; +} + +int FileUtills::GetExecDirectory_Syscall(std::string & retStr) +{ + // Init vars. + int ret = COMMON_ERROR_UNKNOWN_ERROR; // The result code returned from this function. + std::string result = ""; // The string returned from this function. +#ifdef __linux__ + + // Call FileUtills::ResolveSystemSymoblicLink_Syscall(). (Make sure it's the real path not a symlink. (PROC_PATH is a symlink, and a weird one at that.)) + ret = FileUtills::ResolveSystemSymoblicLink_Syscall(PROC_PATH, result); + if (ret == COMMON_ERROR_SUCCESS) + { + // Copy the result string to retStr. + retStr = result; + } + else + { + // Check for an invalid argument error. + if (ret == COMMON_ERROR_INVALID_ARGUMENT) + { + // This is an internal engine error. + ret = COMMON_ERROR_INTERNAL_ERROR; + + // Report it. + COMMON_LOG_WARNING("FileUtills::GetExecDirectory(): "); + COMMON_LOG_WARNING(Common::Get_Error_Message(COMMON_ERROR_INTERNAL_ERROR)); + COMMON_LOG_WARNING(" Getting the executable path failed. (Call to an internal engine function failed.) Please report this bug.\n"); + } + } + +#endif + // Clear the result string. + result.clear(); + + // Return result. + return ret; +} + +FileUtills::dirlist * FileUtills::getDirectory_Syscall(const std::string & absPath, const bool & cleanList) +{ + // Init vars. + int errcpy = 0; // Used to fetch the error code. + FileUtills::dirlist * ret = NULL; // The FileUtills directory structure. + struct dirent * dir = NULL; // The OS (POSIX) directory structure. + DIR * dp = NULL; // Directory stream to hold directory name..... (Why can't it just take a c string?) + std::string tempname = ""; // Used to store the filename / subdirectory name for the addToArray function. + + // Dumb check. + if (absPath.size() > 0) + { +#ifdef POSIX_COMMON_H + // Allocate the dirlist. + try{ + ret = new FileUtills::dirlist; + if (ret != NULL) + { + // Set the path. + ret->path = absPath; + + // Dump the path as a c string into the Directory stream object......(Overly complicated POS......) + + // Check and make sure we can open the directory first. + if ((dp = (opendir(absPath.c_str()))) == NULL) + { + // Copy the error code, and translate it. + errcpy = errno; + errcpy = Common::Translate_Posix_Errno_To_Common_Error_Code(errcpy); + + // An error occured. + if (ret != NULL) + { + delete ret; + ret = NULL; + } + + // Log the error. + COMMON_LOG_INFO("FileUtills::getDirectory(): Unable to get directory contents for ( "); + COMMON_LOG_INFO(absPath.c_str()); + COMMON_LOG_INFO(" ) The system returned "); + COMMON_LOG_INFO(Common::Get_Error_Message(errcpy)); + COMMON_LOG_INFO("\n"); + + // Copy the translated error code to Common::commonLastErrorCode. + Common::commonLastErrorCode = errcpy; + } + + // Start filesystem fetch loop. + while ((dir = readdir(dp))) // Call Host OS function. + { + // Check and see if the cleanList flag is set. + if (cleanList) + { + // Check to see if d_name is a POSIX directory shortcut. + if ((strcmp(dir->d_name, ".") == 0) || (strcmp(dir->d_name, "..") == 0)) + { + // d_name is a directory shortcut, do not add it to the list. + continue; + } + } + + // Cast d_name to a string. + tempname = dir->d_name; + + // Add the data to the array. + ret->list.push_back(tempname); + } + + // Close the directory stream and reset it. + closedir(dp); + + // Set the number of entries. + ret->numOfEntries = ret->list.size(); + + // Set Common::commonLastErrorCode. + Common::commonLastErrorCode = COMMON_ERROR_SUCCESS; + } + else + { + // Could not allocate memory. + Common::commonLastErrorCode = COMMON_ERROR_MEMORY_ERROR; + } + } + catch(exception &ex) + { + // Free memory if needed. + if (ret != NULL) + { + delete ret; + ret = NULL; + } + + // Could not allocate struct. + Common::commonLastErrorCode = COMMON_ERROR_EXCEPTION_THROWN; + + // Log the error. + COMMON_LOG_DEBUG("FileUtills::getDirectory(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(COMMON_ERROR_EXCEPTION_THROWN)); + COMMON_LOG_DEBUG(" "); + COMMON_LOG_DEBUG(ex.what()); + COMMON_LOG_DEBUG("\n"); + } +#endif + } + else + { + // Invalid path. + Common::commonLastErrorCode = COMMON_ERROR_INVALID_ARGUMENT; + + // Log the error. + COMMON_LOG_DEBUG("FileUtills::getDirectory(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(COMMON_ERROR_INVALID_ARGUMENT)); + COMMON_LOG_DEBUG(" Given path is invalid.\n"); + } + + // Return the result. + return ret; +} + +int FileUtills::GetByteFreespace_Syscall(const std::string & absPath, size_t & result) +{ + // Init vars. + int ret = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; // The result of this function. + +#ifdef POSIX_COMMON_H + struct statvfs * buffer = NULL; // Buffer used to get filesystem info from the OS. + + // Reset result. + result = 0; + + // Check for invalid absPath. + if (absPath.size() > 0) + { + // Begin try block. + try { + // Create buffer. + buffer = new struct statvfs; + if (buffer != NULL) + { + // Call host's function, and check for error. + if (statvfs(absPath.c_str(), buffer) == 0) + { + // Determine number of free bytes. (Number of avaiable blocks * block size) + result = (buffer->f_bavail * buffer->f_bsize); + + // Set success. + ret = COMMON_ERROR_SUCCESS; + } + else + { + // Figure out what the error we got back was. + ret = errno; + ret = Common::Translate_Posix_Errno_To_Common_Error_Code(ret); + + // Log the error. + COMMON_LOG_DEBUG("FileUtills::GetByteFreespace(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(ret)); + COMMON_LOG_DEBUG("\n"); + } + + // Delete the buffer + delete buffer; + buffer = NULL; + } + else + { + // Could not allocate memory. + ret = COMMON_ERROR_MEMORY_ERROR; + + // Log the error. + COMMON_LOG_DEBUG("FileUtills::GetByteFreespace(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(ret)); + COMMON_LOG_DEBUG("\n"); + } + } + catch (exception &ex) + { + // Exception thrown. + ret = COMMON_ERROR_EXCEPTION_THROWN; + + // Check for allocated buffer. + if (buffer != NULL) + { + delete buffer; + buffer = NULL; + } + + // Log the error. + COMMON_LOG_VERBOSE("FileUtills::GetByteFreespace(): "); + COMMON_LOG_VERBOSE(Common::Get_Error_Message(ret)); + COMMON_LOG_VERBOSE(" "); + COMMON_LOG_VERBOSE(ex.what()); + COMMON_LOG_VERBOSE("\n"); + } + } + else + { + // Invalid absPath. + ret = COMMON_ERROR_INVALID_ARGUMENT; + + // Log the error. + COMMON_LOG_DEBUG("FileUtills::GetByteFreespace(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(ret)); + COMMON_LOG_DEBUG(" Given path is invalid.\n"); + } +#endif + + // Copy ret to Common::commonLastErrorCode. + Common::commonLastErrorCode = ret; + + // Return the result. + return ret; +} + +int FileUtills::CreateDirectory_Syscall(const char * absPath) +{ + // Init errcpy. + int ret = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; // The result of this function. + int errcpy = 0; // Used to copy errno for translation if needed. + + // Check for NULL pointer. + if (absPath != NULL) + { + // Attempt to create the given directory. + if (mkdir(absPath, S_IRWXU) != 0) + { + // Copy errno, and convert it. + errcpy = errno; + ret = Common::Translate_Posix_Errno_To_Common_Error_Code(errcpy); + } + else + { + // Directory created successfully. + ret = COMMON_ERROR_SUCCESS; + } + } + else + { + // Invalid argument. + ret = COMMON_ERROR_INVALID_ARGUMENT; + + // Log the error. + COMMON_LOG_DEBUG("FileUtills::CreateDirectory(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(ret)); + COMMON_LOG_DEBUG(" Given path is invalid.\n"); + } + + // Copy ret to Common::commonLastErrorCode. + Common::commonLastErrorCode = ret; + + // Return the result. + return ret; +} + +int FileUtills::CheckPermissions_Syscall(const std::string & absPath, const bool & read, const bool & write, const bool & exec) +{ + // Init vars. + int errcpy = 0; // Used to hold the errno value to translate it if needed. + int mode = 0; // Used to construct the mode bitmask. + int ret = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; // The result of this function. + + // Make sure that absPath is valid. + if (absPath.size() > 0) + { + // Double check and make sure we have something to do. + if ((read != false) || (write != false) || (exec != false)) + { + // Set the mode. + mode = F_OK; + + // Check for read permission check. + if (read == true) + { + mode = mode | R_OK; + } + + // Check for write permission check. + if (write == true) + { + mode = mode | W_OK; + } + + // Check for execute permission check. + if (exec == true) + { + mode = mode | X_OK; + } + + // Issue syscall. + ret = access(absPath.c_str(), mode); + if (ret == 0) + { + // File or directory is readable & writable set ret to: COMMON_ERROR_SUCCESS. + ret = COMMON_ERROR_SUCCESS; + } + else + { + // Translate the errorcode. + errcpy = errno; + ret = Common::Translate_Posix_Errno_To_Common_Error_Code(errcpy); + + // Log the error. + COMMON_LOG_VERBOSE("FileUtills::CheckPermissions(): "); + COMMON_LOG_VERBOSE(Common::Get_Error_Message(Common::commonLastErrorCode)); + COMMON_LOG_VERBOSE("\n"); + } + } + else + { + // No check to make. + ret = COMMON_ERROR_INVALID_ARGUMENT; + + // Log the error. + COMMON_LOG_DEBUG("FileUtills::CheckPermissions(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(ret)); + COMMON_LOG_DEBUG(" No check to perform, aborting.\n"); + } + } + else + { + // Invalid absPath. + ret = COMMON_ERROR_INVALID_ARGUMENT; + + // Log the error. + COMMON_LOG_DEBUG("FileUtills::CheckPermissions(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(ret)); + COMMON_LOG_DEBUG(" Given path is invalid.\n"); + } + + // Copy ret to Common::commonLastErrorCode. + Common::commonLastErrorCode = ret; + + // Default return. + return ret; +} + +int FileUtills::DoesExist_Syscall(const std::string & absPath) +{ + // Init vars. + int ret = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; // The result of this function. + + // Check for valid arg. + if (absPath.size() > 0) + { +#ifdef POSIX_COMMON_H + int errcpy = 0; // Used to copy errno if needed. + + // Check and see if the file exists. + ret = access(absPath.c_str(), F_OK); + if (ret == 0) + { + // Path exists. + ret = FILEUTILLS_ERROR_EXISTANT; + } + else + { + // Copy the error code. + errcpy = errno; + + // Translate the error code. + ret = Common::Translate_Posix_Errno_To_Common_Error_Code(errcpy); + } +#endif // POSIX_COMMON_H + } + else + { + // Invalid absPath. + ret = COMMON_ERROR_INVALID_ARGUMENT; + + // Log the error. + COMMON_LOG_DEBUG("FileUtills::DoesExist(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(ret)); + COMMON_LOG_DEBUG(" Given path is invalid.\n"); + } + + // Set Common::commonLastErrorCode. + Common::commonLastErrorCode = ret; + + // Return the result. + return ret; +} + +int FileUtills::IsFileOrDirectory_Syscall(const char * absPath, const size_t absPathSize) +{ + // Init vars. + int ret = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; // Result of this function. (Defaults to function not implemetated.) + int errcpy = 0; // Used to copy errno if needed. + +#ifdef POSIX_COMMON_H + struct stat * buf = NULL; // Linux stat structure, used with syscall. + + // Check for invalid absPath. + if ((absPath != NULL) && (absPathSize() > 0)) + { + // Init stat buffer. + buf = new struct stat; + if (buf != NULL) + { + // Ask the OS to stat() the path. + ret = lstat(absPath, buf); + + // Check the result. + if (ret == 0) + { + // Log result. + COMMON_LOG_VERBOSE("FileUtills::IsFileOrDirectory(): The given path ( "); + COMMON_LOG_VERBOSE(absPath); + + // Check the stat structure. + if (S_ISREG((buf->st_mode))) + { + // Path is a regular file. + ret = FILEUTILLS_ERROR_PATH_IS_A_FILE; + + // Log result. + COMMON_LOG_VERBOSE(" ) is a regular file."); + } + else + { + if (S_ISDIR((buf->st_mode))) + { + // Path is a directory. + ret = FILEUTILLS_ERROR_PATH_IS_A_DIRECTORY; + + // Log result. + COMMON_LOG_VERBOSE(" ) is a directory."); + } + else + { + // Check for a symlink. + if (S_ISLNK((buf->st_mode))) + { + // Symlink. + ret = FILEUTILLS_ERROR_PATH_IS_A_SYMLINK; + + // Log result. + COMMON_LOG_VERBOSE(" ) is a symbolic link."); + } + else + { + // Special file. + ret = COMMON_ERROR_SUCCESS; + + // Log result. + COMMON_LOG_VERBOSE(" ) is a special file."); + } + } + } + } + else + { + // Error, translate it and log it. + errcpy = errno; + ret = Common::Translate_Posix_Errno_To_Common_Error_Code(errcpy); + + // Check for non-existance. + if (ret == FILEUTILLS_ERROR_NON_EXISTANT) + { + COMMON_LOG_VERBOSE("FileUtills::IsFileOrDirectory(): The given path ( "); + COMMON_LOG_VERBOSE(absPath); + COMMON_LOG_VERBOSE(" ) or a componet of it does not exist."); + } + else + { + COMMON_LOG_DEBUG("FileUtills::IsFileOrDirectory(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(ret)); + COMMON_LOG_DEBUG(" Was returned while checking path ( "); + COMMON_LOG_DEBUG(absPath); + COMMON_LOG_DEBUG(" )."); + } + } + + // Delete stat buffer. + delete buf; + buf = NULL; + } + else + { + // Coul not allocate stat structure. + ret = COMMON_ERROR_MEMORY_ERROR; + + // Log the error if needed. + COMMON_LOG_DEBUG("FileUtills::IsFileOrDirectory(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(ret)); + } + } + else + { + // Invalid absPath. + ret = COMMON_ERROR_INVALID_ARGUMENT; + + // Log the error. + COMMON_LOG_DEBUG("FileUtills::IsFileOrDirectory(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(ret)); + COMMON_LOG_DEBUG(" Given path is invalid."); + } +#endif // POSIX_COMMON_H + + // Return the result. + return ret; +} + +int FileUtills::DeletePath_Syscall(const std::string & absPath) +{ + // Init vars. + int ret = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; // The result of this function. + int errcpy = 0; // Used to copy the error code if needed. + + // Begin try block. + try { + // Check for invalid absPath. + if (absPath.size() > 0) + { +#ifdef POSIX_COMMON_H + // Issue syscall. + if (remove(absPath.c_str()) == 0) + { + // Success. + ret = COMMON_ERROR_SUCCESS; + } + else + { + // Copy errno. + errcpy = errno; + + // Translate the error. + ret = Common::Translate_Posix_Errno_To_Common_Error_Code(errcpy); + } +#endif // POSIX_COMMON_H + } + else + { + // Invalid absPath. + ret = COMMON_ERROR_INVALID_ARGUMENT; + + // Log the error. + COMMON_LOG_DEBUG("FileUtills::DeletePath(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(ret)); + COMMON_LOG_DEBUG(" Given path is invalid.\n"); + } + } + catch (exception &ex) + { + // Exception thrown. + ret = COMMON_ERROR_EXCEPTION_THROWN; + + // Log the error. + COMMON_LOG_VERBOSE("FileUtills::DeletePath(): "); + COMMON_LOG_VERBOSE(Common::Get_Error_Message(ret)); + COMMON_LOG_VERBOSE(" "); + COMMON_LOG_VERBOSE(ex.what()); + COMMON_LOG_VERBOSE("\n"); + } + + // Copy ret to Common::commonLastErrorCode. + Common::commonLastErrorCode = ret; + + // Return the result. + return ret; +} + +int FileUtills::RenamePath_Syscall(const std::string & absPathSrc, const std::string & absPathDest, const bool & dereferenceSymLinks) +{ + // Init vars. + bool srcIsASymLink = false; // Used to tell if the source is a symlink. + bool destIsASymLink = false; // Used to tell if the destionation is a symlink. + int ret = COMMON_ERROR_UNKNOWN_ERROR; // The result of this function. + int errcpy = 0; // Used to copy errno for translation if needed. + char * resultFromRealPath = NULL; // Used to check the result from realpath(). + char * srcLinkedPath = NULL; // Used to hold the dereferenced source path if needed. + char * destLinkedPath = NULL; // Used to hold the dereferenced destionation path if needed. + + // Begin try block. + try { + // Check for valid source path. + if (absPathSrc.capacity() > 0) + { + // Check for valid destionation path. + if (absPathDest.capacity() > 0) + { + // Disable the symlink check if dereferenceSymLinks is set to false. + if (!dereferenceSymLinks) + { + // Check and see if the source is a symlink. + ret = FileUtills::IsFileOrDirectory_Syscall(absPathSrc); + if (ret == FILEUTILLS_ERROR_PATH_IS_A_SYMLINK) + { + // Clear resultFromRealPath. + resultFromRealPath = NULL; + + // Source is a symlink, so we need to dereference it. + srcIsASymLink = true; + resultFromRealPath = realpath(absPathSrc.c_str(), srcLinkedPath); + if (resultFromRealPath == NULL) + { + // We've hit an error. + errcpy = errno; + ret = Common::Translate_Posix_Errno_To_Common_Error_Code(errcpy); + + // Log the error. + COMMON_LOG_DEBUG("FileUtills::RenamePath(): Unable to dereference symlink on the source path ( "); + COMMON_LOG_DEBUG(absPathSrc.c_str()); + COMMON_LOG_DEBUG(").\n"); + + // Deallocate the srcLinkedPath if needed. + if (srcLinkedPath != NULL) + { + free(srcLinkedPath); + srcLinkedPath = NULL; + } + } + } + + // Check and see if the destionation is a symlink. + ret = FileUtills::IsFileOrDirectory_Syscall(absPathDest); + if (ret == FILEUTILLS_ERROR_PATH_IS_A_SYMLINK) + { + // Clear resultFromRealPath. + resultFromRealPath = NULL; + + // Destionation is a symlink, so we need to dereference it. + destIsASymLink = true; + resultFromRealPath = realpath(absPathDest.c_str(), destLinkedPath); + if (resultFromRealPath == NULL) + { + // We've hit an error. + errcpy = errno; + ret = Common::Translate_Posix_Errno_To_Common_Error_Code(errcpy); + + // Log the error. + COMMON_LOG_DEBUG("FileUtills::RenamePath(): Unable to dereference symlink on the destionation path ( "); + COMMON_LOG_DEBUG(absPathDest.c_str()); + COMMON_LOG_DEBUG(").\n"); + + // Deallocate the destLinkedPath if needed. + if (destLinkedPath != NULL) + { + free(destLinkedPath); + destLinkedPath = NULL; + } + } + } + } + + // Check and see what variables must be passed to rename. + if (srcIsASymLink && destIsASymLink) + { + // Check for allocated srcLinkedPath. + if (srcLinkedPath != NULL) + { + // Check for allocated destLinkedPath. + if (destLinkedPath != NULL) + { + // Issue syscall. + errcpy = rename(srcLinkedPath, destLinkedPath); + } + else + { + // Success without result? + ret = COMMON_ERROR_INTERNAL_ERROR; + + // Log the error. + COMMON_LOG_WARNING("FileUtills::RenamePath(): Resolved symlink buffer for the destionation path ( "); + COMMON_LOG_WARNING(absPathDest.c_str()); + COMMON_LOG_WARNING(" ) is invalid, but it should be valid. Please report this bug.\n"); + } + } + else + { + // Success without result? + ret = COMMON_ERROR_INTERNAL_ERROR; + + // Log the error. + COMMON_LOG_WARNING("FileUtills::RenamePath(): Resolved symlink buffer for the source path ( "); + COMMON_LOG_WARNING(absPathSrc.c_str()); + COMMON_LOG_WARNING(" ) is invalid, but it should be valid. Please report this bug.\n"); + } + } + else + { + if (srcIsASymLink && !destIsASymLink) + { + // Check for allocated srcLinkedPath. + if (srcLinkedPath != NULL) + { + // Issue syscall. + errcpy = rename(srcLinkedPath, absPathDest.c_str()); + } + else + { + // Success without result? + ret = COMMON_ERROR_INTERNAL_ERROR; + + // Log the error. + COMMON_LOG_WARNING("FileUtills::RenamePath(): Resolved symlink buffer for the source path ( "); + COMMON_LOG_WARNING(absPathSrc.c_str()); + COMMON_LOG_WARNING(" ) is invalid, but it should be valid. Please report this bug.\n"); + } + } + else + { + if (!srcIsASymLink && destIsASymLink) + { + // Check for allocated destLinkedPath. + if (destLinkedPath != NULL) + { + // Issue syscall. + errcpy = rename(absPathSrc.c_str(), destLinkedPath); + } + else + { + // Success without result? + ret = COMMON_ERROR_INTERNAL_ERROR; + + // Log the error. + COMMON_LOG_WARNING("FileUtills::RenamePath(): Resolved symlink buffer for the destionation path ( "); + COMMON_LOG_WARNING(absPathDest.c_str()); + COMMON_LOG_WARNING(" ) is invalid, but it should be valid. Please report this bug.\n"); + } + } + else + { + // Issue syscall. + errcpy = rename(absPathSrc.c_str(), absPathDest.c_str()); + } + } + } + + // Check to see if we hit an internal error. + if (ret != COMMON_ERROR_INTERNAL_ERROR) + { + // Check the result of the syscall. + if (errcpy == 0) + { + // Success. + ret = COMMON_ERROR_SUCCESS; + } + else + { + // Copy the error code. + errcpy = errno; + + // Check for EXDEV. + if (errcpy = EXDEV) + { + // The result is that the source and destionation are not on the same filesystem. + ret = FILEUTILLS_ERROR_NOT_ON_SAME_FILESYSTEM; + } + else + { + // Translate the error code. + ret = Common::Translate_Posix_Errno_To_Common_Error_Code(errcpy); + } + } + } + } + else + { + // Invalid absPathDest. + ret = COMMON_ERROR_INVALID_ARGUMENT; + + // Log the error. + COMMON_LOG_DEBUG("FileUtills::RenamePath(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(ret)); + COMMON_LOG_DEBUG(" Given destionation path is invalid.\n"); + } + } + else + { + // Invalid absPathSrc. + ret = COMMON_ERROR_INVALID_ARGUMENT; + + // Log the error. + COMMON_LOG_DEBUG("FileUtills::RenamePath(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(ret)); + COMMON_LOG_DEBUG(" Given source path is invalid.\n"); + } + + // Deallocate srcLinkedPath and destLinkedPath if needed. + if (srcLinkedPath != NULL) + { + free(srcLinkedPath); + srcLinkedPath = NULL; + } + if (destLinkedPath != NULL) + { + free(destLinkedPath); + destLinkedPath = NULL; + } + } + catch (exception &ex) + { + // Exception thrown. + ret = COMMON_ERROR_EXCEPTION_THROWN; + + // Log the error. + COMMON_LOG_VERBOSE("FileUtills::RenamePath(): "); + COMMON_LOG_VERBOSE(Common::Get_Error_Message(ret)); + COMMON_LOG_VERBOSE(" "); + COMMON_LOG_VERBOSE(ex.what()); + COMMON_LOG_VERBOSE("\n"); + } + + // Copy ret to Common::commonLastErrorCode. + Common::commonLastErrorCode = ret; + + // Return the result. + return ret; +} diff --git a/src/Common/Src/File_Management_Subsystem/FileUtills_Private_API_Posix_Syscall.h b/src/Common/Src/File_Management_Subsystem/FileUtills_Private_API_Posix_Syscall.h new file mode 100644 index 0000000..78ed703 --- /dev/null +++ b/src/Common/Src/File_Management_Subsystem/FileUtills_Private_API_Posix_Syscall.h @@ -0,0 +1,30 @@ +/*! + Multiverse Engine Project 16/5/2015 FileUtills FileUtills_Private_API_Posix_Syscall.h + + Copyright (C) 2015 Multiverse Engine Project + + This program is free software; + you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this program; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Official source repository and project information can be found at + https://github.com/codebase7/mengine +*/ + +// Include guard. +#ifndef FILEUTILLS_PRIVATE_API_POSIX_SYSCALL_H +#define FILEUTILLS_PRIVATE_API_POSIX_SYSCALL_H + +// Local definitions for paths. +#define PROC_PATH "/proc/self/exe" // The actual path to the symlink that represents the executable in the /proc filesystem. + +#endif // FILEUTILLS_PRIVATE_API_POSIX_SYSCALL_H + +// End of FileUtills_Private_API_Posix_Syscall.h From d222e073b0983a529f35b0c01cfacb6bdd19ec4e Mon Sep 17 00:00:00 2001 From: codebase7 Date: Sun, 24 May 2015 20:15:38 -0400 Subject: [PATCH 003/325] Update FileUtills::RemoveLastPathSegment(). This commit makes FileUtills::RemoveLastPathSegment() conform to the new FileUtills API requirements. (Does not use C++ code, returns Common error codes, results in argument list, no modification to arguments unless successful.) --- .../File_Management_Subsystem/FileUtills.cpp | 2 +- .../FileUtills_Private_API.cpp | 96 ++++++++++++------- .../FileUtills_Private_API.h | 19 ++-- 3 files changed, 72 insertions(+), 45 deletions(-) diff --git a/src/Common/Src/File_Management_Subsystem/FileUtills.cpp b/src/Common/Src/File_Management_Subsystem/FileUtills.cpp index a8ebee5..a9b1c13 100644 --- a/src/Common/Src/File_Management_Subsystem/FileUtills.cpp +++ b/src/Common/Src/File_Management_Subsystem/FileUtills.cpp @@ -437,7 +437,7 @@ int FileUtills::ResolvePath(const char * path, const size_t pathSize, char * ret if (ret == FILEUTILLS_ERROR_PATH_IS_RELATIVE) { // Remove the symlink from the outputStr. - ret = FileUtills::RemoveLastPathSegment(outputStr, outputStrSize); + ret = FileUtills::RemoveLastPathSegment(&outputStr, &outputStrSize); if (ret == COMMON_ERROR_SUCCESS) { // Reallocate the buffer to store the relative path. diff --git a/src/Common/Src/File_Management_Subsystem/FileUtills_Private_API.cpp b/src/Common/Src/File_Management_Subsystem/FileUtills_Private_API.cpp index 39a0177..66abf48 100644 --- a/src/Common/Src/File_Management_Subsystem/FileUtills_Private_API.cpp +++ b/src/Common/Src/File_Management_Subsystem/FileUtills_Private_API.cpp @@ -245,45 +245,58 @@ int FileUtills::GetLastPathSegment(const std::string & path, std::string & pathS return (FileUtills::GetPathSegment(path, currentPathPos, pathSegment)); } -int FileUtills::RemoveLastPathSegment(std::string & path, size_t & currentPathPos) +int FileUtills::RemoveLastPathSegment(char ** path, size_t * pathSize, size_t * currentPathPos) { // Init vars. int result = COMMON_ERROR_UNKNOWN_ERROR; // Result of this function. + size_t tempPathSize = 0; // The temporary variable used to store the new path's size. // Check for valid path. - if (path.capacity() > 0) + if ((pathSize != NULL) && ((*pathSize) > 0) && (path != NULL) && ((*path) != NULL)) { // Check for a valid path position. - if (currentPathPos > 0) + if ((currentPathPos != NULL) && ((*currentPathPos) > 0)) { // Make sure the path position is within the path buffer. - if (currentPathPos < path.capacity()) + if (*currentPathPos < *pathSize) { // Remove last path segment from output. (Search from the end of the output string.) - for (size_t y = 0; ((y < path.capacity()) && (result == COMMON_ERROR_UNKNOWN_ERROR)); y++) + for (size_t y = 0; ((y < (*pathSize))) && (result == COMMON_ERROR_UNKNOWN_ERROR)); y++) { // Look for the DIR_SEP. - if (path[(currentPathPos - y)] == DIR_SEP) + if ((*path)[((*currentPathPos) - y)] == DIR_SEP) { // Check to see if we have hit the first directory seperator. - if ((currentPathPos - y) == MINIMAL_VALID_ABSOLUTE_PATH_LENGTH) + if (((*currentPathPos) - y) == MINIMAL_VALID_ABSOLUTE_PATH_LENGTH) { // Decrement y, as we need this directory seperator. y--; } - // This position is the start of the last directory segment. - for (size_t z = 0; z < (path.capacity() - (currentPathPos - y)); z++) - { - // Blank the value. - path[((currentPathPos - y) + z)] = '\0'; - } + // Calculate the new string's length. + tempPathSize = (sizeof(char) * ((*currentPathPos) - y)); - // Reset the path position. - currentPathPos = (currentPathPos - y); + // Reallocate the new path string. + result = FileUtills_Reallocate_CString_Buffer(path, (*pathSize), tempPathSize); + if (result == COMMON_ERROR_SUCCESS) - // Set result. - result = COMMON_ERROR_SUCCESS; + // Reset the current path position. + (*currentPathPos) = ((*currentPathPos) - y); + + // Reset the pathSize. + (*pathSize) = tempPathSize; + } + else + { + // Call to FileUtills_Reallocate_CString_Buffer() failed. + COMMON_LOG_DEBUG("FileUtills_RemoveLastPathSegment(): Call to FileUtills_Reallocate_CString_Buffer() failed with error code: "); + COMMON_LOG_DEBUG(Common_Get_Error_Message(result)); + if (result == COMMON_ERROR_UNKNOWN_ERROR) + { + // Change result to COMMON_ERROR_INTERNAL_ERROR, to avoid false success message later. + result = COMMON_ERROR_INTERNAL_ERROR; + } + } } } @@ -297,50 +310,59 @@ int FileUtills::RemoveLastPathSegment(std::string & path, size_t & currentPathPo { // currentPathPos is beyond the end of the path buffer. result = COMMON_ERROR_INVALID_ARGUMENT; - COMMON_LOG_VERBOSE("FileUtills::RemoveLastPathSegment(): "); - COMMON_LOG_VERBOSE(Common::Get_Error_Message(result)); - COMMON_LOG_VERBOSE(" current path position is beyond the end of the path buffer. (Nice try.)\n"); + COMMON_LOG_VERBOSE("FileUtills_RemoveLastPathSegment(): "); + COMMON_LOG_VERBOSE(Common_Get_Error_Message(COMMON_ERROR_INVALID_ARGUMENT)); + COMMON_LOG_VERBOSE(" current path position is beyond the end of the path buffer. (Nice try.)"); } } else { // Invalid currentPathPos. result = COMMON_ERROR_INVALID_ARGUMENT; - COMMON_LOG_VERBOSE("FileUtills::RemoveLastPathSegment(): "); - COMMON_LOG_VERBOSE(Common::Get_Error_Message(result)); - COMMON_LOG_VERBOSE(" current path position is invalid.\n"); + COMMON_LOG_VERBOSE("FileUtills_RemoveLastPathSegment(): "); + COMMON_LOG_VERBOSE(Common_Get_Error_Message(COMMON_ERROR_INVALID_ARGUMENT)); + COMMON_LOG_VERBOSE(" current path position is invalid."); } } else { // No path given. result = COMMON_ERROR_INVALID_ARGUMENT; - COMMON_LOG_VERBOSE("FileUtills::RemoveLastPathSegment(): "); - COMMON_LOG_VERBOSE(Common::Get_Error_Message(result)); - COMMON_LOG_VERBOSE(" No path given.\n"); + COMMON_LOG_VERBOSE("FileUtills_RemoveLastPathSegment(): "); + COMMON_LOG_VERBOSE(Common_Get_Error_Message(COMMON_ERROR_INVALID_ARGUMENT)); + COMMON_LOG_VERBOSE(" No valid path given."); } - // Copy result to commonLastErrorCode. - Common::commonLastErrorCode = result; - // Return the result. return result; } -int FileUtills::RemoveLastPathSegment(std::string & path) +int FileUtills::RemoveLastPathSegment(char ** path, size_t * pathSize) { - // Init fake currentPathPos. - size_t currentPathPos = path.size(); + // Init ret. + int ret = COMMON_ERROR_UNKNOWN_ERROR; // The result of this function. + size_t currentPathPos = 0; // A fake variable to satisfy the Real FileUtills_RemoveLastPathSegment() function. - // Check for valid path size. (No need to check for false here. If this is false, then the real function will return COMMON_ERROR_INVALID_ARGUMENT. (It does it's own check.)) - if (currentPathPos > 0) + // Check for valid pathSize. + if (((*pathSize) != NULL) && ((*pathSize) > 0)) { - // Make sure currentPathPos is less than it's size. - currentPathPos--; + // currentPathPos must be within the path. (I.e. it can't be at the NULL terminator.) + currentPathPos = ((*pathSize) - 1); + + // Call the real FileUtills_RemoveLastPathSegment() function. + ret = FileUtills::RemoveLastPathSegment(path, pathSize, ¤tPathPos)); + } + else + { + // Invalid pathSize. + ret = COMMON_ERROR_INVALID_ARGUMENT; + COMMON_LOG_VERBOSE("FileUtills_RemoveLastPathSegment(): "); + COMMON_LOG_VERBOSE(Common_Get_Error_Message(COMMON_ERROR_INVALID_ARGUMENT)); + COMMON_LOG_VERBOSE(" No valid path given."); } // Call the real RemoveLastPathSegment() function. - return (FileUtills::RemoveLastPathSegment(path, currentPathPos)); + return ret; } int FileUtills::ResolvePath_Helper(char * retStr, size_t * retStrSize) diff --git a/src/Common/Src/File_Management_Subsystem/FileUtills_Private_API.h b/src/Common/Src/File_Management_Subsystem/FileUtills_Private_API.h index 37a30b3..93ff456 100644 --- a/src/Common/Src/File_Management_Subsystem/FileUtills_Private_API.h +++ b/src/Common/Src/File_Management_Subsystem/FileUtills_Private_API.h @@ -142,7 +142,7 @@ int GetPathSegment(const std::string & path, const size_t & currentPathPos, std: int GetLastPathSegment(const std::string & path, std::string & pathSegment, const bool & blankPathSegment = true); /*! - * int FileUtills::RemoveLastPathSegment(std::string & path, size_t & currentPathPos) + * int FileUtills::RemoveLastPathSegment(char ** path, size_t * currentPathPos) * * This function removes a path segment from the given path, and updates the * given currentPathPos variable to point to the location in the string @@ -189,21 +189,26 @@ int GetLastPathSegment(const std::string & path, std::string & pathSegment, cons * This function will return the COMMON_ERROR_SUCCESS error code if it is successfull, * the results will be stored in the given arguments. * + * NOTE: This function will NOT deallocate a pre-existing pointer, but it WILL OVERWRITE IT. + * (So if you need to use or deallocate it later, make sure to copy the pointer before calling + * this function.) + * * If an error occurs, the error will be returned, and the given arguments will NOT * be altered. - * - * In any case, the returned error code will also be written to Common::commonLastErrorCode. */ -int RemoveLastPathSegment(std::string & path, size_t & currentPathPos); +int RemoveLastPathSegment(char ** path, size_t * pathSize, size_t * currentPathPos); /*! - * int FileUtills::RemoveLastPathSegment(std::string & path) + * int FileUtills::RemoveLastPathSegment(char ** path, size_t * pathSize) * - * This function acts as a wrapper to FileUtills::RemoveLastPathSegment(std::string &, size_t &) + * This function acts as a wrapper to FileUtills::RemoveLastPathSegment(char **, size_t *, size_t *) * with the assumption that the path segment you want to remove is at the end of the * string. (end of the given string is determined by the string's size.) + * + * See the function comment for FileUtills::RemoveLastPathSegment(char **, size_t *, size_t *) + * the expected behavior of this wrapper function. */ -int RemoveLastPathSegment(std::string & path); +int RemoveLastPathSegment(char ** path, size_t * pathSize); /*! * size_t FileUtills::Get_Max_Symlink_Depth() From d647d974ea9cbcb3d0e9e111f473050a5d23ca2b Mon Sep 17 00:00:00 2001 From: codebase7 Date: Sun, 24 May 2015 20:18:39 -0400 Subject: [PATCH 004/325] Compile fix for FileUtills::ResolvePath(). This commit fixes a syntax error in FileUtills::ResolvePath() when it calls FileUtills_Reallocate_CString_Buffer(). (C-string argument is a double not single pointer.) --- src/Common/Src/File_Management_Subsystem/FileUtills.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Common/Src/File_Management_Subsystem/FileUtills.cpp b/src/Common/Src/File_Management_Subsystem/FileUtills.cpp index a9b1c13..95a5a20 100644 --- a/src/Common/Src/File_Management_Subsystem/FileUtills.cpp +++ b/src/Common/Src/File_Management_Subsystem/FileUtills.cpp @@ -441,7 +441,7 @@ int FileUtills::ResolvePath(const char * path, const size_t pathSize, char * ret if (ret == COMMON_ERROR_SUCCESS) { // Reallocate the buffer to store the relative path. - ret = FileUtills_Reallocate_CString_Buffer(outputStr, outputStrSize, (outputStrSize + tempLinkBufSize)); + ret = FileUtills_Reallocate_CString_Buffer(&outputStr, outputStrSize, (outputStrSize + tempLinkBufSize)); if (ret == COMMON_ERROR_SUCCESS) { // Reset ret. From d909301c6f1a43746a8685e3a36b9df3121b5826 Mon Sep 17 00:00:00 2001 From: codebase7 Date: Sun, 24 May 2015 23:28:59 -0400 Subject: [PATCH 005/325] Fix FileUtills::ResolveSystemSymoblicLink_Syscall This commit makes the "Devil's loop" in the FileUtills::ResolveSystemSymoblicLink_Syscall() actually resolve misbehaving symbolic links that are not /proc/self/exe. (Rather than resolving /proc/self/exe which was not what was intended. Up the score for copy-pastea.) Also this commit makes FileUtills::ResolveSystemSymoblicLink_Syscall() conform to the new FileUtills API requirements. --- .../FileUtills_Private_API.h | 23 ++-- .../FileUtills_Private_API_Posix_Syscall.cpp | 120 +++++++++++------- 2 files changed, 85 insertions(+), 58 deletions(-) diff --git a/src/Common/Src/File_Management_Subsystem/FileUtills_Private_API.h b/src/Common/Src/File_Management_Subsystem/FileUtills_Private_API.h index 93ff456..2f2e3e9 100644 --- a/src/Common/Src/File_Management_Subsystem/FileUtills_Private_API.h +++ b/src/Common/Src/File_Management_Subsystem/FileUtills_Private_API.h @@ -304,7 +304,7 @@ size_t Get_Max_Symlink_Depth() int ResolvePath_Helper(char * retStr, size_t * retStrSize); /*! - * int FileUtills::ResolveSystemSymoblicLink_Syscall(const char * path, const size_t pathSize, char ** resolvedPath, size_t * resolvedPathSize) + * int FileUtills::ResolveSystemSymoblicLink_Syscall(char ** path, size_t * pathSize) * * WARNING: NEVER CALL THIS FUNCTION DIRECTLY OUTSIDE OF THE * FILEUTILLS NAMESPACE. THIS FUNCTION EXPECTS ANY AND ALL OTHER @@ -323,8 +323,10 @@ int ResolvePath_Helper(char * retStr, size_t * retStrSize); * called public FileUtills function had it's disableSymLinkResolution boolean argument set to true * explisitly.) * - * Returns COMMON_ERROR_SUCCESS if successful. (resolvedPath with have it's contents reset and the resolved - * path stored in it.) + * Returns COMMON_ERROR_SUCCESS if successful. (path with have it's contents reset and the resolved + * path stored in it. pathSize will be reset and have the correct size in it for the resolved path. + * Note: No deallocation is performed on either pointer, so if you need to keep the existing pointer + * you should copy it elsewhere before calling this function.) * * Returns COMMON_ERROR_INVALID_ARGUMENT if the given path argument is empty, or if the given path string is * not a symbolic link as defined by the host system. @@ -335,8 +337,7 @@ int ResolvePath_Helper(char * retStr, size_t * retStrSize); * may be returned by the syscall into a Common namespace * error code. * - * The result of this function is returned to the caller, (The requested path will be stored in - * given path argument.) + * In the case of ANY error, the pointer arguments will NOT be altered. * * This function is permitted to perform any nessacarry allocations or * modifications needed by the host's syscall to perform the task, however @@ -345,7 +346,7 @@ int ResolvePath_Helper(char * retStr, size_t * retStrSize); * exception created by itself or the host's syscall. (In that instance * COMMON_ERROR_EXCEPTION_THROWN must be returned, regardless of result.) */ -int ResolveSystemSymoblicLink_Syscall(const char * path, const size_t pathSize, char ** resolvedPath, size_t * resolvedPathSize); +int ResolveSystemSymoblicLink_Syscall(char ** path, size_t * pathSize); /*! * int FileUtills::GetUserProfileDirectoryPath_Syscall(std::string & path) @@ -404,7 +405,7 @@ int GetUserProfileDirectoryPath_Syscall(std::string & path); int GetCurrentWorkingDirectoryPath_Syscall(std::string & path); /*! - * int FileUtills::GetExecDirectory_Syscall(std::string & retStr) + * int FileUtills::GetExecDirectory_Syscall(char ** retStr, size_t * retStrSize) * * WARNING: NEVER CALL THIS FUNCTION DIRECTLY OUTSIDE OF THE * FILEUTILLS NAMESPACE. THIS FUNCTION EXPECTS ANY AND ALL OTHER @@ -417,9 +418,9 @@ int GetCurrentWorkingDirectoryPath_Syscall(std::string & path); * may be returned by the syscall into a Common namespace * error code. * - * The result of this function is returned to the caller, - * and the std::string argument retStr is altered with the result. - * (In case of error the std::string argument is NOT altered.) + * The result code of this function is returned to the caller, + * and the argument retStr is altered with the result. + * (In case of error the arguments are NOT altered.) * * This function is permitted to perform any nessacarry allocations or * modifications needed by the host's syscall to perform the task, however @@ -428,7 +429,7 @@ int GetCurrentWorkingDirectoryPath_Syscall(std::string & path); * exception created by itself or the host's syscall. (In that instance * COMMON_ERROR_EXCEPTION_THROWN must be returned, regardless of result.) */ -int GetExecDirectory_Syscall(std::string & retStr); +int GetExecDirectory_Syscall(char ** retStr, size_t * retStrSize); /*! * FileUtills::dirlist * FileUtills::getDirectory_Helper(const std::string & absPath, const bool & cleanList) diff --git a/src/Common/Src/File_Management_Subsystem/FileUtills_Private_API_Posix_Syscall.cpp b/src/Common/Src/File_Management_Subsystem/FileUtills_Private_API_Posix_Syscall.cpp index f8910ad..c35c7ae 100644 --- a/src/Common/Src/File_Management_Subsystem/FileUtills_Private_API_Posix_Syscall.cpp +++ b/src/Common/Src/File_Management_Subsystem/FileUtills_Private_API_Posix_Syscall.cpp @@ -22,7 +22,7 @@ #include "FileUtills_Private_API.h" #include "FileUtills_Private_API_Posix_Syscall.h" -int FileUtills::ResolveSystemSymoblicLink_Syscall(const char * path, const size_t pathSize, char ** resolvedPath, size_t * resolvedPathSize) +int FileUtills::ResolveSystemSymoblicLink_Syscall(char ** path, size_t * pathSize) { // Init vars. int ret = COMMON_ERROR_UNKNOWN_ERROR; // The result of this function. @@ -37,10 +37,10 @@ int FileUtills::ResolveSystemSymoblicLink_Syscall(const char * path, const size_ struct stat st; // POSIX Stat structure for retriving the status of the given path. (Whether or not it's a symlink and it's length.) // Make sure we got a valid path. - if (pathSize > 0) - { + if ((path != NULL) && ((*path) != NULL) && (pathSize != NULL) && ((*pathSize) > 0)) + { // Call lstat. - if (lstat(path, &st) == 0) + if (lstat((*path), &st) == 0) { // Check and see if the given path is a symbolic link. if (S_ISLNK((st.st_mode))) @@ -53,7 +53,7 @@ int FileUtills::ResolveSystemSymoblicLink_Syscall(const char * path, const size_ if (readLinkBuf != NULL) { // Call readlink. - firstBufferLength = readlink(path, readLinkBuf, st.st_size); + firstBufferLength = readlink((*path), readLinkBuf, st.st_size); // Check and see if the result from readlink is not -1 and if it equals st.st_size. if (firstBufferLength != -1) @@ -63,8 +63,8 @@ int FileUtills::ResolveSystemSymoblicLink_Syscall(const char * path, const size_ // Insert a NULL character after the end of the string. readLinkBuf[st.st_size] = '\0'; - // Copy the result to the resolvedPath buffer. - resolvedPath = readLinkBuf; + // Copy the result to the path buffer. + (*path) = readLinkBuf; // Set success. ret = COMMON_ERROR_SUCCESS; @@ -108,7 +108,8 @@ int FileUtills::ResolveSystemSymoblicLink_Syscall(const char * path, const size_ * (Copied from the original FileUtills::GetExecDirectory_Syscall() implemetation for POSIX.) * * We do this to avoid a runaway reallocation loop which could be considered a resource starvation - * issue. (See below for the original rant....) + * issue. (See below for the original rant, just ignore the /proc file system issues for symlinks + * in general. (Only issues 1 and 3 apply to ALL symlinks.)) * * (Begin original rant.) * @@ -120,7 +121,7 @@ int FileUtills::ResolveSystemSymoblicLink_Syscall(const char * path, const size_ * path in linux, is by using readlink() on /proc/self/exe. * * However, this has several issues. - * + * * First issue: readlink() expects a preallocated buffer to store the result. * If the preallocated buffer is too small for the full path, then readlink() * will silently truncate the remaining data and not tell us how much was @@ -139,15 +140,18 @@ int FileUtills::ResolveSystemSymoblicLink_Syscall(const char * path, const size_ * loop of memory allocation->readlink()->if(!got entire link)->Deallocate memory->Allocate memory. * for reading a symlink from the filesystem. * - * This loop is reimplimented here, but with two differences. + * This loop is reimplimented here, but with three differences. * * - The loop will end once a certian amount of reallocations (defined by MAX_GET_EXE_PATH_REALLOC) * is reached. (This is to prevent some of the above issues.) * * - The loop will also check to make sure that the returned string has not been altered. * (via memcmp). (Attempt to prevent a compromised system from mallissously changing the - * symlink's destionation as a result of our multiple accesses to /proc/self/path.) + * symlink's destionation as a result of our multiple accesses to the link itself.) * + * - The loop will reallocate the buffer after the link is fully read so that ONLY the + * needed memory to store it is allocated for it. (Prevent unnessacarry memory usage.) + * * (End of original rant.) */ // Begin the devil's loop. @@ -170,7 +174,7 @@ int FileUtills::ResolveSystemSymoblicLink_Syscall(const char * path, const size_ memset(checkBuffer, '\0', realBufferLength); // Call readlink() for the first buffer. - firstBufferLength = readlink(PROC_PATH, readLinkBuf, realBufferLength); + firstBufferLength = readlink((*path), readLinkBuf, realBufferLength); // Check bufferLength. if (firstBufferLength >= 0) @@ -179,7 +183,7 @@ int FileUtills::ResolveSystemSymoblicLink_Syscall(const char * path, const size_ if (firstBufferLength < realBufferLength) { // Call readlink() for the second buffer. - secondBufferLength = readlink(PROC_PATH, checkBuffer, realBufferLength); + secondBufferLength = readlink((*path), checkBuffer, realBufferLength); // Check secondBufferLength. if (secondBufferLength >= 0) @@ -193,29 +197,39 @@ int FileUtills::ResolveSystemSymoblicLink_Syscall(const char * path, const size_ // Paths match, deallocate the second buffer. if (checkBuffer != NULL) { + memset(checkBuffer, '\0', realBufferLength); free(checkBuffer); checkBuffer = NULL; } - // Copy the first buffer to the resolvedPath buffer. - resolvedPath = readLinkBuf; - - // Because the returned link is the actual executable, call GetParent(). - resolvedPath = FileUtills::GetParent(resolvedPath); - if (resolvedPath.size() > 0) + // Reallocate the buffer. (Free unneeded memory.) + ret = FileUtills_Reallocate_CString_Buffer(readLinkBuf, realBufferLength, firstBufferLength); + if (ret == COMMON_ERROR_SUCCESS) { - // Clear Common::commonLastErrorCode. - ret = COMMON_ERROR_SUCCESS; + // Copy the first buffer pointer to the path buffer pointer. + (*path) = readLinkBuf; } else { - // GetParent() failed. - ret = COMMON_ERROR_INTERNAL_ERROR; - COMMON_LOG_DEBUG("FileUtills_ResolveSystemSymoblicLink(): "); - COMMON_LOG_DEBUG(Common_Get_Error_Message(COMMON_ERROR_INTERNAL_ERROR)); - COMMON_LOG_DEBUG(" Call to FileUtills_GetParent() failed."); + // Could not free the unneeded memory. + COMMON_LOG_DEBUG("FileUtills_ResolveSystemSymoblicLink(): Call to FileUtills_Reallocate_CString_Buffer() failed: "); + COMMON_LOG_DEBUG(Common_Get_Error_Message(ret)); } } + else + { + // Something is screwing with us...abort. + ret = COMMON_ERROR_INTERNAL_ERROR; + COMMON_LOG_DEBUG("FileUtills_ResolveSystemSymoblicLink(): "); + COMMON_LOG_DEBUG(Common_Get_Error_Message(COMMON_ERROR_INTERNAL_ERROR)); + } + } + else + { + // Something is screwing with us...abort. + ret = COMMON_ERROR_INTERNAL_ERROR; + COMMON_LOG_DEBUG("FileUtills_ResolveSystemSymoblicLink(): "); + COMMON_LOG_DEBUG(Common_Get_Error_Message(COMMON_ERROR_INTERNAL_ERROR)); } } else @@ -227,6 +241,22 @@ int FileUtills::ResolveSystemSymoblicLink_Syscall(const char * path, const size_ COMMON_LOG_DEBUG(Common_Get_Error_Message(ret)); } } + else + { + // We did not get the entire link, so we need to deallocate it for the next loop. + if (readLinkBuf != NULL) + { + memset(readLinkBuf, '\0', realBufferLength); + free(readLinkBuf); + readLinkBuf = NULL; + } + if (checkBuffer != NULL) + { + memset(checkBuffer, '\0', realBufferLength); + free(checkBuffer); + checkBuffer = NULL; + } + } } else { @@ -258,6 +288,23 @@ int FileUtills::ResolveSystemSymoblicLink_Syscall(const char * path, const size_ COMMON_LOG_INFO(Common_Get_Error_Message(COMMON_ERROR_INTERNAL_ERROR)); COMMON_LOG_INFO(" Unable to resolve the symbolic link due to engine limitation. (Length of the resolved path is too long.)"); } + + // If unsuccessful, make sure both buffers are deallocated. + if (ret != COMMON_ERROR_SUCCESS) + { + if (readLinkBuf != NULL) + { + memset(readLinkBuf, '\0', realBufferLength); + free(readLinkBuf); + readLinkBuf = NULL; + } + if (checkBuffer != NULL) + { + memset(checkBuffer, '\0', realBufferLength); + free(checkBuffer); + checkBuffer = NULL; + } + } } } else @@ -295,27 +342,6 @@ int FileUtills::ResolveSystemSymoblicLink_Syscall(const char * path, const size_ COMMON_LOG_DEBUG(" Given path argument is invalid."); } - // Deallocate the used memory if needed. - if (readLinkBuf != NULL) - { - // Deallocate the memory. - free(readLinkBuf); - readLinkBuf = NULL; - } - if (checkBuffer != NULL) - { - // Deallocate the memory. - free(checkBuffer); - checkBuffer = NULL; - } - - // Reset resolvedPath if needed. - if (ret != COMMON_ERROR_SUCCESS) - { - // Reset resolvedPath. - resolvedPath.clear(); - } - // Return the result. return ret; } From 5d66a26c165f1462afe725f1b2ba902aec131db3 Mon Sep 17 00:00:00 2001 From: codebase7 Date: Sat, 30 May 2015 02:09:23 -0400 Subject: [PATCH 006/325] Fix FileUtills::GetExecDirectory_Syscall() Rewrites FileUtills::GetExecDirectory_Syscall() to be more C like. (API changes due to rewrite.) --- .../FileUtills_Private_API_Posix_Syscall.cpp | 61 +++++++++++++------ 1 file changed, 41 insertions(+), 20 deletions(-) diff --git a/src/Common/Src/File_Management_Subsystem/FileUtills_Private_API_Posix_Syscall.cpp b/src/Common/Src/File_Management_Subsystem/FileUtills_Private_API_Posix_Syscall.cpp index c35c7ae..a302e94 100644 --- a/src/Common/Src/File_Management_Subsystem/FileUtills_Private_API_Posix_Syscall.cpp +++ b/src/Common/Src/File_Management_Subsystem/FileUtills_Private_API_Posix_Syscall.cpp @@ -503,38 +503,59 @@ int FileUtills::GetCurrentWorkingDirectoryPath_Syscall(std::string & path) return ret; } -int FileUtills::GetExecDirectory_Syscall(std::string & retStr) +int FileUtills::GetExecDirectory_Syscall(char ** retStr, size_t * retStrSize) { // Init vars. int ret = COMMON_ERROR_UNKNOWN_ERROR; // The result code returned from this function. - std::string result = ""; // The string returned from this function. -#ifdef __linux__ + char * result = NULL; // The string returned from this function. + size_t resultSize = 0; // The size of the result string. - // Call FileUtills::ResolveSystemSymoblicLink_Syscall(). (Make sure it's the real path not a symlink. (PROC_PATH is a symlink, and a weird one at that.)) - ret = FileUtills::ResolveSystemSymoblicLink_Syscall(PROC_PATH, result); - if (ret == COMMON_ERROR_SUCCESS) - { - // Copy the result string to retStr. - retStr = result; - } - else + // Check for valid arguments. + if ((retStr != NULL) && (retStrSize != NULL)) { - // Check for an invalid argument error. - if (ret == COMMON_ERROR_INVALID_ARGUMENT) +#ifdef __linux__ + // Copy the pointer. + result = PROC_PATH; + resultSize = PROC_PATH_SIZE; + + // Call FileUtills::ResolveSystemSymoblicLink_Syscall(). (Make sure it's the real path not a symlink. (PROC_PATH is a symlink, and a weird one at that.)) + ret = FileUtills::ResolveSystemSymoblicLink_Syscall(&result, &resultSize); + if (ret == COMMON_ERROR_SUCCESS) + { + // The resulting path is actually the exe itself, so we need to call RemoveLastPathSegment(). + ret = FileUtills::RemoveLastPathSegment(&result, &resultSize); + if (ret == COMMON_ERROR_SUCCESS) + { + // Copy the result string to retStr. + (*retStr) = result; + (*retStrSize) = resultSize; + } + else + { + // Could not remove exe from path. + COMMON_LOG_DEBUG("FileUtills_GetExecDirectory_Syscall(): Could not remove exe from it's path, call to FileUtills_RemoveLastPathSegment() failed: "); + COMMON_LOG_DEBUG(Common_Get_Error_Message(ret)); + } + } + else { // This is an internal engine error. ret = COMMON_ERROR_INTERNAL_ERROR; // Report it. - COMMON_LOG_WARNING("FileUtills::GetExecDirectory(): "); - COMMON_LOG_WARNING(Common::Get_Error_Message(COMMON_ERROR_INTERNAL_ERROR)); - COMMON_LOG_WARNING(" Getting the executable path failed. (Call to an internal engine function failed.) Please report this bug.\n"); + COMMON_LOG_WARNING("FileUtills_GetExecDirectory(): "); + COMMON_LOG_WARNING(Common_Get_Error_Message(COMMON_ERROR_INTERNAL_ERROR)); + COMMON_LOG_WARNING(" Getting the executable path failed. (Call to an internal engine function failed.) Please report this bug."); } - } - #endif - // Clear the result string. - result.clear(); + } + else + { + // Invalid arguments. + ret = COMMON_ERROR_INVALID_ARGUMENT; + COMMON_LOG_DEBUG("FileUtills_GetExecDirectory(): "); + COMMON_LOG_DEBUG(Common_Get_Error_Message(COMMON_ERROR_INVALID_ARGUMENT)); + } // Return result. return ret; From 44863bed1cb4384d18050992a626ad3610f6f140 Mon Sep 17 00:00:00 2001 From: codebase7 Date: Sat, 30 May 2015 02:10:55 -0400 Subject: [PATCH 007/325] More API call changes for FileUtills. This commit "fixes" FileUtills::GetExecDirectory() to be more C like. (API call changes due to rewrite.) This commit adds FileUtills_Copy_CString(). --- .../File_Management_Subsystem/FileUtills.cpp | 112 ++++++++++++++---- 1 file changed, 91 insertions(+), 21 deletions(-) diff --git a/src/Common/Src/File_Management_Subsystem/FileUtills.cpp b/src/Common/Src/File_Management_Subsystem/FileUtills.cpp index 95a5a20..d8669cb 100644 --- a/src/Common/Src/File_Management_Subsystem/FileUtills.cpp +++ b/src/Common/Src/File_Management_Subsystem/FileUtills.cpp @@ -210,43 +210,113 @@ int FileUtills::GetCurrentWorkingDirectoryPath(std::string & path) return ret; } -int FileUtills::GetExecDirectory(std::string & retStr) +int FileUtills::GetExecDirectory(char ** retStr, size_t * retStrSize) { // Init vars. int ret = COMMON_ERROR_UNKNOWN_ERROR; // The result code of this function. - std::string result = ""; // The result string from GetExecDirectory_Syscall(). + size_t resultSize = 0; // The size of the result string. + char * result = NULL; // The result string from GetExecDirectory_Syscall(). - // Call the syscall. - ret = FileUtills::GetExecDirectory_Syscall(result); - if (ret == COMMON_ERROR_SUCCESS) + // Check for valid arguments. + if ((retStr != NULL) && (retStrSize != NULL)) { - // Copy result to retStr. - retStr = result; + // Call the syscall. + ret = FileUtills::GetExecDirectory_Syscall(&result, &resultSize); + + // Check the error code. + switch(ret) + { + // VALID ERROR CODES. + COMMON_ERROR_SUCCESS: + COMMON_ERROR_INVALID_ARGUMENT: + COMMON_ERROR_MEMORY_ERROR: + break; + default: // INVALID ERROR CODE. + ret = COMMON_ERROR_UNKNOWN_ERROR; + COMMON_LOG_DEBUG("FileUtills_GetExecDirectory(): Called Syscall Function returned an invalid Common error code, and should be rewritten to return VALID Common error codes."); + break; + }; + + // If we were successful, copy the pointers. + if (ret == COMMON_ERROR_SUCCESS) + { + (*retStr) = result; + (*retStrSize) = resultSize; + } + else + { + // Log the error. + COMMON_LOG_DEBUG("FileUtills_GetExecDirectory(): "); + COMMON_LOG_DEBUG(Common_Get_Error_Message(ret)); + } } else { - // Check for a INVALID_ARGUMENT. - if (ret == COMMON_ERROR_INVALID_ARGUMENT) + // Invalid argument error. + ret = COMMON_ERROR_INVALID_ARGUMENT; + COMMON_LOG_DEBUG("FileUtills_GetExecDirectory(): "); + COMMON_LOG_DEBUG(Common_Get_Error_Message(COMMON_ERROR_INVALID_ARGUMENT)); + COMMON_LOG_DEBUG(" Invalid string or string size given."); + } + + // Return ret. + return ret; +} + +/*! + * int FileUtills_Copy_CString(const char * src, const size_t srcSize, char ** dest) + * + * Allocates a new c-string and copies the given source string to it. + * The copied c-string is identical to the source, and is allocated + * with the same size. + * + * Returns COMMON_ERROR_SUCCESS if successful. (The dest pointer will point + * to the copied c-string in this case.) + * + * Otherwise returns the appropriate error. (The dest pointer will NOT be + * altered in this case.) + */ +int FileUtills_Copy_CString(const char * src, const size_t srcSize, char ** dest) +{ + // Init vars. + int ret = COMMON_ERROR_UNKNOWN_ERROR; // The result of this function. + char * tempBuf = NULL; // Temporary variable to copy the src with. + + // Check for valid arguments. + if ((src != NULL) && (srcSize > 0) && (dest != NULL)) + { + // Allocate tempBuf. + tempBuf = (char*)malloc(srcSize); + if (tempBuf != NULL) { - // This is an internal error. - ret = COMMON_ERROR_INTERNAL_ERROR; + // Copy the string. + for (size_t x = 0; (x < srcSize); x++) + { + tempBuf[x] = src[x]; + } - // Log this error. - COMMON_LOG_WARNING("FileUtills::GetExecDirectory(): Syscall returned an invalid argument error. Please report this bug.\n"); + // Set the dest pointer. + (*dest) = tempBuf; + + // Done. + ret = COMMON_ERROR_SUCCESS; } else { - // Log the error. - COMMON_LOG_DEBUG("FileUtills::GetExecDirectory(): "); - COMMON_LOG_DEBUG(Common::Get_Error_Message(ret)); - COMMON_LOG_DEBUG("\n"); + // Could not allocate memory. + ret = COMMON_ERROR_MEMORY_ERROR; } } + else + { + // Invalid argument error. + ret = COMMON_ERROR_INVALID_ARGUMENT; + COMMON_LOG_DEBUG("FileUtills_Copy_CString(): "); + COMMON_LOG_DEBUG(Common_Get_Error_Message(COMMON_ERROR_INVALID_ARGUMENT)); + COMMON_LOG_DEBUG(" Invalid string, string size, or destionation pointer given."); + } - // Blank result. - result.clear(); - - // Return ret. + // Return the result. return ret; } From 7873f01c9c7af9a26a058c54f583b0d88f6a661a Mon Sep 17 00:00:00 2001 From: codebase7 Date: Tue, 2 Jun 2015 23:37:27 -0400 Subject: [PATCH 008/325] Fix two FileUtills functions. Fixes RemoveTrailingSlash (renamed to FileUtills_RemoveTrailingSlash), and CheckPathType (renamed to FileUtills_CheckPathType) for the new API changes. --- .../File_Management_Subsystem/FileUtills.cpp | 211 +++++++++++------- 1 file changed, 133 insertions(+), 78 deletions(-) diff --git a/src/Common/Src/File_Management_Subsystem/FileUtills.cpp b/src/Common/Src/File_Management_Subsystem/FileUtills.cpp index d8669cb..291d71d 100644 --- a/src/Common/Src/File_Management_Subsystem/FileUtills.cpp +++ b/src/Common/Src/File_Management_Subsystem/FileUtills.cpp @@ -23,103 +23,158 @@ #include "FileUtills_Private_API.h" /*! - std::string RemoveTrailingSlash(const std::string & path) - - Removes a DIR_SEP on the end of the given path string (if it exists) - Will not do anything and return the original string if there is only 1 charater in the given path string. - Will also return the original string if a memory error occurs. -*/ -std::string RemoveTrailingSlash(const std::string & path) + * int FileUtills_RemoveTrailingSlash(char ** retStr, size_t * retStrSize) + * + * Removes a DIR_SEP (Either a '\\' or '/' character) on the end of the given NULL terminated path string. + * + * WARNING: This function will DEALLOCATE the original string if it finds a character to remove. As such, + * if this call returns COMMON_ERROR_SUCCESS, any pointer to the original string will be INVALID. The + * result of attempting to dereference such a pointer is undefined. + * + * Returns COMMON_ERROR_SUCCESS if the removal was successful, or if there was not a character to remove. + * (The character at the end of the string was NOT a '\\' or '/' character.) + * + * Returns COMMON_ERROR_INVALID_ARGUMENT if the given pointers are NULL, or if the given size is less + * than 3. + * + * Returns COMMON_ERROR_MEMORY_ERROR if a memory allocation attempt fails. + * + * Otherwise returns the appropriate error code. + * + * In case of error, (the return code is NOT COMMON_ERROR_SUCCESS), this function will NOT alter any given + * arguments. + */ +int FileUtills_RemoveTrailingSlash(char ** retStr, size_t * retStrSize) { - // Init vars. - size_t size = 0; - std::string buffer = ""; + /* Init vars. */ + int ret = COMMON_ERROR_UNKNOWN_ERROR; /* The result code for this function. */ + char * tempBuffer = NULL; /* Temporary buffer to alter the string with. */ - // Get size of the Directory string. - size = path.size(); + /* Check for invalid arguments. */ + if ((retStr != NULL) && ((*retStr) != NULL) && (retStrSize != NULL) && ((*retStrSize) > 2)) + { + /* Check and see if the last character in the string is either '/' or '\\'. */ + /* String should be NULL terminated. */ + if (((*retStr)[((*retStrSize) - 2)] == '\\') || ((*retStr)[((*retStrSize) - 2)] == '/')) + { + /* OK, allocate a new string. */ + tempBuffer = (char*)malloc(((*retStrSize) - 1)); + if (tempBuffer != NULL) + { + /* NULL out the buffer. */ + memset(tempBuffer, '\0', ((*retStrSize) - 1)); - // Check the length of the string see if it is only 1 charater. - if (size <= 1) - { - // We can't remove anything, if we do the return would be empty. - return path; - } + /* Copy the data. */ + memcpy(tempBuffer, retStr, ((*retStrSize) - 2)); - // Copy the directory string to buffer - buffer = path; + /* Deallocate the original string. */ + free((*retStr)); - // Check and see if a directory seperator is on the end of the string. - if ((path.find_last_of(DIR_SEP)) == (size - 1)) - { - // Remove the trailing Directory seperator so we don't screw up the next check. - // Note: substr CAN throw an exception so we must put it in a try catch block. - try{ - buffer = path.substr(0, (size - 1)); + /* Copy the new pointer. */ + (*retStr) = tempBuffer; + + /* Copy the new size. */ + (*retStrSize) = ((*retStrSize) - 1); + + /* Done! */ + ret = COMMON_ERROR_SUCCESS; + } + else + { + /* Could not allocate memory for new string. */ + ret = COMMON_ERROR_MEMORY_ERROR; + } + } + else + { + /* There is no DIR_SEP character ('\\' or '/') to remove. */ + ret = COMMON_ERROR_SUCCESS; + } } - catch(exception ex) + else { - // We can't return an error so we will silently fail. - return path; + /* We can't remove anything, if we do the return would be empty. */ + ret = COMMON_ERROR_INVALID_ARGUMENT; } - } - // Return new path. - return buffer; + /* Exit function. */ + return ret; } -int CheckPathType(const std::string & path, bool & bIsDosStylePath) +/*! + * int FileUtills_CheckPathType(const char * path, const size_t pathSize, bool * bIsDosStylePath) + * + * Checks the given path to see if it matches the DOS / Windows path format. + * (I.e. :\ OR \). + * The assumption being that if a '/' is found then it's a POSIX style path. + * + * Returns COMMON_ERROR_SUCCESS if the check was performed. + * (Result will be stored in the given bIsDosStylePath argument.) + * + * Returns COMMON_ERROR_INVALID_ARGUMENT if the given pointers are NULL, or the + * given path size is less than 1. + * + * Otherwise returns the appropriate error code. + * + * In case of error, (the return code is NOT COMMON_ERROR_SUCCESS), this function will NOT + * alter any given arguments. + * + * Under NO circumstance is the given path or pathSize argument altered in any way. + */ +int FileUtills_CheckPathType(const char * path, const size_t pathSize, bool * bIsDosStylePath) { - // Init vars. - short ret = COMMON_ERROR_INTERNAL_ERROR; // Result of this function. + /* Init vars. */ + short ret = COMMON_ERROR_INTERNAL_ERROR; /* Result of this function. */ + size_t x = 0; /* Counter used in check loop. */ - // Check for valid path string. - if (path.size() > 0) - { - // Check for a DOS style absolute path reference. - if ((path.size() > 3) && (path[1] == ':') && (path[2] == '\\')) + /* Check for valid arguments. */ + if ((path != NULL) && (pathSize > 0) && (bIsDosStylePath != NULL)) { - // This is DOS style absolute path. - bIsDosStylePath = true; + /* Check for a DOS style absolute path reference. */ + if ((pathSize > 3) && (path[1] == ':') && (path[2] == '\\')) + { + /* This is DOS style absolute path. */ + (*bIsDosStylePath) = true; + } + else + { + /* Set bIsDosStylePath. */ + (*bIsDosStylePath) = true; + + /* + * We are assuming that if a '/' character is found + * in the path, it is a POSIX style path. + * + * (Probably a dangerous assumption, but there is not + * much of a way to determine the path type short of + * determining the OS in use. (And even then it's a + * problem if the target is different than the host.)) + * + * Hopefully the target OS will complain if it gets an + * invalid path...... + */ + for (x = 0; ((x < pathSize) && ((*bIsDosStylePath) == true)); x++) + { + /* Check for a '/' character. */ + if (path[x] == '/') + { + /* OK this is a reserved character on windows, so assume the path is a POSIX style path. */ + (*bIsDosStylePath) = false; + } + } + } + + /* Done. */ + ret = COMMON_ERROR_SUCCESS; } else { - // Set bIsDosStylePath. - bIsDosStylePath = true; - - /* - * We are assuming that if a '/' character is found - * in the path, it is a POSIX style path. - * - * (Probably a dangerous assumption, but there is not - * much of a way to determine the path type short of - * determining the OS in use. (And even then it's a - * problem if the target is different than the host.)) - * - * Hopefully the target OS will complain if it gets an - * invalid path...... - */ - for (size_t x = 0; ((x < path.size()) && (bIsDosStylePath)); x++) - { - // Check for a '/' character. - if (path[x] == '/') - { - // OK this is a reserved character on windows, so assume the path is a POSIX style path. - bIsDosStylePath = false; - } - } + /* Invalid path. */ + ret = COMMON_ERROR_INVALID_ARGUMENT; } - // Done. - ret = COMMON_ERROR_SUCCESS; - } - else - { - // Invalid path. - ret = COMMON_ERROR_INVALID_ARGUMENT; - } - - // Return the result. - return ret; + /* Return the result. */ + return ret; } int FileUtills::GetUserProfileDirectoryPath(std::string & path) From 38d7861225306e473bfcb22cd1759db8e1b2603e Mon Sep 17 00:00:00 2001 From: codebase7 Date: Tue, 9 Jun 2015 11:26:16 -0400 Subject: [PATCH 009/325] Add FileUtills_Write_Data_To_File_From_Memory() This commit adds the FileUtills_Write_Data_To_File_From_Memory() function to FileUtills. --- .../File_Management_Subsystem/FileUtills.cpp | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/src/Common/Src/File_Management_Subsystem/FileUtills.cpp b/src/Common/Src/File_Management_Subsystem/FileUtills.cpp index 291d71d..27ccf76 100644 --- a/src/Common/Src/File_Management_Subsystem/FileUtills.cpp +++ b/src/Common/Src/File_Management_Subsystem/FileUtills.cpp @@ -177,6 +177,55 @@ int FileUtills_CheckPathType(const char * path, const size_t pathSize, bool * bI return ret; } +int FileUtills_Write_Data_To_File_From_Memory(FILE * OUT, const char * data, const size_t dataLength) +{ + /* Init vars. */ + int ret = COMMON_ERROR_UNKNOWN_ERROR; /* The result of this function. */ + int retFromC = 0; /* The result of C calls. */ + size_t x = 0; /* Counter used in output loop. */ + + /* Check for invalid arguments. */ + if ((OUT != NULL) && (ferror(OUT) == 0) && (data != NULL) && (dataLength > 0)) + { + /* Begin output loop. */ + for (x = 0; ((x < dataLength) && (retFromC == 0) && (ferror(OUT) == 0)); x++) + { + /* Write out the data. */ + retFromC = fputc(data[x], OUT); + } + + /* Check for good file stream. */ + if ((retFromC == 0) && (ferror(OUT) == 0)) + { + /* Flush the buffer. */ + retFromC = fflush(OUT); + if ((retFromC == 0) && (ferror(OUT) == 0)) + { + /* Done! */ + ret = COMMON_ERROR_SUCCESS; + } + else + { + /* Bad file stream. */ + ret = COMMON_ERROR_IO_ERROR; + } + } + else + { + /* Bad file stream. */ + ret = COMMON_ERROR_IO_ERROR; + } + } + else + { + /* Invalid arguments. */ + ret = COMMON_ERROR_INVALID_ARGUMENT; + } + + /* Exit function. */ + return ret; +} + int FileUtills::GetUserProfileDirectoryPath(std::string & path) { // Init vars. From f1026ad5ec748d9e3984981f23f09c6877d200c7 Mon Sep 17 00:00:00 2001 From: codebase7 Date: Tue, 9 Jun 2015 11:27:23 -0400 Subject: [PATCH 010/325] Update main FileUtills header. This commit updates the main FileUtills header (FileUtills.h) to be consistant with the new API changes. --- .../File_Management_Subsystem/FileUtills.h | 284 +++++++++--------- 1 file changed, 143 insertions(+), 141 deletions(-) diff --git a/src/Common/Src/File_Management_Subsystem/FileUtills.h b/src/Common/Src/File_Management_Subsystem/FileUtills.h index 8903ec7..4ef8254 100644 --- a/src/Common/Src/File_Management_Subsystem/FileUtills.h +++ b/src/Common/Src/File_Management_Subsystem/FileUtills.h @@ -73,47 +73,64 @@ struct dirlist{ }; /*! - * int FileUtills::GetUserProfileDirectoryPath(std::string & path) + * int FileUtills_Write_Data_To_File_From_Memory(FILE * OUT, const char * data, const size_t dataLength) * - * Fetches the user's profile directory from the enviorment, and stores - * it in the given path argument. (Note: The given path argument will be - * erased when this function is called. So take care not to leave something - * in it you need.) + * Writes out the given data in memory to the given output file. * - * If the function fails for any reason, path will be an empty string, - * the returned error code and Common::commonLastErrorCode will be set - * to the approiate error. + * NOTE: This function expects that the given output file is already open and not errored out when called. + * The output file will remain open after the function returns. (It will still be usable if the returned error code is SUCCESS.) + * + * The output position of the file will NOT be restored in ANY instance after this function returns. + * If you need the current position for something, copy it elsewhere before calling this function. + * + * Returns COMMON_ERROR_SUCCESS if the data is written to the output file successfully. + * + * Returns COMMON_ERROR_INVALID_ARGUMENT if the given output file pointer is NULL, + * the given output file has errored out prior to the function call, + * data is NULL, or dataLength is less than 1. + * + * Returns COMMON_ERROR_IO_ERROR on all f*() errors. + * + * Otherwise returns the appropriate error code. + */ +int FileUtills_Write_Data_To_File_From_Memory(FILE * OUT, const char * data, const size_t dataLength); + +/*! + * int FileUtills::GetUserProfileDirectoryPath(char ** retStr, size_t * retStrSize) + * + * Fetches the user's profile directory from the environment, and stores + * it in the given path argument. + * + * If the function fails for any reason, the arguments will NOT be altered, + * and the appropriate error will be returned to the caller. */ -int GetUserProfileDirectoryPath(std::string & path); +int GetUserProfileDirectoryPath(char ** retStr, size_t * retStrSize); /*! - * int FileUtills::GetCurrentWorkingDirectoryPath(std::string & path) + * int FileUtills::GetCurrentWorkingDirectoryPath(char ** path, size_t * pathSize) * - * Fetches the current working directory from the enviorment, and stores - * it in the given path argument. (Note: The given path argument will be - * erased when this function is called. So take care not to leave something - * in it you need.) + * Fetches the current working directory from the environment, and stores + * it in the given retStr argument. * - * If the function fails for any reason, path will be an empty string, - * the returned error code and Common::commonLastErrorCode will be set - * to the approiate error. + * If the function fails for any reason, the arguments will NOT be altered, + * and the appropriate error will be returned to the caller. */ -int GetCurrentWorkingDirectoryPath(std::string & path); +int GetCurrentWorkingDirectoryPath(char ** retStr, size_t * retStrSize); /*! - * int FileUtills::GetExecDirectory(std::string & retStr) + * int FileUtills::GetExecDirectory(char ** path, size_t * pathSize) * * Replaces the contents of the given retStr argument with a NULL - * terminated std::string that contains the path to the directory where the + * terminated C-String that contains the path to the directory where the * executable is stored. * - * If the function fails for any reason, the retStr argument will NOT be altered, + * If the function fails for any reason, the arguments will NOT be altered, * and the appropriate error will be returned to the caller. */ -int GetExecDirectory(std::string & retStr); +int GetExecDirectory(char ** retStr, size_t * retStrSize); /*! - int getDirectory(const std::string & path, FileUtills::dirlist ** dirTree, const bool & cleanList) + int getDirectory(const char * path, const size_t pathSize, FileUtills::dirlist ** dirTree, const bool & cleanList) Lists the given directory's contents. @@ -123,7 +140,7 @@ int GetExecDirectory(std::string & retStr); FileUtills::dirlist structure that will contain the resulting directory listing if successful. If the structure is already allocated when passed to this function and this function succeeds, - the pre-existing structure will be deallocated. + the pre-existing structure will be deallocated. Pram: cleanList, If this is true then, the generated list will be sorted (via decrementing sort), and the list will have the entries for the current @@ -138,64 +155,60 @@ int GetExecDirectory(std::string & retStr); set cleanList to true when calling this function. Returns COMMON_ERROR_SUCCESS if successfull, dirTree's pointer will point to a valid - FileUtills::dirlist structure with the given path's contents in this case. - (Any previous structure pointed to by the dirTree pointer will be deallocated.) + FileUtills::dirlist structure with the given path's contents in this case. + (Any previous structure pointed to by the dirTree pointer will be deallocated.) Otherwise this function will return the appropriate error, and dirTree's pointer will not be modified. */ -int getDirectory(const std::string & path, dirlist ** dirTree, const bool & cleanList = false); +int getDirectory(const char * path, const size_t pathSize, dirlist ** dirTree, const bool cleanList); /*! - int FileUtills::DoesExist(const std::string & path) + int FileUtills::DoesExist(const char * path, const size_t pathSize) - Prams: @std::string path, path to check for existance on the filesystem. + Prams: @std::string path, path to check for existence on the filesystem. This function checks to see if given file or directory exists. - This function is called by FileUtills::CheckPermissions() before runing permission checks. - - The returned error code is always copied to Common::commonLastErrorCode. + This function is called by FileUtills::CheckPermissions() before running permission checks. Returns FILEUTILLS_ERROR_EXISTANT if file or directory exists on the system. Returns FILEUTILLS_ERROR_NON_EXISTANT if file or directory does not exist on the system. Returns COMMON_ERROR_INVALID_ARGUMENT if the given path is empty. Returns COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED if the given system is unsupported. - Returns the approiate error in all other instances. + Returns the appropriate error in all other instances. */ -int DoesExist(const std::string & path); +int DoesExist(const char * path, const size_t pathSize); /*! - FileUtills::IsFileOrDirectory(const std::string & path) + FileUtills::IsFileOrDirectory(const char * path, const size_t pathSize) Checks to see if a given path is a file or directory. - The returned error code is always copied to Common::commonLastErrorCode. - Returns COMMON_ERROR_SUCCESS if the path exists but it is not a file or directory. Returns FILEUTILLS_ERROR_PATH_IS_A_FILE if the path is a file. Returns FILEUTILLS_ERROR_PATH_IS_A_DIRECTORY if the path is a directory. Returns COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED if the given system is unsupported. Returns COMMON_ERROR_ACCESS_DENIED if a permissions error occurs. Returns COMMON_ERROR_INVALID_ARGUMENT if the given path is empty. - Returns FILEUTILLS_ERROR_NON_EXISTANT if a path componet does not exist. + Returns FILEUTILLS_ERROR_NON_EXISTANT if a path component does not exist. Returns FILEUTILLS_ERROR_ if the path has a file in it and is not at the end. (I.e you are treating a file as a directory.) - Returns the approiate error in all other instances. + Returns the appropriate error in all other instances. */ -int IsFileOrDirectory(const std::string & path); +int IsFileOrDirectory(const char * path, const size_t pathSize); /*! - int FileUtills::CheckParent(const std::string & path, const bool & read, const bool & write, const bool & exec) + int FileUtills::CheckParent(const char * path, const size_t pathSize, const bool read, const bool write, const bool exec) Acts as a wrapper to DoesExist and CheckPermissions - Checks for the parent directory's existance in the path given. + Checks for the parent directory's existence in the path given. Also Checks to see if it is accessible. By default it checks for Read and Write access. - (Optionaly it can check for execute permissions, and any combonation of the three. This + (Optionally it can check for execute permissions, and any combination of the three. This function will return a COMMON_ERROR_INVALID_ARGUMENT error however if all of the permissions to check are false.) Ex. If this path is given: "/home/user/Homework.txt", this function will check and see if the "/home/user" parent - directory exists, and if it is accessable. + directory exists, and if it is accessible. The returned error code is always copied to Common::commonLastErrorCode. @@ -207,25 +220,27 @@ int IsFileOrDirectory(const std::string & path); Returns COMMON_ERROR_INTERNAL_ERROR if an engine error occurs. Returns COMMON_ERROR_UNKNOWN_ERROR if an unknown error occurs. Returns COMMON_ERROR_EXCEPTION_THROWN if an exception is thrown. - Returns the approiate error in all other cases. + Returns the appropriate error in all other cases. */ -int CheckParent(const std::string & path, const bool & read = true, const bool & write = true, const bool & exec = false); +int CheckParent(const char * path, const size_t pathSize, const bool read, const bool write, const bool exec); /*! - std::string FileUtills::GetParent(const std::string & path) + int FileUtills::GetParent(char ** retStr, size_t * retStrSize) Returns the parent directory for the given file. Gets the path exactly like FileUtills::CheckParent(). - Returns std::string with parent directory path if successful. - Returns an empty string otherwise, and sets - Common::commonLastErrorCode to the approiate error code. + Returns COMMON_ERROR_SUCCESS with parent directory path set in retStr if successful. + (retStr's size will be set in retStrSize.) + + Returns the appropriate error code otherwise. + (retStr and retStrSize will NOT be altered in this case.) */ -std::string GetParent(const std::string & path); +int GetParent(char ** retStr, size_t * retStrSize); /*! - int FileUtills::ResolvePath(const char * path, const size_t pathSize, char * retStr, size_t * retStrSize, const bool disableSymLinkResolution) + int FileUtills::ResolvePath(const char * path, const size_t pathSize, char ** retStr, size_t * retStrSize, const bool disableSymLinkResolution) Checks the path given, and converts it to a absolute path. @@ -234,49 +249,45 @@ std::string GetParent(const std::string & path); disableSymLinkResolution to false will make this function resolve any symbolic link(s) that are encountered while resolving the given path(s). - Returns COMMON_ERROR_SUCCESS if successfull, retStr and retStrSize will be altered in this + Returns COMMON_ERROR_SUCCESS if successful, retStr and retStrSize will be altered in this case. (Any pre-existing c-string given to this function as retStr will be deallocated.) - Otherwise the approiate error code is returned. (retStr and retStrSize will be unaltered in + Otherwise the appropriate error code is returned. (retStr and retStrSize will be unaltered in this instance.) */ -int ResolvePath(const char * path, const size_t pathSize, char * retStr, size_t * retStrSize, const bool disableSymLinkResolution); +int ResolvePath(const char * path, const size_t pathSize, char ** retStr, size_t * retStrSize, const bool disableSymLinkResolution); /*! - int FileUtills::CreateDirectory(const std::string & directory, const bool & createRecursive) + int FileUtills::CreateDirectory(const char * directory, const size_t directorySize, const bool createRecursive) @pram : directory, path to create. @pram : createRecursive, if this is set to true, then this function will try to create the parent directories of the given directory if they do not exist. This function attempts to create the given directory on the filesystem. - The returned error code is always copied to Common::commonLastErrorCode. - Returns COMMON_ERROR_SUCCESS if directory creation was successful. Returns COMMON_ERROR_ACCESS_DENIED if permission is denied. Returns COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED if this function is unsupported. Returns FILEUTILLS_ERROR_FILESYSTEM_FULL if the disk is full. Returns FILEUTILLS_ERROR_EXISTANT if the directory already exists. - Returns the approiate error or COMMON_ERROR_UNKNOWN_ERROR if another error is encountered. + Returns the appropriate error or COMMON_ERROR_UNKNOWN_ERROR if another error is encountered. */ -int CreateDirectory(const std::string & directory, const bool & createRecursive = false); +int CreateDirectory(const char * directory, const size_t directorySize, const bool createRecursive); /*! - int FileUtills::CheckPermissions(const std::string & path, const bool & read, const bool & write, const bool & exec) + int FileUtills::CheckPermissions(const char * path, const size_t pathSize, const bool read, const bool write, const bool exec) Checks Permissions on the given file or directory. Also checks if the given file or directory - actully exists first before checking other permissions. By default it will check for both read and - write permissions. (Optionaly it can check for execute permissions, and any combonation of the three. This + actually exists first before checking other permissions. By default it will check for both read and + write permissions. (Optionally it can check for execute permissions, and any combination of the three. This function will return a COMMON_ERROR_INVALID_ARGUMENT error however if all of the permissions to check are false.) Pram: path to directory or file to check. Pram: check for read permission. default is true. - Pram: check for wrtie permission. default is true. + Pram: check for write permission. default is true. Pram: check for execute permission. default is false. - The returned error code is always copied to Common::commonLastErrorCode. - Returns COMMON_ERROR_SUCCESS if the directory exists and is accessible with the requested permissions. Returns COMMON_ERROR_ACCESS_DENIED if A permission error occurs. Returns FILEUTILLS_ERROR_NON_EXISTANT if the parent directory does not exist. @@ -285,88 +296,84 @@ int CreateDirectory(const std::string & directory, const bool & createRecursive Returns COMMON_ERROR_INTERNAL_ERROR if an engine error occurs. Returns COMMON_ERROR_UNKNOWN_ERROR if an unknown error occurs. Returns COMMON_ERROR_EXCEPTION_THROWN if an exception is thrown. - Returns the approiate error in all other cases. + Returns the appropriate error in all other cases. */ -int CheckPermissions(const std::string & path, const bool & read = true, const bool & write = true, const bool & exec = false); +int CheckPermissions(const char * path, const size_t pathSize, const bool read, const bool write, const bool exec); /*! - int FileUtills::GetGigaFreespace(const std::string & path, size_t & result) + int FileUtills::GetGigaFreespace(const char * path, const size_t pathSize, size_t * result) Returns the remaining disk space in Gigabytes (SI Unit) on the given disk. Note if an error occurs, result will be set to zero, and an error code will be returned. (Although result can also be set to zero if there really is no remaining disk space.) - @pram const std::string & path : volume / path to check. + @pram const char * path : string that contains the volume / path to check. + @pram const size_t pathSize: length of the path string. @pram size_t & result : The remaining space on the filesystem. - The returned error code is always copied to Common::commonLastErrorCode. - - Returns COMMON_ERROR_SUCCESS if successfull, result will contain the remaining space. - Returns a Common namespace error if an error occurs. Size will be equal to zero in this + Returns COMMON_ERROR_SUCCESS if successful, result will contain the remaining space. + Returns a Common name-space error if an error occurs. result will not be altered in this case. To obtain more detailed info register an error hander before calling this function. */ -int GetGigaFreespace(const std::string & path, size_t & result); +int GetGigaFreespace(const char * path, const size_t pathSize, size_t * result); /*! - int FileUtills::GetFreespace(const std::string & path, size_t & result) + int FileUtills::GetFreespace(const char * path, const size_t pathSize, size_t * result) Returns the remaining disk space in Megabytes (SI Unit) on the given disk. Note if an error occurs, result will be set to zero, and an error code will be returned. (Although result can also be set to zero if there really is no remaining disk space.) - @pram const std::string & path : volume / path to check. + @pram const char * path : string that contains the volume / path to check. + @pram const size_t pathSize: length of the path string. @pram size_t & result : The remaining space on the filesystem. - The returned error code is always copied to Common::commonLastErrorCode. - - Returns COMMON_ERROR_SUCCESS if successfull, result will contain the remaining space. - Returns a Common namespace error if an error occurs. Size will be equal to zero in this + Returns COMMON_ERROR_SUCCESS if successful, result will contain the remaining space. + Returns a Common name-space error if an error occurs. Size will be equal to zero in this case. To obtain more detailed info register an error hander before calling this function. */ -int GetFreespace(const std::string & path, size_t & result); +int GetFreespace(const char * path, const size_t pathSize, size_t * result); /*! - int FileUtills::GetKiloFreespace(const std::string & path, size_t & result) + int FileUtills::GetKiloFreespace(const char * path, const size_t pathSize, size_t * result) Returns the remaining disk space in Kilobytes (SI Unit) on the given disk. Note if an error occurs, result will be set to zero, and an error code will be returned. (Although result can also be set to zero if there really is no remaining disk space.) - @pram const std::string & path : volume / path to check. + @pram const char * path : string that contains the volume / path to check. + @pram const size_t pathSize: length of the path string. @pram size_t & result : The remaining space on the filesystem. - The returned error code is always copied to Common::commonLastErrorCode. - - Returns COMMON_ERROR_SUCCESS if successfull, result will contain the remaining space. - Returns a Common namespace error if an error occurs. Size will be equal to zero in this + Returns COMMON_ERROR_SUCCESS if successful, result will contain the remaining space. + Returns a Common name-space error if an error occurs. Size will be equal to zero in this case. To obtain more detailed info register an error hander before calling this function. */ -int GetKiloFreespace(const std::string & path, size_t & result); +int GetKiloFreespace(const char * path, const size_t pathSize, size_t * result); /*! - int FileUtills::GetByteFreespace(const std::string & path, size_t & result) + int FileUtills::GetByteFreespace(const char * path, const size_t pathSize, size_t * result) Returns the remaining disk space in Bytes (SI Unit) on the given disk. Note if an error occurs, result will be set to zero, and an error code will be returned. (Although result can also be set to zero if there really is no remaining disk space.) - @pram const std::string & path : volume / path to check. + @pram const char * path : string that contains the volume / path to check. + @pram const size_t pathSize: length of the path string. @pram size_t & result : The remaining space on the filesystem. - The returned error code is always copied to Common::commonLastErrorCode. - - Returns COMMON_ERROR_SUCCESS if successfull, result will contain the remaining space. - Returns a Common namespace error if an error occurs. Size will be equal to zero in this + Returns COMMON_ERROR_SUCCESS if successful, result will contain the remaining space. + Returns a Common name-space error if an error occurs. Size will be equal to zero in this case. To obtain more detailed info register an error hander before calling this function. */ -int GetByteFreespace(const std::string & path, size_t & result); +int GetByteFreespace(const char * path, const size_t pathSize, size_t * result); /*! - int FileUtills::DeletePath(const std::string & path, const bool & recursive) + int FileUtills::DeletePath(const char * path, const size_t pathSize, const bool recursive) This function attempts to delete the given file or directory from the filesystem. @@ -374,26 +381,24 @@ int GetByteFreespace(const std::string & path, size_t & result); If the given path is a non-empty directory, by default this function will throw an error. If the given path is an empty directory, however by default this function WILL delete it. - Note: If while deleting rescursively, a file or subdirectory can't be deleted, this function will try to continue - deleting any other files and subdirectories that can be deleted, but it will throw an error apon exit. - - The returned error code is always copied to Common::commonLastErrorCode. - - Returns 0 if successful. - -1 if the user lacks permission to delete the path. (Or if recursively deleting a directory, a file or subdirectory could not be deleted.) - -2 if the path does not exist. (Or if recursively deleting a directory, a file or subdirectory does not exist.) - -3 if the function is not supported. - -4 if a memory error occurs. - -5 if an unknown error occurs. (An error other than a permissions error occured while deleting something.) - -6 if the path is a non empty directory and recursive is set to false. - -7 if while deleting recursively, the parent directory of a deleted directory could not be obtained. (I.e could not "go up a level in the directory tree.") - -8 if while deleting recursively, there were files and or subdirectories that could not be deleted. (Some files may have been deleted however.) + Note: If while deleting recursively, a file or subdirectory can't be deleted, this function will try to continue + deleting any other files and subdirectories that can be deleted, but it will throw an error upon exit. + + Returns COMMON_ERROR_SUCCESS if successful. + COMMON_ERROR_ACCESS_DENIED if the user lacks permission to delete the path. (Or if recursively deleting a directory, a file or subdirectory could not be deleted.) + FILEUTILLS_ERROR_NON_EXISTANT if the path does not exist. (Or if recursively deleting a directory, a file or subdirectory does not exist.) + COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED if the function is not supported. + COMMON_ERROR_MEMORY_ERROR if a memory error occurs. + COMMON_ERROR_UNKNOWN_ERROR if an unknown error occurs. (An error other than a permissions error occured while deleting something.) + FILEUTILLS_ERROR_PATH_IS_A_DIRECTORY if the path is a non empty directory and recursive is set to false. + COMMON_ERROR_IO_ERROR if while deleting recursively, the parent directory of a deleted directory could not be obtained. (I.e could not "go up a level in the directory tree.") + COMMON_ERROR_IO_ERROR if while deleting recursively, there were files and or subdirectories that could not be deleted. (Some files may have been deleted however.) */ -int DeletePath(const std::string & path, const bool & recursive = false); +int DeletePath(const char * path, const size_t pathSize, const bool recursive); /*! - int FileUtills::CopyFile(const std::string & src, const std::string & dest, const bool & append, - const streamsize & begOffset, const streamsize & endOffset) + int FileUtills::CopyFile(const char * srcPath, const size_t srcPathSize, const char * destPath, const size_t destPathSize, + const bool append, const size_t begOffset, const size_t endOffset) Copies endOffset bytes starting at begOffset, from source file to dest file. @@ -431,9 +436,9 @@ int DeletePath(const std::string & path, const bool & recursive = false); By default the entire file is copied and the dest file is overwritten. - Note: This function does NOT make any attempt to preserve the destionation file if it already exists. + Note: This function does NOT make any attempt to preserve the destination file if it already exists. - Note: This function can return ANY error in the Common namespace error list, below is only an example + Note: This function can return ANY error in the Common name-space error list, below is only an example of what errors this function itself may generate. (I.e. This function calls other FileUtills functions and as such can return the errors generated by them.) If you need a more detailed error message, you should register a callback function for the Common error handler (via Common::Register_Error_Log_Callback()) @@ -445,22 +450,20 @@ int DeletePath(const std::string & path, const bool & recursive = false); Returns COMMON_ERROR_MEMORY_ERROR if the memory buffer could not be allocated. Returns COMMON_ERROR_INVALID_ARGUMENT if the source file was not given. Returns COMMON_ERROR_IO_ERROR if the source file could not be opened. - Returns COMMON_ERROR_IO_ERROR if an I/O error occured while reading the source file. + Returns COMMON_ERROR_IO_ERROR if an I/O error occurred while reading the source file. Returns COMMON::FILEUTILLS_PATH_IS_A_DIRECTORY if the given source file was a directory. Returns COMMON_ERROR_INVALID_ARGUMENT if the dest file was not given. Returns COMMON_ERROR_IO_ERROR if dest file could not be opened. - Returns COMMON_ERROR_IO_ERROR if an I/O error occured while writing to the dest file. + Returns COMMON_ERROR_IO_ERROR if an I/O error occurred while writing to the dest file. Returns FILEUTILLS_ERROR_PATH_IS_A_DIRECTORY if the given dest file was a directory. Returns COMMON_ERROR_EXCEPTION_THROWN if an exception is thrown while copying data. */ -int CopyFile(const std::string & src, const std::string & dest, const bool & append = false, - const streamsize & begOffset = 0, const streamsize & endOffset = 0); +int CopyFile(const char * srcPath, const size_t srcPathSize, const char * destPath, const size_t destPathSize, const bool append, + const size_t begOffset, const size_t endOffset); /*! - int FileUtills::CopyPath(const std::string & src, const std::string & dest, const bool & recursive, - const bool & rename, const bool & abort_on_failure, - const bool & append, const streamsize & begOffset, - const streamsize & endOffset) + int FileUtills::CopyPath(const char * srcPath, const size_t srcPathSize, const char * destPath, const size_t destPathSize, const bool recursive, + const bool rename, const bool abort_on_failure, const bool append, const size_t begOffset, const size_t endOffset) This function takes a given source path and copies it to the given dest path. @@ -471,7 +474,7 @@ int CopyFile(const std::string & src, const std::string & dest, const bool & app error codes. If the given src is a directory, then this function will copy the entire directory to the given dest, creating dest if - nessacarry. If recursive is set to true, then the entire directory AND it's subdirectories will be copied. + necessary. If recursive is set to true, then the entire directory AND it's subdirectories will be copied. (The subdirectories will be created as needed, if a subdirectory already exists, then the data from src will be merged.) @pram recursive, if this is true, then this function will recursively copy all subdirectories from src. Merging / creating @@ -480,7 +483,7 @@ int CopyFile(const std::string & src, const std::string & dest, const bool & app @pram rename, if this is set to true, then this function will try to rename the file rather than copy it. otherwise a copy will be performed (Default). - It should be noted that a rename is equivelent to calling CopyFile(), and then DeletePath() on the same source. + It should be noted that a rename is equivalent to calling CopyFile(), and then DeletePath() on the same source. (Minus the overhead and extra disk space use of actually copying the source first.) And that renaming a src will only work if the dest is on the same filesystem. In the event that rename fails, then a copy will be performed UNLESS abort_on_failure is set to true. In that case @@ -505,40 +508,39 @@ int CopyFile(const std::string & src, const std::string & dest, const bool & app Below are return codes for when src is a directory, if src is a file, then the return codes for this function are identical to FileUtills::CopyFile(). Please see FileUtills::CopyFile() for it's return codes. - Returns 0 on success. + Returns COMMON_ERROR_SUCCESS on success. Returns -1 if the function was unable to create top level dest path and top level dest path does not exist. Returns -2 if the top level dest path exists and is a file or some other filesystem entry. - Returns -3 if the host OS / Arch is unsupported. + Returns COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED if the host OS / Arch is unsupported. Returns -4 if the function could not get a directory listing. Returns -5 if the function could not get parent directory string. Returns -6 if the function was unable to copy all files. (Some files may have been copied however.) Returns -13 if FileUtills::IsFileOrDirectory() returns -3. (OS / Arch not supported.) - Returns -14 if FileUtills::IsFileOrDirectory() returns -4. (A permissions error occured.) + Returns -14 if FileUtills::IsFileOrDirectory() returns -4. (A permissions error occurred.) Returns -15 if FileUtills::IsFileOrDirectory() returns -5. (The given path is empty.) - Returns -16 if FileUtills::IsFileOrDirectory() returns -6. (A path componet does not exist.) + Returns -16 if FileUtills::IsFileOrDirectory() returns -6. (A path component does not exist.) Returns -17 if FileUtills::IsFileOrDirectory() returns -7. (The path has a file in it and is not at the end. (I.e you are treating a file as a directory.)) - Returns -19 if FileUtills::IsFileOrDirectory() returns -9. (All other errors.) + Returns COMMON_ERROR_UNKNOWN_ERROR if FileUtills::IsFileOrDirectory() returns -9. (All other errors.) */ -int CopyPath(const std::string & src, const std::string & dest, const bool & recursive = false, - const bool & rename = false, const bool & abort_on_failure = false, - const bool & append = false, const streamsize & begOffset = 0, const streamsize & endOffset = 0); +int CopyPath(const char * srcPath, const size_t srcPathSize, const char * destPath, const size_t destPathSize, const bool recursive, + const bool rename, const bool abort_on_failure, const bool append, const size_t begOffset, const size_t endOffset); /*! - int FileUtills::MovePath(const std::string & src, const std::string & dest, const bool & overwrite) + int FileUtills::MovePath(const char * srcPath, const size_t srcPathSize, const char * destPath, const size_t destPathSize, const bool overwrite) Acts as a wrapper for a call to CopyPath and DeletePath. - The src file is copied to the dest file and then the src file is deleted. + The srcPath is copied to the destPath and then the srcPath is deleted. - Returns 0 on success. + Returns COMMON_ERROR_SUCCESS on success. Returns -10 If an error occurs while accessing the src file. Returns -20 If dest already exists and overwriting is disabled. Returns -21 If dest already exists and can't be deleted. (overwrite = true) Returns -22 If an error occurs while accessing the dest file. - Returns -3 If an Implementation does not exist for your system. - Returns -4 If an error occurs while moving data. - Returns -5 If an argument to the function is bad. + Returns COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED If an Implementation does not exist for your system. + Returns COMMON_ERROR_IO_ERROR If an error occurs while moving data. + Returns COMMON_ERROR_INVALID_ARGUMENT If an argument to the function is bad. */ -int MovePath(const std::string & src, const std::string & dest, const bool & overwrite = false); +int MovePath(const char * srcPath, const size_t srcPathSize, const char * destPath, const size_t destPathSize, const bool overwrite); } From bd9acbf38904a81ac497560ee3d332bc3669f251 Mon Sep 17 00:00:00 2001 From: codebase7 Date: Tue, 9 Jun 2015 11:28:25 -0400 Subject: [PATCH 011/325] Add DataProcess_Endianness_Check() This commit adds the DataProcess_Endianness_Check() function template to DataProcess. --- src/Core/Src/DataProcess.h | 47 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/src/Core/Src/DataProcess.h b/src/Core/Src/DataProcess.h index 1155ef9..f31953b 100644 --- a/src/Core/Src/DataProcess.h +++ b/src/Core/Src/DataProcess.h @@ -26,6 +26,53 @@ namespace DataProcess{ +/* Define Endianness Result Values. */ +#define MSYS_BIG_ENDIAN 0 +#define MSYS_LITTLE_ENDIAN 1 +#define MSYS_UNKNOWN_ENDIANNESS 2 + +/*! + * template + * int DataProcess_Endianness_Check(T & a) + * + * Template function which checks the host's endianness for the + * given argument's data type. + * + * Note: The given argument is not altered or used by the function. + * It's only used to exploit the C++ template generator. + * + * Returns MSYS_BIG_ENDIAN if the given data type is stored as big + * endian on the host machine. + * + * Returns MSYS_LITTLE_ENDIAN if the given data type stored as little + * endian on the host machine. + * + * Returns MSYS_UNKNOWN_ENDIANNESS if the given data type's byte ordering + * is unknown for the given host. + */ +template +int DataProcess_Endianness_Check(const T & a) +{ + /* Init vars. */ + int ret = MSYS_UNKNOWN_ENDIANNESS; /* The result of this function. */ + T t = 1; /* Variable to check. */ + + /* Cast i to a char string and see if the result is 1. */ + if (((char*)&t)[0]) + { + /* The first byte is 1 so it's little endian. */ + ret = MSYS_LITTLE_ENDIAN; + } + else + { + /* The first byte is 0 so it's big endian. */ + ret = MSYS_BIG_ENDIAN; + } + + /* Return the result. */ + return ret; +} + class Data_Object{ private: char * data; // Pointer to data. From 774b37854e65fa79fb417aecded7b1277060e245 Mon Sep 17 00:00:00 2001 From: codebase7 Date: Tue, 9 Jun 2015 11:30:11 -0400 Subject: [PATCH 012/325] Update FileUtills_Emulated_Symobilic_Link_Functions header. This commit updates the FileUtills_Emulated_Symobilic_Link_Functions header (FileUtills_Emulated_Symobilic_Link_Functions.h) to be consistant with the new API changes. --- ...eUtills_Emulated_Symbolic_Link_Functions.h | 77 +++++++++---------- 1 file changed, 36 insertions(+), 41 deletions(-) diff --git a/src/Common/Src/File_Management_Subsystem/FileUtills_Emulated_Symbolic_Link_Functions.h b/src/Common/Src/File_Management_Subsystem/FileUtills_Emulated_Symbolic_Link_Functions.h index 702c3d4..ed99938 100644 --- a/src/Common/Src/File_Management_Subsystem/FileUtills_Emulated_Symbolic_Link_Functions.h +++ b/src/Common/Src/File_Management_Subsystem/FileUtills_Emulated_Symbolic_Link_Functions.h @@ -19,49 +19,52 @@ https://github.com/codebase7/mengine */ -// Include guard. +/* Include guard. */ #ifndef FILEUTILLS_EMULATED_SYMBOLIC_LINK_FUNCTIONS_H #define FILEUTILLS_EMULATED_SYMBOLIC_LINK_FUNCTIONS_H -// Internal includes. +/* Internal includes. */ #include "../Error_Handler/Common_Error_Handler.h" #include "../Error_Handler/Common_Error_Handler_Internal.h" -// External includes. +/* External includes. */ #include #include #include #include +/* Define magic string for the emulated symbolic link file. */ +#define MSYS_EMU_SYMLINK_MAGIC "MSYS_EMU_SYMLINK" + +/* Define file extension for the emulated symbolic link file. */ +#define MSYS_EMU_SYMLINK_FILE_EXT "msl" + +/* Define size of the byte count field. */ +#define MSYS_EMU_SYMLINK_BYTE_COUNT_FIELD_SIZE 4 /*! * Description of the emulated symbolic link file format: * * Offset 0: Magic string. (E.g. "MSYS_EMU_SYMLINK") * - * Offset (0 + sizeof()): uint (4 bytes, little endian) size of the length value. (I.e. sizeof(size_t)). + * Offset (0 + sizeof()): unsigned 32-bit integer (4 bytes, big endian) size of the length value. (I.e. sizeof(size_t)). * * Offset (0 + sizeof() + 4): length of the link. (Length is the same as the read size variable.) * * Offset (0 + sizeof() + 4 + (size of the length value)): Start of link. * - * Offset (0 + sizeof() + 4 + (size of the length value) + ): End of the link, and enf of file. + * Offset (0 + sizeof() + 4 + (size of the length value) + ): End of the link, and end of file. */ // Define namespace. namespace FileUtills -{ - // Define magic string for the emulated symbolic link file. - #define MSYS_EMU_SYMLINK_MAGIC "MSYS_EMU_SYMLINK" - - // Define file extension for the emulated symbolic link file. - #define MSYS_EMU_SYMLINK_FILE_EXT "msl" - +{ // Define functions. /*! - * int FileUtills::Create_MSYS_Emulated_Symbolic_Link(const std::string & linkDestionation, const std::string & pathToLinkFile) + * int FileUtills::Create_MSYS_Emulated_Symbolic_Link(const char * linkDestionation, const size_t linkDestionationSize, + * const char * pathToLinkFile, const size_t pathToLinkFileSize) * * Takes the given linkDestionation string and creates an emulated symbolic link file with the string's * contents at the given path on the filesystem. @@ -72,21 +75,19 @@ namespace FileUtills * need to create the directory tree leading up to the file to create.) If either of these assumptions * are false, this function will abort and return an error. * - * If successfull this function will return COMMON_ERROR_SUCCESS, and the emulated symbolic link file + * If successful this function will return COMMON_ERROR_SUCCESS, and the emulated symbolic link file * will be present at the given location on the filesystem. * - * If an error occurs, the approperite Common namespace error code will be returned. In addition, the + * If an error occurs, the appropriate Common name-space error code will be returned. In addition, the * emulated link file will be rendered invalid on the filesystem. (It will still be present on the * filesystem however, as such it will need to be deleted manually.) - * - * In all instances the returned error code will be copied to Common::commonLastErrorCode. (In addition, - * depending on the configured log level, a human readable error message will be outputted to the logging - * function to better describe the error that occured.) */ - int Create_MSYS_Emulated_Symbolic_Link(const std::string & linkDestionation, const std::string & pathToLinkFile); + int Create_MSYS_Emulated_Symbolic_Link(const char * linkDestionation, const size_t linkDestionationSize, + const char * pathToLinkFile, const size_t pathToLinkFileSize); /*! - * int FileUtills::Read_MSYS_Emulated_Symbolic_Link(std::string & link, const std::string & pathToLinkFile) + * int FileUtills::Read_MSYS_Emulated_Symbolic_Link(char ** retStr, size_t * retStrSize, const char * pathToLinkFile, + * const size_t pathToLinkFileSize) * * Erases the given link argument string, then reads the file from the given path for a symbolic link * string, and writes it to the given link argument string. @@ -94,9 +95,9 @@ namespace FileUtills * NOTE: This function does NOT resolve the read symbolic link, and will return it as is on the filesystem. * To resolve the link, either call your own resolver function, or call FileUtills::ResolvePath(). * - * NOTE: This function is called automaticly by FileUtills::ResolvePath() if symbolic link resolution is + * NOTE: This function is called automatically by FileUtills::ResolvePath() if symbolic link resolution is * enabled by the caller (it is by default), and an emulated link file is found during path resolution. - * As such it's not nessacarry to call this function directly before FileUtills::ResolvePath(). + * As such it's not necessary to call this function directly before FileUtills::ResolvePath(). * * (Sidenote: This function returns read links as is, if the read link is relative to the directory it is in, * then the link string will need to have the path to the directory that the emulated link file is stored @@ -105,20 +106,17 @@ namespace FileUtills * calling program's current working directory. (Along with all of the issues that come with that * assumption.)) * - * If successfull, the given link argument string will have it's contents replaced with the read link + * If successful, the given link argument string will have it's contents replaced with the read link * string, and COMMON_ERROR_SUCCESS will be returned. * - * If an error occurs then the given link argument string will be blank / empty, and the approperite - * Common namespace error code will be returned. - * - * In all instances the returned error code will be copied to Common::commonLastErrorCode. (In addition, - * depending on the configured log level, a human readable error message will be outputted to the logging - * function to better describe the error that occured.) + * If an error occurs then the given link argument string will be blank / empty, and the appropriate + * Common name-space error code will be returned. */ - int Read_MSYS_Emulated_Symbolic_Link(std::string & link, const std::string & pathToLinkFile); + int Read_MSYS_Emulated_Symbolic_Link(char ** retStr, size_t * retStrSize, const char * pathToLinkFile, const size_t pathToLinkFileSize); /*! - * int FileUtills::Update_MSYS_Emulated_Symbolic_Link(const std::string & linkDestionation, const std::string & pathToLinkFile) + * int FileUtills::Update_MSYS_Emulated_Symbolic_Link(const char * linkDestionation, const size_t linkDestionationSize, + * const char * pathToLinkFile, const size_t pathToLinkFileSize) * * This function updates a pre-existing emulated link file at the given path on the filesystem, with the contents * of the given linkDestionation argument string. @@ -127,20 +125,17 @@ namespace FileUtills * expects that the emulated link file will be valid. If either of these two conditions are not true, then this function * will abort and return an error. * - * If successfull, the given emulated link file will contain the contents of the given linkDestionation argument string, and + * If successful, the given emulated link file will contain the contents of the given linkDestionation argument string, and * the returned error code will be COMMON_ERROR_SUCCESS. * - * If an error occurs, the approperite Common namespace error code will be returned. In addition, the + * If an error occurs, the appropriate Common name-space error code will be returned. In addition, the * emulated link file will be rendered invalid on the filesystem. (It will still be present on the * filesystem however, as such it will need to be deleted manually.) - * - * In all instances the returned error code will be copied to Common::commonLastErrorCode. (In addition, - * depending on the configured log level, a human readable error message will be outputted to the logging - * function to better describe the error that occured.) */ - int Update_MSYS_Emulated_Symbolic_Link(const std::string & linkDestionation, const std::string & pathToLinkFile); + int Update_MSYS_Emulated_Symbolic_Link(const char * linkDestionation, const size_t linkDestionationSize, + const char * pathToLinkFile, const size_t pathToLinkFileSize); }; -#endif +#endif /* FILEUTILLS_EMULATED_SYMBOLIC_LINK_FUNCTIONS_H */ -// End of FileUtills_Emulated_Symbolic_Link_Functions.h +/* End of FileUtills_Emulated_Symbolic_Link_Functions.h */ From 7eaaca082a558aca6575873138b4192db61aaf1f Mon Sep 17 00:00:00 2001 From: codebase7 Date: Tue, 9 Jun 2015 11:59:59 -0400 Subject: [PATCH 013/325] Fix DataProcess_Endianness_Check() This commit makes DataProcess_Endianness_Check() actually return an MSYS_UNKNOWN_ENDIANNESS error if the host's endianness for a data type can not be determined. --- src/Core/Src/DataProcess.h | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/Core/Src/DataProcess.h b/src/Core/Src/DataProcess.h index f31953b..a2c69c9 100644 --- a/src/Core/Src/DataProcess.h +++ b/src/Core/Src/DataProcess.h @@ -57,7 +57,7 @@ int DataProcess_Endianness_Check(const T & a) int ret = MSYS_UNKNOWN_ENDIANNESS; /* The result of this function. */ T t = 1; /* Variable to check. */ - /* Cast i to a char string and see if the result is 1. */ + /* Cast t to a char string and see if the result is 1. */ if (((char*)&t)[0]) { /* The first byte is 1 so it's little endian. */ @@ -65,8 +65,19 @@ int DataProcess_Endianness_Check(const T & a) } else { - /* The first byte is 0 so it's big endian. */ - ret = MSYS_BIG_ENDIAN; + /* + * The first byte is 0 so, check and see if the last byte is non-zero. + * If it is, then the host is big endian. + * + * Otherwise the host is using something like middle-endian to store + * the value, but we would need more checks to determine what exact + * kind of endianness the host is using. + */ + if (((char*)&t)[((sizeof(t)) - 1)]) + { + /* It's big endian. */ + ret = MSYS_BIG_ENDIAN; + } } /* Return the result. */ From 107c62d58cb2a87b028083bf7e975dbe3501fa66 Mon Sep 17 00:00:00 2001 From: codebase7 Date: Wed, 10 Jun 2015 10:41:52 -0400 Subject: [PATCH 014/325] Add floating point special.... This commit adds template specializations for floating point types float, and double to DataProcess_Endianness_Check(). (Needed to properly detect the correct endianness for those data types.) --- src/Core/Src/DataProcess.h | 71 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/src/Core/Src/DataProcess.h b/src/Core/Src/DataProcess.h index a2c69c9..c8ea7ba 100644 --- a/src/Core/Src/DataProcess.h +++ b/src/Core/Src/DataProcess.h @@ -41,6 +41,9 @@ namespace DataProcess{ * Note: The given argument is not altered or used by the function. * It's only used to exploit the C++ template generator. * + * The specializations for float and double are required as floating + * point data types must be detected differently from integers. + * * Returns MSYS_BIG_ENDIAN if the given data type is stored as big * endian on the host machine. * @@ -84,6 +87,74 @@ int DataProcess_Endianness_Check(const T & a) return ret; } +template<> +int DataProcess_Endianness_Check(const float & a) +{ + /* Init vars. */ + int ret = MSYS_UNKNOWN_ENDIANNESS; /* The result of this function. */ + float t = 1.0; /* Variable to check. */ + + /* Cast t to a char string and see if the first 2 values are 0x3F80. */ + if ((((char*)&t)[0] == 0x3F) && ((((char*)&t)[1] == 0x80))) + { + /* The first 2 bytes are 0x3F80 so it's big endian. */ + ret = MSYS_BIG_ENDIAN; + } + else + { + /* + * The first check did not pass, so check and see if the last 2 bytes are 0x803F. + * If they are, then the host is little endian. + * + * Otherwise the host is using something like middle-endian to store + * the value, but we would need more checks to determine what exact + * kind of endianness the host is using. + */ + if ((((char*)&t)[(sizeof (float) - 1)] == 0x80) && ((((char*)&t)[(sizeof (float) - 2)] == 0x3F))) + { + /* It's little endian. */ + ret = MSYS_LITTLE_ENDIAN; + } + } + + /* Return the result. */ + return ret; +} + +template<> +int DataProcess_Endianness_Check(const double & a) +{ + /* Init vars. */ + int ret = MSYS_UNKNOWN_ENDIANNESS; /* The result of this function. */ + double t = 1.0; /* Variable to check. */ + + /* Cast t to a char string and see if the first 2 values are 0x3FF0. */ + if ((((char*)&t)[0] == 0x3F) && ((((char*)&t)[1] == 0xF0))) + { + /* The first 2 bytes are 0x3F80 so it's big endian. */ + ret = MSYS_BIG_ENDIAN; + } + else + { + /* + * The first check did not pass, so check and see if the last 2 bytes are 0xF03F. + * If they are, then the host is little endian. + * + * Otherwise the host is using something like middle-endian to store + * the value, but we would need more checks to determine what exact + * kind of endianness the host is using. + */ + if ((((char*)&t)[(sizeof (double) - 1)] == 0xF0) && ((((char*)&t)[(sizeof (double) - 2)] == 0x3F))) + { + /* It's little endian. */ + ret = MSYS_LITTLE_ENDIAN; + } + } + + /* Return the result. */ + return ret; +} + class Data_Object{ private: char * data; // Pointer to data. From 93199aa7662b72c19aa42a554de09fa34e82cd86 Mon Sep 17 00:00:00 2001 From: codebase7 Date: Thu, 11 Jun 2015 14:18:37 -0400 Subject: [PATCH 015/325] Move fake stdbool.h This commit moves the fake stdbool.h from src/Common/Src/Mutexes to src/Common/Src. --- src/Common/Src/Mutexes/Windows/MSYS_Mutexes_MSVC.h | 2 +- src/Common/Src/{Mutexes => }/stdbool.h | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename src/Common/Src/{Mutexes => }/stdbool.h (100%) diff --git a/src/Common/Src/Mutexes/Windows/MSYS_Mutexes_MSVC.h b/src/Common/Src/Mutexes/Windows/MSYS_Mutexes_MSVC.h index 83d9af3..f1e625b 100644 --- a/src/Common/Src/Mutexes/Windows/MSYS_Mutexes_MSVC.h +++ b/src/Common/Src/Mutexes/Windows/MSYS_Mutexes_MSVC.h @@ -35,7 +35,7 @@ extern "C" { #endif /* __cplusplus */ /* Define stdbool. */ -#include "..\stdbool.h" +#include "..\..\stdbool.h" /* Define the functions. */ diff --git a/src/Common/Src/Mutexes/stdbool.h b/src/Common/Src/stdbool.h similarity index 100% rename from src/Common/Src/Mutexes/stdbool.h rename to src/Common/Src/stdbool.h From 23ba84692495683be3d86d8fb664034c56533b12 Mon Sep 17 00:00:00 2001 From: codebase7 Date: Thu, 11 Jun 2015 15:19:39 -0400 Subject: [PATCH 016/325] MSVC fix for Error_Handler.c This commit is a compile fix for Common_Error_Handler.c under MSVC. Also changes the data type for registeredFatalErrorCallbackFunctionsSize from an unsigned int to a size_t. --- .../Src/Error_Handler/Common_Error_Handler.c | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/Common/Src/Error_Handler/Common_Error_Handler.c b/src/Common/Src/Error_Handler/Common_Error_Handler.c index eb462fe..ca2aefe 100644 --- a/src/Common/Src/Error_Handler/Common_Error_Handler.c +++ b/src/Common/Src/Error_Handler/Common_Error_Handler.c @@ -84,11 +84,11 @@ void Common_Register_Error_Log_Callback(void (*loggingFunction)(const unsigned i // Build the Fatal Error Handler if needed. #ifdef MSYS_BUILD_FATAL_ERROR_SUPPORT /*! - * static unsigned int registeredFatalErrorCallbackFunctionsSize + * static size_t registeredFatalErrorCallbackFunctionsSize * - * This unsigned int is used to remember the allocated size of the registeredFatalErrorCallbackFunctions array. + * This size_t is used to remember the allocated size of the registeredFatalErrorCallbackFunctions array. */ -static unsigned int registeredFatalErrorCallbackFunctionsSize = 0; +static size_t registeredFatalErrorCallbackFunctionsSize = 0; /* * static Common_pErrorCallBackFunction * registeredFatalErrorCallbackFunctions @@ -113,6 +113,7 @@ bool Common_Register_Fatal_Error_Callback(const Common_pErrorCallBackFunction fa bool ret = false; // The result of this function. size_t previousErrorListSize = registeredFatalErrorCallbackFunctionsSize; // The size of the previous error list. size_t newErrorListSize = 0; // The size of the new error list we are creating. + size_t x = 0; /* Counter used in for loops. */ Common_pErrorCallBackFunction * previousErrorList = registeredFatalErrorCallbackFunctions; // The previous error list. Common_pErrorCallBackFunction * newErrorList = NULL; // The new error list we are creating. MSYS_Mutex * retFromLockMutex = NULL; // The result from the call to MSYS_Lock_Mutex(). @@ -142,7 +143,7 @@ bool Common_Register_Fatal_Error_Callback(const Common_pErrorCallBackFunction fa newErrorListSize = (previousErrorListSize + 1); // Copy the data. - for (size_t x = 0; x < previousErrorListSize; x++) + for (x = 0; x < previousErrorListSize; x++) { newErrorList[x] = previousErrorList[x]; } @@ -173,7 +174,7 @@ bool Common_Register_Fatal_Error_Callback(const Common_pErrorCallBackFunction fa if ((previousErrorList != NULL) && (previousErrorList != newErrorList) && (previousErrorListSize > 0)) { // Null out the old pointer list. - for (size_t x = 0; x < previousErrorListSize; x++) + for (x = 0; x < previousErrorListSize; x++) { previousErrorList[x] = NULL; } @@ -203,6 +204,8 @@ bool Common_Unregister_Fatal_Error_Callback(const Common_pErrorCallBackFunction bool ret = false; // The result of this function. size_t previousErrorListSize = registeredFatalErrorCallbackFunctionsSize; // The size of the previous error list. size_t newErrorListSize = 0; // The size of the new error list we are creating. + size_t x = 0; /* Counter used in top level for loops. */ + size_t y = 0; /* Counter used in sub level 1 for loops. */ Common_pErrorCallBackFunction * previousErrorList = registeredFatalErrorCallbackFunctions; // The previous error list. Common_pErrorCallBackFunction * newErrorList = NULL; // The new error list we are creating. MSYS_Mutex * retFromLockMutex = NULL; // The result from the call to MSYS_Lock_Mutex(). @@ -218,7 +221,7 @@ bool Common_Unregister_Fatal_Error_Callback(const Common_pErrorCallBackFunction if ((previousErrorList != NULL) && (previousErrorListSize > 0)) { // Check the existing list for that function. - for (size_t x = 0; ((newErrorList == NULL) && (x < previousErrorListSize)); x++) + for (x = 0; ((newErrorList == NULL) && (x < previousErrorListSize)); x++) { // Check for the correct function, to see if the function was registered previously. if (previousErrorList[x] == fatalErrorNotifyFunction) @@ -237,7 +240,7 @@ bool Common_Unregister_Fatal_Error_Callback(const Common_pErrorCallBackFunction if ((newErrorList != NULL) && (newErrorListSize == (previousErrorListSize - 1))) { // Copy the data. - for (size_t x = 0, y = 0; ((x < previousErrorListSize) && (y < newErrorListSize)); x++) + for (x = 0, y = 0; ((x < previousErrorListSize) && (y < newErrorListSize)); x++) { // Make sure we don't copy the pointer we are removing. if (previousErrorList[x] != fatalErrorNotifyFunction) @@ -256,7 +259,7 @@ bool Common_Unregister_Fatal_Error_Callback(const Common_pErrorCallBackFunction if ((previousErrorList != NULL) && (previousErrorList != newErrorList) && (previousErrorListSize > 0)) { // Null out the old pointer list. - for (size_t x = 0; x < previousErrorListSize; x++) + for (x = 0; x < previousErrorListSize; x++) { previousErrorList[x] = NULL; } @@ -284,6 +287,7 @@ void Common_Fatal_Error_Notify() { // Init vars. MSYS_Mutex * retFromLockMutex = NULL; // The result from the call to MSYS_Lock_Mutex(). + size_t x = 0; /* Counter used in loops. */ // Lock the error handler mutex. retFromLockMutex = MSYS_Lock_Mutex(fatalErrorHandlerMutex); @@ -293,7 +297,7 @@ void Common_Fatal_Error_Notify() if (registeredFatalErrorCallbackFunctionsSize > 0) { // Begin vector iteration loop. - for (size_t x = 0; (x < registeredFatalErrorCallbackFunctionsSize); x++) + for (x = 0; (x < registeredFatalErrorCallbackFunctionsSize); x++) { // Trigger each function. if (registeredFatalErrorCallbackFunctions[x] != NULL) From 55e9861feda9030111abc5c20c424a163ce6ee22 Mon Sep 17 00:00:00 2001 From: codebase7 Date: Thu, 11 Jun 2015 15:20:55 -0400 Subject: [PATCH 017/325] Remove unused exception var This commit removes the unused execption variable from Common::Fatal_Error_Notify(). (Get rid of compile warning.) --- .../Src/Error_Handler/Common_Error_Handler_CPP_Bindings.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Common/Src/Error_Handler/Common_Error_Handler_CPP_Bindings.cpp b/src/Common/Src/Error_Handler/Common_Error_Handler_CPP_Bindings.cpp index f880379..f355d93 100644 --- a/src/Common/Src/Error_Handler/Common_Error_Handler_CPP_Bindings.cpp +++ b/src/Common/Src/Error_Handler/Common_Error_Handler_CPP_Bindings.cpp @@ -105,7 +105,7 @@ void Common::Fatal_Error_Notify() // Call real function. Common_Fatal_Error_Notify(); } - catch (std::exception & ex) + catch (...) { // Well, not much to do here, we are terminating anyway. COMMON_LOG_CRITICAL("Common::Fatal_Error_Notify(): Exception occured while notifying engine subsystems / application that a fatal error occured."); From 7b918ff838a218c37f9ed26478d155989c86b284 Mon Sep 17 00:00:00 2001 From: codebase7 Date: Thu, 11 Jun 2015 15:22:22 -0400 Subject: [PATCH 018/325] MSVC fix for Error_Handler_Struct This commit is a compile fix for Common_Error_Handler_Structures.c under MSVC. --- src/Common/Src/Error_Handler/Common_Error_Handler_Structures.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Common/Src/Error_Handler/Common_Error_Handler_Structures.c b/src/Common/Src/Error_Handler/Common_Error_Handler_Structures.c index 0c682f4..c693f92 100644 --- a/src/Common/Src/Error_Handler/Common_Error_Handler_Structures.c +++ b/src/Common/Src/Error_Handler/Common_Error_Handler_Structures.c @@ -122,12 +122,13 @@ const char * Common_Get_Error_Message(const int errorCode) // Init vars. const char * result = COMMON_ERROR_UNKNOWN_ERROR_MSG; // Result of this function. const size_t errorTableSize = Common_Get_Error_Table_Size(); // Size of the Common error lookup table. + size_t x = 0; /* Counter used in for loop. */ // Check for COMMON_UNKNOWN_ERROR. if (errorCode != COMMON_ERROR_UNKNOWN_ERROR) { // Begin lookup loop. - for (size_t x = 0; ((x < errorTableSize) && (result == COMMON_ERROR_UNKNOWN_ERROR_MSG)); x++) + for (x = 0; ((x < errorTableSize) && (result == COMMON_ERROR_UNKNOWN_ERROR_MSG)); x++) { // Check for the correct error code. if (Common_commonErrorTable[x].errorCode == errorCode) From 4e1f6353ac90824489a1ba1592caff6afe784be4 Mon Sep 17 00:00:00 2001 From: codebase7 Date: Thu, 11 Jun 2015 15:31:27 -0400 Subject: [PATCH 019/325] MSVC fix Common_Error_Handler.h This commit is a compile fix for Common_Error_Handler.h under MSVC. (Fix missing stdbool.h with false header.) --- src/Common/Src/Error_Handler/Common_Error_Handler.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Common/Src/Error_Handler/Common_Error_Handler.h b/src/Common/Src/Error_Handler/Common_Error_Handler.h index 02f4949..03267f4 100644 --- a/src/Common/Src/Error_Handler/Common_Error_Handler.h +++ b/src/Common/Src/Error_Handler/Common_Error_Handler.h @@ -25,8 +25,12 @@ // External includes. #include // Defines NULL. #ifndef __cplusplus -#include // Defines bool data type. (For C compilers.) -#endif // __cplusplus +#ifdef _MSC_FULL_VER /* VC is special. */ +#include "..\stdbool.h" /* Defines bool data type. (For C compilers.) */ +#else +#include +#endif /* _MSC_FULL_VER */ +#endif /* __cplusplus */ // Project includes. #ifdef _WIN32 // Needed for different path seperator in Windows. From ff80017ce633810bbde571239c6fe9a8d82d7c7b Mon Sep 17 00:00:00 2001 From: codebase7 Date: Thu, 11 Jun 2015 21:19:12 -0400 Subject: [PATCH 020/325] Commit missing file. This commit adds the missing Dynamic_Library_Subsystem_Windows.c file. (It's defined to be built in master, but not present. We are creating this branch as it requires the fake stdbool header from the error_handler branch to build under MSVC. Also due to the code being untested, we are moving it here to avoid messing up master.) --- .../Dynamic_Library_Subsystem_Windows.c | 212 ++++++++++++++++++ 1 file changed, 212 insertions(+) create mode 100644 src/Common/Src/Dynamic_Library_Subsystem/Dynamic_Library_Subsystem_Windows.c diff --git a/src/Common/Src/Dynamic_Library_Subsystem/Dynamic_Library_Subsystem_Windows.c b/src/Common/Src/Dynamic_Library_Subsystem/Dynamic_Library_Subsystem_Windows.c new file mode 100644 index 0000000..0691225 --- /dev/null +++ b/src/Common/Src/Dynamic_Library_Subsystem/Dynamic_Library_Subsystem_Windows.c @@ -0,0 +1,212 @@ +/*! + Multiverse Engine Project 28/3/2014 Dynamic_Library_Subsystem Dynamic_Library_Subsystem_Windows.c + + Copyright (C) 2014 Multiverse Engine Project + + This program is free software; + you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this program; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Official source repository and project information can be found at + https://github.com/codebase7/mengine +*/ + +#include "Dynamic_Library_Subsystem.h" +#include + +#ifdef __cplusplus +// Define extern C. +extern "C" { +#endif + int Common_Dynamic_Library_Subsystem_Load_Library(const char * pathToLibrary, const bool reloadLibrary, Common_Dynamic_Library_Subsystem_Loaded_Dynamic_Library * lib) + { + // Init vars. + int result = 0; // The result of this function. + HMODULE callResult = NULL; // The result of the call to LoadLibraryEx(). + + // Check to see if the pointer to the management structure is valid. + if (lib != NULL) + { + // Check to see if pathToLibrary is NULL. + if (pathToLibrary != NULL) + { + // Check to see if the library is loaded. + if ((!lib->bIsLoaded) || (reloadLibrary)) + { + // Check and see if the library is loaded. + if (lib->bIsLoaded) + { + // Call Unload_Library. + result = Common_Dynamic_Library_Subsystem_Unload_Library(lib); + } + + // Only continue if the library was unloaded, or if we did not need to unload the library. + if (result == 0) + { + // Set the values in lib. + lib->bIsLoaded = false; + lib->bLastCallEncounteredAnError = false; + lib->osSpecificPointerData = NULL; + lib->pathToLibrary = pathToLibrary; + + // Call LoadLibraryEx(). + callResult = LoadLibraryEx(lib->pathToLibrary, NULL, 0); + + // Check the callResult. + if (callResult == NULL) + { + // Could not load the library. + result = -1; + lib->bLastCallEncounteredAnError = true; + COMMON_LOG_VERBOSE("Common_Dynamic_Library_Subsystem_Load_Library(): Could not load the library.\n"); + } + else + { + // Cast the OS specific data structure pointer to void*. + lib->osSpecificPointerData = (void*)callResult; + + // Set bIsLoaded. + lib->bIsLoaded = true; + } + } + else + { + // Encountered an error during the unload. + result = -2; + lib->bLastCallEncounteredAnError = true; + COMMON_LOG_VERBOSE("Common_Dynamic_Library_Subsystem_Load_Library(): Unable to reload library.\n"); + } + } + else + { + // Library is already loaded. + result = 1; + } + } + else + { + // pathToLibrary is NULL. + result = -3; + lib->bLastCallEncounteredAnError = true; + COMMON_LOG_VERBOSE("Common_Dynamic_Library_Subsystem_Load_Library(): No path to the library was given. Unable to load a library without the path to it.\n"); + } + } + else + { + // Management structure is invalid. + result = -4; + COMMON_LOG_VERBOSE("Common_Dynamic_Library_Subsystem_Load_Library(): The engine's library structure for the given library is invalid. Unable to load a library without a valid library structure.\n"); + } + + // Return result. + return result; + } + + int Common_Dynamic_Library_Subsystem_Unload_Library(Common_Dynamic_Library_Subsystem_Loaded_Dynamic_Library * lib) + { + // Init vars. + int result = 0; // The result of this function. + + // Check to see if the pointer to the management structure is valid. + if (lib != NULL) + { + // Reset bLastCallEncounteredAnError. + lib->bLastCallEncounteredAnError = false; + + // Check and see if the OS specific data structure pointer is valid. + if ((lib->bIsLoaded) && (lib->osSpecificPointerData != NULL)) + { + // Call FreeLibrary. + if (FreeLibrary((HMODULE)lib->osSpecificPointerData)) + { + // The library was unloaded successfully. + lib->bIsLoaded = false; + lib->osSpecificPointerData = NULL; + } + else + { + // Could not unload the library. + result = -2; + lib->bLastCallEncounteredAnError = true; + COMMON_LOG_VERBOSE("Common_Dynamic_Library_Subsystem_Unload_Library(): Could not unload the library.\n"); + } + } + else + { + // Library is not loaded. + result = -1; + lib->bLastCallEncounteredAnError = true; + COMMON_LOG_VERBOSE("Common_Dynamic_Library_Subsystem_Unload_Library(): The library is not loaded.\n"); + } + } + else + { + // Management structure is invalid. + result = -4; + COMMON_LOG_VERBOSE("Common_Dynamic_Library_Subsystem_Unload_Library(): The engine's library structure for the given library is invalid. Unable to unload a library without a valid library structure.\n"); + } + + // Return result. + return result; + } + + void * Common_Dynamic_Library_Subsystem_Get_Symbol(Common_Dynamic_Library_Subsystem_Loaded_Dynamic_Library * lib, const char * symbolName) + { + // Init vars. + void * result = NULL; // The result of this function. + + // Check to see if the pointer to the management structure is valid. + if (lib != NULL) + { + // Reset bLastCallEncounteredAnError. + lib->bLastCallEncounteredAnError = false; + + // Check to see if symbolName is NULL. + if (symbolName != NULL) + { + // Check for a loaded library. + if (((lib->bIsLoaded) && (lib->osSpecificPointerData != NULL))) + { + // Get the address. + result = (void*)GetProcAddress((HMODULE)lib->osSpecificPointerData, symbolName); + if (result == NULL) + { + // An error occured fetching the symbol. + lib->bLastCallEncounteredAnError = true; + COMMON_LOG_VERBOSE("Common_Dynamic_Library_Subsystem_Get_Symbol(): Unable to retrive symbol.\n"); + } + } + else + { + // Library is not loaded. + lib->bLastCallEncounteredAnError = true; + COMMON_LOG_VERBOSE("Common_Dynamic_Library_Subsystem_Get_Symbol(): The library is not loaded.\n"); + } + } + else + { + // symbolName is NULL. + lib->bLastCallEncounteredAnError = true; + COMMON_LOG_VERBOSE("Common_Dynamic_Library_Subsystem_Get_Symbol(): No symbol name was given, cannot load a symbol without a name to identifiy it.\n"); + } + } + else + { + // Library structure is invalid. + COMMON_LOG_VERBOSE("Common_Dynamic_Library_Subsystem_Get_Symbol(): The engine's library structure for the given library is invalid. Unable to lookup function without a valid library structure.\n"); + } + + // Return result. + return result; + } +#ifdef __cplusplus +} // End of extern C. +#endif + From 9dfbcb97167c0b4394b1a6795de30d011818a21f Mon Sep 17 00:00:00 2001 From: codebase7 Date: Thu, 11 Jun 2015 21:20:10 -0400 Subject: [PATCH 021/325] MSVC Compile Fix This commit is a compile fix for Dynamic_Library_Subsystem.h under MSVC. (Fake bool header.) --- .../Dynamic_Library_Subsystem/Dynamic_Library_Subsystem.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Common/Src/Dynamic_Library_Subsystem/Dynamic_Library_Subsystem.h b/src/Common/Src/Dynamic_Library_Subsystem/Dynamic_Library_Subsystem.h index 7042a1e..d972e8f 100644 --- a/src/Common/Src/Dynamic_Library_Subsystem/Dynamic_Library_Subsystem.h +++ b/src/Common/Src/Dynamic_Library_Subsystem/Dynamic_Library_Subsystem.h @@ -22,7 +22,12 @@ #ifndef MSYS_DYNAMIC_LIBRARY_SUBSYSTEM_H #define MSYS_DYNAMIC_LIBRARY_SUBSYSTEM_H +/* Check for MSVC. */ +#ifdef _MSC_FULL_VER +#include "..\stdbool.h" /* bool. (MSVC is special.) */ +#else #include // bool. +#endif /* _MSC_FULL_VER */ #include // NULL. #include // Malloc. From 2f65d1903ef8bf2f98a52c5552613528a608a684 Mon Sep 17 00:00:00 2001 From: codebase7 Date: Thu, 11 Jun 2015 21:36:39 -0400 Subject: [PATCH 022/325] Fix warnings. This commit fixes the missing const statement from the function arguments for the following functions: Common_Dynamic_Library_Subsystem_Load_Library(), Common_Dynamic_Library_Subsystem_Unload_Library(), and Common_Dynamic_Library_Subsystem_Get_Symbol() in Dynamic_Library_Subsystem_Windows.c. --- .../Dynamic_Library_Subsystem_Windows.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Common/Src/Dynamic_Library_Subsystem/Dynamic_Library_Subsystem_Windows.c b/src/Common/Src/Dynamic_Library_Subsystem/Dynamic_Library_Subsystem_Windows.c index 0691225..4e24acc 100644 --- a/src/Common/Src/Dynamic_Library_Subsystem/Dynamic_Library_Subsystem_Windows.c +++ b/src/Common/Src/Dynamic_Library_Subsystem/Dynamic_Library_Subsystem_Windows.c @@ -25,7 +25,7 @@ // Define extern C. extern "C" { #endif - int Common_Dynamic_Library_Subsystem_Load_Library(const char * pathToLibrary, const bool reloadLibrary, Common_Dynamic_Library_Subsystem_Loaded_Dynamic_Library * lib) + int Common_Dynamic_Library_Subsystem_Load_Library(const char * pathToLibrary, const bool reloadLibrary, Common_Dynamic_Library_Subsystem_Loaded_Dynamic_Library *const lib) { // Init vars. int result = 0; // The result of this function. @@ -109,7 +109,7 @@ extern "C" { return result; } - int Common_Dynamic_Library_Subsystem_Unload_Library(Common_Dynamic_Library_Subsystem_Loaded_Dynamic_Library * lib) + int Common_Dynamic_Library_Subsystem_Unload_Library(Common_Dynamic_Library_Subsystem_Loaded_Dynamic_Library *const lib) { // Init vars. int result = 0; // The result of this function. @@ -157,7 +157,7 @@ extern "C" { return result; } - void * Common_Dynamic_Library_Subsystem_Get_Symbol(Common_Dynamic_Library_Subsystem_Loaded_Dynamic_Library * lib, const char * symbolName) + void * Common_Dynamic_Library_Subsystem_Get_Symbol(Common_Dynamic_Library_Subsystem_Loaded_Dynamic_Library *const lib, const char * symbolName) { // Init vars. void * result = NULL; // The result of this function. From 22f6a9f111db98f135d8d1310072a037a16ae640 Mon Sep 17 00:00:00 2001 From: codebase7 Date: Sat, 13 Jun 2015 11:56:27 -0400 Subject: [PATCH 023/325] Add DLL exports for MSVC to Error Handler Structures. This commit adds the needed MSYS_DLL_EXPORT declarations for the functions in Common_Error_Handler_Structures.h. --- .../Error_Handler/Common_Error_Handler_Structures.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Common/Src/Error_Handler/Common_Error_Handler_Structures.h b/src/Common/Src/Error_Handler/Common_Error_Handler_Structures.h index 92a5b06..e24c2cf 100644 --- a/src/Common/Src/Error_Handler/Common_Error_Handler_Structures.h +++ b/src/Common/Src/Error_Handler/Common_Error_Handler_Structures.h @@ -93,14 +93,14 @@ extern "C" { * * Returns the API version number of the common error table. */ -const unsigned int Common_Get_Error_Table_API_Version(); +MSYS_DLL_EXPORT const unsigned int Common_Get_Error_Table_API_Version(); /*! * const unsigned int Common_Get_Error_Table_Size() * * Returns the size of the common error table. */ -const unsigned int Common_Get_Error_Table_Size(); +MSYS_DLL_EXPORT const unsigned int Common_Get_Error_Table_Size(); /*! * const char * Common_Get_Error_Message(const int & errorCode) @@ -111,7 +111,7 @@ const unsigned int Common_Get_Error_Table_Size(); * Returns a valid pointer if the given error code is in the common error table. * Returns the message for Common_COMMON_UNKNOWN_ERROR otherwise. */ -const char * Common_Get_Error_Message(const int errorCode); +MSYS_DLL_EXPORT const char * Common_Get_Error_Message(const int errorCode); /* End C Linkage if needed. */ #ifdef __cplusplus @@ -130,7 +130,7 @@ namespace Common * * Returns the API version number of the common error table. */ - const unsigned int Get_Error_Table_API_Version(); + MSYS_DLL_EXPORT const unsigned int Get_Error_Table_API_Version(); /*! * const unsigned int Common::Get_Error_Table_Size() @@ -139,7 +139,7 @@ namespace Common * * Returns the size of the common error table. */ - const unsigned int Get_Error_Table_Size(); + MSYS_DLL_EXPORT const unsigned int Get_Error_Table_Size(); /*! * const char * Common::Get_Error_Message(const int & errorCode) @@ -152,7 +152,7 @@ namespace Common * Returns a valid pointer if the given error code is in the common error table. * Returns the message for Common_COMMON_UNKNOWN_ERROR otherwise. */ - const char * Get_Error_Message(const int & errorCode); + MSYS_DLL_EXPORT const char * Get_Error_Message(const int & errorCode); }; #endif /* __cplusplus */ From a383b713458fc257102beee2e3be734ec3eab8ed Mon Sep 17 00:00:00 2001 From: codebase7 Date: Sat, 13 Jun 2015 12:04:13 -0400 Subject: [PATCH 024/325] Fix missing link libraries for Common Error Handler. This commit fixes the CMakeLists.txt for Common Error Handler to include the needed link libraries. (A.K.A. Internal Mutex Support for Fatal Error Support.) --- src/Common/Src/Error_Handler/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Common/Src/Error_Handler/CMakeLists.txt b/src/Common/Src/Error_Handler/CMakeLists.txt index 73a53f6..30966b5 100644 --- a/src/Common/Src/Error_Handler/CMakeLists.txt +++ b/src/Common/Src/Error_Handler/CMakeLists.txt @@ -43,7 +43,9 @@ endif(${CMAKE_COMPILER_IS_GNUCC}) # Create the static library. add_library(Common_Error_Handler_Multiverse_Engine_Static STATIC ${COMMON_ERROR_HANDLER_C_INCLUDES} ${COMMON_ERROR_HANDLER_CXX_INCLUDES}) set_property(TARGET Common_Error_Handler_Multiverse_Engine_Static APPEND PROPERTY COMPILE_DEFINITIONS ${COMMON_ERROR_HANDLER_DEFINES}) +target_link_libraries(Common_Error_Handler_Multiverse_Engine_Static ${COMMON_ERROR_HANDLER_STATIC_LINK_LIBS}) # Now the shared library. add_library(Common_Error_Handler_Multiverse_Engine SHARED ${COMMON_ERROR_HANDLER_C_INCLUDES} ${COMMON_ERROR_HANDLER_CXX_INCLUDES}) set_property(TARGET Common_Error_Handler_Multiverse_Engine_Static APPEND PROPERTY COMPILE_DEFINITIONS ${COMMON_ERROR_HANDLER_DEFINES}) +target_link_libraries(Common_Error_Handler_Multiverse_Engine ${COMMON_ERROR_HANDLER_LINK_LIBS}) From f3294ea925fbdfa7871966c85e7889eeaa109d92 Mon Sep 17 00:00:00 2001 From: codebase7 Date: Sat, 13 Jun 2015 12:28:39 -0400 Subject: [PATCH 025/325] Define DLL exports for Dynamic Library Subsystem This commit defines the needed DLL exports for the Dynamic Library Subsystem. --- .../Dynamic_Library_Subsystem.h | 11 +++++++---- .../Dynamic_Library_Subsystem_Data_Structures.h | 4 ++-- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/Common/Src/Dynamic_Library_Subsystem/Dynamic_Library_Subsystem.h b/src/Common/Src/Dynamic_Library_Subsystem/Dynamic_Library_Subsystem.h index d972e8f..8a03248 100644 --- a/src/Common/Src/Dynamic_Library_Subsystem/Dynamic_Library_Subsystem.h +++ b/src/Common/Src/Dynamic_Library_Subsystem/Dynamic_Library_Subsystem.h @@ -22,6 +22,9 @@ #ifndef MSYS_DYNAMIC_LIBRARY_SUBSYSTEM_H #define MSYS_DYNAMIC_LIBRARY_SUBSYSTEM_H +/* Internal includes. */ +#include "../../../DLL_PORT.h" /* Defines MSYS_DLL_EXPORT, and MSYS_DLL_IMPORT_TEMPLATE. */ + /* Check for MSVC. */ #ifdef _MSC_FULL_VER #include "..\stdbool.h" /* bool. (MSVC is special.) */ @@ -72,8 +75,8 @@ extern "C" { * Returns -4 if the given Common_Dynamic_Library_Subsystem_Loaded_Dynamic_Library pointer was NULL. * Returns 1 if the library was already loaded. (Only possible if reloadLibrary is false.) (The value of lib.bLastCallEncounteredAnError will be false in this case as well.) */ - int Common_Dynamic_Library_Subsystem_Load_Library(const char * pathToLibrary, const bool reloadLibrary, - Common_Dynamic_Library_Subsystem_Loaded_Dynamic_Library *const lib); + MSYS_DLL_EXPORT int Common_Dynamic_Library_Subsystem_Load_Library(const char * pathToLibrary, const bool reloadLibrary, + Common_Dynamic_Library_Subsystem_Loaded_Dynamic_Library *const lib); /*! * int Common_Dynamic_Library_Subsystem_Unload_Library(Common_Dynamic_Library_Subsystem_Loaded_Dynamic_Library *const lib) @@ -101,7 +104,7 @@ extern "C" { * Returns -2 if the library unload call returned unsuccessful. * Returns -4 if the given Common_Dynamic_Library_Subsystem_Loaded_Dynamic_Library pointer was NULL. */ - int Common_Dynamic_Library_Subsystem_Unload_Library(Common_Dynamic_Library_Subsystem_Loaded_Dynamic_Library *const lib); + MSYS_DLL_EXPORT int Common_Dynamic_Library_Subsystem_Unload_Library(Common_Dynamic_Library_Subsystem_Loaded_Dynamic_Library *const lib); /*! * void * Common_Dynamic_Library_Subsystem_Get_Symbol(Common_Dynamic_Library_Subsystem_Loaded_Dynamic_Library *const lib, @@ -126,7 +129,7 @@ extern "C" { * Returns a NULL pointer if the lookup failed for some reason. (The value of lib.bLastCallEncounteredAnError will be true in this case.) * Returns a NULL pointer if the given Common_Dynamic_Library_Subsystem_Loaded_Dynamic_Library pointer was NULL. */ - void * Common_Dynamic_Library_Subsystem_Get_Symbol(Common_Dynamic_Library_Subsystem_Loaded_Dynamic_Library *const lib, const char * symbolName); + MSYS_DLL_EXPORT void * Common_Dynamic_Library_Subsystem_Get_Symbol(Common_Dynamic_Library_Subsystem_Loaded_Dynamic_Library *const lib, const char * symbolName); #ifdef __cplusplus } // End of extern C. #endif diff --git a/src/Common/Src/Dynamic_Library_Subsystem/Dynamic_Library_Subsystem_Data_Structures.h b/src/Common/Src/Dynamic_Library_Subsystem/Dynamic_Library_Subsystem_Data_Structures.h index f5beb16..1273b4f 100644 --- a/src/Common/Src/Dynamic_Library_Subsystem/Dynamic_Library_Subsystem_Data_Structures.h +++ b/src/Common/Src/Dynamic_Library_Subsystem/Dynamic_Library_Subsystem_Data_Structures.h @@ -65,7 +65,7 @@ extern "C" { * Returns a pointer to a Common_Dynamic_Library_Subsystem_Loaded_Dynamic_Library data structure if successful. * Otherwise returns NULL. */ - Common_Dynamic_Library_Subsystem_Loaded_Dynamic_Library * Common_Dynamic_Library_Subsystem_Create_Loaded_Dynamic_Library(); + MSYS_DLL_EXPORT Common_Dynamic_Library_Subsystem_Loaded_Dynamic_Library * Common_Dynamic_Library_Subsystem_Create_Loaded_Dynamic_Library(); /*! * void Common_Dynamic_Library_Subsystem_Destroy_Loaded_Dynamic_Library(Common_Dynamic_Library_Subsystem_Loaded_Dynamic_Library * lib) @@ -77,7 +77,7 @@ extern "C" { * * This function has no return. */ - void Common_Dynamic_Library_Subsystem_Destroy_Loaded_Dynamic_Library(Common_Dynamic_Library_Subsystem_Loaded_Dynamic_Library * lib); + MSYS_DLL_EXPORT void Common_Dynamic_Library_Subsystem_Destroy_Loaded_Dynamic_Library(Common_Dynamic_Library_Subsystem_Loaded_Dynamic_Library * lib); #ifdef __cplusplus } // End of extern C. #endif From 63b9628006e2462d4ad609abaf06637f02128c79 Mon Sep 17 00:00:00 2001 From: codebase7 Date: Sat, 13 Jun 2015 13:05:41 -0400 Subject: [PATCH 026/325] Inital commit to the Byte_Order branch This commit is the initial commit to the Byte_Order branch. --- src/Common/Src/Byte_Order.c | 251 ++++ src/Common/Src/Byte_Order.h | 142 ++ src/Common/Src/Byte_Order_Floating_Points.c | 281 ++++ src/Common/Src/Byte_Order_Floating_Points.h | 176 +++ src/Common/Src/Byte_Order_Integers.c | 1340 +++++++++++++++++++ src/Common/Src/Byte_Order_Integers.h | 752 +++++++++++ 6 files changed, 2942 insertions(+) create mode 100644 src/Common/Src/Byte_Order.c create mode 100644 src/Common/Src/Byte_Order.h create mode 100644 src/Common/Src/Byte_Order_Floating_Points.c create mode 100644 src/Common/Src/Byte_Order_Floating_Points.h create mode 100644 src/Common/Src/Byte_Order_Integers.c create mode 100644 src/Common/Src/Byte_Order_Integers.h diff --git a/src/Common/Src/Byte_Order.c b/src/Common/Src/Byte_Order.c new file mode 100644 index 0000000..9246a9c --- /dev/null +++ b/src/Common/Src/Byte_Order.c @@ -0,0 +1,251 @@ +/*! + Multiverse Engine Project 03/6/2015 Common Byte_Order.c + + Copyright (C) 2015 Multiverse Engine Project + + This program is free software; + you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this program; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Official source repository and project information can be found at + https://github.com/codebase7/mengine +*/ + +/* Include header */ +#include "Byte_Order.h" + +/* Check for C++ compiler. */ +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +int Common_Byte_Swap(char * data, const size_t dataLength) +{ + /* Init ret. */ + int ret = COMMON_ERROR_UNKNOWN_ERROR; /* The result of this function. */ + size_t x = 0; /* Counter used in the swap loop. */ + char tempByte = '\0'; /* Temporary memory storage for a byte being swapped out. */ + + /* Check for invalid arguments. */ + if ((data != NULL) && ((dataLength % 2) == 0)) + { + /* Begin swap loop. */ + for (x = 0; (x < (dataLength / 2)); x++) + { + /* + * Each bit is swapped with it's partner on the other side of the array. + * I.e. Each byte from x distance from the start of the array is swapped + * with the byte x distance from the end of the array. + */ + tempByte = data[x]; + data[x] = data[((dataLength - 1) - x)]; + data[((dataLength - 1) - x)] = tempByte; + } + + /* Done! */ + ret = COMMON_ERROR_SUCCESS; + } + else + { + /* Invalid arguments. */ + ret = COMMON_ERROR_INVALID_ARGUMENT; + } + + /* Exit function. */ + return ret; +} + +int Common_Print_Bytes_To_CString(const char * data, const size_t dataLength, char ** retStr, size_t * retStrSize, const size_t base, const size_t width, const char fillValue, const bool spaceBetweenBytes) +{ + /* Init vars. */ + int ret = COMMON_ERROR_UNKNOWN_ERROR; /* The result of this function. */ + size_t x = 0; /* Counter used in the print and spacing loops. */ + size_t byteValueCount = 0; /* Used to keep track of how many bytes we have outputted for the current byte. */ + unsigned char currentByte = '\0'; /* Temporary value used to store the current byte we are working on. */ + char outputValue = '\0'; /* The value that we need to write into the output buffer. (Calculated from currentValue.) */ + char * outputBuffer = NULL; /* Pointer to the c-string that will be outputted to the standard output. */ + char * previousOutputBuffer = NULL; /* Temporary pointer used to copy previously generated data into the current outputBuffer. */ + const char outputValues[17] = "0123456789ABCDEF"; /* C-String used to map a generated value to it's corrosponding character. */ + size_t outputBufferSize = 1; /* Current size of the outputBuffer. Set to one by default to allow the string to be NULL terminated. */ + + /* Check for invalid arguments. */ + if ((data != NULL) && (dataLength > 0) && (retStr != NULL) && (retStrSize != NULL) && (base >= 2) && (base <= 16)) + { + /* Begin data print loop. */ + for (x = 0; ((x < dataLength) && (ret != COMMON_ERROR_MEMORY_ERROR)); x++) + { + /* Copy current value. */ + currentByte = data[((dataLength - 1) - x)]; + + /* Reset byte value count. */ + byteValueCount = 0; + + /* Begin value parsing loop. */ + do + { + /* Read the current byte's value from right to left. (Mod is a reduction operation.) */ + outputValue = (currentByte % base); + + /* Copy the current buffer's pointer because we are about to create a new one. */ + previousOutputBuffer = outputBuffer; + + /* Increment the size of the new buffer. */ + outputBufferSize++; + + /* Allocate the new buffer. */ + outputBuffer = (char*)malloc(outputBufferSize); + + /* Check for successful memory allocation. */ + if (outputBuffer != NULL) + { + /* Blank out the new buffer. */ + memset(outputBuffer, '\0', outputBufferSize); + + /* Set the first value as the previous data comes after it. */ + outputBuffer[0] = outputValues[outputValue]; + + /* If we have any previous data we need to copy it into the new buffer and deallocate the previous one. */ + if (previousOutputBuffer != NULL) + { + memcpy((outputBuffer + 1), previousOutputBuffer, (outputBufferSize - 1)); + free(previousOutputBuffer); + previousOutputBuffer = NULL; + } + + /* Increment byte value count. */ + byteValueCount++; + + /* Get the next value by choping off the "ones place", aka devide by the current base. */ + currentByte /= base; + } + else + { + /* Could not allocate memory for output buffer. */ + ret = COMMON_ERROR_MEMORY_ERROR; + } + }while ((currentByte) && (ret != COMMON_ERROR_MEMORY_ERROR)); + + /* Check and see if the generated values used up all of the requested width. */ + if ((ret != COMMON_ERROR_MEMORY_ERROR) && (outputBuffer != NULL) && (byteValueCount < width)) + { + /* Copy the current buffer's pointer because we are about to create a new one. */ + previousOutputBuffer = outputBuffer; + + /* Increment the output buffer size by the remaining filler we need to add. */ + outputBufferSize += (width - byteValueCount); + + /* Allocate the new buffer. */ + outputBuffer = (char*)malloc(outputBufferSize); + + /* Check for successful memory allocation. */ + if (outputBuffer != NULL) + { + /* Blank out the new buffer. */ + memset(outputBuffer, '\0', outputBufferSize); + + /* Put in our filler. */ + memset(outputBuffer, fillValue, (width - byteValueCount)); + + /* If we have any previous data we need to copy it into the new buffer and deallocate the previous one. */ + if (previousOutputBuffer != NULL) + { + memcpy((outputBuffer + (width - byteValueCount)), previousOutputBuffer, (outputBufferSize - (width - byteValueCount))); + free(previousOutputBuffer); + previousOutputBuffer = NULL; + } + } + else + { + /* Could not allocate memory for output buffer. */ + ret = COMMON_ERROR_MEMORY_ERROR; + } + } + + /* Insert spacing if needed. */ + if ((spaceBetweenBytes) && (ret != COMMON_ERROR_MEMORY_ERROR) && (outputBuffer != NULL) && ((x + 1) < dataLength)) + { + /* Copy the current buffer's pointer because we are about to create a new one. */ + previousOutputBuffer = outputBuffer; + + /* Increment the output buffer size. */ + outputBufferSize++; + + /* Allocate the new buffer. */ + outputBuffer = (char*)malloc(outputBufferSize); + + /* Check for successful memory allocation. */ + if (outputBuffer != NULL) + { + /* Blank out the new buffer. */ + memset(outputBuffer, '\0', outputBufferSize); + + /* Insert our space. */ + outputBuffer[0] = ' '; + + /* Copy the original buffer. */ + memcpy((outputBuffer + 1), previousOutputBuffer, (outputBufferSize - 1)); + } + else + { + /* Could not allocate memory for output buffer. */ + ret = COMMON_ERROR_MEMORY_ERROR; + } + } + } + + /* Check for NULL output buffer. */ + if ((ret != COMMON_ERROR_MEMORY_ERROR) && (outputBuffer != NULL) && (outputBufferSize > 0)) + { + /* Copy the outputBuffer pointer to retStr. */ + (*retStr) = outputBuffer; + + /* Copy outputBufferSize to retStrSize. */ + (*retStrSize) = outputBufferSize; + + /* Done! */ + ret = COMMON_ERROR_SUCCESS; + } + } + else + { + /* Invalid arguments. */ + ret = COMMON_ERROR_INVALID_ARGUMENT; + } + + /* Exit function. */ + return ret; +} + +void Common_Deallocate_Print_Bytes_CString(char ** str) +{ + /* Check for NULL. */ + if (str != NULL) + { + free((*str)); + (*str) = NULL; + } + + /* Exit function. */ + return; +} + +int Common_Print_Bytes_In_Hex(const char * data, const size_t dataLength, char ** retStr, size_t * retStrSize, const bool spaceBetweenBytes) +{ + return Common_Print_Bytes_To_CString(data, dataLength, retStr, retStrSize, 16, 2, '0', spaceBetweenBytes); +} + +int Common_Print_Bytes_In_Binary(const char * data, const size_t dataLength, char ** retStr, size_t * retStrSize, const bool spaceBetweenBytes) +{ + return Common_Print_Bytes_To_CString(data, dataLength, retStr, retStrSize, 2, 8, '0', spaceBetweenBytes); +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ diff --git a/src/Common/Src/Byte_Order.h b/src/Common/Src/Byte_Order.h new file mode 100644 index 0000000..1a1837d --- /dev/null +++ b/src/Common/Src/Byte_Order.h @@ -0,0 +1,142 @@ +/*! + Multiverse Engine Project 03/6/2015 Common Byte_Order.h + + Copyright (C) 2015 Multiverse Engine Project + + This program is free software; + you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this program; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Official source repository and project information can be found at + https://github.com/codebase7/mengine +*/ + +/* Include guard. */ +#ifndef MSYS_BYTE_ORDER_H +#define MSYS_BYTE_ORDER_H + +/* Check for C++ compiler. */ +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Define Endianness Result Values. */ +#define MSYS_BIG_ENDIAN 0 +#define MSYS_LITTLE_ENDIAN 1 +#define MSYS_UNKNOWN_ENDIANNESS 2 + +/* Internal headers. */ +#include "Byte_Order_Integers.h" +#include "Byte_Order_Floating_Points.h" + +/*! + * int Common_Byte_Swap(char * data, const size_t dataLength) + * + * Swaps the given bytes by swapping each byte + * with it's complement on the other end of the + * byte string. + * + * I.e. Each byte from x distance from the start of the string is swapped + * with the byte x distance from the end of the string. + * + * Note: This function expects that the amount of data given to it + * is a multiple of 2. Also this function will alter the given + * data in-place. (I.e. If an error occurs, the data WILL be altered.) + * + * Returns COMMON_ERROR_SUCCESS if swapping was successful. + * + * Returns COMMON_ERROR_INVALID_ARGUMENT if the given pointer is + * NULL, or if the data length is not a multiple of 2. + * + * Otherwise returns the appropriate error code. + */ +int Common_Byte_Swap(char * data, const size_t dataLength); + +/*! + * int Common_Print_Bytes_To_CString(const char * data, const size_t dataLength, char ** retStr, size_t * retStrSize, const size_t base, + * const size_t width, const char fillValue, const bool spaceBetweenBytes) + * + * Converts a given byte string to a printable (NULL-terminated) and human-readable string in the given base. + * + * @pram data: the byte string to convert. + * @pram dataLength: the length of the byte string. + * @pram retStr: a double pointer that will point to the converted string. + * @pram retStrSize: the size of the generated string. + * @pram base: the numerical base to convert each byte to. + * + * @pram width: the minimal number of values to print for each byte. (Note the minimal keyword. The value will not be truncated if it + * requires more than width characters to represent it. This is solely to make smaller values take up more space for more uniform value + * representation.) + * + * @pram fillValue: the value printed in the converted string to take up the extra space, when a byte's value representation is smaller + * than the given width. (E.x. the byte value is 0, width is 3, and fillValue is '.': "..0" would be the result.) + * + * @pram spaceBetweenBytes: Whether or not to insert a space character after each of the converted byte values. (Readability.) + * + * WARNING: If retStr is non-NULL when this function is called, and this function returns COMMON_ERROR_SUCCESS, then the pointer will + * be overwritten without being deallocated. If you need that pointer to deallocate it later, you should copy it elsewhere before calling + * this function. + * + * Note: To deallocate the returned string from this function, pass the returned string to Common_Deallocate_Print_Bytes_CString(). + * + * Returns COMMON_ERROR_SUCCESS if the conversion is successful. + * Returns COMMON_ERROR_INVALID_ARGUMENT if the given pointers are NULL, or if the given base is not a value between 2 and 16. + * Returns COMMON_ERROR_MEMORY_ERROR if a memory allocation fails. + * + * In case of error, (the returned error code is not COMMON_ERROR_SUCCESS, then the given arguments will NOT be altered by this function. + */ +int Common_Print_Bytes_To_CString(const char * data, const size_t dataLength, char ** retStr, size_t * retStrSize, const size_t base, const size_t width, const char fillValue, const bool spaceBetweenBytes); + +/*! + * void Common_Deallocate_Print_Bytes_CString(char ** str) + * + * Deallocates the given c-string and sets the given pointer to char to NULL. + * + * Note: This function is a destructor function for strings made by Common_Print_Bytes_To_CString() and + * should ONLY be used for that purpose. The behaviour for using this function to deallocate other allocations is undefined. + * + * This function has no return. If a given pointer is NULL, this function will silently fail. + */ +void Common_Deallocate_Print_Bytes_CString(char ** str); + +/*! + * int Common_Print_Bytes_In_Hex(const char * data, const size_t dataLength, char ** retStr, size_t * retStrSize, const bool spaceBetweenBytes) + * + * Wrapper function around Common_Print_Bytes_To_CString() for converting a byte string to a human-readable hexadecimal string. + * Example output: ("001FAC" if spacing is disabled, "00 1F AC" if spacing is enabled.) + * + * Note: This function is to make calls shorter, if you want more control over the output, call Common_Print_Bytes_To_CString() directly. + * + * All arguments and return values are identical to their Common_Print_Bytes_To_CString() counterparts. See Common_Print_Bytes_To_CString() + * for their descriptions. + */ +int Common_Print_Bytes_In_Hex(const char * data, const size_t dataLength, char ** retStr, size_t * retStrSize, const bool spaceBetweenBytes); + +/*! + * int Common_Print_Bytes_In_Binary(const char * data, const size_t dataLength, char ** retStr, size_t * retStrSize, + * const bool spaceBetweenBytes) + * + * Wrapper function around Common_Print_Bytes_To_CString() for converting a byte string to a human-readable binary string. + * Example output: ("00000101000001010000010100000101" if spacing is disabled, "00000101 00000101 00000101 00000101" if spacing is enabled.) + * + * Note: This function is to make calls shorter, if you want more control over the output, call Common_Print_Bytes_To_CString() directly. + * + * All arguments and return values are identical to their Common_Print_Bytes_To_CString() counterparts. See Common_Print_Bytes_To_CString() + * for their descriptions. + */ +int Common_Print_Bytes_In_Binary(const char * data, const size_t dataLength, char ** retStr, size_t * retStrSize, const bool spaceBetweenBytes); + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ + +#endif /* MSYS_BYTE_ORDER_H */ + +/* End of Byte_Order.h */ diff --git a/src/Common/Src/Byte_Order_Floating_Points.c b/src/Common/Src/Byte_Order_Floating_Points.c new file mode 100644 index 0000000..c6dabe1 --- /dev/null +++ b/src/Common/Src/Byte_Order_Floating_Points.c @@ -0,0 +1,281 @@ +/*! + Multiverse Engine Project 09/6/2015 Common Byte_Order_Floating_Points.c + + Copyright (C) 2015 Multiverse Engine Project + + This program is free software; + you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this program; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Official source repository and project information can be found at + https://github.com/codebase7/mengine +*/ + +/* Include main header. */ +#include "Byte_Order.h" + +/* Check for C++ compiler. */ +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +int Common_Host_To_Big_Endian_Float(float * f) +{ + /* Init vars. */ + int ret = COMMON_ERROR_UNKNOWN_ERROR; /* The result of this function. */ + + /* Check host's endianness. */ + ret = Common_FLOAT_Endianness_Check(); + if (ret != MSYS_BIG_ENDIAN) + { + /* Check for valid endianness. */ + if (ret == MSYS_LITTLE_ENDIAN) + { + /* Check for invalid arguments. */ + if (f != NULL) + { + /* Call Common_Byte_Swap(). */ + ret = Common_Byte_Swap(((char*)f), sizeof (float)); + } + else + { + /* Invalid arguments. */ + ret = COMMON_ERROR_INVALID_ARGUMENT; + } + } + else + { + /* Host endianness is unknown. Cannot convert unknown endianness. */ + ret = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; + } + } + else + { + /* + * This value should already be in the correct byte order, + * as the host is big endian. + */ + ret = COMMON_ERROR_SUCCESS; + } + + /* Exit function. */ + return ret; +} + +int Common_Big_Endian_To_Host_Float(float * f) +{ + /* Init vars. */ + int ret = COMMON_ERROR_UNKNOWN_ERROR; /* The result of this function. */ + + /* Check host's endianness. */ + ret = Common_FLOAT_Endianness_Check(); + if (ret != MSYS_BIG_ENDIAN) + { + /* Check for valid endianness. */ + if (ret == MSYS_LITTLE_ENDIAN) + { + /* Check for invalid arguments. */ + if (f != NULL) + { + /* + * Call Common_Byte_Swap(). + * + * (We could call Common_Host_To_Big_Endian_Float() here, but + * that would just repeat the calls above. Plus we may not be able + * to do that on all systems.) + */ + ret = Common_Byte_Swap(((char*)f), sizeof (float)); + } + else + { + /* Invalid arguments. */ + ret = COMMON_ERROR_INVALID_ARGUMENT; + } + } + else + { + /* Host endianness is unknown. Cannot convert unknown endianness. */ + ret = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; + } + } + else + { + /* + * This value should already be in the correct byte order, + * as the host is big endian. + */ + ret = COMMON_ERROR_SUCCESS; + } + + /* Exit function. */ + return ret; +} + +int Common_Host_To_Big_Endian_Double(double * d) +{ + /* Init vars. */ + int ret = COMMON_ERROR_UNKNOWN_ERROR; /* The result of this function. */ + + /* Check host's endianness. */ + ret = Common_DOUBLE_Endianness_Check(); + if (ret != MSYS_BIG_ENDIAN) + { + /* Check for valid endianness. */ + if (ret == MSYS_LITTLE_ENDIAN) + { + /* Check for invalid arguments. */ + if (d != NULL) + { + /* Call Common_Byte_Swap(). */ + ret = Common_Byte_Swap(((char*)d), sizeof (double)); + } + else + { + /* Invalid arguments. */ + ret = COMMON_ERROR_INVALID_ARGUMENT; + } + } + else + { + /* Host endianness is unknown. Cannot convert unknown endianness. */ + ret = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; + } + } + else + { + /* + * This value should already be in the correct byte order, + * as the host is big endian. + */ + ret = COMMON_ERROR_SUCCESS; + } + + /* Exit function. */ + return ret; +} + +int Common_Big_Endian_To_Host_Double(double * d) +{ + /* Init vars. */ + int ret = COMMON_ERROR_UNKNOWN_ERROR; /* The result of this function. */ + + /* Check host's endianness. */ + ret = Common_DOUBLE_Endianness_Check(); + if (ret != MSYS_BIG_ENDIAN) + { + /* Check for valid endianness. */ + if (ret == MSYS_LITTLE_ENDIAN) + { + /* Check for invalid arguments. */ + if (d != NULL) + { + /* + * Call Common_Byte_Swap(). + * + * (We could call Common_Host_To_Big_Endian_Double() here, but + * that would just repeat the calls above. Plus we may not be able + * to do that on all systems.) + */ + ret = Common_Byte_Swap(((char*)d), sizeof (double)); + } + else + { + /* Invalid arguments. */ + ret = COMMON_ERROR_INVALID_ARGUMENT; + } + } + else + { + /* Host endianness is unknown. Cannot convert unknown endianness. */ + ret = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; + } + } + else + { + /* + * This value should already be in the correct byte order, + * as the host is big endian. + */ + ret = COMMON_ERROR_SUCCESS; + } + + /* Exit function. */ + return ret; +} + +int Common_FLOAT_Endianness_Check() +{ + /* Init vars. */ + int ret = MSYS_UNKNOWN_ENDIANNESS; /* The result of this function. */ + float t = 1.0; /* Variable to check. */ + + /* Cast t to a char string and see if the first 2 values are 0x3F80. */ + if ((((char*)&t)[0] == 0x3F) && ((((char*)&t)[1] == 0x80))) + { + /* The first 2 bytes are 0x3F80 so it's big endian. */ + ret = MSYS_BIG_ENDIAN; + } + else + { + /* + * The first check did not pass, so check and see if the last 2 bytes are 0x803F. + * If they are, then the host is little endian. + * + * Otherwise the host is using something like middle-endian to store + * the value, but we would need more checks to determine what exact + * kind of endianness the host is using. + */ + if ((((char*)&t)[(sizeof (float) - 1)] == 0x80) && ((((char*)&t)[(sizeof (float) - 2)] == 0x3F))) + { + /* It's little endian. */ + ret = MSYS_LITTLE_ENDIAN; + } + } + + /* Return the result. */ + return ret; +} + +int Common_DOUBLE_Endianness_Check() +{ + /* Init vars. */ + int ret = MSYS_UNKNOWN_ENDIANNESS; /* The result of this function. */ + double t = 1.0; /* Variable to check. */ + + /* Cast t to a char string and see if the first 2 values are 0x3FF0. */ + if ((((char*)&t)[0] == 0x3F) && ((((char*)&t)[1] == 0xF0))) + { + /* The first 2 bytes are 0x3F80 so it's big endian. */ + ret = MSYS_BIG_ENDIAN; + } + else + { + /* + * The first check did not pass, so check and see if the last 2 bytes are 0xF03F. + * If they are, then the host is little endian. + * + * Otherwise the host is using something like middle-endian to store + * the value, but we would need more checks to determine what exact + * kind of endianness the host is using. + */ + if ((((char*)&t)[(sizeof (double) - 1)] == 0xF0) && ((((char*)&t)[(sizeof (double) - 2)] == 0x3F))) + { + /* It's little endian. */ + ret = MSYS_LITTLE_ENDIAN; + } + } + + /* Return the result. */ + return ret; +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ diff --git a/src/Common/Src/Byte_Order_Floating_Points.h b/src/Common/Src/Byte_Order_Floating_Points.h new file mode 100644 index 0000000..394abcb --- /dev/null +++ b/src/Common/Src/Byte_Order_Floating_Points.h @@ -0,0 +1,176 @@ +/*! + Multiverse Engine Project 09/6/2015 Common Byte_Order_Floating_Points.h + + Copyright (C) 2015 Multiverse Engine Project + + This program is free software; + you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this program; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Official source repository and project information can be found at + https://github.com/codebase7/mengine +*/ + +/* Include guard. */ +#ifndef MSYS_BYTE_ORDER_FLAOTING_POINTS_H +#define MSYS_BYTE_ORDER_FLAOTING_POINTS_H + +/* Make sure we are not included directly. */ +#ifndef MSYS_BYTE_ORDER_H +#error "You should not include __FILE__ directly, it is included automatically by Byte_Order.h, remove this include. Aborting build." +#endif + +/* Check for C++ compiler. */ +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/*! + * int Common_Host_To_Big_Endian_Float(float * f) + * + * Converts a given FLOAT value from the host's endianness + * to Big Endian format. + * + * Returns COMMON_ERROR_SUCCESS, if the conversion is successful, + * (data will be converted after call returns), + * or if the host is a Big Endian host. (In such case no data alteration + * is performed.) + * + * Returns COMMON_ERROR_INVALID_ARGUMENT if the given pointer is NULL. + * + * Returns COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED if the given data type's + * byte ordering is unknown for the given host. + * + * In case of error, (returned error code is not COMMON_ERROR_SUCCESS), + * all arguments will be left unaltered. + */ +int Common_Host_To_Big_Endian_Float(float * f); + +/*! + * int Common_Big_Endian_To_Host_Float(float * f) + * + * Converts a given FLOAT value from Big Endian format + * to the host's endianness format. + * + * Returns COMMON_ERROR_SUCCESS, if the conversion is successful, + * (data will be converted after call returns), + * or if the host is a Big Endian host. (In such case no data alteration + * is performed.) + * + * Returns COMMON_ERROR_INVALID_ARGUMENT if the given pointer is NULL. + * + * Returns COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED if the given data type's + * byte ordering is unknown for the given host. + * + * In case of error, (returned error code is not COMMON_ERROR_SUCCESS), + * all arguments will be left unaltered. + */ +int Common_Big_Endian_To_Host_Float(float * f); + +/*! + * int Common_Host_To_Big_Endian_DOUBLE(double * d) + * + * Converts a given DOUBLE value from the host's endianness + * to Big Endian format. + * + * Returns COMMON_ERROR_SUCCESS, if the conversion is successful, + * (data will be converted after call returns), + * or if the host is a Big Endian host. (In such case no data alteration + * is performed.) + * + * Returns COMMON_ERROR_INVALID_ARGUMENT if the given pointer is NULL. + * + * Returns COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED if the given data type's + * byte ordering is unknown for the given host. + * + * In case of error, (returned error code is not COMMON_ERROR_SUCCESS), + * all arguments will be left unaltered. + */ +int Common_Host_To_Big_Endian_Double(double * d); + +/*! + * int Common_Big_Endian_To_Host_Double(double * d) + * + * Converts a given DOUBLE value from Big Endian format + * to the host's endianness format. + * + * Returns COMMON_ERROR_SUCCESS, if the conversion is successful, + * (data will be converted after call returns), + * or if the host is a Big Endian host. (In such case no data alteration + * is performed.) + * + * Returns COMMON_ERROR_INVALID_ARGUMENT if the given pointer is NULL. + * + * Returns COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED if the given data type's + * byte ordering is unknown for the given host. + * + * In case of error, (returned error code is not COMMON_ERROR_SUCCESS), + * all arguments will be left unaltered. + */ +int Common_Big_Endian_To_Host_Double(double * d); + +/*! + * General Definitions for the Common_*_Endianness_Check() functions: + * + * The functions below all contain the same returns, + * and purpose. + */ + +/*! + * int Common_FLOAT_Endianness_Check() + * + * Template function which checks the host's endianness for the + * FLOAT data type. + * + * Note: This function is the equivalent of calling + * DataProcess_Endianness_Check() with a signed FLOAT argument. + * This function is here for the purpose of making it easier + * to use C code. + * + * Returns MSYS_BIG_ENDIAN if the given data type is stored as big + * endian on the host machine. + * + * Returns MSYS_LITTLE_ENDIAN if the given data type stored as little + * endian on the host machine. + * + * Returns MSYS_UNKNOWN_ENDIANNESS if the given data type's byte ordering + * is unknown for the given host. + */ +int Common_FLOAT_Endianness_Check(); + +/*! + * int Common_DOUBLE_Endianness_Check() + * + * Template function which checks the host's endianness for the + * DOUBLE data type. + * + * Note: This function is the equivalent of calling + * DataProcess_Endianness_Check() with a signed DOUBLE argument. + * This function is here for the purpose of making it easier + * to use C code. + * + * Returns MSYS_BIG_ENDIAN if the given data type is stored as big + * endian on the host machine. + * + * Returns MSYS_LITTLE_ENDIAN if the given data type stored as little + * endian on the host machine. + * + * Returns MSYS_UNKNOWN_ENDIANNESS if the given data type's byte ordering + * is unknown for the given host. + */ +int Common_DOUBLE_Endianness_Check(); + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ + +#endif /* MSYS_BYTE_ORDER_FLAOTING_POINTS_H */ + +/* End of Byte_Order_Floating_Points.h */ diff --git a/src/Common/Src/Byte_Order_Integers.c b/src/Common/Src/Byte_Order_Integers.c new file mode 100644 index 0000000..6d0149d --- /dev/null +++ b/src/Common/Src/Byte_Order_Integers.c @@ -0,0 +1,1340 @@ +/*! + Multiverse Engine Project 09/6/2015 Common Byte_Order_Integers.c + + Copyright (C) 2015 Multiverse Engine Project + + This program is free software; + you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this program; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Official source repository and project information can be found at + https://github.com/codebase7/mengine +*/ + +/* Include main header. */ +#include "Byte_Order.h" + +/* Check for C++ compiler. */ +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +int Common_Host_To_Big_Endian_UChar(unsigned char * uc) +{ + /* Init vars. */ + int ret = COMMON_ERROR_UNKNOWN_ERROR; /* The result of this function. */ + + /* Check host's endianness. */ + ret = Common_UCHAR_Endianness_Check(); + if (ret != MSYS_BIG_ENDIAN) + { + /* Check for valid endianness. */ + if (ret == MSYS_LITTLE_ENDIAN) + { + /* Check for invalid arguments. */ + if (uc != NULL) + { + /* Call Common_Byte_Swap(). */ + ret = Common_Byte_Swap(((char*)uc), sizeof (unsigned char)); + } + else + { + /* Invalid arguments. */ + ret = COMMON_ERROR_INVALID_ARGUMENT; + } + } + else + { + /* Host endianness is unknown. Cannot convert unknown endianness. */ + ret = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; + } + } + else + { + /* + * This value should already be in the correct byte order, + * as the host is big endian. + */ + ret = COMMON_ERROR_SUCCESS; + } + + /* Exit function. */ + return ret; +} + +int Common_Big_Endian_To_Host_UChar(unsigned char * uc) +{ + /* Init vars. */ + int ret = COMMON_ERROR_UNKNOWN_ERROR; /* The result of this function. */ + + /* Check host's endianness. */ + ret = Common_UCHAR_Endianness_Check(); + if (ret != MSYS_BIG_ENDIAN) + { + /* Check for valid endianness. */ + if (ret == MSYS_LITTLE_ENDIAN) + { + /* Check for invalid arguments. */ + if (uc != NULL) + { + /* Call Common_Byte_Swap(). */ + ret = Common_Byte_Swap(((char*)uc), sizeof (unsigned char)); + } + else + { + /* Invalid arguments. */ + ret = COMMON_ERROR_INVALID_ARGUMENT; + } + } + else + { + /* Host endianness is unknown. Cannot convert unknown endianness. */ + ret = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; + } + } + else + { + /* + * This value should already be in the correct byte order, + * as the host is big endian. + */ + ret = COMMON_ERROR_SUCCESS; + } + + /* Exit function. */ + return ret; +} + +int Common_Host_To_Big_Endian_Char(char * c) +{ + /* Init vars. */ + int ret = COMMON_ERROR_UNKNOWN_ERROR; /* The result of this function. */ + + /* Check host's endianness. */ + ret = Common_CHAR_Endianness_Check(); + if (ret != MSYS_BIG_ENDIAN) + { + /* Check for valid endianness. */ + if (ret == MSYS_LITTLE_ENDIAN) + { + /* Check for invalid arguments. */ + if (c != NULL) + { + /* Call Common_Byte_Swap(). */ + ret = Common_Byte_Swap(((char*)c), sizeof (char)); + } + else + { + /* Invalid arguments. */ + ret = COMMON_ERROR_INVALID_ARGUMENT; + } + } + else + { + /* Host endianness is unknown. Cannot convert unknown endianness. */ + ret = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; + } + } + else + { + /* + * This value should already be in the correct byte order, + * as the host is big endian. + */ + ret = COMMON_ERROR_SUCCESS; + } + + /* Exit function. */ + return ret; +} + +int Common_Big_Endian_To_Host_Char(char * c) +{ + /* Init vars. */ + int ret = COMMON_ERROR_UNKNOWN_ERROR; /* The result of this function. */ + + /* Check host's endianness. */ + ret = Common_CHAR_Endianness_Check(); + if (ret != MSYS_BIG_ENDIAN) + { + /* Check for valid endianness. */ + if (ret == MSYS_LITTLE_ENDIAN) + { + /* Check for invalid arguments. */ + if (c != NULL) + { + /* Call Common_Byte_Swap(). */ + ret = Common_Byte_Swap(((char*)c), sizeof (char)); + } + else + { + /* Invalid arguments. */ + ret = COMMON_ERROR_INVALID_ARGUMENT; + } + } + else + { + /* Host endianness is unknown. Cannot convert unknown endianness. */ + ret = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; + } + } + else + { + /* + * This value should already be in the correct byte order, + * as the host is big endian. + */ + ret = COMMON_ERROR_SUCCESS; + } + + /* Exit function. */ + return ret; +} + +int Common_Host_To_Big_Endian_UShort(unsigned short * us) +{ + /* Init vars. */ + int ret = COMMON_ERROR_UNKNOWN_ERROR; /* The result of this function. */ + + /* Check host's endianness. */ + ret = Common_USHORT_Endianness_Check(); + if (ret != MSYS_BIG_ENDIAN) + { + /* Check for valid endianness. */ + if (ret == MSYS_LITTLE_ENDIAN) + { + /* Check for invalid arguments. */ + if (us != NULL) + { + /* Call Common_Byte_Swap(). */ + ret = Common_Byte_Swap(((char*)us), sizeof (unsigned short)); + } + else + { + /* Invalid arguments. */ + ret = COMMON_ERROR_INVALID_ARGUMENT; + } + } + else + { + /* Host endianness is unknown. Cannot convert unknown endianness. */ + ret = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; + } + } + else + { + /* + * This value should already be in the correct byte order, + * as the host is big endian. + */ + ret = COMMON_ERROR_SUCCESS; + } + + /* Exit function. */ + return ret; +} + +int Common_Big_Endian_To_Host_UShort(unsigned short * us) +{ + /* Init vars. */ + int ret = COMMON_ERROR_UNKNOWN_ERROR; /* The result of this function. */ + + /* Check host's endianness. */ + ret = Common_USHORT_Endianness_Check(); + if (ret != MSYS_BIG_ENDIAN) + { + /* Check for valid endianness. */ + if (ret == MSYS_LITTLE_ENDIAN) + { + /* Check for invalid arguments. */ + if (us != NULL) + { + /* Call Common_Byte_Swap(). */ + ret = Common_Byte_Swap(((char*)us), sizeof (unsigned short)); + } + else + { + /* Invalid arguments. */ + ret = COMMON_ERROR_INVALID_ARGUMENT; + } + } + else + { + /* Host endianness is unknown. Cannot convert unknown endianness. */ + ret = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; + } + } + else + { + /* + * This value should already be in the correct byte order, + * as the host is big endian. + */ + ret = COMMON_ERROR_SUCCESS; + } + + /* Exit function. */ + return ret; +} + +int Common_Host_To_Big_Endian_Short(short * s) +{ + /* Init vars. */ + int ret = COMMON_ERROR_UNKNOWN_ERROR; /* The result of this function. */ + + /* Check host's endianness. */ + ret = Common_SHORT_Endianness_Check(); + if (ret != MSYS_BIG_ENDIAN) + { + /* Check for valid endianness. */ + if (ret == MSYS_LITTLE_ENDIAN) + { + /* Check for invalid arguments. */ + if (s != NULL) + { + /* Call Common_Byte_Swap(). */ + ret = Common_Byte_Swap(((char*)s), sizeof (short)); + } + else + { + /* Invalid arguments. */ + ret = COMMON_ERROR_INVALID_ARGUMENT; + } + } + else + { + /* Host endianness is unknown. Cannot convert unknown endianness. */ + ret = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; + } + } + else + { + /* + * This value should already be in the correct byte order, + * as the host is big endian. + */ + ret = COMMON_ERROR_SUCCESS; + } + + /* Exit function. */ + return ret; +} + +int Common_Big_Endian_To_Host_Short(short * s) +{ + /* Init vars. */ + int ret = COMMON_ERROR_UNKNOWN_ERROR; /* The result of this function. */ + + /* Check host's endianness. */ + ret = Common_SHORT_Endianness_Check(); + if (ret != MSYS_BIG_ENDIAN) + { + /* Check for valid endianness. */ + if (ret == MSYS_LITTLE_ENDIAN) + { + /* Check for invalid arguments. */ + if (s != NULL) + { + /* Call Common_Byte_Swap(). */ + ret = Common_Byte_Swap(((char*)s), sizeof (short)); + } + else + { + /* Invalid arguments. */ + ret = COMMON_ERROR_INVALID_ARGUMENT; + } + } + else + { + /* Host endianness is unknown. Cannot convert unknown endianness. */ + ret = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; + } + } + else + { + /* + * This value should already be in the correct byte order, + * as the host is big endian. + */ + ret = COMMON_ERROR_SUCCESS; + } + + /* Exit function. */ + return ret; +} + +int Common_Host_To_Big_Endian_UInt(unsigned int * ui) +{ + /* Init vars. */ + int ret = COMMON_ERROR_UNKNOWN_ERROR; /* The result of this function. */ + + /* Check host's endianness. */ + ret = Common_UINT_Endianness_Check(); + if (ret != MSYS_BIG_ENDIAN) + { + /* Check for valid endianness. */ + if (ret == MSYS_LITTLE_ENDIAN) + { + /* Check for invalid arguments. */ + if (ui != NULL) + { + /* Call Common_Byte_Swap(). */ + ret = Common_Byte_Swap(((char*)ui), sizeof (unsigned int)); + } + else + { + /* Invalid arguments. */ + ret = COMMON_ERROR_INVALID_ARGUMENT; + } + } + else + { + /* Host endianness is unknown. Cannot convert unknown endianness. */ + ret = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; + } + } + else + { + /* + * This value should already be in the correct byte order, + * as the host is big endian. + */ + ret = COMMON_ERROR_SUCCESS; + } + + /* Exit function. */ + return ret; +} + +int Common_Big_Endian_To_Host_UInt(unsigned int * ui) +{ + /* Init vars. */ + int ret = COMMON_ERROR_UNKNOWN_ERROR; /* The result of this function. */ + + /* Check host's endianness. */ + ret = Common_UINT_Endianness_Check(); + if (ret != MSYS_BIG_ENDIAN) + { + /* Check for valid endianness. */ + if (ret == MSYS_LITTLE_ENDIAN) + { + /* Check for invalid arguments. */ + if (ui != NULL) + { + /* Call Common_Byte_Swap(). */ + ret = Common_Byte_Swap(((char*)ui), sizeof (unsigned int)); + } + else + { + /* Invalid arguments. */ + ret = COMMON_ERROR_INVALID_ARGUMENT; + } + } + else + { + /* Host endianness is unknown. Cannot convert unknown endianness. */ + ret = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; + } + } + else + { + /* + * This value should already be in the correct byte order, + * as the host is big endian. + */ + ret = COMMON_ERROR_SUCCESS; + } + + /* Exit function. */ + return ret; +} + +int Common_Host_To_Big_Endian_Int(int * i) +{ + /* Init vars. */ + int ret = COMMON_ERROR_UNKNOWN_ERROR; /* The result of this function. */ + + /* Check host's endianness. */ + ret = Common_INT_Endianness_Check(); + if (ret != MSYS_BIG_ENDIAN) + { + /* Check for valid endianness. */ + if (ret == MSYS_LITTLE_ENDIAN) + { + /* Check for invalid arguments. */ + if (i != NULL) + { + /* Call Common_Byte_Swap(). */ + ret = Common_Byte_Swap(((char*)i), sizeof (int)); + } + else + { + /* Invalid arguments. */ + ret = COMMON_ERROR_INVALID_ARGUMENT; + } + } + else + { + /* Host endianness is unknown. Cannot convert unknown endianness. */ + ret = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; + } + } + else + { + /* + * This value should already be in the correct byte order, + * as the host is big endian. + */ + ret = COMMON_ERROR_SUCCESS; + } + + /* Exit function. */ + return ret; +} + +int Common_Big_Endian_To_Host_Int(int * i) +{ + /* Init vars. */ + int ret = COMMON_ERROR_UNKNOWN_ERROR; /* The result of this function. */ + + /* Check host's endianness. */ + ret = Common_INT_Endianness_Check(); + if (ret != MSYS_BIG_ENDIAN) + { + /* Check for valid endianness. */ + if (ret == MSYS_LITTLE_ENDIAN) + { + /* Check for invalid arguments. */ + if (i != NULL) + { + /* Call Common_Byte_Swap(). */ + ret = Common_Byte_Swap(((char*)i), sizeof (int)); + } + else + { + /* Invalid arguments. */ + ret = COMMON_ERROR_INVALID_ARGUMENT; + } + } + else + { + /* Host endianness is unknown. Cannot convert unknown endianness. */ + ret = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; + } + } + else + { + /* + * This value should already be in the correct byte order, + * as the host is big endian. + */ + ret = COMMON_ERROR_SUCCESS; + } + + /* Exit function. */ + return ret; +} + +int Common_Host_To_Big_Endian_ULong(unsigned long * ul) +{ + /* Init vars. */ + int ret = COMMON_ERROR_UNKNOWN_ERROR; /* The result of this function. */ + + /* Check host's endianness. */ + ret = Common_ULONG_Endianness_Check(); + if (ret != MSYS_BIG_ENDIAN) + { + /* Check for valid endianness. */ + if (ret == MSYS_LITTLE_ENDIAN) + { + /* Check for invalid arguments. */ + if (ul != NULL) + { + /* Call Common_Byte_Swap(). */ + ret = Common_Byte_Swap(((char*)ul), sizeof (unsigned long)); + } + else + { + /* Invalid arguments. */ + ret = COMMON_ERROR_INVALID_ARGUMENT; + } + } + else + { + /* Host endianness is unknown. Cannot convert unknown endianness. */ + ret = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; + } + } + else + { + /* + * This value should already be in the correct byte order, + * as the host is big endian. + */ + ret = COMMON_ERROR_SUCCESS; + } + + /* Exit function. */ + return ret; +} + +int Common_Big_Endian_To_Host_ULong(unsigned long * ul) +{ + /* Init vars. */ + int ret = COMMON_ERROR_UNKNOWN_ERROR; /* The result of this function. */ + + /* Check host's endianness. */ + ret = Common_ULONG_Endianness_Check(); + if (ret != MSYS_BIG_ENDIAN) + { + /* Check for valid endianness. */ + if (ret == MSYS_LITTLE_ENDIAN) + { + /* Check for invalid arguments. */ + if (ul != NULL) + { + /* Call Common_Byte_Swap(). */ + ret = Common_Byte_Swap(((char*)ul), sizeof (unsigned long)); + } + else + { + /* Invalid arguments. */ + ret = COMMON_ERROR_INVALID_ARGUMENT; + } + } + else + { + /* Host endianness is unknown. Cannot convert unknown endianness. */ + ret = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; + } + } + else + { + /* + * This value should already be in the correct byte order, + * as the host is big endian. + */ + ret = COMMON_ERROR_SUCCESS; + } + + /* Exit function. */ + return ret; +} + +int Common_Host_To_Big_Endian_Long(long * l) +{ + /* Init vars. */ + int ret = COMMON_ERROR_UNKNOWN_ERROR; /* The result of this function. */ + + /* Check host's endianness. */ + ret = Common_LONG_Endianness_Check(); + if (ret != MSYS_BIG_ENDIAN) + { + /* Check for valid endianness. */ + if (ret == MSYS_LITTLE_ENDIAN) + { + /* Check for invalid arguments. */ + if (l != NULL) + { + /* Call Common_Byte_Swap(). */ + ret = Common_Byte_Swap(((char*)l), sizeof (long)); + } + else + { + /* Invalid arguments. */ + ret = COMMON_ERROR_INVALID_ARGUMENT; + } + } + else + { + /* Host endianness is unknown. Cannot convert unknown endianness. */ + ret = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; + } + } + else + { + /* + * This value should already be in the correct byte order, + * as the host is big endian. + */ + ret = COMMON_ERROR_SUCCESS; + } + + /* Exit function. */ + return ret; +} + +int Common_Big_Endian_To_Host_Long(long * l) +{ + /* Init vars. */ + int ret = COMMON_ERROR_UNKNOWN_ERROR; /* The result of this function. */ + + /* Check host's endianness. */ + ret = Common_LONG_Endianness_Check(); + if (ret != MSYS_BIG_ENDIAN) + { + /* Check for valid endianness. */ + if (ret == MSYS_LITTLE_ENDIAN) + { + /* Check for invalid arguments. */ + if (l != NULL) + { + /* Call Common_Byte_Swap(). */ + ret = Common_Byte_Swap(((char*)l), sizeof (long)); + } + else + { + /* Invalid arguments. */ + ret = COMMON_ERROR_INVALID_ARGUMENT; + } + } + else + { + /* Host endianness is unknown. Cannot convert unknown endianness. */ + ret = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; + } + } + else + { + /* + * This value should already be in the correct byte order, + * as the host is big endian. + */ + ret = COMMON_ERROR_SUCCESS; + } + + /* Exit function. */ + return ret; +} + +int Common_Host_To_Big_Endian_ULong_Long(unsigned long long * ull) +{ + /* Init vars. */ + int ret = COMMON_ERROR_UNKNOWN_ERROR; /* The result of this function. */ + + /* Check host's endianness. */ + ret = Common_ULONG_LONG_Endianness_Check(); + if (ret != MSYS_BIG_ENDIAN) + { + /* Check for valid endianness. */ + if (ret == MSYS_LITTLE_ENDIAN) + { + /* Check for invalid arguments. */ + if (ull != NULL) + { + /* Call Common_Byte_Swap(). */ + ret = Common_Byte_Swap(((char*)ull), sizeof (unsigned long long)); + } + else + { + /* Invalid arguments. */ + ret = COMMON_ERROR_INVALID_ARGUMENT; + } + } + else + { + /* Host endianness is unknown. Cannot convert unknown endianness. */ + ret = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; + } + } + else + { + /* + * This value should already be in the correct byte order, + * as the host is big endian. + */ + ret = COMMON_ERROR_SUCCESS; + } + + /* Exit function. */ + return ret; +} + +int Common_Big_Endian_To_Host_ULong_Long(unsigned long long * ull) +{ + /* Init vars. */ + int ret = COMMON_ERROR_UNKNOWN_ERROR; /* The result of this function. */ + + /* Check host's endianness. */ + ret = Common_ULONG_LONG_Endianness_Check(); + if (ret != MSYS_BIG_ENDIAN) + { + /* Check for valid endianness. */ + if (ret == MSYS_LITTLE_ENDIAN) + { + /* Check for invalid arguments. */ + if (ull != NULL) + { + /* Call Common_Byte_Swap(). */ + ret = Common_Byte_Swap(((char*)ull), sizeof (unsigned long long)); + } + else + { + /* Invalid arguments. */ + ret = COMMON_ERROR_INVALID_ARGUMENT; + } + } + else + { + /* Host endianness is unknown. Cannot convert unknown endianness. */ + ret = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; + } + } + else + { + /* + * This value should already be in the correct byte order, + * as the host is big endian. + */ + ret = COMMON_ERROR_SUCCESS; + } + + /* Exit function. */ + return ret; +} + +int Common_Host_To_Big_Endian_Long_Long(long long * ll) +{ + /* Init vars. */ + int ret = COMMON_ERROR_UNKNOWN_ERROR; /* The result of this function. */ + + /* Check host's endianness. */ + ret = Common_LONG_LONG_Endianness_Check(); + if (ret != MSYS_BIG_ENDIAN) + { + /* Check for valid endianness. */ + if (ret == MSYS_LITTLE_ENDIAN) + { + /* Check for invalid arguments. */ + if (ll != NULL) + { + /* Call Common_Byte_Swap(). */ + ret = Common_Byte_Swap(((char*)ll), sizeof (long long)); + } + else + { + /* Invalid arguments. */ + ret = COMMON_ERROR_INVALID_ARGUMENT; + } + } + else + { + /* Host endianness is unknown. Cannot convert unknown endianness. */ + ret = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; + } + } + else + { + /* + * This value should already be in the correct byte order, + * as the host is big endian. + */ + ret = COMMON_ERROR_SUCCESS; + } + + /* Exit function. */ + return ret; +} + +int Common_Big_Endian_To_Host_Long_Long(long long * ll) +{ + /* Init vars. */ + int ret = COMMON_ERROR_UNKNOWN_ERROR; /* The result of this function. */ + + /* Check host's endianness. */ + ret = Common_LONG_LONG_Endianness_Check(); + if (ret != MSYS_BIG_ENDIAN) + { + /* Check for valid endianness. */ + if (ret == MSYS_LITTLE_ENDIAN) + { + /* Check for invalid arguments. */ + if (ll != NULL) + { + /* Call Common_Byte_Swap(). */ + ret = Common_Byte_Swap(((char*)ll), sizeof (long long)); + } + else + { + /* Invalid arguments. */ + ret = COMMON_ERROR_INVALID_ARGUMENT; + } + } + else + { + /* Host endianness is unknown. Cannot convert unknown endianness. */ + ret = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; + } + } + else + { + /* + * This value should already be in the correct byte order, + * as the host is big endian. + */ + ret = COMMON_ERROR_SUCCESS; + } + + /* Exit function. */ + return ret; +} + +int Common_Host_To_Big_Endian_Size_T(size_t * st) +{ + /* Init vars. */ + int ret = COMMON_ERROR_UNKNOWN_ERROR; /* The result of this function. */ + + /* Check host's endianness. */ + ret = Common_SIZE_T_Endianness_Check(); + if (ret != MSYS_BIG_ENDIAN) + { + /* Check for valid endianness. */ + if (ret == MSYS_LITTLE_ENDIAN) + { + /* Check for invalid arguments. */ + if (st != NULL) + { + /* Call Common_Byte_Swap(). */ + ret = Common_Byte_Swap(((char*)st), sizeof (size_t)); + } + else + { + /* Invalid arguments. */ + ret = COMMON_ERROR_INVALID_ARGUMENT; + } + } + else + { + /* Host endianness is unknown. Cannot convert unknown endianness. */ + ret = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; + } + } + else + { + /* + * This value should already be in the correct byte order, + * as the host is big endian. + */ + ret = COMMON_ERROR_SUCCESS; + } + + /* Exit function. */ + return ret; +} + +int Common_Big_Endian_To_Host_Size_T(size_t * st) +{ + /* Init vars. */ + int ret = COMMON_ERROR_UNKNOWN_ERROR; /* The result of this function. */ + + /* Check host's endianness. */ + ret = Common_SIZE_T_Endianness_Check(); + if (ret != MSYS_BIG_ENDIAN) + { + /* Check for valid endianness. */ + if (ret == MSYS_LITTLE_ENDIAN) + { + /* Check for invalid arguments. */ + if (st != NULL) + { + /* Call Common_Byte_Swap(). */ + ret = Common_Byte_Swap(((char*)st), sizeof (size_t)); + } + else + { + /* Invalid arguments. */ + ret = COMMON_ERROR_INVALID_ARGUMENT; + } + } + else + { + /* Host endianness is unknown. Cannot convert unknown endianness. */ + ret = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; + } + } + else + { + /* + * This value should already be in the correct byte order, + * as the host is big endian. + */ + ret = COMMON_ERROR_SUCCESS; + } + + /* Exit function. */ + return ret; +} + +int Common_UCHAR_Endianness_Check() +{ + /* Init vars. */ + int ret = MSYS_UNKNOWN_ENDIANNESS; /* The result of this function. */ + unsigned char t = '\1'; /* Variable to check. */ + + /* Cast t to a char string and see if the result is 1. */ + if (((char*)&t)[0]) + { + /* The first byte is 1 so it's little endian. */ + ret = MSYS_LITTLE_ENDIAN; + } + else + { + /* + * The first byte is 0 so, check and see if the last byte is non-zero. + * If it is, then the host is big endian. + * + * Otherwise the host is using something like middle-endian to store + * the value, but we would need more checks to determine what exact + * kind of endianness the host is using. + */ + if (((char*)&t)[((sizeof(t)) - 1)]) + { + /* It's big endian. */ + ret = MSYS_BIG_ENDIAN; + } + } + + /* Return the result. */ + return ret; +} + +int Common_CHAR_Endianness_Check() +{ + /* Init vars. */ + int ret = MSYS_UNKNOWN_ENDIANNESS; /* The result of this function. */ + char t = '\1'; /* Variable to check. */ + + /* Cast t to a char string and see if the result is 1. */ + if (((char*)&t)[0]) + { + /* The first byte is 1 so it's little endian. */ + ret = MSYS_LITTLE_ENDIAN; + } + else + { + /* + * The first byte is 0 so, check and see if the last byte is non-zero. + * If it is, then the host is big endian. + * + * Otherwise the host is using something like middle-endian to store + * the value, but we would need more checks to determine what exact + * kind of endianness the host is using. + */ + if (((char*)&t)[((sizeof(t)) - 1)]) + { + /* It's big endian. */ + ret = MSYS_BIG_ENDIAN; + } + } + + /* Return the result. */ + return ret; +} + +int Common_USHORT_Endianness_Check() +{ + /* Init vars. */ + int ret = MSYS_UNKNOWN_ENDIANNESS; /* The result of this function. */ + unsigned short t = 1; /* Variable to check. */ + + /* Cast t to a char string and see if the result is 1. */ + if (((char*)&t)[0]) + { + /* The first byte is 1 so it's little endian. */ + ret = MSYS_LITTLE_ENDIAN; + } + else + { + /* + * The first byte is 0 so, check and see if the last byte is non-zero. + * If it is, then the host is big endian. + * + * Otherwise the host is using something like middle-endian to store + * the value, but we would need more checks to determine what exact + * kind of endianness the host is using. + */ + if (((char*)&t)[((sizeof(t)) - 1)]) + { + /* It's big endian. */ + ret = MSYS_BIG_ENDIAN; + } + } + + /* Return the result. */ + return ret; +} + +int Common_SHORT_Endianness_Check() +{ + /* Init vars. */ + int ret = MSYS_UNKNOWN_ENDIANNESS; /* The result of this function. */ + short t = 1; /* Variable to check. */ + + /* Cast t to a char string and see if the result is 1. */ + if (((char*)&t)[0]) + { + /* The first byte is 1 so it's little endian. */ + ret = MSYS_LITTLE_ENDIAN; + } + else + { + /* + * The first byte is 0 so, check and see if the last byte is non-zero. + * If it is, then the host is big endian. + * + * Otherwise the host is using something like middle-endian to store + * the value, but we would need more checks to determine what exact + * kind of endianness the host is using. + */ + if (((char*)&t)[((sizeof(t)) - 1)]) + { + /* It's big endian. */ + ret = MSYS_BIG_ENDIAN; + } + } + + /* Return the result. */ + return ret; +} + +int Common_UINT_Endianness_Check() +{ + /* Init vars. */ + int ret = MSYS_UNKNOWN_ENDIANNESS; /* The result of this function. */ + unsigned int t = 1; /* Variable to check. */ + + /* Cast t to a char string and see if the result is 1. */ + if (((char*)&t)[0]) + { + /* The first byte is 1 so it's little endian. */ + ret = MSYS_LITTLE_ENDIAN; + } + else + { + /* + * The first byte is 0 so, check and see if the last byte is non-zero. + * If it is, then the host is big endian. + * + * Otherwise the host is using something like middle-endian to store + * the value, but we would need more checks to determine what exact + * kind of endianness the host is using. + */ + if (((char*)&t)[((sizeof(t)) - 1)]) + { + /* It's big endian. */ + ret = MSYS_BIG_ENDIAN; + } + } + + /* Return the result. */ + return ret; +} + +int Common_INT_Endianness_Check() +{ + /* Init vars. */ + int ret = MSYS_UNKNOWN_ENDIANNESS; /* The result of this function. */ + int t = 1; /* Variable to check. */ + + /* Cast t to a char string and see if the result is 1. */ + if (((char*)&t)[0]) + { + /* The first byte is 1 so it's little endian. */ + ret = MSYS_LITTLE_ENDIAN; + } + else + { + /* + * The first byte is 0 so, check and see if the last byte is non-zero. + * If it is, then the host is big endian. + * + * Otherwise the host is using something like middle-endian to store + * the value, but we would need more checks to determine what exact + * kind of endianness the host is using. + */ + if (((char*)&t)[((sizeof(t)) - 1)]) + { + /* It's big endian. */ + ret = MSYS_BIG_ENDIAN; + } + } + + /* Return the result. */ + return ret; +} + +int Common_ULONG_Endianness_Check() +{ + /* Init vars. */ + int ret = MSYS_UNKNOWN_ENDIANNESS; /* The result of this function. */ + unsigned long t = 1; /* Variable to check. */ + + /* Cast t to a char string and see if the result is 1. */ + if (((char*)&t)[0]) + { + /* The first byte is 1 so it's little endian. */ + ret = MSYS_LITTLE_ENDIAN; + } + else + { + /* + * The first byte is 0 so, check and see if the last byte is non-zero. + * If it is, then the host is big endian. + * + * Otherwise the host is using something like middle-endian to store + * the value, but we would need more checks to determine what exact + * kind of endianness the host is using. + */ + if (((char*)&t)[((sizeof(t)) - 1)]) + { + /* It's big endian. */ + ret = MSYS_BIG_ENDIAN; + } + } + + /* Return the result. */ + return ret; +} + +int Common_LONG_Endianness_Check() +{ + /* Init vars. */ + int ret = MSYS_UNKNOWN_ENDIANNESS; /* The result of this function. */ + long t = 1; /* Variable to check. */ + + /* Cast t to a char string and see if the result is 1. */ + if (((char*)&t)[0]) + { + /* The first byte is 1 so it's little endian. */ + ret = MSYS_LITTLE_ENDIAN; + } + else + { + /* + * The first byte is 0 so, check and see if the last byte is non-zero. + * If it is, then the host is big endian. + * + * Otherwise the host is using something like middle-endian to store + * the value, but we would need more checks to determine what exact + * kind of endianness the host is using. + */ + if (((char*)&t)[((sizeof(t)) - 1)]) + { + /* It's big endian. */ + ret = MSYS_BIG_ENDIAN; + } + } + + /* Return the result. */ + return ret; +} + +int Common_ULONG_LONG_Endianness_Check() +{ + /* Init vars. */ + int ret = MSYS_UNKNOWN_ENDIANNESS; /* The result of this function. */ + unsigned long long t = 1; /* Variable to check. */ + + /* Cast t to a char string and see if the result is 1. */ + if (((char*)&t)[0]) + { + /* The first byte is 1 so it's little endian. */ + ret = MSYS_LITTLE_ENDIAN; + } + else + { + /* + * The first byte is 0 so, check and see if the last byte is non-zero. + * If it is, then the host is big endian. + * + * Otherwise the host is using something like middle-endian to store + * the value, but we would need more checks to determine what exact + * kind of endianness the host is using. + */ + if (((char*)&t)[((sizeof(t)) - 1)]) + { + /* It's big endian. */ + ret = MSYS_BIG_ENDIAN; + } + } + + /* Return the result. */ + return ret; +} + +int Common_LONG_LONG_Endianness_Check() +{ + /* Init vars. */ + int ret = MSYS_UNKNOWN_ENDIANNESS; /* The result of this function. */ + long long t = 1; /* Variable to check. */ + + /* Cast t to a char string and see if the result is 1. */ + if (((char*)&t)[0]) + { + /* The first byte is 1 so it's little endian. */ + ret = MSYS_LITTLE_ENDIAN; + } + else + { + /* + * The first byte is 0 so, check and see if the last byte is non-zero. + * If it is, then the host is big endian. + * + * Otherwise the host is using something like middle-endian to store + * the value, but we would need more checks to determine what exact + * kind of endianness the host is using. + */ + if (((char*)&t)[((sizeof(t)) - 1)]) + { + /* It's big endian. */ + ret = MSYS_BIG_ENDIAN; + } + } + + /* Return the result. */ + return ret; +} + +int Common_SIZE_T_Endianness_Check() +{ + /* Init vars. */ + int ret = MSYS_UNKNOWN_ENDIANNESS; /* The result of this function. */ + size_t t = 1; /* Variable to check. */ + + /* Cast t to a char string and see if the result is 1. */ + if (((char*)&t)[0]) + { + /* The first byte is 1 so it's little endian. */ + ret = MSYS_LITTLE_ENDIAN; + } + else + { + /* + * The first byte is 0 so, check and see if the last byte is non-zero. + * If it is, then the host is big endian. + * + * Otherwise the host is using something like middle-endian to store + * the value, but we would need more checks to determine what exact + * kind of endianness the host is using. + */ + if (((char*)&t)[((sizeof(t)) - 1)]) + { + /* It's big endian. */ + ret = MSYS_BIG_ENDIAN; + } + } + + /* Return the result. */ + return ret; +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ diff --git a/src/Common/Src/Byte_Order_Integers.h b/src/Common/Src/Byte_Order_Integers.h new file mode 100644 index 0000000..429a5ab --- /dev/null +++ b/src/Common/Src/Byte_Order_Integers.h @@ -0,0 +1,752 @@ +/*! + Multiverse Engine Project 09/6/2015 Common Byte_Order_Integers.h + + Copyright (C) 2015 Multiverse Engine Project + + This program is free software; + you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this program; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Official source repository and project information can be found at + https://github.com/codebase7/mengine +*/ + +/* Include guard. */ +#ifndef MSYS_BYTE_ORDER_INTEGERS_H +#define MSYS_BYTE_ORDER_INTEGERS_H + +/* Make sure we are not included directly. */ +#ifndef MSYS_BYTE_ORDER_H +#error "You should not include __FILE__ directly, it is included automaticly by Byte_Order.h, remove this include. Aborting build." +#endif + +/* Check for C++ compiler. */ +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/*! + * int Common_Host_To_Big_Endian_UChar(unsigned char * uc) + * + * Converts a given unsigned CHAR value from the host's endianness + * to Big Endian format. + * + * Returns COMMON_ERROR_SUCCESS, if the conversion is successful, + * (data will be converted after call returns), + * or if the host is a Big Endian host. (In such case no data alteration + * is performed.) + * + * Returns COMMON_ERROR_INVALID_ARGUMENT if the given pointer is NULL. + * + * Returns COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED if the given data type's + * byte ordering is unknown for the given host. + * + * In case of error, (returned error code is not COMMON_ERROR_SUCCESS), + * all arguments will be left unaltered. + */ +int Common_Host_To_Big_Endian_UChar(unsigned char * uc); + +/*! + * int Common_Big_Endian_To_Host_UChar(unsigned char * uc) + * + * Converts a given unsigned CHAR value from the Big Endian format + * to the host's endianness format. + * + * Returns COMMON_ERROR_SUCCESS, if the conversion is successful, + * (data will be converted after call returns), + * or if the host is a Big Endian host. (In such case no data alteration + * is performed.) + * + * Returns COMMON_ERROR_INVALID_ARGUMENT if the given pointer is NULL. + * + * Returns COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED if the given data type's + * byte ordering is unknown for the given host. + * + * In case of error, (returned error code is not COMMON_ERROR_SUCCESS), + * all arguments will be left unaltered. + */ +int Common_Big_Endian_To_Host_UChar(unsigned char * uc); + +/*! + * int Common_Host_To_Big_Endian_Char(char * c) + * + * Converts a given CHAR value from the host's endianness + * to Big Endian format. + * + * Returns COMMON_ERROR_SUCCESS, if the conversion is successful, + * (data will be converted after call returns), + * or if the host is a Big Endian host. (In such case no data alteration + * is performed.) + * + * Returns COMMON_ERROR_INVALID_ARGUMENT if the given pointer is NULL. + * + * Returns COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED if the given data type's + * byte ordering is unknown for the given host. + * + * In case of error, (returned error code is not COMMON_ERROR_SUCCESS), + * all arguments will be left unaltered. + */ +int Common_Host_To_Big_Endian_Char(char * c); + +/*! + * int Common_Big_Endian_To_Host_Char(char * c) + * + * Converts a given CHAR value from the Big Endian format + * to the host's endianness format. + * + * Returns COMMON_ERROR_SUCCESS, if the conversion is successful, + * (data will be converted after call returns), + * or if the host is a Big Endian host. (In such case no data alteration + * is performed.) + * + * Returns COMMON_ERROR_INVALID_ARGUMENT if the given pointer is NULL. + * + * Returns COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED if the given data type's + * byte ordering is unknown for the given host. + * + * In case of error, (returned error code is not COMMON_ERROR_SUCCESS), + * all arguments will be left unaltered. + */ +int Common_Big_Endian_To_Host_Char(char * c); + +/*! + * int Common_Host_To_Big_Endian_UShort(unsigned short * us) + * + * Converts a given unsigned SHORT value from the host's endianness + * to Big Endian format. + * + * Returns COMMON_ERROR_SUCCESS, if the conversion is successful, + * (data will be converted after call returns), + * or if the host is a Big Endian host. (In such case no data alteration + * is performed.) + * + * Returns COMMON_ERROR_INVALID_ARGUMENT if the given pointer is NULL. + * + * Returns COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED if the given data type's + * byte ordering is unknown for the given host. + * + * In case of error, (returned error code is not COMMON_ERROR_SUCCESS), + * all arguments will be left unaltered. + */ +int Common_Host_To_Big_Endian_UShort(unsigned short * us); + +/*! + * int Common_Big_Endian_To_Host_UShort(unsigned short * us) + * + * Converts a given unsigned SHORT value from the Big Endian format + * to the host's endianness format. + * + * Returns COMMON_ERROR_SUCCESS, if the conversion is successful, + * (data will be converted after call returns), + * or if the host is a Big Endian host. (In such case no data alteration + * is performed.) + * + * Returns COMMON_ERROR_INVALID_ARGUMENT if the given pointer is NULL. + * + * Returns COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED if the given data type's + * byte ordering is unknown for the given host. + * + * In case of error, (returned error code is not COMMON_ERROR_SUCCESS), + * all arguments will be left unaltered. + */ +int Common_Big_Endian_To_Host_UShort(unsigned short * us); + +/*! + * int Common_Host_To_Big_Endian_Short(short * s) + * + * Converts a given SHORT value from the host's endianness + * to Big Endian format. + * + * Returns COMMON_ERROR_SUCCESS, if the conversion is successful, + * (data will be converted after call returns), + * or if the host is a Big Endian host. (In such case no data alteration + * is performed.) + * + * Returns COMMON_ERROR_INVALID_ARGUMENT if the given pointer is NULL. + * + * Returns COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED if the given data type's + * byte ordering is unknown for the given host. + * + * In case of error, (returned error code is not COMMON_ERROR_SUCCESS), + * all arguments will be left unaltered. + */ +int Common_Host_To_Big_Endian_Short(short * s); + +/*! + * int Common_Big_Endian_To_Host_Short(short * s) + * + * Converts a given SHORT value from the Big Endian format + * to the host's endianness format. + * + * Returns COMMON_ERROR_SUCCESS, if the conversion is successful, + * (data will be converted after call returns), + * or if the host is a Big Endian host. (In such case no data alteration + * is performed.) + * + * Returns COMMON_ERROR_INVALID_ARGUMENT if the given pointer is NULL. + * + * Returns COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED if the given data type's + * byte ordering is unknown for the given host. + * + * In case of error, (returned error code is not COMMON_ERROR_SUCCESS), + * all arguments will be left unaltered. + */ +int Common_Big_Endian_To_Host_Short(short * s); + +/*! + * int Common_Host_To_Big_Endian_UInt(unsigned int * ui) + * + * Converts a given unsigned INT value from the host's endianness + * to Big Endian format. + * + * Returns COMMON_ERROR_SUCCESS, if the conversion is successful, + * (data will be converted after call returns), + * or if the host is a Big Endian host. (In such case no data alteration + * is performed.) + * + * Returns COMMON_ERROR_INVALID_ARGUMENT if the given pointer is NULL. + * + * Returns COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED if the given data type's + * byte ordering is unknown for the given host. + * + * In case of error, (returned error code is not COMMON_ERROR_SUCCESS), + * all arguments will be left unaltered. + */ +int Common_Host_To_Big_Endian_UInt(unsigned int * ui); + +/*! + * int Common_Big_Endian_To_Host_UInt(unsigned int * ui) + * + * Converts a given unsigned INT value from the Big Endian format + * to the host's endianness format. + * + * Returns COMMON_ERROR_SUCCESS, if the conversion is successful, + * (data will be converted after call returns), + * or if the host is a Big Endian host. (In such case no data alteration + * is performed.) + * + * Returns COMMON_ERROR_INVALID_ARGUMENT if the given pointer is NULL. + * + * Returns COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED if the given data type's + * byte ordering is unknown for the given host. + * + * In case of error, (returned error code is not COMMON_ERROR_SUCCESS), + * all arguments will be left unaltered. + */ +int Common_Big_Endian_To_Host_UInt(unsigned int * ui); + +/*! + * int Common_Host_To_Big_Endian_Int(int * i) + * + * Converts a given INT value from the host's endianness + * to Big Endian format. + * + * Returns COMMON_ERROR_SUCCESS, if the conversion is successful, + * (data will be converted after call returns), + * or if the host is a Big Endian host. (In such case no data alteration + * is performed.) + * + * Returns COMMON_ERROR_INVALID_ARGUMENT if the given pointer is NULL. + * + * Returns COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED if the given data type's + * byte ordering is unknown for the given host. + * + * In case of error, (returned error code is not COMMON_ERROR_SUCCESS), + * all arguments will be left unaltered. + */ +int Common_Host_To_Big_Endian_Int(int * i); + +/*! + * int Common_Big_Endian_To_Host_Int(int * i) + * + * Converts a given INT value from the Big Endian format + * to the host's endianness format. + * + * Returns COMMON_ERROR_SUCCESS, if the conversion is successful, + * (data will be converted after call returns), + * or if the host is a Big Endian host. (In such case no data alteration + * is performed.) + * + * Returns COMMON_ERROR_INVALID_ARGUMENT if the given pointer is NULL. + * + * Returns COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED if the given data type's + * byte ordering is unknown for the given host. + * + * In case of error, (returned error code is not COMMON_ERROR_SUCCESS), + * all arguments will be left unaltered. + */ +int Common_Big_Endian_To_Host_Int(int * i); + +/*! + * int Common_Host_To_Big_Endian_ULong(unsigned long * ul) + * + * Converts a given unsigned LONG value from the host's endianness + * to Big Endian format. + * + * Returns COMMON_ERROR_SUCCESS, if the conversion is successful, + * (data will be converted after call returns), + * or if the host is a Big Endian host. (In such case no data alteration + * is performed.) + * + * Returns COMMON_ERROR_INVALID_ARGUMENT if the given pointer is NULL. + * + * Returns COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED if the given data type's + * byte ordering is unknown for the given host. + * + * In case of error, (returned error code is not COMMON_ERROR_SUCCESS), + * all arguments will be left unaltered. + */ +int Common_Host_To_Big_Endian_ULong(unsigned long * ul); + +/*! + * int Common_Big_Endian_To_Host_ULong(unsigned long * ul) + * + * Converts a given unsigned LONG value from the Big Endian format + * to the host's endianness format. + * + * Returns COMMON_ERROR_SUCCESS, if the conversion is successful, + * (data will be converted after call returns), + * or if the host is a Big Endian host. (In such case no data alteration + * is performed.) + * + * Returns COMMON_ERROR_INVALID_ARGUMENT if the given pointer is NULL. + * + * Returns COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED if the given data type's + * byte ordering is unknown for the given host. + * + * In case of error, (returned error code is not COMMON_ERROR_SUCCESS), + * all arguments will be left unaltered. + */ +int Common_Big_Endian_To_Host_ULong(unsigned long * ul); + +/*! + * int Common_Host_To_Big_Endian_Long(long * l) + * + * Converts a given LONG value from the host's endianness + * to Big Endian format. + * + * Returns COMMON_ERROR_SUCCESS, if the conversion is successful, + * (data will be converted after call returns), + * or if the host is a Big Endian host. (In such case no data alteration + * is performed.) + * + * Returns COMMON_ERROR_INVALID_ARGUMENT if the given pointer is NULL. + * + * Returns COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED if the given data type's + * byte ordering is unknown for the given host. + * + * In case of error, (returned error code is not COMMON_ERROR_SUCCESS), + * all arguments will be left unaltered. + */ +int Common_Host_To_Big_Endian_Long(long * l); + +/*! + * int Common_Big_Endian_To_Host_Long(long * l) + * + * Converts a given LONG value from the Big Endian format + * to the host's endianness format. + * + * Returns COMMON_ERROR_SUCCESS, if the conversion is successful, + * (data will be converted after call returns), + * or if the host is a Big Endian host. (In such case no data alteration + * is performed.) + * + * Returns COMMON_ERROR_INVALID_ARGUMENT if the given pointer is NULL. + * + * Returns COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED if the given data type's + * byte ordering is unknown for the given host. + * + * In case of error, (returned error code is not COMMON_ERROR_SUCCESS), + * all arguments will be left unaltered. + */ +int Common_Big_Endian_To_Host_Long(long * l); + +/*! + * int Common_Host_To_Big_Endian_ULong_Long(unsigned long long * ull) + * + * Converts a given unsigned LONG LONG value from the host's endianness + * to Big Endian format. + * + * Returns COMMON_ERROR_SUCCESS, if the conversion is successful, + * (data will be converted after call returns), + * or if the host is a Big Endian host. (In such case no data alteration + * is performed.) + * + * Returns COMMON_ERROR_INVALID_ARGUMENT if the given pointer is NULL. + * + * Returns COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED if the given data type's + * byte ordering is unknown for the given host. + * + * In case of error, (returned error code is not COMMON_ERROR_SUCCESS), + * all arguments will be left unaltered. + */ +int Common_Host_To_Big_Endian_ULong_Long(unsigned long long * ull); + +/*! + * int Common_Big_Endian_To_Host_ULong_Long(unsigned long long * ull) + * + * Converts a given unsigned LONG LONG value from the Big Endian format + * to the host's endianness format. + * + * Returns COMMON_ERROR_SUCCESS, if the conversion is successful, + * (data will be converted after call returns), + * or if the host is a Big Endian host. (In such case no data alteration + * is performed.) + * + * Returns COMMON_ERROR_INVALID_ARGUMENT if the given pointer is NULL. + * + * Returns COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED if the given data type's + * byte ordering is unknown for the given host. + * + * In case of error, (returned error code is not COMMON_ERROR_SUCCESS), + * all arguments will be left unaltered. + */ +int Common_Big_Endian_To_Host_ULong_Long(unsigned long long * ull); + +/*! + * int Common_Host_To_Big_Endian_Long_Long(long long * ull) + * + * Converts a given LONG LONG value from the host's endianness + * to Big Endian format. + * + * Returns COMMON_ERROR_SUCCESS, if the conversion is successful, + * (data will be converted after call returns), + * or if the host is a Big Endian host. (In such case no data alteration + * is performed.) + * + * Returns COMMON_ERROR_INVALID_ARGUMENT if the given pointer is NULL. + * + * Returns COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED if the given data type's + * byte ordering is unknown for the given host. + * + * In case of error, (returned error code is not COMMON_ERROR_SUCCESS), + * all arguments will be left unaltered. + */ +int Common_Host_To_Big_Endian_Long_Long(long long * ll); + +/*! + * int Common_Big_Endian_To_Host_Long_Long(long long * ll) + * + * Converts a given LONG LONG value from the Big Endian format + * to the host's endianness format. + * + * Returns COMMON_ERROR_SUCCESS, if the conversion is successful, + * (data will be converted after call returns), + * or if the host is a Big Endian host. (In such case no data alteration + * is performed.) + * + * Returns COMMON_ERROR_INVALID_ARGUMENT if the given pointer is NULL. + * + * Returns COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED if the given data type's + * byte ordering is unknown for the given host. + * + * In case of error, (returned error code is not COMMON_ERROR_SUCCESS), + * all arguments will be left unaltered. + */ +int Common_Big_Endian_To_Host_Long_Long(long long * ll); + +/*! + * int Common_Host_To_Big_Endian_Size_T(size_t * st) + * + * Converts a given SIZE_T value from the host's endianness + * to Big Endian format. + * + * Returns COMMON_ERROR_SUCCESS, if the conversion is successful, + * (data will be converted after call returns), + * or if the host is a Big Endian host. (In such case no data alteration + * is performed.) + * + * Returns COMMON_ERROR_INVALID_ARGUMENT if the given pointer is NULL. + * + * Returns COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED if the given data type's + * byte ordering is unknown for the given host. + * + * In case of error, (returned error code is not COMMON_ERROR_SUCCESS), + * all arguments will be left unaltered. + */ +int Common_Host_To_Big_Endian_Size_T(size_t * st); + +/*! + * int Common_Big_Endian_To_Host_Size_T(size_t * st) + * + * Converts a given SIZE_T value from the Big Endian format + * to the host's endianness format. + * + * Returns COMMON_ERROR_SUCCESS, if the conversion is successful, + * (data will be converted after call returns), + * or if the host is a Big Endian host. (In such case no data alteration + * is performed.) + * + * Returns COMMON_ERROR_INVALID_ARGUMENT if the given pointer is NULL. + * + * Returns COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED if the given data type's + * byte ordering is unknown for the given host. + * + * In case of error, (returned error code is not COMMON_ERROR_SUCCESS), + * all arguments will be left unaltered. + */ +int Common_Big_Endian_To_Host_Size_T(size_t * st); + +/*! + * General Definitions for the Common_*_Endianness_Check() functions: + * + * The functions below all contain the same returns, + * and purpose. + */ + +/*! + * int Common_UCHAR_Endianness_Check() + * + * Template function which checks the host's endianness for the + * UCHAR data type. + * + * Note: This function is the equivalent of calling + * DataProcess_Endianness_Check() with a unsigned CHAR argument. + * This function is here for the purpose of making it easier + * to use C code. + * + * Returns MSYS_BIG_ENDIAN if the given data type is stored as big + * endian on the host machine. + * + * Returns MSYS_LITTLE_ENDIAN if the given data type stored as little + * endian on the host machine. + * + * Returns MSYS_UNKNOWN_ENDIANNESS if the given data type's byte ordering + * is unknown for the given host. + */ +int Common_UCHAR_Endianness_Check(); + +/*! + * int Common_CHAR_Endianness_Check() + * + * Template function which checks the host's endianness for the + * UCHAR data type. + * + * Note: This function is the equivalent of calling + * DataProcess_Endianness_Check() with a CHAR argument. + * This function is here for the purpose of making it easier + * to use C code. + * + * Returns MSYS_BIG_ENDIAN if the given data type is stored as big + * endian on the host machine. + * + * Returns MSYS_LITTLE_ENDIAN if the given data type stored as little + * endian on the host machine. + * + * Returns MSYS_UNKNOWN_ENDIANNESS if the given data type's byte ordering + * is unknown for the given host. + */ +int Common_CHAR_Endianness_Check(); + +/*! + * int Common_USHORT_Endianness_Check() + * + * Template function which checks the host's endianness for the + * UCHAR data type. + * + * Note: This function is the equivalent of calling + * DataProcess_Endianness_Check() with a unsigned SHORT argument. + * This function is here for the purpose of making it easier + * to use C code. + * + * Returns MSYS_BIG_ENDIAN if the given data type is stored as big + * endian on the host machine. + * + * Returns MSYS_LITTLE_ENDIAN if the given data type stored as little + * endian on the host machine. + * + * Returns MSYS_UNKNOWN_ENDIANNESS if the given data type's byte ordering + * is unknown for the given host. + */ +int Common_USHORT_Endianness_Check(); + +/*! + * int Common_SHORT_Endianness_Check() + * + * Template function which checks the host's endianness for the + * UCHAR data type. + * + * Note: This function is the equivalent of calling + * DataProcess_Endianness_Check() with a SHORT argument. + * This function is here for the purpose of making it easier + * to use C code. + * + * Returns MSYS_BIG_ENDIAN if the given data type is stored as big + * endian on the host machine. + * + * Returns MSYS_LITTLE_ENDIAN if the given data type stored as little + * endian on the host machine. + * + * Returns MSYS_UNKNOWN_ENDIANNESS if the given data type's byte ordering + * is unknown for the given host. + */ +int Common_SHORT_Endianness_Check(); + +/*! + * int Common_UINT_Endianness_Check() + * + * Template function which checks the host's endianness for the + * UCHAR data type. + * + * Note: This function is the equivalent of calling + * DataProcess_Endianness_Check() with a unsigned INT argument. + * This function is here for the purpose of making it easier + * to use C code. + * + * Returns MSYS_BIG_ENDIAN if the given data type is stored as big + * endian on the host machine. + * + * Returns MSYS_LITTLE_ENDIAN if the given data type stored as little + * endian on the host machine. + * + * Returns MSYS_UNKNOWN_ENDIANNESS if the given data type's byte ordering + * is unknown for the given host. + */ +int Common_UINT_Endianness_Check(); + +/*! + * int Common_INT_Endianness_Check() + * + * Template function which checks the host's endianness for the + * UCHAR data type. + * + * Note: This function is the equivalent of calling + * DataProcess_Endianness_Check() with a INT argument. + * This function is here for the purpose of making it easier + * to use C code. + * + * Returns MSYS_BIG_ENDIAN if the given data type is stored as big + * endian on the host machine. + * + * Returns MSYS_LITTLE_ENDIAN if the given data type stored as little + * endian on the host machine. + * + * Returns MSYS_UNKNOWN_ENDIANNESS if the given data type's byte ordering + * is unknown for the given host. + */ +int Common_INT_Endianness_Check(); + +/*! + * int Common_ULONG_Endianness_Check() + * + * Template function which checks the host's endianness for the + * UCHAR data type. + * + * Note: This function is the equivalent of calling + * DataProcess_Endianness_Check() with a unsigned LONG argument. + * This function is here for the purpose of making it easier + * to use C code. + * + * Returns MSYS_BIG_ENDIAN if the given data type is stored as big + * endian on the host machine. + * + * Returns MSYS_LITTLE_ENDIAN if the given data type stored as little + * endian on the host machine. + * + * Returns MSYS_UNKNOWN_ENDIANNESS if the given data type's byte ordering + * is unknown for the given host. + */ +int Common_ULONG_Endianness_Check(); + +/*! + * int Common_LONG_Endianness_Check() + * + * Template function which checks the host's endianness for the + * UCHAR data type. + * + * Note: This function is the equivalent of calling + * DataProcess_Endianness_Check() with a LONG argument. + * This function is here for the purpose of making it easier + * to use C code. + * + * Returns MSYS_BIG_ENDIAN if the given data type is stored as big + * endian on the host machine. + * + * Returns MSYS_LITTLE_ENDIAN if the given data type stored as little + * endian on the host machine. + * + * Returns MSYS_UNKNOWN_ENDIANNESS if the given data type's byte ordering + * is unknown for the given host. + */ +int Common_LONG_Endianness_Check(); + +/*! + * int Common_ULONG_LONG_Endianness_Check() + * + * Template function which checks the host's endianness for the + * UCHAR data type. + * + * Note: This function is the equivalent of calling + * DataProcess_Endianness_Check() with a unsigned LONG LONG argument. + * This function is here for the purpose of making it easier + * to use C code. + * + * Returns MSYS_BIG_ENDIAN if the given data type is stored as big + * endian on the host machine. + * + * Returns MSYS_LITTLE_ENDIAN if the given data type stored as little + * endian on the host machine. + * + * Returns MSYS_UNKNOWN_ENDIANNESS if the given data type's byte ordering + * is unknown for the given host. + */ +int Common_ULONG_LONG_Endianness_Check(); + +/*! + * int Common_LONG_LONG_Endianness_Check() + * + * Template function which checks the host's endianness for the + * UCHAR data type. + * + * Note: This function is the equivalent of calling + * DataProcess_Endianness_Check() with a LONG LONG argument. + * This function is here for the purpose of making it easier + * to use C code. + * + * Returns MSYS_BIG_ENDIAN if the given data type is stored as big + * endian on the host machine. + * + * Returns MSYS_LITTLE_ENDIAN if the given data type stored as little + * endian on the host machine. + * + * Returns MSYS_UNKNOWN_ENDIANNESS if the given data type's byte ordering + * is unknown for the given host. + */ +int Common_LONG_LONG_Endianness_Check(); + +/*! + * int Common_SIZE_T_Endianness_Check() + * + * Template function which checks the host's endianness for the + * UCHAR data type. + * + * Note: This function is the equivalent of calling + * DataProcess_Endianness_Check() with a SIZE_T argument. + * This function is here for the purpose of making it easier + * to use C code. + * + * Returns MSYS_BIG_ENDIAN if the given data type is stored as big + * endian on the host machine. + * + * Returns MSYS_LITTLE_ENDIAN if the given data type stored as little + * endian on the host machine. + * + * Returns MSYS_UNKNOWN_ENDIANNESS if the given data type's byte ordering + * is unknown for the given host. + */ +int Common_SIZE_T_Endianness_Check(); + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ + +#endif /* MSYS_BYTE_ORDER_INTEGERS_H */ + +/* End of Byte_Order_Integers.h */ From 7087d90bd49cb1a640d5a6d2c776b91e8481eeeb Mon Sep 17 00:00:00 2001 From: codebase7 Date: Sat, 13 Jun 2015 13:29:59 -0400 Subject: [PATCH 027/325] Move Byte_Order*.* files to their own folder. This commit moves the Byte_Order*.* files to their own folder. --- src/Common/Src/{ => Byte_Order}/Byte_Order.c | 0 src/Common/Src/{ => Byte_Order}/Byte_Order.h | 0 src/Common/Src/{ => Byte_Order}/Byte_Order_Floating_Points.c | 0 src/Common/Src/{ => Byte_Order}/Byte_Order_Floating_Points.h | 0 src/Common/Src/{ => Byte_Order}/Byte_Order_Integers.c | 0 src/Common/Src/{ => Byte_Order}/Byte_Order_Integers.h | 0 6 files changed, 0 insertions(+), 0 deletions(-) rename src/Common/Src/{ => Byte_Order}/Byte_Order.c (100%) rename src/Common/Src/{ => Byte_Order}/Byte_Order.h (100%) rename src/Common/Src/{ => Byte_Order}/Byte_Order_Floating_Points.c (100%) rename src/Common/Src/{ => Byte_Order}/Byte_Order_Floating_Points.h (100%) rename src/Common/Src/{ => Byte_Order}/Byte_Order_Integers.c (100%) rename src/Common/Src/{ => Byte_Order}/Byte_Order_Integers.h (100%) diff --git a/src/Common/Src/Byte_Order.c b/src/Common/Src/Byte_Order/Byte_Order.c similarity index 100% rename from src/Common/Src/Byte_Order.c rename to src/Common/Src/Byte_Order/Byte_Order.c diff --git a/src/Common/Src/Byte_Order.h b/src/Common/Src/Byte_Order/Byte_Order.h similarity index 100% rename from src/Common/Src/Byte_Order.h rename to src/Common/Src/Byte_Order/Byte_Order.h diff --git a/src/Common/Src/Byte_Order_Floating_Points.c b/src/Common/Src/Byte_Order/Byte_Order_Floating_Points.c similarity index 100% rename from src/Common/Src/Byte_Order_Floating_Points.c rename to src/Common/Src/Byte_Order/Byte_Order_Floating_Points.c diff --git a/src/Common/Src/Byte_Order_Floating_Points.h b/src/Common/Src/Byte_Order/Byte_Order_Floating_Points.h similarity index 100% rename from src/Common/Src/Byte_Order_Floating_Points.h rename to src/Common/Src/Byte_Order/Byte_Order_Floating_Points.h diff --git a/src/Common/Src/Byte_Order_Integers.c b/src/Common/Src/Byte_Order/Byte_Order_Integers.c similarity index 100% rename from src/Common/Src/Byte_Order_Integers.c rename to src/Common/Src/Byte_Order/Byte_Order_Integers.c diff --git a/src/Common/Src/Byte_Order_Integers.h b/src/Common/Src/Byte_Order/Byte_Order_Integers.h similarity index 100% rename from src/Common/Src/Byte_Order_Integers.h rename to src/Common/Src/Byte_Order/Byte_Order_Integers.h From 86782e35e1622dcad03e45e773f26139ff6b8b86 Mon Sep 17 00:00:00 2001 From: codebase7 Date: Sat, 13 Jun 2015 13:32:17 -0400 Subject: [PATCH 028/325] Fix comments. This commit is a comment change commit for Byte_Order*.c files. (No code change.) --- src/Common/Src/Byte_Order/Byte_Order.c | 2 +- src/Common/Src/Byte_Order/Byte_Order_Floating_Points.c | 2 +- src/Common/Src/Byte_Order/Byte_Order_Integers.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Common/Src/Byte_Order/Byte_Order.c b/src/Common/Src/Byte_Order/Byte_Order.c index 9246a9c..3323cfc 100644 --- a/src/Common/Src/Byte_Order/Byte_Order.c +++ b/src/Common/Src/Byte_Order/Byte_Order.c @@ -18,7 +18,7 @@ https://github.com/codebase7/mengine */ -/* Include header */ +/* Internal includes. */ #include "Byte_Order.h" /* Check for C++ compiler. */ diff --git a/src/Common/Src/Byte_Order/Byte_Order_Floating_Points.c b/src/Common/Src/Byte_Order/Byte_Order_Floating_Points.c index c6dabe1..45d40f9 100644 --- a/src/Common/Src/Byte_Order/Byte_Order_Floating_Points.c +++ b/src/Common/Src/Byte_Order/Byte_Order_Floating_Points.c @@ -18,7 +18,7 @@ https://github.com/codebase7/mengine */ -/* Include main header. */ +/* Internal includes. */ #include "Byte_Order.h" /* Check for C++ compiler. */ diff --git a/src/Common/Src/Byte_Order/Byte_Order_Integers.c b/src/Common/Src/Byte_Order/Byte_Order_Integers.c index 6d0149d..263e952 100644 --- a/src/Common/Src/Byte_Order/Byte_Order_Integers.c +++ b/src/Common/Src/Byte_Order/Byte_Order_Integers.c @@ -18,7 +18,7 @@ https://github.com/codebase7/mengine */ -/* Include main header. */ +/* Internal includes. */ #include "Byte_Order.h" /* Check for C++ compiler. */ From c8fd818195d8081ebea701bc51d3cf81a4f9858c Mon Sep 17 00:00:00 2001 From: codebase7 Date: Sat, 13 Jun 2015 13:34:26 -0400 Subject: [PATCH 029/325] Add DLL export declarations for Byte_Order This commit adds the DLL exports for Byte_Order. --- src/Common/Src/Byte_Order/Byte_Order.h | 13 ++-- .../Byte_Order/Byte_Order_Floating_Points.h | 12 ++-- .../Src/Byte_Order/Byte_Order_Integers.h | 66 +++++++++---------- 3 files changed, 47 insertions(+), 44 deletions(-) diff --git a/src/Common/Src/Byte_Order/Byte_Order.h b/src/Common/Src/Byte_Order/Byte_Order.h index 1a1837d..e9886b9 100644 --- a/src/Common/Src/Byte_Order/Byte_Order.h +++ b/src/Common/Src/Byte_Order/Byte_Order.h @@ -32,6 +32,9 @@ extern "C" { #define MSYS_LITTLE_ENDIAN 1 #define MSYS_UNKNOWN_ENDIANNESS 2 +/* Pull in DLL_PORT.h */ +#include "../../../DLL_PORT.h" /* Defines MSYS_DLL_EXPORT, and MSYS_DLL_IMPORT_TEMPLATE. */ + /* Internal headers. */ #include "Byte_Order_Integers.h" #include "Byte_Order_Floating_Points.h" @@ -57,7 +60,7 @@ extern "C" { * * Otherwise returns the appropriate error code. */ -int Common_Byte_Swap(char * data, const size_t dataLength); +MSYS_DLL_EXPORT int Common_Byte_Swap(char * data, const size_t dataLength); /*! * int Common_Print_Bytes_To_CString(const char * data, const size_t dataLength, char ** retStr, size_t * retStrSize, const size_t base, @@ -92,7 +95,7 @@ int Common_Byte_Swap(char * data, const size_t dataLength); * * In case of error, (the returned error code is not COMMON_ERROR_SUCCESS, then the given arguments will NOT be altered by this function. */ -int Common_Print_Bytes_To_CString(const char * data, const size_t dataLength, char ** retStr, size_t * retStrSize, const size_t base, const size_t width, const char fillValue, const bool spaceBetweenBytes); +MSYS_DLL_EXPORT int Common_Print_Bytes_To_CString(const char * data, const size_t dataLength, char ** retStr, size_t * retStrSize, const size_t base, const size_t width, const char fillValue, const bool spaceBetweenBytes); /*! * void Common_Deallocate_Print_Bytes_CString(char ** str) @@ -104,7 +107,7 @@ int Common_Print_Bytes_To_CString(const char * data, const size_t dataLength, ch * * This function has no return. If a given pointer is NULL, this function will silently fail. */ -void Common_Deallocate_Print_Bytes_CString(char ** str); +MSYS_DLL_EXPORT void Common_Deallocate_Print_Bytes_CString(char ** str); /*! * int Common_Print_Bytes_In_Hex(const char * data, const size_t dataLength, char ** retStr, size_t * retStrSize, const bool spaceBetweenBytes) @@ -117,7 +120,7 @@ void Common_Deallocate_Print_Bytes_CString(char ** str); * All arguments and return values are identical to their Common_Print_Bytes_To_CString() counterparts. See Common_Print_Bytes_To_CString() * for their descriptions. */ -int Common_Print_Bytes_In_Hex(const char * data, const size_t dataLength, char ** retStr, size_t * retStrSize, const bool spaceBetweenBytes); +MSYS_DLL_EXPORT int Common_Print_Bytes_In_Hex(const char * data, const size_t dataLength, char ** retStr, size_t * retStrSize, const bool spaceBetweenBytes); /*! * int Common_Print_Bytes_In_Binary(const char * data, const size_t dataLength, char ** retStr, size_t * retStrSize, @@ -131,7 +134,7 @@ int Common_Print_Bytes_In_Hex(const char * data, const size_t dataLength, char * * All arguments and return values are identical to their Common_Print_Bytes_To_CString() counterparts. See Common_Print_Bytes_To_CString() * for their descriptions. */ -int Common_Print_Bytes_In_Binary(const char * data, const size_t dataLength, char ** retStr, size_t * retStrSize, const bool spaceBetweenBytes); +MSYS_DLL_EXPORT int Common_Print_Bytes_In_Binary(const char * data, const size_t dataLength, char ** retStr, size_t * retStrSize, const bool spaceBetweenBytes); #ifdef __cplusplus } /* extern "C" */ diff --git a/src/Common/Src/Byte_Order/Byte_Order_Floating_Points.h b/src/Common/Src/Byte_Order/Byte_Order_Floating_Points.h index 394abcb..8bcd0c5 100644 --- a/src/Common/Src/Byte_Order/Byte_Order_Floating_Points.h +++ b/src/Common/Src/Byte_Order/Byte_Order_Floating_Points.h @@ -51,7 +51,7 @@ extern "C" { * In case of error, (returned error code is not COMMON_ERROR_SUCCESS), * all arguments will be left unaltered. */ -int Common_Host_To_Big_Endian_Float(float * f); +MSYS_DLL_EXPORT int Common_Host_To_Big_Endian_Float(float * f); /*! * int Common_Big_Endian_To_Host_Float(float * f) @@ -72,7 +72,7 @@ int Common_Host_To_Big_Endian_Float(float * f); * In case of error, (returned error code is not COMMON_ERROR_SUCCESS), * all arguments will be left unaltered. */ -int Common_Big_Endian_To_Host_Float(float * f); +MSYS_DLL_EXPORT int Common_Big_Endian_To_Host_Float(float * f); /*! * int Common_Host_To_Big_Endian_DOUBLE(double * d) @@ -93,7 +93,7 @@ int Common_Big_Endian_To_Host_Float(float * f); * In case of error, (returned error code is not COMMON_ERROR_SUCCESS), * all arguments will be left unaltered. */ -int Common_Host_To_Big_Endian_Double(double * d); +MSYS_DLL_EXPORT int Common_Host_To_Big_Endian_Double(double * d); /*! * int Common_Big_Endian_To_Host_Double(double * d) @@ -114,7 +114,7 @@ int Common_Host_To_Big_Endian_Double(double * d); * In case of error, (returned error code is not COMMON_ERROR_SUCCESS), * all arguments will be left unaltered. */ -int Common_Big_Endian_To_Host_Double(double * d); +MSYS_DLL_EXPORT int Common_Big_Endian_To_Host_Double(double * d); /*! * General Definitions for the Common_*_Endianness_Check() functions: @@ -143,7 +143,7 @@ int Common_Big_Endian_To_Host_Double(double * d); * Returns MSYS_UNKNOWN_ENDIANNESS if the given data type's byte ordering * is unknown for the given host. */ -int Common_FLOAT_Endianness_Check(); +MSYS_DLL_EXPORT int Common_FLOAT_Endianness_Check(); /*! * int Common_DOUBLE_Endianness_Check() @@ -165,7 +165,7 @@ int Common_FLOAT_Endianness_Check(); * Returns MSYS_UNKNOWN_ENDIANNESS if the given data type's byte ordering * is unknown for the given host. */ -int Common_DOUBLE_Endianness_Check(); +MSYS_DLL_EXPORT int Common_DOUBLE_Endianness_Check(); #ifdef __cplusplus } /* extern "C" */ diff --git a/src/Common/Src/Byte_Order/Byte_Order_Integers.h b/src/Common/Src/Byte_Order/Byte_Order_Integers.h index 429a5ab..551f883 100644 --- a/src/Common/Src/Byte_Order/Byte_Order_Integers.h +++ b/src/Common/Src/Byte_Order/Byte_Order_Integers.h @@ -51,7 +51,7 @@ extern "C" { * In case of error, (returned error code is not COMMON_ERROR_SUCCESS), * all arguments will be left unaltered. */ -int Common_Host_To_Big_Endian_UChar(unsigned char * uc); +MSYS_DLL_EXPORT int Common_Host_To_Big_Endian_UChar(unsigned char * uc); /*! * int Common_Big_Endian_To_Host_UChar(unsigned char * uc) @@ -72,7 +72,7 @@ int Common_Host_To_Big_Endian_UChar(unsigned char * uc); * In case of error, (returned error code is not COMMON_ERROR_SUCCESS), * all arguments will be left unaltered. */ -int Common_Big_Endian_To_Host_UChar(unsigned char * uc); +MSYS_DLL_EXPORT int Common_Big_Endian_To_Host_UChar(unsigned char * uc); /*! * int Common_Host_To_Big_Endian_Char(char * c) @@ -93,7 +93,7 @@ int Common_Big_Endian_To_Host_UChar(unsigned char * uc); * In case of error, (returned error code is not COMMON_ERROR_SUCCESS), * all arguments will be left unaltered. */ -int Common_Host_To_Big_Endian_Char(char * c); +MSYS_DLL_EXPORT int Common_Host_To_Big_Endian_Char(char * c); /*! * int Common_Big_Endian_To_Host_Char(char * c) @@ -114,7 +114,7 @@ int Common_Host_To_Big_Endian_Char(char * c); * In case of error, (returned error code is not COMMON_ERROR_SUCCESS), * all arguments will be left unaltered. */ -int Common_Big_Endian_To_Host_Char(char * c); +MSYS_DLL_EXPORT int Common_Big_Endian_To_Host_Char(char * c); /*! * int Common_Host_To_Big_Endian_UShort(unsigned short * us) @@ -135,7 +135,7 @@ int Common_Big_Endian_To_Host_Char(char * c); * In case of error, (returned error code is not COMMON_ERROR_SUCCESS), * all arguments will be left unaltered. */ -int Common_Host_To_Big_Endian_UShort(unsigned short * us); +MSYS_DLL_EXPORT int Common_Host_To_Big_Endian_UShort(unsigned short * us); /*! * int Common_Big_Endian_To_Host_UShort(unsigned short * us) @@ -156,7 +156,7 @@ int Common_Host_To_Big_Endian_UShort(unsigned short * us); * In case of error, (returned error code is not COMMON_ERROR_SUCCESS), * all arguments will be left unaltered. */ -int Common_Big_Endian_To_Host_UShort(unsigned short * us); +MSYS_DLL_EXPORT int Common_Big_Endian_To_Host_UShort(unsigned short * us); /*! * int Common_Host_To_Big_Endian_Short(short * s) @@ -177,7 +177,7 @@ int Common_Big_Endian_To_Host_UShort(unsigned short * us); * In case of error, (returned error code is not COMMON_ERROR_SUCCESS), * all arguments will be left unaltered. */ -int Common_Host_To_Big_Endian_Short(short * s); +MSYS_DLL_EXPORT int Common_Host_To_Big_Endian_Short(short * s); /*! * int Common_Big_Endian_To_Host_Short(short * s) @@ -198,7 +198,7 @@ int Common_Host_To_Big_Endian_Short(short * s); * In case of error, (returned error code is not COMMON_ERROR_SUCCESS), * all arguments will be left unaltered. */ -int Common_Big_Endian_To_Host_Short(short * s); +MSYS_DLL_EXPORT int Common_Big_Endian_To_Host_Short(short * s); /*! * int Common_Host_To_Big_Endian_UInt(unsigned int * ui) @@ -219,7 +219,7 @@ int Common_Big_Endian_To_Host_Short(short * s); * In case of error, (returned error code is not COMMON_ERROR_SUCCESS), * all arguments will be left unaltered. */ -int Common_Host_To_Big_Endian_UInt(unsigned int * ui); +MSYS_DLL_EXPORT int Common_Host_To_Big_Endian_UInt(unsigned int * ui); /*! * int Common_Big_Endian_To_Host_UInt(unsigned int * ui) @@ -240,7 +240,7 @@ int Common_Host_To_Big_Endian_UInt(unsigned int * ui); * In case of error, (returned error code is not COMMON_ERROR_SUCCESS), * all arguments will be left unaltered. */ -int Common_Big_Endian_To_Host_UInt(unsigned int * ui); +MSYS_DLL_EXPORT int Common_Big_Endian_To_Host_UInt(unsigned int * ui); /*! * int Common_Host_To_Big_Endian_Int(int * i) @@ -261,7 +261,7 @@ int Common_Big_Endian_To_Host_UInt(unsigned int * ui); * In case of error, (returned error code is not COMMON_ERROR_SUCCESS), * all arguments will be left unaltered. */ -int Common_Host_To_Big_Endian_Int(int * i); +MSYS_DLL_EXPORT int Common_Host_To_Big_Endian_Int(int * i); /*! * int Common_Big_Endian_To_Host_Int(int * i) @@ -282,7 +282,7 @@ int Common_Host_To_Big_Endian_Int(int * i); * In case of error, (returned error code is not COMMON_ERROR_SUCCESS), * all arguments will be left unaltered. */ -int Common_Big_Endian_To_Host_Int(int * i); +MSYS_DLL_EXPORT int Common_Big_Endian_To_Host_Int(int * i); /*! * int Common_Host_To_Big_Endian_ULong(unsigned long * ul) @@ -303,7 +303,7 @@ int Common_Big_Endian_To_Host_Int(int * i); * In case of error, (returned error code is not COMMON_ERROR_SUCCESS), * all arguments will be left unaltered. */ -int Common_Host_To_Big_Endian_ULong(unsigned long * ul); +MSYS_DLL_EXPORT int Common_Host_To_Big_Endian_ULong(unsigned long * ul); /*! * int Common_Big_Endian_To_Host_ULong(unsigned long * ul) @@ -324,7 +324,7 @@ int Common_Host_To_Big_Endian_ULong(unsigned long * ul); * In case of error, (returned error code is not COMMON_ERROR_SUCCESS), * all arguments will be left unaltered. */ -int Common_Big_Endian_To_Host_ULong(unsigned long * ul); +MSYS_DLL_EXPORT int Common_Big_Endian_To_Host_ULong(unsigned long * ul); /*! * int Common_Host_To_Big_Endian_Long(long * l) @@ -345,7 +345,7 @@ int Common_Big_Endian_To_Host_ULong(unsigned long * ul); * In case of error, (returned error code is not COMMON_ERROR_SUCCESS), * all arguments will be left unaltered. */ -int Common_Host_To_Big_Endian_Long(long * l); +MSYS_DLL_EXPORT int Common_Host_To_Big_Endian_Long(long * l); /*! * int Common_Big_Endian_To_Host_Long(long * l) @@ -366,7 +366,7 @@ int Common_Host_To_Big_Endian_Long(long * l); * In case of error, (returned error code is not COMMON_ERROR_SUCCESS), * all arguments will be left unaltered. */ -int Common_Big_Endian_To_Host_Long(long * l); +MSYS_DLL_EXPORT int Common_Big_Endian_To_Host_Long(long * l); /*! * int Common_Host_To_Big_Endian_ULong_Long(unsigned long long * ull) @@ -387,7 +387,7 @@ int Common_Big_Endian_To_Host_Long(long * l); * In case of error, (returned error code is not COMMON_ERROR_SUCCESS), * all arguments will be left unaltered. */ -int Common_Host_To_Big_Endian_ULong_Long(unsigned long long * ull); +MSYS_DLL_EXPORT int Common_Host_To_Big_Endian_ULong_Long(unsigned long long * ull); /*! * int Common_Big_Endian_To_Host_ULong_Long(unsigned long long * ull) @@ -408,7 +408,7 @@ int Common_Host_To_Big_Endian_ULong_Long(unsigned long long * ull); * In case of error, (returned error code is not COMMON_ERROR_SUCCESS), * all arguments will be left unaltered. */ -int Common_Big_Endian_To_Host_ULong_Long(unsigned long long * ull); +MSYS_DLL_EXPORT int Common_Big_Endian_To_Host_ULong_Long(unsigned long long * ull); /*! * int Common_Host_To_Big_Endian_Long_Long(long long * ull) @@ -429,7 +429,7 @@ int Common_Big_Endian_To_Host_ULong_Long(unsigned long long * ull); * In case of error, (returned error code is not COMMON_ERROR_SUCCESS), * all arguments will be left unaltered. */ -int Common_Host_To_Big_Endian_Long_Long(long long * ll); +MSYS_DLL_EXPORT int Common_Host_To_Big_Endian_Long_Long(long long * ll); /*! * int Common_Big_Endian_To_Host_Long_Long(long long * ll) @@ -450,7 +450,7 @@ int Common_Host_To_Big_Endian_Long_Long(long long * ll); * In case of error, (returned error code is not COMMON_ERROR_SUCCESS), * all arguments will be left unaltered. */ -int Common_Big_Endian_To_Host_Long_Long(long long * ll); +MSYS_DLL_EXPORT int Common_Big_Endian_To_Host_Long_Long(long long * ll); /*! * int Common_Host_To_Big_Endian_Size_T(size_t * st) @@ -471,7 +471,7 @@ int Common_Big_Endian_To_Host_Long_Long(long long * ll); * In case of error, (returned error code is not COMMON_ERROR_SUCCESS), * all arguments will be left unaltered. */ -int Common_Host_To_Big_Endian_Size_T(size_t * st); +MSYS_DLL_EXPORT int Common_Host_To_Big_Endian_Size_T(size_t * st); /*! * int Common_Big_Endian_To_Host_Size_T(size_t * st) @@ -492,7 +492,7 @@ int Common_Host_To_Big_Endian_Size_T(size_t * st); * In case of error, (returned error code is not COMMON_ERROR_SUCCESS), * all arguments will be left unaltered. */ -int Common_Big_Endian_To_Host_Size_T(size_t * st); +MSYS_DLL_EXPORT int Common_Big_Endian_To_Host_Size_T(size_t * st); /*! * General Definitions for the Common_*_Endianness_Check() functions: @@ -521,7 +521,7 @@ int Common_Big_Endian_To_Host_Size_T(size_t * st); * Returns MSYS_UNKNOWN_ENDIANNESS if the given data type's byte ordering * is unknown for the given host. */ -int Common_UCHAR_Endianness_Check(); +MSYS_DLL_EXPORT int Common_UCHAR_Endianness_Check(); /*! * int Common_CHAR_Endianness_Check() @@ -543,7 +543,7 @@ int Common_UCHAR_Endianness_Check(); * Returns MSYS_UNKNOWN_ENDIANNESS if the given data type's byte ordering * is unknown for the given host. */ -int Common_CHAR_Endianness_Check(); +MSYS_DLL_EXPORT int Common_CHAR_Endianness_Check(); /*! * int Common_USHORT_Endianness_Check() @@ -565,7 +565,7 @@ int Common_CHAR_Endianness_Check(); * Returns MSYS_UNKNOWN_ENDIANNESS if the given data type's byte ordering * is unknown for the given host. */ -int Common_USHORT_Endianness_Check(); +MSYS_DLL_EXPORT int Common_USHORT_Endianness_Check(); /*! * int Common_SHORT_Endianness_Check() @@ -587,7 +587,7 @@ int Common_USHORT_Endianness_Check(); * Returns MSYS_UNKNOWN_ENDIANNESS if the given data type's byte ordering * is unknown for the given host. */ -int Common_SHORT_Endianness_Check(); +MSYS_DLL_EXPORT int Common_SHORT_Endianness_Check(); /*! * int Common_UINT_Endianness_Check() @@ -609,7 +609,7 @@ int Common_SHORT_Endianness_Check(); * Returns MSYS_UNKNOWN_ENDIANNESS if the given data type's byte ordering * is unknown for the given host. */ -int Common_UINT_Endianness_Check(); +MSYS_DLL_EXPORT int Common_UINT_Endianness_Check(); /*! * int Common_INT_Endianness_Check() @@ -631,7 +631,7 @@ int Common_UINT_Endianness_Check(); * Returns MSYS_UNKNOWN_ENDIANNESS if the given data type's byte ordering * is unknown for the given host. */ -int Common_INT_Endianness_Check(); +MSYS_DLL_EXPORT int Common_INT_Endianness_Check(); /*! * int Common_ULONG_Endianness_Check() @@ -653,7 +653,7 @@ int Common_INT_Endianness_Check(); * Returns MSYS_UNKNOWN_ENDIANNESS if the given data type's byte ordering * is unknown for the given host. */ -int Common_ULONG_Endianness_Check(); +MSYS_DLL_EXPORT int Common_ULONG_Endianness_Check(); /*! * int Common_LONG_Endianness_Check() @@ -675,7 +675,7 @@ int Common_ULONG_Endianness_Check(); * Returns MSYS_UNKNOWN_ENDIANNESS if the given data type's byte ordering * is unknown for the given host. */ -int Common_LONG_Endianness_Check(); +MSYS_DLL_EXPORT int Common_LONG_Endianness_Check(); /*! * int Common_ULONG_LONG_Endianness_Check() @@ -697,7 +697,7 @@ int Common_LONG_Endianness_Check(); * Returns MSYS_UNKNOWN_ENDIANNESS if the given data type's byte ordering * is unknown for the given host. */ -int Common_ULONG_LONG_Endianness_Check(); +MSYS_DLL_EXPORT int Common_ULONG_LONG_Endianness_Check(); /*! * int Common_LONG_LONG_Endianness_Check() @@ -719,7 +719,7 @@ int Common_ULONG_LONG_Endianness_Check(); * Returns MSYS_UNKNOWN_ENDIANNESS if the given data type's byte ordering * is unknown for the given host. */ -int Common_LONG_LONG_Endianness_Check(); +MSYS_DLL_EXPORT int Common_LONG_LONG_Endianness_Check(); /*! * int Common_SIZE_T_Endianness_Check() @@ -741,7 +741,7 @@ int Common_LONG_LONG_Endianness_Check(); * Returns MSYS_UNKNOWN_ENDIANNESS if the given data type's byte ordering * is unknown for the given host. */ -int Common_SIZE_T_Endianness_Check(); +MSYS_DLL_EXPORT int Common_SIZE_T_Endianness_Check(); #ifdef __cplusplus } /* extern "C" */ From 7d13e411815a7c5f321508df352e36544ed99be4 Mon Sep 17 00:00:00 2001 From: codebase7 Date: Sat, 13 Jun 2015 13:35:51 -0400 Subject: [PATCH 030/325] Forgot to include the Common Error Code header. This commit adds the Common_Error_Handler_Structures.h header to Byte_Order.h. --- src/Common/Src/Byte_Order/Byte_Order.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Common/Src/Byte_Order/Byte_Order.h b/src/Common/Src/Byte_Order/Byte_Order.h index e9886b9..46806f0 100644 --- a/src/Common/Src/Byte_Order/Byte_Order.h +++ b/src/Common/Src/Byte_Order/Byte_Order.h @@ -36,6 +36,7 @@ extern "C" { #include "../../../DLL_PORT.h" /* Defines MSYS_DLL_EXPORT, and MSYS_DLL_IMPORT_TEMPLATE. */ /* Internal headers. */ +#include "../Error_Handler/Common_Error_Handler_Structures.h" /* Defines the error codes. */ #include "Byte_Order_Integers.h" #include "Byte_Order_Floating_Points.h" From b58b843b17bbc8caa65dd2fd6188ab2e26c13bf1 Mon Sep 17 00:00:00 2001 From: codebase7 Date: Sat, 13 Jun 2015 13:57:29 -0400 Subject: [PATCH 031/325] Add CMake build code. This commit adds Byte_Order's CMakeLists.txt as well as making the needed changes to support it in the build. Note: Building is disabled by default currently, pending the needed merge of error_handler into master. (Error code changes.) --- CMakeLists.txt | 1 + src/Common/Src/Byte_Order/CMakeLists.txt | 14 ++++++++++++++ src/Common/Src/CMakeLists.txt | 5 +++++ 3 files changed, 20 insertions(+) create mode 100644 src/Common/Src/Byte_Order/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 2129543..69b0ef7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,6 +19,7 @@ set(O_OUTPUT_DIR ${T_OUTPUT_DIR}/obj CACHE PATH "Build object output directory") endif() # Option Defaults. +option (BUILD_BYTE_ORDER "Whether or not to build the Byte Ordering code. (Defaults to yes, but is disabled currently due to changes to the Common error handler (error code changes) that have not been commited yet.)" OFF) option (BUILD_DYNAMIC_LIBRARY_SUBSYSTEM "Whether or not to build the Dynamic Library Subsystem. (Defaults to yes.)" ON) option (BUILD_INTERNAL_MUTEX_SUPPORT "Whether or not to build the internal mutex support library. (Defaults to yes.)" ON) option (BUILD_COMMON_ERROR_HANDLER "Whether or not to build the common error handler. (Defaults to yes.)" ON) diff --git a/src/Common/Src/Byte_Order/CMakeLists.txt b/src/Common/Src/Byte_Order/CMakeLists.txt new file mode 100644 index 0000000..d97141a --- /dev/null +++ b/src/Common/Src/Byte_Order/CMakeLists.txt @@ -0,0 +1,14 @@ +# Set output directories. +set(LIBRARY_OUTPUT_PATH ${L_OUTPUT_DIR}) +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${O_OUTPUT_DIR}) + +# Define includes. +set (BYTE_ORDER_INCLUDES Byte_Order.c +Byte_Order_Floating_Points.c +Byte_Order_Integers.c) + +# Define static library. +add_library (Common_Byte_Order_Multiverse_Engine_Static STATIC ${BYTE_ORDER_INCLUDES}) + +# Define shared library. +add_library (Common_Byte_Order_Multiverse_Engine SHARED ${BYTE_ORDER_INCLUDES}) diff --git a/src/Common/Src/CMakeLists.txt b/src/Common/Src/CMakeLists.txt index cd3b0ff..8c2589d 100644 --- a/src/Common/Src/CMakeLists.txt +++ b/src/Common/Src/CMakeLists.txt @@ -2,6 +2,11 @@ set(LIBRARY_OUTPUT_PATH ${L_OUTPUT_DIR}) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${O_OUTPUT_DIR}) +# Create the Byte_Order library. +if (BUILD_BYTE_ORDER) + add_subdirectory(Byte_Order) + set (COMMON_BUILT_STATIC_LIBRARY_LIST ${COMMON_BUILT_STATIC_LIBRARY_LIST} Common_Byte_Order_Multiverse_Engine_Static) +endif (BUILD_BYTE_ORDER) # Create the mutexes library. if (BUILD_INTERNAL_MUTEX_SUPPORT) From 90561443ad1a827f6d19159020f0a12c41061c39 Mon Sep 17 00:00:00 2001 From: codebase7 Date: Sat, 13 Jun 2015 17:42:32 -0400 Subject: [PATCH 032/325] Enable Byte_Order build This commit enables the Byte_Order build in CMake. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index dd69ad7..faa9459 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,7 +19,7 @@ set(O_OUTPUT_DIR ${T_OUTPUT_DIR}/obj CACHE PATH "Build object output directory") endif() # Option Defaults. -option (BUILD_BYTE_ORDER "Whether or not to build the Byte Ordering code. (Defaults to yes, but is disabled currently due to changes to the Common error handler (error code changes) that have not been commited yet.)" OFF) +option (BUILD_BYTE_ORDER "Whether or not to build the Byte Ordering code. (Defaults to yes.)" ON) option (BUILD_DYNAMIC_LIBRARY_SUBSYSTEM "Whether or not to build the Dynamic Library Subsystem. (Defaults to yes.)" ON) option (BUILD_COMMON_ERROR_HANDLER "Whether or not to build the Common Error Handler. (Defaults to yes.)" ON) option (BUILD_FATAL_ERROR_NOTIFY_SUPPORT "Whether or not to build the Common Error Handler's fatal error notification support. (Defaults to yes.)" ON) From f364bcb30dd26465af7d625bd7acd744e84c0faa Mon Sep 17 00:00:00 2001 From: codebase7 Date: Thu, 25 Jun 2015 21:59:46 -0400 Subject: [PATCH 033/325] Removal of namespace scope rez p1 This commit removes the namespace scope operators from the FileUtills.h header file. (Part 1 of converting the file to C code. API Changes.) --- .../File_Management_Subsystem/FileUtills.h | 74 +++++++++---------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/src/Common/Src/File_Management_Subsystem/FileUtills.h b/src/Common/Src/File_Management_Subsystem/FileUtills.h index 4ef8254..d642d12 100644 --- a/src/Common/Src/File_Management_Subsystem/FileUtills.h +++ b/src/Common/Src/File_Management_Subsystem/FileUtills.h @@ -96,7 +96,7 @@ struct dirlist{ int FileUtills_Write_Data_To_File_From_Memory(FILE * OUT, const char * data, const size_t dataLength); /*! - * int FileUtills::GetUserProfileDirectoryPath(char ** retStr, size_t * retStrSize) + * int FileUtills_GetUserProfileDirectoryPath(char ** retStr, size_t * retStrSize) * * Fetches the user's profile directory from the environment, and stores * it in the given path argument. @@ -107,7 +107,7 @@ int FileUtills_Write_Data_To_File_From_Memory(FILE * OUT, const char * data, con int GetUserProfileDirectoryPath(char ** retStr, size_t * retStrSize); /*! - * int FileUtills::GetCurrentWorkingDirectoryPath(char ** path, size_t * pathSize) + * int FileUtills_GetCurrentWorkingDirectoryPath(char ** path, size_t * pathSize) * * Fetches the current working directory from the environment, and stores * it in the given retStr argument. @@ -118,7 +118,7 @@ int GetUserProfileDirectoryPath(char ** retStr, size_t * retStrSize); int GetCurrentWorkingDirectoryPath(char ** retStr, size_t * retStrSize); /*! - * int FileUtills::GetExecDirectory(char ** path, size_t * pathSize) + * int FileUtills_GetExecDirectory(char ** path, size_t * pathSize) * * Replaces the contents of the given retStr argument with a NULL * terminated C-String that contains the path to the directory where the @@ -130,14 +130,14 @@ int GetCurrentWorkingDirectoryPath(char ** retStr, size_t * retStrSize); int GetExecDirectory(char ** retStr, size_t * retStrSize); /*! - int getDirectory(const char * path, const size_t pathSize, FileUtills::dirlist ** dirTree, const bool & cleanList) + int getDirectory(const char * path, const size_t pathSize, FileUtills_dirlist ** dirTree, const bool & cleanList) Lists the given directory's contents. Pram: path, path of directory to check. - Pram: FileUtills::dirlist ** dirTree, pointer to a pointer to a - FileUtills::dirlist structure that will contain the resulting + Pram: FileUtills_dirlist ** dirTree, pointer to a pointer to a + FileUtills_dirlist structure that will contain the resulting directory listing if successful. If the structure is already allocated when passed to this function and this function succeeds, the pre-existing structure will be deallocated. @@ -155,22 +155,22 @@ int GetExecDirectory(char ** retStr, size_t * retStrSize); set cleanList to true when calling this function. Returns COMMON_ERROR_SUCCESS if successfull, dirTree's pointer will point to a valid - FileUtills::dirlist structure with the given path's contents in this case. + FileUtills_dirlist structure with the given path's contents in this case. (Any previous structure pointed to by the dirTree pointer will be deallocated.) Otherwise this function will return the appropriate error, and dirTree's pointer will not be modified. */ -int getDirectory(const char * path, const size_t pathSize, dirlist ** dirTree, const bool cleanList); +int getDirectory(const char * path, const size_t pathSize, FileUtills_dirlist ** dirTree, const bool cleanList); /*! - int FileUtills::DoesExist(const char * path, const size_t pathSize) + int FileUtills_DoesExist(const char * path, const size_t pathSize) Prams: @std::string path, path to check for existence on the filesystem. This function checks to see if given file or directory exists. - This function is called by FileUtills::CheckPermissions() before running permission checks. + This function is called by FileUtills_CheckPermissions() before running permission checks. Returns FILEUTILLS_ERROR_EXISTANT if file or directory exists on the system. Returns FILEUTILLS_ERROR_NON_EXISTANT if file or directory does not exist on the system. @@ -181,7 +181,7 @@ int getDirectory(const char * path, const size_t pathSize, dirlist ** dirTree, c int DoesExist(const char * path, const size_t pathSize); /*! - FileUtills::IsFileOrDirectory(const char * path, const size_t pathSize) + FileUtills_IsFileOrDirectory(const char * path, const size_t pathSize) Checks to see if a given path is a file or directory. @@ -198,7 +198,7 @@ int DoesExist(const char * path, const size_t pathSize); int IsFileOrDirectory(const char * path, const size_t pathSize); /*! - int FileUtills::CheckParent(const char * path, const size_t pathSize, const bool read, const bool write, const bool exec) + int FileUtills_CheckParent(const char * path, const size_t pathSize, const bool read, const bool write, const bool exec) Acts as a wrapper to DoesExist and CheckPermissions Checks for the parent directory's existence in the path given. @@ -225,11 +225,11 @@ int IsFileOrDirectory(const char * path, const size_t pathSize); int CheckParent(const char * path, const size_t pathSize, const bool read, const bool write, const bool exec); /*! - int FileUtills::GetParent(char ** retStr, size_t * retStrSize) + int FileUtills_GetParent(char ** retStr, size_t * retStrSize) Returns the parent directory for the given file. - Gets the path exactly like FileUtills::CheckParent(). + Gets the path exactly like FileUtills_CheckParent(). Returns COMMON_ERROR_SUCCESS with parent directory path set in retStr if successful. (retStr's size will be set in retStrSize.) @@ -240,7 +240,7 @@ int CheckParent(const char * path, const size_t pathSize, const bool read, const int GetParent(char ** retStr, size_t * retStrSize); /*! - int FileUtills::ResolvePath(const char * path, const size_t pathSize, char ** retStr, size_t * retStrSize, const bool disableSymLinkResolution) + int FileUtills_ResolvePath(const char * path, const size_t pathSize, char ** retStr, size_t * retStrSize, const bool disableSymLinkResolution) Checks the path given, and converts it to a absolute path. @@ -258,7 +258,7 @@ int GetParent(char ** retStr, size_t * retStrSize); int ResolvePath(const char * path, const size_t pathSize, char ** retStr, size_t * retStrSize, const bool disableSymLinkResolution); /*! - int FileUtills::CreateDirectory(const char * directory, const size_t directorySize, const bool createRecursive) + int FileUtills_CreateDirectory(const char * directory, const size_t directorySize, const bool createRecursive) @pram : directory, path to create. @pram : createRecursive, if this is set to true, then this function will try to create the parent directories of the given directory if they do not exist. @@ -275,7 +275,7 @@ int ResolvePath(const char * path, const size_t pathSize, char ** retStr, size_t int CreateDirectory(const char * directory, const size_t directorySize, const bool createRecursive); /*! - int FileUtills::CheckPermissions(const char * path, const size_t pathSize, const bool read, const bool write, const bool exec) + int FileUtills_CheckPermissions(const char * path, const size_t pathSize, const bool read, const bool write, const bool exec) Checks Permissions on the given file or directory. Also checks if the given file or directory actually exists first before checking other permissions. By default it will check for both read and @@ -301,7 +301,7 @@ int CreateDirectory(const char * directory, const size_t directorySize, const bo int CheckPermissions(const char * path, const size_t pathSize, const bool read, const bool write, const bool exec); /*! - int FileUtills::GetGigaFreespace(const char * path, const size_t pathSize, size_t * result) + int FileUtills_GetGigaFreespace(const char * path, const size_t pathSize, size_t * result) Returns the remaining disk space in Gigabytes (SI Unit) on the given disk. @@ -319,7 +319,7 @@ int CheckPermissions(const char * path, const size_t pathSize, const bool read, int GetGigaFreespace(const char * path, const size_t pathSize, size_t * result); /*! - int FileUtills::GetFreespace(const char * path, const size_t pathSize, size_t * result) + int FileUtills_GetFreespace(const char * path, const size_t pathSize, size_t * result) Returns the remaining disk space in Megabytes (SI Unit) on the given disk. @@ -337,7 +337,7 @@ int GetGigaFreespace(const char * path, const size_t pathSize, size_t * result); int GetFreespace(const char * path, const size_t pathSize, size_t * result); /*! - int FileUtills::GetKiloFreespace(const char * path, const size_t pathSize, size_t * result) + int FileUtills_GetKiloFreespace(const char * path, const size_t pathSize, size_t * result) Returns the remaining disk space in Kilobytes (SI Unit) on the given disk. @@ -355,7 +355,7 @@ int GetFreespace(const char * path, const size_t pathSize, size_t * result); int GetKiloFreespace(const char * path, const size_t pathSize, size_t * result); /*! - int FileUtills::GetByteFreespace(const char * path, const size_t pathSize, size_t * result) + int FileUtills_GetByteFreespace(const char * path, const size_t pathSize, size_t * result) Returns the remaining disk space in Bytes (SI Unit) on the given disk. @@ -373,7 +373,7 @@ int GetKiloFreespace(const char * path, const size_t pathSize, size_t * result); int GetByteFreespace(const char * path, const size_t pathSize, size_t * result); /*! - int FileUtills::DeletePath(const char * path, const size_t pathSize, const bool recursive) + int FileUtills_DeletePath(const char * path, const size_t pathSize, const bool recursive) This function attempts to delete the given file or directory from the filesystem. @@ -397,7 +397,7 @@ int GetByteFreespace(const char * path, const size_t pathSize, size_t * result); int DeletePath(const char * path, const size_t pathSize, const bool recursive); /*! - int FileUtills::CopyFile(const char * srcPath, const size_t srcPathSize, const char * destPath, const size_t destPathSize, + int FileUtills_CopyFile(const char * srcPath, const size_t srcPathSize, const char * destPath, const size_t destPathSize, const bool append, const size_t begOffset, const size_t endOffset) Copies endOffset bytes starting at begOffset, from source file to dest file. @@ -423,7 +423,7 @@ int DeletePath(const char * path, const size_t pathSize, const bool recursive); (This allows for some insurance if the source file's size is known before calling this function.) - This function only works on FILES. Not directories. To copy a directory, call FileUtills::CopyPath(). + This function only works on FILES. Not directories. To copy a directory, call FileUtills_CopyPath(). @pram src, path to the source file. @pram dest, path to the dest file. @@ -462,7 +462,7 @@ int CopyFile(const char * srcPath, const size_t srcPathSize, const char * destPa const size_t begOffset, const size_t endOffset); /*! - int FileUtills::CopyPath(const char * srcPath, const size_t srcPathSize, const char * destPath, const size_t destPathSize, const bool recursive, + int FileUtills_CopyPath(const char * srcPath, const size_t srcPathSize, const char * destPath, const size_t destPathSize, const bool recursive, const bool rename, const bool abort_on_failure, const bool append, const size_t begOffset, const size_t endOffset) This function takes a given source path and copies it to the given dest path. @@ -470,7 +470,7 @@ int CopyFile(const char * srcPath, const size_t srcPathSize, const char * destPa This function supports files and directories. If you give a file as src and a directory as dest, the function WILL return an error. - If the given src is a file, then this function acts as a wrapper to FileUtills::CopyFile(), and returns all of it's + If the given src is a file, then this function acts as a wrapper to FileUtills_CopyFile(), and returns all of it's error codes. If the given src is a directory, then this function will copy the entire directory to the given dest, creating dest if @@ -494,19 +494,19 @@ int CopyFile(const char * srcPath, const size_t srcPathSize, const char * destPa otherwise this function will try to continue with the remaining list of files and subdirectories. (Default) @pram append, this is only used if src is a file. (As this function acts as a wrapper to CopyFile() in that case, - see FileUtills::CopyFile() for it's description. This function provides the same default value for this pram as CopyFile().) + see FileUtills_CopyFile() for it's description. This function provides the same default value for this pram as CopyFile().) If src is a directory, this pram has no effect. @pram begOffset, this is only used if src is a file. (As this function acts as a wrapper to CopyFile() in that case, - see FileUtills::CopyFile() for it's description. This function provides the same default value for this pram as CopyFile().) + see FileUtills_CopyFile() for it's description. This function provides the same default value for this pram as CopyFile().) If src is a directory, this pram has no effect. @pram endOffset, this is only used if src is a file. (As this function acts as a wrapper to CopyFile() in that case, - see FileUtills::CopyFile() for it's description. This function provides the same default value for this pram as CopyFile().) + see FileUtills_CopyFile() for it's description. This function provides the same default value for this pram as CopyFile().) If src is a directory, this pram has no effect. Below are return codes for when src is a directory, if src is a file, then the return codes for this function are identical to - FileUtills::CopyFile(). Please see FileUtills::CopyFile() for it's return codes. + FileUtills_CopyFile(). Please see FileUtills_CopyFile() for it's return codes. Returns COMMON_ERROR_SUCCESS on success. Returns -1 if the function was unable to create top level dest path and top level dest path does not exist. @@ -515,18 +515,18 @@ int CopyFile(const char * srcPath, const size_t srcPathSize, const char * destPa Returns -4 if the function could not get a directory listing. Returns -5 if the function could not get parent directory string. Returns -6 if the function was unable to copy all files. (Some files may have been copied however.) - Returns -13 if FileUtills::IsFileOrDirectory() returns -3. (OS / Arch not supported.) - Returns -14 if FileUtills::IsFileOrDirectory() returns -4. (A permissions error occurred.) - Returns -15 if FileUtills::IsFileOrDirectory() returns -5. (The given path is empty.) - Returns -16 if FileUtills::IsFileOrDirectory() returns -6. (A path component does not exist.) - Returns -17 if FileUtills::IsFileOrDirectory() returns -7. (The path has a file in it and is not at the end. (I.e you are treating a file as a directory.)) - Returns COMMON_ERROR_UNKNOWN_ERROR if FileUtills::IsFileOrDirectory() returns -9. (All other errors.) + Returns -13 if FileUtills_IsFileOrDirectory() returns -3. (OS / Arch not supported.) + Returns -14 if FileUtills_IsFileOrDirectory() returns -4. (A permissions error occurred.) + Returns -15 if FileUtills_IsFileOrDirectory() returns -5. (The given path is empty.) + Returns -16 if FileUtills_IsFileOrDirectory() returns -6. (A path component does not exist.) + Returns -17 if FileUtills_IsFileOrDirectory() returns -7. (The path has a file in it and is not at the end. (I.e you are treating a file as a directory.)) + Returns COMMON_ERROR_UNKNOWN_ERROR if FileUtills_IsFileOrDirectory() returns -9. (All other errors.) */ int CopyPath(const char * srcPath, const size_t srcPathSize, const char * destPath, const size_t destPathSize, const bool recursive, const bool rename, const bool abort_on_failure, const bool append, const size_t begOffset, const size_t endOffset); /*! - int FileUtills::MovePath(const char * srcPath, const size_t srcPathSize, const char * destPath, const size_t destPathSize, const bool overwrite) + int FileUtills_MovePath(const char * srcPath, const size_t srcPathSize, const char * destPath, const size_t destPathSize, const bool overwrite) Acts as a wrapper for a call to CopyPath and DeletePath. The srcPath is copied to the destPath and then the srcPath is deleted. From b1b986855ea8e4cde1e7dba42bbaf65386d6783a Mon Sep 17 00:00:00 2001 From: codebase7 Date: Sun, 5 Jul 2015 00:17:34 -0400 Subject: [PATCH 034/325] Remove namespace decl from FileUtills.h This commit removes the namespace declaration from FileUtills.h, renames all functions and data structures to contain FileUtills_ at the beginning, and modifies the dirList structure to be a linked list structure. (Needed functions for it are not delcared nor defined yet.) (Fixing FileUtills Header as per API changes, part 2.) --- .../File_Management_Subsystem/FileUtills.h | 56 +++++++++---------- 1 file changed, 26 insertions(+), 30 deletions(-) diff --git a/src/Common/Src/File_Management_Subsystem/FileUtills.h b/src/Common/Src/File_Management_Subsystem/FileUtills.h index d642d12..fc8fee6 100644 --- a/src/Common/Src/File_Management_Subsystem/FileUtills.h +++ b/src/Common/Src/File_Management_Subsystem/FileUtills.h @@ -33,8 +33,6 @@ #include "../Error_Handler/Common_Error_Handler_Internal.h" #endif -namespace FileUtills{ - #ifdef _WIN32 // Define the Windows Directory seperator #define DIR_SEP '\\' @@ -65,12 +63,13 @@ namespace FileUtills{ #endif #endif -// Define the directory list structure -struct dirlist{ - size_t numOfEntries; // Used to store the number of entries in the list array. - std::vector list; // Used to store the directory's entry data. - std::string path; // Used to store the path of the directory that the entry list is about. -}; +/* Define the directory list structure. */ +typedef struct FileUtills_dirlist { + size_t numOfEntries; /* Used to store the number of entries in the list array. */ + std::vector list; /* Used to store the directory's entry data. */ + char * path; /* Used to store the path of the directory that the entry list is about. */ + size_t pathSize; /* Length of the path string. */ +} FileUtills_dirlist_T; /*! * int FileUtills_Write_Data_To_File_From_Memory(FILE * OUT, const char * data, const size_t dataLength) @@ -104,7 +103,7 @@ int FileUtills_Write_Data_To_File_From_Memory(FILE * OUT, const char * data, con * If the function fails for any reason, the arguments will NOT be altered, * and the appropriate error will be returned to the caller. */ -int GetUserProfileDirectoryPath(char ** retStr, size_t * retStrSize); +int FileUtills_GetUserProfileDirectoryPath(char ** retStr, size_t * retStrSize); /*! * int FileUtills_GetCurrentWorkingDirectoryPath(char ** path, size_t * pathSize) @@ -115,7 +114,7 @@ int GetUserProfileDirectoryPath(char ** retStr, size_t * retStrSize); * If the function fails for any reason, the arguments will NOT be altered, * and the appropriate error will be returned to the caller. */ -int GetCurrentWorkingDirectoryPath(char ** retStr, size_t * retStrSize); +int FileUtills_GetCurrentWorkingDirectoryPath(char ** retStr, size_t * retStrSize); /*! * int FileUtills_GetExecDirectory(char ** path, size_t * pathSize) @@ -127,7 +126,7 @@ int GetCurrentWorkingDirectoryPath(char ** retStr, size_t * retStrSize); * If the function fails for any reason, the arguments will NOT be altered, * and the appropriate error will be returned to the caller. */ -int GetExecDirectory(char ** retStr, size_t * retStrSize); +int FileUtills_GetExecDirectory(char ** retStr, size_t * retStrSize); /*! int getDirectory(const char * path, const size_t pathSize, FileUtills_dirlist ** dirTree, const bool & cleanList) @@ -161,7 +160,7 @@ int GetExecDirectory(char ** retStr, size_t * retStrSize); Otherwise this function will return the appropriate error, and dirTree's pointer will not be modified. */ -int getDirectory(const char * path, const size_t pathSize, FileUtills_dirlist ** dirTree, const bool cleanList); +int FileUtills_getDirectory(const char * path, const size_t pathSize, FileUtills_dirlist ** dirTree, const bool cleanList); /*! int FileUtills_DoesExist(const char * path, const size_t pathSize) @@ -178,7 +177,7 @@ int getDirectory(const char * path, const size_t pathSize, FileUtills_dirlist ** Returns COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED if the given system is unsupported. Returns the appropriate error in all other instances. */ -int DoesExist(const char * path, const size_t pathSize); +int FileUtills_DoesExist(const char * path, const size_t pathSize); /*! FileUtills_IsFileOrDirectory(const char * path, const size_t pathSize) @@ -195,7 +194,7 @@ int DoesExist(const char * path, const size_t pathSize); Returns FILEUTILLS_ERROR_ if the path has a file in it and is not at the end. (I.e you are treating a file as a directory.) Returns the appropriate error in all other instances. */ -int IsFileOrDirectory(const char * path, const size_t pathSize); +int FileUtills_IsFileOrDirectory(const char * path, const size_t pathSize); /*! int FileUtills_CheckParent(const char * path, const size_t pathSize, const bool read, const bool write, const bool exec) @@ -222,7 +221,7 @@ int IsFileOrDirectory(const char * path, const size_t pathSize); Returns COMMON_ERROR_EXCEPTION_THROWN if an exception is thrown. Returns the appropriate error in all other cases. */ -int CheckParent(const char * path, const size_t pathSize, const bool read, const bool write, const bool exec); +int FileUtills_CheckParent(const char * path, const size_t pathSize, const bool read, const bool write, const bool exec); /*! int FileUtills_GetParent(char ** retStr, size_t * retStrSize) @@ -237,7 +236,7 @@ int CheckParent(const char * path, const size_t pathSize, const bool read, const Returns the appropriate error code otherwise. (retStr and retStrSize will NOT be altered in this case.) */ -int GetParent(char ** retStr, size_t * retStrSize); +int FileUtills_GetParent(char ** retStr, size_t * retStrSize); /*! int FileUtills_ResolvePath(const char * path, const size_t pathSize, char ** retStr, size_t * retStrSize, const bool disableSymLinkResolution) @@ -255,7 +254,7 @@ int GetParent(char ** retStr, size_t * retStrSize); Otherwise the appropriate error code is returned. (retStr and retStrSize will be unaltered in this instance.) */ -int ResolvePath(const char * path, const size_t pathSize, char ** retStr, size_t * retStrSize, const bool disableSymLinkResolution); +int FileUtills_ResolvePath(const char * path, const size_t pathSize, char ** retStr, size_t * retStrSize, const bool disableSymLinkResolution); /*! int FileUtills_CreateDirectory(const char * directory, const size_t directorySize, const bool createRecursive) @@ -272,7 +271,7 @@ int ResolvePath(const char * path, const size_t pathSize, char ** retStr, size_t Returns FILEUTILLS_ERROR_EXISTANT if the directory already exists. Returns the appropriate error or COMMON_ERROR_UNKNOWN_ERROR if another error is encountered. */ -int CreateDirectory(const char * directory, const size_t directorySize, const bool createRecursive); +int FileUtills_CreateDirectory(const char * directory, const size_t directorySize, const bool createRecursive); /*! int FileUtills_CheckPermissions(const char * path, const size_t pathSize, const bool read, const bool write, const bool exec) @@ -298,7 +297,7 @@ int CreateDirectory(const char * directory, const size_t directorySize, const bo Returns COMMON_ERROR_EXCEPTION_THROWN if an exception is thrown. Returns the appropriate error in all other cases. */ -int CheckPermissions(const char * path, const size_t pathSize, const bool read, const bool write, const bool exec); +int FileUtills_CheckPermissions(const char * path, const size_t pathSize, const bool read, const bool write, const bool exec); /*! int FileUtills_GetGigaFreespace(const char * path, const size_t pathSize, size_t * result) @@ -316,7 +315,7 @@ int CheckPermissions(const char * path, const size_t pathSize, const bool read, Returns a Common name-space error if an error occurs. result will not be altered in this case. To obtain more detailed info register an error hander before calling this function. */ -int GetGigaFreespace(const char * path, const size_t pathSize, size_t * result); +int FileUtills_GetGigaFreespace(const char * path, const size_t pathSize, size_t * result); /*! int FileUtills_GetFreespace(const char * path, const size_t pathSize, size_t * result) @@ -334,7 +333,7 @@ int GetGigaFreespace(const char * path, const size_t pathSize, size_t * result); Returns a Common name-space error if an error occurs. Size will be equal to zero in this case. To obtain more detailed info register an error hander before calling this function. */ -int GetFreespace(const char * path, const size_t pathSize, size_t * result); +int FileUtills_GetFreespace(const char * path, const size_t pathSize, size_t * result); /*! int FileUtills_GetKiloFreespace(const char * path, const size_t pathSize, size_t * result) @@ -352,7 +351,7 @@ int GetFreespace(const char * path, const size_t pathSize, size_t * result); Returns a Common name-space error if an error occurs. Size will be equal to zero in this case. To obtain more detailed info register an error hander before calling this function. */ -int GetKiloFreespace(const char * path, const size_t pathSize, size_t * result); +int FileUtills_GetKiloFreespace(const char * path, const size_t pathSize, size_t * result); /*! int FileUtills_GetByteFreespace(const char * path, const size_t pathSize, size_t * result) @@ -370,7 +369,7 @@ int GetKiloFreespace(const char * path, const size_t pathSize, size_t * result); Returns a Common name-space error if an error occurs. Size will be equal to zero in this case. To obtain more detailed info register an error hander before calling this function. */ -int GetByteFreespace(const char * path, const size_t pathSize, size_t * result); +int FileUtills_GetByteFreespace(const char * path, const size_t pathSize, size_t * result); /*! int FileUtills_DeletePath(const char * path, const size_t pathSize, const bool recursive) @@ -394,7 +393,7 @@ int GetByteFreespace(const char * path, const size_t pathSize, size_t * result); COMMON_ERROR_IO_ERROR if while deleting recursively, the parent directory of a deleted directory could not be obtained. (I.e could not "go up a level in the directory tree.") COMMON_ERROR_IO_ERROR if while deleting recursively, there were files and or subdirectories that could not be deleted. (Some files may have been deleted however.) */ -int DeletePath(const char * path, const size_t pathSize, const bool recursive); +int FileUtills_DeletePath(const char * path, const size_t pathSize, const bool recursive); /*! int FileUtills_CopyFile(const char * srcPath, const size_t srcPathSize, const char * destPath, const size_t destPathSize, @@ -458,7 +457,7 @@ int DeletePath(const char * path, const size_t pathSize, const bool recursive); Returns FILEUTILLS_ERROR_PATH_IS_A_DIRECTORY if the given dest file was a directory. Returns COMMON_ERROR_EXCEPTION_THROWN if an exception is thrown while copying data. */ -int CopyFile(const char * srcPath, const size_t srcPathSize, const char * destPath, const size_t destPathSize, const bool append, +int FileUtills_CopyFile(const char * srcPath, const size_t srcPathSize, const char * destPath, const size_t destPathSize, const bool append, const size_t begOffset, const size_t endOffset); /*! @@ -522,7 +521,7 @@ int CopyFile(const char * srcPath, const size_t srcPathSize, const char * destPa Returns -17 if FileUtills_IsFileOrDirectory() returns -7. (The path has a file in it and is not at the end. (I.e you are treating a file as a directory.)) Returns COMMON_ERROR_UNKNOWN_ERROR if FileUtills_IsFileOrDirectory() returns -9. (All other errors.) */ -int CopyPath(const char * srcPath, const size_t srcPathSize, const char * destPath, const size_t destPathSize, const bool recursive, +int FileUtills_CopyPath(const char * srcPath, const size_t srcPathSize, const char * destPath, const size_t destPathSize, const bool recursive, const bool rename, const bool abort_on_failure, const bool append, const size_t begOffset, const size_t endOffset); /*! @@ -540,10 +539,7 @@ int CopyPath(const char * srcPath, const size_t srcPathSize, const char * destPa Returns COMMON_ERROR_IO_ERROR If an error occurs while moving data. Returns COMMON_ERROR_INVALID_ARGUMENT If an argument to the function is bad. */ -int MovePath(const char * srcPath, const size_t srcPathSize, const char * destPath, const size_t destPathSize, const bool overwrite); - -} - +int FileUtills_MovePath(const char * srcPath, const size_t srcPathSize, const char * destPath, const size_t destPathSize, const bool overwrite); #endif From 65f707f1a980d1e3c3c5110f14da52c8d7bb014f Mon Sep 17 00:00:00 2001 From: codebase7 Date: Sun, 5 Jul 2015 00:20:33 -0400 Subject: [PATCH 035/325] Fix EOF in FileUtills.h Make the FileUtills.h header have UNIX line endings instead of Windows line endings. (UNIX style line endings are the default for this project, I don't know why or when FileUtills.h was converted to Windows style line endings, but that is not correct for this project.) --- .../File_Management_Subsystem/FileUtills.h | 1092 ++++++++--------- 1 file changed, 546 insertions(+), 546 deletions(-) diff --git a/src/Common/Src/File_Management_Subsystem/FileUtills.h b/src/Common/Src/File_Management_Subsystem/FileUtills.h index fc8fee6..c3bc269 100644 --- a/src/Common/Src/File_Management_Subsystem/FileUtills.h +++ b/src/Common/Src/File_Management_Subsystem/FileUtills.h @@ -1,546 +1,546 @@ -/*! - Multiverse Engine Project 04/12/2011 FileUtills FileUtills.h - Yes we are reinventing the wheel here, go with it. - - Copyright (C) 2014 Multiverse Engine Project - - This program is free software; - you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; - either version 2 of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with this program; - if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - Official source repository and project information can be found at - https://github.com/codebase7/mengine -*/ - -#ifndef FILEUTILLS -#define FILEUTILLS - -// Engine Includes -#ifdef __win32 -#include "..\BaseHeader.h" -#include "..\Error_Handler\Common_Error_Handler.h" -#include "..\Error_Handler\Common_Error_Handler_Internal.h" -#else -#include "../BaseHeader.h" -#include "../Error_Handler/Common_Error_Handler.h" -#include "../Error_Handler/Common_Error_Handler_Internal.h" -#endif - -#ifdef _WIN32 -// Define the Windows Directory seperator -#define DIR_SEP '\\' -#define HOME_DIR_SYMBOL '~' -// Define the minimal valid absolute directory path length. -/* - * MINIMAL_VALID_ABSOLUTE_PATH_LENGTH is supposed to include the needed DIR_SEP for the root directory. - * In addition it is supposed to be the minimal number of char(s) needed to represent a valid absolute path - * to a root directory. - * - * In windows ":" is minimal for an absolute path. (Root of given drive.) - */ -#define MINIMAL_VALID_ABSOLUTE_PATH_LENGTH 3 -#else -// Define the Posix Directory Seperator. -#ifndef DIR_SEP -#define DIR_SEP '/' -#define HOME_DIR_SYMBOL '~' -#define Relative_Symbol "./" -/* - * MINIMAL_VALID_ABSOLUTE_PATH_LENGTH is supposed to include the needed DIR_SEP for the root directory. - * In addition it is supposed to be the minimal number of char(s) needed to represent a valid absolute path - * to a root directory. - * - * In linux "" is minimal for an absolute path. (Root of the entire filesystem / chroot.) - */ -#define MINIMAL_VALID_ABSOLUTE_PATH_LENGTH 1 -#endif -#endif - -/* Define the directory list structure. */ -typedef struct FileUtills_dirlist { - size_t numOfEntries; /* Used to store the number of entries in the list array. */ - std::vector list; /* Used to store the directory's entry data. */ - char * path; /* Used to store the path of the directory that the entry list is about. */ - size_t pathSize; /* Length of the path string. */ -} FileUtills_dirlist_T; - -/*! - * int FileUtills_Write_Data_To_File_From_Memory(FILE * OUT, const char * data, const size_t dataLength) - * - * Writes out the given data in memory to the given output file. - * - * NOTE: This function expects that the given output file is already open and not errored out when called. - * The output file will remain open after the function returns. (It will still be usable if the returned error code is SUCCESS.) - * - * The output position of the file will NOT be restored in ANY instance after this function returns. - * If you need the current position for something, copy it elsewhere before calling this function. - * - * Returns COMMON_ERROR_SUCCESS if the data is written to the output file successfully. - * - * Returns COMMON_ERROR_INVALID_ARGUMENT if the given output file pointer is NULL, - * the given output file has errored out prior to the function call, - * data is NULL, or dataLength is less than 1. - * - * Returns COMMON_ERROR_IO_ERROR on all f*() errors. - * - * Otherwise returns the appropriate error code. - */ -int FileUtills_Write_Data_To_File_From_Memory(FILE * OUT, const char * data, const size_t dataLength); - -/*! - * int FileUtills_GetUserProfileDirectoryPath(char ** retStr, size_t * retStrSize) - * - * Fetches the user's profile directory from the environment, and stores - * it in the given path argument. - * - * If the function fails for any reason, the arguments will NOT be altered, - * and the appropriate error will be returned to the caller. - */ -int FileUtills_GetUserProfileDirectoryPath(char ** retStr, size_t * retStrSize); - -/*! - * int FileUtills_GetCurrentWorkingDirectoryPath(char ** path, size_t * pathSize) - * - * Fetches the current working directory from the environment, and stores - * it in the given retStr argument. - * - * If the function fails for any reason, the arguments will NOT be altered, - * and the appropriate error will be returned to the caller. - */ -int FileUtills_GetCurrentWorkingDirectoryPath(char ** retStr, size_t * retStrSize); - -/*! - * int FileUtills_GetExecDirectory(char ** path, size_t * pathSize) - * - * Replaces the contents of the given retStr argument with a NULL - * terminated C-String that contains the path to the directory where the - * executable is stored. - * - * If the function fails for any reason, the arguments will NOT be altered, - * and the appropriate error will be returned to the caller. - */ -int FileUtills_GetExecDirectory(char ** retStr, size_t * retStrSize); - -/*! - int getDirectory(const char * path, const size_t pathSize, FileUtills_dirlist ** dirTree, const bool & cleanList) - - Lists the given directory's contents. - - Pram: path, path of directory to check. - - Pram: FileUtills_dirlist ** dirTree, pointer to a pointer to a - FileUtills_dirlist structure that will contain the resulting - directory listing if successful. If the structure is already - allocated when passed to this function and this function succeeds, - the pre-existing structure will be deallocated. - - Pram: cleanList, If this is true then, the generated list will be sorted - (via decrementing sort), and the list will have the entries for the current - and parent directories removed. - Default is to do nothing, and return the list as the OS generated it. - - WARNING: The OS generated list has no guarantee that it will always show up - in the same order, as that depends on the underlying OS and filesystem. - - If you need a predictable list, (I.e. a list that always shows up in the same - order (excluding ANY modifications to the filesystem)) then you should always - set cleanList to true when calling this function. - - Returns COMMON_ERROR_SUCCESS if successfull, dirTree's pointer will point to a valid - FileUtills_dirlist structure with the given path's contents in this case. - (Any previous structure pointed to by the dirTree pointer will be deallocated.) - - Otherwise this function will return the appropriate error, and dirTree's pointer will - not be modified. -*/ -int FileUtills_getDirectory(const char * path, const size_t pathSize, FileUtills_dirlist ** dirTree, const bool cleanList); - -/*! - int FileUtills_DoesExist(const char * path, const size_t pathSize) - - Prams: @std::string path, path to check for existence on the filesystem. - - This function checks to see if given file or directory exists. - - This function is called by FileUtills_CheckPermissions() before running permission checks. - - Returns FILEUTILLS_ERROR_EXISTANT if file or directory exists on the system. - Returns FILEUTILLS_ERROR_NON_EXISTANT if file or directory does not exist on the system. - Returns COMMON_ERROR_INVALID_ARGUMENT if the given path is empty. - Returns COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED if the given system is unsupported. - Returns the appropriate error in all other instances. -*/ -int FileUtills_DoesExist(const char * path, const size_t pathSize); - -/*! - FileUtills_IsFileOrDirectory(const char * path, const size_t pathSize) - - Checks to see if a given path is a file or directory. - - Returns COMMON_ERROR_SUCCESS if the path exists but it is not a file or directory. - Returns FILEUTILLS_ERROR_PATH_IS_A_FILE if the path is a file. - Returns FILEUTILLS_ERROR_PATH_IS_A_DIRECTORY if the path is a directory. - Returns COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED if the given system is unsupported. - Returns COMMON_ERROR_ACCESS_DENIED if a permissions error occurs. - Returns COMMON_ERROR_INVALID_ARGUMENT if the given path is empty. - Returns FILEUTILLS_ERROR_NON_EXISTANT if a path component does not exist. - Returns FILEUTILLS_ERROR_ if the path has a file in it and is not at the end. (I.e you are treating a file as a directory.) - Returns the appropriate error in all other instances. -*/ -int FileUtills_IsFileOrDirectory(const char * path, const size_t pathSize); - -/*! - int FileUtills_CheckParent(const char * path, const size_t pathSize, const bool read, const bool write, const bool exec) - - Acts as a wrapper to DoesExist and CheckPermissions - Checks for the parent directory's existence in the path given. - Also Checks to see if it is accessible. By default it checks for Read and Write access. - (Optionally it can check for execute permissions, and any combination of the three. This - function will return a COMMON_ERROR_INVALID_ARGUMENT error however if all of the permissions to check - are false.) - - Ex. If this path is given: "/home/user/Homework.txt", this function will check and see if the "/home/user" parent - directory exists, and if it is accessible. - - The returned error code is always copied to Common::commonLastErrorCode. - - Returns COMMON_ERROR_SUCCESS if the directory exists and is accessible with the requested permissions. - Returns COMMON_ERROR_ACCESS_DENIED if A permission error occurs. - Returns FILEUTILLS_ERROR_NON_EXISTANT if the parent directory does not exist. - Returns COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED if the OS / Arch is not supported. - Returns COMMON_ERROR_SYSTEM_SPECIFIC if a system specific / untranslated error occurs. - Returns COMMON_ERROR_INTERNAL_ERROR if an engine error occurs. - Returns COMMON_ERROR_UNKNOWN_ERROR if an unknown error occurs. - Returns COMMON_ERROR_EXCEPTION_THROWN if an exception is thrown. - Returns the appropriate error in all other cases. -*/ -int FileUtills_CheckParent(const char * path, const size_t pathSize, const bool read, const bool write, const bool exec); - -/*! - int FileUtills_GetParent(char ** retStr, size_t * retStrSize) - - Returns the parent directory for the given file. - - Gets the path exactly like FileUtills_CheckParent(). - - Returns COMMON_ERROR_SUCCESS with parent directory path set in retStr if successful. - (retStr's size will be set in retStrSize.) - - Returns the appropriate error code otherwise. - (retStr and retStrSize will NOT be altered in this case.) -*/ -int FileUtills_GetParent(char ** retStr, size_t * retStrSize); - -/*! - int FileUtills_ResolvePath(const char * path, const size_t pathSize, char ** retStr, size_t * retStrSize, const bool disableSymLinkResolution) - - Checks the path given, and converts it to a absolute path. - - Setting disableSymLinkResolution to true will disable resolving any symbolic link(s) if a - symbolic link is encountered while resolving the given path(s). Setting - disableSymLinkResolution to false will make this function resolve any - symbolic link(s) that are encountered while resolving the given path(s). - - Returns COMMON_ERROR_SUCCESS if successful, retStr and retStrSize will be altered in this - case. (Any pre-existing c-string given to this function as retStr will be deallocated.) - - Otherwise the appropriate error code is returned. (retStr and retStrSize will be unaltered in - this instance.) -*/ -int FileUtills_ResolvePath(const char * path, const size_t pathSize, char ** retStr, size_t * retStrSize, const bool disableSymLinkResolution); - -/*! - int FileUtills_CreateDirectory(const char * directory, const size_t directorySize, const bool createRecursive) - @pram : directory, path to create. - @pram : createRecursive, if this is set to true, then this function will try to create the - parent directories of the given directory if they do not exist. - - This function attempts to create the given directory on the filesystem. - - Returns COMMON_ERROR_SUCCESS if directory creation was successful. - Returns COMMON_ERROR_ACCESS_DENIED if permission is denied. - Returns COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED if this function is unsupported. - Returns FILEUTILLS_ERROR_FILESYSTEM_FULL if the disk is full. - Returns FILEUTILLS_ERROR_EXISTANT if the directory already exists. - Returns the appropriate error or COMMON_ERROR_UNKNOWN_ERROR if another error is encountered. -*/ -int FileUtills_CreateDirectory(const char * directory, const size_t directorySize, const bool createRecursive); - -/*! - int FileUtills_CheckPermissions(const char * path, const size_t pathSize, const bool read, const bool write, const bool exec) - - Checks Permissions on the given file or directory. Also checks if the given file or directory - actually exists first before checking other permissions. By default it will check for both read and - write permissions. (Optionally it can check for execute permissions, and any combination of the three. This - function will return a COMMON_ERROR_INVALID_ARGUMENT error however if all of the permissions to check - are false.) - - Pram: path to directory or file to check. - Pram: check for read permission. default is true. - Pram: check for write permission. default is true. - Pram: check for execute permission. default is false. - - Returns COMMON_ERROR_SUCCESS if the directory exists and is accessible with the requested permissions. - Returns COMMON_ERROR_ACCESS_DENIED if A permission error occurs. - Returns FILEUTILLS_ERROR_NON_EXISTANT if the parent directory does not exist. - Returns COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED if the OS / Arch is not supported. - Returns COMMON_ERROR_SYSTEM_SPECIFIC if a system specific / untranslated error occurs. - Returns COMMON_ERROR_INTERNAL_ERROR if an engine error occurs. - Returns COMMON_ERROR_UNKNOWN_ERROR if an unknown error occurs. - Returns COMMON_ERROR_EXCEPTION_THROWN if an exception is thrown. - Returns the appropriate error in all other cases. -*/ -int FileUtills_CheckPermissions(const char * path, const size_t pathSize, const bool read, const bool write, const bool exec); - -/*! - int FileUtills_GetGigaFreespace(const char * path, const size_t pathSize, size_t * result) - - Returns the remaining disk space in Gigabytes (SI Unit) on the given disk. - - Note if an error occurs, result will be set to zero, and an error code will be returned. - (Although result can also be set to zero if there really is no remaining disk space.) - - @pram const char * path : string that contains the volume / path to check. - @pram const size_t pathSize: length of the path string. - @pram size_t & result : The remaining space on the filesystem. - - Returns COMMON_ERROR_SUCCESS if successful, result will contain the remaining space. - Returns a Common name-space error if an error occurs. result will not be altered in this - case. To obtain more detailed info register an error hander before calling this function. -*/ -int FileUtills_GetGigaFreespace(const char * path, const size_t pathSize, size_t * result); - -/*! - int FileUtills_GetFreespace(const char * path, const size_t pathSize, size_t * result) - - Returns the remaining disk space in Megabytes (SI Unit) on the given disk. - - Note if an error occurs, result will be set to zero, and an error code will be returned. - (Although result can also be set to zero if there really is no remaining disk space.) - - @pram const char * path : string that contains the volume / path to check. - @pram const size_t pathSize: length of the path string. - @pram size_t & result : The remaining space on the filesystem. - - Returns COMMON_ERROR_SUCCESS if successful, result will contain the remaining space. - Returns a Common name-space error if an error occurs. Size will be equal to zero in this - case. To obtain more detailed info register an error hander before calling this function. -*/ -int FileUtills_GetFreespace(const char * path, const size_t pathSize, size_t * result); - -/*! - int FileUtills_GetKiloFreespace(const char * path, const size_t pathSize, size_t * result) - - Returns the remaining disk space in Kilobytes (SI Unit) on the given disk. - - Note if an error occurs, result will be set to zero, and an error code will be returned. - (Although result can also be set to zero if there really is no remaining disk space.) - - @pram const char * path : string that contains the volume / path to check. - @pram const size_t pathSize: length of the path string. - @pram size_t & result : The remaining space on the filesystem. - - Returns COMMON_ERROR_SUCCESS if successful, result will contain the remaining space. - Returns a Common name-space error if an error occurs. Size will be equal to zero in this - case. To obtain more detailed info register an error hander before calling this function. -*/ -int FileUtills_GetKiloFreespace(const char * path, const size_t pathSize, size_t * result); - -/*! - int FileUtills_GetByteFreespace(const char * path, const size_t pathSize, size_t * result) - - Returns the remaining disk space in Bytes (SI Unit) on the given disk. - - Note if an error occurs, result will be set to zero, and an error code will be returned. - (Although result can also be set to zero if there really is no remaining disk space.) - - @pram const char * path : string that contains the volume / path to check. - @pram const size_t pathSize: length of the path string. - @pram size_t & result : The remaining space on the filesystem. - - Returns COMMON_ERROR_SUCCESS if successful, result will contain the remaining space. - Returns a Common name-space error if an error occurs. Size will be equal to zero in this - case. To obtain more detailed info register an error hander before calling this function. -*/ -int FileUtills_GetByteFreespace(const char * path, const size_t pathSize, size_t * result); - -/*! - int FileUtills_DeletePath(const char * path, const size_t pathSize, const bool recursive) - - This function attempts to delete the given file or directory from the filesystem. - - By default this function will NOT delete recursively. - If the given path is a non-empty directory, by default this function will throw an error. - If the given path is an empty directory, however by default this function WILL delete it. - - Note: If while deleting recursively, a file or subdirectory can't be deleted, this function will try to continue - deleting any other files and subdirectories that can be deleted, but it will throw an error upon exit. - - Returns COMMON_ERROR_SUCCESS if successful. - COMMON_ERROR_ACCESS_DENIED if the user lacks permission to delete the path. (Or if recursively deleting a directory, a file or subdirectory could not be deleted.) - FILEUTILLS_ERROR_NON_EXISTANT if the path does not exist. (Or if recursively deleting a directory, a file or subdirectory does not exist.) - COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED if the function is not supported. - COMMON_ERROR_MEMORY_ERROR if a memory error occurs. - COMMON_ERROR_UNKNOWN_ERROR if an unknown error occurs. (An error other than a permissions error occured while deleting something.) - FILEUTILLS_ERROR_PATH_IS_A_DIRECTORY if the path is a non empty directory and recursive is set to false. - COMMON_ERROR_IO_ERROR if while deleting recursively, the parent directory of a deleted directory could not be obtained. (I.e could not "go up a level in the directory tree.") - COMMON_ERROR_IO_ERROR if while deleting recursively, there were files and or subdirectories that could not be deleted. (Some files may have been deleted however.) -*/ -int FileUtills_DeletePath(const char * path, const size_t pathSize, const bool recursive); - -/*! - int FileUtills_CopyFile(const char * srcPath, const size_t srcPathSize, const char * destPath, const size_t destPathSize, - const bool append, const size_t begOffset, const size_t endOffset) - - Copies endOffset bytes starting at begOffset, from source file to dest file. - - Offset rules: - - If offsets are used, they must be positive. (If one or both of the given offsets is negative, - then COMMON_ERROR_INVALID_ARGUMENT will be returned.) - - - If zeros are used for both offsets, then the entire file will be copied. - - - If endOffset is greater than begOffset then the given range of bytes - from the file will be copied. - - - If begOffset is equal to zero and endOffset is greater than zero, then - the file will be copied from the start of the file to endOffset. - - - If begOffset is greater than zero and endOffset is equal to zero, then - the file will be copied from begOffset to the end of the file. - - - If any offset is not zero, then ONLY IF the file has enough bytes in it - to copy the given range of bytes from the given beginning offset, will the - copy take place. - (This allows for some insurance if the source file's size is known before - calling this function.) - - This function only works on FILES. Not directories. To copy a directory, call FileUtills_CopyPath(). - - @pram src, path to the source file. - @pram dest, path to the dest file. - - @pram append, Whether or not to append data to the dest file. - (Note only applies if the dest file exists. If append is false, then the dest file will be overwritten.) - - @pram begOffset, Location in the source file to start copying data from. - @pram endOffset, Location in the source file to stop copying data when it is reached. - - By default the entire file is copied and the dest file is overwritten. - - Note: This function does NOT make any attempt to preserve the destination file if it already exists. - - Note: This function can return ANY error in the Common name-space error list, below is only an example - of what errors this function itself may generate. (I.e. This function calls other FileUtills functions - and as such can return the errors generated by them.) If you need a more detailed error message, you - should register a callback function for the Common error handler (via Common::Register_Error_Log_Callback()) - before calling this function. - - Returns COMMON_ERROR_SUCCESS on success. - Returns COMMON_ERROR_INVALID_ARGUMENT if a given offset is negative. - Returns COMMON_ERROR_INVALID_ARGUMENT if the given begOffset is bigger than the given endOffset. (I.e you reversed the offsets.) - Returns COMMON_ERROR_MEMORY_ERROR if the memory buffer could not be allocated. - Returns COMMON_ERROR_INVALID_ARGUMENT if the source file was not given. - Returns COMMON_ERROR_IO_ERROR if the source file could not be opened. - Returns COMMON_ERROR_IO_ERROR if an I/O error occurred while reading the source file. - Returns COMMON::FILEUTILLS_PATH_IS_A_DIRECTORY if the given source file was a directory. - Returns COMMON_ERROR_INVALID_ARGUMENT if the dest file was not given. - Returns COMMON_ERROR_IO_ERROR if dest file could not be opened. - Returns COMMON_ERROR_IO_ERROR if an I/O error occurred while writing to the dest file. - Returns FILEUTILLS_ERROR_PATH_IS_A_DIRECTORY if the given dest file was a directory. - Returns COMMON_ERROR_EXCEPTION_THROWN if an exception is thrown while copying data. -*/ -int FileUtills_CopyFile(const char * srcPath, const size_t srcPathSize, const char * destPath, const size_t destPathSize, const bool append, - const size_t begOffset, const size_t endOffset); - -/*! - int FileUtills_CopyPath(const char * srcPath, const size_t srcPathSize, const char * destPath, const size_t destPathSize, const bool recursive, - const bool rename, const bool abort_on_failure, const bool append, const size_t begOffset, const size_t endOffset) - - This function takes a given source path and copies it to the given dest path. - - This function supports files and directories. - If you give a file as src and a directory as dest, the function WILL return an error. - - If the given src is a file, then this function acts as a wrapper to FileUtills_CopyFile(), and returns all of it's - error codes. - - If the given src is a directory, then this function will copy the entire directory to the given dest, creating dest if - necessary. If recursive is set to true, then the entire directory AND it's subdirectories will be copied. - (The subdirectories will be created as needed, if a subdirectory already exists, then the data from src will be merged.) - - @pram recursive, if this is true, then this function will recursively copy all subdirectories from src. Merging / creating - subdirectories as needed. Otherwise this function will only copy the top level directory. (Default) - If src is a file, then this pram has no effect. - - @pram rename, if this is set to true, then this function will try to rename the file rather than copy it. - otherwise a copy will be performed (Default). - It should be noted that a rename is equivalent to calling CopyFile(), and then DeletePath() on the same source. - (Minus the overhead and extra disk space use of actually copying the source first.) And that renaming a - src will only work if the dest is on the same filesystem. - In the event that rename fails, then a copy will be performed UNLESS abort_on_failure is set to true. In that case - the function will abort imeadently. - NOTE: Currently rename does nothing, as the RenamePath() function does not exist. - - @pram abort_on_failure, if this is set to true then this function will abort when the first failure is encountered. - otherwise this function will try to continue with the remaining list of files and subdirectories. (Default) - - @pram append, this is only used if src is a file. (As this function acts as a wrapper to CopyFile() in that case, - see FileUtills_CopyFile() for it's description. This function provides the same default value for this pram as CopyFile().) - If src is a directory, this pram has no effect. - - @pram begOffset, this is only used if src is a file. (As this function acts as a wrapper to CopyFile() in that case, - see FileUtills_CopyFile() for it's description. This function provides the same default value for this pram as CopyFile().) - If src is a directory, this pram has no effect. - - @pram endOffset, this is only used if src is a file. (As this function acts as a wrapper to CopyFile() in that case, - see FileUtills_CopyFile() for it's description. This function provides the same default value for this pram as CopyFile().) - If src is a directory, this pram has no effect. - - Below are return codes for when src is a directory, if src is a file, then the return codes for this function are identical to - FileUtills_CopyFile(). Please see FileUtills_CopyFile() for it's return codes. - - Returns COMMON_ERROR_SUCCESS on success. - Returns -1 if the function was unable to create top level dest path and top level dest path does not exist. - Returns -2 if the top level dest path exists and is a file or some other filesystem entry. - Returns COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED if the host OS / Arch is unsupported. - Returns -4 if the function could not get a directory listing. - Returns -5 if the function could not get parent directory string. - Returns -6 if the function was unable to copy all files. (Some files may have been copied however.) - Returns -13 if FileUtills_IsFileOrDirectory() returns -3. (OS / Arch not supported.) - Returns -14 if FileUtills_IsFileOrDirectory() returns -4. (A permissions error occurred.) - Returns -15 if FileUtills_IsFileOrDirectory() returns -5. (The given path is empty.) - Returns -16 if FileUtills_IsFileOrDirectory() returns -6. (A path component does not exist.) - Returns -17 if FileUtills_IsFileOrDirectory() returns -7. (The path has a file in it and is not at the end. (I.e you are treating a file as a directory.)) - Returns COMMON_ERROR_UNKNOWN_ERROR if FileUtills_IsFileOrDirectory() returns -9. (All other errors.) -*/ -int FileUtills_CopyPath(const char * srcPath, const size_t srcPathSize, const char * destPath, const size_t destPathSize, const bool recursive, - const bool rename, const bool abort_on_failure, const bool append, const size_t begOffset, const size_t endOffset); - -/*! - int FileUtills_MovePath(const char * srcPath, const size_t srcPathSize, const char * destPath, const size_t destPathSize, const bool overwrite) - - Acts as a wrapper for a call to CopyPath and DeletePath. - The srcPath is copied to the destPath and then the srcPath is deleted. - - Returns COMMON_ERROR_SUCCESS on success. - Returns -10 If an error occurs while accessing the src file. - Returns -20 If dest already exists and overwriting is disabled. - Returns -21 If dest already exists and can't be deleted. (overwrite = true) - Returns -22 If an error occurs while accessing the dest file. - Returns COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED If an Implementation does not exist for your system. - Returns COMMON_ERROR_IO_ERROR If an error occurs while moving data. - Returns COMMON_ERROR_INVALID_ARGUMENT If an argument to the function is bad. -*/ -int FileUtills_MovePath(const char * srcPath, const size_t srcPathSize, const char * destPath, const size_t destPathSize, const bool overwrite); - -#endif - -// End of FileUtills.h +/*! + Multiverse Engine Project 04/12/2011 FileUtills FileUtills.h + Yes we are reinventing the wheel here, go with it. + + Copyright (C) 2014 Multiverse Engine Project + + This program is free software; + you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this program; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Official source repository and project information can be found at + https://github.com/codebase7/mengine +*/ + +#ifndef FILEUTILLS +#define FILEUTILLS + +// Engine Includes +#ifdef __win32 +#include "..\BaseHeader.h" +#include "..\Error_Handler\Common_Error_Handler.h" +#include "..\Error_Handler\Common_Error_Handler_Internal.h" +#else +#include "../BaseHeader.h" +#include "../Error_Handler/Common_Error_Handler.h" +#include "../Error_Handler/Common_Error_Handler_Internal.h" +#endif + +#ifdef _WIN32 +// Define the Windows Directory seperator +#define DIR_SEP '\\' +#define HOME_DIR_SYMBOL '~' +// Define the minimal valid absolute directory path length. +/* + * MINIMAL_VALID_ABSOLUTE_PATH_LENGTH is supposed to include the needed DIR_SEP for the root directory. + * In addition it is supposed to be the minimal number of char(s) needed to represent a valid absolute path + * to a root directory. + * + * In windows ":" is minimal for an absolute path. (Root of given drive.) + */ +#define MINIMAL_VALID_ABSOLUTE_PATH_LENGTH 3 +#else +// Define the Posix Directory Seperator. +#ifndef DIR_SEP +#define DIR_SEP '/' +#define HOME_DIR_SYMBOL '~' +#define Relative_Symbol "./" +/* + * MINIMAL_VALID_ABSOLUTE_PATH_LENGTH is supposed to include the needed DIR_SEP for the root directory. + * In addition it is supposed to be the minimal number of char(s) needed to represent a valid absolute path + * to a root directory. + * + * In linux "" is minimal for an absolute path. (Root of the entire filesystem / chroot.) + */ +#define MINIMAL_VALID_ABSOLUTE_PATH_LENGTH 1 +#endif +#endif + +/* Define the directory list structure. */ +typedef struct FileUtills_dirlist { + size_t numOfEntries; /* Used to store the number of entries in the list array. */ + std::vector list; /* Used to store the directory's entry data. */ + char * path; /* Used to store the path of the directory that the entry list is about. */ + size_t pathSize; /* Length of the path string. */ +} FileUtills_dirlist_T; + +/*! + * int FileUtills_Write_Data_To_File_From_Memory(FILE * OUT, const char * data, const size_t dataLength) + * + * Writes out the given data in memory to the given output file. + * + * NOTE: This function expects that the given output file is already open and not errored out when called. + * The output file will remain open after the function returns. (It will still be usable if the returned error code is SUCCESS.) + * + * The output position of the file will NOT be restored in ANY instance after this function returns. + * If you need the current position for something, copy it elsewhere before calling this function. + * + * Returns COMMON_ERROR_SUCCESS if the data is written to the output file successfully. + * + * Returns COMMON_ERROR_INVALID_ARGUMENT if the given output file pointer is NULL, + * the given output file has errored out prior to the function call, + * data is NULL, or dataLength is less than 1. + * + * Returns COMMON_ERROR_IO_ERROR on all f*() errors. + * + * Otherwise returns the appropriate error code. + */ +int FileUtills_Write_Data_To_File_From_Memory(FILE * OUT, const char * data, const size_t dataLength); + +/*! + * int FileUtills_GetUserProfileDirectoryPath(char ** retStr, size_t * retStrSize) + * + * Fetches the user's profile directory from the environment, and stores + * it in the given path argument. + * + * If the function fails for any reason, the arguments will NOT be altered, + * and the appropriate error will be returned to the caller. + */ +int FileUtills_GetUserProfileDirectoryPath(char ** retStr, size_t * retStrSize); + +/*! + * int FileUtills_GetCurrentWorkingDirectoryPath(char ** path, size_t * pathSize) + * + * Fetches the current working directory from the environment, and stores + * it in the given retStr argument. + * + * If the function fails for any reason, the arguments will NOT be altered, + * and the appropriate error will be returned to the caller. + */ +int FileUtills_GetCurrentWorkingDirectoryPath(char ** retStr, size_t * retStrSize); + +/*! + * int FileUtills_GetExecDirectory(char ** path, size_t * pathSize) + * + * Replaces the contents of the given retStr argument with a NULL + * terminated C-String that contains the path to the directory where the + * executable is stored. + * + * If the function fails for any reason, the arguments will NOT be altered, + * and the appropriate error will be returned to the caller. + */ +int FileUtills_GetExecDirectory(char ** retStr, size_t * retStrSize); + +/*! + int getDirectory(const char * path, const size_t pathSize, FileUtills_dirlist ** dirTree, const bool & cleanList) + + Lists the given directory's contents. + + Pram: path, path of directory to check. + + Pram: FileUtills_dirlist ** dirTree, pointer to a pointer to a + FileUtills_dirlist structure that will contain the resulting + directory listing if successful. If the structure is already + allocated when passed to this function and this function succeeds, + the pre-existing structure will be deallocated. + + Pram: cleanList, If this is true then, the generated list will be sorted + (via decrementing sort), and the list will have the entries for the current + and parent directories removed. + Default is to do nothing, and return the list as the OS generated it. + + WARNING: The OS generated list has no guarantee that it will always show up + in the same order, as that depends on the underlying OS and filesystem. + + If you need a predictable list, (I.e. a list that always shows up in the same + order (excluding ANY modifications to the filesystem)) then you should always + set cleanList to true when calling this function. + + Returns COMMON_ERROR_SUCCESS if successfull, dirTree's pointer will point to a valid + FileUtills_dirlist structure with the given path's contents in this case. + (Any previous structure pointed to by the dirTree pointer will be deallocated.) + + Otherwise this function will return the appropriate error, and dirTree's pointer will + not be modified. +*/ +int FileUtills_getDirectory(const char * path, const size_t pathSize, FileUtills_dirlist ** dirTree, const bool cleanList); + +/*! + int FileUtills_DoesExist(const char * path, const size_t pathSize) + + Prams: @std::string path, path to check for existence on the filesystem. + + This function checks to see if given file or directory exists. + + This function is called by FileUtills_CheckPermissions() before running permission checks. + + Returns FILEUTILLS_ERROR_EXISTANT if file or directory exists on the system. + Returns FILEUTILLS_ERROR_NON_EXISTANT if file or directory does not exist on the system. + Returns COMMON_ERROR_INVALID_ARGUMENT if the given path is empty. + Returns COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED if the given system is unsupported. + Returns the appropriate error in all other instances. +*/ +int FileUtills_DoesExist(const char * path, const size_t pathSize); + +/*! + FileUtills_IsFileOrDirectory(const char * path, const size_t pathSize) + + Checks to see if a given path is a file or directory. + + Returns COMMON_ERROR_SUCCESS if the path exists but it is not a file or directory. + Returns FILEUTILLS_ERROR_PATH_IS_A_FILE if the path is a file. + Returns FILEUTILLS_ERROR_PATH_IS_A_DIRECTORY if the path is a directory. + Returns COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED if the given system is unsupported. + Returns COMMON_ERROR_ACCESS_DENIED if a permissions error occurs. + Returns COMMON_ERROR_INVALID_ARGUMENT if the given path is empty. + Returns FILEUTILLS_ERROR_NON_EXISTANT if a path component does not exist. + Returns FILEUTILLS_ERROR_ if the path has a file in it and is not at the end. (I.e you are treating a file as a directory.) + Returns the appropriate error in all other instances. +*/ +int FileUtills_IsFileOrDirectory(const char * path, const size_t pathSize); + +/*! + int FileUtills_CheckParent(const char * path, const size_t pathSize, const bool read, const bool write, const bool exec) + + Acts as a wrapper to DoesExist and CheckPermissions + Checks for the parent directory's existence in the path given. + Also Checks to see if it is accessible. By default it checks for Read and Write access. + (Optionally it can check for execute permissions, and any combination of the three. This + function will return a COMMON_ERROR_INVALID_ARGUMENT error however if all of the permissions to check + are false.) + + Ex. If this path is given: "/home/user/Homework.txt", this function will check and see if the "/home/user" parent + directory exists, and if it is accessible. + + The returned error code is always copied to Common::commonLastErrorCode. + + Returns COMMON_ERROR_SUCCESS if the directory exists and is accessible with the requested permissions. + Returns COMMON_ERROR_ACCESS_DENIED if A permission error occurs. + Returns FILEUTILLS_ERROR_NON_EXISTANT if the parent directory does not exist. + Returns COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED if the OS / Arch is not supported. + Returns COMMON_ERROR_SYSTEM_SPECIFIC if a system specific / untranslated error occurs. + Returns COMMON_ERROR_INTERNAL_ERROR if an engine error occurs. + Returns COMMON_ERROR_UNKNOWN_ERROR if an unknown error occurs. + Returns COMMON_ERROR_EXCEPTION_THROWN if an exception is thrown. + Returns the appropriate error in all other cases. +*/ +int FileUtills_CheckParent(const char * path, const size_t pathSize, const bool read, const bool write, const bool exec); + +/*! + int FileUtills_GetParent(char ** retStr, size_t * retStrSize) + + Returns the parent directory for the given file. + + Gets the path exactly like FileUtills_CheckParent(). + + Returns COMMON_ERROR_SUCCESS with parent directory path set in retStr if successful. + (retStr's size will be set in retStrSize.) + + Returns the appropriate error code otherwise. + (retStr and retStrSize will NOT be altered in this case.) +*/ +int FileUtills_GetParent(char ** retStr, size_t * retStrSize); + +/*! + int FileUtills_ResolvePath(const char * path, const size_t pathSize, char ** retStr, size_t * retStrSize, const bool disableSymLinkResolution) + + Checks the path given, and converts it to a absolute path. + + Setting disableSymLinkResolution to true will disable resolving any symbolic link(s) if a + symbolic link is encountered while resolving the given path(s). Setting + disableSymLinkResolution to false will make this function resolve any + symbolic link(s) that are encountered while resolving the given path(s). + + Returns COMMON_ERROR_SUCCESS if successful, retStr and retStrSize will be altered in this + case. (Any pre-existing c-string given to this function as retStr will be deallocated.) + + Otherwise the appropriate error code is returned. (retStr and retStrSize will be unaltered in + this instance.) +*/ +int FileUtills_ResolvePath(const char * path, const size_t pathSize, char ** retStr, size_t * retStrSize, const bool disableSymLinkResolution); + +/*! + int FileUtills_CreateDirectory(const char * directory, const size_t directorySize, const bool createRecursive) + @pram : directory, path to create. + @pram : createRecursive, if this is set to true, then this function will try to create the + parent directories of the given directory if they do not exist. + + This function attempts to create the given directory on the filesystem. + + Returns COMMON_ERROR_SUCCESS if directory creation was successful. + Returns COMMON_ERROR_ACCESS_DENIED if permission is denied. + Returns COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED if this function is unsupported. + Returns FILEUTILLS_ERROR_FILESYSTEM_FULL if the disk is full. + Returns FILEUTILLS_ERROR_EXISTANT if the directory already exists. + Returns the appropriate error or COMMON_ERROR_UNKNOWN_ERROR if another error is encountered. +*/ +int FileUtills_CreateDirectory(const char * directory, const size_t directorySize, const bool createRecursive); + +/*! + int FileUtills_CheckPermissions(const char * path, const size_t pathSize, const bool read, const bool write, const bool exec) + + Checks Permissions on the given file or directory. Also checks if the given file or directory + actually exists first before checking other permissions. By default it will check for both read and + write permissions. (Optionally it can check for execute permissions, and any combination of the three. This + function will return a COMMON_ERROR_INVALID_ARGUMENT error however if all of the permissions to check + are false.) + + Pram: path to directory or file to check. + Pram: check for read permission. default is true. + Pram: check for write permission. default is true. + Pram: check for execute permission. default is false. + + Returns COMMON_ERROR_SUCCESS if the directory exists and is accessible with the requested permissions. + Returns COMMON_ERROR_ACCESS_DENIED if A permission error occurs. + Returns FILEUTILLS_ERROR_NON_EXISTANT if the parent directory does not exist. + Returns COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED if the OS / Arch is not supported. + Returns COMMON_ERROR_SYSTEM_SPECIFIC if a system specific / untranslated error occurs. + Returns COMMON_ERROR_INTERNAL_ERROR if an engine error occurs. + Returns COMMON_ERROR_UNKNOWN_ERROR if an unknown error occurs. + Returns COMMON_ERROR_EXCEPTION_THROWN if an exception is thrown. + Returns the appropriate error in all other cases. +*/ +int FileUtills_CheckPermissions(const char * path, const size_t pathSize, const bool read, const bool write, const bool exec); + +/*! + int FileUtills_GetGigaFreespace(const char * path, const size_t pathSize, size_t * result) + + Returns the remaining disk space in Gigabytes (SI Unit) on the given disk. + + Note if an error occurs, result will be set to zero, and an error code will be returned. + (Although result can also be set to zero if there really is no remaining disk space.) + + @pram const char * path : string that contains the volume / path to check. + @pram const size_t pathSize: length of the path string. + @pram size_t & result : The remaining space on the filesystem. + + Returns COMMON_ERROR_SUCCESS if successful, result will contain the remaining space. + Returns a Common name-space error if an error occurs. result will not be altered in this + case. To obtain more detailed info register an error hander before calling this function. +*/ +int FileUtills_GetGigaFreespace(const char * path, const size_t pathSize, size_t * result); + +/*! + int FileUtills_GetFreespace(const char * path, const size_t pathSize, size_t * result) + + Returns the remaining disk space in Megabytes (SI Unit) on the given disk. + + Note if an error occurs, result will be set to zero, and an error code will be returned. + (Although result can also be set to zero if there really is no remaining disk space.) + + @pram const char * path : string that contains the volume / path to check. + @pram const size_t pathSize: length of the path string. + @pram size_t & result : The remaining space on the filesystem. + + Returns COMMON_ERROR_SUCCESS if successful, result will contain the remaining space. + Returns a Common name-space error if an error occurs. Size will be equal to zero in this + case. To obtain more detailed info register an error hander before calling this function. +*/ +int FileUtills_GetFreespace(const char * path, const size_t pathSize, size_t * result); + +/*! + int FileUtills_GetKiloFreespace(const char * path, const size_t pathSize, size_t * result) + + Returns the remaining disk space in Kilobytes (SI Unit) on the given disk. + + Note if an error occurs, result will be set to zero, and an error code will be returned. + (Although result can also be set to zero if there really is no remaining disk space.) + + @pram const char * path : string that contains the volume / path to check. + @pram const size_t pathSize: length of the path string. + @pram size_t & result : The remaining space on the filesystem. + + Returns COMMON_ERROR_SUCCESS if successful, result will contain the remaining space. + Returns a Common name-space error if an error occurs. Size will be equal to zero in this + case. To obtain more detailed info register an error hander before calling this function. +*/ +int FileUtills_GetKiloFreespace(const char * path, const size_t pathSize, size_t * result); + +/*! + int FileUtills_GetByteFreespace(const char * path, const size_t pathSize, size_t * result) + + Returns the remaining disk space in Bytes (SI Unit) on the given disk. + + Note if an error occurs, result will be set to zero, and an error code will be returned. + (Although result can also be set to zero if there really is no remaining disk space.) + + @pram const char * path : string that contains the volume / path to check. + @pram const size_t pathSize: length of the path string. + @pram size_t & result : The remaining space on the filesystem. + + Returns COMMON_ERROR_SUCCESS if successful, result will contain the remaining space. + Returns a Common name-space error if an error occurs. Size will be equal to zero in this + case. To obtain more detailed info register an error hander before calling this function. +*/ +int FileUtills_GetByteFreespace(const char * path, const size_t pathSize, size_t * result); + +/*! + int FileUtills_DeletePath(const char * path, const size_t pathSize, const bool recursive) + + This function attempts to delete the given file or directory from the filesystem. + + By default this function will NOT delete recursively. + If the given path is a non-empty directory, by default this function will throw an error. + If the given path is an empty directory, however by default this function WILL delete it. + + Note: If while deleting recursively, a file or subdirectory can't be deleted, this function will try to continue + deleting any other files and subdirectories that can be deleted, but it will throw an error upon exit. + + Returns COMMON_ERROR_SUCCESS if successful. + COMMON_ERROR_ACCESS_DENIED if the user lacks permission to delete the path. (Or if recursively deleting a directory, a file or subdirectory could not be deleted.) + FILEUTILLS_ERROR_NON_EXISTANT if the path does not exist. (Or if recursively deleting a directory, a file or subdirectory does not exist.) + COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED if the function is not supported. + COMMON_ERROR_MEMORY_ERROR if a memory error occurs. + COMMON_ERROR_UNKNOWN_ERROR if an unknown error occurs. (An error other than a permissions error occured while deleting something.) + FILEUTILLS_ERROR_PATH_IS_A_DIRECTORY if the path is a non empty directory and recursive is set to false. + COMMON_ERROR_IO_ERROR if while deleting recursively, the parent directory of a deleted directory could not be obtained. (I.e could not "go up a level in the directory tree.") + COMMON_ERROR_IO_ERROR if while deleting recursively, there were files and or subdirectories that could not be deleted. (Some files may have been deleted however.) +*/ +int FileUtills_DeletePath(const char * path, const size_t pathSize, const bool recursive); + +/*! + int FileUtills_CopyFile(const char * srcPath, const size_t srcPathSize, const char * destPath, const size_t destPathSize, + const bool append, const size_t begOffset, const size_t endOffset) + + Copies endOffset bytes starting at begOffset, from source file to dest file. + + Offset rules: + - If offsets are used, they must be positive. (If one or both of the given offsets is negative, + then COMMON_ERROR_INVALID_ARGUMENT will be returned.) + + - If zeros are used for both offsets, then the entire file will be copied. + + - If endOffset is greater than begOffset then the given range of bytes + from the file will be copied. + + - If begOffset is equal to zero and endOffset is greater than zero, then + the file will be copied from the start of the file to endOffset. + + - If begOffset is greater than zero and endOffset is equal to zero, then + the file will be copied from begOffset to the end of the file. + + - If any offset is not zero, then ONLY IF the file has enough bytes in it + to copy the given range of bytes from the given beginning offset, will the + copy take place. + (This allows for some insurance if the source file's size is known before + calling this function.) + + This function only works on FILES. Not directories. To copy a directory, call FileUtills_CopyPath(). + + @pram src, path to the source file. + @pram dest, path to the dest file. + + @pram append, Whether or not to append data to the dest file. + (Note only applies if the dest file exists. If append is false, then the dest file will be overwritten.) + + @pram begOffset, Location in the source file to start copying data from. + @pram endOffset, Location in the source file to stop copying data when it is reached. + + By default the entire file is copied and the dest file is overwritten. + + Note: This function does NOT make any attempt to preserve the destination file if it already exists. + + Note: This function can return ANY error in the Common name-space error list, below is only an example + of what errors this function itself may generate. (I.e. This function calls other FileUtills functions + and as such can return the errors generated by them.) If you need a more detailed error message, you + should register a callback function for the Common error handler (via Common::Register_Error_Log_Callback()) + before calling this function. + + Returns COMMON_ERROR_SUCCESS on success. + Returns COMMON_ERROR_INVALID_ARGUMENT if a given offset is negative. + Returns COMMON_ERROR_INVALID_ARGUMENT if the given begOffset is bigger than the given endOffset. (I.e you reversed the offsets.) + Returns COMMON_ERROR_MEMORY_ERROR if the memory buffer could not be allocated. + Returns COMMON_ERROR_INVALID_ARGUMENT if the source file was not given. + Returns COMMON_ERROR_IO_ERROR if the source file could not be opened. + Returns COMMON_ERROR_IO_ERROR if an I/O error occurred while reading the source file. + Returns COMMON::FILEUTILLS_PATH_IS_A_DIRECTORY if the given source file was a directory. + Returns COMMON_ERROR_INVALID_ARGUMENT if the dest file was not given. + Returns COMMON_ERROR_IO_ERROR if dest file could not be opened. + Returns COMMON_ERROR_IO_ERROR if an I/O error occurred while writing to the dest file. + Returns FILEUTILLS_ERROR_PATH_IS_A_DIRECTORY if the given dest file was a directory. + Returns COMMON_ERROR_EXCEPTION_THROWN if an exception is thrown while copying data. +*/ +int FileUtills_CopyFile(const char * srcPath, const size_t srcPathSize, const char * destPath, const size_t destPathSize, const bool append, + const size_t begOffset, const size_t endOffset); + +/*! + int FileUtills_CopyPath(const char * srcPath, const size_t srcPathSize, const char * destPath, const size_t destPathSize, const bool recursive, + const bool rename, const bool abort_on_failure, const bool append, const size_t begOffset, const size_t endOffset) + + This function takes a given source path and copies it to the given dest path. + + This function supports files and directories. + If you give a file as src and a directory as dest, the function WILL return an error. + + If the given src is a file, then this function acts as a wrapper to FileUtills_CopyFile(), and returns all of it's + error codes. + + If the given src is a directory, then this function will copy the entire directory to the given dest, creating dest if + necessary. If recursive is set to true, then the entire directory AND it's subdirectories will be copied. + (The subdirectories will be created as needed, if a subdirectory already exists, then the data from src will be merged.) + + @pram recursive, if this is true, then this function will recursively copy all subdirectories from src. Merging / creating + subdirectories as needed. Otherwise this function will only copy the top level directory. (Default) + If src is a file, then this pram has no effect. + + @pram rename, if this is set to true, then this function will try to rename the file rather than copy it. + otherwise a copy will be performed (Default). + It should be noted that a rename is equivalent to calling CopyFile(), and then DeletePath() on the same source. + (Minus the overhead and extra disk space use of actually copying the source first.) And that renaming a + src will only work if the dest is on the same filesystem. + In the event that rename fails, then a copy will be performed UNLESS abort_on_failure is set to true. In that case + the function will abort imeadently. + NOTE: Currently rename does nothing, as the RenamePath() function does not exist. + + @pram abort_on_failure, if this is set to true then this function will abort when the first failure is encountered. + otherwise this function will try to continue with the remaining list of files and subdirectories. (Default) + + @pram append, this is only used if src is a file. (As this function acts as a wrapper to CopyFile() in that case, + see FileUtills_CopyFile() for it's description. This function provides the same default value for this pram as CopyFile().) + If src is a directory, this pram has no effect. + + @pram begOffset, this is only used if src is a file. (As this function acts as a wrapper to CopyFile() in that case, + see FileUtills_CopyFile() for it's description. This function provides the same default value for this pram as CopyFile().) + If src is a directory, this pram has no effect. + + @pram endOffset, this is only used if src is a file. (As this function acts as a wrapper to CopyFile() in that case, + see FileUtills_CopyFile() for it's description. This function provides the same default value for this pram as CopyFile().) + If src is a directory, this pram has no effect. + + Below are return codes for when src is a directory, if src is a file, then the return codes for this function are identical to + FileUtills_CopyFile(). Please see FileUtills_CopyFile() for it's return codes. + + Returns COMMON_ERROR_SUCCESS on success. + Returns -1 if the function was unable to create top level dest path and top level dest path does not exist. + Returns -2 if the top level dest path exists and is a file or some other filesystem entry. + Returns COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED if the host OS / Arch is unsupported. + Returns -4 if the function could not get a directory listing. + Returns -5 if the function could not get parent directory string. + Returns -6 if the function was unable to copy all files. (Some files may have been copied however.) + Returns -13 if FileUtills_IsFileOrDirectory() returns -3. (OS / Arch not supported.) + Returns -14 if FileUtills_IsFileOrDirectory() returns -4. (A permissions error occurred.) + Returns -15 if FileUtills_IsFileOrDirectory() returns -5. (The given path is empty.) + Returns -16 if FileUtills_IsFileOrDirectory() returns -6. (A path component does not exist.) + Returns -17 if FileUtills_IsFileOrDirectory() returns -7. (The path has a file in it and is not at the end. (I.e you are treating a file as a directory.)) + Returns COMMON_ERROR_UNKNOWN_ERROR if FileUtills_IsFileOrDirectory() returns -9. (All other errors.) +*/ +int FileUtills_CopyPath(const char * srcPath, const size_t srcPathSize, const char * destPath, const size_t destPathSize, const bool recursive, + const bool rename, const bool abort_on_failure, const bool append, const size_t begOffset, const size_t endOffset); + +/*! + int FileUtills_MovePath(const char * srcPath, const size_t srcPathSize, const char * destPath, const size_t destPathSize, const bool overwrite) + + Acts as a wrapper for a call to CopyPath and DeletePath. + The srcPath is copied to the destPath and then the srcPath is deleted. + + Returns COMMON_ERROR_SUCCESS on success. + Returns -10 If an error occurs while accessing the src file. + Returns -20 If dest already exists and overwriting is disabled. + Returns -21 If dest already exists and can't be deleted. (overwrite = true) + Returns -22 If an error occurs while accessing the dest file. + Returns COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED If an Implementation does not exist for your system. + Returns COMMON_ERROR_IO_ERROR If an error occurs while moving data. + Returns COMMON_ERROR_INVALID_ARGUMENT If an argument to the function is bad. +*/ +int FileUtills_MovePath(const char * srcPath, const size_t srcPathSize, const char * destPath, const size_t destPathSize, const bool overwrite); + +#endif + +// End of FileUtills.h From 51fbb9a7b30e253283ca298e861e1915263b72df Mon Sep 17 00:00:00 2001 From: codebase7 Date: Sun, 5 Jul 2015 07:10:30 -0400 Subject: [PATCH 036/325] Move the error codes into their own header. This commit moves the Common namespace error codes to their own header file so that other sections that only need the error code definitions can use them without needing to link in Common_Error_Handler. (I should have done this a long time ago..... but I'm lazy.) --- .../Src/Error_Handler/Common_Error_Handler.h | 3 +- .../Common_Error_Handler_Error_Codes.h | 83 +++++++++++++++++++ .../Common_Error_Handler_Structures.h | 52 +----------- 3 files changed, 86 insertions(+), 52 deletions(-) create mode 100644 src/Common/Src/Error_Handler/Common_Error_Handler_Error_Codes.h diff --git a/src/Common/Src/Error_Handler/Common_Error_Handler.h b/src/Common/Src/Error_Handler/Common_Error_Handler.h index e28441e..bf7c7ac 100644 --- a/src/Common/Src/Error_Handler/Common_Error_Handler.h +++ b/src/Common/Src/Error_Handler/Common_Error_Handler.h @@ -40,9 +40,10 @@ #include "..\..\..\Core\Src\Panic_Error_Levels.h" // Defines the log levels. #else #include "../../../Core/Src/Panic_Error_Levels.h" // Defines the log levels. -#include "Posix_Error_Translation_Table.h" // Defines the POSIX errno to Common namespace error translation table and functions. +#include "Posix_Error_Translation_Table.h" // Defines the POSIX errno to Common namespace error translation table and functions. #endif // _WIN32 +#include "Common_Error_Handler_Error_Codes.h" /* Defines error codes. */ #include "Common_Error_Handler_Structures.h" // Defines the error codes, error lookup table error lookup table version number, and Common::commonLastErrorCode. // Enable C linkage if needed. diff --git a/src/Common/Src/Error_Handler/Common_Error_Handler_Error_Codes.h b/src/Common/Src/Error_Handler/Common_Error_Handler_Error_Codes.h new file mode 100644 index 0000000..f2baa3d --- /dev/null +++ b/src/Common/Src/Error_Handler/Common_Error_Handler_Error_Codes.h @@ -0,0 +1,83 @@ +/*! + Multiverse Engine Project 05/7/2015 Common Common_Error_Handler_Error_Codes.h + + Copyright (C) 2015 Multiverse Engine Project + + This program is free software; + you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this program; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Official source repository and project information can be found at + https://github.com/codebase7/mengine +*/ + +/* Include guard. */ +#ifndef COMMON_ERROR_HANDLER_ERROR_CODES_H +#define COMMON_ERROR_HANDLER_ERROR_CODES_H + +/* Common namespace error code definitions. (Human-readable error message translation table is located in Common_Error_Handler_Structures.c) */ + enum { + /* Generic error codes. */ + COMMON_ERROR_SYSTEM_SPECIFIC = 99, + COMMON_ERROR_SUCCESS = 0, + COMMON_ERROR_UNKNOWN_ERROR = -1, + COMMON_ERROR_INVALID_ARGUMENT = -2, + COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED = -3, + COMMON_ERROR_ACCESS_DENIED = -4, + COMMON_ERROR_EXCEPTION_THROWN = -5, + COMMON_ERROR_INTERNAL_ERROR = -6, + COMMON_ERROR_IO_ERROR = -7, + COMMON_ERROR_RANGE_ERROR = -8, + COMMON_ERROR_MEMORY_ERROR = -9, + COMMON_ERROR_INVALID_LIBRARY_ID = -10, /* Formerly THREAD_UTILS_INVALID_LIBRARY_ID. */ + COMMON_ERROR_PEBKAC_INVALID_OPERATION_ORDER = -11, + COMMON_ERROR_CANNOT_GET_SYSTEM_TIME = -12, + COMMON_ERROR_SUBSYSTEM_OBJECT_NOT_INITED = -13, + COMMON_ERROR_SUBSYSTEM_OBJECT_ALREADY_INITED = -14, + + /* Rendering Subsystem error codes. */ + RENDERER_ERROR_UNABLE_TO_ALLOC_OI_BUF = -21, /* Overlay image buffer. */ + RENDERER_ERROR_UNABLE_TO_ALLOC_TD_BUF = -22, /* Transparency data buffer. */ + RENDERER_ERROR_MEM_BUF_ALLOC_EXCEPTION = -23, + RENDERER_ERROR_DUPE_OVERLAY_EXCEPTION = -24, + RENDERER_ERROR_INVAL_OVERLAY_SELF_OVERWRITE = -25, + RENDERER_ERROR_TRANSPARENCY_DISABLED = -26, + /* Threading Subsystem error codes. */ + THREAD_UTILS_ERROR_EXCEPTION_THROWN = -31, + THREAD_UTILS_ERROR_PLUGIN_LOAD_FAILURE = -32, + THREAD_UTILS_ERROR_THREAD_COULD_NOT_START = -33, + THREAD_UTILS_ERROR_THREAD_COULD_NOT_DETACH = -34, + THREAD_UTILS_ERROR_THREAD_COULD_NOT_JOIN = -35, + THREAD_UTILS_ERROR_MUTEX_ALREADY_LOCKED = -36, + THREAD_UTILS_ERROR_CONDITION_CANNOT_LOCK_MUTEX = -37, + THREAD_UTILS_ERROR_CONDITION_WAIT_TIMEOUT_REACHED = -38, + /* FileUtills error codes. */ + FILEUTILLS_ERROR_EXISTANT = -60, + FILEUTILLS_ERROR_NON_EXISTANT = -61, + FILEUTILLS_ERROR_READ_ONLY = -62, + FILEUTILLS_ERROR_PATH_LENGTH_INVALID = -63, + FILEUTILLS_ERROR_PATH_FILE_AS_DIRECTORY = -64, + FILEUTILLS_ERROR_PATH_IS_A_FILE = -65, + FILEUTILLS_ERROR_PATH_IS_A_DIRECTORY = -66, + FILEUTILLS_ERROR_PATH_IS_A_SYMLINK = -67, + FILEUTILLS_ERROR_PATH_IS_ABSOLUTE = -68, + FILEUTILLS_ERROR_PATH_IS_RELATIVE = -69, + FILEUTILLS_ERROR_FILESYSTEM_FULL = -70, + FILEUTILLS_ERROR_FILESYSTEM_QUOTA_REACHED = -71, + FILEUTILLS_ERROR_EMPTY_DIRECTORY = -72, + FILEUTILLS_ERROR_NON_EMPTY_DIRECTORY = -73, + FILEUTILLS_ERROR_SYMLINK_CHAIN_TOO_DEEP = -74, + /* UI Subsystem. */ + UI_SUBSYSTEM_ERROR_EXCEPTION_THROWN = -90, + }; + +#endif /* COMMON_ERROR_HANDLER_ERROR_CODES_H */ + +/* End of Common_Error_Handler_Error_Codes.h. */ diff --git a/src/Common/Src/Error_Handler/Common_Error_Handler_Structures.h b/src/Common/Src/Error_Handler/Common_Error_Handler_Structures.h index e24c2cf..e178afc 100644 --- a/src/Common/Src/Error_Handler/Common_Error_Handler_Structures.h +++ b/src/Common/Src/Error_Handler/Common_Error_Handler_Structures.h @@ -36,57 +36,7 @@ extern "C" { #endif /* __cplusplus */ -/* Common namespace error code definitions. (Human-readable error message translation table is located in Common_Error_Handler_Structures.c) */ - enum { - /* Generic error codes. */ - COMMON_ERROR_SYSTEM_SPECIFIC = 99, - COMMON_ERROR_SUCCESS = 0, - COMMON_ERROR_UNKNOWN_ERROR = -1, - COMMON_ERROR_INVALID_ARGUMENT = -2, - COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED = -3, - COMMON_ERROR_ACCESS_DENIED = -4, - COMMON_ERROR_EXCEPTION_THROWN = -5, - COMMON_ERROR_INTERNAL_ERROR = -6, - COMMON_ERROR_IO_ERROR = -7, - COMMON_ERROR_RANGE_ERROR = -8, - COMMON_ERROR_MEMORY_ERROR = -9, - COMMON_ERROR_INVALID_LIBRARY_ID = -10, /* Formerly THREAD_UTILS_INVALID_LIBRARY_ID. */ - COMMON_ERROR_PEBKAC_INVALID_OPERATION_ORDER = -11, - COMMON_ERROR_CANNOT_GET_SYSTEM_TIME = -12, - COMMON_ERROR_SUBSYSTEM_OBJECT_NOT_INITED = -13, - COMMON_ERROR_SUBSYSTEM_OBJECT_ALREADY_INITED = -14, - - /* Rendering Subsystem error codes. */ - RENDERER_ERROR_UNABLE_TO_ALLOC_OI_BUF = -21, /* Overlay image buffer. */ - RENDERER_ERROR_UNABLE_TO_ALLOC_TD_BUF = -22, /* Transparency data buffer. */ - RENDERER_ERROR_MEM_BUF_ALLOC_EXCEPTION = -23, - RENDERER_ERROR_DUPE_OVERLAY_EXCEPTION = -24, - RENDERER_ERROR_INVAL_OVERLAY_SELF_OVERWRITE = -25, - RENDERER_ERROR_TRANSPARENCY_DISABLED = -26, - /* Threading Subsystem error codes. */ - THREAD_UTILS_ERROR_EXCEPTION_THROWN = -31, - THREAD_UTILS_ERROR_PLUGIN_LOAD_FAILURE = -32, - THREAD_UTILS_ERROR_THREAD_COULD_NOT_START = -33, - THREAD_UTILS_ERROR_THREAD_COULD_NOT_DETACH = -34, - THREAD_UTILS_ERROR_THREAD_COULD_NOT_JOIN = -35, - THREAD_UTILS_ERROR_MUTEX_ALREADY_LOCKED = -36, - THREAD_UTILS_ERROR_CONDITION_CANNOT_LOCK_MUTEX = -37, - THREAD_UTILS_ERROR_CONDITION_WAIT_TIMEOUT_REACHED = -38, - /* FileUtills error codes. */ - FILEUTILLS_ERROR_EXISTANT = -60, - FILEUTILLS_ERROR_NON_EXISTANT = -61, - FILEUTILLS_ERROR_READ_ONLY = -62, - FILEUTILLS_ERROR_PATH_LENGTH_INVALID = -63, - FILEUTILLS_ERROR_PATH_FILE_AS_DIRECTORY = -64, - FILEUTILLS_ERROR_PATH_IS_A_FILE = -65, - FILEUTILLS_ERROR_PATH_IS_A_DIRECTORY = -66, - FILEUTILLS_ERROR_FILESYSTEM_FULL = -67, - FILEUTILLS_ERROR_FILESYSTEM_QUOTA_REACHED = -68, - FILEUTILLS_ERROR_EMPTY_DIRECTORY = -69, - FILEUTILLS_ERROR_NON_EMPTY_DIRECTORY = -70, - /* UI Subsystem. */ - UI_SUBSYSTEM_ERROR_EXCEPTION_THROWN = -90, - }; +/* ERROR CODES MOVED TO Common_Error_Handler_Error_Codes.h */ /*! * const unsigned int Common_Get_Error_Table_API_Version() From 6fff570ff420ca30554cd74edccfd27ae0fda68a Mon Sep 17 00:00:00 2001 From: codebase7 Date: Sun, 5 Jul 2015 21:08:35 -0400 Subject: [PATCH 037/325] Add File_Length*() functions This commit adds the FileUtills_Get_File_Length_By_Filename() and FileUtills_Get_File_Length() functions to FileUtills. --- .../File_Management_Subsystem/FileUtills.cpp | 188 ++++++++++++++++++ .../File_Management_Subsystem/FileUtills.h | 43 ++++ 2 files changed, 231 insertions(+) diff --git a/src/Common/Src/File_Management_Subsystem/FileUtills.cpp b/src/Common/Src/File_Management_Subsystem/FileUtills.cpp index 27ccf76..118e066 100644 --- a/src/Common/Src/File_Management_Subsystem/FileUtills.cpp +++ b/src/Common/Src/File_Management_Subsystem/FileUtills.cpp @@ -177,6 +177,194 @@ int FileUtills_CheckPathType(const char * path, const size_t pathSize, bool * bI return ret; } +#ifdef _MSC_VER +int FileUtills_Get_File_Length_By_Filename(const char * filename, const size_t filenameSize, __int64 * fileLength) +#else +int FileUtills_Get_File_Length_By_Filename(const char * filename, const size_t filenameSize, off_t * fileLength) +#endif /* _MSC_VER */ +{ + /* Init vars. */ + int retFromC = 0; /* The result from C calls. */ + int ret = COMMON_ERROR_UNKNOWN_ERROR; /* The result of this function. */ + FILE * fp = NULL; /* Pointer to the file. */ +#ifdef _MSC_VER + __int64 fileSize = 0; /* Returned size from Get_File_Length(). (VC is special.) */ +#else + off_t fileSize = 0; /* Returned size from Get_File_Length(). */ +#endif /* _MSC_VER */ + + /* Check for invalid arguments. */ + if ((filename != NULL) && (filenameSize > 0) && (fileLength != NULL)) + { + /* Open the file. */ + fp = fopen(filename, "rb"); + if (fp != NULL) + { + /* Call correct function. */ + ret = FileUtills_Get_File_Length(fp, &fileSize); + if (ret == COMMON_ERROR_SUCCESS) + { + /* Close the file. */ + retFromC = fclose(fp); + if (retFromC == 0) + { + /* Copy the size. */ + (*fileLength) = fileSize; + + /* SUCCESS. */ + ret = COMMON_ERROR_SUCCESS; + } + else + { + /* Could not close the file. */ + ret = COMMON_ERROR_IO_ERROR; + } + } + else + { + /* Close the file. */ + retFromC = fclose(fp); + if (retFromC != 0) + { + /* Could not close the file. */ + ret = COMMON_ERROR_IO_ERROR; + } + } + } + else + { + /* Could not open file. */ + ret = COMMON_ERROR_IO_ERROR; + } + } + else + { + /* Invalid arguments. */ + ret = COMMON_ERROR_INVALID_ARGUMENT; + } + + /* Exit function. */ + return ret; +} + +#ifdef _MSC_VER +int FileUtills_Get_File_Length(FILE * fp, __int64 * fileLength) +#else +int FileUtills_Get_File_Length(FILE * fp, off_t * fileLength) +#endif /* _MSC_VER */ +{ + /* Init vars. */ + int ret = COMMON_ERROR_UNKNOWN_ERROR; /* The result of this function. */ + int retFromC = 0; /* The result of C calls. */ + fpos_t * previousLocation = NULL; /* The location to restore us to at the end of the function. */ +#ifdef _MSC_VER + long long length = 0; /* The size of the file. (Visual C is special.) */ +#else + off_t length = 0; /* The size of the file. */ +#endif /* _MSC_VER */ + + /* Check for invalid arguments. */ + if ((fp != NULL) && (fileLength != NULL)) + { + /* Check for errors. */ + if (ferror(fp) != 0) + { + /* Get the current position. */ + retFromC = fgetpos(fp, previousLocation); + if (retFromC == 0) + { + /* Go back to the beginining of the file. */ + rewind(fp); + + /* Begin loop to find the end of the file. */ + while ((ferror(fp) == 0) && (feof(fp) == 0)) + { + /* Get next char. */ + retFromC = fgetc(fp); + } + + /* OK, now figure out if we hit the end of the file or if we hit an error. */ + retFromC = ferror(fp); + if (retFromC == 0) /* No error. */ + { + /* Check for eof. */ + retFromC = feof(fp); + if (retFromC != 0) /* Hit EOF. */ + { + /* Get the end of file position. */ +#ifdef _MSC_VER + length = _ftelli64(fp); /* Visual C is special. */ +#else + length = ftello(fp); +#endif /* _MSC_VER */ + if ((length != -1) && (length >= 0)) + { + /* Set success. */ + ret = COMMON_ERROR_SUCCESS; + } + else + { + /* Check and see if the error is EOVERFLOW. */ + if ((ret == -1) && (errno == EOVERFLOW)) + { + /* This is a memory error, as we can't store the result. */ + ret = COMMON_ERROR_MEMORY_ERROR; + } + else + { + /* OK, yet another IO_ERROR. */ + ret = COMMON_ERROR_IO_ERROR; + } + } + } + else + { + /* We hit a file stream error. */ + ret = COMMON_ERROR_IO_ERROR; + } + } + else + { + /* We hit a file stream error. */ + ret = COMMON_ERROR_IO_ERROR; + } + + /* Clear the error status, and reset the file position. */ + clearerr(fp); + retFromC = fsetpos(fp, previousLocation); + if ((retFromC == 0) && (length >= 0) && (ret == COMMON_ERROR_SUCCESS)) + { + /* Copy the length to the size_t value. */ + (*fileLength) = length; + } + else + { + /* File stream error. */ + ret = COMMON_ERROR_IO_ERROR; + } + } + else + { + /* Could not get current file position. */ + ret = COMMON_ERROR_IO_ERROR; + } + } + else + { + /* File stream has errored out. */ + ret = COMMON_ERROR_IO_ERROR; + } + } + else + { + /* Invalid arguments. */ + ret = COMMON_ERROR_INVALID_ARGUMENT; + } + + /* Exit function. */ + return ret; +} + int FileUtills_Write_Data_To_File_From_Memory(FILE * OUT, const char * data, const size_t dataLength) { /* Init vars. */ diff --git a/src/Common/Src/File_Management_Subsystem/FileUtills.h b/src/Common/Src/File_Management_Subsystem/FileUtills.h index c3bc269..d6fa4f5 100644 --- a/src/Common/Src/File_Management_Subsystem/FileUtills.h +++ b/src/Common/Src/File_Management_Subsystem/FileUtills.h @@ -71,6 +71,49 @@ typedef struct FileUtills_dirlist { size_t pathSize; /* Length of the path string. */ } FileUtills_dirlist_T; +/*! + * int FileUtills_Get_File_Length_By_Filename(const char * filename, const size_t filenameSize, size_t * fileLength) + * + * Returns the length of the given file. + * (This is just a wrapper around Get_File_Length().) + * + * Returns COMMON_ERROR_SUCCESS if the length is read in successfuly. (fileLength will be set to the named file's length in this case.) + * Otherwise returns the approperate error code. + * + * In case of error, (the returned error code is not COMMON_ERROR_SUCCESS), the fileLength argument will NOT be altered. + */ +int FileUtills_Get_File_Length_By_Filename(const char * filename, const size_t filenameSize, size_t * fileLength); + +/*! + * int FileUtills_Get_File_Length(FILE * fp, size_t * fileLength) + * + * Gets the length of the given open file. + * + * This function expects the file stream to be in a good state, (I.e. It's error flag is not set), and that the file + * stream was opened in binary mode. (If the stream is not already open, use Get_File_Length_By_Filename() instead, + * it will ensure that these requirements are met.) + * + * This function calculates the size of the file by starting at the begining and working it's way to the end by calling + * fgetc(), and then checking the state flags (error and eof) after each call to fgetc(). When the eof flag is set, + * (and the error flag is not set), the function will call ftello() to get the offset and check it for error. Finally + * regardless if an error has occured or not, the function will attempt to restore the previous position in the file + * that the file was at when the call to this function was made. + * + * Returns COMMON_ERROR_SUCCESS if the file length is determined. (fileLength will be set to the determined length in this case.) + * + * Returns COMMON_ERROR_INVALID_ARGUMENT if the given file pointer or fileLength pointer is NULL. + * + * Returns COMMON_ERROR_IO_ERROR if one of the f*() functions fails. + * + * Returns COMMON_ERROR_MEMORY_ERROR if the file length was determined, but could not be retrived from the file stream because the + * value could not be converted and stored. (Blame the C standard in this case.....) + * + * Otherwise returns the approperate error code. + * + * In case of error, (the returned error code is not SUCCESS), the fileLength argument will NOT be altered. + */ +int FileUtills_Get_File_Length(FILE * fp, size_t * fileLength); + /*! * int FileUtills_Write_Data_To_File_From_Memory(FILE * OUT, const char * data, const size_t dataLength) * From 23b90d59752f10380f44c49cdb2e9edd7f3d3025 Mon Sep 17 00:00:00 2001 From: codebase7 Date: Sun, 5 Jul 2015 21:11:03 -0400 Subject: [PATCH 038/325] Add Read_Bytes_From_File(). This commit adds the FileUtills_Read_Bytes_From_File() function to FileUtills. --- .../File_Management_Subsystem/FileUtills.cpp | 46 +++++++++++++++++++ .../File_Management_Subsystem/FileUtills.h | 37 +++++++++++++++ 2 files changed, 83 insertions(+) diff --git a/src/Common/Src/File_Management_Subsystem/FileUtills.cpp b/src/Common/Src/File_Management_Subsystem/FileUtills.cpp index 118e066..7ed52b7 100644 --- a/src/Common/Src/File_Management_Subsystem/FileUtills.cpp +++ b/src/Common/Src/File_Management_Subsystem/FileUtills.cpp @@ -365,6 +365,52 @@ int FileUtills_Get_File_Length(FILE * fp, off_t * fileLength) return ret; } +int FileUtills_Read_Bytes_From_File(FILE * IN, const size_t dataLength, char * dataBuf, const size_t dataBufLength, const size_t destStaringOffset, const bool blankDataBuf) +{ + /* Init vars. */ + int ret = COMMON_ERROR_UNKNOWN_ERROR; /* The result of this function. */ + int retFromC = 0; /* The result of C calls. */ + size_t x = 0; /* Counter in for loop. */ + + /* Check for invalid arguments. */ + if ((IN != NULL) && (ferror(IN) == 0) && (feof(IN) == 0) && (dataBuf != NULL) && (dataBufLength > 0) && (dataLength > 0) && ((destStaringOffset + dataLength) < dataBufLength)) + { + /* Blank out dataBuf with NULL bytes if needed. */ + if (blankDataBuf) + { + memset(dataBuf, '\0', dataBufLength); + } + + /* Begin data input loop. */ + for (x = 0; ((x < dataLength) && ((destStaringOffset + x) < dataBufLength) && (ferror(IN) == 0) && (feof(IN) == 0) && (retFromC == 0)); x++) + { + /* Get the data. */ + retFromC = fgetc(IN); + dataBuf[(destStaringOffset + x)] = retFromC; + } + + /* Check for success. */ + if ((ferror(IN) == 0) && (feof(IN) == 0) && (retFromC == 0)) + { + /* Data read successfully. */ + ret = COMMON_ERROR_SUCCESS; + } + else + { + /* Bad file stream. */ + ret = COMMON_ERROR_IO_ERROR; + } + } + else + { + /* Invalid arguments. */ + ret = COMMON_ERROR_INVALID_ARGUMENT; + } + + /* Exit function. */ + return ret; +} + int FileUtills_Write_Data_To_File_From_Memory(FILE * OUT, const char * data, const size_t dataLength) { /* Init vars. */ diff --git a/src/Common/Src/File_Management_Subsystem/FileUtills.h b/src/Common/Src/File_Management_Subsystem/FileUtills.h index d6fa4f5..cff2bc7 100644 --- a/src/Common/Src/File_Management_Subsystem/FileUtills.h +++ b/src/Common/Src/File_Management_Subsystem/FileUtills.h @@ -114,6 +114,43 @@ int FileUtills_Get_File_Length_By_Filename(const char * filename, const size_t f */ int FileUtills_Get_File_Length(FILE * fp, size_t * fileLength); +/*! + * int FileUtills_Read_Bytes_From_File(FILE * IN, const size_t dataLength, char * dataBuf, const size_t dataBufLength, const size_t destStaringOffset, const bool blankDataBuf) + * + * Reads the given amount of bytes from the given input file and copies them + * to the given memory buffer. + * + * WARNING: This function expects a pre-allocated memory buffer as big as the + * given data length. If the buffer is smaller than this a memory access violation + * WILL HAPPEN. + * + * NOTE: This function expects that the given input file is already open and not errored out when called. + * The input file will remain open after the function returns. (It will still be usable if the returned error code is SUCCESS.) + * + * The input position of the file will NOT be restored in ANY instance after this function returns. + * If you need the current position for something, copy it elsewhere before calling this function. + * + * @pram IN: C FILE structure that points to a pre-opened file that data will be read from. (Cannot be in an error state, data will be read from the file's current offset.) + * @pram dataLength: The amount of data to read from the file. + * @pram dataBuf: Preallocated C-String where the data read from the file will be stored. (Will not be reallocated if too small.) + * @pram dataBufLength: The total length of the pre-allocated dataBuf string. + * @pram destStaringOffset: Position in the dataBuf string where read data from the file will start at. + * @pram blankDataBuf: Whether or not to blank out the dataBuf with NULL bytes. + * + * Returns COMMON_ERROR_SUCCESS if the data is read into the memory buffer successfully. + * + * Returns COMMON_ERROR_INVALID_ARGUMENT if a given pointer is NULL, + * the given input file has errored out prior to the function call, + * dataLength or dataBufLength is less than 1, or destStaringOffset plus dataLength + * is greater than or equal to dataBufLength. + * + * Returns COMMON_ERROR_IO_ERROR on all f*() errors, or if the end of the file is hit prior to reading + * the amount of requested data. + * + * Otherwise returns the appropriate error code. + */ +int FileUtills_Read_Bytes_From_File(FILE * IN, const size_t dataLength, char * dataBuf, const size_t dataBufLength, const size_t destStaringOffset, const bool blankDataBuf); + /*! * int FileUtills_Write_Data_To_File_From_Memory(FILE * OUT, const char * data, const size_t dataLength) * From c0298956e5f7d9f82bc9afe73a36904a90bc0753 Mon Sep 17 00:00:00 2001 From: codebase7 Date: Sun, 5 Jul 2015 21:14:40 -0400 Subject: [PATCH 039/325] Rewrite attempt at FileUtills::Create_MSYS_Emulated_Symbolic_Link() This commit is an attempt to rewrite / impliment the FileUtills_Create_MSYS_Emulated_Symbolic_Link() and FileUtills::Read_MSYS_Emulated_Symbolic_Link() functions for FileUtills. --- ...tills_Emulated_Symbolic_Link_Functions.cpp | 529 +++++++++--------- 1 file changed, 271 insertions(+), 258 deletions(-) diff --git a/src/Common/Src/File_Management_Subsystem/FileUtills_Emulated_Symbolic_Link_Functions.cpp b/src/Common/Src/File_Management_Subsystem/FileUtills_Emulated_Symbolic_Link_Functions.cpp index 440e352..3e26c7f 100644 --- a/src/Common/Src/File_Management_Subsystem/FileUtills_Emulated_Symbolic_Link_Functions.cpp +++ b/src/Common/Src/File_Management_Subsystem/FileUtills_Emulated_Symbolic_Link_Functions.cpp @@ -21,287 +21,300 @@ // Include header file. #include "FileUtills_Emulated_Symbolic_Link_Functions.h" +#include "../Byte_Order.h" /* Defines the various Common_*_Endianness_Check() functions. */ -int FileUtills::Create_MSYS_Emulated_Symbolic_Link(const std::string & linkDestionation, const std::string & pathToLinkFile) +int FileUtills::Create_MSYS_Emulated_Symbolic_Link(const char * linkDestionation, const size_t linkDestionationSize, + const char * pathToLinkFile, const size_t pathToLinkFileSize) { - // Init vars. - int ret = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; // The result of this function. - size_t linkSize = linkDestionation.size(); // The size of the link destionation. - fstream outputFile; // The fstream for the emulated link file. - - // Check for valid arguments. - if (linkSize > 0) - { - if (pathToLinkFile.size() > 0) + /* Init vars. */ + int ret = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; /* The result of this function. */ + int retFromC = 0; /* The result of C calls. */ + FILE * outputFile = NULL; /* The FILE pointer for the emulated link file. */ + size_t tempSize = 0; /* Temporary size used to calculate the size of variables. */ + + /* Check for valid arguments. */ + if ((linkDestionation != NULL) && (pathToLinkFile != NULL) && (linkDestionationSize > 0) && (pathToLinkFileSize > 0)) { - // Begin try block. - try { - // Open the link file in append mode. - outputFile.open(pathToLinkFile.c_str(), std::ios::out | std::ios::binary | std::ios::append); - if (outputFile.is_open()) - { - // OK, Check to see if the file is blank. - outputFile.seekg(0, std::ios::end); - if (outputFile.tellg() == 0) + /* Check and see if the file already exists. */ + ret = FileUtills::DoesExist(pathToLinkFile, pathToLinkFileSize); + if (ret == FILEUTILLS_ERROR_NON_EXISTANT) { - // OK, seek back to the beginning. - outputFile.seekg(0, std::ios::beg); - - // Now output the magic string. - outputFile << MSYS_EMU_SYMLINK_MAGIC; - - // Determine if we need to swap the byte order of the integers. (size of length and the length itself are supposed to be little-endian encoded.) - if (DataProcess::) - { - // Now we need to output the number of bytes for the destionationLink string's length. (ie. sizeof(size_t)). (This is in little-endianess format.) - outputFile << - - // Now we need to output the length of the destionationLink string. (This is in little-endianess format.) - outputFile << - } - else - { - // Now we need to output the number of bytes for the destionationLink string's length. (ie. sizeof(size_t)). (This is in little-endianess format.) - outputFile << - - // Now we need to output the length of the destionationLink string. (This is in little-endianess format.) - outputFile << - } - - // Output the destionationLink string. - outputFile << destionationLink; - - // Flush the output buffer. - outputFile.flush(); - - // Check for good output buffer. - if (outputFile.good()) - { - // Success. - ret = COMMON_ERROR_SUCCESS; - } - else - { - // IO Error. - ret = COMMON_ERROR_IO_ERROR; - - // Log the error. - COMMON_LOG_DEBUG("FileUtills::Create_MSYS_Emulated_Symbolic_Link(): "); - COMMON_LOG_DEBUG(Common::Get_Error_Message(ret)); - COMMON_LOG_DEBUG(" Unable to create emulated symbolic link file ( "); - COMMON_LOG_DEBUG(pathToLinkFile.c_str()); - COMMON_LOG_DEBUG(" )\n"); - - // Invalidate link file. - outputFile.clear(); - outputFile.seekp(0, std::ios::beg); - outputFile.seekg(0, std::ios::beg); - outputFile.put('\0'); - } - - // Close the file. - outputFile.close(); + /* Open the new link file for writing. */ + outputFile = fopen(pathToLinkFile, "wb"); + if (outputFile != NULL) + { + /* Now output the magic string. */ + ret = FileUtills_Write_Data_To_File_From_Memory(outputFile, MSYS_EMU_SYMLINK_MAGIC, sizeof MSYS_EMU_SYMLINK_MAGIC); + if (ret == COMMON_ERROR_SUCCESS) + { + /* Set tempSize to the length of a size_t. (length of the path length integer.) */ + tempSize = sizeof (size_t); + + /* Determine if we need to swap the byte order of the integers. (size of length and the length itself are supposed to be big-endian encoded.) */ + if (Common_UINT_Endianness_Check() == MSYS_BIG_ENDIAN) + { + /* Now we need to output the number of bytes for the linkDestionation string's length. (ie. sizeof(size_t)). (This is in big-endianess format.) */ + ret = FileUtills_Write_Data_To_File_From_Memory(outputFile, ((char*)(&tempSize)), MSYS_EMU_SYMLINK_BYTE_COUNT_FIELD_SIZE); + if (ret == COMMON_ERROR_SUCCESS) + { + /* Now we need to output the length of the linkDestionation string. (This is in big-endianess format.) */ + tempSize = linkDestionationSize; + ret = FileUtills_Write_Data_To_File_From_Memory(outputFile, ((char*)(&tempSize)), sizeof(size_t)); + } + } + else + { + /* Convert the bits to big endian first. */ + ret = Common_Host_To_Big_Endian_UInt(&tempSize); + if (ret == COMMON_ERROR_SUCCESS) + { + /* Now we need to output the number of bytes for the linkDestionation string's length. (ie. sizeof(size_t)). (This is in big-endianess format.) */ + ret = FileUtills_Write_Data_To_File_From_Memory(outputFile, ((char*)(&tempSize)), MSYS_EMU_SYMLINK_BYTE_COUNT_FIELD_SIZE); + if (ret == COMMON_ERROR_SUCCESS) + { + /* Now convert the length of the string to big-endian format. */ + tempSize = linkDestionationSize; + ret = Common_Host_To_Big_Endian_UInt(&tempSize); + if (ret == COMMON_ERROR_SUCCESS) + { + /* Now we need to output the length of the linkDestionation string. (This is in big-endianess format.) */ + ret = FileUtills_Write_Data_To_File_From_Memory(outputFile, ((char*)(&tempSize)), sizeof(size_t)); + } + } + } + } + + /* Only continue if we were successful in outputting the length. */ + if (ret == COMMON_ERROR_SUCCESS) + { + /* Output the linkDestionation string. */ + ret = FileUtills_Write_Data_To_File_From_Memory(outputFile, linkDestionation, linkDestionationSize); + } + + /* Close the file. */ + retFromC = fclose(outputFile); + if (retFromC != 0) + { + if (ret == COMMON_ERROR_SUCCESS) + { + /* OK, we could not close the file for some reason. */ + ret = COMMON_ERROR_IO_ERROR; + COMMON_LOG_DEBUG("FileUtills_Create_MSYS_Emulated_Symbolic_Link(): "); + COMMON_LOG_DEBUG(Common_Get_Error_Message(COMMON_ERROR_IO_ERROR)); + COMMON_LOG_DEBUG(" Could not close link file."); + + } + else + { + /* Previous errors detected. */ + COMMON_LOG_DEBUG("FileUtills_Create_MSYS_Emulated_Symbolic_Link(): "); + COMMON_LOG_DEBUG(Common_Get_Error_Message(COMMON_ERROR_IO_ERROR)); + COMMON_LOG_DEBUG(" Could not close link file, another error was detected: "); + COMMON_LOG_DEBUG(Common_Get_Error_Message(ret)); + ret = COMMON_ERROR_IO_ERROR; + } + } + } + } + else + { + /* Could not open output file for writing. */ + ret = COMMON_ERROR_IO_ERROR; + + /* Log the error. */ + COMMON_LOG_DEBUG("FileUtills_Create_MSYS_Emulated_Symbolic_Link(): "); + COMMON_LOG_DEBUG(Common_Get_Error_Message(COMMON_ERROR_IO_ERROR)); + COMMON_LOG_DEBUG(" could not open ( "); + COMMON_LOG_DEBUG(pathToLinkFile); + COMMON_LOG_DEBUG(" ) for writing."); + } } else { - // File is not empty, abort. - ret = FILEUTILLS_ERROR_EXISTANT; - - // Log the error. - COMMON_LOG_INFO("FileUtills::Create_MSYS_Emulated_Symbolic_Link(): "); - COMMON_LOG_INFO(Common::Get_Error_Message(ret)); - COMMON_LOG_INFO(" The given path ( "); - COMMON_LOG_INFO(pathToLinkFile.c_str()); - COMMON_LOG_INFO(" ) already exists.\n"); + /* File is not empty, abort. */ + ret = FILEUTILLS_ERROR_EXISTANT; + + /* Log the error. */ + COMMON_LOG_INFO("FileUtills_Create_MSYS_Emulated_Symbolic_Link(): "); + COMMON_LOG_INFO(Common_Get_Error_Message(FILEUTILLS_ERROR_EXISTANT)); + COMMON_LOG_INFO(" The given path ( "); + COMMON_LOG_INFO(pathToLinkFile); + COMMON_LOG_INFO(" ) already exists."); } - } - else - { - // Could not open output file for writing. - ret = COMMON_ERROR_IO_ERROR; - - // Log the error. - COMMON_LOG_INFO("FileUtills::Create_MSYS_Emulated_Symbolic_Link(): "); - COMMON_LOG_INFO(Common::Get_Error_Message(ret)); - COMMON_LOG_INFO(" Unable to open ( "); - COMMON_LOG_INFO(pathToLinkFile.c_str()); - COMMON_LOG_INFO(" ) for writing.\n"); - } - } - catch(exception &ex) - { - // Exception thown. - ret = COMMON_ERROR_EXCEPTION_THROWN; - COMMON_LOG_VERBOSE("FileUtills::Create_MSYS_Emulated_Symbolic_Link(): "); - COMMON_LOG_VERBOSE(Common::Get_Error_Message(ret)); - COMMON_LOG_VERBOSE(" "); - COMMON_LOG_VERBOSE(ex.what()); - COMMON_LOG_VERBOSE("\n"); - } } else { - // Invalid path. - ret = COMMON_ERROR_INVALID_ARGUMENT; - - // Log the error. - COMMON_LOG_DEBUG("FileUtills::Create_MSYS_Emulated_Symbolic_Link(): "); - COMMON_LOG_DEBUG(Common::Get_Error_Message(COMMON_ERROR_INVALID_ARGUMENT)); - COMMON_LOG_DEBUG(" Given path to the emulated link file is invalid.\n"); - } - } - else - { - // Invalid destionationLink. - ret = COMMON_ERROR_INVALID_ARGUMENT; - - // Log the error. - COMMON_LOG_DEBUG("FileUtills::Create_MSYS_Emulated_Symbolic_Link(): "); - COMMON_LOG_DEBUG(Common::Get_Error_Message(COMMON_ERROR_INVALID_ARGUMENT)); - COMMON_LOG_DEBUG(" Given destionation link string is invalid.\n"); - } - - // Close the file if it's still open. - if (outputFile.is_open()) - { - outputFile.close(); - } - - // Copy the result to Common::commonLastErrorCode. - Common::commonLastErrorCode = ret; - - // Return the result. - return ret; -} - -int FileUtills::Read_MSYS_Emulated_Symbolic_Link(std::string & link, const std::string & pathToLinkFile) -{ - // Init vars. - int ret = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; // The result of this function. - std::string tempLinkBuf = ""; // Temporary buffer for constructing the link string. - fstream inputFile; // The fstream for the emulated link file. - - // Blank the link string. - link.clear(); - - // Check for valid argument. - if (pathToLinkFile.size() > 0) - { - // Begin try block. - try { - + /* Invalid destionationLink. */ + ret = COMMON_ERROR_INVALID_ARGUMENT; + /* Log the error. */ + COMMON_LOG_DEBUG("FileUtills_Create_MSYS_Emulated_Symbolic_Link(): "); + COMMON_LOG_DEBUG(Common_Get_Error_Message(COMMON_ERROR_INVALID_ARGUMENT)); + COMMON_LOG_DEBUG(" Given destination link string is invalid."); } - catch(exception &ex) - { - // Exception thown. - ret = COMMON_ERROR_EXCEPTION_THROWN; - COMMON_LOG_VERBOSE("FileUtills::Read_MSYS_Emulated_Symbolic_Link(): "); - COMMON_LOG_VERBOSE(Common::Get_Error_Message(ret)); - COMMON_LOG_VERBOSE(" "); - COMMON_LOG_VERBOSE(ex.what()); - COMMON_LOG_VERBOSE("\n"); - } - } - else - { - // Invalid path. - ret = COMMON_ERROR_INVALID_ARGUMENT; - - // Log the error. - COMMON_LOG_DEBUG("FileUtills::Read_MSYS_Emulated_Symbolic_Link(): "); - COMMON_LOG_DEBUG(Common::Get_Error_Message(COMMON_ERROR_INVALID_ARGUMENT)); - COMMON_LOG_DEBUG(" Given path to the emulated link file is invalid.\n"); - } - - // Close the file if it's still open. - if (inputFile.is_open()) - { - inputFile.close(); - } - // If we failed, blank the link string. - if (ret != COMMON_ERROR_SUCCESS) - { - tempLinkBuf.clear(); - link.clear(); - } - - // Copy the result to Common::commonLastErrorCode. - Common::commonLastErrorCode = ret; - - // Return the result. - return ret; + /* Return the result. */ + return ret; } -int FileUtills::Update_MSYS_Emulated_Symbolic_Link(const std::string & linkDestionation, const std::string & pathToLinkFile) +int FileUtills::Read_MSYS_Emulated_Symbolic_Link(char ** retStr, size_t * retStrSize, const char * pathToLinkFile, + const size_t pathToLinkFileSize) { - // Init vars. - int ret = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; // The result of this function. - size_t linkSize = linkDestionation.size(); // The size of the link destionation. - std::string tempLinkBuf = ""; // Temporary buffer for constructing the link string. - fstream linkFile; // The fstream for the emulated link file. - - // Check for valid arguments. - if (linkSize > 0) - { - if (pathToLinkFile.size() > 0) + /* Init vars. */ + int ret = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; /* The result of this function. */ + int retFromC = 0; /* The result of C calls. */ + unsigned int byteCount = 0; /* The number of bytes in a size_t variable, as reported from the file. */ + FILE * inputFile = NULL; /* The FILE pointer for the emulated link file. */ + char * tempRetStr = NULL; /* Used to construct the retStr before we copy the pointer at the end. */ + size_t tempSize = 0; /* Temporary size used to calculate the size of variables. */ + size_t fileSize = 0; /* Size of the given input file. */ + + + /* Check for valid arguments. */ + if ((retStr != NULL) && (pathToLinkFile != NULL) && (retStrSize != NULL) && (pathToLinkFileSize > 0)) { - // Begin try block. - try { - - - } - catch(exception &ex) - { - // Exception thown. - ret = COMMON_ERROR_EXCEPTION_THROWN; - COMMON_LOG_VERBOSE("FileUtills::Update_MSYS_Emulated_Symbolic_Link(): "); - COMMON_LOG_VERBOSE(Common::Get_Error_Message(ret)); - COMMON_LOG_VERBOSE(" "); - COMMON_LOG_VERBOSE(ex.what()); - COMMON_LOG_VERBOSE("\n"); - } + /* Open the file for reading. */ + inputFile = fopen(pathToLinkFile, "rb"); + if (inputFile != NULL) + { + /* Get the size of the file. */ + + + /* Allocate the needed tempRetStr buffer. */ + tempRetStr = (char*)malloc(MSYS_FILEUTILLS_IO_BUFFER_LENGTH); + if (tempRetStr != NULL) + { + /* OK, check and see if this is a link file. */ + ret = FileUtills_Read_Bytes_From_File(IN, (sizeof MSYS_EMU_SYMLINK_MAGIC), tempRetStr, MSYS_FILEUTILLS_IO_BUFFER_LENGTH, 0, true); + if (ret == COMMON_ERROR_SUCCESS) + { + /* Check and see if the given bytes are the correct magic signature. */ + if (memcmp(tempRetStr, MSYS_EMU_SYMLINK_MAGIC, (sizeof MSYS_EMU_SYMLINK_MAGIC)) == 0) + { + /* Valid magic signature found, check and see if we can store the byte count in a size_t variable. */ + if (MSYS_EMU_SYMLINK_BYTE_COUNT_FIELD_SIZE < (sizeof(size_t))) + { + /* Load the length of size_t from the file. */ + ret = FileUtills_Read_Bytes_From_File(IN, MSYS_EMU_SYMLINK_BYTE_COUNT_FIELD_SIZE, tempRetStr, MSYS_FILEUTILLS_IO_BUFFER_LENGTH, ((sizeof (size_t)) - MSYS_EMU_SYMLINK_BYTE_COUNT_FIELD_SIZE), true); + if (ret == COMMON_ERROR_SUCCESS) + { + /* Memcpy the data into tempSize. */ + memcpy(((char*)&tempSize), tempRetStr, sizeof (tempSize)); + + /* Get the system's endianess. */ + ret = Common_SIZE_T_Endianness_Check(); + switch (ret) + { + MSYS_BIG_ENDIAN: + /* Nothing to do. */ + ret = COMMON_ERROR_SUCCESS; + break; + MSYS_LITTLE_ENDIAN: + /* We need to convert the bytes. */ + ret = Common_Big_Endian_To_Host_UInt(tempSize); + break; + MSYS_UNKNOWN_ENDIANNESS: + default: + /* ERROR, we cannot convert the bytes due to unknown host endianess. */ + ret = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; + break; + }; + + /* Make sure we can store the size_t from the file. */ + if (tempSize <= sizeof(size_t)) + { + /* Get link length variable. */ + ret = FileUtills_Read_Bytes_From_File(IN, , tempRetStr , ); + if (ret == COMMON_ERROR_SUCCESS) + { + /* OK copy the bytes from the tempRetStr buffer to byteCount. */ + memcpy(((char*)&byteCount), tempRetStr, MSYS_EMU_SYMLINK_BYTE_COUNT_FIELD_SIZE); + + /* Check and see if we need to convert the bytes to the host's format. */ + ret = Common_SIZE_T_Endianness_Check(); + switch (ret) + { + MSYS_BIG_ENDIAN: + /* Nothing to do. */ + ret = COMMON_ERROR_SUCCESS; + break; + MSYS_LITTLE_ENDIAN: + /* We need to convert the bytes. */ + ret = Common_Big_Endian_To_Host_UInt(tempSize); + break; + MSYS_UNKNOWN_ENDIANNESS: + default: + /* ERROR, we cannot convert the bytes due to unknown host endianess. */ + ret = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; + break; + }; + + /* Check for success. */ + if (ret == COMMON_ERROR_SUCCESS) + { + /* OK, check and see if our size_t can store that much data. */ + if (byteCount <= (sizeof size_t)) + { + + } + else + { + /* Size of length variable is too big for us to process. */ + ret = ; + } + } + } + } + } + } + } + else + { + /* Could not allocate memory. */ + ret = COMMON_ERROR_MEMORY_ERROR; + } + + /* Close the input file. */ + retFromC = fclose(IN); + if (retFromC != 0) + { + /* Could not close the input file. */ + if (ret != COMMON_ERROR_IO_ERROR) + { + ret = COMMON_ERROR_IO_ERROR; + } + + /* Log the error. */ + COMMON_LOG_DEBUG("FileUtills_Read_MSYS_Emulated_Symbolic_Link(): "); + COMMON_LOG_DEBUG(Common_Get_Error_Message(COMMON_ERROR_IO_ERROR)); + COMMON_LOG_DEBUG(" could not close input file."); + } + } + else + { + /* Could not open input file for reading. */ + ret = COMMON_ERROR_IO_ERROR; + + /* Log the error. */ + COMMON_LOG_DEBUG("FileUtills_Read_MSYS_Emulated_Symbolic_Link(): "); + COMMON_LOG_DEBUG(Common_Get_Error_Message(COMMON_ERROR_IO_ERROR)); + COMMON_LOG_DEBUG(" could not open ( "); + COMMON_LOG_DEBUG(pathToLinkFile); + COMMON_LOG_DEBUG(" ) for reading."); + } } else { - // Invalid path. - ret = COMMON_ERROR_INVALID_ARGUMENT; + /* Invalid arguments. */ + ret = COMMON_ERROR_INVALID_ARGUMENT; - // Log the error. - COMMON_LOG_DEBUG("FileUtills::Update_MSYS_Emulated_Symbolic_Link(): "); - COMMON_LOG_DEBUG(Common::Get_Error_Message(COMMON_ERROR_INVALID_ARGUMENT)); - COMMON_LOG_DEBUG(" Given path to the emulated link file is invalid.\n"); + /* Log the error. */ + COMMON_LOG_DEBUG("FileUtills_Read_MSYS_Emulated_Symbolic_Link(): "); + COMMON_LOG_DEBUG(Common_Get_Error_Message(COMMON_ERROR_INVALID_ARGUMENT)); } - } - else - { - // Invalid destionationLink. - ret = COMMON_ERROR_INVALID_ARGUMENT; - - // Log the error. - COMMON_LOG_DEBUG("FileUtills::Update_MSYS_Emulated_Symbolic_Link(): "); - COMMON_LOG_DEBUG(Common::Get_Error_Message(COMMON_ERROR_INVALID_ARGUMENT)); - COMMON_LOG_DEBUG(" Given destionation link string is invalid.\n"); - } - - // Close the file if it's still open. - if (linkFile.is_open()) - { - linkFile.close(); - } - - // If we failed, blank the link string. - if (ret != COMMON_ERROR_SUCCESS) - { - tempLinkBuf.clear(); - } - - // Copy the result to Common::commonLastErrorCode. - Common::commonLastErrorCode = ret; - // Return the result. - return ret; + /* Return the result. */ + return ret; } -// End of FileUtills_Emulated_Symbolic_Link_Functions.cpp +/* End of FileUtills_Emulated_Symbolic_Link_Functions.cpp */ From 44f4797866f401133d403cd4884b875bbe104a7f Mon Sep 17 00:00:00 2001 From: codebase7 Date: Mon, 6 Jul 2015 02:59:06 -0400 Subject: [PATCH 040/325] Compile Fixes for Byte_Order.h This commit fixes the following with Byte_Order.h: - Fixes include file for Common namespace error codes. (Due to commit 51fbb9a7b30e253283ca298e861e1915263b72df ) - Fixes stdbool header include. (MSVC 2013 includes support for C99's stdbool.h) - Adds missing include headers stdlib.h, stddef.h, and string.h. --- src/Common/Src/Byte_Order/Byte_Order.h | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/Common/Src/Byte_Order/Byte_Order.h b/src/Common/Src/Byte_Order/Byte_Order.h index 46806f0..e93e9cc 100644 --- a/src/Common/Src/Byte_Order/Byte_Order.h +++ b/src/Common/Src/Byte_Order/Byte_Order.h @@ -36,10 +36,22 @@ extern "C" { #include "../../../DLL_PORT.h" /* Defines MSYS_DLL_EXPORT, and MSYS_DLL_IMPORT_TEMPLATE. */ /* Internal headers. */ -#include "../Error_Handler/Common_Error_Handler_Structures.h" /* Defines the error codes. */ +#include "../Error_Handler/Common_Error_Handler_Error_Codes.h" /* Defines the error codes. */ #include "Byte_Order_Integers.h" #include "Byte_Order_Floating_Points.h" +/* Define bool. */ +#if _MSC_FULL_VER && _MSC_FULL_VER < 180031101 +#include "../stdbool.h" /* Older versions of Visual C don't support the C99 stdbool header. So we have to fake one. */ +#else +#include +#endif + +/* External headers. */ +#include /* Defines NULL. */ +#include /* Defines malloc(), free(). */ +#include /* Defines memset(), memcpy(). */ + /*! * int Common_Byte_Swap(char * data, const size_t dataLength) * From c845c9e7f33c649bbce38e2380a923a65b95a6aa Mon Sep 17 00:00:00 2001 From: codebase7 Date: Mon, 6 Jul 2015 03:06:33 -0400 Subject: [PATCH 041/325] Add the Basic_Linked_List code. This commit adds the initial attempt at some Linked List support. (C code, not needed for C++ code, use a standard library container instead please!) --- src/Core/Src/Basic_Linked_List.c | 446 +++++++++++++++++++++++++++++++ src/Core/Src/Basic_Linked_List.h | 192 +++++++++++++ src/Core/Src/CMakeLists.txt | 9 +- 3 files changed, 645 insertions(+), 2 deletions(-) create mode 100644 src/Core/Src/Basic_Linked_List.c create mode 100644 src/Core/Src/Basic_Linked_List.h diff --git a/src/Core/Src/Basic_Linked_List.c b/src/Core/Src/Basic_Linked_List.c new file mode 100644 index 0000000..29d615b --- /dev/null +++ b/src/Core/Src/Basic_Linked_List.c @@ -0,0 +1,446 @@ +/*! + Multiverse Engine Project 05/7/2015 Basic_Linked_List.c + + Copyright (C) 2015 Multiverse Engine Project + + This program is free software; + you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this program; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Official source repository and project information can be found at + https://github.com/codebase7/mengine +*/ + +/* Begin extern C if needed. */ +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Internal includes. */ +#include "Basic_Linked_List.h" + +/* External includes. */ +#include /* Define malloc() & free(). */ +#include /* Define memset(). */ + +void Blank_MSYS_Linked_List_Object(MSYS_Linked_List_T * list) +{ + /* Check for valid arguments. */ + if (list != NULL) + { + /* Blank out the list object. */ + list->data = NULL; + list->dataLength = 0; + list->nextObject = NULL; + list->prevObject = NULL; + } + + /* Exit function. */ + return; +} + +int MSYS_Linked_List_Allocate_Linked_List_Object(MSYS_Linked_List_T ** ppAllocatedList) +{ + /* Init vars. */ + int ret = COMMON_ERROR_UNKNOWN_ERROR; /* The result code for this function. */ + MSYS_Linked_List_T * pList = NULL; /* Temporary pointer used to create the list object. */ + + /* Check for valid args. */ + if (ppAllocatedList != NULL) + { + /* Allocating new object. */ + pList = (MSYS_Linked_List_T *)malloc(sizeof(MSYS_Linked_List_T)); + if (pList != NULL) + { + /* Blank out the list. */ + Blank_MSYS_Linked_List_Object(pList); + + /* Determine if we are creating a new list or appending to an existing one. */ + if ((*ppAllocatedList) != NULL) + { + /* Appending to an existing list, determine if we are at the end of the list. */ + if ((*ppAllocatedList)->nextObject != NULL) + { + /* Only update the next object's prevObject pointer if it points to the current object. */ + if ((*ppAllocatedList)->nextObject->prevObject == (*ppAllocatedList)) + { + (*ppAllocatedList)->nextObject->prevObject = pList; + } + + /* Somewhere within the list, need to update the pointers. */ + pList->prevObject = (*ppAllocatedList); + pList->nextObject = (*ppAllocatedList)->nextObject; + } + + /* Set the next pointer. */ + (*ppAllocatedList)->nextObject = pList; + } + else + { + /* Creating a new list. */ + (*ppAllocatedList) = pList; + } + + /* Done. */ + ret = COMMON_ERROR_SUCCESS; + } + else + { + /* Could not allocate memory. */ + ret = COMMON_ERROR_MEMORY_ERROR; + } + } + else + { + /* Invalid arguments. */ + ret = COMMON_ERROR_INVALID_ARGUMENT; + } + + /* Exit function. */ + return ret; +} + +void MSYS_Linked_List_Deallocate_Linked_List_Object(MSYS_Linked_List_T ** ppAllocatedList) +{ + /* Init vars. */ + MSYS_Linked_List_T * pList = NULL; /* Temporary pointer used to deallocate the given object. + * (Just in case we get called with an object's nextObject or prevObject + * pointer as the current object.) + */ + + /* Check for valid args. */ + if ((ppAllocatedList != NULL) && ((*ppAllocatedList) != NULL)) + { + /* Copy the pointer. */ + pList = (*ppAllocatedList); + + /* Check for other objects to update. */ + if ((pList->prevObject != NULL) || (pList->nextObject != NULL)) + { + /* Check and see if both the previous object and the next object are defined. */ + if ((pList->prevObject != NULL) && (pList->nextObject != NULL)) + { + /* Simple stiching, but make sure that the next and previous objects actually point to the current one before altering them. */ + if (pList->prevObject->nextObject == pList) + { + pList->prevObject->nextObject = pList->nextObject; + } + if (pList->nextObject->prevObject == pList) + { + pList->nextObject->prevObject = pList->prevObject; + } + } + else + { + /* OK, figure out what object needs to be updated. */ + if (pList->prevObject != NULL) + { + /* Set the previous object's next object pointer to NULL, + * but make sure that the previous object actually points + * to the current one before altering it. + */ + if (pList->prevObject->nextObject == pList) + { + pList->prevObject->nextObject = NULL; + } + } + if (pList->nextObject != NULL) + { + /* Set the next object's previous object pointer to NULL, + * but make sure that the next object actually points + * to the current one before altering it. + */ + if (pList->nextObject->prevObject == pList) + { + pList->nextObject->prevObject = NULL; + } + } + } + } + + /* Blank and deallocate the current object. */ + Blank_MSYS_Linked_List_Object((*ppAllocatedList)); + free((*ppAllocatedList)); + (*ppAllocatedList) = NULL; + } + + /* Exit function. */ + return; +} + +void MSYS_Linked_List_Deallocate_Entire_List(MSYS_Linked_List_T ** ppAllocatedList) +{ + /* Init vars. */ + int retFromFunct = COMMON_ERROR_UNKNOWN_ERROR; /* The result code from MSYS_Linked_List_*() functions. */ + MSYS_Linked_List_T * nextObject = NULL; /* The next object in the list, after the current one. */ + MSYS_Linked_List_T * currentObject = NULL; /* The current object we are looking at in the list. */ + MSYS_Linked_List_T * lastObject = NULL; /* The last object in the list. */ + + /* Check for invalid arguments. */ + if ((ppAllocatedList != NULL) && ((*ppAllocatedList) != NULL)) + { + /* Get the first object in the list. */ + retFromFunct = MSYS_Linked_List_Get_First_Object((*ppAllocatedList), ¤tObject); + if (retFromFunct == COMMON_ERROR_SUCCESS) + { + /* Get the last object in the list. */ + retFromFunct = MSYS_Linked_List_Get_Last_Object((*ppAllocatedList), &lastObject); + if (retFromFunct == COMMON_ERROR_SUCCESS) + { + /* Begin deallocation loop. */ + while ((retFromFunct == COMMON_ERROR_SUCCESS) && (currentObject != lastObject)) + { + /* Get the next object. */ + retFromFunct = MSYS_Linked_List_Get_Next_Object(currentObject, &nextObject); + if (retFromFunct == COMMON_ERROR_SUCCESS) + { + /* Deallocate the current object. */ + MSYS_Linked_List_Deallocate_Linked_List_Object(¤tObject); + + /* Copy the pointer for the next object to the current one. */ + currentObject = nextObject; + } + } + } + } + } + + /* Exit function. */ + return; +} + +int MSYS_Linked_List_Get_First_Object(const MSYS_Linked_List_T * pAllocatedList, MSYS_Linked_List_T ** ppFirstObject) +{ + /* Init vars. */ + int ret = COMMON_ERROR_UNKNOWN_ERROR; /* The result code for this function. */ + const MSYS_Linked_List_T * currentObject = NULL; /* The current object we are looking at in the list. */ + + /* Check for valid args. */ + if ((pAllocatedList != NULL) && (ppFirstObject != NULL)) + { + /* Copy the pointer. */ + currentObject = pAllocatedList; + + /* Set ret to COMMON_ERROR_INTERNAL_ERROR. */ + ret = COMMON_ERROR_INTERNAL_ERROR; + + /* Search for the first object. + * (The first object in the list has it's prevObject pointer set to NULL.) + * Also the extra check is to prevent jumping out of our chain. + */ + while ((ret == COMMON_ERROR_INTERNAL_ERROR) && + (currentObject->prevObject != NULL) && + (currentObject->prevObject->nextObject == currentObject) && + (currentObject->prevObject->prevObject != currentObject)) + { + /* Check and see if the next object is going to end the loop. */ + if (currentObject->prevObject->prevObject == NULL) + { + /* Copy the pointer for the first object. */ + (*ppFirstObject) = currentObject->prevObject; + + /* Success. */ + ret = COMMON_ERROR_SUCCESS; + } + + /* Switch to previous object. */ + currentObject = currentObject->prevObject; + } + } + else + { + /* Invalid arguments. */ + ret = COMMON_ERROR_INVALID_ARGUMENT; + } + + /* Exit function. */ + return ret; +} + +int MSYS_Linked_List_Get_Last_Object(const MSYS_Linked_List_T * pAllocatedList, MSYS_Linked_List_T ** ppLastObject) +{ + /* Init vars. */ + int ret = COMMON_ERROR_UNKNOWN_ERROR; /* The result code for this function. */ + const MSYS_Linked_List_T * currentObject = NULL; /* The current object we are looking at in the list. */ + + /* Check for valid args. */ + if ((pAllocatedList != NULL) && (ppLastObject != NULL)) + { + /* Copy the pointer. */ + currentObject = pAllocatedList; + + /* Set ret to COMMON_ERROR_INTERNAL_ERROR. */ + ret = COMMON_ERROR_INTERNAL_ERROR; + + /* Search for the last object. + * (The last object in the list has it's nextObject pointer set to NULL.) + * Also the extra check is to prevent jumping out of our chain. + */ + while ((ret == COMMON_ERROR_INTERNAL_ERROR) && + (currentObject->nextObject != NULL) && + (currentObject->nextObject->prevObject == currentObject) && + (currentObject->nextObject->nextObject != currentObject)) + { + /* Check and see if the next object is going to end the loop. */ + if (currentObject->nextObject->nextObject == NULL) + { + /* Copy the pointer for the last object. */ + (*ppLastObject) = currentObject->nextObject; + + /* Success. */ + ret = COMMON_ERROR_SUCCESS; + } + + /* Switch to next object. */ + currentObject = currentObject->nextObject; + } + } + else + { + /* Invalid arguments. */ + ret = COMMON_ERROR_INVALID_ARGUMENT; + } + + /* Exit function. */ + return ret; +} + +int MSYS_Linked_List_Get_Next_Object(const MSYS_Linked_List_T * pAllocatedList, MSYS_Linked_List_T ** ppNextObject) +{ + /* Init vars. */ + int ret = COMMON_ERROR_UNKNOWN_ERROR; /* The result code for this function. */ + + /* Check for valid args. */ + if ((pAllocatedList != NULL) && (ppNextObject != NULL)) + { + /* Copy the pointer to the next object. */ + (*ppNextObject) = pAllocatedList->nextObject; + + /* Success. */ + ret = COMMON_ERROR_SUCCESS; + } + else + { + /* Invalid arguments. */ + ret = COMMON_ERROR_INVALID_ARGUMENT; + } + + /* Exit function. */ + return ret; +} + +int MSYS_Linked_List_Get_Previous_Object(const MSYS_Linked_List_T * pAllocatedList, MSYS_Linked_List_T ** ppPrevObject) +{ + /* Init vars. */ + int ret = COMMON_ERROR_UNKNOWN_ERROR; /* The result code for this function. */ + + /* Check for valid args. */ + if ((pAllocatedList != NULL) && (ppPrevObject != NULL)) + { + /* Copy the pointer to the previous object. */ + (*ppPrevObject) = pAllocatedList->prevObject; + + /* Success. */ + ret = COMMON_ERROR_SUCCESS; + } + else + { + /* Invalid arguments. */ + ret = COMMON_ERROR_INVALID_ARGUMENT; + } + + /* Exit function. */ + return ret; +} + +int MSYS_Linked_List_Get_Current_Object_Contents(const MSYS_Linked_List_T * pAllocatedList, void ** ppData, size_t * dataLength) +{ + /* Init vars. */ + int ret = COMMON_ERROR_UNKNOWN_ERROR; /* The result code for this function. */ + + /* Check for valid args. */ + if ((pAllocatedList != NULL) && (ppData != NULL) && (dataLength != NULL)) + { + /* Copy the pointer and length. */ + (*ppData) = pAllocatedList->data; + (*dataLength) = pAllocatedList->dataLength; + + /* Success. */ + ret = COMMON_ERROR_SUCCESS; + } + else + { + /* Invalid arguments. */ + ret = COMMON_ERROR_INVALID_ARGUMENT; + } + + /* Exit function. */ + return ret; +} + +int MSYS_Linked_List_Set_Current_Object_Contents(MSYS_Linked_List_T * pAllocatedList, void * pData, const size_t dataLength) +{ + /* Init vars. */ + int ret = COMMON_ERROR_UNKNOWN_ERROR; /* The result code for this function. */ + + /* Check for valid args. */ + if (pAllocatedList != NULL) + { + /* Copy the pointer and length. */ + pAllocatedList->data = pData; + pAllocatedList->dataLength = dataLength; + + /* Success. */ + ret = COMMON_ERROR_SUCCESS; + } + else + { + /* Invalid arguments. */ + ret = COMMON_ERROR_INVALID_ARGUMENT; + } + + /* Exit function. */ + return ret; +} + +int MSYS_Linked_List_Swap_Objects(MSYS_Linked_List_T * pFirstObject, MSYS_Linked_List_T * pSecondObject) +{ + /* Init vars. */ + int ret = COMMON_ERROR_UNKNOWN_ERROR; /* The result code of this function. */ + void * pData = NULL; /* Temporary pointer used to swap the data pointers. */ + size_t dataLength = 0; /* Temporary pointer used to swap the data lengths. */ + + /* Check for invalid arguments. */ + if ((pFirstObject != NULL) && (pSecondObject != NULL)) + { + /* Copy the pointers. */ + pData = pFirstObject->data; + pFirstObject->data = pSecondObject->data; + pSecondObject->data = pData; + pData = NULL; + + /* Copy the data lengths. */ + dataLength = pFirstObject->dataLength; + pFirstObject->dataLength = pSecondObject->dataLength; + pSecondObject->dataLength = dataLength; + dataLength = 0; + + /* Done. */ + ret = COMMON_ERROR_SUCCESS; + } + else + { + /* Invalid arguments. */ + ret = COMMON_ERROR_INVALID_ARGUMENT; + } + + /* Exit function. */ + return ret; +} diff --git a/src/Core/Src/Basic_Linked_List.h b/src/Core/Src/Basic_Linked_List.h new file mode 100644 index 0000000..7375721 --- /dev/null +++ b/src/Core/Src/Basic_Linked_List.h @@ -0,0 +1,192 @@ +/*! + Multiverse Engine Project 25/6/2015 Basic_Linked_List.h + + Copyright (C) 2015 Multiverse Engine Project + + This program is free software; + you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this program; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Official source repository and project information can be found at + https://github.com/codebase7/mengine +*/ + +/* Include guard. */ +#ifndef MSYS_BASIC_LINKED_LIST_H +#define MSYS_BASIC_LINKED_LIST_H + +/* Begin extern C if needed. */ +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Internal includes. */ +#include "../../DLL_PORT.h" /* Defines MSYS_DLL_EXPORT, and MSYS_DLL_IMPORT_TEMPLATE. */ +#include "../../Common/Src/Error_Handler/Common_Error_Handler_Error_Codes.h" /* Defines Common error codes used for return codes. */ + +/* External includes. */ +#include /* Define NULL, size_t. */ + +/* Define basic linked list object. */ +typedef struct MSYS_Linked_List { + void * data; /* Data structure for this object in the chain. */ + size_t dataLength; /* Optional Length of the given data structure if data is non-NULL. */ + struct MSYS_Linked_List * nextObject; /* The next object in the chain, should be NULL if the current object is the last one in the chain. */ + struct MSYS_Linked_List * prevObject; /* The previous object in the chain, should be NULL if the current object is the first one in the chain. */ +} MSYS_Linked_List_T; + +/*! + * MSYS_DLL_EXPORT int MSYS_Linked_List_Allocate_Linked_List_Object(MSYS_Linked_List_T ** ppAllocatedList) + * + * Allocates a new MSYS_Linked_List object. + * + * If the given pointer to object is non-NULL, the newly allocated object will be pointed + * to by the given object's nextObject pointer. If given object's nextObject pointer is + * non-NULL, then the newly allocated object will be inserted between the given object and + * the object that came after it prior to the call to this function. + * + * Ex. + * ppAllocatedList nextObject pointer result: + * NULL N / A (*ppAllocatedList) points to allocated object. + * + * non-NULL NULL (*ppAllocatedList)->nextObject points to allocated object. + * + * non-NULL non-NULL (*ppAllocatedList)->nextObject points to allocated object, + * allocated object->nextObject points to nextObject. + * allocated object->prevObject points to (*ppAllocatedList). + * nextObject->prevObject points to allocated object. (ONLY TRUE IF nextObject->prevObject == (*ppAllocatedList)) + * + * Returns COMMON_ERROR_SUCCESS if allocation was successful. + * Returns COMMON_ERROR_INVALID_ARGUMENT if given pointer to pointer was NULL. + * Returns COMMON_ERROR_MEMORY_ERROR if memory allocation for new object failed. + * Otherwise returns the appropriate error. + * + * If an error is returned, then the list will not be altered. + */ +MSYS_DLL_EXPORT int MSYS_Linked_List_Allocate_Linked_List_Object(MSYS_Linked_List_T ** ppAllocatedList); + +/*! + * MSYS_DLL_EXPORT void MSYS_Linked_List_Deallocate_Linked_List_Object(MSYS_Linked_List_T ** ppAllocatedList) + * + * Deallocates the given MSYS_Linked_List object, and sets it's pointer to NULL. + * + * If the given object points to any other MSYS_Linked_List object, then they will be modified to + * reflect the removal of the given object. + * I.e. The pointed to objects will have their nextObject and prevObject pointers updated. + * + * This function has no return, and will silently fail if the given pointer to pointer is NULL. + * Otherwise upon return, the given pointer to object will be set to NULL. + */ +MSYS_DLL_EXPORT void MSYS_Linked_List_Deallocate_Linked_List_Object(MSYS_Linked_List_T ** ppAllocatedList); + +/*! + * MSYS_DLL_EXPORT void MSYS_Linked_List_Deallocate_Entire_List(MSYS_Linked_List_T ** ppAllocatedList) + * + * Deallocates the given MSYS_Linked_List object and all other objects in it's list. Then sets the given + * argument to NULL. + * + * If the given object points to any other MSYS_Linked_List object, then they will deallocated as well. + * + * This function has no return, and will silently fail if the given pointer to pointer is NULL. + * Otherwise upon return, the given pointer to object will be set to NULL. + */ +MSYS_DLL_EXPORT void MSYS_Linked_List_Deallocate_Entire_List(MSYS_Linked_List_T ** ppAllocatedList); + +/*! + * MSYS_DLL_EXPORT int MSYS_Linked_List_Get_First_Object(const MSYS_Linked_List_T * pAllocatedList, MSYS_Linked_List_T ** ppFirstObject) + * + * Copies the pointer to the first object in the list to the given ppFirstObject argument. + * + * Returns COMMON_ERROR_SUCCESS if copying the pointer to the first object was successful. + * Returns COMMON_ERROR_INVALID_ARGUMENT if a given pointer to pointer or pointer to object was NULL. + * Returns COMMON_ERROR_INTERNAL_ERROR if the given linked list is broken. (I.e. recursive.) + * Otherwise returns the appropriate error. + * + * If an error occurs, ppFirstObject will not be modified. + */ +MSYS_DLL_EXPORT int MSYS_Linked_List_Get_First_Object(const MSYS_Linked_List_T * pAllocatedList, MSYS_Linked_List_T ** ppFirstObject); + +/*! + * MSYS_DLL_EXPORT int MSYS_Linked_List_Get_Last_Object(const MSYS_Linked_List_T * pAllocatedList, MSYS_Linked_List_T ** ppLastObject) + * + * Copies the pointer to the last object in the list to the given ppLastObject argument. + * + * Returns COMMON_ERROR_SUCCESS if copying the pointer to the last object was successful. + * Returns COMMON_ERROR_INVALID_ARGUMENT if a given pointer to pointer or pointer to object was NULL. + * Returns COMMON_ERROR_INTERNAL_ERROR if the given linked list is broken. (I.e. recursive.) + * Otherwise returns the appropriate error. + * + * If an error occurs, ppLastObject will not be modified. + */ +MSYS_DLL_EXPORT int MSYS_Linked_List_Get_Last_Object(const MSYS_Linked_List_T * pAllocatedList, MSYS_Linked_List_T ** ppLastObject); + +/*! + * MSYS_DLL_EXPORT int MSYS_Linked_List_Get_Next_Object(const MSYS_Linked_List_T * pAllocatedList, MSYS_Linked_List_T ** ppNextObject) + * + * Copies the pointer to the next object in the list to the given ppNextObject argument. + * + * Returns COMMON_ERROR_SUCCESS if copying the pointer to the next object was successful. + * Returns COMMON_ERROR_INVALID_ARGUMENT if a given pointer to pointer or pointer to object was NULL. + * Otherwise returns the appropriate error. + */ +MSYS_DLL_EXPORT int MSYS_Linked_List_Get_Next_Object(const MSYS_Linked_List_T * pAllocatedList, MSYS_Linked_List_T ** ppNextObject); + +/*! + * MSYS_DLL_EXPORT int MSYS_Linked_List_Get_Previous_Object(const MSYS_Linked_List_T * pAllocatedList, MSYS_Linked_List_T ** ppPrevObject) + * + * Copies the pointer to the previous object in the list to the given ppPrevObject argument. + * + * Returns COMMON_ERROR_SUCCESS if copying the pointer to the previous object was successful. + * Returns COMMON_ERROR_INVALID_ARGUMENT if a given pointer to pointer or pointer to object was NULL. + * Otherwise returns the appropriate error. + */ +MSYS_DLL_EXPORT int MSYS_Linked_List_Get_Previous_Object(const MSYS_Linked_List_T * pAllocatedList, MSYS_Linked_List_T ** ppPrevObject); + +/*! + * MSYS_DLL_EXPORT int MSYS_Linked_List_Get_Current_Object_Contents(const MSYS_Linked_List_T * pAllocatedList, void ** ppData, size_t * dataLength) + * + * Copies the contents of the given object in the list to the given pointers. + * + * Returns COMMON_ERROR_SUCCESS if copying the contents was successful. + * Returns COMMON_ERROR_INVALID_ARGUMENT if a given pointer to pointer or pointer to data was NULL. + * Otherwise returns the appropriate error. + */ +MSYS_DLL_EXPORT int MSYS_Linked_List_Get_Current_Object_Contents(const MSYS_Linked_List_T * pAllocatedList, void ** ppData, size_t * dataLength); + +/*! + * MSYS_DLL_EXPORT int MSYS_Linked_List_Set_Current_Object_Contents(MSYS_Linked_List_T * pAllocatedList, void * pData, const size_t dataLength) + * + * Copies the given contents to the given object in the list. + * + * Returns COMMON_ERROR_SUCCESS if copying the contents was successful. + * Returns COMMON_ERROR_INVALID_ARGUMENT if a given pointer to object was NULL. + * Otherwise returns the appropriate error. + */ +MSYS_DLL_EXPORT int MSYS_Linked_List_Set_Current_Object_Contents(MSYS_Linked_List_T * pAllocatedList, void * pData, const size_t dataLength); + +/*! + * MSYS_DLL_EXPORT int MSYS_Linked_List_Swap_Objects(MSYS_Linked_List_T * pFirstObject, MSYS_Linked_List_T * pSecondObject) + * + * Swaps the given contents of the two given objects in the list. + * + * Returns COMMON_ERROR_SUCCESS if swapping the contents of the two objects was successful. + * Returns COMMON_ERROR_INVALID_ARGUMENT if a given pointer to object was NULL. + * Otherwise returns the appropriate error. + */ +MSYS_DLL_EXPORT int MSYS_Linked_List_Swap_Objects(MSYS_Linked_List_T * pFirstObject, MSYS_Linked_List_T * pSecondObject); + +/* End extern C if needed. */ +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ + +#endif /* MSYS_BASIC_LINKED_LIST_H */ + +/* End of Basic_Linked_List.h. */ diff --git a/src/Core/Src/CMakeLists.txt b/src/Core/Src/CMakeLists.txt index 800ab92..43d2832 100644 --- a/src/Core/Src/CMakeLists.txt +++ b/src/Core/Src/CMakeLists.txt @@ -6,7 +6,12 @@ set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${O_OUTPUT_DIR}) add_library(Panic_Handler_Multiverse_Engine SHARED Panic.cpp) add_library(Panic_Handler_Multiverse_Engine_Static STATIC Panic.cpp) +add_library(Basic_Linked_List_Multiverse_Engine SHARED Basic_Linked_List.c) +add_library(Basic_Linked_List_Multiverse_Engine_Static STATIC Basic_Linked_List.c) + add_library(Core_Multiverse_Engine SHARED DataProcess.cpp FileStreams.cpp) add_library(Core_Multiverse_Engine_Static STATIC DataProcess.cpp FileStreams.cpp) -target_link_libraries(Core_Multiverse_Engine Panic_Handler_Multiverse_Engine) -target_link_libraries(Core_Multiverse_Engine_Static Panic_Handler_Multiverse_Engine_Static) +target_link_libraries(Core_Multiverse_Engine Panic_Handler_Multiverse_Engine +Basic_Linked_List_Multiverse_Engine) +target_link_libraries(Core_Multiverse_Engine_Static Panic_Handler_Multiverse_Engine_Static +Basic_Linked_List_Multiverse_Engine_Static) From 53f1bfb03222b4b02070bb825b6988f351ccf99d Mon Sep 17 00:00:00 2001 From: codebase7 Date: Mon, 6 Jul 2015 03:20:58 -0400 Subject: [PATCH 042/325] Commit missing FileUtills_Private_API_Windows_Syscall.cpp This commit adds the missing FileUtills_Private_API_Windows_Syscall.cpp file. Note: Currently this is just a stub file based on FileUtills_Private_API_Posix_Syscall.cpp to allow CMake to finish generating it's makefile. It will not build on a Windows system due to not actually implementing the needed functions properly. (Well minus one that was not gutted prior to commit that is actually the Posix function, but that is beside the point.) --- ...FileUtills_Private_API_Windows_Syscall.cpp | 791 ++++++++++++++++++ 1 file changed, 791 insertions(+) create mode 100644 src/Common/Src/File_Management_Subsystem/FileUtills_Private_API_Windows_Syscall.cpp diff --git a/src/Common/Src/File_Management_Subsystem/FileUtills_Private_API_Windows_Syscall.cpp b/src/Common/Src/File_Management_Subsystem/FileUtills_Private_API_Windows_Syscall.cpp new file mode 100644 index 0000000..f8e6e85 --- /dev/null +++ b/src/Common/Src/File_Management_Subsystem/FileUtills_Private_API_Windows_Syscall.cpp @@ -0,0 +1,791 @@ +/*! + Multiverse Engine Project 06/7/2015 FileUtills FileUtills_Private_API_Windows_Syscall.cpp (Based on FileUtills_Private_API_Posix_Syscall.cpp) + + Copyright (C) 2015 Multiverse Engine Project + + This program is free software; + you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this program; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Official source repository and project information can be found at + https://github.com/codebase7/mengine +*/ + +/* Internal includes. */ +#include "FileUtills.h" +#include "FileUtills_Private_API.h" + +int FileUtills::ResolveSystemSymoblicLink_Syscall(char ** path, size_t * pathSize) +{ + // Init vars. + int ret = COMMON_ERROR_UNKNOWN_ERROR; // The result of this function. + + // Make sure we got a valid path. + if ((path != NULL) && ((*path) != NULL) && (pathSize != NULL) && ((*pathSize) > 0)) + { + + } + else + { + // Invalid path. + ret = COMMON_ERROR_INVALID_ARGUMENT; + + // Log the error. + COMMON_LOG_DEBUG("FileUtills_ResolveSystemSymoblicLink(): "); + COMMON_LOG_DEBUG(Common_Get_Error_Message(COMMON_ERROR_INVALID_ARGUMENT)); + COMMON_LOG_DEBUG(" Given path argument is invalid."); + } + + // Return the result. + return ret; +} + +int FileUtills::GetUserProfileDirectoryPath_Syscall(std::string & path) +{ + // Init vars. + int ret = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; // The result of this function. + + + + // Return the result. + return ret; +} + +int FileUtills::GetCurrentWorkingDirectoryPath_Syscall(std::string & path) +{ + // Init vars. + int ret = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; // The result of this function. + + + + // Return the result. + return ret; +} + +int FileUtills::GetExecDirectory_Syscall(char ** retStr, size_t * retStrSize) +{ + // Init vars. + int ret = COMMON_ERROR_UNKNOWN_ERROR; // The result code returned from this function. + char * result = NULL; // The string returned from this function. + size_t resultSize = 0; // The size of the result string. + + // Check for valid arguments. + if ((retStr != NULL) && (retStrSize != NULL)) + { + + // Copy the pointer. + result = PROC_PATH; + resultSize = PROC_PATH_SIZE; + + // Call FileUtills::ResolveSystemSymoblicLink_Syscall(). (Make sure it's the real path not a symlink. (PROC_PATH is a symlink, and a weird one at that.)) + ret = FileUtills::ResolveSystemSymoblicLink_Syscall(&result, &resultSize); + if (ret == COMMON_ERROR_SUCCESS) + { + // The resulting path is actually the exe itself, so we need to call RemoveLastPathSegment(). + ret = FileUtills::RemoveLastPathSegment(&result, &resultSize); + if (ret == COMMON_ERROR_SUCCESS) + { + // Copy the result string to retStr. + (*retStr) = result; + (*retStrSize) = resultSize; + } + else + { + // Could not remove exe from path. + COMMON_LOG_DEBUG("FileUtills_GetExecDirectory_Syscall(): Could not remove exe from it's path, call to FileUtills_RemoveLastPathSegment() failed: "); + COMMON_LOG_DEBUG(Common_Get_Error_Message(ret)); + } + } + else + { + // This is an internal engine error. + ret = COMMON_ERROR_INTERNAL_ERROR; + + // Report it. + COMMON_LOG_WARNING("FileUtills_GetExecDirectory(): "); + COMMON_LOG_WARNING(Common_Get_Error_Message(COMMON_ERROR_INTERNAL_ERROR)); + COMMON_LOG_WARNING(" Getting the executable path failed. (Call to an internal engine function failed.) Please report this bug."); + } +#endif + } + else + { + // Invalid arguments. + ret = COMMON_ERROR_INVALID_ARGUMENT; + COMMON_LOG_DEBUG("FileUtills_GetExecDirectory(): "); + COMMON_LOG_DEBUG(Common_Get_Error_Message(COMMON_ERROR_INVALID_ARGUMENT)); + } + + // Return result. + return ret; +} + +FileUtills::dirlist * FileUtills::getDirectory_Syscall(const std::string & absPath, const bool & cleanList) +{ + // Init vars. + int errcpy = 0; // Used to fetch the error code. + FileUtills::dirlist * ret = NULL; // The FileUtills directory structure. + std::string tempname = ""; // Used to store the filename / subdirectory name for the addToArray function. + + // Dumb check. + if (absPath.size() > 0) + { + + // Allocate the dirlist. + try{ + ret = new FileUtills::dirlist; + if (ret != NULL) + { + // Set the path. + ret->path = absPath; + + // Dump the path as a c string into the Directory stream object......(Overly complicated POS......) + + // Check and make sure we can open the directory first. + if ((dp = (opendir(absPath.c_str()))) == NULL) + { + // Copy the error code, and translate it. + errcpy = errno; + errcpy = Common::Translate_Posix_Errno_To_Common_Error_Code(errcpy); + + // An error occured. + if (ret != NULL) + { + delete ret; + ret = NULL; + } + + // Log the error. + COMMON_LOG_INFO("FileUtills::getDirectory(): Unable to get directory contents for ( "); + COMMON_LOG_INFO(absPath.c_str()); + COMMON_LOG_INFO(" ) The system returned "); + COMMON_LOG_INFO(Common::Get_Error_Message(errcpy)); + COMMON_LOG_INFO("\n"); + + // Copy the translated error code to Common::commonLastErrorCode. + Common::commonLastErrorCode = errcpy; + } + + // Start filesystem fetch loop. + while ((dir = readdir(dp))) // Call Host OS function. + { + // Check and see if the cleanList flag is set. + if (cleanList) + { + // Check to see if d_name is a POSIX directory shortcut. + if ((strcmp(dir->d_name, ".") == 0) || (strcmp(dir->d_name, "..") == 0)) + { + // d_name is a directory shortcut, do not add it to the list. + continue; + } + } + + // Cast d_name to a string. + tempname = dir->d_name; + + // Add the data to the array. + ret->list.push_back(tempname); + } + + // Close the directory stream and reset it. + closedir(dp); + + // Set the number of entries. + ret->numOfEntries = ret->list.size(); + + // Set Common::commonLastErrorCode. + Common::commonLastErrorCode = COMMON_ERROR_SUCCESS; + } + else + { + // Could not allocate memory. + Common::commonLastErrorCode = COMMON_ERROR_MEMORY_ERROR; + } + } + catch(exception &ex) + { + // Free memory if needed. + if (ret != NULL) + { + delete ret; + ret = NULL; + } + + // Could not allocate struct. + Common::commonLastErrorCode = COMMON_ERROR_EXCEPTION_THROWN; + + // Log the error. + COMMON_LOG_DEBUG("FileUtills::getDirectory(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(COMMON_ERROR_EXCEPTION_THROWN)); + COMMON_LOG_DEBUG(" "); + COMMON_LOG_DEBUG(ex.what()); + COMMON_LOG_DEBUG("\n"); + } +#endif + } + else + { + // Invalid path. + Common::commonLastErrorCode = COMMON_ERROR_INVALID_ARGUMENT; + + // Log the error. + COMMON_LOG_DEBUG("FileUtills::getDirectory(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(COMMON_ERROR_INVALID_ARGUMENT)); + COMMON_LOG_DEBUG(" Given path is invalid.\n"); + } + + // Return the result. + return ret; +} + +int FileUtills::GetByteFreespace_Syscall(const std::string & absPath, size_t & result) +{ + // Init vars. + int ret = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; // The result of this function. + + + + // Return the result. + return ret; +} + +int FileUtills::CreateDirectory_Syscall(const char * absPath) +{ + // Init errcpy. + int ret = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; // The result of this function. + + // Check for NULL pointer. + if (absPath != NULL) + { + + } + else + { + // Invalid argument. + ret = COMMON_ERROR_INVALID_ARGUMENT; + + // Log the error. + COMMON_LOG_DEBUG("FileUtills::CreateDirectory(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(ret)); + COMMON_LOG_DEBUG(" Given path is invalid.\n"); + } + + // Return the result. + return ret; +} + +int FileUtills::CheckPermissions_Syscall(const std::string & absPath, const bool & read, const bool & write, const bool & exec) +{ + // Init vars. + int ret = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; // The result of this function. + + // Make sure that absPath is valid. + if (absPath.size() > 0) + { + // Double check and make sure we have something to do. + if ((read != false) || (write != false) || (exec != false)) + { + + } + else + { + // No check to make. + ret = COMMON_ERROR_INVALID_ARGUMENT; + + // Log the error. + COMMON_LOG_DEBUG("FileUtills::CheckPermissions(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(ret)); + COMMON_LOG_DEBUG(" No check to perform, aborting.\n"); + } + } + else + { + // Invalid absPath. + ret = COMMON_ERROR_INVALID_ARGUMENT; + + // Log the error. + COMMON_LOG_DEBUG("FileUtills::CheckPermissions(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(ret)); + COMMON_LOG_DEBUG(" Given path is invalid.\n"); + } + + // Default return. + return ret; +} + +int FileUtills::DoesExist_Syscall(const std::string & absPath) +{ + // Init vars. + int ret = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; // The result of this function. + + // Check for valid arg. + if (absPath.size() > 0) + { + + int errcpy = 0; // Used to copy errno if needed. + + // Check and see if the file exists. + ret = access(absPath.c_str(), F_OK); + if (ret == 0) + { + // Path exists. + ret = FILEUTILLS_ERROR_EXISTANT; + } + else + { + // Copy the error code. + errcpy = errno; + + // Translate the error code. + ret = Common::Translate_Posix_Errno_To_Common_Error_Code(errcpy); + } +#endif // POSIX_COMMON_H + } + else + { + // Invalid absPath. + ret = COMMON_ERROR_INVALID_ARGUMENT; + + // Log the error. + COMMON_LOG_DEBUG("FileUtills::DoesExist(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(ret)); + COMMON_LOG_DEBUG(" Given path is invalid.\n"); + } + + // Return the result. + return ret; +} + +int FileUtills::IsFileOrDirectory_Syscall(const char * absPath, const size_t absPathSize) +{ + // Init vars. + int ret = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; // Result of this function. (Defaults to function not implemented.) + + // Check for invalid absPath. + if ((absPath != NULL) && (absPathSize() > 0)) + { + + struct stat * buf = NULL; // Linux stat structure, used with syscall. + + // Check for invalid absPath. + if ((absPath != NULL) && (absPathSize() > 0)) + { + // Init stat buffer. + buf = new struct stat; + if (buf != NULL) + { + // Ask the OS to stat() the path. + ret = lstat(absPath, buf); + + // Check the result. + if (ret == 0) + { + // Log result. + COMMON_LOG_VERBOSE("FileUtills::IsFileOrDirectory(): The given path ( "); + COMMON_LOG_VERBOSE(absPath); + + // Check the stat structure. + if (S_ISREG((buf->st_mode))) + { + // Path is a regular file. + ret = FILEUTILLS_ERROR_PATH_IS_A_FILE; + + // Log result. + COMMON_LOG_VERBOSE(" ) is a regular file."); + } + else + { + if (S_ISDIR((buf->st_mode))) + { + // Path is a directory. + ret = FILEUTILLS_ERROR_PATH_IS_A_DIRECTORY; + + // Log result. + COMMON_LOG_VERBOSE(" ) is a directory."); + } + else + { + // Check for a symlink. + if (S_ISLNK((buf->st_mode))) + { + // Symlink. + ret = FILEUTILLS_ERROR_PATH_IS_A_SYMLINK; + + // Log result. + COMMON_LOG_VERBOSE(" ) is a symbolic link."); + } + else + { + // Special file. + ret = COMMON_ERROR_SUCCESS; + + // Log result. + COMMON_LOG_VERBOSE(" ) is a special file."); + } + } + } + } + else + { + // Error, translate it and log it. + errcpy = errno; + ret = Common::Translate_Posix_Errno_To_Common_Error_Code(errcpy); + + // Check for non-existance. + if (ret == FILEUTILLS_ERROR_NON_EXISTANT) + { + COMMON_LOG_VERBOSE("FileUtills::IsFileOrDirectory(): The given path ( "); + COMMON_LOG_VERBOSE(absPath); + COMMON_LOG_VERBOSE(" ) or a componet of it does not exist."); + } + else + { + COMMON_LOG_DEBUG("FileUtills::IsFileOrDirectory(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(ret)); + COMMON_LOG_DEBUG(" Was returned while checking path ( "); + COMMON_LOG_DEBUG(absPath); + COMMON_LOG_DEBUG(" )."); + } + } + + // Delete stat buffer. + delete buf; + buf = NULL; + } + else + { + // Coul not allocate stat structure. + ret = COMMON_ERROR_MEMORY_ERROR; + + // Log the error if needed. + COMMON_LOG_DEBUG("FileUtills::IsFileOrDirectory(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(ret)); + } + } + #endif // POSIX_COMMON_H + } + else + { + // Invalid absPath. + ret = COMMON_ERROR_INVALID_ARGUMENT; + + // Log the error. + COMMON_LOG_DEBUG("FileUtills::IsFileOrDirectory(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(ret)); + COMMON_LOG_DEBUG(" Given path is invalid."); + } + + // Return the result. + return ret; +} + +int FileUtills::DeletePath_Syscall(const std::string & absPath) +{ + // Init vars. + int ret = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; // The result of this function. + + // Begin try block. + try { + // Check for invalid absPath. + if (absPath.size() > 0) + { + + // Issue syscall. + if (remove(absPath.c_str()) == 0) + { + // Success. + ret = COMMON_ERROR_SUCCESS; + } + else + { + // Copy errno. + errcpy = errno; + + // Translate the error. + ret = Common::Translate_Posix_Errno_To_Common_Error_Code(errcpy); + } +#endif // POSIX_COMMON_H + } + else + { + // Invalid absPath. + ret = COMMON_ERROR_INVALID_ARGUMENT; + + // Log the error. + COMMON_LOG_DEBUG("FileUtills::DeletePath(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(ret)); + COMMON_LOG_DEBUG(" Given path is invalid.\n"); + } + } + catch (exception &ex) + { + // Exception thrown. + ret = COMMON_ERROR_EXCEPTION_THROWN; + + // Log the error. + COMMON_LOG_VERBOSE("FileUtills::DeletePath(): "); + COMMON_LOG_VERBOSE(Common::Get_Error_Message(ret)); + COMMON_LOG_VERBOSE(" "); + COMMON_LOG_VERBOSE(ex.what()); + COMMON_LOG_VERBOSE("\n"); + } + + // Return the result. + return ret; +} + +int FileUtills::RenamePath_Syscall(const std::string & absPathSrc, const std::string & absPathDest, const bool & dereferenceSymLinks) +{ + // Init vars. + bool srcIsASymLink = false; // Used to tell if the source is a symlink. + bool destIsASymLink = false; // Used to tell if the destionation is a symlink. + int ret = COMMON_ERROR_UNKNOWN_ERROR; // The result of this function. + int errcpy = 0; // Used to copy errno for translation if needed. + char * resultFromRealPath = NULL; // Used to check the result from realpath(). + char * srcLinkedPath = NULL; // Used to hold the dereferenced source path if needed. + char * destLinkedPath = NULL; // Used to hold the dereferenced destionation path if needed. + + // Begin try block. + try { + // Check for valid source path. + if (absPathSrc.capacity() > 0) + { + // Check for valid destionation path. + if (absPathDest.capacity() > 0) + { + // Disable the symlink check if dereferenceSymLinks is set to false. + if (!dereferenceSymLinks) + { + // Check and see if the source is a symlink. + ret = FileUtills::IsFileOrDirectory_Syscall(absPathSrc); + if (ret == FILEUTILLS_ERROR_PATH_IS_A_SYMLINK) + { + // Clear resultFromRealPath. + resultFromRealPath = NULL; + + // Source is a symlink, so we need to dereference it. + srcIsASymLink = true; + resultFromRealPath = realpath(absPathSrc.c_str(), srcLinkedPath); + if (resultFromRealPath == NULL) + { + // We've hit an error. + errcpy = errno; + ret = Common::Translate_Posix_Errno_To_Common_Error_Code(errcpy); + + // Log the error. + COMMON_LOG_DEBUG("FileUtills::RenamePath(): Unable to dereference symlink on the source path ( "); + COMMON_LOG_DEBUG(absPathSrc.c_str()); + COMMON_LOG_DEBUG(").\n"); + + // Deallocate the srcLinkedPath if needed. + if (srcLinkedPath != NULL) + { + free(srcLinkedPath); + srcLinkedPath = NULL; + } + } + } + + // Check and see if the destionation is a symlink. + ret = FileUtills::IsFileOrDirectory_Syscall(absPathDest); + if (ret == FILEUTILLS_ERROR_PATH_IS_A_SYMLINK) + { + // Clear resultFromRealPath. + resultFromRealPath = NULL; + + // Destionation is a symlink, so we need to dereference it. + destIsASymLink = true; + resultFromRealPath = realpath(absPathDest.c_str(), destLinkedPath); + if (resultFromRealPath == NULL) + { + // We've hit an error. + errcpy = errno; + ret = Common::Translate_Posix_Errno_To_Common_Error_Code(errcpy); + + // Log the error. + COMMON_LOG_DEBUG("FileUtills::RenamePath(): Unable to dereference symlink on the destionation path ( "); + COMMON_LOG_DEBUG(absPathDest.c_str()); + COMMON_LOG_DEBUG(").\n"); + + // Deallocate the destLinkedPath if needed. + if (destLinkedPath != NULL) + { + free(destLinkedPath); + destLinkedPath = NULL; + } + } + } + } + + // Check and see what variables must be passed to rename. + if (srcIsASymLink && destIsASymLink) + { + // Check for allocated srcLinkedPath. + if (srcLinkedPath != NULL) + { + // Check for allocated destLinkedPath. + if (destLinkedPath != NULL) + { + // Issue syscall. + errcpy = rename(srcLinkedPath, destLinkedPath); + } + else + { + // Success without result? + ret = COMMON_ERROR_INTERNAL_ERROR; + + // Log the error. + COMMON_LOG_WARNING("FileUtills::RenamePath(): Resolved symlink buffer for the destionation path ( "); + COMMON_LOG_WARNING(absPathDest.c_str()); + COMMON_LOG_WARNING(" ) is invalid, but it should be valid. Please report this bug.\n"); + } + } + else + { + // Success without result? + ret = COMMON_ERROR_INTERNAL_ERROR; + + // Log the error. + COMMON_LOG_WARNING("FileUtills::RenamePath(): Resolved symlink buffer for the source path ( "); + COMMON_LOG_WARNING(absPathSrc.c_str()); + COMMON_LOG_WARNING(" ) is invalid, but it should be valid. Please report this bug.\n"); + } + } + else + { + if (srcIsASymLink && !destIsASymLink) + { + // Check for allocated srcLinkedPath. + if (srcLinkedPath != NULL) + { + // Issue syscall. + errcpy = rename(srcLinkedPath, absPathDest.c_str()); + } + else + { + // Success without result? + ret = COMMON_ERROR_INTERNAL_ERROR; + + // Log the error. + COMMON_LOG_WARNING("FileUtills::RenamePath(): Resolved symlink buffer for the source path ( "); + COMMON_LOG_WARNING(absPathSrc.c_str()); + COMMON_LOG_WARNING(" ) is invalid, but it should be valid. Please report this bug.\n"); + } + } + else + { + if (!srcIsASymLink && destIsASymLink) + { + // Check for allocated destLinkedPath. + if (destLinkedPath != NULL) + { + // Issue syscall. + errcpy = rename(absPathSrc.c_str(), destLinkedPath); + } + else + { + // Success without result? + ret = COMMON_ERROR_INTERNAL_ERROR; + + // Log the error. + COMMON_LOG_WARNING("FileUtills::RenamePath(): Resolved symlink buffer for the destionation path ( "); + COMMON_LOG_WARNING(absPathDest.c_str()); + COMMON_LOG_WARNING(" ) is invalid, but it should be valid. Please report this bug.\n"); + } + } + else + { + // Issue syscall. + errcpy = rename(absPathSrc.c_str(), absPathDest.c_str()); + } + } + } + + // Check to see if we hit an internal error. + if (ret != COMMON_ERROR_INTERNAL_ERROR) + { + // Check the result of the syscall. + if (errcpy == 0) + { + // Success. + ret = COMMON_ERROR_SUCCESS; + } + else + { + // Copy the error code. + errcpy = errno; + + // Check for EXDEV. + if (errcpy = EXDEV) + { + // The result is that the source and destionation are not on the same filesystem. + ret = FILEUTILLS_ERROR_NOT_ON_SAME_FILESYSTEM; + } + else + { + // Translate the error code. + ret = Common::Translate_Posix_Errno_To_Common_Error_Code(errcpy); + } + } + } + } + else + { + // Invalid absPathDest. + ret = COMMON_ERROR_INVALID_ARGUMENT; + + // Log the error. + COMMON_LOG_DEBUG("FileUtills::RenamePath(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(ret)); + COMMON_LOG_DEBUG(" Given destionation path is invalid.\n"); + } + } + else + { + // Invalid absPathSrc. + ret = COMMON_ERROR_INVALID_ARGUMENT; + + // Log the error. + COMMON_LOG_DEBUG("FileUtills::RenamePath(): "); + COMMON_LOG_DEBUG(Common::Get_Error_Message(ret)); + COMMON_LOG_DEBUG(" Given source path is invalid.\n"); + } + + // Deallocate srcLinkedPath and destLinkedPath if needed. + if (srcLinkedPath != NULL) + { + free(srcLinkedPath); + srcLinkedPath = NULL; + } + if (destLinkedPath != NULL) + { + free(destLinkedPath); + destLinkedPath = NULL; + } + } + catch (exception &ex) + { + // Exception thrown. + ret = COMMON_ERROR_EXCEPTION_THROWN; + + // Log the error. + COMMON_LOG_VERBOSE("FileUtills::RenamePath(): "); + COMMON_LOG_VERBOSE(Common::Get_Error_Message(ret)); + COMMON_LOG_VERBOSE(" "); + COMMON_LOG_VERBOSE(ex.what()); + COMMON_LOG_VERBOSE("\n"); + } + + // Copy ret to Common::commonLastErrorCode. + Common::commonLastErrorCode = ret; + + // Return the result. + return ret; +} From e4eb71c16b0fbd7f9aa40ee10ab27e4ec18d0105 Mon Sep 17 00:00:00 2001 From: codebase7 Date: Fri, 7 Aug 2015 00:51:47 -0400 Subject: [PATCH 043/325] Create the MSYS_FILESIZE structure and functions. This commit creates the MSYS_FILESIZE structure and the needed accessor functions. This commit also modifies FileUtills_Get_File_Length_By_Filename() and FileUtills_Get_File_Length() to use these structures. --- .../File_Management_Subsystem/FileUtills.cpp | 388 ++++++++++++------ .../File_Management_Subsystem/FileUtills.h | 108 ++++- .../FileUtills_Private_API.h | 10 + 3 files changed, 368 insertions(+), 138 deletions(-) diff --git a/src/Common/Src/File_Management_Subsystem/FileUtills.cpp b/src/Common/Src/File_Management_Subsystem/FileUtills.cpp index 7ed52b7..a55db1c 100644 --- a/src/Common/Src/File_Management_Subsystem/FileUtills.cpp +++ b/src/Common/Src/File_Management_Subsystem/FileUtills.cpp @@ -177,65 +177,185 @@ int FileUtills_CheckPathType(const char * path, const size_t pathSize, bool * bI return ret; } +int FileUtills_Create_MSYS_FILESIZE_Structure(struct MSYS_FILESIZE ** str) +{ + /* Init vars. */ + int ret = COMMON_ERROR_UNKNOWN_ERROR; /* The result code of this function. */ + struct MSYS_FILESIZE_PRIV * realStr = NULL; /* Temporary pointer for creation of structure. */ + + /* Check for invalid argument. */ + if (str != NULL) + { + /* Allocate memory. */ + realStr = (struct MSYS_FILESIZE_PRIV *)malloc(sizeof(struct MSYS_FILESIZE_PRIV)); + if (realStr != NULL) + { + /* Blank out the structure. */ + memset(realStr, '\0', sizeof(struct MSYS_FILESIZE_PRIV)); + + /* Set the type. */ #ifdef _MSC_VER -int FileUtills_Get_File_Length_By_Filename(const char * filename, const size_t filenameSize, __int64 * fileLength) + realStr->type = WINDOWS_FILESIZE_TYPE; #else -int FileUtills_Get_File_Length_By_Filename(const char * filename, const size_t filenameSize, off_t * fileLength) + realStr->type = POSIX_FILESIZE_TYPE; #endif /* _MSC_VER */ + + /* Copy the pointer. */ + (*str) = (struct MSYS_FILESIZE *)realStr; + + /* Done. */ + ret = COMMON_ERROR_SUCCESS; + } + else + { + /* Could not allocate memory for structure. */ + ret = COMMON_ERROR_MEMORY_ERROR; + } + } + else + { + /* Invalid argument. */ + ret = COMMON_ERROR_INVALID_ARGUMENT; + } + + /* Exit function. */ + return ret; +} + +void FileUtills_Destroy_MSYS_FILESIZE_Structure(struct MSYS_FILESIZE ** str) +{ + /* Check for invalid argument. */ + if ((str != NULL) && ((*str) != NULL)) + { + /* Deallocate the structure. */ + free((*str)); + (*str) = NULL; + } + + /* Exit function. */ + return; +} + +int FileUtills_Get_Length_From_MSYS_FILESIZE_Structure_LLINT(const struct MSYS_FILESIZE * str, long long int * retVal) +{ + /* Init vars. */ + int ret = COMMON_ERROR_UNKNOWN_ERROR; /* The result code of this function. */ + const struct MSYS_FILESIZE_PRIV * realStr = NULL; /* Temporary pointer for dereferencing of structure. */ + + /* Check for invalid argument. */ + if ((str != NULL) && (retVal != NULL)) + { + /* Reinterpret the struct. */ + realStr = (const struct MSYS_FILESIZE_PRIV *)str; + + /* Set retVal. */ + (*retVal) = realStr->length; + + /* Done. */ + ret = COMMON_ERROR_SUCCESS; + } + else + { + /* Invalid argument. */ + ret = COMMON_ERROR_INVALID_ARGUMENT; + } + + /* Exit function. */ + return ret; +} + +int FileUtills_Set_Length_From_MSYS_FILESIZE_Structure_LLINT(struct MSYS_FILESIZE * str, const long long int * val) +{ + /* Init vars. */ + int ret = COMMON_ERROR_UNKNOWN_ERROR; /* The result code of this function. */ + struct MSYS_FILESIZE_PRIV * realStr = NULL; /* Temporary pointer for dereferencing of structure. */ + + /* Check for invalid argument. */ + if ((str != NULL) && (val != NULL)) + { + /* Reinterpret the struct. */ + realStr = (struct MSYS_FILESIZE_PRIV *)str; + + /* Set length. */ + realStr->length = (*val); + + /* Done. */ + ret = COMMON_ERROR_SUCCESS; + } + else + { + /* Invalid argument. */ + ret = COMMON_ERROR_INVALID_ARGUMENT; + } + + /* Exit function. */ + return ret; +} + +int FileUtills_Get_File_Length_By_Filename(const char * filename, const size_t filenameSize, struct MSYS_FILESIZE * fileLength) { /* Init vars. */ int retFromC = 0; /* The result from C calls. */ int ret = COMMON_ERROR_UNKNOWN_ERROR; /* The result of this function. */ FILE * fp = NULL; /* Pointer to the file. */ -#ifdef _MSC_VER - __int64 fileSize = 0; /* Returned size from Get_File_Length(). (VC is special.) */ -#else - off_t fileSize = 0; /* Returned size from Get_File_Length(). */ -#endif /* _MSC_VER */ + struct MSYS_FILESIZE * fileSize = NULL; /* Returned size from Get_File_Length(). */ /* Check for invalid arguments. */ if ((filename != NULL) && (filenameSize > 0) && (fileLength != NULL)) { + /* Allocate memory for the size structure. */ + ret = FileUtills_Create_MSYS_FILESIZE_Structure(&fileSize); + if (ret == COMMON_ERROR_SUCCESS) + { /* Open the file. */ fp = fopen(filename, "rb"); if (fp != NULL) { - /* Call correct function. */ - ret = FileUtills_Get_File_Length(fp, &fileSize); - if (ret == COMMON_ERROR_SUCCESS) + /* Call correct function. */ + ret = FileUtills_Get_File_Length(fp, fileSize); + if (ret == COMMON_ERROR_SUCCESS) + { + /* Close the file. */ + retFromC = fclose(fp); + if (retFromC == 0) { - /* Close the file. */ - retFromC = fclose(fp); - if (retFromC == 0) - { - /* Copy the size. */ - (*fileLength) = fileSize; + /* Copy the size. */ + (*fileLength).length = (*fileSize).length; - /* SUCCESS. */ - ret = COMMON_ERROR_SUCCESS; - } - else - { - /* Could not close the file. */ - ret = COMMON_ERROR_IO_ERROR; - } + /* SUCCESS. */ + ret = COMMON_ERROR_SUCCESS; } else { - /* Close the file. */ - retFromC = fclose(fp); - if (retFromC != 0) - { - /* Could not close the file. */ - ret = COMMON_ERROR_IO_ERROR; - } + /* Could not close the file. */ + ret = COMMON_ERROR_IO_ERROR; } + } + else + { + /* Close the file. */ + retFromC = fclose(fp); + if (retFromC != 0) + { + /* Could not close the file. */ + ret = COMMON_ERROR_IO_ERROR; + } + } } else { - /* Could not open file. */ - ret = COMMON_ERROR_IO_ERROR; + /* Could not open file. */ + ret = COMMON_ERROR_IO_ERROR; } + + /* Deallocate the fileSize structure. */ + Destroy_MSYS_FILESIZE_Structure(&fileSize); + } + else + { + /* Could not allocate memory for the fileSize structure. */ + ret = COMMON_ERROR_MEMORY_ERROR; + } } else { @@ -247,122 +367,142 @@ int FileUtills_Get_File_Length_By_Filename(const char * filename, const size_t f return ret; } -#ifdef _MSC_VER -int FileUtills_Get_File_Length(FILE * fp, __int64 * fileLength) -#else -int FileUtills_Get_File_Length(FILE * fp, off_t * fileLength) -#endif /* _MSC_VER */ +int FileUtills_Get_File_Length(FILE * fp, struct MSYS_FILESIZE * fileLength) { - /* Init vars. */ - int ret = COMMON_ERROR_UNKNOWN_ERROR; /* The result of this function. */ - int retFromC = 0; /* The result of C calls. */ - fpos_t * previousLocation = NULL; /* The location to restore us to at the end of the function. */ -#ifdef _MSC_VER - long long length = 0; /* The size of the file. (Visual C is special.) */ -#else - off_t length = 0; /* The size of the file. */ -#endif /* _MSC_VER */ - - /* Check for invalid arguments. */ - if ((fp != NULL) && (fileLength != NULL)) + /* Init vars. */ + int ret = COMMON_ERROR_UNKNOWN_ERROR; /* The result of this function. */ + int retFromC = 0; /* The result of C calls. */ + int retFromCall = COMMON_ERROR_UNKNOWN_ERROR; /* The result of a call to an engine function. */ + fpos_t * previousLocation = NULL; /* The location to restore us to at the end of the function. */ + long long int retFromGetPos = 0; /* Result from the various calls to ftell*(). */ + + /* Check for invalid arguments. */ + if ((fp != NULL) && (fileLength != NULL)) + { + /* Check for errors. */ + retFromC = ferror(fp); + if (retFromC == 0) { - /* Check for errors. */ - if (ferror(fp) != 0) + /* Allocate memory for fpos_t. */ + previousLocation = (fpos_t *)malloc(sizeof(fpos_t)); + if (previousLocation != NULL) + { + /* NULL out the previousLocation buffer. */ + memset(previousLocation, '\0', sizeof(fpos_t)); + + /* Set previousLocation to a known value. */ + (*previousLocation) = 0; + + /* Get the current position. */ + retFromC = fgetpos(fp, previousLocation); + if (retFromC == 0) { - /* Get the current position. */ - retFromC = fgetpos(fp, previousLocation); - if (retFromC == 0) - { - /* Go back to the beginining of the file. */ - rewind(fp); + /* Go back to the beginining of the file. */ + rewind(fp); - /* Begin loop to find the end of the file. */ - while ((ferror(fp) == 0) && (feof(fp) == 0)) - { - /* Get next char. */ - retFromC = fgetc(fp); - } + /* Begin loop to find the end of the file. */ + while ((ferror(fp) == 0) && (feof(fp) == 0)) + { + /* Get next char. */ + retFromC = fgetc(fp); + } - /* OK, now figure out if we hit the end of the file or if we hit an error. */ - retFromC = ferror(fp); - if (retFromC == 0) /* No error. */ - { - /* Check for eof. */ - retFromC = feof(fp); - if (retFromC != 0) /* Hit EOF. */ - { - /* Get the end of file position. */ + /* OK, now figure out if we hit the end of the file or if we hit an error. */ + retFromC = ferror(fp); + if (retFromC == 0) /* No error. */ + { + /* Check for eof. */ + retFromC = feof(fp); + if (retFromC != 0) /* Hit EOF. */ + { + /* Get the end of file position. */ #ifdef _MSC_VER - length = _ftelli64(fp); /* Visual C is special. */ + retFromGetPos = _ftelli64(fp); /* Visual C is special. */ #else - length = ftello(fp); + retFromGetPos = ftello(fp); #endif /* _MSC_VER */ - if ((length != -1) && (length >= 0)) - { - /* Set success. */ - ret = COMMON_ERROR_SUCCESS; - } - else - { - /* Check and see if the error is EOVERFLOW. */ - if ((ret == -1) && (errno == EOVERFLOW)) - { - /* This is a memory error, as we can't store the result. */ - ret = COMMON_ERROR_MEMORY_ERROR; - } - else - { - /* OK, yet another IO_ERROR. */ - ret = COMMON_ERROR_IO_ERROR; - } - } - } - else - { - /* We hit a file stream error. */ - ret = COMMON_ERROR_IO_ERROR; - } - } - else - { - /* We hit a file stream error. */ - ret = COMMON_ERROR_IO_ERROR; - } - - /* Clear the error status, and reset the file position. */ - clearerr(fp); - retFromC = fsetpos(fp, previousLocation); - if ((retFromC == 0) && (length >= 0) && (ret == COMMON_ERROR_SUCCESS)) + if ((retFromGetPos == -1) || (retFromGetPos < 0)) + { + /* Check and see if the error is EOVERFLOW. */ + if ((retFromGetPos == -1) && (errno == EOVERFLOW)) { - /* Copy the length to the size_t value. */ - (*fileLength) = length; + /* This is a memory error, as we can't store the result. */ + ret = COMMON_ERROR_MEMORY_ERROR; } else { - /* File stream error. */ - ret = COMMON_ERROR_IO_ERROR; + /* OK, yet another IO_ERROR. */ + ret = COMMON_ERROR_IO_ERROR; } + } } else { - /* Could not get current file position. */ - ret = COMMON_ERROR_IO_ERROR; + /* We hit a file stream error. */ + ret = COMMON_ERROR_IO_ERROR; } + } + else + { + /* We hit a file stream error. */ + ret = COMMON_ERROR_IO_ERROR; + } + + /* Clear the error status, and reset the file position. */ + clearerr(fp); + retFromC = fsetpos(fp, previousLocation); + if ((retFromC == 0) && (tempSize->length >= 0)) + { + /* Copy the length to the given MSYS_FILESIZE structure. */ + retFromCall = FileUtills_Set_Length_From_MSYS_FILESIZE_Structure_LLINT(fileLength, retFromGetPos); + if (retFromCall == COMMON_ERROR_SUCCESS) + { + /* Set success. */ + ret = COMMON_ERROR_SUCCESS; + } + else + { + /* Internal engine error. */ + ret = COMMON_ERROR_INTERNAL_ERROR; + COMMON_LOG_DEBUG("FileUtills_Get_File_Length(): Could not copy file length to management structure."); + } + } + else + { + /* File stream error. */ + ret = COMMON_ERROR_IO_ERROR; + } } else { - /* File stream has errored out. */ - ret = COMMON_ERROR_IO_ERROR; + /* Could not get current file position. */ + ret = COMMON_ERROR_IO_ERROR; } + + /* Free previousLocation. */ + free(previousLocation); + previousLocation = NULL; + } + else + { + /* Could not allocate memory for fpos_t buffer. */ + ret = COMMON_ERROR_MEMORY_ERROR; + } } - else + else { - /* Invalid arguments. */ - ret = COMMON_ERROR_INVALID_ARGUMENT; + /* File stream has errored out. */ + ret = COMMON_ERROR_IO_ERROR; } + } + else + { + /* Invalid arguments. */ + ret = COMMON_ERROR_INVALID_ARGUMENT; + } - /* Exit function. */ - return ret; + /* Exit function. */ + return ret; } int FileUtills_Read_Bytes_From_File(FILE * IN, const size_t dataLength, char * dataBuf, const size_t dataBufLength, const size_t destStaringOffset, const bool blankDataBuf) diff --git a/src/Common/Src/File_Management_Subsystem/FileUtills.h b/src/Common/Src/File_Management_Subsystem/FileUtills.h index cff2bc7..3f5b253 100644 --- a/src/Common/Src/File_Management_Subsystem/FileUtills.h +++ b/src/Common/Src/File_Management_Subsystem/FileUtills.h @@ -63,6 +63,22 @@ #endif #endif +/*! + * enum MSYS_FILESIZE_TYPES + * + * Defines the types that an MSYS_FILESIZE object may have. + */ +enum MSYS_FILESIZE_TYPES { + UNKNOWN_FILESIZE_TYPE = 0, + WINDOWS_FILESIZE_TYPE = 1, + POSIX_FILESIZE_TYPE = 2, +}; + +/* File size structure. Contains the length of a file's size. */ +typedef struct MSYS_FILESIZE { +enum MSYS_FILESIZE_TYPES type; /* What type of struct it is. (Windows or POSIX. )*/ +} MSYS_FILESIZE_T; + /* Define the directory list structure. */ typedef struct FileUtills_dirlist { size_t numOfEntries; /* Used to store the number of entries in the list array. */ @@ -72,31 +88,95 @@ typedef struct FileUtills_dirlist { } FileUtills_dirlist_T; /*! - * int FileUtills_Get_File_Length_By_Filename(const char * filename, const size_t filenameSize, size_t * fileLength) + * int FileUtills_Create_MSYS_FILESIZE_Structure(struct MSYS_FILESIZE ** str) + * + * Factory function for MSYS_FILESIZE structures. + * + * WARNING: This function will NOT deallocate a preexisting object pointed to by the given + * pointer argument. The function WILL overwrite the original pointer if it is successful. + * If you need to keep that pointer for later deallocation, copy it elsewhere before calling + * this function. + * + * Returns COMMON_ERROR_SUCCESS if creation of structure was successful. + * Returns COMMON_ERROR_INVALID_ARGUMENT if the given pointer to pointer is NULL. + * Returns COMMON_ERROR_MEMORY_ERROR if a memory allocation fails. + * Otherwise returns the appropriate error code. + * + * In case of error, this function will NOT modify it's argument. + */ +int FileUtills_Create_MSYS_FILESIZE_Structure(struct MSYS_FILESIZE ** str); + +/*! + * void FileUtills_Destroy_MSYS_FILESIZE_Structure(struct MSYS_FILESIZE ** str) + * + * Destructor for MSYS_FILESIZE structures. Takes the given pointer to pointer, derefs it and + * deallocates the pointer to object if it is allocated. + * + * WARNING: This function is a destructor for MSYS_FILESIZE objects ONLY! Giving a different object + * to this function will cause undefined behavior. + * + * If the given pointer is NULL, then this function will silently fail. + * + * This function has no return. + */ +void FileUtills_Destroy_MSYS_FILESIZE_Structure(struct MSYS_FILESIZE ** str); + +/*! + * int FileUtills_Get_Length_From_MSYS_FILESIZE_Structure_LLINT(const struct MSYS_FILESIZE * str, long long int * retVal) + * + * Accessor function. + * + * Returns the length variable from the given MSYS_FILESIZE structure. + * + * Returns COMMON_ERROR_SUCCESS if successful. retVal will hold the result. + * Returns COMMON_ERROR_INVALID_ARGUMENT if the given pointers are NULL. + * Otherwise returns the appropriate error code. + * + * In case of error, this function will NOT modify it's arguments. + */ +int FileUtills_Get_Length_From_MSYS_FILESIZE_Structure_LLINT(const struct MSYS_FILESIZE * str, long long int * retVal); + +/*! + * int FileUtills_Set_Length_From_MSYS_FILESIZE_Structure_LLINT(struct MSYS_FILESIZE * str, const long long int * val) + * + * Accessor function. + * + * Sets the length variable for the given MSYS_FILESIZE structure. + * + * Returns COMMON_ERROR_SUCCESS if successful. + * Returns COMMON_ERROR_INVALID_ARGUMENT if the given pointers are NULL. + * Otherwise returns the appropriate error code. + * + * In case of error, this function will NOT modify it's arguments. + */ +int FileUtills_Set_Length_From_MSYS_FILESIZE_Structure_LLINT(struct MSYS_FILESIZE * str, const long long int * val); + +/* + * int FileUtills_Get_File_Length_By_Filename(const char * filename, const size_t filenameSize, struct MSYS_FILESIZE * fileLength) * * Returns the length of the given file. - * (This is just a wrapper around Get_File_Length().) + * (This is just a wrapper around FileUtills_Get_File_Length().) * - * Returns COMMON_ERROR_SUCCESS if the length is read in successfuly. (fileLength will be set to the named file's length in this case.) - * Otherwise returns the approperate error code. + * Returns COMMON_ERROR_SUCCESS if the length is read in successfully. (fileLength will be set to the named file's length in this case.) + * Otherwise returns the appropriate error code. * * In case of error, (the returned error code is not COMMON_ERROR_SUCCESS), the fileLength argument will NOT be altered. */ -int FileUtills_Get_File_Length_By_Filename(const char * filename, const size_t filenameSize, size_t * fileLength); +int FileUtills_Get_File_Length_By_Filename(const char * filename, const size_t filenameSize, struct MSYS_FILESIZE * fileLength); /*! - * int FileUtills_Get_File_Length(FILE * fp, size_t * fileLength) + * int FileUtills_Get_File_Length(FILE * fp, struct MSYS_FILESIZE * fileLength) * * Gets the length of the given open file. * * This function expects the file stream to be in a good state, (I.e. It's error flag is not set), and that the file - * stream was opened in binary mode. (If the stream is not already open, use Get_File_Length_By_Filename() instead, + * stream was opened in binary mode. (If the stream is not already open, use FileUtills_Get_File_Length_By_Filename() instead, * it will ensure that these requirements are met.) * - * This function calculates the size of the file by starting at the begining and working it's way to the end by calling - * fgetc(), and then checking the state flags (error and eof) after each call to fgetc(). When the eof flag is set, + * This function calculates the size of the file by starting at the beginning and working it's way to the end by calling + * fgetc(), and then checking the state flags (error and eof) after each call to fgetc(). When the EOF flag is set, * (and the error flag is not set), the function will call ftello() to get the offset and check it for error. Finally - * regardless if an error has occured or not, the function will attempt to restore the previous position in the file + * regardless if an error has occurred or not, the function will attempt to restore the previous position in the file * that the file was at when the call to this function was made. * * Returns COMMON_ERROR_SUCCESS if the file length is determined. (fileLength will be set to the determined length in this case.) @@ -105,14 +185,14 @@ int FileUtills_Get_File_Length_By_Filename(const char * filename, const size_t f * * Returns COMMON_ERROR_IO_ERROR if one of the f*() functions fails. * - * Returns COMMON_ERROR_MEMORY_ERROR if the file length was determined, but could not be retrived from the file stream because the + * Returns COMMON_ERROR_MEMORY_ERROR if the file length was determined, but could not be retrieved from the file stream because the * value could not be converted and stored. (Blame the C standard in this case.....) * - * Otherwise returns the approperate error code. + * Otherwise returns the appropriate error code. * - * In case of error, (the returned error code is not SUCCESS), the fileLength argument will NOT be altered. + * In case of error, (the returned error code is not COMMON_ERROR_SUCCESS), the fileLength argument will NOT be altered. */ -int FileUtills_Get_File_Length(FILE * fp, size_t * fileLength); +int FileUtills_Get_File_Length(FILE * fp, struct MSYS_FILESIZE * fileLength); /*! * int FileUtills_Read_Bytes_From_File(FILE * IN, const size_t dataLength, char * dataBuf, const size_t dataBufLength, const size_t destStaringOffset, const bool blankDataBuf) diff --git a/src/Common/Src/File_Management_Subsystem/FileUtills_Private_API.h b/src/Common/Src/File_Management_Subsystem/FileUtills_Private_API.h index 2f2e3e9..568ccdf 100644 --- a/src/Common/Src/File_Management_Subsystem/FileUtills_Private_API.h +++ b/src/Common/Src/File_Management_Subsystem/FileUtills_Private_API.h @@ -25,6 +25,16 @@ // External includes. #include +/* Define the internal MSYS_FILESIZE_PRIV structure. */ +typedef struct MSYS_FILESIZE_PRIV { +enum MSYS_FILESIZE_TYPES type; /* What type of struct it is. (Windows or POSIX. )*/ +#ifdef _MSC_VER + __int64 length; /* Length of the file. */ +#else + off_t length; /* Length of the file. */ +#endif /* _MSC_VER */ +} MSYS_FILESIZE_PRIV_T; + // Namespace definition. namespace FileUtills{ From 50c2934ce15f7f52223ac2cabc5c840b64e278f3 Mon Sep 17 00:00:00 2001 From: codebase7 Date: Fri, 7 Aug 2015 00:58:18 -0400 Subject: [PATCH 044/325] Add FileUtills_Get_Last_Path_Component(). This commit adds the function: FileUtills_Get_Last_Path_Component(). --- .../File_Management_Subsystem/FileUtills.cpp | 84 +++++++++++++++++++ .../File_Management_Subsystem/FileUtills.h | 23 +++++ 2 files changed, 107 insertions(+) diff --git a/src/Common/Src/File_Management_Subsystem/FileUtills.cpp b/src/Common/Src/File_Management_Subsystem/FileUtills.cpp index a55db1c..71d9825 100644 --- a/src/Common/Src/File_Management_Subsystem/FileUtills.cpp +++ b/src/Common/Src/File_Management_Subsystem/FileUtills.cpp @@ -600,6 +600,90 @@ int FileUtills_Write_Data_To_File_From_Memory(FILE * OUT, const char * data, con return ret; } +int FileUtills_Get_Last_Path_Component(const char * path, const size_t pathLength, char ** component, size_t * componentLength) +{ + /* Init vars. */ + int ret = COMMON_ERROR_UNKNOWN_ERROR; /* The result code of this function. */ + char * cleanedPath = NULL; /* Path without a trailing PATH_SEP. */ + char * tempSubStr = NULL; /* Used to create the substr. */ + size_t tempSubStrLength = 0; /* Size of the tempSubString. */ + size_t cleanedPathLength = 0; /* Length of the cleanedPath string. */ + + /* Check for invalid arguments. */ + if ((path != NULL) && (pathLength > 0) && (component != NULL) && (componentLength != NULL)) + { + /* Allocate memory for the cleanedPath string. */ + cleanedPathLength = pathLength; + cleanedPath = (char *)malloc(cleanedPathLength); + if (cleanedPath != NULL) + { + /* NULL out the cleaned path string. */ + memset(cleanedPath, '\0', cleanedPathLength); + + /* Copy the given path to cleanedPath. */ + memcpy(cleanedPath, path, cleanedPathLength); + + /* Call FileUtills_RemoveTrailingSlash(). (Path had to be copied as this function will reallocate the path if it needs to.) */ + ret = FileUtills_RemoveTrailingSlash(&cleanedPath, &cleanedPathLength); + if (ret == COMMON_ERROR_SUCCESS) + { + /* Call DataProcess_Get_SubString_Using_Delimiter(). */ + ret = DataProcess_Get_SubString_Using_Delimiter(cleanedPath, cleanedPathLength, DIR_SEP_STR, + /* (Note: DIR_SEP_STR is NULL terminated, so we are subtracting one from the length of the delimiter.) */ + ((DIR_SEP_STR[(sizeof(DIR_SEP_STR) - 1)] == '\0') ? (sizeof(DIR_SEP_STR) - 1) : (sizeof(DIR_SEP_STR))), + &tempSubStr, &tempSubStrLength, true, false); + if ((ret == COMMON_ERROR_SUCCESS) && (tempSubStr != NULL) && (tempSubStrLength > 0)) + { + /* Copy the pointer and length. */ + (*component) = tempSubStr; + (*componentLength) = tempSubStrLength; + + /* Done. */ + ret = COMMON_ERROR_SUCCESS; + } + else + { + /* Change the error code to internal error if it's not range or end of data. */ + if ((ret != COMMON_ERROR_RANGE_ERROR) && (ret != COMMON_ERROR_END_OF_DATA)) + { + /* Internal error. */ + ret = COMMON_ERROR_INTERNAL_ERROR; + } + + /* Deallocate the tempSubStr if needed. */ + if (tempSubStr != NULL) + { + DataProcess_Deallocate_CString(&tempSubStr); + } + } + } + else + { + /* Call to FileUtills_RemoveTrailingSlash() failed. */ + ret = COMMON_ERROR_INTERNAL_ERROR; + } + + /* Deallocate the cleanedPath string. */ + free(cleanedPath); + cleanedPath = NULL; + cleanedPathLength = 0; + } + else + { + /* Could not allocate memory for cleanedPath. */ + ret = COMMON_ERROR_MEMORY_ERROR; + } + } + else + { + /* Invalid argument(s). */ + ret = COMMON_ERROR_INVALID_ARGUMENT; + } + + /* Exit function. */ + return ret; +} + int FileUtills::GetUserProfileDirectoryPath(std::string & path) { // Init vars. diff --git a/src/Common/Src/File_Management_Subsystem/FileUtills.h b/src/Common/Src/File_Management_Subsystem/FileUtills.h index 3f5b253..300095c 100644 --- a/src/Common/Src/File_Management_Subsystem/FileUtills.h +++ b/src/Common/Src/File_Management_Subsystem/FileUtills.h @@ -254,6 +254,29 @@ int FileUtills_Read_Bytes_From_File(FILE * IN, const size_t dataLength, char * d */ int FileUtills_Write_Data_To_File_From_Memory(FILE * OUT, const char * data, const size_t dataLength); +/*! + * int FileUtills_Get_Last_Path_Component(const char * path, const size_t pathLength, char ** component, size_t * componentLength) + * + * Fetches the last part of the given path and creates a sub-string from it. + * + * (This is a wrapper around DataProcess_Get_SubString_Using_Delimiter(), and as such has similar error codes.) + * + * Returns COMMON_ERROR_SUCCESS if the last path component was found and a sub-string was created. + * Returns COMMON_ERROR_RANGE_ERROR if the path is a relative path without any directory components. + * Returns COMMON_ERROR_END_OF_DATA if the path is a directory with directory separator on the end. + * (This should be stripped off by this function if needed, but may still be returned.) + * Returns COMMON_ERROR_INVALID_ARGUMENT if a given argument is invalid. + * Returns COMMON_ERROR_MEMORY_ERROR if a memory allocation attempt fails. + * Returns COMMON_ERROR_INTERNAL_ERROR if a call to an engine function fails. + * Otherwise returns the appropriate error code. + * + * No alteration clause: + * In case of error, this function will not alter any given argument. + * (For the purposes of this no-alteration clause, the error codes COMMON_ERROR_RANGE_ERROR and COMMON_ERROR_END_OF_DATA + * are considered errors.) + */ +int FileUtills_Get_Last_Path_Component(const char * path, const size_t pathLength, char ** component, size_t * componentLength); + /*! * int FileUtills_GetUserProfileDirectoryPath(char ** retStr, size_t * retStrSize) * From 7335b7016c393c03b6a82a0951b74fe967063dc0 Mon Sep 17 00:00:00 2001 From: codebase7 Date: Fri, 7 Aug 2015 01:02:13 -0400 Subject: [PATCH 045/325] Add function FileUtills_Get_File_Name_Component(). This commit adds the FileUtills_Get_File_Name_Component() function. --- .../File_Management_Subsystem/FileUtills.cpp | 110 ++++++++++++++++++ .../File_Management_Subsystem/FileUtills.h | 27 +++++ 2 files changed, 137 insertions(+) diff --git a/src/Common/Src/File_Management_Subsystem/FileUtills.cpp b/src/Common/Src/File_Management_Subsystem/FileUtills.cpp index 71d9825..9655d89 100644 --- a/src/Common/Src/File_Management_Subsystem/FileUtills.cpp +++ b/src/Common/Src/File_Management_Subsystem/FileUtills.cpp @@ -684,6 +684,116 @@ int FileUtills_Get_Last_Path_Component(const char * path, const size_t pathLengt return ret; } +int FileUtills_Get_File_Name_Component(const char * path, const size_t pathLength, char ** retStr, size_t * retStrLength, const int getExtension) +{ + /* Init vars. */ + int ret = COMMON_ERROR_UNKNOWN_ERROR; /* The result code of this function. */ + char * tempFilename = NULL; /* Used to create the filename. */ + char * tempSubStr = NULL; /* Used to create the substr. */ + size_t tempFilenameLength = 0; /* Size of the tempFilename string. */ + size_t tempSubStrLength = 0; /* Size of the tempSubString. */ + + /* Check for invalid arguments. */ + if ((path != NULL) && (pathLength > 0) && (retStr != NULL) && (retStrLength != NULL)) + { + /* Call DataProcess_Get_SubString_Using_Delimiter() to get the filename. */ + ret = DataProcess_Get_SubString_Using_Delimiter(path, pathLength, DIR_SEP_STR, + /* (Note: DIR_SEP_STR is NULL terminated, so we are subtracting one from the length of the delimiter.) */ + ((DIR_SEP_STR[(sizeof(DIR_SEP_STR) - 1)] == '\0') ? (sizeof(DIR_SEP_STR) - 1) : (sizeof(DIR_SEP_STR))), + &tempFilename, &tempFilenameLength, true, false); + if ((ret == COMMON_ERROR_SUCCESS) && (tempFilename != NULL) && (tempFilenameLength > 0)) + { + /* Call DataProcess_Get_SubString_Using_Delimiter() to get the file name (if getExtension is zero) / extension. (if getExtension is non-zero) */ + ret = DataProcess_Get_SubString_Using_Delimiter(tempFilename, tempFilenameLength, FILEEXT_SEP_STR, + /* (Note: FILEEXT_SEP_STR is NULL terminated, so we are subtracting one from the length of the delimiter.) */ + ((FILEEXT_SEP_STR[(sizeof(FILEEXT_SEP_STR) - 1)] == '\0') ? (sizeof(FILEEXT_SEP_STR) - 1) : (sizeof(FILEEXT_SEP_STR))), + &tempSubStr, &tempSubStrLength, true, (getExtension ? false : true)); + if ((ret == COMMON_ERROR_SUCCESS) && (tempSubStr != NULL) && (tempSubStrLength > 0)) + { + /* Copy the pointer and length. */ + (*retStr) = tempSubStr; + (*retStrLength) = tempSubStrLength; + + /* Done. */ + ret = COMMON_ERROR_SUCCESS; + } + else + { + /* Change the error code to internal error if it's not range or end of data. */ + if ((ret != COMMON_ERROR_RANGE_ERROR) && (ret != COMMON_ERROR_END_OF_DATA)) + { + /* Internal error. */ + ret = COMMON_ERROR_INTERNAL_ERROR; + } + + /* Deallocate the tempSubStr if needed. */ + if (tempSubStr != NULL) + { + DataProcess_Deallocate_CString(&tempSubStr); + } + } + + /* Deallocate the temporary filename string. */ + DataProcess_Deallocate_CString(&tempFilename); + } + else + { + /* Check for a path without a directory component. */ + if (ret == COMMON_ERROR_RANGE_ERROR) + { + /* There is not a directory component in this path, so just check for the file name (if getExtension is zero) / extension. (if getExtension is non-zero) */ + ret = DataProcess_Get_SubString_Using_Delimiter(path, pathLength, FILEEXT_SEP_STR, + /* (Note: FILEEXT_SEP_STR is NULL terminated, so we are subtracting one from the length of the delimiter.) */ + ((FILEEXT_SEP_STR[(sizeof(FILEEXT_SEP_STR) - 1)] == '\0') ? (sizeof(FILEEXT_SEP_STR) - 1) : (sizeof(FILEEXT_SEP_STR))), + &tempSubStr, &tempSubStrLength, true, (getExtension ? false : true)); + if ((ret == COMMON_ERROR_SUCCESS) && (tempSubStr != NULL) && (tempSubStrLength > 0)) + { + /* Copy the pointer and length. */ + (*retStr) = tempSubStr; + (*retStrLength) = tempSubStrLength; + + /* Done. */ + ret = COMMON_ERROR_SUCCESS; + } + else + { + /* Change the error code to internal error if it's not range or end of data. */ + if ((ret != COMMON_ERROR_RANGE_ERROR) && (ret != COMMON_ERROR_END_OF_DATA)) + { + /* Internal error. */ + ret = COMMON_ERROR_INTERNAL_ERROR; + } + + /* Deallocate the tempSubStr if needed. */ + if (tempSubStr != NULL) + { + DataProcess_Deallocate_CString(&tempSubStr); + } + } + } + else + { + /* Change the error code to internal error if it's not a range error. */ + ret = COMMON_ERROR_INTERNAL_ERROR; + } + + /* Deallocate the tempFilename if needed. */ + if (tempFilename != NULL) + { + DataProcess_Deallocate_CString(&tempFilename); + } + } + } + else + { + /* Invalid argument(s). */ + ret = COMMON_ERROR_INVALID_ARGUMENT; + } + + /* Exit function. */ + return ret; +} + int FileUtills::GetUserProfileDirectoryPath(std::string & path) { // Init vars. diff --git a/src/Common/Src/File_Management_Subsystem/FileUtills.h b/src/Common/Src/File_Management_Subsystem/FileUtills.h index 300095c..e438279 100644 --- a/src/Common/Src/File_Management_Subsystem/FileUtills.h +++ b/src/Common/Src/File_Management_Subsystem/FileUtills.h @@ -277,6 +277,33 @@ int FileUtills_Write_Data_To_File_From_Memory(FILE * OUT, const char * data, con */ int FileUtills_Get_Last_Path_Component(const char * path, const size_t pathLength, char ** component, size_t * componentLength); +/*! + * int FileUtills_Get_File_Name_Component(const char * path, const size_t pathLength, char ** retStr, size_t * retStrLength, + * const int getExtension) + * + * Fetches the file name or extension from the given path and creates a sub-string from it. + * + * (This is a wrapper around DataProcess_Get_SubString_Using_Delimiter(), and as such has similar error codes.) + * + * @pram getExtension whether or not to get the file extension. If set to zero the file name will be put into the sub-string, + * otherwise the file extension will be put into the sub-string. + * + * Returns COMMON_ERROR_SUCCESS if the file name / extension was found and a sub-string was created. + * Returns COMMON_ERROR_RANGE_ERROR if the path is a path without an name / extension. + * Returns COMMON_ERROR_END_OF_DATA if the path is a path with an extension separator ('.') (on the end / at the beginning) + * and nothing (before / after) it. + * Returns COMMON_ERROR_INVALID_ARGUMENT if a given argument is invalid. + * Returns COMMON_ERROR_MEMORY_ERROR if a memory allocation attempt fails. + * Returns COMMON_ERROR_INTERNAL_ERROR if a call to an engine function fails. + * Otherwise returns the appropriate error code. + * + * No alteration clause: + * In case of error, this function will not alter any given argument. + * (For the purposes of this no-alteration clause, the error codes COMMON_ERROR_RANGE_ERROR and COMMON_ERROR_END_OF_DATA + * are considered errors.) + */ +int FileUtills_Get_File_Name_Component(const char * path, const size_t pathLength, char ** retStr, size_t * retStrLength, const int getExtension); + /*! * int FileUtills_GetUserProfileDirectoryPath(char ** retStr, size_t * retStrSize) * From 0b6045590aa287f5baa73fac2e1ca6f6e48dff35 Mon Sep 17 00:00:00 2001 From: codebase7 Date: Fri, 7 Aug 2015 01:19:23 -0400 Subject: [PATCH 046/325] Fix missing error messages added in 51fbb9a7b30e253283ca298e861e1915263b72df This commit adds the missing human readable error messages needed for the common error codes added in commit 51fbb9a7b30e253283ca298e861e1915263b72df. --- .../Src/Error_Handler/Common_Error_Handler_Structures.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Common/Src/Error_Handler/Common_Error_Handler_Structures.c b/src/Common/Src/Error_Handler/Common_Error_Handler_Structures.c index c693f92..3dda43f 100644 --- a/src/Common/Src/Error_Handler/Common_Error_Handler_Structures.c +++ b/src/Common/Src/Error_Handler/Common_Error_Handler_Structures.c @@ -98,10 +98,14 @@ const Common_Error_Object Common_commonErrorTable[] = { {FILEUTILLS_ERROR_PATH_FILE_AS_DIRECTORY, "The path has a file in it that is being treated as a directory."}, {FILEUTILLS_ERROR_PATH_IS_A_FILE, "Given path is a file."}, {FILEUTILLS_ERROR_PATH_IS_A_DIRECTORY, "Given path is a directory."}, + {FILEUTILLS_ERROR_PATH_IS_A_SYMLINK, "Given path is a symbolic link."}, + {FILEUTILLS_ERROR_PATH_IS_ABSOLUTE, "Given path is in absolute format (Fully resolved)."}, + {FILEUTILLS_ERROR_PATH_IS_RELATIVE, "Given path is in relative format (Needs resolving)."}, {FILEUTILLS_ERROR_FILESYSTEM_FULL, "Given filesystem is full."}, {FILEUTILLS_ERROR_FILESYSTEM_QUOTA_REACHED, "User's disk usage quota for the given filesystem has been reached."}, {FILEUTILLS_ERROR_EMPTY_DIRECTORY, "The given path is an empty directory."}, {FILEUTILLS_ERROR_NON_EMPTY_DIRECTORY, "The given path is a non-empty directory."}, + {FILEUTILLS_ERROR_SYMLINK_CHAIN_TOO_DEEP, "While parsing a host-defined symbolic link chain, the host system indicated the link chain was longer than what it supports."}, // UI Subsystem/ {UI_SUBSYSTEM_ERROR_EXCEPTION_THROWN, "An exception was thrown in the UI Subsystem."}, // TODO: Need to add the error codes from all common namespace functions. From 0db914ff1951f1719090bf8bd5e3d47fa3c94832 Mon Sep 17 00:00:00 2001 From: codebase7 Date: Fri, 7 Aug 2015 01:21:28 -0400 Subject: [PATCH 047/325] Add error code COMMON_ERROR_END_OF_DATA. This commit creates the common namespace error code COMMON_ERROR_END_OF_DATA. --- src/Common/Src/Error_Handler/Common_Error_Handler_Error_Codes.h | 1 + src/Common/Src/Error_Handler/Common_Error_Handler_Structures.c | 1 + 2 files changed, 2 insertions(+) diff --git a/src/Common/Src/Error_Handler/Common_Error_Handler_Error_Codes.h b/src/Common/Src/Error_Handler/Common_Error_Handler_Error_Codes.h index f2baa3d..8ba7925 100644 --- a/src/Common/Src/Error_Handler/Common_Error_Handler_Error_Codes.h +++ b/src/Common/Src/Error_Handler/Common_Error_Handler_Error_Codes.h @@ -41,6 +41,7 @@ COMMON_ERROR_CANNOT_GET_SYSTEM_TIME = -12, COMMON_ERROR_SUBSYSTEM_OBJECT_NOT_INITED = -13, COMMON_ERROR_SUBSYSTEM_OBJECT_ALREADY_INITED = -14, + COMMON_ERROR_END_OF_DATA = -15, /* Rendering Subsystem error codes. */ RENDERER_ERROR_UNABLE_TO_ALLOC_OI_BUF = -21, /* Overlay image buffer. */ diff --git a/src/Common/Src/Error_Handler/Common_Error_Handler_Structures.c b/src/Common/Src/Error_Handler/Common_Error_Handler_Structures.c index 3dda43f..84838dd 100644 --- a/src/Common/Src/Error_Handler/Common_Error_Handler_Structures.c +++ b/src/Common/Src/Error_Handler/Common_Error_Handler_Structures.c @@ -74,6 +74,7 @@ const Common_Error_Object Common_commonErrorTable[] = { {COMMON_ERROR_CANNOT_GET_SYSTEM_TIME, "Could not get the system's current time."}, {COMMON_ERROR_SUBSYSTEM_OBJECT_NOT_INITED, "Given object has not been inited yet."}, {COMMON_ERROR_SUBSYSTEM_OBJECT_ALREADY_INITED, "Given object has already been inited."}, + {COMMON_ERROR_END_OF_DATA, "There is no remaining data to process."}, // Rendering Subsystem error codes. {RENDERER_ERROR_UNABLE_TO_ALLOC_OI_BUF, "Could not allocate memory for overlay image buffer."}, {RENDERER_ERROR_UNABLE_TO_ALLOC_TD_BUF, "Could not allocate memory for transparency data buffer."}, From e3decf20e1ea5bb8f1e48d565956af9b7b33ee62 Mon Sep 17 00:00:00 2001 From: codebase7 Date: Fri, 7 Aug 2015 01:23:48 -0400 Subject: [PATCH 048/325] MSVC 2013 fix for Common_Error_Handler.h This commit makes Common_Error_Handler.h use the builtin _Bool in MSVC 2013, instead of using our fake version. --- src/Common/Src/Error_Handler/Common_Error_Handler.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Common/Src/Error_Handler/Common_Error_Handler.h b/src/Common/Src/Error_Handler/Common_Error_Handler.h index bf7c7ac..846b7c8 100644 --- a/src/Common/Src/Error_Handler/Common_Error_Handler.h +++ b/src/Common/Src/Error_Handler/Common_Error_Handler.h @@ -28,11 +28,11 @@ // External includes. #include // Defines NULL. #ifndef __cplusplus -#ifdef _MSC_FULL_VER /* VC is special. */ +#if _MSC_FULL_VER && _MSC_FULL_VER < 180031101 /* Visual C versions less than 2013 are special. (They lack support for C99's bool type.) */ #include "..\stdbool.h" /* Defines bool data type. (For C compilers.) */ #else #include -#endif /* _MSC_FULL_VER */ +#endif /* _MSC_FULL_VER && _MSC_FULL_VER < 180031101 */ #endif /* __cplusplus */ // Project includes. From 64bb173cfe716418bfe2ea7919fcee40be3de42d Mon Sep 17 00:00:00 2001 From: codebase7 Date: Fri, 7 Aug 2015 01:26:11 -0400 Subject: [PATCH 049/325] Add some safeguards to our fake stdbool header. This commit adds some more preprocessor checks to the internal fake stdbool.h header in an attempt to prevent accidental inclusion when the header is not needed. --- src/Common/Src/stdbool.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/Common/Src/stdbool.h b/src/Common/Src/stdbool.h index e7b9d91..6fde9c0 100644 --- a/src/Common/Src/stdbool.h +++ b/src/Common/Src/stdbool.h @@ -23,6 +23,15 @@ #ifndef MSYS_STD_BOOL_H #define MSYS_STD_BOOL_H +/* This is only needed for C. */ +#ifndef __cplusplus + +/* Only define this if STD_BOOL is not defined. */ +#ifndef _STDBOOL + +/* Only define this if __bool_true_false_are_defined is not defined. */ +#ifndef __bool_true_false_are_defined + /* Define true and false. */ #define TRUE 0x01 /* Really this could be anything. */ #define FALSE 0x00 /* Litteral NULL byte to conform to ANYTHING NOT NULL IS TRUE. */ @@ -34,6 +43,9 @@ typedef char bool; /* This is a char to conform to the expectation in C++ that s /* Define __bool_true_false_are_defined (ISO) */ #define __bool_true_false_are_defined 1 +#endif /* __bool_true_false_are_defined */ +#endif /* _STDBOOL */ +#endif /* __cplusplus */ #endif /* MSYS_STD_BOOL_H */ From fc64ac239ffb7c484935f142ff57cc7761bc522e Mon Sep 17 00:00:00 2001 From: codebase7 Date: Fri, 7 Aug 2015 01:28:00 -0400 Subject: [PATCH 050/325] Add function Common_Print_Bytes_In_Decimal(). This commit adds the Common_Print_Bytes_In_Decimal() function to Byte_Order. --- src/Common/Src/Byte_Order/Byte_Order.c | 5 +++++ src/Common/Src/Byte_Order/Byte_Order.h | 14 ++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/src/Common/Src/Byte_Order/Byte_Order.c b/src/Common/Src/Byte_Order/Byte_Order.c index 3323cfc..f19379f 100644 --- a/src/Common/Src/Byte_Order/Byte_Order.c +++ b/src/Common/Src/Byte_Order/Byte_Order.c @@ -246,6 +246,11 @@ int Common_Print_Bytes_In_Binary(const char * data, const size_t dataLength, cha return Common_Print_Bytes_To_CString(data, dataLength, retStr, retStrSize, 2, 8, '0', spaceBetweenBytes); } +int Common_Print_Bytes_In_Decimal(const char * data, const size_t dataLength, char ** retStr, size_t * retStrSize, const bool spaceBetweenBytes) +{ + return Common_Print_Bytes_To_CString(data, dataLength, retStr, retStrSize, 10, 8, '0', spaceBetweenBytes); +} + #ifdef __cplusplus } /* extern "C" */ #endif /* __cplusplus */ diff --git a/src/Common/Src/Byte_Order/Byte_Order.h b/src/Common/Src/Byte_Order/Byte_Order.h index e93e9cc..3edaf70 100644 --- a/src/Common/Src/Byte_Order/Byte_Order.h +++ b/src/Common/Src/Byte_Order/Byte_Order.h @@ -149,6 +149,20 @@ MSYS_DLL_EXPORT int Common_Print_Bytes_In_Hex(const char * data, const size_t da */ MSYS_DLL_EXPORT int Common_Print_Bytes_In_Binary(const char * data, const size_t dataLength, char ** retStr, size_t * retStrSize, const bool spaceBetweenBytes); +/*! +* int Common_Print_Bytes_In_Decimal(const char * data, const size_t dataLength, char ** retStr, size_t * retStrSize, +* const bool spaceBetweenBytes) +* +* Wrapper function around Common_Print_Bytes_To_CString() for converting a byte string to a human-readable decimal string. +* Example output: ("10012" if spacing is disabled, "10 0 12" if spacing is enabled.) +* +* Note: This function is to make calls shorter, if you want more control over the output, call Common_Print_Bytes_To_CString() directly. +* +* All arguments and return values are identical to their Common_Print_Bytes_To_CString() counterparts. See Common_Print_Bytes_To_CString() +* for their descriptions. +*/ +MSYS_DLL_EXPORT int Common_Print_Bytes_In_Decimal(const char * data, const size_t dataLength, char ** retStr, size_t * retStrSize, const bool spaceBetweenBytes); + #ifdef __cplusplus } /* extern "C" */ #endif /* __cplusplus */ From 3171cb90860ebeb9681babe2dd5c40dd6a579acc Mon Sep 17 00:00:00 2001 From: codebase7 Date: Fri, 7 Aug 2015 01:31:02 -0400 Subject: [PATCH 051/325] Silence a compiler warning and clean up comments in Common_Print_Bytes_To_CString(). This commit silences a compiler warning about possible loss of data in Common_Print_Bytes_To_CString(). (We expect that loss to happen.) This commit also corrects some spelling mistakes in Common_Print_Bytes_To_CString(). --- src/Common/Src/Byte_Order/Byte_Order.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Common/Src/Byte_Order/Byte_Order.c b/src/Common/Src/Byte_Order/Byte_Order.c index f19379f..b664ab6 100644 --- a/src/Common/Src/Byte_Order/Byte_Order.c +++ b/src/Common/Src/Byte_Order/Byte_Order.c @@ -72,7 +72,7 @@ int Common_Print_Bytes_To_CString(const char * data, const size_t dataLength, ch char outputValue = '\0'; /* The value that we need to write into the output buffer. (Calculated from currentValue.) */ char * outputBuffer = NULL; /* Pointer to the c-string that will be outputted to the standard output. */ char * previousOutputBuffer = NULL; /* Temporary pointer used to copy previously generated data into the current outputBuffer. */ - const char outputValues[17] = "0123456789ABCDEF"; /* C-String used to map a generated value to it's corrosponding character. */ + const char outputValues[17] = "0123456789ABCDEF"; /* C-String used to map a generated value to it's corresponding character. */ size_t outputBufferSize = 1; /* Current size of the outputBuffer. Set to one by default to allow the string to be NULL terminated. */ /* Check for invalid arguments. */ @@ -122,8 +122,8 @@ int Common_Print_Bytes_To_CString(const char * data, const size_t dataLength, ch /* Increment byte value count. */ byteValueCount++; - /* Get the next value by choping off the "ones place", aka devide by the current base. */ - currentByte /= base; + /* Get the next value by chopping off the "ones place", aka divide by the current base. */ + currentByte /= (unsigned char)base; } else { From 39ab3ae2610676fdc00b9475b8938f609faa048b Mon Sep 17 00:00:00 2001 From: codebase7 Date: Fri, 7 Aug 2015 01:45:25 -0400 Subject: [PATCH 052/325] Fix CMakeLists to include Byte_Order in built shared list. This commit fixes the common CMakeLists.txt to include the Byte_Order shared library in the built common shared libraries list: COMMON_BUILT_SHARED_LIBRARY_LIST. --- src/Common/Src/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Common/Src/CMakeLists.txt b/src/Common/Src/CMakeLists.txt index ebb7edb..7ba4e04 100644 --- a/src/Common/Src/CMakeLists.txt +++ b/src/Common/Src/CMakeLists.txt @@ -5,6 +5,7 @@ set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${O_OUTPUT_DIR}) # Create the Byte_Order library. if (BUILD_BYTE_ORDER) add_subdirectory(Byte_Order) + set (COMMON_BUILT_SHARED_LIBRARY_LIST ${COMMON_BUILT_SHARED_LIBRARY_LIST} Common_Byte_Order_Multiverse_Engine) set (COMMON_BUILT_STATIC_LIBRARY_LIST ${COMMON_BUILT_STATIC_LIBRARY_LIST} Common_Byte_Order_Multiverse_Engine_Static) endif (BUILD_BYTE_ORDER) From 85e8dc3185f130f47b7da34195d2db10c637fcbe Mon Sep 17 00:00:00 2001 From: codebase7 Date: Fri, 7 Aug 2015 01:49:08 -0400 Subject: [PATCH 053/325] Add common error codes COMMON_ERROR_COMPARISON_PASSED COMMON_ERROR_COMPARISON_FAILED This commit adds the common namespace error codes: COMMON_ERROR_COMPARISON_PASSED and COMMON_ERROR_COMPARISON_FAILED. --- src/Common/Src/Error_Handler/Common_Error_Handler_Error_Codes.h | 2 ++ src/Common/Src/Error_Handler/Common_Error_Handler_Structures.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/Common/Src/Error_Handler/Common_Error_Handler_Error_Codes.h b/src/Common/Src/Error_Handler/Common_Error_Handler_Error_Codes.h index 8ba7925..9bdc4f4 100644 --- a/src/Common/Src/Error_Handler/Common_Error_Handler_Error_Codes.h +++ b/src/Common/Src/Error_Handler/Common_Error_Handler_Error_Codes.h @@ -42,6 +42,8 @@ COMMON_ERROR_SUBSYSTEM_OBJECT_NOT_INITED = -13, COMMON_ERROR_SUBSYSTEM_OBJECT_ALREADY_INITED = -14, COMMON_ERROR_END_OF_DATA = -15, + COMMON_ERROR_COMPARISON_PASSED = -16, + COMMON_ERROR_COMPARISON_FAILED = -17, /* Rendering Subsystem error codes. */ RENDERER_ERROR_UNABLE_TO_ALLOC_OI_BUF = -21, /* Overlay image buffer. */ diff --git a/src/Common/Src/Error_Handler/Common_Error_Handler_Structures.c b/src/Common/Src/Error_Handler/Common_Error_Handler_Structures.c index 84838dd..9eee49b 100644 --- a/src/Common/Src/Error_Handler/Common_Error_Handler_Structures.c +++ b/src/Common/Src/Error_Handler/Common_Error_Handler_Structures.c @@ -75,6 +75,8 @@ const Common_Error_Object Common_commonErrorTable[] = { {COMMON_ERROR_SUBSYSTEM_OBJECT_NOT_INITED, "Given object has not been inited yet."}, {COMMON_ERROR_SUBSYSTEM_OBJECT_ALREADY_INITED, "Given object has already been inited."}, {COMMON_ERROR_END_OF_DATA, "There is no remaining data to process."}, + {COMMON_ERROR_COMPARISON_PASSED, "A check passed it's requirements."}, + {COMMON_ERROR_COMPARISON_FAILED, "A check failed to pass it's requirements."}, // Rendering Subsystem error codes. {RENDERER_ERROR_UNABLE_TO_ALLOC_OI_BUF, "Could not allocate memory for overlay image buffer."}, {RENDERER_ERROR_UNABLE_TO_ALLOC_TD_BUF, "Could not allocate memory for transparency data buffer."}, From d769a4342410ff89a7ff4997da87bca339206c98 Mon Sep 17 00:00:00 2001 From: codebase7 Date: Fri, 7 Aug 2015 01:52:48 -0400 Subject: [PATCH 054/325] Add function Byte_Order_Bit_Comparison(). This commit adds the Byte_Order_Bit_Comparison() to Byte_Order. --- src/Common/Src/Byte_Order/Byte_Order.c | 77 ++++++++++++++++++++++++++ src/Common/Src/Byte_Order/Byte_Order.h | 43 ++++++++++++++ 2 files changed, 120 insertions(+) diff --git a/src/Common/Src/Byte_Order/Byte_Order.c b/src/Common/Src/Byte_Order/Byte_Order.c index b664ab6..17ac3f2 100644 --- a/src/Common/Src/Byte_Order/Byte_Order.c +++ b/src/Common/Src/Byte_Order/Byte_Order.c @@ -26,6 +26,83 @@ extern "C" { #endif /* __cplusplus */ +int Byte_Order_Bit_Comparison(const char * byte, const char bitMask, const char bitValues) +{ + /* Init vars. */ + int ret = COMMON_ERROR_UNKNOWN_ERROR; /* The result code of this function. */ + + /* 10000000 wanna check the first two bits, how? + + 11000000 <-- Bit mask of bits to actually check. + + 10 <-- What the two bits should be. + + Do two comparisons. (One for the set (1) bits and one for the unset (0) bits. + + bits should be: BINARY AND BITMASK. BITS THAT ARE ACTUALLY SET TO CHECK. + (1000000) & (11000000) = (1000000) + + BITWISE NOT bits should be: Inverted what bits should be. + ~ (1000000) = (01111111) + + Inverted what bits should be: BINARY AND BITMASK. BITS THAT ARE NOT SET TO CHECK. + (01111111) & (11000000) = (0100000) + + BITS TO CHECK. BINARY AND BITS THAT ARE SET TO CHECK. (Comparison one result) + (10000000) & (1000000) = SUCCESS. (1000000) + + Inverted BITS TO CHECK. BINARY AND BITS THAT ARE NOT SET TO CHECK. (Comparison two result) + (01111111) & (0100000) = SUCCESS. (0100000) + + (Comparison one result) BINARY INCLUSIVE OR (Comparison two result) (Result of both comparisons) + (1000000) | (0100000) = (11000000) + + BITMASK BINARY AND (Result of both comparisons) Final result + (11000000) & (11000000) = SUCCESS (11000000) + + */ + + /* Check for invalid arguments. */ + if (byte != NULL) + { + /* Check for all value comparison. */ + /*ret = (bitMask == UCHAR_MAX) ? + /* Simple equality check, we only need to check for an exact match. Otherwise continue comparison on the next line. / + (((*byte) == bitValues) ? COMMON_ERROR_COMPARISON_PASSED : COMMON_ERROR_COMPARISON_FAILED) : \ + /* HARDCODED CHECK: If both bitValues and byte are zero, + and bitMask is non-zero we need to return true. Otherwise continue on the next line. / + ((((*byte) == 0) && (bitValues == 0)) ? ((bitMask != 0) ? COMMON_ERROR_COMPARISON_PASSED : COMMON_ERROR_COMPARISON_FAILED) : \ + /* Because it's not a simple equality check, Do first comparison. (Set (1) bits.) / + ((((*byte) & (bitValues & bitMask)) && ((~(*byte)) & ((~bitValues) & bitMask))) ? + /* Do the second comparison. (Unset (0) bits.) / + COMMON_ERROR_COMPARISON_PASSED : COMMON_ERROR_COMPARISON_FAILED));*/ + if (bitMask == UCHAR_MAX) + { + ret = ((*byte) == bitValues) ? COMMON_ERROR_COMPARISON_PASSED : COMMON_ERROR_COMPARISON_FAILED; + } + else + { + if (((*byte) == 0) && (bitValues == 0)) + { + ret = (bitMask != 0) ? COMMON_ERROR_COMPARISON_PASSED : COMMON_ERROR_COMPARISON_FAILED; + } + else + { + ret = ((((*byte) & (bitValues & bitMask)) | ((~(*byte)) & ((~bitValues) & bitMask))) & bitMask) ? + COMMON_ERROR_COMPARISON_PASSED : COMMON_ERROR_COMPARISON_FAILED; + } + } + } + else + { + /* Invalid arguments. */ + ret = COMMON_ERROR_INVALID_ARGUMENT; + } + + /* Exit function. */ + return ret; +} + int Common_Byte_Swap(char * data, const size_t dataLength) { /* Init ret. */ diff --git a/src/Common/Src/Byte_Order/Byte_Order.h b/src/Common/Src/Byte_Order/Byte_Order.h index 3edaf70..f85bd87 100644 --- a/src/Common/Src/Byte_Order/Byte_Order.h +++ b/src/Common/Src/Byte_Order/Byte_Order.h @@ -52,6 +52,49 @@ extern "C" { #include /* Defines malloc(), free(). */ #include /* Defines memset(), memcpy(). */ +/*! + * int Byte_Order_Bit_Comparison(const char * byte, const char bitMask, const char bitValues) + * + * Compares the given byte's bits to the given bitValues using bitMask to define what bits to compare. + * + * I.e. This function compares bits to see if they are equal, using the bitMask to determine what + * bits to actually compare. + * + * Example: If bitMask is 11000000, then only the first two bits are checked. So to make a truth table: + * + * byte: bitMask: bitValues: Result: + * 11000000 11000000 11000000 TRUE (The checked values in byte and bitValues are identical.) + * 10000000 11000000 10000000 TRUE (The checked first and second bits are identical.) + * 01110010 00110010 10110010 TRUE (The checked 3rd, 4th, and 7th bits are identical.) + * 11000100 11000000 11000000 TRUE (Extra bit in byte is not checked.) + * 11000000 11000000 11000100 TRUE (Extra bit in bitValues is not checked.) + * 01000000 11000000 11000000 FALSE (byte does not match bitValues.) + * 11000000 11000000 10000000 FALSE (bitValues does not match byte.) + * 00000000 00000000 00000000 FALSE (No bits are defined to check.) + * 00000000 00110010 00000000 TRUE (Third, forth, and 7th bits are identical. + * (Hardcoded zero check, for consistancy with other results.)) + * 00000000 11111111 00000000 TRUE (Checking all bits, byte and bitValues are both zero. + * (Hardcoded zero check, for consistancy with other results.)) + * + * A note about checking for zero bits: + * For consistancy with the other results, in the event an all zero byte and bitValues is given + * to this function, a hard coded check is inserted to return COMMON_ERROR_COMPARISON_PASSED if + * the given bitMask is not equal to zero. Otherwise it returns COMMON_ERROR_COMPARISON_FAILED. + * This contradicts what would be expected from a binary AND operation and callers of this + * function should therefore be aware of it and check for this result. + * (Normally, a binary AND operation on an all zero set of operands would give a FALSE result. + * The best antidote I can give to deal with this function's inconsistancy is: + * It checks the given bits to see if they match, if given to a non-programmer, what would they + * think the result should be? + * Answer: (0 == 0) is TRUE, so the function should return TRUE.") + * + * Returns COMMON_ERROR_COMPARISON_PASSED if the checked bits match. + * Returns COMMON_ERROR_COMPARISON_FAILED if the checked bits do NOT match. + * Returns COMMON_ERROR_INVALID_ARGUMENT if the given pointer to char is invalid. + * Otherwise returns the approperite error code. + */ +MSYS_DLL_EXPORT int Byte_Order_Bit_Comparison(const char * byte, const char bitMask, const char bitValues); + /*! * int Common_Byte_Swap(char * data, const size_t dataLength) * From 93a6f478f4ba8ff22d11599269859d086930405b Mon Sep 17 00:00:00 2001 From: codebase7 Date: Fri, 7 Aug 2015 01:59:36 -0400 Subject: [PATCH 055/325] Refactor Common_Print_Bytes_To_CString() This commit is a refactoring of Common_Print_Bytes_To_CString() with the intent of fixing an output bug with a base argument of 2. --- src/Common/Src/Byte_Order/Byte_Order.c | 60 ++++++++++++++++---------- src/Common/Src/Byte_Order/Byte_Order.h | 4 +- 2 files changed, 39 insertions(+), 25 deletions(-) diff --git a/src/Common/Src/Byte_Order/Byte_Order.c b/src/Common/Src/Byte_Order/Byte_Order.c index 17ac3f2..dbcb25a 100644 --- a/src/Common/Src/Byte_Order/Byte_Order.c +++ b/src/Common/Src/Byte_Order/Byte_Order.c @@ -139,27 +139,30 @@ int Common_Byte_Swap(char * data, const size_t dataLength) return ret; } -int Common_Print_Bytes_To_CString(const char * data, const size_t dataLength, char ** retStr, size_t * retStrSize, const size_t base, const size_t width, const char fillValue, const bool spaceBetweenBytes) +int Common_Print_Bytes_To_CString(const char * data, const size_t dataLength, char ** retStr, size_t * retStrSize, const unsigned int base, const size_t width, const char fillValue, const bool spaceBetweenBytes) { +/* Define the size of the output values array. */ +#define MSYSOUTPUTVALUESSIZE 17 + /* Init vars. */ - int ret = COMMON_ERROR_UNKNOWN_ERROR; /* The result of this function. */ - size_t x = 0; /* Counter used in the print and spacing loops. */ - size_t byteValueCount = 0; /* Used to keep track of how many bytes we have outputted for the current byte. */ - unsigned char currentByte = '\0'; /* Temporary value used to store the current byte we are working on. */ - char outputValue = '\0'; /* The value that we need to write into the output buffer. (Calculated from currentValue.) */ - char * outputBuffer = NULL; /* Pointer to the c-string that will be outputted to the standard output. */ - char * previousOutputBuffer = NULL; /* Temporary pointer used to copy previously generated data into the current outputBuffer. */ - const char outputValues[17] = "0123456789ABCDEF"; /* C-String used to map a generated value to it's corresponding character. */ - size_t outputBufferSize = 1; /* Current size of the outputBuffer. Set to one by default to allow the string to be NULL terminated. */ + int ret = COMMON_ERROR_UNKNOWN_ERROR; /* The result of this function. */ + size_t x = 0; /* Counter used in the print and spacing loops. */ + size_t byteValueCount = 0; /* Used to keep track of how many bytes we have outputted for the current byte. */ + unsigned char currentByte = '\0'; /* Temporary value used to store the current byte we are working on. */ + size_t outputValue = 0; /* The value that we need to write into the output buffer. (Calculated from currentValue.) */ + char * outputBuffer = NULL; /* Pointer to the c-string that will be given back to the caller. */ + char * previousOutputBuffer = NULL; /* Temporary pointer used to copy previously generated data into the current outputBuffer. */ + const char outputValues[MSYSOUTPUTVALUESSIZE] = "0123456789ABCDEF"; /* C-String used to map a generated value to it's corresponding character. */ + size_t outputBufferSize = 1; /* Current size of the outputBuffer. Set to one by default to allow the string to be NULL terminated. */ /* Check for invalid arguments. */ if ((data != NULL) && (dataLength > 0) && (retStr != NULL) && (retStrSize != NULL) && (base >= 2) && (base <= 16)) { /* Begin data print loop. */ - for (x = 0; ((x < dataLength) && (ret != COMMON_ERROR_MEMORY_ERROR)); x++) + for (x = 0; ((x < dataLength) && (ret == COMMON_ERROR_UNKNOWN_ERROR)); x++) { /* Copy current value. */ - currentByte = data[((dataLength - 1) - x)]; + currentByte = (data[((dataLength - 1) - x)]); /* Reset byte value count. */ byteValueCount = 0; @@ -182,35 +185,43 @@ int Common_Print_Bytes_To_CString(const char * data, const size_t dataLength, ch /* Check for successful memory allocation. */ if (outputBuffer != NULL) { - /* Blank out the new buffer. */ - memset(outputBuffer, '\0', outputBufferSize); + /* Blank out the new buffer. */ + memset(outputBuffer, '\0', outputBufferSize); - /* Set the first value as the previous data comes after it. */ + /* Set the first value as the previous data comes after it. */ + if ((outputValue >= 0) && (outputValue < MSYSOUTPUTVALUESSIZE)) + { outputBuffer[0] = outputValues[outputValue]; /* If we have any previous data we need to copy it into the new buffer and deallocate the previous one. */ if (previousOutputBuffer != NULL) { - memcpy((outputBuffer + 1), previousOutputBuffer, (outputBufferSize - 1)); - free(previousOutputBuffer); - previousOutputBuffer = NULL; + memcpy((outputBuffer + 1), previousOutputBuffer, (outputBufferSize - 1)); + free(previousOutputBuffer); + previousOutputBuffer = NULL; } /* Increment byte value count. */ byteValueCount++; /* Get the next value by chopping off the "ones place", aka divide by the current base. */ - currentByte /= (unsigned char)base; + currentByte /= base; + } + else + { + /* Invalid byte value. */ + ret = COMMON_ERROR_RANGE_ERROR; + } } else { /* Could not allocate memory for output buffer. */ ret = COMMON_ERROR_MEMORY_ERROR; } - }while ((currentByte) && (ret != COMMON_ERROR_MEMORY_ERROR)); + }while ((currentByte) && (ret == COMMON_ERROR_UNKNOWN_ERROR)); /* Check and see if the generated values used up all of the requested width. */ - if ((ret != COMMON_ERROR_MEMORY_ERROR) && (outputBuffer != NULL) && (byteValueCount < width)) + if ((ret == COMMON_ERROR_UNKNOWN_ERROR) && (outputBuffer != NULL) && (byteValueCount < width)) { /* Copy the current buffer's pointer because we are about to create a new one. */ previousOutputBuffer = outputBuffer; @@ -246,7 +257,7 @@ int Common_Print_Bytes_To_CString(const char * data, const size_t dataLength, ch } /* Insert spacing if needed. */ - if ((spaceBetweenBytes) && (ret != COMMON_ERROR_MEMORY_ERROR) && (outputBuffer != NULL) && ((x + 1) < dataLength)) + if ((spaceBetweenBytes) && (ret == COMMON_ERROR_UNKNOWN_ERROR) && (outputBuffer != NULL) && ((x + 1) < dataLength)) { /* Copy the current buffer's pointer because we are about to create a new one. */ previousOutputBuffer = outputBuffer; @@ -278,7 +289,7 @@ int Common_Print_Bytes_To_CString(const char * data, const size_t dataLength, ch } /* Check for NULL output buffer. */ - if ((ret != COMMON_ERROR_MEMORY_ERROR) && (outputBuffer != NULL) && (outputBufferSize > 0)) + if ((ret == COMMON_ERROR_UNKNOWN_ERROR) && (outputBuffer != NULL) && (outputBufferSize > 0)) { /* Copy the outputBuffer pointer to retStr. */ (*retStr) = outputBuffer; @@ -298,6 +309,9 @@ int Common_Print_Bytes_To_CString(const char * data, const size_t dataLength, ch /* Exit function. */ return ret; + +/* Undefine the size of the output values array. */ +#undef MSYSOUTPUTVALUESSIZE } void Common_Deallocate_Print_Bytes_CString(char ** str) diff --git a/src/Common/Src/Byte_Order/Byte_Order.h b/src/Common/Src/Byte_Order/Byte_Order.h index f85bd87..c2aa6af 100644 --- a/src/Common/Src/Byte_Order/Byte_Order.h +++ b/src/Common/Src/Byte_Order/Byte_Order.h @@ -119,7 +119,7 @@ MSYS_DLL_EXPORT int Byte_Order_Bit_Comparison(const char * byte, const char bitM MSYS_DLL_EXPORT int Common_Byte_Swap(char * data, const size_t dataLength); /*! - * int Common_Print_Bytes_To_CString(const char * data, const size_t dataLength, char ** retStr, size_t * retStrSize, const size_t base, + * int Common_Print_Bytes_To_CString(const char * data, const size_t dataLength, char ** retStr, size_t * retStrSize, const unsigned int base, * const size_t width, const char fillValue, const bool spaceBetweenBytes) * * Converts a given byte string to a printable (NULL-terminated) and human-readable string in the given base. @@ -151,7 +151,7 @@ MSYS_DLL_EXPORT int Common_Byte_Swap(char * data, const size_t dataLength); * * In case of error, (the returned error code is not COMMON_ERROR_SUCCESS, then the given arguments will NOT be altered by this function. */ -MSYS_DLL_EXPORT int Common_Print_Bytes_To_CString(const char * data, const size_t dataLength, char ** retStr, size_t * retStrSize, const size_t base, const size_t width, const char fillValue, const bool spaceBetweenBytes); +MSYS_DLL_EXPORT int Common_Print_Bytes_To_CString(const char * data, const size_t dataLength, char ** retStr, size_t * retStrSize, const unsigned int base, const size_t width, const char fillValue, const bool spaceBetweenBytes); /*! * void Common_Deallocate_Print_Bytes_CString(char ** str) From bc8f43c6e3ce7d5090c9ee106cfb75fa67994384 Mon Sep 17 00:00:00 2001 From: codebase7 Date: Fri, 7 Aug 2015 02:05:34 -0400 Subject: [PATCH 056/325] Add Unit_Tests for Byte_Order. This commit is the initial Unit_Tests code for the Byte_Order code. --- src/Tests/CMakeLists.txt | 5 +- src/Tests/Unit_Test_Byte_Order.cpp | 461 +++++++++++++++++++++++++++++ src/Tests/Unit_Test_Common.h | 2 + src/Tests/Unit_Tests.cpp | 4 + src/Tests/Unit_Tests_Byte_Order.h | 80 +++++ 5 files changed, 550 insertions(+), 2 deletions(-) create mode 100644 src/Tests/Unit_Test_Byte_Order.cpp create mode 100644 src/Tests/Unit_Tests_Byte_Order.h diff --git a/src/Tests/CMakeLists.txt b/src/Tests/CMakeLists.txt index d6ed68f..5e78551 100644 --- a/src/Tests/CMakeLists.txt +++ b/src/Tests/CMakeLists.txt @@ -5,11 +5,12 @@ set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${O_OUTPUT_DIR}) # Define Unit Tests base includes. set (UNIT_TESTS_INCLUDES_BASE Unit_Tests.cpp) -# We may make Core an optional subsystem in the future. +# We may make Core and Byte_Order an optional subsystem in the future. set (UNIT_TESTS_INCLUDES ${UNIT_TESTS_INCLUDES_BASE} Test_Base_Header.cpp Unit_Test_Data_Object.cpp -Unit_Test_Data_Object_Insert_Char.cpp) +Unit_Test_Data_Object_Insert_Char.cpp +Unit_Test_Byte_Order.cpp) # Only build the tests for the subsystems that are enabled. if (BUILD_COMMON_ERROR_HANDLER) diff --git a/src/Tests/Unit_Test_Byte_Order.cpp b/src/Tests/Unit_Test_Byte_Order.cpp new file mode 100644 index 0000000..b9011f8 --- /dev/null +++ b/src/Tests/Unit_Test_Byte_Order.cpp @@ -0,0 +1,461 @@ +/*! + Multiverse Engine Project 11/7/2015 Unit Tests Unit_Test_Byte_Order.cpp + + Copyright (C) 2015 Multiverse Engine Project + + This program is free software; + you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this program; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Official source repository and project information can be found at + https://github.com/codebase7/mengine +*/ + +/* Internal includes. */ +#include "Unit_Tests.h" + +void Print_Random_Bits(const char bits) +{ + /* Init vars. */ + int retFromFunct = COMMON_ERROR_UNKNOWN_ERROR; /* Result code from engine function. */ + char * bitMaskString = NULL; /* The bitmask represented as a human-readable string. */ + size_t bitMaskStringLength = 0; /* The length of the bit mask string. */ + + /* Print the bits. */ + retFromFunct = Common_Print_Bytes_In_Binary(&bits, 1, &bitMaskString, &bitMaskStringLength, 1); + if (retFromFunct == COMMON_ERROR_SUCCESS) + { + /* Print the string. */ + std::cout << bitMaskString << " "; + + /* Deallocate the string. */ + Common_Deallocate_Print_Bytes_CString(&bitMaskString); + } + else + { + std::cout << "< ERROR: Unable to print random bits, Common_Print_Bytes_In_Binary() failed. > "; + } + std::cout.flush(); + + /* Exit function. */ + return; +} + +void Print_Bits_and_BitMask(const char byteToCheck, const char bitMask, const char bitValues) +{ + /* Print the values. */ + std::cout << "DEBUG: BYTE:\t\t"; + Print_Random_Bits(byteToCheck); + std::cout << "\nDEBUG: BITMASK:\t\t"; + Print_Random_Bits(bitMask); + std::cout << "\nDEBUG: BIT_VALUES:\t"; + Print_Random_Bits(bitValues); + std::cout << '\n'; + std::cout.flush(); + + /* Exit function. */ + return; +} + +char Generate_Random_Non_Conforming_Bit_Mask(const char byte1, const char byte2) +{ + /* Init vars. */ + char ret = '\0'; /* The result of this function. */ + + /* Generate a random bit mask to check for. */ + std::cout << "Generating random bit mask. Please Wait.\n"; + std::cout.flush(); + + /* Begin generation loop. */ + do + { + ret = ((char)DataProcess::Trivial_Random_Number_Generator(0, 255)); + } while ((byte1 | byte2) ^ ret); + + /* Exit function. */ + return ret; +} + +char Generate_Random_Bit_Mask(const char bitMask) +{ + /* Init vars. */ + char ret = '\0'; /* The result of this function. */ + + /* Generate a random bit mask to check for. */ + std::cout << "Generating random bit mask. Please Wait.\n"; + std::cout.flush(); + do + { + /* Generate a bit mask. */ + ret = ((char)DataProcess::Trivial_Random_Number_Generator(1, 254)); + } while (ret == bitMask); + + /* Exit function. */ + return ret; +} + +char Generate_Random_Bits(const char notThisValue) +{ + /* Init vars. */ + char ret = '\0'; /* The result of this function. */ + + /* Generate some random bits to check for. */ + std::cout << "Generating random bits. Please Wait.\n"; + std::cout.flush(); + + /* Generate some bits, avoiding the given value if needed. */ + while (ret == notThisValue) + { + ret = ((char)DataProcess::Trivial_Random_Number_Generator(2, 254)); + } + + /* Exit function. */ + return ret; +} + +int Generate_Matching_Bitmask_Random_Data(char * byteToCheck, char * bitMask, char * bitValues) +{ + /* Init vars. */ + int ret = COMMON_ERROR_UNKNOWN_ERROR; /* The result code of this function. */ + + /* Check for invalid arguments. */ + if ((byteToCheck != NULL) && (bitMask != NULL) && (bitValues != NULL)) + { + /* Call bitmask generation function. */ + (*bitMask) = Generate_Random_Bit_Mask(0); + + /* Generate the byteToCheck and bitValues data. (If needed, check memory addresses.) */ + if (byteToCheck != bitMask) + { + (*byteToCheck) = Generate_Random_Bits((*bitMask)); + + /* Bitwise Or the bitMask to the byteToCheck data. */ + (*byteToCheck) |= (*bitMask); + } + if ((bitValues != bitMask) && (bitValues != byteToCheck)) + { + (*bitValues) = Generate_Random_Bits((*byteToCheck)); + + /* Bitwise Or the bitMask to the bitValues data. */ + (*bitValues) |= (*bitMask); + } + + /* Done. */ + ret = COMMON_ERROR_SUCCESS; + } + else + { + /* Invalid arguments. */ + ret = COMMON_ERROR_INVALID_ARGUMENT; + } + + /* Exit function. */ + return ret; +} + +int unit_test_byte_order_Common_Print_Bytes_In_Binary_check() +{ + /* Init vars. */ + int ret = 0; /* The result of this function. */ + + + + /* Exit function. */ + return ret; +} + +int unit_test_byte_order_comparison_check() +{ + /* Init vars. */ + int ret = 0; /* The result of this function. */ + char byteToCheck = '\0'; /* The byte to compare against. */ + char bitMask = '\0'; /* The bits we should compare. */ + char bitValues = '\0'; /* The bits we compare to. */ + char extraBits = '\0'; /* Used to generate extra random bits to test with. */ + + /* Run zero comparison checks. */ + std::cout << "Byte_Order_Bit_Comparison() Test 1: All zero, no bits to check test. (Should result in COMMON_ERROR_COMPARISON_FAILED.): "; + if (Byte_Order_Bit_Comparison(&byteToCheck, bitMask, bitValues) == COMMON_ERROR_COMPARISON_FAILED) + { + /* Test 1 successful. */ + std::cout << "PASS\n"; + std::cout << "Byte_Order_Bit_Comparison() Test 2: All zero, check all bits test. (Should result in COMMON_ERROR_COMPARISON_PASSED.): "; + bitMask = CHAR_MIN; + if (Byte_Order_Bit_Comparison(&byteToCheck, bitMask, bitValues) == COMMON_ERROR_COMPARISON_PASSED) + { + /* Test 2 successful. */ + std::cout << "PASS\n"; + + /* Generate random bit mask. */ + std::cout << "Byte_Order_Bit_Comparison() Test 3: All zero, random bit mask test.\n"; + bitMask = Generate_Random_Bit_Mask(0); + Print_Bits_and_BitMask(byteToCheck, bitMask, bitValues); + std::cout << "(Should result in COMMON_ERROR_COMPARISON_PASSED.): "; + + /* Perform all zero test with random bit mask. */ + if (Byte_Order_Bit_Comparison(&byteToCheck, bitMask, bitValues) == COMMON_ERROR_COMPARISON_PASSED) + { + /* Test 3 successful. */ + std::cout << "PASS\n"; + + std::cout << "Byte_Order_Bit_Comparison() Test 4: Non-zero matching bits, no bits to check test. (Should result in COMMON_ERROR_COMPARISON_FAILED.): "; + /* Begin checks on non-zero bit values. */ + bitMask = 0; + bitValues = 1; + byteToCheck = 1; + if (Byte_Order_Bit_Comparison(&byteToCheck, bitMask, bitValues) == COMMON_ERROR_COMPARISON_FAILED) + { + /* Test 4 successful. */ + std::cout << "PASS\n"; + + std::cout << "Byte_Order_Bit_Comparison() Test 5: Non-zero matching bits, check bits test. (Should result in COMMON_ERROR_COMPARISON_PASSED.): "; + bitMask = 1; + + if (Byte_Order_Bit_Comparison(&byteToCheck, bitMask, bitValues) == COMMON_ERROR_COMPARISON_PASSED) + { + /* Test 5 successful. */ + std::cout << "PASS\n"; + + std::cout << "Byte_Order_Bit_Comparison() Test 6: Non-zero matching bits, extra bits in byte, check bits test.\n"; + Generate_Matching_Bitmask_Random_Data(&byteToCheck, &bitMask, &bitMask); + bitValues = bitMask; /* Only the bits in the bit mask should be set in bitValues. */ + Print_Bits_and_BitMask(byteToCheck, bitMask, bitValues); + std::cout << "(Should result in COMMON_ERROR_COMPARISON_PASSED.): "; + + /* Perform Non-zero matching bits, extra bits in byte, check bits test. */ + if (Byte_Order_Bit_Comparison(&byteToCheck, bitMask, bitValues) == COMMON_ERROR_COMPARISON_PASSED) + { + /* Test 6 successful. */ + std::cout << "PASS\n"; + + std::cout << "Byte_Order_Bit_Comparison() Test 7: Non-zero matching bits, extra bits in bitValues, check bits test.\n"; + Generate_Matching_Bitmask_Random_Data(&bitMask, &bitMask, &bitValues); + byteToCheck = bitMask; /* Only the bits in the bit mask should be set in byteToCheck. */ + Print_Bits_and_BitMask(byteToCheck, bitMask, bitValues); + std::cout << "(Should result in COMMON_ERROR_COMPARISON_PASSED.): "; + + /* Perform Non-zero matching bits, extra bits in bitValues, check bits test. */ + if (Byte_Order_Bit_Comparison(&byteToCheck, bitMask, bitValues) == COMMON_ERROR_COMPARISON_PASSED) + { + /* Test 7 successful. */ + std::cout << "PASS\n"; + + std::cout << "Byte_Order_Bit_Comparison() Test 8: Non-zero matching bits, extra bits in byte and bitValues, check bits test.\n"; + Generate_Matching_Bitmask_Random_Data(&byteToCheck, &bitMask, &bitValues); + Print_Bits_and_BitMask(byteToCheck, bitMask, bitValues); + std::cout << "(Should result in COMMON_ERROR_COMPARISON_PASSED.): "; + + /* Perform Non-zero matching bits, extra bits in byte and bitValues, check bits test. */ + if (Byte_Order_Bit_Comparison(&byteToCheck, bitMask, bitValues) == COMMON_ERROR_COMPARISON_PASSED) + { + /* Test 8 successful. */ + std::cout << "PASS\n"; + + std::cout << "Byte_Order_Bit_Comparison() Test 9: Non-zero matching bits, extra bits in byte and bitValues, random bitmask check bits test.\n"; + extraBits = Generate_Random_Bits(0); + + /* Binary OR the bits together so that the bits we check for will be valid. */ + byteToCheck = 0; + byteToCheck |= extraBits; + extraBits = Generate_Random_Bits(0); + + /* Binary OR the bits together so that the bits we check for will be valid. */ + bitValues = 0; + bitValues |= extraBits; + + /* Generate random bit mask. */ + bitMask = Generate_Random_Bit_Mask(0); + + /* Binary OR the bits together so that the bits we check for will be valid. */ + byteToCheck |= bitMask; + bitValues |= bitMask; + + Print_Bits_and_BitMask(byteToCheck, bitMask, bitValues); + std::cout << "(Should result in COMMON_ERROR_COMPARISON_PASSED.): "; + + /* Perform Non-zero matching bits, extra bits in byte and bitValues, random bitmask check bits test. */ + if (Byte_Order_Bit_Comparison(&byteToCheck, bitMask, bitValues) == COMMON_ERROR_COMPARISON_PASSED) + { + /* Test 9 successful. */ + std::cout << "PASS\n"; + + std::cout << "Byte_Order_Bit_Comparison() Test 10: Non-zero NON-matching bits, extra bits in byte and bitValues, random bitmask check bits test.\n"; + extraBits = Generate_Random_Bits(0); + + /* Binary OR the bits together so that the bits we check for will be valid. */ + byteToCheck = 0; + byteToCheck |= extraBits; + extraBits = Generate_Random_Bits(byteToCheck); + + /* Binary OR the bits together so that the bits we check for will be valid. */ + bitValues = 0; + bitValues |= extraBits; + + /* Generate random bit mask. */ + bitMask = Generate_Random_Non_Conforming_Bit_Mask(byteToCheck, bitValues); + + Print_Bits_and_BitMask(byteToCheck, bitMask, bitValues); + std::cout << "(Should result in COMMON_ERROR_COMPARISON_FAILED.): "; + + /* Perform Non-zero NON-matching bits, extra bits in byte and bitValues, random bitmask check bits test. */ + if (Byte_Order_Bit_Comparison(&byteToCheck, bitMask, bitValues) == COMMON_ERROR_COMPARISON_FAILED) + { + /* Test 10 successful. */ + std::cout << "PASS\n"; + + std::cout << "Byte_Order_Bit_Comparison() Test 11: All bits set, check all bits test. (Should result in COMMON_ERROR_COMPARISON_PASSED.): "; + bitMask = UCHAR_MAX; + byteToCheck = UCHAR_MAX; + bitValues = UCHAR_MAX; + + /* Perform All bits set, check all bits test. */ + if (Byte_Order_Bit_Comparison(&byteToCheck, bitMask, bitValues) == COMMON_ERROR_COMPARISON_PASSED) + { + /* Test 11 successful. */ + std::cout << "PASS\n"; + std::cout << "Byte_Order_Bit_Comparison() Test 12: All bits set, no bits to check test. (Should result in COMMON_ERROR_COMPARISON_FAILED.): "; + bitMask = 0; + + /* Perform All bits set, no bits to check test. */ + if (Byte_Order_Bit_Comparison(&byteToCheck, bitMask, bitValues) == COMMON_ERROR_COMPARISON_FAILED) + { + /* Test 12 successful. */ + std::cout << "PASS\n"; + + std::cout << "Byte_Order_Bit_Comparison() Test 13: All bits set, random bit mask test.\n"; + bitMask = Generate_Random_Bit_Mask(0); + Print_Bits_and_BitMask(byteToCheck, bitMask, bitValues); + std::cout << "(Should result in COMMON_ERROR_COMPARISON_PASSED.): "; + + /* Perform All bits set, random bit mask test. */ + if (Byte_Order_Bit_Comparison(&byteToCheck, bitMask, bitValues) == COMMON_ERROR_COMPARISON_PASSED) + { + /* Test 13 successful. */ + std::cout << "PASS\n"; + + /* End of tests. */ + ret = 0; + } + else + { + /* All bits set, random bit mask test failed. */ + ret = -13; + std::cout << "FAIL\n"; + } + } + else + { + /* All bits set, no bits to check test failed. */ + ret = -12; + std::cout << "FAIL\n"; + } + } + else + { + /* All bits set, check all bits test failed. */ + ret = -11; + std::cout << "FAIL\n"; + } + } + else + { + /* Non-zero NON-matching bits, extra bits in byte and bitValues, random bitmask check bits test failed. */ + ret = -10; + std::cout << "FAIL\n"; + } + } + else + { + /* Non-zero matching bits, extra bits in byte and bitValues, random bitmask check bits test failed. */ + ret = -9; + std::cout << "FAIL\n"; + } + } + else + { + /* Non-zero matching bits, extra bits in byte and bitValues, check bits test failed. */ + ret = -8; + std::cout << "FAIL\n"; + } + } + else + { + /* Non-zero matching bits, extra bits in bitValues, check bits test failed. */ + ret = -7; + std::cout << "FAIL\n"; + } + } + else + { + /* Non-zero matching bits, extra bits in byte, check bits test failed. */ + ret = -6; + std::cout << "FAIL\n"; + } + } + else + { + /* Non-zero matching bits, check bits test failed. */ + ret = -5; + std::cout << "FAIL\n"; + } + } + else + { + /* Non-zero matching bits, no bits to check test failed. */ + ret = -4; + std::cout << "FAIL\n"; + } + } + else + { + /* All zero, random bit mask test failed. */ + ret = -3; + std::cout << "FAIL\n"; + } + } + else + { + /* All zero, check all bits test failed. */ + ret = -2; + std::cout << "FAIL\n"; + } + } + else + { + /* All zero no bits to check test failed. */ + ret = -1; + std::cout << "FAIL\n"; + } + + /* Flush output buffer. */ + std::cout.flush(); + + /* Exit function. */ + return ret; +} + +int Unit_Test_Byte_Order_Main() +{ + /* Init vars. */ + int ret = 0; /* The result of this function. */ + int result_comparision_check = 0; /* The result of the comparison checks. */ + + /* Output START OF TEST SECTION. */ + std::cout << START_TEST_SECTION; + + /* Run comparison checks. */ + result_comparision_check = unit_test_byte_order_comparison_check(); + + /* Output END OF TEST SECTION. */ + std::cout << END_TEST_SECTION; + + /* Exit function. */ + return ret; +} diff --git a/src/Tests/Unit_Test_Common.h b/src/Tests/Unit_Test_Common.h index d72fb95..20c1a9d 100644 --- a/src/Tests/Unit_Test_Common.h +++ b/src/Tests/Unit_Test_Common.h @@ -23,6 +23,8 @@ #define COMMON_UNIT_TESTS_H /* Include headers from Common. (If needed.) */ +#include "Unit_Tests_Byte_Order.h" + #ifdef MSYS_HAVE_FILEUTILLS #include "Unit_Tests_FileUtills.h" #endif /* MSYS_HAVE_FILEUTILLS */ diff --git a/src/Tests/Unit_Tests.cpp b/src/Tests/Unit_Tests.cpp index 56f4df9..e7b52e4 100644 --- a/src/Tests/Unit_Tests.cpp +++ b/src/Tests/Unit_Tests.cpp @@ -27,12 +27,16 @@ int main() short error_code_data_object = 0; short error_code_fileutills = 0; short error_code_thread_utils = 0; + int error_code_byte_order = 0; // Starting Unit tests. std::cout << "Multiverse_Engine_Project_Public Unit Tests Compiled on: " << TESTCOMPILEDATE << " " << TESTCOMPILETIME << "\n"; std::cout << "Starting Unit tests for DataProcess::Data_Object. Please be pacent this can take some time.\n"; error_code_data_object = Unit_Test_Data_Object(); + std::cout << "Starting unit tests for Byte_Order. Please wait.\n"; + error_code_byte_order = Unit_Test_Byte_Order_Main(); + /* Only call FileUtills tests if FileUtills was built. */ #ifdef MSYS_HAVE_FILEUTILLS std::cout << "Starting FileUtills Tests.\n"; diff --git a/src/Tests/Unit_Tests_Byte_Order.h b/src/Tests/Unit_Tests_Byte_Order.h new file mode 100644 index 0000000..6f57575 --- /dev/null +++ b/src/Tests/Unit_Tests_Byte_Order.h @@ -0,0 +1,80 @@ +/*! + Multiverse Engine Project 11/7/2015 Unit Tests Unit_Tests_Byte_Order.h + + Copyright (C) 2015 Multiverse Engine Project + + This program is free software; + you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this program; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Official source repository and project information can be found at + https://github.com/codebase7/mengine +*/ + +/* Include guard. */ +#ifndef UNIT_TESTS_BYTE_ORDER_H +#define UNIT_TESTS_BYTE_ORDER_H + +/* Internal includes. */ +#include "../Common/Src/Byte_Order/Byte_Order.h" + +/* Define test functions. */ +/*! + * void Print_Random_Bits(const char bits) + * + * Wrapper around Common_Print_Bytes_In_Binary() and + * Common_Deallocate_Print_Bytes_CString() to print + * the given byte to the standard output. + * + * This function has no return. + */ +void Print_Random_Bits(const char bits); + +/*! + * char Generate_Random_Bit_Mask(const char bitMask) + * + * Generates some random bits between 1 and 254, retrying if it + * generates the given bitMask, while telling the user + * it is doing so. + * + * Returns the generated bit mask. + */ +char Generate_Random_Bit_Mask(const char bitMask); + +/*! + * char Generate_Random_Bits(const char notThisValue) + * + * Generates some random bits between 2 and 254, retrying if it + * generates the given notThisValue, while telling the user + * it is doing so. + * + * Returns the generated bits. + */ +char Generate_Random_Bits(const char notThisValue); + +int unit_test_byte_order_Common_Print_Bytes_In_Binary_check(); + +/*! + * int unit_test_byte_order_comparison_check() + * + * Performs tests on the Byte_Order_Bit_Comparison() function. + */ +int unit_test_byte_order_comparison_check(); + +/*! + * int Unit_Test_Byte_Order_Main() + * + * Main test function for Byte_Order. + */ +int Unit_Test_Byte_Order_Main(); + +#endif /* UNIT_TESTS_BYTE_ORDER_H */ + +/* End of Unit_Tests_Byte_Order.h */ From c7b9ebd95ce9f169fd2cc13395a185ddb6a8a930 Mon Sep 17 00:00:00 2001 From: codebase7 Date: Fri, 7 Aug 2015 02:13:13 -0400 Subject: [PATCH 057/325] Move DataProcess_Endianness_Check into it's own headers. This commit adds DataProcess_Endianness_Check into the error_handler branch, while also moving it into it's own files. --- src/Core/Src/CMakeLists.txt | 8 +- src/Core/Src/DataProcess.h | 3 + src/Core/Src/DataProcess_Endianness_Check.cpp | 126 ++++++++++++++++++ src/Core/Src/DataProcess_Endianness_Check.h | 68 ++++++++++ 4 files changed, 203 insertions(+), 2 deletions(-) create mode 100644 src/Core/Src/DataProcess_Endianness_Check.cpp create mode 100644 src/Core/Src/DataProcess_Endianness_Check.h diff --git a/src/Core/Src/CMakeLists.txt b/src/Core/Src/CMakeLists.txt index 800ab92..a77611e 100644 --- a/src/Core/Src/CMakeLists.txt +++ b/src/Core/Src/CMakeLists.txt @@ -6,7 +6,11 @@ set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${O_OUTPUT_DIR}) add_library(Panic_Handler_Multiverse_Engine SHARED Panic.cpp) add_library(Panic_Handler_Multiverse_Engine_Static STATIC Panic.cpp) -add_library(Core_Multiverse_Engine SHARED DataProcess.cpp FileStreams.cpp) -add_library(Core_Multiverse_Engine_Static STATIC DataProcess.cpp FileStreams.cpp) +add_library(Core_Multiverse_Engine SHARED DataProcess.cpp +DataProcess_Endianness_Check.cpp +FileStreams.cpp) +add_library(Core_Multiverse_Engine_Static STATIC DataProcess.cpp +DataProcess_Endianness_Check.cpp +FileStreams.cpp) target_link_libraries(Core_Multiverse_Engine Panic_Handler_Multiverse_Engine) target_link_libraries(Core_Multiverse_Engine_Static Panic_Handler_Multiverse_Engine_Static) diff --git a/src/Core/Src/DataProcess.h b/src/Core/Src/DataProcess.h index a7d7fe5..29e5215 100644 --- a/src/Core/Src/DataProcess.h +++ b/src/Core/Src/DataProcess.h @@ -18,11 +18,14 @@ https://github.com/codebase7/mengine */ +/* Include guard. */ #ifndef DATAPROCESS_H #define DATAPROCESS_H +/* Internal includes. */ #include "BaseHeader.h" #include "Panic.h" +#include "DataProcess_Endianness_Check.h" namespace DataProcess{ diff --git a/src/Core/Src/DataProcess_Endianness_Check.cpp b/src/Core/Src/DataProcess_Endianness_Check.cpp new file mode 100644 index 0000000..f30da8f --- /dev/null +++ b/src/Core/Src/DataProcess_Endianness_Check.cpp @@ -0,0 +1,126 @@ +/*! + Multiverse Engine Project 11/7/2015 DataProcess DataProcess_Endianness_Check.cpp + + Copyright (C) 2015 Multiverse Engine Project + + This program is free software; + you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this program; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Official source repository and project information can be found at + https://github.com/codebase7/mengine +*/ + +/* Include internal header. */ +#include "DataProcess_Endianness_Check.h" + +template +int DataProcess_Endianness_Check(const T & a) +{ + /* Init vars. */ + int ret = MSYS_UNKNOWN_ENDIANNESS; /* The result of this function. */ + T t = 1; /* Variable to check. */ + + /* Cast t to a char string and see if the result is 1. */ + if (((char*)&t)[0]) + { + /* The first byte is 1 so it's little endian. */ + ret = MSYS_LITTLE_ENDIAN; + } + else + { + /* + * The first byte is 0 so, check and see if the last byte is non-zero. + * If it is, then the host is big endian. + * + * Otherwise the host is using something like middle-endian to store + * the value, but we would need more checks to determine what exact + * kind of endianness the host is using. + */ + if (((char*)&t)[((sizeof(t)) - 1)]) + { + /* It's big endian. */ + ret = MSYS_BIG_ENDIAN; + } + } + + /* Return the result. */ + return ret; +} + +template<> +int DataProcess_Endianness_Check(const float & a) +{ + /* Init vars. */ + int ret = MSYS_UNKNOWN_ENDIANNESS; /* The result of this function. */ + float t = 1.0; /* Variable to check. */ + + /* Cast t to a char string and see if the first 2 values are 0x3F80. */ + if ((((char*)&t)[0] == 0x3F) && ((((char*)&t)[1] == 0x80))) + { + /* The first 2 bytes are 0x3F80 so it's big endian. */ + ret = MSYS_BIG_ENDIAN; + } + else + { + /* + * The first check did not pass, so check and see if the last 2 bytes are 0x803F. + * If they are, then the host is little endian. + * + * Otherwise the host is using something like middle-endian to store + * the value, but we would need more checks to determine what exact + * kind of endianness the host is using. + */ + if ((((char*)&t)[(sizeof (float) - 1)] == 0x80) && ((((char*)&t)[(sizeof (float) - 2)] == 0x3F))) + { + /* It's little endian. */ + ret = MSYS_LITTLE_ENDIAN; + } + } + + /* Return the result. */ + return ret; +} + +template<> +int DataProcess_Endianness_Check(const double & a) +{ + /* Init vars. */ + int ret = MSYS_UNKNOWN_ENDIANNESS; /* The result of this function. */ + double t = 1.0; /* Variable to check. */ + + /* Cast t to a char string and see if the first 2 values are 0x3FF0. */ + if ((((char*)&t)[0] == 0x3F) && ((((char*)&t)[1] == 0xF0))) + { + /* The first 2 bytes are 0x3F80 so it's big endian. */ + ret = MSYS_BIG_ENDIAN; + } + else + { + /* + * The first check did not pass, so check and see if the last 2 bytes are 0xF03F. + * If they are, then the host is little endian. + * + * Otherwise the host is using something like middle-endian to store + * the value, but we would need more checks to determine what exact + * kind of endianness the host is using. + */ + if ((((char*)&t)[(sizeof (double) - 1)] == 0xF0) && ((((char*)&t)[(sizeof (double) - 2)] == 0x3F))) + { + /* It's little endian. */ + ret = MSYS_LITTLE_ENDIAN; + } + } + + /* Return the result. */ + return ret; +} + +/* End of DataProcess_Endianness_Check.cpp */ diff --git a/src/Core/Src/DataProcess_Endianness_Check.h b/src/Core/Src/DataProcess_Endianness_Check.h new file mode 100644 index 0000000..148e5c5 --- /dev/null +++ b/src/Core/Src/DataProcess_Endianness_Check.h @@ -0,0 +1,68 @@ +/*! + Multiverse Engine Project 11/7/2015 DataProcess DataProcess_Endianness_Check.h + + Copyright (C) 2015 Multiverse Engine Project + + This program is free software; + you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this program; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Official source repository and project information can be found at + https://github.com/codebase7/mengine +*/ + +/* Include guard. */ +#ifndef DATAPROCESS_ENDIANNESS_CHECK_H +#define DATAPROCESS_ENDIANNESS_CHECK_H + +/* Define Endianness Result Values. */ +#define MSYS_BIG_ENDIAN 0 +#define MSYS_LITTLE_ENDIAN 1 +#define MSYS_UNKNOWN_ENDIANNESS 2 + +/* Define namespace. */ +namespace DataProcess { + +/*! + * template + * int DataProcess_Endianness_Check(T & a) + * + * Template function which checks the host's endianness for the + * given argument's data type. + * + * Note: The given argument is not altered or used by the function. + * It's only used to exploit the C++ template generator. + * + * The specializations for float and double are required as floating + * point data types must be detected differently from integers. + * + * Returns MSYS_BIG_ENDIAN if the given data type is stored as big + * endian on the host machine. + * + * Returns MSYS_LITTLE_ENDIAN if the given data type stored as little + * endian on the host machine. + * + * Returns MSYS_UNKNOWN_ENDIANNESS if the given data type's byte ordering + * is unknown for the given host. + */ +template +int DataProcess_Endianness_Check(const T & a); + +template<> +int DataProcess_Endianness_Check(const float & a); + +template<> +int DataProcess_Endianness_Check(const double & a); + +} /* namespace DataProcess */ + +#endif /* DATAPROCESS_ENDIANNESS_CHECK_H */ + +/* End of DataProcess_Endianness_Check.h */ From 0526964830fd55244e3b73ec919c27bc1b78eded Mon Sep 17 00:00:00 2001 From: codebase7 Date: Fri, 7 Aug 2015 02:22:41 -0400 Subject: [PATCH 058/325] Remove DataProcess_Endianness_Check code from DataProcess. This code removes the DataProcess_Endianness_Check code from the DataProcess.h header file. (It was moved to it's own files in the error_handler branch.) --- src/Core/Src/DataProcess.h | 132 +------------------------------------ 1 file changed, 3 insertions(+), 129 deletions(-) diff --git a/src/Core/Src/DataProcess.h b/src/Core/Src/DataProcess.h index edee90c..29e5215 100644 --- a/src/Core/Src/DataProcess.h +++ b/src/Core/Src/DataProcess.h @@ -18,143 +18,17 @@ https://github.com/codebase7/mengine */ +/* Include guard. */ #ifndef DATAPROCESS_H #define DATAPROCESS_H +/* Internal includes. */ #include "BaseHeader.h" #include "Panic.h" +#include "DataProcess_Endianness_Check.h" namespace DataProcess{ -/* Define Endianness Result Values. */ -#define MSYS_BIG_ENDIAN 0 -#define MSYS_LITTLE_ENDIAN 1 -#define MSYS_UNKNOWN_ENDIANNESS 2 - -/*! - * template - * int DataProcess_Endianness_Check(T & a) - * - * Template function which checks the host's endianness for the - * given argument's data type. - * - * Note: The given argument is not altered or used by the function. - * It's only used to exploit the C++ template generator. - * - * The specializations for float and double are required as floating - * point data types must be detected differently from integers. - * - * Returns MSYS_BIG_ENDIAN if the given data type is stored as big - * endian on the host machine. - * - * Returns MSYS_LITTLE_ENDIAN if the given data type stored as little - * endian on the host machine. - * - * Returns MSYS_UNKNOWN_ENDIANNESS if the given data type's byte ordering - * is unknown for the given host. - */ -template -int DataProcess_Endianness_Check(const T & a) -{ - /* Init vars. */ - int ret = MSYS_UNKNOWN_ENDIANNESS; /* The result of this function. */ - T t = 1; /* Variable to check. */ - - /* Cast t to a char string and see if the result is 1. */ - if (((char*)&t)[0]) - { - /* The first byte is 1 so it's little endian. */ - ret = MSYS_LITTLE_ENDIAN; - } - else - { - /* - * The first byte is 0 so, check and see if the last byte is non-zero. - * If it is, then the host is big endian. - * - * Otherwise the host is using something like middle-endian to store - * the value, but we would need more checks to determine what exact - * kind of endianness the host is using. - */ - if (((char*)&t)[((sizeof(t)) - 1)]) - { - /* It's big endian. */ - ret = MSYS_BIG_ENDIAN; - } - } - - /* Return the result. */ - return ret; -} - -template<> -int DataProcess_Endianness_Check(const float & a) -{ - /* Init vars. */ - int ret = MSYS_UNKNOWN_ENDIANNESS; /* The result of this function. */ - float t = 1.0; /* Variable to check. */ - - /* Cast t to a char string and see if the first 2 values are 0x3F80. */ - if ((((char*)&t)[0] == 0x3F) && ((((char*)&t)[1] == 0x80))) - { - /* The first 2 bytes are 0x3F80 so it's big endian. */ - ret = MSYS_BIG_ENDIAN; - } - else - { - /* - * The first check did not pass, so check and see if the last 2 bytes are 0x803F. - * If they are, then the host is little endian. - * - * Otherwise the host is using something like middle-endian to store - * the value, but we would need more checks to determine what exact - * kind of endianness the host is using. - */ - if ((((char*)&t)[(sizeof (float) - 1)] == 0x80) && ((((char*)&t)[(sizeof (float) - 2)] == 0x3F))) - { - /* It's little endian. */ - ret = MSYS_LITTLE_ENDIAN; - } - } - - /* Return the result. */ - return ret; -} - -template<> -int DataProcess_Endianness_Check(const double & a) -{ - /* Init vars. */ - int ret = MSYS_UNKNOWN_ENDIANNESS; /* The result of this function. */ - double t = 1.0; /* Variable to check. */ - - /* Cast t to a char string and see if the first 2 values are 0x3FF0. */ - if ((((char*)&t)[0] == 0x3F) && ((((char*)&t)[1] == 0xF0))) - { - /* The first 2 bytes are 0x3F80 so it's big endian. */ - ret = MSYS_BIG_ENDIAN; - } - else - { - /* - * The first check did not pass, so check and see if the last 2 bytes are 0xF03F. - * If they are, then the host is little endian. - * - * Otherwise the host is using something like middle-endian to store - * the value, but we would need more checks to determine what exact - * kind of endianness the host is using. - */ - if ((((char*)&t)[(sizeof (double) - 1)] == 0xF0) && ((((char*)&t)[(sizeof (double) - 2)] == 0x3F))) - { - /* It's little endian. */ - ret = MSYS_LITTLE_ENDIAN; - } - } - - /* Return the result. */ - return ret; -} - class Data_Object{ private: char * data; // Pointer to data. From 084eb11d0b5b80ad52fd2885f1b67cb1b716f9d0 Mon Sep 17 00:00:00 2001 From: codebase7 Date: Fri, 7 Aug 2015 02:50:25 -0400 Subject: [PATCH 059/325] More useless comment fixing and blank line removal This commit is code clean up for FileUtills_Private_API_Windows_Syscall.cpp (A template file.) Because we need to fix a merge. --- ...FileUtills_Private_API_Windows_Syscall.cpp | 68 ++++++++++++------- 1 file changed, 42 insertions(+), 26 deletions(-) diff --git a/src/Common/Src/File_Management_Subsystem/FileUtills_Private_API_Windows_Syscall.cpp b/src/Common/Src/File_Management_Subsystem/FileUtills_Private_API_Windows_Syscall.cpp index f8e6e85..49be101 100644 --- a/src/Common/Src/File_Management_Subsystem/FileUtills_Private_API_Windows_Syscall.cpp +++ b/src/Common/Src/File_Management_Subsystem/FileUtills_Private_API_Windows_Syscall.cpp @@ -21,51 +21,61 @@ /* Internal includes. */ #include "FileUtills.h" #include "FileUtills_Private_API.h" +#include "FileUtills_Private_API_Windows_Syscall.h" int FileUtills::ResolveSystemSymoblicLink_Syscall(char ** path, size_t * pathSize) { - // Init vars. - int ret = COMMON_ERROR_UNKNOWN_ERROR; // The result of this function. + /* Init vars. */ + int ret = COMMON_ERROR_UNKNOWN_ERROR; /* The result of this function. */ - // Make sure we got a valid path. + /* Make sure we got a valid path. */ if ((path != NULL) && ((*path) != NULL) && (pathSize != NULL) && ((*pathSize) > 0)) { } else { - // Invalid path. + /* Invalid path. */ ret = COMMON_ERROR_INVALID_ARGUMENT; - // Log the error. + /* Log the error. */ COMMON_LOG_DEBUG("FileUtills_ResolveSystemSymoblicLink(): "); COMMON_LOG_DEBUG(Common_Get_Error_Message(COMMON_ERROR_INVALID_ARGUMENT)); COMMON_LOG_DEBUG(" Given path argument is invalid."); } - // Return the result. + /* Return the result. */ return ret; } -int FileUtills::GetUserProfileDirectoryPath_Syscall(std::string & path) +int FileUtills::GetUserProfileDirectoryPath_Syscall(char ** path, size_t * pathLength) { - // Init vars. - int ret = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; // The result of this function. + /* Init vars. */ + int ret = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; /* The result of this function. */ + _TCHAR * tempPath = NULL; /* Temporary pointer for constructing the path. */ + size_t tempPathLength = 0; /* Temporary variable for storing the length of the path. */ - + /* Check for invalid arguments. */ + if ((path != NULL) && (pathLength != NULL)) + { - // Return the result. + } + else + { + /* Invalid arguments. */ + ret = COMMON_ERROR_INVALID_ARGUMENT; + } + + /* Return the result. */ return ret; } int FileUtills::GetCurrentWorkingDirectoryPath_Syscall(std::string & path) { - // Init vars. - int ret = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; // The result of this function. - - + /* Init vars. */ + int ret = COMMON_ERROR_FUNCTION_NOT_IMPLEMENTED; /* The result of this function. */ - // Return the result. + /* Return the result. */ return ret; } @@ -129,26 +139,32 @@ int FileUtills::GetExecDirectory_Syscall(char ** retStr, size_t * retStrSize) FileUtills::dirlist * FileUtills::getDirectory_Syscall(const std::string & absPath, const bool & cleanList) { - // Init vars. - int errcpy = 0; // Used to fetch the error code. - FileUtills::dirlist * ret = NULL; // The FileUtills directory structure. - std::string tempname = ""; // Used to store the filename / subdirectory name for the addToArray function. - - // Dumb check. + /* Init vars. */ + int errcpy = 0; /* Used to fetch the error code. */ + FileUtills::dirlist * ret = NULL; /* The FileUtills directory structure. */ + std::string tempname = ""; /* Used to store the filename / subdirectory name for the addToArray function. */ + _TCHAR * tempPath = NULL; + + + _tfindfirst(); /* Find first file. */ + _tfindnext(); /* Find next file. */ + _tfindclose(); /* Release directory search handles and resources. */ + + /* Dumb check. */ if (absPath.size() > 0) { - // Allocate the dirlist. + /* Allocate the dirlist. */ try{ ret = new FileUtills::dirlist; if (ret != NULL) { - // Set the path. + /* Set the path.*/ ret->path = absPath; - // Dump the path as a c string into the Directory stream object......(Overly complicated POS......) + /* Dump the path as a c string into the Directory stream object......(Overly complicated POS......) */ - // Check and make sure we can open the directory first. + /* Check and make sure we can open the directory first. */ if ((dp = (opendir(absPath.c_str()))) == NULL) { // Copy the error code, and translate it. From 1e68239ebfcd060ca6496004d2d311bdc68b350d Mon Sep 17 00:00:00 2001 From: codebase7 Date: Fri, 7 Aug 2015 02:52:54 -0400 Subject: [PATCH 060/325] Add FileUtills_Private_API_Windows_Syscall.h header. This commit adds the FileUtills_Private_API_Windows_Syscall.h header to FileUtills. --- .../FileUtills_Private_API_Windows_Syscall.h | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 src/Common/Src/File_Management_Subsystem/FileUtills_Private_API_Windows_Syscall.h diff --git a/src/Common/Src/File_Management_Subsystem/FileUtills_Private_API_Windows_Syscall.h b/src/Common/Src/File_Management_Subsystem/FileUtills_Private_API_Windows_Syscall.h new file mode 100644 index 0000000..08a70b9 --- /dev/null +++ b/src/Common/Src/File_Management_Subsystem/FileUtills_Private_API_Windows_Syscall.h @@ -0,0 +1,32 @@ +/*! + Multiverse Engine Project 06/7/2015 FileUtills FileUtills_Private_API_Windows_Syscall.h + + Copyright (C) 2015 Multiverse Engine Project + + This program is free software; + you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this program; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Official source repository and project information can be found at + https://github.com/codebase7/mengine +*/ + +/* Include guard. */ +#ifndef FILEUTILLS_PRIVATE_API_WINDOWS_SYSCALL_H +#define FILEUTILLS_PRIVATE_API_WINDOWS_SYSCALL_H + +/* Define CSIDL values. */ +#define FILEUTILLS_USER_PROFILE_ID CSIDL_PROFILE +#define FILEUTILLS_USER_DOCUMENTS_ID CSIDL_PERSONAL +#define FILEUTILLS_APPDATA_ID CSIDL_LOCAL_APPDATA + +#endif /* FILEUTILLS_PRIVATE_API_WINDOWS_SYSCALL_H */ + +/* End of FileUtills_Private_API_Windows_Syscall.h. */ From a595d4397e4572c914b8c24512faa1878dcd4802 Mon Sep 17 00:00:00 2001 From: codebase7 Date: Fri, 7 Aug 2015 03:13:48 -0400 Subject: [PATCH 061/325] Add FileUtills_Write_Data_To_File_From_File(). This commit adds the FileUtills_Write_Data_To_File_From_File() function to FileUtills. --- .../File_Management_Subsystem/FileUtills.cpp | 224 ++++++++++++++++++ .../File_Management_Subsystem/FileUtills.h | 29 +++ 2 files changed, 253 insertions(+) diff --git a/src/Common/Src/File_Management_Subsystem/FileUtills.cpp b/src/Common/Src/File_Management_Subsystem/FileUtills.cpp index 9655d89..790ad18 100644 --- a/src/Common/Src/File_Management_Subsystem/FileUtills.cpp +++ b/src/Common/Src/File_Management_Subsystem/FileUtills.cpp @@ -551,6 +551,230 @@ int FileUtills_Read_Bytes_From_File(FILE * IN, const size_t dataLength, char * d return ret; } +int FileUtills_Write_Data_To_File_From_File(FILE * OUT, const char * filename, const size_t filenameLength, const struct MSYS_FILESIZE * fileStartingOffset, const size_t dataLength) +{ + /* Init vars. */ + int ret = COMMON_ERROR_UNKNOWN_ERROR; /* The result of this function. */ + int retFromC = 0; /* The result of C calls. */ + struct MSYS_FILESIZE * inFileLength = NULL; /* The size of the input file. */ + FILE * IN = NULL; /* The input file. */ + char * inputBuf = NULL; /* Memory buffer used for reading in data from a file. NOT on the stack! Bad input can follow! */ + size_t remainingLength = 0; /* Used to calculate remaining bytes to write in output loop. */ + size_t x = 0; /* Counter used in I/O loop. */ + size_t y = 0; /* Counter used in Input Loop and Output Loop. */ + long long int realStartOffset = 0; /* The position to start writing data into the file at. */ + + /* Check for invalid arguments. */ + if ((OUT != NULL) && (ferror(OUT) == 0) && (filename != NULL) && (filenameLength > 0) && (fileStartingOffset != NULL) && (fileStartingOffset->length >= 0) && (dataLength > 0)) + { + /* Allocate memory for the filesize structures. */ + ret = FileUtills_Create_MSYS_FILESIZE_Structure(&inFileLength); + if (ret == COMMON_ERROR_SUCCESS) + { + /* Open the input file. */ + IN = fopen(filename, "rb"); + if (IN != NULL) + { + /* Get the length of the input file. */ + ret = FileUtills_Get_File_Length(IN, inFileLength); + + /* Make sure we got a valid file length and that the length of the file is big enough to store the data we want. */ + if ((ret == COMMON_ERROR_SUCCESS) && (inFileLength->length > 0) && ((((unsigned)(fileStartingOffset->length)) + dataLength) <= ((unsigned)(inFileLength->length)))) + { + /* Reset ret. */ + ret = COMMON_ERROR_UNKNOWN_ERROR; + + /* Get the starting offset. */ + retFromCall = FileUtills_Get_Length_From_MSYS_FILESIZE_Structure_LLINT(fileStartingOffset, realStartOffset); + if (retFromCall == COMMON_ERROR_SUCCESS) + { + /* Skip to the starting offset. */ +#ifdef _MSC_VER /* VC is special */ + retFromC = _fseeki64(IN, realStartOffset, SEEK_SET); +#else + retFromC = fseeko64(IN, realStartOffset, SEEK_SET); +#endif /* _MSC_VER */ + if (retFromC == 0) + { + /* Allocate input buffer. */ + inputBuf = (char*)malloc(IO_BUF_SIZE); + if (inputBuf != NULL) + { + /* Begin I/O loop. */ + for (x = 0; ((x < dataLength) && (!ferror(IN)) && (!feof(IN)) && (!ferror(OUT)));) + { + /* Determine if the remaining data to read in is less than the buffer size. */ + remainingLength = (dataLength - x); + if (remainingLength >= IO_BUF_SIZE) + { + /* Set remaining length to the buffer size. */ + remainingLength = IO_BUF_SIZE; + } + + /* Begin input loop. */ + for (y = 0; ((y < remainingLength) && (!ferror(IN)) && (!feof(IN))); y++) + { + /* Read in the remaining data. */ + retFromC = fgetc(IN); + inputBuf[y] = retFromC; + } + + /* Check for successful read. */ + if ((!ferror(IN)) && (!feof(IN))) + { + /* OK, begin the output loop. */ + for (y = 0; ((y < remainingLength) && (!ferror(OUT))); y++) + { + /* Output the current buffer. */ + fputc(inputBuf[y], OUT); + } + + /* Check for successful output. */ + if (!ferror(OUT)) + { + /* OK, flush the buffer. */ + retFromC = fflush(OUT); + if (retFromC == 0) + { + /* OK, add the remaining amount to x. */ + x = (x + remainingLength); + } + else + { + /* Could not flush the buffer. */ + ret = COMMON_ERROR_IO_ERROR; + + /* Log error. */ + COMMON_LOG_DEBUG("DEBUG: FileUtills_Write_Data_To_File_From_File(): Could not flush output buffer data to output file.\n"); + } + } + else + { + /* Bad output file stream. */ + ret = COMMON_ERROR_IO_ERROR; + + /* Log error. */ + COMMON_LOG_DEBUG("DEBUG: FileUtills_Write_Data_To_File_From_File(): Could not write data to output file.\n"); + } + } + else + { + /* Bad input file stream. */ + ret = COMMON_ERROR_IO_ERROR; + + /* Log error. */ + COMMON_LOG_DEBUG("DEBUG: FileUtills_Write_Data_To_File_From_File(): Could not read data from input file.\n"); + } + } + + /* Deallocate the input memory buffer. */ + if (inputBuf != NULL) + { + free(inputBuf); + inputBuf = NULL; + } + + /* Check for success. */ + if ((ret == COMMON_ERROR_UNKNOWN_ERROR) && (!ferror(IN)) && (!feof(IN)) && (!ferror(OUT))) + { + /* Success! */ + ret = COMMON_ERROR_SUCCESS; + } + else + { + /* Check for and log IO errors. */ + if (ret == COMMON_ERROR_IO_ERROR) + { + /* Log error. */ + COMMON_LOG_DEBUG("DEBUG: FileUtills_Write_Data_To_File_From_File(): File I/O Error.\n"); + } + } + } + else + { + /* Could not allocate memory for input buffer. */ + ret = COMMON_ERROR_MEMORY_ERROR; + + /* Log error. */ + COMMON_LOG_DEBUG("DEBUG: FileUtills_Write_Data_To_File_From_File(): Could not allocate memory for input buffer.\n"); + } + } + else + { + /* Bad file stream. */ + ret = COMMON_ERROR_IO_ERROR; + + /* Log error. */ + COMMON_LOG_DEBUG("DEBUG: FileUtills_Write_Data_To_File_From_File(): Could not seek to starting offset.\n"); + } + } + else + { + /* Could not get starting offset. */ + ret = COMMON_ERROR_INTERNAL_ERROR; + + /* Log error. */ + COMMON_LOG_DEBUG("DEBUG: FileUtills_Write_Data_To_File_From_File(): Could not get starting offset from management structure."); + } + } + else + { + /* Invalid input file. */ + ret = COMMON_ERROR_IO_ERROR; + + /* Log error. */ + COMMON_LOG_DEBUG("DEBUG: FileUtills_Write_Data_To_File_From_File(): Could not get input file length or input file is empty.\n"); + } + + /* Close the input file. */ + retFromC = fclose(IN); + if ((retFromC != 0) && (ret != COMMON_ERROR_IO_ERROR)) + { + /* Could not close the input file. */ + ret = COMMON_ERROR_IO_ERROR; + + /* Log error. */ + COMMON_LOG_DEBUG("DEBUG: FileUtills_Write_Data_To_File_From_File(): Could not close input file ( "); + COMMON_LOG_DEBUG(filename); + COMMON_LOG_DEBUG(" ).\n"); + } + } + else + { + /* Could not open input file. */ + ret = COMMON_ERROR_IO_ERROR; + + /* Log error. */ + COMMON_LOG_DEBUG("DEBUG: FileUtills_Write_Data_To_File_From_File(): Could not open input file ( "); + COMMON_LOG_DEBUG(filename); + COMMON_LOG_DEBUG(" ).\n"); + } + + /* Deallocate inFileLength. */ + FileUtills_Destroy_MSYS_FILESIZE_Structure(&inFileLength); + } + else + { + /* Could not allocate memory for the inFileLength structure. */ + ret = COMMON_ERROR_MEMORY_ERROR; + + /* Log error. */ + COMMON_LOG_DEBUG("DEBUG: FileUtills_Write_Data_To_File_From_File(): Could not allocate memory for MSYS_FILESIZE structure.\n"); + } + } + else + { + /* Invalid arguments. */ + ret = COMMON_ERROR_INVALID_ARGUMENT; + + /* Log error. */ + COMMON_LOG_DEBUG("DEBUG: FileUtills_Write_Data_To_File_From_File(): Invalid argument.\n"); + } + + /* Exit function. */ + return ret; +} + int FileUtills_Write_Data_To_File_From_Memory(FILE * OUT, const char * data, const size_t dataLength) { /* Init vars. */ diff --git a/src/Common/Src/File_Management_Subsystem/FileUtills.h b/src/Common/Src/File_Management_Subsystem/FileUtills.h index e438279..dae5316 100644 --- a/src/Common/Src/File_Management_Subsystem/FileUtills.h +++ b/src/Common/Src/File_Management_Subsystem/FileUtills.h @@ -231,6 +231,35 @@ int FileUtills_Get_File_Length(FILE * fp, struct MSYS_FILESIZE * fileLength); */ int FileUtills_Read_Bytes_From_File(FILE * IN, const size_t dataLength, char * dataBuf, const size_t dataBufLength, const size_t destStaringOffset, const bool blankDataBuf); +/*! + * int FileUtills_Write_Data_To_File_From_File(FILE * OUT, const char * filename, const size_t filenameLength, const struct MSYS_FILESIZE * fileStartingOffset, const size_t dataLength) + * + * Opens the given input file in binary mode and jumps to the given starting offset, + * then reads the given amount of data and writes it directly to the given output file, + * finally it closes the input file. + * + * NOTE: This function expects that the given output file is already open and not errored out when called. + * The output file will remain open after the function returns. (It will still be usable if the returned error code is SUCCESS.) + * + * The output position of the file will NOT be restored in ANY instance after this function returns. + * If you need the current position for something, copy it elsewhere before calling this function. + * + * Returns COMMON_ERROR_SUCCESS if the data is written to the output file successfully. + * + * Returns COMMON_ERROR_INVALID_ARGUMENT if the given output file pointer is NULL, + * the given output file has errored out prior to the function call, + * filename is NULL, filenameLength is less than 1, fileStartingOffset is less than 0, + * or dataLength is less than 1. + * + * Returns COMMON_ERROR_MEMORY_ERROR if a memory allocation attempt fails. + * + * Returns COMMON_ERROR_IO_ERROR on all f*() errors, or if the end of the file is hit prior to reading + * the amount of requested data. + * + * Otherwise returns the appropriate error code. + */ +int FileUtills_Write_Data_To_File_From_File(FILE * OUT, const char * filename, const size_t filenameLength, const struct MSYS_FILESIZE * fileStartingOffset, const size_t dataLength); + /*! * int FileUtills_Write_Data_To_File_From_Memory(FILE * OUT, const char * data, const size_t dataLength) * From 413c012ed34f0dc2c9e8753827bf659c67ed9b04 Mon Sep 17 00:00:00 2001 From: codebase7 Date: Fri, 7 Aug 2015 04:36:52 -0400 Subject: [PATCH 062/325] Create DataProcess.c This commit creates a seperate file (DataProcess.c) for the DataProcess code that can be used by a C program. The point of this is to allow the use of some DataProcess functionality by C programs where possible. To kickoff the new DataProcess.c file, this commit also moves the DataProces::Trivial_Random_Number_Generator() function code to the new C file and renames it to DataProcess_Trivial_Random_Number_Generator(). The original DataProcess::Trivial_Random_Number_Generator() function now acts as a wrapper to the DataProcess_Trivial_Random_Number_Generator() C function. --- src/Core/Src/CMakeLists.txt | 2 ++ src/Core/Src/DataProcess.c | 55 ++++++++++++++++++++++++++++++++++++ src/Core/Src/DataProcess.cpp | 22 ++------------- src/Core/Src/DataProcess.h | 49 +++++++++++++++++++++++--------- 4 files changed, 95 insertions(+), 33 deletions(-) create mode 100644 src/Core/Src/DataProcess.c diff --git a/src/Core/Src/CMakeLists.txt b/src/Core/Src/CMakeLists.txt index a77611e..bfeda7c 100644 --- a/src/Core/Src/CMakeLists.txt +++ b/src/Core/Src/CMakeLists.txt @@ -7,9 +7,11 @@ add_library(Panic_Handler_Multiverse_Engine SHARED Panic.cpp) add_library(Panic_Handler_Multiverse_Engine_Static STATIC Panic.cpp) add_library(Core_Multiverse_Engine SHARED DataProcess.cpp +DataProcess.c DataProcess_Endianness_Check.cpp FileStreams.cpp) add_library(Core_Multiverse_Engine_Static STATIC DataProcess.cpp +DataProcess.c DataProcess_Endianness_Check.cpp FileStreams.cpp) target_link_libraries(Core_Multiverse_Engine Panic_Handler_Multiverse_Engine) diff --git a/src/Core/Src/DataProcess.c b/src/Core/Src/DataProcess.c new file mode 100644 index 0000000..f1f735d --- /dev/null +++ b/src/Core/Src/DataProcess.c @@ -0,0 +1,55 @@ +/*! + Multiverse Engine Project DataProcess DataProcess.c 07/8/2015 + + Copyright (C) 2015 Multiverse Engine Project + + This program is free software; + you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this program; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Official source repository and project information can be found at + https://github.com/codebase7/mengine +*/ + +/* Set extern C. */ +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Internal includes. */ +#include "DataProcess.h" + +/* External includes. */ +#include