summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libc/libio.c
diff options
context:
space:
mode:
Diffstat (limited to 'c/src/lib/libc/libio.c')
-rw-r--r--c/src/lib/libc/libio.c663
1 files changed, 217 insertions, 446 deletions
diff --git a/c/src/lib/libc/libio.c b/c/src/lib/libc/libio.c
index 12682c1190..e63a4626d4 100644
--- a/c/src/lib/libc/libio.c
+++ b/c/src/lib/libc/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;
}