RTEMS CPU Kit with SuperCore  4.11.3
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 
33 #ifdef __cplusplus
34 extern "C" {
35 #endif
36 
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 
61 extern rtems_id rtems_libio_semaphore;
62 
63 /*
64  * File descriptor Table Information
65  */
66 
67 extern const uint32_t rtems_libio_number_iops;
68 extern rtems_libio_t rtems_libio_iops[];
69 extern rtems_libio_t *rtems_libio_iop_freelist;
70 
71 extern const rtems_filesystem_file_handlers_r rtems_filesystem_null_handlers;
72 
73 extern rtems_filesystem_mount_table_entry_t rtems_filesystem_null_mt_entry;
74 
91 
92 /*
93  * rtems_libio_iop
94  *
95  * Macro to return the file descriptor pointer.
96  */
97 
98 #define rtems_libio_iop(_fd) \
99  ((((uint32_t)(_fd)) < rtems_libio_number_iops) ? \
100  &rtems_libio_iops[_fd] : 0)
101 
102 /*
103  * rtems_libio_iop_to_descriptor
104  *
105  * Macro to convert an internal file descriptor pointer (iop) into
106  * the integer file descriptor used by the "section 2" system calls.
107  */
108 
109 #define rtems_libio_iop_to_descriptor(_iop) \
110  ((_iop) - &rtems_libio_iops[0])
111 
112 /*
113  * rtems_libio_check_is_open
114  *
115  * Macro to check if a file descriptor is actually open.
116  */
117 
118 #define rtems_libio_check_is_open(_iop) \
119  do { \
120  if (((_iop)->flags & LIBIO_FLAGS_OPEN) == 0) { \
121  errno = EBADF; \
122  return -1; \
123  } \
124  } while (0)
125 
126 /*
127  * rtems_libio_check_fd
128  *
129  * Macro to check if a file descriptor number is valid.
130  */
131 
132 #define rtems_libio_check_fd(_fd) \
133  do { \
134  if ((uint32_t) (_fd) >= rtems_libio_number_iops) { \
135  errno = EBADF; \
136  return -1; \
137  } \
138  } while (0)
139 
140 /*
141  * rtems_libio_check_buffer
142  *
143  * Macro to check if a buffer pointer is valid.
144  */
145 
146 #define rtems_libio_check_buffer(_buffer) \
147  do { \
148  if ((_buffer) == 0) { \
149  errno = EINVAL; \
150  return -1; \
151  } \
152  } while (0)
153 
154 /*
155  * rtems_libio_check_count
156  *
157  * Macro to check if a count or length is valid.
158  */
159 
160 #define rtems_libio_check_count(_count) \
161  do { \
162  if ((_count) == 0) { \
163  return 0; \
164  } \
165  } while (0)
166 
167 /*
168  * rtems_libio_check_permissions_with_error
169  *
170  * Macro to check if a file descriptor is open for this operation.
171  * On failure, return the user specified error.
172  */
173 
174 #define rtems_libio_check_permissions_with_error(_iop, _flag, _errno) \
175  do { \
176  if (((_iop)->flags & (_flag)) == 0) { \
177  rtems_set_errno_and_return_minus_one( _errno ); \
178  return -1; \
179  } \
180  } while (0)
181 
182 /*
183  * rtems_libio_check_permissions
184  *
185  * Macro to check if a file descriptor is open for this operation.
186  * On failure, return EINVAL
187  */
188 
189 #define rtems_libio_check_permissions(_iop, _flag) \
190  rtems_libio_check_permissions_with_error(_iop, _flag, EINVAL )
191 
205 );
206 
220 
221 /*
222  * External structures
223  */
224 #include <rtems/userenv.h>
225 
226 void rtems_libio_free_user_env( void *env );
227 
228 extern pthread_key_t rtems_current_user_env_key;
229 
230 static inline void rtems_libio_lock( void )
231 {
232  rtems_semaphore_obtain( rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT );
233 }
234 
235 static inline void rtems_libio_unlock( void )
236 {
237  rtems_semaphore_release( rtems_libio_semaphore );
238 }
239 
240 static inline void rtems_filesystem_mt_lock( void )
241 {
242  rtems_libio_lock();
243 }
244 
245 static inline void rtems_filesystem_mt_unlock( void )
246 {
247  rtems_libio_unlock();
248 }
249 
250 extern rtems_interrupt_lock rtems_filesystem_mt_entry_lock_control;
251 
252 #define rtems_filesystem_mt_entry_declare_lock_context( ctx ) \
253  rtems_interrupt_lock_context ctx
254 
255 #define rtems_filesystem_mt_entry_lock( ctx ) \
256  rtems_interrupt_lock_acquire( &rtems_filesystem_mt_entry_lock_control, &ctx )
257 
258 #define rtems_filesystem_mt_entry_unlock( ctx ) \
259  rtems_interrupt_lock_release( &rtems_filesystem_mt_entry_lock_control, &ctx )
260 
261 static inline void rtems_filesystem_instance_lock(
263 )
264 {
265  const rtems_filesystem_mount_table_entry_t *mt_entry = loc->mt_entry;
266 
267  (*mt_entry->ops->lock_h)( mt_entry );
268 }
269 
270 static inline void rtems_filesystem_instance_unlock(
272 )
273 {
274  const rtems_filesystem_mount_table_entry_t *mt_entry = loc->mt_entry;
275 
276  (*mt_entry->ops->unlock_h)( mt_entry );
277 }
278 
279 /*
280  * File Descriptor Routine Prototypes
281  */
282 
288 
292 uint32_t rtems_libio_fcntl_flags( int fcntl_flags );
293 
297 int rtems_libio_to_fcntl_flags( uint32_t flags );
298 
303 void rtems_libio_free(
304  rtems_libio_t *iop
305 );
306 
307 /*
308  * File System Routine Prototypes
309  */
310 
312 rtems_filesystem_eval_path_start(
314  const char *path,
315  int eval_flags
316 );
317 
319 rtems_filesystem_eval_path_start_with_parent(
321  const char *path,
322  int eval_flags,
324  int parent_eval_flags
325 );
326 
328 rtems_filesystem_eval_path_start_with_root_and_current(
330  const char *path,
331  size_t pathlen,
332  int eval_flags,
333  rtems_filesystem_global_location_t *const *global_root_ptr,
334  rtems_filesystem_global_location_t *const *global_current_ptr
335 );
336 
337 void rtems_filesystem_eval_path_continue(
339 );
340 
341 void rtems_filesystem_eval_path_cleanup(
343 );
344 
345 void rtems_filesystem_eval_path_recursive(
347  const char *path,
348  size_t pathlen
349 );
350 
351 void rtems_filesystem_eval_path_cleanup_with_parent(
354 );
355 
371  rtems_filesystem_global_location_t **newstartloc_ptr
372 );
373 
374 typedef enum {
375  RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_CONTINUE,
376  RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_DONE,
377  RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_NO_ENTRY
378 } rtems_filesystem_eval_path_generic_status;
379 
393  void *arg
394 );
395 
408 typedef rtems_filesystem_eval_path_generic_status
411  void *arg,
412  const char *token,
413  size_t tokenlen
414 );
415 
416 typedef struct {
420 
421 void rtems_filesystem_eval_path_generic(
423  void *arg,
425 );
426 
427 void rtems_filesystem_initialize(void);
428 
445 );
446 
447 static inline rtems_filesystem_location_info_t *
448 rtems_filesystem_location_initialize_to_null(
450 )
451 {
453  loc,
454  &rtems_filesystem_global_location_null.location
455  );
456 }
457 
459 rtems_filesystem_location_transform_to_global(
461 );
462 
471  rtems_filesystem_global_location_t **lhs_global_loc_ptr,
472  rtems_filesystem_global_location_t *rhs_global_loc
473 );
474 
495  rtems_filesystem_global_location_t *const *global_loc_ptr
496 );
497 
517  bool deferred
518 );
519 
520 void rtems_filesystem_location_detach(
522 );
523 
524 void rtems_filesystem_location_copy_and_detach(
527 );
528 
530 rtems_filesystem_global_location_obtain_null(void)
531 {
532  rtems_filesystem_global_location_t *global_loc = NULL;
533 
534  return rtems_filesystem_global_location_obtain( &global_loc );
535 }
536 
537 static inline bool rtems_filesystem_location_is_null(
539 )
540 {
541  return loc->handlers == &rtems_filesystem_null_handlers;
542 }
543 
544 static inline bool rtems_filesystem_global_location_is_null(
545  const rtems_filesystem_global_location_t *global_loc
546 )
547 {
548  return rtems_filesystem_location_is_null( &global_loc->location );
549 }
550 
551 static inline void rtems_filesystem_location_error(
553  int eno
554 )
555 {
556  if ( !rtems_filesystem_location_is_null( loc ) ) {
557  errno = eno;
558  }
559 }
560 
561 int rtems_filesystem_mknod(
562  const rtems_filesystem_location_info_t *parentloc,
563  const char *name,
564  size_t namelen,
565  mode_t mode,
566  dev_t dev
567 );
568 
569 int rtems_filesystem_chdir( rtems_filesystem_location_info_t *loc );
570 
571 int rtems_filesystem_chmod(
573  mode_t mode
574 );
575 
576 int rtems_filesystem_chown(
578  uid_t owner,
579  gid_t group
580 );
581 
582 static inline bool rtems_filesystem_is_ready_for_unmount(
584 )
585 {
586  bool ready = !mt_entry->mounted
587  && rtems_chain_has_only_one_node( &mt_entry->location_chain )
588  && mt_entry->mt_fs_root->reference_count == 1;
589 
590  if ( ready ) {
591  rtems_chain_initialize_empty( &mt_entry->location_chain );
592  }
593 
594  return ready;
595 }
596 
597 static inline void rtems_filesystem_location_add_to_mt_entry(
599 )
600 {
601  rtems_filesystem_mt_entry_declare_lock_context( lock_context );
602 
603  rtems_filesystem_mt_entry_lock( lock_context );
605  &loc->mt_entry->location_chain,
606  &loc->mt_entry_node
607  );
608  rtems_filesystem_mt_entry_unlock( lock_context );
609 }
610 
611 void rtems_filesystem_location_remove_from_mt_entry(
613 );
614 
615 void rtems_filesystem_do_unmount(
617 );
618 
619 static inline bool rtems_filesystem_location_is_instance_root(
621 )
622 {
623  const rtems_filesystem_mount_table_entry_t *mt_entry = loc->mt_entry;
624 
625  return (*mt_entry->ops->are_nodes_equal_h)(
626  loc,
627  &mt_entry->mt_fs_root->location
628  );
629 }
630 
631 static inline const char *rtems_filesystem_eval_path_get_path(
633 )
634 {
635  return ctx->path;
636 }
637 
638 static inline size_t rtems_filesystem_eval_path_get_pathlen(
640 )
641 {
642  return ctx->pathlen;
643 }
644 
645 static inline void rtems_filesystem_eval_path_set_path(
647  const char *path,
648  size_t pathlen
649 )
650 {
651  ctx->path = path;
652  ctx->pathlen = pathlen;
653 }
654 
655 static inline void rtems_filesystem_eval_path_clear_path(
657 )
658 {
659  ctx->pathlen = 0;
660 }
661 
662 static inline const char *rtems_filesystem_eval_path_get_token(
664 )
665 {
666  return ctx->token;
667 }
668 
669 static inline size_t rtems_filesystem_eval_path_get_tokenlen(
671 )
672 {
673  return ctx->tokenlen;
674 }
675 
676 static inline void rtems_filesystem_eval_path_set_token(
678  const char *token,
679  size_t tokenlen
680 )
681 {
682  ctx->token = token;
683  ctx->tokenlen = tokenlen;
684 }
685 
686 static inline void rtems_filesystem_eval_path_clear_token(
688 )
689 {
690  ctx->tokenlen = 0;
691 }
692 
693 static inline void rtems_filesystem_eval_path_put_back_token(
695 )
696 {
697  size_t tokenlen = ctx->tokenlen;
698 
699  ctx->path -= tokenlen;
700  ctx->pathlen += tokenlen;
701  ctx->tokenlen = 0;
702 }
703 
704 void rtems_filesystem_eval_path_eat_delimiter(
706 );
707 
708 void rtems_filesystem_eval_path_next_token(
710 );
711 
712 static inline void rtems_filesystem_eval_path_get_next_token(
714  const char **token,
715  size_t *tokenlen
716 )
717 {
718  rtems_filesystem_eval_path_next_token(ctx);
719  *token = ctx->token;
720  *tokenlen = ctx->tokenlen;
721 }
722 
723 static inline rtems_filesystem_location_info_t *
724 rtems_filesystem_eval_path_get_currentloc(
726 )
727 {
728  return &ctx->currentloc;
729 }
730 
731 static inline bool rtems_filesystem_eval_path_has_path(
733 )
734 {
735  return ctx->pathlen > 0;
736 }
737 
738 static inline bool rtems_filesystem_eval_path_has_token(
740 )
741 {
742  return ctx->tokenlen > 0;
743 }
744 
745 static inline int rtems_filesystem_eval_path_get_flags(
747 )
748 {
749  return ctx->flags;
750 }
751 
752 static inline void rtems_filesystem_eval_path_set_flags(
754  int flags
755 )
756 {
757  ctx->flags = flags;
758 }
759 
760 static inline void rtems_filesystem_eval_path_clear_and_set_flags(
762  int clear,
763  int set
764 )
765 {
766  int flags = ctx->flags;
767 
768  flags &= ~clear;
769  flags |= set;
770 
771  ctx->flags = flags;
772 }
773 
774 static inline void rtems_filesystem_eval_path_extract_currentloc(
777 )
778 {
779  rtems_filesystem_location_copy_and_detach(
780  get,
781  &ctx->currentloc
782  );
783 }
784 
785 void rtems_filesystem_eval_path_error(
787  int eno
788 );
789 
799 );
800 
821  int flags,
822  mode_t object_mode,
823  uid_t object_uid,
824  gid_t object_gid
825 );
826 
827 bool rtems_filesystem_eval_path_check_access(
829  int eval_flags,
830  mode_t node_mode,
831  uid_t node_uid,
832  gid_t node_gid
833 );
834 
835 static inline bool rtems_filesystem_is_delimiter(char c)
836 {
837  return c == '/' || c == '\\';
838 }
839 
840 static inline bool rtems_filesystem_is_current_directory(
841  const char *token,
842  size_t tokenlen
843 )
844 {
845  return tokenlen == 1 && token [0] == '.';
846 }
847 
848 static inline bool rtems_filesystem_is_parent_directory(
849  const char *token,
850  size_t tokenlen
851 )
852 {
853  return tokenlen == 2 && token [0] == '.' && token [1] == '.';
854 }
855 
856 static inline ssize_t rtems_libio_iovec_eval(
857  int fd,
858  const struct iovec *iov,
859  int iovcnt,
860  uint32_t flags,
861  rtems_libio_t **iopp
862 )
863 {
864  ssize_t total;
865  int v;
866  rtems_libio_t *iop;
867 
868  rtems_libio_check_fd( fd );
869  iop = rtems_libio_iop( fd );
870  rtems_libio_check_is_open( iop );
871  rtems_libio_check_permissions_with_error( iop, flags, EBADF );
872 
873  *iopp = iop;
874 
875  /*
876  * Argument validation on IO vector
877  */
878  if ( iov == NULL )
880 
881  if ( iovcnt <= 0 )
883 
884  if ( iovcnt > IOV_MAX )
886 
887  /*
888  * OpenGroup says that you are supposed to return EINVAL if the
889  * sum of the iov_len values in the iov array would overflow a
890  * ssize_t.
891  */
892  total = 0;
893  for ( v = 0 ; v < iovcnt ; ++v ) {
894  size_t len = iov[ v ].iov_len;
895 
896  if ( len > ( size_t ) ( SSIZE_MAX - total ) ) {
898  }
899 
900  total += ( ssize_t ) len;
901 
902  if ( iov[ v ].iov_base == NULL && len != 0 ) {
904  }
905  }
906 
907  return total;
908 }
909 
918 static inline mode_t rtems_filesystem_location_type(
920 )
921 {
922  struct stat st;
923 
924  st.st_mode = 0;
925  (void) ( *loc->handlers->fstat_h )( loc, &st );
926 
927  return st.st_mode;
928 }
929 
932 #ifdef __cplusplus
933 }
934 #endif
935 
936 #endif
937 /* 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:507
const char * token
The contents of the token to be evaluated with respect to the current location.
Definition: libio.h:98
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:116
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:185
Basic IO API.
Data which Ease the Burden of Consistently Setting Errno.
Objects_Id rtems_id
Used to manage and manipulate RTEMS object identifiers.
Definition: types.h:80
User Environment Support.
int flags
The path evaluation is controlled by the following flags.
Definition: libio.h:118
POSIX Threads Private Support.
rtems_filesystem_global_location_t rtems_filesystem_global_location_null
The global null location.
Definition: __usrenv.c:226
void rtems_libio_free(rtems_libio_t *iop)
This routine frees the resources associated with an IOP (file descriptor) and clears the slot in the ...
Definition: libio.c:132
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:95
size_t tokenlen
The length of the token to be evaluated with respect to the current location.
Definition: libio.h:104
ISR lock control.
Definition: isrlock.h:56
File system node operations table.
Definition: libio.h:982
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:692
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:391
#define rtems_set_errno_and_return_minus_one(_error)
This is a helper macro which will set the variable errno and return -1 to the caller.
Definition: seterr.h:48
rtems_status_code rtems_semaphore_release(rtems_id id)
RTEMS Semaphore Release.
Definition: semrelease.c:56
rtems_filesystem_location_info_t currentloc
This is the current file system location of the evaluation process.
Definition: libio.h:134
rtems_status_code rtems_semaphore_obtain(rtems_id id, rtems_option option_set, rtems_interval timeout)
RTEMS Obtain Semaphore.
Definition: semobtain.c:34
void rtems_filesystem_location_free(rtems_filesystem_location_info_t *loc)
Releases all resources of a location.
Definition: freenode.c:25
uint32_t rtems_libio_fcntl_flags(int fcntl_flags)
Convert UNIX fnctl(2) flags to ones that RTEMS drivers understand.
Definition: libio.c:62
#define RTEMS_NO_TIMEOUT
Constant for indefinite wait.
Definition: rtems.h:170
#define RTEMS_WAIT
This option constants indicates that the task is to wait on resource.
Definition: options.h:56
Definition: _iovec.h:53
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:409
Mount table entry.
Definition: libio.h:1542
Path evaluation context.
Definition: libio.h:83
int rtems_libio_to_fcntl_flags(uint32_t flags)
Convert RTEMS internal flags to UNIX fnctl(2) flags.
Definition: libio.c:87
An open file data structure.
Definition: libio.h:1281
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
The contents of the remaining path to be evaluated.
Definition: libio.h:87
rtems_libio_t * rtems_libio_allocate(void)
This routine searches the IOP Table for an unused entry.
Definition: libio.c:114
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:162
size_t pathlen
The length of the remaining path to be evaluated.
Definition: libio.h:92
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:208
Global file system location.
Definition: fs.h:81
void rtems_filesystem_initialize(void)
Base File System Initialization.
Definition: base_fs.c:32
File system location.
Definition: fs.h:53