Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:17

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup IMFS
0007  *
0008  * @brief Evaluation IMFS Node Support
0009  */
0010 
0011 /*
0012  *  COPYRIGHT (c) 1989-1999.
0013  *  On-Line Applications Research Corporation (OAR).
0014  *
0015  *  Modifications to support reference counting in the file system are
0016  *  Copyright (c) 2012 embedded brains GmbH & Co. KG
0017  *
0018  * Redistribution and use in source and binary forms, with or without
0019  * modification, are permitted provided that the following conditions
0020  * are met:
0021  * 1. Redistributions of source code must retain the above copyright
0022  *    notice, this list of conditions and the following disclaimer.
0023  * 2. Redistributions in binary form must reproduce the above copyright
0024  *    notice, this list of conditions and the following disclaimer in the
0025  *    documentation and/or other materials provided with the distribution.
0026  *
0027  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0028  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0029  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0030  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0031  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0032  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0033  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0034  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0035  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0036  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0037  * POSSIBILITY OF SUCH DAMAGE.
0038  */
0039 
0040 #ifdef HAVE_CONFIG_H
0041 #include "config.h"
0042 #endif
0043 
0044 #include <rtems/imfs.h>
0045 
0046 #include <string.h>
0047 
0048 static bool IMFS_eval_is_directory(
0049   rtems_filesystem_eval_path_context_t *ctx,
0050   void *arg
0051 )
0052 {
0053   rtems_filesystem_location_info_t *currentloc =
0054     rtems_filesystem_eval_path_get_currentloc( ctx );
0055   IMFS_jnode_t *node = currentloc->node_access;
0056 
0057   return IMFS_is_directory( node );
0058 }
0059 
0060 static IMFS_jnode_t *IMFS_search_in_directory(
0061   IMFS_directory_t *dir,
0062   const char *token,
0063   size_t tokenlen
0064 )
0065 {
0066   if ( rtems_filesystem_is_current_directory( token, tokenlen ) ) {
0067     return &dir->Node;
0068   } else {
0069     if ( rtems_filesystem_is_parent_directory( token, tokenlen ) ) {
0070       return dir->Node.Parent;
0071     } else {
0072       rtems_chain_control *entries = &dir->Entries;
0073       rtems_chain_node *current = rtems_chain_first( entries );
0074       rtems_chain_node *tail = rtems_chain_tail( entries );
0075 
0076       while ( current != tail ) {
0077         IMFS_jnode_t *entry = (IMFS_jnode_t *) current;
0078         bool match = entry->namelen == tokenlen
0079           && memcmp( entry->name, token, tokenlen ) == 0;
0080 
0081         if ( match ) {
0082           return entry;
0083         }
0084 
0085         current = rtems_chain_next( current );
0086       }
0087 
0088       return NULL;
0089     }
0090   }
0091 }
0092 
0093 static rtems_filesystem_global_location_t **IMFS_is_mount_point(
0094   IMFS_jnode_t *node,
0095   mode_t mode
0096 )
0097 {
0098   rtems_filesystem_global_location_t **fs_root_ptr = NULL;
0099 
0100   if ( S_ISDIR( mode ) ) {
0101     IMFS_directory_t *dir = (IMFS_directory_t *) node;
0102 
0103     if ( dir->mt_fs != NULL ) {
0104       fs_root_ptr = &dir->mt_fs->mt_fs_root;
0105     }
0106   }
0107 
0108   return fs_root_ptr;
0109 }
0110 
0111 static rtems_filesystem_eval_path_generic_status IMFS_eval_token(
0112   rtems_filesystem_eval_path_context_t *ctx,
0113   void *arg,
0114   const char *token,
0115   size_t tokenlen
0116 )
0117 {
0118   rtems_filesystem_eval_path_generic_status status =
0119     RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_DONE;
0120   rtems_filesystem_location_info_t *currentloc =
0121     rtems_filesystem_eval_path_get_currentloc( ctx );
0122   IMFS_directory_t *dir = currentloc->node_access;
0123   bool access_ok = rtems_filesystem_eval_path_check_access(
0124     ctx,
0125     RTEMS_FS_PERMS_EXEC,
0126     dir->Node.st_mode,
0127     dir->Node.st_uid,
0128     dir->Node.st_gid
0129   );
0130 
0131   if ( access_ok ) {
0132     IMFS_jnode_t *entry = IMFS_search_in_directory( dir, token, tokenlen );
0133 
0134     if ( entry != NULL ) {
0135       bool terminal = !rtems_filesystem_eval_path_has_path( ctx );
0136       int eval_flags = rtems_filesystem_eval_path_get_flags( ctx );
0137       bool follow_hard_link = (eval_flags & RTEMS_FS_FOLLOW_HARD_LINK) != 0;
0138       bool follow_sym_link = (eval_flags & RTEMS_FS_FOLLOW_SYM_LINK) != 0;
0139       mode_t mode = entry->st_mode;
0140 
0141       rtems_filesystem_eval_path_clear_token( ctx );
0142 
0143       if ( IMFS_is_hard_link( mode ) && ( follow_hard_link || !terminal ) ) {
0144         const IMFS_link_t *hard_link = (const IMFS_link_t *) entry;
0145 
0146         entry = hard_link->link_node;
0147       }
0148 
0149       if ( S_ISLNK( mode ) && ( follow_sym_link || !terminal ) ) {
0150         const IMFS_sym_link_t *sym_link = (const IMFS_sym_link_t *) entry;
0151         const char *target = sym_link->name;
0152 
0153         rtems_filesystem_eval_path_recursive( ctx, target, strlen( target ) );
0154       } else {
0155         rtems_filesystem_global_location_t **fs_root_ptr =
0156           IMFS_is_mount_point( entry, mode );
0157 
0158         if ( fs_root_ptr == NULL ) {
0159           --dir->Node.reference_count;
0160           ++entry->reference_count;
0161           currentloc->node_access = entry;
0162           currentloc->node_access_2 =
0163             IMFS_generic_get_context_by_node( entry );
0164           IMFS_Set_handlers( currentloc );
0165 
0166           if ( !terminal ) {
0167             status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_CONTINUE;
0168           }
0169         } else {
0170           access_ok = rtems_filesystem_eval_path_check_access(
0171             ctx,
0172             RTEMS_FS_PERMS_EXEC,
0173             entry->st_mode,
0174             entry->st_uid,
0175             entry->st_gid
0176           );
0177           if ( access_ok ) {
0178             rtems_filesystem_eval_path_restart( ctx, fs_root_ptr );
0179           }
0180         }
0181       }
0182     } else {
0183       status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_NO_ENTRY;
0184     }
0185   }
0186 
0187   return status;
0188 }
0189 
0190 static const rtems_filesystem_eval_path_generic_config IMFS_eval_config = {
0191   .is_directory = IMFS_eval_is_directory,
0192   .eval_token = IMFS_eval_token
0193 };
0194 
0195 void IMFS_eval_path( rtems_filesystem_eval_path_context_t *ctx )
0196 {
0197   rtems_filesystem_eval_path_generic( ctx, NULL, &IMFS_eval_config );
0198 }