summaryrefslogtreecommitdiffstats
path: root/cpukit/libcsupport/src/sup_fs_eval_path_generic.c
diff options
context:
space:
mode:
Diffstat (limited to 'cpukit/libcsupport/src/sup_fs_eval_path_generic.c')
-rw-r--r--cpukit/libcsupport/src/sup_fs_eval_path_generic.c118
1 files changed, 118 insertions, 0 deletions
diff --git a/cpukit/libcsupport/src/sup_fs_eval_path_generic.c b/cpukit/libcsupport/src/sup_fs_eval_path_generic.c
new file mode 100644
index 0000000000..c789ee4f64
--- /dev/null
+++ b/cpukit/libcsupport/src/sup_fs_eval_path_generic.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2012 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * 82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#if HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include <rtems/libio_.h>
+
+static bool is_fs_root( const rtems_filesystem_location_info_t *loc )
+{
+ const rtems_filesystem_location_info_t *mt_fs_root =
+ &loc->mt_entry->mt_fs_root->location;
+
+ return (*loc->ops->are_nodes_equal_h)( loc, mt_fs_root );
+}
+
+static bool is_eval_path_root(
+ const rtems_filesystem_eval_path_context_t *ctx,
+ const rtems_filesystem_location_info_t *loc
+)
+{
+ const rtems_filesystem_location_info_t *rootloc = &ctx->rootloc->location;
+
+ return loc->mt_entry == rootloc->mt_entry
+ && (*loc->ops->are_nodes_equal_h)( loc, rootloc );
+}
+
+void rtems_filesystem_eval_path_generic(
+ rtems_filesystem_eval_path_context_t *ctx,
+ void *arg,
+ const rtems_filesystem_eval_path_generic_config *config
+)
+{
+ rtems_filesystem_eval_path_generic_status status =
+ RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_CONTINUE;
+
+ while (status == RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_CONTINUE) {
+ const char *token;
+ size_t tokenlen;
+
+ rtems_filesystem_eval_path_get_next_token(ctx, &token, &tokenlen);
+
+ if (tokenlen > 0) {
+ if ((*config->is_directory)(ctx, arg)) {
+ if (rtems_filesystem_is_current_directory(token, tokenlen)) {
+ if (rtems_filesystem_eval_path_has_path(ctx)) {
+ status = (*config->eval_token)(ctx, arg, ".", 1);
+ } else {
+ int eval_flags = rtems_filesystem_eval_path_get_flags(ctx);
+
+ if ((eval_flags & RTEMS_LIBIO_REJECT_TERMINAL_DOT) == 0) {
+ status = (*config->eval_token)(ctx, arg, ".", 1);
+ } else {
+ rtems_filesystem_eval_path_error(ctx, EINVAL);
+ status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_DONE;
+ }
+ }
+ } else if (rtems_filesystem_is_parent_directory(token, tokenlen)) {
+ rtems_filesystem_location_info_t *currentloc =
+ rtems_filesystem_eval_path_get_currentloc( ctx );
+
+ if (is_eval_path_root(ctx, currentloc)) {
+ /* This prevents the escape from a chroot() environment */
+ status = (*config->eval_token)(ctx, arg, ".", 1);
+ } else if (is_fs_root(currentloc)) {
+ if (currentloc->mt_entry->mt_point_node != NULL) {
+ rtems_filesystem_eval_path_put_back_token(ctx);
+ rtems_filesystem_eval_path_restart(
+ ctx,
+ &currentloc->mt_entry->mt_point_node
+ );
+ status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_DONE;
+ } else {
+ /* This is the root file system */
+ status = (*config->eval_token)(ctx, arg, ".", 1);
+ }
+ } else {
+ status = (*config->eval_token)(ctx, arg, "..", 2);
+ }
+ } else {
+ status = (*config->eval_token)(ctx, arg, token, tokenlen);
+ }
+
+ if (status == RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_NO_ENTRY) {
+ if (rtems_filesystem_eval_path_has_path(ctx)) {
+ int eval_flags;
+
+ rtems_filesystem_eval_path_eat_delimiter(ctx);
+ eval_flags = rtems_filesystem_eval_path_get_flags(ctx);
+ if (
+ (eval_flags & RTEMS_LIBIO_ACCEPT_RESIDUAL_DELIMITERS) == 0
+ || rtems_filesystem_eval_path_has_path(ctx)
+ ) {
+ rtems_filesystem_eval_path_error(ctx, ENOENT);
+ }
+ }
+ }
+ } else {
+ rtems_filesystem_eval_path_error(ctx, ENOTDIR);
+ status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_DONE;
+ }
+ } else {
+ status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_DONE;
+ }
+ }
+}