Back to home page

LXR

 
 

    


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

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @brief LibIO Internal Interface
0007  *
0008  * This file is the libio internal interface.
0009  */
0010 
0011 /*
0012  * COPYRIGHT (C) 1989, 2021 On-Line Applications Research Corporation (OAR).
0013  *
0014  * Modifications to support reference counting in the file system are
0015  * Copyright (c) 2012 embedded brains GmbH & Co. KG
0016  *
0017  * Redistribution and use in source and binary forms, with or without
0018  * modification, are permitted provided that the following conditions
0019  * are met:
0020  * 1. Redistributions of source code must retain the above copyright
0021  *    notice, this list of conditions and the following disclaimer.
0022  * 2. Redistributions in binary form must reproduce the above copyright
0023  *    notice, this list of conditions and the following disclaimer in the
0024  *    documentation and/or other materials provided with the distribution.
0025  *
0026  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0027  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0028  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0029  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0030  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0031  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0032  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0033  * * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0034  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0035  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0036  * POSSIBILITY OF SUCH DAMAGE.
0037  */
0038 
0039 #ifndef _RTEMS_RTEMS_LIBIO__H
0040 #define _RTEMS_RTEMS_LIBIO__H
0041 
0042 #include <sys/uio.h>
0043 #include <errno.h>
0044 #include <limits.h>
0045 #include <pthread.h>
0046 
0047 #include <rtems.h>
0048 #include <rtems/libio.h>
0049 #include <rtems/seterr.h>
0050 #include <rtems/score/assert.h>
0051 #include <rtems/score/timespec.h>
0052 
0053 #ifdef __cplusplus
0054 extern "C" {
0055 #endif
0056 
0057 /**
0058  * @defgroup LibIOInternal IO Internal Library
0059  *
0060  * @ingroup LibIO
0061  *
0062  * @brief Internal IO library API and implementation.
0063  *
0064  */
0065 /**@{**/
0066 
0067 #define RTEMS_FILESYSTEM_SYMLOOP_MAX 32
0068 
0069 /*
0070  * Not defined in newlib so provide here. Users should use dup2 and
0071  * not this non-portable fcntl command. Provided here to allow the
0072  * RTEMS implementation to work.
0073  */
0074 #define F_DUP2FD 20
0075 
0076 /*
0077  *  File descriptor Table Information
0078  */
0079 
0080 extern const uint32_t rtems_libio_number_iops;
0081 extern rtems_libio_t rtems_libio_iops[];
0082 extern void *rtems_libio_iop_free_head;
0083 extern void **rtems_libio_iop_free_tail;
0084 
0085 extern const rtems_filesystem_file_handlers_r rtems_filesystem_null_handlers;
0086 
0087 extern rtems_filesystem_mount_table_entry_t rtems_filesystem_null_mt_entry;
0088 
0089 /**
0090  * @brief The global null location.
0091  *
0092  * Every operation and the open and fstat handlers of this location returns an
0093  * error status.  The errno is not touched by these operations and handlers.
0094  * The purpose of this location is to deliver the error return status for a
0095  * previous error condition which must set the errno accordingly.
0096  *
0097  * The usage of this null location instead of the NULL pointer eliminates
0098  * a lot of branches.
0099  *
0100  * The user environment root and current directory are statically initialized
0101  * with the null location.  Due to that all file system services are in a
0102  * defined state even if no root file system was mounted.
0103  */
0104 extern rtems_filesystem_global_location_t rtems_filesystem_global_location_null;
0105 
0106 /**
0107  * @brief Sets the specified flags in the iop.
0108  *
0109  * @param[in] iop The iop.
0110  * @param[in] set The flags to set.
0111  *
0112  * @return The previous flags.
0113  */
0114 static inline unsigned int rtems_libio_iop_flags_set(
0115   rtems_libio_t *iop,
0116   unsigned int   set
0117 )
0118 {
0119   return _Atomic_Fetch_or_uint( &iop->flags, set, ATOMIC_ORDER_RELAXED );
0120 }
0121 
0122 /**
0123  * @brief Clears the specified flags in the iop.
0124  *
0125  * @param[in] iop The iop.
0126  * @param[in] clear The flags to clear.
0127  *
0128  * @return The previous flags.
0129  */
0130 static inline unsigned int rtems_libio_iop_flags_clear(
0131   rtems_libio_t *iop,
0132   unsigned int   clear
0133 )
0134 {
0135   return _Atomic_Fetch_and_uint( &iop->flags, ~clear, ATOMIC_ORDER_RELAXED );
0136 }
0137 
0138 /**
0139  * @brief Maps a file descriptor to the iop.
0140  *
0141  * The file descriptor must be a valid index into the iop table.
0142  *
0143  * @param[in] fd The file descriptor.
0144  *
0145  * @return The iop corresponding to the specified file descriptor.
0146  */
0147 static inline rtems_libio_t *rtems_libio_iop( int fd )
0148 {
0149   return &rtems_libio_iops[ fd ];
0150 }
0151 
0152 /**
0153  * @brief Holds a refernece to the iop.
0154  *
0155  * @param[in] iop The iop.
0156  *
0157  * @return The flags corresponding to the specified iop.
0158  */
0159 static inline unsigned int rtems_libio_iop_hold( rtems_libio_t *iop )
0160 {
0161   return _Atomic_Fetch_add_uint(
0162     &iop->flags,
0163     LIBIO_FLAGS_REFERENCE_INC,
0164     ATOMIC_ORDER_ACQUIRE
0165   );
0166 }
0167 
0168 /**
0169  * @brief Drops a refernece to the iop.
0170  *
0171  * @param[in] iop The iop.
0172  */
0173 static inline void rtems_libio_iop_drop( rtems_libio_t *iop )
0174 {
0175 #if defined(RTEMS_DEBUG)
0176   unsigned int flags;
0177   bool         success;
0178 
0179   flags = _Atomic_Load_uint( &iop->flags, ATOMIC_ORDER_RELAXED );
0180 
0181   do {
0182     unsigned int desired;
0183 
0184     _Assert( flags >= LIBIO_FLAGS_REFERENCE_INC );
0185 
0186     desired = flags - LIBIO_FLAGS_REFERENCE_INC;
0187     success = _Atomic_Compare_exchange_uint(
0188       &iop->flags,
0189       &flags,
0190       desired,
0191       ATOMIC_ORDER_RELEASE,
0192       ATOMIC_ORDER_RELAXED
0193     );
0194   } while ( !success );
0195 #else
0196   _Atomic_Fetch_sub_uint(
0197     &iop->flags,
0198     LIBIO_FLAGS_REFERENCE_INC,
0199     ATOMIC_ORDER_RELEASE
0200   );
0201 #endif
0202 }
0203 
0204 /*
0205  *  rtems_libio_iop_to_descriptor
0206  *
0207  *  Macro to convert an internal file descriptor pointer (iop) into
0208  *  the integer file descriptor used by the "section 2" system calls.
0209  */
0210 
0211 #define rtems_libio_iop_to_descriptor(_iop) \
0212   ((_iop) - &rtems_libio_iops[0])
0213 
0214 /*
0215  *  rtems_libio_check_is_open
0216  *
0217  *  Macro to check if a file descriptor is actually open.
0218  */
0219 
0220 #define rtems_libio_check_is_open(_iop) \
0221   do {                                               \
0222       if ((rtems_libio_iop_flags(_iop) & LIBIO_FLAGS_OPEN) == 0) { \
0223           errno = EBADF;                             \
0224           return -1;                                 \
0225       }                                              \
0226   } while (0)
0227 
0228 /**
0229  * @brief Macro to get the iop for the specified file descriptor.
0230  *
0231  * Checks that the file descriptor is in the valid range and open.
0232  */
0233 #define LIBIO_GET_IOP( _fd, _iop ) \
0234   do { \
0235     unsigned int _flags; \
0236     if ( (uint32_t) ( _fd ) >= rtems_libio_number_iops ) { \
0237       rtems_set_errno_and_return_minus_one( EBADF ); \
0238     } \
0239     _iop = rtems_libio_iop( _fd ); \
0240     _flags = rtems_libio_iop_hold( _iop ); \
0241     if ( ( _flags & LIBIO_FLAGS_OPEN ) == 0 ) { \
0242       rtems_libio_iop_drop( _iop ); \
0243       rtems_set_errno_and_return_minus_one( EBADF ); \
0244     } \
0245   } while ( 0 )
0246 
0247 /**
0248  * @brief Macro to get the iop for the specified file descriptor with access
0249  * flags and error.
0250  *
0251  * Checks that the file descriptor is in the valid range and open.
0252  */
0253 #define LIBIO_GET_IOP_WITH_ACCESS( _fd, _iop, _access_flags, _access_error ) \
0254   do { \
0255     unsigned int _flags; \
0256     unsigned int _mandatory; \
0257     if ( (uint32_t) ( _fd ) >= rtems_libio_number_iops ) { \
0258       rtems_set_errno_and_return_minus_one( EBADF ); \
0259     } \
0260     _iop = rtems_libio_iop( _fd ); \
0261     _flags = rtems_libio_iop_hold( _iop ); \
0262     _mandatory = LIBIO_FLAGS_OPEN | ( _access_flags ); \
0263     if ( ( _flags & _mandatory ) != _mandatory ) { \
0264       int _error; \
0265       rtems_libio_iop_drop( _iop ); \
0266       if ( ( _flags & LIBIO_FLAGS_OPEN ) == 0 ) { \
0267         _error = EBADF; \
0268       } else { \
0269         _error = _access_error; \
0270       } \
0271       rtems_set_errno_and_return_minus_one( _error ); \
0272     } \
0273   } while ( 0 )
0274 
0275 /*
0276  *  rtems_libio_check_buffer
0277  *
0278  *  Macro to check if a buffer pointer is valid.
0279  */
0280 
0281 #define rtems_libio_check_buffer(_buffer) \
0282   do {                                    \
0283       if ((_buffer) == 0) {               \
0284           errno = EINVAL;                 \
0285           return -1;                      \
0286       }                                   \
0287   } while (0)
0288 
0289 /*
0290  *  rtems_libio_check_count
0291  *
0292  *  Macro to check if a count or length is valid.
0293  */
0294 
0295 #define rtems_libio_check_count(_count) \
0296   do {                                  \
0297       if ((_count) == 0) {              \
0298           return 0;                     \
0299       }                                 \
0300   } while (0)
0301 
0302 /**
0303  * @brief Clones a node.
0304  *
0305  * The caller must hold the file system instance lock.
0306  *
0307  * @param[out] clone The cloned location.
0308  * @param[in] master The master location.
0309  *
0310  * @see rtems_filesystem_instance_lock().
0311  */
0312 void rtems_filesystem_location_clone(
0313   rtems_filesystem_location_info_t *clone,
0314   const rtems_filesystem_location_info_t *master
0315 );
0316 
0317 /**
0318  * @brief Releases all resources of a location.
0319  *
0320  * This function may block on a mutex and may complete an unmount process.
0321  *
0322  * @param[in] loc The location to free.
0323  *
0324  * @note The file system root location is released by the file system
0325  * instance destruction handler (see @ref rtems_filesystem_fsunmount_me_t).
0326  *
0327  * @see rtems_filesystem_freenode_t.
0328  */
0329 void rtems_filesystem_location_free( rtems_filesystem_location_info_t *loc );
0330 
0331 /*
0332  *  External structures
0333  */
0334 #include <rtems/userenv.h>
0335 
0336 void rtems_libio_lock( void );
0337 
0338 void rtems_libio_unlock( void );
0339 
0340 static inline void rtems_filesystem_mt_lock( void )
0341 {
0342   rtems_libio_lock();
0343 }
0344 
0345 static inline void rtems_filesystem_mt_unlock( void )
0346 {
0347   rtems_libio_unlock();
0348 }
0349 
0350 extern rtems_interrupt_lock rtems_filesystem_mt_entry_lock_control;
0351 
0352 #define rtems_filesystem_mt_entry_declare_lock_context( ctx ) \
0353   rtems_interrupt_lock_context ctx
0354 
0355 #define rtems_filesystem_mt_entry_lock( ctx ) \
0356   rtems_interrupt_lock_acquire( &rtems_filesystem_mt_entry_lock_control, &ctx )
0357 
0358 #define rtems_filesystem_mt_entry_unlock( ctx ) \
0359   rtems_interrupt_lock_release( &rtems_filesystem_mt_entry_lock_control, &ctx )
0360 
0361 static inline void rtems_filesystem_instance_lock(
0362   const rtems_filesystem_location_info_t *loc
0363 )
0364 {
0365   const rtems_filesystem_mount_table_entry_t *mt_entry = loc->mt_entry;
0366 
0367   (*mt_entry->ops->lock_h)( mt_entry );
0368 }
0369 
0370 static inline void rtems_filesystem_instance_unlock(
0371   const rtems_filesystem_location_info_t *loc
0372 )
0373 {
0374   const rtems_filesystem_mount_table_entry_t *mt_entry = loc->mt_entry;
0375 
0376   (*mt_entry->ops->unlock_h)( mt_entry );
0377 }
0378 
0379 /**
0380  * @brief Checks the tv_nsec member of a timespec struct
0381  *
0382  * This function is used with utimensat() and futimens() only. This ensures
0383  * that the value in the tv_nsec member is equal to either UTIME_NOW,
0384  * UTIME_OMIT, or a value greater-than or equal to zero and less than a
0385  * billion.
0386  *
0387  * @param[in] time The timespec struct to be validated
0388  *
0389  * @retval true The tv_nsec member is a valid value.
0390  * @retval false The tv_nsec member is not a valid value.
0391  */
0392 bool rtems_filesystem_utime_tv_nsec_valid( struct timespec time );
0393 
0394 /**
0395  * @brief Checks for errors and if the process has write permissions to the file.
0396  *
0397  * This function is only used with utimensat() and futimens().It checks for
0398  * EACCES and EPERM errors depending on what values are in @a times and if the
0399  * process has write permissions to the file.
0400  *
0401  * @param[in] currentloc The current location to a file
0402  * @param[in] times The timespecs used to check for errors. The timespec at
0403  *                  index 0 is the access time, and the timespec at index 1 is
0404  *                  the modification time.
0405  *
0406  * @retval 0 An error was not found.
0407  * @retval -1 An error was found.
0408  */
0409 int rtems_filesystem_utime_check_permissions(
0410   const rtems_filesystem_location_info_t *currentloc,
0411   const struct timespec times[2]
0412 );
0413 
0414 /**
0415  * @brief Checks @a times and fills @a new_times with the time to be written
0416  *
0417  * This function is only used with utimensat() and futimens(). @a times contains
0418  * the constant values passed into utimensat/futimens. @a new_times contains the
0419  * values that will be written to the file. These values depend on @a times. If
0420  * @a times is NULL, or either of its elements' tv_nsec members are UTIME_NOW,
0421  * the current elapsed time in nanoseconds will be saved in the corresponding
0422  * location in @a new_times.
0423  *
0424  * For each of the arguments, the timespec at index 0 is the access time, and
0425  * the timespec at index 1 is the modification time.
0426  *
0427  * @param[in] times The timespecs to be checked
0428  * @param[out] new_times The timespecs containing the time to be written
0429  *
0430  * @retval 0 @a times is valid.
0431  * @retval -1 @a times is not valid.
0432  */
0433 int rtems_filesystem_utime_update(
0434   const struct timespec times[2],
0435   struct timespec new_times[2]
0436 );
0437 
0438 /*
0439  *  File Descriptor Routine Prototypes
0440  */
0441 
0442 /**
0443  * This routine searches the IOP Table for an unused entry.  If it
0444  * finds one, it returns it.  Otherwise, it returns NULL.
0445  */
0446 rtems_libio_t *rtems_libio_allocate(void);
0447 
0448 /**
0449  * Convert UNIX fnctl(2) flags to ones that RTEMS drivers understand
0450  */
0451 unsigned int rtems_libio_fcntl_flags( int fcntl_flags );
0452 
0453 /**
0454  * Convert RTEMS internal flags to UNIX fnctl(2) flags
0455  */
0456 int rtems_libio_to_fcntl_flags( unsigned int flags );
0457 
0458 /**
0459  * This routine frees the resources associated with an IOP (file descriptor)
0460  * and clears the slot in the IOP Table.
0461  */
0462 void rtems_libio_free(
0463   rtems_libio_t *iop
0464 );
0465 
0466 /**
0467  * Return the number of open iop descriptors
0468  */
0469 int rtems_libio_count_open_iops( void );
0470 
0471 /*
0472  *  File System Routine Prototypes
0473  */
0474 
0475 rtems_filesystem_location_info_t *
0476 rtems_filesystem_eval_path_start(
0477   rtems_filesystem_eval_path_context_t *ctx,
0478   const char *path,
0479   int eval_flags
0480 );
0481 
0482 rtems_filesystem_location_info_t *
0483 rtems_filesystem_eval_path_start_with_parent(
0484   rtems_filesystem_eval_path_context_t *ctx,
0485   const char *path,
0486   int eval_flags,
0487   rtems_filesystem_location_info_t *parentloc,
0488   int parent_eval_flags
0489 );
0490 
0491 rtems_filesystem_location_info_t *
0492 rtems_filesystem_eval_path_start_with_root_and_current(
0493   rtems_filesystem_eval_path_context_t *ctx,
0494   const char *path,
0495   size_t pathlen,
0496   int eval_flags,
0497   rtems_filesystem_global_location_t *const *global_root_ptr,
0498   rtems_filesystem_global_location_t *const *global_current_ptr
0499 );
0500 
0501 void rtems_filesystem_eval_path_continue(
0502   rtems_filesystem_eval_path_context_t *ctx
0503 );
0504 
0505 void rtems_filesystem_eval_path_cleanup(
0506   rtems_filesystem_eval_path_context_t *ctx
0507 );
0508 
0509 void rtems_filesystem_eval_path_recursive(
0510   rtems_filesystem_eval_path_context_t *ctx,
0511   const char *path,
0512   size_t pathlen
0513 );
0514 
0515 void rtems_filesystem_eval_path_cleanup_with_parent(
0516   rtems_filesystem_eval_path_context_t *ctx,
0517   rtems_filesystem_location_info_t *parentloc
0518 );
0519 
0520 /**
0521  * @brief Requests a path evaluation restart.
0522  *
0523  * Sets the start and current location to the new start location.  The caller
0524  * must terminate its current evaluation process.  The path evaluation
0525  * continues in the next loop iteration within
0526  * rtems_filesystem_eval_path_continue().  This avoids recursive invocations.
0527  * The function obtains the new start location and clones it to set the new
0528  * current location.  The previous start and current locations are released.
0529  *
0530  * @param[in, out] ctx The path evaluation context.
0531  * @param[in, out] newstartloc_ptr Pointer to the new start location.
0532  */
0533 void rtems_filesystem_eval_path_restart(
0534   rtems_filesystem_eval_path_context_t *ctx,
0535   rtems_filesystem_global_location_t **newstartloc_ptr
0536 );
0537 
0538 typedef enum {
0539   RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_CONTINUE,
0540   RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_DONE,
0541   RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_NO_ENTRY
0542 } rtems_filesystem_eval_path_generic_status;
0543 
0544 /**
0545  * @brief Tests if the current location is a directory.
0546  *
0547  * @param[in, out] ctx The path evaluation context.
0548  * @param[in, out] arg The handler argument.
0549  *
0550  * @retval true The current location is a directory.
0551  * @retval false Otherwise.
0552  *
0553  * @see rtems_filesystem_eval_path_generic().
0554  */
0555 typedef bool (*rtems_filesystem_eval_path_is_directory)(
0556   rtems_filesystem_eval_path_context_t *ctx,
0557   void *arg
0558 );
0559 
0560 /**
0561  * @brief Evaluates a token.
0562  *
0563  * @param[in, out] ctx The path evaluation context.
0564  * @param[in, out] arg The handler argument.
0565  * @param[in] token The token contents.
0566  * @param[in] tokenlen The token length in characters.
0567  *
0568  * @retval status The generic path evaluation status.
0569  *
0570  * @see rtems_filesystem_eval_path_generic().
0571  */
0572 typedef rtems_filesystem_eval_path_generic_status
0573 (*rtems_filesystem_eval_path_eval_token)(
0574   rtems_filesystem_eval_path_context_t *ctx,
0575   void *arg,
0576   const char *token,
0577   size_t tokenlen
0578 );
0579 
0580 typedef struct {
0581   rtems_filesystem_eval_path_is_directory is_directory;
0582   rtems_filesystem_eval_path_eval_token eval_token;
0583 } rtems_filesystem_eval_path_generic_config;
0584 
0585 void rtems_filesystem_eval_path_generic(
0586   rtems_filesystem_eval_path_context_t *ctx,
0587   void *arg,
0588   const rtems_filesystem_eval_path_generic_config *config
0589 );
0590 
0591 void rtems_filesystem_initialize(void);
0592 
0593 /**
0594  * @brief Copies a location.
0595  *
0596  * A bitwise copy is performed.  The destination location will be added to the
0597  * corresponding mount entry.
0598  *
0599  * @param[out] dst The destination location.
0600  * @param[in] src The  source location.
0601  *
0602  * @retval dst The destination location.
0603  *
0604  * @see rtems_filesystem_location_clone().
0605  */
0606 rtems_filesystem_location_info_t *rtems_filesystem_location_copy(
0607   rtems_filesystem_location_info_t *dst,
0608   const rtems_filesystem_location_info_t *src
0609 );
0610 
0611 static inline rtems_filesystem_location_info_t *
0612 rtems_filesystem_location_initialize_to_null(
0613   rtems_filesystem_location_info_t *loc
0614 )
0615 {
0616   return rtems_filesystem_location_copy(
0617     loc,
0618     &rtems_filesystem_global_location_null.location
0619   );
0620 }
0621 
0622 rtems_filesystem_global_location_t *
0623 rtems_filesystem_location_transform_to_global(
0624   rtems_filesystem_location_info_t *loc
0625 );
0626 
0627 /**
0628  * @brief Assigns a global file system location.
0629  *
0630  * @param[in, out] lhs_global_loc_ptr Pointer to the global left hand side file
0631  * system location.  The current left hand side location will be released.
0632  * @param[in] rhs_global_loc The global right hand side file system location.
0633  */
0634 void rtems_filesystem_global_location_assign(
0635   rtems_filesystem_global_location_t **lhs_global_loc_ptr,
0636   rtems_filesystem_global_location_t *rhs_global_loc
0637 );
0638 
0639 /**
0640  * @brief Obtains a global file system location.
0641  *
0642  * Deferred releases will be processed in this function.
0643  *
0644  * This function must be called from normal thread context and may block on a
0645  * mutex.  Thread dispatching is disabled to protect some critical sections.
0646  *
0647  * @param[in] global_loc_ptr Pointer to the global file system location.
0648  *
0649  * @return A global file system location.  It returns always a valid object.
0650  * In case of an error, the global null location will be returned.  Each
0651  * operation or handler of the null location returns an error status.  The
0652  * errno indicates the error.  The NULL pointer is never returned.
0653  *
0654  * @see rtems_filesystem_location_transform_to_global(),
0655  * rtems_filesystem_global_location_obtain_null(), and
0656  * rtems_filesystem_global_location_release().
0657  */
0658 rtems_filesystem_global_location_t *rtems_filesystem_global_location_obtain(
0659   rtems_filesystem_global_location_t *const *global_loc_ptr
0660 );
0661 
0662 /**
0663  * @brief Releases a global file system location.
0664  *
0665  * In case the reference count reaches zero, all associated resources will be
0666  * released.  This may include the complete unmount of the corresponding file
0667  * system instance.
0668  *
0669  * This function may block on a mutex.  It may be called within critical
0670  * sections of the operating system.  In this case the release will be
0671  * deferred.  The next obtain call will do the actual release.
0672  *
0673  * @param[in] global_loc The global file system location.  It must not be NULL.
0674  * @param[in] deferred If true, then do a deferred release, otherwise release
0675  *   it immediately.
0676  *
0677  * @see rtems_filesystem_global_location_obtain().
0678  */
0679 void rtems_filesystem_global_location_release(
0680   rtems_filesystem_global_location_t *global_loc,
0681   bool deferred
0682 );
0683 
0684 void rtems_filesystem_location_detach(
0685   rtems_filesystem_location_info_t *detach
0686 );
0687 
0688 void rtems_filesystem_location_copy_and_detach(
0689   rtems_filesystem_location_info_t *copy,
0690   rtems_filesystem_location_info_t *detach
0691 );
0692 
0693 static inline rtems_filesystem_global_location_t *
0694 rtems_filesystem_global_location_obtain_null(void)
0695 {
0696   rtems_filesystem_global_location_t *global_loc = NULL;
0697 
0698   return rtems_filesystem_global_location_obtain( &global_loc );
0699 }
0700 
0701 static inline bool rtems_filesystem_location_is_null(
0702   const rtems_filesystem_location_info_t *loc
0703 )
0704 {
0705   return loc->handlers == &rtems_filesystem_null_handlers;
0706 }
0707 
0708 static inline bool rtems_filesystem_global_location_is_null(
0709   const rtems_filesystem_global_location_t *global_loc
0710 )
0711 {
0712   return rtems_filesystem_location_is_null( &global_loc->location );
0713 }
0714 
0715 static inline void rtems_filesystem_location_error(
0716   const rtems_filesystem_location_info_t *loc,
0717   int eno
0718 )
0719 {
0720   if ( !rtems_filesystem_location_is_null( loc ) ) {
0721     errno = eno;
0722   }
0723 }
0724 
0725 int rtems_filesystem_mknod(
0726   const rtems_filesystem_location_info_t *parentloc,
0727   const char *name,
0728   size_t namelen,
0729   mode_t mode,
0730   dev_t dev
0731 );
0732 
0733 int rtems_filesystem_chdir( rtems_filesystem_location_info_t *loc );
0734 
0735 int rtems_filesystem_chmod(
0736   const rtems_filesystem_location_info_t *loc,
0737   mode_t mode
0738 );
0739 
0740 int rtems_filesystem_chown(
0741   const rtems_filesystem_location_info_t *loc,
0742   uid_t owner,
0743   gid_t group
0744 );
0745 
0746 static inline bool rtems_filesystem_is_ready_for_unmount(
0747   rtems_filesystem_mount_table_entry_t *mt_entry
0748 )
0749 {
0750   bool ready = !mt_entry->mounted
0751     && rtems_chain_has_only_one_node( &mt_entry->location_chain )
0752     && mt_entry->mt_fs_root->reference_count == 1;
0753 
0754   if ( ready ) {
0755     rtems_chain_initialize_empty( &mt_entry->location_chain );
0756   }
0757 
0758   return ready;
0759 }
0760 
0761 static inline void rtems_filesystem_location_add_to_mt_entry(
0762   rtems_filesystem_location_info_t *loc
0763 )
0764 {
0765   rtems_filesystem_mt_entry_declare_lock_context( lock_context );
0766 
0767   rtems_filesystem_mt_entry_lock( lock_context );
0768   rtems_chain_append_unprotected(
0769     &loc->mt_entry->location_chain,
0770     &loc->mt_entry_node
0771   );
0772   rtems_filesystem_mt_entry_unlock( lock_context );
0773 }
0774 
0775 void rtems_filesystem_location_remove_from_mt_entry(
0776   rtems_filesystem_location_info_t *loc
0777 );
0778 
0779 void rtems_filesystem_do_unmount(
0780   rtems_filesystem_mount_table_entry_t *mt_entry
0781 );
0782 
0783 static inline bool rtems_filesystem_location_is_instance_root(
0784   const rtems_filesystem_location_info_t *loc
0785 )
0786 {
0787   const rtems_filesystem_mount_table_entry_t *mt_entry = loc->mt_entry;
0788 
0789   return (*mt_entry->ops->are_nodes_equal_h)(
0790     loc,
0791     &mt_entry->mt_fs_root->location
0792   );
0793 }
0794 
0795 static inline const char *rtems_filesystem_eval_path_get_path(
0796   const rtems_filesystem_eval_path_context_t *ctx
0797 )
0798 {
0799   return ctx->path;
0800 }
0801 
0802 static inline size_t rtems_filesystem_eval_path_get_pathlen(
0803   const rtems_filesystem_eval_path_context_t *ctx
0804 )
0805 {
0806   return ctx->pathlen;
0807 }
0808 
0809 static inline void rtems_filesystem_eval_path_set_path(
0810   rtems_filesystem_eval_path_context_t *ctx,
0811   const char *path,
0812   size_t pathlen
0813 )
0814 {
0815   ctx->path = path;
0816   ctx->pathlen = pathlen;
0817 }
0818 
0819 static inline void rtems_filesystem_eval_path_clear_path(
0820   rtems_filesystem_eval_path_context_t *ctx
0821 )
0822 {
0823   ctx->pathlen = 0;
0824 }
0825 
0826 static inline const char *rtems_filesystem_eval_path_get_token(
0827   const rtems_filesystem_eval_path_context_t *ctx
0828 )
0829 {
0830   return ctx->token;
0831 }
0832 
0833 static inline size_t rtems_filesystem_eval_path_get_tokenlen(
0834   const rtems_filesystem_eval_path_context_t *ctx
0835 )
0836 {
0837   return ctx->tokenlen;
0838 }
0839 
0840 static inline void rtems_filesystem_eval_path_set_token(
0841   rtems_filesystem_eval_path_context_t *ctx,
0842   const char *token,
0843   size_t tokenlen
0844 )
0845 {
0846   ctx->token = token;
0847   ctx->tokenlen = tokenlen;
0848 }
0849 
0850 static inline void rtems_filesystem_eval_path_clear_token(
0851   rtems_filesystem_eval_path_context_t *ctx
0852 )
0853 {
0854   ctx->tokenlen = 0;
0855 }
0856 
0857 static inline void rtems_filesystem_eval_path_put_back_token(
0858   rtems_filesystem_eval_path_context_t *ctx
0859 )
0860 {
0861   size_t tokenlen = ctx->tokenlen;
0862 
0863   ctx->path -= tokenlen;
0864   ctx->pathlen += tokenlen;
0865   ctx->tokenlen = 0;
0866 }
0867 
0868 void rtems_filesystem_eval_path_eat_delimiter(
0869   rtems_filesystem_eval_path_context_t *ctx
0870 );
0871 
0872 void rtems_filesystem_eval_path_next_token(
0873   rtems_filesystem_eval_path_context_t *ctx
0874 );
0875 
0876 static inline void rtems_filesystem_eval_path_get_next_token(
0877   rtems_filesystem_eval_path_context_t *ctx,
0878   const char **token,
0879   size_t *tokenlen
0880 )
0881 {
0882   rtems_filesystem_eval_path_next_token(ctx);
0883   *token = ctx->token;
0884   *tokenlen = ctx->tokenlen;
0885 }
0886 
0887 static inline rtems_filesystem_location_info_t *
0888 rtems_filesystem_eval_path_get_currentloc(
0889   rtems_filesystem_eval_path_context_t *ctx
0890 )
0891 {
0892   return &ctx->currentloc;
0893 }
0894 
0895 static inline bool rtems_filesystem_eval_path_has_path(
0896   const rtems_filesystem_eval_path_context_t *ctx
0897 )
0898 {
0899   return ctx->pathlen > 0;
0900 }
0901 
0902 static inline bool rtems_filesystem_eval_path_has_token(
0903   const rtems_filesystem_eval_path_context_t *ctx
0904 )
0905 {
0906   return ctx->tokenlen > 0;
0907 }
0908 
0909 static inline int rtems_filesystem_eval_path_get_flags(
0910   const rtems_filesystem_eval_path_context_t *ctx
0911 )
0912 {
0913   return ctx->flags;
0914 }
0915 
0916 static inline void rtems_filesystem_eval_path_set_flags(
0917   rtems_filesystem_eval_path_context_t *ctx,
0918   int flags
0919 )
0920 {
0921   ctx->flags = flags;
0922 }
0923 
0924 static inline void rtems_filesystem_eval_path_clear_and_set_flags(
0925   rtems_filesystem_eval_path_context_t *ctx,
0926   int clear,
0927   int set
0928 )
0929 {
0930   int flags = ctx->flags;
0931 
0932   flags &= ~clear;
0933   flags |= set;
0934 
0935   ctx->flags = flags;
0936 }
0937 
0938 static inline void rtems_filesystem_eval_path_extract_currentloc(
0939   rtems_filesystem_eval_path_context_t *ctx,
0940   rtems_filesystem_location_info_t *get
0941 )
0942 {
0943   rtems_filesystem_location_copy_and_detach(
0944     get,
0945     &ctx->currentloc
0946   );
0947 }
0948 
0949 void rtems_filesystem_eval_path_error(
0950   rtems_filesystem_eval_path_context_t *ctx,
0951   int eno
0952 );
0953 
0954 /**
0955  * @brief Checks that the locations exist in the same file system instance.
0956  *
0957  * @retval 0 The locations exist and are in the same file system instance.
0958  * @retval -1 An error occurred.  The @c errno indicates the error.
0959  */
0960 int rtems_filesystem_location_exists_in_same_instance_as(
0961   const rtems_filesystem_location_info_t *a,
0962   const rtems_filesystem_location_info_t *b
0963 );
0964 
0965 /**
0966  * @brief Checks if access to an object is allowed for the current user.
0967  *
0968  * If the effective UID is zero or equals the UID of the object, then the user
0969  * permission flags of the object will be used.  Otherwise if the effective GID
0970  * is zero or equals the GID of the object or one of the supplementary group
0971  * IDs is equal to the GID of the object, then the group permission flags of
0972  * the object will be used.  Otherwise the other permission flags of the object
0973  * will be used.
0974  *
0975  * @param[in] flags The flags determining the access type.  It can be
0976  *   RTEMS_FS_PERMS_READ, RTEMS_FS_PERMS_WRITE or RTEMS_FS_PERMS_EXEC.
0977  * @param[in] object_mode The mode of the object specifying the permission flags.
0978  * @param[in] object_uid The UID of the object.
0979  * @param[in] object_gid The GID of the object.
0980  *
0981  * @retval true Access is allowed.
0982  * @retval false Otherwise.
0983  */
0984 bool rtems_filesystem_check_access(
0985   int flags,
0986   mode_t object_mode,
0987   uid_t object_uid,
0988   gid_t object_gid
0989 );
0990 
0991 bool rtems_filesystem_eval_path_check_access(
0992   rtems_filesystem_eval_path_context_t *ctx,
0993   int eval_flags,
0994   mode_t node_mode,
0995   uid_t node_uid,
0996   gid_t node_gid
0997 );
0998 
0999 static inline bool rtems_filesystem_is_delimiter(char c)
1000 {
1001   return c == '/' || c == '\\';
1002 }
1003 
1004 static inline bool rtems_filesystem_is_current_directory(
1005   const char *token,
1006   size_t tokenlen
1007 )
1008 {
1009   return tokenlen == 1 && token [0] == '.';
1010 }
1011 
1012 static inline bool rtems_filesystem_is_parent_directory(
1013   const char *token,
1014   size_t tokenlen
1015 )
1016 {
1017   return tokenlen == 2 && token [0] == '.' && token [1] == '.';
1018 }
1019 
1020 typedef ssize_t ( *rtems_libio_iovec_adapter )(
1021   rtems_libio_t      *iop,
1022   const struct iovec *iov,
1023   int                 iovcnt,
1024   ssize_t             total
1025 );
1026 
1027 static inline ssize_t rtems_libio_iovec_eval(
1028   int                        fd,
1029   const struct iovec        *iov,
1030   int                        iovcnt,
1031   unsigned int               flags,
1032   rtems_libio_iovec_adapter  adapter
1033 )
1034 {
1035   ssize_t        total;
1036   int            v;
1037   rtems_libio_t *iop;
1038 
1039   /*
1040    *  Argument validation on IO vector
1041    */
1042   if ( iov == NULL )
1043     rtems_set_errno_and_return_minus_one( EINVAL );
1044 
1045   if ( iovcnt <= 0 )
1046     rtems_set_errno_and_return_minus_one( EINVAL );
1047 
1048   if ( iovcnt > IOV_MAX )
1049     rtems_set_errno_and_return_minus_one( EINVAL );
1050 
1051   /*
1052    *  OpenGroup says that you are supposed to return EINVAL if the
1053    *  sum of the iov_len values in the iov array would overflow a
1054    *  ssize_t.
1055    */
1056   total = 0;
1057   for ( v = 0 ; v < iovcnt ; ++v ) {
1058     size_t len = iov[ v ].iov_len;
1059 
1060     if ( len > ( size_t ) ( SSIZE_MAX - total ) ) {
1061       rtems_set_errno_and_return_minus_one( EINVAL );
1062     }
1063 
1064     total += ( ssize_t ) len;
1065 
1066     if ( iov[ v ].iov_base == NULL && len != 0 ) {
1067       rtems_set_errno_and_return_minus_one( EINVAL );
1068     }
1069   }
1070 
1071   LIBIO_GET_IOP_WITH_ACCESS( fd, iop, flags, EBADF );
1072 
1073   if ( total > 0 ) {
1074     total = ( *adapter )( iop, iov, iovcnt, total );
1075   }
1076 
1077   rtems_libio_iop_drop( iop );
1078   return total;
1079 }
1080 
1081 /**
1082  * @brief Returns the file type of the file referenced by the filesystem
1083  * location.
1084  *
1085  * @brief[in] loc The filesystem location.
1086  *
1087  * @return The type of the file or an invalid file type in case of an error.
1088  */
1089 static inline mode_t rtems_filesystem_location_type(
1090   const rtems_filesystem_location_info_t *loc
1091 )
1092 {
1093   struct stat st;
1094 
1095   st.st_mode = 0;
1096   (void) ( *loc->handlers->fstat_h )( loc, &st );
1097 
1098   return st.st_mode;
1099 }
1100 
1101 /** @} */
1102 
1103 #ifdef __cplusplus
1104 }
1105 #endif
1106 
1107 #endif
1108 /* end of include file */