/* SPDX-License-Identifier: BSD-2-Clause */ /** * @file * * @brief Header File for the In-Memory File System */ /* * COPYRIGHT (C) 1989, 2021 On-Line Applications Research Corporation (OAR). * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTEMS_IMFS_H #define _RTEMS_IMFS_H #include #include #include #include #include /** * @brief In-Memory File System Support. * * @defgroup IMFS In-Memory File System Support * * @ingroup FileSystemTypesAndMount */ /**@{*/ #ifdef __cplusplus extern "C" { #endif /* * Data types */ struct IMFS_jnode_tt; typedef struct IMFS_jnode_tt IMFS_jnode_t; /** * IMFS "memfile" information * * The data structure for the in-memory "memfiles" is based on classic UNIX. * * block_ptr is a pointer to a block of IMFS_MEMFILE_BYTES_PER_BLOCK in * length which could be data or a table of pointers to blocks. * * Setting IMFS_MEMFILE_BYTES_PER_BLOCK to different values has a significant * impact on the maximum file size supported as well as the amount of * memory wasted due to internal file fragmentation. The following * is a list of maximum file sizes based on various settings * * @code * max_filesize with blocks of 16 is 1,328 * max_filesize with blocks of 32 is 18,656 * max_filesize with blocks of 64 is 279,488 * max_filesize with blocks of 128 is 4,329,344 * max_filesize with blocks of 256 is 68,173,568 * max_filesize with blocks of 512 is 1,082,195,456 * @endcode */ #define IMFS_MEMFILE_DEFAULT_BYTES_PER_BLOCK 128 extern const int imfs_memfile_bytes_per_block; #define IMFS_MEMFILE_BYTES_PER_BLOCK imfs_memfile_bytes_per_block #define IMFS_MEMFILE_BLOCK_SLOTS \ (IMFS_MEMFILE_BYTES_PER_BLOCK / sizeof(void *)) typedef uint8_t *block_p; typedef block_p *block_ptr; /* * Important block numbers for "memfiles" */ #define FIRST_INDIRECT (0) #define LAST_INDIRECT (IMFS_MEMFILE_BLOCK_SLOTS - 1) #define FIRST_DOUBLY_INDIRECT (LAST_INDIRECT + 1) #define LAST_DOUBLY_INDIRECT \ (LAST_INDIRECT + \ (IMFS_MEMFILE_BLOCK_SLOTS * IMFS_MEMFILE_BLOCK_SLOTS)) #define FIRST_TRIPLY_INDIRECT (LAST_DOUBLY_INDIRECT + 1) #define LAST_TRIPLY_INDIRECT \ (LAST_DOUBLY_INDIRECT +\ (IMFS_MEMFILE_BLOCK_SLOTS * \ IMFS_MEMFILE_BLOCK_SLOTS * IMFS_MEMFILE_BLOCK_SLOTS)) #define IMFS_MEMFILE_MAXIMUM_SIZE \ (LAST_TRIPLY_INDIRECT * IMFS_MEMFILE_BYTES_PER_BLOCK) /** @} */ /** * @addtogroup IMFSGenericNodes */ /**@{*/ /** * @brief Initializes an IMFS node. * * @param[in] node The IMFS node. * @param[in] arg The user provided argument pointer. It may contain node * specific initialization information. * * @retval node Successful operation. * @retval NULL An error occurred. The @c errno indicates the error. This * will abort the make operation. * * @see IMFS_node_control, IMFS_node_initialize_default(), and * IMFS_node_initialize_generic(). */ typedef IMFS_jnode_t *(*IMFS_node_control_initialize)( IMFS_jnode_t *node, void *arg ); /** * @brief Returns the node and does nothing else. * * @param[in] node The IMFS node. * @param[in] arg The user provided argument pointer. It is not used. * * @retval node Returns always the node passed as parameter. * * @see IMFS_node_control. */ IMFS_jnode_t *IMFS_node_initialize_default( IMFS_jnode_t *node, void *arg ); IMFS_jnode_t *IMFS_node_initialize_directory( IMFS_jnode_t *node, void *arg ); /** * @brief Returns the node and sets the generic node context. * * @param[in] node The IMFS node. * @param[in] arg The user provided argument pointer. It must contain the * generic context. * * @retval node Returns always the node passed as parameter. * * @see IMFS_node_control. */ IMFS_jnode_t *IMFS_node_initialize_generic( IMFS_jnode_t *node, void *arg ); /** * @brief Prepares the removal of an IMFS node from its parent directory. * * @param[in] node The IMFS node. * * @retval node Successful operation. * @retval NULL An error occurred. The @c errno indicates the error. This * will abort the removal operation. * * @see IMFS_node_control and IMFS_node_remove_default(). */ typedef IMFS_jnode_t *(*IMFS_node_control_remove)( IMFS_jnode_t *node ); /** * @brief Returns the node and does nothing else. * * @param[in] node The IMFS node. * * @retval node Returns always the node passed as parameter. * * @see IMFS_node_control. */ IMFS_jnode_t *IMFS_node_remove_default( IMFS_jnode_t *node ); IMFS_jnode_t *IMFS_node_remove_directory( IMFS_jnode_t *node ); /** * @brief Destroys an IMFS node. * * @param[in] node The IMFS node. * * @see IMFS_node_control and IMFS_node_destroy_default(). */ typedef void (*IMFS_node_control_destroy)( IMFS_jnode_t *node ); /** * @brief Frees the node. * * @param[in] node The IMFS node. * * @see IMFS_node_control. */ void IMFS_node_destroy_default( IMFS_jnode_t *node ); /** * @brief Does nothing. * * @param node The IMFS node. * * @see IMFS_node_control. */ void IMFS_do_nothing_destroy( IMFS_jnode_t *node ); /** * @brief IMFS node control. */ typedef struct { const rtems_filesystem_file_handlers_r *handlers; IMFS_node_control_initialize node_initialize; IMFS_node_control_remove node_remove; IMFS_node_control_destroy node_destroy; } IMFS_node_control; typedef struct { IMFS_node_control node_control; size_t node_size; } IMFS_mknod_control; /** @} */ /** * @addtogroup IMFS */ /**@{*/ /* * Maximum length of a "basename" of an IMFS file/node. */ #define IMFS_NAME_MAX _POSIX_NAME_MAX /* * The control structure for an IMFS jnode. */ struct IMFS_jnode_tt { rtems_chain_node Node; /* for chaining them together */ IMFS_jnode_t *Parent; /* Parent node */ const char *name; /* "basename" (not \0 terminated) */ uint16_t namelen; /* Length of "basename" */ mode_t st_mode; /* File mode */ unsigned short reference_count; nlink_t st_nlink; /* Link count */ uid_t st_uid; /* User ID of owner */ gid_t st_gid; /* Group ID of owner */ time_t stat_atime; /* Time of last access */ time_t stat_mtime; /* Time of last modification */ time_t stat_ctime; /* Time of last status change */ const IMFS_node_control *control; }; typedef struct { IMFS_jnode_t Node; rtems_chain_control Entries; rtems_filesystem_mount_table_entry_t *mt_fs; } IMFS_directory_t; typedef struct { IMFS_jnode_t Node; rtems_device_major_number major; rtems_device_minor_number minor; } IMFS_device_t; typedef struct { IMFS_jnode_t Node; IMFS_jnode_t *link_node; } IMFS_link_t; typedef struct { IMFS_jnode_t Node; char *name; } IMFS_sym_link_t; typedef struct { IMFS_jnode_t Node; size_t size; /* size of file in bytes */ } IMFS_filebase_t; typedef struct { IMFS_filebase_t File; block_ptr indirect; /* array of 128 data blocks pointers */ block_ptr doubly_indirect; /* 128 indirect blocks */ block_ptr triply_indirect; /* 128 doubly indirect blocks */ } IMFS_memfile_t; typedef struct { IMFS_filebase_t File; block_p direct; /* pointer to file image */ } IMFS_linearfile_t; /* Support copy on write for linear files */ typedef union { IMFS_jnode_t Node; IMFS_filebase_t File; IMFS_memfile_t Memfile; IMFS_linearfile_t Linearfile; } IMFS_file_t; typedef struct { IMFS_jnode_t Node; pipe_control_t *pipe; } IMFS_fifo_t; typedef struct { IMFS_jnode_t Node; void *context; } IMFS_generic_t; typedef struct { const void *data; size_t size; } IMFS_linearfile_context; static inline IMFS_jnode_t *IMFS_iop_to_node( const rtems_libio_t *iop ) { return (IMFS_jnode_t *) iop->pathinfo.node_access; } static inline IMFS_directory_t *IMFS_iop_to_directory( const rtems_libio_t *iop ) { return (IMFS_directory_t *) iop->pathinfo.node_access; } static inline IMFS_device_t *IMFS_iop_to_device( const rtems_libio_t *iop ) { return (IMFS_device_t *) iop->pathinfo.node_access; } static inline IMFS_file_t *IMFS_iop_to_file( const rtems_libio_t *iop ) { return (IMFS_file_t *) iop->pathinfo.node_access; } static inline IMFS_memfile_t *IMFS_iop_to_memfile( const rtems_libio_t *iop ) { return (IMFS_memfile_t *) iop->pathinfo.node_access; } static inline time_t _IMFS_get_time( void ) { struct bintime now; /* Use most efficient way to get the time in seconds (CLOCK_REALTIME) */ _Timecounter_Getbintime( &now ); return now.sec; } static inline void IMFS_update_atime( IMFS_jnode_t *jnode ) { jnode->stat_atime = _IMFS_get_time(); } static inline void IMFS_update_mtime( IMFS_jnode_t *jnode ) { jnode->stat_mtime = _IMFS_get_time(); } static inline void IMFS_update_ctime( IMFS_jnode_t *jnode ) { jnode->stat_ctime = _IMFS_get_time(); } static inline void IMFS_mtime_ctime_update( IMFS_jnode_t *jnode ) { time_t now; now = _IMFS_get_time(); jnode->stat_mtime = now; jnode->stat_ctime = now; } typedef struct { const IMFS_mknod_control *directory; const IMFS_mknod_control *device; const IMFS_mknod_control *file; const IMFS_mknod_control *fifo; } IMFS_mknod_controls; typedef struct { IMFS_directory_t Root_directory; const IMFS_mknod_controls *mknod_controls; } IMFS_fs_info_t; typedef struct { IMFS_fs_info_t *fs_info; const rtems_filesystem_operations_table *ops; const IMFS_mknod_controls *mknod_controls; } IMFS_mount_data; /* * Shared Data */ extern const IMFS_mknod_control IMFS_mknod_control_dir_default; extern const IMFS_mknod_control IMFS_mknod_control_dir_minimal; extern const IMFS_mknod_control IMFS_mknod_control_device; extern const IMFS_mknod_control IMFS_mknod_control_memfile; extern const IMFS_node_control IMFS_node_control_linfile; extern const IMFS_mknod_control IMFS_mknod_control_fifo; extern const IMFS_mknod_control IMFS_mknod_control_enosys; extern const rtems_filesystem_limits_and_options_t IMFS_LIMITS_AND_OPTIONS; /* * Routines */ extern int IMFS_initialize( rtems_filesystem_mount_table_entry_t *mt_entry, const void *data ); extern int IMFS_initialize_support( rtems_filesystem_mount_table_entry_t *mt_entry, const void *data ); /** * @brief Unmount this instance of IMFS. */ extern void IMFS_fsunmount( rtems_filesystem_mount_table_entry_t *mt_entry ); /** * @brief RTEMS load tarfs. * * This file implements the "mount" procedure for tar-based IMFS * extensions. The TAR is not actually mounted under the IMFS. * Directories from the TAR file are created as usual in the IMFS. * File entries are created as IMFS_LINEAR_FILE nodes with their nods * pointing to addresses in the TAR image. * * Here we create the mountpoint directory and load the tarfs at * that node. Once the IMFS has been mounted, we work through the * tar image and perform as follows: * - For directories, simply call mkdir(). The IMFS creates nodes as * needed. * - For files, we make our own calls to IMFS eval_for_make and * create_node. * * TAR file format: * * @code * Offset Length Contents * 0 100 bytes File name ('\0' terminated, 99 maxmum length) * 100 8 bytes File mode (in octal ascii) * 108 8 bytes User ID (in octal ascii) * 116 8 bytes Group ID (in octal ascii) * 124 12 bytes File size (s) (in octal ascii) * 136 12 bytes Modify time (in octal ascii) * 148 8 bytes Header checksum (in octal ascii) * 156 1 bytes Link flag * 157 100 bytes Linkname ('\0' terminated, 99 maxmum length) * 257 8 bytes Magic PAX ("ustar\0" + 2 bytes padding) * 257 8 bytes Magic GNU tar ("ustar \0") * 265 32 bytes User name ('\0' terminated, 31 maxmum length) * 297 32 bytes Group name ('\0' terminated, 31 maxmum length) * 329 8 bytes Major device ID (in octal ascii) * 337 8 bytes Minor device ID (in octal ascii) * 345 167 bytes Padding * 512 (s+p) bytes File contents (s+p) := (((s) + 511) & ~511), * round up to 512 bytes * @endcode * * Checksum: * @code * int i, sum; * char *header = tar_header_pointer; * * sum = 0; * for (i = 0; i < 512; i++) * sum += 0xFF & header[i]; * @endcode */ extern int rtems_tarfs_load( const char *mountpoint, uint8_t *tar_image, size_t tar_size ); /** * @brief Destroy an IMFS node. */ extern void IMFS_node_destroy( IMFS_jnode_t *node ); /** * @brief Clone an IMFS node. */ extern int IMFS_node_clone( rtems_filesystem_location_info_t *loc ); /** * @brief Free an IMFS node. */ extern void IMFS_node_free( const rtems_filesystem_location_info_t *loc ); /** * @brief Perform a status processing for the IMFS. * * This routine provides a stat for the IMFS file system. */ extern int IMFS_stat( const rtems_filesystem_location_info_t *loc, struct stat *buf ); extern int IMFS_stat_file( const rtems_filesystem_location_info_t *loc, struct stat *buf ); /** * @brief IMFS evaluation node support. */ extern void IMFS_eval_path( rtems_filesystem_eval_path_context_t *ctx ); /** * @brief IMFS device filesystem evaluation node support. */ extern void IMFS_eval_path_devfs( rtems_filesystem_eval_path_context_t *ctx ); /** * @brief Create a new IMFS link node. * * The following rouine creates a new link node under parent with the * name given in name. The link node is set to point to the node at * to_loc. */ extern int IMFS_link( const rtems_filesystem_location_info_t *parentloc, const rtems_filesystem_location_info_t *targetloc, const char *name, size_t namelen ); /** * @brief Change the owner of IMFS. * * This routine is the implementation of the chown() system * call for the IMFS. */ extern int IMFS_chown( const rtems_filesystem_location_info_t *loc, uid_t owner, gid_t group ); /** * @brief Create an IMFS node. * * Routine to create a node in the IMFS file system. */ extern int IMFS_mknod( const rtems_filesystem_location_info_t *parentloc, const char *name, size_t namelen, mode_t mode, dev_t dev ); extern IMFS_jnode_t *IMFS_initialize_node( IMFS_jnode_t *node, const IMFS_node_control *node_control, const char *name, size_t namelen, mode_t mode, void *arg ); /** * @brief Create an IMFS node. * * Create an IMFS filesystem node of an arbitrary type that is NOT * the root directory node. */ extern IMFS_jnode_t *IMFS_create_node( const rtems_filesystem_location_info_t *parentloc, const IMFS_node_control *node_control, size_t node_size, const char *name, size_t namelen, mode_t mode, void *arg ); static inline bool IMFS_is_imfs_instance( const rtems_filesystem_location_info_t *loc ) { return loc->mt_entry->ops->clonenod_h == IMFS_node_clone; } /** * @brief Initializer for an IMFS node control. * * @param handlers The file system node handlers. * @param init The node initialization method. * @param destroy The node destruction method. */ #define IMFS_NODE_CONTROL_INITIALIZER( handlers, init, destroy ) \ { \ ( handlers ), \ ( init ), \ IMFS_node_remove_default, \ ( destroy ) \ } /** * @brief Initializer for an IMFS node. * * Initialize the node control with IMFS_NODE_CONTROL_INITIALIZER(). * * @param node_control The node control of the IMFS node. * @param name The name of the IMFS node. * @param namelen The length of the name of the IMFS node. * @param mode The mode of the IMFS node. * * @see IMFS_node_preinitialize(). */ #define IMFS_NODE_INITIALIZER( node_control, name, namelen, mode ) \ { \ { NULL, NULL }, \ NULL, \ ( name ), \ ( namelen ), \ ( mode ), \ 0, \ 0, \ 0, \ 0, \ 0, \ 0, \ 0, \ ( node_control ) \ } /** * @brief Preinitializes an IMFS node. * * Initialize the node control with IMFS_NODE_CONTROL_INITIALIZER(). * * @param node The IMFS node to preinitialize. * @param node_control The node control of the IMFS node. * @param name The name of the IMFS node. * @param namelen The length of the name of the IMFS node. * @param mode The mode of the IMFS node. * * @see IMFS_NODE_INITIALIZER(). */ static inline void IMFS_node_preinitialize( IMFS_jnode_t *node, const IMFS_node_control *node_control, const char *name, size_t namelen, mode_t mode ) { node->control = node_control; node->name = name; node->namelen = namelen; node->st_mode = mode; } /** * @brief Adds an IMFS node. * * Initialize the node with IMFS_NODE_INITIALIZER(), IMFS_node_preinitialize(), * IMFS_GENERIC_NODE_INITIALIZER(), or IMFS_generic_node_preinitialize(). * * @param path The path of parent directories for the IMFS node to add. * @param node The IMFS node to add. * @param arg The argument passed to the node initialization method. * * @retval 0 Successful operation. * @retval -1 An error occurred. The @c errno indicates the error. */ int IMFS_add_node( const char *path, IMFS_jnode_t *node, void *arg ); extern int IMFS_make_node( const char *path, mode_t mode, const IMFS_node_control *node_control, size_t node_size, void *context ); /** * @brief Makes a linear IMFS file. * * @param path The path to the new linear IMFS file. * @param mode The file mode permissions. S_IFREG is set by the function. * @param data The begin of linear file data area. * @param size The size of the linear file data area in bytes. * * @retval 0 Successful operation. * @retval -1 An error occurred. The @c errno indicates the error. */ extern int IMFS_make_linearfile( const char *path, mode_t mode, const void *data, size_t size ); /** @} */ /** * @defgroup IMFSGenericNodes IMFS Generic Nodes * * @ingroup LibIO * * @brief Generic nodes are an alternative to standard drivers in RTEMS. * * The handlers of a generic node are called with less overhead compared to the * standard driver operations. The usage of file system node handlers enable * more features like support for fsync() and fdatasync(). The generic nodes * use the reference counting of the IMFS. This provides automatic node * destruction when the last reference vanishes. * * @{ */ /* Provided for backward compatibility */ #define IMFS_GENERIC_INITIALIZER( handlers, init, destroy ) \ IMFS_NODE_CONTROL_INITIALIZER( handlers, init, destroy ) /** * @brief Initializer for a generic node control. * * @param handlers The file system node handlers. * @param init The node initialization method. * @param destroy The node destruction method. */ #define IMFS_GENERIC_CONTROL_INITIALIZER( handlers, init, destroy ) \ IMFS_NODE_CONTROL_INITIALIZER( handlers, init, destroy ) /** * @brief Initializer for a generic node. * * Initialize the node control with IMFS_GENERIC_CONTROL_INITIALIZER(). * * @param node_control The node control of the IMFS generic node. * @param name The name of the IMFS generic node. * @param namelen The length of the name of the IMFS generic node. * @param mode The mode of the IMFS generic node. */ #define IMFS_GENERIC_NODE_INITIALIZER( node_control, name, namelen, mode ) \ { IMFS_NODE_INITIALIZER( node_control, name, namelen, mode ), NULL } /** * @brief Preinitializes a generic IMFS node. * * Initialize the node control with IMFS_GENERIC_CONTROL_INITIALIZER(). * * @param node The generic IMFS node to preinitialize. * @param node_control The node control of the generic IMFS node. * @param name The name of the generic IMFS node. * @param namelen The length of the name of the generic IMFS node. * @param mode The mode of the generic IMFS node. * * @see IMFS_GENERIC_NODE_INITIALIZER(). */ static inline void IMFS_generic_node_preinitialize( IMFS_generic_t *node, const IMFS_node_control *node_control, const char *name, size_t namelen, mode_t mode ) { IMFS_node_preinitialize( &node->Node, node_control, name, namelen, mode ); } /** * @brief Makes a generic IMFS node. * * @param[in] path The path to the new generic IMFS node. * @param[in] mode The node mode. * @param[in] node_control The node control. * @param[in] context The node control handler context. * * @retval 0 Successful operation. * @retval -1 An error occurred. The @c errno indicates the error. * * @code * #include * #include * #include * * #include * * static const rtems_filesystem_file_handlers_r some_node_handlers = { * ... * }; * * static IMFS_jnode_t *some_node_init(IMFS_jnode_t *node, void *arg) * { * void *context; * * node = IMFS_node_initialize_generic(node, arg); * context = IMFS_generic_get_context_by_node(node); * * return node; * } * * static void some_node_destroy(IMFS_jnode_t *node) * { * void *context = IMFS_generic_get_context_by_node(node); * * IMFS_node_destroy_default(node); * } * * static const IMFS_node_control * some_node_control = IMFS_GENERIC_CONTROL_INITIALIZER( * &some_node_handlers, * some_node_init, * some_node_destroy * ); * * void example(void *some_node_context) * { * int rv; * * rv = IMFS_make_generic_node( * "/path/to/some/generic/node", * S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, * &some_node_control, * some_node_context * ); * assert(rv == 0); * } * @endcode */ extern int IMFS_make_generic_node( const char *path, mode_t mode, const IMFS_node_control *node_control, void *context ); /** @} */ /** * @addtogroup IMFS */ /**@{*/ /** * @brief Mount an IMFS. */ extern int IMFS_mount( rtems_filesystem_mount_table_entry_t *mt_entry /* IN */ ); /** * @brief Unmount an IMFS. */ extern int IMFS_unmount( rtems_filesystem_mount_table_entry_t *mt_entry /* IN */ ); /** * @name IMFS Memory File Handlers * * This section contains the set of handlers used to process operations on * IMFS memory file nodes. The memory files are created in memory using * malloc'ed memory. Thus any data stored in one of these files is lost * at system shutdown unless special arrangements to copy the data to * some type of non-volailte storage are made by the application. */ /**@{*/ extern ssize_t IMFS_memfile_write( IMFS_memfile_t *memfile, off_t start, const unsigned char *source, unsigned int length ); /** @} */ /** * @name IMFS Device Node Handlers * * This section contains the set of handlers used to map operations on * IMFS device nodes onto calls to the RTEMS Classic API IO Manager. */ /**@{*/ extern int device_open( rtems_libio_t *iop, /* IN */ const char *pathname, /* IN */ int oflag, /* IN */ mode_t mode /* IN */ ); extern int device_close( rtems_libio_t *iop /* IN */ ); extern ssize_t device_read( rtems_libio_t *iop, /* IN */ void *buffer, /* IN */ size_t count /* IN */ ); extern ssize_t device_write( rtems_libio_t *iop, /* IN */ const void *buffer, /* IN */ size_t count /* IN */ ); extern int device_ioctl( rtems_libio_t *iop, ioctl_command_t command, void *buffer ); extern int device_ftruncate( rtems_libio_t *iop, /* IN */ off_t length /* IN */ ); /** @} */ /** * @brief Set IMFS file access and modification times. * * * This routine is the implementation of the utime() system * call for the IMFS. */ extern int IMFS_utimens( const rtems_filesystem_location_info_t *loc, struct timespec times[2] ); /** * @brief Change the IMFS file mode. */ extern int IMFS_fchmod( const rtems_filesystem_location_info_t *loc, mode_t mode ); /** * @brief Create a new IMFS symbolic link node. * * The following rouine creates a new symbolic link node under parent * with the name given in name. The node is set to point to the node at * to_loc. */ extern int IMFS_symlink( const rtems_filesystem_location_info_t *parentloc, const char *name, size_t namelen, const char *target ); /** * @brief Put IMFS symbolic link into buffer. * * The following rouine puts the symbolic links destination name into * buff. * */ extern ssize_t IMFS_readlink( const rtems_filesystem_location_info_t *loc, char *buf, size_t bufsize ); /** * @brief Rename the IMFS. * * The following rouine creates a new link node under parent with the * name given in name and removes the old. */ extern int IMFS_rename( const rtems_filesystem_location_info_t *oldparentloc, const rtems_filesystem_location_info_t *oldloc, const rtems_filesystem_location_info_t *newparentloc, const char *name, size_t namelen ); /** * @brief IMFS node removal handler. * * This file contains the handler used to remove a node when a file type * does not require special actions. */ extern int IMFS_rmnod( const rtems_filesystem_location_info_t *parentloc, const rtems_filesystem_location_info_t *loc ); /* * Turn on IMFS assertions when RTEMS_DEBUG is defined. */ #ifdef RTEMS_DEBUG #include #define IMFS_assert(_x) assert(_x) #else #define IMFS_assert(_x) #endif static inline void IMFS_Set_handlers( rtems_filesystem_location_info_t *loc ) { IMFS_jnode_t *node = (IMFS_jnode_t *) loc->node_access; loc->handlers = node->control->handlers; } static inline void IMFS_add_to_directory( IMFS_jnode_t *dir_node, IMFS_jnode_t *entry_node ) { IMFS_directory_t *dir = (IMFS_directory_t *) dir_node; entry_node->Parent = dir_node; rtems_chain_append_unprotected( &dir->Entries, &entry_node->Node ); } static inline void IMFS_remove_from_directory( IMFS_jnode_t *node ) { IMFS_assert( node->Parent != NULL ); node->Parent = NULL; rtems_chain_extract_unprotected( &node->Node ); } static inline bool IMFS_is_directory( const IMFS_jnode_t *node ) { return S_ISDIR( node->st_mode ); } #define IMFS_STAT_FMT_HARD_LINK 0 static inline bool IMFS_is_hard_link( mode_t mode ) { return ( mode & S_IFMT ) == IMFS_STAT_FMT_HARD_LINK; } static inline ino_t IMFS_node_to_ino( const IMFS_jnode_t *node ) { return (ino_t) ((uintptr_t) node); } /** @} */ /** * @addtogroup IMFSGenericNodes */ /**@{*/ static inline void *IMFS_generic_get_context_by_node( const IMFS_jnode_t *node ) { const IMFS_generic_t *generic = (const IMFS_generic_t *) node; return generic->context; } static inline void *IMFS_generic_get_context_by_location( const rtems_filesystem_location_info_t *loc ) { return loc->node_access_2; } static inline void *IMFS_generic_get_context_by_iop( const rtems_libio_t *iop ) { return IMFS_generic_get_context_by_location( &iop->pathinfo ); } static inline dev_t IMFS_generic_get_device_identifier_by_node( const IMFS_jnode_t *node ) { return rtems_filesystem_make_dev_t_from_pointer( node ); } #ifdef __cplusplus } #endif /** @} */ #endif /* end of include file */