source: rtems/cpukit/libcsupport/src/sup_fs_eval_path.c @ 3b7c123

4.115
Last change on this file since 3b7c123 was 3b7c123, checked in by Sebastian Huber <sebastian.huber@…>, on 03/13/12 at 10:33:51

Filesystem: Reference counting for locations

o A new data structure rtems_filesystem_global_location_t was

introduced to be used for

o the mount point location in the mount table entry,
o the file system root location in the mount table entry,
o the root directory location in the user environment, and
o the current directory location in the user environment.

During the path evaluation global start locations are obtained to
ensure that the current file system instance will be not unmounted in
the meantime.

o The user environment uses now reference counting and is protected

from concurrent access.

o The path evaluation process was completely rewritten and simplified.

The IMFS, RFS, NFS, and DOSFS use now a generic path evaluation
method. Recursive calls in the path evaluation have been replaced
with iteration to avoid stack overflows. Only the evaluation of
symbolic links is recursive. No dynamic memory allocations and
intermediate buffers are used in the high level path evaluation. No
global locks are held during the file system instance specific path
evaluation process.

o Recursive symbolic link evaluation is now limited by

RTEMS_FILESYSTEM_SYMLOOP_MAX. Applications can retrieve this value
via sysconf().

o The device file system (devFS) uses now no global variables and

allocation from the workspace. Node names are allocated from the
heap.

o The upper layer lseek() performs now some parameter checks.
o The upper layer ftruncate() performs now some parameter checks.
o unmask() is now restricted to the RWX flags and protected from

concurrent access.

o The fchmod_h and rmnod_h file system node handlers are now a file

system operation.

o The unlink_h operation has been removed. All nodes are now destroyed

with the rmnod_h operation.

o New lock_h, unlock_h, clonenod_h, and are_nodes_equal_h file system

operations.

o The path evaluation and file system operations are now protected by

per file system instance lock and unlock operations.

o Fix and test file descriptor duplicate in fcntl().
o New test fstests/fsnofs01.

  • Property mode set to 100644
