source: rtems/c/src/lib/libc/libio.c @ 3ef8798

4.104.114.84.95
Last change on this file since 3ef8798 was 3ef8798, checked in by Joel Sherrill <joel.sherrill@…>, on 03/06/99 at 18:09:15

Added F_GETFL support so the fdopen() implementation in newlib 1.8.1
would work. At the same time, the initial implementation of F_SETFL
was added. A support routine was added to convert internal libio
flags back to the POSIX style. Eventually the internal representation
should be eliminated in the interest of simplicity and code reduction.
This problem was reported by Jake Janovetz <janovetz@…>.

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