source: rtems/c/src/exec/libcsupport/src/libio.c @ 4955afc

4.104.114.84.95
Last change on this file since 4955afc was 4955afc, checked in by Joel Sherrill <joel.sherrill@…>, on 04/18/98 at 17:25:35

rtems_libio_number_iops is now defined in confdefs.h so the maximum
file descriptors is user configurable.

  • Property mode set to 100644
File size: 12.1 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
40extern unsigned32     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 ((unsigned32) (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/*
83 * External I/O handlers
84 *
85 * Space for all possible handlers is preallocated
86 * to speed up dispatch to external handlers.
87 */
88
89static rtems_libio_handler_t handlers[15];
90
91void
92rtems_register_libio_handler(
93    int                         handler_flag,
94    const rtems_libio_handler_t *handler
95)
96{
97  int handler_index = rtems_file_descriptor_type_index(handler_flag);
98
99  if ((handler_index < 0) || (handler_index >= 15))
100    rtems_fatal_error_occurred( RTEMS_INVALID_NUMBER );
101  handlers[handler_index] = *handler;
102}
103
104/*
105 * Called by bsp startup code to init the libio area.
106 */
107
108void
109rtems_libio_init(void)
110{
111    rtems_status_code rc;
112
113    if (rtems_libio_number_iops > 0)
114    {
115        rtems_libio_iops = (rtems_libio_t *) calloc(rtems_libio_number_iops,
116                                                    sizeof(rtems_libio_t));
117        if (rtems_libio_iops == NULL)
118            rtems_fatal_error_occurred(RTEMS_NO_MEMORY);
119
120        rtems_libio_last_iop = rtems_libio_iops + (rtems_libio_number_iops - 1);
121    }
122
123    rc = rtems_semaphore_create(
124      RTEMS_LIBIO_SEM,
125      1,
126      RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
127      RTEMS_NO_PRIORITY,
128      &rtems_libio_semaphore
129    );
130    if (rc != RTEMS_SUCCESSFUL)
131        rtems_fatal_error_occurred(rc);
132}
133
134/*
135 * Convert RTEMS status to a UNIX errno
136 */
137
138rtems_assoc_t errno_assoc[] = {
139    { "OK",                 RTEMS_SUCCESSFUL,                0 },
140    { "BUSY",               RTEMS_RESOURCE_IN_USE,           EBUSY },
141    { "INVALID NAME",       RTEMS_INVALID_NAME,              EINVAL },
142    { "NOT IMPLEMENTED",    RTEMS_NOT_IMPLEMENTED,           ENOSYS },
143    { "TIMEOUT",            RTEMS_TIMEOUT,                   ETIMEDOUT },
144    { "NO MEMORY",          RTEMS_NO_MEMORY,                 ENOMEM },
145    { "NO DEVICE",          RTEMS_UNSATISFIED,               ENODEV },
146    { "INVALID NUMBER",     RTEMS_INVALID_NUMBER,            EBADF},
147    { "NOT RESOURCE OWNER", RTEMS_NOT_OWNER_OF_RESOURCE,     EPERM},
148    { "IO ERROR",           RTEMS_IO_ERROR,                  EIO},
149    { 0, 0, 0 },
150};
151
152static unsigned32
153rtems_libio_errno(rtems_status_code code)
154{
155    int rc;
156   
157    if ((rc = rtems_assoc_remote_by_local(errno_assoc, (unsigned32) code)))
158    {
159        errno = rc;
160        return -1;
161    }
162    return -1;
163}
164
165/*
166 * Convert UNIX fnctl(2) flags to ones that RTEMS drivers understand
167 */
168
169rtems_assoc_t access_modes_assoc[] = {
170    { "READ",       LIBIO_FLAGS_READ,  O_RDONLY },
171    { "WRITE",      LIBIO_FLAGS_WRITE, O_WRONLY },
172    { "READ/WRITE", LIBIO_FLAGS_READ_WRITE, O_RDWR },
173    { 0, 0, 0 },
174};
175
176rtems_assoc_t status_flags_assoc[] = {
177    { "NO DELAY",  LIBIO_FLAGS_NO_DELAY,  O_NDELAY },
178    { "APPEND",    LIBIO_FLAGS_APPEND,    O_APPEND },
179    { "CREATE",    LIBIO_FLAGS_CREATE,    O_CREAT },
180    { 0, 0, 0 },
181};
182
183static unsigned32
184rtems_libio_fcntl_flags(unsigned32 fcntl_flags)
185{
186    unsigned32 flags = 0;
187    unsigned32 access_modes;
188
189    /*
190     * Access mode is a small integer
191     */
192   
193    access_modes = fcntl_flags & O_ACCMODE;
194    fcntl_flags &= ~O_ACCMODE;
195    flags = rtems_assoc_local_by_remote(access_modes_assoc, access_modes);
196
197    /*
198     * Everything else is single bits
199     */
200
201    flags |= rtems_assoc_local_by_remote_bitfield(status_flags_assoc, fcntl_flags);
202    return flags;
203}
204
205
206static rtems_libio_t *
207rtems_libio_allocate(void)
208{
209    rtems_libio_t *iop;
210    rtems_status_code rc;
211   
212    rtems_semaphore_obtain(rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
213
214    for (iop = rtems_libio_iops; iop <= rtems_libio_last_iop; iop++)
215        if ((iop->flags & LIBIO_FLAGS_OPEN) == 0)
216        {
217            /*
218             * Got one; create a semaphore for it
219             */
220
221            rc = rtems_semaphore_create(
222              RTEMS_LIBIO_IOP_SEM(iop - rtems_libio_iops),
223              1,
224              RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
225              RTEMS_NO_PRIORITY,
226              &iop->sem
227            );
228            if (rc != RTEMS_SUCCESSFUL)
229                goto failed;
230           
231            iop->flags = LIBIO_FLAGS_OPEN;
232            goto done;
233        }
234   
235failed:
236    iop = 0;
237   
238done:
239    rtems_semaphore_release(rtems_libio_semaphore);
240    return iop;
241}
242
243static void
244rtems_libio_free(rtems_libio_t *iop)
245{
246    rtems_semaphore_obtain(rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
247
248    if (iop->sem)
249        rtems_semaphore_delete(iop->sem);
250    (void) memset(iop, 0, sizeof(*iop));
251
252    rtems_semaphore_release(rtems_libio_semaphore);
253}
254
255int
256__rtems_open(
257    const char   *pathname,
258    unsigned32    flag,
259    unsigned32    mode)
260{
261    rtems_status_code rc;
262    rtems_libio_t *iop = 0;
263    rtems_driver_name_t *np;
264    rtems_libio_open_close_args_t args;
265
266    /*
267     * Additional external I/O handlers would be supported by
268     * adding code to pick apart the pathname appropriately.
269     * The networking code does not require changes here since
270     * network file descriptors are obtained using socket(), not
271     * open().
272     */
273
274    if ((rc = rtems_io_lookup_name(pathname, &np)) != RTEMS_SUCCESSFUL)
275        goto done;
276
277    iop = rtems_libio_allocate();
278    if (iop == 0)
279    {
280        rc = RTEMS_TOO_MANY;
281        goto done;
282    }
283   
284    iop->driver = np;
285    iop->pathname = (char *) pathname;
286    iop->flags |= rtems_libio_fcntl_flags(flag);
287
288    args.iop = iop;
289    args.flags = iop->flags;
290    args.mode = mode;
291
292    rc = rtems_io_open(np->major, np->minor, (void *) &args);
293   
294done:
295 
296    if (rc != RTEMS_SUCCESSFUL)
297    {
298        if (iop)
299            rtems_libio_free(iop);
300        return rtems_libio_errno(rc);
301    }
302   
303    return iop - rtems_libio_iops;
304}
305   
306int
307__rtems_close(
308    int  fd
309  )   
310{
311    rtems_status_code rc;
312    rtems_driver_name_t *np;
313    rtems_libio_t *iop;
314    rtems_libio_open_close_args_t args;
315    int status;
316
317    if (rtems_file_descriptor_type(fd)) {
318        int (*fp)(int fd);
319
320        fp = handlers[rtems_file_descriptor_type_index(fd)].close;
321        if (fp == NULL) {
322            errno = EBADF;
323            return -1;
324        }
325        status = (*fp)(fd);
326        return status;
327    }
328    iop = rtems_libio_iop(fd);
329    rtems_libio_check_fd(fd);
330
331    np = iop->driver;
332
333    args.iop = iop;
334    args.flags = 0;
335    args.mode = 0;
336   
337    rc = rtems_io_close(np->major, np->minor, (void *) &args);
338
339    rtems_libio_free(iop);
340
341    if (rc != RTEMS_SUCCESSFUL)
342        return rtems_libio_errno(rc);
343    return 0;
344}
345   
346int
347__rtems_read(
348    int       fd,
349    void *    buffer,
350    unsigned32 count
351  )
352{
353    rtems_status_code rc;
354    rtems_driver_name_t *np;
355    rtems_libio_t *iop;
356    rtems_libio_rw_args_t args;
357
358    if (rtems_file_descriptor_type(fd)) {
359        int (*fp)(int fd, void *buffer, unsigned32 count);
360
361        fp = handlers[rtems_file_descriptor_type_index(fd)].read;
362        if (fp == NULL) {
363            errno = EBADF;
364            return -1;
365        }
366        return (*fp)(fd, buffer, count);
367    }
368    iop = rtems_libio_iop(fd);
369    rtems_libio_check_fd(fd);
370    rtems_libio_check_buffer(buffer);
371    rtems_libio_check_count(count);
372    rtems_libio_check_permissions(iop, LIBIO_FLAGS_READ);
373
374    np = iop->driver;
375
376    args.iop = iop;
377    args.offset = iop->offset;
378    args.buffer = buffer;
379    args.count = count;
380    args.flags = iop->flags;
381    args.bytes_moved = 0;
382
383    rc = rtems_io_read(np->major, np->minor, (void *) &args);
384
385    iop->offset += args.bytes_moved;
386
387    if (rc != RTEMS_SUCCESSFUL)
388        return rtems_libio_errno(rc);
389
390    return args.bytes_moved;
391}
392
393int
394__rtems_write(
395    int         fd,
396    const void *buffer,
397    unsigned32  count
398  )
399{
400    rtems_status_code rc;
401    rtems_driver_name_t *np;
402    rtems_libio_t *iop;
403    rtems_libio_rw_args_t args;
404
405    if (rtems_file_descriptor_type(fd)) {
406        int (*fp)(int fd, const void *buffer, unsigned32 count);
407
408        fp = handlers[rtems_file_descriptor_type_index(fd)].write;
409        if (fp == NULL) {
410            errno = EBADF;
411            return -1;
412        }
413        return (*fp)(fd, buffer, count);
414    }
415    iop = rtems_libio_iop(fd);
416    rtems_libio_check_fd(fd);
417    rtems_libio_check_buffer(buffer);
418    rtems_libio_check_count(count);
419    rtems_libio_check_permissions(iop, LIBIO_FLAGS_WRITE);
420
421    np = iop->driver;
422
423    args.iop = iop;
424    args.offset = iop->offset;
425    args.buffer = (void *) buffer;
426    args.count = count;
427    args.flags = iop->flags;
428    args.bytes_moved = 0;
429
430    rc = rtems_io_write(np->major, np->minor, (void *) &args);
431
432    iop->offset += args.bytes_moved;
433
434    if (rc != RTEMS_SUCCESSFUL)
435        return rtems_libio_errno(rc);
436
437    return args.bytes_moved;
438}
439
440int
441__rtems_ioctl(
442    int         fd,
443    unsigned32  command,
444    void *      buffer)
445{
446    rtems_status_code rc;
447    rtems_driver_name_t *np;
448    rtems_libio_t *iop;
449    rtems_libio_ioctl_args_t args;
450
451    if (rtems_file_descriptor_type(fd)) {
452        int (*fp)(int fd, unsigned32 command, void *buffer);
453
454        fp = handlers[rtems_file_descriptor_type_index(fd)].ioctl;
455        if (fp == NULL) {
456            errno = EBADF;
457            return -1;
458        }
459        return (*fp)(fd, command, buffer);
460    }
461    iop = rtems_libio_iop(fd);
462    rtems_libio_check_fd(fd);
463
464    np = iop->driver;
465
466    args.iop = iop;
467    args.command = command;
468    args.buffer = buffer;
469
470    rc = rtems_io_control(np->major, np->minor, (void *) &args);
471
472    if (rc != RTEMS_SUCCESSFUL)
473        return rtems_libio_errno(rc);
474
475    return args.ioctl_return;
476}
477   
478/*
479 * internal only??
480 */
481
482
483int
484__rtems_lseek(
485    int                  fd,
486    rtems_libio_offset_t offset,
487    int                  whence
488  )   
489{
490    rtems_libio_t *iop;
491
492    if (rtems_file_descriptor_type(fd)) {
493        int (*fp)(int fd, rtems_libio_offset_t offset, int whence);
494
495        fp = handlers[rtems_file_descriptor_type_index(fd)].lseek;
496        if (fp == NULL) {
497            errno = EBADF;
498            return -1;
499        }
500        return (*fp)(fd, offset, whence);
501    }
502    iop = rtems_libio_iop(fd);
503    rtems_libio_check_fd(fd);
504
505    switch (whence)
506    {
507        case SEEK_SET:
508            iop->offset = offset;
509            break;
510
511        case SEEK_CUR:
512            iop->offset += offset;
513            break;
514
515        case SEEK_END:
516            iop->offset = iop->size - offset;
517            break;
518
519        default:
520            errno = EINVAL;
521            return -1;
522    }
523    return 0;
524}
Note: See TracBrowser for help on using the repository browser.