source: rtems/cpukit/include/rtems/libio_.h

Last change on this file was bcef89f2, checked in by Sebastian Huber <sebastian.huber@…>, on 05/19/23 at 06:18:25

Update company name

The embedded brains GmbH & Co. KG is the legal successor of embedded
brains GmbH.

  • Property mode set to 100644
File size: 28.8 KB
Line 
1/* SPDX-License-Identifier: BSD-2-Clause */
2
3/**
4 * @file
5 *
6 * @brief LibIO Internal Interface
7 *
8 * This file is the libio internal interface.
9 */
10
11/*
12 * COPYRIGHT (C) 1989, 2021 On-Line Applications Research Corporation (OAR).
13 *
14 * Modifications to support reference counting in the file system are
15 * Copyright (c) 2012 embedded brains GmbH & Co. KG
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions
19 * are met:
20 * 1. Redistributions of source code must retain the above copyright
21 *    notice, this list of conditions and the following disclaimer.
22 * 2. Redistributions in binary form must reproduce the above copyright
23 *    notice, this list of conditions and the following disclaimer in the
24 *    documentation and/or other materials provided with the distribution.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
27 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
30 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39#ifndef _RTEMS_RTEMS_LIBIO__H
40#define _RTEMS_RTEMS_LIBIO__H
41
42#include <sys/uio.h>
43#include <errno.h>
44#include <limits.h>
45#include <pthread.h>
46
47#include <rtems.h>
48#include <rtems/libio.h>
49#include <rtems/seterr.h>
50#include <rtems/score/assert.h>
51#include <rtems/score/timespec.h>
52
53#ifdef __cplusplus
54extern "C" {
55#endif
56
57/**
58 * @defgroup LibIOInternal IO Internal Library
59 *
60 * @ingroup LibIO
61 *
62 * @brief Internal IO library API and implementation.
63 *
64 */
65/**@{**/
66
67#define RTEMS_FILESYSTEM_SYMLOOP_MAX 32
68
69/*
70 * Not defined in newlib so provide here. Users should use dup2 and
71 * not this non-portable fcntl command. Provided here to allow the
72 * RTEMS implementation to work.
73 */
74#define F_DUP2FD 20
75
76/*
77 *  File descriptor Table Information
78 */
79
80extern const uint32_t rtems_libio_number_iops;
81extern rtems_libio_t rtems_libio_iops[];
82extern void *rtems_libio_iop_free_head;
83extern void **rtems_libio_iop_free_tail;
84
85extern const rtems_filesystem_file_handlers_r rtems_filesystem_null_handlers;
86
87extern rtems_filesystem_mount_table_entry_t rtems_filesystem_null_mt_entry;
88
89/**
90 * @brief The global null location.
91 *
92 * Every operation and the open and fstat handlers of this location returns an
93 * error status.  The errno is not touched by these operations and handlers.
94 * The purpose of this location is to deliver the error return status for a
95 * previous error condition which must set the errno accordingly.
96 *
97 * The usage of this null location instead of the NULL pointer eliminates
98 * a lot of branches.
99 *
100 * The user environment root and current directory are statically initialized
101 * with the null location.  Due to that all file system services are in a
102 * defined state even if no root file system was mounted.
103 */
104extern rtems_filesystem_global_location_t rtems_filesystem_global_location_null;
105
106/**
107 * @brief Sets the specified flags in the iop.
108 *
109 * @param[in] iop The iop.
110 * @param[in] set The flags to set.
111 *
112 * @return The previous flags.
113 */
114static inline unsigned int rtems_libio_iop_flags_set(
115  rtems_libio_t *iop,
116  unsigned int   set
117)
118{
119  return _Atomic_Fetch_or_uint( &iop->flags, set, ATOMIC_ORDER_RELAXED );
120}
121
122/**
123 * @brief Clears the specified flags in the iop.
124 *
125 * @param[in] iop The iop.
126 * @param[in] clear The flags to clear.
127 *
128 * @return The previous flags.
129 */
130static inline unsigned int rtems_libio_iop_flags_clear(
131  rtems_libio_t *iop,
132  unsigned int   clear
133)
134{
135  return _Atomic_Fetch_and_uint( &iop->flags, ~clear, ATOMIC_ORDER_RELAXED );
136}
137
138/**
139 * @brief Maps a file descriptor to the iop.
140 *
141 * The file descriptor must be a valid index into the iop table.
142 *
143 * @param[in] fd The file descriptor.
144 *
145 * @return The iop corresponding to the specified file descriptor.
146 */
147static inline rtems_libio_t *rtems_libio_iop( int fd )
148{
149  return &rtems_libio_iops[ fd ];
150}
151
152/**
153 * @brief Holds a refernece to the iop.
154 *
155 * @param[in] iop The iop.
156 *
157 * @return The flags corresponding to the specified iop.
158 */
159static inline unsigned int rtems_libio_iop_hold( rtems_libio_t *iop )
160{
161  return _Atomic_Fetch_add_uint(
162    &iop->flags,
163    LIBIO_FLAGS_REFERENCE_INC,
164    ATOMIC_ORDER_ACQUIRE
165  );
166}
167
168/**
169 * @brief Drops a refernece to the iop.
170 *
171 * @param[in] iop The iop.
172 */
173static inline void rtems_libio_iop_drop( rtems_libio_t *iop )
174{
175#if defined(RTEMS_DEBUG)
176  unsigned int flags;
177  bool         success;
178
179  flags = _Atomic_Load_uint( &iop->flags, ATOMIC_ORDER_RELAXED );
180
181  do {
182    unsigned int desired;
183
184    _Assert( flags >= LIBIO_FLAGS_REFERENCE_INC );
185
186    desired = flags - LIBIO_FLAGS_REFERENCE_INC;
187    success = _Atomic_Compare_exchange_uint(
188      &iop->flags,
189      &flags,
190      desired,
191      ATOMIC_ORDER_RELEASE,
192      ATOMIC_ORDER_RELAXED
193    );
194  } while ( !success );
195#else
196  _Atomic_Fetch_sub_uint(
197    &iop->flags,
198    LIBIO_FLAGS_REFERENCE_INC,
199    ATOMIC_ORDER_RELEASE
200  );
201#endif
202}
203
204/*
205 *  rtems_libio_iop_to_descriptor
206 *
207 *  Macro to convert an internal file descriptor pointer (iop) into
208 *  the integer file descriptor used by the "section 2" system calls.
209 */
210
211#define rtems_libio_iop_to_descriptor(_iop) \
212  ((_iop) - &rtems_libio_iops[0])
213
214/*
215 *  rtems_libio_check_is_open
216 *
217 *  Macro to check if a file descriptor is actually open.
218 */
219
220#define rtems_libio_check_is_open(_iop) \
221  do {                                               \
222      if ((rtems_libio_iop_flags(_iop) & LIBIO_FLAGS_OPEN) == 0) { \
223          errno = EBADF;                             \
224          return -1;                                 \
225      }                                              \
226  } while (0)
227
228/**
229 * @brief Macro to get the iop for the specified file descriptor.
230 *
231 * Checks that the file descriptor is in the valid range and open.
232 */
233#define LIBIO_GET_IOP( _fd, _iop ) \
234  do { \
235    unsigned int _flags; \
236    if ( (uint32_t) ( _fd ) >= rtems_libio_number_iops ) { \
237      rtems_set_errno_and_return_minus_one( EBADF ); \
238    } \
239    _iop = rtems_libio_iop( _fd ); \
240    _flags = rtems_libio_iop_hold( _iop ); \
241    if ( ( _flags & LIBIO_FLAGS_OPEN ) == 0 ) { \
242      rtems_libio_iop_drop( _iop ); \
243      rtems_set_errno_and_return_minus_one( EBADF ); \
244    } \
245  } while ( 0 )
246
247/**
248 * @brief Macro to get the iop for the specified file descriptor with access
249 * flags and error.
250 *
251 * Checks that the file descriptor is in the valid range and open.
252 */
253#define LIBIO_GET_IOP_WITH_ACCESS( _fd, _iop, _access_flags, _access_error ) \
254  do { \
255    unsigned int _flags; \
256    unsigned int _mandatory; \
257    if ( (uint32_t) ( _fd ) >= rtems_libio_number_iops ) { \
258      rtems_set_errno_and_return_minus_one( EBADF ); \
259    } \
260    _iop = rtems_libio_iop( _fd ); \
261    _flags = rtems_libio_iop_hold( _iop ); \
262    _mandatory = LIBIO_FLAGS_OPEN | ( _access_flags ); \
263    if ( ( _flags & _mandatory ) != _mandatory ) { \
264      int _error; \
265      rtems_libio_iop_drop( _iop ); \
266      if ( ( _flags & LIBIO_FLAGS_OPEN ) == 0 ) { \
267        _error = EBADF; \
268      } else { \
269        _error = _access_error; \
270      } \
271      rtems_set_errno_and_return_minus_one( _error ); \
272    } \
273  } while ( 0 )
274
275/*
276 *  rtems_libio_check_buffer
277 *
278 *  Macro to check if a buffer pointer is valid.
279 */
280
281#define rtems_libio_check_buffer(_buffer) \
282  do {                                    \
283      if ((_buffer) == 0) {               \
284          errno = EINVAL;                 \
285          return -1;                      \
286      }                                   \
287  } while (0)
288
289/*
290 *  rtems_libio_check_count
291 *
292 *  Macro to check if a count or length is valid.
293 */
294
295#define rtems_libio_check_count(_count) \
296  do {                                  \
297      if ((_count) == 0) {              \
298          return 0;                     \
299      }                                 \
300  } while (0)
301
302/**
303 * @brief Clones a node.
304 *
305 * The caller must hold the file system instance lock.
306 *
307 * @param[out] clone The cloned location.
308 * @param[in] master The master location.
309 *
310 * @see rtems_filesystem_instance_lock().
311 */
312void rtems_filesystem_location_clone(
313  rtems_filesystem_location_info_t *clone,
314  const rtems_filesystem_location_info_t *master
315);
316
317/**
318 * @brief Releases all resources of a location.
319 *
320 * This function may block on a mutex and may complete an unmount process.
321 *
322 * @param[in] loc The location to free.
323 *
324 * @note The file system root location is released by the file system
325 * instance destruction handler (see @ref rtems_filesystem_fsunmount_me_t).
326 *
327 * @see rtems_filesystem_freenode_t.
328 */
329void rtems_filesystem_location_free( rtems_filesystem_location_info_t *loc );
330
331/*
332 *  External structures
333 */
334#include <rtems/userenv.h>
335
336void rtems_libio_lock( void );
337
338void rtems_libio_unlock( void );
339
340static inline void rtems_filesystem_mt_lock( void )
341{
342  rtems_libio_lock();
343}
344
345static inline void rtems_filesystem_mt_unlock( void )
346{
347  rtems_libio_unlock();
348}
349
350extern rtems_interrupt_lock rtems_filesystem_mt_entry_lock_control;
351
352#define rtems_filesystem_mt_entry_declare_lock_context( ctx ) \
353  rtems_interrupt_lock_context ctx
354
355#define rtems_filesystem_mt_entry_lock( ctx ) \
356  rtems_interrupt_lock_acquire( &rtems_filesystem_mt_entry_lock_control, &ctx )
357
358#define rtems_filesystem_mt_entry_unlock( ctx ) \
359  rtems_interrupt_lock_release( &rtems_filesystem_mt_entry_lock_control, &ctx )
360
361static inline void rtems_filesystem_instance_lock(
362  const rtems_filesystem_location_info_t *loc
363)
364{
365  const rtems_filesystem_mount_table_entry_t *mt_entry = loc->mt_entry;
366
367  (*mt_entry->ops->lock_h)( mt_entry );
368}
369
370static inline void rtems_filesystem_instance_unlock(
371  const rtems_filesystem_location_info_t *loc
372)
373{
374  const rtems_filesystem_mount_table_entry_t *mt_entry = loc->mt_entry;
375
376  (*mt_entry->ops->unlock_h)( mt_entry );
377}
378
379/**
380 * @brief Checks the tv_nsec member of a timespec struct
381 *
382 * This function is used with utimensat() and futimens() only. This ensures
383 * that the value in the tv_nsec member is equal to either UTIME_NOW,
384 * UTIME_OMIT, or a value greater-than or equal to zero and less than a
385 * billion.
386 *
387 * @param[in] time The timespec struct to be validated
388 *
389 * @retval true The tv_nsec member is a valid value.
390 * @retval false The tv_nsec member is not a valid value.
391 */
392bool rtems_filesystem_utime_tv_nsec_valid( struct timespec time );
393
394/**
395 * @brief Checks for errors and if the process has write permissions to the file.
396 *
397 * This function is only used with utimensat() and futimens().It checks for
398 * EACCES and EPERM errors depending on what values are in @a times and if the
399 * process has write permissions to the file.
400 *
401 * @param[in] currentloc The current location to a file
402 * @param[in] times The timespecs used to check for errors. The timespec at
403 *                  index 0 is the access time, and the timespec at index 1 is
404 *                  the modification time.
405 *
406 * @retval 0 An error was not found.
407 * @retval -1 An error was found.
408 */
409int rtems_filesystem_utime_check_permissions(
410  const rtems_filesystem_location_info_t *currentloc,
411  const struct timespec times[2]
412);
413
414/**
415 * @brief Checks @a times and fills @a new_times with the time to be written
416 *
417 * This function is only used with utimensat() and futimens(). @a times contains
418 * the constant values passed into utimensat/futimens. @a new_times contains the
419 * values that will be written to the file. These values depend on @a times. If
420 * @a times is NULL, or either of its elements' tv_nsec members are UTIME_NOW,
421 * the current elapsed time in nanoseconds will be saved in the corresponding
422 * location in @a new_times.
423 *
424 * For each of the arguments, the timespec at index 0 is the access time, and
425 * the timespec at index 1 is the modification time.
426 *
427 * @param[in] times The timespecs to be checked
428 * @param[out] new_times The timespecs containing the time to be written
429 *
430 * @retval 0 @a times is valid.
431 * @retval -1 @a times is not valid.
432 */
433int rtems_filesystem_utime_update(
434  const struct timespec times[2],
435  struct timespec new_times[2]
436);
437
438/*
439 *  File Descriptor Routine Prototypes
440 */
441
442/**
443 * This routine searches the IOP Table for an unused entry.  If it
444 * finds one, it returns it.  Otherwise, it returns NULL.
445 */
446rtems_libio_t *rtems_libio_allocate(void);
447
448/**
449 * Convert UNIX fnctl(2) flags to ones that RTEMS drivers understand
450 */
451unsigned int rtems_libio_fcntl_flags( int fcntl_flags );
452
453/**
454 * Convert RTEMS internal flags to UNIX fnctl(2) flags
455 */
456int rtems_libio_to_fcntl_flags( unsigned int flags );
457
458/**
459 * This routine frees the resources associated with an IOP (file descriptor)
460 * and clears the slot in the IOP Table.
461 */
462void rtems_libio_free(
463  rtems_libio_t *iop
464);
465
466/*
467 *  File System Routine Prototypes
468 */
469
470rtems_filesystem_location_info_t *
471rtems_filesystem_eval_path_start(
472  rtems_filesystem_eval_path_context_t *ctx,
473  const char *path,
474  int eval_flags
475);
476
477rtems_filesystem_location_info_t *
478rtems_filesystem_eval_path_start_with_parent(
479  rtems_filesystem_eval_path_context_t *ctx,
480  const char *path,
481  int eval_flags,
482  rtems_filesystem_location_info_t *parentloc,
483  int parent_eval_flags
484);
485
486rtems_filesystem_location_info_t *
487rtems_filesystem_eval_path_start_with_root_and_current(
488  rtems_filesystem_eval_path_context_t *ctx,
489  const char *path,
490  size_t pathlen,
491  int eval_flags,
492  rtems_filesystem_global_location_t *const *global_root_ptr,
493  rtems_filesystem_global_location_t *const *global_current_ptr
494);
495
496void rtems_filesystem_eval_path_continue(
497  rtems_filesystem_eval_path_context_t *ctx
498);
499
500void rtems_filesystem_eval_path_cleanup(
501  rtems_filesystem_eval_path_context_t *ctx
502);
503
504void rtems_filesystem_eval_path_recursive(
505  rtems_filesystem_eval_path_context_t *ctx,
506  const char *path,
507  size_t pathlen
508);
509
510void rtems_filesystem_eval_path_cleanup_with_parent(
511  rtems_filesystem_eval_path_context_t *ctx,
512  rtems_filesystem_location_info_t *parentloc
513);
514
515/**
516 * @brief Requests a path evaluation restart.
517 *
518 * Sets the start and current location to the new start location.  The caller
519 * must terminate its current evaluation process.  The path evaluation
520 * continues in the next loop iteration within
521 * rtems_filesystem_eval_path_continue().  This avoids recursive invocations.
522 * The function obtains the new start location and clones it to set the new
523 * current location.  The previous start and current locations are released.
524 *
525 * @param[in, out] ctx The path evaluation context.
526 * @param[in, out] newstartloc_ptr Pointer to the new start location.
527 */
528void rtems_filesystem_eval_path_restart(
529  rtems_filesystem_eval_path_context_t *ctx,
530  rtems_filesystem_global_location_t **newstartloc_ptr
531);
532
533typedef enum {
534  RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_CONTINUE,
535  RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_DONE,
536  RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_NO_ENTRY
537} rtems_filesystem_eval_path_generic_status;
538
539/**
540 * @brief Tests if the current location is a directory.
541 *
542 * @param[in, out] ctx The path evaluation context.
543 * @param[in, out] arg The handler argument.
544 *
545 * @retval true The current location is a directory.
546 * @retval false Otherwise.
547 *
548 * @see rtems_filesystem_eval_path_generic().
549 */
550typedef bool (*rtems_filesystem_eval_path_is_directory)(
551  rtems_filesystem_eval_path_context_t *ctx,
552  void *arg
553);
554
555/**
556 * @brief Evaluates a token.
557 *
558 * @param[in, out] ctx The path evaluation context.
559 * @param[in, out] arg The handler argument.
560 * @param[in] token The token contents.
561 * @param[in] tokenlen The token length in characters.
562 *
563 * @retval status The generic path evaluation status.
564 *
565 * @see rtems_filesystem_eval_path_generic().
566 */
567typedef rtems_filesystem_eval_path_generic_status
568(*rtems_filesystem_eval_path_eval_token)(
569  rtems_filesystem_eval_path_context_t *ctx,
570  void *arg,
571  const char *token,
572  size_t tokenlen
573);
574
575typedef struct {
576  rtems_filesystem_eval_path_is_directory is_directory;
577  rtems_filesystem_eval_path_eval_token eval_token;
578} rtems_filesystem_eval_path_generic_config;
579
580void rtems_filesystem_eval_path_generic(
581  rtems_filesystem_eval_path_context_t *ctx,
582  void *arg,
583  const rtems_filesystem_eval_path_generic_config *config
584);
585
586void rtems_filesystem_initialize(void);
587
588/**
589 * @brief Copies a location.
590 *
591 * A bitwise copy is performed.  The destination location will be added to the
592 * corresponding mount entry.
593 *
594 * @param[out] dst The destination location.
595 * @param[in] src The  source location.
596 *
597 * @retval dst The destination location.
598 *
599 * @see rtems_filesystem_location_clone().
600 */
601rtems_filesystem_location_info_t *rtems_filesystem_location_copy(
602  rtems_filesystem_location_info_t *dst,
603  const rtems_filesystem_location_info_t *src
604);
605
606static inline rtems_filesystem_location_info_t *
607rtems_filesystem_location_initialize_to_null(
608  rtems_filesystem_location_info_t *loc
609)
610{
611  return rtems_filesystem_location_copy(
612    loc,
613    &rtems_filesystem_global_location_null.location
614  );
615}
616
617rtems_filesystem_global_location_t *
618rtems_filesystem_location_transform_to_global(
619  rtems_filesystem_location_info_t *loc
620);
621
622/**
623 * @brief Assigns a global file system location.
624 *
625 * @param[in, out] lhs_global_loc_ptr Pointer to the global left hand side file
626 * system location.  The current left hand side location will be released.
627 * @param[in] rhs_global_loc The global right hand side file system location.
628 */
629void rtems_filesystem_global_location_assign(
630  rtems_filesystem_global_location_t **lhs_global_loc_ptr,
631  rtems_filesystem_global_location_t *rhs_global_loc
632);
633
634/**
635 * @brief Obtains a global file system location.
636 *
637 * Deferred releases will be processed in this function.
638 *
639 * This function must be called from normal thread context and may block on a
640 * mutex.  Thread dispatching is disabled to protect some critical sections.
641 *
642 * @param[in] global_loc_ptr Pointer to the global file system location.
643 *
644 * @return A global file system location.  It returns always a valid object.
645 * In case of an error, the global null location will be returned.  Each
646 * operation or handler of the null location returns an error status.  The
647 * errno indicates the error.  The NULL pointer is never returned.
648 *
649 * @see rtems_filesystem_location_transform_to_global(),
650 * rtems_filesystem_global_location_obtain_null(), and
651 * rtems_filesystem_global_location_release().
652 */
653rtems_filesystem_global_location_t *rtems_filesystem_global_location_obtain(
654  rtems_filesystem_global_location_t *const *global_loc_ptr
655);
656
657/**
658 * @brief Releases a global file system location.
659 *
660 * In case the reference count reaches zero, all associated resources will be
661 * released.  This may include the complete unmount of the corresponding file
662 * system instance.
663 *
664 * This function may block on a mutex.  It may be called within critical
665 * sections of the operating system.  In this case the release will be
666 * deferred.  The next obtain call will do the actual release.
667 *
668 * @param[in] global_loc The global file system location.  It must not be NULL.
669 * @param[in] deferred If true, then do a deferred release, otherwise release
670 *   it immediately.
671 *
672 * @see rtems_filesystem_global_location_obtain().
673 */
674void rtems_filesystem_global_location_release(
675  rtems_filesystem_global_location_t *global_loc,
676  bool deferred
677);
678
679void rtems_filesystem_location_detach(
680  rtems_filesystem_location_info_t *detach
681);
682
683void rtems_filesystem_location_copy_and_detach(
684  rtems_filesystem_location_info_t *copy,
685  rtems_filesystem_location_info_t *detach
686);
687
688static inline rtems_filesystem_global_location_t *
689rtems_filesystem_global_location_obtain_null(void)
690{
691  rtems_filesystem_global_location_t *global_loc = NULL;
692
693  return rtems_filesystem_global_location_obtain( &global_loc );
694}
695
696static inline bool rtems_filesystem_location_is_null(
697  const rtems_filesystem_location_info_t *loc
698)
699{
700  return loc->handlers == &rtems_filesystem_null_handlers;
701}
702
703static inline bool rtems_filesystem_global_location_is_null(
704  const rtems_filesystem_global_location_t *global_loc
705)
706{
707  return rtems_filesystem_location_is_null( &global_loc->location );
708}
709
710static inline void rtems_filesystem_location_error(
711  const rtems_filesystem_location_info_t *loc,
712  int eno
713)
714{
715  if ( !rtems_filesystem_location_is_null( loc ) ) {
716    errno = eno;
717  }
718}
719
720int rtems_filesystem_mknod(
721  const rtems_filesystem_location_info_t *parentloc,
722  const char *name,
723  size_t namelen,
724  mode_t mode,
725  dev_t dev
726);
727
728int rtems_filesystem_chdir( rtems_filesystem_location_info_t *loc );
729
730int rtems_filesystem_chmod(
731  const rtems_filesystem_location_info_t *loc,
732  mode_t mode
733);
734
735int rtems_filesystem_chown(
736  const rtems_filesystem_location_info_t *loc,
737  uid_t owner,
738  gid_t group
739);
740
741static inline bool rtems_filesystem_is_ready_for_unmount(
742  rtems_filesystem_mount_table_entry_t *mt_entry
743)
744{
745  bool ready = !mt_entry->mounted
746    && rtems_chain_has_only_one_node( &mt_entry->location_chain )
747    && mt_entry->mt_fs_root->reference_count == 1;
748
749  if ( ready ) {
750    rtems_chain_initialize_empty( &mt_entry->location_chain );
751  }
752
753  return ready;
754}
755
756static inline void rtems_filesystem_location_add_to_mt_entry(
757  rtems_filesystem_location_info_t *loc
758)
759{
760  rtems_filesystem_mt_entry_declare_lock_context( lock_context );
761
762  rtems_filesystem_mt_entry_lock( lock_context );
763  rtems_chain_append_unprotected(
764    &loc->mt_entry->location_chain,
765    &loc->mt_entry_node
766  );
767  rtems_filesystem_mt_entry_unlock( lock_context );
768}
769
770void rtems_filesystem_location_remove_from_mt_entry(
771  rtems_filesystem_location_info_t *loc
772);
773
774void rtems_filesystem_do_unmount(
775  rtems_filesystem_mount_table_entry_t *mt_entry
776);
777
778static inline bool rtems_filesystem_location_is_instance_root(
779  const rtems_filesystem_location_info_t *loc
780)
781{
782  const rtems_filesystem_mount_table_entry_t *mt_entry = loc->mt_entry;
783
784  return (*mt_entry->ops->are_nodes_equal_h)(
785    loc,
786    &mt_entry->mt_fs_root->location
787  );
788}
789
790static inline const char *rtems_filesystem_eval_path_get_path(
791  const rtems_filesystem_eval_path_context_t *ctx
792)
793{
794  return ctx->path;
795}
796
797static inline size_t rtems_filesystem_eval_path_get_pathlen(
798  const rtems_filesystem_eval_path_context_t *ctx
799)
800{
801  return ctx->pathlen;
802}
803
804static inline void rtems_filesystem_eval_path_set_path(
805  rtems_filesystem_eval_path_context_t *ctx,
806  const char *path,
807  size_t pathlen
808)
809{
810  ctx->path = path;
811  ctx->pathlen = pathlen;
812}
813
814static inline void rtems_filesystem_eval_path_clear_path(
815  rtems_filesystem_eval_path_context_t *ctx
816)
817{
818  ctx->pathlen = 0;
819}
820
821static inline const char *rtems_filesystem_eval_path_get_token(
822  const rtems_filesystem_eval_path_context_t *ctx
823)
824{
825  return ctx->token;
826}
827
828static inline size_t rtems_filesystem_eval_path_get_tokenlen(
829  const rtems_filesystem_eval_path_context_t *ctx
830)
831{
832  return ctx->tokenlen;
833}
834
835static inline void rtems_filesystem_eval_path_set_token(
836  rtems_filesystem_eval_path_context_t *ctx,
837  const char *token,
838  size_t tokenlen
839)
840{
841  ctx->token = token;
842  ctx->tokenlen = tokenlen;
843}
844
845static inline void rtems_filesystem_eval_path_clear_token(
846  rtems_filesystem_eval_path_context_t *ctx
847)
848{
849  ctx->tokenlen = 0;
850}
851
852static inline void rtems_filesystem_eval_path_put_back_token(
853  rtems_filesystem_eval_path_context_t *ctx
854)
855{
856  size_t tokenlen = ctx->tokenlen;
857
858  ctx->path -= tokenlen;
859  ctx->pathlen += tokenlen;
860  ctx->tokenlen = 0;
861}
862
863void rtems_filesystem_eval_path_eat_delimiter(
864  rtems_filesystem_eval_path_context_t *ctx
865);
866
867void rtems_filesystem_eval_path_next_token(
868  rtems_filesystem_eval_path_context_t *ctx
869);
870
871static inline void rtems_filesystem_eval_path_get_next_token(
872  rtems_filesystem_eval_path_context_t *ctx,
873  const char **token,
874  size_t *tokenlen
875)
876{
877  rtems_filesystem_eval_path_next_token(ctx);
878  *token = ctx->token;
879  *tokenlen = ctx->tokenlen;
880}
881
882static inline rtems_filesystem_location_info_t *
883rtems_filesystem_eval_path_get_currentloc(
884  rtems_filesystem_eval_path_context_t *ctx
885)
886{
887  return &ctx->currentloc;
888}
889
890static inline bool rtems_filesystem_eval_path_has_path(
891  const rtems_filesystem_eval_path_context_t *ctx
892)
893{
894  return ctx->pathlen > 0;
895}
896
897static inline bool rtems_filesystem_eval_path_has_token(
898  const rtems_filesystem_eval_path_context_t *ctx
899)
900{
901  return ctx->tokenlen > 0;
902}
903
904static inline int rtems_filesystem_eval_path_get_flags(
905  const rtems_filesystem_eval_path_context_t *ctx
906)
907{
908  return ctx->flags;
909}
910
911static inline void rtems_filesystem_eval_path_set_flags(
912  rtems_filesystem_eval_path_context_t *ctx,
913  int flags
914)
915{
916  ctx->flags = flags;
917}
918
919static inline void rtems_filesystem_eval_path_clear_and_set_flags(
920  rtems_filesystem_eval_path_context_t *ctx,
921  int clear,
922  int set
923)
924{
925  int flags = ctx->flags;
926
927  flags &= ~clear;
928  flags |= set;
929
930  ctx->flags = flags;
931}
932
933static inline void rtems_filesystem_eval_path_extract_currentloc(
934  rtems_filesystem_eval_path_context_t *ctx,
935  rtems_filesystem_location_info_t *get
936)
937{
938  rtems_filesystem_location_copy_and_detach(
939    get,
940    &ctx->currentloc
941  );
942}
943
944void rtems_filesystem_eval_path_error(
945  rtems_filesystem_eval_path_context_t *ctx,
946  int eno
947);
948
949/**
950 * @brief Checks that the locations exist in the same file system instance.
951 *
952 * @retval 0 The locations exist and are in the same file system instance.
953 * @retval -1 An error occurred.  The @c errno indicates the error.
954 */
955int rtems_filesystem_location_exists_in_same_instance_as(
956  const rtems_filesystem_location_info_t *a,
957  const rtems_filesystem_location_info_t *b
958);
959
960/**
961 * @brief Checks if access to an object is allowed for the current user.
962 *
963 * If the effective UID is zero or equals the UID of the object, then the user
964 * permission flags of the object will be used.  Otherwise if the effective GID
965 * is zero or equals the GID of the object or one of the supplementary group
966 * IDs is equal to the GID of the object, then the group permission flags of
967 * the object will be used.  Otherwise the other permission flags of the object
968 * will be used.
969 *
970 * @param[in] flags The flags determining the access type.  It can be
971 *   RTEMS_FS_PERMS_READ, RTEMS_FS_PERMS_WRITE or RTEMS_FS_PERMS_EXEC.
972 * @param[in] object_mode The mode of the object specifying the permission flags.
973 * @param[in] object_uid The UID of the object.
974 * @param[in] object_gid The GID of the object.
975 *
976 * @retval true Access is allowed.
977 * @retval false Otherwise.
978 */
979bool rtems_filesystem_check_access(
980  int flags,
981  mode_t object_mode,
982  uid_t object_uid,
983  gid_t object_gid
984);
985
986bool rtems_filesystem_eval_path_check_access(
987  rtems_filesystem_eval_path_context_t *ctx,
988  int eval_flags,
989  mode_t node_mode,
990  uid_t node_uid,
991  gid_t node_gid
992);
993
994static inline bool rtems_filesystem_is_delimiter(char c)
995{
996  return c == '/' || c == '\\';
997}
998
999static inline bool rtems_filesystem_is_current_directory(
1000  const char *token,
1001  size_t tokenlen
1002)
1003{
1004  return tokenlen == 1 && token [0] == '.';
1005}
1006
1007static inline bool rtems_filesystem_is_parent_directory(
1008  const char *token,
1009  size_t tokenlen
1010)
1011{
1012  return tokenlen == 2 && token [0] == '.' && token [1] == '.';
1013}
1014
1015typedef ssize_t ( *rtems_libio_iovec_adapter )(
1016  rtems_libio_t      *iop,
1017  const struct iovec *iov,
1018  int                 iovcnt,
1019  ssize_t             total
1020);
1021
1022static inline ssize_t rtems_libio_iovec_eval(
1023  int                        fd,
1024  const struct iovec        *iov,
1025  int                        iovcnt,
1026  unsigned int               flags,
1027  rtems_libio_iovec_adapter  adapter
1028)
1029{
1030  ssize_t        total;
1031  int            v;
1032  rtems_libio_t *iop;
1033
1034  /*
1035   *  Argument validation on IO vector
1036   */
1037  if ( iov == NULL )
1038    rtems_set_errno_and_return_minus_one( EINVAL );
1039
1040  if ( iovcnt <= 0 )
1041    rtems_set_errno_and_return_minus_one( EINVAL );
1042
1043  if ( iovcnt > IOV_MAX )
1044    rtems_set_errno_and_return_minus_one( EINVAL );
1045
1046  /*
1047   *  OpenGroup says that you are supposed to return EINVAL if the
1048   *  sum of the iov_len values in the iov array would overflow a
1049   *  ssize_t.
1050   */
1051  total = 0;
1052  for ( v = 0 ; v < iovcnt ; ++v ) {
1053    size_t len = iov[ v ].iov_len;
1054
1055    if ( len > ( size_t ) ( SSIZE_MAX - total ) ) {
1056      rtems_set_errno_and_return_minus_one( EINVAL );
1057    }
1058
1059    total += ( ssize_t ) len;
1060
1061    if ( iov[ v ].iov_base == NULL && len != 0 ) {
1062      rtems_set_errno_and_return_minus_one( EINVAL );
1063    }
1064  }
1065
1066  LIBIO_GET_IOP_WITH_ACCESS( fd, iop, flags, EBADF );
1067
1068  if ( total > 0 ) {
1069    total = ( *adapter )( iop, iov, iovcnt, total );
1070  }
1071
1072  rtems_libio_iop_drop( iop );
1073  return total;
1074}
1075
1076/**
1077 * @brief Returns the file type of the file referenced by the filesystem
1078 * location.
1079 *
1080 * @brief[in] loc The filesystem location.
1081 *
1082 * @return The type of the file or an invalid file type in case of an error.
1083 */
1084static inline mode_t rtems_filesystem_location_type(
1085  const rtems_filesystem_location_info_t *loc
1086)
1087{
1088  struct stat st;
1089
1090  st.st_mode = 0;
1091  (void) ( *loc->handlers->fstat_h )( loc, &st );
1092
1093  return st.st_mode;
1094}
1095
1096/** @} */
1097
1098#ifdef __cplusplus
1099}
1100#endif
1101
1102#endif
1103/* end of include file */
Note: See TracBrowser for help on using the repository browser.