source: rtems/cpukit/libfs/src/rfs/rtems-rfs-rtems.c @ 66b8047

4.115
Last change on this file since 66b8047 was 66b8047, checked in by Ralf Corsepius <ralf.corsepius@…>, on 11/06/11 at 12:44:24

Remove stray whitespaces.

  • Property mode set to 100644
File size: 37.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 *  $Id$
9 */
10/**
11 * @file
12 *
13 * @ingroup rtems-rfs
14 *
15 * RTEMS File System Interface for RTEMS.
16 */
17
18#if HAVE_CONFIG_H
19#include "config.h"
20#endif
21
22#include <inttypes.h>
23#include <stdlib.h>
24
25#if SIZEOF_MODE_T == 8
26#define PRIomode_t PRIo64
27#elif SIZEOF_MODE_T == 4
28#define PRIomode_t PRIo32
29#else
30#error "unsupport size of mode_t"
31#endif
32
33#include <rtems/rfs/rtems-rfs-file.h>
34#include <rtems/rfs/rtems-rfs-dir.h>
35#include <rtems/rfs/rtems-rfs-link.h>
36#include "rtems-rfs-rtems.h"
37
38/**
39 * The libio permissions for read/execute.
40 */
41#define RTEMS_LIBIO_PERMS_RX (RTEMS_LIBIO_PERMS_SEARCH | RTEMS_LIBIO_PERMS_READ)
42/**
43 * The libio permissions for write/execute.
44 */
45#define RTEMS_LIBIO_PERMS_WX (RTEMS_LIBIO_PERMS_SEARCH | RTEMS_LIBIO_PERMS_WRITE)
46
47/**
48 * Evaluate the path to a node that wishes to be accessed. The pathloc is
49 * returned with the ino to the node to be accessed.
50 *
51 * The routine starts from the root stripping away any leading path separators
52 * breaking the path up into the node names and checking an inode exists for
53 * that node name. Permissions are checked to insure access to the node is
54 * allowed. A path to a node must be accessable all the way even if the end
55 * result is directly accessable. As a user on Linux try "ls /root/../tmp" and
56 * you will see if fails.
57 *
58 * The whole process is complicated by crossmount paths where we head down into
59 * this file system only to return to the top and out to a another mounted file
60 * system. For example we are mounted on '/e' and the user enters "ls
61 * /e/a/b/../../dev". We need to head down then back up.
62 *
63 * @param path
64 * @param pathlen
65 * @param flags
66 * @param pathloc
67 */
68static int
69rtems_rfs_rtems_eval_path (const char*                       path,
70                           size_t                            pathlen,
71                           int                               flags,
72                           rtems_filesystem_location_info_t* pathloc)
73{
74  rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc);
75  rtems_rfs_inode_handle inode;
76  rtems_rfs_ino          ino = rtems_rfs_rtems_get_pathloc_ino (pathloc);
77  uint32_t               doff = 0;
78  const char*            node;
79  size_t                 node_len;
80  int                    stripped;
81  int                    rc;
82
83  if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_EVAL_PATH))
84    printf ("rtems-rfs-rtems: eval-path: in: path:%s pathlen:%zi ino:%" PRId32 "\n",
85            path, pathlen, ino);
86
87  /*
88   * Eat any separators at the start of the path.
89   */
90  stripped = rtems_filesystem_prefix_separators (path, pathlen);
91  path += stripped;
92  pathlen -= stripped;
93
94  rtems_rfs_rtems_lock (fs);
95
96  while (true)
97  {
98    /*
99     * Open and load the inode.
100     */
101    rc = rtems_rfs_inode_open (fs, ino, &inode, true);
102    if (rc > 0)
103    {
104      rtems_rfs_rtems_unlock (fs);
105      return rtems_rfs_rtems_error ("eval_path: opening inode", rc);
106    }
107
108    /*
109     * Is this the end of the pathname we were given ?
110     */
111    if ((*path == '\0') || (pathlen == 0))
112      break;
113
114    /*
115     * If a directory the execute bit must be set for us to enter.
116     */
117    if (RTEMS_RFS_S_ISDIR (rtems_rfs_inode_get_mode (&inode)) &&
118        !rtems_rfs_rtems_eval_perms (&inode, RTEMS_LIBIO_PERMS_SEARCH))
119    {
120      rtems_rfs_inode_close (fs, &inode);
121      rtems_rfs_rtems_unlock (fs);
122      return rtems_rfs_rtems_error ("eval_path: eval perms", EACCES);
123    }
124
125    /*
126     * Extract the node name we will look for this time around.
127     */
128    node = path;
129    node_len = 0;
130    while (!rtems_filesystem_is_separator (*path) &&
131           (*path != '\0') && pathlen &&
132           ((node_len + 1) < rtems_rfs_fs_max_name (fs)))
133    {
134      path++;
135      pathlen--;
136      node_len++;
137    }
138
139    /*
140     * Eat any separators at the start of the path.
141     */
142    stripped = rtems_filesystem_prefix_separators (path, pathlen);
143    path += stripped;
144    pathlen -= stripped;
145    node_len += stripped;
146
147    /*
148     * If the node is the current directory and there is more path to come move
149     * on to it otherwise we are at the inode we want.
150     */
151    if (rtems_rfs_current_dir (node))
152    {
153      if (*path)
154      {
155        rtems_rfs_inode_close (fs, &inode);
156        continue;
157      }
158      break;
159    }
160
161    /*
162     * If the node is a parent we must move up one directory. If the location
163     * is on another file system we have a crossmount so we call that file
164     * system to handle the remainder of the path.
165     */
166    if (rtems_rfs_parent_dir (node))
167    {
168      /*
169       * If we are at the root inode of the file system we have a crossmount
170       * path.
171       */
172      if (ino == RTEMS_RFS_ROOT_INO)
173      {
174        if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_EVAL_PATH))
175          printf("rtems-rfs-rtems: eval-path: crossmount: path:%s (%zd)\n",
176                 path - node_len, pathlen + node_len);
177        rtems_rfs_inode_close (fs, &inode);
178        rtems_rfs_rtems_unlock (fs);
179        *pathloc = pathloc->mt_entry->mt_point_node;
180        return (*pathloc->ops->evalpath_h)(path - node_len, pathlen + node_len,
181                                           flags, pathloc);
182      }
183
184      /*
185       * We need to find the parent of this node.
186       */
187      rc = rtems_rfs_dir_lookup_ino (fs, &inode,
188                                     RTEMS_RFS_PARENT_DIR_STR,
189                                     RTEMS_RFS_PARENT_DIR_SIZE, &ino, &doff);
190      if (rc > 0)
191      {
192        rtems_rfs_inode_close (fs, &inode);
193        rtems_rfs_rtems_unlock (fs);
194        return rtems_rfs_rtems_error ("eval_path: read parent inode", rc);
195      }
196      if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_EVAL_PATH))
197        printf("rtems-rfs-rtems: eval-path: parent: ino:%" PRId32 "\n", ino);
198    }
199    else
200    {
201      /*
202       * Look up the node name in this directory. If found drop through, close
203       * the current inode and let the loop open the inode so the mode can be
204       * read and handlers set.
205       */
206      rc = rtems_rfs_dir_lookup_ino (fs, &inode,
207                                     node, node_len - stripped, &ino, &doff);
208      if (rc > 0)
209      {
210        rtems_rfs_inode_close (fs, &inode);
211        rtems_rfs_rtems_unlock (fs);
212        return ((errno = rc) == 0) ? 0 : -1;
213      }
214      if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_EVAL_PATH))
215        printf("rtems-rfs-rtems: eval-path: down: path:%s ino:%" PRId32 "\n", node, ino);
216    }
217
218    rc = rtems_rfs_inode_close (fs, &inode);
219    if (rc > 0)
220    {
221      rtems_rfs_inode_close (fs, &inode);
222      rtems_rfs_rtems_unlock (fs);
223      return rtems_rfs_rtems_error ("eval_path: closing node", rc);
224    }
225  }
226
227  rtems_rfs_rtems_set_pathloc_ino (pathloc, ino);
228  rtems_rfs_rtems_set_pathloc_doff (pathloc, doff);
229
230  rc = rtems_rfs_rtems_set_handlers (pathloc, &inode) ? 0 : EIO;
231
232  rtems_rfs_inode_close (fs, &inode);
233  rtems_rfs_rtems_unlock (fs);
234
235  if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_EVAL_PATH))
236    printf("rtems-rfs-rtems: eval-path: ino:%" PRId32 "\n", ino);
237
238  return rc;
239}
240
241/**
242 * The following routine evaluates a path for a new node to be created. The
243 * pathloc is returned with a pointer to the parent of the new node. The name
244 * is returned with a pointer to the first character in the new node name. The
245 * parent node is verified to be a directory.
246 *
247 * @param path
248 * @param pathloc
249 * @param name
250 * @return int
251 */
252static int
253rtems_rfs_rtems_eval_for_make (const char*                       path,
254                               rtems_filesystem_location_info_t* pathloc,
255                               const char**                      name)
256{
257  rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc);
258  rtems_rfs_inode_handle inode;
259  rtems_rfs_ino          ino = rtems_rfs_rtems_get_pathloc_ino (pathloc);
260  rtems_rfs_ino          node_ino;
261  uint32_t               doff = 0;
262  const char*            node;
263  int                    node_len;
264  int                    stripped;
265  int                    rc;
266
267  if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_EVAL_FOR_MAKE))
268    printf ("rtems-rfs-rtems: eval-for-make: path:%s ino:%" PRId32 "\n", path, ino);
269
270  *name = path + strlen (path);
271
272  while (*name != path)
273  {
274    (*name)--;
275    if (rtems_filesystem_is_separator (**name))
276    {
277      (*name)++;
278      break;
279    }
280  }
281
282  /*
283   * Eat any separators at start of the path.
284   */
285  stripped = rtems_filesystem_prefix_separators (path, strlen(path));
286  path += stripped;
287
288  rtems_rfs_rtems_lock (fs);
289
290  while (true)
291  {
292    /*
293     * Open and load the inode.
294     */
295    rc = rtems_rfs_inode_open (fs, ino, &inode, true);
296    if (rc > 0)
297    {
298      rtems_rfs_rtems_unlock (fs);
299      return rtems_rfs_rtems_error ("eval_for_make: read ino", rc);
300    }
301
302    /*
303     * If a directory the execute bit must be set for us to enter.
304     */
305    if (RTEMS_RFS_S_ISDIR (rtems_rfs_inode_get_mode (&inode)) &&
306        !rtems_rfs_rtems_eval_perms (&inode, RTEMS_LIBIO_PERMS_SEARCH))
307    {
308      rtems_rfs_inode_close (fs, &inode);
309      rtems_rfs_rtems_unlock (fs);
310      return rtems_rfs_rtems_error ("eval_for_make: eval perms", EACCES);
311    }
312
313    /*
314     * Is this the end of the pathname we were given ?
315     */
316    if (path == *name)
317      break;
318
319    /*
320     * Extract the node name we will look for this time around.
321     */
322    node = path;
323    node_len = 0;
324    while (!rtems_filesystem_is_separator(*path) &&
325           (*path != '\0') &&
326           (node_len < (rtems_rfs_fs_max_name (fs) - 1)))
327    {
328      node_len++;
329      path++;
330    }
331
332    /*
333     * Eat any separators at start of the new path.
334     */
335    stripped = rtems_filesystem_prefix_separators (path, strlen (path));
336    path += stripped;
337    node_len += stripped;
338
339    /*
340     * If the node is the current directory and there is more path to come move
341     * on to it otherwise we are at the inode we want.
342     */
343    if (rtems_rfs_current_dir (node))
344    {
345      if (*path)
346      {
347        rtems_rfs_inode_close (fs, &inode);
348        continue;
349      }
350      break;
351    }
352
353    /*
354     * If the node is a parent we must move up one directory. If the location
355     * is on another file system we have a crossmount so we call that file
356     * system to handle the remainder of the path.
357     */
358    if (rtems_rfs_parent_dir (path))
359    {
360      /*
361       * If we are at the root inode of the file system we have a crossmount
362       * path.
363       */
364      if (ino == RTEMS_RFS_ROOT_INO)
365      {
366        if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_EVAL_FOR_MAKE))
367          printf("rtems-rfs-rtems: eval-for-make: crossmount: path:%s\n",
368                 path - node_len);
369
370        rtems_rfs_inode_close (fs, &inode);
371        rtems_rfs_rtems_unlock (fs);
372        *pathloc = pathloc->mt_entry->mt_point_node;
373        return (*pathloc->ops->evalformake_h)(path + 2, pathloc, name);
374      }
375
376      /*
377       * If not a directory give and up return. We cannot change dir from a
378       * regular file or device node.
379       */
380      if (!RTEMS_RFS_S_ISDIR (rtems_rfs_inode_get_mode (&inode)))
381      {
382        rtems_rfs_inode_close (fs, &inode);
383        rtems_rfs_rtems_unlock (fs);
384        return rtems_rfs_rtems_error ("eval_for_make: not dir", ENOTSUP);
385      }
386
387      /*
388       * We need to find the parent of this node.
389       */
390      rc = rtems_rfs_dir_lookup_ino (fs, &inode,
391                                     RTEMS_RFS_PARENT_DIR_STR,
392                                     RTEMS_RFS_PARENT_DIR_SIZE, &ino, &doff);
393      if (rc > 0)
394      {
395        rtems_rfs_inode_close (fs, &inode);
396        rtems_rfs_rtems_unlock (fs);
397        return rtems_rfs_rtems_error ("eval_for_make: read parent inode", rc);
398      }
399      if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_EVAL_FOR_MAKE))
400        printf ("rtems-rfs-rtems: eval-for-make: parent: ino:%" PRId32 "\n", ino);
401    }
402    else
403    {
404      /*
405       * Read the inode so we know it exists and what type it is.
406       */
407      rc = rtems_rfs_dir_lookup_ino (fs, &inode,
408                                     node, node_len - stripped, &ino, &doff);
409      if (rc > 0)
410      {
411        rtems_rfs_inode_close (fs, &inode);
412        rtems_rfs_rtems_unlock (fs);
413        return rtems_rfs_rtems_error ("eval_for_make: reading inode", rc);
414      }
415      if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_EVAL_FOR_MAKE))
416        printf("rtems-rfs-rtems: eval-for-make: down: path:%s ino:%" PRId32 "\n",
417               node, ino);
418    }
419
420    rc = rtems_rfs_inode_close (fs, &inode);
421    if (rc > 0)
422    {
423      rtems_rfs_rtems_unlock (fs);
424      return rtems_rfs_rtems_error ("eval_for_make: closing node", rc);
425    }
426  }
427
428  if (!RTEMS_RFS_S_ISDIR (rtems_rfs_inode_get_mode (&inode)))
429  {
430    rtems_rfs_inode_close (fs, &inode);
431    rtems_rfs_rtems_unlock (fs);
432    return rtems_rfs_rtems_error ("eval_for_make: not dir", ENOTDIR);
433  }
434
435  if (!rtems_rfs_rtems_eval_perms (&inode, RTEMS_LIBIO_PERMS_WX))
436  {
437    rtems_rfs_inode_close (fs, &inode);
438    rtems_rfs_rtems_unlock (fs);
439    return rtems_rfs_rtems_error ("eval_for_make: cannot write", EACCES);
440  }
441
442  /*
443   * Make sure the name does not already exists in the directory.
444   */
445  rc = rtems_rfs_dir_lookup_ino (fs, &inode, *name, strlen (*name),
446                                 &node_ino, &doff);
447  if (rc == 0)
448  {
449    rtems_rfs_inode_close (fs, &inode);
450    rtems_rfs_rtems_unlock (fs);
451    return rtems_rfs_rtems_error ("eval_for_make: found name", EEXIST);
452  }
453
454  if (rc != ENOENT)
455  {
456    rtems_rfs_inode_close (fs, &inode);
457    rtems_rfs_rtems_unlock (fs);
458    return rtems_rfs_rtems_error ("eval_for_make: look up", rc);
459  }
460
461  /*
462   * Set the parent ino in the path location.
463   */
464
465  rtems_rfs_rtems_set_pathloc_ino (pathloc, ino);
466  rtems_rfs_rtems_set_pathloc_doff (pathloc, doff);
467
468  rc = rtems_rfs_rtems_set_handlers (pathloc, &inode) ? 0 : EIO;
469
470  if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_EVAL_FOR_MAKE))
471    printf("rtems-rfs-rtems: eval-for-make: parent ino:%" PRId32 " name:%s\n",
472           ino, *name);
473
474  rtems_rfs_inode_close (fs, &inode);
475  rtems_rfs_rtems_unlock (fs);
476
477  return rc;
478}
479
480/**
481 * The following rouine creates a new link node under parent with the name
482 * given in name. The link node is set to point to the node at to_loc.
483 *
484 * @param to_loc
485 * @param parent_loc
486 * @param name
487 * @return int
488 */
489static int
490rtems_rfs_rtems_link (rtems_filesystem_location_info_t* to_loc,
491                      rtems_filesystem_location_info_t* parent_loc,
492                      const char*                       name)
493{
494  rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (to_loc);
495  rtems_rfs_ino          target = rtems_rfs_rtems_get_pathloc_ino (to_loc);
496  rtems_rfs_ino          parent = rtems_rfs_rtems_get_pathloc_ino (parent_loc);
497  int                    rc;
498
499  if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_LINK))
500    printf ("rtems-rfs-rtems: link: in: parent:%" PRId32 " target:%" PRId32 "\n",
501            parent, target);
502
503  rtems_rfs_rtems_lock (fs);
504
505  rc = rtems_rfs_link (fs, name, strlen (name), parent, target, false);
506  if (rc)
507  {
508    rtems_rfs_rtems_unlock (fs);
509    return rtems_rfs_rtems_error ("link: linking", rc);
510        }
511
512  rtems_rfs_rtems_unlock (fs);
513
514        return 0;
515}
516
517/**
518 * Routine to remove a link node from the file system.
519 *
520 * @param parent_loc
521 * @param loc
522 * @return int
523 */
524
525static int
526rtems_rfs_rtems_unlink (rtems_filesystem_location_info_t* parent_loc,
527                        rtems_filesystem_location_info_t* loc)
528{
529  rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (parent_loc);
530  rtems_rfs_ino          parent = rtems_rfs_rtems_get_pathloc_ino (parent_loc);
531  rtems_rfs_ino          ino = rtems_rfs_rtems_get_pathloc_ino (loc);
532  uint32_t               doff = rtems_rfs_rtems_get_pathloc_doff (loc);
533  int                    rc;
534
535  rtems_rfs_rtems_lock (fs);
536
537  if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_UNLINK))
538    printf("rtems-rfs-rtems: unlink: parent:%" PRId32 " doff:%" PRIu32 " ino:%" PRId32 "\n",
539           parent, doff, ino);
540
541  rc = rtems_rfs_unlink (fs, parent, ino, doff, rtems_rfs_unlink_dir_denied);
542  if (rc)
543  {
544    rtems_rfs_rtems_unlock (fs);
545    return rtems_rfs_rtems_error ("unlink: unlink inode", rc);
546  }
547
548  rtems_rfs_rtems_unlock (fs);
549
550  return 0;
551}
552
553/**
554 * The following verifies that and returns the type of node that the loc refers
555 * to.
556 *
557 * @param pathloc
558 * @return rtems_filesystem_node_types_t
559 */
560
561static rtems_filesystem_node_types_t
562rtems_rfs_rtems_node_type (rtems_filesystem_location_info_t* pathloc)
563{
564  rtems_rfs_file_system*        fs = rtems_rfs_rtems_pathloc_dev (pathloc);
565  rtems_rfs_ino                 ino = rtems_rfs_rtems_get_pathloc_ino (pathloc);
566  rtems_filesystem_node_types_t type;
567  rtems_rfs_inode_handle        inode;
568  uint16_t                      mode;
569  int                           rc;
570
571  rtems_rfs_rtems_lock (fs);
572
573  rc = rtems_rfs_inode_open (fs, ino, &inode, true);
574  if (rc > 0)
575  {
576    rtems_rfs_rtems_unlock (fs);
577    return rtems_rfs_rtems_error ("node_type: opening inode", rc);
578  }
579
580  /*
581   * Do not return RTEMS_FILESYSTEM_HARD_LINK because this would result in an
582   * eval link which does not make sense in the case of the RFS file
583   * system. All directory entries are links to an inode. A link such as a HARD
584   * link is actually the normal path to a regular file, directory, device
585   * etc's inode. Links to inodes can be considered "the real" one, yet they
586   * are all links.
587   */
588  mode = rtems_rfs_inode_get_mode (&inode);
589  if (RTEMS_RFS_S_ISDIR (mode))
590    type = RTEMS_FILESYSTEM_DIRECTORY;
591  else if (RTEMS_RFS_S_ISLNK (mode))
592    type = RTEMS_FILESYSTEM_SYM_LINK;
593  else if (RTEMS_RFS_S_ISBLK (mode) || RTEMS_RFS_S_ISCHR (mode))
594    type = RTEMS_FILESYSTEM_DEVICE;
595  else
596    type = RTEMS_FILESYSTEM_MEMORY_FILE;
597
598  rc = rtems_rfs_inode_close (fs, &inode);
599  if (rc > 0)
600  {
601    rtems_rfs_rtems_unlock (fs);
602    return rtems_rfs_rtems_error ("node_type: closing inode", rc);
603  }
604
605  rtems_rfs_rtems_unlock (fs);
606
607  return type;
608}
609
610/**
611 * This routine is the implementation of the chown() system call for the
612 * RFS.
613 *
614 * @param pathloc
615 * @param owner
616 * @param group
617 * return int
618 */
619
620static int
621rtems_rfs_rtems_chown (rtems_filesystem_location_info_t *pathloc,
622                       uid_t                             owner,
623                       gid_t                             group)
624{
625  rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc);
626  rtems_rfs_ino          ino = rtems_rfs_rtems_get_pathloc_ino (pathloc);
627  rtems_rfs_inode_handle inode;
628#if defined (RTEMS_POSIX_API)
629  uid_t                  uid;
630#endif
631  int                    rc;
632
633  if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_CHOWN))
634    printf ("rtems-rfs-rtems: chown: in: ino:%" PRId32 " uid:%d gid:%d\n",
635            ino, owner, group);
636
637  rtems_rfs_rtems_lock (fs);
638
639  rc = rtems_rfs_inode_open (fs, ino, &inode, true);
640  if (rc > 0)
641  {
642    rtems_rfs_rtems_unlock (fs);
643    return rtems_rfs_rtems_error ("chown: opening inode", rc);
644  }
645
646  /*
647   *  Verify I am the owner of the node or the super user.
648   */
649
650#if defined (RTEMS_POSIX_API)
651  uid = geteuid();
652
653  if ((uid != rtems_rfs_inode_get_uid (&inode)) && (uid != 0))
654  {
655    rtems_rfs_inode_close (fs, &inode);
656    rtems_rfs_rtems_unlock (fs);
657    return rtems_rfs_rtems_error ("chown: not able", EPERM);
658  }
659#endif
660
661  rtems_rfs_inode_set_uid_gid (&inode, owner, group);
662
663  rc = rtems_rfs_inode_close (fs, &inode);
664  if (rc)
665  {
666    rtems_rfs_rtems_unlock (fs);
667    return rtems_rfs_rtems_error ("chown: closing inode", rc);
668  }
669
670  rtems_rfs_rtems_unlock (fs);
671
672  return 0;
673}
674
675/**
676 * This routine is the implementation of the utime() system call for the
677 * RFS.
678 *
679 * @param pathloc
680 * @param atime
681 * @param mtime
682 * return int
683 */
684
685static int
686rtems_rfs_rtems_utime(rtems_filesystem_location_info_t* pathloc,
687                      time_t                            atime,
688                      time_t                            mtime)
689{
690  rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc);
691  rtems_rfs_ino          ino = rtems_rfs_rtems_get_pathloc_ino (pathloc);
692  rtems_rfs_inode_handle inode;
693  int                    rc;
694
695  rtems_rfs_rtems_lock (fs);
696
697  rc = rtems_rfs_inode_open (fs, ino, &inode, true);
698  if (rc)
699  {
700    rtems_rfs_rtems_unlock (fs);
701    return rtems_rfs_rtems_error ("utime: read inode", rc);
702  }
703
704  rtems_rfs_inode_set_atime (&inode, atime);
705  rtems_rfs_inode_set_mtime (&inode, mtime);
706
707  rc = rtems_rfs_inode_close (fs, &inode);
708  if (rc)
709  {
710    rtems_rfs_rtems_unlock (fs);
711    return rtems_rfs_rtems_error ("utime: closing inode", rc);
712  }
713
714  rtems_rfs_rtems_unlock (fs);
715
716  return 0;
717}
718
719/**
720 * The following rouine creates a new symbolic link node under parent with the
721 * name given in name. The node is set to point to the node at to_loc.
722 *
723 * @param parent_loc
724 * @param link_name
725 * @param node_name
726 * return int
727 */
728
729static int
730rtems_rfs_rtems_symlink (rtems_filesystem_location_info_t* parent_loc,
731                         const char*                       link_name,
732                         const char*                       node_name)
733{
734  rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (parent_loc);
735  rtems_rfs_ino          parent = rtems_rfs_rtems_get_pathloc_ino (parent_loc);
736  uid_t                  uid;
737  gid_t                  gid;
738  int                    rc;
739
740#if defined(RTEMS_POSIX_API)
741  uid = geteuid ();
742  gid = getegid ();
743#else
744  uid = 0;
745  gid = 0;
746#endif
747
748  rtems_rfs_rtems_lock (fs);
749
750  rc = rtems_rfs_symlink (fs, node_name, strlen (node_name),
751                          link_name, strlen (link_name),
752                          uid, gid, parent);
753  if (rc)
754  {
755    rtems_rfs_rtems_unlock (fs);
756    return rtems_rfs_rtems_error ("symlink: linking", rc);
757  }
758
759  rtems_rfs_rtems_unlock (fs);
760
761  return 0;
762}
763
764/**
765 * The following rouine puts the symblic links destination name into buf.
766 *
767 * @param loc
768 * @param buf
769 * @param bufsize
770 * @return int
771 */
772
773static ssize_t
774rtems_rfs_rtems_readlink (rtems_filesystem_location_info_t* pathloc,
775                          char*                             buf,
776                          size_t                            bufsize)
777{
778  rtems_rfs_file_system*  fs = rtems_rfs_rtems_pathloc_dev (pathloc);
779  rtems_rfs_ino           ino = rtems_rfs_rtems_get_pathloc_ino (pathloc);
780  size_t                  length;
781  int                     rc;
782
783  if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_READLINK))
784    printf ("rtems-rfs-rtems: readlink: in: ino:%" PRId32 "\n", ino);
785
786  rtems_rfs_rtems_lock (fs);
787
788  rc = rtems_rfs_symlink_read (fs, ino, buf, bufsize, &length);
789  if (rc)
790  {
791    rtems_rfs_rtems_unlock (fs);
792    return rtems_rfs_rtems_error ("readlink: reading link", rc);
793  }
794
795  rtems_rfs_rtems_unlock (fs);
796
797  return (int) length;
798}
799
800int
801rtems_rfs_rtems_fchmod (rtems_filesystem_location_info_t* pathloc,
802                        mode_t                            mode)
803{
804  rtems_rfs_file_system*  fs = rtems_rfs_rtems_pathloc_dev (pathloc);
805  rtems_rfs_ino           ino = rtems_rfs_rtems_get_pathloc_ino (pathloc);
806  rtems_rfs_inode_handle  inode;
807  uint16_t                imode;
808#if defined (RTEMS_POSIX_API)
809  uid_t                   uid;
810#endif
811  int                     rc;
812
813  if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_FCHMOD))
814    printf ("rtems-rfs-rtems: fchmod: in: ino:%" PRId32 " mode:%06" PRIomode_t "\n",
815            ino, mode);
816
817  rtems_rfs_rtems_lock (fs);
818
819  rc = rtems_rfs_inode_open (fs, ino, &inode, true);
820  if (rc)
821  {
822    rtems_rfs_rtems_unlock (fs);
823    return rtems_rfs_rtems_error ("fchmod: opening inode", rc);
824  }
825
826  imode = rtems_rfs_inode_get_mode (&inode);
827
828  /*
829   *  Verify I am the owner of the node or the super user.
830   */
831#if defined (RTEMS_POSIX_API)
832  uid = geteuid();
833
834  if ((uid != rtems_rfs_inode_get_uid (&inode)) && (uid != 0))
835  {
836    rtems_rfs_inode_close (fs, &inode);
837    rtems_rfs_rtems_unlock (fs);
838    return rtems_rfs_rtems_error ("fchmod: checking uid", EPERM);
839  }
840#endif
841
842  imode &= ~(S_IRWXU | S_IRWXG | S_IRWXO | S_ISUID | S_ISGID | S_ISVTX);
843  imode |= mode & (S_IRWXU | S_IRWXG | S_IRWXO | S_ISUID | S_ISGID | S_ISVTX);
844
845  rtems_rfs_inode_set_mode (&inode, imode);
846
847  rc = rtems_rfs_inode_close (fs, &inode);
848  if (rc > 0)
849  {
850    rtems_rfs_rtems_unlock (fs);
851    return rtems_rfs_rtems_error ("fchmod: closing inode", rc);
852  }
853
854  rtems_rfs_rtems_unlock (fs);
855
856  return 0;
857}
858
859int
860rtems_rfs_rtems_fstat (rtems_filesystem_location_info_t* pathloc,
861                       struct stat*                      buf)
862{
863  rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc);
864  rtems_rfs_ino          ino = rtems_rfs_rtems_get_pathloc_ino (pathloc);
865  rtems_rfs_inode_handle inode;
866  rtems_rfs_file_shared* shared;
867  uint16_t               mode;
868  int                    rc;
869
870  if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_STAT))
871    printf ("rtems-rfs-rtems: stat: in: ino:%" PRId32 "\n", ino);
872
873  rtems_rfs_rtems_lock (fs);
874
875  rc = rtems_rfs_inode_open (fs, ino, &inode, true);
876  if (rc)
877  {
878    rtems_rfs_rtems_unlock (fs);
879    return rtems_rfs_rtems_error ("stat: opening inode", rc);
880  }
881
882  mode = rtems_rfs_inode_get_mode (&inode);
883
884  if (RTEMS_RFS_S_ISCHR (mode) || RTEMS_RFS_S_ISBLK (mode))
885  {
886    buf->st_rdev =
887      rtems_filesystem_make_dev_t (rtems_rfs_inode_get_block (&inode, 0),
888                                   rtems_rfs_inode_get_block (&inode, 1));
889  }
890
891  buf->st_dev     = rtems_rfs_fs_device (fs);
892  buf->st_ino     = rtems_rfs_inode_ino (&inode);
893  buf->st_mode    = rtems_rfs_rtems_mode (mode);
894  buf->st_nlink   = rtems_rfs_inode_get_links (&inode);
895  buf->st_uid     = rtems_rfs_inode_get_uid (&inode);
896  buf->st_gid     = rtems_rfs_inode_get_gid (&inode);
897
898  /*
899   * Need to check is the ino is an open file. If so we take the values from
900   * the open file rather than the inode.
901   */
902  shared = rtems_rfs_file_get_shared (fs, rtems_rfs_inode_ino (&inode));
903
904  if (shared)
905  {
906    buf->st_atime   = rtems_rfs_file_shared_get_atime (shared);
907    buf->st_mtime   = rtems_rfs_file_shared_get_mtime (shared);
908    buf->st_ctime   = rtems_rfs_file_shared_get_ctime (shared);
909    buf->st_blocks  = rtems_rfs_file_shared_get_block_count (shared);
910
911    if (S_ISLNK (buf->st_mode))
912      buf->st_size = rtems_rfs_file_shared_get_block_offset (shared);
913    else
914      buf->st_size = rtems_rfs_file_shared_get_size (fs, shared);
915  }
916  else
917  {
918    buf->st_atime   = rtems_rfs_inode_get_atime (&inode);
919    buf->st_mtime   = rtems_rfs_inode_get_mtime (&inode);
920    buf->st_ctime   = rtems_rfs_inode_get_ctime (&inode);
921    buf->st_blocks  = rtems_rfs_inode_get_block_count (&inode);
922
923    if (S_ISLNK (buf->st_mode))
924      buf->st_size = rtems_rfs_inode_get_block_offset (&inode);
925    else
926      buf->st_size = rtems_rfs_inode_get_size (fs, &inode);
927  }
928
929  buf->st_blksize = rtems_rfs_fs_block_size (fs);
930
931  rc = rtems_rfs_inode_close (fs, &inode);
932  if (rc > 0)
933  {
934    rtems_rfs_rtems_unlock (fs);
935    return rtems_rfs_rtems_error ("stat: closing inode", rc);
936  }
937
938  rtems_rfs_rtems_unlock (fs);
939  return 0;
940}
941
942/**
943 * Routine to create a node in the RFS file system.
944 *
945 * @param name
946 * @param mode
947 * @param dev
948 * @param pathloc
949 * @return int
950 */
951
952static int
953rtems_rfs_rtems_mknod (const char                       *name,
954                       mode_t                            mode,
955                       dev_t                             dev,
956                       rtems_filesystem_location_info_t *pathloc)
957{
958  rtems_rfs_file_system*  fs = rtems_rfs_rtems_pathloc_dev (pathloc);
959  rtems_rfs_ino           parent = rtems_rfs_rtems_get_pathloc_ino (pathloc);
960  rtems_rfs_ino           ino;
961  rtems_rfs_inode_handle  inode;
962  uid_t                   uid;
963  gid_t                   gid;
964  int                     rc;
965
966#if defined(RTEMS_POSIX_API)
967  uid = geteuid ();
968  gid = getegid ();
969#else
970  uid = 0;
971  gid = 0;
972#endif
973
974  rtems_rfs_rtems_lock (fs);
975
976  rc = rtems_rfs_inode_create (fs, parent, name, strlen (name),
977                               rtems_rfs_rtems_imode (mode),
978                               1, uid, gid, &ino);
979  if (rc > 0)
980  {
981    rtems_rfs_rtems_unlock (fs);
982    return rtems_rfs_rtems_error ("mknod: inode create", rc);
983  }
984
985  rc = rtems_rfs_inode_open (fs, ino, &inode, true);
986  if (rc > 0)
987  {
988    rtems_rfs_rtems_unlock (fs);
989    return rtems_rfs_rtems_error ("mknod: inode open", rc);
990  }
991
992  if (S_ISDIR(mode) || S_ISREG(mode))
993  {
994  }
995  else if (S_ISCHR (mode) || S_ISBLK (mode))
996  {
997    int major;
998    int minor;
999    rtems_filesystem_split_dev_t (dev, major, minor);
1000    rtems_rfs_inode_set_block (&inode, 0, major);
1001    rtems_rfs_inode_set_block (&inode, 1, minor);
1002  }
1003  else
1004  {
1005    rtems_rfs_inode_close (fs, &inode);
1006    rtems_rfs_rtems_unlock (fs);
1007    return rtems_rfs_rtems_error ("mknod: bad mode", EINVAL);
1008  }
1009
1010  rc = rtems_rfs_inode_close (fs, &inode);
1011  if (rc > 0)
1012  {
1013    rtems_rfs_rtems_unlock (fs);
1014    return rtems_rfs_rtems_error ("mknod: closing inode", rc);
1015  }
1016
1017  rtems_rfs_rtems_unlock (fs);
1018  return 0;
1019}
1020
1021/**
1022 * Routine to remove a node from the RFS file system.
1023 *
1024 * @param parent_pathloc
1025 * @param pathloc
1026 * @return int
1027 */
1028int
1029rtems_rfs_rtems_rmnod (rtems_filesystem_location_info_t* parent_pathloc,
1030                       rtems_filesystem_location_info_t* pathloc)
1031{
1032  rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc);
1033  rtems_rfs_ino          parent = rtems_rfs_rtems_get_pathloc_ino (parent_pathloc);
1034  rtems_rfs_ino          ino = rtems_rfs_rtems_get_pathloc_ino (pathloc);
1035  uint32_t               doff = rtems_rfs_rtems_get_pathloc_doff (pathloc);
1036  int                    rc;
1037
1038  if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_RMNOD))
1039    printf ("rtems-rfs: rmnod: parent:%" PRId32 " doff:%" PRIu32 ", ino:%" PRId32 "\n",
1040            parent, doff, ino);
1041
1042  rtems_rfs_rtems_lock (fs);
1043
1044  rc = rtems_rfs_unlink (fs, parent, ino, doff, rtems_rfs_unlink_dir_denied);
1045  if (rc)
1046  {
1047    rtems_rfs_rtems_unlock (fs);
1048    return rtems_rfs_rtems_error ("rmnod: unlinking", rc);
1049  }
1050
1051  rtems_rfs_rtems_unlock (fs);
1052  return 0;
1053}
1054
1055/**
1056 * The following routine does a sync on an inode node. Currently it flushes
1057 * everything related to this device.
1058 *
1059 * @param iop
1060 * @return int
1061 */
1062int
1063rtems_rfs_rtems_fdatasync (rtems_libio_t* iop)
1064{
1065  int rc;
1066
1067  rc = rtems_rfs_buffer_sync (rtems_rfs_rtems_pathloc_dev (&iop->pathinfo));
1068  if (rc)
1069    return rtems_rfs_rtems_error ("fdatasync: sync", rc);
1070
1071  return 0;
1072}
1073
1074/**
1075 * Rename the node.
1076 *
1077 * @param old_parent_loc The old name's parent location.
1078 * @param old_loc The old name's location.
1079 * @param new_parent_loc The new name's parent location.
1080 * @param new_name The new name.
1081 * @return int
1082 */
1083static int
1084rtems_rfs_rtems_rename(rtems_filesystem_location_info_t* old_parent_loc,
1085                       rtems_filesystem_location_info_t* old_loc,
1086                       rtems_filesystem_location_info_t* new_parent_loc,
1087                       const char*                       new_name)
1088{
1089  rtems_rfs_file_system*  fs = rtems_rfs_rtems_pathloc_dev (old_loc);
1090  rtems_rfs_ino           old_parent;
1091  rtems_rfs_ino           new_parent;
1092  rtems_rfs_ino           ino;
1093  uint32_t                doff;
1094  int                     rc;
1095
1096  old_parent = rtems_rfs_rtems_get_pathloc_ino (old_parent_loc);
1097  new_parent = rtems_rfs_rtems_get_pathloc_ino (new_parent_loc);
1098
1099  ino  = rtems_rfs_rtems_get_pathloc_ino (old_loc);
1100  doff = rtems_rfs_rtems_get_pathloc_doff (old_loc);
1101
1102  if (rtems_rfs_rtems_trace (RTEMS_RFS_RTEMS_DEBUG_RENAME))
1103    printf ("rtems-rfs: rename: ino:%" PRId32 " doff:%" PRIu32 ", new parent:%" PRId32 " new name:%s\n",
1104            ino, doff, new_parent, new_name);
1105
1106  rtems_rfs_rtems_lock (fs);
1107
1108  /*
1109   * Link to the inode before unlinking so the inode is not erased when
1110   * unlinked.
1111   */
1112  rc = rtems_rfs_link (fs, new_name, strlen (new_name), new_parent, ino, true);
1113  if (rc)
1114  {
1115    rtems_rfs_rtems_unlock (fs);
1116    return rtems_rfs_rtems_error ("rename: linking", rc);
1117  }
1118
1119  /*
1120   * Unlink all inodes even directories with the dir option as false because a
1121   * directory may not be empty.
1122   */
1123  rc = rtems_rfs_unlink (fs, old_parent, ino, doff,
1124                         rtems_rfs_unlink_dir_allowed);
1125  if (rc)
1126  {
1127    rtems_rfs_rtems_unlock (fs);
1128    return rtems_rfs_rtems_error ("rename: unlinking", rc);
1129  }
1130
1131  rtems_rfs_rtems_unlock (fs);
1132
1133  return 0;
1134}
1135
1136/**
1137 * Return the file system stat data.
1138 *
1139 * @param pathloc
1140 * @param sb
1141 * @return int
1142 */
1143static int
1144rtems_rfs_rtems_statvfs (rtems_filesystem_location_info_t* pathloc,
1145                         struct statvfs*                   sb)
1146{
1147  rtems_rfs_file_system* fs = rtems_rfs_rtems_pathloc_dev (pathloc);
1148  size_t                 blocks;
1149  size_t                 inodes;
1150
1151  rtems_rfs_group_usage (fs, &blocks, &inodes);
1152
1153  sb->f_bsize   = rtems_rfs_fs_block_size (fs);
1154  sb->f_frsize  = rtems_rfs_fs_media_block_size (fs);
1155  sb->f_blocks  = rtems_rfs_fs_media_blocks (fs);
1156  sb->f_bfree   = rtems_rfs_fs_blocks (fs) - blocks;
1157  sb->f_bavail  = sb->f_bfree;
1158  sb->f_files   = rtems_rfs_fs_inodes (fs);
1159  sb->f_ffree   = rtems_rfs_fs_inodes (fs) - inodes;
1160  sb->f_favail  = sb->f_ffree;
1161  sb->f_fsid    = RTEMS_RFS_SB_MAGIC;
1162  sb->f_flag    = rtems_rfs_fs_flags (fs);
1163  sb->f_namemax = rtems_rfs_fs_max_name (fs);
1164
1165  return 0;
1166}
1167
1168/**
1169 *  Handler table for RFS link nodes
1170 */
1171const rtems_filesystem_file_handlers_r rtems_rfs_rtems_link_handlers =
1172{
1173  .open_h      = rtems_filesystem_default_open,
1174  .close_h     = rtems_filesystem_default_close,
1175  .read_h      = rtems_filesystem_default_read,
1176  .write_h     = rtems_filesystem_default_write,
1177  .ioctl_h     = rtems_filesystem_default_ioctl,
1178  .lseek_h     = rtems_filesystem_default_lseek,
1179  .fstat_h     = rtems_rfs_rtems_fstat,
1180  .fchmod_h    = rtems_filesystem_default_fchmod,
1181  .ftruncate_h = rtems_filesystem_default_ftruncate,
1182  .fpathconf_h = rtems_filesystem_default_fpathconf,
1183  .fsync_h     = rtems_filesystem_default_fsync,
1184  .fdatasync_h = rtems_filesystem_default_fdatasync,
1185  .fcntl_h     = rtems_filesystem_default_fcntl,
1186  .rmnod_h     = rtems_rfs_rtems_rmnod
1187};
1188
1189/**
1190 * Forward decl for the ops table.
1191 */
1192
1193int rtems_rfs_rtems_initialise (rtems_filesystem_mount_table_entry_t *mt_entry,
1194                                const void                           *data);
1195int rtems_rfs_rtems_shutdown (rtems_filesystem_mount_table_entry_t *mt_entry);
1196
1197/**
1198 * RFS file system operations table.
1199 */
1200const rtems_filesystem_operations_table rtems_rfs_ops =
1201{
1202  .evalpath_h     = rtems_rfs_rtems_eval_path,
1203  .evalformake_h  = rtems_rfs_rtems_eval_for_make,
1204  .link_h         = rtems_rfs_rtems_link,
1205  .unlink_h       = rtems_rfs_rtems_unlink,
1206  .node_type_h    = rtems_rfs_rtems_node_type,
1207  .mknod_h        = rtems_rfs_rtems_mknod,
1208  .chown_h        = rtems_rfs_rtems_chown,
1209  .freenod_h      = rtems_filesystem_default_freenode,
1210  .mount_h        = rtems_filesystem_default_mount,
1211  .fsmount_me_h   = rtems_rfs_rtems_initialise,
1212  .unmount_h      = rtems_filesystem_default_unmount,
1213  .fsunmount_me_h = rtems_rfs_rtems_shutdown,
1214  .utime_h        = rtems_rfs_rtems_utime,
1215  .eval_link_h    = rtems_filesystem_default_evaluate_link, /* never called cause we lie in the node type */
1216  .symlink_h      = rtems_rfs_rtems_symlink,
1217  .readlink_h     = rtems_rfs_rtems_readlink,
1218  .rename_h       = rtems_rfs_rtems_rename,
1219  .statvfs_h      = rtems_rfs_rtems_statvfs
1220};
1221
1222/**
1223 * Open the file system.
1224 */
1225
1226int
1227rtems_rfs_rtems_initialise (rtems_filesystem_mount_table_entry_t* mt_entry,
1228                            const void*                           data)
1229{
1230  rtems_rfs_rtems_private* rtems;
1231  rtems_rfs_file_system*   fs;
1232  uint32_t                 flags = 0;
1233  uint32_t                 max_held_buffers = RTEMS_RFS_FS_MAX_HELD_BUFFERS;
1234  const char*              options = data;
1235  int                      rc;
1236
1237  /*
1238   * Parse the options the user specifiies.
1239   */
1240  while (options)
1241  {
1242    printf ("options=%s\n", options);
1243    if (strncmp (options, "hold-bitmaps",
1244                 sizeof ("hold-bitmaps") - 1) == 0)
1245      flags |= RTEMS_RFS_FS_BITMAPS_HOLD;
1246    else if (strncmp (options, "no-local-cache",
1247                      sizeof ("no-local-cache") - 1) == 0)
1248      flags |= RTEMS_RFS_FS_NO_LOCAL_CACHE;
1249    else if (strncmp (options, "max-held-bufs",
1250                      sizeof ("max-held-bufs") - 1) == 0)
1251    {
1252      max_held_buffers = strtoul (options + sizeof ("max-held-bufs"), 0, 0);
1253    }
1254    else
1255      return rtems_rfs_rtems_error ("initialise: invalid option", EINVAL);
1256
1257    options = strchr (options, ',');
1258    if (options)
1259    {
1260      ++options;
1261      if (*options == '\0')
1262        options = NULL;
1263    }
1264  }
1265
1266  rtems = malloc (sizeof (rtems_rfs_rtems_private));
1267  if (!rtems)
1268    return rtems_rfs_rtems_error ("initialise: local data", ENOMEM);
1269
1270  memset (rtems, 0, sizeof (rtems_rfs_rtems_private));
1271
1272  rc = rtems_rfs_mutex_create (&rtems->access);
1273  if (rc > 0)
1274  {
1275    free (rtems);
1276    return rtems_rfs_rtems_error ("initialise: cannot create mutex", rc);
1277  }
1278
1279  rc = rtems_rfs_mutex_lock (&rtems->access);
1280  if (rc > 0)
1281  {
1282    rtems_rfs_mutex_destroy (&rtems->access);
1283    free (rtems);
1284    return rtems_rfs_rtems_error ("initialise: cannot lock access  mutex", rc);
1285  }
1286
1287  rc = rtems_rfs_fs_open (mt_entry->dev, rtems, flags, max_held_buffers, &fs);
1288  if (rc)
1289  {
1290    free (rtems);
1291    return rtems_rfs_rtems_error ("initialise: open", rc);
1292  }
1293
1294  mt_entry->fs_info = fs;
1295
1296  mt_entry->mt_fs_root.node_access = (void*) RTEMS_RFS_ROOT_INO;
1297  mt_entry->mt_fs_root.handlers    = &rtems_rfs_rtems_dir_handlers;
1298  mt_entry->mt_fs_root.ops         = &rtems_rfs_ops;
1299
1300  rtems_rfs_rtems_unlock (fs);
1301
1302  return 0;
1303}
1304
1305/**
1306 * Shutdown the file system.
1307 */
1308int
1309rtems_rfs_rtems_shutdown (rtems_filesystem_mount_table_entry_t* mt_entry)
1310{
1311  rtems_rfs_file_system*   fs = mt_entry->fs_info;
1312  rtems_rfs_rtems_private* rtems;
1313  int                      rc;
1314
1315  rtems = rtems_rfs_fs_user (fs);
1316
1317  rc = rtems_rfs_fs_close(fs);
1318
1319  rtems_rfs_mutex_destroy (&rtems->access);
1320  free (rtems);
1321
1322  return rtems_rfs_rtems_error ("shutdown: close", rc);
1323}
Note: See TracBrowser for help on using the repository browser.