source: rtems/cpukit/libcsupport/src/libio.c @ 79e028d3

4.104.115
Last change on this file since 79e028d3 was 79e028d3, checked in by Ralf Corsepius <ralf.corsepius@…>, on 09/15/09 at 09:53:01

Reflect rtems_libio_number_iops being uint32_t.

  • Property mode set to 100644
File size: 7.1 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.rtems.com/license/LICENSE.
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/* define this to alias O_NDELAY to  O_NONBLOCK, i.e.,
30 * O_NDELAY is accepted on input but fcntl(F_GETFL) returns
31 * O_NONBLOCK. This is because rtems has no distinction
32 * between the two (but some systems have).
33 * Note that accepting this alias creates a problem:
34 * an application trying to clear the non-blocking flag
35 * using a
36 *
37 *    fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) & ~O_NDELAY);
38 *
39 * does (silently) ignore the operation.
40 */
41#undef ACCEPT_O_NDELAY_ALIAS
42
43#include <errno.h>
44#include <string.h>                     /* strcmp */
45#include <unistd.h>
46#include <stdlib.h>                     /* calloc() */
47
48#include <rtems/libio.h>                /* libio.h not pulled in by rtems */
49
50/*
51 *  File descriptor Table Information
52 */
53
54extern uint32_t       rtems_libio_number_iops;
55extern rtems_id       rtems_libio_semaphore;
56extern rtems_libio_t *rtems_libio_iops;
57extern rtems_libio_t *rtems_libio_iop_freelist;
58
59/*
60 *  rtems_libio_fcntl_flags
61 *
62 *  Convert UNIX fnctl(2) flags to ones that RTEMS drivers understand
63 */
64
65const rtems_assoc_t access_modes_assoc[] = {
66  { "READ",       LIBIO_FLAGS_READ,  O_RDONLY },
67  { "WRITE",      LIBIO_FLAGS_WRITE, O_WRONLY },
68  { "READ/WRITE", LIBIO_FLAGS_READ_WRITE, O_RDWR },
69  { 0, 0, 0 },
70};
71
72const rtems_assoc_t status_flags_assoc[] = {
73#ifdef ACCEPT_O_NDELAY_ALIAS
74  { "NO DELAY",  LIBIO_FLAGS_NO_DELAY,  O_NDELAY },
75#endif
76  { "NONBLOCK",  LIBIO_FLAGS_NO_DELAY,  O_NONBLOCK },
77  { "APPEND",    LIBIO_FLAGS_APPEND,    O_APPEND },
78  { "CREATE",    LIBIO_FLAGS_CREATE,    O_CREAT },
79  { 0, 0, 0 },
80};
81
82uint32_t   rtems_libio_fcntl_flags(
83  uint32_t   fcntl_flags
84)
85{
86  uint32_t   flags = 0;
87  uint32_t   access_modes;
88
89  /*
90   * Access mode is a small integer
91   */
92
93  access_modes = fcntl_flags & O_ACCMODE;
94  fcntl_flags &= ~O_ACCMODE;
95  flags = rtems_assoc_local_by_remote( access_modes_assoc, access_modes );
96
97  /*
98   * Everything else is single bits
99   */
100
101  flags |=
102     rtems_assoc_local_by_remote_bitfield(status_flags_assoc, fcntl_flags);
103  return flags;
104}
105
106/*
107 *  rtems_libio_to_fcntl_flags
108 *
109 *  Convert RTEMS internal flags to UNIX fnctl(2) flags
110 */
111
112uint32_t   rtems_libio_to_fcntl_flags(
113  uint32_t   flags
114)
115{
116  uint32_t   fcntl_flags = 0;
117
118  if ( (flags & LIBIO_FLAGS_READ_WRITE) == LIBIO_FLAGS_READ_WRITE ) {
119    fcntl_flags |= O_RDWR;
120  } else if ( (flags & LIBIO_FLAGS_READ) == LIBIO_FLAGS_READ) {
121    fcntl_flags |= O_RDONLY;
122  } else if ( (flags & LIBIO_FLAGS_WRITE) == LIBIO_FLAGS_WRITE) {
123    fcntl_flags |= O_WRONLY;
124  }
125
126  if ( (flags & LIBIO_FLAGS_NO_DELAY) == LIBIO_FLAGS_NO_DELAY ) {
127    fcntl_flags |= O_NONBLOCK;
128  }
129
130  if ( (flags & LIBIO_FLAGS_APPEND) == LIBIO_FLAGS_APPEND ) {
131    fcntl_flags |= O_APPEND;
132  }
133
134  if ( (flags & LIBIO_FLAGS_CREATE) == LIBIO_FLAGS_CREATE ) {
135    fcntl_flags |= O_CREAT;
136  }
137
138  return fcntl_flags;
139}
140
141/*
142 *  rtems_libio_allocate
143 *
144 *  This routine searches the IOP Table for an unused entry.  If it
145 *  finds one, it returns it.  Otherwise, it returns NULL.
146 */
147
148rtems_libio_t *rtems_libio_allocate( void )
149{
150  rtems_libio_t *iop, *next;
151  rtems_status_code rc;
152  rtems_id sema;
153
154  rtems_semaphore_obtain( rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT );
155
156  if (rtems_libio_iop_freelist) {
157    rc = rtems_semaphore_create(
158      RTEMS_LIBIO_IOP_SEM(rtems_libio_iop_freelist - rtems_libio_iops),
159      1,
160      RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
161      RTEMS_NO_PRIORITY,
162      &sema
163    );
164    if (rc != RTEMS_SUCCESSFUL)
165      goto failed;
166    iop = rtems_libio_iop_freelist;
167    next = iop->data1;
168    (void) memset( iop, 0, sizeof(rtems_libio_t) );
169    iop->flags = LIBIO_FLAGS_OPEN;
170    iop->sem = sema;
171    rtems_libio_iop_freelist = next;
172    goto done;
173  }
174
175failed:
176  iop = 0;
177
178done:
179  rtems_semaphore_release( rtems_libio_semaphore );
180  return iop;
181}
182
183/*
184 *  rtems_libio_free
185 *
186 *  This routine frees the resources associated with an IOP (file descriptor)
187 *  and clears the slot in the IOP Table.
188 */
189
190void rtems_libio_free(
191  rtems_libio_t *iop
192)
193{
194  rtems_semaphore_obtain( rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT );
195
196    if (iop->sem)
197      rtems_semaphore_delete(iop->sem);
198
199    iop->flags &= ~LIBIO_FLAGS_OPEN;
200    iop->data1 = rtems_libio_iop_freelist;
201    rtems_libio_iop_freelist = iop;
202
203  rtems_semaphore_release(rtems_libio_semaphore);
204}
205
206/*
207 *  rtems_libio_is_open_files_in_fs
208 *
209 *  This routine scans the entire file descriptor table to determine if the
210 *  are any active file descriptors that refer to the at least one node in the
211 *  file system that we are trying to dismount.
212 *
213 *  If there is at least one node in the file system referenced by the mount
214 *  table entry a 1 is returned, otherwise a 0 is returned.
215 */
216
217int rtems_libio_is_open_files_in_fs(
218  rtems_filesystem_mount_table_entry_t * fs_mt_entry
219)
220{
221  rtems_libio_t     *iop;
222  int                result = 0;
223  uint32_t           i;
224
225  rtems_semaphore_obtain( rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT );
226
227  /*
228   *  Look for any active file descriptor entry.
229   */
230
231  for (iop=rtems_libio_iops,i=0; i < rtems_libio_number_iops; iop++, i++){
232
233    if ((iop->flags & LIBIO_FLAGS_OPEN) != 0) {
234
235       /*
236        *  Check if this node is under the file system that we
237        *  are trying to dismount.
238        */
239
240       if ( iop->pathinfo.mt_entry == fs_mt_entry ) {
241          result = 1;
242          break;
243       }
244    }
245  }
246
247  rtems_semaphore_release( rtems_libio_semaphore );
248
249  return result;
250}
251
252/*
253 *  rtems_libio_is_file_open
254 *
255 *  This routine scans the entire file descriptor table to determine if the
256 *  given file refers to an active file descriptor.
257 *
258 *  If the given file is open a 1 is returned, otherwise a 0 is returned.
259 */
260
261int rtems_libio_is_file_open(
262  void         *node_access
263)
264{
265  rtems_libio_t     *iop;
266  int                result=0;
267  uint32_t           i;
268
269  rtems_semaphore_obtain( rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT );
270
271  /*
272   *  Look for any active file descriptor entry.
273   */
274
275 for (iop=rtems_libio_iops,i=0; i < rtems_libio_number_iops; iop++, i++){
276    if ((iop->flags & LIBIO_FLAGS_OPEN) != 0) {
277
278       /*
279        *  Check if this node is under the file system that we
280        *  are trying to dismount.
281        */
282
283       if ( iop->pathinfo.node_access == node_access ) {
284          result = 1;
285          break;
286       }
287    }
288  }
289
290  rtems_semaphore_release( rtems_libio_semaphore );
291
292  return result;
293}
Note: See TracBrowser for help on using the repository browser.