source: rtems/cpukit/libfs/src/rfs/rtems-rfs-rtems-dir.c @ 4116fce6

4.115
Last change on this file since 4116fce6 was 4116fce6, checked in by Sebastian Huber <sebastian.huber@…>, on 02/24/12 at 16:39:27

Filesystem: New defaults fsync_h and fdatasync_h

New defaults rtems_filesystem_default_fsync_or_fdatasync() and
rtems_filesystem_default_fsync_or_fdatasync_success() for fsync_h and
fdatasync_h. The rtems_filesystem_default_fsync_or_fdatasync() sets now
errno to EINVAL according to POSIX.

  • 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_or_fdatasync,
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.