source: rtems/cpukit/libcsupport/src/sup_fs_eval_path.c @ da154e14

4.11
Last change on this file since da154e14 was da154e14, checked in by Sebastian Huber <sebastian.huber@…>, on May 14, 2012 at 2:55:41 PM

Filesystem: Move operations to mount table entry

The scope of the file system operations is the file system instance.
The scope of the file system node handlers is the file location. The
benefit of moving the operations to the mount table entry is a size
reduction of the file location (rtems_filesystem_location_info_t). The
code size is slightly increased due to additional load instructions.

Restructure rtems_filesystem_mount_table_entry_t to improve cache
efficiency.

  • Property mode set to 100644
File size: 7.9 KB
Line 
1/*
2 * Copyright (c) 2012 embedded brains GmbH.  All rights reserved.
3 *
4 *  embedded brains GmbH
5 *  Obere Lagerstr. 30
6 *  82178 Puchheim
7 *  Germany
8 *  <rtems@embedded-brains.de>
9 *
10 * The license and distribution terms for this file may be
11 * found in the file LICENSE in this distribution or at
12 * http://www.rtems.com/license/LICENSE.
13 */
14
15#if HAVE_CONFIG_H
16  #include "config.h"
17#endif
18
19#include <rtems/libio_.h>
20
21static size_t get_parentpathlen(const char *path, size_t pathlen)
22{
23  while (pathlen > 0) {
24    size_t i = pathlen - 1;
25
26    if (rtems_filesystem_is_delimiter(path [i])) {
27      return pathlen;
28    }
29
30    pathlen = i;
31  }
32
33  return 0;
34}
35
36static void set_startloc(
37  rtems_filesystem_eval_path_context_t *ctx,
38  rtems_filesystem_global_location_t *const *global_root_ptr,
39  rtems_filesystem_global_location_t *const *global_current_ptr
40)
41{
42  if (ctx->pathlen > 0) {
43    char c = ctx->path [0];
44
45    ctx->rootloc = rtems_filesystem_global_location_obtain(global_root_ptr);
46
47    if (rtems_filesystem_is_delimiter(c)) {
48      ++ctx->path;
49      --ctx->pathlen;
50      ctx->startloc = rtems_filesystem_global_location_obtain(
51        &ctx->rootloc
52      );
53    } else {
54      ctx->startloc = rtems_filesystem_global_location_obtain(
55        global_current_ptr
56      );
57    }
58  } else {
59    ctx->rootloc = rtems_filesystem_global_location_obtain_null();
60    ctx->startloc = rtems_filesystem_global_location_obtain_null();
61    errno = ENOENT;
62  }
63}
64
65static void check_access(
66  rtems_filesystem_eval_path_context_t *ctx,
67  int eval_flags
68)
69{
70  const rtems_filesystem_location_info_t *currentloc = &ctx->currentloc;
71  const rtems_filesystem_mount_table_entry_t *mt_entry = currentloc->mt_entry;
72
73  if ((eval_flags & RTEMS_FS_PERMS_WRITE) == 0 || mt_entry->writeable) {
74    struct stat st;
75    int rv;
76
77    st.st_mode = 0;
78    st.st_uid = 0;
79    st.st_gid = 0;
80    rv = (*currentloc->handlers->fstat_h)(currentloc, &st);
81    if (rv == 0) {
82      bool access_ok = rtems_filesystem_check_access(
83        eval_flags,
84        st.st_mode,
85        st.st_uid,
86        st.st_gid
87      );
88
89      if (!access_ok) {
90        rtems_filesystem_eval_path_error(ctx, EACCES);
91      }
92    } else {
93      rtems_filesystem_eval_path_error(ctx, 0);
94    }
95  } else {
96    rtems_filesystem_eval_path_error(ctx, EROFS);
97  }
98}
99
100void rtems_filesystem_eval_path_continue(
101  rtems_filesystem_eval_path_context_t *ctx
102)
103{
104  int eval_flags;
105
106  while (ctx->pathlen > 0) {
107    (*ctx->currentloc.mt_entry->ops->eval_path_h)(ctx);
108  }
109
110  eval_flags = rtems_filesystem_eval_path_get_flags(ctx);
111  if (rtems_filesystem_eval_path_has_token(ctx)) {
112    bool make = (eval_flags & RTEMS_FS_MAKE) != 0;
113
114    if (make) {
115      check_access(ctx, RTEMS_FS_PERMS_WRITE);
116    } else {
117      rtems_filesystem_eval_path_error(ctx, ENOENT);
118    }
119  } else {
120    bool exclusive = (eval_flags & RTEMS_FS_EXCLUSIVE) != 0;
121
122    if (!exclusive) {
123      check_access(ctx, ctx->flags);
124    } else {
125      rtems_filesystem_eval_path_error(ctx, EEXIST);
126    }
127  }
128}
129
130static rtems_filesystem_location_info_t *
131eval_path_start(
132  rtems_filesystem_eval_path_context_t *ctx,
133  const char *path,
134  size_t pathlen,
135  int eval_flags,
136  rtems_filesystem_global_location_t *const *global_root_ptr,
137  rtems_filesystem_global_location_t *const *global_current_ptr
138)
139{
140  memset(ctx, 0, sizeof(*ctx));
141
142  ctx->path = path;
143  ctx->pathlen = pathlen;
144  ctx->flags = eval_flags;
145
146  set_startloc(ctx, global_root_ptr, global_current_ptr);
147
148  rtems_filesystem_instance_lock(&ctx->startloc->location);
149
150  rtems_filesystem_location_clone(
151    &ctx->currentloc,
152    &ctx->startloc->location
153  );
154
155  rtems_filesystem_eval_path_continue(ctx);
156
157  return &ctx->currentloc;
158}
159
160rtems_filesystem_location_info_t *
161rtems_filesystem_eval_path_start_with_root_and_current(
162  rtems_filesystem_eval_path_context_t *ctx,
163  const char *path,
164  int eval_flags,
165  rtems_filesystem_global_location_t *const *global_root_ptr,
166  rtems_filesystem_global_location_t *const *global_current_ptr
167)
168{
169  return eval_path_start(
170    ctx,
171    path,
172    strlen(path),
173    eval_flags,
174    global_root_ptr,
175    global_current_ptr
176  );
177}
178
179rtems_filesystem_location_info_t *
180rtems_filesystem_eval_path_start(
181  rtems_filesystem_eval_path_context_t *ctx,
182  const char *path,
183  int eval_flags
184)
185{
186  return rtems_filesystem_eval_path_start_with_root_and_current(
187    ctx,
188    path,
189    eval_flags,
190    &rtems_filesystem_root,
191    &rtems_filesystem_current
192  );
193}
194
195rtems_filesystem_location_info_t *
196rtems_filesystem_eval_path_start_with_parent(
197  rtems_filesystem_eval_path_context_t *ctx,
198  const char *path,
199  int eval_flags,
200  rtems_filesystem_location_info_t *parentloc,
201  int parent_eval_flags
202)
203{
204  size_t pathlen = strlen(path);
205  const char *parentpath = path;
206  size_t parentpathlen = get_parentpathlen(path, pathlen);
207  const char *name = NULL;
208  size_t namelen = 0;
209  const rtems_filesystem_location_info_t *currentloc = NULL;
210
211  if (pathlen > 0) {
212    if (parentpathlen == 0) {
213      parentpath = ".";
214      parentpathlen = 1;
215      name = path;
216      namelen = pathlen;
217    } else {
218      name = path + parentpathlen;
219      namelen = pathlen - parentpathlen;
220    }
221  }
222
223  currentloc = eval_path_start(
224    ctx,
225    parentpath,
226    parentpathlen,
227    parent_eval_flags,
228    &rtems_filesystem_root,
229    &rtems_filesystem_current
230  );
231
232  rtems_filesystem_location_clone(parentloc, currentloc);
233
234  ctx->path = name;
235  ctx->pathlen = namelen;
236  ctx->flags = eval_flags;
237
238  rtems_filesystem_eval_path_continue(ctx);
239
240  return &ctx->currentloc;
241}
242
243void rtems_filesystem_eval_path_recursive(
244  rtems_filesystem_eval_path_context_t *ctx,
245  const char *path,
246  size_t pathlen
247)
248{
249  if (pathlen > 0) {
250    if (ctx->recursionlevel < RTEMS_FILESYSTEM_SYMLOOP_MAX) {
251      const char *saved_path = ctx->path;
252      size_t saved_pathlen = ctx->pathlen;
253
254      if (rtems_filesystem_is_delimiter(path [0])) {
255        rtems_filesystem_eval_path_restart(ctx, &ctx->rootloc);
256      }
257
258      ctx->path = path;
259      ctx->pathlen = pathlen;
260
261      ++ctx->recursionlevel;
262      while (ctx->pathlen > 0) {
263        (*ctx->currentloc.mt_entry->ops->eval_path_h)(ctx);
264      }
265      --ctx->recursionlevel;
266
267      ctx->path = saved_path;
268      ctx->pathlen = saved_pathlen;
269    } else {
270      rtems_filesystem_eval_path_error(ctx, ELOOP);
271    }
272  } else {
273    rtems_filesystem_eval_path_error(ctx, ENOENT);
274  }
275}
276
277void rtems_filesystem_eval_path_error(
278  rtems_filesystem_eval_path_context_t *ctx,
279  int eno
280)
281{
282  ctx->path = NULL;
283  ctx->pathlen = 0;
284  ctx->token = NULL;
285  ctx->tokenlen = 0;
286
287  if (!rtems_filesystem_location_is_null(&ctx->currentloc)) {
288    if (eno != 0) {
289      errno = eno;
290    }
291
292    rtems_filesystem_location_detach(&ctx->currentloc);
293  }
294}
295
296static void free_location(rtems_filesystem_location_info_t *loc)
297{
298  rtems_filesystem_mt_entry_declare_lock_context(lock_context);
299
300  (*loc->mt_entry->ops->freenod_h)(loc);
301
302  rtems_filesystem_mt_entry_lock(lock_context);
303  rtems_chain_extract_unprotected(&loc->mt_entry_node);
304  rtems_filesystem_mt_entry_unlock(lock_context);
305}
306
307void rtems_filesystem_eval_path_cleanup(
308  rtems_filesystem_eval_path_context_t *ctx
309)
310{
311  free_location(&ctx->currentloc);
312  rtems_filesystem_instance_unlock(&ctx->startloc->location);
313  rtems_filesystem_global_location_release(ctx->startloc);
314  rtems_filesystem_global_location_release(ctx->rootloc);
315}
316
317void rtems_filesystem_eval_path_cleanup_with_parent(
318  rtems_filesystem_eval_path_context_t *ctx,
319  rtems_filesystem_location_info_t *parentloc
320)
321{
322  free_location(parentloc);
323  rtems_filesystem_eval_path_cleanup(ctx);
324}
325
326void rtems_filesystem_eval_path_restart(
327  rtems_filesystem_eval_path_context_t *ctx,
328  rtems_filesystem_global_location_t **newstartloc_ptr
329)
330{
331  free_location(&ctx->currentloc);
332  rtems_filesystem_instance_unlock(&ctx->startloc->location);
333  rtems_filesystem_global_location_assign(
334    &ctx->startloc,
335    rtems_filesystem_global_location_obtain(newstartloc_ptr)
336  );
337  rtems_filesystem_instance_lock(&ctx->startloc->location);
338  rtems_filesystem_location_clone(&ctx->currentloc, &ctx->startloc->location);
339}
Note: See TracBrowser for help on using the repository browser.