diff options
Diffstat (limited to '')
-rw-r--r-- | cpukit/libcsupport/src/libio.c | 663 |
1 files changed, 217 insertions, 446 deletions
diff --git a/cpukit/libcsupport/src/libio.c b/cpukit/libcsupport/src/libio.c index 12682c1190..e63a4626d4 100644 --- a/cpukit/libcsupport/src/libio.c +++ b/cpukit/libcsupport/src/libio.c @@ -1,524 +1,295 @@ /* - * Provide UNIX/POSIX-like io system calls for RTEMS using the - * RTEMS IO manager + * This file contains the support infrastructure used to manage the + * table of integer style file descriptors used by the low level + * POSIX system calls like open(), read, fstat(), etc. + * + * This provides the foundation for POSIX compliant IO system calls + * for RTEMS. + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. * * $Id$ */ -#include <rtems.h> -#include <rtems/assoc.h> /* assoc.h not included by rtems.h */ - -#include <stdio.h> /* O_RDONLY, et.al. */ -#include <fcntl.h> /* O_RDONLY, et.al. */ -#include <assert.h> - -#if ! defined(O_NDELAY) -# if defined(solaris2) -# define O_NDELAY O_NONBLOCK -# elif defined(RTEMS_NEWLIB) -# define O_NDELAY _FNBIO -# endif -#endif - - -#include <errno.h> -#include <string.h> /* strcmp */ -#include <unistd.h> -#include <stdlib.h> /* calloc() */ - -#include "libio.h" /* libio.h not pulled in by rtems */ +#include "libio_.h" /* libio_.h pulls in rtems */ /* - * Semaphore to protect the io table + * Global variables used to manage the File Descriptor Table. + * IOP = IO Pointer. */ -Objects_Id rtems_libio_semaphore; - -#define RTEMS_LIBIO_SEM rtems_build_name('L', 'B', 'I', 'O') -#define RTEMS_LIBIO_IOP_SEM(n) rtems_build_name('L', 'B', 'I', n) - -extern unsigned32 rtems_libio_number_iops; -rtems_libio_t *rtems_libio_iops; -rtems_libio_t *rtems_libio_last_iop; - -#define rtems_libio_iop(fd) ((((unsigned32)(fd)) < rtems_libio_number_iops) ? \ - &rtems_libio_iops[fd] : 0) - -#define rtems_libio_check_fd(fd) \ - do { \ - if ((unsigned32) (fd) >= rtems_libio_number_iops) \ - { \ - errno = EBADF; \ - return -1; \ - } \ - } while (0) - -#define rtems_libio_check_buffer(buffer) \ - do { \ - if ((buffer) == 0) \ - { \ - errno = EINVAL; \ - return -1; \ - } \ - } while (0) - -#define rtems_libio_check_count(count) \ - do { \ - if ((count) == 0) \ - { \ - return 0; \ - } \ - } while (0) - -#define rtems_libio_check_permissions(iop, flag) \ - do { \ - if (((iop)->flags & (flag)) == 0) \ - { \ - errno = EINVAL; \ - return -1; \ - } \ - } while (0) +rtems_id rtems_libio_semaphore; +rtems_libio_t *rtems_libio_iops; +rtems_libio_t *rtems_libio_last_iop; +rtems_libio_handler_t rtems_libio_handlers[15]; /* - * External I/O handlers - * - * Space for all possible handlers is preallocated - * to speed up dispatch to external handlers. + * rtems_register_libio_handler + * + * This function registers an external IO handler set. This lets + * other subsystems have their own versions of many of the system + * calls. For example, the networking code registers handlers which + * map the system calls for read() and write() to socket calls. + * */ -static rtems_libio_handler_t handlers[15]; - -void -rtems_register_libio_handler( - int handler_flag, - const rtems_libio_handler_t *handler +void rtems_register_libio_handler( + int handler_flag, + const rtems_libio_handler_t *handler ) { - int handler_index = rtems_file_descriptor_type_index(handler_flag); + int handler_index = rtems_file_descriptor_type_index( handler_flag ); + if ((handler_index < 0) || (handler_index >= 15)) rtems_fatal_error_occurred( RTEMS_INVALID_NUMBER ); - handlers[handler_index] = *handler; -} - -/* - * Called by bsp startup code to init the libio area. - */ -void -rtems_libio_init(void) -{ - rtems_status_code rc; - - if (rtems_libio_number_iops > 0) - { - rtems_libio_iops = (rtems_libio_t *) calloc(rtems_libio_number_iops, - sizeof(rtems_libio_t)); - if (rtems_libio_iops == NULL) - rtems_fatal_error_occurred(RTEMS_NO_MEMORY); - - rtems_libio_last_iop = rtems_libio_iops + (rtems_libio_number_iops - 1); - } - - rc = rtems_semaphore_create( - RTEMS_LIBIO_SEM, - 1, - RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY, - RTEMS_NO_PRIORITY, - &rtems_libio_semaphore - ); - if (rc != RTEMS_SUCCESSFUL) - rtems_fatal_error_occurred(rc); + rtems_libio_handlers[handler_index] = *handler; } /* - * Convert RTEMS status to a UNIX errno + * rtems_libio_init + * + * Called by BSP startup code to initialize the libio subsystem. */ -rtems_assoc_t errno_assoc[] = { - { "OK", RTEMS_SUCCESSFUL, 0 }, - { "BUSY", RTEMS_RESOURCE_IN_USE, EBUSY }, - { "INVALID NAME", RTEMS_INVALID_NAME, EINVAL }, - { "NOT IMPLEMENTED", RTEMS_NOT_IMPLEMENTED, ENOSYS }, - { "TIMEOUT", RTEMS_TIMEOUT, ETIMEDOUT }, - { "NO MEMORY", RTEMS_NO_MEMORY, ENOMEM }, - { "NO DEVICE", RTEMS_UNSATISFIED, ENODEV }, - { "INVALID NUMBER", RTEMS_INVALID_NUMBER, EBADF}, - { "NOT RESOURCE OWNER", RTEMS_NOT_OWNER_OF_RESOURCE, EPERM}, - { "IO ERROR", RTEMS_IO_ERROR, EIO}, - { 0, 0, 0 }, -}; - -static unsigned32 -rtems_libio_errno(rtems_status_code code) +void rtems_libio_init( void ) { - int rc; - - if ((rc = rtems_assoc_remote_by_local(errno_assoc, (unsigned32) code))) - { - errno = rc; - return -1; - } - return -1; + rtems_status_code rc; + + /* + * Allocate memory for the IOP Table + */ + + if ( rtems_libio_number_iops > 0 ) { + rtems_libio_iops = + (rtems_libio_t *) calloc(rtems_libio_number_iops, sizeof(rtems_libio_t)); + + if (rtems_libio_iops == NULL) + rtems_fatal_error_occurred( RTEMS_NO_MEMORY ); + + rtems_libio_last_iop = rtems_libio_iops + (rtems_libio_number_iops - 1); + } + + /* + * Create the binary semaphore used to provide mutual exclusion + * on the IOP Table. + */ + + rc = rtems_semaphore_create( + RTEMS_LIBIO_SEM, + 1, + RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY, + RTEMS_NO_PRIORITY, + &rtems_libio_semaphore + ); + if ( rc != RTEMS_SUCCESSFUL ) + rtems_fatal_error_occurred( rc ); + + /* + * Initialize the base file system infrastructure. + */ + + rtems_filesystem_initialize(); } /* - * Convert UNIX fnctl(2) flags to ones that RTEMS drivers understand + * rtems_libio_fcntl_flags + * + * Convert UNIX fnctl(2) flags to ones that RTEMS drivers understand */ rtems_assoc_t access_modes_assoc[] = { - { "READ", LIBIO_FLAGS_READ, O_RDONLY }, - { "WRITE", LIBIO_FLAGS_WRITE, O_WRONLY }, - { "READ/WRITE", LIBIO_FLAGS_READ_WRITE, O_RDWR }, - { 0, 0, 0 }, + { "READ", LIBIO_FLAGS_READ, O_RDONLY }, + { "WRITE", LIBIO_FLAGS_WRITE, O_WRONLY }, + { "READ/WRITE", LIBIO_FLAGS_READ_WRITE, O_RDWR }, + { 0, 0, 0 }, }; rtems_assoc_t status_flags_assoc[] = { - { "NO DELAY", LIBIO_FLAGS_NO_DELAY, O_NDELAY }, - { "APPEND", LIBIO_FLAGS_APPEND, O_APPEND }, - { "CREATE", LIBIO_FLAGS_CREATE, O_CREAT }, - { 0, 0, 0 }, + { "NO DELAY", LIBIO_FLAGS_NO_DELAY, O_NDELAY }, + { "APPEND", LIBIO_FLAGS_APPEND, O_APPEND }, + { "CREATE", LIBIO_FLAGS_CREATE, O_CREAT }, + { 0, 0, 0 }, }; -static unsigned32 -rtems_libio_fcntl_flags(unsigned32 fcntl_flags) +unsigned32 rtems_libio_fcntl_flags( + unsigned32 fcntl_flags +) { - unsigned32 flags = 0; - unsigned32 access_modes; + unsigned32 flags = 0; + unsigned32 access_modes; - /* - * Access mode is a small integer - */ - - access_modes = fcntl_flags & O_ACCMODE; - fcntl_flags &= ~O_ACCMODE; - flags = rtems_assoc_local_by_remote(access_modes_assoc, access_modes); + /* + * Access mode is a small integer + */ + + access_modes = fcntl_flags & O_ACCMODE; + fcntl_flags &= ~O_ACCMODE; + flags = rtems_assoc_local_by_remote( access_modes_assoc, access_modes ); - /* - * Everything else is single bits - */ + /* + * Everything else is single bits + */ - flags |= rtems_assoc_local_by_remote_bitfield(status_flags_assoc, fcntl_flags); - return flags; + flags |= + rtems_assoc_local_by_remote_bitfield(status_flags_assoc, fcntl_flags); + return flags; } +/* + * rtems_libio_allocate + * + * This routine searches the IOP Table for an unused entry. If it + * finds one, it returns it. Otherwise, it returns NULL. + */ -static rtems_libio_t * -rtems_libio_allocate(void) +rtems_libio_t *rtems_libio_allocate( void ) { - rtems_libio_t *iop; - rtems_status_code rc; - - rtems_semaphore_obtain(rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT); - - for (iop = rtems_libio_iops; iop <= rtems_libio_last_iop; iop++) - if ((iop->flags & LIBIO_FLAGS_OPEN) == 0) - { - /* - * Got one; create a semaphore for it - */ - - rc = rtems_semaphore_create( - RTEMS_LIBIO_IOP_SEM(iop - rtems_libio_iops), - 1, - RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY, - RTEMS_NO_PRIORITY, - &iop->sem - ); - if (rc != RTEMS_SUCCESSFUL) - goto failed; - - iop->flags = LIBIO_FLAGS_OPEN; - goto done; - } + rtems_libio_t *iop; + rtems_status_code rc; + + rtems_semaphore_obtain( rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT ); + + for (iop = rtems_libio_iops; iop <= rtems_libio_last_iop; iop++) + if ((iop->flags & LIBIO_FLAGS_OPEN) == 0) { + /* + * Got an IOP -- create a semaphore for it. + */ + + rc = rtems_semaphore_create( + RTEMS_LIBIO_IOP_SEM(iop - rtems_libio_iops), + 1, + RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY, + RTEMS_NO_PRIORITY, + &iop->sem + ); + if ( rc != RTEMS_SUCCESSFUL ) + goto failed; + iop->flags = LIBIO_FLAGS_OPEN; + goto done; + } + failed: - iop = 0; - + iop = 0; + done: - rtems_semaphore_release(rtems_libio_semaphore); - return iop; + rtems_semaphore_release( rtems_libio_semaphore ); + return iop; } -static void -rtems_libio_free(rtems_libio_t *iop) -{ - rtems_semaphore_obtain(rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT); - - if (iop->sem) - rtems_semaphore_delete(iop->sem); - (void) memset(iop, 0, sizeof(*iop)); - - rtems_semaphore_release(rtems_libio_semaphore); -} +/* + * rtems_libio_free + * + * This routine frees the resources associated with an IOP (file descriptor) + * and clears the slot in the IOP Table. + */ -int -__rtems_open( - const char *pathname, - unsigned32 flag, - unsigned32 mode) +void rtems_libio_free( + rtems_libio_t *iop +) { - rtems_status_code rc; - rtems_libio_t *iop = 0; - rtems_driver_name_t *np; - rtems_libio_open_close_args_t args; - - /* - * Additional external I/O handlers would be supported by - * adding code to pick apart the pathname appropriately. - * The networking code does not require changes here since - * network file descriptors are obtained using socket(), not - * open(). - */ - - if ((rc = rtems_io_lookup_name(pathname, &np)) != RTEMS_SUCCESSFUL) - goto done; - - iop = rtems_libio_allocate(); - if (iop == 0) - { - rc = RTEMS_TOO_MANY; - goto done; - } - - iop->driver = np; - iop->pathname = (char *) pathname; - iop->flags |= rtems_libio_fcntl_flags(flag); + rtems_semaphore_obtain( rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT ); - args.iop = iop; - args.flags = iop->flags; - args.mode = mode; + if (iop->sem) + rtems_semaphore_delete(iop->sem); - rc = rtems_io_open(np->major, np->minor, (void *) &args); - -done: - - if (rc != RTEMS_SUCCESSFUL) - { - if (iop) - rtems_libio_free(iop); - return rtems_libio_errno(rc); - } - - return iop - rtems_libio_iops; -} - -int -__rtems_close( - int fd - ) -{ - rtems_status_code rc; - rtems_driver_name_t *np; - rtems_libio_t *iop; - rtems_libio_open_close_args_t args; - int status; - - if (rtems_file_descriptor_type(fd)) { - int (*fp)(int fd); - - fp = handlers[rtems_file_descriptor_type_index(fd)].close; - if (fp == NULL) { - errno = EBADF; - return -1; - } - status = (*fp)(fd); - return status; - } - iop = rtems_libio_iop(fd); - rtems_libio_check_fd(fd); + (void) memset(iop, 0, sizeof(*iop)); - np = iop->driver; - - args.iop = iop; - args.flags = 0; - args.mode = 0; - - rc = rtems_io_close(np->major, np->minor, (void *) &args); + rtems_semaphore_release( rtems_libio_semaphore ); +} - rtems_libio_free(iop); +/* + * rtems_libio_is_open_files_in_fs + * + * This routine scans the entire file descriptor table to determine if the + * are any active file descriptors that refer to the atleast one node in the + * file system that we are trying to dismount. + * + * If there is at least one node in the file system referenced by the mount + * table entry a 1 is returned, otherwise a 0 is returned. + */ - if (rc != RTEMS_SUCCESSFUL) - return rtems_libio_errno(rc); - return 0; -} - -int -__rtems_read( - int fd, - void * buffer, - unsigned32 count - ) +int rtems_libio_is_open_files_in_fs( + rtems_filesystem_mount_table_entry_t * fs_mt_entry +) { - rtems_status_code rc; - rtems_driver_name_t *np; - rtems_libio_t *iop; - rtems_libio_rw_args_t args; - - if (rtems_file_descriptor_type(fd)) { - int (*fp)(int fd, void *buffer, unsigned32 count); - - fp = handlers[rtems_file_descriptor_type_index(fd)].read; - if (fp == NULL) { - errno = EBADF; - return -1; - } - return (*fp)(fd, buffer, count); - } - iop = rtems_libio_iop(fd); - rtems_libio_check_fd(fd); - rtems_libio_check_buffer(buffer); - rtems_libio_check_count(count); - rtems_libio_check_permissions(iop, LIBIO_FLAGS_READ); + rtems_libio_t *iop; + int result = 0; - np = iop->driver; + rtems_semaphore_obtain( rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT ); - args.iop = iop; - args.offset = iop->offset; - args.buffer = buffer; - args.count = count; - args.flags = iop->flags; - args.bytes_moved = 0; + /* + * Look for any active file descriptor entry. + */ - rc = rtems_io_read(np->major, np->minor, (void *) &args); + for ( iop=rtems_libio_iops ; iop <= rtems_libio_last_iop ; iop++ ) { - iop->offset += args.bytes_moved; + if ((iop->flags & LIBIO_FLAGS_OPEN) != 0) { - if (rc != RTEMS_SUCCESSFUL) - return rtems_libio_errno(rc); + /* + * Check if this node is under the file system that we + * are trying to dismount. + */ - return args.bytes_moved; -} - -int -__rtems_write( - int fd, - const void *buffer, - unsigned32 count - ) -{ - rtems_status_code rc; - rtems_driver_name_t *np; - rtems_libio_t *iop; - rtems_libio_rw_args_t args; - - if (rtems_file_descriptor_type(fd)) { - int (*fp)(int fd, const void *buffer, unsigned32 count); - - fp = handlers[rtems_file_descriptor_type_index(fd)].write; - if (fp == NULL) { - errno = EBADF; - return -1; - } - return (*fp)(fd, buffer, count); + if ( iop->pathinfo.mt_entry == fs_mt_entry ) { + result = 1; + break; + } } - iop = rtems_libio_iop(fd); - rtems_libio_check_fd(fd); - rtems_libio_check_buffer(buffer); - rtems_libio_check_count(count); - rtems_libio_check_permissions(iop, LIBIO_FLAGS_WRITE); - - np = iop->driver; - - args.iop = iop; - args.offset = iop->offset; - args.buffer = (void *) buffer; - args.count = count; - args.flags = iop->flags; - args.bytes_moved = 0; - - rc = rtems_io_write(np->major, np->minor, (void *) &args); + } - iop->offset += args.bytes_moved; + rtems_semaphore_release( rtems_libio_semaphore ); - if (rc != RTEMS_SUCCESSFUL) - return rtems_libio_errno(rc); - - return args.bytes_moved; + return result; } -int -__rtems_ioctl( - int fd, - unsigned32 command, - void * buffer) -{ - rtems_status_code rc; - rtems_driver_name_t *np; - rtems_libio_t *iop; - rtems_libio_ioctl_args_t args; - - if (rtems_file_descriptor_type(fd)) { - int (*fp)(int fd, unsigned32 command, void *buffer); - - fp = handlers[rtems_file_descriptor_type_index(fd)].ioctl; - if (fp == NULL) { - errno = EBADF; - return -1; - } - return (*fp)(fd, command, buffer); - } - iop = rtems_libio_iop(fd); - rtems_libio_check_fd(fd); +/* + * rtems_libio_is_file_open + * + * This routine scans the entire file descriptor table to determine if the + * given file refers to an active file descriptor. + * + * If the given file is open a 1 is returned, otherwise a 0 is returned. + */ - np = iop->driver; +int rtems_libio_is_file_open( + void *node_access +) +{ + rtems_libio_t *iop; + int result=0; - args.iop = iop; - args.command = command; - args.buffer = buffer; + rtems_semaphore_obtain( rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT ); - rc = rtems_io_control(np->major, np->minor, (void *) &args); + /* + * Look for any active file descriptor entry. + */ - if (rc != RTEMS_SUCCESSFUL) - return rtems_libio_errno(rc); + for ( iop=rtems_libio_iops ; iop <= rtems_libio_last_iop ; iop++ ) { - return args.ioctl_return; -} - -/* - * internal only?? - */ + if ((iop->flags & LIBIO_FLAGS_OPEN) != 0) { + /* + * Check if this node is under the file system that we + * are trying to dismount. + */ -int -__rtems_lseek( - int fd, - rtems_libio_offset_t offset, - int whence - ) -{ - rtems_libio_t *iop; + if ( iop->pathinfo.node_access == node_access ) { + result = 1; + break; + } + } + } - if (rtems_file_descriptor_type(fd)) { - int (*fp)(int fd, rtems_libio_offset_t offset, int whence); + rtems_semaphore_release( rtems_libio_semaphore ); - fp = handlers[rtems_file_descriptor_type_index(fd)].lseek; - if (fp == NULL) { - errno = EBADF; - return -1; - } - return (*fp)(fd, offset, whence); - } - iop = rtems_libio_iop(fd); - rtems_libio_check_fd(fd); - - switch (whence) - { - case SEEK_SET: - iop->offset = offset; - break; - - case SEEK_CUR: - iop->offset += offset; - break; - - case SEEK_END: - iop->offset = iop->size - offset; - break; - - default: - errno = EINVAL; - return -1; - } - return 0; + return result; } |