source: rtems/c/src/lib/libc/libio.c @ 62c4e481

4.104.114.84.95
Last change on this file since 62c4e481 was 5e9b32b, checked in by Joel Sherrill <joel.sherrill@…>, on 09/26/95 at 19:27:15

posix support initially added

  • Property mode set to 100644
File size: 9.5 KB
Line 
1/*
2 *      @(#)libio.c     1.1 - 95/06/02
3 *     
4 *
5 * Provide UNIX/POSIX-like io system calls for RTEMS using the
6 *  RTEMS IO manager
7 *
8 * TODO
9 *
10 *  $Id$
11 */
12
13#include <rtems.h>
14#include <rtems/assoc.h>                /* assoc.h not included by rtems.h */
15
16#include <stdio.h>                      /* O_RDONLY, et.al. */
17#include <fcntl.h>                      /* O_RDONLY, et.al. */
18#include <sys/fcntl.h>                      /* O_RDONLY, et.al. */
19#if defined(solaris2)
20#define O_NDELAY O_NONBLOCK
21#elif  defined(RTEMS_NEWLIB)
22#define O_NDELAY _FNBIO
23#endif
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    config->maximum_semaphores += 1;            /* one for iop table */
96    config->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.