diff options
Diffstat (limited to 'cpukit/libfs/src/imfs/imfs_dir_default.c')
-rw-r--r-- | cpukit/libfs/src/imfs/imfs_dir_default.c | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/cpukit/libfs/src/imfs/imfs_dir_default.c b/cpukit/libfs/src/imfs/imfs_dir_default.c new file mode 100644 index 0000000000..98f06dfce4 --- /dev/null +++ b/cpukit/libfs/src/imfs/imfs_dir_default.c @@ -0,0 +1,143 @@ +/** + * @file + * + * @ingroup IMFS + */ + +/* + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * 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 HAVE_CONFIG_H + #include "config.h" +#endif + +#include "imfs.h" + +#include <dirent.h> +#include <string.h> + +static ssize_t IMFS_dir_read( + rtems_libio_t *iop, + void *buffer, + size_t count +) +{ + /* + * Read up to element iop->offset in the directory chain of the + * imfs_jnode_t struct for this file descriptor. + */ + const IMFS_directory_t *dir; + const rtems_chain_node *node; + const rtems_chain_control *entries; + struct dirent *dir_ent; + ssize_t bytes_transferred; + off_t current_entry; + off_t first_entry; + off_t last_entry; + + rtems_filesystem_instance_lock( &iop->pathinfo ); + + dir = IMFS_iop_to_directory( iop ); + entries = &dir->Entries; + + /* Move to the first of the desired directory entries */ + + bytes_transferred = 0; + first_entry = iop->offset; + /* protect against using sizes that are not exact multiples of the */ + /* -dirent- size. These could result in unexpected results */ + last_entry = first_entry + + (count / sizeof( *dir_ent )) * sizeof( *dir_ent ); + + /* The directory was not empty so try to move to the desired entry in chain*/ + for ( + current_entry = 0, + node = rtems_chain_immutable_first( entries ); + current_entry < last_entry + && !rtems_chain_is_tail( entries, node ); + current_entry += sizeof( *dir_ent ), + node = rtems_chain_immutable_next( node ) + ) { + if( current_entry >= first_entry ) { + const IMFS_jnode_t *imfs_node = (const IMFS_jnode_t *) node; + + dir_ent = (struct dirent *) ((char *) buffer + bytes_transferred); + + /* Move the entry to the return buffer */ + dir_ent->d_off = current_entry; + dir_ent->d_reclen = sizeof( *dir_ent ); + dir_ent->d_ino = IMFS_node_to_ino( imfs_node ); + dir_ent->d_namlen = strlen( imfs_node->name ); + memcpy( dir_ent->d_name, imfs_node->name, dir_ent->d_namlen + 1 ); + + iop->offset += sizeof( *dir_ent ); + bytes_transferred += (ssize_t) sizeof( *dir_ent ); + } + } + + rtems_filesystem_instance_unlock( &iop->pathinfo ); + + return bytes_transferred; +} + +static size_t IMFS_directory_size( const IMFS_jnode_t *node ) +{ + size_t size = 0; + const IMFS_directory_t *dir = (const IMFS_directory_t *) node; + const rtems_chain_control *chain = &dir->Entries; + const rtems_chain_node *current = rtems_chain_immutable_first( chain ); + const rtems_chain_node *tail = rtems_chain_immutable_tail( chain ); + + while ( current != tail ) { + size += sizeof( struct dirent ); + current = rtems_chain_immutable_next( current ); + } + + return size; +} + +static int IMFS_stat_directory( + const rtems_filesystem_location_info_t *loc, + struct stat *buf +) +{ + const IMFS_jnode_t *node = loc->node_access; + + buf->st_size = IMFS_directory_size( node ); + + return IMFS_stat( loc, buf ); +} + +static const rtems_filesystem_file_handlers_r IMFS_dir_default_handlers = { + .open_h = rtems_filesystem_default_open, + .close_h = rtems_filesystem_default_close, + .read_h = IMFS_dir_read, + .write_h = rtems_filesystem_default_write, + .ioctl_h = rtems_filesystem_default_ioctl, + .lseek_h = rtems_filesystem_default_lseek_directory, + .fstat_h = IMFS_stat_directory, + .ftruncate_h = rtems_filesystem_default_ftruncate_directory, + .fsync_h = rtems_filesystem_default_fsync_or_fdatasync_success, + .fdatasync_h = rtems_filesystem_default_fsync_or_fdatasync_success, + .fcntl_h = rtems_filesystem_default_fcntl, + .kqfilter_h = rtems_filesystem_default_kqfilter, + .poll_h = rtems_filesystem_default_poll, + .readv_h = rtems_filesystem_default_readv, + .writev_h = rtems_filesystem_default_writev +}; + +const IMFS_mknod_control IMFS_mknod_control_dir_default = { + { + .handlers = &IMFS_dir_default_handlers, + .node_initialize = IMFS_node_initialize_directory, + .node_remove = IMFS_node_remove_directory, + .node_destroy = IMFS_node_destroy_default + }, + .node_size = sizeof( IMFS_directory_t ) +}; |