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

4.104.115
Last change on this file since 355b0544 was 355b0544, checked in by Chris Johns <chrisj@…>, on 03/27/10 at 04:04:40

2010-03-27 Chris Johns <chrisj@…>

libfs/src/nfsclient/src/cexphelp.c,
libfs/src/nfsclient/src/dirutils.c,
libfs/src/nfsclient/src/nfs.modini.c,
libfs/src/nfsclient/src/nfsTest.c,
libfs/src/nfsclient/src/rpcio.c,
libfs/src/nfsclient/src/rpcio.modini.c,
libfs/src/nfsclient/src/sock_mbuf.c,
libfs/src/nfsclient/src/xdr_mbuf.c,
libfs/src/rfs/rtems-rfs-bitmaps-ut.c,
libfs/src/rfs/rtems-rfs-bitmaps.c,
libfs/src/rfs/rtems-rfs-block.c,
libfs/src/rfs/rtems-rfs-buffer-bdbuf.c,
libfs/src/rfs/rtems-rfs-buffer-devio.c,
libfs/src/rfs/rtems-rfs-buffer.c,
libfs/src/rfs/rtems-rfs-dir-hash.c, libfs/src/rfs/rtems-rfs-dir.c,
libfs/src/rfs/rtems-rfs-file-system.c,
libfs/src/rfs/rtems-rfs-file.c, libfs/src/rfs/rtems-rfs-format.c,
libfs/src/rfs/rtems-rfs-group.c, libfs/src/rfs/rtems-rfs-inode.c,
libfs/src/rfs/rtems-rfs-link.c, libfs/src/rfs/rtems-rfs-mutex.c,
libfs/src/rfs/rtems-rfs-rtems-dev.c,
libfs/src/rfs/rtems-rfs-rtems-dir.c,
libfs/src/rfs/rtems-rfs-rtems-file.c,
libfs/src/rfs/rtems-rfs-rtems-utils.c,
libfs/src/rfs/rtems-rfs-rtems.c, libfs/src/rfs/rtems-rfs-shell.c,
libfs/src/rfs/rtems-rfs-trace.c: Add HAVE_CONFIG_H support to let
files receive configure defines.

  • Property mode set to 100644
