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

4.115
Last change on this file since e6f4a612 was e6f4a612, checked in by Sebastian Huber <sebastian.huber@…>, on 03/16/15 at 19:28:20

IMFS: NUL-terminate name returned by readdir()

  • Property mode set to 100644
File size: 4.4 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 "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         dir_ent->d_namlen =
78           MIN( imfs_node->namelen, sizeof( dir_ent->d_name ) - 1 );
79         dir_ent->d_name[ dir_ent->d_namlen ] = '\0';
80         memcpy( dir_ent->d_name, imfs_node->name, dir_ent->d_namlen );
81
82         iop->offset += sizeof( *dir_ent );
83         bytes_transferred += (ssize_t) sizeof( *dir_ent );
84      }
85   }
86
87   rtems_filesystem_instance_unlock( &iop->pathinfo );
88
89   return bytes_transferred;
90}
91
92static size_t IMFS_directory_size( const IMFS_jnode_t *node )
93{
94  size_t size = 0;
95  const IMFS_directory_t *dir = (const IMFS_directory_t *) node;
96  const rtems_chain_control *chain = &dir->Entries;
97  const rtems_chain_node *current = rtems_chain_immutable_first( chain );
98  const rtems_chain_node *tail = rtems_chain_immutable_tail( chain );
99
100  while ( current != tail ) {
101    size += sizeof( struct dirent );
102    current = rtems_chain_immutable_next( current );
103  }
104
105  return size;
106}
107
108static int IMFS_stat_directory(
109  const rtems_filesystem_location_info_t *loc,
110  struct stat *buf
111)
112{
113  const IMFS_jnode_t *node = loc->node_access;
114
115  buf->st_size = IMFS_directory_size( node );
116
117  return IMFS_stat( loc, buf );
118}
119
120static const rtems_filesystem_file_handlers_r IMFS_dir_default_handlers = {
121  .open_h = rtems_filesystem_default_open,
122  .close_h = rtems_filesystem_default_close,
123  .read_h = IMFS_dir_read,
124  .write_h = rtems_filesystem_default_write,
125  .ioctl_h = rtems_filesystem_default_ioctl,
126  .lseek_h = rtems_filesystem_default_lseek_directory,
127  .fstat_h = IMFS_stat_directory,
128  .ftruncate_h = rtems_filesystem_default_ftruncate_directory,
129  .fsync_h = rtems_filesystem_default_fsync_or_fdatasync_success,
130  .fdatasync_h = rtems_filesystem_default_fsync_or_fdatasync_success,
131  .fcntl_h = rtems_filesystem_default_fcntl,
132  .kqfilter_h = rtems_filesystem_default_kqfilter,
133  .poll_h = rtems_filesystem_default_poll,
134  .readv_h = rtems_filesystem_default_readv,
135  .writev_h = rtems_filesystem_default_writev
136};
137
138const IMFS_mknod_control IMFS_mknod_control_dir_default = {
139  {
140    .handlers = &IMFS_dir_default_handlers,
141    .node_initialize = IMFS_node_initialize_directory,
142    .node_remove = IMFS_node_remove_directory,
143    .node_destroy = IMFS_node_destroy_default
144  },
145  .node_size = sizeof( IMFS_directory_t )
146};
Note: See TracBrowser for help on using the repository browser.