source: rtems/cpukit/libcsupport/src/libio.c @ e6d4b1d

4.104.114.84.95
Last change on this file since e6d4b1d was e6d4b1d, checked in by Joel Sherrill <joel.sherrill@…>, on 05/28/96 at 13:13:34

added initial posix configuration support

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