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

4.115
Last change on this file since a43a3466 was a43a3466, checked in by Sebastian Huber <sebastian.huber@…>, on 02/15/15 at 09:38:15

IMFS: Implement variable length node names

This reduces the average node size and adds more flexibility.

  • Property mode set to 100644
File size: 4.7 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.org/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_directory_t *dir,
42  const char *token,
43  size_t tokenlen
44)
45{
46  if ( rtems_filesystem_is_current_directory( token, tokenlen ) ) {
47    return &dir->Node;
48  } else {
49    if ( rtems_filesystem_is_parent_directory( token, tokenlen ) ) {
50      return dir->Node.Parent;
51    } else {
52      rtems_chain_control *entries = &dir->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 = entry->namelen == tokenlen
59          && memcmp( entry->name, token, 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  mode_t mode
76)
77{
78  rtems_filesystem_global_location_t **fs_root_ptr = NULL;
79
80  if ( S_ISDIR( mode ) ) {
81    IMFS_directory_t *dir = (IMFS_directory_t *) node;
82
83    if ( dir->mt_fs != NULL ) {
84      fs_root_ptr = &dir->mt_fs->mt_fs_root;
85    }
86  }
87
88  return fs_root_ptr;
89}
90
91static rtems_filesystem_eval_path_generic_status IMFS_eval_token(
92  rtems_filesystem_eval_path_context_t *ctx,
93  void *arg,
94  const char *token,
95  size_t tokenlen
96)
97{
98  rtems_filesystem_eval_path_generic_status status =
99    RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_DONE;
100  rtems_filesystem_location_info_t *currentloc =
101    rtems_filesystem_eval_path_get_currentloc( ctx );
102  IMFS_directory_t *dir = currentloc->node_access;
103  bool access_ok = rtems_filesystem_eval_path_check_access(
104    ctx,
105    RTEMS_FS_PERMS_EXEC,
106    dir->Node.st_mode,
107    dir->Node.st_uid,
108    dir->Node.st_gid
109  );
110
111  if ( access_ok ) {
112    IMFS_jnode_t *entry = IMFS_search_in_directory( dir, token, tokenlen );
113
114    if ( entry != NULL ) {
115      bool terminal = !rtems_filesystem_eval_path_has_path( ctx );
116      int eval_flags = rtems_filesystem_eval_path_get_flags( ctx );
117      bool follow_hard_link = (eval_flags & RTEMS_FS_FOLLOW_HARD_LINK) != 0;
118      bool follow_sym_link = (eval_flags & RTEMS_FS_FOLLOW_SYM_LINK) != 0;
119      mode_t mode = entry->st_mode;
120
121      rtems_filesystem_eval_path_clear_token( ctx );
122
123      if ( IMFS_is_hard_link( mode ) && ( follow_hard_link || !terminal ) ) {
124        const IMFS_link_t *hard_link = (const IMFS_link_t *) entry;
125
126        entry = hard_link->link_node;
127      }
128
129      if ( S_ISLNK( mode ) && ( follow_sym_link || !terminal ) ) {
130        const IMFS_sym_link_t *sym_link = (const IMFS_sym_link_t *) entry;
131        const char *target = sym_link->name;
132
133        rtems_filesystem_eval_path_recursive( ctx, target, strlen( target ) );
134      } else {
135        rtems_filesystem_global_location_t **fs_root_ptr =
136          IMFS_is_mount_point( entry, mode );
137
138        if ( fs_root_ptr == NULL ) {
139          --dir->Node.reference_count;
140          ++entry->reference_count;
141          currentloc->node_access = entry;
142          currentloc->node_access_2 =
143            IMFS_generic_get_context_by_node( entry );
144          IMFS_Set_handlers( currentloc );
145
146          if ( !terminal ) {
147            status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_CONTINUE;
148          }
149        } else {
150          access_ok = rtems_filesystem_eval_path_check_access(
151            ctx,
152            RTEMS_FS_PERMS_EXEC,
153            entry->st_mode,
154            entry->st_uid,
155            entry->st_gid
156          );
157          if ( access_ok ) {
158            rtems_filesystem_eval_path_restart( ctx, fs_root_ptr );
159          }
160        }
161      }
162    } else {
163      status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_NO_ENTRY;
164    }
165  }
166
167  return status;
168}
169
170static const rtems_filesystem_eval_path_generic_config IMFS_eval_config = {
171  .is_directory = IMFS_eval_is_directory,
172  .eval_token = IMFS_eval_token
173};
174
175void IMFS_eval_path( rtems_filesystem_eval_path_context_t *ctx )
176{
177  rtems_filesystem_eval_path_generic( ctx, NULL, &IMFS_eval_config );
178}
Note: See TracBrowser for help on using the repository browser.