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

4.115
Last change on this file since ff1becb was ff1becb, checked in by Joel Sherrill <joel.sherrill@…>, on 01/10/13 at 19:22:57

rfs: Doxygen group cannot have a dash in it

Change rtems-rfs to rtems_rfs

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