File indexing completed on 2025-05-11 08:24:15
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
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 }