source: rtems/c/src/lib/libc/libio.c @ 72650fcb

4.104.114.84.95
Last change on this file since 72650fcb was 1e4968e, checked in by Joel Sherrill <joel.sherrill@…>, on 10/26/01 at 19:22:03

2001-10-26 Joel Sherrill <joel@…>

  • libc/libio.c: Cleanup of initialization per suggestion from Eric Norum.
  • Property mode set to 100644
File size: 7.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 *  COPYRIGHT (c) 1989-1999.
7 *  On-Line Applications Research Corporation (OAR).
8 *
9 *  The license and distribution terms for this file may be
10 *  found in the file LICENSE in this distribution or at
11 *  http://www.OARcorp.com/rtems/license.html.
12 *
13 *  $Id$
14 */
15
16#if HAVE_CONFIG_H
17#include "config.h"
18#endif
19
20#include <rtems/libio_.h>               /* libio_.h pulls in rtems */
21#include <rtems.h>
22#include <rtems/assoc.h>                /* assoc.h not included by rtems.h */
23
24#include <stdio.h>                      /* O_RDONLY, et.al. */
25#include <fcntl.h>                      /* O_RDONLY, et.al. */
26#include <assert.h>
27#include <errno.h>
28
29#if ! defined(O_NDELAY)
30# if defined(solaris2)
31#  define O_NDELAY O_NONBLOCK
32# elif defined(__CYGWIN__)
33#   define O_NDELAY _FNBIO
34# elif defined(RTEMS_NEWLIB)
35#  define O_NDELAY _FNBIO
36# endif
37#endif
38
39
40#include <errno.h>
41#include <string.h>                     /* strcmp */
42#include <unistd.h>
43#include <stdlib.h>                     /* calloc() */
44
45#include <rtems/libio.h>                /* libio.h not pulled in by rtems */
46
47/*                           
48 *  File descriptor Table Information
49 */         
50
51extern unsigned32  rtems_libio_number_iops;
52rtems_id           rtems_libio_semaphore;
53rtems_libio_t     *rtems_libio_iops;
54rtems_libio_t     *rtems_libio_iop_freelist;
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    int i;
66    rtems_libio_t *iop;
67
68    if (rtems_libio_number_iops > 0)
69    {
70        rtems_libio_iops = (rtems_libio_t *) calloc(rtems_libio_number_iops,
71                                                    sizeof(rtems_libio_t));
72        if (rtems_libio_iops == NULL)
73            rtems_fatal_error_occurred(RTEMS_NO_MEMORY);
74
75        iop = rtems_libio_iop_freelist = rtems_libio_iops;
76        for (i = 0 ; i < (rtems_libio_number_iops - 1) ; i++, iop++)
77                iop->data1 = iop + 1;
78        iop->data1 = NULL;
79    }
80
81  /*
82   *  Create the binary semaphore used to provide mutual exclusion
83   *  on the IOP Table.
84   */
85
86  rc = rtems_semaphore_create(
87    RTEMS_LIBIO_SEM,
88    1,
89    RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
90    RTEMS_NO_PRIORITY,
91    &rtems_libio_semaphore
92  );
93  if ( rc != RTEMS_SUCCESSFUL )
94    rtems_fatal_error_occurred( rc );
95
96  /*
97   *  Initialize the base file system infrastructure.
98   */
99
100  rtems_filesystem_initialize();
101}
102
103/*
104 *  rtems_libio_fcntl_flags
105 *
106 *  Convert UNIX fnctl(2) flags to ones that RTEMS drivers understand
107 */
108
109rtems_assoc_t access_modes_assoc[] = {
110  { "READ",       LIBIO_FLAGS_READ,  O_RDONLY },
111  { "WRITE",      LIBIO_FLAGS_WRITE, O_WRONLY },
112  { "READ/WRITE", LIBIO_FLAGS_READ_WRITE, O_RDWR },
113  { 0, 0, 0 },
114};
115
116rtems_assoc_t status_flags_assoc[] = {
117  { "NO DELAY",  LIBIO_FLAGS_NO_DELAY,  O_NDELAY },
118  { "NONBLOCK",  LIBIO_FLAGS_NO_DELAY,  O_NONBLOCK },
119  { "APPEND",    LIBIO_FLAGS_APPEND,    O_APPEND },
120  { "CREATE",    LIBIO_FLAGS_CREATE,    O_CREAT },
121  { 0, 0, 0 },
122};
123
124unsigned32 rtems_libio_fcntl_flags(
125  unsigned32 fcntl_flags
126)
127{
128  unsigned32 flags = 0;
129  unsigned32 access_modes;
130
131  /*
132   * Access mode is a small integer
133   */
134 
135  access_modes = fcntl_flags & O_ACCMODE;
136  fcntl_flags &= ~O_ACCMODE;
137  flags = rtems_assoc_local_by_remote( access_modes_assoc, access_modes );
138
139  /*
140   * Everything else is single bits
141   */
142
143  flags |=
144     rtems_assoc_local_by_remote_bitfield(status_flags_assoc, fcntl_flags);
145  return flags;
146}
147
148/*
149 *  rtems_libio_to_fcntl_flags
150 *
151 *  Convert RTEMS internal flags to UNIX fnctl(2) flags
152 */
153
154unsigned32 rtems_libio_to_fcntl_flags(
155  unsigned32 flags
156)
157{
158  unsigned32 fcntl_flags = 0;
159
160  if ( (flags & LIBIO_FLAGS_READ_WRITE) == LIBIO_FLAGS_READ_WRITE ) {
161    fcntl_flags |= O_RDWR;
162  } else if ( (flags & LIBIO_FLAGS_READ) == LIBIO_FLAGS_READ) {
163    fcntl_flags |= O_RDONLY;
164  } else if ( (flags & LIBIO_FLAGS_WRITE) == LIBIO_FLAGS_WRITE) {
165    fcntl_flags |= O_WRONLY;
166  }
167
168  if ( (flags & LIBIO_FLAGS_NO_DELAY) == LIBIO_FLAGS_NO_DELAY ) {
169    fcntl_flags |= O_NDELAY;
170  }
171
172  if ( (flags & LIBIO_FLAGS_APPEND) == LIBIO_FLAGS_APPEND ) {
173    fcntl_flags |= O_APPEND;
174  }
175
176  if ( (flags & LIBIO_FLAGS_CREATE) == LIBIO_FLAGS_CREATE ) {
177    fcntl_flags |= O_CREAT;
178  }
179
180  return fcntl_flags;
181}
182
183/*
184 *  rtems_libio_allocate
185 *
186 *  This routine searches the IOP Table for an unused entry.  If it
187 *  finds one, it returns it.  Otherwise, it returns NULL.
188 */
189
190rtems_libio_t *rtems_libio_allocate( void )
191{
192  rtems_libio_t *iop, *next;
193  rtems_status_code rc;
194 
195  rtems_semaphore_obtain( rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT );
196
197  if (rtems_libio_iop_freelist) {
198    iop = rtems_libio_iop_freelist;
199    next = iop->data1;
200    (void) memset( iop, 0, sizeof(rtems_libio_t) );
201    iop->flags = LIBIO_FLAGS_OPEN;
202    rc = rtems_semaphore_create(
203      RTEMS_LIBIO_IOP_SEM(iop - rtems_libio_iops),
204      1,
205      RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
206      RTEMS_NO_PRIORITY,
207      &iop->sem
208    );
209    if (rc != RTEMS_SUCCESSFUL)
210      goto failed;
211    rtems_libio_iop_freelist = next;
212    goto done;
213  }
214 
215failed:
216  iop = 0;
217 
218done:
219  rtems_semaphore_release( rtems_libio_semaphore );
220  return iop;
221}
222
223/*
224 *  rtems_libio_free
225 *
226 *  This routine frees the resources associated with an IOP (file descriptor)
227 *  and clears the slot in the IOP Table.
228 */
229
230void rtems_libio_free(
231  rtems_libio_t *iop
232)
233{
234  rtems_semaphore_obtain( rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT );
235
236    if (iop->sem)
237      rtems_semaphore_delete(iop->sem);
238
239    iop->flags &= ~LIBIO_FLAGS_OPEN;
240    iop->data1 = rtems_libio_iop_freelist;
241    rtems_libio_iop_freelist = iop;
242
243  rtems_semaphore_release(rtems_libio_semaphore);
244}
245
246/*
247 *  rtems_libio_is_open_files_in_fs
248 *
249 *  This routine scans the entire file descriptor table to determine if the
250 *  are any active file descriptors that refer to the at least one node in the
251 *  file system that we are trying to dismount.
252 *
253 *  If there is at least one node in the file system referenced by the mount
254 *  table entry a 1 is returned, otherwise a 0 is returned.
255 */
256
257int rtems_libio_is_open_files_in_fs(
258  rtems_filesystem_mount_table_entry_t * fs_mt_entry
259)
260{
261  rtems_libio_t     *iop;
262  int                result = 0;
263  int                i;
264
265  rtems_semaphore_obtain( rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT );
266             
267  /*
268   *  Look for any active file descriptor entry.
269   */         
270     
271  for (iop=rtems_libio_iops,i=0; i < rtems_libio_number_iops; iop++, i++){
272       
273    if ((iop->flags & LIBIO_FLAGS_OPEN) != 0) {
274       
275       /*
276        *  Check if this node is under the file system that we
277        *  are trying to dismount.
278        */
279
280       if ( iop->pathinfo.mt_entry == fs_mt_entry ) {
281          result = 1;
282          break;
283       }
284    }
285  }
286
287  rtems_semaphore_release( rtems_libio_semaphore );
288 
289  return result;
290}
291
292/*
293 *  rtems_libio_is_file_open
294 *
295 *  This routine scans the entire file descriptor table to determine if the
296 *  given file refers to an active file descriptor.
297 *
298 *  If the given file is open a 1 is returned, otherwise a 0 is returned.
299 */
300
301int rtems_libio_is_file_open(
302  void         *node_access
303)
304{
305  rtems_libio_t     *iop;
306  int                result=0;
307  int                i;
308
309  rtems_semaphore_obtain( rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT );
310
311  /*
312   *  Look for any active file descriptor entry.
313   */
314 
315 for (iop=rtems_libio_iops,i=0; i < rtems_libio_number_iops; iop++, i++){
316    if ((iop->flags & LIBIO_FLAGS_OPEN) != 0) {
317 
318       /*
319        *  Check if this node is under the file system that we
320        *  are trying to dismount.
321        */
322
323       if ( iop->pathinfo.node_access == node_access ) {
324          result = 1;
325          break;
326       }
327    }
328  }
329
330  rtems_semaphore_release( rtems_libio_semaphore );
331
332  return result;
333}
334
335
Note: See TracBrowser for help on using the repository browser.