diff options
Diffstat (limited to 'cpukit/include/rtems/rfs')
-rw-r--r-- | cpukit/include/rtems/rfs/rtems-rfs-bitmaps.h | 326 | ||||
-rw-r--r-- | cpukit/include/rtems/rfs/rtems-rfs-block-pos.h | 242 | ||||
-rw-r--r-- | cpukit/include/rtems/rfs/rtems-rfs-block.h | 344 | ||||
-rw-r--r-- | cpukit/include/rtems/rfs/rtems-rfs-buffer.h | 283 | ||||
-rw-r--r-- | cpukit/include/rtems/rfs/rtems-rfs-data.h | 89 | ||||
-rw-r--r-- | cpukit/include/rtems/rfs/rtems-rfs-dir-hash.h | 36 | ||||
-rw-r--r-- | cpukit/include/rtems/rfs/rtems-rfs-dir.h | 209 | ||||
-rw-r--r-- | cpukit/include/rtems/rfs/rtems-rfs-file-system-fwd.h | 29 | ||||
-rw-r--r-- | cpukit/include/rtems/rfs/rtems-rfs-file-system.h | 410 | ||||
-rw-r--r-- | cpukit/include/rtems/rfs/rtems-rfs-file.h | 416 | ||||
-rw-r--r-- | cpukit/include/rtems/rfs/rtems-rfs-group.h | 181 | ||||
-rw-r--r-- | cpukit/include/rtems/rfs/rtems-rfs-inode.h | 728 | ||||
-rw-r--r-- | cpukit/include/rtems/rfs/rtems-rfs-link.h | 124 | ||||
-rw-r--r-- | cpukit/include/rtems/rfs/rtems-rfs-mutex.h | 116 | ||||
-rw-r--r-- | cpukit/include/rtems/rfs/rtems-rfs-trace.h | 135 |
15 files changed, 3668 insertions, 0 deletions
diff --git a/cpukit/include/rtems/rfs/rtems-rfs-bitmaps.h b/cpukit/include/rtems/rfs/rtems-rfs-bitmaps.h new file mode 100644 index 0000000000..5574339421 --- /dev/null +++ b/cpukit/include/rtems/rfs/rtems-rfs-bitmaps.h @@ -0,0 +1,326 @@ +/** + * @file + * + * @brief RTEMS File Systems Bitmap Routines + * + * @ingroup rtems_rfs + * + * RTEMS File Systems Bitmap Routines. + * + * These functions manage bit maps. A bit map consists of the map of bit + * allocated in a block and a search map where a bit represents 32 actual + * bits. The search map allows for a faster search for an available bit as 32 + * search bits can checked in a test. + */ + +/* + * COPYRIGHT (c) 2010 Chris Johns <chrisj@rtems.org> + * + * 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_BITMAPS_H_) +#define _RTEMS_RFS_BITMAPS_H_ + +#include <rtems/rfs/rtems-rfs-buffer.h> +#include <rtems/rfs/rtems-rfs-file-system-fwd.h> +#include <rtems/rfs/rtems-rfs-trace.h> + +/** + * Define the way the bits are configured. We can have them configured as clear + * being 0 or clear being 1. This does not effect how masks are defined. A mask + * always has a 1 for set and 0 for clear. + */ +#define RTEMS_RFS_BITMAP_CLEAR_ZERO 0 + +#if RTEMS_RFS_BITMAP_CLEAR_ZERO +/* + * Bit set is a 1 and clear is 0. + */ +#define RTEMS_RFS_BITMAP_BIT_CLEAR 0 +#define RTEMS_RFS_BITMAP_BIT_SET 1 +#define RTEMS_RFS_BITMAP_ELEMENT_SET (RTEMS_RFS_BITMAP_ELEMENT_FULL_MASK) +#define RTEMS_RFS_BITMAP_ELEMENT_CLEAR (0) +#define RTEMS_RFS_BITMAP_SET_BITS(_t, _b) ((_t) | (_b)) +#define RTEMS_RFS_BITMAP_CLEAR_BITS(_t, _b) ((_t) & ~(_b)) +#define RTEMS_RFS_BITMAP_TEST_BIT(_t, _b) (((_t) & (1 << (_b))) != 0 ? true : false) +#else +/* + * Bit set is a 0 and clear is 1. + */ +#define RTEMS_RFS_BITMAP_BIT_CLEAR 1 +#define RTEMS_RFS_BITMAP_BIT_SET 0 +#define RTEMS_RFS_BITMAP_ELEMENT_SET (0) +#define RTEMS_RFS_BITMAP_ELEMENT_CLEAR (RTEMS_RFS_BITMAP_ELEMENT_FULL_MASK) +#define RTEMS_RFS_BITMAP_SET_BITS(_t, _b) ((_t) & ~(_b)) +#define RTEMS_RFS_BITMAP_CLEAR_BITS(_t, _b) ((_t) | (_b)) +#define RTEMS_RFS_BITMAP_TEST_BIT(_t, _b) (((_t) & (1 << (_b))) == 0 ? true : false) +#endif + +/** + * Invert a mask. Masks are always 1 for set and 0 for clear. + */ +#define RTEMS_RFS_BITMAP_INVERT_MASK(_mask) (~(_mask)) + +/** + * This is the full mask of the length of the element. A mask is always a 1 for + * set and 0 for clear. It is not effected by the state of + * RTEMS_RFS_BITMAP_CLEAR_ZERO. + */ +#define RTEMS_RFS_BITMAP_ELEMENT_FULL_MASK (0xffffffffUL) + +/** + * The bitmap search window. Searches occur around a seed in either direction + * for half the window. + */ +#define RTEMS_RFS_BITMAP_SEARCH_WINDOW (rtems_rfs_bitmap_element_bits () * 64) + +/** + * A bit in a map. + */ +typedef int32_t rtems_rfs_bitmap_bit; + +/** + * The basic element of a bitmap. A bitmap is manipulated by elements. + */ +typedef uint32_t rtems_rfs_bitmap_element; + +/** + * The power of 2 number of bits in the element. + */ +#define RTEMS_RFS_ELEMENT_BITS_POWER_2 (5) + +/** + * A bitmap or map is an array of bitmap elements. + */ +typedef rtems_rfs_bitmap_element* rtems_rfs_bitmap_map; + +/** + * The bitmap control is a simple way to manage the various parts of a bitmap. + */ +typedef struct rtems_rfs_bitmap_control_s +{ + rtems_rfs_buffer_handle* buffer; //< Handle the to buffer with the bit + //map. + rtems_rfs_file_system* fs; //< The map's file system. + rtems_rfs_buffer_block block; //< The map's block number on disk. + size_t size; //< Number of bits in the map. Passed + //to create. + size_t free; //< Number of bits in the map that are + //free (clear). + rtems_rfs_bitmap_map search_bits; //< The search bit map memory. +} rtems_rfs_bitmap_control; + +/** + * Return the number of bits for the number of bytes provided. + */ +#define rtems_rfs_bitmap_numof_bits(_bytes) (8 * (_bytes)) + +/** + * Return the number of bits for the number of bytes provided. The search + * element and the element must have the same number of bits. + */ +#define rtems_rfs_bitmap_element_bits() \ + rtems_rfs_bitmap_numof_bits (sizeof (rtems_rfs_bitmap_element)) + +/** + * Return the number of bits a search element covers. + */ +#define rtems_rfs_bitmap_search_element_bits() \ + (rtems_rfs_bitmap_element_bits() * rtems_rfs_bitmap_element_bits()) + +/** + * Return the number of elements for a given number of bits. + */ +#define rtems_rfs_bitmap_elements(_bits) \ + ((((_bits) - 1) / rtems_rfs_bitmap_element_bits()) + 1) + +/** + * Release the bitmap buffer back to the buffer pool or cache. + */ +#define rtems_rfs_bitmap_release_buffer(_fs, _bm) \ + rtems_rfs_buffer_handle_release (_fs, (_bm)->buffer) + +/** + * Return the element index for a given bit. We use a macro to hide any + * implementation assuptions. Typically this would be calculated by dividing + * the bit index by the number of bits in an element. Given we have a power of + * 2 as the number of bits we can avoid the division by using a shift. A good + * compiler should figure this out but I would rather enforce this than rely on + * the specific backend of a compiler to do the right thing. + */ +#define rtems_rfs_bitmap_map_index(_b) \ + ((_b) >> RTEMS_RFS_ELEMENT_BITS_POWER_2) + +/** + * Return the bit offset for a given bit in an element in a map. See @ref + * rtems_rfs_bitmap_map_index for a detailed reason why. + */ +#define rtems_rfs_bitmap_map_offset(_b) \ + ((_b) & ((1 << RTEMS_RFS_ELEMENT_BITS_POWER_2) - 1)) + +/** + * Return the size of the bitmap. + */ +#define rtems_rfs_bitmap_map_size(_c) ((_c)->size) + +/** + * Return the number of free bits in the bitmap. + */ +#define rtems_rfs_bitmap_map_free(_c) ((_c)->free) + +/** + * Return the buffer handle. + */ +#define rtems_rfs_bitmap_map_handle(_c) ((_c)->buffer) + +/** + * Return the bitmap map block. + */ +#define rtems_rfs_bitmap_map_block(_c) ((_c)->block) + +/** + * Create a bit mask with the specified number of bits up to an element's + * size. The mask is aligned to bit 0 of the element. + * + * @param[in] size is the number of bits in the mask. + * + * @return The mask of the argument size number of bits. + */ +rtems_rfs_bitmap_element rtems_rfs_bitmap_mask (unsigned int size); + +/** + * Create a bit mask section. A mask section is a mask that is not aligned to + * an end of the element. + * + * @param[in] start is the first bit of the mask numbered from 0. + * @param[in] end is the end bit of the mask numbered from 0. + * + * @return Mask section as defined by the start and end arguments. + */ +rtems_rfs_bitmap_element rtems_rfs_bitmap_mask_section (unsigned int start, + unsigned int end); + +/** + * Set a bit in a map and if all the bits are set, set the search map bit as + * well. + * + * @param[in] control is the control for the map. + * @param[in] bit is the bit in the map to set. + * + * @retval 0 Successful operation. + * @retval error_code An error occurred. + */ +int rtems_rfs_bitmap_map_set (rtems_rfs_bitmap_control* control, + rtems_rfs_bitmap_bit bit); + +/** + * Clear a bit in a map and make sure the search map bit is clear so a search + * will find this bit available. + * + * @param[in] control is the control for the map. + * @param[in] bit is the bit in the map to clear. + * + * @retval 0 Successful operation. + * @retval error_code An error occurred. + */ +int rtems_rfs_bitmap_map_clear (rtems_rfs_bitmap_control* control, + rtems_rfs_bitmap_bit bit); + +/** + * Test a bit in the map. + * + * @param[in] control is the bitmap control. + * @param[in] bit is the bit to test. + * @param[in] state is the state of the bit if no error is returned. + * + * @retval 0 Successful operation. + * @retval error_code An error occurred. + */ +int +rtems_rfs_bitmap_map_test (rtems_rfs_bitmap_control* control, + rtems_rfs_bitmap_bit bit, + bool* state); + +/** + * Set all bits in the bitmap and set the dirty bit. + * + * @param[in] control is the bitmap control. + * + * @retval 0 Successful operation. + * @retval error_code An error occurred. + */ +int rtems_rfs_bitmap_map_set_all (rtems_rfs_bitmap_control* control); + +/** + * Clear all bits in the bitmap and set the dirty bit. + * + * @param[in] control is the bitmap control. + * + * @retval 0 Successful operation. + * @retval error_code An error occurred. + */ +int rtems_rfs_bitmap_map_clear_all (rtems_rfs_bitmap_control* control); + +/** + * Find a free bit searching from the seed up and down until found. The search + * is performing by moving up from the seed for the window distance then to + * search down from the seed for the window distance. This is repeated out + * from the seed for each window until a free bit is found. The search is + * performed by checking the search map to see if the map has a free bit. + * + * @param[in] control is the map control. + * @param[in] seed is the bit to search out from. + * @param[out] allocate A bit was allocated. + * @param[out] bit will contain the bit found free if true is returned. + * + * @retval 0 Successful operation. + * @retval error_code An error occurred. + */ +int rtems_rfs_bitmap_map_alloc (rtems_rfs_bitmap_control* control, + rtems_rfs_bitmap_bit seed, + bool* allocate, + rtems_rfs_bitmap_bit* bit); + +/** + * Create a search bit map from the actual bit map. + * + * @param[in] control is the map control. + * + * @retval 0 Successful operation. + * @retval error_code An error occurred. + */ +int rtems_rfs_bitmap_create_search (rtems_rfs_bitmap_control* control); + +/** + * Open a bitmap control with a map and search map. + * + * @param[in] control is the map control. + * @param[in] fs is the file system data. + * @param[in] buffer is a pointer to the buffer handle the map is + * stored in. + * @param[in] size is the number of bits in the map. + * + * @retval 0 Successful operation. + * @retval error_code An error occurred. + */ +int rtems_rfs_bitmap_open (rtems_rfs_bitmap_control* control, + rtems_rfs_file_system* fs, + rtems_rfs_buffer_handle* buffer, + size_t size, + rtems_rfs_buffer_block block); + +/** + * Close a bitmap. + * + * @param[in] control is the bit map control. + * + * @retval 0 Successful operation. + * @retval error_code An error occurred. + */ +int rtems_rfs_bitmap_close (rtems_rfs_bitmap_control* control); + +#endif diff --git a/cpukit/include/rtems/rfs/rtems-rfs-block-pos.h b/cpukit/include/rtems/rfs/rtems-rfs-block-pos.h new file mode 100644 index 0000000000..7d0f0693be --- /dev/null +++ b/cpukit/include/rtems/rfs/rtems-rfs-block-pos.h @@ -0,0 +1,242 @@ +/** + * @file + * + * @brief RTEMS File Systems Block Position and Size Management + * + * @ingroup rtems_rfs + * + * RTEMS File Systems Block Position and Size Management. + * + * These functions manage the position in a block map as well as a size of data + * held in a block map. The position is the block count plus the offset into + * the last block where a block position of 0 and an offset of 0 is the start + * of a map. The size has a block count plus an offset, but the offset into the + * last block gives the actual size of the data in the map. This means a size + * will always have a block count greater than 0 when the file is not empty. A + * size offset of 0 and a non-zero block count means the length if aligned to + * the end of the block. For this reason there are 2 similar types so we know + * which set of rules are in use and the reason for this file. + */ + +/* + * COPYRIGHT (c) 2010 Chris Johns <chrisj@rtems.org> + * + * 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_BLOCK_POS_H_) +#define _RTEMS_RFS_BLOCK_POS_H_ + +#include <rtems/rfs/rtems-rfs-file-system.h> +#include <rtems/rfs/rtems-rfs-inode.h> + +/** + * The block number is the same type as the inode block number. This makes sure + * the sizes of the types match. + */ +typedef rtems_rfs_inode_block rtems_rfs_block_no; + +/** + * The offset into a block. + */ +typedef uint32_t rtems_rfs_block_off; + +/** + * A block position is a block number times the block size plus the offset. The + * block field can be used hold a block number for the position as a look up + * cache. + */ +typedef struct rtems_rfs_block_pos_s +{ + /** + * The block index in the map. Range is from 0 to the maps block count minus + * 1. + */ + rtems_rfs_block_no bno; + + /** + * The offset into the block. Must be less than the block size. + */ + rtems_rfs_block_off boff; + + /** + * The block number that the bpos + boff map to. The 0 value is invalid and + * means no block number has been set. + */ + rtems_rfs_block_no block; + +} rtems_rfs_block_pos; + +/** + * Copy a block position. + * + * @param[in] _lhs is the left hand side. + * @param[in] _rhs is the right hand side. + */ +#define rtems_rfs_block_copy_bpos(_lhs, _rhs) \ + do { (_lhs)->bno = (_rhs)->bno; \ + (_lhs)->boff = (_rhs)->boff; \ + (_lhs)->block = (_rhs)->block; } while (0) + +/** + * Zero a block position. + * + * @param[in] bpos is a pointer to the block position. + */ +static inline void +rtems_rfs_block_set_bpos_zero (rtems_rfs_block_pos* bpos) +{ + bpos->bno = 0; + bpos->boff = 0; + bpos->block = 0; +} + +/** + * Given a position compute the block number and block offset. + * + * @param[in] fs is the file system data. + * @param[in] pos is the position as an absolute offset from the start. + * @param[out] bpos is a pointer to the block position to fill in. + */ +void rtems_rfs_block_get_bpos (rtems_rfs_file_system* fs, + rtems_rfs_pos pos, + rtems_rfs_block_pos* bpos); + +/** + * Given a block position compute the absolute offset. + * + * @param[in] fs is the file system data. + * @param[out] bpos is a pointer to the block position to fill in. + * + * @retval offset The absolute offset. + */ +rtems_rfs_pos rtems_rfs_block_get_pos (rtems_rfs_file_system* fs, + rtems_rfs_block_pos* bpos); + +/** + * Add the relative position to the block position. The relative position is + * signed. + * + * @param[in] fs is the file system data. + * @param[in] offset is the relative offset add to the block position. + * @param[out] bpos is a pointer to the block position to fill in. + */ +static inline void +rtems_rfs_block_add_pos (rtems_rfs_file_system* fs, + rtems_rfs_pos_rel offset, + rtems_rfs_block_pos* bpos) +{ + rtems_rfs_block_get_bpos (fs, + rtems_rfs_block_get_pos (fs, bpos) + offset, + bpos); + bpos->block = 0; +} + +/** + * A block size is the number of blocks less one plus the offset where the + * offset must be less than the block size. + */ +typedef struct rtems_rfs_block_size_s +{ + /** + * The count of blocks in a map. A 0 means no blocks and a zero length and + * the offset should also be 0. + */ + rtems_rfs_block_no count; + + /** + * The offset into the block. An offset of 0 means block size, ie the first + * byte of the next block which is not allocated. + */ + rtems_rfs_block_off offset; + +} rtems_rfs_block_size; + +/** + * Copy a block size. + * + * @param[in] _lhs is the left hand side. + * @param[in] _rhs is the right hand side. + */ +#define rtems_rfs_block_copy_size(_lhs, _rhs) \ + do { (_lhs)->count = (_rhs)->count; \ + (_lhs)->offset = (_rhs)->offset; } while (0) + +/** + * Last block ? + */ +#define rtems_rfs_block_pos_last_block(_p, _s) \ + ((((_p)->bno == 0) && ((_s)->count == 0)) || ((_p)->bno == ((_s)->count - 1))) + +/** + * Last block ? + */ +#define rtems_rfs_block_pos_past_end(_p, _s) \ + (((_p)->bno && ((_s)->count == 0)) || \ + ((_p)->bno >= (_s)->count) || \ + (((_p)->bno == ((_s)->count - 1)) && ((_p)->boff > (_s)->offset))) + +/** + * Is the block position past the end. + */ +#define rtems_rfs_block_pos_block_past_end(_p, _s) \ + (((_p)->bno && ((_s)->count == 0)) || ((_p)->bno >= (_s)->count)) + +/** + * Copy the size to the block position. Note the block position and the size + * have different block counts. + */ +#define rtems_rfs_block_size_get_bpos(_s, _b) \ + do { (_b)->bno = (_s)->count; \ + (_b)->boff = (_s)->offset; \ + (_b)->block = 0; \ + if ((_b)->boff) --(_b)->bno; } while (0) + +/** + * Do the sizes match ? + */ +#define rtems_rfs_block_size_equal(_lhs, _rhs) \ + (((_lhs)->count == (_rhs)->count) && ((_lhs)->offset == (_rhs)->offset)) + +/** + * Zero a block size. + * + * @param[in] size is a pointer to the block size. + */ +static inline void +rtems_rfs_block_set_size_zero (rtems_rfs_block_size* size) +{ + size->count = 0; + size->offset = 0; +} + +/** + * Set the size given a position. + * + * @param[in] fs is the file system data. + * @param[in] pos is the position as an absolute offset from the start. + * @param[out] size is a pointer to the block size to fill in. + */ +void rtems_rfs_block_get_block_size (rtems_rfs_file_system* fs, + rtems_rfs_pos pos, + rtems_rfs_block_size* size); + +/** + * Calculate the position given the number of blocks and the offset. If the + * block count is 0 the size is 0. If the block is greater than 0 and the + * offset is 0 the size is number of blocks multipled by the block size and if + * the offset is not 0 it is the offset into the last block. For example if + * blocks is 1 and offset is 0 the size is the block size. If the block count + * is 1 and size is 100 the size is 100. + * + * @param[in] fs is the file system data. + * @param[in] size The size in blocks and offset. + * + * @retval size The size in bytes. + */ +rtems_rfs_pos rtems_rfs_block_get_size (rtems_rfs_file_system* fs, + rtems_rfs_block_size* size); + +#endif diff --git a/cpukit/include/rtems/rfs/rtems-rfs-block.h b/cpukit/include/rtems/rfs/rtems-rfs-block.h new file mode 100644 index 0000000000..394853b7ad --- /dev/null +++ b/cpukit/include/rtems/rfs/rtems-rfs-block.h @@ -0,0 +1,344 @@ +/** + * @file + * + * @brief RTEMS File Systems Block Management + * + * @ingroup rtems_rfs + * + * RTEMS File Systems Block Management. + * + * These functions manage the blocks used in the file system. + */ + +/* + * COPYRIGHT (c) 2010 Chris Johns <chrisj@rtems.org> + * + * 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_BLOCK_H_) +#define _RTEMS_RFS_BLOCK_H_ + +#include <rtems/rfs/rtems-rfs-block-pos.h> +#include <rtems/rfs/rtems-rfs-buffer.h> +#include <rtems/rfs/rtems-rfs-data.h> +#include <rtems/rfs/rtems-rfs-file-system.h> + +/** + * Get a block number in the media format and return it in the host format. + * + * @param[in] _h is the buffer handle of the block. + * @param[in] _b is the block number index. + * + * @retval block The block number. + */ +#define rtems_rfs_block_get_number(_h, _b) \ + ((rtems_rfs_block_no) \ + (rtems_rfs_read_u32 (rtems_rfs_buffer_data (_h) + \ + ((_b) * sizeof (rtems_rfs_block_no))))) + +/** + * Set a block number in the media format given a number in the host format. + * + * @param[in] _h is the buffer handle of the block. + * @param[in] _b is the block number index, ie the number of block number not the + * buffer offset. + * @param[in] _n is the block number. + */ +#define rtems_rfs_block_set_number(_h, _b, _n) \ + do { \ + rtems_rfs_write_u32 (rtems_rfs_buffer_data (_h) + \ + ((_b) * sizeof (rtems_rfs_block_no)), (_n)); \ + rtems_rfs_buffer_mark_dirty (_h); \ + } while (0) + +/** + * A block map manges the block lists that originate from an inode. The inode + * contains a number of block numbers. A block map takes those block numbers + * and manages them. + * + * The blocks cannot have all ones as a block number nor block 0. The block map + * is series of block numbers in a blocks. The size of the map determines the + * way the block numbers are stored. The map uses the following: + * + * @li @e Direct Access, + * @li @e Single Indirect Access, and + * @li @e Double Indirect Access. + * + * Direct access has the blocks numbers in the inode slots. The Single Indirect + * Access has block numbers in the inode slots that pointer to a table of block + * numbers that point to data blocks. The Double Indirect Access has block + * numbers in the inode that point to Single Indirect block tables. + * + * The inode can hold a number of Direct, Single Indirect, and Double Indirect + * block tables. The move from Direct to Single occurs then the block count in + * the map is above the number of slots in the inode. The move from Single to + * Double occurs when the map block count is greated than the block numbers per + * block multipled by the slots in the inode. The move from Single to Double + * occurs when the map block count is over the block numbers per block squared + * multipled by the number of slots in the inode. + * + * The block map can managed files of the follow size verses block size with 5 + * inode slots: + * + * @li 41,943,040 bytes for a 512 byte block size, + * @li 335,544,320 bytes for a 1024 byte block size, + * @li 2,684,354,560 bytes for a 2048 byte block size, and + * @li 21,474,836,480 bytes for a 4096 byte block size. + */ +typedef struct rtems_rfs_block_map_s +{ + /** + * Is the map dirty ? + */ + bool dirty; + + /** + * The inode this map is attached to. + */ + rtems_rfs_inode_handle* inode; + + /** + * The size of the map. + */ + rtems_rfs_block_size size; + + /** + * The block map position. Used to navigate the map when seeking. The find + * call is to a position in the file/directory and is a block number plus + * offset. The block find only needs to locate a block and not worry about + * the offset while a seek can be less than a block size yet move across a + * block boundary. Therefore the position a block map has to maintain must + * include the offset so seeks work. + */ + rtems_rfs_block_pos bpos; + + /** + * The last map block allocated. This is used as the goal when allocating a + * new map block. + */ + rtems_rfs_block_no last_map_block; + + /** + * The last data block allocated. This is used as the goal when allocating a + * new data block. + */ + rtems_rfs_block_no last_data_block; + + /** + * The block map. + */ + uint32_t blocks[RTEMS_RFS_INODE_BLOCKS]; + + /** + * Singly Buffer handle. + */ + rtems_rfs_buffer_handle singly_buffer; + + /** + * Doubly Buffer handle. + */ + rtems_rfs_buffer_handle doubly_buffer; + +} rtems_rfs_block_map; + +/** + * Is the map dirty ? + */ +#define rtems_rfs_block_map_is_dirty(_m) ((_m)->dirty) + +/** + * Return the block count in the map. + */ +#define rtems_rfs_block_map_count(_m) ((_m)->size.count) + +/** + * Return the map's size element. + */ +#define rtems_rfs_block_map_size(_m) (&((_m)->size)) + +/** + * Return the size offset for the map. + */ +#define rtems_rfs_block_map_size_offset(_m) ((_m)->size.offset) + +/** + * Are we at the last block in the map ? + */ +#define rtems_rfs_block_map_last(_m) \ + rtems_rfs_block_pos_last_block (&(_m)->bpos, &(_m)->size) + +/** + * Is the position past the end of the block ? + */ +#define rtems_rfs_block_map_past_end(_m, _p) \ + rtems_rfs_block_pos_past_end (_p, &(_m)->size) + +/** + * Return the current position in the map. + */ +#define rtems_rfs_block_map_pos(_f, _m) \ + rtems_rfs_block_get_pos (_f, &(_m)->bpos) + +/** + * Return the map's current block number. + */ +#define rtems_rfs_block_map_block(_m) ((_m)->bpos.bno) + +/** + * Return the map's current block offset. + */ +#define rtems_rfs_block_map_block_offset(_m) ((_m)->bpos.boff) + +/** + * Set the size offset for the map. The map is tagged as dirty. + * + * @param[in] map is a pointer to the open map to set the offset in. + * @param[in] offset is the offset to set in the map's size. + */ +static inline void +rtems_rfs_block_map_set_size_offset (rtems_rfs_block_map* map, + rtems_rfs_block_off offset) +{ + map->size.offset = offset; + map->dirty = true; +} + +/** + * Set the map's size. The map is tagged as dirty. + * + * @param[in] map is a pointer to the open map to set the offset in. + * @param[in] size is the size to set in the map's size. + */ +static inline void +rtems_rfs_block_map_set_size (rtems_rfs_block_map* map, + rtems_rfs_block_size* size) +{ + rtems_rfs_block_copy_size (&map->size, size); + map->dirty = true; +} +/** + * Open a block map. The block map data in the inode is copied into the + * map. The buffer handles are opened. The block position is set to the start + * so a seek of offset 0 will return the first block. + * + * @param[in] fs is the file system data. + * @param[in] inode is a pointer to the inode the map belongs to. + * @param[in] map is a pointer to the map that is opened. + * + * @retval 0 Successful operation. + * @retval error_code An error occurred. + */ +int rtems_rfs_block_map_open (rtems_rfs_file_system* fs, + rtems_rfs_inode_handle* inode, + rtems_rfs_block_map* map); + +/** + * Close the map. The buffer handles are closed and any help buffers are + * released. + * + * @param[in] fs is the file system data. + * @param[in] map is a pointer to the map that is opened. + * + * @retval 0 Successful operation. + * @retval error_code An error occurred. + */ +int rtems_rfs_block_map_close (rtems_rfs_file_system* fs, + rtems_rfs_block_map* map); + +/** + * Find a block number in the map from the position provided. + * + * @param[in] fs is the file system data. + * @param[in] map is a pointer to the map to search. + * @param[in] bpos is a pointer to the block position to find. + * @param[out] block will contain the block in when found. + * + * @retval 0 Successful operation. + * @retval error_code An error occurred. + */ +int rtems_rfs_block_map_find (rtems_rfs_file_system* fs, + rtems_rfs_block_map* map, + rtems_rfs_block_pos* bpos, + rtems_rfs_buffer_block* block); + +/** + * Seek around the map. + * + * @param[in] fs is the file system data. + * @param[in] map is a pointer to the map to search. + * @param[in] offset is the distance to seek. It is signed. + * @param[out] block will contain the block in when found. + * + * @retval 0 Successful operation. + * @retval ENXIO Failed to seek because it is outside the block map. + * @retval error_code An error occurred. + */ +int rtems_rfs_block_map_seek (rtems_rfs_file_system* fs, + rtems_rfs_block_map* map, + rtems_rfs_pos_rel offset, + rtems_rfs_buffer_block* block); + +/** + * Seek to the next block. + * + * @param[in] fs is the file system data. + * @param[in] map is a pointer to the map to search. + * @param[out] block will contain the block in when found. + * + * @retval 0 Successful operation. + * @retval ENXIO Failed to seek because it is outside the block map. + * @retval error_code An error occurred. + */ +int rtems_rfs_block_map_next_block (rtems_rfs_file_system* fs, + rtems_rfs_block_map* map, + rtems_rfs_buffer_block* block); + +/** + * Grow the block map by the specified number of blocks. + * + * @param[in] fs is the file system data. + * @param[in] map is a pointer to the open map to grow. + * @param[in] blocks is the number of blocks to grow the map by. + * @param[out] new_block will contain first of the blocks allocated + * to the map. + * + * @retval 0 Successful operation. + * @retval error_code An error occurred. + */ +int rtems_rfs_block_map_grow (rtems_rfs_file_system* fs, + rtems_rfs_block_map* map, + size_t blocks, + rtems_rfs_block_no* new_block); + +/** + * Grow the block map by the specified number of blocks. + * + * @param[in] fs is the file system data. + * @param[in] map is a pointer to the open map to shrink. + * @param[in] blocks is the number of blocks to shrink the map by. If more + * than the number of blocks the map is emptied. + * + * @retval 0 Successful operation. + * @retval error_code An error occurred. + */ +int rtems_rfs_block_map_shrink (rtems_rfs_file_system* fs, + rtems_rfs_block_map* map, + size_t blocks); + +/** + * Free all blocks in the map. + * + * @param[in] fs is the file system data. + * @param[in] map is a pointer to the open map to free all blocks from. + * + * @retval 0 Successful operation. + * @retval error_code An error occurred. + */ +int rtems_rfs_block_map_free_all (rtems_rfs_file_system* fs, + rtems_rfs_block_map* map); + +#endif diff --git a/cpukit/include/rtems/rfs/rtems-rfs-buffer.h b/cpukit/include/rtems/rfs/rtems-rfs-buffer.h new file mode 100644 index 0000000000..1c603e1827 --- /dev/null +++ b/cpukit/include/rtems/rfs/rtems-rfs-buffer.h @@ -0,0 +1,283 @@ +/** + * @file + * + * @ingroup rtems_rfs + * + * @brief Maps Blocks to the Media Interface Layers + * + * These functions map blocks to the media interface layers. + */ + +/* + * COPYRIGHT (c) 2010 Chris Johns <chrisj@rtems.org> + * + * 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_BUFFER_H_) +#define _RTEMS_RFS_BUFFER_H_ + +#include <errno.h> + +#include <rtems/rfs/rtems-rfs-file-system-fwd.h> +#include <rtems/rfs/rtems-rfs-trace.h> + +/** + * Define the method used to interface to the buffers. It can be libblock or + * device I/O. The libblock interface is to the RTEMS cache and block devices + * and device I/O accesses the media via a device file handle. + */ +#if defined (__rtems__) +#define RTEMS_RFS_USE_LIBBLOCK 1 +#endif + +/** + * The RTEMS RFS I/O Layering. + */ +#if RTEMS_RFS_USE_LIBBLOCK +#include <rtems/bdbuf.h> +#include <rtems/error.h> + +typedef rtems_blkdev_bnum rtems_rfs_buffer_block; +typedef rtems_bdbuf_buffer rtems_rfs_buffer; +#define rtems_rfs_buffer_io_request rtems_rfs_buffer_bdbuf_request +#define rtems_rfs_buffer_io_release rtems_rfs_buffer_bdbuf_release + +/** + * Request a buffer from the RTEMS libblock BD buffer cache. + */ +int rtems_rfs_buffer_bdbuf_request (rtems_rfs_file_system* fs, + rtems_rfs_buffer_block block, + bool read, + rtems_rfs_buffer** buffer); +/** + * Release a buffer to the RTEMS libblock BD buffer cache. + */ +int rtems_rfs_buffer_bdbuf_release (rtems_rfs_buffer* handle, + bool modified); +#else /* Device I/O */ +typedef uint32_t rtems_rfs_buffer_block; +typedef struct _rtems_rfs_buffer +{ + rtems_chain_node link; + rtems_rfs_buffer_block user; + void* buffer; + size_t size; + uint32_t references; +} rtems_rfs_buffer; +#define rtems_rfs_buffer_io_request rtems_rfs_buffer_deviceio_request +#define rtems_rfs_buffer_io_release rtems_rfs_buffer_deviceio_release + +/** + * Request a buffer from the device I/O. + */ +int rtems_rfs_buffer_deviceio_request (rtems_rfs_file_system* fs, + rtems_rfs_buffer_block block, + bool read, + rtems_rfs_buffer* buffer); +/** + * Release a buffer to the RTEMS libblock BD buffer cache. + */ +int rtems_rfs_buffer_deviceio_release (rtems_rfs_buffer* handle, + bool modified); +#endif + +/** + * RFS Buffer handle. + */ +typedef struct rtems_rfs_buffer_handle_t +{ + /** + * Has the buffer been modifed? + */ + bool dirty; + + /** + * Block number. The lower layer block number may be absolute and we maybe + * relative to an offset in the disk so hold locally. + */ + rtems_rfs_buffer_block bnum; + + /** + * Reference the buffer descriptor. + */ + rtems_rfs_buffer* buffer; + +} rtems_rfs_buffer_handle; + +/** + * The buffer linkage. + */ +#define rtems_rfs_buffer_link(_h) (&(_h)->buffer->link) + +/** + * Return the start of the data area of the buffer given a handle. + */ +#define rtems_rfs_buffer_data(_h) ((void*)((_h)->buffer->buffer)) + +/** + * Return the size of the buffer given a handle. + */ +#define rtems_rfs_buffer_size(_h) ((_h)->buffer->size) + +/** + * Return the block number. + */ +#define rtems_rfs_buffer_bnum(_h) ((_h)->bnum) + +/** + * Return the buffer dirty status. + */ +#define rtems_rfs_buffer_dirty(_h) ((_h)->dirty) + +/** + * Does the handle have a valid block attached ? + */ +#define rtems_rfs_buffer_handle_has_block(_h) ((_h)->buffer ? true : false) + +/** + * Mark the buffer as dirty. + */ +#define rtems_rfs_buffer_mark_dirty(_h) ((_h)->dirty = true) + +/** + * Return the reference count. + */ +#define rtems_rfs_buffer_refs(_h) ((_h)->buffer->references) + +/** + * Increment the reference count. + */ +#define rtems_rfs_buffer_refs_up(_h) ((_h)->buffer->references += 1) + +/** + * Decrement the reference count. + */ +#define rtems_rfs_buffer_refs_down(_h) ((_h)->buffer->references -= 1) + +/** + * Request a buffer. The buffer can be filled with data from the media + * (read == true) or you can request a buffer to fill with data. + * + * @param[in] fs is the file system data. + * @param[in] handle is the handle the requested buffer is attached to. + * @param[in] block is the block number. + * @param[in] read Read the data from the disk. + * + * @retval 0 Successful operation. + * @retval error_code An error occurred. + */ +int rtems_rfs_buffer_handle_request (rtems_rfs_file_system* fs, + rtems_rfs_buffer_handle* handle, + rtems_rfs_buffer_block block, + bool read); + +/** + * Release a buffer. If the buffer is dirty the buffer is written to disk. The + * result does not indicate if the data was successfully written to the disk as + * this operation may be performed in asynchronously to this release. + * + * @param[in] fs is the file system data. + * @param[in] handle is the handle the requested buffer is attached to. + * + * @retval 0 Successful operation. + * @retval error_code An error occurred. + */ +int rtems_rfs_buffer_handle_release (rtems_rfs_file_system* fs, + rtems_rfs_buffer_handle* handle); + +/** + * Open a handle. + * + * @param[in] fs i the file system data. + * @param[in] handle i the buffer handle to open. + * + * @retval 0 Successful operation. + * @retval error_code An error occurred. + */ +static inline int +rtems_rfs_buffer_handle_open (rtems_rfs_file_system* fs, + rtems_rfs_buffer_handle* handle) +{ + handle->dirty = false; + handle->bnum = 0; + handle->buffer = NULL; + return 0; +} + +/** + * Close a handle. + * + * @param[in] fs is the file system data. + * @param[in] handle is the buffer handle to close. + * + * @retval 0 Successful operation. + * @retval error_code An error occurred. + */ +static inline int +rtems_rfs_buffer_handle_close (rtems_rfs_file_system* fs, + rtems_rfs_buffer_handle* handle) +{ + rtems_rfs_buffer_handle_release (fs, handle); + handle->dirty = false; + handle->bnum = 0; + handle->buffer = NULL; + return 0; +} + +/** + * Open the buffer interface. + * + * @param[in] name is a pointer to the device name to the media. + * @param[in] fs is the file system data. + * + * @retval 0 Successful operation. + * @retval error_code An error occurred. + */ +int rtems_rfs_buffer_open (const char* name, rtems_rfs_file_system* fs); + +/** + * Close the buffer interface. + * + * @param[in] fs is the file system data. + * + * @retval 0 Successful operation. + * @retval error_code An error occurred. + */ +int rtems_rfs_buffer_close (rtems_rfs_file_system* fs); + +/** + * Sync all buffers to the media. + * + * @param[in] fs is the file system data. + * + * @retval 0 Successful operation. + * @retval error_code An error occurred. + */ +int rtems_rfs_buffer_sync (rtems_rfs_file_system* fs); + +/** + * Set the block size of the device. + * + * @param[in] fs is the file system data. + * @param[in] size is the new block size. + * + * @retval 0 Successful operation. + * @retval error_code An error occurred. + */ +int rtems_rfs_buffer_setblksize (rtems_rfs_file_system* fs, uint32_t size); + +/** + * Release any chained buffers. + * + * @param[in] fs is the file system data. + * + * @retval 0 Successful operation. + * @retval error_code An error occurred. + */ +int rtems_rfs_buffers_release (rtems_rfs_file_system* fs); + +#endif diff --git a/cpukit/include/rtems/rfs/rtems-rfs-data.h b/cpukit/include/rtems/rfs/rtems-rfs-data.h new file mode 100644 index 0000000000..6217e74587 --- /dev/null +++ b/cpukit/include/rtems/rfs/rtems-rfs-data.h @@ -0,0 +1,89 @@ +/** + * @file + * + * @brief RTEMS File System Data + * + * @ingroup rtems_rfs + * + * RTEMS File System Data. + * + * Access data in the correct byte order for the specific target we are running + * on. + * + * @todo Make direct access on matching byte ordered targets. + */ + +/* + * COPYRIGHT (c) 2010 Chris Johns <chrisj@rtems.org> + * + * 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_DATA_H_) +#define _RTEMS_RFS_DATA_H_ + +#include <stdint.h> + +/** + * Helper function to make sure we have a byte pointer. + */ +#define rtems_rfs_data_ptr(_d) ((uint8_t*)(_d)) + +/** + * Helper function to get the data shifted in the correctly sized type. + */ +#define rtems_rfs_data_get(_d, _t, _o, _s) \ + (((_t)(rtems_rfs_data_ptr (_d)[_o])) << (_s)) + +/** + * RFS Read Unsigned 8bit Integer + */ +#define rtems_rfs_read_u8(_d) \ + (*rtems_rfs_data_ptr (_d)) + +/** + * RFS Read Unsigned 16bit Integer + */ +#define rtems_rfs_read_u16(_d) \ + (rtems_rfs_data_get (_d, uint16_t, 0, 8) | \ + rtems_rfs_data_get (_d, uint16_t, 1, 0)) + +/** + * RFS Read Unsigned 32bit Integer + */ +#define rtems_rfs_read_u32(_d) \ + (rtems_rfs_data_get (_d, uint32_t, 0, 24) | \ + rtems_rfs_data_get (_d, uint32_t, 1, 16) | \ + rtems_rfs_data_get (_d, uint32_t, 2, 8) | \ + rtems_rfs_data_get (_d, uint32_t, 3, 0)) + +/** + * RFS Write Unsigned 8bit Integer + */ +#define rtems_rfs_write_u8(_d, _v) \ + (*rtems_rfs_data_ptr (_d) = (uint8_t)(_v)) + +/** + * RFS Write Unsigned 16bit Integer + */ +#define rtems_rfs_write_u16(_d, _v) \ + do { \ + rtems_rfs_data_ptr (_d)[0] = (uint8_t)(((uint16_t)(_v)) >> 8); \ + rtems_rfs_data_ptr (_d)[1] = (uint8_t)((_v)); \ + } while (0) + +/** + * RFS Write Unsigned 32bit Integer + */ +#define rtems_rfs_write_u32(_d, _v) \ + do { \ + rtems_rfs_data_ptr (_d)[0] = (uint8_t)(((uint32_t)(_v)) >> 24); \ + rtems_rfs_data_ptr (_d)[1] = (uint8_t)(((uint32_t)(_v)) >> 16); \ + rtems_rfs_data_ptr (_d)[2] = (uint8_t)(((uint32_t)(_v)) >> 8); \ + rtems_rfs_data_ptr (_d)[3] = (uint8_t)((uint32_t)(_v)); \ + } while (0) + +#endif diff --git a/cpukit/include/rtems/rfs/rtems-rfs-dir-hash.h b/cpukit/include/rtems/rfs/rtems-rfs-dir-hash.h new file mode 100644 index 0000000000..d9a8a2004f --- /dev/null +++ b/cpukit/include/rtems/rfs/rtems-rfs-dir-hash.h @@ -0,0 +1,36 @@ +/** + * @file + * + * @brief Provides a 32bit Hash of a String used to Search a Directory + * + * @ingroup rtems_rfs + * + * RTEMS File Systems Directory Hash provides a 32bit hash of a string. This is + * used to search a directory. + */ + +/* + * COPYRIGHT (c) 2010 Chris Johns <chrisj@rtems.org> + * + * 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_DIR_HASH_H_) +#define _RTEMS_RFS_DIR_HAS_H_ + +#include <stddef.h> +#include <stdint.h> + +/** + * Compute a hash of the key over the length of string. + * + * @param[in] key is a pointer to the key to calculate the hash of. + * @param[in] length is the length of the key in bytes. + * + * @retval hash The computed uint32_t hash. + */ +uint32_t rtems_rfs_dir_hash (const void *key, size_t length); + +#endif diff --git a/cpukit/include/rtems/rfs/rtems-rfs-dir.h b/cpukit/include/rtems/rfs/rtems-rfs-dir.h new file mode 100644 index 0000000000..ae3647d03c --- /dev/null +++ b/cpukit/include/rtems/rfs/rtems-rfs-dir.h @@ -0,0 +1,209 @@ +/** + * @file + * + * @brief RTEMS File System Directory Support + * + * @ingroup rtems_rfs + * + * RTEMS File System Directory Support + * + * This file provides the directory support functions. + */ + +/* + * COPYRIGHT (c) 2010 Chris Johns <chrisj@rtems.org> + * + * 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_DIR_H_) +#define _RTEMS_RFS_DIR_H_ + +#include <dirent.h> + +#include <rtems/libio_.h> + +#include <rtems/rfs/rtems-rfs-data.h> +#include <rtems/rfs/rtems-rfs-file-system.h> +#include <rtems/rfs/rtems-rfs-inode.h> + +/** + * Define the offsets of the fields of a directory entry. + */ +#define RTEMS_RFS_DIR_ENTRY_INO (0) /**< The ino offset in a directory + * entry. */ +#define RTEMS_RFS_DIR_ENTRY_HASH (4) /**< The hash offset in a directory + * entry. The hash is 32bits. We need at + * least 16bits and given the length and + * ino field are 4 the extra 2 bytes is + * not a big overhead.*/ +#define RTEMS_RFS_DIR_ENTRY_LEN (8) /**< The length offset in a directory + * entry. */ + +/** + * The length of the directory entry header. + */ +#define RTEMS_RFS_DIR_ENTRY_SIZE (4 + 4 + 2) + +/** + * The length when the remainder of the directory block is empty. + */ +#define RTEMS_RFS_DIR_ENTRY_EMPTY (0xffff) + +/** + * Return the hash of the entry. + * + * @param[in] _e is a pointer to the directory entry. + * + * @retval hash The uint32_t hash of the entry. + */ +#define rtems_rfs_dir_entry_hash(_e) \ + rtems_rfs_read_u32 (_e + RTEMS_RFS_DIR_ENTRY_HASH) + +/** + * Set the hash of the entry. + * + * @param[in] _e is a pointer to the directory entry. + * + * @param[in] _h is the hash of the entry. + */ +#define rtems_rfs_dir_set_entry_hash(_e, _h) \ + rtems_rfs_write_u32 (_e + RTEMS_RFS_DIR_ENTRY_HASH, _h) + +/** + * Return the ino of the entry. + * + * @param[in] _e is a pointer to the directory entry. + * + * @retval ino The ino of the entry. + */ +#define rtems_rfs_dir_entry_ino(_e) \ + rtems_rfs_read_u32 (_e + RTEMS_RFS_DIR_ENTRY_INO) + +/** + * Set the ino of the entry. + * + * @param[in] _e is a pointer to the directory entry. + * + * @param[in] _i is the ino of the entry. + */ +#define rtems_rfs_dir_set_entry_ino(_e, _i) \ + rtems_rfs_write_u32 (_e + RTEMS_RFS_DIR_ENTRY_INO, _i) + +/** + * Return the length of the entry. + * + * @param[in] _e Pointer to the directory entry. + * + * @retval length The length of the entry. + */ +#define rtems_rfs_dir_entry_length(_e) \ + rtems_rfs_read_u16 (_e + RTEMS_RFS_DIR_ENTRY_LEN) + +/** + * Set the length of the entry. + * + * @param[in] _e is a pointer to the directory entry. + * @param[in] _l is the length. + */ +#define rtems_rfs_dir_set_entry_length(_e, _l) \ + rtems_rfs_write_u16 (_e + RTEMS_RFS_DIR_ENTRY_LEN, _l) + +/** + * Look up a directory entry in the directory pointed to by the inode. The look + * up is local to this directory. No need to decend. + * + * @param[in] fs is the file system. + * @param[in] inode is a pointer to the inode of the directory to search. + * @param[in] name is a pointer to the name to look up. The name may not be + * nul terminated. + * @param[in] length is the length of the name. + * @param[out] ino will be filled in with the inode number + * if there is no error. + * @param[in] offset is the offset in the directory for the entry. + * + * @retval 0 Successful operation. + * @retval error_code An error occurred. + */ +int rtems_rfs_dir_lookup_ino (rtems_rfs_file_system* fs, + rtems_rfs_inode_handle* inode, + const char* name, + int length, + rtems_rfs_ino* ino, + uint32_t* offset); + +/** + * Add an entry to the directory returing the inode number allocated to the + * entry. + * + * @param[in] fs is the file system data. + * @param[in] dir is a pointer to the directory inode the + * entry is to be added too. + * @param[in] name is a pointer to the name of the entry to be added. + * @param[in] length is the length of the name excluding a terminating 0. + * @param[in] ino is the ino of the entry. + * + * @retval 0 Successful operation. + * @retval error_code An error occurred. + */ +int rtems_rfs_dir_add_entry (rtems_rfs_file_system* fs, + rtems_rfs_inode_handle* dir, + const char* name, + size_t length, + rtems_rfs_ino ino); + +/** + * Del an entry from the directory using an inode number as a key. + * + * @param[in] fs is the file system data. + * @param[in] dir is a pointer to the directory inode the + * entry is to be deleted from. + * @param[in] ino is the ino of the entry. + * @param[in] offset is the offset in the directory of the entry + * to delete. If 0 search from the start for the ino. + * + * @retval 0 Successful operation. + * @retval error_code An error occurred. + */ +int rtems_rfs_dir_del_entry (rtems_rfs_file_system* fs, + rtems_rfs_inode_handle* dir, + rtems_rfs_ino ino, + uint32_t offset); + +/** + * Read the directory entry from offset into the directory entry buffer and + * return the length of space this entry uses in the directory table. + * + * @param[in] fs is the file system data. + * @param[in] dir is a pointer to the direct inode handler. + * @param[in] offset is the offset in the directory to read from. + * @param[in] dirent is a ointer to the dirent structure the entry + * is written into. + * @param[out] length will contain the length this entry + * takes in the directory. + * + * @retval 0 Successful operation. + * @retval error_code An error occurred. + */ +int rtems_rfs_dir_read (rtems_rfs_file_system* fs, + rtems_rfs_inode_handle* dir, + rtems_rfs_pos_rel offset, + struct dirent* dirent, + size_t* length); + +/** + * Check if the directory is empty. The current and parent directory entries + * are ignored. + * + * @param[in] fs is the file system data + * @param[in] dir is a pointer to the directory inode to check. + * + * @retval 0 Successful operation. + * @retval error_code An error occurred. + */ +int rtems_rfs_dir_empty (rtems_rfs_file_system* fs, + rtems_rfs_inode_handle* dir); + +#endif diff --git a/cpukit/include/rtems/rfs/rtems-rfs-file-system-fwd.h b/cpukit/include/rtems/rfs/rtems-rfs-file-system-fwd.h new file mode 100644 index 0000000000..e239c25d6f --- /dev/null +++ b/cpukit/include/rtems/rfs/rtems-rfs-file-system-fwd.h @@ -0,0 +1,29 @@ +/** + * @file + * + * @brief RTEMS File Systems Data Forward Declaration + * + * @ingroup rtems_rfs + * + * RTEMS File Systems Data forward decl. + */ + +/* + * COPYRIGHT (c) 2010 Chris Johns <chrisj@rtems.org> + * + * 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_SYSTEM_FWD_H_) +#define _RTEMS_RFS_FILE_SYSTEM_FWD_H_ + +/** + * Forward reference to the file system data. + */ +struct _rtems_rfs_file_system; +typedef struct _rtems_rfs_file_system rtems_rfs_file_system; + +#endif diff --git a/cpukit/include/rtems/rfs/rtems-rfs-file-system.h b/cpukit/include/rtems/rfs/rtems-rfs-file-system.h new file mode 100644 index 0000000000..e00b142532 --- /dev/null +++ b/cpukit/include/rtems/rfs/rtems-rfs-file-system.h @@ -0,0 +1,410 @@ +/** + * @file + * + * @brief RTEMS File System Data + * + * @ingroup rtems_rfs + * + * RTEMS File System Data + * + * This file defines the file system data. + */ + +/* + * COPYRIGHT (c) 2010 Chris Johns <chrisj@rtems.org> + * + * 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_SYSTEM_H_) +#define _RTEMS_RFS_FILE_SYSTEM_H_ + +#include <rtems/rfs/rtems-rfs-group.h> + +/** + * Superblock offsets and values. + */ +#define RTEMS_RFS_SB_OFFSET_MAGIC (0) +#define RTEMS_RFS_SB_MAGIC (0x28092001) +#define RTEMS_RFS_SB_OFFSET_VERSION (RTEMS_RFS_SB_OFFSET_MAGIC + 4) +#define RTEMS_RFS_SB_OFFSET_BLOCK_SIZE (RTEMS_RFS_SB_OFFSET_VERSION + 4) +#define RTEMS_RFS_SB_OFFSET_BLOCKS (RTEMS_RFS_SB_OFFSET_BLOCK_SIZE + 4) +#define RTEMS_RFS_SB_OFFSET_BAD_BLOCKS (RTEMS_RFS_SB_OFFSET_BLOCKS + 4) +#define RTEMS_RFS_SB_OFFSET_MAX_NAME_LENGTH (RTEMS_RFS_SB_OFFSET_BAD_BLOCKS + 4) +#define RTEMS_RFS_SB_OFFSET_GROUPS (RTEMS_RFS_SB_OFFSET_MAX_NAME_LENGTH + 4) +#define RTEMS_RFS_SB_OFFSET_GROUP_BLOCKS (RTEMS_RFS_SB_OFFSET_GROUPS + 4) +#define RTEMS_RFS_SB_OFFSET_GROUP_INODES (RTEMS_RFS_SB_OFFSET_GROUP_BLOCKS + 4) +#define RTEMS_RFS_SB_OFFSET_INODE_SIZE (RTEMS_RFS_SB_OFFSET_GROUP_INODES + 4) + +/** + * RFS Version Number. + */ +#define RTEMS_RFS_VERSION (0x00000000) + +/** + * RFS Version Number Mask. The mask determines which bits of the version + * number indicate compatility issues. + */ +#define RTEMS_RFS_VERSION_MASK INT32_C(0x00000000) + +/** + * The root inode number. Do not use 0 as this has special meaning in some + * Unix operating systems. + */ +#define RTEMS_RFS_ROOT_INO (1) + +/** + * Empty inode number. + */ +#define RTEMS_RFS_EMPTY_INO (0) + +/** + * The number of blocks in the inode. This number effects the size of the + * inode and that effects the overhead of the inode tables in a group. + */ +#define RTEMS_RFS_INODE_BLOCKS (5) + +/** + * The inode overhead is the percentage of space reserved for inodes. It is + * calculated as the percentage number of blocks in a group. The number of + * blocks in a group is the number of bits a block can hold. + */ +#define RTEMS_RFS_INODE_OVERHEAD_PERCENTAGE (1) + +/** + * Number of blocks in the superblock. Yes I know it is a superblock and not + * superblocks but if for any reason this needs to change it is handled. + */ +#define RTEMS_RFS_SUPERBLOCK_SIZE (1) + +/** + * The maximum number of buffers held by the file system at any one time. + */ +#define RTEMS_RFS_FS_MAX_HELD_BUFFERS (5) + +/** + * Absolute position. Make a 64bit value. + */ +typedef uint64_t rtems_rfs_pos; + +/** + * Relative position. Make a 64bit value. + */ +typedef int64_t rtems_rfs_pos_rel; + +/** + * Flags to control the file system. + */ +#define RTEMS_RFS_FS_BITMAPS_HOLD (1 << 0) /**< Do not release bitmaps + * when finished. Default is + * off so they are released. */ +#define RTEMS_RFS_FS_NO_LOCAL_CACHE (1 << 1) /**< Do not cache the buffers + * and release directly to the + * buffer support layer. The + * default is to hold buffers. */ +#define RTEMS_RFS_FS_FORCE_OPEN (1 << 2) /**< Force open and ignore any + * errors. */ +#define RTEMS_RFS_FS_READ_ONLY (1 << 3) /**< Make the mount + * read-only. Currently not + * supported. */ +/** + * RFS File System data. + */ +struct _rtems_rfs_file_system +{ + /** + * Flags to control the file system. Some can be controlled via the ioctl. + */ + uint32_t flags; + + /** + * The number of blocks in the disk. The size of the disk is the number of + * blocks by the block size. This should be within a block size of the size + * returned by the media driver. + */ + size_t blocks; + + /** + * The size of a block. This must be a multiple of the disk's media block + * size. + */ + size_t block_size; + + /** + * The file descriptor for device I/O. + */ + int device; + +#if RTEMS_RFS_USE_LIBBLOCK + /** + * The disk device. This is the data about the block device this file system + * is mounted on. We access the data held in this structure rather than + * making an extra copy in this structure. + */ + rtems_disk_device* disk; +#else + /** + * The number of blocks in the file system. + */ + size_t size; +#endif + + /** + * Inode count. + */ + uint32_t inodes; + + /** + * Bad block blocks. This is a table of blocks that have been found to be + * bad. + */ + uint32_t bad_blocks; + + /** + * Maximum length of names supported by this file system. + */ + uint32_t max_name_length; + + /** + * A disk is broken down into a series of groups. + */ + rtems_rfs_group* groups; + + /** + * Number of groups. + */ + int group_count; + + /** + * Number of blocks in a group. + */ + size_t group_blocks; + + /** + * Number of inodes in a group. + */ + size_t group_inodes; + + /** + * Number of inodes in each block. + */ + size_t inodes_per_block; + + /** + * Number of block numbers in a block. + */ + size_t blocks_per_block; + + /** + * Block map single indirect count. This is the block number per block + * multiplied but the slots in the inode. + */ + size_t block_map_singly_blocks; + + /** + * Block map double indirect count. This is the block number per block + * squared and multiplied by the slots in the inode. It is the maximum + * number of blocks a map (file/directory) can have. + */ + size_t block_map_doubly_blocks; + + /** + * Number of buffers held before releasing back to the cache. + */ + uint32_t max_held_buffers; + + /** + * List of buffers attached to buffer handles. Allows sharing. + */ + rtems_chain_control buffers; + + /** + * Number of buffers held on the buffers list. + */ + uint32_t buffers_count; + + /** + * List of buffers that need to be released when the processing of a file + * system request has completed. + */ + rtems_chain_control release; + + /** + * Number of buffers held on the release list. + */ + uint32_t release_count; + + /** + * List of buffers that need to be released modified when the processing of a + * file system request has completed. + */ + rtems_chain_control release_modified; + + /** + * Number of buffers held on the release modified list. + */ + uint32_t release_modified_count; + + /** + * List of open shared file node data. The shared node data such as the inode + * and block map allows a single file to be open more than once. + */ + rtems_chain_control file_shares; + + /** + * Pointer to user data supplied when opening. + */ + void* user; +}; + +/** + * Return the flags. + * + * @param[in] _fs is a pointer to the file system. + */ +#define rtems_rfs_fs_flags(_f) ((_f)->flags) +/** + * Should bitmap buffers be released when finished ? + * + * @param[in] _fs is a pointer to the file system. + */ +#define rtems_rfs_fs_release_bitmaps(_f) (!((_f)->flags & RTEMS_RFS_FS_BITMAPS_HOLD)) + +/** + * Are the buffers locally cache or released back to the buffering layer ? + * + * @param[in] _fs is a pointer to the file system. + */ +#define rtems_rfs_fs_no_local_cache(_f) ((_f)->flags & RTEMS_RFS_FS_NO_LOCAL_CACHE) + +/** + * The disk device number. + * + * @param[in] _fs is a pointer to the file system. + */ +#if RTEMS_RFS_USE_LIBBLOCK +#define rtems_rfs_fs_device(_fs) ((_fs)->disk) +#else +#define rtems_rfs_fs_device(_fs) ((_fs)->device) +#endif + +/** + * The size of the disk in blocks. + * + * @param[in] _fs is a pointer to the file system. + */ +#define rtems_rfs_fs_blocks(_fs) ((_fs)->blocks) + +/** + * The block size. + * + * @param[in] _fs is a pointer to the file system. + */ +#define rtems_rfs_fs_block_size(_fs) ((_fs)->block_size) + +/** + * The number of inodes. + * + * @param[in] _fs is a pointer to the file system. + */ +#define rtems_rfs_fs_inodes(_fs) ((_fs)->inodes) + +/** + * Calculate a block in the file system given the group and the block within + * the group. + * + * @param[in] _fs is a pointer to the file system. + * @param[in] _grp is the group. + * @param[in] _blk is the block within the group. + * @return The absolute block number. + */ +#define rtems_rfs_fs_block(_fs, _grp, _blk) \ + ((((_fs)->group_blocks) * (_grp)) + (_blk) + 1) + +/** + * The media size of the disk in media size blocks. + * + * @param[in] _fs is a pointer to the file system. + */ +#if RTEMS_RFS_USE_LIBBLOCK +#define rtems_rfs_fs_media_blocks(_fs) ((_fs)->disk->size) +#else +#define rtems_rfs_fs_media_blocks(_fs) ((_fs)->media_size) +#endif + +/** + * The media block size. This is the size of a block on disk. For a device I/O + * this value is 1. + * + * @param[in] _fs is a pointer to the file system. + */ +#if RTEMS_RFS_USE_LIBBLOCK +#define rtems_rfs_fs_media_block_size(_fs) ((_fs)->disk->media_block_size) +#else +#define rtems_rfs_fs_media_block_size(_fs) (1) +#endif + +/** + * The maximum length of a name supported by the file system. + */ +#define rtems_rfs_fs_max_name(_fs) ((_fs)->max_name_length) + +/** + * Return the maximum number of blocks in a block map. + * + * @return uint32_t The maximum number of blocks possible. + */ +#define rtems_rfs_fs_max_block_map_blocks(_fs) ((_fs)->block_map_doubly_blocks) + +/** + * Return the user pointer. + */ +#define rtems_rfs_fs_user(_fs) ((_fs)->user) + +/** + * Return the size of the disk in bytes. + * + * @param[in] fs is a pointer to the file system. + * @return uint64_t The size of the disk in bytes. + */ +uint64_t rtems_rfs_fs_size(rtems_rfs_file_system* fs); + +/** + * The size of the disk in bytes calculated from the media parameters.. + * + * @param[in] fs is a pointer to the file system. + * @return uint64_t The size of the disk in bytes. + */ +uint64_t rtems_rfs_fs_media_size (rtems_rfs_file_system* fs); + +/** + * Open the file system given a file path. + * + * @param[in] name is a pointer to the device to open. + * @param[in] fs is the file system data filled in by this call. + * @param[in] user is a pointer to the user data. + * @param[in] flags is a initial set of user flags for the file system. + * @param[in] max_held_buffers is the maximum number of buffers the RFS holds. + * + * @retval 0 Successful operation. + * @retval -1 Error. See errno + */ +int rtems_rfs_fs_open (const char* name, + void* user, + uint32_t flags, + uint32_t max_held_buffers, + rtems_rfs_file_system** fs); + +/** + * Close the file system. + * + * @param[in] fs is the file system data. + * + * @retval 0 Successful operation. + * @retval -1 Error. See errno + */ +int rtems_rfs_fs_close (rtems_rfs_file_system* fs); + +#endif diff --git a/cpukit/include/rtems/rfs/rtems-rfs-file.h b/cpukit/include/rtems/rfs/rtems-rfs-file.h new file mode 100644 index 0000000000..772e846143 --- /dev/null +++ b/cpukit/include/rtems/rfs/rtems-rfs-file.h @@ -0,0 +1,416 @@ +/** + * @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 <chrisj@rtems.org> + * + * 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 <rtems/libio_.h> + +#include <rtems/rfs/rtems-rfs-block.h> +#include <rtems/rfs/rtems-rfs-data.h> +#include <rtems/rfs/rtems-rfs-file-system.h> +#include <rtems/rfs/rtems-rfs-inode.h> + +/** + * 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 diff --git a/cpukit/include/rtems/rfs/rtems-rfs-group.h b/cpukit/include/rtems/rfs/rtems-rfs-group.h new file mode 100644 index 0000000000..23e6434b2c --- /dev/null +++ b/cpukit/include/rtems/rfs/rtems-rfs-group.h @@ -0,0 +1,181 @@ +/** + * @file + * + * @brief RTEMS File Systems Group Management + * + * @ingroup rtems_rfs + * + * RTEMS File Systems Group Management. + * + * These functions manage the groups used in the file system. + */ + +/* + * COPYRIGHT (c) 2010 Chris Johns <chrisj@rtems.org> + * + * 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_GROUP_H_) +#define _RTEMS_RFS_GROUP_H_ + +/** + * @ingroup rtems_rfs + * + * RTEMS File System Group Management + */ +/**@{*/ + +#include <rtems/rfs/rtems-rfs-trace.h> +#include <rtems/rfs/rtems-rfs-bitmaps.h> +#include <rtems/rfs/rtems-rfs-buffer.h> + +/** + * Block allocations for a group on disk. + */ +#define RTEMS_RFS_GROUP_BLOCK_BITMAP_BLOCK (0) +#define RTEMS_RFS_GROUP_INODE_BITMAP_BLOCK (1) +#define RTEMS_RFS_GROUP_INODE_BLOCK (2) + +/** + * @brief Creates bit allocator for blocks in the group simpler. + * + * A group is a selection of blocks on the disk. Typically the number of blocks + * in a group is determined by the number of bits a block holds. This makes the + * bit allocator for blocks in the group simpler plus is allows a simple way to + * localise access to files and directories. + */ +typedef struct _rtems_rfs_group +{ + /** + * Base block number. + */ + rtems_rfs_buffer_block base; + + /** + * The number of blocks in the group. Groups may be different sizes. + */ + size_t size; + + /** + * The block bitmap control. + */ + rtems_rfs_bitmap_control block_bitmap; + + /** + * The handle to the block bitmap buffer. + */ + rtems_rfs_buffer_handle block_bitmap_buffer; + + /** + * The inode bitmap control. + */ + rtems_rfs_bitmap_control inode_bitmap; + + /** + * The handle to the inode bitmap buffer. + */ + rtems_rfs_buffer_handle inode_bitmap_buffer; + +} rtems_rfs_group; + +/** + * Return the disk's block for a block in a group. + */ +#define rtems_rfs_group_block(_g, _b) (((_g)->base) + (_b)) + +/** + * Return the file system inode for a inode in a group. + */ +#define rtems_rfs_group_inode(_f, _g, _i) \ + (((_f)->group_inodes * (_g)) + (_i) + RTEMS_RFS_ROOT_INO) + +/** + * @brief Open a group. + * + * Allocate all the resources including the bitmaps. + * + * @param fs The file system. + * @param base The base block number. + * @param size The number of blocks in the group. + * @param group Reference to the group to open. + * @retval int The error number (errno). No error if 0. + */ +int rtems_rfs_group_open (rtems_rfs_file_system* fs, + rtems_rfs_buffer_block base, + size_t size, + size_t inodes, + rtems_rfs_group* group); + +/** + * @brief Close a group. + * + * Release all resources the group holds. + * + * @param fs The file system. + * @param group The group to close. + * @retval int The error number (errno). No error if 0. + */ +int rtems_rfs_group_close (rtems_rfs_file_system* fs, + rtems_rfs_group* group); + +/** + * @brief Allocate an inode or block. + * + * The groups are searched to find the next + * available inode or block. + * + * @param fs The file system data. + * @param goal The goal to seed the bitmap search. + * @param inode If true allocate an inode else allocate a block. + * @param result The allocated bit in the bitmap. + * @retval int The error number (errno). No error if 0. + */ +int rtems_rfs_group_bitmap_alloc (rtems_rfs_file_system* fs, + rtems_rfs_bitmap_bit goal, + bool inode, + rtems_rfs_bitmap_bit* result); + +/** + * @brief Free the group allocated bit. + * + * @param fs The file system data. + * @param inode If true the number to free is an inode else it is a block. + * @param block The inode or block number to free. + * @retval int The error number (errno). No error if 0. + */ +int rtems_rfs_group_bitmap_free (rtems_rfs_file_system* fs, + bool inode, + rtems_rfs_bitmap_bit no); + +/** + * @brief Test the group allocated bit. + * + * @param fs The file system data. + * @param inode If true the number to free is an inode else it is a block. + * @param block The inode or block number to free. + * @param state Return the state of the bit. + * @retval int The error number (errno). No error if 0. + */ +int rtems_rfs_group_bitmap_test (rtems_rfs_file_system* fs, + bool inode, + rtems_rfs_bitmap_bit no, + bool* state); + +/** + * @brief Determine the number of blocks and inodes used. + * + * @param fs The file system data. + * @param blocks The number of blocks used. + * @param inodes The number of inodes used. + * @retval int The error number (errno). No error if 0. + */ +int rtems_rfs_group_usage (rtems_rfs_file_system* fs, + size_t* blocks, + size_t* inodes); + +/** @} */ +#endif diff --git a/cpukit/include/rtems/rfs/rtems-rfs-inode.h b/cpukit/include/rtems/rfs/rtems-rfs-inode.h new file mode 100644 index 0000000000..95861ea8a7 --- /dev/null +++ b/cpukit/include/rtems/rfs/rtems-rfs-inode.h @@ -0,0 +1,728 @@ +/** + * @file + * + * @brief RTEMS File System Information Node + * + * @ingroup rtems_rfs + * + * RTEMS File System Information Node. + * + * The information nodes hold the data about all nodes in the file system. + */ + +/* + * COPYRIGHT (c) 2010 Chris Johns <chrisj@rtems.org> + * + * 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_INODE_H_) +#define _RTEMS_RFS_INODE_H_ + +#include <sys/stat.h> + +#include <rtems/rfs/rtems-rfs-data.h> +#include <rtems/rfs/rtems-rfs-file-system.h> + +/** + * The RFS mode definitions. Currently map to the C library ones. + */ +#define RTEMS_RFS_S_ISUID S_ISUID /**< Set user id on execution */ +#define RTEMS_RFS_S_ISGID S_ISGID /**< Set group id on execution */ +#define RTEMS_RFS_S_ISVTX S_ISVTX /**< Save swapped text even after use */ +#define RTEMS_RFS_S_IREAD S_IREAD /**< Read permission, owner */ +#define RTEMS_RFS_S_IWRITE S_IWRITE /**< Write permission, owner */ +#define RTEMS_RFS_S_IEXEC S_IEXEC /**< Execute/search permission, owner */ +#define RTEMS_RFS_S_ENFMT S_ENFMT /**< Enforcement-mode locking */ +#define RTEMS_RFS_S_IFMT S_IFMT /**< Type of file */ +#define RTEMS_RFS_S_IFDIR S_IFDIR /**< Directory */ +#define RTEMS_RFS_S_IFCHR S_IFCHR /**< Character special */ +#define RTEMS_RFS_S_IFBLK S_IFBLK /**< Block special */ +#define RTEMS_RFS_S_IFREG S_IFREG /**< Regular */ +#define RTEMS_RFS_S_IFLNK S_IFLNK /**< Symbolic link */ +#define RTEMS_RFS_S_IFSOCK S_IFSOCK /**< Socket */ +#define RTEMS_RFS_S_IFIFO S_IFIFO /**< Fifo */ +#define RTEMS_RFS_S_IRWXU S_IRWXU +#define RTEMS_RFS_S_IRUSR S_IRUSR /**< Read permission, owner */ +#define RTEMS_RFS_S_IWUSR S_IWUSR /**< Write permission, owner */ +#define RTEMS_RFS_S_IXUSR S_IXUSR /**< Execute/search permission, owner */ +#define RTEMS_RFS_S_IRWXG S_IRWXG +#define RTEMS_RFS_S_IRGRP S_IRGRP /**< Read permission, group */ +#define RTEMS_RFS_S_IWGRP S_IWGRP /**< Write permission, grougroup */ +#define RTEMS_RFS_S_IXGRP S_IXGRP /**< Execute/search permission, group */ +#define RTEMS_RFS_S_IRWXO S_IRWXO +#define RTEMS_RFS_S_IROTH S_IROTH /**< Read permission, other */ +#define RTEMS_RFS_S_IWOTH S_IWOTH /**< Write permission, other */ +#define RTEMS_RFS_S_IXOTH S_IXOTH /**< Execute/search permission, other */ + +#define RTEMS_RFS_S_ISBLK(m) S_ISBLK(m) +#define RTEMS_RFS_S_ISCHR(m) S_ISCHR(m) +#define RTEMS_RFS_S_ISDIR(m) S_ISDIR(m) +#define RTEMS_RFS_S_ISFIFO(m) S_ISFIFO(m) +#define RTEMS_RFS_S_ISREG(m) S_ISREG(m) +#define RTEMS_RFS_S_ISLNK(m) S_ISLNK(m) +#define RTEMS_RFS_S_ISSOCK(m) S_ISSOCK(m) + +/** + * Permissions of a symlink. + */ +#define RTEMS_RFS_S_SYMLINK \ + RTEMS_RFS_S_IFLNK | RTEMS_RFS_S_IRWXU | RTEMS_RFS_S_IRWXG | RTEMS_RFS_S_IRWXO + +/** + * The inode number or ino. + */ +typedef uint32_t rtems_rfs_ino; + +/** + * The time in the file system. + */ +typedef uint32_t rtems_rfs_time; + +/** + * The size of a block value on disk. This include the inodes and indirect + * tables. + */ +typedef uint32_t rtems_rfs_inode_block; + +/** + * The size of the data name field in the inode. + */ +#define RTEMS_RFS_INODE_DATA_NAME_SIZE \ + (RTEMS_RFS_INODE_BLOCKS * sizeof (rtems_rfs_inode_block)) + +/** + * The inode. + */ +typedef struct _rtems_rfs_inode +{ + /** + * The number of links to the inode. + */ + uint16_t links; + + /** + * The mode of the node. + */ + uint16_t mode; + + /** + * The owner of the node. + */ + uint32_t owner; + + /** + * Reserved. + */ + uint16_t flags; + + /** + * Amount of data held in the last block data. + */ + uint16_t block_offset; + + /** + * Number of blocks held by this file. + */ + uint32_t block_count; + + /** + * 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; + + /** + * Blocks. These are the block numbers used by the node or table of + * nodes. The flags indicate the mode the blocks are being held in. In the + * direct table mode the blocks are entries in this table. In the indirect + * mode the blocks point to blocks that hold the block numbers. The data can + * also be a name if it fits. For example a symbolic link. + */ + union + { + rtems_rfs_inode_block blocks[RTEMS_RFS_INODE_BLOCKS]; + uint8_t name[RTEMS_RFS_INODE_DATA_NAME_SIZE]; + } data; + + /** + * The last block map block. Used as the goal when allocating a new block for + * use in the map. + */ + rtems_rfs_inode_block last_map_block; + + /** + * The last data block. Used as the goal when allocating a new block. + */ + rtems_rfs_inode_block last_data_block; + +} rtems_rfs_inode; + +/** + * The size of an inode. + */ +#define RTEMS_RFS_INODE_SIZE (sizeof (rtems_rfs_inode)) + +/** + * RFS Inode Handle. + */ +typedef struct _rtems_rfs_inode_handle +{ + /** + * Handles can be linked as a list for easy processing. + */ + rtems_chain_node link; + + /** + * The ino for this handle. + */ + rtems_rfs_ino ino; + + /** + * The pointer to the inode. + */ + rtems_rfs_inode* node; + + /** + * The buffer that contains this inode. + */ + rtems_rfs_buffer_handle buffer; + + /** + * The block number that holds the inode. + */ + rtems_rfs_buffer_block block; + + /** + * The offset into the block for the inode. + */ + int offset; + + /** + * Number of load requests. + */ + int loads; + +} rtems_rfs_inode_handle; + +/** + * Is the inode loaded ? + */ +#define rtems_rfs_inode_is_loaded(_h) ((_h)->node) + +/** + * Get the inode ino for a handle. + */ +#define rtems_rfs_inode_ino(_h) ((_h)->ino) + +/** + * Get the link count. + * + * @param[in] handle is the inode handle. + * + * @retval links The link count. + */ +static inline uint16_t +rtems_rfs_inode_get_links (rtems_rfs_inode_handle* handle) +{ + uint16_t links; + links = rtems_rfs_read_u16 (&handle->node->links); + if (links == 0xffff) + links = 0; + return links; +} + +/** + * Set the link count. + * + * @param[in] handle is the inode handle. + * @param[in] links are the links. + */ +static inline void +rtems_rfs_inode_set_links (rtems_rfs_inode_handle* handle, uint16_t links) +{ + rtems_rfs_write_u16 (&handle->node->links, links); + rtems_rfs_buffer_mark_dirty (&handle->buffer); +} + +/** + * Get the flags. + * + * @param[in] handle is the inode handle. + * + * @retval flags The flags. + */ +static inline uint16_t +rtems_rfs_inode_get_flags (rtems_rfs_inode_handle* handle) +{ + return rtems_rfs_read_u16 (&handle->node->flags); +} + +/** + * Set the flags. + * + * @param[in] handle is the inode handle. + * @param[in] flags are the flags. + */ +static inline void +rtems_rfs_inode_set_flags (rtems_rfs_inode_handle* handle, uint16_t flags) +{ + rtems_rfs_write_u16 (&handle->node->flags, flags); + rtems_rfs_buffer_mark_dirty (&handle->buffer); +} + +/** + * Get the mode. + * + * @param[in] handle is the inode handle. + * + * @retval mode The mode. + */ +static inline uint16_t +rtems_rfs_inode_get_mode (rtems_rfs_inode_handle* handle) +{ + return rtems_rfs_read_u16 (&handle->node->mode); +} + +/** + * Set the mode. + * + * @param[in] handle is the inode handle. + * @param[in] mode is the mode. + */ +static inline void +rtems_rfs_inode_set_mode (rtems_rfs_inode_handle* handle, uint16_t mode) +{ + rtems_rfs_write_u16 (&handle->node->mode, mode); + rtems_rfs_buffer_mark_dirty (&handle->buffer); +} + +/** + * Get the user id. + * + * @param[in] handle is the inode handle. + * + * @retval uid The used id. + */ +static inline uint16_t +rtems_rfs_inode_get_uid (rtems_rfs_inode_handle* handle) +{ + return rtems_rfs_read_u32 (&handle->node->owner) & 0xffff; +} + +/** + * Get the group id. + * + * @param[in] handle is the inode handle. + * + * @retval gid The grpup id. + */ +static inline uint16_t +rtems_rfs_inode_get_gid (rtems_rfs_inode_handle* handle) +{ + return (rtems_rfs_read_u32 (&handle->node->owner) >> 16) & 0xffff; +} + +/** + * Set the user id and group id. + * + * @param[in] handle is the inode handle. + * @param[in] uid is the user id (uid). + * @param[in] gid is the group id (gid). + */ +static inline void +rtems_rfs_inode_set_uid_gid (rtems_rfs_inode_handle* handle, + uint16_t uid, uint16_t gid) +{ + rtems_rfs_write_u32 (&handle->node->owner, (((uint32_t) gid) << 16) | uid); + rtems_rfs_buffer_mark_dirty (&handle->buffer); +} + +/** + * Get the block offset. + * + * @param[in] handle is the inode handle. + * + * @retval offset The block offset. + */ +static inline uint16_t +rtems_rfs_inode_get_block_offset (rtems_rfs_inode_handle* handle) +{ + return rtems_rfs_read_u16 (&handle->node->block_offset); +} + +/** + * Set the block offset. + * + * @param[in] handle is the inode handle. + * @param[in] block_count is the block offset. + */ +static inline void +rtems_rfs_inode_set_block_offset (rtems_rfs_inode_handle* handle, + uint16_t block_offset) +{ + rtems_rfs_write_u16 (&handle->node->block_offset, block_offset); + rtems_rfs_buffer_mark_dirty (&handle->buffer); +} + +/** + * Get the block count. + * + * @param[in] handle is the inode handle. + * + * @retval count The block count. + */ +static inline uint32_t +rtems_rfs_inode_get_block_count (rtems_rfs_inode_handle* handle) +{ + return rtems_rfs_read_u32 (&handle->node->block_count); +} + +/** + * Set the block count. + * + * @param[in] handle is the inode handle. + * @param[in] block_count is the block count. + */ +static inline void +rtems_rfs_inode_set_block_count (rtems_rfs_inode_handle* handle, uint32_t block_count) +{ + rtems_rfs_write_u32 (&handle->node->block_count, block_count); + rtems_rfs_buffer_mark_dirty (&handle->buffer); +} + +/** + * Get the atime. + * + * @param[in] handle is the inode handle. + * + * @retval atime The atime. + */ +static inline rtems_rfs_time +rtems_rfs_inode_get_atime (rtems_rfs_inode_handle* handle) +{ + return rtems_rfs_read_u32 (&handle->node->atime); +} + +/** + * Set the atime. + * + * @param[in] handle is the inode handle. + * @param[in] atime The atime. + */ +static inline void +rtems_rfs_inode_set_atime (rtems_rfs_inode_handle* handle, + rtems_rfs_time atime) +{ + rtems_rfs_write_u32 (&handle->node->atime, atime); + rtems_rfs_buffer_mark_dirty (&handle->buffer); +} + +/** + * Get the mtime. + * + * @param[in] handle is the inode handle. + * + * @retval mtime The mtime. + */ +static inline rtems_rfs_time +rtems_rfs_inode_get_mtime (rtems_rfs_inode_handle* handle) +{ + return rtems_rfs_read_u32 (&handle->node->mtime); +} + +/** + * Set the mtime. + * + * @param[in] handle is the inode handle. + * @param[in] mtime The mtime. + */ +static inline void +rtems_rfs_inode_set_mtime (rtems_rfs_inode_handle* handle, + rtems_rfs_time mtime) +{ + rtems_rfs_write_u32 (&handle->node->mtime, mtime); + rtems_rfs_buffer_mark_dirty (&handle->buffer); +} + +/** + * Get the ctime. + * + * @param[in] handle is the inode handle. + * + * @retval ctime The ctime. + */ +static inline rtems_rfs_time +rtems_rfs_inode_get_ctime (rtems_rfs_inode_handle* handle) +{ + return rtems_rfs_read_u32 (&handle->node->ctime); +} + +/** + * Set the ctime. + * + * @param[in] handle is the inode handle. + * @param[in] ctime The ctime. + */ +static inline void +rtems_rfs_inode_set_ctime (rtems_rfs_inode_handle* handle, + rtems_rfs_time ctime) +{ + rtems_rfs_write_u32 (&handle->node->ctime, ctime); + rtems_rfs_buffer_mark_dirty (&handle->buffer); +} + +/** + * Get the block number. + * + * @param[in] handle is the inode handle. + * @param[in] block is the block number to return. + * + * @retval block The block number. + */ +static inline uint32_t +rtems_rfs_inode_get_block (rtems_rfs_inode_handle* handle, int block) +{ + return rtems_rfs_read_u32 (&handle->node->data.blocks[block]); +} + +/** + * Set the block number for a given block index. + * + * @param[in] handle is the inode handle. + * @param[in] block is the block index. + * @param[in] bno is the block number. + */ +static inline void +rtems_rfs_inode_set_block (rtems_rfs_inode_handle* handle, int block, uint32_t bno) +{ + rtems_rfs_write_u32 (&handle->node->data.blocks[block], bno); + rtems_rfs_buffer_mark_dirty (&handle->buffer); +} + +/** + * Get the last map block from the inode. + * + * @param[in] handle is the inode handle. + * + * @retval block The last map block number. + */ +static inline uint32_t +rtems_rfs_inode_get_last_map_block (rtems_rfs_inode_handle* handle) +{ + return rtems_rfs_read_u32 (&handle->node->last_map_block); +} + +/** + * Set the last map block. + * + * @param[in] handle is the inode handle. + * @param[in] block_count is last map block number. + */ +static inline void +rtems_rfs_inode_set_last_map_block (rtems_rfs_inode_handle* handle, uint32_t last_map_block) +{ + rtems_rfs_write_u32 (&handle->node->last_map_block, last_map_block); + rtems_rfs_buffer_mark_dirty (&handle->buffer); +} + +/** + * Get the last data block from the inode. + * + * @param[in] handle is the inode handle. + * + * @retval block The last data block number. + * + */ +static inline uint32_t +rtems_rfs_inode_get_last_data_block (rtems_rfs_inode_handle* handle) +{ + return rtems_rfs_read_u32 (&handle->node->last_data_block); +} + +/** + * Set the last data block. + * + * @param[in] handle is the inode handle. + * @param[in] block_count is the last data block number. + */ +static inline void +rtems_rfs_inode_set_last_data_block (rtems_rfs_inode_handle* handle, uint32_t last_data_block) +{ + rtems_rfs_write_u32 (&handle->node->last_data_block, last_data_block); + rtems_rfs_buffer_mark_dirty (&handle->buffer); +} + +/** + * Allocate an inode number and return it. + * + * @param[in] fs is the file system data. + * @param[out] ino will contain the ino. + * + * @retval 0 Successful operation. + * @retval error_code An error occurred. + */ +int rtems_rfs_inode_alloc (rtems_rfs_file_system* fs, + rtems_rfs_bitmap_bit goal, + rtems_rfs_ino* ino); + +/** + * Free an inode. + * + * @param[in] fs is the file system data. + * @param[in] ino is the ino too free. + * + * @retval 0 Successful operation. + * @retval error_code An error occurred. + */ +int rtems_rfs_inode_free (rtems_rfs_file_system* fs, + rtems_rfs_ino ino); + +/** + * Open the inode handle. This reads the inode into the buffer and sets the + * data pointer. All data is in media byte order and needs to be accessed via + * the supporting calls. + * + * @param[in] fs is the file system. + * @param[in] ino is the inode number. + * @param[in] handle is the handle to the inode we are opening. + * @param[in] load If true load the inode into memory from the media. + * + * @retval 0 Successful operation. + * @retval error_code An error occurred. + */ +int rtems_rfs_inode_open (rtems_rfs_file_system* fs, + rtems_rfs_ino ino, + rtems_rfs_inode_handle* handle, + bool load); + +/** + * The close inode handle. All opened inodes need to be closed. + * + * @param[in] fs is the file system. + * @param[in] handle is the handle to close. + * + * @retval 0 Successful operation. + * @retval error_code An error occurred. + */ +int rtems_rfs_inode_close (rtems_rfs_file_system* fs, + rtems_rfs_inode_handle* handle); + +/** + * Load the inode into memory. + * + * @param[in] fs is the file system. + * @param[in] handle is the inode handle to load. + * + * @retval 0 Successful operation. + * @retval error_code An error occurred. + */ +int rtems_rfs_inode_load (rtems_rfs_file_system* fs, + rtems_rfs_inode_handle* handle); + +/** + * Unload the inode from memory. + * + * @param[in] fs is the file system. + * @param[in] handle is the inode handle to unload. + * @param[in] update_ctime Update the ctime field of the inode. + * + * @retval 0 Successful operation. + * @retval error_code An error occurred. + */ +int rtems_rfs_inode_unload (rtems_rfs_file_system* fs, + rtems_rfs_inode_handle* handle, + bool update_ctime); + +/** + * Create an inode allocating, initialising and adding an entry to the parent + * directory. + * + * @param[in] fs is the file system data. + * @param[in] parent is the parent inode number to add the directory entry to. + * @param[in] name is a pointer to the name of the directory entryinode + * to create. + * + */ +int rtems_rfs_inode_create (rtems_rfs_file_system* fs, + rtems_rfs_ino parent, + const char* name, + size_t length, + uint16_t mode, + uint16_t links, + uid_t uid, + gid_t gid, + rtems_rfs_ino* ino); + +/** + * Delete the inode eraseing it and release the buffer to commit the write. You + * need to load the inode again if you wish to use it again. + * + * @param[in] fs is the file system. + * @param[in] handle is the inode handle to erase. + * + * @retval 0 Successful operation. + * @retval error_code An error occurred. + */ +int rtems_rfs_inode_delete (rtems_rfs_file_system* fs, + rtems_rfs_inode_handle* handle); + +/** + * Initialise a new inode. + * + * @param[in] handle is the inode handle to initialise. + * @param[in] links are the number of links to the inode. + * @param[in] mode is the inode mode. + * @param[in] uid is the user id. + * @param[in] gid is the group id. + * + * @retval 0 Successful operation. + * @retval error_code An error occurred. + */ +int rtems_rfs_inode_initialise (rtems_rfs_inode_handle* handle, + uint16_t links, + uint16_t mode, + uid_t uid, + gid_t gid); + +/** + * Time stamp the inode with the current time. The ctime field is hanlded + * automatically. + * + * @param[in] handle is the inode handle. + * @param[in] atime Update the atime field. + * @param[in] mtime UPdate the mtime field. + * + * @retval 0 Successful operation. + * @retval ENXIO No inode is loaded. + * @retval error_code An error occurred. + */ +int rtems_rfs_inode_time_stamp_now (rtems_rfs_inode_handle* handle, + bool atime, + bool mtime); + +/** + * Calculate the size of data attached to the inode. + * + * @param[in] fs is the file system data. + * @param[in] handle is the inode handle. + * + * @retval size The data size in bytes in the block map attched to the inode. + */ +rtems_rfs_pos rtems_rfs_inode_get_size (rtems_rfs_file_system* fs, + rtems_rfs_inode_handle* handle); + +#endif + diff --git a/cpukit/include/rtems/rfs/rtems-rfs-link.h b/cpukit/include/rtems/rfs/rtems-rfs-link.h new file mode 100644 index 0000000000..d30814aaff --- /dev/null +++ b/cpukit/include/rtems/rfs/rtems-rfs-link.h @@ -0,0 +1,124 @@ +/** + * @file + * + * @brief RTEMS File System Link Support + * + * @ingroup rtems_rfs + * + * RTEMS File System Link Support + * + * This file provides the link support functions. + */ + +/* + * COPYRIGHT (c) 2010 Chris Johns <chrisj@rtems.org> + * + * 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_LINK_H_) +#define _RTEMS_RFS_LINK_H_ + +#include <dirent.h> + +#include <rtems/rfs/rtems-rfs-file-system.h> +#include <rtems/rfs/rtems-rfs-inode.h> + +/** + * Directory unlink modes. + */ +typedef enum rtems_rfs_unlink_dir_e +{ + rtems_rfs_unlink_dir_denied, /**< Not allowed to unlink a directory. */ + rtems_rfs_unlink_dir_if_empty, /**< Unlink if the directory is empty. */ + rtems_rfs_unlink_dir_allowed /**< Unlinking of directories is allowed. */ +} rtems_rfs_unlink_dir; + +/** + * Create a link. Do not link directories unless renaming or you will create + * loops in the file system. + * + * @param[in] fs is the file system. + * @param[in] name is a pointer to the name of the link. + * @param[in] length is the length of the name. + * @param[in] parent is the inode number of the parent directory. + * @param[in] target is the inode of the target. + * @param[in] link_dir If true directories can be linked. Useful when + * renaming. + * + * @retval 0 Successful operation. + * @retval error_code An error occurred. + */ +int rtems_rfs_link (rtems_rfs_file_system* fs, + const char* name, + int length, + rtems_rfs_ino parent, + rtems_rfs_ino target, + bool link_dir); + +/** + * Unlink the node from the parent directory. A directory offset for the + * target entry is required because links cause a number of inode numbers to + * appear in a single directory so scanning does not work. + * + * @param[in] fs is the file system. + * @param[in] parent is the inode number of the parent directory. + * @param[in] target is the inode of the target. + * @param[in] doff is the parent directory entry offset for the target entry. + * @param[in] dir_mode is the directory unlink mode. + * + * @retval 0 Successful operation. + * @retval error_code An error occurred. + */ +int rtems_rfs_unlink (rtems_rfs_file_system* fs, + rtems_rfs_ino parent, + rtems_rfs_ino target, + uint32_t doff, + rtems_rfs_unlink_dir dir_mode); + +/** + * Symbolic link is an inode that has a path attached. + * + * @param[in] fs is the file system data. + * @param[in] name is a pointer to the name of the node. + * @param[in] length is the length of the name of the node. + * @param[in] link is a pointer to the link path attached to the + * symlink inode. + * @param[in] link_length is the length of the link path. + * @param[in] parent is the parent inode number. + * + * @retval 0 Successful operation. + * @retval error_code An error occurred. + */ +int rtems_rfs_symlink (rtems_rfs_file_system* fs, + const char* name, + int length, + const char* link, + int link_length, + uid_t uid, + gid_t gid, + rtems_rfs_ino parent); + +/** + * Read a symbolic link into the provided buffer returning the link of link + * name. + * + * @param[in] fs is the file system data. + * @param[in] link is the link inode number to read. + * @param[in] path is a pointer to the buffer to write the link path into. + * @param[in] size is the size of the buffer. + * @param[out] length will contain the length of the link path. + * + * @retval 0 Successful operation. + * @retval error_code An error occurred. + */ +int rtems_rfs_symlink_read (rtems_rfs_file_system* fs, + rtems_rfs_ino link, + char* path, + size_t size, + size_t* length); + +#endif diff --git a/cpukit/include/rtems/rfs/rtems-rfs-mutex.h b/cpukit/include/rtems/rfs/rtems-rfs-mutex.h new file mode 100644 index 0000000000..606fd53233 --- /dev/null +++ b/cpukit/include/rtems/rfs/rtems-rfs-mutex.h @@ -0,0 +1,116 @@ +/** + * @file + * + * @brief RTEMS File System Mutex + * + * @ingroup rtems_rfs + * + * RTEMS File System Mutex. + * + * It may be suprising we abstract this for the RTEMS file system but this code + * is designed to be run on host operating systems. + */ + +/* + * COPYRIGHT (c) 2010 Chris Johns <chrisj@rtems.org> + * + * 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_MUTEX_H_) +#define _RTEMS_RFS_MUTEX_H_ + +#include <errno.h> + +#include <rtems/rfs/rtems-rfs-trace.h> + +#if __rtems__ +#include <rtems.h> +#include <rtems/error.h> +#endif + +/** + * RFS Mutex type. + */ +#if __rtems__ +typedef rtems_id rtems_rfs_mutex; +#else +typedef uint32_t rtems_rfs_mutex; /* place holder */ +#endif + +/** + * @brief Create the mutex. + * + * @param [in] mutex is pointer to the mutex handle returned to the caller. + * + * @retval 0 Successful operation. + * @retval EIO An error occurred. + * + */ +int rtems_rfs_mutex_create (rtems_rfs_mutex* mutex); + +/** + * @brief Destroy the mutex. + * + * @param[in] mutex Reference to the mutex handle returned to the caller. + * + * @retval 0 Successful operation. + * @retval EIO An error occurred. + */ +int rtems_rfs_mutex_destroy (rtems_rfs_mutex* mutex); + +/** + * @brief Lock the mutex. + * + * @param[in] mutex is a pointer to the mutex to lock. + * + * @retval 0 Successful operation. + * @retval EIO An error occurred. + */ +static inline int +rtems_rfs_mutex_lock (rtems_rfs_mutex* mutex) +{ +#if __rtems__ + rtems_status_code sc = rtems_semaphore_obtain (*mutex, RTEMS_WAIT, 0); + if (sc != RTEMS_SUCCESSFUL) + { +#if RTEMS_RFS_TRACE + if (rtems_rfs_trace (RTEMS_RFS_TRACE_MUTEX)) + printf ("rtems-rfs: mutex: obtain failed: %s\n", + rtems_status_text (sc)); +#endif + return EIO; + } +#endif + return 0; +} + +/** + * @brief Unlock the mutex. + * + * @param[in] mutex is a pointer to the mutex to unlock. + * + * @retval 0 Successful operation. + * @retval EIO An error occurred. + */ +static inline int +rtems_rfs_mutex_unlock (rtems_rfs_mutex* mutex) +{ +#if __rtems__ + rtems_status_code sc = rtems_semaphore_release (*mutex); + if (sc != RTEMS_SUCCESSFUL) + { +#if RTEMS_RFS_TRACE + if (rtems_rfs_trace (RTEMS_RFS_TRACE_MUTEX)) + printf ("rtems-rfs: mutex: release failed: %s\n", + rtems_status_text (sc)); +#endif + return EIO; + } +#endif + return 0; +} + +#endif diff --git a/cpukit/include/rtems/rfs/rtems-rfs-trace.h b/cpukit/include/rtems/rfs/rtems-rfs-trace.h new file mode 100644 index 0000000000..4d6d0c9ddb --- /dev/null +++ b/cpukit/include/rtems/rfs/rtems-rfs-trace.h @@ -0,0 +1,135 @@ +/** + * @file + * + * @brief Manages the Trace and Debugging Features of the + * RTEMS RFS File System + * + * @ingroup rtems_rfs + * + * RTEMS File Systems Trace manages the trace and debugging features of the + * RTEMS RFS file system. The design allows all tracing code and strings to be + * removed from the target code for small footprint systems. + */ + +/* + * COPYRIGHT (c) 2010 Chris Johns <chrisj@rtems.org> + * + * 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_TRACE_H_) +#define _RTEMS_RFS_TRACE_H_ + +#include <stddef.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> + +/** + * Is tracing enabled ? + */ +#if !defined (RTEMS_RFS_TRACE) +#define RTEMS_RFS_TRACE 1 +#endif + +/** + * The type of the mask. + */ +typedef uint64_t rtems_rfs_trace_mask; + +/** + * List of tracing bits for the various parts of the file system. + */ +#define RTEMS_RFS_TRACE_ALL (0xffffffffffffffffULL) +#define RTEMS_RFS_TRACE_OPEN (1ULL << 0) +#define RTEMS_RFS_TRACE_CLOSE (1ULL << 1) +#define RTEMS_RFS_TRACE_MUTEX (1ULL << 2) +#define RTEMS_RFS_TRACE_BUFFER_OPEN (1ULL << 3) +#define RTEMS_RFS_TRACE_BUFFER_CLOSE (1ULL << 4) +#define RTEMS_RFS_TRACE_BUFFER_SYNC (1ULL << 5) +#define RTEMS_RFS_TRACE_BUFFER_RELEASE (1ULL << 6) +#define RTEMS_RFS_TRACE_BUFFER_CHAINS (1ULL << 7) +#define RTEMS_RFS_TRACE_BUFFER_HANDLE_REQUEST (1ULL << 8) +#define RTEMS_RFS_TRACE_BUFFER_HANDLE_RELEASE (1ULL << 9) +#define RTEMS_RFS_TRACE_BUFFER_SETBLKSIZE (1ULL << 10) +#define RTEMS_RFS_TRACE_BUFFERS_RELEASE (1ULL << 11) +#define RTEMS_RFS_TRACE_BLOCK_FIND (1ULL << 12) +#define RTEMS_RFS_TRACE_BLOCK_MAP_GROW (1ULL << 13) +#define RTEMS_RFS_TRACE_BLOCK_MAP_SHRINK (1ULL << 14) +#define RTEMS_RFS_TRACE_GROUP_OPEN (1ULL << 15) +#define RTEMS_RFS_TRACE_GROUP_CLOSE (1ULL << 16) +#define RTEMS_RFS_TRACE_GROUP_BITMAPS (1ULL << 17) +#define RTEMS_RFS_TRACE_INODE_OPEN (1ULL << 18) +#define RTEMS_RFS_TRACE_INODE_CLOSE (1ULL << 19) +#define RTEMS_RFS_TRACE_INODE_LOAD (1ULL << 20) +#define RTEMS_RFS_TRACE_INODE_UNLOAD (1ULL << 21) +#define RTEMS_RFS_TRACE_INODE_CREATE (1ULL << 22) +#define RTEMS_RFS_TRACE_INODE_DELETE (1ULL << 23) +#define RTEMS_RFS_TRACE_LINK (1ULL << 24) +#define RTEMS_RFS_TRACE_UNLINK (1ULL << 25) +#define RTEMS_RFS_TRACE_DIR_LOOKUP_INO (1ULL << 26) +#define RTEMS_RFS_TRACE_DIR_LOOKUP_INO_CHECK (1ULL << 27) +#define RTEMS_RFS_TRACE_DIR_LOOKUP_INO_FOUND (1ULL << 28) +#define RTEMS_RFS_TRACE_DIR_ADD_ENTRY (1ULL << 29) +#define RTEMS_RFS_TRACE_DIR_DEL_ENTRY (1ULL << 30) +#define RTEMS_RFS_TRACE_DIR_READ (1ULL << 31) +#define RTEMS_RFS_TRACE_DIR_EMPTY (1ULL << 32) +#define RTEMS_RFS_TRACE_SYMLINK (1ULL << 33) +#define RTEMS_RFS_TRACE_SYMLINK_READ (1ULL << 34) +#define RTEMS_RFS_TRACE_FILE_OPEN (1ULL << 35) +#define RTEMS_RFS_TRACE_FILE_CLOSE (1ULL << 36) +#define RTEMS_RFS_TRACE_FILE_IO (1ULL << 37) +#define RTEMS_RFS_TRACE_FILE_SET (1ULL << 38) + +/** + * Call to check if this part is bring traced. If RTEMS_RFS_TRACE is defined to + * 0 the code is dead code elminiated when built with -Os, -O2, or higher. + * + * @param[in] mask is the part of the API to trace. + * + * @retval true Tracing is active for the mask. + * @retval false Do not trace. + */ +#if RTEMS_RFS_TRACE +bool rtems_rfs_trace (rtems_rfs_trace_mask mask); +#else +#define rtems_rfs_trace(_m) (0) +#endif + +/** + * Set the mask. + * + * @param[in] mask are the mask bits to set. + * + * @retval mask The previous mask. + */ +#if RTEMS_RFS_TRACE +rtems_rfs_trace_mask rtems_rfs_trace_set_mask (rtems_rfs_trace_mask mask); +#else +#define rtems_rfs_trace_set_mask(_m) +#endif + +/** + * Clear the mask. + * + * @param[in] mask are the mask bits to clear. + * + * @retval mask The previous mask. + */ +#if RTEMS_RFS_TRACE +rtems_rfs_trace_mask rtems_rfs_trace_clear_mask (rtems_rfs_trace_mask mask); +#else +#define rtems_rfs_trace_clear_mask(_m) +#endif + +/** + * Add shell trace shell command. + */ +#if RTEMS_RFS_TRACE +int rtems_rfs_trace_shell_command (int argc, char *argv[]); +#endif + +#endif |