RTEMS  5.0.0
libio_.h
Go to the documentation of this file.
1 
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 #include <rtems/score/assert.h>
33 
34 #ifdef __cplusplus
35 extern "C" {
36 #endif
37 
46 #define RTEMS_FILESYSTEM_SYMLOOP_MAX 32
47 
48 /*
49  * Not defined in newlib so provide here. Users should use dup2 and
50  * not this non-portable fcntl command. Provided here to allow the
51  * RTEMS implementation to work.
52  */
53 #define F_DUP2FD 20
54 
55 /*
56  * File descriptor Table Information
57  */
58 
59 extern const uint32_t rtems_libio_number_iops;
60 extern rtems_libio_t rtems_libio_iops[];
61 extern void *rtems_libio_iop_free_head;
62 extern void **rtems_libio_iop_free_tail;
63 
64 extern const rtems_filesystem_file_handlers_r rtems_filesystem_null_handlers;
65 
66 extern rtems_filesystem_mount_table_entry_t rtems_filesystem_null_mt_entry;
67 
84 
95 static inline void rtems_libio_iop_flags_initialize(
96  rtems_libio_t *iop,
97  uint32_t flags
98 )
99 {
100  _Atomic_Store_uint(
101  &iop->flags,
102  LIBIO_FLAGS_OPEN | flags,
103  ATOMIC_ORDER_RELEASE
104  );
105 }
106 
115 static inline unsigned int rtems_libio_iop_flags_set(
116  rtems_libio_t *iop,
117  unsigned int set
118 )
119 {
120  return _Atomic_Fetch_or_uint( &iop->flags, set, ATOMIC_ORDER_RELAXED );
121 }
122 
131 static inline unsigned int rtems_libio_iop_flags_clear(
132  rtems_libio_t *iop,
133  unsigned int clear
134 )
135 {
136  return _Atomic_Fetch_and_uint( &iop->flags, ~clear, ATOMIC_ORDER_RELAXED );
137 }
138 
148 static inline rtems_libio_t *rtems_libio_iop( int fd )
149 {
150  return &rtems_libio_iops[ fd ];
151 }
152 
160 static inline unsigned int rtems_libio_iop_hold( rtems_libio_t *iop )
161 {
162  return _Atomic_Fetch_add_uint(
163  &iop->flags,
164  LIBIO_FLAGS_REFERENCE_INC,
165  ATOMIC_ORDER_ACQUIRE
166  );
167 }
168 
174 static inline void rtems_libio_iop_drop( rtems_libio_t *iop )
175 {
176 #if defined(RTEMS_DEBUG)
177  unsigned int flags;
178  bool success;
179 
180  flags = _Atomic_Load_uint( &iop->flags, ATOMIC_ORDER_RELAXED );
181 
182  do {
183  unsigned int desired;
184 
185  _Assert( flags >= LIBIO_FLAGS_REFERENCE_INC );
186 
187  desired = flags - LIBIO_FLAGS_REFERENCE_INC;
188  success = _Atomic_Compare_exchange_uint(
189  &iop->flags,
190  &flags,
191  desired,
192  ATOMIC_ORDER_RELEASE,
193  ATOMIC_ORDER_RELAXED
194  );
195  } while ( !success );
196 #else
197  _Atomic_Fetch_sub_uint(
198  &iop->flags,
199  LIBIO_FLAGS_REFERENCE_INC,
200  ATOMIC_ORDER_RELEASE
201  );
202 #endif
203 }
204 
205 /*
206  * rtems_libio_iop_to_descriptor
207  *
208  * Macro to convert an internal file descriptor pointer (iop) into
209  * the integer file descriptor used by the "section 2" system calls.
210  */
211 
212 #define rtems_libio_iop_to_descriptor(_iop) \
213  ((_iop) - &rtems_libio_iops[0])
214 
215 /*
216  * rtems_libio_check_is_open
217  *
218  * Macro to check if a file descriptor is actually open.
219  */
220 
221 #define rtems_libio_check_is_open(_iop) \
222  do { \
223  if (((_iop)->flags & LIBIO_FLAGS_OPEN) == 0) { \
224  errno = EBADF; \
225  return -1; \
226  } \
227  } while (0)
228 
234 #define LIBIO_GET_IOP( _fd, _iop ) \
235  do { \
236  unsigned int _flags; \
237  if ( (uint32_t) ( _fd ) >= rtems_libio_number_iops ) { \
238  rtems_set_errno_and_return_minus_one( EBADF ); \
239  } \
240  _iop = rtems_libio_iop( _fd ); \
241  _flags = rtems_libio_iop_hold( _iop ); \
242  if ( ( _flags & LIBIO_FLAGS_OPEN ) == 0 ) { \
243  rtems_libio_iop_drop( _iop ); \
244  rtems_set_errno_and_return_minus_one( EBADF ); \
245  } \
246  } while ( 0 )
247 
254 #define LIBIO_GET_IOP_WITH_ACCESS( _fd, _iop, _access_flags, _access_error ) \
255  do { \
256  unsigned int _flags; \
257  unsigned int _mandatory; \
258  if ( (uint32_t) ( _fd ) >= rtems_libio_number_iops ) { \
259  rtems_set_errno_and_return_minus_one( EBADF ); \
260  } \
261  _iop = rtems_libio_iop( _fd ); \
262  _flags = rtems_libio_iop_hold( _iop ); \
263  _mandatory = LIBIO_FLAGS_OPEN | ( _access_flags ); \
264  if ( ( _flags & _mandatory ) != _mandatory ) { \
265  int _error; \
266  rtems_libio_iop_drop( _iop ); \
267  if ( ( _flags & LIBIO_FLAGS_OPEN ) == 0 ) { \
268  _error = EBADF; \
269  } else { \
270  _error = _access_error; \
271  } \
272  rtems_set_errno_and_return_minus_one( _error ); \
273  } \
274  } while ( 0 )
275 
276 /*
277  * rtems_libio_check_buffer
278  *
279  * Macro to check if a buffer pointer is valid.
280  */
281 
282 #define rtems_libio_check_buffer(_buffer) \
283  do { \
284  if ((_buffer) == 0) { \
285  errno = EINVAL; \
286  return -1; \
287  } \
288  } while (0)
289 
290 /*
291  * rtems_libio_check_count
292  *
293  * Macro to check if a count or length is valid.
294  */
295 
296 #define rtems_libio_check_count(_count) \
297  do { \
298  if ((_count) == 0) { \
299  return 0; \
300  } \
301  } while (0)
302 
316 );
317 
331 
332 /*
333  * External structures
334  */
335 #include <rtems/userenv.h>
336 
337 void rtems_libio_free_user_env( void *env );
338 
339 extern pthread_key_t rtems_current_user_env_key;
340 
341 void rtems_libio_lock( void );
342 
343 void rtems_libio_unlock( void );
344 
345 static inline void rtems_filesystem_mt_lock( void )
346 {
347  rtems_libio_lock();
348 }
349 
350 static inline void rtems_filesystem_mt_unlock( void )
351 {
352  rtems_libio_unlock();
353 }
354 
355 extern rtems_interrupt_lock rtems_filesystem_mt_entry_lock_control;
356 
357 #define rtems_filesystem_mt_entry_declare_lock_context( ctx ) \
358  rtems_interrupt_lock_context ctx
359 
360 #define rtems_filesystem_mt_entry_lock( ctx ) \
361  rtems_interrupt_lock_acquire( &rtems_filesystem_mt_entry_lock_control, &ctx )
362 
363 #define rtems_filesystem_mt_entry_unlock( ctx ) \
364  rtems_interrupt_lock_release( &rtems_filesystem_mt_entry_lock_control, &ctx )
365 
366 static inline void rtems_filesystem_instance_lock(
368 )
369 {
370  const rtems_filesystem_mount_table_entry_t *mt_entry = loc->mt_entry;
371 
372  (*mt_entry->ops->lock_h)( mt_entry );
373 }
374 
375 static inline void rtems_filesystem_instance_unlock(
377 )
378 {
379  const rtems_filesystem_mount_table_entry_t *mt_entry = loc->mt_entry;
380 
381  (*mt_entry->ops->unlock_h)( mt_entry );
382 }
383 
384 /*
385  * File Descriptor Routine Prototypes
386  */
387 
393 
397 unsigned int rtems_libio_fcntl_flags( int fcntl_flags );
398 
402 int rtems_libio_to_fcntl_flags( unsigned int flags );
403 
408 void rtems_libio_free(
409  rtems_libio_t *iop
410 );
411 
412 /*
413  * File System Routine Prototypes
414  */
415 
417 rtems_filesystem_eval_path_start(
419  const char *path,
420  int eval_flags
421 );
422 
424 rtems_filesystem_eval_path_start_with_parent(
426  const char *path,
427  int eval_flags,
429  int parent_eval_flags
430 );
431 
433 rtems_filesystem_eval_path_start_with_root_and_current(
435  const char *path,
436  size_t pathlen,
437  int eval_flags,
438  rtems_filesystem_global_location_t *const *global_root_ptr,
439  rtems_filesystem_global_location_t *const *global_current_ptr
440 );
441 
442 void rtems_filesystem_eval_path_continue(
444 );
445 
446 void rtems_filesystem_eval_path_cleanup(
448 );
449 
450 void rtems_filesystem_eval_path_recursive(
452  const char *path,
453  size_t pathlen
454 );
455 
456 void rtems_filesystem_eval_path_cleanup_with_parent(
459 );
460 
476  rtems_filesystem_global_location_t **newstartloc_ptr
477 );
478 
479 typedef enum {
480  RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_CONTINUE,
481  RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_DONE,
482  RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_NO_ENTRY
483 } rtems_filesystem_eval_path_generic_status;
484 
498  void *arg
499 );
500 
513 typedef rtems_filesystem_eval_path_generic_status
516  void *arg,
517  const char *token,
518  size_t tokenlen
519 );
520 
521 typedef struct {
525 
526 void rtems_filesystem_eval_path_generic(
528  void *arg,
530 );
531 
532 void rtems_filesystem_initialize(void);
533 
550 );
551 
552 static inline rtems_filesystem_location_info_t *
553 rtems_filesystem_location_initialize_to_null(
555 )
556 {
558  loc,
559  &rtems_filesystem_global_location_null.location
560  );
561 }
562 
564 rtems_filesystem_location_transform_to_global(
566 );
567 
576  rtems_filesystem_global_location_t **lhs_global_loc_ptr,
577  rtems_filesystem_global_location_t *rhs_global_loc
578 );
579 
600  rtems_filesystem_global_location_t *const *global_loc_ptr
601 );
602 
622  bool deferred
623 );
624 
625 void rtems_filesystem_location_detach(
627 );
628 
629 void rtems_filesystem_location_copy_and_detach(
632 );
633 
635 rtems_filesystem_global_location_obtain_null(void)
636 {
638 
639  return rtems_filesystem_global_location_obtain( &global_loc );
640 }
641 
642 static inline bool rtems_filesystem_location_is_null(
644 )
645 {
646  return loc->handlers == &rtems_filesystem_null_handlers;
647 }
648 
649 static inline bool rtems_filesystem_global_location_is_null(
650  const rtems_filesystem_global_location_t *global_loc
651 )
652 {
653  return rtems_filesystem_location_is_null( &global_loc->location );
654 }
655 
656 static inline void rtems_filesystem_location_error(
658  int eno
659 )
660 {
661  if ( !rtems_filesystem_location_is_null( loc ) ) {
662  errno = eno;
663  }
664 }
665 
666 int rtems_filesystem_mknod(
667  const rtems_filesystem_location_info_t *parentloc,
668  const char *name,
669  size_t namelen,
670  mode_t mode,
671  dev_t dev
672 );
673 
674 int rtems_filesystem_chdir( rtems_filesystem_location_info_t *loc );
675 
676 int rtems_filesystem_chmod(
678  mode_t mode
679 );
680 
681 int rtems_filesystem_chown(
683  uid_t owner,
684  gid_t group
685 );
686 
687 static inline bool rtems_filesystem_is_ready_for_unmount(
689 )
690 {
691  bool ready = !mt_entry->mounted
692  && rtems_chain_has_only_one_node( &mt_entry->location_chain )
693  && mt_entry->mt_fs_root->reference_count == 1;
694 
695  if ( ready ) {
696  rtems_chain_initialize_empty( &mt_entry->location_chain );
697  }
698 
699  return ready;
700 }
701 
702 static inline void rtems_filesystem_location_add_to_mt_entry(
704 )
705 {
706  rtems_filesystem_mt_entry_declare_lock_context( lock_context );
707 
708  rtems_filesystem_mt_entry_lock( lock_context );
710  &loc->mt_entry->location_chain,
711  &loc->mt_entry_node
712  );
713  rtems_filesystem_mt_entry_unlock( lock_context );
714 }
715 
716 void rtems_filesystem_location_remove_from_mt_entry(
718 );
719 
720 void rtems_filesystem_do_unmount(
722 );
723 
724 static inline bool rtems_filesystem_location_is_instance_root(
726 )
727 {
728  const rtems_filesystem_mount_table_entry_t *mt_entry = loc->mt_entry;
729 
730  return (*mt_entry->ops->are_nodes_equal_h)(
731  loc,
732  &mt_entry->mt_fs_root->location
733  );
734 }
735 
736 static inline const char *rtems_filesystem_eval_path_get_path(
738 )
739 {
740  return ctx->path;
741 }
742 
743 static inline size_t rtems_filesystem_eval_path_get_pathlen(
745 )
746 {
747  return ctx->pathlen;
748 }
749 
750 static inline void rtems_filesystem_eval_path_set_path(
752  const char *path,
753  size_t pathlen
754 )
755 {
756  ctx->path = path;
757  ctx->pathlen = pathlen;
758 }
759 
760 static inline void rtems_filesystem_eval_path_clear_path(
762 )
763 {
764  ctx->pathlen = 0;
765 }
766 
767 static inline const char *rtems_filesystem_eval_path_get_token(
769 )
770 {
771  return ctx->token;
772 }
773 
774 static inline size_t rtems_filesystem_eval_path_get_tokenlen(
776 )
777 {
778  return ctx->tokenlen;
779 }
780 
781 static inline void rtems_filesystem_eval_path_set_token(
783  const char *token,
784  size_t tokenlen
785 )
786 {
787  ctx->token = token;
788  ctx->tokenlen = tokenlen;
789 }
790 
791 static inline void rtems_filesystem_eval_path_clear_token(
793 )
794 {
795  ctx->tokenlen = 0;
796 }
797 
798 static inline void rtems_filesystem_eval_path_put_back_token(
800 )
801 {
802  size_t tokenlen = ctx->tokenlen;
803 
804  ctx->path -= tokenlen;
805  ctx->pathlen += tokenlen;
806  ctx->tokenlen = 0;
807 }
808 
809 void rtems_filesystem_eval_path_eat_delimiter(
811 );
812 
813 void rtems_filesystem_eval_path_next_token(
815 );
816 
817 static inline void rtems_filesystem_eval_path_get_next_token(
819  const char **token,
820  size_t *tokenlen
821 )
822 {
823  rtems_filesystem_eval_path_next_token(ctx);
824  *token = ctx->token;
825  *tokenlen = ctx->tokenlen;
826 }
827 
828 static inline rtems_filesystem_location_info_t *
829 rtems_filesystem_eval_path_get_currentloc(
831 )
832 {
833  return &ctx->currentloc;
834 }
835 
836 static inline bool rtems_filesystem_eval_path_has_path(
838 )
839 {
840  return ctx->pathlen > 0;
841 }
842 
843 static inline bool rtems_filesystem_eval_path_has_token(
845 )
846 {
847  return ctx->tokenlen > 0;
848 }
849 
850 static inline int rtems_filesystem_eval_path_get_flags(
852 )
853 {
854  return ctx->flags;
855 }
856 
857 static inline void rtems_filesystem_eval_path_set_flags(
859  int flags
860 )
861 {
862  ctx->flags = flags;
863 }
864 
865 static inline void rtems_filesystem_eval_path_clear_and_set_flags(
867  int clear,
868  int set
869 )
870 {
871  int flags = ctx->flags;
872 
873  flags &= ~clear;
874  flags |= set;
875 
876  ctx->flags = flags;
877 }
878 
879 static inline void rtems_filesystem_eval_path_extract_currentloc(
882 )
883 {
884  rtems_filesystem_location_copy_and_detach(
885  get,
886  &ctx->currentloc
887  );
888 }
889 
890 void rtems_filesystem_eval_path_error(
892  int eno
893 );
894 
904 );
905 
926  int flags,
927  mode_t object_mode,
928  uid_t object_uid,
929  gid_t object_gid
930 );
931 
932 bool rtems_filesystem_eval_path_check_access(
934  int eval_flags,
935  mode_t node_mode,
936  uid_t node_uid,
937  gid_t node_gid
938 );
939 
940 static inline bool rtems_filesystem_is_delimiter(char c)
941 {
942  return c == '/' || c == '\\';
943 }
944 
945 static inline bool rtems_filesystem_is_current_directory(
946  const char *token,
947  size_t tokenlen
948 )
949 {
950  return tokenlen == 1 && token [0] == '.';
951 }
952 
953 static inline bool rtems_filesystem_is_parent_directory(
954  const char *token,
955  size_t tokenlen
956 )
957 {
958  return tokenlen == 2 && token [0] == '.' && token [1] == '.';
959 }
960 
961 typedef ssize_t ( *rtems_libio_iovec_adapter )(
962  rtems_libio_t *iop,
963  const struct iovec *iov,
964  int iovcnt,
965  ssize_t total
966 );
967 
968 static inline ssize_t rtems_libio_iovec_eval(
969  int fd,
970  const struct iovec *iov,
971  int iovcnt,
972  unsigned int flags,
973  rtems_libio_iovec_adapter adapter
974 )
975 {
976  ssize_t total;
977  int v;
978  rtems_libio_t *iop;
979 
980  /*
981  * Argument validation on IO vector
982  */
983  if ( iov == NULL )
985 
986  if ( iovcnt <= 0 )
988 
989  if ( iovcnt > IOV_MAX )
991 
992  /*
993  * OpenGroup says that you are supposed to return EINVAL if the
994  * sum of the iov_len values in the iov array would overflow a
995  * ssize_t.
996  */
997  total = 0;
998  for ( v = 0 ; v < iovcnt ; ++v ) {
999  size_t len = iov[ v ].iov_len;
1000 
1001  if ( len > ( size_t ) ( SSIZE_MAX - total ) ) {
1003  }
1004 
1005  total += ( ssize_t ) len;
1006 
1007  if ( iov[ v ].iov_base == NULL && len != 0 ) {
1009  }
1010  }
1011 
1012  LIBIO_GET_IOP_WITH_ACCESS( fd, iop, flags, EBADF );
1013 
1014  if ( total > 0 ) {
1015  total = ( *adapter )( iop, iov, iovcnt, total );
1016  }
1017 
1018  rtems_libio_iop_drop( iop );
1019  return total;
1020 }
1021 
1030 static inline mode_t rtems_filesystem_location_type(
1032 )
1033 {
1034  struct stat st;
1035 
1036  st.st_mode = 0;
1037  (void) ( *loc->handlers->fstat_h )( loc, &st );
1038 
1039  return st.st_mode;
1040 }
1041 
1044 #ifdef __cplusplus
1045 }
1046 #endif
1047 
1048 #endif
1049 /* end of include file */
RTEMS_INLINE_ROUTINE bool rtems_chain_has_only_one_node(const rtems_chain_control *the_chain)
Does this chain have only one node.
Definition: chain.h:522
#define LIBIO_GET_IOP_WITH_ACCESS(_fd, _iop, _access_flags, _access_error)
Macro to get the iop for the specified file descriptor with access flags and error.
Definition: libio_.h:254
const char * token
Definition: libio.h:99
RTEMS_INLINE_ROUTINE void rtems_chain_initialize_empty(rtems_chain_control *the_chain)
Initialize this chain as empty.
Definition: chain.h:168
int rtems_filesystem_location_exists_in_same_instance_as(const rtems_filesystem_location_info_t *a, const rtems_filesystem_location_info_t *b)
Checks that the locations exist in the same file system instance.
Definition: sup_fs_exist_in_same_instance.c:28
Definition: deflate.c:115
void rtems_filesystem_global_location_release(rtems_filesystem_global_location_t *global_loc, bool deferred)
Releases a global file system location.
Definition: sup_fs_location.c:186
Basic IO API.
Data which Ease the Burden of Consistently Setting Errno.
User Environment Support.
int flags
Definition: libio.h:119
int rtems_libio_to_fcntl_flags(unsigned int flags)
Definition: libio.c:86
POSIX Threads Private Support.
rtems_filesystem_global_location_t rtems_filesystem_global_location_null
The global null location.
Definition: __usrenv.c:227
Definition: if_em.h:352
void rtems_libio_free(rtems_libio_t *iop)
Definition: libio.c:133
void rtems_filesystem_global_location_assign(rtems_filesystem_global_location_t **lhs_global_loc_ptr, rtems_filesystem_global_location_t *rhs_global_loc)
Assigns a global file system location.
Definition: sup_fs_location.c:96
size_t tokenlen
Definition: libio.h:105
ISR lock control.
Definition: isrlock.h:56
File system node operations table.
Definition: libio.h:1005
RTEMS_INLINE_ROUTINE void rtems_chain_append_unprotected(rtems_chain_control *the_chain, rtems_chain_node *the_node)
Append a node on the end of a chain (unprotected).
Definition: chain.h:679
void rtems_filesystem_location_clone(rtems_filesystem_location_info_t *clone, const rtems_filesystem_location_info_t *master)
Clones a node.
Definition: clonenode.c:28
bool(* rtems_filesystem_eval_path_is_directory)(rtems_filesystem_eval_path_context_t *ctx, void *arg)
Tests if the current location is a directory.
Definition: libio_.h:496
#define rtems_set_errno_and_return_minus_one(_error)
Definition: seterr.h:48
rtems_filesystem_location_info_t currentloc
Definition: libio.h:135
void rtems_filesystem_location_free(rtems_filesystem_location_info_t *loc)
Releases all resources of a location.
Definition: freenode.c:25
rtems_filesystem_eval_path_generic_status(* rtems_filesystem_eval_path_eval_token)(rtems_filesystem_eval_path_context_t *ctx, void *arg, const char *token, size_t tokenlen)
Evaluates a token.
Definition: libio_.h:514
Mount table entry.
Definition: libio.h:1606
Path evaluation context.
Definition: libio.h:84
unsigned int rtems_libio_fcntl_flags(int fcntl_flags)
Definition: libio.c:61
An open file data structure.
Definition: libio.h:1320
bool rtems_filesystem_check_access(int flags, mode_t object_mode, uid_t object_uid, gid_t object_gid)
Checks if access to an object is allowed for the current user.
Definition: sup_fs_check_permissions.c:89
const char * path
Definition: libio.h:88
rtems_libio_t * rtems_libio_allocate(void)
Definition: libio.c:109
rtems_filesystem_global_location_t * rtems_filesystem_global_location_obtain(rtems_filesystem_global_location_t *const *global_loc_ptr)
Obtains a global file system location.
Definition: sup_fs_location.c:163
size_t pathlen
Definition: libio.h:93
unsigned v
Definition: tte.h:73
void rtems_filesystem_eval_path_restart(rtems_filesystem_eval_path_context_t *ctx, rtems_filesystem_global_location_t **newstartloc_ptr)
Requests a path evaluation restart.
Definition: sup_fs_eval_path.c:317
rtems_filesystem_location_info_t * rtems_filesystem_location_copy(rtems_filesystem_location_info_t *dst, const rtems_filesystem_location_info_t *src)
Copies a location.
Definition: main_edit.c:207
Global file system location.
Definition: fs.h:81
void rtems_filesystem_initialize(void)
Base File System Initialization.
Definition: base_fs.c:32
#define NULL
Requests a GPIO pin group configuration.
Definition: bestcomm_api.h:77
File system location.
Definition: fs.h:53