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

4.104.115
Last change on this file since 5fe3834 was 5fe3834, checked in by Joel Sherrill <joel.sherrill@…>, on 03/22/10 at 14:55:37

2010-03-22 Joel Sherrill <joel.sherrill@…>

  • libfs/src/rfs/rtems-rfs-bitmaps-ut.c, libfs/src/rfs/rtems-rfs-block.c, libfs/src/rfs/rtems-rfs-buffer.c, libfs/src/rfs/rtems-rfs-dir.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-rtems-file.c, libfs/src/rfs/rtems-rfs-shell.c: Fix printf format warning. Primarily for size_t.
  • Property mode set to 100644
File size: 16.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 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
279      && rtems_rfs_block_map_last (rtems_rfs_file_map (handle))
280      && rtems_rfs_block_map_size_offset (rtems_rfs_file_map (handle)))
281    size = rtems_rfs_block_map_size_offset (rtems_rfs_file_map (handle));
282  else
283    size = rtems_rfs_fs_block_size (rtems_rfs_file_fs (handle));
284 
285  *available = size - rtems_rfs_file_block_offset (handle);
286
287  if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_IO))
288    printf ("rtems-rfs: file-io: start: available=%zu (%zu)\n",
289            *available, size);
290   
291  return 0;
292}
293
294int
295rtems_rfs_file_io_end (rtems_rfs_file_handle* handle,
296                       size_t                 size,
297                       bool                   read)
298{
299  bool atime;
300  bool mtime;
301  bool length;
302  int  rc = 0;
303
304  if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_IO))
305    printf ("rtems-rfs: file-io:   end: %s size=%zu\n",
306            read ? "read" : "write", size);
307 
308  if (rtems_rfs_buffer_handle_has_block (&handle->buffer))
309  {
310    if (!read)
311      rtems_rfs_buffer_mark_dirty (rtems_rfs_file_buffer (handle));
312    rc = rtems_rfs_buffer_handle_release (rtems_rfs_file_fs (handle),
313                                          rtems_rfs_file_buffer (handle));
314    if (rc > 0)
315    {
316      printf (
317        "rtems-rfs: file-io:   end: error on release: %s size=%zu: %d: %s\n",
318        read ? "read" : "write", size, rc, strerror (rc));
319     
320      return rc;
321    }
322  }
323
324  /*
325   * Update the handle's position. Only a block size can be handled at a time
326   * so no special maths is needed. If the offset is bigger than the block size
327   * increase the block number and adjust the offset.
328   *
329   * If we are the last block and the position is past the current size update
330   * the size with the new length. The map holds the block count.
331   */
332  handle->bpos.boff += size;
333
334  if (handle->bpos.boff >=
335      rtems_rfs_fs_block_size (rtems_rfs_file_fs (handle)))
336  {
337    handle->bpos.bno++;
338    handle->bpos.boff -= rtems_rfs_fs_block_size (rtems_rfs_file_fs (handle));
339  }
340
341  length = false;
342  mtime = false;
343 
344  if (!read &&
345      rtems_rfs_block_map_past_end (rtems_rfs_file_map (handle),
346                                    rtems_rfs_file_bpos (handle)))
347  {
348    rtems_rfs_block_map_set_size_offset (rtems_rfs_file_map (handle),
349                                         handle->bpos.boff);
350    length = true;
351    mtime = true;
352  }
353 
354  atime  = rtems_rfs_file_update_atime (handle);
355  mtime  = rtems_rfs_file_update_mtime (handle) && mtime;
356  length = rtems_rfs_file_update_length (handle) && length;
357 
358  if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_IO))
359    printf ("rtems-rfs: file-io:   end: pos=%lu:%lu %c %c %c\n",
360            handle->bpos.bno, handle->bpos.boff,
361            atime ? 'A' : '-', mtime ? 'M' : '-', length ? 'L' : '-');
362 
363  if (atime || mtime)
364  {
365    time_t now = time (NULL);
366    if (read && atime)
367      handle->shared->atime = now;
368    if (!read && mtime)
369      handle->shared->mtime = now;
370  }
371  if (length)
372  {
373    handle->shared->size.count =
374      rtems_rfs_block_map_count (rtems_rfs_file_map (handle));
375    handle->shared->size.offset =
376      rtems_rfs_block_map_size_offset (rtems_rfs_file_map (handle));
377  }
378 
379  return rc;
380}
381
382int
383rtems_rfs_file_io_release (rtems_rfs_file_handle* handle)
384{
385  int rc = 0;
386  if (rtems_rfs_buffer_handle_has_block (&handle->buffer))
387    rc = rtems_rfs_buffer_handle_release (rtems_rfs_file_fs (handle),
388                                          rtems_rfs_file_buffer (handle));
389  return rc;
390}
391
392int
393rtems_rfs_file_seek (rtems_rfs_file_handle* handle,
394                     rtems_rfs_pos          pos,
395                     rtems_rfs_pos*         new_pos)
396{
397  if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_IO))
398    printf ("rtems-rfs: file-seek: new=%Lu\n", pos);
399 
400  /*
401   * This call only sets the position if it is in a valid part of the file. The
402   * user can request past the end of the file then write to extend the
403   * file. The lseek entry states:
404   *
405   *    "Although lseek() may position the file offset beyond the end of the
406   *     file, this function does not itself extend the size of the file."
407   *
408   * This means the file needs to set the file size to the pos only when a
409   * write occurs.
410   */
411  if (pos <= rtems_rfs_file_shared_get_size (rtems_rfs_file_fs (handle),
412                                             handle->shared))
413    rtems_rfs_file_set_bpos (handle, pos);
414 
415  *new_pos = pos;
416  return 0;
417}
418
419int
420rtems_rfs_file_set_size (rtems_rfs_file_handle* handle,
421                         rtems_rfs_pos          new_size)
422{
423  rtems_rfs_block_map* map  = rtems_rfs_file_map (handle);
424  rtems_rfs_pos        size;
425  int                  rc;
426
427  if (rtems_rfs_trace (RTEMS_RFS_TRACE_FILE_IO))
428    printf ("rtems-rfs: file-set-size: size=%Lu\n", new_size);
429
430  /*
431   * Short cut for the common truncate on open call.
432   */
433  if (new_size == 0)
434  {
435    rc = rtems_rfs_block_map_free_all (rtems_rfs_file_fs (handle), map);
436    if (rc > 0)
437      return rc;
438  }
439  else
440  {
441    size = rtems_rfs_file_size (handle);
442 
443    /*
444     * If the file is same size do nothing else grow or shrink it ?
445     */
446    if (size != new_size)
447    {
448      if (size < new_size)
449      {
450        /*
451         * Grow. Fill with 0's.
452         */
453        rtems_rfs_pos count;
454        uint32_t      length;
455        bool          read_block;
456
457        count = new_size - size;
458        length = rtems_rfs_fs_block_size (rtems_rfs_file_fs (handle));
459        read_block = false;
460       
461        while (count)
462        {
463          rtems_rfs_buffer_block block;
464          rtems_rfs_block_pos    bpos;
465          uint8_t*               dst;
466
467          /*
468           * Get the block position for the current end of the file as seen by
469           * the map. If not found and the EOF grow the map then fill the block
470           * with 0.
471           */
472          rtems_rfs_block_size_get_bpos (rtems_rfs_block_map_size (map), &bpos);
473          rc = rtems_rfs_block_map_find (rtems_rfs_file_fs (handle),
474                                         map, &bpos, &block);
475          if (rc > 0)
476          {
477            /*
478             * Have we reached the EOF ?
479             */
480            if (rc != ENXIO)
481              return rc;
482
483            rc = rtems_rfs_block_map_grow (rtems_rfs_file_fs (handle),
484                                           map, 1, &block);
485            if (rc > 0)
486              return rc;
487          }
488
489          if (count < (length - bpos.boff))
490          {
491            length = count + bpos.boff;
492            read_block = true;
493            rtems_rfs_block_map_set_size_offset (map, length);
494          }
495          else
496          {
497            rtems_rfs_block_map_set_size_offset (map, 0);
498          }
499
500          /*
501           * Only read the block if the length is not the block size.
502           */
503          rc = rtems_rfs_buffer_handle_request (rtems_rfs_file_fs (handle),
504                                                rtems_rfs_file_buffer (handle),
505                                                block, read_block);
506          if (rc > 0)
507            return rc;
508
509          dst = rtems_rfs_buffer_data (&handle->buffer);
510          memset (dst + bpos.boff, 0, length - bpos.boff);
511
512          rtems_rfs_buffer_mark_dirty (rtems_rfs_file_buffer (handle));
513
514          rc = rtems_rfs_buffer_handle_release (rtems_rfs_file_fs (handle),
515                                                rtems_rfs_file_buffer (handle));
516          if (rc > 0)
517            return rc;
518       
519          count -= length - bpos.boff;
520        }
521      }
522      else
523      {
524        /*
525         * Shrink
526         */
527        rtems_rfs_block_no blocks;
528        uint32_t           offset;
529   
530        blocks =
531          rtems_rfs_block_map_count (map) -
532          (((new_size - 1) /
533            rtems_rfs_fs_block_size (rtems_rfs_file_fs (handle))) + 1);
534
535        offset =
536          new_size % rtems_rfs_fs_block_size (rtems_rfs_file_fs (handle));
537     
538        if (blocks)
539        {
540          int rc;
541          rc = rtems_rfs_block_map_shrink (rtems_rfs_file_fs (handle),
542                                           rtems_rfs_file_map (handle),
543                                           blocks);
544          if (rc > 0)
545            return rc;
546        }
547
548        rtems_rfs_block_map_set_size_offset (map, offset);
549
550        if (rtems_rfs_block_pos_past_end (rtems_rfs_file_bpos (handle),
551                                          rtems_rfs_block_map_size (map)))
552          rtems_rfs_block_size_get_bpos (rtems_rfs_block_map_size (map),
553                                         rtems_rfs_file_bpos (handle));
554      }
555    }
556  }
557
558  handle->shared->size.count  = rtems_rfs_block_map_count (map);
559  handle->shared->size.offset = rtems_rfs_block_map_size_offset (map);
560
561  if (rtems_rfs_file_update_mtime (handle))
562    handle->shared->mtime = time (NULL);
563 
564  return 0;
565}
566
567rtems_rfs_file_shared*
568rtems_rfs_file_get_shared (rtems_rfs_file_system* fs,
569                           rtems_rfs_ino          ino)
570{
571  rtems_chain_node* node;
572  node = rtems_chain_first (&fs->file_shares);
573  while (!rtems_chain_is_tail (&fs->file_shares, node))
574  {
575    rtems_rfs_file_shared* shared;
576    shared = (rtems_rfs_file_shared*) node;
577    if (shared->inode.ino == ino)
578      return shared;
579    node = rtems_chain_next (node);
580  }
581  return NULL;
582}
Note: See TracBrowser for help on using the repository browser.