source: rtems/cpukit/libfs/src/imfs/imfs_directory.c @ 3b7c123

4.115
Last change on this file since 3b7c123 was 3b7c123, checked in by Sebastian Huber <sebastian.huber@…>, on 03/13/12 at 10:33:51

Filesystem: Reference counting for locations

o A new data structure rtems_filesystem_global_location_t was

introduced to be used for

o the mount point location in the mount table entry,
o the file system root location in the mount table entry,
o the root directory location in the user environment, and
o the current directory location in the user environment.

During the path evaluation global start locations are obtained to
ensure that the current file system instance will be not unmounted in
the meantime.

o The user environment uses now reference counting and is protected

from concurrent access.

o The path evaluation process was completely rewritten and simplified.

The IMFS, RFS, NFS, and DOSFS use now a generic path evaluation
method. Recursive calls in the path evaluation have been replaced
with iteration to avoid stack overflows. Only the evaluation of
symbolic links is recursive. No dynamic memory allocations and
intermediate buffers are used in the high level path evaluation. No
global locks are held during the file system instance specific path
evaluation process.

o Recursive symbolic link evaluation is now limited by

RTEMS_FILESYSTEM_SYMLOOP_MAX. Applications can retrieve this value
via sysconf().

o The device file system (devFS) uses now no global variables and

allocation from the workspace. Node names are allocated from the
heap.

o The upper layer lseek() performs now some parameter checks.
o The upper layer ftruncate() performs now some parameter checks.
o unmask() is now restricted to the RWX flags and protected from

concurrent access.

o The fchmod_h and rmnod_h file system node handlers are now a file

system operation.

o The unlink_h operation has been removed. All nodes are now destroyed

with the rmnod_h operation.

o New lock_h, unlock_h, clonenod_h, and are_nodes_equal_h file system

operations.

o The path evaluation and file system operations are now protected by

per file system instance lock and unlock operations.

o Fix and test file descriptor duplicate in fcntl().
o New test fstests/fsnofs01.

  • Property mode set to 100644
