source: rtems/cpukit/libfs/src/imfs/imfs_eval.c @ 5b34e7a

4.115
Last change on this file since 5b34e7a was 5b34e7a, checked in by Sebastian Huber <sebastian.huber@…>, on Jan 16, 2014 at 12:05:13 PM

IMFS: Improved support for generic nodes

The rtems_filesystem_location_info_t::node_access_2 was unused by the
IMFS. Use it to hold the context of generic nodes. This makes it
possible to use node handlers for objects with and without a
corresponding file system node.

For example network sockets created with socket() have only a file
descriptor, but no corresponding file system node. The UNIX(4) domain
sockets can be bound to file system nodes. In both cases the
rtems_filesystem_location_info_t must provide a pointer to the socket
structure used by the socket node handlers. With the context pointer
(for sockets, this is the socket structure) in
rtems_filesystem_location_info_t::node_access_2 the same node handlers
can be used in both cases.

  • Property mode set to 100644
File size: 4.6 KB
Line 
1/**
2 * @file
3 *
4 * @brief Evaluation IMFS Node Support
5 * @ingroup IMFS
6 */
7
8/*
9 *  COPYRIGHT (c) 1989-1999.
10 *  On-Line Applications Research Corporation (OAR).
11 *
12 *  Modifications to support reference counting in the file system are
13 *  Copyright (c) 2012 embedded brains GmbH.
14 *
15 *  The license and distribution terms for this file may be
16 *  found in the file LICENSE in this distribution or at
17 *  http://www.rtems.com/license/LICENSE.
18 */
19
20#if HAVE_CONFIG_H
21  #include "config.h"
22#endif
23
24#include "imfs.h"
25
26#include <string.h>
27
28static bool IMFS_eval_is_directory(
29  rtems_filesystem_eval_path_context_t *ctx,
30  void *arg
31)
32{
33  rtems_filesystem_location_info_t *currentloc =
34    rtems_filesystem_eval_path_get_currentloc( ctx );
35  IMFS_jnode_t *node = currentloc->node_access;
36
37  return IMFS_is_directory( node );
38}
39
40static IMFS_jnode_t *IMFS_search_in_directory(
41  IMFS_jnode_t *dir,
42  const char *token,
43  size_t tokenlen
44)
45{
46  if ( rtems_filesystem_is_current_directory( token, tokenlen ) ) {
47    return dir;
48  } else {
49    if ( rtems_filesystem_is_parent_directory( token, tokenlen ) ) {
50      return dir->Parent;
51    } else {
52      rtems_chain_control *entries = &dir->info.directory.Entries;
53      rtems_chain_node *current = rtems_chain_first( entries );
54      rtems_chain_node *tail = rtems_chain_tail( entries );
55
56      while ( current != tail ) {
57        IMFS_jnode_t *entry = (IMFS_jnode_t *) current;
58        bool match = strncmp( entry->name, token, tokenlen ) == 0
59          && entry->name [tokenlen] == '\0';
60
61        if ( match ) {
62          return entry;
63        }
64
65        current = rtems_chain_next( current );
66      }
67
68      return NULL;
69    }
70  }
71}
72
73static rtems_filesystem_global_location_t **IMFS_is_mount_point(
74  IMFS_jnode_t *node,
75  IMFS_jnode_types_t type
76)
77{
78  rtems_filesystem_global_location_t **fs_root_ptr = NULL;
79
80  if ( type == IMFS_DIRECTORY ) {
81    if ( node->info.directory.mt_fs != NULL ) {
82      fs_root_ptr = &node->info.directory.mt_fs->mt_fs_root;
83    }
84  }
85
86  return fs_root_ptr;
87}
88
89static rtems_filesystem_eval_path_generic_status IMFS_eval_token(
90  rtems_filesystem_eval_path_context_t *ctx,
91  void *arg,
92  const char *token,
93  size_t tokenlen
94)
95{
96  rtems_filesystem_eval_path_generic_status status =
97    RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_DONE;
98  rtems_filesystem_location_info_t *currentloc =
99    rtems_filesystem_eval_path_get_currentloc( ctx );
100  IMFS_jnode_t *dir = currentloc->node_access;
101  bool access_ok = rtems_filesystem_eval_path_check_access(
102    ctx,
103    RTEMS_FS_PERMS_EXEC,
104    dir->st_mode,
105    dir->st_uid,
106    dir->st_gid
107  );
108
109  if ( access_ok ) {
110    IMFS_jnode_t *entry = IMFS_search_in_directory( dir, token, tokenlen );
111
112    if ( entry != NULL ) {
113      bool terminal = !rtems_filesystem_eval_path_has_path( ctx );
114      int eval_flags = rtems_filesystem_eval_path_get_flags( ctx );
115      bool follow_hard_link = (eval_flags & RTEMS_FS_FOLLOW_HARD_LINK) != 0;
116      bool follow_sym_link = (eval_flags & RTEMS_FS_FOLLOW_SYM_LINK) != 0;
117      IMFS_jnode_types_t type = IMFS_type( entry );
118
119      rtems_filesystem_eval_path_clear_token( ctx );
120
121      if ( type == IMFS_HARD_LINK && (follow_hard_link || !terminal)) {
122        entry = entry->info.hard_link.link_node;
123      }
124
125      if ( type == IMFS_SYM_LINK && (follow_sym_link || !terminal)) {
126        const char *target = entry->info.sym_link.name;
127
128        rtems_filesystem_eval_path_recursive( ctx, target, strlen( target ) );
129      } else {
130        rtems_filesystem_global_location_t **fs_root_ptr =
131          IMFS_is_mount_point( entry, type );
132
133        if ( fs_root_ptr == NULL ) {
134          --dir->reference_count;
135          ++entry->reference_count;
136          currentloc->node_access = entry;
137          currentloc->node_access_2 =
138            IMFS_generic_get_context_by_node( entry );
139          IMFS_Set_handlers( currentloc );
140
141          if ( !terminal ) {
142            status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_CONTINUE;
143          }
144        } else {
145          access_ok = rtems_filesystem_eval_path_check_access(
146            ctx,
147            RTEMS_FS_PERMS_EXEC,
148            entry->st_mode,
149            entry->st_uid,
150            entry->st_gid
151          );
152          if ( access_ok ) {
153            rtems_filesystem_eval_path_restart( ctx, fs_root_ptr );
154          }
155        }
156      }
157    } else {
158      status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_NO_ENTRY;
159    }
160  }
161
162  return status;
163}
164
165static const rtems_filesystem_eval_path_generic_config IMFS_eval_config = {
166  .is_directory = IMFS_eval_is_directory,
167  .eval_token = IMFS_eval_token
168};
169
170void IMFS_eval_path( rtems_filesystem_eval_path_context_t *ctx )
171{
172  rtems_filesystem_eval_path_generic( ctx, NULL, &IMFS_eval_config );
173}
Note: See TracBrowser for help on using the repository browser.