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

4.104.115
Last change on this file since 3c0654d was a9fa9b7, checked in by Chris Johns <chrisj@…>, on 02/18/10 at 00:24:25

2010-02-18 Chris Johns <chrisj@…>

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