source: rtems/c/src/lib/libc/libio.c @ 0836603

4.104.114.84.95
Last change on this file since 0836603 was 09b1f1a, checked in by Joel Sherrill <joel.sherrill@…>, on 06/06/96 at 17:57:39

patch from Tony Bennett on the ifdef for O_NDELAY

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