source: rtems/cpukit/libfs/src/rfs/rtems-rfs-rtems-file.c @ c499856

4.115
Last change on this file since c499856 was c499856, checked in by Chris Johns <chrisj@…>, on 03/20/14 at 21:10:47

Change all references of rtems.com to rtems.org.

  • Property mode set to 100644
File size: 9.0 KB
Line 
1/**
2 * @file
3 *
4 * @brief RTEMS RFS File Handlers
5 * @ingroup rtems_rfs
6 *
7 * This file contains the set of handlers used to process operations on
8 * RFS file nodes.
9 */
10
11/*
12 *  COPYRIGHT (c) 2010 Chris Johns <chrisj@rtems.org>
13 *
14 *  The license and distribution terms for this file may be
15 *  found in the file LICENSE in this distribution or at
16 *  http://www.rtems.org/license/LICENSE.
17 */
18
19#if HAVE_CONFIG_H
20#include "config.h"
21#endif
22
23#include <inttypes.h>
24#include <string.h>
25
26#if SIZEOF_OFF_T == 8
27#define PRIdoff_t PRId64
28#elif SIZEOF_OFF_T == 4
29#define PRIdoff_t PRId32
30#else
31#error "unsupported size of off_t"
32#endif
33
34#include <rtems/rfs/rtems-rfs-file.h>
35#include "rtems-rfs-rtems.h"
36
37/**
38 * This routine processes the open() system call.  Note that there is nothing
39 * special to be done at open() time.
40 */
41
42static int
43rtems_rfs_rtems_file_open (rtems_libio_t* iop,
44                           const char*    pathname,
45                           int            oflag,
46                           mode_t         mode)
47{
48  rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (&iop->pathinfo);
49  rtems_rfs_ino          ino;
50  rtems_rfs_file_handle* file;
51  int                    flags;
52  int                    rc;
53
54  flags = 0;
55
56  if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_FILE_OPEN))
57    printf("rtems-rfs: file-open: path:%s ino:%" PRId32 " flags:%04i mode:%04" PRIu32 "\n",
58           pathname, ino, flags, (uint32_t) mode);
59
60  rtems_rfs_rtems_lock (fs);
61
62  ino = rtems_rfs_rtems_get_iop_ino (iop);
63
64  rc = rtems_rfs_file_open (fs, ino, flags, &file);
65  if (rc > 0)
66  {
67    rtems_rfs_rtems_unlock (fs);
68    return rtems_rfs_rtems_error ("file-open: open", rc);
69  }
70
71  if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_FILE_OPEN))
72    printf("rtems-rfs: file-open: handle:%p\n", file);
73
74  rtems_rfs_rtems_set_iop_file_handle (iop, file);
75
76  rtems_rfs_rtems_unlock (fs);
77  return 0;
78}
79
80/**
81 * This routine processes the close() system call.  Note that there is nothing
82 * to flush at this point.
83 *
84 * @param iop
85 * @return int
86 */
87static int
88rtems_rfs_rtems_file_close (rtems_libio_t* iop)
89{
90  rtems_rfs_file_handle* file = rtems_rfs_rtems_get_iop_file_handle (iop);
91  rtems_rfs_file_system* fs = rtems_rfs_file_fs (file);
92  int                    rc;
93
94  if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_FILE_CLOSE))
95    printf("rtems-rfs: file-close: handle:%p\n", file);
96
97  rtems_rfs_rtems_lock (fs);
98
99  rc = rtems_rfs_file_close (fs, file);
100  if (rc > 0)
101    rc = rtems_rfs_rtems_error ("file-close: file close", rc);
102
103  rtems_rfs_rtems_unlock (fs);
104  return rc;
105}
106
107/**
108 * This routine processes the read() system call.
109 *
110 * @param iop
111 * @param buffer
112 * @param count
113 * @return int
114 */
115static ssize_t
116rtems_rfs_rtems_file_read (rtems_libio_t* iop,
117                           void*          buffer,
118                           size_t         count)
119{
120  rtems_rfs_file_handle* file = rtems_rfs_rtems_get_iop_file_handle (iop);
121  rtems_rfs_pos          pos;
122  uint8_t*               data = buffer;
123  ssize_t                read = 0;
124  int                    rc;
125
126  if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_FILE_READ))
127    printf("rtems-rfs: file-read: handle:%p count:%zd\n", file, count);
128
129  rtems_rfs_rtems_lock (rtems_rfs_file_fs (file));
130
131  pos = iop->offset;
132
133  if (pos < rtems_rfs_file_size (file))
134  {
135    while (count)
136    {
137      size_t size;
138
139      rc = rtems_rfs_file_io_start (file, &size, true);
140      if (rc > 0)
141      {
142        read = rtems_rfs_rtems_error ("file-read: read: io-start", rc);
143        break;
144      }
145
146      if (size == 0)
147        break;
148
149      if (size > count)
150        size = count;
151
152      memcpy (data, rtems_rfs_file_data (file), size);
153
154      data  += size;
155      count -= size;
156      read  += size;
157
158      rc = rtems_rfs_file_io_end (file, size, true);
159      if (rc > 0)
160      {
161        read = rtems_rfs_rtems_error ("file-read: read: io-end", rc);
162        break;
163      }
164    }
165  }
166
167  if (read >= 0)
168    iop->offset = pos + read;
169
170  rtems_rfs_rtems_unlock (rtems_rfs_file_fs (file));
171
172  return read;
173}
174
175/**
176 * This routine processes the write() system call.
177 *
178 * @param iop
179 * @param buffer
180 * @param count
181 * @return ssize_t
182 */
183static ssize_t
184rtems_rfs_rtems_file_write (rtems_libio_t* iop,
185                            const void*    buffer,
186                            size_t         count)
187{
188  rtems_rfs_file_handle* file = rtems_rfs_rtems_get_iop_file_handle (iop);
189  rtems_rfs_pos          pos;
190  rtems_rfs_pos          file_size;
191  const uint8_t*         data = buffer;
192  ssize_t                write = 0;
193  int                    rc;
194
195  if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_FILE_WRITE))
196    printf("rtems-rfs: file-write: handle:%p count:%zd\n", file, count);
197
198  rtems_rfs_rtems_lock (rtems_rfs_file_fs (file));
199
200  pos = iop->offset;
201  file_size = rtems_rfs_file_size (file);
202  if (pos > file_size)
203  {
204    /*
205     * If the iop position is past the physical end of the file we need to set
206     * the file size to the new length before writing.  The
207     * rtems_rfs_file_io_end() will grow the file subsequently.
208     */
209    rc = rtems_rfs_file_set_size (file, pos);
210    if (rc)
211    {
212      rtems_rfs_rtems_unlock (rtems_rfs_file_fs (file));
213      return rtems_rfs_rtems_error ("file-write: write extend", rc);
214    }
215
216    rtems_rfs_file_set_bpos (file, pos);
217  }
218  else if (pos < file_size && (iop->flags & LIBIO_FLAGS_APPEND) != 0)
219  {
220    pos = file_size;
221    rc = rtems_rfs_file_seek (file, pos, &pos);
222    if (rc)
223    {
224      rtems_rfs_rtems_unlock (rtems_rfs_file_fs (file));
225      return rtems_rfs_rtems_error ("file-write: write append seek", rc);
226    }
227  }
228
229  while (count)
230  {
231    size_t size = count;
232
233    rc = rtems_rfs_file_io_start (file, &size, false);
234    if (rc)
235    {
236      /*
237       * If we have run out of space and have written some data return that
238       * amount first as the inode will have accounted for it. This means
239       * there was no error and the return code from can be ignored.
240       */
241      if (!write)
242        write = rtems_rfs_rtems_error ("file-write: write open", rc);
243      break;
244    }
245
246    if (size > count)
247      size = count;
248
249    memcpy (rtems_rfs_file_data (file), data, size);
250
251    data  += size;
252    count -= size;
253    write  += size;
254
255    rc = rtems_rfs_file_io_end (file, size, false);
256    if (rc)
257    {
258      write = rtems_rfs_rtems_error ("file-write: write close", rc);
259      break;
260    }
261  }
262
263  if (write >= 0)
264    iop->offset = pos + write;
265
266  rtems_rfs_rtems_unlock (rtems_rfs_file_fs (file));
267
268  return write;
269}
270
271/**
272 * This routine processes the lseek() system call.
273 *
274 * @param iop
275 * @param offset
276 * @param whence
277 * @return off_t
278 */
279static off_t
280rtems_rfs_rtems_file_lseek (rtems_libio_t* iop,
281                            off_t          offset,
282                            int            whence)
283{
284  rtems_rfs_file_handle* file = rtems_rfs_rtems_get_iop_file_handle (iop);
285  off_t                  old_offset;
286  off_t                  new_offset;
287
288  if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_FILE_LSEEK))
289    printf("rtems-rfs: file-lseek: handle:%p offset:%" PRIdoff_t "\n", file, offset);
290
291  rtems_rfs_rtems_lock (rtems_rfs_file_fs (file));
292
293  old_offset = iop->offset;
294  new_offset = rtems_filesystem_default_lseek_file (iop, offset, whence);
295  if (new_offset != -1)
296  {
297    rtems_rfs_pos pos = iop->offset;
298    int           rc = rtems_rfs_file_seek (file, pos, &pos);
299
300    if (rc)
301    {
302      rtems_rfs_rtems_error ("file_lseek: lseek", rc);
303      iop->offset = old_offset;
304      new_offset = -1;
305    }
306  }
307
308  rtems_rfs_rtems_unlock (rtems_rfs_file_fs (file));
309
310  return new_offset;
311}
312
313/**
314 * This routine processes the ftruncate() system call.
315 *
316 * @param iop
317 * @param length
318 * @return int
319 */
320static int
321rtems_rfs_rtems_file_ftruncate (rtems_libio_t* iop,
322                                off_t          length)
323{
324  rtems_rfs_file_handle* file = rtems_rfs_rtems_get_iop_file_handle (iop);
325  int                    rc;
326
327  if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_FILE_FTRUNC))
328    printf("rtems-rfs: file-ftrunc: handle:%p length:%" PRIdoff_t "\n", file, length);
329
330  rtems_rfs_rtems_lock (rtems_rfs_file_fs (file));
331
332  rc = rtems_rfs_file_set_size (file, length);
333  if (rc)
334    rc = rtems_rfs_rtems_error ("file_ftruncate: set size", rc);
335
336  rtems_rfs_rtems_unlock (rtems_rfs_file_fs (file));
337
338  return rc;
339}
340
341/*
342 *  Set of operations handlers for operations on RFS files.
343 */
344
345const rtems_filesystem_file_handlers_r rtems_rfs_rtems_file_handlers = {
346  .open_h      = rtems_rfs_rtems_file_open,
347  .close_h     = rtems_rfs_rtems_file_close,
348  .read_h      = rtems_rfs_rtems_file_read,
349  .write_h     = rtems_rfs_rtems_file_write,
350  .ioctl_h     = rtems_filesystem_default_ioctl,
351  .lseek_h     = rtems_rfs_rtems_file_lseek,
352  .fstat_h     = rtems_rfs_rtems_fstat,
353  .ftruncate_h = rtems_rfs_rtems_file_ftruncate,
354  .fsync_h     = rtems_rfs_rtems_fdatasync,
355  .fdatasync_h = rtems_rfs_rtems_fdatasync,
356  .fcntl_h     = rtems_filesystem_default_fcntl,
357  .kqfilter_h  = rtems_filesystem_default_kqfilter,
358  .poll_h      = rtems_filesystem_default_poll,
359  .readv_h     = rtems_filesystem_default_readv,
360  .writev_h    = rtems_filesystem_default_writev
361};
Note: See TracBrowser for help on using the repository browser.