source: rtems/cpukit/libfs/src/rfs/rtems-rfs-rtems-dir.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.8 KB
Line 
1/*
2 *  COPYRIGHT (c) 2010 Chris Johns <chrisj@rtems.org>
3 *
4 *  The license and distribution terms for this file may be
5 *  found in the file LICENSE in this distribution or at
6 *  http://www.rtems.com/license/LICENSE.
7 *
8 *  $Id$
9 */
10/**
11 * @file
12 *
13 * @ingroup rtems-rfs
14 *
15 * RTEMS RFS Directory Access Routines
16 */
17
18#if HAVE_CONFIG_H
19#include "config.h"
20#endif
21
22#include <inttypes.h>
23
24#include <sys/types.h>
25#include <sys/stat.h>
26#include <fcntl.h>
27#include <stdlib.h>
28#include <stdio.h>
29#include <unistd.h>
30
31#include <rtems/rfs/rtems-rfs-dir.h>
32#include <rtems/rfs/rtems-rfs-link.h>
33#include "rtems-rfs-rtems.h"
34
35/**
36 * This rountine will verify that the node being opened as a directory is in
37 * fact a directory node. If it is then the offset into the directory will be
38 * set to 0 to position to the first directory entry.
39 */
40static int
41rtems_rfs_rtems_dir_open (rtems_libio_t* iop,
42                          const char*    pathname,
43                          int            oflag,
44                          mode_t         mode)
45{
46  rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (&iop->pathinfo);
47  rtems_rfs_ino          ino = rtems_rfs_rtems_get_iop_ino (iop);
48  rtems_rfs_inode_handle inode;
49  int                    rc;
50
51  rtems_rfs_rtems_lock (fs);
52
53  rc = rtems_rfs_inode_open (fs, ino, &inode, true);
54  if (rc)
55  {
56    rtems_rfs_rtems_unlock (fs);
57    return rtems_rfs_rtems_error ("dir_open: opening inode", rc);
58  }
59
60  if (!RTEMS_RFS_S_ISDIR (rtems_rfs_inode_get_mode (&inode)))
61  {
62    rtems_rfs_inode_close (fs, &inode);
63    rtems_rfs_rtems_unlock (fs);
64    return rtems_rfs_rtems_error ("dir_open: not dir", ENOTDIR);
65  }
66
67  iop->offset = 0;
68
69  rtems_rfs_inode_close (fs, &inode);
70  rtems_rfs_rtems_unlock (fs);
71  return 0;
72}
73
74/**
75 * This routine will be called by the generic close routine to cleanup any
76 * resources that have been allocated for the management of the file
77 *
78 * @param iop
79 * @retval 0 Always no error.
80 */
81static int
82rtems_rfs_rtems_dir_close (rtems_libio_t* iop)
83{
84  /*
85   * The RFS does not hold any resources. Nothing to do.
86   */
87  return 0;
88}
89
90/**
91 * This routine will read the next directory entry based on the directory
92 * offset. The offset should be equal to -n- time the size of an individual
93 * dirent structure. If n is not an integer multiple of the sizeof a dirent
94 * structure, an integer division will be performed to determine directory
95 * entry that will be returned in the buffer. Count should reflect -m- times
96 * the sizeof dirent bytes to be placed in the buffer.  If there are not -m-
97 * dirent elements from the current directory position to the end of the
98 * exisiting file, the remaining entries will be placed in the buffer and the
99 * returned value will be equal to -m actual- times the size of a directory
100 * entry.
101 */
102static ssize_t
103rtems_rfs_rtems_dir_read (rtems_libio_t* iop,
104                          void*          buffer,
105                          size_t         count)
106{
107  rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (&iop->pathinfo);
108  rtems_rfs_ino          ino = rtems_rfs_rtems_get_iop_ino (iop);
109  rtems_rfs_inode_handle inode;
110  struct dirent*         dirent;
111  ssize_t                bytes_transferred;
112  int                    d;
113  int                    rc;
114
115  count  = count / sizeof (struct dirent);
116  dirent = buffer;
117
118  rtems_rfs_rtems_lock (fs);
119
120  rc = rtems_rfs_inode_open (fs, ino, &inode, true);
121  if (rc)
122  {
123    rtems_rfs_rtems_unlock (fs);
124    return rtems_rfs_rtems_error ("dir_read: read inode", rc);
125  }
126
127  bytes_transferred = 0;
128
129  for (d = 0; d < count; d++, dirent++)
130  {
131    size_t size;
132    rc = rtems_rfs_dir_read (fs, &inode, iop->offset, dirent, &size);
133    if (rc == ENOENT)
134    {
135      rc = 0;
136      break;
137    }
138    if (rc > 0)
139    {
140      bytes_transferred = rtems_rfs_rtems_error ("dir_read: dir read", rc);
141      break;
142    }
143    iop->offset += size;
144    bytes_transferred += sizeof (struct dirent);
145  }
146
147  rtems_rfs_inode_close (fs, &inode);
148  rtems_rfs_rtems_unlock (fs);
149
150  return bytes_transferred;
151}
152
153/**
154 * This routine will behave in one of three ways based on the state of argument
155 * whence. Based on the state of its value the offset argument will be
156 * interpreted using one of the following methods:
157 *
158 *   SEEK_SET - offset is the absolute byte offset from the start of the
159 *              logical start of the dirent sequence that represents the
160 *              directory
161 *   SEEK_CUR - offset is used as the relative byte offset from the current
162 *              directory position index held in the iop structure
163 *   SEEK_END - N/A --> This will cause an assert.
164 *
165 * @param iop
166 * @param offset
167 * @param whence
168 * return off_t
169 */
170static off_t
171rtems_rfs_rtems_dir_lseek (rtems_libio_t* iop,
172                           off_t          offset,
173                           int            whence)
174{
175  switch (whence)
176  {
177    case SEEK_SET:   /* absolute move from the start of the file */
178    case SEEK_CUR:   /* relative move */
179      break;
180
181     case SEEK_END:   /* Movement past the end of the directory via lseek */
182                      /* is not a permitted operation                     */
183    default:
184      return rtems_rfs_rtems_error ("dir_lseek: bad whence", EINVAL);
185      break;
186  }
187  return 0;
188}
189
190/*
191 *  Set of operations handlers for operations on directories.
192 */
193
194const rtems_filesystem_file_handlers_r rtems_rfs_rtems_dir_handlers = {
195  .open_h      = rtems_rfs_rtems_dir_open,
196  .close_h     = rtems_rfs_rtems_dir_close,
197  .read_h      = rtems_rfs_rtems_dir_read,
198  .write_h     = rtems_filesystem_default_write,
199  .ioctl_h     = rtems_filesystem_default_ioctl,
200  .lseek_h     = rtems_rfs_rtems_dir_lseek,
201  .fstat_h     = rtems_rfs_rtems_fstat,
202  .ftruncate_h = rtems_filesystem_default_ftruncate_directory,
203  .fsync_h     = rtems_filesystem_default_fsync,
204  .fdatasync_h = rtems_rfs_rtems_fdatasync,
205  .fcntl_h     = rtems_filesystem_default_fcntl
206};
Note: See TracBrowser for help on using the repository browser.