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

4.10
Last change on this file since b439daa was b439daa, checked in by Ralf Corsepius <ralf.corsepius@…>, on Jun 17, 2010 at 3:48:39 AM

2010-06-17 Ralf Corsépius <ralf.corsepius@…>

  • libfs/src/rfs/rtems-rfs-format.c: Various 64bit fixes.
  • Property mode set to 100644
File size: 6.9 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
30#include <rtems/rfs/rtems-rfs-dir.h>
31#include <rtems/rfs/rtems-rfs-link.h>
32#include "rtems-rfs-rtems.h"
33
34/**
35 * This rountine will verify that the node being opened as a directory is in
36 * fact a directory node. If it is then the offset into the directory will be
37 * set to 0 to position to the first directory entry.
38 *
39 * @param iop
40 * @param pathname
41 * @param flag
42 * @param mode
43 * @@return int
44 */
45static int
46rtems_rfs_rtems_dir_open (rtems_libio_t* iop,
47                          const char*    pathname,
48                          uint32_t       flag,
49                          uint32_t       mode)
50{
51  rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (&iop->pathinfo);
52  rtems_rfs_ino          ino = rtems_rfs_rtems_get_iop_ino (iop);
53  rtems_rfs_inode_handle inode;
54  int                    rc;
55
56  rtems_rfs_rtems_lock (fs);
57 
58  rc = rtems_rfs_inode_open (fs, ino, &inode, true);
59  if (rc)
60  {
61    rtems_rfs_rtems_unlock (fs);
62    return rtems_rfs_rtems_error ("dir_open: opening inode", rc);
63  }
64 
65  if (!RTEMS_RFS_S_ISDIR (rtems_rfs_inode_get_mode (&inode)))
66  {
67    rtems_rfs_inode_close (fs, &inode);
68    rtems_rfs_rtems_unlock (fs);
69    return rtems_rfs_rtems_error ("dir_open: not dir", ENOTDIR);
70  }
71   
72  iop->offset = 0;
73
74  rtems_rfs_inode_close (fs, &inode);
75  rtems_rfs_rtems_unlock (fs);
76  return 0;
77}
78
79/**
80 * This routine will be called by the generic close routine to cleanup any
81 * resources that have been allocated for the management of the file
82 *
83 * @param iop
84 * @retval 0 Always no error.
85 */
86static int
87rtems_rfs_rtems_dir_close (rtems_libio_t* iop)
88{
89  /*
90   * The RFS does not hold any resources. Nothing to do.
91   */
92  return 0;
93}
94
95/**
96 * This routine will read the next directory entry based on the directory
97 * offset. The offset should be equal to -n- time the size of an individual
98 * dirent structure. If n is not an integer multiple of the sizeof a dirent
99 * structure, an integer division will be performed to determine directory
100 * entry that will be returned in the buffer. Count should reflect -m- times
101 * the sizeof dirent bytes to be placed in the buffer.  If there are not -m-
102 * dirent elements from the current directory position to the end of the
103 * exisiting file, the remaining entries will be placed in the buffer and the
104 * returned value will be equal to -m actual- times the size of a directory
105 * entry.
106 */
107static ssize_t
108rtems_rfs_rtems_dir_read (rtems_libio_t* iop,
109                          void*          buffer,
110                          size_t         count)
111{
112  rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (&iop->pathinfo);
113  rtems_rfs_ino          ino = rtems_rfs_rtems_get_iop_ino (iop);
114  rtems_rfs_inode_handle inode;
115  struct dirent*         dirent;
116  size_t                 bytes_transfered;
117  int                    d;
118  int                    rc;
119
120  count  = count / sizeof (struct dirent);
121  dirent = buffer;
122 
123  rtems_rfs_rtems_lock (fs);
124 
125  rc = rtems_rfs_inode_open (fs, ino, &inode, true);
126  if (rc)
127  {
128    rtems_rfs_rtems_unlock (fs);
129    return rtems_rfs_rtems_error ("dir_read: read inode", rc);
130  }
131
132  bytes_transfered = 0;
133 
134  for (d = 0; d < count; d++, dirent++)
135  {
136    size_t size;
137    rc = rtems_rfs_dir_read (fs, &inode, iop->offset, dirent, &size);
138    if (rc == ENOENT)
139    {
140      rc = 0;
141      break;
142    }
143    if (rc > 0)
144    {
145      bytes_transfered = rtems_rfs_rtems_error ("dir_read: dir read", rc);
146      break;
147    }
148    iop->offset += size;
149    bytes_transfered += sizeof (struct dirent);
150  }
151
152  rtems_rfs_inode_close (fs, &inode);
153  rtems_rfs_rtems_unlock (fs);
154 
155  return (ssize_t) bytes_transfered;
156}
157
158/**
159 * This routine will behave in one of three ways based on the state of argument
160 * whence. Based on the state of its value the offset argument will be
161 * interpreted using one of the following methods:
162 *
163 *   SEEK_SET - offset is the absolute byte offset from the start of the
164 *              logical start of the dirent sequence that represents the
165 *              directory
166 *   SEEK_CUR - offset is used as the relative byte offset from the current
167 *              directory position index held in the iop structure
168 *   SEEK_END - N/A --> This will cause an assert.
169 *
170 * @param iop
171 * @param offset
172 * @param whence
173 * return rtems_off64_t
174 */
175static rtems_off64_t
176rtems_rfs_rtems_dir_lseek (rtems_libio_t* iop,
177                           rtems_off64_t  offset,
178                           int            whence)
179{
180  switch (whence)
181  {
182    case SEEK_SET:   /* absolute move from the start of the file */
183    case SEEK_CUR:   /* relative move */
184      break;
185
186     case SEEK_END:   /* Movement past the end of the directory via lseek */
187                      /* is not a permitted operation                     */
188    default:
189      return rtems_rfs_rtems_error ("dir_lseek: bad whence", EINVAL);
190      break;
191  }
192  return 0;
193}
194
195static int
196rtems_rfs_rtems_dir_rmnod (rtems_filesystem_location_info_t* parent_pathloc,
197                           rtems_filesystem_location_info_t* pathloc)
198{
199  rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc);
200  rtems_rfs_ino          parent = rtems_rfs_rtems_get_pathloc_ino (parent_pathloc);
201  rtems_rfs_ino          ino = rtems_rfs_rtems_get_pathloc_ino (pathloc);
202  uint32_t               doff = rtems_rfs_rtems_get_pathloc_doff (pathloc);
203  int                    rc;
204
205  if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_DIR_RMNOD))
206    printf ("rtems-rfs: dir-rmnod: parent:%" PRId32 " doff:%" PRIu32 ", ino:%" PRId32 "\n",
207            parent, doff, ino);
208
209  if (ino == RTEMS_RFS_ROOT_INO)
210    return rtems_rfs_rtems_error ("dir_rmnod: root inode", EBUSY);
211
212  rtems_rfs_rtems_lock (fs);
213 
214  rc = rtems_rfs_unlink (fs, parent, ino, doff, rtems_rfs_unlink_dir_if_empty);
215  if (rc)
216  {
217    rtems_rfs_rtems_unlock (fs);
218    return rtems_rfs_rtems_error ("dir_rmnod: unlinking", rc);
219  }
220
221  rtems_rfs_rtems_unlock (fs);
222  return 0;
223}
224
225/*
226 *  Set of operations handlers for operations on directories.
227 */
228
229const rtems_filesystem_file_handlers_r rtems_rfs_rtems_dir_handlers = {
230  .open_h      = rtems_rfs_rtems_dir_open,
231  .close_h     = rtems_rfs_rtems_dir_close,
232  .read_h      = rtems_rfs_rtems_dir_read,
233  .write_h     = NULL,
234  .ioctl_h     = NULL,
235  .lseek_h     = rtems_rfs_rtems_dir_lseek,
236  .fstat_h     = rtems_rfs_rtems_stat,
237  .fchmod_h    = rtems_rfs_rtems_fchmod,
238  .ftruncate_h = NULL,
239  .fpathconf_h = NULL,
240  .fsync_h     = NULL,
241  .fdatasync_h = rtems_rfs_rtems_fdatasync,
242  .fcntl_h     = rtems_rfs_rtems_fcntl,
243  .rmnod_h     = rtems_rfs_rtems_dir_rmnod
244};
Note: See TracBrowser for help on using the repository browser.