File size: 7.7 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  struct stat st;
72  int rv;
73
74  st.st_mode = 0;
75  st.st_uid = 0;
76  st.st_gid = 0;
77  rv = (*currentloc->handlers->fstat_h)(currentloc, &st);
78  if (rv == 0) {
79    bool access_ok = rtems_filesystem_check_access(
80      eval_flags,
81      st.st_mode,
82      st.st_uid,
83      st.st_gid
84    );
85
86    if (!access_ok) {
87      rtems_filesystem_eval_path_error(ctx, EACCES);
88    }
89  } else {
90    rtems_filesystem_eval_path_error(ctx, 0);
91  }
92}
93
94void rtems_filesystem_eval_path_continue(
95  rtems_filesystem_eval_path_context_t *ctx
96)
97{
98  int eval_flags;
99
100  while (ctx->pathlen > 0) {
101    (*ctx->currentloc.ops->eval_path_h)(ctx);
102  }
103
104  eval_flags = rtems_filesystem_eval_path_get_flags(ctx);
105  if (rtems_filesystem_eval_path_has_token(ctx)) {
106    bool make = (eval_flags & RTEMS_LIBIO_MAKE) != 0;
107
108    if (make) {
109      check_access(ctx, RTEMS_LIBIO_PERMS_WRITE);
110    } else {
111      rtems_filesystem_eval_path_error(ctx, ENOENT);
112    }
113  } else {
114    bool exclusive = (eval_flags & RTEMS_LIBIO_EXCLUSIVE) != 0;
115
116    if (!exclusive) {
117      check_access(ctx, ctx->flags);
118    } else {
119      rtems_filesystem_eval_path_error(ctx, EEXIST);
120    }
121  }
122}
123
124static rtems_filesystem_location_info_t *
125eval_path_start(
126  rtems_filesystem_eval_path_context_t *ctx,
127  const char *path,
128  size_t pathlen,
129  int eval_flags,
130  rtems_filesystem_global_location_t *const *global_root_ptr,
131  rtems_filesystem_global_location_t *const *global_current_ptr
132)
133{
134  memset(ctx, 0, sizeof(*ctx));
135
136  ctx->path = path;
137  ctx->pathlen = pathlen;
138  ctx->flags = eval_flags;
139
140  set_startloc(ctx, global_root_ptr, global_current_ptr);
141
142  rtems_filesystem_instance_lock(&ctx->startloc->location);
143
144  rtems_filesystem_location_clone(
145    &ctx->currentloc,
146    &ctx->startloc->location
147  );
148
149  rtems_filesystem_eval_path_continue(ctx);
150
151  return &ctx->currentloc;
152}
153
154rtems_filesystem_location_info_t *
155rtems_filesystem_eval_path_start_with_root_and_current(
156  rtems_filesystem_eval_path_context_t *ctx,
157  const char *path,
158  int eval_flags,
159  rtems_filesystem_global_location_t *const *global_root_ptr,
160  rtems_filesystem_global_location_t *const *global_current_ptr
161)
162{
163  return eval_path_start(
164    ctx,
165    path,
166    strlen(path),
167    eval_flags,
168    global_root_ptr,
169    global_current_ptr
170  );
171}
172
173rtems_filesystem_location_info_t *
174rtems_filesystem_eval_path_start(
175  rtems_filesystem_eval_path_context_t *ctx,
176  const char *path,
177  int eval_flags
178)
179{
180  return rtems_filesystem_eval_path_start_with_root_and_current(
181    ctx,
182    path,
183    eval_flags,
184    &rtems_filesystem_root,
185    &rtems_filesystem_current
186  );
187}
188
189rtems_filesystem_location_info_t *
190rtems_filesystem_eval_path_start_with_parent(
191  rtems_filesystem_eval_path_context_t *ctx,
192  const char *path,
193  int eval_flags,
194  rtems_filesystem_location_info_t *parentloc,
195  int parent_eval_flags
196)
197{
198  size_t pathlen = strlen(path);
199  const char *parentpath = path;
200  size_t parentpathlen = get_parentpathlen(path, pathlen);
201  const char *name = NULL;
202  size_t namelen = 0;
203  const rtems_filesystem_location_info_t *currentloc = NULL;
204
205  if (pathlen > 0) {
206    if (parentpathlen == 0) {
207      parentpath = ".";
208      parentpathlen = 1;
209      name = path;
210      namelen = pathlen;
211    } else {
212      name = path + parentpathlen;
213      namelen = pathlen - parentpathlen;
214    }
215  }
216
217  currentloc = eval_path_start(
218    ctx,
219    parentpath,
220    parentpathlen,
221    parent_eval_flags,
222    &rtems_filesystem_root,
223    &rtems_filesystem_current
224  );
225
226  rtems_filesystem_location_clone(parentloc, currentloc);
227
228  ctx->path = name;
229  ctx->pathlen = namelen;
230  ctx->flags = eval_flags;
231
232  rtems_filesystem_eval_path_continue(ctx);
233
234  return &ctx->currentloc;
235}
236
237void rtems_filesystem_eval_path_recursive(
238  rtems_filesystem_eval_path_context_t *ctx,
239  const char *path,
240  size_t pathlen
241)
242{
243  if (pathlen > 0) {
244    if (ctx->recursionlevel < RTEMS_FILESYSTEM_SYMLOOP_MAX) {
245      const char *saved_path = ctx->path;
246      size_t saved_pathlen = ctx->pathlen;
247
248      if (rtems_filesystem_is_delimiter(path [0])) {
249        rtems_filesystem_eval_path_restart(ctx, &ctx->rootloc);
250      }
251
252      ctx->path = path;
253      ctx->pathlen = pathlen;
254
255      ++ctx->recursionlevel;
256      while (ctx->pathlen > 0) {
257        (*ctx->currentloc.ops->eval_path_h)(ctx);
258      }
259      --ctx->recursionlevel;
260
261      ctx->path = saved_path;
262      ctx->pathlen = saved_pathlen;
263    } else {
264      rtems_filesystem_eval_path_error(ctx, ELOOP);
265    }
266  } else {
267    rtems_filesystem_eval_path_error(ctx, ENOENT);
268  }
269}
270
271void rtems_filesystem_eval_path_error(
272  rtems_filesystem_eval_path_context_t *ctx,
273  int eno
274)
275{
276  ctx->path = NULL;
277  ctx->pathlen = 0;
278  ctx->token = NULL;
279  ctx->tokenlen = 0;
280
281  if (!rtems_filesystem_location_is_null(&ctx->currentloc)) {
282    if (eno != 0) {
283      errno = eno;
284    }
285
286    rtems_filesystem_location_detach(&ctx->currentloc);
287  }
288}
289
290static void free_location(rtems_filesystem_location_info_t *loc)
291{
292  rtems_filesystem_mt_entry_declare_lock_context(lock_context);
293
294  (*loc->ops->freenod_h)(loc);
295
296  rtems_filesystem_mt_entry_lock(lock_context);
297  rtems_chain_extract_unprotected(&loc->mt_entry_node);
298  rtems_filesystem_mt_entry_unlock(lock_context);
299}
300
301void rtems_filesystem_eval_path_cleanup(
302  rtems_filesystem_eval_path_context_t *ctx
303)
304{
305  free_location(&ctx->currentloc);
306  rtems_filesystem_instance_unlock(&ctx->startloc->location);
307  rtems_filesystem_global_location_release(ctx->startloc);
308  rtems_filesystem_global_location_release(ctx->rootloc);
309}
310
311void rtems_filesystem_eval_path_cleanup_with_parent(
312  rtems_filesystem_eval_path_context_t *ctx,
313  rtems_filesystem_location_info_t *parentloc
314)
315{
316  free_location(parentloc);
317  rtems_filesystem_eval_path_cleanup(ctx);
318}
319
320void rtems_filesystem_eval_path_restart(
321  rtems_filesystem_eval_path_context_t *ctx,
322  rtems_filesystem_global_location_t **newstartloc_ptr
323)
324{
325  free_location(&ctx->currentloc);
326  rtems_filesystem_instance_unlock(&ctx->startloc->location);
327  rtems_filesystem_global_location_assign(
328    &ctx->startloc,
329    rtems_filesystem_global_location_obtain(newstartloc_ptr)
330  );
331  rtems_filesystem_instance_lock(&ctx->startloc->location);
332  rtems_filesystem_location_clone(&ctx->currentloc, &ctx->startloc->location);
333}
Note: See TracBrowser for help on using the repository browser.