Back to home page

LXR

 
 

    


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

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  *  @file
0005  *
0006  *  @brief RTEMS File Sysyem Path Eval Support
0007  *  @ingroup LibIOInternal
0008  */
0009 
0010 /*
0011  * Copyright (c) 2012 embedded brains GmbH & Co. KG
0012  *
0013  * Redistribution and use in source and binary forms, with or without
0014  * modification, are permitted provided that the following conditions
0015  * are met:
0016  * 1. Redistributions of source code must retain the above copyright
0017  *    notice, this list of conditions and the following disclaimer.
0018  * 2. Redistributions in binary form must reproduce the above copyright
0019  *    notice, this list of conditions and the following disclaimer in the
0020  *    documentation and/or other materials provided with the distribution.
0021  *
0022  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0023  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0024  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0025  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0026  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0027  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0028  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0029  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0030  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0031  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0032  * POSSIBILITY OF SUCH DAMAGE.
0033  */
0034 
0035 #ifdef HAVE_CONFIG_H
0036 #include "config.h"
0037 #endif
0038 
0039 #include <rtems/libio_.h>
0040 
0041 #include <string.h>
0042 
0043 static size_t get_parentpathlen(const char *path, size_t pathlen)
0044 {
0045   while (pathlen > 0) {
0046     size_t i = pathlen - 1;
0047 
0048     if (rtems_filesystem_is_delimiter(path [i])) {
0049       return pathlen;
0050     }
0051 
0052     pathlen = i;
0053   }
0054 
0055   return 0;
0056 }
0057 
0058 static void set_startloc(
0059   rtems_filesystem_eval_path_context_t *ctx,
0060   rtems_filesystem_global_location_t *const *global_root_ptr,
0061   rtems_filesystem_global_location_t *const *global_current_ptr
0062 )
0063 {
0064   if (ctx->pathlen > 0) {
0065     char c = ctx->path [0];
0066 
0067     ctx->rootloc = rtems_filesystem_global_location_obtain(global_root_ptr);
0068 
0069     if (rtems_filesystem_is_delimiter(c)) {
0070       ++ctx->path;
0071       --ctx->pathlen;
0072       ctx->startloc = rtems_filesystem_global_location_obtain(
0073         &ctx->rootloc
0074       );
0075     } else {
0076       ctx->startloc = rtems_filesystem_global_location_obtain(
0077         global_current_ptr
0078       );
0079     }
0080   } else {
0081     ctx->rootloc = rtems_filesystem_global_location_obtain_null();
0082     ctx->startloc = rtems_filesystem_global_location_obtain_null();
0083     errno = ENOENT;
0084   }
0085 }
0086 
0087 static void check_access(
0088   rtems_filesystem_eval_path_context_t *ctx,
0089   int eval_flags
0090 )
0091 {
0092   const rtems_filesystem_location_info_t *currentloc = &ctx->currentloc;
0093   const rtems_filesystem_mount_table_entry_t *mt_entry = currentloc->mt_entry;
0094 
0095   if ((eval_flags & RTEMS_FS_PERMS_WRITE) == 0 || mt_entry->writeable) {
0096     struct stat st;
0097     int rv;
0098 
0099     st.st_mode = 0;
0100     st.st_uid = 0;
0101     st.st_gid = 0;
0102     rv = (*currentloc->handlers->fstat_h)(currentloc, &st);
0103     if (rv == 0) {
0104       bool access_ok = rtems_filesystem_check_access(
0105         eval_flags,
0106         st.st_mode,
0107         st.st_uid,
0108         st.st_gid
0109       );
0110 
0111       if (!access_ok) {
0112         rtems_filesystem_eval_path_error(ctx, EACCES);
0113       }
0114     } else {
0115       rtems_filesystem_eval_path_error(ctx, 0);
0116     }
0117   } else {
0118     rtems_filesystem_eval_path_error(ctx, EROFS);
0119   }
0120 }
0121 
0122 void rtems_filesystem_eval_path_continue(
0123   rtems_filesystem_eval_path_context_t *ctx
0124 )
0125 {
0126   int eval_flags;
0127 
0128   while (ctx->pathlen > 0) {
0129     (*ctx->currentloc.mt_entry->ops->eval_path_h)(ctx);
0130   }
0131 
0132   eval_flags = rtems_filesystem_eval_path_get_flags(ctx);
0133   if (rtems_filesystem_eval_path_has_token(ctx)) {
0134     bool make = (eval_flags & RTEMS_FS_MAKE) != 0;
0135 
0136     if (make) {
0137       check_access(ctx, RTEMS_FS_PERMS_WRITE);
0138     } else {
0139       rtems_filesystem_eval_path_error(ctx, ENOENT);
0140     }
0141   } else {
0142     bool exclusive = (eval_flags & RTEMS_FS_EXCLUSIVE) != 0;
0143 
0144     if (!exclusive) {
0145       check_access(ctx, ctx->flags);
0146     } else {
0147       rtems_filesystem_eval_path_error(ctx, EEXIST);
0148     }
0149   }
0150 }
0151 
0152 rtems_filesystem_location_info_t *
0153 rtems_filesystem_eval_path_start_with_root_and_current(
0154   rtems_filesystem_eval_path_context_t *ctx,
0155   const char *path,
0156   size_t pathlen,
0157   int eval_flags,
0158   rtems_filesystem_global_location_t *const *global_root_ptr,
0159   rtems_filesystem_global_location_t *const *global_current_ptr
0160 )
0161 {
0162   memset(ctx, 0, sizeof(*ctx));
0163 
0164   ctx->path = path;
0165   ctx->pathlen = pathlen;
0166   ctx->flags = eval_flags;
0167 
0168   set_startloc(ctx, global_root_ptr, global_current_ptr);
0169 
0170   rtems_filesystem_instance_lock(&ctx->startloc->location);
0171 
0172   rtems_filesystem_location_clone(
0173     &ctx->currentloc,
0174     &ctx->startloc->location
0175   );
0176 
0177   rtems_filesystem_eval_path_continue(ctx);
0178 
0179   return &ctx->currentloc;
0180 }
0181 
0182 rtems_filesystem_location_info_t *
0183 rtems_filesystem_eval_path_start(
0184   rtems_filesystem_eval_path_context_t *ctx,
0185   const char *path,
0186   int eval_flags
0187 )
0188 {
0189   return rtems_filesystem_eval_path_start_with_root_and_current(
0190     ctx,
0191     path,
0192     strlen(path),
0193     eval_flags,
0194     &rtems_filesystem_root,
0195     &rtems_filesystem_current
0196   );
0197 }
0198 
0199 rtems_filesystem_location_info_t *
0200 rtems_filesystem_eval_path_start_with_parent(
0201   rtems_filesystem_eval_path_context_t *ctx,
0202   const char *path,
0203   int eval_flags,
0204   rtems_filesystem_location_info_t *parentloc,
0205   int parent_eval_flags
0206 )
0207 {
0208   size_t pathlen = strlen(path);
0209   const char *parentpath = path;
0210   size_t parentpathlen = get_parentpathlen(path, pathlen);
0211   const char *name = NULL;
0212   size_t namelen = 0;
0213   const rtems_filesystem_location_info_t *currentloc = NULL;
0214 
0215   if (pathlen > 0) {
0216     if (parentpathlen == 0) {
0217       parentpath = ".";
0218       parentpathlen = 1;
0219       name = path;
0220       namelen = pathlen;
0221     } else {
0222       name = path + parentpathlen;
0223       namelen = pathlen - parentpathlen;
0224     }
0225   }
0226 
0227   currentloc = rtems_filesystem_eval_path_start_with_root_and_current(
0228     ctx,
0229     parentpath,
0230     parentpathlen,
0231     parent_eval_flags,
0232     &rtems_filesystem_root,
0233     &rtems_filesystem_current
0234   );
0235 
0236   rtems_filesystem_location_clone(parentloc, currentloc);
0237 
0238   ctx->path = name;
0239   ctx->pathlen = namelen;
0240   ctx->flags = eval_flags;
0241 
0242   rtems_filesystem_eval_path_continue(ctx);
0243 
0244   return &ctx->currentloc;
0245 }
0246 
0247 void rtems_filesystem_eval_path_recursive(
0248   rtems_filesystem_eval_path_context_t *ctx,
0249   const char *path,
0250   size_t pathlen
0251 )
0252 {
0253   if (pathlen > 0) {
0254     if (ctx->recursionlevel < RTEMS_FILESYSTEM_SYMLOOP_MAX) {
0255       const char *saved_path = ctx->path;
0256       size_t saved_pathlen = ctx->pathlen;
0257 
0258       if (rtems_filesystem_is_delimiter(path [0])) {
0259         rtems_filesystem_eval_path_restart(ctx, &ctx->rootloc);
0260       }
0261 
0262       ctx->path = path;
0263       ctx->pathlen = pathlen;
0264 
0265       ++ctx->recursionlevel;
0266       while (ctx->pathlen > 0) {
0267         (*ctx->currentloc.mt_entry->ops->eval_path_h)(ctx);
0268       }
0269       --ctx->recursionlevel;
0270 
0271       ctx->path = saved_path;
0272       ctx->pathlen = saved_pathlen;
0273     } else {
0274       rtems_filesystem_eval_path_error(ctx, ELOOP);
0275     }
0276   } else {
0277     rtems_filesystem_eval_path_error(ctx, ENOENT);
0278   }
0279 }
0280 
0281 void rtems_filesystem_eval_path_error(
0282   rtems_filesystem_eval_path_context_t *ctx,
0283   int eno
0284 )
0285 {
0286   ctx->path = NULL;
0287   ctx->pathlen = 0;
0288   ctx->token = NULL;
0289   ctx->tokenlen = 0;
0290 
0291   if (!rtems_filesystem_location_is_null(&ctx->currentloc)) {
0292     if (eno != 0) {
0293       errno = eno;
0294     }
0295 
0296     rtems_filesystem_location_detach(&ctx->currentloc);
0297   }
0298 }
0299 
0300 static void free_location(rtems_filesystem_location_info_t *loc)
0301 {
0302   rtems_filesystem_mt_entry_declare_lock_context(lock_context);
0303 
0304   (*loc->mt_entry->ops->freenod_h)(loc);
0305 
0306   rtems_filesystem_mt_entry_lock(lock_context);
0307   rtems_chain_extract_unprotected(&loc->mt_entry_node);
0308   rtems_filesystem_mt_entry_unlock(lock_context);
0309 }
0310 
0311 void rtems_filesystem_eval_path_cleanup(
0312   rtems_filesystem_eval_path_context_t *ctx
0313 )
0314 {
0315   free_location(&ctx->currentloc);
0316   rtems_filesystem_instance_unlock(&ctx->startloc->location);
0317   rtems_filesystem_global_location_release(ctx->startloc, false);
0318   rtems_filesystem_global_location_release(ctx->rootloc, false);
0319 }
0320 
0321 void rtems_filesystem_eval_path_cleanup_with_parent(
0322   rtems_filesystem_eval_path_context_t *ctx,
0323   rtems_filesystem_location_info_t *parentloc
0324 )
0325 {
0326   free_location(parentloc);
0327   rtems_filesystem_eval_path_cleanup(ctx);
0328 }
0329 
0330 void rtems_filesystem_eval_path_restart(
0331   rtems_filesystem_eval_path_context_t *ctx,
0332   rtems_filesystem_global_location_t **newstartloc_ptr
0333 )
0334 {
0335   free_location(&ctx->currentloc);
0336   rtems_filesystem_instance_unlock(&ctx->startloc->location);
0337   rtems_filesystem_global_location_assign(
0338     &ctx->startloc,
0339     rtems_filesystem_global_location_obtain(newstartloc_ptr)
0340   );
0341   rtems_filesystem_instance_lock(&ctx->startloc->location);
0342   rtems_filesystem_location_clone(&ctx->currentloc, &ctx->startloc->location);
0343 }