File size: 5.7 KB
Line 
1/*
2 *  IMFS Directory Access Routines
3 *
4 *  COPYRIGHT (c) 1989-1999.
5 *  On-Line Applications Research Corporation (OAR).
6 *
7 *  The license and distribution terms for this file may be
8 *  found in the file LICENSE in this distribution or at
9 *  http://www.rtems.com/license/LICENSE.
10 *
11 *  $Id$
12 */
13
14#if HAVE_CONFIG_H
15  #include "config.h"
16#endif
17
18#include "imfs.h"
19
20#include <string.h>
21#include <dirent.h>
22
23/*
24 *  imfs_dir_open
25 *
26 *  This rountine will verify that the node being opened as a directory is
27 *  in fact a directory node. If it is then the offset into the directory
28 *  will be set to 0 to position to the first directory entry.
29 */
30
31int imfs_dir_open(
32  rtems_libio_t  *iop,
33  const char *pathname,
34  int oflag,
35  mode_t mode
36)
37{
38  IMFS_jnode_t      *the_jnode;
39
40  /* Is the node a directory ? */
41  the_jnode = (IMFS_jnode_t *) iop->pathinfo.node_access;
42
43  if ( the_jnode->type != IMFS_DIRECTORY )
44     return -1;      /* It wasn't a directory --> return error */
45
46  iop->offset = 0;
47  return 0;
48}
49
50/*
51 *  imfs_dir_read
52 *
53 *  This routine will read the next directory entry based on the directory
54 *  offset. The offset should be equal to -n- time the size of an individual
55 *  dirent structure. If n is not an integer multiple of the sizeof a
56 *  dirent structure, an integer division will be performed to determine
57 *  directory entry that will be returned in the buffer. Count should reflect
58 *  -m- times the sizeof dirent bytes to be placed in the buffer.
59 *  If there are not -m- dirent elements from the current directory position
60 *  to the end of the exisiting file, the remaining entries will be placed in
61 *  the buffer and the returned value will be equal to -m actual- times the
62 *  size of a directory entry.
63 */
64
65ssize_t imfs_dir_read(
66  rtems_libio_t  *iop,
67  void           *buffer,
68  size_t          count
69)
70{
71  /*
72   *  Read up to element  iop->offset in the directory chain of the
73   *  imfs_jnode_t struct for this file descriptor.
74   */
75   rtems_chain_node    *the_node;
76   rtems_chain_control *the_chain;
77   IMFS_jnode_t        *the_jnode;
78   int                  bytes_transferred;
79   int                  current_entry;
80   int                  first_entry;
81   int                  last_entry;
82   struct dirent        tmp_dirent;
83
84   the_jnode = (IMFS_jnode_t *)iop->pathinfo.node_access;
85   the_chain = &the_jnode->info.directory.Entries;
86
87   if ( rtems_chain_is_empty( the_chain ) )
88      return 0;
89
90   /* Move to the first of the desired directory entries */
91   the_node = rtems_chain_first( the_chain );
92
93   bytes_transferred = 0;
94   first_entry = iop->offset;
95   /* protect against using sizes that are not exact multiples of the */
96   /* -dirent- size. These could result in unexpected results          */
97   last_entry = first_entry + (count/sizeof(struct dirent)) * sizeof(struct dirent);
98
99   /* The directory was not empty so try to move to the desired entry in chain*/
100   for (
101      current_entry = 0;
102      current_entry < last_entry;
103      current_entry = current_entry + sizeof(struct dirent) ){
104
105      if ( rtems_chain_is_tail( the_chain, the_node ) ){
106         /* We hit the tail of the chain while trying to move to the first */
107         /* entry in the read */
108         return bytes_transferred;  /* Indicate that there are no more */
109                                    /* entries to return */
110      }
111
112      if( current_entry >= first_entry ) {
113         /* Move the entry to the return buffer */
114         tmp_dirent.d_off = current_entry;
115         tmp_dirent.d_reclen = sizeof( struct dirent );
116         the_jnode = (IMFS_jnode_t *) the_node;
117         tmp_dirent.d_ino = the_jnode->st_ino;
118         tmp_dirent.d_namlen = strlen( the_jnode->name );
119         strcpy( tmp_dirent.d_name, the_jnode->name );
120         memcpy(
121            buffer + bytes_transferred,
122            (void *)&tmp_dirent,
123            sizeof( struct dirent )
124         );
125         iop->offset = iop->offset + sizeof(struct dirent);
126         bytes_transferred = bytes_transferred + sizeof( struct dirent );
127      }
128
129      the_node = the_node->next;
130   }
131
132   /* Success */
133   return bytes_transferred;
134}
135
136
137
138/*
139 *  imfs_dir_close
140 *
141 *  This routine will be called by the generic close routine to cleanup any
142 *  resources that have been allocated for the management of the file
143 */
144
145int imfs_dir_close(
146  rtems_libio_t  *iop
147)
148{
149  /*
150   *  The generic close routine handles the deallocation of the file control
151   *  and associated memory. At present the imfs_dir_close simply
152   *  returns a successful completion status.
153   */
154
155  return 0;
156}
157
158
159
160/*
161 *  imfs_dir_lseek
162 *
163 *  This routine will behave in one of three ways based on the state of
164 *  argument whence. Based on the state of its value the offset argument will
165 *  be interpreted using one of the following methods:
166 *
167 *     SEEK_SET - offset is the absolute byte offset from the start of the
168 *                logical start of the dirent sequence that represents the
169 *                directory
170 *     SEEK_CUR - offset is used as the relative byte offset from the current
171 *                directory position index held in the iop structure
172 *     SEEK_END - N/A --> This will cause an EINVAL to be returned.
173 */
174
175off_t imfs_dir_lseek(
176  rtems_libio_t  *iop,
177  off_t           offset,
178  int             whence
179)
180{
181  switch( whence ) {
182     case SEEK_SET:   /* absolute move from the start of the file */
183     case SEEK_CUR:   /* relative move */
184        iop->offset = (iop->offset/sizeof(struct dirent)) *
185              sizeof(struct dirent);
186        break;
187
188     case SEEK_END:   /* Movement past the end of the directory via lseek */
189                      /* is not a permitted operation                     */
190      default:
191        rtems_set_errno_and_return_minus_one( EINVAL );
192        break;
193  }
194
195  return 0;
196}
Note: See TracBrowser for help on using the repository browser.