source: rtems/cpukit/libfs/src/rfs/rtems-rfs-inode.c @ b3c3864

4.10
Last change on this file since b3c3864 was b3c3864, checked in by Chris Johns <chrisj@…>, on 03/03/11 at 06:33:16

2011-03-03 Chris Johns <chrisj@…>

  • libcsupport/src/mknod.c, libfs/src/rfs/rtems-rfs-inode.c: PR
  1. Fix the incorrect handling of the file type in the mode value to reject invalid types as per the standard.
  • Property mode set to 100644
File size: 10.5 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 Inode Routines.
16 *
17 * These functions manage inodes in the RFS file system. An inode is part of a
18 * block that reside after the bitmaps in the group.
19 */
20
21#if HAVE_CONFIG_H
22#include "config.h"
23#endif
24
25#include <inttypes.h>
26
27#include <rtems/rfs/rtems-rfs-block.h>
28#include <rtems/rfs/rtems-rfs-file-system.h>
29#include <rtems/rfs/rtems-rfs-inode.h>
30#include <rtems/rfs/rtems-rfs-dir.h>
31
32int
33rtems_rfs_inode_alloc (rtems_rfs_file_system* fs,
34                       rtems_rfs_bitmap_bit   goal,
35                       rtems_rfs_ino*         ino)
36{
37  rtems_rfs_bitmap_bit bit;
38  int                  rc;
39  rc = rtems_rfs_group_bitmap_alloc (fs, goal, true, &bit);
40  *ino = bit;
41  return rc;
42}
43
44int
45rtems_rfs_inode_free (rtems_rfs_file_system* fs,
46                      rtems_rfs_ino          ino)
47{
48  rtems_rfs_bitmap_bit bit;
49  bit = ino;
50  return rtems_rfs_group_bitmap_free (fs, true, bit);
51}
52
53int
54rtems_rfs_inode_open (rtems_rfs_file_system*  fs,
55                      rtems_rfs_ino           ino,
56                      rtems_rfs_inode_handle* handle,
57                      bool                    load)
58{
59  int group;
60  int gino;
61  int index;
62  int rc;
63 
64  if (rtems_rfs_trace (RTEMS_RFS_TRACE_INODE_OPEN))
65    printf ("rtems-rfs: inode-open: ino: %" PRIu32 "\n", ino);
66
67  if (ino == RTEMS_RFS_EMPTY_INO)
68    return EINVAL;
69 
70  if ((ino - RTEMS_RFS_ROOT_INO) > rtems_rfs_fs_inodes (fs))
71    return EINVAL;
72 
73  handle->ino = ino;
74  handle->node = NULL;
75  handle->loads = 0;
76 
77  gino  = ino - RTEMS_RFS_ROOT_INO;
78  group = gino / fs->group_inodes;
79  gino  = gino % fs->group_inodes;
80  index = (gino / fs->inodes_per_block) + RTEMS_RFS_GROUP_INODE_BLOCK;
81
82  handle->offset = gino % fs->inodes_per_block;
83  handle->block  = rtems_rfs_group_block (&fs->groups[group], index);
84
85  rc = rtems_rfs_buffer_handle_open (fs, &handle->buffer);
86  if ((rc == 0) && load)
87    rc = rtems_rfs_inode_load (fs, handle);
88  return rc;
89}
90
91int
92rtems_rfs_inode_close (rtems_rfs_file_system*  fs,
93                       rtems_rfs_inode_handle* handle)
94{
95  int rc;
96
97  if (rtems_rfs_trace (RTEMS_RFS_TRACE_INODE_CLOSE))
98    printf ("rtems-rfs: inode-close: ino: %" PRIu32 "\n", handle->ino);
99
100  rc = rtems_rfs_inode_unload (fs, handle, true);
101
102  if ((rc == 0) && (handle->loads > 0))
103  {
104    if (rtems_rfs_trace (RTEMS_RFS_TRACE_INODE_CLOSE))
105      printf ("rtems-rfs: inode-close: bad loads number: %d\n",
106              handle->loads);
107    rc = EIO;
108  }
109 
110  handle->ino = 0;
111  return rc;
112}
113
114int
115rtems_rfs_inode_load (rtems_rfs_file_system*  fs,
116                      rtems_rfs_inode_handle* handle)
117{
118  if (rtems_rfs_trace (RTEMS_RFS_TRACE_INODE_LOAD))
119    printf ("rtems-rfs: inode-load: ino=%" PRIu32 " loads=%i loaded=%s\n",
120            handle->ino, handle->loads,
121            rtems_rfs_inode_is_loaded (handle) ? "yes" : "no");
122
123  /*
124   * An inode does not move so once loaded no need to do again.
125   */
126
127  if (!rtems_rfs_inode_is_loaded (handle))
128  {
129    int rc;
130   
131    rc = rtems_rfs_buffer_handle_request (fs,&handle->buffer,
132                                          handle->block, true);
133    if (rc > 0)
134      return rc;
135
136    handle->node = rtems_rfs_buffer_data (&handle->buffer);
137    handle->node += handle->offset;
138  }
139
140  handle->loads++;
141 
142  return 0;
143}
144
145int
146rtems_rfs_inode_unload (rtems_rfs_file_system*  fs,
147                        rtems_rfs_inode_handle* handle,
148                        bool                    update_ctime)
149{
150  int rc = 0;
151 
152  if (rtems_rfs_trace (RTEMS_RFS_TRACE_INODE_UNLOAD))
153    printf ("rtems-rfs: inode-unload: ino=%" PRIu32 " loads=%i loaded=%s\n",
154            handle->ino, handle->loads,
155            rtems_rfs_inode_is_loaded (handle) ? "yes" : "no");
156 
157  if (rtems_rfs_inode_is_loaded (handle))
158  {
159    if (handle->loads == 0)
160      return EIO;
161
162    handle->loads--;
163   
164    if (handle->loads == 0)
165    {
166      /*
167       * If the buffer is dirty it will be release. Also set the ctime.
168       */
169      if (rtems_rfs_buffer_dirty (&handle->buffer) && update_ctime)
170        rtems_rfs_inode_set_ctime (handle, time (NULL));
171      rc = rtems_rfs_buffer_handle_release (fs, &handle->buffer);
172      handle->node = NULL;
173    }
174  }
175 
176  return rc;
177}
178
179int
180rtems_rfs_inode_create (rtems_rfs_file_system*  fs,
181                        rtems_rfs_ino           parent,
182                        const char*             name,
183                        size_t                  length,
184                        uint16_t                mode,
185                        uint16_t                links,
186                        uid_t                   uid,
187                        gid_t                   gid,
188                        rtems_rfs_ino*          ino)
189{
190  rtems_rfs_inode_handle parent_inode;
191  rtems_rfs_inode_handle inode;
192  int                    rc;
193 
194  if (rtems_rfs_trace (RTEMS_RFS_TRACE_INODE_CREATE))
195  {
196    const char* type = "unknown";
197    int         c;
198    if (RTEMS_RFS_S_ISDIR (mode))
199      type = "dir";
200    else if (RTEMS_RFS_S_ISCHR (mode))
201      type = "char";
202    else if (RTEMS_RFS_S_ISBLK (mode))
203      type = "block";
204    else if (RTEMS_RFS_S_ISREG (mode))
205      type = "file";
206    else if (RTEMS_RFS_S_ISLNK (mode))
207      type = "link";
208    printf("rtems-rfs: inode-create: parent:%" PRIu32 " name:", parent);
209    for (c = 0; c < length; c++)
210      printf ("%c", name[c]);
211    printf (" type:%s mode:%04x (%03o)\n", type, mode, mode & ((1 << 10) - 1));
212  }
213
214  /*
215   * The file type is field within the mode. Check we have a sane mode set.
216   */
217  switch (mode & RTEMS_RFS_S_IFMT)
218  {
219    case RTEMS_RFS_S_IFDIR:
220    case RTEMS_RFS_S_IFCHR:
221    case RTEMS_RFS_S_IFBLK:
222    case RTEMS_RFS_S_IFREG:
223    case RTEMS_RFS_S_IFLNK:
224      break;
225    default:
226      return EINVAL;
227  }
228 
229  rc = rtems_rfs_inode_alloc (fs, parent, ino);
230  if (rc > 0)
231    return rc;
232
233  rc = rtems_rfs_inode_open (fs, *ino, &inode, true);
234  if (rc > 0)
235  {
236    rtems_rfs_inode_free (fs, *ino);
237    return rc;
238  }
239 
240  rc = rtems_rfs_inode_initialise (&inode, links, mode, uid, gid);
241  if (rc > 0)
242  {
243    rtems_rfs_inode_close (fs, &inode);
244    rtems_rfs_inode_free (fs, *ino);
245    return rc;
246  }
247
248  /*
249   * Only handle the specifics of a directory. Let caller handle the others.
250   *
251   * The inode delete will free the inode.
252   */
253  if (RTEMS_RFS_S_ISDIR (mode))
254  {
255    rc = rtems_rfs_dir_add_entry (fs, &inode, ".", 1, *ino);
256    if (rc == 0)
257      rc = rtems_rfs_dir_add_entry (fs, &inode, "..", 2, parent);
258    if (rc > 0)
259    {
260      rtems_rfs_inode_delete (fs, &inode);
261      rtems_rfs_inode_close (fs, &inode);
262      return rc;
263    }
264  }
265
266  rc = rtems_rfs_inode_open (fs, parent, &parent_inode, true);
267  if (rc > 0)
268  {
269    rtems_rfs_inode_delete (fs, &inode);
270    rtems_rfs_inode_close (fs, &inode);
271    return rc;
272  }
273
274  rc = rtems_rfs_dir_add_entry (fs, &parent_inode, name, length, *ino);
275  if (rc > 0)
276  {
277    rtems_rfs_inode_delete (fs, &inode);
278    rtems_rfs_inode_close (fs, &inode);
279    rtems_rfs_inode_close (fs, &parent_inode);
280    return rc;
281  }
282
283  /*
284   * If the node is a directory update the parent link count as the
285   * new directory has the '..' link that points to the parent.
286   */
287  if (RTEMS_RFS_S_ISDIR (mode))
288    rtems_rfs_inode_set_links (&parent_inode,
289                               rtems_rfs_inode_get_links (&parent_inode) + 1);
290 
291  rc = rtems_rfs_inode_close (fs, &parent_inode);
292  if (rc > 0)
293  {
294    rtems_rfs_inode_delete (fs, &inode);
295    rtems_rfs_inode_close (fs, &inode);
296    return rc;
297  }
298
299  rc = rtems_rfs_inode_close (fs, &inode);
300  if (rc > 0)
301  {
302    rtems_rfs_inode_free (fs, *ino);
303    return rc;
304  }
305 
306  return 0;
307}
308
309int
310rtems_rfs_inode_delete (rtems_rfs_file_system*  fs,
311                        rtems_rfs_inode_handle* handle)
312{
313  int rc = 0;
314 
315  if (rtems_rfs_trace (RTEMS_RFS_TRACE_INODE_DELETE))
316    printf("rtems-rfs: inode-delete: ino:%" PRIu32 " loaded:%s\n",
317           rtems_rfs_inode_ino (handle),
318           rtems_rfs_inode_is_loaded (handle) ? "yes" : "no");
319
320  if (rtems_rfs_inode_is_loaded (handle))
321  {
322    rtems_rfs_block_map map;
323
324    /*
325     * Free the ino number.
326     */
327    rc = rtems_rfs_inode_free (fs, handle->ino);
328    if (rc > 0)
329      return rc;
330   
331    /*
332     * Free the blocks the inode may have attached.
333     */
334    rc = rtems_rfs_block_map_open (fs, handle, &map);
335    if (rc == 0)
336    {
337      int rrc;
338      rrc = rtems_rfs_block_map_free_all (fs, &map);
339      rc = rtems_rfs_block_map_close (fs, &map);
340      if (rc > 0)
341        rrc = rc;
342      memset (handle->node, 0xff, RTEMS_RFS_INODE_SIZE);
343      rtems_rfs_buffer_mark_dirty (&handle->buffer);
344      /*
345       * Do the release here to avoid the ctime field being set on a
346       * close. Also if there loads is greater then one then other loads
347       * active. Forcing the loads count to 0.
348       */
349      rc = rtems_rfs_buffer_handle_release (fs, &handle->buffer);
350      handle->loads = 0;
351      handle->node = NULL;
352    }
353  }
354  return rc;
355}
356
357int
358rtems_rfs_inode_initialise (rtems_rfs_inode_handle* handle,
359                            uint16_t                links,
360                            uint16_t                mode,
361                            uid_t                   uid,
362                            gid_t                   gid)
363{
364  int b;
365  rtems_rfs_inode_set_links (handle, links);
366  rtems_rfs_inode_set_flags (handle, 0);
367  rtems_rfs_inode_set_mode (handle,  mode);
368  rtems_rfs_inode_set_uid_gid (handle, uid, gid);
369  rtems_rfs_inode_set_block_offset (handle, 0);
370  rtems_rfs_inode_set_block_count (handle, 0);
371  for (b = 0; b < RTEMS_RFS_INODE_BLOCKS; b++)
372    rtems_rfs_inode_set_block (handle, b, 0);
373  rtems_rfs_inode_set_last_map_block (handle, 0);
374  rtems_rfs_inode_set_last_data_block (handle, 0);
375  return rtems_rfs_inode_time_stamp_now (handle, true, true);
376}
377
378int
379rtems_rfs_inode_time_stamp_now (rtems_rfs_inode_handle* handle,
380                                bool                    atime,
381                                bool                    mtime)
382{
383  time_t now;
384  if (!rtems_rfs_inode_is_loaded (handle))
385    return ENXIO;
386  now = time (NULL);
387  if (atime)
388    rtems_rfs_inode_set_atime (handle, now);
389  if (mtime)
390    rtems_rfs_inode_set_mtime (handle, now);
391  return 0;
392}
393
394rtems_rfs_pos
395rtems_rfs_inode_get_size (rtems_rfs_file_system*  fs,
396                          rtems_rfs_inode_handle* handle)
397{
398  rtems_rfs_block_size size;
399  size.count = rtems_rfs_inode_get_block_count (handle);
400  size.offset = rtems_rfs_inode_get_block_offset (handle);
401  return rtems_rfs_block_get_size (fs, &size);
402}
Note: See TracBrowser for help on using the repository browser.