RTEMS 5.2
All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
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
35extern "C" {
36#endif
37
48#define RTEMS_FILESYSTEM_SYMLOOP_MAX 32
49
50/*
51 * Not defined in newlib so provide here. Users should use dup2 and
52 * not this non-portable fcntl command. Provided here to allow the
53 * RTEMS implementation to work.
54 */
55#define F_DUP2FD 20
56
57/*
58 * File descriptor Table Information
59 */
60
61extern const uint32_t rtems_libio_number_iops;
62extern rtems_libio_t rtems_libio_iops[];
63extern void *rtems_libio_iop_free_head;
64extern void **rtems_libio_iop_free_tail;
65
66extern const rtems_filesystem_file_handlers_r rtems_filesystem_null_handlers;
67
68extern rtems_filesystem_mount_table_entry_t rtems_filesystem_null_mt_entry;
69
86
95static inline unsigned int rtems_libio_iop_flags_set(
96 rtems_libio_t *iop,
97 unsigned int set
98)
99{
100 return _Atomic_Fetch_or_uint( &iop->flags, set, ATOMIC_ORDER_RELAXED );
101}
102
111static inline unsigned int rtems_libio_iop_flags_clear(
112 rtems_libio_t *iop,
113 unsigned int clear
114)
115{
116 return _Atomic_Fetch_and_uint( &iop->flags, ~clear, ATOMIC_ORDER_RELAXED );
117}
118
128static inline rtems_libio_t *rtems_libio_iop( int fd )
129{
130 return &rtems_libio_iops[ fd ];
131}
132
140static inline unsigned int rtems_libio_iop_hold( rtems_libio_t *iop )
141{
142 return _Atomic_Fetch_add_uint(
143 &iop->flags,
144 LIBIO_FLAGS_REFERENCE_INC,
145 ATOMIC_ORDER_ACQUIRE
146 );
147}
148
154static inline void rtems_libio_iop_drop( rtems_libio_t *iop )
155{
156#if defined(RTEMS_DEBUG)
157 unsigned int flags;
158 bool success;
159
160 flags = _Atomic_Load_uint( &iop->flags, ATOMIC_ORDER_RELAXED );
161
162 do {
163 unsigned int desired;
164
165 _Assert( flags >= LIBIO_FLAGS_REFERENCE_INC );
166
167 desired = flags - LIBIO_FLAGS_REFERENCE_INC;
168 success = _Atomic_Compare_exchange_uint(
169 &iop->flags,
170 &flags,
171 desired,
172 ATOMIC_ORDER_RELEASE,
173 ATOMIC_ORDER_RELAXED
174 );
175 } while ( !success );
176#else
177 _Atomic_Fetch_sub_uint(
178 &iop->flags,
179 LIBIO_FLAGS_REFERENCE_INC,
180 ATOMIC_ORDER_RELEASE
181 );
182#endif
183}
184
185/*
186 * rtems_libio_iop_to_descriptor
187 *
188 * Macro to convert an internal file descriptor pointer (iop) into
189 * the integer file descriptor used by the "section 2" system calls.
190 */
191
192#define rtems_libio_iop_to_descriptor(_iop) \
193 ((_iop) - &rtems_libio_iops[0])
194
195/*
196 * rtems_libio_check_is_open
197 *
198 * Macro to check if a file descriptor is actually open.
199 */
200
201#define rtems_libio_check_is_open(_iop) \
202 do { \
203 if ((rtems_libio_iop_flags(_iop) & LIBIO_FLAGS_OPEN) == 0) { \
204 errno = EBADF; \
205 return -1; \
206 } \
207 } while (0)
208
214#define LIBIO_GET_IOP( _fd, _iop ) \
215 do { \
216 unsigned int _flags; \
217 if ( (uint32_t) ( _fd ) >= rtems_libio_number_iops ) { \
218 rtems_set_errno_and_return_minus_one( EBADF ); \
219 } \
220 _iop = rtems_libio_iop( _fd ); \
221 _flags = rtems_libio_iop_hold( _iop ); \
222 if ( ( _flags & LIBIO_FLAGS_OPEN ) == 0 ) { \
223 rtems_libio_iop_drop( _iop ); \
224 rtems_set_errno_and_return_minus_one( EBADF ); \
225 } \
226 } while ( 0 )
227
234#define LIBIO_GET_IOP_WITH_ACCESS( _fd, _iop, _access_flags, _access_error ) \
235 do { \
236 unsigned int _flags; \
237 unsigned int _mandatory; \
238 if ( (uint32_t) ( _fd ) >= rtems_libio_number_iops ) { \
239 rtems_set_errno_and_return_minus_one( EBADF ); \
240 } \
241 _iop = rtems_libio_iop( _fd ); \
242 _flags = rtems_libio_iop_hold( _iop ); \
243 _mandatory = LIBIO_FLAGS_OPEN | ( _access_flags ); \
244 if ( ( _flags & _mandatory ) != _mandatory ) { \
245 int _error; \
246 rtems_libio_iop_drop( _iop ); \
247 if ( ( _flags & LIBIO_FLAGS_OPEN ) == 0 ) { \
248 _error = EBADF; \
249 } else { \
250 _error = _access_error; \
251 } \
252 rtems_set_errno_and_return_minus_one( _error ); \
253 } \
254 } while ( 0 )
255
256/*
257 * rtems_libio_check_buffer
258 *
259 * Macro to check if a buffer pointer is valid.
260 */
261
262#define rtems_libio_check_buffer(_buffer) \
263 do { \
264 if ((_buffer) == 0) { \
265 errno = EINVAL; \
266 return -1; \
267 } \
268 } while (0)
269
270/*
271 * rtems_libio_check_count
272 *
273 * Macro to check if a count or length is valid.
274 */
275
276#define rtems_libio_check_count(_count) \
277 do { \
278 if ((_count) == 0) { \
279 return 0; \
280 } \
281 } while (0)
282
296);
297
311
312/*
313 * External structures
314 */
315#include <rtems/userenv.h>
316
317void rtems_libio_lock( void );
318
319void rtems_libio_unlock( void );
320
321static inline void rtems_filesystem_mt_lock( void )
322{
323 rtems_libio_lock();
324}
325
326static inline void rtems_filesystem_mt_unlock( void )
327{
328 rtems_libio_unlock();
329}
330
331extern rtems_interrupt_lock rtems_filesystem_mt_entry_lock_control;
332
333#define rtems_filesystem_mt_entry_declare_lock_context( ctx ) \
334 rtems_interrupt_lock_context ctx
335
336#define rtems_filesystem_mt_entry_lock( ctx ) \
337 rtems_interrupt_lock_acquire( &rtems_filesystem_mt_entry_lock_control, &ctx )
338
339#define rtems_filesystem_mt_entry_unlock( ctx ) \
340 rtems_interrupt_lock_release( &rtems_filesystem_mt_entry_lock_control, &ctx )
341
342static inline void rtems_filesystem_instance_lock(
344)
345{
346 const rtems_filesystem_mount_table_entry_t *mt_entry = loc->mt_entry;
347
348 (*mt_entry->ops->lock_h)( mt_entry );
349}
350
351static inline void rtems_filesystem_instance_unlock(
353)
354{
355 const rtems_filesystem_mount_table_entry_t *mt_entry = loc->mt_entry;
356
357 (*mt_entry->ops->unlock_h)( mt_entry );
358}
359
360/*
361 * File Descriptor Routine Prototypes
362 */
363
369
373unsigned int rtems_libio_fcntl_flags( int fcntl_flags );
374
378int rtems_libio_to_fcntl_flags( unsigned int flags );
379
385 rtems_libio_t *iop
386);
387
388/*
389 * File System Routine Prototypes
390 */
391
393rtems_filesystem_eval_path_start(
395 const char *path,
396 int eval_flags
397);
398
400rtems_filesystem_eval_path_start_with_parent(
402 const char *path,
403 int eval_flags,
405 int parent_eval_flags
406);
407
409rtems_filesystem_eval_path_start_with_root_and_current(
411 const char *path,
412 size_t pathlen,
413 int eval_flags,
414 rtems_filesystem_global_location_t *const *global_root_ptr,
415 rtems_filesystem_global_location_t *const *global_current_ptr
416);
417
418void rtems_filesystem_eval_path_continue(
420);
421
422void rtems_filesystem_eval_path_cleanup(
424);
425
426void rtems_filesystem_eval_path_recursive(
428 const char *path,
429 size_t pathlen
430);
431
432void rtems_filesystem_eval_path_cleanup_with_parent(
435);
436
452 rtems_filesystem_global_location_t **newstartloc_ptr
453);
454
455typedef enum {
456 RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_CONTINUE,
457 RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_DONE,
458 RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_NO_ENTRY
459} rtems_filesystem_eval_path_generic_status;
460
474 void *arg
475);
476
489typedef rtems_filesystem_eval_path_generic_status
492 void *arg,
493 const char *token,
494 size_t tokenlen
495);
496
497typedef struct {
501
502void rtems_filesystem_eval_path_generic(
504 void *arg,
506);
507
509
526);
527
529rtems_filesystem_location_initialize_to_null(
531)
532{
534 loc,
536 );
537}
538
540rtems_filesystem_location_transform_to_global(
542);
543
552 rtems_filesystem_global_location_t **lhs_global_loc_ptr,
554);
555
576 rtems_filesystem_global_location_t *const *global_loc_ptr
577);
578
598 bool deferred
599);
600
601void rtems_filesystem_location_detach(
603);
604
605void rtems_filesystem_location_copy_and_detach(
608);
609
611rtems_filesystem_global_location_obtain_null(void)
612{
614
615 return rtems_filesystem_global_location_obtain( &global_loc );
616}
617
618static inline bool rtems_filesystem_location_is_null(
620)
621{
622 return loc->handlers == &rtems_filesystem_null_handlers;
623}
624
625static inline bool rtems_filesystem_global_location_is_null(
626 const rtems_filesystem_global_location_t *global_loc
627)
628{
629 return rtems_filesystem_location_is_null( &global_loc->location );
630}
631
632static inline void rtems_filesystem_location_error(
634 int eno
635)
636{
637 if ( !rtems_filesystem_location_is_null( loc ) ) {
638 errno = eno;
639 }
640}
641
642int rtems_filesystem_mknod(
643 const rtems_filesystem_location_info_t *parentloc,
644 const char *name,
645 size_t namelen,
646 mode_t mode,
647 dev_t dev
648);
649
650int rtems_filesystem_chdir( rtems_filesystem_location_info_t *loc );
651
652int rtems_filesystem_chmod(
654 mode_t mode
655);
656
657int rtems_filesystem_chown(
659 uid_t owner,
660 gid_t group
661);
662
663static inline bool rtems_filesystem_is_ready_for_unmount(
665)
666{
667 bool ready = !mt_entry->mounted
668 && rtems_chain_has_only_one_node( &mt_entry->location_chain )
669 && mt_entry->mt_fs_root->reference_count == 1;
670
671 if ( ready ) {
672 rtems_chain_initialize_empty( &mt_entry->location_chain );
673 }
674
675 return ready;
676}
677
678static inline void rtems_filesystem_location_add_to_mt_entry(
680)
681{
682 rtems_filesystem_mt_entry_declare_lock_context( lock_context );
683
684 rtems_filesystem_mt_entry_lock( lock_context );
686 &loc->mt_entry->location_chain,
687 &loc->mt_entry_node
688 );
689 rtems_filesystem_mt_entry_unlock( lock_context );
690}
691
692void rtems_filesystem_location_remove_from_mt_entry(
694);
695
696void rtems_filesystem_do_unmount(
698);
699
700static inline bool rtems_filesystem_location_is_instance_root(
702)
703{
704 const rtems_filesystem_mount_table_entry_t *mt_entry = loc->mt_entry;
705
706 return (*mt_entry->ops->are_nodes_equal_h)(
707 loc,
708 &mt_entry->mt_fs_root->location
709 );
710}
711
712static inline const char *rtems_filesystem_eval_path_get_path(
714)
715{
716 return ctx->path;
717}
718
719static inline size_t rtems_filesystem_eval_path_get_pathlen(
721)
722{
723 return ctx->pathlen;
724}
725
726static inline void rtems_filesystem_eval_path_set_path(
728 const char *path,
729 size_t pathlen
730)
731{
732 ctx->path = path;
733 ctx->pathlen = pathlen;
734}
735
736static inline void rtems_filesystem_eval_path_clear_path(
738)
739{
740 ctx->pathlen = 0;
741}
742
743static inline const char *rtems_filesystem_eval_path_get_token(
745)
746{
747 return ctx->token;
748}
749
750static inline size_t rtems_filesystem_eval_path_get_tokenlen(
752)
753{
754 return ctx->tokenlen;
755}
756
757static inline void rtems_filesystem_eval_path_set_token(
759 const char *token,
760 size_t tokenlen
761)
762{
763 ctx->token = token;
764 ctx->tokenlen = tokenlen;
765}
766
767static inline void rtems_filesystem_eval_path_clear_token(
769)
770{
771 ctx->tokenlen = 0;
772}
773
774static inline void rtems_filesystem_eval_path_put_back_token(
776)
777{
778 size_t tokenlen = ctx->tokenlen;
779
780 ctx->path -= tokenlen;
781 ctx->pathlen += tokenlen;
782 ctx->tokenlen = 0;
783}
784
785void rtems_filesystem_eval_path_eat_delimiter(
787);
788
789void rtems_filesystem_eval_path_next_token(
791);
792
793static inline void rtems_filesystem_eval_path_get_next_token(
795 const char **token,
796 size_t *tokenlen
797)
798{
799 rtems_filesystem_eval_path_next_token(ctx);
800 *token = ctx->token;
801 *tokenlen = ctx->tokenlen;
802}
803
805rtems_filesystem_eval_path_get_currentloc(
807)
808{
809 return &ctx->currentloc;
810}
811
812static inline bool rtems_filesystem_eval_path_has_path(
814)
815{
816 return ctx->pathlen > 0;
817}
818
819static inline bool rtems_filesystem_eval_path_has_token(
821)
822{
823 return ctx->tokenlen > 0;
824}
825
826static inline int rtems_filesystem_eval_path_get_flags(
828)
829{
830 return ctx->flags;
831}
832
833static inline void rtems_filesystem_eval_path_set_flags(
835 int flags
836)
837{
838 ctx->flags = flags;
839}
840
841static inline void rtems_filesystem_eval_path_clear_and_set_flags(
843 int clear,
844 int set
845)
846{
847 int flags = ctx->flags;
848
849 flags &= ~clear;
850 flags |= set;
851
852 ctx->flags = flags;
853}
854
855static inline void rtems_filesystem_eval_path_extract_currentloc(
858)
859{
860 rtems_filesystem_location_copy_and_detach(
861 get,
862 &ctx->currentloc
863 );
864}
865
866void rtems_filesystem_eval_path_error(
868 int eno
869);
870
880);
881
902 int flags,
903 mode_t object_mode,
904 uid_t object_uid,
905 gid_t object_gid
906);
907
908bool rtems_filesystem_eval_path_check_access(
910 int eval_flags,
911 mode_t node_mode,
912 uid_t node_uid,
913 gid_t node_gid
914);
915
916static inline bool rtems_filesystem_is_delimiter(char c)
917{
918 return c == '/' || c == '\\';
919}
920
921static inline bool rtems_filesystem_is_current_directory(
922 const char *token,
923 size_t tokenlen
924)
925{
926 return tokenlen == 1 && token [0] == '.';
927}
928
929static inline bool rtems_filesystem_is_parent_directory(
930 const char *token,
931 size_t tokenlen
932)
933{
934 return tokenlen == 2 && token [0] == '.' && token [1] == '.';
935}
936
937typedef ssize_t ( *rtems_libio_iovec_adapter )(
938 rtems_libio_t *iop,
939 const struct iovec *iov,
940 int iovcnt,
941 ssize_t total
942);
943
944static inline ssize_t rtems_libio_iovec_eval(
945 int fd,
946 const struct iovec *iov,
947 int iovcnt,
948 unsigned int flags,
949 rtems_libio_iovec_adapter adapter
950)
951{
952 ssize_t total;
953 int v;
954 rtems_libio_t *iop;
955
956 /*
957 * Argument validation on IO vector
958 */
959 if ( iov == NULL )
961
962 if ( iovcnt <= 0 )
964
965 if ( iovcnt > IOV_MAX )
967
968 /*
969 * OpenGroup says that you are supposed to return EINVAL if the
970 * sum of the iov_len values in the iov array would overflow a
971 * ssize_t.
972 */
973 total = 0;
974 for ( v = 0 ; v < iovcnt ; ++v ) {
975 size_t len = iov[ v ].iov_len;
976
977 if ( len > ( size_t ) ( SSIZE_MAX - total ) ) {
979 }
980
981 total += ( ssize_t ) len;
982
983 if ( iov[ v ].iov_base == NULL && len != 0 ) {
985 }
986 }
987
988 LIBIO_GET_IOP_WITH_ACCESS( fd, iop, flags, EBADF );
989
990 if ( total > 0 ) {
991 total = ( *adapter )( iop, iov, iovcnt, total );
992 }
993
994 rtems_libio_iop_drop( iop );
995 return total;
996}
997
1006static inline mode_t rtems_filesystem_location_type(
1008)
1009{
1010 struct stat st;
1011
1012 st.st_mode = 0;
1013 (void) ( *loc->handlers->fstat_h )( loc, &st );
1014
1015 return st.st_mode;
1016}
1017
1020#ifdef __cplusplus
1021}
1022#endif
1023
1024#endif
1025/* end of include file */
Information for the Assert Handler.
#define NULL
Requests a GPIO pin group configuration.
Definition: bestcomm_api.h:77
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
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
RTEMS_INLINE_ROUTINE void rtems_chain_initialize_empty(rtems_chain_control *the_chain)
Initialize this chain as empty.
Definition: chain.h:168
#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:234
unsigned int rtems_libio_fcntl_flags(int fcntl_flags)
Definition: libio.c:61
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:472
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
rtems_filesystem_global_location_t rtems_filesystem_global_location_null
The global null location.
Definition: __usrenv.c:229
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
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
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
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
int rtems_libio_to_fcntl_flags(unsigned int flags)
Definition: libio.c:86
rtems_libio_t * rtems_libio_allocate(void)
Definition: libio.c:109
void rtems_filesystem_location_free(rtems_filesystem_location_info_t *loc)
Releases all resources of a location.
Definition: freenode.c:25
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
void rtems_libio_free(rtems_libio_t *iop)
Definition: libio.c:133
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
void rtems_filesystem_initialize(void)
Base File System Initialization.
Definition: base_fs.c:32
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.
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:490
#define _Assert(_e)
Assertion similar to assert() controlled via RTEMS_DEBUG instead of NDEBUG.
Definition: assert.h:100
#define rtems_set_errno_and_return_minus_one(_error)
Definition: seterr.h:48
Basic IO API.
POSIX Threads Private Support.
Data which Ease the Burden of Consistently Setting Errno.
ISR lock control.
Definition: isrlock.h:56
File system node operations table.
Definition: libio.h:1005
Definition: if_em.h:352
Definition: deflate.c:115
Path evaluation context.
Definition: libio.h:84
rtems_filesystem_location_info_t currentloc
Definition: libio.h:135
const char * path
Definition: libio.h:88
size_t pathlen
Definition: libio.h:93
size_t tokenlen
Definition: libio.h:105
const char * token
Definition: libio.h:99
int flags
Definition: libio.h:119
Global file system location.
Definition: fs.h:81
File system location.
Definition: fs.h:53
Mount table entry.
Definition: libio.h:1604
An open file data structure.
Definition: libio.h:1320
unsigned v
Definition: tte.h:0
User Environment Support.