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

4.115
Last change on this file since 9b4422a2 was 9b4422a2, checked in by Joel Sherrill <joel.sherrill@…>, on 05/03/12 at 15:09:24

Remove All CVS Id Strings Possible Using a Script

Script does what is expected and tries to do it as
smartly as possible.

+ remove occurrences of two blank comment lines

next to each other after Id string line removed.

+ remove entire comment blocks which only exited to

contain CVS Ids

+ If the processing left a blank line at the top of

a file, it was removed.

  • Property mode set to 100644
File size: 18.4 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/**
9 * @file
10 *
11 * @ingroup rtems-rfs
12 *
13 * RTEMS File Systems File Routines.
14 *
15 * These functions manage files.
16 */
17
18#if HAVE_CONFIG_H
19#include "config.h"
20#endif
21
22#include <inttypes.h>
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                     int                     oflag,
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=%" PRId32 "\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=%" PRId32 " 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=%" PRId32 " share created\n", ino);
131  }
132
133  handle->flags  = oflag;
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=%" PRId32 "\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    if (!rtems_rfs_inode_is_loaded (&handle->shared->inode))
160      rrc = rtems_rfs_inode_load (fs, &handle->shared->inode);
161
162    if (rrc == 0)
163    {
164      /*
165       * @todo This could be clever and only update if different.
166       */
167      rtems_rfs_inode_set_atime (&handle->shared->inode,
168                                 handle->shared->atime);
169      rtems_rfs_inode_set_mtime (&handle->shared->inode,
170                                 handle->shared->mtime);
171      rtems_rfs_inode_set_ctime (&handle->shared->inode,
172                                 handle->shared->ctime);
173      if (!rtems_rfs_block_size_equal (&handle->shared->size,
174                                       &handle->shared->map.size))
175        rtems_rfs_block_map_set_size (&handle->shared->map,
176                                      &handle->shared->size);
177    }
178
179    rc = rtems_rfs_block_map_close (fs, &handle->shared->map);
180    if (rc > 0)
181    {
182      if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_CLOSE))
183        printf ("rtems-rfs: file-close: map close error: ino=%" PRId32 ": %d: %s\n",
184                handle->shared->inode.ino, rc, strerror (rc));
185      if (rrc == 0)
186        rrc = rc;
187    }
188
189    rc = rtems_rfs_inode_close (fs, &handle->shared->inode);
190    if (rc > 0)
191    {
192      if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_CLOSE))
193        printf ("rtems-rfs: file-close: inode close error: ino=%" PRId32 ": %d: %s\n",
194                handle->shared->inode.ino, rc, strerror (rc));
195      if (rrc == 0)
196        rrc = rc;
197    }
198
199    rtems_chain_extract (&handle->shared->link);
200    free (handle->shared);
201  }
202
203  rc = rtems_rfs_buffer_handle_close (fs, &handle->buffer);
204  if ((rrc == 0) && (rc > 0))
205    rrc = rc;
206
207  if (rrc > 0)
208  {
209    if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_CLOSE))
210      printf ("rtems-rfs: file-close: result: %d: %s\n", rrc, strerror (rrc));
211  }
212
213  free (handle);
214
215  return rrc;
216}
217
218int
219rtems_rfs_file_io_start (rtems_rfs_file_handle* handle,
220                         size_t*                available,
221                         bool                   read)
222{
223  size_t size;
224
225  if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_IO))
226    printf ("rtems-rfs: file-io: start: %s pos=%" PRIu32 ":%" PRIu32 "\n",
227            read ? "read" : "write",  handle->bpos.bno, handle->bpos.boff);
228
229  if (!rtems_rfs_buffer_handle_has_block (&handle->buffer))
230  {
231    rtems_rfs_buffer_block block;
232    bool                   request_read;
233    int                    rc;
234
235    request_read = read;
236
237    rc = rtems_rfs_block_map_find (rtems_rfs_file_fs (handle),
238                                   rtems_rfs_file_map (handle),
239                                   rtems_rfs_file_bpos (handle),
240                                   &block);
241    if (rc > 0)
242    {
243      /*
244       * Has the read reached the EOF ?
245       */
246      if (read && (rc == ENXIO))
247      {
248        *available = 0;
249        return 0;
250      }
251
252      if (rc != ENXIO)
253        return rc;
254
255      if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_IO))
256        printf ("rtems-rfs: file-io: start: grow\n");
257
258      rc = rtems_rfs_block_map_grow (rtems_rfs_file_fs (handle),
259                                     rtems_rfs_file_map (handle),
260                                     1, &block);
261      if (rc > 0)
262        return rc;
263
264      request_read = false;
265    }
266    else
267    {
268      /*
269       * If this is a write check if the write starts within a block or the
270       * amount of data is less than a block size. If it is read the block
271       * rather than getting a block to fill.
272       */
273      if (!read &&
274          (rtems_rfs_file_block_offset (handle) ||
275           (*available < rtems_rfs_fs_block_size (rtems_rfs_file_fs (handle)))))
276        request_read = true;
277    }
278
279    if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_IO))
280      printf ("rtems-rfs: file-io: start: block=%" PRIu32 " request-read=%s\n",
281              block, request_read ? "yes" : "no");
282
283    rc = rtems_rfs_buffer_handle_request (rtems_rfs_file_fs (handle),
284                                          rtems_rfs_file_buffer (handle),
285                                          block, request_read);
286    if (rc > 0)
287      return rc;
288  }
289
290  if (read
291      && rtems_rfs_block_map_last (rtems_rfs_file_map (handle))
292      && rtems_rfs_block_map_size_offset (rtems_rfs_file_map (handle)))
293    size = rtems_rfs_block_map_size_offset (rtems_rfs_file_map (handle));
294  else
295    size = rtems_rfs_fs_block_size (rtems_rfs_file_fs (handle));
296
297  *available = size - rtems_rfs_file_block_offset (handle);
298
299  if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_IO))
300    printf ("rtems-rfs: file-io: start: available=%zu (%zu)\n",
301            *available, size);
302
303  return 0;
304}
305
306int
307rtems_rfs_file_io_end (rtems_rfs_file_handle* handle,
308                       size_t                 size,
309                       bool                   read)
310{
311  bool atime;
312  bool mtime;
313  bool length;
314  int  rc = 0;
315
316  if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_IO))
317    printf ("rtems-rfs: file-io:   end: %s size=%zu\n",
318            read ? "read" : "write", size);
319
320  if (rtems_rfs_buffer_handle_has_block (&handle->buffer))
321  {
322    if (!read)
323      rtems_rfs_buffer_mark_dirty (rtems_rfs_file_buffer (handle));
324    rc = rtems_rfs_buffer_handle_release (rtems_rfs_file_fs (handle),
325                                          rtems_rfs_file_buffer (handle));
326    if (rc > 0)
327    {
328      printf (
329        "rtems-rfs: file-io:   end: error on release: %s size=%zu: %d: %s\n",
330        read ? "read" : "write", size, rc, strerror (rc));
331
332      return rc;
333    }
334  }
335
336  /*
337   * Update the handle's position. Only a block size can be handled at a time
338   * so no special maths is needed. If the offset is bigger than the block size
339   * increase the block number and adjust the offset.
340   *
341   * If we are the last block and the position is past the current size update
342   * the size with the new length. The map holds the block count.
343   */
344  handle->bpos.boff += size;
345
346  if (handle->bpos.boff >=
347      rtems_rfs_fs_block_size (rtems_rfs_file_fs (handle)))
348  {
349    handle->bpos.bno++;
350    handle->bpos.boff -= rtems_rfs_fs_block_size (rtems_rfs_file_fs (handle));
351  }
352
353  length = false;
354  mtime = false;
355
356  if (!read &&
357      rtems_rfs_block_map_past_end (rtems_rfs_file_map (handle),
358                                    rtems_rfs_file_bpos (handle)))
359  {
360    rtems_rfs_block_map_set_size_offset (rtems_rfs_file_map (handle),
361                                         handle->bpos.boff);
362    length = true;
363    mtime = true;
364  }
365
366  atime  = rtems_rfs_file_update_atime (handle);
367  mtime  = rtems_rfs_file_update_mtime (handle) && mtime;
368  length = rtems_rfs_file_update_length (handle) && length;
369
370  if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_IO))
371    printf ("rtems-rfs: file-io:   end: pos=%" PRIu32 ":%" PRIu32 " %c %c %c\n",
372            handle->bpos.bno, handle->bpos.boff,
373            atime ? 'A' : '-', mtime ? 'M' : '-', length ? 'L' : '-');
374
375  if (atime || mtime)
376  {
377    time_t now = time (NULL);
378    if (read && atime)
379      handle->shared->atime = now;
380    if (!read && mtime)
381      handle->shared->mtime = now;
382  }
383  if (length)
384  {
385    handle->shared->size.count =
386      rtems_rfs_block_map_count (rtems_rfs_file_map (handle));
387    handle->shared->size.offset =
388      rtems_rfs_block_map_size_offset (rtems_rfs_file_map (handle));
389  }
390
391  return rc;
392}
393
394int
395rtems_rfs_file_io_release (rtems_rfs_file_handle* handle)
396{
397  int rc = 0;
398  if (rtems_rfs_buffer_handle_has_block (&handle->buffer))
399    rc = rtems_rfs_buffer_handle_release (rtems_rfs_file_fs (handle),
400                                          rtems_rfs_file_buffer (handle));
401  return rc;
402}
403
404int
405rtems_rfs_file_seek (rtems_rfs_file_handle* handle,
406                     rtems_rfs_pos          pos,
407                     rtems_rfs_pos*         new_pos)
408{
409  if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_IO))
410    printf ("rtems-rfs: file-seek: new=%" PRIu64 "\n", pos);
411
412  /*
413   * This call only sets the position if it is in a valid part of the file. The
414   * user can request past the end of the file then write to extend the
415   * file. The lseek entry states:
416   *
417   *    "Although lseek() may position the file offset beyond the end of the
418   *     file, this function does not itself extend the size of the file."
419   *
420   * This means the file needs to set the file size to the pos only when a
421   * write occurs.
422   */
423  if (pos <= rtems_rfs_file_shared_get_size (rtems_rfs_file_fs (handle),
424                                            handle->shared))
425  {
426    rtems_rfs_file_set_bpos (handle, pos);
427   
428    /*
429     * If the file has a block check if it maps to the current position and it
430     * does not release it. That will force us to get the block at the new
431     * position when the I/O starts.
432     */
433    if (rtems_rfs_buffer_handle_has_block (&handle->buffer))
434    {
435      rtems_rfs_buffer_block block;
436      int                    rc;
437     
438      rc = rtems_rfs_block_map_find (rtems_rfs_file_fs (handle),
439                                     rtems_rfs_file_map (handle),
440                                     rtems_rfs_file_bpos (handle),
441                                     &block);
442      if (rc > 0)
443        return rc;
444      if (rtems_rfs_buffer_bnum (&handle->buffer) != block)
445      {       
446        rc = rtems_rfs_buffer_handle_release (rtems_rfs_file_fs (handle),
447                                              rtems_rfs_file_buffer (handle));
448        if (rc > 0)
449          return rc;
450      }
451    }
452  }
453  else
454  {
455    /*
456     * The seek is outside the current file so release any buffer. A write will
457     * extend the file.
458     */
459    int rc = rtems_rfs_file_io_release (handle);
460    if (rc > 0)
461      return rc;
462  }
463 
464  *new_pos = pos;
465  return 0;
466}
467
468int
469rtems_rfs_file_set_size (rtems_rfs_file_handle* handle,
470                         rtems_rfs_pos          new_size)
471{
472  rtems_rfs_block_map* map  = rtems_rfs_file_map (handle);
473  rtems_rfs_pos        size;
474  int                  rc;
475
476  if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_IO))
477    printf ("rtems-rfs: file-set-size: size=%" PRIu64 "\n", new_size);
478
479  size = rtems_rfs_file_size (handle);
480 
481  /*
482   * If the file is same size do nothing else grow or shrink it ?
483   *
484   * If the file does not change size do not update the times.
485   */
486  if (size != new_size)
487  {
488    /*
489     * Short cut for the common truncate on open call.
490     */
491    if (new_size == 0)
492    {
493      rc = rtems_rfs_block_map_free_all (rtems_rfs_file_fs (handle), map);
494      if (rc > 0)
495        return rc;
496    }
497    else
498    {
499      if (size < new_size)
500      {
501        /*
502         * Grow. Fill with 0's.
503         */
504        rtems_rfs_pos count;
505        uint32_t      length;
506        bool          read_block;
507
508        count = new_size - size;
509        length = rtems_rfs_fs_block_size (rtems_rfs_file_fs (handle));
510        read_block = false;
511
512        while (count)
513        {
514          rtems_rfs_buffer_block block;
515          rtems_rfs_block_pos    bpos;
516          uint8_t*               dst;
517
518          /*
519           * Get the block position for the current end of the file as seen by
520           * the map. If not found and the EOF grow the map then fill the block
521           * with 0.
522           */
523          rtems_rfs_block_size_get_bpos (rtems_rfs_block_map_size (map), &bpos);
524          rc = rtems_rfs_block_map_find (rtems_rfs_file_fs (handle),
525                                         map, &bpos, &block);
526          if (rc > 0)
527          {
528            /*
529             * Have we reached the EOF ?
530             */
531            if (rc != ENXIO)
532              return rc;
533
534            rc = rtems_rfs_block_map_grow (rtems_rfs_file_fs (handle),
535                                           map, 1, &block);
536            if (rc > 0)
537              return rc;
538          }
539
540          if (count < (length - bpos.boff))
541          {
542            length = count + bpos.boff;
543            read_block = true;
544            rtems_rfs_block_map_set_size_offset (map, length);
545          }
546          else
547          {
548            rtems_rfs_block_map_set_size_offset (map, 0);
549          }
550
551          /*
552           * Only read the block if the length is not the block size.
553           */
554          rc = rtems_rfs_buffer_handle_request (rtems_rfs_file_fs (handle),
555                                                rtems_rfs_file_buffer (handle),
556                                                block, read_block);
557          if (rc > 0)
558            return rc;
559
560          dst = rtems_rfs_buffer_data (&handle->buffer);
561          memset (dst + bpos.boff, 0, length - bpos.boff);
562
563          rtems_rfs_buffer_mark_dirty (rtems_rfs_file_buffer (handle));
564
565          rc = rtems_rfs_buffer_handle_release (rtems_rfs_file_fs (handle),
566                                                rtems_rfs_file_buffer (handle));
567          if (rc > 0)
568            return rc;
569
570          count -= length - bpos.boff;
571        }
572      }
573      else
574      {
575        /*
576         * Shrink
577         */
578        rtems_rfs_block_no blocks;
579        uint32_t           offset;
580
581        blocks =
582          rtems_rfs_block_map_count (map) -
583          (((new_size - 1) /
584            rtems_rfs_fs_block_size (rtems_rfs_file_fs (handle))) + 1);
585
586        offset =
587          new_size % rtems_rfs_fs_block_size (rtems_rfs_file_fs (handle));
588
589        if (blocks)
590        {
591          int rc;
592          rc = rtems_rfs_block_map_shrink (rtems_rfs_file_fs (handle),
593                                           rtems_rfs_file_map (handle),
594                                           blocks);
595          if (rc > 0)
596            return rc;
597        }
598
599        rtems_rfs_block_map_set_size_offset (map, offset);
600
601        if (rtems_rfs_block_pos_past_end (rtems_rfs_file_bpos (handle),
602                                          rtems_rfs_block_map_size (map)))
603          rtems_rfs_block_size_get_bpos (rtems_rfs_block_map_size (map),
604                                         rtems_rfs_file_bpos (handle));
605      }
606    }
607
608    handle->shared->size.count  = rtems_rfs_block_map_count (map);
609    handle->shared->size.offset = rtems_rfs_block_map_size_offset (map);
610
611    if (rtems_rfs_file_update_mtime (handle))
612      handle->shared->mtime = time (NULL);
613  }
614 
615  return 0;
616}
617
618rtems_rfs_file_shared*
619rtems_rfs_file_get_shared (rtems_rfs_file_system* fs,
620                           rtems_rfs_ino          ino)
621{
622  rtems_chain_node* node;
623  node = rtems_chain_first (&fs->file_shares);
624  while (!rtems_chain_is_tail (&fs->file_shares, node))
625  {
626    rtems_rfs_file_shared* shared;
627    shared = (rtems_rfs_file_shared*) node;
628    if (shared->inode.ino == ino)
629      return shared;
630    node = rtems_chain_next (node);
631  }
632  return NULL;
633}
Note: See TracBrowser for help on using the repository browser.