From 68a627aef192ff5a8fb68067a9f83d3f0d88fe87 Mon Sep 17 00:00:00 2001
From: "Gerardo E. Cruz-Ortiz" <59618057+astrogeco@users.noreply.github.com>
Date: Sun, 11 Apr 2021 13:42:56 -0400
Subject: [PATCH] CFS-41, Add FS Files
---
.gitignore | 4 +-
modules/core_api/eds/cfe_fs.xml | 165 ++++
modules/core_api/fsw/inc/cfe_fs.h | 344 +++++++
.../core_api/fsw/inc/cfe_fs_api_typedefs.h | 121 +++
.../core_api/fsw/inc/cfe_fs_core_internal.h | 60 ++
.../core_api/fsw/inc/cfe_fs_extern_typedefs.h | 230 +++++
modules/fs/fsw/src/cfe_fs_api.c | 886 ++++++++++++++++++
modules/fs/fsw/src/cfe_fs_module_all.h | 41 +
modules/fs/fsw/src/cfe_fs_priv.c | 140 +++
modules/fs/fsw/src/cfe_fs_priv.h | 155 +++
10 files changed, 2144 insertions(+), 2 deletions(-)
create mode 100644 modules/core_api/eds/cfe_fs.xml
create mode 100644 modules/core_api/fsw/inc/cfe_fs.h
create mode 100644 modules/core_api/fsw/inc/cfe_fs_api_typedefs.h
create mode 100644 modules/core_api/fsw/inc/cfe_fs_core_internal.h
create mode 100644 modules/core_api/fsw/inc/cfe_fs_extern_typedefs.h
create mode 100644 modules/fs/fsw/src/cfe_fs_api.c
create mode 100644 modules/fs/fsw/src/cfe_fs_module_all.h
create mode 100644 modules/fs/fsw/src/cfe_fs_priv.c
create mode 100644 modules/fs/fsw/src/cfe_fs_priv.h
diff --git a/.gitignore b/.gitignore
index 70428b516..f6f8a08e4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,5 +15,5 @@
!modules/core_private/fsw/inc/cfe_evs_log_typedef.h
# FS
-# !cfe_fs*
-# !modules/fs/fsw/*
+!cfe_fs*
+!modules/fs/fsw/*
diff --git a/modules/core_api/eds/cfe_fs.xml b/modules/core_api/eds/cfe_fs.xml
new file mode 100644
index 000000000..da85a5912
--- /dev/null
+++ b/modules/core_api/eds/cfe_fs.xml
@@ -0,0 +1,165 @@
+
+
+
+
+
+
+
+
+
+
+ Executive Services Exception/Reset Log File which is generated in response to a
+ \link #CFE_ES_WRITE_ERLOG_CC \ES_WRITEERLOG2FILE \endlink
+ command.
+
+
+
+
+ Executive Services System Log File which is generated in response to a
+ \link #CFE_ES_WRITE_SYSLOG_CC \ES_WRITESYSLOG2FILE \endlink
+ command.
+
+
+
+
+ Executive Services Information on All Applications File which is generated in response to a
+ \link #CFE_ES_QUERY_ALL_CC \ES_WRITEAPPINFO2FILE \endlink
+ command.
+
+
+
+
+ Executive Services Performance Analyzer Data File which is generated in response to a
+ \link #CFE_ES_PERF_STOPDATA_CC \ES_STOPLADATA \endlink
+ command.
+
+
+
+
+ Executive Services Shell Response Data File which is generated in response to a
+ \link #CFE_ES_SHELL_CMD_CC \ES_SHELL \endlink
+ command.
+
+
+
+
+ Executive Services Critical Data Store Registry Dump File which is generated in response to a
+ \link #CFE_ES_DUMP_CDS_REG_CC \ES_DUMPCDSREG \endlink
+ command.
+
+
+
+
+ Table Services Registry Dump File which is generated in response to a
+ \link #CFE_TBL_DUMP_REG_CC \TBL_WRITEREG2FILE \endlink
+ command.
+
+
+
+
+ Table Services Table Image File which is generated either on the ground or in response to a
+ \link #CFE_TBL_DUMP_CC \TBL_DUMP \endlink command.
+
+
+
+
+ Event Services Application Data Dump File which is generated in response to a
+ \link #CFE_EVS_FILE_WRITE_APP_DATA_CC \EVS_WRITEAPPDATA2FILE \endlink
+ command.
+
+
+
+
+ Event Services Local Event Log Dump File which is generated in response to a
+ \link #CFE_EVS_FILE_WRITE_LOG_DATA_CC \EVS_WRITELOG2FILE \endlink
+ command.
+
+
+
+
+ Software Bus Pipe Data Dump File which is generated in response to a
+ \link #CFE_SB_SEND_PIPE_INFO_CC \SB_WRITEPIPE2FILE \endlink
+ command.
+
+
+
+
+ Software Bus Message Routing Data Dump File which is generated in response to a
+ \link #CFE_SB_SEND_ROUTING_INFO_CC \SB_WRITEROUTING2FILE \endlink
+ command.
+
+
+
+
+ Software Bus Message Mapping Data Dump File which is generated in response to a
+ \link #CFE_SB_SEND_MAP_INFO_CC \SB_WRITEMAP2FILE \endlink
+ command.
+
+
+
+
+ Executive Services Query All Tasks Data File which is generated in response to a
+ \link #CFE_ES_QUERY_ALL_TASKS_CC \ES_WRITETASKINFO2FILE \endlink
+ command.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/core_api/fsw/inc/cfe_fs.h b/modules/core_api/fsw/inc/cfe_fs.h
new file mode 100644
index 000000000..6bca3f5c4
--- /dev/null
+++ b/modules/core_api/fsw/inc/cfe_fs.h
@@ -0,0 +1,344 @@
+/*
+** GSC-18128-1, "Core Flight Executive Version 6.7"
+**
+** Copyright (c) 2006-2019 United States Government as represented by
+** the Administrator of the National Aeronautics and Space Administration.
+** All Rights Reserved.
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+/**
+ * @file
+ *
+ * Purpose: cFE File Services (FS) library API header file
+ *
+ * Author: S.Walling/Microtel
+ *
+ */
+
+#ifndef CFE_FS_H
+#define CFE_FS_H
+
+/*
+** Required header files...
+*/
+#include "common_types.h"
+#include "osconfig.h"
+#include "cfe_platform_cfg.h"
+#include "cfe_error.h"
+#include "cfe_fs_api_typedefs.h"
+#include "cfe_fs_extern_typedefs.h"
+
+/** @defgroup CFEAPIFSHeader cFE File Header Management APIs
+ * @{
+ */
+
+/*****************************************************************************/
+/**
+** \brief Read the contents of the Standard cFE File Header
+**
+** \par Description
+** This API will fill the specified #CFE_FS_Header_t variable with the
+** contents of the Standard cFE File Header of the file identified by
+** the given File Descriptor.
+**
+** \par Assumptions, External Events, and Notes:
+** -# The File has already been successfully opened using #OS_OpenCreate and
+** the caller has a legitimate File Descriptor.
+**
+** \param[in] FileDes File Descriptor obtained from a previous call to #OS_OpenCreate
+** that is associated with the file whose header is to be read.
+**
+** \param[in, out] Hdr Pointer to a variable of type #CFE_FS_Header_t that will be
+** filled with the contents of the Standard cFE File Header. *Hdr is the contents of the
+** Standard cFE File Header for the specified file.
+**
+** \return Execution status, see \ref CFEReturnCodes
+**
+** \sa #CFE_FS_WriteHeader
+**
+******************************************************************************/
+CFE_Status_t CFE_FS_ReadHeader(CFE_FS_Header_t *Hdr, osal_id_t FileDes);
+
+/*****************************************************************************/
+/**
+** \brief Initializes the contents of the Standard cFE File Header
+**
+** \par Description
+** This API will clear the specified #CFE_FS_Header_t variable and
+** initialize the description field with the specified value
+**
+** \param[in] Hdr Pointer to a variable of type #CFE_FS_Header_t that will be
+** cleared and initialized
+**
+** \param[in] *Description Initializes Header's Description
+**
+** \param[in] SubType Initializes Header's SubType
+**
+** \sa #CFE_FS_WriteHeader
+**
+******************************************************************************/
+void CFE_FS_InitHeader(CFE_FS_Header_t *Hdr, const char *Description, uint32 SubType);
+
+/*****************************************************************************/
+/**
+** \brief Write the specified Standard cFE File Header to the specified file
+**
+** \par Description
+** This API will output the specified #CFE_FS_Header_t variable, with some
+** fields automatically updated, to the specified file as the Standard cFE
+** File Header. This API will automatically populate the following fields
+** in the specified #CFE_FS_Header_t:
+**
+** -# \link #CFE_FS_Header_t::ContentType \c ContentType \endlink - Filled with 0x63464531 ('cFE1')
+** -# \link #CFE_FS_Header_t::Length \c Length \endlink - Filled with the sizeof(CFE_FS_Header_t)
+** -# \link #CFE_FS_Header_t::SpacecraftID \c SpacecraftID \endlink - Filled with the Spacecraft ID
+** -# \link #CFE_FS_Header_t::ProcessorID \c ProcessorID \endlink - Filled with the Processor ID
+** -# \link #CFE_FS_Header_t::ApplicationID \c ApplicationID \endlink - Filled with the Application ID
+** -# \link #CFE_FS_Header_t::TimeSeconds \c TimeSeconds \endlink - Filled with the Time, in seconds, as obtained
+** by #CFE_TIME_GetTime
+** -# \link #CFE_FS_Header_t::TimeSubSeconds \c TimeSubSeconds \endlink - Filled with the Time, subseconds, as
+** obtained by #CFE_TIME_GetTime
+**
+** \par Assumptions, External Events, and Notes:
+** -# The File has already been successfully opened using #OS_OpenCreate and
+** the caller has a legitimate File Descriptor.
+** -# The \c SubType field has been filled appropriately by the Application.
+** -# The \c Description field has been filled appropriately by the Application.
+**
+** \param[in] FileDes File Descriptor obtained from a previous call to #OS_OpenCreate
+** that is associated with the file whose header is to be read.
+**
+** \param[in, out] Hdr Pointer to a variable of type #CFE_FS_Header_t that will be
+** filled with the contents of the Standard cFE File Header. *Hdr is the contents of the
+** Standard cFE File Header for the specified file.
+**
+** \return Execution status, see \ref CFEReturnCodes
+**
+** \sa #CFE_FS_ReadHeader
+**
+******************************************************************************/
+CFE_Status_t CFE_FS_WriteHeader(osal_id_t FileDes, CFE_FS_Header_t *Hdr);
+
+/*****************************************************************************/
+/**
+** \brief Modifies the Time Stamp field in the Standard cFE File Header for the specified file
+**
+** \par Description
+** This API will modify the \link #CFE_FS_Header_t::TimeSeconds timestamp \endlink found
+** in the Standard cFE File Header of the specified file. The timestamp will be replaced
+** with the time specified by the caller.
+**
+** \par Assumptions, External Events, and Notes:
+** -# The File has already been successfully opened using #OS_OpenCreate and
+** the caller has a legitimate File Descriptor.
+** -# The \c NewTimestamp field has been filled appropriately by the Application.
+**
+** \param[in] FileDes File Descriptor obtained from a previous call to #OS_OpenCreate
+** that is associated with the file whose header is to be read.
+**
+** \param[in] NewTimestamp A #CFE_TIME_SysTime_t data structure containing the desired time
+** to be put into the file's Standard cFE File Header.
+**
+** \return Execution status, see \ref CFEReturnCodes
+**
+******************************************************************************/
+CFE_Status_t CFE_FS_SetTimestamp(osal_id_t FileDes, CFE_TIME_SysTime_t NewTimestamp);
+/**@}*/
+
+/** @defgroup CFEAPIFSUtil cFE File Utility APIs
+ * @{
+ */
+
+/*****************************************************************************/
+/**
+** \brief Get the default virtual mount point for a file category
+**
+** Certain classes of files generally reside in a common directory, mainly
+** either the persistent storage (/cf typically) or ram disk (/ram typically).
+**
+** Ephemeral status files are generally in the ram disk while application
+** modules and scripts are generally in the persistent storage.
+**
+** This returns the expected directory for a given class of files in the form
+** of a virtual OSAL mount point string.
+**
+** \returns String containing the mount point, or NULL if unkown/invalid
+*/
+const char *CFE_FS_GetDefaultMountPoint(CFE_FS_FileCategory_t FileCategory);
+
+/*****************************************************************************/
+/**
+** \brief Get the default filename extension for a file category
+**
+** Certain file types may have an extension that varies from system to system.
+** This is primarily an issue for application modules which are ".so" on
+** Linux systems, ".dll" on Windows, ".o" on VxWorks, ".obj" on RTEMS, and so on.
+**
+** This uses a combination of compile-time configuration and hints from the
+** build environment to get the default/expected extension for a given file
+** category.
+**
+** \returns String containing the extension, or NULL if unkown/invalid
+*/
+const char *CFE_FS_GetDefaultExtension(CFE_FS_FileCategory_t FileCategory);
+
+/*****************************************************************************/
+/**
+** \brief Parse a filename input from an input buffer into a local buffer
+**
+** \par Description
+** This provides a more user friendly way to specify file names,
+** using default values for the path and extension, which can
+** vary from system to system.
+**
+** If InputBuffer is null or its length is zero, then DefaultInput
+** is used as if it was the content of the input buffer.
+**
+** If either the pathname or extension is missing from the input,
+** it will be added from defaults, with the complete fully-qualified
+** filename stored in the output buffer.
+**
+** \par Assumptions, External Events, and Notes:
+** -# The paths and filenames used here are the standard unix style
+** filenames separated by "/" (path) and "." (extension) characters.
+** -# Input Buffer has a fixed max length. Parsing will not exceed InputBufSize,
+** and does not need to be null terminated. However parsing will stop
+** at the first null char, when the input is shorter than the maximum.
+**
+** \param[out] OutputBuffer Buffer to store result.
+** \param[in] InputBuffer A input buffer that may contain a file name (e.g. from command).
+** \param[in] OutputBufSize Maximum Size of output buffer.
+** \param[in] InputBufSize Maximum Size of input buffer.
+** \param[in] DefaultInput Default value to use for input if InputBffer is empty
+** \param[in] DefaultPath Default value to use for pathname if omitted from input
+** \param[in] DefaultExtension Default value to use for extension if omitted from input
+**
+** \return Execution status, see \ref CFEReturnCodes
+**
+******************************************************************************/
+int32 CFE_FS_ParseInputFileNameEx(char *OutputBuffer, const char *InputBuffer, size_t OutputBufSize,
+ size_t InputBufSize, const char *DefaultInput, const char *DefaultPath,
+ const char *DefaultExtension);
+
+/*****************************************************************************/
+/**
+** \brief Parse a filename string from the user into a local buffer
+**
+** \par Description
+** Simplified API for CFE_FS_ParseInputFileNameEx() where input is
+** always known to be a non-empty, null terminated string and the fixed-length
+** input buffer not needed. For instance this may be used where
+** the input is a fixed string from cfe_platform_cfg.h or similar.
+**
+** \par Assumptions, External Events, and Notes:
+** The parameters are organized such that this is basically like strncpy() with an
+** extra argument, and existing file name accesses which use a direct copy can
+** easily change to use this instead.
+**
+** \sa CFE_FS_ParseInputFileNameEx()
+**
+** \param[out] OutputBuffer Buffer to store result.
+** \param[in] InputName A null terminated input string
+** \param[in] OutputBufSize Maximum Size of output buffer.
+** \param[in] FileCategory The generalized category of file (implies default path/extension)
+**
+** \return Execution status, see \ref CFEReturnCodes
+**
+**---------------------------------------------------------------------------------------
+*/
+int32 CFE_FS_ParseInputFileName(char *OutputBuffer, const char *InputName, size_t OutputBufSize,
+ CFE_FS_FileCategory_t FileCategory);
+
+/*****************************************************************************/
+/**
+** \brief Extracts the filename from a unix style path and filename string.
+**
+** \par Description
+** This API will take the original unix path/filename combination and
+** extract the base filename. Example: Given the path/filename : "/cf/apps/myapp.o.gz"
+** this function will return the filename: "myapp.o.gz".
+**
+** \par Assumptions, External Events, and Notes:
+** -# The paths and filenames used here are the standard unix style
+** filenames separated by "/" characters.
+** -# The extracted filename (including terminator) is no longer than #OS_MAX_PATH_LEN
+**
+** \param[in] OriginalPath The original path.
+** \param[out] FileNameOnly The filename that is extracted from the path.
+**
+** \return Execution status, see \ref CFEReturnCodes
+**
+******************************************************************************/
+CFE_Status_t CFE_FS_ExtractFilenameFromPath(const char *OriginalPath, char *FileNameOnly);
+
+/*****************************************************************************/
+/**
+** \brief Register a background file dump request
+**
+** \par Description
+** Puts the previously-initialized metadata into the pending request queue
+**
+** \par Assumptions, External Events, and Notes:
+** Metadata structure should be stored in a static memory area (not on heap) as it
+** must persist and be accessible by the file writer task throughout the asynchronous
+** job operation.
+**
+** \param[inout] Meta The background file write persistent state object
+**
+** \return Execution status, see \ref CFEReturnCodes
+**
+******************************************************************************/
+int32 CFE_FS_BackgroundFileDumpRequest(CFE_FS_FileWriteMetaData_t *Meta);
+
+/*****************************************************************************/
+/**
+** \brief Query if a background file write request is currently pending
+**
+** \par Description
+** This returns "true" while the request is on the background work queue
+** This returns "false" once the request is complete and removed from the queue.
+**
+** \par Assumptions, External Events, and Notes:
+** None
+**
+** \param[inout] Meta The background file write persistent state object
+**
+** \return true if request is already pending, false if not
+**
+******************************************************************************/
+bool CFE_FS_BackgroundFileDumpIsPending(const CFE_FS_FileWriteMetaData_t *Meta);
+
+/*****************************************************************************/
+/**
+** \brief Execute the background file write job(s)
+**
+** \par Description
+** Runs the state machine associated with background file write requests
+**
+** \par Assumptions, External Events, and Notes:
+** This should only be invoked as a background job from the ES background task,
+** it should not be invoked directly.
+**
+** \param[in] ElapsedTime The amount of time passed since last invocation (ms)
+** \param[in] Arg Not used/ignored
+**
+** \return true if jobs are pending, false if idle
+**
+******************************************************************************/
+bool CFE_FS_RunBackgroundFileDump(uint32 ElapsedTime, void *Arg);
+
+/**@}*/
+
+#endif /* CFE_FS_H */
diff --git a/modules/core_api/fsw/inc/cfe_fs_api_typedefs.h b/modules/core_api/fsw/inc/cfe_fs_api_typedefs.h
new file mode 100644
index 000000000..0e7a80594
--- /dev/null
+++ b/modules/core_api/fsw/inc/cfe_fs_api_typedefs.h
@@ -0,0 +1,121 @@
+/*
+** GSC-18128-1, "Core Flight Executive Version 6.7"
+**
+** Copyright (c) 2006-2019 United States Government as represented by
+** the Administrator of the National Aeronautics and Space Administration.
+** All Rights Reserved.
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+/**
+ * @file
+ *
+ * Purpose: cFE File Services (FS) library API header file
+ *
+ * Author: S.Walling/Microtel
+ *
+ */
+
+#ifndef CFE_FS_API_TYPEDEFS_H
+#define CFE_FS_API_TYPEDEFS_H
+
+/*
+** Required header files...
+*/
+#include "common_types.h"
+#include "osconfig.h"
+#include "cfe_fs_extern_typedefs.h"
+
+/**
+ * \brief Generalized file types/categories known to FS
+ *
+ * This defines different categories of files, where they
+ * may reside in different default locations of the virtualized file system.
+ *
+ * This is different from, and should not be confused with, the "SubType"
+ * field in the FS header. This value is only used at runtime for FS APIs
+ * and should not actually appear in any output file or message.
+ */
+typedef enum
+{
+ CFE_FS_FileCategory_UNKNOWN, /**< Placeholder, unknown file category */
+ CFE_FS_FileCategory_DYNAMIC_MODULE, /**< Dynamically loadable apps/libraries (e.g. .so, .o, .dll, etc) */
+ CFE_FS_FileCategory_BINARY_DATA_DUMP, /**< Binary log file generated by various data dump commands */
+ CFE_FS_FileCategory_TEXT_LOG, /**< Text-based log file generated by various commands */
+ CFE_FS_FileCategory_SCRIPT, /**< Text-based Script files (e.g. ES startup script) */
+ CFE_FS_FileCategory_TEMP, /**< Temporary/Ephemeral files */
+ CFE_FS_FileCategory_MAX /**< Placeholder, keep last */
+} CFE_FS_FileCategory_t;
+
+/*
+ * Because FS is a library not an app, it does not have its own context or
+ * event IDs. The file writer runs in the context of the ES background task
+ * on behalf of whatever App requested the file write.
+ *
+ * This is a list of abstract events associated with background file write jobs.
+ * An app requesting the file write must supply a callback function to translate
+ * these into its own event IDs for feedback (i.e. file complete, error conditions, etc).
+ */
+typedef enum
+{
+ CFE_FS_FileWriteEvent_UNDEFINED, /* placeholder, no-op, keep as 0 */
+
+ CFE_FS_FileWriteEvent_COMPLETE, /**< File is completed successfully */
+ CFE_FS_FileWriteEvent_CREATE_ERROR, /**< Unable to create/open file */
+ CFE_FS_FileWriteEvent_HEADER_WRITE_ERROR, /**< Unable to write FS header */
+ CFE_FS_FileWriteEvent_RECORD_WRITE_ERROR, /**< Unable to write data record */
+
+ CFE_FS_FileWriteEvent_MAX /* placeholder, no-op, keep last */
+
+} CFE_FS_FileWriteEvent_t;
+
+/**
+ * Data Getter routine provided by requester
+ *
+ * Outputs a data block. Should return true if the file is complete (last record/EOF), otherwise return false.
+ */
+typedef bool (*CFE_FS_FileWriteGetData_t)(void *Meta, uint32 RecordNum, void **Buffer, size_t *BufSize);
+
+/**
+ * Event generator routine provided by requester
+ *
+ * Invoked from certain points in the file write process. Implementation may invoke CFE_EVS_SendEvent() appropriately
+ * to inform of progress.
+ */
+typedef void (*CFE_FS_FileWriteOnEvent_t)(void *Meta, CFE_FS_FileWriteEvent_t Event, int32 Status, uint32 RecordNum,
+ size_t BlockSize, size_t Position);
+
+/**
+ * \brief External Metadata/State object associated with background file writes
+ *
+ * Applications intending to schedule background file write jobs should instantiate
+ * this object in static/global data memory. This keeps track of the state of the
+ * file write request(s).
+ */
+typedef struct CFE_FS_FileWriteMetaData
+{
+ volatile bool IsPending; /**< Whether request is pending (volatile as it may be checked outside lock) */
+
+ char FileName[OS_MAX_PATH_LEN]; /**< Name of file to write */
+
+ /* Data for FS header */
+ uint32 FileSubType; /**< Type of file to write (for FS header) */
+ char Description[CFE_FS_HDR_DESC_MAX_LEN]; /**< Description of file (for FS header) */
+
+ CFE_FS_FileWriteGetData_t GetData; /**< Application callback to get a data record */
+ CFE_FS_FileWriteOnEvent_t OnEvent; /**< Application callback for abstract event processing */
+
+} CFE_FS_FileWriteMetaData_t;
+
+#endif /* CFE_FS_API_TYPEDEFS_H */
diff --git a/modules/core_api/fsw/inc/cfe_fs_core_internal.h b/modules/core_api/fsw/inc/cfe_fs_core_internal.h
new file mode 100644
index 000000000..ee1f8768d
--- /dev/null
+++ b/modules/core_api/fsw/inc/cfe_fs_core_internal.h
@@ -0,0 +1,60 @@
+/*
+** GSC-18128-1, "Core Flight Executive Version 6.7"
+**
+** Copyright (c) 2006-2019 United States Government as represented by
+** the Administrator of the National Aeronautics and Space Administration.
+** All Rights Reserved.
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+/**
+ * @file
+ *
+ * Purpose: cFE File Services (FS) library API header file
+ *
+ * Author: S.Walling/Microtel
+ *
+ */
+
+#ifndef CFE_FS_CORE_INTERNAL_H
+#define CFE_FS_CORE_INTERNAL_H
+
+#include "common_types.h"
+
+/*
+ * The internal APIs prototyped within this block are only intended to be invoked from
+ * other CFE core apps. They still need to be prototyped in the shared header such that
+ * they can be called from other core modules, but applications should not call these.
+ */
+
+/** @defgroup CFEAPIFSCoreInternal cFE Internal File Service APIs, internal to CFE core
+ * @{
+ */
+
+/*****************************************************************************/
+/**
+** \brief Initializes the cFE core module API Library
+**
+** \par Description
+** Initializes the cFE core module API Library
+**
+** \par Assumptions, External Events, and Notes:
+** -# This function MUST be called before any module API's are called.
+**
+******************************************************************************/
+extern int32 CFE_FS_EarlyInit(void);
+
+/**@}*/
+
+#endif /* CFE_FS_CORE_INTERNAL_H */
diff --git a/modules/core_api/fsw/inc/cfe_fs_extern_typedefs.h b/modules/core_api/fsw/inc/cfe_fs_extern_typedefs.h
new file mode 100644
index 000000000..d1780b544
--- /dev/null
+++ b/modules/core_api/fsw/inc/cfe_fs_extern_typedefs.h
@@ -0,0 +1,230 @@
+/*
+** GSC-18128-1, "Core Flight Executive Version 6.7"
+**
+** Copyright (c) 2006-2019 United States Government as represented by
+** the Administrator of the National Aeronautics and Space Administration.
+** All Rights Reserved.
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+/**
+ * @file
+ *
+ * Declarations and prototypes for cfe_fs_extern_typedefs module
+ */
+
+#ifndef CFE_FS_EXTERN_TYPEDEFS_H
+#define CFE_FS_EXTERN_TYPEDEFS_H
+
+/* This header may be generated from an EDS file,
+ * tools are available and the feature is enabled */
+#ifdef CFE_EDS_ENABLED_BUILD
+
+/* Use the EDS generated version of these types */
+#include "cfe_fs_eds_typedefs.h"
+
+#else
+/* Use the local definitions of these types */
+
+#include "common_types.h"
+
+/******************* Macro Definitions ***********************/
+
+/*
+ * NOTE: the value of CFE_FS_HDR_DESC_MAX_LEN, if modified, should
+ * be constrained to multiples of 4, as it is used within a structure that
+ * also contains uint32 types. This ensures that the entire structure
+ * remains 32-bit aligned without the need for implicit padding bytes.
+ */
+
+#define CFE_FS_HDR_DESC_MAX_LEN 32 /**< \brief Max length of description field in a standard cFE File Header */
+
+#define CFE_FS_FILE_CONTENT_ID 0x63464531 /**< \brief Magic Number for cFE compliant files (= 'cFE1') */
+
+/**
+ * @brief Label definitions associated with CFE_FS_SubType_Enum_t
+ */
+enum CFE_FS_SubType
+{
+
+ /**
+ * @brief Executive Services Exception/Reset Log Type
+ *
+ * Executive Services Exception/Reset Log File which is generated in response to a
+ * \link #CFE_ES_WRITE_ER_LOG_CC \ES_WRITEERLOG2FILE \endlink
+ * command.
+ *
+ */
+ CFE_FS_SubType_ES_ERLOG = 1,
+
+ /**
+ * @brief Executive Services System Log Type
+ *
+ * Executive Services System Log File which is generated in response to a
+ * \link #CFE_ES_WRITE_SYSLOG_CC \ES_WRITESYSLOG2FILE \endlink
+ * command.
+ *
+ */
+ CFE_FS_SubType_ES_SYSLOG = 2,
+
+ /**
+ * @brief Executive Services Information on All Applications File
+ *
+ * Executive Services Information on All Applications File which is generated in response to a
+ * \link #CFE_ES_QUERY_ALL_CC \ES_WRITEAPPINFO2FILE \endlink
+ * command.
+ *
+ */
+ CFE_FS_SubType_ES_QUERYALL = 3,
+
+ /**
+ * @brief Executive Services Performance Data File
+ *
+ * Executive Services Performance Analyzer Data File which is generated in response to a
+ * \link #CFE_ES_STOP_PERF_DATA_CC \ES_STOPLADATA \endlink
+ * command.
+ *
+ */
+ CFE_FS_SubType_ES_PERFDATA = 4,
+
+ /**
+ * @brief Executive Services Shell Response File
+ *
+ * Executive Services Shell Response Data File which is generated in response to a
+ * shell command.
+ *
+ */
+ CFE_FS_SubType_ES_SHELL = 5,
+
+ /**
+ * @brief Executive Services Critical Data Store Registry Dump File
+ *
+ * Executive Services Critical Data Store Registry Dump File which is generated in response to a
+ * \link #CFE_ES_DUMP_CDS_REGISTRY_CC \ES_DUMPCDSREG \endlink
+ * command.
+ *
+ */
+ CFE_FS_SubType_ES_CDS_REG = 6,
+
+ /**
+ * @brief Table Services Registry Dump File
+ *
+ * Table Services Registry Dump File which is generated in response to a
+ * \link #CFE_TBL_DUMP_REGISTRY_CC \TBL_WRITEREG2FILE \endlink
+ * command.
+ *
+ */
+ CFE_FS_SubType_TBL_REG = 9,
+
+ /**
+ * @brief Table Services Table Image File
+ *
+ * Table Services Table Image File which is generated either on the ground or in response to a
+ * \link #CFE_TBL_DUMP_CC \TBL_DUMP \endlink command.
+ *
+ */
+ CFE_FS_SubType_TBL_IMG = 8,
+
+ /**
+ * @brief Event Services Application Data Dump File
+ *
+ * Event Services Application Data Dump File which is generated in response to a
+ * \link #CFE_EVS_WRITE_APP_DATA_FILE_CC \EVS_WRITEAPPDATA2FILE \endlink
+ * command.
+ *
+ */
+ CFE_FS_SubType_EVS_APPDATA = 15,
+
+ /**
+ * @brief Event Services Local Event Log Dump File
+ *
+ * Event Services Local Event Log Dump File which is generated in response to a
+ * \link #CFE_EVS_WRITE_LOG_DATA_FILE_CC \EVS_WRITELOG2FILE \endlink
+ * command.
+ *
+ */
+ CFE_FS_SubType_EVS_EVENTLOG = 16,
+
+ /**
+ * @brief Software Bus Pipe Data Dump File
+ *
+ * Software Bus Pipe Data Dump File which is generated in response to a
+ * \link #CFE_SB_WRITE_PIPE_INFO_CC \SB_WRITEPIPE2FILE \endlink
+ * command.
+ *
+ */
+ CFE_FS_SubType_SB_PIPEDATA = 20,
+
+ /**
+ * @brief Software Bus Message Routing Data Dump File
+ *
+ * Software Bus Message Routing Data Dump File which is generated in response to a
+ * \link #CFE_SB_WRITE_ROUTING_INFO_CC \SB_WRITEROUTING2FILE \endlink
+ * command.
+ *
+ */
+ CFE_FS_SubType_SB_ROUTEDATA = 21,
+
+ /**
+ * @brief Software Bus Message Mapping Data Dump File
+ *
+ * Software Bus Message Mapping Data Dump File which is generated in response to a
+ * \link #CFE_SB_WRITE_MAP_INFO_CC \SB_WRITEMAP2FILE \endlink
+ * command.
+ *
+ */
+ CFE_FS_SubType_SB_MAPDATA = 22,
+
+ /**
+ * @brief Executive Services Query All Tasks Data File
+ *
+ * Executive Services Query All Tasks Data File which is generated in response to a
+ * \link #CFE_ES_QUERY_ALL_TASKS_CC \ES_WRITETASKINFO2FILE \endlink
+ * command.
+ *
+ */
+ CFE_FS_SubType_ES_QUERYALLTASKS = 23
+};
+
+/**
+ * @brief Content descriptor for File Headers
+ *
+ * @sa enum CFE_FS_SubType
+ */
+typedef uint32 CFE_FS_SubType_Enum_t;
+
+/**
+** \brief Standard cFE File header structure definition
+*/
+typedef struct CFE_FS_Header
+{
+ uint32 ContentType; /**< \brief Identifies the content type (='cFE1'=0x63464531)*/
+ uint32 SubType; /**< \brief Type of \c ContentType, if necessary */
+ /**< Standard SubType definitions can be found
+ \link #CFE_FS_SubType_ES_ERLOG here \endlink */
+ uint32 Length; /**< \brief Length of primary header */
+ uint32 SpacecraftID; /**< \brief Spacecraft that generated the file */
+ uint32 ProcessorID; /**< \brief Processor that generated the file */
+ uint32 ApplicationID; /**< \brief Application that generated the file */
+
+ uint32 TimeSeconds; /**< \brief File creation timestamp (seconds) */
+ uint32 TimeSubSeconds; /**< \brief File creation timestamp (sub-seconds) */
+
+ char Description[CFE_FS_HDR_DESC_MAX_LEN]; /**< \brief File description */
+
+} CFE_FS_Header_t;
+
+#endif /* CFE_EDS_ENABLED_BUILD */
+
+#endif /* CFE_FS_EXTERN_TYPEDEFS_H */
diff --git a/modules/fs/fsw/src/cfe_fs_api.c b/modules/fs/fsw/src/cfe_fs_api.c
new file mode 100644
index 000000000..b3703eedf
--- /dev/null
+++ b/modules/fs/fsw/src/cfe_fs_api.c
@@ -0,0 +1,886 @@
+/*
+** GSC-18128-1, "Core Flight Executive Version 6.7"
+**
+** Copyright (c) 2006-2019 United States Government as represented by
+** the Administrator of the National Aeronautics and Space Administration.
+** All Rights Reserved.
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+/*
+** File: cfe_fs_api.c
+**
+** Purpose: cFE File Services (FS) library API source file
+**
+** Author: S.Walling/Microtel
+**
+** Notes:
+**
+*/
+
+/*
+** Required header files...
+*/
+#include "cfe_fs_module_all.h"
+
+#include
+
+/* The target config allows refs into global CONFIGDATA object(s) */
+#include "target_config.h"
+
+/*
+ * Fixed default file system extensions (not platform dependent)
+ */
+const char CFE_FS_DEFAULT_SCRIPT_EXTENSION[] = ".scr";
+const char CFE_FS_DEFAULT_DUMP_FILE_EXTENSION[] = ".dat";
+const char CFE_FS_DEFAULT_TEMP_FILE_EXTENSION[] = ".tmp";
+const char CFE_FS_DEFAULT_LOG_FILE_EXTENSION[] = ".log";
+
+const char *CFE_FS_GetDefaultMountPoint(CFE_FS_FileCategory_t FileCategory)
+{
+ const char *Result;
+
+ switch (FileCategory)
+ {
+ case CFE_FS_FileCategory_SCRIPT:
+ case CFE_FS_FileCategory_DYNAMIC_MODULE:
+ /* scripts and app/lib modules reside in the non-volatile/CF mount by default */
+ Result = GLOBAL_CFE_CONFIGDATA.NonvolMountPoint;
+ break;
+ case CFE_FS_FileCategory_TEMP:
+ case CFE_FS_FileCategory_BINARY_DATA_DUMP:
+ case CFE_FS_FileCategory_TEXT_LOG:
+ /* temporary and data dump files are put in the RAM DISK mount by default */
+ Result = GLOBAL_CFE_CONFIGDATA.RamdiskMountPoint;
+ break;
+ default:
+ Result = NULL; /* Should not be used */
+ break;
+ }
+
+ return Result;
+}
+
+const char *CFE_FS_GetDefaultExtension(CFE_FS_FileCategory_t FileCategory)
+{
+ const char *Result;
+
+ switch (FileCategory)
+ {
+ case CFE_FS_FileCategory_SCRIPT:
+ Result = CFE_FS_DEFAULT_SCRIPT_EXTENSION;
+ break;
+ case CFE_FS_FileCategory_DYNAMIC_MODULE:
+ /* app/lib modules use a platform-specific extension, and the
+ * default is derived from the build system */
+ Result = GLOBAL_CONFIGDATA.Default_ModuleExtension;
+ break;
+ case CFE_FS_FileCategory_TEMP:
+ Result = CFE_FS_DEFAULT_TEMP_FILE_EXTENSION;
+ break;
+ case CFE_FS_FileCategory_BINARY_DATA_DUMP:
+ Result = CFE_FS_DEFAULT_DUMP_FILE_EXTENSION;
+ break;
+ case CFE_FS_FileCategory_TEXT_LOG:
+ Result = CFE_FS_DEFAULT_LOG_FILE_EXTENSION;
+ break;
+ default:
+ Result = NULL; /* Should not be used */
+ break;
+ }
+
+ return Result;
+}
+
+/*
+** CFE_FS_ReadHeader() - See API and header file for details
+*/
+int32 CFE_FS_ReadHeader(CFE_FS_Header_t *Hdr, osal_id_t FileDes)
+{
+ int32 Result;
+ int32 EndianCheck = 0x01020304;
+
+ if (Hdr == NULL)
+ {
+ return CFE_FS_BAD_ARGUMENT;
+ }
+
+ /*
+ ** Ensure that we are at the start of the file...
+ */
+ Result = OS_lseek(FileDes, 0, OS_SEEK_SET);
+
+ if (Result == OS_SUCCESS)
+ {
+ /*
+ ** Read header structure into callers buffer...
+ */
+ Result = OS_read(FileDes, Hdr, sizeof(CFE_FS_Header_t));
+
+ /* Determine if this processor is a little endian processor */
+ if ((*(char *)(&EndianCheck)) == 0x04)
+ {
+ /* If this is a little endian processor, then convert the header data structure from */
+ /* its standard big-endian format into a little endian format to ease user access */
+ CFE_FS_ByteSwapCFEHeader(Hdr);
+ }
+ }
+
+ return (Result);
+
+} /* End of CFE_FS_ReadHeader() */
+
+/*
+** CFE_FS_InitHeader() - See API and header file for details
+*/
+void CFE_FS_InitHeader(CFE_FS_Header_t *Hdr, const char *Description, uint32 SubType)
+{
+ if (Hdr == NULL || Description == NULL)
+ {
+ CFE_ES_WriteToSysLog("CFE_FS:InitHeader-Failed invalid arguments\n");
+ }
+ else
+ {
+ memset(Hdr, 0, sizeof(CFE_FS_Header_t));
+ strncpy((char *)Hdr->Description, Description, sizeof(Hdr->Description) - 1);
+ Hdr->SubType = SubType;
+ }
+}
+
+/*
+** CFE_FS_WriteHeader() - See API and header file for details
+*/
+int32 CFE_FS_WriteHeader(osal_id_t FileDes, CFE_FS_Header_t *Hdr)
+{
+ CFE_TIME_SysTime_t Time;
+ int32 Result;
+ int32 EndianCheck = 0x01020304;
+ CFE_ES_AppId_t AppID;
+
+ if (Hdr == NULL)
+ {
+ return CFE_FS_BAD_ARGUMENT;
+ }
+
+ /*
+ ** Ensure that we are at the start of the file...
+ */
+ Result = OS_lseek(FileDes, 0, OS_SEEK_SET);
+
+ if (Result == OS_SUCCESS)
+ {
+ /*
+ ** Fill in the ID fields...
+ */
+ Hdr->SpacecraftID = CFE_PSP_GetSpacecraftId();
+ Hdr->ProcessorID = CFE_PSP_GetProcessorId();
+ CFE_ES_GetAppID(&AppID);
+ Hdr->ApplicationID = CFE_RESOURCEID_TO_ULONG(AppID);
+
+ /* Fill in length field */
+
+ Hdr->Length = sizeof(CFE_FS_Header_t);
+
+ /* put the header, 'cfe1' in hex, in to the content type */
+ Hdr->ContentType = 0x63464531;
+
+ /*
+ ** Fill in the timestamp fields...
+ */
+ Time = CFE_TIME_GetTime();
+ Hdr->TimeSeconds = Time.Seconds;
+ Hdr->TimeSubSeconds = Time.Subseconds;
+
+ /*
+ ** Determine if this is a little endian processor
+ */
+ if ((*(char *)(&EndianCheck)) == 0x04)
+ {
+ /* If this is a little endian processor, then convert the header data structure from */
+ /* the native little endian format to the required CFE standard big endian format */
+ CFE_FS_ByteSwapCFEHeader(Hdr);
+ }
+
+ /*
+ ** Write header structure from callers buffer...
+ */
+ Result = OS_write(FileDes, Hdr, sizeof(CFE_FS_Header_t));
+
+ /*
+ ** Determine if this is a little endian processor
+ */
+ if ((*(char *)(&EndianCheck)) == 0x04)
+ {
+ /* If this is a little endian processor, then convert the header data structure back */
+ /* from the required CFE standard big endian format to the little endian format */
+ CFE_FS_ByteSwapCFEHeader(Hdr);
+ }
+ }
+
+ return (Result);
+
+} /* End of CFE_FS_WriteHeader() */
+
+/*
+** CFE_FS_SetTimestamp - See API and header file for details
+*/
+int32 CFE_FS_SetTimestamp(osal_id_t FileDes, CFE_TIME_SysTime_t NewTimestamp)
+{
+ int32 Result;
+ CFE_FS_Header_t TempHdr;
+ int32 EndianCheck = 0x01020304;
+ CFE_TIME_SysTime_t OutTimestamp = NewTimestamp;
+ int32 FileOffset = 0;
+
+ FileOffset = ((char *)&TempHdr.TimeSeconds - (char *)&TempHdr.ContentType);
+ Result = OS_lseek(FileDes, FileOffset, OS_SEEK_SET);
+
+ if (Result == FileOffset)
+ {
+ /*
+ ** Determine if this is a little endian processor
+ */
+ if ((*(char *)(&EndianCheck)) == 0x04)
+ {
+ /* If this processor is a little endian processor, then convert the timestamp to a big */
+ /* endian format so that it is compatible with the standard cFE File Header format */
+ CFE_FS_ByteSwapUint32(&OutTimestamp.Seconds);
+ CFE_FS_ByteSwapUint32(&OutTimestamp.Subseconds);
+ }
+
+ Result = OS_write(FileDes, &OutTimestamp.Seconds, sizeof(OutTimestamp.Seconds));
+
+ /* On a good write, the value returned will equal the number of bytes written */
+ if (Result == sizeof(OutTimestamp.Seconds))
+ {
+ Result = OS_write(FileDes, &OutTimestamp.Subseconds, sizeof(OutTimestamp.Subseconds));
+
+ if (Result == sizeof(OutTimestamp.Subseconds))
+ {
+ Result = OS_SUCCESS;
+ }
+ else
+ {
+ CFE_ES_WriteToSysLog("CFE_FS:SetTime-Failed to write Seconds (Status=0x%08X)\n", (unsigned int)Result);
+ }
+ }
+ else
+ {
+ CFE_ES_WriteToSysLog("CFE_FS:SetTime-Failed to write Seconds (Status=0x%08X)\n", (unsigned int)Result);
+ }
+ }
+ else
+ {
+ CFE_ES_WriteToSysLog("CFE_FS:SetTime-Failed to lseek time fields (Status=0x%08X)\n", (unsigned int)Result);
+ }
+
+ return (Result);
+} /* End of CFE_FS_SetTimestamp() */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+/* */
+/* CFE_FS_ByteSwapCFEHeader() -- byte swap cFE file header structure */
+/* */
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+void CFE_FS_ByteSwapCFEHeader(CFE_FS_Header_t *Hdr)
+{
+ CFE_FS_ByteSwapUint32(&Hdr->ContentType);
+ CFE_FS_ByteSwapUint32(&Hdr->SubType);
+ CFE_FS_ByteSwapUint32(&Hdr->Length);
+ CFE_FS_ByteSwapUint32(&Hdr->SpacecraftID);
+ CFE_FS_ByteSwapUint32(&Hdr->ProcessorID);
+ CFE_FS_ByteSwapUint32(&Hdr->ApplicationID);
+ CFE_FS_ByteSwapUint32(&Hdr->TimeSeconds);
+ CFE_FS_ByteSwapUint32(&Hdr->TimeSubSeconds);
+
+} /* End of CFE_FS_ByteSwapCFEHeader() */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+/* */
+/* CFE_FS_ByteSwapUint32() -- byte swap an uint32 */
+/* */
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+void CFE_FS_ByteSwapUint32(uint32 *Uint32ToSwapPtr)
+{
+ int32 Temp = *Uint32ToSwapPtr;
+ char *InPtr = (char *)&Temp;
+ char *OutPtr = (char *)Uint32ToSwapPtr;
+
+ OutPtr[0] = InPtr[3];
+ OutPtr[1] = InPtr[2];
+ OutPtr[2] = InPtr[1];
+ OutPtr[3] = InPtr[0];
+} /* End of CFE_FS_ByteSwapUint32() */
+
+/*
+**---------------------------------------------------------------------------------------
+** Name: CFE_FS_ParseInputFileNameEx
+**
+** Purpose: This reads a file name from user input with extra logic to make more user friendly
+** - absolute path is optional; assume default dir if missing
+** - module extension is optional; append default for OS/platform if missing
+**---------------------------------------------------------------------------------------
+*/
+int32 CFE_FS_ParseInputFileNameEx(char *OutputBuffer, const char *InputBuffer, size_t OutputBufSize,
+ size_t InputBufSize, const char *DefaultInput, const char *DefaultPath,
+ const char *DefaultExtension)
+{
+ int32 Status;
+ const char *InputPtr;
+ const char *ComponentPtr;
+ size_t ComponentLen;
+ char ComponentTerm;
+ size_t OutputLen;
+ size_t InputLen;
+ bool LastPathReached;
+
+ /* The filename consists of a pathname, filename, and extension component. */
+ enum
+ {
+ PROCESS_INIT,
+ PATHNAME_COMPONENT,
+ PATHNAME_SEPARATOR,
+ FILENAME_COMPONENT,
+ EXTENSION_SEPARATOR,
+ EXTENSION_COMPONENT,
+ END_COMPONENT
+ } Component;
+
+ /* Sanity check buffer input */
+ if (OutputBuffer == NULL || OutputBufSize == 0)
+ {
+ return CFE_FS_BAD_ARGUMENT;
+ }
+
+ Status = CFE_FS_INVALID_PATH;
+ OutputLen = 0;
+ ComponentTerm = 0;
+ LastPathReached = false;
+
+ /* If input buffer is not empty, then use it, otherwise use DefaultInput */
+ if (InputBuffer != NULL && InputBufSize > 0 && InputBuffer[0] != 0)
+ {
+ InputPtr = InputBuffer;
+ InputLen = InputBufSize;
+ }
+ else if (DefaultInput != NULL)
+ {
+ /* This must be a normal null terminated string */
+ InputPtr = DefaultInput;
+ InputLen = strlen(DefaultInput);
+ }
+ else
+ {
+ /* No input */
+ InputPtr = NULL;
+ InputLen = 0;
+ }
+
+ Component = PROCESS_INIT;
+ while (InputPtr != NULL && Component < END_COMPONENT)
+ {
+ /* Move to next component */
+ if (Component == PATHNAME_SEPARATOR && !LastPathReached)
+ {
+ /* repeat until LastPathReached */
+ Component = PATHNAME_COMPONENT;
+ }
+ else
+ {
+ ++Component;
+ }
+
+ switch (Component)
+ {
+ case PATHNAME_COMPONENT:
+ /* path part ends with the last / char, which begins the filename */
+ ComponentTerm = '/';
+ ComponentPtr = memchr(InputPtr, ComponentTerm, InputLen);
+ if (ComponentPtr != NULL)
+ {
+ /* has path: use pathname from input, advance InputPtr to next part (filename) */
+ ComponentLen = ComponentPtr - InputPtr;
+ ComponentPtr = InputPtr;
+ InputPtr += ComponentLen;
+ InputLen -= ComponentLen;
+ }
+ else
+ {
+ LastPathReached = true;
+
+ /* no path: if no output at all yet, use default pathname, otherwise move on. */
+ if (DefaultPath != NULL && OutputLen == 0)
+ {
+ ComponentLen = strlen(DefaultPath);
+ ComponentPtr = DefaultPath;
+ }
+ else
+ {
+ /* use no pathname at all */
+ ComponentLen = 0;
+ ComponentPtr = NULL;
+ }
+ }
+ break;
+
+ case FILENAME_COMPONENT:
+ /* filename ends with a . char, which begins the extension */
+ ComponentTerm = '.';
+ ComponentPtr = memchr(InputPtr, ComponentTerm, InputLen);
+ if (ComponentPtr != NULL)
+ {
+ /* has ext: use pathname from input, advance InputPtr to next part (extension) */
+ ComponentLen = ComponentPtr - InputPtr;
+ ComponentPtr = InputPtr;
+ InputPtr += ComponentLen;
+ InputLen -= ComponentLen;
+ }
+ else
+ {
+ /* no ext: use remainder of input here - then use default extension for next part */
+ ComponentLen = InputLen;
+ ComponentPtr = InputPtr;
+ if (DefaultExtension != NULL)
+ {
+ InputPtr = DefaultExtension;
+ InputLen = strlen(DefaultExtension);
+ }
+ else
+ {
+ /* Use no extension */
+ InputPtr = NULL;
+ InputLen = 0;
+ }
+ }
+
+ if (ComponentLen > 0 && *ComponentPtr != 0)
+ {
+ /*
+ * If the filename part is non-empty, then consider the conversion successful
+ * (note that extension is not really needed for an acceptable filename)
+ */
+ Status = CFE_SUCCESS;
+ }
+
+ break;
+
+ case PATHNAME_SEPARATOR:
+ case EXTENSION_SEPARATOR:
+ /* Remove duplicate terminators that may have been in the input */
+ while (OutputLen > 0 && OutputBuffer[OutputLen - 1] == ComponentTerm)
+ {
+ --OutputLen;
+ }
+
+ ComponentLen = 1;
+ ComponentPtr = &ComponentTerm;
+
+ /* advance past any separators in input to get to the next content */
+ while (*InputPtr == ComponentTerm && InputLen > 0)
+ {
+ ++InputPtr;
+ --InputLen;
+ }
+ break;
+
+ case EXTENSION_COMPONENT:
+ /* Intentional fall through to default case */
+
+ default:
+ /* Just consume the rest of input -
+ * should already be pointing to correct data */
+ ComponentTerm = 0;
+ ComponentLen = InputLen;
+ ComponentPtr = InputPtr;
+ InputPtr = NULL; /* no more input */
+ InputLen = 0;
+ break;
+ }
+
+ /* Append component */
+ while (ComponentLen > 0 && *ComponentPtr != 0)
+ {
+ OutputBuffer[OutputLen] = *ComponentPtr;
+ ++ComponentPtr;
+ ++OutputLen;
+ --ComponentLen;
+
+ if (OutputLen >= OutputBufSize)
+ {
+ /* name is too long to fit in output buffer */
+ Status = CFE_FS_FNAME_TOO_LONG;
+ InputPtr = NULL; /* no more input */
+ InputLen = 0;
+ --OutputLen; /* back up one char for term */
+ break;
+ }
+ }
+ }
+
+ /*
+ * Always add a final terminating NUL char.
+ *
+ * Note that the loop above should never entirely fill
+ * buffer (length check includes extra char).
+ */
+ OutputBuffer[OutputLen] = 0;
+
+ return Status;
+}
+
+/*
+**---------------------------------------------------------------------------------------
+** Name: CFE_FS_ParseInputFileName
+**
+** Purpose: Simplified API for CFE_FS_ParseInputFileNameEx where input is always known to be
+** a non-empty, null terminated string and the fixed-length input buffer not needed.
+**---------------------------------------------------------------------------------------
+*/
+int32 CFE_FS_ParseInputFileName(char *OutputBuffer, const char *InputName, size_t OutputBufSize,
+ CFE_FS_FileCategory_t FileCategory)
+{
+ return CFE_FS_ParseInputFileNameEx(OutputBuffer, NULL, OutputBufSize, 0, InputName,
+ CFE_FS_GetDefaultMountPoint(FileCategory),
+ CFE_FS_GetDefaultExtension(FileCategory));
+}
+
+/*
+** CFE_FS_ExtractFilenameFromPath - See API and header file for details
+*/
+int32 CFE_FS_ExtractFilenameFromPath(const char *OriginalPath, char *FileNameOnly)
+{
+ uint32 i, j;
+ int StringLength;
+ int DirMarkIdx;
+ int32 ReturnCode;
+
+ if (OriginalPath == NULL || FileNameOnly == NULL)
+ {
+ ReturnCode = CFE_FS_BAD_ARGUMENT;
+ }
+ else
+ {
+
+ /*
+ ** Get the string length of the original file path
+ */
+ StringLength = strlen(OriginalPath);
+
+ /*
+ ** Extract the filename from the Path
+ */
+
+ /*
+ ** Find the last '/' Character
+ */
+ DirMarkIdx = -1;
+ for (i = 0; i < StringLength; i++)
+ {
+ if (OriginalPath[i] == '/')
+ {
+ DirMarkIdx = i;
+ }
+ }
+
+ /*
+ ** Verify the filename isn't too long
+ */
+ if ((StringLength - (DirMarkIdx + 1)) < OS_MAX_PATH_LEN)
+ {
+ /*
+ ** Extract the filename portion
+ */
+ if (DirMarkIdx > 0)
+ {
+ /*
+ ** Extract the filename portion
+ */
+ j = 0;
+ for (i = DirMarkIdx + 1; i < StringLength; i++)
+ {
+ FileNameOnly[j] = OriginalPath[i];
+ j++;
+ }
+ FileNameOnly[j] = '\0';
+
+ ReturnCode = CFE_SUCCESS;
+ }
+ else
+ {
+ ReturnCode = CFE_FS_INVALID_PATH;
+ }
+ }
+ else
+ {
+ ReturnCode = CFE_FS_FNAME_TOO_LONG;
+ }
+ }
+
+ return (ReturnCode);
+}
+
+/*
+** CFE_FS_RunBackgroundFileDump - See API and header file for details
+*/
+bool CFE_FS_RunBackgroundFileDump(uint32 ElapsedTime, void *Arg)
+{
+ CFE_FS_CurrentFileState_t * State;
+ CFE_FS_BackgroundFileDumpEntry_t *Curr;
+ CFE_FS_FileWriteMetaData_t * Meta;
+ int32 Status;
+ CFE_FS_Header_t FileHdr;
+ void * RecordPtr;
+ size_t RecordSize;
+ bool IsEOF;
+
+ State = &CFE_FS_Global.FileDump.Current;
+ Curr = NULL;
+ IsEOF = false;
+ RecordPtr = NULL;
+ RecordSize = 0;
+
+ State->Credit += (ElapsedTime * CFE_FS_BACKGROUND_CREDIT_PER_SECOND) / 1000;
+ if (State->Credit > CFE_FS_BACKGROUND_MAX_CREDIT)
+ {
+ State->Credit = CFE_FS_BACKGROUND_MAX_CREDIT;
+ }
+
+ /*
+ * Lock shared data.
+ * Not strictly necessary as the "CompleteCount" is only updated
+ * by this task but this helps in case the access isn't atomic.
+ */
+ CFE_FS_LockSharedData(__func__);
+
+ if (CFE_FS_Global.FileDump.CompleteCount != CFE_FS_Global.FileDump.RequestCount)
+ {
+ Curr = &CFE_FS_Global.FileDump
+ .Entries[CFE_FS_Global.FileDump.CompleteCount & (CFE_FS_MAX_BACKGROUND_FILE_WRITES - 1)];
+ }
+
+ CFE_FS_UnlockSharedData(__func__);
+
+ if (Curr == NULL)
+ {
+ return false;
+ }
+
+ Meta = Curr->Meta;
+
+ if (!OS_ObjectIdDefined(State->Fd) && Meta->IsPending)
+ {
+ /* First time processing this entry - open the file */
+ Status = OS_OpenCreate(&State->Fd, Meta->FileName, OS_FILE_FLAG_CREATE | OS_FILE_FLAG_TRUNCATE, OS_WRITE_ONLY);
+ if (Status < 0)
+ {
+ State->Fd = OS_OBJECT_ID_UNDEFINED;
+ Meta->OnEvent(Meta, CFE_FS_FileWriteEvent_CREATE_ERROR, Status, 0, 0, 0);
+ }
+ else
+ {
+ CFE_FS_InitHeader(&FileHdr, Meta->Description, Meta->FileSubType);
+
+ /* write the cFE header to the file */
+ Status = CFE_FS_WriteHeader(State->Fd, &FileHdr);
+ if (Status != sizeof(CFE_FS_Header_t))
+ {
+ OS_close(State->Fd);
+ State->Fd = OS_OBJECT_ID_UNDEFINED;
+ Meta->OnEvent(Meta, CFE_FS_FileWriteEvent_HEADER_WRITE_ERROR, Status, State->RecordNum,
+ sizeof(CFE_FS_Header_t), State->FileSize);
+ }
+ else
+ {
+ State->FileSize = sizeof(CFE_FS_Header_t);
+ State->Credit -= sizeof(CFE_FS_Header_t);
+ State->RecordNum = 0;
+ }
+ }
+ }
+
+ while (OS_ObjectIdDefined(State->Fd) && State->Credit > 0 && !IsEOF)
+ {
+ /*
+ * Getter should return false on EOF (last record), true if more data is still waiting
+ */
+ IsEOF = Meta->GetData(Meta, State->RecordNum, &RecordPtr, &RecordSize);
+
+ /*
+ * if the getter outputs a record size of 0, this means there is no data for
+ * this entry, but the cycle keeps going (in case of "holes" or unused table entries
+ * in the database).
+ */
+ if (RecordSize > 0)
+ {
+ State->Credit -= RecordSize;
+
+ /*
+ * Now write to file
+ */
+ Status = OS_write(State->Fd, RecordPtr, RecordSize);
+
+ if (Status != RecordSize)
+ {
+ /* end the file early (cannot set "IsEOF" as this would cause the complete event to be generated too) */
+ OS_close(State->Fd);
+ State->Fd = OS_OBJECT_ID_UNDEFINED;
+
+ /* generate write error event */
+ Meta->OnEvent(Meta, CFE_FS_FileWriteEvent_RECORD_WRITE_ERROR, Status, State->RecordNum, RecordSize,
+ State->FileSize);
+ break;
+ }
+ else
+ {
+ State->FileSize += RecordSize;
+ }
+ }
+
+ ++State->RecordNum;
+
+ } /* end if */
+
+ /* On normal EOF close the file and generate the complete event */
+ if (IsEOF)
+ {
+ OS_close(State->Fd);
+ State->Fd = OS_OBJECT_ID_UNDEFINED;
+
+ /* generate complete event */
+ Meta->OnEvent(Meta, CFE_FS_FileWriteEvent_COMPLETE, CFE_SUCCESS, State->RecordNum, 0, State->FileSize);
+ }
+
+ /*
+ * if the file is not open, consider this file complete, and advance the head position.
+ * (done this way so it also catches the case where the file failed to create, not just EOF)
+ */
+ if (!OS_ObjectIdDefined(State->Fd))
+ {
+ CFE_FS_LockSharedData(__func__);
+
+ /* Wipe the entry structure, as it will be reused */
+ memset(Curr, 0, sizeof(*Curr));
+ ++CFE_FS_Global.FileDump.CompleteCount;
+
+ /* Set the "IsPending" flag to false - this indicates that the originator may re-post now */
+ Meta->IsPending = false;
+
+ CFE_FS_UnlockSharedData(__func__);
+
+ } /* end if */
+
+ return !IsEOF;
+}
+
+/*
+** CFE_FS_BackgroundFileDumpRequest - See API and header file for details
+*/
+int32 CFE_FS_BackgroundFileDumpRequest(CFE_FS_FileWriteMetaData_t *Meta)
+{
+ CFE_FS_BackgroundFileDumpEntry_t *Curr;
+ int32 Status;
+ uint32 PendingRequestCount;
+
+ /* Pre-validate inputs */
+ if (Meta == NULL)
+ {
+ return CFE_FS_BAD_ARGUMENT;
+ }
+
+ /* getter and event functions must be set */
+ if (Meta->GetData == NULL || Meta->OnEvent == NULL)
+ {
+ return CFE_FS_BAD_ARGUMENT;
+ }
+
+ /* filename cannot be empty */
+ if (Meta->FileName[0] == 0)
+ {
+ return CFE_FS_INVALID_PATH;
+ }
+
+ /* request must not already be pending */
+ if (Meta->IsPending)
+ {
+ return CFE_STATUS_REQUEST_ALREADY_PENDING;
+ }
+
+ CFE_FS_LockSharedData(__func__);
+
+ PendingRequestCount = CFE_FS_Global.FileDump.RequestCount + 1;
+
+ /* Check if queue is full before writing to tail position */
+ if (PendingRequestCount == (CFE_FS_Global.FileDump.CompleteCount + CFE_FS_MAX_BACKGROUND_FILE_WRITES))
+ {
+ Status = CFE_STATUS_REQUEST_ALREADY_PENDING;
+ }
+ else
+ {
+ Curr = &CFE_FS_Global.FileDump
+ .Entries[CFE_FS_Global.FileDump.RequestCount & (CFE_FS_MAX_BACKGROUND_FILE_WRITES - 1)];
+
+ /*
+ * store the meta object - note this retains the pointer that was submitted
+ * (caller must not reuse/change this object until request is completed)
+ */
+ Curr->Meta = Meta;
+
+ /*
+ * The "IsPending" Flag will be set true whenever while this is waiting in the request queue.
+ * It will be set false when the file is done.
+ *
+ * The requester can check this flag to determine if/when the request is complete
+ */
+ Meta->IsPending = true;
+
+ /* update tail position */
+ CFE_FS_Global.FileDump.RequestCount = PendingRequestCount;
+
+ Status = CFE_SUCCESS;
+ }
+
+ CFE_FS_UnlockSharedData(__func__);
+
+ if (Status == CFE_SUCCESS)
+ {
+ /*
+ * If successfully added to write queue, then wake the ES background task to get started.
+ *
+ * This may reduce the overall latency between request and completion (depending on other
+ * background task work). If this is the only pending job, this should get it started faster.
+ */
+ CFE_ES_BackgroundWakeup();
+ }
+
+ return Status;
+}
+
+/*
+** CFE_FS_ExtractFilenameFromPath - See API and header file for details
+*/
+bool CFE_FS_BackgroundFileDumpIsPending(const CFE_FS_FileWriteMetaData_t *Meta)
+{
+ if (Meta == NULL)
+ {
+ return false;
+ }
+
+ return Meta->IsPending;
+}
+
+/************************/
+/* End of File Comment */
+/************************/
diff --git a/modules/fs/fsw/src/cfe_fs_module_all.h b/modules/fs/fsw/src/cfe_fs_module_all.h
new file mode 100644
index 000000000..9c2affb85
--- /dev/null
+++ b/modules/fs/fsw/src/cfe_fs_module_all.h
@@ -0,0 +1,41 @@
+/*
+** GSC-18128-1, "Core Flight Executive Version 6.7"
+**
+** Copyright (c) 2006-2019 United States Government as represented by
+** the Administrator of the National Aeronautics and Space Administration.
+** All Rights Reserved.
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+/**
+ * @file
+ *
+ * Encapsulates all FS module internal header files, as well
+ * as the public API from all other CFE core modules, OSAL, and PSP.
+ *
+ * This simplifies the set of include files that need to be put at the
+ * start of every source file.
+ */
+
+#ifndef CFE_FS_MODULE_ALL_H
+#define CFE_FS_MODULE_ALL_H
+
+/*
+** Includes
+*/
+#include "cfe.h"
+#include "cfe_fs_priv.h"
+#include "cfe_fs_core_internal.h"
+
+#endif /* CFE_FS_MODULE_ALL_H */
diff --git a/modules/fs/fsw/src/cfe_fs_priv.c b/modules/fs/fsw/src/cfe_fs_priv.c
new file mode 100644
index 000000000..4344aaddc
--- /dev/null
+++ b/modules/fs/fsw/src/cfe_fs_priv.c
@@ -0,0 +1,140 @@
+/*
+** GSC-18128-1, "Core Flight Executive Version 6.7"
+**
+** Copyright (c) 2006-2019 United States Government as represented by
+** the Administrator of the National Aeronautics and Space Administration.
+** All Rights Reserved.
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+/*
+** File: cfe_fs_priv.c
+**
+** Purpose: cFE File Services (FS) library API Initialization
+**
+** Author: Alan Cudmore/NASA GSFC
+**
+** Notes:
+**
+*/
+
+/*
+** Required header files
+*/
+#include "cfe_fs_module_all.h"
+
+#include
+
+/*
+** Global data
+**
+*/
+CFE_FS_Global_t CFE_FS_Global;
+
+/******************************************************************************
+** Function: CFE_FS_EarlyInit()
+**
+** Purpose:
+** Initialize the FS data structures before the cFE runs.
+**
+** Arguments:
+**
+** Notes:
+** This function MUST be called before any FS API's are called.
+**
+** Return:
+** CFE_SUCCESS
+*/
+int32 CFE_FS_EarlyInit(void)
+{
+ int32 Stat;
+
+ memset(&CFE_FS_Global, 0, sizeof(CFE_FS_Global));
+
+ Stat = OS_MutSemCreate(&CFE_FS_Global.SharedDataMutexId, "CFE_FS_SharedMutex", 0);
+ if (Stat != OS_SUCCESS)
+ {
+ CFE_ES_WriteToSysLog("FS Shared Data Mutex creation failed! RC=0x%08x\n", (unsigned int)Stat);
+ return Stat;
+ } /* end if */
+
+ return Stat;
+
+} /* end CFE_FS_EarlyInit */
+
+/******************************************************************************
+** Function: CFE_FS_LockSharedData()
+**
+** Purpose:
+** FS internal function to handle a semaphore take failure for the FS
+** Data Mutex
+**
+** Arguments:
+** FunctionName - the Function Name of the code that generated the error.
+**
+** Return:
+** None
+*/
+void CFE_FS_LockSharedData(const char *FunctionName)
+{
+ int32 Status;
+ CFE_ES_AppId_t AppId;
+
+ Status = OS_MutSemTake(CFE_FS_Global.SharedDataMutexId);
+ if (Status != OS_SUCCESS)
+ {
+ CFE_ES_GetAppID(&AppId);
+
+ CFE_ES_WriteToSysLog("FS SharedData Mutex Take Err Stat=0x%x,App=%lu,Function=%s\n", (unsigned int)Status,
+ CFE_RESOURCEID_TO_ULONG(AppId), FunctionName);
+
+ } /* end if */
+
+ return;
+
+} /* end CFE_FS_LockSharedData */
+
+/******************************************************************************
+** Function: CFE_FS_UnlockSharedData()
+**
+** Purpose:
+** FS internal function to handle a semaphore give failure for the Shared
+** Data Mutex
+**
+** Arguments:
+** FunctionName - the Function containing the code that generated the error.
+**
+** Return:
+** None
+*/
+void CFE_FS_UnlockSharedData(const char *FunctionName)
+{
+ int32 Status;
+ CFE_ES_AppId_t AppId;
+
+ Status = OS_MutSemGive(CFE_FS_Global.SharedDataMutexId);
+ if (Status != OS_SUCCESS)
+ {
+ CFE_ES_GetAppID(&AppId);
+ CFE_ES_WriteToSysLog("FS SharedData Mutex Give Err Stat=0x%x,App=%lu,Function=%s\n", (unsigned int)Status,
+ CFE_RESOURCEID_TO_ULONG(AppId), FunctionName);
+
+ } /* end if */
+ return;
+
+} /* end CFE_FS_UnlockSharedData */
+
+/************************/
+/* End of File Comment */
+/************************/
diff --git a/modules/fs/fsw/src/cfe_fs_priv.h b/modules/fs/fsw/src/cfe_fs_priv.h
new file mode 100644
index 000000000..3979d98ec
--- /dev/null
+++ b/modules/fs/fsw/src/cfe_fs_priv.h
@@ -0,0 +1,155 @@
+/*
+** GSC-18128-1, "Core Flight Executive Version 6.7"
+**
+** Copyright (c) 2006-2019 United States Government as represented by
+** the Administrator of the National Aeronautics and Space Administration.
+** All Rights Reserved.
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+/**
+ * @file
+ *
+ * Purpose:
+ * This header file contains prototypes for private functions and type
+ * definitions for FS internal use.
+ *
+ * Author: A. Cudmore/NASA GSFC
+ *
+ */
+
+#ifndef CFE_FS_PRIV_H
+#define CFE_FS_PRIV_H
+
+/*
+** Includes
+*/
+#include "common_types.h"
+#include "cfe_fs_api_typedefs.h"
+#include "cfe_es_api_typedefs.h"
+
+/*
+** Macro Definitions
+*/
+
+/*
+ * Max Number of file write requests that can be queued
+ *
+ * This needs to be a power of two to simplify the masking/wraparound (bitwise AND).
+ */
+#define CFE_FS_MAX_BACKGROUND_FILE_WRITES 4
+
+/*
+ * Background file credit accumulation rate
+ *
+ * The background file writer will limit the total bytes written over time. This
+ * controls the amount of "credit" (bytes that can be written) per second
+ * of elapsed time.
+ *
+ * This permits a file writing rate of up to 10kbytes/sec.
+ */
+#define CFE_FS_BACKGROUND_CREDIT_PER_SECOND 10000
+
+/*
+ * Maximum credit that the background write task can accumulate
+ *
+ * The background file writer will limit the total bytes written over time, and
+ * will accumulate credit against this limit while no writes are in progress.
+ * This is an upper cap on the amount of credit that can be accumulated.
+ *
+ * Without this limit, after a long period of inactivity without any file
+ * writes, a large credit would essentially bypass the rate limiting for
+ * the next file write command(s) once they are issued.
+ */
+#define CFE_FS_BACKGROUND_MAX_CREDIT 10000
+
+/*
+** Type Definitions
+*/
+
+/*
+ * Background file dump entry structure
+ *
+ * This structure is stored in global memory and keeps the state
+ * of the file dump from one iteration to the next.
+ */
+typedef struct
+{
+ CFE_ES_AppId_t RequestorAppId;
+ CFE_FS_FileWriteMetaData_t *Meta;
+} CFE_FS_BackgroundFileDumpEntry_t;
+
+typedef struct
+{
+ osal_id_t Fd;
+ int32 Credit;
+ uint32 RecordNum;
+ size_t FileSize;
+} CFE_FS_CurrentFileState_t;
+
+/**
+ * \brief Background file dump queue structure
+ *
+ * This structure is stored in global memory and keeps the state
+ * of the file dump from one iteration to the next.
+ *
+ * Normally when idle the "RequestCount" and "CompleteCount" are the
+ * same value. When an application requests a background file dump,
+ * the "RequestCount" is incremented accordingly, and when the background
+ * job finishes, the "CompleteCount" is incremented accordingly.
+ */
+typedef struct
+{
+ uint32 RequestCount; /**< Total Number of background file writes requested */
+ uint32 CompleteCount; /**< Total Number of background file writes completed */
+
+ /**
+ * Data related to each background file write request
+ */
+ CFE_FS_BackgroundFileDumpEntry_t Entries[CFE_FS_MAX_BACKGROUND_FILE_WRITES];
+
+ /**
+ * Persistent storage for the current file write
+ * (reused for each file)
+ */
+ CFE_FS_CurrentFileState_t Current;
+
+} CFE_FS_BackgroundFileDumpState_t;
+
+/******************************************************************************
+** Typedef: CFE_FS_Global_t
+**
+** Purpose:
+** This structure contains the FS global variables.
+*/
+typedef struct
+{
+ osal_id_t SharedDataMutexId;
+
+ CFE_FS_BackgroundFileDumpState_t FileDump;
+
+} CFE_FS_Global_t;
+
+extern CFE_FS_Global_t CFE_FS_Global;
+
+/*
+** FS Function Prototypes
+*/
+
+extern void CFE_FS_LockSharedData(const char *FunctionName);
+extern void CFE_FS_UnlockSharedData(const char *FunctionName);
+extern void CFE_FS_ByteSwapCFEHeader(CFE_FS_Header_t *Hdr);
+extern void CFE_FS_ByteSwapUint32(uint32 *Uint32ToSwapPtr);
+
+#endif /* CFE_FS_PRIV_H */