source: rtems/cpukit/libfs/src/imfs/imfs_dir_default.c @ 03fcbb1

5
Last change on this file since 03fcbb1 was 03fcbb1, checked in by Sebastian Huber <sebastian.huber@…>, on 11/27/18 at 11:45:53

fs: Add struct dirent::d_type support

  • Property mode set to 100644
File size: 4.5 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup IMFS
5 */
6
7/*
8 *  COPYRIGHT (c) 1989-1999.
9 *  On-Line Applications Research Corporation (OAR).
10 *
11 *  The license and distribution terms for this file may be
12 *  found in the file LICENSE in this distribution or at
13 *  http://www.rtems.org/license/LICENSE.
14 */
15
16#if HAVE_CONFIG_H
17  #include "config.h"
18#endif
19
20#include <rtems/imfs.h>
21
22#include <sys/param.h>
23#include <dirent.h>
24#include <string.h>
25
26static ssize_t IMFS_dir_read(
27  rtems_libio_t  *iop,
28  void           *buffer,
29  size_t          count
30)
31{
32  /*
33   *  Read up to element  iop->offset in the directory chain of the
34   *  imfs_jnode_t struct for this file descriptor.
35   */
36   const IMFS_directory_t    *dir;
37   const rtems_chain_node    *node;
38   const rtems_chain_control *entries;
39   struct dirent             *dir_ent;
40   ssize_t                    bytes_transferred;
41   off_t                      current_entry;
42   off_t                      first_entry;
43   off_t                      last_entry;
44
45   rtems_filesystem_instance_lock( &iop->pathinfo );
46
47   dir = IMFS_iop_to_directory( iop );
48   entries = &dir->Entries;
49
50   /* Move to the first of the desired directory entries */
51
52   bytes_transferred = 0;
53   first_entry = iop->offset;
54   /* protect against using sizes that are not exact multiples of the */
55   /* -dirent- size. These could result in unexpected results          */
56   last_entry = first_entry
57     + (count / sizeof( *dir_ent )) * sizeof( *dir_ent );
58
59   /* The directory was not empty so try to move to the desired entry in chain*/
60   for (
61      current_entry = 0,
62        node = rtems_chain_immutable_first( entries );
63      current_entry < last_entry
64        && !rtems_chain_is_tail( entries, node );
65      current_entry +=  sizeof( *dir_ent ),
66        node = rtems_chain_immutable_next( node )
67   ) {
68      if( current_entry >= first_entry ) {
69         const IMFS_jnode_t *imfs_node = (const IMFS_jnode_t *) node;
70
71         dir_ent = (struct dirent *) ((char *) buffer + bytes_transferred);
72
73         /* Move the entry to the return buffer */
74         dir_ent->d_off = current_entry;
75         dir_ent->d_reclen = sizeof( *dir_ent );
76         dir_ent->d_ino = IMFS_node_to_ino( imfs_node );
77#ifdef DT_DIR
78         dir_ent->d_type = IFTODT( imfs_node->st_mode );
79#endif
80         dir_ent->d_namlen =
81           MIN( imfs_node->namelen, sizeof( dir_ent->d_name ) - 1 );
82         dir_ent->d_name[ dir_ent->d_namlen ] = '\0';
83         memcpy( dir_ent->d_name, imfs_node->name, dir_ent->d_namlen );
84
85         iop->offset += sizeof( *dir_ent );
86         bytes_transferred += (ssize_t) sizeof( *dir_ent );
87      }
88   }
89
90   rtems_filesystem_instance_unlock( &iop->pathinfo );
91
92   return bytes_transferred;
93}
94
95static size_t IMFS_directory_size( const IMFS_jnode_t *node )
96{
97  size_t size = 0;
98  const IMFS_directory_t *dir = (const IMFS_directory_t *) node;
99  const rtems_chain_control *chain = &dir->Entries;
100  const rtems_chain_node *current = rtems_chain_immutable_first( chain );
101  const rtems_chain_node *tail = rtems_chain_immutable_tail( chain );
102
103  while ( current != tail ) {
104    size += sizeof( struct dirent );
105    current = rtems_chain_immutable_next( current );
106  }
107
108  return size;
109}
110
111static int IMFS_stat_directory(
112  const rtems_filesystem_location_info_t *loc,
113  struct stat *buf
114)
115{
116  const IMFS_jnode_t *node = loc->node_access;
117
118  buf->st_size = IMFS_directory_size( node );
119
120  return IMFS_stat( loc, buf );
121}
122
123static const rtems_filesystem_file_handlers_r IMFS_dir_default_handlers = {
124  .open_h = rtems_filesystem_default_open,
125  .close_h = rtems_filesystem_default_close,
126  .read_h = IMFS_dir_read,
127  .write_h = rtems_filesystem_default_write,
128  .ioctl_h = rtems_filesystem_default_ioctl,
129  .lseek_h = rtems_filesystem_default_lseek_directory,
130  .fstat_h = IMFS_stat_directory,
131  .ftruncate_h = rtems_filesystem_default_ftruncate_directory,
132  .fsync_h = rtems_filesystem_default_fsync_or_fdatasync_success,
133  .fdatasync_h = rtems_filesystem_default_fsync_or_fdatasync_success,
134  .fcntl_h = rtems_filesystem_default_fcntl,
135  .kqfilter_h = rtems_filesystem_default_kqfilter,
136  .mmap_h = rtems_filesystem_default_mmap,
137  .poll_h = rtems_filesystem_default_poll,
138  .readv_h = rtems_filesystem_default_readv,
139  .writev_h = rtems_filesystem_default_writev
140};
141
142const IMFS_mknod_control IMFS_mknod_control_dir_default = {
143  {
144    .handlers = &IMFS_dir_default_handlers,
145    .node_initialize = IMFS_node_initialize_directory,
146    .node_remove = IMFS_node_remove_directory,
147    .node_destroy = IMFS_node_destroy_default
148  },
149  .node_size = sizeof( IMFS_directory_t )
150};
Note: See TracBrowser for help on using the repository browser.