source: rtems/c/src/exec/libcsupport/src/libio.c @ f4b7e297

4.104.114.84.95
Last change on this file since f4b7e297 was 331d9e3b, checked in by Joel Sherrill <joel.sherrill@…>, on 11/08/96 at 20:08:52

Added asserts for unhandled conditions which need to result in error
statuses being returned to gnat runtime in order for it to raise
use_errors. This was needed to identify the places in gnat's runtime
which needed to be addressed.

  • Property mode set to 100644
File size: 9.7 KB
Line 
1/*
2 *  Provide UNIX/POSIX-like io system calls for RTEMS using the
3 *  RTEMS IO manager
4 *
5 *  $Id$
6 */
7
8#include <rtems.h>
9#include <rtems/assoc.h>                /* assoc.h not included by rtems.h */
10
11#include <stdio.h>                      /* O_RDONLY, et.al. */
12#include <fcntl.h>                      /* O_RDONLY, et.al. */
13#include <assert.h>
14
15#if ! defined(O_NDELAY)
16# if defined(solaris2)
17#  define O_NDELAY O_NONBLOCK
18# elif defined(RTEMS_NEWLIB)
19#  define O_NDELAY _FNBIO
20# endif
21#endif
22
23
24#include <errno.h>
25#include <string.h>                     /* strcmp */
26#include <unistd.h>
27#include <stdlib.h>                     /* calloc() */
28
29#include "libio.h"                      /* libio.h not pulled in by rtems */
30
31/*
32 * Semaphore to protect the io table
33 */
34
35Objects_Id rtems_libio_semaphore;
36
37#define RTEMS_LIBIO_SEM         rtems_build_name('L', 'B', 'I', 'O')
38#define RTEMS_LIBIO_IOP_SEM(n)  rtems_build_name('L', 'B', 'I', n)
39
40unsigned32     rtems_libio_number_iops;
41rtems_libio_t *rtems_libio_iops;
42rtems_libio_t *rtems_libio_last_iop;
43
44#define rtems_libio_iop(fd)    ((((unsigned32)(fd)) < rtems_libio_number_iops) ? \
45                                       &rtems_libio_iops[fd] : 0)
46
47#define rtems_libio_check_fd(fd) \
48    do { \
49        if ((fd) >= rtems_libio_number_iops) \
50        { \
51            errno = EBADF; \
52            return -1; \
53        } \
54    } while (0)
55
56#define rtems_libio_check_buffer(buffer) \
57    do { \
58        if ((buffer) == 0) \
59        { \
60            errno = EINVAL; \
61            return -1; \
62        } \
63    } while (0)
64
65#define rtems_libio_check_count(count) \
66    do { \
67        if ((count) == 0) \
68        { \
69            return 0; \
70        } \
71    } while (0)
72
73#define rtems_libio_check_permissions(iop, flag) \
74    do { \
75        if (((iop)->flags & (flag)) == 0) \
76        { \
77              errno = EINVAL; \
78              return -1; \
79        } \
80    } while (0)
81
82
83void
84rtems_libio_config(
85    rtems_configuration_table *config,
86    unsigned32                 max_fds
87  )
88{
89    rtems_libio_number_iops = max_fds;
90
91    /*
92     * tweak config to reflect # of semaphores we will need
93     */
94
95    /* one for iop table */
96    config->RTEMS_api_configuration->maximum_semaphores += 1;
97    config->RTEMS_api_configuration->maximum_semaphores += max_fds;
98}
99
100/*
101 * Called by bsp startup code to init the libio area.
102 */
103
104void
105rtems_libio_init(void)
106{
107    rtems_status_code rc;
108
109    if (rtems_libio_number_iops > 0)
110    {
111        rtems_libio_iops = (rtems_libio_t *) calloc(rtems_libio_number_iops,
112                                                    sizeof(rtems_libio_t));
113        if (rtems_libio_iops == NULL)
114            rtems_fatal_error_occurred(RTEMS_NO_MEMORY);
115
116        rtems_libio_last_iop = rtems_libio_iops + (rtems_libio_number_iops - 1);
117    }
118
119    rc = rtems_semaphore_create(
120      RTEMS_LIBIO_SEM,
121      1,
122      RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
123      RTEMS_NO_PRIORITY,
124      &rtems_libio_semaphore
125    );
126    if (rc != RTEMS_SUCCESSFUL)
127        rtems_fatal_error_occurred(rc);
128}
129
130/*
131 * Convert RTEMS status to a UNIX errno
132 */
133
134rtems_assoc_t errno_assoc[] = {
135    { "OK",        RTEMS_SUCCESSFUL,       0 },
136    { "TIMEOUT",   RTEMS_TIMEOUT,          ETIME },
137    { "NO MEMORY", RTEMS_NO_MEMORY,        ENOMEM },
138    { "NO DEVICE", RTEMS_UNSATISFIED,      ENOSYS },
139    { 0, 0, 0 },
140};
141
142static unsigned32
143rtems_libio_errno(rtems_status_code code)
144{
145    int rc;
146   
147    if ((rc = rtems_assoc_remote_by_local(errno_assoc, (unsigned32) code)))
148    {
149        errno = rc;
150        return -1;
151    }
152    return 0;
153}
154
155/*
156 * Convert UNIX fnctl(2) flags to ones that RTEMS drivers understand
157 */
158
159rtems_assoc_t access_modes_assoc[] = {
160    { "READ",     LIBIO_FLAGS_READ,  O_RDONLY },
161    { "WRITE",    LIBIO_FLAGS_WRITE, O_WRONLY },
162    { "READ/WRITE", LIBIO_FLAGS_READ_WRITE, O_RDWR },
163    { 0, 0, 0 },
164};
165
166rtems_assoc_t status_flags_assoc[] = {
167    { "NO DELAY",  LIBIO_FLAGS_NO_DELAY,  O_NDELAY },
168    { "APPEND",    LIBIO_FLAGS_APPEND,    O_APPEND },
169    { "CREATE",    LIBIO_FLAGS_CREATE,    O_CREAT },
170    { 0, 0, 0 },
171};
172
173static unsigned32
174rtems_libio_fcntl_flags(unsigned32 fcntl_flags)
175{
176    unsigned32 flags = 0;
177    unsigned32 access_modes;
178
179    /*
180     * Access mode is a small integer
181     */
182   
183    access_modes = fcntl_flags & O_ACCMODE;
184    fcntl_flags &= ~O_ACCMODE;
185    flags = rtems_assoc_local_by_remote(access_modes_assoc, access_modes);
186
187    /*
188     * Everything else is single bits
189     */
190
191    flags |= rtems_assoc_local_by_remote_bitfield(status_flags_assoc, fcntl_flags);
192    return flags;
193}
194
195
196static rtems_libio_t *
197rtems_libio_allocate(void)
198{
199    rtems_libio_t *iop;
200    rtems_status_code rc;
201   
202    rtems_semaphore_obtain(rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
203
204    for (iop = rtems_libio_iops; iop <= rtems_libio_last_iop; iop++)
205        if ((iop->flags & LIBIO_FLAGS_OPEN) == 0)
206        {
207            /*
208             * Got one; create a semaphore for it
209             */
210
211            rc = rtems_semaphore_create(
212              RTEMS_LIBIO_IOP_SEM(iop - rtems_libio_iops),
213              1,
214              RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
215              RTEMS_NO_PRIORITY,
216              &iop->sem
217            );
218            if (rc != RTEMS_SUCCESSFUL)
219                goto failed;
220           
221            iop->flags = LIBIO_FLAGS_OPEN;
222            goto done;
223        }
224   
225failed:
226    iop = 0;
227   
228done:
229    rtems_semaphore_release(rtems_libio_semaphore);
230    return iop;
231}
232
233static void
234rtems_libio_free(rtems_libio_t *iop)
235{
236    rtems_semaphore_obtain(rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
237
238    if (iop->sem)
239        rtems_semaphore_delete(iop->sem);
240    (void) memset(iop, 0, sizeof(*iop));
241
242    rtems_semaphore_release(rtems_libio_semaphore);
243}
244
245int
246__open(
247    const char   *pathname,
248    unsigned32    flag,
249    unsigned32    mode)
250{
251    rtems_status_code rc;
252    rtems_libio_t *iop = 0;
253    rtems_driver_name_t *np;
254    rtems_libio_open_close_args_t args;
255
256    if ((rc = rtems_io_lookup_name(pathname, &np)) != RTEMS_SUCCESSFUL) {
257      if ( rc == RTEMS_UNSATISFIED ) {
258        puts( "open -- ENOSYS case" );
259        assert( 0 );
260      }
261        goto done;
262    }
263
264    iop = rtems_libio_allocate();
265    if (iop == 0)
266    {
267        rc = RTEMS_TOO_MANY;
268        goto done;
269    }
270   
271    iop->driver = np;
272    iop->pathname = (char *) pathname;
273    iop->flags |= rtems_libio_fcntl_flags(flag);
274
275    args.iop = iop;
276    args.flags = iop->flags;
277    args.mode = mode;
278
279    rc = rtems_io_open(np->major, np->minor, (void *) &args);
280   
281done:
282 
283    if (rc != RTEMS_SUCCESSFUL)
284    {
285        if (iop)
286            rtems_libio_free(iop);
287        return rtems_libio_errno(rc);
288    }
289   
290    return iop - rtems_libio_iops;
291}
292   
293int
294__close(
295    int  fd
296  )   
297{
298    rtems_status_code rc;
299    rtems_driver_name_t *np;
300    rtems_libio_t *iop = rtems_libio_iop(fd);
301    rtems_libio_open_close_args_t args;
302
303    rtems_libio_check_fd(fd);
304
305    np = iop->driver;
306
307    args.iop = iop;
308    args.flags = 0;
309    args.mode = 0;
310   
311    rc = rtems_io_close(np->major, np->minor, (void *) &args);
312
313    if (rc != RTEMS_SUCCESSFUL)
314        return rtems_libio_errno(rc);
315    return 0;
316}
317   
318int
319__read(
320    int       fd,
321    void *    buffer,
322    unsigned32 count
323  )
324{
325    rtems_status_code rc;
326    rtems_driver_name_t *np;
327    rtems_libio_t *iop = rtems_libio_iop(fd);
328    rtems_libio_rw_args_t args;
329
330    rtems_libio_check_fd(fd);
331    rtems_libio_check_buffer(buffer);
332    rtems_libio_check_count(count);
333    rtems_libio_check_permissions(iop, LIBIO_FLAGS_READ);
334
335    np = iop->driver;
336
337    args.iop = iop;
338    args.offset = iop->offset;
339    args.buffer = buffer;
340    args.count = count;
341    args.flags = iop->flags;
342    args.bytes_moved = 0;
343
344    rc = rtems_io_read(np->major, np->minor, (void *) &args);
345
346    iop->offset += args.bytes_moved;
347
348    if (rc != RTEMS_SUCCESSFUL)
349        return rtems_libio_errno(rc);
350
351    return args.bytes_moved;
352}
353
354int
355__write(
356    int         fd,
357    const void *buffer,
358    unsigned32  count
359  )
360{
361    rtems_status_code rc;
362    rtems_driver_name_t *np;
363    rtems_libio_t *iop = rtems_libio_iop(fd);
364    rtems_libio_rw_args_t args;
365
366    rtems_libio_check_fd(fd);
367    rtems_libio_check_buffer(buffer);
368    rtems_libio_check_count(count);
369    rtems_libio_check_permissions(iop, LIBIO_FLAGS_WRITE);
370
371    np = iop->driver;
372
373    args.iop = iop;
374    args.offset = iop->offset;
375    args.buffer = (void *) buffer;
376    args.count = count;
377    args.flags = iop->flags;
378    args.bytes_moved = 0;
379
380    rc = rtems_io_write(np->major, np->minor, (void *) &args);
381
382    iop->offset += args.bytes_moved;
383
384    if (rc != RTEMS_SUCCESSFUL)
385        return rtems_libio_errno(rc);
386
387    return args.bytes_moved;
388}
389
390int
391__ioctl(
392    int         fd,
393    unsigned32  command,
394    void *      buffer)
395{
396    rtems_status_code rc;
397    rtems_driver_name_t *np;
398    rtems_libio_t *iop = rtems_libio_iop(fd);
399    rtems_libio_ioctl_args_t args;
400
401    rtems_libio_check_fd(fd);
402
403    np = iop->driver;
404
405    args.iop = iop;
406    args.command = command;
407    args.buffer = buffer;
408
409    rc = rtems_io_control(np->major, np->minor, (void *) &args);
410
411    if (rc != RTEMS_SUCCESSFUL)
412        return rtems_libio_errno(rc);
413
414    return args.ioctl_return;
415}
416   
417/*
418 * internal only??
419 */
420
421
422int
423__lseek(
424    int                  fd,
425    rtems_libio_offset_t offset,
426    int                  whence
427  )   
428{
429    rtems_libio_t *iop = rtems_libio_iop(fd);
430
431    rtems_libio_check_fd(fd);
432
433    switch (whence)
434    {
435        case SEEK_SET:
436            iop->offset = offset;
437            break;
438
439        case SEEK_CUR:
440            iop->offset += offset;
441            break;
442
443        case SEEK_END:
444            iop->offset = iop->size - offset;
445            break;
446
447        default:
448            errno = EINVAL;
449            return -1;
450    }
451    return 0;
452}
Note: See TracBrowser for help on using the repository browser.