source: rtems/cpukit/libcsupport/include/rtems/libio_.h @ ac74162

5
Last change on this file since ac74162 was ac74162, checked in by Sebastian Huber <sebastian.huber@…>, on 09/14/17 at 13:21:14

libio: Use FIFO for iop free list

Update #3136.

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