/** * @file * * @brief RTEMS File System File Support * * @ingroup rtems_rfs * * RTEMS File System File Support * * This file provides the support functions. */ /* * COPYRIGHT (c) 2010 Chris Johns * * The license and distribution terms for this file may be * found in the file LICENSE in this distribution or at * http://www.rtems.org/license/LICENSE. */ #if !defined (_RTEMS_RFS_FILE_H_) #define _RTEMS_RFS_FILE_H_ #include #include #include #include #include /** * File data that is shared by various file handles accessing the same file. We * hold various inode values common to the file that can change frequently so * the inode is not thrashed yet we meet the requirements of the POSIX * standard. The stat call needs to check the shared file data. */ typedef struct _rtems_rfs_file_shared { /** * The shared parts are maintained as a list. */ rtems_chain_node link; /** * Reference count the users of this data. */ int references; /** * The inode for the file. */ rtems_rfs_inode_handle inode; /** * The block map for the file. The handle holds the file's position not the * map. */ rtems_rfs_block_map map; /** * The size of the file as taken from the inode. The map's size and * this size should be the same. */ rtems_rfs_block_size size; /** * The access time. The last time the file was read. */ rtems_rfs_time atime; /** * The modified time. The last time the file was written too. */ rtems_rfs_time mtime; /** * The change time. The last time the inode was written too. */ rtems_rfs_time ctime; /** * Hold a pointer to the file system data so users can take the handle and * use it without the needing to hold the file system data pointer. */ rtems_rfs_file_system* fs; } rtems_rfs_file_shared; /** * Get the atime. * * @param[in] shared is a pointer to the shared file data. * * @retval atime The atime. */ static inline rtems_rfs_time rtems_rfs_file_shared_get_atime (rtems_rfs_file_shared* shared) { return shared->atime; } /** * Get the mtime. * * @param[in] shared is a pointer to the shared file data. * * @retval mtime The mtime. */ static inline rtems_rfs_time rtems_rfs_file_shared_get_mtime (rtems_rfs_file_shared* shared) { return shared->mtime; } /** * Get the ctime. * * @param[in] shared is a pointer to the shared file data. * * @retval ctime The ctime. */ static inline rtems_rfs_time rtems_rfs_file_shared_get_ctime (rtems_rfs_file_shared* shared) { return shared->ctime; } /** * Get the block count. * * @param[in] shared is a pointer to the shared file data. * * @retval count The block count. */ static inline uint32_t rtems_rfs_file_shared_get_block_count (rtems_rfs_file_shared* shared) { return shared->size.count; } /** * Get the block offset. * * @param shared is a pointer to the shared file data. * * @retval offset The block offset. */ static inline uint16_t rtems_rfs_file_shared_get_block_offset (rtems_rfs_file_shared* shared) { return shared->size.offset; } /** * Calculate the size of data. * * @param[in] fs is the file system data. * @param[in] shared is a pointer to the shared file data. * * @retval data The data size in bytes. */ static inline rtems_rfs_pos rtems_rfs_file_shared_get_size (rtems_rfs_file_system* fs, rtems_rfs_file_shared* shared) { return rtems_rfs_block_get_size (fs, &shared->size); } /** * File flags. */ #define RTEMS_RFS_FILE_NO_ATIME_UPDATE (1 << 0) /**< Do not update the atime * field in the inode if * set. */ #define RTEMS_RFS_FILE_NO_MTIME_UPDATE (1 << 1) /**< Do not update the mtime * field in the inode if * set. */ #define RTEMS_RFS_FILE_NO_LENGTH_UPDATE (1 << 2) /**< Do not update the position * field in the inode if * set. */ /** * File data used to managed an open file. */ typedef struct _rtems_rfs_file_handle { /** * Special flags that can be controlled by the fctrl call. */ int flags; /** * The buffer of data at the file's position. */ rtems_rfs_buffer_handle buffer; /** * The block position of this file handle. */ rtems_rfs_block_pos bpos; /** * Pointer to the shared file data. */ rtems_rfs_file_shared* shared; } rtems_rfs_file_handle; /** * Access the data in the buffer. */ #define rtems_rfs_file_data(_f) \ (rtems_rfs_buffer_data (&(_f)->buffer) + (_f)->bpos.boff) /** * Return the file system data pointer given a file handle. */ #define rtems_rfs_file_fs(_f) ((_f)->shared->fs) /** * Return the file's inode handle pointer given a file handle. */ #define rtems_rfs_file_inode(_f) (&(_f)->shared->inode) /** * Return the file's block map pointer given a file handle. */ #define rtems_rfs_file_map(_f) (&(_f)->shared->map) /** * Return the file's block position pointer given a file handle. */ #define rtems_rfs_file_bpos(_f) (&(_f)->bpos) /** * Return the file's block number given a file handle. */ #define rtems_rfs_file_block(_f) ((_f)->bpos.bno) /** * Return the file's block offset given a file handle. */ #define rtems_rfs_file_block_offset(_f) ((_f)->bpos.boff) /** * Set the file's block position given a file position (absolute). */ #define rtems_rfs_file_set_bpos(_f, _p) \ rtems_rfs_block_get_bpos (rtems_rfs_file_fs (_f), _p, (&(_f)->bpos)) /** * Return the file's buffer handle pointer given a file handle. */ #define rtems_rfs_file_buffer(_f) (&(_f)->buffer) /** * Update the access time field of the inode when reading if flagged to do so. */ #define rtems_rfs_file_update_atime(_f) \ (((_f)->flags & RTEMS_RFS_FILE_NO_ATIME_UPDATE) == 0) /** * Update the modified time field of the inode when writing if flagged to do so. */ #define rtems_rfs_file_update_mtime(_f) \ (((_f)->flags & RTEMS_RFS_FILE_NO_MTIME_UPDATE) == 0) /** * Update the length field of the inode. */ #define rtems_rfs_file_update_length(_f) \ (((_f)->flags & RTEMS_RFS_FILE_NO_LENGTH_UPDATE) == 0) /** * Return the shared size varable. */ #define rtems_rfs_file_get_size(_f) \ (&(_f)->shared->size) /** * Return the size of file. */ #define rtems_rfs_file_size(_f) \ rtems_rfs_file_shared_get_size (rtems_rfs_file_fs (_f), (_f)->shared) /** * Return the file block count. */ #define rtems_rfs_file_size_count(_f) \ rtems_rfs_file_shared_get_block_count ((_f)->shared) /** * Return the file block offset. */ #define rtems_rfs_file_size_offset(_f) \ rtems_rfs_file_shared_get_block_offset ((_f)->shared) /** * Open a file handle. * * @param[in] fs is the file system. * @param[in] ino is the inode number of the file to be opened. * @param[out] handle will be filled in with the handle pointer. * * @retval 0 Successful operation. * @retval error_code An error occurred. */ int rtems_rfs_file_open (rtems_rfs_file_system* fs, rtems_rfs_ino ino, int oflag, rtems_rfs_file_handle** handle); /** * Close an open file handle. * * @param[in] fs is the file system. * @param[in] handle is the open file handle. * * @retval 0 Successful operation. * @retval error_code An error occurred. */ int rtems_rfs_file_close (rtems_rfs_file_system* fs, rtems_rfs_file_handle* handle); /** * Start I/O on a block of a file. This call only requests the block from the * media if reading and makes the buffer available to you the via the * rtems_rfs_file_data interface after the call. The available amount data is * taken from the current file position until the end of the block. The file * position is not adujsted until the I/O ends. An I/O request cannot perform * I/O past the end of a block so the call returns the amount of data * available. * * @param[in] handle is the file handle. * @param[in] available is the amount of data available for I/O. * @param[in] read is the I/O operation is a read so the block is read from the media. * * @retval 0 Successful operation. * @retval error_code An error occurred. */ int rtems_rfs_file_io_start (rtems_rfs_file_handle* handle, size_t* available, bool read); /** * End the I/O. Any buffers held in the file handle and returned to the * cache. If inode updating is not disable and the I/O is a read the atime * field is updated and if a write I/O the mtime is updated. * * If the file's position is updated by the size amount. * * @param[in] handle is the file handle. * @param[in] size is the amount of data read or written. * @param[in] read is the I/O was a read if true else it was a write. * * @retval 0 Successful operation. * @retval error_code An error occurred. */ int rtems_rfs_file_io_end (rtems_rfs_file_handle* handle, size_t size, bool read); /** * Release the I/O resources without any changes. If data has changed in the * buffer and the buffer was not already released as modified the data will be * lost. * * @param[in] handle is the file handle. * * @retval 0 Successful operation. * @retval error_code An error occurred. */ int rtems_rfs_file_io_release (rtems_rfs_file_handle* handle); /** * The file to the position returning the old position. The position is * abolute. * * @param[in] handle The file handle. * @param[in] pos is the position to seek to. * @param[out] new_pos will contain the actual position. * * @retval 0 Successful operation. * @retval error_code An error occurred. */ int rtems_rfs_file_seek (rtems_rfs_file_handle* handle, rtems_rfs_pos pos, rtems_rfs_pos* new_pos); /** * Set the size of the file to the new size. This can extend the file to a new * size. * * @param[in] handle is the file handle. * @param[in] size is the new size of the file. * @retval 0 Successful operation. * @retval error_code An error occurred. */ int rtems_rfs_file_set_size (rtems_rfs_file_handle* handle, rtems_rfs_pos size); /** * Return the shared file data for an ino. * * @param[in] fs is the file system data. * @param[in] ino is the inode number to locate the data for. * @return rtems_rfs_file_shared* The shared data or NULL is not located. * * @retval shared The shared data. * @retval NULL No shared file data is located. */ rtems_rfs_file_shared* rtems_rfs_file_get_shared (rtems_rfs_file_system* fs, rtems_rfs_ino ino); #endif