source: rtems/c/src/lib/libc/libio.c @ 8cf88427

4.104.114.84.95
Last change on this file since 8cf88427 was c64e4ed4, checked in by Joel Sherrill <joel.sherrill@…>, on 01/15/96 at 21:50:28

updates from Tony Bennett for PA and UNIX ports

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