File size: 17.0 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 File Systems File Routines.
16 *
17 * These functions manage files.
18 */
19
20#if HAVE_CONFIG_H
21#include "config.h"
22#endif
23
24#include <rtems/rfs/rtems-rfs-block-pos.h>
25#include <rtems/rfs/rtems-rfs-file.h>
26#include <rtems/rfs/rtems-rfs-file-system.h>
27#include <rtems/rfs/rtems-rfs-trace.h>
28
29int
30rtems_rfs_file_open (rtems_rfs_file_system*  fs,
31                     rtems_rfs_ino           ino,
32                     uint32_t                flags,
33                     rtems_rfs_file_handle** file)
34{
35  rtems_rfs_file_handle* handle;
36  rtems_rfs_file_shared* shared;
37  int                    rc;
38
39  if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_OPEN))
40    printf ("rtems-rfs: file-open: ino=%ld\n", ino);
41           
42  *file = NULL;
43
44  /*
45   * Allocate a new handle and initialise it. Do this before we deal with the
46   * shared node data so we do not have to be concerned with reference
47   * counting.
48   */
49  handle = malloc (sizeof (rtems_rfs_file_handle));
50  if (!handle)
51    return ENOMEM;
52
53  memset (handle, 0, sizeof (rtems_rfs_file_handle));
54
55  rc = rtems_rfs_buffer_handle_open (fs, &handle->buffer);
56  if (rc > 0)
57  {
58    if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_OPEN))
59      printf ("rtems-rfs: file-open: buffer handle open failed: %d: %s\n",
60              rc, strerror (rc));
61    free (handle);
62    return rc;
63  }
64 
65  /*
66   * Scan the file system data list of open files for this ino. If found up
67   * the reference count and return the pointer to the data.
68   */
69  shared = rtems_rfs_file_get_shared (fs, ino);
70  if (shared)
71  {
72    shared->references++;
73    if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_OPEN))
74      printf ("rtems-rfs: file-open: ino=%ld shared\n", ino);
75  }
76  else
77  {
78    /*
79     * None exists so create. Copy in the shared parts of the inode we hold in
80     * memory.
81     */
82    shared = malloc (sizeof (rtems_rfs_file_shared));
83    if (!shared)
84    {
85      rtems_rfs_buffer_handle_close (fs, &handle->buffer);
86      free (handle);
87      return ENOMEM;
88    }
89
90    memset (shared, 0, sizeof (rtems_rfs_file_shared));
91   
92    rc = rtems_rfs_inode_open (fs, ino, &shared->inode, true);
93    if (rc > 0)
94    {
95      if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_OPEN))
96        printf ("rtems-rfs: file-open: inode open failed: %d: %s\n",
97                rc, strerror (rc));
98      free (shared);
99      rtems_rfs_buffer_handle_close (fs, &handle->buffer);
100      free (handle);
101      return rc;
102    }
103
104    rc = rtems_rfs_block_map_open (fs, &shared->inode, &shared->map);
105    if (rc > 0)
106    {
107      if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_OPEN))
108        printf ("rtems-rfs: file-open: block map open failed: %d: %s\n",
109                rc, strerror (rc));
110      rtems_rfs_inode_close (fs, &shared->inode);
111      free (shared);
112      rtems_rfs_buffer_handle_close (fs, &handle->buffer);
113      free (handle);
114      return rc;
115    }
116
117    shared->references = 1;
118    shared->size.count = rtems_rfs_inode_get_block_count (&shared->inode);
119    shared->size.offset = rtems_rfs_inode_get_block_offset (&shared->inode);
120    shared->atime = rtems_rfs_inode_get_atime (&shared->inode);
121    shared->mtime = rtems_rfs_inode_get_mtime (&shared->inode);
122    shared->ctime = rtems_rfs_inode_get_ctime (&shared->inode);
123    shared->fs = fs;
124
125    rtems_chain_append (&fs->file_shares, &shared->link);
126
127    rtems_rfs_inode_unload (fs, &shared->inode, false);
128
129    if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_OPEN))
130      printf ("rtems-rfs: file-open: ino=%ld share created\n", ino);
131  }
132
133  handle->flags  = flags;
134  handle->shared = shared;
135 
136  *file = handle;
137 
138  return 0;
139}
140
141int
142rtems_rfs_file_close (rtems_rfs_file_system* fs,
143                      rtems_rfs_file_handle* handle)
144{
145  int rrc;
146  int rc;
147
148  rrc = 0;
149 
150  if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_CLOSE))
151    printf ("rtems-rfs: file-close: entry: ino=%ld\n",
152            handle->shared->inode.ino);
153
154  if (handle->shared->references > 0)
155    handle->shared->references--;
156
157  if (handle->shared->references == 0)
158  {
159    /*
160     * @todo This could be clever and only update if different.
161     */
162    rtems_rfs_inode_set_atime (&handle->shared->inode,
163                               handle->shared->atime);
164    rtems_rfs_inode_set_mtime (&handle->shared->inode,
165                               handle->shared->mtime);
166    rtems_rfs_inode_set_ctime (&handle->shared->inode,
167                               handle->shared->ctime);
168    handle->shared->map.size.count = handle->shared->size.count;
169    handle->shared->map.size.offset = handle->shared->size.offset;
170
171    rc = rtems_rfs_block_map_close (fs, &handle->shared->map);
172    if (rc > 0)
173    {
174      if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_CLOSE))
175        printf ("rtems-rfs: file-close: map close error: ino=%ld: %d: %s\n",
176                handle->shared->inode.ino, rc, strerror (rc));
177      if (rrc == 0)
178        rrc = rc;
179    }
180   
181    rc = rtems_rfs_inode_close (fs, &handle->shared->inode);
182    if (rc > 0)
183    {
184      if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_CLOSE))
185        printf ("rtems-rfs: file-close: inode close error: ino=%ld: %d: %s\n",
186                handle->shared->inode.ino, rc, strerror (rc));
187      if (rrc == 0)
188        rrc = rc;
189    }
190   
191    rtems_chain_extract (&handle->shared->link);
192    free (handle->shared);
193  }
194
195  rc = rtems_rfs_buffer_handle_close (fs, &handle->buffer);
196  if ((rrc == 0) && (rc > 0))
197    rrc = rc;
198 
199  if (rrc > 0)
200  {
201    if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_CLOSE))
202      printf ("rtems-rfs: file-close: result: %d: %s\n", rrc, strerror (rrc));
203  }
204
205  free (handle);
206 
207  return rrc;
208}
209
210int
211rtems_rfs_file_io_start (rtems_rfs_file_handle* handle,
212                         size_t*                available,
213                         bool                   read)
214{
215  size_t size;
216 
217  if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_IO))
218    printf ("rtems-rfs: file-io: start: %s pos=%lu:%lu\n",
219            read ? "read" : "write",  handle->bpos.bno, handle->bpos.boff);
220 
221  if (!rtems_rfs_buffer_handle_has_block (&handle->buffer))
222  {
223    rtems_rfs_buffer_block block;
224    bool                   request_read;
225    int                    rc;
226     
227    request_read = read;
228   
229    rc = rtems_rfs_block_map_find (rtems_rfs_file_fs (handle),
230                                   rtems_rfs_file_map (handle),
231                                   rtems_rfs_file_bpos (handle),
232                                   &block);
233    if (rc > 0)
234    {
235      /*
236       * Has the read reached the EOF ?
237       */
238      if (read && (rc == ENXIO))
239      {
240        *available = 0;
241        return 0;
242      }
243     
244      if (rc != ENXIO)
245        return rc;
246
247      if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_IO))
248        printf ("rtems-rfs: file-io: start: grow\n");
249     
250      rc = rtems_rfs_block_map_grow (rtems_rfs_file_fs (handle),
251                                     rtems_rfs_file_map (handle),
252                                     1, &block);
253      if (rc > 0)
254        return rc;
255
256      request_read = false;
257    }
258    else
259    {
260      /*
261       * If this is a write check if the write starts within a block or the
262       * amount of data is less than a block size. If it is read the block
263       * rather than getting a block to fill.
264       */
265      if (!read &&
266          (rtems_rfs_file_block_offset (handle) ||
267           (*available < rtems_rfs_fs_block_size (rtems_rfs_file_fs (handle)))))
268        request_read = true;
269    }
270   
271    if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_IO))
272      printf ("rtems-rfs: file-io: start: block=%lu request-read=%s\n",
273              block, request_read ? "yes" : "no");
274   
275    rc = rtems_rfs_buffer_handle_request (rtems_rfs_file_fs (handle),
276                                          rtems_rfs_file_buffer (handle),
277                                          block, request_read);
278    if (rc > 0)
279      return rc;
280  }
281 
282  if (read
283      && rtems_rfs_block_map_last (rtems_rfs_file_map (handle))
284      && rtems_rfs_block_map_size_offset (rtems_rfs_file_map (handle)))
285    size = rtems_rfs_block_map_size_offset (rtems_rfs_file_map (handle));
286  else
287    size = rtems_rfs_fs_block_size (rtems_rfs_file_fs (handle));
288 
289  *available = size - rtems_rfs_file_block_offset (handle);
290
291  if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_IO))
292    printf ("rtems-rfs: file-io: start: available=%zu (%zu)\n",
293            *available, size);
294   
295  return 0;
296}
297
298int
299rtems_rfs_file_io_end (rtems_rfs_file_handle* handle,
300                       size_t                 size,
301                       bool                   read)
302{
303  bool atime;
304  bool mtime;
305  bool length;
306  int  rc = 0;
307
308  if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_IO))
309    printf ("rtems-rfs: file-io:   end: %s size=%zu\n",
310            read ? "read" : "write", size);
311 
312  if (rtems_rfs_buffer_handle_has_block (&handle->buffer))
313  {
314    if (!read)
315      rtems_rfs_buffer_mark_dirty (rtems_rfs_file_buffer (handle));
316    rc = rtems_rfs_buffer_handle_release (rtems_rfs_file_fs (handle),
317                                          rtems_rfs_file_buffer (handle));
318    if (rc > 0)
319    {
320      printf (
321        "rtems-rfs: file-io:   end: error on release: %s size=%zu: %d: %s\n",
322        read ? "read" : "write", size, rc, strerror (rc));
323     
324      return rc;
325    }
326  }
327
328  /*
329   * Update the handle's position. Only a block size can be handled at a time
330   * so no special maths is needed. If the offset is bigger than the block size
331   * increase the block number and adjust the offset.
332   *
333   * If we are the last block and the position is past the current size update
334   * the size with the new length. The map holds the block count.
335   */
336  handle->bpos.boff += size;
337
338  if (handle->bpos.boff >=
339      rtems_rfs_fs_block_size (rtems_rfs_file_fs (handle)))
340  {
341    handle->bpos.bno++;
342    handle->bpos.boff -= rtems_rfs_fs_block_size (rtems_rfs_file_fs (handle));
343  }
344
345  length = false;
346  mtime = false;
347 
348  if (!read &&
349      rtems_rfs_block_map_past_end (rtems_rfs_file_map (handle),
350                                    rtems_rfs_file_bpos (handle)))
351  {
352    rtems_rfs_block_map_set_size_offset (rtems_rfs_file_map (handle),
353                                         handle->bpos.boff);
354    length = true;
355    mtime = true;
356  }
357 
358  atime  = rtems_rfs_file_update_atime (handle);
359  mtime  = rtems_rfs_file_update_mtime (handle) && mtime;
360  length = rtems_rfs_file_update_length (handle) && length;
361 
362  if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_IO))
363    printf ("rtems-rfs: file-io:   end: pos=%lu:%lu %c %c %c\n",
364            handle->bpos.bno, handle->bpos.boff,
365            atime ? 'A' : '-', mtime ? 'M' : '-', length ? 'L' : '-');
366 
367  if (atime || mtime)
368  {
369    time_t now = time (NULL);
370    if (read && atime)
371      handle->shared->atime = now;
372    if (!read && mtime)
373      handle->shared->mtime = now;
374  }
375  if (length)
376  {
377    handle->shared->size.count =
378      rtems_rfs_block_map_count (rtems_rfs_file_map (handle));
379    handle->shared->size.offset =
380      rtems_rfs_block_map_size_offset (rtems_rfs_file_map (handle));
381  }
382 
383  return rc;
384}
385
386int
387rtems_rfs_file_io_release (rtems_rfs_file_handle* handle)
388{
389  int rc = 0;
390  if (rtems_rfs_buffer_handle_has_block (&handle->buffer))
391    rc = rtems_rfs_buffer_handle_release (rtems_rfs_file_fs (handle),
392                                          rtems_rfs_file_buffer (handle));
393  return rc;
394}
395
396int
397rtems_rfs_file_seek (rtems_rfs_file_handle* handle,
398                     rtems_rfs_pos          pos,
399                     rtems_rfs_pos*         new_pos)
400{
401  if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_IO))
402    printf ("rtems-rfs: file-seek: new=%Lu\n", pos);
403 
404  /*
405   * This call only sets the position if it is in a valid part of the file. The
406   * user can request past the end of the file then write to extend the
407   * file. The lseek entry states:
408   *
409   *    "Although lseek() may position the file offset beyond the end of the
410   *     file, this function does not itself extend the size of the file."
411   *
412   * This means the file needs to set the file size to the pos only when a
413   * write occurs.
414   */
415  if (pos <= rtems_rfs_file_shared_get_size (rtems_rfs_file_fs (handle),
416                                             handle->shared))
417    rtems_rfs_file_set_bpos (handle, pos);
418 
419  *new_pos = pos;
420  return 0;
421}
422
423int
424rtems_rfs_file_set_size (rtems_rfs_file_handle* handle,
425                         rtems_rfs_pos          new_size)
426{
427  rtems_rfs_block_map* map  = rtems_rfs_file_map (handle);
428  rtems_rfs_pos        size;
429  int                  rc;
430
431  if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_IO))
432    printf ("rtems-rfs: file-set-size: size=%Lu\n", new_size);
433
434  /*
435   * Short cut for the common truncate on open call.
436   */
437  if (new_size == 0)
438  {
439    rc = rtems_rfs_block_map_free_all (rtems_rfs_file_fs (handle), map);
440    if (rc > 0)
441      return rc;
442  }
443  else
444  {
445    size = rtems_rfs_file_size (handle);
446 
447    /*
448     * If the file is same size do nothing else grow or shrink it ?
449     */
450    if (size != new_size)
451    {
452      if (size < new_size)
453      {
454        /*
455         * Grow. Fill with 0's.
456         */
457        rtems_rfs_pos count;
458        uint32_t      length;
459        bool          read_block;
460
461        count = new_size - size;
462        length = rtems_rfs_fs_block_size (rtems_rfs_file_fs (handle));
463        read_block = false;
464       
465        while (count)
466        {
467          rtems_rfs_buffer_block block;
468          rtems_rfs_block_pos    bpos;
469          uint8_t*               dst;
470
471          /*
472           * Get the block position for the current end of the file as seen by
473           * the map. If not found and the EOF grow the map then fill the block
474           * with 0.
475           */
476          rtems_rfs_block_size_get_bpos (rtems_rfs_block_map_size (map), &bpos);
477          rc = rtems_rfs_block_map_find (rtems_rfs_file_fs (handle),
478                                         map, &bpos, &block);
479          if (rc > 0)
480          {
481            /*
482             * Have we reached the EOF ?
483             */
484            if (rc != ENXIO)
485              return rc;
486
487            rc = rtems_rfs_block_map_grow (rtems_rfs_file_fs (handle),
488                                           map, 1, &block);
489            if (rc > 0)
490              return rc;
491          }
492
493          if (count < (length - bpos.boff))
494          {
495            length = count + bpos.boff;
496            read_block = true;
497            rtems_rfs_block_map_set_size_offset (map, length);
498          }
499          else
500          {
501            rtems_rfs_block_map_set_size_offset (map, 0);
502          }
503
504          /*
505           * Only read the block if the length is not the block size.
506           */
507          rc = rtems_rfs_buffer_handle_request (rtems_rfs_file_fs (handle),
508                                                rtems_rfs_file_buffer (handle),
509                                                block, read_block);
510          if (rc > 0)
511            return rc;
512
513          dst = rtems_rfs_buffer_data (&handle->buffer);
514          memset (dst + bpos.boff, 0, length - bpos.boff);
515
516          rtems_rfs_buffer_mark_dirty (rtems_rfs_file_buffer (handle));
517
518          rc = rtems_rfs_buffer_handle_release (rtems_rfs_file_fs (handle),
519                                                rtems_rfs_file_buffer (handle));
520          if (rc > 0)
521            return rc;
522       
523          count -= length - bpos.boff;
524        }
525      }
526      else
527      {
528        /*
529         * Shrink
530         */
531        rtems_rfs_block_no blocks;
532        uint32_t           offset;
533   
534        blocks =
535          rtems_rfs_block_map_count (map) -
536          (((new_size - 1) /
537            rtems_rfs_fs_block_size (rtems_rfs_file_fs (handle))) + 1);
538
539        offset =
540          new_size % rtems_rfs_fs_block_size (rtems_rfs_file_fs (handle));
541     
542        if (blocks)
543        {
544          int rc;
545          rc = rtems_rfs_block_map_shrink (rtems_rfs_file_fs (handle),
546                                           rtems_rfs_file_map (handle),
547                                           blocks);
548          if (rc > 0)
549            return rc;
550        }
551
552        rtems_rfs_block_map_set_size_offset (map, offset);
553
554        if (rtems_rfs_block_pos_past_end (rtems_rfs_file_bpos (handle),
555                                          rtems_rfs_block_map_size (map)))
556          rtems_rfs_block_size_get_bpos (rtems_rfs_block_map_size (map),
557                                         rtems_rfs_file_bpos (handle));
558      }
559    }
560  }
561
562  handle->shared->size.count  = rtems_rfs_block_map_count (map);
563  handle->shared->size.offset = rtems_rfs_block_map_size_offset (map);
564
565  if (rtems_rfs_file_update_mtime (handle))
566    handle->shared->mtime = time (NULL);
567 
568  return 0;
569}
570
571rtems_rfs_file_shared*
572rtems_rfs_file_get_shared (rtems_rfs_file_system* fs,
573                           rtems_rfs_ino          ino)
574{
575  rtems_chain_node* node;
576  node = rtems_chain_first (&fs->file_shares);
577  while (!rtems_chain_is_tail (&fs->file_shares, node))
578  {
579    rtems_rfs_file_shared* shared;
580    shared = (rtems_rfs_file_shared*) node;
581    if (shared->inode.ino == ino)
582      return shared;
583    node = rtems_chain_next (node);
584  }
585  return NULL;
586}
Note: See TracBrowser for help on using the repository browser.