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

4.115
Last change on this file since 674f8b1b was 674f8b1b, checked in by Jamie Iles <jamie@…>, on 03/16/15 at 17:23:36

IMFS: don't strlen() an unterminated string in IMFS_dir_read().

a43a3466 (IMFS: Implement variable length node names) introduced a
changed to IMFS_jnode_t from being a null terminated string to a
separate unterminated string and length. IMFS_dir_read() was still
performing a strlen() on this unterminated string though and when doing
an 'ls' in the fileio example I saw that some filenames had garbage
suffixes.

  • Property mode set to 100644
File size: 4.2 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 <dirent.h>
23#include <string.h>
24
25static ssize_t IMFS_dir_read(
26  rtems_libio_t  *iop,
27  void           *buffer,
28  size_t          count
29)
30{
31  /*
32   *  Read up to element  iop->offset in the directory chain of the
33   *  imfs_jnode_t struct for this file descriptor.
34   */
35   const IMFS_directory_t    *dir;
36   const rtems_chain_node    *node;
37   const rtems_chain_control *entries;
38   struct dirent             *dir_ent;
39   ssize_t                    bytes_transferred;
40   off_t                      current_entry;
41   off_t                      first_entry;
42   off_t                      last_entry;
43
44   rtems_filesystem_instance_lock( &iop->pathinfo );
45
46   dir = IMFS_iop_to_directory( iop );
47   entries = &dir->Entries;
48
49   /* Move to the first of the desired directory entries */
50
51   bytes_transferred = 0;
52   first_entry = iop->offset;
53   /* protect against using sizes that are not exact multiples of the */
54   /* -dirent- size. These could result in unexpected results          */
55   last_entry = first_entry
56     + (count / sizeof( *dir_ent )) * sizeof( *dir_ent );
57
58   /* The directory was not empty so try to move to the desired entry in chain*/
59   for (
60      current_entry = 0,
61        node = rtems_chain_immutable_first( entries );
62      current_entry < last_entry
63        && !rtems_chain_is_tail( entries, node );
64      current_entry +=  sizeof( *dir_ent ),
65        node = rtems_chain_immutable_next( node )
66   ) {
67      if( current_entry >= first_entry ) {
68         const IMFS_jnode_t *imfs_node = (const IMFS_jnode_t *) node;
69
70         dir_ent = (struct dirent *) ((char *) buffer + bytes_transferred);
71
72         /* Move the entry to the return buffer */
73         dir_ent->d_off = current_entry;
74         dir_ent->d_reclen = sizeof( *dir_ent );
75         dir_ent->d_ino = IMFS_node_to_ino( imfs_node );
76         dir_ent->d_namlen = imfs_node->namelen;
77         memcpy( dir_ent->d_name, imfs_node->name, dir_ent->d_namlen + 1 );
78
79         iop->offset += sizeof( *dir_ent );
80         bytes_transferred += (ssize_t) sizeof( *dir_ent );
81      }
82   }
83
84   rtems_filesystem_instance_unlock( &iop->pathinfo );
85
86   return bytes_transferred;
87}
88
89static size_t IMFS_directory_size( const IMFS_jnode_t *node )
90{
91  size_t size = 0;
92  const IMFS_directory_t *dir = (const IMFS_directory_t *) node;
93  const rtems_chain_control *chain = &dir->Entries;
94  const rtems_chain_node *current = rtems_chain_immutable_first( chain );
95  const rtems_chain_node *tail = rtems_chain_immutable_tail( chain );
96
97  while ( current != tail ) {
98    size += sizeof( struct dirent );
99    current = rtems_chain_immutable_next( current );
100  }
101
102  return size;
103}
104
105static int IMFS_stat_directory(
106  const rtems_filesystem_location_info_t *loc,
107  struct stat *buf
108)
109{
110  const IMFS_jnode_t *node = loc->node_access;
111
112  buf->st_size = IMFS_directory_size( node );
113
114  return IMFS_stat( loc, buf );
115}
116
117static const rtems_filesystem_file_handlers_r IMFS_dir_default_handlers = {
118  .open_h = rtems_filesystem_default_open,
119  .close_h = rtems_filesystem_default_close,
120  .read_h = IMFS_dir_read,
121  .write_h = rtems_filesystem_default_write,
122  .ioctl_h = rtems_filesystem_default_ioctl,
123  .lseek_h = rtems_filesystem_default_lseek_directory,
124  .fstat_h = IMFS_stat_directory,
125  .ftruncate_h = rtems_filesystem_default_ftruncate_directory,
126  .fsync_h = rtems_filesystem_default_fsync_or_fdatasync_success,
127  .fdatasync_h = rtems_filesystem_default_fsync_or_fdatasync_success,
128  .fcntl_h = rtems_filesystem_default_fcntl,
129  .kqfilter_h = rtems_filesystem_default_kqfilter,
130  .poll_h = rtems_filesystem_default_poll,
131  .readv_h = rtems_filesystem_default_readv,
132  .writev_h = rtems_filesystem_default_writev
133};
134
135const IMFS_mknod_control IMFS_mknod_control_dir_default = {
136  {
137    .handlers = &IMFS_dir_default_handlers,
138    .node_initialize = IMFS_node_initialize_directory,
139    .node_remove = IMFS_node_remove_directory,
140    .node_destroy = IMFS_node_destroy_default
141  },
142  .node_size = sizeof( IMFS_directory_t )
143};
Note: See TracBrowser for help on using the repository browser.