source: rtems/cpukit/libcsupport/src/libio.c @ 07a3253d

4.104.114.84.95
Last change on this file since 07a3253d was 07a3253d, checked in by Joel Sherrill <joel.sherrill@…>, on Nov 23, 1998 at 7:07:58 PM

Added base version of file system infrastructure. This includes a major
overhaul of the RTEMS system call interface. This base file system is
the "In-Memory File System" aka IMFS.

The design and implementation was done by the following people:

+ Joel Sherrill (joel@…)
+ Jennifer Averett (jennifer@…)
+ Steve "Mr Mount" Salitasc (salitasc@…)
+ Kerwin Wade (wade@…)

PROBLEMS
========

+ It is VERY likely that merging this will break the UNIX port. This

can/will be fixed.

+ There is likely some reentrancy/mutual exclusion needed.

+ Eventually, there should be a "mini-IMFS" description table to

eliminate links, symlinks, etc to save memory. All you need to
have "classic RTEMS" functionality is technically directories
and device IO. All the rest could be left out to save memory.

  • Property mode set to 100644
File size: 6.9 KB
Line 
1/*
2 *  This file contains the support infrastructure used to manage the
3 *  table of integer style file descriptors used by the low level
4 *  POSIX system calls like open(), read, fstat(), etc.
5 *
6 *  This provides the foundation for POSIX compliant IO system calls
7 *  for RTEMS.
8 *
9 *  COPYRIGHT (c) 1989-1998.
10 *  On-Line Applications Research Corporation (OAR).
11 *  Copyright assigned to U.S. Government, 1994.
12 *
13 *  The license and distribution terms for this file may be
14 *  found in the file LICENSE in this distribution or at
15 *  http://www.OARcorp.com/rtems/license.html.
16 *
17 *  $Id$
18 */
19
20#include "libio_.h"                   /* libio_.h pulls in rtems */
21
22/*
23 *  Global variables used to manage the File Descriptor Table.
24 *  IOP = IO Pointer.
25 */
26
27rtems_id                rtems_libio_semaphore;
28rtems_libio_t          *rtems_libio_iops;
29rtems_libio_t          *rtems_libio_last_iop;
30rtems_libio_handler_t   rtems_libio_handlers[15];
31
32/*
33 *  rtems_register_libio_handler
34 *
35 *  This function registers an external IO handler set.  This lets
36 *  other subsystems have their own versions of many of the system
37 *  calls.  For example, the networking code registers handlers which
38 *  map the system calls for read() and write() to socket calls.
39 *
40 */
41
42void rtems_register_libio_handler(
43  int                          handler_flag,
44  const rtems_libio_handler_t *handler
45)
46{
47  int handler_index = rtems_file_descriptor_type_index( handler_flag );
48
49
50  if ((handler_index < 0) || (handler_index >= 15))
51    rtems_fatal_error_occurred( RTEMS_INVALID_NUMBER );
52
53  rtems_libio_handlers[handler_index] = *handler;
54}
55
56/*
57 *  rtems_libio_init
58 *
59 *  Called by BSP startup code to initialize the libio subsystem.
60 */
61
62void rtems_libio_init( void )
63{
64  rtems_status_code rc;
65
66  /*
67   *  Allocate memory for the IOP Table
68   */
69
70  if ( rtems_libio_number_iops > 0 ) {
71    rtems_libio_iops =
72      (rtems_libio_t *) calloc(rtems_libio_number_iops, sizeof(rtems_libio_t));
73
74    if (rtems_libio_iops == NULL)
75        rtems_fatal_error_occurred( RTEMS_NO_MEMORY );
76
77    rtems_libio_last_iop = rtems_libio_iops + (rtems_libio_number_iops - 1);
78  }
79
80  /*
81   *  Create the binary semaphore used to provide mutual exclusion
82   *  on the IOP Table.
83   */
84
85  rc = rtems_semaphore_create(
86    RTEMS_LIBIO_SEM,
87    1,
88    RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
89    RTEMS_NO_PRIORITY,
90    &rtems_libio_semaphore
91  );
92  if ( rc != RTEMS_SUCCESSFUL )
93    rtems_fatal_error_occurred( rc );
94
95  /*
96   *  Initialize the base file system infrastructure.
97   */
98
99  rtems_filesystem_initialize();
100}
101
102/*
103 *  rtems_libio_fcntl_flags
104 *
105 *  Convert UNIX fnctl(2) flags to ones that RTEMS drivers understand
106 */
107
108rtems_assoc_t access_modes_assoc[] = {
109  { "READ",       LIBIO_FLAGS_READ,  O_RDONLY },
110  { "WRITE",      LIBIO_FLAGS_WRITE, O_WRONLY },
111  { "READ/WRITE", LIBIO_FLAGS_READ_WRITE, O_RDWR },
112  { 0, 0, 0 },
113};
114
115rtems_assoc_t status_flags_assoc[] = {
116  { "NO DELAY",  LIBIO_FLAGS_NO_DELAY,  O_NDELAY },
117  { "APPEND",    LIBIO_FLAGS_APPEND,    O_APPEND },
118  { "CREATE",    LIBIO_FLAGS_CREATE,    O_CREAT },
119  { 0, 0, 0 },
120};
121
122unsigned32 rtems_libio_fcntl_flags(
123  unsigned32 fcntl_flags
124)
125{
126  unsigned32 flags = 0;
127  unsigned32 access_modes;
128
129  /*
130   * Access mode is a small integer
131   */
132 
133  access_modes = fcntl_flags & O_ACCMODE;
134  fcntl_flags &= ~O_ACCMODE;
135  flags = rtems_assoc_local_by_remote( access_modes_assoc, access_modes );
136
137  /*
138   * Everything else is single bits
139   */
140
141  flags |=
142     rtems_assoc_local_by_remote_bitfield(status_flags_assoc, fcntl_flags);
143  return flags;
144}
145
146/*
147 *  rtems_libio_allocate
148 *
149 *  This routine searches the IOP Table for an unused entry.  If it
150 *  finds one, it returns it.  Otherwise, it returns NULL.
151 */
152
153rtems_libio_t *rtems_libio_allocate( void )
154{
155  rtems_libio_t *iop;
156  rtems_status_code rc;
157 
158  rtems_semaphore_obtain( rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT );
159
160  for (iop = rtems_libio_iops; iop <= rtems_libio_last_iop; iop++)
161    if ((iop->flags & LIBIO_FLAGS_OPEN) == 0) {
162      /*
163       *  Got an IOP -- create a semaphore for it.
164       */
165
166      rc = rtems_semaphore_create(
167        RTEMS_LIBIO_IOP_SEM(iop - rtems_libio_iops),
168        1,
169        RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
170        RTEMS_NO_PRIORITY,
171        &iop->sem
172      );
173      if ( rc != RTEMS_SUCCESSFUL )
174        goto failed;
175   
176      iop->flags = LIBIO_FLAGS_OPEN;
177      goto done;
178  }
179 
180failed:
181  iop = 0;
182 
183done:
184  rtems_semaphore_release( rtems_libio_semaphore );
185  return iop;
186}
187
188/*
189 *  rtems_libio_free
190 *
191 *  This routine frees the resources associated with an IOP (file descriptor)
192 *  and clears the slot in the IOP Table.
193 */
194
195void rtems_libio_free(
196  rtems_libio_t *iop
197)
198{
199  rtems_semaphore_obtain( rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT );
200
201  if (iop->sem)
202    rtems_semaphore_delete(iop->sem);
203
204  (void) memset(iop, 0, sizeof(*iop));
205
206  rtems_semaphore_release( rtems_libio_semaphore );
207}
208
209/*
210 *  rtems_libio_is_open_files_in_fs
211 *
212 *  This routine scans the entire file descriptor table to determine if the
213 *  are any active file descriptors that refer to the atleast one node in the
214 *  file system that we are trying to dismount.
215 *
216 *  If there is at least one node in the file system referenced by the mount
217 *  table entry a 1 is returned, otherwise a 0 is returned.
218 */
219
220int rtems_libio_is_open_files_in_fs(
221  rtems_filesystem_mount_table_entry_t * fs_mt_entry
222)
223{
224  rtems_libio_t     *iop;
225  int                result = 0;
226
227  rtems_semaphore_obtain( rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT );
228
229  /*
230   *  Look for any active file descriptor entry.
231   */
232
233  for ( iop=rtems_libio_iops ; iop <= rtems_libio_last_iop ; iop++ ) {
234
235    if ((iop->flags & LIBIO_FLAGS_OPEN) != 0) {
236
237       /*
238        *  Check if this node is under the file system that we
239        *  are trying to dismount.
240        */ 
241
242       if ( iop->pathinfo.mt_entry == fs_mt_entry ) {
243          result = 1;
244          break;
245       }
246    }
247  }
248
249  rtems_semaphore_release( rtems_libio_semaphore );
250
251  return result;
252}
253
254/*
255 *  rtems_libio_is_file_open
256 *
257 *  This routine scans the entire file descriptor table to determine if the
258 *  given file refers to an active file descriptor.
259 *
260 *  If the given file is open a 1 is returned, otherwise a 0 is returned.
261 */
262
263int rtems_libio_is_file_open(
264  void         *node_access
265)
266{
267  rtems_libio_t     *iop;
268  int                result=0; 
269
270  rtems_semaphore_obtain( rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT );
271
272  /*
273   *  Look for any active file descriptor entry.
274   */
275
276  for ( iop=rtems_libio_iops ; iop <= rtems_libio_last_iop ; iop++ ) {
277
278    if ((iop->flags & LIBIO_FLAGS_OPEN) != 0) {
279
280       /*
281        *  Check if this node is under the file system that we
282        *  are trying to dismount.
283        */ 
284
285       if ( iop->pathinfo.node_access == node_access ) {
286          result = 1;
287          break;
288       }
289    }
290  }
291
292  rtems_semaphore_release( rtems_libio_semaphore );
293
294  return result;
295}
Note: See TracBrowser for help on using the repository browser.